diff --git a/.github/workflows/render_nanomaps.yml b/.github/workflows/render_nanomaps.yml
index 57f305772c..d6f2622041 100644
--- a/.github/workflows/render_nanomaps.yml
+++ b/.github/workflows/render_nanomaps.yml
@@ -11,8 +11,13 @@ 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
steps:
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 4ce9b60b73..30cd6dc47b 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -6,7 +6,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/README.md b/README.md
index 2c769a3af9..3e98669224 100644
--- a/README.md
+++ b/README.md
@@ -1,101 +1,103 @@
-# Yawn-Wider
-
-[](http://forthebadge.com) [](http://forthebadge.com) [](http://forthebadge.com)
-
-[Website (we dont have one)](https://www.youtube.com/watch?v=oHg5SJYRHA0) - [Forums](https://yawn-widerstation.proboards.com/) - [Wiki](https://yawn.izac.live/index.php?title=Main_Page) - [Discord](https://discord.gg/Wh27EAY)
-
-Going to make a Pull Request? Make sure you read the [CONTRIBUTING.md](.github/CONTRIBUTING.md) first!
-
-Yawn-Wider is a fork of the VOREStation code branch which is a fork of the Polaris code branch, itself a fork of the Baystation12 code branch, for the game Space Station 13.
-
-
-[](https://github.com/Yawn-Wider/YWPolarisVore/actions/workflows/ci.yml)
-
----
-
-### LICENSE
-The code for Yawn-Wider is licensed under the [GNU Affero General Public License](http://www.gnu.org/licenses/agpl.html) version 3, which can be found in full in LICENSE-AGPL3.txt.
-
-Code with a git authorship date prior to `1420675200 +0000` (2015/01/08 00:00) are licensed under the GNU General Public License version 3, which can be found in full in LICENSE-GPL3.txt.
-
-All code whose authorship dates are not prior to `1420675200 +0000` is assumed to be licensed under AGPL v3, if you wish to license under GPL v3 please make this clear in the commit message and any added files.
-
-If you wish to develop and host this codebase in a closed source manner you may use all code prior to `1420675200 +0000`, which is licensed under GPL v3. The major change here is that if you host a server using any code licensed under AGPLv3 you are required to provide full source code for your servers users as well including addons and modifications you have made.
-
-See [here](https://www.gnu.org/licenses/why-affero-gpl.html) for more information.
-
-Any files located in the
-`vorestation/goon`,
-`vorestation/icons/goonstation`, or
-`vorestation/sound/goonstation`
-directories, or any subdirectories of mentioned directories are licensed under the
-Creative Commons 3.0 BY-NC-SA license
-(https://creativecommons.org/licenses/by-nc-sa/3.0)
-
-All assets including icons and sound are under a [CC BY-SA 3.0](http://creativecommons.org/licenses/by-sa/3.0/) license unless otherwise indicated.
-
-Attributions and other licenses with links to original works are noted in [ATTRIBUTIONS.md](./ATTRIBUTIONS.md).
-
-### GETTING THE CODE
-The simplest way to obtain the code is using the github .zip feature. If you do this, you won't be able to make a Pull Request later, though. You'll need to use the git method.
-
-Click [here](https://github.com/Yawn-Wider/YWPolarisVore/archive/master.zip) to get the latest code as a .zip file, then unzip it to wherever you want.
-
-The more complicated and easier to update method is using git. You'll need to download git or some client from [here](http://git-scm.com/). When that's installed, right click in any folder and click on "Git Bash". When that opens, type in:
-
- git clone https://github.com/Yawn-Wider/YWPolarisVore.git
-
-(hint: hold down ctrl and press insert to paste into git bash)
-
-This will take a while to download, but it provides an easier method for updating.
-
-### INSTALLATION
-
-First-time installation should be fairly straightforward. First, you'll need BYOND installed. You can get it from [here](http://www.byond.com/).
-
-This is a sourcecode-only release, so the next step is to compile the server files. Open vorestation.dme by double-clicking it, open the Build menu, and click compile. This'll take a little while, and if everything's done right you'll get a message like this:
-
- saving vorestation.dmb (DEBUG mode)
-
- vorestation.dmb - 0 errors, 0 warnings
-
-If you see any errors or warnings, something has gone wrong - possibly a corrupt download or the files extracted wrong, or a code issue on the main repo. Ask on IRC.
-
-Once that's done, open up the config folder. You'll want to edit config.txt to set the probabilities for different gamemodes in Secret and to set your server location so that all your players don't get disconnected at the end of each round. It's recommended you don't turn on the gamemodes with probability 0, as they have various issues and aren't currently being tested, so they may have unknown and bizarre bugs.
-
-You'll also want to edit admins.txt to remove the default admins and add your own. "Host" is the highest level of access, and the other recommended admin levels for now are "Game Admin" and "Moderator". The format is:
-
- byondkey - Rank
-
-where the BYOND key must be in lowercase and the admin rank must be properly capitalised. There are a bunch more admin ranks, but these two should be enough for most servers, assuming you have trustworthy admins.
-
-Finally, to start the server, run Dream Daemon and enter the path to your compiled vorestation.dmb file. Make sure to set the port to the one you specified in the config.txt, and set the Security box to 'Trusted'. Then press GO and the server should start up and be ready to join.
-
----
-
-### UPDATING
-
-To update an existing installation, first back up your /config and /data folders
-as these store your server configuration, player preferences and banlist.
-
-If you used the zip method, you'll need to download the zip file again and unzip it somewhere else, and then copy the /config and /data folders over.
-
-If you used the git method, you simply need to type this in to git bash:
-
- git pull
-
-When this completes, copy over your /data and /config folders again, just in case.
-
-When you have done this, you'll need to recompile the code, but then it should work fine.
-
----
-
-### Configuration
-
-For a basic setup, simply copy every file from config/example to config.
-
----
-
-### SQL Setup
-
-The SQL backend for the library and stats tracking requires a MySQL server. Your server details go in /config/dbconfig.txt, and the SQL schema is in /SQL/tgstation_schema.sql. More detailed setup instructions arecoming soon, for now ask in our Discord.
\ No newline at end of file
+# Yawn-Wider
+
+[](http://forthebadge.com) [](http://forthebadge.com) [](http://forthebadge.com)
+
+[Website (we dont have one)](https://www.youtube.com/watch?v=oHg5SJYRHA0) - [Forums](https://yawn-widerstation.proboards.com/) - [Wiki](https://yawn.izac.live/index.php?title=Main_Page) - [Discord](https://discord.gg/Wh27EAY)
+
+Going to make a Pull Request? Make sure you read the [CONTRIBUTING.md](.github/CONTRIBUTING.md) first!
+
+Want to make a test server or your own private server? Read our [GitHub Wiki!](https://github.com/VOREStation/VOREStation/wiki)
+
+Yawn-Wider is a fork of the VOREStation code branch which is a fork of the Polaris code branch, itself a fork of the Baystation12 code branch, for the game Space Station 13.
+
+
+[](https://github.com/Yawn-Wider/YWPolarisVore/actions/workflows/ci.yml)
+
+---
+
+### LICENSE
+The code for Yawn-Wider is licensed under the [GNU Affero General Public License](http://www.gnu.org/licenses/agpl.html) version 3, which can be found in full in LICENSE-AGPL3.txt.
+
+Code with a git authorship date prior to `1420675200 +0000` (2015/01/08 00:00) are licensed under the GNU General Public License version 3, which can be found in full in LICENSE-GPL3.txt.
+
+All code whose authorship dates are not prior to `1420675200 +0000` is assumed to be licensed under AGPL v3, if you wish to license under GPL v3 please make this clear in the commit message and any added files.
+
+If you wish to develop and host this codebase in a closed source manner you may use all code prior to `1420675200 +0000`, which is licensed under GPL v3. The major change here is that if you host a server using any code licensed under AGPLv3 you are required to provide full source code for your servers users as well including addons and modifications you have made.
+
+See [here](https://www.gnu.org/licenses/why-affero-gpl.html) for more information.
+
+Any files located in the
+`vorestation/goon`,
+`vorestation/icons/goonstation`, or
+`vorestation/sound/goonstation`
+directories, or any subdirectories of mentioned directories are licensed under the
+Creative Commons 3.0 BY-NC-SA license
+(https://creativecommons.org/licenses/by-nc-sa/3.0)
+
+All assets including icons and sound are under a [CC BY-SA 3.0](http://creativecommons.org/licenses/by-sa/3.0/) license unless otherwise indicated.
+
+Attributions and other licenses with links to original works are noted in [ATTRIBUTIONS.md](./ATTRIBUTIONS.md).
+
+### GETTING THE CODE
+The simplest way to obtain the code is using the github .zip feature. If you do this, you won't be able to make a Pull Request later, though. You'll need to use the git method.
+
+Click [here](https://github.com/Yawn-Wider/YWPolarisVore/archive/master.zip) to get the latest code as a .zip file, then unzip it to wherever you want.
+
+The more complicated and easier to update method is using git. You'll need to download git or some client from [here](http://git-scm.com/). When that's installed, right click in any folder and click on "Git Bash". When that opens, type in:
+
+ git clone https://github.com/Yawn-Wider/YWPolarisVore.git
+
+(hint: hold down ctrl and press insert to paste into git bash)
+
+This will take a while to download, but it provides an easier method for updating.
+
+### INSTALLATION
+
+First-time installation should be fairly straightforward. First, you'll need BYOND installed. You can get it from [here](http://www.byond.com/).
+
+This is a sourcecode-only release, so the next step is to compile the server files. Open vorestation.dme by double-clicking it, open the Build menu, and click compile. This'll take a little while, and if everything's done right you'll get a message like this:
+
+ saving vorestation.dmb (DEBUG mode)
+
+ vorestation.dmb - 0 errors, 0 warnings
+
+If you see any errors or warnings, something has gone wrong - possibly a corrupt download or the files extracted wrong, or a code issue on the main repo. Ask on IRC.
+
+Once that's done, open up the config folder. You'll want to edit config.txt to set the probabilities for different gamemodes in Secret and to set your server location so that all your players don't get disconnected at the end of each round. It's recommended you don't turn on the gamemodes with probability 0, as they have various issues and aren't currently being tested, so they may have unknown and bizarre bugs.
+
+You'll also want to edit admins.txt to remove the default admins and add your own. "Host" is the highest level of access, and the other recommended admin levels for now are "Game Admin" and "Moderator". The format is:
+
+ byondkey - Rank
+
+where the BYOND key must be in lowercase and the admin rank must be properly capitalised. There are a bunch more admin ranks, but these two should be enough for most servers, assuming you have trustworthy admins.
+
+Finally, to start the server, run Dream Daemon and enter the path to your compiled vorestation.dmb file. Make sure to set the port to the one you specified in the config.txt, and set the Security box to 'Trusted'. Then press GO and the server should start up and be ready to join.
+
+---
+
+### UPDATING
+
+To update an existing installation, first back up your /config and /data folders
+as these store your server configuration, player preferences and banlist.
+
+If you used the zip method, you'll need to download the zip file again and unzip it somewhere else, and then copy the /config and /data folders over.
+
+If you used the git method, you simply need to type this in to git bash:
+
+ git pull
+
+When this completes, copy over your /data and /config folders again, just in case.
+
+When you have done this, you'll need to recompile the code, but then it should work fine.
+
+---
+
+### Configuration
+
+For a basic setup, simply copy every file from config/example to config.
+
+---
+
+### SQL Setup
+
+The SQL backend for the library and stats tracking requires a MySQL server. Your server details go in /config/dbconfig.txt, and the SQL schema is in /SQL/tgstation_schema.sql. More detailed setup instructions arecoming soon, for now ask in our Discord.
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/__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 7086ef7c9d..97f30e5247 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/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/subsystems.dm b/code/__defines/subsystems.dm
index 8ed8125dac..716a1c1540 100644
--- a/code/__defines/subsystems.dm
+++ b/code/__defines/subsystems.dm
@@ -118,26 +118,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)"}
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 b4406f5a0b..fd21a86c6f 100644
--- a/code/game/machinery/pointdefense.dm
+++ b/code/game/machinery/pointdefense.dm
@@ -94,7 +94,8 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/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)
@@ -211,7 +212,8 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
/obj/machinery/power/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
@@ -295,7 +297,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
var/obj/machinery/pointdefense_control/PC = get_controller()
if(!istype(PC))
return
-
+
// Compile list of known targets
var/list/existing_targets = list()
for(var/weakref/WR in PC.targets)
@@ -319,7 +321,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
engaging = target
Shoot(target)
return
-
+
/obj/machinery/power/pointdefense/proc/targeting_check(var/obj/effect/meteor/M)
// Target in range
var/list/connected_z_levels = GetConnectedZlevels(get_z(src))
@@ -330,7 +332,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
// If we can shoot it, then shoot
if(emagged || !space_los(M))
return FALSE
-
+
return TRUE
/obj/machinery/power/pointdefense/RefreshParts()
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index ea2854480a..db94f63adb 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) //VOREStation Add - NSFW Batteries
+ 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/device/personal_shield_generator) //VOREStation Add - NSFW Batteries
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 d2adbad8da..44459d1b96 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -100,12 +100,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()
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 e678b36f67..124f5171b4 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/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/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 d3614f03c2..35af662ac2 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
/obj/item/weapon/banner/virgov
name = "\improper VirGov banner"
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 749797c433..4353520880 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -96,7 +96,8 @@
explode(M)
if(istype(M, /mob/living/))
- if(!M.hovering)
+ var/mob/living/mob = M
+ if(!mob.hovering || !mob.flying)
explode(M)
/obj/effect/mine/attackby(obj/item/W as obj, mob/living/user as mob)
@@ -398,6 +399,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 || !L.flying)
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/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/explosion_recursive.dm b/code/game/objects/explosion_recursive.dm
index a8067805a2..d60dc90f3e 100644
--- a/code/game/objects/explosion_recursive.dm
+++ b/code/game/objects/explosion_recursive.dm
@@ -6,19 +6,14 @@
/obj
var/explosion_resistance
-
-
-var/list/explosion_turfs = list()
-
-var/explosion_in_progress = 0
-
-
/proc/explosion_rec(turf/epicenter, power)
+ var/list/explosion_turfs = list()
+ var/explosion_in_progress = 0
var/loopbreak = 0
while(explosion_in_progress)
if(loopbreak >= 15) return
- sleep(10)
+ spawn(10)
loopbreak++
if(power <= 0) return
@@ -39,7 +34,7 @@ var/explosion_in_progress = 0
//This steap handles the gathering of turfs which will be ex_act() -ed in the next step. It also ensures each turf gets the maximum possible amount of power dealt to it.
for(var/direction in cardinal)
var/turf/T = get_step(epicenter, direction)
- T.explosion_spread(power - epicenter.explosion_resistance, direction)
+ T.explosion_spread(power - epicenter.explosion_resistance, direction, explosion_turfs)
//This step applies the ex_act effects for the explosion, as planned in the previous step.
for(var/turf/T in explosion_turfs)
@@ -56,8 +51,10 @@ var/explosion_in_progress = 0
T.ex_act(severity)
if(!T)
T = locate(x,y,z)
- for(var/atom/A in T)
- A.ex_act(severity)
+ for(var/atom_movable in T.contents)
+ var/atom/movable/AM = atom_movable
+ if(AM && AM.simulated)
+ AM.ex_act(severity)
explosion_in_progress = 0
@@ -67,6 +64,9 @@ var/explosion_in_progress = 0
/turf/space
explosion_resistance = 3
+/turf/simulated/open
+ explosion_resistance = 3
+
/turf/simulated/floor
explosion_resistance = 1
@@ -90,17 +90,12 @@ var/explosion_in_progress = 0
//Code-wise, a safe value for power is something up to ~25 or ~30.. This does quite a bit of damage to the station.
//direction is the direction that the spread took to come to this tile. So it is pointing in the main blast direction - meaning where this tile should spread most of it's force.
-/turf/proc/explosion_spread(power, direction)
+/turf/proc/explosion_spread(power, direction, var/list/explosion_turfs)
if(power <= 0)
return
-
- /*
- sleep(2)
- new/obj/effect/debugging/marker(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(src in explosion_turfs)
+ 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
@@ -109,11 +104,11 @@ var/explosion_in_progress = 0
spread_power -= O.explosion_resistance
var/turf/T = get_step(src, direction)
- T.explosion_spread(spread_power, direction)
+ T.explosion_spread(spread_power, direction, explosion_turfs)
T = get_step(src, turn(direction,90))
- T.explosion_spread(spread_power, 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))
+ 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
\ No newline at end of file
+ return //So it doesn't get to the parent proc, which simulates explosions
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 06099b325a..279f77c511 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/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 += "| 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