Merge branch 'master' into upstream-merge-28046

This commit is contained in:
LetterJay
2017-06-14 13:10:37 -05:00
committed by GitHub
382 changed files with 304519 additions and 166836 deletions
+3 -3
View File
@@ -58,7 +58,7 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
//clockcult power defines
#define MIN_CLOCKCULT_POWER 25 //the minimum amount of power clockcult machines will handle gracefully
#define CLOCKCULT_POWER_UNIT (MIN_CLOCKCULT_POWER*100) //standard power amount for clockwork proselytizer costs
#define CLOCKCULT_POWER_UNIT (MIN_CLOCKCULT_POWER*100) //standard power amount for replica fabricator costs
#define POWER_STANDARD (CLOCKCULT_POWER_UNIT*0.2) //how much power is in anything else; doesn't matter as much as the following
@@ -76,7 +76,7 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#define POWER_PLASTEEL (CLOCKCULT_POWER_UNIT*0.05) //how much power is in one sheet of plasteel
#define RATVAR_POWER_CHECK "ratvar?" //when passed into can_use_power(), converts it into a check for if ratvar has woken/the proselytizer is debug
#define RATVAR_POWER_CHECK "ratvar?" //when passed into can_use_power(), converts it into a check for if ratvar has woken/the fabricator is debug
//Ark defines
#define GATEWAY_SUMMON_RATE 1 //the time amount the Gateway to the Celestial Derelict gets each process tick; defaults to 1 per tick
@@ -99,7 +99,7 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
#define SIGIL_ACCESS_RANGE 2 //range at which transmission sigils can access power
#define PROSELYTIZER_REPAIR_PER_TICK 4 //how much a proselytizer repairs each tick, and also how many deciseconds each tick is
#define FABRICATOR_REPAIR_PER_TICK 4 //how much a fabricator 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
+7 -1
View File
@@ -429,4 +429,10 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define GIBTONITE_UNSTRUCK 0
#define GIBTONITE_ACTIVE 1
#define GIBTONITE_STABLE 2
#define GIBTONITE_DETONATE 3
#define GIBTONITE_DETONATE 3
//for obj explosion block calculation
#define EXPLOSION_BLOCK_PROC -1
//Gangster starting influences
#define GANGSTER_SOLDIER_STARTING_INFLUENCE 5
#define GANGSTER_BOSS_STARTING_INFLUENCE 20
+1
View File
@@ -11,6 +11,7 @@
#define SERVICE_CMD_HARD_REBOOT "hard_reboot"
#define SERVICE_CMD_GRACEFUL_SHUTDOWN "graceful_shutdown"
#define SERVICE_CMD_WORLD_ANNOUNCE "world_announce"
#define SERVICE_CMD_IRC_CHECK "irc_check"
#define SERVICE_CMD_IRC_STATUS "irc_status"
#define SERVICE_CMD_ADMIN_MSG "adminmsg"
#define SERVICE_CMD_NAME_CHECK "namecheck"
+11 -1
View File
@@ -30,7 +30,6 @@
// DEBUFFS //
/////////////
#define STATUS_EFFECT_SIGILMARK /datum/status_effect/sigil_mark
#define STATUS_EFFECT_BELLIGERENT /datum/status_effect/belligerent //forces the affected to walk, doing damage if they try to run
#define STATUS_EFFECT_MANIAMOTOR /datum/status_effect/maniamotor //disrupts, damages, and confuses the affected as long as they're in range of the motor
@@ -41,3 +40,14 @@
#define STATUS_EFFECT_SUMMONEDGHOST /datum/status_effect/cultghost //is a cult ghost and can't use manifest runes
#define STATUS_EFFECT_CRUSHERMARK /datum/status_effect/crusher_mark //if struck with a proto-kinetic crusher, takes a ton of damage
/////////////
// NEUTRAL //
/////////////
#define STATUS_EFFECT_SIGILMARK /datum/status_effect/sigil_mark
#define STATUS_EFFECT_CRUSHERDAMAGETRACKING /datum/status_effect/crusher_damage //tracks total kinetic crusher damage on a target
#define STATUS_EFFECT_SYPHONMARK /datum/status_effect/syphon_mark //tracks kills for the KA death syphon module
+1 -2
View File
@@ -451,13 +451,12 @@
//Picks from the list, with some safeties, and returns the "default" arg if it fails
#define DEFAULTPICK(L, default) ((istype(L, /list) && L:len) ? pick(L) : default)
#define LAZYINITLIST(L) if (!L) L = list()
#define UNSETEMPTY(L) if (L && !L.len) L = null
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!L.len) { L = null; } }
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null)
#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V;
#define LAZYLEN(L) length(L)
#define LAZYCLEARLIST(L) if(L) L.Cut()
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
+8 -4
View File
@@ -3,7 +3,7 @@
for(var/file in args)
src << browse_rsc(file)
/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list(".txt",".log",".htm"))
/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list("txt","log","htm", "html"))
var/path = root
for(var/i=0, i<max_iterations, i++)
@@ -22,9 +22,13 @@
if(copytext(path,-1,0) != "/") //didn't choose a directory, no need to iterate again
break
var/extension = copytext(path,-4,0)
if( !fexists(path) || !(extension in valid_extensions) )
var/extensions
for(var/i in valid_extensions)
if(extensions)
extensions += "|"
extensions += "[i]"
var/regex/valid_ext = new("\\.([extensions])$", "i")
if( !fexists(path) || !(valid_ext.Find(path)) )
to_chat(src, "<font color='red'>Error: browse_files(): File not found/Invalid file([path]).</font>")
return
+2 -1
View File
@@ -14,4 +14,5 @@ GLOBAL_VAR_INIT(cult_vote_called, FALSE)
GLOBAL_VAR_INIT(cult_mastered, FALSE)
GLOBAL_VAR_INIT(reckoning_complete, FALSE)
GLOBAL_VAR_INIT(sac_complete, FALSE)
GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
GLOBAL_LIST_EMPTY(summon_spots)
+2 -2
View File
@@ -43,11 +43,11 @@ GLOBAL_LIST_INIT(security_depts_prefs, list(SEC_DEPT_RANDOM, SEC_DEPT_NONE, SEC_
//Backpacks
#define GBACKPACK "Grey Backpack"
#define GSATCHEL "Grey Satchel"
#define GDUFFLEBAG "Grey Dufflebag"
#define GDUFFLEBAG "Grey Dufflebag"
#define LSATCHEL "Leather Satchel"
#define DBACKPACK "Department Backpack"
#define DSATCHEL "Department Satchel"
#define DDUFFLEBAG "Department Dufflebag"
#define DDUFFLEBAG "Department Dufflebag"
GLOBAL_LIST_INIT(backbaglist, list(DBACKPACK, DSATCHEL, DDUFFLEBAG, GBACKPACK, GSATCHEL, GDUFFLEBAG, LSATCHEL))
//Uplink spawn loc
+1
View File
@@ -0,0 +1 @@
GLOBAL_LIST_EMPTY(commendations)
+1 -1
View File
@@ -13,4 +13,4 @@ GLOBAL_REAL_VAR(sqlport) = "3306"
GLOBAL_REAL_VAR(sqlfdbkdb) = "test"
GLOBAL_REAL_VAR(sqlfdbklogin) = "root"
GLOBAL_REAL_VAR(sqlfdbkpass) = ""
GLOBAL_REAL_VAR(sqlfdbktableprefix) = "erro_"
GLOBAL_REAL_VAR(sqlfdbktableprefix) = ""
+48 -1
View File
@@ -1,5 +1,10 @@
/client
var/list/atom/selected_target[2]
var/obj/item/active_mousedown_item = null
var/mouseParams = ""
var/mouseLocation = null
var/mouseObject = null
var/mouseControlObject = null
/client/MouseDown(object, location, control, params)
var/delay = mob.CanMobAutoclick(object, location, params)
@@ -9,14 +14,26 @@
while(selected_target[1])
Click(selected_target[1], location, control, selected_target[2])
sleep(delay)
active_mousedown_item = mob.canMobMousedown(object, location, params)
if(active_mousedown_item)
active_mousedown_item.onMouseDown(object, location, params, mob)
/client/MouseUp(object, location, control, params)
selected_target[1] = null
if(active_mousedown_item)
active_mousedown_item.onMouseUp(object, location, params, mob)
active_mousedown_item = null
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
mouseParams = params
mouseLocation = over_location
mouseObject = over_object
mouseControlObject = over_control
if(selected_target[1] && over_object && over_object.IsAutoclickable())
selected_target[1] = over_object
selected_target[2] = params
if(active_mousedown_item)
active_mousedown_item.onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
/mob/proc/CanMobAutoclick(object, location, params)
@@ -27,8 +44,31 @@
if(h)
. = h.CanItemAutoclick(object, location, params)
/mob/proc/canMobMousedown(object, location, params)
/mob/living/carbon/canMobMousedown(atom/object, location, params)
var/obj/item/H = get_active_held_item()
if(H)
. = H.canItemMouseDown(object, location, params)
/obj/item/proc/CanItemAutoclick(object, location, params)
/obj/item/proc/canItemMouseDown(object, location, params)
if(canMouseDown)
return src
/obj/item/proc/onMouseDown(object, location, params, mob)
return
/obj/item/proc/onMouseUp(object, location, params, mob)
return
/obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
return
/obj/item
var/canMouseDown = FALSE
/obj/item/weapon/gun
var/automatic = 0 //can gun use it, 0 is no, anything above 0 is the delay between clicks in ds
@@ -42,4 +82,11 @@
. = 0
/obj/screen/click_catcher/IsAutoclickable()
. = 1
. = 1
//Please don't roast me too hard
/client/MouseMove(object,location,control,params)
mouseParams = params
mouseLocation = location
mouseObject = object
mouseControlObject = control
+8 -10
View File
@@ -306,7 +306,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
angle = 0
cut_overlays()
icon_state = "runed_sense1"
desc = "The sacrifice is complete, bring the wrath of Nar-Sie upon the crew!"
desc = "The sacrifice is complete, summon Nar-Sie! The summoning can only take place in [english_list(GLOB.summon_spots)]!"
add_overlay(narnar)
return
var/turf/P = get_turf(blood_target)
@@ -361,7 +361,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
name = "Next Tier Requirements"
desc = "You shouldn't be seeing this description unless you're very fast. If you're very fast, good job!"
icon_state = "no-servants-caches"
var/static/list/scripture_states = list(SCRIPTURE_DRIVER = TRUE, SCRIPTURE_SCRIPT = FALSE, SCRIPTURE_APPLICATION = FALSE, SCRIPTURE_REVENANT = FALSE, SCRIPTURE_JUDGEMENT = FALSE)
/obj/screen/alert/clockwork/scripture_reqs/Initialize()
. = ..()
@@ -374,12 +374,11 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
/obj/screen/alert/clockwork/scripture_reqs/process()
if(GLOB.clockwork_gateway_activated)
qdel(src)
mob_viewer.clear_alert("scripturereq")
return
var/current_state
scripture_states = scripture_unlock_check()
for(var/i in scripture_states)
if(!scripture_states[i])
for(var/i in SSticker.scripture_states)
if(!SSticker.scripture_states[i])
current_state = i
break
icon_state = "no"
@@ -459,7 +458,6 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
var/servants = 0
var/validservants = 0
var/unconverted_ais_exist = get_unconverted_ais()
var/list/scripture_states = scripture_unlock_check()
var/list/textlist
for(var/mob/living/L in GLOB.living_mob_list)
if(is_servant_of_ratvar(L))
@@ -496,7 +494,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
textlist += "<b>[unconverted_ais_exist] unconverted AIs exist!</b><br>"
else
textlist += "<b>An unconverted AI exists!</b><br>"
if(scripture_states[SCRIPTURE_REVENANT])
if(SSticker.scripture_states[SCRIPTURE_REVENANT])
var/inathneq_available = GLOB.clockwork_generals_invoked["inath-neq"] <= world.time
var/sevtug_available = GLOB.clockwork_generals_invoked["sevtug"] <= world.time
var/nezbere_available = GLOB.clockwork_generals_invoked["nezbere"] <= world.time
@@ -508,9 +506,9 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
textlist += "Generals available: <b>NONE</b><br>"
else
textlist += "Generals available: <b>NONE</b><br>"
for(var/i in scripture_states)
for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff
textlist += "[i] Scripture: <b>[scripture_states[i] ? "UNLOCKED":"LOCKED"]</b><br>"
textlist += "[i] Scripture: <b>[SSticker.scripture_states[i] ? "UNLOCKED":"LOCKED"]</b><br>"
desc = textlist.Join()
..()
Regular → Executable
+6
View File
@@ -21,6 +21,7 @@
C.parallax_layers_cached = list()
C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_1(null, C.view)
C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_2(null, C.view)
C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_3(null, C.view)
C.parallax_layers = C.parallax_layers_cached.Copy()
@@ -278,6 +279,11 @@
speed = 1
layer = 2
/obj/screen/parallax_layer/layer_3
icon_state = "layer3"
speed = 1.4
layer = 3
#undef LOOP_NONE
#undef LOOP_NORMAL
#undef LOOP_REVERSE
+1
View File
@@ -19,6 +19,7 @@
/obj/screen/plane_master/game_world
name = "game world plane master"
plane = GAME_PLANE
appearance_flags = PLANE_MASTER //should use client color
blend_mode = BLEND_OVERLAY
/obj/screen/plane_master/lighting
+1 -1
View File
@@ -7,7 +7,7 @@
#define SSAIR_SUPERCONDUCTIVITY 7
SUBSYSTEM_DEF(air)
name = "Air"
name = "Atmospherics"
init_order = INIT_ORDER_AIR
priority = 20
wait = 5
+4 -4
View File
@@ -27,7 +27,7 @@ SUBSYSTEM_DEF(blackbox)
if(M.client)
playercount += 1
var/admincount = GLOB.admins.len
var/datum/DBQuery/query_record_playercount = SSdbcore.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port) VALUES ([playercount], [admincount], '[SQLtime()]', COALESCE(INET_ATON('[world.internet_address]'), 0), '[world.port]')")
var/datum/DBQuery/query_record_playercount = SSdbcore.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port) VALUES ([playercount], [admincount], '[SQLtime()]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]')")
query_record_playercount.Execute()
/datum/controller/subsystem/blackbox/Recover()
@@ -171,12 +171,12 @@ SUBSYSTEM_DEF(blackbox)
var/sqlfire = sanitizeSQL(L.getFireLoss())
var/sqlbrain = sanitizeSQL(L.getBrainLoss())
var/sqloxy = sanitizeSQL(L.getOxyLoss())
var/sqltox = sanitizeSQL(L.getStaminaLoss())
var/sqlclone = sanitizeSQL(L.getStaminaLoss())
var/sqltox = sanitizeSQL(L.getToxLoss())
var/sqlclone = sanitizeSQL(L.getCloneLoss())
var/sqlstamina = sanitizeSQL(L.getStaminaLoss())
var/coord = sanitizeSQL("[L.x], [L.y], [L.z]")
var/map = sanitizeSQL(SSmapping.config.map_name)
var/datum/DBQuery/query_report_death = SSdbcore.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss, coord, mapname, server_ip, server_port) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[SQLtime()]', '[laname]', '[lakey]', '[sqlgender]', [sqlbrute], [sqlfire], [sqlbrain], [sqloxy], [sqltox], [sqlclone], [sqlstamina], '[coord]', '[map]', COALESCE(INET_ATON('[world.internet_address]'), 0), '[world.port]')")
var/datum/DBQuery/query_report_death = SSdbcore.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss, coord, mapname, server_ip, server_port) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[SQLtime()]', '[laname]', '[lakey]', '[sqlgender]', [sqlbrute], [sqlfire], [sqlbrain], [sqloxy], [sqltox], [sqlclone], [sqlstamina], '[coord]', '[map]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]')")
query_report_death.Execute()
+1 -1
View File
@@ -33,7 +33,7 @@ SUBSYSTEM_DEF(dbcore)
//This is as close as we can get to the true round end before Disconnect() without changing where it's called, defeating the reason this is a subsystem
if(SSdbcore.Connect())
var/sql_station_name = sanitizeSQL(station_name())
var/datum/DBQuery/query_round_end = SSdbcore.NewQuery("INSERT INTO [format_table_name("round")] (end_datetime, game_mode_result, end_state, station_name) VALUES (Now(), '[SSticker.mode_result]', '[SSticker.end_state]', '[sql_station_name]') WHERE id = [GLOB.round_id]")
var/datum/DBQuery/query_round_end = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = '[SSticker.mode_result]', end_state = '[SSticker.end_state]', station_name = '[sql_station_name]' WHERE id = [GLOB.round_id]")
query_round_end.Execute()
if(IsConnected())
Disconnect()
@@ -161,7 +161,7 @@ PROCESSING_SUBSYSTEM_DEF(overlays)
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
/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
if(!other)
if(cut_old)
cut_overlays()
@@ -190,3 +190,18 @@ PROCESSING_SUBSYSTEM_DEF(overlays)
/image/proc/cut_overlays(x)
overlays.Cut()
/image/proc/copy_overlays(atom/other, cut_old)
if(!other)
if(cut_old)
cut_overlays()
return
var/list/cached_other = other.our_overlays
if(cached_other)
if(cut_old || !overlays.len)
overlays = cached_other.Copy()
else
overlays |= cached_other
else if(cut_old)
cut_overlays()
@@ -22,9 +22,7 @@ SUBSYSTEM_DEF(processing)
while(current_run.len)
var/datum/thing = current_run[current_run.len]
current_run.len--
if(thing)
thing.process(wait)
else
if(QDELETED(thing) || thing.process(wait) == PROCESS_KILL)
processing -= thing
if (MC_TICK_CHECK)
return
@@ -33,4 +31,4 @@ SUBSYSTEM_DEF(processing)
/datum/proc/process()
set waitfor = 0
STOP_PROCESSING(SSobj, src)
return 0
return 0
+9 -36
View File
@@ -239,6 +239,8 @@ SUBSYSTEM_DEF(ticker)
/datum/controller/subsystem/ticker/proc/PostSetup()
set waitfor = 0
mode.post_setup()
GLOB.start_state = new /datum/station_state()
GLOB.start_state.count(1)
//Cleanup some stuff
for(var/obj/effect/landmark/start/S in GLOB.landmarks_list)
//Deleting Startpoints but we need the ai point to AI-ize people later
@@ -438,7 +440,7 @@ SUBSYSTEM_DEF(ticker)
/datum/controller/subsystem/ticker/proc/transfer_characters()
var/list/livings = list()
for(var/mob/dead/new_player/player in GLOB.player_list)
for(var/mob/dead/new_player/player in GLOB.mob_list)
var/mob/living = player.transfer_character()
if(living)
qdel(player)
@@ -579,45 +581,16 @@ SUBSYSTEM_DEF(ticker)
CHECK_TICK
//Borers
var/borerwin = FALSE
if(GLOB.borers.len)
var/borertext = "<br><font size=3><b>The borers were:</b></font>"
for(var/mob/living/simple_animal/borer/B in GLOB.borers)
if((B.key || B.controlling) && B.stat != DEAD)
borertext += "<br>[B.controlling ? B.victim.key : B.key] was [B.truename] ("
var/turf/location = get_turf(B)
if(location.z == ZLEVEL_CENTCOM && B.victim)
borertext += "escaped with host"
else
borertext += "failed"
borertext += ")"
to_chat(world, borertext)
mode.declare_station_goal_completion()
var/total_borers = 0
for(var/mob/living/simple_animal/borer/B in GLOB.borers)
if((B.key || B.victim) && B.stat != DEAD)
total_borers++
if(total_borers)
var/total_borer_hosts = 0
for(var/mob/living/carbon/C in GLOB.mob_list)
var/mob/living/simple_animal/borer/D = C.has_brain_worms()
var/turf/location = get_turf(C)
if(location.z == ZLEVEL_CENTCOM && D && D.stat != DEAD)
total_borer_hosts++
if(GLOB.total_borer_hosts_needed <= total_borer_hosts)
borerwin = TRUE
to_chat(world, "<b>There were [total_borers] borers alive at round end!</b>")
to_chat(world, "<b>A total of [total_borer_hosts] borers with hosts escaped on the shuttle alive. The borers needed [GLOB.total_borer_hosts_needed] hosts to escape.</b>")
if(borerwin)
to_chat(world, "<b><font color='green'>The borers were successful!</font></b>")
else
to_chat(world, "<b><font color='red'>The borers have failed!</font></b>")
//medals, placed far down so that people can actually see the commendations.
if(GLOB.commendations)
to_chat(world, "<b><font size=3>Medal Commendations:</font></b>")
for (var/com in GLOB.commendations)
to_chat(world, com)
CHECK_TICK
mode.declare_station_goal_completion()
CHECK_TICK
//Adds the del() log to world.log in a format condensable by the runtime condenser found in tools
+14 -2
View File
@@ -1,3 +1,5 @@
#define SUMMON_POSSIBILITIES 3
/datum/antagonist/cult
var/datum/action/innate/cult/comm/communion = new
var/datum/action/innate/cult/mastervote/vote = new
@@ -35,6 +37,11 @@
message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!")
GLOB.sac_complete = TRUE
SSticker.mode.cult_objectives += "sacrifice"
if(!GLOB.summon_spots.len)
while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES)
var/area/summon = pick(GLOB.sortedAreas - GLOB.summon_spots)
if(summon && (summon.z == ZLEVEL_STATION) && summon.valid_territory)
GLOB.summon_spots += summon
SSticker.mode.cult_objectives += "eldergod"
/datum/antagonist/cult/proc/cult_memorization(datum/mind/cult_mind)
@@ -47,8 +54,9 @@
explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it."
else
explanation = "The veil has already been weakened here, proceed to the final objective."
GLOB.sac_complete = TRUE
if("eldergod")
explanation = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie' with nine acolytes on it. You must do this after sacrificing your target."
explanation = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie'. <b>The summoning can only be accomplished in [english_list(GLOB.summon_spots)] - where the veil is weak enough for the ritual to begin.</b>"
if(!silent)
to_chat(current, "<B>Objective #[obj_count]</B>: [explanation]")
cult_mind.memory += "<B>Objective #[obj_count]</B>: [explanation]<BR>"
@@ -112,10 +120,12 @@
/datum/antagonist/cult/master
var/datum/action/innate/cult/master/finalreck/reckoning = new
var/datum/action/innate/cult/master/cultmark/bloodmark = new
var/datum/action/innate/cult/master/pulse/throwing = new
/datum/antagonist/cult/master/Destroy()
QDEL_NULL(reckoning)
QDEL_NULL(bloodmark)
QDEL_NULL(throwing)
return ..()
/datum/antagonist/cult/master/on_gain()
@@ -136,6 +146,7 @@
if(!GLOB.reckoning_complete)
reckoning.Grant(current)
bloodmark.Grant(current)
throwing.Grant(current)
current.update_action_buttons_icon()
current.apply_status_effect(/datum/status_effect/cult_master)
@@ -146,5 +157,6 @@
current = mob_override
reckoning.Remove(current)
bloodmark.Remove(current)
throwing.Remove(current)
current.update_action_buttons_icon()
current.remove_status_effect(/datum/status_effect/cult_master)
current.remove_status_effect(/datum/status_effect/cult_master)
+12 -5
View File
@@ -115,12 +115,19 @@
else
return
if(isturf(source.loc))
var/turf/T = source.loc
if(istype(T))
for(var/mob/living/carbon/C in oview(spread_range, source))
if(isturf(C.loc))
if(AStar(source, C.loc,/turf/proc/Distance, spread_range, adjacent = (spread_flags & AIRBORNE) ? /turf/proc/reachableAdjacentAtmosTurfs : /turf/proc/reachableAdjacentTurfs))
C.ContractDisease(src)
var/turf/V = get_turf(C)
if(V)
while(TRUE)
if(V == T)
C.ContractDisease(src)
break
var/turf/Temp = get_step_towards(V, T)
if(!CANATMOSPASS(V, Temp))
break
V = Temp
/datum/disease/process()
if(!holder)
+11
View File
@@ -38,6 +38,8 @@
if(findtext(msg, "%s"))
msg = replacetext(msg, "%s", user.p_s())
msg = replace_pronoun(user, msg)
var/mob/living/L = user
for(var/obj/item/weapon/implant/I in L.implants)
I.trigger(key, L)
@@ -61,6 +63,15 @@
user.visible_message(msg)
log_emote("[key_name(user)] : [msg]")
/datum/emote/proc/replace_pronoun(mob/user, message)
if(findtext(message, "their"))
message = replacetext(message, "their", user.p_their())
if(findtext(message, "them"))
message = replacetext(message, "them", user.p_them())
if(findtext(message, "%s"))
message = replacetext(message, "%s", user.p_s())
return message
/datum/emote/proc/select_message_type(mob/user)
. = message
if(!muzzle_ignore && user.is_muzzled() && emote_type == EMOTE_AUDIBLE)
+7 -22
View File
@@ -279,16 +279,9 @@ GLOBAL_LIST_EMPTY(explosions)
var/turf/T = affected_turfs[I]
var/current_exp_block = T.density ? T.explosion_block : 0
for(var/obj/machinery/door/D in T)
if(D.density)
current_exp_block += D.explosion_block
for(var/obj/structure/window/W in T)
if(W.reinf && W.fulltile)
current_exp_block += W.explosion_block
for(var/obj/structure/blob/B in T)
current_exp_block += B.explosion_block
for(var/obj/O in T)
var/the_block = O.explosion_block
current_exp_block += the_block == EXPLOSION_BLOCK_PROC ? O.GetExplosionBlock() : the_block
.[T] = current_exp_block
@@ -351,20 +344,12 @@ GLOBAL_LIST_EMPTY(explosions)
var/turf/TT = T
while(TT != epicenter)
TT = get_step_towards(TT,epicenter)
if(TT.density && TT.explosion_block)
if(TT.density)
dist += TT.explosion_block
for(var/obj/machinery/door/D in TT)
if(D.density && D.explosion_block)
dist += D.explosion_block
for(var/obj/structure/window/W in TT)
if(W.explosion_block && W.fulltile)
dist += W.explosion_block
for(var/obj/structure/blob/B in T)
dist += B.explosion_block
for(var/obj/O in T)
var/the_block = O.explosion_block
dist += the_block == EXPLOSION_BLOCK_PROC ? O.GetExplosionBlock() : the_block
if(dist < dev)
T.color = "red"
T.maptext = "Dev"
+1 -1
View File
@@ -73,9 +73,9 @@
return ""
. = header ? "The following pull requests are currently test merged:<br>" : ""
for(var/line in testmerge)
var/cm = testmerge[line]["commit"]
var/details
if(world.RunningService())
var/cm = testmerge[line]["commit"]
details = ": '" + html_encode(testmerge[line]["title"]) + "' by " + html_encode(testmerge[line]["author"]) + " at commit " + html_encode(copytext(cm, 1, min(length(cm), 7)))
else if(has_pr_details) //tgs2 support
details = ": '" + html_encode(testmerge[line]["title"]) + "' by " + html_encode(testmerge[line]["user"]["login"])
+31 -12
View File
@@ -1,4 +1,3 @@
#define HOLOPAD_MAX_DIAL_TIME 200
/mob/camera/aiEye/remote/holo/setLoc()
@@ -16,6 +15,7 @@
var/mob/camera/aiEye/remote/holo/eye //user's eye, once connected
var/obj/effect/overlay/holo_pad_hologram/hologram //user's hologram, once connected
var/datum/action/innate/end_holocall/hangup //hangup action
var/call_start_time
@@ -43,19 +43,25 @@
//cleans up ALL references :)
/datum/holocall/Destroy()
user.reset_perspective()
if(!QDELETED(eye) && user.client)
for(var/datum/camerachunk/chunk in eye.visibleCameraChunks)
chunk.remove(eye)
QDEL_NULL(hangup)
var/user_good = !QDELETED(user)
if(user_good)
user.reset_perspective()
user.remote_control = null
if(!QDELETED(eye))
if(user_good && user.client)
for(var/datum/camerachunk/chunk in eye.visibleCameraChunks)
chunk.remove(eye)
qdel(eye)
eye = null
user.remote_control = null
user = null
if(hologram)
hologram.HC = null
hologram = null
calling_holopad.outgoing_call = null
hologram = null
for(var/I in dialed_holopads)
var/obj/machinery/holopad/H = I
@@ -63,6 +69,7 @@
dialed_holopads.Cut()
if(calling_holopad)
calling_holopad.outgoing_call = null
calling_holopad.SetLightsAndPower()
calling_holopad = null
if(connected_holopad)
@@ -87,7 +94,7 @@
/datum/holocall/proc/ConnectionFailure(obj/machinery/holopad/H, graceful = FALSE)
testing("Holocall connection failure: graceful [graceful]")
if(H == connected_holopad || H == calling_holopad)
if(!graceful)
if(!graceful && H != calling_holopad)
calling_holopad.say("Connection failure.")
qdel(src)
return
@@ -140,6 +147,8 @@
user.reset_perspective(eye)
eye.setLoc(H.loc)
hangup = new(eye, src)
//Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise
/datum/holocall/proc/Check()
for(var/I in dialed_holopads)
@@ -153,9 +162,7 @@
. = !QDELETED(user) && !user.incapacitated() && !QDELETED(calling_holopad) && calling_holopad.is_operational() && user.loc == calling_holopad.loc
if(.)
if(connected_holopad)
. = !QDELETED(connected_holopad) && connected_holopad.is_operational()
else
if(!connected_holopad)
. = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME)
if(!.)
calling_holopad.say("No answer recieved.")
@@ -164,3 +171,15 @@
if(!.)
testing("Holocall Check fail")
qdel(src)
/datum/action/innate/end_holocall
name = "End Holocall"
button_icon_state = "camera_off"
var/datum/holocall/hcall
/datum/action/innate/end_holocall/New(Target, datum/holocall/HC)
..()
hcall = HC
/datum/action/innate/end_holocall/Activate()
hcall.Disconnect(hcall.calling_holopad)
+10
View File
@@ -0,0 +1,10 @@
diff a/code/datums/holocall.dm b/code/datums/holocall.dm (rejected hunks)
@@ -42,6 +43,8 @@
//cleans up ALL references :)
/datum/holocall/Destroy()
+ QDEL_NULL(hangup)
+
var/user_good = !QDELETED(user)
if(user_good)
user.reset_perspective()
+1 -1
View File
@@ -989,7 +989,7 @@
if(!G || (src in G.bosses))
return
SSticker.mode.remove_gangster(src,0,2,1)
G.bosses += src
G.bosses[src] = GANGSTER_BOSS_STARTING_INFLUENCE
gang_datum = G
special_role = "[G.name] Gang Boss"
G.add_gang_hud(src)
+5
View File
@@ -408,6 +408,11 @@ GLOBAL_LIST_EMPTY(mutations_list)
/datum/mutation/human/chameleon/on_move(mob/living/carbon/human/owner)
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
/datum/mutation/human/chameleon/on_attack_hand(mob/living/carbon/human/owner, atom/target, proximity)
if(proximity) //stops tk from breaking chameleon
owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY
return
/datum/mutation/human/chameleon/on_losing(mob/living/carbon/human/owner)
if(..())
return
Regular → Executable
+10
View File
@@ -22,6 +22,9 @@
var/internals_slot = null //ID of slot containing a gas tank
var/list/backpack_contents = null // In the list(path=count,otherpath=count) format
var/list/implants = null
var/accessory = null
var/can_be_admin_equipped = TRUE // Set to FALSE if your outfit requires runtime parameters
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overriden for customization depending on client prefs,species etc
@@ -62,6 +65,13 @@
if(suit_store)
H.equip_to_slot_or_del(new suit_store(H),slot_s_store)
if(accessory)
var/obj/item/clothing/under/U = H.w_uniform
if(U)
U.attach_accessory(new accessory(H))
else
WARNING("Unable to equip accessory [accessory] in outfit [name]. No uniform present!")
if(l_hand)
H.put_in_l_hand(new l_hand(H))
if(r_hand)
-10
View File
@@ -1,15 +1,5 @@
//Largely negative status effects go here, even if they have small benificial effects
/datum/status_effect/sigil_mark //allows the affected target to always trigger sigils while mindless
id = "sigil_mark"
duration = -1
alert_type = null
var/stat_allowed = DEAD //if owner's stat is below this, will remove itself
/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
+58
View File
@@ -0,0 +1,58 @@
//entirely neutral or internal status effects go here
/datum/status_effect/sigil_mark //allows the affected target to always trigger sigils while mindless
id = "sigil_mark"
duration = -1
alert_type = null
var/stat_allowed = DEAD //if owner's stat is below this, will remove itself
/datum/status_effect/sigil_mark/tick()
if(owner.stat < stat_allowed)
qdel(src)
/datum/status_effect/crusher_damage //tracks the damage dealt to this mob by kinetic crushers
id = "crusher_damage"
duration = -1
status_type = STATUS_EFFECT_UNIQUE
alert_type = null
var/total_damage = 0
/datum/status_effect/syphon_mark/on_apply()
if(owner.stat == DEAD)
return FALSE
return ..()
/datum/status_effect/syphon_mark/proc/get_kill()
if(reward_target)
reward_target.get_kill(owner)
/datum/status_effect/syphon_mark/tick()
if(owner.stat == DEAD)
get_kill()
qdel(src)
/datum/status_effect/syphon_mark/on_remove()
get_kill()
. = ..()
/datum/status_effect/syphon_mark
id = "syphon_mark"
duration = 50
status_type = STATUS_EFFECT_MULTIPLE
alert_type = null
on_remove_on_mob_delete = TRUE
var/obj/item/borg/upgrade/modkit/bounty/reward_target
/datum/status_effect/syphon_mark/on_apply()
if(owner.stat == DEAD)
return FALSE
return ..()
/datum/status_effect/syphon_mark/tick()
if(owner.stat == DEAD)
get_kill()
qdel(src)
/datum/status_effect/syphon_mark/on_remove()
get_kill()
. = ..()
+101
View File
@@ -0,0 +1,101 @@
/datum/verbs
var/name
var/list/children
var/datum/verbs/parent
var/list/verblist
var/abstract = FALSE
//returns the master list for verbs of a type
/datum/verbs/proc/GetList()
CRASH("Abstract verblist for [type]")
//modify outlist for each entry in Generate_list
/datum/verbs/proc/HandleVerb(list/outlist, atom/verb/verbpath, ...)
/datum/verbs/New()
var/mainlist = GetList()
var/ourentry = mainlist[type]
children = list()
verblist = list()
if (ourentry)
if (!islist(ourentry)) //some of our childern already loaded
qdel(src)
CRASH("Verb double load: [type]")
Add_children(ourentry)
mainlist[type] = src
Load_verbs(type, typesof("[type]/verb"))
var/datum/verbs/parent = mainlist[parent_type]
if (!parent)
mainlist[parent_type] = list(src)
else if (islist(parent))
parent += src
else
parent.Add_children(list(src))
/datum/verbs/proc/Set_parent(datum/verbs/_parent)
parent = _parent
if (abstract)
parent.Add_children(children)
var/list/verblistoftypes = list()
for(var/thing in verblist)
LAZYADD(verblistoftypes[verblist[thing]], thing)
for(var/verbparenttype in verblistoftypes)
parent.Load_verbs(verbparenttype, verblistoftypes[verbparenttype])
/datum/verbs/proc/Add_children(list/kids)
if (abstract && parent)
parent.Add_children(kids)
return
for(var/thing in kids)
var/datum/verbs/item = thing
item.Set_parent(src)
if (!item.abstract)
children += item
/datum/verbs/proc/Load_verbs(verb_parent_type, list/verbs)
if (abstract && parent)
parent.Load_verbs(verb_parent_type, verbs)
return
for (var/verbpath in verbs)
verblist[verbpath] = verb_parent_type
/datum/verbs/proc/Generate_list(...)
. = list()
if (length(children))
for (var/thing in children)
var/datum/verbs/child = thing
var/list/childlist = child.Generate_list(arglist(args))
if (childlist)
var/childname = "[child]"
if (childname == "[child.type]")
var/list/tree = splittext(childname, "/")
childname = tree[tree.len]
.[child.type] = "parent=[url_encode(type)];name=[url_encode(childname)]"
. += childlist
for (var/thing in verblist)
var/atom/verb/verbpath = thing
if (!verbpath)
stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]")
var/list/entry = list()
entry["parent"] = "[type]"
entry["name"] = verbpath.desc
if (copytext(verbpath.name,1,2) == "@")
entry["command"] = copytext(verbpath.name,2)
else
entry["command"] = replacetext(verbpath.name, " ", "-")
HandleVerb(arglist(list(entry, verbpath) + args))
.[verbpath] = entry
/world/proc/LoadVerbs(verb_type)
if(!ispath(verb_type, /datum/verbs) || verb_type == /datum/verbs)
CRASH("Invalid verb_type: [verb_type]")
for (var/typepath in subtypesof(verb_type))
new typepath()
+36 -5
View File
@@ -43,7 +43,7 @@
/area/ruin/powered/greed
icon_state = "dk_yellow"
/area/ruin/unpowered/hierophant
name = "Hierophant's Arena"
icon_state = "dk_yellow"
@@ -222,16 +222,48 @@
name = "Deep Storage"
icon_state = "storage"
/area/ruin/deepstorage/airlock
name = "Deep Storage Airlock"
icon_state = "quart"
/area/ruin/deepstorage/power
name = "Deep Storage Power and Atmospherics Room"
icon_state = "engi_storage"
/area/ruin/deepstorage/hydroponics
name = "Deep Storage Hydroponics"
icon_state = "garden"
/area/ruin/deepstorage/armory
name = "Deep Storage Secure Storage"
icon_state = "armory"
/area/ruin/deepstorage/storage
name = "Deep Storage Storage"
icon_state = "storage_wing"
/area/ruin/deepstorage/dorm
name = "Deep Storage Dormory"
icon_state = "crew_quarters"
/area/ruin/deepstorage/kitchen
name = "Deep Storage Kitchen"
icon_state = "kitchen"
/area/ruin/deepstorage/crusher
name = "Deep Storage Recycler"
icon_state = "storage"
//Ruin of Abandoned Zoo
/area/ruin/abandonedzoo
name = "Abandoned Zoo"
icon_state = "green"
//Xeno Nest
/area/ruin/xenonest
name = "The Hive"
always_unpowered = 1
@@ -239,4 +271,3 @@
power_equip = 0
power_light = 0
poweralm = 0
+20
View File
@@ -59,3 +59,23 @@
/area/shuttle/abandoned
name = "Abandoned Ship"
blob_allowed = FALSE
/area/shuttle/sbc_starfury
name = "SBC Starfury"
blob_allowed = FALSE
/area/shuttle/sbc_fighter1
name = "SBC Fighter 1"
blob_allowed = FALSE
/area/shuttle/sbc_fighter2
name = "SBC Fighter 2"
blob_allowed = FALSE
/area/shuttle/sbc_corvette
name = "SBC corvette"
blob_allowed = FALSE
/area/shuttle/syndicate_scout
name = "Syndicate Scout"
blob_allowed = FALSE
+1 -6
View File
@@ -79,13 +79,8 @@
return INITIALIZE_HINT_NORMAL
//called if Initialize returns INITIALIZE_HINT_LATELOAD
//This version shouldn't be called
/atom/proc/LateInitialize()
var/static/list/warned_types = list()
if(!warned_types[type])
WARNING("Old style LateInitialize behaviour detected in [type]!")
warned_types[type] = TRUE
Initialize(FALSE)
return
/atom/Destroy()
if(alternate_appearances)
-9
View File
@@ -1,9 +0,0 @@
diff a/code/game/atoms.dm b/code/game/atoms.dm (rejected hunks)
@@ -274,6 +274,7 @@
return
/atom/proc/ex_act(severity, target)
+ set waitfor = FALSE
contents_explosion(severity, target)
/atom/proc/blob_act(obj/structure/blob/B)
+4
View File
@@ -679,3 +679,7 @@
set waitfor = FALSE
if(!anchored && has_gravity())
step(src, movedir)
//Returns an atom's power cell, if it has one. Overload for individual items.
/atom/movable/proc/get_cell()
return
@@ -57,9 +57,9 @@
/obj/effect/proc_holder/changeling/sting/transformation
name = "Transformation Sting"
desc = "We silently sting a human, injecting a retrovirus that forces them to transform."
helptext = "The victim will transform much like a changeling would. The effects will be obvious to the victim, and the process will damage our genomes."
helptext = "The victim will transform much like a changeling would. Does not provide a warning to others. Mutations will not be transferred, and monkeys will become human."
sting_icon = "sting_transform"
chemical_cost = 40
chemical_cost = 50
dna_cost = 3
var/datum/changelingprofile/selected_dna = null
@@ -86,26 +86,19 @@
return 1
/obj/effect/proc_holder/changeling/sting/transformation/sting_action(mob/user, mob/target)
set waitfor = FALSE
add_logs(user, target, "stung", "transformation sting", " new identity is [selected_dna.dna.real_name]")
var/datum/dna/NewDNA = selected_dna.dna
if(ismonkey(target))
to_chat(user, "<span class='notice'>Our genes cry out as we sting [target.name]!</span>")
var/mob/living/carbon/C = target
if(istype(C))
if(C.status_flags & CANWEAKEN)
C.do_jitter_animation(500)
C.take_bodypart_damage(20, 0) //The process is extremely painful
target.visible_message("<span class='danger'>[target] begins to violenty convulse!</span>","<span class='userdanger'>You feel a tiny prick and a begin to uncontrollably convulse!</span>")
. = TRUE
sleep(10)
if(istype(C))
C.real_name = NewDNA.real_name
NewDNA.transfer_identity(C, transfer_SE=1)
NewDNA.transfer_identity(C)
if(ismonkey(C))
C.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_DEFAULTMSG)
C.updateappearance(mutcolor_update=1)
C.domutcheck()
/obj/effect/proc_holder/changeling/sting/false_armblade
+2 -3
View File
@@ -207,10 +207,9 @@ Credit where due:
text += "<br><b>The servants' objective was:</b> <br>[CLOCKCULT_OBJECTIVE]"
text += "<br>Ratvar's servants had <b>[GLOB.clockwork_caches]</b> Tinkerer's Caches."
text += "<br><b>Construction Value(CV)</b> was: <b>[GLOB.clockwork_construction_value]</b>"
var/list/scripture_states = scripture_unlock_check()
for(var/i in scripture_states)
for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER)
text += "<br><b>[i] scripture</b> was: <b>[scripture_states[i] ? "UN":""]LOCKED</b>"
text += "<br><b>[i] scripture</b> was: <b>[SSticker.scripture_states[i] ? "UN":""]LOCKED</b>"
if(servants_of_ratvar.len)
text += "<br><b>Ratvar's servants were:</b>"
for(var/datum/mind/M in servants_of_ratvar)
@@ -204,7 +204,7 @@
else if(!GLOB.ratvar_awakens)
to_chat(user, "<span class='brass'>Hitting the [sigil_name] with brass sheets will convert them to power at a rate of <b>1</b> brass sheet to <b>[POWER_FLOOR]W</b> power.</span>")
if(!GLOB.ratvar_awakens)
to_chat(user, "<span class='brass'>You can recharge Clockwork Proselytizers from the [sigil_name].</span>")
to_chat(user, "<span class='brass'>You can recharge Replica Fabricators from the [sigil_name].</span>")
/obj/effect/clockwork/sigil/transmission/attackby(obj/item/I, mob/living/user, params)
if(is_servant_of_ratvar(user) && istype(I, /obj/item/stack/tile/brass) && !GLOB.ratvar_awakens)
@@ -29,7 +29,7 @@
if(charge)
. = min(charge, 250)
charge = use(.)
updateicon()
update_icon()
/obj/machinery/light/power_drain(clockcult_user)
if(on)
@@ -0,0 +1,372 @@
//For the clockwork fabricator, this proc exists to make it easy to customize what the fabricator does when hitting something.
//if a valid target, returns an associated list in this format;
//list("operation_time" = 15, "new_obj_type" = /obj/structure/window/reinforced/clockwork, "power_cost" = 5, "spawn_dir" = dir, "dir_in_new" = TRUE)
//otherwise, return literally any non-list thing but preferably FALSE
//returning TRUE won't produce the "cannot be fabricated" message and will still prevent fabrication
/atom/proc/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
/atom/proc/consume_visual(obj/item/clockwork/replica_fabricator/fabricator, power_amount)
if(fabricator.can_use_power(power_amount))
var/obj/effect/temp_visual/ratvar/beam/itemconsume/B = new /obj/effect/temp_visual/ratvar/beam/itemconsume(get_turf(src))
B.pixel_x = pixel_x
B.pixel_y = pixel_y
//Turf conversion
/turf/closed/wall/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //four sheets of metal
return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 4), "spawn_dir" = SOUTH)
/turf/closed/wall/mineral/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //two sheets of metal
return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 2), "spawn_dir" = SOUTH)
/turf/closed/wall/mineral/iron/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //two sheets of metal, five rods
return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 2) - (POWER_ROD * 5), "spawn_dir" = SOUTH)
/turf/closed/wall/mineral/cult/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //no metal
return list("operation_time" = 80, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL, "spawn_dir" = SOUTH)
/turf/closed/wall/shuttle/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //two sheets of metal
return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 2), "spawn_dir" = SOUTH)
/turf/closed/wall/r_wall/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
/turf/closed/wall/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 50, "new_obj_type" = /turf/open/floor/clockwork, "power_cost" = -POWER_WALL_MINUS_FLOOR, "spawn_dir" = SOUTH)
/turf/open/floor/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
if(floor_tile == /obj/item/stack/tile/plasteel)
new floor_tile(src)
make_plating()
playsound(src, 'sound/items/Crowbar.ogg', 10, 1) //clink
return list("operation_time" = 30, "new_obj_type" = /turf/open/floor/clockwork, "power_cost" = POWER_FLOOR, "spawn_dir" = SOUTH)
/turf/open/floor/plating/asteroid/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
/turf/open/floor/plating/ashplanet/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
/turf/open/floor/plating/lava/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
/turf/open/floor/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
if(locate(/obj/structure/table) in src)
return FALSE
if(locate(/obj/structure/falsewall) in contents)
to_chat(user, "<span class='warning'>There is a false wall in the way, preventing you from fabricating a clockwork wall on [src].</span>")
return
if(is_blocked_turf(src, TRUE))
to_chat(user, "<span class='warning'>Something is in the way, preventing you from fabricating a clockwork wall on [src].</span>")
return TRUE
var/operation_time = 100
if(!GLOB.ratvar_awakens && fabricator.speed_multiplier > 0) //if ratvar isn't awake, this always takes 10 seconds
operation_time /= fabricator.speed_multiplier
return list("operation_time" = operation_time, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_MINUS_FLOOR, "spawn_dir" = SOUTH)
//False wall conversion
/obj/structure/falsewall/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
var/cost = POWER_WALL_MINUS_FLOOR
if(ispath(mineral, /obj/item/stack/sheet/metal))
cost -= (POWER_METAL * (2 + mineral_amount)) //four sheets of metal, plus an assumption that the girder is also two
else
cost -= (POWER_METAL * 2) //anything that doesn't use metal just has the girder
return list("operation_time" = 50, "new_obj_type" = /obj/structure/falsewall/brass, "power_cost" = cost, "spawn_dir" = SOUTH)
/obj/structure/falsewall/iron/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) //two sheets of metal, two rods; special assumption
return list("operation_time" = 50, "new_obj_type" = /obj/structure/falsewall/brass, "power_cost" = POWER_WALL_MINUS_FLOOR - (POWER_METAL * 2) - (POWER_ROD * 2), "spawn_dir" = SOUTH)
/obj/structure/falsewall/reinforced/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
/obj/structure/falsewall/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
//Metal conversion
/obj/item/stack/tile/plasteel/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
if(source)
return FALSE
var/amount_temp = get_amount()
var/no_delete = FALSE
if(amount_temp < 2)
to_chat(user, "<span class='warning'>You need at least <b>2</b> floor tiles to convert into power.</span>")
return TRUE
if(IsOdd(amount_temp))
amount_temp--
no_delete = TRUE
use(amount_temp)
amount_temp *= 12.5 //each tile is 12.5 power so this is 2 tiles to 25 power
consume_visual(fabricator, amount_temp)
return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = -amount_temp, "spawn_dir" = SOUTH, "no_target_deletion" = no_delete)
/obj/item/stack/rods/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
if(source)
return FALSE
var/power_amount = -(amount*POWER_ROD)
consume_visual(fabricator, power_amount)
return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
/obj/item/stack/sheet/metal/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
if(source)
return FALSE
var/power_amount = -(amount*POWER_METAL)
consume_visual(fabricator, power_amount)
return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
/obj/item/stack/sheet/plasteel/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
if(source)
return FALSE
var/power_amount = -(amount*POWER_PLASTEEL)
consume_visual(fabricator, power_amount)
return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
//Brass directly to power
/obj/item/stack/tile/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
if(source)
return FALSE
var/power_amount = -(amount*POWER_FLOOR)
consume_visual(fabricator, power_amount)
return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
//Airlock conversion
/obj/machinery/door/airlock/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
var/doortype = /obj/machinery/door/airlock/clockwork
if(glass)
doortype = /obj/machinery/door/airlock/clockwork/brass
return list("operation_time" = 60, "new_obj_type" = doortype, "power_cost" = POWER_WALL_TOTAL, "spawn_dir" = dir)
/obj/machinery/door/airlock/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
//Table conversion
/obj/structure/table/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
var/fabrication_cost = POWER_STANDARD
if(framestack == /obj/item/stack/rods)
fabrication_cost -= POWER_ROD*framestackamount
else if(framestack == /obj/item/stack/tile/brass)
fabrication_cost -= POWER_FLOOR*framestackamount
if(buildstack == /obj/item/stack/sheet/metal)
fabrication_cost -= POWER_METAL*buildstackamount
else if(buildstack == /obj/item/stack/sheet/plasteel)
fabrication_cost -= POWER_PLASTEEL*buildstackamount
return list("operation_time" = 20, "new_obj_type" = /obj/structure/table/reinforced/brass, "power_cost" = fabrication_cost, "spawn_dir" = SOUTH)
/obj/structure/table/reinforced/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
/obj/structure/table_frame/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
var/fabrication_cost = POWER_FLOOR
if(framestack == /obj/item/stack/rods)
fabrication_cost -= POWER_ROD*framestackamount
else if(framestack == /obj/item/stack/tile/brass)
fabrication_cost -= POWER_FLOOR*framestackamount
return list("operation_time" = 10, "new_obj_type" = /obj/structure/table_frame/brass, "power_cost" = fabrication_cost, "spawn_dir" = SOUTH)
/obj/structure/table_frame/brass/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
//Window conversion
/obj/structure/window/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
var/windowtype = /obj/structure/window/reinforced/clockwork
var/new_dir = TRUE
var/fabrication_time = 15
var/fabrication_cost = POWER_FLOOR
if(fulltile)
windowtype = /obj/structure/window/reinforced/clockwork/fulltile
new_dir = FALSE
fabrication_time = 30
fabrication_cost = POWER_STANDARD
if(reinf)
fabrication_cost -= POWER_ROD
if(reinf)
fabrication_cost -= POWER_ROD
for(var/obj/structure/grille/G in get_turf(src))
INVOKE_ASYNC(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricate, G, user)
return list("operation_time" = fabrication_time, "new_obj_type" = windowtype, "power_cost" = fabrication_cost, "spawn_dir" = dir, "dir_in_new" = new_dir)
/obj/structure/window/reinforced/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
//Windoor conversion
/obj/machinery/door/window/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 30, "new_obj_type" = /obj/machinery/door/window/clockwork, "power_cost" = POWER_STANDARD, "spawn_dir" = dir, "dir_in_new" = TRUE)
/obj/machinery/door/window/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
//Grille conversion
/obj/structure/grille/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
var/grilletype = /obj/structure/grille/ratvar
var/fabrication_time = 15
if(broken)
grilletype = /obj/structure/grille/ratvar/broken
fabrication_time = 5
return list("operation_time" = fabrication_time, "new_obj_type" = grilletype, "power_cost" = 0, "spawn_dir" = dir)
/obj/structure/grille/ratvar/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
//Lattice conversion
/obj/structure/lattice/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 0, "new_obj_type" = /obj/structure/lattice/clockwork, "power_cost" = 0, "spawn_dir" = SOUTH, "no_target_deletion" = TRUE)
/obj/structure/lattice/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
ratvar_act() //just in case we're the wrong type for some reason??
return FALSE
/obj/structure/lattice/catwalk/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return list("operation_time" = 0, "new_obj_type" = /obj/structure/lattice/catwalk/clockwork, "power_cost" = 0, "spawn_dir" = SOUTH, "no_target_deletion" = TRUE)
/obj/structure/lattice/catwalk/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
return FALSE
//Girder conversion
/obj/structure/girder/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
var/fabrication_cost = POWER_GEAR - (POWER_METAL * 2)
if(state == GIRDER_REINF_STRUTS || state == GIRDER_REINF)
fabrication_cost -= POWER_PLASTEEL
return list("operation_time" = 20, "new_obj_type" = /obj/structure/destructible/clockwork/wall_gear, "power_cost" = fabrication_cost, "spawn_dir" = SOUTH)
//Hitting a clockwork structure will try to repair it.
/obj/structure/destructible/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
. = TRUE
var/list/repair_values = list()
if(!fabricator.fabricator_repair_checks(repair_values, src, user))
return
user.visible_message("<span class='notice'>[user]'s [fabricator.name] starts covering [src] in glowing orange energy...</span>", \
"<span class='alloy'>You start repairing [src]...</span>")
fabricator.repairing = src
while(fabricator && user && src)
if(!do_after(user, repair_values["healing_for_cycle"] * fabricator.speed_multiplier, target = src, \
extra_checks = CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricator_repair_checks, repair_values, src, user, TRUE)))
break
obj_integrity = Clamp(obj_integrity + repair_values["healing_for_cycle"], 0, max_integrity)
fabricator.modify_stored_power(-repair_values["power_required"])
playsound(src, 'sound/machines/click.ogg', 50, 1)
if(fabricator)
fabricator.repairing = null
if(user)
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops covering [src] with glowing orange energy.</span>", \
"<span class='alloy'>You finish repairing [src]. It is now at <b>[obj_integrity]/[max_integrity]</b> integrity.</span>")
//Hitting a sigil of transmission will try to charge from it.
/obj/effect/clockwork/sigil/transmission/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
. = TRUE
var/list/charge_values = list()
if(!fabricator.sigil_charge_checks(charge_values, src, user))
return
user.visible_message("<span class='notice'>[user]'s [fabricator.name] starts draining glowing orange energy from [src]...</span>", \
"<span class='alloy'>You start recharging your [fabricator.name]...</span>")
fabricator.recharging = src
while(fabricator && user && src)
if(!do_after(user, 10, target = src, extra_checks = CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/sigil_charge_checks, charge_values, src, user, TRUE)))
break
modify_charge(charge_values["power_gain"])
fabricator.modify_stored_power(charge_values["power_gain"])
playsound(src, 'sound/effects/light_flicker.ogg', charge_values["power_gain"] * 0.1, 1)
if(fabricator)
fabricator.recharging = null
if(user)
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops draining glowing orange energy from [src].</span>", \
"<span class='alloy'>You finish recharging your [fabricator.name]. It now contains <b>[fabricator.get_power()]W/[fabricator.get_max_power()]W</b> power.</span>")
//Fabricator mob heal proc, to avoid as much copypaste as possible.
/mob/living/proc/fabricator_heal(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator)
var/list/repair_values = list()
if(!fabricator.fabricator_repair_checks(repair_values, src, user))
return
user.visible_message("<span class='notice'>[user]'s [fabricator.name] starts coverin[src == user ? "g [user.p_them()]" : "g [src]"] in glowing orange energy...</span>", \
"<span class='alloy'>You start repairin[src == user ? "g yourself" : "g [src]"]...</span>")
fabricator.repairing = src
while(fabricator && user && src)
if(!do_after(user, repair_values["healing_for_cycle"] * fabricator.speed_multiplier, target = src, \
extra_checks = CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricator_repair_checks, repair_values, src, user, TRUE)))
break
fabricator_heal_tick(repair_values["healing_for_cycle"])
fabricator.modify_stored_power(-repair_values["power_required"])
playsound(src, 'sound/machines/click.ogg', 50, 1)
if(fabricator)
fabricator.repairing = null
return TRUE
/mob/living/proc/fabricator_heal_tick(amount)
var/static/list/damage_heal_order = list(BRUTE, BURN, TOX, OXY)
heal_ordered_damage(amount, damage_heal_order)
/mob/living/simple_animal/fabricator_heal_tick(amount)
adjustHealth(-amount)
//Hitting a ratvar'd silicon will also try to repair it.
/mob/living/silicon/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
. = TRUE
if(health == maxHealth) //if we're at maximum health, replace the turf under us
return FALSE
else if(fabricator_heal(user, fabricator) && user)
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops coverin[src == user ? "g [user.p_them()]" : "g [src]"] with glowing orange energy.</span>", \
"<span class='alloy'>You finish repairin[src == user ? "g yourself. You are":"g [src]. [p_they(TRUE)] [p_are()]"] now at <b>[abs(HEALTH_THRESHOLD_DEAD - health)]/[abs(HEALTH_THRESHOLD_DEAD - maxHealth)]</b> health.</span>")
//Same with clockwork mobs.
/mob/living/simple_animal/hostile/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
. = TRUE
if(health == maxHealth) //if we're at maximum health, replace the turf under us
return FALSE
else if(fabricator_heal(user, fabricator) && user)
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops coverin[src == user ? "g [user.p_them()]" : "g [src]"] with glowing orange energy.</span>", \
"<span class='alloy'>You finish repairin[src == user ? "g yourself. You are":"g [src]. [p_they(TRUE)] [p_are()]"] now at <b>[health]/[maxHealth]</b> health.</span>")
//Cogscarabs get special interaction because they're drones and have innate self-heals/revives.
/mob/living/simple_animal/drone/cogscarab/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent)
. = TRUE
if(stat == DEAD)
try_reactivate(user) //if we're dead, try to repair us
return
if(health == maxHealth)
return FALSE
else if(!(flags & GODMODE))
user.visible_message("<span class='notice'>[user]'s [fabricator.name] starts coverin[src == user ? "g [user.p_them()]" : "g [src]"] in glowing orange energy...</span>", \
"<span class='alloy'>You start repairin[src == user ? "g yourself" : "g [src]"]...</span>")
fabricator.repairing = src
if(do_after(user, (maxHealth - health)*2, target=src))
adjustHealth(-maxHealth)
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops coverin[src == user ? "g [user.p_them()]" : "g [src]"] with glowing orange energy.</span>", \
"<span class='alloy'>You finish repairin[src == user ? "g yourself" : "g [src]"].</span>")
if(fabricator)
fabricator.repairing = null
//Convert shards and gear bits directly to power
/obj/item/clockwork/alloy_shards/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
if(!power_amount)
power_amount = -POWER_STANDARD
consume_visual(fabricator, power_amount)
if(!silent) //looper no looping
for(var/obj/item/clockwork/alloy_shards/S in get_turf(src)) //convert all other shards in the turf if we can
if(S == src)
continue //we want the shards to be fabricated after the main shard, thus this delay
addtimer(CALLBACK(fabricator, /obj/item/clockwork/replica_fabricator.proc/fabricate, S, user, TRUE), 0)
return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
/obj/item/clockwork/alloy_shards/medium/gear_bit/large/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
if(!power_amount)
power_amount = -(CLOCKCULT_POWER_UNIT*0.08)
return ..()
/obj/item/clockwork/alloy_shards/large/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
if(!power_amount)
power_amount = -(CLOCKCULT_POWER_UNIT*0.06)
return ..()
/obj/item/clockwork/alloy_shards/medium/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
if(!power_amount)
power_amount = -(CLOCKCULT_POWER_UNIT*0.04)
return ..()
/obj/item/clockwork/alloy_shards/small/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent, power_amount)
if(!power_amount)
power_amount = -(CLOCKCULT_POWER_UNIT*0.02)
return ..()
@@ -49,6 +49,9 @@
/turf/open/floor/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
if(locate(/obj/structure/table) in src)
return FALSE
if(locate(/obj/structure/falsewall) in contents)
to_chat(user, "<span class='warning'>There is a false wall in the way, preventing you from proselytizing [src] into a clockwork wall.</span>")
return
if(is_blocked_turf(src, TRUE))
to_chat(user, "<span class='warning'>Something is in the way, preventing you from proselytizing [src] into a clockwork wall.</span>")
return TRUE
@@ -7,13 +7,17 @@
servants++
. = 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 && GLOB.clockwork_caches >= SCRIPT_CACHE_REQ)
.[SCRIPTURE_SCRIPT] = (SSticker.scripture_states[SCRIPTURE_SCRIPT] || \
(servants >= SCRIPT_SERVANT_REQ && GLOB.clockwork_caches >= SCRIPT_CACHE_REQ))
//Script: SCRIPT_SERVANT_REQ or more non-brain servants and SCRIPT_CACHE_REQ or more clockwork caches
.[SCRIPTURE_APPLICATION] = (servants >= APPLICATION_SERVANT_REQ && GLOB.clockwork_caches >= APPLICATION_CACHE_REQ && GLOB.clockwork_construction_value >= APPLICATION_CV_REQ)
.[SCRIPTURE_APPLICATION] = (SSticker.scripture_states[SCRIPTURE_APPLICATION] || \
(servants >= APPLICATION_SERVANT_REQ && GLOB.clockwork_caches >= APPLICATION_CACHE_REQ && GLOB.clockwork_construction_value >= APPLICATION_CV_REQ))
//Application: APPLICATION_SERVANT_REQ or more non-brain servants, APPLICATION_CACHE_REQ or more clockwork caches, and at least APPLICATION_CV_REQ CV
.[SCRIPTURE_REVENANT] = (servants >= REVENANT_SERVANT_REQ && GLOB.clockwork_caches >= REVENANT_CACHE_REQ && GLOB.clockwork_construction_value >= REVENANT_CV_REQ)
.[SCRIPTURE_REVENANT] = (SSticker.scripture_states[SCRIPTURE_REVENANT] || \
(servants >= REVENANT_SERVANT_REQ && GLOB.clockwork_caches >= REVENANT_CACHE_REQ && GLOB.clockwork_construction_value >= REVENANT_CV_REQ))
//Revenant: REVENANT_SERVANT_REQ or more non-brain servants, REVENANT_CACHE_REQ or more clockwork caches, and at least REVENANT_CV_REQ CV
.[SCRIPTURE_JUDGEMENT] = (servants >= JUDGEMENT_SERVANT_REQ && GLOB.clockwork_caches >= JUDGEMENT_CACHE_REQ && GLOB.clockwork_construction_value >= JUDGEMENT_CV_REQ && !unconverted_ai_exists)
.[SCRIPTURE_JUDGEMENT] = (SSticker.scripture_states[SCRIPTURE_JUDGEMENT] || \
(servants >= JUDGEMENT_SERVANT_REQ && GLOB.clockwork_caches >= JUDGEMENT_CACHE_REQ && GLOB.clockwork_construction_value >= JUDGEMENT_CV_REQ && !unconverted_ai_exists))
//Judgement: JUDGEMENT_SERVANT_REQ or more non-brain servants, JUDGEMENT_CACHE_REQ or more clockwork caches, at least JUDGEMENT_CV_REQ CV, and there are no living, non-servant ais
//reports to servants when scripture is locked or unlocked
@@ -59,3 +63,6 @@
//changes construction value
/proc/change_construction_value(amount)
GLOB.clockwork_construction_value += amount
/proc/can_recite_scripture(mob/living/L)
return (is_servant_of_ratvar(L) && L.stat == CONSCIOUS && L.can_speak_vocal() && (GLOB.ratvar_awakens || (ishuman(L) || issilicon(L))))
@@ -153,11 +153,11 @@
icon_state = "obelisk_prism"
w_class = WEIGHT_CLASS_NORMAL
//Shards of Alloy, suitable only for proselytization.
//Shards of Alloy, suitable only as a source of power for a replica fabricator.
/obj/item/clockwork/alloy_shards
name = "replicant alloy shards"
desc = "Broken shards of some oddly malleable metal. They occasionally move and seem to glow."
clockwork_desc = "Broken shards of replicant alloy. Can be proselytized for additional power."
clockwork_desc = "Broken shards of replicant alloy."
icon_state = "alloy_shards"
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/randomsinglesprite = FALSE
@@ -172,10 +172,15 @@
pixel_x = rand(-sprite_shift, sprite_shift)
pixel_y = rand(-sprite_shift, sprite_shift)
/obj/item/clockwork/alloy_shards/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
to_chat(user, "<span class='brass'>Can be consumed by a replica fabricator as a source of power.</span>")
/obj/item/clockwork/alloy_shards/proc/replace_name_desc()
name = "replicant alloy shard"
desc = "A broken shard of some oddly malleable metal. It occasionally moves and seems to glow."
clockwork_desc = "A broken shard of replicant alloy. Can be proselytized for additional power."
clockwork_desc = "A broken shard of replicant alloy."
/obj/item/clockwork/alloy_shards/large
w_class = WEIGHT_CLASS_TINY
@@ -197,7 +202,7 @@
/obj/item/clockwork/alloy_shards/medium/gear_bit/replace_name_desc()
name = "gear bit"
desc = "A broken chunk of a gear. You want it."
clockwork_desc = "A broken chunk of a gear. Can be proselytized for additional power."
clockwork_desc = "A broken chunk of a gear."
/obj/item/clockwork/alloy_shards/medium/gear_bit/large //gives more power
@@ -215,5 +220,5 @@
/obj/item/clockwork/alloy_shards/pinion_lock
name = "pinion lock"
desc = "A dented and scratched gear. It's very heavy."
clockwork_desc = "A broken gear lock for pinion airlocks. Can be proselytized for additional power."
clockwork_desc = "A broken gear lock for pinion airlocks"
icon_state = "pinion_lock"
@@ -25,7 +25,7 @@
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
else
armor = list(melee = 80, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100)
flags &= STOPSPRESSUREDMAGE
flags &= ~STOPSPRESSUREDMAGE
max_heat_protection_temperature = initial(max_heat_protection_temperature)
min_cold_protection_temperature = initial(min_cold_protection_temperature)
@@ -81,7 +81,7 @@
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
else
armor = list(melee = 80, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100)
flags &= STOPSPRESSUREDMAGE
flags &= ~STOPSPRESSUREDMAGE
max_heat_protection_temperature = initial(max_heat_protection_temperature)
min_cold_protection_temperature = initial(min_cold_protection_temperature)
@@ -142,7 +142,7 @@
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
else
armor = list(melee = 80, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100)
flags &= STOPSPRESSUREDMAGE
flags &= ~STOPSPRESSUREDMAGE
max_heat_protection_temperature = initial(max_heat_protection_temperature)
min_cold_protection_temperature = initial(min_cold_protection_temperature)
@@ -194,7 +194,7 @@
if(GLOB.ratvar_awakens)
flags |= NOSLIP
else
flags &= NOSLIP
flags &= ~NOSLIP
/obj/item/clothing/shoes/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
if(equipper && !is_servant_of_ratvar(equipper))
@@ -14,7 +14,6 @@
var/target_component_id //the target component ID to create, if any
var/no_cost = FALSE //If the slab is admin-only and needs no components and has no scripture locks
var/speed_multiplier = 1 //multiples how fast this slab recites scripture
var/nonhuman_usable = FALSE //if the slab can be used by nonhumans, defaults to off
var/produces_components = TRUE //if it produces components at all
var/selected_scripture = SCRIPTURE_DRIVER
var/recollecting = FALSE //if we're looking at fancy recollection
@@ -33,29 +32,24 @@
no_cost = TRUE
produces_components = FALSE
/obj/item/clockwork/slab/scarab
nonhuman_usable = TRUE
/obj/item/clockwork/slab/debug
speed_multiplier = 0
no_cost = TRUE
nonhuman_usable = TRUE
/obj/item/clockwork/slab/debug/attack_hand(mob/living/user)
..()
if(!is_servant_of_ratvar(user))
add_servant_of_ratvar(user)
/obj/item/clockwork/slab/cyborg //three scriptures, plus a spear and proselytizer
/obj/item/clockwork/slab/cyborg //three scriptures, plus a spear and fabricator
clockwork_desc = "A divine link to the Celestial Derelict, allowing for limited recital of scripture.\n\
Hitting a slab, a Servant with a slab, or a cache will <b>transfer</b> this slab's components into the target, the target's slab, or the global cache, respectively."
nonhuman_usable = TRUE
quickbound = list(/datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/ranged_ability/linked_vanguard, \
/datum/clockwork_scripture/create_object/tinkerers_cache)
maximum_quickbound = 6 //we usually have one or two unique scriptures, so if ratvar is up let us bind one more
actions_types = list()
/obj/item/clockwork/slab/cyborg/engineer //five scriptures, plus a proselytizer
/obj/item/clockwork/slab/cyborg/engineer //five scriptures, plus a fabricator
quickbound = list(/datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/cogscarab, \
/datum/clockwork_scripture/create_object/soul_vessel, /datum/clockwork_scripture/create_object/sigil_of_transmission, /datum/clockwork_scripture/create_object/interdiction_lens)
@@ -71,7 +65,7 @@
quickbound = list(/datum/clockwork_scripture/channeled/belligerent, /datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/channeled/taunting_tirade, \
/datum/clockwork_scripture/channeled/volt_void/cyborg)
/obj/item/clockwork/slab/cyborg/janitor //five scriptures, plus a proselytizer
/obj/item/clockwork/slab/cyborg/janitor //five scriptures, plus a fabricator
quickbound = list(/datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transgression, \
/datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor, /datum/clockwork_scripture/create_object/tinkerers_daemon)
@@ -106,12 +100,6 @@
slab_ability = null
return ..()
/obj/item/clockwork/slab/ratvar_act()
if(GLOB.ratvar_awakens)
nonhuman_usable = TRUE
else
nonhuman_usable = initial(nonhuman_usable)
/obj/item/clockwork/slab/dropped(mob/user)
. = ..()
addtimer(CALLBACK(src, .proc/check_on_mob, user), 1) //dropped is called before the item is out of the slot, so we need to check slightly later
@@ -138,7 +126,7 @@
production_time = world.time + SLAB_PRODUCTION_TIME + production_slowdown
var/mob/living/L
L = get_atom_on_turf(src, /mob/living)
if(istype(L) && is_servant_of_ratvar(L) && (nonhuman_usable || ishuman(L)))
if(istype(L) && can_recite_scripture(L))
var/component_to_generate = target_component_id
if(!component_to_generate)
component_to_generate = get_weighted_component_id(src) //more likely to generate components that we have less of
@@ -268,7 +256,7 @@
if(busy)
to_chat(user, "<span class='warning'>[src] refuses to work, displaying the message: \"[busy]!\"</span>")
return 0
if(!nonhuman_usable && !ishuman(user))
if(!can_recite_scripture(user))
to_chat(user, "<span class='nezbere'>[src] hums fitfully in your hands, but doesn't seem to do anything...</span>")
return 0
access_display(user)
@@ -288,15 +276,14 @@
ui.open()
/obj/item/clockwork/slab/proc/recite_scripture(datum/clockwork_scripture/scripture, mob/living/user)
if(!scripture || !user || !user.canUseTopic(src) || (!nonhuman_usable && !ishuman(user)))
if(!scripture || !user || !user.canUseTopic(src) || !can_recite_scripture(user))
return FALSE
if(user.get_active_held_item() != src)
to_chat(user, "<span class='warning'>You need to hold the slab in your active hand to recite scripture!</span>")
return FALSE
var/initial_tier = initial(scripture.tier)
if(initial_tier != SCRIPTURE_PERIPHERAL)
var/list/tiers_of_scripture = scripture_unlock_check()
if(!GLOB.ratvar_awakens && !no_cost && !tiers_of_scripture[initial_tier])
if(!GLOB.ratvar_awakens && !no_cost && !SSticker.scripture_states[initial_tier])
to_chat(user, "<span class='warning'>That scripture is not unlocked, and cannot be recited!</span>")
return FALSE
var/datum/clockwork_scripture/scripture_to_recite = new scripture
@@ -415,13 +402,25 @@
if(SCRIPTURE_DRIVER)
data["tier_info"] = "<font color=#B18B25><i>These scriptures are always unlocked.</i></font>"
if(SCRIPTURE_SCRIPT)
data["tier_info"] = "<font color=#B18B25><i>These scriptures require at least <b>[SCRIPT_SERVANT_REQ]</b> Servants and <b>[SCRIPT_CACHE_REQ]</b> Tinkerer's Cache.</i></font>"
if(SSticker.scripture_states[SCRIPTURE_SCRIPT])
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permenantly unlocked.</b></font>"
else
data["tier_info"] = "<font color=#B18B25><i>These scriptures require at least <b>[SCRIPT_SERVANT_REQ]</b> Servants and <b>[SCRIPT_CACHE_REQ]</b> Tinkerer's Cache.</i></font>"
if(SCRIPTURE_APPLICATION)
data["tier_info"] = "<font color=#B18B25><i>These scriptures require at least <b>[APPLICATION_SERVANT_REQ]</b> Servants, <b>[APPLICATION_CACHE_REQ]</b> Tinkerer's Caches, and <b>[APPLICATION_CV_REQ]CV</b>.</i></font>"
if(SSticker.scripture_states[SCRIPTURE_APPLICATION])
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permenantly unlocked.</b></font>"
else
data["tier_info"] = "<font color=#B18B25><i>These scriptures require at least <b>[APPLICATION_SERVANT_REQ]</b> Servants, <b>[APPLICATION_CACHE_REQ]</b> Tinkerer's Caches, and <b>[APPLICATION_CV_REQ]CV</b>.</i></font>"
if(SCRIPTURE_REVENANT)
data["tier_info"] = "<font color=#B18B25><i>These scriptures require at least <b>[REVENANT_SERVANT_REQ]</b> Servants, <b>[REVENANT_CACHE_REQ]</b> Tinkerer's Caches, and <b>[REVENANT_CV_REQ]CV</b>.</i></font>"
if(SSticker.scripture_states[SCRIPTURE_REVENANT])
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permenantly unlocked.</b></font>"
else
data["tier_info"] = "<font color=#B18B25><i>These scriptures require at least <b>[REVENANT_SERVANT_REQ]</b> Servants, <b>[REVENANT_CACHE_REQ]</b> Tinkerer's Caches, and <b>[REVENANT_CV_REQ]CV</b>.</i></font>"
if(SCRIPTURE_JUDGEMENT)
data["tier_info"] = "<font color=#B18B25><i>This scripture requires at least <b>[JUDGEMENT_SERVANT_REQ]</b> Servants, <b>[JUDGEMENT_CACHE_REQ]</b> Tinkerer's Caches, and <b>[JUDGEMENT_CV_REQ]CV</b>.<br>In addition, there may not be any active non-Servant AIs.</i></font>"
if(SSticker.scripture_states[SCRIPTURE_JUDGEMENT])
data["tier_info"] = "<font color=#B18B25><b>This scripture is permenantly unlocked.</b></font>"
else
data["tier_info"] = "<font color=#B18B25><i>This scripture requires at least <b>[JUDGEMENT_SERVANT_REQ]</b> Servants, <b>[JUDGEMENT_CACHE_REQ]</b> Tinkerer's Caches, and <b>[JUDGEMENT_CV_REQ]CV</b>.<br>In addition, there may not be any active non-Servant AIs.</i></font>"
data["selected"] = selected_scripture
@@ -1,51 +1,48 @@
//Clockwork proselytizer: Converts applicable objects to Ratvarian variants.
/obj/item/clockwork/clockwork_proselytizer
name = "clockwork proselytizer"
//Replica Fabricator: Converts applicable objects to Ratvarian variants.
/obj/item/clockwork/replica_fabricator
name = "replica fabricator"
desc = "An odd, L-shaped device that hums with energy."
clockwork_desc = "A device that allows the replacing of mundane objects with Ratvarian variants. It requires power to function."
icon_state = "clockwork_proselytizer"
icon_state = "replica_fabricator"
w_class = WEIGHT_CLASS_NORMAL
force = 5
flags = NOBLUDGEON
var/stored_power = 0 //Requires power to function
var/max_power = CLOCKCULT_POWER_UNIT * 10
var/uses_power = TRUE
var/metal_to_power = FALSE
var/repairing = null //what we're currently repairing, if anything
var/obj/effect/clockwork/sigil/transmission/recharging = null //the sigil we're charging from, if any
var/speed_multiplier = 1 //how fast this proselytizer works
var/speed_multiplier = 1 //how fast this fabricator works
var/charge_rate = MIN_CLOCKCULT_POWER //how much power we gain every two seconds
var/charge_delay = 2 //how many proccess ticks remain before we can start to charge
/obj/item/clockwork/clockwork_proselytizer/preloaded
/obj/item/clockwork/replica_fabricator/preloaded
stored_power = POWER_WALL_MINUS_FLOOR+POWER_WALL_TOTAL
/obj/item/clockwork/clockwork_proselytizer/scarab
name = "scarab proselytizer"
clockwork_desc = "A cogscarab's internal proselytizer. It can only be successfully used by a cogscarab and requires power to function."
metal_to_power = TRUE
/obj/item/clockwork/replica_fabricator/scarab
name = "scarab fabricator"
clockwork_desc = "A cogscarab's internal fabricator. It can only be successfully used by a cogscarab and requires power to function."
item_state = "nothing"
w_class = WEIGHT_CLASS_TINY
speed_multiplier = 0.5
charge_rate = MIN_CLOCKCULT_POWER * 2
var/debug = FALSE
/obj/item/clockwork/clockwork_proselytizer/scarab/proselytize(atom/target, mob/living/user)
/obj/item/clockwork/replica_fabricator/scarab/fabricate(atom/target, mob/living/user)
if(!debug && !isdrone(user))
return 0
return ..()
/obj/item/clockwork/clockwork_proselytizer/scarab/debug
clockwork_desc = "A cogscarab's internal proselytizer. It can convert nearly any object into a Ratvarian variant."
/obj/item/clockwork/replica_fabricator/scarab/debug
clockwork_desc = "A cogscarab's internal fabricator. It can convert nearly any object into a Ratvarian variant."
uses_power = FALSE
debug = TRUE
/obj/item/clockwork/clockwork_proselytizer/cyborg
name = "cyborg proselytizer"
clockwork_desc = "A cyborg's internal proselytizer. It is capable of using the cyborg's power in addition to stored power."
metal_to_power = TRUE
/obj/item/clockwork/replica_fabricator/cyborg
name = "cyborg fabricator"
clockwork_desc = "A cyborg's internal fabricator. It is capable of using the cyborg's power in addition to stored power."
/obj/item/clockwork/clockwork_proselytizer/cyborg/get_power() //returns power and cyborg's power
/obj/item/clockwork/replica_fabricator/cyborg/get_power() //returns power and cyborg's power
var/mob/living/silicon/robot/R = get_atom_on_turf(src, /mob/living)
var/borg_power = 0
var/current_charge = 0
@@ -56,14 +53,14 @@
borg_power += MIN_CLOCKCULT_POWER
return ..() + borg_power
/obj/item/clockwork/clockwork_proselytizer/cyborg/get_max_power()
/obj/item/clockwork/replica_fabricator/cyborg/get_max_power()
var/mob/living/silicon/robot/R = get_atom_on_turf(src, /mob/living)
var/cell_maxcharge = 0
if(istype(R) && R.cell)
cell_maxcharge = R.cell.maxcharge
return ..() + cell_maxcharge
/obj/item/clockwork/clockwork_proselytizer/cyborg/can_use_power(amount)
/obj/item/clockwork/replica_fabricator/cyborg/can_use_power(amount)
if(amount != RATVAR_POWER_CHECK)
var/mob/living/silicon/robot/R = get_atom_on_turf(src, /mob/living)
var/current_charge = 0
@@ -76,7 +73,7 @@
return FALSE
. = ..()
/obj/item/clockwork/clockwork_proselytizer/cyborg/modify_stored_power(amount)
/obj/item/clockwork/replica_fabricator/cyborg/modify_stored_power(amount)
var/mob/living/silicon/robot/R = get_atom_on_turf(src, /mob/living)
if(istype(R) && R.cell && amount)
if(amount < 0)
@@ -89,15 +86,15 @@
amount -= MIN_CLOCKCULT_POWER
. = ..()
/obj/item/clockwork/clockwork_proselytizer/Initialize()
/obj/item/clockwork/replica_fabricator/Initialize()
. = ..()
START_PROCESSING(SSobj, src)
/obj/item/clockwork/clockwork_proselytizer/Destroy()
/obj/item/clockwork/replica_fabricator/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/clockwork/clockwork_proselytizer/process()
/obj/item/clockwork/replica_fabricator/process()
if(!charge_rate)
return
var/mob/living/L = get_atom_on_turf(src, /mob/living)
@@ -106,14 +103,14 @@
charge_delay--
return
modify_stored_power(charge_rate)
for(var/obj/item/clockwork/clockwork_proselytizer/S in L.GetAllContents()) //no multiple proselytizers
for(var/obj/item/clockwork/replica_fabricator/S in L.GetAllContents()) //no multiple fabricators
if(S == src)
continue
S.charge_delay = 2
else
charge_delay = 2
/obj/item/clockwork/clockwork_proselytizer/ratvar_act()
/obj/item/clockwork/replica_fabricator/ratvar_act()
if(GLOB.nezbere_invoked)
charge_rate = 1250
else
@@ -125,21 +122,19 @@
uses_power = initial(uses_power)
speed_multiplier = initial(speed_multiplier)
/obj/item/clockwork/clockwork_proselytizer/examine(mob/living/user)
/obj/item/clockwork/replica_fabricator/examine(mob/living/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
to_chat(user, "<span class='brass'>Can be used to convert walls, floors, windows, airlocks, and a variety of other objects to clockwork variants.</span>")
to_chat(user, "<span class='brass'>Can also form some objects into Brass sheets, as well as reform Clockwork Walls into Clockwork Floors, and vice versa.</span>")
to_chat(user, "<span class='brass'>Can be used to replace walls, floors, tables, windows, windoors, and airlocks with Clockwork variants.</span>")
to_chat(user, "<span class='brass'>Can construct Clockwork Walls on Clockwork Floors and deconstruct Clockwork Walls to Clockwork Floors.</span>")
if(uses_power)
if(metal_to_power)
to_chat(user, "<span class='alloy'>It can convert rods, metal, plasteel, and brass to power at rates of <b>1:[POWER_ROD]W</b>, <b>1:[POWER_METAL]W</b>, \
<b>1:[POWER_PLASTEEL]W</b>, and <b>1:[POWER_FLOOR]W</b>, respectively.</span>")
else
to_chat(user, "<span class='alloy'>It can convert brass to power at a rate of <b>1:[POWER_FLOOR]W</b>.</span>")
to_chat(user, "<span class='alloy'>It is storing <b>[get_power()]W/[get_max_power()]W</b> of power, and is gaining <b>[charge_rate*0.5]W</b> of power per second.</span>")
to_chat(user, "<span class='alloy'>It can consume floor tiles, rods, metal, and plasteel for power at rates of <b>2:[POWER_ROD]W</b>, <b>1:[POWER_ROD]W</b>, <b>1:[POWER_METAL]W</b>, \
and <b>1:[POWER_PLASTEEL]W</b>, respectively.</span>")
to_chat(user, "<span class='alloy'>It can also consume brass sheets for power at a rate of <b>1:[POWER_FLOOR]W</b>.</span>")
to_chat(user, "<span class='alloy'>It is storing <b>[get_power()]W/[get_max_power()]W</b> of power[charge_rate ? ", and is gaining <b>[charge_rate*0.5]W</b> of power per second":""].</span>")
to_chat(user, "<span class='alloy'>Use it in-hand to produce <b>5</b> brass sheets at a cost of <b>[POWER_WALL_TOTAL]W</b> power.</span>")
/obj/item/clockwork/clockwork_proselytizer/attack_self(mob/living/user)
/obj/item/clockwork/replica_fabricator/attack_self(mob/living/user)
if(is_servant_of_ratvar(user))
if(uses_power)
if(!can_use_power(POWER_WALL_TOTAL))
@@ -148,24 +143,24 @@
modify_stored_power(-POWER_WALL_TOTAL)
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
new/obj/item/stack/tile/brass(user.loc, 5)
to_chat(user, "<span class='brass'>You user [stored_power ? "some":"all"] of [src]'s power to produce some brass sheets. It now stores <b>[get_power()]W/[get_max_power()]W</b> of power.</span>")
to_chat(user, "<span class='brass'>You use [stored_power ? "some":"all"] of [src]'s power to produce <b>5</b> brass sheets. It now stores <b>[get_power()]W/[get_max_power()]W</b> of power.</span>")
/obj/item/clockwork/clockwork_proselytizer/pre_attackby(atom/target, mob/living/user, params)
/obj/item/clockwork/replica_fabricator/pre_attackby(atom/target, mob/living/user, params)
if(!target || !user || !is_servant_of_ratvar(user) || istype(target, /obj/item/weapon/storage))
return TRUE
return proselytize(target, user)
return fabricate(target, user)
/obj/item/clockwork/clockwork_proselytizer/proc/get_power()
/obj/item/clockwork/replica_fabricator/proc/get_power()
return stored_power
/obj/item/clockwork/clockwork_proselytizer/proc/get_max_power()
/obj/item/clockwork/replica_fabricator/proc/get_max_power()
return max_power
/obj/item/clockwork/clockwork_proselytizer/proc/modify_stored_power(amount)
/obj/item/clockwork/replica_fabricator/proc/modify_stored_power(amount)
stored_power = Clamp(stored_power + amount, 0, max_power)
return TRUE
/obj/item/clockwork/clockwork_proselytizer/proc/can_use_power(amount)
/obj/item/clockwork/replica_fabricator/proc/can_use_power(amount)
if(amount == RATVAR_POWER_CHECK)
if(GLOB.ratvar_awakens || !uses_power)
return TRUE
@@ -178,7 +173,7 @@
return TRUE
//A note here; return values are for if we CAN BE PUT ON A TABLE, not IF WE ARE SUCCESSFUL, unless no_table_check is TRUE
/obj/item/clockwork/clockwork_proselytizer/proc/proselytize(atom/target, mob/living/user, silent, no_table_check)
/obj/item/clockwork/replica_fabricator/proc/fabricate(atom/target, mob/living/user, silent, no_table_check)
if(!target || !user)
return FALSE
if(repairing)
@@ -189,59 +184,77 @@
if(!silent)
to_chat(user, "<span class='warning'>You are currently recharging [src] from the [recharging.sigil_name]!</span>")
return FALSE
var/list/proselytize_values = target.proselytize_vals(user, src, silent) //relevant values for proselytizing stuff, given as an associated list
if(!islist(proselytize_values))
if(proselytize_values != TRUE) //if we get true, fail, but don't send a message for whatever reason
if(!isturf(target)) //otherwise, if we didn't get TRUE and the original target wasn't a turf, try to proselytize the turf
return proselytize(get_turf(target), user, no_table_check)
var/list/fabrication_values = target.fabrication_vals(user, src, silent) //relevant values for fabricating stuff, given as an associated list
if(!islist(fabrication_values))
if(fabrication_values != TRUE) //if we get true, fail, but don't send a message for whatever reason
if(!isturf(target)) //otherwise, if we didn't get TRUE and the original target wasn't a turf, try to fabricate the turf
return fabricate(get_turf(target), user, no_table_check)
if(!silent)
to_chat(user, "<span class='warning'>[target] cannot be proselytized!</span>")
to_chat(user, "<span class='warning'>[target] cannot be fabricated!</span>")
if(!no_table_check)
return TRUE
return FALSE
if(can_use_power(RATVAR_POWER_CHECK))
proselytize_values["power_cost"] = 0
fabrication_values["power_cost"] = 0
var/turf/Y = get_turf(user)
if(!Y || (Y.z != ZLEVEL_STATION && Y.z != ZLEVEL_CENTCOM && Y.z != ZLEVEL_MINING && Y.z != ZLEVEL_LAVALAND))
proselytize_values["operation_time"] *= 2
if(proselytize_values["power_cost"] > 0)
proselytize_values["power_cost"] *= 2
fabrication_values["operation_time"] *= 2
if(fabrication_values["power_cost"] > 0)
fabrication_values["power_cost"] *= 2
var/target_type = target.type
if(!proselytize_checks(proselytize_values, target, target_type, user, silent))
if(!fabricate_checks(fabrication_values, target, target_type, user, silent))
return FALSE
proselytize_values["operation_time"] *= speed_multiplier
fabrication_values["operation_time"] *= speed_multiplier
playsound(target, 'sound/machines/click.ogg', 50, 1)
if(proselytize_values["operation_time"])
if(fabrication_values["operation_time"])
if(!silent)
user.visible_message("<span class='warning'>[user]'s [name] begins tearing apart [target]!</span>", "<span class='brass'>You begin proselytizing [target]...</span>")
if(!do_after(user, proselytize_values["operation_time"], target = target, extra_checks = CALLBACK(src, .proc/proselytize_checks, proselytize_values, target, target_type, user, TRUE)))
var/atom/A = fabrication_values["new_obj_type"]
if(A)
user.visible_message("<span class='warning'>[user]'s [name] starts ripping [target] apart!</span>", \
"<span class='brass'>You start fabricating \a [initial(A.name)] from [target]...</span>")
else
user.visible_message("<span class='warning'>[user]'s [name] starts consuming [target]!</span>", \
"<span class='brass'>Your [name] starts consuming [target]...</span>")
if(!do_after(user, fabrication_values["operation_time"], target = target, extra_checks = CALLBACK(src, .proc/fabricate_checks, fabrication_values, target, target_type, user, TRUE)))
return FALSE
if(!silent)
user.visible_message("<span class='warning'>[user]'s [name] covers [target] in golden energy!</span>", "<span class='brass'>You proselytize [target].</span>")
var/atom/A = fabrication_values["new_obj_type"]
if(A)
user.visible_message("<span class='warning'>[user]'s [name] replaces [target] with \a [initial(A.name)]!</span>", \
"<span class='brass'>You fabricate \a [initial(A.name)] from [target].</span>")
else
user.visible_message("<span class='warning'>[user]'s [name] consumes [target]!</span>", \
"<span class='brass'>Your [name] consumes [target].</span>")
else
if(!silent)
user.visible_message("<span class='warning'>[user]'s [name] tears apart [target], covering it in golden energy!</span>", "<span class='brass'>You proselytize [target].</span>")
var/atom/A = fabrication_values["new_obj_type"]
if(A)
user.visible_message("<span class='warning'>[user]'s [name] rips apart [target], replacing it with \a [initial(A.name)]!</span>", \
"<span class='brass'>You fabricate \a [initial(A.name)] from [target].</span>")
else
user.visible_message("<span class='warning'>[user]'s [name] rapidly consumes [target]!</span>", \
"<span class='brass'>Your [name] consumes [target].</span>")
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
var/new_thing_type = proselytize_values["new_obj_type"]
var/new_thing_type = fabrication_values["new_obj_type"]
if(isturf(target)) //if our target is a turf, we're just going to ChangeTurf it and assume it'll work out.
var/turf/T = target
T.ChangeTurf(new_thing_type)
else
if(new_thing_type)
if(proselytize_values["dir_in_new"])
new new_thing_type(get_turf(target), proselytize_values["spawn_dir"]) //please verify that your new object actually wants to get a dir in New()
if(fabrication_values["dir_in_new"])
new new_thing_type(get_turf(target), fabrication_values["spawn_dir"]) //please verify that your new object actually wants to get a dir in New()
else
var/atom/A = new new_thing_type(get_turf(target))
A.setDir(proselytize_values["spawn_dir"])
if(!proselytize_values["no_target_deletion"]) //for some cases where proselytize_vals() modifies the object but doesn't want it deleted
A.setDir(fabrication_values["spawn_dir"])
if(!fabrication_values["no_target_deletion"]) //for some cases where fabrication_vals() modifies the object but doesn't want it deleted
qdel(target)
modify_stored_power(-proselytize_values["power_cost"])
modify_stored_power(-fabrication_values["power_cost"])
if(no_table_check)
return TRUE
return FALSE
@@ -250,28 +263,34 @@
//What these procs do is they take an existing list of values, which they then modify.
//This(modifying an existing object, in this case the list) is the only way to get information OUT of a do_after callback, which this is used as.
//The proselytize check proc.
/obj/item/clockwork/clockwork_proselytizer/proc/proselytize_checks(list/proselytize_values, atom/target, expected_type, mob/user, silent) //checked constantly while proselytizing
if(!islist(proselytize_values) || QDELETED(target) || QDELETED(user))
//The fabricate check proc.
/obj/item/clockwork/replica_fabricator/proc/fabricate_checks(list/fabrication_values, atom/target, expected_type, mob/user, silent) //checked constantly while fabricating
if(!islist(fabrication_values) || QDELETED(target) || QDELETED(user))
return FALSE
if(repairing || recharging)
return FALSE
if(target.type != expected_type)
return FALSE
if(can_use_power(RATVAR_POWER_CHECK))
proselytize_values["power_cost"] = 0
if(!can_use_power(proselytize_values["power_cost"]))
if(stored_power - proselytize_values["power_cost"] < 0)
fabrication_values["power_cost"] = 0
if(!can_use_power(fabrication_values["power_cost"]))
if(stored_power - fabrication_values["power_cost"] < 0)
if(!silent)
to_chat(user, "<span class='warning'>You need <b>[proselytize_values["power_cost"]]W</b> power to proselytize [target]!</span>")
else if(stored_power - proselytize_values["power_cost"] > max_power)
var/atom/A = fabrication_values["new_obj_type"]
if(A)
to_chat(user, "<span class='warning'>You need <b>[fabrication_values["power_cost"]]W</b> power to fabricate \a [initial(A.name)] from [target]!</span>")
else if(stored_power - fabrication_values["power_cost"] > max_power)
if(!silent)
to_chat(user, "<span class='warning'>Your [name] contains too much power to proselytize [target]!</span>")
var/atom/A = fabrication_values["new_obj_type"]
if(A)
to_chat(user, "<span class='warning'>Your [name] contains too much power to fabricate \a [initial(A.name)] from [target]!</span>")
else
to_chat(user, "<span class='warning'>Your [name] contains too much power to consume [target]!</span>")
return FALSE
return TRUE
//The repair check proc.
/obj/item/clockwork/clockwork_proselytizer/proc/proselytizer_repair_checks(list/repair_values, atom/target, mob/user, silent) //Exists entirely to avoid an otherwise unreadable series of checks.
/obj/item/clockwork/replica_fabricator/proc/fabricator_repair_checks(list/repair_values, atom/target, mob/user, silent) //Exists entirely to avoid an otherwise unreadable series of checks.
if(!islist(repair_values) || QDELETED(target) || QDELETED(user))
return FALSE
if(isliving(target)) //standard checks for if we can affect the target
@@ -302,7 +321,7 @@
return FALSE
if(repair_values["amount_to_heal"] <= 0) //nothing to heal!
return FALSE
repair_values["healing_for_cycle"] = min(repair_values["amount_to_heal"], PROSELYTIZER_REPAIR_PER_TICK) //modify the healing for this cycle
repair_values["healing_for_cycle"] = min(repair_values["amount_to_heal"], FABRICATOR_REPAIR_PER_TICK) //modify the healing for this cycle
repair_values["power_required"] = round(repair_values["healing_for_cycle"]*MIN_CLOCKCULT_POWER, MIN_CLOCKCULT_POWER) //and get the power cost from that
if(!can_use_power(RATVAR_POWER_CHECK) && !can_use_power(repair_values["power_required"]))
if(!silent)
@@ -312,7 +331,7 @@
return TRUE
//The sigil charge check proc.
/obj/item/clockwork/clockwork_proselytizer/proc/sigil_charge_checks(list/charge_values, obj/effect/clockwork/sigil/transmission/sigil, mob/user, silent)
/obj/item/clockwork/replica_fabricator/proc/sigil_charge_checks(list/charge_values, obj/effect/clockwork/sigil/transmission/sigil, mob/user, silent)
if(!islist(charge_values) || QDELETED(sigil) || QDELETED(user))
return FALSE
if(can_use_power(RATVAR_POWER_CHECK))
@@ -120,7 +120,7 @@ Judgement: 12 servants, 5 caches, 300 CV, and any existing AIs are converted or
if(multiple_invokers_used && !multiple_invokers_optional && !GLOB.ratvar_awakens && !slab.no_cost)
var/nearby_servants = 0
for(var/mob/living/L in range(1, get_turf(invoker)))
if(is_servant_of_ratvar(L) && L.stat == CONSCIOUS && L.can_speak_vocal())
if(can_recite_scripture(L))
nearby_servants++
if(nearby_servants < invokers_required)
to_chat(invoker, "<span class='warning'>There aren't enough non-mute servants nearby ([nearby_servants]/[invokers_required])!</span>")
@@ -170,7 +170,7 @@ Judgement: 12 servants, 5 caches, 300 CV, and any existing AIs are converted or
if(!channel_time && invocations.len)
if(multiple_invokers_used)
for(var/mob/living/L in range(1, invoker))
if(is_servant_of_ratvar(L) && L.stat == CONSCIOUS && L.can_speak_vocal())
if(can_recite_scripture(L))
for(var/invocation in invocations)
clockwork_say(L, text2ratvar(invocation), whispered)
else
@@ -185,7 +185,7 @@ Judgement: 12 servants, 5 caches, 300 CV, and any existing AIs are converted or
return FALSE
if(multiple_invokers_used)
for(var/mob/living/L in range(1, get_turf(invoker)))
if(is_servant_of_ratvar(L) && L.stat == CONSCIOUS && L.can_speak_vocal())
if(can_recite_scripture(L))
clockwork_say(L, text2ratvar(invocation), whispered)
else
clockwork_say(invoker, text2ratvar(invocation), whispered)
@@ -53,7 +53,7 @@
/datum/clockwork_scripture/fellowship_armory/run_scripture()
for(var/mob/living/L in orange(1, invoker))
if(is_servant_of_ratvar(L) && L.stat == CONSCIOUS && L.can_speak_vocal())
if(can_recite_scripture(L))
channel_time = max(channel_time - 10, 0)
return ..()
@@ -105,11 +105,11 @@
descname = "Global Structure Buff"
name = "Invoke Nezbere, the Brass Eidolon"
desc = "Taps the limitless power of Nezbere, one of Ratvar's four generals. The restless toil of the Eidolon will empower a wide variety of clockwork apparatus for a full minute - notably, \
clockwork proselytizers will charge very rapidly."
replica fabricators will charge very rapidly."
invocations = list("I call upon you, Armorer!!", "Let your machinations reign on this miserable station!!", "Let your power flow through the tools of your master!!")
channel_time = 150
consumed_components = list(BELLIGERENT_EYE = 6, VANGUARD_COGWHEEL = 6, GEIS_CAPACITOR = 6, REPLICANT_ALLOY = 10)
usage_tip = "Ocular wardens will become empowered, clockwork proselytizers will require no alloy, tinkerer's daemons will produce twice as quickly, \
usage_tip = "Ocular wardens will become empowered, tinkerer's daemons will produce twice as quickly, \
and interdiction lenses, mania motors, tinkerer's daemons, and clockwork obelisks will all require no power."
tier = SCRIPTURE_REVENANT
primary_component = REPLICANT_ALLOY
@@ -33,7 +33,7 @@
/datum/clockwork_scripture/create_object/cogscarab
descname = "Constructor Soul Vessel Shell"
name = "Cogscarab"
desc = "Creates a small shell fitted for soul vessels. Adding an active soul vessel to it results in a small construct with tools and an inbuilt proselytizer."
desc = "Creates a small shell fitted for soul vessels. Adding an active soul vessel to it results in a small construct with tools and an inbuilt fabricator."
invocations = list("Call forth...", "...the workers of Armorer.")
channel_time = 60
consumed_components = list(BELLIGERENT_EYE = 2, HIEROPHANT_ANSIBLE = 1)
@@ -221,24 +221,24 @@
quickbind_desc = "Creates a Soul Vessel, which can be placed in construct shells and cyborg bodies once filled."
//Clockwork Proselytizer: Creates a clockwork proselytizer, used to convert objects and repair clockwork structures.
/datum/clockwork_scripture/create_object/clockwork_proselytizer
descname = "Converts Objects to Ratvarian"
name = "Clockwork Proselytizer"
desc = "Forms a device that, when used on certain objects, converts them into their Ratvarian equivalents. It requires power to function."
//Replica Fabricator: Creates a replica fabricator, used to convert objects and repair clockwork structures.
/datum/clockwork_scripture/create_object/replica_fabricator
descname = "Replaces Objects with Ratvarian Versions"
name = "Replica Fabricator"
desc = "Forms a device that, when used on certain objects, replaces them with their Ratvarian equivalents. It requires power to function."
invocations = list("With this device...", "...his presence shall be made known.")
channel_time = 20
consumed_components = list(GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 2)
whispered = TRUE
object_path = /obj/item/clockwork/clockwork_proselytizer/preloaded
creator_message = "<span class='brass'>You form a clockwork proselytizer.</span>"
usage_tip = "Clockwork Walls cause nearby tinkerer's caches to generate components passively, making them a vital tool. Clockwork Floors heal toxin damage in Servants standing on them."
object_path = /obj/item/clockwork/replica_fabricator/preloaded
creator_message = "<span class='brass'>You form a replica fabricator.</span>"
usage_tip = "Clockwork Walls cause nearby Tinkerer's Caches to generate components passively, making this a vital tool. Clockwork Floors heal toxin damage in Servants standing on them."
tier = SCRIPTURE_SCRIPT
space_allowed = TRUE
primary_component = REPLICANT_ALLOY
sort_priority = 7
quickbind = TRUE
quickbind_desc = "Creates a Clockwork Proselytizer, which can convert various objects to Ratvarian variants."
quickbind_desc = "Creates a Replica Fabricator, which can convert various objects to Ratvarian variants."
//Function Call: Grants the invoker the ability to call forth a Ratvarian spear that deals significant damage to silicons.
@@ -9,7 +9,7 @@
anchored = 1
density = 1
resistance_flags = FIRE_PROOF | ACID_PROOF
var/can_be_repaired = TRUE //if a proselytizer can repair it
var/can_be_repaired = TRUE //if a fabricator can repair it
break_message = "<span class='warning'>The frog isn't a meme after all!</span>" //The message shown when a structure breaks
break_sound = 'sound/magic/clockwork/anima_fragment_death.ogg' //The sound played when a structure breaks
debris = list(/obj/item/clockwork/alloy_shards/large = 1, \
@@ -34,7 +34,7 @@
/obj/structure/destructible/clockwork/shell/cogscarab
name = "cogscarab shell"
desc = "A small brass shell with a cube-shaped receptable in its center. It gives off an aura of obsessive perfectionism."
clockwork_desc = "A dormant receptable that, when powered with a soul vessel, will become a weak construct with an inbuilt proselytizer."
clockwork_desc = "A dormant receptable that, when powered with a soul vessel, will become a weak construct with an inbuilt fabricator."
icon_state = "clockdrone_shell"
mobtype = /mob/living/simple_animal/drone/cogscarab
spawn_message = "'s eyes blink open, glowing bright red."
@@ -14,7 +14,7 @@
light_color = "#BE8700"
var/atom/prey //Whatever Ratvar is chasing
var/clashing = FALSE //If Ratvar is FUCKING FIGHTING WITH NAR-SIE
var/proselytize_range = 10
var/convert_range = 10
dangerous_possession = TRUE
/obj/structure/destructible/clockwork/massive/ratvar/Initialize()
@@ -58,10 +58,10 @@
/obj/structure/destructible/clockwork/massive/ratvar/process()
if(clashing) //I'm a bit occupied right now, thanks
return
for(var/I in circlerangeturfs(src, proselytize_range))
for(var/I in circlerangeturfs(src, convert_range))
var/turf/T = I
T.ratvar_act()
for(var/I in circleviewturfs(src, round(proselytize_range * 0.5)))
for(var/I in circleviewturfs(src, round(convert_range * 0.5)))
var/turf/T = I
T.ratvar_act(TRUE)
var/dir_to_step_in = pick(GLOB.cardinal)
+9 -3
View File
@@ -53,7 +53,6 @@
/datum/game_mode/cult/pre_setup()
cult_objectives += "sacrifice"
cult_objectives += "eldergod"
if(config.protect_roles_from_antagonist)
restricted_jobs += protected_jobs
@@ -102,6 +101,13 @@
GLOB.sac_image = reshape
else
message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!")
if(!GLOB.summon_spots.len)
while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES)
var/area/summon = pick(GLOB.sortedAreas - GLOB.summon_spots)
if((summon.z == ZLEVEL_STATION) && summon.valid_territory)
GLOB.summon_spots += summon
cult_objectives += "eldergod"
for(var/datum/mind/cult_mind in cultists_to_cult)
equip_cultist(cult_mind.current)
update_cult_icons_added(cult_mind)
@@ -239,11 +245,11 @@
SSblackbox.add_details("cult_objective","cult_sacrifice|FAIL")
if("eldergod")
if(!eldergod)
explanation = "Summon Nar-Sie. <span class='greenannounce'>Success!</span>"
explanation = "Summon Nar-Sie. The summoning can only be accomplished in [english_list(GLOB.summon_spots)].<span class='greenannounce'>Success!</span>"
SSblackbox.add_details("cult_objective","cult_narsie|SUCCESS")
SSticker.news_report = CULT_SUMMON
else
explanation = "Summon Nar-Sie. <span class='boldannounce'>Fail.</span>"
explanation = "Summon Nar-Sie. The summoning can only be accomplished in [english_list(GLOB.summon_spots)]<span class='boldannounce'>Fail.</span>"
SSblackbox.add_details("cult_objective","cult_narsie|FAIL")
SSticker.news_report = CULT_FAILURE
+88
View File
@@ -300,3 +300,91 @@
B.current.client.images -= GLOB.blood_target_image
QDEL_NULL(GLOB.blood_target_image)
GLOB.blood_target = null
//////// ELDRITCH PULSE /////////
/datum/action/innate/cult/master/pulse
name = "Eldritch Pulse"
desc = "Seize upon a fellow cultist or cult structure and teleport it to a nearby location."
button_icon_state = "arcane_barrage"
var/obj/effect/proc_holder/pulse/PM
var/cooldown = 0
var/base_cooldown = 150
var/throwing = FALSE
var/mob/living/throwee
/datum/action/innate/cult/master/pulse/New()
PM = new()
PM.attached_action = src
..()
/datum/action/innate/cult/master/pulse/IsAvailable()
if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER))
return FALSE
if(cooldown > world.time)
if(!PM.active)
owner << "<span class='cultlarge'><b>You need to wait [round((cooldown - world.time) * 0.1)] seconds before you can pulse again!</b></span>"
return FALSE
return ..()
/datum/action/innate/cult/master/pulse/Destroy()
QDEL_NULL(PM)
return ..()
/datum/action/innate/cult/master/pulse/Activate()
PM.toggle(owner) //the important bit
return TRUE
/obj/effect/proc_holder/pulse
active = FALSE
ranged_mousepointer = 'icons/effects/throw_target.dmi'
var/datum/action/innate/cult/master/pulse/attached_action
/obj/effect/proc_holder/pulse/Destroy()
QDEL_NULL(attached_action)
return ..()
/obj/effect/proc_holder/pulse/proc/toggle(mob/user)
if(active)
remove_ranged_ability("<span class='cult'>You cease your preparations...</span>")
attached_action.throwing = FALSE
else
add_ranged_ability(user, "<span class='cult'>You prepare to tear through the fabric of reality...</span>")
/obj/effect/proc_holder/pulse/InterceptClickOn(mob/living/caller, params, atom/target)
if(..())
return
if(ranged_ability_user.incapacitated())
remove_ranged_ability()
return
var/turf/T = get_turf(ranged_ability_user)
if(!isturf(T))
return FALSE
if(target in view(7, get_turf(ranged_ability_user)))
if((!(iscultist(target) || istype(target, /obj/structure/destructible/cult)) || target == caller) && !(attached_action.throwing))
return
if(!attached_action.throwing)
attached_action.throwing = TRUE
attached_action.throwee = target
ranged_ability_user << 'sound/weapons/thudswoosh.ogg'
to_chat(ranged_ability_user,"<span class='cult'><b>You reach through the veil with your mind's eye and seize [target]!</b></span>")
return
else
new /obj/effect/temp_visual/cult/sparks(get_turf(attached_action.throwee), ranged_ability_user.dir)
var/distance = get_dist(attached_action.throwee, target)
if(distance >= 16)
return
playsound(target,'sound/magic/exit_blood.ogg')
attached_action.throwee.Beam(target,icon_state="sendbeam",time=4)
attached_action.throwee.forceMove(get_turf(target))
new /obj/effect/temp_visual/cult/sparks(get_turf(target), ranged_ability_user.dir)
attached_action.throwing = FALSE
attached_action.cooldown = world.time + attached_action.base_cooldown
remove_mousepointer(ranged_ability_user.client)
remove_ranged_ability("<span class='cult'>A pulse of blood magic surges through you as you shift [attached_action.throwee] through time and space.</span>")
caller.update_action_buttons_icon()
addtimer(CALLBACK(caller, /mob.proc/update_action_buttons_icon), attached_action.base_cooldown)
+4 -1
View File
@@ -381,7 +381,7 @@
on_damage = 15
slot_flags = null
on = 1
var/charges = 3
var/charges = 5
/obj/item/device/flashlight/flare/culttorch/afterattack(atom/movable/A, mob/user, proximity)
if(!proximity)
@@ -408,6 +408,9 @@
to_chat(user, "<span class='cultitalic'>[cultist_to_receive] is not a follower of the Geometer!</span>")
log_game("Void torch failed - target was deconverted")
return
if(A in user.GetAllContents())
to_chat(user, "<span class='cultitalic'>[A] must be on a surface in order to teleport it!</span>")
return
to_chat(user, "<span class='cultitalic'>You ignite [A] with \the [src], turning it to ash, but through the torch's flames you see that [A] has reached [cultist_to_receive]!")
cultist_to_receive.put_in_hands(A)
charges--
+4 -9
View File
@@ -206,8 +206,8 @@ This file contains the arcane tome files.
if(!SSticker.mode.eldergod)
to_chat(user, "<span class='cultlarge'>\"I am already here. There is no need to try to summon me now.\"</span>")
return
if((loc.z && loc.z != ZLEVEL_STATION) || !A.blob_allowed)
to_chat(user, "<span class='warning'>The Geometer is not interested in lesser locations; the station is the prize!</span>")
if(!(A in GLOB.summon_spots))
to_chat(user, "<span class='cultlarge'>The Geometer can only be summoned where the veil is weak - in [english_list(GLOB.summon_spots)]!</span>")
return
var/confirm_final = alert(user, "This is the FINAL step to summon Nar-Sie; it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for Nar-Sie!", "No")
if(confirm_final == "No")
@@ -215,7 +215,8 @@ This file contains the arcane tome files.
return
Turf = get_turf(user)
A = get_area(src)
if(!check_rune_turf(Turf, user) || (loc.z && loc.z != ZLEVEL_STATION)|| !A.blob_allowed)
if(!(A in GLOB.summon_spots)) // Check again to make sure they didn't move
to_chat(user, "<span class='cultlarge'>The Geometer can only be summoned where the veil is weak - in [english_list(GLOB.summon_spots)]!</span>")
return
priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/AI/spanomalies.ogg')
for(var/B in spiral_range_turfs(1, user, 1))
@@ -248,8 +249,6 @@ This file contains the arcane tome files.
SSblackbox.add_details("cult_runes_scribed", R.cultist_name)
/obj/item/weapon/tome/proc/check_rune_turf(turf/T, mob/user)
var/area/A = get_area(T)
if(isspaceturf(T))
to_chat(user, "<span class='warning'>You cannot scribe runes in space!</span>")
return FALSE
@@ -262,8 +261,4 @@ This file contains the arcane tome files.
to_chat(user, "<span class='warning'>The veil is not weak enough here.")
return FALSE
if(istype(A, /area/shuttle))
to_chat(user, "<span class='warning'>Interference from hyperspace engines disrupts the Geometer's power on shuttles.</span>")
return FALSE
return TRUE
+2 -2
View File
@@ -446,7 +446,7 @@ structure_check() searches for nearby cultist structures required for the invoca
icon_state = "rune_large"
pixel_x = -32 //So the big ol' 96x96 sprite shows up right
pixel_y = -32
scribe_delay = 450 //how long the rune takes to create
scribe_delay = 500 //how long the rune takes to create
scribe_damage = 40.1 //how much damage you take doing it
var/used = FALSE
@@ -631,7 +631,7 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/spirit/examine(mob/user)
..()
if(affecting)
to_chat(user, "<span class='cultitalic'>A translucent field encases [user] above the rune!</span>")
to_chat(user, "<span class='cultitalic'>A translucent field encases [affecting] above the rune!</span>")
/obj/effect/rune/spirit/can_invoke(mob/living/user)
if(rune_in_use)
+1 -1
View File
@@ -9,7 +9,7 @@
S.update_icon()
S.power_change()
var/list/skipped_areas = list(/area/engine/engineering, /area/ai_monitored/turret_protected/ai)
var/list/skipped_areas = list(/area/engine/engineering, /area/engine/supermatter, /area/engine/atmospherics_engine, /area/ai_monitored/turret_protected/ai)
for(var/area/A in world)
if( !A.requires_power || A.always_unpowered )
+51 -16
View File
@@ -80,22 +80,20 @@
report = config.intercept
addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME)
if(SSdbcore.Connect())
var/sql
if(SSticker && SSticker.mode)
sql += "game_mode = '[SSticker.mode]'"
if(sql)
sql += ", "
if(GLOB.revdata.commit)
sql += "commit_hash = '[GLOB.revdata.commit]'"
if(sql)
var/datum/DBQuery/query_round_game_mode = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET [sql] WHERE id = [GLOB.round_id]")
query_round_game_mode.Execute()
if(SSdbcore.Connect())
var/sql
if(SSticker && SSticker.mode)
sql += "game_mode = '[SSticker.mode]'"
if(GLOB.revdata.originmastercommit)
if(sql)
sql += ", "
sql += "commit_hash = '[GLOB.revdata.originmastercommit]'"
if(sql)
var/datum/DBQuery/query_round_game_mode = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET [sql] WHERE id = [GLOB.round_id]")
query_round_game_mode.Execute()
if(report)
addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h))
generate_station_goals()
GLOB.start_state = new /datum/station_state()
GLOB.start_state.count(1)
return 1
@@ -239,11 +237,11 @@
if(ishuman(M))
if(!M.stat)
surviving_humans++
if(M.z == ZLEVEL_CENTCOM)
if(M.z == ZLEVEL_CENTCOM)
escaped_humans++
if(!M.stat)
surviving_total++
if(M.z == ZLEVEL_CENTCOM)
if(M.z == ZLEVEL_CENTCOM)
escaped_total++
@@ -265,6 +263,43 @@
send2irc("Server", "Round just ended.")
if(cult.len && !istype(SSticker.mode,/datum/game_mode/cult))
datum_cult_completion()
if(GLOB.borers.len)
var/borerwin = FALSE
var/borertext = "<br><font size=3><b>The borers were:</b></font>"
for(var/mob/living/simple_animal/borer/B in GLOB.borers)
if((B.key || B.controlling) && B.stat != DEAD)
borertext += "<br>[B.controlling ? B.victim.key : B.key] was [B.truename] ("
var/turf/location = get_turf(B)
if(location.z == ZLEVEL_CENTCOM && B.victim)
borertext += "escaped with host"
else
borertext += "failed"
borertext += ")"
to_chat(world, borertext)
var/total_borers = 0
for(var/mob/living/simple_animal/borer/B in GLOB.borers)
if((B.key || B.victim) && B.stat != DEAD)
total_borers++
if(total_borers)
var/total_borer_hosts = 0
for(var/mob/living/carbon/C in GLOB.mob_list)
var/mob/living/simple_animal/borer/D = C.has_brain_worms()
var/turf/location = get_turf(C)
if(location.z == ZLEVEL_CENTCOM && D && D.stat != DEAD)
total_borer_hosts++
if(GLOB.total_borer_hosts_needed <= total_borer_hosts)
borerwin = TRUE
to_chat(world, "<b>There were [total_borers] borers alive at round end!</b>")
to_chat(world, "<b>A total of [total_borer_hosts] borers with hosts escaped on the shuttle alive. The borers needed [GLOB.total_borer_hosts_needed] hosts to escape.</b>")
if(borerwin)
to_chat(world, "<b><font color='green'>The borers were successful!</font></b>")
else
to_chat(world, "<b><font color='red'>The borers have failed!</font></b>")
CHECK_TICK
return 0
@@ -565,4 +600,4 @@
/datum/game_mode/proc/declare_station_goal_completion()
for(var/V in station_goals)
var/datum/station_goal/G = V
G.print_result()
G.print_result()
+4
View File
@@ -1,5 +1,6 @@
#define DOM_BLOCKED_SPAM_CAP 6
#define DOM_REQUIRED_TURFS 30
#define DOM_HULK_HITS_REQUIRED 10
/obj/machinery/dominator
name = "dominator"
@@ -20,6 +21,9 @@
var/datum/effect_system/spark_spread/spark_system
var/obj/effect/countdown/dominator/countdown
/obj/machinery/dominator/hulk_damage()
return (max_integrity - integrity_failure) / DOM_HULK_HITS_REQUIRED
/proc/dominator_excessive_walls(atom/A)
var/open = 0
for(var/turf/T in view(3, A))
+12 -2
View File
@@ -62,7 +62,7 @@ GLOBAL_LIST_INIT(gang_outfit_pool, list(/obj/item/clothing/suit/jacket/leather,/
for(var/n in 1 to 3)
var/datum/mind/boss = pick(antag_candidates)
antag_candidates -= boss
G.bosses += boss
G.bosses[boss] = GANGSTER_BOSS_STARTING_INFLUENCE
boss.gang_datum = G
var/title
if(n == 1)
@@ -85,6 +85,7 @@ GLOBAL_LIST_INIT(gang_outfit_pool, list(/obj/item/clothing/suit/jacket/leather,/
sleep(rand(10,100))
for(var/datum/gang/G in gangs)
for(var/datum/mind/boss_mind in G.bosses)
G.bosses[boss_mind] = GANGSTER_BOSS_STARTING_INFLUENCE //Force influence to be put on it.
G.add_gang_hud(boss_mind)
forge_gang_objectives(boss_mind)
greet_gang(boss_mind)
@@ -170,7 +171,7 @@ GLOBAL_LIST_INIT(gang_outfit_pool, list(/obj/item/clothing/suit/jacket/leather,/
return 0
if(check && gangster_mind.current.isloyal()) //Check to see if the potential gangster is implanted
return 1
G.gangsters += gangster_mind
G.gangsters[gangster_mind] = GANGSTER_SOLDIER_STARTING_INFLUENCE
gangster_mind.gang_datum = G
if(check)
if(iscarbon(gangster_mind.current))
@@ -209,15 +210,24 @@ GLOBAL_LIST_INIT(gang_outfit_pool, list(/obj/item/clothing/suit/jacket/leather,/
if(!G.is_deconvertible && !remove_bosses)
return 0
if(gangster_mind in G.gangsters)
G.reclaim_points(G.gangsters[gangster_mind])
G.gangsters -= gangster_mind
removed = 1
if(remove_bosses && (gangster_mind in G.bosses))
G.reclaim_points(G.bosses[gangster_mind])
G.bosses -= gangster_mind
removed = 1
if(G.tags_by_mind[gangster_mind] && islist(G.tags_by_mind[gangster_mind]))
var/list/tags_cache = G.tags_by_mind[gangster_mind]
for(var/v in tags_cache)
var/obj/effect/decal/cleanable/crayon/gang/c = v
c.set_mind_owner(null)
G.tags_by_mind -= gangster_mind
if(!removed)
return 0
gangster_mind.special_role = null
gangster_mind.gang_datum = null
+87 -43
View File
@@ -8,6 +8,7 @@
var/list/datum/mind/gangsters = list() //gang B Members
var/list/datum/mind/bosses = list() //gang A Bosses
var/list/obj/item/device/gangtool/gangtools = list()
var/list/tags_by_mind = list() //Assoc list in format of tags_by_mind[mind_of_gangster] = list(tag1, tag2, tag3) where tags are the actual object decals.
var/style
var/fighting_style = "normal"
var/list/territory = list()
@@ -75,7 +76,7 @@
/datum/gang_item/clothing/hands,
/datum/gang_item/clothing/belt,
/datum/gang_item/weapon/shuriken,
/datum/gang_item/weapon/shuriken,
/datum/gang_item/weapon/switchblade,
/datum/gang_item/weapon/improvised,
/datum/gang_item/weapon/ammo/improvised_ammo,
@@ -202,9 +203,9 @@
return
var/added_names = ""
var/lost_names = ""
SSticker.mode.shuttle_check() // See if its time to start wrapping things up
//Re-add territories that were reclaimed, so if they got tagged over, they can still earn income if they tag it back before the next status report
var/list/reclaimed_territories = territory_new & territory_lost
territory |= reclaimed_territories
@@ -245,47 +246,90 @@
set_domination_time(new_time)
message += "<b>[seconds_remaining] seconds remain</b> in hostile takeover.<BR>"
else
for(var/obj/item/device/gangtool/G in gangtools)
var/pmessage = message
var/points_new = 0
if(istype(G, /obj/item/device/gangtool/soldier))
points_new = max(0,round(3 - G.points/10)) + (sbonus) + (LAZYLEN(G.tags)/2) // Soldier points
pmessage += "Your influence has increased by [round(sbonus)] from your gang holding [LAZYLEN(territory)] territories, and a bonus of [round(LAZYLEN(G.tags)/2)] for territories you have personally marked and kept intact.<BR>"
else
points_new = max(0,round(5 - G.points/10)) + LAZYLEN(territory) // Boss points, more focused on big picture
pmessage += "Your influence has increased by [round(points_new)] from your gang holding [territory.len] territories<BR>"
G.points += points_new
var/mob/living/carbon/human/ganger = get(G.loc, /mob/living)
var/points_newer = 0
var/static/inner = inner_outfit
var/static/outer = outer_outfit
if(ishuman(ganger) && ganger.mind in (gangsters|bosses))
for(var/obj/C in ganger.contents)
if(C.type == inner_outfit)
points_newer += 2
continue
if(C.type == outer_outfit)
points_newer += 2
continue
switch(C.type)
if(/obj/item/clothing/neck/necklace/dope)
points_newer += 2
if(/obj/item/clothing/head/collectable/petehat/gang)
points_newer += 4
if(/obj/item/clothing/shoes/gang)
points_newer += 6
if(/obj/item/clothing/mask/gskull)
points_newer += 5
if(/obj/item/clothing/gloves/gang)
points_newer += 3
if(/obj/item/weapon/storage/belt/military/gang)
points_newer += 4
if(points_newer)
G.points += points_newer
pmessage += "Your influential choice of clothing has further increased your influence by [points_newer] points.<BR>"
pmessage += "You now have <b>[G.points] influence</b>.<BR>"
to_chat(ganger, "<span class='notice'>\icon[G] [pmessage]</span>")
pay_territory_income_to_bosses()
pay_territory_income_to_soldiers(sbonus)
pay_all_clothing_bonuses()
announce_all_influence()
/datum/gang/proc/pay_all_clothing_bonuses()
for(var/datum/mind/mind in gangsters|bosses)
pay_clothing_bonus(mind)
/datum/gang/proc/pay_clothing_bonus(var/datum/mind/gangsta)
var/mob/living/carbon/human/gangbanger = gangsta.current
. = 0
if(!istype(gangbanger) || gangbanger.stat == DEAD) //Dead gangsters aren't influential at all!
return 0
var/static/inner = inner_outfit
var/static/outer = outer_outfit
for(var/obj/item/C in gangbanger.contents)
if(C.type == inner_outfit)
. += 2
continue
else if(C.type == outer_outfit)
. += 2
continue
. += C.gang_contraband_value()
adjust_influence(gangsta, .)
if(.)
announce_to_mind(gangsta, "<span class='notice'>Your influential choice of clothing has increased your influence by [.] points!</span>")
else
announce_to_mind(gangsta, "<span class='warning'>Unfortunately, you have not gained any additional influence from your drab, old, boring clothing. Learn to dress like a gangsta, bro!</span>") //Kek
/datum/gang/proc/pay_soldier_territory_income(datum/mind/soldier, sbonus = 0)
. = 0
. = max(0,round(3 - gangsters[soldier]/10)) + (sbonus) + (get_soldier_territories(soldier)/2)
adjust_influence(soldier, .)
/datum/gang/proc/get_soldier_territories(datum/mind/soldier)
if(!islist(tags_by_mind[soldier])) //They have no tagged territories!
return 0
var/list/tags = tags_by_mind[soldier]
return tags.len
/datum/gang/proc/pay_territory_income_to_soldiers(sbonus = 0)
for(var/datum/mind/soldier in gangsters)
var/returned = pay_soldier_territory_income(soldier)
if(!returned)
announce_to_mind(soldier, "<span class='warning'>You have not gained any influence from territories you personally tagged. Get to work, soldier!</span>")
else
announce_to_mind(soldier, "<span class='notice'>You have gained [returned] influence from [get_soldier_territories(soldier)] territories you have personally tagged.</span>")
/datum/gang/proc/announce_all_influence()
for(var/datum/mind/MG in bosses|gangsters)
announce_total_influence(MG)
/datum/gang/proc/pay_territory_income_to_bosses()
. = 0
for(var/datum/mind/boss_mind in bosses)
var/inc = max(0,round(5 - bosses[boss_mind]/10)) + LAZYLEN(territory)
. += inc
adjust_influence(boss_mind, inc)
announce_to_mind(boss_mind, "<span class='boldnotice'>Your influence has increased by [inc] from your gang holding [LAZYLEN(territory)] territories!</span>")
/datum/gang/proc/get_influence(datum/mind/gangster_mind)
if(gangster_mind in gangsters)
return gangsters[gangster_mind]
if(gangster_mind in bosses)
return bosses[gangster_mind]
/datum/gang/proc/adjust_influence(datum/mind/gangster_mind, amount)
if(gangster_mind in gangsters)
gangsters[gangster_mind] += amount
if(gangster_mind in bosses)
bosses[gangster_mind] += amount
/datum/gang/proc/announce_to_mind(datum/mind/gangster_mind, message)
if(gangster_mind.current && gangster_mind.current.stat != DEAD)
to_chat(gangster_mind.current, message)
/datum/gang/proc/announce_total_influence(datum/mind/gangster_mind)
announce_to_mind(gangster_mind, "<span class='boldnotice'>[name] Gang: You now have a total of [get_influence(gangster_mind)] influence!</span>")
/datum/gang/proc/reclaim_points(amount)
for(var/datum/mind/bawss in bosses)
adjust_influence(bawss, amount/bosses.len)
announce_to_mind(bawss, "<span class='notice'>[name] Gang: [amount/bosses.len] influence given from internal automatic restructuring.</span>")
//Multiverse
+33 -14
View File
@@ -11,7 +11,7 @@
if(check_canbuy && !can_buy(user, gang, gangtool))
return FALSE
var/real_cost = get_cost(user, gang, gangtool)
gangtool.points -= real_cost
gang.adjust_influence(user.mind, -real_cost)
spawn_item(user, gang, gangtool)
return TRUE
@@ -23,7 +23,7 @@
to_chat(user, spawn_msg)
/datum/gang_item/proc/can_buy(mob/living/carbon/user, datum/gang/gang, obj/item/device/gangtool/gangtool)
return gang && (gangtool.points >= get_cost(user, gang, gangtool)) && can_see(user, gang, gangtool)
return gang && (gang.get_influence(user.mind) >= get_cost(user, gang, gangtool)) && can_see(user, gang, gangtool)
/datum/gang_item/proc/can_see(mob/living/carbon/user, datum/gang/gang, obj/item/device/gangtool/gangtool)
return TRUE
@@ -111,17 +111,20 @@
/datum/gang_item/clothing/hat
name = "Pimp Hat"
id = "hat"
cost = 18
cost = 16
item_path = /obj/item/clothing/head/collectable/petehat/gang
/obj/item/clothing/head/collectable/petehat/gang
name = "pimpin' hat"
desc = "The undisputed king of style."
/obj/item/clothing/head/collectable/petehat/gang/gang_contraband_value()
return 4
/datum/gang_item/clothing/mask
name = "Golden Death Mask"
id = "mask"
cost = 20
cost = 18
item_path = /obj/item/clothing/mask/gskull
/obj/item/clothing/mask/gskull
@@ -129,11 +132,13 @@
icon_state = "gskull"
desc = "Strike terror, and envy, into the hearts of your enemies."
/obj/item/clothing/mask/gskull/gang_contraband_value()
return 5
/datum/gang_item/clothing/shoes
name = "Bling Boots"
id = "boots"
cost = 25
cost = 22
item_path = /obj/item/clothing/shoes/gang
/obj/item/clothing/shoes/gang
@@ -141,17 +146,19 @@
desc = "Stand aside peasants."
icon_state = "bling"
/obj/item/clothing/shoes/gang/gang_contraband_value()
return 6
/datum/gang_item/clothing/neck
name = "Gold Necklace"
id = "necklace"
cost = 10
cost = 9
item_path = /obj/item/clothing/neck/necklace/dope
/datum/gang_item/clothing/hands
name = "Decorative Brass Knuckles"
id = "hand"
cost = 12
cost = 11
item_path = /obj/item/clothing/gloves/gang
/obj/item/clothing/gloves/gang
@@ -160,10 +167,13 @@
icon_state = "knuckles"
w_class = 3
/obj/item/clothing/gloves/gang/gang_contraband_value()
return 3
/datum/gang_item/clothing/belt
name = "Badass Belt"
id = "belt"
cost = 15
cost = 13
item_path = /obj/item/weapon/storage/belt/military/gang
/obj/item/weapon/storage/belt/military/gang
@@ -173,7 +183,8 @@
desc = "The belt buckle simply reads 'BAMF'."
storage_slots = 1
/obj/item/weapon/storage/belt/military/gang/gang_contraband_value()
return 4
///////////////////
//WEAPONS
@@ -236,16 +247,24 @@
item_path = /obj/item/ammo_box/magazine/m10mm
/datum/gang_item/weapon/sniper
name = ".50cal Sniper Rifle"
name = "Black Market .50cal Sniper Rifle"
id = "sniper"
cost = 40
item_path = /obj/item/weapon/gun/ballistic/automatic/sniper_rifle
item_path = /obj/item/weapon/gun/ballistic/automatic/sniper_rifle/gang
/datum/gang_item/weapon/ammo/sniper_ammo
name = "Standard .50cal Sniper Rounds"
name = "Smuggled .50cal Sniper Rounds"
id = "sniper_ammo"
cost = 15
item_path = /obj/item/ammo_box/magazine/sniper_rounds
item_path = /obj/item/ammo_box/magazine/sniper_rounds/gang
/datum/gang_item/weapon/ammo/sleeper_ammo
name = "Illicit Tranquilizer Cartridges"
id = "sniper_ammo"
cost = 15
item_path = /obj/item/ammo_box/magazine/sniper_rounds/gang/sleeper
/datum/gang_item/weapon/machinegun
name = "Mounted Machine Gun"
+4 -7
View File
@@ -15,7 +15,6 @@
var/outfits = 2
var/free_pen = 0
var/promotable = 0
var/points = 15
var/list/tags = list()
/obj/item/device/gangtool/Initialize() //Initialize supply point income if it hasn't already been started
@@ -50,7 +49,7 @@
var/isboss = (user.mind == gang.bosses[1])
dat += "Registration: <B>[gang.name] Gang [isboss ? "Boss" : "Lieutenant"]</B><br>"
dat += "Organization Size: <B>[gang.gangsters.len + gang.bosses.len]</B> | Station Control: <B>[round((gang.territory.len/GLOB.start_state.num_territories)*100, 1)]%</B><br>"
dat += "Your Influence: <B>[points]</B><br>"
dat += "Your Influence: <B>[gang.get_influence(user.mind)]</B><br>"
dat += "Time until Influence grows: <B>[time2text(SSticker.mode.gang_points.next_point_time - world.time, "mm:ss")]</B><br>"
dat += "<hr>"
@@ -147,8 +146,9 @@
gang.gangtools += src
icon_state = "gangtool-[gang.color]"
if(!(user.mind in gang.bosses))
var/cached_influence = gang.gangsters[user.mind]
SSticker.mode.remove_gangster(user.mind, 0, 2)
gang.bosses += user.mind
gang.bosses[user.mind] = cached_influence
user.mind.gang_datum = gang
user.mind.special_role = "[gang.name] Gang Lieutenant"
gang.add_gang_hud(user.mind)
@@ -246,9 +246,6 @@
///////////// Internal tool used by gang regulars ///////////
/obj/item/device/gangtool/soldier
points = 5
/obj/item/device/gangtool/soldier/New(mob/user)
. = ..()
gang = user.mind.gang_datum
@@ -264,7 +261,7 @@
dat += "<center><font color='red'>Takeover In Progress:<br><B>[gang.domination_time_remaining()] seconds remain</B></font></center>"
dat += "Registration: <B>[gang.name] - Foot Soldier</B><br>"
dat += "Organization Size: <B>[gang.gangsters.len + gang.bosses.len]</B> | Station Control: <B>[round((gang.territory.len/GLOB.start_state.num_territories)*100, 1)]%</B><br>"
dat += "Your Influence: <B>[points]</B><br>"
dat += "Your Influence: <B>[gang.get_influence(user.mind)]</B><br>"
if(LAZYLEN(tags))
dat += "Your tags generate bonus influence for you.<br> You have tagged the following territories:"
for(var/obj/effect/decal/cleanable/crayon/gang/T in tags)
+25 -22
View File
@@ -1,3 +1,4 @@
#define DEFAULT_DOOMSDAY_TIMER 4500
/datum/AI_Module
var/uses = 0
var/module_name
@@ -37,12 +38,13 @@
to_chat(src, "<span class='notice'>Doomsday device armed.</span>")
priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", 'sound/AI/aimalf.ogg')
set_security_level("delta")
nuking = 1
var/obj/machinery/doomsday_device/DOOM = new /obj/machinery/doomsday_device(src)
nuking = TRUE
var/obj/machinery/doomsday_device/DOOM = new (src)
doomsday_device = DOOM
doomsday_device.start()
verbs -= /mob/living/silicon/ai/proc/nuke_station
for(var/obj/item/weapon/pinpointer/P in GLOB.pinpointer_list)
for(var/pinpointer in GLOB.pinpointer_list)
var/obj/item/weapon/pinpointer/P = pinpointer
P.switch_mode_to(TRACK_MALF_AI) //Pinpointers start tracking the AI wherever it goes
/obj/machinery/doomsday_device
@@ -50,34 +52,32 @@
name = "doomsday device"
icon_state = "nuclearbomb_base"
desc = "A weapon which disintegrates all organic life in a large area."
anchored = 1
density = 1
anchored = TRUE
density = TRUE
verb_exclaim = "blares"
var/timing = FALSE
var/default_timer = 4500
var/obj/effect/countdown/doomsday/countdown
var/detonation_timer
var/list/milestones = list()
var/list/milestones
/obj/machinery/doomsday_device/New()
..()
/obj/machinery/doomsday_device/Initialize()
. = ..()
countdown = new(src)
milestones = list()
/obj/machinery/doomsday_device/Destroy()
if(countdown)
qdel(countdown)
countdown = null
QDEL_NULL(countdown)
STOP_PROCESSING(SSfastprocess, src)
SSshuttle.clearHostileEnvironment(src)
SSmapping.remove_nuke_threat(src)
for(var/A in GLOB.ai_list)
var/mob/living/silicon/ai/Mlf = A
if(Mlf.doomsday_device == src)
Mlf.doomsday_device = null
. = ..()
var/mob/living/silicon/ai/AI = A
if(AI.doomsday_device == src)
AI.doomsday_device = null
return ..()
/obj/machinery/doomsday_device/proc/start()
detonation_timer = world.time + default_timer
detonation_timer = world.time + DEFAULT_DOOMSDAY_TIMER
timing = TRUE
countdown.start()
START_PROCESSING(SSfastprocess, src)
@@ -90,24 +90,24 @@
/obj/machinery/doomsday_device/process()
var/turf/T = get_turf(src)
if(!T || T.z != ZLEVEL_STATION)
minor_announce("DOOMSDAY DEVICE OUT OF STATION RANGE, ABORTING", "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4", 1)
minor_announce("DOOMSDAY DEVICE OUT OF STATION RANGE, ABORTING", "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4", TRUE)
SSshuttle.clearHostileEnvironment(src)
qdel(src)
return
if(!timing)
STOP_PROCESSING(SSfastprocess, src)
return
var/sec_left = seconds_remaining()
if(sec_left <= 0)
if(!sec_left)
timing = FALSE
detonate(T.z)
else
var/key = num2text(sec_left)
if(!(sec_left % 60) && !(key in milestones))
milestones[key] = TRUE
var/message = "[key] SECONDS UNTIL DOOMSDAY DEVICE ACTIVATION!"
minor_announce(message, "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4", 1)
minor_announce("[key] SECONDS UNTIL DOOMSDAY DEVICE ACTIVATION!", "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4", TRUE)
/obj/machinery/doomsday_device/proc/detonate(z_level = 1)
/obj/machinery/doomsday_device/proc/detonate(z_level = ZLEVEL_STATION)
for(var/mob/M in GLOB.player_list)
M << 'sound/machines/Alarm.ogg'
sleep(100)
@@ -604,3 +604,6 @@
eyeobj.relay_speech = TRUE
to_chat(src, "<span class='notice'>OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online.</span>")
verbs -= /mob/living/silicon/ai/proc/surveillance
#undef DEFAULT_DOOMSDAY_TIMER
@@ -2,7 +2,6 @@
name = "Human Observation Console"
var/team = 0
networks = list("SS13","Abductor")
off_action = new/datum/action/innate/camera_off/abductor //specific datum
var/datum/action/innate/teleport_in/tele_in_action = new
var/datum/action/innate/teleport_out/tele_out_action = new
var/datum/action/innate/teleport_self/tele_self_action = new
@@ -23,29 +22,37 @@
eyeobj.icon_state = "camera_target"
/obj/machinery/computer/camera_advanced/abductor/GrantActions(mob/living/carbon/user)
off_action.target = user
off_action.Grant(user)
..()
jump_action.target = user
jump_action.Grant(user)
//TODO : add null checks
tele_in_action.target = console.pad
tele_in_action.Grant(user)
if(tele_in_action)
tele_in_action.target = console.pad
tele_in_action.Grant(user)
actions += tele_in_action
tele_out_action.target = console
tele_out_action.Grant(user)
if(tele_out_action)
tele_out_action.target = console
tele_out_action.Grant(user)
actions += tele_out_action
tele_self_action.target = console.pad
tele_self_action.Grant(user)
if(tele_self_action)
tele_self_action.target = console.pad
tele_self_action.Grant(user)
actions += tele_self_action
vest_mode_action.target = console
vest_mode_action.Grant(user)
if(vest_mode_action)
vest_mode_action.target = console
vest_mode_action.Grant(user)
actions += vest_mode_action
vest_disguise_action.target = console
vest_disguise_action.Grant(user)
if(vest_disguise_action)
vest_disguise_action.target = console
vest_disguise_action.Grant(user)
actions += vest_disguise_action
set_droppoint_action.target = console
set_droppoint_action.Grant(user)
if(set_droppoint_action)
set_droppoint_action.target = console
set_droppoint_action.Grant(user)
actions += set_droppoint_action
/obj/machinery/computer/camera_advanced/abductor/proc/IsScientist(mob/living/carbon/human/H)
var/datum/species/abductor/S = H.dna.species
@@ -56,30 +63,6 @@
return
return ..()
/datum/action/innate/camera_off/abductor/Activate()
if(!target || !iscarbon(target))
return
var/mob/living/carbon/C = target
var/mob/camera/aiEye/remote/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/abductor/origin = remote_eye.origin
origin.current_user = null
origin.jump_action.Remove(C)
origin.tele_in_action.Remove(C)
origin.tele_out_action.Remove(C)
origin.tele_self_action.Remove(C)
origin.vest_mode_action.Remove(C)
origin.vest_disguise_action.Remove(C)
origin.set_droppoint_action.Remove(C)
C.reset_perspective(null)
if(C.client)
C.client.images -= remote_eye.user_image
for(var/datum/camerachunk/chunk in remote_eye.visibleCameraChunks)
chunk.remove(remote_eye)
remote_eye.eye_user = null
C.remote_control = null
C.unset_machine()
Remove(C)
/datum/action/innate/teleport_in
name = "Send To"
button_icon_state = "beam_down"
+1 -1
View File
@@ -43,7 +43,7 @@
/datum/objective_item/steal/capmedal
name = "the medal of captaincy"
targetitem = /obj/item/clothing/tie/medal/gold/captain
targetitem = /obj/item/clothing/accessory/medal/gold/captain
difficulty = 5
excludefromjob = list("Captain")
+1 -1
View File
@@ -243,7 +243,7 @@
if(!is_gangster(user))
var/datum/gang/multiverse/G = new(src, "[user.real_name]")
SSticker.mode.gangs += G
G.bosses += user.mind
G.bosses[user.mind] = 0
G.add_gang_hud(user.mind)
user.mind.gang_datum = G
to_chat(user, "<span class='warning'><B>With your new found power you could easily conquer the station!</B></span>")
+1 -2
View File
@@ -106,10 +106,9 @@
name = "Fireball"
spell_type = /obj/effect/proc_holder/spell/aimed/fireball
/*
/datum/spellbook_entry/rod_form
name = "Rod Form"
spell_type = /obj/effect/proc_holder/spell/targeted/rod_form */
spell_type = /obj/effect/proc_holder/spell/targeted/rod_form
/datum/spellbook_entry/magicm
name = "Magic Missile"
+26 -89
View File
@@ -1,56 +1,35 @@
/obj/machinery/ai_slipper
name = "\improper AI liquid dispenser"
name = "foam dispenser"
desc = "A remotely-activatable dispenser for crowd-controlling foam."
icon = 'icons/obj/device.dmi'
icon_state = "ai-slipper0"
layer = PROJECTILE_HIT_THRESHHOLD_LAYER
anchored = 1
anchored = TRUE
obj_integrity = 200
max_integrity = 200
armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30)
var/uses = 20
var/disabled = 1
var/lethal = 0
var/locked = 1
var/cooldown_time = 0
var/cooldown_timeleft = 0
var/cooldown_on = 0
var/cooldown = 0
var/cooldown_time = 100
req_access = list(GLOB.access_ai_upload)
/obj/machinery/ai_slipper/examine(mob/user)
..()
to_chat(user, "<span class='notice'>It has <b>[uses]</b> uses of foam remaining.</span>")
/obj/machinery/ai_slipper/power_change()
if(stat & BROKEN)
return
else
if( powered() )
if(powered())
stat &= ~NOPOWER
else
icon_state = "ai-slipper0"
stat |= NOPOWER
/obj/machinery/ai_slipper/proc/setState(enabled, uses)
src.disabled = disabled
src.uses = uses
src.power_change()
/obj/machinery/ai_slipper/attackby(obj/item/weapon/W, mob/user, params)
if(stat & (NOPOWER|BROKEN))
return
if (issilicon(user))
return src.attack_hand(user)
else // trying to unlock the interface
if (src.allowed(user))
locked = !locked
to_chat(user, "<span class='notice'>You [ locked ? "lock" : "unlock"] the device.</span>")
if (locked)
if (user.machine==src)
user.unset_machine()
user << browse(null, "window=ai_slipper")
else
if (user.machine==src)
src.attack_hand(user)
if((stat & (NOPOWER|BROKEN)) || cooldown_time > world.time || !uses)
icon_state = "ai-slipper0"
else
to_chat(user, "<span class='danger'>Access denied.</span>")
icon_state = "ai-slipper1"
/obj/machinery/ai_slipper/attack_ai(mob/user)
return attack_hand(user)
@@ -58,60 +37,18 @@
/obj/machinery/ai_slipper/attack_hand(mob/user)
if(stat & (NOPOWER|BROKEN))
return
if ( (get_dist(src, user) > 1 ))
if (!(issilicon(user) || IsAdminGhost(user)))
to_chat(user, text("Too far away."))
user.unset_machine()
user << browse(null, "window=ai_slipper")
return
user.set_machine(src)
var/area/A = get_area(src)
var/t = "<TT><B>AI Liquid Dispenser</B> ([format_text(A.name)])<HR>"
if(locked && (!(issilicon(user) || IsAdminGhost(user))))
t += "<I>(Swipe ID card to unlock control panel.)</I><BR>"
else
t += "Dispenser [disabled?"deactivated":"activated"] - <A href='?src=\ref[src];toggleOn=1'>[disabled?"Enable":"Disable"]?</a><br>\n"
t += "Uses Left: [uses]. <A href='?src=\ref[src];toggleUse=1'>Activate the dispenser?</A><br>\n"
user << browse(t, "window=computer;size=575x450")
onclose(user, "computer")
/obj/machinery/ai_slipper/Topic(href, href_list)
if(..())
if(!allowed(user))
to_chat(user, "<span class='danger'>Access denied.</span>")
return
if (src.locked)
if(!(issilicon(usr)|| IsAdminGhost(usr)))
to_chat(usr, "Control panel is locked!")
return
if (href_list["toggleOn"])
src.disabled = !src.disabled
icon_state = src.disabled? "ai-slipper0":"ai-slipper1"
if (href_list["toggleUse"])
if(cooldown_on || disabled)
return
else
new /obj/effect/particle_effect/foam(loc)
src.uses--
cooldown_on = 1
cooldown_time = world.timeofday + 100
slip_process()
return
src.attack_hand(usr)
/obj/machinery/ai_slipper/proc/slip_process()
while(cooldown_time - world.timeofday > 0)
var/ticksleft = cooldown_time - world.timeofday
if(ticksleft > 1e5)
cooldown_time = world.timeofday + 10 // midnight rollover
cooldown_timeleft = (ticksleft / 10)
sleep(5)
if (uses <= 0)
if(!uses)
to_chat(user, "<span class='danger'>[src] is out of foam and cannot be activated.</span>")
return
if(cooldown_time > world.time)
to_chat(user, "<span class='danger'>[src] cannot be activated for another <b>[round((world.time - cooldown_time) * 0.1)]</b> second\s.</span>")
return
if (uses >= 0)
cooldown_on = 0
src.power_change()
new /obj/effect/particle_effect/foam(loc)
uses--
to_chat(user, "<span class='notice'>You activate [src]. It now has <b>[uses]</b> uses of foam remaining.</span>")
cooldown = world.time + cooldown_time
power_change()
addtimer(CALLBACK(src, .proc/power_change), cooldown_time)
+2 -1
View File
@@ -159,9 +159,10 @@
else if(istype(W, /obj/item/stack/sheet/mineral/plasma))
if(!isEmpProof())
var/obj/item/stack/sheet/mineral/plasma/P = W
upgradeEmpProof()
to_chat(user, "[msg]")
qdel(W)
P.use(1)
else
to_chat(user, "[msg2]")
return
+1 -1
View File
@@ -71,7 +71,7 @@
/obj/machinery/cell_charger/proc/removecell()
charging.updateicon()
charging.update_icon()
charging = null
chargelevel = -1
updateicon()
+40 -21
View File
@@ -9,6 +9,7 @@
var/list/networks = list("SS13")
var/datum/action/innate/camera_off/off_action = new
var/datum/action/innate/camera_jump/jump_action = new
var/list/actions = list()
light_color = LIGHT_COLOR_RED
@@ -17,10 +18,31 @@
eyeobj.origin = src
/obj/machinery/computer/camera_advanced/proc/GrantActions(mob/living/user)
off_action.target = user
off_action.Grant(user)
jump_action.target = user
jump_action.Grant(user)
if(off_action)
off_action.target = user
off_action.Grant(user)
actions += off_action
if(jump_action)
jump_action.target = user
jump_action.Grant(user)
actions += jump_action
/obj/machinery/computer/camera_advanced/proc/remove_eye_control(mob/living/user)
if(!user)
return
for(var/V in actions)
var/datum/action/A = V
A.Remove(user)
if(user.client)
user.reset_perspective(null)
eyeobj.RemoveImages()
eyeobj.eye_user = null
user.remote_control = null
current_user = null
user.unset_machine()
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
/obj/machinery/computer/camera_advanced/check_eye(mob/user)
if( (stat & (NOPOWER|BROKEN)) || (!Adjacent(user) && !user.has_unlimited_silicon_privilege) || user.eye_blind || user.incapacitated() )
@@ -35,7 +57,7 @@
/obj/machinery/computer/camera_advanced/on_unset_machine(mob/M)
if(M == current_user)
off_action.Activate()
remove_eye_control(M)
/obj/machinery/computer/camera_advanced/attack_hand(mob/user)
if(current_user)
@@ -69,7 +91,7 @@
/obj/machinery/computer/camera_advanced/attack_robot(mob/user)
return attack_hand(user)
obj/machinery/computer/camera_advanced/attack_ai(mob/user)
/obj/machinery/computer/camera_advanced/attack_ai(mob/user)
return //AIs would need to disable their own camera procs to use the console safely. Bugs happen otherwise.
@@ -92,13 +114,20 @@ obj/machinery/computer/camera_advanced/attack_ai(mob/user)
var/eye_initialized = 0
var/visible_icon = 0
var/image/user_image = null
/mob/camera/aiEye/remote/update_remote_sight(mob/living/user)
user.see_invisible = SEE_INVISIBLE_LIVING //can't see ghosts through cameras
user.sight = 0
user.see_in_dark = 2
return 1
/mob/camera/aiEye/remote/RemoveImages()
..()
if(visible_icon)
var/client/C = GetViewerClient()
if(C)
C.images -= user_image
/mob/camera/aiEye/remote/Destroy()
eye_user = null
origin = null
@@ -115,7 +144,8 @@ obj/machinery/computer/camera_advanced/attack_ai(mob/user)
return
T = get_turf(T)
loc = T
GLOB.cameranet.visibility(src)
if(use_static)
GLOB.cameranet.visibility(src)
if(visible_icon)
if(eye_user.client)
eye_user.client.images -= user_image
@@ -149,19 +179,8 @@ obj/machinery/computer/camera_advanced/attack_ai(mob/user)
return
var/mob/living/C = target
var/mob/camera/aiEye/remote/remote_eye = C.remote_control
remote_eye.origin.current_user = null
remote_eye.origin.jump_action.Remove(C)
if(C.client)
C.reset_perspective(null)
if(remote_eye.visible_icon)
C.client.images -= remote_eye.user_image
for(var/datum/camerachunk/chunk in remote_eye.visibleCameraChunks)
chunk.remove(remote_eye)
remote_eye.eye_user = null
C.remote_control = null
C.unset_machine()
Remove(C)
playsound(remote_eye.origin, 'sound/machines/terminal_off.ogg', 25, 0)
var/obj/machinery/computer/camera_advanced/console = remote_eye.origin
console.remove_eye_control(target)
/datum/action/innate/camera_jump
name = "Jump To Camera"
+1 -1
View File
@@ -1,7 +1,7 @@
// The communications computer
/obj/machinery/computer/communications
name = "communications console"
desc = "This can be used for various important functions. Still under developement."
desc = "A console used for high-priority announcements and emergencies."
icon_screen = "comm"
icon_keyboard = "tech_key"
req_access = list(GLOB.access_heads)
+5 -5
View File
@@ -332,7 +332,7 @@
src.active2.fields["mi_dis"] = t1
if("mi_dis_d")
if(active2)
var/t1 = stripped_multiline_input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], null)
var/t1 = stripped_input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], null)
if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
return
src.active2.fields["mi_dis_d"] = t1
@@ -344,7 +344,7 @@
src.active2.fields["ma_dis"] = t1
if("ma_dis_d")
if(active2)
var/t1 = stripped_multiline_input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], null)
var/t1 = stripped_input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], null)
if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
return
src.active2.fields["ma_dis_d"] = t1
@@ -356,7 +356,7 @@
src.active2.fields["alg"] = t1
if("alg_d")
if(active2)
var/t1 = stripped_multiline_input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], null)
var/t1 = stripped_input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], null)
if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
return
src.active2.fields["alg_d"] = t1
@@ -368,13 +368,13 @@
src.active2.fields["cdi"] = t1
if("cdi_d")
if(active2)
var/t1 = stripped_multiline_input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], null)
var/t1 = stripped_input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], null)
if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
return
src.active2.fields["cdi_d"] = t1
if("notes")
if(active2)
var/t1 = stripped_multiline_input("Please summarize notes:", "Med. records", src.active2.fields["notes"], null)
var/t1 = stripped_input("Please summarize notes:", "Med. records", src.active2.fields["notes"], null)
if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
return
src.active2.fields["notes"] = t1
+10 -2
View File
@@ -23,6 +23,14 @@
light_color = LIGHT_COLOR_RED
/obj/machinery/computer/secure_data/laptop
name = "security laptop"
desc = "A cheap Nanotrasen security laptop, it functions as a security records console. It's bolted to the table."
icon_state = "laptop"
icon_screen = "seclaptop"
icon_keyboard = "laptop_key"
clockwork = TRUE //it'd look weird
/obj/machinery/computer/secure_data/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/weapon/card/id))
if(!scan)
@@ -620,7 +628,7 @@ What a mess.*/
if("mi_crim_add")
if(istype(active1, /datum/data/record))
var/t1 = stripped_input(usr, "Please input minor crime names:", "Secure. records", "", null)
var/t2 = stripped_multiline_input(usr, "Please input minor crime details:", "Secure. records", "", null)
var/t2 = stripped_input(usr, "Please input minor crime details:", "Secure. records", "", null)
if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
return
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, worldtime2text())
@@ -634,7 +642,7 @@ What a mess.*/
if("ma_crim_add")
if(istype(active1, /datum/data/record))
var/t1 = stripped_input(usr, "Please input major crime names:", "Secure. records", "", null)
var/t2 = stripped_multiline_input(usr, "Please input major crime details:", "Secure. records", "", null)
var/t2 = stripped_input(usr, "Please input major crime details:", "Secure. records", "", null)
if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
return
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, worldtime2text())
+53
View File
@@ -72,6 +72,7 @@
var/hasShocked = 0 //Prevents multiple shocks from happening
autoclose = 1
var/obj/item/device/doorCharge/charge = null //If applied, causes an explosion upon opening the door
var/obj/item/weapon/note //Any papers pinned to the airlock
var/detonated = 0
var/doorOpen = 'sound/machines/airlock.ogg'
var/doorClose = 'sound/machines/AirlockClose.ogg'
@@ -82,6 +83,7 @@
var/airlock_material = null //material of inner filling; if its an airlock with glass, this should be set to "glass"
var/overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi'
var/note_overlay_file = 'icons/obj/doors/airlocks/station/overlays.dmi' //Used for papers and photos pinned to the airlock
var/cyclelinkeddir = 0
var/obj/machinery/door/airlock/cyclelinkedairlock
@@ -213,8 +215,14 @@
if(id_tag)
for(var/obj/machinery/doorButtons/D in GLOB.machines)
D.removeMe(src)
qdel(note)
return ..()
/obj/machinery/door/airlock/handle_atom_del(atom/A)
if(A == note)
note = null
update_icon()
/obj/machinery/door/airlock/bumpopen(mob/living/user) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite
if(!issilicon(usr))
if(src.isElectrified())
@@ -369,6 +377,8 @@
var/mutable_appearance/weld_overlay
var/mutable_appearance/damag_overlay
var/mutable_appearance/sparks_overlay
var/mutable_appearance/note_overlay
var/notetype = note_type()
switch(state)
if(AIRLOCK_CLOSED)
@@ -393,6 +403,8 @@
lights_overlay = get_airlock_overlay("lights_bolts", overlays_file)
else if(emergency)
lights_overlay = get_airlock_overlay("lights_emergency", overlays_file)
if(note)
note_overlay = get_airlock_overlay(notetype, note_overlay_file)
if(AIRLOCK_DENY)
if(!hasPower())
@@ -414,6 +426,8 @@
if(welded)
weld_overlay = get_airlock_overlay("welded", overlays_file)
lights_overlay = get_airlock_overlay("lights_denied", overlays_file)
if(note)
note_overlay = get_airlock_overlay(notetype, note_overlay_file)
if(AIRLOCK_EMAG)
frame_overlay = get_airlock_overlay("closed", icon)
@@ -433,6 +447,8 @@
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file)
if(welded)
weld_overlay = get_airlock_overlay("welded", overlays_file)
if(note)
note_overlay = get_airlock_overlay(notetype, note_overlay_file)
if(AIRLOCK_CLOSING)
frame_overlay = get_airlock_overlay("closing", icon)
@@ -447,6 +463,8 @@
panel_overlay = get_airlock_overlay("panel_closing_protected", overlays_file)
else
panel_overlay = get_airlock_overlay("panel_closing", overlays_file)
if(note)
note_overlay = get_airlock_overlay("[notetype]_closing", note_overlay_file)
if(AIRLOCK_OPEN)
frame_overlay = get_airlock_overlay("open", icon)
@@ -461,6 +479,8 @@
panel_overlay = get_airlock_overlay("panel_open", overlays_file)
if(obj_integrity < (0.75 * max_integrity))
damag_overlay = get_airlock_overlay("sparks_open", overlays_file)
if(note)
note_overlay = get_airlock_overlay("[notetype]_open", note_overlay_file)
if(AIRLOCK_OPENING)
frame_overlay = get_airlock_overlay("opening", icon)
@@ -475,6 +495,8 @@
panel_overlay = get_airlock_overlay("panel_opening_protected", overlays_file)
else
panel_overlay = get_airlock_overlay("panel_opening", overlays_file)
if(note)
note_overlay = get_airlock_overlay("[notetype]_opening", note_overlay_file)
cut_overlays()
add_overlay(frame_overlay)
@@ -484,6 +506,7 @@
add_overlay(weld_overlay)
add_overlay(sparks_overlay)
add_overlay(damag_overlay)
add_overlay(note_overlay)
/proc/get_airlock_overlay(icon_state, icon_file)
var/obj/machinery/door/airlock/A
@@ -512,6 +535,12 @@
to_chat(user, "<span class='warning'>The maintenance panel seems haphazardly fastened.</span>")
if(charge && panel_open)
to_chat(user, "<span class='warning'>Something is wired up to the airlock's electronics!</span>")
if(note)
if(!in_range(user, src))
to_chat(user, "There's a [note.name] pinned to the front. You can't read it from here.")
else
to_chat(user, "There's a [note.name] pinned to the front...")
note.examine(user)
if(panel_open)
switch(security_level)
@@ -1094,6 +1123,12 @@
to_chat(user, "<span class='notice'>You [panel_open ? "open":"close"] the maintenance panel of the airlock.</span>")
playsound(src.loc, C.usesound, 50, 1)
src.update_icon()
else if(istype(C, /obj/item/weapon/wirecutters) && note)
user.visible_message("<span class='notice'>[user] cuts down [note] from [src].</span>", "<span class='notice'>You remove [note] from [src].</span>")
playsound(src, 'sound/items/Wirecutter.ogg', 50, 1)
note.forceMove(get_turf(user))
note = null
update_icon()
else if(is_wire_tool(C))
return attack_hand(user)
else if(istype(C, /obj/item/weapon/pai_cable))
@@ -1119,6 +1154,16 @@
update_icon()
C.forceMove(src)
charge = C
else if(istype(C, /obj/item/weapon/paper) || istype(C, /obj/item/weapon/photo))
if(note)
to_chat(user, "<span class='warning'>There's already something pinned to this airlock! Use wirecutters to remove it.<spa>")
return
if(!user.transferItemToLoc(C, src))
to_chat(user, "<span class='warning'>For some reason, you can't attach [C]!</span>")
return
user.visible_message("<span class='notice'>[user] pins [C] to [src].</span>", "<span class='notice'>You pin [C] to [src].</span>")
note = C
update_icon()
else
return ..()
@@ -1550,6 +1595,14 @@
return TRUE
return FALSE
/obj/machinery/door/airlock/proc/note_type() //Returns a string representing the type of note pinned to this airlock
if(!note)
return
else if(istype(note, /obj/item/weapon/paper))
return "note"
else if(istype(note, /obj/item/weapon/photo))
return "photo"
#undef AIRLOCK_CLOSED
#undef AIRLOCK_CLOSING
#undef AIRLOCK_OPEN
@@ -252,6 +252,7 @@
name = "external airlock"
icon = 'icons/obj/doors/airlocks/external/external.dmi'
overlays_file = 'icons/obj/doors/airlocks/external/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/external/overlays.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_ext
explosion_block = 1
@@ -271,6 +272,7 @@
/obj/machinery/door/airlock/centcom
icon = 'icons/obj/doors/airlocks/centcom/centcom.dmi'
overlays_file = 'icons/obj/doors/airlocks/centcom/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/centcom/overlays.dmi'
opacity = 1
assemblytype = /obj/structure/door_assembly/door_assembly_centcom
normal_integrity = 1000
@@ -286,6 +288,7 @@
name = "vault door"
icon = 'icons/obj/doors/airlocks/vault/vault.dmi'
overlays_file = 'icons/obj/doors/airlocks/vault/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/vault/overlays.dmi'
opacity = 1
assemblytype = /obj/structure/door_assembly/door_assembly_vault
explosion_block = 2
@@ -301,6 +304,7 @@
name = "airtight hatch"
icon = 'icons/obj/doors/airlocks/hatch/centcom.dmi'
overlays_file = 'icons/obj/doors/airlocks/hatch/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/hatch/overlays.dmi'
opacity = 1
assemblytype = /obj/structure/door_assembly/door_assembly_hatch
@@ -308,6 +312,7 @@
name = "maintenance hatch"
icon = 'icons/obj/doors/airlocks/hatch/maintenance.dmi'
overlays_file = 'icons/obj/doors/airlocks/hatch/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/hatch/overlays.dmi'
opacity = 1
assemblytype = /obj/structure/door_assembly/door_assembly_mhatch
@@ -342,6 +347,7 @@
desc = "With humanity's current technological level, it could take years to hack this advanced airlock... or maybe we should give a screwdriver a try?"
icon = 'icons/obj/doors/airlocks/abductor/abductor_airlock.dmi'
overlays_file = 'icons/obj/doors/airlocks/abductor/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/abductor/overlays.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_abductor
damage_deflection = 30
opacity = 1
@@ -549,6 +555,7 @@
name = "large glass airlock"
icon = 'icons/obj/doors/airlocks/glass_large/glass_large.dmi'
overlays_file = 'icons/obj/doors/airlocks/glass_large/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/glass_large/overlays.dmi'
opacity = 0
assemblytype = null
glass = 1
+10 -2
View File
@@ -12,7 +12,7 @@
max_integrity = 350
armor = list(melee = 30, bullet = 30, laser = 20, energy = 20, bomb = 10, bio = 100, rad = 100, fire = 80, acid = 70)
CanAtmosPass = ATMOS_PASS_DENSITY
flags = PREVENT_CLICK_UNDER
flags = PREVENT_CLICK_UNDER
var/secondsElectrified = 0
var/shockedby = list()
@@ -32,6 +32,7 @@
var/auto_close //TO BE REMOVED, no longer used, it's just preventing a runtime with a map var edit.
var/datum/effect_system/spark_spread/spark_system
var/damage_deflection = 10
var/real_explosion_block //ignore this, just use explosion_block
/obj/machinery/door/New()
..()
@@ -45,6 +46,10 @@
spark_system = new /datum/effect_system/spark_spread
spark_system.set_up(2, 1, src)
//doors only block while dense though so we have to use the proc
real_explosion_block = explosion_block
explosion_block = EXPLOSION_BLOCK_PROC
/obj/machinery/door/Destroy()
@@ -284,7 +289,7 @@
/obj/machinery/door/proc/crush()
for(var/mob/living/L in get_turf(src))
L.visible_message("<span class='warning'>[src] closes on [L], crushing them!</span>", "<span class='userdanger'>[src] closes on you and crushes you!</span>")
L.visible_message("<span class='warning'>[src] closes on [L], crushing them!</span>", "<span class='userdanger'>[src] closes on you and crushes you!</span>")
if(isalien(L)) //For xenos
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans.
L.emote("roar")
@@ -346,3 +351,6 @@
//if it blows up a wall it should blow up a door
..(severity ? max(1, severity - 1) : 0, target)
/obj/machinery/door/GetExplosionBlock()
return density ? real_explosion_block : 0
+8 -17
View File
@@ -58,12 +58,11 @@ Possible to do for anyone motivated enough:
/obj/machinery/holopad/Destroy()
if(outgoing_call)
LAZYADD(holo_calls, outgoing_call)
outgoing_call.ConnectionFailure(src)
for(var/I in holo_calls)
var/datum/holocall/HC = I
HC.ConnectionFailure(src)
LAZYCLEARLIST(holo_calls)
for (var/I in masters)
clear_holo(I)
@@ -75,6 +74,13 @@ Possible to do for anyone motivated enough:
stat &= ~NOPOWER
else
stat |= NOPOWER
if(outgoing_call)
outgoing_call.ConnectionFailure(src)
/obj/machinery/holopad/obj_break()
. = ..()
if(outgoing_call)
outgoing_call.ConnectionFailure(src)
/obj/machinery/holopad/RefreshParts()
var/holograph_range = 4
@@ -99,26 +105,11 @@ Possible to do for anyone motivated enough:
return
return ..()
/obj/machinery/holopad/proc/CheckCallClose()
for(var/I in holo_calls)
var/datum/holocall/HC = I
if(usr == HC.eye)
HC.Disconnect(HC.calling_holopad) //disconnect via clicking the called holopad
return TRUE
return FALSE
/obj/machinery/holopad/Click(location,control,params)
if(!CheckCallClose())
return ..()
/obj/machinery/holopad/AltClick(mob/living/carbon/human/user)
if(isAI(user))
hangup_all_calls()
return
if(!CheckCallClose())
interact(user)
/obj/machinery/holopad/interact(mob/living/carbon/human/user) //Carn: Hologram requests.
if(!istype(user))
return
+1 -1
View File
@@ -53,7 +53,7 @@
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["make"])
if(!wait)
if(wait < world.time)
var/p_type = text2path(href_list["make"])
var/p_dir = text2num(href_list["dir"])
var/obj/item/pipe/P = new (src.loc, pipe_type=p_type, dir=p_dir)
@@ -87,9 +87,9 @@
if(has_cover)
cover = new /obj/machinery/porta_turret_cover(loc)
cover.parent_turret = src
var/mutable_appearance/base = mutable_appearance('icons/obj/turrets.dmi', "basedark")
base.layer = NOT_HIGH_OBJ_LAYER
underlays += base
var/mutable_appearance/base = mutable_appearance('icons/obj/turrets.dmi', "basedark")
base.layer = NOT_HIGH_OBJ_LAYER
underlays += base
if(!has_cover)
INVOKE_ASYNC(src, .proc/popUp)
@@ -554,7 +554,7 @@
use_power = 0
has_cover = 0
scan_range = 9
req_access = list(GLOB.access_syndicate)
req_access = list(GLOB.access_syndicate)
stun_projectile = /obj/item/projectile/bullet
lethal_projectile = /obj/item/projectile/bullet
lethal_projectile_sound = 'sound/weapons/Gunshot.ogg'
@@ -564,6 +564,15 @@
faction = "syndicate"
emp_vunerable = 0
/obj/machinery/porta_turret/syndicate/energy
icon_state = "standard_stun"
base_icon_state = "standard"
stun_projectile = /obj/item/projectile/energy/electrode
stun_projectile_sound = 'sound/weapons/Taser.ogg'
lethal_projectile = /obj/item/projectile/beam/laser/heavylaser
lethal_projectile_sound = 'sound/weapons/lasercannonfire.ogg'
/obj/machinery/porta_turret/syndicate/setup()
return
@@ -571,8 +580,8 @@
return 10 //Syndicate turrets shoot everything not in their faction
/obj/machinery/porta_turret/syndicate/pod
max_integrity = 40
integrity_failure = 20
max_integrity = 40
integrity_failure = 20
obj_integrity = 40
stun_projectile = /obj/item/projectile/bullet/weakbullet3
lethal_projectile = /obj/item/projectile/bullet/weakbullet3
@@ -925,181 +934,3 @@
on = 0
spawn(100)
on = 1
/////// MANNED TURRET ////////
/obj/machinery/manned_turret
name = "machine gun turret"
desc = "While the trigger is held down, this gun will redistribute recoil to allow its user to easily shift targets."
icon = 'icons/obj/turrets.dmi'
icon_state = "machinegun"
can_buckle = TRUE
density = TRUE
max_integrity = 100
obj_integrity = 100
buckle_lying = 0
layer = ABOVE_MOB_LAYER
var/view_range = 10
var/cooldown = 0
var/projectile_type = /obj/item/projectile/bullet/weakbullet3
var/rate_of_fire = 1
var/number_of_shots = 40
var/cooldown_duration = 90
var/atom/target
var/turf/target_turf
var/warned = FALSE
var/mouseparams
//BUCKLE HOOKS
/obj/machinery/manned_turret/unbuckle_mob(mob/living/buckled_mob,force = 0)
playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
for(var/obj/item/I in buckled_mob.held_items)
if(istype(I, /obj/item/gun_control))
qdel(I)
if(istype(buckled_mob))
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = 0
if(buckled_mob.client)
buckled_mob.client.change_view(world.view)
anchored = FALSE
. = ..()
/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user)
if(user.incapacitated() || !istype(user))
return
M.forceMove(get_turf(src))
..()
for(var/V in M.held_items)
var/obj/item/I = V
if(istype(I))
if(M.dropItemToGround(I))
var/obj/item/gun_control/TC = new /obj/item/gun_control(src)
M.put_in_hands(TC)
else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
var/obj/item/gun_control/TC = new /obj/item/gun_control(src)
M.put_in_hands(TC)
M.pixel_y = 14
layer = ABOVE_MOB_LAYER
setDir(SOUTH)
playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
anchored = TRUE
if(user.client)
user.client.change_view(view_range)
/obj/item/gun_control
name = "turret controls"
icon = 'icons/obj/weapons.dmi'
icon_state = "offhand"
w_class = WEIGHT_CLASS_HUGE
flags = ABSTRACT | NODROP | NOBLUDGEON
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/obj/machinery/manned_turret/turret
/obj/item/gun_control/New(obj/machinery/manned_turret/MT)
if(MT)
turret = MT
else
qdel(src)
/obj/item/gun_control/CanItemAutoclick()
return 1
/obj/item/gun_control/attack_obj(obj/O, mob/living/user)
user.changeNext_move(CLICK_CD_MELEE)
O.attacked_by(src, user)
/obj/item/gun_control/attack(mob/living/M, mob/living/user)
user.lastattacked = M
M.lastattacker = user
M.attacked_by(src, user)
add_fingerprint(user)
/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user, flag, params)
..()
var/obj/machinery/manned_turret/E = user.buckled
E.setDir(get_dir(E,targeted_atom))
user.setDir(E.dir)
E.mouseparams = params
switch(E.dir)
if(NORTH)
E.layer = BELOW_MOB_LAYER
user.pixel_x = 0
user.pixel_y = -14
if(NORTHEAST)
E.layer = BELOW_MOB_LAYER
user.pixel_x = -8
user.pixel_y = -4
if(EAST)
E.layer = ABOVE_MOB_LAYER
user.pixel_x = -14
user.pixel_y = 0
if(SOUTHEAST)
E.layer = BELOW_MOB_LAYER
user.pixel_x = -8
user.pixel_y = 4
if(SOUTH)
E.layer = ABOVE_MOB_LAYER
user.pixel_x = 0
user.pixel_y = 14
if(SOUTHWEST)
E.layer = BELOW_MOB_LAYER
user.pixel_x = 8
user.pixel_y = 4
if(WEST)
E.layer = ABOVE_MOB_LAYER
user.pixel_x = 14
user.pixel_y = 0
if(NORTHWEST)
E.layer = BELOW_MOB_LAYER
user.pixel_x = 8
user.pixel_y = -4
E.checkfire(targeted_atom, user)
/obj/machinery/manned_turret/proc/checkfire(atom/targeted_atom, mob/user)
target = targeted_atom
if(target == user || target == get_turf(src))
return
if(world.time < cooldown)
if(!warned && world.time > (cooldown - cooldown_duration + rate_of_fire*number_of_shots)) // To capture the window where one is done firing
warned = TRUE
playsound(src, 'sound/weapons/sear.ogg', 100, 1)
return
else
cooldown = world.time + cooldown_duration
warned = FALSE
volley(user)
/obj/machinery/manned_turret/proc/volley(mob/user)
target_turf = get_turf(target)
for(var/i in 1 to number_of_shots)
addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper, user), i*rate_of_fire)
/obj/machinery/manned_turret/proc/fire_helper(mob/user)
if(!src)
return
var/turf/targets_from = get_turf(src)
if(QDELETED(target))
target = target_turf
var/obj/item/projectile/P = new projectile_type(targets_from)
P.current = targets_from
P.starting = targets_from
P.firer = user
P.original = target
playsound(src, 'sound/weapons/Gunshot_smg.ogg', 75, 1)
P.preparePixelProjectile(target, target_turf, user, mouseparams, rand(-9, 9))
P.fire()
/obj/machinery/manned_turret/ultimate // Admin-only proof of concept for autoclicker automatics
name = "Infinity Gun"
view_range = 12
projectile_type = /obj/item/projectile/bullet/weakbullet3
/obj/machinery/manned_turret/ultimate/checkfire(atom/targeted_atom, mob/user)
target = targeted_atom
if(target == user || target == get_turf(src))
return
target_turf = get_turf(target)
fire_helper(user)
+20 -36
View File
@@ -61,7 +61,7 @@
G.loc = src
charging = G
use_power = 2
update_icon(scan = TRUE)
update_icon(scan = TRUE)
else
to_chat(user, "<span class='notice'>[src] isn't connected to anything!</span>")
return 1
@@ -108,41 +108,25 @@
var/using_power = 0
if(charging)
if(istype(charging, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/E = charging
if(E.power_supply.charge < E.power_supply.maxcharge)
E.power_supply.give(E.power_supply.chargerate * recharge_coeff)
E.recharge_newshot()
var/obj/item/weapon/stock_parts/cell/C = charging.get_cell()
if(C)
if(C.charge < C.maxcharge)
C.give(C.chargerate * recharge_coeff)
use_power(250 * recharge_coeff)
using_power = 1
if(istype(charging, /obj/item/weapon/melee/baton))
var/obj/item/weapon/melee/baton/B = charging
if(B.bcell)
if(B.bcell.give(B.bcell.chargerate * recharge_coeff))
use_power(200 * recharge_coeff)
using_power = 1
update_icon(using_power)
if(istype(charging, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/E = charging
E.recharge_newshot()
return
if(istype(charging, /obj/item/ammo_box/magazine/recharge))
var/obj/item/ammo_box/magazine/recharge/R = charging
if(R.stored_ammo.len < R.max_ammo)
R.stored_ammo += new R.ammo_type(R)
use_power(200 * recharge_coeff)
using_power = 1
if(istype(charging, /obj/item/device/modular_computer))
var/obj/item/device/modular_computer/C = charging
var/obj/item/weapon/computer_hardware/battery/battery_module = C.all_components[MC_CELL]
if(battery_module)
var/obj/item/weapon/computer_hardware/battery/B = battery_module
if(B.battery)
if(B.battery.charge < B.battery.maxcharge)
B.battery.give(B.battery.chargerate * recharge_coeff)
use_power(200 * recharge_coeff)
using_power = 1
update_icon(using_power)
update_icon(using_power)
return
/obj/machinery/recharger/power_change()
..()
@@ -152,23 +136,23 @@
if(!(stat & (NOPOWER|BROKEN)) && anchored)
if(istype(charging, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/E = charging
if(E.power_supply)
E.power_supply.emp_act(severity)
if(E.cell)
E.cell.emp_act(severity)
else if(istype(charging, /obj/item/weapon/melee/baton))
var/obj/item/weapon/melee/baton/B = charging
if(B.bcell)
B.bcell.charge = 0
if(B.cell)
B.cell.charge = 0
..()
/obj/machinery/recharger/update_icon(using_power = 0, scan) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
/obj/machinery/recharger/update_icon(using_power = 0, scan) //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
if(stat & (NOPOWER|BROKEN) || !anchored)
icon_state = "rechargeroff"
return
if(scan)
icon_state = "rechargeroff"
return
if(scan)
icon_state = "rechargeroff"
return
if(panel_open)
icon_state = "rechargeropen"
return
+1 -3
View File
@@ -49,9 +49,7 @@
/obj/structure/emergency_shield/take_damage(damage, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
. = ..()
if(.) //damage was dealt
set_opacity(1)
spawn(20)
set_opacity(0)
new /obj/effect/temp_visual/impact_effect/ion(loc)
/obj/structure/emergency_shield/sanguine
name = "sanguine barrier"
+3
View File
@@ -24,6 +24,9 @@
var/settableTemperatureMedian = 30 + T0C
var/settableTemperatureRange = 30
/obj/machinery/space_heater/get_cell()
return cell
/obj/machinery/space_heater/New()
..()
cell = new(src)
+8
View File
@@ -213,6 +213,14 @@
var/emotion = "Neutral"
/obj/machinery/ai_status_display/Initialize()
. = ..()
GLOB.ai_status_displays.Add(src)
/obj/machinery/ai_status_display/Destroy()
GLOB.ai_status_displays.Remove(src)
. = ..()
/obj/machinery/ai_status_display/attack_ai(mob/living/silicon/ai/user)
if(isAI(user))
user.ai_statuschange()
+2 -2
View File
@@ -995,7 +995,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/item/clothing/head/helmet/gladiator = 1,/obj/item/clothing/under/gimmick/rank/captain/suit = 1,/obj/item/clothing/head/flatcap = 1,
/obj/item/clothing/suit/toggle/labcoat/mad = 1,/obj/item/clothing/shoes/jackboots = 1,
/obj/item/clothing/under/schoolgirl = 1,/obj/item/clothing/under/schoolgirl/red = 1,/obj/item/clothing/under/schoolgirl/green = 1,/obj/item/clothing/under/schoolgirl/orange = 1,/obj/item/clothing/head/kitty = 1,/obj/item/clothing/under/skirt/black = 1,/obj/item/clothing/head/beret = 1,
/obj/item/clothing/tie/waistcoat = 1,/obj/item/clothing/under/suit_jacket = 1,/obj/item/clothing/head/that =1,/obj/item/clothing/under/kilt = 1,/obj/item/clothing/head/beret = 1,/obj/item/clothing/tie/waistcoat = 1,
/obj/item/clothing/accessory/waistcoat = 1,/obj/item/clothing/under/suit_jacket = 1,/obj/item/clothing/head/that =1,/obj/item/clothing/under/kilt = 1,/obj/item/clothing/head/beret = 1,/obj/item/clothing/accessory/waistcoat = 1,
/obj/item/clothing/glasses/monocle =1,/obj/item/clothing/head/bowler = 1,/obj/item/weapon/cane = 1,/obj/item/clothing/under/sl_suit = 1,
/obj/item/clothing/mask/fakemoustache = 1,/obj/item/clothing/suit/bio_suit/plaguedoctorsuit = 1,/obj/item/clothing/head/plaguedoctorhat = 1,/obj/item/clothing/mask/gas/plaguedoctor = 1,
/obj/item/clothing/suit/toggle/owlwings = 1, /obj/item/clothing/under/owl = 1,/obj/item/clothing/mask/gas/owl_mask = 1,
@@ -1136,7 +1136,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/item/clothing/neck/scarf/purple=1,/obj/item/clothing/neck/scarf/yellow=1,/obj/item/clothing/neck/scarf/orange=1,
/obj/item/clothing/neck/scarf/cyan=1,/obj/item/clothing/neck/scarf=1,/obj/item/clothing/neck/scarf/black=1,
/obj/item/clothing/neck/scarf/zebra=1,/obj/item/clothing/neck/scarf/christmas=1,/obj/item/clothing/neck/stripedredscarf=1,
/obj/item/clothing/neck/stripedbluescarf=1,/obj/item/clothing/neck/stripedgreenscarf=1,/obj/item/clothing/tie/waistcoat=1,
/obj/item/clothing/neck/stripedbluescarf=1,/obj/item/clothing/neck/stripedgreenscarf=1,/obj/item/clothing/accessory/waistcoat=1,
/obj/item/clothing/under/skirt/black=1,/obj/item/clothing/under/skirt/blue=1,/obj/item/clothing/under/skirt/red=1,/obj/item/clothing/under/skirt/purple=1,
/obj/item/clothing/under/sundress=2,/obj/item/clothing/under/stripeddress=1, /obj/item/clothing/under/sailordress=1, /obj/item/clothing/under/redeveninggown=1, /obj/item/clothing/under/blacktango=1,
/obj/item/clothing/under/plaid_skirt=1,/obj/item/clothing/under/plaid_skirt/blue=1,/obj/item/clothing/under/plaid_skirt/purple=1,/obj/item/clothing/under/plaid_skirt/green=1,
+4 -1
View File
@@ -142,6 +142,9 @@
diag_hud_set_mechstat()
diag_hud_set_mechtracking()
/obj/mecha/get_cell()
return cell
/obj/mecha/Destroy()
go_out()
@@ -154,7 +157,7 @@
M.forceMove(loc)
if(prob(30))
explosion(get_turf(loc), 0, 0, 1, 3)
explosion(get_turf(loc), 0, 0, 1, 3)
if(wreckage)
var/obj/structure/mecha_wreckage/WR = new wreckage(loc, AI)
+8 -10
View File
@@ -43,19 +43,19 @@
buckled_mobs = list()
if(!istype(M))
return 0
return FALSE
if(check_loc && M.loc != loc)
return 0
return FALSE
if((!can_buckle && !force) || M.buckled || (buckled_mobs.len >= max_buckled_mobs) || (buckle_requires_restraints && !M.restrained()) || M == src)
return 0
return FALSE
if(!M.can_buckle() && !force)
if(M == usr)
to_chat(M, "<span class='warning'>You are unable to buckle yourself to the [src]!</span>")
else
to_chat(usr, "<span class='warning'>You are unable to buckle [M] to the [src]!</span>")
return 0
return FALSE
if(M.pulledby && buckle_prevents_pull)
M.pulledby.stop_pulling()
@@ -70,7 +70,7 @@
M.throw_alert("buckled", /obj/screen/alert/restrained/buckled, new_master = src)
post_buckle_mob(M)
return 1
return TRUE
/obj/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
. = ..()
@@ -105,11 +105,11 @@
//Wrapper procs that handle sanity and user feedback
/atom/movable/proc/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE)
if(!in_range(user, src) || user.stat || user.restrained())
return 0
return FALSE
add_fingerprint(user)
if(buckle_mob(M, check_loc = check_loc))
. = buckle_mob(M, check_loc = check_loc)
if(.)
if(M == user)
M.visible_message(\
"<span class='notice'>[M] buckles [M.p_them()]self to [src].</span>",\
@@ -120,8 +120,6 @@
"<span class='warning'>[user] buckles [M] to [src]!</span>",\
"<span class='warning'>[user] buckles you to [src]!</span>",\
"<span class='italics'>You hear metal clanking.</span>")
return 1
/atom/movable/proc/user_unbuckle_mob(mob/living/buckled_mob, mob/user)
var/mob/living/M = unbuckle_mob(buckled_mob)
+14 -6
View File
@@ -30,27 +30,35 @@
layer = HIGH_OBJ_LAYER //Harder to hide
do_icon_rotate = FALSE //These are designed to always face south, so no rotation please.
var/datum/gang/gang
var/obj/item/device/gangtool/linked_tool
var/datum/mind/user_mind
var/area/territory
/obj/effect/decal/cleanable/crayon/gang/Initialize(mapload, var/datum/gang/G, var/e_name = "gang tag", var/rotation = 0, var/mob/user)
if(!type || !G)
qdel(src)
user_mind = user.mind
territory = get_area(src)
gang = G
var/newcolor = G.color_hex
icon_state = G.name
G.territory_new |= list(territory.type = territory.name)
linked_tool = locate(/obj/item/device/gangtool) in user.contents
if(linked_tool)
linked_tool.tags += src
//If this isn't tagged by a specific gangster there's no bonus income.
set_mind_owner(user_mind)
..(mapload, newcolor, icon_state, e_name, rotation)
/obj/effect/decal/cleanable/crayon/gang/proc/set_mind_owner(datum/mind/mind)
if(istype(user_mind) && istype(gang) && islist(gang.tags_by_mind[user_mind])) //Clear us out of old ownership
gang.tags_by_mind[user_mind] -= src
if(istype(mind))
if(!islist(gang.tags_by_mind[mind]))
gang.tags_by_mind[mind] = list()
gang.tags_by_mind[mind] += src
user_mind = mind
/obj/effect/decal/cleanable/crayon/gang/Destroy()
if(linked_tool)
linked_tool.tags -= src
if(gang)
gang.territory -= territory.type
set_mind_owner(null)
gang.territory_new -= territory.type
gang.territory_lost |= list(territory.type = territory.name)
return ..()
+4 -1
View File
@@ -64,4 +64,7 @@
icon_state = "sandyfloor"
/obj/effect/turf_decal/sand/plating
icon_state = "sandyplating"
icon_state = "sandyplating"
/obj/effect/turf_decal/plaque
icon_state = "plaque"
+2 -2
View File
@@ -60,7 +60,7 @@
/obj/effect/spawner/bundle/costume/butler
name = "butler costume spawner"
items = list(
/obj/item/clothing/tie/waistcoat,
/obj/item/clothing/accessory/waistcoat,
/obj/item/clothing/under/suit_jacket,
/obj/item/clothing/head/that)
@@ -73,7 +73,7 @@
/obj/effect/spawner/bundle/costume/prig
name = "prig costume spawner"
items = list(
/obj/item/clothing/tie/waistcoat,
/obj/item/clothing/accessory/waistcoat,
/obj/item/clothing/glasses/monocle,
/obj/effect/spawner/lootdrop/minor/bowler_or_that,
/obj/item/clothing/shoes/sneakers/black,
+30 -1
View File
@@ -54,6 +54,35 @@
/obj/item/trash/sosjerky = 1,
/obj/item/trash/syndi_cakes = 1)
/obj/effect/spawner/lootdrop/three_course_meal
name = "three course meal spawner"
lootcount = 3
lootdoubles = FALSE
var/soups = list(
/obj/item/weapon/reagent_containers/food/snacks/soup/beet,
/obj/item/weapon/reagent_containers/food/snacks/soup/sweetpotato,
/obj/item/weapon/reagent_containers/food/snacks/soup/stew,
/obj/item/weapon/reagent_containers/food/snacks/soup/hotchili,
/obj/item/weapon/reagent_containers/food/snacks/soup/nettle,
/obj/item/weapon/reagent_containers/food/snacks/soup/meatball)
var/salads = list(
/obj/item/weapon/reagent_containers/food/snacks/salad/herbsalad,
/obj/item/weapon/reagent_containers/food/snacks/salad/validsalad,
/obj/item/weapon/reagent_containers/food/snacks/salad/fruit,
/obj/item/weapon/reagent_containers/food/snacks/salad/jungle,
/obj/item/weapon/reagent_containers/food/snacks/salad/aesirsalad)
var/mains = list(
/obj/item/weapon/reagent_containers/food/snacks/bearsteak,
/obj/item/weapon/reagent_containers/food/snacks/enchiladas,
/obj/item/weapon/reagent_containers/food/snacks/stewedsoymeat,
/obj/item/weapon/reagent_containers/food/snacks/burger/bigbite,
/obj/item/weapon/reagent_containers/food/snacks/burger/superbite,
/obj/item/weapon/reagent_containers/food/snacks/burger/fivealarm)
/obj/effect/spawner/lootdrop/three_course_meal/Initialize(mapload)
loot = list(pick(soups) = 1,pick(salads) = 1,pick(mains) = 1)
. = ..()
/obj/effect/spawner/lootdrop/maintenance
name = "maintenance loot spawner"
// see code/_globalvars/lists/maintenance_loot.dm for loot table
@@ -85,7 +114,7 @@
/obj/item/organ/heart/gland/spiderman = 5,
/obj/item/organ/heart/gland/ventcrawling = 1,
/obj/item/organ/body_egg/alien_embryo = 1,
/obj/item/organ/hivelord_core = 2)
/obj/item/organ/regenerative_core = 2)
lootcount = 3
/obj/effect/spawner/lootdrop/two_percent_xeno_egg_spawner
+1 -1
View File
@@ -172,7 +172,7 @@
amount_grown += rand(0,2)
if(amount_grown >= 100)
if(!grow_as)
grow_as = pick(typesof(/mob/living/simple_animal/hostile/poison/giant_spider))
grow_as = pick(/mob/living/simple_animal/hostile/poison/giant_spider, /mob/living/simple_animal/hostile/poison/giant_spider/hunter, /mob/living/simple_animal/hostile/poison/giant_spider/nurse)
var/mob/living/simple_animal/hostile/poison/giant_spider/S = new grow_as(src.loc)
S.poison_per_bite = poison_per_bite
S.poison_type = poison_type
@@ -18,11 +18,13 @@
icon_state = "bloodout"
/obj/effect/temp_visual/dir_setting/cult/phase // The veil shifter teleport
icon = 'icons/effects/cult_effects.dmi'
name = "phase glow"
duration = 7
icon_state = "cultin"
/obj/effect/temp_visual/dir_setting/cult/phase/out
icon = 'icons/effects/cult_effects.dmi'
icon_state = "cultout"
/obj/effect/temp_visual/cult/sac
@@ -169,7 +169,9 @@
/obj/effect/temp_visual/fire
icon = 'icons/effects/fire.dmi'
icon_state = "3"
duration = 20
light_range = 3
light_color = LIGHT_COLOR_FIRE
duration = 10
/obj/effect/temp_visual/revenant
name = "spooky lights"

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