89 Commits

Author SHA1 Message Date
chompstation-ci[bot]
ad7d82f3ae Automatic changelog compile [ci skip] 2025-12-05 01:23:02 +00:00
chompstation-ci[bot]
c4337dc60a Automatic changelog for PR #12068 [ci skip] 2025-12-05 01:19:46 +00:00
chompstation-ci[bot]
90bebd219a Automatic changelog for PR #12067 [ci skip] 2025-12-05 01:19:30 +00:00
CHOMPStation2StaffMirrorBot
067ab7459b [MIRROR] Hair fix things (#12068)
Co-authored-by: FluffMedic <109300046+FluffMedic@users.noreply.github.com>
2025-12-05 02:19:06 +01:00
CHOMPStation2StaffMirrorBot
a42bdce47b [MIRROR] Iframe fix (#12067)
Co-authored-by: Selis <12716288+ItsSelis@users.noreply.github.com>
2025-12-05 02:18:52 +01:00
chompstation-ci[bot]
28a8d23bf6 Automatic changelog for PR #12040 [ci skip] 2025-12-05 00:26:47 +00:00
CHOMPStation2StaffMirrorBot
ba5019bd9d [MIRROR] Port of the iframe storage for settings (#12040)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
2025-12-05 01:26:10 +01:00
chompstation-ci[bot]
1b99ac2969 Automatic changelog for PR #12039 [ci skip] 2025-12-04 20:51:53 +00:00
CHOMPStation2StaffMirrorBot
bea3ac2c9f [MIRROR] Subsystem overruns (#12039)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
2025-12-04 21:51:11 +01:00
chompstation-ci[bot]
2de333c264 Automatic changelog for PR #12066 [ci skip] 2025-12-04 20:36:08 +00:00
CHOMPStation2StaffMirrorBot
c82f5a7d6d [MIRROR] No shadekin knockdown on shuttle move (#12066)
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com>
2025-12-04 21:33:47 +01:00
chompstation-ci[bot]
a7916bac08 Automatic changelog compile [ci skip] 2025-12-04 01:22:35 +00:00
chompstation-ci[bot]
0cfffbf94c Automatic changelog for PR #12065 [ci skip] 2025-12-03 18:58:01 +00:00
FluffMedic
cf85818600 Tyr Hotfix Thingy (#12065) 2025-12-03 13:57:19 -05:00
chompstation-ci[bot]
6f65a96a96 Automatic changelog compile [ci skip] 2025-12-03 01:22:33 +00:00
chompstation-ci[bot]
8a478f0827 Automatic changelog for PR #12064 [ci skip] 2025-12-02 10:16:10 +00:00
CHOMPStation2StaffMirrorBot
95c03abd07 [MIRROR] Upports Filling Cabinet UI (#12064)
Co-authored-by: Guti <32563288+TheCaramelion@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-12-02 05:15:33 -05:00
chompstation-ci[bot]
8b1b3d0324 Automatic changelog for PR #12063 [ci skip] 2025-12-02 08:53:06 +00:00
CHOMPStation2StaffMirrorBot
22a09e47a1 [MIRROR] Fusion Coil Updates (#12063)
Co-authored-by: Killian <49700375+KillianKirilenko@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-12-02 03:52:28 -05:00
chompstation-ci[bot]
258a4c8537 Automatic changelog compile [ci skip] 2025-12-02 01:22:27 +00:00
chompstation-ci[bot]
bb9e724bd2 Automatic changelog for PR #12061 [ci skip] 2025-12-01 10:56:16 +00:00
chompstation-ci[bot]
26d30d3ad7 Automatic changelog for PR #12060 [ci skip] 2025-12-01 10:55:54 +00:00
Victor Zisthus
3c2c33eafe POI tweaks (#12061) 2025-12-01 11:55:39 +01:00
chompstation-ci[bot]
ec176ca8f8 Automatic changelog for PR #12045 [ci skip] 2025-12-01 10:55:34 +00:00
chompstation-ci[bot]
ca6fd0a199 Automatic changelog for PR #12046 [ci skip] 2025-12-01 10:55:25 +00:00
Guti
e8ba2fc63d Fixes not being able to scoop up snow (#12060) 2025-12-01 11:55:07 +01:00
CHOMPStation2StaffMirrorBot
683448fd50 [MIRROR] Hotfix for species whitelist command (#12046)
Co-authored-by: Selis <12716288+ItsSelis@users.noreply.github.com>
2025-12-01 11:54:48 +01:00
FluffMedic
e8ba2765ac Tyr Update (#12045) 2025-12-01 11:54:31 +01:00
chompstation-ci[bot]
101dd347e0 Automatic changelog compile [ci skip] 2025-12-01 01:45:00 +00:00
chompstation-ci[bot]
6b4ea59565 Automatic changelog for PR #12062 [ci skip] 2025-11-30 05:05:57 +00:00
CHOMPStation2StaffMirrorBot
ad5a944c8a [MIRROR] Mech construction fix and unittest (#12062)
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com>
Co-authored-by: C.L. <killer65311@gmail.com>
2025-11-30 00:05:21 -05:00
chompstation-ci[bot]
7e9ad48982 Automatic changelog compile [ci skip] 2025-11-29 01:19:04 +00:00
chompstation-ci[bot]
5d08cae5ab Automatic changelog for PR #12059 [ci skip] 2025-11-28 09:32:43 +00:00
CHOMPStation2StaffMirrorBot
648fcd8162 [MIRROR] Catslug Tail Cosmetic (#12059)
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com>
2025-11-28 04:32:05 -05:00
chompstation-ci[bot]
49aa0c138e Automatic changelog for PR #12058 [ci skip] 2025-11-28 05:24:18 +00:00
CHOMPStation2StaffMirrorBot
0b87f2b24c [MIRROR] Hemostat bleeeding clamp (#12058)
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-28 00:23:39 -05:00
chompstation-ci[bot]
bdc17c81fe Automatic changelog for PR #12054 [ci skip] 2025-11-28 05:08:06 +00:00
CHOMPStation2StaffMirrorBot
f72988f992 [MIRROR] More surgery tweaks and fixes (#12054)
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-28 00:07:28 -05:00
chompstation-ci[bot]
77ec7cd6e4 Automatic changelog for PR #12053 [ci skip] 2025-11-28 05:05:20 +00:00
chompstation-ci[bot]
1a19f01c47 Automatic changelog for PR #12056 [ci skip] 2025-11-28 05:05:09 +00:00
CHOMPStation2StaffMirrorBot
a649749ea0 [MIRROR] Ports "Fixes SS_KEEP_TIMING causing RUNLEVEL_LOBBY subsystems to fire with 75% their set wait" from /TG/ (#12053)
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-28 00:04:42 -05:00
chompstation-ci[bot]
cb9fe98463 Automatic changelog for PR #12057 [ci skip] 2025-11-28 05:04:34 +00:00
CHOMPStation2StaffMirrorBot
07d47cbe4d [MIRROR] Fixes appreciating absorbed species (#12056)
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-28 00:04:30 -05:00
CHOMPStation2StaffMirrorBot
0b084ecf97 [MIRROR] Fixes a bug with reagent splashing (#12057)
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-28 00:03:56 -05:00
chompstation-ci[bot]
38b2114ffa Automatic changelog for PR #12055 [ci skip] 2025-11-28 04:59:21 +00:00
CHOMPStation2StaffMirrorBot
ffd8660d76 [MIRROR] a buncha sprites (#12055)
Co-authored-by: Olive <49600480+zeskorion@users.noreply.github.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
2025-11-27 23:58:45 -05:00
chompstation-ci[bot]
8655a9a8a4 Automatic changelog for PR #12052 [ci skip] 2025-11-28 04:29:53 +00:00
CHOMPStation2StaffMirrorBot
78ff349c8f [MIRROR] Makes ambulant blood not a genetrait [GBP IGNORE] (#12052)
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-27 23:29:17 -05:00
chompstation-ci[bot]
b94c6c09cf Automatic changelog for PR #12051 [ci skip] 2025-11-28 03:38:07 +00:00
CHOMPStation2StaffMirrorBot
408eeaa5d1 [MIRROR] Many new global signals from downstream (#12051)
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com>
2025-11-27 22:37:30 -05:00
chompstation-ci[bot]
9c25b75d6c Automatic changelog for PR #12050 [ci skip] 2025-11-28 03:13:50 +00:00
chompstation-ci[bot]
846a3dc43e Automatic changelog for PR #12049 [ci skip] 2025-11-28 03:13:26 +00:00
CHOMPStation2StaffMirrorBot
425baec2ba [MIRROR] Chemical engineer alt-title (#12050)
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com>
2025-11-27 22:13:09 -05:00
CHOMPStation2StaffMirrorBot
4540ee5b1b [MIRROR] Woodstravaganza (#12049)
Co-authored-by: Killian <49700375+KillianKirilenko@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-27 22:12:45 -05:00
chompstation-ci[bot]
fdac7a69ed Automatic changelog for PR #12048 [ci skip] 2025-11-28 02:17:07 +00:00
CHOMPStation2StaffMirrorBot
a7bac7c918 [MIRROR] Chemical Refinery Splitter Machine (#12048)
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com>
2025-11-27 21:16:28 -05:00
chompstation-ci[bot]
dfee7007cc Automatic changelog for PR #12044 [ci skip] 2025-11-28 01:59:25 +00:00
CHOMPStation2StaffMirrorBot
f10636966f [MIRROR] Add AFK pred/prey and contaminate worn items preferences (#12044)
Co-authored-by: TheGreatKitsune <88862343+TheGreatKitsune@users.noreply.github.com>
2025-11-27 20:58:46 -05:00
chompstation-ci[bot]
2465e088c7 Automatic changelog for PR #12043 [ci skip] 2025-11-28 01:53:03 +00:00
CHOMPStation2StaffMirrorBot
bc3d47cd46 [MIRROR] Gives Vox a Voice Box (#12043)
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-27 20:52:18 -05:00
chompstation-ci[bot]
e317669e61 Automatic changelog for PR #12041 [ci skip] 2025-11-27 10:31:39 +00:00
Zack
d17145aa15 Fixed some supply & scrubber pipes on southern cross (#12041) 2025-11-27 11:30:57 +01:00
chompstation-ci[bot]
965716ae2a Automatic changelog for PR #12035 [ci skip] 2025-11-27 10:21:35 +00:00
CHOMPStation2StaffMirrorBot
8fecb82f35 [MIRROR] test symlink support (#12035)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
2025-11-27 11:20:49 +01:00
chompstation-ci[bot]
428dc8fb33 Automatic changelog for PR #12037 [ci skip] 2025-11-27 10:20:05 +00:00
chompstation-ci[bot]
a79f68e0db Automatic changelog for PR #12038 [ci skip] 2025-11-27 10:19:24 +00:00
CHOMPStation2StaffMirrorBot
59ae2027de [MIRROR] byond 1670 support (#12037)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
2025-11-27 11:19:23 +01:00
CHOMPStation2StaffMirrorBot
03abe9a4d4 [MIRROR] add more whitelist checks (#12038)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
Co-authored-by: Selis <12716288+ItsSelis@users.noreply.github.com>
2025-11-27 11:18:46 +01:00
chompstation-ci[bot]
f28d8b9b1b Automatic changelog for PR #12029 [ci skip] 2025-11-27 02:48:03 +00:00
CHOMPStation2StaffMirrorBot
85cd76fda6 [MIRROR] Makes sizeoxadone more affordable (#12029)
Co-authored-by: SatinIsle <98125273+SatinIsle@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-26 21:47:22 -05:00
chompstation-ci[bot]
1f85a9c9b5 Automatic changelog compile [ci skip] 2025-11-27 01:19:38 +00:00
chompstation-ci[bot]
3f987d9a57 Automatic changelog for PR #12033 [ci skip] 2025-11-26 03:05:15 +00:00
CHOMPStation2StaffMirrorBot
3b24fa7553 [MIRROR] Disposal Bin Update (#12033)
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-25 22:04:29 -05:00
chompstation-ci[bot]
f5fa75c5bf Automatic changelog for PR #12032 [ci skip] 2025-11-26 01:41:44 +00:00
chompstation-ci[bot]
cbe0f0f6f2 Automatic changelog for PR #12031 [ci skip] 2025-11-26 01:41:14 +00:00
CHOMPStation2StaffMirrorBot
5b35770372 [MIRROR] Additional Material Tiles (#12032)
Co-authored-by: Guti <32563288+TheCaramelion@users.noreply.github.com>
2025-11-25 20:41:04 -05:00
CHOMPStation2StaffMirrorBot
3ead20716e [MIRROR] Cortical Borer Fixes (#12031)
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-25 20:40:33 -05:00
chompstation-ci[bot]
5290e9b81c Automatic changelog for PR #12030 [ci skip] 2025-11-26 01:40:21 +00:00
CHOMPStation2StaffMirrorBot
efacc58cce [MIRROR] Some New Hairs (#12030)
Co-authored-by: FluffMedic <109300046+FluffMedic@users.noreply.github.com>
2025-11-25 20:39:41 -05:00
chompstation-ci[bot]
6c896f5af9 Automatic changelog compile [ci skip] 2025-11-26 01:20:51 +00:00
chompstation-ci[bot]
d6d860142b Automatic changelog for PR #12028 [ci skip] 2025-11-25 01:58:26 +00:00
CHOMPStation2StaffMirrorBot
cd48bc74b9 [MIRROR] Maintenance Panels (#12028)
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
2025-11-25 02:57:44 +01:00
chompstation-ci[bot]
e2c413f92d Automatic changelog for PR #12027 [ci skip] 2025-11-25 01:46:39 +00:00
CHOMPStation2StaffMirrorBot
51b0d8978a [MIRROR] Circuitry code improvements (#12027)
Co-authored-by: Aura Dusklight <46622484+NovaDusklight@users.noreply.github.com>
2025-11-25 02:46:01 +01:00
chompstation-ci[bot]
b052607c73 Automatic changelog compile [ci skip] 2025-11-24 01:25:27 +00:00
chompstation-ci[bot]
6f8a7580ae Automatic changelog for PR #12026 [ci skip] 2025-11-23 22:00:00 +00:00
chompstation-ci[bot]
c18ea87772 Automatic changelog for PR #12024 [ci skip] 2025-11-23 21:59:49 +00:00
Zack
d15a21b6b4 yay more missing pipes on southern cross (#12026) 2025-11-23 22:59:24 +01:00
CHOMPStation2StaffMirrorBot
7ec8dfca29 [MIRROR] Add basic consent for body writing. (#12024)
Co-authored-by: Aura Dusklight <46622484+NovaDusklight@users.noreply.github.com>
2025-11-23 22:59:10 +01:00
230 changed files with 11677 additions and 8124 deletions

View File

@@ -0,0 +1,33 @@
name: "Generate Client Storage"
on:
push:
branches:
- master
paths:
- tgui/public/*
jobs:
dispatch_repo:
if: ( !contains(github.event.head_commit.message, '[ci skip]') )
name: Repository Dispatch
runs-on: ubuntu-latest
steps:
- name: Generate App Token
id: app-token-generation
uses: actions/create-github-app-token@v2
if: env.APP_PRIVATE_KEY != '' && env.APP_ID != ''
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: vorestation
env:
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
APP_ID: ${{ secrets.APP_ID }}
- name: Send Repository Dispatch
if: success()
uses: peter-evans/repository-dispatch@v4
with:
token: ${{ steps.app-token-generation.outputs.token }}
repository: vorestation/byond-client-storage
event-type: on_master_push

View File

@@ -3,7 +3,7 @@
version: 1
# The BYOND version to use (kept in sync with dependencies.sh by the "TGS Test Suite" CI job)
# Must be interpreted as a string, keep quoted
byond: "516.1669"
byond: "516.1673"
# Folders to create in "<instance_path>/Configuration/GameStaticFiles/"
static_files:
# Config directory should be static

View File

@@ -9,11 +9,11 @@
//Update this whenever you need to take advantage of more recent byond features
#define MIN_COMPILER_VERSION 516
#define MIN_COMPILER_BUILD 1664
#define MIN_COMPILER_BUILD 1667
#if (DM_VERSION < MIN_COMPILER_VERSION || DM_BUILD < MIN_COMPILER_BUILD) && !defined(SPACEMAN_DMM) && !defined(OPENDREAM)
//Don't forget to update this part
#error Your version of BYOND is too out-of-date to compile this project. Go to https://secure.byond.com/download and update.
#error You need version 516.1664 or higher
#error You need version 516.1667 or higher
#endif
// Keep savefile compatibilty at minimum supported level

View File

@@ -48,6 +48,18 @@
/// Create a typed list global that is initialized as an empty list
#define GLOBAL_LIST_EMPTY_TYPED(X, Typepath) GLOBAL_LIST_INIT_TYPED(X, Typepath, list())
/// Create an alist global with an initializer expression
#define GLOBAL_ALIST_INIT(X, InitValue) GLOBAL_RAW(/alist/##X); GLOBAL_MANAGED(X, InitValue)
/// Create an alist global that is initialized as an empty list
#define GLOBAL_ALIST_EMPTY(X) GLOBAL_ALIST_INIT(X, alist())
/// Create a typed alist global with an initializer expression
//#define GLOBAL_ALIST_INIT_TYPED(X, Typepath, InitValue) GLOBAL_RAW(/alist##Typepath/X); GLOBAL_MANAGED(X, InitValue) // Missing in spacemandmm
/// Create a typed alist global that is initialized as an empty list
//#define GLOBAL_ALIST_EMPTY_TYPED(X, Typepath) GLOBAL_ALIST_INIT_TYPED(X, Typepath, alist()) // Missing in spacemandmm
/// Create a typed global with an initializer expression
#define GLOBAL_DATUM_INIT(X, Typepath, InitValue) GLOBAL_RAW(Typepath/##X); GLOBAL_MANAGED(X, InitValue)
@@ -57,5 +69,8 @@
/// Create a null global list
#define GLOBAL_LIST(X) GLOBAL_RAW(/list/##X); GLOBAL_UNMANAGED(X)
/// Create a null global alist
#define GLOBAL_ALIST(X) GLOBAL_RAW(/alist/##X); GLOBAL_UNMANAGED(X)
/// Create a typed null global
#define GLOBAL_DATUM(X, Typepath) GLOBAL_RAW(Typepath/##X); GLOBAL_UNMANAGED(X)

View File

@@ -58,4 +58,4 @@
#endif //ifdef REFERENCE_TRACKING
// Standard flags to use for browser-options
#define DEFAULT_CLIENT_BROWSER_OPTIONS "byondstorage,find"
#define DEFAULT_CLIENT_BROWSER_OPTIONS "find"

View File

@@ -42,7 +42,7 @@
// Reads L or an empty list if L is not a list. Note: Does NOT assign, L may be an expression.
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
#define reverseList(L) reverseRange(L.Copy())
#define reverseList(L) reverse_range(L.Copy())
#define islist(L) istype(L, /list)

6
code/__defines/borer.dm Normal file
View File

@@ -0,0 +1,6 @@
#define BORER_MAX_CHEMS 80
#define BORER_POWER_COST_TORTURE 5
#define BORER_POWER_COST_SECRETE 25
#define BORER_POWER_COST_REPRODUCE 50
#define BORER_PSYCHIC_SAY_MINIMUM_CHEMS 20

View File

@@ -83,6 +83,7 @@
#define DISPOSAL_SORT_NORMAL 0
#define DISPOSAL_SORT_WILDCARD 1
#define DISPOSAL_SORT_UNTAGGED 2
#define DISPOSAL_SORT_BODIES 3
// Macro for easy use of boilerplate code for searching for a valid node connection.
#define STANDARD_ATMOS_CHOOSE_NODE(node_num, direction) \

View File

@@ -29,7 +29,7 @@
#define COMSIG_GLOB_BUTTON_PRESSED "!button_pressed"
/// Supply shuttle selling, before all items are sold, called by /datum/controller/subsystem/supply/proc/sell() : (/list/area/supply_shuttle_areas)
#define COMSIG_GLOB_SUPPLY_SHUTTLE_DEPART "!sell_supply_shuttle"
/// Supply shuttle selling, for each item sold, called by /datum/controller/subsystem/supply/proc/sell() : (atom/movable/sold_item, sold_successfully, datum/exported_crate/export_data, area/shuttle_subarea)
/// Supply shuttle selling, for each item sold, called by /datum/controller/subsystem/supply/proc/sell() : (atom/movable/sold_item, list/things_sold_successfully, datum/exported_crate/export_data, area/shuttle_subarea)
#define COMSIG_GLOB_SUPPLY_SHUTTLE_SELL_ITEM "!supply_shuttle_sell_item"
/// Mind inserted into body: (mob/new_owner, /datum/mind/assigned_mind)
#define COMSIG_GLOB_RESLEEVED_MIND "!resleeved_mind_into_body"
@@ -45,6 +45,26 @@
#define COMSIG_GLOB_BORGIFY "!borgify_mob"
/// brain removed from body, called by /obj/item/organ/internal/brain/proc/transfer_identity() : (mob/living/carbon/brain/brainmob)
#define COMSIG_GLOB_BRAIN_REMOVED "!brain_removed_from_mob"
// base /decl/emote/proc/do_emote() : (mob/user, extra_params)
#define COMSIG_GLOB_EMOTE_PERFORMED "!emote_performed"
// base /proc/say_dead_direct() : (message)
#define COMSIG_GLOB_DEAD_SAY "!dead_say"
// base /turf/wash() : ()
#define COMSIG_GLOB_WASHED_FLOOR "!washed_floor"
// base /obj/machinery/artifact_harvester/proc/harvest() : (obj/item/anobattery/inserted_battery, mob/user)
#define COMSIG_GLOB_HARVEST_ARTIFACT "!harvest_artifact"
// upon harvesting a slime's extract : (obj/item/slime_extract/newly_made_core)
#define COMSIG_GLOB_HARVEST_SLIME_CORE "!harvest_slime_core"
// base /datum/recipe/proc/make_food() : (obj/container, list/results)
#define COMSIG_GLOB_FOOD_PREPARED "!recipe_food_completed"
// base /datum/construction/proc/spawn_result() : (/obj/mecha/result_mech)
#define COMSIG_GLOB_MECH_CONSTRUCTED "!mecha_constructed"
// when trashpiles are successfully searched : (mob/living/user, list/searched_by)
#define COMSIG_GLOB_TRASHPILE_SEARCHED "!trash_pile_searched"
// base /obj/item/autopsy_scanner/do_surgery() : (mob/user, mob/target)
#define COMSIG_GLOB_AUTOPSY_PERFORMED "!performed_autopsy"
// upon forensics swap or sample kit forensics collection : (atom/target, mob/user)
#define COMSIG_GLOB_FORENSICS_COLLECTED "!performed_forensics_collection"
/// signals from globally accessible objects
@@ -813,6 +833,11 @@
///from base of /obj/effect/decal/cleanable/blood/gibs/streak(): (list/directions, list/diseases)
#define COMSIG_GIBS_STREAK "gibs_streak"
//Autopsy
//from base of /obj/item/autopsy_scanner/do_surgery() : (mob/user, mob/target)
#define COMSIG_AUTOPSY_PERFORMED "performed_autopsy"
//Mood
///called when you send a mood event from anywhere in the code.

View File

@@ -208,6 +208,7 @@
#define JOB_ALT_ELECTRICIAN "Electrician"
#define JOB_ALT_CONSTRUCTION_ENGINEER "Construction Engineer"
#define JOB_ALT_ENGINEERING_CONTRACTOR "Engineering Contractor"
#define JOB_ALT_CHEMENGINEER "Chemical Engineer"
#define JOB_ALT_COMPUTER_TECHNICIAN "Computer Technician"
#define JOB_ALT_SALVAGE_TECHNICIAN "Salvage Technician"
#define JOB_ALT_DAMAGE_CONTROL_SPECIALIST "Damage Control Specialist"

View File

@@ -1,19 +1,35 @@
//metals
#define MAT_IRON "iron"
#define MAT_MARBLE "marble"
#define MAT_STEEL "steel"
#define MAT_PLASTIC "plastic"
#define MAT_GLASS "glass"
#define MAT_RGLASS "rglass"
#define MAT_PGLASS "borosilicate glass"
#define MAT_RPGLASS "reinforced borosilicate glass"
#define MAT_STEELHULL "steel hull"
#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_PLASTEEL "plasteel"
#define MAT_PLASTEELHULL "plasteel hull"
#define MAT_DURASTEEL "durasteel"
#define MAT_DURASTEELHULL "durasteel hull"
#define MAT_TITANIUMHULL "titanium hull"
#define MAT_LEAD "lead"
#define MAT_METALHYDROGEN "mhydrogen"
#define MAT_COPPER "copper"
#define MAT_ALUMINIUM "aluminium"
#define MAT_BRONZE "bronze"
#define MAT_PLATINUM "platinum"
#define MAT_OSMIUM "osmium"
#define MAT_MORPHIUM "morphium"
#define MAT_MORPHIUMHULL "morphium hull"
#define MAT_TIN "tin"
//stone
#define MAT_MARBLE "marble"
#define MAT_GRAPHITE "graphite"
#define MAT_SANDSTONE "sandstone"
#define MAT_FLINT "flint"
#define MAT_CONCRETE "concrete"
//wood
#define MAT_WOOD "wood"
#define MAT_LOG "log"
#define MAT_SIFWOOD "alien wood"
@@ -21,38 +37,34 @@
#define MAT_HARDWOOD "hardwood"
#define MAT_HARDLOG "hardwood log"
#define MAT_WOODEN_STICK "wooden stick"
#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_BIRCHWOOD "birch"
#define MAT_PINEWOOD "pine"
#define MAT_OAKWOOD "oak"
#define MAT_ACACIAWOOD "acacia"
#define MAT_REDWOOD "redwood"
//other
#define MAT_PLASTIC "plastic"
#define MAT_GLASS "glass"
#define MAT_RGLASS "rglass"
#define MAT_PGLASS "borosilicate glass"
#define MAT_RPGLASS "reinforced borosilicate glass"
#define MAT_PHORON "phoron"
#define MAT_DIAMOND "diamond"
#define MAT_SNOW "snow"
#define MAT_SNOWBRICK "packed snow"
#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_CHITIN "chitin"
#define MAT_ALIENCHITIN "alien chitin"
#define MAT_ALIENCLAW "alien claw"
#define MAT_FUR "fur"
#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_SANDSTONE "sandstone"
#define MAT_FLINT "flint"
#define MAT_PLATINUM "platinum"
#define MAT_TRITIUM "tritium"
#define MAT_DEUTERIUM "deuterium"
#define MAT_CONCRETE "concrete"
#define MAT_PLASTEELREBAR "plasteel rebar"
#define MAT_GRASS "grass"
#define MAT_RESIN "resin"
@@ -60,7 +72,6 @@
#define MAT_BIOMASS "biomass"
#define MAT_WEEDEXTRACT "weed extract"
#define MAT_CARDBOARD "cardboard"
#define MAT_COTTON "cotton"
#define MAT_GLAMOUR "stable glamour"
#define MAT_DARKGLASS "darkglass"
#define MAT_FLESH "flesh"
@@ -88,6 +99,8 @@
#define MAT_CLOTH "cloth"
#define MAT_SYNCLOTH "syncloth"
// # define MAT_CARPET "carpet" // CHOMPRemove
#define MAT_COTTON "cotton"
// colours
#define MAT_CLOTH_TEAL "teal"
#define MAT_CLOTH_BLACK "black"

View File

@@ -15,6 +15,7 @@
#define REFINERY_TUTORIAL_NOOUTPUT (1 << 5)
#define REFINERY_TUTORIAL_ALLIN (1 << 6)
#define REFINERY_TUTORIAL_SINGLEOUTPUT (1 << 7)
#define REFINERY_TUTORIAL_SPLITTEROUTPUT (1 << 8)
#define REAGENT_VAT_VOLUME 500
#define CARGOTANKER_VOLUME 3000

View File

@@ -0,0 +1,5 @@
//Defines for when surgery steps are performed. These are used to track progress through surgeries and how 'open' we are.
#define INCISION_MADE 1
#define FLESH_RETRACTED 2
#define BONE_CUT 2.5
#define BONE_RETRACTED 3

View File

@@ -20,6 +20,8 @@
\
target.can_be_drop_prey = source.can_be_drop_prey; \
target.can_be_drop_pred = source.can_be_drop_pred; \
target.can_be_afk_prey = source.can_be_afk_prey; \
target.can_be_afk_pred = source.can_be_afk_pred; \
target.throw_vore = source.throw_vore; \
target.food_vore = source.food_vore; \
target.drop_vore = source.drop_vore; \
@@ -56,6 +58,7 @@
\
target.autotransferable = source.autotransferable; \
target.strip_pref = source.strip_pref; \
target.contaminate_pref = source.contaminate_pref; \
target.vore_sprite_multiply = source.vore_sprite_multiply; \
target.vore_sprite_color = source.vore_sprite_color; \
target.belly_rub_target = source.belly_rub_target; \

View File

@@ -1,7 +1,7 @@
//Languages/species/whitelist.
GLOBAL_LIST_EMPTY_TYPED(all_species, /datum/species)
GLOBAL_LIST_EMPTY_TYPED(whitelisted_species, /datum/species) // Species that require a whitelist check.
GLOBAL_LIST_EMPTY_TYPED(playable_species, /datum/species) // A list of ALL playable species, whitelisted, latejoin or otherwise.
GLOBAL_LIST_EMPTY(whitelisted_species) // Species that require a whitelist check.
GLOBAL_LIST_EMPTY(playable_species) // A list of ALL playable species, whitelisted, latejoin or otherwise.
GLOBAL_LIST_EMPTY_TYPED(all_languages, /datum/language)
GLOBAL_LIST_INIT(language_name_conflicts, list())

View File

@@ -849,20 +849,20 @@ Checks if a list has the same entries and values as an element of big.
L.Cut(fromIndex, fromIndex+1)
//replaces reverseList ~Carnie
/proc/reverseRange(list/L, start=1, end=0)
if(L.len)
start = start % L.len
end = end % (L.len+1)
/proc/reverse_range(list/inserted_list, start = 1, end = 0)
if(inserted_list.len)
start = start % inserted_list.len
end = end % (inserted_list.len + 1)
if(start <= 0)
start += L.len
start += inserted_list.len
if(end <= 0)
end += L.len + 1
end += inserted_list.len + 1
--end
while(start < end)
L.Swap(start++,end--)
inserted_list.Swap(start++, end--)
return L
return inserted_list
//Copies a list, and all lists inside it recusively
//Does not copy any other reference type
@@ -1043,6 +1043,29 @@ GLOBAL_LIST_EMPTY(json_cache)
return FALSE
return TRUE
/**
* Attempts to convert a numeric keyed alist of (2=second, 1=first) to a list of (first, second).
*
* If you instead want to discard values and keep only keys, just do list + alist.
*
* Arguments:
* * to_flatten - The alist with sequential numeric keys to extract values from into a normal list.
* * assert - Whether to assert every key is numeric and in bounds.
*/
/proc/flatten_numeric_alist(alist/to_flatten, assert=TRUE)
RETURN_TYPE(/list)
var/count = length(to_flatten)
if(assert)
for(var/key in to_flatten)
if(!isnum(key) || key < 1 || key > count)
CRASH("flatten_numeric_alist not possible for alist: [json_encode(to_flatten)]")
var/list/retval = list()
for(var/i in 1 to count)
retval += to_flatten[i]
return retval
//CHOMPAdd start
/proc/pick_weight(list/list_to_pick)
var/total = 0

View File

@@ -1243,7 +1243,7 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle = new
GLOBAL_LIST_EMPTY(gun_choices)
GLOBAL_LIST_INIT(severity_to_string, list(
GLOBAL_ALIST_INIT(severity_to_string, alist(
EVENT_LEVEL_MUNDANE = "Mundane",
EVENT_LEVEL_MODERATE = "Moderate",
EVENT_LEVEL_MAJOR = "Major"

View File

@@ -173,7 +173,7 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sort_instance, new())
if(call(cmp)(current, last) >= 0)
break
++runHi
reverseRange(L, lo, runHi)
reverse_range(L, lo, runHi)
else
while(runHi < hi)
last = current

View File

@@ -17,6 +17,10 @@
return FALSE
if(!pred.vore_selected)
return FALSE
if(!pred.can_be_afk_pred && (!pred.client || pred.away_from_keyboard))
return FALSE
if(!prey.can_be_afk_prey && (!prey.client || prey.away_from_keyboard))
return FALSE
return TRUE
/// Basic spont vore check.

View File

@@ -410,6 +410,13 @@
name = "chemical storage"
icon_state = "power_display"
/atom/movable/screen/borer
invisibility = INVISIBILITY_ABSTRACT
/atom/movable/screen/borer/chems
name = "chemical storage"
icon_state = "power_display"
/atom/movable/screen/wizard
invisibility = INVISIBILITY_ABSTRACT

View File

@@ -11,3 +11,7 @@
/datum/config_entry/flag/smart_cache_assets
/datum/config_entry/flag/save_spritesheets
/datum/config_entry/string/storage_cdn_iframe
protection = CONFIG_ENTRY_LOCKED
default = "https://vorestation.github.io/byond-client-storage/iframe.html"

View File

@@ -137,7 +137,7 @@ GLOBAL_REAL(Master, /datum/controller/master)
/datum/controller/master/Shutdown()
processing = FALSE
sortTim(subsystems, GLOBAL_PROC_REF(cmp_subsystem_init))
reverseRange(subsystems)
reverse_range(subsystems)
for(var/datum/controller/subsystem/ss in subsystems)
log_world("Shutting down [ss.name] subsystem...")
if (ss.slept_count > 0)
@@ -195,7 +195,7 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
"cost_ms" = subsystem.cost,
"tick_usage" = subsystem.tick_usage,
"usage_per_tick" = average,
"tick_overrun" = subsystem.tick_overrun,
"overtime" = subsystem.tick_overrun,
"initialized" = subsystem.initialized,
"initialization_failure_message" = subsystem.initialization_failure_message,
))
@@ -224,6 +224,12 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
return TRUE
if("view_variables")
if(!check_rights_for(ui.user.client, R_DEBUG))
message_admins(
"[key_name(ui.user)] tried to view master controller variables while having improper rights, \
this is potentially a malicious exploit and worth noting."
)
var/datum/controller/subsystem/subsystem = locate(params["ref"]) in subsystems
if(isnull(subsystem))
to_chat(ui.user, span_warning("Failed to locate subsystem."))
@@ -339,7 +345,7 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
// Allows subsystems to declare other subsystems that must initialize after them.
for(var/datum/controller/subsystem/subsystem as anything in subsystems)
for(var/dependent_type as anything in subsystem.dependents)
for(var/dependent_type in subsystem.dependents)
if(!ispath(dependent_type, /datum/controller/subsystem))
stack_trace("ERROR: MC: subsystem `[subsystem.type]` has an invalid dependent: `[dependent_type]`. Skipping")
continue
@@ -349,7 +355,7 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
// Constructs a reverse-dependency graph.
for(var/datum/controller/subsystem/subsystem as anything in subsystems)
for(var/dependency_type as anything in subsystem.dependencies)
for(var/dependency_type in subsystem.dependencies)
if(!ispath(dependency_type, /datum/controller/subsystem))
stack_trace("ERROR: MC: subsystem `[subsystem.type]` has an invalid dependency: `[dependency_type]`. Skipping")
continue
@@ -383,11 +389,11 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
// Topological sorting algorithm end
if(length(subsystems) != length(sorted_subsystems))
var/list/circular_dependency = subsystems.Copy() - sorted_subsystems
var/list/circular_dependency = subsystems - sorted_subsystems
var/list/debug_msg = list()
var/list/usr_msg = list()
for(var/datum/controller/subsystem/subsystem as anything in circular_dependency)
usr_msg += "[subsystem.name]"
usr_msg += subsystem.name
var/list/datum/controller/subsystem/nodes = list(circular_dependency[1])
var/list/loop = list()
@@ -604,10 +610,19 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
if ((SS.flags & (SS_TICKER|SS_BACKGROUND)) == SS_TICKER)
tickersubsystems += SS
// Timer subsystems aren't allowed to bunch up, so we offset them a bit
timer += world.tick_lag * rand(0, 1)
timer += TICKS2DS(rand(0, 1))
SS.next_fire = timer
continue
// Now, we have to set starting next_fires for all our new non ticker kids
if(SS.init_stage == init_stage - 1 && (SS.runlevels & current_runlevel))
// Give em a random offset so things don't clump up too bad
var/delay = SS.wait
if(SS.flags & SS_TICKER)
delay = TICKS2DS(delay)
// Gotta convert to ticks cause rand needs integers
SS.next_fire = world.time + TICKS2DS(rand(0, DS2TICKS(min(delay, 2 SECONDS))))
var/ss_runlevels = SS.runlevels
var/added_to_any = FALSE
for(var/I in 1 to GLOB.bitflags.len)
@@ -703,7 +718,11 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
//we only want to offset it if it's new and also behind
if(SS.next_fire > world.time || (SS in old_subsystems))
continue
SS.next_fire = world.time + world.tick_lag * rand(0, DS2TICKS(min(SS.wait, 2 SECONDS)))
// If they're new, give em a random offset so things don't clump up too bad
var/delay = SS.wait
if(SS.flags & SS_TICKER)
delay = TICKS2DS(delay)
SS.next_fire = world.time + TICKS2DS(rand(0, DS2TICKS(min(delay, 2 SECONDS))))
subsystems_to_check = current_runlevel_subsystems
else
@@ -798,6 +817,8 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
if (SS_flags & SS_NO_FIRE)
subsystemstocheck -= SS
continue
// If we're keeping timing and running behind,
// fire at most 25% faster then normal to try and make up the gap without spamming
if ((SS_flags & (SS_TICKER|SS_KEEP_TIMING)) == SS_KEEP_TIMING && SS.last_fire + (SS.wait * 0.75) > world.time)
continue
if (SS.postponed_fires >= 1)

View File

@@ -75,10 +75,15 @@ SUBSYSTEM_DEF(appreciation)
return
var/mob/living/carbon/human/H = pick(human_list)
if(!istype(H))
appreciated = pick(loremaster.appreciation_targets)
return
if(H.absorbed)
appreciated = pick(loremaster.appreciation_targets)
return
if(H.custom_species)
appreciated = H.custom_species
return

View File

@@ -11,13 +11,13 @@ SUBSYSTEM_DEF(events)
var/list/datum/event/finished_events = list()
var/list/datum/event/allEvents
var/list/datum/event_container/event_containers
var/alist/event_containers
var/datum/event_meta/new_event = new
/datum/controller/subsystem/events/Initialize()
allEvents = subtypesof(/datum/event)
event_containers = list(
event_containers = alist(
EVENT_LEVEL_MUNDANE = new/datum/event_container/mundane,
EVENT_LEVEL_MODERATE = new/datum/event_container/moderate,
EVENT_LEVEL_MAJOR = new/datum/event_container/major

View File

@@ -5,12 +5,12 @@ SUBSYSTEM_DEF(nightshift)
)
priority = FIRE_PRIORITY_NIGHTSHIFT
wait = 60 SECONDS
flags = SS_NO_TICK_CHECK
var/nightshift_active = FALSE
var/nightshift_first_check = 30 SECONDS
var/high_security_mode = FALSE
var/list/currentrun
/datum/controller/subsystem/nightshift/Initialize()
if(!CONFIG_GET(flag/enable_night_shifts))
@@ -18,7 +18,10 @@ SUBSYSTEM_DEF(nightshift)
return SS_INIT_SUCCESS
/datum/controller/subsystem/nightshift/fire(resumed = FALSE)
if(round_duration_in_ds < nightshift_first_check)
if(resumed)
update_nightshift(resumed = TRUE)
return
if(world.time - SSticker.round_start_time < nightshift_first_check)
return
check_nightshift()
@@ -39,9 +42,7 @@ SUBSYSTEM_DEF(nightshift)
// CHOMPEdit End
//VOREStation Edit End
/datum/controller/subsystem/nightshift/proc/check_nightshift(check_canfire=FALSE) //This is called from elsewhere, like setting the alert levels
if(check_canfire && !can_fire)
return
/datum/controller/subsystem/nightshift/proc/check_nightshift(forced) //This is called from elsewhere, like setting the alert levels, sadly
var/emergency = GLOB.security_level > SEC_LEVEL_GREEN
var/announcing = TRUE
var/night_time = using_map.get_nightshift()
@@ -56,16 +57,20 @@ SUBSYSTEM_DEF(nightshift)
if(emergency)
night_time = FALSE
if(nightshift_active != night_time)
update_nightshift(night_time, announcing)
update_nightshift(night_time, announcing, forced = forced)
/datum/controller/subsystem/nightshift/proc/update_nightshift(active, announce = TRUE, resumed = FALSE, forced = FALSE)
nightshift_active = active
if(announce)
if(active)
announce("Good evening, crew. To reduce power consumption and stimulate the circadian rhythms of some species, all of the lights aboard the station have been dimmed for the night.")
else
announce("Good morning, crew. As it is now day time, all of the lights aboard the station have been restored to their former brightness.")
for(var/obj/machinery/power/apc/apc in GLOB.apcs)
if(!resumed)
currentrun = GLOB.apcs
nightshift_active = active
if(announce)
if (active)
announce("Good evening, crew. To reduce power consumption and stimulate the circadian rhythms of some species, all of the lights aboard the station have been dimmed for the night.")
else
announce("Good morning, crew. As it is now day time, all of the lights aboard the station have been restored to their former brightness.")
for(var/obj/machinery/power/apc/apc as anything in currentrun)
currentrun -= apc
if(apc.z in using_map.station_levels)
apc.set_nightshift(active, TRUE)
CHECK_TICK
if(MC_TICK_CHECK && !forced) // subsystem will be in state SS_IDLE if forced by an admin
return

View File

@@ -3,6 +3,20 @@ SUBSYSTEM_DEF(sun)
wait = 600
flags = SS_NO_INIT
var/static/datum/sun/sun = new
var/list/current_run
/datum/controller/subsystem/sun/fire()
sun.calc_position()
/datum/controller/subsystem/sun/fire(resumed)
if(!resumed)
current_run = GLOB.solars_list.Copy()
sun.calc_position()
//now tell the solar control computers to update their status and linked devices
while(current_run.len)
var/obj/machinery/power/solar_control/SC = current_run[current_run.len]
current_run.len--
if(!SC.powernet)
GLOB.solars_list.Remove(SC)
continue
SC.update()
if(MC_TICK_CHECK)
return

View File

@@ -80,7 +80,7 @@ SUBSYSTEM_DEF(supply)
var/base_value = 0
// Most items must be in a crate!
var/sold_successfully = FALSE
var/list/things_sold_successfully = list()
if(istype(MA,/obj/structure/closet/crate))
var/obj/structure/closet/crate/CR = MA
@@ -90,12 +90,14 @@ SUBSYSTEM_DEF(supply)
// For each thing in the crate, get the value and quantity
for(var/atom/A in CR)
sold_successfully = SEND_SIGNAL(A,COMSIG_ITEM_SOLD,EC,TRUE)
if(SEND_SIGNAL(A,COMSIG_ITEM_SOLD,EC,TRUE))
things_sold_successfully += A
else
// Selling things that are not in crates.
// Usually it just makes a log that it wasn't shipped properly, and so isn't worth anything
sold_successfully = SEND_SIGNAL(MA,COMSIG_ITEM_SOLD,EC,FALSE)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_SUPPLY_SHUTTLE_SELL_ITEM, MA, sold_successfully, EC, subarea)
if(SEND_SIGNAL(MA,COMSIG_ITEM_SOLD,EC,FALSE))
things_sold_successfully += MA
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_SUPPLY_SHUTTLE_SELL_ITEM, MA, things_sold_successfully, EC, subarea)
exported_crates += EC
points += EC.value

View File

@@ -15,9 +15,12 @@ SUBSYSTEM_DEF(tgui)
wait = 9
flags = SS_NO_INIT
priority = FIRE_PRIORITY_TGUI
init_stage = INITSTAGE_EARLY
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
dependencies = list(
/datum/controller/subsystem/assets
)
/// A list of UIs scheduled to process
var/list/current_run = list()
/// A list of all open UIs
@@ -40,6 +43,25 @@ SUBSYSTEM_DEF(tgui)
basehtml = replacetextEx(basehtml, "<!-- tgui:nt-copyright -->", "Nanotrasen (c) 2284-[text2num(time2text(world.realtime,"YYYY")) + STATION_YEAR_OFFSET]")
/datum/controller/subsystem/tgui/OnConfigLoad()
var/storage_iframe = CONFIG_GET(string/storage_cdn_iframe)
if(storage_iframe && storage_iframe != /datum/config_entry/string/storage_cdn_iframe::default)
basehtml = replacetextEx(basehtml, "\[tgui:storagecdn]", storage_iframe)
return
if(CONFIG_GET(string/asset_transport) == "webroot")
var/datum/asset_transport/webroot/webroot = SSassets.transport
var/datum/asset_cache_item/item = webroot.register_asset("iframe.html", file("tgui/public/iframe.html"))
basehtml = replacetextEx(basehtml, "\[tgui:storagecdn]", webroot.get_asset_url("iframe.html", item))
return
if(!storage_iframe)
return
basehtml = replacetextEx(basehtml, "\[tgui:storagecdn]", storage_iframe)
/datum/controller/subsystem/tgui/Shutdown()
close_all_uis()

View File

@@ -379,7 +379,7 @@ SUBSYSTEM_DEF(timer)
var/spent = 0
/// Holds info about this timer, stored from the moment it was created
/// Used to create a visible "name" whenever the timer is stringified
var/list/timer_info
var/alist/timer_info
/// Next timed event in the bucket
var/datum/timedevent/next
/// Previous timed event in the bucket
@@ -521,7 +521,7 @@ SUBSYSTEM_DEF(timer)
/datum/timedevent/proc/bucketJoin()
#if defined(TIMER_DEBUG)
// Generate debug-friendly list for timer, more complex but also more expensive
timer_info = list(
timer_info = alist(
1 = id,
2 = timeToRun,
3 = wait,
@@ -536,7 +536,7 @@ SUBSYSTEM_DEF(timer)
)
#else
// Generate a debuggable list for the timer, simpler but wayyyy cheaper, string generation (and ref/copy memes) is a bitch and this saves a LOT of time
timer_info = list(
timer_info = alist(
1 = id,
2 = timeToRun,
3 = wait,

View File

@@ -55,7 +55,7 @@
return
if(owner.client && (owner.client.prefs.muted & MUTE_IC))
return
if(owner.paralysis <= 1 && (H.pulse == PULSE_NORM ? (prob(1)) : (prob(50))))
if(owner.paralysis <= 1 && (H.pulse <= PULSE_NORM ? (prob(1)) : (prob(50))))
owner.make_jittery(30 + rand(10, 30))
owner.emote(pick(motor_tics))

View File

@@ -74,7 +74,8 @@
/datum/construction/proc/spawn_result()
if(result)
new result(get_turf(holder))
var/atom/spawned_construct = new result(get_turf(holder))
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MECH_CONSTRUCTED, spawned_construct)
spawn()
qdel(holder)
return

View File

@@ -39,3 +39,13 @@
belt = /obj/item/storage/belt/utility/atmostech
id_type = /obj/item/card/id/engineering/atmos
pda_type = /obj/item/pda/atmos
/decl/hierarchy/outfit/job/engineering/chems
name = OUTFIT_JOB_NAME(JOB_ALT_CHEMENGINEER)
head = /obj/item/clothing/head/hardhat
uniform = /obj/item/clothing/under/rank/engineer
belt = /obj/item/storage/belt/utility/chemtech
id_type = /obj/item/card/id/engineering/chemical
pda_type = /obj/item/pda
r_pocket = null // no tray
suit = /obj/item/clothing/suit/storage/toggle/labcoat/yellow

View File

@@ -32,10 +32,3 @@
else
dx = s/abs(s)
dy = c / abs(s)
//now tell the solar control computers to update their status and linked devices
for(var/obj/machinery/power/solar_control/SC in GLOB.solars_list)
if(!SC.powernet)
GLOB.solars_list.Remove(SC)
continue
SC.update()

View File

@@ -29,6 +29,27 @@
containertype = /obj/structure/closet/crate/grayson
containername = "Wooden planks crate"
/datum/supply_pack/materials/birch50
name = "50 birch planks"
contains = list(/obj/fiftyspawner/birchwood)
cost = 10
containertype = /obj/structure/closet/crate/grayson
containername = "Birch planks crate"
/datum/supply_pack/materials/oak50
name = "50 oak planks"
contains = list(/obj/fiftyspawner/oakwood)
cost = 10
containertype = /obj/structure/closet/crate/grayson
containername = "Oak planks crate"
/datum/supply_pack/materials/pine50
name = "50 pine planks"
contains = list(/obj/fiftyspawner/pinewood)
cost = 10
containertype = /obj/structure/closet/crate/grayson
containername = "Pine planks crate"
/datum/supply_pack/materials/alienwood50
name = "50 alien wood planks"
contains = list(/obj/fiftyspawner/sifwood)
@@ -36,6 +57,13 @@
containertype = /obj/structure/closet/crate/grayson
containername = "Alien wood planks crate"
/datum/supply_pack/materials/acacia50
name = "50 acacia planks"
contains = list(/obj/fiftyspawner/acaciawood)
cost = 35
containertype = /obj/structure/closet/crate/gilthari
containername = "Acacia planks crate"
/datum/supply_pack/materials/hardwood50
name = "50 hardwood planks"
contains = list(/obj/fiftyspawner/hardwood)
@@ -43,6 +71,13 @@
containertype = /obj/structure/closet/crate/gilthari
containername = "Hardwood planks crate"
/datum/supply_pack/materials/redwood50
name = "50 redwood planks"
contains = list(/obj/fiftyspawner/redwood)
cost = 50
containertype = /obj/structure/closet/crate/gilthari
containername = "Redwood planks crate"
/datum/supply_pack/materials/plastic50
name = "50 plastic sheets"
contains = list(/obj/fiftyspawner/plastic)

View File

@@ -5,7 +5,7 @@ var/datum/antagonist/borer/borers
role_type = BE_ALIEN
role_text = "Cortical Borer"
role_text_plural = "Cortical Borers"
mob_path = /mob/living/simple_mob/animal/borer
mob_path = /mob/living/simple_mob/animal/borer/roundstart // Use roundstart borer, or ghostcheck makes it take forever to enter mob when assigned
bantype = "Borer"
welcome_text = "Use your Infest power to crawl into the ear of a host and fuse with their brain. You can only take control temporarily, and at risk of hurting your host, so be clever and careful; your host is encouraged to help you however they can. Talk to your fellow borers with :x."
antag_indicator = "brainworm"

View File

@@ -26,6 +26,8 @@
M = new /mob/living/carbon/human(get_turf(source))
M.real_name = source.real_name
M.name = M.real_name
if(!isnull(source.mind))
source.mind.transfer_to(M)
M.ckey = source.ckey
add_antagonist(M.mind, 1, 0, 1) // Equip them and move them to spawn.
return M

View File

@@ -80,7 +80,7 @@
access = list(ACCESS_EVA, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS)
minimal_access = list(ACCESS_EVA, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION)
alt_titles = list(JOB_ALT_MAINTENANCE_TECHNICIAN = /datum/alt_title/maint_tech, JOB_ALT_ENGINE_TECHNICIAN = /datum/alt_title/engine_tech,
JOB_ALT_ELECTRICIAN = /datum/alt_title/electrician, JOB_ALT_CONSTRUCTION_ENGINEER = /datum/alt_title/construction_engi, JOB_ALT_ENGINEERING_CONTRACTOR = /datum/alt_title/engineering_contractor, JOB_ALT_COMPUTER_TECHNICIAN = /datum/alt_title/computer_tech, JOB_ALT_SALVAGE_TECHNICIAN = /datum/alt_title/salvage_tech, JOB_ALT_DAMAGE_CONTROL_SPECIALIST = /datum/alt_title/damage_control_specialist)
JOB_ALT_ELECTRICIAN = /datum/alt_title/electrician, JOB_ALT_CONSTRUCTION_ENGINEER = /datum/alt_title/construction_engi, JOB_ALT_ENGINEERING_CONTRACTOR = /datum/alt_title/engineering_contractor, JOB_ALT_COMPUTER_TECHNICIAN = /datum/alt_title/computer_tech, JOB_ALT_SALVAGE_TECHNICIAN = /datum/alt_title/salvage_tech, JOB_ALT_DAMAGE_CONTROL_SPECIALIST = /datum/alt_title/damage_control_specialist, JOB_ALT_CHEMENGINEER = /datum/alt_title/chem_tech)
minimal_player_age = 3
min_age_by_species = list(SPECIES_PROMETHEAN = 2)
@@ -135,6 +135,11 @@
title = JOB_ALT_DAMAGE_CONTROL_SPECIALIST
title_blurb = "A " + JOB_ALT_DAMAGE_CONTROL_SPECIALIST + " is the Engineering Department's answer to first responders like the " + JOB_PARAMEDIC + ", being responsible for stabilizing situations and evacuating personnel, then conducting repairs."
/datum/alt_title/chem_tech
title = JOB_ALT_CHEMENGINEER
title_blurb = "A " + JOB_ALT_CHEMENGINEER + " specializes in industrial scale chemical production. They are responsible for planning the construction of and operating chemical refinery machines."
title_outfit = /decl/hierarchy/outfit/job/engineering/chems
//////////////////////////////////
// Atmos Tech
//////////////////////////////////

View File

@@ -247,6 +247,11 @@ GLOBAL_LIST(construction_frame_floor)
icon_override = 'icons/obj/stock_parts_refinery.dmi'
frame_class = FRAME_CLASS_MACHINE
/datum/frame/frame_types/industrial_reagent_splitter
name = "Industrial Chemical Splitter"
icon_override = 'icons/obj/stock_parts_refinery.dmi'
frame_class = FRAME_CLASS_MACHINE
/datum/frame/frame_types/industrial_reagent_waste_processor
name = "Industrial Chemical Waste Processor"
icon_override = 'icons/obj/stock_parts_refinery.dmi'

View File

@@ -57,6 +57,7 @@ GLOBAL_LIST_INIT(disposal_pipe_recipes, list(
new /datum/pipe_recipe/disposal("Sort Junction", DISPOSAL_PIPE_SORTER, "conpipe-j1s", PIPE_TRIN_M, DISPOSAL_SORT_NORMAL),
new /datum/pipe_recipe/disposal("Sort Junction (Wildcard)", DISPOSAL_PIPE_SORTER, "conpipe-j1s", PIPE_TRIN_M, DISPOSAL_SORT_WILDCARD),
new /datum/pipe_recipe/disposal("Sort Junction (Untagged)", DISPOSAL_PIPE_SORTER, "conpipe-j1s", PIPE_TRIN_M, DISPOSAL_SORT_UNTAGGED),
new /datum/pipe_recipe/disposal("Sort Junction (Body Recovery)", DISPOSAL_PIPE_SORTER, "conpipe-j1s", PIPE_TRIN_M, DISPOSAL_SORT_BODIES),
new /datum/pipe_recipe/disposal("Tagger", DISPOSAL_PIPE_TAGGER, "pipe-tagger", PIPE_STRAIGHT),
new /datum/pipe_recipe/disposal("Tagger (Partial)", DISPOSAL_PIPE_TAGGER_PARTIAL, "pipe-tagger-partial", PIPE_STRAIGHT),
new /datum/pipe_recipe/disposal("Trunk", DISPOSAL_PIPE_TRUNK, "conpipe-t"),

View File

@@ -192,11 +192,12 @@
update_icon()
if(!M.has_brain_worms())
update_use_power(USE_POWER_ACTIVE)
enter_vr()
else
if(M.has_brain_worms())
to_chat(user, span_warning("\The [src] rejects [M] with a sharp beep."))
return
update_use_power(USE_POWER_ACTIVE)
enter_vr()
return
/obj/machinery/vr_sleeper/proc/go_out()

View File

@@ -99,7 +99,7 @@
/datum/construction/reversible/mecha/ripley
result = "/obj/mecha/working/ripley"
result = /obj/mecha/working/ripley
steps = list(
//1
list("key"=IS_WELDER,
@@ -307,7 +307,7 @@
/datum/construction/reversible/mecha/gygax
result = "/obj/mecha/combat/gygax"
result = /obj/mecha/combat/gygax
steps = list(
//1
list("key"=IS_WELDER,
@@ -589,7 +589,7 @@
/datum/construction/reversible/mecha/serenity
result = "/obj/mecha/combat/gygax/serenity"
result = /obj/mecha/combat/gygax/serenity
steps = list(
//1
list("key"=IS_WELDER,
@@ -872,7 +872,7 @@
/datum/construction/reversible/mecha/firefighter
result = "/obj/mecha/working/ripley/firefighter"
result = /obj/mecha/working/ripley/firefighter
steps = list(
//1
list("key"=IS_WELDER,
@@ -1092,7 +1092,7 @@
/datum/construction/reversible/mecha/durand
result = "/obj/mecha/combat/durand"
result = /obj/mecha/combat/durand
steps = list(
//1
list("key"=IS_WELDER,
@@ -1374,7 +1374,7 @@
/datum/construction/reversible/mecha/odysseus
result = "/obj/mecha/medical/odysseus"
result = /obj/mecha/medical/odysseus
steps = list(
//1
list("key"=IS_WELDER,
@@ -1554,7 +1554,7 @@
// Phazon
//////////////////////
/datum/construction/mecha/phazon_chassis
result = "/obj/mecha/combat/phazon"
result = /obj/mecha/combat/phazon
steps = list(list("key"=/obj/item/mecha_parts/part/phazon_torso),//1
list("key"=/obj/item/mecha_parts/part/phazon_left_arm),//2
list("key"=/obj/item/mecha_parts/part/phazon_right_arm),//3
@@ -1583,7 +1583,7 @@
return
/datum/construction/reversible/mecha/phazon
result = "/obj/mecha/combat/phazon"
result = /obj/mecha/combat/phazon
steps = list(
//1
list("key"=IS_WELDER,
@@ -1833,7 +1833,7 @@
// Janus
//////////////////////
/datum/construction/mecha/janus_chassis
result = "/obj/mecha/combat/phazon/janus"
result = /obj/mecha/combat/phazon/janus
steps = list(list("key"=/obj/item/mecha_parts/part/janus_torso),//1
list("key"=/obj/item/mecha_parts/part/janus_left_arm),//2
list("key"=/obj/item/mecha_parts/part/janus_right_arm),//3
@@ -1862,7 +1862,7 @@
return
/datum/construction/reversible/mecha/janus
result = "/obj/mecha/combat/phazon/janus"
result = /obj/mecha/combat/phazon/janus
steps = list(
//1
list("key"=IS_WELDER,
@@ -2138,7 +2138,7 @@
// Pinnace
//////////////////////
/datum/construction/mecha/fighter/pinnace_chassis
result = "/obj/mecha/combat/fighter/pinnace"
result = /obj/mecha/combat/fighter/pinnace
steps = list(list("key"=/obj/item/mecha_parts/fighter/part/pinnace_core),//1
list("key"=/obj/item/mecha_parts/fighter/part/pinnace_cockpit),//2
list("key"=/obj/item/mecha_parts/fighter/part/pinnace_main_engine),//3
@@ -2168,7 +2168,7 @@
return
/datum/construction/reversible/mecha/fighter/pinnace
result = "/obj/mecha/combat/fighter/pinnace"
result = /obj/mecha/combat/fighter/pinnace
steps = list(
//1
list("key"=IS_WELDER,
@@ -2421,7 +2421,7 @@
// Baron
//////////////////////
/datum/construction/mecha/fighter/baron_chassis
result = "/obj/mecha/combat/fighter/baron"
result = /obj/mecha/combat/fighter/baron
steps = list(list("key"=/obj/item/mecha_parts/fighter/part/baron_core),//1
list("key"=/obj/item/mecha_parts/fighter/part/baron_cockpit),//2
list("key"=/obj/item/mecha_parts/fighter/part/baron_main_engine),//3
@@ -2451,7 +2451,7 @@
return
/datum/construction/reversible/mecha/fighter/baron
result = "/obj/mecha/combat/fighter/baron"
result = /obj/mecha/combat/fighter/baron
steps = list(
//1
list("key"=IS_WELDER,

View File

@@ -28,7 +28,7 @@
/datum/construction/reversible/mecha/scarab
result = "/obj/mecha/combat/scarab"
result = /obj/mecha/combat/scarab
steps = list(
//1
list("key"=IS_WELDER,

View File

@@ -29,7 +29,7 @@
/datum/construction/reversible/mecha/polecat
result = "/obj/mecha/micro/sec/polecat"
result = /obj/mecha/micro/sec/polecat
steps = list(
//1
list("key"=IS_WELDER,
@@ -308,7 +308,7 @@
/datum/construction/reversible/mecha/gopher
result = "/obj/mecha/micro/utility/gopher"
result = /obj/mecha/micro/utility/gopher
steps = list(
//1
list("key"=IS_WELDER,
@@ -514,7 +514,7 @@
/datum/construction/reversible/mecha/weasel
result = "/obj/mecha/micro/sec/weasel"
result = /obj/mecha/micro/sec/weasel
steps = list(
//1
list("key"=IS_WELDER,

View File

@@ -138,8 +138,7 @@
for(var/i = 0, i < range, i++) //calculate positions for smoke coverage - then spawn smoke
var/radius = i * 1.5
if(!radius)
spawn(0)
spawnSmoke(location, I, 1)
spawnSmoke(location, I, 1)
continue
var/offset = 0
@@ -157,8 +156,7 @@
if(!T)
continue
if(T in targetTurfs)
spawn(0)
spawnSmoke(T, I, range)
spawnSmoke(T, I, range)
//------------------------------------------
// Randomizes and spawns the smoke effect.

View File

@@ -268,7 +268,7 @@
dat += "<br>"
// if (M.reagents && M.reagents.get_reagent_amount(REAGENT_ID_INAPROVALINE))
// user.show_message(span_notice("Bloodstream Analysis located [M.reagents:get_reagent_amount(REAGENT_ID_INAPROVALINE)] units of rejuvenation chemicals."))
if (M.has_brain_worms())
if (advscan >= 2 && M.has_brain_worms()) // Borers need to hide
dat += span_warning("Subject suffering from aberrant brain activity. Recommend further scanning.")
dat += "<br>"
else if (M.getBrainLoss() >= 60 || !M.has_brain())

View File

@@ -19,11 +19,14 @@
/obj/item/motiontracker/Initialize(mapload)
RegisterSignal(SSmotiontracker, COMSIG_MOVABLE_MOTIONTRACKER, PROC_REF(handle_motion_tracking))
. = ..()
if(ismob(loc))
var/mob/M = loc
M.motiontracker_subscribe()
/obj/item/motiontracker/Destroy(force, ...)
if(ismob(loc))
var/mob/M = loc
M.motiontracker_subscribe()
M.motiontracker_unsubscribe()
UnregisterSignal(SSmotiontracker, COMSIG_MOVABLE_MOTIONTRACKER)
. = ..()

View File

@@ -121,31 +121,272 @@
drop_sound = 'sound/items/drop/wooden.ogg'
pickup_sound = 'sound/items/pickup/wooden.ogg'
/obj/item/stack/tile/wood/sif
name = "alien wood tile"
singular_name = "alien wood tile"
desc = "An easy to fit wooden floor tile. It's blue!"
icon_state = "tile-sifwood"
/obj/item/stack/tile/wood/alt
name = "wood floor tile"
singular_name = "wood floor tile"
icon_state = "tile-wood_tile"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-gs"
color = "#593c1c"
/obj/item/stack/tile/wood/parquet
name = "parquet wood floor tile"
singular_name = "parquet wood floor tile"
icon_state = "tile-wood_parquet"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-gs_parquet"
color = "#593c1c"
/obj/item/stack/tile/wood/panel
name = "large wood floor tile"
singular_name = "large wood floor tile"
icon_state = "tile-wood_large"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-gs_large"
color = "#593c1c"
/obj/item/stack/tile/wood/tile
name = "tiled wood floor tile"
singular_name = "tiled wood floor tile"
icon_state = "tile-wood_tile"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-gs_tile"
color = "#593c1c"
/obj/item/stack/tile/wood/vert
name = "vertical wood floor tile"
singular_name = "vertical wood floor tile"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-vert-gs"
color = "#593c1c"
/obj/item/stack/tile/wood/vert_panel
name = "large vertical wood floor tile"
singular_name = "large vertical wood floor tile"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-vert-gs_large"
color = "#593c1c"
/obj/item/stack/tile/wood/sif
name = "alien wood tile"
singular_name = "alien wood tile"
desc = "An easy to fit wooden floor tile. It's blue!"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-gs"
color = "#293c50"
/obj/item/stack/tile/wood/sif/parquet
name = "alien wood parquet tile"
singular_name = "alien wood parquet tile"
icon_state = "tile-wood-gs_parquet"
/obj/item/stack/tile/wood/sif/panel
name = "large alien wood tile"
singular_name = "large alien wood tile"
icon_state = "tile-wood-gs_large"
/obj/item/stack/tile/wood/sif/tile
name = "tiled alien wood tile"
singular_name = "tiled alien wood tile"
icon_state = "tile-wood-gs_tile"
/obj/item/stack/tile/wood/sif/vert
name = "vertical alien wood floor tile"
singular_name = "vertical alien wood floor tile"
icon_state = "tile-wood-vert-gs"
/obj/item/stack/tile/wood/sif/vert_panel
name = "large vertical alien wood floor tile"
singular_name = "large vertical alien wood floor tile"
icon_state = "tile-wood-vert-gs_large"
/obj/item/stack/tile/wood/acacia
name = "acacia wood floor tile"
singular_name = "wood floor tile"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-gs"
color = "#b75e12"
/obj/item/stack/tile/wood/acacia/parquet
name = "acacia parquet floor tile"
singular_name = "parquet wood floor tile"
icon_state = "tile-wood-gs_parquet"
/obj/item/stack/tile/wood/acacia/panel
name = "large acacia floor tile"
singular_name = "large wood floor tile"
icon_state = "tile-wood-gs_large"
/obj/item/stack/tile/wood/acacia/tile
name = "tiled acacia floor tile"
singular_name = "tiled wood floor tile"
icon_state = "tile-wood-gs_tile"
/obj/item/stack/tile/wood/acacia/vert
name = "vertical acacia wood floor tile"
singular_name = "vertical acacia wood floor tile"
icon_state = "tile-wood-vert-gs"
/obj/item/stack/tile/wood/acacia/vert_panel
name = "large vertical acacia wood floor tile"
singular_name = "large vertical acacia wood floor tile"
icon_state = "tile-wood-vert-gs_large"
/obj/item/stack/tile/wood/birch
name = "birch wood floor tile"
singular_name = "wood floor tile"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-gs"
color = "#f6dec0"
/obj/item/stack/tile/wood/birch/parquet
name = "birch parquet floor tile"
singular_name = "parquet wood floor tile"
icon_state = "tile-wood-gs_parquet"
/obj/item/stack/tile/wood/birch/panel
name = "large birch floor tile"
singular_name = "large wood floor tile"
icon_state = "tile-wood-gs_large"
/obj/item/stack/tile/wood/birch/tile
name = "tiled birch floor tile"
singular_name = "tiled wood floor tile"
icon_state = "tile-wood-gs_tile"
/obj/item/stack/tile/wood/birch/vert
name = "vertical birch wood floor tile"
singular_name = "vertical birch wood floor tile"
icon_state = "tile-wood-vert-gs"
/obj/item/stack/tile/wood/birch/vert_panel
name = "large vertical birch wood floor tile"
singular_name = "large vertical birch wood floor tile"
icon_state = "tile-wood-vert-gs_large"
/obj/item/stack/tile/wood/hardwood
name = "hardwood wood floor tile"
singular_name = "wood floor tile"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-gs"
color = "#42291a"
/obj/item/stack/tile/wood/hardwood/parquet
name = "hardwood parquet floor tile"
singular_name = "parquet wood floor tile"
icon_state = "tile-wood-gs_parquet"
/obj/item/stack/tile/wood/hardwood/panel
name = "large hardwood floor tile"
singular_name = "large wood floor tile"
icon_state = "tile-wood-gs_large"
/obj/item/stack/tile/wood/hardwood/tile
name = "tiled hardwood floor tile"
singular_name = "tiled wood floor tile"
icon_state = "tile-wood-gs_tile"
/obj/item/stack/tile/wood/hardwood/vert
name = "vertical hardwood wood floor tile"
singular_name = "vertical hardwood wood floor tile"
icon_state = "tile-wood-vert-gs"
/obj/item/stack/tile/wood/hardwood/vert_panel
name = "large vertical hardwood wood floor tile"
singular_name = "large vertical hardwood wood floor tile"
icon_state = "tile-wood-vert-gs_large"
/obj/item/stack/tile/wood/pine
name = "pine wood floor tile"
singular_name = "wood floor tile"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-gs"
color = "#cd9d6f"
/obj/item/stack/tile/wood/pine/parquet
name = "pine parquet floor tile"
singular_name = "parquet wood floor tile"
icon_state = "tile-wood-gs_parquet"
/obj/item/stack/tile/wood/pine/panel
name = "large pine floor tile"
singular_name = "large wood floor tile"
icon_state = "tile-wood-gs_large"
/obj/item/stack/tile/wood/pine/tile
name = "tiled pine floor tile"
singular_name = "tiled wood floor tile"
icon_state = "tile-wood-gs_tile"
/obj/item/stack/tile/wood/pine/vert
name = "vertical pine wood floor tile"
singular_name = "vertical pine wood floor tile"
icon_state = "tile-wood-vert-gs"
/obj/item/stack/tile/wood/pine/vert_panel
name = "large vertical pine wood floor tile"
singular_name = "large vertical pine wood floor tile"
icon_state = "tile-wood-vert-gs_large"
/obj/item/stack/tile/wood/oak
name = "oak wood floor tile"
singular_name = "wood floor tile"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-gs"
color = "#674928"
/obj/item/stack/tile/wood/oak/parquet
name = "oak parquet floor tile"
singular_name = "parquet wood floor tile"
icon_state = "tile-wood-gs_parquet"
/obj/item/stack/tile/wood/oak/panel
name = "large oak floor tile"
singular_name = "large wood floor tile"
icon_state = "tile-wood-gs_large"
/obj/item/stack/tile/wood/oak/tile
name = "tiled oak floor tile"
singular_name = "tiled wood floor tile"
icon_state = "tile-wood-gs_tile"
/obj/item/stack/tile/wood/oak/vert
name = "vertical oak wood floor tile"
singular_name = "vertical oak wood floor tile"
icon_state = "tile-wood-vert-gs"
/obj/item/stack/tile/wood/oak/vert_panel
name = "large vertical oak wood floor tile"
singular_name = "large vertical oak wood floor tile"
icon_state = "tile-wood-vert-gs_large"
/obj/item/stack/tile/wood/redwood
name = "redwood floor tile"
singular_name = "redwood floor tile"
icon = 'icons/obj/stacks_vr.dmi'
icon_state = "tile-wood-gs"
color = "#a45a52"
/obj/item/stack/tile/wood/redwood/parquet
name = "redwood parquet floor tile"
singular_name = "parquet redwood floor tile"
icon_state = "tile-wood-gs_parquet"
/obj/item/stack/tile/wood/redwood/panel
name = "large redwood floor tile"
singular_name = "large redwood floor tile"
icon_state = "tile-wood-gs_large"
/obj/item/stack/tile/wood/redwood/tile
name = "tiled redwood floor tile"
singular_name = "tiled redwood floor tile"
icon_state = "tile-wood-gs_tile"
/obj/item/stack/tile/wood/redwood/vert
name = "vertical redwood wood floor tile"
singular_name = "vertical redwood wood floor tile"
icon_state = "tile-wood-vert-gs"
/obj/item/stack/tile/wood/redwood/vert_panel
name = "large vertical redwood wood floor tile"
singular_name = "large vertical redwood wood floor tile"
icon_state = "tile-wood-vert-gs_large"
/obj/item/stack/tile/wood/cyborg
name = "wood floor tile synthesizer"
@@ -397,3 +638,43 @@
stacktype = /obj/item/stack/tile/roofing
build_type = /obj/item/stack/tile/roofing
can_weld = FALSE
/obj/item/stack/tile/floor/gold
name = "gold floor tile"
singular_name = "gold floor tile"
icon_state = "tile-gold"
matter = list(MAT_GOLD = SHEET_MATERIAL_AMOUNT / 4)
welds_into = /obj/item/stack/material/gold
no_variants = FALSE
/obj/item/stack/tile/floor/silver
name = "silver floor tile"
singular_name = "silver floor tile"
icon_state = "tile-silver"
matter = list(MAT_SILVER = SHEET_MATERIAL_AMOUNT / 4)
welds_into = /obj/item/stack/material/silver
no_variants = FALSE
/obj/item/stack/tile/floor/phoron
name = "phoron floor tile"
singular_name = "phoron floor tile"
icon_state = "tile-phoron"
matter = list(MAT_PHORON = SHEET_MATERIAL_AMOUNT / 4)
welds_into = /obj/item/stack/material/phoron
no_variants = FALSE
/obj/item/stack/tile/floor/diamond
name = "diamond floor tile"
singular_name = "diamond floor tile"
icon_state = "tile-diamond"
matter = list(MAT_DIAMOND = SHEET_MATERIAL_AMOUNT / 4)
welds_into = /obj/item/stack/material/diamond
no_variants = FALSE
/obj/item/stack/tile/floor/uranium
name = "uranium floor tile"
singular_name = "uranium floor tile"
icon_state = "tile-uranium"
matter = list(MAT_URANIUM = SHEET_MATERIAL_AMOUNT / 4)
welds_into = /obj/item/stack/material/uranium
no_variants = FALSE

View File

@@ -180,5 +180,7 @@
M.visible_message(span_infoplain(span_bold("\The [user]") + " scans the wounds on [M]'s [S.name] with [src]"))
src.add_data(S)
SEND_SIGNAL(src,COMSIG_AUTOPSY_PERFORMED, user, M)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_AUTOPSY_PERFORMED, user, M)
return 1

View File

@@ -352,6 +352,14 @@
board_type = new /datum/frame/frame_types/industrial_reagent_pipe
req_components = list( /obj/item/stack/material/glass/reinforced = 1)
/obj/item/circuitboard/industrial_reagent_splitter
name = T_BOARD("industrial chemical splitter")
build_path = /obj/machinery/reagent_refinery/splitter
board_type = new /datum/frame/frame_types/industrial_reagent_splitter
req_components = list(
/obj/item/stack/material/glass/reinforced = 1,
/obj/item/stock_parts/motor = 1)
/obj/item/circuitboard/industrial_reagent_waste_processor
name = T_BOARD("industrial chemical waste processor")
build_path = /obj/machinery/reagent_refinery/waste_processor

View File

@@ -157,6 +157,11 @@
initial_sprite_stack = list("base-stamp-silver", "top-orange", "stamp-n", "pips-gold")
rank = JOB_CHIEF_ENGINEER
/obj/item/card/id/engineering/chemical
name = JOB_ALT_CHEMENGINEER + "'s ID"
initial_sprite_stack = list("base-stamp", "top-orange", "stamp-n", "pips-medblu", "stripe-white")
rank = JOB_ENGINEER
//Science
/obj/item/card/id/science

View File

@@ -121,7 +121,10 @@
if(!proximity) return
..()
if(A && wielded)
if(istype(A,/obj/structure/window))
if(istype(A,/obj/structure/window/maintenance_panel))
var/obj/structure/window/maintenance_panel/P = A
P.take_damage(75,TRUE) // Not instant break, but still useful
else if(istype(A,/obj/structure/window))
var/obj/structure/window/W = A
W.shatter()
else if(istype(A,/obj/structure/grille))

View File

@@ -84,7 +84,9 @@
/obj/item/integrated_electronics/debugger,
/obj/item/shovel/spade,
/obj/item/stack/nanopaste,
/obj/item/geiger
/obj/item/geiger,
/obj/item/reagent_scanner,
/obj/item/lightpainter
)
/obj/item/storage/belt/utility/full
@@ -108,6 +110,16 @@
/obj/item/multitool
)
/obj/item/storage/belt/utility/chemtech
starts_with = list(
/obj/item/tool/screwdriver,
/obj/item/tool/wrench,
/obj/item/weldingtool,
/obj/item/tool/crowbar,
/obj/item/tool/wirecutters,
/obj/item/reagent_scanner
)
/obj/item/storage/belt/utility/atmostech
starts_with = list(
/obj/item/tool/screwdriver,
@@ -220,7 +232,9 @@
/obj/item/stack/material/glass,
/obj/item/lightreplacer,
/obj/item/pickaxe/plasmacutter,
/obj/item/holosign_creator/combifan
/obj/item/holosign_creator/combifan,
/obj/item/reagent_scanner,
/obj/item/lightpainter
)

View File

@@ -47,6 +47,7 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
busy = TRUE
if(do_after(user, rand(4 SECONDS,6 SECONDS), target = src))
SEND_SIGNAL(src,COMSIG_LOOT_REWARD,L,searchedby)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_TRASHPILE_SEARCHED,L,searchedby)
busy = FALSE
else
return ..()

View File

@@ -271,9 +271,31 @@
/obj/structure/simple_door/hardwood/Initialize(mapload,var/material_name)
. = ..(mapload, material_name || MAT_HARDWOOD)
knock_sound = 'sound/machines/door/knock_wood.wav'
/obj/structure/simple_door/sifwood/Initialize(mapload,var/material_name)
. = ..(mapload, material_name || MAT_SIFWOOD)
knock_sound = 'sound/machines/door/knock_wood.wav'
/obj/structure/simple_door/birchwood/Initialize(mapload,var/material_name)
. = ..(mapload, material_name || MAT_BIRCHWOOD)
knock_sound = 'sound/machines/door/knock_wood.wav'
/obj/structure/simple_door/pinewood/Initialize(mapload,var/material_name)
. = ..(mapload, material_name || MAT_PINEWOOD)
knock_sound = 'sound/machines/door/knock_wood.wav'
/obj/structure/simple_door/oakwood/Initialize(mapload,var/material_name)
. = ..(mapload, material_name || MAT_OAKWOOD)
knock_sound = 'sound/machines/door/knock_wood.wav'
/obj/structure/simple_door/acaciawood/Initialize(mapload,var/material_name)
. = ..(mapload, material_name || MAT_ACACIAWOOD)
knock_sound = 'sound/machines/door/knock_wood.wav'
/obj/structure/simple_door/redwood/Initialize(mapload,var/material_name)
. = ..(mapload, material_name || MAT_REDWOOD)
knock_sound = 'sound/machines/door/knock_wood.wav'
/obj/structure/simple_door/resin/Initialize(mapload,var/material_name)
. = ..(mapload, material_name || MAT_RESIN)

View File

@@ -129,6 +129,7 @@
to_chat(user,span_danger("Some sort of creature leaps out of \the [src]!"))
else
SEND_SIGNAL(src,COMSIG_LOOT_REWARD,user,searchedby, 5)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_TRASHPILE_SEARCHED,user,searchedby)
busy = FALSE
else
return ..()

View File

@@ -393,7 +393,7 @@ var/list/flooring_types
/decl/flooring/linoleum
name = "linoleum"
desc = "It's like the 2390's all over again."
desc = "It's like the 2390's all over again." //CHOMPEDIT - Age
icon = 'icons/turf/flooring/linoleum.dmi'
icon_base = "lino"
can_paint = 1
@@ -493,10 +493,30 @@ var/list/flooring_types
/decl/flooring/wood/sif
desc = "Polished wood planks made from sivian wood."
icon = 'icons/turf/flooring/wood.dmi'
icon_base = "sifwood"
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood"
build_type = /obj/item/stack/tile/wood/sif
/decl/flooring/wood/sif/panel
icon_base = "sif_panel"
build_type = /obj/item/stack/tile/wood/sif/panel
/decl/flooring/wood/sif/parquet
icon_base = "wood_parquet"
build_type = /obj/item/stack/tile/wood/sif/parquet
/decl/flooring/wood/sif/tile
icon_base = "wood_tile"
build_type = /obj/item/stack/tile/wood/sif/tile
/decl/flooring/wood/sif/vert
icon_base = "wood_vert"
build_type = /obj/item/stack/tile/wood/sif/vert
/decl/flooring/wood/sif/vert_panel
icon_base = "wood_vert_panel"
build_type = /obj/item/stack/tile/wood/sif/vert_panel
/decl/flooring/wood/alt
icon = 'icons/turf/flooring/wood.dmi'
icon_base = "wood"
@@ -504,24 +524,303 @@ var/list/flooring_types
/decl/flooring/wood/alt/panel
desc = "Polished wooden panels."
icon = 'icons/turf/flooring/wood.dmi'
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/panel
/decl/flooring/wood/alt/parquet
desc = "Polished wooden tiles."
icon = 'icons/turf/flooring/wood.dmi'
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_parquet"
build_type = /obj/item/stack/tile/wood/parquet
/decl/flooring/wood/alt/vert
desc = "Polished wooden planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert"
build_type = /obj/item/stack/tile/wood/vert
/decl/flooring/wood/alt/vert_panel
desc = "Polished wooden panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert_panel"
build_type = /obj/item/stack/tile/wood/vert_panel
/decl/flooring/wood/alt/tile
desc = "Polished wooden tiles."
icon = 'icons/turf/flooring/wood.dmi'
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_tile"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/tile
//New Wood
/decl/flooring/wood/acacia
name = "wooden floor"
desc = "Polished acacia planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood"
has_damage_range = 6
damage_temperature = T0C+200
descriptor = "planks"
build_type = /obj/item/stack/tile/wood/acacia
flags = TURF_CAN_BREAK | TURF_REMOVE_CROWBAR | TURF_REMOVE_SCREWDRIVER
/decl/flooring/wood/acacia/panel
desc = "Polished acacia panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/acacia/panel
/decl/flooring/wood/acacia/parquet
desc = "Polished acacia parquet."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_parquet"
build_type = /obj/item/stack/tile/wood/acacia/parquet
/decl/flooring/wood/acacia/tile
desc = "Polished acacia tiles."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_tile"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/acacia/tile
/decl/flooring/wood/acacia/vert
desc = "Polished acacia planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert"
build_type = /obj/item/stack/tile/wood/acacia/vert
/decl/flooring/wood/acacia/vert_panel
desc = "Polished acacia panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/acacia/vert_panel
/decl/flooring/wood/birch
name = "wooden floor"
desc = "Polished birch planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood"
has_damage_range = 6
damage_temperature = T0C+200
descriptor = "planks"
build_type = /obj/item/stack/tile/wood/birch
flags = TURF_CAN_BREAK | TURF_REMOVE_CROWBAR | TURF_REMOVE_SCREWDRIVER
/decl/flooring/wood/birch/panel
desc = "Polished birch panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/birch/panel
/decl/flooring/wood/birch/parquet
desc = "Polished birch tiles."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_parquet"
build_type = /obj/item/stack/tile/wood/birch/parquet
/decl/flooring/wood/birch/tile
desc = "Polished birch tiles."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_tile"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/birch/tile
/decl/flooring/wood/birch/vert
desc = "Polished birch planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert"
build_type = /obj/item/stack/tile/wood/birch/vert
/decl/flooring/wood/birch/vert_panel
desc = "Polished birch panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/birch/vert_panel
/decl/flooring/wood/hardwood
name = "wooden floor"
desc = "Polished hardwood planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood"
has_damage_range = 6
damage_temperature = T0C+200
descriptor = "planks"
build_type = /obj/item/stack/tile/wood/hardwood
flags = TURF_CAN_BREAK | TURF_REMOVE_CROWBAR | TURF_REMOVE_SCREWDRIVER
/decl/flooring/wood/hardwood/panel
desc = "Polished hardwood panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/hardwood/panel
/decl/flooring/wood/hardwood/parquet
desc = "Polished hardwood tiles."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_parquet"
build_type = /obj/item/stack/tile/wood/hardwood/parquet
/decl/flooring/wood/hardwood/tile
desc = "Polished hardwood tiles."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_tile"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/hardwood/tile
/decl/flooring/wood/hardwood/vert
desc = "Polished hardwood planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert"
build_type = /obj/item/stack/tile/wood/hardwood/vert
/decl/flooring/wood/hardwood/vert_panel
desc = "Polished hardwood panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/hardwood/vert_panel
/decl/flooring/wood/oak
name = "wooden floor"
desc = "Polished oak planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood"
has_damage_range = 6
damage_temperature = T0C+200
descriptor = "planks"
build_type = /obj/item/stack/tile/wood/oak
flags = TURF_CAN_BREAK | TURF_REMOVE_CROWBAR | TURF_REMOVE_SCREWDRIVER
/decl/flooring/wood/oak/panel
desc = "Polished oak panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/oak/panel
/decl/flooring/wood/oak/parquet
desc = "Polished oak tiles."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_parquet"
build_type = /obj/item/stack/tile/wood/oak/parquet
/decl/flooring/wood/oak/tile
desc = "Polished oak tiles."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_tile"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/oak/tile
/decl/flooring/wood/oak/vert
desc = "Polished oak planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert"
build_type = /obj/item/stack/tile/wood/oak/vert
/decl/flooring/wood/oak/vert_panel
desc = "Polished oak panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/oak/vert_panel
/decl/flooring/wood/pine
name = "wooden floor"
desc = "Polished pine planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood"
has_damage_range = 6
damage_temperature = T0C+200
descriptor = "planks"
build_type = /obj/item/stack/tile/wood/pine
flags = TURF_CAN_BREAK | TURF_REMOVE_CROWBAR | TURF_REMOVE_SCREWDRIVER
/decl/flooring/wood/pine/panel
desc = "Polished pine panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/pine/panel
/decl/flooring/wood/pine/parquet
desc = "Polished pine tiles."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_parquet"
build_type = /obj/item/stack/tile/wood/pine/parquet
/decl/flooring/wood/pine/tile
desc = "Polished pine tiles."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_tile"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/pine/tile
/decl/flooring/wood/pine/vert
desc = "Polished pine planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert"
build_type = /obj/item/stack/tile/wood/pine/vert
/decl/flooring/wood/pine/vert_panel
desc = "Polished pine panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/pine/vert_panel
/decl/flooring/wood/redwood
name = "wooden floor"
desc = "Polished redwood planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood"
has_damage_range = 6
damage_temperature = T0C+200
descriptor = "planks"
build_type = /obj/item/stack/tile/wood/redwood
flags = TURF_CAN_BREAK | TURF_REMOVE_CROWBAR | TURF_REMOVE_SCREWDRIVER
/decl/flooring/wood/redwood/panel
desc = "Polished redwood panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/redwood/panel
/decl/flooring/wood/redwood/parquet
desc = "Polished redwood tiles."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_parquet"
build_type = /obj/item/stack/tile/wood/redwood/parquet
/decl/flooring/wood/redwood/tile
desc = "Polished redwood tiles."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_tile"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/redwood/tile
/decl/flooring/wood/redwood/vert
desc = "Polished redwood planks."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert"
build_type = /obj/item/stack/tile/wood/redwood/vert
/decl/flooring/wood/redwood/vert_panel
desc = "Polished redwood panels."
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_base = "wood_vert_panel"
has_damage_range = 2
build_type = /obj/item/stack/tile/wood/redwood/vert_panel
// no more wood
/decl/flooring/reinforced
name = "reinforced floor"
desc = "Heavily reinforced with steel rods."

View File

@@ -127,8 +127,10 @@
/turf/simulated/floor/wood/sif
name = "alien wooden floor"
icon_state = "sifwood"
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood"
initial_flooring = /decl/flooring/wood/sif
color = "#293c50"
/turf/simulated/floor/wood/sif/broken
icon_state = "sifwood-broken0" // This gets changed when spawned.
@@ -137,9 +139,30 @@
. = ..()
break_tile()
/turf/simulated/floor/wood/sif/tile
icon_state = "wood_tile"
initial_flooring = /decl/flooring/wood/sif/tile
/turf/simulated/floor/wood/sif/panel
icon_state = "wood_panel"
initial_flooring = /decl/flooring/wood/sif/panel
/turf/simulated/floor/wood/sif/parquet
icon_state = "wood_parquet"
initial_flooring = /decl/flooring/wood/sif/parquet
/turf/simulated/floor/wood/sif/vert
icon_state = "wood_vert"
initial_flooring = /decl/flooring/wood/sif/vert
/turf/simulated/floor/wood/sif/vert_panel
icon_state = "wood_vert_panel"
initial_flooring = /decl/flooring/wood/sif/vert_panel
/turf/simulated/floor/wood/alt
icon = 'icons/turf/flooring/wood.dmi'
icon = 'icons/turf/flooring/wood_greyscale.dmi'
initial_flooring = /decl/flooring/wood/alt
color = "#593c1c"
/turf/simulated/floor/wood/alt/broken
icon_state = "wood-broken0" // This gets changed when spawned.
@@ -181,6 +204,14 @@
. = ..()
break_tile()
/turf/simulated/floor/wood/alt/vert
icon_state = "wood_vert"
initial_flooring = /decl/flooring/wood/alt/vert
/turf/simulated/floor/wood/alt/vert_panel
icon_state = "wood_vert_panel"
initial_flooring = /decl/flooring/wood/alt/vert_panel
/turf/simulated/floor/grass
name = "grass patch"
icon = 'icons/turf/flooring/grass.dmi'
@@ -555,3 +586,197 @@
icon = 'icons/turf/concrete.dmi'
icon_state = "concrete"
initial_flooring = /decl/flooring/concrete
//New Wood
/turf/simulated/floor/wood/acacia
name = "acacia wood floor"
icon = 'icons/turf/flooring/wood_greyscale.dmi'
color = "#b75e12"
icon_state = "wood"
initial_flooring = /decl/flooring/wood/acacia
/turf/simulated/floor/wood/acacia/tile
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_tile"
initial_flooring = /decl/flooring/wood/acacia/tile
/turf/simulated/floor/wood/acacia/panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_panel"
initial_flooring = /decl/flooring/wood/acacia/panel
/turf/simulated/floor/wood/acacia/parquet
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_parquet"
initial_flooring = /decl/flooring/wood/acacia/parquet
/turf/simulated/floor/wood/acacia/vert
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert"
initial_flooring = /decl/flooring/wood/acacia/vert
/turf/simulated/floor/wood/acacia/vert_panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert_panel"
initial_flooring = /decl/flooring/wood/acacia/vert_panel
/turf/simulated/floor/wood/birch
name = "birch wood floor"
icon = 'icons/turf/flooring/wood_greyscale.dmi'
color = "#f6dec0"
icon_state = "wood"
initial_flooring = /decl/flooring/wood/birch
/turf/simulated/floor/wood/birch/tile
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_tile"
initial_flooring = /decl/flooring/wood/birch/tile
/turf/simulated/floor/wood/birch/panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_panel"
initial_flooring = /decl/flooring/wood/birch/panel
/turf/simulated/floor/wood/birch/parquet
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_parquet"
initial_flooring = /decl/flooring/wood/birch/parquet
/turf/simulated/floor/wood/birch/vert
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert"
initial_flooring = /decl/flooring/wood/birch/vert
/turf/simulated/floor/wood/birch/vert_panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert_panel"
initial_flooring = /decl/flooring/wood/birch/vert_panel
/turf/simulated/floor/wood/hardwood
name = "hardwood wood floor"
icon = 'icons/turf/flooring/wood_greyscale.dmi'
color = "#42291a"
icon_state = "wood"
initial_flooring = /decl/flooring/wood/hardwood
/turf/simulated/floor/wood/hardwood/tile
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_tile"
initial_flooring = /decl/flooring/wood/hardwood/tile
/turf/simulated/floor/wood/hardwood/panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_panel"
initial_flooring = /decl/flooring/wood/hardwood/panel
/turf/simulated/floor/wood/hardwood/parquet
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_parquet"
initial_flooring = /decl/flooring/wood/hardwood/parquet
/turf/simulated/floor/wood/hardwood/vert
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert"
initial_flooring = /decl/flooring/wood/hardwood/vert
/turf/simulated/floor/wood/hardwood/vert_panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert_panel"
initial_flooring = /decl/flooring/wood/hardwood/vert_panel
/turf/simulated/floor/wood/oak
name = "oak wood floor"
icon = 'icons/turf/flooring/wood_greyscale.dmi'
color = "#674928"
icon_state = "wood"
initial_flooring = /decl/flooring/wood/oak
/turf/simulated/floor/wood/oak/tile
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_tile"
initial_flooring = /decl/flooring/wood/oak/tile
/turf/simulated/floor/wood/oak/panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_panel"
initial_flooring = /decl/flooring/wood/oak/panel
/turf/simulated/floor/wood/oak/parquet
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_parquet"
initial_flooring = /decl/flooring/wood/oak/parquet
/turf/simulated/floor/wood/oak/vert
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert"
initial_flooring = /decl/flooring/wood/oak/vert
/turf/simulated/floor/wood/oak/vert_panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert_panel"
initial_flooring = /decl/flooring/wood/oak/vert_panel
/turf/simulated/floor/wood/pine
name = "pine wood floor"
icon = 'icons/turf/flooring/wood_greyscale.dmi'
color = "#cd9d6f"
icon_state = "wood"
initial_flooring = /decl/flooring/wood/pine
/turf/simulated/floor/wood/pine/tile
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_tile"
initial_flooring = /decl/flooring/wood/pine/tile
/turf/simulated/floor/wood/pine/panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_panel"
initial_flooring = /decl/flooring/wood/pine/panel
/turf/simulated/floor/wood/pine/parquet
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_parquet"
initial_flooring = /decl/flooring/wood/pine/parquet
/turf/simulated/floor/wood/pine/vert
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert"
initial_flooring = /decl/flooring/wood/pine/vert
/turf/simulated/floor/wood/pine/vert_panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert_panel"
initial_flooring = /decl/flooring/wood/pine/vert_panel
/turf/simulated/floor/wood/redwood
name = "redwood wood floor"
icon = 'icons/turf/flooring/wood_greyscale.dmi'
color = "#a45a52"
icon_state = "wood"
initial_flooring = /decl/flooring/wood/redwood
/turf/simulated/floor/wood/redwood/tile
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_tile"
initial_flooring = /decl/flooring/wood/redwood/tile
/turf/simulated/floor/wood/redwood/panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_panel"
initial_flooring = /decl/flooring/wood/redwood/panel
/turf/simulated/floor/wood/redwood/parquet
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_parquet"
initial_flooring = /decl/flooring/wood/redwood/parquet
/turf/simulated/floor/wood/redwood/vert
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert"
initial_flooring = /decl/flooring/wood/redwood/vert
/turf/simulated/floor/wood/redwood/vert_panel
icon = 'icons/turf/flooring/wood_greyscale.dmi'
icon_state = "wood_vert_panel"
initial_flooring = /decl/flooring/wood/redwood/vert_panel

View File

@@ -71,6 +71,7 @@
desc = base_desc
icon = base_icon
icon_state = base_icon_state
color = null
if(!is_plating()) // Flooring -> Plating
swap_decals()

View File

@@ -77,6 +77,8 @@
S.use(1)
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
ChangeTurf(/turf/simulated/floor, preserve_outdoors = TRUE)
if(S.color)
color = S.color
return
else if(istype(C, /obj/item))
try_deconstruct_tile(C, user)
@@ -119,6 +121,8 @@
return
if(S.use(use_flooring.build_cost))
set_flooring(use_flooring)
if(S.color)
color = S.color
playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
return
// Plating repairs and removal

View File

@@ -299,3 +299,57 @@
/turf/simulated/shuttle/floor/voidcraft/external/dark
/turf/simulated/shuttle/floor/voidcraft/external/light
/turf/simulated/floor/tiled/material
icon = 'icons/turf/floors.dmi'
/decl/flooring/tiling/material
name = "material floor"
icon_base = "steel"
icon = 'icons/turf/floors.dmi'
flags = TURF_REMOVE_CROWBAR | TURF_CAN_BREAK
/turf/simulated/floor/tiled/material/uranium
icon_state = "uranium"
initial_flooring = /decl/flooring/tiling/material/uranium
/decl/flooring/tiling/material/uranium
name = "uranium floor"
icon_base = "uranium"
build_type = /obj/item/stack/tile/floor/uranium
/turf/simulated/floor/tiled/material/phoron
icon_state = "phoron"
initial_flooring = /decl/flooring/tiling/material/phoron
/decl/flooring/tiling/material/phoron
name = "phoron floor"
icon_base = "phoron"
build_type = /obj/item/stack/tile/floor/phoron
/turf/simulated/floor/tiled/material/gold
icon_state = "gold"
initial_flooring = /decl/flooring/tiling/material/gold
/decl/flooring/tiling/material/gold
name = "gold floor"
icon_base = "gold"
build_type = /obj/item/stack/tile/floor/gold
/turf/simulated/floor/tiled/material/silver
icon_state = "silver"
initial_flooring = /decl/flooring/tiling/material/silver
/decl/flooring/tiling/material/silver
name = "silver floor"
icon_base = "silver"
build_type = /obj/item/stack/tile/floor/silver
/turf/simulated/floor/tiled/material/diamond
icon_state = "diamond"
initial_flooring = /decl/flooring/tiling/material/diamond
/decl/flooring/tiling/material/diamond
name = "diamond floor"
icon_base = "diamond"
build_type = /obj/item/stack/tile/floor/diamond

View File

@@ -65,7 +65,7 @@
/turf/simulated/floor/outdoors/snow/sif/planetuse/attackby(var/obj/item/W, var/mob/user)
if(istype(W, /obj/item/shovel))
to_chat(user, span_notice("You begin to remove \the [src] with your [W]."))
if(do_after(user, 4 SECONDS * W.toolspeed))
if(do_after(user, 4 SECONDS * W.toolspeed, src))
to_chat(user, span_notice("\The [src] has been dug up, and now lies in a pile nearby."))
new /obj/item/stack/material/snow(src)
demote()
@@ -76,7 +76,7 @@
/turf/simulated/floor/outdoors/snow/sif/planetuse/attack_hand(mob/user as mob)
visible_message("[user] starts scooping up some snow.", "You start scooping up some snow.")
if(do_after(user, 1 SECOND))
if(do_after(user, 1 SECOND, src))
var/obj/S = new /obj/item/stack/material/snow(user.loc)
user.put_in_hands(S)
visible_message("[user] scoops up a pile of snow.", "You scoop up a pile of snow.")

View File

@@ -123,6 +123,21 @@
. = ..(mapload, MAT_SIFWOOD, MAT_SIFWOOD, MAT_SIFWOOD)
// CHOMPEdit End
/turf/simulated/wall/birchwood/Initialize(mapload)
. = ..(mapload, MAT_BIRCHWOOD)
/turf/simulated/wall/pinewood/Initialize(mapload)
. = ..(mapload, MAT_PINEWOOD)
/turf/simulated/wall/oakwood/Initialize(mapload)
. = ..(mapload, MAT_OAKWOOD)
/turf/simulated/wall/acaciawood/Initialize(mapload)
. = ..(mapload, MAT_ACACIAWOOD)
/turf/simulated/wall/redwood/Initialize(mapload)
. = ..(mapload, MAT_REDWOOD)
/turf/simulated/wall/log/Initialize(mapload)
. = ..(mapload, MAT_LOG)

View File

@@ -230,6 +230,30 @@ var/list/flesh_overlay_cache = list()
icon_state = "wood"
icon = 'icons/turf/wall_masks_vr.dmi'
/turf/simulated/wall/acaciawood
icon_state = "acaciawood"
icon = 'icons/turf/wall_masks_vr.dmi'
/turf/simulated/wall/birchwood
icon_state = "birchwood"
icon = 'icons/turf/wall_masks_vr.dmi'
/turf/simulated/wall/hardwood
icon_state = "hardwood"
icon = 'icons/turf/wall_masks_vr.dmi'
/turf/simulated/wall/oakwood
icon_state = "oakwood"
icon = 'icons/turf/wall_masks_vr.dmi'
/turf/simulated/wall/pinewood
icon_state = "pinewood"
icon = 'icons/turf/wall_masks_vr.dmi'
/turf/simulated/wall/redwood
icon_state = "redwood"
icon = 'icons/turf/wall_masks_vr.dmi'
/turf/simulated/wall/stonebricks
icon_state = "stonebrick"
icon = 'icons/turf/wall_masks_vr.dmi'

View File

@@ -520,6 +520,8 @@
if(istype(src, /turf/simulated))
var/turf/simulated/T = src
if(T.dirt > 0)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_WASHED_FLOOR)
T.dirt = 0
for(var/am in src)

View File

@@ -1016,7 +1016,7 @@ var/datum/announcement/minor/admin_min_announcer = new
set desc="Delay the game start/end"
set name="Delay"
if(!check_rights(R_SERVER|R_EVENT)) return
if(!check_rights(R_SERVER|R_EVENT|R_ADMIN|R_MOD)) return
if (SSticker.current_state >= GAME_STATE_PLAYING)
// Tell the ticker to delay/resume
SSticker.toggle_delay()

View File

@@ -7,38 +7,38 @@
feedback_add_details("admin_verb","CP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
if(tgui_alert(usr, "WARNING: This command should not be run on a live server. Do you want to continue?", "Check Piping", list("No", "Yes")) != "Yes")
if(tgui_alert(src, "WARNING: This command should not be run on a live server. Do you want to continue?", "Check Piping", list("No", "Yes")) != "Yes")
return
to_chat(usr, "Checking for disconnected pipes...")
to_chat(src, "Checking for disconnected pipes...")
//all plumbing - yes, some things might get stated twice, doesn't matter.
for (var/obj/machinery/atmospherics/plumbing in GLOB.machines)
if (plumbing.nodealert)
to_chat(usr, span_filter_adminlog(span_warning("Unconnected [plumbing.name] located at [plumbing.x],[plumbing.y],[plumbing.z] ([get_area(plumbing.loc)])")))
to_chat(src, span_filter_adminlog(span_warning("Unconnected [plumbing.name] located at [plumbing.x],[plumbing.y],[plumbing.z] ([get_area(plumbing.loc)])")))
//Manifolds
for (var/obj/machinery/atmospherics/pipe/manifold/pipe in GLOB.machines)
if (!pipe.node1 || !pipe.node2 || !pipe.node3)
to_chat(usr, span_filter_adminlog(span_warning("Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")))
to_chat(src, span_filter_adminlog(span_warning("Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")))
//Pipes
for (var/obj/machinery/atmospherics/pipe/simple/pipe in GLOB.machines)
if (!pipe.node1 || !pipe.node2)
to_chat(usr, span_filter_adminlog(span_warning("Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")))
to_chat(src, span_filter_adminlog(span_warning("Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")))
to_chat(usr, "Checking for overlapping pipes...")
to_chat(src, "Checking for overlapping pipes...")
next_turf:
for(var/turf/T in world)
for(var/dir in GLOB.cardinal)
var/list/connect_types = list(1 = 0, 2 = 0, 3 = 0)
var/alist/connect_types = alist(1 = 0, 2 = 0, 3 = 0)
for(var/obj/machinery/atmospherics/pipe in T)
if(dir & pipe.initialize_directions)
for(var/connect_type in pipe.connect_types)
connect_types[connect_type] += 1
if(connect_types[1] > 1 || connect_types[2] > 1 || connect_types[3] > 1)
to_chat(usr, span_filter_adminlog(span_warning("Overlapping pipe ([pipe.name]) located at [T.x],[T.y],[T.z] ([get_area(T)])")))
to_chat(src, span_filter_adminlog(span_warning("Overlapping pipe ([pipe.name]) located at [T.x],[T.y],[T.z] ([get_area(T)])")))
continue next_turf
to_chat(usr, "Done")
to_chat(src, "Done")
/client/proc/powerdebug()
set category = "Mapping"

View File

@@ -782,3 +782,8 @@ ADMIN_VERB(quick_nif, R_ADMIN, "Quick NIF", "Spawns a NIF into someone in quick-
log_and_message_admins("Quick NIF'd [H.real_name] with a [input_NIF].", user)
feedback_add_details("admin_verb","QNIF") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
ADMIN_VERB(reload_configuration, R_DEBUG, "Reload Configuration", "Reloads the configuration from the default path on the disk, wiping any in-round modifications.", ADMIN_CATEGORY_DEBUG)
if(tgui_alert(user, "Are you absolutely sure you want to reload the configuration from the default path on the disk, wiping any in-round modifications?", "Really reset?", list("No", "Yes")) != "Yes")
return
config.admin_reload()

View File

@@ -269,6 +269,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
if (CONFIG_GET(flag/chatlog_database_backend))
chatlog_token = vchatlog_generate_token(ckey, GLOB.round_id)
winset(src, null, list("browser-options" = "find,refresh"))
// Instantiate stat panel
stat_panel = new(src, "statbrowser")
stat_panel.subscribe(src, PROC_REF(on_stat_panel_message))

View File

@@ -137,6 +137,7 @@
/obj/item/forensics/sample_kit/proc/take_sample(var/mob/user, var/atom/supplied)
var/obj/item/sample/S = new evidence_path(get_turf(user), supplied)
to_chat(user, span_notice("You transfer [S.evidence.len] [S.evidence.len > 1 ? "[evidence_type]s" : "[evidence_type]"] to \the [S]."))
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_FORENSICS_COLLECTED, supplied, user)
/obj/item/forensics/sample_kit/afterattack(var/atom/A, var/mob/user, var/proximity)
if(!proximity)

View File

@@ -114,6 +114,7 @@
if(sample_type)
user.visible_message("\The [user] swabs \the [A] for a sample.", "You swab \the [A] for a sample.")
set_used(sample_type, A)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_FORENSICS_COLLECTED, A, user)
/obj/item/forensics/swab/proc/set_used(var/sample_str, var/atom/source)
name = "[initial(name)] ([sample_str] - [source])"

View File

@@ -147,6 +147,7 @@
do_extra(user, target)
do_sound(user)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_EMOTE_PERFORMED, user, extra_params)
/decl/emote/proc/replace_target_tokens(var/msg, var/atom/target)
. = msg

View File

@@ -284,7 +284,7 @@
return 0
for(var/datum/medical_issue/MI in affected.medical_issues)
if(MI.cure_surgery == "bone reinforcement")
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= FLESH_RETRACTED
return 0
/datum/surgery_step/medical_issue/strengthen_bone/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -325,7 +325,7 @@
return 0
for(var/datum/medical_issue/MI in affected.medical_issues)
if(MI.cure_surgery == "remove growths")
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= FLESH_RETRACTED
return 0
/datum/surgery_step/medical_issue/remove_growth/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -366,7 +366,7 @@
return 0
for(var/datum/medical_issue/MI in affected.medical_issues)
if(MI.cure_surgery == "redirect blood vessels")
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= FLESH_RETRACTED
return 0
/datum/surgery_step/medical_issue/redirect_vessels/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -407,7 +407,7 @@
return 0
for(var/datum/medical_issue/MI in affected.medical_issues)
if(MI.cure_surgery == "extract object")
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= FLESH_RETRACTED
return 0
/datum/surgery_step/medical_issue/extract_object/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -448,7 +448,7 @@
return 0
for(var/datum/medical_issue/MI in affected.medical_issues)
if(MI.cure_surgery == "flesh graft")
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= FLESH_RETRACTED
return 0
/datum/surgery_step/medical_issue/flesh_graft/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -492,7 +492,7 @@
for(var/obj/item/organ/internal/I in affected.internal_organs)
for(var/datum/medical_issue/MI in I.medical_issues)
if(MI.cure_surgery == "remove growths")
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= FLESH_RETRACTED
return 0
/datum/surgery_step/medical_issue/remove_growth_internal/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -535,7 +535,7 @@
for(var/obj/item/organ/internal/I in affected.internal_organs)
for(var/datum/medical_issue/MI in I.medical_issues)
if(MI.cure_surgery == "redirect blood vessels")
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= FLESH_RETRACTED
return 0
/datum/surgery_step/medical_issue/redirect_vessels_internal/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -578,7 +578,7 @@
for(var/obj/item/organ/internal/I in affected.internal_organs)
for(var/datum/medical_issue/MI in I.medical_issues)
if(MI.cure_surgery == "close holes")
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= FLESH_RETRACTED
return 0
/datum/surgery_step/medical_issue/close_holes/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -621,7 +621,7 @@
for(var/obj/item/organ/internal/I in affected.internal_organs)
for(var/datum/medical_issue/MI in I.medical_issues)
if(MI.cure_surgery == "ultrasound")
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= FLESH_RETRACTED
return 0
/datum/surgery_step/medical_issue/ultrasound/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
@@ -664,7 +664,7 @@
for(var/obj/item/organ/internal/I in affected.internal_organs)
for(var/datum/medical_issue/MI in I.medical_issues)
if(MI.cure_surgery == "reoxygenate tissue")
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2
return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= FLESH_RETRACTED
return 0
/datum/surgery_step/medical_issue/reoxygenate_tissue/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)

View File

@@ -270,6 +270,8 @@
result_obj.reagents.trans_to(holder, result_obj.reagents.total_volume)
tally++
if(results.len)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_FOOD_PREPARED, container, results)
switch(reagent_mix)
if (RECIPE_REAGENT_REPLACE)

View File

@@ -105,13 +105,13 @@ a creative player the means to solve many problems. Circuits are held inside an
var/list/outputs_list = list()
var/list/activators_list = list()
for(var/datum/integrated_io/io in inputs)
inputs_list.Add(list(tgui_pin_data(io)))
UNTYPED_LIST_ADD(inputs_list, tgui_pin_data(io))
for(var/datum/integrated_io/io in outputs)
outputs_list.Add(list(tgui_pin_data(io)))
UNTYPED_LIST_ADD(outputs_list, tgui_pin_data(io))
for(var/datum/integrated_io/io in activators)
activators_list.Add(list(tgui_pin_data(io)))
UNTYPED_LIST_ADD(activators_list, tgui_pin_data(io))
data["inputs"] = inputs_list
data["outputs"] = outputs_list
@@ -130,12 +130,12 @@ a creative player the means to solve many problems. Circuits are held inside an
pindata["ref"] = REF(io)
var/list/linked_list = list()
for(var/datum/integrated_io/linked in io.linked)
linked_list.Add(list(list(
UNTYPED_LIST_ADD(linked_list, list(
"ref" = REF(linked),
"name" = linked.name,
"holder_ref" = REF(linked.holder),
"holder_name" = linked.holder.displayed_name,
)))
))
pindata["linked"] = linked_list
return pindata

View File

@@ -53,10 +53,9 @@
playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3)
var/datum/effect/effect/system/smoke_spread/chem/smoke_system = new()
smoke_system.set_up(reagents, 10, 0, get_turf(src))
spawn(0)
for(var/i = 1 to 8)
smoke_system.start()
reagents.clear_reagents()
for(var/i = 1 to 8)
smoke_system.start()
reagents.clear_reagents()
activate_pin(2)
/obj/item/integrated_circuit/reagent/injector

View File

@@ -9,6 +9,17 @@
per_round_cap = 3 //limited supply!
vendor_category = MAINTVENDOR_CONSTRUCTION
/datum/maint_recycler_vendor_entry/DIY_SifWood
name = "SIF WOOD???"
desc = "Seeing this stuff for the first time BLUE our minds, but not your wallets!!"
object_type_to_spawn = /obj/item/stack/material/wood/sif{amount = 20}
item_cost = 15 //not too pricy
tagline = "the trees are speaking 👽"
ad_message = "SIF! WOOD! WIF! WOOD!"
per_person_cap = 1
per_round_cap = 3 //limited supply!
vendor_category = MAINTVENDOR_CONSTRUCTION
/datum/maint_recycler_vendor_entry/DIY_HardWood //this one writes itself
name = "Hard... Knotty Wood... "
desc = "Seriously! this tree sucked! unsuitable for professional construction due to how hard the knots are, the savings (and various aches and pains) are passed onto YOU!!!"
@@ -20,6 +31,55 @@
per_round_cap = 3 //limited supply!
object_type_to_spawn = /obj/item/stack/material/wood/hard{amount = 20}
/datum/maint_recycler_vendor_entry/DIY_AcaciaWood //this one writes itself
name = "Acacia? I 'ardly Know 'er!"
desc = "Seriously! this tree sucked! unsuitable for professional construction due to how hard the knots are, the savings (and various aches and pains) are passed onto YOU!!!"
tagline = "Tree for the price of one!!!"
ad_message = "owo"
vendor_category = MAINTVENDOR_CONSTRUCTION
per_person_cap = 1
per_round_cap = 3 //limited supply!
object_type_to_spawn = /obj/item/stack/material/wood/acacia{amount = 20}
/datum/maint_recycler_vendor_entry/DIY_BirchWood //this one writes itself
name = "Hot Birches In Your Area!!"
desc = "99 Problems But A Birch Ain't One!"
tagline = "BIRCHES! IN! HEAT!"
ad_message = "🤤"
vendor_category = MAINTVENDOR_CONSTRUCTION
per_person_cap = 1
per_round_cap = 3 //limited supply!
object_type_to_spawn = /obj/item/stack/material/wood/birch{amount = 20}
/datum/maint_recycler_vendor_entry/DIY_OakWood
name = "Oak-y, Pal"
desc = "No ACORN-y jokes here, just gen-u-ine oak wood! That's it. Promise."
tagline = "Sure thing bud"
ad_message = "🤤"
vendor_category = MAINTVENDOR_CONSTRUCTION
per_person_cap = 1
per_round_cap = 3 //limited supply!
object_type_to_spawn = /obj/item/stack/material/wood/oak{amount = 20}
/datum/maint_recycler_vendor_entry/DIY_PineWood
name = "Pine For The Fjords..."
desc = "Smells like home. And also those little air freshener thingies you put in your car. Do people still have cars?"
tagline = "Enjoy the needles"
ad_message = "🌲"
vendor_category = MAINTVENDOR_CONSTRUCTION
per_person_cap = 1
per_round_cap = 3 //limited supply!
object_type_to_spawn = /obj/item/stack/material/wood/pine{amount = 20}
/datum/maint_recycler_vendor_entry/DIY_RedWood //this one writes itself
name = "REDWOOD? I SURE HAVE!"
desc = "This stuff is way too expensive to be in here, but we won't tell anyone if you don't!"
tagline = "REDRUM! Wait, no, don't."
ad_message = "waow"
vendor_category = MAINTVENDOR_CONSTRUCTION
per_person_cap = 1
per_round_cap = 3 //limited supply!
object_type_to_spawn = /obj/item/stack/material/wood/redwood{amount = 20}
/datum/maint_recycler_vendor_entry/cardboard
vendor_category = MAINTVENDOR_CONSTRUCTION

View File

@@ -0,0 +1,88 @@
/obj/structure/window/maintenance_panel
name = "maintenance panel"
desc = "A maintenance panel. It covers important things hidden inside the wall."
description_info = "Can be cut through or repaired with a welder. Can be deconstructed with a wrench once detached."
icon = 'icons/obj/maintenance_panel.dmi'
icon_state = "panel"
basestate = "panel"
maxhealth = 350
glasstype = /obj/item/stack/tile/maintenance_panel // Yes these are technically windows, drops into their panel on deconstruct and shatter
maximal_heat = /datum/material/steel::melting_point
force_threshold = 5
shardtype = null
opacity = 1 // Difficult to see past
/obj/structure/window/maintenance_panel/apply_silicate(var/amount)
return // can't fix it like that
/obj/structure/window/maintenance_panel/updateSilicate()
return // can't fix it like that
/obj/structure/window/maintenance_panel/attack_ghost(mob/observer/dead/user as mob)
return // Too powerful for ghosts
/obj/structure/window/maintenance_panel/is_fulltile()
return FALSE // NEVER
/obj/structure/window/maintenance_panel/attackby(obj/item/W, mob/user)
if(W.has_tool_quality(TOOL_SCREWDRIVER))
return // Cannot be screwed down
if(istype(W, /obj/item/stack/cable_coil))
return // Cannot be electrochromed
if(W.has_tool_quality(TOOL_WELDER) && (user.a_intent != I_HELP || health == maxhealth)) // If at max health or not on help
var/obj/item/weldingtool/WT = W.get_welder()
if(WT.remove_fuel(1, user))
to_chat(user, span_warning("You begin to [!anchored ? "weld" : "cut"] the [src] [!anchored ? "to" : "off"] the wall."))
playsound(src, W.usesound, 75, 1)
if(do_after(user, 2 SECONDS, target = src))
anchored = !anchored
update_nearby_tiles(need_rebuild = 1)
update_nearby_icons()
update_verbs()
to_chat(user, span_info("You [anchored ? "weld" : "cut"] the [src] [anchored ? "to" : "off"] the wall."))
return
. = ..()
/obj/structure/window/maintenance_panel/take_damage(var/damage = 0, var/sound_effect = 1)
var/initialhealth = health
health = max(0, health - damage)
if(health <= 0)
shatter()
return
if(sound_effect)
if(damage < 30)
playsound(src, 'sound/effects/Glasshit.ogg', 100, 1)
else
playsound(src, 'sound/effects/grillehit.ogg', 75, 1)
if(health < maxhealth / 4 && initialhealth >= maxhealth / 4)
visible_message("\the [src] is about to break free!")
update_icon()
else if(health < maxhealth / 2 && initialhealth >= maxhealth / 2)
visible_message("\the [src] looks seriously damaged!")
update_icon()
else if(health < maxhealth * 3/4 && initialhealth >= maxhealth * 3/4)
visible_message("\the [src] looks like it's taking damage!")
update_icon()
/obj/structure/window/maintenance_panel/shatter(var/display_message = 1)
playsound(src, pick(list('sound/effects/metalscrape1.ogg','sound/effects/metalscrape2.ogg','sound/effects/metalscrape3.ogg')), 70, 1)
if(display_message)
visible_message("\the [src] thunks free of the wall!")
new glasstype(loc)
qdel(src)
/obj/structure/window/maintenance_panel/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature <= maximal_heat)
return
var/burndamage = log(RAND_F(0.9, 1.1) * (exposed_temperature - maximal_heat))
if(burndamage)
take_damage(burndamage)
/obj/structure/window/maintenance_panel/examine(mob/user)
. = ..()
if(anchored)
. += span_notice("It's welded firmly in place.")
else
. += span_warning("It's hanging freely, and hasn't been welded in place! It can be deconstructed with a wrench.")

View File

@@ -0,0 +1,70 @@
// Maintenance panel sheets
/obj/item/stack/tile/maintenance_panel
name = "maintenance panel"
desc = "A maintenance panel"
singular_name = "panel"
icon_state = "maintpanel"
force = 6.0
matter = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT / 4)
throwforce = 15.0
throw_speed = 5
throw_range = 20
can_weld = TRUE
no_variants = FALSE
/obj/item/stack/tile/maintenance_panel/attack_self(var/mob/user)
var/turf/T = user.loc
if(!user || (loc != user && !isrobot(user)) || user.stat || user.loc != T)
return FALSE
if(!user.IsAdvancedToolUser())
to_chat(user, span_warning("This task is too complex for your clumsy hands."))
return TRUE
// Get data for building windows here.
var/list/possible_directions = GLOB.cardinal.Copy()
var/window_count = 0
for (var/obj/structure/window/check_window in user.loc)
window_count++
possible_directions -= check_window.dir
for (var/obj/structure/windoor_assembly/check_assembly in user.loc)
window_count++
possible_directions -= check_assembly.dir
for (var/obj/machinery/door/window/check_windoor in user.loc)
window_count++
possible_directions -= check_windoor.dir
// Get the closest available dir to the user's current facing.
var/build_dir = SOUTHWEST //Default to southwest for fulltile windows.
var/failed_to_build
if(window_count >= 4)
failed_to_build = 1
else
if(possible_directions.len)
for(var/direction in list(user.dir, turn(user.dir,90), turn(user.dir,270), turn(user.dir,180)))
if(direction in possible_directions)
build_dir = direction
break
else
failed_to_build = 1
if(failed_to_build)
to_chat(user, span_warning("There is no room in this location."))
return TRUE
var/sheets_needed = 1
if(get_amount() < sheets_needed)
to_chat(user, span_warning("You need at least [sheets_needed] sheets to build this."))
return TRUE
if(build_dir == SOUTHWEST)
to_chat(user, span_warning("A maintenance panel cannot be built like that!"))
return TRUE
// Build the structure and update sheet count etc.
use(sheets_needed)
new /obj/structure/window/maintenance_panel(T, build_dir, 1)
return TRUE
// Spawner
/obj/fiftyspawner/maintenance_panel
name = "stack of maintenance panels"
type_to_spawn = /obj/item/stack/tile/maintenance_panel

View File

@@ -104,6 +104,26 @@
name = "stack of hardwood"
type_to_spawn = /obj/item/stack/material/wood/hard
/obj/fiftyspawner/birchwood
name = "stack of birchwood"
type_to_spawn = /obj/item/stack/material/wood/birch
/obj/fiftyspawner/pinewood
name = "stack of pinewood"
type_to_spawn = /obj/item/stack/material/wood/pine
/obj/fiftyspawner/oakwood
name = "stack of oakwood"
type_to_spawn = /obj/item/stack/material/wood/oak
/obj/fiftyspawner/acaciawood
name = "stack of acaciawood"
type_to_spawn = /obj/item/stack/material/wood/acacia
/obj/fiftyspawner/redwood
name = "stack of redwood"
type_to_spawn = /obj/item/stack/material/wood/redwood
/obj/fiftyspawner/log
name = "stack of logs"
type_to_spawn = /obj/item/stack/material/log
@@ -152,7 +172,26 @@
name = "stack of stable glamour"
type_to_spawn = /obj/item/stack/material/glamour
//R-UST port
/obj/fiftyspawner/deuterium
name = "stack of deuterium"
type_to_spawn = /obj/item/stack/material/deuterium
/obj/fiftyspawner/titanium
name = "stack of titanium"
type_to_spawn = /obj/item/stack/material/titanium
/obj/fiftyspawner/titanium_glass
name = "stack of ti-glass"
type_to_spawn = /obj/item/stack/material/glass/titanium
/obj/fiftyspawner/plastitanium
name = "stack of plastitanium"
type_to_spawn = /obj/item/stack/material/plastitanium
/obj/fiftyspawner/plastitanium_hull
name = "stack of plastitanium"
type_to_spawn = /obj/item/stack/material/plastitanium/hull
/obj/fiftyspawner/plastitanium_glass
name = "stack of plastitanium glass"
type_to_spawn = /obj/item/stack/material/glass/plastitanium

View File

@@ -1,19 +0,0 @@
/obj/fiftyspawner/titanium
name = "stack of titanium"
type_to_spawn = /obj/item/stack/material/titanium
/obj/fiftyspawner/titanium_glass
name = "stack of ti-glass"
type_to_spawn = /obj/item/stack/material/glass/titanium
/obj/fiftyspawner/plastitanium
name = "stack of plastitanium"
type_to_spawn = /obj/item/stack/material/plastitanium
/obj/fiftyspawner/plastitanium_hull
name = "stack of plastitanium"
type_to_spawn = /obj/item/stack/material/plastitanium/hull
/obj/fiftyspawner/plastitanium_glass
name = "stack of plastitanium glass"
type_to_spawn = /obj/item/stack/material/glass/plastitanium

View File

@@ -0,0 +1,7 @@
/datum/material/diamond/generate_recipes()
..()
recipes += list(
new /datum/stack_recipe_list("floor tiles", list(
new /datum/stack_recipe("diamond floor tile", /obj/item/stack/tile/floor/diamond, 1, 4, 20, recycle_material = "[name]")
))
)

View File

@@ -0,0 +1,7 @@
/datum/material/gold/generate_recipes()
..()
recipes += list(
new /datum/stack_recipe_list("floor tiles", list(
new /datum/stack_recipe("gold floor tile", /obj/item/stack/tile/floor/gold, 1, 4, 20, recycle_material = "[name]")
))
)

View File

@@ -0,0 +1,7 @@
/datum/material/phoron/generate_recipes()
..()
recipes += list(
new /datum/stack_recipe_list("floor tiles", list(
new /datum/stack_recipe("phoron floor tile", /obj/item/stack/tile/floor/phoron, 1, 4, 20, recycle_material = "[name]")
))
)

View File

@@ -0,0 +1,7 @@
/datum/material/silver/generate_recipes()
..()
recipes += list(
new /datum/stack_recipe_list("floor tiles", list(
new /datum/stack_recipe("silver floor tile", /obj/item/stack/tile/floor/silver, 1, 4, 20, recycle_material = "[name]")
))
)

View File

@@ -80,6 +80,7 @@
new /datum/stack_recipe("closet", /obj/structure/closet, 2, time = 15, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
new /datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"),
new /datum/stack_recipe("cannon frame", /obj/item/cannonframe, 10, time = 15, one_per_turf = 0, on_floor = 0, recycle_material = "[name]"),
new /datum/stack_recipe("maintenance panel", /obj/item/stack/tile/maintenance_panel, 4, 1, 20, recycle_material = "[name]"),
new /datum/stack_recipe_list("floor tiles", list(
new /datum/stack_recipe("regular floor tile", /obj/item/stack/tile/floor, 1, 4, 20, recycle_material = "[name]"),
new /datum/stack_recipe("steel hi-grip tile", /obj/item/stack/tile/floor/steelgrip, 1, 4, 20, recycle_material = "[name]"),

View File

@@ -0,0 +1,7 @@
/datum/material/uranium/generate_recipes()
..()
recipes += list(
new /datum/stack_recipe_list("floor tiles", list(
new /datum/stack_recipe("uranium floor tile", /obj/item/stack/tile/floor/uranium, 1, 4, 20, recycle_material = "[name]")
))
)

View File

@@ -30,7 +30,12 @@
new /datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("wood circlet", /obj/item/clothing/head/woodcirclet, 1, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("clipboard", /obj/item/clipboard, 1, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]"),
new /datum/stack_recipe("large wood floor tile", /obj/item/stack/tile/wood/panel, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]"),
new /datum/stack_recipe("parquet wood floor tile", /obj/item/stack/tile/wood/parquet, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]"),
new /datum/stack_recipe("tiled wood floor tile", /obj/item/stack/tile/wood/tile, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]"),
new /datum/stack_recipe("vertical wood floor tile", /obj/item/stack/tile/wood/vert, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]"),
new /datum/stack_recipe("vertical large wood floor tile", /obj/item/stack/tile/wood/vert_panel, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]"),
new /datum/stack_recipe("wooden chair", /obj/structure/bed/chair/wood, 3, time = 10, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("crossbow frame", /obj/item/crossbowframe, 5, time = 25, one_per_turf = 0, on_floor = 0, pass_stack_color = TRUE, recycle_material = "[name]"),
new /datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1, pass_stack_color = TRUE, recycle_material = "[name]"),
@@ -58,11 +63,31 @@
/datum/material/wood/sif/generate_recipes()
..()
recipes += new /datum/stack_recipe("alien wood floor tile", /obj/item/stack/tile/wood/sif, 1, 4, 20, pass_stack_color = TRUE)
recipes += new /datum/stack_recipe("alien wood floor tile", /obj/item/stack/tile/wood/sif, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("large alien wood floor tile", /obj/item/stack/tile/wood/sif/panel, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("alien wood parquet tile", /obj/item/stack/tile/wood/sif/parquet, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("tiled alien wood floor tile", /obj/item/stack/tile/wood/sif/tile, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("vertical alien wood floor tile", /obj/item/stack/tile/wood/sif/vert, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("vertical large alien wood floor tile", /obj/item/stack/tile/wood/sif/vert_panel, 1, 4, 20, pass_stack_color = FALSE)
for(var/datum/stack_recipe/r_recipe in recipes)
if(r_recipe.title == "wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "parquet wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "tiled wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden chair")
recipes -= r_recipe
continue
@@ -80,11 +105,31 @@
/datum/material/wood/hardwood/generate_recipes()
..()
recipes += new /datum/stack_recipe("parquet wood floor tile", /obj/item/stack/tile/wood/parquet, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("hardwood floor tile", /obj/item/stack/tile/wood/hardwood, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("large hardwood floor tile", /obj/item/stack/tile/wood/hardwood/panel, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("parquet hardwood floor tile", /obj/item/stack/tile/wood/hardwood/parquet, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("tiled hardwood floor tile", /obj/item/stack/tile/wood/hardwood/tile, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("vertical hardwood floor tile", /obj/item/stack/tile/wood/hardwood/vert, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("vertical large hardwood floor tile", /obj/item/stack/tile/wood/hardwood/vert_panel, 1, 4, 20, pass_stack_color = FALSE)
for(var/datum/stack_recipe/r_recipe in recipes)
if(r_recipe.title == "wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "parquet wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "tiled wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden chair")
recipes -= r_recipe
continue
@@ -121,7 +166,6 @@
icon_colour = "#6f432a"
stack_type = /obj/item/stack/material/log/hard
//VOREStation Addition Start
/datum/material/wood/stick
name = "wooden stick"
icon_colour = "#824B28"
@@ -136,4 +180,224 @@
/datum/material/wood/stick/generate_recipes()
return
//VOREStation Addition End
/datum/material/wood/birch
name = MAT_BIRCHWOOD
stack_type = /obj/item/stack/material/wood/birch
icon_colour = "#f6dec0"
icon_base = "wood"
icon_reinf = "reinf_stone"
integrity = 65
hardness = 20
weight = 20
/datum/material/wood/birch/generate_recipes()
..()
recipes += new /datum/stack_recipe("birch floor tile", /obj/item/stack/tile/wood/birch, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("large birch floor tile", /obj/item/stack/tile/wood/birch/panel, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("parquet birch floor tile", /obj/item/stack/tile/wood/birch/parquet, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("tiled birch floor tile", /obj/item/stack/tile/wood/birch/tile, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("vertical birch floor tile", /obj/item/stack/tile/wood/birch/vert, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("vertical large birch floor tile", /obj/item/stack/tile/wood/birch/vert_panel, 1, 4, 20, pass_stack_color = FALSE)
for(var/datum/stack_recipe/r_recipe in recipes)
if(r_recipe.title == "wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "parquet wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "tiled wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden chair")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden standup figure")
recipes -= r_recipe
continue
/datum/material/wood/pine
name = MAT_PINEWOOD
stack_type = /obj/item/stack/material/wood/pine
icon_colour = "#cd9d6f"
icon_base = "wood"
icon_reinf = "reinf_stone"
integrity = 65
hardness = 20
weight = 20
/datum/material/wood/pine/generate_recipes()
..()
recipes += new /datum/stack_recipe("pine floor tile", /obj/item/stack/tile/wood/pine, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("large pine floor tile", /obj/item/stack/tile/wood/pine/panel, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("parquet pine floor tile", /obj/item/stack/tile/wood/pine/parquet, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("tiled pine floor tile", /obj/item/stack/tile/wood/pine/tile, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("vertical pine floor tile", /obj/item/stack/tile/wood/pine/vert, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("vertical large pine floor tile", /obj/item/stack/tile/wood/pine/vert_panel, 1, 4, 20, pass_stack_color = FALSE)
for(var/datum/stack_recipe/r_recipe in recipes)
if(r_recipe.title == "wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "parquet wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "tiled wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden chair")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden standup figure")
recipes -= r_recipe
continue
/datum/material/wood/oak
name = MAT_OAKWOOD
stack_type = /obj/item/stack/material/wood/oak
icon_colour = "#674928"
icon_base = "wood"
icon_reinf = "reinf_stone"
integrity = 65
hardness = 20
weight = 20
/datum/material/wood/oak/generate_recipes()
..()
recipes += new /datum/stack_recipe("oak floor tile", /obj/item/stack/tile/wood/oak, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("large oak floor tile", /obj/item/stack/tile/wood/oak/panel, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("parquet oak floor tile", /obj/item/stack/tile/wood/oak/parquet, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("tiled oak floor tile", /obj/item/stack/tile/wood/oak/tile, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("vertical oak floor tile", /obj/item/stack/tile/wood/oak/vert, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("vertical large oak floor tile", /obj/item/stack/tile/wood/oak/vert_panel, 1, 4, 20, pass_stack_color = FALSE)
for(var/datum/stack_recipe/r_recipe in recipes)
if(r_recipe.title == "wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "parquet wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "tiled wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden chair")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden standup figure")
recipes -= r_recipe
continue
/datum/material/wood/acacia
name = MAT_ACACIAWOOD
stack_type = /obj/item/stack/material/wood/acacia
icon_colour = "#b75e12"
icon_base = "wood"
icon_reinf = "reinf_stone"
integrity = 65
hardness = 20
weight = 20
/datum/material/wood/acacia/generate_recipes()
..()
recipes += new /datum/stack_recipe("acacia floor tile", /obj/item/stack/tile/wood/acacia, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("large acacia floor tile", /obj/item/stack/tile/wood/acacia/panel, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("parquet acacia floor tile", /obj/item/stack/tile/wood/acacia/parquet, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("tiled acacia floor tile", /obj/item/stack/tile/wood/acacia/tile, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("vertical acacia floor tile", /obj/item/stack/tile/wood/acacia/vert, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("vertical large acacia floor tile", /obj/item/stack/tile/wood/acacia/vert_panel, 1, 4, 20, pass_stack_color = FALSE)
for(var/datum/stack_recipe/r_recipe in recipes)
if(r_recipe.title == "wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "parquet wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "tiled wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden chair")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden standup figure")
recipes -= r_recipe
continue
/datum/material/wood/redwood
name = MAT_REDWOOD
stack_type = /obj/item/stack/material/wood/redwood
icon_colour = "#a45a52"
icon_base = "wood"
table_icon_base = "stone"
icon_reinf = "reinf_stone"
integrity = 65
hardness = 20
weight = 20
/datum/material/wood/redwood/generate_recipes()
..()
recipes += new /datum/stack_recipe("redwood floor tile", /obj/item/stack/tile/wood/redwood, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("large redwood floor tile", /obj/item/stack/tile/wood/redwood/panel, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("parquet redwood floor tile", /obj/item/stack/tile/wood/redwood/parquet, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("tiled redwood floor tile", /obj/item/stack/tile/wood/redwood/tile, 1, 4, 20, pass_stack_color = FALSE, recycle_material = "[name]")
recipes += new /datum/stack_recipe("vertical redwood floor tile", /obj/item/stack/tile/wood/redwood/vert, 1, 4, 20, pass_stack_color = FALSE)
recipes += new /datum/stack_recipe("vertical large redwood floor tile", /obj/item/stack/tile/wood/redwood/vert_panel, 1, 4, 20, pass_stack_color = FALSE)
for(var/datum/stack_recipe/r_recipe in recipes)
if(r_recipe.title == "wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "parquet wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "tiled wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "vertical large wood floor tile")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden chair")
recipes -= r_recipe
continue
if(r_recipe.title == "wooden standup figure")
recipes -= r_recipe
continue

View File

@@ -1,5 +1,5 @@
/obj/item/stack/material/wood
name = "wooden plank"
name = MAT_WOOD + " plank"
icon_state = "sheet-wood"
default_type = MAT_WOOD
strict_color_stacking = TRUE
@@ -9,16 +9,46 @@
no_variants = FALSE
/obj/item/stack/material/wood/sif
name = "alien wooden plank"
name = MAT_SIFWOOD + " plank"
color = "#0099cc"
default_type = MAT_SIFWOOD
/obj/item/stack/material/wood/hard
name = "hardwood plank"
name = MAT_HARDWOOD + " plank"
color = "#42291a"
default_type = MAT_HARDWOOD
description_info = "Rich, lustrous hardwood, imported from offworld at moderate expense. Mostly used for luxurious furniture, and not very good for weapons or other structures."
/obj/item/stack/material/wood/birch
name = MAT_BIRCHWOOD + " plank"
color = "#f6dec0"
default_type = MAT_BIRCHWOOD
description_info = "Sturdy hardwood, birch makes for beautiful furniture but also has many secondary applications. It's also an exceptionally good choice for firewood."
/obj/item/stack/material/wood/pine
name = MAT_PINEWOOD + " plank"
color = "#cd9d6f"
default_type = MAT_PINEWOOD
description_info = "Planks from tall, fast-growing coniferous pine trees, dense and mostly used for construction or furnishings."
/obj/item/stack/material/wood/oak
name = MAT_OAKWOOD + " plank"
color = "#674928"
default_type = MAT_OAKWOOD
description_info = "A sturdy, fairly common hardwood. A good choice for furnishings and structures. Oak barrels can be used to age alcohol, whilst oakwood chips are often used for smoking meats and cheeses."
/obj/item/stack/material/wood/acacia
name = MAT_ACACIAWOOD + " plank"
color = "#b75e12"
default_type = MAT_ACACIAWOOD
description_info = "Vibrant reddish-orange acacia makes a striking statement wherever it's used, and the bark of some acacia species is useful for tanning leather."
/obj/item/stack/material/wood/redwood
name = MAT_REDWOOD + " plank"
color = "#a45a52"
default_type = MAT_REDWOOD
description_info = "Blazing orange-red redwood planks. The trees used to make this can grow for centuries, and are often protected. This wood has been sustainably harvested from special tree nurseries, rather than chopping down ancient giants."
/obj/item/stack/material/log
name = MAT_LOG
icon_state = "sheet-log"

View File

@@ -79,7 +79,6 @@
outgoing_melee_damage_percent = 0.9 // 10% less melee damage.
disable_duration_percent = 1.25 // Stuns last 25% longer.
incoming_healing_percent = 0.9 // -10% to all healing
slowdown = 0.5 // Slower, by a smidge.
evasion = -5 // 5% easier to hit.
accuracy_dispersion = 1 // Inaccurate trait level of tile dispersion.
@@ -93,16 +92,6 @@
return ..()
/datum/modifier/franken_sickness/tick()
if(holder.stat != DEAD)
if(ishuman(holder))
var/mob/living/carbon/human/F = holder
if(F.can_defib)
F.can_defib = 0
/datum/modifier/franken_sickness/on_expire() //Not permanent, but its child is.
holder.add_modifier(/datum/modifier/franken_recovery, 0)
/datum/modifier/franken_recovery //When Franken_Sickness expires, this will be permanently applied in its place.
name = "neural recovery"
desc = "You feel out of touch, as your central nervous system is still recovering from being repaired."

View File

@@ -71,6 +71,11 @@
if(stat == DEAD)
return 0
var/mob/living/simple_mob/animal/borer/has_worm = has_brain_worms()
if(has_worm) // This is our host's problem to deal with
has_worm.detatch()
SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_DEATH, src, gibbed)

View File

@@ -1,66 +1,3 @@
//Brain slug proc for voluntary removal of control.
/mob/living/carbon/proc/release_control()
set category = "Abilities.Brainslug"
set name = "Release Control"
set desc = "Release control of your host's body."
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
if(B && B.host_brain)
to_chat(src, span_danger("You withdraw your probosci, releasing control of [B.host_brain]"))
B.detatch()
remove_verb(src, /mob/living/carbon/proc/release_control)
remove_verb(src, /mob/living/carbon/proc/punish_host)
remove_verb(src, /mob/living/carbon/proc/spawn_larvae)
else
to_chat(src, span_danger("ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !"))
//Brain slug proc for tormenting the host.
/mob/living/carbon/proc/punish_host()
set category = "Abilities.Brainslug"
set name = "Torment host"
set desc = "Punish your host with agony."
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
if(!B)
return
if(B.host_brain.ckey)
to_chat(src, span_danger("You send a punishing spike of psychic agony lancing into your host's brain."))
if (!can_feel_pain())
to_chat(B.host_brain, span_warning("You feel a strange sensation as a foreign influence prods your mind."))
to_chat(src, span_danger("It doesn't seem to be as effective as you hoped."))
else
to_chat(B.host_brain, span_danger(span_large("Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!")))
/mob/living/carbon/proc/spawn_larvae()
set category = "Abilities.Brainslug"
set name = "Reproduce"
set desc = "Spawn several young."
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
if(!B)
return
if(B.chemicals >= 100)
to_chat(src, span_danger("Your host twitches and quivers as you rapidly excrete a larva from your sluglike body."))
visible_message(span_danger("\The [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!"))
B.chemicals -= 100
B.has_reproduced = 1
vomit(1)
new /mob/living/simple_mob/animal/borer(get_turf(src))
else
to_chat(src, span_warning("You do not have enough chemicals stored to reproduce."))
return
/mob/living/proc/toggle_active_cloaking() // Borrowed from Rogue Star, thanks guys!
set category = "Abilities.General"
set name = "Toggle Active Cloaking"

View File

@@ -1216,7 +1216,7 @@
if(src.pulse)
to_chat(usr, span_notice("[self ? "You have a" : "[src] has a"] pulse! Counting..."))
else
to_chat(usr, span_danger("[src] has no pulse!")) //it is REALLY UNLIKELY that a dead person would check his own pulse
to_chat(usr, span_danger("[src] has no pulse!"))
return
to_chat(usr, span_filter_notice("You must[self ? "" : " both"] remain still until counting is finished."))

View File

@@ -75,13 +75,13 @@
has_organ = list(
O_HEART = /obj/item/organ/internal/heart/vox,
O_LUNGS = /obj/item/organ/internal/lungs/vox,
O_VOICE = /obj/item/organ/internal/voicebox,
O_LIVER = /obj/item/organ/internal/liver/vox,
O_KIDNEYS = /obj/item/organ/internal/kidneys/vox,
O_BRAIN = /obj/item/organ/internal/brain/vox,
O_EYES = /obj/item/organ/internal/eyes,
O_HEART = /obj/item/organ/internal/heart/vox,
O_LUNGS = /obj/item/organ/internal/lungs/vox,
O_VOICE = /obj/item/organ/internal/voicebox/vox,
O_LIVER = /obj/item/organ/internal/liver/vox,
O_KIDNEYS = /obj/item/organ/internal/kidneys/vox,
O_BRAIN = /obj/item/organ/internal/brain/vox,
O_EYES = /obj/item/organ/internal/eyes,
)
genders = list(NEUTER)

View File

@@ -205,7 +205,7 @@
cost = -1 //CHOMPEdit - Keep original value
can_take = ORGANICS
is_genetrait = TRUE
is_genetrait = FALSE
hidden = FALSE
activity_bounds = DNA_HARDER_BOUNDS // Shouldn't be easy for genetics to find this

View File

@@ -683,7 +683,7 @@
if(last_adrenaline_rush && last_adrenaline_rush + (30 MINUTES) > world.time)
return
last_adrenaline_rush = world.time
log_and_message_admins("[H]'s adrenaline rush trait just activated!")
log_and_message_admins("[H]'s adrenaline rush trait just activated!", H)
H.add_modifier(/datum/modifier/adrenaline, 30 SECONDS)
/datum/modifier/adrenaline

View File

@@ -21,6 +21,7 @@
status_flags = CANPUSH
pass_flags = PASSTABLE
movement_cooldown = 1.5
mob_size = MOB_TINY // no landmines for you
universal_understand = TRUE
can_be_antagged = TRUE
@@ -35,16 +36,37 @@
var/antag = TRUE // If false, will avoid setting up objectives and events
var/chemicals = 10 // A resource used for reproduction and powers.
var/max_chemicals = 250 // Max of said resource.
var/true_name = null // String used when speaking among other worms.
var/controlling = FALSE // Used in human death ceck.
var/docile = FALSE // Sugar can stop borers from acting.
var/docile_counter = 0 // How long we are docile for
var/has_reproduced = FALSE
var/used_dominate // world.time when the dominate power was last used.
var/datum/ghost_query/Q // Used to unregister our signal
can_be_drop_prey = FALSE
vent_crawl_time = 30 // faster vent crawler
var/static/borer_chem_list = list(
// Antag utlity
"Repair Brain Tissue" = list(REAGENT_ID_ALKYSINE, 5),
"Repair Brute" = list(REAGENT_ID_BICARIDINE, 10),
"Repair Burn" = list(REAGENT_ID_KELOTANE, 10),
"Enhance Speed" = list(REAGENT_ID_HYPERZINE, 10),
// Stablization
"Stablize Mind" = list(REAGENT_ID_CITALOPRAM, 10),
"Stablize Nerves" = list(REAGENT_ID_ADRANOL, 10),
"Stablize Bleeding" = list(REAGENT_ID_INAPROVALINE, 5),
"Stablize Infection" = list(REAGENT_ID_SPACEACILLIN, 15),
"Stablize Pain" = list(REAGENT_ID_TRAMADOL, 5),
// Scene tools
"Make Drunk" = list(REAGENT_ID_ETHANOL, 5),
"Cure Drunk" = list(REAGENT_ID_ETHYLREDOXRAZINE, 10),
"Euphoric High" = list(REAGENT_ID_BLISS, 5),
"Mood Stimulant" = list(REAGENT_ID_APHRODISIAC, 5),
// Borer last resport
"Revive Dead Host" = null
)
/mob/living/simple_mob/animal/borer/roundstart
roundstart = TRUE
@@ -53,18 +75,19 @@
antag = FALSE
/mob/living/simple_mob/animal/borer/Login()
..()
. = ..()
if(antag && mind)
borers.add_antagonist(mind)
/mob/living/simple_mob/animal/borer/Initialize(mapload)
add_language("Cortical Link")
add_verb(src, /mob/living/proc/ventcrawl)
add_verb(src, /mob/living/proc/hide)
motiontracker_subscribe()
true_name = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]"
..()
. = ..()
if(!roundstart && antag)
return INITIALIZE_HINT_LATELOAD
@@ -72,52 +95,145 @@
/mob/living/simple_mob/animal/borer/LateInitialize()
request_player()
/mob/living/simple_mob/animal/borer/Destroy()
. = ..()
motiontracker_unsubscribe()
QDEL_NULL(ghost_check)
if(host)
detatch()
leave_host()
/mob/living/simple_mob/animal/borer/handle_special()
if(host && !stat && !host.stat)
// Handle docility.
if(host.reagents.has_reagent(REAGENT_ID_SUGAR) && !docile)
var/message = "You feel the soporific flow of sugar in your host's blood, lulling you into docility."
var/target = controlling ? host : src
to_chat(target, span_warning(message))
docile = TRUE
else if(docile)
var/message = "You shake off your lethargy as the sugar leaves your host's blood."
var/target = controlling ? host : src
to_chat(target, span_notice(message))
docile = FALSE
// Chem regen.
if(chemicals < max_chemicals)
chemicals++
// Control stuff.
if(controlling)
if(docile)
to_chat(host, span_warning("You are feeling far too docile to continue controlling your host..."))
host.release_control()
return
if(prob(5))
host.adjustBrainLoss(0.1)
if(prob(host.brainloss/20))
host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_v","gasp"))]")
handle_chemicals()
handle_docile()
handle_braindamage()
/mob/living/simple_mob/animal/borer/get_status_tab_items()
. = ..()
. += "Chemicals: [chemicals]"
. += "Chemicals: [FLOOR(chemicals,1)]"
/mob/living/simple_mob/animal/borer/proc/handle_chemicals()
if(stat == DEAD || !host || host.stat == DEAD)
return
if(chemicals >= BORER_MAX_CHEMS || docile)
return
var/chem_before = chemicals
if(controlling)
chemicals += 0.25
else
chemicals += 0.1
var/new_chem = FLOOR(chemicals/10,1)
if(new_chem > FLOOR(chem_before/10,1))
to_chat(host, span_alien("Your chemicals have increased to [new_chem * 10]"))
/mob/living/simple_mob/animal/borer/proc/handle_docile()
if(stat == DEAD)
docile_counter = 0
return
// Start docile
if(host && (host.reagents.has_reagent(REAGENT_ID_SUGAR) || host.ingested.has_reagent(REAGENT_ID_SUGAR)))
docile_counter = 5 SECONDS
if(!docile)
var/message = "You feel the soporific flow of sugar in your host's blood, lulling you into docility."
var/target = controlling ? host : src
to_chat(target, span_danger( message))
docile = TRUE
// Drop control if docile
if(controlling && docile)
to_chat(host, span_vdanger("You are feeling far too docile to continue controlling your host..."))
host.release_control()
return
// wear it off
docile_counter--
if(docile_counter > 0)
return
// End docile
if(docile)
to_chat(controlling ? host : src, span_notice("You shake off your lethargy as the sugar leaves your host's blood."))
docile = FALSE
docile_counter = 0
/mob/living/simple_mob/animal/borer/proc/handle_braindamage()
if(QDELETED(src) || !host || QDELETED(host) || !controlling)
return
if(prob(2))
host.adjustBrainLoss(0.1)
if(prob(host.brainloss/20))
host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_v","gasp"))]")
/mob/living/simple_mob/animal/borer/proc/can_use_power_in_host()
if(QDELETED(src))
return FALSE
if(!host || QDELETED(host))
to_chat(src, span_warning("You are not inside a host body."))
return FALSE
if(stat)
to_chat(controlling ? host : src, span_warning("You cannot that that in your current state."))
return FALSE
return TRUE
/mob/living/simple_mob/animal/borer/proc/can_use_power_controlling_host()
if(!can_use_power_in_host())
return FALSE
if(!controlling)
to_chat(controlling ? host : src, span_warning("You need to be in complete control to do this."))
return FALSE
if(host.stat)
to_chat(controlling ? host : src, span_warning("Your host is in no condition to do that."))
return FALSE
return TRUE
/mob/living/simple_mob/animal/borer/proc/can_use_power_docile()
if(docile)
to_chat(controlling ? host : src, span_info("You are feeling far too docile to do that."))
return !docile
/mob/living/simple_mob/animal/borer/proc/use_chems(amount)
if(chemicals < amount)
to_chat(controlling ? host : src, span_warning("You don't have enough chemicals, requires [amount]! Currently you have [FLOOR(chemicals,1)]."))
return FALSE
chemicals -= amount
to_chat(controlling ? host : src, span_info("You use [amount] chemicals, [FLOOR(chemicals,1)] remain."))
return TRUE
/mob/living/simple_mob/animal/borer/handle_regular_hud_updates()
. = ..()
if(!.)
return
if(borer_chem_display)
borer_chem_display.invisibility = INVISIBILITY_NONE
switch(chemicals)
if(0 to 9)
borer_chem_display.icon_state = "ling_chems0e"
if(10 to 19)
borer_chem_display.icon_state = "ling_chems10e"
if(20 to 29)
borer_chem_display.icon_state = "ling_chems20e"
if(30 to 39)
borer_chem_display.icon_state = "ling_chems30e"
if(40 to 49)
borer_chem_display.icon_state = "ling_chems40e"
if(50 to 59)
borer_chem_display.icon_state = "ling_chems50e"
if(60 to 69)
borer_chem_display.icon_state = "ling_chems60e"
if(70 to 79)
borer_chem_display.icon_state = "ling_chems70e"
if(80 to INFINITY)
borer_chem_display.icon_state = "ling_chems80e"
/mob/living/simple_mob/animal/borer/proc/detatch()
if(!host || !controlling)
return
if(ishuman(host))
var/mob/living/carbon/human/H = host
var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
if(head)
head.implants -= src
var/obj/item/organ/external/head = host.get_organ(BP_HEAD)
if(head)
head.implants -= src
controlling = FALSE
host.remove_language("Cortical Link")
@@ -125,6 +241,7 @@
remove_verb(host, /mob/living/carbon/proc/punish_host)
remove_verb(host, /mob/living/carbon/proc/spawn_larvae)
// This entire section is awful and a relic of ancient times. It needs to be replaced
if(host_brain)
// these are here so bans and multikey warnings are not triggered on the wrong people when ckey is changed.
// computer_id and IP are not updated magically on their own in offline mobs -walter0o
@@ -160,7 +277,7 @@
host.lastKnownIP = b2h_ip
qdel(host_brain)
// End horrible ip swapping code for bans
/mob/living/simple_mob/animal/borer/proc/leave_host()
if(!host)
@@ -169,32 +286,16 @@
if(host.mind)
borers.remove_antagonist(host.mind)
forceMove(get_turf(host))
if(!QDELETED(src))
forceMove(get_turf(host.loc))
unset_machine()
if(ishuman(host))
var/mob/living/carbon/human/H = host
var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
if(head)
head.implants -= src
var/obj/item/organ/external/head = host.get_organ(BP_HEAD)
if(head)
head.implants -= src
host.unset_machine()
host = null
/mob/living/simple_mob/animal/borer/proc/request_player()
Q = new /datum/ghost_query/borer()
RegisterSignal(Q, COMSIG_GHOST_QUERY_COMPLETE, PROC_REF(get_winner))
Q.query() // This will sleep the proc for awhile.
/mob/living/simple_mob/animal/borer/proc/get_winner()
SIGNAL_HANDLER
if(Q && Q.candidates.len) //Q should NEVER get deleted but...whatever, sanity.
var/mob/observer/dead/D = Q.candidates[1]
transfer_personality(D)
UnregisterSignal(Q, COMSIG_GHOST_QUERY_COMPLETE)
QDEL_NULL(Q) //get rid of the query
/mob/living/simple_mob/animal/borer/proc/transfer_personality(mob/candidate)
if(!candidate)
return
@@ -206,17 +307,25 @@
mind.assigned_role = JOB_CORTICAL_BORER
mind.special_role = JOB_CORTICAL_BORER
// TODO - This needs to be made into something more pref friendly if it's ever going to be used on virgo.
to_chat(src, span_notice("You are a cortical borer! You are a brain slug that worms its way \
into the head of its victim. Use stealth, persuasion and your powers of mind control to keep you, \
your host and your eventual spawn safe and warm."))
to_chat(src, "You can speak to your victim with <b>say</b>, to other borers with <b>say :x</b>, and use your Abilities tab to access powers.")
/mob/living/simple_mob/animal/borer/cannot_use_vents()
return
return host || stat
/mob/living/simple_mob/animal/borer/extra_huds(var/datum/hud/hud,var/icon/ui_style,var/list/hud_elements)
// Chem hud
borer_chem_display = new /atom/movable/screen/borer/chems()
borer_chem_display.screen_loc = ui_ling_chemical_display
borer_chem_display.icon_state = "ling_chems"
hud_elements |= borer_chem_display
/mob/living/simple_mob/animal/borer/UnarmedAttack(var/atom/A, var/proximity)
if(ismob(loc))
to_chat(src, span_warning("You cannot interact with that from inside a host!"))
to_chat(src, span_notice("You cannot interact with that from inside a host!"))
return
. = ..()
@@ -230,7 +339,7 @@
if(stat >= DEAD)
return say_dead(message)
else if(stat)
if(stat)
return
if(client && client.prefs.muted & MUTE_IC)
@@ -247,10 +356,10 @@
return
if(!host)
if(chemicals >= 30)
if(chemicals >= BORER_PSYCHIC_SAY_MINIMUM_CHEMS)
to_chat(src, span_alien("..You emit a psionic pulse with an encoded message.."))
var/list/nearby_mobs = list()
for(var/mob/living/LM in view(src, 1 + round(6 * (chemicals / max_chemicals))))
for(var/mob/living/LM in view(src, 1 + round(6 * (chemicals / BORER_MAX_CHEMS))))
if(LM == src)
continue
if(!LM.stat)

View File

@@ -7,12 +7,12 @@
/mob/living/captive_brain/say(var/message, var/datum/language/speaking = null, var/whispering = 0)
if (src.client)
if(client)
if(client.prefs.muted & MUTE_IC)
to_chat(src, span_red("You cannot speak in IC (muted)."))
return
if(istype(src.loc, /mob/living/simple_mob/animal/borer))
if(istype(loc, /mob/living/simple_mob/animal/borer))
message = sanitize(message)
if (!message)
@@ -21,7 +21,7 @@
if (stat == 2)
return say_dead(message)
var/mob/living/simple_mob/animal/borer/B = src.loc
var/mob/living/simple_mob/animal/borer/B = loc
to_chat(src, "You whisper silently, \"[message]\"")
to_chat(B.host, "The captive mind of [src] whispers, \"[message]\"")
@@ -41,24 +41,19 @@
/mob/living/captive_brain/process_resist()
//Resisting control by an alien mind.
if(istype(src.loc, /mob/living/simple_mob/animal/borer))
var/mob/living/simple_mob/animal/borer/B = src.loc
var/mob/living/captive_brain/H = src
to_chat(H, span_danger("You begin doggedly resisting the parasite's control (this will take approximately sixty seconds)."))
if(istype(loc, /mob/living/simple_mob/animal/borer))
var/mob/living/simple_mob/animal/borer/B = loc
to_chat(src, span_danger("You begin doggedly resisting the parasite's control (this will take approximately sixty seconds)."))
to_chat(B.host, span_danger("You feel the captive mind of [src] begin to resist your control."))
spawn(rand(200,250)+B.host.brainloss)
if(!B || !B.controlling) return
B.host.adjustBrainLoss(rand(0.1,0.5))
to_chat(H, span_danger("With an immense exertion of will, you regain control of your body!"))
to_chat(B.host, span_danger("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you."))
B.detatch()
remove_verb(src, /mob/living/carbon/proc/release_control)
remove_verb(src, /mob/living/carbon/proc/punish_host)
remove_verb(src, /mob/living/carbon/proc/spawn_larvae)
addtimer(CALLBACK(src, PROC_REF(break_control_of_borer)), (rand(20,25) + (B.host.brainloss/10)) SECONDS, TIMER_DELETE_ME)
return
. = ..()
..()
/mob/living/captive_brain/proc/break_control_of_borer()
var/mob/living/simple_mob/animal/borer/B = loc
if(!B || !B.controlling)
return
to_chat(src, span_danger("With an immense exertion of will, you regain control of your body!"))
to_chat(B.host, span_danger("You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you."))
B.host.adjustBrainLoss(rand(0.1,0.5))
B.detatch()

View File

@@ -0,0 +1,112 @@
/**
* Assume control of a borer's host, putting the borer's client in control, and putting the other into a dominated brain.
*/
/mob/living/simple_mob/animal/borer/verb/bond_brain()
set category = "Abilities.Borer"
set name = "Assume Control"
set desc = "Fully connect to the brain of your host."
if(!can_use_power_in_host())
return
if(!can_use_power_docile())
return
if(host.stat == DEAD)
to_chat(src, span_warning("Your host is in no condition to do that."))
return
to_chat(src, span_alien("You begin delicately adjusting your connection to the host brain..."))
addtimer(CALLBACK(src, PROC_REF(finish_bond_brain)), 100 + (host.brainloss * 5), TIMER_DELETE_ME)
// This entire section is awful and a relic of ancient times. It needs to be replaced
/mob/living/simple_mob/animal/borer/proc/finish_bond_brain()
PRIVATE_PROC(TRUE)
RETURN_TYPE(null)
if(!host || QDELETED(src) || controlling)
return
if(host.stat == DEAD)
to_chat(src, span_warning("Your host is in no condition to do that."))
return
to_chat(src, span_alien("You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system."))
to_chat(host, span_danger("You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours."))
host.add_language("Cortical Link")
// host -> brain
var/h2b_id = host.computer_id
var/h2b_ip= host.lastKnownIP
host.computer_id = null
host.lastKnownIP = null
qdel(host_brain)
host_brain = new(src)
host_brain.ckey = host.ckey
host_brain.name = host.name
if(!host_brain.computer_id)
host_brain.computer_id = h2b_id
if(!host_brain.lastKnownIP)
host_brain.lastKnownIP = h2b_ip
// self -> host
var/s2h_id = src.computer_id
var/s2h_ip= src.lastKnownIP
src.computer_id = null
src.lastKnownIP = null
host.ckey = src.ckey
if(!host.computer_id)
host.computer_id = s2h_id
if(!host.lastKnownIP)
host.lastKnownIP = s2h_ip
controlling = TRUE
add_verb(host, /mob/living/carbon/proc/release_control)
add_verb(host, /mob/living/carbon/proc/punish_host)
if(antag)
add_verb(host, /mob/living/carbon/proc/spawn_larvae)
// End horrible ip swapping code for bans
/**
* Releases manual control of the borer from a mind-dominated host. Returning control to the original mind.
*/
/mob/living/simple_mob/animal/borer/verb/release_host()
set category = "Abilities.Borer"
set name = "Release Host"
set desc = "Slither out of your host."
if(!host)
to_chat(src, span_warning("You are not inside a host body."))
return
if(stat)
to_chat(src, span_warning("You cannot leave your host in your current state."))
return
if(!can_use_power_docile())
return
to_chat(src, span_alien("You begin disconnecting from [host]'s synapses and prodding at their internal ear canal."))
if(!host.stat)
to_chat(host, span_danger("An odd, uncomfortable pressure begins to build inside your skull, behind your ear..."))
addtimer(CALLBACK(src, PROC_REF(finish_release_host)), 10 SECONDS, TIMER_DELETE_ME)
/mob/living/simple_mob/animal/borer/proc/finish_release_host()
PRIVATE_PROC(TRUE)
if(!host || QDELETED(src))
return
if(stat)
to_chat(src, span_warning("You cannot release your host in your current state."))
return
to_chat(src, span_alien("You wiggle out of [host]'s ear and plop to the ground."))
if(host.mind)
if(!host.stat)
to_chat(host, span_danger("Something slimy wiggles out of your ear and plops to the ground!"))
to_chat(host, span_danger("As though waking from a dream, you shake off the insidious mind control of the brain worm. Your thoughts are your own again."))
detatch()
leave_host()

View File

@@ -0,0 +1,68 @@
/**
* Brain slug proc for voluntary removal of control.
*/
/mob/living/carbon/proc/release_control()
set category = "Abilities.Brainslug"
set name = "Release Control"
set desc = "Release control of your host's body."
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
if(!B)
return
if(!B.host_brain)
return
to_chat(src, span_alien("You withdraw your probosci, releasing control of [B.host_brain]"))
B.detatch()
/**
* Brain slug proc for tormenting the host.
*/
/mob/living/carbon/proc/punish_host()
set category = "Abilities.Brainslug"
set name = "Torment host"
set desc = "Punish your host with agony."
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
if(!B)
return
if(!B.host_brain)
return
if(!B.can_use_power_docile())
return
if(!B.use_chems(BORER_POWER_COST_TORTURE))
return
to_chat(src, span_alien("You send a punishing spike of psychic agony lancing into your host's brain."))
if(!B.host_brain.client || !can_feel_pain())
to_chat(B.host_brain, span_warning("You feel a strange sensation as a foreign influence prods your mind."))
to_chat(src, span_danger("It doesn't seem to be as effective as you hoped."))
return
to_chat(B.host_brain, span_danger(span_large("Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!")))
/**
* Brain slug proc for spitting up new borers. They are ghostjoin by default, but are infertile.
*/
/mob/living/carbon/proc/spawn_larvae()
set category = "Abilities.Brainslug"
set name = "Reproduce"
set desc = "Spawn several young."
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
if(!B || !B.can_use_power_controlling_host())
return
if(!B.can_use_power_docile())
return
if(!B.antag)
to_chat(src, span_warning("You cannot reproduce, you are infertile!"))
return
if(!B.use_chems(BORER_POWER_COST_REPRODUCE))
return
to_chat(src, span_alien("Your host twitches and quivers as you rapidly excrete a larva from your sluglike body."))
visible_message(span_danger("\The [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!"))
do_vomit(lost_nutrition = 1) // Needs to be instant
new /mob/living/simple_mob/animal/borer/non_antag(get_turf(src))
B.has_reproduced = TRUE

View File

@@ -1,43 +1,55 @@
/mob/living/simple_mob/animal/borer/verb/release_host()
/**
* Put a nearby target to sleep to allow for infestation.
*/
/mob/living/simple_mob/animal/borer/verb/knockout_victim()
set category = "Abilities.Borer"
set name = "Release Host"
set desc = "Slither out of your host."
set name = "Knockout Victim"
set desc = "Use your psychic influence to put a target into a temporary catatonic state."
if(!host)
to_chat(src, span_warning("You are not inside a host body."))
if(world.time - used_dominate < 150)
to_chat(src, span_warning("You cannot use that ability again so soon."))
return
if(host)
to_chat(src, span_warning("You cannot do that from within a host body."))
return
if(stat)
to_chat(src, span_warning("You cannot leave your host in your current state."))
if(docile)
to_chat(src, span_blue("You are feeling far too docile to do that."))
to_chat(src, span_warning("You cannot do that in your current state."))
return
if(!host || !src) return
var/attack_range = 5
var/list/choices = list()
for(var/mob/living/carbon/human/attackable in view(attack_range,src))
if(attackable.stat != DEAD && !attackable.has_brain_worms())
choices += attackable
if(world.time - used_dominate < 150)
to_chat(src, span_warning("You cannot use that ability again so soon."))
return
to_chat(src, span_warning("You begin disconnecting from [host]'s synapses and prodding at their internal ear canal."))
if(!choices.len)
to_chat(src, span_notice("There are no viable targets within range..."))
return
var/mob/living/carbon/human/attack_target = choices[1]
if(choices.len > 1)
tgui_input_list(src, "Who do you wish to dominate?", "Target Choice", choices)
if(!host.stat)
to_chat(host, span_warning("An odd, uncomfortable pressure begins to build inside your skull, behind your ear..."))
if(!attack_target || QDELETED(src))
return
if(!(attack_target in view(attack_range,src)))
to_chat(src, span_warning("\The [attack_target] escaped your influence..."))
return
if(attack_target.has_brain_worms())
to_chat(src, span_warning("You cannot influence someone who is already infested!"))
return
spawn(100)
if(!host || !src) return
if(src.stat)
to_chat(src, span_warning("You cannot release your host in your current state."))
return
to_chat(src, span_warning("You wiggle out of [host]'s ear and plop to the ground."))
if(host.mind)
if(!host.stat)
to_chat(host, span_danger("Something slimy wiggles out of your ear and plops to the ground!"))
to_chat(host, span_danger("As though waking from a dream, you shake off the insidious mind control of the brain worm. Your thoughts are your own again."))
detatch()
leave_host()
to_chat(src, span_alien("You focus your psychic lance on [attack_target] and freeze their limbs with a wave of terrible dread."))
to_chat(attack_target, span_vdanger("You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing."))
attack_target.Sleeping(10) // This was paralyze, but it resulted in players instantly screaming over radio. So get slept nerds.
used_dominate = world.time
add_attack_logs(src, attack_target, "psychic knockout (borer)")
/**
* Crawls inside of a target mob, and adds the borer as an implant to the mob's brain. If no brain exists the body will become a borer husk zombie.
*/
/mob/living/simple_mob/animal/borer/verb/infest()
set category = "Abilities.Borer"
set name = "Infest"
@@ -46,311 +58,190 @@
if(host)
to_chat(src, span_warning("You are already within a host."))
return
if(stat)
to_chat(src, span_warning("You cannot infest a target in your current state."))
return
var/list/choices = list()
for(var/mob/living/carbon/C in view(1,src))
if(src.Adjacent(C))
choices += C
for(var/mob/living/carbon/human/check_target in view(1,src))
if(Adjacent(check_target) && !check_target.has_brain_worms())
choices += check_target
if(!choices.len)
to_chat(src, span_warning("There are no viable hosts within range..."))
return
var/mob/living/carbon/M = tgui_input_list(src, "Who do you wish to infest?", "Target Choice", choices)
var/mob/living/carbon/human/infest_target = choices[1]
if(choices.len > 1)
infest_target = tgui_input_list(src, "Who do you wish to infest?", "Target Choice", choices)
if(QDELETED(infest_target) || QDELETED(src))
return
infest_target(infest_target)
if(!M || !src) return
if(!(src.Adjacent(M))) return
if(M.has_brain_worms())
/// Infests mob with borer.
/mob/living/simple_mob/animal/borer/proc/infest_target(mob/living/carbon/human/infest_target)
if(!istype(infest_target))
to_chat(src, span_warning("\The [infest_target] is not suitable for infestation..."))
return
if(!(Adjacent(infest_target)))
to_chat(src, span_warning("\The [infest_target] has escaped your range..."))
return
if(infest_target.has_brain_worms())
to_chat(src, span_warning("You cannot infest someone who is already infested!"))
return
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/entering_timer = 30
var/protected = FALSE
var/obj/item/organ/external/E = infest_target.organs_by_name[BP_HEAD]
if(!E || E.is_stump())
to_chat(src, span_warning("\The [infest_target] does not have a head!"))
var/obj/item/organ/external/E = H.organs_by_name[BP_HEAD]
if(!E || E.is_stump())
to_chat(src, span_warning("\The [H] does not have a head!"))
if(!H.should_have_organ(O_BRAIN))
to_chat(src, span_warning("\The [H] does not seem to have an ear canal to breach."))
return
if(H.check_head_coverage())
to_chat(src, span_warning("You cannot get through that host's protective gear."))
return
to_chat(M, "Something slimy begins probing at the opening of your ear canal...")
to_chat(src, span_warning("You slither up [M] and begin probing at their ear canal..."))
if(!do_after(src, 3 SECONDS, target = M))
to_chat(src, span_warning("As [M] moves away, you are dislodged and fall to the ground."))
if(!infest_target.should_have_organ(O_BRAIN))
to_chat(src, span_warning("\The [infest_target] does not seem to have an ear canal to breach."))
return
if(infest_target.check_head_coverage())
to_chat(src, span_alien("You begin to flatten and squirm into \the [infest_target]'s helmet to find a way inside them."))
entering_timer = 55
protected = TRUE
if(!M || !src) return
if(src.stat)
to_chat(src, span_warning("You cannot infest a target in your current state."))
return
if(M in view(1, src))
to_chat(src, span_warning("You wiggle into [M]'s ear."))
if(!M.stat)
to_chat(M, "Something disgusting and slimy wiggles into your ear!")
src.host = M
src.forceMove(M)
//Update their traitor status.
if(host.mind)
borers.add_antagonist_mind(host.mind, 1, borers.faction_role_text, borers.faction_welcome)
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/organ/I = H.internal_organs_by_name[O_BRAIN]
if(!I) // No brain organ, so the borer moves in and replaces it permanently.
replace_brain()
else
// If they're in normally, implant removal can get them out.
var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
head.implants += src
return
if(!protected)
to_chat(infest_target, span_vdanger("Something slimy begins probing at the opening of your ear canal..."))
else
to_chat(infest_target, span_vdanger("Something slimy begins trying to find a way past your helmet..."))
to_chat(src, span_alien("You slither up to \the [infest_target] and begin probing at their ear canal..."))
if(!do_after(src, entering_timer, target = infest_target))
to_chat(src, span_danger("As [infest_target] moves away, you are dislodged and fall to the ground."))
return
if(!infest_target || QDELETED(src))
return
if(stat)
to_chat(src, span_warning("You cannot infest \the [infest_target] in your current state."))
return
if(!(Adjacent(infest_target)))
to_chat(src, span_warning("They are no longer in range!"))
return
/*
/mob/living/simple_mob/animal/borer/verb/devour_brain()
set category = "Abilities.Borer"
set name = "Devour Brain"
set desc = "Take permanent control of a dead host."
if(!host)
to_chat(src, span_warning("You are not inside a host body."))
if(!infest_target.internal_organs_by_name[O_BRAIN]) // See section below about replace_brain() being disabled
to_chat(src, span_danger("\The [infest_target] has no brain to bond to!"))
return
if(host.stat != 2)
to_chat(src, span_warning("Your host is still alive."))
to_chat(src, span_alien("You wiggle into [infest_target]'s ear."))
if(!infest_target.stat)
to_chat(infest_target, span_vdanger("Something disgusting and slimy wiggles into your ear!"))
host = infest_target
forceMove(host)
//Update their traitor status.
if(host.mind)
borers.add_antagonist_mind(host.mind, 1, borers.faction_role_text, borers.faction_welcome)
/* This is likely not desired, and has some major issues with ghost behavior. Disabling for now
// No brain organ, so the borer moves in and replaces it permanently.
if(!host.internal_organs_by_name[O_BRAIN])
add_attack_logs(src, host, "merged with brainless body (borer)")
replace_brain()
return
*/
if(stat)
to_chat(src, span_warning("You cannot do that in your current state."))
if(docile)
to_chat(src, span_warning(span_blue("You are feeling far too docile to do that.")))
return
to_chat(src, span_danger("It only takes a few moments to render the dead host brain down into a nutrient-rich slurry..."))
replace_brain()
*/
// BRAIN WORM ZOMBIES AAAAH.
/mob/living/simple_mob/animal/borer/proc/replace_brain()
var/mob/living/carbon/human/H = host
if(!istype(host))
to_chat(src, span_warning("This host does not have a suitable brain."))
return
to_chat(src, span_danger("You settle into the empty brainpan and begin to expand, fusing inextricably with the dead flesh of [H]."))
H.add_language("Cortical Link")
if(host.stat == 2)
add_verb(H, /mob/living/carbon/human/proc/jumpstart)
add_verb(H, /mob/living/carbon/human/proc/psychic_whisper)
add_verb(H, /mob/living/carbon/human/proc/tackle)
if(antag)
add_verb(H, /mob/living/carbon/proc/spawn_larvae)
if(H.client)
H.ghostize(0)
if(src.mind)
src.mind.special_role = "Borer Husk"
src.mind.transfer_to(host)
H.ChangeToHusk()
var/obj/item/organ/internal/borer/B = new(H)
H.internal_organs_by_name[O_BRAIN] = B
H.internal_organs |= B
var/obj/item/organ/external/affecting = H.get_organ(BP_HEAD)
affecting.implants -= src
var/s2h_id = src.computer_id
var/s2h_ip= src.lastKnownIP
src.computer_id = null
src.lastKnownIP = null
if(!H.computer_id)
H.computer_id = s2h_id
if(!H.lastKnownIP)
H.lastKnownIP = s2h_ip
// If they're in normally, implant removal can get them out.
var/obj/item/organ/external/head = host.get_organ(BP_HEAD)
head.implants += src
add_attack_logs(src, host, "infested target (borer)")
/**
* Releases chemicals from the borer into their host. Can be used as a standalone chemist in your head for an antag cooperating with their borer.
*/
/mob/living/simple_mob/animal/borer/verb/secrete_chemicals()
set category = "Abilities.Borer"
set name = "Secrete Chemicals"
set desc = "Push some chemicals into your host's bloodstream."
set desc = "Drain some chemicals into your host's bloodstream."
if(!host)
to_chat(src, span_warning("You are not inside a host body."))
if(!can_use_power_in_host())
return
if(!can_use_power_docile())
return
if(controlling)
to_chat(src, span_warning("You cannot do that while in full control of a host."))
return
if(stat)
to_chat(src, span_warning("You cannot secrete chemicals in your current state."))
if(docile)
to_chat(src, span_warning(span_blue("You are feeling far too docile to do that.")))
return
if(chemicals < 50)
to_chat(src, span_warning("You don't have enough chemicals!"))
var/chem = tgui_input_list(src, "Select a chemical to secrete.", "Chemicals", list(REAGENT_ID_ALKYSINE,REAGENT_ID_BICARIDINE,REAGENT_ID_HYPERZINE,REAGENT_ID_TRAMADOL))
if(!chem || chemicals < 50 || !host || controlling || !src || stat) //Sanity check.
return
to_chat(src, span_bolddanger("You squirt a measure of [chem] from your reservoirs into [host]'s bloodstream."))
host.reagents.add_reagent(chem, 10)
chemicals -= 50
/mob/living/simple_mob/animal/borer/verb/dominate_victim()
set category = "Abilities.Borer"
set name = "Paralyze Victim"
set desc = "Freeze the limbs of a potential host with supernatural fear."
if(world.time - used_dominate < 150)
to_chat(src, span_warning("You cannot use that ability again so soon."))
return
if(host)
to_chat(src, span_warning("You cannot do that from within a host body."))
return
if(src.stat)
to_chat(src, span_warning("You cannot do that in your current state."))
return
var/list/choices = list()
for(var/mob/living/carbon/C in view(3,src))
if(C.stat != 2)
choices += C
if(world.time - used_dominate < 150)
to_chat(src, span_warning("You cannot use that ability again so soon."))
return
var/mob/living/carbon/M = tgui_input_list(src, "Who do you wish to dominate?", "Target Choice", choices)
if(!M || !src) return
if(M.has_brain_worms())
to_chat(src, span_warning("You cannot infest someone who is already infested!"))
return
to_chat(src, span_red("You focus your psychic lance on [M] and freeze their limbs with a wave of terrible dread."))
to_chat(M, span_red("You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing."))
M.Weaken(10)
used_dominate = world.time
/mob/living/simple_mob/animal/borer/verb/bond_brain()
set category = "Abilities.Borer"
set name = "Assume Control"
set desc = "Fully connect to the brain of your host."
if(!host)
to_chat(src, span_warning("You are not inside a host body."))
return
if(src.stat)
to_chat(src, span_warning("You cannot do that in your current state."))
return
if(docile)
to_chat(src, span_blue("You are feeling far too docile to do that."))
return
to_chat(src, span_warning("You begin delicately adjusting your connection to the host brain..."))
spawn(100+(host.brainloss*5))
if(!host || !src || controlling)
var/injection_choice = tgui_input_list(src, "Select a chemical to secrete.", "Chemicals", borer_chem_list)
if(injection_choice == "Revive Dead Host")
if(!can_use_power_in_host())
return
else
to_chat(src, span_bolddanger("You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system."))
to_chat(host, span_bolddanger("You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours."))
host.add_language("Cortical Link")
// host -> brain
var/h2b_id = host.computer_id
var/h2b_ip= host.lastKnownIP
host.computer_id = null
host.lastKnownIP = null
qdel(host_brain)
host_brain = new(src)
host_brain.ckey = host.ckey
host_brain.name = host.name
if(!host_brain.computer_id)
host_brain.computer_id = h2b_id
if(!host_brain.lastKnownIP)
host_brain.lastKnownIP = h2b_ip
// self -> host
var/s2h_id = src.computer_id
var/s2h_ip= src.lastKnownIP
src.computer_id = null
src.lastKnownIP = null
host.ckey = src.ckey
if(!host.computer_id)
host.computer_id = s2h_id
if(!host.lastKnownIP)
host.lastKnownIP = s2h_ip
controlling = 1
add_verb(host, /mob/living/carbon/proc/release_control)
add_verb(host, /mob/living/carbon/proc/punish_host)
if(antag)
add_verb(host, /mob/living/carbon/proc/spawn_larvae)
if(controlling)
to_chat(src, span_warning("You cannot do that while in full control of a host."))
return
if(!can_use_power_docile())
return
if(host.stat != DEAD)
to_chat(src, span_danger("Your host must be dead!"))
return
if(HUSK in host.mutations)
to_chat(src, span_danger("Your host is too destroyed to revive."))
return
if(!host.can_defib)
to_chat(src, span_vdanger("Your host's brain is not connected to its body!"))
return
if(!use_chems(BORER_POWER_COST_SECRETE))
return
to_chat(src, span_alien("You squirt an intense mix of chemicals from your reservoirs into [host]'s bloodstream."))
add_attack_logs(src, host, "jumpstart host (borer)")
host.jumpstart()
return
// Is this even legal to do still? We had to wait for a selection...
if(!can_use_power_in_host())
return
if(!can_use_power_docile())
return
if(controlling)
to_chat(src, span_warning("You cannot do that while in full control of a host."))
return
// Get the chem we're injecting
var/list/injection_data = borer_chem_list[injection_choice]
if(!injection_data) //Sanity check.
return
var/injecting_chem = injection_data[1]
var/injectsize = injection_data[2]
if(!injecting_chem || !injectsize)
return
// Finally get to injecting
if(!use_chems(BORER_POWER_COST_SECRETE))
return
var/datum/reagent/inject_reagent = SSchemistry.chemical_reagents[injecting_chem]
if(!inject_reagent)
CRASH("Invalid chem reagent [injecting_chem], in borer chemical injection.")
add_attack_logs(src, host, "chemical injection [inject_reagent] (borer)")
to_chat(src, span_alien("You squirt a measure of [inject_reagent] from your reservoirs into [host]'s bloodstream."))
host.bloodstr.add_reagent(injecting_chem, injectsize)
/// Does some basic regeneration on a host
/mob/living/carbon/human/proc/jumpstart()
set category = "Abilities.Borer"
set name = "Revive Host"
set desc = "Send a jolt of electricity through your host, reviving them."
if(stat != 2)
to_chat(src, "Your host is already alive.")
return
// This is meant to be a bit silly, cause borers don't have much options otherwise
remove_verb(src, /mob/living/carbon/human/proc/jumpstart)
visible_message(span_warning("With a hideous, rattling moan, [src] shudders back to life!"))
visible_message(span_danger("With a hideous, rattling moan, [src] shudders back to life!"))
// Dump damage or we won't be able to revive properly
setHalLoss(0)
setOxyLoss(0)
adjustBruteLoss(-20)
adjustFireLoss(-20)
adjust_nutrition(-200)
// Boilerplate revivial
rejuvenate()
restore_blood()
fixblood()
update_canmove()
// Get some healing in us
bloodstr.add_reagent(REAGENT_BICARIDINE, 5)
bloodstr.add_reagent(REAGENT_KELOTANE, 5)
bloodstr.add_reagent(REAGENT_ID_TRAMADOL, 5)
bloodstr.add_reagent(REAGENT_ID_ALKYSINE, 5)

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