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:
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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])"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ..()
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
. = ..()
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,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
|
||||
|
||||
/*
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user