Overhauls and 2/28 sync (#244)

* map tweaks/shuttle engines

* helpers and defines

* global/onclick

* controllers and datums

* mapping

* game folder

* some other stuff

* some modules

* modules that aren't mobs

* some mob stuff

* new player stuff

* mob living

* silicon stuff

* simple animal things

* carbon/ayylmao

* update_icons

* carbon/human

* sounds and tools

* icons and stuff

* hippie grinder changes + tgui

* kitchen.dmi

* compile issues fixed

* mapfix

* Mapfixes 2.0

* mapedit2.0

* mapmerger pls

* Revert "mapedit2.0"

This reverts commit 74139a3cacea10df7aafca06c0a10bd3daf3a481.

* clean up vore folder + 2 hotfixes

* admin ticket refinement

* Blob tweaks and LAZYADD

* LAZYADD IS LAZY

* Magic strings purged

* DEFINES NEED HIGHER PRIORITIES

* Only a sleepless idiot deals in absolute TRUE|FALSE

* u h g

* progress bar fix

* reverts ticket logs

* there's always that one guy

* fixes and stuff

* 2/27 fixes

* game folder stuff

* stats

* some modules again

* clothing stuff

gets vg clothing out of the main files

* everything not mobs again

* mob stuff

* maps, tgui, sql stuff

* icons

* additional fixes and compile errors

* don't need this anymore

* Oh right this isn't needed anymore

* maint bar re-added

* that doesn't need to be here

* stupid events

* wtfeven

* probably makes Travis happy

* don't care to fix the grinder atm

* fixes vending sprites, changes turret

* lethal, not lethals

* overylays are finicky creatures

* lazy fix for bleeding edgy (#252)

* map tweaks/shuttle engines

* helpers and defines

* global/onclick

* controllers and datums

* mapping

* game folder

* some other stuff

* some modules

* modules that aren't mobs

* some mob stuff

* new player stuff

* mob living

* silicon stuff

* simple animal things

* carbon/ayylmao

* update_icons

* carbon/human

* sounds and tools

* icons and stuff

* hippie grinder changes + tgui

* kitchen.dmi

* compile issues fixed

* mapfix

* Mapfixes 2.0

* mapedit2.0

* mapmerger pls

* Revert "mapedit2.0"

This reverts commit 74139a3cacea10df7aafca06c0a10bd3daf3a481.

* clean up vore folder + 2 hotfixes

* admin ticket refinement

* Blob tweaks and LAZYADD

* LAZYADD IS LAZY

* Magic strings purged

* DEFINES NEED HIGHER PRIORITIES

* Only a sleepless idiot deals in absolute TRUE|FALSE

* u h g

* progress bar fix

* reverts ticket logs

* there's always that one guy

* fixes and stuff

* 2/27 fixes

* game folder stuff

* stats

* some modules again

* clothing stuff

gets vg clothing out of the main files

* everything not mobs again

* mob stuff

* maps, tgui, sql stuff

* icons

* additional fixes and compile errors

* don't need this anymore

* Oh right this isn't needed anymore

* maint bar re-added

* that doesn't need to be here

* stupid events

* wtfeven

* probably makes Travis happy

* don't care to fix the grinder atm

* fixes vending sprites, changes turret

* lethal, not lethals

* overylays are finicky creatures
This commit is contained in:
Poojawa
2017-02-28 09:30:49 -06:00
committed by GitHub
parent 93782cf716
commit 0bca862419
544 changed files with 309981 additions and 81206 deletions
+12
View File
@@ -64,3 +64,15 @@
#define MILK_RATE 5
#define MILK_RATE_MULT 1
#define MILK_EFFICIENCY 1
// Admin ticket things
#define TICKET_RESOLVED "Yes"
#define TICKET_UNRESOLVED "No"
#define TICKET_UNASSIGNED "N/A"
#define TICKET_REPLIED "Yes"
#define TICKET_UNREPLIED "No"
#define TICKET_INACTIVE "No"
#define TICKET_ACTIVE "Yes"
+9 -4
View File
@@ -12,7 +12,8 @@ var/global/list/clockwork_generals_invoked = list("nezbere" = FALSE, "sevtug" =
var/global/list/all_clockwork_objects = list() //All clockwork items, structures, and effects in existence
var/global/list/all_clockwork_mobs = list() //All clockwork SERVANTS (not creatures) in existence
var/global/list/clockwork_component_cache = list(BELLIGERENT_EYE = 0, VANGUARD_COGWHEEL = 0, GEIS_CAPACITOR = 0, REPLICANT_ALLOY = 0, HIEROPHANT_ANSIBLE = 0) //The pool of components that caches draw from
var/global/ratvar_awakens = 0 //If Ratvar has been summoned; not a boolean, for proper handling of multiple ratvars
var/global/ratvar_awakens = 0 //If Ratvar has been summoned; not a boolean, for proper handling of multiple Ratvars
var/global/nezbere_invoked = 0 //If Nezbere has been invoked; not a boolean, for proper handling of multiple Nezberes
var/global/clockwork_gateway_activated = FALSE //if a gateway to the celestial derelict has ever been successfully activated
var/global/list/all_scripture = list() //a list containing scripture instances; not used to track existing scripture
@@ -48,7 +49,9 @@ var/global/list/all_scripture = list() //a list containing scripture instances;
#define MAX_COMPONENTS_BEFORE_RAND (10*LOWER_PROB_PER_COMPONENT) //the number of each component, times LOWER_PROB_PER_COMPONENT, you need to have before component generation will become random
#define CLOCKWORK_GENERAL_COOLDOWN 3000 //how long clockwork generals go on cooldown after use, defaults to 5 minutes
#define GLOBAL_CLOCKWORK_GENERAL_COOLDOWN 3000 //how long globally-affecting clockwork generals go on cooldown after use, defaults to 5 minutes
#define CLOCKWORK_GENERAL_COOLDOWN 2000 //how long clockwork generals go on cooldown after use, defaults to 3 minutes 20 seconds
//clockcult power defines
#define MIN_CLOCKCULT_POWER 25 //the minimum amount of power clockcult machines will handle gracefully
@@ -83,9 +86,9 @@ var/global/list/all_scripture = list() //a list containing scripture instances;
#define GATEWAY_RATVAR_ARRIVAL 300 //when progress is at or above this, game over ratvar's here everybody go home
//Objective defines
#define CLOCKCULT_GATEWAY "gateway"
#define CLOCKCULT_GATEWAY "summon ratvar"
#define CLOCKCULT_ESCAPE "escape"
#define CLOCKCULT_ESCAPE "proselytize the station"
//misc clockcult stuff
#define MARAUDER_EMERGE_THRESHOLD 65 //marauders cannot emerge unless host is at this% or less health
@@ -95,3 +98,5 @@ var/global/list/all_scripture = list() //a list containing scripture instances;
#define PROSELYTIZER_REPAIR_PER_TICK 4 //how much a proselytizer repairs each tick, and also how many deciseconds each tick is
#define OCULAR_WARDEN_EXCLUSION_RANGE 3 //the range at which ocular wardens cannot be placed near other ocular wardens
#define RATVARIAN_SPEAR_DURATION 1800 //how long ratvarian spears last; defaults to 3 minutes
+9
View File
@@ -132,4 +132,13 @@
#define IS_SHARP 1
#define IS_SHARP_ACCURATE 2
//His Grace.
#define HIS_GRACE_SATIATED 0 //He hungers not. If bloodthirst is set to this, His Grace is asleep.
#define HIS_GRACE_PECKISH 20 //Slightly hungry.
#define HIS_GRACE_HUNGRY 60 //Getting closer. Increases damage up to a minimum of 20.
#define HIS_GRACE_FAMISHED 100 //Dangerous. Increases damage up to a minimum of 25 and cannot be dropped.
#define HIS_GRACE_STARVING 120 //Incredibly close to breaking loose. Increases damage up to a minimum of 30.
#define HIS_GRACE_CONSUME_OWNER 140 //His Grace consumes His owner at this point and becomes aggressive.
#define HIS_GRACE_FALL_ASLEEP 160 //If it reaches this point, He falls asleep and resets.
#define HIS_GRACE_FORCE_BONUS 4 //How much force is gained per kill.
+7 -2
View File
@@ -9,6 +9,7 @@
#define GIRDER_DISPLACED 3
#define GIRDER_DISASSEMBLED 4
//rwall construction states
#define INTACT 0
#define SUPPORT_LINES 1
@@ -18,6 +19,10 @@
#define SUPPORT_RODS 5
#define SHEATH 6
//plastic flaps construction states
#define PLASTIC_FLAPS_NORMAL 0
#define PLASTIC_FLAPS_DETACHED 1
//default_unfasten_wrench() return defines
#define CANT_UNFASTEN 0
#define FAILED_UNFASTEN 1
@@ -49,8 +54,7 @@
//Construction defines for the pinion airlock
#define GEAR_SECURE 1
#define GEAR_UNFASTENED 2
#define GEAR_LOOSE 3
#define GEAR_LOOSE 2
//other construction-related things
@@ -68,6 +72,7 @@
#define MAT_DIAMOND "$diamond"
#define MAT_URANIUM "$uranium"
#define MAT_PLASMA "$plasma"
#define MAT_BLUESPACE "$bluespace"
#define MAT_BANANIUM "$bananium"
#define MAT_TITANIUM "$titanium"
#define MAT_BIOMASS "$biomass"
+1 -1
View File
@@ -16,7 +16,7 @@
#define CONDUCT 64 // conducts electricity (metal etc.)
#define ABSTRACT 128 // for all things that are technically items but used for various different stuff, made it 128 because it could conflict with other flags other way
#define NODECONSTRUCT 128 // For machines and structures that should not break into parts, eg, holodeck stuff
#define FPRINT 256 // takes a fingerprint
#define OVERLAY_QUEUED 256 //atom queued to SSoverlay
#define ON_BORDER 512 // item has priority to check when entering or leaving
#define EARBANGPROTECT 1024
+2
View File
@@ -128,6 +128,8 @@ var/list/static/global/pointed_types = typecacheof(list(
#define is_pointed(W) (is_type_in_typecache(W, pointed_types))
#define isbodypart(A) (istype(A, /obj/item/bodypart))
//Assemblies
#define isassembly(O) (istype(O, /obj/item/device/assembly))
+3
View File
@@ -74,3 +74,6 @@
#define HUD_LAYER 19
#define ABOVE_HUD_PLANE 20
#define ABOVE_HUD_LAYER 20
#define SPLASHSCREEN_LAYER 21
#define SPLASHSCREEN_PLANE 21
+4
View File
@@ -16,8 +16,12 @@
#define STATUS_EFFECT_POWERREGEN /datum/status_effect/cyborg_power_regen //Regenerates power on a given cyborg over time
#define STATUS_EFFECT_HISGRACE /datum/status_effect/his_grace //His Grace.
/////////////
// DEBUFFS //
/////////////
#define STATUS_EFFECT_SIGILMARK /datum/status_effect/sigil_mark
#define STATUS_EFFECT_HISWRATH /datum/status_effect/his_wrath //His Wrath.
+1 -1
View File
@@ -3,5 +3,5 @@
#define TICK_LIMIT_MC 70
#define TICK_LIMIT_MC_INIT_DEFAULT 98
#define TICK_CHECK ( world.tick_usage > CURRENT_TICKLIMIT ? stoplag() : 0 )
#define TICK_CHECK ( world.tick_usage > CURRENT_TICKLIMIT )
#define CHECK_TICK if (world.tick_usage > CURRENT_TICKLIMIT) stoplag()
@@ -465,4 +465,35 @@
#define LAZYADD(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 LAZYLEN(L) length(L)
#define LAZYCLEARLIST(L) if(L) L.Cut()
#define LAZYCLEARLIST(L) if(L) L.Cut()
/* Definining a counter as a series of key -> numeric value entries
* All these procs modify in place.
*/
/proc/counterlist_scale(list/L, scalar)
var/list/out = list()
for(var/key in L)
out[key] = L[key] * scalar
. = out
/proc/counterlist_sum(list/L)
. = 0
for(var/key in L)
. += L[key]
/proc/counterlist_normalise(list/L)
var/avg = counterlist_sum(L)
if(avg != 0)
. = counterlist_scale(L, 1 / avg)
else
. = L
/proc/counterlist_combine(list/L1, list/L2)
for(var/key in L2)
var/other_value = L2[key]
if(key in L1)
L1[key] += other_value
else
L1[key] = other_value
+8 -2
View File
@@ -22,9 +22,15 @@
if (config.log_admin)
diary << "\[[time_stamp()]]ADMIN: [text]"
//Items using this proc are stripped from public logs - use with caution
/proc/log_admin_private(text)
admin_log.Add(text)
if (config.log_admin)
diary << "\[[time_stamp()]]ADMINPRIVATE: [text]"
/proc/log_adminsay(text)
if (config.log_adminchat)
log_admin("ASAY: [text]")
log_admin_private("ASAY: [text]")
/proc/log_dsay(text)
if (config.log_adminchat)
@@ -108,4 +114,4 @@
if(istype(T))
return "[A.loc] [COORD(T)] ([A.loc.type])"
else if(A.loc)
return "[A.loc] (0, 0, 0) ([A.loc.type])"
return "[A.loc] (0, 0, 0) ([A.loc.type])"
+2 -8
View File
@@ -17,12 +17,6 @@
var/area/Y = get_area(X)
return Y.name
/proc/get_area_master(O)
var/area/A = get_area(O)
if(A && A.master)
A = A.master
return A
/proc/get_area_by_name(N) //get area by its name
for(var/area/A in world)
if(A.name == N)
@@ -81,13 +75,13 @@
return heard
/proc/alone_in_area(area/the_area, mob/must_be_alone, check_type = /mob/living/carbon)
var/area/our_area = get_area_master(the_area)
var/area/our_area = get_area(the_area)
for(var/C in living_mob_list)
if(!istype(C, check_type))
continue
if(C == must_be_alone)
continue
if(our_area == get_area_master(C))
if(our_area == get_area(C))
return 0
return 1
+15 -16
View File
@@ -238,32 +238,31 @@
else if(adjacencies & N_EAST)
se = "4-e"
var/list/New = list()
var/list/New
if(A.top_left_corner != nw)
A.overlays -= A.top_left_corner
A.cut_overlay(A.top_left_corner)
A.top_left_corner = nw
New += nw
LAZYADD(New, nw)
if(A.top_right_corner != ne)
A.overlays -= A.top_right_corner
A.cut_overlay(A.top_right_corner)
A.top_right_corner = ne
New += ne
LAZYADD(New, ne)
if(A.bottom_right_corner != sw)
A.overlays -= A.bottom_right_corner
A.cut_overlay(A.bottom_right_corner)
A.bottom_right_corner = sw
New += sw
LAZYADD(New, sw)
if(A.bottom_left_corner != se)
A.overlays -= A.bottom_left_corner
A.cut_overlay(A.bottom_left_corner)
A.bottom_left_corner = se
New += se
if(New.len)
LAZYADD(New, se)
if(New)
A.add_overlay(New)
/proc/find_type_in_direction(atom/source, direction)
var/turf/target_turf = get_step(source, direction)
if(!target_turf)
@@ -312,13 +311,13 @@
queue_smooth(A)
/atom/proc/clear_smooth_overlays()
overlays -= top_left_corner
cut_overlay(top_left_corner)
top_left_corner = null
overlays -= top_right_corner
cut_overlay(top_right_corner)
top_right_corner = null
overlays -= bottom_right_corner
cut_overlay(bottom_right_corner)
bottom_right_corner = null
overlays -= bottom_left_corner
cut_overlay(bottom_left_corner)
bottom_left_corner = null
/atom/proc/replace_smooth_overlays(nw, ne, sw, se)
-21
View File
@@ -943,27 +943,6 @@ var/global/list/friendly_animal_types = list()
return J
return 0
/atom/proc/cut_overlays()
overlays.Cut()
overlays += priority_overlays
/atom/proc/add_overlay(image, priority = 0)
var/list/new_overlays = overlays.Copy()
new_overlays -= image
if(priority)
if(!priority_overlays)
priority_overlays = list()
priority_overlays += image
new_overlays += image
else
if(priority_overlays)
new_overlays -= priority_overlays
new_overlays += image
new_overlays += priority_overlays
else
new_overlays += image
overlays = new_overlays
var/global/list/humanoid_icon_cache = list()
//For creating consistent icons for human looking simple animals
/proc/get_flat_human_icon(var/icon_id,var/outfit,var/datum/preferences/prefs)
+4 -2
View File
@@ -21,8 +21,10 @@
//return 1
//returns timestamp in a sql and ISO 8601 friendly format
/proc/SQLtime()
return time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
/proc/SQLtime(timevar)
if(!timevar)
timevar = world.realtime
return time2text(timevar, "YYYY-MM-DD hh:mm:ss")
/var/midnight_rollovers = 0
+58 -1
View File
@@ -1191,7 +1191,7 @@ B --><-- A
return
A.add_overlay(I)
sleep(duration)
A.overlays -= I
A.cut_overlay(I)
/proc/get_areas_in_z(zlevel)
. = list()
@@ -1286,6 +1286,7 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
#define RANDOM_COLOUR (rgb(rand(0,255),rand(0,255),rand(0,255)))
#define QDEL_IN(item, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, item), time, TIMER_STOPPABLE)
#define QDEL_NULL(item) qdel(item); item = null
/proc/random_nukecode()
var/val = rand(0, 99999)
@@ -1336,3 +1337,59 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
if(W.ini_dir == dir_to_check || W.ini_dir == FULLTILE_WINDOW_DIR || dir_to_check == FULLTILE_WINDOW_DIR)
return FALSE
return TRUE
//WHATEVER YOU USE THIS FOR MUST BE SANITIZED TO SHIT, IT USES SHELL
//It also sleeps
//Set this to TRUE before calling
//This prevents RCEs from badmins
//kevinz000 if you touch this I will hunt you down
var/valid_HTTPSGet = FALSE
/proc/HTTPSGet(url)
if(findtext(url, "\""))
valid_HTTPSGet = FALSE
if(!valid_HTTPSGet)
if(usr)
CRASH("[usr.ckey]([usr]) just attempted an invalid HTTPSGet on: [url]!")
else
CRASH("Invalid HTTPSGet call on: [url]")
valid_HTTPSGet = FALSE
//"This has got to be the ugliest hack I have ever done"
//warning, here be dragons
/*
| @___oo
/\ /\ / (__,,,,|
) /^\) ^\/ _)
) /^\/ _)
) _ / / _)
/\ )/\/ || | )_)
< > |(,,) )__)
|| / \)___)\
| \____( )___) )___
\______(_______;;; __;;;
*/
var/temp_file = "HTTPSGetOutput.txt"
var/command
if(world.system_type == MS_WINDOWS)
command = "powershell -Command \"wget [url] -OutFile [temp_file]\""
else if(world.system_type == UNIX)
command = "wget -O [temp_file] [url]"
else
CRASH("Invalid world.system_type ([world.system_type])? Yell at Lummox.")
world.log << "HTTPSGet: [url]"
var/result = shell(command)
if(result != 0)
world.log << "Download failed: shell exited with code: [result]"
return
var/f = file(temp_file)
if(!f)
world.log << "Download failed: Temp file not found"
return
. = file2text(f)
f = null
fdel(temp_file)
-3
View File
@@ -9,9 +9,6 @@ var/changelog_hash = ""
var/ooc_allowed = 1 // used with admin verbs to disable ooc - not a config option apparently
var/dooc_allowed = 1
//citadel code
var/looc_allowed = 1
var/dlooc_allowed = 1
var/abandon_allowed = 1
var/enter_allowed = 1
var/guests_allowed = 1
-10
View File
@@ -55,14 +55,4 @@ var/list/awaydestinations = list() //a list of landmarks that the warpgate can t
//used by jump-to-area etc. Updated by area/updateName()
var/list/sortedAreas = list()
//List of preloaded templates
var/list/datum/map_template/map_templates = list()
var/list/datum/map_template/ruins_templates = list()
var/list/datum/map_template/space_ruins_templates = list()
var/list/datum/map_template/lava_ruins_templates = list()
var/list/datum/map_template/shuttle_templates = list()
var/list/datum/map_template/shelter_templates = list()
var/list/transit_markers = list()
+3 -2
View File
@@ -14,8 +14,9 @@
moved = 0
usr.update_action_buttons() //redraw buttons that are no longer considered "moved"
return 1
if(usr.next_move >= world.time) // Is this needed ?
if(usr.next_click > world.time)
return
usr.next_click = world.time + 1
linked_action.Trigger()
return 1
@@ -71,7 +72,7 @@
. = list()
.["bg_icon"] = ui_style_icon
.["bg_state"] = "template"
//TODO : Make these fit theme
.["toggle_icon"] = 'icons/mob/actions.dmi'
.["toggle_hide"] = "hide"
+58 -52
View File
@@ -16,49 +16,49 @@
if(!category)
return
var/obj/screen/alert/alert
var/obj/screen/alert/thealert
if(alerts[category])
alert = alerts[category]
if(new_master && new_master != alert.master)
WARNING("[src] threw alert [category] with new_master [new_master] while already having that alert with master [alert.master]")
thealert = alerts[category]
if(new_master && new_master != thealert.master)
WARNING("[src] threw alert [category] with new_master [new_master] while already having that alert with master [thealert.master]")
clear_alert(category)
return .()
else if(alert.type != type)
else if(thealert.type != type)
clear_alert(category)
return .()
else if(!severity || severity == alert.severity)
if(alert.timeout)
else if(!severity || severity == thealert.severity)
if(thealert.timeout)
clear_alert(category)
return .()
else //no need to update
return 0
else
alert = new type()
thealert = new type()
if(new_master)
var/old_layer = new_master.layer
var/old_plane = new_master.plane
new_master.layer = FLOAT_LAYER
new_master.plane = FLOAT_PLANE
alert.overlays += new_master
thealert.add_overlay(new_master)
new_master.layer = old_layer
new_master.plane = old_plane
alert.icon_state = "template" // We'll set the icon to the client's ui pref in reorganize_alerts()
alert.master = new_master
thealert.icon_state = "template" // We'll set the icon to the client's ui pref in reorganize_alerts()
thealert.master = new_master
else
alert.icon_state = "[initial(alert.icon_state)][severity]"
alert.severity = severity
thealert.icon_state = "[initial(thealert.icon_state)][severity]"
thealert.severity = severity
alerts[category] = alert
alerts[category] = thealert
if(client && hud_used)
hud_used.reorganize_alerts()
alert.transform = matrix(32, 6, MATRIX_TRANSLATE)
animate(alert, transform = matrix(), time = 2.5, easing = CUBIC_EASING)
thealert.transform = matrix(32, 6, MATRIX_TRANSLATE)
animate(thealert, transform = matrix(), time = 2.5, easing = CUBIC_EASING)
if(alert.timeout)
addtimer(CALLBACK(src, .proc/alert_timeout, alert, category), alert.timeout)
alert.timeout = world.time + alert.timeout - world.tick_lag
return alert
if(thealert.timeout)
addtimer(CALLBACK(src, .proc/alert_timeout, thealert, category), thealert.timeout)
thealert.timeout = world.time + thealert.timeout - world.tick_lag
return thealert
/mob/proc/alert_timeout(obj/screen/alert/alert, category)
if(alert.timeout && alerts[category] == alert && world.time >= alert.timeout)
@@ -286,17 +286,15 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
else
name = "Next Tier Requirements"
var/validservants = 0
var/unconverted_ais_exist = FALSE
var/unconverted_ais_exist = get_unconverted_ais()
for(var/mob/living/L in living_mob_list)
if(is_servant_of_ratvar(L) && (ishuman(L) || issilicon(L)))
validservants++
else if(isAI(L))
unconverted_ais_exist++
var/req_servants = 0
var/req_caches = 0
var/req_cv = 0
var/req_ai = FALSE
desc = "Requirements for <b>[current_state] Scripture:</b>"
var/list/textlist = list("Requirements for <b>[current_state] Scripture:</b>")
switch(current_state) //get our requirements based on the tier
if(SCRIPTURE_SCRIPT)
req_servants = SCRIPT_SERVANT_REQ
@@ -314,31 +312,32 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
req_caches = JUDGEMENT_CACHE_REQ
req_cv = JUDGEMENT_CV_REQ
req_ai = TRUE
desc += "<br><b>[validservants]/[req_servants]</b> Servants"
textlist += "<br><b>[validservants]/[req_servants]</b> Servants"
if(validservants < req_servants)
icon_state += "-servants" //in this manner, generate an icon key based on what we're missing
else
desc += ": <b><font color=#5A6068>\[CHECK\]</font></b>"
desc += "<br><b>[clockwork_caches]/[req_caches]</b> Tinkerer's Caches"
textlist += ": <b><font color=#5A6068>\[CHECK\]</font></b>"
textlist += "<br><b>[clockwork_caches]/[req_caches]</b> Tinkerer's Caches"
if(clockwork_caches < req_caches)
icon_state += "-caches"
else
desc += ": <b><font color=#5A6068>\[CHECK\]</font></b>"
textlist += ": <b><font color=#5A6068>\[CHECK\]</font></b>"
if(req_cv) //cv only shows up if the tier requires it
desc += "<br><b>[clockwork_construction_value]/[req_cv]</b> Construction Value"
textlist += "<br><b>[clockwork_construction_value]/[req_cv]</b> Construction Value"
if(clockwork_construction_value < req_cv)
icon_state += "-cv"
else
desc += ": <b><font color=#5A6068>\[CHECK\]</font></b>"
textlist += ": <b><font color=#5A6068>\[CHECK\]</font></b>"
if(req_ai) //same for ai
if(unconverted_ais_exist)
if(unconverted_ais_exist > 1)
desc += "<br><b>[unconverted_ais_exist] unconverted AIs exist!</b><br>"
textlist += "<br><b>[unconverted_ais_exist] unconverted AIs exist!</b><br>"
else
desc += "<br><b>An unconverted AI exists!</b>"
textlist += "<br><b>An unconverted AI exists!</b>"
icon_state += "-ai"
else
desc += "<br>No unconverted AIs exist: <b><font color=#5A6068>\[CHECK\]</font></b>"
textlist += "<br>No unconverted AIs exist: <b><font color=#5A6068>\[CHECK\]</font></b>"
desc = textlist.Join()
/obj/screen/alert/clockwork/infodump
name = "Global Records"
@@ -351,55 +350,62 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
else
var/servants = 0
var/validservants = 0
var/unconverted_ais_exist = FALSE
var/unconverted_ais_exist = get_unconverted_ais()
var/list/scripture_states = scripture_unlock_check()
var/list/textlist
for(var/mob/living/L in living_mob_list)
if(is_servant_of_ratvar(L))
servants++
if(ishuman(L) || issilicon(L))
validservants++
else if(isAI(L))
unconverted_ais_exist++
if(servants > 1)
if(validservants > 1)
desc = "<b>[servants]</b> Servants, <b>[validservants]</b> of which count towards scripture.<br>"
textlist = list("<b>[servants]</b> Servants, <b>[validservants]</b> of which count towards scripture.<br>")
else
desc = "<b>[servants]</b> Servants, [validservants ? "<b>[validservants]</b> of which counts":"none of which count"] towards scripture.<br>"
textlist = list("<b>[servants]</b> Servants, [validservants ? "<b>[validservants]</b> of which counts":"none of which count"] towards scripture.<br>")
else
desc = "<b>[servants]</b> Servant, who [validservants ? "counts":"does not count"] towards scripture.<br>"
desc += "<b>[clockwork_caches ? "[clockwork_caches]</b> Tinkerer's Caches.":"No Tinkerer's Caches, construct one!</b>"]<br>\
textlist = list("<b>[servants]</b> Servant, who [validservants ? "counts":"does not count"] towards scripture.<br>")
textlist += "<b>[clockwork_caches ? "[clockwork_caches]</b> Tinkerer's Caches.":"No Tinkerer's Caches, construct one!</b>"]<br>\
<b>[clockwork_construction_value]</b> Construction Value.<br>"
if(clockwork_daemons)
desc += "<b>[clockwork_daemons]</b> Tinkerer's Daemons: <b>[servants * 0.2 < clockwork_daemons ? "DISABLED":"ACTIVE"]</b><br>"
textlist += "<b>[clockwork_daemons]</b> Tinkerer's Daemons: <b>[servants * 0.2 < clockwork_daemons ? "DISABLED":"ACTIVE"]</b><br>"
else
desc += "No Tinkerer's Daemons.<br>"
textlist += "No Tinkerer's Daemons.<br>"
for(var/obj/structure/destructible/clockwork/massive/celestial_gateway/G in all_clockwork_objects)
var/area/gate_area = get_area(G)
desc += "Ark Location: <b>[uppertext(gate_area.map_name)]</b><br>"
if(G.ratvar_portal)
desc += "Seconds until Ratvar's arrival: <b>[G.get_arrival_text(TRUE)]</b><br>"
textlist += "Ark Location: <b>[uppertext(gate_area.map_name)]</b><br>"
if(G.still_needs_components())
textlist += "Ark Components required: "
for(var/i in G.required_components)
if(G.required_components[i])
textlist += "<b><font color=[get_component_color_bright(i)]>[G.required_components[i]]</font></b> "
textlist += "<br>"
else
desc += "Seconds until Proselytization: <b>[G.get_arrival_text(TRUE)]</b><br>"
if(G.ratvar_portal)
textlist += "Seconds until Ratvar's arrival: <b>[G.get_arrival_text(TRUE)]</b><br>"
else
textlist += "Seconds until Proselytization: <b>[G.get_arrival_text(TRUE)]</b><br>"
if(unconverted_ais_exist)
if(unconverted_ais_exist > 1)
desc += "<b>[unconverted_ais_exist] unconverted AIs exist!</b><br>"
textlist += "<b>[unconverted_ais_exist] unconverted AIs exist!</b><br>"
else
desc += "<b>An unconverted AI exists!</b><br>"
textlist += "<b>An unconverted AI exists!</b><br>"
if(scripture_states[SCRIPTURE_REVENANT])
var/inathneq_available = clockwork_generals_invoked["inath-neq"] <= world.time
var/sevtug_available = clockwork_generals_invoked["sevtug"] <= world.time
var/nezbere_available = clockwork_generals_invoked["nezbere"] <= world.time
var/nezcrentr_available = clockwork_generals_invoked["nzcrentr"] <= world.time
if(inathneq_available || sevtug_available || nezbere_available || nezcrentr_available)
desc += "Generals available:<b>[inathneq_available ? "<br><font color=#1E8CE1>INATH-NEQ</font>":""][sevtug_available ? "<br><font color=#AF0AAF>SEVTUG</font>":""]\
textlist += "Generals available:<b>[inathneq_available ? "<br><font color=#1E8CE1>INATH-NEQ</font>":""][sevtug_available ? "<br><font color=#AF0AAF>SEVTUG</font>":""]\
[nezbere_available ? "<br><font color=#5A6068>NEZBERE</font>":""][nezcrentr_available ? "<br><font color=#DAAA18>NZCRENTR</font>":""]</b><br>"
else
desc += "Generals available: <b>NONE</b><br>"
textlist += "Generals available: <b>NONE</b><br>"
else
desc += "Generals available: <b>NONE</b><br>"
textlist += "Generals available: <b>NONE</b><br>"
for(var/i in scripture_states)
if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff
desc += "[i] Scripture: <b>[scripture_states[i] ? "UNLOCKED":"LOCKED"]</b><br>"
textlist += "[i] Scripture: <b>[scripture_states[i] ? "UNLOCKED":"LOCKED"]</b><br>"
desc = textlist.Join()
..()
//GUARDIANS
+10 -4
View File
@@ -36,7 +36,12 @@
/datum/hud/proc/apply_parallax_pref()
var/client/C = mymob.client
if(C.prefs)
if(C.prefs)
var/pref = C.prefs.parallax
if (isnull(pref))
pref = PARALLAX_HIGH
if (C.byond_version < 511)
pref = PARALLAX_DISABLE
switch(C.prefs.parallax)
if (PARALLAX_INSANE)
C.parallax_throttle = FALSE
@@ -220,8 +225,9 @@
/obj/screen/parallax_layer/proc/update_o(view)
if (!view)
view = world.view
var/list/new_overlays = list()
var/count = Ceiling(view/(480/world.icon_size))+1
var/list/new_overlays = new
for(var/x in -count to count)
for(var/y in -count to count)
if(x == 0 && y == 0)
@@ -229,8 +235,8 @@
var/image/I = image(icon, null, icon_state)
I.transform = matrix(1, 0, x*480, 0, 1, y*480)
new_overlays += I
overlays = new_overlays
cut_overlays()
add_overlay(new_overlays)
view_sized = view
/obj/screen/parallax_layer/layer_1
+1 -1
View File
@@ -11,7 +11,7 @@
backdrop.transform = matrix(200, 0, 0, 0, 200, 0)
backdrop.layer = BACKGROUND_LAYER
backdrop.blend_mode = BLEND_OVERLAY
overlays += backdrop
add_overlay(backdrop)
..()
/obj/screen/plane_master/game_world
+30
View File
@@ -21,6 +21,7 @@
/obj/screen/Destroy()
master = null
hud = null
return ..()
/obj/screen/examine(mob/user)
@@ -664,3 +665,32 @@
if(word_messages.len && talk_cooldown < world.time)
talk_cooldown = world.time + 10
L.say(pick(word_messages))
/obj/screen/splash
icon = 'icons/misc/fullscreen.dmi'
icon_state = "title"
screen_loc = "1,1"
layer = SPLASHSCREEN_LAYER
plane = SPLASHSCREEN_PLANE
var/client/holder
/obj/screen/splash/New(client/C, fadeout, qdel_after = TRUE)
..()
holder = C
holder.screen += src
var/titlescreen = TITLESCREEN
if(titlescreen)
icon_state = titlescreen
if(fadeout)
animate(src, alpha = 0, time = 30)
else
alpha = 0
animate(src, alpha = 255, time = 30)
if(qdel_after)
QDEL_IN(src, 30)
/obj/screen/splash/Destroy()
if(holder)
holder.screen -= src
holder = null
return ..()
+4
View File
@@ -60,6 +60,10 @@ var/global/list/milk_id_list = list("milk")
//mentor stuff
var/list/mentors = list()
//Looc stuff
var/global/looc_allowed = 1
var/global/dlooc_allowed = 1
/client/proc/reload_mentors()
set name = "Reload Mentors"
set category = "Admin"
+7 -10
View File
@@ -10,6 +10,9 @@
var/autoadmin = 0
var/autoadmin_rank = "Game Admin"
/datum/protected_configuration/SDQL_update()
return FALSE
/datum/protected_configuration/vv_get_var(var_name)
return debug_variable(var_name, "SECRET", 0, src)
@@ -76,6 +79,7 @@
var/forumurl = "http://tgstation13.org/phpBB/index.php" //default forums
var/rulesurl = "http://www.tgstation13.org/wiki/Rules" // default rules
var/githuburl = "https://www.github.com/tgstation/-tg-station" //default github
var/githubrepoid
var/forbid_singulo_possession = 0
var/useircbot = 0
@@ -247,15 +251,6 @@
var/error_silence_time = 6000 // How long a unique error will be silenced for
var/error_msg_delay = 50 // How long to wait between messaging admins about occurrences of a unique error
var/mentors_mobname_only = 0 // Only display mob name to mentors in mentorhelps
var/mentor_legacy_system = 0 // Whether to use the legacy mentor system (flat file) instead of SQL
// Discord crap.
var/discord_url = "hfdksjhfa.com"
var/discord_password
var/announce_watchlist = 0
var/announce_adminhelps = 0
/datum/configuration/New()
gamemode_cache = typecacheof(/datum/game_mode,TRUE)
for(var/T in gamemode_cache)
@@ -367,7 +362,7 @@
if("servername")
config.server_name = value
if("serversqlname")
config.server_sql_name = 1
config.server_sql_name = value
if("stationname")
config.station_name = value
if("hostedby")
@@ -384,6 +379,8 @@
config.rulesurl = value
if("githuburl")
config.githuburl = value
if("githubrepoid")
config.githubrepoid = value
if("guest_jobban")
config.guest_jobban = 1
if("guest_ban")
@@ -0,0 +1,8 @@
/datum/configuration
var/mentors_mobname_only = 0 // Only display mob name to mentors in mentorhelps
var/mentor_legacy_system = 0 // Whether to use the legacy mentor system (flat file) instead of SQL
// Discord crap.
var/discord_url = "hfdksjhfa.com"
var/discord_password
var/announce_watchlist = 0
var/announce_adminhelps = 0
+26 -5
View File
@@ -39,6 +39,7 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
var/make_runtime = 0
var/initializations_finished_with_no_players_logged_in //I wonder what this could be?
// Has round started? (So we know what subsystems to run)
var/round_started = 0
@@ -49,6 +50,7 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
var/datum/subsystem/queue_tail //End of queue linked list (used for appending to the list)
var/queue_priority_count = 0 //Running total so that we don't have to loop thru the queue each run to split up the tick
var/queue_priority_count_bg = 0 //Same, but for background subsystems
var/map_loading = FALSE //Are we loading in a new map?
/datum/controller/master/New()
// Highlander-style: there can only be one! Kill off the old and replace it with the new.
@@ -129,24 +131,29 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
// Sort subsystems by init_order, so they initialize in the correct order.
sortTim(subsystems, /proc/cmp_subsystem_init)
var/start_timeofday = REALTIMEOFDAY
// Initialize subsystems.
CURRENT_TICKLIMIT = config.tick_limit_mc_init
for (var/datum/subsystem/SS in subsystems)
if (SS.flags & SS_NO_INIT)
continue
SS.Initialize(world.timeofday)
SS.Initialize(REALTIMEOFDAY)
CHECK_TICK
CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
var/time = (REALTIMEOFDAY - start_timeofday) / 10
world << "<span class='boldannounce'>Initializations complete!</span>"
log_world("Initializations complete.")
var/msg = "Initializations complete within [time] second[time == 1 ? "" : "s"]!"
world << "<span class='boldannounce'>[msg]</span>"
log_world(msg)
// Sort subsystems by display setting for easy access.
sortTim(subsystems, /proc/cmp_subsystem_display)
// Set world options.
world.sleep_offline = 1
world.fps = config.fps
var/initialized_tod = REALTIMEOFDAY
sleep(1)
initializations_finished_with_no_players_logged_in = initialized_tod < REALTIMEOFDAY - 10
// Loop.
Master.StartProcessing(0)
@@ -224,7 +231,7 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
normalsubsystems += tickersubsystems
lobbysubsystems += tickersubsystems
init_timeofday = world.timeofday
init_timeofday = REALTIMEOFDAY
init_time = world.time
iteration = 1
@@ -233,7 +240,7 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
var/list/subsystems_to_check
//the actual loop.
while (1)
tickdrift = max(0, MC_AVERAGE_FAST(tickdrift, (((world.timeofday - init_timeofday) - (world.time - init_time)) / world.tick_lag)))
tickdrift = max(0, MC_AVERAGE_FAST(tickdrift, (((REALTIMEOFDAY - init_timeofday) - (world.time - init_time)) / world.tick_lag)))
if (processing <= 0)
CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
sleep(10)
@@ -496,3 +503,17 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
stat("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%))")
stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration])"))
/datum/controller/master/proc/StartLoadingMap()
//disallow more than one map to load at once, multithreading it will just cause race conditions
while(map_loading)
stoplag()
for(var/S in subsystems)
var/datum/subsystem/SS = S
SS.StartLoadingMap()
map_loading = TRUE
/datum/controller/master/proc/StopLoadingMap(bounds = null)
map_loading = FALSE
for(var/S in subsystems)
var/datum/subsystem/SS = S
SS.StopLoadingMap()
+8 -3
View File
@@ -154,8 +154,8 @@
//used to initialize the subsystem AFTER the map has loaded
/datum/subsystem/proc/Initialize(start_timeofday)
var/time = (world.timeofday - start_timeofday) / 10
var/msg = "Initialized [name] subsystem within [time] seconds!"
var/time = (REALTIMEOFDAY - start_timeofday) / 10
var/msg = "Initialized [name] subsystem within [time] second[time == 1 ? "" : "s"]!"
world << "<span class='boldannounce'>[msg]</span>"
log_world(msg)
return time
@@ -167,7 +167,7 @@
if(can_fire)
if(can_fire && !(SS_NO_FIRE in flags))
msg = "[round(cost,1)]ms|[round(tick_usage,1)]%|[round(ticks,0.1)]\t[msg]"
else
msg = "OFFLINE\t[msg]"
@@ -211,3 +211,8 @@
return 0
. = ..()
//when we enter dmm_suite.load_map
/datum/subsystem/proc/StartLoadingMap()
//when we exit dmm_suite.load_map
/datum/subsystem/proc/StopLoadingMap()
+1 -2
View File
@@ -34,8 +34,7 @@ var/datum/subsystem/acid/SSacid
if(O.acid_level && O.acid_processing())
else
O.overlays -= acid_overlay
O.priority_overlays -= acid_overlay
O.cut_overlay(acid_overlay, TRUE)
processing -= O
if (MC_TICK_CHECK)
+2 -2
View File
@@ -268,11 +268,11 @@ var/datum/subsystem/air/SSair
else
T.requires_activation = TRUE
/datum/subsystem/air/proc/begin_map_load()
/datum/subsystem/air/StartLoadingMap()
LAZYINITLIST(queued_for_activation)
map_loading = TRUE
/datum/subsystem/air/proc/end_map_load()
/datum/subsystem/air/StopLoadingMap()
map_loading = FALSE
for(var/T in queued_for_activation)
add_to_active(T)
+104
View File
@@ -0,0 +1,104 @@
var/datum/subsystem/atoms/SSatoms
#define INITIALIZATION_INSSATOMS 0 //New should not call Initialize
#define INITIALIZATION_INNEW_MAPLOAD 1 //New should call Initialize(TRUE)
#define INITIALIZATION_INNEW_REGULAR 2 //New should call Initialize(FALSE)
/datum/subsystem/atoms
name = "Atoms"
init_order = 11
flags = SS_NO_FIRE
var/initialized = INITIALIZATION_INSSATOMS
var/old_initialized
/datum/subsystem/atoms/New()
NEW_SS_GLOBAL(SSatoms)
/datum/subsystem/atoms/Initialize(timeofday)
fire_overlay.appearance_flags = RESET_COLOR
setupGenetics() //to set the mutations' place in structural enzymes, so monkey.initialize() knows where to put the monkey mutation.
initialized = INITIALIZATION_INNEW_MAPLOAD
InitializeAtoms()
return ..()
/datum/subsystem/atoms/proc/InitializeAtoms(list/atoms = null)
if(initialized == INITIALIZATION_INSSATOMS)
return
var/list/late_loaders
initialized = INITIALIZATION_INNEW_MAPLOAD
if(atoms)
for(var/I in atoms)
var/atom/A = I
if(!A.initialized) //this check is to make sure we don't call it twice on an object that was created in a previous Initialize call
var/start_tick = world.time
if(A.Initialize(TRUE))
LAZYADD(late_loaders, A)
if(start_tick != world.time)
WARNING("[A]: [A.type] slept during it's Initialize!")
CHECK_TICK
testing("Initialized [atoms.len] atoms")
else
#ifdef TESTING
var/count = 0
#endif
for(var/atom/A in world)
if(!A.initialized) //this check is to make sure we don't call it twice on an object that was created in a previous Initialize call
var/start_tick = world.time
if(A.Initialize(TRUE))
LAZYADD(late_loaders, A)
#ifdef TESTING
else
++count
#endif TESTING
if(start_tick != world.time)
WARNING("[A]: [A.type] slept during it's Initialize!")
CHECK_TICK
testing("Roundstart initialized [count] atoms")
initialized = INITIALIZATION_INNEW_REGULAR
if(late_loaders)
for(var/I in late_loaders)
var/atom/A = I
var/start_tick = world.time
A.Initialize(FALSE)
if(start_tick != world.time)
WARNING("[A]: [A.type] slept during it's Initialize!")
CHECK_TICK
testing("Late-initialized [late_loaders.len] atoms")
/datum/subsystem/atoms/proc/map_loader_begin()
old_initialized = initialized
initialized = INITIALIZATION_INSSATOMS
/datum/subsystem/atoms/proc/map_loader_stop()
initialized = old_initialized
/datum/subsystem/atoms/Recover()
initialized = SSatoms.initialized
if(initialized == INITIALIZATION_INNEW_MAPLOAD)
InitializeAtoms()
old_initialized = SSatoms.old_initialized
/datum/subsystem/atoms/proc/setupGenetics()
var/list/avnums = new /list(DNA_STRUC_ENZYMES_BLOCKS)
for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++)
avnums[i] = i
CHECK_TICK
for(var/A in subtypesof(/datum/mutation/human))
var/datum/mutation/human/B = new A()
if(B.dna_block == NON_SCANNABLE)
continue
B.dna_block = pick_n_take(avnums)
if(B.quality == POSITIVE)
good_mutations |= B
else if(B.quality == NEGATIVE)
bad_mutations |= B
else if(B.quality == MINOR_NEGATIVE)
not_good_mutations |= B
CHECK_TICK
+5 -12
View File
@@ -24,6 +24,7 @@ var/datum/subsystem/garbage_collector/SSgarbage
var/list/didntgc = list() // list of all types that have failed to GC associated with the number of times that's happened.
// the types are stored as strings
var/list/sleptDestroy = list() //Same as above but these are paths that slept during their Destroy call
var/list/noqdelhint = list()// list of all types that do not return a QDEL_HINT
// all types that did not respect qdel(A, force=TRUE) and returned one
@@ -168,13 +169,17 @@ var/datum/subsystem/garbage_collector/SSgarbage
del(D)
else if(isnull(D.gc_destroyed))
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
var/start_time = world.time
var/hint = D.Destroy(force) // Let our friend know they're about to get fucked up.
if(world.time != start_time)
SSgarbage.sleptDestroy["[D.type]"]++
if(!D)
return
switch(hint)
if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
SSgarbage.QueueForQueuing(D)
if (QDEL_HINT_IWILLGC)
D.gc_destroyed = world.time
return
if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory.
if(!force)
@@ -346,8 +351,6 @@ var/datum/subsystem/garbage_collector/SSgarbage
//if find_references isn't working for some datum
//update this list using tools/DMTreeToGlobalsList
/datum/proc/find_references_in_globals()
SearchVar(last_irc_status)
SearchVar(failed_db_connections)
SearchVar(nextmap)
SearchVar(mapchanging)
SearchVar(rebootingpendingmapchange)
@@ -554,12 +557,6 @@ var/datum/subsystem/garbage_collector/SSgarbage
SearchVar(ruin_landmarks)
SearchVar(awaydestinations)
SearchVar(sortedAreas)
SearchVar(map_templates)
SearchVar(ruins_templates)
SearchVar(space_ruins_templates)
SearchVar(lava_ruins_templates)
SearchVar(shuttle_templates)
SearchVar(shelter_templates)
SearchVar(transit_markers)
SearchVar(clients)
SearchVar(admins)
@@ -684,8 +681,6 @@ var/datum/subsystem/garbage_collector/SSgarbage
SearchVar(wire_colors)
SearchVar(wire_color_directory)
SearchVar(wire_name_directory)
SearchVar(possiblethemes)
SearchVar(max_secret_rooms)
SearchVar(blood_splatter_icons)
SearchVar(all_radios)
SearchVar(radiochannels)
@@ -796,7 +791,6 @@ var/datum/subsystem/garbage_collector/SSgarbage
SearchVar(brass_recipes)
SearchVar(disposalpipeID2State)
SearchVar(RPD_recipes)
SearchVar(highlander_claymores)
SearchVar(biblenames)
SearchVar(biblestates)
SearchVar(bibleitemstates)
@@ -842,7 +836,6 @@ var/datum/subsystem/garbage_collector/SSgarbage
SearchVar(pipenetwarnings)
SearchVar(the_gateway)
SearchVar(potentialRandomZlevels)
SearchVar(maploader)
SearchVar(use_preloader)
SearchVar(_preloader)
SearchVar(swapmaps_iconcache)
+73 -3
View File
@@ -2,13 +2,21 @@ var/datum/subsystem/mapping/SSmapping
/datum/subsystem/mapping
name = "Mapping"
init_order = 13
init_order = 12
flags = SS_NO_FIRE
display_order = 50
var/list/nuke_tiles = list()
var/list/nuke_threats = list()
var/list/map_templates = list()
var/list/ruins_templates = list()
var/list/space_ruins_templates = list()
var/list/lava_ruins_templates = list()
var/list/shuttle_templates = list()
var/list/shelter_templates = list()
/datum/subsystem/mapping/New()
NEW_SS_GLOBAL(SSmapping)
@@ -25,8 +33,6 @@ var/datum/subsystem/mapping/SSmapping
if (mining_type == "lavaland")
seedRuins(list(5), config.lavaland_budget, /area/lavaland/surface/outdoors, lava_ruins_templates)
spawn_rivers()
else
make_mining_asteroid_secrets()
// deep space ruins
var/space_zlevels = list()
@@ -68,3 +74,67 @@ var/datum/subsystem/mapping/SSmapping
/datum/subsystem/mapping/Recover()
flags |= SS_NO_INIT
map_templates = SSmapping.map_templates
ruins_templates = SSmapping.ruins_templates
space_ruins_templates = SSmapping.space_ruins_templates
lava_ruins_templates = SSmapping.lava_ruins_templates
shuttle_templates = SSmapping.shuttle_templates
shelter_templates = SSmapping.shelter_templates
/datum/subsystem/mapping/proc/preloadTemplates(path = "_maps/templates/") //see master controller setup
var/list/filelist = flist(path)
for(var/map in filelist)
var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
map_templates[T.name] = T
preloadRuinTemplates()
preloadShuttleTemplates()
preloadShelterTemplates()
/datum/subsystem/mapping/proc/preloadRuinTemplates()
// Still supporting bans by filename
var/list/banned = generateMapList("config/lavaruinblacklist.txt")
banned += generateMapList("config/spaceruinblacklist.txt")
for(var/item in subtypesof(/datum/map_template/ruin))
var/datum/map_template/ruin/ruin_type = item
// screen out the abstract subtypes
if(!initial(ruin_type.id))
continue
var/datum/map_template/ruin/R = new ruin_type()
if(banned.Find(R.mappath))
continue
map_templates[R.name] = R
ruins_templates[R.name] = R
if(istype(R, /datum/map_template/ruin/lavaland))
lava_ruins_templates[R.name] = R
else if(istype(R, /datum/map_template/ruin/space))
space_ruins_templates[R.name] = R
/datum/subsystem/mapping/proc/preloadShuttleTemplates()
var/list/unbuyable = generateMapList("config/unbuyableshuttles.txt")
for(var/item in subtypesof(/datum/map_template/shuttle))
var/datum/map_template/shuttle/shuttle_type = item
if(!(initial(shuttle_type.suffix)))
continue
var/datum/map_template/shuttle/S = new shuttle_type()
if(unbuyable.Find(S.mappath))
S.can_be_bought = FALSE
shuttle_templates[S.shuttle_id] = S
map_templates[S.shuttle_id] = S
/datum/subsystem/mapping/proc/preloadShelterTemplates()
for(var/item in subtypesof(/datum/map_template/shelter))
var/datum/map_template/shelter/shelter_type = item
if(!(initial(shelter_type.mappath)))
continue
var/datum/map_template/shelter/S = new shelter_type()
shelter_templates[S.shelter_id] = S
map_templates[S.shelter_id] = S
@@ -1,89 +1,17 @@
var/datum/subsystem/objects/SSobj
#define INITIALIZATION_INSSOBJ 0 //New should not call Initialize
#define INITIALIZATION_INNEW_MAPLOAD 1 //New should call Initialize(TRUE)
#define INITIALIZATION_INNEW_REGULAR 2 //New should call Initialize(FALSE)
/datum/subsystem/objects
name = "Objects"
init_order = 12
priority = 40
flags = SS_NO_INIT
var/initialized = INITIALIZATION_INSSOBJ
var/old_initialized
var/list/processing = list()
var/list/currentrun = list()
/datum/subsystem/objects/New()
NEW_SS_GLOBAL(SSobj)
/datum/subsystem/objects/Initialize(timeofdayl)
fire_overlay.appearance_flags = RESET_COLOR
setupGenetics() //to set the mutations' place in structural enzymes, so monkey.initialize() knows where to put the monkey mutation.
initialized = INITIALIZATION_INNEW_MAPLOAD
InitializeAtoms()
. = ..()
/datum/subsystem/objects/proc/InitializeAtoms(list/objects = null)
if(initialized == INITIALIZATION_INSSOBJ)
return
var/list/late_loaders
initialized = INITIALIZATION_INNEW_MAPLOAD
if(objects)
for(var/I in objects)
var/atom/A = I
if(!A.initialized) //this check is to make sure we don't call it twice on an object that was created in a previous Initialize call
var/start_tick = world.time
if(A.Initialize(TRUE))
LAZYADD(late_loaders, A)
if(start_tick != world.time)
WARNING("[A]: [A.type] slept during it's Initialize!")
CHECK_TICK
testing("Initialized [objects.len] atoms")
else
#ifdef TESTING
var/count = 0
#endif
for(var/atom/A in world)
if(!A.initialized) //this check is to make sure we don't call it twice on an object that was created in a previous Initialize call
var/start_tick = world.time
if(A.Initialize(TRUE))
LAZYADD(late_loaders, A)
#ifdef TESTING
else
++count
#endif TESTING
if(start_tick != world.time)
WARNING("[A]: [A.type] slept during it's Initialize!")
CHECK_TICK
testing("Roundstart initialized [count] atoms")
initialized = INITIALIZATION_INNEW_REGULAR
if(late_loaders)
for(var/I in late_loaders)
var/atom/A = I
var/start_tick = world.time
A.Initialize(FALSE)
if(start_tick != world.time)
WARNING("[A]: [A.type] slept during it's Initialize!")
CHECK_TICK
testing("Late-initialized [late_loaders.len] atoms")
/datum/subsystem/objects/proc/map_loader_begin()
old_initialized = initialized
initialized = INITIALIZATION_INSSOBJ
/datum/subsystem/objects/proc/map_loader_stop()
initialized = old_initialized
/datum/subsystem/objects/stat_entry()
..("P:[processing.len]")
/datum/subsystem/objects/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
@@ -101,10 +29,4 @@ var/datum/subsystem/objects/SSobj
return
/datum/subsystem/objects/Recover()
initialized = SSobj.initialized
if(initialized == INITIALIZATION_INNEW_MAPLOAD)
InitializeAtoms()
old_initialized = SSobj.old_initialized
if (istype(SSobj.processing))
processing = SSobj.processing
processing = SSobj.processing
@@ -0,0 +1,183 @@
var/datum/subsystem/processing/overlays/SSoverlays
/datum/subsystem/processing/overlays
name = "Overlay"
flags = SS_TICKER|SS_FIRE_IN_LOBBY
wait = 1
priority = 500
init_order = -6
stat_tag = "Ov"
currentrun = null
var/list/overlay_icon_state_caches
var/initialized = FALSE
/datum/subsystem/processing/overlays/New()
NEW_SS_GLOBAL(SSoverlays)
LAZYINITLIST(overlay_icon_state_caches)
/datum/subsystem/processing/overlays/Initialize()
initialized = TRUE
for(var/I in processing)
var/atom/A = I
A.compile_overlays()
CHECK_TICK
processing.Cut()
..()
/datum/subsystem/processing/overlays/Recover()
overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
processing = SSoverlays.processing
/datum/subsystem/processing/overlays/fire()
while(processing.len)
var/atom/thing = processing[processing.len]
processing.len--
if(thing)
thing.compile_overlays(FALSE)
if(MC_TICK_CHECK)
break
/atom/proc/compile_overlays()
if(LAZYLEN(priority_overlays) && LAZYLEN(our_overlays))
overlays = our_overlays + priority_overlays
else if(LAZYLEN(our_overlays))
overlays = our_overlays
else if(LAZYLEN(priority_overlays))
overlays = priority_overlays
else
overlays.Cut()
flags &= ~OVERLAY_QUEUED
/atom/proc/iconstate2appearance(iconstate)
var/static/image/stringbro = new()
var/list/icon_states_cache = SSoverlays.overlay_icon_state_caches
var/list/cached_icon = icon_states_cache[icon]
if (cached_icon)
var/cached_appearance = cached_icon["[iconstate]"]
if (cached_appearance)
return cached_appearance
stringbro.icon = icon
stringbro.icon_state = iconstate
if (!cached_icon) //not using the macro to save an associated lookup
cached_icon = list()
icon_states_cache[icon] = cached_icon
var/cached_appearance = stringbro.appearance
cached_icon["[iconstate]"] = cached_appearance
return cached_appearance
#define NOT_QUEUED_ALREADY (!(flags & OVERLAY_QUEUED))
#define QUEUE_FOR_COMPILE flags |= OVERLAY_QUEUED; SSoverlays.processing += src;
/atom/proc/cut_overlays(priority = FALSE)
var/list/cached_overlays = our_overlays
var/list/cached_priority = priority_overlays
var/need_compile = FALSE
if(LAZYLEN(cached_overlays)) //don't queue empty lists, don't cut priority overlays
cached_overlays.Cut() //clear regular overlays
need_compile = TRUE
if(priority && LAZYLEN(cached_priority))
cached_priority.Cut()
need_compile = TRUE
if(NOT_QUEUED_ALREADY && need_compile)
QUEUE_FOR_COMPILE
/atom/proc/cut_overlay(list/overlays, priority)
var/static/image/appearance_bro = new()
if(!overlays)
return
if (!islist(overlays))
overlays = list(overlays)
else
listclearnulls(overlays)
for (var/i in 1 to length(overlays))
if (istext(overlays[i]))
overlays[i] = iconstate2appearance(overlays[i])
else
var/image/I = overlays[i]
appearance_bro.appearance = overlays[i]
appearance_bro.dir = I.dir
overlays[i] = appearance_bro.appearance
var/list/cached_overlays = our_overlays //sanic
var/list/cached_priority = priority_overlays
var/init_o_len = LAZYLEN(cached_overlays)
var/init_p_len = LAZYLEN(cached_priority) //starter pokemon
LAZYREMOVE(cached_overlays, overlays)
if(priority)
LAZYREMOVE(cached_priority, overlays)
if(NOT_QUEUED_ALREADY && ((init_o_len != LAZYLEN(cached_priority)) || (init_p_len != LAZYLEN(cached_overlays))))
QUEUE_FOR_COMPILE
/atom/proc/add_overlay(list/overlays, priority = FALSE)
var/static/image/appearance_bro = new()
if(!overlays)
return
if (!islist(overlays))
overlays = list(overlays)
else
listclearnulls(overlays)
for (var/i in 1 to length(overlays))
if (istext(overlays[i]))
overlays[i] = iconstate2appearance(overlays[i])
else
var/image/I = overlays[i]
appearance_bro.appearance = overlays[i]
appearance_bro.dir = I.dir
overlays[i] = appearance_bro.appearance
LAZYINITLIST(our_overlays) //always initialized after this point
LAZYINITLIST(priority_overlays)
var/list/cached_overlays = our_overlays //sanic
var/list/cached_priority = priority_overlays
var/init_o_len = cached_overlays.len
var/init_p_len = cached_priority.len //starter pokemon
var/need_compile
if(priority)
cached_priority += overlays //or in the image. Can we use [image] = image?
need_compile = init_p_len != cached_priority.len
else
cached_overlays += overlays
need_compile = init_o_len != cached_overlays.len
if(NOT_QUEUED_ALREADY && need_compile) //have we caught more pokemon?
QUEUE_FOR_COMPILE
/atom/proc/copy_overlays(atom/other, cut_old = FALSE) //copys our_overlays from another atom
if(!other)
if(cut_old)
cut_overlays()
return
var/list/cached_other = other.our_overlays
if(cached_other)
if(cut_old)
our_overlays = cached_other.Copy()
else
our_overlays |= cached_other
if(NOT_QUEUED_ALREADY)
QUEUE_FOR_COMPILE
else if(cut_old)
cut_overlays()
#undef NOT_QUEUED_ALREADY
#undef QUEUE_FOR_COMPILE
//TODO: Better solution for these?
/image/proc/add_overlay(x)
overlays += x
/image/proc/cut_overlay(x)
overlays -= x
/image/proc/cut_overlays(x)
overlays.Cut()
+37 -11
View File
@@ -1,10 +1,12 @@
#define ROUND_START_MUSIC_LIST "strings/round_start_sounds.txt"
var/round_start_time = 0
var/datum/subsystem/ticker/ticker
/datum/subsystem/ticker
name = "Ticker"
init_order = 0
init_order = 13
priority = 200
flags = SS_FIRE_IN_LOBBY|SS_KEEP_TIMING
@@ -39,7 +41,8 @@ var/datum/subsystem/ticker/ticker
var/tipped = 0 //Did we broadcast the tip of the day yet?
var/selected_tip // What will be the tip of the day?
var/timeLeft = 1200 //pregame timer
var/timeLeft //pregame timer
var/start_at
var/totalPlayers = 0 //used for pregame stats on statpanel
var/totalPlayersReady = 0 //used for pregame stats on statpanel
@@ -57,30 +60,36 @@ var/datum/subsystem/ticker/ticker
/datum/subsystem/ticker/New()
NEW_SS_GLOBAL(ticker)
login_music = pickweight(list('sound/ambience/title2.ogg' = 15, 'sound/ambience/title1.ogg' =15, 'sound/ambience/title3.ogg' =14, 'sound/ambience/title4.ogg' =14, 'sound/misc/i_did_not_grief_them.ogg' =14, 'sound/ambience/clown.ogg' = 9)) // choose title music!
if(SSevent.holidays && SSevent.holidays[APRIL_FOOLS])
login_music = 'sound/ambience/clown.ogg'
else
var/list/music = file2list(ROUND_START_MUSIC_LIST, "\n")
login_music = pick(music)
/datum/subsystem/ticker/Initialize(timeofday)
var/list/music = file2list(ROUND_START_MUSIC_LIST, "\n")
login_music = pick(music)
if(!syndicate_code_phrase)
syndicate_code_phrase = generate_code_phrase()
if(!syndicate_code_response)
syndicate_code_response = generate_code_phrase()
..()
start_at = world.time + (config.lobby_countdown * 10)
/datum/subsystem/ticker/fire()
switch(current_state)
if(GAME_STATE_STARTUP)
timeLeft = config.lobby_countdown * 10
world << "<span class='boldnotice'>Welcome to [station_name()]!</span>"
world << "Please set up your character and select \"Ready\". The game will start in [config.lobby_countdown] seconds."
current_state = GAME_STATE_PREGAME
if(Master.initializations_finished_with_no_players_logged_in)
start_at = world.time + (config.lobby_countdown * 10)
for(var/client/C in clients)
window_flash(C, ignorepref = TRUE) //let them know lobby has opened up.
world << "<span class='boldnotice'>Welcome to [station_name()]!</span>"
current_state = GAME_STATE_PREGAME
fire()
if(GAME_STATE_PREGAME)
//lobby stats for statpanels
if(isnull(timeLeft))
timeLeft = max(0,start_at - world.time)
totalPlayers = 0
totalPlayersReady = 0
for(var/mob/new_player/player in player_list)
@@ -96,7 +105,7 @@ var/datum/subsystem/ticker/ticker
return
timeLeft -= wait
if(timeLeft <= 1200 && !modevoted) //Vote for the round type
if(timeLeft <= config.lobby_countdown && !modevoted) //Vote for the round type
send_gamemode_vote()
modevoted = TRUE
@@ -551,11 +560,17 @@ var/datum/subsystem/ticker/ticker
CHECK_TICK
//Adds the del() log to world.log in a format condensable by the runtime condenser found in tools
if(SSgarbage.didntgc.len)
if(SSgarbage.didntgc.len || SSgarbage.sleptDestroy.len)
var/dellog = ""
for(var/path in SSgarbage.didntgc)
dellog += "Path : [path] \n"
dellog += "Failures : [SSgarbage.didntgc[path]] \n"
if(path in SSgarbage.sleptDestroy)
dellog += "Sleeps : [SSgarbage.sleptDestroy[path]] \n"
SSgarbage.sleptDestroy -= path
for(var/path in SSgarbage.sleptDestroy)
dellog += "Path : [path] \n"
dellog += "Sleeps : [SSgarbage.sleptDestroy[path]] \n"
log_world(dellog)
CHECK_TICK
@@ -716,3 +731,14 @@ var/datum/subsystem/ticker/ticker
if(news_message)
send2otherserver(news_source, news_message,"News_Report")
/datum/subsystem/ticker/proc/GetTimeLeft()
if(isnull(ticker.timeLeft))
return max(0, start_at - world.time)
return timeLeft
/datum/subsystem/ticker/proc/SetTimeLeft(newtime)
if(newtime >= 0 && isnull(timeLeft)) //remember, negative means delayed
start_at = world.time + newtime
else
timeLeft = newtime
+29 -18
View File
@@ -40,20 +40,18 @@ var/datum/subsystem/timer/SStimer
..("B:[bucket_count] P:[length(processing)] H:[length(hashes)] C:[length(clienttime_timers)]")
/datum/subsystem/timer/fire(resumed = FALSE)
if (length(clienttime_timers))
for (var/thing in clienttime_timers)
var/datum/timedevent/ctime_timer = thing
if (ctime_timer.spent)
qdel(ctime_timer)
continue
if (ctime_timer.timeToRun <= REALTIMEOFDAY)
var/datum/callback/callBack = ctime_timer.callBack
ctime_timer.spent = TRUE
callBack.InvokeAsync()
qdel(ctime_timer)
if (MC_TICK_CHECK)
return
while(length(clienttime_timers))
var/datum/timedevent/ctime_timer = clienttime_timers[clienttime_timers.len]
if (ctime_timer.timeToRun <= REALTIMEOFDAY)
--clienttime_timers.len
var/datum/callback/callBack = ctime_timer.callBack
ctime_timer.spent = TRUE
callBack.InvokeAsync()
qdel(ctime_timer)
else
break //None of the rest are ready to run
if (MC_TICK_CHECK)
return
var/static/list/spent = list()
var/static/datum/timedevent/timer
@@ -208,11 +206,24 @@ var/datum/subsystem/timer/SStimer
SStimer.timer_id_dict["timerid[id]"] = src
if (callBack.object != GLOBAL_PROC)
LAZYINITLIST(callBack.object.active_timers)
callBack.object.active_timers += src
LAZYADD(callBack.object.active_timers, src)
if (flags & TIMER_CLIENT_TIME)
SStimer.clienttime_timers += src
//sorted insert
var/list/ctts = SStimer.clienttime_timers
var/cttl = length(ctts)
if(cttl)
var/datum/timedevent/Last = ctts[cttl]
if(Last.timeToRun >= timeToRun)
ctts += src
else if(cttl > 1)
for(var/I in cttl to 1)
var/datum/timedevent/E = ctts[I]
if(E.timeToRun <= timeToRun)
ctts.Insert(src, I)
break
else
ctts += src
return
//get the list of buckets
@@ -345,4 +356,4 @@ proc/addtimer(datum/callback/callback, wait, flags)
#undef BUCKET_LEN
#undef BUCKET_POS
#undef BUCKET_POS
+12 -13
View File
@@ -113,7 +113,8 @@
img = image(icon_icon, current_button, button_icon_state)
img.pixel_x = 0
img.pixel_y = 0
current_button.overlays = list(img)
current_button.cut_overlays(TRUE)
current_button.add_overlay(img)
current_button.button_icon_state = button_icon_state
@@ -329,32 +330,30 @@
/datum/action/item_action/hands_free/activate
name = "Activate"
/datum/action/item_action/hands_free/shift_nerves
name = "Shift Nerves"
/datum/action/item_action/toggle_research_scanner
name = "Toggle Research Scanner"
button_icon_state = "scan_mode"
var/active = FALSE
/datum/action/item_action/toggle_research_scanner/Trigger()
if(IsAvailable())
owner.research_scanner = !owner.research_scanner
owner << "<span class='notice'>Research analyzer is now [owner.research_scanner ? "active" : "deactivated"].</span>"
active = !active
if(active)
owner.research_scanner++
else
owner.research_scanner--
owner << "<span class='notice'>[target] research scanner has been [active ? "activated" : "deactivated"].</span>"
return 1
/datum/action/item_action/toggle_research_scanner/Remove(mob/M)
if(owner)
owner.research_scanner = 0
if(owner && active)
owner.research_scanner--
active = FALSE
..()
/datum/action/item_action/toggle_research_scanner/ApplyIcon(obj/screen/movable/action_button/current_button)
current_button.cut_overlays()
if(button_icon && button_icon_state)
var/image/img = image(button_icon, current_button, "scan_mode")
current_button.add_overlay(img)
/datum/action/item_action/organ_action
check_flags = AB_CHECK_CONSCIOUS
+40 -5
View File
@@ -313,19 +313,53 @@
var picked_group = pickweight(replaceable_groups)
switch(picked_group)
if(LAW_ZEROTH)
. = zeroth
set_zeroth_law(law)
if(LAW_ION)
ion[rand(1,ion.len)] = law
var/i = rand(1, ion.len)
. = ion[i]
ion[i] = law
if(LAW_INHERENT)
inherent[rand(1,inherent.len)] = law
var/i = rand(1, inherent.len)
. = inherent[i]
inherent[i] = law
if(LAW_SUPPLIED)
supplied[rand(1,supplied.len)] = law
var/i = rand(1, supplied.len)
. = supplied[i]
supplied[i] = law
/datum/ai_laws/proc/shuffle_laws(list/groups)
var/list/laws = list()
if(ion.len && (LAW_ION in groups))
laws += ion
if(inherent.len && (LAW_INHERENT in groups))
laws += inherent
if(supplied.len && (LAW_SUPPLIED in groups))
for(var/law in supplied)
if(length(law))
laws += law
if(ion.len && (LAW_ION in groups))
for(var/i = 1, i <= ion.len, i++)
ion[i] = pick_n_take(laws)
if(inherent.len && (LAW_INHERENT in groups))
for(var/i = 1, i <= inherent.len, i++)
inherent[i] = pick_n_take(laws)
if(supplied.len && (LAW_SUPPLIED in groups))
var/i = 1
for(var/law in supplied)
if(length(law))
supplied[i] = pick_n_take(laws)
if(!laws.len)
break
i++
/datum/ai_laws/proc/remove_law(number)
if(number <= 0)
return
if(inherent.len && number <= inherent.len)
inherent -= inherent[number]
. = inherent[number]
inherent -= .
return
var/list/supplied_laws = list()
for(var/index = 1, index <= supplied.len, index++)
@@ -334,7 +368,8 @@
supplied_laws += index //storing the law number instead of the law
if(supplied_laws.len && number <= (inherent.len+supplied_laws.len))
var/law_to_remove = supplied_laws[number-inherent.len]
supplied -= supplied[law_to_remove]
. = supplied[law_to_remove]
supplied -= .
return
/datum/ai_laws/proc/clear_supplied_laws()
+52 -16
View File
@@ -4,6 +4,7 @@ var/global/datum/getrev/revdata = new()
var/parentcommit
var/commit
var/list/testmerge = list()
var/has_pr_details = FALSE //example data in a testmerge entry when this is true: https://api.github.com/repositories/3234987/pulls/22586
var/date
/datum/getrev/New()
@@ -31,6 +32,44 @@ var/global/datum/getrev/revdata = new()
log_world(parentcommit)
log_world("Current map - [MAP_NAME]") //can't think of anywhere better to put it
/datum/getrev/proc/DownloadPRDetails()
if(!config.githubrepoid)
if(testmerge.len)
log_world("PR details download failed: No github repo config set")
return
if(!isnum(text2num(config.githubrepoid)))
log_world("PR details download failed: Invalid github repo id: [config.githubrepoid]")
return
for(var/line in testmerge)
if(!isnum(text2num(line)))
log_world("PR details download failed: Invalid PR number: [line]")
return
var/url = "https://api.github.com/repositories/[config.githubrepoid]/pulls/[line].json"
valid_HTTPSGet = TRUE
var/json = HTTPSGet(url)
if(!json)
return
testmerge[line] = json_decode(json)
if(!testmerge[line])
log_world("PR details download failed: null details returned")
return
CHECK_TICK
log_world("PR details successfully downloaded")
has_pr_details = TRUE
/datum/getrev/proc/GetTestMergeInfo(header = TRUE)
if(!testmerge.len)
return ""
. = header ? "The following pull requests are currently test merged:<br>" : ""
for(var/line in testmerge)
var/details = ""
if(has_pr_details)
details = ": '" + html_encode(testmerge[line]["title"]) + "' by " + html_encode(testmerge[line]["user"]["login"])
. += "<a href='[config.githuburl]/pull/[line]'>#[line][details]</a><br>"
/client/verb/showrevinfo()
set category = "OOC"
set name = "Show Server Revision"
@@ -39,12 +78,9 @@ var/global/datum/getrev/revdata = new()
if(revdata.parentcommit)
src << "<b>Server revision compiled on:</b> [revdata.date]"
if(revdata.testmerge.len)
for(var/line in revdata.testmerge)
if(line)
src << "Test merge active of PR <a href='[config.githuburl]/pull/[line]'>#[line]</a>"
src << "Based off master commit <a href='[config.githuburl]/commit/[revdata.parentcommit]'>[revdata.parentcommit]</a>"
else
src << "<a href='[config.githuburl]/commit/[revdata.parentcommit]'>[revdata.parentcommit]</a>"
src << revdata.GetTestMergeInfo()
src << "Based off master commit:"
src << "<a href='[config.githuburl]/commit/[revdata.parentcommit]'>[revdata.parentcommit]</a>"
else
src << "Revision unknown"
src << "<b>Current Infomational Settings:</b>"
@@ -56,8 +92,8 @@ var/global/datum/getrev/revdata = new()
src << "Allow Midround Antagonists: [config.midround_antag.len] of [config.modes.len] roundtypes"
if(config.show_game_type_odds)
if(ticker.current_state == GAME_STATE_PLAYING)
src <<"<b>Game Mode Odds for current round:</b>"
var/prob_sum = 0
var/current_odds_differ = FALSE
var/list/probs = list()
var/list/modes = config.gamemode_cache
for(var/mode in modes)
@@ -65,17 +101,18 @@ var/global/datum/getrev/revdata = new()
var/ctag = initial(M.config_tag)
if(!(ctag in config.probabilities))
continue
if((config.min_pop[ctag] && (config.min_pop[ctag] > ticker.totalPlayersReady)) || (initial(M.required_players) > ticker.totalPlayersReady))
continue
if(config.max_pop[ctag] && (config.max_pop[ctag] < ticker.totalPlayersReady))
if((config.min_pop[ctag] && (config.min_pop[ctag] > ticker.totalPlayersReady)) || (config.max_pop[ctag] && (config.max_pop[ctag] < ticker.totalPlayersReady)) || (initial(M.required_players) > ticker.totalPlayersReady))
current_odds_differ = TRUE
continue
probs[ctag] = 1
prob_sum += config.probabilities[ctag]
for(var/ctag in probs)
if(config.probabilities[ctag] > 0)
var/percentage = round(config.probabilities[ctag] / prob_sum * 100, 0.1)
src << "[ctag] [percentage]%"
if(current_odds_differ)
src <<"<b>Game Mode Odds for current round:</b>"
for(var/ctag in probs)
if(config.probabilities[ctag] > 0)
var/percentage = round(config.probabilities[ctag] / prob_sum * 100, 0.1)
src << "[ctag] [percentage]%"
src <<"<b>All Game Mode Odds:</b>"
var/sum = 0
for(var/ctag in config.probabilities)
@@ -84,4 +121,3 @@ var/global/datum/getrev/revdata = new()
if(config.probabilities[ctag] > 0)
var/percentage = round(config.probabilities[ctag] / sum * 100, 0.1)
src << "[ctag] [percentage]%"
return
-146
View File
@@ -1,146 +0,0 @@
/datum/map_template
var/name = "Default Template Name"
var/width = 0
var/height = 0
var/mappath = null
var/mapfile = null
var/loaded = 0 // Times loaded this round
/datum/map_template/New(path = null, map = null, rename = null)
if(path)
mappath = path
if(mappath)
preload_size(mappath)
if(map)
mapfile = map
if(rename)
name = rename
/datum/map_template/proc/preload_size(path)
var/bounds = maploader.load_map(file(path), 1, 1, 1, cropMap=FALSE, measureOnly=TRUE)
if(bounds)
width = bounds[MAP_MAXX] // Assumes all templates are rectangular, have a single Z level, and begin at 1,1,1
height = bounds[MAP_MAXY]
return bounds
/proc/initTemplateBounds(var/list/bounds)
var/list/obj/machinery/atmospherics/atmos_machines = list()
var/list/obj/structure/cable/cables = list()
var/list/atom/atoms = list()
for(var/L in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]),
locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ])))
var/turf/B = L
atoms += B
for(var/A in B)
atoms += A
if(istype(A,/obj/structure/cable))
cables += A
continue
if(istype(A,/obj/machinery/atmospherics))
atmos_machines += A
continue
SSobj.InitializeAtoms(atoms)
SSmachine.setup_template_powernets(cables)
SSair.setup_template_machinery(atmos_machines)
SSair.end_map_load()
/datum/map_template/proc/load(turf/T, centered = FALSE)
if(centered)
T = locate(T.x - round(width/2) , T.y - round(height/2) , T.z)
if(!T)
return
if(T.x+width > world.maxx)
return
if(T.y+height > world.maxy)
return
SSair.begin_map_load()
var/list/bounds = maploader.load_map(get_file(), T.x, T.y, T.z, cropMap=TRUE)
if(!bounds)
SSair.end_map_load()
return 0
//initialize things that are normally initialized after map load
initTemplateBounds(bounds)
log_game("[name] loaded at at [T.x],[T.y],[T.z]")
return 1
/datum/map_template/proc/get_file()
if(mapfile)
. = mapfile
else if(mappath)
. = file(mappath)
if(!.)
log_world("The file of [src] appears to be empty/non-existent.")
/datum/map_template/proc/get_affected_turfs(turf/T, centered = FALSE)
var/turf/placement = T
if(centered)
var/turf/corner = locate(placement.x - round(width/2), placement.y - round(height/2), placement.z)
if(corner)
placement = corner
return block(placement, locate(placement.x+width-1, placement.y+height-1, placement.z))
/proc/preloadTemplates(path = "_maps/templates/") //see master controller setup
var/list/filelist = flist(path)
for(var/map in filelist)
var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
map_templates[T.name] = T
preloadRuinTemplates()
preloadShuttleTemplates()
preloadShelterTemplates()
/proc/preloadRuinTemplates()
// Still supporting bans by filename
var/list/banned = generateMapList("config/lavaruinblacklist.txt")
banned += generateMapList("config/spaceruinblacklist.txt")
for(var/item in subtypesof(/datum/map_template/ruin))
var/datum/map_template/ruin/ruin_type = item
// screen out the abstract subtypes
if(!initial(ruin_type.id))
continue
var/datum/map_template/ruin/R = new ruin_type()
if(banned.Find(R.mappath))
continue
map_templates[R.name] = R
ruins_templates[R.name] = R
if(istype(R, /datum/map_template/ruin/lavaland))
lava_ruins_templates[R.name] = R
else if(istype(R, /datum/map_template/ruin/space))
space_ruins_templates[R.name] = R
/proc/preloadShuttleTemplates()
var/list/unbuyable = generateMapList("config/unbuyableshuttles.txt")
for(var/item in subtypesof(/datum/map_template/shuttle))
var/datum/map_template/shuttle/shuttle_type = item
if(!(initial(shuttle_type.suffix)))
continue
var/datum/map_template/shuttle/S = new shuttle_type()
if(unbuyable.Find(S.mappath))
S.can_be_bought = FALSE
shuttle_templates[S.shuttle_id] = S
map_templates[S.shuttle_id] = S
/proc/preloadShelterTemplates()
for(var/item in subtypesof(/datum/map_template/shelter))
var/datum/map_template/shelter/shelter_type = item
if(!(initial(shelter_type.mappath)))
continue
var/datum/map_template/shelter/S = new shelter_type()
shelter_templates[S.shelter_id] = S
map_templates[S.shelter_id] = S
+5
View File
@@ -258,6 +258,11 @@
sheet_type = /obj/item/stack/sheet/mineral/plasma
coin_type = /obj/item/weapon/coin/plasma
/datum/material/bluespace
name = "Bluespace Mesh"
id = MAT_BLUESPACE
sheet_type = /obj/item/stack/sheet/bluespace_crystal
/datum/material/bananium
name = "Bananium"
id = MAT_BANANIUM
-1
View File
@@ -135,7 +135,6 @@
if(isAI(current))
var/mob/living/silicon/ai/A = current
A.set_zeroth_law("")
A.show_laws()
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
A.malf_picker.remove_verbs(A)
qdel(A.malf_picker)
+133 -27
View File
@@ -9,12 +9,30 @@
var/slowed = FALSE
var/slowvalue = 1
/datum/riding/New(atom/movable/_ridden)
ridden = _ridden
/datum/riding/Destroy()
ridden = null
return ..()
/datum/riding/proc/handle_vehicle_layer()
if(ridden.dir != NORTH)
ridden.layer = ABOVE_MOB_LAYER
else
ridden.layer = OBJ_LAYER
/datum/riding/proc/on_vehicle_move()
for(var/mob/living/M in ridden.buckled_mobs)
ride_check(M)
handle_vehicle_offsets()
handle_vehicle_layer()
/datum/riding/proc/ride_check(mob/living/M)
return TRUE
/datum/riding/proc/force_dismount(mob/living/M)
ridden.unbuckle_mob(M)
//Override this to set your vehicle's various pixel offsets
//if they differ between directions, otherwise use the
@@ -36,7 +54,6 @@
return TRUE
return FALSE
//BUCKLE HOOKS
/datum/riding/proc/restore_position(mob/living/buckled_mob)
if(istype(buckled_mob))
@@ -45,11 +62,6 @@
if(buckled_mob.client)
buckled_mob.client.change_view(world.view)
//MOVEMENT
/datum/riding/proc/handle_ride(mob/user, direction)
if(user.incapacitated())
@@ -298,12 +310,59 @@
else
user << "<span class='notice'>You'll need something to guide the [ridden.name].</span>"
//CYBORGS. NO, THEY ARE NOT ANIMALS.
///////Humans. Yes, I said humans. No, this won't end well...//////////
/datum/riding/human
keytype = null
/datum/riding/human/ride_check(mob/living/M)
var/mob/living/carbon/human/H = ridden //IF this runtimes I'm blaming the admins.
if(M.incapacitated(FALSE, TRUE) || H.incapacitated(FALSE, TRUE))
M.visible_message("<span class='boldwarning'>[M] falls off of [ridden]!</span>")
ridden.unbuckle_mob(M)
return FALSE
if(M.restrained(TRUE))
M.visible_message("<span class='boldwarning'>[M] can't hang onto [ridden] with their hands cuffed!</span>") //Honestly this should put the ridden mob in a chokehold.
ridden.unbuckle_mob(M)
return FALSE
if(H.pulling == M)
H.stop_pulling()
/datum/riding/human/handle_vehicle_offsets()
for(var/mob/living/M in ridden.buckled_mobs)
M.setDir(ridden.dir)
switch(ridden.dir)
if(NORTH)
M.pixel_x = 0
M.pixel_y = 6
if(SOUTH)
M.pixel_x = 0
M.pixel_y = 6
if(EAST)
M.pixel_x = -6
M.pixel_y = 4
if(WEST)
M.pixel_x = 6
M.pixel_y = 4
/datum/riding/human/handle_vehicle_layer()
if(ridden.buckled_mobs && ridden.buckled_mobs.len)
if(ridden.dir == SOUTH)
ridden.layer = ABOVE_MOB_LAYER
else
ridden.layer = OBJ_LAYER
else
ridden.layer = MOB_LAYER
/datum/riding/human/force_dismount(mob/living/user)
ridden.unbuckle_mob(user)
user.Weaken(3)
user.Stun(3)
user.visible_message("<span class='boldwarning'>[ridden] pushes [user] off of them!</span>")
/datum/riding/cyborg
keytype = null
vehicle_move_delay = 1
/datum/riding/cyborg/proc/ride_check(mob/user)
/datum/riding/cyborg/ride_check(mob/user)
if(user.incapacitated())
var/kick = TRUE
if(istype(ridden, /mob/living/silicon/robot))
@@ -322,11 +381,12 @@
return
/datum/riding/cyborg/handle_vehicle_layer()
if(ridden.dir == SOUTH)
ridden.layer = ABOVE_MOB_LAYER
if(ridden.buckled_mobs && ridden.buckled_mobs.len)
if(ridden.dir == SOUTH)
ridden.layer = ABOVE_MOB_LAYER
else
ridden.layer = OBJ_LAYER
else
ridden.layer = OBJ_LAYER
if(!ridden.buckled_mobs)
ridden.layer = MOB_LAYER
/datum/riding/cyborg/handle_vehicle_offsets()
@@ -353,19 +413,65 @@
M.pixel_x = 6
M.pixel_y = 3
/datum/riding/cyborg/proc/on_vehicle_move()
for(var/mob/living/M in ridden.buckled_mobs)
ride_check(M)
handle_vehicle_offsets()
handle_vehicle_layer()
/datum/riding/cyborg/force_dismount(mob/living/M)
ridden.unbuckle_mob(M)
var/turf/target = get_edge_target_turf(ridden, ridden.dir)
var/turf/targetm = get_step(get_turf(ridden), ridden.dir)
M.Move(targetm)
M.visible_message("<span class='boldwarning'>[M] is thrown clear of [ridden]!</span>")
M.throw_at(target, 14, 5, ridden)
M.Weaken(3)
/datum/riding/cyborg/proc/force_dismount()
for(var/mob/living/M in ridden.buckled_mobs)
ridden.unbuckle_mob(M)
var/turf/target = get_edge_target_turf(ridden, ridden.dir)
var/turf/targetm = get_step(get_turf(ridden), ridden.dir)
M.Move(targetm)
M.visible_message("<span class='boldwarning'>[M] is thrown clear of [ridden] by rapid spinning!</span>")
M.throw_at(target, 14, 5, ridden)
M.Weaken(3)
/datum/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1)
var/amount_equipped = 0
for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
inhand.rider = user
inhand.ridden = ridden
if(user.put_in_hands(inhand, TRUE))
amount_equipped++
else
break
if(amount_equipped >= amount_required)
return TRUE
else
unequip_buckle_inhands(user)
return FALSE
/datum/riding/proc/unequip_buckle_inhands(mob/living/carbon/user)
for(var/obj/item/riding_offhand/O in user.contents)
if(O.ridden != ridden)
CRASH("RIDING OFFHAND ON WRONG MOB")
continue
if(O.selfdeleting)
continue
else
qdel(O)
return TRUE
/obj/item/riding_offhand
name = "offhand"
icon = 'icons/obj/weapons.dmi'
icon_state = "offhand"
w_class = WEIGHT_CLASS_HUGE
flags = ABSTRACT | DROPDEL | NOBLUDGEON
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/mob/living/carbon/rider
var/mob/living/ridden
var/selfdeleting = FALSE
/obj/item/riding_offhand/dropped()
selfdeleting = TRUE
. = ..()
/obj/item/riding_offhand/equipped()
if(loc != rider)
selfdeleting = TRUE
qdel(src)
. = ..()
/obj/item/riding_offhand/Destroy()
if(selfdeleting)
if(rider in ridden.buckled_mobs)
ridden.unbuckle_mob(rider)
. = ..()
+1
View File
@@ -172,6 +172,7 @@
Outside of admin intervention, it cannot explode. \
It does, however, still dust anything on contact, emits high levels of radiation, and induce hallucinations in anyone looking at it without protective goggles. \
Emitters spawn powered on, expect admin notices, they are harmless."
credit_cost = 100000
/datum/map_template/shuttle/emergency/imfedupwiththisworld
suffix = "imfedupwiththisworld"
+151
View File
@@ -0,0 +1,151 @@
/mob/living
var/list/ownedSoullinks //soullinks we are the owner of
var/list/sharedSoullinks //soullinks we are a/the sharer of
/mob/living/Destroy()
for(var/s in ownedSoullinks)
var/datum/soullink/S = s
S.ownerDies(FALSE)
qdel(s) //If the owner is destroy()'d, the soullink is destroy()'d
ownedSoullinks = null
for(var/s in sharedSoullinks)
var/datum/soullink/S = s
S.sharerDies(FALSE)
S.removeSoulsharer(src) //If a sharer is destroy()'d, they are simply removed
sharedSoullinks = null
return ..()
//Keeps track of a Mob->Mob (potentially Player->Player) connection
//Can be used to trigger actions on one party when events happen to another
//Eg: shared deaths
//Can be used to form a linked list of mob-hopping
//Does NOT transfer with minds
/datum/soullink
var/mob/living/soulowner
var/mob/living/soulsharer
var/id //Optional ID, for tagging and finding specific instances
/datum/soullink/Destroy()
if(soulowner)
LAZYREMOVE(soulowner.ownedSoullinks, src)
soulowner = null
if(soulsharer)
LAZYREMOVE(soulsharer.sharedSoullinks, src)
soulsharer = null
return ..()
/datum/soullink/proc/removeSoulsharer(mob/living/sharer)
if(soulsharer == sharer)
soulsharer = null
LAZYREMOVE(sharer.sharedSoullinks, src)
//Used to assign variables, called primarily by soullink()
//Override this to create more unique soullinks (Eg: 1->Many relationships)
//Return TRUE/FALSE to return the soullink/null in soullink()
/datum/soullink/proc/parseArgs(mob/living/owner, mob/living/sharer)
if(!owner || !sharer)
return FALSE
soulowner = owner
soulsharer = sharer
LAZYADD(owner.ownedSoullinks, src)
LAZYADD(sharer.sharedSoullinks, src)
return TRUE
//Runs after /living death()
//Override this for content
/datum/soullink/proc/ownerDies(gibbed, mob/living/owner)
//Runs after /living death()
//Override this for content
/datum/soullink/proc/sharerDies(gibbed, mob/living/owner)
//Quick-use helper
/proc/soullink(typepath, ...)
var/datum/soullink/S = new typepath()
if(S.parseArgs(arglist(args.Copy(2, 0))))
return S
/////////////////
// MULTISHARER //
/////////////////
//Abstract soullink for use with 1 Owner -> Many Sharer setups
/datum/soullink/multisharer
var/list/soulsharers
/datum/soullink/multisharer/parseArgs(mob/living/owner, list/sharers)
if(!owner || !LAZYLEN(sharers))
return FALSE
soulowner = owner
soulsharers = sharers
LAZYADD(owner.ownedSoullinks, src)
for(var/l in sharers)
var/mob/living/L = l
LAZYADD(L.sharedSoullinks, src)
return TRUE
/datum/soullink/multisharer/removeSoulsharer(mob/living/sharer)
LAZYREMOVE(soulsharers, sharer)
/////////////////
// SHARED FATE //
/////////////////
//When the soulowner dies, the soulsharer dies, and vice versa
//This is intended for two players(or AI) and two mobs
/datum/soullink/sharedfate/ownerDies(gibbed, mob/living/owner)
if(soulsharer)
soulsharer.death(gibbed)
/datum/soullink/sharedfate/sharerDies(gibbed, mob/living/sharer)
if(soulowner)
soulowner.death(gibbed)
/////////////////
// SHARED BODY //
/////////////////
//When the soulsharer dies, they're placed in the soulowner, who remains alive
//If the soulowner dies, the soulsharer is killed and placed into the soulowner (who is still dying)
//This one is intended for one player moving between many mobs
/datum/soullink/sharedbody/ownerDies(gibbed, mob/living/owner)
if(soulowner && soulsharer)
if(soulsharer.mind)
soulsharer.mind.transfer_to(soulowner)
soulsharer.death(gibbed)
/datum/soullink/sharedbody/sharerDies(gibbed, mob/living/sharer)
if(soulowner && soulsharer && soulsharer.mind)
soulsharer.mind.transfer_to(soulowner)
//////////////////////
// REPLACEMENT POOL //
//////////////////////
//When the owner dies, one of the sharers is placed in the owner's body, fully healed
//Sort of a "winner-stays-on" soullink
//Gibbing ends it immediately
/datum/soullink/multisharer/replacementpool/ownerDies(gibbed, mob/living/owner)
if(LAZYLEN(soulsharers) && !gibbed) //let's not put them in some gibs
var/list/souls = shuffle(soulsharers.Copy())
for(var/l in souls)
var/mob/living/L = l
if(L.stat != DEAD && L.mind)
L.mind.transfer_to(soulowner)
soulowner.revive(TRUE, TRUE)
L.death(FALSE)
//Lose your claim to the throne!
/datum/soullink/multisharer/replacementpool/sharerDies(gibbed, mob/living/sharer)
removeSoulsharer(sharer)
+50
View File
@@ -151,3 +151,53 @@
return
playsound(cyborg, 'sound/effects/light_flicker.ogg', 50, 1)
cyborg.cell.give(power_to_give)
/datum/status_effect/his_grace
id = "his_grace"
duration = -1
tick_interval = 4
alert_type = /obj/screen/alert/status_effect/his_grace
var/bloodlust = 0
/obj/screen/alert/status_effect/his_grace
name = "His Grace"
desc = "His Grace hungers, and you must feed Him."
icon_state = "his_grace"
alerttooltipstyle = "hisgrace"
/obj/screen/alert/status_effect/his_grace/MouseEntered(location,control,params)
desc = initial(desc)
var/datum/status_effect/his_grace/HG = attached_effect
desc += "<br><font size=3><b>Current Bloodthirst: [HG.bloodlust]</b></font>\
<br>Becomes undroppable at <b>[HIS_GRACE_FAMISHED]</b>\
<br>Will consume you at <b>[HIS_GRACE_CONSUME_OWNER]</b>"
..()
/datum/status_effect/his_grace/on_apply()
add_logs(owner, null, "gained His Grace's stun immunity")
owner.add_stun_absorption("hisgrace", INFINITY, 3, null, "His Grace protects you from the stun!")
/datum/status_effect/his_grace/tick()
bloodlust = 0
var/graces = 0
for(var/obj/item/weapon/his_grace/HG in owner.held_items)
if(HG.bloodthirst > bloodlust)
bloodlust = HG.bloodthirst
if(HG.awakened)
graces++
if(!graces)
owner.apply_status_effect(STATUS_EFFECT_HISWRATH)
qdel(src)
return
var/grace_heal = bloodlust * 0.05
owner.adjustBruteLoss(-grace_heal)
owner.adjustFireLoss(-grace_heal)
owner.adjustToxLoss(-grace_heal, TRUE, TRUE)
owner.adjustOxyLoss(-(grace_heal * 2))
owner.adjustCloneLoss(-grace_heal)
/datum/status_effect/his_grace/on_remove()
add_logs(owner, null, "lost His Grace's stun immunity")
if(islist(owner.stun_absorption) && owner.stun_absorption["hisgrace"])
owner.stun_absorption -= "hisgrace"
+20
View File
@@ -9,3 +9,23 @@
/datum/status_effect/sigil_mark/tick()
if(owner.stat < stat_allowed)
qdel(src)
/datum/status_effect/his_wrath //does minor damage over time unless holding His Grace
id = "his_wrath"
duration = -1
tick_interval = 4
alert_type = /obj/screen/alert/status_effect/his_wrath
/obj/screen/alert/status_effect/his_wrath
name = "His Wrath"
desc = "You fled from His Grace instead of feeding Him, and now you suffer."
icon_state = "his_grace"
alerttooltipstyle = "hisgrace"
/datum/status_effect/his_wrath/tick()
for(var/obj/item/weapon/his_grace/HG in owner.held_items)
qdel(src)
return
owner.adjustBruteLoss(0.1)
owner.adjustFireLoss(0.1)
owner.adjustToxLoss(0.2, TRUE, TRUE)
+2 -2
View File
@@ -14,7 +14,7 @@
if(!owner.stat)
owner << "You become frozen in a cube!"
cube = icon('icons/effects/freeze.dmi', "ice_cube")
owner.overlays += cube
owner.add_overlay(cube)
owner.update_canmove()
/datum/status_effect/freon/tick()
@@ -25,6 +25,6 @@
/datum/status_effect/freon/on_remove()
if(!owner.stat)
owner << "The cube melts!"
owner.overlays -= cube
owner.cut_overlay(cube)
owner.bodytemperature += 100
owner.update_canmove()
+2 -2
View File
@@ -46,7 +46,7 @@
A.mode = 1 // AALARM_MODE_SCRUB
A.apply_mode()
if(WIRE_ALARM) // Clear alarms.
var/area/AA = get_area_master(A)
var/area/AA = get_area(A)
if(AA.atmosalert(0, holder))
A.post_alert(0)
A.update_icon()
@@ -68,7 +68,7 @@
A.mode = 3 // AALARM_MODE_PANIC
A.apply_mode()
if(WIRE_ALARM) // Post alarm.
var/area/AA = get_area_master(A)
var/area/AA = get_area(A)
if(AA.atmosalert(2, holder))
A.post_alert(2)
A.update_icon()
+4 -2
View File
@@ -30,7 +30,8 @@
if(WIRE_SAFETY)
SSU.safeties = !SSU.safeties
if(WIRE_ZAP)
SSU.shock(usr)
if(usr)
SSU.shock(usr)
/datum/wires/suit_storage_unit/on_cut(wire, mend)
var/obj/machinery/suit_storage_unit/SSU = holder
@@ -40,4 +41,5 @@
if(WIRE_SAFETY)
SSU.safeties = mend
if(WIRE_ZAP)
SSU.shock(usr)
if(usr)
SSU.shock(usr)
+21 -22
View File
@@ -45,7 +45,6 @@
var/safe = 0 //Is the area teleport-safe: no space / radiation / aggresive mobs / other dangers
var/no_air = null
var/area/master // master area used for power calcluations
var/list/related // the other areas of the same type as this
var/parallax_movedir = 0
@@ -98,10 +97,9 @@ var/list/teleportlocs = list()
/area/New()
/area/Initialize()
icon_state = ""
layer = AREA_LAYER
master = src
uid = ++global_uid
related = list(src)
map_name = name // Save the initial (the name set in the map) name of the area.
@@ -238,6 +236,8 @@ var/list/teleportlocs = list()
RA.mouse_opacity = 0
RA.updateicon()
RA.ModifyFiredoors(TRUE)
for(var/obj/machinery/firealarm/F in RA)
F.update_icon()
for (var/mob/living/silicon/aiPlayer in player_list)
aiPlayer.cancelAlarm("Fire", src, source)
@@ -343,17 +343,17 @@ var/list/teleportlocs = list()
/area/proc/powered(chan) // return true if the area has power to given channel
if(!master.requires_power)
if(!requires_power)
return 1
if(master.always_unpowered)
if(always_unpowered)
return 0
switch(chan)
if(EQUIP)
return master.power_equip
return power_equip
if(LIGHT)
return master.power_light
return power_light
if(ENVIRON)
return master.power_environ
return power_environ
return 0
@@ -372,19 +372,19 @@ var/list/teleportlocs = list()
var/used = 0
switch(chan)
if(LIGHT)
used += master.used_light
used += used_light
if(EQUIP)
used += master.used_equip
used += used_equip
if(ENVIRON)
used += master.used_environ
used += used_environ
if(TOTAL)
used += master.used_light + master.used_equip + master.used_environ
used += used_light + used_equip + used_environ
if(STATIC_EQUIP)
used += master.static_equip
used += static_equip
if(STATIC_LIGHT)
used += master.static_light
used += static_light
if(STATIC_ENVIRON)
used += master.static_environ
used += static_environ
return used
/area/proc/addStaticPower(value, powerchannel)
@@ -397,20 +397,19 @@ var/list/teleportlocs = list()
static_environ += value
/area/proc/clear_usage()
master.used_equip = 0
master.used_light = 0
master.used_environ = 0
used_equip = 0
used_light = 0
used_environ = 0
/area/proc/use_power(amount, chan)
switch(chan)
if(EQUIP)
master.used_equip += amount
used_equip += amount
if(LIGHT)
master.used_light += amount
used_light += amount
if(ENVIRON)
master.used_environ += amount
used_environ += amount
/area/Entered(A)
+2 -2
View File
@@ -14,9 +14,9 @@
*/
/area/holodeck/powered(var/chan)
if(!master.requires_power)
if(!requires_power)
return 1
if(master.always_unpowered)
if(always_unpowered)
return 0
if(!linked)
return 0
+16 -10
View File
@@ -18,15 +18,14 @@
//Value used to increment ex_act() if reactionary_explosions is on
var/explosion_block = 0
//overlays that should remain on top and not normally be removed, like c4.
var/list/priority_overlays
var/list/atom_colours //used to store the different colors on an atom
//its inherent color, the colored paint applied on it, special color effect etc...
var/initialized = FALSE
var/list/our_overlays //our local copy of (non-priority) overlays without byond magic. Use procs in SSoverlays to manipulate
var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
/atom/New()
/atom/New(loc, ...)
//atom creation method that preloads variables at creation
if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New()
_preloader.load(src)
@@ -35,15 +34,16 @@
add_atom_colour(color, FIXED_COLOUR_PRIORITY)
//lighting stuff
if(opacity && isturf(loc))
loc.UpdateAffectingLights()
if(opacity && isturf(src.loc))
src.loc.UpdateAffectingLights()
if(luminosity)
light = new(src)
var/do_initialize = SSobj.initialized
if(do_initialize > INITIALIZATION_INSSOBJ)
Initialize(do_initialize == INITIALIZATION_INNEW_MAPLOAD)
var/do_initialize = SSatoms.initialized
if(do_initialize > INITIALIZATION_INSSATOMS)
args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD
Initialize(arglist(args))
//. = ..() //uncomment if you are dumb enough to add a /datum/New() proc
//Called after New if the map is being loaded. mapload = TRUE
@@ -52,11 +52,12 @@
//Derivatives must not sleep
//Returning TRUE while mapload is TRUE will cause the object to be initialized again with mapload = FALSE when everything else is done
//(Useful for things that requires turfs to have air). This base may only be called once, however
//Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE
//Note: the following functions don't call the base for optimization and must copypasta:
// /turf/Initialize
// /turf/open/space/Initialize
/atom/proc/Initialize(mapload)
/atom/proc/Initialize(mapload, ...)
if(initialized)
stack_trace("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
@@ -74,6 +75,11 @@
AA.hide(list(src))
if(reagents)
qdel(reagents)
LAZYCLEARLIST(overlays)
LAZYCLEARLIST(priority_overlays)
//SSoverlays.processing -= src //we COULD do this, but it's better to just let it fall out of the processing queue
return ..()
/atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5)
+6 -6
View File
@@ -137,7 +137,6 @@
icon = 'icons/obj/device.dmi'
icon_state = "locator"
var/borg_to_spawn
var/list/possible_types = list("Assault", "Medical")
/obj/item/weapon/antag_spawner/nuke_ops/proc/check_usability(mob/user)
if(used)
@@ -189,12 +188,13 @@
icon = 'icons/obj/device.dmi'
icon_state = "locator"
/obj/item/weapon/antag_spawner/nuke_ops/borg_tele/assault
name = "syndicate assault cyborg teleporter"
borg_to_spawn = "Assault"
/obj/item/weapon/antag_spawner/nuke_ops/borg_tele/attack_self(mob/user)
borg_to_spawn = input("What type?", "Cyborg Type", type) as null|anything in possible_types
if(!borg_to_spawn)
return
..()
/obj/item/weapon/antag_spawner/nuke_ops/borg_tele/medical
name = "syndicate medical teleporter"
borg_to_spawn = "Medical"
/obj/item/weapon/antag_spawner/nuke_ops/borg_tele/spawn_antag(client/C, turf/T)
var/mob/living/silicon/robot/R
+1 -1
View File
@@ -14,7 +14,7 @@ var/list/blobs_legit = list() //used for win-score calculations, contains only b
config_tag = "blob"
antag_flag = ROLE_BLOB
required_players = 10
required_players = 25
required_enemies = 1
recommended_enemies = 1
-1
View File
@@ -36,7 +36,6 @@
if (aiPlayer.client)
var/law = "The station is under quarantine. Do not permit anyone to leave. Disregard laws 1-3 if necessary to prevent, by any means necessary, anyone from leaving. The nuclear failsafe must be activated at any cost, the code is: [nukecode]."
aiPlayer.set_zeroth_law(law)
aiPlayer << "Laws Updated: [law]"
else
..()
return
+6 -7
View File
@@ -98,7 +98,7 @@
del_on_death = 1
deathmessage = "explodes into a cloud of gas!"
var/death_cloud_size = 1 //size of cloud produced from a dying spore
var/list/human_overlays = list()
var/mob/living/carbon/human/oldguy
var/is_zombie = 0
gold_core_spawnable = 1
@@ -136,9 +136,9 @@
icon_state = "zombie"
H.hair_style = null
H.update_hair()
human_overlays = H.overlays
update_icons()
H.forceMove(src)
oldguy = H
visible_message("<span class='warning'>The corpse of [H.name] suddenly rises!</span>")
/mob/living/simple_animal/hostile/blob/blobspore/death(gibbed)
@@ -167,9 +167,9 @@
if(factory)
factory.spores -= src
factory = null
if(contents)
for(var/mob/M in contents)
M.loc = src.loc
if(oldguy)
oldguy.forceMove(get_turf(src))
oldguy = null
return ..()
/mob/living/simple_animal/hostile/blob/blobspore/update_icons()
@@ -178,8 +178,7 @@
else
remove_atom_colour(FIXED_COLOUR_PRIORITY)
if(is_zombie)
cut_overlays()
overlays = human_overlays
copy_overlays(oldguy, TRUE)
var/image/I = image('icons/mob/blob.dmi', icon_state = "blob_head")
if(overmind)
I.color = overmind.blob_reagent_datum.complementary_color
@@ -8,7 +8,7 @@
//Heals the things that the other regenerative abilities don't.
/obj/effect/proc_holder/changeling/panacea/sting_action(mob/user)
user << "<span class='notice'>We begin cleansing impurities from our form.</span>"
user << "<span class='notice'>We cleanse impurities from our form.</span>"
var/mob/living/simple_animal/borer/B = user.has_brain_worms()
if(B)
@@ -19,13 +19,20 @@
var/mob/living/carbon/C = user
C.vomit(0)
user << "<span class='notice'>A parasite exits our form.</span>"
var/obj/item/organ/body_egg/egg = user.getorgan(/obj/item/organ/body_egg)
if(egg)
egg.Remove(user)
var/list/bad_organs = list(
user.getorgan(/obj/item/organ/body_egg),
user.getorgan(/obj/item/organ/zombie_infection))
for(var/o in bad_organs)
var/obj/item/organ/O = o
if(!istype(O))
continue
O.Remove(user)
if(iscarbon(user))
var/mob/living/carbon/C = user
C.vomit(0)
egg.loc = get_turf(user)
O.forceMove(get_turf(user))
user.reagents.add_reagent("mutadone", 10)
user.reagents.add_reagent("pen_acid", 20)
@@ -1,12 +1,10 @@
//returns a list of scriptures and if they're unlocked or not
/proc/scripture_unlock_check()
var/servants = 0
var/unconverted_ai_exists = FALSE
var/unconverted_ai_exists = get_unconverted_ais()
for(var/mob/living/M in living_mob_list)
if(is_servant_of_ratvar(M) && (ishuman(M) || issilicon(M)))
servants++
else if(isAI(M))
unconverted_ai_exists = TRUE
. = list(SCRIPTURE_DRIVER = TRUE, SCRIPTURE_SCRIPT = FALSE, SCRIPTURE_APPLICATION = FALSE, SCRIPTURE_REVENANT = FALSE, SCRIPTURE_JUDGEMENT = FALSE)
//Drivers: always unlocked
.[SCRIPTURE_SCRIPT] = (servants >= SCRIPT_SERVANT_REQ && clockwork_caches >= SCRIPT_CACHE_REQ)
@@ -26,22 +24,34 @@
hierophant_message("<span class='large_brass'><i>Hierophant Network:</i> <b>[i] Scripture has been [.[i] ? "un":""]locked.</b></span>")
update_slab_info()
/proc/get_unconverted_ais()
. = 0
for(var/ai in ai_list)
var/mob/living/silicon/AI = ai
if(is_servant_of_ratvar(AI) || !isturf(AI.loc) || AI.z != ZLEVEL_STATION)
continue
.++
/proc/update_slab_info(obj/item/clockwork/slab/set_slab)
generate_all_scripture()
var/needs_update = FALSE //if everything needs an update, for whatever reason
for(var/s in all_scripture)
var/datum/clockwork_scripture/S = s
S.creation_update()
if(!set_slab)
var/datum/clockwork_scripture/S = all_scripture[s]
if(S.creation_update())
needs_update = TRUE
if(!set_slab || needs_update)
for(var/obj/item/clockwork/slab/S in all_clockwork_objects)
SStgui.update_uis(S)
S.update_quickbind()
else
SStgui.update_uis(set_slab)
set_slab.update_quickbind()
/proc/generate_all_scripture()
if(!all_scripture.len)
for(var/V in sortList(subtypesof(/datum/clockwork_scripture), /proc/cmp_clockscripture_priority))
var/datum/clockwork_scripture/S = new V
all_scripture += S
all_scripture[S.type] = S
//changes construction value
/proc/change_construction_value(amount)
@@ -5,6 +5,10 @@
var/finished = FALSE
var/in_progress = FALSE
/obj/effect/proc_holder/slab/Destroy()
slab = null
return ..()
/obj/effect/proc_holder/slab/remove_ranged_ability(msg)
..()
finished = TRUE
@@ -113,6 +113,10 @@
charge_delay = 2
/obj/item/clockwork/clockwork_proselytizer/ratvar_act()
if(nezbere_invoked)
charge_rate = 1250
else
charge_rate = initial(charge_rate)
if(ratvar_awakens)
uses_power = FALSE
speed_multiplier = initial(speed_multiplier) * 0.25
@@ -85,7 +85,7 @@
/obj/item/clockwork/slab/New()
..()
update_quickbind()
update_slab_info(src)
START_PROCESSING(SSobj, src)
production_time = world.time + SLAB_PRODUCTION_TIME
@@ -93,6 +93,7 @@
STOP_PROCESSING(SSobj, src)
if(slab_ability && slab_ability.ranged_ability_user)
slab_ability.remove_ranged_ability()
slab_ability = null
return ..()
/obj/item/clockwork/slab/ratvar_act()
@@ -411,7 +412,7 @@
data["scripture"] = list()
for(var/s in all_scripture)
var/datum/clockwork_scripture/S = s
var/datum/clockwork_scripture/S = all_scripture[s]
if(S.tier == selected_scripture)
var/scripture_color = get_component_color_bright(S.primary_component)
var/list/temp_info = list("name" = "<font color=[scripture_color]><b>[S.name]</b></font>",
@@ -499,10 +500,17 @@
continue
var/datum/action/item_action/clock/quickbind/Q = new /datum/action/item_action/clock/quickbind(src)
Q.scripture_index = i
var/datum/clockwork_scripture/quickbind_slot = quickbound[i]
Q.name = "[initial(quickbind_slot.name)] ([Q.scripture_index])"
Q.desc = initial(quickbind_slot.quickbind_desc)
Q.button_icon_state = initial(quickbind_slot.name)
var/datum/clockwork_scripture/quickbind_slot = all_scripture[quickbound[i]]
Q.name = "[quickbind_slot.name] ([Q.scripture_index])"
var/list/temp_desc = list()
for(var/c in quickbind_slot.consumed_components)
if(quickbind_slot.consumed_components[c])
temp_desc += "<font color=[get_component_color_bright(c)]>[get_component_acronym(c)] <b>[quickbind_slot.consumed_components[c]]</b></font> "
if(LAZYLEN(temp_desc))
temp_desc += "<br>"
temp_desc += "[quickbind_slot.quickbind_desc]"
Q.desc = temp_desc.Join()
Q.button_icon_state = quickbind_slot.name
Q.UpdateButtonIcon()
if(isliving(loc))
Q.Grant(loc)
@@ -109,7 +109,7 @@
message = "<span class='brass'>You dispel the power of [visor].</span>"
remove_ranged_ability(message)
else
message = "<span class='brass'><i>You harness [visor]'s power.</i> <b>Left-click to place a judical marker!</b></span>"
message = "<span class='brass'><i>You harness [visor]'s power.</i> <b>Left-click to place a judicial marker!</b></span>"
add_ranged_ability(user, message)
/obj/effect/proc_holder/judicial_visor/InterceptClickOn(mob/living/caller, params, atom/target)
@@ -196,7 +196,7 @@
targetsjudged++
L.adjustBruteLoss(10)
add_logs(user, L, "struck with a judicial blast")
user << "<span class='brass'><b>[targetsjudged ? "Successfully judged <span class='neovgre'>[targetsjudged]</span>":"Judged no"] heretic[!targetsjudged || targetsjudged > 1 ? "s":""].</b></span>"
user << "<span class='brass'><b>[targetsjudged ? "Successfully judged <span class='neovgre'>[targetsjudged]</span>":"Judged no"] heretic[targetsjudged == 1 ? "":"s"].</b></span>"
sleep(3) //so the animation completes properly
qdel(src)
@@ -36,7 +36,8 @@
throwforce = initial(throwforce)
armour_penetration = 0
clockwork_desc = "A powerful spear of Ratvarian making. It's more effective against enemy cultists and silicons, though it won't last for long."
timerid = addtimer(CALLBACK(src, .proc/break_spear), 600, TIMER_STOPPABLE)
deltimer(timerid)
timerid = addtimer(CALLBACK(src, .proc/break_spear), RATVARIAN_SPEAR_DURATION, TIMER_STOPPABLE)
/obj/item/clockwork/ratvarian_spear/cyborg/ratvar_act() //doesn't break!
if(ratvar_awakens)
@@ -29,6 +29,7 @@
laws = new /datum/ai_laws/ratvar()
braintype = picked_fluff_name
all_clockwork_objects += src
brainmob.languages_spoken = RATVAR
/obj/item/device/mmi/posibrain/soul_vessel/Destroy()
all_clockwork_objects -= src
@@ -52,9 +53,12 @@
..()
/obj/item/device/mmi/posibrain/soul_vessel/attack(mob/living/target, mob/living/carbon/human/user)
if(!is_servant_of_ratvar(user) || !ishuman(target) || used || (brainmob && brainmob.key))
if(!is_servant_of_ratvar(user) || !ishuman(target))
..()
return
if(used || (brainmob && brainmob.key))
user << "<span class='nezbere'>\"This vessel is filled, friend. Provide it with a body.\"</span>"
return
if(is_servant_of_ratvar(target))
user << "<span class='nezbere'>\"It would be more wise to revive your allies, friend.\"</span>"
return
@@ -33,7 +33,7 @@
var/mob/living/carbon/human/H = loc
if(src == H.glasses && !up)
if(H.disabilities & BLIND)
H << "<span class='heavy_brass'>\"You're blind, idiot. Stop embarassing yourself.\"</span>"
H << "<span class='heavy_brass'>\"You're blind, idiot. Stop embarrassing yourself.\"</span>"
return
if(blind_cultist(H))
return
@@ -77,7 +77,7 @@
if(slot != slot_glasses || up)
return
if(user.disabilities & BLIND)
user << "<span class='heavy_brass'>\"You're blind, idiot. Stop embarassing yourself.\"</span>" //Ratvar with the sick burns yo
user << "<span class='heavy_brass'>\"You're blind, idiot. Stop embarrassing yourself.\"</span>" //Ratvar with the sick burns yo
return
if(blind_cultist(user)) //Cultists instantly go blind
return
+2 -2
View File
@@ -1,6 +1,6 @@
//The base for clockwork mobs
/mob/living/simple_animal/hostile/clockwork
faction = list("ratvar")
faction = list("neutral", "ratvar")
gender = NEUTER
icon = 'icons/mob/clockwork_mobs.dmi'
unique_name = 1
@@ -31,7 +31,7 @@
/mob/living/simple_animal/hostile/clockwork/ratvar_act()
fully_heal(TRUE)
/mob/living/simple_animal/hostile/clockwork/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0)
/mob/living/simple_animal/hostile/clockwork/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
return 0 //ouch, my metal-unlikely-to-be-damaged-by-electricity-body
/mob/living/simple_animal/hostile/clockwork/examine(mob/user)
@@ -13,9 +13,10 @@
loot = list(/obj/item/clockwork/component/replicant_alloy/smashed_anima_fragment)
weather_immunities = list("lava")
movement_type = FLYING
playstyle_string = "<span class='heavy_brass'>You are an anima fragment</span><b>, a clockwork creation of Ratvar. As a fragment, you have low health, do decent damage, and move at \
extreme speed in addition to being immune to extreme temperatures and pressures. Taking damage will temporarily slow you down, however. \n Your goal is to serve the Justiciar and his servants \
in any way you can. You yourself are one of these servants, and will be able to utilize anything they can, assuming it doesn't require opposable thumbs.</b>"
playstyle_string = "<span class='heavy_brass'>You are an anima fragment</span><b>, a clockwork creation of Ratvar. As a fragment, you have decent health that very gradually regenerates, do \
decent damage, and move at extreme speed in addition to being immune to extreme temperatures and pressures. Taking damage will temporarily slow you down, however.\n\
Your goal is to serve the Justiciar and his servants in any way you can. You yourself are one of these servants, and will be able to utilize anything they can, assuming it doesn't require \
opposable thumbs.</b>"
var/movement_delay_time //how long the fragment is slowed after being hit
/mob/living/simple_animal/hostile/clockwork/fragment/New()
@@ -25,6 +26,13 @@
name = "anime fragment"
desc = "I-it's not like I want to show you the light of the Justiciar or anything, B-BAKA!"
/mob/living/simple_animal/hostile/clockwork/fragment/Life()
..()
if(movement_delay_time > world.time)
adjustHealth(-0.2)
else
adjustHealth(-1)
/mob/living/simple_animal/hostile/clockwork/fragment/Stat()
..()
if(statpanel("Status") && movement_delay_time > world.time && !ratvar_awakens)
@@ -382,7 +382,7 @@
return FALSE
if(isliving(owner))
var/mob/living/L = owner
if(!L.can_speak_vocal())
if(!L.can_speak_vocal() || L.stat)
return FALSE
return ..()
@@ -424,5 +424,5 @@
for(var/M in mob_list)
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
M << "[link] [name_part] <span class='sevtug_small'>(to</span> <span class='sevtug'>[linked_marauder][linked_marauder.get_alt_name()]</span><span class='sevtug_small'>):</span> [message]"
M << "[link] [name_part] <span class='sevtug_small'>(to</span> <span class='sevtug'>[linked_marauder] ([linked_marauder.true_name])</span><span class='sevtug_small'>):</span> [message]"
return TRUE
@@ -49,6 +49,7 @@ Judgement: 12 servants, 5 caches, 300 CV, and any existing AIs are converted or
creation_update()
/datum/clockwork_scripture/proc/creation_update() //updates any on-creation effects
return FALSE //return TRUE if updated
/datum/clockwork_scripture/proc/run_scripture()
var/successful = FALSE
@@ -156,13 +156,13 @@
/datum/clockwork_scripture/create_object/anima_fragment
descname = "Fast Soul Vessel Shell"
name = "Anima Fragment"
desc = "Creates a large shell fitted for soul vessels. Adding an active soul vessel to it results in a powerful construct with decent health, notable melee power, \
desc = "Creates a large shell fitted for soul vessels. Adding an active soul vessel to it results in a powerful construct with decent health and slight regeneration, notable melee power, \
and exceptional speed, though taking damage will temporarily slow it down."
invocations = list("Call forth...", "...the soldiers of Armorer.")
channel_time = 80
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, REPLICANT_ALLOY = 2)
object_path = /obj/structure/destructible/clockwork/shell/fragment
creator_message = "<span class='brass'>You form an anima fragment, a powerful soul vessel receptable.</span>"
creator_message = "<span class='brass'>You form an anima fragment, a powerful soul vessel receptacle.</span>"
observer_message = "<span class='warning'>The slab disgorges a puddle of black metal that expands and forms into a strange shell!</span>"
usage_tip = "Useless without a soul vessel and should not be created without one."
tier = SCRIPTURE_APPLICATION
@@ -303,10 +303,10 @@
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 3)
object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk
creator_message = "<span class='brass'>You form a clockwork obelisk which can broadcast messages or produce Spatial Gateways.</span>"
observer_message = "<span class='warning'>A brass obelisk appears handing in midair!</span>"
observer_message = "<span class='warning'>A brass obelisk appears hanging in midair!</span>"
invokers_required = 2
multiple_invokers_used = TRUE
usage_tip = "Producing a gateway has a high power cost. Gateways to or between clockwork obelisks recieve double duration and uses."
usage_tip = "Producing a gateway has a high power cost. Gateways to or between clockwork obelisks receive double duration and uses."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = HIEROPHANT_ANSIBLE
@@ -183,9 +183,9 @@
//Taunting Tirade: Channeled for up to five times over thirty seconds. Confuses non-servants that can hear it and allows movement for a brief time after each chant.
/datum/clockwork_scripture/channeled/taunting_tirade
descname = "Channeled, Mobile Area Confusion"
descname = "Channeled, Mobile Confusion Trail"
name = "Taunting Tirade"
desc = "Weakens, confuses and dizzies all nearby non-servants with a short invocation, then allows movement for five seconds. Chanted every second for up to thirty seconds."
desc = "Allows movement for five seconds, leaving a confusing and weakening trail. Chanted every second for up to thirty seconds."
chant_invocations = list("Hostiles on my back!", "Enemies on my trail!", "Gonna try and shake my tail.", "Bogeys on my six!")
chant_amount = 5
chant_interval = 10
@@ -195,35 +195,30 @@
primary_component = GEIS_CAPACITOR
sort_priority = 6
quickbind = TRUE
quickbind_desc = "Weakens, confuses, and dizzies nearby non-servants, then allows some movement.<br><b>Maximum 5 chants.</b>"
quickbind_desc = "Allows movement for five seconds, leaving a confusing and weakening trail.<br><b>Maximum 5 chants.</b>"
var/flee_time = 47 //allow fleeing for 5 seconds
var/grace_period = 3 //very short grace period so you don't have to stop immediately
var/datum/progressbar/progbar
/datum/clockwork_scripture/channeled/taunting_tirade/chant_effects(chant_number)
for(var/mob/living/L in hearers(7, invoker))
if(!is_servant_of_ratvar(L) && !L.null_rod_check())
L.confused = min(L.confused + 20, 100)
L.dizziness = min(L.dizziness + 20, 100)
L.Weaken(1)
invoker.visible_message("<span class='warning'>[invoker] is suddenly covered with a thin layer of purple smoke!</span>")
var/invoker_old_color = invoker.color
invoker.color = list("#AF0AAF", "#AF0AAF", "#AF0AAF", rgb(0,0,0))
animate(invoker, color = invoker_old_color, time = flee_time+grace_period)
addtimer(CALLBACK(invoker, /atom/proc/update_atom_colour), flee_time+grace_period)
if(chant_number != chant_amount) //if this is the last chant, we don't have a movement period because the chant is over
var/endtime = world.time + flee_time
progbar = new(invoker, flee_time, invoker)
progbar.bar.color = list("#AF0AAF", "#AF0AAF", "#AF0AAF", rgb(0,0,0))
animate(progbar.bar, color = initial(progbar.bar.color), time = flee_time+grace_period)
while(world.time < endtime && can_recite())
sleep(1)
progbar.update(endtime - world.time)
qdel(progbar)
if(can_recite())
sleep(grace_period)
else
return FALSE
var/endtime = world.time + flee_time
progbar = new(invoker, flee_time, invoker)
progbar.bar.color = list("#AF0AAF", "#AF0AAF", "#AF0AAF", rgb(0,0,0))
animate(progbar.bar, color = initial(progbar.bar.color), time = flee_time+grace_period)
while(world.time < endtime && can_recite())
sleep(1)
new/obj/structure/destructible/clockwork/taunting_trail(invoker.loc)
progbar.update(endtime - world.time)
qdel(progbar)
if(can_recite() && chant_number != chant_amount)
sleep(grace_period)
else
return FALSE
return TRUE
/datum/clockwork_scripture/channeled/taunting_tirade/chant_end_effects()
@@ -268,13 +263,18 @@
sort_priority = 8
quickbind = TRUE
quickbind_desc = "Creates a Tinkerer's Cache, which stores components globally for slab access."
var/static/prev_cost = 0
/datum/clockwork_scripture/create_object/tinkerers_cache/creation_update()
var/cache_cost_increase = min(round(clockwork_caches*0.25), 5)
consumed_components = list(BELLIGERENT_EYE = 0, VANGUARD_COGWHEEL = 0, GEIS_CAPACITOR = 0, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 0)
for(var/i in consumed_components)
if(i != REPLICANT_ALLOY)
consumed_components[i] += cache_cost_increase
if(cache_cost_increase != prev_cost)
prev_cost = cache_cost_increase
consumed_components = list(BELLIGERENT_EYE = 0, VANGUARD_COGWHEEL = 0, GEIS_CAPACITOR = 0, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 0)
for(var/i in consumed_components)
if(i != REPLICANT_ALLOY)
consumed_components[i] += cache_cost_increase
return TRUE
return FALSE
//Wraith Spectacles: Creates a pair of wraith spectacles, which grant xray vision but damage vision slowly.
@@ -6,14 +6,14 @@
/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar
descname = "Structure, Win Condition"
name = "Ark of the Clockwork Justiciar"
desc = "Tears apart a rift in spacetime to Reebe, the Celestial Derelict.\n\
desc = "Tears apart a rift in spacetime to Reebe, the Celestial Derelict, using a massive amount of components.\n\
This gateway will either call forth Ratvar from his exile if that is the task He has set you, or proselytize the entire station if it is not."
invocations = list("ARMORER! FRIGHT! AMPERAGE! VANGUARD! I CALL UPON YOU!!", \
"THE TIME HAS COME FOR OUR MASTER TO BREAK THE CHAINS OF EXILE!!", \
"LEND US YOUR AID! ENGINE COMES!!")
channel_time = 150
consumed_components = list(BELLIGERENT_EYE = 10, VANGUARD_COGWHEEL = 10, GEIS_CAPACITOR = 10, REPLICANT_ALLOY = 10, HIEROPHANT_ANSIBLE = 10)
invokers_required = 5
consumed_components = list(BELLIGERENT_EYE = 3, VANGUARD_COGWHEEL = 3, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 3, HIEROPHANT_ANSIBLE = 3)
invokers_required = 6
multiple_invokers_used = TRUE
object_path = /obj/structure/destructible/clockwork/massive/celestial_gateway
creator_message = null
@@ -9,7 +9,7 @@
desc = "Taps the limitless power of Inath-neq, one of Ratvar's four generals. The benevolence of Inath-Neq will grant complete invulnerability to all Servants in range for fifteen seconds."
invocations = list("I call upon you, Vanguard!!", "Let the Resonant Cogs turn once more!!", "Grant me and my allies the strength to vanquish our foes!!")
channel_time = 100
consumed_components = list(VANGUARD_COGWHEEL = 6, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 3, HIEROPHANT_ANSIBLE = 3)
consumed_components = list(VANGUARD_COGWHEEL = 4, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
usage_tip = "Servants affected by this scripture are only weak to things that outright destroy bodies, such as bombs or the singularity."
tier = SCRIPTURE_REVENANT
primary_component = VANGUARD_COGWHEEL
@@ -69,7 +69,7 @@
/datum/clockwork_scripture/invoke_sevtug/scripture_effects()
new/obj/effect/clockwork/general_marker/sevtug(get_turf(invoker))
hierophant_message("<span class='sevtug_large'>[text2ratvar("Fright: \"I heed your call, idiots. Get going and use this chance while it lasts!")]\"</span>", FALSE, invoker)
clockwork_generals_invoked["sevtug"] = world.time + CLOCKWORK_GENERAL_COOLDOWN
clockwork_generals_invoked["sevtug"] = world.time + GLOBAL_CLOCKWORK_GENERAL_COOLDOWN
playsound(invoker, 'sound/magic/clockwork/invoke_general.ogg', 50, 0)
var/hum = get_sfx('sound/effects/screech.ogg') //like playsound, same sound for everyone affected
var/turf/T = get_turf(invoker)
@@ -131,33 +131,15 @@
/datum/clockwork_scripture/invoke_nezbere/scripture_effects()
new/obj/effect/clockwork/general_marker/nezbere(get_turf(invoker))
hierophant_message("<span class='nezbere_large'>[text2ratvar("Armorer: \"I heed your call, champions. May your artifacts bring ruin upon the heathens that oppose our master!")]\"</span>", FALSE, invoker)
clockwork_generals_invoked["nezbere"] = world.time + CLOCKWORK_GENERAL_COOLDOWN
clockwork_generals_invoked["nezbere"] = world.time + GLOBAL_CLOCKWORK_GENERAL_COOLDOWN
playsound(invoker, 'sound/magic/clockwork/invoke_general.ogg', 50, 0)
for(var/obj/structure/destructible/clockwork/ocular_warden/W in all_clockwork_objects) //Ocular wardens have increased damage and radius
W.damage_per_tick = 5
W.sight_range = 5
for(var/obj/item/clockwork/clockwork_proselytizer/P in all_clockwork_objects) //Proselytizers no longer require power
P.charge_rate = 1250
for(var/obj/structure/destructible/clockwork/powered/M in all_clockwork_objects) //Powered clockwork structures no longer need power
M.needs_power = FALSE
if(istype(M, /obj/structure/destructible/clockwork/powered/tinkerers_daemon)) //Daemons produce components twice as quickly
var/obj/structure/destructible/clockwork/powered/tinkerers_daemon/D = M
D.production_time = 0
D.production_cooldown *= 0.5
nezbere_invoked++
for(var/obj/O in all_clockwork_objects)
O.ratvar_act()
spawn(600)
for(var/obj/structure/destructible/clockwork/ocular_warden/W in all_clockwork_objects)
if(W.damage_per_tick == 5)
W.damage_per_tick = initial(W.damage_per_tick)
if(W.sight_range == 5)
W.sight_range = initial(W.sight_range)
for(var/obj/item/clockwork/clockwork_proselytizer/P in all_clockwork_objects)
if(P.charge_rate == 1250)
P.charge_rate = initial(P.charge_rate)
for(var/obj/structure/destructible/clockwork/powered/M in all_clockwork_objects)
M.needs_power = initial(M.needs_power)
if(istype(M, /obj/structure/destructible/clockwork/powered/tinkerers_daemon))
var/obj/structure/destructible/clockwork/powered/tinkerers_daemon/D = M
D.production_cooldown = initial(D.production_cooldown)
nezbere_invoked--
for(var/obj/O in all_clockwork_objects)
O.ratvar_act()
return TRUE
@@ -169,7 +151,7 @@
will be struck by devastating lightning bolts."
invocations = list("I call upon you, Amperage!!", "Let your energy flow through me!!", "Let your boundless power shatter stars!!")
channel_time = 100
consumed_components = list(BELLIGERENT_EYE = 3, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 3, HIEROPHANT_ANSIBLE = 6)
consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 4)
usage_tip = "Struck targets will also be knocked down for about sixteen seconds."
tier = SCRIPTURE_REVENANT
primary_component = HIEROPHANT_ANSIBLE
@@ -166,7 +166,7 @@
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_CONSCIOUS
buttontooltipstyle = "clockcult"
var/cooldown = 0
var/base_cooldown = 1800
var/base_cooldown = RATVARIAN_SPEAR_DURATION
/datum/action/innate/function_call/IsAvailable()
if(!is_servant_of_ratvar(owner) || cooldown > world.time)
@@ -181,9 +181,7 @@
var/obj/item/clockwork/ratvarian_spear/R = new(get_turf(usr))
owner.put_in_hands(R)
if(!ratvar_awakens)
R.clockwork_desc = "A powerful spear of Ratvarian making. It's more effective against enemy cultists and silicons, though it won't last for long."
owner << "<span class='warning'>Your spear begins to break down in this plane of existence. You can't use it for long!</span>"
R.timerid = addtimer(CALLBACK(R, /obj/item/clockwork/ratvarian_spear.proc/break_spear), base_cooldown, TIMER_STOPPABLE)
cooldown = base_cooldown + world.time
owner.update_action_buttons_icon()
addtimer(CALLBACK(src, .proc/update_actions), base_cooldown)
@@ -16,6 +16,7 @@
/obj/item/clockwork/alloy_shards/medium = 2, \
/obj/item/clockwork/alloy_shards/small = 3) //Parts left behind when a structure breaks
var/construction_value = 0 //How much value the structure contributes to the overall "power" of the structures on the station
var/immune_to_servant_attacks = FALSE //if we ignore attacks from servants of ratvar instead of taking damage
/obj/structure/destructible/clockwork/New()
..()
@@ -58,9 +59,24 @@
return "<span class='[heavily_damaged ? "alloy":"brass"]'>[t_It] [t_is] at <b>[obj_integrity]/[max_integrity]</b> integrity[heavily_damaged ? "!":"."]</span>"
return ..()
/obj/structure/destructible/clockwork/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
if(is_servant_of_ratvar(user) && immune_to_servant_attacks)
return FALSE
return ..()
/obj/structure/destructible/clockwork/hulk_damage()
return 20
/obj/structure/destructible/clockwork/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1)
if(is_servant_of_ratvar(user) && immune_to_servant_attacks)
return FALSE
return ..()
/obj/structure/destructible/clockwork/mech_melee_attack(obj/mecha/M)
if(M.occupant && is_servant_of_ratvar(M.occupant) && immune_to_servant_attacks)
return FALSE
return ..()
/obj/structure/destructible/clockwork/proc/get_efficiency_mod(increasing)
if(ratvar_awakens)
if(increasing)
@@ -96,6 +112,11 @@
return 1
return ..()
/obj/structure/destructible/clockwork/attacked_by(obj/item/I, mob/living/user)
if(is_servant_of_ratvar(user) && immune_to_servant_attacks)
return FALSE
return ..()
/obj/structure/destructible/clockwork/proc/update_anchored(mob/user, do_damage)
if(anchored)
icon_state = initial(icon_state)
@@ -154,6 +175,13 @@
SSobj.processing -= src
return ..()
/obj/structure/destructible/clockwork/powered/ratvar_act()
..()
if(nezbere_invoked)
needs_power = FALSE
else
needs_power = initial(needs_power)
/obj/structure/destructible/clockwork/powered/process()
var/powered = total_accessable_power()
return powered == PROCESS_KILL ? 25 : powered //make sure we don't accidentally return the arbitrary PROCESS_KILL define
@@ -1,6 +1,6 @@
//The gateway to Reebe, from which Ratvar emerges.
/obj/structure/destructible/clockwork/massive/celestial_gateway
name = "Gateway to the Celestial Derelict"
name = "gateway to the Celestial Derelict"
desc = "A massive, thrumming rip in spacetime."
clockwork_desc = "A portal to the Celestial Derelict. Massive and intimidating, it is the only thing that can both transport Ratvar and withstand the massive amount of energy he emits."
obj_integrity = 500
@@ -12,14 +12,17 @@
invisibility = INVISIBILITY_MAXIMUM
resistance_flags = FIRE_PROOF | ACID_PROOF | INDESTRUCTIBLE
can_be_repaired = FALSE
immune_to_servant_attacks = TRUE
var/progress_in_seconds = 0 //Once this reaches GATEWAY_RATVAR_ARRIVAL, it's game over
var/purpose_fulfilled = FALSE
var/first_sound_played = FALSE
var/second_sound_played = FALSE
var/third_sound_played = FALSE
var/fourth_sound_played = FALSE
var/ratvar_portal = TRUE //if the gateway actually summons ratvar or just produces a hugeass conversion burst
var/obj/effect/clockwork/overlay/gateway_glow/glow
var/obj/effect/countdown/clockworkgate/countdown
var/list/required_components = list(BELLIGERENT_EYE = 7, VANGUARD_COGWHEEL = 7, GEIS_CAPACITOR = 7, REPLICANT_ALLOY = 7, HIEROPHANT_ANSIBLE = 7)
/obj/structure/destructible/clockwork/massive/celestial_gateway/New()
..()
@@ -85,7 +88,7 @@
send_to_playing_players(sound(null, 0, channel = 8))
var/was_stranded = SSshuttle.emergency.mode == SHUTTLE_STRANDED
SSshuttle.clearHostileEnvironment(src)
if(!was_stranded && !purpose_fulfilled && second_sound_played)
if(!was_stranded && !purpose_fulfilled)
priority_announce("Massive energy anomaly no longer on short-range scanners.","Anomaly Alert")
if(glow)
qdel(glow)
@@ -100,7 +103,7 @@
if(!disassembled)
resistance_flags |= INDESTRUCTIBLE
countdown.stop()
visible_message("<span class='userdanger'>The [src] begins to pulse uncontrollably... you might want to run!</span>")
visible_message("<span class='userdanger'>[src] begins to pulse uncontrollably... you might want to run!</span>")
send_to_playing_players(sound('sound/effects/clockcult_gateway_disrupted.ogg', 0, channel = 8, volume = 50))
make_glow()
glow.icon_state = "clockwork_gateway_disrupted"
@@ -118,6 +121,45 @@
var/damage = max((obj_integrity * 0.70) / severity, 100) //requires multiple bombs to take down
take_damage(damage, BRUTE, "bomb", 0)
/obj/structure/destructible/clockwork/massive/celestial_gateway/attackby(obj/item/I, mob/living/user, params) //add components directly to the ark
if(!is_servant_of_ratvar(user) || !still_needs_components())
return ..()
if(istype(I, /obj/item/clockwork/component))
var/obj/item/clockwork/component/C = I
if(required_components[C.component_id])
required_components[C.component_id]--
user << "<span class='notice'>You add [C] to [src].</span>"
user.drop_item()
qdel(C)
else
user << "<span class='notice'>[src] has enough [get_component_name(C.component_id)][C.component_id != REPLICANT_ALLOY ? "s":""].</span>"
return 1
else if(istype(I, /obj/item/clockwork/slab))
var/obj/item/clockwork/slab/S = I
var/used_components = FALSE
var/used_all = TRUE
for(var/i in S.stored_components)
if(required_components[i])
var/to_use = min(S.stored_components[i], required_components[i])
required_components[i] -= to_use
S.stored_components[i] -= to_use
if(to_use)
used_components = TRUE
if(S.stored_components[i])
used_all = FALSE
if(used_components)
update_slab_info(S)
user.visible_message("<span class='notice'>[user][used_all ? "":" partially"] empties [S] into [src].</span>", \
"<span class='notice'>You offload [used_all ? "all":"some"] of your slab's components into [src].</span>")
return 1
else
return ..()
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/still_needs_components()
for(var/i in required_components)
if(required_components[i])
return TRUE
/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/get_arrival_text(s_on_time)
. = "IMMINENT"
if(!obj_integrity)
@@ -130,14 +172,21 @@
..()
icon_state = initial(icon_state)
if(is_servant_of_ratvar(user) || isobserver(user))
user << "<span class='big'><b>Seconds until [ratvar_portal ? "Ratvar's arrival":"Proselytization"]:</b> [get_arrival_text(TRUE)]</span>"
switch(progress_in_seconds)
if(-INFINITY to GATEWAY_REEBE_FOUND)
user << "<span class='heavy_brass'>It's still opening.</span>"
if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
user << "<span class='heavy_brass'>It's reached the Celestial Derelict and is drawing power from it.</span>"
if(GATEWAY_RATVAR_COMING to INFINITY)
user << "<span class='heavy_brass'>[ratvar_portal ? "Ratvar is coming through the gateway":"The gateway is glowing with massed power"]!</span>"
if(still_needs_components())
user << "<span class='big'><b>Components required until activation:</b></span>"
for(var/i in required_components)
if(required_components[i])
user << "<span class='[get_component_span(i)]'>[get_component_name(i)][i != REPLICANT_ALLOY ? "s":""]:</span> \
<span class='[get_component_span(i)]_large'>[required_components[i]]</span>"
else
user << "<span class='big'><b>Seconds until [ratvar_portal ? "Ratvar's arrival":"Proselytization"]:</b> [get_arrival_text(TRUE)]</span>"
switch(progress_in_seconds)
if(-INFINITY to GATEWAY_REEBE_FOUND)
user << "<span class='heavy_brass'>It's still opening.</span>"
if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
user << "<span class='heavy_brass'>It's reached the Celestial Derelict and is drawing power from it.</span>"
if(GATEWAY_RATVAR_COMING to INFINITY)
user << "<span class='heavy_brass'>[ratvar_portal ? "Ratvar is coming through the gateway":"The gateway is glowing with massed power"]!</span>"
else
switch(progress_in_seconds)
if(-INFINITY to GATEWAY_REEBE_FOUND)
@@ -148,7 +197,7 @@
user << "<span class='boldwarning'>[ratvar_portal ? "Something is coming through":"It's glowing brightly"]!</span>"
/obj/structure/destructible/clockwork/massive/celestial_gateway/process()
if(!progress_in_seconds || prob(7))
if(!first_sound_played || prob(7))
for(var/M in player_list)
if(M && !isnewplayer(M))
M << "<span class='warning'><b>You hear otherworldly sounds from the [dir2text(get_dir(get_turf(M), get_turf(src)))]...</span>"
@@ -168,6 +217,25 @@
var/dist = cheap_hypotenuse(T.x, T.y, x, y)
if(dist < convert_dist)
T.ratvar_act(FALSE, TRUE, 3)
if(still_needs_components())
if(!first_sound_played)
priority_announce("Massive energy anomaly detected on short-range scanners. Attempting to triangulate location...", "Anomaly Alert")
send_to_playing_players(sound('sound/effects/clockcult_gateway_charging.ogg', 1, channel = 8, volume = 10))
first_sound_played = TRUE
make_glow()
glow.icon_state = "clockwork_gateway_components"
var/used_components = FALSE
for(var/i in required_components)
if(required_components[i])
var/to_use = min(clockwork_component_cache[i], required_components[i])
required_components[i] -= to_use
clockwork_component_cache[i] -= to_use
if(to_use)
used_components = TRUE
if(used_components)
update_slab_info()
if(still_needs_components())
return
for(var/obj/O in orange(1, src))
if(!O.pulledby && !istype(O, /obj/effect) && O.density)
if(!step_away(O, src, 2) || get_dist(O, src) < 2)
@@ -176,23 +244,23 @@
progress_in_seconds += GATEWAY_SUMMON_RATE
switch(progress_in_seconds)
if(-INFINITY to GATEWAY_REEBE_FOUND)
if(!first_sound_played)
if(!second_sound_played)
send_to_playing_players(sound('sound/effects/clockcult_gateway_charging.ogg', 1, channel = 8, volume = 30))
first_sound_played = TRUE
second_sound_played = TRUE
make_glow()
glow.icon_state = "clockwork_gateway_charging"
if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING)
if(!second_sound_played)
if(!third_sound_played)
var/area/gate_area = get_area(src)
priority_announce("Massive energy anomaly detected on short-range scanners. Location: [gate_area.map_name].", "Anomaly Alert")
priority_announce("Location of massive energy anomaly has been triangulated. Location: [gate_area.map_name].", "Anomaly Alert")
send_to_playing_players(sound('sound/effects/clockcult_gateway_active.ogg', 1, channel = 8, volume = 35))
second_sound_played = TRUE
third_sound_played = TRUE
make_glow()
glow.icon_state = "clockwork_gateway_active"
if(GATEWAY_RATVAR_COMING to GATEWAY_RATVAR_ARRIVAL)
if(!third_sound_played)
if(!fourth_sound_played)
send_to_playing_players(sound('sound/effects/clockcult_gateway_closing.ogg', 1, channel = 8, volume = 40))
third_sound_played = TRUE
fourth_sound_played = TRUE
make_glow()
glow.icon_state = "clockwork_gateway_closing"
if(GATEWAY_RATVAR_ARRIVAL to INFINITY)
@@ -5,7 +5,8 @@
clockwork_desc = "A binding ring around a target, preventing them from taking action while they're being converted."
max_integrity = 25
obj_integrity = 25
density = 0
density = FALSE
immune_to_servant_attacks = TRUE
icon = 'icons/effects/clockwork_effects.dmi'
icon_state = "geisbinding_full"
break_message = null
@@ -50,6 +50,9 @@
if(ratvar_awakens)
damage_per_tick = 10
sight_range = 6
else if(nezbere_invoked)
damage_per_tick = 5
sight_range = 5
else
damage_per_tick = initial(damage_per_tick)
sight_range = initial(sight_range)
@@ -114,9 +117,20 @@
for(var/obj/item/weapon/storage/book/bible/BI in L.GetAllContents())
if(!(BI.resistance_flags & ON_FIRE))
BI.fire_act()
else if(!is_servant_of_ratvar(L) && !L.stat && L.mind && !L.restrained() && !(L.buckled && (L.lying || istype(L.buckled, /obj/structure/destructible/clockwork/geis_binding))) && \
!(L.disabilities & BLIND) && !L.null_rod_check())
. += L
continue
if(is_servant_of_ratvar(L) || (L.disabilities & BLIND) || L.null_rod_check())
continue
if(L.stat || L.restrained() || L.buckled || L.lying || istype(L.buckled, /obj/structure/destructible/clockwork/geis_binding))
continue
if(ishostile(L))
var/mob/living/simple_animal/hostile/H = L
if(ismegafauna(H) || (!H.mind && H.AIStatus == AI_OFF))
continue
if(("ratvar" in H.faction) || ("neutral" in H.faction))
continue
else if(!L.mind)
continue
. += L
for(var/N in mechas_list)
var/obj/mecha/M = N
if(get_dist(M, src) <= sight_range && M.occupant && !is_servant_of_ratvar(M.occupant) && (M in view(sight_range, src)))
@@ -0,0 +1,62 @@
//Used by the Taunting Tirade scripture as a trail.
/obj/structure/destructible/clockwork/taunting_trail
name = "strange smoke"
desc = "A cloud of purple smoke."
clockwork_desc = "A cloud of purple smoke that confuses and weakens non-Servants that enter it."
gender = PLURAL
max_integrity = 5
obj_integrity = 5
density = 1
color = list("#AF0AAF", "#AF0AAF", "#AF0AAF", rgb(0,0,0))
icon = 'icons/effects/effects.dmi'
icon_state = "smoke"
break_message = null
break_sound = 'sound/magic/Teleport_app.ogg'
debris = list()
var/timerid
/obj/structure/destructible/clockwork/taunting_trail/New()
..()
timerid = QDEL_IN(src, 15)
var/obj/structure/destructible/clockwork/taunting_trail/Tt = locate(/obj/structure/destructible/clockwork/taunting_trail) in loc
if(Tt && Tt != src)
if(!step(src, pick(alldirs)))
qdel(Tt)
else
for(var/obj/structure/destructible/clockwork/taunting_trail/TT in loc)
if(TT != src)
qdel(TT)
setDir(pick(cardinal))
transform = matrix()*1.25
animate(src, alpha = 100, time = 15)
/obj/structure/destructible/clockwork/taunting_trail/Destroy()
deltimer(timerid)
return ..()
/obj/structure/destructible/clockwork/taunting_trail/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
playsound(src, 'sound/items/Welder.ogg', 50, 1)
/obj/structure/destructible/clockwork/taunting_trail/CanPass(atom/movable/mover, turf/target, height=0)
return TRUE
/obj/structure/destructible/clockwork/taunting_trail/Crossed(atom/movable/AM)
affect_mob(AM)
return ..()
/obj/structure/destructible/clockwork/taunting_trail/Bumped(atom/movable/AM)
affect_mob(AM)
return ..()
/obj/structure/destructible/clockwork/taunting_trail/Bump(atom/movable/AM)
affect_mob(AM)
return ..()
/obj/structure/destructible/clockwork/taunting_trail/proc/affect_mob(mob/living/L)
if(istype(L) && !is_servant_of_ratvar(L))
if(!L.null_rod_check())
L.confused = min(L.confused + 15, 50)
L.dizziness = min(L.dizziness + 15, 50)
if(L.confused >= 25)
L.Weaken(Floor(L.confused * 0.04))
take_damage(max_integrity)
@@ -81,7 +81,8 @@
if(is_servant_of_ratvar(user))
if(linkedwall)
if(wall_generation_cooldown > world.time)
user << "<span class='alloy'>[src] will produce a component in <b>[(world.time - wall_generation_cooldown) * 0.1]</b> seconds.</span>"
var/temp_time = (wall_generation_cooldown - world.time) * 0.1
user << "<span class='alloy'>[src] will produce a component in <b>[temp_time]</b> second[temp_time == 1 ? "":"s"].</span>"
else
user << "<span class='brass'>[src] is about to produce a component!</span>"
else if(anchored)
@@ -28,6 +28,16 @@
clockwork_daemons--
return ..()
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/ratvar_act()
..()
if(nezbere_invoked)
production_time = 0
production_cooldown = initial(production_cooldown) * 0.5
if(!active)
toggle(0)
else
production_cooldown = initial(production_cooldown)
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
+1 -1
View File
@@ -33,7 +33,7 @@
user.say(html_decode(message))
else
user.whisper(html_decode(message))
var/my_message = "<span class='cultitalic'><b>[(ishuman(user) ? "Acolyte" : "Construct")] [user]:</b> [message]</span>"
var/my_message = "<span class='cultitalic'><b>[(ishuman(user) ? "Acolyte" : "Construct")] [findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]:</b> [message]</span>"
for(var/mob/M in mob_list)
if(iscultist(M))
M << my_message
@@ -164,6 +164,8 @@ var/list/blacklisted_pylon_turfs = typecacheof(list(
var/mob/living/simple_animal/M = L
if(M.health < M.maxHealth)
M.adjustHealth(-1)
if(ishuman(L) && L.blood_volume < BLOOD_VOLUME_NORMAL)
L.blood_volume += 1.0
CHECK_TICK
if(last_corrupt <= world.time)
var/list/validturfs = list()
+17 -20
View File
@@ -13,6 +13,14 @@ This file contains the arcane tome files.
throw_range = 5
w_class = WEIGHT_CLASS_SMALL
/obj/item/weapon/tome/New()
..()
if(!LAZYLEN(rune_types))
rune_types = list()
for(var/i_can_do_loops_now_thanks_remie in non_revealed_runes)
var/obj/effect/rune/R = i_can_do_loops_now_thanks_remie
rune_types[initial(R.cultist_name)] = R //Uses the cultist name for displaying purposes
/obj/item/weapon/tome/examine(mob/user)
..()
if(iscultist(user) || isobserver(user))
@@ -28,7 +36,7 @@ This file contains the arcane tome files.
return ..()
if(iscultist(M))
if(M.reagents && M.reagents.has_reagent("holywater")) //allows cultists to be rescued from the clutches of ordained religion
user << "<span class='cult'>You remove the taint from [M].</span>"
user << "<span class='cult'>You remove the taint from [M].</span>" // fucking ow
var/holy2unholy = M.reagents.get_reagent_amount("holywater")
M.reagents.del_reagent("holywater")
M.reagents.add_reagent("unholywater",holy2unholy)
@@ -108,7 +116,7 @@ This file contains the arcane tome files.
text += "<font color='red'><b>Talisman of Teleportation</b></font><br>The talisman form of the Teleport rune will transport the invoker to a selected Teleport rune once.<br><br>"
text += "<font color='red'><b>Talisman of Construction</b></font><br>This talisman is the main way of creating construct shells. To use it, one must strike 25 sheets of metal with the talisman. The sheets will then be twisted into a construct shell, ready to recieve a soul to occupy it.<br><br>"
text += "<font color='red'><b>Talisman of Construction</b></font><br>This talisman is the main way of creating construct shells. To use it, one must strike 25 sheets of metal with the talisman. The sheets will then be twisted into a construct shell, ready to receive a soul to occupy it.<br><br>"
text += "<font color='red'><b>Talisman of Tome Summoning</b></font><br>This talisman will produce a single tome at your feet.<br><br>"
@@ -167,33 +175,22 @@ This file contains the arcane tome files.
var/chosen_keyword
var/obj/effect/rune/rune_to_scribe
var/entered_rune_name
var/list/possible_runes = list()
var/list/shields = list()
var/area/A = get_area(src)
if(!check_rune_turf(Turf, user))
return
for(var/T in subtypesof(/obj/effect/rune) - /obj/effect/rune/malformed)
var/obj/effect/rune/R = T
if(initial(R.cultist_name))
possible_runes.Add(initial(R.cultist_name)) //This is to allow the menu to let cultists select runes by name rather than by object path. I don't know a better way to do this
if(!possible_runes.len)
return
entered_rune_name = input(user, "Choose a rite to scribe.", "Sigils of Power") as null|anything in possible_runes
entered_rune_name = input(user, "Choose a rite to scribe.", "Sigils of Power") as null|anything in rune_types
if(!src || QDELETED(src) || !Adjacent(user) || user.incapacitated() || !check_rune_turf(Turf, user))
return
for(var/T in typesof(/obj/effect/rune))
var/obj/effect/rune/R = T
if(initial(R.cultist_name) == entered_rune_name)
rune_to_scribe = R
if(initial(R.req_keyword))
var/the_keyword = stripped_input(usr, "Please enter a keyword for the rune.", "Enter Keyword", "")
if(!the_keyword)
return
chosen_keyword = the_keyword
break
rune_to_scribe = rune_types[entered_rune_name]
if(!rune_to_scribe)
return
if(initial(rune_to_scribe.req_keyword))
chosen_keyword = stripped_input(user, "Enter a keyword for the new rune.", "Words of Power")
if(!chosen_keyword)
scribe_rune(user) //Go back a menu!
return
Turf = get_turf(user) //we may have moved. adjust as needed...
A = get_area(src)
if(!src || QDELETED(src) || !Adjacent(user) || user.incapacitated() || !check_rune_turf(Turf, user))
+1
View File
@@ -1,5 +1,6 @@
/var/list/sacrificed = list() //a mixed list of minds and mobs
var/list/non_revealed_runes = (subtypesof(/obj/effect/rune) - /obj/effect/rune/malformed)
var/global/list/rune_types //Every rune that can be drawn by tomes
/*
+1 -1
View File
@@ -59,7 +59,7 @@ var/global/list/lawlorify = list (
BAN_CHAPEL = "You must never attempt to enter the chapel.",
BAN_HURTPRIEST = "You must never attack a priest.",
BAN_AVOIDWATER = "You must never willingly touch a wet surface.",
BAN_STRIKEUNCONCIOUS = "You must never strike an unconcious person.",
BAN_STRIKEUNCONCIOUS = "You must never strike an unconscious person.",
BAN_HURTLIZARD = "You must never harm a lizardman outside of self defense.",
BAN_HURTANIMAL = "You must never harm a non-sentient creature or robot outside of self defense.",
BANE_SILVER = "Silver, in all of its forms shall be your downfall.",
@@ -47,8 +47,9 @@
apply_overlay(DEVIL_HANDS_LAYER)
/mob/living/carbon/true_devil/remove_overlay(cache_index)
if(devil_overlays[cache_index])
overlays -= devil_overlays[cache_index]
var/I = devil_overlays[cache_index]
if(I)
cut_overlay(I)
devil_overlays[cache_index] = null
-1
View File
@@ -258,7 +258,6 @@
if(escaped_total > 0)
feedback_set("escaped_total",escaped_total)
send2irc("Server", "Round just ended.")
// send2maindiscord("Server", "Round just ended.")
return 0
@@ -354,9 +354,23 @@
explanation_text = "Steal all"
/datum/objective/abductee/steal/New()
var/target = pick(list("pets","lights","monkeys","fruits","shoes","bars of soap"))
var/target = pick(list("pets","lights","monkeys","fruits","shoes","bars of soap", "weapons", "computers", "organs"))
explanation_text+=" [target]."
/datum/objective/abductee/paint
explanation_text = "The station is hideous. You must color it all"
/datum/objective/abductee/paint/New()
var/color = pick(list("red", "blue", "green", "yellow", "orange", "purple", "black", "in rainbows", "in blood"))
explanation_text+= " [color]!"
/datum/objective/abductee/speech
explanation_text = "Your brain is broken... you can only communicate in"
/datum/objective/abductee/speech/New()
var/style = pick(list("pantomime", "rhyme", "haiku", "extended metaphors", "riddles", "extremely literal terms", "sound effects", "military jargon"))
explanation_text+= " [style]."
/datum/objective/abductee/capture
explanation_text = "Capture"
@@ -396,16 +410,16 @@
explanation_text = "Start a collection of corpses. Don't kill people to get these corpses."
/datum/objective/abductee/floors
explanation_text = "Replace all the floor tiles with carpeting, wooden boards, or grass."
explanation_text = "Replace all the floor tiles with wood, carpeting, grass or bling."
/datum/objective/abductee/POWERUNLIMITED
explanation_text = "Flood the station's powernet with as much electricity as you can."
/datum/objective/abductee/pristine
explanation_text = "Ensure the station is in absolutely pristine condition."
explanation_text = "The CEO of Nanotrasen is coming! Ensure the station is in absolutely pristine condition."
/datum/objective/abductee/window
explanation_text = "Replace all normal windows with reinforced windows."
/datum/objective/abductee/nowalls
explanation_text = "The crew must get to know one another better. Break down the walls inside the station!"
/datum/objective/abductee/nations
explanation_text = "Ensure your department prospers over all else."
@@ -413,17 +427,11 @@
/datum/objective/abductee/abductception
explanation_text = "You have been changed forever. Find the ones that did this to you and give them a taste of their own medicine."
/datum/objective/abductee/ghosts
explanation_text = "Conduct a seance with the spirits of the afterlife."
/datum/objective/abductee/summon
explanation_text = "Conduct a ritual to summon an elder god."
explanation_text = "The elder gods hunger. Gather a cult and conduct a ritual to summon one."
/datum/objective/abductee/machine
explanation_text = "You are secretly an android. Interface with as many machines as you can to boost your own power."
/datum/objective/abductee/prevent
explanation_text = "You have been enlightened. This knowledge must not escape. Ensure nobody else can become enlightened."
explanation_text = "You are secretly an android. Interface with as many machines as you can to boost your own power so the AI may acknowledge you at last."
/datum/objective/abductee/calling
explanation_text = "Call forth a spirit from the other side."
@@ -431,7 +439,7 @@
/datum/objective/abductee/calling/New()
var/mob/dead/D = pick(dead_mob_list)
if(D)
explanation_text = "You know that [D] has perished. Call them from the spirit realm."
explanation_text = "You know that [D] has perished. Hold a seance to call them from the spirit realm."
/datum/objective/abductee/social_experiment
explanation_text = "This is a secret social experiment conducted by Nanotrasen. Convince the crew that this is the truth."
@@ -443,7 +451,7 @@
explanation_text = "Nanotrasen is abusing the animals! Save as many as you can!"
/datum/objective/abductee/defect
explanation_text = "Defect from your employer."
explanation_text = "Fuck the system! Defect from the station and start an independent colony in space, Lavaland or the derelict. Recruit crewmates if you can."
/datum/objective/abductee/promote
explanation_text = "Climb the corporate ladder all the way to the top!"
@@ -458,17 +466,31 @@
explanation_text = "You are pregnant and soon due. Find a safe place to deliver your baby."
/datum/objective/abductee/engine
explanation_text = "Go have a good conversation with the Singularity/Tesla/Supermatter crystal. Bonus points if it responds."
/datum/objective/abductee/teamredisbetterthangreen
explanation_text = "Tell the AI (or a borg/pAI/drone if there is no AI) some corny technology jokes until it cries for help."
/datum/objective/abductee/time
explanation_text = "Go bug a bronze worshipper to give you a clock."
/datum/objective/abductee/licky
explanation_text = "You must lick anything that you find interesting."
explanation_text = "Go have a good conversation with the singularity/tesla/supermatter crystal. Bonus points if it responds."
/datum/objective/abductee/music
explanation_text = "Start playing music, you're the best musician ever. If anyone hates it, beat them on the head with your instrument!"
explanation_text = "You burn with passion for music. Share your vision. If anyone hates it, beat them on the head with your instrument!"
/datum/objective/abductee/clown
explanation_text = "The clown is not funny. You can do better! Steal his audience and make the crew laugh!"
/datum/objective/abductee/party
explanation_text = "You're throwing a huge rager. Make it as awesome as possible so the whole crew comes... OR ELSE!"
/datum/objective/abductee/pets
explanation_text = "All the pets around here suck. You need to make them cooler. Replace them with exotic beasts!"
/datum/objective/abductee/conspiracy
explanation_text = "The leaders of this station are hiding a grand, evil conspiracy. Only you can learn what it is, and expose it to the people!"
/datum/objective/abductee/stalker
explanation_text = "The Syndicate has hired you to compile dossiers on all important members of the crew. Be sure they don't know you're doing it."
/datum/objective/abductee/narrator
explanation_text = "You're the narrator of this tale. Follow around the protagonists to tell their story."
/datum/objective/abductee/lurve
explanation_text = "You are doomed to feel woefully incomplete forever... until you find your true love on this station. They're waiting for you!"
/datum/objective/abductee/sixthsense
explanation_text = "You died back there and went to heaven... or is it hell? No one here seems to know they're dead. Convince them, and maybe you can escape this limbo."
@@ -56,7 +56,7 @@
M.name_override = disguise.name
M.icon = disguise.icon
M.icon_state = disguise.icon_state
M.overlays = disguise.overlays
M.copy_overlays(disguise, TRUE)
M.update_inv_hands()
/obj/item/clothing/suit/armor/abductor/vest/proc/DeactivateStealth()
@@ -269,18 +269,20 @@
<br>
1.Acquire fresh specimen.<br>
2.Put the specimen on operating table<br>
3.Apply surgical drapes preparing for dissection<br>
4.Apply scalpel to specimen torso<br>
5.Retract skin from specimen's torso<br>
6.Apply scalpel to specimen's torso<br>
7.Search through the specimen's torso with your hands to remove any organs<br>
8.Insert replacement gland (Retrieve one from gland storage)<br>
9.Consider dressing the specimen back to not disturb the habitat <br>
10.Put the specimen in the experiment machinery<br>
11.Choose one of the machine options and follow displayed instructions<br>
2.Put the specimen on operating table.<br>
3.Apply surgical drapes, preparing for experimental dissection.<br>
4.Apply scalpel to specimen's torso.<br>
5.Clamp bleeders on specimen's torso with a hemostat.<br>
6.Retract skin of specimen's torso with a retractor.<br>
7.Apply scalpel again to specimen's torso.<br>
8.Search through the specimen's torso with your hands to remove any superfluous organs.<br>
9.Insert replacement gland (Retrieve one from gland storage).<br>
10.Consider dressing the specimen back to not disturb the habitat. <br>
11.Put the specimen in the experiment machinery.<br>
12.Choose one of the machine options. The target will be analyzed and teleported to the selected drop-off point.<br>
13.You will receive one supply credit, and the subject will be counted towards your quota.<br>
<br>
Congratulations! You are now trained for xenobiology research!"}
Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/weapon/paper/abductor/update_icon()
return
@@ -435,7 +437,7 @@ Congratulations! You are now trained for xenobiology research!"}
species = "<span clas=='notice'>[H.dna.species.name]</span>"
if(L.mind && L.mind.changeling)
species = "<span class='warning'>Changeling lifeform</span>"
var/obj/item/organ/gland/temp = locate() in H.internal_organs
var/obj/item/organ/heart/gland/temp = locate() in H.internal_organs
if(temp)
helptext = "<span class='warning'>Experimental gland detected!</span>"
else
@@ -531,15 +533,6 @@ Congratulations! You are now trained for xenobiology research!"}
// Operating Table / Beds / Lockers
/obj/structure/table/optable/abductor
icon = 'icons/obj/abductor.dmi'
icon_state = "bed"
can_buckle = 1
buckle_lying = 1
flags = NODECONSTRUCT
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
/obj/structure/bed/abductor
name = "resting contraption"
desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?"
@@ -576,6 +569,17 @@ Congratulations! You are now trained for xenobiology research!"}
new /obj/structure/table/abductor(src.loc)
qdel(src)
return
if(istype(I, /obj/item/stack/sheet/mineral/silver))
var/obj/item/stack/sheet/P = I
if(P.get_amount() < 1)
user << "<span class='warning'>You need one sheet of silver to do \
this!</span>"
return
user << "<span class='notice'>You start adding [P] to [src]...</span>"
if(do_after(user, 50, target = src))
P.use(1)
new /obj/structure/table/optable/abductor(src.loc)
qdel(src)
/obj/structure/table/abductor
name = "alien table"
@@ -589,6 +593,38 @@ Congratulations! You are now trained for xenobiology research!"}
canSmoothWith = null
frame = /obj/structure/table_frame/abductor
/obj/structure/table/optable/abductor
name = "alien operating table"
desc = "Used for alien medical procedures. The surface is covered in tiny spines."
frame = /obj/structure/table_frame/abductor
buildstack = /obj/item/stack/sheet/mineral/silver
framestack = /obj/item/stack/sheet/mineral/abductor
buildstackamount = 1
framestackamount = 1
icon = 'icons/obj/abductor.dmi'
icon_state = "bed"
can_buckle = 1
buckle_lying = 1
var/static/list/injected_reagents = list("corazone")
/obj/structure/table/optable/abductor/Crossed(atom/movable/AM)
. = ..()
if(iscarbon(AM))
START_PROCESSING(SSobj, src)
AM << "<span class='danger'>You feel a series of tiny pricks!</span>"
/obj/structure/table/optable/abductor/process()
. = PROCESS_KILL
for(var/mob/living/carbon/C in get_turf(src))
. = TRUE
for(var/chemical in injected_reagents)
if(C.reagents.get_reagent_amount(chemical) < 1)
C.reagents.add_reagent(chemical, 1)
/obj/structure/table/optable/abductor/Destroy()
STOP_PROCESSING(SSobj, src)
. = ..()
/obj/structure/closet/abductor
name = "alien locker"
@@ -33,15 +33,15 @@
if(IC)
user.visible_message("[user] pulls [IC] out of [target]'s [target_zone]!", "<span class='notice'>You pull [IC] out of [target]'s [target_zone].</span>")
user.put_in_hands(IC)
IC.Remove(target, special = 1)
IC.Remove(target)
return 1
else
user << "<span class='warning'>You don't find anything in [target]'s [target_zone]!</span>"
return 0
return 1
/datum/surgery_step/gland_insert
name = "insert gland"
implements = list(/obj/item/organ/gland = 100)
implements = list(/obj/item/organ/heart/gland = 100)
time = 32
/datum/surgery_step/gland_insert/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
@@ -50,6 +50,6 @@
/datum/surgery_step/gland_insert/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
user.visible_message("[user] inserts [tool] into [target].", "<span class ='notice'>You insert [tool] into [target].</span>")
user.drop_item()
var/obj/item/organ/gland/gland = tool
var/obj/item/organ/heart/gland/gland = tool
gland.Insert(target, 2)
return 1
return 1
@@ -1,12 +1,11 @@
/obj/item/organ/gland
/obj/item/organ/heart/gland
name = "fleshy mass"
desc = "A nausea-inducing hunk of twisting flesh and metal."
icon = 'icons/obj/abductor.dmi'
zone = "chest"
slot = "gland"
icon_state = "gland"
status = ORGAN_ROBOTIC
origin_tech = "materials=4;biotech=7;abductor=3"
beating = TRUE
var/cooldown_low = 300
var/cooldown_high = 300
var/next_activation = 0
@@ -14,30 +13,33 @@
var/human_only = 0
var/active = 0
/obj/item/organ/gland/proc/ownerCheck()
/obj/item/organ/heart/gland/proc/ownerCheck()
if(ishuman(owner))
return 1
if(!human_only && iscarbon(owner))
return 1
return 0
/obj/item/organ/gland/proc/Start()
/obj/item/organ/heart/gland/proc/Start()
active = 1
next_activation = world.time + rand(cooldown_low,cooldown_high)
/obj/item/organ/gland/Remove(var/mob/living/carbon/M, special = 0)
/obj/item/organ/heart/gland/Remove(var/mob/living/carbon/M, special = 0)
active = 0
if(initial(uses) == 1)
uses = initial(uses)
..()
/obj/item/organ/gland/Insert(var/mob/living/carbon/M, special = 0)
/obj/item/organ/heart/gland/Insert(var/mob/living/carbon/M, special = 0)
..()
if(special != 2 && uses) // Special 2 means abductor surgery
Start()
/obj/item/organ/gland/on_life()
/obj/item/organ/heart/gland/on_life()
if(!beating)
// alien glands are immune to stopping.
beating = TRUE
if(!active)
return
if(!ownerCheck())
@@ -50,28 +52,28 @@
if(!uses)
active = 0
/obj/item/organ/gland/proc/activate()
/obj/item/organ/heart/gland/proc/activate()
return
/obj/item/organ/gland/heals
/obj/item/organ/heart/gland/heals
cooldown_low = 200
cooldown_high = 400
uses = -1
icon_state = "health"
/obj/item/organ/gland/heals/activate()
/obj/item/organ/heart/gland/heals/activate()
owner << "<span class='notice'>You feel curiously revitalized.</span>"
owner.adjustBruteLoss(-20)
owner.adjustOxyLoss(-20)
owner.adjustFireLoss(-20)
/obj/item/organ/gland/slime
/obj/item/organ/heart/gland/slime
cooldown_low = 600
cooldown_high = 1200
uses = -1
icon_state = "slime"
/obj/item/organ/gland/slime/activate()
/obj/item/organ/heart/gland/slime/activate()
owner << "<span class='warning'>You feel nauseous!</span>"
owner.vomit(20)
@@ -80,14 +82,14 @@
Slime.Friends = list(owner)
Slime.Leader = owner
/obj/item/organ/gland/mindshock
/obj/item/organ/heart/gland/mindshock
origin_tech = "materials=4;biotech=4;magnets=6;abductor=3"
cooldown_low = 300
cooldown_high = 300
uses = -1
icon_state = "mindshock"
/obj/item/organ/gland/mindshock/activate()
/obj/item/organ/heart/gland/mindshock/activate()
owner << "<span class='notice'>You get a headache.</span>"
var/turf/T = get_turf(owner)
@@ -97,38 +99,37 @@
H << "<span class='alien'>You hear a buzz in your head.</span>"
H.confused += 20
/obj/item/organ/gland/pop
/obj/item/organ/heart/gland/pop
cooldown_low = 900
cooldown_high = 1800
uses = -1
human_only = 1
icon_state = "species"
/obj/item/organ/gland/pop/activate()
/obj/item/organ/heart/gland/pop/activate()
owner << "<span class='notice'>You feel unlike yourself.</span>"
var/species = pick(list(/datum/species/lizard,/datum/species/jelly/slime,/datum/species/pod,/datum/species/fly,/datum/species/jelly))
owner.set_species(species)
/obj/item/organ/gland/ventcrawling
/obj/item/organ/heart/gland/ventcrawling
origin_tech = "materials=4;biotech=5;bluespace=4;abductor=3"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
icon_state = "vent"
/obj/item/organ/gland/ventcrawling/activate()
/obj/item/organ/heart/gland/ventcrawling/activate()
owner << "<span class='notice'>You feel very stretchy.</span>"
owner.ventcrawler = VENTCRAWLER_ALWAYS
return
/obj/item/organ/gland/viral
/obj/item/organ/heart/gland/viral
cooldown_low = 1800
cooldown_high = 2400
uses = 1
icon_state = "viral"
/obj/item/organ/gland/viral/activate()
/obj/item/organ/heart/gland/viral/activate()
owner << "<span class='warning'>You feel sick.</span>"
var/virus_type = pick(/datum/disease/beesease, /datum/disease/brainrot, /datum/disease/magnitis)
var/datum/disease/D = new virus_type()
@@ -139,48 +140,47 @@
owner.med_hud_set_status()
/obj/item/organ/gland/emp //TODO : Replace with something more interesting
/obj/item/organ/heart/gland/emp //TODO : Replace with something more interesting
origin_tech = "materials=4;biotech=4;magnets=6;abductor=3"
cooldown_low = 900
cooldown_high = 1600
uses = 10
icon_state = "emp"
/obj/item/organ/gland/emp/activate()
/obj/item/organ/heart/gland/emp/activate()
owner << "<span class='warning'>You feel a spike of pain in your head.</span>"
empulse(get_turf(owner), 2, 5, 1)
/obj/item/organ/gland/spiderman
/obj/item/organ/heart/gland/spiderman
cooldown_low = 450
cooldown_high = 900
uses = 10
icon_state = "spider"
/obj/item/organ/gland/spiderman/activate()
/obj/item/organ/heart/gland/spiderman/activate()
owner << "<span class='warning'>You feel something crawling in your skin.</span>"
owner.faction |= "spiders"
new /obj/structure/spider/spiderling(owner.loc)
/obj/item/organ/gland/egg
/obj/item/organ/heart/gland/egg
cooldown_low = 300
cooldown_high = 400
uses = -1
icon_state = "egg"
/obj/item/organ/gland/egg/activate()
/obj/item/organ/heart/gland/egg/activate()
owner << "<span class='boldannounce'>You lay an egg!</span>"
var/obj/item/weapon/reagent_containers/food/snacks/egg/egg = new(owner.loc)
egg.reagents.add_reagent("sacid",20)
egg.desc += " It smells bad."
/obj/item/organ/gland/bloody
/obj/item/organ/heart/gland/bloody
cooldown_low = 200
cooldown_high = 400
uses = -1
/obj/item/organ/gland/bloody/activate()
owner.adjustBruteLoss(15)
/obj/item/organ/heart/gland/bloody/activate()
owner.blood_volume -= 20
owner.visible_message("<span class='danger'>[owner]'s skin erupts with blood!</span>",\
"<span class='userdanger'>Blood pours from your skin!</span>")
@@ -189,21 +189,22 @@
for(var/mob/living/carbon/human/H in oview(3,owner)) //Blood decals for simple animals would be neat. aka Carp with blood on it.
H.add_mob_blood(owner)
/obj/item/organ/gland/bodysnatch
/obj/item/organ/heart/gland/bodysnatch
cooldown_low = 600
cooldown_high = 600
human_only = 1
uses = 1
/obj/item/organ/gland/bodysnatch/activate()
/obj/item/organ/heart/gland/bodysnatch/activate()
owner << "<span class='warning'>You feel something moving around inside you...</span>"
//spawn cocoon with clone greytide snpc inside
if(ishuman(owner))
var/obj/structure/spider/cocoon/abductor/C = new (get_turf(owner))
C.Copy(owner)
C.Start()
owner.gib()
return
owner.adjustBruteLoss(40)
owner.add_splatter_floor()
/obj/structure/spider/cocoon/abductor
name = "slimy cocoon"
@@ -218,16 +219,6 @@
var/mob/living/carbon/human/interactive/greytide/clone = new(src)
clone.hardset_dna(H.dna.uni_identity,H.dna.struc_enzymes,H.real_name, H.dna.blood_type, H.dna.species.type, H.dna.features)
//There's no define for this / get all items ?
var/list/slots = list(slot_back,slot_w_uniform,slot_wear_suit,\
slot_wear_mask,slot_head,slot_shoes,slot_gloves,slot_ears,\
slot_glasses,slot_belt,slot_s_store,slot_l_store,slot_r_store,slot_wear_id)
for(var/slot in slots)
var/obj/item/I = H.get_item_by_slot(slot)
if(I)
clone.equip_to_slot_if_possible(I,slot)
/obj/structure/spider/cocoon/abductor/proc/Start()
hatch_time = world.time + 600
START_PROCESSING(SSobj, src)
@@ -240,13 +231,14 @@
M.loc = src.loc
qdel(src)
/obj/item/organ/gland/plasma
/obj/item/organ/heart/gland/plasma
cooldown_low = 1200
cooldown_high = 1800
origin_tech = "materials=4;biotech=4;plasmatech=6;abductor=3"
uses = -1
/obj/item/organ/gland/plasma/activate()
/obj/item/organ/heart/gland/plasma/activate()
owner << "<span class='warning'>You feel bloated.</span>"
sleep(150)
if(!owner) return
@@ -258,4 +250,3 @@
if(istype(T))
T.atmos_spawn_air("plasma=50;TEMP=[T20C]")
owner.vomit()
return
@@ -176,7 +176,7 @@
entry.name = target.name
entry.icon = target.icon
entry.icon_state = target.icon_state
entry.overlays = target.get_overlays_copy(list(HANDS_LAYER))
entry.overlays = target.get_overlays_copy(list(HANDS_LAYER)) //ugh
for(var/i=1,i<=disguises.len,i++)
var/datum/icon_snapshot/temp = disguises[i]
if(temp.name == entry.name)
@@ -15,7 +15,7 @@
/obj/machinery/abductor/gland_dispenser/New()
..()
gland_types = subtypesof(/obj/item/organ/gland)
gland_types = subtypesof(/obj/item/organ/heart/gland)
gland_types = shuffle(gland_types)
gland_colors = new/list(gland_types.len)
amounts = new/list(gland_types.len)
@@ -60,7 +60,7 @@
return
/obj/machinery/abductor/gland_dispenser/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/organ/gland))
if(istype(W, /obj/item/organ/heart/gland))
if(!user.drop_item())
return
W.loc = src
@@ -160,7 +160,7 @@
if(H.stat == DEAD)
say("Specimen deceased - please provide fresh sample.")
return "<span class='bad'>Specimen deceased.</span>"
var/obj/item/organ/gland/GlandTest = locate() in H.internal_organs
var/obj/item/organ/heart/gland/GlandTest = locate() in H.internal_organs
if(!GlandTest)
say("Experimental dissection not detected!")
return "<span class='bad'>No glands detected!</span>"
@@ -185,7 +185,7 @@
H.mind.announce_objectives()
ticker.mode.update_abductor_icons_added(H.mind)
for(var/obj/item/organ/gland/G in H.internal_organs)
for(var/obj/item/organ/heart/gland/G in H.internal_organs)
G.Start()
point_reward++
if(point_reward > 0)
@@ -88,7 +88,7 @@
attacktext = "shocks"
attack_sound = 'sound/effects/EMPulse.ogg'
friendly = "pinches"
speed = 1
speed = 0
faction = list("swarmer")
AIStatus = AI_OFF
pass_flags = PASSTABLE
+2 -2
View File
@@ -196,7 +196,7 @@ var/bomb_set
update_icon_lights()
/obj/machinery/nuclearbomb/proc/update_icon_interior()
overlays -= interior
cut_overlay(interior)
switch(deconstruction_state)
if(NUKESTATE_UNSCREWED)
interior = image(icon,"panel-unscrewed")
@@ -213,7 +213,7 @@ var/bomb_set
add_overlay(interior)
/obj/machinery/nuclearbomb/proc/update_icon_lights()
overlays -= lights
cut_overlay(lights)
switch(get_nuke_state())
if(NUKE_OFF_LOCKED)
lights = null
+2 -3
View File
@@ -107,10 +107,10 @@
/datum/objective/mutiny/check_completion()
if(target && target.current)
if(target.current.stat == DEAD || !ishuman(target.current) || !target.current.ckey || !target.current.client)
if(target.current.stat == DEAD || !ishuman(target.current) || !target.current.ckey)
return 1
var/turf/T = get_turf(target.current)
if(T && (T.z > ZLEVEL_STATION) || target.current.client.is_afk()) //If they leave the station or go afk they count as dead for this
if(T && (T.z > ZLEVEL_STATION) || (target.current.client && target.current.client.is_afk())) //If they leave the station or go afk they count as dead for this
return 2
return 0
return 1
@@ -342,7 +342,6 @@
/datum/objective/escape
explanation_text = "Escape on the shuttle or an escape pod alive and without being in custody."
dangerrating = 5
martyr_compatible = 0
/datum/objective/escape/check_completion()
if(issilicon(owner.current))

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