mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2025-12-21 07:42:21 +00:00
Merge remote-tracking branch 'ParadiseSS13/master' into client-data-loading
This commit is contained in:
418
.github/CONTRIBUTING.md
vendored
418
.github/CONTRIBUTING.md
vendored
@@ -8,17 +8,20 @@ refer to the [Issue Report](#issues) section, as well as the
|
|||||||
[Issue Report Template](ISSUE_TEMPLATE.md).
|
[Issue Report Template](ISSUE_TEMPLATE.md).
|
||||||
|
|
||||||
## Commenting
|
## Commenting
|
||||||
If you comment on an active pull request, or issue report, make sure your comment is
|
If you comment on an active pull request or issue report, make sure your comment is
|
||||||
concise and to the point. Comments on issue reports or pull requests should be relevant
|
concise and to the point. Comments on issue reports or pull requests should be relevant
|
||||||
and friendly, not attacks on the author or adages about something minimally relevant.
|
and friendly, not attacks on the author or adages about something minimally relevant.
|
||||||
If you believe an issue report is not a "bug", please report it to the Maintainers, or
|
If you believe an issue report is not a "bug", please point out specifically and concisely your reasoning in a comment on the issue itself.
|
||||||
point out specifically and concisely your reasoning in a comment on the issue report.
|
|
||||||
|
#### Guidelines:
|
||||||
|
* Comments on Pull Requests and Issues should remain relevant to the subject in question and not derail discussions.
|
||||||
|
* Under no circumstances are users to be attacked for their ideas or contributions. All participants on a given PR or issue are expected to be civil. Failure to do so will result in disciplinary action.<br>
|
||||||
|
For more details, see the [Code of Conduct](../CODE_OF_CONDUCT.md).
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
The Issues section is not a place to request features, or ask for things to be changed
|
The Issues section is not a place to request features, or ask for things to be changed
|
||||||
because you think they should be that way; The Issues section is specifically for
|
because you think they should be that way; The Issues section is specifically for
|
||||||
reporting bugs in the code. Refer to ISSUE_TEMPLATE for the exact format that your Issue
|
reporting bugs in the code.
|
||||||
should be in.
|
|
||||||
|
|
||||||
#### Guidelines:
|
#### Guidelines:
|
||||||
* Issue reports should be as detailed as possible, and if applicable, should include
|
* Issue reports should be as detailed as possible, and if applicable, should include
|
||||||
@@ -57,21 +60,21 @@ actual development.
|
|||||||
* While we have no issue helping contributors (and especially new contributors) bring reasonably sized contributions up to standards via the pull request review process, larger contributions are expected to pass a higher bar of completeness and code quality *before* you open a pull request. Maintainers may close such pull requests that are deemed to be substantially flawed. You should take some time to discuss with maintainers or other contributors on how to improve the changes.
|
* While we have no issue helping contributors (and especially new contributors) bring reasonably sized contributions up to standards via the pull request review process, larger contributions are expected to pass a higher bar of completeness and code quality *before* you open a pull request. Maintainers may close such pull requests that are deemed to be substantially flawed. You should take some time to discuss with maintainers or other contributors on how to improve the changes.
|
||||||
|
|
||||||
#### Using Changelog
|
#### Using Changelog
|
||||||
* Tags used in changelog include add/rscadd, del/rscdel, fix/fixes, typo/spellcheck.
|
* The tags able to be used in the changelog are: `add/soundadd/imageadd`, `del/sounddel/imagedel`, `tweak`, `fix`, `wip`, `spellcheck`, and `experiment`.
|
||||||
* Without specifying a name it will default to using your GitHub name.
|
* Without specifying a name it will default to using your GitHub name. Some examples include:
|
||||||
Some examples
|
|
||||||
```
|
```
|
||||||
:cl:
|
:cl:
|
||||||
add: The ability to change the color of wires
|
add: The ability to change the color of wires
|
||||||
del: Deleted depreciated wire merging now handled in parent
|
del: Deleted depreciated wire merging now handled in parent
|
||||||
fix: Moving wires now follows the user input instead of moving the stack
|
fix: Moving wires now follows the user input instead of moving the stack
|
||||||
/:cl:
|
/:cl:
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
:cl: N3X15
|
:cl: UsernameHere
|
||||||
typo: Fixes some misspelled words under Using Changelog
|
spellcheck: Fixes some misspelled words under Using Changelog
|
||||||
/:cl:
|
/:cl:
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Specifications
|
## Specifications
|
||||||
@@ -113,14 +116,13 @@ datum
|
|||||||
code
|
code
|
||||||
```
|
```
|
||||||
|
|
||||||
The use of this is not allowed in this project *unless the majority of the file is already relatively pathed* as it makes finding definitions via full text
|
The use of this format is **not** allowed in this project, as it makes finding definitions via full text searching next to impossible. The only exception is the variables of an object may be nested to the object, but must not nest further.
|
||||||
searching next to impossible. The only exception is the variables of an object may be nested to the object, but must not nest further.
|
|
||||||
|
|
||||||
The previous code made compliant:
|
The previous code made compliant:
|
||||||
|
|
||||||
```DM
|
```DM
|
||||||
/datum/datum1
|
/datum/datum1
|
||||||
var/varname1
|
var/varname1 = 1
|
||||||
var/varname2
|
var/varname2
|
||||||
var/static/varname3
|
var/static/varname3
|
||||||
var/static/varname4
|
var/static/varname4
|
||||||
@@ -129,6 +131,7 @@ The previous code made compliant:
|
|||||||
code
|
code
|
||||||
/datum/datum1/proc/proc2()
|
/datum/datum1/proc/proc2()
|
||||||
code
|
code
|
||||||
|
|
||||||
/datum/datum1/datum2
|
/datum/datum1/datum2
|
||||||
varname1 = 0
|
varname1 = 0
|
||||||
/datum/datum1/datum2/proc/proc3()
|
/datum/datum1/datum2/proc/proc3()
|
||||||
@@ -139,11 +142,11 @@ The previous code made compliant:
|
|||||||
```
|
```
|
||||||
|
|
||||||
### User Interfaces
|
### User Interfaces
|
||||||
All new user interfaces in the game must be created using the TGUI framework. Documentation can be found inside the `tgui/docs` folder.
|
All new user interfaces in the game must be created using the TGUI framework. Documentation can be found inside the [`tgui/docs`](../tgui/docs) folder, and the [`README.md`](../tgui/README.md) file.
|
||||||
This is to ensure all ingame UIs are snappy and respond well. An exception is made for user interfaces which are purely for OOC actions (Such as character creation, or anything admin related)
|
This is to ensure all ingame UIs are snappy and respond well. An exception is made for user interfaces which are purely for OOC actions (Such as character creation, or anything admin related)
|
||||||
|
|
||||||
### 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.
|
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 begin with a /
|
### Type paths must begin with a /
|
||||||
eg: `/datum/thing`, not `datum/thing`
|
eg: `/datum/thing`, not `datum/thing`
|
||||||
@@ -156,11 +159,11 @@ will still be, in actuality, `/datum/arbitrary`. Write your code to reflect this
|
|||||||
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:
|
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:
|
||||||
|
|
||||||
```DM
|
```DM
|
||||||
//Good
|
|
||||||
var/path_type = /obj/item/baseball_bat
|
|
||||||
|
|
||||||
//Bad
|
//Bad
|
||||||
var/path_type = "/obj/item/baseball_bat"
|
var/path_type = "/obj/item/baseball_bat"
|
||||||
|
|
||||||
|
//Good
|
||||||
|
var/path_type = /obj/item/baseball_bat
|
||||||
```
|
```
|
||||||
|
|
||||||
### Do not use `\The`.
|
### Do not use `\The`.
|
||||||
@@ -170,17 +173,18 @@ The only exception to this rule is when dealing with items "belonging" to a mob,
|
|||||||
ever forming.
|
ever forming.
|
||||||
|
|
||||||
```DM
|
```DM
|
||||||
|
//Bad
|
||||||
|
var/atom/A
|
||||||
|
"\The [A]"
|
||||||
|
|
||||||
//Good
|
//Good
|
||||||
var/atom/A
|
var/atom/A
|
||||||
"[A]"
|
"[A]"
|
||||||
|
|
||||||
//Bad
|
|
||||||
"\The [A]"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Use the pronoun library instead of `\his` macros.
|
### Use the pronoun library instead of `\his` macros.
|
||||||
We have a system in code/\_\_HELPERS/pronouns.dm for addressing all forms of pronouns. This is useful in a number of ways;
|
We have a system in [`code/__HELPERS/pronouns.dm`](../code/__HELPERS/pronouns.dm) for addressing all forms of pronouns. This is useful in a number of ways;
|
||||||
* BYOND's \his macro can be unpredictable on what object it references.
|
* BYOND's `\his` macro can be unpredictable on what object it references.
|
||||||
Take this example: `"[user] waves \his [user.weapon] around, hitting \his opponents!"`.
|
Take this example: `"[user] waves \his [user.weapon] around, hitting \his opponents!"`.
|
||||||
This will end up referencing the user's gender in the first occurence, but what about the second?
|
This will end up referencing the user's gender in the first occurence, but what about the second?
|
||||||
It'll actually print the gender set on the weapon he's carrying, which is unintended - and there's no way around this.
|
It'll actually print the gender set on the weapon he's carrying, which is unintended - and there's no way around this.
|
||||||
@@ -189,14 +193,14 @@ We have a system in code/\_\_HELPERS/pronouns.dm for addressing all forms of pro
|
|||||||
|
|
||||||
The way to avoid these problems is to use the pronoun system. Instead of `"[user] waves \his arms."`, you can do `"[user] waves [user.p_their()] arms."`
|
The way to avoid these problems is to use the pronoun system. Instead of `"[user] waves \his arms."`, you can do `"[user] waves [user.p_their()] arms."`
|
||||||
|
|
||||||
```
|
```DM
|
||||||
//Good
|
|
||||||
"[H] waves [H.p_their()] hands!"
|
|
||||||
"[user] waves [H.p_their()] [user.weapon] around, hitting [H.p_their()] opponents!"`
|
|
||||||
|
|
||||||
//Bad
|
//Bad
|
||||||
"[H] waves \his hands!"
|
"[H] waves \his hands!"
|
||||||
"[user] waves \his [user.weapon] around, hitting \his opponents!"
|
"[user] waves \his [user.weapon] around, hitting \his opponents!"
|
||||||
|
|
||||||
|
//Good
|
||||||
|
"[H] waves [H.p_their()] hands!"
|
||||||
|
"[user] waves [H.p_their()] [user.weapon] around, hitting [H.p_their()] opponents!"`
|
||||||
```
|
```
|
||||||
|
|
||||||
### Use `[A.UID()]` over `\ref[A]`
|
### Use `[A.UID()]` over `\ref[A]`
|
||||||
@@ -207,24 +211,30 @@ if the original datum has been deleted - BYOND recycles the references.
|
|||||||
|
|
||||||
UID's are actually unique; they work off of a global counter and are not recycled. Each datum has one assigned to it when it's created, which can be
|
UID's are actually unique; they work off of a global counter and are not recycled. Each datum has one assigned to it when it's created, which can be
|
||||||
accessed by `[datum.UID()]`. You can use this as a snap-in replacement for `\ref` by changing any `locate(ref)` calls in your code to `locateUID(ref)`.
|
accessed by `[datum.UID()]`. You can use this as a snap-in replacement for `\ref` by changing any `locate(ref)` calls in your code to `locateUID(ref)`.
|
||||||
Usage of this system is mandatory for any /Topic( calls, and will produce errors in Dream Daemon if it's not used. `<a href='?src=[UID()];'>`, not `<a href='?src=\ref[src];'`.
|
Usage of this system is mandatory for any `Topic()` calls, and will produce errors in Dream Daemon if it's not used.
|
||||||
|
```DM
|
||||||
|
//Bad
|
||||||
|
"<a href='?src=\ref[src];'>Link!</a>"
|
||||||
|
|
||||||
### Use var/name format when declaring variables
|
//Good
|
||||||
|
"<a href='?src=[UID()];'>Link!</a>"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use `var/name` format when declaring variables
|
||||||
While DM allows other ways of declaring variables, this one should be used for consistency.
|
While DM allows other ways of declaring variables, this one should be used for consistency.
|
||||||
|
|
||||||
### Tabs, not spaces
|
### Tabs, not spaces
|
||||||
You must use tabs to indent your code, 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)
|
(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 (ex: `istype(src, /obj/whatever)`), is highly discouraged and only allowed when there is ***no*** other option. (
|
Hacky code, such as adding specific checks (ex: `istype(src, /obj/whatever)`), 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! If you can't think of anything else, say that outright and admit that you need help with it. Maintainers, PR Reviewers, and other contributors who can help you exist for exactly that reason.)
|
||||||
Protip: 'I couldn't immediately think of a proper way so thus there must be no other option' is not gonna cut it here! If you can't think of anything else, say that outright and admit that you need help with it. Maintainers exist for exactly that reason.)
|
|
||||||
|
|
||||||
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
|
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.
|
then overriding them as required.
|
||||||
|
|
||||||
The same also applies to bugfix - If an invalid value is being passed into a proc from something that shouldn't have that value, don't fix it on the proc itself, fix it at its origin! (Where feasible)
|
The same also applies to bugfixes - If an invalid value is being passed into a proc from something that shouldn't have that value, don't fix it on the proc itself, fix it at its origin! (Where feasible)
|
||||||
|
|
||||||
### No duplicated code
|
### No duplicated code
|
||||||
Copying code from one place to another may be suitable for small, short-time projects, but Paradise is a long-term project and highly discourages this.
|
Copying code from one place to another may be suitable for small, short-time projects, but Paradise is a long-term project and highly discourages this.
|
||||||
@@ -236,220 +246,226 @@ First, read the comments in [this BYOND thread](http://www.byond.com/forum/?post
|
|||||||
|
|
||||||
There are two key points here:
|
There are two key points here:
|
||||||
|
|
||||||
1) Defining a list in the variable's definition calls a hidden proc - init. If you have to define a list at startup, do so in New() (or preferably Initialize()) and avoid the overhead of a second call (Init() and then New())
|
1) Defining a list in the variable's definition calls a hidden proc - init. If you have to define a list at startup, do so in `New()` (or preferably `Initialize()`) and avoid the overhead of a second call (`init()` and then `New()`)
|
||||||
|
|
||||||
2) It also consumes more memory to the point where the list is actually required, even if the object in question may never use it!
|
2) It also consumes more memory to the point where the list is actually required, even if the object in question may never use it!
|
||||||
|
|
||||||
Remember: although this tradeoff makes sense in many cases, it doesn't cover them all. Think carefully about your addition before deciding if you need to use it.
|
Remember: although this tradeoff makes sense in many cases, it doesn't cover them all. Think carefully about your addition before deciding if you need to use it.
|
||||||
|
|
||||||
### 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.
|
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.
|
||||||
|
|
||||||
While we normally encourage (and in some cases, even require) bringing out of date code up to date when you make unrelated changes near the out of date code, that is not the case for `New` -> `Initialize` conversions. These systems are generally more dependant on parent and children procs so unrelated random conversions of existing things can cause bugs that take months to figure out.
|
While we normally encourage (and in some cases, even require) bringing out of date code up to date when you make unrelated changes near the out of date code, that is not the case for `New()` -> `Initialize()` conversions. These systems are generally more dependent on parent and children procs, so unrelated random conversions of existing things can cause bugs that take months to figure out.
|
||||||
|
|
||||||
### No implicit var/
|
### No implicit `var/`
|
||||||
When you declare a parameter in a proc, the var/ is implicit. Do not include any implicit var/ when declaring a variable.
|
When you declare a parameter in a proc, the `var/` is implicit. Do not include any implicit `var/` when declaring a variable.
|
||||||
|
```DM
|
||||||
|
//Bad
|
||||||
|
/obj/item/proc1(var/mob/input1, var/input2)
|
||||||
|
code
|
||||||
|
|
||||||
I.e.
|
//Good
|
||||||
Bad:
|
/obj/item/proc1(mob/input1, input2)
|
||||||
````
|
code
|
||||||
obj/item/proc1(var/input1, var/input2)
|
```
|
||||||
````
|
|
||||||
Good:
|
|
||||||
|
|
||||||
````
|
|
||||||
obj/item/proc1(input1, input2)
|
|
||||||
````
|
|
||||||
|
|
||||||
### No magic numbers or strings
|
### No magic numbers or strings
|
||||||
This means stuff like having a "mode" variable for an object set to "1" or "2" with no clear indicator of what that means. Make these #defines with a name that
|
This means stuff like having a "mode" variable for an object set to "1" or "2" with no clear indicator of what that means. Make these #defines with a name that more clearly states what it's for. For instance:
|
||||||
more clearly states what it's for. For instance:
|
```DM
|
||||||
````DM
|
//Bad
|
||||||
/datum/proc/do_the_thing(thing_to_do)
|
/datum/proc/do_the_thing(thing_to_do)
|
||||||
switch(thing_to_do)
|
switch(thing_to_do)
|
||||||
if(1)
|
if(1)
|
||||||
(...)
|
do_stuff()
|
||||||
if(2)
|
if(2)
|
||||||
(...)
|
do_other_stuff()
|
||||||
````
|
```
|
||||||
There's no indication of what "1" and "2" mean! Instead, you should do something like this:
|
There's no indication of what "1" and "2" mean! Instead, you should do something like this:
|
||||||
````DM
|
```DM
|
||||||
|
//Good
|
||||||
#define DO_THE_THING_REALLY_HARD 1
|
#define DO_THE_THING_REALLY_HARD 1
|
||||||
#define DO_THE_THING_EFFICIENTLY 2
|
#define DO_THE_THING_EFFICIENTLY 2
|
||||||
|
|
||||||
/datum/proc/do_the_thing(thing_to_do)
|
/datum/proc/do_the_thing(thing_to_do)
|
||||||
switch(thing_to_do)
|
switch(thing_to_do)
|
||||||
if(DO_THE_THING_REALLY_HARD)
|
if(DO_THE_THING_REALLY_HARD)
|
||||||
(...)
|
do_stuff()
|
||||||
if(DO_THE_THING_EFFICIENTLY)
|
if(DO_THE_THING_EFFICIENTLY)
|
||||||
(...)
|
do_other_stuff()
|
||||||
````
|
```
|
||||||
This is clearer and enhances readability of your code! Get used to doing it!
|
This is clearer and enhances readability of your code! Get used to doing it!
|
||||||
|
|
||||||
### Control statements
|
### Control statements
|
||||||
(if, while, for, etc)
|
(if, while, for, etc)
|
||||||
|
|
||||||
* All control statements must not contain code on the same line as the statement (`if(condition) return`)
|
|
||||||
* All control statements comparing a variable to a number should use the formula of `thing` `operator` `number`, not the reverse
|
* 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)`)
|
(eg: `if(count <= 10)` not `if(10 >= count)`)
|
||||||
* All control statements must be spaced as `if()`, with the brackets touching the keyword.
|
* All control statements must be spaced as `if()`, with the brackets touching the keyword.
|
||||||
* Do not use one-line control statements.
|
* All control statements must not contain code on the same line as the statement.
|
||||||
Instead of doing
|
|
||||||
```
|
```DM
|
||||||
|
//Bad
|
||||||
if(x) return
|
if(x) return
|
||||||
```
|
|
||||||
You should do
|
//Good
|
||||||
```
|
|
||||||
if(x)
|
if(x)
|
||||||
return
|
return
|
||||||
```
|
```
|
||||||
|
|
||||||
### Player Output
|
### Player Output
|
||||||
Due to the use of "Goonchat", Paradise requires a special syntax for outputting text messages to players. Instead of `mob/client/world << "message"`,
|
Due to the use of "Goonchat", Paradise requires a special syntax for outputting text messages to players. Instead of `mob << "message"`, you must use `to_chat(mob, "message")`. Failure to do so will lead to your code not working.
|
||||||
you must use `to_chat(mob/client/world, "message")`. Failure to do so will lead to your code not working.
|
|
||||||
|
|
||||||
### Use early return
|
### Use early returns
|
||||||
Do not enclose a proc in an if-block when returning on a condition is more feasible.
|
Do not enclose a proc in an if-block when returning on a condition is more feasible.
|
||||||
|
|
||||||
This is bad:
|
This is bad:
|
||||||
````DM
|
````DM
|
||||||
/datum/datum1/proc/proc1()
|
/datum/datum1/proc/proc1()
|
||||||
if(thing1)
|
if(thing1)
|
||||||
if(!thing2)
|
if(!thing2)
|
||||||
if(thing3 == 30)
|
if(thing3 == 30)
|
||||||
do stuff
|
do stuff
|
||||||
````
|
````
|
||||||
This is good:
|
This is good:
|
||||||
````DM
|
````DM
|
||||||
/datum/datum1/proc/proc1()
|
/datum/datum1/proc/proc1()
|
||||||
if(!thing1)
|
if(!thing1)
|
||||||
return
|
return
|
||||||
if(thing2)
|
if(thing2)
|
||||||
return
|
return
|
||||||
if(thing3 != 30)
|
if(thing3 != 30)
|
||||||
return
|
return
|
||||||
do stuff
|
do stuff
|
||||||
````
|
````
|
||||||
This prevents nesting levels from getting deeper then they need to be.
|
This prevents nesting levels from getting deeper then they need to be.
|
||||||
|
|
||||||
### Uses addtimer() instead of sleep() or spawn()
|
### Use `addtimer()` instead of `sleep()` or `spawn()`
|
||||||
If you need to call a proc after a set amount of time, use addtimer() instead of spawn() / sleep() where feasible.
|
If you need to call a proc after a set amount of time, use `addtimer()` instead of `spawn()` / `sleep()` where feasible.
|
||||||
Although it is more complex, it is more performant and unlike spawn() or sleep(), it can be cancelled.
|
Though more complex, this method has greater performance. Additionally, unlike `spawn()` or `sleep()`, it can be cancelled.
|
||||||
For more details, see https://github.com/tgstation/tgstation/pull/22933.
|
For more details, see https://github.com/tgstation/tgstation/pull/22933.
|
||||||
|
|
||||||
Look for code example on how to properly use it.
|
Look for code examples on how to properly use it.
|
||||||
|
```DM
|
||||||
|
//Bad
|
||||||
|
/datum/datum1/proc/proc1(target)
|
||||||
|
spawn(5 SECONDS)
|
||||||
|
target.dothing(arg1, arg2, arg3)
|
||||||
|
|
||||||
This is bad:
|
//Good
|
||||||
````DM
|
/datum/datum1/proc/proc1(target)
|
||||||
/datum/datum1/proc/proc1()
|
addtimer(CALLBACK(target, .proc/dothing, arg1, arg2, arg3), 5 SECONDS)
|
||||||
spawn(5)
|
```
|
||||||
dothing(arg1, arg2, arg3)
|
|
||||||
````
|
|
||||||
This is good:
|
|
||||||
````DM
|
|
||||||
addtimer(CALLBACK(procsource, .proc/dothing, arg1, arg2, arg3), waittime, timertype)
|
|
||||||
````
|
|
||||||
This prevents nesting levels from getting deeper then they need to be.
|
This prevents nesting levels from getting deeper then they need to be.
|
||||||
|
|
||||||
### Operators
|
### Operators
|
||||||
#### Spacing
|
#### Spacing
|
||||||
* Operators that should be separated by spaces
|
* Operators that should be separated by spaces:
|
||||||
* Boolean and logic operators like &&, || <, >, ==, etc (but not !)
|
* Boolean and logic operators like `&&`, `||` `<`, `>`, `==`, etc. (But not `!`)
|
||||||
* Bitwise AND & and OR |
|
* Bitwise AND `&` and OR `|`.
|
||||||
* Argument separator operators like , (and ; when used in a forloop)
|
* Argument separator operators like `,`. (and `;` when used in a forloop)
|
||||||
* Assignment operators like = or += or the like
|
* Assignment operators like `=` or `+=` or the like.
|
||||||
* Math operators like +, -, /, or \*
|
* Math operators like `+`, `-`, `/`, or `*`.
|
||||||
* Operators that should not be separated by spaces
|
* Operators that should NOT be separated by spaces:
|
||||||
* Access operators like . and :
|
* Access operators like `.` and `:`.
|
||||||
* Parentheses ()
|
* Parentheses `()`.
|
||||||
* logical not !
|
* Logical not `!`.
|
||||||
|
|
||||||
#### Use
|
#### Use
|
||||||
* Bitwise AND - '&'
|
* Bitwise AND `&`
|
||||||
* Should be written as ```bitfield & bitflag``` NEVER ```bitflag & bitfield```, both are valid, but the latter is confusing and nonstandard.
|
* Should be written as `bitfield & bitflag` NEVER `bitflag & bitfield`, both are valid, but the latter is confusing and nonstandard.
|
||||||
* Associated lists declarations must have their key value quoted if it's a string
|
* Associated lists declarations must have their key value quoted if it's a string
|
||||||
* WRONG: list(a = "b")
|
|
||||||
* RIGHT: list("a" = "b")
|
```DM
|
||||||
|
//Bad
|
||||||
|
list(a = "b")
|
||||||
|
|
||||||
|
//Good
|
||||||
|
list("a" = "b")
|
||||||
|
```
|
||||||
|
|
||||||
#### Bitflags
|
#### Bitflags
|
||||||
* We prefer using bitshift operators instead of directly typing out the value. I.E.
|
* We prefer using bitshift operators instead of directly typing out the value. I.E:
|
||||||
|
|
||||||
```
|
```
|
||||||
#define MACRO_ONE (1<<0)
|
#define MACRO_ONE (1<<0)
|
||||||
#define MACRO_TWO (1<<1)
|
#define MACRO_TWO (1<<1)
|
||||||
#define MACRO_THREE (1<<2)
|
#define MACRO_THREE (1<<2)
|
||||||
```
|
```
|
||||||
Is preferable to
|
Is preferable to:
|
||||||
```
|
```
|
||||||
#define MACRO_ONE 1
|
#define MACRO_ONE 1
|
||||||
#define MACRO_TWO 2
|
#define MACRO_TWO 2
|
||||||
#define MACRO_THREE 4
|
#define MACRO_THREE 4
|
||||||
```
|
```
|
||||||
This make the code more readable and less prone to error
|
While it may initially look intimidating, `(1<<x)` is actually very simple and, as the name implies, shifts the bits of a given binary number over by one digit.
|
||||||
|
```
|
||||||
|
000100 (4, or (1<<2))
|
||||||
|
<<
|
||||||
|
001000 (8, or (1<<3))
|
||||||
|
```
|
||||||
|
Using this system makes the code more readable and less prone to error.
|
||||||
|
|
||||||
### Legacy Code
|
### Legacy Code
|
||||||
SS13 has a lot of legacy code that's never been updated. Here are some examples of common legacy trends which are no longer acceptable:
|
SS13 has a lot of legacy code that's never been updated. Here are some examples of common legacy trends which are no longer acceptable:
|
||||||
* To display messages to all mobs that can view `src`, you should use
|
* To display messages to all mobs that can view `user`, you should use `visible_message()`.
|
||||||
`visible_message()`.
|
|
||||||
* Bad:
|
```DM
|
||||||
```
|
//Bad
|
||||||
for(var/mob/M in viewers(src))
|
for(var/mob/M in viewers(user))
|
||||||
M.show_message("<span class='warning'>Arbitrary text</span>")
|
M.show_message("<span class='warning'>Arbitrary text</span>")
|
||||||
```
|
|
||||||
* Good:
|
//Good
|
||||||
```
|
user.visible_message("<span class='warning'>Arbitrary text</span>")
|
||||||
visible_message("<span class='warning'>Arbitrary text</span>")
|
```
|
||||||
```
|
|
||||||
* You should not use color macros (`\red, \blue, \green, \black`) to color text,
|
* You should not use color macros (`\red, \blue, \green, \black`) to color text,
|
||||||
instead, you should use span classes. `<span class='warning'>red text</span>`,
|
instead, you should use span classes. `<span class='warning'>Red text</span>`, `<span class='notice'>Blue text</span>`.
|
||||||
`<span class='notice'>blue text</span>`.
|
|
||||||
* Bad:
|
|
||||||
```
|
```
|
||||||
to_chat("\red Red Text \black black text")
|
//Bad
|
||||||
```
|
to_chat(user, "\red Red text \black Black text")
|
||||||
* Good:
|
|
||||||
```
|
//Good
|
||||||
to_chat("<span class='warning'>Red Text</span>black text")
|
to_chat(user, "<span class='warning'>Red text</span>Black text")
|
||||||
```
|
```
|
||||||
* To use variables in strings, you should **never** use the `text()` operator, use
|
* To use variables in strings, you should **never** use the `text()` operator, use
|
||||||
embedded expressions directly in the string.
|
embedded expressions directly in the string.
|
||||||
* Bad:
|
|
||||||
```
|
```DM
|
||||||
to_chat(text("[] is leaking []!", src.name, src.liquid_type))
|
//Bad
|
||||||
```
|
to_chat(user, text("[] is leaking []!", name, liquid_type))
|
||||||
* Good:
|
|
||||||
```
|
//Good
|
||||||
to_chat("[src] is leaking [liquid_type]")
|
to_chat(user, "[name] is leaking [liquid_type]!")
|
||||||
```
|
```
|
||||||
* To reference a variable/proc on the src object, you should **not** use
|
* To reference a variable/proc on the src object, you should **not** use
|
||||||
`src.var`/`src.proc()`. The `src.` in these cases is implied, so you should just use
|
`src.var`/`src.proc()`. The `src.` in these cases is implied, so you should just use
|
||||||
`var`/`proc()`.
|
`var`/`proc()`.
|
||||||
* Bad:
|
|
||||||
```
|
|
||||||
var/user = src.interactor
|
|
||||||
src.fillReserves(user)
|
|
||||||
```
|
|
||||||
* Good:
|
|
||||||
```
|
|
||||||
var/user = interactor
|
|
||||||
fillReserves(user)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
```DM
|
||||||
|
//Bad
|
||||||
|
var/user = src.interactor
|
||||||
|
src.fill_reserves(user)
|
||||||
|
|
||||||
|
//Good
|
||||||
|
var/user = interactor
|
||||||
|
fill_reserves(user)
|
||||||
|
```
|
||||||
|
|
||||||
### 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
|
* 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.
|
||||||
|
|
||||||
* Calls to the database must be escaped properly - use proper parameters (values starting with a :). You can then replace these with a list of parameters, and these will be properly escaped during the query, and prevent any SQL injection.
|
* Calls to the database must be escaped properly - use proper parameters (values starting with a :). You can then replace these with a list of parameters, and these will be properly escaped during the query, and prevent any SQL injection.
|
||||||
* Good:
|
|
||||||
```dm
|
|
||||||
var/datum/db_query/query_watch = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey=:target_ckey", list(
|
|
||||||
"target_ckey" = target_ckey
|
|
||||||
)) // Note the use of parameters on the above line and :target_ckey in the query
|
|
||||||
```
|
|
||||||
|
|
||||||
* Bad:
|
```DM
|
||||||
```dm
|
//Bad
|
||||||
var/datum/db_query/query_watch = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey='[target_ckey]'")
|
var/datum/db_query/query_watch = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey='[target_ckey]'")
|
||||||
```
|
|
||||||
|
//Good
|
||||||
|
var/datum/db_query/query_watch = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey=:target_ckey", list(
|
||||||
|
"target_ckey" = target_ckey
|
||||||
|
)) // Note the use of parameters on the above line and :target_ckey in the query.
|
||||||
|
```
|
||||||
|
|
||||||
* All calls to topics must be checked for correctness. Topic href calls can be easily faked by clients, so you should ensure that the call is valid for the state the item is in. Do not rely on the UI code to provide only valid topic calls, because it won't.
|
* All calls to topics must be checked for correctness. Topic href calls can be easily faked by clients, so you should ensure that the call is valid for the state the item is in. Do not rely on the UI code to provide only valid topic calls, because it won't.
|
||||||
|
|
||||||
@@ -467,13 +483,13 @@ SS13 has a lot of legacy code that's never been updated. Here are some examples
|
|||||||
### SQL
|
### SQL
|
||||||
* Do not use the shorthand sql insert format (where no column names are specified) because it unnecessarily breaks all queries on minor column changes and prevents using these tables for tracking outside related info such as in a connected site/forum.
|
* Do not use the shorthand sql insert format (where no column names are specified) because it unnecessarily breaks all queries on minor column changes and prevents using these tables for tracking outside related info such as in a connected site/forum.
|
||||||
|
|
||||||
* Use parameters for queries (Mentioned above in) [###Develop Secure Code](###Develop Secure Code)
|
* Use parameters for queries, as mentioned above in [Develop Secure Code](#develop-secure-code).
|
||||||
|
|
||||||
* Always check your queries for success with if(!query.warn_execute()). By using this standard format, you can ensure the correct log messages are used
|
* Always check your queries for success with `if(!query.warn_execute())`. By using this standard format, you can ensure the correct log messages are used.
|
||||||
|
|
||||||
* Always qdel() your queries after you are done with them, this cleans up the results and helps things run smoother
|
* Always `qdel()` your queries after you are done with them, this cleans up the results and helps things run smoother.
|
||||||
|
|
||||||
* All changes to the database's layout(schema) must be specified in the database changelog in SQL, as well as reflected in the schema files
|
* All changes to the database's layout (schema) must be specified in the database changelog in SQL, as well as reflected in the schema file.
|
||||||
|
|
||||||
* Any time the schema is changed the `SQL_VERSION` defines must be incremented, as well as the example config, with an appropriate conversion kit placed
|
* Any time the schema is changed the `SQL_VERSION` defines must be incremented, as well as the example config, with an appropriate conversion kit placed
|
||||||
in the SQL/updates folder.
|
in the SQL/updates folder.
|
||||||
@@ -536,7 +552,7 @@ in the SQL/updates folder.
|
|||||||
* External areas, or areas where depressurisation is expected and normal, should use airless turf variants to prevent additional atmospherics load.
|
* External areas, or areas where depressurisation is expected and normal, should use airless turf variants to prevent additional atmospherics load.
|
||||||
* Edits in mapping tools should generally be possible to replicate in-game. For this reason, avoid stacking multiple structures on the same tile (i.e. placing a light and an APC on the same wall.)
|
* Edits in mapping tools should generally be possible to replicate in-game. For this reason, avoid stacking multiple structures on the same tile (i.e. placing a light and an APC on the same wall.)
|
||||||
### Other Notes
|
### Other Notes
|
||||||
* Code should be modular where possible; if you are working on a new addition, then strongly consider putting it in its own file unless it makes sense to put it with similar ones (i.e. a new tool would go in the "tools.dm" file)
|
* Code should be modular where possible; if you are working on a new addition, then strongly consider putting it in its own file unless it makes sense to put it with similar ones (i.e. a new tool would go in the `tools.dm` 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.
|
* 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.
|
||||||
|
|
||||||
* You are expected to help maintain the code that you add, meaning that if there is a problem then you are likely to be approached in order to fix any issues, runtimes, or bugs.
|
* You are expected to help maintain the code that you add, meaning that if there is a problem then you are likely to be approached in order to fix any issues, runtimes, or bugs.
|
||||||
@@ -546,38 +562,38 @@ in the SQL/updates folder.
|
|||||||
* All new var/proc names should use the American English spelling of words. This is for consistency with BYOND.
|
* All new var/proc names should use the American English spelling of words. This is for consistency with BYOND.
|
||||||
|
|
||||||
### 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
|
Like all languages, Dream Maker has its quirks, some of them are beneficial to us, like these:
|
||||||
|
|
||||||
#### In-To for-loops
|
#### 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), but
|
`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), but
|
||||||
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. (
|
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
|
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```).
|
some_value-1`).
|
||||||
|
|
||||||
HOWEVER, if either ```some_value``` or ```i``` changes within the body of the for (underneath the ```for(...)``` header) or if you are looping over a list AND
|
HOWEVER, if either `some_value` or `i` changes within the body of the for (underneath the `for(...)` header) or if you are looping over a list AND
|
||||||
changing the length of the list then you can NOT use this type of for-loop!
|
changing the length of the list then you can NOT use this type of for-loop!
|
||||||
|
|
||||||
### for(var/A in list) VS for(var/i in 1 to list.len)
|
### `for(var/A in list)` VS `for(var/i in 1 to list.len)`
|
||||||
The former is faster than the latter, as shown by the following profile results:
|
The former is faster than the latter, as shown by the following profile results:
|
||||||
https://file.house/zy7H.png
|
https://file.house/zy7H.png <br>
|
||||||
Code used for the test in a readable format:
|
Code used for the test in a readable format:
|
||||||
https://pastebin.com/w50uERkG
|
https://pastebin.com/w50uERkG
|
||||||
|
|
||||||
#### Istypeless for loops
|
#### Istypeless for loops
|
||||||
A name for a differing syntax for writing for-each style loops in DM. It's NOT DM's standard syntax, hence why this is considered a quirk. Take a look at this:
|
A name for a differing syntax for writing for-each style loops in DM. It's NOT DM's standard syntax, hence why this is considered a quirk. Take a look at this:
|
||||||
```DM
|
```DM
|
||||||
var/list/bag_of_items = list(sword, apple, coinpouch, sword, sword)
|
var/list/bag_of_items = list(sword1, apple, coinpouch, sword2, sword3)
|
||||||
var/obj/item/sword/best_sword
|
var/obj/item/sword/best_sword
|
||||||
for(var/obj/item/sword/S in bag_of_items)
|
for(var/obj/item/sword/S in bag_of_items)
|
||||||
if(!best_sword || S.damage > best_sword.damage)
|
if(!best_sword || S.damage > best_sword.damage)
|
||||||
best_sword = S
|
best_sword = S
|
||||||
```
|
```
|
||||||
The above is a simple proc for checking all swords in a container and returning the one with the highest damage, and it uses DM's standard syntax for a
|
The above is a simple proc for checking all swords in a container and returning the one with the highest damage, and it uses DM's standard syntax for a
|
||||||
for-loop by specifying a type in the variable of the for's header that DM interprets as a type to filter by. It performs this filter using ```istype()``` (or
|
for-loop by specifying a type in the variable of the for's header that DM interprets as a type to filter by. It performs this filter using `istype()` (or
|
||||||
some internal-magic similar to ```istype()``` - this is BYOND, after all). This is fine in its current state for ```bag_of_items```, but if ```bag_of_items```
|
some internal-magic similar to `istype()` - this is BYOND, after all). This is fine in its current state for `bag_of_items`, but if `bag_of_items`
|
||||||
contained ONLY swords, or only SUBTYPES of swords, then the above is inefficient. For example:
|
contained ONLY swords, or only SUBTYPES of swords, then the above is inefficient. For example:
|
||||||
```DM
|
```DM
|
||||||
var/list/bag_of_swords = list(sword, sword, sword, sword)
|
var/list/bag_of_swords = list(sword1, sword2, sword3, sword4)
|
||||||
var/obj/item/sword/best_sword
|
var/obj/item/sword/best_sword
|
||||||
for(var/obj/item/sword/S in bag_of_swords)
|
for(var/obj/item/sword/S in bag_of_swords)
|
||||||
if(!best_sword || S.damage > best_sword.damage)
|
if(!best_sword || S.damage > best_sword.damage)
|
||||||
@@ -585,10 +601,10 @@ for(var/obj/item/sword/S in bag_of_swords)
|
|||||||
```
|
```
|
||||||
specifies a type for DM to filter by.
|
specifies a type for DM to filter by.
|
||||||
|
|
||||||
With the previous example that's perfectly fine, we only want swords, but here the bag only contains swords? Is DM still going to try to filter because we gave
|
With the previous example that's perfectly fine, we only want swords, but if the bag only contains swords? Is DM still going to try to filter because we gave
|
||||||
it a type to filter by? YES, and here comes the inefficiency. Wherever a list (or other container, such as an atom (in which case you're technically accessing
|
it a type to filter by? YES, and here comes the inefficiency. Wherever a list (or other container, such as an atom (in which case you're technically accessing
|
||||||
their special contents list, but that's irrelevant)) contains datums of the same datatype or subtypes of the datatype you require for your loop's body,
|
their special contents list, but that's irrelevant)) contains datums of the same datatype or subtypes of the datatype you require for your loop's body,
|
||||||
you can circumvent DM's filtering and automatic ```istype()``` checks by writing the loop as such:
|
you can circumvent DM's filtering and automatic `istype()` checks by writing the loop as such:
|
||||||
```DM
|
```DM
|
||||||
var/list/bag_of_swords = list(sword, sword, sword, sword)
|
var/list/bag_of_swords = list(sword, sword, sword, sword)
|
||||||
var/obj/item/sword/best_sword
|
var/obj/item/sword/best_sword
|
||||||
@@ -607,7 +623,7 @@ eg:
|
|||||||
var/mob/living/carbon/human/H = YOU_THE_READER
|
var/mob/living/carbon/human/H = YOU_THE_READER
|
||||||
H.gib()
|
H.gib()
|
||||||
```
|
```
|
||||||
However, DM also has a dot variable, accessed just as `.` on its 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` statement) at the end of a proc, provided the proc does not already manually return (`return count` for example.) Why is this special?
|
However, DM also has a dot *variable*, accessed just as `.` on its 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` statement) at the end of a proc, provided the proc does not already manually return (`return count` for example.) Why is this special?
|
||||||
|
|
||||||
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, although 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 that it's a list.
|
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, although 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 that it's a list.
|
||||||
|
|
||||||
@@ -627,7 +643,7 @@ There is also an undocumented keyword called `static` that has the same behaviou
|
|||||||
|
|
||||||
### Global Vars
|
### Global Vars
|
||||||
|
|
||||||
All new global vars must use the defines in code/\_\_DEFINES/\_globals.dm. Basic usage is as follows:
|
All new global vars must use the defines in [`code/__DEFINES/_globals.dm`](../code/__DEFINES/_globals.dm). Basic usage is as follows:
|
||||||
|
|
||||||
To declare a global var:
|
To declare a global var:
|
||||||
```DM
|
```DM
|
||||||
@@ -648,13 +664,13 @@ responsible for properly tagging new pull requests and issues, moderating commen
|
|||||||
pull requests/issues, and merging/closing pull requests.
|
pull requests/issues, and merging/closing pull requests.
|
||||||
|
|
||||||
### Maintainer List
|
### Maintainer List
|
||||||
* [Fox P McCloud](https://github.com/Fox-McCloud)
|
|
||||||
* [Crazy Lemon](https://github.com/Crazylemon64)
|
|
||||||
* [Ansari](https://github.com/variableundefined)
|
|
||||||
* [AffectedArc07](https://github.com/AffectedArc07)
|
* [AffectedArc07](https://github.com/AffectedArc07)
|
||||||
|
* [Ansari](https://github.com/variableundefined)
|
||||||
|
* [Crazy Lemon](https://github.com/Crazylemon64)
|
||||||
|
* [Fox P McCloud](https://github.com/Fox-McCloud)
|
||||||
|
|
||||||
### Maintainer instructions
|
### Maintainer instructions
|
||||||
* Do not `self-merge`; this refers to the practice of opening a pull request, then
|
* Do not "self-merge"; this refers to the practice of opening a pull request, then
|
||||||
merging it yourself. A different maintainer must review and merge your pull request, no
|
merging it yourself. A different maintainer must review and merge your pull request, no
|
||||||
matter how trivial. This is to ensure quality.
|
matter how trivial. This is to ensure quality.
|
||||||
* A subset of this instruction: Do not push directly to the repository, always make a
|
* A subset of this instruction: Do not push directly to the repository, always make a
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -40,7 +40,6 @@
|
|||||||
#define BELOW_OPEN_DOOR_LAYER 2.6
|
#define BELOW_OPEN_DOOR_LAYER 2.6
|
||||||
#define BLASTDOOR_LAYER 2.65
|
#define BLASTDOOR_LAYER 2.65
|
||||||
#define OPEN_DOOR_LAYER 2.7
|
#define OPEN_DOOR_LAYER 2.7
|
||||||
#define DOOR_HELPER_LAYER 2.71 //keep this above OPEN_DOOR_LAYER
|
|
||||||
#define PROJECTILE_HIT_THRESHHOLD_LAYER 2.75 //projectiles won't hit objects at or below this layer if possible
|
#define PROJECTILE_HIT_THRESHHOLD_LAYER 2.75 //projectiles won't hit objects at or below this layer if possible
|
||||||
#define TABLE_LAYER 2.8
|
#define TABLE_LAYER 2.8
|
||||||
#define BELOW_OBJ_LAYER 2.9
|
#define BELOW_OBJ_LAYER 2.9
|
||||||
@@ -52,6 +51,7 @@
|
|||||||
#define SHUTTER_LAYER 3.12 // HERE BE DRAGONS
|
#define SHUTTER_LAYER 3.12 // HERE BE DRAGONS
|
||||||
#define ABOVE_OBJ_LAYER 3.2
|
#define ABOVE_OBJ_LAYER 3.2
|
||||||
#define ABOVE_WINDOW_LAYER 3.3
|
#define ABOVE_WINDOW_LAYER 3.3
|
||||||
|
#define DOOR_HELPER_LAYER 3.31 // Keep this above doors and windoors
|
||||||
#define SIGN_LAYER 3.4
|
#define SIGN_LAYER 3.4
|
||||||
#define NOT_HIGH_OBJ_LAYER 3.5
|
#define NOT_HIGH_OBJ_LAYER 3.5
|
||||||
#define HIGH_OBJ_LAYER 3.6
|
#define HIGH_OBJ_LAYER 3.6
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ GLOBAL_PROTECT(log_end)
|
|||||||
|
|
||||||
/proc/log_access_in(client/new_client)
|
/proc/log_access_in(client/new_client)
|
||||||
if(GLOB.configuration.logging.access_logging)
|
if(GLOB.configuration.logging.access_logging)
|
||||||
var/message = "[key_name(new_client)] - IP:[new_client.address] - CID:[new_client.computer_id] - BYOND v[new_client.byond_version]"
|
var/message = "[key_name(new_client)] - IP:[new_client.address] - CID:[new_client.computer_id] - BYOND v[new_client.byond_version].[new_client.byond_build]"
|
||||||
rustg_log_write(GLOB.world_game_log, "ACCESS IN: [message][GLOB.log_end]")
|
rustg_log_write(GLOB.world_game_log, "ACCESS IN: [message][GLOB.log_end]")
|
||||||
|
|
||||||
/proc/log_access_out(mob/last_mob)
|
/proc/log_access_out(mob/last_mob)
|
||||||
|
|||||||
@@ -680,6 +680,7 @@ proc/dd_sortedObjectList(list/incoming)
|
|||||||
#define UNSETEMPTY(L) if (L && !L.len) L = null
|
#define UNSETEMPTY(L) if (L && !L.len) L = null
|
||||||
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!L.len) { L = null; } }
|
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!L.len) { L = null; } }
|
||||||
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
|
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
|
||||||
|
#define LAZYADDOR(L, I) if(!L) { L = list(); } L |= I;
|
||||||
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null)
|
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null)
|
||||||
#define LAZYLEN(L) length(L) // Despite how pointless this looks, it's still needed in order to convey that the list is specificially a 'Lazy' list.
|
#define LAZYLEN(L) length(L) // Despite how pointless this looks, it's still needed in order to convey that the list is specificially a 'Lazy' list.
|
||||||
#define LAZYCLEARLIST(L) if(L) L.Cut()
|
#define LAZYCLEARLIST(L) if(L) L.Cut()
|
||||||
|
|||||||
@@ -616,7 +616,7 @@ so as to remain in compliance with the most up-to-date laws."
|
|||||||
if(stone)
|
if(stone)
|
||||||
if(alert(usr, "Do you want to be captured by [stoner]'s soul stone? This will destroy your corpse and make it \
|
if(alert(usr, "Do you want to be captured by [stoner]'s soul stone? This will destroy your corpse and make it \
|
||||||
impossible for you to get back into the game as your regular character.",, "No", "Yes") == "Yes")
|
impossible for you to get back into the game as your regular character.",, "No", "Yes") == "Yes")
|
||||||
stone.opt_in = TRUE
|
stone?.opt_in = TRUE
|
||||||
|
|
||||||
/obj/screen/alert/notify_soulstone/Destroy()
|
/obj/screen/alert/notify_soulstone/Destroy()
|
||||||
stone = null
|
stone = null
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
|
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
|
||||||
if(!tool_attack_chain(user, target) && pre_attackby(target, user, params))
|
if(!tool_attack_chain(user, target) && pre_attack(target, user, params))
|
||||||
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
|
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
|
||||||
var/resolved = target.attackby(src, user, params)
|
var/resolved = target.attackby(src, user, params)
|
||||||
if(!resolved && target && !QDELETED(src))
|
if(!resolved && target && !QDELETED(src))
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
return
|
return
|
||||||
return
|
return
|
||||||
|
|
||||||
/obj/item/proc/pre_attackby(atom/A, mob/living/user, params) //do stuff before attackby!
|
/obj/item/proc/pre_attack(atom/A, mob/living/user, params) //do stuff before attackby!
|
||||||
if(is_hot(src) && A.reagents && !ismob(A))
|
if(is_hot(src) && A.reagents && !ismob(A))
|
||||||
to_chat(user, "<span class='notice'>You heat [A] with [src].</span>")
|
to_chat(user, "<span class='notice'>You heat [A] with [src].</span>")
|
||||||
A.reagents.temperature_reagents(is_hot(src))
|
A.reagents.temperature_reagents(is_hot(src))
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
var/shutdown_shell_command = null
|
var/shutdown_shell_command = null
|
||||||
/// 2FA backend server host
|
/// 2FA backend server host
|
||||||
var/_2fa_auth_host = null
|
var/_2fa_auth_host = null
|
||||||
|
/// List of IP addresses which bypass world topic rate limiting
|
||||||
|
var/list/topic_ip_ratelimit_bypass = list()
|
||||||
|
|
||||||
/datum/configuration_section/system_configuration/load_data(list/data)
|
/datum/configuration_section/system_configuration/load_data(list/data)
|
||||||
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
|
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
|
||||||
@@ -24,3 +26,5 @@
|
|||||||
CONFIG_LOAD_STR(medal_hub_password, data["medal_hub_password"])
|
CONFIG_LOAD_STR(medal_hub_password, data["medal_hub_password"])
|
||||||
CONFIG_LOAD_STR(shutdown_shell_command, data["shutdown_shell_command"])
|
CONFIG_LOAD_STR(shutdown_shell_command, data["shutdown_shell_command"])
|
||||||
CONFIG_LOAD_STR(_2fa_auth_host, data["_2fa_auth_host"])
|
CONFIG_LOAD_STR(_2fa_auth_host, data["_2fa_auth_host"])
|
||||||
|
|
||||||
|
CONFIG_LOAD_LIST(topic_ip_ratelimit_bypass, data["topic_ip_ratelimit_bypass"])
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ SUBSYSTEM_DEF(mobs)
|
|||||||
var/static/list/clients_by_zlevel[][]
|
var/static/list/clients_by_zlevel[][]
|
||||||
var/static/list/dead_players_by_zlevel[][] = list(list()) // Needs to support zlevel 1 here, MaxZChanged only happens when CC is created and new_players can login before that.
|
var/static/list/dead_players_by_zlevel[][] = list(list()) // Needs to support zlevel 1 here, MaxZChanged only happens when CC is created and new_players can login before that.
|
||||||
var/static/list/cubemonkeys = list()
|
var/static/list/cubemonkeys = list()
|
||||||
|
/// The amount of giant spiders that exist in the world. Used for mob capping.
|
||||||
|
var/giant_spiders = 0
|
||||||
|
|
||||||
/datum/controller/subsystem/mobs/stat_entry()
|
/datum/controller/subsystem/mobs/stat_entry()
|
||||||
..("P:[GLOB.mob_living_list.len]")
|
..("P:[GLOB.mob_living_list.len]")
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ SUBSYSTEM_DEF(shuttle)
|
|||||||
var/list/shoppinglist = list()
|
var/list/shoppinglist = list()
|
||||||
var/list/requestlist = list()
|
var/list/requestlist = list()
|
||||||
var/list/supply_packs = list()
|
var/list/supply_packs = list()
|
||||||
var/datum/round_event/shuttle_loan/shuttle_loan
|
|
||||||
var/sold_atoms = ""
|
var/sold_atoms = ""
|
||||||
var/list/hidden_shuttle_turfs = list() //all turfs hidden from navigation computers associated with a list containing the image hiding them and the type of the turf they are pretending to be
|
var/list/hidden_shuttle_turfs = list() //all turfs hidden from navigation computers associated with a list containing the image hiding them and the type of the turf they are pretending to be
|
||||||
var/list/hidden_shuttle_turf_images = list() //only the images from the above list
|
var/list/hidden_shuttle_turf_images = list() //only the images from the above list
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ SUBSYSTEM_DEF(vote)
|
|||||||
CHECK_TICK
|
CHECK_TICK
|
||||||
|
|
||||||
/datum/controller/subsystem/vote/proc/autotransfer()
|
/datum/controller/subsystem/vote/proc/autotransfer()
|
||||||
initiate_vote("crew_transfer","the server")
|
initiate_vote("crew transfer", "the server")
|
||||||
|
|
||||||
/datum/controller/subsystem/vote/proc/reset()
|
/datum/controller/subsystem/vote/proc/reset()
|
||||||
initiator = null
|
initiator = null
|
||||||
@@ -95,7 +95,7 @@ SUBSYSTEM_DEF(vote)
|
|||||||
choices[GLOB.master_mode] += non_voters
|
choices[GLOB.master_mode] += non_voters
|
||||||
if(choices[GLOB.master_mode] >= greatest_votes)
|
if(choices[GLOB.master_mode] >= greatest_votes)
|
||||||
greatest_votes = choices[GLOB.master_mode]
|
greatest_votes = choices[GLOB.master_mode]
|
||||||
else if(mode == "crew_transfer")
|
else if(mode == "crew transfer")
|
||||||
var/factor = 0.5
|
var/factor = 0.5
|
||||||
switch(world.time / (10 * 60)) // minutes
|
switch(world.time / (10 * 60)) // minutes
|
||||||
if(0 to 60)
|
if(0 to 60)
|
||||||
@@ -174,9 +174,9 @@ SUBSYSTEM_DEF(vote)
|
|||||||
if(!SSticker.ticker_going)
|
if(!SSticker.ticker_going)
|
||||||
SSticker.ticker_going = TRUE
|
SSticker.ticker_going = TRUE
|
||||||
to_chat(world, "<font color='red'><b>The round will start soon.</b></font>")
|
to_chat(world, "<font color='red'><b>The round will start soon.</b></font>")
|
||||||
if("crew_transfer")
|
if("crew transfer")
|
||||||
if(. == "Initiate Crew Transfer")
|
if(. == "Initiate Crew Transfer")
|
||||||
init_shift_change(null, 1)
|
init_shift_change(null, TRUE)
|
||||||
if("map")
|
if("map")
|
||||||
// Find target map.
|
// Find target map.
|
||||||
var/datum/map/top_voted_map
|
var/datum/map/top_voted_map
|
||||||
@@ -222,7 +222,7 @@ SUBSYSTEM_DEF(vote)
|
|||||||
if(SSticker.current_state >= 2)
|
if(SSticker.current_state >= 2)
|
||||||
return 0
|
return 0
|
||||||
choices.Add(GLOB.configuration.gamemode.votable_modes)
|
choices.Add(GLOB.configuration.gamemode.votable_modes)
|
||||||
if("crew_transfer")
|
if("crew transfer")
|
||||||
if(check_rights(R_ADMIN|R_MOD))
|
if(check_rights(R_ADMIN|R_MOD))
|
||||||
if(SSticker.current_state <= 2)
|
if(SSticker.current_state <= 2)
|
||||||
return 0
|
return 0
|
||||||
@@ -266,16 +266,16 @@ SUBSYSTEM_DEF(vote)
|
|||||||
<a href='?src=[UID()];vote=open'>Click here or type vote to place your vote.</a>
|
<a href='?src=[UID()];vote=open'>Click here or type vote to place your vote.</a>
|
||||||
You have [GLOB.configuration.vote.vote_time / 10] seconds to vote.</font>"})
|
You have [GLOB.configuration.vote.vote_time / 10] seconds to vote.</font>"})
|
||||||
switch(vote_type)
|
switch(vote_type)
|
||||||
if("crew_transfer", "gamemode", "custom", "map")
|
if("crew transfer", "gamemode", "custom", "map")
|
||||||
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
|
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
|
||||||
if(mode == "gamemode" && SSticker.ticker_going)
|
if(mode == "gamemode" && SSticker.ticker_going)
|
||||||
SSticker.ticker_going = FALSE
|
SSticker.ticker_going = FALSE
|
||||||
to_chat(world, "<font color='red'><b>Round start has been delayed.</b></font>")
|
to_chat(world, "<font color='red'><b>Round start has been delayed.</b></font>")
|
||||||
if(mode == "crew_transfer" && GLOB.ooc_enabled)
|
if(mode == "crew transfer" && GLOB.ooc_enabled)
|
||||||
auto_muted = TRUE
|
auto_muted = TRUE
|
||||||
GLOB.ooc_enabled = FALSE
|
GLOB.ooc_enabled = FALSE
|
||||||
to_chat(world, "<b>The OOC channel has been automatically disabled due to a crew transfer vote.</b>")
|
to_chat(world, "<b>The OOC channel has been automatically disabled due to a crew transfer vote.</b>")
|
||||||
log_admin("OOC was toggled automatically due to crew_transfer vote.")
|
log_admin("OOC was toggled automatically due to crew transfer vote.")
|
||||||
message_admins("OOC has been toggled off automatically.")
|
message_admins("OOC has been toggled off automatically.")
|
||||||
if(mode == "gamemode" && GLOB.ooc_enabled)
|
if(mode == "gamemode" && GLOB.ooc_enabled)
|
||||||
auto_muted = TRUE
|
auto_muted = TRUE
|
||||||
@@ -314,37 +314,41 @@ SUBSYSTEM_DEF(vote)
|
|||||||
dat += "(<a href='?src=[UID()];vote=cancel'>Cancel Vote</a>) "
|
dat += "(<a href='?src=[UID()];vote=cancel'>Cancel Vote</a>) "
|
||||||
else
|
else
|
||||||
dat += "<div id='vote_div'><h2>Start a vote:</h2><hr><ul><li>"
|
dat += "<div id='vote_div'><h2>Start a vote:</h2><hr><ul><li>"
|
||||||
//restart
|
// Crew transfer
|
||||||
if(admin || GLOB.configuration.vote.allow_restart_votes)
|
|
||||||
dat += "<a href='?src=[UID()];vote=restart'>Restart</a>"
|
|
||||||
else
|
|
||||||
dat += "<font color='grey'>Restart (Disallowed)</font>"
|
|
||||||
dat += "</li><li>"
|
|
||||||
if(admin || GLOB.configuration.vote.allow_restart_votes)
|
if(admin || GLOB.configuration.vote.allow_restart_votes)
|
||||||
dat += "<a href='?src=[UID()];vote=crew_transfer'>Crew Transfer</a>"
|
dat += "<a href='?src=[UID()];vote=crew_transfer'>Crew Transfer</a>"
|
||||||
else
|
else
|
||||||
dat += "<font color='grey'>Crew Transfer (Disallowed)</font>"
|
dat += "<font color='grey'>Crew Transfer (Disallowed)</font>"
|
||||||
|
dat += "</li><li>"
|
||||||
|
|
||||||
|
// Restart
|
||||||
|
if(admin || GLOB.configuration.vote.allow_restart_votes)
|
||||||
|
dat += "<a href='?src=[UID()];vote=restart'>Restart</a>"
|
||||||
|
else
|
||||||
|
dat += "<font color='grey'>Restart (Disallowed)</font>"
|
||||||
if(admin)
|
if(admin)
|
||||||
dat += "\t(<a href='?src=[UID()];vote=toggle_restart'>[GLOB.configuration.vote.allow_restart_votes ? "Allowed" : "Disallowed"]</a>)"
|
dat += "\t(<a href='?src=[UID()];vote=toggle_restart'>[GLOB.configuration.vote.allow_restart_votes ? "Allowed" : "Disallowed"]</a>)"
|
||||||
dat += "</li><li>"
|
dat += "</li><li>"
|
||||||
//gamemode
|
|
||||||
|
// Gamemode
|
||||||
if(admin || GLOB.configuration.vote.allow_mode_votes)
|
if(admin || GLOB.configuration.vote.allow_mode_votes)
|
||||||
dat += "<a href='?src=[UID()];vote=gamemode'>GameMode</a>"
|
dat += "<a href='?src=[UID()];vote=gamemode'>Gamemode</a>"
|
||||||
else
|
else
|
||||||
dat += "<font color='grey'>GameMode (Disallowed)</font>"
|
dat += "<font color='grey'>Gamemode (Disallowed)</font>"
|
||||||
if(admin)
|
if(admin)
|
||||||
dat += "\t(<a href='?src=[UID()];vote=toggle_gamemode'>[GLOB.configuration.vote.allow_mode_votes ? "Allowed" : "Disallowed"]</a>)"
|
dat += "\t(<a href='?src=[UID()];vote=toggle_gamemode'>[GLOB.configuration.vote.allow_mode_votes ? "Allowed" : "Disallowed"]</a>)"
|
||||||
|
|
||||||
dat += "</li><li>"
|
dat += "</li><li>"
|
||||||
|
|
||||||
|
// Map
|
||||||
if(admin)
|
if(admin)
|
||||||
dat += "<a href='?src=[UID()];vote=map'>Map</a>"
|
dat += "<a href='?src=[UID()];vote=map'>Map</a>"
|
||||||
else
|
else
|
||||||
dat += "<font color='grey'>Map (Disallowed)</font>"
|
dat += "<font color='grey'>Map (Disallowed)</font>"
|
||||||
|
dat += "</li><li>"
|
||||||
|
|
||||||
dat += "</li>"
|
// Custom
|
||||||
//custom
|
|
||||||
if(admin)
|
if(admin)
|
||||||
dat += "<li><a href='?src=[UID()];vote=custom'>Custom</a></li>"
|
dat += "<a href='?src=[UID()];vote=custom'>Custom</a></li>"
|
||||||
dat += "</ul></div><hr>"
|
dat += "</ul></div><hr>"
|
||||||
var/datum/browser/popup = new(C.mob, "vote", "Voting Panel", nref=src)
|
var/datum/browser/popup = new(C.mob, "vote", "Voting Panel", nref=src)
|
||||||
popup.set_content(dat)
|
popup.set_content(dat)
|
||||||
@@ -387,14 +391,16 @@ SUBSYSTEM_DEF(vote)
|
|||||||
var/votedesc = capitalize(mode)
|
var/votedesc = capitalize(mode)
|
||||||
if(mode == "custom")
|
if(mode == "custom")
|
||||||
votedesc += " ([question])"
|
votedesc += " ([question])"
|
||||||
log_and_message_admins("cancelled the running [votedesc] vote.")
|
log_and_message_admins("cancelled the running '[votedesc]' vote.")
|
||||||
reset()
|
reset()
|
||||||
if("toggle_restart")
|
if("toggle_restart")
|
||||||
if(admin)
|
if(admin)
|
||||||
GLOB.configuration.vote.allow_restart_votes = !GLOB.configuration.vote.allow_restart_votes
|
GLOB.configuration.vote.allow_restart_votes = !GLOB.configuration.vote.allow_restart_votes
|
||||||
|
log_and_message_admins("has [GLOB.configuration.vote.allow_restart_votes ? "enabled" : "disabled"] public restart voting.")
|
||||||
if("toggle_gamemode")
|
if("toggle_gamemode")
|
||||||
if(admin)
|
if(admin)
|
||||||
GLOB.configuration.vote.allow_mode_votes = !GLOB.configuration.vote.allow_mode_votes
|
GLOB.configuration.vote.allow_mode_votes = !GLOB.configuration.vote.allow_mode_votes
|
||||||
|
log_and_message_admins("has [GLOB.configuration.vote.allow_mode_votes ? "enabled" : "disabled"] public gamemode voting.")
|
||||||
if("restart")
|
if("restart")
|
||||||
if(GLOB.configuration.vote.allow_restart_votes || admin)
|
if(GLOB.configuration.vote.allow_restart_votes || admin)
|
||||||
initiate_vote("restart",usr.key)
|
initiate_vote("restart",usr.key)
|
||||||
@@ -406,7 +412,7 @@ SUBSYSTEM_DEF(vote)
|
|||||||
initiate_vote("map", usr.key)
|
initiate_vote("map", usr.key)
|
||||||
if("crew_transfer")
|
if("crew_transfer")
|
||||||
if(GLOB.configuration.vote.allow_restart_votes || admin)
|
if(GLOB.configuration.vote.allow_restart_votes || admin)
|
||||||
initiate_vote("crew_transfer",usr.key)
|
initiate_vote("crew transfer", usr.key)
|
||||||
if("custom")
|
if("custom")
|
||||||
if(admin)
|
if(admin)
|
||||||
initiate_vote("custom",usr.key)
|
initiate_vote("custom",usr.key)
|
||||||
|
|||||||
@@ -647,20 +647,20 @@
|
|||||||
name = "Solar Federation Marine"
|
name = "Solar Federation Marine"
|
||||||
uniform = /obj/item/clothing/under/solgov
|
uniform = /obj/item/clothing/under/solgov
|
||||||
suit = /obj/item/clothing/suit/armor/bulletproof
|
suit = /obj/item/clothing/suit/armor/bulletproof
|
||||||
back = /obj/item/storage/backpack/security
|
back = /obj/item/storage/backpack/ert/solgov
|
||||||
belt = /obj/item/storage/belt/military/assault/marines/full
|
belt = /obj/item/storage/belt/military/assault/marines/full
|
||||||
head = /obj/item/clothing/head/soft/solgov/marines
|
head = /obj/item/clothing/head/soft/solgov/marines
|
||||||
glasses = /obj/item/clothing/glasses/night
|
glasses = /obj/item/clothing/glasses/night
|
||||||
gloves = /obj/item/clothing/gloves/combat
|
gloves = /obj/item/clothing/gloves/combat
|
||||||
shoes = /obj/item/clothing/shoes/combat
|
shoes = /obj/item/clothing/shoes/combat
|
||||||
l_ear = /obj/item/radio/headset/ert
|
l_ear = /obj/item/radio/headset/ert/alt/solgov
|
||||||
id = /obj/item/card/id
|
id = /obj/item/card/id
|
||||||
l_hand = /obj/item/gun/projectile/automatic/shotgun/bulldog
|
l_hand = /obj/item/gun/projectile/automatic/shotgun/bulldog
|
||||||
suit_store = /obj/item/gun/projectile/automatic/pistol/m1911
|
suit_store = /obj/item/gun/projectile/automatic/pistol/m1911
|
||||||
r_pocket = /obj/item/flashlight/seclite
|
r_pocket = /obj/item/flashlight/seclite
|
||||||
pda = /obj/item/pda
|
pda = /obj/item/pda
|
||||||
|
box = /obj/item/storage/box/responseteam
|
||||||
backpack_contents = list(
|
backpack_contents = list(
|
||||||
/obj/item/storage/box/responseteam = 1,
|
|
||||||
/obj/item/clothing/shoes/magboots = 1,
|
/obj/item/clothing/shoes/magboots = 1,
|
||||||
/obj/item/whetstone = 1,
|
/obj/item/whetstone = 1,
|
||||||
/obj/item/clothing/mask/gas/explorer/marines = 1,
|
/obj/item/clothing/mask/gas/explorer/marines = 1,
|
||||||
@@ -702,13 +702,12 @@
|
|||||||
head = /obj/item/clothing/head/beret/solgov/command
|
head = /obj/item/clothing/head/beret/solgov/command
|
||||||
glasses = /obj/item/clothing/glasses/night
|
glasses = /obj/item/clothing/glasses/night
|
||||||
back = /obj/item/storage/backpack/satchel
|
back = /obj/item/storage/backpack/satchel
|
||||||
l_ear = /obj/item/radio/headset/ert/alt/commander
|
l_ear = /obj/item/radio/headset/ert/alt/commander/solgov
|
||||||
l_hand = null
|
l_hand = null
|
||||||
belt = /obj/item/melee/baton/loaded
|
belt = /obj/item/melee/baton/loaded
|
||||||
suit_store = /obj/item/gun/projectile/automatic/pistol/deagle
|
suit_store = /obj/item/gun/projectile/automatic/pistol/deagle
|
||||||
l_pocket = /obj/item/pinpointer/advpinpointer
|
l_pocket = /obj/item/pinpointer/advpinpointer
|
||||||
backpack_contents = list(
|
backpack_contents = list(
|
||||||
/obj/item/storage/box/responseteam = 1,
|
|
||||||
/obj/item/storage/box/handcuffs = 1,
|
/obj/item/storage/box/handcuffs = 1,
|
||||||
/obj/item/clothing/shoes/magboots/advance = 1,
|
/obj/item/clothing/shoes/magboots/advance = 1,
|
||||||
/obj/item/reagent_containers/hypospray/autoinjector/survival = 1,
|
/obj/item/reagent_containers/hypospray/autoinjector/survival = 1,
|
||||||
@@ -720,14 +719,14 @@
|
|||||||
/datum/outfit/admin/solgov/elite
|
/datum/outfit/admin/solgov/elite
|
||||||
name = "Solar Federation Specops Marine"
|
name = "Solar Federation Specops Marine"
|
||||||
uniform = /obj/item/clothing/under/solgov/elite
|
uniform = /obj/item/clothing/under/solgov/elite
|
||||||
head = /obj/item/clothing/head/soft/solgov/marines/elite
|
suit = /obj/item/clothing/suit/space/hardsuit/ert/solgov
|
||||||
|
head = null
|
||||||
|
mask = /obj/item/clothing/mask/gas/explorer/marines
|
||||||
belt = /obj/item/storage/belt/military/assault/marines/elite/full
|
belt = /obj/item/storage/belt/military/assault/marines/elite/full
|
||||||
l_hand = /obj/item/gun/projectile/automatic/ar
|
l_hand = /obj/item/gun/projectile/automatic/ar
|
||||||
backpack_contents = list(
|
backpack_contents = list(
|
||||||
/obj/item/storage/box/responseteam = 1,
|
|
||||||
/obj/item/clothing/shoes/magboots/advance = 1,
|
/obj/item/clothing/shoes/magboots/advance = 1,
|
||||||
/obj/item/whetstone = 1,
|
/obj/item/whetstone = 1,
|
||||||
/obj/item/clothing/mask/gas/explorer/marines = 1,
|
|
||||||
/obj/item/reagent_containers/hypospray/autoinjector/survival = 1
|
/obj/item/reagent_containers/hypospray/autoinjector/survival = 1
|
||||||
)
|
)
|
||||||
cybernetic_implants = list(
|
cybernetic_implants = list(
|
||||||
@@ -737,22 +736,22 @@
|
|||||||
/obj/item/organ/internal/cyberimp/arm/flash,
|
/obj/item/organ/internal/cyberimp/arm/flash,
|
||||||
/obj/item/organ/internal/eyes/cybernetic/shield
|
/obj/item/organ/internal/eyes/cybernetic/shield
|
||||||
)
|
)
|
||||||
|
|
||||||
/datum/outfit/admin/solgov/elite/lieutenant
|
/datum/outfit/admin/solgov/elite/lieutenant
|
||||||
name = "Solar Federation Specops Lieutenant"
|
name = "Solar Federation Specops Lieutenant"
|
||||||
uniform = /obj/item/clothing/under/solgov/command/elite
|
uniform = /obj/item/clothing/under/solgov/command/elite
|
||||||
head = /obj/item/clothing/head/beret/solgov/command/elite
|
suit = /obj/item/clothing/suit/space/hardsuit/ert/solgov/command
|
||||||
|
head = null
|
||||||
|
mask = /obj/item/clothing/mask/gas/explorer/marines
|
||||||
glasses = /obj/item/clothing/glasses/night
|
glasses = /obj/item/clothing/glasses/night
|
||||||
back = /obj/item/storage/backpack/satchel
|
|
||||||
belt = /obj/item/melee/baton/loaded
|
belt = /obj/item/melee/baton/loaded
|
||||||
l_hand = null
|
l_hand = null
|
||||||
suit_store = /obj/item/gun/projectile/automatic/pistol/deagle
|
suit_store = /obj/item/gun/projectile/automatic/pistol/deagle
|
||||||
l_pocket = /obj/item/pinpointer/advpinpointer
|
l_pocket = /obj/item/pinpointer/advpinpointer
|
||||||
l_ear = /obj/item/radio/headset/ert/alt/commander
|
l_ear = /obj/item/radio/headset/ert/alt/commander/solgov
|
||||||
backpack_contents = list(
|
backpack_contents = list(
|
||||||
/obj/item/storage/box/responseteam = 1,
|
|
||||||
/obj/item/storage/box/handcuffs = 1,
|
/obj/item/storage/box/handcuffs = 1,
|
||||||
/obj/item/clothing/shoes/magboots/advance = 1,
|
/obj/item/clothing/shoes/magboots/advance = 1,
|
||||||
/obj/item/clothing/mask/gas/explorer/marines = 1,
|
|
||||||
/obj/item/reagent_containers/hypospray/autoinjector/survival = 1,
|
/obj/item/reagent_containers/hypospray/autoinjector/survival = 1,
|
||||||
/obj/item/ammo_box/magazine/m50 = 3
|
/obj/item/ammo_box/magazine/m50 = 3
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -560,7 +560,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
|||||||
to_chat(user, "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>")
|
to_chat(user, "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if(is_admin_level(user.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
|
var/turf/T = get_turf(user)
|
||||||
|
if(is_admin_level(T.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if(!holy_area_cancast && user.holy_check())
|
if(!holy_area_cancast && user.holy_check())
|
||||||
|
|||||||
@@ -273,6 +273,12 @@
|
|||||||
/atom/proc/HasProximity(atom/movable/AM)
|
/atom/proc/HasProximity(atom/movable/AM)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proc which will make the atom act accordingly to an EMP.
|
||||||
|
* This proc can sleep depending on the implementation. So assume it sleeps!
|
||||||
|
*
|
||||||
|
* severity - The severity of the EMP. Either EMP_HEAVY or EMP_LIGHT
|
||||||
|
*/
|
||||||
/atom/proc/emp_act(severity)
|
/atom/proc/emp_act(severity)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -822,9 +822,10 @@
|
|||||||
else
|
else
|
||||||
M.change_gender(FEMALE)
|
M.change_gender(FEMALE)
|
||||||
|
|
||||||
var/new_eyes = input("Please select eye color.", "Character Generation", eyes_organ.eye_color) as null|color
|
if(eyes_organ)
|
||||||
if(new_eyes)
|
var/new_eyes = input("Please select eye color.", "Character Generation", eyes_organ.eye_color) as null|color
|
||||||
M.change_eye_color(new_eyes)
|
if(new_eyes)
|
||||||
|
M.change_eye_color(new_eyes)
|
||||||
|
|
||||||
//Alt heads.
|
//Alt heads.
|
||||||
if(head_organ.dna.species.bodyflags & HAS_ALT_HEADS)
|
if(head_organ.dna.species.bodyflags & HAS_ALT_HEADS)
|
||||||
|
|||||||
@@ -238,7 +238,7 @@
|
|||||||
blobber.LoseTarget()
|
blobber.LoseTarget()
|
||||||
spawn()
|
spawn()
|
||||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a blobbernaut?", ROLE_BLOB, TRUE, 10 SECONDS, source = blobber)
|
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a blobbernaut?", ROLE_BLOB, TRUE, 10 SECONDS, source = blobber)
|
||||||
if(candidates.len)
|
if(length(candidates) && !QDELETED(blobber))
|
||||||
var/mob/C = pick(candidates)
|
var/mob/C = pick(candidates)
|
||||||
if(C)
|
if(C)
|
||||||
blobber.key = C.key
|
blobber.key = C.key
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","E
|
|||||||
name = "changeling"
|
name = "changeling"
|
||||||
config_tag = "changeling"
|
config_tag = "changeling"
|
||||||
restricted_jobs = list("AI", "Cyborg")
|
restricted_jobs = list("AI", "Cyborg")
|
||||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer")
|
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer", "Solar Federation Brigadier General")
|
||||||
protected_species = list("Machine")
|
protected_species = list("Machine")
|
||||||
required_players = 15
|
required_players = 15
|
||||||
required_enemies = 1
|
required_enemies = 1
|
||||||
|
|||||||
@@ -185,7 +185,7 @@
|
|||||||
owner.visible_message("<span class='warning'>[owner]'s body flashes a bright blue!</span>", \
|
owner.visible_message("<span class='warning'>[owner]'s body flashes a bright blue!</span>", \
|
||||||
"<span class='cultitalic'>You speak the cursed words, channeling an electromagnetic pulse from your body.</span>")
|
"<span class='cultitalic'>You speak the cursed words, channeling an electromagnetic pulse from your body.</span>")
|
||||||
owner.emp_act(2)
|
owner.emp_act(2)
|
||||||
empulse(owner, 2, 5, cause = "cult")
|
INVOKE_ASYNC(GLOBAL_PROC, /proc/empulse, owner, 2, 5, TRUE, "cult")
|
||||||
owner.whisper(invocation)
|
owner.whisper(invocation)
|
||||||
charges--
|
charges--
|
||||||
if(charges <= 0)
|
if(charges <= 0)
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ GLOBAL_LIST_EMPTY(all_cults)
|
|||||||
/datum/game_mode/cult
|
/datum/game_mode/cult
|
||||||
name = "cult"
|
name = "cult"
|
||||||
config_tag = "cult"
|
config_tag = "cult"
|
||||||
restricted_jobs = list("Chaplain", "AI", "Cyborg", "Internal Affairs Agent", "Security Officer", "Warden", "Detective", "Security Pod Pilot", "Head of Security", "Captain", "Head of Personnel", "Blueshield", "Nanotrasen Representative", "Magistrate", "Brig Physician", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer")
|
restricted_jobs = list("Chaplain", "AI", "Cyborg", "Internal Affairs Agent", "Security Officer", "Warden", "Detective", "Security Pod Pilot", "Head of Security", "Captain", "Head of Personnel", "Blueshield", "Nanotrasen Representative", "Magistrate", "Brig Physician", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer", "Solar Federation Brigadier General")
|
||||||
protected_jobs = list()
|
protected_jobs = list()
|
||||||
required_players = 30
|
required_players = 30
|
||||||
required_enemies = 3
|
required_enemies = 3
|
||||||
|
|||||||
@@ -607,7 +607,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
|||||||
set waitfor = FALSE
|
set waitfor = FALSE
|
||||||
to_chat(user, "<span class='cult'>[mob_to_revive] was revived, but their mind is lost! Seeking a lost soul to replace it.</span>")
|
to_chat(user, "<span class='cult'>[mob_to_revive] was revived, but their mind is lost! Seeking a lost soul to replace it.</span>")
|
||||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Would you like to play as a revived Cultist?", ROLE_CULTIST, TRUE, poll_time = 20 SECONDS, source = /obj/item/melee/cultblade/dagger)
|
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Would you like to play as a revived Cultist?", ROLE_CULTIST, TRUE, poll_time = 20 SECONDS, source = /obj/item/melee/cultblade/dagger)
|
||||||
if(length(candidates))
|
if(length(candidates) && !QDELETED(mob_to_revive))
|
||||||
var/mob/dead/observer/C = pick(candidates)
|
var/mob/dead/observer/C = pick(candidates)
|
||||||
to_chat(mob_to_revive.mind, "<span class='biggerdanger'>Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form.</span>")
|
to_chat(mob_to_revive.mind, "<span class='biggerdanger'>Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form.</span>")
|
||||||
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(mob_to_revive)]) to replace an AFK player.")
|
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(mob_to_revive)]) to replace an AFK player.")
|
||||||
|
|||||||
@@ -90,6 +90,8 @@
|
|||||||
if(!length(candidates))
|
if(!length(candidates))
|
||||||
to_chat(owner, "<span class='danger'>There were no ghosts willing to take control of your guardian. You can try again in 5 minutes.</span>")
|
to_chat(owner, "<span class='danger'>There were no ghosts willing to take control of your guardian. You can try again in 5 minutes.</span>")
|
||||||
return
|
return
|
||||||
|
if(QDELETED(guardian)) // Just in case
|
||||||
|
return
|
||||||
|
|
||||||
var/mob/dead/observer/new_stand = pick(candidates)
|
var/mob/dead/observer/new_stand = pick(candidates)
|
||||||
to_chat(guardian, "<span class='danger'>Your user reset you, and your body was taken over by a ghost. Looks like they weren't happy with your performance.</span>")
|
to_chat(guardian, "<span class='danger'>Your user reset you, and your body was taken over by a ghost. Looks like they weren't happy with your performance.</span>")
|
||||||
|
|||||||
@@ -168,6 +168,8 @@
|
|||||||
visible_message("<span class='warning'>[src] disappears in a flash of red light!</span>")
|
visible_message("<span class='warning'>[src] disappears in a flash of red light!</span>")
|
||||||
qdel(src)
|
qdel(src)
|
||||||
return
|
return
|
||||||
|
if(QDELETED(src)) // Just in case
|
||||||
|
return
|
||||||
var/mob/M = pick(demon_candidates)
|
var/mob/M = pick(demon_candidates)
|
||||||
var/mob/living/simple_animal/slaughter/cult/S = src
|
var/mob/living/simple_animal/slaughter/cult/S = src
|
||||||
if(!M || !M.client)
|
if(!M || !M.client)
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
#define NUKE_SEALANT_OPEN 3
|
#define NUKE_SEALANT_OPEN 3
|
||||||
#define NUKE_UNWRENCHED 4
|
#define NUKE_UNWRENCHED 4
|
||||||
#define NUKE_MOBILE 5
|
#define NUKE_MOBILE 5
|
||||||
|
#define NUKE_CORE_EVERYTHING_FINE 6
|
||||||
|
#define NUKE_CORE_PANEL_EXPOSED 7
|
||||||
|
#define NUKE_CORE_PANEL_UNWELDED 8
|
||||||
|
#define NUKE_CORE_FULLY_EXPOSED 9
|
||||||
|
|
||||||
GLOBAL_VAR(bomb_set)
|
GLOBAL_VAR(bomb_set)
|
||||||
|
|
||||||
@@ -25,12 +29,17 @@ GLOBAL_VAR(bomb_set)
|
|||||||
var/yes_code = FALSE
|
var/yes_code = FALSE
|
||||||
var/safety = TRUE
|
var/safety = TRUE
|
||||||
var/obj/item/disk/nuclear/auth = null
|
var/obj/item/disk/nuclear/auth = null
|
||||||
var/removal_stage = NUKE_INTACT
|
var/obj/item/nuke_core/plutonium/core = null
|
||||||
var/lastentered
|
var/lastentered
|
||||||
var/is_syndicate = FALSE
|
var/is_syndicate = FALSE
|
||||||
use_power = NO_POWER_USE
|
use_power = NO_POWER_USE
|
||||||
var/previous_level = ""
|
var/previous_level = ""
|
||||||
var/datum/wires/nuclearbomb/wires = null
|
var/datum/wires/nuclearbomb/wires = null
|
||||||
|
var/removal_stage = NUKE_INTACT
|
||||||
|
///The same state removal stage is, until someone opens the panel of the nuke. This way we can have someone open the front of the nuke, while keeping track of where in the world we are on the anchoring bolts.
|
||||||
|
var/anchor_stage = NUKE_INTACT
|
||||||
|
///This is so that we can check if the internal components are sealed up properly when the outer hatch is closed.
|
||||||
|
var/core_stage = NUKE_CORE_EVERYTHING_FINE
|
||||||
|
|
||||||
/obj/machinery/nuclearbomb/syndicate
|
/obj/machinery/nuclearbomb/syndicate
|
||||||
is_syndicate = TRUE
|
is_syndicate = TRUE
|
||||||
@@ -39,16 +48,19 @@ GLOBAL_VAR(bomb_set)
|
|||||||
extended = FALSE
|
extended = FALSE
|
||||||
anchored = FALSE
|
anchored = FALSE
|
||||||
|
|
||||||
/obj/machinery/nuclearbomb/New()
|
/obj/machinery/nuclearbomb/Initialize()
|
||||||
..()
|
. = ..()
|
||||||
r_code = rand(10000, 99999.0) // Creates a random code upon object spawn.
|
r_code = rand(10000, 99999) // Creates a random code upon object spawn.
|
||||||
wires = new/datum/wires/nuclearbomb(src)
|
wires = new/datum/wires/nuclearbomb(src)
|
||||||
previous_level = get_security_level()
|
previous_level = get_security_level()
|
||||||
GLOB.poi_list |= src
|
GLOB.poi_list |= src
|
||||||
|
core = new /obj/item/nuke_core/plutonium(src)
|
||||||
|
STOP_PROCESSING(SSobj, core) //Let us not irradiate the vault by default.
|
||||||
|
|
||||||
/obj/machinery/nuclearbomb/Destroy()
|
/obj/machinery/nuclearbomb/Destroy()
|
||||||
SStgui.close_uis(wires)
|
SStgui.close_uis(wires)
|
||||||
QDEL_NULL(wires)
|
QDEL_NULL(wires)
|
||||||
|
QDEL_NULL(core)
|
||||||
GLOB.poi_list.Remove(src)
|
GLOB.poi_list.Remove(src)
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
@@ -73,16 +85,41 @@ GLOBAL_VAR(bomb_set)
|
|||||||
else
|
else
|
||||||
to_chat(user, "<span class='notice'>You need to deploy [src] first.</span>")
|
to_chat(user, "<span class='notice'>You need to deploy [src] first.</span>")
|
||||||
return
|
return
|
||||||
|
if(istype(O, /obj/item/stack/sheet/mineral/titanium) && removal_stage == NUKE_CORE_FULLY_EXPOSED)
|
||||||
|
if(do_after(user, 2 SECONDS, target = src))
|
||||||
|
var/obj/item/stack/S = O
|
||||||
|
if(!loc || !S || S.get_amount() < 5)
|
||||||
|
return
|
||||||
|
S.use(5)
|
||||||
|
user.visible_message("<span class='notice'>[user] repairs [src]'s inner core plate.</span>", "<span class='notice'>You repair [src]'s inner core plate. The radiation is contained.</span>")
|
||||||
|
removal_stage = NUKE_CORE_PANEL_UNWELDED
|
||||||
|
if(core)
|
||||||
|
STOP_PROCESSING(SSobj, core)
|
||||||
|
return
|
||||||
|
if(istype(O, /obj/item/stack/sheet/metal) && removal_stage == NUKE_CORE_PANEL_EXPOSED)
|
||||||
|
var/obj/item/stack/S = O
|
||||||
|
if(do_after(user, 2 SECONDS, target = src))
|
||||||
|
if(!loc || !S || S.get_amount() < 5)
|
||||||
|
return
|
||||||
|
S.use(5)
|
||||||
|
user.visible_message("<span class='notice'>[user] repairs [src]'s outer core plate.</span>", "<span class='notice'>You repair [src]'s outer core plate.</span>")
|
||||||
|
removal_stage = NUKE_CORE_EVERYTHING_FINE
|
||||||
|
return
|
||||||
|
if(istype(O, /obj/item/nuke_core/plutonium) && removal_stage == NUKE_CORE_FULLY_EXPOSED)
|
||||||
|
if(do_after(user, 2 SECONDS, target = src))
|
||||||
|
if(!user.unEquip(O))
|
||||||
|
to_chat(user, "<span class='notice'>The [O] is stuck to your hand!</span>")
|
||||||
|
return
|
||||||
|
user.visible_message("<span class='notice'>[user] puts [O] back in [src].</span>", "<span class='notice'>You put [O] back in [src].</span>")
|
||||||
|
O.forceMove(src)
|
||||||
|
core = O
|
||||||
|
|
||||||
else if(istype(O, /obj/item/disk/plantgene))
|
else if(istype(O, /obj/item/disk/plantgene))
|
||||||
to_chat(user, "<span class='warning'>You try to plant the disk, but despite rooting around, it won't fit! After you branch out to read the instructions, you find out where the problem stems from. You've been bamboo-zled, this isn't a nuclear disk at all!</span>")
|
to_chat(user, "<span class='warning'>You try to plant the disk, but despite rooting around, it won't fit! After you branch out to read the instructions, you find out where the problem stems from. You've been bamboo-zled, this isn't a nuclear disk at all!</span>")
|
||||||
return
|
return
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/obj/machinery/nuclearbomb/crowbar_act(mob/user, obj/item/I)
|
/obj/machinery/nuclearbomb/crowbar_act(mob/user, obj/item/I)
|
||||||
if(!anchored)
|
|
||||||
return
|
|
||||||
if(removal_stage != NUKE_UNWRENCHED && removal_stage != NUKE_COVER_OFF)
|
|
||||||
return
|
|
||||||
. = TRUE
|
. = TRUE
|
||||||
if(!I.tool_use_check(user, 0))
|
if(!I.tool_use_check(user, 0))
|
||||||
return
|
return
|
||||||
@@ -92,9 +129,26 @@ GLOBAL_VAR(bomb_set)
|
|||||||
return
|
return
|
||||||
user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.")
|
user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.")
|
||||||
removal_stage = NUKE_COVER_OPEN
|
removal_stage = NUKE_COVER_OPEN
|
||||||
else
|
if(removal_stage == NUKE_CORE_EVERYTHING_FINE)
|
||||||
|
user.visible_message("<span class='notice'>[user] starts removing [src]'s outer core plate...</span>", "<span class='notice'>You start removing [src]'s outer core plate...</span>")
|
||||||
|
if(!I.use_tool(src, user, 4 SECONDS, volume = I.tool_volume) || removal_stage != NUKE_CORE_EVERYTHING_FINE)
|
||||||
|
return
|
||||||
|
user.visible_message("<span class='notice'>[user] finishes removing [src]'s outer core plate.</span>", "<span class='notice'>You finish removing [src]'s outer core plate.</span>")
|
||||||
|
new /obj/item/stack/sheet/metal(loc, 5)
|
||||||
|
removal_stage = NUKE_CORE_PANEL_EXPOSED
|
||||||
|
|
||||||
|
if(removal_stage == NUKE_CORE_PANEL_UNWELDED)
|
||||||
|
user.visible_message("<span class='notice'>[user] starts removing [src]'s inner core plate...</span>", "<span class='notice'>You start removing [src]'s inner core plate...</span>")
|
||||||
|
if(!I.use_tool(src, user, 8 SECONDS, volume = I.tool_volume) || removal_stage != NUKE_CORE_PANEL_UNWELDED)
|
||||||
|
return
|
||||||
|
user.visible_message("<span class='notice'>[user] finishes removing [src]'s inner core plate.</span>", "<span class='notice'>You remove [src]'s inner core plate. You can see the core's green glow!</span>")
|
||||||
|
removal_stage = NUKE_CORE_FULLY_EXPOSED
|
||||||
|
new /obj/item/stack/sheet/mineral/titanium(loc, 5)
|
||||||
|
if(core)
|
||||||
|
START_PROCESSING(SSobj, core)
|
||||||
|
if(removal_stage == NUKE_UNWRENCHED)
|
||||||
user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...")
|
user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...")
|
||||||
if(!I.use_tool(src, user, 80, volume = I.tool_volume) || removal_stage != NUKE_UNWRENCHED)
|
if(!I.use_tool(src, user, 8 SECONDS, volume = I.tool_volume) || removal_stage != NUKE_UNWRENCHED)
|
||||||
return
|
return
|
||||||
user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!")
|
user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!")
|
||||||
anchored = FALSE
|
anchored = FALSE
|
||||||
@@ -126,15 +180,19 @@ GLOBAL_VAR(bomb_set)
|
|||||||
. = TRUE
|
. = TRUE
|
||||||
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
|
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
|
||||||
return
|
return
|
||||||
if(auth)
|
if(auth || (istype(I, /obj/item/screwdriver/nuke)))
|
||||||
if(!panel_open)
|
if(!panel_open)
|
||||||
panel_open = TRUE
|
panel_open = TRUE
|
||||||
overlays += image(icon, "npanel_open")
|
overlays += image(icon, "npanel_open")
|
||||||
to_chat(user, "You unscrew the control panel of [src].")
|
to_chat(user, "You unscrew the control panel of [src].")
|
||||||
|
anchor_stage = removal_stage
|
||||||
|
removal_stage = core_stage
|
||||||
else
|
else
|
||||||
panel_open = FALSE
|
panel_open = FALSE
|
||||||
overlays -= image(icon, "npanel_open")
|
overlays -= image(icon, "npanel_open")
|
||||||
to_chat(user, "You screw the control panel of [src] back on.")
|
to_chat(user, "You screw the control panel of [src] back on.")
|
||||||
|
core_stage = removal_stage
|
||||||
|
removal_stage = anchor_stage
|
||||||
else
|
else
|
||||||
if(!panel_open)
|
if(!panel_open)
|
||||||
to_chat(user, "[src] emits a buzzing noise, the panel staying locked in.")
|
to_chat(user, "[src] emits a buzzing noise, the panel staying locked in.")
|
||||||
@@ -142,6 +200,8 @@ GLOBAL_VAR(bomb_set)
|
|||||||
panel_open = FALSE
|
panel_open = FALSE
|
||||||
overlays -= image(icon, "npanel_open")
|
overlays -= image(icon, "npanel_open")
|
||||||
to_chat(user, "You screw the control panel of [src] back on.")
|
to_chat(user, "You screw the control panel of [src] back on.")
|
||||||
|
core_stage = removal_stage
|
||||||
|
removal_stage = anchor_stage
|
||||||
flick("nuclearbombc", src)
|
flick("nuclearbombc", src)
|
||||||
|
|
||||||
/obj/machinery/nuclearbomb/wirecutter_act(mob/user, obj/item/I)
|
/obj/machinery/nuclearbomb/wirecutter_act(mob/user, obj/item/I)
|
||||||
@@ -154,8 +214,6 @@ GLOBAL_VAR(bomb_set)
|
|||||||
|
|
||||||
/obj/machinery/nuclearbomb/welder_act(mob/user, obj/item/I)
|
/obj/machinery/nuclearbomb/welder_act(mob/user, obj/item/I)
|
||||||
. = TRUE
|
. = TRUE
|
||||||
if(removal_stage != NUKE_INTACT && removal_stage != NUKE_COVER_OPEN)
|
|
||||||
return
|
|
||||||
if(!I.tool_use_check(user, 0))
|
if(!I.tool_use_check(user, 0))
|
||||||
return
|
return
|
||||||
if(removal_stage == NUKE_INTACT)
|
if(removal_stage == NUKE_INTACT)
|
||||||
@@ -167,7 +225,20 @@ GLOBAL_VAR(bomb_set)
|
|||||||
visible_message("<span class='notice'>[user] cuts through the bolt covers on [src].</span>",\
|
visible_message("<span class='notice'>[user] cuts through the bolt covers on [src].</span>",\
|
||||||
"<span class='notice'>You cut through the bolt cover.</span>")
|
"<span class='notice'>You cut through the bolt cover.</span>")
|
||||||
removal_stage = NUKE_COVER_OFF
|
removal_stage = NUKE_COVER_OFF
|
||||||
else if(removal_stage == NUKE_COVER_OPEN)
|
if(removal_stage == NUKE_CORE_PANEL_UNWELDED)
|
||||||
|
user.visible_message("<span class='notice'>[user] starts welding [src]'s inner core plate...</span>", "<span class='notice'>You start welding [src]'s inner core plate...</span>")
|
||||||
|
if(!I.use_tool(src, user, 4 SECONDS, 5, volume = I.tool_volume) || removal_stage != NUKE_CORE_PANEL_UNWELDED)
|
||||||
|
return
|
||||||
|
user.visible_message("<span class='notice'>[user] finishes welding [src]'s inner core plate...</span>", "<span class='notice'>You finish welding [src]'s inner core plate...</span>")
|
||||||
|
removal_stage = NUKE_CORE_PANEL_EXPOSED
|
||||||
|
|
||||||
|
else if(removal_stage == NUKE_CORE_PANEL_EXPOSED)
|
||||||
|
user.visible_message("<span class='notice'>[user] starts unwelding [src]'s inner core plate...</span>", "<span class='notice'>You start unwelding [src]'s inner core plate...</span>")
|
||||||
|
if(!I.use_tool(src, user, 4 SECONDS, 5, volume = I.tool_volume) || removal_stage != NUKE_CORE_PANEL_EXPOSED)
|
||||||
|
return
|
||||||
|
user.visible_message("<span class='notice'>[user] finishes unwelding [src]'s inner core plate...</span>", "<span class='notice'>You finish unwelding [src]'s inner core plate...</span>")
|
||||||
|
removal_stage = NUKE_CORE_PANEL_UNWELDED
|
||||||
|
if(removal_stage == NUKE_COVER_OPEN)
|
||||||
visible_message("<span class='notice'>[user] starts cutting apart the anchoring system sealant on [src].</span>",\
|
visible_message("<span class='notice'>[user] starts cutting apart the anchoring system sealant on [src].</span>",\
|
||||||
"<span class='notice'>You start cutting apart the anchoring system's sealant with [I]...</span>",\
|
"<span class='notice'>You start cutting apart the anchoring system's sealant with [I]...</span>",\
|
||||||
"<span class='warning'>You hear welding.</span>")
|
"<span class='warning'>You hear welding.</span>")
|
||||||
@@ -181,10 +252,18 @@ GLOBAL_VAR(bomb_set)
|
|||||||
attack_hand(user)
|
attack_hand(user)
|
||||||
|
|
||||||
/obj/machinery/nuclearbomb/attack_hand(mob/user as mob)
|
/obj/machinery/nuclearbomb/attack_hand(mob/user as mob)
|
||||||
if(panel_open)
|
if(!panel_open)
|
||||||
wires.Interact(user)
|
return ui_interact(user)
|
||||||
else
|
if(removal_stage != NUKE_CORE_FULLY_EXPOSED || !core)
|
||||||
ui_interact(user)
|
return wires.Interact(user)
|
||||||
|
if(timing) //removing the core is less risk then cutting wires, and doesnt take long, so we should not let crew do it while the nuke is armed. You can however get to it, without the special screwdriver, if you put the NAD in.
|
||||||
|
to_chat(user, "<span class='warning'>[core] won't budge, metal clamps keep it in!</span>")
|
||||||
|
return
|
||||||
|
user.visible_message("<span class='notice'>[user] starts to pull [core] out of [src]!</span>", "<span class='notice'>You start to pull [core] out of [src]!</span>")
|
||||||
|
if(do_after(user, 5 SECONDS, target = src))
|
||||||
|
user.visible_message("<span class='notice'>[user] pulls [core] out of [src]!</span>", "<span class='notice'>You pull [core] out of [src]! Might want to put it somewhere safe.</span>")
|
||||||
|
core.forceMove(loc)
|
||||||
|
core = null
|
||||||
|
|
||||||
/obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
/obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||||
@@ -308,6 +387,9 @@ GLOBAL_VAR(bomb_set)
|
|||||||
if(safety)
|
if(safety)
|
||||||
to_chat(usr, "<span class='notice'>The safety is still on.</span>")
|
to_chat(usr, "<span class='notice'>The safety is still on.</span>")
|
||||||
return
|
return
|
||||||
|
if(!core)
|
||||||
|
to_chat(usr, "<span class='danger'>[src]'s screen blinks red! There is no plutonium core in [src]!</span>")
|
||||||
|
return
|
||||||
timing = !(timing)
|
timing = !(timing)
|
||||||
if(timing)
|
if(timing)
|
||||||
if(!lighthack)
|
if(!lighthack)
|
||||||
@@ -471,3 +553,7 @@ GLOBAL_VAR(bomb_set)
|
|||||||
#undef NUKE_SEALANT_OPEN
|
#undef NUKE_SEALANT_OPEN
|
||||||
#undef NUKE_UNWRENCHED
|
#undef NUKE_UNWRENCHED
|
||||||
#undef NUKE_MOBILE
|
#undef NUKE_MOBILE
|
||||||
|
#undef NUKE_CORE_EVERYTHING_FINE
|
||||||
|
#undef NUKE_CORE_PANEL_EXPOSED
|
||||||
|
#undef NUKE_CORE_PANEL_UNWELDED
|
||||||
|
#undef NUKE_CORE_FULLY_EXPOSED
|
||||||
|
|||||||
@@ -391,6 +391,8 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
|
|||||||
explanation_text = "Steal [steal_target]. One was last seen in [get_location()]. "
|
explanation_text = "Steal [steal_target]. One was last seen in [get_location()]. "
|
||||||
if(length(O.protected_jobs))
|
if(length(O.protected_jobs))
|
||||||
explanation_text += "It may also be in the possession of the [english_list(O.protected_jobs, and_text = " or ")]."
|
explanation_text += "It may also be in the possession of the [english_list(O.protected_jobs, and_text = " or ")]."
|
||||||
|
if(steal_target.special_equipment)
|
||||||
|
give_kit(steal_target.special_equipment)
|
||||||
return
|
return
|
||||||
explanation_text = "Free Objective."
|
explanation_text = "Free Objective."
|
||||||
|
|
||||||
@@ -412,6 +414,8 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
|
|||||||
else
|
else
|
||||||
steal_target = new new_target
|
steal_target = new new_target
|
||||||
explanation_text = "Steal [steal_target.name]."
|
explanation_text = "Steal [steal_target.name]."
|
||||||
|
if(steal_target.special_equipment)
|
||||||
|
give_kit(steal_target.special_equipment)
|
||||||
return steal_target
|
return steal_target
|
||||||
|
|
||||||
/datum/objective/steal/check_completion()
|
/datum/objective/steal/check_completion()
|
||||||
@@ -429,6 +433,23 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
|
|||||||
if(I.type in steal_target.altitems)
|
if(I.type in steal_target.altitems)
|
||||||
return steal_target.check_special_completion(I)
|
return steal_target.check_special_completion(I)
|
||||||
|
|
||||||
|
/datum/objective/steal/proc/give_kit(obj/item/item_path)
|
||||||
|
var/mob/living/carbon/human/mob = owner.current
|
||||||
|
var/I = new item_path
|
||||||
|
var/list/slots = list(
|
||||||
|
"backpack" = slot_in_backpack,
|
||||||
|
"left pocket" = slot_l_store,
|
||||||
|
"right pocket" = slot_r_store,
|
||||||
|
"left hand" = slot_l_hand,
|
||||||
|
"right hand" = slot_r_hand,
|
||||||
|
)
|
||||||
|
var/where = mob.equip_in_one_of_slots(I, slots)
|
||||||
|
if(where)
|
||||||
|
to_chat(mob, "<br><br><span class='info'>In your [where] is a box containing <b>items and instructions</b> to help you with your steal objective.</span><br>")
|
||||||
|
else
|
||||||
|
to_chat(mob, "<span class='userdanger'>Unfortunately, you weren't able to get a stealing kit. This is very bad and you should adminhelp immediately (press F1).</span>")
|
||||||
|
message_admins("[ADMIN_LOOKUPFLW(mob)] Failed to spawn with their [item_path] theft kit.")
|
||||||
|
qdel(I)
|
||||||
|
|
||||||
/datum/objective/steal/exchange
|
/datum/objective/steal/exchange
|
||||||
martyr_compatible = 0
|
martyr_compatible = 0
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ Made by Xhuis
|
|||||||
required_enemies = 2
|
required_enemies = 2
|
||||||
recommended_enemies = 2
|
recommended_enemies = 2
|
||||||
restricted_jobs = list("AI", "Cyborg")
|
restricted_jobs = list("AI", "Cyborg")
|
||||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Head of Personnel", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer")
|
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Head of Personnel", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer", "Solar Federation Brigadier General")
|
||||||
|
|
||||||
/datum/game_mode/shadowling/announce()
|
/datum/game_mode/shadowling/announce()
|
||||||
to_chat(world, "<b>The current game mode is - Shadowling!</b>")
|
to_chat(world, "<b>The current game mode is - Shadowling!</b>")
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
var/list/altitems = list()
|
var/list/altitems = list()
|
||||||
var/flags = 0
|
var/flags = 0
|
||||||
var/location_override
|
var/location_override
|
||||||
|
/// Do we have a special item we give to somewhen when they get this objective?
|
||||||
|
var/special_equipment = null
|
||||||
|
|
||||||
/datum/theft_objective/proc/check_completion(datum/mind/owner)
|
/datum/theft_objective/proc/check_completion(datum/mind/owner)
|
||||||
if(!owner.current)
|
if(!owner.current)
|
||||||
@@ -138,6 +140,19 @@
|
|||||||
protected_jobs = list("Head Of Security", "Warden")
|
protected_jobs = list("Head Of Security", "Warden")
|
||||||
location_override = "the Warden's Office"
|
location_override = "the Warden's Office"
|
||||||
|
|
||||||
|
/datum/theft_objective/supermatter_sliver
|
||||||
|
name = "a supermatter sliver"
|
||||||
|
typepath = /obj/item/nuke_core/supermatter_sliver
|
||||||
|
protected_jobs = list("Chief Engineer", "Engineer", "Atmospheric Technician") //Unlike other steal objectives, all jobs in the department have easy access, and would not be noticed at all stealing this
|
||||||
|
location_override = "Engineering. You can use the box and instructions provided to harvest the sliver."
|
||||||
|
special_equipment = /obj/item/storage/box/syndie_kit/supermatter
|
||||||
|
|
||||||
|
/datum/theft_objective/plutonium_core
|
||||||
|
name = "the plutonium core from the stations nuclear device"
|
||||||
|
typepath = /obj/item/nuke_core/plutonium
|
||||||
|
location_override = "the Vault. You can use the box and instructions provided to remove the core, with some extra tools."
|
||||||
|
special_equipment = /obj/item/storage/box/syndie_kit/nuke
|
||||||
|
|
||||||
/datum/theft_objective/number
|
/datum/theft_objective/number
|
||||||
var/min=0
|
var/min=0
|
||||||
var/max=0
|
var/max=0
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
name = "traitor"
|
name = "traitor"
|
||||||
config_tag = "traitor"
|
config_tag = "traitor"
|
||||||
restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances
|
restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances
|
||||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Internal Affairs Agent", "Brig Physician", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer")
|
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Internal Affairs Agent", "Brig Physician", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer", "Solar Federation Brigadier General")
|
||||||
required_players = 0
|
required_players = 0
|
||||||
required_enemies = 1
|
required_enemies = 1
|
||||||
recommended_enemies = 4
|
recommended_enemies = 4
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name = "traitor+vampire"
|
name = "traitor+vampire"
|
||||||
config_tag = "traitorvamp"
|
config_tag = "traitorvamp"
|
||||||
traitors_possible = 3 //hard limit on traitors if scaling is turned off
|
traitors_possible = 3 //hard limit on traitors if scaling is turned off
|
||||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Chaplain", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Special Operations Officer")
|
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Chaplain", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Special Operations Officer", "Solar Federation Brigadier General")
|
||||||
restricted_jobs = list("Cyborg")
|
restricted_jobs = list("Cyborg")
|
||||||
secondary_restricted_jobs = list("AI")
|
secondary_restricted_jobs = list("AI")
|
||||||
required_players = 10
|
required_players = 10
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
name = "vampire"
|
name = "vampire"
|
||||||
config_tag = "vampire"
|
config_tag = "vampire"
|
||||||
restricted_jobs = list("AI", "Cyborg")
|
restricted_jobs = list("AI", "Cyborg")
|
||||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Chaplain", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer")
|
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Magistrate", "Chaplain", "Brig Physician", "Internal Affairs Agent", "Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer", "Solar Federation Brigadier General")
|
||||||
protected_species = list("Machine")
|
protected_species = list("Machine")
|
||||||
required_players = 15
|
required_players = 15
|
||||||
required_enemies = 1
|
required_enemies = 1
|
||||||
|
|||||||
@@ -100,6 +100,8 @@
|
|||||||
return get_all_centcom_access() + get_all_accesses()
|
return get_all_centcom_access() + get_all_accesses()
|
||||||
if("Special Operations Officer")
|
if("Special Operations Officer")
|
||||||
return get_all_centcom_access() + get_all_accesses()
|
return get_all_centcom_access() + get_all_accesses()
|
||||||
|
if("Solar Federation Brigadier General")
|
||||||
|
return get_all_centcom_access() + get_all_accesses()
|
||||||
if("Nanotrasen Navy Representative")
|
if("Nanotrasen Navy Representative")
|
||||||
return get_all_centcom_access() + get_all_accesses()
|
return get_all_centcom_access() + get_all_accesses()
|
||||||
if("Nanotrasen Navy Officer")
|
if("Nanotrasen Navy Officer")
|
||||||
@@ -401,7 +403,7 @@
|
|||||||
return list("VIP Guest","Custodian","Thunderdome Overseer","Emergency Response Team Member","Emergency Response Team Leader","Intel Officer","Medical Officer","Death Commando","Research Officer","Deathsquad Officer","Special Operations Officer","Nanotrasen Navy Representative","Nanotrasen Navy Officer","Nanotrasen Navy Captain","Supreme Commander")
|
return list("VIP Guest","Custodian","Thunderdome Overseer","Emergency Response Team Member","Emergency Response Team Leader","Intel Officer","Medical Officer","Death Commando","Research Officer","Deathsquad Officer","Special Operations Officer","Nanotrasen Navy Representative","Nanotrasen Navy Officer","Nanotrasen Navy Captain","Supreme Commander")
|
||||||
|
|
||||||
/proc/get_all_solgov_jobs()
|
/proc/get_all_solgov_jobs()
|
||||||
return list("Solar Federation Lieutenant","Solar Federation Specops Lieutenant","Solar Federation Marine","Solar Federation Specops Marine","Solar Federation Representative","Sol Trader")
|
return list("Solar Federation Lieutenant","Solar Federation Specops Lieutenant","Solar Federation Marine","Solar Federation Specops Marine","Solar Federation Representative","Sol Trader","Solar Federation Brigadier General")
|
||||||
|
|
||||||
//gets the actual job rank (ignoring alt titles)
|
//gets the actual job rank (ignoring alt titles)
|
||||||
//this is used solely for sechuds
|
//this is used solely for sechuds
|
||||||
|
|||||||
@@ -69,9 +69,9 @@
|
|||||||
/datum/outfit/job/ntspecops
|
/datum/outfit/job/ntspecops
|
||||||
name = "Special Operations Officer"
|
name = "Special Operations Officer"
|
||||||
jobtype = /datum/job/ntspecops
|
jobtype = /datum/job/ntspecops
|
||||||
|
allow_backbag_choice = FALSE
|
||||||
uniform = /obj/item/clothing/under/rank/centcom/captain
|
uniform = /obj/item/clothing/under/rank/centcom/captain
|
||||||
suit = /obj/item/clothing/suit/space/deathsquad/officer
|
suit = /obj/item/clothing/suit/space/deathsquad/officer
|
||||||
back = /obj/item/storage/backpack/ert/security
|
|
||||||
belt = /obj/item/storage/belt/military/assault
|
belt = /obj/item/storage/belt/military/assault
|
||||||
gloves = /obj/item/clothing/gloves/combat
|
gloves = /obj/item/clothing/gloves/combat
|
||||||
shoes = /obj/item/clothing/shoes/combat
|
shoes = /obj/item/clothing/shoes/combat
|
||||||
@@ -82,8 +82,8 @@
|
|||||||
id = /obj/item/card/id/centcom
|
id = /obj/item/card/id/centcom
|
||||||
pda = /obj/item/pda/centcom
|
pda = /obj/item/pda/centcom
|
||||||
r_pocket = /obj/item/storage/box/matches
|
r_pocket = /obj/item/storage/box/matches
|
||||||
|
back = /obj/item/storage/backpack/satchel
|
||||||
box = /obj/item/storage/box/centcomofficer
|
box = /obj/item/storage/box/centcomofficer
|
||||||
backpack = /obj/item/storage/backpack/satchel
|
|
||||||
backpack_contents = list(
|
backpack_contents = list(
|
||||||
/obj/item/clothing/shoes/magboots/advance = 1,
|
/obj/item/clothing/shoes/magboots/advance = 1,
|
||||||
/obj/item/storage/box/zipties = 1
|
/obj/item/storage/box/zipties = 1
|
||||||
@@ -104,3 +104,23 @@
|
|||||||
if(visualsOnly)
|
if(visualsOnly)
|
||||||
return
|
return
|
||||||
H.mind.offstation_role = TRUE
|
H.mind.offstation_role = TRUE
|
||||||
|
|
||||||
|
/datum/job/ntspecops/solgovspecops
|
||||||
|
title = "Solar Federation Brigadier General"
|
||||||
|
outfit = /datum/outfit/job/ntspecops/solgovspecops
|
||||||
|
|
||||||
|
/datum/outfit/job/ntspecops/solgovspecops
|
||||||
|
name = "Solar Federation Brigadier General"
|
||||||
|
uniform = /obj/item/clothing/under/rank/centcom/captain/solgov
|
||||||
|
suit = /obj/item/clothing/suit/space/deathsquad/officer/solgov
|
||||||
|
head = /obj/item/clothing/head/helmet/space/deathsquad/beret/solgov
|
||||||
|
|
||||||
|
/datum/outfit/job/ntspecops/solgovspecops/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||||
|
. = ..()
|
||||||
|
if(visualsOnly)
|
||||||
|
return
|
||||||
|
var/obj/item/card/id/I = H.wear_id
|
||||||
|
if(istype(I))
|
||||||
|
apply_to_card(I, H, get_centcom_access(name), name, "lifetimeid")
|
||||||
|
H.sec_hud_set_ID()
|
||||||
|
H.mind.offstation_role = TRUE
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
|||||||
var/list/blacklisted_full = list(
|
var/list/blacklisted_full = list(
|
||||||
/datum/job/ntnavyofficer,
|
/datum/job/ntnavyofficer,
|
||||||
/datum/job/ntspecops,
|
/datum/job/ntspecops,
|
||||||
|
/datum/job/ntspecops/solgovspecops,
|
||||||
/datum/job/civilian,
|
/datum/job/civilian,
|
||||||
/datum/job/syndicateofficer,
|
/datum/job/syndicateofficer,
|
||||||
/datum/job/explorer // blacklisted so that HOPs don't try prioritizing it, then wonder why that doesn't work
|
/datum/job/explorer // blacklisted so that HOPs don't try prioritizing it, then wonder why that doesn't work
|
||||||
|
|||||||
@@ -758,8 +758,7 @@
|
|||||||
var/mob/living/silicon/robot/R = occupant
|
var/mob/living/silicon/robot/R = occupant
|
||||||
if(!istype(R)) return ..()
|
if(!istype(R)) return ..()
|
||||||
|
|
||||||
R.contents -= R.mmi
|
QDEL_NULL(R.mmi)
|
||||||
qdel(R.mmi)
|
|
||||||
for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc
|
for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc
|
||||||
for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags
|
for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags
|
||||||
O.loc = R
|
O.loc = R
|
||||||
@@ -771,7 +770,7 @@
|
|||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
|
|
||||||
/proc/cryo_ssd(mob/living/carbon/person_to_cryo)
|
/proc/cryo_ssd(mob/living/person_to_cryo)
|
||||||
if(istype(person_to_cryo.loc, /obj/machinery/cryopod))
|
if(istype(person_to_cryo.loc, /obj/machinery/cryopod))
|
||||||
return 0
|
return 0
|
||||||
if(isobj(person_to_cryo.loc))
|
if(isobj(person_to_cryo.loc))
|
||||||
@@ -779,7 +778,9 @@
|
|||||||
O.force_eject_occupant(person_to_cryo)
|
O.force_eject_occupant(person_to_cryo)
|
||||||
var/list/free_cryopods = list()
|
var/list/free_cryopods = list()
|
||||||
for(var/obj/machinery/cryopod/P in GLOB.machines)
|
for(var/obj/machinery/cryopod/P in GLOB.machines)
|
||||||
if(!P.occupant && istype(get_area(P), /area/crew_quarters/sleep))
|
if(P.occupant)
|
||||||
|
continue
|
||||||
|
if((ishuman(person_to_cryo) && istype(get_area(P), /area/crew_quarters/sleep)) || istype(P, /obj/machinery/cryopod/robot))
|
||||||
free_cryopods += P
|
free_cryopods += P
|
||||||
var/obj/machinery/cryopod/target_cryopod = null
|
var/obj/machinery/cryopod/target_cryopod = null
|
||||||
if(free_cryopods.len)
|
if(free_cryopods.len)
|
||||||
|
|||||||
@@ -85,6 +85,13 @@
|
|||||||
else
|
else
|
||||||
do_animate("deny")
|
do_animate("deny")
|
||||||
|
|
||||||
|
/obj/machinery/door/window/unrestricted_side(mob/M)
|
||||||
|
var/mob_dir = get_dir(src, M)
|
||||||
|
if(mob_dir == 0) // If the mob is inside the tile
|
||||||
|
mob_dir = GetOppositeDir(dir) // Set it to the inside direction of the windoor
|
||||||
|
|
||||||
|
return mob_dir & unres_sides
|
||||||
|
|
||||||
/obj/machinery/door/window/CanPass(atom/movable/mover, turf/target, height=0)
|
/obj/machinery/door/window/CanPass(atom/movable/mover, turf/target, height=0)
|
||||||
if(istype(mover) && mover.checkpass(PASSGLASS))
|
if(istype(mover) && mover.checkpass(PASSGLASS))
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@@ -51,6 +51,11 @@
|
|||||||
"Emergency Response Team Officer" = "dsquadradio",
|
"Emergency Response Team Officer" = "dsquadradio",
|
||||||
"Nanotrasen Navy Officer" = "dsquadradio",
|
"Nanotrasen Navy Officer" = "dsquadradio",
|
||||||
"Special Operations Officer" = "dsquadradio",
|
"Special Operations Officer" = "dsquadradio",
|
||||||
|
"Solar Federation Brigadier General" = "dsquadradio",
|
||||||
|
"Solar Federation Specops Lieutenant" = "dsquadradio",
|
||||||
|
"Solar Federation Specops Marine" = "dsquadradio",
|
||||||
|
"Solar Federation Lieutenant" = "dsquadradio",
|
||||||
|
"Solar Federation Marine" = "dsquadradio",
|
||||||
// Medical
|
// Medical
|
||||||
"Chemist" = "medradio",
|
"Chemist" = "medradio",
|
||||||
"Chief Medical Officer" = "medradio",
|
"Chief Medical Officer" = "medradio",
|
||||||
@@ -119,7 +124,9 @@
|
|||||||
/// List of ERT jobs
|
/// List of ERT jobs
|
||||||
var/list/ert_jobs = list("Emergency Response Team Officer", "Emergency Response Team Engineer", "Emergency Response Team Medic", "Emergency Response Team Leader", "Emergency Response Team Member")
|
var/list/ert_jobs = list("Emergency Response Team Officer", "Emergency Response Team Engineer", "Emergency Response Team Medic", "Emergency Response Team Leader", "Emergency Response Team Member")
|
||||||
/// List of CentComm jobs
|
/// List of CentComm jobs
|
||||||
var/list/cc_jobs = list("Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer")
|
var/list/cc_jobs = list("Nanotrasen Navy Officer", "Special Operations Officer", "Syndicate Officer", "Solar Federation Brigadier General")
|
||||||
|
/// List of SolGov Marine jobs
|
||||||
|
var/list/tsf_jobs = list("Solar Federation Specops Lieutenant", "Solar Federation Specops Marine", "Solar Federation Lieutenant", "Solar Federation Marine")
|
||||||
// Defined so code compiles and incase someone has a non-standard job
|
// Defined so code compiles and incase someone has a non-standard job
|
||||||
var/job_class = "radio"
|
var/job_class = "radio"
|
||||||
// NOW FOR ACTUAL TOGGLES
|
// NOW FOR ACTUAL TOGGLES
|
||||||
@@ -278,7 +285,7 @@
|
|||||||
// Makes heads of staff bold
|
// Makes heads of staff bold
|
||||||
if(toggle_command_bold)
|
if(toggle_command_bold)
|
||||||
var/job = tcm.sender_job
|
var/job = tcm.sender_job
|
||||||
if((job in ert_jobs) || (job in heads) || (job in cc_jobs))
|
if((job in ert_jobs) || (job in heads) || (job in cc_jobs) || (job in tsf_jobs))
|
||||||
for(var/I in 1 to length(message_pieces))
|
for(var/I in 1 to length(message_pieces))
|
||||||
var/datum/multilingual_say_piece/S = message_pieces[I]
|
var/datum/multilingual_say_piece/S = message_pieces[I]
|
||||||
if(!S.message)
|
if(!S.message)
|
||||||
|
|||||||
@@ -107,10 +107,10 @@
|
|||||||
if(R.mind && !R.client && !R.grab_ghost()) // Make sure this is an actual player first and not just a humanized monkey or something.
|
if(R.mind && !R.client && !R.grab_ghost()) // Make sure this is an actual player first and not just a humanized monkey or something.
|
||||||
message_admins("[key_name_admin(R)] was just transformed by a borg factory, but they were SSD. Polling ghosts for a replacement.")
|
message_admins("[key_name_admin(R)] was just transformed by a borg factory, but they were SSD. Polling ghosts for a replacement.")
|
||||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a malfunctioning cyborg?", ROLE_TRAITOR, poll_time = 15 SECONDS)
|
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a malfunctioning cyborg?", ROLE_TRAITOR, poll_time = 15 SECONDS)
|
||||||
if(!length(candidates))
|
if(!length(candidates) || QDELETED(R))
|
||||||
return
|
return
|
||||||
var/mob/dead/observer/O = pick(candidates)
|
var/mob/dead/observer/O = pick(candidates)
|
||||||
R.key= O.key
|
R.key = O.key
|
||||||
|
|
||||||
/obj/machinery/transformer/mime
|
/obj/machinery/transformer/mime
|
||||||
name = "Mimetech Greyscaler"
|
name = "Mimetech Greyscaler"
|
||||||
|
|||||||
@@ -287,7 +287,7 @@
|
|||||||
A.Grant(S)
|
A.Grant(S)
|
||||||
|
|
||||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as a pyroclastic anomaly slime?", ROLE_SENTIENT, FALSE, 100, source = S, role_cleanname = "pyroclastic anomaly slime")
|
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as a pyroclastic anomaly slime?", ROLE_SENTIENT, FALSE, 100, source = S, role_cleanname = "pyroclastic anomaly slime")
|
||||||
if(LAZYLEN(candidates))
|
if(length(candidates) && !QDELETED(S))
|
||||||
var/mob/dead/observer/chosen = pick(candidates)
|
var/mob/dead/observer/chosen = pick(candidates)
|
||||||
S.key = chosen.key
|
S.key = chosen.key
|
||||||
S.mind.special_role = SPECIAL_ROLE_PYROCLASTIC_SLIME
|
S.mind.special_role = SPECIAL_ROLE_PYROCLASTIC_SLIME
|
||||||
|
|||||||
@@ -67,6 +67,11 @@
|
|||||||
/obj/effect/mapping_helpers/no_lava
|
/obj/effect/mapping_helpers/no_lava
|
||||||
icon_state = "no_lava"
|
icon_state = "no_lava"
|
||||||
|
|
||||||
|
/obj/effect/mapping_helpers/no_lava/New()
|
||||||
|
var/turf/T = get_turf(src)
|
||||||
|
T.flags |= NO_LAVA_GEN
|
||||||
|
..()
|
||||||
|
|
||||||
/obj/effect/mapping_helpers/airlock
|
/obj/effect/mapping_helpers/airlock
|
||||||
layer = DOOR_HELPER_LAYER
|
layer = DOOR_HELPER_LAYER
|
||||||
|
|
||||||
@@ -78,13 +83,9 @@
|
|||||||
if(!mapload)
|
if(!mapload)
|
||||||
log_world("### MAP WARNING, [src] spawned outside of mapload!")
|
log_world("### MAP WARNING, [src] spawned outside of mapload!")
|
||||||
return
|
return
|
||||||
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in src.loc
|
var/obj/machinery/door/door = locate(/obj/machinery/door) in loc
|
||||||
if(airlock)
|
if(door)
|
||||||
airlock.unres_sides ^= dir
|
door.unres_sides ^= dir
|
||||||
else
|
else
|
||||||
log_world("### MAP WARNING, [src] failed to find an airlock at [AREACOORD(src)]")
|
log_world("### MAP WARNING, [src] failed to find an airlock at [AREACOORD(src)]")
|
||||||
..()
|
..()
|
||||||
/obj/effect/mapping_helpers/no_lava/New()
|
|
||||||
var/turf/T = get_turf(src)
|
|
||||||
T.flags |= NO_LAVA_GEN
|
|
||||||
. = ..()
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
//generic procs copied from obj/effect/alien
|
//generic procs copied from obj/effect/alien
|
||||||
|
#define SPIDER_SOFT_CAP 30
|
||||||
|
#define SPIDER_HARD_CAP 40
|
||||||
/obj/structure/spider
|
/obj/structure/spider
|
||||||
name = "web"
|
name = "web"
|
||||||
desc = "it's stringy and sticky"
|
desc = "it's stringy and sticky"
|
||||||
@@ -67,7 +69,11 @@
|
|||||||
START_PROCESSING(SSobj, src)
|
START_PROCESSING(SSobj, src)
|
||||||
|
|
||||||
/obj/structure/spider/eggcluster/process()
|
/obj/structure/spider/eggcluster/process()
|
||||||
amount_grown += rand(0,2)
|
if(SSmobs.giant_spiders > SPIDER_SOFT_CAP) //eggs gonna chill out until there is less spiders
|
||||||
|
return
|
||||||
|
|
||||||
|
amount_grown += rand(0, 2)
|
||||||
|
|
||||||
if(amount_grown >= 100)
|
if(amount_grown >= 100)
|
||||||
var/num = rand(3, 12)
|
var/num = rand(3, 12)
|
||||||
for(var/i in 1 to num)
|
for(var/i in 1 to num)
|
||||||
@@ -75,7 +81,7 @@
|
|||||||
S.faction = faction.Copy()
|
S.faction = faction.Copy()
|
||||||
S.master_commander = master_commander
|
S.master_commander = master_commander
|
||||||
if(player_spiders)
|
if(player_spiders)
|
||||||
S.player_spiders = 1
|
S.player_spiders = TRUE
|
||||||
qdel(src)
|
qdel(src)
|
||||||
|
|
||||||
/obj/structure/spider/spiderling
|
/obj/structure/spider/spiderling
|
||||||
@@ -168,9 +174,13 @@
|
|||||||
if(isturf(loc))
|
if(isturf(loc))
|
||||||
amount_grown += rand(0,2)
|
amount_grown += rand(0,2)
|
||||||
if(amount_grown >= 100)
|
if(amount_grown >= 100)
|
||||||
|
if(SSmobs.giant_spiders > SPIDER_HARD_CAP)
|
||||||
|
qdel(src)
|
||||||
|
return
|
||||||
if(!grow_as)
|
if(!grow_as)
|
||||||
grow_as = pick(typesof(/mob/living/simple_animal/hostile/poison/giant_spider))
|
grow_as = pick(typesof(/mob/living/simple_animal/hostile/poison/giant_spider))
|
||||||
var/mob/living/simple_animal/hostile/poison/giant_spider/S = new grow_as(loc)
|
var/mob/living/simple_animal/hostile/poison/giant_spider/S = new grow_as(loc)
|
||||||
|
SSmobs.giant_spiders++
|
||||||
S.faction = faction.Copy()
|
S.faction = faction.Copy()
|
||||||
S.master_commander = master_commander
|
S.master_commander = master_commander
|
||||||
if(player_spiders && !selecting_player)
|
if(player_spiders && !selecting_player)
|
||||||
@@ -178,7 +188,7 @@
|
|||||||
spawn()
|
spawn()
|
||||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a giant spider?", ROLE_GSPIDER, TRUE, source = S)
|
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a giant spider?", ROLE_GSPIDER, TRUE, source = S)
|
||||||
|
|
||||||
if(candidates.len)
|
if(length(candidates) && !QDELETED(S))
|
||||||
var/mob/C = pick(candidates)
|
var/mob/C = pick(candidates)
|
||||||
if(C)
|
if(C)
|
||||||
S.key = C.key
|
S.key = C.key
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Will cause an EMP on the given epicenter.
|
||||||
|
* This proc can sleep depending on the affected objects. So assume it sleeps!
|
||||||
|
*
|
||||||
|
* epicenter - The center of the EMP. Can be an atom, as long as the given atom is on a turf (in)directly
|
||||||
|
* heavy_range - The max distance from the epicenter where objects will be get heavy EMPed
|
||||||
|
* light_range - The max distance from the epicenter where objects will get light EMPed
|
||||||
|
* log - Whether or not this action should be logged or not. Will use the cause if provided
|
||||||
|
* cause - The cause of the EMP. Used for the logging
|
||||||
|
*/
|
||||||
/proc/empulse(turf/epicenter, heavy_range, light_range, log = FALSE, cause = null)
|
/proc/empulse(turf/epicenter, heavy_range, light_range, log = FALSE, cause = null)
|
||||||
if(!epicenter) return
|
if(!epicenter) return
|
||||||
|
|
||||||
|
|||||||
@@ -329,5 +329,6 @@
|
|||||||
..()
|
..()
|
||||||
|
|
||||||
/obj/item/paicard/extinguish_light()
|
/obj/item/paicard/extinguish_light()
|
||||||
pai.extinguish_light()
|
if(pai)
|
||||||
set_light(0)
|
pai.extinguish_light()
|
||||||
|
set_light(0)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/obj/item/painter
|
/obj/item/painter
|
||||||
name = "modular painter"
|
name = "modular painter"
|
||||||
icon = 'icons/obj/painting.dmi'
|
icon = 'icons/obj/painting.dmi'
|
||||||
|
icon_state = "floor_painter"
|
||||||
usesound = 'sound/effects/spray2.ogg'
|
usesound = 'sound/effects/spray2.ogg'
|
||||||
flags = CONDUCT | NOBLUDGEON
|
flags = CONDUCT | NOBLUDGEON
|
||||||
w_class = WEIGHT_CLASS_SMALL
|
w_class = WEIGHT_CLASS_SMALL
|
||||||
|
|||||||
@@ -307,12 +307,18 @@
|
|||||||
icon_state = "com_headset_alt"
|
icon_state = "com_headset_alt"
|
||||||
item_state = "com_headset_alt"
|
item_state = "com_headset_alt"
|
||||||
|
|
||||||
|
/obj/item/radio/headset/ert/alt/solgov
|
||||||
|
name = "\improper Trans-Solar Federation Marine's bowman headset"
|
||||||
|
|
||||||
/obj/item/radio/headset/ert/alt/commander
|
/obj/item/radio/headset/ert/alt/commander
|
||||||
name = "ERT commander's bowman headset"
|
name = "ERT commander's bowman headset"
|
||||||
desc = "The headset of the boss. Protects ears from flashbangs. Can transmit even if telecomms are down."
|
desc = "The headset of the boss. Protects ears from flashbangs. Can transmit even if telecomms are down."
|
||||||
requires_tcomms = FALSE
|
requires_tcomms = FALSE
|
||||||
instant = TRUE
|
instant = TRUE
|
||||||
|
|
||||||
|
/obj/item/radio/headset/ert/alt/commander/solgov
|
||||||
|
name = "\improper Trans-Solar Federation Lieutenant's bowman headset"
|
||||||
|
|
||||||
/obj/item/radio/headset/centcom
|
/obj/item/radio/headset/centcom
|
||||||
name = "centcom officer's bowman headset"
|
name = "centcom officer's bowman headset"
|
||||||
desc = "The headset of final authority. Protects ears from flashbangs. Can transmit even if telecomms are down."
|
desc = "The headset of final authority. Protects ears from flashbangs. Can transmit even if telecomms are down."
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
name = "station intercom (General)"
|
name = "station intercom (General)"
|
||||||
desc = "Talk through this."
|
desc = "Talk through this."
|
||||||
icon_state = "intercom"
|
icon_state = "intercom"
|
||||||
|
layer = ABOVE_WINDOW_LAYER
|
||||||
anchored = 1
|
anchored = 1
|
||||||
w_class = WEIGHT_CLASS_BULKY
|
w_class = WEIGHT_CLASS_BULKY
|
||||||
canhear_range = 2
|
canhear_range = 2
|
||||||
|
|||||||
282
code/game/objects/items/theft_items.dm
Normal file
282
code/game/objects/items/theft_items.dm
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
//Items for nuke theft, supermatter theft traitor objective
|
||||||
|
|
||||||
|
|
||||||
|
// STEALING THE NUKE
|
||||||
|
|
||||||
|
//the nuke core, base item
|
||||||
|
/obj/item/nuke_core
|
||||||
|
name = "plutonium core"
|
||||||
|
desc = "Extremely radioactive. Wear goggles."
|
||||||
|
icon = 'icons/obj/nuke_tools.dmi'
|
||||||
|
icon_state = "plutonium_core"
|
||||||
|
item_state = "plutoniumcore"
|
||||||
|
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||||
|
flags_2 = RAD_NO_CONTAMINATE_2 //Don't have the item itself become irradiated when it makes radiation.
|
||||||
|
var/pulse = 0
|
||||||
|
var/cooldown = 0
|
||||||
|
var/pulseicon = "plutonium_core_pulse"
|
||||||
|
|
||||||
|
/obj/item/nuke_core/Initialize()
|
||||||
|
. = ..()
|
||||||
|
START_PROCESSING(SSobj, src)
|
||||||
|
|
||||||
|
/obj/item/nuke_core/Destroy()
|
||||||
|
STOP_PROCESSING(SSobj, src)
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/obj/item/nuke_core/attackby(obj/item/nuke_core_container/container, mob/user)
|
||||||
|
if(istype(container))
|
||||||
|
container.load(src, user)
|
||||||
|
else
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/obj/item/nuke_core/process()
|
||||||
|
if(cooldown < world.time - 6 SECONDS)
|
||||||
|
cooldown = world.time
|
||||||
|
flick(pulseicon, src)
|
||||||
|
radiation_pulse(src, 400, 2)
|
||||||
|
|
||||||
|
/obj/item/nuke_core/suicide_act(mob/user)
|
||||||
|
user.visible_message("<span class='suicide'>[user] is rubbing [src] against [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||||
|
return TOXLOSS
|
||||||
|
|
||||||
|
/obj/item/nuke_core/plutonium //The steal objective, so it doesnt mess with the SM sliver on pinpointers and objectives
|
||||||
|
|
||||||
|
//nuke core box, for carrying the core
|
||||||
|
/obj/item/nuke_core_container
|
||||||
|
name = "nuke core container"
|
||||||
|
desc = "A solid container for radioactive objects."
|
||||||
|
icon = 'icons/obj/nuke_tools.dmi'
|
||||||
|
icon_state = "core_container_empty"
|
||||||
|
item_state = "metal"
|
||||||
|
var/obj/item/nuke_core/plutonium/core
|
||||||
|
|
||||||
|
/obj/item/nuke_core_container/Destroy()
|
||||||
|
QDEL_NULL(core)
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/obj/item/nuke_core_container/proc/load(obj/item/nuke_core/plutonium/new_core, mob/user)
|
||||||
|
if(core || !istype(new_core))
|
||||||
|
return
|
||||||
|
new_core.forceMove(src)
|
||||||
|
core = new_core
|
||||||
|
icon_state = "core_container_loaded"
|
||||||
|
to_chat(user, "<span class='warning'>Container is sealing...</span>")
|
||||||
|
addtimer(CALLBACK(src, .proc/seal), 10 SECONDS)
|
||||||
|
|
||||||
|
/obj/item/nuke_core_container/proc/seal()
|
||||||
|
if(!QDELETED(core))
|
||||||
|
STOP_PROCESSING(SSobj, core)
|
||||||
|
icon_state = "core_container_sealed"
|
||||||
|
playsound(src, 'sound/items/deconstruct.ogg', 60, TRUE)
|
||||||
|
if(ismob(loc))
|
||||||
|
to_chat(loc, "<span class='warning'>[src] is permanently sealed, [core]'s radiation is contained.</span>")
|
||||||
|
|
||||||
|
/obj/item/nuke_core_container/attackby(obj/item/nuke_core/plutonium/core, mob/user)
|
||||||
|
if(!istype(core))
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
if(!user.drop_item())
|
||||||
|
to_chat(user, "<span class='warning'>[core] is stuck to your hand!</span>")
|
||||||
|
return
|
||||||
|
else
|
||||||
|
load(core, user)
|
||||||
|
|
||||||
|
/obj/item/paper/guides/antag/nuke_instructions
|
||||||
|
info = "How to break into a Nanotrasen nuclear device and remove its plutonium core:<br>\
|
||||||
|
<ul>\
|
||||||
|
<li>Use a screwdriver with a very thin tip (provided) to unscrew the terminal's front panel.</li>\
|
||||||
|
<li>Dislodge and remove the front panel with a crowbar.</li>\
|
||||||
|
<li>Cut the inner metal plate with a welding tool.</li>\
|
||||||
|
<li>Pry off the inner plate with a crowbar to expose the radioactive core.</li>\
|
||||||
|
<li>Pull the core out of the nuclear device. </li>\
|
||||||
|
<li>Put the core in the provided container, which will take some time to seal. </li>\
|
||||||
|
<li>???</li>\
|
||||||
|
</ul>"
|
||||||
|
|
||||||
|
// STEALING SUPERMATTER.
|
||||||
|
|
||||||
|
/obj/item/paper/guides/antag/supermatter_sliver
|
||||||
|
info = "How to safely extract a supermatter sliver:<br>\
|
||||||
|
<ul>\
|
||||||
|
<li>Approach an active supermatter crystal with radiation shielded personal protective equipment. DO NOT MAKE PHYSICAL CONTACT.</li>\
|
||||||
|
<li>Use a supermatter scalpel (provided) to slice off a sliver of the crystal.</li>\
|
||||||
|
<li>Use supermatter extraction tongs (also provided) to safely pick up the sliver you sliced off.</li>\
|
||||||
|
<li>Physical contact of any object with the sliver will dust the object, as well as yourself.</li>\
|
||||||
|
<li>Use the tongs to place the sliver into the provided container, which will take some time to seal.</li>\
|
||||||
|
<li>Get the hell out before the crystal delaminates.</li>\
|
||||||
|
<li>???</li>\
|
||||||
|
</ul>"
|
||||||
|
|
||||||
|
/obj/item/nuke_core/supermatter_sliver
|
||||||
|
name = "supermatter sliver"
|
||||||
|
desc = "A tiny, highly volatile sliver of a supermatter crystal. Do not handle without protection!"
|
||||||
|
icon_state = "supermatter_sliver"
|
||||||
|
pulseicon = "supermatter_sliver_pulse"
|
||||||
|
|
||||||
|
/obj/item/nuke_core/supermatter_sliver/attack_tk(mob/user) // no TK dusting memes
|
||||||
|
return
|
||||||
|
|
||||||
|
/obj/item/nuke_core/supermatter_sliver/can_be_pulled(user) // no drag memes
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
/obj/item/nuke_core/supermatter_sliver/attackby(obj/item/I, mob/living/user, params)
|
||||||
|
if(istype(I, /obj/item/retractor/supermatter))
|
||||||
|
var/obj/item/retractor/supermatter/tongs = I
|
||||||
|
if(tongs.sliver)
|
||||||
|
to_chat(user, "<span class='warning'>[tongs] are already holding a supermatter sliver!</span>")
|
||||||
|
return FALSE
|
||||||
|
forceMove(tongs)
|
||||||
|
tongs.sliver = src
|
||||||
|
tongs.icon_state = "supermatter_tongs_loaded"
|
||||||
|
tongs.item_state = "supermatter_tongs_loaded"
|
||||||
|
to_chat(user, "<span class='notice'>You carefully pick up [src] with [tongs].</span>")
|
||||||
|
else if(istype(I, /obj/item/scalpel/supermatter) || istype(I, /obj/item/nuke_core_container/supermatter)) // we don't want it to dust
|
||||||
|
return
|
||||||
|
else
|
||||||
|
to_chat(user, "<span class='danger'>As it touches [src], both [src] and [I] burst into dust!</span>")
|
||||||
|
radiation_pulse(user, 100)
|
||||||
|
playsound(src, 'sound/effects/supermatter.ogg', 50, TRUE)
|
||||||
|
qdel(I)
|
||||||
|
qdel(src)
|
||||||
|
|
||||||
|
/obj/item/nuke_core/supermatter_sliver/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||||
|
if(!isliving(hit_atom))
|
||||||
|
return ..()
|
||||||
|
var/mob/living/victim = hit_atom
|
||||||
|
if(victim.incorporeal_move || victim.status_flags & GODMODE) //try to keep this in sync with supermatter's consume fail conditions
|
||||||
|
return ..()
|
||||||
|
if(throwingdatum?.thrower)
|
||||||
|
var/mob/user = throwingdatum.thrower
|
||||||
|
add_attack_logs(user, victim, "[victim] consumed by [src] thrown by [user] ")
|
||||||
|
message_admins("[src] has consumed [key_name_admin(victim)] [ADMIN_JMP(src)], thrown by [key_name_admin(user)].")
|
||||||
|
investigate_log("has consumed [key_name(victim)], thrown by [key_name(user)]", "supermatter")
|
||||||
|
else
|
||||||
|
message_admins("[src] has consumed [key_name_admin(victim)] [ADMIN_JMP(src)] via throw impact.")
|
||||||
|
investigate_log("has consumed [key_name(victim)] via throw impact.", "supermatter")
|
||||||
|
victim.visible_message("<span class='danger'>As [victim] is hit by [src], both flash into dust and silence fills the room...</span>",
|
||||||
|
"<span class='userdanger'>You're hit by [src] and everything suddenly goes silent.\n[src] flashes into dust, and soon as you can register this, you do as well.</span>",
|
||||||
|
"<span class='hear'>Everything suddenly goes silent.</span>")
|
||||||
|
victim.dust()
|
||||||
|
radiation_pulse(src, 500, 2)
|
||||||
|
playsound(src, 'sound/effects/supermatter.ogg', 50, TRUE)
|
||||||
|
qdel(src)
|
||||||
|
|
||||||
|
/obj/item/nuke_core/supermatter_sliver/pickup(mob/living/user)
|
||||||
|
..()
|
||||||
|
if(!isliving(user) || user.status_flags & GODMODE) //try to keep this in sync with supermatter's consume fail conditions
|
||||||
|
return FALSE
|
||||||
|
user.visible_message("<span class='danger'>[user] reaches out and tries to pick up [src]. [user.p_their()] body starts to glow and bursts into flames before flashing into dust!</span>",
|
||||||
|
"<span class='userdanger'>You reach for [src] with your hands. That was dumb.</span>",
|
||||||
|
"<span class='hear'>Everything suddenly goes silent.</span>")
|
||||||
|
radiation_pulse(user, 500, 2)
|
||||||
|
playsound(src, 'sound/effects/supermatter.ogg', 50, TRUE)
|
||||||
|
user.dust()
|
||||||
|
|
||||||
|
/obj/item/nuke_core_container/supermatter
|
||||||
|
name = "supermatter bin"
|
||||||
|
desc = "A tiny receptacle that releases an inert hyper-noblium mix upon sealing, allowing a sliver of a supermatter crystal to be safely stored."
|
||||||
|
var/obj/item/nuke_core/supermatter_sliver/sliver
|
||||||
|
|
||||||
|
/obj/item/nuke_core_container/supermatter/Destroy()
|
||||||
|
QDEL_NULL(sliver)
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/obj/item/nuke_core_container/supermatter/load(obj/item/retractor/supermatter/I, mob/user)
|
||||||
|
if(!istype(I) || !I.sliver)
|
||||||
|
return
|
||||||
|
I.sliver.forceMove(src)
|
||||||
|
sliver = I.sliver
|
||||||
|
I.sliver = null
|
||||||
|
I.icon_state = "supermatter_tongs"
|
||||||
|
I.item_state = "supermatter_tongs"
|
||||||
|
icon_state = "supermatter_container_loaded"
|
||||||
|
to_chat(user, "<span class='warning'>Container is sealing...</span>")
|
||||||
|
addtimer(CALLBACK(src, .proc/seal), 10 SECONDS)
|
||||||
|
|
||||||
|
/obj/item/nuke_core_container/supermatter/seal()
|
||||||
|
if(!QDELETED(sliver))
|
||||||
|
STOP_PROCESSING(SSobj, sliver)
|
||||||
|
icon_state = "supermatter_container_sealed"
|
||||||
|
playsound(src, 'sound/items/deconstruct.ogg', 60, TRUE)
|
||||||
|
if(ismob(loc))
|
||||||
|
to_chat(loc, "<span class='warning'>[src] is permanently sealed, [sliver] is safely contained.</span>")
|
||||||
|
|
||||||
|
/obj/item/nuke_core_container/supermatter/attackby(obj/item/retractor/supermatter/tongs, mob/user)
|
||||||
|
if(istype(tongs))
|
||||||
|
//try to load shard into core
|
||||||
|
load(tongs, user)
|
||||||
|
else
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/obj/item/scalpel/supermatter
|
||||||
|
name = "supermatter scalpel"
|
||||||
|
desc = "A scalpel with a fragile tip of condensed hyper-noblium gas, searingly cold to the touch, that can safely shave a sliver off a supermatter crystal."
|
||||||
|
icon = 'icons/obj/nuke_tools.dmi'
|
||||||
|
icon_state = "supermatter_scalpel"
|
||||||
|
toolspeed = 0.5
|
||||||
|
damtype = BURN
|
||||||
|
usesound = 'sound/weapons/bladeslice.ogg'
|
||||||
|
var/uses_left
|
||||||
|
|
||||||
|
/obj/item/scalpel/supermatter/Initialize()
|
||||||
|
. = ..()
|
||||||
|
uses_left = rand(2, 4)
|
||||||
|
|
||||||
|
/obj/item/retractor/supermatter
|
||||||
|
name = "supermatter extraction tongs"
|
||||||
|
desc = "A pair of tongs made from condensed hyper-noblium gas, searingly cold to the touch, that can safely grip a supermatter sliver."
|
||||||
|
icon = 'icons/obj/nuke_tools.dmi'
|
||||||
|
icon_state = "supermatter_tongs"
|
||||||
|
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
|
||||||
|
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
|
||||||
|
item_state = "supermatter_tongs"
|
||||||
|
toolspeed = 0.75
|
||||||
|
damtype = BURN
|
||||||
|
var/obj/item/nuke_core/supermatter_sliver/sliver
|
||||||
|
|
||||||
|
/obj/item/retractor/supermatter/Destroy()
|
||||||
|
QDEL_NULL(sliver)
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/obj/item/retractor/supermatter/afterattack(atom/O, mob/user, proximity)
|
||||||
|
. = ..()
|
||||||
|
if(!sliver)
|
||||||
|
return
|
||||||
|
if(proximity && ismovable(O) && O != sliver)
|
||||||
|
Consume(O, user)
|
||||||
|
|
||||||
|
/obj/item/retractor/supermatter/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) // no instakill supermatter javelins
|
||||||
|
if(sliver)
|
||||||
|
sliver.forceMove(loc)
|
||||||
|
visible_message("<span class='notice'>[sliver] falls out of [src] as it hits the ground.</span>")
|
||||||
|
sliver = null
|
||||||
|
icon_state = "supermatter_tongs"
|
||||||
|
item_state = "supermatter_tongs"
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/obj/item/retractor/supermatter/proc/Consume(atom/movable/AM, mob/living/user)
|
||||||
|
if(ismob(AM))
|
||||||
|
if(!isliving(AM))
|
||||||
|
return
|
||||||
|
var/mob/living/victim = AM
|
||||||
|
if(victim.incorporeal_move || victim.status_flags & GODMODE) //try to keep this in sync with supermatter's consume fail conditions
|
||||||
|
return
|
||||||
|
victim.dust()
|
||||||
|
message_admins("[src] has consumed [key_name_admin(victim)] [ADMIN_JMP(src)].")
|
||||||
|
investigate_log("has irradiated [key_name(victim)].", "supermatter")
|
||||||
|
else if(istype(AM, /obj/singularity))
|
||||||
|
return
|
||||||
|
else
|
||||||
|
investigate_log("has consumed [AM].", "supermatter")
|
||||||
|
qdel(AM)
|
||||||
|
|
||||||
|
if(user)
|
||||||
|
add_attack_logs(user, AM, "[AM] and [user] consumed by melee attack with [src] by [user]")
|
||||||
|
user.visible_message("<span class='danger'>As [user] touches [AM] with [src], both flash into dust and silence fills the room...</span>",
|
||||||
|
"<span class='userdanger'>You touch [AM] with [src], and everything suddenly goes silent.\n[AM] and [sliver] flash into dust, and soon as you can register this, you do as well.</span>",
|
||||||
|
"<span class='hear'>Everything suddenly goes silent.</span>")
|
||||||
|
user.dust()
|
||||||
|
radiation_pulse(src, 500, 2)
|
||||||
|
playsound(src, 'sound/effects/supermatter.ogg', 50, TRUE)
|
||||||
|
QDEL_NULL(sliver)
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
desc = "A screwdriver with an ultra thin tip."
|
desc = "A screwdriver with an ultra thin tip."
|
||||||
icon_state = "screwdriver_nuke"
|
icon_state = "screwdriver_nuke"
|
||||||
toolspeed = 0.5
|
toolspeed = 0.5
|
||||||
|
random_color = FALSE
|
||||||
|
|
||||||
/obj/item/screwdriver/suicide_act(mob/user)
|
/obj/item/screwdriver/suicide_act(mob/user)
|
||||||
user.visible_message("<span class='suicide'>[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
user.visible_message("<span class='suicide'>[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
icon_state = "explosive"
|
icon_state = "explosive"
|
||||||
origin_tech = "materials=2;combat=3;biotech=4;syndicate=4"
|
origin_tech = "materials=2;combat=3;biotech=4;syndicate=4"
|
||||||
actions_types = list(/datum/action/item_action/hands_free/activate/always)
|
actions_types = list(/datum/action/item_action/hands_free/activate/always)
|
||||||
|
var/detonating = FALSE
|
||||||
var/weak = 2
|
var/weak = 2
|
||||||
var/medium = 0.8
|
var/medium = 0.8
|
||||||
var/heavy = 0.4
|
var/heavy = 0.4
|
||||||
@@ -26,16 +27,20 @@
|
|||||||
activate("death")
|
activate("death")
|
||||||
|
|
||||||
/obj/item/implant/explosive/activate(cause)
|
/obj/item/implant/explosive/activate(cause)
|
||||||
if(!cause || !imp_in) return 0
|
if(!cause || !imp_in)
|
||||||
|
return FALSE
|
||||||
if(cause == "action_button" && alert(imp_in, "Are you sure you want to activate your microbomb implant? This will cause you to explode!", "Microbomb Implant Confirmation", "Yes", "No") != "Yes")
|
if(cause == "action_button" && alert(imp_in, "Are you sure you want to activate your microbomb implant? This will cause you to explode!", "Microbomb Implant Confirmation", "Yes", "No") != "Yes")
|
||||||
return 0
|
return FALSE
|
||||||
|
if(detonating)
|
||||||
|
return FALSE
|
||||||
heavy = round(heavy)
|
heavy = round(heavy)
|
||||||
medium = round(medium)
|
medium = round(medium)
|
||||||
weak = round(weak)
|
weak = round(weak)
|
||||||
to_chat(imp_in, "<span class='notice'>You activate your microbomb implant.</span>")
|
detonating = TRUE
|
||||||
|
to_chat(imp_in, "<span class='danger'>You activate your microbomb implant.</span>")
|
||||||
//If the delay is short, just blow up already jeez
|
//If the delay is short, just blow up already jeez
|
||||||
if(delay <= 7)
|
if(delay <= 7)
|
||||||
explosion(src,heavy,medium,weak,weak, flame_range = weak)
|
explosion(src, heavy, medium, weak, weak, flame_range = weak)
|
||||||
if(imp_in)
|
if(imp_in)
|
||||||
imp_in.gib()
|
imp_in.gib()
|
||||||
qdel(src)
|
qdel(src)
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
|
|
||||||
/obj/item/implant/emp/activate()
|
/obj/item/implant/emp/activate()
|
||||||
uses--
|
uses--
|
||||||
empulse(imp_in, 3, 5, 1)
|
INVOKE_ASYNC(GLOBAL_PROC, .proc/empulse, get_turf(imp_in), 3, 5, 1)
|
||||||
if(!uses)
|
if(!uses)
|
||||||
qdel(src)
|
qdel(src)
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,9 @@
|
|||||||
return
|
return
|
||||||
if(istype(W, /obj/item))
|
if(istype(W, /obj/item))
|
||||||
var/obj/item/IW = W
|
var/obj/item/IW = W
|
||||||
|
if(IW.flags & (ABSTRACT | NODROP | DROPDEL))
|
||||||
|
to_chat(user, "<span class='warning'>You can't put [IW] into [src]!</span>")
|
||||||
|
return
|
||||||
if((loadedWeightClass + IW.w_class) > maxWeightClass)
|
if((loadedWeightClass + IW.w_class) > maxWeightClass)
|
||||||
to_chat(user, "<span class='warning'>\The [IW] won't fit into \the [src]!</span>")
|
to_chat(user, "<span class='warning'>\The [IW] won't fit into \the [src]!</span>")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -584,3 +584,9 @@
|
|||||||
name = "emergency response team janitor backpack"
|
name = "emergency response team janitor backpack"
|
||||||
desc = "A spacious backpack with lots of pockets, worn by janitorial members of a Nanotrasen Emergency Response Team."
|
desc = "A spacious backpack with lots of pockets, worn by janitorial members of a Nanotrasen Emergency Response Team."
|
||||||
icon_state = "ert_janitor"
|
icon_state = "ert_janitor"
|
||||||
|
|
||||||
|
//Solgov
|
||||||
|
/obj/item/storage/backpack/ert/solgov
|
||||||
|
name = "\improper TSF marine backpack"
|
||||||
|
desc = "A spacious backpack with lots of pockets, worn by marines of the Trans-Solar Federation."
|
||||||
|
icon_state = "ert_solgov"
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
/// No message on putting items in.
|
/// No message on putting items in.
|
||||||
var/silent = FALSE
|
var/silent = FALSE
|
||||||
/// List of objects which this item can store (if set, it can't store anything else)
|
/// List of objects which this item can store (if set, it can't store anything else)
|
||||||
var/list/can_hold = new/list()
|
var/list/can_hold = list()
|
||||||
/// List of objects which this item can't store (in effect only if can_hold isn't set)
|
/// List of objects which this item can't store (in effect only if can_hold isn't set)
|
||||||
var/list/cant_hold = new/list()
|
var/list/cant_hold = list()
|
||||||
/// Max size of objects that this object can store (in effect only if can_hold isn't set)
|
/// Max size of objects that this object can store (in effect only if can_hold isn't set)
|
||||||
var/max_w_class = WEIGHT_CLASS_SMALL
|
var/max_w_class = WEIGHT_CLASS_SMALL
|
||||||
/// The sum of the w_classes of all the items in this storage item.
|
/// The sum of the w_classes of all the items in this storage item.
|
||||||
@@ -42,6 +42,9 @@
|
|||||||
/// How much of the stack item do you get.
|
/// How much of the stack item do you get.
|
||||||
var/foldable_amt = 0
|
var/foldable_amt = 0
|
||||||
|
|
||||||
|
/// Lazy list of mobs which are currently viewing the storage inventory.
|
||||||
|
var/list/mobs_viewing
|
||||||
|
|
||||||
/obj/item/storage/Initialize(mapload)
|
/obj/item/storage/Initialize(mapload)
|
||||||
. = ..()
|
. = ..()
|
||||||
can_hold = typecacheof(can_hold)
|
can_hold = typecacheof(can_hold)
|
||||||
@@ -73,6 +76,15 @@
|
|||||||
closer.plane = ABOVE_HUD_PLANE
|
closer.plane = ABOVE_HUD_PLANE
|
||||||
orient2hud()
|
orient2hud()
|
||||||
|
|
||||||
|
/obj/item/storage/Destroy()
|
||||||
|
for(var/obj/O in contents)
|
||||||
|
O.mouse_opacity = initial(O.mouse_opacity)
|
||||||
|
|
||||||
|
QDEL_NULL(boxes)
|
||||||
|
QDEL_NULL(closer)
|
||||||
|
LAZYCLEARLIST(mobs_viewing)
|
||||||
|
return ..()
|
||||||
|
|
||||||
/obj/item/storage/MouseDrop(obj/over_object)
|
/obj/item/storage/MouseDrop(obj/over_object)
|
||||||
if(!ismob(usr)) //so monkeys can take off their backpacks -- Urist
|
if(!ismob(usr)) //so monkeys can take off their backpacks -- Urist
|
||||||
return
|
return
|
||||||
@@ -177,11 +189,13 @@
|
|||||||
user.client.screen += closer
|
user.client.screen += closer
|
||||||
user.client.screen += contents
|
user.client.screen += contents
|
||||||
user.s_active = src
|
user.s_active = src
|
||||||
|
LAZYADDOR(mobs_viewing, user)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hides the current container interface from `user`.
|
* Hides the current container interface from `user`.
|
||||||
*/
|
*/
|
||||||
/obj/item/storage/proc/hide_from(mob/user)
|
/obj/item/storage/proc/hide_from(mob/user)
|
||||||
|
LAZYREMOVE(mobs_viewing, user) // Remove clientless mobs too
|
||||||
if(!user.client)
|
if(!user.client)
|
||||||
return
|
return
|
||||||
user.client.screen -= boxes
|
user.client.screen -= boxes
|
||||||
@@ -190,6 +204,16 @@
|
|||||||
if(user.s_active == src)
|
if(user.s_active == src)
|
||||||
user.s_active = null
|
user.s_active = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks all mobs currently viewing the storage inventory, and hides it if they shouldn't be able to see it.
|
||||||
|
*/
|
||||||
|
/obj/item/storage/proc/update_viewers()
|
||||||
|
for(var/_M in mobs_viewing)
|
||||||
|
var/mob/M = _M
|
||||||
|
if(!QDELETED(M) && M.s_active == src && (M in range(1, loc)))
|
||||||
|
continue
|
||||||
|
hide_from(M)
|
||||||
|
|
||||||
/obj/item/storage/proc/open(mob/user)
|
/obj/item/storage/proc/open(mob/user)
|
||||||
if(use_sound)
|
if(use_sound)
|
||||||
playsound(loc, use_sound, 50, TRUE, -5)
|
playsound(loc, use_sound, 50, TRUE, -5)
|
||||||
@@ -374,6 +398,12 @@
|
|||||||
prevent_warning = TRUE
|
prevent_warning = TRUE
|
||||||
I.forceMove(src)
|
I.forceMove(src)
|
||||||
I.on_enter_storage(src)
|
I.on_enter_storage(src)
|
||||||
|
|
||||||
|
for(var/_M in mobs_viewing)
|
||||||
|
var/mob/M = _M
|
||||||
|
if((M.s_active == src) && M.client)
|
||||||
|
M.client.screen += I
|
||||||
|
|
||||||
if(usr)
|
if(usr)
|
||||||
if(usr.client && usr.s_active != src)
|
if(usr.client && usr.s_active != src)
|
||||||
usr.client.screen -= I
|
usr.client.screen -= I
|
||||||
@@ -412,7 +442,8 @@
|
|||||||
var/obj/item/storage/fancy/F = src
|
var/obj/item/storage/fancy/F = src
|
||||||
F.update_icon(TRUE)
|
F.update_icon(TRUE)
|
||||||
|
|
||||||
for(var/mob/M in range(1, loc))
|
for(var/_M in mobs_viewing)
|
||||||
|
var/mob/M = _M
|
||||||
if((M.s_active == src) && M.client)
|
if((M.s_active == src) && M.client)
|
||||||
M.client.screen -= I
|
M.client.screen -= I
|
||||||
|
|
||||||
@@ -498,6 +529,10 @@
|
|||||||
close(M)
|
close(M)
|
||||||
add_fingerprint(user)
|
add_fingerprint(user)
|
||||||
|
|
||||||
|
/obj/item/storage/equipped(mob/user, slot, initial)
|
||||||
|
. = ..()
|
||||||
|
update_viewers()
|
||||||
|
|
||||||
/obj/item/storage/attack_ghost(mob/user)
|
/obj/item/storage/attack_ghost(mob/user)
|
||||||
if(isobserver(user))
|
if(isobserver(user))
|
||||||
// Revenants don't get to play with the toys.
|
// Revenants don't get to play with the toys.
|
||||||
@@ -539,14 +574,6 @@
|
|||||||
/obj/item/storage/proc/populate_contents()
|
/obj/item/storage/proc/populate_contents()
|
||||||
return // Override
|
return // Override
|
||||||
|
|
||||||
/obj/item/storage/Destroy()
|
|
||||||
for(var/obj/O in contents)
|
|
||||||
O.mouse_opacity = initial(O.mouse_opacity)
|
|
||||||
|
|
||||||
QDEL_NULL(boxes)
|
|
||||||
QDEL_NULL(closer)
|
|
||||||
return ..()
|
|
||||||
|
|
||||||
/obj/item/storage/emp_act(severity)
|
/obj/item/storage/emp_act(severity)
|
||||||
..()
|
..()
|
||||||
for(var/I in contents)
|
for(var/I in contents)
|
||||||
|
|||||||
@@ -309,3 +309,24 @@ To apply, hold the injector a short distance away from the outer thigh before ap
|
|||||||
new /obj/item/reagent_containers/syringe/capulettium_plus(src)
|
new /obj/item/reagent_containers/syringe/capulettium_plus(src)
|
||||||
new /obj/item/reagent_containers/syringe/sarin(src)
|
new /obj/item/reagent_containers/syringe/sarin(src)
|
||||||
new /obj/item/reagent_containers/syringe/pancuronium(src)
|
new /obj/item/reagent_containers/syringe/pancuronium(src)
|
||||||
|
|
||||||
|
/obj/item/storage/box/syndie_kit/nuke
|
||||||
|
name = "box" //Bit of stealth, since you spawn with it
|
||||||
|
desc = "It's just an ordinary box."
|
||||||
|
icon_state = "box"
|
||||||
|
|
||||||
|
/obj/item/storage/box/syndie_kit/nuke/populate_contents()
|
||||||
|
new /obj/item/screwdriver/nuke(src)
|
||||||
|
new /obj/item/nuke_core_container(src)
|
||||||
|
new /obj/item/paper/guides/antag/nuke_instructions(src)
|
||||||
|
|
||||||
|
/obj/item/storage/box/syndie_kit/supermatter
|
||||||
|
name = "box"
|
||||||
|
desc = "It's just an ordinary box."
|
||||||
|
icon_state = "box"
|
||||||
|
|
||||||
|
/obj/item/storage/box/syndie_kit/supermatter/populate_contents()
|
||||||
|
new /obj/item/scalpel/supermatter(src)
|
||||||
|
new /obj/item/retractor/supermatter(src)
|
||||||
|
new /obj/item/nuke_core_container/supermatter(src)
|
||||||
|
new /obj/item/paper/guides/antag/supermatter_sliver(src)
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
trigger_alarm()
|
trigger_alarm()
|
||||||
|
|
||||||
emagged = TRUE
|
emagged = TRUE
|
||||||
|
toggle_lock()
|
||||||
|
|
||||||
/obj/structure/displaycase/examine(mob/user)
|
/obj/structure/displaycase/examine(mob/user)
|
||||||
. = ..()
|
. = ..()
|
||||||
@@ -110,12 +111,12 @@
|
|||||||
/obj/structure/displaycase/attackby(obj/item/I, mob/user, params)
|
/obj/structure/displaycase/attackby(obj/item/I, mob/user, params)
|
||||||
if(I.GetID() && !broken && openable)
|
if(I.GetID() && !broken && openable)
|
||||||
if(allowed(user) || emagged)
|
if(allowed(user) || emagged)
|
||||||
to_chat(user, "<span class='notice'>You [open ? "close":"open"] [src].</span>")
|
to_chat(user, "<span class='notice'>You [open ? "close":"open"] [src].</span>")
|
||||||
toggle_lock(user)
|
toggle_lock()
|
||||||
else
|
else
|
||||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||||
else if(open && !showpiece)
|
else if(open && !showpiece)
|
||||||
if(user.drop_item())
|
if(!(I.flags & (ABSTRACT | DROPDEL)) && user.drop_item())
|
||||||
I.forceMove(src)
|
I.forceMove(src)
|
||||||
showpiece = I
|
showpiece = I
|
||||||
to_chat(user, "<span class='notice'>You put [I] on display</span>")
|
to_chat(user, "<span class='notice'>You put [I] on display</span>")
|
||||||
@@ -151,14 +152,14 @@
|
|||||||
if(!I.use_tool(src, user, 20, volume = I.tool_volume))
|
if(!I.use_tool(src, user, 20, volume = I.tool_volume))
|
||||||
return
|
return
|
||||||
to_chat(user, "<span class='notice'>You [open ? "close":"open"] [src].</span>")
|
to_chat(user, "<span class='notice'>You [open ? "close":"open"] [src].</span>")
|
||||||
toggle_lock(user)
|
toggle_lock()
|
||||||
|
|
||||||
/obj/structure/displaycase/welder_act(mob/user, obj/item/I)
|
/obj/structure/displaycase/welder_act(mob/user, obj/item/I)
|
||||||
. = TRUE
|
. = TRUE
|
||||||
if(default_welder_repair(user, I))
|
if(default_welder_repair(user, I))
|
||||||
broken = FALSE
|
broken = FALSE
|
||||||
|
|
||||||
/obj/structure/displaycase/proc/toggle_lock(mob/user)
|
/obj/structure/displaycase/proc/toggle_lock()
|
||||||
open = !open
|
open = !open
|
||||||
update_icon()
|
update_icon()
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
if(GIRDER_DISASSEMBLED)
|
if(GIRDER_DISASSEMBLED)
|
||||||
. += "<span class='notice'>[src] is disassembled! You probably shouldn't be able to see this examine message.</span>"
|
. += "<span class='notice'>[src] is disassembled! You probably shouldn't be able to see this examine message.</span>"
|
||||||
|
|
||||||
/obj/structre/girder/detailed_examine()
|
/obj/structure/girder/detailed_examine()
|
||||||
return "Use metal sheets on this to build a normal wall. Adding plasteel instead will make a reinforced wall.<br>\
|
return "Use metal sheets on this to build a normal wall. Adding plasteel instead will make a reinforced wall.<br>\
|
||||||
A false wall can be made by using a crowbar on this girder, and then adding metal or plasteel.<br>\
|
A false wall can be made by using a crowbar on this girder, and then adding metal or plasteel.<br>\
|
||||||
You can dismantle the girder with a wrench."
|
You can dismantle the girder with a wrench."
|
||||||
|
|||||||
@@ -46,9 +46,16 @@
|
|||||||
/obj/structure/inflatable/CanAtmosPass(turf/T)
|
/obj/structure/inflatable/CanAtmosPass(turf/T)
|
||||||
return !density
|
return !density
|
||||||
|
|
||||||
/obj/structure/inflatable/attack_hand(mob/user as mob)
|
/obj/structure/inflatable/attack_hand(mob/user)
|
||||||
add_fingerprint(user)
|
add_fingerprint(user)
|
||||||
|
|
||||||
|
/obj/structure/inflatable/attackby(obj/item/I, mob/living/user, params)
|
||||||
|
if(I.sharp || is_type_in_typecache(I, GLOB.pointed_types))
|
||||||
|
user.do_attack_animation(src, used_item = I)
|
||||||
|
deconstruct(FALSE)
|
||||||
|
return FALSE
|
||||||
|
return ..()
|
||||||
|
|
||||||
/obj/structure/inflatable/AltClick()
|
/obj/structure/inflatable/AltClick()
|
||||||
if(usr.stat || usr.restrained())
|
if(usr.stat || usr.restrained())
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -203,6 +203,7 @@
|
|||||||
windoor.req_one_access = electronics.selected_accesses
|
windoor.req_one_access = electronics.selected_accesses
|
||||||
else
|
else
|
||||||
windoor.req_access = electronics.selected_accesses
|
windoor.req_access = electronics.selected_accesses
|
||||||
|
windoor.unres_sides = electronics.unres_access_from
|
||||||
windoor.electronics = src.electronics
|
windoor.electronics = src.electronics
|
||||||
electronics.forceMove(windoor)
|
electronics.forceMove(windoor)
|
||||||
electronics = null
|
electronics = null
|
||||||
|
|||||||
@@ -85,15 +85,16 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
|
|||||||
TGS_TOPIC
|
TGS_TOPIC
|
||||||
log_misc("WORLD/TOPIC: \"[T]\", from:[addr], master:[master], key:[key]")
|
log_misc("WORLD/TOPIC: \"[T]\", from:[addr], master:[master], key:[key]")
|
||||||
|
|
||||||
// Handle spam prevention
|
// Handle spam prevention, if their IP isnt in the whitelist
|
||||||
if(!GLOB.world_topic_spam_prevention_handlers[address])
|
if(!(addr in GLOB.configuration.system.topic_ip_ratelimit_bypass))
|
||||||
GLOB.world_topic_spam_prevention_handlers[address] = new /datum/world_topic_spam_prevention_handler
|
if(!GLOB.world_topic_spam_prevention_handlers[addr])
|
||||||
|
GLOB.world_topic_spam_prevention_handlers[addr] = new /datum/world_topic_spam_prevention_handler(addr)
|
||||||
|
|
||||||
var/datum/world_topic_spam_prevention_handler/sph = GLOB.world_topic_spam_prevention_handlers[address]
|
var/datum/world_topic_spam_prevention_handler/sph = GLOB.world_topic_spam_prevention_handlers[addr]
|
||||||
|
|
||||||
// Lock the user out and cancel their topic if needed
|
// Lock the user out and cancel their topic if needed
|
||||||
if(sph.check_lockout())
|
if(sph.check_lockout())
|
||||||
return
|
return
|
||||||
|
|
||||||
var/list/input = params2list(T)
|
var/list/input = params2list(T)
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
|
|||||||
body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\] "
|
body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\] "
|
||||||
body += "\[<A href='?_src_=holder;getplaytimewindow=[M.UID()]'>" + M.client.get_exp_type(EXP_TYPE_CREW) + " as [EXP_TYPE_CREW]</a>\]"
|
body += "\[<A href='?_src_=holder;getplaytimewindow=[M.UID()]'>" + M.client.get_exp_type(EXP_TYPE_CREW) + " as [EXP_TYPE_CREW]</a>\]"
|
||||||
body += "<br>BYOND account registration date: [M.client.byondacc_date || "ERROR"] [M.client.byondacc_age <= GLOB.configuration.general.byond_account_age_threshold ? "<b>" : ""]([M.client.byondacc_age] days old)[M.client.byondacc_age <= GLOB.configuration.general.byond_account_age_threshold ? "</b>" : ""]"
|
body += "<br>BYOND account registration date: [M.client.byondacc_date || "ERROR"] [M.client.byondacc_age <= GLOB.configuration.general.byond_account_age_threshold ? "<b>" : ""]([M.client.byondacc_age] days old)[M.client.byondacc_age <= GLOB.configuration.general.byond_account_age_threshold ? "</b>" : ""]"
|
||||||
|
body += "<br>BYOND client version: [M.client.byond_version].[M.client.byond_build]"
|
||||||
body += "<br>Global Ban DB Lookup: [GLOB.configuration.url.centcom_ban_db_url ? "<a href='?_src_=holder;open_ccbdb=[M.client.ckey]'>Lookup</a>" : "<i>Disabled</i>"]"
|
body += "<br>Global Ban DB Lookup: [GLOB.configuration.url.centcom_ban_db_url ? "<a href='?_src_=holder;open_ccbdb=[M.client.ckey]'>Lookup</a>" : "<i>Disabled</i>"]"
|
||||||
|
|
||||||
body += "<br>"
|
body += "<br>"
|
||||||
|
|||||||
@@ -2300,26 +2300,40 @@
|
|||||||
else if(href_list["cryossd"])
|
else if(href_list["cryossd"])
|
||||||
if(!check_rights(R_ADMIN))
|
if(!check_rights(R_ADMIN))
|
||||||
return
|
return
|
||||||
var/mob/living/carbon/human/H = locateUID(href_list["cryossd"])
|
var/mob/living/M = locateUID(href_list["cryossd"])
|
||||||
if(!istype(H))
|
var/human = ishuman(M)
|
||||||
to_chat(usr, "<span class='warning'>This can only be used on instances of type /mob/living/carbon/human</span>")
|
if(!human && !issilicon(M))
|
||||||
|
to_chat(usr, "<span class='warning'>This can only be used on humans and silicons.</span>")
|
||||||
return
|
return
|
||||||
if(!href_list["cryoafk"] && !isLivingSSD(H))
|
if(!href_list["cryoafk"] && !isLivingSSD(M))
|
||||||
to_chat(usr, "<span class='warning'>This can only be used on living, SSD players.</span>")
|
to_chat(usr, "<span class='warning'>This can only be used on living, SSD players.</span>")
|
||||||
return
|
return
|
||||||
if(istype(H.loc, /obj/machinery/cryopod))
|
if(isAI(M))
|
||||||
var/obj/machinery/cryopod/P = H.loc
|
var/mob/living/silicon/ai/A = M
|
||||||
|
A.cryo_AI()
|
||||||
|
if(istype(M.loc, /obj/machinery/cryopod))
|
||||||
|
var/obj/machinery/cryopod/P = M.loc
|
||||||
P.despawn_occupant()
|
P.despawn_occupant()
|
||||||
log_admin("[key_name(usr)] despawned [H.job] [H] in cryo.")
|
if(human)
|
||||||
message_admins("[key_name_admin(usr)] despawned [H.job] [H] in cryo.")
|
var/mob/living/carbon/human/H = M
|
||||||
else if(cryo_ssd(H))
|
log_admin("[key_name(usr)] despawned [H.job] [H] in cryo.")
|
||||||
log_admin("[key_name(usr)] sent [H.job] [H] to cryo.")
|
message_admins("[key_name_admin(usr)] despawned [H.job] [H] in cryo.")
|
||||||
message_admins("[key_name_admin(usr)] sent [H.job] [H] to cryo.")
|
else //robot
|
||||||
|
log_admin("[key_name(usr)] despawned [M] in cryo.")
|
||||||
|
message_admins("[key_name_admin(usr)] despawned [M] in cryo.")
|
||||||
|
else if(cryo_ssd(M))
|
||||||
|
if(human)
|
||||||
|
var/mob/living/carbon/human/H = M
|
||||||
|
log_admin("[key_name(usr)] sent [H.job] [H] to cryo.")
|
||||||
|
message_admins("[key_name_admin(usr)] sent [H.job] [H] to cryo.")
|
||||||
|
else
|
||||||
|
log_admin("[key_name(usr)] sent [M] to cryo.")
|
||||||
|
message_admins("[key_name_admin(usr)] sent [M] to cryo.")
|
||||||
if(href_list["cryoafk"]) // Warn them if they are send to storage and are AFK
|
if(href_list["cryoafk"]) // Warn them if they are send to storage and are AFK
|
||||||
to_chat(H, "<span class='danger'>The admins have moved you to cryo storage for being AFK. Please eject yourself (right click, eject) out of the cryostorage if you want to avoid being despawned.</span>")
|
to_chat(M, "<span class='danger'>The admins have moved you to cryo storage for being AFK. Please eject yourself (right click, eject) out of the cryostorage if you want to avoid being despawned.</span>")
|
||||||
SEND_SOUND(H, sound('sound/effects/adminhelp.ogg'))
|
SEND_SOUND(M, sound('sound/effects/adminhelp.ogg'))
|
||||||
if(H.client)
|
if(M.client)
|
||||||
window_flash(H.client)
|
window_flash(M.client)
|
||||||
else if(href_list["FaxReplyTemplate"])
|
else if(href_list["FaxReplyTemplate"])
|
||||||
if(!check_rights(R_ADMIN))
|
if(!check_rights(R_ADMIN))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
|||||||
log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
|
log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
|
||||||
returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc
|
returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc
|
||||||
|
|
||||||
to_chat(usr, "<font color='blue'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</font>")
|
to_chat(usr, "<font color='#EB4E00'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</font>")
|
||||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Advanced Proc-Call") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
SSblackbox.record_feedback("tally", "admin_verb", 1, "Advanced Proc-Call") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||||
|
|
||||||
// All these vars are related to proc call protection
|
// All these vars are related to proc call protection
|
||||||
|
|||||||
@@ -528,8 +528,8 @@
|
|||||||
if(!antnum || antnum <= 0)
|
if(!antnum || antnum <= 0)
|
||||||
return
|
return
|
||||||
|
|
||||||
log_admin("[key_name(owner)] tried making Vampires with One-Click-Antag")
|
log_admin("[key_name(owner)] tried making [antnum] Vampires with One-Click-Antag")
|
||||||
message_admins("[key_name_admin(owner)] tried making Vampires with One-Click-Antag")
|
message_admins("[key_name_admin(owner)] tried making [antnum] Vampires with One-Click-Antag")
|
||||||
|
|
||||||
for(var/mob/living/carbon/human/applicant in GLOB.player_list)
|
for(var/mob/living/carbon/human/applicant in GLOB.player_list)
|
||||||
if(CandCheck(ROLE_VAMPIRE, applicant, temp))
|
if(CandCheck(ROLE_VAMPIRE, applicant, temp))
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
|||||||
set waitfor = FALSE
|
set waitfor = FALSE
|
||||||
|
|
||||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as a [name]?", job_rank, TRUE, 5 SECONDS)
|
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as a [name]?", job_rank, TRUE, 5 SECONDS)
|
||||||
if(LAZYLEN(candidates))
|
if(length(candidates))
|
||||||
var/mob/dead/observer/C = pick(candidates)
|
var/mob/dead/observer/C = pick(candidates)
|
||||||
to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
|
to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
|
||||||
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
|
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
to_chat(user, "<span class='notice'>You activate [src] and wait for confirmation.</span>")
|
to_chat(user, "<span class='notice'>You activate [src] and wait for confirmation.</span>")
|
||||||
var/image/I = new('icons/mob/simple_human.dmi', "syndicate_space_sword")
|
var/image/I = new('icons/mob/simple_human.dmi', "syndicate_space_sword")
|
||||||
var/list/nuke_candidates = SSghost_spawns.poll_candidates("Do you want to play as a [rolename]?", ROLE_OPERATIVE, TRUE, 15 SECONDS, source = I)
|
var/list/nuke_candidates = SSghost_spawns.poll_candidates("Do you want to play as a [rolename]?", ROLE_OPERATIVE, TRUE, 15 SECONDS, source = I)
|
||||||
if(LAZYLEN(nuke_candidates))
|
if(length(nuke_candidates))
|
||||||
checking = FALSE
|
checking = FALSE
|
||||||
if(QDELETED(src) || !check_usability(user))
|
if(QDELETED(src) || !check_usability(user))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -34,21 +34,30 @@
|
|||||||
"Virology",
|
"Virology",
|
||||||
"Waste Disposal",
|
"Waste Disposal",
|
||||||
// Maintenance
|
// Maintenance
|
||||||
|
"Aft Maintenance",
|
||||||
|
"Aft-Port Maintenance",
|
||||||
|
"Aft-Port Secondary Maintenance",
|
||||||
"Aft Port Solar Maintenance",
|
"Aft Port Solar Maintenance",
|
||||||
|
"Aft Secondary Maintenance",
|
||||||
|
"Aft-Starboard Maintenance",
|
||||||
|
"Aft-Starboard Secondary Maintenance",
|
||||||
"Aft Starboard Solar Maintenance",
|
"Aft Starboard Solar Maintenance",
|
||||||
"Arrivals North Maintenance",
|
|
||||||
"Bar Maintenance",
|
|
||||||
"Cargo Maintenance",
|
|
||||||
"Dormitory Maintenance",
|
|
||||||
"Electrical Maintenance",
|
"Electrical Maintenance",
|
||||||
"EVA Maintenance",
|
"Electronics Den",
|
||||||
"Engineering Maintenance",
|
"Fore Maintenance",
|
||||||
|
"Fore-Port Maintenance",
|
||||||
|
"Fore-Port Secondary Maintenance",
|
||||||
"Fore Port Solar Maintenance",
|
"Fore Port Solar Maintenance",
|
||||||
|
"Fore Secondary Maintenance",
|
||||||
|
"Fore-Starboard Maintenance",
|
||||||
|
"Fore-Starboard Secondary Maintenance",
|
||||||
"Fore Starboard Solar Maintenance",
|
"Fore Starboard Solar Maintenance",
|
||||||
|
"Gambling Den",
|
||||||
"Genetics Maintenance",
|
"Genetics Maintenance",
|
||||||
"Locker Room Maintenance",
|
"Port Maintenance",
|
||||||
"Medbay Maintenance",
|
"Port Secondary Maintenance",
|
||||||
"Science Maintenance",
|
"Starboard Maintenance",
|
||||||
|
"Starboard Secondary Maintenance",
|
||||||
),
|
),
|
||||||
EXTRACTION_DIFFICULTY_MEDIUM = list(
|
EXTRACTION_DIFFICULTY_MEDIUM = list(
|
||||||
// Rooms
|
// Rooms
|
||||||
@@ -89,7 +98,8 @@
|
|||||||
"Xenobiology Lab",
|
"Xenobiology Lab",
|
||||||
// Maintenance
|
// Maintenance
|
||||||
"Atmospherics Maintenance",
|
"Atmospherics Maintenance",
|
||||||
"Bridge Maintenance",
|
"Central Maintenance",
|
||||||
|
"Central Secondary Maintenance",
|
||||||
),
|
),
|
||||||
EXTRACTION_DIFFICULTY_HARD = list(
|
EXTRACTION_DIFFICULTY_HARD = list(
|
||||||
// No AI Chamber because I'm not that sadistic.
|
// No AI Chamber because I'm not that sadistic.
|
||||||
@@ -100,7 +110,6 @@
|
|||||||
"AI Satellite Hallway",
|
"AI Satellite Hallway",
|
||||||
"Bar",
|
"Bar",
|
||||||
"Cargo Office",
|
"Cargo Office",
|
||||||
"Central Primary Hallway",
|
|
||||||
"Chemistry",
|
"Chemistry",
|
||||||
"Chief Engineer's office",
|
"Chief Engineer's office",
|
||||||
"Chief Medical Officer's office",
|
"Chief Medical Officer's office",
|
||||||
|
|||||||
@@ -198,13 +198,7 @@
|
|||||||
apply_mode()
|
apply_mode()
|
||||||
|
|
||||||
/obj/machinery/alarm/New(loc, direction, building = 0)
|
/obj/machinery/alarm/New(loc, direction, building = 0)
|
||||||
. = ..()
|
if(building) // Do this first since the Init uses this later on. TODO refactor to just use an Init
|
||||||
GLOB.air_alarms += src
|
|
||||||
GLOB.air_alarms = sortAtom(GLOB.air_alarms)
|
|
||||||
|
|
||||||
wires = new(src)
|
|
||||||
|
|
||||||
if(building)
|
|
||||||
if(loc)
|
if(loc)
|
||||||
src.loc = loc
|
src.loc = loc
|
||||||
|
|
||||||
@@ -214,10 +208,15 @@
|
|||||||
buildstage = 0
|
buildstage = 0
|
||||||
wiresexposed = 1
|
wiresexposed = 1
|
||||||
set_pixel_offsets_from_dir(-24, 24, -24, 24)
|
set_pixel_offsets_from_dir(-24, 24, -24, 24)
|
||||||
update_icon()
|
|
||||||
return
|
|
||||||
|
|
||||||
first_run()
|
. = ..()
|
||||||
|
GLOB.air_alarms += src
|
||||||
|
GLOB.air_alarms = sortAtom(GLOB.air_alarms)
|
||||||
|
|
||||||
|
wires = new(src)
|
||||||
|
|
||||||
|
if(!building)
|
||||||
|
first_run()
|
||||||
|
|
||||||
/obj/machinery/alarm/Destroy()
|
/obj/machinery/alarm/Destroy()
|
||||||
SStgui.close_uis(wires)
|
SStgui.close_uis(wires)
|
||||||
|
|||||||
@@ -194,7 +194,7 @@
|
|||||||
servant_mind.transfer_to(H)
|
servant_mind.transfer_to(H)
|
||||||
|
|
||||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as the servant of [user.real_name]?", ROLE_WIZARD, poll_time = 30 SECONDS, source = H)
|
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as the servant of [user.real_name]?", ROLE_WIZARD, poll_time = 30 SECONDS, source = H)
|
||||||
if(LAZYLEN(candidates))
|
if(length(candidates) && !QDELETED(H))
|
||||||
var/mob/dead/observer/C = pick(candidates)
|
var/mob/dead/observer/C = pick(candidates)
|
||||||
message_admins("[ADMIN_LOOKUPFLW(C)] was spawned as Dice Servant")
|
message_admins("[ADMIN_LOOKUPFLW(C)] was spawned as Dice Servant")
|
||||||
H.key = C.key
|
H.key = C.key
|
||||||
|
|||||||
@@ -206,11 +206,13 @@
|
|||||||
icon_state = "solgovcberet"
|
icon_state = "solgovcberet"
|
||||||
item_color = "solgovc"
|
item_color = "solgovc"
|
||||||
dog_fashion = null
|
dog_fashion = null
|
||||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 60)
|
armor = list("melee" = 20, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 60)
|
||||||
strip_delay = 80
|
strip_delay = 80
|
||||||
|
|
||||||
/obj/item/clothing/head/beret/solgov/command/elite
|
/obj/item/clothing/head/beret/solgov/command/elite
|
||||||
name = "\improper Trans-Solar Federation Specops Lieutenant's beret"
|
name = "\improper Trans-Solar Federation Specops Lieutenant's beret"
|
||||||
desc = "A beret worn by marines of the Trans-Solar Federation Psiops division. The insignia signifies the wearer bears the rank of a Lieutenant."
|
desc = "A beret worn by marines of the Trans-Solar Federation Specops division. The insignia signifies the wearer bears the rank of a Lieutenant."
|
||||||
|
armor = list("melee" = 35, "bullet" = 60, "laser" = 10, "energy" = 10, "bomb" = 25, "bio" = 10, "rad" = 50, "fire" = 80, "acid" = 80)
|
||||||
icon_state = "solgovceliteberet"
|
icon_state = "solgovceliteberet"
|
||||||
item_color = "solgovcelite"
|
item_color = "solgovcelite"
|
||||||
|
resistance_flags = FIRE_PROOF
|
||||||
|
|||||||
@@ -125,28 +125,32 @@
|
|||||||
dog_fashion = null
|
dog_fashion = null
|
||||||
|
|
||||||
/obj/item/clothing/head/soft/solgov/marines
|
/obj/item/clothing/head/soft/solgov/marines
|
||||||
armor = list("melee" = 35, "bullet" = 30, "laser" = 30,"energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 50)
|
armor = list("melee" = 20, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 60)
|
||||||
strip_delay = 60
|
|
||||||
icon_state = "solgovsoft_flipped"
|
icon_state = "solgovsoft_flipped"
|
||||||
|
strip_delay = 60
|
||||||
flipped = TRUE
|
flipped = TRUE
|
||||||
|
|
||||||
/obj/item/clothing/head/soft/solgov/marines/elite
|
/obj/item/clothing/head/soft/solgov/marines/elite
|
||||||
name = "\improper Trans-Solar Federation Specops marine cap"
|
name = "\improper Trans-Solar Federation Specops marine cap"
|
||||||
desc = "A soft cap worn by marines of the Trans-Solar Federation Specops division."
|
desc = "A cap worn by marines of the Trans-Solar Federation Specops division. You aren't quite sure how they made this bulletproof, but you are glad it is!"
|
||||||
|
armor = list("melee" = 35, "bullet" = 60, "laser" = 10, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 50, "fire" = 80, "acid" = 80)
|
||||||
icon_state = "solgovelitesoft_flipped"
|
icon_state = "solgovelitesoft_flipped"
|
||||||
item_color = "solgovelite"
|
item_color = "solgovelite"
|
||||||
|
resistance_flags = FIRE_PROOF
|
||||||
|
|
||||||
/obj/item/clothing/head/soft/solgov/marines/command
|
/obj/item/clothing/head/soft/solgov/marines/command
|
||||||
name = "\improper Trans-Solar Federation lieutenant's cap"
|
name = "\improper Trans-Solar Federation lieutenant's cap"
|
||||||
desc = "A soft cap worn by marines of the Trans-Solar Federation. The insignia signifies the wearer bears the rank of a Lieutenant."
|
desc = "A soft cap worn by marines of the Trans-Solar Federation. The insignia signifies the wearer bears the rank of a Lieutenant."
|
||||||
|
armor = list("melee" = 20, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 60)
|
||||||
icon_state = "solgovcsoft_flipped"
|
icon_state = "solgovcsoft_flipped"
|
||||||
item_color = "solgovc"
|
item_color = "solgovc"
|
||||||
dog_fashion = null
|
dog_fashion = null
|
||||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 60)
|
|
||||||
strip_delay = 80
|
strip_delay = 80
|
||||||
|
|
||||||
/obj/item/clothing/head/soft/solgov/marines/command/elite
|
/obj/item/clothing/head/soft/solgov/marines/command/elite
|
||||||
name = "\improper Trans-Solar Federation Specops Lieutenant's cap"
|
name = "\improper Trans-Solar Federation Specops Lieutenant's cap"
|
||||||
desc = "A soft cap worn by marines of the Trans-Solar Federation Specops division. The insignia signifies the wearer bears the rank of a Lieutenant."
|
desc = "A cap worn by marines of the Trans-Solar Federation Specops division. You aren't quite sure how they made this bulletproof, but you are glad it is! The insignia signifies the wearer bears the rank of a Lieutenant."
|
||||||
|
armor= list("melee" = 35, "bullet" = 60, "laser" = 10, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 50, "fire" = 80, "acid" = 80)
|
||||||
icon_state = "solgovcelitesoft"
|
icon_state = "solgovcelitesoft"
|
||||||
item_color = "solgovcelite"
|
item_color = "solgovcelite"
|
||||||
|
resistance_flags = FIRE_PROOF
|
||||||
|
|||||||
@@ -259,3 +259,38 @@
|
|||||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/berserker
|
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/berserker
|
||||||
armor = list(melee = 65, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 100, rad = 100, fire = 80, acid = 80)
|
armor = list(melee = 65, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 100, rad = 100, fire = 80, acid = 80)
|
||||||
slowdown = 0
|
slowdown = 0
|
||||||
|
|
||||||
|
// Solgov
|
||||||
|
|
||||||
|
/obj/item/clothing/head/helmet/space/hardsuit/ert/solgov
|
||||||
|
name = "\improper Trans-Solar Federation Specops Marine helmet"
|
||||||
|
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||||
|
desc = "A helmet worn by marines of the Trans-Solar Federation. Armored, space ready, and fireproof."
|
||||||
|
icon_state = "hardsuit0-solgovmarine"
|
||||||
|
item_state = "hardsuit0-solgovmarine"
|
||||||
|
item_color = "solgovmarine"
|
||||||
|
armor = list("melee" = 35, "bullet" = 60, "laser" = 15, "energy" = 10, "bomb" = 25, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100)
|
||||||
|
|
||||||
|
/obj/item/clothing/suit/space/hardsuit/ert/solgov
|
||||||
|
name = "\improper Trans-Solar Federation Specops Marine hardsuit"
|
||||||
|
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||||
|
desc = "A suit worn by marines of the Trans-Solar Federation. Armored, space ready, and fireproof."
|
||||||
|
icon_state = "ert_solgov_marine"
|
||||||
|
item_state = "ert_solgov_marine"
|
||||||
|
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/solgov
|
||||||
|
slowdown = 0
|
||||||
|
armor = list("melee" = 35, "bullet" = 60, "laser" = 15, "energy" = 10, "bomb" = 25, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100)
|
||||||
|
|
||||||
|
/obj/item/clothing/head/helmet/space/hardsuit/ert/solgov/command
|
||||||
|
name = "\improper Trans-Solar Federation Specops Lieutenant helmet"
|
||||||
|
desc = "A helmet worn by Lieutenants of the Trans-Solar Federation Marines. Has gold highlights to denote the wearer's rank. Armored, space ready, and fireproof."
|
||||||
|
icon_state = "hardsuit0-solgovcommand"
|
||||||
|
item_state = "hardsuit0-solgovcommand"
|
||||||
|
item_color = "solgovcommand"
|
||||||
|
|
||||||
|
/obj/item/clothing/suit/space/hardsuit/ert/solgov/command
|
||||||
|
name = "\improper Trans-Solar Federation Specops Lieutenant hardsuit"
|
||||||
|
desc = "A suit worn by Lieutenants of the Trans-Solar Federation Marines. Has gold highlights to denote the wearer's rank. Armored, space ready, and fireproof."
|
||||||
|
icon_state = "ert_solgov_command"
|
||||||
|
item_state = "ert_solgov_command"
|
||||||
|
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/solgov/command
|
||||||
|
|||||||
@@ -87,6 +87,11 @@
|
|||||||
armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
|
armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
|
||||||
flags = STOPSPRESSUREDMAGE | THICKMATERIAL
|
flags = STOPSPRESSUREDMAGE | THICKMATERIAL
|
||||||
|
|
||||||
|
/obj/item/clothing/head/helmet/space/deathsquad/beret/solgov
|
||||||
|
name = "\improper Trans-Solar Federation commander's beret"
|
||||||
|
desc = "A camouflaged beret adorned with the star of the Trans-Solar Federation, worn by generals of the Trans-Solar Federation."
|
||||||
|
icon_state = "solgovceliteberet"
|
||||||
|
|
||||||
/obj/item/clothing/suit/space/deathsquad/officer
|
/obj/item/clothing/suit/space/deathsquad/officer
|
||||||
name = "officer jacket"
|
name = "officer jacket"
|
||||||
desc = "An armored jacket used in special operations."
|
desc = "An armored jacket used in special operations."
|
||||||
@@ -99,6 +104,12 @@
|
|||||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||||
w_class = WEIGHT_CLASS_NORMAL
|
w_class = WEIGHT_CLASS_NORMAL
|
||||||
|
|
||||||
|
/obj/item/clothing/suit/space/deathsquad/officer/solgov
|
||||||
|
name = "\improper Trans-Solar Federation commander's jacket"
|
||||||
|
icon_state = "solgovcommander"
|
||||||
|
item_state = "solgovcommander"
|
||||||
|
|
||||||
|
|
||||||
//Space santa outfit suit
|
//Space santa outfit suit
|
||||||
/obj/item/clothing/head/helmet/space/santahat
|
/obj/item/clothing/head/helmet/space/santahat
|
||||||
name = "Santa's hat"
|
name = "Santa's hat"
|
||||||
|
|||||||
@@ -129,6 +129,10 @@
|
|||||||
armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30)
|
armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30)
|
||||||
displays_id = 0
|
displays_id = 0
|
||||||
|
|
||||||
|
/obj/item/clothing/under/rank/centcom/captain/solgov
|
||||||
|
name = "\improper Trans-Solar Federation commander's uniform"
|
||||||
|
desc = "Gold trim on space-black cloth, this uniform is worn by generals of the Trans-Solar Federation. It has exotic materials for protection."
|
||||||
|
|
||||||
/obj/item/clothing/under/rank/centcom/blueshield
|
/obj/item/clothing/under/rank/centcom/blueshield
|
||||||
name = "formal blueshield's uniform"
|
name = "formal blueshield's uniform"
|
||||||
desc = "Gold trim on space-black cloth, this uniform bears \"Close Protection\" on the left shoulder. It's got exotic materials for protection."
|
desc = "Gold trim on space-black cloth, this uniform bears \"Close Protection\" on the left shoulder. It's got exotic materials for protection."
|
||||||
|
|||||||
@@ -1470,13 +1470,13 @@
|
|||||||
|
|
||||||
|
|
||||||
/obj/item/clothing/head/fluff/lfbowler //Lightfire: Hyperion
|
/obj/item/clothing/head/fluff/lfbowler //Lightfire: Hyperion
|
||||||
name = "Classy bowler hat"
|
name = "classy bowler hat"
|
||||||
desc = "a very classy looking bowler hat"
|
desc = "A very classy looking bowler hat."
|
||||||
icon = 'icons/obj/custom_items.dmi'
|
icon = 'icons/obj/custom_items.dmi'
|
||||||
icon_state = "bowler_lightfire"
|
icon_state = "bowler_lightfire"
|
||||||
|
|
||||||
/obj/item/clothing/under/fluff/lfvicsuit //Lightfire: Hyperion
|
/obj/item/clothing/under/fluff/lfvicsuit //Lightfire: Hyperion
|
||||||
name = "Classy victorian suit"
|
name = "classy victorian suit"
|
||||||
desc = "A blue and black victorian suit with silver buttons, very fancy!"
|
desc = "A blue and black victorian suit with silver buttons, very fancy!"
|
||||||
icon = 'icons/obj/custom_items.dmi'
|
icon = 'icons/obj/custom_items.dmi'
|
||||||
lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi'
|
lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi'
|
||||||
|
|||||||
@@ -4,46 +4,46 @@
|
|||||||
INVOKE_ASYNC(src, .proc/make_sentient_mob)
|
INVOKE_ASYNC(src, .proc/make_sentient_mob)
|
||||||
|
|
||||||
/datum/event/sentience/proc/make_sentient_mob()
|
/datum/event/sentience/proc/make_sentient_mob()
|
||||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to awaken as a sentient being?", ROLE_SENTIENT, TRUE)
|
|
||||||
var/list/potential = list()
|
var/list/potential = list()
|
||||||
var/sentience_type = SENTIENCE_ORGANIC
|
|
||||||
|
|
||||||
for(var/mob/living/simple_animal/L in GLOB.alive_mob_list)
|
for(var/mob/living/simple_animal/L in GLOB.alive_mob_list)
|
||||||
var/turf/T = get_turf(L)
|
var/turf/T = get_turf(L)
|
||||||
if (!is_station_level(T.z))
|
if(!is_station_level(T.z))
|
||||||
continue
|
continue
|
||||||
if(!(L in GLOB.player_list) && !L.mind && (L.sentience_type == sentience_type))
|
if(!(L in GLOB.player_list) && !L.mind && (L.sentience_type == SENTIENCE_ORGANIC))
|
||||||
potential += L
|
potential += L
|
||||||
|
|
||||||
if(!candidates.len || !potential.len) //if there are no players or simple animals to choose from, then end
|
if(!length(potential)) // If there are somehow no simple animals to choose from, then end.
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
var/mob/living/simple_animal/SA = pick(potential)
|
var/mob/living/simple_animal/SA = pick(potential)
|
||||||
|
|
||||||
|
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to awaken as \a [SA]?", ROLE_SENTIENT, TRUE, source = SA)
|
||||||
|
if(!length(candidates) || QDELETED(SA)) // If there's no candidates or the mob got deleted.
|
||||||
|
return
|
||||||
|
|
||||||
var/mob/SG = pick(candidates)
|
var/mob/SG = pick(candidates)
|
||||||
|
|
||||||
var/sentience_report = "<font size=3><b>NAS Trurl Medium-Priority Update</b></font>"
|
|
||||||
|
|
||||||
var/data = pick("scans from our long-range sensors", "our sophisticated probabilistic models", "our omnipotence", "the communications traffic on your station", "energy emissions we detected", "\[REDACTED\]", "Steve")
|
|
||||||
var/pets = pick("animals", "pets", "simple animals", "lesser lifeforms", "\[REDACTED\]")
|
|
||||||
var/strength = pick("human", "skrell", "vox", "grey", "diona", "IPC", "tajaran", "vulpakanin", "kidan", "plasmaman", "drask",
|
|
||||||
"slime", "monkey", "moderate", "lizard", "security", "command", "clown", "mime", "low", "very low", "greytide", "catgirl", "\[REDACTED\]")
|
|
||||||
|
|
||||||
sentience_report += "<br><br>Based on [data], we believe that one of the station's [pets] has developed [strength] level intelligence, and the ability to communicate."
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SA.key = SG.key
|
SA.key = SG.key
|
||||||
SA.universal_speak = 1
|
SA.universal_speak = TRUE
|
||||||
SA.sentience_act()
|
SA.sentience_act()
|
||||||
SA.can_collar = 1
|
SA.can_collar = TRUE
|
||||||
SA.maxHealth = max(SA.maxHealth, 200)
|
SA.maxHealth = max(SA.maxHealth, 200)
|
||||||
SA.health = SA.maxHealth
|
SA.health = SA.maxHealth
|
||||||
SA.del_on_death = FALSE
|
SA.del_on_death = FALSE
|
||||||
greet_sentient(SA)
|
greet_sentient(SA)
|
||||||
|
|
||||||
|
var/sentience_report = "<font size=3><b>NAS Trurl Medium-Priority Update</b></font>"
|
||||||
|
|
||||||
|
var/data = pick("scans from our long-range sensors", "our sophisticated probabilistic models", "our omnipotence", "the communications traffic on your station", "energy emissions we detected", "\[REDACTED]", "Steve")
|
||||||
|
var/pets = pick("animals", "pets", "simple animals", "lesser lifeforms", "\[REDACTED]")
|
||||||
|
var/strength = pick("human", "skrell", "vox", "grey", "diona", "IPC", "tajaran", "vulpakanin", "kidan", "plasmaman", "drask",
|
||||||
|
"slime", "monkey", "moderate", "lizard", "security", "command", "clown", "mime", "low", "very low", "greytide", "catgirl", "\[REDACTED]")
|
||||||
|
|
||||||
|
sentience_report += "<br><br>Based on [data], we believe that one of the station's [pets] has developed [strength] level intelligence, and the ability to communicate."
|
||||||
print_command_report(sentience_report, "NAS Trurl Update", FALSE)
|
print_command_report(sentience_report, "NAS Trurl Update", FALSE)
|
||||||
|
|
||||||
/datum/event/sentience/proc/greet_sentient(mob/living/carbon/human/M)
|
/datum/event/sentience/proc/greet_sentient(mob/living/carbon/human/M)
|
||||||
to_chat(M, "<span class='userdanger'>Hello world!</span>")
|
to_chat(M, "<span class='userdanger'>Hello world!</span>")
|
||||||
to_chat(M, "<span class='warning'>Due to freak radiation, you have gained \
|
to_chat(M, "<span class='warning'>Due to freak radiation, you have gained \
|
||||||
human level intelligence and the ability to speak and understand \
|
human level intelligence and the ability to speak and understand \
|
||||||
human language!</span>")
|
human language!</span>")
|
||||||
|
|||||||
@@ -274,7 +274,7 @@
|
|||||||
// Bust through windows or other stuff blocking the way
|
// Bust through windows or other stuff blocking the way
|
||||||
if(!target.Enter(holder))
|
if(!target.Enter(holder))
|
||||||
for(var/atom/movable/AM in target)
|
for(var/atom/movable/AM in target)
|
||||||
if(istype(AM, /obj/structure/spacevine) || !AM.density)
|
if(!AM.density || isvineimmune(AM))
|
||||||
continue
|
continue
|
||||||
AM.ex_act(severity)
|
AM.ex_act(severity)
|
||||||
target.ex_act(severity) // vine immunity handled at /mob/ex_act
|
target.ex_act(severity) // vine immunity handled at /mob/ex_act
|
||||||
@@ -697,8 +697,10 @@
|
|||||||
. = ..()
|
. = ..()
|
||||||
|
|
||||||
/proc/isvineimmune(atom/A)
|
/proc/isvineimmune(atom/A)
|
||||||
. = FALSE
|
|
||||||
if(isliving(A))
|
if(isliving(A))
|
||||||
var/mob/living/M = A
|
var/mob/living/M = A
|
||||||
if(("vines" in M.faction) || ("plants" in M.faction))
|
if(("vines" in M.faction) || ("plants" in M.faction))
|
||||||
. = TRUE
|
return TRUE
|
||||||
|
else if(istype(A, /obj/structure/spacevine) || istype(A, /obj/structure/alien/resin/flower_bud_enemy))
|
||||||
|
return TRUE
|
||||||
|
return FALSE
|
||||||
|
|||||||
@@ -139,7 +139,7 @@
|
|||||||
playsound(loc, pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg'), 50, 1, -1)
|
playsound(loc, pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg'), 50, 1, -1)
|
||||||
return BRUTELOSS
|
return BRUTELOSS
|
||||||
|
|
||||||
/obj/item/scythe/pre_attackby(atom/A, mob/living/user, params)
|
/obj/item/scythe/pre_attack(atom/A, mob/living/user, params)
|
||||||
if(swiping || !istype(A, /obj/structure/spacevine) || get_turf(A) == get_turf(user))
|
if(swiping || !istype(A, /obj/structure/spacevine) || get_turf(A) == get_turf(user))
|
||||||
return ..()
|
return ..()
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
new /obj/effect/temp_visual/resonance(T, user, src, burst_time)
|
new /obj/effect/temp_visual/resonance(T, user, src, burst_time)
|
||||||
user.changeNext_move(CLICK_CD_MELEE)
|
user.changeNext_move(CLICK_CD_MELEE)
|
||||||
|
|
||||||
/obj/item/resonator/pre_attackby(atom/target, mob/user, params)
|
/obj/item/resonator/pre_attack(atom/target, mob/user, params)
|
||||||
if(check_allowed_items(target, 1))
|
if(check_allowed_items(target, 1))
|
||||||
CreateResonance(target, user)
|
CreateResonance(target, user)
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|||||||
@@ -247,7 +247,7 @@
|
|||||||
|
|
||||||
to_chat(user, "<span class='notice'>You release the wisp. It begins to bob around your head.</span>")
|
to_chat(user, "<span class='notice'>You release the wisp. It begins to bob around your head.</span>")
|
||||||
icon_state = "lantern"
|
icon_state = "lantern"
|
||||||
wisp.orbit(user, 20)
|
INVOKE_ASYNC(wisp, /atom/movable/.proc/orbit, user, 20)
|
||||||
set_light(0)
|
set_light(0)
|
||||||
|
|
||||||
user.update_sight()
|
user.update_sight()
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
|||||||
real_name = name
|
real_name = name
|
||||||
|
|
||||||
//starts ghosts off with all HUDs.
|
//starts ghosts off with all HUDs.
|
||||||
toggle_all_huds_on()
|
toggle_all_huds_on(body)
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/mob/dead/observer/Destroy()
|
/mob/dead/observer/Destroy()
|
||||||
@@ -323,10 +323,23 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
|||||||
return
|
return
|
||||||
GLOB.ghost_hud_panel.ui_interact(src)
|
GLOB.ghost_hud_panel.ui_interact(src)
|
||||||
|
|
||||||
/mob/dead/observer/proc/toggle_all_huds_on()
|
/**
|
||||||
|
* Toggles on all HUDs for the ghost player.
|
||||||
|
*
|
||||||
|
* Enables antag HUD only if the ghost belongs to an admin.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * user - A reference to the ghost's old mob. This argument is required since `src` does not have a `client` at this point.
|
||||||
|
*/
|
||||||
|
/mob/dead/observer/proc/toggle_all_huds_on(mob/user)
|
||||||
show_me_the_hud(DATA_HUD_DIAGNOSTIC)
|
show_me_the_hud(DATA_HUD_DIAGNOSTIC)
|
||||||
show_me_the_hud(DATA_HUD_SECURITY_ADVANCED)
|
show_me_the_hud(DATA_HUD_SECURITY_ADVANCED)
|
||||||
show_me_the_hud(DATA_HUD_MEDICAL_ADVANCED)
|
show_me_the_hud(DATA_HUD_MEDICAL_ADVANCED)
|
||||||
|
if(!check_rights((R_ADMIN | R_MOD), FALSE, user))
|
||||||
|
return
|
||||||
|
antagHUD = TRUE
|
||||||
|
for(var/datum/atom_hud/antag/H in GLOB.huds)
|
||||||
|
H.add_hud_to(src)
|
||||||
|
|
||||||
/mob/dead/observer/verb/set_dnr()
|
/mob/dead/observer/verb/set_dnr()
|
||||||
set name = "Set DNR"
|
set name = "Set DNR"
|
||||||
|
|||||||
@@ -486,6 +486,14 @@
|
|||||||
flags = RESTRICTED | HIVEMIND | NOBABEL
|
flags = RESTRICTED | HIVEMIND | NOBABEL
|
||||||
follow = TRUE
|
follow = TRUE
|
||||||
|
|
||||||
|
/datum/language/terrorspider/broadcast(mob/living/speaker, message, speaker_mask)
|
||||||
|
if(isterrorspider(speaker))
|
||||||
|
var/mob/living/simple_animal/hostile/poison/terror_spider/T = speaker
|
||||||
|
if(T.loudspeaker)
|
||||||
|
..(speaker, "<font size=3><b>[message]</b></font>")
|
||||||
|
return
|
||||||
|
..(speaker, message)
|
||||||
|
|
||||||
/datum/language/ling
|
/datum/language/ling
|
||||||
name = "Changeling"
|
name = "Changeling"
|
||||||
desc = "Although they are normally wary and suspicious of each other, changelings can commune over a distance."
|
desc = "Although they are normally wary and suspicious of each other, changelings can commune over a distance."
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ GLOBAL_LIST_EMPTY(empty_playable_ai_cores)
|
|||||||
if(alert("WARNING: This will immediately wipe your core and ghost you, removing your character from the round permanently (similar to cryo and robotic storage). Are you entirely sure you want to do this?",
|
if(alert("WARNING: This will immediately wipe your core and ghost you, removing your character from the round permanently (similar to cryo and robotic storage). Are you entirely sure you want to do this?",
|
||||||
"Wipe Core", "No", "No", "Yes") != "Yes")
|
"Wipe Core", "No", "No", "Yes") != "Yes")
|
||||||
return
|
return
|
||||||
|
cryo_AI()
|
||||||
|
|
||||||
// We warned you.
|
/mob/living/silicon/ai/proc/cryo_AI()
|
||||||
GLOB.empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(loc)
|
GLOB.empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(loc)
|
||||||
GLOB.global_announcer.autosay("[src] has been moved to intelligence storage.", "Artificial Intelligence Oversight")
|
GLOB.global_announcer.autosay("[src] has been moved to intelligence storage.", "Artificial Intelligence Oversight")
|
||||||
|
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
|||||||
else
|
else
|
||||||
to_chat(src, "<span class='boldannounce'>Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug.</span>")
|
to_chat(src, "<span class='boldannounce'>Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug.</span>")
|
||||||
ghostize()
|
ghostize()
|
||||||
error("A borg has been destroyed, but its MMI lacked a brainmob, so the mind could not be transferred. Player: [ckey].")
|
log_runtime(EXCEPTION("A borg has been destroyed, but its MMI lacked a brainmob, so the mind could not be transferred. Player: [ckey]."), src)
|
||||||
mmi = null
|
mmi = null
|
||||||
if(connected_ai)
|
if(connected_ai)
|
||||||
connected_ai.connected_robots -= src
|
connected_ai.connected_robots -= src
|
||||||
|
|||||||
@@ -129,6 +129,7 @@
|
|||||||
status_flags = 0
|
status_flags = 0
|
||||||
construct_type = "juggernaut"
|
construct_type = "juggernaut"
|
||||||
mob_size = MOB_SIZE_LARGE
|
mob_size = MOB_SIZE_LARGE
|
||||||
|
move_resist = MOVE_FORCE_STRONG
|
||||||
construct_spells = list(/obj/effect/proc_holder/spell/targeted/night_vision, /obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall)
|
construct_spells = list(/obj/effect/proc_holder/spell/targeted/night_vision, /obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall)
|
||||||
force_threshold = 11
|
force_threshold = 11
|
||||||
playstyle_string = "<b>You are a Juggernaut. Though slow, your shell can withstand extreme punishment, \
|
playstyle_string = "<b>You are a Juggernaut. Though slow, your shell can withstand extreme punishment, \
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
icon_living = "cow"
|
icon_living = "cow"
|
||||||
icon_dead = "cow_dead"
|
icon_dead = "cow_dead"
|
||||||
icon_gib = "cow_gib"
|
icon_gib = "cow_gib"
|
||||||
speak = list("moo?","moo","MOOOOOO")
|
speak = list("Moo?","Moo","MOOOOOO")
|
||||||
speak_emote = list("moos","moos hauntingly")
|
speak_emote = list("moos","moos hauntingly")
|
||||||
emote_hear = list("brays")
|
emote_hear = list("brays")
|
||||||
emote_see = list("shakes its head")
|
emote_see = list("shakes its head")
|
||||||
|
|||||||
@@ -56,6 +56,12 @@
|
|||||||
for(var/obj/structure/spider/S in range(1, get_turf(src)))
|
for(var/obj/structure/spider/S in range(1, get_turf(src)))
|
||||||
return S
|
return S
|
||||||
|
|
||||||
|
/mob/living/simple_animal/hostile/poison/giant_spider/death(gibbed)
|
||||||
|
. = ..()
|
||||||
|
if(!.)
|
||||||
|
return FALSE
|
||||||
|
SSmobs.giant_spiders--
|
||||||
|
|
||||||
//nursemaids - these create webs and eggs
|
//nursemaids - these create webs and eggs
|
||||||
/mob/living/simple_animal/hostile/poison/giant_spider/nurse
|
/mob/living/simple_animal/hostile/poison/giant_spider/nurse
|
||||||
desc = "Furry and black, it makes you shudder to look at it. This one has brilliant green eyes."
|
desc = "Furry and black, it makes you shudder to look at it. This one has brilliant green eyes."
|
||||||
|
|||||||
@@ -408,7 +408,7 @@ Difficulty: Hard
|
|||||||
/obj/effect/decal/cleanable/blood/gibs/bubblegum/can_bloodcrawl_in()
|
/obj/effect/decal/cleanable/blood/gibs/bubblegum/can_bloodcrawl_in()
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A, visual_effect_icon)
|
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
|
||||||
if(!charging)
|
if(!charging)
|
||||||
..()
|
..()
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
regen_points_per_kill = 200 // >2x normal, since they're food reprocessors
|
regen_points_per_kill = 200 // >2x normal, since they're food reprocessors
|
||||||
idle_ventcrawl_chance = 5
|
idle_ventcrawl_chance = 5
|
||||||
spider_tier = TS_TIER_3
|
spider_tier = TS_TIER_3
|
||||||
|
loudspeaker = TRUE
|
||||||
spider_opens_doors = 2
|
spider_opens_doors = 2
|
||||||
web_type = /obj/structure/spider/terrorweb/mother
|
web_type = /obj/structure/spider/terrorweb/mother
|
||||||
var/datum/action/innate/terrorspider/ventsmash/ventsmash_action
|
var/datum/action/innate/terrorspider/ventsmash/ventsmash_action
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
environment_smash = ENVIRONMENT_SMASH_RWALLS
|
environment_smash = ENVIRONMENT_SMASH_RWALLS
|
||||||
idle_ventcrawl_chance = 0
|
idle_ventcrawl_chance = 0
|
||||||
spider_tier = TS_TIER_3
|
spider_tier = TS_TIER_3
|
||||||
|
loudspeaker = TRUE
|
||||||
spider_opens_doors = 2
|
spider_opens_doors = 2
|
||||||
web_type = /obj/structure/spider/terrorweb/purple
|
web_type = /obj/structure/spider/terrorweb/purple
|
||||||
ai_spins_webs = FALSE
|
ai_spins_webs = FALSE
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
projectilesound = 'sound/weapons/pierce.ogg'
|
projectilesound = 'sound/weapons/pierce.ogg'
|
||||||
projectiletype = /obj/item/projectile/terrorqueenspit
|
projectiletype = /obj/item/projectile/terrorqueenspit
|
||||||
spider_tier = TS_TIER_4
|
spider_tier = TS_TIER_4
|
||||||
|
loudspeaker = TRUE
|
||||||
spider_opens_doors = 2
|
spider_opens_doors = 2
|
||||||
web_type = /obj/structure/spider/terrorweb/queen
|
web_type = /obj/structure/spider/terrorweb/queen
|
||||||
var/spider_spawnfrequency = 1200 // 120 seconds. Default for player queens and NPC queens on station. Awaymission queens have this changed in New()
|
var/spider_spawnfrequency = 1200 // 120 seconds. Default for player queens and NPC queens on station. Awaymission queens have this changed in New()
|
||||||
|
|||||||
@@ -137,6 +137,8 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
|
|||||||
var/killcount = 0
|
var/killcount = 0
|
||||||
var/busy = 0 // leave this alone!
|
var/busy = 0 // leave this alone!
|
||||||
var/spider_tier = TS_TIER_1 // 1 for red,gray,green. 2 for purple,black,white, 3 for prince, mother. 4 for queen
|
var/spider_tier = TS_TIER_1 // 1 for red,gray,green. 2 for purple,black,white, 3 for prince, mother. 4 for queen
|
||||||
|
/// Does this terror speak loudly on the terror hivemind?
|
||||||
|
var/loudspeaker = FALSE
|
||||||
var/hasdied = 0
|
var/hasdied = 0
|
||||||
var/list/spider_special_drops = list()
|
var/list/spider_special_drops = list()
|
||||||
var/attackstep = 0
|
var/attackstep = 0
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
melee_damage_lower = 5
|
melee_damage_lower = 5
|
||||||
melee_damage_upper = 15
|
melee_damage_upper = 15
|
||||||
spider_tier = TS_TIER_2
|
spider_tier = TS_TIER_2
|
||||||
|
loudspeaker = TRUE
|
||||||
web_type = /obj/structure/spider/terrorweb/white
|
web_type = /obj/structure/spider/terrorweb/white
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
name = "venus human trap"
|
name = "venus human trap"
|
||||||
desc = "Now you know how the fly feels."
|
desc = "Now you know how the fly feels."
|
||||||
icon_state = "venus_human_trap"
|
icon_state = "venus_human_trap"
|
||||||
|
icon_living = "venus_human_trap"
|
||||||
mob_biotypes = MOB_ORGANIC | MOB_PLANT
|
mob_biotypes = MOB_ORGANIC | MOB_PLANT
|
||||||
layer = MOB_LAYER + 0.9
|
layer = MOB_LAYER + 0.9
|
||||||
health = 50
|
health = 50
|
||||||
|
|||||||
@@ -20,10 +20,10 @@
|
|||||||
spawn() alert("You have logged in already with another key this round, please log out of this one NOW or risk being banned!")
|
spawn() alert("You have logged in already with another key this round, please log out of this one NOW or risk being banned!")
|
||||||
if(matches)
|
if(matches)
|
||||||
if(M.client)
|
if(M.client)
|
||||||
message_admins("<font color='red'><B>Notice: </B><font color='blue'><A href='?src=[usr.UID()];priv_msg=[src.client.ckey]'>[key_name_admin(src)]</A> has the same [matches] as <A href='?src=[usr.UID()];priv_msg=[M.client.ckey]'>[key_name_admin(M)]</A>.</font>", 1)
|
message_admins("<font color='red'><B>Notice: </B><font color='#EB4E00'><A href='?src=[usr.UID()];priv_msg=[src.client.ckey]'>[key_name_admin(src)]</A> has the same [matches] as <A href='?src=[usr.UID()];priv_msg=[M.client.ckey]'>[key_name_admin(M)]</A>.</font>", 1)
|
||||||
log_adminwarn("Notice: [key_name(src)] has the same [matches] as [key_name(M)].")
|
log_adminwarn("Notice: [key_name(src)] has the same [matches] as [key_name(M)].")
|
||||||
else
|
else
|
||||||
message_admins("<font color='red'><B>Notice: </B><font color='blue'><A href='?src=[usr.UID()];priv_msg=[src.client.ckey]'>[key_name_admin(src)]</A> has the same [matches] as [key_name_admin(M)] (no longer logged in). </font>", 1)
|
message_admins("<font color='red'><B>Notice: </B><font color='#EB4E00'><A href='?src=[usr.UID()];priv_msg=[src.client.ckey]'>[key_name_admin(src)]</A> has the same [matches] as [key_name_admin(M)] (no longer logged in). </font>", 1)
|
||||||
log_adminwarn("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).")
|
log_adminwarn("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).")
|
||||||
|
|
||||||
/mob/Login()
|
/mob/Login()
|
||||||
|
|||||||
@@ -116,7 +116,9 @@
|
|||||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("[question]?", poll_time = 10 SECONDS, min_hours = minhours, source = M)
|
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("[question]?", poll_time = 10 SECONDS, min_hours = minhours, source = M)
|
||||||
var/mob/dead/observer/theghost = null
|
var/mob/dead/observer/theghost = null
|
||||||
|
|
||||||
if(LAZYLEN(candidates))
|
if(length(candidates))
|
||||||
|
if(QDELETED(M))
|
||||||
|
return
|
||||||
theghost = pick(candidates)
|
theghost = pick(candidates)
|
||||||
to_chat(M, "Your mob has been taken over by a ghost!")
|
to_chat(M, "Your mob has been taken over by a ghost!")
|
||||||
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)])")
|
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)])")
|
||||||
|
|||||||
@@ -172,7 +172,7 @@
|
|||||||
if(alert(src,"Are you sure you wish to observe? You cannot normally join the round after doing this!","Player Setup","Yes","No") == "Yes")
|
if(alert(src,"Are you sure you wish to observe? You cannot normally join the round after doing this!","Player Setup","Yes","No") == "Yes")
|
||||||
if(!client)
|
if(!client)
|
||||||
return 1
|
return 1
|
||||||
var/mob/dead/observer/observer = new()
|
var/mob/dead/observer/observer = new(src)
|
||||||
src << browse(null, "window=playersetup")
|
src << browse(null, "window=playersetup")
|
||||||
spawning = 1
|
spawning = 1
|
||||||
stop_sound_channel(CHANNEL_LOBBYMUSIC)
|
stop_sound_channel(CHANNEL_LOBBYMUSIC)
|
||||||
|
|||||||
@@ -80,6 +80,7 @@
|
|||||||
/datum/job/chaplain,
|
/datum/job/chaplain,
|
||||||
/datum/job/ntnavyofficer,
|
/datum/job/ntnavyofficer,
|
||||||
/datum/job/ntspecops,
|
/datum/job/ntspecops,
|
||||||
|
/datum/job/ntspecops/solgovspecops,
|
||||||
/datum/job/civilian,
|
/datum/job/civilian,
|
||||||
/datum/job/syndicateofficer
|
/datum/job/syndicateofficer
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -730,7 +730,20 @@
|
|||||||
return
|
return
|
||||||
if(moveable && default_unfasten_wrench(user, I, time = 20))
|
if(moveable && default_unfasten_wrench(user, I, time = 20))
|
||||||
return
|
return
|
||||||
if(user.drop_item())
|
if(istype(I, /obj/item/scalpel/supermatter))
|
||||||
|
var/obj/item/scalpel/supermatter/scalpel = I
|
||||||
|
to_chat(user, "<span class='notice'>You carefully begin to scrape [src] with [I]...</span>")
|
||||||
|
if(I.use_tool(src, user, 10 SECONDS, volume = 100))
|
||||||
|
if(scalpel.uses_left)
|
||||||
|
to_chat(user, "<span class='danger'>You extract a sliver from [src], and it begins to react violently!</span>")
|
||||||
|
new /obj/item/nuke_core/supermatter_sliver(drop_location())
|
||||||
|
matter_power += 800
|
||||||
|
scalpel.uses_left--
|
||||||
|
if(!scalpel.uses_left)
|
||||||
|
to_chat(user, "<span class='boldwarning'>A tiny piece of [I] falls off, rendering it useless!</span>")
|
||||||
|
else
|
||||||
|
to_chat(user, "<span class='warning'>You fail to extract a sliver from [src]! [I] isn't sharp enough anymore.</span>")
|
||||||
|
else if(user.drop_item())
|
||||||
user.visible_message("<span class='danger'>As [user] touches [src] with \a [I], silence fills the room...</span>",\
|
user.visible_message("<span class='danger'>As [user] touches [src] with \a [I], silence fills the room...</span>",\
|
||||||
"<span class='userdanger'>You touch [src] with [I], and everything suddenly goes silent.</span>\n<span class='notice'>[I] flashes into dust as you flinch away from [src].</span>",\
|
"<span class='userdanger'>You touch [src] with [I], and everything suddenly goes silent.</span>\n<span class='notice'>[I] flashes into dust as you flinch away from [src].</span>",\
|
||||||
"<span class='italics'>Everything suddenly goes silent.</span>")
|
"<span class='italics'>Everything suddenly goes silent.</span>")
|
||||||
|
|||||||
@@ -78,6 +78,8 @@
|
|||||||
for(var/atom/T in get_turf(D))
|
for(var/atom/T in get_turf(D))
|
||||||
D.reagents.reaction(T)
|
D.reagents.reaction(T)
|
||||||
sleep(3)
|
sleep(3)
|
||||||
|
if(QDELETED(D))
|
||||||
|
return
|
||||||
qdel(D)
|
qdel(D)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -153,10 +153,14 @@
|
|||||||
resistance_flags = FLAMMABLE
|
resistance_flags = FLAMMABLE
|
||||||
var/static/list/no_wrap = list(/obj/item/smallDelivery, /obj/structure/bigDelivery, /obj/item/evidencebag, /obj/structure/closet/body_bag, /obj/item/twohanded/required)
|
var/static/list/no_wrap = list(/obj/item/smallDelivery, /obj/structure/bigDelivery, /obj/item/evidencebag, /obj/structure/closet/body_bag, /obj/item/twohanded/required)
|
||||||
|
|
||||||
/obj/item/stack/packageWrap/afterattack(obj/target as obj, mob/user as mob, proximity)
|
/obj/item/stack/packageWrap/pre_attack(atom/A, mob/living/user, params)
|
||||||
if(!proximity) return
|
. = ..()
|
||||||
if(!istype(target)) //this really shouldn't be necessary (but it is). -Pete
|
if(!in_range(A, user))
|
||||||
return
|
return
|
||||||
|
if(!isobj(A))
|
||||||
|
return
|
||||||
|
var/obj/target = A
|
||||||
|
|
||||||
if(is_type_in_list(target, no_wrap))
|
if(is_type_in_list(target, no_wrap))
|
||||||
return
|
return
|
||||||
if(target.anchored)
|
if(target.anchored)
|
||||||
@@ -166,62 +170,61 @@
|
|||||||
|
|
||||||
if(istype(target, /obj/item) && !(istype(target, /obj/item/storage) && !istype(target,/obj/item/storage/box) && !istype(target, /obj/item/shippingPackage)))
|
if(istype(target, /obj/item) && !(istype(target, /obj/item/storage) && !istype(target,/obj/item/storage/box) && !istype(target, /obj/item/shippingPackage)))
|
||||||
var/obj/item/O = target
|
var/obj/item/O = target
|
||||||
if(use(1))
|
if(!use(1))
|
||||||
var/obj/item/smallDelivery/P = new /obj/item/smallDelivery(get_turf(O.loc)) //Aaannd wrap it up!
|
return FALSE
|
||||||
if(!istype(O.loc, /turf))
|
var/obj/item/smallDelivery/P = new /obj/item/smallDelivery(get_turf(O.loc)) //Aaannd wrap it up!
|
||||||
if(user.client)
|
if(!isturf(O.loc))
|
||||||
user.client.screen -= O
|
if(user.client)
|
||||||
P.wrapped = O
|
user.client.screen -= O
|
||||||
O.loc = P
|
P.wrapped = O
|
||||||
var/i = round(O.w_class)
|
O.loc = P
|
||||||
if(i in list(1,2,3,4,5))
|
var/i = round(O.w_class)
|
||||||
P.icon_state = "deliverycrate[i]"
|
if(i in list(1,2,3,4,5))
|
||||||
P.w_class = i
|
P.icon_state = "deliverycrate[i]"
|
||||||
P.add_fingerprint(usr)
|
P.w_class = i
|
||||||
O.add_fingerprint(usr)
|
P.add_fingerprint(user)
|
||||||
add_fingerprint(usr)
|
O.add_fingerprint(user)
|
||||||
else
|
add_fingerprint(user)
|
||||||
return
|
|
||||||
else if(istype(target, /obj/structure/closet/crate))
|
else if(istype(target, /obj/structure/closet/crate))
|
||||||
var/obj/structure/closet/crate/O = target
|
var/obj/structure/bigDelivery/D = wrap_closet(target, user)
|
||||||
if(O.opened)
|
if(!D)
|
||||||
return
|
return FALSE
|
||||||
if(amount >= 3 && do_after_once(user, 15, target = target))
|
D.icon_state = "deliverycrate"
|
||||||
if(O.opened || !use(3))
|
|
||||||
return
|
else if(istype(target, /obj/structure/closet))
|
||||||
var/obj/structure/bigDelivery/P = new /obj/structure/bigDelivery(get_turf(O.loc))
|
var/obj/structure/closet/C = target
|
||||||
P.icon_state = "deliverycrate"
|
var/obj/structure/bigDelivery/D = wrap_closet(target, user)
|
||||||
P.wrapped = O
|
if(!D)
|
||||||
O.loc = P
|
return FALSE
|
||||||
else
|
D.init_welded = C.welded
|
||||||
to_chat(user, "<span class='notice'>You need more paper.</span>")
|
C.welded = TRUE
|
||||||
return
|
|
||||||
else if(istype (target, /obj/structure/closet))
|
|
||||||
var/obj/structure/closet/O = target
|
|
||||||
if(O.opened)
|
|
||||||
return
|
|
||||||
if(amount >= 3 && do_after_once(user, 15, target = target))
|
|
||||||
if(O.opened || !use(3))
|
|
||||||
return
|
|
||||||
var/obj/structure/bigDelivery/P = new /obj/structure/bigDelivery(get_turf(O.loc))
|
|
||||||
P.wrapped = O
|
|
||||||
P.init_welded = O.welded
|
|
||||||
O.welded = 1
|
|
||||||
O.loc = P
|
|
||||||
else
|
|
||||||
to_chat(user, "<span class='notice'>You need more paper.</span>")
|
|
||||||
return
|
|
||||||
else
|
else
|
||||||
to_chat(user, "<span class='notice'>The object you are trying to wrap is unsuitable for the sorting machinery.</span>")
|
to_chat(user, "<span class='notice'>The object you are trying to wrap is unsuitable for the sorting machinery.</span>")
|
||||||
return
|
return FALSE
|
||||||
|
|
||||||
user.visible_message("<span class='notice'>[user] wraps [target].</span>")
|
user.visible_message("<span class='notice'>[user] wraps [target].</span>")
|
||||||
user.create_attack_log("<font color='blue'>Has used [name] on [target]</font>")
|
user.create_attack_log("<font color='blue'>Has used [name] on [target]</font>")
|
||||||
add_attack_logs(user, target, "used [name]", ATKLOG_ALL)
|
add_attack_logs(user, target, "used [name]", ATKLOG_ALL)
|
||||||
|
|
||||||
if(amount <= 0 && !src.loc) //if we used our last wrapping paper, drop a cardboard tube
|
if(amount <= 0 && QDELETED(src)) //if we used our last wrapping paper, drop a cardboard tube
|
||||||
new /obj/item/c_tube( get_turf(user) )
|
var/obj/item/c_tube/T = new(get_turf(user))
|
||||||
return
|
user.put_in_active_hand(T)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
// Separate proc to avoid copy pasting the code twice
|
||||||
|
/obj/item/stack/packageWrap/proc/wrap_closet(obj/structure/closet/C, mob/user)
|
||||||
|
if(C.opened)
|
||||||
|
return
|
||||||
|
if(amount < 3)
|
||||||
|
to_chat(user, "<span class='warning'>You need more paper.</span>")
|
||||||
|
return
|
||||||
|
if(!do_after_once(user, 1.5 SECONDS, target = C) || C.opened || !use(3)) // Checking these again since it's after a delay
|
||||||
|
return
|
||||||
|
var/obj/structure/bigDelivery/P = new(get_turf(C))
|
||||||
|
P.wrapped = C
|
||||||
|
C.loc = P
|
||||||
|
return P
|
||||||
|
|
||||||
/obj/item/destTagger
|
/obj/item/destTagger
|
||||||
name = "destination tagger"
|
name = "destination tagger"
|
||||||
|
|||||||
@@ -205,7 +205,7 @@
|
|||||||
var/ghostmsg = "Play as [SM.name], pet of [user.name]?"
|
var/ghostmsg = "Play as [SM.name], pet of [user.name]?"
|
||||||
var/list/candidates = SSghost_spawns.poll_candidates(ghostmsg, ROLE_SENTIENT, FALSE, 10 SECONDS, source = M)
|
var/list/candidates = SSghost_spawns.poll_candidates(ghostmsg, ROLE_SENTIENT, FALSE, 10 SECONDS, source = M)
|
||||||
|
|
||||||
if(!src)
|
if(QDELETED(src) || QDELETED(SM))
|
||||||
return
|
return
|
||||||
|
|
||||||
if(candidates.len)
|
if(candidates.len)
|
||||||
|
|||||||
@@ -858,7 +858,7 @@
|
|||||||
next_request = world.time + 60 SECONDS //1 minute cooldown
|
next_request = world.time + 60 SECONDS //1 minute cooldown
|
||||||
to_chat(usr, "<span class='notice'>Your request has been recieved by Centcom.</span>")
|
to_chat(usr, "<span class='notice'>Your request has been recieved by Centcom.</span>")
|
||||||
log_admin("[key_name(usr)] requested to move the transport ferry to Centcom.")
|
log_admin("[key_name(usr)] requested to move the transport ferry to Centcom.")
|
||||||
message_admins("<b>FERRY: <font color='blue'>[key_name_admin(usr)] (<A HREF='?_src_=holder;secretsfun=moveferry'>Move Ferry</a>)</b> is requesting to move the transport ferry to Centcom.</font>")
|
message_admins("<b>FERRY: <font color='#EB4E00'>[key_name_admin(usr)] (<A HREF='?_src_=holder;secretsfun=moveferry'>Move Ferry</a>)</b> is requesting to move the transport ferry to Centcom.</font>")
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user