Merge branch 'master' into upstream-merge-33917

This commit is contained in:
LetterJay
2018-01-02 17:14:53 -06:00
committed by GitHub
288 changed files with 1526 additions and 1186 deletions

View File

@@ -51,7 +51,7 @@ As mentioned before, you are expected to follow these specifications in order to
### Object Oriented Code
As BYOND's Dream Maker (henceforth "DM") is an object-oriented language, code must be object-oriented when possible in order to be more flexible when adding content to it. If you don't know what "object-oriented" means, we highly recommend you do some light research to grasp the basics.
### All BYOND paths must contain the full path.
### All BYOND paths must contain the full path
(i.e. absolute pathing)
DM will allow you nest almost any type keyword into a block, such as:
@@ -105,7 +105,7 @@ The previous code made compliant:
code
```
### No overriding type safety checks.
### No overriding type safety checks
The use of the : operator to override type safety checks is not allowed. You must cast the variable to the proper type.
### Type paths must begin with a /
@@ -264,6 +264,8 @@ This prevents nesting levels from getting deeper then they need to be.
* If you used regex to replace code during development of your code, post the regex in your PR for the benefit of future developers and downstream users.
* Changes to the `/config` tree must be made in a way that allows for updating server deployments while preserving previous behaviour. This is due to the fact that the config tree is to be considered owned by the user and not necessarily updated alongside the remainder of the code. The code to preserve previous behaviour may be removed at some point in the future given the OK by maintainers.
#### Enforced not enforced
The following coding styles are not only not enforced at all, but are generally frowned upon to change for little to no reason:

View File

@@ -37,7 +37,7 @@ hassle if you want to make any changes at all, so it's not recommended.)
## INSTALLATION
First-time installation should be fairly straightforward. First, you'll need
BYOND installed. You can get it from http://www.byond.com/. Once you've done
BYOND installed. You can get it from https://www.byond.com/download. Once you've done
that, extract the game files to wherever you want to keep them. This is a
sourcecode-only release, so the next step is to compile the server files.
Open tgstation.dme by double-clicking it, open the Build menu, and click

View File

@@ -22174,7 +22174,8 @@
req_access_txt = "20"
},
/obj/structure/window/reinforced,
/obj/item/aiModule/core/full/corp,
/obj/effect/spawner/lootdrop/aimodule_harmless,
/obj/effect/spawner/lootdrop/aimodule_neutral,
/obj/structure/window/reinforced{
dir = 1
},
@@ -22235,7 +22236,7 @@
},
/obj/item/aiModule/reset/purge,
/obj/structure/window/reinforced,
/obj/item/aiModule/core/full/antimov,
/obj/effect/spawner/lootdrop/aimodule_harmful,
/obj/structure/window/reinforced{
dir = 1
},

View File

@@ -54219,14 +54219,10 @@
name = "Core Modules";
req_access_txt = "20"
},
/obj/item/aiModule/core/full/paladin{
pixel_x = 3;
pixel_y = 3
},
/obj/item/aiModule/core/full/asimov,
/obj/item/aiModule/core/full/corp{
pixel_x = -3;
pixel_y = -3
/obj/effect/spawner/lootdrop/aimodule_harmless{
fan_out_items = 1;
lootdoubles = 0;
lootcount = 3
},
/obj/structure/sign/nanotrasen{
pixel_x = -32
@@ -54279,12 +54275,12 @@
name = "Core Modules";
req_access_txt = "20"
},
/obj/item/aiModule/core/full/antimov{
pixel_x = 3;
pixel_y = 3
/obj/effect/spawner/lootdrop/aimodule_harmful{
fan_out_items = 1;
lootdoubles = 0;
lootcount = 2
},
/obj/item/aiModule/supplied/oxygen,
/obj/item/aiModule/supplied/protectStation{
/obj/item/aiModule/supplied/oxygen{
pixel_x = -3;
pixel_y = -3
},
@@ -55144,6 +55140,10 @@
pixel_y = 3
},
/obj/item/aiModule/core/full/custom,
/obj/item/aiModule/core/full/asimov{
pixel_x = -3;
pixel_y = -3
},
/turf/open/floor/plasteel/vault{
dir = 8
},
@@ -55226,7 +55226,7 @@
req_access_txt = "20"
},
/obj/structure/window/reinforced,
/obj/item/aiModule/core/full/tyrant{
/obj/item/aiModule/supplied/protectStation{
pixel_x = 3;
pixel_y = 3
},
@@ -57252,14 +57252,10 @@
/area/ai_monitored/turret_protected/ai_upload)
"clQ" = (
/obj/structure/table/reinforced,
/obj/item/aiModule/core/full/drone{
pixel_x = 3;
pixel_y = 3
},
/obj/item/aiModule/core/full/reporter,
/obj/item/aiModule/core/full/liveandletlive{
pixel_x = -3;
pixel_y = -3
/obj/effect/spawner/lootdrop/aimodule_neutral{
fan_out_items = 1;
lootdoubles = 0;
lootcount = 3
},
/turf/open/floor/plasteel/vault{
dir = 8

View File

@@ -18443,6 +18443,7 @@
"aMG" = (
/obj/structure/table,
/obj/item/aiModule/core/full/asimov,
/obj/effect/spawner/lootdrop/aimodule_harmless,
/obj/item/aiModule/core/freeformcore,
/obj/machinery/door/window{
base_state = "right";
@@ -18452,7 +18453,7 @@
req_access_txt = "20"
},
/obj/structure/window/reinforced,
/obj/item/aiModule/core/full/corp,
/obj/effect/spawner/lootdrop/aimodule_neutral,
/obj/item/aiModule/core/full/custom,
/obj/machinery/flasher{
pixel_y = 24;
@@ -18477,7 +18478,7 @@
pixel_y = 24;
id = "AI"
},
/obj/item/aiModule/core/full/antimov,
/obj/effect/spawner/lootdrop/aimodule_harmful,
/obj/item/aiModule/supplied/oxygen,
/obj/item/aiModule/supplied/protectStation,
/obj/item/aiModule/zeroth/oneHuman,

View File

@@ -2376,14 +2376,10 @@
name = "Core Modules";
req_access_txt = "20"
},
/obj/item/aiModule/core/full/paladin{
pixel_x = 3;
pixel_y = 3
},
/obj/item/aiModule/core/full/asimov,
/obj/item/aiModule/core/full/corp{
pixel_x = -3;
pixel_y = -3
/obj/effect/spawner/lootdrop/aimodule_harmless{
fan_out_items = 1;
lootdoubles = 0;
lootcount = 3
},
/obj/structure/sign/nanotrasen{
pixel_x = -32
@@ -2499,12 +2495,12 @@
name = "Core Modules";
req_access_txt = "20"
},
/obj/item/aiModule/core/full/antimov{
pixel_x = 3;
pixel_y = 3
/obj/effect/spawner/lootdrop/aimodule_harmful{
fan_out_items = 1;
lootdoubles = 0;
lootcount = 2
},
/obj/item/aiModule/supplied/oxygen,
/obj/item/aiModule/supplied/protectStation{
/obj/item/aiModule/supplied/oxygen{
pixel_x = -3;
pixel_y = -3
},
@@ -2875,6 +2871,10 @@
pixel_y = 3
},
/obj/item/aiModule/core/full/custom,
/obj/item/aiModule/core/full/asimov{
pixel_x = -3;
pixel_y = -3
},
/obj/machinery/camera{
c_tag = "AI Core - Port";
dir = 4;
@@ -2900,7 +2900,7 @@
req_access_txt = "20"
},
/obj/structure/window/reinforced,
/obj/item/aiModule/core/full/tyrant{
/obj/item/aiModule/supplied/protectStation{
pixel_x = 3;
pixel_y = 3
},
@@ -4361,14 +4361,10 @@
/area/ai_monitored/turret_protected/ai)
"ahV" = (
/obj/structure/table/reinforced,
/obj/item/aiModule/core/full/drone{
pixel_x = 3;
pixel_y = 3
},
/obj/item/aiModule/core/full/reporter,
/obj/item/aiModule/core/full/liveandletlive{
pixel_x = -3;
pixel_y = -3
/obj/effect/spawner/lootdrop/aimodule_neutral{
fan_out_items = 1;
lootdoubles = 0;
lootcount = 3
},
/turf/open/floor/plasteel/vault{
dir = 8
@@ -23737,7 +23733,6 @@
/obj/structure/chair/office/light{
dir = 1
},
/obj/effect/landmark/start/chemist,
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
/area/medical/chemistry)
@@ -24229,7 +24224,6 @@
/obj/structure/chair/office/light{
dir = 4
},
/obj/effect/landmark/start/chemist,
/obj/effect/turf_decal/stripes/line{
dir = 6
},
@@ -74189,7 +74183,7 @@ aRf
aSk
aTr
aUt
aVk
aVl
aWg
aRf
aXr

View File

@@ -164,4 +164,5 @@ MAP_REMOVE_JOB(geneticist)
MAP_REMOVE_JOB(virologist)
MAP_REMOVE_JOB(rd)
MAP_REMOVE_JOB(warden)
MAP_REMOVE_JOB(lawyer)
MAP_REMOVE_JOB(lawyer)
MAP_REMOVE_JOB(chemist)

View File

@@ -12140,6 +12140,7 @@
"aED" = (
/obj/structure/table,
/obj/item/aiModule/core/full/asimov,
/obj/effect/spawner/lootdrop/aimodule_harmless,
/obj/item/aiModule/core/freeformcore,
/obj/machinery/door/window{
base_state = "right";
@@ -12148,7 +12149,7 @@
name = "Core Modules";
req_access_txt = "20"
},
/obj/item/aiModule/core/full/corp,
/obj/effect/spawner/lootdrop/aimodule_neutral,
/obj/item/aiModule/core/full/custom,
/obj/structure/window/reinforced{
dir = 1;
@@ -12197,7 +12198,7 @@
req_access_txt = "20"
},
/obj/item/aiModule/reset/purge,
/obj/item/aiModule/core/full/antimov,
/obj/effect/spawner/lootdrop/aimodule_harmful,
/obj/item/aiModule/supplied/protectStation,
/obj/structure/window/reinforced{
dir = 1;

View File

@@ -129,38 +129,12 @@
#define MAX_OUTPUT_PRESSURE 4500 // (kPa) What pressure pumps and powered equipment max out at.
#define MAX_TRANSFER_RATE 200 // (L/s) Maximum speed powered equipment can work at.
//used for device_type vars; used by DEVICE_TYPE_LOOP
//used for device_type vars
#define UNARY 1
#define BINARY 2
#define TRINARY 3
#define QUATERNARY 4
//TODO: finally remove this bullshit
//this is the standard for loop used by all sorts of atmos machinery procs
#define DEVICE_TYPE_LOOP var/I in 1 to device_type
//defines for the various machinery lists
//NODE_I, AIR_I, PARENT_I are used within DEVICE_TYPE_LOOP
//nodes list - all atmos machinery
#define NODE1 nodes[1]
#define NODE2 nodes[2]
#define NODE3 nodes[3]
#define NODE4 nodes[4]
#define NODE_I nodes[I]
//airs list - components only
#define AIR1 airs[1]
#define AIR2 airs[2]
#define AIR3 airs[3]
#define AIR_I airs[I]
//parents list - components only
#define PARENT1 parents[1]
#define PARENT2 parents[2]
#define PARENT3 parents[3]
#define PARENT_I parents[I]
//TANKS
#define TANK_MELT_TEMPERATURE 1000000 //temperature in kelvins at which a tank will start to melt
#define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE) //Tank starts leaking

View File

@@ -4,4 +4,9 @@
#define CLEAN_MEDIUM 3 // Acceptable tools
#define CLEAN_STRONG 4 // Industrial strength
#define CLEAN_IMPRESSIVE 5 // Cleaning strong enough your granny would be proud
#define CLEAN_GOD 6 // Cleans things spotless down to the atomic structure
#define CLEAN_GOD 6 // Cleans things spotless down to the atomic structure
//How strong things have to be to wipe forensic evidence...
#define CLEAN_STRENGTH_FINGERPRINTS CLEAN_IMPRESSIVE
#define CLEAN_STRENGTH_BLOOD CLEAN_WEAK
#define CLEAN_STRENGTH_FIBERS CLEAN_IMPRESSIVE

View File

@@ -27,6 +27,13 @@
#define COMPONENT_NO_AFTERATTACK 1 //Return this in response if you don't want afterattack to be called
#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human)
#define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (/mob)
#define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" //from base of atom/get_examine_name(): (/mob, list/overrides)
//Positions for overrides list
#define EXAMINE_POSITION_ARTICLE 1
#define EXAMINE_POSITION_BEFORE 2
#define EXAMINE_POSITION_NAME 3
//End positions
#define COMPONENT_EXNAME_CHANGED 1
#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (/atom/movable, /atom)
#define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target)
#define COMSIG_ATOM_EMP_ACT "atom_emp_act" //from base of atom/emp_act(): (severity)

View File

@@ -0,0 +1,2 @@
#define IF_HAS_BLOOD_DNA(__thing) GET_COMPONENT_FROM(__FR##__thing, /datum/component/forensics, __thing); if(__FR##__thing && length(__FR##__thing.blood_DNA))
#define IF_HAS_BLOOD_DNA_AND(__thing, __conditions...) GET_COMPONENT_FROM(__FR##__thing, /datum/component/forensics, __thing); if(__FR##__thing && length(__FR##__thing.blood_DNA) && (##__conditions))

View File

@@ -108,6 +108,7 @@
#define AI_ON 1
#define AI_IDLE 2
#define AI_OFF 3
#define AI_Z_OFF 4
//determines if a mob can smash through it
#define ENVIRONMENT_SMASH_NONE 0

View File

@@ -25,13 +25,17 @@
// common disability sources
#define EYE_DAMAGE "eye_damage"
#define GENETIC_MUTATION "genetic"
#define STATUE_MUTE "statue"
#define CHANGELING_DRAIN "drain"
#define OBESITY "obesity"
#define MAGIC_DISABILITY "magic"
#define STASIS_MUTE "stasis"
#define GENETICS_SPELL "genetics_spell"
#define TRAUMA_DISABILITY "trauma"
#define CHEMICAL_DISABILITY "chemical"
// unique disability sources, still defines
#define STATUE_MUTE "statue"
#define CHANGELING_DRAIN "drain"
#define ABYSSAL_GAZE_BLIND "abyssal_gaze"
// bitflags for machine stat variable
#define BROKEN 1

View File

@@ -64,6 +64,8 @@
#define STATUS_EFFECT_KINDLE /datum/status_effect/kindle //A knockdown reduced by 1 second for every 3 points of damage the target takes.
#define STATUS_EFFECT_ICHORIAL_STAIN /datum/status_effect/ichorial_stain //Prevents a servant from being revived by vitality matrices for one minute.
/////////////
// NEUTRAL //
/////////////

View File

@@ -70,6 +70,40 @@
#define INIT_ORDER_SQUEAK -40
#define INIT_ORDER_PERSISTENCE -100
// Subsystem fire priority, from lowest to highest priority
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
#define FIRE_PRIORITY_IDLE_NPC 1
#define FIRE_PRIORITY_SERVER_MAINT 1
#define FIRE_PRIORITY_GARBAGE 4
#define FIRE_PRIORITY_RESEARCH 4
#define FIRE_PRIORITY_AIR 5
#define FIRE_PRIORITY_NPC 5
#define FIRE_PRIORITY_PROCESS 6
#define FIRE_PRIORITY_THROWING 6
#define FIRE_PRIORITY_FLIGHTPACKS 7
#define FIRE_PRIORITY_SPACEDRIFT 7
#define FIRE_PRIOTITY_SMOOTHING 8
#define FIRE_PRIORITY_ORBIT 8
#define FIRE_PRIORITY_OBJ 9
#define FIRE_PRIORUTY_FIELDS 9
#define FIRE_PRIORITY_ACID 9
#define FIRE_PRIOTITY_BURNING 9
#define FIRE_PRIORITY_INBOUNDS 9
#define FIRE_PRIORITY_DEFAULT 10
#define FIRE_PRIORITY_PARALLAX 11
#define FIRE_PRIORITY_NETWORKS 12
#define FIRE_PRIORITY_MOBS 13
#define FIRE_PRIORITY_TGUI 14
#define FIRE_PRIORITY_TICKER 19
#define FIRE_PRIORITY_OVERLAYS 20
#define FIRE_PRIORITY_INPUT 100 // This must always always be the max highest priority. Player input must never be lost.
// SS runlevels
#define RUNLEVEL_INIT 0

View File

@@ -0,0 +1,17 @@
// Helpers for checking whether a z-level conforms to a specific requirement
// Basic levels
#define is_centcom_level(z) ((z) == ZLEVEL_CENTCOM)
#define is_station_level(z) ((z) in GLOB.station_z_levels)
#define is_mining_level(z) ((z) == ZLEVEL_MINING)
#define is_reebe(z) ((z) == ZLEVEL_CITYOFCOGS)
#define is_transit_level(z) ((z) == ZLEVEL_TRANSIT)
#define is_away_level(z) ((z) > ZLEVEL_SPACEMAX)
// If true, the singularity cannot strip away asteroid turf on this Z
#define is_planet_level(z) (GLOB.z_is_planet["z"])

View File

@@ -18,6 +18,9 @@
//Antag information
gather_antag_data()
//Nuke disk
record_nuke_disk_location()
/datum/controller/subsystem/ticker/proc/gather_antag_data()
var/team_gid = 1
var/list/team_ids = list()
@@ -46,11 +49,57 @@
antag_info["objectives"] += list(list("objective_type"=O.type,"text"=O.explanation_text,"result"=result))
SSblackbox.record_feedback("associative", "antagonists", 1, antag_info)
/datum/controller/subsystem/ticker/proc/record_nuke_disk_location()
var/obj/item/disk/nuclear/N = locate() in GLOB.poi_list
if(N)
var/list/data = list()
var/turf/T = get_turf(N)
if(T)
data["x"] = T.x
data["y"] = T.y
data["z"] = T.z
var/atom/outer = get_atom_on_turf(N,/mob/living)
if(outer != N)
if(isliving(outer))
var/mob/living/L = outer
data["holder"] = L.real_name
else
data["holder"] = outer.name
SSblackbox.record_feedback("associative", "roundend_nukedisk", 1 , data)
/datum/controller/subsystem/ticker/proc/gather_newscaster()
var/json_file = file("[GLOB.log_directory]/newscaster.json")
var/list/file_data = list()
var/pos = 1
for(var/V in GLOB.news_network.network_channels)
var/datum/newscaster/feed_channel/channel = V
if(!istype(channel))
stack_trace("Non-channel in newscaster channel list")
continue
file_data["[pos]"] = list("channel name" = "[channel.channel_name]", "author" = "[channel.author]", "censored" = channel.censored ? 1 : 0, "author censored" = channel.authorCensor ? 1 : 0, "messages" = list())
for(var/M in channel.messages)
var/datum/newscaster/feed_message/message = M
if(!istype(message))
stack_trace("Non-message in newscaster channel messages list")
continue
var/list/comment_data = list()
for(var/C in message.comments)
var/datum/newscaster/feed_comment/comment = C
if(!istype(comment))
stack_trace("Non-message in newscaster message comments list")
continue
comment_data += list(list("author" = "[comment.author]", "time stamp" = "[comment.time_stamp]", "body" = "[comment.body]"))
file_data["[pos]"]["messages"] += list(list("author" = "[message.author]", "time stamp" = "[message.time_stamp]", "censored" = message.bodyCensor ? 1 : 0, "author censored" = message.authorCensor ? 1 : 0, "photo file" = "[message.photo_file]", "photo caption" = "[message.caption]", "body" = "[message.body]", "comments" = comment_data))
pos++
if(GLOB.news_network.wanted_issue.active)
file_data["wanted"] = list("author" = "[GLOB.news_network.wanted_issue.scannedUser]", "criminal" = "[GLOB.news_network.wanted_issue.criminal]", "description" = "[GLOB.news_network.wanted_issue.body]", "photo file" = "[GLOB.news_network.wanted_issue.photo_file]")
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/ticker/proc/declare_completion()
set waitfor = FALSE
to_chat(world, "<BR><BR><BR><FONT size=3><B>The round has ended.</B></FONT>")
to_chat(world, "<BR><BR><BR><span class='big bold'>The round has ended.</span>")
if(LAZYLEN(GLOB.round_end_notifiees))
send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.")
@@ -78,7 +127,7 @@
send2irc("Server", "Round just ended.")
if(CONFIG_GET(string/cross_server_address))
if(length(CONFIG_GET(keyed_string_list/cross_server)))
send_news_report()
CHECK_TICK
@@ -182,7 +231,7 @@
num_human_escapees++
if(shuttle_areas[get_area(Player)])
num_shuttle_escapees++
.[POPCOUNT_SURVIVORS] = num_survivors
.[POPCOUNT_ESCAPEES] = num_escapees
.[POPCOUNT_SHUTTLE_ESCAPEES] = num_shuttle_escapees
@@ -194,7 +243,7 @@
var/list/parts = list()
var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
var/popcount = count_survivors()
//Round statistics report
var/datum/station_state/end_state = new /datum/station_state()
end_state.count()
@@ -346,7 +395,7 @@
currrent_category = A.roundend_category
previous_category = A
result += A.roundend_report()
result += "<br>"
result += "<br><br>"
if(all_antagonists.len)
var/datum/antagonist/last = all_antagonists[all_antagonists.len]
@@ -393,7 +442,7 @@
text += " <span class='greentext'>survived</span>"
if(fleecheck)
var/turf/T = get_turf(ply.current)
if(!T || !(T.z in GLOB.station_z_levels))
if(!T || !is_station_level(T.z))
text += " while <span class='redtext'>fleeing the station</span>"
if(ply.current.real_name != ply.name)
text += " as <b>[ply.current.real_name]</b>"

View File

@@ -1434,11 +1434,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
temp = ((temp + (temp>>3))&29127) % 63 //070707
return temp
//checks if a turf is in the planet z list.
/proc/turf_z_is_planet(turf/T)
return GLOB.z_is_planet["[T.z]"]
//same as do_mob except for movables and it allows both to drift and doesn't draw progressbar
/proc/do_atom(atom/movable/user , atom/movable/target, time = 30, uninterruptible = 0,datum/callback/extra_checks = null)
if(!user || !target)

View File

@@ -22,7 +22,7 @@ GLOBAL_LIST_EMPTY(carbon_list) //all instances of /mob/living/carbon and subt
GLOBAL_LIST_EMPTY(ai_list)
GLOBAL_LIST_EMPTY(pai_list)
GLOBAL_LIST_EMPTY(available_ai_shells)
GLOBAL_LIST_INIT(simple_animals, list(list(),list(),list())) // One for each AI_* status define
GLOBAL_LIST_INIT(simple_animals, list(list(),list(),list(),list())) // One for each AI_* status define
GLOBAL_LIST_EMPTY(spidermobs) //all sentient spider mobs
GLOBAL_LIST_EMPTY(bots_list)

View File

@@ -58,9 +58,11 @@
SendSignal(COMSIG_ITEM_ATTACK, M, user)
if(flags_1 & NOBLUDGEON_1)
return
if(user.has_disability(DISABILITY_PACIFISM))
if(force && user.has_disability(DISABILITY_PACIFISM))
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
return
if(!force)
playsound(loc, 'sound/weapons/tap.ogg', get_clamped_volume(), 1, -1)
else if(hitsound)

View File

@@ -21,7 +21,7 @@
S = new(T)
S.reagents.add_reagent("semen", reac_volume)
if(data["blood_DNA"])
S.blood_DNA[data["blood_DNA"]] = data["blood_type"]
S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
/obj/effect/decal/cleanable/semen
name = "semen"
@@ -62,17 +62,16 @@
icon = 'code/citadel/icons/effects.dmi'
icon_state = "fem1"
random_icon_states = list("fem1", "fem2", "fem3", "fem4")
blood_DNA = list()
blood_state = null
bloodiness = null
/obj/effect/decal/cleanable/femcum/New()
..()
dir = pick(1,2,4,8)
add_blood_DNA(list("Non-human DNA" = "A+"))
/obj/effect/decal/cleanable/femcum/replace_decal(obj/effect/decal/cleanable/femcum/F)
if (F.blood_DNA)
blood_DNA |= F.blood_DNA.Copy()
F.add_blood_DNA(return_blood_DNA())
..()
/datum/reagent/consumable/femcum/reaction_turf(turf/T, reac_volume)
@@ -86,7 +85,7 @@
S = new(T)
S.reagents.add_reagent("femcum", reac_volume)
if(data["blood_DNA"])
S.blood_DNA[data["blood_DNA"]] = data["blood_type"]
S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
//aphrodisiac & anaphrodisiac

View File

@@ -10,6 +10,14 @@
w_class = WEIGHT_CLASS_TINY
flags_1 = NOBLUDGEON_1
/obj/item/soap/cebu //real versions, for admin shenanigans. Adminspawn only
desc = "A bright blue bar of soap that smells of wolves"
icon = 'icons/obj/custom.dmi'
icon_state = "cebu"
/obj/item/soap/cebu/fast //speedyquick cleaning version. Still not as fast as Syndiesoap. Adminspawn only.
cleanspeed = 15
/*Inferno707*/

View File

@@ -259,7 +259,7 @@
to_chat(user,"<span class='notice'>You clean \the [target.name].</span>")
var/obj/effect/decal/cleanable/C = locate() in target
qdel(C)
target.clean_blood()
SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
else if(ishuman(target))
if(src.emagged)
var/mob/living/silicon/robot.R = user
@@ -292,7 +292,7 @@
to_chat(user, "<span class='notice'>You clean \the [target.name].</span>")
var/obj/effect/decal/cleanable/C = locate() in target
qdel(C)
target.clean_blood()
SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
return

View File

@@ -4,7 +4,7 @@
name = "fire coderbus" //name of the subsystem
var/init_order = INIT_ORDER_DEFAULT //order of initialization. Higher numbers are initialized first, lower numbers later. Use defines in __DEFINES/subsystems.dm for easy understanding of order.
var/wait = 20 //time to wait (in deciseconds) between each call to fire(). Must be a positive integer.
var/priority = 50 //When mutiple subsystems need to run in the same tick, higher priority subsystems will run first and be given a higher share of the tick before MC_TICK_CHECK triggers a sleep
var/priority = FIRE_PRIORITY_DEFAULT //When mutiple subsystems need to run in the same tick, higher priority subsystems will run first and be given a higher share of the tick before MC_TICK_CHECK triggers a sleep
var/flags = 0 //see MC.dm in __DEFINES Most flags must be set on world start to take full effect. (You can also restart the mc to force them to process again)

View File

@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(acid)
name = "Acid"
priority = 40
priority = FIRE_PRIORITY_ACID
flags = SS_NO_INIT|SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME

View File

@@ -9,7 +9,7 @@
SUBSYSTEM_DEF(air)
name = "Atmospherics"
init_order = INIT_ORDER_AIR
priority = 20
priority = FIRE_PRIORITY_AIR
wait = 5
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME

View File

@@ -30,7 +30,7 @@ SUBSYSTEM_DEF(communications)
/datum/controller/subsystem/communications/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE)
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && (C.z in GLOB.station_z_levels))
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
if(unique)
C.add_message(sending)
else //We copy the message for each console, answers and deletions won't be shared

View File

@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(fire_burning)
name = "Fire Burning"
priority = 40
priority = FIRE_PRIOTITY_BURNING
flags = SS_NO_INIT|SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME

View File

@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(garbage)
name = "Garbage"
priority = 15
priority = FIRE_PRIORITY_GARBAGE
wait = 2 SECONDS
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY

View File

@@ -2,7 +2,7 @@ SUBSYSTEM_DEF(icon_smooth)
name = "Icon Smoothing"
init_order = INIT_ORDER_ICON_SMOOTHING
wait = 1
priority = 35
priority = FIRE_PRIOTITY_SMOOTHING
flags = SS_TICKER
var/list/smooth_queue = list()

View File

@@ -1,15 +1,21 @@
SUBSYSTEM_DEF(idlenpcpool)
name = "Idling NPC Pool"
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
priority = 10
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND
priority = FIRE_PRIORITY_IDLE_NPC
wait = 60
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/currentrun = list()
var/static/list/idle_mobs_by_zlevel[][]
/datum/controller/subsystem/idlenpcpool/stat_entry()
var/list/idlelist = GLOB.simple_animals[AI_IDLE]
..("IdleNPCS:[idlelist.len]")
var/list/zlist = GLOB.simple_animals[AI_Z_OFF]
..("IdleNPCS:[idlelist.len]|Z:[zlist.len]")
/datum/controller/subsystem/idlenpcpool/Initialize(start_timeofday)
idle_mobs_by_zlevel = new /list(world.maxz,0)
return ..()
/datum/controller/subsystem/idlenpcpool/fire(resumed = FALSE)
@@ -24,6 +30,9 @@ SUBSYSTEM_DEF(idlenpcpool)
while(currentrun.len)
var/mob/living/simple_animal/SA = currentrun[currentrun.len]
--currentrun.len
if (!SA)
GLOB.simple_animals[AI_IDLE] -= SA
continue
if(!SA.ckey)
if(SA.stat != DEAD)
@@ -32,3 +41,4 @@ SUBSYSTEM_DEF(idlenpcpool)
SA.consider_wakeup()
if (MC_TICK_CHECK)
return

View File

@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(inbounds)
name = "Inbounds"
priority = 40
priority = FIRE_PRIORITY_INBOUNDS
flags = SS_NO_INIT
runlevels = RUNLEVEL_GAME

View File

@@ -2,7 +2,7 @@ SUBSYSTEM_DEF(input)
name = "Input"
wait = 1 //SS_TICKER means this runs every tick
flags = SS_TICKER | SS_NO_INIT
priority = 1000
priority = FIRE_PRIORITY_INPUT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
/datum/controller/subsystem/input/fire()

View File

@@ -146,7 +146,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
var/list/station_areas_blacklist = typecacheof(list(/area/space, /area/mine, /area/ruin))
for(var/area/A in world)
var/turf/picked = safepick(get_area_turfs(A.type))
if(picked && (picked.z in GLOB.station_z_levels))
if(picked && is_station_level(picked.z))
if(!(A.type in GLOB.the_station_areas) && !is_type_in_typecache(A, station_areas_blacklist))
GLOB.the_station_areas.Add(A.type)

View File

@@ -61,7 +61,7 @@ SUBSYSTEM_DEF(minimap)
for(var/z in z_levels)
send_asset(client, "minimap_[z].png")
/datum/controller/subsystem/minimap/proc/generate(z = 1, x1 = 1, y1 = 1, x2 = world.maxx, y2 = world.maxy)
/datum/controller/subsystem/minimap/proc/generate(z, x1 = 1, y1 = 1, x2 = world.maxx, y2 = world.maxy)
// Load the background.
var/icon/minimap = new /icon('icons/minimap.dmi')
// Scale it up to our target size.

View File

@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(mobs)
name = "Mobs"
priority = 100
priority = FIRE_PRIORITY_MOBS
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME

View File

@@ -6,7 +6,7 @@
SUBSYSTEM_DEF(npcpool)
name = "NPC Pool"
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
priority = 20
priority = FIRE_PRIORITY_NPC
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/canBeUsed = list()

View File

@@ -1,44 +1,42 @@
SUBSYSTEM_DEF(orbit)
name = "Orbits"
priority = 35
wait = 2
flags = SS_NO_INIT|SS_TICKER
var/list/currentrun = list()
var/list/processing = list()
/datum/controller/subsystem/orbit/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/orbit/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while (currentrun.len)
var/datum/orbit/O = currentrun[currentrun.len]
currentrun.len--
if (!O)
processing -= O
if (MC_TICK_CHECK)
return
continue
if (!O.orbiter)
qdel(O)
if (MC_TICK_CHECK)
return
continue
if (O.lastprocess >= world.time) //we already checked recently
if (MC_TICK_CHECK)
return
continue
var/targetloc = get_turf(O.orbiting)
if (targetloc != O.lastloc || O.orbiter.loc != targetloc)
O.Check(targetloc)
if (MC_TICK_CHECK)
return
SUBSYSTEM_DEF(orbit)
name = "Orbits"
priority = FIRE_PRIORITY_ORBIT
wait = 2
flags = SS_NO_INIT|SS_TICKER
var/list/currentrun = list()
var/list/processing = list()
/datum/controller/subsystem/orbit/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/orbit/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while (currentrun.len)
var/datum/orbit/O = currentrun[currentrun.len]
currentrun.len--
if (!O)
processing -= O
if (MC_TICK_CHECK)
return
continue
if (!O.orbiter)
qdel(O)
if (MC_TICK_CHECK)
return
continue
if (O.lastprocess >= world.time) //we already checked recently
if (MC_TICK_CHECK)
return
continue
var/targetloc = get_turf(O.orbiting)
if (targetloc != O.lastloc || O.orbiter.loc != targetloc)
O.Check(targetloc)
if (MC_TICK_CHECK)
return

View File

@@ -2,7 +2,7 @@ SUBSYSTEM_DEF(overlays)
name = "Overlay"
flags = SS_TICKER
wait = 1
priority = 500
priority = FIRE_PRIORITY_OVERLAYS
init_order = INIT_ORDER_OVERLAY
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_SETUP

View File

@@ -2,7 +2,7 @@ SUBSYSTEM_DEF(parallax)
name = "Parallax"
wait = 2
flags = SS_POST_FIRE_TIMING | SS_BACKGROUND | SS_NO_INIT
priority = 65
priority = FIRE_PRIORITY_PARALLAX
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun

View File

@@ -1,6 +1,6 @@
PROCESSING_SUBSYSTEM_DEF(fields)
name = "Fields"
wait = 2
priority = 40
priority = FIRE_PRIORUTY_FIELDS
flags = SS_KEEP_TIMING | SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME

View File

@@ -1,6 +1,6 @@
PROCESSING_SUBSYSTEM_DEF(flightpacks)
name = "Flightpack Movement"
priority = 30
priority = FIRE_PRIORITY_FLIGHTPACKS
wait = 2
stat_tag = "FM"
flags = SS_NO_INIT|SS_TICKER|SS_KEEP_TIMING

View File

@@ -1,36 +1,36 @@
PROCESSING_SUBSYSTEM_DEF(networks)
name = "Networks"
priority = 80
wait = 1
stat_tag = "NET"
flags = SS_KEEP_TIMING
init_order = INIT_ORDER_NETWORKS
var/datum/ntnet/station/station_network
var/assignment_hardware_id = HID_RESTRICTED_END
var/list/networks_by_id = list() //id = network
var/list/interfaces_by_id = list() //hardware id = component interface
/datum/controller/subsystem/processing/networks/Initialize()
station_network = new
station_network.register_map_supremecy()
. = ..()
/datum/controller/subsystem/processing/networks/proc/register_network(datum/ntnet/network)
if(!networks_by_id[network.network_id])
networks_by_id[network.network_id] = network
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_network(datum/ntnet/network)
networks_by_id -= network.network_id
return TRUE
/datum/controller/subsystem/processing/networks/proc/register_interface(datum/component/ntnet_interface/D)
if(!interfaces_by_id[D.hardware_id])
interfaces_by_id[D.hardware_id] = D
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_interface(datum/component/ntnet_interface/D)
interfaces_by_id -= D.hardware_id
return TRUE
PROCESSING_SUBSYSTEM_DEF(networks)
name = "Networks"
priority = FIRE_PRIORITY_NETWORKS
wait = 1
stat_tag = "NET"
flags = SS_KEEP_TIMING
init_order = INIT_ORDER_NETWORKS
var/datum/ntnet/station/station_network
var/assignment_hardware_id = HID_RESTRICTED_END
var/list/networks_by_id = list() //id = network
var/list/interfaces_by_id = list() //hardware id = component interface
/datum/controller/subsystem/processing/networks/Initialize()
station_network = new
station_network.register_map_supremecy()
. = ..()
/datum/controller/subsystem/processing/networks/proc/register_network(datum/ntnet/network)
if(!networks_by_id[network.network_id])
networks_by_id[network.network_id] = network
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_network(datum/ntnet/network)
networks_by_id -= network.network_id
return TRUE
/datum/controller/subsystem/processing/networks/proc/register_interface(datum/component/ntnet_interface/D)
if(!interfaces_by_id[D.hardware_id])
interfaces_by_id[D.hardware_id] = D
return TRUE
return FALSE
/datum/controller/subsystem/processing/networks/proc/unregister_interface(datum/component/ntnet_interface/D)
interfaces_by_id -= D.hardware_id
return TRUE

View File

@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(obj)
name = "Objects"
priority = 40
priority = FIRE_PRIORITY_OBJ
flags = SS_NO_INIT
var/list/processing = list()

View File

@@ -2,7 +2,7 @@
SUBSYSTEM_DEF(processing)
name = "Processing"
priority = 25
priority = FIRE_PRIORITY_PROCESS
flags = SS_BACKGROUND|SS_POST_FIRE_TIMING|SS_NO_INIT
wait = 10

View File

@@ -1,6 +1,5 @@
PROCESSING_SUBSYSTEM_DEF(projectiles)
name = "Projectiles"
priority = 25
wait = 1
stat_tag = "PP"
flags = SS_NO_INIT|SS_TICKER|SS_KEEP_TIMING

View File

@@ -1,7 +1,6 @@
PROCESSING_SUBSYSTEM_DEF(radiation)
name = "Radiation"
flags = SS_NO_INIT | SS_BACKGROUND
priority = 25
var/list/warned_atoms = list()

View File

@@ -2,7 +2,7 @@
SUBSYSTEM_DEF(research)
name = "Research"
flags = SS_KEEP_TIMING
priority = 15 //My powergame is priority.
priority = FIRE_PRIORITY_RESEARCH
wait = 10
init_order = INIT_ORDER_RESEARCH
var/list/invalid_design_ids = list() //associative id = number of times

View File

@@ -4,7 +4,7 @@ SUBSYSTEM_DEF(server_maint)
name = "Server Tasks"
wait = 6
flags = SS_POST_FIRE_TIMING
priority = 10
priority = FIRE_PRIORITY_SERVER_MAINT
init_order = INIT_ORDER_SERVER_MAINT
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun

View File

@@ -325,7 +325,7 @@ SUBSYSTEM_DEF(shuttle)
continue
var/turf/T = get_turf(thing)
if(T && (T.z in GLOB.station_z_levels))
if(T && is_station_level(T.z))
callShuttle = 0
break

View File

@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(spacedrift)
name = "Space Drift"
priority = 30
priority = FIRE_PRIORITY_SPACEDRIFT
wait = 5
flags = SS_NO_INIT|SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME

View File

@@ -2,7 +2,7 @@ SUBSYSTEM_DEF(tgui)
name = "tgui"
wait = 9
flags = SS_NO_INIT
priority = 110
priority = FIRE_PRIORITY_TGUI
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun = list()

View File

@@ -3,7 +3,7 @@
SUBSYSTEM_DEF(throwing)
name = "Throwing"
priority = 25
priority = FIRE_PRIORITY_THROWING
wait = 1
flags = SS_NO_INIT|SS_KEEP_TIMING|SS_TICKER
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME

View File

@@ -4,7 +4,7 @@ SUBSYSTEM_DEF(ticker)
name = "Ticker"
init_order = INIT_ORDER_TICKER
priority = 200
priority = FIRE_PRIORITY_TICKER
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME

View File

@@ -0,0 +1,59 @@
/datum/antagonist/blob
name = "Blob"
roundend_category = "blobs"
job_rank = ROLE_BLOB
var/datum/action/innate/blobpop/pop_action
var/starting_points_human_blob = 60
var/point_rate_human_blob = 2
/datum/antagonist/blob/roundend_report()
var/basic_report = ..()
//Display max blobpoints for blebs that lost
if(isovermind(owner.current)) //embarrasing if not
var/mob/camera/blob/overmind = owner.current
if(!overmind.victory_in_progress) //if it won this doesn't really matter
var/point_report = "<br><b>[owner.name]</b> took over [overmind.max_count] tiles at the height of its growth."
return basic_report+point_report
return basic_report
/datum/antagonist/blob/greet()
if(!isovermind(owner.current))
to_chat(owner,"<span class='userdanger'>You feel bloated.</span>")
/datum/antagonist/blob/on_gain()
create_objectives()
. = ..()
/datum/antagonist/blob/proc/create_objectives()
var/datum/objective/blob_takeover/main = new
main.owner = owner
objectives += main
owner.objectives |= objectives
/datum/antagonist/blob/apply_innate_effects(mob/living/mob_override)
if(!isovermind(owner.current))
if(!pop_action)
pop_action = new
pop_action.Grant(owner.current)
/datum/objective/blob_takeover
explanation_text = "Reach critical mass!"
//Non-overminds get this on blob antag assignment
/datum/action/innate/blobpop
name = "Pop"
desc = "Unleash the blob"
icon_icon = 'icons/mob/blob.dmi'
button_icon_state = "blob"
/datum/action/innate/blobpop/Activate()
var/mob/old_body = owner
var/datum/antagonist/blob/blobtag = owner.mind.has_antag_datum(/datum/antagonist/blob)
if(!blobtag)
Remove()
return
var/mob/camera/blob/B = new /mob/camera/blob(get_turf(old_body), blobtag.starting_points_human_blob)
owner.mind.transfer_to(B)
old_body.gib()
B.place_blob_core(blobtag.point_rate_human_blob, pop_override = TRUE)

View File

@@ -257,7 +257,7 @@
var/sanity = 0
while(summon_spots.len < SUMMON_POSSIBILITIES && sanity < 100)
var/area/summon = pick(GLOB.sortedAreas - summon_spots)
if(summon && (summon.z in GLOB.station_z_levels) && summon.valid_territory)
if(summon && is_station_level(summon.z) && summon.valid_territory)
summon_spots += summon
sanity++
update_explanation_text()

View File

@@ -232,7 +232,7 @@
/datum/team/nuclear/proc/syndies_escaped()
var/obj/docking_port/mobile/S = SSshuttle.getShuttle("syndicate")
return (S && (S.z == ZLEVEL_CENTCOM || S.z == ZLEVEL_TRANSIT))
return S && (is_centcom_level(S.z) || is_transit_level(S.z))
/datum/team/nuclear/proc/get_result()
var/evacuation = SSshuttle.emergency.mode == SHUTTLE_ENDGAME

View File

@@ -205,13 +205,13 @@
new_comp = new nt(arglist(args))
if(!QDELETED(new_comp))
old_comp.InheritComponent(new_comp, TRUE)
qdel(new_comp)
QDEL_NULL(new_comp)
if(COMPONENT_DUPE_HIGHLANDER)
if(!new_comp)
new_comp = new nt(arglist(args))
if(!QDELETED(new_comp))
new_comp.InheritComponent(old_comp, FALSE)
qdel(old_comp)
QDEL_NULL(old_comp)
if(COMPONENT_DUPE_UNIQUE_PASSARGS)
if(!new_comp)
var/list/arguments = args.Copy(2)

View File

@@ -13,28 +13,28 @@
if(!isturf(tile))
return
tile.clean_blood()
tile.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
for(var/A in tile)
if(is_cleanable(A))
qdel(A)
else if(istype(A, /obj/item))
var/obj/item/cleaned_item = A
cleaned_item.clean_blood()
var/obj/item/I = A
I.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
else if(ishuman(A))
var/mob/living/carbon/human/cleaned_human = A
if(cleaned_human.lying)
if(cleaned_human.head)
cleaned_human.head.clean_blood()
cleaned_human.head.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
cleaned_human.update_inv_head()
if(cleaned_human.wear_suit)
cleaned_human.wear_suit.clean_blood()
cleaned_human.wear_suit.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
cleaned_human.update_inv_wear_suit()
else if(cleaned_human.w_uniform)
cleaned_human.w_uniform.clean_blood()
cleaned_human.w_uniform.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
cleaned_human.update_inv_w_uniform()
if(cleaned_human.shoes)
cleaned_human.shoes.clean_blood()
cleaned_human.shoes.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
cleaned_human.update_inv_shoes()
cleaned_human.clean_blood()
cleaned_human.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
cleaned_human.wash_cream()
to_chat(cleaned_human, "<span class='danger'>[AM] cleans your face!</span>")

View File

@@ -6,19 +6,11 @@
var/mutable_appearance/pic
/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description)
if(!isatom(parent) || !_icon || !_icon_state)
if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color))
. = COMPONENT_INCOMPATIBLE
CRASH("A turf decal was applied incorrectly to [parent.type]: icon:[_icon ? _icon : "none"] icon_state:[_icon_state ? _icon_state : "none"]")
// It has to be made from an image or dir breaks because of a byond bug
var/temp_image = image(_icon, null, _icon_state, _layer, _dir)
pic = new(temp_image)
pic.color = _color
cleanable = _cleanable
description = _description
apply()
cleanable = _cleanable
if(_dir) // If no dir is assigned at start then it follows the atom's dir
RegisterSignal(COMSIG_ATOM_DIR_CHANGE, .proc/rotate_react)
@@ -26,6 +18,7 @@
RegisterSignal(COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_react)
if(_description)
RegisterSignal(COMSIG_PARENT_EXAMINE, .proc/examine)
apply()
/datum/component/decal/Destroy()
remove()
@@ -36,6 +29,15 @@
remove(thing)
apply(thing)
/datum/component/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color)
if(!_icon || !_icon_state)
return FALSE
// It has to be made from an image or dir breaks because of a byond bug
var/temp_image = image(_icon, null, _icon_state, _layer, _dir)
pic = new(temp_image)
pic.color = _color
return TRUE
/datum/component/decal/proc/apply(atom/thing)
var/atom/master = thing || parent
master.add_overlay(pic, TRUE)

View File

@@ -0,0 +1,35 @@
/datum/component/decal/blood
dupe_mode = COMPONENT_DUPE_UNIQUE
/datum/component/decal/blood/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_STRENGTH_BLOOD, _color, _layer=ABOVE_OBJ_LAYER)
if(!isitem(parent))
. = COMPONENT_INCOMPATIBLE
CRASH("Warning: Blood decal attempted to be added to non-item of type [parent.type]")
. = ..()
RegisterSignal(COMSIG_ATOM_GET_EXAMINE_NAME, .proc/get_examine_name)
/datum/component/decal/blood/generate_appearance(_icon, _icon_state, _dir, _layer, _color)
var/obj/item/I = parent
if(!_icon)
_icon = 'icons/effects/blood.dmi'
if(!_icon_state)
_icon_state = "itemblood"
if(!initial(I.icon) || !initial(I.icon_state))
return FALSE
var/static/list/blood_splatter_appearances = list()
//try to find a pre-processed blood-splatter. otherwise, make a new one
var/index = "[REF(initial(I.icon))]-[initial(I.icon_state)]"
pic = blood_splatter_appearances[index]
if(!pic)
var/icon/blood_splatter_icon = icon(initial(I.icon), initial(I.icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object
blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent)
blood_splatter_icon.Blend(icon(_icon, _icon_state), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
pic = mutable_appearance(blood_splatter_icon, initial(I.icon_state), I.layer)
blood_splatter_appearances[index] = pic
return TRUE
/datum/component/decal/blood/proc/get_examine_name(mob/user, list/override)
var/atom/A = parent
override[EXAMINE_POSITION_ARTICLE] = A.gender == PLURAL? "some" : "a"
override[EXAMINE_POSITION_BEFORE] = " blood-stained "
return COMPONENT_EXNAME_CHANGED

View File

@@ -138,7 +138,7 @@
if(laststamppos)
LAZYSET(hiddenprints, M.key, copytext(hiddenprints[M.key], 1, laststamppos))
hiddenprints[M.key] += " Last: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]" //made sure to be existing by if(!LAZYACCESS);else
parent.fingerprintslast = M.ckey
fingerprintslast = M.ckey
return TRUE
/datum/component/forensics/proc/add_blood_DNA(list/dna) //list(dna_enzymes = type)

View File

@@ -408,7 +408,7 @@
AD.Refresh()
for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list))
if(!(H.z in GLOB.station_z_levels))
if(!is_station_level(H.z))
continue
if(!H.HasDisease(D))
H.ForceContractDisease(D)

View File

@@ -55,6 +55,8 @@ GLOBAL_LIST_EMPTY(explosions)
var/orig_heavy_range = heavy_impact_range
var/orig_light_range = light_impact_range
var/orig_max_distance = max(devastation_range, heavy_impact_range, light_impact_range, flash_range, flame_range)
//Zlevel specific bomb cap multiplier
var/cap_multiplier = 1
switch(epicenter.z)
@@ -119,11 +121,13 @@ GLOBAL_LIST_EMPTY(explosions)
// If inside the blast radius + world.view - 2
if(dist <= round(max_range + world.view - 2, 1))
M.playsound_local(epicenter, null, 100, 1, frequency, falloff = 5, S = explosion_sound)
shake_camera(M, 25, min(orig_max_distance - dist, 100))
// You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
else if(dist <= far_dist)
var/far_volume = CLAMP(far_dist, 30, 50) // Volume is based on explosion size and dist
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
M.playsound_local(epicenter, null, far_volume, 1, frequency, falloff = 5, S = far_explosion_sound)
shake_camera(M, 10, min(orig_max_distance - dist, 50))
EX_PREPROCESS_CHECK_TICK
//postpone processing for a bit

View File

@@ -545,7 +545,7 @@
if(I == src)
continue
var/mob/M = I.current
if(M && (M.z in GLOB.station_z_levels) && !M.stat)
if(M && is_station_level(M.z) && !M.stat)
last_healthy_headrev = FALSE
break
text += "head | not mindshielded | <a href='?src=[REF(src)];revolution=clear'>employee</a> | <b>[last_healthy_headrev ? "<font color='red'>LAST </font> " : ""]HEADREV</b> | <a href='?src=[REF(src)];revolution=rev'>rev</a>"

View File

@@ -479,3 +479,27 @@
desc = "Blinding light dances in your vision, stunning and silencing you. <i>Any damage taken will shorten the light's effects!</i>"
icon_state = "kindle"
alerttooltipstyle = "clockcult"
//Ichorial Stain: Applied to servants revived by a vitality matrix. Prevents them from being revived by one again until the effect fades.
/datum/status_effect/ichorial_stain
id = "ichorial_stain"
status_type = STATUS_EFFECT_UNIQUE
duration = 600
examine_text = "<span class='warning'>SUBJECTPRONOUN is drenched in thick, blue ichor!</span>"
alert_type = /obj/screen/alert/status_effect/ichorial_stain
/datum/status_effect/ichorial_stain/on_apply()
owner.visible_message("<span class='danger'>[owner] gets back up, [owner.p_their()] body dripping blue ichor!</span>", \
"<span class='userdanger'>Thick blue ichor covers your body; you can't be revived like this again until it dries!</span>")
return TRUE
/datum/status_effect/ichorial_stain/on_remove()
owner.visible_message("<span class='danger'>The blue ichor on [owner]'s body dries out!</span>", \
"<span class='boldnotice'>The ichor on your body is dry - you can now be revived by vitality matrices again!</span>")
/obj/screen/alert/status_effect/ichorial_stain
name = "Ichorial Stain"
desc = "Your body is covered in blue ichor! You can't be revived by vitality matrices."
icon_state = "ichorial_stain"
alerttooltipstyle = "clockcult"

View File

@@ -9,6 +9,7 @@
var/mob/living/owner //The mob affected by the status effect.
var/status_type = STATUS_EFFECT_UNIQUE //How many of the effect can be on one mob, and what happens when you try to add another
var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted
var/examine_text //If defined, this text will appear when the mob is examined - to use he, she etc. use "SUBJECTPRONOUN" and replace it in the examines themselves
var/alert_type = /obj/screen/alert/status_effect //the alert thrown by the status effect, contains name and description
var/obj/screen/alert/status_effect/linked_alert = null //the alert itself, if it exists

View File

@@ -76,7 +76,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
if(GLOB.teleportlocs[AR.name])
continue
var/turf/picked = safepick(get_area_turfs(AR.type))
if (picked && (picked.z in GLOB.station_z_levels))
if (picked && is_station_level(picked.z))
GLOB.teleportlocs[AR.name] = AR
sortTim(GLOB.teleportlocs, /proc/cmp_text_dsc)

View File

@@ -5,10 +5,6 @@
var/flags_1 = 0
var/flags_2 = 0
var/list/fingerprints
var/list/fingerprintshidden
var/list/blood_DNA
var/container_type = NONE
var/admin_spawned = 0 //was this spawned by an admin? used for stat tracking stuff.
var/datum/reagents/reagents = null
@@ -113,7 +109,7 @@
if(!T)
return FALSE
if(T.z == ZLEVEL_TRANSIT)
if(is_transit_level(T.z))
for(var/A in SSshuttle.mobile)
var/obj/docking_port/mobile/M = A
if(M.launch_status == ENDGAME_TRANSIT)
@@ -122,7 +118,7 @@
if(T in shuttle_area)
return TRUE
if(T.z != ZLEVEL_CENTCOM)//if not, don't bother
if(!is_centcom_level(T.z))//if not, don't bother
return FALSE
//Check for centcom itself
@@ -141,15 +137,15 @@
/atom/proc/onSyndieBase()
var/turf/T = get_turf(src)
if(!T)
return 0
return FALSE
if(T.z != ZLEVEL_CENTCOM)//if not, don't bother
return 0
if(!is_centcom_level(T.z))//if not, don't bother
return FALSE
if(istype(T.loc, /area/shuttle/syndicate) || istype(T.loc, /area/syndicate_mothership))
return 1
if(istype(T.loc, /area/shuttle/syndicate) || istype(T.loc, /area/syndicate_mothership) || istype(T.loc, /area/shuttle/assault_pod))
return TRUE
return 0
return FALSE
/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
SendSignal(COMSIG_ATOM_HULK_ATTACK, user)
@@ -232,21 +228,22 @@
/atom/proc/in_contents_of(container)//can take class or object instance as argument
if(ispath(container))
if(istype(src.loc, container))
return 1
return TRUE
else if(src in container)
return 1
return TRUE
return FALSE
/atom/proc/get_examine_name(mob/user)
. = "\a [src]"
var/list/override = list(gender == PLURAL? "some" : "a" , " ", "[name]")
if(SendSignal(COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED)
. = override.Join("")
/atom/proc/get_examine_string(mob/user, thats = FALSE)
. = "[icon2html(src, user)] [thats? "That's ":""][get_examine_name(user)]"
/atom/proc/examine(mob/user)
//This reformat names to get a/an properly working on item descriptions when they are bloody
var/f_name = "\a [src]."
if(src.blood_DNA && !istype(src, /obj/effect/decal))
if(gender == PLURAL)
f_name = "some "
else
f_name = "a "
f_name += "<span class='danger'>blood-stained</span> [name]!"
to_chat(user, "[icon2html(src, user)] That's [f_name]")
to_chat(user, get_examine_string(user, TRUE))
if(desc)
to_chat(user, desc)
@@ -303,11 +300,6 @@
if(AM && isturf(AM.loc))
step(AM, turn(AM.dir, 180))
GLOBAL_LIST_EMPTY(blood_splatter_icons)
/atom/proc/blood_splatter_index()
return "[REF(initial(icon))]-[initial(icon_state)]"
//returns the mob's dna info as a list, to be inserted in an object's blood_DNA list
/mob/living/proc/get_blood_dna_list()
if(get_blood_id() != "blood")
@@ -332,100 +324,28 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
// Returns 0 if we have that blood already
var/new_blood_dna = L.get_blood_dna_list()
if(!new_blood_dna)
return 0
if(!blood_DNA) //if our list of DNA doesn't exist yet, initialise it.
blood_DNA = list()
var/old_length = blood_DNA.len
blood_DNA |= new_blood_dna
if(blood_DNA.len == old_length)
return 0
return 1
//to add blood dna info to the object's blood_DNA list
/atom/proc/transfer_blood_dna(list/blood_dna)
if(!blood_DNA)
blood_DNA = list()
var/old_length = blood_DNA.len
blood_DNA |= blood_dna
if(blood_DNA.len > old_length)
return 1//some new blood DNA was added
return FALSE
var/old_length = blood_DNA_length()
add_blood_DNA(new_blood_dna)
if(blood_DNA_length() == old_length)
return FALSE
return TRUE
//to add blood from a mob onto something, and transfer their dna info
/atom/proc/add_mob_blood(mob/living/M)
var/list/blood_dna = M.get_blood_dna_list()
if(!blood_dna)
return 0
return add_blood(blood_dna)
//to add blood onto something, with blood dna info to include.
/atom/proc/add_blood(list/blood_dna)
return 0
/obj/add_blood(list/blood_dna)
return transfer_blood_dna(blood_dna)
/obj/item/add_blood(list/blood_dna)
var/blood_count = !blood_DNA ? 0 : blood_DNA.len
if(!..())
return 0
if(!blood_count)//apply the blood-splatter overlay if it isn't already in there
add_blood_overlay()
return 1 //we applied blood to the item
/obj/item/proc/add_blood_overlay()
if(initial(icon) && initial(icon_state))
//try to find a pre-processed blood-splatter. otherwise, make a new one
var/index = blood_splatter_index()
var/icon/blood_splatter_icon = GLOB.blood_splatter_icons[index]
if(!blood_splatter_icon)
blood_splatter_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object
blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent)
blood_splatter_icon.Blend(icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
blood_splatter_icon = fcopy_rsc(blood_splatter_icon)
GLOB.blood_splatter_icons[index] = blood_splatter_icon
add_overlay(blood_splatter_icon)
/obj/item/clothing/gloves/add_blood(list/blood_dna)
. = ..()
transfer_blood = rand(2, 4)
/turf/add_blood(list/blood_dna, list/datum/disease/diseases)
var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src
if(!B)
B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases)
B.transfer_blood_dna(blood_dna) //give blood info to the blood decal.
return 1 //we bloodied the floor
/mob/living/carbon/human/add_blood(list/blood_dna)
if(wear_suit)
wear_suit.add_blood(blood_dna)
update_inv_wear_suit()
else if(w_uniform)
w_uniform.add_blood(blood_dna)
update_inv_w_uniform()
if(gloves)
var/obj/item/clothing/gloves/G = gloves
G.add_blood(blood_dna)
else
transfer_blood_dna(blood_dna)
bloody_hands = rand(2, 4)
update_inv_gloves() //handles bloody hands overlays and updating
return 1
/atom/proc/clean_blood()
if(islist(blood_DNA))
blood_DNA = null
return 1
return FALSE
return add_blood_DNA(blood_dna)
/atom/proc/wash_cream()
return 1
return TRUE
/atom/proc/isinspace()
if(isspaceturf(get_turf(src)))
return 1
return TRUE
else
return 0
return FALSE
/atom/proc/handle_fall()
return

View File

@@ -144,27 +144,27 @@
/atom/movable/proc/clean_on_move()
var/turf/tile = loc
if(isturf(tile))
tile.clean_blood()
tile.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
for(var/A in tile)
if(is_cleanable(A))
qdel(A)
else if(istype(A, /obj/item))
var/obj/item/cleaned_item = A
cleaned_item.clean_blood()
cleaned_item.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
else if(ishuman(A))
var/mob/living/carbon/human/cleaned_human = A
if(cleaned_human.lying)
if(cleaned_human.head)
cleaned_human.head.clean_blood()
cleaned_human.head.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
cleaned_human.update_inv_head()
if(cleaned_human.wear_suit)
cleaned_human.wear_suit.clean_blood()
cleaned_human.wear_suit.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
cleaned_human.update_inv_wear_suit()
else if(cleaned_human.w_uniform)
cleaned_human.w_uniform.clean_blood()
cleaned_human.w_uniform.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
cleaned_human.update_inv_w_uniform()
if(cleaned_human.shoes)
cleaned_human.shoes.clean_blood()
cleaned_human.shoes.SendSignal(COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
cleaned_human.update_inv_shoes()
cleaned_human.clean_blood()
cleaned_human.wash_cream()
@@ -611,8 +611,8 @@
/atom/movable/proc/in_bounds()
. = FALSE
var/turf/currentturf = get_turf(src)
if(currentturf && (currentturf.z == ZLEVEL_CENTCOM || (currentturf.z in GLOB.station_z_levels) || currentturf.z == ZLEVEL_TRANSIT))
var/turf/T = get_turf(src)
if (T && (is_centcom_level(T.z) || is_station_level(T.z) || is_transit_level(T.z)))
. = TRUE

View File

@@ -108,7 +108,7 @@
if(!user.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE))
to_chat(user, "<span class='danger'>AUTHENTICATION FAILURE. ACCESS DENIED.</span>")
return FALSE
if(user.z != ZLEVEL_CENTCOM)
if(!user.onSyndieBase())
to_chat(user, "<span class='warning'>[src] is out of range! It can only be used at your base!</span>")
return FALSE
return TRUE
@@ -208,7 +208,7 @@
/obj/item/antag_spawner/slaughter_demon/attack_self(mob/user)
if(!(user.z in GLOB.station_z_levels))
if(!is_station_level(user.z))
to_chat(user, "<span class='notice'>You should probably wait until you reach the station.</span>")
return
if(used)

View File

@@ -4,6 +4,7 @@ GLOBAL_LIST_EMPTY(blob_cores)
GLOBAL_LIST_EMPTY(overminds)
GLOBAL_LIST_EMPTY(blob_nodes)
/mob/camera/blob
name = "Blob Overmind"
real_name = "Blob Overmind"
@@ -33,10 +34,12 @@ GLOBAL_LIST_EMPTY(blob_nodes)
var/manualplace_min_time = 600 //in deciseconds //a minute, to get bearings
var/autoplace_max_time = 3600 //six minutes, as long as should be needed
var/list/blobs_legit = list()
var/max_count = 0 //The biggest it got before death
var/blobwincount = 400
var/victory_in_progress = FALSE
/mob/camera/blob/Initialize(mapload, starting_points = 60)
validate_location()
blob_points = starting_points
manualplace_min_time += world.time
autoplace_max_time += world.time
@@ -50,11 +53,18 @@ GLOBAL_LIST_EMPTY(blob_nodes)
color = blob_reagent_datum.complementary_color
if(blob_core)
blob_core.update_icon()
SSshuttle.registerHostileEnvironment(src)
.= ..()
/mob/camera/blob/proc/validate_location()
var/turf/T = get_turf(src)
var/area/A = get_area(T)
if(((A && !A.blob_allowed) || !T || !(T.z in GLOB.station_z_levels)) && LAZYLEN(GLOB.blobstart))
T = get_turf(pick(GLOB.blobstart))
if(!T)
CRASH("No blobspawnpoints and blob spawned in nullspace.")
forceMove(T)
/mob/camera/blob/Life()
if(!blob_core)
if(!placed)
@@ -73,6 +83,9 @@ GLOBAL_LIST_EMPTY(blob_nodes)
max_blob_points = INFINITY
blob_points = INFINITY
addtimer(CALLBACK(src, .proc/victory), 450)
if(!victory_in_progress && max_count < blobs_legit.len)
max_count = blobs_legit.len
..()
@@ -111,6 +124,11 @@ GLOBAL_LIST_EMPTY(blob_nodes)
A.layer = BELOW_MOB_LAYER
A.invisibility = 0
A.blend_mode = 0
var/datum/antagonist/blob/B = mind.has_antag_datum(/datum/antagonist/blob)
if(B)
var/datum/objective/blob_takeover/main_objective = locate() in B.objectives
if(main_objective)
main_objective.completed = TRUE
to_chat(world, "<B>[real_name] consumed the station in an unstoppable tide!</B>")
SSticker.news_report = BLOB_WIN
SSticker.force_ending = 1
@@ -134,7 +152,6 @@ GLOBAL_LIST_EMPTY(blob_nodes)
/mob/camera/blob/Login()
..()
sync_mind()
to_chat(src, "<span class='notice'>You are the overmind!</span>")
blob_help()
update_health_hud()
@@ -224,3 +241,9 @@ GLOBAL_LIST_EMPTY(blob_nodes)
return 0
forceMove(NewLoc)
return 1
/mob/camera/blob/mind_initialize()
. = ..()
var/datum/antagonist/blob/B = mind.has_antag_datum(/datum/antagonist/blob)
if(!B)
mind.add_antag_datum(/datum/antagonist/blob)

View File

@@ -7,22 +7,23 @@
// Power verbs
/mob/camera/blob/proc/place_blob_core(point_rate, placement_override)
/mob/camera/blob/proc/place_blob_core(point_rate, placement_override , pop_override = FALSE)
if(placed && placement_override != -1)
return 1
if(!placement_override)
for(var/mob/living/M in range(7, src))
if("blob" in M.faction)
continue
if(M.client)
to_chat(src, "<span class='warning'>There is someone too close to place your blob core!</span>")
return 0
for(var/mob/living/M in view(13, src))
if("blob" in M.faction)
continue
if(M.client)
to_chat(src, "<span class='warning'>Someone could see your blob core from here!</span>")
return 0
if(!pop_override)
for(var/mob/living/M in range(7, src))
if("blob" in M.faction)
continue
if(M.client)
to_chat(src, "<span class='warning'>There is someone too close to place your blob core!</span>")
return 0
for(var/mob/living/M in view(13, src))
if("blob" in M.faction)
continue
if(M.client)
to_chat(src, "<span class='warning'>Someone could see your blob core from here!</span>")
return 0
var/turf/T = get_turf(src)
if(T.density)
to_chat(src, "<span class='warning'>This spot is too dense to place a blob core on!</span>")
@@ -37,7 +38,7 @@
else if(O.density)
to_chat(src, "<span class='warning'>This spot is too dense to place a blob core on!</span>")
return 0
if(world.time <= manualplace_min_time && world.time <= autoplace_max_time)
if(!pop_override && world.time <= manualplace_min_time && world.time <= autoplace_max_time)
to_chat(src, "<span class='warning'>It is too early to place your blob core!</span>")
return 0
else if(placement_override == 1)

View File

@@ -8,6 +8,8 @@
/obj/effect/proc_holder/changeling/headcrab/sting_action(mob/user)
set waitfor = FALSE
if(alert("Are we sure we wish to kill ourself and create a headslug?",,"Yes", "No") == "No")
return
var/datum/mind/M = user.mind
var/list/organs = user.getorganszone("head", 1)
@@ -35,4 +37,4 @@
if(crab.origin)
crab.origin.active = 1
crab.origin.transfer_to(crab)
to_chat(crab, "<span class='warning'>You burst out of the remains of your former body in a shower of gore!</span>")
to_chat(crab, "<span class='warning'>You burst out of the remains of your former body in a shower of gore!</span>")

View File

@@ -278,7 +278,7 @@
animate(src, alpha = 255, time = 10, flags = ANIMATION_END_NOW) //we may have a previous animation going. finish it first, then do this one without delay.
sleep(10)
//as long as they're still on the sigil and are either not a servant or they're a servant AND it has remaining vitality
while(L && (!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && (GLOB.ratvar_awakens || GLOB.clockwork_vitality))) && get_turf(L) == get_turf(src))
while(L && (!is_servant_of_ratvar(L) || (is_servant_of_ratvar(L) && (GLOB.ratvar_awakens || GLOB.clockwork_vitality))) && get_turf(L) == get_turf(src) && !L.buckled)
sigil_active = TRUE
if(animation_number >= 4)
new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
@@ -313,21 +313,28 @@
revival_cost = 0
var/mob/dead/observer/ghost = L.get_ghost(TRUE)
if(GLOB.clockwork_vitality >= revival_cost && (ghost || (L.mind && L.mind.active)))
if(ghost)
ghost.reenter_corpse()
L.revive(1, 1)
var/obj/effect/temp_visual/ratvar/sigil/vitality/V = new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
animate(V, alpha = 0, transform = matrix()*2, time = 8)
playsound(L, 'sound/magic/staff_healing.ogg', 50, 1)
L.visible_message("<span class='warning'>[L] suddenly gets back up, [L.p_their()] body dripping blue ichor!</span>", "<span class='inathneq'>\"[text2ratvar("You will be okay, child.")]\"</span>")
GLOB.clockwork_vitality -= revival_cost
if(L.has_status_effect(STATUS_EFFECT_ICHORIAL_STAIN))
visible_message("<span class='boldwarning'>[src] strains, but nothing happens...</span>")
if(L.pulledby)
to_chat(L.pulledby, "<span class='userdanger'>[L] was already revived recently by a vitality matrix! Wait a bit longer!</span>")
break
else
if(ghost)
ghost.reenter_corpse()
L.revive(1, 1)
var/obj/effect/temp_visual/ratvar/sigil/vitality/V = new /obj/effect/temp_visual/ratvar/sigil/vitality(get_turf(src))
animate(V, alpha = 0, transform = matrix()*2, time = 8)
playsound(L, 'sound/magic/staff_healing.ogg', 50, 1)
to_chat(L, "<span class='inathneq'>\"[text2ratvar("You will be okay, child.")]\"</span>")
L.apply_status_effect(STATUS_EFFECT_ICHORIAL_STAIN)
GLOB.clockwork_vitality -= revival_cost
break
if(!L.client || L.client.is_afk())
set waitfor = FALSE
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [L.name], an inactive clock cultist?", "[name]", null, "Clock Cultist", 50, L)
var/mob/dead/observer/theghost = null
if(candidates.len)
to_chat(L, "Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form!")
to_chat(L, "<span class='userdanger'>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(theghost)] has taken control of ([key_name_admin(L)]) to replace an inactive clock cultist.")
L.ghostize(0)
L.key = theghost.key

View File

@@ -165,13 +165,13 @@
var/list/teleportnames = list()
for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in GLOB.all_clockwork_objects)
if(!O.Adjacent(invoker) && O != src && (O.z <= ZLEVEL_SPACEMAX) && O.anchored) //don't list obelisks that we're next to
if(!O.Adjacent(invoker) && O != src && !is_away_level(O.z) && O.anchored) //don't list obelisks that we're next to
var/area/A = get_area(O)
var/locname = initial(A.name)
possible_targets[avoid_assoc_duplicate_keys("[locname] [O.name]", teleportnames)] = O
for(var/mob/living/L in GLOB.alive_mob_list)
if(!L.stat && is_servant_of_ratvar(L) && !L.Adjacent(invoker) && (L.z <= ZLEVEL_SPACEMAX)) //People right next to the invoker can't be portaled to, for obvious reasons
if(!L.stat && is_servant_of_ratvar(L) && !L.Adjacent(invoker) && !is_away_level(L.z)) //People right next to the invoker can't be portaled to, for obvious reasons
possible_targets[avoid_assoc_duplicate_keys("[L.name] ([L.real_name])", teleportnames)] = L
if(!possible_targets.len)

View File

@@ -94,7 +94,7 @@
fabrication_values["power_cost"] = 0
var/turf/Y = get_turf(user)
if(!Y || (!(Y.z in GLOB.station_z_levels) && Y.z != ZLEVEL_CENTCOM && Y.z != ZLEVEL_MINING && Y.z != ZLEVEL_LAVALAND))
if(!Y || (!is_centcom_level(Y.z) && !is_station_level(Y.z) && !is_mining_level(Y.z)))
fabrication_values["operation_time"] *= 2
if(fabrication_values["power_cost"] > 0)
fabrication_values["power_cost"] *= 2

View File

@@ -63,7 +63,7 @@
hierophant_message("<span class='large_brass'><b>The Eminence:</b> \"[message]\"</span>")
/mob/camera/eminence/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
if(z == ZLEVEL_CITYOFCOGS || is_servant_of_ratvar(speaker) || GLOB.ratvar_approaches || GLOB.ratvar_awakens) //Away from Reebe, the Eminence can't hear anything
if(is_reebe(z) || is_servant_of_ratvar(speaker) || GLOB.ratvar_approaches || GLOB.ratvar_awakens) //Away from Reebe, the Eminence can't hear anything
to_chat(src, message)
return
to_chat(src, "<i>[speaker] says something, but you can't understand any of it...</i>")
@@ -233,7 +233,7 @@
button_icon_state = "warp_down"
/datum/action/innate/eminence/station_jump/Activate()
if(owner.z == ZLEVEL_CITYOFCOGS)
if(is_reebe(owner.z))
owner.forceMove(get_turf(pick(GLOB.generic_event_spawns)))
owner.playsound_local(owner, 'sound/magic/magic_missile.ogg', 50, TRUE)
flash_color(owner, flash_color = "#AF0AAF", flash_time = 25)

View File

@@ -126,7 +126,7 @@ Applications: 8 servants, 3 caches, and 100 CV
/datum/clockwork_scripture/proc/check_offstation_penalty()
var/turf/T = get_turf(invoker)
if(!T || (!(T.z in GLOB.station_z_levels) && T.z != ZLEVEL_CENTCOM && T.z != ZLEVEL_MINING && T.z != ZLEVEL_LAVALAND && T.z != ZLEVEL_CITYOFCOGS))
if(!T || (!is_centcom_level(T.z) && !is_station_level(T.z) && !is_mining_level(T.z) && !is_reebe(T.z)))
channel_time *= 2
power_cost *= 2
return TRUE
@@ -262,7 +262,7 @@ Applications: 8 servants, 3 caches, and 100 CV
to_chat(invoker, "<span class='warning'>There are too many constructs of this type ([constructs])! You may only have [round(construct_limit)] at once.</span>")
return
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
if(G && !G.active && combat_construct && invoker.z == ZLEVEL_CITYOFCOGS && !confirmed) //Putting marauders on the base during the prep phase is a bad idea mmkay
if(G && !G.active && combat_construct && is_reebe(invoker.z) && !confirmed) //Putting marauders on the base during the prep phase is a bad idea mmkay
if(alert(invoker, "This is a combat construct, and you cannot easily get it to the station. Are you sure you want to make one here?", "Construct Alert", "Yes", "Cancel") == "Cancel")
return
if(!is_servant_of_ratvar(invoker) || !invoker.canUseTopic(slab))

View File

@@ -209,7 +209,7 @@
quickbind_desc = "Returns you to Reebe."
/datum/clockwork_scripture/abscond/check_special_requirements()
if(invoker.z == ZLEVEL_CITYOFCOGS)
if(is_reebe(invoker.z))
to_chat(invoker, "<span class='danger'>You're already at Reebe.</span>")
return
return TRUE

View File

@@ -70,6 +70,12 @@
quickbind = TRUE
quickbind_desc = "Creates a Vitality Matrix, which drains non-Servants on it to heal Servants that cross it."
/datum/clockwork_scripture/create_object/vitality_matrix/check_special_requirements()
if(locate(object_path) in range(1, invoker))
to_chat(invoker, "<span class='danger'>Vitality matrices placed next to each other could interfere and cause a feedback loop! Move away from the other ones!</span>")
return FALSE
return ..()
//Judicial Visor: Creates a judicial visor, which can smite an area.
/datum/clockwork_scripture/create_object/judicial_visor

View File

@@ -3,7 +3,7 @@
name = "pressure sensor"
desc = "A thin plate of brass, barely visible but clearly distinct."
clockwork_desc = "A trigger that will activate when a non-servant runs across it."
max_integrity = 25
max_integrity = 5
icon_state = "pressure_sensor"
alpha = 80
layer = LOW_ITEM_LAYER

View File

@@ -21,9 +21,10 @@
STOP_PROCESSING(SSfastprocess, src)
if(buckled_mobs && buckled_mobs.len)
var/mob/living/L = buckled_mobs[1]
L.Knockdown(100)
L.visible_message("<span class='warning'>[L] is maimed as the skewer shatters while still in their body!</span>")
L.adjustBruteLoss(15)
if(iscarbon(L))
L.Knockdown(100)
L.visible_message("<span class='warning'>[L] is maimed as the skewer shatters while still in their body!</span>")
L.adjustBruteLoss(15)
unbuckle_mob(L)
return ..()
@@ -48,14 +49,22 @@
/obj/structure/destructible/clockwork/trap/brass_skewer/activate()
if(density)
return
var/mob/living/carbon/squirrel = locate() in get_turf(src)
var/mob/living/squirrel = locate() in get_turf(src)
if(squirrel)
squirrel.visible_message("<span class='boldwarning'>A massive brass spike erupts from the ground, impaling [squirrel]!</span>", \
"<span class='userdanger'>A massive brass spike rams through your chest, hoisting you into the air!</span>")
squirrel.emote("scream")
playsound(squirrel, 'sound/effects/splat.ogg', 50, TRUE)
playsound(squirrel, 'sound/misc/desceration-03.ogg', 50, TRUE)
squirrel.apply_damage(20, BRUTE, "chest")
if(iscyborg(squirrel))
if(!squirrel.stat)
squirrel.visible_message("<span class='boldwarning'>A massive brass spike erupts from the ground, rending [squirrel]'s chassis but shattering into pieces!</span>", \
"<span class='userdanger'>A massive brass spike rips through your chassis and bursts into shrapnel in your casing!</span>")
squirrel.adjustBruteLoss(50)
squirrel.Stun(20)
addtimer(CALLBACK(src, .proc/take_damage, max_integrity), 1)
else
squirrel.visible_message("<span class='boldwarning'>A massive brass spike erupts from the ground, impaling [squirrel]!</span>", \
"<span class='userdanger'>A massive brass spike rams through your chest, hoisting you into the air!</span>")
squirrel.emote("scream")
playsound(squirrel, 'sound/effects/splat.ogg', 50, TRUE)
playsound(squirrel, 'sound/misc/desceration-03.ogg', 50, TRUE)
squirrel.apply_damage(20, BRUTE, "chest")
mouse_opacity = MOUSE_OPACITY_OPAQUE //So players can interact with the tile it's on to pull them off
buckle_mob(squirrel, TRUE)
else

View File

@@ -203,7 +203,7 @@ This file contains the arcane tome files.
A = get_area(src)
if(!src || QDELETED(src) || !Adjacent(user) || user.incapacitated() || !check_rune_turf(Turf, user))
return
//AAAAAAAAAAAAAAAH, i'm rewriting enough for now so TODO: remove this shit
if(ispath(rune_to_scribe, /obj/effect/rune/narsie))
if(!summon_objective)
@@ -265,8 +265,7 @@ This file contains the arcane tome files.
if(locate(/obj/effect/rune) in T)
to_chat(user, "<span class='cult'>There is already a rune here.</span>")
return FALSE
if(!(T.z in GLOB.station_z_levels) && T.z != ZLEVEL_MINING)
if(!is_station_level(T.z) && !is_mining_level(T.z))
to_chat(user, "<span class='warning'>The veil is not weak enough here.</span>")
return FALSE

View File

@@ -268,7 +268,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/list/teleportnames = list()
for(var/R in GLOB.teleport_runes)
var/obj/effect/rune/teleport/T = R
if(T != src && (T.z <= ZLEVEL_SPACEMAX))
if(T != src && !is_away_level(T.z))
potential_runes[avoid_assoc_duplicate_keys(T.listkey, teleportnames)] = T
if(!potential_runes.len)
@@ -277,8 +277,9 @@ structure_check() searches for nearby cultist structures required for the invoca
fail_invoke()
return
if(user.z > ZLEVEL_SPACEMAX)
to_chat(user, "<span class='cultitalic'>You are not in the right dimension!</span>")
var/turf/T = get_turf(src)
if(is_away_level(T.z))
to_chat(user, "<span class='cult italic'>You are not in the right dimension!</span>")
log_game("Teleport rune failed - user in away mission")
fail_invoke()
return
@@ -289,7 +290,6 @@ structure_check() searches for nearby cultist structures required for the invoca
fail_invoke()
return
var/turf/T = get_turf(src)
var/turf/target = get_turf(actual_selected_rune)
if(is_blocked_turf(target, TRUE))
to_chat(user, "<span class='warning'>The target rune is blocked. Attempting to teleport to it would be massively unwise.</span>")
@@ -479,7 +479,7 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/narsie/invoke(var/list/invokers)
if(used)
return
if(!(z in GLOB.station_z_levels))
if(!is_station_level(z))
return
if(locate(/obj/singularity/narsie) in GLOB.poi_list)
@@ -815,8 +815,8 @@ structure_check() searches for nearby cultist structures required for the invoca
fail_invoke()
log_game("Summon Cultist rune failed - target was deconverted")
return
if(cultist_to_summon.z > ZLEVEL_SPACEMAX)
to_chat(user, "<span class='cultitalic'>[cultist_to_summon] is not in our dimension!</span>")
if(is_away_level(cultist_to_summon.z))
to_chat(user, "<span class='cult italic'>[cultist_to_summon] is not in our dimension!</span>")
fail_invoke()
log_game("Summon Cultist rune failed - target in away mission")
return

View File

@@ -65,8 +65,8 @@
log_game("Teleport talisman failed - no other teleport runes")
return ..(user, 0)
if(user.z > ZLEVEL_SPACEMAX)
to_chat(user, "<span class='cultitalic'>You are not in the right dimension!</span>")
if(is_away_level(user.z))
to_chat(user, "<span class='cult italic'>You are not in the right dimension!</span>")
log_game("Teleport talisman failed - user in away mission")
return ..(user, 0)

View File

@@ -67,10 +67,7 @@
//Left hand items
for(var/obj/item/I in held_items)
if(!(I.flags_1 & ABSTRACT_1))
if(I.blood_DNA)
msg += "<span class='warning'>It is holding [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!</span>\n"
else
msg += "It is holding [icon2html(I, user)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
msg += "It is holding [I.get_examine_string(user)] in its [get_held_index_name(get_held_index_of_item(I))].\n"
//Braindead
if(!client && stat != DEAD)

View File

@@ -1,7 +1,7 @@
/proc/power_failure()
priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", 'sound/ai/poweroff.ogg')
for(var/obj/machinery/power/smes/S in GLOB.machines)
if(istype(get_area(S), /area/ai_monitored/turret_protected) || !(S.z in GLOB.station_z_levels))
if(istype(get_area(S), /area/ai_monitored/turret_protected) || !is_station_level(S.z))
continue
S.charge = 0
S.output_level = 0
@@ -22,7 +22,7 @@
break
if(A.contents)
for(var/atom/AT in A.contents)
if(!(AT.z in GLOB.station_z_levels)) //Only check one, it's enough.
if(!is_station_level(AT.z)) //Only check one, it's enough.
skip = 1
break
if(skip)
@@ -33,7 +33,7 @@
A.power_change()
for(var/obj/machinery/power/apc/C in GLOB.apcs_list)
if(C.cell && (C.z in GLOB.station_z_levels))
if(C.cell && is_station_level(C.z))
var/area/A = C.area
var/skip = 0
@@ -50,11 +50,11 @@
priority_announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", 'sound/ai/poweron.ogg')
for(var/obj/machinery/power/apc/C in GLOB.machines)
if(C.cell && (C.z in GLOB.station_z_levels))
if(C.cell && is_station_level(C.z))
C.cell.charge = C.cell.maxcharge
C.failure_timer = 0
for(var/obj/machinery/power/smes/S in GLOB.machines)
if(!(S.z in GLOB.station_z_levels))
if(!is_station_level(S.z))
continue
S.charge = S.capacity
S.output_level = S.output_level_max
@@ -72,7 +72,7 @@
priority_announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", 'sound/ai/poweron.ogg')
for(var/obj/machinery/power/smes/S in GLOB.machines)
if(!(S.z in GLOB.station_z_levels))
if(!is_station_level(S.z))
continue
S.charge = S.capacity
S.output_level = S.output_level_max

View File

@@ -233,7 +233,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/datum/action/innate/ai/nuke_station/Activate()
var/turf/T = get_turf(owner)
if(!istype(T) || !(T.z in GLOB.station_z_levels))
if(!istype(T) || !is_station_level(T.z))
to_chat(owner, "<span class='warning'>You cannot activate the doomsday device while off-station!</span>")
return
if(alert(owner, "Send arming signal? (true = arm, false = cancel)", "purge_all_life()", "confirm = TRUE;", "confirm = FALSE;") != "confirm = TRUE;")
@@ -356,7 +356,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/obj/machinery/doomsday_device/process()
var/turf/T = get_turf(src)
if(!T || !(T.z in GLOB.station_z_levels))
if(!T || !is_station_level(T.z))
minor_announce("DOOMSDAY DEVICE OUT OF STATION RANGE, ABORTING", "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4", TRUE)
SSshuttle.clearHostileEnvironment(src)
qdel(src)
@@ -378,7 +378,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
for(var/i in GLOB.mob_living_list)
var/mob/living/L = i
var/turf/T = get_turf(L)
if(!T || !(T.z in GLOB.station_z_levels))
if(!T || !is_station_level(T.z))
continue
if(issilicon(L))
continue
@@ -425,7 +425,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/datum/action/innate/ai/lockdown/Activate()
for(var/obj/machinery/door/D in GLOB.airlocks)
if(!(D.z in GLOB.station_z_levels))
if(!is_station_level(D.z))
continue
INVOKE_ASYNC(D, /obj/machinery/door.proc/hostile_lockdown, owner)
addtimer(CALLBACK(D, /obj/machinery/door.proc/disable_lockdown), 900)
@@ -503,7 +503,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/datum/action/innate/ai/break_fire_alarms/Activate()
for(var/obj/machinery/firealarm/F in GLOB.machines)
if(!(F.z in GLOB.station_z_levels))
if(!is_station_level(F.z))
continue
F.emagged = TRUE
to_chat(owner, "<span class='notice'>All thermal sensors on the station have been disabled. Fire alerts will no longer be recognized.</span>")
@@ -530,7 +530,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/datum/action/innate/ai/break_air_alarms/Activate()
for(var/obj/machinery/airalarm/AA in GLOB.machines)
if(!(AA.z in GLOB.station_z_levels))
if(!is_station_level(AA.z))
continue
AA.emagged = TRUE
to_chat(owner, "<span class='notice'>All air alarm safeties on the station have been overriden. Air alarms may now use the Flood environmental mode.</span>")
@@ -753,7 +753,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
/datum/action/innate/ai/emergency_lights/Activate()
for(var/obj/machinery/light/L in GLOB.machines)
if(L.z in GLOB.station_z_levels)
if(is_station_level(L.z))
L.no_emergency = TRUE
INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE)
CHECK_TICK

View File

@@ -27,7 +27,7 @@
if(QDELETED(temp_vent))
continue
if(temp_vent.loc.z == ZLEVEL_STATION_PRIMARY && !temp_vent.welded)
var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1
var/datum/pipeline/temp_vent_parent = temp_vent.parents[1]
if(temp_vent_parent.other_atmosmch.len > 20)
vents += temp_vent

View File

@@ -454,7 +454,7 @@
if(target == src)
return
if(!(z in GLOB.station_z_levels) && z != ZLEVEL_LAVALAND)
if(!is_station_level(z) && !is_mining_level(z))
to_chat(src, "<span class='warning'>Our bluespace transceiver cannot locate a viable bluespace link, our teleportation abilities are useless in this area.</span>")
return

View File

@@ -67,7 +67,7 @@
var/datum/disease/D = new /datum/disease/transformation/jungle_fever() //ugly but unfortunately needed
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
if(!(H.z in GLOB.station_z_levels))
if(!is_station_level(H.z))
continue
if(H.mind && H.client && H.stat != DEAD)
if(H.HasDisease(D))

View File

@@ -67,7 +67,7 @@
if(GLOB.player_list.len < CHALLENGE_MIN_PLAYERS)
to_chat(user, "The enemy crew is too small to be worth declaring war on.")
return FALSE
if(user.z != ZLEVEL_CENTCOM)
if(!user.onSyndieBase())
to_chat(user, "You have to be at your base to use this.")
return FALSE
if(world.time-SSticker.round_start_time > CHALLENGE_TIME_LIMIT)

View File

@@ -451,12 +451,12 @@
var/off_station = 0
var/turf/bomb_location = get_turf(src)
var/area/A = get_area(bomb_location)
if(bomb_location && (bomb_location.z in GLOB.station_z_levels))
if(bomb_location && is_station_level(bomb_location.z))
if(istype(A, /area/space))
off_station = NUKE_NEAR_MISS
if((bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)))
off_station = NUKE_NEAR_MISS
else if((istype(A, /area/syndicate_mothership) || (istype(A, /area/shuttle/syndicate)) && bomb_location.z == ZLEVEL_CENTCOM))
else if(bomb_location.onSyndieBase())
off_station = NUKE_SYNDICATE_BASE
else
off_station = NUKE_MISS_STATION
@@ -556,7 +556,7 @@ This is here to make the tiles around the station mininuke change when it's arme
addtimer(CALLBACK(user, /atom/proc/add_atom_colour, (i % 2)? "#00FF00" : "#FF0000", ADMIN_COLOUR_PRIORITY), i)
addtimer(CALLBACK(src, .proc/manual_suicide, user), 101)
return MANUAL_SUICIDE
/obj/item/disk/proc/manual_suicide(mob/living/user)
user.remove_atom_colour(ADMIN_COLOUR_PRIORITY)
user.visible_message("<span class='suicide'>[user] was destroyed by the nuclear blast!</span>")

View File

@@ -154,7 +154,7 @@
if(!target || !considered_alive(target) || considered_afk(target))
return TRUE
var/turf/T = get_turf(target.current)
return T && !(T.z in GLOB.station_z_levels)
return T && !is_station_level(T.z)
/datum/objective/mutiny/update_explanation_text()
..()

View File

@@ -164,7 +164,7 @@
/datum/game_mode/revolution/proc/check_heads_victory()
for(var/datum/mind/rev_mind in revolution.head_revolutionaries())
var/turf/T = get_turf(rev_mind.current)
if(!considered_afk(rev_mind) && considered_alive(rev_mind) && (T.z in GLOB.station_z_levels))
if(!considered_afk(rev_mind) && considered_alive(rev_mind) && is_station_level(T.z))
if(ishuman(rev_mind.current))
return FALSE
return TRUE

View File

@@ -213,7 +213,7 @@
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
var/mob/living/carbon/human/target = null
var/list/mob/living/carbon/human/possible = list()
var/obj/item/linked_item = null
var/obj/item/voodoo_link = null
var/cooldown_time = 30 //3s
var/cooldown = 0
max_integrity = 10
@@ -237,10 +237,10 @@
cooldown = world.time +cooldown_time
return
if(!linked_item)
if(!voodoo_link)
if(I.loc == user && istype(I) && I.w_class <= WEIGHT_CLASS_SMALL)
if (user.transferItemToLoc(I,src))
linked_item = I
voodoo_link = I
to_chat(user, "You attach [I] to the doll.")
update_targets()
@@ -255,11 +255,11 @@
return
if(user.zone_selected == "chest")
if(linked_item)
if(voodoo_link)
target = null
linked_item.forceMove(drop_location())
to_chat(user, "<span class='notice'>You remove the [linked_item] from the doll.</span>")
linked_item = null
voodoo_link.forceMove(drop_location())
to_chat(user, "<span class='notice'>You remove the [voodoo_link] from the doll.</span>")
voodoo_link = null
update_targets()
return
@@ -291,10 +291,13 @@
/obj/item/voodoo/proc/update_targets()
possible = list()
if(!linked_item)
if(!voodoo_link)
return
var/list/prints = voodoo_link.return_fingerprints()
if(!length(prints))
return FALSE
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
if(md5(H.dna.uni_identity) in linked_item.fingerprints)
if(prints[md5(H.dna.uni_identity)])
possible |= H
/obj/item/voodoo/proc/GiveHint(mob/victim,force=0)

View File

@@ -149,8 +149,6 @@
if(href_list["make"])
var/turf/T = loc
/////////////////
//href protection
being_built = stored_research.isDesignResearchedID(href_list["make"])
@@ -174,34 +172,8 @@
use_power(power)
icon_state = "autolathe"
flick("autolathe_n",src)
if(is_stack)
spawn(32*coeff)
use_power(power)
var/list/materials_used = list(MAT_METAL=metal_cost*multiplier, MAT_GLASS=glass_cost*multiplier)
materials.use_amount(materials_used)
var/obj/item/stack/N = new being_built.build_path(T, multiplier)
N.update_icon()
N.autolathe_crafted(src)
for(var/obj/item/stack/S in T.contents - N)
if(istype(S, N.merge_type))
N.merge(S)
busy = FALSE
updateUsrDialog()
else
spawn(32*coeff*multiplier)
use_power(power)
var/list/materials_used = list(MAT_METAL=metal_cost*coeff*multiplier, MAT_GLASS=glass_cost*coeff*multiplier)
materials.use_amount(materials_used)
for(var/i=1, i<=multiplier, i++)
var/obj/item/new_item = new being_built.build_path(T)
for(var/mat in materials_used)
new_item.materials[mat] = materials_used[mat] / multiplier
new_item.autolathe_crafted(src)
busy = FALSE
updateUsrDialog()
var/time = is_stack ? 32 : 32*coeff*multiplier
addtimer(CALLBACK(src, .proc/make_item, power, metal_cost, glass_cost, multiplier, coeff, is_stack), time)
if(href_list["search"])
matching_designs.Cut()
@@ -218,6 +190,30 @@
return
/obj/machinery/autolathe/proc/make_item(power, metal_cost, glass_cost, multiplier, coeff, is_stack)
GET_COMPONENT(materials, /datum/component/material_container)
var/atom/A = drop_location()
use_power(power)
var/list/materials_used = list(MAT_METAL=metal_cost*coeff*multiplier, MAT_GLASS=glass_cost*coeff*multiplier)
materials.use_amount(materials_used)
if(is_stack)
var/obj/item/stack/N = new being_built.build_path(A, multiplier)
N.update_icon()
N.autolathe_crafted(src)
for(var/obj/item/stack/S in (A.contents - N))
if(istype(S, N.merge_type))
N.merge(S)
else
for(var/i=1, i<=multiplier, i++)
var/obj/item/new_item = new being_built.build_path(A)
for(var/mat in materials_used)
new_item.materials[mat] = materials_used[mat] / multiplier
new_item.autolathe_crafted(src)
busy = FALSE
updateDialog()
/obj/machinery/autolathe/RefreshParts()
var/T = 0
for(var/obj/item/stock_parts/matter_bin/MB in component_parts)

View File

@@ -59,7 +59,7 @@
if(..())
return
src.add_fingerprint(usr)
var/dat = "[world.name] secure vault. Authorized personnel only.<br>"
var/dat = "[station_name()] secure vault. Authorized personnel only.<br>"
dat += "Current Balance: [SSshuttle.points] credits.<br>"
if(!siphoning)
dat += "<A href='?src=[REF(src)];siphon=1'>Siphon Credits</A><br>"

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