diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 4e64cf6ff7..38a16bdba9 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -53,7 +53,8 @@ Mostly for chomp exclusive stuff, otherwise if you need to modify a base file fo
* For multi-line removals: Use a block comment (/\* xxx \*/) to comment out the existing code block (do not modify whitespace more than necessary) and at the start, it should contain /\* CHOMP Removal - "Reason"
* If it is something like a bugfix that Polaris or Vorestation would want (the codebase we use), you may want to consider coding it there as well. They may want any general gameplay bugfixes, and things that are obviously intended to work one way, but do not. They do not have any of our fluff species (vulp, akula, fenn, etc) so do not make PRs related to that, or any vore content to them.
* Change whitespace as little as possible. Do not randomly add/remove whitespace.
-* Any new files should have "_ch" at the end. For example, "life_ch.dm". Just make them in the same location as the file they are related to.
+* Any new files should preferrably go into the modular_chomp folder following the file structure of where it would be placed normally. The old method was to have "_ch" at the end. For example, "life_ch.dm".
+* Do not make changes to base icon files. New icon files should go into modular_chomp and code should be changed to point to the new file.
* Map changes must be in tgm format. See the [Mapmerge2 Readme] for details, or use [StrongDMM] which can automatically save maps as tgm.
The `attempt_ch()` proc has been added for your convienence. It allows a many-line change to become a single-line change in the existing Polaris files, preserving mergeability and allowing better code separation while preventing your new code from causing runtimes that stop the original code from running. If you are wanting to inject new procedures into an existing proc, called `update_atoms()` for example, you would create `update_atoms_ch()` in a nearby `_ch.dm` file, and then call to it from a single line in the original `update_atoms()` with `attempt_ch()`.
@@ -81,6 +82,12 @@ Then in our `handle_grabs_ch()` proc, if we want to avoid performing the stock g
* Reference issues and pull requests liberally.
* Use the GitHub magic words "Fixed/Fixes/Fix, Resolved/Resolves/Resolve, Closed/Closes/Close", as in, "Closes #1928", as this will automatically close that issue when the PR is merged if it is a fix for that issue.
+### Early porting
+
+* You may earlyport.
+* Follow standard chompcomments incase upstream ends up closing their PR for any reason.
+* If it does get merged upstream and the mirror appears on our repo, you are responsible for unfucking the comments situation, because it'll have to say VORE edits instead of CHOMP edits.
+
## Licensing
CHOMPStation is licensed under the GNU Affero General Public License version 3, which can be found in full in LICENSE-AGPL3.txt.
diff --git a/.github/workflows/autochangelog.yml b/.github/workflows/autochangelog.yml
index cb6ecabe46..c9c628fa29 100644
--- a/.github/workflows/autochangelog.yml
+++ b/.github/workflows/autochangelog.yml
@@ -11,7 +11,7 @@ env:
jobs:
autochangelog:
name: Autochangelog
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
if: github.event.pull_request.merged == true
steps:
- uses: /actions/checkout@v3
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c531d1ffd9..4dcbd75275 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -10,7 +10,7 @@ env:
jobs:
file_tests:
name: Run Linters
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Ensure +x on CI directory
@@ -36,7 +36,7 @@ jobs:
dreamchecker:
name: DreamChecker
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
@@ -57,14 +57,14 @@ jobs:
~/dreamchecker > ${GITHUB_WORKSPACE}/output-annotations.txt 2>&1
- name: Annotate Linter
- uses: yogstation13/DreamAnnotate@v1
+ uses: yogstation13/DreamAnnotate@v2
if: always()
with:
outputFile: output-annotations.txt
unit_tests:
name: Integration Tests
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Ensure +x on CI directory
diff --git a/.github/workflows/render_nanomaps.yml b/.github/workflows/render_nanomaps.yml
index 57f305772c..62076dca06 100644
--- a/.github/workflows/render_nanomaps.yml
+++ b/.github/workflows/render_nanomaps.yml
@@ -11,10 +11,15 @@ on:
paths:
- 'maps/**'
+permissions: {}
jobs:
generate_maps:
+ permissions:
+ contents: write # to push to branch
+ pull-requests: write # to create pull requests (repo-sync/pull-request)
+
name: 'Generate NanoMaps'
- runs-on: ubuntu-latest
+ runs-on: ubuntu-20.04
steps:
- name: Clone
uses: actions/checkout@v3
diff --git a/.gitignore b/.gitignore
index 282f3eabf8..b7121fe8fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,9 +22,6 @@ cfg/
!/.vscode/settings.json
!/.vscode/tasks.json
-code/game/gamemodes/technomancer/spells/projectile/overload.dm
-code/game/gamemodes/technomancer/spells/projectile/overload.dm
-code/modules/client/preference_setup/loadout/loadout_xeno.dm
temp.dmi
node_modules/
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000000..2b7500b231
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,5 @@
+# We don't want prettier to run on anything outside of the TGUI folder, so we have to do this.
+/*
+
+# We want it to run into the TGUI folder, however.
+!/tgui
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 4b96db2f5a..42b452ee25 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -7,7 +7,6 @@
"oderwat.indent-rainbow",
"rexebin.darkpurple-black",
"dbaeumer.vscode-eslint",
- "editorconfig.editorconfig",
"donkie.vscode-tgstation-test-adapter",
"icrawl.discord-vscode",
"esbenp.prettier-vscode"
diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm
index 145381146f..4b8970fd94 100644
--- a/code/ATMOSPHERICS/components/unary/vent_pump.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm
@@ -94,6 +94,13 @@
assign_uid()
id_tag = num2text(uid)
+/obj/machinery/atmospherics/unary/vent_pump/proc/update_area()
+ initial_loc = get_area(loc)
+ area_uid = "\ref[initial_loc]"
+ assign_uid()
+ id_tag = num2text(uid)
+
+
/obj/machinery/atmospherics/unary/vent_pump/Destroy()
unregister_radio(src, frequency)
if(initial_loc)
diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
index 64a57a744e..fe3e68130f 100644
--- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
@@ -43,6 +43,12 @@
assign_uid()
id_tag = num2text(uid)
+/obj/machinery/atmospherics/unary/vent_scrubber/proc/update_area()
+ initial_loc = get_area(loc)
+ area_uid = "\ref[initial_loc]"
+ assign_uid()
+ id_tag = num2text(uid)
+
/obj/machinery/atmospherics/unary/vent_scrubber/Destroy()
unregister_radio(src, frequency)
if(initial_loc)
diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm
index 64b5490472..7a1f5cce95 100644
--- a/code/ATMOSPHERICS/datum_pipeline.dm
+++ b/code/ATMOSPHERICS/datum_pipeline.dm
@@ -161,16 +161,14 @@
if(istype(target, /turf/simulated))
var/turf/simulated/modeled_location = target
-
- if(modeled_location.special_temperature)//First do special interactions then the usuall stuff
- var/delta_temp = modeled_location.special_temperature - air.temperature//2200C - 20C = 2180K
- //assuming aluminium with thermal conductivity 235 W * K / m, Copper (400), Silver (430), steel (50), gold (320)
- var/heat_gain = 23500 * 100 * delta_temp
- air.add_thermal_energy(heat_gain)
- if(network)
- network.update = 1
-
+ if (modeled_location.special_temperature)
+ air.temperature += thermal_conductivity * (modeled_location.special_temperature - air.temperature)
+ if (air.temperature < TCMB)
+ air.temperature = TCMB
+ if (network)
+ network.update = TRUE
+
if(modeled_location.blocks_air)
if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm
index e67d2ad3ac..73ce3f01e8 100644
--- a/code/ZAS/Fire.dm
+++ b/code/ZAS/Fire.dm
@@ -170,7 +170,7 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
continue
//Spread the fire.
- if(prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && my_tile.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, my_tile, 0,0))
+ if(prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && my_tile.CanPass(src, enemy_tile, 0,0) && enemy_tile.CanPass(src, my_tile, 0,0))
enemy_tile.create_fire(firelevel)
else
diff --git a/code/__defines/admin_ch.dm b/code/__defines/admin_ch.dm
new file mode 100644
index 0000000000..cdbc9b064f
--- /dev/null
+++ b/code/__defines/admin_ch.dm
@@ -0,0 +1,2 @@
+#define SMITE_PIE "Pie Splat"
+#define SMITE_SPICE "Spicy Air"
\ No newline at end of file
diff --git a/code/__defines/admin_vr.dm b/code/__defines/admin_vr.dm
index 62c4add906..5cc4ac2299 100644
--- a/code/__defines/admin_vr.dm
+++ b/code/__defines/admin_vr.dm
@@ -1,5 +1,6 @@
#define SMITE_SHADEKIN_ATTACK "Shadekin (Attack)"
#define SMITE_SHADEKIN_NOMF "Shadekin (Devour)"
#define SMITE_REDSPACE_ABDUCT "Redspace Abduction"
+#define SMITE_AD_SPAM "Ad Spam"
#define SMITE_AUTOSAVE "10 Second Autosave"
#define SMITE_AUTOSAVE_WIDE "10 Second Autosave (AoE)"
diff --git a/code/__defines/belly_modes_ch.dm b/code/__defines/belly_modes_ch.dm
index e4b04aa87a..e1bb06b753 100644
--- a/code/__defines/belly_modes_ch.dm
+++ b/code/__defines/belly_modes_ch.dm
@@ -7,3 +7,8 @@
#define DM_FLAG_REAGENTSDIGEST 0x2
#define DM_FLAG_REAGENTSABSORB 0x4
#define DM_FLAG_REAGENTSDRAIN 0x8
+
+//Vore Sprite Flags
+#define DM_FLAG_VORESPRITE_BELLY 0x1
+#define DM_FLAG_VORESPRITE_TAIL 0x2
+#define DM_FLAG_VORESPRITE_MARKING 0x4
\ No newline at end of file
diff --git a/code/__defines/belly_modes_vr.dm b/code/__defines/belly_modes_vr.dm
index 2d8f714fc4..7ac58ddf6b 100644
--- a/code/__defines/belly_modes_vr.dm
+++ b/code/__defines/belly_modes_vr.dm
@@ -21,6 +21,7 @@
#define DM_FLAG_AFFECTWORN 0x10
#define DM_FLAG_JAMSENSORS 0x20
#define DM_FLAG_FORCEPSAY 0x40
+#define DM_FLAG_SLOWBODY 0x80 //CHOMPAdd
//Item related modes
#define IM_HOLD "Hold"
diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index ed22966cbe..abaab99885 100644
--- a/code/__defines/chemistry.dm
+++ b/code/__defines/chemistry.dm
@@ -54,8 +54,9 @@ var/list/cheartstopper = list("potassium_chloride") // Thi
#define MAX_PILL_SPRITE 24 //max icon state of the pill sprites
#define MAX_BOTTLE_SPRITE 4 //max icon state of the pill sprites
+#define MAX_PATCH_SPRITE 4 //max icon state of the patch sprites, CHOMPedit
#define MAX_MULTI_AMOUNT 20 // Max number of pills/patches that can be made at once
#define MAX_UNITS_PER_PILL 60 // Max amount of units in a pill
#define MAX_UNITS_PER_PATCH 60 // Max amount of units in a patch
#define MAX_UNITS_PER_BOTTLE 60 // Max amount of units in a bottle (it's volume)
-#define MAX_CUSTOM_NAME_LEN 64 // Max length of a custom pill/condiment/whatever
\ No newline at end of file
+#define MAX_CUSTOM_NAME_LEN 64 // Max length of a custom pill/condiment/whatever
diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm
index 1ae4237a0d..06fb819b07 100644
--- a/code/__defines/dcs/signals.dm
+++ b/code/__defines/dcs/signals.dm
@@ -400,10 +400,6 @@
///called when removing a given item from a mob, from mob/living/carbon/remove_embedded_object(mob/living/carbon/target, /obj/item)
#define COMSIG_CARBON_EMBED_REMOVAL "item_embed_remove_safe"
-// /mob/living/simple_animal/hostile signals
-#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget"
- #define COMPONENT_HOSTILE_NO_ATTACK (1<<0)
-
// /obj signals
///from base of obj/deconstruct(): (disassembled)
diff --git a/code/__defines/input.dm b/code/__defines/input.dm
index cbc703935a..16afe5a2f3 100644
--- a/code/__defines/input.dm
+++ b/code/__defines/input.dm
@@ -10,7 +10,7 @@
// Combine the held WASD and arrow keys together (OR) into byond N/S/E/W dir
#define MOVEMENT_KEYS_TO_DIR(MK) ((((MK)>>4)|(MK))&(ALL_CARDINALS))
-// Bitflags for pressed modifier keys.
+// Bitflags for pressed modifier keys.
// Values chosen specifically to not conflict with dir bitfield, in case we want to smoosh them together.
#define CTRL_KEY (1<<8)
#define SHIFT_KEY (1<<9)
diff --git a/code/__defines/materials.dm b/code/__defines/materials.dm
index 9536547c1d..e9ec7a357a 100644
--- a/code/__defines/materials.dm
+++ b/code/__defines/materials.dm
@@ -54,6 +54,8 @@
#define MAT_PLATINUM "platinum"
#define MAT_TRITIUM "tritium"
#define MAT_DEUTERIUM "deuterium"
+#define MAT_CONCRETE "concrete"
+#define MAT_PLASTEELREBAR "plasteel rebar"
#define DEFAULT_TABLE_MATERIAL MAT_PLASTIC
diff --git a/code/__defines/misc_ch.dm b/code/__defines/misc_ch.dm
index 0ea4cec334..126c925bba 100644
--- a/code/__defines/misc_ch.dm
+++ b/code/__defines/misc_ch.dm
@@ -1,3 +1,8 @@
+//Department defines
+#define DEPARTMENT_NONCREW "Non crew"
+
+//Job defines
+#define JOB_OUTSIDER "Outsider"
//Material defines
#define MAT_CARPET "red carpet"
@@ -8,4 +13,4 @@
#define MAT_CARPET_SILVERBLUE "silver blue carpet"
#define MAT_CARPET_PINK "pink carpet"
#define MAT_CARPET_PURPLE "purple carpet"
-#define MAT_CARPET_ORANGE "orange carpet"
\ No newline at end of file
+#define MAT_CARPET_ORANGE "orange carpet"
diff --git a/code/__defines/mobs_vr.dm b/code/__defines/mobs_vr.dm
index be17f09c39..253cde36e9 100644
--- a/code/__defines/mobs_vr.dm
+++ b/code/__defines/mobs_vr.dm
@@ -25,6 +25,7 @@
#define SPECIES_PROTEAN "Protean"
#define SPECIES_RAPALA "Rapala"
#define SPECIES_SERGAL "Sergal"
+#define SPECIES_ALTEVIAN "Altevian"
#define SPECIES_SHADEKIN_CREW "Black-Eyed Shadekin"
#define SPECIES_VASILISSAN "Vasilissan"
#define SPECIES_VULPKANIN "Vulpkanin"
@@ -42,3 +43,9 @@
//custom species base sprites
#define SPECIES_FENNEC "Fennec"
#define SPECIES_XENOHYBRID "Xenohybrid"
+
+//for custom bodytypes
+
+#define SELECTS_BODYTYPE_FALSE 0
+#define SELECTS_BODYTYPE_CUSTOM 1
+#define SELECTS_BODYTYPE_SHAPESHIFTER 2
diff --git a/code/__defines/nifsoft.dm b/code/__defines/nifsoft.dm
index cca614f1fb..114ee32779 100644
--- a/code/__defines/nifsoft.dm
+++ b/code/__defines/nifsoft.dm
@@ -40,9 +40,10 @@
#define NIF_SIZECHANGE 33
#define NIF_SOULCATCHER 34
#define NIF_WORLDBEND 35
+#define NIF_MALWARE 36
// Must be equal to the highest number above
-#define TOTAL_NIF_SOFTWARE 35
+#define TOTAL_NIF_SOFTWARE 36
//////////////////////
// NIF flag list hints
diff --git a/code/__defines/planets.dm b/code/__defines/planets.dm
index da67d42ea2..3579cc804d 100644
--- a/code/__defines/planets.dm
+++ b/code/__defines/planets.dm
@@ -11,6 +11,7 @@
#define WEATHER_BLOOD_MOON "blood moon" // For admin fun or cult later on.
#define WEATHER_EMBERFALL "emberfall" // More adminbuse, from TG. Harmless.
#define WEATHER_ASH_STORM "ash storm" // Ripped from TG, like the above. Less harmless.
+#define WEATHER_ASH_STORM_SAFE "light ash storm" //Safe version of the ash storm. Dimmer.
#define WEATHER_FALLOUT "fallout" // Modified emberfall, actually harmful. Admin only.
#define MOON_PHASE_NEW_MOON "new moon"
diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm
index f81e48b044..b133acc9ec 100644
--- a/code/__defines/species_languages.dm
+++ b/code/__defines/species_languages.dm
@@ -86,18 +86,15 @@
#define LANGUAGE_ROOTLOCAL "Local Rootspeak"
#define LANGUAGE_ROOTGLOBAL "Global Rootspeak"
#define LANGUAGE_CULT "Cult"
-#define LANGUAGE_OCCULT "Occult"
#define LANGUAGE_CHANGELING "Changeling"
#define LANGUAGE_VOX "Vox-Pidgin"
#define LANGUAGE_TERMINUS "Terminus"
-#define LANGUAGE_SKRELLIANFAR "High Skrellian"
#define LANGUAGE_MINBUS "Minbus"
#define LANGUAGE_EVENT1 "Occursus"
#define LANGUAGE_AKHANI "Akhani"
#define LANGUAGE_ALAI "Alai"
#define LANGUAGE_ZADDAT "Vedahq"
#define LANGUAGE_PROMETHEAN "Promethean Biolinguistics"
-#define LANGUAGE_BLOB "Chemosense Transmission"
#define LANGUAGE_GIBBERISH "Babel"
// Language flags.
diff --git a/code/__defines/species_languages_vr.dm b/code/__defines/species_languages_vr.dm
index 1a5fbdab4c..7980683f9c 100644
--- a/code/__defines/species_languages_vr.dm
+++ b/code/__defines/species_languages_vr.dm
@@ -1,7 +1,7 @@
#define SPECIES_WHITELIST_SELECTABLE 0x20 // Can select and customize, but not join as
#define LANGUAGE_DRUDAKAR "D'Rudak'Ar"
-#define LANGUAGE_SLAVIC "Pan-Slavic"
+#define LANGUAGE_SLAVIC "Pan-Slavic" //CHOMP reAdd
#define LANGUAGE_BIRDSONG "Birdsong"
#define LANGUAGE_SAGARU "Sagaru"
#define LANGUAGE_CANILUNZT "Canilunzt"
@@ -10,13 +10,11 @@
#define LANGUAGE_ENOCHIAN "Enochian"
#define LANGUAGE_VESPINAE "Vespinae"
#define LANGUAGE_SPACER "Spacer"
-#define LANGUAGE_CLOWNISH "Coulrian"
#define LANGUAGE_TAVAN "Tavan"
#define LANGUAGE_ECHOSONG "Echo Song"
-#define LANGUAGE_CHIMPANZEE "Chimpanzee"
-#define LANGUAGE_NEAERA "Neaera"
-#define LANGUAGE_STOK "Stok"
-#define LANGUAGE_FARWA "Farwa"
+#define LANGUAGE_ANIMAL "Animal"
+#define LANGUAGE_TEPPI "Teppi"
+#define LANGUAGE_MOUSE "Mouse"
#define LANGUAGE_SHADEKIN "Shadekin Empathy"
diff --git a/code/__defines/sprite_sheets.dm b/code/__defines/sprite_sheets.dm
index 603bb82d5f..2194efca23 100644
--- a/code/__defines/sprite_sheets.dm
+++ b/code/__defines/sprite_sheets.dm
@@ -11,7 +11,8 @@ SPECIES_SERGAL = 'icons/inventory/suit/mob_vr_sergal.dmi',\
SPECIES_NEVREAN = 'icons/inventory/suit/mob_vr_sergal.dmi',\
SPECIES_VULPKANIN = 'icons/inventory/suit/mob_vr_vulpkanin.dmi',\
SPECIES_ZORREN_HIGH = 'icons/inventory/suit/mob_vr_vulpkanin.dmi',\
-SPECIES_FENNEC = 'icons/inventory/suit/mob_vr_vulpkanin.dmi')
+SPECIES_FENNEC = 'icons/inventory/suit/mob_vr_vulpkanin.dmi',\
+SPECIES_ALTEVIAN = 'icons/inventory/suit/mob_vr_altevian.dmi')
#define VR_SPECIES_SPRITE_SHEETS_HEAD_MOB list(\
SPECIES_HUMAN = 'icons/inventory/head/mob.dmi',\
SPECIES_TAJ = 'icons/inventory/head/mob_tajaran.dmi',\
@@ -24,7 +25,8 @@ SPECIES_SERGAL = 'icons/inventory/head/mob_vr_sergal.dmi',\
SPECIES_NEVREAN = 'icons/inventory/head/mob_vr_sergal.dmi',\
SPECIES_VULPKANIN = 'icons/inventory/head/mob_vr_vulpkanin.dmi',\
SPECIES_ZORREN_HIGH = 'icons/inventory/head/mob_vr_vulpkanin.dmi',\
-SPECIES_FENNEC = 'icons/inventory/head/mob_vr_vulpkanin.dmi')
+SPECIES_FENNEC = 'icons/inventory/head/mob_vr_vulpkanin.dmi',\
+SPECIES_ALTEVIAN = 'icons/inventory/head/mob_vr_altevian.dmi')
#define VR_SPECIES_SPRITE_SHEETS_HANDS_MOB list(\
SPECIES_HUMAN = 'icons/inventory/hands/mob.dmi',\
SPECIES_TAJ = 'icons/inventory/hands/mob_tajaran.dmi',\
@@ -64,7 +66,8 @@ SPECIES_SERGAL = 'icons/inventory/suit/item_vr_sergal.dmi',\
SPECIES_NEVREAN = 'icons/inventory/suit/item_vr_sergal.dmi',\
SPECIES_VULPKANIN = 'icons/inventory/suit/item_vr_vulpkanin.dmi',\
SPECIES_ZORREN_HIGH = 'icons/inventory/suit/item_vr_vulpkanin.dmi',\
-SPECIES_FENNEC = 'icons/inventory/suit/item_vr_vulpkanin.dmi')
+SPECIES_FENNEC = 'icons/inventory/suit/item_vr_vulpkanin.dmi',\
+SPECIES_ALTEVIAN = 'icons/inventory/suit/item_vr_altevian.dmi')
#define VR_SPECIES_SPRITE_SHEETS_HEAD_ITEM list(\
SPECIES_HUMAN = 'icons/inventory/head/item.dmi',\
SPECIES_TAJ = 'icons/inventory/head/item_tajaran.dmi',\
@@ -77,7 +80,8 @@ SPECIES_SERGAL = 'icons/inventory/head/item_vr_sergal.dmi',\
SPECIES_NEVREAN = 'icons/inventory/head/item_vr_sergal.dmi',\
SPECIES_VULPKANIN = 'icons/inventory/head/item_vr_vulpkanin.dmi',\
SPECIES_ZORREN_HIGH = 'icons/inventory/head/item_vr_vulpkanin.dmi',\
-SPECIES_FENNEC = 'icons/inventory/head/item_vr_vulpkanin.dmi')
+SPECIES_FENNEC = 'icons/inventory/head/item_vr_vulpkanin.dmi',\
+SPECIES_ALTEVIAN = 'icons/inventory/head/item_vr_altevian.dmi')
#define VR_SPECIES_SPRITE_SHEETS_HANDS_ITEM list(\
SPECIES_HUMAN = 'icons/inventory/hands/item.dmi',\
SPECIES_TAJ = 'icons/inventory/hands/item_tajaran.dmi',\
@@ -118,7 +122,8 @@ SPECIES_SERGAL = 'icons/inventory/suit/mob_vr_sergal.dmi',\
SPECIES_NEVREAN = 'icons/inventory/suit/mob_vr_sergal.dmi',\
SPECIES_VULPKANIN = 'icons/inventory/suit/mob_vr_vulpkanin.dmi',\
SPECIES_ZORREN_HIGH = 'icons/inventory/suit/mob_vr_vulpkanin.dmi',\
-SPECIES_FENNEC = 'icons/inventory/suit/mob_vr_vulpkanin.dmi')
+SPECIES_FENNEC = 'icons/inventory/suit/mob_vr_vulpkanin.dmi',\
+SPECIES_ALTEVIAN = 'icons/inventory/suit/mob_vr_altevian.dmi')
#define ALL_VR_SPRITE_SHEETS_HEAD_MOB list(\
SPECIES_HUMAN = 'icons/inventory/head/mob_vr.dmi',\
SPECIES_TAJ = 'icons/inventory/head/mob_vr_tajaran.dmi',\
@@ -131,7 +136,8 @@ SPECIES_SERGAL = 'icons/inventory/head/mob_vr_sergal.dmi',\
SPECIES_NEVREAN = 'icons/inventory/head/mob_vr_sergal.dmi',\
SPECIES_VULPKANIN = 'icons/inventory/head/mob_vr_vulpkanin.dmi',\
SPECIES_ZORREN_HIGH = 'icons/inventory/head/mob_vr_vulpkanin.dmi',\
-SPECIES_FENNEC = 'icons/inventory/head/mob_vr_vulpkanin.dmi')
+SPECIES_FENNEC = 'icons/inventory/head/mob_vr_vulpkanin.dmi',\
+SPECIES_ALTEVIAN = 'icons/inventory/head/mob_vr_altevian.dmi')
#define ALL_VR_SPRITE_SHEETS_HANDS_MOB list(\
SPECIES_HUMAN = 'icons/inventory/hands/mob_vr.dmi',\
SPECIES_TAJ = 'icons/inventory/hands/mob_vr_tajaran.dmi',\
@@ -171,7 +177,8 @@ SPECIES_SERGAL = 'icons/inventory/suit/item_vr_sergal.dmi',\
SPECIES_NEVREAN = 'icons/inventory/suit/item_vr_sergal.dmi',\
SPECIES_VULPKANIN = 'icons/inventory/suit/item_vr_vulpkanin.dmi',\
SPECIES_ZORREN_HIGH = 'icons/inventory/suit/item_vr_vulpkanin.dmi',\
-SPECIES_FENNEC = 'icons/inventory/suit/item_vr_vulpkanin.dmi')
+SPECIES_FENNEC = 'icons/inventory/suit/item_vr_vulpkanin.dmi',\
+SPECIES_ALTEVIAN = 'icons/inventory/suit/item_vr_altevian.dmi')
#define ALL_VR_SPRITE_SHEETS_HEAD_ITEM list(\
SPECIES_HUMAN = 'icons/inventory/head/item_vr.dmi',\
SPECIES_TAJ = 'icons/inventory/head/item_vr_tajaran.dmi',\
@@ -184,7 +191,8 @@ SPECIES_SERGAL = 'icons/inventory/head/item_vr_sergal.dmi',\
SPECIES_NEVREAN = 'icons/inventory/head/item_vr_sergal.dmi',\
SPECIES_VULPKANIN = 'icons/inventory/head/item_vr_vulpkanin.dmi',\
SPECIES_ZORREN_HIGH = 'icons/inventory/head/item_vr_vulpkanin.dmi',\
-SPECIES_FENNEC = 'icons/inventory/head/item_vr_vulpkanin.dmi')
+SPECIES_FENNEC = 'icons/inventory/head/item_vr_vulpkanin.dmi',\
+SPECIES_ALTEVIAN = 'icons/inventory/head/item_vr_altevian.dmi')
#define ALL_VR_SPRITE_SHEETS_HANDS_ITEM list(\
SPECIES_HUMAN = 'icons/inventory/hands/item_vr.dmi',\
SPECIES_TAJ = 'icons/inventory/hands/item_vr_tajaran.dmi',\
diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm
index cb30162b73..0a8b333956 100644
--- a/code/__defines/subsystems.dm
+++ b/code/__defines/subsystems.dm
@@ -119,26 +119,3 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_CHAT 400
#define FIRE_PRIORITY_OVERLAYS 500
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
-
-// Macro defining the actual code applying our overlays lists to the BYOND overlays list. (I guess a macro for speed)
-// TODO - I don't really like the location of this macro define. Consider it. ~Leshana
-#define COMPILE_OVERLAYS(A)\
- do {\
- var/list/oo = A.our_overlays;\
- var/list/po = A.priority_overlays;\
- if(LAZYLEN(po)){\
- if(LAZYLEN(oo)){\
- A.overlays = oo + po;\
- }\
- else{\
- A.overlays = po;\
- }\
- }\
- else if(LAZYLEN(oo)){\
- A.overlays = oo;\
- }\
- else{\
- A.overlays.Cut();\
- }\
- A.flags &= ~OVERLAY_QUEUED;\
- } while (FALSE)
diff --git a/code/__defines/turfs.dm b/code/__defines/turfs.dm
index 1c4b228b63..fe327cd632 100644
--- a/code/__defines/turfs.dm
+++ b/code/__defines/turfs.dm
@@ -28,3 +28,12 @@
#define OUTDOORS_NO 0 // Ditto.
#define OUTDOORS_AREA -1 // If a turf has this, it will defer to the area's settings on init.
// Note that after init, it will be either YES or NO.
+
+//supposedly the fastest way to do this according to https://gist.github.com/Giacom/be635398926bb463b42a
+///Returns a list of turf in a square
+
+#define RECT_TURFS(H_RADIUS, V_RADIUS, CENTER) \
+ block( \
+ locate(max(CENTER.x-(H_RADIUS),1), max(CENTER.y-(V_RADIUS),1), CENTER.z), \
+ locate(min(CENTER.x+(H_RADIUS),world.maxx), min(CENTER.y+(V_RADIUS),world.maxy), CENTER.z) \
+ )
\ No newline at end of file
diff --git a/code/__defines/spaceman_dmm.dm b/code/__spaceman_dmm.dm
similarity index 85%
rename from code/__defines/spaceman_dmm.dm
rename to code/__spaceman_dmm.dm
index 94f1743377..51b09cd036 100644
--- a/code/__defines/spaceman_dmm.dm
+++ b/code/__spaceman_dmm.dm
@@ -1,7 +1,8 @@
-// Interfaces for the SpacemanDMM linter, define'd to nothing when the linter
-// is not in use.
+/**
+* SpacemanDMM dreamchecker extensions for suite 1.7
+* According to the [src.name], you are now in an unclaimed territory. This place is not noted on the [src.name]. Create or modify an existing area (3x3 space) (1 Charge) Create new area or merge two areas. (Whole Room.) (5 Charges)
Examples include:")
+ var/good_num = 5
+ var/ourticket
+ while(good_num > 0)
+ ourticket = null
+ if(security_printer_tickets.len)
+ ourticket = pick(security_printer_tickets)
+ security_printer_tickets -= ourticket
+ if(ourticket)
+ valid_stats_list.Add("-\"[ourticket]\"")
+ good_num--
+ else
+ good_num = 0
+
//VOREStation Add Start - Vore stats lets gooooo
if(GLOB.prey_eaten_roundstat > 0)
valid_stats_list.Add("A total of [GLOB.prey_eaten_roundstat] individuals were eaten today!")
diff --git a/code/datums/supplypacks/engineering.dm b/code/datums/supplypacks/engineering.dm
index c35d048f54..0529f5aedd 100644
--- a/code/datums/supplypacks/engineering.dm
+++ b/code/datums/supplypacks/engineering.dm
@@ -77,6 +77,20 @@
containertype = /obj/structure/closet/crate/focalpoint
containername = "advanced hull shield generator crate"
+/datum/supply_pack/eng/point_defense_cannon_circuit
+ name = "Point Defense Turret Circuit"
+ contains = list(/obj/item/weapon/circuitboard/pointdefense = 2)
+ cost = 20
+ containertype = /obj/structure/closet/crate/heph
+ containername = "point defense turret circuit crate"
+
+/datum/supply_pack/eng/point_defense_control_circuit
+ name = "Point Defense Controller Circuit"
+ contains = list(/obj/item/weapon/circuitboard/pointdefense_control = 1)
+ cost = 30
+ containertype = /obj/structure/closet/crate/heph
+ containername = "point defense mainframe circuit crate"
+
/datum/supply_pack/eng/electrical
name = "Electrical maintenance crate"
contains = list(
diff --git a/code/datums/supplypacks/hospitality.dm b/code/datums/supplypacks/hospitality.dm
index bcf472a0b9..544ad90b6e 100644
--- a/code/datums/supplypacks/hospitality.dm
+++ b/code/datums/supplypacks/hospitality.dm
@@ -47,7 +47,7 @@
cost = 10
containertype = /obj/structure/closet/crate/gilthari
containername = "crate of bar supplies"
-
+
/datum/supply_pack/hospitality/cookingoil
name = "Cooking oil tank crate"
contains = list(/obj/structure/reagent_dispensers/cookingoil)
@@ -96,6 +96,15 @@
containertype = /obj/structure/closet/crate/centauri
containername = "Painting equipment"
+/datum/supply_pack/hospitality/holywater
+ name = "Holy water crate"
+ contains = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater = 3
+ )
+ cost = 15
+ containertype = /obj/structure/closet/crate/gilthari
+ containername = "holy water crate"
+
/datum/supply_pack/randomised/hospitality/
group = "Hospitality"
diff --git a/code/datums/supplypacks/hydroponics_vr.dm b/code/datums/supplypacks/hydroponics_vr.dm
index 7476fdd29b..fa912852e7 100644
--- a/code/datums/supplypacks/hydroponics_vr.dm
+++ b/code/datums/supplypacks/hydroponics_vr.dm
@@ -70,4 +70,10 @@
name = "Jerboa crate"
cost = 10
containertype = /obj/structure/largecrate/animal/jerboa
- containername = "Jerboa crate"
\ No newline at end of file
+ containername = "Jerboa crate"
+
+/datum/supply_pack/hydro/tits
+ name = "A pair of great tits"
+ cost = 10
+ containertype = /obj/structure/largecrate/tits
+ containername = "A pair of great tits"
diff --git a/code/datums/supplypacks/materials.dm b/code/datums/supplypacks/materials.dm
index 3268d05a46..d06238dc41 100644
--- a/code/datums/supplypacks/materials.dm
+++ b/code/datums/supplypacks/materials.dm
@@ -83,4 +83,11 @@
containertype = /obj/structure/closet/crate/grayson
containername = "Linoleum crate"
cost = 15
- contains = list(/obj/fiftyspawner/linoleum)
\ No newline at end of file
+ contains = list(/obj/fiftyspawner/linoleum)
+
+/datum/supply_pack/materials/concrete
+ name = "Concrete"
+ cost = 10
+ containertype = /obj/structure/closet/crate/grayson
+ contains = list(/obj/fiftyspawner/concrete)
+ containername = "Concrete bricks crate"
\ No newline at end of file
diff --git a/code/datums/supplypacks/misc_vr.dm b/code/datums/supplypacks/misc_vr.dm
index dbe2143e03..8118ff0ab1 100644
--- a/code/datums/supplypacks/misc_vr.dm
+++ b/code/datums/supplypacks/misc_vr.dm
@@ -161,3 +161,18 @@
cost = 300
containertype = /obj/structure/closet/crate
containername = "cordless jukebox speakers crate"
+
+/datum/supply_pack/misc/explorer_headsets
+ name = "shortwave-capable headsets (x4)"
+ contains = list(
+ /obj/item/device/radio/headset/explorer = 4
+ )
+ cost = 20
+ containertype = /obj/structure/closet/crate/secure/gear
+ containername = "exploration radio headsets crate"
+ access = list(
+ access_explorer,
+ access_eva,
+ access_pilot
+ )
+ one_access = TRUE
diff --git a/code/datums/supplypacks/munitions.dm b/code/datums/supplypacks/munitions.dm
index 73d150fd03..64567176a0 100644
--- a/code/datums/supplypacks/munitions.dm
+++ b/code/datums/supplypacks/munitions.dm
@@ -75,6 +75,19 @@
containername = "Shotgun crate"
access = access_armory
/* VOREStation edit -- This is a bad idea. -- So is this.
+
+/datum/supply_pack/munitions/shotgunsemi
+ name = "Weapons - Semi-Automatic Shotgun crate"
+ contains = list(
+ /obj/item/ammo_magazine/ammo_box/b12g,
+ /obj/item/ammo_magazine/ammo_box/b12g/pellet,
+ /obj/item/weapon/gun/projectile/shotgun/semi = 2
+ )
+ cost = 100
+ containertype = /obj/structure/closet/crate/secure/weapon
+ containername = "Semi-Auto Shotgun crate"
+ access = access_armory
+
/datum/supply_pack/munitions/erifle
name = "Weapons - Energy marksman"
contains = list(/obj/item/weapon/gun/energy/sniperrifle = 2)
@@ -307,4 +320,4 @@
cost = 500
containertype = /obj/structure/closet/crate/secure
containername = "Light machine gun crate"
- access = access_armory
\ No newline at end of file
+ access = access_armory
diff --git a/code/datums/supplypacks/science_vr.dm b/code/datums/supplypacks/science_vr.dm
index 1d9922e7d8..2e9f756aa2 100644
--- a/code/datums/supplypacks/science_vr.dm
+++ b/code/datums/supplypacks/science_vr.dm
@@ -29,7 +29,7 @@
containertype = /obj/structure/largecrate/animal/weretiger
containername = "Weretiger crate"
access = access_xenobiology
-/*
+
/datum/supply_pack/sci/otie
name = "VARMAcorp adoptable reject (Dangerous!)"
cost = 100
@@ -43,4 +43,3 @@
containertype = /obj/structure/largecrate/animal/otie/phoron
containername = "VARMAcorp adaptive beta subject (Experimental)"
access = access_xenobiology
-*/ //VORESTATION AI TEMPORARY REMOVAL. Oties commented out cuz broke.
diff --git a/code/datums/supplypacks/security.dm b/code/datums/supplypacks/security.dm
index 5c4ddf1a6a..fc8d9b373b 100644
--- a/code/datums/supplypacks/security.dm
+++ b/code/datums/supplypacks/security.dm
@@ -444,7 +444,8 @@
/obj/item/weapon/storage/belt/security = 3,
/obj/item/clothing/glasses/sunglasses/sechud = 3,
/obj/item/device/radio/headset/headset_sec/alt = 3,
- /obj/item/clothing/suit/storage/hooded/wintercoat/security = 3
+ /obj/item/clothing/suit/storage/hooded/wintercoat/security = 3,
+ /obj/item/clothing/glasses/sunglasses/sechud/tactical_sec_vis = 3
)
cost = 10
containertype = /obj/structure/closet/crate/nanothreads
diff --git a/code/datums/supplypacks/security_vr.dm b/code/datums/supplypacks/security_vr.dm
index a00556e528..bbb28e08fb 100644
--- a/code/datums/supplypacks/security_vr.dm
+++ b/code/datums/supplypacks/security_vr.dm
@@ -1,4 +1,4 @@
-/*/datum/supply_pack/security/guardbeast //VORESTATION AI TEMPORARY REMOVAL
+/datum/supply_pack/security/guardbeast
name = "VARMAcorp autoNOMous security solution"
cost = 150
containertype = /obj/structure/largecrate/animal/guardbeast
@@ -17,7 +17,6 @@
access_security,
access_xenobiology)
one_access = TRUE
-*/
/datum/supply_pack/randomised/security/armor
access = access_armory
diff --git a/code/datums/supplypacks/vending_refills_vr.dm b/code/datums/supplypacks/vending_refills_vr.dm
index 47ee538d7e..bfa42113f7 100644
--- a/code/datums/supplypacks/vending_refills_vr.dm
+++ b/code/datums/supplypacks/vending_refills_vr.dm
@@ -18,11 +18,6 @@
name = "SweatMAX Vendor Refill Cartridge"
cost = 10
-/datum/supply_pack/vending_refills/hotfood
- contains = list(/obj/item/weapon/refill_cartridge/autoname/food/hotfood)
- name = "Hot Foods Vendor Refill Cartridge"
- cost = 10
-
/datum/supply_pack/vending_refills/weeb
contains = list(/obj/item/weapon/refill_cartridge/autoname/food/weeb)
name = "Nippon-tan Vendor Refill Cartridge"
@@ -48,6 +43,11 @@
name = "Ration Station Vendor Refill Cartridge"
cost = 10
+/datum/supply_pack/vending_refills/altevian
+ contains = list(/obj/item/weapon/refill_cartridge/autoname/food/altevian)
+ name = "Altevian Vendor Refill Cartridge"
+ cost = 10
+
/datum/supply_pack/vending_refills/coffee
contains = list(/obj/item/weapon/refill_cartridge/autoname/drink/coffee)
name = "Hot Drinks Vendor Refill Cartridge"
@@ -117,7 +117,6 @@
num_contained = 5
contains = list(/obj/item/weapon/refill_cartridge/autoname/food/snack,
/obj/item/weapon/refill_cartridge/autoname/food/fitness,
- /obj/item/weapon/refill_cartridge/autoname/food/hotfood,
/obj/item/weapon/refill_cartridge/autoname/food/weeb,
/obj/item/weapon/refill_cartridge/autoname/food/sol,
/obj/item/weapon/refill_cartridge/autoname/food/snix,
diff --git a/code/datums/supplypacks/voidsuits.dm b/code/datums/supplypacks/voidsuits.dm
index f8e091bb3d..c28b3e9559 100644
--- a/code/datums/supplypacks/voidsuits.dm
+++ b/code/datums/supplypacks/voidsuits.dm
@@ -259,4 +259,20 @@
cost = 80
containertype = /obj/structure/closet/crate/oculum
containername = "Vox Civilian Hardsuit"
+
+/datum/supply_pack/voidsuits/voxeng
+ name = "Vox Engineering Hardsuit"
+ contains = list (/obj/item/weapon/rig/vox/engineering)
+ cost = 150
+ containertype = /obj/structure/closet/crate/oculum
+ containername = "Vox Engineering Hardsuit"
+
+/datum/supply_pack/voidsuits/voxsec
+ name = "Vox Security Hardsuit"
+ contains = list (/obj/item/weapon/rig/vox/security)
+ cost = 90
+ containertype = /obj/structure/closet/crate/secure/heph
+ containername = "Vox security Rigsuit Crate"
+ access = access_security
+
//ChompEdit End
diff --git a/code/datums/underwear/socks.dm b/code/datums/underwear/socks.dm
index e1fe7e07f2..16465cfb61 100644
--- a/code/datums/underwear/socks.dm
+++ b/code/datums/underwear/socks.dm
@@ -60,4 +60,128 @@
/datum/category_item/underwear/socks/leggings
name = "Leggings"
- icon_state = "leggings"
\ No newline at end of file
+ icon_state = "leggings"
+
+
+
+//NEW SOCKS BELOW HERE
+/datum/category_item/underwear/socks/white_norm
+ name = "White Socks"
+ icon_state = "white_norm"
+ has_color = TRUE
+
+/datum/category_item/underwear/socks/white_short
+ name = "Short White Socks"
+ icon_state = "white_short"
+ has_color = TRUE
+
+/datum/category_item/underwear/socks/white_knee
+ name = "White Knee Socks"
+ icon_state = "white_knee"
+ has_color = TRUE
+
+/datum/category_item/underwear/socks/white_thigh
+ name = "White Thigh Socks"
+ icon_state = "white_thigh"
+ has_color = TRUE
+
+/datum/category_item/underwear/socks/black_norm
+ name = "Black Socks"
+ icon_state = "black_norm"
+
+/datum/category_item/underwear/socks/black_short
+ name = "Short Black Socks"
+ icon_state = "black_short"
+
+/datum/category_item/underwear/socks/black_knee
+ name = "Black Knee Socks"
+ icon_state = "black_knee"
+
+/datum/category_item/underwear/socks/black_thigh
+ name = "Black Thigh Socks"
+ icon_state = "black_thigh"
+
+/datum/category_item/underwear/socks/assblastusa_knee
+ name = "Striped Patriotic Knee Socks"
+ icon_state = "assblastusa_knee"
+
+/datum/category_item/underwear/socks/assblastusa_thigh
+ name = "Striped Patriotic Thigh Socks"
+ icon_state = "assblastusa_thigh"
+
+/datum/category_item/underwear/socks/uk_knee
+ name = "United Kingdom Knee Socks"
+ icon_state = "uk_knee"
+
+/datum/category_item/underwear/socks/uk_thigh
+ name = "United Kingdom Thigh Socks"
+ icon_state = "uk_thigh"
+
+/datum/category_item/underwear/socks/commie_knee
+ name = "Yellow and Red Striped Knee Socks"
+ icon_state = "commie_knee"
+
+/datum/category_item/underwear/socks/commie_thigh
+ name = "Yellow and Red Striped Thigh Socks"
+ icon_state = "commie_thigh"
+
+/datum/category_item/underwear/socks/stockings_lpink
+ name = "Light Pink Stockings"
+ icon_state = "stockings_lpink"
+
+/datum/category_item/underwear/socks/stockings_purple
+ name = "Purple Stockings"
+ icon_state = "stockings_purple"
+
+/datum/category_item/underwear/socks/stockings_green
+ name = "Green Stockings"
+ icon_state = "stockings_green"
+
+/datum/category_item/underwear/socks/stockings_cyan
+ name = "Cyan Stockings"
+ icon_state = "stockings_cyan"
+
+/datum/category_item/underwear/socks/stockings_orange
+ name = "Orange Stockings"
+ icon_state = "stockings_orange"
+
+/datum/category_item/underwear/socks/stockings_yellow
+ name = "Yellow Stockings"
+ icon_state = "stockings_yellow"
+
+/datum/category_item/underwear/socks/stockings_dpink
+ name = "Dark Pink Stockings"
+ icon_state = "stockings_dpink"
+
+/datum/category_item/underwear/socks/stockings_blue
+ name = "Blue Stockings"
+ icon_state = "stockings_blue"
+
+/datum/category_item/underwear/socks/bee_thigh
+ name = "Bee Thigh Socks"
+ icon_state = "bee_thigh"
+
+/datum/category_item/underwear/socks/bee_knee
+ name = "Bee Knee Socks" //You do not know how much I want to make a 'bee's knees' pun.
+ icon_state = "bee_knee"
+
+/datum/category_item/underwear/socks/thocks
+ name = "Thocks"
+ icon_state = "thocks"
+ has_color = TRUE
+
+/datum/category_item/underwear/socks/ace_thigh
+ name = "Ace Pride Thigh Socks"
+ icon_state = "ace_thigh"
+
+/datum/category_item/underwear/socks/ace_knee
+ name = "Ace Pride Knee Socks"
+ icon_state = "ace_knee"
+
+/datum/category_item/underwear/socks/trans_knee
+ name = "Trans Pride Knee Socks"
+ icon_state = "trans_knee"
+
+/datum/category_item/underwear/socks/trans_thigh
+ name = "Trans Pride Thigh Socks"
+ icon_state = "trans_thigh"
diff --git a/code/datums/uplink/armor.dm b/code/datums/uplink/armor.dm
index 0d7d814310..362aec5d92 100644
--- a/code/datums/uplink/armor.dm
+++ b/code/datums/uplink/armor.dm
@@ -6,25 +6,25 @@
/datum/uplink_item/item/armor/combat
name = "Combat Armor Set"
- item_cost = 60
+ item_cost = 30
path = /obj/item/weapon/storage/box/syndie_kit/combat_armor
/datum/uplink_item/item/armor/heavy_vest
name = "Heavy Armor Vest"
- item_cost = 40
+ item_cost = 20
path = /obj/item/clothing/suit/storage/vest/heavy/merc
/datum/uplink_item/item/armor/gorlexsuit
name = "Mercenary Voidsuit"
- item_cost = 40
+ item_cost = 20
path = /obj/item/weapon/storage/box/syndie_kit/voidsuit
/datum/uplink_item/item/armor/gorlexsuit_fire
name = "Mercenary Voidsuit (Fire)"
- item_cost = 40
+ item_cost = 20
path = /obj/item/weapon/storage/box/syndie_kit/voidsuit/fire
/datum/uplink_item/item/armor/combat
name = "Combat Platecarrier Set"
- item_cost = 60
+ item_cost = 30
path = /obj/item/clothing/suit/armor/pcarrier/merc
diff --git a/code/datums/uplink/medical.dm b/code/datums/uplink/medical.dm
index c7b0b0d123..c1ff848877 100644
--- a/code/datums/uplink/medical.dm
+++ b/code/datums/uplink/medical.dm
@@ -6,88 +6,108 @@
/datum/uplink_item/item/medical/onegativeblood
name = "O- Blood Pack"
- item_cost = 5
+ item_cost = 1
path = /obj/item/weapon/reagent_containers/blood/OMinus
/datum/uplink_item/item/medical/sinpockets
name = "Box of Sin-Pockets"
- item_cost = 5
+ item_cost = 1
path = /obj/item/weapon/storage/box/sinpockets
/datum/uplink_item/item/medical/ambrosiaseeds
name = "Box of 7x ambrosia seed packets"
- item_cost = 5
+ item_cost = 1
path = /obj/item/weapon/storage/box/ambrosia
/datum/uplink_item/item/medical/clotting
name = "Clotting Medicine injector"
- item_cost = 10
+ item_cost = 5
path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting
/datum/uplink_item/item/medical/clotting_case
name = "Clotting Medicine case"
- item_cost = 20
+ item_cost = 10
desc = "A case of three myelamine injectors. Can rapidly remove and stow up to six injectors."
path = /obj/item/weapon/storage/quickdraw/syringe_case/clotting
/datum/uplink_item/item/medical/bonemeds
name = "Bone Repair injector"
- item_cost = 10
+ item_cost = 5
path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/bonemed
/datum/uplink_item/item/medical/clonemeds
name = "Clone injector"
- item_cost = 15
+ item_cost = 5
path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/clonemed
/datum/uplink_item/item/medical/bonemeds_case
name = "Bone Repair case"
- item_cost = 20
+ item_cost = 10
desc = "A case of three osteodaxon injectors. Can rapidly remove and stow up to six injectors."
path = /obj/item/weapon/storage/quickdraw/syringe_case/bonemed
/datum/uplink_item/item/medical/clonemeds_case
name = "Clone case"
- item_cost = 30
+ item_cost = 10
desc = "A case of three rezadone injectors. Can rapidly remove and stow up to six injectors."
path = /obj/item/weapon/storage/quickdraw/syringe_case/clonemed
/datum/uplink_item/item/medical/ambrosiadeusseeds
name = "Box of 7x ambrosia deus seed packets"
- item_cost = 10
+ item_cost = 5
path = /obj/item/weapon/storage/box/ambrosiadeus
/datum/uplink_item/item/medical/freezer
name = "Portable Freezer"
- item_cost = 10
+ item_cost = 1
path = /obj/item/weapon/storage/box/freezer
/datum/uplink_item/item/medical/monkeycubes
name = "Box, Monkey Cubes"
- item_cost = 10
+ item_cost = 1
path = /obj/item/weapon/storage/box/monkeycubes
/datum/uplink_item/item/medical/farwacubes
name = "Box, Farwa Cubes"
- item_cost = 10
+ item_cost = 1
path = /obj/item/weapon/storage/box/monkeycubes
/datum/uplink_item/item/medical/neaeracubes
name = "Box, Neaera Cubes"
- item_cost = 10
+ item_cost = 1
path = /obj/item/weapon/storage/box/monkeycubes/neaeracubes
/datum/uplink_item/item/medical/stokcubes
name = "Box, Stok Cubes"
- item_cost = 10
+ item_cost = 1
path = /obj/item/weapon/storage/box/monkeycubes/stokcubes
/datum/uplink_item/item/medical/surgery
name = "Surgery kit"
- item_cost = 45
+ item_cost = 5
path = /obj/item/weapon/storage/firstaid/surgery
+/datum/uplink_item/item/medical/toxins
+ name = "Anti-toxins medical kit"
+ item_cost = 5
+ path = /obj/item/weapon/storage/firstaid/toxin
+
+/datum/uplink_item/item/medical/o2
+ name = "oxygen deprivation medical kit"
+ item_cost = 5
+ path = /obj/item/weapon/storage/firstaid/o2
+
+/datum/uplink_item/item/medical/fire
+ name = "fire medical kit"
+ item_cost = 5
+ path = /obj/item/weapon/storage/firstaid/fire
+
+/datum/uplink_item/item/medical/adv
+ name = "advanced medical kit"
+ item_cost = 10
+ path = /obj/item/weapon/storage/firstaid/adv
+
/datum/uplink_item/item/medical/combat
name = "Combat medical kit"
- item_cost = 60
+ item_cost = 20
path = /obj/item/weapon/storage/firstaid/combat
diff --git a/code/datums/uplink/tools.dm b/code/datums/uplink/tools.dm
index eee41e9699..9c1a46d632 100644
--- a/code/datums/uplink/tools.dm
+++ b/code/datums/uplink/tools.dm
@@ -6,22 +6,22 @@
/datum/uplink_item/item/tools/binoculars
name = "Binoculars"
- item_cost = 5
+ item_cost = 3
path = /obj/item/device/binoculars
/datum/uplink_item/item/tools/toolbox // Leaving the basic as an option since powertools are loud.
name = "Fully Loaded Toolbox"
- item_cost = 5
+ item_cost = 3
path = /obj/item/weapon/storage/toolbox/syndicate
/datum/uplink_item/item/tools/powertoolbox
name = "Fully Loaded Powertool Box"
- item_cost = 10
+ item_cost = 5
path = /obj/item/weapon/storage/toolbox/syndicate/powertools
/datum/uplink_item/item/tools/clerical
name = "Morphic Clerical Kit"
- item_cost = 10
+ item_cost = 5
path = /obj/item/weapon/storage/box/syndie_kit/clerical
/datum/uplink_item/item/tools/encryptionkey_radio
@@ -42,7 +42,7 @@
/datum/uplink_item/item/tools/duffle
name = "Black Duffle Bag"
- item_cost = 10
+ item_cost = 5
path = /obj/item/weapon/storage/backpack/dufflebag/syndie
/datum/uplink_item/item/tools/duffle/med
@@ -61,7 +61,7 @@
/datum/uplink_item/item/tools/space_suit
name = "Space Suit"
- item_cost = 15
+ item_cost = 10
path = /obj/item/weapon/storage/box/syndie_kit/space
/datum/uplink_item/item/tools/encryptionkey_binary
@@ -71,7 +71,7 @@
/datum/uplink_item/item/tools/hacking_tool
name = "Door Hacking Tool"
- item_cost = 20
+ item_cost = 15
path = /obj/item/device/multitool/hacktool
desc = "Appears and functions as a standard multitool until the mode is toggled by applying a screwdriver appropriately. \
When in hacking mode this device will grant full access to any standard airlock within 20 to 40 seconds. \
@@ -79,7 +79,7 @@
/datum/uplink_item/item/tools/ai_detector
name = "Anti-Surveillance Tool"
- item_cost = 20
+ item_cost = 15
path = /obj/item/device/multitool/ai_detector
desc = "This functions like a normal multitool, but includes an integrated camera network sensor that will warn the holder if they are being \
watched, by changing color and beeping. It is able to detect both AI visual surveillance and security camera utilization from terminals, and \
@@ -87,20 +87,20 @@
/datum/uplink_item/item/tools/radio_jammer
name = "Subspace Jammer"
- item_cost = 25
+ item_cost = 20
path = /obj/item/device/radio_jammer
desc = "A device which is capable of disrupting subspace communications, preventing the use of headsets, PDAs, and communicators within \
a radius of seven meters. It runs off weapon cells, which can be replaced as needed. One cell will last for approximately ten minutes."
/datum/uplink_item/item/tools/wall_elecrtifier
name = "Wall Electrifier"
- item_cost = 10
+ item_cost = 5
path = /obj/item/weapon/cell/spike
desc = "A modified powercell which will electrify walls and reinforced floors in a 3x3 tile range around it. Always active."
/datum/uplink_item/item/tools/emag
name = "Cryptographic Sequencer"
- item_cost = 30
+ item_cost = 20
path = /obj/item/weapon/card/emag
/datum/uplink_item/item/tools/graviton
@@ -111,7 +111,7 @@
/datum/uplink_item/item/tools/thermal
name = "Thermal Imaging Glasses"
- item_cost = 30
+ item_cost = 25
path = /obj/item/clothing/glasses/thermal/syndi
/datum/uplink_item/item/tools/packagebomb
diff --git a/code/datums/uplink/visible_weapons.dm b/code/datums/uplink/visible_weapons.dm
index b939e953de..f8526c022a 100644
--- a/code/datums/uplink/visible_weapons.dm
+++ b/code/datums/uplink/visible_weapons.dm
@@ -139,6 +139,11 @@
item_cost = 75
path = /obj/item/weapon/gun/projectile/shotgun/pump/combat
+/datum/uplink_item/item/visible_weapons/semishotgun
+ name = "Semi-Automatic Shotgun"
+ item_cost = 100
+ path = /obj/item/weapon/gun/projectile/shotgun/semi
+
/datum/uplink_item/item/visible_weapons/leveraction
name = "Lever Action Rifle"
item_cost = 50
diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm
index 83ebb65fa8..9a411c60ee 100644
--- a/code/datums/wires/wires.dm
+++ b/code/datums/wires/wires.dm
@@ -43,6 +43,7 @@
if(!GLOB.wire_color_directory[holder_type])
randomize()
GLOB.wire_color_directory[holder_type] = colors
+ GLOB.wire_name_directory[holder_type] = proper_name
else
colors = GLOB.wire_color_directory[holder_type]
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index 99fc8efcf1..116a17c67e 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -29,9 +29,9 @@
/obj/item/weapon/soap
name = "soap"
- desc = "A cheap bar of soap. Doesn't smell."
+ desc = "A cheap bar of soap. Smells of lye."
gender = PLURAL
- icon = 'icons/obj/items.dmi'
+ icon = 'icons/obj/soap.dmi'
icon_state = "soap"
flags = NOCONDUCT
w_class = ITEMSIZE_SMALL
@@ -39,9 +39,15 @@
throwforce = 0
throw_speed = 4
throw_range = 20
+ var/randomize = TRUE
+ var/square_chance = 10
+
+/obj/item/weapon/soap/Initialize()
+ if(randomize && prob(square_chance))
+ icon_state = "[icon_state]-alt"
/obj/item/weapon/soap/nanotrasen
- desc = "A NanoTrasen-brand bar of soap. Smells of phoron."
+ desc = "A NanoTrasen-brand bar of soap. Smells of phoron, a years-old marketing gimmick."
icon_state = "soapnt"
/obj/item/weapon/soap/deluxe
@@ -55,6 +61,82 @@
desc = "An untrustworthy bar of soap. Smells of fear."
icon_state = "soapsyndie"
+/obj/item/weapon/soap/space_soap
+ desc = "Smells like hot metal and walnuts."
+ icon_state = "space_soap"
+
+/obj/item/weapon/soap/water_soap
+ desc = "Smells like chlorine."
+ icon_state = "water_soap"
+
+/obj/item/weapon/soap/fire_soap
+ desc = "Smells like a campfire."
+ icon_state = "fire_soap"
+
+/obj/item/weapon/soap/rainbow_soap
+ desc = "Smells sickly sweet."
+ icon_state = "rainbow_soap"
+
+/obj/item/weapon/soap/diamond_soap
+ desc = "Smells like saffron and vanilla."
+ icon_state = "diamond_soap"
+
+/obj/item/weapon/soap/uranium_soap
+ desc = "Smells not great... Not terrible."
+ icon_state = "uranium_soap"
+
+/obj/item/weapon/soap/silver_soap
+ desc = "Smells like birch and amaranth."
+ icon_state = "silver_soap"
+
+/obj/item/weapon/soap/brown_soap
+ desc = "Smells like cinnamon and cognac."
+ icon_state = "brown_soap"
+
+/obj/item/weapon/soap/white_soap
+ desc = "Smells like nutmeg and oats."
+ icon_state = "white_soap"
+
+/obj/item/weapon/soap/grey_soap
+ desc = "Smells like bergamot and lilies."
+ icon_state = "grey_soap"
+
+/obj/item/weapon/soap/pink_soap
+ desc = "Smells like bubblegum."
+ icon_state = "pink_soap"
+
+/obj/item/weapon/soap/purple_soap
+ desc = "Smells like lavender."
+ icon_state = "purple_soap"
+
+/obj/item/weapon/soap/blue_soap
+ desc = "Smells like cardamom."
+ icon_state = "blue_soap"
+
+/obj/item/weapon/soap/cyan_soap
+ desc = "Smells like bluebells and peaches."
+ icon_state = "cyan_soap"
+
+/obj/item/weapon/soap/green_soap
+ desc = "Smells like a freshly mowed lawn."
+ icon_state = "green_soap"
+
+/obj/item/weapon/soap/yellow_soap
+ desc = "Smells like citron and ginger."
+ icon_state = "yellow_soap"
+
+/obj/item/weapon/soap/orange_soap
+ desc = "Smells like oranges and dark chocolate."
+ icon_state = "orange_soap"
+
+/obj/item/weapon/soap/red_soap
+ desc = "Smells like cherries."
+ icon_state = "red_soap"
+
+/obj/item/weapon/soap/golden_soap
+ desc = "Smells like honey."
+ icon_state = "golden_soap"
+
/obj/item/weapon/bikehorn
name = "bike horn"
desc = "A horn off of a bicycle."
@@ -397,6 +479,7 @@
continue
remove_from_storage(B, T)
+
/obj/item/weapon/stock_parts
name = "stock part"
desc = "What?"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 18d7dc4666..e8f9e2fe13 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -451,6 +451,8 @@ var/list/mob/living/forced_ambiance_list = new
return
if(H.incorporeal_move) // VOREstation edit - Phaseshifted beings should not be affected by gravity
return
+ if(H.species.can_zero_g_move || H.species.can_space_freemove)
+ return
if(H.m_intent == "run")
H.AdjustStunned(6)
@@ -463,7 +465,7 @@ var/list/mob/living/forced_ambiance_list = new
/area/proc/prison_break(break_lights = TRUE, open_doors = TRUE, open_blast_doors = FALSE) //CHOMP Edit set blast doors to FALSE
var/obj/machinery/power/apc/theAPC = get_apc()
- if(theAPC.operating)
+ if(theAPC && theAPC.operating)
if(break_lights)
for(var/obj/machinery/power/apc/temp_apc in src)
temp_apc.overload_lighting(70)
diff --git a/code/game/area/areas_vr.dm b/code/game/area/areas_vr.dm
index e356063e2a..f932674566 100644
--- a/code/game/area/areas_vr.dm
+++ b/code/game/area/areas_vr.dm
@@ -5,6 +5,9 @@
var/block_suit_sensors = FALSE //If mob size is limited in the area.
var/turf/ceiling_type
+ // Size of the area in open turfs, only calculated for indoors areas.
+ var/areasize = 0
+
/area/Entered(var/atom/movable/AM, oldLoc)
. = ..()
if(enter_message && isliving(AM))
@@ -29,3 +32,41 @@
var/turf/TA = GetAbove(T)
if(isopenspace(TA))
TA.ChangeTurf(ceiling_type, TRUE, TRUE, TRUE)
+
+/**
+ * Setup an area (with the given name)
+ *
+ * Sets the area name, sets all status var's to false and adds the area to the sorted area list
+ * //NOTE: Virgo does not have a sorted area list.
+ */
+/area/proc/setup(a_name)
+ name = a_name
+ power_equip = FALSE
+ power_light = FALSE
+ power_environ = FALSE
+ always_unpowered = FALSE
+ update_areasize()
+
+/area/proc/update_areasize()
+ if(outdoors)
+ return FALSE
+ areasize = 0
+ for(var/turf/simulated/floor/T in contents)
+ areasize++
+
+/proc/rename_area(a, new_name)
+ var/area/A = get_area(a)
+ var/prevname = "[A.name]"
+ set_area_machinery(A, new_name, prevname)
+ A.name = new_name
+ A.update_areasize()
+ return TRUE
+
+/area/proc/power_check()
+ if(!requires_power || !apc)
+ power_light = 0
+ power_equip = 0
+ power_environ = 0
+ power_change() // all machines set to current power level, also updates lighting icon
+ if(no_spoilers)
+ set_spoiler_obfuscation(TRUE)
\ No newline at end of file
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 29c937afd6..a17be310bd 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -639,4 +639,4 @@
return selfimage
/atom/movable/proc/get_cell()
- return
+ return
\ No newline at end of file
diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm
index 931b298091..d5cdc700c7 100644
--- a/code/game/dna/dna2_helpers.dm
+++ b/code/game/dna/dna2_helpers.dm
@@ -22,7 +22,7 @@
// Give Random Bad Mutation to M
/proc/randmutb(var/mob/living/M)
- if(!M) return
+ if(!M || !(M.dna)) return
M.dna.check_integrity()
//var/block = pick(GLASSESBLOCK,COUGHBLOCK,FAKEBLOCK,NERVOUSBLOCK,CLUMSYBLOCK,TWITCHBLOCK,HEADACHEBLOCK,BLINDBLOCK,DEAFBLOCK,HALLUCINATIONBLOCK) // Most of these are disabled anyway.
var/block = pick(FAKEBLOCK,CLUMSYBLOCK,BLINDBLOCK,DEAFBLOCK)
@@ -30,7 +30,7 @@
// Give Random Good Mutation to M
/proc/randmutg(var/mob/living/M)
- if(!M) return
+ if(!M || !(M.dna)) return
M.dna.check_integrity()
//var/block = pick(HULKBLOCK,XRAYBLOCK,FIREBLOCK,TELEBLOCK,NOBREATHBLOCK,REMOTEVIEWBLOCK,REGENERATEBLOCK,INCREASERUNBLOCK,REMOTETALKBLOCK,MORPHBLOCK,BLENDBLOCK,NOPRINTSBLOCK,SHOCKIMMUNITYBLOCK,SMALLSIZEBLOCK) // Much like above, most of these blocks are disabled in code.
var/block = pick(HULKBLOCK,XRAYBLOCK,FIREBLOCK,TELEBLOCK,REGENERATEBLOCK,REMOTETALKBLOCK)
@@ -38,13 +38,13 @@
// Random Appearance Mutation
/proc/randmuti(var/mob/living/M)
- if(!M) return
+ if(!M || !(M.dna)) return
M.dna.check_integrity()
M.dna.SetUIValue(rand(1,DNA_UI_LENGTH),rand(1,4095))
// Scramble UI or SE.
/proc/scramble(var/UI, var/mob/M, var/prob)
- if(!M) return
+ if(!M || !(M.dna)) return
M.dna.check_integrity()
if(UI)
for(var/i = 1, i <= DNA_UI_LENGTH-1, i++)
diff --git a/code/game/gamemodes/cult/construct_spells.dm b/code/game/gamemodes/cult/construct_spells.dm
index 62cdd5bf48..5bd8929555 100644
--- a/code/game/gamemodes/cult/construct_spells.dm
+++ b/code/game/gamemodes/cult/construct_spells.dm
@@ -512,7 +512,7 @@
var/obj/item/projectile/new_projectile = make_projectile(spell_projectile, user)
new_projectile.old_style_target(hit_atom)
new_projectile.fire()
- log_and_message_admins("has casted [src] at \the [hit_atom].")
+ log_attack("has casted [src] at \the [hit_atom].")//CHOMPEdit from log_and_message_admins
if(fire_sound)
playsound(src, fire_sound, 75, 1)
return 1
diff --git a/code/game/gamemodes/events/holidays/Holidays.dm b/code/game/gamemodes/events/holidays/Holidays.dm
index c04d6408b6..9c156a50bd 100644
--- a/code/game/gamemodes/events/holidays/Holidays.dm
+++ b/code/game/gamemodes/events/holidays/Holidays.dm
@@ -22,7 +22,7 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
Holiday = list() // reset our switch now so we can recycle it as our Holiday name
- var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year
+ //var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year - unused currently but can be used for floating dates
var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
@@ -36,56 +36,63 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
Holiday["New Years's Day"] = "The day of the new solar year on Sol."
if(12)
Holiday["Vertalliq-Qerr"] = "Vertalliq-Qerr, translated to mean 'Festival of the Royals', is a \
- Skrell holiday that celebrates the Qerr-Katish and all they have provided for the rest of Skrell society, \
+ skrellian holiday that celebrates the Qerr-Katish and all they have provided for the rest of skrellian society, \
it often features colourful displays and skilled performers take this time to show off some of their more \
- fancy displays."
+ elaborate displays."
+ if(14)
+ Holiday["Lohri"] = "A human festival traditionally celebrating the end of winter on the Indian subcontinent. \
+ The holiday is now celebrated independently of seasons in many colonies with large populations of Indian \
+ descent. Traditions include the burning of bonfires, dancing, and door-to-door singing in exchange for treats."
+ if(30)
+ Holiday["Lunar New Year"] = "Originally the new year on the ancient lunisolar calendar, the Lunar New Year is \
+ celebrated with a wide variety of east Asian traditions with roots in Chinese, Japanese, Korean, Vietnamese, \
+ Tibetan, Mongolian, and Ryukyu cultures. Elaborate parades, performances, dances and meals are usual staples."
if(2) //Feb
switch(DD)
if(2)
- Holiday["Groundhog Day"] = "An unoffical holiday based on ancient folklore that originated on Earth, \
- that involves the worship of an almighty groundhog, that could control the weather based on if it casted a shadow."
+ Holiday["Groundhog Day"] = "An unoffical holiday based on medieval folklore that originated on Earth, \
+ that involves the reverence of a prophetic animal - traditionally a badger, fox or groundhog - that was \
+ said to be able to predict, or even control the changing of the seasons."
if(14)
- Holiday["Valentine's Day"] = "An old holiday that revolves around romance and love."
+ Holiday["Valentine's Day"] = "A human holiday that revolves around expressions of romance and love. \
+ In particular, the exchanging of gifts, letters and cards is traditional."
+ if(15)
+ Holiday["Lantern Festival"] = "A human holiday with origins in Chinese new year celebrations. Participants \
+ carry or hang elaborate paper lanterns that are thought to bring good luck. Today, electric lights are often used \
+ in environments where open flames would be hazardous or non-functional."
if(17)
Holiday["Random Acts of Kindness Day"] = "An unoffical holiday that challenges everyone to perform \
- acts of kindness to their friends, co-workers, and strangers, for no reason."
+ acts of kindness to their friends, co-workers, and strangers, with no strings attached."
if(3) //Mar
switch(DD)
if(3)
- Holiday["Qixm-tes"] = "Qixm-tes, or 'Day of mourning', is a Skrell holiday where Skrell gather at places \
- of worship and sing a song of mourning for all those who have died in service to their empire."
+ Holiday["Qixm-tes"] = "Qixm-tes, or 'Day of mourning', is a skrellian holiday where skrell gather at places \
+ of worship and sing a song of mourning for all those who have died in service to their kingdoms."
if(14)
Holiday["Pi Day"] = "An unoffical holiday celebrating the mathematical constant Pi. It is celebrated on \
March 14th, as the digits form 3 14, the first three significant digits of Pi. Observance of Pi Day generally \
involve eating (or throwing) pie, due to a pun. Pies also tend to be round, and thus relatable to Pi."
if(17)
- Holiday["St. Patrick's Day"] = "An old holiday originating from Earth, Sol, celebrating the color green, \
- shamrocks, attending parades, and drinking alcohol."
+ Holiday["St. Patrick's Day"] = "A holiday originating on Earth, celebrating a popular version of Irish culture. \
+ Traditions include elaborate parades, wearing of the colour green, and drinking alcohol."
+ if(18)
+ Holiday["Holi"] = "Also known as the Festival of Colours, a human Hindu festival celebrating divine love and the \
+ triumph of good over evil. Traditionally a bonfire is lit overnight, followed by the free-for-all smearing of \
+ celebrants with colourful pigments, and the forgiveness of past wrongs."
if(27)
- if(YY == 16)
- Holiday["Easter"] = ""
- if(31)
- if(YY == 13)
- Holiday["Easter"] = ""
+ Holiday["Easter"] = "A Earth springtime festival variously celebrating rebirth and the beginning of the planting \
+ season. Traditionally celebrated with the painting and exchange of eggs, sometimes made from chocolate. \
+ The holiday's date was standardized in the 22nd century."
if(4) //Apr
switch(DD)
if(1)
- Holiday["April Fool's Day"] = "An old holiday that endevours one to pull pranks and spread hoaxes on their friends."
- if(YY == 18)
- Holiday["Easter"] = ""
- if(8)
- if(YY == 15)
- Holiday["Easter"] = ""
- if(16)
- if(YY == 17) //Easter can go die for all of this copypasta.
- Holiday["Easter"] = ""
-
- if(20)
- if(YY == 14)
- Holiday["Easter"] = ""
+ Holiday["April Fool's Day"] = "A human holiday that endevours one to pull pranks and spread hoaxes on their friends."
+ if(5)
+ Holiday["First Day of Passover"] = "The first of eight days of a human holiday celebrating the exodus of ancient Jewish people \
+ from slavery, and of the spring harvest. The most well-known tradition is the Sedar meal. The date was standardized in the 22nd century."
if(22)
Holiday["Earth Day"] = "A holiday of enviromentalism, that originated on it's namesake, Earth."
@@ -100,7 +107,7 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
Observance of this day varies throughout human space, but most common traditions are the act of bringing flowers to graves,\
attending parades, and the wearing of poppies (either paper or real) in one's clothing."
if(28)
- Holiday["Jiql-tes"] = "A Skrellian holiday that translates to 'Day of Celebration', Skrell communities \
+ Holiday["Jiql-tes"] = "A skrellian holiday that translates to 'Day of Celebration', skrell communities \
gather for a grand feast and give gifts to friends and close relatives."
if(6) //Jun
@@ -113,7 +120,11 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
and to thank blood donors for their voluntary, life-saving gifts of blood."
if(20)
Holiday["Civil Servant's Day"] = "Civil Servant's Day is a holiday observed in SCG member states that honors civil servants everywhere,\
-+ (especially those who are members of the armed forces and the emergency services), or have been or have been civil servants in the past."
+ (especially those who are members of the armed forces and the emergency services), or have been or have been civil servants in the past."
+/* if(25)
+ Holiday["Merhyat Njarha"] = "A Njarir'Akhan tajaran tradition translating to \"Harmony of the House\", in which Njarjirii citizens pay \
+ homage to their ruling house and their ancestors. Traditions include large communal meals and dances hosted by the ruling house, \
+ and the intensive upkeep of community spaces."*/
if(7) //Jul
switch(DD)
@@ -126,36 +137,43 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
if(8) //Aug
switch(DD)
-// if(10)
-// Holiday["S'randarr's Day"] = "A Tajaran holiday that occurs on the longest day of the year in summer,
-// on Ahdomai. It is named after the Tajaran deity of Light, and huge celebrations are common."
-//VOREStation Add - Of course we need this.
- if(8)
- Holiday["Vore Day"] = "A holiday representing the innate desire in all/most/some/a few of us to devour each other or be devoured. \
- That's probably why you're here, isn't it? Get to it, then!"
-//VOREStation Add End.
-
+ if(11)
+ Holiday["Tajaran Contact Day"] = "The anniversary of first contact between SolGov and the tajaran species, widely observed\
+ throughout tajaran and human space. Marks the date that in 2513, a human exploration team investigating electromagnetic \
+ emissions from the Meralar system made radio contact with the tajaran scientific outpost that had broadcast them."
+ if(20)
+ Holiday["Obon"] = "An ancient Earth holiday originating in east Asia, for the honouring of one's ancestral spirits. \
+ Traditions include the maintenance of grave sites and memorials, and community traditional dance performances."
if(27)
Holiday["Forgiveness Day"] = "A time to forgive and be forgiven."
if(9) //Sep
switch(DD)
if(17)
- Holiday["Qill-xamr"] = "Translated to 'Night of the dead', it is a Skrell holiday where Skrell \
+ Holiday["Qill-xamr"] = "Translated to 'Night of the dead', it is a skrellian holiday where skrell \
communities hold parties in order to remember loved ones who passed, unlike Qixm-tes, this applies to everyone \
and is a joyful celebration."
if(19)
- Holiday["Talk-Like-a-Pirate Day"] = "Ahoy, matey! Tis unoffical holiday be celebratin' the jolly \
- good humor of speakin' like the pirates of old."
+ Holiday["Talk-Like-a-Pirate Day"] = "Ahoy, matey! It be the unoffical holiday celebratin' the salty \
+ sea humor of speakin' like the pirates of old."
+ if(20)
+ Holiday["Rosh Hashanah"] = "An old human holiday that marks the traditional Hebrew new year."
if(28)
Holiday["Stupid-Questions Day"] = "Known as Ask A Stupid Question Day, it is an unoffical holiday \
created by teachers in Sol, very long ago, to encourage students to ask more questions in the classroom."
if(10) //Oct
switch(DD)
+ if(9)
+ Holiday["Lief Eriksson Day"] = "A day commemorating Norse explorer Lief Eriksson, an early Scandinavian cultural figure \
+ who is thought to have been the first European to set foot in North America."
if(16)
Holiday["Boss' Day"] = "Boss' Day has traditionally been a day for employees to thank their bosses for the difficult work that they do \
throughout the year. This day was created for the purpose of strengthening the bond between employer and employee."
+ if(21)
+ Holiday["First Day of Diwali"] = "An ancient Hindu, Jain and Sikh festival lasting five days, celebrating victory of light over darkness, good over \
+ evil, and knowledge over ignorance. It is celebrated by the wearing of your finest clothes, decorating with oil lamps and rangolis, \
+ fireworks, and gift-giving. Electric lights are often used in modern times where oil lamps would be hazardous or inoperable."
if(31)
Holiday["Halloween"] = "Originating from Earth, Halloween is also known as All Saints' Eve, and \
is celebrated by some by attending costume parties, trick-or-treating, carving faces in pumpkins, or visiting \
@@ -163,6 +181,10 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
if(11) //Nov
switch(DD)
+ if(1)
+ Holiday["Day of the Dead"] = "An old human holiday celebrating the lives of deceased friends and family members, \
+ by means of good humour and joyful parties. Offerings are often left at altars to the dead, and exchanging gifts \
+ among the living is not uncommon."
if(13)
Holiday["Kindness Day"] = "Kindness Day is an unofficial holiday to highlight good deeds in the \
community, focusing on the positive power and the common thread of kindness which binds humanity and \
@@ -182,16 +204,17 @@ var/global/list/Holiday = list() //Holidays are lists now, so we can have more t
if(10)
Holiday["Human-Rights Day"] = "An old holiday created by an intergovernmental organization known back than as the United Nations, \
human rights were not recognized globally at the time, and the holiday was made in honor of the Universal Declaration of Human Rights. \
- These days, SolGov ensures that past efforts were not in vein, and continues to honor this holiday across the galaxy."
+ These days, SolGov ensures that past efforts were not in vein, and continues to honor this holiday across the galaxy as a historical \
+ reminder."
if(22)
- Holiday["Vertalliq-qixim"] = "A Skrellian holiday that celebrates the Skrell's first landing on one of \
- their moons. It's often celebrated with grand festivals."
+ Holiday["Vertalliq-qixim"] = "A skrellian holiday that celebrates the skrell's first landing on one of \
+ their moons. It's often celebrated with grand festivals."
if(24)
Holiday["Christmas Eve"] = "The eve of Christmas, an old holiday from Earth that mainly involves gift \
giving, decorating, family reunions, and a fat red human breaking into people's homes to steal milk and cookies."
if(25)
Holiday["Christmas"] = "Christmas is a very old holiday that originated in Earth, Sol. It was a \
- religious holiday for the Christian religion, which would later form Unitarianism. Nowdays, the holiday is celebrated \
+ religious holiday for the Christian religion, which would later form Unitarianism. Nowadays, the holiday is celebrated \
generally by giving gifts, symbolic decoration, and reuniting with one's family. It also features a mythical fat \
red human, known as Santa, who broke into people's homes to loot cookies and milk."
if(31)
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index 0b0b8d014c..6b88e45765 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -13,7 +13,7 @@
/obj/effect/meteor/big=3,
/obj/effect/meteor/flaming=1,
/obj/effect/meteor/irradiated=3
- )
+ )
//for threatening meteor event
/var/list/meteors_threatening = list(
@@ -109,13 +109,13 @@
desc = "You should probably run instead of gawking at this."
icon = 'icons/obj/meteor.dmi'
icon_state = "small"
- density = 1
- anchored = 1
+ density = TRUE
+ anchored = TRUE
var/hits = 4
var/hitpwr = 2 //Level of ex_act to be called on hit.
var/dest
pass_flags = PASSTABLE
- var/heavy = 0
+ var/heavy = FALSE
var/z_original
var/meteordrop = /obj/item/weapon/ore/iron
@@ -147,7 +147,7 @@
get_hit()
/obj/effect/meteor/Destroy()
- walk(src,0) //this cancels the walk_towards() proc
+ walk(src,FALSE) //this cancels the walk_towards() proc
GLOB.meteor_list -= src
return ..()
@@ -162,10 +162,10 @@
ram_turf(get_turf(A))
get_hit()
else
- die(0)
+ die(FALSE)
/obj/effect/meteor/CanPass(atom/movable/mover, turf/target)
- return istype(mover, /obj/effect/meteor) ? 1 : ..()
+ return istype(mover, /obj/effect/meteor) ? TRUE : ..()
/obj/effect/meteor/proc/ram_turf(var/turf/T)
//first bust whatever is in the turf
@@ -190,9 +190,9 @@
/obj/effect/meteor/proc/get_hit()
hits--
if(hits <= 0)
- die(1)
+ die(TRUE)
-/obj/effect/meteor/proc/die(var/explode = 1)
+/obj/effect/meteor/proc/die(var/explode = TRUE)
make_debris()
meteor_effect(explode)
qdel(src)
@@ -206,6 +206,18 @@
return
..()
+/obj/effect/meteor/bullet_act(var/obj/item/projectile/Proj)
+ if(Proj.excavation_amount)
+ get_hit()
+
+ if(!QDELETED(src))
+ wall_power -= Proj.excavation_amount + Proj.damage + (Proj.hitscan * 25) // Instant-impact projectiles are inherently better at dealing with meteors.
+
+ if(wall_power <= 0)
+ die(FALSE) // If you kill the meteor, then it dies.
+ return
+ return
+
/obj/effect/meteor/proc/make_debris()
for(var/throws = dropamt, throws > 0, throws--)
var/obj/item/O = new meteordrop(get_turf(src))
@@ -330,4 +342,4 @@
/obj/effect/meteor/tunguska/Bump()
..()
if(prob(20))
- explosion(src.loc,2,4,6,8)
+ explosion(src.loc,2,4,6,8)
\ No newline at end of file
diff --git a/code/game/gamemodes/newobjective.dm b/code/game/gamemodes/newobjective.dm
index c52e51d5b5..1b3a1147a1 100644
--- a/code/game/gamemodes/newobjective.dm
+++ b/code/game/gamemodes/newobjective.dm
@@ -749,7 +749,7 @@ datum
blueprints
- steal_target = /obj/item/blueprints
+ steal_target = /obj/item/areaeditor/blueprints
explanation_text = "Steal the station's blueprints."
weight = 20
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 2ab94983f5..787cc0fc49 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -431,7 +431,7 @@ var/global/list/all_objectives = list()
"a site manager's jumpsuit" = /obj/item/clothing/under/rank/captain,
"a functional AI" = /obj/item/device/aicard,
"a pair of magboots" = /obj/item/clothing/shoes/magboots,
- "the station blueprints" = /obj/item/blueprints,
+ "the station blueprints" = /obj/item/areaeditor/blueprints,
"a nasa voidsuit" = /obj/item/clothing/suit/space/void,
"28 moles of phoron (full tank)" = /obj/item/weapon/tank,
"a sample of slime extract" = /obj/item/slime_extract,
diff --git a/code/game/jobs/job/assistant_vr.dm b/code/game/jobs/job/assistant_vr.dm
index bfcf3037b4..1aa1f7cb55 100644
--- a/code/game/jobs/job/assistant_vr.dm
+++ b/code/game/jobs/job/assistant_vr.dm
@@ -27,6 +27,7 @@
job_description = "An Intern does whatever is requested of them, often doing so in process of learning \
another job. Though they are part of the crew, they have no real authority."
timeoff_factor = 0 // Interns, noh
+ requestable = FALSE
/datum/alt_title/intern_eng
title = "Apprentice Engineer"
@@ -96,6 +97,7 @@
supervisors = "nobody! You don't work here"
job_description = "A Visitor is just there to visit the place. They have no real authority or responsibility."
timeoff_factor = 0
+ requestable = FALSE
alt_titles = list("Guest" = /datum/alt_title/guest, "Traveler" = /datum/alt_title/traveler)
/datum/job/assistant/New()
diff --git a/code/game/jobs/job/captain_vr.dm b/code/game/jobs/job/captain_vr.dm
index e327805cc0..62b0eb93ef 100644
--- a/code/game/jobs/job/captain_vr.dm
+++ b/code/game/jobs/job/captain_vr.dm
@@ -14,6 +14,9 @@
/datum/alt_title/captain
title = "Captain"
+/datum/job/captain/get_request_reasons()
+ return list("Training crew")
+
/datum/job/hop
disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN
@@ -29,13 +32,13 @@
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
- access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway)
+ access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway, access_entertainment)
minimal_access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
- access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway)
+ access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway, access_entertainment)
/datum/alt_title/deputy_director
title = "Deputy Director"
@@ -46,6 +49,9 @@
/datum/alt_title/facility_steward
title = "Facility Steward"
+/datum/job/hop/get_request_reasons()
+ return list("ID modification", "Training crew")
+
/datum/job/secretary
disallow_jobhop = TRUE
diff --git a/code/game/jobs/job/civilian_vr.dm b/code/game/jobs/job/civilian_vr.dm
index 688f52bf85..9c5de6d54b 100644
--- a/code/game/jobs/job/civilian_vr.dm
+++ b/code/game/jobs/job/civilian_vr.dm
@@ -30,7 +30,7 @@
spawn_positions = 2
pto_type = PTO_CIVILIAN
alt_titles = list("Hydroponicist" = /datum/alt_title/hydroponicist, "Cultivator" = /datum/alt_title/cultivator, "Farmer" = /datum/alt_title/farmer,
- "Gardener" = /datum/alt_title/gardener, "Florist" = /datum/alt_title/florsit)
+ "Gardener" = /datum/alt_title/gardener, "Florist" = /datum/alt_title/florsit, "Rancher" = /datum/alt_title/rancher)
/datum/alt_title/hydroponicist
title = "Hydroponicist"
@@ -45,6 +45,10 @@
title = "Florist"
title_blurb = "A Florist may be less professional than their counterparts, and are more likely to tend to the public gardens if they aren't needed elsewhere."
+/datum/alt_title/rancher
+ title = "Rancher"
+ title_blurb = "A Rancher is tasked with the care, feeding, raising, and harvesting of livestock."
+
/datum/job/qm
pto_type = PTO_CARGO
@@ -57,6 +61,9 @@
/datum/alt_title/cargo_supervisor
title = "Cargo Supervisor"
+/datum/job/qm/get_request_reasons()
+ return list("Training crew")
+
/datum/job/cargo_tech
total_positions = 3
diff --git a/code/game/jobs/job/engineering_vr.dm b/code/game/jobs/job/engineering_vr.dm
index 1455fe0df0..58ebb57dd2 100644
--- a/code/game/jobs/job/engineering_vr.dm
+++ b/code/game/jobs/job/engineering_vr.dm
@@ -23,6 +23,9 @@
/datum/alt_title/maintenance_manager
title = "Maintenance Manager"
+/datum/job/chief_engineer/get_request_reasons()
+ return list("Engine setup", "Construction project", "Repairs necessary", "Training crew")
+
/datum/job/engineer
pto_type = PTO_ENGINEERING
@@ -38,6 +41,9 @@
title = "Engineering Contractor"
title_blurb = "An Engineering Contractor fulfills similar duties to other engineers, but isn't directly employed by NT proper."
+/datum/job/engineer/get_request_reasons()
+ return list("Engine setup", "Construction project", "Repairs necessary")
+
@@ -55,3 +61,6 @@
/datum/alt_title/disposals_tech
title = "Disposals Technician"
title_blurb = "A Disposals Technician is an Atmospheric Technician still and can fulfill all the same duties, although specializes more in disposals delivery system's operations and configurations."
+
+/datum/job/atmos/get_request_reasons()
+ return list("Construction project", "Repairs necessary")
\ No newline at end of file
diff --git a/code/game/jobs/job/exploration_vr.dm b/code/game/jobs/job/exploration_vr.dm
index 05427d5173..66ece35139 100644
--- a/code/game/jobs/job/exploration_vr.dm
+++ b/code/game/jobs/job/exploration_vr.dm
@@ -55,6 +55,9 @@
/datum/alt_title/exploration_manager
title = "Exploration Manager"
+/datum/job/pathfinder/get_request_reasons()
+ return list("Training crew")
+
/datum/job/pilot
title = "Pilot"
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index 509572aa98..b0e678298b 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -147,7 +147,7 @@
var/mob/living/carbon/human/dummy/mannequin/mannequin = get_mannequin("#job_icon")
dress_mannequin(mannequin)
mannequin.dir = SOUTH
- COMPILE_OVERLAYS(mannequin)
+ mannequin.ImmediateOverlayUpdate()
var/icon/preview_icon = getFlatIcon(mannequin)
preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser.
@@ -174,6 +174,10 @@
//return (brain_type && LAZYACCESS(ideal_age_by_species, brain_type)) || LAZYACCESS(ideal_age_by_species, brain_type) || ideal_character_age //VOREStation Removal
/datum/job/proc/is_species_banned(species_name, brain_type)
+ // CHOMPEdit begin -- Shadekin cannot be any crew position
+ if(species_name == SPECIES_SHADEKIN)
+ return TRUE
+ // CHOMPEdit end
return FALSE // VOREStation Edit - Any species can be any job.
/* VOREStation Removal
if(banned_job_species == null)
diff --git a/code/game/jobs/job/job_vr.dm b/code/game/jobs/job/job_vr.dm
index 0f2599b8aa..ac8b6be0b4 100644
--- a/code/game/jobs/job/job_vr.dm
+++ b/code/game/jobs/job/job_vr.dm
@@ -20,6 +20,8 @@
//Do we forbid ourselves from earning PTO?
var/playtime_only = FALSE
+ var/requestable = TRUE
+
// Check client-specific availability rules.
/datum/job/proc/player_has_enough_pto(client/C)
return timeoff_factor >= 0 || (C && LAZYACCESS(C.department_hours, pto_type) > 0)
@@ -58,4 +60,7 @@
if(isnum(C.play_hours[PTO_EXPLORATION]))
remaining_time_needed = max(0, remaining_time_needed - C.play_hours[PTO_EXPLORATION])
return remaining_time_needed
- return 0
\ No newline at end of file
+ return 0
+
+/datum/job/proc/get_request_reasons()
+ return list()
\ No newline at end of file
diff --git a/code/game/jobs/job/medical_vr.dm b/code/game/jobs/job/medical_vr.dm
index 29033ebadc..8c2140c5a0 100644
--- a/code/game/jobs/job/medical_vr.dm
+++ b/code/game/jobs/job/medical_vr.dm
@@ -21,6 +21,9 @@
/datum/alt_title/healthcare_manager
title = "Healthcare Manager"
+/datum/job/cmo/get_request_reasons()
+ return list("Surgery pending", "Viral outbreak", "Training crew")
+
/datum/job/doctor
spawn_positions = 5
@@ -29,7 +32,6 @@
"Emergency Physician" = /datum/alt_title/emergency_physician, "Nurse" = /datum/alt_title/nurse, "Orderly" = /datum/alt_title/orderly,
"Virologist" = /datum/alt_title/virologist, "Medical Contractor" = /datum/alt_title/medical_contractor)
-
/datum/alt_title/physician
title = "Physician"
@@ -46,6 +48,9 @@
title = "Medical Contractor"
title_blurb = "A Medical Contractor can be anything from a full-blown doctor to the likes of a nurse or orderly, but isn't directly employed by NT proper."
+/datum/job/doctor/get_request_reasons()
+ return list("Surgery pending", "Viral outbreak")
+
/datum/job/chemist
pto_type = PTO_MEDICAL
diff --git a/code/game/jobs/job/science_vr.dm b/code/game/jobs/job/science_vr.dm
index b40b264aff..bbcf853324 100644
--- a/code/game/jobs/job/science_vr.dm
+++ b/code/game/jobs/job/science_vr.dm
@@ -25,6 +25,9 @@
/datum/alt_title/head_scientist
title = "Head Scientist"
+/datum/job/rd/get_request_reasons()
+ return list("Repairs needed", "Training crew")
+
/datum/job/scientist
spawn_positions = 5
pto_type = PTO_SCIENCE
@@ -87,6 +90,9 @@
/datum/alt_title/assembly_tech
title = "Assembly Technician"
+/datum/job/roboticist/get_request_reasons()
+ return list("Repairs needed")
+
//////////////////////////////////
// Xenobotanist
//////////////////////////////////
@@ -116,4 +122,4 @@
title = "Xenoflorist"
/datum/alt_title/xenohydroponicist
- title = "Xenohydroponicist"
\ No newline at end of file
+ title = "Xenohydroponicist"
diff --git a/code/game/jobs/job/security_vr.dm b/code/game/jobs/job/security_vr.dm
index bba60df71a..80acbb451e 100644
--- a/code/game/jobs/job/security_vr.dm
+++ b/code/game/jobs/job/security_vr.dm
@@ -16,6 +16,9 @@
/datum/alt_title/security_manager
title = "Security Manager"
+/datum/job/hos/get_request_reasons()
+ return list("Wildlife management", "Forensic investigation", "Training crew")
+
/datum/job/warden
pto_type = PTO_SECURITY
@@ -28,6 +31,9 @@
/datum/alt_title/armory_superintendent
title = "Armory Superintendent"
+/datum/job/warden/get_request_reasons()
+ return list("Wildlife management")
+
/datum/job/detective
pto_type = PTO_SECURITY
@@ -39,6 +45,9 @@
/datum/alt_title/security_inspector
title = "Security Inspector"
+/datum/job/detective/get_request_reasons()
+ return list("Forensic investigation")
+
/datum/job/officer
total_positions = 5
@@ -58,3 +67,6 @@
/datum/alt_title/security_contractor
title = "Security Contractor"
+
+/datum/job/officer/get_request_reasons()
+ return list("Wildlife management")
diff --git a/code/game/jobs/job/special_vr.dm b/code/game/jobs/job/special_vr.dm
index 54e8c157da..3a10a23df5 100644
--- a/code/game/jobs/job/special_vr.dm
+++ b/code/game/jobs/job/special_vr.dm
@@ -113,6 +113,7 @@
job_description = "A Clown is there to entertain the crew and keep high morale using various harmless pranks and ridiculous jokes!"
whitelist_only = 1
latejoin_only = 0
+ requestable = FALSE
outfit_type = /decl/hierarchy/outfit/job/clown
pto_type = PTO_CIVILIAN
alt_titles = list("Jester" = /datum/alt_title/jester, "Fool" = /datum/alt_title/fool)
@@ -144,6 +145,7 @@
alt_titles = list("Poseur" = /datum/alt_title/poseur)
whitelist_only = 1
latejoin_only = 0
+ requestable = FALSE
outfit_type = /decl/hierarchy/outfit/job/mime
pto_type = PTO_CIVILIAN
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index 5a414430ea..63f8a702e0 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -393,7 +393,7 @@ var/global/datum/controller/occupations/job_master
//Equip custom gear loadout.
var/list/custom_equip_slots = list()
var/list/custom_equip_leftovers = list()
- if(H.client.prefs.gear && H.client.prefs.gear.len && !(job.mob_type & JOB_SILICON))
+ if(H.client && H.client.prefs && H.client.prefs.gear && H.client.prefs.gear.len && !(job.mob_type & JOB_SILICON))
for(var/thing in H.client.prefs.gear)
var/datum/gear/G = gear_datums[thing]
if(!G) //Not a real gear datum (maybe removed, as this is loaded from their savefile)
@@ -657,8 +657,7 @@ var/global/datum/controller/occupations/job_master
var/obj/belly/vore_spawn_gut
var/mob/living/prey_to_nomph
- var/datum/job/J = SSjob.get_job(rank)
- fail_deadly = J?.offmap_spawn
+ //CHOMPEdit - Remove fail_deadly addition on offmap_spawn
//Spawn them at their preferred one
if(C && C.prefs.spawnpoint)
@@ -804,7 +803,8 @@ var/global/datum/controller/occupations/job_master
.["msg"] = spawnpos.msg
.["channel"] = spawnpos.announce_channel
else
- if(fail_deadly)
+ var/datum/job/J = SSjob.get_job(rank)
+ if(fail_deadly || J?.offmap_spawn)
to_chat(C, "Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Please correct your spawn point choice.")
return
to_chat(C, "Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Spawning you at the Arrivals shuttle instead.")
diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm
index 3c949ba66d..e71f4eb72b 100644
--- a/code/game/jobs/jobs.dm
+++ b/code/game/jobs/jobs.dm
@@ -51,6 +51,8 @@ var/const/ASSISTANT =(1<<11)
var/const/BRIDGE =(1<<12)
var/const/ENTERTAINER =(1<<13) //VOREStation Add
+var/const/OTHER =(1<<10) //CHOMPStation Add
+var/const/NONCREW =(1<<0) //CHOMPStation Add
/* // CHOMPedit: Comment out Talon positions, we don't have that here.
//VOREStation Add
var/const/TALON =(1<<3)
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index b785a42639..18765fcf9b 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -423,6 +423,8 @@
/obj/machinery/sleeper/relaymove(var/mob/user)
..()
+ if(user.incapacitated())
+ return
go_out()
/obj/machinery/sleeper/emp_act(var/severity)
diff --git a/code/game/machinery/air_alarm.dm b/code/game/machinery/air_alarm.dm
index 8d3933faca..874b04b51b 100644
--- a/code/game/machinery/air_alarm.dm
+++ b/code/game/machinery/air_alarm.dm
@@ -154,6 +154,12 @@
update_icon()
+/obj/machinery/alarm/proc/update_area()
+ alarm_area = get_area(src)
+ area_uid = "\ref[alarm_area]"
+ if(name == "alarm")
+ name = "[alarm_area.name] Air Alarm"
+
/obj/machinery/alarm/Initialize()
. = ..()
set_frequency(frequency)
@@ -540,9 +546,9 @@
var/list/list/environment_data = list()
data["environment_data"] = environment_data
-
+
DECLARE_TLV_VALUES
-
+
var/pressure = environment.return_pressure()
LOAD_TLV_VALUES(TLV["pressure"], pressure)
environment_data.Add(list(list(
@@ -551,7 +557,7 @@
"unit" = "kPa",
"danger_level" = TEST_TLV_VALUES
)))
-
+
var/temperature = environment.temperature
LOAD_TLV_VALUES(TLV["temperature"], temperature)
environment_data.Add(list(list(
@@ -573,7 +579,7 @@
"unit" = "%",
"danger_level" = TEST_TLV_VALUES
)))
-
+
if(!locked || issilicon(user) || data["remoteUser"])
var/list/list/vents = list()
data["vents"] = vents
@@ -595,7 +601,7 @@
"extdefault"= (info["external"] == ONE_ATMOSPHERE),
"intdefault"= (info["internal"] == 0),
)))
-
+
var/list/list/scrubbers = list()
data["scrubbers"] = scrubbers
@@ -622,7 +628,7 @@
data["scrubbers"] = scrubbers
data["mode"] = mode
-
+
var/list/list/modes = list()
data["modes"] = modes
modes[++modes.len] = list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0)
@@ -682,7 +688,7 @@
else
target_temperature = input_temperature + T0C
return TRUE
-
+
// Account for remote users here.
// Yes, this is kinda snowflaky; however, I would argue it would be far more snowflakey
// to include "custom hrefs" and all the other bullshit that nano states have just for the
diff --git a/code/game/machinery/casino_ch.dm b/code/game/machinery/casino_ch.dm
index 13c65bc335..e892d1218b 100644
--- a/code/game/machinery/casino_ch.dm
+++ b/code/game/machinery/casino_ch.dm
@@ -277,7 +277,7 @@
"sodawater", "lemon_lime", "sugar", "orangejuice", "limejuice", "watermelonjuice", "thirteenloko", "grapesoda",
"coffee", "cafe_latte", "soy_latte", "hot_coco", "milk", "cream", "tea", "ice", "orangejuice", "lemonjuice",
"limejuice", "berryjuice", "mint", "lemon_lime", "sugar", "orangejuice", "limejuice", "sodawater",
- "tonic", "beer", "kahlua", "whiskey", "wine", "vodka", "gin", "rum", "tequilla", "vermouth", "cognac",
+ "tonic", "beer", "kahlua", "whiskey", "redwine", "vodka", "gin", "rum", "tequilla", "vermouth", "cognac",
"ale", "mead", "bitters", "champagne", "singulo", "doctorsdelight", "nothing", "banana", "honey", "egg",
"coco", "cherryjelly", "carrotjuice", "applejuice", "tomatojuice", "peanutbutter", "soymilk", "grenadine", "gingerale", "roy_rogers",
"patron", "goldschlager", "gelatin", "melonliquor", "bluecuracao", "thirteenloko", "deadrum", "sake", "acidspit",
diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm
index 4efec263f8..1d45a3e508 100644
--- a/code/game/machinery/computer/Operating.dm
+++ b/code/game/machinery/computer/Operating.dm
@@ -184,7 +184,7 @@
/obj/machinery/computer/operating/proc/build_surgery_list(mob/user)
if(!istype(victim))
return null
-
+
. = list()
for(var/limb in victim.organs_by_name)
@@ -281,6 +281,7 @@
/datum/surgery_step/cavity,
/datum/surgery_step/limb,
/datum/surgery_step/brainstem,
+ /datum/surgery_step/generic/ripper,
)
good_surgeries = surgery_steps
for(var/datum/surgery_step/S in good_surgeries)
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index 35a060863e..0226d0bc66 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -189,7 +189,7 @@
var/mob/M = grab.affecting
qdel(grab)
put_mob(M)
-
+
return
/obj/machinery/atmospherics/unary/cryo_cell/MouseDrop_T(var/mob/target, var/mob/user) //Allows borgs to put people into cryo without external assistance
@@ -226,6 +226,9 @@
if(occupant.bodytemperature < 225)
if(occupant.getToxLoss())
occupant.adjustToxLoss(max(-1, -20/occupant.getToxLoss()))
+ if(occupant.radiation || occupant.accumulated_rads)
+ occupant.radiation -= 25
+ occupant.accumulated_rads -= 25
var/heal_brute = occupant.getBruteLoss() ? min(1, 20/occupant.getBruteLoss()) : 0
var/heal_fire = occupant.getFireLoss() ? min(1, 20/occupant.getFireLoss()) : 0
occupant.heal_organ_damage(heal_brute,heal_fire)
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 38ac815cff..3ae04b718b 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -475,8 +475,8 @@
//Handle job slot/tater cleanup.
var/job = to_despawn.mind.assigned_role
-
job_master.FreeRole(job)
+ to_despawn.mind.assigned_role = null
if(to_despawn.mind.objectives.len)
qdel(to_despawn.mind.objectives)
@@ -526,12 +526,14 @@
//VOREStation Edit Start
var/depart_announce = TRUE
+ var/departing_job = to_despawn.mind.role_alt_title
+
if(istype(to_despawn, /mob/living/dominated_brain))
depart_announce = FALSE
if(depart_announce)
- announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE))
+ announce.autosay("[to_despawn.real_name][departing_job ? ", [departing_job], " : " "][on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE))
visible_message("\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2]", 3)
//VOREStation Edit End
diff --git a/code/game/machinery/deployable_vr.dm b/code/game/machinery/deployable_vr.dm
index bbb835b763..c939fea3f4 100644
--- a/code/game/machinery/deployable_vr.dm
+++ b/code/game/machinery/deployable_vr.dm
@@ -72,7 +72,7 @@
/obj/structure/barricade/cutout/attackby(var/obj/I, var/mob/user)
if(is_type_in_list(I, painters))
var/choice = tgui_input_list(user, "What would you like to paint the cutout as?", "Cutout Painting", cutout_types)
- if(!choice || !Adjacent(user, src) || I != user.get_active_hand())
+ if(!choice || !Adjacent(user) || I != user.get_active_hand())
return TRUE
if(do_after(user, 10 SECONDS, src))
var/picked_type = cutout_types[choice]
diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm
index 6e5618d39e..6a66f568cd 100644
--- a/code/game/machinery/door_control.dm
+++ b/code/game/machinery/door_control.dm
@@ -149,6 +149,41 @@
M.close()
return
+//CHOMP Add start
+/obj/machinery/button/remote/blast_door/bear
+ name = "stuffed bear"
+ icon = 'icons/obj/stationobjs_vr.dmi'
+ icon_state = "stuffedbear"
+ desc = "A stuffed and mounted bear. Quite a statement piece, but holds a curious glare."
+ density = 1
+
+/obj/machinery/button/remote/blast_door/bear/attack_hand(mob/user as mob) //code to stop bear ever reverting to standard button sprites
+ if(..())
+ return
+
+ add_fingerprint(user)
+ if(stat & (NOPOWER|BROKEN))
+ return
+
+ if(!allowed(user) && (wires & 1))
+ to_chat(user, "Access Denied")
+ flick("doorctrl-denied",src)
+ return
+
+ use_power(5)
+ icon_state = "stuffedbear"
+ desiredstate = !desiredstate
+ trigger(user)
+ spawn(15)
+ update_icon()
+
+/obj/machinery/button/remote/blast_door/bear/update_icon()
+ if(stat & NOPOWER)
+ icon_state = "stuffedbear"
+ else
+ icon_state = "stuffedbear"
+//CHOMP Add end
+
/*
Emitter remote control
*/
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index eb763daa2d..b1c6b23b71 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -43,6 +43,7 @@
var/obj/item/weapon/airlock_electronics/electronics = null
var/hasShocked = 0 //Prevents multiple shocks from happening
var/secured_wires = 0
+ var/security_level = 1 //VOREStation Addition - acts as a multiplier on the time required to hack an airlock with a hacktool
var/datum/wires/airlock/wires = null
var/open_sound_powered = 'sound/machines/door/covert1o.ogg'
@@ -129,6 +130,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/cmd3o.ogg'
department_close_powered = 'sound/machines/door/cmd3c.ogg'
+ security_level = 3 //VOREStation Addition
/obj/machinery/door/airlock/security
name = "Security Airlock"
@@ -139,6 +141,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/sec1o.ogg'
department_close_powered = 'sound/machines/door/sec1c.ogg'
+ security_level = 2 //VOREStation Addition
/obj/machinery/door/airlock/engineering
name = "Engineering Airlock"
@@ -149,6 +152,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/eng1o.ogg'
department_close_powered = 'sound/machines/door/eng1c.ogg'
+ security_level = 1.5 //VOREStation Addition
/obj/machinery/door/airlock/engineeringatmos
name = "Atmospherics Airlock"
@@ -159,6 +163,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/eng1o.ogg'
department_close_powered = 'sound/machines/door/eng1c.ogg'
+ security_level = 1.5 //VOREStation Addition
/obj/machinery/door/airlock/medical
name = "Medical Airlock"
@@ -169,6 +174,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/med1o.ogg'
department_close_powered = 'sound/machines/door/med1c.ogg'
+ security_level = 1.5 //VOREStation Addition
/obj/machinery/door/airlock/maintenance
name = "Maintenance Access"
@@ -260,6 +266,7 @@
opacity = 1
open_sound_powered = 'sound/machines/door/cmd3o.ogg'
close_sound_powered = 'sound/machines/door/cmd3c.ogg'
+ security_level = 100 //VOREStation Addition
/obj/machinery/door/airlock/glass_centcom
name = "Airlock"
@@ -268,6 +275,7 @@
glass = 1
open_sound_powered = 'sound/machines/door/cmd3o.ogg'
close_sound_powered = 'sound/machines/door/cmd3c.ogg'
+ security_level = 100 //VOREStation Addition
/obj/machinery/door/airlock/vault
name = "Vault"
@@ -279,6 +287,7 @@
req_one_access = list(access_heads_vault)
open_sound_powered = 'sound/machines/door/vault1o.ogg'
close_sound_powered = 'sound/machines/door/vault1c.ogg'
+ security_level = 5 //VOREStation Addition
/obj/machinery/door/airlock/vault/bolted
icon_state = "door_locked"
@@ -326,6 +335,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/cmd1o.ogg'
department_close_powered = 'sound/machines/door/cmd1c.ogg'
+ security_level = 3 //VOREStation Addition
/obj/machinery/door/airlock/glass_engineering
name = "Engineering Airlock"
@@ -339,6 +349,7 @@
req_one_access = list(access_engine)
department_open_powered = 'sound/machines/door/eng1o.ogg'
department_close_powered = 'sound/machines/door/eng1c.ogg'
+ security_level = 1.5 //VOREStation Addition
/obj/machinery/door/airlock/glass_engineeringatmos
name = "Atmospherics Airlock"
@@ -354,6 +365,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/eng1o.ogg'
department_close_powered = 'sound/machines/door/eng1c.ogg'
+ security_level = 1.5 //VOREStation Addition
/obj/machinery/door/airlock/glass_security
name = "Security Airlock"
@@ -369,6 +381,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/sec1o.ogg'
department_close_powered = 'sound/machines/door/sec1c.ogg'
+ security_level = 2 //VOREStation Additio
/obj/machinery/door/airlock/glass_medical
name = "Medical Airlock"
@@ -384,6 +397,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/med1o.ogg'
department_close_powered = 'sound/machines/door/med1c.ogg'
+ security_level = 1.5 //VOREStation Addition
/obj/machinery/door/airlock/mining
name = "Mining Airlock"
@@ -404,6 +418,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/eng1o.ogg'
department_close_powered = 'sound/machines/door/eng1c.ogg'
+ security_level = 1.5 //VOREStation Addition
/obj/machinery/door/airlock/research
name = "Research Airlock"
@@ -413,6 +428,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/sci1o.ogg'
department_close_powered = 'sound/machines/door/sci1c.ogg'
+ security_level = 2 //VOREStation Addition
/obj/machinery/door/airlock/glass_research
name = "Research Airlock"
@@ -428,6 +444,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/sci1o.ogg'
department_close_powered = 'sound/machines/door/sci1c.ogg'
+ security_level = 2 //VOREStation Addition
/obj/machinery/door/airlock/glass_mining
name = "Mining Airlock"
@@ -458,6 +475,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/eng1o.ogg'
department_close_powered = 'sound/machines/door/eng1c.ogg'
+ security_level = 1.5 //VOREStation Addition
/obj/machinery/door/airlock/gold
name = "Gold Airlock"
@@ -542,6 +560,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/sci1o.ogg'
department_close_powered = 'sound/machines/door/sci1c.ogg'
+ security_level = 1.5 //VOREStation Addition
/obj/machinery/door/airlock/glass_science
name = "Glass Airlocks"
@@ -554,6 +573,7 @@
close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off.
department_open_powered = 'sound/machines/door/sci1o.ogg'
department_close_powered = 'sound/machines/door/sci1c.ogg'
+ security_level = 1.5 //VOREStation Addition
/obj/machinery/door/airlock/highsecurity
name = "Secure Airlock"
@@ -564,6 +584,7 @@
req_one_access = list(access_heads_vault)
open_sound_powered = 'sound/machines/door/secure1o.ogg'
close_sound_powered = 'sound/machines/door/secure1c.ogg'
+ security_level = 4 //VOREStation Addition
/obj/machinery/door/airlock/voidcraft
name = "voidcraft hatch"
@@ -611,6 +632,7 @@
hackProof = TRUE
assembly_type = /obj/structure/door_assembly/door_assembly_alien
req_one_access = list(access_alien)
+ security_level = 100 //VOREStation Addition
/obj/machinery/door/airlock/alien/locked
icon_state = "door_locked"
diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm
index cc8227147c..9c6950bfbe 100644
--- a/code/game/machinery/doors/blast_door.dm
+++ b/code/game/machinery/doors/blast_door.dm
@@ -319,6 +319,15 @@
density = FALSE
opacity = 0
+/obj/machinery/door/blast/regular/bookcase //CHOMP Add code block
+ name = "bookcase"
+ desc = "On closer inspection, the array of books is decorative and built into the frame."
+ icon_state = "bookcase1"
+ icon_state_open = "bookcase0"
+ icon_state_opening = "bookcasec0"
+ icon_state_closed = "bookcase1"
+ icon_state_closing = "bookcasec1"
+
// SUBTYPE: Shutters
// Nicer looking, and also weaker, shutters. Found in kitchen and similar areas.
/obj/machinery/door/blast/shutters
@@ -456,4 +465,4 @@
#undef BLAST_DOOR_CRUSH_DAMAGE
-#undef SHUTTER_CRUSH_DAMAGE
\ No newline at end of file
+#undef SHUTTER_CRUSH_DAMAGE
diff --git a/code/game/machinery/frame.dm b/code/game/machinery/frame.dm
index d651ad2025..6c71e63207 100644
--- a/code/game/machinery/frame.dm
+++ b/code/game/machinery/frame.dm
@@ -81,31 +81,6 @@
frame_class = FRAME_CLASS_MACHINE
frame_size = 4
-/datum/frame/frame_types/oven
- name = "Oven"
- frame_class = FRAME_CLASS_MACHINE
- frame_size = 4
-
-/datum/frame/frame_types/fryer
- name = "Fryer"
- frame_class = FRAME_CLASS_MACHINE
- frame_size = 4
-
-/datum/frame/frame_types/grill
- name = "Grill"
- frame_class = FRAME_CLASS_MACHINE
- frame_size = 4
-
-/datum/frame/frame_types/cerealmaker
- name = "Cereal Maker"
- frame_class = FRAME_CLASS_MACHINE
- frame_size = 4
-
-/datum/frame/frame_types/candymachine
- name = "Candy Machine"
- frame_class = FRAME_CLASS_MACHINE
- frame_size = 4
-
/datum/frame/frame_types/fax
name = "Fax"
frame_class = FRAME_CLASS_MACHINE
@@ -221,7 +196,7 @@
frame_style = FRAME_STYLE_WALL
x_offset = 28
y_offset = 28
-
+
/datum/frame/frame_types/arfgs
name = "ARF Generator"
frame_class = FRAME_CLASS_MACHINE
diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm
index 1e1fff180e..be37e988b8 100644
--- a/code/game/machinery/navbeacon.dm
+++ b/code/game/machinery/navbeacon.dm
@@ -150,7 +150,7 @@ Transponder Codes:"}
usr.set_machine(src)
if(href_list["locedit"])
- var/newloc = sanitize(tgui_input_text(usr, "Enter New Location", "Navigation Beacon", location))
+ var/newloc = sanitize(tgui_input_text(usr, "Enter New Location", "Navigation Beacon", location, MAX_NAME_LEN))
if(newloc)
location = newloc
updateDialog()
@@ -158,12 +158,14 @@ Transponder Codes:
"}
else if(href_list["edit"])
var/codekey = href_list["code"]
- var/newkey = tgui_input_text(usr, "Enter Transponder Code Key", "Navigation Beacon", codekey)
+ var/newkey = tgui_input_text(usr, "Enter Transponder Code Key", "Navigation Beacon", codekey, MAX_NAME_LEN)
+ newkey = sanitize(newkey,MAX_NAME_LEN)
if(!newkey)
return
var/codeval = codes[codekey]
- var/newval = tgui_input_text(usr, "Enter Transponder Code Value", "Navigation Beacon", codeval)
+ var/newval = tgui_input_text(usr, "Enter Transponder Code Value", "Navigation Beacon", codeval, MAX_NAME_LEN)
+ newval = sanitize(newval,MAX_NAME_LEN)
if(!newval)
newval = codekey
return
@@ -180,11 +182,13 @@ Transponder Codes:
"}
else if(href_list["add"])
- var/newkey = tgui_input_text(usr, "Enter New Transponder Code Key", "Navigation Beacon")
+ var/newkey = tgui_input_text(usr, "Enter New Transponder Code Key", "Navigation Beacon", null, MAX_NAME_LEN)
+ newkey = sanitize(newkey,MAX_NAME_LEN)
if(!newkey)
return
- var/newval = tgui_input_text(usr, "Enter New Transponder Code Value", "Navigation Beacon")
+ var/newval = tgui_input_text(usr, "Enter New Transponder Code Value", "Navigation Beacon", null, MAX_NAME_LEN)
+ newval = sanitize(newval,MAX_NAME_LEN)
if(!newval)
newval = "1"
return
diff --git a/code/game/machinery/pointdefense.dm b/code/game/machinery/pointdefense.dm
index 2a98271836..aee8710c05 100644
--- a/code/game/machinery/pointdefense.dm
+++ b/code/game/machinery/pointdefense.dm
@@ -10,6 +10,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
/obj/machinery/pointdefense_control
name = "fire assist mainframe"
desc = "A specialized computer designed to synchronize a variety of weapon systems and a vessel's astronav data."
+ description_info = "To connect the mainframe to turrets, use a multitool to set the ident tag to that of the turrets."
icon = 'icons/obj/pointdefense.dmi'
icon_state = "control"
power_channel = EQUIP // CHOMPStation Edit Starts
@@ -97,7 +98,8 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
/obj/machinery/pointdefense_control/attackby(var/obj/item/W, var/mob/user)
if(W?.is_multitool())
- var/new_ident = tgui_input_text(user, "Enter a new ident tag.", "[src]", id_tag)
+ var/new_ident = tgui_input_text(user, "Enter a new ident tag.", "[src]", id_tag, MAX_NAME_LEN)
+ new_ident = sanitize(new_ident,MAX_NAME_LEN)
if(new_ident && new_ident != id_tag && user.Adjacent(src) && CanInteract(user, GLOB.tgui_physical_state))
// Check for duplicate controllers with this ID
for(var/obj/machinery/pointdefense_control/PC as anything in GLOB.pointdefense_controllers)
@@ -125,7 +127,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
icon = 'icons/obj/pointdefense.dmi'
icon_state = "pointdefense2"
desc = "A Kuiper pattern anti-meteor battery. Capable of destroying most threats in a single salvo."
- description_info = "Must have the same ident tag as a fire assist mainframe on the same facility."
+ description_info = "Must have the same ident tag as a fire assist mainframe on the same facility. Use a multitool to set the ident tag."
density = TRUE
anchored = TRUE
circuit = /obj/item/weapon/circuitboard/pointdefense
@@ -137,7 +139,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
var/last_shot = 0
var/kill_range = 18
var/rotation_speed = 4.5 SECONDS //How quickly we turn to face threats
- var/engaging = FALSE
+ var/weakref/engaging = null // The meteor we're shooting at
var/id_tag = null
/obj/machinery/pointdefense/Initialize()
@@ -146,17 +148,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
if(ispath(circuit))
circuit = new circuit(src)
default_apply_parts()
- // if(anchored)
- // connect_to_network()
update_icon()
- var/image/I = image(icon, icon_state = "[icon_state]_under")
- I.appearance_flags |= RESET_TRANSFORM
- underlays += I
-
-// /obj/machinery/pointdefense/examine(mob/user)
-// . = ..()
-// if(powernet)
-// . += "It is connected to a power cable below."
/obj/machinery/pointdefense/get_description_interaction()
. = ..()
@@ -169,38 +161,12 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
else
icon_state = initial(icon_state)
-/obj/machinery/pointdefense/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/W, var/time)
- if((. = ..()))
- src.transform = null // Reset rotation if we're anchored/unanchored
-
-////////// This machine is willing to take power from cables OR APCs. Handle NOPOWER stat specially here! ////////
-/*
-/obj/machinery/pointdefense/connect_to_network()
- if((. = ..()))
- stat &= ~NOPOWER // We now ignore APC power
- update_icon()
-
-/obj/machinery/pointdefense/disconnect_from_network()
- if((. = ..()))
- power_change() // We're back on APC power.
-
/obj/machinery/pointdefense/power_change()
- if(powernet)
- return // We don't care, we are cable powered anyway
var/old_stat = stat
..()
if(old_stat != stat)
update_icon()
-// Decide where to get the power to fire from
-/obj/machinery/pointdefense/use_power_oneoff(var/amount, var/chan = -1)
- if(powernet)
- return draw_power(amount)
- else if(powered(chan))
- use_power(amount, chan)
- return amount
- return 0 */
-
// Find controller with the same tag on connected z levels (if any)
/obj/machinery/pointdefense/proc/get_controller()
if(!id_tag)
@@ -212,7 +178,8 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
/obj/machinery/pointdefense/attackby(var/obj/item/W, var/mob/user)
if(W?.is_multitool())
- var/new_ident = tgui_input_text(user, "Enter a new ident tag.", "[src]", id_tag)
+ var/new_ident = tgui_input_text(user, "Enter a new ident tag.", "[src]", id_tag, MAX_NAME_LEN)
+ new_ident = sanitize(new_ident,MAX_NAME_LEN)
if(new_ident && new_ident != id_tag && user.Adjacent(src) && CanInteract(user, GLOB.tgui_physical_state))
to_chat(user, "You register [src] with the [new_ident] network.")
id_tag = new_ident
@@ -223,8 +190,6 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
return
if(default_part_replacement(user, W))
return
- if(default_unfasten_wrench(user, W, 40))
- return
return ..()
//Guns cannot shoot through hull or generally dense turfs.
@@ -237,8 +202,9 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
/obj/machinery/pointdefense/proc/Shoot(var/weakref/target)
var/obj/effect/meteor/M = target.resolve()
if(!istype(M))
+ engaging = null
return
- engaging = TRUE
+ engaging = target
var/Angle = round(Get_Angle(src,M))
var/matrix/rot_matrix = matrix()
rot_matrix.Turn(Angle)
@@ -248,47 +214,38 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
set_dir(ATAN2(transform.b, transform.a) > 0 ? NORTH : SOUTH)
/obj/machinery/pointdefense/proc/finish_shot(var/weakref/target)
- //Cleanup from list
var/obj/machinery/pointdefense_control/PC = get_controller()
- if(istype(PC))
- PC.targets -= target
+ engaging = null
+ PC.targets -= target
- engaging = FALSE
last_shot = world.time
var/obj/effect/meteor/M = target.resolve()
if(!istype(M))
return
- /*if(use_power_oneoff(active_power_usage) < active_power_usage)
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- visible_message("[src] sputters as browns out while attempting to fire.")
- flick(src, "[initial(icon_state)]_off")
- return */
//We throw a laser but it doesnt have to hit for meteor to explode
var/obj/item/projectile/beam/pointdefense/beam = new(get_turf(src))
playsound(src, 'sound/weapons/mandalorian.ogg', 75, 1)
+ use_power_oneoff(idle_power_usage * 10)
beam.launch_projectile(target = M.loc, user = src)
- M.make_debris()
- qdel(M)
/obj/machinery/pointdefense/process()
..()
- if(!anchored || stat & (BROKEN))
+ if(stat & (BROKEN))
return
if(!active)
return
- /*
var/desiredir = ATAN2(transform.b, transform.a) > 0 ? NORTH : SOUTH
if(dir != desiredir)
set_dir(desiredir)
- */
+
if(LAZYLEN(GLOB.meteor_list) > 0)
find_and_shoot()
/obj/machinery/pointdefense/proc/find_and_shoot()
+ // There ARE meteors to shoot
if(LAZYLEN(GLOB.meteor_list) == 0)
return
+ // We can shoot
if(engaging || ((world.time - last_shot) < charge_cooldown))
return
@@ -296,29 +253,42 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
if(!istype(PC) || !PC.powered(EQUIP))
return
- var/list/connected_z_levels = GetConnectedZlevels(get_z(src))
- for(var/obj/effect/meteor/M in GLOB.meteor_list)
- var/already_targeted = FALSE
- for(var/weakref/WR in PC.targets)
- var/obj/effect/meteor/m = WR.resolve()
- if(m == M)
- already_targeted = TRUE
- break
- if(!istype(m))
- PC.targets -= WR
+ // Compile list of known targets
+ var/list/existing_targets = list()
+ for(var/weakref/WR in PC.targets)
+ var/obj/effect/meteor/M = WR.resolve()
+ existing_targets += M
- if(already_targeted)
- continue
-
- if(!(M.z in connected_z_levels))
- continue
- if(get_dist(M, src) > kill_range)
- continue
- if(!emagged && space_los(M))
+ // First, try and acquire new targets
+ var/list/potential_targets = GLOB.meteor_list.Copy() - existing_targets
+ for(var/obj/effect/meteor/M in potential_targets)
+ if(targeting_check(M))
var/weakref/target = weakref(M)
PC.targets += target
+ engaging = target
Shoot(target)
return
+
+ // Then, focus fire on existing targets
+ for(var/obj/effect/meteor/M in existing_targets)
+ if(targeting_check(M))
+ var/weakref/target = weakref(M)
+ engaging = target
+ Shoot(target)
+ return
+
+/obj/machinery/pointdefense/proc/targeting_check(var/obj/effect/meteor/M)
+ // Target in range
+ var/list/connected_z_levels = GetConnectedZlevels(get_z(src))
+ if(!(M.z in connected_z_levels))
+ return FALSE
+ if(get_dist(M, src) > kill_range)
+ return FALSE
+ // If we can shoot it, then shoot
+ if(emagged || !space_los(M))
+ return FALSE
+
+ return TRUE
/obj/machinery/pointdefense/RefreshParts()
. = ..()
@@ -354,32 +324,3 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
active = FALSE
update_icon()
return TRUE
-
-//
-// Projectile Beam Definitions
-//
-
-/obj/item/projectile/beam/pointdefense
- name = "point defense salvo"
- icon_state = "laser"
- damage = 15
- damage_type = ELECTROCUTE //You should be safe inside a voidsuit
- sharp = FALSE //"Wide" spectrum beam
- light_color = COLOR_GOLD
-
- muzzle_type = /obj/effect/projectile/muzzle/pointdefense
- tracer_type = /obj/effect/projectile/tracer/pointdefense
- impact_type = /obj/effect/projectile/impact/pointdefense
-
-
-/obj/effect/projectile/tracer/pointdefense
- icon = 'icons/obj/projectiles_vr.dmi'
- icon_state = "beam_pointdef"
-
-/obj/effect/projectile/muzzle/pointdefense
- icon = 'icons/obj/projectiles_vr.dmi'
- icon_state = "muzzle_pointdef"
-
-/obj/effect/projectile/impact/pointdefense
- icon = 'icons/obj/projectiles_vr.dmi'
- icon_state = "impact_pointdef"
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index 81e04792c1..cc71d5983c 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -903,7 +903,6 @@
var/check_weapons
var/check_anomalies
var/check_all
- var/check_down
var/ailock
/obj/machinery/porta_turret/proc/setState(var/datum/turret_checks/TC)
@@ -919,7 +918,6 @@
check_weapons = TC.check_weapons
check_anomalies = TC.check_anomalies
check_all = TC.check_all
- check_down = TC.check_down
ailock = TC.ailock
power_change()
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 115e5e710a..9781ad98a0 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -10,7 +10,7 @@
active_power_usage = 40000 //40 kW
var/efficiency = 40000 //will provide the modified power rate when upgraded
var/obj/item/charging = null
- var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/modular_computer, /obj/item/weapon/computer_hardware/battery_module, /obj/item/weapon/cell, /obj/item/device/suit_cooling_unit/emergency, /obj/item/device/flashlight, /obj/item/device/electronic_assembly, /obj/item/weapon/weldingtool/electric, /obj/item/ammo_magazine/smart, /obj/item/device/flash, /obj/item/device/defib_kit, /obj/item/ammo_casing/microbattery, /obj/item/device/paicard, /obj/item/ammo_magazine/cell_mag, /obj/item/weapon/gun/projectile/cell_loaded) // CHOMPedit: medigun stuff
+ var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/modular_computer, /obj/item/weapon/computer_hardware/battery_module, /obj/item/weapon/cell, /obj/item/device/suit_cooling_unit/emergency, /obj/item/device/flashlight, /obj/item/device/electronic_assembly, /obj/item/weapon/weldingtool/electric, /obj/item/ammo_magazine/smart, /obj/item/device/flash, /obj/item/device/defib_kit, /obj/item/ammo_casing/microbattery, /obj/item/device/paicard, /obj/item/ammo_magazine/cell_mag, /obj/item/weapon/gun/projectile/cell_loaded, /obj/item/device/personal_shield_generator) // CHOMPedit: medigun stuff
var/icon_state_charged = "recharger2"
var/icon_state_charging = "recharger1"
var/icon_state_idle = "recharger0" //also when unpowered
@@ -28,7 +28,8 @@
. += "[charging ? "[charging]" : "Nothing"] is in [src]."
if(charging)
var/obj/item/weapon/cell/C = charging.get_cell()
- . += "Current charge: [C.charge] / [C.maxcharge]"
+ if(C) // Sometimes we get things without cells in it.
+ . += "Current charge: [C.charge] / [C.maxcharge]"
/obj/machinery/recharger/attackby(obj/item/weapon/G as obj, mob/user as mob)
var/allowed = 0
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index a1d44b9838..67fc80168a 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -84,6 +84,16 @@
R.adjustBruteLoss(-weld_rate)
if(wire_rate && R.getFireLoss() && cell.checked_use(wire_power_use * wire_rate * CELLRATE))
R.adjustFireLoss(-wire_rate)
+
+ //VOREStation Add Start
+ else if(ispAI(occupant))
+ var/mob/living/silicon/pai/P = occupant
+
+ if(P.nutrition < 400)
+ P.nutrition = min(P.nutrition+10, 400)
+ cell.use(7000/450*10)
+ //VOREStation Add End
+
else if(ishuman(occupant))
var/mob/living/carbon/human/H = occupant
@@ -100,12 +110,13 @@
// Also recharge their internal battery.
if(H.isSynthetic() && H.nutrition < 500) //VOREStation Edit
- H.nutrition = min(H.nutrition+10, 500) //VOREStation Edit
+ H.nutrition = min(H.nutrition+(10*(1-H.species.synthetic_food_coeff)), 500) //VOREStation Edit
cell.use(7000/450*10)
// And clear up radiation
- if(H.radiation > 0)
- H.radiation = max(H.radiation - rand(5, 15), 0)
+ if(H.radiation > 0 || H.accumulated_rads > 0)
+ H.radiation = max(H.radiation - 25, 0)
+ H.accumulated_rads = max(H.accumulated_rads - 25, 0)
if(H.wearing_rig) // stepping into a borg charger to charge your rig and fix your shit
var/obj/item/weapon/rig/wornrig = H.get_rig()
@@ -198,7 +209,7 @@
desc += "
It is capable of repairing burn damage."
/obj/machinery/recharge_station/proc/build_overlays()
- cut_overlay()
+ cut_overlays()
switch(round(chargepercentage()))
if(1 to 20)
add_overlay("statn_c0")
@@ -257,6 +268,21 @@
occupant = R
update_icon()
return 1
+
+ //VOREStation Add Start
+ else if(istype(L, /mob/living/silicon/pai))
+ var/mob/living/silicon/pai/P = L
+
+ if(P.incapacitated())
+ return
+
+ add_fingerprint(P)
+ P.reset_view(src)
+ P.forceMove(src)
+ occupant = P
+ update_icon()
+ return 1
+ //VOREStation Add End
else if(istype(L, /mob/living/carbon/human))
var/mob/living/carbon/human/H = L
@@ -323,4 +349,4 @@
icon_state = "borg_pod_opened"
if(icon_update_tick == 0)
- build_overlays()
\ No newline at end of file
+ build_overlays()
diff --git a/code/game/machinery/suit_cycler_datums.dm b/code/game/machinery/suit_cycler_datums.dm
index 4d84d116af..6cc706aea1 100644
--- a/code/game/machinery/suit_cycler_datums.dm
+++ b/code/game/machinery/suit_cycler_datums.dm
@@ -346,3 +346,5 @@ GLOBAL_LIST_EMPTY(suit_cycler_emagged)
name = SPECIES_SERGAL
/datum/suit_cycler_choice/species/vulpkanin
name = SPECIES_VULPKANIN
+/datum/suit_cycler_choice/species/altevian
+ name = SPECIES_ALTEVIAN
diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm
index 461a200481..2de8d04a49 100644
--- a/code/game/machinery/telecomms/logbrowser.dm
+++ b/code/game/machinery/telecomms/logbrowser.dm
@@ -46,7 +46,7 @@
for(var/c in SelectedServer.log_entries)
i++
var/datum/comm_log_entry/C = c
-
+
// This is necessary to prevent leaking information to the clientside
var/static/list/acceptable_params = list("uspeech", "intelligible", "message", "name", "race", "job", "timecode")
var/list/parameters = list()
@@ -74,7 +74,7 @@
if(!ui)
ui = new(user, src, "TelecommsLogBrowser", name)
ui.open()
-
+
/obj/machinery/computer/telecomms/server/tgui_act(action, params)
if(..())
return TRUE
@@ -128,7 +128,8 @@
. = TRUE
if("network")
- var/newnet = tgui_input_text(usr, "Which network do you want to view?", "Comm Monitor", network)
+ var/newnet = tgui_input_text(usr, "Which network do you want to view?", "Comm Monitor", network, 15)
+ newnet = sanitize(newnet,15)
if(newnet && ((usr in range(1, src) || issilicon(usr))))
if(length(newnet) > 15)
@@ -139,7 +140,7 @@
set_temp("NEW NETWORK TAG SET IN ADDRESS \[[network]\]", "good")
. = TRUE
-
+
if("cleartemp")
temp = null
. = TRUE
diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm
index 5bc216dac6..24394b2bc3 100644
--- a/code/game/machinery/telecomms/machine_interactions.dm
+++ b/code/game/machinery/telecomms/machine_interactions.dm
@@ -41,7 +41,7 @@
/obj/machinery/telecomms/tgui_data(mob/user)
var/list/data = list()
-
+
data["temp"] = temp
data["on"] = on
@@ -81,7 +81,7 @@
"index" = i,
)))
data["linked"] = linked
-
+
var/list/filter = list()
for(var/x in freq_listening)
filter.Add(list(list(
@@ -213,7 +213,7 @@
/obj/machinery/telecomms/bus/Options_Act(action, params)
if(..())
return TRUE
-
+
switch(action)
if("change_freq")
. = TRUE
@@ -267,7 +267,7 @@
/obj/machinery/telecomms/receiver/Options_Act(action, params)
if(..())
return TRUE
-
+
switch(action)
if("range")
var/new_range = params["range"]
@@ -296,6 +296,7 @@
if("network")
var/newnet = tgui_input_text(usr, "Specify the new network for this machine. This will break all current links.", src, network)
+ newnet = sanitize(newnet,15)
if(newnet && canAccess(usr))
if(length(newnet) > 15)
diff --git a/code/game/machinery/telecomms/telemonitor.dm b/code/game/machinery/telecomms/telemonitor.dm
index 3014474b8e..cf9ab2096d 100644
--- a/code/game/machinery/telecomms/telemonitor.dm
+++ b/code/game/machinery/telecomms/telemonitor.dm
@@ -100,7 +100,8 @@
. = TRUE
if("network")
- var/newnet = tgui_input_text(usr, "Which network do you want to view?", "Comm Monitor", network)
+ var/newnet = tgui_input_text(usr, "Which network do you want to view?", "Comm Monitor", network, 15)
+ newnet = sanitize(newnet,15) //Honestly, I'd be amazed if someone managed to do HTML in 15 chars.
if(newnet && ((usr in range(1, src) || issilicon(usr))))
if(length(newnet) > 15)
set_temp("FAILED: NETWORK TAG STRING TOO LENGTHY", "bad")
@@ -108,7 +109,7 @@
network = newnet
machinelist = list()
set_temp("NEW NETWORK TAG SET IN ADDRESS \[[network]\]", "good")
-
+
. = TRUE
if("cleartemp")
diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm
index cf7f9946aa..17dbed4e2c 100644
--- a/code/game/machinery/telecomms/traffic_control.dm
+++ b/code/game/machinery/telecomms/traffic_control.dm
@@ -192,7 +192,8 @@
if(href_list["network"])
- var/newnet = tgui_input_text(usr, "Which network do you want to view?", "Comm Monitor", network)
+ var/newnet = tgui_input_text(usr, "Which network do you want to view?", "Comm Monitor", network, 15)
+ newnet = sanitize(newnet,15)
if(newnet && ((usr in range(1, src) || issilicon(usr))))
if(length(newnet) > 15)
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index 505ff94947..dc0a70f711 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -92,8 +92,8 @@
return
-/obj/machinery/teleport/station/attack_ai()
- attack_hand()
+/obj/machinery/teleport/station/attack_ai(mob/user)
+ attack_hand(user)
/obj/machinery/computer/teleporter/attack_ai(mob/user)
teleport_control.tgui_interact(user)
diff --git a/code/game/machinery/turret_control.dm b/code/game/machinery/turret_control.dm
index 6e684974aa..cd0ebf2d71 100644
--- a/code/game/machinery/turret_control.dm
+++ b/code/game/machinery/turret_control.dm
@@ -194,7 +194,6 @@
TC.check_weapons = check_weapons
TC.check_anomalies = check_anomalies
TC.check_all = check_all
- TC.check_down = check_down
TC.ailock = ailock
if(istype(control_area))
diff --git a/code/game/machinery/virtual_reality/vr_console.dm b/code/game/machinery/virtual_reality/vr_console.dm
index 9d165cc7e3..b66bc2dff8 100644
--- a/code/game/machinery/virtual_reality/vr_console.dm
+++ b/code/game/machinery/virtual_reality/vr_console.dm
@@ -2,9 +2,9 @@
name = "virtual reality sleeper"
desc = "A fancy bed with built-in sensory I/O ports and connectors to interface users' minds with their bodies in virtual reality."
icon = 'icons/obj/Cryogenic2.dmi'
- icon_state = "syndipod_0"
+ icon_state = "body_scanner_0"
- var/base_state = "syndipod_"
+ var/base_state = "body_scanner_"
density = TRUE
anchored = TRUE
@@ -23,6 +23,7 @@
active_power_usage = 200
light_color = "#FF0000"
+
/obj/machinery/vr_sleeper/Initialize()
. = ..()
default_apply_parts()
@@ -88,9 +89,9 @@
-/obj/machinery/sleeper/relaymove(var/mob/user)
+/obj/machinery/vr_sleeper/relaymove(var/mob/user)
..()
- if(usr.incapacitated())
+ if(user.incapacitated())
return
go_out()
@@ -245,10 +246,15 @@
if(occupant.species.name != "Promethean" && occupant.species.name != "Human" && mirror_first_occupant)
avatar.shapeshifter_change_shape(occupant.species.name)
avatar.forceMove(get_turf(S)) // Put the mob on the landmark, instead of inside it
- avatar.Sleeping(1)
+//CHOMPedit start VR fix
occupant.enter_vr(avatar)
+ //Yes, I am using a aheal just so your markings transfer over, I could not get .prefs.copy_to working. This is very stupid, and I can't be assed to rewrite this. Too bad!
+ avatar.revive()
+ avatar.species.equip_survival_gear(avatar)
+ avatar.verbs += /mob/living/carbon/human/proc/exit_vr //ahealing removes the prommie verbs and the VR verbs, giving it back
+//CHOMPedit end
// Prompt for username after they've enterred the body.
var/newname = sanitize(tgui_input_text(avatar, "You are entering virtual reality. Your username is currently [src.name]. Would you like to change it to something else?", "Name change", null, MAX_NAME_LEN), MAX_NAME_LEN)
if (newname)
diff --git a/code/game/mecha/equipment/tools/drill.dm b/code/game/mecha/equipment/tools/drill.dm
index 2b64f93616..a7038eaa62 100644
--- a/code/game/mecha/equipment/tools/drill.dm
+++ b/code/game/mecha/equipment/tools/drill.dm
@@ -48,7 +48,8 @@
if(ore_box)
for(var/obj/item/weapon/ore/ore in range(chassis,1))
if(get_dir(chassis,ore)&chassis.dir)
- ore.forceMove(ore_box)
+ ore_box.stored_ore[ore.material]++
+ qdel(ore)
else if(isliving(target))
drill_mob(target, chassis.occupant)
return 1
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 59c9fc39cc..8d3ab1c8b4 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -572,7 +572,6 @@
/obj/mecha/proc/show_radial_occupant(var/mob/user)
var/list/choices = list(
- "Eject" = radial_image_eject,
"Toggle Airtank" = radial_image_airtoggle,
"Toggle Light" = radial_image_lighttoggle,
"View Stats" = radial_image_statpanel
@@ -584,9 +583,6 @@
if(!choice)
return
switch(choice)
- if("Eject")
- go_out()
- add_fingerprint(usr)
if("Toggle Airtank")
use_internal_tank = !use_internal_tank
occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].")
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index ce54008c45..61b4d90183 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -38,7 +38,8 @@
if(ore_box)
for(var/obj/item/weapon/ore/ore in range(1, src))
if(ore.Adjacent(src) && ((get_dir(src, ore) & dir) || ore.loc == loc)) //we can reach it and it's in front of us? grab it!
- ore.forceMove(ore_box)
+ ore_box.stored_ore[ore.material]++
+ qdel(ore)
/obj/mecha/working/ripley/Destroy()
for(var/atom/movable/A in src.cargo)
diff --git a/code/game/objects/banners.dm b/code/game/objects/banners.dm
index 0e4aaef6d8..d491e41119 100644
--- a/code/game/objects/banners.dm
+++ b/code/game/objects/banners.dm
@@ -31,6 +31,12 @@
desc = "A banner with the symbol of the Solar Confederate Government."
catalogue_data = list(/datum/category_item/catalogue/information/organization/solgov)
+/obj/item/weapon/banner/altevian
+ name = "\improper Altevian Hegemony Banner"
+ icon_state = "banner-altevian"
+ desc = "A banner that flies for the pride of the hegemony."
+ //catalogue_data = list(/datum/category_item/catalogue/information/organization/altevian_hegemony) // TODO?
+
//VOREStation Removal //CHOMP re-addition. Seriously? You commented this out for your lore? What's wrong with JUST NOT SPAWNING IT or something.
/obj/item/weapon/banner/virgov
name = "\improper VirGov banner"
diff --git a/code/game/objects/effects/bump_teleporter.dm b/code/game/objects/effects/bump_teleporter.dm
index 0286622705..581aeea16f 100644
--- a/code/game/objects/effects/bump_teleporter.dm
+++ b/code/game/objects/effects/bump_teleporter.dm
@@ -23,12 +23,12 @@ var/list/obj/effect/bump_teleporter/BUMP_TELEPORTERS = list()
if(!ismob(user))
//user.loc = src.loc //Stop at teleporter location
return
-
+ var/mob/M = user //VOREStation edit
if(!id_target)
//user.loc = src.loc //Stop at teleporter location, there is nowhere to teleport to.
return
for(var/obj/effect/bump_teleporter/BT in BUMP_TELEPORTERS)
if(BT.id == src.id_target)
- usr.loc = BT.loc //Teleport to location with correct id.
- return
\ No newline at end of file
+ M.forceMove(BT.loc) //Teleport to location with correct id. //VOREStation Edit
+ return
diff --git a/code/game/objects/effects/decals/remains.dm b/code/game/objects/effects/decals/remains.dm
index 95adae5e4b..6f8af8cdd9 100644
--- a/code/game/objects/effects/decals/remains.dm
+++ b/code/game/objects/effects/decals/remains.dm
@@ -58,9 +58,13 @@
/obj/effect/decal/remains/attack_hand(mob/user as mob)
to_chat(user, "[src] sinks together into a pile of ash.")
var/turf/simulated/floor/F = get_turf(src)
- if (istype(F))
+ if(istype(F))
new /obj/effect/decal/cleanable/ash(F)
qdel(src)
/obj/effect/decal/remains/robot/attack_hand(mob/user as mob)
- return
+ to_chat(user, "[src] crumbles down into a pile of debris.")
+ var/turf/simulated/floor/F = get_turf(src)
+ if(istype(F))
+ new /obj/effect/decal/cleanable/blood/gibs/robot(F)
+ qdel(src)
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index da675f6828..7c88ab8ad3 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -42,6 +42,10 @@
latejoin_gatewaystation += loc
delete_me = 1
return
+ if("JoinLateSifPlains")
+ latejoin_plainspath += loc
+ delete_me = 1
+ return
//CHOMPEdit End
if("JoinLateElevator")
latejoin_elevator += loc
diff --git a/code/game/objects/effects/map_effects/portal.dm b/code/game/objects/effects/map_effects/portal.dm
index ede5cbdaca..f07ba99767 100644
--- a/code/game/objects/effects/map_effects/portal.dm
+++ b/code/game/objects/effects/map_effects/portal.dm
@@ -51,7 +51,7 @@ when portals are shortly lived, or when portals are made to be obvious with spec
plane = TURF_PLANE
layer = ABOVE_TURF_LAYER
appearance_flags = NONE
-
+
var/obj/effect/map_effect/portal/counterpart = null // The portal line or master that this is connected to, on the 'other side'.
// Information used to apply `pixel_[x|y]` offsets so that the visuals line up.
@@ -71,8 +71,8 @@ when portals are shortly lived, or when portals are made to be obvious with spec
// Called when something touches the portal, and usually teleports them to the other side.
/obj/effect/map_effect/portal/Crossed(atom/movable/AM)
- if(AM.is_incorporeal())
- return
+ /*if(AM.is_incorporeal())
+ return CHOMPEdit: This is why phased critters couldn't enter z transits */
..()
if(!AM)
return
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 749797c433..89b0bc2e87 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -96,7 +96,7 @@
explode(M)
if(istype(M, /mob/living/))
- if(!M.hovering)
+ if(!M.hovering) //CHOMPedit: let's not make wings ignore mines because we use those here.
explode(M)
/obj/effect/mine/attackby(obj/item/W as obj, mob/living/user as mob)
@@ -398,6 +398,6 @@
// This tells AI mobs to not be dumb and step on mines willingly.
/obj/item/weapon/mine/is_safe_to_step(mob/living/L)
- if(!L.hovering)
+ if(!L.hovering) //CHOMPedit: Let's not trivialize mines.
return FALSE
return ..()
diff --git a/code/game/objects/effects/spawners/graffiti.dm b/code/game/objects/effects/spawners/graffiti.dm
index afac11f4f1..9450c90206 100644
--- a/code/game/objects/effects/spawners/graffiti.dm
+++ b/code/game/objects/effects/spawners/graffiti.dm
@@ -25,4 +25,4 @@
C.name = name
- qdel(src)
+ return INITIALIZE_HINT_QDEL
diff --git a/code/game/objects/effects/step_triggers.dm b/code/game/objects/effects/step_triggers.dm
index 56cc000dc9..9b66d1b3c1 100644
--- a/code/game/objects/effects/step_triggers.dm
+++ b/code/game/objects/effects/step_triggers.dm
@@ -13,13 +13,11 @@
return 0
/obj/effect/step_trigger/Crossed(atom/movable/H as mob|obj)
- if(H.is_incorporeal())
- return
+ if((istype(H, /mob/observer) && !affect_ghosts) || (!istype(H, /mob/observer) && H.is_incorporeal() && !affect_ghosts))
+ return //CHOMPEdit: Fixing some step trigger stuff to coincide with incorporeal check changes
..()
if(!H)
return
- if(istype(H, /mob/observer) && !affect_ghosts)
- return
Trigger(H)
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index eb2aefeb5c..c22ddaa46f 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -24,6 +24,18 @@
icon_state = "smoke"
duration = 50
+/obj/effect/temp_visual/glitch
+ icon_state = "glitch"
+ duration = 5
+
+/obj/effect/temp_visual/confuse
+ icon_state = "confuse"
+ duration = 5
+
+/obj/effect/temp_visual/pre_confuse
+ icon_state = "pre_confuse"
+ duration = 5
+
/obj/effect/temp_visual/impact_effect
icon_state = "impact_bullet"
plane = PLANE_LIGHTING_ABOVE // So they're visible even in a shootout in maint.
diff --git a/code/game/objects/effects/temporary_visuals/projectiles/impact.dm b/code/game/objects/effects/temporary_visuals/projectiles/impact.dm
index 6c99d70482..adecdbe1c0 100644
--- a/code/game/objects/effects/temporary_visuals/projectiles/impact.dm
+++ b/code/game/objects/effects/temporary_visuals/projectiles/impact.dm
@@ -94,4 +94,6 @@
light_range = 2
light_power = 0.5
light_color = "#80F5FF"
-//VOREStation edit ends
\ No newline at end of file
+//VOREStation edit ends
+/obj/effect/projectile/impact/pointdefense
+ icon_state = "impact_pointdef"
\ No newline at end of file
diff --git a/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm b/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm
index 9b3ff9e03c..44240eb487 100644
--- a/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm
+++ b/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm
@@ -106,4 +106,6 @@
light_range = 2
light_power = 0.5
light_color = "#80F5FF"
-//VOREStation edit ends
\ No newline at end of file
+//VOREStation edit ends
+/obj/effect/projectile/muzzle/pointdefense
+ icon_state = "muzzle_pointdef"
\ No newline at end of file
diff --git a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
index 1f2d72282a..9f05cc30ca 100644
--- a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
+++ b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
@@ -134,3 +134,5 @@
light_power = 0.5
light_color = "#80F5FF"
//VOREStation edit ends
+/obj/effect/projectile/tracer/pointdefense
+ icon_state = "beam_pointdef"
\ No newline at end of file
diff --git a/code/game/objects/explosion_recursive.dm b/code/game/objects/explosion_recursive.dm
index c530e37692..d60dc90f3e 100644
--- a/code/game/objects/explosion_recursive.dm
+++ b/code/game/objects/explosion_recursive.dm
@@ -94,12 +94,8 @@
if(power <= 0)
return
if(src in explosion_turfs)
- return
-
- explosion_turfs |= src
-
- if(explosion_turfs[src] >= power)
- return //The turf already sustained and spread a power greated than what we are dealing with. No point spreading again.
+ if(explosion_turfs[src] >= power)
+ return //The turf already sustained and spread a power greated than what we are dealing with. No point spreading again.
explosion_turfs[src] = power
var/spread_power = power - src.explosion_resistance //This is the amount of power that will be spread to the tile in the direction of the blast
@@ -112,7 +108,7 @@
T = get_step(src, turn(direction,90))
T.explosion_spread(spread_power, turn(direction,90), explosion_turfs)
T = get_step(src, turn(direction,-90))
- T.explosion_spread(spread_power, turn(direction,90), explosion_turfs)
+ T.explosion_spread(spread_power, turn(direction,-90), explosion_turfs)
/turf/unsimulated/explosion_spread(power)
return //So it doesn't get to the parent proc, which simulates explosions
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index d44ad2e73f..645168b041 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -106,7 +106,7 @@
var/drop_sound = "generic_drop"
var/tip_timer // reference to timer id for a tooltip we might open soon
-
+
var/no_random_knockdown = FALSE //stops item from being able to randomly knock people down in combat
/obj/item/Initialize(mapload) //CHOMPedit I stg I'm going to overwrite these many uncommented edits.
@@ -222,9 +222,12 @@
/obj/item/attack_hand(mob/living/user as mob)
if (!user) return
- if(anchored)
- to_chat(user, span("notice", "\The [src] won't budge, you can't pick it up!"))
- return
+ if(anchored) // Start CHOMPStation Edit
+ if(hascall(src, "attack_self"))
+ return src.attack_self(user)
+ else
+ to_chat ("This is anchored and you can't lift it.")
+ return // End CHOMPStation Edit
if (hasorgans(user))
var/mob/living/carbon/human/H = user
var/obj/item/organ/external/temp = H.organs_by_name["r_hand"]
@@ -261,7 +264,7 @@
ghost.assumeform(src)
ghost.animate_towards(user)
//VORESTATION EDIT START. This handles possessed items.
- if(src.possessed_voice.len && !(user.ckey in warned_of_possession)) //Is this item possessed?
+ if(src.possessed_voice && src.possessed_voice.len && !(user.ckey in warned_of_possession)) //Is this item possessed?
warned_of_possession |= user.ckey
tgui_alert_async(user,{"
THIS ITEM IS POSSESSED BY A PLAYER CURRENTLY IN THE ROUND. This could be by anomalous means or otherwise.
diff --git a/code/game/objects/items/blueprints_vr.dm b/code/game/objects/items/blueprints_vr.dm
new file mode 100644
index 0000000000..accae37f6b
--- /dev/null
+++ b/code/game/objects/items/blueprints_vr.dm
@@ -0,0 +1,940 @@
+#define BP_MAX_ROOM_SIZE 300
+
+// WARNING: ESOTERIC BULLSHIT INSIDE OF THIS FILE.
+// This is a port of /tg/'s blueprints that also have Virgo modifications as well.
+// However it is heavily modified and lacking the 't-ray' scanner functionality that /TG/ has. We have our own t-rays after all.
+// This works and uses a bunch of really odd hacks and trickery to get it to all function.
+// If you're looking at this a few years from now and going 'What the hell were they thinking' just know that this was the best we had at the time.
+
+// Now that I've scared away half the people looking at this file, here's the relevant info:
+
+// Banning areas: Go to global_lists_vr, jump to the BUILDABLE_AREA_TYPES and read the comments left there.
+
+
+
+
+// These areas are defined here so they can be blacklisted in global_lists_vr
+/area/tether/elevator
+
+ name = "Tether Elevator"
+
+/area/tether/surfacebase/outside
+ name = "Outside - Surface"
+
+/area/groundbase/unexplored/outdoors
+ name = "\improper Rascal's Pass"
+
+/area/groundbase/mining
+ name = "Mining"
+
+/area/groundbase/unexplored/rock
+ name = "\improper Rascal's Pass"
+
+/area/maintenance/groundbase/level1
+ name = "Groundbase Level One Maint"
+
+/area/submap/groundbase/wilderness
+ name = "Groundbase Wilderness"
+
+/area/offmap/aerostat/surface
+ name = "Aerostat Surface"
+
+/area/tether_away/beach
+ name = "\improper Away Mission - Virgo 4 Beach"
+
+/area/tether_away/cave
+ name = "Tether Away Cave"
+
+/area/offmap/aerostat/surface
+
+ name = "Aerostat Surface"
+
+/area/submap/virgo2
+ name = "Submap Area"
+
+/area/submap/casino_event
+ name = "\improper Space Casino"
+
+
+
+//TG blueprints.
+#define AREA_ERRNONE 0
+#define AREA_STATION 1
+#define AREA_SPACE 2
+#define AREA_SPECIAL 3
+
+/obj/item/areaeditor
+ name = "area modification item"
+ icon = 'icons/obj/items.dmi'
+ icon_state = "blueprints"
+ attack_verb = list("attacked", "bapped", "hit")
+ in_use = FALSE
+ preserve_item = 1
+ var/uses_charges = 0 // If the area editor has limited uses.
+ var/initial_charges = 10
+ var/charges = 10 // The amount of uses the area editor has.
+ var/station_master = 1 // If the areaeditor can add charges to others.
+ var/wire_schematics = 0 // If the areaeditor can see wires.
+ var/can_override = 0 // If you want the areaeditor to override the 'Don't make a new area where one already exists' logic. Only given to CE blueprints.
+
+ var/can_create_areas_in = AREA_SPACE // Must be standing in space to create
+ var/can_create_areas_into = AREA_SPACE // New areas will only overwrite space area turfs.
+ var/can_expand_areas_in = AREA_STATION // Must be standing in station to expand
+ var/can_expand_areas_into = AREA_SPACE // Can expand station areas only into space.
+ var/can_rename_areas_in = AREA_STATION // Only station areas can be reanamed
+
+
+ var/const/ROOM_ERR_LOLWAT = 0 // Don't touch these three consts or BYOND will literally tear out your throat
+ var/const/ROOM_ERR_SPACE = -1
+ var/const/ROOM_ERR_TOOLARGE = -2
+ var/const/ROOM_ERR_FORBIDDEN = -3
+
+ var/list/areaColor_turfs = list()
+ var/legend = 0 //If viewing wires or not.
+
+/obj/item/areaeditor/examine(mob/user)
+ . =..()
+ if(uses_charges && !isnull(charges))
+ . += "There appears to be enough space for a total of [charges] more changes!"
+ if(!charges)
+ . += "There seems to be no more room for any more edits!"
+
+/obj/item/areaeditor/attackby(obj/item/W, mob/user, params)
+ if(uses_charges && (charges < initial_charges) && istype(W, /obj/item/areaeditor)) //Do we have a reason to add charges? And is it something that COULD add charges?
+ var/missing_charges = initial_charges-charges
+ var/obj/item/areaeditor/blueprint = W
+ if(blueprint.station_master) //Master can refill.
+ charges = initial_charges
+ to_chat(user, span_notice("You add some more writing material to the [src] with the [blueprint]!"))
+ return
+ else if(blueprint.uses_charges && blueprint.charges) //Getting from another with limited charges.
+ var/to_add = tgui_input_number(user, "How many charges do you want to add to the [src]?", "[blueprint]", missing_charges)
+ if(!isnull(to_add) && blueprint.charges >= to_add)
+ to_chat(user, span_notice("You add some more writing material to the [src] with the [blueprint]!"))
+ blueprint.charges -= to_add
+ charges += to_add
+ return
+
+ else
+ to_chat(user, span_notice("You decide not to add any more material to the [src]"))
+ return
+ else if(!blueprint.uses_charges || !blueprint.charges) // The item it's being hit by doesn't use charges OR doesn't have any charges.
+ to_chat(user, span_warning("You can't add find any suitable material to add from the [blueprint]!"))
+ else
+ ..()
+
+/obj/item/areaeditor/attack_self(mob/user) //Convert this to TGUI some time.
+ add_fingerprint(user)
+ . = "[station_name()] [src.name]
"
+ switch(get_area_type())
+ if(AREA_SPACE)
+ . += "[station_name()] [src.name]
"
+ if(legend == TRUE)
+ . += view_station_wire_devices(user);
+ else
+ //legend is a wireset
+ . += "<< Back"
+ . += view_station_wire_set(user, legend)
+
+ var/datum/browser/popup = new(user, "blueprints", "[src]", 700, 500)
+ popup.set_content(.)
+ popup.open()
+ onclose(user, "blueprints")
+
+/obj/item/wire_reader/Topic(href, href_list)
+ if(..())
+ return
+ if(href_list["view_wireset"])
+ legend = href_list["view_wireset"];
+ if(href_list["view_legend"])
+ legend = TRUE
+ attack_self(usr)
+
+/obj/item/wire_reader/proc/view_station_wire_devices(mob/user)
+ var/message = "
You examine the wire legend.
"
+ for(var/wireset in GLOB.wire_color_directory)
+ //if(istype(wireset,/datum/wires/grid_checker))//Uncomment this in if you want the grid checker minigame to not be revealed here.
+ // continue
+ message += "
[GLOB.wire_name_directory[wireset]]"
+ message += "
[GLOB.wire_name_directory[device]]:" + for(var/Col in GLOB.wire_color_directory[device]) + var/wire_name = GLOB.wire_color_directory[device][Col] + if(!findtext(wire_name, WIRE_DUD_PREFIX)) //don't show duds + message += "
[Col]: [wire_name]
" + message += "" + return message + return "" + +//Station blueprints!!! +/obj/item/areaeditor/blueprints + name = "station blueprints" + desc = "Blueprints of the station. There is a \"Classified\" stamp and several coffee stains on it." + //var/list/image/showing = list() //For viewing pipes. Unused. + //var/client/viewing //For viewing pipes. Unused. + can_override = 1 //In case there is a reason for building in a non-blacklisted, non-buildable area. + +/obj/item/areaeditor/blueprints/engineers + name = "writing blueprints" + desc = "A piece of paper that allows for expansion of the station and creaiton of new areas. There is a \"For Official Use Only\" stamp on it. NOT to be mistaken with the staion blueprints." + station_master = 0 + uses_charges = 1 + can_override = 0 + + + + +/obj/item/areaeditor/blueprints/Destroy() + //clear_viewer() + return ..() + + +/obj/item/areaeditor/blueprints/attack_self(mob/user) + . = ..() + var/area/A = get_area(user) + if(!legend) + if(get_area_type() == AREA_STATION) + . += "According to \the [src], you are now in \"[html_encode(A.name)]\".
" + . += "" //You can change the name without charges. + if(wire_schematics) + . += "" + else + if(legend == TRUE) + . += "<< Back" + . += view_wire_devices(user); + else + //legend is a wireset + . += "<< Back" + . += view_wire_set(user, legend) + var/datum/browser/popup = new(user, "blueprints", "[src]", 700, 500) + popup.set_content(.) + popup.open() + onclose(user, "blueprints") + + +/obj/item/areaeditor/blueprints/Topic(href, href_list) + if(..()) + return + if(href_list["edit_area"]) + if(get_area_type()!=AREA_STATION) + return + if(in_use) + return + in_use = TRUE + edit_area() + in_use = FALSE + if(href_list["exit_legend"]) + legend = FALSE; + if(href_list["view_legend"]) + if(wire_schematics) //No href hacks allow for you, my friend! + legend = TRUE; + if(href_list["view_wireset"]) + if(wire_schematics) //No href hacks allow for you, my friend! + legend = href_list["view_wireset"]; + attack_self(usr) + + +//Code for viewing pipes or whatnot. Think t-ray scanner. +//Code for viewing pipes or whatnot. Think t-ray scanner. +//Code for viewing pipes or whatnot. Think t-ray scanner. +/* +/obj/item/areaeditor/blueprints/proc/get_images(turf/central_turf, viewsize) + . = list() + var/list/dimensions = getviewsize(viewsize) + var/horizontal_radius = dimensions[1] / 2 + var/vertical_radius = dimensions[2] / 2 + for(var/turf/nearby_turf as anything in RECT_TURFS(horizontal_radius, vertical_radius, central_turf)) + if(nearby_turf.blueprint_data) + . += nearby_turf.blueprint_data +*/ +/* +/obj/item/areaeditor/blueprints/proc/set_viewer(mob/user, message = "") + if(user?.client) + if(viewing) + clear_viewer() + viewing = user.client + showing = get_images(get_turf(viewing.eye || user), viewing.view) + viewing.images |= showing + if(message) + to_chat(user, message) +*/ +/* +/obj/item/areaeditor/blueprints/proc/clear_viewer(mob/user, message = "") + if(viewing) + viewing.images -= showing + viewing = null + showing.Cut() + if(message) + to_chat(user, message) +*/ +/obj/item/areaeditor/blueprints/dropped(mob/user) + ..() + //clear_viewer() + if(areaColor_turfs.len) + seeAreaColors_remove() + legend = FALSE + + + +/obj/item/areaeditor/proc/get_area_type(area/A) + if (!A) + A = get_area(usr) + if(A.outdoors) + return AREA_SPACE + + for (var/type in BUILDABLE_AREA_TYPES) + if ( istype(A,type) ) + return AREA_SPACE + + for (var/type in SPECIALS) + if ( istype(A,type) ) + return AREA_SPECIAL + return AREA_STATION + + +/obj/item/areaeditor/blueprints/proc/view_wire_devices(mob/user) + var/message = "[GLOB.wire_name_directory[device]]:" + for(var/Col in GLOB.wire_color_directory[device]) + var/wire_name = GLOB.wire_color_directory[device][Col] + if(!findtext(wire_name, WIRE_DUD_PREFIX)) //don't show duds + message += "
[Col]: [wire_name]
" + message += "" + return message + return "" + + +/obj/item/areaeditor/proc/edit_area() + var/area/A = get_area(usr) + var/prevname = "[A.name]" + var/str = tgui_input_text(usr, "New area name", "Area Creation", max_length = MAX_NAME_LEN) + str = sanitize(str,MAX_NAME_LEN) + if(!str || !length(str) || str==prevname) //cancel + return + if(length(str) > 50) + to_chat(usr, span_warning("The given name is too long. The area's name is unchanged.")) + return + + rename_area(A, str) + + to_chat(usr, span_notice("You rename the '[prevname]' to '[str]'.")) + log_and_message_admins("has changed the area '[prevname]' title to '[str]'.") + A.update_areasize() + interact() + return TRUE + +//Blueprint Subtypes + +/obj/item/areaeditor/blueprints/cyborg + name = "station schematics" + desc = "A digital copy of the station blueprints stored in your memory." + + +/proc/set_area_machinery(area/area, title, oldtitle) + if(!oldtitle) // or replacetext goes to infinite loop + return + for(var/obj/machinery/alarm/airpanel in area) + airpanel.name = replacetext(airpanel.name,oldtitle,title) + airpanel.update_area() + for(var/obj/machinery/power/apc/apcpanel in area) + apcpanel.name = replacetext(apcpanel.name,oldtitle,title) + apcpanel.update_area() //DECIDE IF THIS IS WANTED OR NOT. This can mean that the APC will overwrite the current APC the area being expanded has since areas cant have multiple APCs. + for(var/obj/machinery/atmospherics/unary/vent_scrubber/scrubber in area) + scrubber.name = replacetext(scrubber.name,oldtitle,title) + scrubber.update_area() + for(var/obj/machinery/atmospherics/unary/vent_pump/vent in area) + vent.name = replacetext(vent.name,oldtitle,title) + vent.update_area() + for(var/obj/machinery/door/door in area) + door.name = replacetext(door.name,oldtitle,title) + for(var/obj/machinery/firealarm/firepanel in area) + firepanel.name = replacetext(firepanel.name,oldtitle,title) + area.update_areasize() + //TODO: much much more. Unnamed airlocks, cameras, etc. + +/proc/detect_room(turf/origin, list/break_if_found, max_size=INFINITY) + if(origin.blocks_air) + return list(origin) + + . = list() + var/list/checked_turfs = list() + var/list/found_turfs = list(origin) + while(length(found_turfs)) + var/turf/sourceT = found_turfs[1] + found_turfs.Cut(1, 2) + var/dir_flags = checked_turfs[sourceT] + for(var/dir in GLOB.alldirs) + if(length(.) > max_size) + return + if(dir_flags & dir) // This means we've checked this dir before, probably from the other turf + continue + var/turf/checkT = get_step(sourceT, dir) + if(!checkT) + continue + + checked_turfs[sourceT] |= dir + checked_turfs[checkT] |= turn(dir, 180) + .[sourceT] |= dir + .[checkT] |= turn(dir, 180) + if(break_if_found[checkT.type] || break_if_found[checkT.loc.type]) + return FALSE + + //The below checks to make sure air can pass between the two turfs. If not, it can't be added to the area. + //This means walls can not be added to an area. The turf must first be added and then the wall. + //UNCOMMENT THIS IF YOU WANT THE BLUEPRINTS TO NOT ADD WALLS TO AN AREA. + //I personally think adding walls to an area is a big deal, so this is commented out. + + //BEGIN ESOTERIC BULLSHIT + //log_debug("Origin: [origin.c_airblock(checkT)] SourceT: [sourceT.c_airblock(checkT)] 0=NB 1=AB 2=ZB, 3=B") + /* + if(origin.c_airblock(checkT)) //If everything breaks and it doesn't want to work, turn on the above debug and check this line. C.L. 0 = not blocked. + continue + */ + //END ESOTERIC BULLSHIT + + found_turfs += checkT // Since checkT is connected, add it to the list to be processed + if(found_turfs.len) + found_turfs += origin //If this isn't done, it just adds the 8 tiles around the user. + return found_turfs + +/proc/create_area(mob/creator, var/obj/item/areaeditor/AO) + if(AO && istype(AO,/obj/item/areaeditor)) + if(AO.uses_charges && AO.charges < 1) + to_chat(creator, span_warning("You need more paper before you can even think of editing this area!")) + return + + var/list/turfs = detect_room(get_turf(creator), area_or_turf_fail_types, BP_MAX_ROOM_SIZE*2) + if(!turfs) + to_chat(creator, span_warning("The new area must have a floor and not a part of a shuttle.")) + return + if(length(turfs) > BP_MAX_ROOM_SIZE) + to_chat(creator, span_warning("The room you're in is too big. It is [length(turfs) >= BP_MAX_ROOM_SIZE *2 ? "more than 100" : ((length(turfs) / BP_MAX_ROOM_SIZE)-1)*100]% larger than allowed.")) + return + var/list/areas = list("New Area" = /area) + var/annoy_admins = 0 + + for(var/i in 1 to length(turfs)) + var/area/place = get_area(turfs[i]) + if(blacklisted_areas[place.type]) + continue + if(!place.requires_power || (place.flags & BLUE_SHIELDED)) + continue // No expanding powerless rooms etc + areas[place.name] = place + + var/area_choice = tgui_input_list(creator, "Choose an area to expand or make a new area", "Area Expansion", areas) + if(isnull(area_choice)) + to_chat(creator, span_warning("No choice selected. No adjustments made.")) + return + area_choice = areas[area_choice] + + var/area/newA + var/area/oldA = get_area(get_turf(creator)) + if(!isarea(area_choice)) + var/str = tgui_input_text(creator, "New area name", "Blueprint Editing", max_length = MAX_NAME_LEN) + str = sanitize(str,MAX_NAME_LEN) + if(!str || !length(str)) //cancel + return + if(length(str) > 50) + to_chat(creator, "Name too long.") + return + for(var/area/A in world) //Check to make sure we're not making a duplicate name. Sanity. + if(A.name == str) + to_chat(creator, "An area in the world alreay has this name.") + return + annoy_admins = 1 //They just made a new area entirely. + newA = new area_choice + newA.setup(str) + newA.has_gravity = oldA.has_gravity + else + newA = area_choice + + for(var/i in 1 to length(turfs)) //Fix lighting. Praise the lord. + var/turf/thing = turfs[i] + newA.contents += thing + thing.change_area(oldA, newA) + + + set_area_machinery(newA, newA.name, oldA.name)// Change the name and area defines of all the machinery to the correct area. + oldA.power_check() //Simply makes the area turn the power off if you nicked an APC from it. + to_chat(creator, span_notice("You have created a new area, named [newA.name]. It is now weather proof, and constructing an APC will allow it to be powered.")) + if(annoy_admins) + message_admins("[key_name(creator, creator.client)] just made a new area called [newA.name] ](?) at ([creator.x],[creator.y],[creator.z] - JMP)",0,1) + log_game("[key_name(creator, creator.client)] just made a new area called [newA.name]") + if(AO && istype(AO,/obj/item/areaeditor)) + if(AO.uses_charges) + AO.charges -= 1 + return TRUE + + + +// USED FOR VARIANT ROOM CREATION. +// OLD CODE. DON'T TOUCH OR 100 RABID SQUIRRELS WILL DEVOUR YOU. +// I say old code, but it truly isn't. It's a bastardization of the new create_area code and the old create_area code. +// In essence, it does a few things: Ensure no blacklisted areas are nearby, get the nearby areas (to allow merging), and allow you to make a whole near area. +/obj/item/areaeditor/proc/create_area_whole(mob/creator, var/override = 0) //Gets the entire enclosed space and makes a new area out of it. Can overwrite old areas. + if(uses_charges && charges < 5) + to_chat(creator, span_warning("You need more paper before you can even think of editing this area!")) + return + + var/res = detect_room_ex(get_turf(creator), can_create_areas_into, area_or_turf_fail_types) + if(!res) + to_chat(creator, span_warning("There is an area forbidden from being edited here! Use the fine-tune area creator! (3x3)")) + return + + if(!istype(res,/list)) + switch(res) + if(ROOM_ERR_SPACE) + to_chat(creator, "The new area must be completely airtight!") + return + if(ROOM_ERR_TOOLARGE) + to_chat(creator, "The new area too large!") + return + if(ROOM_ERR_FORBIDDEN) + to_chat(creator, "There is an area forbidden from being edited here!") + return + else + to_chat(creator, "Error! Please notify administration!") + return + var/list/turf/turfs = res + + var/list/areas = list("New Area" = /area) //The list of areas surrounding the user. + var/area/newA //The new area + var/area/oldA = get_area(get_turf(creator)) //The old area (area currently standing in) + var/str //What the new area is named. + var/can_make_new_area = 1 //If they can make a new area here or not. + + var/list/nearby_turfs_to_check = detect_room(get_turf(creator), area_or_turf_fail_types, BP_MAX_ROOM_SIZE*2) //Get the nearby areas. + + if(!nearby_turfs_to_check) + to_chat(creator, span_warning("The new area must have a floor and not a part of a shuttle.")) + return + if(length(turfs) > BP_MAX_ROOM_SIZE) + to_chat(creator, span_warning("The room you're in is too big. It is [length(turfs) >= BP_MAX_ROOM_SIZE *2 ? "more than 100" : ((length(turfs) / BP_MAX_ROOM_SIZE)-1)*100]% larger than allowed.")) + return + + for(var/i in 1 to length(nearby_turfs_to_check)) + var/area/place = get_area(nearby_turfs_to_check[i]) + if(blacklisted_areas[place.type]) + if(!creator.lastarea != place) //Stops them from merging a blacklisted area to make it larger. Allows them to merge a blacklisted area into an allowed area. (Expansion!) + continue + if(!BUILDABLE_AREA_TYPES[place.type]) //TODOTODOTODO + can_make_new_area = 0 + if(!place.requires_power || (place.flags & BLUE_SHIELDED)) + continue // No expanding powerless rooms etc + areas[place.name] = place + + //They can select an area they want to turn their current area into. + var/area_choice = tgui_input_list(creator, "What area do you want to turn the area YOU ARE CURRENTLY STANDING IN to? Or do you want to make a new area?", "Area Expansion", areas) + if(isnull(area_choice)) //They pressed cancel. + to_chat(creator, "No changes made.") + return + + area_choice = areas[area_choice] + + + if(!isarea(area_choice)) //They chose "New Area" + if(!can_make_new_area && !can_override) + to_chat(creator, "Making a new area here would be meaningless. Renaming it would be a better option.") + return + str = tgui_input_text(creator, "New area name", "Blueprint Editing", max_length = MAX_NAME_LEN) + str = sanitize(str,MAX_NAME_LEN) + if(!str || !length(str)) //cancel + return + if(length(str) > 50) + to_chat(creator, "Name too long.") + return + for(var/area/A in world) //Check to make sure we're not making a duplicate name. Sanity. + if(A.name == str) + to_chat(creator, "An area in the world alreay has this name.") + return + + var/confirm = tgui_alert(creator, "Are you sure you want to change [oldA.name] into a new area named [str]?", "READ CAREFULLY", list("No", "Yes")) + if(confirm == "No") + to_chat(creator, "No changes made.") + return + + newA = new area_choice + newA.setup(str) + newA.has_gravity = oldA.has_gravity + else + var/confirm = tgui_alert(creator, "Are you sure you want to change [oldA.name] into [area_choice]?", "READ CAREFULLY", list("No", "Yes")) + if(confirm == "No") + to_chat(creator, "No changes made.") + return + newA = area_choice //They selected to turn the area they're standing on into the selected area. + + if(str) //New area, new name. + newA.setup(str) + else + newA.setup(newA.name) + + for(var/i in 1 to length(turfs)) //Fix lighting. Praise the lord. + var/turf/thing = turfs[i] + newA.contents += thing + thing.change_area(oldA, newA) + + move_turfs_to_area(turfs, newA) + newA.has_gravity = oldA.has_gravity + set_area_machinery(newA, newA.name, oldA.name) + oldA.power_check() //Simply makes the area turn the power off if you nicked an APC from it. + to_chat(creator, span_notice("You have created a new area, named [newA.name]. It is now weather proof, and constructing an APC will allow it to be powered.")) + message_admins("[key_name(creator, creator.client)] just made a new area called [newA.name] ](?) at ([creator.x],[creator.y],[creator.z] - JMP)",0,1) + log_game("[key_name(creator, creator.client)] just made a new area called [newA.name]") + charges -= 5 + + spawn(5) + interact() + return + +/proc/move_turfs_to_area(var/list/turf/turfs, var/area/A) + for(var/T in turfs) + ChangeArea(T, A) + + +/obj/item/areaeditor/proc/detect_room_ex(var/turf/first, var/allowedAreas = AREA_SPACE, var/list/forbiddenAreas = list(), var/visual) + if(!istype(first)) + return ROOM_ERR_LOLWAT + if(!visual && forbiddenAreas[first.loc.type] || forbiddenAreas[first.type]) //Is the area of the starting turf a banned area? Is the turf a banned area? + return ROOM_ERR_FORBIDDEN + var/list/turf/found = new + var/list/turf/pending = list(first) + while(pending.len) + if (found.len+pending.len > BP_MAX_ROOM_SIZE) + return ROOM_ERR_TOOLARGE + var/turf/T = pending[1] //why byond havent list::pop()? + pending -= T + for (var/dir in cardinal) + var/turf/NT = get_step(T,dir) + if (!isturf(NT) || (NT in found) || (NT in pending)) + continue + if(!visual && forbiddenAreas[NT.loc.type]) + return ROOM_ERR_FORBIDDEN + // We ask ZAS to determine if its airtight. Thats what matters anyway right? + if(air_master.air_blocked(T, NT)) + // Okay thats the edge of the room + if(get_area_type(NT.loc) == AREA_SPACE && air_master.air_blocked(NT, NT)) + found += NT // So we include walls/doors not already in any area + continue + if (istype(NT, /turf/space)) + return ROOM_ERR_SPACE //omg hull breach we all going to die here + if (istype(NT, /turf/simulated/shuttle)) + return ROOM_ERR_SPACE // Unsure why this, but was in old code. Trusting for now. + if (NT.loc != first.loc && !(get_area_type(NT.loc) & allowedAreas)) + // Edge of a protected area. Lets stop here... + continue + if (!istype(NT, /turf/simulated)) + // Great, unsimulated... eh, just stop searching here + continue + // Okay, NT looks promising, lets continue the search there! + pending += NT + found += T + // end while + return found + + + + + + + +//Nice verbs for the engineer to see where areas start/end. + +/obj/item/areaeditor/verb/seeRoomColors() + set src in usr + set category = "Blueprints" + set name = "Show Room Colors" + + // If standing somewhere we can expand from, use expand perms, otherwise create + var/canOverwrite = (get_area_type() & can_expand_areas_in) ? can_expand_areas_into : can_create_areas_into + var/res = detect_room_ex(get_turf(usr), canOverwrite, visual = 1) + if(!istype(res, /list)) + switch(res) + if(ROOM_ERR_SPACE) + to_chat(usr, "The new area must be completely airtight!") + return + if(ROOM_ERR_TOOLARGE) + to_chat(usr, "The new area too large!") + return + else + to_chat(usr, "Error! Please notify administration!") + return + // Okay we got a room, lets color it + seeAreaColors_remove() + var/icon/green = new('icons/misc/debug_group.dmi', "green") + for(var/turf/T in res) + usr << image(green, T, "blueprints", TURF_LAYER) + areaColor_turfs += T + to_chat(usr, "The space covered by the new area is highlighted in green.") + +/obj/item/areaeditor/verb/seeAreaColors() + set src in usr + set category = "Blueprints" + set name = "Show Area Colors" + + // Remove any existing + seeAreaColors_remove() + + to_chat(usr, "\The [src] shows nearby areas in different colors.") + var/i = 0 + for(var/area/A in range(usr)) + if(get_area_type(A) == AREA_SPACE) + continue // Don't overlay all of space! + var/icon/areaColor = new('icons/misc/debug_rebuild.dmi', "[++i]") + to_chat(usr, "- [A] as [i]") + for(var/turf/T in A.contents) + usr << image(areaColor, T, "blueprints", TURF_LAYER) + areaColor_turfs += T + +/obj/item/areaeditor/verb/seeAreaColors_remove() + set src in usr + set category = "Blueprints" + set name = "Remove Area Colors" + + areaColor_turfs.Cut() + if(usr.client.images.len) + for(var/image/i in usr.client.images) + if(i.icon_state == "blueprints") + usr.client.images.Remove(i) + + + + + + + + + + + +//GLOBAL VERB FOR PAPER TO ENABLE ANYONE TO MAKE AN AREA IN BUILDABLE AREAS. +//THIS IS 70 TILES. ANYTHING LARGER SHOULD USE ACTUAL BLUEPRINTS. + +/obj/item/weapon/paper + var/created_area = 0 + var/area_cooldown = 0 + +/obj/item/weapon/paper/verb/create_area() + set name = "Create Area" + set category = "Object" + set src in usr + + if(created_area) + to_chat(usr, "This paper has already been used to create an area.") + return + + if(usr.stat || world.time < area_cooldown) + to_chat(usr, "You recently used this paper to try to create an area. Wait one minute before using it again.") + return + + area_cooldown = world.time + 600 //Anti spam. + + create_new_area(usr) + add_fingerprint(usr) + return + +/proc/get_new_area_type(area/A) //1 = can build in. 0 = can not build in. + if (!A) + A = get_area(usr) + if(A.outdoors) //ALWAYS able to build outdoors. This means if it's missed in BUILDABLE_AREA_TYPES it's fine. + return 1 + + for (var/type in BUILDABLE_AREA_TYPES) //This works well. + if ( istype(A,type) ) + return 1 + + for (var/type in SPECIALS) + if ( istype(A,type) ) + return 0 + return 0 //If it's not a buildable area, don't let them build in it. + + +/proc/detect_new_area(var/turf/first, var/user) //Heavily simplified version for creating an area yourself. + if(!istype(first)) //Not on a turf. + to_chat(usr, "") + return + if(get_new_area_type(first.loc) == 1) //Are they in an area they can build? I tried to do this BUILDABLE_AREA_TYPES[first.loc.type] but it refused. + var/list/turf/found = new + var/list/turf/pending = list(first) + while(pending.len) + if (found.len+pending.len > 70) + return 1 //TOOLARGE + var/turf/T = pending[1] + pending -= T + for (var/dir in cardinal) + var/turf/NT = get_step(T,dir) + if (!isturf(NT) || (NT in found) || (NT in pending)) + continue + if(!get_new_area_type(NT.loc) == 1) //The contains somewhere that is NOT a buildable area. + return 3 //NOT A BUILDABLE AREA + + if(air_master.air_blocked(T, NT)) //Is the room airtight? + // Okay thats the edge of the room + if(get_new_area_type(NT.loc) == 1 && air_master.air_blocked(NT, NT)) + found += NT // So we include walls/doors not already in any area + continue + if (istype(NT, /turf/space)) + return 2 //SPACE + if (istype(NT, /turf/simulated/shuttle)) + return 2 //SPACE + if (NT.loc != first.loc && !(get_new_area_type(NT.loc) & 1)) + // Edge of a protected area. Lets stop here... + continue + if (!istype(NT, /turf/simulated)) + // Great, unsimulated... eh, just stop searching here + continue + // Okay, NT looks promising, lets continue the search there! + pending += NT + found += T + // end while + return found + else + return 3 + +/proc/create_new_area(mob/creator) //Heavily simplified version of the blueprint version. + var/res = detect_new_area(get_turf(creator), creator) + if(!res) + to_chat(creator, span_warning("Something went wrong.")) + return + + if(!istype(res,/list)) + switch(res) + if(1) + to_chat(creator, "The new area too large! You can only have an area that is up to 70 tiles.") + return + if(2) + to_chat(creator, "The new area must be completely airtight and not be part of a shuttle!") + return + if(3) + to_chat(creator, "There is an area not permitted to be built in somewhere in the room!") + return + else + to_chat(creator, "Error! Please notify administration!") + return + var/list/turf/turfs = res + + var/area/newA //The new area + var/area/oldA = get_area(get_turf(creator)) //The old area (area currently standing in) + var/str //What the new area is named. + + var/list/nearby_turfs_to_check = detect_room(get_turf(creator), area_or_turf_fail_types, 70) //Get the nearby areas. + + if(!nearby_turfs_to_check) + to_chat(creator, span_warning("The new area must have a floor and not a part of a shuttle.")) + return + if(length(turfs) > 70) //Sanity + to_chat(creator, span_warning("The room you're in is too big. It can only be 70 tiles in size, excluding walls.")) + return + + //They can select an area they want to turn their current area into. + str = sanitizeSafe(tgui_input_text(usr, "What would you like to name the area?", "Area Name", null, MAX_NAME_LEN), MAX_NAME_LEN) + if(isnull(str)) //They pressed cancel. + to_chat(creator, "No new area made. Cancelling.") + return + if(!str || !length(str)) //sanity + to_chat(creator, "No new area made. Cancelling.") + return + if(length(str) > MAX_NAME_LEN) + to_chat(creator, "Name too long.") + return + for(var/area/A in world) //Check to make sure we're not making a duplicate name. Sanity. + if(A.name == str) + to_chat(creator, "An area in the world alreay has this name.") + return + newA = new /area + newA.setup(str) + newA.has_gravity = oldA.has_gravity + newA.setup(str) + + for(var/i in 1 to length(turfs)) //Fix lighting. Praise the lord. + var/turf/thing = turfs[i] + newA.contents += thing + thing.change_area(oldA, newA) + + move_turfs_to_area(turfs, newA) + newA.has_gravity = oldA.has_gravity + set_area_machinery(newA, newA.name, oldA.name) + oldA.power_check() //Simply makes the area turn the power off if you nicked an APC from it. + to_chat(creator, span_notice("You have created a new area, named [newA.name]. It is now weather proof, and constructing an APC will allow it to be powered.")) + message_admins("[key_name(creator, creator.client)] just made a new area called [newA.name] ](?) at ([creator.x],[creator.y],[creator.z] - JMP)",0,1) + log_game("[key_name(creator, creator.client)] just made a new area called [newA.name]") + + return + + +#undef BP_MAX_ROOM_SIZE diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 099bdfad1b..b88785b9fc 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -53,7 +53,7 @@ /obj/structure/closet/body_bag/attackby(var/obj/item/W as obj, mob/user as mob) if (istype(W, /obj/item/weapon/pen)) - var/t = tgui_input_text(user, "What would you like the label to be?", text("[]", src.name), null) + var/t = tgui_input_text(user, "What would you like the label to be?", text("[]", src.name), null, MAX_NAME_LEN ) if (user.get_active_hand() != W) return if (!in_range(src, user) && src.loc != user) diff --git a/code/game/objects/items/contraband_vr.dm b/code/game/objects/items/contraband_vr.dm index 2bb1df1dd2..6737788486 100644 --- a/code/game/objects/items/contraband_vr.dm +++ b/code/game/objects/items/contraband_vr.dm @@ -42,12 +42,16 @@ /obj/item/mecha_parts/part/phazon_right_arm, /obj/item/mecha_parts/part/phazon_right_leg, /obj/item/mecha_parts/part/phazon_torso, + /obj/item/weapon/circuitboard/mecha/phazon/targeting, + /obj/item/weapon/circuitboard/mecha/phazon/peripherals, + /obj/item/weapon/circuitboard/mecha/phazon/main, /obj/item/device/bodysnatcher, /obj/item/weapon/bluespace_harpoon, /obj/item/clothing/accessory/permit/gun, /obj/item/device/perfect_tele, /obj/item/device/sleevemate, /obj/item/weapon/disk/nifsoft/compliance, + /obj/item/weapon/implanter/compliance, /obj/item/seeds/ambrosiadeusseed, /obj/item/seeds/ambrosiavulgarisseed, /obj/item/seeds/libertymycelium, @@ -108,4 +112,4 @@ w_class = ITEMSIZE_NORMAL /obj/item/weapon/miscdisc/attack_self(mob/living/user as mob) - to_chat(user, "As you hold the large disc in your open palm, fingers cusped around the edge, the crystal embedded in the item begins to vibrate. It lifts itself from the disc a few cenimetres, before beginning to glow with a bright red light. The glow lasts for a few seconds, before the crystal embeds itself back into the disc with a quick snap.") \ No newline at end of file + to_chat(user, "As you hold the large disc in your open palm, fingers cusped around the edge, the crystal embedded in the item begins to vibrate. It lifts itself from the disc a few cenimetres, before beginning to glow with a bright red light. The glow lasts for a few seconds, before the crystal embeds itself back into the disc with a quick snap.") diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index b2bd8757f3..8c3a5b0551 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -98,10 +98,10 @@ new /obj/effect/decal/cleanable/crayon(target,colour,shadeColour,drawtype) to_chat(user, "You finish drawing.") + var/msg = "[user.client.key] ([user]) has drawn [drawtype] (with [src]) at [target.x],[target.y],[target.z]." if(config.log_graffiti) - var/msg = "[user.client.key] ([user]) has drawn [drawtype] (with [src]) at [target.x],[target.y],[target.z]." message_admins(msg) - log_game(msg) + log_game(msg) //We will log it anyways. target.add_fingerprint(user) // Adds their fingerprints to the floor the crayon is drawn on. if(uses) @@ -211,4 +211,4 @@ ..() /obj/item/weapon/pen/crayon/attack_self(var/mob/user) - return \ No newline at end of file + return diff --git a/code/game/objects/items/devices/communicator/UI_tgui.dm b/code/game/objects/items/devices/communicator/UI_tgui.dm index 092b45cea2..2f4e73c5eb 100644 --- a/code/game/objects/items/devices/communicator/UI_tgui.dm +++ b/code/game/objects/items/devices/communicator/UI_tgui.dm @@ -382,7 +382,7 @@ im_list += list(list("address" = exonet.address, "to_address" = their_address, "im" = text)) log_pda("(COMM: [src]) sent \"[text]\" to [exonet.get_atom_from_address(their_address)]", usr) var/obj/item/device/communicator/comm = exonet.get_atom_from_address(their_address) - to_chat(usr, "\icon[src][bicon(src)] Sent message to [comm.owner], \"[text]\" (Reply)") + to_chat(usr, "\icon[src][bicon(src)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], \"[text]\" (Reply)") for(var/mob/M in player_list) if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat) diff --git a/code/game/objects/items/devices/communicator/messaging.dm b/code/game/objects/items/devices/communicator/messaging.dm index 5c27d8a850..e5a27902b1 100644 --- a/code/game/objects/items/devices/communicator/messaging.dm +++ b/code/game/objects/items/devices/communicator/messaging.dm @@ -108,7 +108,7 @@ exonet.send_message(comm.exonet.address, "text", message) im_list += list(list("address" = exonet.address, "to_address" = comm.exonet.address, "im" = message)) log_pda("(COMM: [src]) sent \"[message]\" to [exonet.get_atom_from_address(comm.exonet.address)]", usr) - to_chat(usr, "\icon[src][bicon(src)] Sent message to [comm.owner], \"[message]\" (Reply)") + to_chat(usr, "\icon[src][bicon(src)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], \"[message]\" (Reply)") // Verb: text_communicator() // Parameters: None diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index 55a7803e75..4fa7e7d983 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -308,8 +308,8 @@ return bad_vital_organ //this needs to be last since if any of the 'other conditions are met their messages take precedence - if(!H.client && !H.teleop) - return "buzzes, \"Resuscitation failed - Mental interface error. Further attempts may be successful.\"" + //if(!H.client && !H.teleop) + // return "buzzes, \"Resuscitation failed - Mental interface error. Further attempts may be successful.\""// CHOMPEdit, removing this check to allow revival through bad internet connections. return null diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index f3f8b5c982..eff6d34848 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -126,7 +126,11 @@ if(H.species.vision_organ) vision = H.internal_organs_by_name[H.species.vision_organ] if(!vision) + user.visible_message("\The [user] directs [src] at [M]'s face.", \ + "You direct [src] at [M]'s face.") to_chat(user, "You can't find any [H.species.vision_organ ? H.species.vision_organ : "eyes"] on [H]!") + user.setClickCooldown(user.get_attack_speed(src)) + return user.visible_message("\The [user] directs [src] to [M]'s eyes.", \ "You direct [src] to [M]'s eyes.") diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm index 21ec2ea3b6..980685f124 100644 --- a/code/game/objects/items/devices/gps.dm +++ b/code/game/objects/items/devices/gps.dm @@ -137,7 +137,7 @@ var/list/GPS_list = list() if(emped) to_chat(user, "It's busted!") return - + toggle_tracking() if(tracking) to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.") @@ -194,7 +194,7 @@ var/list/GPS_list = list() dat["curr_z"] = curr.z dat["curr_z_name"] = strip_improper(using_map.get_zlevel_name(curr.z)) dat["z_level_detection"] = using_map.get_map_levels(curr.z, long_range) - + var/list/gps_list = list() for(var/obj/item/device/gps/G in GPS_list - src) @@ -250,7 +250,7 @@ var/list/GPS_list = list() dat += "
The former corpse staggers to its feet, all its former wounds having vanished...
") //Bloody hell... clear_alert("hatch") @@ -168,6 +171,13 @@ revive_ready = world.time + 10 MINUTES //set the cooldown CHOMPEdit: Reduced this to 10 minutes, you're playing with fire if you're reviving that often. +/datum/modifier/resleeving_sickness/chimera //near identical to the regular version, just with different flavortexts + name = "imperfect regeneration" + desc = "You feel rather weak and unfocused, having just regrown your body not so long ago." + + on_created_text = "You feel weak and unsteady, that regeneration having been rougher than most." + on_expired_text = "You feel your strength and focus return to you." + /mob/living/carbon/human/proc/revivingreset() // keep this as a debug proc or potential future use revive_ready = REVIVING_READY @@ -1065,3 +1075,316 @@ C.update_transform() //egg_contents -= src C.contents -= src + +/mob/living/carbon/human/proc/water_stealth() + set name = "Dive under water / Resurface" + set desc = "Dive under water, allowing for you to be stealthy and move faster." + set category = "Abilities" + + if(last_special > world.time) + return + last_special = world.time + 50 //No spamming! + + if(has_modifier_of_type(/datum/modifier/underwater_stealth)) + to_chat(src, "You resurface!") + remove_modifiers_of_type(/datum/modifier/underwater_stealth) + return + + if(!isturf(loc)) //We have no turf. + to_chat(src, "There is no water for you to dive into!") + return + + if(istype(src.loc, /turf/simulated/floor/water)) + var/turf/simulated/floor/water/water_floor = src.loc + if(water_floor.depth >= 1) //Is it deep enough? + add_modifier(/datum/modifier/underwater_stealth) //No duration. It'll remove itself when they exit the water! + to_chat(src, "You dive into the water!") + visible_message("[src] dives into the water!") + else + to_chat(src, "The water here is not deep enough to dive into!") + return + + else + to_chat(src, "There is no water for you to dive into!") + return + +/mob/living/carbon/human/proc/underwater_devour() + set name = "Devour From Water" + set desc = "Grab something in the water with you and devour them with your selected stomach." + set category = "Abilities" + + if(last_special > world.time) + return + last_special = world.time + 50 //No spamming! + + if(stat == DEAD || paralysis || weakened || stunned) + to_chat(src, "You cannot do that while in your current state.") + return + + if(!(src.vore_selected)) + to_chat(src, "No selected belly found.") + return + + + if(!has_modifier_of_type(/datum/modifier/underwater_stealth)) + to_chat(src, "You must be underwater to do this!!") + return + + var/list/targets = list() //Shameless copy and paste. If it ain't broke don't fix it! + + for(var/turf/T in range(1, src)) + if(istype(T, /turf/simulated/floor/water)) + for(var/mob/living/L in T) + if(L == src) //no eating yourself. 1984. + continue + if(L.devourable) + targets += L + + if(!(targets.len)) + to_chat(src, "No eligible targets found.") + return + + var/mob/living/target = tgui_input_list(src, "Please select a target.", "Victim", targets) + + if(!target) + return + + to_chat(target, "Something begins to circle around you in the water!") //Dun dun... + var/starting_loc = target.loc + + if(do_after(src, 50)) + if(target.loc != starting_loc) + to_chat(target, "You got away from whatever that was...") + to_chat(src, "They got away.") + return + if(target.buckled) //how are you buckled in the water?! + target.buckled.unbuckle_mob() + target.visible_message("\The [target] suddenly disappears, being dragged into the water!",\ + "You are dragged below the water and feel yourself slipping directly into \the [src]'s [vore_selected]!") + to_chat(src, "You successfully drag \the [target] into the water, slipping them into your [vore_selected].") + target.forceMove(src.vore_selected) + +/mob/living/carbon/human/proc/toggle_pain_module() + set name = "Toggle pain simulation." + set desc = "Turn on your pain simulation for that organic experience! Or turn it off for repairs, or if it's too much." + set category = "Abilities" + + if(synth_cosmetic_pain) + to_chat(src, " You turn off your pain simulators.") + else + to_chat(src, " You turn on your pain simulators ") + + synth_cosmetic_pain = !synth_cosmetic_pain + +//This is the 'long vore' ability. Also known as "Grab Prey with appendage" or "Long Predatorial Reach". Or simply "Tongue Vore" +//It involves projectiles (which means it can be VV'd onto a gun for shenanigans) +//It can also be recolored via the proc, which persists between rounds. + +/mob/living/proc/long_vore() // Allows the user to tongue grab a creature in range. Made a /living proc so frogs can frog you. + set name = "Grab Prey With Appendage" + set category = "Abilities" + set desc = "Grab a target with any of your appendages!" + + if(stat || paralysis || weakened || stunned || world.time < last_special) //No tongue flicking while stunned. + to_chat(src, "You can't do that in your current state.") + return + + last_special = world.time + 10 //Anti-spam. + + if (!istype(src, /mob/living)) + to_chat(src, "It doesn't work that way.") + return + + var/choice = tgui_alert(src, "Do you wish to change the color of your appendage, use it, or change its functionality?", "Selection List", list("Use it", "Color", "Functionality")) + + if(choice == "Color") //Easy way to set color so we don't bloat up the menu with even more buttons. + var/new_color = input(usr, "Choose a color to set your appendage to!", "", appendage_color) as color|null + if(new_color) + appendage_color = new_color + + if(choice == "Functionality") //Easy way to set color so we don't bloat up the menu with even more buttons. + var/choice2 = tgui_alert(usr, "Choose if you want to be pulled to the target or pull them to you!", "Functionality Setting", list("Pull target to self", "Pull self to target")) + if(choice2 == "Pull target to self") + appendage_alt_setting = 0 + else + appendage_alt_setting = 1 + else + var/list/targets = list() //IF IT IS NOT BROKEN. DO NOT FIX IT. + + for(var/mob/living/L in range(5, src)) + if(!istype(L, /mob/living)) //Don't eat anything that isn't mob/living. Failsafe. + continue + if(L == src) //no eating yourself. 1984. + continue + if(L.devourable && L.throw_vore && (L.can_be_drop_pred || L.can_be_drop_prey)) + targets += L + + if(!(targets.len)) + to_chat(src, "No eligible targets found.") + return + + var/mob/living/target = tgui_input_list(src, "Please select a target.", "Victim", targets) + + if(!target) + return + + if(!istype(target, /mob/living)) //Safety. + to_chat(src, "You need to select a living target!") + return + + if (get_dist(src,target) >= 6) + to_chat(src, "You need to be closer to do that.") + return + + visible_message("\The [src] attempts to snatch up [target]!", \ + "You attempt to snatch up [target]!" ) + playsound(src, 'sound/vore/sunesound/pred/schlorp.ogg', 25) + + //Code to shoot the beam here. + var/obj/item/projectile/beam/appendage/appendage_attack = new /obj/item/projectile/beam/appendage(get_turf(loc)) + appendage_attack.launch_projectile(target, BP_TORSO, src) //Send it. + last_special = world.time + 100 //Cooldown for successful strike. + + + + +/obj/item/projectile/beam/appendage //The tongue projecitle. + name = "appendage" + icon_state = "laser" + nodamage = 1 + damage = 0 + eyeblur = 0 + check_armour = "bullet" //Not really needed, but whatever. + can_miss = FALSE //Let's not miss our tongue! + fire_sound = 'sound/effects/slime_squish.ogg' + hitsound = 'sound/vore/sunesound/pred/schlorp.ogg' + hitsound_wall = 'sound/vore/sunesound/pred/schlorp.ogg' + excavation_amount = 0 + hitscan_light_intensity = 0 + hitscan_light_range = 0 + muzzle_flash_intensity = 0 + muzzle_flash_range = 0 + impact_light_intensity = 0 + impact_light_range = 0 + light_range = 0 //No your tongue can not glow...For now. + light_power = 0 + light_on = 0 //NO LIGHT + combustion = FALSE //No, your tongue can't set the room on fire. + pass_flags = PASSTABLE + + muzzle_type = /obj/effect/projectile/muzzle/appendage + tracer_type = /obj/effect/projectile/tracer/appendage + impact_type = /obj/effect/projectile/impact/appendage + +/obj/item/projectile/beam/appendage/generate_hitscan_tracers() + if(firer) //This neat little code block allows for C O L O R A B L E tongues! Correction: 'Appendages' + if(istype(firer,/mob/living)) + var/mob/living/originator = firer + color = originator.appendage_color + ..() + +/obj/item/projectile/beam/appendage/on_hit(var/atom/target) + if(target == firer) //NO EATING YOURSELF + return + if(istype(target, /mob/living)) + var/mob/living/M = target + var/throw_range = get_dist(firer,M) + if(istype(firer, /mob/living)) //Let's check for any alt settings. Such as: User selected to be thrown at target. + var/mob/living/F = firer + if(F.appendage_alt_setting == 1) + F.throw_at(M, throw_range, firer.throw_speed, F) //Firer thrown at target. + F.updateicon() + return + if(istype(M)) + M.throw_at(firer, throw_range, M.throw_speed, firer) //Fun fact: living things have a throw_speed of 2. + M.updateicon() + return + else //Anything that isn't a /living + return + if(istype(target, /obj/item/)) //We hit an object? Pull it. This can only happen via admin shenanigans such as a gun being VV'd with this projectile. + var/obj/item/hit_object = target + if(hit_object.density || hit_object.anchored) + if(istype(firer, /mob/living)) + var/mob/living/originator = firer + originator.Weaken(2) //If you hit something dense or anchored, fall flat on your face. + originator.visible_message("\The [originator] trips over their self and falls flat on their face!", \ + "You trip over yourself and fall flat on your face!" ) + playsound(originator, "punch", 25, 1, -1) + return + else + hit_object.throw_at(firer, throw_range, hit_object.throw_speed, firer) + if(istype(target, /turf/simulated/wall) || istype(target, /obj/machinery/door) || istype(target, /obj/structure/window)) //This can happen normally due to odd terrain. For some reason, it seems to not actually interact with walls. + if(istype(firer, /mob/living)) + var/mob/living/originator = firer + originator.Weaken(2) //Hit a wall? Whoops! + originator.visible_message("\The [originator] trips over their self and falls flat on their face!", \ + "You trip over yourself and fall flat on your face!" ) + playsound(originator, "punch", 25, 1, -1) + return + else + return + + + +/obj/effect/projectile/muzzle/appendage + icon = 'icons/obj/projectiles_vr.dmi' + icon_state = "muzzle_appendage" + light_range = 0 + light_power = 0 + light_color = "#FF0D00" + +/obj/effect/projectile/tracer/appendage + icon = 'icons/obj/projectiles_vr.dmi' + icon_state = "appendage_beam" + light_range = 0 + light_power = 0 + light_color = "#FF0D00" //Doesn't matter. Not used. + +/obj/effect/projectile/impact/appendage + icon = 'icons/obj/projectiles_vr.dmi' + icon_state = "impact_appendage_combined" + light_range = 0 + light_power = 0 + light_color = "#FF0D00" +//LONG VORE ABILITY END + +/obj/item/weapon/gun/energy/gun/tongue //This is the 'tongue' gun for admin memery. + name = "tongue" + desc = "A tongue that can be used to grab things." + icon = 'icons/mob/dogborg_vr.dmi' + icon_state = "synthtongue" + item_state = "gun" + fire_delay = null + force = 0 + fire_delay = 1 //Adminspawn. No delay. + charge_cost = 0 //This is an adminspawn gun...No reason to force it to have a charge state. + + projectile_type = /obj/item/projectile/beam/appendage + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 + modifystate = null + + + firemodes = list( + list(mode_name="vore", projectile_type=/obj/item/projectile/beam/appendage, modifystate=null, fire_sound='sound/vore/sunesound/pred/schlorp.ogg', charge_cost = 0),) + +/obj/item/weapon/gun/energy/gun/tongue/update_icon() //No updating the icon. + icon_state = "synthtongue" + return + +/obj/item/weapon/gun/energy/bfgtaser/tongue + name = "9000-series Ball Tongue Taser" + desc = "A banned riot control device." + slot_flags = SLOT_BELT|SLOT_BACK + projectile_type = /obj/item/projectile/bullet/BFGtaser/tongue + fire_delay = 20 + w_class = ITEMSIZE_LARGE + one_handed_penalty = 90 // The thing's heavy and huge. + accuracy = 45 + charge_cost = 2400 //yes, this bad boy empties an entire weapon cell in one shot. What of it? + +/obj/item/projectile/bullet/BFGtaser/tongue + name = "tongue ball" + hitsound = 'sound/vore/sunesound/pred/schlorp.ogg' + hitsound_wall = 'sound/vore/sunesound/pred/schlorp.ogg' + zaptype = /obj/item/projectile/beam/appendage diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm index e736ee29f4..5239589931 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm @@ -15,9 +15,10 @@ brute_mod = 0.8 //About as tanky to brute as a Unathi. They'll probably snap and go feral when hurt though. burn_mod = 1.15 //As vulnerable to burn as a Tajara. base_species = "Xenochimera" - selects_bodytype = TRUE + selects_bodytype = SELECTS_BODYTYPE_CUSTOM num_alternate_languages = 3 + species_language = null secondary_langs = list("Sol Common") //color_mult = 1 //It seemed to work fine in testing, but I've been informed it's unneeded. tail = "tail" //Scree's tail. Can be disabled in the vore tab by choosing "hide species specific tail sprite" @@ -26,9 +27,6 @@ /mob/living/carbon/human/proc/reconstitute_form, /mob/living/carbon/human/proc/sonar_ping, /mob/living/carbon/human/proc/tie_hair, - /mob/living/proc/flying_toggle, - /mob/living/proc/flying_vore_toggle, - /mob/living/proc/start_wings_hovering, /mob/living/carbon/human/proc/lick_wounds) //Xenochimera get all the special verbs since they can't select traits. // CHOMPEdit: Lick Wounds Verb @@ -151,14 +149,14 @@ cause = "jittery" //check to see if they go feral if they weren't before - if(!feral) + if(!feral && !isbelly(H.loc)) // if stress is below 15, no chance of snapping. Also if they weren't feral before, they won't suddenly become feral unless they get MORE stressed if((currentstress > laststress) && prob(clamp(currentstress-15, 0, 100)) ) go_feral(H, currentstress, cause) feral = currentstress //update the local var //they didn't go feral, give 'em a chance of hunger messages - else if(H.nutrition <= 200 && prob(0.5) && !isbelly(H.loc)) + else if(H.nutrition <= 200 && prob(0.5)) switch(H.nutrition) if(150 to 200) to_chat(H,"You feel rather hungry. It might be a good idea to find some some food...") @@ -167,7 +165,8 @@ danger = TRUE //now the check's done, update their brain so it remembers how stressed they were - B.laststress = currentstress + if(B && !isbelly(H.loc)) //another sanity check for brain implant shenanigans, also no you don't get to hide in a belly and get your laststress set to a huge amount to skip rolls + B.laststress = currentstress // Handle being feral if(feral) @@ -340,6 +339,7 @@ burn_mod = 1.15 //15% burn damage increase. They're spiders. Aerosol can+lighter = dead spiders. num_alternate_languages = 3 + species_language = LANGUAGE_VESPINAE secondary_langs = list(LANGUAGE_VESPINAE) color_mult = 1 tail = "tail" //Spider tail. @@ -428,6 +428,7 @@ num_alternate_languages = 3 secondary_langs = list(LANGUAGE_CANILUNZT) name_language = LANGUAGE_CANILUNZT + species_language = LANGUAGE_CANILUNZT primitive_form = "Wolpin" color_mult = 1 icon_height = 64 diff --git a/code/modules/mob/living/carbon/human/species/station/station_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_vr.dm index aa9b570889..af8e13e9a4 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_vr.dm @@ -14,6 +14,7 @@ num_alternate_languages = 3 secondary_langs = list(LANGUAGE_SAGARU) name_language = LANGUAGE_SAGARU + species_language = LANGUAGE_SAGARU color_mult = 1 inherent_verbs = list(/mob/living/carbon/human/proc/tie_hair) @@ -81,11 +82,12 @@ //burn_mod = 1.15 //gluttonous = 1 num_alternate_languages = 3 - secondary_langs = list(LANGUAGE_SKRELLIAN) - name_language = LANGUAGE_SKRELLIAN + secondary_langs = list(LANGUAGE_SPACER) + name_language = LANGUAGE_SPACER + species_language = LANGUAGE_SPACER color_mult = 1 assisted_langs = list(LANGUAGE_EAL, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) - inherent_verbs = list(/mob/living/carbon/human/proc/tie_hair) + inherent_verbs = list(/mob/living/carbon/human/proc/tie_hair, /mob/living/carbon/human/proc/water_stealth, /mob/living/carbon/human/proc/underwater_devour) min_age = 18 max_age = 110 @@ -113,6 +115,7 @@ appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR water_breather = TRUE + water_movement = -4 //Negates shallow. Halves deep. flesh_color = "#AFA59E" base_color = "#777777" @@ -135,6 +138,7 @@ num_alternate_languages = 3 secondary_langs = list(LANGUAGE_BIRDSONG) name_language = LANGUAGE_BIRDSONG + species_language = LANGUAGE_BIRDSONG color_mult = 1 inherent_verbs = list(/mob/living/proc/flying_toggle, /mob/living/proc/flying_vore_toggle, @@ -184,10 +188,11 @@ num_alternate_languages = 3 secondary_langs = list(LANGUAGE_TERMINUS) name_language = LANGUAGE_TERMINUS + species_language = LANGUAGE_TERMINUS inherent_verbs = list(/mob/living/carbon/human/proc/lick_wounds, /mob/living/proc/shred_limb, /mob/living/carbon/human/proc/tie_hair) - assisted_langs = list(LANGUAGE_EAL, LANGUAGE_SKRELLIAN, LANGUAGE_SKRELLIANFAR, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) //AEIOU edit: Zorren can speak Terminus unassisted. + assisted_langs = list(LANGUAGE_EAL, LANGUAGE_SKRELLIAN, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) //AEIOU edit: Zorren can speak Terminus unassisted. min_age = 18 max_age = 110 @@ -238,6 +243,7 @@ // default_language = "Sol Common" secondary_langs = list(LANGUAGE_CANILUNZT) name_language = LANGUAGE_CANILUNZT + species_language = LANGUAGE_CANILUNZT primitive_form = "Wolpin" tail = "vulptail" tail_animation = 'icons/mob/species/vulpkanin/tail.dmi' // probably need more than just one of each, but w/e @@ -256,6 +262,27 @@ // wikilink="https://wiki.vore-station.net/Backstory#Vulpkanin" catalogue_data = list(/datum/category_item/catalogue/fauna/vulpkanin) + + //Furry fox-like animals shouldn't start freezing at 5 degrees celsius. + //Minor cold is resisted, but not severe frost. + cold_discomfort_level = 263 //Not as good at surviving the frost as tajara, but still better than humans. + + cold_level_1 = 243 //Default 260, other values remain at default. Starts taking damage at -30 celsius. Default tier 2 is -70 and tier 3 is -150 + + + breath_cold_level_1 = 220 // Default 240, lower is better. + + //While foxes can survive in deserts, that's handled by zorren. It's a good contrast that our vulp find heat a little uncomfortable. + + heat_discomfort_level = 295 //Just above standard 20 C to avoid heat message spam, same as Taj + + heat_level_1 = 345 //Default 360 + heat_level_2 = 390 //Default 400 + heat_level_3 = 900 //Default 1000 + + breath_heat_level_1 = 370 //Default 380 - Higher is better + breath_heat_level_2 = 445 //Default 450 + breath_heat_level_3 = 1125 //Default 1250 primitive_form = "Wolpin" @@ -269,6 +296,12 @@ min_age = 18 max_age = 110 + + heat_discomfort_strings = list( + "Your fur prickles in the heat.", + "You feel uncomfortably warm.", + "Your overheated skin itches." + ) /datum/species/unathi mob_size = MOB_MEDIUM //To allow normal mob swapping @@ -311,7 +344,7 @@ deform = 'icons/mob/human_races/r_def_skrell_vr.dmi' color_mult = 1 min_age = 18 - inherent_verbs = list(/mob/living/carbon/human/proc/tie_hair) + inherent_verbs = list(/mob/living/carbon/human/proc/tie_hair, /mob/living/carbon/human/proc/water_stealth, /mob/living/carbon/human/proc/underwater_devour) reagent_tag = null allergens = null assisted_langs = list(LANGUAGE_EAL, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) @@ -320,6 +353,9 @@ wikilink="https://wiki.chompstation13.net/index.php?title=Skrell" genders = list(MALE, FEMALE, PLURAL, NEUTER) + water_breather = TRUE + water_movement = -4 //Negates shallow. Halves deep. + /datum/species/zaddat spawn_flags = SPECIES_CAN_JOIN min_age = 18 @@ -394,7 +430,8 @@ icobase_tail = 1 unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite) num_alternate_languages = 3 - secondary_langs = list(LANGUAGE_BIRDSONG) + secondary_langs = list(LANGUAGE_BIRDSONG, LANGUAGE_UNATHI) + species_language = LANGUAGE_UNATHI name_language = null color_mult = 1 genders = list(MALE, FEMALE, PLURAL, NEUTER) @@ -553,6 +590,7 @@ num_alternate_languages = 3 secondary_langs = list(LANGUAGE_TERMINUS) name_language = LANGUAGE_TERMINUS + species_language = LANGUAGE_TERMINUS inherent_verbs = list(/mob/living/carbon/human/proc/lick_wounds,/mob/living/proc/shred_limb,/mob/living/carbon/human/proc/tie_hair) min_age = 18 @@ -617,3 +655,61 @@ "You feel uncomfortably warm.", "Your chitin feels hot." ) + +/datum/species/altevian + name = SPECIES_ALTEVIAN + name_plural = "Altevians" + icobase = 'icons/mob/human_races/r_altevian.dmi' + deform = 'icons/mob/human_races/r_def_altevian.dmi' + unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp) + language = LANGUAGE_TAVAN + num_alternate_languages = 3 + secondary_langs = list(LANGUAGE_TAVAN) + species_language = LANGUAGE_TAVAN + name_language = null + color_mult = 1 + inherent_verbs = list(/mob/living/carbon/human/proc/tie_hair) + + min_age = 18 + max_age = 80 + + blurb = "The Altevian are a species of tall, rodent humanoids that are akin to rats for their features. \ + The Altevian, unlike most species, do not have a home planet, nor system, adopting a fully nomadic lifestyle \ + for their survival across the stars. Instead, they have opted to live in massive super capital-class colony-ships \ + with a flagship as their place they would call home." + + // wikilink="https://wiki.vore-station.net/Altevian" //CHOMPedit + + catalogue_data = list(/datum/category_item/catalogue/fauna/altevian) + + spawn_flags = SPECIES_CAN_JOIN + appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR + + flesh_color = "#AFA59E" + base_color = "#777777" + + genders = list(MALE, FEMALE, PLURAL, NEUTER) + + burn_mod = 1.15 + hunger_factor = 0.04 + can_zero_g_move = TRUE + + heat_discomfort_strings = list( + "Your fur prickles in the heat.", + "You feel uncomfortably warm.", + "Your overheated skin itches." + ) + + has_limbs = list( + BP_TORSO = list("path" = /obj/item/organ/external/chest), + BP_GROIN = list("path" = /obj/item/organ/external/groin), + BP_HEAD = list("path" = /obj/item/organ/external/head), + BP_L_ARM = list("path" = /obj/item/organ/external/arm), + BP_R_ARM = list("path" = /obj/item/organ/external/arm/right), + BP_L_LEG = list("path" = /obj/item/organ/external/leg), + BP_R_LEG = list("path" = /obj/item/organ/external/leg/right), + BP_L_HAND = list("path" = /obj/item/organ/external/hand), + BP_R_HAND = list("path" = /obj/item/organ/external/hand/right), + BP_L_FOOT = list("path" = /obj/item/organ/external/foot), + BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right) + ) diff --git a/code/modules/mob/living/carbon/human/species/station/teshari.dm b/code/modules/mob/living/carbon/human/species/station/teshari.dm index 17fe6606da..050e3a729b 100644 --- a/code/modules/mob/living/carbon/human/species/station/teshari.dm +++ b/code/modules/mob/living/carbon/human/species/station/teshari.dm @@ -27,6 +27,7 @@ //CHOMPStation Add. Y'know I should probably just put this upstream. male_scream_sound = 'sound/effects/mob_effects/teshariscream.ogg' female_scream_sound = 'sound/effects/mob_effects/teshariscream.ogg' + center_offset = 0 //CHOMPEdit //CHOMPStation Add End blood_color = "#D514F7" @@ -80,7 +81,7 @@ breath_cold_level_2 = 100 //Default 180 breath_cold_level_3 = 60 //Default 100 - heat_level_1 = 320 //Default 360 + heat_level_1 = 330 //Default 360 heat_level_2 = 370 //Default 400 heat_level_3 = 600 //Default 1000 diff --git a/code/modules/mob/living/carbon/human/species/station/teshari_vr.dm b/code/modules/mob/living/carbon/human/species/station/teshari_vr.dm index 4e61c3b169..b7f46bcc3c 100644 --- a/code/modules/mob/living/carbon/human/species/station/teshari_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/teshari_vr.dm @@ -1,5 +1,5 @@ /datum/species/teshari - mob_size = MOB_SMALL //YW Edit: changed from MOB_MEDIUM to MOB_SMALL + mob_size = MOB_MEDIUM spawn_flags = SPECIES_CAN_JOIN icobase = 'icons/mob/human_races/r_teshari_vr.dmi' deform = 'icons/mob/human_races/r_teshari_vr.dmi' diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm index 7c01fd47f7..25bb2c5aaf 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm @@ -124,7 +124,7 @@ /datum/trait/negative/neural_hypersensitivity name = "Neural Hypersensitivity" - desc = "Your nerves are particularly sensitive to physical changes, leading to experiencing twice the intensity of pain and pleasure alike. Doubles traumatic shock." + desc = "Your nerves are particularly sensitive to physical changes, leading to experiencing twice the intensity of pain and pleasure alike. Makes all pain effects twice as strong, and occur at half as much damage." cost = -1 var_changes = list("trauma_mod" = 2) can_take = ORGANICS @@ -136,19 +136,12 @@ /datum/trait/negative/breathes/phoron name = "Phoron Breather" desc = "You breathe phoron instead of oxygen (which is poisonous to you), much like a Vox." - var_changes = list("breath_type" = "phoron", "poison_type" = "oxygen") + var_changes = list("breath_type" = "phoron", "poison_type" = "oxygen", "ideal_air_type" = /datum/gas_mixture/belly_air/vox) /datum/trait/negative/breathes/nitrogen name = "Nitrogen Breather" desc = "You breathe nitrogen instead of oxygen (which is poisonous to you). Incidentally, phoron isn't poisonous to breathe to you." - var_changes = list("breath_type" = "nitrogen", "poison_type" = "oxygen") - -/datum/trait/negative/monolingual - name = "Monolingual" - desc = "You are not good at learning languages." - cost = -3 - var_changes = list("num_alternate_languages" = 0) - varchange_type = TRAIT_VARCHANGE_MORE_BETTER + var_changes = list("breath_type" = "nitrogen", "poison_type" = "oxygen", "ideal_air_type" = /datum/gas_mixture/belly_air/nitrogen_breather) /datum/trait/negative/monolingual name = "Monolingual" diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative_ch.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative_ch.dm index 9396c85293..fb91b0cce7 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative_ch.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative_ch.dm @@ -76,6 +76,7 @@ desc = "You are blind. For whatever reason, nothing is able to change this fact, not even surgery. WARNING: YOU WILL NOT BE ABLE TO SEE ANY POSTS USING THE ME VERB, ONLY SUBTLE AND DIALOGUE ARE VIEWABLE TO YOU, YOU HAVE BEEN WARNED." cost = -8 special_env = TRUE + custom_only = FALSE /datum/trait/negative/blindness/handle_environment_special(var/mob/living/carbon/human/H) H.sdisabilities |= BLIND //no matter what you do, the blindess still comes for you @@ -169,10 +170,10 @@ // Check for company. for(var/mob/living/M in viewers(get_turf(H))) in_range |= check_mob_company(H,M) - + for(var/obj/effect/overlay/aiholo/A in range(5, H)) in_range |= A - + if(in_range.len > 2) if(H.loneliness_stage < warning_cap) H.loneliness_stage = min(warning_cap,H.loneliness_stage+escalation_speed) @@ -232,7 +233,7 @@ return in_range var/social_check = !istype(M, /mob/living/carbon) && !istype(M, /mob/living/silicon/robot) var/ckey_check = !M.ckey - var/overall_checks = M == H || M.stat == DEAD || social_check || ckey_check + var/overall_checks = M == H || M.stat == DEAD || social_check || ckey_check if(invis_matters && M.invisibility > H.see_invisible) return in_range if(!overall_checks) @@ -291,7 +292,7 @@ var/social_check = only_people && !istype(M, /mob/living/carbon) && !istype(M, /mob/living/silicon/robot) var/self_invisible_check = M == H || M.invisibility > H.see_invisible var/ckey_check = only_people && !M.ckey - var/overall_checks = M.stat == DEAD || social_check || ckey_check + var/overall_checks = M.stat == DEAD || social_check || ckey_check if(self_invisible_check) return 0 if((M.faction == "neutral" || M.faction == H.faction) && !overall_checks) @@ -351,7 +352,7 @@ sub_loneliness(H) for(var/obj/effect/overlay/aiholo/A in range(5, H)) sub_loneliness(H) - + // No company? Suffer :( if(H.loneliness_stage < warning_cap) H.loneliness_stage = min(warning_cap,H.loneliness_stage+escalation_speed) @@ -382,23 +383,23 @@ desc = "Your body is very fragile. Reduces your maximum hitpoints to 25. Beware sneezes. You require only 50 damage in total to die, compared to 200 normally. You will go into crit after losing 25 HP, compared to crit at 100 HP." cost = -12 // Similar to Very Low Endurance, this straight up will require you NEVER getting in a fight. This is extremely crippling. I salute the madlad that takes this. var_changes = list("total_health" = 25) - + /datum/trait/negative/endurance_glass/apply(var/datum/species/S,var/mob/living/carbon/human/H) ..(S,H) H.setMaxHealth(S.total_health) - + /datum/trait/negative/reduced_biocompat_minor name = "Reduced Biocompatibility, Minor" desc = "For whatever reason, you're one of the unlucky few who don't get as much benefit from modern-day chemicals. Remember to note this down in your medical records! Chems are only 80% as effective on you!" cost = -1 var_changes = list("chem_strength_heal" = 0.8) - + /datum/trait/negative/reduced_biocompat name = "Reduced Biocompatibility" desc = "For whatever reason, you're one of the unlucky few who don't get as much benefit from modern-day chemicals. Remember to note this down in your medical records! Chems are only 60% as effective on you!" cost = -4 var_changes = list("chem_strength_heal" = 0.6) - + /datum/trait/negative/reduced_biocompat_extreme name = "Reduced Biocompatibility, Major" desc = "For whatever reason, you're one of the unlucky few who don't get as much benefit from modern-day chemicals. Remember to note this down in your medical records! Chems are only 30% as effective on you!" @@ -428,10 +429,10 @@ /datum/trait/negative/haemophilia_plus/apply(var/datum/species/S,var/mob/living/carbon/human/H) ..(S,H) H.add_modifier(/datum/modifier/trait/haemophilia) - + /datum/trait/negative/pain_intolerance_basic name = "Pain Intolerance" - desc = "You are frail and sensitive to pain. You experience 25% more pain from all sources." + desc = "You are frail and sensitive to pain. You experience 25% more pain from all sources." cost = -2 var_changes = list("pain_mod" = 1.2) // CHOMPEdit: Makes this exact opposite of Pain Tolerance Basic. @@ -440,7 +441,7 @@ desc = "You are highly sensitive to all sources of pain, and experience 50% more pain." cost = -3 var_changes = list("pain_mod" = 1.5) //this makes you extremely vulnerable to most sources of pain, a stunbaton bop or shotgun beanbag will do around 90 agony, almost enough to drop you in one hit. CHOMPEdit: This really should cost more if it's this bad. - + /datum/trait/negative/sensitive_biochem name = "Sensitive Biochemistry" diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm index fbd4c094b1..7aae2b9d69 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm @@ -91,8 +91,8 @@ desc = "Makes you unable to gain nutrition from anything but blood. To compensate, you get fangs that can be used to drain blood from prey." cost = 0 custom_only = FALSE - var_changes = list("organic_food_coeff" = 0) //The verb is given in human.dm - excludes = list(/datum/trait/positive/bloodsucker_plus) //YW edit + var_changes = list("organic_food_coeff" = 0, "bloodsucker" = TRUE) //The verb is given in human.dm + excludes = list(/datum/trait/neutral/bloodsucker_freeform, /datum/trait/positive/bloodsucker_plus) //YW edit /datum/trait/neutral/bloodsucker/apply(var/datum/species/S,var/mob/living/carbon/human/H) ..(S,H) @@ -103,6 +103,7 @@ desc = "You get fangs that can be used to drain blood from prey." cost = 0 custom_only = FALSE + var_changes = list("bloodsucker" = TRUE) excludes = list(/datum/trait/neutral/bloodsucker, /datum/trait/positive/bloodsucker_plus) //YW edit /datum/trait/neutral/bloodsucker_freeform/apply(var/datum/species/S,var/mob/living/carbon/human/H) @@ -121,6 +122,16 @@ H.verbs |= /mob/living/carbon/human/proc/succubus_drain_finalize H.verbs |= /mob/living/carbon/human/proc/succubus_drain_lethal +/datum/trait/neutral/long_vore + name = "Long Predatorial Reach" + desc = "Makes you able to use your tongue to grab creatures." + cost = 0 + custom_only = FALSE + +/datum/trait/neutral/long_vore/apply(var/datum/species/S,var/mob/living/carbon/human/H) + ..(S,H) + H.verbs |= /mob/living/proc/long_vore + /datum/trait/neutral/feeder name = "Feeder" desc = "Allows you to feed your prey using your own body." @@ -165,11 +176,12 @@ /datum/trait/neutral/synth_chemfurnace name = "Biofuel Processor" - desc = "You are able to gain energy through consuming and processing normal food. Energy-dense foods such as protein bars and survival food will yield the best results." + desc = "You are able to gain energy through consuming and processing normal food, at the cost of significantly slower recharging via cyborg chargers. Energy-dense foods such as protein bars and survival food will yield the best results." cost = 0 custom_only = FALSE can_take = SYNTHETICS var_changes = list("organic_food_coeff" = 0.75, "synthetic_food_coeff" = 1) //CHOMPEdit: Increase values + excludes = list(/datum/trait/neutral/biofuel_value_down) /datum/trait/neutral/glowing_eyes name = "Glowing Eyes" @@ -269,8 +281,75 @@ custom_only = FALSE allergen = ALLERGEN_COFFEE +/datum/trait/neutral/allergy_reaction + name = "Allergy Reaction: Disable Toxicity" + desc = "Take this trait to disable the toxic damage effect of being exposed to one of your allergens. Combine with the Disable Suffocation trait to have purely nonlethal reactions." + cost = 0 + custom_only = FALSE + var/reaction = AG_TOX_DMG + +/datum/trait/neutral/allergy_reaction/apply(var/datum/species/S,var/mob/living/carbon/human/H) + S.allergen_reaction ^= reaction + ..(S,H) + +/datum/trait/neutral/allergy_reaction/oxy + name = "Allergy Reaction: Disable Suffocation" + desc = "Take this trait to disable the oxygen deprivation damage effect of being exposed to one of your allergens. Combine with the Disable Toxicity trait to have purely nonlethal reactions." + cost = 0 + custom_only = FALSE + reaction = AG_OXY_DMG + +/datum/trait/neutral/allergy_reaction/brute + name = "Allergy Reaction: Spontaneous Trauma" + desc = "When exposed to one of your allergens, your skin develops unnatural bruises and other 'stigmata'-like injuries. Be aware that untreated wounds may become infected." + cost = 0 + custom_only = FALSE + reaction = AG_PHYS_DMG + +/datum/trait/neutral/allergy_reaction/burn + name = "Allergy Reaction: Blistering" + desc = "When exposed to one of your allergens, your skin develops unnatural blisters and burns, as if exposed to fire. Be aware that untreated burns are very susceptible to infection!" + cost = 0 + custom_only = FALSE + reaction = AG_BURN_DMG + +/datum/trait/neutral/allergy_reaction/pain + name = "Allergy Reaction: Disable Pain" + desc = "Take this trait to disable experiencing pain after being exposed to one of your allergens." + cost = 0 + custom_only = FALSE + reaction = AG_PAIN + +/datum/trait/neutral/allergy_reaction/weaken + name = "Allergy Reaction: Knockdown" + desc = "When exposed to one of your allergens, you will experience sudden and abrupt loss of muscle control and tension, resulting in immediate collapse and immobility. Does nothing if you have no allergens." + cost = 0 + custom_only = FALSE + reaction = AG_WEAKEN + +/datum/trait/neutral/allergy_reaction/blurry + name = "Allergy Reaction: Disable Blurring" + desc = "Take this trait to disable the blurred/impeded vision effect of allergens." + cost = 0 + custom_only = FALSE + reaction = AG_BLURRY + +/datum/trait/neutral/allergy_reaction/sleepy + name = "Allergy Reaction: Fatigue" + desc = "When exposed to one of your allergens, you will experience fatigue and tiredness, and may potentially pass out entirely. Does nothing if you have no allergens." + cost = 0 + custom_only = FALSE + reaction = AG_SLEEPY + +/datum/trait/neutral/allergy_reaction/confusion + name = "Allergy Reaction: Disable Confusion" + desc = "Take this trait to disable the confusion/disorientation effect of allergens." + cost = 0 + custom_only = FALSE + reaction = AG_CONFUSE + /datum/trait/neutral/allergen_reduced_effect - name = "Reduced Allergen Reaction" + name = "Allergen Reaction: Reduced Intensity" desc = "This trait drastically reduces the effects of allergen reactions. If you don't have any allergens set, it does nothing. It does not apply to special reactions (such as unathi drowsiness from sugars)." cost = 0 custom_only = FALSE @@ -278,7 +357,7 @@ excludes = list(/datum/trait/neutral/allergen_increased_effect) /datum/trait/neutral/allergen_increased_effect - name = "Increased Allergen Reaction" + name = "Allergen Reaction: Increased Intensity" desc = "This trait drastically increases the effects of allergen reactions, enough that even a small dose can be lethal. If you don't have any allergens set, it does nothing. It does not apply to special reactions (such as unathi drowsiness from sugars)." cost = 0 custom_only = FALSE @@ -331,45 +410,53 @@ // Alcohol Traits Start Here, from negative to positive. /datum/trait/neutral/alcohol_intolerance_advanced name = "Liver of Air" - desc = "The only way you can hold a drink is if it's in your own two hands, and even then you'd best not inhale too deeply near it. Drinks are three times as strong." + desc = "The only way you can hold a drink is if it's in your own two hands, and even then you'd best not inhale too deeply near it. Alcohol hits you three times as hard as they do other people." cost = 0 custom_only = FALSE - var_changes = list("alcohol_mod" = 3) // 300% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! + var_changes = list("chem_strength_alcohol" = 3) /datum/trait/neutral/alcohol_intolerance_basic name = "Liver of Lilies" - desc = "You have a hard time with alcohol. Maybe you just never took to it, or maybe it doesn't agree with you... either way, drinks are twice as strong." + desc = "You have a hard time with alcohol. Maybe you just never took to it, or maybe it doesn't agree with your system... either way, alcohol hits you twice as hard." cost = 0 custom_only = FALSE - var_changes = list("alcohol_mod" = 2) // 200% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! + var_changes = list("chem_strength_alcohol" = 2) /datum/trait/neutral/alcohol_intolerance_slight name = "Liver of Tulips" - desc = "You have a slight struggle with alcohol. Drinks are one and a half times stronger." + desc = "You are what some might call 'a bit of a lightweight', but you can still keep your drinks down... most of the time. Alcohol hits you fifty percent harder." cost = 0 custom_only = FALSE - var_changes = list("alcohol_mod" = 1.5) // 150% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! + var_changes = list("chem_strength_alcohol" = 1.5) + +/datum/trait/neutral/alcohol_tolerance_reset + name = "Liver of Unremarkableness" + desc = "This trait exists to reset alcohol (in)tolerance for non-custom species to baseline normal. It can only be taken by Skrell, Tajara, Unathi, Diona, and Prometheans, as it would have no effect on other species." + cost = 0 + custom_only = FALSE + var_changes = list("chem_strength_alcohol" = 1) + allowed_species = list(SPECIES_SKRELL,SPECIES_TAJ,SPECIES_UNATHI,SPECIES_DIONA,SPECIES_PROMETHEAN) /datum/trait/neutral/alcohol_tolerance_basic name = "Liver of Iron" - desc = "You can hold drinks much better than those lily-livered land-lubbers! Arr! Drinks are only three-quarters as strong." + desc = "You can hold drinks much better than those lily-livered land-lubbers! Arr! Alcohol's effects on you are reduced by about a quarter." cost = 0 custom_only = FALSE - var_changes = list("alcohol_mod" = 0.75) // 75% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! + var_changes = list("chem_strength_alcohol" = 0.75) /datum/trait/neutral/alcohol_tolerance_advanced name = "Liver of Steel" - desc = "Drinks tremble before your might! You can hold your alcohol twice as well as those blue-bellied barnacle boilers! Drinks are only half as strong." + desc = "Drinks tremble before your might! You can hold your alcohol twice as well as those blue-bellied barnacle boilers! Alcohol has just half the effect on you as it does on others." cost = 0 custom_only = FALSE - var_changes = list("alcohol_mod" = 0.5) // 50% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! + var_changes = list("chem_strength_alcohol" = 0.5) /datum/trait/neutral/alcohol_immunity name = "Liver of Durasteel" desc = "You've drunk so much that most booze doesn't even faze you. It takes something like a Pan-Galactic or a pint of Deathbell for you to even get slightly buzzed." cost = 0 custom_only = FALSE - var_changes = list("alcohol_mod" = 0.25) // 25% as effective if alcohol_mod is set to 1. If it's not 1 in species.dm, update this! + var_changes = list("chem_strength_alcohol" = 0.25) // Alcohol Traits End Here. /datum/trait/neutral/colorblind/mono @@ -584,4 +671,44 @@ desc = "You provide a lot less nutrition to anyone who makes a meal of you." cost = 0 custom_only = FALSE - var_changes = list("digestion_nutrition_modifier" = 0.25) \ No newline at end of file + var_changes = list("digestion_nutrition_modifier" = 0.25) + + +/datum/trait/neutral/food_value_down + name = "Insatiable" + desc = "You need to eat a third of a plate more to be sated." + cost = 0 + custom_only = FALSE + can_take = ORGANICS + var_changes = list(organic_food_coeff = 0.67, digestion_efficiency = 0.66) + excludes = list(/datum/trait/neutral/bloodsucker) + +/datum/trait/neutral/food_value_down_plus + name = "Insatiable, Greater" + desc = "You need to eat three times as much to feel sated." + cost = 0 + custom_only = FALSE + can_take = ORGANICS + var_changes = list(organic_food_coeff = 0.33, digestion_efficiency = 0.33) + excludes = list(/datum/trait/neutral/bloodsucker, /datum/trait/neutral/food_value_down) + +/datum/trait/neutral/biofuel_value_down + name = "Discount Biofuel processor" + desc = "You are able to gain energy through consuming and processing normal food. Unfortunately, it is half as effective as premium models. On the plus side, you still recharge from charging stations fairly efficiently." + cost = 0 + custom_only = FALSE + can_take = SYNTHETICS + var_changes = list("organic_food_coeff" = 0, "synthetic_food_coeff" = 0.3, digestion_efficiency = 0.5) + excludes = list(/datum/trait/neutral/synth_chemfurnace) + +/datum/trait/neutral/synth_cosmetic_pain + name = "Pain simulation" + desc = "You have added modules in your synthetic shell that simulates the sensation of pain. You are able to turn this on and off for repairs as needed or convenience at will." + cost = 0 + custom_only = FALSE + can_take = SYNTHETICS + + +/datum/trait/neutral/synth_cosmetic_pain/apply(var/datum/species/S,var/mob/living/carbon/human/H) + ..(S,H) + H.verbs |= /mob/living/carbon/human/proc/toggle_pain_module diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm index be507a7c78..b61f3923e4 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/positive.dm @@ -175,11 +175,16 @@ H.verbs |= /mob/living/carbon/human/proc/weave_item H.verbs |= /mob/living/carbon/human/proc/set_silk_color -/datum/trait/positive/water_breather - name = "Water Breather" - desc = "You can breathe under water." +/datum/trait/positive/aquatic + name = "Aquatic" + desc = "You can breathe under water and can traverse water more efficiently. Additionally, you can eat others in the water." cost = 1 - var_changes = list("water_breather" = 1) + var_changes = list("water_breather" = 1, "water_movement" = -4) //Negate shallow water. Half the speed in deep water. + +/datum/trait/positive/aquatic/apply(var/datum/species/S,var/mob/living/carbon/human/H) + ..(S,H) + H.verbs |= /mob/living/carbon/human/proc/water_stealth + H.verbs |= /mob/living/carbon/human/proc/underwater_devour /datum/trait/positive/cocoon_tf name = "Cocoon Spinner" @@ -210,3 +215,11 @@ custom_only = FALSE varchange_type = TRAIT_VARCHANGE_MORE_BETTER */ + +/datum/trait/positive/trauma_tolerance //CHOMPEdit renamed because we already have pain_tolerance pathname for halloss damage resistance. + name = "Grit" + desc = "You can keep going a little longer, a little harder when you get hurt, Injuries only inflict 85% as much pain, and slowdown from pain is 85% as effective." + cost = 2 + var_changes = list("trauma_mod" = 0.85) + excludes = list(/datum/trait/negative/neural_hypersensitivity) + can_take = ORGANICS diff --git a/code/modules/mob/living/carbon/human/species/station/xenochimera_trait_vr.dm b/code/modules/mob/living/carbon/human/species/station/xenochimera_trait_vr.dm index 2f2adc4487..023a9272cb 100644 --- a/code/modules/mob/living/carbon/human/species/station/xenochimera_trait_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/xenochimera_trait_vr.dm @@ -43,7 +43,7 @@ cost = 0 category = 0 custom_only = FALSE - var_changes = list("unarmed_types" = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/chimera, /datum/unarmed_attack/bite/sharp, /datum/unarmed_attack/bite/sharp/numbing)) // CHOMPEdit: Fix 'chimera unarmed attacks with this trait + var_changes = list("unarmed_types" = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/chimera, /datum/unarmed_attack/bite/sharp, /datum/unarmed_attack/bite/sharp/numbing)) // Fixes the parent forgetting to add 'chimera-specific claws /datum/trait/positive/snowwalker/xenochimera sort = TRAIT_SORT_SPECIES @@ -54,13 +54,23 @@ category = 0 custom_only = FALSE -/datum/trait/positive/water_breather/xenochimera +/datum/trait/positive/aquatic/xenochimera sort = TRAIT_SORT_SPECIES allowed_species = list(SPECIES_XENOCHIMERA) - name = "Xenochimera: Water Breather" - desc = "You can breathe under water." + name = "Xenochimera: Aquatic" + desc = "You can breathe under water and can traverse water more efficiently. Additionally, you can eat others in the water." cost = 0 category = 0 + excludes = list(/datum/trait/positive/winged_flight/xenochimera) + custom_only = FALSE + +/datum/trait/positive/winged_flight/xenochimera + sort = TRAIT_SORT_SPECIES + allowed_species = list(SPECIES_XENOCHIMERA) + name = "Xenochhimera: Winged Flight" + desc = "Allows you to fly by using your wings. Don't forget to bring them!" + cost = 0 + excludes = list(/datum/trait/positive/aquatic/xenochimera) custom_only = FALSE /* // Commented out in lieu of finding a better solution. @@ -136,3 +146,13 @@ ), autohiss_exempt = list("Vespinae")) excludes = list(/datum/trait/neutral/autohiss_tajaran, /datum/trait/neutral/autohiss_unathi) +//End YW edit + +/datum/trait/positive/cocoon_tf/xenochimera + sort = TRAIT_SORT_SPECIES + allowed_species = list(SPECIES_XENOCHIMERA) + custom_only = FALSE + name = "Xenochimera: Cocoon Spinner" + desc = "Allows you to build a cocoon around yourself, using it to transform your body if you desire." + cost = 0 + category = 0 diff --git a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm index 17b31ffecc..c9254c0c9a 100644 --- a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm +++ b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm @@ -34,8 +34,12 @@ /mob/living/carbon/human/proc/shapeshifter_select_hair, /mob/living/carbon/human/proc/shapeshifter_select_hair_colors, /mob/living/carbon/human/proc/shapeshifter_select_gender, + /mob/living/carbon/human/proc/shapeshifter_select_wings, + /mob/living/carbon/human/proc/shapeshifter_select_tail, + /mob/living/carbon/human/proc/shapeshifter_select_ears, + /mob/living/proc/set_size, /mob/living/carbon/human/proc/regenerate, - /mob/living/carbon/human/proc/shapeshifter_change_opacity, + /mob/living/carbon/human/proc/promethean_select_opaqueness, /mob/living/carbon/human/proc/exit_vr ) @@ -75,9 +79,9 @@ src.vr_link = avatar // Can't reuse vr_holder so that death can automatically eject users from VR // Move the mind - avatar.Sleeping(1) + // avatar.Sleeping(1) So vox don't drop their can, also feels arbitrary src.mind.transfer_to(avatar) - to_chat(avatar, "You have enterred Virtual Reality!\nAll normal gameplay rules still apply.\nWounds you suffer here won't persist when you leave VR, but some of the pain will.\nYou can leave VR at any time by using the \"Exit Virtual Reality\" verb in the Abilities tab, or by ghosting.\nYou can modify your appearance by using various \"Change \[X\]\" verbs in the Abilities tab.") + to_chat(avatar, "You have enterred Virtual Reality!\nAll normal gameplay rules still apply.\nWounds you suffer here won't persist when you leave VR, but some of the pain will.\nYou can leave VR at any time by using the \"Exit Virtual Reality\" verb in the Abilities tab, or by ghosting.") //No more prommie VR thing, so removed tidbit about changing appearance to_chat(avatar, " You black out for a moment, and wake to find yourself in a new body in virtual reality.") // So this is what VR feels like? // exit_vr is called on the vr mob, and puts the mind back into the original mob @@ -113,4 +117,14 @@ if(istype(vr_holder.loc, /obj/machinery/vr_sleeper)) var/obj/machinery/vr_sleeper/V = vr_holder.loc - V.go_out() \ No newline at end of file + V.go_out() + + if(died_in_vr) + spawn(3000) //Delete the body after 5 minutes to make sure mob subsystem doesn't cry + var/list/slots = list(slot_back,slot_handcuffed,slot_l_store,slot_r_store,slot_wear_mask,slot_l_hand,slot_r_hand,slot_wear_id,slot_glasses,slot_gloves,slot_head,slot_shoes,slot_belt,slot_wear_suit,slot_w_uniform,slot_s_store,slot_l_ear,slot_r_ear) + for(var/slot in slots) + var/obj/item/I = get_equipped_item(slot = slot) + if(I) + unEquip(I,force = TRUE) + release_vore_contents(include_absorbed = TRUE, silent = TRUE) + qdel(src) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/stripping.dm b/code/modules/mob/living/carbon/human/stripping.dm index 7aa08accbb..e8c38208b2 100644 --- a/code/modules/mob/living/carbon/human/stripping.dm +++ b/code/modules/mob/living/carbon/human/stripping.dm @@ -59,6 +59,12 @@ var/obj/item/held = user.get_active_hand() if(!istype(held) || is_robot_module(held)) stripping = TRUE + //CHOMPEdit Start - Let borg grippers put stuff on. + if(is_robot_module(held) && istype(held, /obj/item/weapon/gripper)) + var/obj/item/weapon/gripper/G = held + if(istype(G.wrapped)) + stripping = FALSE + //CHOMPEdit End else var/obj/item/weapon/holder/holder = held if(istype(holder) && src == holder.held_mob) @@ -67,7 +73,7 @@ var/obj/item/weapon/grab/grab = held if(istype(grab) && grab.affecting == src) stripping = TRUE - + if(stripping) if(!istype(target_slot)) // They aren't holding anything valid and there's nothing to remove, why are we even here? return @@ -75,11 +81,19 @@ to_chat(user, "You cannot remove \the [src]'s [target_slot.name].") return visible_message("\The [user] is trying to remove \the [src]'s [target_slot.name]!") - else + else if(!istype(held, /obj/item/weapon/gripper)) //CHOMPEdit - Let borg grippers put stuff on. if(slot_to_strip == slot_wear_mask && istype(held, /obj/item/weapon/grenade)) visible_message("\The [user] is trying to put \a [held] in \the [src]'s mouth!") else visible_message("\The [user] is trying to put \a [held] on \the [src]!") + //CHOMPEdit Start - Let borg grippers put stuff on. + else + var/obj/item/weapon/gripper/G = held + if(slot_to_strip == slot_wear_mask && istype(G.wrapped, /obj/item/weapon/grenade)) + visible_message("\The [user] is trying to put \a [G.wrapped] in \the [src]'s mouth!") + else + visible_message("\The [user] is trying to put \a [G.wrapped] on \the [src]!") + //CHOMPEdit End if(!do_after(user,HUMAN_STRIP_DELAY,src)) return @@ -95,6 +109,14 @@ if(stripping) add_attack_logs(user,src,"Removed equipment from slot [target_slot]") unEquip(target_slot) + //CHOMPEdit Start - Let borg grippers put stuff on. + else if(is_robot_module(held) && istype(held, /obj/item/weapon/gripper)) + var/obj/item/weapon/gripper/G = held + var/obj/item/wrapped = G.wrapped + if(istype(wrapped)) + G.drop_item_nm() + equip_to_slot_if_possible(wrapped, text2num(slot_to_strip), 0, 1, 1) + //CHOMPEdit End else if(user.unEquip(held)) equip_to_slot_if_possible(held, text2num(slot_to_strip), 0, 1, 1) if(held.loc != src) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 7790bce549..a029e02b75 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -66,40 +66,41 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() #define MOB_DAM_LAYER 4 //Injury overlay sprites like open wounds #define SURGERY_LAYER 5 //Overlays for open surgical sites #define UNDERWEAR_LAYER 6 //Underwear/bras/etc -#define TAIL_SOUTH_LAYER 7 //Tail as viewed from the south -#define SHOES_LAYER_ALT 8 //Shoe-slot item (when set to be under uniform via verb) -#define UNIFORM_LAYER 9 //Uniform-slot item -#define ID_LAYER 10 //ID-slot item -#define SHOES_LAYER 11 //Shoe-slot item -#define GLOVES_LAYER 12 //Glove-slot item -#define BELT_LAYER 13 //Belt-slot item -#define SUIT_LAYER 14 //Suit-slot item -#define TAIL_NORTH_LAYER 15 //Some species have tails to render (As viewed from the N, E, or W) -#define GLASSES_LAYER 16 //Eye-slot item -#define BELT_LAYER_ALT 17 //Belt-slot item (when set to be above suit via verb) -#define SUIT_STORE_LAYER 18 //Suit storage-slot item -#define BACK_LAYER 19 //Back-slot item -#define HAIR_LAYER 20 //The human's hair -#define HAIR_ACCESSORY_LAYER 21 //VOREStation edit. Simply move this up a number if things are added. -#define EARS_LAYER 22 //Both ear-slot items (combined image) -#define EYES_LAYER 23 //Mob's eyes (used for glowing eyes) -#define FACEMASK_LAYER 24 //Mask-slot item -#define HEAD_LAYER 25 //Head-slot item -#define HANDCUFF_LAYER 26 //Handcuffs, if the human is handcuffed, in a secret inv slot -#define LEGCUFF_LAYER 27 //Same as handcuffs, for legcuffs -#define L_HAND_LAYER 28 //Left-hand item -#define R_HAND_LAYER 29 //Right-hand item -#define WING_LAYER 30 //Wings or protrusions over the suit. -#define TAIL_NORTH_LAYER_ALT 31 //Modified tail-sprite layer. Tend to be larger. -#define MODIFIER_EFFECTS_LAYER 32 //Effects drawn by modifiers -#define FIRE_LAYER 33 //'Mob on fire' overlay layer -#define MOB_WATER_LAYER 34 //'Mob submerged' overlay layer -#define TARGETED_LAYER 35 //'Aimed at' overlay layer -#define TOTAL_LAYERS 35 //VOREStation edit. <---- KEEP THIS UPDATED, should always equal the highest number here, used to initialize a list. +#define TAIL_LOWER_LAYER 7 //Tail as viewed from the south +#define WING_LOWER_LAYER 8 //Wings as viewed from the south +#define SHOES_LAYER_ALT 9 //Shoe-slot item (when set to be under uniform via verb) +#define UNIFORM_LAYER 10 //Uniform-slot item +#define ID_LAYER 11 //ID-slot item +#define SHOES_LAYER 12 //Shoe-slot item +#define GLOVES_LAYER 13 //Glove-slot item +#define BELT_LAYER 14 //Belt-slot item +#define SUIT_LAYER 15 //Suit-slot item +#define TAIL_UPPER_LAYER 16 //Some species have tails to render (As viewed from the N, E, or W) +#define GLASSES_LAYER 17 //Eye-slot item +#define BELT_LAYER_ALT 18 //Belt-slot item (when set to be above suit via verb) +#define SUIT_STORE_LAYER 19 //Suit storage-slot item +#define BACK_LAYER 20 //Back-slot item +#define HAIR_LAYER 21 //The human's hair +#define HAIR_ACCESSORY_LAYER 22 //VOREStation edit. Simply move this up a number if things are added. +#define EARS_LAYER 23 //Both ear-slot items (combined image) +#define EYES_LAYER 24 //Mob's eyes (used for glowing eyes) +#define FACEMASK_LAYER 25 //Mask-slot item +#define HEAD_LAYER 26 //Head-slot item +#define HANDCUFF_LAYER 27 //Handcuffs, if the human is handcuffed, in a secret inv slot +#define LEGCUFF_LAYER 28 //Same as handcuffs, for legcuffs +#define L_HAND_LAYER 29 //Left-hand item +#define R_HAND_LAYER 30 //Right-hand item +#define WING_LAYER 31 //Wings or protrusions over the suit. +#define VORE_BELLY_LAYER 32 //CHOMPStation edit - Move this and everything after up if things are added. +#define VORE_TAIL_LAYER 33 //CHOMPStation edit - Move this and everything after up if things are added. +#define TAIL_UPPER_LAYER_ALT 34 //Modified tail-sprite layer. Tend to be larger. +#define MODIFIER_EFFECTS_LAYER 35 //Effects drawn by modifiers +#define FIRE_LAYER 36 //'Mob on fire' overlay layer +#define MOB_WATER_LAYER 37 //'Mob submerged' overlay layer +#define TARGETED_LAYER 38 //'Aimed at' overlay layer +#define TOTAL_LAYERS 38 //CHOMPStation edit. <---- KEEP THIS UPDATED, should always equal the highest number here, used to initialize a list. ////////////////////////////////// -#define GET_TAIL_LAYER (dir == SOUTH ? TAIL_SOUTH_LAYER : TAIL_NORTH_LAYER) - /mob/living/carbon/human var/list/overlays_standing[TOTAL_LAYERS] var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed @@ -122,10 +123,10 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() // First, get the correct size. var/desired_scale_x = icon_scale_x var/desired_scale_y = icon_scale_y - + desired_scale_x *= species.icon_scale_x desired_scale_y *= species.icon_scale_y - + for(var/datum/modifier/M in modifiers) if(!isnull(M.icon_scale_x_percent)) desired_scale_x *= M.icon_scale_x_percent @@ -136,10 +137,14 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() var/desired_scale_y = size_multiplier * icon_scale_y desired_scale_x *= species.icon_scale_x desired_scale_y *= species.icon_scale_y + center_offset = species.center_offset //CHOMPEdit + if(offset_override) //CHOMPEdit + center_offset = 0 //CHOMPEdit vis_height = species.icon_height appearance_flags |= PIXEL_SCALE if(fuzzy) appearance_flags &= ~PIXEL_SCALE + center_offset = 0 //CHOMPEdit //VOREStation Edit End // Regular stuff again. @@ -151,20 +156,29 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() anim_time = 1 //Thud if(lying && !species.prone_icon) //Only rotate them if we're not drawing a specific icon for being prone. - var/randn = rand(1, 2) - if(randn <= 1) // randomly choose a rotation - M.Turn(-90) + // CHOMPEdit Start Loafy Time + if(tail_style?.can_loaf && resting) // Only call these if we're resting? + update_tail_showing() + M.Scale(desired_scale_x, desired_scale_y) else - M.Turn(90) - M.Scale(desired_scale_y, desired_scale_x)//VOREStation Edit - if(species.icon_height == 64)//VOREStation Edit - M.Translate(13,-22) - else - M.Translate(1,-6) + var/randn = rand(1, 2) + if(randn <= 1) // randomly choose a rotation + M.Turn(-90) + else + M.Turn(90) + if(species.icon_height == 64) + M.Translate(13,-22) + else + M.Translate(1,-6) + M.Scale(desired_scale_y, desired_scale_x) + M.Translate(center_offset * desired_scale_x, (vis_height/2)*(desired_scale_y-1)) //CHOMPEdit + // CHOMPEdit End layer = MOB_LAYER -0.01 // Fix for a byond bug where turf entry order no longer matters else M.Scale(desired_scale_x, desired_scale_y)//VOREStation Edit - M.Translate(0, (vis_height/2)*(desired_scale_y-1)) //VOREStation edit + M.Translate(center_offset * desired_scale_x, (vis_height/2)*(desired_scale_y-1)) //CHOMPEdit + if(tail_style?.can_loaf) // VOREStation Edit: Taur Loafing + update_tail_showing() // VOREStation Edit: Taur Loafing layer = MOB_LAYER // Fix for a byond bug where turf entry order no longer matters animate(src, transform = M, time = anim_time) @@ -252,6 +266,12 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() var/obj/item/organ/external/head/head = organs_by_name[BP_HEAD] if(head) if(!istype(head, /obj/item/organ/external/stump)) + if (species.selects_bodytype != SELECTS_BODYTYPE_FALSE) + var/headtype = GLOB.all_species[species.base_species]?.has_limbs[BP_HEAD] + var/obj/item/organ/external/head/headtypepath = headtype["path"] + if (headtypepath) + head.eye_icon = initial(headtypepath.eye_icon) + head.eye_icon_location = initial(headtypepath.eye_icon_location) icon_key += "[head.eye_icon]" for(var/organ_tag in species.has_limbs) var/obj/item/organ/external/part = organs_by_name[organ_tag] @@ -302,7 +322,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(digitigrade && (part.organ_tag == BP_R_LEG || part.organ_tag == BP_L_LEG || part.organ_tag == BP_R_FOOT || part.organ_tag == BP_L_FOOT)) icon_key += "_digi" //ChompEDIT END - + icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0]" var/icon/base_icon if(human_icon_cache[icon_key]) @@ -378,6 +398,8 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() //tail update_tail_showing() update_wing_showing() + update_vore_belly_sprite() + update_vore_tail_sprite() /mob/living/carbon/human/proc/update_skin() @@ -723,16 +745,34 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!l_ear && !r_ear) return //Why bother, if no ear sprites + if(hide_headset) //CHOMPEdit Start + if(l_ear && istype(l_ear, /obj/item/device/radio/headset)) //No need to generate blank images if only headsets are present. + if(!r_ear || istype(r_ear, /obj/item/device/radio/headset)) + return + if(r_ear && istype(r_ear, /obj/item/device/radio/headset)) + if(!l_ear || istype(l_ear, /obj/item/device/radio/headset)) + return + // Blank image upon which to layer left & right overlays. var/image/both = image(icon = 'icons/effects/effects.dmi', icon_state = "nothing", layer = BODY_LAYER+EARS_LAYER) if(l_ear) - var/image/standing = l_ear.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_l_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER) - both.add_overlay(standing) + if(istype(l_ear, /obj/item/device/radio/headset)) + if(!hide_headset) + var/image/standing = l_ear.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_l_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER) + both.add_overlay(standing) + else + var/image/standing = l_ear.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_l_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER) + both.add_overlay(standing) if(r_ear) - var/image/standing = r_ear.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_r_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER) - both.add_overlay(standing) + if(istype(r_ear, /obj/item/device/radio/headset)) + if(!hide_headset) + var/image/standing = r_ear.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_r_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER) + both.add_overlay(standing) + else + var/image/standing = r_ear.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_r_ear_str, default_icon = INV_EARS_DEF_ICON, default_layer = EARS_LAYER) + both.add_overlay(standing) //CHOMPEdit End overlays_standing[EARS_LAYER] = both apply_layer(EARS_LAYER) @@ -845,7 +885,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() suit_sprite = INV_SUIT_DEF_ICON var/icon/c_mask = null - var/tail_is_rendered = (overlays_standing[TAIL_NORTH_LAYER] || overlays_standing[TAIL_NORTH_LAYER_ALT] || overlays_standing[TAIL_SOUTH_LAYER]) + var/tail_is_rendered = (overlays_standing[TAIL_UPPER_LAYER] || overlays_standing[TAIL_UPPER_LAYER_ALT] || overlays_standing[TAIL_LOWER_LAYER]) var/valid_clip_mask = tail_style?.clip_mask if(tail_is_rendered && valid_clip_mask && !(istype(suit) && suit.taurized)) //Clip the lower half of the suit off using the tail's clip mask for taurs since taur bodies aren't hidden. @@ -958,19 +998,29 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() apply_layer(L_HAND_LAYER) +/mob/living/carbon/human/proc/get_tail_layer() + var/list/lower_layer_dirs = list(SOUTH) + if(tail_style) + lower_layer_dirs = tail_style.lower_layer_dirs.Copy() + + if(dir in lower_layer_dirs) + return TAIL_LOWER_LAYER + else + return TAIL_UPPER_LAYER + /mob/living/carbon/human/proc/update_tail_showing() if(QDESTROYING(src)) return - remove_layer(TAIL_NORTH_LAYER) - remove_layer(TAIL_NORTH_LAYER_ALT) - remove_layer(TAIL_SOUTH_LAYER) + remove_layer(TAIL_UPPER_LAYER) + remove_layer(TAIL_UPPER_LAYER_ALT) + remove_layer(TAIL_LOWER_LAYER) - var/tail_layer = GET_TAIL_LAYER + var/tail_layer = get_tail_layer() if(src.tail_style && src.tail_style.clip_mask_state) - tail_layer = TAIL_NORTH_LAYER // Use default, let clip mask handle everything - if(tail_alt && tail_layer == TAIL_NORTH_LAYER) - tail_layer = TAIL_NORTH_LAYER_ALT + tail_layer = TAIL_UPPER_LAYER // Use default, let clip mask handle everything + if(tail_alt && tail_layer == TAIL_UPPER_LAYER) + tail_layer = TAIL_UPPER_LAYER_ALT var/image/tail_image = get_tail_image() if(tail_image) @@ -1009,16 +1059,16 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() return tail_icon /mob/living/carbon/human/proc/set_tail_state(var/t_state) - var/tail_layer = GET_TAIL_LAYER + var/tail_layer = get_tail_layer() if(src.tail_style && src.tail_style.clip_mask_state) - tail_layer = TAIL_NORTH_LAYER // Use default, let clip mask handle everything - if(tail_alt && tail_layer == TAIL_NORTH_LAYER) - tail_layer = TAIL_NORTH_LAYER_ALT + tail_layer = TAIL_UPPER_LAYER // Use default, let clip mask handle everything + if(tail_alt && tail_layer == TAIL_UPPER_LAYER) + tail_layer = TAIL_UPPER_LAYER_ALT var/image/tail_overlay = overlays_standing[tail_layer] - remove_layer(TAIL_NORTH_LAYER) - remove_layer(TAIL_NORTH_LAYER_ALT) - remove_layer(TAIL_SOUTH_LAYER) + remove_layer(TAIL_UPPER_LAYER) + remove_layer(TAIL_UPPER_LAYER_ALT) + remove_layer(TAIL_LOWER_LAYER) if(tail_overlay) overlays_standing[tail_layer] = tail_overlay @@ -1036,9 +1086,9 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() return var/t_state = "[species.get_tail(src)]_once" - var/tail_layer = GET_TAIL_LAYER + var/tail_layer = get_tail_layer() if(src.tail_style && src.tail_style.clip_mask_state) - tail_layer = TAIL_NORTH_LAYER // Use default, let clip mask handle everything + tail_layer = TAIL_UPPER_LAYER // Use default, let clip mask handle everything var/image/tail_overlay = overlays_standing[tail_layer] if(tail_overlay && tail_overlay.icon_state == t_state) @@ -1084,13 +1134,20 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() return remove_layer(WING_LAYER) + remove_layer(WING_LOWER_LAYER) - var/image/wing_image = get_wing_image() + var/image/wing_image = get_wing_image(FALSE) if(wing_image) wing_image.layer = BODY_LAYER+WING_LAYER overlays_standing[WING_LAYER] = wing_image + if(wing_style && wing_style.multi_dir) + wing_image = get_wing_image(TRUE) + if(wing_image) + wing_image.layer = BODY_LAYER+WING_LOWER_LAYER + overlays_standing[WING_LOWER_LAYER] = wing_image apply_layer(WING_LAYER) + apply_layer(WING_LOWER_LAYER) /mob/living/carbon/human/update_modifier_visuals() if(QDESTROYING(src)) @@ -1104,8 +1161,14 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() var/image/effects = new() for(var/datum/modifier/M in modifiers) if(M.mob_overlay_state) - var/image/I = image(icon = 'icons/mob/modifier_effects.dmi', icon_state = M.mob_overlay_state) - effects.overlays += I // Leaving this as overlays += + if(M.icon_override) //VOREStation Edit. Override for the modifer icon. + var/image/I = image(icon = 'icons/mob/modifier_effects_vr.dmi', icon_state = M.mob_overlay_state) + I.color = M.effect_color + effects.overlays += I // Leaving this as overlays += + else + var/image/I = image(icon = 'icons/mob/modifier_effects.dmi', icon_state = M.mob_overlay_state) + I.color = M.effect_color + effects.overlays += I // Leaving this as overlays += overlays_standing[MODIFIER_EFFECTS_LAYER] = effects @@ -1157,7 +1220,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() overlays_standing[SURGERY_LAYER] = total apply_layer(SURGERY_LAYER) -/mob/living/carbon/human/proc/get_wing_image() +/mob/living/carbon/human/proc/get_wing_image(var/under_layer) if(QDESTROYING(src)) return @@ -1171,7 +1234,10 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() //If you have custom wings selected if(wing_style && !(wear_suit && wear_suit.flags_inv & HIDETAIL) && !wings_hidden) //VOREStation Edit - var/icon/wing_s = new/icon("icon" = wing_style.icon, "icon_state" = flapping && wing_style.ani_state ? wing_style.ani_state : wing_style.icon_state) + var/wing_state = (flapping && wing_style.ani_state) ? wing_style.ani_state : wing_style.icon_state + if(wing_style.multi_dir) + wing_state += "_[under_layer ? "back" : "front"]" + var/icon/wing_s = new/icon("icon" = wing_style.icon, "icon_state" = wing_state) if(wing_style.do_colouration) wing_s.Blend(rgb(src.r_wing, src.g_wing, src.b_wing), wing_style.color_blend_mode) if(wing_style.extra_overlay) @@ -1193,6 +1259,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() var/image/working = image(wing_s) if(wing_style.em_block) working.overlays += em_block_image_generic(working) // Leaving this as overlays += + working.pixel_x -= wing_style.wing_offset return working /mob/living/carbon/human/proc/get_ears_overlay() @@ -1224,18 +1291,20 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() /mob/living/carbon/human/proc/get_tail_image() //If you are FBP with tail style and didn't set a custom one var/datum/robolimb/model = isSynthetic() - if(istype(model) && model.includes_tail && !tail_style) + if(istype(model) && model.includes_tail && !tail_style && !tail_hidden) var/icon/tail_s = new/icon("icon" = synthetic.icon, "icon_state" = "tail") tail_s.Blend(rgb(src.r_skin, src.g_skin, src.b_skin), species.color_mult ? ICON_MULTIPLY : ICON_ADD) return image(tail_s) //If you have a custom tail selected - if(tail_style && !(wear_suit && wear_suit.flags_inv & HIDETAIL && !istaurtail(tail_style))) - var/icon/tail_s = new/icon("icon" = tail_style.icon, "icon_state" = wagging && tail_style.ani_state ? tail_style.ani_state : tail_style.icon_state) + if(tail_style && !(wear_suit && wear_suit.flags_inv & HIDETAIL && !istaurtail(tail_style)) && !tail_hidden) + var/icon/tail_s = new/icon("icon" = (tail_style.can_loaf && resting) ? tail_style.icon_loaf : tail_style.icon, "icon_state" = (wagging && tail_style.ani_state ? tail_style.ani_state : tail_style.icon_state)) //CHOMPEdit + if(tail_style.can_loaf && !is_shifted) + pixel_y = (resting) ? -tail_style.loaf_offset*size_multiplier : default_pixel_y //move player down, then taur up, to fit the overlays correctly // VOREStation Edit: Taur Loafing if(tail_style.do_colouration) tail_s.Blend(rgb(src.r_tail, src.g_tail, src.b_tail), tail_style.color_blend_mode) if(tail_style.extra_overlay) - var/icon/overlay = new/icon("icon" = tail_style.icon, "icon_state" = tail_style.extra_overlay) + var/icon/overlay = new/icon("icon" = (tail_style?.can_loaf && resting) ? tail_style.icon_loaf : tail_style.icon, "icon_state" = tail_style.extra_overlay) //CHOMPEdit if(wagging && tail_style.ani_state) overlay = new/icon("icon" = tail_style.icon, "icon_state" = tail_style.extra_overlay_w) overlay.Blend(rgb(src.r_tail2, src.g_tail2, src.b_tail2), tail_style.color_blend_mode) @@ -1247,7 +1316,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() qdel(overlay) if(tail_style.extra_overlay2) - var/icon/overlay = new/icon("icon" = tail_style.icon, "icon_state" = tail_style.extra_overlay2) + var/icon/overlay = new/icon("icon" = (tail_style?.can_loaf && resting) ? tail_style.icon_loaf : tail_style.icon, "icon_state" = tail_style.extra_overlay2) //CHOMPEdit if(wagging && tail_style.ani_state) overlay = new/icon("icon" = tail_style.icon, "icon_state" = tail_style.extra_overlay2_w) overlay.Blend(rgb(src.r_tail3, src.g_tail3, src.b_tail3), tail_style.color_blend_mode) @@ -1298,9 +1367,8 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() #undef GLOVES_LAYER #undef BELT_LAYER #undef SUIT_LAYER -#undef TAIL_NORTH_LAYER -#undef TAIL_SOUTH_LAYER -#undef GET_TAIL_LAYER +#undef TAIL_UPPER_LAYER +#undef TAIL_LOWER_LAYER #undef GLASSES_LAYER #undef BELT_LAYER_ALT #undef SUIT_STORE_LAYER @@ -1314,6 +1382,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() #undef LEGCUFF_LAYER #undef L_HAND_LAYER #undef R_HAND_LAYER +#undef VORE_BELLY_LAYER #undef MODIFIER_EFFECTS_LAYER #undef FIRE_LAYER #undef WATER_LAYER diff --git a/code/modules/mob/living/carbon/human/update_icons_ch.dm b/code/modules/mob/living/carbon/human/update_icons_ch.dm deleted file mode 100644 index 1062d52938..0000000000 --- a/code/modules/mob/living/carbon/human/update_icons_ch.dm +++ /dev/null @@ -1,39 +0,0 @@ -// Expand shoe layer to allow changing the icon for digi legs -// For some reason, suit and uniform already has this funcitonality, but shoes do not. - -#define SHOES_LAYER_ALT 8 //Shoe-slot item (when set to be under uniform via verb) -#define SHOES_LAYER 11 //Shoe-slot item - -/mob/living/carbon/human/update_inv_shoes() - //. = ..() - remove_layer(SHOES_LAYER) - remove_layer(SHOES_LAYER_ALT) //Dumb alternate layer for shoes being under the uniform. - - if(!shoes || (wear_suit && wear_suit.flags_inv & HIDESHOES) || (w_uniform && w_uniform.flags_inv & HIDESHOES)) - return //Either nothing to draw, or it'd be hidden. - - for(var/f in list(BP_L_FOOT, BP_R_FOOT)) - var/obj/item/organ/external/foot/foot = get_organ(f) - if(istype(foot) && foot.is_hidden_by_tail()) //If either foot is hidden by the tail, don't render footwear. - return - - var/obj/item/clothing/shoes/shoe = shoes - var/shoe_sprite - - if(istype(shoe) && !isnull(shoe.update_icon_define)) - shoe_sprite = shoe.update_icon_define - else - shoe_sprite = INV_FEET_DEF_ICON - - //Allow for shoe layer toggle nonsense - var/shoe_layer = SHOES_LAYER - if(istype(shoes, /obj/item/clothing/shoes)) - var/obj/item/clothing/shoes/ushoes = shoes - if(ushoes.shoes_under_pants == 1) - shoe_layer = SHOES_LAYER_ALT - - //NB: the use of a var for the layer on this one - overlays_standing[shoe_layer] = shoes.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_shoes_str, default_icon = shoe_sprite, default_layer = shoe_layer) - - apply_layer(SHOES_LAYER) - apply_layer(SHOES_LAYER_ALT) diff --git a/code/modules/mob/living/carbon/lick_wounds.dm b/code/modules/mob/living/carbon/lick_wounds.dm index 277a13efe2..8ec651d05b 100644 --- a/code/modules/mob/living/carbon/lick_wounds.dm +++ b/code/modules/mob/living/carbon/lick_wounds.dm @@ -1,8 +1,12 @@ -/mob/living/carbon/human/proc/lick_wounds(var/mob/living/carbon/M as mob in range(1)) // Allows the user to lick themselves. Given how rarely this trait is used, I don't see an issue with a slight buff. +/mob/living/carbon/human/proc/lick_wounds(var/mob/living/carbon/M as mob in view(1)) // Allows the user to lick themselves. Given how rarely this trait is used, I don't see an issue with a slight buff. set name = "Lick Wounds" set category = "Abilities" set desc = "Disinfect and heal small wounds with your saliva." + if(stat || paralysis || weakened || stunned) + to_chat(src, "You can't do that in your current state.") + return + if(nutrition < 50) to_chat(src, "You need more energy to produce antiseptic enzymes. Eat something and try again.") return @@ -57,7 +61,7 @@ if(affecting.brute_dam > 20 || affecting.burn_dam > 20) to_chat(src, "The wounds on [M]'s [affecting.name] are too severe to treat with just licking.") return - + else visible_message("\The [src] starts licking the wounds on [M]'s [affecting.name] clean.", \ "You start licking the wounds on [M]'s [affecting.name] clean." ) @@ -73,7 +77,7 @@ if(affecting.is_bandaged() && affecting.is_salved()) // We do a second check after the delay, in case it was bandaged after the first check. to_chat(src, "The wounds on [M]'s [affecting.name] have already been treated.") - return + return else visible_message("\The [src] [pick("slathers \a [W.desc] on [M]'s [affecting.name] with their spit.", diff --git a/code/modules/mob/living/carbon/taste.dm b/code/modules/mob/living/carbon/taste.dm index f02e704721..150f67d955 100644 --- a/code/modules/mob/living/carbon/taste.dm +++ b/code/modules/mob/living/carbon/taste.dm @@ -11,6 +11,9 @@ from.trans_to_holder(temp, amount, multiplier, 1) var/text_output = temp.generate_taste_message(src) + if(accumulated_rads >= 100) //If you're irradiated, you can't taste! + text_output = "nothing" + if(text_output != last_taste_text || last_taste_time + 100 < world.time) //We dont want to spam the same message over and over again at the person. Give it a bit of a buffer. to_chat(src, "You can taste [text_output].")//no taste means there are too many tastes and not enough flavor. diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 4eaab77926..a865a6b05d 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -13,6 +13,53 @@ to_world_log("## DEBUG: apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked].") if(!damage || (blocked >= 100)) return 0 + for(var/datum/modifier/M in modifiers) //MODIFIER STUFF. It's best to do this RIGHT before armor is calculated, so it's done here! This is the 'forcefield' defence. + if(damagetype == BRUTE && (!isnull(M.effective_brute_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_brute_resistance + continue + if((damagetype == BURN || damagetype == ELECTROCUTE)&& (!isnull(M.effective_fire_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_fire_resistance + continue + if(damagetype == TOX && (!isnull(M.effective_tox_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_tox_resistance + continue + if(damagetype == OXY && (!isnull(M.effective_oxy_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_oxy_resistance + continue + if(damagetype == CLONE && (!isnull(M.effective_clone_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_clone_resistance + continue + if(damagetype == HALLOSS && (!isnull(M.effective_hal_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_hal_resistance + continue + if(damagetype == SEARING && (!isnull(M.effective_fire_resistance) || !isnull(M.effective_brute_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + var/damage_mitigation = 0//Used for dual calculations. + if(!isnull(M.effective_fire_resistance)) + damage_mitigation += round((1/3)*damage * M.effective_fire_resistance) + if(!isnull(M.effective_brute_resistance)) + damage_mitigation += round((2/3)*damage * M.effective_brute_resistance) + damage -= damage_mitigation + continue + if(damagetype == BIOACID && (isSynthetic() && (!isnull(M.effective_fire_resistance))) || (!isSynthetic() && M.effective_tox_resistance)) + if(isSynthetic()) + damage = damage * M.effective_fire_resistance + else + damage = damage * M.effective_tox_resistance + continue if(soaked) if(soaked >= round(damage*0.8)) damage -= round(damage*0.8) @@ -55,6 +102,7 @@ /mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/halloss = 0, var/def_zone = null, var/blocked = 0) if(blocked >= 100) return 0 + // INSERT MODIFIER CODE HERE... But no, really, only two things in the game use it, quad and viruses. The former is admin-only and the latter wouldn't be affected logically, but would if shield code was inerted here. If you really want, you can copy&paste the above and modify it to adjust brute/burn/etc. I do not advise this however. if(brute) apply_damage(brute, BRUTE, def_zone, blocked) if(burn) apply_damage(burn, BURN, def_zone, blocked) if(tox) apply_damage(tox, TOX, def_zone, blocked) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 6356bfb7b3..eb7462967e 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -238,6 +238,9 @@ return /mob/living/proc/handle_light() + if(glow_override) + return FALSE + if(instability >= TECHNOMANCER_INSTABILITY_MIN_GLOW) var/distance = round(sqrt(instability / 2)) if(distance) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index e0f7d9a14b..0364fd8237 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -192,8 +192,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_brute_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -219,8 +223,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_oxy_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_oxy_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -243,8 +251,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_tox_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_tox_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -273,8 +285,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_fire_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -298,8 +314,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_clone_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_clone_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -331,6 +351,9 @@ if(status_flags & GODMODE) return 0 //godmode if(amount > 0) for(var/datum/modifier/M in modifiers) + if(M.energy_based && (!isnull(M.incoming_hal_damage_percent) || !isnull(M.disable_duration_percent))) + M.energy_source.use(M.damage_cost*amount) // Cost of the Damage absorbed. + M.energy_source.use(M.energy_cost) // Cost of the Effect absorbed. if(!isnull(M.incoming_damage_percent)) amount *= M.incoming_damage_percent if(!isnull(M.incoming_hal_damage_percent)) @@ -607,12 +630,18 @@ SetStunned(0) SetWeakened(0) + // undo various death related conveniences + sight = initial(sight) + see_in_dark = initial(see_in_dark) + see_invisible = initial(see_invisible) + // shut down ongoing problems radiation = 0 nutrition = 400 bodytemperature = T20C sdisabilities = 0 disabilities = 0 + resting = FALSE // fix blindness and deafness blinded = 0 @@ -1088,6 +1117,7 @@ src.inertia_dir = get_dir(target, src) step(src, inertia_dir) item.throw_at(target, throw_range, item.throw_speed, src) + item.throwing = 1 //Small edit so thrown interactions actually work! return TRUE else return FALSE diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index e695ce96bd..6835b9496b 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -324,6 +324,41 @@ src.anchored = TRUE src.pinned += O + //VORESTATION EDIT START - Allows for thrown vore! + //Throwing a prey into a pred takes priority. After that it checks to see if the person being thrown is a pred. + if(istype(AM, /mob/living)) + var/mob/living/thrown_mob = AM + + if(!allowmobvore && isanimal(thrown_mob)) //Does the person being hit not allow mob vore and the perrson being thrown a simple_mob? + return + if(!thrown_mob.allowmobvore && isanimal(src)) //Does the person being thrown not allow mob vore and is the person being hit (us) a simple_mob? + return + + // PERSON BEING HIT: CAN BE DROP PRED, ALLOWS THROW VORE. + // PERSON BEING THROWN: DEVOURABLE, ALLOWS THROW VORE, CAN BE DROP PREY. + if((can_be_drop_pred && throw_vore) && (thrown_mob.devourable && thrown_mob.throw_vore && thrown_mob.can_be_drop_prey)) //Prey thrown into pred. + vore_selected.nom_mob(thrown_mob) //Eat them!!! + visible_message("[thrown_mob] is thrown right into [src]'s [lowertext(vore_selected.name)]!") + if(thrown_mob.loc != vore_selected) + thrown_mob.forceMove(vore_selected) //Double check. Should never happen but...Weirder things have happened! + on_throw_vore_special(TRUE, thrown_mob) + add_attack_logs(thrown_mob.thrower,src,"Devoured [thrown_mob.name] via throw vore.") + return //We can stop here. We don't need to calculate damage or anything else. They're eaten. + + // PERSON BEING HIT: CAN BE DROP PREY, ALLOWS THROW VORE, AND IS DEVOURABLE. + // PERSON BEING THROWN: CAN BE DROP PRED, ALLOWS THROW VORE. + else if((can_be_drop_prey && throw_vore && devourable) && (thrown_mob.can_be_drop_pred && thrown_mob.throw_vore)) //Pred thrown into prey. + visible_message("[src] suddenly slips inside of [thrown_mob]'s [lowertext(thrown_mob.vore_selected.name)] as [thrown_mob] flies into them!") + thrown_mob.vore_selected.nom_mob(src) //Eat them!!! + if(src.loc != thrown_mob.vore_selected) + src.forceMove(thrown_mob.vore_selected) //Double check. Should never happen but...Weirder things have happened! + add_attack_logs(thrown_mob.LAssailant,src,"Was Devoured by [thrown_mob.name] via throw vore.") + return + //VORESTATION EDIT END - Allows for thrown vore! + +/mob/living/proc/on_throw_vore_special(var/pred = TRUE, var/mob/living/target) + return + /mob/living/proc/embed(var/obj/O, var/def_zone=null) O.loc = src src.embedded += O diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index c5e7a857b8..031d6ddb89 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -55,7 +55,8 @@ var/image/dsoverlay = null //Overlay used for darksight eye adjustments - var/glow_toggle = 0 // If they're glowing! + var/glow_toggle = FALSE // If they're glowing! + var/glow_override = FALSE // Ignore the manual toggle var/glow_range = 2 var/glow_intensity = null var/glow_color = "#FFFFFF" // The color they're glowing! @@ -80,4 +81,4 @@ var/flying = 0 // Allows flight var/inventory_panel_type = /datum/inventory_panel var/datum/inventory_panel/inventory_panel - var/last_resist_time = 0 // world.time of the most recent resist that wasn't on cooldown. + var/last_resist_time = 0 // world.time of the most recent resist that wasn't on cooldown. diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm index d7abf3bcc1..e68d333cec 100644 --- a/code/modules/mob/living/login.dm +++ b/code/modules/mob/living/login.dm @@ -19,12 +19,14 @@ verbs |= /mob/living/proc/lick verbs |= /mob/living/proc/smell verbs |= /mob/living/proc/switch_scaling + verbs |= /mob/living/proc/mute_entry //CHOMPEdit + verbs |= /mob/living/proc/center_offset //CHOMPEdit if(!no_vore) verbs |= /mob/living/proc/vorebelly_printout if(!vorePanel) AddComponent(/datum/component/vore_panel) - + verbs += /mob/living/proc/vore_transfer_reagents //CHOMP If mob doesnt have bellies it cant use this verb for anything verbs += /mob/living/proc/vore_check_reagents //CHOMP If mob doesnt have bellies it cant use this verb for anything verbs += /mob/living/proc/vore_bellyrub //CHOMP If mob doesnt have bellies it probably won't be needing this anyway diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index ca5319313f..a2ce47c2be 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -161,7 +161,6 @@ var/list/ai_verbs_default = list( add_language(LANGUAGE_SIIK, 1) add_language(LANGUAGE_AKHANI, 1) add_language(LANGUAGE_SKRELLIAN, 1) - add_language(LANGUAGE_SKRELLIANFAR, 0) add_language(LANGUAGE_TRADEBAND, 1) add_language(LANGUAGE_GUTTER, 1) add_language(LANGUAGE_EAL, 1) diff --git a/code/modules/mob/living/silicon/emote.dm b/code/modules/mob/living/silicon/emote.dm index a471c62b22..5bb86dac68 100644 --- a/code/modules/mob/living/silicon/emote.dm +++ b/code/modules/mob/living/silicon/emote.dm @@ -13,11 +13,11 @@ var/list/_silicon_default_emotes = list( ) /mob/living/silicon/get_available_emotes() - return global._silicon_default_emotes + return global._silicon_default_emotes.Copy() /mob/living/silicon/pai/get_available_emotes() - var/list/fulllist = _silicon_default_emotes + var/list/fulllist = global._silicon_default_emotes.Copy() fulllist |= _robot_default_emotes fulllist |= _human_default_emotes return fulllist \ No newline at end of file diff --git a/code/modules/mob/living/silicon/pai/pai_vr.dm b/code/modules/mob/living/silicon/pai/pai_vr.dm index 86ef6cca5a..662ff89642 100644 --- a/code/modules/mob/living/silicon/pai/pai_vr.dm +++ b/code/modules/mob/living/silicon/pai/pai_vr.dm @@ -1,5 +1,5 @@ /mob/living/silicon/pai - var/people_eaten = 0 + //var/people_eaten = 0 //CHOMPEdit - no longer needed. icon = 'icons/mob/pai_vr.dmi' softfall = TRUE var/eye_glow = TRUE @@ -57,6 +57,11 @@ var/soft_si = FALSE //signaler var/soft_ar = FALSE //ar hud + //CHOMPEdit Begin - Add vore capacity + vore_capacity = 1 + vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End + /mob/living/silicon/pai/Initialize() . = ..() @@ -97,12 +102,14 @@ return return feed_grabbed_to_self(src,T) +/*CHOMPEdit - Just using the update_fullness from living now. /mob/living/silicon/pai/proc/update_fullness_pai() //Determines if they have something in their stomach. Copied and slightly modified. var/new_people_eaten = 0 for(var/obj/belly/B as anything in vore_organs) for(var/mob/living/M in B) new_people_eaten += M.size_multiplier people_eaten = min(1, new_people_eaten) +*/ /mob/living/silicon/pai/update_icon() //Some functions cause this to occur, such as resting ..() @@ -111,22 +118,28 @@ add_eyes() return - update_fullness_pai() + update_fullness() //CHOMPEdit - Switch to /living update_fullness + //CHOMPEdit begin - Add multiple belly size support + //Add a check when selecting a chassis if you add in support for this, to set vore_capacity to 2 or however many states you have. + var/fullness_extension = "" + if(vore_capacity > 1 && vore_fullness > 1) + fullness_extension = "_[vore_fullness]" + //CHOMPEdit end - if(!people_eaten && !resting) + if(!vore_fullness && !resting) //CHOMPEdit - Use vore_fullness instead of people_eaten icon_state = "[chassis]" //Using icon_state here resulted in quite a few bugs. Chassis is much less buggy. - else if(!people_eaten && resting) + else if(!vore_fullness && resting) //CHOMPEdit - Use vore_fullness instead of people_eaten icon_state = "[chassis]_rest" // Unfortunately not all these states exist, ugh. - else if(people_eaten && !resting) - if("[chassis]_full" in cached_icon_states(icon)) - icon_state = "[chassis]_full" + else if(vore_fullness && !resting) //CHOMPEdit - Use vore_fullness instead of people_eaten + if("[chassis]_full[fullness_extension]" in cached_icon_states(icon)) //CHOMPEdit begin - Add multiple belly size support + icon_state = "[chassis]_full[fullness_extension]" //CHOMPEdit - Add multiple belly size support else icon_state = "[chassis]" - else if(people_eaten && resting) - if("[chassis]_rest_full" in cached_icon_states(icon)) - icon_state = "[chassis]_rest_full" + else if(vore_fullness && resting) //CHOMPEdit - Use vore_fullness instead of people_eaten + if("[chassis]_rest_full[fullness_extension]" in cached_icon_states(icon)) //CHOMPEdit begin - Add multiple belly size support + icon_state = "[chassis]_rest_full[fullness_extension]" //CHOMPEdit begin - Add multiple belly size support else icon_state = "[chassis]_rest" if(chassis in wide_chassis) @@ -143,15 +156,21 @@ icon = holo_icon add_eyes() return - update_fullness_pai() - if(!people_eaten && !resting) + update_fullness() + //CHOMPEdit begin - Add multiple belly size support + //Add a check when selecting a chassis if you add in support for this, to set vore_capacity to 2 or however many states you have. + var/fullness_extension = "" + if(vore_capacity > 1 && vore_fullness > 1) + fullness_extension = "_[vore_fullness]" + //CHOMPEdit end + if(!vore_fullness && !resting) //CHOMPEdit - Use vore_fullness instead of people_eaten icon_state = "[chassis]" - else if(!people_eaten && resting) + else if(!vore_fullness && resting) //CHOMPEdit - Use vore_fullness instead of people_eaten icon_state = "[chassis]_rest" - else if(people_eaten && !resting) - icon_state = "[chassis]_full" - else if(people_eaten && resting) - icon_state = "[chassis]_rest_full" + else if(vore_fullness && !resting) //CHOMPEdit - Use vore_fullness instead of people_eaten + icon_state = "[chassis]_full[fullness_extension]" //CHOMPEdit begin - Add multiple belly size support + else if(vore_fullness && resting) //CHOMPEdit - Use vore_fullness instead of people_eaten + icon_state = "[chassis]_rest_full[fullness_extension]" //CHOMPEdit begin - Add multiple belly size support if(chassis in wide_chassis) pixel_x = -16 default_pixel_x = -16 @@ -171,6 +190,19 @@ var/oursize = size_multiplier resize(1, FALSE, TRUE, TRUE, FALSE) //We resize ourselves to normal here for a moment to let the vis_height get reset chassis = possible_chassis[choice] + + //CHOMPEdit Begin - Reset vore_capacity to allow multiple belly sizes as an option + vore_capacity = 1 + vore_capacity_ex = list("stomach" = 1) + //As an example of how you would add support for multiple belly sizes... + /* + if(chassis == "example") + vore_capacity = 2 + vore_capacity_ex = list("stomach" = 2) + */ + //Vore sprites would need to be added with sizes being example, example_full, example_full_2, example_full_3, and so forth + //CHOMPEdit End + if(chassis == "13") if(!holo_icon) if(!get_character_icon()) diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index 53fa801dd6..ea182ad224 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -404,7 +404,7 @@ user.add_language(LANGUAGE_ZADDAT) user.add_language(LANGUAGE_SCHECHI) user.add_language(LANGUAGE_DRUDAKAR) - user.add_language(LANGUAGE_SLAVIC) + user.add_language(LANGUAGE_SLAVIC) //CHOMP reAdd user.add_language(LANGUAGE_BIRDSONG) user.add_language(LANGUAGE_SAGARU) user.add_language(LANGUAGE_CANILUNZT) @@ -413,24 +413,16 @@ user.add_language(LANGUAGE_ENOCHIAN) user.add_language(LANGUAGE_VESPINAE) user.add_language(LANGUAGE_SPACER) - user.add_language(LANGUAGE_CLOWNISH) user.add_language(LANGUAGE_TAVAN) user.add_language(LANGUAGE_ECHOSONG) - user.add_language(LANGUAGE_CHIMPANZEE) - user.add_language(LANGUAGE_NEAERA) - user.add_language(LANGUAGE_STOK) - user.add_language(LANGUAGE_FARWA) user.add_language(LANGUAGE_ROOTLOCAL) user.add_language(LANGUAGE_VOX) - user.add_language(LANGUAGE_SKRELLIANFAR) user.add_language(LANGUAGE_MINBUS) user.add_language(LANGUAGE_ALAI) user.add_language(LANGUAGE_PROMETHEAN) user.add_language(LANGUAGE_GIBBERISH) user.add_language("Mouse") - user.add_language("Cat") - user.add_language("Bird") - user.add_language("Dog") + user.add_language("Animal") user.add_language("Teppi") else user.remove_language(LANGUAGE_UNATHI) @@ -440,7 +432,7 @@ user.remove_language(LANGUAGE_ZADDAT) user.remove_language(LANGUAGE_SCHECHI) user.remove_language(LANGUAGE_DRUDAKAR) - user.remove_language(LANGUAGE_SLAVIC) + user.remove_language(LANGUAGE_SLAVIC) //CHOMP reAdd user.remove_language(LANGUAGE_BIRDSONG) user.remove_language(LANGUAGE_SAGARU) user.remove_language(LANGUAGE_CANILUNZT) @@ -449,24 +441,16 @@ user.remove_language(LANGUAGE_ENOCHIAN) user.remove_language(LANGUAGE_VESPINAE) user.remove_language(LANGUAGE_SPACER) - user.remove_language(LANGUAGE_CLOWNISH) user.remove_language(LANGUAGE_TAVAN) user.remove_language(LANGUAGE_ECHOSONG) - user.remove_language(LANGUAGE_CHIMPANZEE) - user.remove_language(LANGUAGE_NEAERA) - user.remove_language(LANGUAGE_STOK) - user.remove_language(LANGUAGE_FARWA) user.remove_language(LANGUAGE_ROOTLOCAL) user.remove_language(LANGUAGE_VOX) - user.remove_language(LANGUAGE_SKRELLIANFAR) user.remove_language(LANGUAGE_MINBUS) user.remove_language(LANGUAGE_ALAI) user.remove_language(LANGUAGE_PROMETHEAN) user.remove_language(LANGUAGE_GIBBERISH) user.remove_language("Mouse") - user.remove_language("Cat") - user.remove_language("Bird") - user.remove_language("Dog") + user.remove_language("Animal") user.remove_language("Teppi") /datum/pai_software/translator/is_active(mob/living/silicon/pai/user) diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm index e6315d944f..f6f37fa210 100644 --- a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm +++ b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm @@ -66,12 +66,12 @@ var/agony = 60 // Copied from stun batons var/stun = 0 // ... same - + var/obj/item/organ/external/affecting = null if(ishuman(target)) var/mob/living/carbon/human/H = target affecting = H.get_organ(hit_zone) - + if(user.a_intent == I_HURT) // Parent handles messages . = ..() @@ -91,7 +91,7 @@ var/mob/living/silicon/robot/R = loc if(R.cell?.use(charge_cost) == charge_cost) stunning = TRUE - + if(stunning) target.stun_effect_act(stun, agony, hit_zone, src) msg_admin_attack("[key_name(user)] stunned [key_name(target)] with the [src].") @@ -216,6 +216,11 @@ desc = "An advanced chemical synthesizer and injection system utilizing carrier's reserves." reagent_ids = list("tricordrazine", "inaprovaline", "bicaridine", "dexalin", "anti_toxin", "tramadol", "spaceacillin") +/obj/item/weapon/reagent_containers/borghypo/hound/trauma + name = "Hound hypospray" + desc = "An advanced chemical synthesizer and injection system utilizing carrier's reserves." + reagent_ids = list("tricordrazine", "inaprovaline", "oxycodone", "dexalin" ,"spaceacillin") + //Tongue stuff /obj/item/device/dogborg/tongue @@ -404,24 +409,33 @@ var/datum/matter_synth/glass = null /obj/item/device/lightreplacer/dogborg/attack_self(mob/user)//Recharger refill is so last season. Now we recycle without magic! - if(uses >= max_uses) - to_chat(user, "[src.name] is full.") + + var/choice = tgui_alert(user, "Do you wish to check the reserves or change the color?", "Selection List", list("Reserves", "Color")) + if(choice == "Color") + var/new_color = input(usr, "Choose a color to set the light to! (Default is [LIGHT_COLOR_INCANDESCENT_TUBE])", "", selected_color) as color|null + if(new_color) + selected_color = new_color + to_chat(user, "The light color has been changed.") return - if(uses < max_uses && cooldown == 0) - if(glass.energy < 125) - to_chat(user, "Insufficient material reserves.") - return - to_chat(user, "It has [uses] lights remaining. Attempting to fabricate a replacement. Please stand still.") - cooldown = 1 - if(do_after(user, 50)) - glass.use_charge(125) - add_uses(1) - cooldown = 0 - else - cooldown = 0 else - to_chat(user, "It has [uses] lights remaining.") - return + if(uses >= max_uses) + to_chat(user, "[src.name] is full.") + return + if(uses < max_uses && cooldown == 0) + if(glass.energy < 125) + to_chat(user, "Insufficient material reserves.") + return + to_chat(user, "It has [uses] lights remaining. Attempting to fabricate a replacement. Please stand still.") + cooldown = 1 + if(do_after(user, 50)) + glass.use_charge(125) + add_uses(1) + cooldown = 0 + else + cooldown = 0 + else + to_chat(user, "It has [uses] lights remaining.") + return //Pounce stuff for K-9 /obj/item/weapon/dogborg/pounce diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm index 54fca8d569..26ab8389a4 100644 --- a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm +++ b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm @@ -42,11 +42,13 @@ var/digest_multiplier = 1 var/recycles = FALSE var/medsensor = TRUE //Does belly sprite come with patient ok/dead light? + var/obj/item/device/healthanalyzer/med_analyzer = null /obj/item/device/dogborg/sleeper/New() ..() flags |= NOBLUDGEON //No more attack messages files = new /datum/research/techonly(src) + med_analyzer = new /obj/item/device/healthanalyzer /obj/item/device/dogborg/sleeper/Destroy() go_out() @@ -128,7 +130,7 @@ trashman.reset_view(src) START_PROCESSING(SSobj, src) user.visible_message("[hound.name]'s [src.name] groans lightly as [trashman] slips inside.", "Your [src.name] groans lightly as [trashman] slips inside.") - message_admins("[key_name(hound)] has eaten [key_name(patient)] as a dogborg. ([hound ? "JMP" : "null"])") + log_attack("[key_name(hound)] has eaten [key_name(patient)] as a dogborg. ([hound ? "JMP" : "null"])")//CHOMPEdit from message_admins playsound(src, gulpsound, vol = 100, vary = 1, falloff = 0.1, preference = /datum/client_preference/eating_noises) if(delivery) if(islist(deliverylists[delivery_tag])) @@ -216,6 +218,8 @@ dat += "Eject port: [eject_port]" if(!cleaning) dat += "Self-Clean" + if(medsensor) + dat += "Analyze Patient" else dat += "Self-Clean" if(delivery) @@ -336,6 +340,8 @@ if(cleaning) sleeperUI(usr) return + if(href_list["analyze"]) //DO HEALTH ANALYZER STUFF HERE. + med_analyzer.scan_mob(patient,hound) if(href_list["port"]) switch(eject_port) if("ingestion") @@ -548,7 +554,8 @@ var/actual_burn = T.getFireLoss() - old_burn var/damage_gain = actual_brute + actual_burn drain(-25 * damage_gain) //25*total loss as with voreorgan stats. - water.add_charge(damage_gain) + if(water) + water.add_charge(damage_gain) if(T.stat == DEAD) if(ishuman(T)) message_admins("[key_name(hound)] has digested [key_name(T)] as a dogborg. ([hound ? "JMP" : "null"])") @@ -585,13 +592,18 @@ if(ishuman(T)) var/mob/living/carbon/human/Prey = T volume = (Prey.bloodstr.total_volume + Prey.ingested.total_volume + Prey.touching.total_volume + Prey.weight) * Prey.size_multiplier - water.add_charge(volume) + if(water) + water.add_charge(volume) if(T.reagents) volume = T.reagents.total_volume - water.add_charge(volume) + if(water) + water.add_charge(volume) + if(T.ckey) + GLOB.prey_digested_roundstat++ if(patient == T) patient_laststat = null patient = null + T.mind?.vore_death = TRUE qdel(T) //Pick a random item to deal with (if there are any) @@ -612,7 +624,7 @@ for(var/tech in tech_item.origin_tech) files.UpdateTech(tech, tech_item.origin_tech[tech]) synced = FALSE - if(volume) + if(volume && water) water.add_charge(volume) if(recycles && T.matter) for(var/material in T.matter) @@ -620,14 +632,14 @@ if(istype(T,/obj/item/stack)) var/obj/item/stack/stack = T total_material *= stack.get_amount() - if(material == MAT_STEEL) + if(material == MAT_STEEL && metal) metal.add_charge(total_material) - if(material == "glass") + if(material == "glass" && glass) glass.add_charge(total_material) if(decompiler) - if(material == "plastic") + if(material == "plastic" && plastic) plastic.add_charge(total_material) - if(material == "wood") + if(material == "wood" && wood) wood.add_charge(total_material) drain(-50 * digested) else if(istype(target,/obj/effect/decal/remains)) @@ -757,4 +769,11 @@ icon_state = "sleeperert" injection_chems = list("inaprovaline", "paracetamol") // short list +/obj/item/device/dogborg/sleeper/compactor/trauma //Trauma borg belly + name = "Recovery Belly" + desc = "A downgraded model of the medihound sleeper." + icon_state = "sleeper" + injection_chems = list("inaprovaline", "dexalin", "bicaridine", "anti_toxin", "spaceacillin", "paracetamol") + max_item_count = 1 + #undef SLEEPER_INJECT_COST diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm index 71b84648d5..862993b884 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm @@ -100,7 +100,9 @@ /obj/item/weapon/reagent_containers/pill, /obj/item/weapon/reagent_containers/blood, /obj/item/device/nif, //Chompedit Add Nif handling - /obj/item/stack/material/phoron + /obj/item/stack/material/phoron, + /obj/item/weapon/tank/anesthetic, + /obj/item/weapon/disk/body_record //Vorestation Edit: this lets you get an empty sleeve or help someone else ) /obj/item/weapon/gripper/research //A general usage gripper, used for toxins/robotics/xenobio/etc @@ -180,7 +182,8 @@ desc = "A specialized grasping tool used to preserve and manipulate organic material." can_hold = list( - /obj/item/organ + /obj/item/organ, + /obj/item/device/nif //NIFs can be slapped in during surgery ) /obj/item/weapon/gripper/no_use/organ/Entered(var/atom/movable/AM) @@ -208,7 +211,8 @@ /obj/item/organ/external, /obj/item/organ/internal/brain, //to insert into MMIs, /obj/item/organ/internal/cell, - /obj/item/organ/internal/eyes/robot + /obj/item/organ/internal/eyes/robot, + /obj/item/device/nif //NIFs can be slapped in during surgery ) /obj/item/weapon/gripper/no_use/mech diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index 9def436c7c..018c2b4336 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -33,4 +33,4 @@ var/list/_robot_default_emotes = list( ) /mob/living/silicon/robot/get_available_emotes() - return global._robot_default_emotes + return global._robot_default_emotes.Copy() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index eabc175c0f..b5d4eed0cc 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1074,6 +1074,23 @@ choose_icon(icon_selection_tries, module_sprites) return + //CHOMPEdit Begin - Allow multiple sizes of vore sprites and/or resting vore sprites + if(dogborg && (icontype == "Cat" || icontype == "Cat Mining" || icontype == "Cat Cargo")) + sleeper_resting = TRUE + else + sleeper_resting = FALSE + //And then for multiple belly sizes... + if(dogborg && (icontype == "example")) + vore_capacity = 2 + vore_capacity_ex["stomach"] = 2 + else if(dogborg) + vore_capacity = 1 + vore_capacity_ex["stomach"] = 1 + else + vore_capacity = 0 + vore_capacity_ex["stomach"] = 0 + //CHOMPEdit End + icon_selected = 1 icon_selection_tries = 0 to_chat(src, "Your icon has been set. You now require a module reset to change it.") diff --git a/code/modules/mob/living/silicon/robot/robot_modules/event_vr.dm b/code/modules/mob/living/silicon/robot/robot_modules/event_vr.dm index a61c1847b4..eb553ec3a3 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/event_vr.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/event_vr.dm @@ -53,7 +53,11 @@ R.pixel_x = -16 R.old_x = -16 R.default_pixel_x = -16 - R.dogborg = TRUE + R.dogborg = TRUE + //CHOMPEdit - Add vore capacity + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill R.verbs |= /mob/living/silicon/robot/proc/robot_mount diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm index e676c871c4..35474383a1 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm @@ -182,6 +182,7 @@ var/global/list/robot_modules = list( src.modules += new /obj/item/weapon/tool/crowbar/cyborg(src) src.modules += new /obj/item/weapon/extinguisher(src) src.modules += new /obj/item/device/gps/robot(src) + src.modules += new /obj/item/weapon/gripper/scene(src) //CHOMPEdit - Give all borgs a scene gripper vr_new() // Vorestation Edit: For modules in robot_modules_vr.dm /obj/item/weapon/robot_module/robot/standard @@ -262,6 +263,7 @@ var/global/list/robot_modules = list( src.modules += new /obj/item/weapon/surgical/bonesetter/cyborg(src) src.modules += new /obj/item/weapon/surgical/circular_saw/cyborg(src) src.modules += new /obj/item/weapon/surgical/surgicaldrill/cyborg(src) + src.modules += new /obj/item/weapon/surgical/bioregen/cyborg(src) //VoreStation Edit: LET ME SUCC src.modules += new /obj/item/weapon/gripper/no_use/organ(src) src.modules += new /obj/item/weapon/gripper/medical(src) src.modules += new /obj/item/weapon/shockpaddles/robot(src) @@ -278,14 +280,19 @@ var/global/list/robot_modules = list( var/obj/item/stack/nanopaste/N = new /obj/item/stack/nanopaste(src) var/obj/item/stack/medical/advanced/bruise_pack/B = new /obj/item/stack/medical/advanced/bruise_pack(src) + var/obj/item/stack/medical/advanced/ointment/O = new /obj/item/stack/medical/advanced/ointment(src) //VoreStation edit: we have burn surgeries so they should be able to do them N.uses_charge = 1 N.charge_costs = list(1000) N.synths = list(medicine) B.uses_charge = 1 B.charge_costs = list(1000) B.synths = list(medicine) + O.uses_charge = 1 + O.charge_costs = list(1000) + O.synths = list(medicine) src.modules += N src.modules += B + src.modules += O /obj/item/weapon/robot_module/robot/medical/surgeon/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) @@ -538,6 +545,7 @@ var/global/list/robot_modules = list( src.modules += new /obj/item/taperoll/police(src) src.modules += new /obj/item/weapon/reagent_containers/spray/pepper(src) src.modules += new /obj/item/weapon/gripper/security(src) + src.modules += new /obj/item/device/ticket_printer(src) //VOREStation Add src.emag = new /obj/item/weapon/gun/energy/laser/mounted(src) /obj/item/weapon/robot_module/robot/security/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) @@ -607,7 +615,6 @@ var/global/list/robot_modules = list( LANGUAGE_SIIK = 1, LANGUAGE_AKHANI = 1, LANGUAGE_SKRELLIAN = 1, - LANGUAGE_SKRELLIANFAR = 0, LANGUAGE_ROOTLOCAL = 0, LANGUAGE_TRADEBAND = 1, LANGUAGE_GUTTER = 1, @@ -675,7 +682,8 @@ var/global/list/robot_modules = list( src.emag.reagents = R R.my_atom = src.emag R.add_reagent("beer2", 50) - src.emag.name = "Mickey Finn's Special Brew" + src.emag.name = "Auntie Hong's Final Sip" + src.emag.desc = "A bottle of very special mix of alcohol and poison. Some may argue that there's alcohol to die for, but Auntie Hong took it to next level." /obj/item/weapon/robot_module/robot/clerical/general name = "clerical robot module" @@ -856,6 +864,7 @@ var/global/list/robot_modules = list( src.modules += new /obj/item/weapon/pickaxe/plasmacutter/borg(src) src.modules += new /obj/item/borg/combat/shield(src) src.modules += new /obj/item/borg/combat/mobility(src) + src.modules += new /obj/item/device/ticket_printer(src) //VOREStation Add src.emag = new /obj/item/weapon/gun/energy/lasercannon/mounted(src) diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station_ch.dm b/code/modules/mob/living/silicon/robot/robot_modules/station_ch.dm index 36cbca3565..e90b557d20 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station_ch.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station_ch.dm @@ -85,6 +85,8 @@ R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill R.verbs |= /mob/living/silicon/robot/proc/robot_mount diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm b/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm index 327743f4cf..0af7b1a8b9 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm @@ -75,6 +75,7 @@ robot_modules["UnityHound"] = /obj/item/weapon/robot_module/robot/chound //CHOMP Addition Unity robot_modules["Honk-Hound"] = /obj/item/weapon/robot_module/robot/clerical/honkborg //CHOMP Addition Honk robot_modules["Stray"] = /obj/item/weapon/robot_module/robot/stray + robot_modules["TraumaHound"] = /obj/item/weapon/robot_module/robot/medical/trauma return 1 //Just add a new proc with the robot_module type if you wish to run some other vore code @@ -99,6 +100,7 @@ "Acheron" = "mechoid-Medical", "Shellguard Noble" = "Noble-MED", "ZOOM-BA" = "zoomba-medical", + "W02M" = "worm-surgeon", "Feminine Humanoid" = "uptall-medical" ) @@ -109,6 +111,7 @@ "Acheron" = "mechoid-Medical", "Shellguard Noble" = "Noble-MED", "ZOOM-BA" = "zoomba-crisis", + "W02M" = "worm-crisis", "Feminine Humanoid" = "uptall-crisis" ) @@ -120,6 +123,7 @@ "Acheron" = "mechoid-Service", "Shellguard Noble" = "Noble-SRV", "ZOOM-BA" = "zoomba-service", + "W02M" = "worm-service", "Feminine Humanoid" = "uptall-service" ) @@ -130,6 +134,7 @@ "Acheron" = "mechoid-Service", "Shellguard Noble" = "Noble-SRV", "ZOOM-BA" = "zoomba-clerical", + "W02M" = "worm-service", "Feminine Humanoid" = "uptall-service" ) @@ -140,6 +145,7 @@ "Acheron" = "mechoid-Janitor", "Shellguard Noble" = "Noble-CLN", "ZOOM-BA" = "zoomba-janitor", + "W02M" = "worm-janitor", "Feminine Humanoid" = "uptall-janitor" ) @@ -150,6 +156,7 @@ "Acheron" = "mechoid-Security", "Shellguard Noble" = "Noble-SEC", "ZOOM-BA" = "zoomba-security", + "W02M" = "worm-security", "Feminine Humanoid" = "uptall-security" ) @@ -160,6 +167,7 @@ "Acheron" = "mechoid-Miner", "Shellguard Noble" = "Noble-DIG", "ZOOM-BA" = "zoomba-miner", + "W02M" = "worm-miner", "Feminine Humanoid" = "uptall-miner" ) @@ -170,6 +178,7 @@ "Acheron" = "mechoid-Standard", "Shellguard Noble" = "Noble-STD", "ZOOM-BA" = "zoomba-standard", + "W02M" = "worm-standard", "Feminine Humanoid" = "uptall-standard", "Feminine Humanoid, Variant 2" = "uptall-standard2" ) @@ -179,6 +188,7 @@ "Acheron" = "mechoid-Engineering", "Shellguard Noble" = "Noble-ENG", "ZOOM-BA" = "zoomba-engineering", + "W02M" = "worm-engineering", "Feminine Humanoid" = "uptall-engineering" ) @@ -188,6 +198,7 @@ "Acheron" = "mechoid-Science", "ZOOM-BA" = "zoomba-research", "XI-GUS" = "spiderscience", + "W02M" = "worm-janitor", "Feminine Humanoid" = "uptall-science" ) @@ -196,6 +207,7 @@ vr_sprites = list( "Acheron" = "mechoid-Combat", "ZOOM-BA" = "zoomba-combat", + "W02M" = "worm-combat", "Feminine Humanoid" = "uptall-security" ) @@ -209,7 +221,8 @@ "Otieborg" = "oties", "Secborg model V-3" = "SecVale", //CHOMPEdit "Cat" = "vixsec", //CHOMPEdit - "Drake" = "drakesec" + "Drake" = "drakesec", + "Secborg model V-4" = "secraptor"//CHOMPEdit ) channels = list("Security" = 1) networks = list(NETWORK_SECURITY) @@ -225,6 +238,7 @@ src.modules += new /obj/item/taperoll/police(src) //Block out crime scenes. src.modules += new /obj/item/weapon/gun/energy/taser/mounted/cyborg(src) //They /are/ a security borg, after all. src.modules += new /obj/item/weapon/dogborg/pounce(src) //Pounce + src.modules += new /obj/item/device/ticket_printer(src) src.emag = new /obj/item/weapon/gun/energy/laser/mounted(src) //Emag. Not a big problem. var/datum/matter_synth/water = new /datum/matter_synth(500) //Starts full and has a max of 500 @@ -249,6 +263,10 @@ R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + //CHOMPEdit - Add vore capacity + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill R.verbs |= /mob/living/silicon/robot/proc/robot_mount @@ -290,7 +308,8 @@ "Borgi" = "borgi-medi", "Mediborg model V-3" = "vale2", //CHOMPEdit "Cat" = "vixmed", //CHOMPEdit - "Drake" = "drakemed" + "Drake" = "drakemed", + "Mediborg model V-4" = "medraptor" //CHOMPEdit ) /obj/item/weapon/robot_module/robot/medihound/New(var/mob/living/silicon/robot/R) @@ -299,10 +318,12 @@ src.modules += new /obj/item/device/healthanalyzer(src) // See who's hurt specificially. src.modules += new /obj/item/borg/sight/hud/med(src) //See who's hurt generally. src.modules += new /obj/item/weapon/reagent_containers/syringe(src) //In case the chemist is nice! - src.modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src)//For holding the chemicals when the chemist is nice + src.modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src)//For holding the chemicals when the chemist is nice, made it the large variant in 2022 src.modules += new /obj/item/device/sleevemate(src) //Lets them scan people. src.modules += new /obj/item/weapon/shockpaddles/robot/hound(src) //Paws of life src.modules += new /obj/item/weapon/inflatable_dispenser/robot(src) //This is kinda important for rescuing people without making it worse for everyone + src.modules += new /obj/item/weapon/gripper/medical(src) //Let them do literally anything in medbay other than patch external damage and lick people + src.modules += new /obj/item/weapon/reagent_containers/dropper/industrial(src) //dropper is nice to have for so much actually src.emag = new /obj/item/weapon/dogborg/pounce(src) //Pounce src.modules += new /obj/item/weapon/gripper/medical(src)//Now you can set up cyro or make peri. //CHOMPEdit @@ -310,10 +331,15 @@ synths += medicine var/obj/item/stack/medical/advanced/clotting/C = new (src) + var/obj/item/stack/medical/splint/S = new /obj/item/stack/medical/splint(src) C.uses_charge = 1 - C.charge_costs = list(1000) + C.charge_costs = list(5000) C.synths = list(medicine) + S.uses_charge = 1 + S.charge_costs = list(1000) + S.synths = list(medicine) src.modules += C + src.modules += S var/datum/matter_synth/water = new /datum/matter_synth(500) water.name = "Water reserves" @@ -334,23 +360,18 @@ B.water = water src.modules += B + //CHOMPEdit Start - Give back the ATK/ABP since we don't have the surgeryhound var/obj/item/stack/medical/advanced/ointment/O = new /obj/item/stack/medical/advanced/ointment(src) var/obj/item/stack/medical/advanced/bruise_pack/P = new /obj/item/stack/medical/advanced/bruise_pack(src) - var/obj/item/stack/medical/splint/S = new /obj/item/stack/medical/splint(src) O.uses_charge = 1 O.charge_costs = list(1000) O.synths = list(medicine) P.uses_charge = 1 P.charge_costs = list(1000) P.synths = list(medicine) - S.uses_charge = 1 - S.charge_costs = list(1000) - S.synths = list(medicine) src.modules += O src.modules += P - src.modules += S - -// End YW Edit + //CHOMPEdit End R.icon = 'icons/mob/widerobot_vr.dmi' @@ -363,6 +384,98 @@ R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + //CHOMPEdit - Add vore capacity + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End + R.wideborg = TRUE + R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill + R.verbs |= /mob/living/silicon/robot/proc/robot_mount + R.verbs |= /mob/living/proc/toggle_rider_reins + R.verbs |= /mob/living/proc/shred_limb + R.verbs |= /mob/living/silicon/robot/proc/rest_style + ..() + +/obj/item/weapon/robot_module/robot/medical/trauma + name = "traumahound robot module" + channels = list("Medical" = 1) + networks = list(NETWORK_MEDICAL) + subsystems = list(/mob/living/silicon/proc/subsystem_crew_monitor) + pto_type = PTO_MEDICAL + can_be_pushed = 0 + sprites = list( + "Traumahound" = "traumavale", + "Drake" = "draketrauma", + "Borgi" = "borgi-trauma" + ) + +/obj/item/weapon/robot_module/robot/medical/trauma/New(var/mob/living/silicon/robot/R) + src.modules += new /obj/item/device/healthanalyzer(src) + src.modules += new /obj/item/weapon/dogborg/jaws/small(src) + src.modules += new /obj/item/device/dogborg/boop_module(src) + src.modules += new /obj/item/weapon/autopsy_scanner(src) + src.modules += new /obj/item/weapon/surgical/scalpel/cyborg(src) + src.modules += new /obj/item/weapon/surgical/hemostat/cyborg(src) + src.modules += new /obj/item/weapon/surgical/retractor/cyborg(src) + src.modules += new /obj/item/weapon/surgical/cautery/cyborg(src) + src.modules += new /obj/item/weapon/surgical/bonegel/cyborg(src) + src.modules += new /obj/item/weapon/surgical/FixOVein/cyborg(src) + src.modules += new /obj/item/weapon/surgical/bonesetter/cyborg(src) + src.modules += new /obj/item/weapon/surgical/circular_saw/cyborg(src) + src.modules += new /obj/item/weapon/surgical/surgicaldrill/cyborg(src) + src.modules += new /obj/item/weapon/surgical/bioregen/cyborg(src) //let them succ + src.modules += new /obj/item/weapon/gripper/no_use/organ(src) + src.modules += new /obj/item/weapon/gripper/medical(src) + src.modules += new /obj/item/weapon/shockpaddles/robot/hound(src) //Paws of life + src.modules += new /obj/item/weapon/reagent_containers/dropper(src) // Allows surgeon borg to fix necrosis + src.modules += new /obj/item/weapon/reagent_containers/syringe(src) + src.emag = new /obj/item/weapon/dogborg/pounce(src) //Pounce, also, lets not give them polyacid spray + + var/datum/matter_synth/water = new /datum/matter_synth(500) + water.name = "Water reserves" + water.recharge_rate = 0 + R.water_res = water + synths += water + + var/obj/item/device/dogborg/tongue/T = new /obj/item/device/dogborg/tongue(src) + T.water = water + src.modules += T + + var/obj/item/weapon/reagent_containers/borghypo/hound/trauma/H = new /obj/item/weapon/reagent_containers/borghypo/hound/trauma(src) //surgeon chems + H.water = water + src.modules += H + + var/obj/item/device/dogborg/sleeper/compactor/trauma/B = new /obj/item/device/dogborg/sleeper/compactor/trauma(src) //So they can nom people and heal them + B.water = water + src.modules += B + + var/datum/matter_synth/medicine = new /datum/matter_synth/medicine(10000) //this is so they can do brute/burn surgeries and fix assisted/prosthetic organs + synths += medicine + + var/obj/item/stack/nanopaste/N = new /obj/item/stack/nanopaste(src) + var/obj/item/stack/medical/advanced/bruise_pack/S = new /obj/item/stack/medical/advanced/bruise_pack(src) + var/obj/item/stack/medical/advanced/ointment/O = new /obj/item/stack/medical/advanced/ointment(src) + N.uses_charge = 1 + N.charge_costs = list(1000) + N.synths = list(medicine) + S.uses_charge = 1 + S.charge_costs = list(1000) + S.synths = list(medicine) + O.uses_charge = 1 + O.charge_costs = list(1000) + O.synths = list(medicine) + src.modules += N + src.modules += S + src.modules += O + + R.icon = 'icons/mob/widerobot_trauma_vr.dmi' + R.wideborg_dept = 'icons/mob/widerobot_trauma_vr.dmi' + R.hands.icon = 'icons/mob/screen1_robot_vr.dmi' + R.ui_style_vr = TRUE + R.pixel_x = -16 + R.old_x = -16 + R.default_pixel_x = -16 + R.dogborg = TRUE R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill R.verbs |= /mob/living/silicon/robot/proc/robot_mount @@ -415,6 +528,10 @@ R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + //CHOMPEdit - Add vore capacity + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill R.verbs |= /mob/living/silicon/robot/proc/robot_mount @@ -503,6 +620,10 @@ R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + //CHOMPEdit - Add vore capacity + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill R.verbs |= /mob/living/silicon/robot/proc/robot_mount @@ -519,7 +640,8 @@ "SciHound" = "scihound", "SciHoundDark" = "scihounddark", "Cat" = "vixsci", //CHOMPEdit - "Drake" = "drakesci" + "Drake" = "drakesci", + "Sciborg model V-4" = "sciraptor"//CHOMPEdit ) channels = list("Science" = 1) pto_type = PTO_SCIENCE @@ -543,9 +665,15 @@ //Added a circuit gripper src.modules += new /obj/item/weapon/gripper/circuit(src) src.modules += new /obj/item/weapon/gripper/no_use/organ/robotics(src) + //src.modules += new /obj/item/weapon/surgical/scalpel/cyborg(src) //these are on the normal one, but do not appear to have a purpose other than borging + //src.modules += new /obj/item/weapon/surgical/circular_saw/cyborg(src) //so I am leaving them here but commented out because robotics no do the borging w/o medical + src.modules += new /obj/item/weapon/portable_destructive_analyzer(src) //destructive analyzer option for pref respect while also being able to do job src.modules += new /obj/item/weapon/gripper/no_use/mech(src) - src.modules += new /obj/item/weapon/melee/baton/slime/robot(src) //Chompedit this was missing for some strange reason. - src.modules += new /obj/item/weapon/gun/energy/taser/xeno/robot(src) //Chompedit This also. + src.modules += new /obj/item/weapon/shockpaddles/robot/jumper(src) //unkilling synths may be important actually + src.modules += new /obj/item/weapon/melee/baton/slime/robot(src) //save the xenobio from themselves + src.modules += new /obj/item/weapon/gun/energy/taser/xeno/robot(src) //save the xenobio from themselves from a distance + src.modules += new /obj/item/device/xenoarch_multi_tool(src) //go find fancy rock + src.modules += new /obj/item/weapon/pickaxe/excavationdrill(src) //go get fancy rock src.emag = new /obj/item/weapon/hand_tele(src) var/datum/matter_synth/water = new /datum/matter_synth(500) @@ -585,6 +713,10 @@ R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + //CHOMPEdit - Add vore capacity + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill R.verbs |= /mob/living/silicon/robot/proc/robot_mount @@ -743,6 +875,10 @@ R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + //CHOMPEdit - Add vore capacity + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill R.verbs |= /mob/living/silicon/robot/proc/robot_mount @@ -822,6 +958,10 @@ R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + //CHOMPEdit - Add vore capacity + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill R.verbs |= /mob/living/silicon/robot/proc/robot_mount @@ -885,6 +1025,10 @@ R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + //CHOMPEdit - Add vore capacity + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill R.verbs |= /mob/living/silicon/robot/proc/robot_mount @@ -956,13 +1100,7 @@ src.modules += new /obj/item/weapon/tray/robotray(src) src.modules += new /obj/item/weapon/reagent_containers/borghypo/service(src) - src.emag = new /obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer(src) - var/datum/reagents/N = new/datum/reagents(50) - src.emag.reagents = N - N.my_atom = src.emag - N.add_reagent("beer2", 50) - src.emag.name = "Mickey Finn's Special Brew" R.icon = 'icons/mob/widerobot_colors_vr.dmi' R.wideborg_dept = 'icons/mob/widerobot_colors_vr.dmi' R.hands.icon = 'icons/mob/screen1_robot_vr.dmi' @@ -971,6 +1109,10 @@ R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + //CHOMPEdit - Add vore capacity + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill ..() @@ -978,9 +1120,6 @@ /obj/item/weapon/robot_module/robot/booze/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) var/obj/item/weapon/reagent_containers/food/condiment/enzyme/E = locate() in src.modules E.reagents.add_reagent("enzyme", 2 * amount) - if(src.emag) - var/obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer/B = src.emag - B.reagents.add_reagent("beer2", 2 * amount) //CHOMP addition start BORGHYPO /obj/item/weapon/reagent_containers/borghypo/service/booze @@ -1046,6 +1185,10 @@ R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + //CHOMPEdit - Add vore capacity + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) + //CHOMPEdit End R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill R.verbs |= /mob/living/silicon/robot/proc/robot_mount @@ -1070,4 +1213,3 @@ R.verbs -= /mob/living/proc/shred_limb R.verbs -= /mob/living/silicon/robot/proc/rest_style ..() -// CH changes - Unity Hound end diff --git a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm index d8f7aa8a3a..324e4afabc 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm @@ -10,7 +10,6 @@ LANGUAGE_SIIK = 0, LANGUAGE_AKHANI = 0, LANGUAGE_SKRELLIAN = 0, - LANGUAGE_SKRELLIANFAR = 0, LANGUAGE_ROOTLOCAL = 0, LANGUAGE_GUTTER = 1, LANGUAGE_SCHECHI = 0, diff --git a/code/modules/mob/living/silicon/robot/robot_vr.dm b/code/modules/mob/living/silicon/robot/robot_vr.dm index 72c323bfba..dd0d900db4 100644 --- a/code/modules/mob/living/silicon/robot/robot_vr.dm +++ b/code/modules/mob/living/silicon/robot/robot_vr.dm @@ -66,7 +66,16 @@ "uptall-engineering", "uptall-miner", "uptall-security", - "uptall-science" + "uptall-science", + "worm-standard", + "worm-engineering", + "worm-janitor", + "worm-crisis", + "worm-miner", + "worm-security", + "worm-combat", + "worm-surgeon", + "worm-service" ) //List of all used sprites that are in robots_vr.dmi @@ -98,10 +107,17 @@ vr_sprite_check() ..() if(dogborg == TRUE && stat == CONSCIOUS) + //update_fullness() // CHOMPEdit - Needed so that we can have the vore sprites when only using vore bellies + //CHOMPEdit begin - Add multiple belly size support + //Add a check when selecting an icon in robot.dm if you add in support for this, to set vore_capacity to 2 or however many states you have. + var/fullness_extension = "" + if(vore_capacity_ex["stomach"] > 1 && vore_fullness_ex["stomach"] > 1) + fullness_extension = "_[vore_fullness_ex["stomach"]]" + //CHOMPEdit end if(sleeper_g == TRUE) add_overlay("[module_sprites[icontype]]-sleeper_g") - if(sleeper_r == TRUE) - add_overlay("[module_sprites[icontype]]-sleeper_r") + if(sleeper_r == TRUE || (!sleeper_g && vore_fullness_ex["stomach"])) //CHOMPEdit - Also allow normal vore bellies to affect this sprite + add_overlay("[module_sprites[icontype]]-sleeper_r[fullness_extension]") //CHOMPEdit - Allow multiple belly sizes... if(istype(module_active,/obj/item/weapon/gun/energy/laser/mounted)) add_overlay("laser") if(istype(module_active,/obj/item/weapon/gun/energy/taser/mounted/cyborg)) @@ -115,24 +131,24 @@ //CHOMPEdit Begin - Add ability to have sleeper belly sprites if available if(sleeper_resting && sleeper_g == TRUE) add_overlay("[module_sprites[icontype]]-sleeper_g-sit") - if(sleeper_resting && sleeper_r == TRUE) - add_overlay("[module_sprites[icontype]]-sleeper_r-sit") + if(sleeper_resting && (sleeper_r == TRUE || (!sleeper_g && vore_fullness_ex["stomach"]))) + add_overlay("[module_sprites[icontype]]-sleeper_r-sit[fullness_extension]") //CHOMPEdit End if(bellyup) icon_state = "[module_sprites[icontype]]-bellyup" //CHOMPEdit Begin - Add ability to have sleeper belly sprites if available if(sleeper_resting && sleeper_g == TRUE) add_overlay("[module_sprites[icontype]]-sleeper_g-bellyup") - if(sleeper_resting && sleeper_r == TRUE) - add_overlay("[module_sprites[icontype]]-sleeper_r-bellyup") + if(sleeper_resting && (sleeper_r == TRUE || (!sleeper_g && vore_fullness_ex["stomach"]))) + add_overlay("[module_sprites[icontype]]-sleeper_r-bellyup[fullness_extension]") //CHOMPEdit End else if(!sitting && !bellyup) icon_state = "[module_sprites[icontype]]-rest" //CHOMPEdit Begin - Add ability to have sleeper belly sprites if available if(sleeper_resting && sleeper_g == TRUE) add_overlay("[module_sprites[icontype]]-sleeper_g-rest") - if(sleeper_resting && sleeper_r == TRUE) - add_overlay("[module_sprites[icontype]]-sleeper_r-rest") + if(sleeper_resting && (sleeper_r == TRUE || (!sleeper_g && vore_fullness_ex["stomach"]))) + add_overlay("[module_sprites[icontype]]-sleeper_r-rest[fullness_extension]") //CHOMPEdit End else icon_state = "[module_sprites[icontype]]" @@ -180,7 +196,8 @@ icon = 'modular_chomp/icons/mob/widerobot_ch.dmi' else if(icontype == "Cat" || icontype == "Cat Mining" || icontype == "Cat Cargo") // CHOMPEdit icon = 'modular_chomp/icons/mob/catborg/catborg.dmi' - sleeper_resting = TRUE + else if(icontype == "Mediborg model V-4" || icontype == "Secborg model V-4"|| icontype == "Sciborg model V-4") //CHOMPEdit + icon = 'modular_chomp/icons/mob/raptorborg/raptor.dmi' else icon = wideborg_dept return diff --git a/code/modules/mob/living/silicon/robot/subtypes/boozeborg_ch.dm b/code/modules/mob/living/silicon/robot/subtypes/boozeborg_ch.dm index 32b7fec8d1..2ab1cd5b0a 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/boozeborg_ch.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/boozeborg_ch.dm @@ -107,6 +107,8 @@ What Borgs are available is sadly handled in the above file in the proc R.old_x = -16 R.default_pixel_x = -16 R.dogborg = TRUE + R.vore_capacity = 1 + R.vore_capacity_ex = list("stomach" = 1) R.wideborg = TRUE R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill ..() diff --git a/code/modules/mob/living/simple_mob/appearance.dm b/code/modules/mob/living/simple_mob/appearance.dm index 08b36da6fc..f49a1b875d 100644 --- a/code/modules/mob/living/simple_mob/appearance.dm +++ b/code/modules/mob/living/simple_mob/appearance.dm @@ -64,6 +64,8 @@ /mob/living/simple_mob/proc/add_eyes() if(!eye_layer) eye_layer = image(icon, "[icon_state]-eyes") + if(custom_eye_color) + eye_layer.color = custom_eye_color eye_layer.plane = PLANE_LIGHTING_ABOVE eye_layer.appearance_flags = appearance_flags //VOREStation Edit. Make eye overlays respect the mob's scaling settings. add_overlay(eye_layer) diff --git a/code/modules/mob/living/simple_mob/simple_hud.dm b/code/modules/mob/living/simple_mob/simple_hud.dm index 3d186cc55f..b546774281 100644 --- a/code/modules/mob/living/simple_mob/simple_hud.dm +++ b/code/modules/mob/living/simple_mob/simple_hud.dm @@ -194,7 +194,7 @@ //Hand slots themselves inv_box = new /obj/screen/inventory/hand() - inv_box.hud = src + inv_box.hud = HUD inv_box.name = "r_hand" inv_box.icon = ui_style inv_box.icon_state = "r_hand_inactive" @@ -209,7 +209,7 @@ slot_info["[slot_r_hand]"] = inv_box.screen_loc inv_box = new /obj/screen/inventory/hand() - inv_box.hud = src + inv_box.hud = HUD inv_box.name = "l_hand" inv_box.icon = ui_style inv_box.icon_state = "l_hand_inactive" diff --git a/code/modules/mob/living/simple_mob/simple_mob.dm b/code/modules/mob/living/simple_mob/simple_mob.dm index c9dd6dd461..8406a48137 100644 --- a/code/modules/mob/living/simple_mob/simple_mob.dm +++ b/code/modules/mob/living/simple_mob/simple_mob.dm @@ -38,6 +38,7 @@ var/image/modifier_overlay = null // Holds overlays from modifiers. var/image/eye_layer = null // Holds the eye overlay. var/has_eye_glow = FALSE // If true, adds an overlay over the lighting plane for [icon_state]-eyes. + var/custom_eye_color = null attack_icon = 'icons/effects/effects.dmi' //Just the default, played like the weapon attack anim attack_icon_state = "slash" //Just the default @@ -252,11 +253,13 @@ // Turf related slowdown var/turf/T = get_turf(src) - if(T && T.movement_cost && !hovering) // Flying mobs ignore turf-based slowdown. Aquatic mobs ignore water slowdown, and can gain bonus speed in it. + if(T && T.movement_cost && (!hovering || !flying)) // Flying mobs ignore turf-based slowdown. Aquatic mobs ignore water slowdown, and can gain bonus speed in it. if(istype(T,/turf/simulated/floor/water) && aquatic_movement) . -= aquatic_movement - 1 else . += T.movement_cost + if(flying) + adjust_nutrition(-0.5) if(purge)//Purged creatures will move more slowly. The more time before their purge stops, the slower they'll move. if(. <= 0) diff --git a/code/modules/mob/living/simple_mob/simple_mob_vr.dm b/code/modules/mob/living/simple_mob/simple_mob_vr.dm index b51d2c3a87..7da6e35861 100644 --- a/code/modules/mob/living/simple_mob/simple_mob_vr.dm +++ b/code/modules/mob/living/simple_mob/simple_mob_vr.dm @@ -12,7 +12,8 @@ var/vore_active = 0 // If vore behavior is enabled for this mob - var/vore_capacity = 1 // The capacity (in people) this person can hold + //CHOMPEdit - Vore_capacity is now defined on living + vore_capacity = 1 // The capacity (in people) this person can hold var/vore_max_size = RESIZE_HUGE // The max size this mob will consider eating var/vore_min_size = RESIZE_TINY // The min size this mob will consider eating var/vore_bump_chance = 0 // Chance of trying to eat anyone that bumps into them, regardless of hostility @@ -40,9 +41,11 @@ var/vore_default_contamination_flavor = "Generic" //Contamination descriptors var/vore_default_contamination_color = "green" //Contamination color - var/vore_fullness = 0 // How "full" the belly is (controls icons) - var/vore_icons = 0 // Bitfield for which fields we have vore icons for. - var/vore_eyes = FALSE // For mobs with fullness specific eye overlays. + //CHOMPEDIT start - Moved to living + //var/vore_fullness = 0 // How "full" the belly is (controls icons) + //var/vore_icons = 0 // Bitfield for which fields we have vore icons for. + //var/vore_eyes = FALSE // For mobs with fullness specific eye overlays. + //CHOMPEDIT end. var/life_disabled = 0 // For performance reasons var/mount_offset_x = 5 // Horizontal riding offset. @@ -51,16 +54,17 @@ var/obj/item/device/radio/headset/mob_radio //Adminbus headset for simplemob shenanigans. does_spin = FALSE can_be_drop_pred = TRUE // Mobs are pred by default. + can_be_drop_prey = TRUE //CHOMP Add This also counts for spontaneous prey for telenoms and phase noms. var/damage_threshold = 0 //For some mobs, they have a damage threshold required to deal damage to them. + var/nom_mob = FALSE //If a mob is meant to be hostile for vore purposes but is otherwise not hostile, if true makes certain AI ignore the mob var/voremob_loaded = FALSE //CHOMPedit: On-demand belly loading. // Release belly contents before being gc'd! /mob/living/simple_mob/Destroy() release_vore_contents() - if(prey_excludes) - prey_excludes.Cut() + LAZYCLEARLIST(prey_excludes) return ..() //For all those ID-having mobs @@ -69,6 +73,7 @@ return myid // Update fullness based on size & quantity of belly contents +/* CHOMPEdit - moved to living /mob/living/simple_mob/proc/update_fullness() var/new_fullness = 0 for(var/obj/belly/B as anything in vore_organs) @@ -77,6 +82,7 @@ new_fullness = new_fullness / size_multiplier //Divided by pred's size so a macro mob won't get macro belly from a regular prey. new_fullness = round(new_fullness, 1) // Because intervals of 0.25 are going to make sprite artists cry. vore_fullness = min(vore_capacity, new_fullness) +*/ /mob/living/simple_mob/update_icon() . = ..() @@ -86,6 +92,7 @@ voremob_awake = TRUE update_fullness() if(!vore_fullness) + update_transform() return 0 else if((stat == CONSCIOUS) && (!icon_rest || !resting || !incapacitated(INCAPACITATION_DISABLED)) && (vore_icons & SA_ICON_LIVING)) icon_state = "[icon_living]-[vore_fullness]" @@ -118,7 +125,7 @@ if(!M.allowmobvore || !M.devourable) // Don't eat people who don't want to be ate by mobs //ai_log("vr/wont eat [M] because they don't allow mob vore", 3) //VORESTATION AI TEMPORARY REMOVAL return 0 - if(M in prey_excludes) // They're excluded + if(LAZYFIND(prey_excludes, M)) // They're excluded //ai_log("vr/wont eat [M] because they are excluded", 3) //VORESTATION AI TEMPORARY REMOVAL return 0 if(M.size_multiplier < vore_min_size || M.size_multiplier > vore_max_size) @@ -223,6 +230,7 @@ var/obj/belly/B = new /obj/belly(src) vore_selected = B B.immutable = 1 + B.affects_vore_sprites = TRUE //CHOMPEdit - vore sprites enabled for simplemobs! B.name = vore_stomach_name ? vore_stomach_name : "stomach" B.desc = vore_stomach_flavor ? vore_stomach_flavor : "Your surroundings are warm, soft, and slimy. Makes sense, considering you're inside \the [name]." B.digest_mode = vore_default_mode @@ -258,6 +266,8 @@ "The juices pooling beneath you sizzle against your sore skin.", "The churning walls slowly pulverize you into meaty nutrients.", "The stomach glorps and gurgles as it tries to work you into slop.") + can_be_drop_pred = TRUE // Mobs will eat anyone that decides to drop/slip into them by default. + B.belly_fullscreen = "yet_another_tumby" /mob/living/simple_mob/Bumped(var/atom/movable/AM, yes) if(tryBumpNom(AM)) @@ -372,7 +382,7 @@ if(buckle_mob(M)) visible_message("[M] starts riding [name]!") -/mob/living/simple_mob/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name) +/mob/living/simple_mob/handle_message_mode(message_mode, message, verb, used_radios, speaking, alt_name) //CHOMPEdit - This whole proc tbh if(message_mode) if(message_mode == "intercom") diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm index 3aa9f3691d..5081c63b8e 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/catslug.dm @@ -51,7 +51,7 @@ say_list_type = /datum/say_list/catslug player_msg = "You have escaped the foul weather, into this much more pleasant place. You are an intelligent creature capable of more than most think. You can pick up and use many things, and even carry some of them with you into the vents, which you can use to move around quickly. You're quiet and capable, you speak with your hands and your deeds!
") //CHOMPEdit
- t = replacetext(t, "\[sglogo\]", "
") //CHOMPEdit
+ t = replacetext(t, "\[sglogo\]", "
") //CHOMPEdit
t = "[t]"
else // If it is a crayon, and he still tries to use these, make them empty!
@@ -451,7 +451,7 @@
var/raw = tgui_input_text(usr, "Enter what you want to write:", "Write", multiline = TRUE, prevent_enter = TRUE)
if(!raw)
return
-
+
var/t = sanitize(raw, MAX_PAPER_MESSAGE_LEN, extra = 0)
if(!t)
return
@@ -534,7 +534,7 @@
/obj/item/weapon/paper/attackby(obj/item/weapon/P as obj, mob/user as mob)
..()
var/clown = 0
- if(user.mind && (user.mind.assigned_role == "Clown"))
+ if(user.mind && ((user.mind.role_alt_title == "Clown") || (user.mind.role_alt_title == "Jester") || (user.mind.role_alt_title == "Fool"))) // CHOMPStation Edit - Let clows/fools/jesters use clown stamps
clown = 1
if(istype(P, /obj/item/weapon/tape_roll))
diff --git a/code/modules/planet/virgo3b_vr.dm b/code/modules/planet/virgo3b_vr.dm
index 9e76fd1eda..b3e6d136fb 100644
--- a/code/modules/planet/virgo3b_vr.dm
+++ b/code/modules/planet/virgo3b_vr.dm
@@ -99,18 +99,19 @@ var/datum/planet/virgo3b/planet_virgo3b = null
/datum/weather_holder/virgo3b
temperature = T0C
allowed_weather_types = list(
- WEATHER_CLEAR = new /datum/weather/virgo3b/clear(),
- WEATHER_OVERCAST = new /datum/weather/virgo3b/overcast(),
- WEATHER_LIGHT_SNOW = new /datum/weather/virgo3b/light_snow(),
- WEATHER_SNOW = new /datum/weather/virgo3b/snow(),
- WEATHER_BLIZZARD = new /datum/weather/virgo3b/blizzard(),
- WEATHER_RAIN = new /datum/weather/virgo3b/rain(),
- WEATHER_STORM = new /datum/weather/virgo3b/storm(),
- WEATHER_HAIL = new /datum/weather/virgo3b/hail(),
- WEATHER_BLOOD_MOON = new /datum/weather/virgo3b/blood_moon(),
- WEATHER_EMBERFALL = new /datum/weather/virgo3b/emberfall(),
- WEATHER_ASH_STORM = new /datum/weather/virgo3b/ash_storm(),
- WEATHER_FALLOUT = new /datum/weather/virgo3b/fallout()
+ WEATHER_CLEAR = new /datum/weather/virgo3b/clear(),
+ WEATHER_OVERCAST = new /datum/weather/virgo3b/overcast(),
+ WEATHER_LIGHT_SNOW = new /datum/weather/virgo3b/light_snow(),
+ WEATHER_SNOW = new /datum/weather/virgo3b/snow(),
+ WEATHER_BLIZZARD = new /datum/weather/virgo3b/blizzard(),
+ WEATHER_RAIN = new /datum/weather/virgo3b/rain(),
+ WEATHER_STORM = new /datum/weather/virgo3b/storm(),
+ WEATHER_HAIL = new /datum/weather/virgo3b/hail(),
+ WEATHER_BLOOD_MOON = new /datum/weather/virgo3b/blood_moon(),
+ WEATHER_EMBERFALL = new /datum/weather/virgo3b/emberfall(),
+ WEATHER_ASH_STORM = new /datum/weather/virgo3b/ash_storm(),
+ WEATHER_ASH_STORM_SAFE = new /datum/weather/virgo3b/ash_storm_safe(),
+ WEATHER_FALLOUT = new /datum/weather/virgo3b/fallout()
)
roundstart_weather_chances = list(
WEATHER_CLEAR = 30,
@@ -479,6 +480,27 @@ var/datum/planet/virgo3b/planet_virgo3b = null
L.inflict_heat_damage(rand(1, 3))
+/datum/weather/virgo3b/ash_storm_safe
+ name = "light ash storm"
+ icon_state = "ashfall_moderate"
+ light_modifier = 0.1
+ light_color = "#FF0000"
+ temp_high = 323.15 // 50c
+ temp_low = 313.15 // 40c
+ wind_high = 6
+ wind_low = 3
+ flight_failure_modifier = 50
+ transition_chances = list(
+ WEATHER_ASH_STORM_SAFE = 100
+ )
+ observed_message = "All that can be seen is black smoldering ash."
+ transition_messages = list(
+ "Smoldering clouds of scorching ash billow down around you!"
+ )
+ // Lets recycle.
+ outdoor_sounds_type = /datum/looping_sound/weather/outside_blizzard
+ indoor_sounds_type = /datum/looping_sound/weather/inside_blizzard
+
// Totally radical.
/datum/weather/virgo3b/fallout
diff --git a/code/modules/planet/virgo3c_vr.dm b/code/modules/planet/virgo3c_vr.dm
index 45c64daee2..9786602f1a 100644
--- a/code/modules/planet/virgo3c_vr.dm
+++ b/code/modules/planet/virgo3c_vr.dm
@@ -119,18 +119,19 @@ var/datum/planet/virgo3c/planet_virgo3c = null
/datum/weather_holder/virgo3c
temperature = T0C
allowed_weather_types = list(
- WEATHER_CLEAR = new /datum/weather/virgo3c/clear(),
- WEATHER_OVERCAST = new /datum/weather/virgo3c/overcast(),
- WEATHER_LIGHT_SNOW = new /datum/weather/virgo3c/light_snow(),
- WEATHER_SNOW = new /datum/weather/virgo3c/snow(),
- WEATHER_BLIZZARD = new /datum/weather/virgo3c/blizzard(),
- WEATHER_RAIN = new /datum/weather/virgo3c/rain(),
- WEATHER_STORM = new /datum/weather/virgo3c/storm(),
- WEATHER_HAIL = new /datum/weather/virgo3c/hail(),
- WEATHER_BLOOD_MOON = new /datum/weather/virgo3c/blood_moon(),
- WEATHER_EMBERFALL = new /datum/weather/virgo3c/emberfall(),
- WEATHER_ASH_STORM = new /datum/weather/virgo3c/ash_storm(),
- WEATHER_FALLOUT = new /datum/weather/virgo3c/fallout()
+ WEATHER_CLEAR = new /datum/weather/virgo3c/clear(),
+ WEATHER_OVERCAST = new /datum/weather/virgo3c/overcast(),
+ WEATHER_LIGHT_SNOW = new /datum/weather/virgo3c/light_snow(),
+ WEATHER_SNOW = new /datum/weather/virgo3c/snow(),
+ WEATHER_BLIZZARD = new /datum/weather/virgo3c/blizzard(),
+ WEATHER_RAIN = new /datum/weather/virgo3c/rain(),
+ WEATHER_STORM = new /datum/weather/virgo3c/storm(),
+ WEATHER_HAIL = new /datum/weather/virgo3c/hail(),
+ WEATHER_BLOOD_MOON = new /datum/weather/virgo3c/blood_moon(),
+ WEATHER_EMBERFALL = new /datum/weather/virgo3c/emberfall(),
+ WEATHER_ASH_STORM = new /datum/weather/virgo3c/ash_storm(),
+ WEATHER_ASH_STORM_SAFE = new /datum/weather/virgo3c/ash_storm_safe(),
+ WEATHER_FALLOUT = new /datum/weather/virgo3c/fallout()
)
roundstart_weather_chances = list(
WEATHER_CLEAR = 50,
@@ -475,6 +476,30 @@ var/datum/planet/virgo3c/planet_virgo3c = null
L.inflict_heat_damage(1)
to_chat(L, "Smoldering ash singes you!")
+
+
+//A non-lethal variant of the ash_storm. Stays on indefinitely.
+/datum/weather/virgo3c/ash_storm_safe
+ name = "light ash storm"
+ icon_state = "ashfall_moderate"
+ light_modifier = 0.1
+ light_color = "#FF0000"
+ temp_high = 313.15 // 40c
+ temp_low = 303.15 // 30c
+ wind_high = 6
+ wind_low = 3
+ flight_failure_modifier = 50
+ transition_chances = list(
+ WEATHER_ASH_STORM_SAFE = 100
+ )
+ observed_message = "All that can be seen is black smoldering ash."
+ transition_messages = list(
+ "Smoldering clouds of scorching ash billow down around you!"
+ )
+ // Lets recycle.
+ outdoor_sounds_type = /datum/looping_sound/weather/outside_blizzard
+ indoor_sounds_type = /datum/looping_sound/weather/inside_blizzard
+
// Totally radical.
/datum/weather/virgo3c/fallout
name = "fallout"
@@ -545,6 +570,7 @@ VIRGO3C_TURF_CREATE(/turf/simulated/floor/glass/reinforced)
VIRGO3C_TURF_CREATE(/turf/simulated/open)
VIRGO3C_TURF_CREATE(/turf/simulated/floor/tiled/dark)
VIRGO3C_TURF_CREATE(/turf/simulated/mineral)
+VIRGO3C_TURF_CREATE(/turf/simulated/mineral/ignore_cavegen)
VIRGO3C_TURF_CREATE(/turf/simulated/floor)
VIRGO3C_TURF_CREATE(/turf/simulated/floor/wood)
VIRGO3C_TURF_CREATE(/turf/simulated/floor/wood/sif)
diff --git a/code/modules/planet/virgo4_vr.dm b/code/modules/planet/virgo4_vr.dm
index f4e2118e80..9cb88591ad 100644
--- a/code/modules/planet/virgo4_vr.dm
+++ b/code/modules/planet/virgo4_vr.dm
@@ -98,18 +98,19 @@ var/datum/planet/virgo4/planet_virgo4 = null
/datum/weather_holder/virgo4
temperature = T0C
allowed_weather_types = list(
- WEATHER_CLEAR = new /datum/weather/virgo4/clear(),
- WEATHER_OVERCAST = new /datum/weather/virgo4/overcast(),
- WEATHER_LIGHT_SNOW = new /datum/weather/virgo4/light_snow(),
- WEATHER_SNOW = new /datum/weather/virgo4/snow(),
- WEATHER_BLIZZARD = new /datum/weather/virgo4/blizzard(),
- WEATHER_RAIN = new /datum/weather/virgo4/rain(),
- WEATHER_STORM = new /datum/weather/virgo4/storm(),
- WEATHER_HAIL = new /datum/weather/virgo4/hail(),
- WEATHER_BLOOD_MOON = new /datum/weather/virgo4/blood_moon(),
- WEATHER_EMBERFALL = new /datum/weather/virgo4/emberfall(),
- WEATHER_ASH_STORM = new /datum/weather/virgo4/ash_storm(),
- WEATHER_FALLOUT = new /datum/weather/virgo4/fallout()
+ WEATHER_CLEAR = new /datum/weather/virgo4/clear(),
+ WEATHER_OVERCAST = new /datum/weather/virgo4/overcast(),
+ WEATHER_LIGHT_SNOW = new /datum/weather/virgo4/light_snow(),
+ WEATHER_SNOW = new /datum/weather/virgo4/snow(),
+ WEATHER_BLIZZARD = new /datum/weather/virgo4/blizzard(),
+ WEATHER_RAIN = new /datum/weather/virgo4/rain(),
+ WEATHER_STORM = new /datum/weather/virgo4/storm(),
+ WEATHER_HAIL = new /datum/weather/virgo4/hail(),
+ WEATHER_BLOOD_MOON = new /datum/weather/virgo4/blood_moon(),
+ WEATHER_EMBERFALL = new /datum/weather/virgo4/emberfall(),
+ WEATHER_ASH_STORM = new /datum/weather/virgo4/ash_storm(),
+ WEATHER_ASH_STORM_SAFE = new /datum/weather/virgo4/ash_storm_safe(),
+ WEATHER_FALLOUT = new /datum/weather/virgo4/fallout()
)
roundstart_weather_chances = list(
WEATHER_CLEAR = 50,
@@ -452,6 +453,28 @@ var/datum/planet/virgo4/planet_virgo4 = null
L.inflict_heat_damage(rand(1, 3))
+//A non-lethal variant of the ash_storm. Stays on indefinitely.
+/datum/weather/virgo4/ash_storm_safe
+ name = "light ash storm"
+ icon_state = "ashfall_moderate"
+ light_modifier = 0.1
+ light_color = "#FF0000"
+ temp_high = 323.15 // 50c
+ temp_low = 313.15 // 40c
+ wind_high = 6
+ wind_low = 3
+ flight_failure_modifier = 50
+ transition_chances = list(
+ WEATHER_ASH_STORM_SAFE = 100
+ )
+ observed_message = "All that can be seen is black smoldering ash."
+ transition_messages = list(
+ "Smoldering clouds of scorching ash billow down around you!"
+ )
+ // Lets recycle.
+ outdoor_sounds_type = /datum/looping_sound/weather/outside_blizzard
+ indoor_sounds_type = /datum/looping_sound/weather/inside_blizzard
+
// Totally radical.
/datum/weather/virgo4/fallout
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 3fd25a83e4..d4c8a8bf59 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -143,7 +143,7 @@ GLOBAL_LIST_EMPTY(apcs)
var/updating_icon = 0
var/global/list/status_overlays_environ
var/alarms_hidden = FALSE //If power alarms from this APC are visible on consoles
-
+
var/nightshift_lights = FALSE
var/nightshift_setting = NIGHTSHIFT_AUTO
var/last_nightshift_switch = 0
@@ -198,7 +198,7 @@ GLOBAL_LIST_EMPTY(apcs)
if(!pixel_x && !pixel_y)
offset_apc()
-
+
if(building)
area = get_area(src)
area.apc = src
@@ -1360,6 +1360,7 @@ GLOBAL_LIST_EMPTY(apcs)
for(var/obj/machinery/light/L in area)
L.nightshift_mode(new_state)
+ L.update() //For some reason it gets hung up on updating the overlay for the light fixture somewhere down the line. This fixes it.
CHECK_TICK
#undef APC_UPDATE_ICON_COOLDOWN
diff --git a/code/modules/power/breaker_box.dm b/code/modules/power/breaker_box.dm
index f8915e08af..2dffe3c228 100644
--- a/code/modules/power/breaker_box.dm
+++ b/code/modules/power/breaker_box.dm
@@ -39,6 +39,9 @@
// Enabled on server startup. Used in substations to keep them in bypass mode.
/obj/machinery/power/breakerbox/activated/Initialize()
. = ..()
+ return INITIALIZE_HINT_LATELOAD
+
+/obj/machinery/power/breakerbox/activated/LateInitialize()
set_state(1)
/obj/machinery/power/breakerbox/examine(mob/user)
@@ -93,7 +96,8 @@
/obj/machinery/power/breakerbox/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
if(istype(W, /obj/item/device/multitool))
- var/newtag = tgui_input_text(user, "Enter new RCON tag. Use \"NO_TAG\" to disable RCON or leave empty to cancel.", "SMES RCON system")
+ var/newtag = tgui_input_text(user, "Enter new RCON tag. Use \"NO_TAG\" to disable RCON or leave empty to cancel.", "SMES RCON system", "", MAX_NAME_LEN)
+ newtag = sanitize(newtag,MAX_NAME_LEN)
if(newtag)
RCon_tag = newtag
to_chat(user, "You changed the RCON tag to: [newtag]")
diff --git a/code/modules/power/fusion/core/_core.dm b/code/modules/power/fusion/core/_core.dm
index 308c930783..dfcf908107 100644
--- a/code/modules/power/fusion/core/_core.dm
+++ b/code/modules/power/fusion/core/_core.dm
@@ -149,7 +149,8 @@ GLOBAL_LIST_EMPTY(fusion_cores)
return
if(istype(W, /obj/item/device/multitool))
- var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", "Fusion Core", id_tag)
+ var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", "Fusion Core", id_tag, MAX_NAME_LEN)
+ new_ident = sanitize(new_ident,MAX_NAME_LEN)
if(new_ident && user.Adjacent(src))
id_tag = new_ident
return
diff --git a/code/modules/power/fusion/fuel_assembly/fuel_control.dm b/code/modules/power/fusion/fuel_assembly/fuel_control.dm
index 24394b7973..621847f79b 100644
--- a/code/modules/power/fusion/fuel_assembly/fuel_control.dm
+++ b/code/modules/power/fusion/fuel_assembly/fuel_control.dm
@@ -117,7 +117,8 @@
/obj/machinery/computer/fusion_fuel_control/attackby(var/obj/item/W, var/mob/user)
..()
if(istype(W, /obj/item/device/multitool))
- var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", "Fuel Control", monitor.fuel_tag)
+ var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", "Fuel Control", monitor.fuel_tag, MAX_NAME_LEN)
+ new_ident = sanitize(new_ident,MAX_NAME_LEN)
if(new_ident && user.Adjacent(src))
monitor.fuel_tag = new_ident
return
diff --git a/code/modules/power/fusion/fuel_assembly/fuel_injector.dm b/code/modules/power/fusion/fuel_assembly/fuel_injector.dm
index f37b8fcd21..74a479e9b6 100644
--- a/code/modules/power/fusion/fuel_assembly/fuel_injector.dm
+++ b/code/modules/power/fusion/fuel_assembly/fuel_injector.dm
@@ -43,7 +43,8 @@ GLOBAL_LIST_EMPTY(fuel_injectors)
/obj/machinery/fusion_fuel_injector/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/device/multitool))
- var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", "Fuel Injector", id_tag)
+ var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", "Fuel Injector", id_tag, MAX_NAME_LEN)
+ new_ident = sanitize(new_ident,MAX_NAME_LEN)
if(new_ident && user.Adjacent(src))
id_tag = new_ident
return
diff --git a/code/modules/power/fusion/gyrotron/gyrotron.dm b/code/modules/power/fusion/gyrotron/gyrotron.dm
index b2b33ef96b..b84d04871e 100644
--- a/code/modules/power/fusion/gyrotron/gyrotron.dm
+++ b/code/modules/power/fusion/gyrotron/gyrotron.dm
@@ -53,7 +53,8 @@ GLOBAL_LIST_EMPTY(gyrotrons)
/obj/machinery/power/emitter/gyrotron/attackby(var/obj/item/W, var/mob/user)
if(istype(W, /obj/item/device/multitool))
- var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", "Gyrotron", id_tag)
+ var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", "Gyrotron", id_tag, MAX_NAME_LEN)
+ new_ident = sanitize(new_ident,MAX_NAME_LEN)
if(new_ident && user.Adjacent(src))
id_tag = new_ident
return
diff --git a/code/modules/power/fusion/gyrotron/gyrotron_control.dm b/code/modules/power/fusion/gyrotron/gyrotron_control.dm
index 9ff359fd29..1979e091ad 100644
--- a/code/modules/power/fusion/gyrotron/gyrotron_control.dm
+++ b/code/modules/power/fusion/gyrotron/gyrotron_control.dm
@@ -119,7 +119,8 @@
/obj/machinery/computer/gyrotron_control/attackby(var/obj/item/W, var/mob/user)
..()
if(istype(W, /obj/item/device/multitool))
- var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", "Gyrotron Control", monitor.gyro_tag)
+ var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", "Gyrotron Control", monitor.gyro_tag, MAX_NAME_LEN)
+ new_ident = sanitize(new_ident,MAX_NAME_LEN)
if(new_ident && user.Adjacent(src))
monitor.gyro_tag = new_ident
return
diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm
index 34622b4e4b..f748baf6e8 100644
--- a/code/modules/power/generator.dm
+++ b/code/modules/power/generator.dm
@@ -261,11 +261,11 @@ GLOBAL_LIST_EMPTY(all_turbines)
src.set_dir(turn(src.dir, 90))
-/obj/machinery/power/generator/power_spike()
-// if(!effective_gen >= max_power / 2 && powernet) // Don't make a spike if we're not making a whole lot of power.
-// return
+/obj/machinery/power/generator/power_spike(var/announce_prob = 30)
+ if(!(effective_gen >= max_power / 2 && powernet)) // Don't make a spike if we're not making a whole lot of power.
+ return
- var/list/powernet_union = powernet.nodes
+ var/list/powernet_union = powernet.nodes.Copy()
for(var/obj/machinery/power/terminal/T in powernet.nodes)
if(T.master && istype(T.master, /obj/machinery/power/smes))
var/obj/machinery/power/smes/S = T.master
@@ -273,7 +273,7 @@ GLOBAL_LIST_EMPTY(all_turbines)
var/found_grid_checker = FALSE
for(var/obj/machinery/power/grid_checker/G in powernet_union)
- G.power_failure(prob(30)) // If we found a grid checker, then all is well.
+ G.power_failure(announce_prob) // If we found a grid checker, then all is well.
found_grid_checker = TRUE
if(!found_grid_checker) // Otherwise lets break some stuff.
spawn(1)
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 621ee7484f..e1b41b602e 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -215,6 +215,7 @@ var/global/list/light_type_cache = list()
idle_power_usage = 2
active_power_usage = 10
power_channel = LIGHT //Lights are calc'd via area so they dont need to be in the machine list
+ var/obj/item/weapon/light/installed_light //What light is currently in the socket! Updated in new()
var/on = 0 // 1 if on, 0 if off
var/brightness_range
var/brightness_power
@@ -344,9 +345,10 @@ var/global/list/light_type_cache = list()
construct.transfer_fingerprints_to(src)
set_dir(construct.dir)
else
+ installed_light = new light_type(src)
if(start_with_cell && !no_emergency)
cell = new/obj/item/weapon/cell/emergency_light(src)
- var/obj/item/weapon/light/L = get_light_type_instance(light_type)
+ var/obj/item/weapon/light/L = get_light_type_instance(light_type) //This is fine, but old code.
update_from_bulb(L)
if(prob(L.broken_chance))
broken(1)
@@ -422,6 +424,7 @@ var/global/list/light_type_cache = list()
if(!shows_alerts)
return
current_alert = "atmos"
+ light_color = "#6D6DFC"
brightness_color = "#6D6DFC"
update()
@@ -429,6 +432,7 @@ var/global/list/light_type_cache = list()
if(!shows_alerts)
return
current_alert = "fire"
+ light_color = "#FF3030"
brightness_color = "#FF3030"
update()
@@ -437,7 +441,7 @@ var/global/list/light_type_cache = list()
return
current_alert = null
- var/obj/item/weapon/light/L = get_light_type_instance(light_type)
+ var/obj/item/weapon/light/L = installed_light //This ensures any special bulbs will stay special!
if(L)
update_from_bulb(L)
@@ -462,7 +466,12 @@ var/global/list/light_type_cache = list()
var/correct_range = nightshift_enabled ? brightness_range_ns : brightness_range
var/correct_power = nightshift_enabled ? brightness_power_ns : brightness_power
var/correct_color = nightshift_enabled ? brightness_color_ns : brightness_color
- if(light_range != correct_range || light_power != correct_power || light_color != correct_color)
+ var/correct_overlay = nightshift_enabled ? brightness_color_ns : brightness_color //Gives lights the correct overlay if NS is enabled.
+ if(current_alert) //Oh no, we're on fire! Or the atmos is bad! Let's change the color
+ correct_range = brightness_range
+ correct_power = brightness_power
+ correct_color = brightness_color
+ if(light_range != correct_range || light_power != correct_power || light_color != correct_color || overlay_color != correct_overlay)
if(!auto_flicker)
switchcount++
if(rigged)
@@ -481,6 +490,7 @@ var/global/list/light_type_cache = list()
else
update_use_power(USE_POWER_ACTIVE)
set_light(correct_range, correct_power, correct_color)
+ overlay_color = correct_overlay
if(cell?.charge < cell?.maxcharge)
START_PROCESSING(SSobj, src)
else if(has_emergency_power(LIGHT_EMERGENCY_POWER_USE) && !turned_off())
@@ -490,8 +500,7 @@ var/global/list/light_type_cache = list()
else
update_use_power(USE_POWER_IDLE)
set_light(0)
- update_icon()
-
+ update_light() //VOREStation Edit - Makes lights update when their color is changed.
update_active_power_usage((light_range * light_power) * LIGHTING_POWER_FACTOR)
/obj/machinery/light/proc/nightshift_mode(var/state)
@@ -566,6 +575,7 @@ var/global/list/light_type_cache = list()
brightness_range = L.brightness_range
brightness_power = L.brightness_power
brightness_color = L.brightness_color
+ overlay_color = L.brightness_color
brightness_range_ns = L.nightshift_range
brightness_power_ns = L.nightshift_power
@@ -575,7 +585,8 @@ var/global/list/light_type_cache = list()
/obj/machinery/light/proc/insert_bulb(obj/item/weapon/light/L)
update_from_bulb(L)
- qdel(L)
+ installed_light = L
+ L.loc = src //Move it into the socket!
on = powered()
update()
@@ -588,16 +599,17 @@ var/global/list/light_type_cache = list()
explode()
/obj/machinery/light/proc/remove_bulb()
- . = new light_type(src.loc, src)
+ //. = new light_type(src.loc, src)
switchcount = 0
+ installed_light = null
status = LIGHT_EMPTY
update()
/obj/machinery/light/attackby(obj/item/W, mob/user)
//Light replacer code
- if(istype(W, /obj/item/device/lightreplacer))
+ if(istype(W, /obj/item/device/lightreplacer)) //These will never be modified, so it's fine to use old code.
var/obj/item/device/lightreplacer/LR = W
if(isliving(user))
var/mob/living/U = user
@@ -614,7 +626,9 @@ var/global/list/light_type_cache = list()
return
to_chat(user, "You insert [W].")
+ user.drop_item()
insert_bulb(W)
+ update() //Like other places, this is done later down the line but this is essential to updating the overlay when nightmode is involved. Again, I have no idea WHY.
src.add_fingerprint(user)
// attempt to break the light
@@ -719,6 +733,7 @@ var/global/list/light_type_cache = list()
if(cell.charge > 300) //it's meant to handle 120 W, ya doofus
visible_message("[src] short-circuits from too powerful of a power cell!")
status = LIGHT_BURNED
+ installed_light.status = status
return FALSE
cell.use(pwr)
set_light(brightness_range * bulb_emergency_brightness_mul, max(bulb_emergency_pow_min, bulb_emergency_pow_mul * (cell.charge / cell.maxcharge)), bulb_emergency_colour)
@@ -800,8 +815,11 @@ var/global/list/light_type_cache = list()
else
to_chat(user, "You remove the light [get_fitting_name()].")
- // create a light tube/bulb item and put it in the user's hand
- user.put_in_active_hand(remove_bulb()) //puts it in our active hand
+ //Let's actually put the real bulb in their hand.
+ installed_light.status = status //Update the bulb they're being given. If it's broken, the bulb should be as well!
+ user.put_in_active_hand(installed_light) //puts it in our active hand
+ installed_light.update_icon()
+ remove_bulb()
/obj/machinery/light/flamp/attack_hand(mob/user)
if(lamp_shade)
@@ -840,13 +858,17 @@ var/global/list/light_type_cache = list()
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
- status = LIGHT_BROKEN
+ status = LIGHT_BROKEN //This occasionally runtimes when it occurs midround after build mode spawns a broken light. No idea why.
+ installed_light.status = status
+ installed_light.update_icon()
update()
/obj/machinery/light/proc/fix()
if(status == LIGHT_OK)
return
status = LIGHT_OK
+ if(installed_light)
+ installed_light.status = LIGHT_OK
on = 1
update()
@@ -953,6 +975,13 @@ var/global/list/light_type_cache = list()
drop_sound = 'sound/items/drop/glass.ogg'
pickup_sound = 'sound/items/pickup/glass.ogg'
+ //VOREStation Edit Start - Modifiable Lighting
+ var/init_brightness_range = 8
+ var/init_brightness_power = 1
+ var/init_nightshift_range = 8
+ var/init_nightshift_power = 0.45
+ //VOREStation Edit End - Modifiable Lighting
+
/obj/item/weapon/light/tube
name = "light tube"
desc = "A replacement light tube."
@@ -962,6 +991,8 @@ var/global/list/light_type_cache = list()
matter = list(MAT_GLASS = 100)
brightness_range = 7
brightness_power = 2
+ init_brightness_range = 7
+ init_brightness_power = 2
/obj/item/weapon/light/tube/large
w_class = ITEMSIZE_SMALL
@@ -972,6 +1003,11 @@ var/global/list/light_type_cache = list()
nightshift_range = 10
nightshift_power = 1.5
+ init_brightness_range = 15
+ init_brightness_power = 4
+ init_nightshift_range = 10
+ init_nightshift_power = 1.5
+
/obj/item/weapon/light/bulb
name = "light bulb"
desc = "A replacement light bulb."
@@ -986,6 +1022,11 @@ var/global/list/light_type_cache = list()
nightshift_range = 3
nightshift_power = 0.5
+ init_brightness_range = 5
+ init_brightness_power = 1
+ init_nightshift_range = 3
+ init_nightshift_power = 0.5
+
// For 'floor lamps' in outdoor use and such
/obj/item/weapon/light/bulb/large
name = "large light bulb"
@@ -995,6 +1036,11 @@ var/global/list/light_type_cache = list()
nightshift_range = 4
nightshift_power = 0.75
+ init_brightness_range = 7
+ init_brightness_power = 1.5
+ init_nightshift_range = 4
+ init_nightshift_power = 0.75
+
/obj/item/weapon/light/throw_impact(atom/hit_atom)
..()
shatter()
@@ -1003,6 +1049,7 @@ var/global/list/light_type_cache = list()
brightness_range = 4
color = "#da0205"
brightness_color = "#da0205"
+ init_brightness_range = 4
/obj/item/weapon/light/bulb/fire
name = "fire bulb"
@@ -1045,7 +1092,56 @@ var/global/list/light_type_cache = list()
// if a syringe, can inject phoron to make it explode
/obj/item/weapon/light/attackby(var/obj/item/I, var/mob/user)
..()
- if(istype(I, /obj/item/weapon/reagent_containers/syringe))
+
+ //VOREStation Edit Start - Multitool Lighting!
+ if(istype(I,/obj/item/device/multitool))
+ var/list/menu_list = list(
+ "Normal Range",
+ "Normal Brightness",
+ "Normal Color",
+ "Nightshift Range",
+ "Nightshift Brightness",
+ "Nightshift Color",
+ )
+
+ var/modification_decision = tgui_input_list(usr, "What do you wish to change about this light?", "Light Adjustment", menu_list)
+ if(!modification_decision)
+ return //They didn't select anything!
+ switch(modification_decision)
+ if("Normal Range")
+ var/new_range = tgui_input_number(usr, "Choose the new range of the light! (1-[init_brightness_range])", "", init_brightness_range, init_brightness_range, 1, 0)
+ if(new_range)
+ brightness_range = new_range
+
+ if("Normal Brightness")
+ var/new_power = tgui_input_number(usr, "Choose the new brightness of the light! (0.01 - [init_brightness_power])", "", init_brightness_power, init_brightness_power, 0.01, 0)
+ if(new_power)
+ brightness_power = new_power
+
+ if("Normal Color")
+ var/new_color = input(usr, "Choose a color to set the light to!", "", brightness_color) as color|null
+ if(new_color)
+ brightness_color = new_color
+
+ if("Nightshift Range")
+ var/new_range = tgui_input_number(usr, "Choose the new range of the light! (1-[init_nightshift_range])", "", init_nightshift_range, init_nightshift_range, 1)
+ if(new_range)
+ nightshift_range = new_range
+
+ if("Nightshift Brightness")
+ var/new_power = tgui_input_number(usr, "Choose the new brightness of the light! (0.01 - [init_nightshift_power])", "", init_nightshift_power, init_nightshift_power, 0.01)
+ if(new_power)
+ nightshift_power = new_power
+
+ if("Nightshift Color")
+ var/new_color = input(usr, "Choose a color to set the light to!", "", nightshift_color) as color|null
+ if(new_color)
+ nightshift_color = new_color
+
+ else //Should never happen.
+ return
+
+ else if(istype(I, /obj/item/weapon/reagent_containers/syringe))
var/obj/item/weapon/reagent_containers/syringe/S = I
to_chat(user, "You inject the solution into the [src].")
diff --git a/code/modules/power/port_gen_vr.dm b/code/modules/power/port_gen_vr.dm
index 0744a9143d..2b891643a6 100644
--- a/code/modules/power/port_gen_vr.dm
+++ b/code/modules/power/port_gen_vr.dm
@@ -316,7 +316,7 @@
/obj/machinery/power/rtg/reg/unbuckle_mob(mob/living/buckled_mob, force = FALSE)
. = ..()
- buckled_mob.pixel_y = initial(buckled_mob.pixel_y)
+ buckled_mob.pixel_y = buckled_mob.default_pixel_y
/obj/machinery/power/rtg/reg/RefreshParts()
var/n = 0
diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm
index e4d3254fda..9ccf421b57 100644
--- a/code/modules/power/singularity/particle_accelerator/particle_control.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm
@@ -184,8 +184,8 @@
/obj/machinery/particle_accelerator/control_box/proc/toggle_power()
active = !active
investigate_log("turned [active?"ON":"OFF"] by [usr ? usr.key : "outside forces"]","singulo")
- message_admins("PA Control Computer turned [active ?"ON":"OFF"] by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1)
- log_game("PACCEL([x],[y],[z]) [key_name(usr)] turned [active?"ON":"OFF"].")
+ message_admins("PA Control Computer turned [active ?"ON":"OFF"] by [usr ? key_name(usr, usr.client) : "outside forces"](?) in ([x],[y],[z] - JMP)",0,1)
+ log_game("PACCEL([x],[y],[z]) [usr ? key_name(usr, usr.client) : "outside forces"] turned [active?"ON":"OFF"].")
if(active)
update_use_power(USE_POWER_ACTIVE)
for(var/obj/structure/particle_accelerator/part in connected_parts)
diff --git a/code/modules/power/smes_construction.dm b/code/modules/power/smes_construction.dm
index 381f6b09f6..15c2f61f0d 100644
--- a/code/modules/power/smes_construction.dm
+++ b/code/modules/power/smes_construction.dm
@@ -312,7 +312,8 @@
// Multitool - change RCON tag
if(istype(W, /obj/item/device/multitool))
- var/newtag = tgui_input_text(user, "Enter new RCON tag. Use \"NO_TAG\" to disable RCON or leave empty to cancel.", "SMES RCON system")
+ var/newtag = tgui_input_text(user, "Enter new RCON tag. Use \"NO_TAG\" to disable RCON or leave empty to cancel.", "SMES RCON system", "", MAX_NAME_LEN)
+ newtag = sanitize(newtag,MAX_NAME_LEN)
if(newtag)
RCon_tag = newtag
to_chat(user, "You changed the RCON tag to: [newtag]")
diff --git a/code/modules/power/smes_vr.dm b/code/modules/power/smes_vr.dm
index a333660a43..fe46cae7f0 100644
--- a/code/modules/power/smes_vr.dm
+++ b/code/modules/power/smes_vr.dm
@@ -32,3 +32,5 @@
/obj/machinery/power/smes/buildable/hybrid/process()
charge += min(recharge_rate, capacity - charge)
..()
+
+//hey travis wake up
\ No newline at end of file
diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm
index 77a5659cdd..9f542db4cc 100644
--- a/code/modules/power/turbine.dm
+++ b/code/modules/power/turbine.dm
@@ -124,7 +124,8 @@
if(default_deconstruction_crowbar(user, W))
return
if(istype(W, /obj/item/device/multitool))
- var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", name, comp_id)
+ var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", name, comp_id, MAX_NAME_LEN)
+ new_ident = sanitize(new_ident,MAX_NAME_LEN)
if(new_ident && user.Adjacent(src))
comp_id = new_ident
return
@@ -337,7 +338,8 @@
/obj/machinery/computer/turbine_computer/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/device/multitool))
- var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", name, id)
+ var/new_ident = tgui_input_text(usr, "Enter a new ident tag.", name, id, MAX_NAME_LEN)
+ new_ident = sanitize(new_ident,MAX_NAME_LEN)
if(new_ident && user.Adjacent(src))
id = new_ident
return
diff --git a/code/modules/projectiles/guns/energy/altevian_vr.dm b/code/modules/projectiles/guns/energy/altevian_vr.dm
new file mode 100644
index 0000000000..150d05c421
--- /dev/null
+++ b/code/modules/projectiles/guns/energy/altevian_vr.dm
@@ -0,0 +1,59 @@
+/obj/item/weapon/gun/energy/altevian
+ name = "Magneto-Electric Energy Projector"
+ desc = "A hand-held version of an energy weapon for the Altevian Hegemony. This one seems to be made for more proper civilian use with its reduced charge capacity, but ease of handling."
+ icon_state = "meep"
+ item_state = "meep"
+ fire_delay = 8
+ slot_flags = SLOT_BELT
+ w_class = ITEMSIZE_NORMAL
+ force = 5
+ origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 2)
+ matter = list(MAT_STEEL = 1000)
+ projectile_type = /obj/item/projectile/beam/meeplaser
+ charge_cost = 150
+
+/obj/item/weapon/gun/energy/altevian/large
+ name = "Proto-Reactive Beam Thruster"
+ desc = "A standard issue energy rifle seen for defensive purposes for a space faring rodent species. The beams are tuned for proper suppression."
+ icon_state = "altevian-pdw"
+ item_state = "altevian-pdw"
+ slot_flags = SLOT_BELT
+ w_class = ITEMSIZE_LARGE
+ force = 10
+ origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 4)
+ matter = list(MAT_STEEL = 2000)
+ projectile_type = /obj/item/projectile/beam/meeplaser/strong
+ charge_cost = 300
+
+/obj/item/projectile/beam/meeplaser
+ name = "meep beam"
+ icon_state = "meep"
+ damage = 15
+ light_color = "#77A6E1"
+ hud_state = "laser_disabler"
+
+ muzzle_type = /obj/effect/projectile/muzzle/meeplaser
+ tracer_type = /obj/effect/projectile/tracer/meeplaser
+ impact_type = /obj/effect/projectile/impact/meeplaser
+
+/obj/item/projectile/beam/meeplaser/strong
+ name = "repeater beam"
+ damage = 35
+
+/obj/effect/projectile/muzzle/meeplaser
+ icon_state = "muzzle_meep"
+ light_range = 2
+ light_power = 0.5
+ light_color = "#77A6E1"
+
+/obj/effect/projectile/tracer/meeplaser
+ icon_state = "meep"
+ light_range = 2
+ light_power = 0.5
+ light_color = "#77A6E1"
+
+/obj/effect/projectile/impact/meeplaser
+ icon_state = "impact_meep"
+ light_range = 2
+ light_power = 0.5
+ light_color = "#77A6E1"
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator_vr.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator_vr.dm
index 3b95676eee..22dd450169 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator_vr.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator_vr.dm
@@ -382,13 +382,6 @@
. = TRUE
if(src in KA.modkits) // Sanity check to prevent installing the same modkit twice thanks to occasional click/lag delays.
return FALSE
- // if(minebot_upgrade)
- // if(minebot_exclusive && !istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone))
- // to_chat(user, "The modkit you're trying to install is only rated for minebot use.")
- // return FALSE
- // else if(istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone))
- // to_chat(user, "The modkit you're trying to install is not rated for minebot use.")
- // return FALSE
if(denied_type)
var/number_of_denied = 0
for(var/A in KA.get_modkits())
diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm
index c97e7c7096..76569a825f 100644
--- a/code/modules/projectiles/guns/energy/laser.dm
+++ b/code/modules/projectiles/guns/energy/laser.dm
@@ -147,6 +147,108 @@
charge_cost = 480 //to compensate a bit for self-recharging
cell_type = /obj/item/weapon/cell/device/weapon/recharge/captain
battery_lock = 1
+/* var/remainingshots = 0 //you may get a limited number of shots regardless of the charge //CHOMPedit: no
+ var/failurechance = 0 //chance per shot of something going awry
+
+/obj/item/weapon/gun/energy/captain/Initialize()
+ //it's an antique and it's been sitting in a case, unmaintained, for who the hell knows how long - who knows what'll happen when you pull it out?
+ ..()
+ //first, we decide, does it have a different type of beam? 75% of just being a 40-damage laser, 15% of being less or 0, 10% of being better
+ projectile_type = pick(prob(1);/obj/item/projectile/beam/pulse,
+ prob(2);/obj/item/projectile/beam/heavylaser/cannon,
+ prob(2);/obj/item/projectile/beam/heavylaser,
+ prob(5);/obj/item/projectile/beam/sniper,
+ prob(45);/obj/item/projectile/beam,
+ prob(10);/obj/item/projectile/beam/cyan,
+ prob(10);/obj/item/projectile/beam/eluger,
+ prob(10);/obj/item/projectile/beam/imperial,
+ prob(10);/obj/item/projectile/beam/weaklaser,
+ prob(5);/obj/item/projectile/beam/practice)
+ //now, decide whether it has a shot limit and if so how many
+ if(prob(50))
+ remainingshots = rand(1,40)
+ if(prob(50))
+ failurechance = rand(1,5)
+
+ //finally, update the description so it has a tell if it's gonna burn out on you
+ if(remainingshots || failurechance)
+ desc = "A rare weapon, produced by the Lunar Arms Company around 2105 - one of humanity's first wholly extra-terrestrial weapon designs. It's been reasonably well-preserved."
+
+/obj/item/weapon/gun/energy/captain/special_check(var/mob/user)
+ if(remainingshots)
+ remainingshots -= 1
+ if(!remainingshots) //you've shot your load, sonny
+ burnout(user)
+ return 0
+ else if(prob(failurechance))
+ malfunction(user)
+ return 0
+ return ..()
+
+/obj/item/weapon/gun/energy/captain/proc/burnout(var/mob/user)
+ //your gun is now rendered useless
+ projectile_type = /obj/item/projectile/beam/practice //just in case you somehow manage to get it to fire again, its beam type is set to one that sucks
+ power_supply.charge = 0
+ power_supply.maxcharge = 1 //just to avoid div/0 runtimes
+ desc = "A rare weapon, produced by the Lunar Arms Company around 2105 - one of humanity's first wholly extra-terrestrial weapon designs. It looks to have completely burned out."
+ user.visible_message("\The [src] erupts in a shower of sparks!", "\the [src] bursts into a shower of sparks!")
+ var/turf/T = get_turf(src)
+ var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
+ sparks.set_up(2, 1, T)
+ sparks.start()
+ update_icon()
+
+/obj/item/weapon/gun/energy/captain/proc/malfunction(var/mob/user)
+ var/screwup = rand(1,10)
+ switch(screwup)
+ if(1 to 5) //50% of just draining the battery and making future malfunctions more likely
+ power_supply.charge = 0
+ var/turf/T = get_turf(src)
+ var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
+ sparks.set_up(2, 1, T)
+ sparks.start()
+ update_icon()
+ user.visible_message("\The [src] shorts out!", "\the [src] shorts out!")
+ failurechance += rand(1,5)
+ return
+ if(6 to 7) //20% chance of weakening the beam type, possibly to uselessness
+ var/obj/item/projectile/beam/B = new projectile_type
+ switch(B.damage)
+ if(0)
+ return //can't weaken it any further
+ if(1 to 15) //weaklaser becomes practice
+ projectile_type = /obj/item/projectile/beam/practice
+ if(16 to 40) //regular becomes weaklaser
+ projectile_type = /obj/item/projectile/beam/weaklaser
+ if(41 to 50) //sniper becomes regular
+ projectile_type = /obj/item/projectile/beam
+ if(51 to 60) //heavy becomes sniper
+ projectile_type = /obj/item/projectile/beam/sniper
+ if(61 to 80) //cannon becomes heavy
+ projectile_type = /obj/item/projectile/beam/heavylaser
+ if(81 to 100) //pulse becomes cannon
+ projectile_type = /obj/item/projectile/beam/heavylaser/cannon
+ user.visible_message("\The [src] dims slightly!", "\the [src] dims slightly!")
+ return
+ if(8) //10% chance of reducing the number of shots you have left, or giving you a limit if there isn't one
+ if(!remainingshots)
+ remainingshots = rand(1,40)
+ else
+ remainingshots = min(1, round(remainingshots/2))
+ user.visible_message("\The [src] lets out a faint pop.", "\the [src] lets out a faint pop.")
+ if(9) //10% chance of permanently reducing the cell's max charge
+ power_supply.maxcharge = power_supply.maxcharge/2
+ power_supply.charge = min(power_supply.charge, power_supply.maxcharge)
+ user.visible_message("\The [src] sparks,letting off a puff of smoke!", "\the [src] sparks,letting off a puff of smoke!")
+ var/turf/T = get_turf(src)
+ var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
+ sparks.set_up(2, 1, T)
+ sparks.start()
+ update_icon()
+ if(10) //10% chance of just straight-up breaking on the spot
+ burnout(user)
+ return
+*/
/obj/item/weapon/gun/energy/lasercannon
name = "laser cannon"
diff --git a/code/modules/projectiles/guns/energy/special_vr.dm b/code/modules/projectiles/guns/energy/special_vr.dm
index 7bb75dcf90..aaab881599 100644
--- a/code/modules/projectiles/guns/energy/special_vr.dm
+++ b/code/modules/projectiles/guns/energy/special_vr.dm
@@ -1,29 +1,104 @@
-/obj/item/weapon/gun/energy/ionrifle/pistol
- projectile_type = /obj/item/projectile/ion/pistol // still packs a punch but no AoE
- w_class = ITEMSIZE_NORMAL //CHOMP Edit.
- move_delay = 0 // CHOMPEdit: Pistols have move_delay of 0
-
-/obj/item/weapon/gun/energy/ionrifle/weak
- projectile_type = /obj/item/projectile/ion/small
-
-/obj/item/weapon/gun/energy/medigun //Adminspawn/ERT etc // CH edit - Changes ML3M to NERD
- name = "directed restoration system"
- desc = "The BL-3 'Phoenix' is an adaptation on the NERD 'Medbeam' design that channels the power of the beam into a single healing laser. It is highly energy-inefficient, but its medical power cannot be denied."
- force = 5
- icon_state = "medbeam"
- item_state = "medbeam"
- icon = 'icons/obj/gun_vr.dmi'
- item_icons = list(
- slot_l_hand_str = 'icons/mob/items/lefthand_guns_vr.dmi',
- slot_r_hand_str = 'icons/mob/items/righthand_guns_vr.dmi',
- )
- slot_flags = SLOT_BELT
- accuracy = 100
- fire_delay = 12
- fire_sound = 'sound/weapons/eluger.ogg'
-
- projectile_type = /obj/item/projectile/beam/medigun
-
- accept_cell_type = /obj/item/weapon/cell
- cell_type = /obj/item/weapon/cell/high
- charge_cost = 2500
\ No newline at end of file
+/obj/item/weapon/gun/energy/ionrifle/pistol
+ projectile_type = /obj/item/projectile/ion/pistol // still packs a punch but no AoE
+ w_class = ITEMSIZE_NORMAL //CHOMP Edit.
+ move_delay = 0 // CHOMPEdit: Pistols have move_delay of 0
+
+/obj/item/weapon/gun/energy/ionrifle/weak
+ projectile_type = /obj/item/projectile/ion/small
+
+/obj/item/weapon/gun/energy/medigun //Adminspawn/ERT etc // CH edit - Changes ML3M to NERD
+ name = "directed restoration system"
+ desc = "The BL-3 'Phoenix' is an adaptation on the NERD 'Medbeam' design that channels the power of the beam into a single healing laser. It is highly energy-inefficient, but its medical power cannot be denied."
+ force = 5
+ icon_state = "medbeam"
+ item_state = "medbeam"
+ icon = 'icons/obj/gun_vr.dmi'
+ item_icons = list(
+ slot_l_hand_str = 'icons/mob/items/lefthand_guns_vr.dmi',
+ slot_r_hand_str = 'icons/mob/items/righthand_guns_vr.dmi',
+ )
+ slot_flags = SLOT_BELT
+ accuracy = 100
+ fire_delay = 12
+ fire_sound = 'sound/weapons/eluger.ogg'
+
+ projectile_type = /obj/item/projectile/beam/medigun
+
+ accept_cell_type = /obj/item/weapon/cell
+ cell_type = /obj/item/weapon/cell/high
+ charge_cost = 2500
+
+/obj/item/weapon/gun/energy/bfgtaser
+ name = "9000-series Ball Lightning Taser"
+ desc = "The brainchild of Hephaestus Industries Civil Pacification Division, the BLT-9000 was intended for riot control but despite enthusiastic interest from law-enforcement agencies across the Commonwealth and beyond, its indiscriminate nature led to it being banned from civilian use in virtually all jurisdictions. As a result, most pieces are found in the hands of collectors."
+ icon = 'icons/obj/gun_vr.dmi'
+ icon_state = "BFG"
+ fire_sound = 'sound/effects/phasein.ogg'
+ item_state = "mhdhowitzer"
+ wielded_item_state = "mhdhowitzer-wielded" //Placeholder
+ slot_flags = SLOT_BELT|SLOT_BACK
+ projectile_type = /obj/item/projectile/bullet/BFGtaser
+ fire_delay = 20
+ w_class = ITEMSIZE_LARGE
+ one_handed_penalty = 90 // The thing's heavy and huge.
+ accuracy = 45
+ charge_cost = 2400 //yes, this bad boy empties an entire weapon cell in one shot. What of it?
+ var/spinning_up = FALSE
+
+/obj/item/weapon/gun/energy/bfgtaser/Fire(atom/target, mob/living/user, clickparams, pointblank=0, reflex=0)
+ if(spinning_up)
+ return
+ if(!power_supply || !power_supply.check_charge(charge_cost))
+ handle_click_empty(user)
+ return
+
+ playsound(src, 'sound/weapons/chargeup.ogg', 100, 1)
+ spinning_up = TRUE
+ update_icon()
+ user.visible_message("[user] starts charging the [src]!", \
+ "You start charging the [src]!")
+ if(do_after(user, 8, src))
+ spinning_up = FALSE
+ ..()
+ else
+ spinning_up = FALSE
+
+/obj/item/projectile/beam/stun/weak/BFG
+ fire_sound = 'sound/effects/sparks6.ogg'
+ hitsound = 'sound/effects/sparks4.ogg'
+ hitsound_wall = 'sound/effects/sparks7.ogg'
+
+/obj/item/projectile/bullet/BFGtaser
+ name = "lightning ball"
+ icon = 'icons/obj/projectiles_vr.dmi'
+ icon_state = "minitesla"
+ speed=5
+ damage = 100
+ damage_type = AGONY
+ check_armour = "energy"
+ embed_chance = 0
+ hitsound = 'sound/weapons/zapbang.ogg'
+ hitsound_wall = 'sound/weapons/effects/searwall.ogg'
+ var/zaptype = /obj/item/projectile/beam/stun/weak/BFG
+
+/obj/item/projectile/bullet/BFGtaser/process()
+ var/list/victims = list()
+ for(var/mob/living/M in living_mobs(world.view))
+ if(M != firer)
+ victims += M
+ if(LAZYLEN(victims))
+ var/target = pick(victims)
+ var/obj/item/projectile/P = new zaptype(src.loc)
+ P.launch_projectile_from_turf(target = target, target_zone = null, user = firer, params = null, angle_override = null, forced_spread = 0)
+ ..()
+
+/obj/item/projectile/bullet/BFGtaser/on_hit()
+ var/list/victims = list()
+ for(var/mob/living/M in living_mobs(world.view))
+ if(M != firer)
+ victims += M
+ if(LAZYLEN(victims))
+ for(var/target in victims)
+ var/obj/item/projectile/P = new zaptype(src.loc)
+ P.launch_projectile_from_turf(target = target, target_zone = null, user = firer, params = null, angle_override = null, forced_spread = 0)
+ ..()
diff --git a/code/modules/projectiles/guns/projectile/altevian_vr.dm b/code/modules/projectiles/guns/projectile/altevian_vr.dm
new file mode 100644
index 0000000000..29d4800fcd
--- /dev/null
+++ b/code/modules/projectiles/guns/projectile/altevian_vr.dm
@@ -0,0 +1,39 @@
+/obj/item/weapon/gun/projectile/altevian
+ name = "Altevian Rivet Repeater"
+ desc = "An offensive weapon designed by the altevians that is used for decompression and maximizes structural damage while also serving as a good method of personnel damage."
+ magazine_type = /obj/item/ammo_magazine/sam48
+ allowed_magazines = list(/obj/item/ammo_magazine/sam48)
+ projectile_type = /obj/item/projectile/bullet/sam48
+ icon_state = "altevian-repeater"
+ item_state = "altevian-repeater"
+ caliber = ".48"
+ load_method = MAGAZINE
+
+/obj/item/weapon/gun/projectile/altevian/update_icon()
+ if(ammo_magazine)
+ icon_state = initial(icon_state)
+ else
+ icon_state = "[initial(icon_state)]-e"
+
+/obj/item/ammo_magazine/sam48
+ name = "ammo clip (SAM .48)"
+ icon_state = "sam48"
+ desc = "Standard Altevian Munition clip, caliber .48."
+ caliber = ".48"
+ ammo_type = /obj/item/ammo_casing/sam48
+ mag_type = MAGAZINE
+ matter = list(MAT_STEEL = 240)
+ max_ammo = 5
+ multiple_sprites = 1
+
+/obj/item/ammo_casing/sam48
+ desc = "A .48 bolt casing."
+ caliber = ".48"
+ projectile_type = /obj/item/projectile/bullet/sam48
+ matter = list(MAT_STEEL = 30)
+
+/obj/item/projectile/bullet/sam48
+ fire_sound = 'sound/weapons/gunshot4.ogg'
+ icon_state = "sam48"
+ damage = 49
+ hud_state = "pistol_special"
diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm
index 5e87e05cfc..51e7827721 100644
--- a/code/modules/projectiles/guns/projectile/shotgun.dm
+++ b/code/modules/projectiles/guns/projectile/shotgun.dm
@@ -226,3 +226,18 @@
w_class = ITEMSIZE_NORMAL
force = 5
sawn_off = TRUE
+
+//Sjorgen Inertial Shotgun
+/obj/item/weapon/gun/projectile/shotgun/semi
+ name = "semi-automatic shotgun"
+ desc = "A shotgun with a simple, yet effective recoil inertia loading mechanism for semi-automatic fire. This gun uses 12 gauge ammunition."
+ description_fluff = "Looking back on yet another venerable design, Hedberg-Hammarstrom settled on a pattern of shotgun that both had the reliability of a well proven semi-automatic loading system in addition to a striking visual aesthetic that would be appealing to even the most discerning of firearm collectors."
+ icon_state = "sjorgen"
+ item_state = "shotgun"
+ w_class = ITEMSIZE_LARGE
+ caliber = "12g"
+ origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2)
+ slot_flags = SLOT_BACK
+ load_method = SINGLE_CASING
+ max_shells = 5
+ ammo_type = /obj/item/ammo_casing/a12g/beanbag
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index d363bc7ccf..15f8d24a5b 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -331,6 +331,26 @@
damage = 5
agony = 10
+
+//
+// Projectile Beam Definitions
+//
+
+/obj/item/projectile/beam/pointdefense
+ name = "point defense salvo"
+ icon_state = "laser"
+ damage = 15
+ damage_type = ELECTROCUTE //You should be safe inside a voidsuit
+ sharp = FALSE //"Wide" spectrum beam
+ light_color = COLOR_GOLD
+
+ excavation_amount = 200 // Good at shooting rocks
+
+ muzzle_type = /obj/effect/projectile/muzzle/pointdefense
+ tracer_type = /obj/effect/projectile/tracer/pointdefense
+ impact_type = /obj/effect/projectile/impact/pointdefense
+
+
/obj/item/projectile/beam/precursor //CHOMPedit added Precursor beam
name = "precursor beam"
icon_state = "alien beam"
diff --git a/code/modules/random_map/noise/ore.dm b/code/modules/random_map/noise/ore.dm
index 5eecf3b3e2..72d8e93b9f 100644
--- a/code/modules/random_map/noise/ore.dm
+++ b/code/modules/random_map/noise/ore.dm
@@ -48,20 +48,20 @@
continue
if(!priority_process) sleep(-1)
T.resources = list()
- T.resources["silicates"] = rand(3,5)
+ T.resources["sand"] = rand(3,5)
T.resources["carbon"] = rand(3,5)
var/current_cell = map[get_map_cell(x,y)]
if(current_cell < rare_val) // Surface metals.
- T.resources["hematite"] = rand(RESOURCE_MID_MIN, RESOURCE_HIGH_MAX)
+ T.resources["hematite"] = rand(RESOURCE_HIGH_MIN, RESOURCE_HIGH_MAX)
T.resources["gold"] = rand(RESOURCE_LOW_MIN, RESOURCE_LOW_MAX)
T.resources["silver"] = rand(RESOURCE_LOW_MIN, RESOURCE_LOW_MAX)
T.resources["uranium"] = rand(RESOURCE_LOW_MIN, RESOURCE_LOW_MAX)
T.resources["marble"] = rand(RESOURCE_LOW_MIN, RESOURCE_MID_MAX)
T.resources["diamond"] = 0
T.resources["phoron"] = 0
- T.resources["osmium"] = 0
- T.resources["hydrogen"] = 0
+ T.resources["platinum"] = 0
+ T.resources["mhydrogen"] = 0
T.resources["verdantium"] = 0
T.resources["lead"] = 0
//T.resources["copper"] = rand(RESOURCE_MID_MIN, RESOURCE_HIGH_MAX)
@@ -76,36 +76,36 @@
T.resources["silver"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
T.resources["uranium"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
T.resources["phoron"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
- T.resources["osmium"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
+ T.resources["platinum"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
T.resources["verdantium"] = rand(RESOURCE_LOW_MIN, RESOURCE_LOW_MAX)
T.resources["lead"] = rand(RESOURCE_LOW_MIN, RESOURCE_MID_MAX)
- T.resources["hydrogen"] = 0
+ T.resources["mhydrogen"] = 0
T.resources["diamond"] = 0
- T.resources["hematite"] = rand(RESOURCE_HIGH_MIN, RESOURCE_HIGH_MAX)
+ T.resources["hematite"] = 0
T.resources["marble"] = 0
//T.resources["copper"] = 0
//T.resources["tin"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
//T.resources["bauxite"] = 0
- T.resources["rutile"] = rand(RESOURCE_LOW_MIN, RESOURCE_MID_MAX)
+ T.resources["rutile"] = 0
//T.resources["void opal"] = 0
//T.resources["quartz"] = 0
//T.resources["painite"] = 0
else // Deep metals.
- T.resources["uranium"] = rand(RESOURCE_MID_MIN, RESOURCE_HIGH_MAX)
+ T.resources["uranium"] = rand(RESOURCE_LOW_MIN, RESOURCE_LOW_MAX)
T.resources["diamond"] = rand(RESOURCE_LOW_MIN, RESOURCE_LOW_MAX)
T.resources["verdantium"] = rand(RESOURCE_LOW_MIN, RESOURCE_MID_MAX)
T.resources["phoron"] = rand(RESOURCE_HIGH_MIN, RESOURCE_HIGH_MAX)
- T.resources["osmium"] = rand(RESOURCE_HIGH_MIN, RESOURCE_HIGH_MAX)
- T.resources["hydrogen"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
+ T.resources["platinum"] = rand(RESOURCE_HIGH_MIN, RESOURCE_HIGH_MAX)
+ T.resources["mhydrogen"] = rand(RESOURCE_MID_MIN, RESOURCE_MID_MAX)
T.resources["marble"] = rand(RESOURCE_MID_MIN, RESOURCE_HIGH_MAX)
T.resources["lead"] = rand(RESOURCE_LOW_MIN, RESOURCE_HIGH_MAX)
- T.resources["hematite"] = rand(RESOURCE_HIGH_MIN, RESOURCE_HIGH_MAX)
- T.resources["gold"] = rand(RESOURCE_MID_MIN, RESOURCE_HIGH_MAX)
- T.resources["silver"] = rand(RESOURCE_MID_MIN, RESOURCE_HIGH_MAX)
+ T.resources["hematite"] = 0
+ T.resources["gold"] = 0
+ T.resources["silver"] = 0
//T.resources["copper"] = 0
//T.resources["tin"] = 0
//T.resources["bauxite"] = 0
- T.resources["rutile"] = rand(RESOURCE_MID_MIN, RESOURCE_HIGH_MAX)
+ T.resources["rutile"] = 0
//T.resources["void opal"] = 0
//T.resources["quartz"] = 0
//T.resources["painite"] = 0
@@ -117,4 +117,4 @@
else if(value < deep_val)
return "R"
else
- return "D"
\ No newline at end of file
+ return "D"
diff --git a/code/modules/reagents/machinery/dispenser/cartridge_presets.dm b/code/modules/reagents/machinery/dispenser/cartridge_presets.dm
index f0515d3904..07c41ba940 100644
--- a/code/modules/reagents/machinery/dispenser/cartridge_presets.dm
+++ b/code/modules/reagents/machinery/dispenser/cartridge_presets.dm
@@ -139,6 +139,10 @@
spawn_reagent = "greentea"
/obj/item/weapon/reagent_containers/chem_disp_cartridge/decaf
spawn_reagent = "decaf"
+/obj/item/weapon/reagent_containers/chem_disp_cartridge/chaitea
+ spawn_reagent = "chaitea"
+/obj/item/weapon/reagent_containers/chem_disp_cartridge/decafchai
+ spawn_reagent = "chaiteadecaf"
// ERT
/obj/item/weapon/reagent_containers/chem_disp_cartridge/inaprov
diff --git a/code/modules/reagents/machinery/dispenser/dispenser_presets.dm b/code/modules/reagents/machinery/dispenser/dispenser_presets.dm
index ab54cd06b4..916c506a2e 100644
--- a/code/modules/reagents/machinery/dispenser/dispenser_presets.dm
+++ b/code/modules/reagents/machinery/dispenser/dispenser_presets.dm
@@ -144,5 +144,7 @@
/obj/item/weapon/reagent_containers/chem_disp_cartridge/lime,
/obj/item/weapon/reagent_containers/chem_disp_cartridge/berry,
/obj/item/weapon/reagent_containers/chem_disp_cartridge/greentea,
- /obj/item/weapon/reagent_containers/chem_disp_cartridge/decaf
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/decaf,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/chaitea,
+ /obj/item/weapon/reagent_containers/chem_disp_cartridge/decafchai
)
diff --git a/code/modules/reagents/machinery/dispenser/reagent_tank.dm b/code/modules/reagents/machinery/dispenser/reagent_tank.dm
index 7f591217c8..13dc59c027 100644
--- a/code/modules/reagents/machinery/dispenser/reagent_tank.dm
+++ b/code/modules/reagents/machinery/dispenser/reagent_tank.dm
@@ -473,9 +473,9 @@
icon_state = "oiltank"
amount_per_transfer_from_this = 120
-/obj/structure/reagent_dispensers/cookingoil/New()
- ..()
- reagents.add_reagent("cookingoil",5000)
+/obj/structure/reagent_dispensers/cookingoil/Initialize()
+ . = ..()
+ reagents.add_reagent("cookingoil",5000)
/obj/structure/reagent_dispensers/cookingoil/bullet_act(var/obj/item/projectile/Proj)
if(Proj.get_structure_damage())
diff --git a/code/modules/reagents/reactions/instant/instant.dm b/code/modules/reagents/reactions/instant/instant.dm
index 2bb809ccef..299ec6d448 100644
--- a/code/modules/reagents/reactions/instant/instant.dm
+++ b/code/modules/reagents/reactions/instant/instant.dm
@@ -689,6 +689,15 @@
required_reagents = list("liquidcarpeto" = 2, "plasticide" = 1)
carpet_type = /obj/item/stack/tile/carpet/oracarpet
+/decl/chemical_reaction/instant/concrete
+ name = "Concrete"
+ id = "concretereagent"
+ required_reagents = list("calcium" = 2, "silicate" = 2, "water" = 2)
+ result_amount = 1
+
+/decl/chemical_reaction/instant/concrete/on_reaction(var/datum/reagents/holder, var/created_volume)
+ new /obj/item/stack/material/concrete(get_turf(holder.my_atom), created_volume)
+ return
/* Grenade reactions */
@@ -1232,4 +1241,4 @@
id = "spidertoxin_neutral"
result = "protein"
required_reagents = list("enzyme" = 1, "spidertoxin" = 1, "sifsap" = 1)
- result_amount = 1
\ No newline at end of file
+ result_amount = 1
diff --git a/code/modules/reagents/reactions/instant/instant_ch.dm b/code/modules/reagents/reactions/instant/instant_ch.dm
index 74b1ce1d1d..b3e2ab0cba 100644
--- a/code/modules/reagents/reactions/instant/instant_ch.dm
+++ b/code/modules/reagents/reactions/instant/instant_ch.dm
@@ -4,7 +4,7 @@
result = "aphrodisiac"
required_reagents = list("carbon" = 2, "hydrogen" = 2, "oxygen" = 2, "water" = 1)
result_amount = 6
-
+
/decl/chemical_reaction/instant/claridyl
name = "claridyl"
id = "claridyl"
@@ -37,7 +37,7 @@
id = "eden_snake"
result = "eden_snake"
required_reagents = list("eden" = 1, "ethanol" = 1)
-
+
/decl/chemical_reaction/instant/tercozolam
id = "tercozolam"
result = "tercozolam"
@@ -48,8 +48,8 @@
name = "Peridaxon"
id = "peridaxon_ch"
result = "peridaxon"
- required_reagents = list("cordradaxon" = 1, "gastirodaxon" = 1, "hepanephrodaxon" = 1, "respirodaxon" = 1)
- result_amount = 12 //More phoron-efficient alternative recipe.
+ required_reagents = list("cordradaxon" = 1, "gastirodaxon" = 1, "hepanephrodaxon" = 1, "respirodaxon" = 1)
+ result_amount = 12 //More phoron-efficient alternative recipe.
/decl/chemical_reaction/instant/sorbitol
name = "Sorbitol"
@@ -78,7 +78,7 @@
name = "Bullvalene"
id = "bullvalene"
result = "bullvalene"
- required_reagents = list("dermaline" = 1, "orangesap" = 1, "Copper" = 1)
+ required_reagents = list("dermaline" = 1, "orangesap" = 1, "copper" = 1)
result_amount = 1
/decl/chemical_reaction/instant/nutrient
@@ -87,16 +87,16 @@
result = "nutriment"
required_reagents = list("purplesap" = 1, "orangesap" = 1, "bluesap" = 1)
result_amount = 3
-
+
/////SERAZINE RECIPES//////
-/decl/chemical_reaction/instant/alizine
- name = "Alizine"
- id = "alizine"
- result = "alizine"
+/decl/chemical_reaction/instant/alizene
+ name = "Alizene"
+ id = "alizene"
+ result = "alizene"
required_reagents = list("bicaridine" = 1, "serazine" = 1, "tungsten" = 1)
result_amount = 3
-
+
/////GENDER CHANGE RECIPES/////
/decl/chemical_reaction/instant/change_drug/male
@@ -119,7 +119,7 @@
result = "change_drug_intersex"
required_reagents = list("change_drug_male" = 1, "change_drug_female" = 1)
result_amount = 1
-
+
// Frost oil reactions for material sheets
/decl/chemical_reaction/instant/solidification/aluminium
name = "Solid Aluminium"
@@ -132,7 +132,7 @@
id = "solidcopper"
required_reagents = list("frostoil" = 5, "copper" = REAGENTS_PER_SHEET)
sheet_to_give = /obj/item/stack/material/copper
-
+
//YW stuff
/decl/chemical_reaction/instant/benzilate
name = "Benzilate"
@@ -147,3 +147,28 @@
result = "phenethylamine"
required_reagents = list("paroxetine" = 1, "benzilate" = 1)
result_amount = 2
+
+// Xenochem stuff
+/decl/chemical_reaction/instant/xenolazarus // Moved here because upstream axed it and this file cannot conflict
+ name = "Discount Lazarus"
+ id = "discountlazarus"
+ result = null
+ required_reagents = list("monstertamer" = 5, "clonexadone" = 5)
+
+/decl/chemical_reaction/instant/xenolazarus/on_reaction(var/datum/reagents/holder, var/created_volume) //literally all this does is mash the regenerate button
+ if(ishuman(holder.my_atom))
+ var/mob/living/carbon/human/H = holder.my_atom
+ if(H.stat == DEAD && (/mob/living/carbon/human/proc/reconstitute_form in H.verbs)) //no magical regen for non-regenners, and can't force the reaction on live ones
+ if(H.hasnutriment()) // make sure it actually has the conditions to revive
+ if(H.revive_ready >= 1) // if it's not reviving, start doing so
+ H.revive_ready = REVIVING_READY // overrides the normal cooldown
+ H.visible_message("[H] shudders briefly, then relaxes, faint movements stirring within.")
+ H.chimera_regenerate()
+ else if (/mob/living/carbon/human/proc/hatch in H.verbs)// already reviving, check if they're ready to hatch
+ H.chimera_hatch()
+ H.visible_message("[H] violently convulses and then bursts open, revealing a new, intact copy in the pool of viscera.
") // Hope you were wearing waterproofs, doc... + H.adjustBrainLoss(10) // they're reviving from dead, so take 10 brainloss + else //they're already reviving but haven't hatched. Give a little message to tell them to wait. + H.visible_message("[H] stirs faintly, but doesn't appear to be ready to wake up yet.") + else + H.visible_message("[H] twitches for a moment, but remains still.") // no nutriment diff --git a/code/modules/reagents/reactions/instant/instant_vr.dm b/code/modules/reagents/reactions/instant/instant_vr.dm index 4691fd5a4e..ca91c19266 100644 --- a/code/modules/reagents/reactions/instant/instant_vr.dm +++ b/code/modules/reagents/reactions/instant/instant_vr.dm @@ -102,31 +102,6 @@ /////////////////////////////////////////////////////////////////////////////////// /// Miscellaneous Reactions -/decl/chemical_reaction/instant/xenolazarus - name = "Discount Lazarus" - id = "discountlazarus" - result = null - required_reagents = list("monstertamer" = 5, "clonexadone" = 5) - -/decl/chemical_reaction/instant/xenolazarus/on_reaction(var/datum/reagents/holder, var/created_volume) //literally all this does is mash the regenerate button - if(ishuman(holder.my_atom)) - var/mob/living/carbon/human/H = holder.my_atom - if(H.stat == DEAD && (/mob/living/carbon/human/proc/reconstitute_form in H.verbs)) //no magical regen for non-regenners, and can't force the reaction on live ones - if(H.hasnutriment()) // make sure it actually has the conditions to revive - if(H.revive_ready >= 1) // if it's not reviving, start doing so - H.revive_ready = REVIVING_READY // overrides the normal cooldown - H.visible_message("[H] shudders briefly, then relaxes, faint movements stirring within.") - H.chimera_regenerate() - else if (/mob/living/carbon/human/proc/hatch in H.verbs)// already reviving, check if they're ready to hatch - H.chimera_hatch() - H.visible_message("[H] violently convulses and then bursts open, revealing a new, intact copy in the pool of viscera.
") // Hope you were wearing waterproofs, doc... - H.adjustBrainLoss(10) // they're reviving from dead, so take 10 brainloss - else //they're already reviving but haven't hatched. Give a little message to tell them to wait. - H.visible_message("[H] stirs faintly, but doesn't appear to be ready to wake up yet.") - else - H.visible_message("[H] twitches for a moment, but remains still.") // no nutriment - - /decl/chemical_reaction/instant/foam/softdrink required_reagents = list("cola" = 1, "mint" = 1) @@ -181,6 +156,13 @@ catalysts = list("phoron" = 5) result_amount = 3 +/decl/chemical_reaction/instant/prussian_blue + name = "Prussian Blue" + id = "prussian_blue" + result = "prussian_blue" + required_reagents = list("carbon" = 3, "iron" = 1, "nitrogen" = 3) + result_amount = 7 + /////////////////////////////////////////////////////////////////////////////////// /// Reagent colonies. /decl/chemical_reaction/instant/meatcolony diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 8548fdd36d..0e21050bca 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -49,7 +49,8 @@ /obj/structure/frame, /obj/machinery/radiocarbon_spectrometer, /obj/machinery/portable_atmospherics/powered/reagent_distillery, - /obj/machinery/feeder + /obj/machinery/feeder, + /obj/machinery/chemical_synthesizer //CHOMPedit, ) //CHOMP Addition for feeder in the above list. I am paranoid about comments within lists so this is outside. @@ -263,6 +264,16 @@ /obj/item/weapon/reagent_containers/glass/beaker/sulphuric prefill = list("sacid" = 60) +/obj/item/weapon/reagent_containers/glass/beaker/stopperedbottle + name = "stoppered bottle" + desc = "A stoppered bottle for keeping beverages fresh." + icon_state = "stopperedbottle" + center_of_mass = list("x" = 16,"y" = 13) + volume = 120 + amount_per_transfer_from_this = 10 + possible_transfer_amounts = list(5,10,15,25,30,60,120) + flags = OPENCONTAINER + /obj/item/weapon/reagent_containers/glass/bucket desc = "It's a bucket." name = "bucket" diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 9072ffafc8..da64f6a808 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -251,7 +251,7 @@ name = "purity hypo" desc = "A refined version of the standard autoinjector, allowing greater capacity. This variant excels at \ resolving viruses, infections, radiation, and genetic maladies." - filled_reagents = list("spaceacillin" = 9, "arithrazine" = 5, "ryetalyn" = 1) + filled_reagents = list("spaceacillin" = 4, "arithrazine" = 5, "prussian_blue" = 5, "ryetalyn" = 1) /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain name = "pain hypo" diff --git a/code/modules/reagents/reagent_containers/syringes_vr.dm b/code/modules/reagents/reagent_containers/syringes_vr.dm index 83c5bacaef..89d81d1f18 100644 --- a/code/modules/reagents/reagent_containers/syringes_vr.dm +++ b/code/modules/reagents/reagent_containers/syringes_vr.dm @@ -85,7 +85,7 @@ //Allow for capped syringes /obj/item/weapon/reagent_containers/syringe/update_icon() - cut_overlays(src) + cut_overlays() var/matrix/tf = matrix() if(isstorage(loc)) @@ -101,12 +101,11 @@ icon_state = "capped" return - var/list/new_overlays = list() var/rounded_vol = round(reagents.total_volume, round(reagents.maximum_volume / 3)) if(reagents.total_volume) filling = image(icon, src, "filler[rounded_vol]") filling.color = reagents.get_color() - new_overlays += filling + add_overlay(filling) if(ismob(loc)) var/injoverlay @@ -115,9 +114,8 @@ injoverlay = "draw" if (SYRINGE_INJECT) injoverlay = "inject" - new_overlays += injoverlay + add_overlay(injoverlay) - add_overlay(new_overlays) icon_state = "[rounded_vol]" item_state = "syringe_[rounded_vol]" diff --git a/code/modules/reagents/reagents/_reagents.dm b/code/modules/reagents/reagents/_reagents.dm index 384696bb56..39b75494ca 100644 --- a/code/modules/reagents/reagents/_reagents.dm +++ b/code/modules/reagents/reagents/_reagents.dm @@ -168,7 +168,7 @@ affect_ingest(M, alien, removed * ingest_abs_mult) if(CHEM_TOUCH) affect_touch(M, alien, removed) - if(overdose && (volume > overdose * M?.species.chemOD_threshold) && (active_metab.metabolism_class != CHEM_TOUCH && !can_overdose_touch)) + if(overdose && (volume > overdose * M?.species.chemOD_threshold) && (active_metab.metabolism_class != CHEM_TOUCH || can_overdose_touch)) overdose(M, alien, removed) if(M.species.allergens & allergen_type) //uhoh, we can't handle this! M.add_chemical_effect(CE_ALLERGEN, allergen_factor * removed) diff --git a/code/modules/reagents/reagents/core.dm b/code/modules/reagents/reagents/core.dm index 901b803cbb..0d803b63d3 100644 --- a/code/modules/reagents/reagents/core.dm +++ b/code/modules/reagents/reagents/core.dm @@ -46,12 +46,12 @@ var/effective_dose = dose if(issmall(M)) effective_dose *= 2 - var/is_vampire = 0 //VOREStation Edit START + var/is_vampire = FALSE //VOREStation Edit START if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.species.organic_food_coeff == 0) - H.adjust_nutrition(removed) - is_vampire = 1 //VOREStation Edit END + if(H.species.bloodsucker) + H.adjust_nutrition(removed*30) + is_vampire = TRUE //VOREStation Edit END if(alien == IS_SLIME) // Treat it like nutriment for the jello, but not equivalent. if(data["species"] == M.species.name) // Unless it's Promethean goo, then refill this one's goo. M.inject_blood(src, volume * volume_mod) @@ -65,10 +65,10 @@ return if(effective_dose > 5) - if(is_vampire == 0) //VOREStation Edit. + if(!is_vampire) //VOREStation Edit. M.adjustToxLoss(removed) //VOREStation Edit. if(effective_dose > 15) - if(is_vampire == 0) //VOREStation Edit. + if(!is_vampire) //VOREStation Edit. M.adjustToxLoss(removed) //VOREStation Edit. if(data && data["virus2"]) var/list/vlist = data["virus2"] diff --git a/code/modules/reagents/reagents/dispenser.dm b/code/modules/reagents/reagents/dispenser.dm index 8e7a5d1862..90d8ea9e2a 100644 --- a/code/modules/reagents/reagents/dispenser.dm +++ b/code/modules/reagents/reagents/dispenser.dm @@ -112,18 +112,15 @@ L.adjust_fire_stacks(amount / 15) /datum/reagent/ethanol/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) //This used to do just toxin. That's boring. Let's make this FUN. - if(issmall(M)) removed *= 2 - var/strength_mod = 3 * M.species.alcohol_mod //Alcohol is 3x stronger when injected into the veins. - if(alien == IS_SKRELL) - strength_mod *= 5 - if(alien == IS_TAJARA) - strength_mod *= 1.25 - if(alien == IS_UNATHI) - strength_mod *= 0.75 - if(alien == IS_DIONA) - strength_mod = 0 + if(issmall(M)) + removed *= 2 + if(alien == IS_SLIME) - strength_mod *= 2 // VOREStation Edit - M.adjustToxLoss(removed) + M.adjustToxLoss(removed) //Sterilizing, if only by a little bit. Also already doubled above. + + var/strength_mod = 3 * M.species.chem_strength_alcohol //Alcohol is 3x stronger when injected into the veins. + if(!strength_mod) + return M.add_chemical_effect(CE_ALCOHOL, 1) var/effective_dose = dose * strength_mod * (1 + volume/60) //drinking a LOT will make you go down faster @@ -156,36 +153,32 @@ M.hallucination = max(M.hallucination, halluci*3) /datum/reagent/ethanol/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) - if(issmall(M)) removed *= 2 + + if(issmall(M)) + removed *= 2 + if(!(M.species.allergens & allergen_type)) //assuming it doesn't cause a horrible reaction, we get the nutrition effects M.adjust_nutrition(nutriment_factor * removed) - var/strength_mod = 1 * M.species.alcohol_mod - if(alien == IS_SKRELL) - strength_mod *= 5 - if(alien == IS_TAJARA) - strength_mod *= 1.25 - if(alien == IS_UNATHI) - strength_mod *= 0.75 - if(alien == IS_DIONA) - strength_mod = 0 - if(alien == IS_SLIME) - strength_mod *= 2 // VOREStation Edit - M.adjustToxLoss(removed * 2) + + var/effective_dose = dose * M.species.chem_strength_alcohol + if(!effective_dose) + return M.add_chemical_effect(CE_ALCOHOL, 1) - if(dose * strength_mod >= strength) // Early warning + if(effective_dose >= strength) // Early warning M.make_dizzy(6) // It is decreased at the speed of 3 per tick - if(dose * strength_mod >= strength * 2) // Slurring + if(effective_dose >= strength * 2) // Slurring M.slurring = max(M.slurring, 30) - if(dose * strength_mod >= strength * 3) // Confusion - walking in random directions + if(effective_dose >= strength * 3) // Confusion - walking in random directions M.Confuse(20) - if(dose * strength_mod >= strength * 4) // Blurry vision + if(effective_dose >= strength * 4) // Blurry vision M.eye_blurry = max(M.eye_blurry, 10) - if(dose * strength_mod >= strength * 5) // Drowsyness - periodically falling asleep + if(effective_dose >= strength * 5) // Drowsyness - periodically falling asleep M.drowsyness = max(M.drowsyness, 20) - if(dose * strength_mod >= strength * 6) // Toxic dose + if(effective_dose >= strength * 6) // Toxic dose M.add_chemical_effect(CE_ALCOHOL_TOXIC, toxicity) - if(dose * strength_mod >= strength * 7) // Pass out + if(effective_dose >= strength * 7) // Pass out M.Paralyse(20) M.Sleeping(30) diff --git a/code/modules/reagents/reagents/drugs.dm b/code/modules/reagents/reagents/drugs.dm index 3dba29d6f7..28a42a5b48 100644 --- a/code/modules/reagents/reagents/drugs.dm +++ b/code/modules/reagents/reagents/drugs.dm @@ -143,6 +143,7 @@ M.druggy = max(M.druggy, 30) + var/drug_strength = 20 var/effective_dose = dose if(issmall(M)) effective_dose *= 2 if(effective_dose < 1 * threshold) @@ -156,6 +157,7 @@ M.make_jittery(5) M.make_dizzy(5) M.druggy = max(M.druggy, 35) + M.hallucination = max(M.hallucination, drug_strength * threshold) if(prob(5) && prob_proc == TRUE) M.emote(pick("twitch", "giggle")) prob_proc = FALSE @@ -164,6 +166,7 @@ M.make_jittery(10) M.make_dizzy(10) M.druggy = max(M.druggy, 40) + M.hallucination = max(M.hallucination, drug_strength * threshold) if(prob(10) && prob_proc == TRUE) M.emote(pick("twitch", "giggle")) prob_proc = FALSE diff --git a/code/modules/reagents/reagents/food_drinks_vr.dm b/code/modules/reagents/reagents/food_drinks_vr.dm index 46cece483e..552fae5d79 100644 --- a/code/modules/reagents/reagents/food_drinks_vr.dm +++ b/code/modules/reagents/reagents/food_drinks_vr.dm @@ -140,7 +140,7 @@ M.adjust_nutrition(alt_nutriment_factor * removed) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.feral > 0 && H.nutrition > 100 && H.traumatic_shock < min(60, H.nutrition/10) && H.jitteriness < 100) // same check as feral triggers to stop them immediately re-feralling + if(H.feral > 0 && H.nutrition > 150 && H.traumatic_shock < 20 && H.jitteriness < 100) //Same check as feral triggers to stop them immediately re-feralling H.feral -= removed * 3 // should calm them down quick, provided they're actually in a state to STAY calm. if (H.feral <=0) //check if they're unferalled H.feral = 0 @@ -523,6 +523,7 @@ color = "#caa3c9" /datum/reagent/nutriment/protein/brainzsnax/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) + ..() if(prob(5) && !(alien == IS_CHIMERA || alien == IS_SLIME || alien == IS_PLANT || alien == IS_DIONA || alien == IS_SHADEKIN && !M.isSynthetic())) M.adjustBrainLoss(removed) //Any other species risks prion disease. M.Confuse(5) @@ -530,7 +531,7 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.feral > 0 && H.nutrition > 100 && H.traumatic_shock < min(60, H.nutrition/10) && H.jitteriness < 100) //Same check as feral triggers to stop them immediately re-feralling + if(H.feral > 0 && H.nutrition > 150 && H.traumatic_shock < 20 && H.jitteriness < 100) //Same check as feral triggers to stop them immediately re-feralling H.feral -= removed * 3 //Should calm them down quick, provided they're actually in a state to STAY calm. if(H.feral <=0) //Check if they're unferalled H.feral = 0 diff --git a/code/modules/reagents/reagents/medicine.dm b/code/modules/reagents/reagents/medicine.dm index 42b7969e4d..897c125b45 100644 --- a/code/modules/reagents/reagents/medicine.dm +++ b/code/modules/reagents/reagents/medicine.dm @@ -1128,6 +1128,7 @@ if(alien == IS_DIONA) return M.radiation = max(M.radiation - 30 * removed * M.species.chem_strength_heal, 0) + M.accumulated_rads = max(M.accumulated_rads - 30 * removed * M.species.chem_strength_heal, 0) /datum/reagent/arithrazine name = "Arithrazine" @@ -1145,6 +1146,7 @@ if(alien == IS_DIONA) return M.radiation = max(M.radiation - 70 * removed * M.species.chem_strength_heal, 0) + M.accumulated_rads = max(M.accumulated_rads - 70 * removed * M.species.chem_strength_heal, 0) M.adjustToxLoss(-10 * removed) if(prob(60)) M.take_organ_damage(4 * removed, 0) diff --git a/code/modules/reagents/reagents/medicine_ch.dm b/code/modules/reagents/reagents/medicine_ch.dm index 0f8bf08a3e..26daefc6fe 100644 --- a/code/modules/reagents/reagents/medicine_ch.dm +++ b/code/modules/reagents/reagents/medicine_ch.dm @@ -142,7 +142,7 @@ /datum/reagent/bullvalene //This is for the third sap. It converts Brute Oxy and burn into slightly less toxins. name = "bullvalene" id = "bullvalene" - description = "witty pending description. Converts brute and burn into toxin. Or at least is supposed to." + description = "A catalytic chemical that can treat a wide variety of ailments at the cost of toxifying the host's body." taste_description = "sulfur" reagent_state = LIQUID color = "#163851" diff --git a/code/modules/reagents/reagents/medicine_vr.dm b/code/modules/reagents/reagents/medicine_vr.dm index 2d336597fb..fa72ab17a5 100644 --- a/code/modules/reagents/reagents/medicine_vr.dm +++ b/code/modules/reagents/reagents/medicine_vr.dm @@ -94,3 +94,22 @@ M.remove_a_modifier_of_type(/datum/modifier/resleeving_sickness) M.remove_a_modifier_of_type(/datum/modifier/faux_resleeving_sickness) */ //CHOMPStation removal end + + + +/datum/reagent/prussian_blue //We don't have iodine, so prussian blue we go. + name = "Prussian Blue" + id = "prussian_blue" + description = "Prussian Blue is an medication used to temporarily pause the effects of radiation poisoning to allow for treatment. Does not treat radiation sickness on its own." + taste_description = "salt" + reagent_state = SOLID + color = "#003153" //Blue! + metabolism = REM * 0.25//20 ticks to do things per unit injected. This means injecting 30u will give you 10 minutes to do what you need. + overdose = REAGENTS_OVERDOSE + scannable = 1 + +/datum/reagent/prussian_blue/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + if(alien == IS_DIONA) + return + if(prob(10)) //Miniscule chance of removing some toxins. + M.adjustToxLoss(-10 * removed) diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index 1996a71358..335ed4240a 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -315,6 +315,13 @@ conveyors += C return +//CHOMPedit: Conveyor belts can be fast :) + if(istype(I, /obj/item/weapon/tool/wirecutters)) + if(panel_open) + toggle_speed() + to_chat(user, "You adjust the speed of the conveyor switch.") + return +//CHOMPedit End /obj/machinery/conveyor_switch/oneway var/convdir = 1 //Set to 1 or -1 depending on which way you want the convayor to go. (In other words keep at 1 and set the proper dir on the belts.) desc = "A conveyor control switch. It appears to only go in one direction." diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 662295e578..a5e95899f5 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -1539,6 +1539,12 @@ if(trunk) trunk.linked = src // link the pipe trunk to self +/obj/structure/disposaloutlet/Destroy() + var/obj/structure/disposalpipe/trunk/trunk = locate() in loc + if(trunk && trunk.linked == src) + trunk.linked = null + return ..() + // expel the contents of the holder object, then delete it // called when the holder exits the outlet /obj/structure/disposaloutlet/proc/expel(var/obj/structure/disposalholder/H) diff --git a/code/modules/research/designs/circuit_assembly.dm b/code/modules/research/designs/circuit_assembly.dm index c637e450d2..e9271d6d5c 100644 --- a/code/modules/research/designs/circuit_assembly.dm +++ b/code/modules/research/designs/circuit_assembly.dm @@ -71,15 +71,61 @@ build_path = /obj/item/device/electronic_assembly/large sort_string = "UDAAC" -/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone - name = "Drone custom assembly" +// CHOMPStation Edit Start +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_a + name = "type-a electronic drone assembly" desc = "A customizable assembly optimized for autonomous devices." - id = "assembly-drone" + id = "assembly-drone-a" req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) materials = list(MAT_STEEL = 30000) build_path = /obj/item/device/electronic_assembly/drone sort_string = "UDAAD" +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_b + name = "type-b electronic drone assembly" + desc = "It's a case, for building mobile electronics with. This one is armed and dangerous." + id = "assembly-drone-b" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(MAT_STEEL = 30000) + build_path = /obj/item/device/electronic_assembly/drone/arms + sort_string = "UDAAD" + +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_c + name = "type-c electronic drone assembly" + desc = "It's a case, for building mobile electronics with. This one resembles a Securitron." + id = "assembly-drone-c" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(MAT_STEEL = 30000) + build_path = /obj/item/device/electronic_assembly/drone/secbot + sort_string = "UDAAD" + +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_d + name = "type-d electronic drone assembly" + desc = "It's a case, for building mobile electronics with. This one resembles a Medibot" + id = "assembly-drone-d" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(MAT_STEEL = 30000) + build_path = /obj/item/device/electronic_assembly/drone/medbot + sort_string = "UDAAD" + +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_e + name = "type-e electronic drone assembly" + desc = "It's a case, for building mobile electronics with. This one has a generic bot design." + id = "assembly-drone-e" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(MAT_STEEL = 30000) + build_path = /obj/item/device/electronic_assembly/drone/genbot + sort_string = "UDAAD" +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_f + name = "type-f electronic drone assembly" + desc = "It's a case, for building mobile electronics with. This one has a hominoid design." + id = "assembly-drone-f" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(MAT_STEEL = 30000) + build_path = /obj/item/device/electronic_assembly/drone/android + sort_string = "UDAAD" +// CHOMPStation Edit End + /datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_device name = "Device custom assembly" desc = "An customizable assembly designed to interface with other devices." @@ -96,4 +142,4 @@ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 3, TECH_BIO = 5) materials = list(MAT_STEEL = 2000) build_path = /obj/item/weapon/implant/integrated_circuit - sort_string = "UDAAF" \ No newline at end of file + sort_string = "UDAAF" diff --git a/code/modules/research/designs/circuits/circuits.dm b/code/modules/research/designs/circuits/circuits.dm index f3a7e396ab..933cd26091 100644 --- a/code/modules/research/designs/circuits/circuits.dm +++ b/code/modules/research/designs/circuits/circuits.dm @@ -676,6 +676,20 @@ CIRCUITS BELOW build_path = /obj/item/weapon/circuitboard/microwave/advanced sort_string = "HACAA" +/datum/design/circuit/pointdefense + name = "point defense battery" + id = "pointdefense" + req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 3, TECH_COMBAT = 4) + build_path = /obj/item/weapon/circuitboard/pointdefense + sort_string = "OAABA" + +/datum/design/circuit/pointdefense_control + name = "point defense control" + id = "pointdefense_control" + req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3, TECH_COMBAT = 2) + build_path = /obj/item/weapon/circuitboard/pointdefense_control + sort_string = "OAABB" + /datum/design/circuit/shield_generator name = "shield generator" id = "shield_generator" diff --git a/code/modules/research/designs/medical_vr.dm b/code/modules/research/designs/medical_vr.dm index 30641fbed2..aaf9c184e6 100644 --- a/code/modules/research/designs/medical_vr.dm +++ b/code/modules/research/designs/medical_vr.dm @@ -30,6 +30,14 @@ build_path = /obj/item/weapon/reagent_containers/hypospray/science sort_string = "KCAVB" +/datum/design/item/medical/recombobray + name = "recombobulation ray" + desc = "The Type Gamma Medical Recombobulation ray! A mysterious looking ray gun! It works to change people who have had their form significantly altered back into their original forms!" + id = "recombobray" + req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 3, TECH_POWER = 4, TECH_BIO = 5, TECH_BLUESPACE = 4) //Not like these matter. *Glares at circuit printer.* + materials = list(MAT_STEEL = 1000, MAT_GLASS = 2000, MAT_URANIUM = 500, MAT_PHORON = 1500) + build_path = /obj/item/weapon/gun/energy/mouseray/medical + sort_string = "KCAVC" // ML-3M medigun and cells // CH edit - turns ML3M to NERD, removes some overtuned cells. diff --git a/code/modules/research/designs/precursor.dm b/code/modules/research/designs/precursor.dm index bb6e98353f..24f888f722 100644 --- a/code/modules/research/designs/precursor.dm +++ b/code/modules/research/designs/precursor.dm @@ -87,3 +87,7 @@ req_tech = list(TECH_MATERIAL = 7, TECH_BLUESPACE = 5, TECH_MAGNET = 6, TECH_PHORON = 3, TECH_ARCANE = 1, TECH_PRECURSOR = 2) build_path = /obj/random/janusmodule sort_string = "ZBBAA" + +/datum/design/item/precursor/janusmodule/Fabricate(var/newloc, var/fabricator) + var/type_to_spawn = pick(subtypesof(/obj/item/weapon/circuitboard/mecha/imperion)) + return new type_to_spawn(newloc) \ No newline at end of file diff --git a/code/modules/research/mechfab_designs.dm b/code/modules/research/mechfab_designs.dm index 9901606b8b..ab4b3abba8 100644 --- a/code/modules/research/mechfab_designs.dm +++ b/code/modules/research/mechfab_designs.dm @@ -813,13 +813,21 @@ build_path = /obj/item/weapon/vehicle_assembly/spacebike /datum/design/item/mechfab/vehicle/quadbike_chassis - name = "Quadbike Chassis" - desc = "A space-bike's un-assembled frame." + name = "Quad bike Chassis" + desc = "A quad bike's un-assembled frame." id = "vehicle_chassis_quadbike" req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 6, TECH_MAGNET = 3, TECH_POWER = 2) materials = list(MAT_STEEL = 15000, MAT_SILVER = 3000, MAT_PLASTIC = 3000, MAT_OSMIUM = 1000) build_path = /obj/item/weapon/vehicle_assembly/quadbike +/datum/design/item/mechfab/vehicle/snowmobile_chassis + name = "Snowmobile Chassis" + desc = "A snowmobile's un-assembled frame." + id = "vehicle_chassis_snowmobile" + req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 6, TECH_MAGNET = 3, TECH_POWER = 2) + materials = list(MAT_STEEL = 12000, MAT_SILVER = 3000, MAT_PLASTIC = 3000, MAT_OSMIUM = 1000) + build_path = /obj/item/weapon/vehicle_assembly/snowmobile + /* * Rigsuits */ diff --git a/code/modules/resleeving/autoresleever.dm b/code/modules/resleeving/autoresleever.dm index 275c2a14e5..b902df6796 100644 --- a/code/modules/resleeving/autoresleever.dm +++ b/code/modules/resleeving/autoresleever.dm @@ -74,7 +74,7 @@ return var/client/ghost_client = ghost.client - + if(!is_alien_whitelisted(ghost, GLOB.all_species[ghost_client?.prefs?.species]) && !check_rights(R_ADMIN, 0)) // Prevents a ghost ghosting in on a slot and spawning via a resleever with race they're not whitelisted for, getting around normal join restrictions. to_chat(ghost, "You are not whitelisted to spawn as this species!") return @@ -132,7 +132,7 @@ else spawn_slots -- return - + if(tgui_alert(ghost, "Would you like to be resleeved?", "Resleeve", list("No","Yes")) == "No") return var/mob/living/carbon/human/new_character @@ -152,7 +152,7 @@ ghost.mind.transfer_to(new_character) new_character.key = player_key - + //Were they any particular special role? If so, copy. if(new_character.mind) new_character.mind.loaded_from_ckey = picked_ckey @@ -167,6 +167,11 @@ if(chosen_language) if(is_lang_whitelisted(src,chosen_language) || (new_character.species && (chosen_language.name in new_character.species.secondary_langs))) new_character.add_language(lang) + for(var/key in ghost_client.prefs.language_custom_keys) + if(ghost_client.prefs.language_custom_keys[key]) + var/datum/language/keylang = GLOB.all_languages[ghost_client.prefs.language_custom_keys[key]] + if(keylang) + new_character.language_keys[key] = keylang //If desired, apply equipment. if(equip_body) diff --git a/code/modules/resleeving/designer.dm b/code/modules/resleeving/designer.dm index 8dd854fa66..371974ec92 100644 --- a/code/modules/resleeving/designer.dm +++ b/code/modules/resleeving/designer.dm @@ -263,7 +263,7 @@ if("menu") menu = params["menu"] temp = "" - + if("href_conversion") PrefHrefMiddleware(params, usr) @@ -281,8 +281,8 @@ mannequin.delete_inventory(TRUE) update_preview_mob(mannequin) - COMPILE_OVERLAYS(mannequin) - + mannequin.ImmediateOverlayUpdate() + var/mutable_appearance/MA = new(mannequin) south_preview.appearance = MA south_preview.dir = SOUTH diff --git a/code/modules/rogueminer_vr/controller.dm b/code/modules/rogueminer_vr/controller.dm index 4c6c710120..efff235f2e 100644 --- a/code/modules/rogueminer_vr/controller.dm +++ b/code/modules/rogueminer_vr/controller.dm @@ -197,6 +197,6 @@ var/datum/controller/rogue/rm_controller rm_controller.dbg("RMC(pnz): Cleaning up oldest zone.") spawn(0) //Detatch it so we can return the new zone for now. var/datum/rogue/zonemaster/ZM_oldest = get_oldest_zone() - ZM_oldest.clean_zone() + if(ZM_oldest) ZM_oldest.clean_zone() return ZM_target \ No newline at end of file diff --git a/code/modules/rogueminer_vr/zonemaster.dm b/code/modules/rogueminer_vr/zonemaster.dm index 15d1887803..4826661d2d 100644 --- a/code/modules/rogueminer_vr/zonemaster.dm +++ b/code/modules/rogueminer_vr/zonemaster.dm @@ -171,8 +171,8 @@ #define XENOARCH_SPAWN_CHANCE 0.3 #define DIGSITESIZE_LOWER 4 #define DIGSITESIZE_UPPER 12 - #define ARTIFACTSPAWNNUM_LOWER 6 - #define ARTIFACTSPAWNNUM_UPPER 12 //Replace with difficulty-based ones. + #define ARTIFACTSPAWNNUM_LOWER 1 + #define ARTIFACTSPAWNNUM_UPPER 1 //Replace with difficulty-based ones. if(!M.mineral && prob(rm_controller.diffstep_chances[rm_controller.diffstep])) //Difficulty translates directly into ore chance rm_controller.dbg("ZM(par): Adding mineral to [M.x],[M.y].") diff --git a/code/modules/shuttles/shuttle_console.dm b/code/modules/shuttles/shuttle_console.dm index b6d3eddfd8..28251d54d4 100644 --- a/code/modules/shuttles/shuttle_console.dm +++ b/code/modules/shuttles/shuttle_console.dm @@ -10,7 +10,7 @@ var/skip_act = FALSE var/tgui_subtemplate = "ShuttleControlConsoleDefault" - var/ai_control = FALSE //VOREStation Edit - AI/Borgs shouldn't really be flying off in ships without crew help + var/ai_control = TRUE //VOREStation Edit - AI/Borgs shouldn't really be flying off in ships without crew help //ChompStation Edit: Flying is better prevented by restricting the helm console if wanted. This is only an unnecessary nuisance that also breaks various other uses for the shuttle console. /obj/machinery/computer/shuttle_control/attack_hand(user as mob) if(..(user)) @@ -111,7 +111,8 @@ return TRUE if("set_codes") - var/newcode = tgui_input_text(usr, "Input new docking codes", "Docking codes", shuttle.docking_codes) + var/newcode = tgui_input_text(usr, "Input new docking codes", "Docking codes", shuttle.docking_codes, MAX_NAME_LEN) + newcode = sanitize(newcode,MAX_NAME_LEN) if(newcode && !..()) shuttle.set_docking_codes(uppertext(newcode)) return TRUE diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm index 6a48eb198d..1a0bd6271b 100644 --- a/code/modules/surgery/bones.dm +++ b/code/modules/surgery/bones.dm @@ -8,6 +8,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/glue_bone + surgery_name = "Glue Bone" allowed_tools = list( /obj/item/weapon/surgical/bonegel = 100 ) @@ -52,6 +53,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/set_bone + surgery_name = "Set Bone" allowed_tools = list( /obj/item/weapon/surgical/bonesetter = 100 ) @@ -98,6 +100,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/mend_skull + surgery_name = "Mend Skull" allowed_tools = list( /obj/item/weapon/surgical/bonesetter = 100 ) @@ -139,6 +142,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/finish_bone + surgery_name = "Finish Mending Bone" allowed_tools = list( /obj/item/weapon/surgical/bonegel = 100 ) @@ -182,6 +186,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/clamp_bone + surgery_name = "Clamp Bone" allowed_tools = list( /obj/item/weapon/surgical/bone_clamp = 100 ) @@ -218,4 +223,4 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user]'s hand slips, damaging the bone in [target]'s [affected.name] with \the [tool]!" , \ "Your hand slips, damaging the bone in [target]'s [affected.name] with \the [tool]!") - affected.createwound(BRUISE, 5) \ No newline at end of file + affected.createwound(BRUISE, 5) diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm index d69c456f7c..c172b9bc44 100644 --- a/code/modules/surgery/encased.dm +++ b/code/modules/surgery/encased.dm @@ -3,6 +3,7 @@ // GENERIC RIBCAGE SURGERY // ////////////////////////////////////////////////////////////////// /datum/surgery_step/open_encased + surgery_name = "Open Encased" priority = 2 can_infect = 1 blood_level = 1 @@ -21,6 +22,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/open_encased/saw + surgery_name = "Cut Bone" allowed_tools = list( /obj/item/weapon/surgical/circular_saw = 100, \ /obj/item/weapon/material/knife/machete/hatchet = 75 @@ -66,10 +68,11 @@ affected.fracture() /////////////////////////////////////////////////////////////// -// Rib Opening Surgery +// Bone Opening Surgery /////////////////////////////////////////////////////////////// /datum/surgery_step/open_encased/retract + surgery_name = "Retract Bone" allowed_tools = list( /obj/item/weapon/surgical/retractor = 100 ) @@ -119,10 +122,11 @@ affected.fracture() /////////////////////////////////////////////////////////////// -// Rib Closing Surgery +// Retracted Bone Closing Surgery /////////////////////////////////////////////////////////////// /datum/surgery_step/open_encased/close + surgery_name = "Close Retracted Bone" allowed_tools = list( /obj/item/weapon/surgical/retractor = 100, ) @@ -177,10 +181,11 @@ target.rupture_lung()*/ /////////////////////////////////////////////////////////////// -// Rib Mending Surgery +// Retracted Bone Mending Surgery /////////////////////////////////////////////////////////////// /datum/surgery_step/open_encased/mend + surgery_name = "Mend Retracted Bone" allowed_tools = list( /obj/item/weapon/surgical/bonegel = 100 ) @@ -222,6 +227,7 @@ // Saw/Retractor/Gel Combi-open and close. /////////////////////////////////////////////////////////////// /datum/surgery_step/open_encased/advancedsaw_open + surgery_name = "Advanced Cut Bone" allowed_tools = list( /obj/item/weapon/surgical/circular_saw/manager = 100 ) @@ -230,6 +236,7 @@ min_duration = 60 max_duration = 90 + excludes_steps = list(/datum/surgery_step/open_encased/saw) /datum/surgery_step/open_encased/advancedsaw_open/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if (!hasorgans(target)) @@ -271,6 +278,7 @@ /datum/surgery_step/open_encased/advancedsaw_mend + surgery_name = "Advanced Mend Retracted Bone" allowed_tools = list( /obj/item/weapon/surgical/circular_saw/manager = 100 ) diff --git a/code/modules/surgery/external_repair.dm b/code/modules/surgery/external_repair.dm index 4f8707e82d..3698f2d1c4 100644 --- a/code/modules/surgery/external_repair.dm +++ b/code/modules/surgery/external_repair.dm @@ -3,6 +3,7 @@ // LIMB REPAIR SURGERY // ////////////////////////////////////////////////////////////////// /datum/surgery_step/repairflesh/ + surgery_name = "Repair Flesh" priority = 1 can_infect = 1 blood_level = 1 @@ -36,6 +37,7 @@ ////////////////////////////////////////////////////////////////// /datum/surgery_step/repairflesh/scan_injury + surgery_name = "Scan Injury" allowed_tools = list( /obj/item/weapon/autopsy_scanner = 100, /obj/item/device/analyzer = 10 @@ -86,6 +88,7 @@ ////////////////////////////////////////////////////////////////// /datum/surgery_step/repairflesh/repair_burns + surgery_name = "Repair Burns" allowed_tools = list( /obj/item/stack/medical/advanced/ointment = 100, /obj/item/stack/medical/ointment = 50, @@ -103,8 +106,6 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) if(affected.burn_stage < 1 || !(affected.burn_dam)) return 0 - if(affected.burn_dam < affected.brute_dam) - return 0 return 1 return 0 @@ -152,6 +153,7 @@ ////////////////////////////////////////////////////////////////// /datum/surgery_step/repairflesh/repair_brute + surgery_name = "Repair Brute" allowed_tools = list( /obj/item/stack/medical/advanced/bruise_pack = 100, /obj/item/stack/medical/bruise_pack = 50, @@ -169,8 +171,6 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) if(affected.brute_stage < 1 || !(affected.brute_dam)) return 0 - if(affected.brute_dam < affected.burn_dam) - return 0 return 1 return 0 diff --git a/code/modules/surgery/face.dm b/code/modules/surgery/face.dm index fc10ecfcca..9ecef80252 100644 --- a/code/modules/surgery/face.dm +++ b/code/modules/surgery/face.dm @@ -4,6 +4,7 @@ ////////////////////////////////////////////////////////////////// /datum/surgery_step/face + surgery_name = "Facial Surgery" priority = 2 req_open = 0 can_infect = 0 @@ -23,6 +24,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/generic/cut_face + surgery_name = "Cut Face" allowed_tools = list( /obj/item/weapon/surgical/scalpel = 100, \ /obj/item/weapon/material/knife = 75, \ @@ -57,6 +59,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/face/mend_vocal + surgery_name = "Mend Vocal Cords" allowed_tools = list( /obj/item/weapon/surgical/hemostat = 100, \ /obj/item/stack/cable_coil = 75, \ @@ -89,6 +92,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/face/fix_face + surgery_name = "Fix Face" allowed_tools = list( /obj/item/weapon/surgical/retractor = 100, \ /obj/item/weapon/material/kitchen/utensil/fork = 75 @@ -123,6 +127,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/face/cauterize + surgery_name = "Cauterize Face" allowed_tools = list( /obj/item/weapon/surgical/cautery = 100, \ /obj/item/clothing/mask/smokable/cigarette = 75, \ @@ -156,4 +161,4 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user]'s hand slips, leaving a small burn on [target]'s face with \the [tool]!", \ "Your hand slips, leaving a small burn on [target]'s face with \the [tool]!") - target.apply_damage(4, BURN, affected) \ No newline at end of file + target.apply_damage(4, BURN, affected) diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index d26ea6c0c1..8f25b42328 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -29,6 +29,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/generic/cut_open + surgery_name = "Create Incision" allowed_tools = list( /obj/item/weapon/surgical/scalpel = 100, \ /obj/item/weapon/material/knife = 75, \ @@ -73,16 +74,18 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/generic/cut_with_laser + surgery_name = "Create Bloodless Incision" allowed_tools = list( - /obj/item/weapon/surgical/scalpel/laser3 = 95, \ - /obj/item/weapon/surgical/scalpel/laser2 = 85, \ - /obj/item/weapon/surgical/scalpel/laser1 = 75, \ + /obj/item/weapon/surgical/scalpel/laser3 = 100, \ + /obj/item/weapon/surgical/scalpel/laser2 = 100, \ + /obj/item/weapon/surgical/scalpel/laser1 = 100, \ /obj/item/weapon/melee/energy/sword = 5 ) priority = 2 req_open = 0 min_duration = 90 max_duration = 110 + excludes_steps = list(/datum/surgery_step/generic/cut_open) /datum/surgery_step/generic/cut_with_laser/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(..()) @@ -98,13 +101,25 @@ /datum/surgery_step/generic/cut_with_laser/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message("[user] has made a bloodless incision on [target]'s [affected.name] with \the [tool].", \ - "You have made a bloodless incision on [target]'s [affected.name] with \the [tool].",) - //Could be cleaner ... affected.open = 1 affected.createwound(CUT, 1) - affected.organ_clamp() + var/clamp_chance = 0 //I hate this. Make all laser scalpels a /laser subtype and give them a clamp_chance var??? + if(istype(tool,/obj/item/weapon/surgical/scalpel/laser1)) + clamp_chance = 75 + if(istype(tool,/obj/item/weapon/surgical/scalpel/laser2)) + clamp_chance = 85 + if(istype(tool,/obj/item/weapon/surgical/scalpel/laser3)) + clamp_chance = 95 + if(clamp_chance) + affected.organ_clamp() + user.visible_message("[user] has made a bloodless incision on [target]'s [affected.name] with \the [tool].", \ + "You have made a bloodless incision on [target]'s [affected.name] with \the [tool].",) + else + user.visible_message("[user] has made an incision on [target]'s [affected.name] with \the [tool], but blood is still escaping from the wound.", \ + "You have made an incision on [target]'s [affected.name] with \the [tool], but blood is still coming from the wound..",) + //Could be cleaner ... + spread_germs_to_organ(affected, user) /datum/surgery_step/generic/cut_with_laser/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -119,6 +134,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/generic/incision_manager + surgery_name = "Create Prepared Incision" allowed_tools = list( /obj/item/weapon/surgical/scalpel/manager = 100 ) @@ -127,6 +143,7 @@ req_open = 0 min_duration = 80 max_duration = 120 + excludes_steps = list(/datum/surgery_step/generic/cut_open) /datum/surgery_step/generic/incision_manager/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(..()) @@ -165,6 +182,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/generic/clamp_bleeders + surgery_name = "Clamp Bleeders" allowed_tools = list( /obj/item/weapon/surgical/hemostat = 100, \ /obj/item/stack/cable_coil = 75, \ @@ -204,6 +222,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/generic/retract_skin + surgery_name = "Retract Skin" allowed_tools = list( /obj/item/weapon/surgical/retractor = 100, \ /obj/item/weapon/material/kitchen/utensil/fork = 50 @@ -264,6 +283,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/generic/cauterize + surgery_name = "Cauterize Incision" allowed_tools = list( /obj/item/weapon/surgical/cautery = 100, \ /obj/item/clothing/mask/smokable/cigarette = 75, \ @@ -305,6 +325,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/generic/amputate + surgery_name = "Amputate Limb" allowed_tools = list( /obj/item/weapon/surgical/circular_saw = 100, \ /obj/item/weapon/material/knife/machete/hatchet = 75 diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm index f1c0af37f4..c3c2496cfd 100644 --- a/code/modules/surgery/implant.dm +++ b/code/modules/surgery/implant.dm @@ -5,6 +5,7 @@ ////////////////////////////////////////////////////////////////// /datum/surgery_step/cavity + surgery_name = "Cavity" priority = 1 /datum/surgery_step/cavity/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -46,6 +47,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/cavity/make_space + surgery_name = "Create Cavity" allowed_tools = list( /obj/item/weapon/surgical/surgicaldrill = 100, \ /obj/item/weapon/pen = 75, \ @@ -78,6 +80,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/cavity/close_space + surgery_name = "Close Cavity" priority = 2 allowed_tools = list( /obj/item/weapon/surgical/cautery = 100, \ @@ -112,6 +115,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/cavity/place_item + surgery_name = "Implant Object" priority = 0 allowed_tools = list(/obj/item = 100) @@ -124,7 +128,14 @@ if(..()) var/obj/item/organ/external/affected = target.get_organ(target_zone) if(istype(user,/mob/living/silicon/robot)) - return + if(istype(tool, /obj/item/weapon/gripper)) + var/obj/item/weapon/gripper/Gripper = tool + if(Gripper.wrapped) + tool = Gripper.wrapped + else + return + else + return if(affected && affected.cavity) var/total_volume = tool.w_class for(var/obj/item/I in affected.implants) @@ -135,6 +146,9 @@ /datum/surgery_step/cavity/place_item/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(isrobot(user) && istype(tool, /obj/item/weapon/gripper)) + var/obj/item/weapon/gripper/G = tool + tool = G.wrapped user.visible_message("[user] starts putting \the [tool] inside [target]'s [get_cavity(affected)] cavity.", \ "You start putting \the [tool] inside [target]'s [get_cavity(affected)] cavity." ) //Nobody will probably ever see this, but I made these two blue. ~CK target.custom_pain("The pain in your chest is living hell!",1) @@ -142,7 +156,12 @@ /datum/surgery_step/cavity/place_item/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/chest/affected = target.get_organ(target_zone) - + if(isrobot(user) && istype(tool, /obj/item/weapon/gripper)) + var/obj/item/weapon/gripper/G = tool + tool = G.wrapped + G.drop_item() + else + user.drop_item() user.visible_message("[user] puts \the [tool] inside [target]'s [get_cavity(affected)] cavity.", \ "You put \the [tool] inside [target]'s [get_cavity(affected)] cavity." ) if (tool.w_class > get_max_wclass(affected)/2 && prob(50) && (affected.robotic < ORGAN_ROBOT)) @@ -150,7 +169,6 @@ var/datum/wound/internal_bleeding/I = new (10) affected.wounds += I affected.owner.custom_pain("You feel something rip in your [affected.name]!", 1) - user.drop_item() affected.implants += tool tool.loc = affected if(istype(tool,/obj/item/device/nif)){var/obj/item/device/nif/N = tool;N.implant(target)} //VOREStation Add - NIF support @@ -161,6 +179,7 @@ ////////////////////////////////////////////////////////////////// /datum/surgery_step/cavity/implant_removal + surgery_name = "Remove Implant" allowed_tools = list( /obj/item/weapon/surgical/hemostat = 100, \ /obj/item/weapon/material/kitchen/utensil/fork = 20 @@ -189,49 +208,54 @@ /datum/surgery_step/cavity/implant_removal/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/chest/affected = target.get_organ(target_zone) - var/time_to_remove = 0 // CHOMPEdit: Changes surgery pass/fail on prob to a timer. - if (affected.implants.len) - var/obj/item/obj = pick(affected.implants) + var/obj/item/obj = tgui_input_list(user, "Which embedded item do you wish to remove?", "Surgery Select", affected.implants) + if(isnull(obj)) //They clicked cancel. + user.visible_message("[user] takes \the [tool] out of [target]'s [affected.name].", \ + "You take \the [tool] out of the incision on [target]'s [affected.name]." ) + return + if(!do_mob(user, target, 1)) //They moved away + to_chat(user, "You must remain close to and keep focused on your patient to conduct surgery.") + user.visible_message("[user] fails to remove anything from [target]'s [affected.name] with \the [tool]!", \ + "You fail to remove the [obj] from [target]'s [affected.name]s with \the [tool]!" ) + return if(istype(obj,/obj/item/weapon/implant)) var/obj/item/weapon/implant/imp = obj - if (imp.islegal()) - time_to_remove += 10 SECONDS // CHOMPEdit: Changes surgery pass/fail on prob to a timer. - else - time_to_remove += 20 SECONDS // CHOMPEdit: Changes surgery pass/fail on prob to a timer. + if (!imp.islegal()) //ILLEGAL IMPLANT ALERT!!!!!!!!!! + user.visible_message("[user] seems to be intently working on something within [target]'s [affected.name] with \the [tool]!", \ + "You intently begin to take [obj] out of the incision on [target]'s [affected.name]s with \the [tool]!" ) + if(!do_after(user, min_duration, target)) + user.visible_message("[user] fails to remove anything from [target]'s [affected.name] with \the [tool]!", \ + "You fail to remove the [obj] from [target]'s [affected.name]s with \the [tool]!" ) + return + + + user.visible_message("[user] takes something out of the incision on [target]'s [affected.name] with \the [tool]!", \ + "You take [obj] out of the incision on [target]'s [affected.name]s with \the [tool]!" ) + affected.implants -= obj + if(!target.has_embedded_objects()) + target.clear_alert("embeddedobject") + + BITSET(target.hud_updateflag, IMPLOYAL_HUD) + + //Handle possessive brain borers. + if(istype(obj,/mob/living/simple_mob/animal/borer)) + var/mob/living/simple_mob/animal/borer/worm = obj + if(worm.controlling) + target.release_control() + worm.detatch() + worm.leave_host() else - time_to_remove += 10 SECONDS // CHOMPEdit: Changes surgery pass/fail on prob to a timer. This else is shrapnel and the like. - - if(do_after(user, time_to_remove)) // CHOMPEdit: Changes surgery pass/fail on prob to a timer. - user.visible_message("[user] takes something out of incision on [target]'s [affected.name] with \the [tool]!", \ - "You take [obj] out of incision on [target]'s [affected.name]s with \the [tool]!" ) - affected.implants -= obj - if(!target.has_embedded_objects()) - target.clear_alert("embeddedobject") - - BITSET(target.hud_updateflag, IMPLOYAL_HUD) - - //Handle possessive brain borers. - if(istype(obj,/mob/living/simple_mob/animal/borer)) - var/mob/living/simple_mob/animal/borer/worm = obj - if(worm.controlling) - target.release_control() - worm.detatch() - worm.leave_host() - else - obj.loc = get_turf(target) - obj.add_blood(target) - obj.update_icon() - if(istype(obj,/obj/item/weapon/implant)) - var/obj/item/weapon/implant/imp = obj - imp.imp_in = null - imp.implanted = 0 - else if(istype(tool,/obj/item/device/nif)){var/obj/item/device/nif/N = tool;N.unimplant(target)} //VOREStation Add - NIF support - else // CHOMPEdit: Shouldn't hit this anymore, but leaving in just-in-case. - user.visible_message("[user] removes \the [tool] from [target]'s [affected.name].", \ - "There's something inside [target]'s [affected.name], but you just missed it this time." ) + obj.loc = get_turf(target) + obj.add_blood(target) + obj.update_icon() + if(istype(obj,/obj/item/weapon/implant)) + var/obj/item/weapon/implant/imp = obj + imp.imp_in = null + imp.implanted = 0 + else if(istype(tool,/obj/item/device/nif)){var/obj/item/device/nif/N = tool;N.unimplant(target)} //VOREStation Add - NIF support else user.visible_message("[user] could not find anything inside [target]'s [affected.name], and pulls \the [tool] out.", \ "You could not find anything inside [target]'s [affected.name]." ) diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm index 8a25be5b51..56c0ccccc1 100644 --- a/code/modules/surgery/limb_reattach.dm +++ b/code/modules/surgery/limb_reattach.dm @@ -4,6 +4,7 @@ ////////////////////////////////////////////////////////////////// /datum/surgery_step/limb/ + surgery_name = "Limb" priority = 3 // Must be higher than /datum/surgery_step/internal req_open = 0 can_infect = 0 @@ -22,6 +23,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/limb/attach + surgery_name = "Attach Limb" allowed_tools = list(/obj/item/organ/external = 100) min_duration = 50 @@ -81,6 +83,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/limb/connect + surgery_name = "Connect Limb" allowed_tools = list( /obj/item/weapon/surgical/hemostat = 100, \ /obj/item/stack/cable_coil = 75, \ @@ -120,6 +123,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/limb/mechanize + surgery_name = "Mechanize Limb" allowed_tools = list(/obj/item/robot_parts = 100) min_duration = 80 diff --git a/code/modules/surgery/neck.dm b/code/modules/surgery/neck.dm index 6b970ad4c2..5b59075612 100644 --- a/code/modules/surgery/neck.dm +++ b/code/modules/surgery/neck.dm @@ -4,6 +4,7 @@ ////////////////////////////////////////////////////////////////////// /datum/surgery_step/brainstem + surgery_name = "Brainstem" priority = 2 req_open = 1 can_infect = 1 @@ -23,6 +24,7 @@ ///////////////////////////// /datum/surgery_step/brainstem/mend_vessels + surgery_name = "Mend Vessels" priority = 1 allowed_tools = list( /obj/item/weapon/surgical/FixOVein = 100, @@ -57,6 +59,7 @@ ///////////////////////////// /datum/surgery_step/brainstem/drill_vertebrae + surgery_name = "Drill Vertebrae" priority = 3 //Do this instead of expanding the skull cavity allowed_tools = list( /obj/item/weapon/surgical/surgicaldrill = 100, @@ -100,6 +103,7 @@ ///////////////////////////// /datum/surgery_step/brainstem/clean_chips + surgery_name = "Remove Bone Chips" priority = 3 //Do this instead of picking around for implants. allowed_tools = list( /obj/item/weapon/surgical/hemostat = 100, @@ -139,6 +143,7 @@ ///////////////////////////// /datum/surgery_step/brainstem/mend_cord + surgery_name = "Mend Spinal Cord" priority = 1 //Do this after IB. allowed_tools = list( /obj/item/weapon/surgical/FixOVein = 100, @@ -179,6 +184,7 @@ ///////////////////////////// /datum/surgery_step/brainstem/mend_vertebrae + surgery_name = "Mend Vertebrae" priority = 3 //Do this instead of fixing bones. allowed_tools = list( /obj/item/weapon/surgical/bonegel = 100, @@ -217,6 +223,7 @@ ///////////////////////////// /datum/surgery_step/brainstem/realign_tissue + surgery_name = "Realign Tissue" priority = 3 //Do this instead of searching for objects in the skull. allowed_tools = list( /obj/item/weapon/surgical/hemostat = 100, diff --git a/code/modules/surgery/organ_ripper_vr.dm b/code/modules/surgery/organ_ripper_vr.dm new file mode 100644 index 0000000000..0fa8f751c5 --- /dev/null +++ b/code/modules/surgery/organ_ripper_vr.dm @@ -0,0 +1,232 @@ +// Ripper tool. This is only for harming the patient or (in organs_internal.dm) ripping out an organ. +// This means if you want to torture someone, do medical malpractice, or harm a fresh sleeve for teaching medical, you can. + +/datum/surgery_step/generic/ripper //This is the base which should never be seen. + surgery_name = "Ripper Tool" + + priority = 3 + + blood_level = 99 //Ripper sugery gets you super bloody. + + min_duration = 60 + max_duration = 80 + excludes_steps = list(/datum/surgery_step/generic/cut_open) //These things can already do the first step! + +/datum/surgery_step/generic/ripper/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/weapon/surgical/scalpel/ripper/tool) + + if (!..()) + return 0 + + var/obj/item/organ/external/affected = target.get_organ(target_zone) + + if(!istype(tool)) //Only rippers can use the ripper! + return 0 + + if(affected.robotic >= ORGAN_ROBOT) //You can't damage robutts. + return 0 + + return affected && affected.open != 0 && target_zone != O_MOUTH //Have to cut them open at a minimum. + +/datum/surgery_step/generic/ripper/tear_vessel + surgery_name = "Tear Blood Vessel" + allowed_tools = list( + /obj/item/weapon/surgical/scalpel/ripper = 100 + ) + +/datum/surgery_step/generic/ripper/tear_vessel/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user] starts ripping into [target] with \the [tool].", \ + "You start ripping into [target] with \the [tool].") + target.custom_pain("[user] is ripping into your [target.op_stage.current_organ]!", 100) + ..() + +/datum/surgery_step/generic/ripper/tear_vessel/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user] has ripped [target]'s [affected] \the [tool], blood and viscera spraying everywhere!", \ + "You have ripped [target]'s [target.op_stage.current_organ] out with \the [tool], spraying blood all through the room!") + var/datum/wound/internal_bleeding/I = new (30) //splurt. New severed artery. + affected.wounds += I + affected.owner.custom_pain("You feel something rip in your [affected.name]!", 1) + target.drip(30) //Lose a lot of blood. + new /obj/effect/gibspawner/human(target.loc,target.dna,target.species.flesh_color,target.species.blood_color) //SPLAT. + target.emote("scream") //Hope you put them under... + +/datum/surgery_step/generic/ripper/tear_vessel/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user]'s hand slips, damaging [target]'s [affected.name] with \the [tool]!", \ + "Your hand slips, damaging [target]'s [affected.name] with \the [tool]!") + affected.createwound(BRUISE, 20) //Only bruised...Sad. + + +//Break Bone +/datum/surgery_step/generic/ripper/break_bone + surgery_name = "Break Skeletal Structure" + allowed_tools = list( + /obj/item/weapon/surgical/scalpel/ripper = 100 + ) + +/datum/surgery_step/generic/ripper/break_bone/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user] starts violently shifting \the [tool] in [target]'s [affected.name]!", \ + "You start violently moving the [tool] in [target]'s [affected.name]!") + target.custom_pain("[user] is ripping into your [target.op_stage.current_organ]!", 100) + ..() + +/datum/surgery_step/generic/ripper/break_bone/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user] has destroyed the bones within [target]'s [affected] with \the [tool]", \ + "You have destroyed the bones in [target]'s [affected] with \the [tool]!") + affected.fracture() + affected.createwound(BRUISE, 20) + target.emote("scream") //Hope you put them under... + +/datum/surgery_step/generic/ripper/tear_vessel/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user]'s hand slips, damaging [target]'s [affected.name] with \the [tool]!", \ + "Your hand slips, damaging [target]'s [affected.name] with \the [tool]!") + affected.createwound(BRUISE, 20) + +//Mutilate Organ + +/datum/surgery_step/generic/ripper/destroy_organ + surgery_name = "Mutilate Organ" + allowed_tools = list( + /obj/item/weapon/surgical/scalpel/ripper = 100 + ) + +/datum/surgery_step/generic/ripper/destroy_organ/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (!..()) + return 0 + + var/list/removable_organs = list() + for(var/organ in target.internal_organs_by_name) + var/obj/item/organ/internal/I = target.internal_organs_by_name[organ] + if(istype(I) && I.parent_organ == target_zone) + removable_organs |= organ + + if(!removable_organs.len) + return 0 + return ..() + +/datum/surgery_step/generic/ripper/destroy_organ/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + + var/list/removable_organs = list() + for(var/organ in target.internal_organs_by_name) + var/obj/item/organ/internal/I = target.internal_organs_by_name[organ] + if(istype(I) && I.parent_organ == target_zone) + removable_organs |= organ + + var/organ_to_destroy = tgui_input_list(user, "Which organ do you want to mutilate?", "Organ Choice", removable_organs) + + if(!organ_to_destroy) //They decided to cancel. Let's slowly pull the tool back... + to_chat(user, "You decide against mutilating any organs.") + user.visible_message("[user] starts pulling their [tool] out from [target]'s [affected.name] with \the [tool].", \ + "You start pulling your \the [tool] out of [target]'s [affected.name].") + target.custom_pain("Someone's moving something around in your [affected.name]!", 100) + else if(organ_to_destroy) + target.op_stage.current_organ = organ_to_destroy + user.visible_message("[user] starts ripping into [target]'s [target.op_stage.current_organ] with \the [tool].", \ + "You start ripping [target]'s [target.op_stage.current_organ] with \the [tool].") + target.custom_pain("Someone's ripping out your [target.op_stage.current_organ]!", 100) + ..() + + +/datum/surgery_step/generic/ripper/destroy_organ/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(!target.op_stage.current_organ) + user.visible_message("[user] has pulled their \the [tool] from [target]'s [affected.name].", \ + "You have pulled your [tool] out from [target]'s [affected].") + + // Damage the organ! + if(target.op_stage.current_organ) + user.visible_message("[user] has ripped [target]'s [target.op_stage.current_organ] out with \the [tool].", \ + "You have ripped [target]'s [target.op_stage.current_organ] out with \the [tool].") + var/obj/item/organ/O = target.internal_organs_by_name[target.op_stage.current_organ] + if(O && istype(O)) + O.take_damage(10) + target.op_stage.current_organ = null + new /obj/effect/gibspawner/human(target.loc,target.dna,target.species.flesh_color,target.species.blood_color) + target.emote("scream") + +/datum/surgery_step/generic/ripper/destroy_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user]'s hand slips, damaging [target]'s [affected.name] with \the [tool]!", \ + "Your hand slips, damaging [target]'s [affected.name] with \the [tool]!") + affected.createwound(BRUISE, 20) + +/////////////////////////////////////////////////////////////// +// Organ Ripping Surgery +/////////////////////////////////////////////////////////////// + +/datum/surgery_step/generic/ripper/rip_organ + surgery_name = "Rip Out Organ" + + allowed_tools = list( + /obj/item/weapon/surgical/scalpel/ripper = 100 + ) + + priority = 3 + + blood_level = 3 + + min_duration = 60 + max_duration = 80 + excludes_steps = list(/datum/surgery_step/generic/cut_open) + +/datum/surgery_step/generic/ripper/rip_organ/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (!..()) + return 0 + + var/list/removable_organs = list() + for(var/organ in target.internal_organs_by_name) + var/obj/item/organ/internal/I = target.internal_organs_by_name[organ] + if(istype(I) && I.parent_organ == target_zone) + removable_organs |= organ + + if(!removable_organs.len) + return 0 + + return ..() + +/datum/surgery_step/generic/ripper/rip_organ/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + var/list/removable_organs = list() + for(var/organ in target.internal_organs_by_name) + var/obj/item/organ/internal/I = target.internal_organs_by_name[organ] + if(istype(I) && I.parent_organ == target_zone) + removable_organs |= organ + + var/organ_to_remove = tgui_input_list(user, "Which organ do you want to tear out?", "Organ Choice", removable_organs) + if(!organ_to_remove) //They decided to cancel. Let's slowly pull the tool back... + to_chat(user, "You decide against ripping out any organs.") + user.visible_message("[user] starts pulling their [tool] out from [target]'s [affected.name] with \the [tool].", \ + "You start pulling your \the [tool] out of [target]'s [affected.name].") + target.custom_pain("Someone's moving something around in your [affected.name]!", 100) + else if(organ_to_remove) + target.op_stage.current_organ = organ_to_remove + user.visible_message("[user] starts ripping [target]'s [target.op_stage.current_organ] out with \the [tool].", \ + "You start ripping [target]'s [target.op_stage.current_organ] out with \the [tool].") + target.custom_pain("Someone's ripping out your [target.op_stage.current_organ]!", 100) + ..() + +/datum/surgery_step/generic/ripper/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(!target.op_stage.current_organ) + user.visible_message("[user] has pulled their \the [tool] from [target]'s [affected.name].", \ + "You have pulled your [tool] out from [target]'s [affected].") + + if(target.op_stage.current_organ) + user.visible_message("[user] has ripped [target]'s [target.op_stage.current_organ] out with \the [tool].", \ + "You have ripped [target]'s [target.op_stage.current_organ] out with \the [tool].") + var/obj/item/organ/O = target.internal_organs_by_name[target.op_stage.current_organ] + if(O && istype(O)) + O.removed(user) + target.op_stage.current_organ = null + new /obj/effect/gibspawner/human(target.loc,target.dna,target.species.flesh_color,target.species.blood_color) + target.emote("scream") + +/datum/surgery_step/internal/rip_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user]'s hand slips, damaging [target]'s [affected.name] with \the [tool]!", \ + "Your hand slips, damaging [target]'s [affected.name] with \the [tool]!") + affected.createwound(BRUISE, 20) diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index e5f49cc922..e92010f8d3 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -78,6 +78,8 @@ if(!(I.robotic >= ORGAN_ROBOT)) user.visible_message("[user] treats damage to [target]'s [I.name] with [tool_name].", \ "You treat damage to [target]'s [I.name] with [tool_name]." ) + if(I.organ_tag == O_BRAIN && I.status == ORGAN_DEAD && target.can_defib == 0) //Let people know they still got more work to get the brain back into working order. + to_chat(user, "You fix their [I] but the neurological structure is still heavily damaged and in need of repair.") I.damage = 0 I.status = 0 if(I.organ_tag == O_EYES) @@ -105,6 +107,81 @@ if(I && I.damage > 0) I.take_damage(dam_amt,0) + + + + + +//Robo internal organ fix. For when an organic has robotic limbs. +/datum/surgery_step/fix_organic_organ_robotic //For artificial organs + allowed_tools = list( + /obj/item/stack/nanopaste = 100, + /obj/item/stack/cable_coil = 75, + /obj/item/weapon/tool/wrench = 50, + /obj/item/weapon/storage/toolbox = 10 //Percussive Maintenance + ) + + min_duration = 70 + max_duration = 90 + +/datum/surgery_step/fix_organic_organ_robotic/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (!hasorgans(target)) + return + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(!affected) return + var/is_organ_damaged = 0 + for(var/obj/item/organ/I in affected.internal_organs) + if(I.damage > 0 && (I.robotic >= ORGAN_ROBOT)) + is_organ_damaged = 1 + break + return affected.open != 3 && is_organ_damaged //Robots have their own code. + +/datum/surgery_step/fix_organic_organ_robotic/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (!hasorgans(target)) + return + var/obj/item/organ/external/affected = target.get_organ(target_zone) + + for(var/obj/item/organ/I in affected.internal_organs) + if(I && I.damage > 0) + if(I.robotic >= ORGAN_ROBOT) + user.visible_message("[user] starts mending the damage to [target]'s [I.name]'s mechanisms.", \ + "You start mending the damage to [target]'s [I.name]'s mechanisms." ) + + target.custom_pain("The pain in your [affected.name] is living hell!",1) + ..() + +/datum/surgery_step/fix_organic_organ_robotic/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (!hasorgans(target)) + return + var/obj/item/organ/external/affected = target.get_organ(target_zone) + + for(var/obj/item/organ/I in affected.internal_organs) + if(I && I.damage > 0) + if(I.robotic >= ORGAN_ROBOT) + user.visible_message("[user] repairs [target]'s [I.name] with [tool].", \ + "You repair [target]'s [I.name] with [tool]." ) + I.damage = 0 + if(I.organ_tag == O_EYES) + target.sdisabilities &= ~BLIND + +/datum/surgery_step/fix_organic_organ_robotic/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (!hasorgans(target)) + return + var/obj/item/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("[user]'s hand slips, gumming up the mechanisms inside of [target]'s [affected.name] with \the [tool]!", \ + "Your hand slips, gumming up the mechanisms inside of [target]'s [affected.name] with \the [tool]!") + + target.adjustBruteLoss(5) + + for(var/obj/item/organ/I in affected.internal_organs) + if(I) + I.take_damage(rand(3,5),0) + + +//Robo limb fix end + + /////////////////////////////////////////////////////////////// // Organ Detaching Surgery /////////////////////////////////////////////////////////////// @@ -175,13 +252,14 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/internal/remove_organ + surgery_name = "Remove Organ" allowed_tools = list( /obj/item/weapon/surgical/hemostat = 100, \ /obj/item/weapon/material/kitchen/utensil/fork = 20 ) - allowed_procs = list(IS_WIRECUTTER = 75) + allowed_procs = list(IS_WIRECUTTER = 100) //FBP code also uses this, so let's be nice. Roboticists won't know to use hemostats. min_duration = 60 max_duration = 80 @@ -193,8 +271,19 @@ if(!istype(tool)) return 0 - target.op_stage.current_organ = null + var/list/removable_organs = list() + for(var/organ in target.internal_organs_by_name) + var/obj/item/organ/internal/I = target.internal_organs_by_name[organ] + if(istype(I) && (I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone) + removable_organs |= organ + if(!removable_organs.len) + return 0 + + return ..() + +/datum/surgery_step/internal/remove_organ/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/obj/item/organ/external/affected = target.get_organ(target_zone) var/list/removable_organs = list() for(var/organ in target.internal_organs_by_name) var/obj/item/organ/internal/I = target.internal_organs_by_name[organ] @@ -202,28 +291,32 @@ removable_organs |= organ var/organ_to_remove = tgui_input_list(user, "Which organ do you want to remove?", "Organ Choice", removable_organs) - if(!organ_to_remove) - return 0 + if(!organ_to_remove) //They chose cancel! + to_chat(user, "You decide against preparing any organs for removal.") + user.visible_message("[user] starts pulling \the [tool] from [target]'s [affected]", \ + "You start pulling \the [tool] from [target]'s [affected].") target.op_stage.current_organ = organ_to_remove - return ..() -/datum/surgery_step/internal/remove_organ/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("[user] starts removing [target]'s [target.op_stage.current_organ] with \the [tool].", \ "You start removing [target]'s [target.op_stage.current_organ] with \the [tool].") target.custom_pain("Someone's ripping out your [target.op_stage.current_organ]!", 100) ..() /datum/surgery_step/internal/remove_organ/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] has removed [target]'s [target.op_stage.current_organ] with \the [tool].", \ - "You have removed [target]'s [target.op_stage.current_organ] with \the [tool].") + var/obj/item/organ/external/affected = target.get_organ(target_zone) + if(!target.op_stage.current_organ) //They chose to remove their tool instead. + user.visible_message("[user] has removed \the [tool] from [target]'s [affected].", \ + "You have removed \the [tool] from [target]'s [affected].") // Extract the organ! if(target.op_stage.current_organ) + user.visible_message("[user] has removed [target]'s [target.op_stage.current_organ] with \the [tool].", \ + "You have removed [target]'s [target.op_stage.current_organ] with \the [tool].") var/obj/item/organ/O = target.internal_organs_by_name[target.op_stage.current_organ] if(O && istype(O)) O.removed(user) - target.op_stage.current_organ = null + target.op_stage.current_organ = null /datum/surgery_step/internal/remove_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) @@ -364,65 +457,3 @@ user.visible_message("[user]'s hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!", \ "Your hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!") affected.createwound(BRUISE, 20) - -/////////////////////////////////////////////////////////////// -// Organ Ripping Surgery -/////////////////////////////////////////////////////////////// - -/datum/surgery_step/internal/rip_organ - - allowed_tools = list( - /obj/item/weapon/surgical/scalpel/ripper = 100 - ) - - priority = 3 - - blood_level = 3 - - min_duration = 60 - max_duration = 80 - -/datum/surgery_step/internal/rip_organ/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if (!..()) - return 0 - - if(!istype(tool)) - return 0 - - target.op_stage.current_organ = null - - var/list/removable_organs = list() - for(var/organ in target.internal_organs_by_name) - var/obj/item/organ/internal/I = target.internal_organs_by_name[organ] - if(istype(I) && I.parent_organ == target_zone) - removable_organs |= organ - - var/organ_to_remove = tgui_input_list(user, "Which organ do you want to remove?", "Organ Choice", removable_organs) - if(!organ_to_remove) - return 0 - - target.op_stage.current_organ = organ_to_remove - return ..() - -/datum/surgery_step/internal/rip_organ/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts ripping [target]'s [target.op_stage.current_organ] out with \the [tool].", \ - "You start ripping [target]'s [target.op_stage.current_organ] out with \the [tool].") - target.custom_pain("Someone's ripping out your [target.op_stage.current_organ]!", 100) - ..() - -/datum/surgery_step/internal/rip_organ/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] has ripped [target]'s [target.op_stage.current_organ] out with \the [tool].", \ - "You have ripped [target]'s [target.op_stage.current_organ] out with \the [tool].") - - // Extract the organ! - if(target.op_stage.current_organ) - var/obj/item/organ/O = target.internal_organs_by_name[target.op_stage.current_organ] - if(O && istype(O)) - O.removed(user) - target.op_stage.current_organ = null - -/datum/surgery_step/internal/rip_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/obj/item/organ/external/affected = target.get_organ(target_zone) - user.visible_message("[user]'s hand slips, damaging [target]'s [affected.name] with \the [tool]!", \ - "Your hand slips, damaging [target]'s [affected.name] with \the [tool]!") - affected.createwound(BRUISE, 20) diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index 9cde26f240..c0c081e05b 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -8,6 +8,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/fix_vein + surgery_name = "Fix Vein" priority = 2 allowed_tools = list( /obj/item/weapon/surgical/FixOVein = 100, \ @@ -61,6 +62,7 @@ // Necrosis Surgery Step 1 /////////////////////////////////////////////////////////////// /datum/surgery_step/fix_dead_tissue //Debridement + surgery_name = "Remove Dead Tissue" priority = 2 allowed_tools = list( /obj/item/weapon/surgical/scalpel = 100, \ @@ -110,6 +112,7 @@ // Necrosis Surgery Step 2 /////////////////////////////////////////////////////////////// /datum/surgery_step/treat_necrosis + surgery_name = "Treat Necrosis" priority = 2 allowed_tools = list( /obj/item/weapon/reagent_containers/dropper = 100, @@ -187,6 +190,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/hardsuit + surgery_name = "Remove Hardsuit" allowed_tools = list( /obj/item/weapon/weldingtool = 80, /obj/item/weapon/surgical/circular_saw = 60, @@ -241,6 +245,7 @@ var/dehusk = 0 /datum/surgery_step/dehusk/ + surgery_name = "Dehusk" priority = 1 can_infect = 0 blood_level = 1 @@ -256,6 +261,7 @@ return target_zone == BP_TORSO && (HUSK in target.mutations) /datum/surgery_step/dehusk/structinitial + surgery_name = "Create Structure" allowed_tools = list( /obj/item/weapon/surgical/bioregen = 100 ) @@ -285,6 +291,7 @@ ..() /datum/surgery_step/dehusk/relocateflesh + surgery_name = "Relocate Flesh" allowed_tools = list( /obj/item/weapon/surgical/hemostat = 100, \ /obj/item/stack/cable_coil = 75, \ @@ -316,6 +323,7 @@ ..() /datum/surgery_step/dehusk/structfinish + surgery_name = "Finish Structure" allowed_tools = list( /obj/item/weapon/surgical/bioregen = 100, \ /obj/item/weapon/surgical/FixOVein = 30 @@ -357,6 +365,7 @@ ..() /datum/surgery_step/internal/detoxify + surgery_name = "Detoxify" blood_level = 1 allowed_tools = list(/obj/item/weapon/surgical/bioregen=100) min_duration = 90 @@ -385,4 +394,4 @@ "Your hand slips, failing to finish the surgery, and damaging [target] with \the [tool].") affected.createwound(CUT, 15) affected.createwound(BRUISE, 10) - ..() \ No newline at end of file + ..() diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index 4f5d451bf8..14a37f39b4 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -4,6 +4,7 @@ ////////////////////////////////////////////////////////////////// /datum/surgery_step/robotics/ + surgery_name = "Robotic Surgery" can_infect = 0 /datum/surgery_step/robotics/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -29,6 +30,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/robotics/unscrew_hatch + surgery_name = "Unscrew Hatch" allowed_tools = list( /obj/item/weapon/coin = 50, /obj/item/weapon/material/knife = 50 @@ -68,6 +70,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/robotics/open_hatch + surgery_name = "Open Hatch" allowed_tools = list( /obj/item/weapon/surgical/retractor = 100, /obj/item/weapon/material/kitchen/utensil = 50 @@ -105,6 +108,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/robotics/close_hatch + surgery_name = "Close Hatch" allowed_tools = list( /obj/item/weapon/surgical/retractor = 100, /obj/item/weapon/material/kitchen/utensil = 50 @@ -143,6 +147,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/robotics/repair_brute + surgery_name = "Repair Robotic Brute" allowed_tools = list( /obj/item/weapon/weldingtool = 100, /obj/item/weapon/pickaxe/plasmacutter = 50 @@ -188,6 +193,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/robotics/repair_burn + surgery_name = "Repair Robotic Burn" allowed_tools = list( /obj/item/stack/cable_coil = 100 ) @@ -236,6 +242,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/robotics/fix_organ_robotic //For artificial organs + surgery_name = "Fix Robotic Organ" allowed_tools = list( /obj/item/stack/nanopaste = 100, \ /obj/item/weapon/surgical/bonegel = 30, \ @@ -306,7 +313,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/robotics/detatch_organ_robotic - + surgery_name = "Detach Robotic Organ" allowed_tools = list( /obj/item/device/multitool = 100 ) @@ -321,23 +328,31 @@ if(affected.open < 3) return 0 - target.op_stage.current_organ = null + var/list/attached_organs = list() //Let's see if we have any organs able to be detached! + for(var/organ in target.internal_organs_by_name) + var/obj/item/organ/I = target.internal_organs_by_name[organ] + if(I && !(I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone) + attached_organs |= organ - var/list/attached_organs = list() + if(!attached_organs.len) //No organs able to be detached! + return 0 + + return ..() + +/datum/surgery_step/robotics/detatch_organ_robotic/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/list/attached_organs = list() //Which organs can we detach? for(var/organ in target.internal_organs_by_name) var/obj/item/organ/I = target.internal_organs_by_name[organ] if(I && !(I.status & ORGAN_CUT_AWAY) && I.parent_organ == target_zone) attached_organs |= organ var/organ_to_remove = tgui_input_list(user, "Which organ do you want to prepare for removal?", "Organ Choice", attached_organs) - if(!organ_to_remove) - return 0 + if(!organ_to_remove) //They chose cancel! + to_chat(user, "You decide against preparing any organs for removal.") + return target.op_stage.current_organ = organ_to_remove - return ..() && organ_to_remove - -/datum/surgery_step/robotics/detatch_organ_robotic/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("[user] starts to decouple [target]'s [target.op_stage.current_organ] with \the [tool].", \ "You start to decouple [target]'s [target.op_stage.current_organ] with \the [tool]." ) ..() @@ -349,6 +364,7 @@ var/obj/item/organ/internal/I = target.internal_organs_by_name[target.op_stage.current_organ] if(I && istype(I)) I.status |= ORGAN_CUT_AWAY + target.op_stage.current_organ = null /datum/surgery_step/robotics/detatch_organ_robotic/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("[user]'s hand slips, disconnecting \the [tool].", \ @@ -359,6 +375,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/robotics/attach_organ_robotic + surgery_name = "Attach Robotic Organ" allowed_procs = list(IS_SCREWDRIVER = 100) min_duration = 100 @@ -371,22 +388,33 @@ if(affected.open < 3) return 0 - target.op_stage.current_organ = null - - var/list/removable_organs = list() + var/list/attachable_organs = list() for(var/organ in target.internal_organs_by_name) var/obj/item/organ/I = target.internal_organs_by_name[organ] if(I && (I.status & ORGAN_CUT_AWAY) && (I.robotic >= ORGAN_ROBOT) && I.parent_organ == target_zone) - removable_organs |= organ + attachable_organs |= organ - var/organ_to_replace = tgui_input_list(user, "Which organ do you want to reattach?", "Organ Choice", removable_organs) - if(!organ_to_replace) + if(!attachable_organs.len) return 0 - target.op_stage.current_organ = organ_to_replace return ..() /datum/surgery_step/robotics/attach_organ_robotic/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + var/list/attachable_organs = list() + for(var/organ in target.internal_organs_by_name) + var/obj/item/organ/I = target.internal_organs_by_name[organ] + if(I && (I.status & ORGAN_CUT_AWAY) && (I.robotic >= ORGAN_ROBOT) && I.parent_organ == target_zone) + attachable_organs |= organ + + var/organ_to_replace = tgui_input_list(user, "Which organ do you want to reattach?", "Organ Choice", attachable_organs) + if(!organ_to_replace) //They chose cancel! + to_chat(user, "You decide against reattaching any organs.") + return + + + target.op_stage.current_organ = organ_to_replace + user.visible_message("[user] begins reattaching [target]'s [target.op_stage.current_organ] with \the [tool].", \ "You start reattaching [target]'s [target.op_stage.current_organ] with \the [tool].") ..() @@ -398,6 +426,7 @@ var/obj/item/organ/I = target.internal_organs_by_name[target.op_stage.current_organ] if(I && istype(I)) I.status &= ~ORGAN_CUT_AWAY + target.op_stage.current_organ = null /datum/surgery_step/robotics/attach_organ_robotic/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("[user]'s hand slips, disconnecting \the [tool].", \ @@ -408,6 +437,7 @@ /////////////////////////////////////////////////////////////// /datum/surgery_step/robotics/install_mmi + surgery_name = "Install MMI" allowed_tools = list( /obj/item/device/mmi = 100 ) @@ -479,9 +509,11 @@ if(clean_name) var/okay = tgui_alert(target,"New name will be '[clean_name]', ok?", "Confirmation",list("Cancel","Ok")) if(okay == "Ok") - target.name = new_name - target.real_name = target.name - return + new_name = clean_name + + new_name = sanitizeName(new_name, allow_numbers = TRUE) + target.name = new_name + target.real_name = target.name /datum/surgery_step/robotics/install_mmi/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("[user]'s hand slips.", \ @@ -492,6 +524,7 @@ */ /datum/surgery_step/robotics/install_nymph + surgery_name = "Install Nymph" allowed_tools = list( /obj/item/weapon/holder/diona = 100 ) diff --git a/code/modules/surgery/slimes.dm b/code/modules/surgery/slimes.dm index e73633397a..84d697272c 100644 --- a/code/modules/surgery/slimes.dm +++ b/code/modules/surgery/slimes.dm @@ -3,6 +3,7 @@ ////////////////////////////////////////////////////////////////// /datum/surgery_step/slime + surgery_name = "Slime Surgery" is_valid_target(mob/living/simple_mob/slime/target) return istype(target, /mob/living/simple_mob/slime/) @@ -12,6 +13,7 @@ /datum/surgery_step/slime/cut_flesh + surgery_name = "Cut Flesh" allowed_tools = list( /obj/item/weapon/surgical/scalpel = 100, \ /obj/item/weapon/material/knife = 75, \ @@ -40,6 +42,7 @@ /datum/surgery_step/slime/cut_innards + surgery_name = "Cut Innards" allowed_tools = list( /obj/item/weapon/surgical/scalpel = 100, \ /obj/item/weapon/material/knife = 75, \ @@ -68,6 +71,7 @@ /datum/surgery_step/slime/saw_core + surgery_name = "Remove Core" allowed_tools = list( /obj/item/weapon/surgical/circular_saw = 100, \ /obj/item/weapon/material/knife/machete/hatchet = 75 @@ -97,4 +101,4 @@ /datum/surgery_step/slime/saw_core/fail_step(mob/living/user, mob/living/simple_mob/slime/target, target_zone, obj/item/tool) var/datum/gender/T = gender_datums[user.get_visible_gender()] user.visible_message("[user]'s hand slips, causing [T.him] to miss the core!", \ - "Your hand slips, causing you to miss the core!") \ No newline at end of file + "Your hand slips, causing you to miss the core!") diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index e6e4554090..8c13af59d3 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -24,8 +24,13 @@ // evil infection stuff that will make everyone hate me var/can_infect = 0 - //How much blood this step can get on surgeon. 1 - hands, 2 - full body. + // How much blood this step can get on surgeon. 1 - hands, 2 - full body. var/blood_level = 0 + // What the surgery will be called in the rare event of multiple surgery steps being shown to the user. + var/surgery_name = "CONTACT A DEVELOPER TO NAME THIS STEP." + // If the surgery stops you from being able to perform another surgery. + var/list/excludes_steps = list() + //returns how well tool is suited for this step /datum/surgery_step/proc/tool_quality(obj/item/tool) @@ -134,49 +139,90 @@ if(!istype(M)) return 0 if (user.a_intent == I_HURT) //check for Hippocratic Oath + //Insert intentional hurt medical code here. return 0 var/zone = user.zone_sel.selecting if(zone in M.op_stage.in_progress) //Can't operate on someone repeatedly. to_chat(user, "You can't operate on this area while surgery is already in progress.") return 1 + var/obj/surface = M.get_surgery_surface(user) + if(!surface || !surface.surgery_odds) // If the surface has a chance of 0% surgery odds (ground), don't even bother trying to do surgery. + return 0 // This is meant to prevent the 'glass shard mouth 60 damage click' exploit. Also saves CPU by doing it here! + + var/list/datum/surgery_step/available_surgeries = list() for(var/datum/surgery_step/S in surgery_steps) //check if tool is right or close enough and if this step is possible if(S.tool_quality(src)) var/step_is_valid = S.can_use(user, M, zone, src) if(step_is_valid && S.is_valid_target(M)) - if(step_is_valid == SURGERY_FAILURE) // This is a failure that already has a message for failing. - return 1 - M.op_stage.in_progress += zone - S.begin_step(user, M, zone, src) //start on it - var/success = TRUE + if(step_is_valid == SURGERY_FAILURE) + continue + available_surgeries[S.surgery_name] = S //Adds the surgery name to the list and sets it equal to S. (Ex: "Cauterize" = surgery_step/cauterize) + continue - // Bad tools make it less likely to succeed. - if(!prob(S.tool_quality(src))) - success = FALSE + if(!available_surgeries.len) //No available surgeries. Failure. + return 0 - // Bad or no surface may mean failure as well. - var/obj/surface = M.get_surgery_surface() - if(!surface || !prob(surface.surgery_odds)) - success = FALSE + // Having trouble with an ASSOSCIATED LIST? or REMOVING SOMETHING FROM AN ASSOCIATED LIST? Look here for a quick guide, developed out of frustration. + // Note: This is an ultra edge case. Like, what is being done here is horrible and is so rare this should never happen again in the code. + // This block of code caused hours of suffering. - // Not staying still fails you too. - if(success) - var/calc_duration = rand(S.min_duration, S.max_duration) - if(!do_mob(user, M, calc_duration * toolspeed, zone, exclusive = TRUE)) - success = FALSE - to_chat(user, "You must remain close to and keep focused on your patient to conduct surgery.") + for(var/surgical_check_name in available_surgeries) // Get the name from available_surgeries. available_surgeries = list("NAME" = DATUM) + var/datum/surgery_step/surgical_check = available_surgeries[surgical_check_name] // We then get the datum. + if(isnull(surgical_check)) // This is here so it doesn't try to keep searching if the thing we're about to check has been deleted. + continue + if(surgical_check.excludes_steps.len) // We check for it's 'excluded_steps' list and see if it has anything in it. + for(var/removal_candidate_name in available_surgeries) // We then look in available_surgeries once again, grabbing the name. + var/datum/surgery_step/removal_candidate = available_surgeries[removal_candidate_name] // We then get the datum while searching. + if(is_path_in_list(removal_candidate.type, surgical_check.excludes_steps)) // We then check the datum and see if it's a path in the list that we want to remove. + available_surgeries -= removal_candidate_name // We then, finally, remove the surgery step. + // All of this just to make it so you are forced to do bloodless surgery with a laser scalpel. - if(success) - S.end_step(user, M, zone, src) - else - S.fail_step(user, M, zone, src) + if(M == user) // Once we determine if we can actually do a step at all, give a slight delay to self-surgery to confirm attempts. + to_chat(user, "You focus on attempting to perform surgery upon yourself.") + if(!do_after(user, 3 SECONDS, M)) + return 0 - M.op_stage.in_progress -= zone // Clear the in-progress flag. - if (ishuman(M)) - var/mob/living/carbon/human/H = M - H.update_surgery() - return 1 //don't want to do weapony things after surgery - return 0 + var/datum/surgery_step/selected_surgery + if(available_surgeries.len > 1) //More than one possible? Ask them which one. + selected_surgery = tgui_input_list(user, "Select which surgery step you wish to perform", "Surgery Select", available_surgeries) //Shows the name in the list. + else + selected_surgery = pick(available_surgeries) + + if(isnull(selected_surgery)) //They clicked 'cancel' + return 1 + selected_surgery = available_surgeries[selected_surgery] //Sets the name they selected to be the datum. + + M.op_stage.in_progress += zone + selected_surgery.begin_step(user, M, zone, src) //start on it + var/success = TRUE + + // Bad tools make it less likely to succeed. + if(!prob(selected_surgery.tool_quality(src))) + success = FALSE + + // Bad surface may mean failure as well. + if(!prob(surface.surgery_odds)) + success = FALSE + + // Not staying still fails you too. + if(success) + var/calc_duration = rand(selected_surgery.min_duration, selected_surgery.max_duration) + if(!do_mob(user, M, calc_duration * toolspeed, zone, exclusive = TRUE)) + success = FALSE + to_chat(user, "You must remain close to and keep focused on your patient to conduct surgery.") + + if(success) + selected_surgery.end_step(user, M, zone, src) + else + selected_surgery.fail_step(user, M, zone, src) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //Gets rid of instakill mechanics. + + M.op_stage.in_progress -= zone // Clear the in-progress flag. + if (ishuman(M)) + var/mob/living/carbon/human/H = M + H.update_surgery() + return 1 //don't want to do weapony things after surgery /proc/sort_surgeries() var/gap = surgery_steps.len @@ -200,4 +246,4 @@ var/brainstem = 0 var/head_reattach = 0 var/current_organ = "organ" - var/list/in_progress = list() \ No newline at end of file + var/list/in_progress = list() diff --git a/code/modules/tgs/v5/chat_commands.dm b/code/modules/tgs/v5/chat_commands.dm index 7c93526178..3deb15f52c 100644 --- a/code/modules/tgs/v5/chat_commands.dm +++ b/code/modules/tgs/v5/chat_commands.dm @@ -4,7 +4,27 @@ admin_only = FALSE /datum/tgs_chat_command/status/Run(datum/tgs_chat_user/sender, params) - return "Current server status:\n**Down! Contact staff.**| t |
, or missing
. Bailing hydration and performing ' + - 'full client-side render.' - ); - } - } - // either not server-rendered, or hydration failed. - // create an empty node and replace it - oldVnode = emptyNodeAt(oldVnode); - } - - // replacing existing element - var oldElm = oldVnode.elm; - var parentElm = nodeOps.parentNode(oldElm); - - // create new node - createElm( - vnode, - insertedVnodeQueue, - // extremely rare edge case: do not insert if old element is in a - // leaving transition. Only happens when combining transition + - // keep-alive + HOCs. (#4590) - oldElm._leaveCb ? null : parentElm, - nodeOps.nextSibling(oldElm) - ); - - // update parent placeholder node element, recursively - if (isDef(vnode.parent)) { - var ancestor = vnode.parent; - var patchable = isPatchable(vnode); - while (ancestor) { - for (var i = 0; i < cbs.destroy.length; ++i) { - cbs.destroy[i](ancestor); - } - ancestor.elm = vnode.elm; - if (patchable) { - for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) { - cbs.create[i$1](emptyNode, ancestor); - } - // #6513 - // invoke insert hooks that may have been merged by create hooks. - // e.g. for directives that uses the "inserted" hook. - var insert = ancestor.data.hook.insert; - if (insert.merged) { - // start at index 1 to avoid re-invoking component mounted hook - for (var i$2 = 1; i$2 < insert.fns.length; i$2++) { - insert.fns[i$2](); - } - } - } else { - registerRef(ancestor); - } - ancestor = ancestor.parent; - } - } - - // destroy old node - if (isDef(parentElm)) { - removeVnodes([oldVnode], 0, 0); - } else if (isDef(oldVnode.tag)) { - invokeDestroyHook(oldVnode); - } - } - } - - invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch); - return vnode.elm - } - } - - /* */ - - var directives = { - create: updateDirectives, - update: updateDirectives, - destroy: function unbindDirectives (vnode) { - updateDirectives(vnode, emptyNode); - } - }; - - function updateDirectives (oldVnode, vnode) { - if (oldVnode.data.directives || vnode.data.directives) { - _update(oldVnode, vnode); - } - } - - function _update (oldVnode, vnode) { - var isCreate = oldVnode === emptyNode; - var isDestroy = vnode === emptyNode; - var oldDirs = normalizeDirectives$1(oldVnode.data.directives, oldVnode.context); - var newDirs = normalizeDirectives$1(vnode.data.directives, vnode.context); - - var dirsWithInsert = []; - var dirsWithPostpatch = []; - - var key, oldDir, dir; - for (key in newDirs) { - oldDir = oldDirs[key]; - dir = newDirs[key]; - if (!oldDir) { - // new directive, bind - callHook$1(dir, 'bind', vnode, oldVnode); - if (dir.def && dir.def.inserted) { - dirsWithInsert.push(dir); - } - } else { - // existing directive, update - dir.oldValue = oldDir.value; - dir.oldArg = oldDir.arg; - callHook$1(dir, 'update', vnode, oldVnode); - if (dir.def && dir.def.componentUpdated) { - dirsWithPostpatch.push(dir); - } - } - } - - if (dirsWithInsert.length) { - var callInsert = function () { - for (var i = 0; i < dirsWithInsert.length; i++) { - callHook$1(dirsWithInsert[i], 'inserted', vnode, oldVnode); - } - }; - if (isCreate) { - mergeVNodeHook(vnode, 'insert', callInsert); - } else { - callInsert(); - } - } - - if (dirsWithPostpatch.length) { - mergeVNodeHook(vnode, 'postpatch', function () { - for (var i = 0; i < dirsWithPostpatch.length; i++) { - callHook$1(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode); - } - }); - } - - if (!isCreate) { - for (key in oldDirs) { - if (!newDirs[key]) { - // no longer present, unbind - callHook$1(oldDirs[key], 'unbind', oldVnode, oldVnode, isDestroy); - } - } - } - } - - var emptyModifiers = Object.create(null); - - function normalizeDirectives$1 ( - dirs, - vm - ) { - var res = Object.create(null); - if (!dirs) { - // $flow-disable-line - return res - } - var i, dir; - for (i = 0; i < dirs.length; i++) { - dir = dirs[i]; - if (!dir.modifiers) { - // $flow-disable-line - dir.modifiers = emptyModifiers; - } - res[getRawDirName(dir)] = dir; - dir.def = resolveAsset(vm.$options, 'directives', dir.name, true); - } - // $flow-disable-line - return res - } - - function getRawDirName (dir) { - return dir.rawName || ((dir.name) + "." + (Object.keys(dir.modifiers || {}).join('.'))) - } - - function callHook$1 (dir, hook, vnode, oldVnode, isDestroy) { - var fn = dir.def && dir.def[hook]; - if (fn) { - try { - fn(vnode.elm, dir, vnode, oldVnode, isDestroy); - } catch (e) { - handleError(e, vnode.context, ("directive " + (dir.name) + " " + hook + " hook")); - } - } - } - - var baseModules = [ - ref, - directives - ]; - - /* */ - - function updateAttrs (oldVnode, vnode) { - var opts = vnode.componentOptions; - if (isDef(opts) && opts.Ctor.options.inheritAttrs === false) { - return - } - if (isUndef(oldVnode.data.attrs) && isUndef(vnode.data.attrs)) { - return - } - var key, cur, old; - var elm = vnode.elm; - var oldAttrs = oldVnode.data.attrs || {}; - var attrs = vnode.data.attrs || {}; - // clone observed objects, as the user probably wants to mutate it - if (isDef(attrs.__ob__)) { - attrs = vnode.data.attrs = extend({}, attrs); - } - - for (key in attrs) { - cur = attrs[key]; - old = oldAttrs[key]; - if (old !== cur) { - setAttr(elm, key, cur); - } - } - // #4391: in IE9, setting type can reset value for input[type=radio] - // #6666: IE/Edge forces progress value down to 1 before setting a max - /* istanbul ignore if */ - if ((isIE || isEdge) && attrs.value !== oldAttrs.value) { - setAttr(elm, 'value', attrs.value); - } - for (key in oldAttrs) { - if (isUndef(attrs[key])) { - if (isXlink(key)) { - elm.removeAttributeNS(xlinkNS, getXlinkProp(key)); - } else if (!isEnumeratedAttr(key)) { - elm.removeAttribute(key); - } - } - } - } - - function setAttr (el, key, value) { - if (el.tagName.indexOf('-') > -1) { - baseSetAttr(el, key, value); - } else if (isBooleanAttr(key)) { - // set attribute for blank value - // e.g. - if (isFalsyAttrValue(value)) { - el.removeAttribute(key); - } else { - // technically allowfullscreen is a boolean attribute for