diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 013a7d1e205..1b1a8f07c83 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -1,16 +1,16 @@
#CONTRIBUTING
-##Reporting Issues
+## Reporting Issues
See [this page](http://tgstation13.org/wiki/Reporting_Issues) for a guide and format to issue reports.
-##Introduction
+## Introduction
Hello and welcome to /tg/station's contributing page. You are here because you are curious or interested in contributing. Thanks for being interested. Everyone is free to contribute to this project as long as they follow the simple guidelines and specifications below, because at /tg/station, we have a goal to increase code maintainability and to do that we are going to need all pull requests to hold up to those specifications. This is in order for all of us to benefit, instead of having to fix the same bug more than once because of duplicated code.
But first we want to make it clear how you can contribute, if contributing is a new experience for you, and what powers the team has over your pull request so you do not get any surprises when submitting pull requests, and it is closed for a reason you did not anticipate.
-##Getting Started
+## Getting Started
At /tg/station we do not have a list of goals and features to add, we instead allow freedom for contributors to suggest and create their ideas for the game. That does not mean we aren't determined to squash bugs, which unfortunately pop up a lot due to the deep complexity of the game. Here are some useful getting started guides, if you want to contribute or if you want to know what challenges you can tackle with zero knowledge about the game's code structure.
If you want to contribute the first thing you'll need to do is [set up Git](http://tgstation13.org/wiki/Setting_up_git) so you can download the source code.
@@ -21,7 +21,7 @@ There is an open list of approachable issues for [your inspiration here](https:/
You can of course, as always, ask for help at [#coderbus](irc://irc.rizon.net/coderbus) on irc.rizon.net. We are just here to have fun and help so do not expect professional support please.
-##Meet the Team
+## Meet the Team
**Project Leads**
@@ -37,14 +37,14 @@ Maintainers are quality control. If a proposed pull request does not meet the me
Maintainers can revert your changes if they feel they are not worth maintaining or if they did not live up to the quality specifications.
-##Specification
+## Specification
As mentioned before, you are expected to follow these specifications in order to make everyone's lives easier, it will also save you and us time, with having to make the changes and us having to tell you what to change. Thank you for reading this section.
-###Object Oriented code
+### Object Oriented code
As BYOND's Dream Maker is an object oriented language, code must be object oriented when possible in order to be more flexible when adding content to it. If you are unfamiliar with this concept, it is highly recommended you look it up.
-###All Byond paths must contain the full path.
+### All Byond paths must contain the full path.
(ie: absolute pathing)
Byond will allow you nest almost any type keyword into a block, such as:
@@ -98,16 +98,16 @@ The previous code made compliant:
code
```
-###No overriding type safety checks.
+### No overriding type safety checks.
The use of the : operator to override type safety checks is not allowed. You must cast the variable to the proper type.
-###Type paths must began with a /
+### Type paths must began with a /
eg: `/datum/thing` not `datum/thing`
-###Datum type paths must began with "datum"
+### Datum type paths must began with "datum"
In byond this is optional, but omitting it makes finding definitions harder.
-###Do not use text/string based type paths
+### Do not use text/string based type paths
It is rarely allowed to put type paths in a text format, as there are no compile errors if the type path no longer exists. Here is an example:
```C++
@@ -118,22 +118,22 @@ var/path_type = /obj/item/weapon/baseball_bat
var/path_type = "/obj/item/weapon/baseball_bat"
```
-###Tabs not spaces
+### Tabs not spaces
You must use tabs to indent your code, NOT SPACES.
(You may use spaces to align something, but you should tab to the block level first, then add the remaining spaces)
-###No Hacky code
+### No Hacky code
Hacky code, such as adding specific checks, is highly discouraged and only allowed when there is ***no*** other option. (Protip: 'I couldn't immediately think of a proper way so thus there must be no other option' is not gonna cut it here )
You can avoid hacky code by using object oriented methodologies, such as overriding a function (called procs in DM) or sectioning code into functions and then overriding them as required.
-###No duplicated code.
+### No duplicated code.
Copying code from one place to another maybe suitable for small short time projects but /tg/station focuses on the long term and thus discourages this.
Instead you can use object orientation, or simply placing repeated code in a function, to obey this specification easily.
-###Startup/Runtime tradeoffs with lists and the "hidden" init proc
+### Startup/Runtime tradeoffs with lists and the "hidden" init proc
First, read the comments in this byond thread, starting here:http://www.byond.com/forum/?post=2086980&page=2#comment19776775
There are two key points here:
@@ -144,19 +144,19 @@ There are two key points here:
Remember, this tradeoff makes sense in many cases but not all, you should think carefully about your implementation before deciding if this is an appropriate thing to do
-###Prefer `Initialize` over `New` for atoms
+### Prefer `Initialize` over `New` for atoms
Our game controller is pretty good at handling long operations and lag. But, it can't control what happens when the map is loaded, which calls `New` for all atoms on the map. If you're creating a new atom, use the `Initialize` proc to do what you would normally do in `New`. This cuts down on the number of proc calls needed when the world is loaded. See here for details on `Initialize`: https://github.com/tgstation/tgstation/blob/master/code/game/atoms.dm#L49
-###No magic numbers or strings
+### No magic numbers or strings
Make these #defines with a name that more clearly states what it's for.
-###Control statements:
+### Control statements:
(if,while,for,etc)
* All control statements must not contain code on the same line as the statement (`if (blah) return`)
* All control statements comparing a variable to a number should use the formula of `thing` `operator` `number`, not the reverse (eg: `if (count <= 10)` not `if (10 >= count)`)
-###Use early return.
+### Use early return.
Do not enclose a proc in an if block when returning on a condition is more feasible
This is bad:
````
@@ -179,7 +179,7 @@ This is good:
````
This prevents nesting levels from getting deeper then they need to be.
-###Develop Secure Code
+### Develop Secure Code
* Player input must always be escaped safely, we recommend you use stripped_input in all cases where you would use input. Essentially, just always treat input from players as inherently malicious and design with that use case in mind
@@ -193,14 +193,14 @@ This prevents nesting levels from getting deeper then they need to be.
* Where you have code that can cause large scale modification and *FUN* make sure you start it out locked behind one of the default admin roles - use common sense to determine which role fits the level of damage a function could do
-###Files
+### Files
* Because runtime errors do not give the full path, try to avoid having files with the same name across folders.
* File names should not be mixed case, or contain spaces or any character that would require escaping in a uri.
* Files and path accessed and referenced by code above simply being #included should be strictly lowercase to avoid issues on filesystems where case matters.
-###Other Notes
+### Other Notes
* Code should be modular where possible, if you are working on a new class then it is best if you put it in a new file.
* Bloated code may be necessary to add a certain feature, which means there has to be a judgement over whether the feature is worth having or not. You can help make this decision easier by making sure your code is modular.
@@ -209,7 +209,7 @@ This prevents nesting levels from getting deeper then they need to be.
* Do not divide when you can easily convert it to a multiplication. (ie `4/2` should be done as `4*0.5`)
-####Enforced not enforced
+#### Enforced not enforced
The following different coding styles are not only not enforced, but it is generally frowned upon to change them over from one to the other for little reason:
* English/British spelling on var/proc names
@@ -217,7 +217,7 @@ The following different coding styles are not only not enforced, but it is gener
* Spaces after control statements
* if() if () nobody cares.
-####Operators and spaces:
+#### Operators and spaces:
(this is not strictly enforced, but more a guideline for readability's sake)
* Operators that should be separated by spaces
@@ -232,7 +232,7 @@ The following different coding styles are not only not enforced, but it is gener
Math operators like +, -, /, *, etc are up in the air, just choose which version looks more readable.
-###Dream Maker Quirks/Tricks:
+### Dream Maker Quirks/Tricks:
Like all languages, Dream Maker has its quirks, some of them are beneficial to us, like these
* In-To for loops: ```for(var/i = 1, i <= some_value, i++)``` is a fairly standard way to write an incremental for loop in most languages (especially those in the C family) however DM's ```for(var/i in 1 to some_value)``` syntax is oddly faster than its implementation of the former syntax; where possible it's advised to use DM's syntax. (Note, the ```to``` keyword is inclusive, so it automatically defaults to replacing ```<=```, if you want ```<``` then you should write it as ```1 to some_value-1```).
@@ -276,7 +276,7 @@ H.gib()
however DM also has a dot variable, accessed just as ```.``` on it's own, defaulting to a value of null, now what's special about the dot operator is that it is automatically returned (as in the ```return``` statment) at the end of a proc, provided the proc does not already manually return (```return count``` for example). Why is this special? well the ```return``` statement should ideally be free from overhead (functionally free, of course nothing's free) but DM fails to fulfill this, DM's return statement is actually fairly costly for what it does and for what it's used for.
With ```.``` being everpresent in every proc can we use it as a temporary variable? Of course we can! However the ```.``` operator cannot replace a typecasted variable, it can hold data any other var in DM can, it just can't be accessed as one, however the ```.``` operator is compatible with a few operators that look weird but work perfectly fine, such as: ```.++``` for incrementing ```.'s``` value, or ```.[1]``` for accessing the first element of ```.``` (provided it's a list).
-##Pull Request Process
+## Pull Request Process
There is no strict process when it comes to merging pull requests, pull requests will sometimes take a while before they are looked at by a maintainer, the bigger the change the more time it will take before they are accepted into the code. Every team member is a volunteer who is giving up their own time to help maintain and contribute, so please be nice. Here are some helpful ways to make it easier for you and for the maintainer when making a pull request.
@@ -297,7 +297,7 @@ Do not add any of the following in a Pull Request or risk getting the PR closed:
* National Socialist Party of Germany content, National Socialist Party of Germany related content, or National Socialist Party of Germany references
* Code where one line of code is split across mutiple lines (except for multiple, separate strings and comments and in those cases existing longer lines must not be split up)
-##A word on git
+## A word on git
Yes we know that the files have a tonne of mixed windows and linux line endings, attempts to fix this have been met with less than stellar success and as such we have decided to give up caring until such a time as it matters.
Therefore EOF settings of main repo are forbidden territory one must avoid wandering into
diff --git a/README.md b/README.md
index e0bbf84967e..4bc94b8dd75 100644
--- a/README.md
+++ b/README.md
@@ -121,24 +121,22 @@ IRC channel/server, see the /bot folder for more
## CONTRIBUTING
-Please see [CONTRIBUTING.md](CONTRIBUTING.md)
+Please see [CONTRIBUTING.md](.github/CONTRIBUTING.md)
## LICENSE
-All code after commit 333c566b88108de218d882840e61928a9b759d8f on 2014/31/12 at 4:38 PM PST (https://github.com/tgstation/tgstation/commit/333c566b88108de218d882840e61928a9b759d8f) is licensed under GNU AGPL v3 (http://www.gnu.org/licenses/agpl-3.0.html).
+All code after [commit 333c566b88108de218d882840e61928a9b759d8f on 2014/31/12 at 4:38 PM PST](https://github.com/tgstation/tgstation/commit/333c566b88108de218d882840e61928a9b759d8f) is licensed under [GNU AGPL v3](http://www.gnu.org/licenses/agpl-3.0.html).
-All code before commit 333c566b88108de218d882840e61928a9b759d8f on 2014/31/12 at 4:38 PM PST (https://github.com/tgstation/tgstation/commit/333c566b88108de218d882840e61928a9b759d8f) is licensed under GNU GPL v3 (https://www.gnu.org/licenses/gpl-3.0.html).
+All code before [commit 333c566b88108de218d882840e61928a9b759d8f on 2014/31/12 at 4:38 PM PST](https://github.com/tgstation/tgstation/commit/333c566b88108de218d882840e61928a9b759d8f) is licensed under [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.html).
(Including tools unless their readme specifies otherwise.)
See LICENSE-AGPLv3.txt and LICENSE-GPLv3.txt for more details.
tgui clientside is licensed as a subproject under the MIT license.
Font Awesome font files, used by tgui, are licensed under the SIL Open Font License v1.1
-tgui assets are licensed under a Creative Commons Attribution-ShareAlike 4.0 International License
-(http://creativecommons.org/licenses/by-sa/4.0/).
+tgui assets are licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).
See tgui/LICENSE.md for the MIT license.
See tgui/assets/fonts/SIL-OFL-1.1-LICENSE.md for the SIL Open Font License.
-All assets including icons and sound are under a Creative Commons 3.0 BY-SA
-license (http://creativecommons.org/licenses/by-sa/3.0/) unless otherwise indicated.
+All assets including icons and sound are under a [Creative Commons 3.0 BY-SA license](http://creativecommons.org/licenses/by-sa/3.0/) unless otherwise indicated.
diff --git a/_maps/map_files/generic/Centcomm.dmm b/_maps/map_files/generic/Centcomm.dmm
index 725135f0d34..87f6dbde560 100644
--- a/_maps/map_files/generic/Centcomm.dmm
+++ b/_maps/map_files/generic/Centcomm.dmm
@@ -14446,7 +14446,7 @@
/area/wizard_station)
"KN" = (
/obj/machinery/light/small{
- dir = 8
+ dir = 4
},
/turf/open/floor/engine/cult,
/area/wizard_station)
@@ -62947,7 +62947,7 @@ tH
qk
Ks
ql
-Ma
+LY
Mb
yS
Lc
diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm
index 2e7c8f4a412..ab0b6690e1c 100644
--- a/code/__DEFINES/admin.dm
+++ b/code/__DEFINES/admin.dm
@@ -43,7 +43,6 @@
#define ADMIN_VV(atom) "(VV)"
#define ADMIN_SM(user) "(SM)"
#define ADMIN_TP(user) "(TP)"
-#define ADMIN_BSA(user) "(BSA)"
#define ADMIN_KICK(user) "(KICK)"
#define ADMIN_CENTCOM_REPLY(user) "(RPLY)"
#define ADMIN_SYNDICATE_REPLY(user) "(RPLY)"
@@ -61,4 +60,5 @@
#define ADMIN_PUNISHMENT_LIGHTNING "Lightning bolt"
#define ADMIN_PUNISHMENT_BRAINDAMAGE "Brain damage"
-#define ADMIN_PUNISHMENT_GIB "Gib"
\ No newline at end of file
+#define ADMIN_PUNISHMENT_GIB "Gib"
+#define ADMIN_PUNISHMENT_BSA "Bluespace Artillery Device"
\ No newline at end of file
diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm
index 8e18c414792..e36348f4e22 100644
--- a/code/__DEFINES/clockcult.dm
+++ b/code/__DEFINES/clockcult.dm
@@ -87,10 +87,8 @@ var/global/list/all_scripture = list() //a list containing scripture instances;
#define GATEWAY_RATVAR_ARRIVAL 300 //when progress is at or above this, game over ratvar's here everybody go home
-//Objective defines
-#define CLOCKCULT_GATEWAY "summon ratvar"
-
-#define CLOCKCULT_ESCAPE "proselytize the station"
+//Objective text define
+#define CLOCKCULT_OBJECTIVE "Construct the Ark of the Clockwork Justicar and free Ratvar."
//misc clockcult stuff
#define MARAUDER_EMERGE_THRESHOLD 65 //marauders cannot emerge unless host is at this% or less health
diff --git a/code/__DEFINES/tick.dm b/code/__DEFINES/tick.dm
index 393ad99eda6..3fa6e21bf3c 100644
--- a/code/__DEFINES/tick.dm
+++ b/code/__DEFINES/tick.dm
@@ -4,4 +4,4 @@
#define TICK_LIMIT_MC_INIT_DEFAULT 98
#define TICK_CHECK ( world.tick_usage > CURRENT_TICKLIMIT )
-#define CHECK_TICK if (world.tick_usage > CURRENT_TICKLIMIT) stoplag()
+#define CHECK_TICK if TICK_CHECK stoplag()
diff --git a/code/_globalvars/lists/poll_ignore.dm b/code/_globalvars/lists/poll_ignore.dm
index 23db4f6ae6a..afe97a9213c 100644
--- a/code/_globalvars/lists/poll_ignore.dm
+++ b/code/_globalvars/lists/poll_ignore.dm
@@ -4,5 +4,6 @@
#define POLL_IGNORE_SENTIENCE_POTION "sentience_potion"
#define POLL_IGNORE_POSSESSED_BLADE "possessed_blade"
#define POLL_IGNORE_ALIEN_LARVA "alien_larva"
+#define POLL_IGNORE_CLOCKWORK_MARAUDER "clockwork_marauder"
var/list/poll_ignore = list()
diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm
index 188d52a51f7..b2b0553eb44 100644
--- a/code/controllers/subsystem/atoms.dm
+++ b/code/controllers/subsystem/atoms.dm
@@ -25,12 +25,16 @@ SUBSYSTEM_DEF(atoms)
initialized = INITIALIZATION_INNEW_MAPLOAD
+ var/static/list/NewQdelList = list()
+
if(atoms)
for(var/I in atoms)
var/atom/A = I
if(!A.initialized) //this check is to make sure we don't call it twice on an object that was created in a previous Initialize call
if(QDELETED(A))
- stack_trace("Found new qdeletion in type [A.type]!")
+ if(!(NewQdelList[A.type]))
+ WARNING("Found new qdeletion in type [A.type]!")
+ NewQdelList[A.type] = TRUE
continue
var/start_tick = world.time
if(A.Initialize(TRUE))
@@ -46,7 +50,9 @@ SUBSYSTEM_DEF(atoms)
for(var/atom/A in world)
if(!A.initialized) //this check is to make sure we don't call it twice on an object that was created in a previous Initialize call
if(QDELETED(A))
- stack_trace("Found new qdeletion in type [A.type]!")
+ if(!(NewQdelList[A.type]))
+ WARNING("Found new qdeletion in type [A.type]!")
+ NewQdelList[A.type] = TRUE
continue
var/start_tick = world.time
if(A.Initialize(TRUE))
diff --git a/code/datums/weather/weather_types.dm b/code/datums/weather/weather_types.dm
index 363d9fb5871..4f1daa02766 100644
--- a/code/datums/weather/weather_types.dm
+++ b/code/datums/weather/weather_types.dm
@@ -184,3 +184,33 @@
status_signal.data["picture_state"] = "radiation"
frequency.post_signal(src, status_signal)
+
+
+/datum/weather/acid_rain
+ name = "acid rain"
+ desc = "Some stay dry and others feel the pain"
+
+ telegraph_duration = 400
+ telegraph_message = "Stinging droplets start to fall upon you.."
+ telegraph_sound = 'sound/ambience/acidrain_start.ogg'
+
+ weather_message = "Your skin melts underneath the rain!"
+ weather_overlay = "acid_rain"
+ weather_duration_lower = 600
+ weather_duration_upper = 1500
+ weather_sound = 'sound/ambience/acidrain_mid.ogg'
+
+ end_duration = 100
+ end_message = "The rain starts to dissipate."
+ end_sound = 'sound/ambience/acidrain_end.ogg'
+
+ area_type = /area/lavaland/surface/outdoors
+ target_z = ZLEVEL_LAVALAND
+
+ immunity_type = "acid" // temp
+
+
+/datum/weather/acid_rain/impact(mob/living/L)
+ var/resist = L.getarmor(null, "acid")
+ if(prob(max(0,100-resist)))
+ L.acid_act(20,20)
\ No newline at end of file
diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm
index 09fd7255945..8ab436faf18 100644
--- a/code/game/gamemodes/clock_cult/clock_cult.dm
+++ b/code/game/gamemodes/clock_cult/clock_cult.dm
@@ -84,7 +84,6 @@ Credit where due:
/datum/game_mode
var/list/servants_of_ratvar = list() //The Enlightened servants of Ratvar
- var/clockwork_objective = CLOCKCULT_GATEWAY //The objective that the servants must fulfill
var/clockwork_explanation = "Construct a Gateway to the Celestial Derelict and free Ratvar." //The description of the current objective
/datum/game_mode/clockwork_cult
@@ -126,7 +125,6 @@ Credit where due:
return 1
/datum/game_mode/clockwork_cult/post_setup()
- forge_clock_objectives()
for(var/S in servants_to_serve)
var/datum/mind/servant = S
log_game("[servant.key] was made an initial servant of Ratvar")
@@ -137,16 +135,6 @@ Credit where due:
..()
return 1
-/datum/game_mode/clockwork_cult/proc/forge_clock_objectives() //Determine what objective that Ratvar's servants will fulfill
- var/list/possible_objectives = list(CLOCKCULT_ESCAPE, CLOCKCULT_GATEWAY)
- clockwork_objective = pick(possible_objectives)
- switch(clockwork_objective)
- if(CLOCKCULT_ESCAPE)
- clockwork_explanation = "Construct a Gateway to the Celestial Derelict and proselytize the entire station."
- if(CLOCKCULT_GATEWAY)
- clockwork_explanation = "Construct a Gateway to the Celestial Derelict and free Ratvar."
- return 1
-
/datum/game_mode/clockwork_cult/proc/greet_servant(mob/M) //Description of their role
if(!M)
return 0
@@ -182,21 +170,18 @@ Credit where due:
if(!L || !istype(L) || !L.mind)
return 0
var/datum/mind/M = L.mind
- to_chat(M.current, "This is Ratvar's will: [clockwork_explanation]")
- M.memory += "Ratvar's will: [clockwork_explanation]
"
+ to_chat(M.current, "This is Ratvar's will: [CLOCKCULT_OBJECTIVE]")
+ M.memory += "Ratvar's will: [CLOCKCULT_OBJECTIVE]
"
return 1
/datum/game_mode/clockwork_cult/proc/check_clockwork_victory()
- switch(clockwork_objective)
- if(CLOCKCULT_ESCAPE)
- if(clockwork_gateway_activated)
- SSticker.news_report = CLOCK_PROSELYTIZATION
- return TRUE
- if(CLOCKCULT_GATEWAY)
- if(ratvar_awakens)
- SSticker.news_report = CLOCK_SUMMON
- return TRUE
- SSticker.news_report = CULT_FAILURE
+ if(clockwork_gateway_activated)
+ SSticker.news_report = CLOCK_PROSELYTIZATION //failure, technically, but we have the station
+ if(ratvar_awakens)
+ SSticker.news_report = CLOCK_SUMMON
+ return TRUE
+ else
+ SSticker.news_report = CULT_FAILURE
return FALSE
/datum/game_mode/clockwork_cult/declare_completion()
@@ -209,20 +194,20 @@ Credit where due:
var/datum/game_mode/clockwork_cult/C = SSticker.mode
if(C.check_clockwork_victory())
text += "Ratvar's servants have succeeded in fulfilling His goals!"
- feedback_set_details("round_end_result", "win - servants completed their objective ([clockwork_objective])")
+ feedback_set_details("round_end_result", "win - servants completed their objective (summon ratvar)")
else
var/half_victory = FALSE
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = locate() in all_clockwork_objects
if(G)
half_victory = TRUE
if(half_victory)
- text += "The crew escaped before [clockwork_objective == CLOCKCULT_GATEWAY ? "Ratvar could rise":"the station could be proselytized"], but the gateway \
+ text += "The crew escaped before Ratvar could rise, but the gateway \
was successfully constructed!"
- feedback_set_details("round_end_result", "halfwin - servants constructed the gateway but their objective was not completed ([clockwork_objective])")
+ feedback_set_details("round_end_result", "halfwin - servants constructed the gateway but their objective was not completed (summon ratvar)")
else
text += "Ratvar's servants have failed!"
- feedback_set_details("round_end_result", "loss - servants failed their objective ([clockwork_objective])")
- text += "
The servants' objective was:
[clockwork_explanation]"
+ feedback_set_details("round_end_result", "loss - servants failed their objective (summon ratvar)")
+ text += "
The servants' objective was:
[CLOCKCULT_OBJECTIVE]"
text += "
Ratvar's servants had [clockwork_caches] Tinkerer's Caches."
text += "
Construction Value(CV) was: [clockwork_construction_value]"
var/list/scripture_states = scripture_unlock_check()
diff --git a/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm b/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm
index c0d97bdff8f..707c5a6a9d8 100644
--- a/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm
+++ b/code/game/gamemodes/clock_cult/clock_helpers/scripture_checks.dm
@@ -28,7 +28,7 @@
. = 0
for(var/ai in ai_list)
var/mob/living/silicon/AI = ai
- if(is_servant_of_ratvar(AI) || !isturf(AI.loc) || AI.z != ZLEVEL_STATION)
+ if(is_servant_of_ratvar(AI) || !isturf(AI.loc) || AI.z != ZLEVEL_STATION || AI.stat == DEAD)
continue
.++
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
index b409b7eb5b6..0d68cbd3ecd 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm
@@ -135,7 +135,7 @@
if(!check_special_requirements())
return FALSE
to_chat(invoker, "The tendril shivers slightly as it selects a marauder...")
- var/list/marauder_candidates = pollCandidates("Do you want to play as the clockwork marauder of [invoker.real_name]?", ROLE_SERVANT_OF_RATVAR, null, FALSE, 50)
+ var/list/marauder_candidates = pollCandidates("Do you want to play as the clockwork marauder of [invoker.real_name]?", ROLE_SERVANT_OF_RATVAR, null, FALSE, 50, POLL_IGNORE_CLOCKWORK_MARAUDER)
if(!check_special_requirements())
return FALSE
if(!marauder_candidates.len)
diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_judgement.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_judgement.dm
index 1710322544e..5a03c3df28c 100644
--- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_judgement.dm
+++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_judgement.dm
@@ -22,13 +22,6 @@
tier = SCRIPTURE_JUDGEMENT
sort_priority = 1
-/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar/New()
- if(SSticker && SSticker.mode && SSticker.mode.clockwork_objective != CLOCKCULT_GATEWAY)
- invocations = list("ARMORER! FRIGHT! AMPERAGE! VANGUARD! I CALL UPON YOU!!", \
- "THIS STATION WILL BE A BEACON OF HOPE IN THE DARKNESS OF SPACE!!", \
- "HELP US MAKE THIS SHOW ENGINE'S GLORY!!")
- ..()
-
/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar/check_special_requirements()
if(!slab.no_cost)
if(ratvar_awakens)
@@ -36,7 +29,7 @@
return FALSE
for(var/obj/structure/destructible/clockwork/massive/celestial_gateway/G in all_clockwork_objects)
var/area/gate_area = get_area(G)
- to_chat(invoker, "There is already a gateway at [gate_area.map_name]!")
+ to_chat(invoker, "There is already an Ark at [gate_area.map_name]!")
return FALSE
var/area/A = get_area(invoker)
var/turf/T = get_turf(invoker)
@@ -44,9 +37,6 @@
to_chat(invoker, "You must be on the station to activate the Ark!")
return FALSE
if(clockwork_gateway_activated)
- if(SSticker && SSticker.mode && SSticker.mode.clockwork_objective != CLOCKCULT_GATEWAY)
- to_chat(invoker, "\"Look upon his works. Is it not glorious?\"")
- else
- to_chat(invoker, "Ratvar's recent banishment renders him too weak to be wrung forth from Reebe!")
+ to_chat(invoker, "Ratvar's recent banishment renders him too weak to be wrung forth from Reebe!")
return FALSE
return ..()
diff --git a/code/game/gamemodes/clock_cult/clock_structures/ark_of_the_clockwork_justicar.dm b/code/game/gamemodes/clock_cult/clock_structures/ark_of_the_clockwork_justicar.dm
index af7f59e266b..70097c0aa44 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/ark_of_the_clockwork_justicar.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/ark_of_the_clockwork_justicar.dm
@@ -1,6 +1,6 @@
//The gateway to Reebe, from which Ratvar emerges.
/obj/structure/destructible/clockwork/massive/celestial_gateway
- name = "gateway to the Celestial Derelict"
+ name = "ark of the Clockwork Justicar"
desc = "A massive, thrumming rip in spacetime."
clockwork_desc = "A portal to the Celestial Derelict. Massive and intimidating, it is the only thing that can both transport Ratvar and withstand the massive amount of energy he emits."
obj_integrity = 500
@@ -30,33 +30,20 @@
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/spawn_animation()
var/turf/T = get_turf(src)
- var/objective_is_gateway = (SSticker && SSticker.mode && SSticker.mode.clockwork_objective == CLOCKCULT_GATEWAY)
new/obj/effect/clockwork/general_marker/inathneq(T)
- if(objective_is_gateway)
- hierophant_message("\"[text2ratvar("Engine, come forth and show your servants your mercy")]!\"")
- else
- hierophant_message("\"[text2ratvar("We will show all the mercy of Engine")]!\"")
+ hierophant_message("\"[text2ratvar("Engine, come forth and show your servants your mercy")]!\"")
playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 30, 0)
sleep(10)
new/obj/effect/clockwork/general_marker/sevtug(T)
- if(objective_is_gateway)
- hierophant_message("\"[text2ratvar("Engine, come forth and show this station your decorating skills")]!\"")
- else
- hierophant_message("\"[text2ratvar("We will show all Engine's decorating skills")]!\"")
+ hierophant_message("\"[text2ratvar("Engine, come forth and show this station your decorating skills")]!\"")
playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 45, 0)
sleep(10)
new/obj/effect/clockwork/general_marker/nezbere(T)
- if(objective_is_gateway)
- hierophant_message("\"[text2ratvar("Engine, come forth and shine your light across this realm")]!!\"")
- else
- hierophant_message("\"[text2ratvar("We will show all Engine's light")]!!\"")
+ hierophant_message("\"[text2ratvar("Engine, come forth and shine your light across this realm")]!!\"")
playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 60, 0)
sleep(10)
new/obj/effect/clockwork/general_marker/nzcrentr(T)
- if(objective_is_gateway)
- hierophant_message("\"[text2ratvar("Engine, come forth")].\"")
- else
- hierophant_message("\"[text2ratvar("We will show all Engine's power")].\"")
+ hierophant_message("\"[text2ratvar("Engine, come forth")].\"")
playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 75, 0)
sleep(10)
playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 100, 0)
@@ -74,9 +61,7 @@
countdown = new(src)
countdown.start()
var/area/gate_area = get_area(src)
- hierophant_message("A gateway to the Celestial Derelict has been created in [gate_area.map_name]!", FALSE, src)
- if(!objective_is_gateway)
- ratvar_portal = FALSE
+ hierophant_message("An Ark of the Clockwork Justicar has been created in [gate_area.map_name]!", FALSE, src)
SSshuttle.registerHostileEnvironment(src)
START_PROCESSING(SSprocessing, src)
@@ -84,7 +69,7 @@
STOP_PROCESSING(SSprocessing, src)
if(!purpose_fulfilled)
var/area/gate_area = get_area(src)
- hierophant_message("A gateway to the Celestial Derelict has fallen at [gate_area.map_name]!")
+ hierophant_message("An Ark of the Clockwork Justicar has fallen at [gate_area.map_name]!")
send_to_playing_players(sound(null, 0, channel = 8))
var/was_stranded = SSshuttle.emergency.mode == SHUTTLE_STRANDED
SSshuttle.clearHostileEnvironment(src)
@@ -186,7 +171,7 @@
if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
to_chat(user, "It's reached the Celestial Derelict and is drawing power from it.")
if(GATEWAY_RATVAR_COMING to INFINITY)
- to_chat(user, "[ratvar_portal ? "Ratvar is coming through the gateway":"The gateway is glowing with massed power"]!")
+ to_chat(user, "Ratvar is coming through the gateway!")
else
switch(progress_in_seconds)
if(-INFINITY to GATEWAY_REEBE_FOUND)
@@ -194,7 +179,7 @@
if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
to_chat(user, "It seems to be leading somewhere.")
if(GATEWAY_RATVAR_COMING to INFINITY)
- to_chat(user, "[ratvar_portal ? "Something is coming through":"It's glowing brightly"]!")
+ to_chat(user, "Something is coming through!")
/obj/structure/destructible/clockwork/massive/celestial_gateway/process()
if(!first_sound_played || prob(7))
@@ -276,39 +261,28 @@
animate(glow, transform = matrix() * 3, alpha = 0, time = 5)
var/turf/startpoint = get_turf(src)
QDEL_IN(src, 3)
- if(ratvar_portal)
- sleep(3)
- clockwork_gateway_activated = TRUE
- new/obj/structure/destructible/clockwork/massive/ratvar(startpoint)
- else
- INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 0) //call the shuttle immediately
- sleep(3)
- clockwork_gateway_activated = TRUE
- send_to_playing_players("\"[text2ratvar("Behold")]!\"\n\"[text2ratvar("See Engine's mercy")]!\"\n\
- \"[text2ratvar("Observe Engine's design skills")]!\"\n\"[text2ratvar("Behold Engine's light")]!!\"\n\
- \"[text2ratvar("Gaze upon Engine's power")]!\"")
- send_to_playing_players('sound/magic/clockwork/invoke_general.ogg')
- var/x0 = startpoint.x
- var/y0 = startpoint.y
- for(var/I in spiral_range_turfs(255, startpoint))
- var/turf/T = I
- if(!T)
- continue
- var/dist = cheap_hypotenuse(T.x, T.y, x0, y0)
- if(dist < 100)
- dist = TRUE
- else
- dist = FALSE
- T.ratvar_act(dist)
- CHECK_TICK
- for(var/mob/living/L in living_mob_list)
- L.ratvar_act()
- for(var/I in all_clockwork_mobs)
- var/mob/M = I
- if(M.stat == CONSCIOUS)
- clockwork_say(M, text2ratvar(pick("Purge all untruths and honor Engine!", "All glory to Engine's light!", "Engine's power is unmatched!")))
+ sleep(3)
+ clockwork_gateway_activated = TRUE
+ new/obj/structure/destructible/clockwork/massive/ratvar(startpoint)
+ send_to_playing_players("\"[text2ratvar("See Engine's mercy")]!\"\n\
+ \"[text2ratvar("Observe Engine's design skills")]!\"\n\"[text2ratvar("Behold Engine's light")]!!\"\n\
+ \"[text2ratvar("Gaze upon Engine's power")].\"")
+ send_to_playing_players('sound/magic/clockwork/invoke_general.ogg')
+ var/x0 = startpoint.x
+ var/y0 = startpoint.y
+ for(var/I in spiral_range_turfs(255, startpoint))
+ var/turf/T = I
+ if(!T)
+ continue
+ var/dist = cheap_hypotenuse(T.x, T.y, x0, y0)
+ if(dist < 100)
+ dist = TRUE
+ else
+ dist = FALSE
+ T.ratvar_act(dist, TRUE)
+ CHECK_TICK
-//the actual appearance of the Gateway to the Celestial Derelict; an object so the edges of the gate can be clicked through.
+//the actual appearance of the Ark of the Clockwork Justicar; an object so the edges of the gate can be clicked through.
/obj/effect/clockwork/overlay/gateway_glow
icon = 'icons/effects/96x96.dmi'
icon_state = "clockwork_gateway_charging"
diff --git a/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm b/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
index 85bd8ba4de0..fd482cf8f42 100644
--- a/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures/ratvar_the_clockwork_justicar.dm
@@ -27,7 +27,7 @@
var/image/alert_overlay = image('icons/effects/clockwork_effects.dmi', "ratvar_alert")
var/area/A = get_area(src)
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [A.name] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
- addtimer(CALLBACK(SSshuttle.emergency, /obj/docking_port/mobile/emergency..proc/request, null, 0.1), 50)
+ INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency..proc/request, null, 0)
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
ratvar_awakens--
@@ -62,27 +62,30 @@
T.ratvar_act()
for(var/I in circleviewturfs(src, round(proselytize_range * 0.5)))
var/turf/T = I
- T.ratvar_act(1)
+ T.ratvar_act(TRUE)
var/dir_to_step_in = pick(cardinal)
+ var/list/meals = list()
+ for(var/mob/living/L in living_mob_list) //we want to know who's alive so we don't lose and retarget a single person
+ if(L.z == z && !is_servant_of_ratvar(L) && L.mind)
+ meals += L
if(!prey)
for(var/obj/singularity/narsie/N in singularities)
if(N.z == z)
prey = N
break
- if(!prey) //In case there's a Nar-Sie
- var/list/meals = list()
- for(var/mob/living/L in living_mob_list)
- if(L.z == z && !is_servant_of_ratvar(L) && L.mind)
- meals += L
- if(meals.len)
- prey = pick(meals)
- to_chat(prey, "\"You will do.\"\n\
- Something very large and very malevolent begins lumbering its way towards you...")
- prey << 'sound/effects/ratvar_reveal.ogg'
+ if(!prey && LAZYLEN(meals))
+ prey = pick(meals)
+ to_chat(prey, "\"You will do, heretic.\"\n\
+ ")
+ prey << 'sound/effects/ratvar_reveal.ogg'
else
- if((!istype(prey, /obj/singularity/narsie) && prob(10)) || is_servant_of_ratvar(prey) || prey.z != z)
- to_chat(prey, "\"How dull. Leave me.\"\n\
- You feel tremendous relief as a set of horrible eyes loses sight of you...")
+ if((!istype(prey, /obj/singularity/narsie) && prob(10) && LAZYLEN(meals) > 1) || prey.z != z || !(prey in meals))
+ if(is_servant_of_ratvar(prey))
+ to_chat(prey, "\"Serve me well.\"\n\
+ You feel great joy as your god turns His eye to another heretic...")
+ else
+ to_chat(prey, "\"No matter. I will find you later, heretic.\"\n\
+ You feel tremendous relief as the crushing focus relents...")
prey = null
else
dir_to_step_in = get_dir(src, prey) //Unlike Nar-Sie, Ratvar ruthlessly chases down his target
diff --git a/code/game/objects/effects/spawners/structure.dm b/code/game/objects/effects/spawners/structure.dm
index 84d940dfdb7..7a14dbb9427 100644
--- a/code/game/objects/effects/spawners/structure.dm
+++ b/code/game/objects/effects/spawners/structure.dm
@@ -8,11 +8,11 @@ again.
name = "map structure spawner"
var/list/spawn_list
-/obj/effect/spawner/structure/New()
+/obj/effect/spawner/structure/Initialize()
+ ..()
if(spawn_list && spawn_list.len)
- for(var/i = 1, i <= spawn_list.len, i++)
- var/to_spawn = spawn_list[i]
- new to_spawn(get_turf(src))
+ for(var/I in spawn_list)
+ new I(get_turf(src))
qdel(src)
/obj/effect/spawner/structure/window
diff --git a/code/game/objects/items/charter.dm b/code/game/objects/items/charter.dm
index 24d3f65d6de..ad23d12754a 100644
--- a/code/game/objects/items/charter.dm
+++ b/code/game/objects/items/charter.dm
@@ -60,7 +60,7 @@
to_chat(user, "Your name has been sent to your employers for approval.")
// Autoapproves after a certain time
response_timer_id = addtimer(CALLBACK(src, .proc/rename_station, new_name, user.name, user.real_name, key_name(user)), approval_time, TIMER_STOPPABLE)
- to_chat(admins, "CUSTOM STATION RENAME:[key_name_admin(user)] (?) proposes to rename the station to [new_name] (will autoapprove in [approval_time / 10] seconds). (BSA) (REJECT) (RPLY)")
+ to_chat(admins, "CUSTOM STATION RENAME:[key_name_admin(user)] (?) proposes to rename the station to [new_name] (will autoapprove in [approval_time / 10] seconds). [ADMIN_SMITE(user)] (REJECT) (RPLY)")
/obj/item/station_charter/proc/reject_proposed(user)
if(!user)
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index e51cc33fe08..eef611d8107 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -230,7 +230,7 @@ effective or pretty fucking useless.
desc = "Device used to disrupt nearby radio communication."
icon_state = "jammer"
var/active = FALSE
- var/range = 7
+ var/range = 12
/obj/item/device/jammer/attack_self(mob/user)
to_chat(user,"You [active ? "deactivate" : "activate"] the [src]")
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 4f09303acf9..04f7825c999 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -118,6 +118,7 @@
icon_state = "gauze"
stop_bleeding = 1800
self_delay = 20
+ max_amount = 12
/obj/item/stack/medical/gauze/improvised
name = "improvised gauze"
diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm
index c935a48f76f..ba82c6177d1 100644
--- a/code/game/objects/structures/flora.dm
+++ b/code/game/objects/structures/flora.dm
@@ -44,7 +44,7 @@
icon = 'icons/obj/flora/pinetrees.dmi'
icon_state = "pine_1"
-/obj/structure/flora/tree/pine/New()
+/obj/structure/flora/tree/pine/Initialize()
icon_state = "pine_[rand(1, 3)]"
..()
@@ -52,7 +52,7 @@
name = "xmas tree"
icon_state = "pine_c"
-/obj/structure/flora/tree/pine/xmas/New()
+/obj/structure/flora/tree/pine/xmas/Initialize()
..()
icon_state = "pine_c"
@@ -64,7 +64,7 @@
icon = 'icons/misc/beach2.dmi'
icon_state = "palm1"
-/obj/structure/flora/tree/palm/New()
+/obj/structure/flora/tree/palm/Initialize()
..()
icon_state = pick("palm1","palm2")
pixel_x = 0
@@ -75,10 +75,17 @@
icon_state = "festivus_pole"
desc = "During last year's Feats of Strength the Research Director was able to suplex this passing immobile rod into a planter."
-/obj/structure/flora/tree/dead/New()
+/obj/structure/flora/tree/dead/Initialize()
icon_state = "tree_[rand(1, 6)]"
..()
+/obj/structure/flora/tree/jungle
+ name = "tree"
+ desc = "It's seriously hampering your view of the jungle."
+
+/obj/structure/flora/tree/jungle/Initialize()
+ icon_state = "[icon_state][rand(1, 3)]"
+ ..()
//grass
/obj/structure/flora/grass
@@ -89,7 +96,7 @@
/obj/structure/flora/grass/brown
icon_state = "snowgrass1bb"
-/obj/structure/flora/grass/brown/New()
+/obj/structure/flora/grass/brown/Initialize()
icon_state = "snowgrass[rand(1, 3)]bb"
..()
@@ -97,14 +104,14 @@
/obj/structure/flora/grass/green
icon_state = "snowgrass1gb"
-/obj/structure/flora/grass/green/New()
+/obj/structure/flora/grass/green/Initialize()
icon_state = "snowgrass[rand(1, 3)]gb"
..()
/obj/structure/flora/grass/both
icon_state = "snowgrassall1"
-/obj/structure/flora/grass/both/New()
+/obj/structure/flora/grass/both/Initialize()
icon_state = "snowgrassall[rand(1, 3)]"
..()
@@ -116,7 +123,7 @@
icon_state = "snowbush1"
anchored = 1
-/obj/structure/flora/bush/New()
+/obj/structure/flora/bush/Initialize()
icon_state = "snowbush[rand(1, 6)]"
..()
@@ -127,7 +134,7 @@
icon = 'icons/obj/flora/ausflora.dmi'
icon_state = "firstbush_1"
-/obj/structure/flora/ausbushes/New()
+/obj/structure/flora/ausbushes/Initialize()
if(icon_state == "firstbush_1")
icon_state = "firstbush_[rand(1, 4)]"
..()
@@ -135,105 +142,105 @@
/obj/structure/flora/ausbushes/reedbush
icon_state = "reedbush_1"
-/obj/structure/flora/ausbushes/reedbush/New()
+/obj/structure/flora/ausbushes/reedbush/Initialize()
icon_state = "reedbush_[rand(1, 4)]"
..()
/obj/structure/flora/ausbushes/leafybush
icon_state = "leafybush_1"
-/obj/structure/flora/ausbushes/leafybush/New()
+/obj/structure/flora/ausbushes/leafybush/Initialize()
icon_state = "leafybush_[rand(1, 3)]"
..()
/obj/structure/flora/ausbushes/palebush
icon_state = "palebush_1"
-/obj/structure/flora/ausbushes/palebush/New()
+/obj/structure/flora/ausbushes/palebush/Initialize()
icon_state = "palebush_[rand(1, 4)]"
..()
/obj/structure/flora/ausbushes/stalkybush
icon_state = "stalkybush_1"
-/obj/structure/flora/ausbushes/stalkybush/New()
+/obj/structure/flora/ausbushes/stalkybush/Initialize()
icon_state = "stalkybush_[rand(1, 3)]"
..()
/obj/structure/flora/ausbushes/grassybush
icon_state = "grassybush_1"
-/obj/structure/flora/ausbushes/grassybush/New()
+/obj/structure/flora/ausbushes/grassybush/Initialize()
icon_state = "grassybush_[rand(1, 4)]"
..()
/obj/structure/flora/ausbushes/fernybush
icon_state = "fernybush_1"
-/obj/structure/flora/ausbushes/fernybush/New()
+/obj/structure/flora/ausbushes/fernybush/Initialize()
icon_state = "fernybush_[rand(1, 3)]"
..()
/obj/structure/flora/ausbushes/sunnybush
icon_state = "sunnybush_1"
-/obj/structure/flora/ausbushes/sunnybush/New()
+/obj/structure/flora/ausbushes/sunnybush/Initialize()
icon_state = "sunnybush_[rand(1, 3)]"
..()
/obj/structure/flora/ausbushes/genericbush
icon_state = "genericbush_1"
-/obj/structure/flora/ausbushes/genericbush/New()
+/obj/structure/flora/ausbushes/genericbush/Initialize()
icon_state = "genericbush_[rand(1, 4)]"
..()
/obj/structure/flora/ausbushes/pointybush
icon_state = "pointybush_1"
-/obj/structure/flora/ausbushes/pointybush/New()
+/obj/structure/flora/ausbushes/pointybush/Initialize()
icon_state = "pointybush_[rand(1, 4)]"
..()
/obj/structure/flora/ausbushes/lavendergrass
icon_state = "lavendergrass_1"
-/obj/structure/flora/ausbushes/lavendergrass/New()
+/obj/structure/flora/ausbushes/lavendergrass/Initialize()
icon_state = "lavendergrass_[rand(1, 4)]"
..()
/obj/structure/flora/ausbushes/ywflowers
icon_state = "ywflowers_1"
-/obj/structure/flora/ausbushes/ywflowers/New()
+/obj/structure/flora/ausbushes/ywflowers/Initialize()
icon_state = "ywflowers_[rand(1, 3)]"
..()
/obj/structure/flora/ausbushes/brflowers
icon_state = "brflowers_1"
-/obj/structure/flora/ausbushes/brflowers/New()
+/obj/structure/flora/ausbushes/brflowers/Initialize()
icon_state = "brflowers_[rand(1, 3)]"
..()
/obj/structure/flora/ausbushes/ppflowers
icon_state = "ppflowers_1"
-/obj/structure/flora/ausbushes/ppflowers/New()
+/obj/structure/flora/ausbushes/ppflowers/Initialize()
icon_state = "ppflowers_[rand(1, 3)]"
..()
/obj/structure/flora/ausbushes/sparsegrass
icon_state = "sparsegrass_1"
-/obj/structure/flora/ausbushes/sparsegrass/New()
+/obj/structure/flora/ausbushes/sparsegrass/Initialize()
icon_state = "sparsegrass_[rand(1, 3)]"
..()
/obj/structure/flora/ausbushes/fullgrass
icon_state = "fullgrass_1"
-/obj/structure/flora/ausbushes/fullgrass/New()
+/obj/structure/flora/ausbushes/fullgrass/Initialize()
icon_state = "fullgrass_[rand(1, 3)]"
..()
@@ -261,7 +268,7 @@
/obj/item/weapon/twohanded/required/kirbyplants/random
var/list/static/states
-/obj/item/weapon/twohanded/required/kirbyplants/random/New()
+/obj/item/weapon/twohanded/required/kirbyplants/random/Initialize()
. = ..()
if(!states)
generate_states()
@@ -295,7 +302,7 @@
resistance_flags = FIRE_PROOF
density = 1
-/obj/structure/flora/rock/New()
+/obj/structure/flora/rock/Initialize()
..()
icon_state = "[icon_state][rand(1,3)]"
@@ -303,6 +310,63 @@
icon_state = "lavarocks"
desc = "A pile of rocks"
-/obj/structure/flora/rock/pile/New()
+/obj/structure/flora/rock/pile/Initialize()
..()
icon_state = "[icon_state][rand(1,3)]"
+
+//Jungle grass
+
+/obj/structure/flora/grass/jungle
+ name = "jungle grass"
+ desc = "Thick alien flora."
+ icon = 'icons/obj/flora/jungleflora.dmi'
+ icon_state = "grassa"
+
+
+/obj/structure/flora/grass/jungle/Initialize()
+ icon_state = "[icon_state][rand(1, 5)]"
+ ..()
+
+/obj/structure/flora/grass/jungle/b
+ icon_state = "grassb"
+
+//Jungle rocks
+
+/obj/structure/flora/rock/jungle
+ icon_state = "pile of rocks"
+ desc = "A pile of rocks."
+ icon = 'icons/obj/flora/jungleflora.dmi'
+ density = FALSE
+
+/obj/structure/flora/rock/jungle/Initialize()
+ ..()
+ icon_state = "[icon_state][rand(1,5)]"
+
+
+//Jungle bushes
+
+/obj/structure/flora/junglebush
+ name = "bush"
+ icon = 'icons/obj/flora/jungleflora.dmi'
+ icon_state = "busha"
+
+/obj/structure/flora/junglebush/Initialize()
+ icon_state = "[icon_state][rand(1, 3)]"
+ ..()
+
+/obj/structure/flora/junglebush/b
+ icon_state = "bushb"
+
+/obj/structure/flora/junglebush/c
+ icon_state = "bushc"
+
+/obj/structure/flora/junglebush/large
+ icon_state = "bush"
+ icon = 'icons/obj/flora/largejungleflora.dmi'
+ pixel_x = -16
+ layer = ABOVE_ALL_MOB_LAYER
+
+/obj/structure/flora/rock/pile/largejungle
+ name = "rocks"
+ icon = 'icons/obj/flora/largejungleflora.dmi'
+ density = FALSE
diff --git a/code/game/turfs/simulated/floor/plating/dirt.dm b/code/game/turfs/simulated/floor/plating/dirt.dm
new file mode 100644
index 00000000000..580aadc85f6
--- /dev/null
+++ b/code/game/turfs/simulated/floor/plating/dirt.dm
@@ -0,0 +1,21 @@
+/turf/open/floor/plating/dirt
+ name = "dirt"
+ desc = "Upon closer examination, it's still dirt."
+ icon = 'icons/turf/floors.dmi'
+ icon_state = "dirt"
+ var/smooth_icon = 'icons/turf/floors/dirt.dmi'
+ canSmoothWith = list(/turf/closed, /turf/open/floor/plating/dirt)
+ smooth = SMOOTH_MORE|SMOOTH_BORDER
+ baseturf = /turf/open/chasm/straight_down/lava_land_surface
+ initial_gas_mix = "o2=14;n2=23;TEMP=300"
+ planetary_atmos = TRUE
+
+/turf/open/floor/plating/dirt/Initialize()
+ pixel_y = -2
+ pixel_x = -2
+ icon = smooth_icon
+ ..()
+
+/turf/open/floor/plating/dirt/dark
+ icon_state = "darkdirt"
+ smooth_icon = 'icons/turf/floors/darkdirt.dmi'
diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm
new file mode 100644
index 00000000000..d0208218a56
--- /dev/null
+++ b/code/game/turfs/simulated/water.dm
@@ -0,0 +1,16 @@
+/turf/open/water
+ name = "water"
+ desc = "Shallow water."
+ icon = 'icons/turf/floors.dmi'
+ icon_state = "riverwater"
+ baseturf = /turf/open/chasm/straight_down/lava_land_surface
+ initial_gas_mix = "o2=14;n2=23;TEMP=300"
+ planetary_atmos = TRUE
+ slowdown = 1
+ wet = TURF_WET_WATER
+
+/turf/open/water/HandleWet()
+ if(wet == TURF_WET_WATER)
+ return
+ ..()
+ MakeSlippery(TURF_WET_WATER) //rewet after ..() clears out lube/ice etc.
\ No newline at end of file
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index d15d8e6e0ec..824e0b1a8a9 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -92,13 +92,13 @@ var/list/admin_verbs_fun = list(
/client/proc/set_ooc,
/client/proc/reset_ooc,
/client/proc/forceEvent,
- /client/proc/bluespace_artillery,
/client/proc/admin_change_sec_level,
/client/proc/toggle_nuke,
/client/proc/mass_zombie_infection,
/client/proc/mass_zombie_cure,
/client/proc/polymorph_all,
- /client/proc/show_tip
+ /client/proc/show_tip,
+ /client/proc/smite
)
var/list/admin_verbs_spawn = list(
/datum/admins/proc/spawn_atom, /*allows us to spawn instances*/
diff --git a/code/modules/admin/sql_message_system.dm b/code/modules/admin/sql_message_system.dm
index 5e959f140ea..3d287c22286 100644
--- a/code/modules/admin/sql_message_system.dm
+++ b/code/modules/admin/sql_message_system.dm
@@ -1,5 +1,5 @@
/proc/create_message(type, target_ckey, admin_ckey, text, timestamp, server, secret, logged = 1, browse)
- if(!dbcon.IsConnected())
+ if(!dbcon.Connect())
to_chat(usr, "Failed to establish database connection.")
return
if(!type)
@@ -56,7 +56,7 @@
browse_messages(target_ckey = target_ckey)
/proc/delete_message(message_id, logged = 1, browse)
- if(!dbcon.IsConnected())
+ if(!dbcon.Connect())
to_chat(usr, "Failed to establish database connection.")
return
message_id = text2num(message_id)
@@ -84,7 +84,7 @@
browse_messages(target_ckey = target_ckey)
/proc/edit_message(message_id, browse)
- if(!dbcon.IsConnected())
+ if(!dbcon.Connect())
to_chat(usr, "Failed to establish database connection.")
return
message_id = text2num(message_id)
@@ -115,7 +115,7 @@
browse_messages(target_ckey = target_ckey)
/proc/toggle_message_secrecy(message_id)
- if(!dbcon.IsConnected())
+ if(!dbcon.Connect())
to_chat(usr, "Failed to establish database connection.")
return
message_id = text2num(message_id)
@@ -139,7 +139,7 @@
browse_messages(target_ckey = target_ckey)
/proc/browse_messages(type, target_ckey, index, linkless = 0, filter)
- if(!dbcon.IsConnected())
+ if(!dbcon.Connect())
to_chat(usr, "Failed to establish database connection.")
return
var/output
@@ -277,7 +277,7 @@
usr << browse(output, "window=browse_messages;size=900x500")
proc/get_message_output(type, target_ckey)
- if(!dbcon.IsConnected())
+ if(!dbcon.Connect())
to_chat(usr, "Failed to establish database connection.")
return
if(!type)
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 3f9bafa25c9..3b71904f4c0 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1716,33 +1716,10 @@
var/mob/living/carbon/human/H = locate(href_list["adminsmite"]) in mob_list
if(!H || !istype(H))
+ to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human")
return
- var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB)
-
- var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
-
- if(QDELETED(H) || !punishment)
- return
-
- switch(punishment)
- if(ADMIN_PUNISHMENT_LIGHTNING)
- var/turf/T = get_step(get_step(H, NORTH), NORTH)
- T.Beam(H, icon_state="lightning[rand(1,12)]", time = 5)
- H.adjustFireLoss(75)
- H.electrocution_animation(40)
- to_chat(H, "The gods have punished you for your sins!")
- if(ADMIN_PUNISHMENT_BRAINDAMAGE)
- H.adjustBrainLoss(75)
- if(ADMIN_PUNISHMENT_GIB)
- H.gib(FALSE)
-
- message_admins("[key_name_admin(usr)] punished [key_name_admin(H)] with [punishment].")
- log_admin("[key_name(usr)] punished [key_name(H)] with [punishment].")
-
- else if(href_list["BlueSpaceArtillery"])
- var/mob/living/M = locate(href_list["BlueSpaceArtillery"]) in mob_list
- usr.client.bluespace_artillery(M)
+ usr.client.smite(H)
else if(href_list["CentcommReply"])
var/mob/living/carbon/human/H = locate(href_list["CentcommReply"]) in mob_list
diff --git a/code/modules/admin/verbs/bluespacearty.dm b/code/modules/admin/verbs/bluespacearty.dm
index 3353986ac3e..2a4c9a2d57a 100644
--- a/code/modules/admin/verbs/bluespacearty.dm
+++ b/code/modules/admin/verbs/bluespacearty.dm
@@ -1,7 +1,4 @@
/client/proc/bluespace_artillery(mob/M in mob_list)
- set name = "Bluespace Artillery"
- set category = "Fun"
-
if(!holder || !check_rights(R_FUN))
return
@@ -11,9 +8,6 @@
to_chat(usr, "This can only be used on instances of type /mob/living")
return
- if(alert(usr, "Are you sure you wish to hit [key_name(target)] with Blue Space Artillery?", "Confirm Firing?" , "Yes" , "No") != "Yes")
- return
-
explosion(target.loc, 0, 0, 0, 0)
var/turf/open/floor/T = get_turf(target)
@@ -23,10 +17,6 @@
else
T.break_tile()
- to_chat(target, "You're hit by bluespace artillery!")
- log_admin("[key_name(target)] has been hit by Bluespace Artillery fired by [key_name(usr)]")
- message_admins("[ADMIN_LOOKUPFLW(target)] has been hit by Bluespace Artillery fired by [ADMIN_LOOKUPFLW(usr)]")
-
if(target.health <= 1)
target.gib(1, 1)
else
diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm
index bb35726331e..e9688ec89ed 100644
--- a/code/modules/admin/verbs/pray.dm
+++ b/code/modules/admin/verbs/pray.dm
@@ -48,34 +48,21 @@
/proc/Centcomm_announce(text , mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
- msg = "\
- CENTCOM:\
- [ADMIN_FULLMONTY(Sender)] [ADMIN_BSA(Sender)] \
- [ADMIN_CENTCOM_REPLY(Sender)]: \
- [msg]"
+ msg = "CENTCOM:[ADMIN_FULLMONTY(Sender)] [ADMIN_SMITE(Sender)] [ADMIN_CENTCOM_REPLY(Sender)]: [msg]"
to_chat(admins, msg)
for(var/obj/machinery/computer/communications/C in machines)
C.overrideCooldown()
/proc/Syndicate_announce(text , mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
- msg = "\
- SYNDICATE:\
- [ADMIN_FULLMONTY(Sender)] [ADMIN_BSA(Sender)] \
- [ADMIN_SYNDICATE_REPLY(Sender)]: \
- [msg]"
+ msg = "SYNDICATE:[ADMIN_FULLMONTY(Sender)] [ADMIN_SMITE(Sender)] [ADMIN_SYNDICATE_REPLY(Sender)]: [msg]"
to_chat(admins, msg)
for(var/obj/machinery/computer/communications/C in machines)
C.overrideCooldown()
/proc/Nuke_request(text , mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
- msg = "\
- NUKE CODE REQUEST:\
- [ADMIN_FULLMONTY(Sender)] [ADMIN_BSA(Sender)] \
- [ADMIN_CENTCOM_REPLY(Sender)] \
- [ADMIN_SET_SD_CODE]: \
- [msg]"
+ msg = "NUKE CODE REQUEST:[ADMIN_FULLMONTY(Sender)] [ADMIN_SMITE(Sender)] [ADMIN_CENTCOM_REPLY(Sender)] [ADMIN_SET_SD_CODE]: [msg]"
to_chat(admins, msg)
for(var/obj/machinery/computer/communications/C in machines)
C.overrideCooldown()
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 2675e27c74c..c213af3584d 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -1131,3 +1131,33 @@ var/list/datum/outfit/custom_outfits = list() //Admin created outfits
message_admins("WARNING: The server will not show up on the hub because byond is detecting that a filewall is blocking incoming connections.")
feedback_add_details("admin_verb","HUB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/smite(mob/living/carbon/human/target as mob)
+ set name = "Smite"
+ set category = "Fun"
+ if(!holder)
+ return
+
+ var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA)
+
+ var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
+
+ if(QDELETED(target) || !punishment)
+ return
+
+ switch(punishment)
+ if(ADMIN_PUNISHMENT_LIGHTNING)
+ var/turf/T = get_step(get_step(target, NORTH), NORTH)
+ T.Beam(target, icon_state="lightning[rand(1,12)]", time = 5)
+ target.adjustFireLoss(75)
+ target.electrocution_animation(40)
+ to_chat(target, "The gods have punished you for your sins!")
+ if(ADMIN_PUNISHMENT_BRAINDAMAGE)
+ target.adjustBrainLoss(75)
+ if(ADMIN_PUNISHMENT_GIB)
+ target.gib(FALSE)
+ if(ADMIN_PUNISHMENT_BSA)
+ bluespace_artillery(target)
+
+ message_admins("[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment].")
+ log_admin("[key_name(usr)] punished [key_name(target)] with [punishment].")
\ No newline at end of file
diff --git a/code/modules/atmospherics/machinery/other/miner.dm b/code/modules/atmospherics/machinery/other/miner.dm
new file mode 100644
index 00000000000..8b55ce14fc5
--- /dev/null
+++ b/code/modules/atmospherics/machinery/other/miner.dm
@@ -0,0 +1,182 @@
+
+#define GASMINER_POWER_NONE 0
+#define GASMINER_POWER_STATIC 1
+#define GASMINER_POWER_MOLES 2 //Scaled from here on down.
+#define GASMINER_POWER_KPA 3
+#define GASMINER_POWER_FULLSCALE 4
+
+/obj/machinery/atmospherics/miner
+ name = "gas miner"
+ desc = "Gasses mined from the gas giant below (above?) flow out through this massive vent."
+ icon = 'icons/obj/atmospherics/components/miners.dmi'
+ icon_state = "miner"
+ anchored = TRUE
+ density = FALSE
+ resistance_flags = INDESTRUCTIBLE|ACID_PROOF|FIRE_PROOF
+ var/spawn_id = null
+ var/spawn_temp = T20C
+ var/spawn_mol = MOLES_CELLSTANDARD * 10
+ var/max_ext_mol = INFINITY
+ var/max_ext_kpa = 6500
+ var/overlay_color = "#FFFFFF"
+ var/active = TRUE
+ var/power_draw = 0
+ var/power_draw_static = 2000
+ var/power_draw_dynamic_mol_coeff = 5 //DO NOT USE DYNAMIC SETTINGS UNTIL SOMEONE MAKES A USER INTERFACE/CONTROLLER FOR THIS!
+ var/power_draw_dynamic_kpa_coeff = 0.5
+ var/broken = FALSE
+ var/broken_message = "ERROR"
+ idle_power_usage = 150
+ active_power_usage = 2000
+
+/obj/machinery/atmospherics/miner/examine(mob/user)
+ ..()
+ if(broken)
+ to_chat(user, "Its debug output is printing \"[broken_message]\"")
+
+/obj/machinery/atmospherics/miner/proc/check_operation()
+ if(!active)
+ return FALSE
+ var/turf/T = get_turf(src)
+ if(!isopenturf(T))
+ broken_message = "VENT BLOCKED"
+ broken = TRUE
+ return FALSE
+ var/turf/open/OT = T
+ if(OT.planetary_atmos)
+ broken_message = "DEVICE NOT ENCLOSED IN A PRESSURIZED ENVIRONMENT"
+ broken = TRUE
+ return FALSE
+ if(isspaceturf(T))
+ broken_message = "AIR VENTING TO SPACE"
+ broken = TRUE
+ return FALSE
+ var/datum/gas_mixture/G = OT.return_air()
+ if(G.return_pressure() > (max_ext_kpa - ((spawn_mol*spawn_temp*R_IDEAL_GAS_EQUATION)/(CELL_VOLUME))))
+ broken_message = "EXTERNAL PRESSURE OVER THRESHOLD"
+ broken = TRUE
+ return FALSE
+ if(G.total_moles() > max_ext_mol)
+ broken_message = "EXTERNAL AIR CONCENTRATION OVER THRESHOLD"
+ broken = TRUE
+ return FALSE
+ if(broken)
+ broken = FALSE
+ broken_message = ""
+ return TRUE
+
+/obj/machinery/atmospherics/miner/proc/update_power()
+ if(!active)
+ active_power_usage = idle_power_usage
+ var/turf/T = get_turf(src)
+ var/datum/gas_mixture/G = T.return_air()
+ var/P = G.return_pressure()
+ switch(power_draw)
+ if(GASMINER_POWER_NONE)
+ active_power_usage = 0
+ if(GASMINER_POWER_STATIC)
+ active_power_usage = power_draw_static
+ if(GASMINER_POWER_MOLES)
+ active_power_usage = spawn_mol * power_draw_dynamic_mol_coeff
+ if(GASMINER_POWER_KPA)
+ active_power_usage = P * power_draw_dynamic_kpa_coeff
+ if(GASMINER_POWER_FULLSCALE)
+ active_power_usage = (spawn_mol * power_draw_dynamic_mol_coeff) + (P * power_draw_dynamic_kpa_coeff)
+
+/obj/machinery/atmospherics/miner/proc/do_use_power(amount)
+ var/turf/T = get_turf(src)
+ if(T && istype(T))
+ var/obj/structure/cable/C = T.get_cable_node() //check if we have a node cable on the machine turf, the first found is picked
+ if(C && C.powernet && (C.powernet.avail > amount))
+ C.powernet.load += amount
+ return TRUE
+ if(powered())
+ use_power(amount)
+ return TRUE
+ return FALSE
+
+/obj/machinery/atmospherics/miner/update_icon()
+ overlays.Cut()
+ if(broken)
+ var/image/A = image(icon, "broken")
+ add_overlay(A)
+ else if(active)
+ var/image/A = image(icon, "on")
+ A.color = overlay_color
+ add_overlay(A)
+
+/obj/machinery/atmospherics/miner/process()
+ update_power()
+ update_icon()
+ check_operation()
+ if(active && !broken)
+ if(isnull(spawn_id))
+ return FALSE
+ if(do_use_power(active_power_usage))
+ mine_gas()
+
+/obj/machinery/atmospherics/miner/proc/mine_gas()
+ var/turf/open/O = get_turf(src)
+ if(!isopenturf(O))
+ return FALSE
+ var/datum/gas_mixture/merger = new
+ merger.assert_gas(spawn_id)
+ merger.gases[spawn_id][MOLES] = (spawn_mol)
+ merger.temperature = spawn_temp
+ O.assume_air(merger)
+ SSair.add_to_active(O)
+
+/obj/machinery/atmospherics/miner/attack_ai(mob/living/silicon/user)
+ if(broken)
+ to_chat(user, "[src] seems to be broken. Its debug interface outputs: [broken_message]")
+ ..()
+
+/obj/machinery/atmospherics/miner/n2o
+ name = "\improper N2O Gas Miner"
+ overlay_color = "#FFCCCC"
+ spawn_id = "n2o"
+
+/obj/machinery/atmospherics/miner/nitrogen
+ name = "\improper N2 Gas Miner"
+ overlay_color = "#CCFFCC"
+ spawn_id = "n2"
+
+/obj/machinery/atmospherics/miner/oxygen
+ name = "\improper O2 Gas Miner"
+ overlay_color = "#007FFF"
+ spawn_id = "o2"
+
+/obj/machinery/atmospherics/miner/toxins
+ name = "\improper Plasma Gas Miner"
+ overlay_color = "#FF0000"
+ spawn_id = "plasma"
+
+/obj/machinery/atmospherics/miner/carbon_dioxide
+ name = "\improper CO2 Gas Miner"
+ overlay_color = "#CDCDCD"
+ spawn_id = "co2"
+
+/obj/machinery/atmospherics/miner/bz
+ name = "\improper BZ Gas Miner"
+ overlay_color = "#FAFF00"
+ spawn_id = "bz"
+
+/obj/machinery/atmospherics/miner/freon
+ name = "\improper Freon Gas Miner"
+ overlay_color = "#00FFE5"
+ spawn_id = "freon"
+
+/obj/machinery/atmospherics/miner/volatile_fuel
+ name = "\improper Volatile Fuel Gas Miner"
+ overlay_color = "#564040"
+ spawn_id = "v_fuel"
+
+/obj/machinery/atmospherics/miner/agent_b
+ name = "\improper Agent B Gas Miner"
+ overlay_color = "#E81E24"
+ spawn_id = "agent_b"
+
+/obj/machinery/atmospherics/miner/water_vapor
+ name = "\improper Water Vapor Gas Miner"
+ overlay_color = "#99928E"
+ spawn_id = "water_vapor"
diff --git a/code/modules/clothing/spacesuits/flightsuit.dm b/code/modules/clothing/spacesuits/flightsuit.dm
index ffc5f22bfbb..5c15d28cc5f 100644
--- a/code/modules/clothing/spacesuits/flightsuit.dm
+++ b/code/modules/clothing/spacesuits/flightsuit.dm
@@ -573,7 +573,7 @@
/obj/item/device/flightpack/proc/mobknockback(mob/living/victim, power, direction)
if(!ismob(victim))
return FALSE
- forceMove(get_turf(victim))
+ wearer.forceMove(get_turf(victim))
wearer.visible_message("[wearer] flies over [victim]!")
/obj/item/device/flightpack/proc/victimknockback(atom/movable/victim, power, direction)
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index c02bdcd4752..c9e71abf0bb 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -450,5 +450,5 @@
name = "Pressure Plate"
result = /obj/item/device/pressure_plate
time = 5
- reqs = list(/obj/item/stack/sheet/plasteel = 1, /obj/item/stack/tile = 1, /obj/item/stack/cable_coil = 2)
+ reqs = list(/obj/item/stack/sheet/plasteel = 1, /obj/item/stack/tile/plasteel = 1, /obj/item/stack/cable_coil = 2)
category = CAT_MISC
diff --git a/code/modules/mapping/reader.dm b/code/modules/mapping/reader.dm
index 31b6fbb098a..5c26b467569 100644
--- a/code/modules/mapping/reader.dm
+++ b/code/modules/mapping/reader.dm
@@ -330,7 +330,7 @@ var/global/dmm_suite/preloader/_preloader = new
_preloader.load(.)
//custom CHECK_TICK here because we don't want things created while we're sleeping to not initialize
- if(world.tick_usage > CURRENT_TICKLIMIT)
+ if(TICK_CHECK)
SSatoms.map_loader_stop()
stoplag()
SSatoms.map_loader_begin()
diff --git a/code/modules/mob/dead/new_player/sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories.dm
index 0b00309fe4d..90ea6497822 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories.dm
@@ -812,7 +812,7 @@
gender = FEMALE
/datum/sprite_accessory/undershirt/lover
- name = "Lover shirt"
+ name = "Lover Shirt"
icon_state = "lover"
gender = NEUTER
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 3dd9e2bf771..9c7bb600a4c 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -17,8 +17,13 @@
var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
+
+ var/face_y_offset = 0
+ var/hair_y_offset = 0
+
var/hair_color = null // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color
var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent.
+
var/use_skintones = 0 // does it use skintones or not? (spoiler alert this is only used by humans)
var/exotic_blood = "" // If your race wants to bleed something other than bog standard blood, change this to reagent id.
var/exotic_bloodtype = "" //If your race uses a non standard bloodtype (A+, O-, AB-, etc)
@@ -281,7 +286,7 @@
else
img_hair.color = forced_colour
img_hair.alpha = hair_alpha
-
+ img_hair.pixel_y += hair_y_offset
standing += img_hair
if(standing.len)
@@ -309,12 +314,14 @@
if(H.lip_style && (LIPS in species_traits) && HD)
var/image/lips = image("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[H.lip_style]", "layer" = -BODY_LAYER)
lips.color = H.lip_color
+ lips.pixel_y += face_y_offset
standing += lips
// eyes
if((EYECOLOR in species_traits) && HD && has_eyes)
var/image/img_eyes = image("icon" = 'icons/mob/human_face.dmi', "icon_state" = "eyes", "layer" = -BODY_LAYER)
img_eyes.color = "#" + H.eye_color
+ img_eyes.pixel_y += face_y_offset
standing += img_eyes
//Underwear, Undershirts & Socks
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 599a8cf32f3..d2f460ca2ee 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -958,7 +958,7 @@
if(module.clean_on_move)
flags |= CLEAN_ON_MOVE
else
- flags &= CLEAN_ON_MOVE
+ flags &= ~CLEAN_ON_MOVE
hat_offset = module.hat_offset
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index df28cca78f8..f51876459a6 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -177,12 +177,12 @@
return ..()
var/mob/living/simple_animal/SM = M
if(SM.sentience_type != sentience_type)
- to_chat(user, "The potion won't work on [SM].")
+ to_chat(user, "[src] won't work on [SM].")
return ..()
- to_chat(user, "You offer the sentience potion to [SM]...")
+ to_chat(user, "You offer [src] to [SM]...")
being_used = 1
var/list/candidates = pollCandidatesForMob("Do you want to play as [SM.name]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, SM, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm
@@ -196,7 +196,7 @@
SM.sentience_act()
to_chat(SM, "All at once it makes sense: you know what you are and who you are! Self awareness is yours!")
to_chat(SM, "You are grateful to be self aware and owe [user] a great debt. Serve [user], and assist [user.p_them()] in completing [user.p_their()] goals at any cost.")
- to_chat(user, "[SM] accepts the potion and suddenly becomes attentive and aware. It worked!")
+ to_chat(user, "[SM] accepts [src] and suddenly becomes attentive and aware. It worked!")
qdel(src)
else
to_chat(user, "[SM] looks interested for a moment, but then looks back down. Maybe you should try again later.")
diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm
index f7ab2418db5..afd66daf955 100644
--- a/code/modules/spells/spell_types/lichdom.dm
+++ b/code/modules/spells/spell_types/lichdom.dm
@@ -17,124 +17,139 @@
cooldown_min = 10
include_user = 1
- var/obj/marked_item
- var/mob/living/current_body
- var/resurrections = 0
- var/existence_stops_round_end = 0
-
action_icon_state = "skeleton"
-/obj/effect/proc_holder/spell/targeted/lichdom/New()
- if(initial(SSticker.mode.round_ends_with_antag_death))
- existence_stops_round_end = 1
- SSticker.mode.round_ends_with_antag_death = 0
- ..()
-
-/obj/effect/proc_holder/spell/targeted/lichdom/Destroy()
- for(var/datum/mind/M in SSticker.mode.wizards) //Make sure no other bones are about
- for(var/obj/effect/proc_holder/spell/S in M.spell_list)
- if(istype(S,/obj/effect/proc_holder/spell/targeted/lichdom) && S != src)
- return ..()
- if(existence_stops_round_end)
- SSticker.mode.round_ends_with_antag_death = 1
- ..()
-
/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets,mob/user = usr)
for(var/mob/M in targets)
var/list/hand_items = list()
if(iscarbon(M))
hand_items = list(M.get_active_held_item(),M.get_inactive_held_item())
-
- if(marked_item && !stat_allowed) //sanity, shouldn't happen without badminry
- marked_item = null
+ if(!hand_items.len)
+ to_chat(M, "You must hold an item you wish to make your phylactery...")
return
- if(stat_allowed) //Death is not my end!
- if(M.stat == CONSCIOUS && iscarbon(M))
- to_chat(M, "You aren't dead enough to revive!" )
- charge_counter = charge_max
- return
+ var/obj/item/marked_item
- if(!marked_item || QDELETED(marked_item)) //Wait nevermind
- to_chat(M, "Your phylactery is gone!")
- return
+ for(var/obj/item in hand_items)
+ // I ensouled the nuke disk once. But it's probably a really
+ // mean tactic, so probably should discourage it.
+ if(ABSTRACT in item.flags || NODROP in item.flags || HAS_SECONDARY_FLAG(item, STATIONLOVING))
+ continue
+ marked_item = item
+ to_chat(M, "You begin to focus your very being into [item]...")
+ break
- var/turf/user_turf = get_turf(M)
- var/turf/item_turf = get_turf(marked_item)
+ if(!marked_item)
+ to_chat(M, "None of the items you hold are suitable for emplacement of your fragile soul.")
+ return
- if(user_turf.z != item_turf.z)
- to_chat(M, "Your phylactery is out of range!")
- return
+ playsound(user, 'sound/effects/pope_entry.ogg', 100)
- if(isobserver(M))
- var/mob/dead/observer/O = M
- O.reenter_corpse()
+ if(!do_after(M, 50, needhand=FALSE, target=marked_item))
+ to_chat(M, "Your soul snaps back to your body as you stop ensouling [marked_item]!")
+ return
- var/mob/living/carbon/human/lich = new /mob/living/carbon/human(item_turf)
+ marked_item.name = "ensouled [marked_item.name]"
+ marked_item.desc += "\nA terrible aura surrounds this item, its very existence is offensive to life itself..."
+ marked_item.add_atom_colour("#003300", ADMIN_COLOUR_PRIORITY)
- lich.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/magic(lich), slot_shoes)
- lich.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(lich), slot_w_uniform)
- lich.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(lich), slot_wear_suit)
- lich.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(lich), slot_head)
+ new /obj/item/phylactery(marked_item, M.mind)
- lich.real_name = M.mind.name
- M.mind.transfer_to(lich)
- lich.hardset_dna(null,null,lich.real_name,null,/datum/species/skeleton)
- to_chat(lich, "Your bones clatter and shutter as you are pulled back into this world!")
- charge_max += 600
- var/mob/old_body = current_body
- var/turf/body_turf = get_turf(old_body)
- current_body = lich
- lich.Weaken(10+10*resurrections)
- ++resurrections
- if(old_body && old_body.loc)
- if(iscarbon(old_body))
- var/mob/living/carbon/C = old_body
- for(var/obj/item/W in C)
- C.dropItemToGround(W)
- for(var/X in C.internal_organs)
- var/obj/item/organ/I = X
- I.Remove(C)
- I.forceMove(body_turf)
- var/wheres_wizdo = dir2text(get_dir(body_turf, item_turf))
- if(wheres_wizdo)
- old_body.visible_message("Suddenly [old_body.name]'s corpse falls to pieces! You see a strange energy rise from the remains, and speed off towards the [wheres_wizdo]!")
- body_turf.Beam(item_turf,icon_state="lichbeam",time=10+10*resurrections,maxdistance=INFINITY)
- old_body.dust()
+ to_chat(M, "With a hideous feeling of emptiness you watch in horrified fascination as skin sloughs off bone! Blood boils, nerves disintegrate, eyes boil in their sockets! As your organs crumble to dust in your fleshless chest you come to terms with your choice. You're a lich!")
+ M.set_species(/datum/species/skeleton)
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ H.dropItemToGround(H.w_uniform)
+ H.dropItemToGround(H.wear_suit)
+ H.dropItemToGround(H.head)
+ H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), slot_wear_suit)
+ H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), slot_head)
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), slot_w_uniform)
- if(!marked_item) //linking item to the spell
- message = ""
- for(var/obj/item in hand_items)
- if(ABSTRACT in item.flags || NODROP in item.flags)
- continue
- marked_item = item
- to_chat(M, "You begin to focus your very being into the [item.name]...")
- break
+ // you only get one phylactery.
+ M.mind.RemoveSpell(src)
- if(!marked_item)
- to_chat(M, "You must hold an item you wish to make your phylactery...")
- return
- if(!do_after(M, 50, needhand=FALSE, target=marked_item))
- to_chat(M, "Your soul snaps back to your body as you stop ensouling [marked_item.name]!")
- marked_item = null
- return
- name = "RISE!"
- desc = "Rise from the dead! You will reform at the location of your phylactery and your old body will crumble away."
- charge_max = 1800 //3 minute cooldown, if you rise in sight of someone and killed again, you're probably screwed.
- charge_counter = 1800
- stat_allowed = 1
- marked_item.name = "ensouled [marked_item.name]"
- marked_item.desc += "\nA terrible aura surrounds this item, its very existence is offensive to life itself..."
- marked_item.add_atom_colour("#003300", ADMIN_COLOUR_PRIORITY)
- poi_list |= marked_item
+/obj/item/phylactery
+ name = "phylactery"
+ desc = "Stores souls. Revives liches. Also repels mosquitos."
+ icon = 'icons/obj/projectiles.dmi'
+ icon_state = "bluespace"
+ color = "#003300"
+ light_color = "#003300"
+ var/lon_range = 3
+ var/resurrections = 0
+ var/datum/mind/mind
+ var/respawn_time = 1800
- to_chat(M, "With a hideous feeling of emptiness you watch in horrified fascination as skin sloughs off bone! Blood boils, nerves disintegrate, eyes boil in their sockets! As your organs crumble to dust in your fleshless chest you come to terms with your choice. You're a lich!")
- M.set_species(/datum/species/skeleton)
- current_body = M.mind.current
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- H.dropItemToGround(H.wear_suit)
- H.dropItemToGround(H.head)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), slot_head)
+ var/static/active_phylacteries = 0
+
+/obj/item/phylactery/Initialize(mapload, datum/mind/newmind)
+ ..()
+ mind = newmind
+ name = "phylactery of [mind.name]"
+
+ active_phylacteries++
+ poi_list |= src
+ START_PROCESSING(SSobj, src)
+ set_light(lon_range)
+ if(initial(ticker.mode.round_ends_with_antag_death))
+ ticker.mode.round_ends_with_antag_death = FALSE
+
+/obj/item/phylactery/Destroy(force=FALSE)
+ STOP_PROCESSING(SSobj, src)
+ active_phylacteries--
+ poi_list -= src
+ if(!active_phylacteries)
+ ticker.mode.round_ends_with_antag_death = initial(ticker.mode.round_ends_with_antag_death)
+ . = ..()
+
+/obj/item/phylactery/process()
+ if(QDELETED(mind))
+ qdel(src)
+ return
+
+ if(!mind.current || (mind.current && mind.current.stat == DEAD))
+ addtimer(CALLBACK(src, .proc/rise), respawn_time, TIMER_UNIQUE)
+
+/obj/item/phylactery/proc/rise()
+ if(mind.current && mind.current.stat != DEAD)
+ return "[mind] already has a living body: [mind.current]"
+
+ var/turf/item_turf = get_turf(src)
+ if(!item_turf)
+ return "[src] is not at a turf? NULLSPACE!?"
+
+ var/mob/old_body = mind.current
+ var/mob/living/carbon/human/lich = new(item_turf)
+
+ lich.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/magic(lich), slot_shoes)
+ lich.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(lich), slot_w_uniform)
+ lich.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(lich), slot_wear_suit)
+ lich.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(lich), slot_head)
+
+ lich.real_name = mind.name
+ mind.transfer_to(lich)
+ mind.grab_ghost(force=TRUE)
+ lich.hardset_dna(null,null,lich.real_name,null,/datum/species/skeleton)
+ to_chat(lich, "Your bones clatter and shutter as you are pulled back into this world!")
+ var/turf/body_turf = get_turf(old_body)
+ lich.Weaken(10+10*resurrections)
+ resurrections++
+ if(old_body && old_body.loc)
+ if(iscarbon(old_body))
+ var/mob/living/carbon/C = old_body
+ for(var/obj/item/W in C)
+ C.dropItemToGround(W)
+ for(var/X in C.internal_organs)
+ var/obj/item/organ/I = X
+ I.Remove(C)
+ I.forceMove(body_turf)
+ var/wheres_wizdo = dir2text(get_dir(body_turf, item_turf))
+ if(wheres_wizdo)
+ old_body.visible_message("Suddenly [old_body.name]'s corpse falls to pieces! You see a strange energy rise from the remains, and speed off towards the [wheres_wizdo]!")
+ body_turf.Beam(item_turf,icon_state="lichbeam",time=10+10*resurrections,maxdistance=INFINITY)
+ old_body.dust()
+
+
+ return "Respawn of [mind] successful."
diff --git a/code/modules/uplink/uplink_item.dm b/code/modules/uplink/uplink_item.dm
index de2afdb8d8f..9d44b96b237 100644
--- a/code/modules/uplink/uplink_item.dm
+++ b/code/modules/uplink/uplink_item.dm
@@ -1081,10 +1081,10 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
cost = 20
/datum/uplink_item/device_tools/jammer
- name = "Radio jammer"
+ name = "Radio Jammer"
desc = "This device will disrupt any nearby outgoing radio communication when activated."
item = /obj/item/device/jammer
- cost = 10
+ cost = 5
// Implants
/datum/uplink_item/implants
diff --git a/code/modules/vehicles/speedbike.dm b/code/modules/vehicles/speedbike.dm
index badbdbe3851..3db99e736b6 100644
--- a/code/modules/vehicles/speedbike.dm
+++ b/code/modules/vehicles/speedbike.dm
@@ -7,8 +7,8 @@
var/image/overlay = null
/obj/vehicle/space/speedbike/buckle_mob(mob/living/M, force = 0, check_loc = 1)
- . = ..()
- riding_datum = new/datum/riding/space/speedbike
+ . = ..()
+ riding_datum = new/datum/riding/space/speedbike
/obj/vehicle/space/speedbike/New()
. = ..()
diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm
index 3bbecd08f6d..1bdbd3fa45c 100644
--- a/code/modules/zombie/items.dm
+++ b/code/modules/zombie/items.dm
@@ -5,6 +5,7 @@
sustain the zombie, smashing open airlock doors and opening \
child-safe caps on bottles."
flags = NODROP|ABSTRACT|DROPDEL
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
icon = 'icons/effects/blood.dmi'
icon_state = "bloodhand_left"
var/icon_left = "bloodhand_left"
diff --git a/html/changelog.html b/html/changelog.html
index a7d00cc2671..e6cb447c149 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -55,6 +55,31 @@
-->
+
23 March 2017
+
Joan updated:
+
+ - Clock cults always have to summon Ratvar, but that always involves a proselytization burst.
+ - The proselytization burst will no longer convert heretics, leaving Ratvar free to chase them down.
+ - Places that referred to the Ark of the Clockwork Justicar as the "Gateway to the Celestial Derelict" have been corrected to always refer to the Ark.
+
+
Penguaro updated:
+
+ - Wizard Ship - Bolts that floating light to the wall.
+
+
XDTM updated:
+
+ - Medical Gauze now stacks up to 12
+ - Pressure plates are now craftable.
+
+
bgobandit updated:
+
+ - Alt-clicking a command headset toggles HIGH VOLUME mode.
+
+
coiax updated:
+
+ - A dead AI no longer counts as an "unconverted AI" for clockcult.
+
+
22 March 2017
BeeSting12 updated:
@@ -1843,39 +1868,6 @@
- A few iconless items have been blacklisted from chameleon clothing.
- Reviver implants now warn you when they're turning on or off, or when giving a heart attack due to EMP.
-
-
19 January 2017
-
Cyberboss updated:
-
- - Various abstract entities will no longer be affected by spacewind
- - Ash will, once again, burn in lava
- - Active testmerges of PRs will now be shown in the MOTD
- - You will no longer appear to bleed while bandaged
-
-
Joan updated:
-
- - Clockwork airlocks now have more explicit deconstruction messages, using the same syntax as rwall deconstruction.
-
-
Mervill updated:
-
- - Raw Telecrystals won't appear in the Traitor's purchase log at the end of the round
-
-
MrStonedOne updated:
-
- - Fixed excessive and immersion ruining delay on the smoothing of asteroid/mining rock after a neighboring rock turf was mined up.
-
-
XDTM updated:
-
- - Plasmamen that are set on fire by reacting with oxygen will burn even if they have protective clothing. It will still protect from external fire sources.
- - Atmos-sealing clothing, like hardsuits, will protect plasmamen from reacting with the atmosphere.
- - Plasmamen can survive up to 1 mole of oxygen before burning, instead of burning with any hint of oxygen.
- - Nanotrasen no longer ships self-glueing posters. You'll have to finish placing the posters to ensure they don't fall on the ground.
- - Exosuits can't push anchored mobs, such as megafauna or tendrils, anymore.
-
-
coiax updated:
-
- - AIs can no longer activate the Doomsday Device off-station. Previously it would activate and then immediately turn off, outing the AI as a traitor without any benefit.
-
GoonStation 13 Development Team
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 1b067b434be..3767d2846e3 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -10284,3 +10284,20 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
blue is charging, green is full. Emagged APCs are also blue. Broken APCs do
not emit light.
- rscadd: Alien glowing resin now glows.
+2017-03-23:
+ Joan:
+ - tweak: Clock cults always have to summon Ratvar, but that always involves a proselytization
+ burst.
+ - rscdel: The proselytization burst will no longer convert heretics, leaving Ratvar
+ free to chase them down.
+ - spellcheck: Places that referred to the Ark of the Clockwork Justicar as the "Gateway
+ to the Celestial Derelict" have been corrected to always refer to the Ark.
+ Penguaro:
+ - bugfix: Wizard Ship - Bolts that floating light to the wall.
+ XDTM:
+ - rscadd: Medical Gauze now stacks up to 12
+ - bugfix: Pressure plates are now craftable.
+ bgobandit:
+ - tweak: Alt-clicking a command headset toggles HIGH VOLUME mode.
+ coiax:
+ - bugfix: A dead AI no longer counts as an "unconverted AI" for clockcult.
diff --git a/html/changelogs/AutoChangeLog-pr-25318.yml b/html/changelogs/AutoChangeLog-pr-25318.yml
deleted file mode 100644
index 5dce685c84c..00000000000
--- a/html/changelogs/AutoChangeLog-pr-25318.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "bgobandit"
-delete-after: True
-changes:
- - tweak: "Alt-clicking a command headset toggles HIGH VOLUME mode."
diff --git a/html/changelogs/AutoChangeLog-pr-25360.yml b/html/changelogs/AutoChangeLog-pr-25360.yml
new file mode 100644
index 00000000000..47a960cbe39
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-25360.yml
@@ -0,0 +1,11 @@
+author: "coiax"
+delete-after: True
+changes:
+ - rscadd: "Destroying a lich's body does not destroy the lich permanently,
+provided the phylactery is intact."
+ - rscadd: "A lich will respawn three minutes after its death, provided the
+phylactery is intact."
+ - rscadd: "The Soul Bind spell is forgotten after cast, respawn is now
+automatic."
+ - rscdel: "Stationloving objects like the nuke disk are not valid objects for
+a phylactery."
diff --git a/icons/effects/weather_effects.dmi b/icons/effects/weather_effects.dmi
index 215cf53556f..c8dc912465c 100644
Binary files a/icons/effects/weather_effects.dmi and b/icons/effects/weather_effects.dmi differ
diff --git a/icons/obj/atmospherics/components/miners.dmi b/icons/obj/atmospherics/components/miners.dmi
new file mode 100644
index 00000000000..db47b47feea
Binary files /dev/null and b/icons/obj/atmospherics/components/miners.dmi differ
diff --git a/icons/obj/flora/jungleflora.dmi b/icons/obj/flora/jungleflora.dmi
new file mode 100644
index 00000000000..02d21b7e51d
Binary files /dev/null and b/icons/obj/flora/jungleflora.dmi differ
diff --git a/icons/obj/flora/jungletrees.dmi b/icons/obj/flora/jungletrees.dmi
new file mode 100644
index 00000000000..172feb9cc9a
Binary files /dev/null and b/icons/obj/flora/jungletrees.dmi differ
diff --git a/icons/obj/flora/largejungleflora.dmi b/icons/obj/flora/largejungleflora.dmi
new file mode 100644
index 00000000000..04b8d94c9fe
Binary files /dev/null and b/icons/obj/flora/largejungleflora.dmi differ
diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi
index ada8ba3cf28..a1cd8fb2f98 100644
Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ
diff --git a/icons/turf/floors/darkdirt.dmi b/icons/turf/floors/darkdirt.dmi
new file mode 100644
index 00000000000..b36b627d6a7
Binary files /dev/null and b/icons/turf/floors/darkdirt.dmi differ
diff --git a/icons/turf/floors/dirt.dmi b/icons/turf/floors/dirt.dmi
new file mode 100644
index 00000000000..4f533a62284
Binary files /dev/null and b/icons/turf/floors/dirt.dmi differ
diff --git a/sound/ambience/acidrain_end.ogg b/sound/ambience/acidrain_end.ogg
new file mode 100644
index 00000000000..75fb4aaf8dd
Binary files /dev/null and b/sound/ambience/acidrain_end.ogg differ
diff --git a/sound/ambience/acidrain_mid.ogg b/sound/ambience/acidrain_mid.ogg
new file mode 100644
index 00000000000..03d4812355b
Binary files /dev/null and b/sound/ambience/acidrain_mid.ogg differ
diff --git a/sound/ambience/acidrain_start.ogg b/sound/ambience/acidrain_start.ogg
new file mode 100644
index 00000000000..48f365d9df9
Binary files /dev/null and b/sound/ambience/acidrain_start.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index 216e0243211..7161d2c4069 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -928,6 +928,7 @@
#include "code\game\turfs\simulated\minerals.dm"
#include "code\game\turfs\simulated\river.dm"
#include "code\game\turfs\simulated\walls.dm"
+#include "code\game\turfs\simulated\water.dm"
#include "code\game\turfs\simulated\floor\fancy_floor.dm"
#include "code\game\turfs\simulated\floor\light_floor.dm"
#include "code\game\turfs\simulated\floor\mineral_floor.dm"
@@ -936,6 +937,7 @@
#include "code\game\turfs\simulated\floor\plating.dm"
#include "code\game\turfs\simulated\floor\reinf_floor.dm"
#include "code\game\turfs\simulated\floor\plating\asteroid.dm"
+#include "code\game\turfs\simulated\floor\plating\dirt.dm"
#include "code\game\turfs\simulated\floor\plating\lava.dm"
#include "code\game\turfs\simulated\floor\plating\misc_plating.dm"
#include "code\game\turfs\simulated\wall\mineral_walls.dm"
@@ -1049,6 +1051,7 @@
#include "code\modules\atmospherics\machinery\components\unary_devices\vent_pump.dm"
#include "code\modules\atmospherics\machinery\components\unary_devices\vent_scrubber.dm"
#include "code\modules\atmospherics\machinery\other\meter.dm"
+#include "code\modules\atmospherics\machinery\other\miner.dm"
#include "code\modules\atmospherics\machinery\other\zvent.dm"
#include "code\modules\atmospherics\machinery\pipes\manifold.dm"
#include "code\modules\atmospherics\machinery\pipes\manifold4w.dm"
diff --git a/tools/mapmerge/README.md b/tools/mapmerge/README.md
index 3a9d0cb8cf5..08190019e4d 100644
--- a/tools/mapmerge/README.md
+++ b/tools/mapmerge/README.md
@@ -1,68 +1,63 @@
-#Map Merger#
+# Map Merger
+
Before any change to a map, it is good to use the Map Merger tools. In a nutshell, it rewrites the map to minimize differences between different versions of the map (DreamMakers map editor rewrites a lot of the tile keys). This makes the git diff between different map changes much smaller. More recently a new way of laying out the map was invented by Remie, called TGM, this helps to further reduce conflicts in the map files.
This is good for a few reasons
-1) Maintainers can actually verify the changes you are making are what you say they are by simply viewing the diff (For small changes at least)
-
-2) The less changes there are in any given map diff, the easier it is for git to merge it without running into unexpected conflicts, which in most cases you have to either manually resolve or require you to remap your changes
+- Maintainers can actually verify the changes you are making are what you say they are by simply viewing the diff (For small changes at least)
+- The less changes there are in any given map diff, the easier it is for git to merge it without running into unexpected conflicts, which in most cases you have to either manually resolve or require you to remap your changes
However - to do all this is going to require you to put some elbow grease into understanding the map merger tool.
If you have difficulty using these tools, ask for help in #coderbus
-#Using the tools#
+## Using the tools
-##1. Install Python 3.5 or greater##
-If you don't have Python already installed it can be downloaded from: https://www.python.org/downloads/ - make sure you grab the latest python 3, again, it must be 3.5 or greater
-##2. PATH Python##
-This step is mostly applicable to windows users, you must make sure you ask the windows installer to add python to your path, [like shown in this example screenshot](https://file.house/DA6H.png)
+1. **Install Python 3.5 or greater** - If you don't have Python already installed it can be downloaded from: https://www.python.org/downloads/ - make sure you grab the latest python 3, again, it must be 3.5 or greater
-If you have already installed python you may need to manually add it to your path as indicated in [this guide](http://superuser.com/questions/143119/how-to-add-python-to-the-windows-path)
-##3. Prepare Maps##
-Run "Prepare Maps.bat" in the tools/mapmerge/ directory.
-##4. Edit your map##
-Make your changes to the map here. Remember to save them!
-##5. Clean map##
-Run "Run Map Merge - TGM.bat" in the tools/mapmerge/ directory.
-##7. Check differences##
-Use your git application of choice to look at the differences between revisions of your code and commit the result.
-##8. Commit##
-Your map is now ready to be committed, rejoice and wait for conflicts.
+2. **PATH Python** - This step is mostly applicable to windows users, you must make sure you ask the windows installer to add python to your path. If you have already installed python you may need to manually add it to your path as indicated in this guide
-#Common pitfalls#
-Open the map in dreameditor before committing the results of the mapmerger - this can cause dreameditor to resave the map back to
-dmm, if you're having issues with your map getting stuck in dmm mode, try comitting and pushing the mapmerger changes before
-reopening in dreameditor.
+3. **Prepare Maps** - Run "Prepare Maps.bat" in the tools/mapmerge/ directory.
+4. **Edit your map** - Make your changes to the map here. Remember to save them!
+5. **Clean map** - Run "Run Map Merge - TGM.bat" in the tools/mapmerge/ directory.
+6. **Check differences** - Use your git application of choice to look at the differences between revisions of your code and commit the result.
+7. **Commit** - Your map is now ready to be committed, rejoice and wait for conflicts.
+## Common pitfalls
+
+Do *not* open the map in dreameditor before committing the results of the mapmerger - this can cause dreameditor to resave the map back to dmm, if you're having issues with your map getting stuck in dmm mode, try committing and pushing the mapmerger changes before reopening in dreameditor.
+
+## Map Conflict Fixer/Helper
-#Map Conflict Fixer/Helper#
The map conflict fixer is a script that can help you fix map conflicts easier and faster. Here's how it works:
-###Before using###
-You need git for this, of course.
-Make sure your development branch is up to date before starting a map edit to ensure the script outputs a correct fix.
+### Before using
+
+You need git for this, of course. Make sure your development branch is up to date before starting a map edit to ensure the script outputs a correct fix.
+
+### Dictionary mode
-##Dictionary mode##
Dictionary conflicts are the easiest to fix, you simply need to create more models to accommodate your changes and everyone elses.
-When you run in this mode, if the script finishes successfuly the map should be ready to be commited.
+When you run in this mode, if the script finishes successfully the map should be ready to be committed.
If the script fails in dictionary mode, you can run it again in full fix mode.
-##Full Fix mode##
+### Full Fix mode
+
When you and someone else edit the same coordinate, there is no easy way to fix the conflict. You need to get your hands dirty.
The script will mark every tile with a marker type to help you identify what needs fixing in the map editor.
After you edit and fix a marked map, you should run it through the map merger. The .backup file should be the same you used before.
-###Priorities###
+#### Priorities
+
In Full Fix mode, the script needs to know which map version has higher priority, yours or someone elses. This important so tiles with multiple area and turf types aren't created.
-Your version has priority - In each conflicted coordinate, your floor type and your area type will be used
-Their version has priority - In each conflicted coordinate, your floor type and your area type will not be used
+Your version has priority - In each conflicted coordinate, your floor type and your area type will be used Their version has priority - In each conflicted coordinate, your floor type and your area type will not be used
-##IMPORTANT##
-This script is in a testing phase and you should not consider any output to be safe. Always verify the maps this script produced to make sure nothing is out of place.
\ No newline at end of file
+### IMPORTANT
+
+This script is in a testing phase and you should not consider any output to be safe. Always verify the maps this script produced to make sure nothing is out of place.