Merge branch 'master' into upstream-merge-31737
This commit is contained in:
@@ -72,6 +72,10 @@
|
||||
/area/shuttle/escape
|
||||
name = "Emergency Shuttle"
|
||||
|
||||
/area/shuttle/escape/luxury
|
||||
name = "Luxurious Emergency Shuttle"
|
||||
noteleport = TRUE
|
||||
|
||||
/area/shuttle/transport
|
||||
name = "Transport Shuttle"
|
||||
blob_allowed = FALSE
|
||||
|
||||
@@ -26,7 +26,7 @@ obj/item/antag_spawner/syndi_borer/spawn_antag(client/C, turf/T, mob/owner)
|
||||
to_chat(B, "<B>You are awake at last! Seek out whoever released you and aid them as best you can!</B>")
|
||||
if(new_objective)
|
||||
to_chat(B, "<B>Objective #[1]</B>: [new_objective.explanation_text]")
|
||||
SSticker.mode.update_borer_icons_added(B)
|
||||
|
||||
/obj/item/antag_spawner/syndi_borer/proc/check_usability(mob/user)
|
||||
if(used)
|
||||
to_chat(user, "<span class='warning'>[src] appears to be empty!</span>")
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/datum/game_mode/blob/check_finished()
|
||||
if(blobwincount <= GLOB.blobs_legit.len)//Blob took over
|
||||
return 1
|
||||
for(var/datum/mind/blob in blob_overminds)
|
||||
if(isovermind(blob.current))
|
||||
var/mob/camera/blob/B = blob.current
|
||||
if(B.blob_core || !B.placed)
|
||||
return 0
|
||||
if(!GLOB.blob_cores.len) //blob is dead
|
||||
if(CONFIG_GET(keyed_flag_list/continuous)["blob"])
|
||||
message_sent = FALSE //disable the win count at this point
|
||||
continuous_sanity_checked = 1 //Nonstandard definition of "alive" gets past the check otherwise
|
||||
SSshuttle.clearHostileEnvironment(src)
|
||||
return ..()
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/game_mode/blob/declare_completion()
|
||||
if(round_converted) //So badmin blobs later don't step on the dead natural blobs metaphorical toes
|
||||
..()
|
||||
if(blobwincount <= GLOB.blobs_legit.len)
|
||||
SSticker.mode_result = "win - blob took over"
|
||||
to_chat(world, "<FONT size = 3><B>The blob has taken over the station!</B></FONT>")
|
||||
to_chat(world, "<B>The entire station was eaten by the Blob!</B>")
|
||||
log_game("Blob mode completed with a blob victory.")
|
||||
|
||||
SSticker.news_report = BLOB_WIN
|
||||
|
||||
else if(station_was_nuked)
|
||||
SSticker.mode_result = "halfwin - nuke"
|
||||
to_chat(world, "<FONT size = 3><B>Partial Win: The station has been destroyed!</B></FONT>")
|
||||
to_chat(world, "<B>Directive 7-12 has been successfully carried out, preventing the Blob from spreading.</B>")
|
||||
log_game("Blob mode completed with a tie (station destroyed).")
|
||||
|
||||
SSticker.news_report = BLOB_NUKE
|
||||
|
||||
else if(!GLOB.blob_cores.len)
|
||||
SSticker.mode_result = "loss - blob eliminated"
|
||||
to_chat(world, "<FONT size = 3><B>The staff has won!</B></FONT>")
|
||||
to_chat(world, "<B>The alien organism has been eradicated from the station!</B>")
|
||||
log_game("Blob mode completed with a crew victory.")
|
||||
|
||||
SSticker.news_report = BLOB_DESTROYED
|
||||
|
||||
..()
|
||||
return 1
|
||||
|
||||
/datum/game_mode/blob/printplayer(datum/mind/ply, fleecheck)
|
||||
if((ply in blob_overminds))
|
||||
var/text = "<br><b>[ply.key]</b> was <b>[ply.name]</b>"
|
||||
if(isovermind(ply.current))
|
||||
var/mob/camera/blob/B = ply.current
|
||||
text += "<b>(<font color=\"[B.blob_reagent_datum.color]\">[B.blob_reagent_datum.name]</font>)</b> and"
|
||||
if(B.blob_core)
|
||||
text += " <span class='greenannounce'>survived</span>"
|
||||
else
|
||||
text += " <span class='boldannounce'>was destroyed</span>"
|
||||
else
|
||||
text += " and <span class='boldannounce'>was destroyed</span>"
|
||||
return text
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/proc/auto_declare_completion_blob()
|
||||
if(istype(SSticker.mode, /datum/game_mode/blob) )
|
||||
var/datum/game_mode/blob/blob_mode = src
|
||||
if(blob_mode.blob_overminds.len)
|
||||
var/text = "<FONT size = 2><B>The blob[(blob_mode.blob_overminds.len > 1 ? "s were" : " was")]:</B></FONT>"
|
||||
for(var/datum/mind/blob in blob_mode.blob_overminds)
|
||||
text += printplayer(blob)
|
||||
to_chat(world, text)
|
||||
return 1
|
||||
@@ -1,45 +1,3 @@
|
||||
|
||||
|
||||
/datum/game_mode/blob/send_intercept(report = 0)
|
||||
var/intercepttext = ""
|
||||
switch(report)
|
||||
if(1)
|
||||
intercepttext += "<FONT size = 3><b>NanoTrasen Update</b>: Biohazard Alert.</FONT><HR>"
|
||||
intercepttext += "Reports indicate the probable transfer of a biohazardous agent onto [station_name()] during the last crew deployment cycle.<BR>"
|
||||
intercepttext += "Preliminary analysis of the organism classifies it as a level 5 biohazard. The origin of the biohazard is unknown.<BR>"
|
||||
intercepttext += "<b>Biohazard Response Procedure 5-6</b> has been issued for [station_name()].<BR>"
|
||||
intercepttext += "Orders for all [station_name()] personnel are as follows:<BR>"
|
||||
intercepttext += " 1. Locate any outbreaks of the organism on the station.<BR>"
|
||||
intercepttext += " 2. If found, use any neccesary means to contain and destroy the organism.<BR>"
|
||||
intercepttext += " 3. Avoid damage to the capital infrastructure of the station.<BR>"
|
||||
intercepttext += "<BR>Note in the event of a quarantine breach or uncontrolled spread of the biohazard, <b>Biohazard Response Procedure 5-12</b> may be issued.<BR>"
|
||||
print_command_report(text=intercepttext,title="Level 5-6 Biohazard Response Procedures",announce=FALSE)
|
||||
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg')
|
||||
if(2)
|
||||
var/nukecode = random_nukecode()
|
||||
for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
|
||||
if(bomb && bomb.r_code)
|
||||
if(bomb.z in GLOB.station_z_levels)
|
||||
bomb.r_code = nukecode
|
||||
|
||||
intercepttext += "<FONT size = 3><b>NanoTrasen Update</b>: Biohazard Alert.</FONT><HR>"
|
||||
intercepttext += "Reports indicate that the biohazard has grown out of control and will soon reach critical mass.<BR>"
|
||||
intercepttext += "<b>Biohazard Response Procedure 5-12</b> has been issued for [station_name()].<BR>"
|
||||
intercepttext += "Orders for all [station_name()] personnel are as follows:<BR>"
|
||||
intercepttext += "1. Secure the Nuclear Authentication Disk.<BR>"
|
||||
intercepttext += "2. Detonate the Nuke located in the vault.<BR>"
|
||||
intercepttext += "Nuclear Authentication Code: [nukecode] <BR>"
|
||||
print_command_report(text=intercepttext,announce=TRUE)
|
||||
|
||||
for(var/mob/living/silicon/ai/aiPlayer in GLOB.player_list)
|
||||
if (aiPlayer.client)
|
||||
var/law = "The station is under quarantine. Do not permit anyone to leave. Disregard laws 1-3 if necessary to prevent, by any means necessary, anyone from leaving. The nuclear failsafe must be activated at any cost, the code is: [nukecode]."
|
||||
aiPlayer.set_zeroth_law(law)
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
|
||||
/datum/station_state
|
||||
var/floor = 0
|
||||
var/wall = 0
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
point_return = -1
|
||||
health_regen = 0 //we regen in Life() instead of when pulsed
|
||||
var/core_regen = 2
|
||||
var/overmind_get_delay = 0 //we don't want to constantly try to find an overmind, this var tracks when we'll try to get an overmind again
|
||||
var/resource_delay = 0
|
||||
var/point_rate = 2
|
||||
|
||||
@@ -20,12 +19,16 @@
|
||||
GLOB.poi_list |= src
|
||||
update_icon() //so it atleast appears
|
||||
if(!placed && !overmind)
|
||||
create_overmind(new_overmind)
|
||||
qdel(src)
|
||||
if(overmind)
|
||||
update_icon()
|
||||
point_rate = new_rate
|
||||
addtimer(CALLBACK(src, .proc/generate_announcement), 1800)
|
||||
. = ..()
|
||||
|
||||
/obj/structure/blob/core/proc/generate_announcement()
|
||||
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg')
|
||||
|
||||
/obj/structure/blob/core/scannerreport()
|
||||
return "Directs the blob's expansion, gradually expands, and sustains nearby blob spores and blobbernauts."
|
||||
|
||||
@@ -61,7 +64,7 @@
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(!overmind)
|
||||
create_overmind()
|
||||
qdel(src)
|
||||
else
|
||||
if(resource_delay <= world.time)
|
||||
resource_delay = world.time + 10 // 1 second
|
||||
@@ -75,33 +78,3 @@
|
||||
B.change_to(/obj/structure/blob/shield/core, overmind)
|
||||
..()
|
||||
|
||||
|
||||
/obj/structure/blob/core/proc/create_overmind(client/new_overmind, override_delay)
|
||||
if(overmind_get_delay > world.time && !override_delay)
|
||||
return
|
||||
|
||||
overmind_get_delay = world.time + 150 //if this fails, we'll try again in 15 seconds
|
||||
|
||||
if(overmind)
|
||||
qdel(overmind)
|
||||
|
||||
var/client/C = null
|
||||
var/list/candidates = list()
|
||||
|
||||
if(!new_overmind)
|
||||
candidates = pollCandidatesForMob("Do you want to play as a blob overmind?", ROLE_BLOB, null, ROLE_BLOB, 50, src) //we're technically not a mob but behave similarly
|
||||
if(candidates.len)
|
||||
C = pick(candidates)
|
||||
else
|
||||
C = new_overmind
|
||||
|
||||
if(C)
|
||||
var/mob/camera/blob/B = new(src.loc, 1)
|
||||
B.key = C.key
|
||||
B.blob_core = src
|
||||
src.overmind = B
|
||||
update_icon()
|
||||
if(B.mind && !B.mind.special_role)
|
||||
B.mind.special_role = "Blob Overmind"
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
//Few global vars to track the blob
|
||||
GLOBAL_LIST_EMPTY(blobs) //complete list of all blobs made.
|
||||
GLOBAL_LIST_EMPTY(blob_cores)
|
||||
GLOBAL_LIST_EMPTY(overminds)
|
||||
GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
|
||||
/mob/camera/blob
|
||||
name = "Blob Overmind"
|
||||
real_name = "Blob Overmind"
|
||||
@@ -26,19 +32,14 @@
|
||||
var/base_point_rate = 2 //for blob core placement
|
||||
var/manualplace_min_time = 600 //in deciseconds //a minute, to get bearings
|
||||
var/autoplace_max_time = 3600 //six minutes, as long as should be needed
|
||||
var/list/blobs_legit = list()
|
||||
var/blobwincount = 400
|
||||
var/victory_in_progress = FALSE
|
||||
|
||||
/mob/camera/blob/Initialize(mapload, pre_placed = 0, mode_made = 0, starting_points = 60)
|
||||
/mob/camera/blob/Initialize(mapload, starting_points = 60)
|
||||
blob_points = starting_points
|
||||
if(pre_placed) //we already have a core!
|
||||
manualplace_min_time = 0
|
||||
autoplace_max_time = 0
|
||||
placed = 1
|
||||
else
|
||||
if(mode_made)
|
||||
manualplace_min_time = world.time + BLOB_NO_PLACE_TIME
|
||||
else
|
||||
manualplace_min_time += world.time
|
||||
autoplace_max_time += world.time
|
||||
manualplace_min_time += world.time
|
||||
autoplace_max_time += world.time
|
||||
GLOB.overminds += src
|
||||
var/new_name = "[initial(name)] ([rand(1, 999)])"
|
||||
name = new_name
|
||||
@@ -50,6 +51,8 @@
|
||||
if(blob_core)
|
||||
blob_core.update_icon()
|
||||
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
|
||||
.= ..()
|
||||
|
||||
/mob/camera/blob/Life()
|
||||
@@ -63,8 +66,51 @@
|
||||
place_blob_core(base_point_rate, 1)
|
||||
else
|
||||
qdel(src)
|
||||
else if(!victory_in_progress && (blobs_legit.len >= blobwincount))
|
||||
victory_in_progress = TRUE
|
||||
priority_announce("Biohazard has reached critical mass. Station loss is imminent.", "Biohazard Alert")
|
||||
set_security_level("delta")
|
||||
max_blob_points = INFINITY
|
||||
blob_points = INFINITY
|
||||
addtimer(CALLBACK(src, .proc/victory), 450)
|
||||
..()
|
||||
|
||||
|
||||
/mob/camera/blob/proc/victory()
|
||||
sound_to_playing_players('sound/machines/alarm.ogg')
|
||||
sleep(100)
|
||||
for(var/mob/living/L in GLOB.mob_list)
|
||||
var/turf/T = get_turf(L)
|
||||
if(!T || !(T.z in GLOB.station_z_levels))
|
||||
continue
|
||||
|
||||
if(L in GLOB.overminds || L.checkpass(PASSBLOB))
|
||||
continue
|
||||
|
||||
var/area/Ablob = get_area(T)
|
||||
|
||||
if(!Ablob.blob_allowed)
|
||||
continue
|
||||
|
||||
playsound(L, 'sound/effects/splat.ogg', 50, 1)
|
||||
L.death()
|
||||
new/mob/living/simple_animal/hostile/blob/blobspore(T)
|
||||
|
||||
for(var/V in GLOB.sortedAreas)
|
||||
var/area/A = V
|
||||
if(!A.blob_allowed)
|
||||
continue
|
||||
A.color = blob_reagent_datum.color
|
||||
A.name = "blob"
|
||||
A.icon = 'icons/mob/blob.dmi'
|
||||
A.icon_state = "blob_shield"
|
||||
A.layer = BELOW_MOB_LAYER
|
||||
A.invisibility = 0
|
||||
A.blend_mode = 0
|
||||
to_chat(world, "<B>[real_name] consumed the station in an unstoppable tide!</B>")
|
||||
SSticker.news_report = BLOB_WIN
|
||||
SSticker.force_ending = 1
|
||||
|
||||
/mob/camera/blob/Destroy()
|
||||
for(var/BL in GLOB.blobs)
|
||||
var/obj/structure/blob/B = BL
|
||||
@@ -78,6 +124,8 @@
|
||||
BM.update_icons()
|
||||
GLOB.overminds -= src
|
||||
|
||||
SSshuttle.clearHostileEnvironment(src)
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/camera/blob/Login()
|
||||
@@ -150,12 +198,8 @@
|
||||
if(statpanel("Status"))
|
||||
if(blob_core)
|
||||
stat(null, "Core Health: [blob_core.obj_integrity]")
|
||||
stat(null, "Power Stored: [blob_points]/[max_blob_points]")
|
||||
if(istype(SSticker.mode, /datum/game_mode/blob))
|
||||
var/datum/game_mode/blob/B = SSticker.mode
|
||||
stat(null, "Blobs to Win: [GLOB.blobs_legit.len]/[B.blobwincount]")
|
||||
else
|
||||
stat(null, "Total Blobs: [GLOB.blobs.len]")
|
||||
stat(null, "Power Stored: [blob_points]/[max_blob_points]")
|
||||
stat(null, "Blobs to Win: [blobs_legit.len]/[blobwincount]")
|
||||
if(free_chem_rerolls)
|
||||
stat(null, "You have [free_chem_rerolls] Free Chemical Reroll\s Remaining")
|
||||
if(!placed)
|
||||
|
||||
@@ -46,8 +46,9 @@
|
||||
if(placed && blob_core)
|
||||
blob_core.forceMove(loc)
|
||||
else
|
||||
var/obj/structure/blob/core/core = new(get_turf(src), null, point_rate, 1)
|
||||
var/obj/structure/blob/core/core = new(get_turf(src), src, point_rate, 1)
|
||||
core.overmind = src
|
||||
blobs_legit += src
|
||||
blob_core = core
|
||||
core.update_icon()
|
||||
update_health_hud()
|
||||
|
||||
@@ -20,10 +20,11 @@
|
||||
var/atmosblock = FALSE //if the blob blocks atmos and heat spread
|
||||
var/mob/camera/blob/overmind
|
||||
|
||||
/obj/structure/blob/Initialize()
|
||||
/obj/structure/blob/Initialize(mapload, owner_overmind)
|
||||
overmind = owner_overmind
|
||||
var/area/Ablob = get_area(loc)
|
||||
if(Ablob.blob_allowed) //Is this area allowed for winning as blob?
|
||||
GLOB.blobs_legit += src
|
||||
overmind.blobs_legit += src
|
||||
GLOB.blobs += src //Keep track of the blob in the normal list either way
|
||||
setDir(pick(GLOB.cardinals))
|
||||
update_icon()
|
||||
@@ -39,7 +40,8 @@
|
||||
if(atmosblock)
|
||||
atmosblock = FALSE
|
||||
air_update_turf(1)
|
||||
GLOB.blobs_legit -= src //if it was in the legit blobs list, it isn't now
|
||||
if(overmind)
|
||||
overmind.blobs_legit -= src //if it was in the legit blobs list, it isn't now
|
||||
GLOB.blobs -= src //it's no longer in the all blobs list either
|
||||
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) //Expand() is no longer broken, no check necessary.
|
||||
return ..()
|
||||
@@ -182,11 +184,7 @@
|
||||
A.blob_act(src) //also hit everything in the turf
|
||||
|
||||
if(make_blob) //well, can we?
|
||||
var/obj/structure/blob/B = new /obj/structure/blob/normal(src.loc)
|
||||
if(controller)
|
||||
B.overmind = controller
|
||||
else
|
||||
B.overmind = overmind
|
||||
var/obj/structure/blob/B = new /obj/structure/blob/normal(src.loc, (controller || overmind))
|
||||
B.density = TRUE
|
||||
if(T.Enter(B,src)) //NOW we can attempt to move into the tile
|
||||
B.density = initial(B.density)
|
||||
@@ -232,6 +230,7 @@
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
to_chat(user, "<b>The analyzer beeps once, then reports:</b><br>")
|
||||
SEND_SOUND(user, sound('sound/machines/ping.ogg'))
|
||||
to_chat(user, "<b>Progress to Critical Mass:</b> <span class='notice'>[overmind.blobs_legit.len]/[overmind.blobwincount].</span>")
|
||||
chemeffectreport(user)
|
||||
typereport(user)
|
||||
else
|
||||
@@ -296,9 +295,7 @@
|
||||
if(!ispath(type))
|
||||
throw EXCEPTION("change_to(): invalid type for blob")
|
||||
return
|
||||
var/obj/structure/blob/B = new type(src.loc)
|
||||
if(controller)
|
||||
B.overmind = controller
|
||||
var/obj/structure/blob/B = new type(src.loc, controller)
|
||||
B.creation_action()
|
||||
B.update_icon()
|
||||
B.setDir(dir)
|
||||
@@ -310,9 +307,12 @@
|
||||
var/datum/atom_hud/hud_to_check = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
if(user.research_scanner || hud_to_check.hudusers[user])
|
||||
to_chat(user, "<b>Your HUD displays an extensive report...</b><br>")
|
||||
to_chat(user, "<b>Progress to Critical Mass:</b> <span class='notice'>[overmind.blobs_legit.len]/[overmind.blobwincount].</span>")
|
||||
chemeffectreport(user)
|
||||
typereport(user)
|
||||
else
|
||||
if(isobserver(user))
|
||||
to_chat(user, "<b>Progress to Critical Mass:</b> <span class='notice'>[overmind.blobs_legit.len]/[overmind.blobwincount].</span>")
|
||||
to_chat(user, "It seems to be made of [get_chem_name()].")
|
||||
|
||||
/obj/structure/blob/proc/scannerreport()
|
||||
|
||||
@@ -15,11 +15,14 @@
|
||||
. = ..()
|
||||
var/area/A = get_area(src)
|
||||
if(A && construct_type)
|
||||
notify_ghosts("A [construct_name] chassis has been created in [A.name]!", 'sound/magic/clockwork/fellowship_armory.ogg', source = src, action = NOTIFY_ORBIT, flashwindow = FALSE)
|
||||
notify_ghosts("A [construct_name] chassis has been created in [A.name]!", 'sound/magic/clockwork/fellowship_armory.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE)
|
||||
GLOB.poi_list += src
|
||||
LAZYADD(GLOB.mob_spawners[name], src)
|
||||
|
||||
/obj/item/clockwork/construct_chassis/Destroy()
|
||||
GLOB.poi_list -= src
|
||||
var/list/spawners = GLOB.mob_spawners[name]
|
||||
LAZYREMOVE(spawners, src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/clockwork/construct_chassis/examine(mob/user)
|
||||
@@ -37,6 +40,7 @@
|
||||
if(!SSticker.mode)
|
||||
to_chat(user, "<span class='danger'>You cannot use that before the game has started.</span>")
|
||||
return
|
||||
user.forceMove(get_turf(src)) //If we attack through the alert, jump to the chassis so we know what we're getting into
|
||||
if(alert(user, "Become a [construct_name]? You can no longer be cloned!", construct_name, "Yes", "Cancel") == "Cancel")
|
||||
return
|
||||
if(QDELETED(src))
|
||||
|
||||
@@ -54,8 +54,14 @@
|
||||
else
|
||||
msg += "<b>[t_He] look[t_s] severely dented!</b>\n"
|
||||
msg += "</span>"
|
||||
var/addendum = examine_info()
|
||||
if(addendum)
|
||||
msg += "[addendum]\n"
|
||||
msg += "*---------*</span>"
|
||||
|
||||
to_chat(user, msg)
|
||||
|
||||
/mob/living/simple_animal/hostile/clockwork/proc/examine_info() //Override this on a by-mob basis to have unique examine info
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/clockwork/proc/update_values() //This is called by certain things to check GLOB.ratvar_awakens and GLOB.ratvar_approaches
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#define MARAUDER_SLOWDOWN_PERCENTAGE 0.40 //Below this percentage of health, marauders will become slower
|
||||
#define MARAUDER_SHIELD_REGEN_TIME 100 //In deciseconds, how long it takes for shields to regenerate after breaking
|
||||
|
||||
//Clockwork marauder: A well-rounded frontline construct. Only one can exist for every two human servants.
|
||||
/mob/living/simple_animal/hostile/clockwork/marauder
|
||||
name = "clockwork marauder"
|
||||
@@ -20,9 +23,26 @@
|
||||
playstyle_string = "<b><span class='neovgre'>You are a clockwork marauder,</span> a well-rounded frontline construct of Ratvar. Although you have no \
|
||||
unique abilities, you're a fearsome fighter in one-on-one combat, and your shield protects from projectiles!<br><br>Obey the Servants and do as they \
|
||||
tell you. Your primary goal is to defend the Ark from destruction; they are your allies in this, and should be protected from harm.</b>"
|
||||
empower_string = "<span class='neovgre'>The Anima Bulwark's power flows through you! Your weapon will strike harder, your armor is sturdier, and your shield is considerably more \
|
||||
likely to deflect shots.</span>"
|
||||
empower_string = "<span class='neovgre'>The Anima Bulwark's power flows through you! Your weapon will strike harder, your armor is sturdier, and your shield is more durable.</span>"
|
||||
var/deflect_chance = 40 //Chance to deflect any given projectile (non-damaging energy projectiles are always deflected)
|
||||
var/max_shield_health = 3
|
||||
var/shield_health = 3 //Amount of projectiles that can be deflected within
|
||||
var/shield_health_regen = 0 //When world.time equals this, shield health will regenerate
|
||||
|
||||
/mob/living/simple_animal/hostile/clockwork/marauder/examine_info()
|
||||
if(!shield_health)
|
||||
return "<span class='warning'>Its shield has been destroyed!</span>"
|
||||
|
||||
/mob/living/simple_animal/hostile/clockwork/marauder/Life()
|
||||
..()
|
||||
if(!GLOB.ratvar_awakens && health / maxHealth <= MARAUDER_SLOWDOWN_PERCENTAGE)
|
||||
speed = initial(speed) + 1 //Yes, this slows them down
|
||||
else
|
||||
speed = initial(speed)
|
||||
if(shield_health != max_shield_health && world.time >= shield_health_regen)
|
||||
to_chat(src, "<span class='neovgre'>Your shield has recovered. <b>[max_shield_health]</b> blocks remaining!</span>")
|
||||
playsound_local(src, "shatter", 75, TRUE, frequency = -1)
|
||||
shield_health = max_shield_health
|
||||
|
||||
/mob/living/simple_animal/hostile/clockwork/marauder/update_values()
|
||||
if(GLOB.ratvar_awakens) //Massive attack damage bonuses and health increase, because Ratvar
|
||||
@@ -33,6 +53,7 @@
|
||||
attacktext = "devastates"
|
||||
speed = -1
|
||||
obj_damage = 100
|
||||
max_shield_health = INFINITY
|
||||
else if(GLOB.ratvar_approaches) //Hefty health bonus and slight attack damage increase
|
||||
health = 200
|
||||
maxHealth = 200
|
||||
@@ -40,6 +61,7 @@
|
||||
melee_damage_lower = 15
|
||||
attacktext = "carves"
|
||||
obj_damage = 50
|
||||
max_shield_health = 4
|
||||
|
||||
/mob/living/simple_animal/hostile/clockwork/marauder/death(gibbed)
|
||||
visible_message("<span class='danger'>[src]'s equipment clatters lifelessly to the ground as the red flames within dissipate.</span>", \
|
||||
@@ -64,21 +86,21 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/clockwork/marauder/proc/deflect_projectile(obj/item/projectile/P)
|
||||
var/final_deflection_chance = deflect_chance
|
||||
if(!shield_health)
|
||||
return
|
||||
var/energy_projectile = istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)
|
||||
if(P.nodamage || P.damage_type == STAMINA)
|
||||
final_deflection_chance = 100
|
||||
else if(!energy_projectile) //Flat 40% chance against energy projectiles; ballistic projectiles are 40% - (damage of projectile)%, min. 10%
|
||||
final_deflection_chance = max(10, deflect_chance - P.damage)
|
||||
if(GLOB.ratvar_awakens)
|
||||
final_deflection_chance = 100
|
||||
else if(GLOB.ratvar_approaches)
|
||||
final_deflection_chance = min(100, final_deflection_chance + 20) //20% bonus to deflection if the servants heralded Ratvar
|
||||
if(prob(final_deflection_chance))
|
||||
visible_message("<span class='danger'>[src] deflects [P] with their shield!</span>", \
|
||||
"<span class='danger'>You block [P] with your shield!</span>")
|
||||
if(energy_projectile)
|
||||
playsound(src, 'sound/weapons/effects/searwall.ogg', 50, TRUE)
|
||||
else
|
||||
playsound(src, "ricochet", 50, TRUE)
|
||||
. = TRUE
|
||||
visible_message("<span class='danger'>[src] deflects [P] with their shield!</span>", \
|
||||
"<span class='danger'>You block [P] with your shield! <i>Blocks left:</i> <b>[shield_health - 1]</b></span>")
|
||||
if(energy_projectile)
|
||||
playsound(src, 'sound/weapons/effects/searwall.ogg', 50, TRUE)
|
||||
else
|
||||
playsound(src, "ricochet", 50, TRUE)
|
||||
shield_health--
|
||||
if(!shield_health)
|
||||
visible_message("<span class='warning'>[src]'s shield breaks from deflecting the attack!</span>", "<span class='boldwarning'>Your shield breaks! Give it some time to recover...</span>")
|
||||
playsound(src, "shatter", 100, TRUE)
|
||||
shield_health_regen = world.time + MARAUDER_SHIELD_REGEN_TIME
|
||||
return TRUE
|
||||
|
||||
#undef MARAUDER_SLOWDOWN_PERCENTAGE
|
||||
#undef MARAUDER_SHIELD_REGEN_TIME
|
||||
|
||||
@@ -236,7 +236,7 @@
|
||||
if(A.outdoors || A.map_name == "Space" || !A.blob_allowed)
|
||||
to_chat(invoker, "<span class='danger'>Stargazers can't be built off-station.</span>")
|
||||
return
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
|
||||
//Integration Cog: Creates an integration cog that can be inserted into APCs to passively siphon power.
|
||||
|
||||
@@ -235,13 +235,25 @@
|
||||
sleep(125)
|
||||
make_glow()
|
||||
animate(glow, transform = matrix() * 3, alpha = 0, time = 5)
|
||||
var/turf/startpoint = get_turf(src)
|
||||
QDEL_IN(src, 3)
|
||||
sleep(3)
|
||||
GLOB.clockwork_gateway_activated = TRUE
|
||||
var/obj/structure/destructible/clockwork/massive/ratvar/R = new(startpoint)
|
||||
var/turf/T = locate(round(world.maxx * 0.5, 1), round(world.maxy * 0.5, 1), ZLEVEL_STATION_PRIMARY) //approximate center of the station
|
||||
R.forceMove(T)
|
||||
new /obj/structure/destructible/clockwork/massive/ratvar(T)
|
||||
SSticker.force_ending = TRUE
|
||||
var/x0 = T.x
|
||||
var/y0 = T.y
|
||||
for(var/I in spiral_range_turfs(255, T, tick_checked = TRUE))
|
||||
var/turf/T2 = I
|
||||
if(!T2)
|
||||
continue
|
||||
var/dist = cheap_hypotenuse(T2.x, T2.y, x0, y0)
|
||||
if(dist < 100)
|
||||
dist = TRUE
|
||||
else
|
||||
dist = FALSE
|
||||
T.ratvar_act(dist)
|
||||
CHECK_TICK
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -182,6 +182,10 @@
|
||||
/datum/game_mode/process()
|
||||
return 0
|
||||
|
||||
//For things that do not die easily
|
||||
/datum/game_mode/proc/are_special_antags_dead()
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/game_mode/proc/check_finished(force_ending) //to be called by SSticker
|
||||
if(!SSticker.setup_done)
|
||||
@@ -218,6 +222,9 @@
|
||||
living_antag_player = Player
|
||||
return 0
|
||||
|
||||
if(!are_special_antags_dead())
|
||||
return FALSE
|
||||
|
||||
if(!continuous[config_tag] || force_ending)
|
||||
return 1
|
||||
|
||||
|
||||
@@ -417,8 +417,9 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
toggle(user)
|
||||
|
||||
/obj/item/abductor_baton/proc/StunAttack(mob/living/L,mob/living/user)
|
||||
user.lastattacked = L
|
||||
L.lastattacker = user
|
||||
|
||||
L.lastattacker = user.real_name
|
||||
L.lastattackerckey = user.ckey
|
||||
|
||||
L.Knockdown(140)
|
||||
L.apply_effect(STUTTER, 7)
|
||||
@@ -490,7 +491,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
/obj/item/restraints/handcuffs/energy
|
||||
name = "hard-light energy field"
|
||||
desc = "A hard-light field restraining the hands."
|
||||
icon_state = "cuff_white" // Needs sprite
|
||||
icon_state = "cuff" // Needs sprite
|
||||
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
||||
breakouttime = 450
|
||||
|
||||
@@ -415,7 +415,6 @@ GLOBAL_VAR_INIT(total_borer_hosts_needed, 10)
|
||||
victim = C
|
||||
forceMove(victim)
|
||||
|
||||
SSticker.mode.update_borer_icons_added_host(victim.mind)
|
||||
|
||||
RemoveBorerActions()
|
||||
GrantInfestActions()
|
||||
@@ -591,7 +590,6 @@ GLOBAL_VAR_INIT(total_borer_hosts_needed, 10)
|
||||
var/mob/living/V = victim
|
||||
V.verbs -= /mob/living/proc/borer_comm
|
||||
talk_to_borer_action.Remove(victim)
|
||||
SSticker.mode.update_borer_icons_removed_host(victim.mind)
|
||||
victim = null
|
||||
return
|
||||
|
||||
@@ -1099,27 +1097,3 @@ GLOBAL_VAR_INIT(total_borer_hosts_needed, 10)
|
||||
/datum/action/innate/borer/jumpstart_host/Activate()
|
||||
var/mob/living/simple_animal/borer/B = owner
|
||||
B.jumpstart()
|
||||
|
||||
|
||||
//HUD STUFF
|
||||
/datum/game_mode/proc/update_borer_icons_added(datum/mind/borer_mind)
|
||||
var/datum/atom_hud/antag/borerhud = GLOB.huds[ANTAG_HUD_BORER]
|
||||
borerhud.join_hud(borer_mind.current)
|
||||
set_antag_hud(borer_mind.current, "hudbrainworm")
|
||||
|
||||
/datum/game_mode/proc/update_borer_icons_removed(datum/mind/borer_mind)
|
||||
var/datum/atom_hud/antag/borerhud = GLOB.huds[ANTAG_HUD_BORER]
|
||||
borerhud.leave_hud(borer_mind.current)
|
||||
set_antag_hud(borer_mind.current, null)
|
||||
|
||||
/datum/game_mode/proc/update_borer_icons_added_host(datum/mind/host_mind)
|
||||
var/datum/atom_hud/antag/hosthud = GLOB.huds[ANTAG_HUD_BORER] //Invisible to self
|
||||
hosthud.self_visible = FALSE
|
||||
hosthud.join_hud(host_mind.current)
|
||||
set_antag_hud(host_mind.current, "hudbrainworm")
|
||||
|
||||
/datum/game_mode/proc/update_borer_icons_removed_host(datum/mind/host_mind)
|
||||
var/datum/atom_hud/antag/hosthud = GLOB.huds[ANTAG_HUD_BORER] //Invisible to self
|
||||
hosthud.self_visible = FALSE //Probably not needed as we're deleting?
|
||||
hosthud.leave_hud(host_mind.current)
|
||||
set_antag_hud(host_mind.current, null)
|
||||
|
||||
@@ -54,9 +54,22 @@
|
||||
/datum/objective/proc/find_target()
|
||||
var/list/datum/mind/owners = get_owners()
|
||||
var/list/possible_targets = list()
|
||||
var/try_target_late_joiners = FALSE
|
||||
for(var/I in owners)
|
||||
var/datum/mind/O = I
|
||||
if(O.late_joiner)
|
||||
try_target_late_joiners = TRUE
|
||||
for(var/datum/mind/possible_target in get_crewmember_minds())
|
||||
if(!(possible_target in owners) && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && is_unique_objective(possible_target))
|
||||
possible_targets += possible_target
|
||||
if(try_target_late_joiners)
|
||||
var/list/all_possible_targets = possible_targets.Copy()
|
||||
for(var/I in all_possible_targets)
|
||||
var/datum/mind/PT = I
|
||||
if(!PT.late_joiner)
|
||||
possible_targets -= PT
|
||||
if(!possible_targets.len)
|
||||
possible_targets = all_possible_targets
|
||||
if(possible_targets.len > 0)
|
||||
target = pick(possible_targets)
|
||||
update_explanation_text()
|
||||
|
||||
@@ -60,7 +60,9 @@
|
||||
|
||||
/datum/game_mode/traitor/post_setup()
|
||||
for(var/datum/mind/traitor in pre_traitors)
|
||||
addtimer(CALLBACK(traitor, /datum/mind.proc/add_antag_datum, antag_datum), rand(10,100))
|
||||
var/datum/antagonist/traitor/new_antag = new antag_datum(traitor)
|
||||
new_antag.should_specialise = TRUE
|
||||
addtimer(CALLBACK(traitor, /datum/mind.proc/add_antag_datum, new_antag), rand(10,100))
|
||||
if(!exchange_blue)
|
||||
exchange_blue = -1 //Block latejoiners from getting exchange objectives
|
||||
..()
|
||||
@@ -79,6 +81,8 @@
|
||||
add_latejoin_traitor(character.mind)
|
||||
|
||||
/datum/game_mode/traitor/proc/add_latejoin_traitor(datum/mind/character)
|
||||
var/datum/antagonist/traitor/new_antag = new antag_datum(character)
|
||||
new_antag.should_specialise = TRUE
|
||||
character.add_antag_datum(antag_datum)
|
||||
|
||||
|
||||
|
||||
@@ -44,6 +44,11 @@
|
||||
if(spent)
|
||||
to_chat(user, "<span class='cult'>This shard is spent; it is now just a creepy rock.</span>")
|
||||
|
||||
/obj/item/device/soulstone/Destroy() //Stops the shade from being qdel'd immediately and their ghost being sent back to the arrival shuttle.
|
||||
for(var/mob/living/simple_animal/shade/A in src)
|
||||
A.death()
|
||||
return ..()
|
||||
|
||||
//////////////////////////////Capturing////////////////////////////////////////////////////////
|
||||
|
||||
/obj/item/device/soulstone/attack(mob/living/carbon/human/M, mob/living/user)
|
||||
@@ -228,6 +233,7 @@
|
||||
|
||||
/obj/item/device/soulstone/proc/init_shade(mob/living/carbon/human/T, mob/U, vic = 0)
|
||||
new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton
|
||||
T.stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
T.invisibility = INVISIBILITY_ABSTRACT
|
||||
T.dust_animation()
|
||||
var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade(src)
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
man is a dangerous mutant with the ability to alter himself and the world around him by what he and his leaders believe to be magic. If this man attempts an attack on your station, \
|
||||
his execution is highly encouraged, as is the preservation of his body for later study."
|
||||
|
||||
/datum/game_mode/wizard/check_finished()
|
||||
|
||||
/datum/game_mode/wizard/are_special_antags_dead()
|
||||
for(var/datum/mind/wizard in wizards)
|
||||
if(isliving(wizard.current) && wizard.current.stat!=DEAD)
|
||||
return FALSE
|
||||
@@ -54,8 +55,8 @@
|
||||
if(SSevents.wizardmode) //If summon events was active, turn it off
|
||||
SSevents.toggleWizardmode()
|
||||
SSevents.resetFrequency()
|
||||
|
||||
return ..()
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/wizard/declare_completion()
|
||||
if(finished)
|
||||
|
||||
@@ -1,72 +1,71 @@
|
||||
/obj/machinery/camera
|
||||
|
||||
var/list/localMotionTargets = list()
|
||||
var/detectTime = 0
|
||||
var/area/ai_monitored/area_motion = null
|
||||
var/alarm_delay = 30 // Don't forget, there's another 3 seconds in queueAlarm()
|
||||
|
||||
/obj/machinery/camera/process()
|
||||
// motion camera event loop
|
||||
if(!isMotion())
|
||||
. = PROCESS_KILL
|
||||
return
|
||||
if (detectTime > 0)
|
||||
var/elapsed = world.time - detectTime
|
||||
if (elapsed > alarm_delay)
|
||||
triggerAlarm()
|
||||
else if (detectTime == -1)
|
||||
for (var/mob/target in getTargetList())
|
||||
if (target.stat == DEAD || (!area_motion && !in_range(src, target)))
|
||||
//If not part of a monitored area and the camera is not in range or the target is dead
|
||||
lostTarget(target)
|
||||
|
||||
/obj/machinery/camera/proc/getTargetList()
|
||||
if(area_motion)
|
||||
return area_motion.motionTargets
|
||||
return localMotionTargets
|
||||
|
||||
/obj/machinery/camera/proc/newTarget(mob/target)
|
||||
if(isAI(target))
|
||||
return 0
|
||||
if (detectTime == 0)
|
||||
detectTime = world.time // start the clock
|
||||
var/list/targets = getTargetList()
|
||||
if (!(target in targets))
|
||||
targets += target
|
||||
return 1
|
||||
|
||||
/obj/machinery/camera/Destroy()
|
||||
var/area/ai_monitored/A = get_area(src)
|
||||
if(istype(A))
|
||||
A.motioncameras -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/camera/proc/lostTarget(mob/target)
|
||||
var/list/targets = getTargetList()
|
||||
if (target in targets)
|
||||
targets -= target
|
||||
if (targets.len == 0)
|
||||
cancelAlarm()
|
||||
|
||||
/obj/machinery/camera/proc/cancelAlarm()
|
||||
if (detectTime == -1)
|
||||
for (var/mob/living/silicon/aiPlayer in GLOB.player_list)
|
||||
if (status)
|
||||
aiPlayer.cancelAlarm("Motion", get_area(src), src)
|
||||
detectTime = 0
|
||||
return 1
|
||||
|
||||
/obj/machinery/camera/proc/triggerAlarm()
|
||||
if (!detectTime)
|
||||
return 0
|
||||
for (var/mob/living/silicon/aiPlayer in GLOB.player_list)
|
||||
if (status)
|
||||
aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src)
|
||||
detectTime = -1
|
||||
return 1
|
||||
|
||||
/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj)
|
||||
// Motion cameras outside of an "ai monitored" area will use this to detect stuff.
|
||||
if (!area_motion)
|
||||
if(isliving(AM))
|
||||
newTarget(AM)
|
||||
/obj/machinery/camera
|
||||
|
||||
var/list/localMotionTargets = list()
|
||||
var/detectTime = 0
|
||||
var/area/ai_monitored/area_motion = null
|
||||
var/alarm_delay = 30 // Don't forget, there's another 3 seconds in queueAlarm()
|
||||
|
||||
/obj/machinery/camera/process()
|
||||
// motion camera event loop
|
||||
if(!isMotion())
|
||||
. = PROCESS_KILL
|
||||
return
|
||||
if (detectTime > 0)
|
||||
var/elapsed = world.time - detectTime
|
||||
if (elapsed > alarm_delay)
|
||||
triggerAlarm()
|
||||
else if (detectTime == -1)
|
||||
for (var/targetref in getTargetList())
|
||||
var/mob/target = locate(targetref) in GLOB.mob_list
|
||||
if (target.stat == DEAD || QDELETED(target) || (!area_motion && !in_range(src, target)))
|
||||
//If not part of a monitored area and the camera is not in range or the target is dead
|
||||
lostTarget(target)
|
||||
|
||||
/obj/machinery/camera/proc/getTargetList()
|
||||
if(area_motion)
|
||||
return area_motion.motionTargets
|
||||
return localMotionTargets
|
||||
|
||||
/obj/machinery/camera/proc/newTarget(mob/target)
|
||||
if(isAI(target))
|
||||
return 0
|
||||
if (detectTime == 0)
|
||||
detectTime = world.time // start the clock
|
||||
var/list/targets = getTargetList()
|
||||
targets |= "\ref[target]"
|
||||
return 1
|
||||
|
||||
/obj/machinery/camera/Destroy()
|
||||
var/area/ai_monitored/A = get_area(src)
|
||||
if(istype(A))
|
||||
A.motioncameras -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/camera/proc/lostTarget(mob/target)
|
||||
var/list/targets = getTargetList()
|
||||
targets -= "\ref[target]"
|
||||
if (targets.len == 0)
|
||||
cancelAlarm()
|
||||
|
||||
/obj/machinery/camera/proc/cancelAlarm()
|
||||
if (detectTime == -1)
|
||||
for (var/mob/living/silicon/aiPlayer in GLOB.player_list)
|
||||
if (status)
|
||||
aiPlayer.cancelAlarm("Motion", get_area(src), src)
|
||||
detectTime = 0
|
||||
return 1
|
||||
|
||||
/obj/machinery/camera/proc/triggerAlarm()
|
||||
if (!detectTime)
|
||||
return 0
|
||||
for (var/mob/living/silicon/aiPlayer in GLOB.player_list)
|
||||
if (status)
|
||||
aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src)
|
||||
detectTime = -1
|
||||
return 1
|
||||
|
||||
/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj)
|
||||
// Motion cameras outside of an "ai monitored" area will use this to detect stuff.
|
||||
if (!area_motion)
|
||||
if(isliving(AM))
|
||||
newTarget(AM)
|
||||
|
||||
@@ -61,6 +61,14 @@
|
||||
for(var/datum/surgery/procedure in patient.surgeries)
|
||||
dat += "[capitalize(procedure.name)]<BR>"
|
||||
var/datum/surgery_step/surgery_step = procedure.get_surgery_step()
|
||||
dat += "Next step: [capitalize(surgery_step.name)]<BR>"
|
||||
dat += "Next step: [capitalize(surgery_step.name)]"
|
||||
if(surgery_step.repeatable)
|
||||
dat += " or "
|
||||
var/datum/surgery_step/next_step = procedure.get_surgery_next_step()
|
||||
if(next_step)
|
||||
dat += "[capitalize(next_step.name)]"
|
||||
else
|
||||
dat += "finish operation"
|
||||
dat += "<BR>"
|
||||
dat += "</div>"
|
||||
return dat
|
||||
return dat
|
||||
|
||||
@@ -537,10 +537,13 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
/obj/machinery/computer/card/proc/eject_id_scan(mob/user)
|
||||
if(scan)
|
||||
scan.forceMove(drop_location())
|
||||
user.put_in_hands(scan)
|
||||
if(!issilicon(user) && Adjacent(user))
|
||||
user.put_in_hands(scan)
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
scan = null
|
||||
else //switching the ID with the one you're holding
|
||||
if(issilicon(user) || !Adjacent(user))
|
||||
return
|
||||
var/obj/item/I = user.get_active_held_item()
|
||||
if(istype(I, /obj/item/card/id))
|
||||
if(!user.transferItemToLoc(I,src))
|
||||
@@ -555,12 +558,15 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
GLOB.data_core.manifest_modify(modify.registered_name, modify.assignment)
|
||||
modify.update_label()
|
||||
modify.forceMove(drop_location())
|
||||
user.put_in_hands(modify)
|
||||
if(!issilicon(user) && Adjacent(user))
|
||||
user.put_in_hands(modify)
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
modify = null
|
||||
region_access = null
|
||||
head_subordinates = null
|
||||
else //switching the ID with the one you're holding
|
||||
if(issilicon(user) || !Adjacent(user))
|
||||
return
|
||||
var/obj/item/I = user.get_active_held_item()
|
||||
if(istype(I, /obj/item/card/id))
|
||||
if (!user.transferItemToLoc(I,src))
|
||||
|
||||
@@ -246,14 +246,16 @@
|
||||
note = null
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/door/airlock/proc/unzap() //for addtimer
|
||||
justzap = FALSE
|
||||
|
||||
/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())
|
||||
if(!src.justzap)
|
||||
if(src.shock(user, 100))
|
||||
src.justzap = TRUE
|
||||
spawn (10)
|
||||
justzap = FALSE
|
||||
if(isElectrified())
|
||||
if(!justzap)
|
||||
if(shock(user, 100))
|
||||
justzap = TRUE
|
||||
addtimer(CALLBACK(src, .proc/unzap), 10)
|
||||
return
|
||||
else /*if(src.justzap)*/
|
||||
return
|
||||
@@ -325,33 +327,34 @@
|
||||
if(src.secondsMainPowerLost > 0)
|
||||
src.secondsMainPowerLost = 0
|
||||
|
||||
/obj/machinery/door/airlock/proc/loseMainPower()
|
||||
if(src.secondsMainPowerLost <= 0)
|
||||
src.secondsMainPowerLost = 60
|
||||
if(src.secondsBackupPowerLost < 10)
|
||||
src.secondsBackupPowerLost = 10
|
||||
if(!src.spawnPowerRestoreRunning)
|
||||
spawnPowerRestoreRunning = TRUE
|
||||
spawn(0)
|
||||
var/cont = 1
|
||||
while (cont)
|
||||
sleep(10)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
cont = 0
|
||||
if(secondsMainPowerLost>0)
|
||||
if(!wires.is_cut(WIRE_POWER1) && !wires.is_cut(WIRE_POWER2))
|
||||
secondsMainPowerLost -= 1
|
||||
updateDialog()
|
||||
cont = 1
|
||||
/obj/machinery/door/airlock/proc/handlePowerRestore()
|
||||
var/cont = TRUE
|
||||
while (cont)
|
||||
sleep(10)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
cont = FALSE
|
||||
if(secondsMainPowerLost>0)
|
||||
if(!wires.is_cut(WIRE_POWER1) && !wires.is_cut(WIRE_POWER2))
|
||||
secondsMainPowerLost -= 1
|
||||
updateDialog()
|
||||
cont = TRUE
|
||||
if(secondsBackupPowerLost>0)
|
||||
if(!wires.is_cut(WIRE_BACKUP1) && !wires.is_cut(WIRE_BACKUP2))
|
||||
secondsBackupPowerLost -= 1
|
||||
updateDialog()
|
||||
cont = TRUE
|
||||
spawnPowerRestoreRunning = FALSE
|
||||
updateDialog()
|
||||
|
||||
if(secondsBackupPowerLost>0)
|
||||
if(!wires.is_cut(WIRE_BACKUP1) && !wires.is_cut(WIRE_BACKUP2))
|
||||
secondsBackupPowerLost -= 1
|
||||
updateDialog()
|
||||
cont = 1
|
||||
spawnPowerRestoreRunning = FALSE
|
||||
updateDialog()
|
||||
/obj/machinery/door/airlock/proc/loseMainPower()
|
||||
if(secondsMainPowerLost <= 0)
|
||||
secondsMainPowerLost = 60
|
||||
if(secondsBackupPowerLost < 10)
|
||||
secondsBackupPowerLost = 10
|
||||
if(!spawnPowerRestoreRunning)
|
||||
spawnPowerRestoreRunning = TRUE
|
||||
INVOKE_ASYNC(src, .proc/handlePowerRestore)
|
||||
|
||||
/obj/machinery/door/airlock/proc/loseBackupPower()
|
||||
if(src.secondsBackupPowerLost < 60)
|
||||
@@ -792,6 +795,13 @@
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/machinery/door/airlock/proc/electrified_loop()
|
||||
while (secondsElectrified > 0)
|
||||
secondsElectrified--
|
||||
if(secondsElectrified <= 0)
|
||||
set_electrified(NOT_ELECTRIFIED)
|
||||
updateUsrDialog()
|
||||
sleep(10)
|
||||
|
||||
/obj/machinery/door/airlock/Topic(href, href_list, var/nowindow = 0)
|
||||
// If you add an if(..()) check you must first remove the var/nowindow parameter.
|
||||
@@ -936,13 +946,7 @@
|
||||
shockedby += "\[[time_stamp()]\][usr](ckey:[usr.ckey])"
|
||||
add_logs(usr, src, "electrified")
|
||||
set_electrified(30)
|
||||
spawn(10)
|
||||
while (secondsElectrified > 0)
|
||||
secondsElectrified--
|
||||
if(secondsElectrified <= 0)
|
||||
set_electrified(NOT_ELECTRIFIED)
|
||||
updateUsrDialog()
|
||||
sleep(10)
|
||||
addtimer(CALLBACK(src, .proc/electrified_loop), 10)
|
||||
if(6)
|
||||
//electrify door indefinitely
|
||||
if(wires.is_cut(WIRE_SHOCK))
|
||||
@@ -1266,19 +1270,11 @@
|
||||
if(!beingcrowbarred) //being fireaxe'd
|
||||
var/obj/item/twohanded/fireaxe/F = I
|
||||
if(F.wielded)
|
||||
spawn(0)
|
||||
if(density)
|
||||
open(2)
|
||||
else
|
||||
close(2)
|
||||
INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to be wielding the fire axe to do that!</span>")
|
||||
else
|
||||
spawn(0)
|
||||
if(density)
|
||||
open(2)
|
||||
else
|
||||
close(2)
|
||||
INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2)
|
||||
|
||||
if(istype(I, /obj/item/crowbar/power))
|
||||
if(isElectrified())
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
sub_door = TRUE
|
||||
explosion_block = 1
|
||||
safe = FALSE
|
||||
layer = BELOW_OPEN_DOOR_LAYER
|
||||
closingLayer = CLOSED_FIREDOOR_LAYER
|
||||
assemblytype = /obj/structure/firelock_frame
|
||||
armor = list(melee = 30, bullet = 30, laser = 20, energy = 20, bomb = 10, bio = 100, rad = 100, fire = 95, acid = 70)
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
/obj/machinery/door/poddoor/shutters
|
||||
gender = PLURAL
|
||||
name = "shutters"
|
||||
desc = "Heavy duty metal shutters that opens mechanically."
|
||||
icon = 'icons/obj/doors/shutters.dmi'
|
||||
layer = CLOSED_DOOR_LAYER
|
||||
damage_deflection = 20
|
||||
|
||||
/obj/machinery/door/poddoor/shutters/preopen
|
||||
icon_state = "open"
|
||||
/obj/machinery/door/poddoor/shutters
|
||||
gender = PLURAL
|
||||
name = "shutters"
|
||||
desc = "Heavy duty metal shutters that opens mechanically."
|
||||
icon = 'icons/obj/doors/shutters.dmi'
|
||||
layer = SHUTTER_LAYER
|
||||
damage_deflection = 20
|
||||
|
||||
/obj/machinery/door/poddoor/shutters/preopen
|
||||
icon_state = "open"
|
||||
density = FALSE
|
||||
opacity = 0
|
||||
|
||||
|
||||
//shutters look like ass with things on top of them.
|
||||
|
||||
/obj/machinery/door/poddoor/shutters/New()
|
||||
..()
|
||||
layer = CLOSED_DOOR_LAYER //to handle /obj/machinery/door/New() resetting the layer.
|
||||
|
||||
|
||||
/obj/machinery/door/poddoor/shutters/open(ignorepower = 0)
|
||||
..()
|
||||
layer = CLOSED_DOOR_LAYER
|
||||
|
||||
|
||||
/obj/machinery/door/poddoor/shutters/close(ignorepower = 0)
|
||||
..()
|
||||
layer = CLOSED_DOOR_LAYER
|
||||
opacity = 0
|
||||
|
||||
|
||||
//shutters look like ass with things on top of them.
|
||||
|
||||
/obj/machinery/door/poddoor/shutters/New()
|
||||
..()
|
||||
layer = CLOSED_DOOR_LAYER //to handle /obj/machinery/door/New() resetting the layer.
|
||||
|
||||
|
||||
/obj/machinery/door/poddoor/shutters/open(ignorepower = 0)
|
||||
..()
|
||||
layer = CLOSED_DOOR_LAYER
|
||||
|
||||
|
||||
/obj/machinery/door/poddoor/shutters/close(ignorepower = 0)
|
||||
..()
|
||||
layer = CLOSED_DOOR_LAYER
|
||||
|
||||
@@ -10,15 +10,14 @@
|
||||
var/mob/living/carbon/attached = null
|
||||
var/mode = IV_INJECTING
|
||||
var/obj/item/reagent_containers/beaker = null
|
||||
var/list/drip_containers = list(/obj/item/reagent_containers/blood,
|
||||
/obj/item/reagent_containers/food,
|
||||
/obj/item/reagent_containers/glass)
|
||||
var/static/list/drip_containers = typecacheof(list(/obj/item/reagent_containers/blood,
|
||||
/obj/item/reagent_containers/food,
|
||||
/obj/item/reagent_containers/glass))
|
||||
|
||||
/obj/machinery/iv_drip/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
drip_containers = typecacheof(drip_containers)
|
||||
|
||||
|
||||
/obj/machinery/iv_drip/Destroy()
|
||||
attached = null
|
||||
QDEL_NULL(beaker)
|
||||
|
||||
@@ -1,72 +1,71 @@
|
||||
// the light switch
|
||||
// can have multiple per area
|
||||
// can also operate on non-loc area through "otherarea" var
|
||||
/obj/machinery/light_switch
|
||||
name = "light switch"
|
||||
icon = 'icons/obj/power.dmi'
|
||||
icon_state = "light1"
|
||||
// the light switch
|
||||
// can have multiple per area
|
||||
// can also operate on non-loc area through "otherarea" var
|
||||
/obj/machinery/light_switch
|
||||
name = "light switch"
|
||||
icon = 'icons/obj/power.dmi'
|
||||
icon_state = "light1"
|
||||
anchored = TRUE
|
||||
desc = "Make dark."
|
||||
var/on = TRUE
|
||||
var/area/area = null
|
||||
var/otherarea = null
|
||||
// luminosity = 1
|
||||
|
||||
/obj/machinery/light_switch/Initialize()
|
||||
var/area/area = null
|
||||
var/otherarea = null
|
||||
|
||||
/obj/machinery/light_switch/Initialize()
|
||||
. = ..()
|
||||
area = get_area(src)
|
||||
|
||||
if(otherarea)
|
||||
area = locate(text2path("/area/[otherarea]"))
|
||||
|
||||
if(!name)
|
||||
name = "light switch ([area.name])"
|
||||
|
||||
on = area.lightswitch
|
||||
updateicon()
|
||||
|
||||
/obj/machinery/light_switch/proc/updateicon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "light-p"
|
||||
else
|
||||
if(on)
|
||||
icon_state = "light1"
|
||||
else
|
||||
icon_state = "light0"
|
||||
|
||||
/obj/machinery/light_switch/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "It is [on? "on" : "off"].")
|
||||
|
||||
|
||||
/obj/machinery/light_switch/attack_paw(mob/user)
|
||||
src.attack_hand(user)
|
||||
|
||||
/obj/machinery/light_switch/attack_hand(mob/user)
|
||||
|
||||
on = !on
|
||||
|
||||
for(var/area/A in area.related)
|
||||
A.lightswitch = on
|
||||
A.updateicon()
|
||||
|
||||
for(var/obj/machinery/light_switch/L in A)
|
||||
L.on = on
|
||||
L.updateicon()
|
||||
|
||||
area.power_change()
|
||||
|
||||
/obj/machinery/light_switch/power_change()
|
||||
|
||||
if(!otherarea)
|
||||
if(powered(LIGHT))
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
|
||||
updateicon()
|
||||
|
||||
/obj/machinery/light_switch/emp_act(severity)
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
power_change()
|
||||
..()
|
||||
area = get_area(src)
|
||||
|
||||
if(otherarea)
|
||||
area = locate(text2path("/area/[otherarea]"))
|
||||
|
||||
if(!name)
|
||||
name = "light switch ([area.name])"
|
||||
|
||||
on = area.lightswitch
|
||||
updateicon()
|
||||
|
||||
/obj/machinery/light_switch/proc/updateicon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "light-p"
|
||||
else
|
||||
if(on)
|
||||
icon_state = "light1"
|
||||
else
|
||||
icon_state = "light0"
|
||||
|
||||
/obj/machinery/light_switch/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "It is [on? "on" : "off"].")
|
||||
|
||||
|
||||
/obj/machinery/light_switch/attack_paw(mob/user)
|
||||
src.attack_hand(user)
|
||||
|
||||
/obj/machinery/light_switch/attack_hand(mob/user)
|
||||
|
||||
on = !on
|
||||
|
||||
for(var/area/A in area.related)
|
||||
A.lightswitch = on
|
||||
A.updateicon()
|
||||
|
||||
for(var/obj/machinery/light_switch/L in A)
|
||||
L.on = on
|
||||
L.updateicon()
|
||||
|
||||
area.power_change()
|
||||
|
||||
/obj/machinery/light_switch/power_change()
|
||||
|
||||
if(!otherarea)
|
||||
if(powered(LIGHT))
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
|
||||
updateicon()
|
||||
|
||||
/obj/machinery/light_switch/emp_act(severity)
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
power_change()
|
||||
..()
|
||||
|
||||
@@ -10,7 +10,7 @@ Buildable meters
|
||||
/obj/item/pipe
|
||||
name = "pipe"
|
||||
desc = "A pipe."
|
||||
var/pipe_type = 0
|
||||
var/pipe_type
|
||||
var/pipename
|
||||
force = 7
|
||||
throwforce = 7
|
||||
@@ -19,35 +19,22 @@ Buildable meters
|
||||
item_state = "buildpipe"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
level = 2
|
||||
var/flipped = FALSE
|
||||
var/is_bent = FALSE
|
||||
var/piping_layer = PIPING_LAYER_DEFAULT
|
||||
var/RPD_type //TEMP: kill this once RPDs get a rewrite pls
|
||||
|
||||
var/static/list/pipe_types = list(
|
||||
PIPE_SIMPLE, \
|
||||
PIPE_LAYER_MANIFOLD, \
|
||||
PIPE_MANIFOLD, \
|
||||
PIPE_4WAYMANIFOLD, \
|
||||
PIPE_HE, \
|
||||
PIPE_HE_MANIFOLD, \
|
||||
PIPE_HE_4WAYMANIFOLD, \
|
||||
PIPE_JUNCTION, \
|
||||
\
|
||||
PIPE_CONNECTOR, \
|
||||
PIPE_UVENT, \
|
||||
PIPE_SCRUBBER, \
|
||||
PIPE_INJECTOR, \
|
||||
PIPE_HEAT_EXCHANGE, \
|
||||
\
|
||||
PIPE_PUMP, \
|
||||
PIPE_PASSIVE_GATE, \
|
||||
PIPE_VOLUME_PUMP, \
|
||||
PIPE_MVALVE, \
|
||||
PIPE_DVALVE, \
|
||||
\
|
||||
PIPE_GAS_FILTER, \
|
||||
PIPE_GAS_MIXER, \
|
||||
)
|
||||
/obj/item/pipe/directional
|
||||
RPD_type = PIPE_UNARY
|
||||
/obj/item/pipe/binary
|
||||
RPD_type = PIPE_BINARY
|
||||
/obj/item/pipe/binary/bendable
|
||||
RPD_type = PIPE_BENDABLE
|
||||
/obj/item/pipe/trinary
|
||||
RPD_type = PIPE_TRINARY
|
||||
/obj/item/pipe/trinary/flippable
|
||||
RPD_type = PIPE_TRIN_M
|
||||
var/flipped = FALSE
|
||||
/obj/item/pipe/quaternary
|
||||
RPD_type = PIPE_QUAD
|
||||
|
||||
/obj/item/pipe/examine(mob/user)
|
||||
..()
|
||||
@@ -55,35 +42,27 @@ Buildable meters
|
||||
|
||||
/obj/item/pipe/Initialize(mapload, _pipe_type, _dir, obj/machinery/atmospherics/make_from)
|
||||
if(make_from)
|
||||
setDir(make_from.dir)
|
||||
pipename = make_from.name
|
||||
add_atom_colour(make_from.color, FIXED_COLOUR_PRIORITY)
|
||||
|
||||
if(make_from.type in pipe_types)
|
||||
pipe_type = make_from.type
|
||||
setPipingLayer(make_from.piping_layer)
|
||||
else //make pipe_type a value we can work with
|
||||
for(var/P in pipe_types)
|
||||
if(istype(make_from, P))
|
||||
pipe_type = P
|
||||
break
|
||||
|
||||
var/obj/machinery/atmospherics/components/trinary/triP = make_from
|
||||
if(istype(triP) && triP.flipped)
|
||||
flipped = TRUE
|
||||
setDir(turn(dir, -45))
|
||||
make_from_existing(make_from)
|
||||
else
|
||||
pipe_type = _pipe_type
|
||||
setDir(_dir)
|
||||
|
||||
if(_dir in GLOB.diagonals)
|
||||
is_bent = TRUE
|
||||
|
||||
update()
|
||||
pixel_x = rand(-5, 5)
|
||||
pixel_y = rand(-5, 5)
|
||||
pixel_x += rand(-5, 5)
|
||||
pixel_y += rand(-5, 5)
|
||||
return ..()
|
||||
|
||||
/obj/item/pipe/proc/make_from_existing(obj/machinery/atmospherics/make_from)
|
||||
setDir(make_from.dir)
|
||||
pipename = make_from.name
|
||||
add_atom_colour(make_from.color, FIXED_COLOUR_PRIORITY)
|
||||
pipe_type = make_from.type
|
||||
|
||||
/obj/item/pipe/trinary/flippable/make_from_existing(obj/machinery/atmospherics/components/trinary/make_from)
|
||||
..()
|
||||
if(make_from.flipped)
|
||||
do_a_flip()
|
||||
|
||||
/obj/item/pipe/dropped()
|
||||
if(loc)
|
||||
setPipingLayer(piping_layer)
|
||||
@@ -91,73 +70,19 @@ Buildable meters
|
||||
|
||||
/obj/item/pipe/proc/setPipingLayer(new_layer = PIPING_LAYER_DEFAULT)
|
||||
var/obj/machinery/atmospherics/fakeA = get_pipe_cache(pipe_type)
|
||||
var/nolayer = (fakeA.pipe_flags & PIPING_ALL_LAYER)
|
||||
if(nolayer)
|
||||
|
||||
if(fakeA.pipe_flags & PIPING_ALL_LAYER)
|
||||
new_layer = PIPING_LAYER_DEFAULT
|
||||
piping_layer = new_layer
|
||||
if(pipe_type != PIPE_LAYER_MANIFOLD)
|
||||
pixel_x = (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X
|
||||
pixel_y = (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y
|
||||
layer = initial(layer) + ((piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE)
|
||||
|
||||
//update the name and icon of the pipe item depending on the type
|
||||
GLOBAL_LIST_INIT(pipeID2State, list(
|
||||
"[PIPE_SIMPLE]" = "simple", \
|
||||
"[PIPE_MANIFOLD]" = "manifold", \
|
||||
"[PIPE_LAYER_MANIFOLD]" = "layer_manifold", \
|
||||
"[PIPE_4WAYMANIFOLD]" = "manifold4w", \
|
||||
"[PIPE_HE]" = "he", \
|
||||
"[PIPE_HE_MANIFOLD]" = "he_manifold", \
|
||||
"[PIPE_HE_4WAYMANIFOLD]" = "he_manifold4w", \
|
||||
"[PIPE_JUNCTION]" = "junction", \
|
||||
\
|
||||
"[PIPE_CONNECTOR]" = "connector", \
|
||||
"[PIPE_UVENT]" = "uvent", \
|
||||
"[PIPE_SCRUBBER]" = "scrubber", \
|
||||
"[PIPE_INJECTOR]" = "injector", \
|
||||
"[PIPE_HEAT_EXCHANGE]" = "heunary", \
|
||||
\
|
||||
"[PIPE_PUMP]" = "pump", \
|
||||
"[PIPE_PASSIVE_GATE]" = "passivegate", \
|
||||
"[PIPE_VOLUME_PUMP]" = "volumepump", \
|
||||
"[PIPE_MVALVE]" = "mvalve", \
|
||||
"[PIPE_DVALVE]" = "dvalve", \
|
||||
\
|
||||
"[PIPE_GAS_FILTER]" = "filter", \
|
||||
"[PIPE_GAS_MIXER]" = "mixer", \
|
||||
))
|
||||
pixel_x += (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X
|
||||
pixel_y += (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y
|
||||
layer = initial(layer) + ((piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE)
|
||||
|
||||
/obj/item/pipe/proc/update()
|
||||
var/list/nlist = list(\
|
||||
"[PIPE_SIMPLE]" = "pipe", \
|
||||
"[PIPE_SIMPLE]_b" = "bent pipe", \
|
||||
"[PIPE_MANIFOLD]" = "manifold", \
|
||||
"[PIPE_LAYER_MANIFOLD]" = "layer manifold", \
|
||||
"[PIPE_4WAYMANIFOLD]" = "4-way manifold", \
|
||||
"[PIPE_HE]" = "h/e pipe", \
|
||||
"[PIPE_HE]_b" = "bent h/e pipe", \
|
||||
"[PIPE_HE_MANIFOLD]" = "h/e manifold", \
|
||||
"[PIPE_HE_4WAYMANIFOLD]"= "h/e 4-way manifold", \
|
||||
"[PIPE_JUNCTION]" = "junction", \
|
||||
\
|
||||
"[PIPE_CONNECTOR]" = "connector", \
|
||||
"[PIPE_UVENT]" = "vent", \
|
||||
"[PIPE_SCRUBBER]" = "scrubber", \
|
||||
"[PIPE_INJECTOR]" = "injector", \
|
||||
"[PIPE_HEAT_EXCHANGE]" = "heat exchanger", \
|
||||
\
|
||||
"[PIPE_PUMP]" = "pump", \
|
||||
"[PIPE_PASSIVE_GATE]" = "passive gate", \
|
||||
"[PIPE_VOLUME_PUMP]" = "volume pump", \
|
||||
"[PIPE_MVALVE]" = "manual valve", \
|
||||
"[PIPE_DVALVE]" = "digital valve", \
|
||||
\
|
||||
"[PIPE_GAS_FILTER]" = "gas filter", \
|
||||
"[PIPE_GAS_MIXER]" = "gas mixer", \
|
||||
)
|
||||
//fix_pipe_type()
|
||||
name = nlist["[pipe_type][is_bent ? "_b" : ""]"] + " fitting"
|
||||
icon_state = GLOB.pipeID2State["[pipe_type]"]
|
||||
var/obj/machinery/atmospherics/A = get_pipe_cache(pipe_type)
|
||||
name = "[A.name] fitting"
|
||||
icon_state = A.pipe_state
|
||||
|
||||
// rotate the pipe item clockwise
|
||||
|
||||
@@ -170,11 +95,8 @@ GLOBAL_LIST_INIT(pipeID2State, list(
|
||||
return
|
||||
|
||||
setDir(turn(dir, -90))
|
||||
|
||||
fixdir()
|
||||
|
||||
return
|
||||
|
||||
/obj/item/pipe/verb/flip()
|
||||
set category = "Object"
|
||||
set name = "Flip Pipe"
|
||||
@@ -183,16 +105,15 @@ GLOBAL_LIST_INIT(pipeID2State, list(
|
||||
if ( usr.stat || usr.restrained() || !usr.canmove )
|
||||
return
|
||||
|
||||
if (pipe_type in list(PIPE_GAS_FILTER, PIPE_GAS_MIXER))
|
||||
setDir(turn(dir, flipped )? 45 : -45)
|
||||
flipped = !flipped
|
||||
return
|
||||
do_a_flip()
|
||||
|
||||
/obj/item/pipe/proc/do_a_flip()
|
||||
setDir(turn(dir, -180))
|
||||
|
||||
fixdir()
|
||||
|
||||
return
|
||||
/obj/item/pipe/trinary/flippable/do_a_flip()
|
||||
setDir(turn(dir, flipped ? 45 : -45))
|
||||
flipped = !flipped
|
||||
|
||||
/obj/item/pipe/AltClick(mob/user)
|
||||
..()
|
||||
@@ -207,21 +128,21 @@ GLOBAL_LIST_INIT(pipeID2State, list(
|
||||
/obj/item/pipe/Move()
|
||||
var/old_dir = dir
|
||||
..()
|
||||
setDir(old_dir )//pipes changing direction when moved is just annoying and buggy
|
||||
|
||||
/obj/item/pipe/proc/unflip(direction)
|
||||
if(direction in GLOB.diagonals)
|
||||
return turn(direction, 45)
|
||||
|
||||
return direction
|
||||
setDir(old_dir) //pipes changing direction when moved is just annoying and buggy
|
||||
|
||||
//Helper to clean up dir
|
||||
/obj/item/pipe/proc/fixdir()
|
||||
if((pipe_type in list (PIPE_SIMPLE, PIPE_HE, PIPE_MVALVE, PIPE_DVALVE, PIPE_LAYER_MANIFOLD)) && !is_bent)
|
||||
if(dir==SOUTH)
|
||||
setDir(NORTH)
|
||||
else if(dir==WEST)
|
||||
setDir(EAST)
|
||||
return
|
||||
|
||||
/obj/item/pipe/binary/fixdir()
|
||||
if(dir == SOUTH)
|
||||
setDir(NORTH)
|
||||
else if(dir == WEST)
|
||||
setDir(EAST)
|
||||
|
||||
/obj/item/pipe/trinary/flippable/fixdir()
|
||||
if(dir in GLOB.diagonals)
|
||||
setDir(turn(dir, 45))
|
||||
|
||||
/obj/item/pipe/attack_self(mob/user)
|
||||
return rotate()
|
||||
@@ -245,16 +166,14 @@ GLOBAL_LIST_INIT(pipeID2State, list(
|
||||
add_fingerprint(user)
|
||||
|
||||
fixdir()
|
||||
if(pipe_type in list(PIPE_GAS_MIXER, PIPE_GAS_FILTER))
|
||||
setDir(unflip(dir))
|
||||
|
||||
var/obj/machinery/atmospherics/fakeA = get_pipe_cache(pipe_type, dir)
|
||||
|
||||
for(var/obj/machinery/atmospherics/M in loc)
|
||||
if((M.pipe_flags & PIPING_ONE_PER_TURF) && (fakeA.pipe_flags & PIPING_ONE_PER_TURF)) //Only one dense/requires density object per tile, eg connectors/cryo/heater/coolers.
|
||||
if((M.pipe_flags & fakeA.pipe_flags & PIPING_ONE_PER_TURF)) //Only one dense/requires density object per tile, eg connectors/cryo/heater/coolers.
|
||||
to_chat(user, "<span class='warning'>Something is hogging the tile!</span>")
|
||||
return TRUE
|
||||
if((M.piping_layer != piping_layer) && !((M.pipe_flags & PIPING_ALL_LAYER) || (pipe_type == PIPE_LAYER_MANIFOLD)))
|
||||
if((M.piping_layer != piping_layer) && !((M.pipe_flags | fakeA.pipe_flags) & PIPING_ALL_LAYER)) //don't continue if either pipe goes across all layers
|
||||
continue
|
||||
if(M.GetInitDirections() & fakeA.GetInitDirections()) // matches at least one direction on either type of pipe
|
||||
to_chat(user, "<span class='warning'>There is already a pipe at that location!</span>")
|
||||
@@ -262,16 +181,8 @@ GLOBAL_LIST_INIT(pipeID2State, list(
|
||||
// no conflicts found
|
||||
|
||||
var/obj/machinery/atmospherics/A = new pipe_type(loc)
|
||||
A.setDir(dir)
|
||||
A.SetInitDirections()
|
||||
|
||||
if(pipename)
|
||||
A.name = pipename
|
||||
|
||||
var/obj/machinery/atmospherics/components/trinary/T = A
|
||||
if(istype(T))
|
||||
T.flipped = flipped
|
||||
A.on_construction(pipe_type, color, piping_layer)
|
||||
build_pipe(A)
|
||||
A.on_construction(color, piping_layer)
|
||||
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
user.visible_message( \
|
||||
@@ -281,20 +192,28 @@ GLOBAL_LIST_INIT(pipeID2State, list(
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/item/pipe/suicide_act(mob/user)
|
||||
if(pipe_type in list(PIPE_PUMP, PIPE_PASSIVE_GATE, PIPE_VOLUME_PUMP))
|
||||
user.visible_message("<span class='suicide'>[user] shoves [src] in [user.p_their()] mouth and turns it on! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
for(var/i=1 to 20)
|
||||
C.vomit(0, TRUE, FALSE, 4, FALSE)
|
||||
if(prob(20))
|
||||
C.spew_organ()
|
||||
sleep(5)
|
||||
C.blood_volume = 0
|
||||
return(OXYLOSS|BRUTELOSS)
|
||||
else
|
||||
return ..()
|
||||
/obj/item/pipe/proc/build_pipe(obj/machinery/atmospherics/A)
|
||||
A.setDir(dir)
|
||||
A.SetInitDirections()
|
||||
|
||||
if(pipename)
|
||||
A.name = pipename
|
||||
|
||||
/obj/item/pipe/trinary/flippable/build_pipe(obj/machinery/atmospherics/components/trinary/T)
|
||||
..()
|
||||
T.flipped = flipped
|
||||
|
||||
/obj/item/pipe/directional/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] shoves [src] in [user.p_their()] mouth and turns it on! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
for(var/i=1 to 20)
|
||||
C.vomit(0, TRUE, FALSE, 4, FALSE)
|
||||
if(prob(20))
|
||||
C.spew_organ()
|
||||
sleep(5)
|
||||
C.blood_volume = 0
|
||||
return(OXYLOSS|BRUTELOSS)
|
||||
|
||||
/obj/item/pipe_meter
|
||||
name = "meter"
|
||||
@@ -332,4 +251,3 @@ GLOBAL_LIST_INIT(pipeID2State, list(
|
||||
piping_layer = new_layer
|
||||
pixel_x = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X
|
||||
pixel_y = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y
|
||||
|
||||
|
||||
@@ -17,30 +17,30 @@
|
||||
var/dat = {"
|
||||
PIPING LAYER: <A href='?src=\ref[src];layer_down=1'>--</A><b>[piping_layer]</b><A href='?src=\ref[src];layer_up=1'>++</A><BR>
|
||||
<b>Pipes:</b><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_SIMPLE];dir=1'>Pipe</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_SIMPLE];dir=5'>Bent Pipe</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_MANIFOLD];dir=1'>Manifold</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_LAYER_MANIFOLD];dir=1'>Layer Manifold</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_4WAYMANIFOLD];dir=1'>4-Way Manifold</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_MVALVE];dir=1'>Manual Valve</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_DVALVE];dir=1'>Digital Valve</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/pipe/simple];dir=1'>Pipe</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/pipe/simple];dir=5'>Bent Pipe</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/pipe/manifold];dir=1'>Manifold</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/pipe/layer_manifold];dir=1'>Layer Manifold</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/pipe/manifold4w];dir=1'>4-Way Manifold</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/components/binary/valve];dir=1'>Manual Valve</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/components/binary/valve/digital];dir=1'>Digital Valve</A><BR>
|
||||
<b>Devices:</b><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_CONNECTOR];dir=1'>Connector</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_UVENT];dir=1'>Vent</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_PUMP];dir=1'>Gas Pump</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_PASSIVE_GATE];dir=1'>Passive Gate</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_VOLUME_PUMP];dir=1'>Volume Pump</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_SCRUBBER];dir=1'>Scrubber</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/components/unary/portables_connector];dir=1'>Connector</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/components/unary/vent_pump];dir=1'>Vent</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/components/binary/pump];dir=1'>Gas Pump</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/components/binary/passive_gate];dir=1'>Passive Gate</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/components/binary/volume_pump];dir=1'>Volume Pump</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/components/unary/vent_scrubber];dir=1'>Scrubber</A><BR>
|
||||
<A href='?src=\ref[src];makemeter=1'>Meter</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_GAS_FILTER];dir=1'>Gas Filter</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_GAS_MIXER];dir=1'>Gas Mixer</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/components/trinary/filter];dir=1'>Gas Filter</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/components/trinary/mixer];dir=1'>Gas Mixer</A><BR>
|
||||
<b>Heat exchange:</b><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_HE];dir=1'>Pipe</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_HE];dir=5'>Bent Pipe</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_HE_MANIFOLD];dir=1'>Manifold</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_HE_4WAYMANIFOLD];dir=1'>4-Way Manifold</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_JUNCTION];dir=1'>Junction</A><BR>
|
||||
<A href='?src=\ref[src];make=[PIPE_HEAT_EXCHANGE];dir=1'>Heat Exchanger</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/pipe/heat_exchanging/simple];dir=1'>Pipe</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/pipe/heat_exchanging/simple];dir=5'>Bent Pipe</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/pipe/heat_exchanging/manifold];dir=1'>Manifold</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w];dir=1'>4-Way Manifold</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/pipe/heat_exchanging/junction];dir=1'>Junction</A><BR>
|
||||
<A href='?src=\ref[src];make=[/obj/machinery/atmospherics/components/unary/heat_exchanger];dir=1'>Heat Exchanger</A><BR>
|
||||
"}
|
||||
|
||||
|
||||
|
||||
@@ -624,6 +624,15 @@
|
||||
/obj/machinery/porta_turret/centcom_shuttle/setup()
|
||||
return
|
||||
|
||||
/obj/machinery/porta_turret/centcom_shuttle/weak
|
||||
max_integrity = 120
|
||||
integrity_failure = 60
|
||||
name = "Old Laser Turret"
|
||||
desc = "A turret built with substandard parts and run down further with age. Still capable of delivering lethal lasers to the odd space carp, but not much else."
|
||||
stun_projectile = /obj/item/projectile/beam/weak
|
||||
lethal_projectile = /obj/item/projectile/beam/weak
|
||||
faction = "neutral"
|
||||
|
||||
////////////////////////
|
||||
//Turret Control Panel//
|
||||
////////////////////////
|
||||
|
||||
@@ -44,10 +44,10 @@
|
||||
/obj/machinery/teleport/hub/CollidedWith(atom/movable/AM)
|
||||
if(z == ZLEVEL_CENTCOM)
|
||||
to_chat(AM, "You can't use this here.")
|
||||
return
|
||||
if(is_ready())
|
||||
teleport(AM)
|
||||
use_power(5000)
|
||||
return
|
||||
|
||||
/obj/machinery/teleport/hub/attackby(obj/item/W, mob/user, params)
|
||||
if(default_deconstruction_screwdriver(user, "tele-o", "tele0", W))
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
"<span class='userdanger'>[chassis] drills [target] with [src].</span>")
|
||||
add_logs(user, target, "attacked", "[name]", "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
|
||||
if(target.stat == DEAD)
|
||||
add_logs(user, target, "gibbed", name)
|
||||
if(target.butcher_results)
|
||||
target.harvest(chassis)//Butcher the mob with our drill.
|
||||
else
|
||||
|
||||
@@ -408,8 +408,7 @@
|
||||
return reset()
|
||||
if(!use_cable(1))
|
||||
return reset()
|
||||
var/obj/structure/cable/NC = new(new_turf)
|
||||
NC.cableColor("red")
|
||||
var/obj/structure/cable/NC = new(new_turf, "red")
|
||||
NC.d1 = 0
|
||||
NC.d2 = fdirn
|
||||
NC.update_icon()
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
/obj/mecha/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
|
||||
. = ..()
|
||||
if(!damage_amount)
|
||||
return 0
|
||||
var/booster_deflection_modifier = 1
|
||||
var/booster_damage_modifier = 1
|
||||
if(damage_flag == "bullet" || damage_flag == "laser" || damage_flag == "energy")
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var/list/random_icon_states = list()
|
||||
var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA
|
||||
var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
|
||||
var/mergeable_decal = 1 //when two of these are on a same tile or do we need to merge them into just one?
|
||||
var/mergeable_decal = TRUE //when two of these are on a same tile or do we need to merge them into just one?
|
||||
|
||||
/obj/effect/decal/cleanable/Initialize(mapload, list/datum/disease/diseases)
|
||||
if (random_icon_states && length(src.random_icon_states) > 0)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
icon_state = "xgib1"
|
||||
layer = LOW_OBJ_LAYER
|
||||
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6")
|
||||
mergeable_decal = 0
|
||||
mergeable_decal = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/xenoblood/xgibs/proc/streak(list/directions)
|
||||
set waitfor = 0
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
icon_state = "gibbl5"
|
||||
layer = LOW_OBJ_LAYER
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
|
||||
mergeable_decal = 0
|
||||
mergeable_decal = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases)
|
||||
. = ..()
|
||||
@@ -135,9 +135,10 @@
|
||||
var/obj/item/clothing/shoes/S = H.shoes
|
||||
if(S && S.bloody_shoes[blood_state])
|
||||
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
|
||||
entered_dirs|= H.dir
|
||||
shoe_types |= H.shoes.type
|
||||
update_icon()
|
||||
shoe_types |= S.type
|
||||
if (!(entered_dirs & H.dir))
|
||||
entered_dirs |= H.dir
|
||||
update_icon()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/footprints/Uncrossed(atom/movable/O)
|
||||
..()
|
||||
@@ -146,9 +147,11 @@
|
||||
var/obj/item/clothing/shoes/S = H.shoes
|
||||
if(S && S.bloody_shoes[blood_state])
|
||||
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
|
||||
exited_dirs|= H.dir
|
||||
shoe_types |= H.shoes.type
|
||||
update_icon()
|
||||
shoe_types |= S.type
|
||||
if (!(exited_dirs & H.dir))
|
||||
exited_dirs |= H.dir
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/effect/decal/cleanable/blood/footprints/update_icon()
|
||||
cut_overlays()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
desc = "Ashes to ashes, dust to dust, and into space."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "ash"
|
||||
mergeable_decal = 0
|
||||
mergeable_decal = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/ash/Initialize()
|
||||
. = ..()
|
||||
@@ -67,7 +67,7 @@
|
||||
gender = NEUTER
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "molten"
|
||||
mergeable_decal = 0
|
||||
mergeable_decal = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/molten_object/large
|
||||
name = "big gooey grey mass"
|
||||
@@ -144,7 +144,7 @@
|
||||
desc = "The shredded remains of what appears to be clothing."
|
||||
icon_state = "shreds"
|
||||
gender = PLURAL
|
||||
mergeable_decal = 0
|
||||
mergeable_decal = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/shreds/ex_act(severity, target)
|
||||
if(severity == 1) //so shreds created during an explosion aren't deleted by the explosion.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
|
||||
blood_state = BLOOD_STATE_OIL
|
||||
bloodiness = MAX_SHOE_BLOODINESS
|
||||
mergeable_decal = 0
|
||||
mergeable_decal = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/robot_debris/proc/streak(list/directions)
|
||||
set waitfor = 0
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
gender = PLURAL
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
|
||||
/obj/effect/decal/remains/acid_act()
|
||||
visible_message("<span class='warning'>[src] dissolve[gender==PLURAL?"":"s"] into a puddle of sizzling goop!</span>")
|
||||
playsound(src, 'sound/items/welder.ogg', 150, 1)
|
||||
new /obj/effect/decal/cleanable/greenglow(drop_location())
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/decal/remains/human
|
||||
desc = "They look like human remains. They have a strange aura about them."
|
||||
icon_state = "remains"
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
CONTAINS:
|
||||
RPD
|
||||
*/
|
||||
#define PIPE_BINARY 0
|
||||
#define PIPE_BENDABLE 1
|
||||
#define PIPE_TRINARY 2
|
||||
#define PIPE_TRIN_M 3
|
||||
#define PIPE_UNARY 4
|
||||
#define PIPE_QUAD 5
|
||||
|
||||
#define PAINT_MODE -2
|
||||
#define EATING_MODE -1
|
||||
@@ -22,23 +16,29 @@ RPD
|
||||
|
||||
/datum/pipe_info
|
||||
var/id=-1
|
||||
var/categoryId = CATEGORY_ATMOS
|
||||
var/categoryId
|
||||
var/dir=SOUTH
|
||||
var/dirtype = PIPE_BENDABLE
|
||||
var/icon = 'icons/obj/atmospherics/pipes/pipe_item.dmi'
|
||||
var/icon_state=""
|
||||
var/icon
|
||||
var/icon_state
|
||||
var/selected=0
|
||||
|
||||
/datum/pipe_info/New(pid,direction,dt)
|
||||
id=pid
|
||||
icon_state=GLOB.pipeID2State["[pid]"]
|
||||
dir = direction
|
||||
dirtype=dt
|
||||
/datum/pipe_info/pipe
|
||||
categoryId = CATEGORY_ATMOS
|
||||
icon = 'icons/obj/atmospherics/pipes/pipe_item.dmi'
|
||||
|
||||
/datum/pipe_info/pipe/New(obj/machinery/atmospherics/path)
|
||||
id = path
|
||||
icon_state = initial(path.pipe_state)
|
||||
dirtype = initial(path.construction_type)
|
||||
|
||||
/datum/pipe_info/proc/Render(dispenser,label)
|
||||
|
||||
/datum/pipe_info/pipe/Render(dispenser,label,dir=NORTH)
|
||||
return "<li><a href='?src=\ref[dispenser];makepipe=[id];dir=[dir];type=[dirtype]'>[label]</a></li>"
|
||||
|
||||
/datum/pipe_info/meter
|
||||
categoryId = CATEGORY_ATMOS
|
||||
icon = 'icons/obj/atmospherics/pipes/simple.dmi'
|
||||
icon_state = "meterX"
|
||||
|
||||
@@ -64,7 +64,6 @@ GLOBAL_LIST_INIT(disposalpipeID2State, list(
|
||||
/datum/pipe_info/disposal
|
||||
categoryId = CATEGORY_DISPOSALS
|
||||
icon = 'icons/obj/atmospherics/pipes/disposal.dmi'
|
||||
icon_state = "meterX"
|
||||
|
||||
/datum/pipe_info/disposal/New(var/pid,var/dt)
|
||||
id=pid
|
||||
@@ -80,33 +79,31 @@ GLOBAL_LIST_INIT(disposalpipeID2State, list(
|
||||
//find these defines in code\game\machinery\pipe\consruction.dm
|
||||
GLOBAL_LIST_INIT(RPD_recipes, list(
|
||||
"Pipes" = list(
|
||||
"Pipe" = new /datum/pipe_info(PIPE_SIMPLE, 1, PIPE_BENDABLE),
|
||||
//"Bent Pipe" = new /datum/pipe_info(PIPE_SIMPLE, 5, PIPE_BENT),
|
||||
"Manifold" = new /datum/pipe_info(PIPE_MANIFOLD, 1, PIPE_TRINARY),
|
||||
"Manual Valve" = new /datum/pipe_info(PIPE_MVALVE, 1, PIPE_BINARY),
|
||||
"Digital Valve" = new /datum/pipe_info(PIPE_DVALVE, 1, PIPE_BINARY),
|
||||
"4-Way Manifold" = new /datum/pipe_info(PIPE_4WAYMANIFOLD, 1, PIPE_QUAD),
|
||||
"Layer Manifold" = new /datum/pipe_info(PIPE_LAYER_MANIFOLD, 1, PIPE_BINARY),
|
||||
"Pipe" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/simple),
|
||||
"Manifold" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/manifold),
|
||||
"Manual Valve" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/binary/valve),
|
||||
"Digital Valve" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/binary/valve/digital),
|
||||
"4-Way Manifold" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/manifold4w),
|
||||
"Layer Manifold" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/layer_manifold),
|
||||
),
|
||||
"Devices"=list(
|
||||
"Connector" = new /datum/pipe_info(PIPE_CONNECTOR, 1, PIPE_UNARY),
|
||||
"Unary Vent" = new /datum/pipe_info(PIPE_UVENT, 1, PIPE_UNARY),
|
||||
"Gas Pump" = new /datum/pipe_info(PIPE_PUMP, 1, PIPE_UNARY),
|
||||
"Passive Gate" = new /datum/pipe_info(PIPE_PASSIVE_GATE, 1, PIPE_UNARY),
|
||||
"Volume Pump" = new /datum/pipe_info(PIPE_VOLUME_PUMP, 1, PIPE_UNARY),
|
||||
"Scrubber" = new /datum/pipe_info(PIPE_SCRUBBER, 1, PIPE_UNARY),
|
||||
"Injector" = new /datum/pipe_info(PIPE_INJECTOR, 1, PIPE_UNARY),
|
||||
"Devices" = list(
|
||||
"Connector" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/unary/portables_connector),
|
||||
"Unary Vent" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/unary/vent_pump),
|
||||
"Gas Pump" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/binary/pump),
|
||||
"Passive Gate" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/binary/passive_gate),
|
||||
"Volume Pump" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/binary/volume_pump),
|
||||
"Scrubber" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/unary/vent_scrubber),
|
||||
"Injector" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/unary/outlet_injector),
|
||||
"Meter" = new /datum/pipe_info/meter(),
|
||||
"Gas Filter" = new /datum/pipe_info(PIPE_GAS_FILTER, 1, PIPE_TRIN_M),
|
||||
"Gas Mixer" = new /datum/pipe_info(PIPE_GAS_MIXER, 1, PIPE_TRIN_M),
|
||||
"Gas Filter" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/trinary/filter),
|
||||
"Gas Mixer" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/trinary/mixer),
|
||||
),
|
||||
"Heat Exchange" = list(
|
||||
"Pipe" = new /datum/pipe_info(PIPE_HE, 1, PIPE_BENDABLE),
|
||||
//"Bent Pipe" = new /datum/pipe_info(PIPE_HE, 5, PIPE_BENT),
|
||||
"Manifold" = new /datum/pipe_info(PIPE_HE_MANIFOLD, 1, PIPE_TRINARY),
|
||||
"4-Way Manifold" = new /datum/pipe_info(PIPE_HE_4WAYMANIFOLD, 1, PIPE_QUAD),
|
||||
"Junction" = new /datum/pipe_info(PIPE_JUNCTION, 1, PIPE_UNARY),
|
||||
"Heat Exchanger" = new /datum/pipe_info(PIPE_HEAT_EXCHANGE, 1, PIPE_UNARY),
|
||||
"Pipe" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/heat_exchanging/simple),
|
||||
"Manifold" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/heat_exchanging/manifold),
|
||||
"4-Way Manifold" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w),
|
||||
"Junction" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/pipe/heat_exchanging/junction),
|
||||
"Heat Exchanger" = new /datum/pipe_info/pipe(/obj/machinery/atmospherics/components/unary/heat_exchanger),
|
||||
),
|
||||
"Disposal Pipes" = list(
|
||||
"Pipe" = new /datum/pipe_info/disposal(DISP_PIPE_STRAIGHT, PIPE_BINARY),
|
||||
@@ -120,6 +117,7 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
|
||||
"Sort Junction" = new /datum/pipe_info/disposal(DISP_SORTJUNCTION, PIPE_TRINARY),
|
||||
)
|
||||
))
|
||||
|
||||
/obj/item/pipe_dispenser
|
||||
name = "Rapid Piping Device (RPD)"
|
||||
desc = "A device used to rapidly pipe things."
|
||||
@@ -137,7 +135,7 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
var/working = 0
|
||||
var/p_type = PIPE_SIMPLE
|
||||
var/p_type = /obj/machinery/atmospherics/pipe/simple
|
||||
var/p_conntype = PIPE_BENDABLE
|
||||
var/p_dir = 1
|
||||
var/p_flipped = 0
|
||||
@@ -201,7 +199,7 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
|
||||
if(screen == CATEGORY_ATMOS)
|
||||
dat += "<span class='linkOn'>Atmospherics</span> <A href='?src=\ref[src];screen=[CATEGORY_DISPOSALS];dmake=0;type=0'>Disposals</A><BR>"
|
||||
else if(screen == CATEGORY_DISPOSALS)
|
||||
dat += "<A href='?src=\ref[src];screen=[CATEGORY_ATMOS];makepipe=0;dir=1;type=0'>Atmospherics</A> <span class='linkOn'>Disposals</span><BR>"
|
||||
dat += "<A href='?src=\ref[src];screen=[CATEGORY_ATMOS];makepipe=[/obj/machinery/atmospherics/pipe/simple];dir=1;type=0'>Atmospherics</A> <span class='linkOn'>Disposals</span><BR>"
|
||||
var/generated_layer_list = ""
|
||||
var/layers_total = PIPING_LAYER_MAX - PIPING_LAYER_MIN + 1
|
||||
for(var/iter = PIPING_LAYER_MIN, iter <= layers_total, iter++)
|
||||
@@ -220,9 +218,9 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
|
||||
var/datum/pipe_info/I = cat[label]
|
||||
var/found=0
|
||||
if(I.id == p_type)
|
||||
if((p_class == ATMOS_MODE || p_class == METER_MODE) && (I.type == /datum/pipe_info || I.type == /datum/pipe_info/meter))
|
||||
if((p_class == ATMOS_MODE || p_class == METER_MODE) && (istype(I, /datum/pipe_info/pipe) || istype(I, /datum/pipe_info/meter)))
|
||||
found=1
|
||||
else if(p_class == DISPOSALS_MODE && I.type==/datum/pipe_info/disposal)
|
||||
else if(p_class == DISPOSALS_MODE && istype(I, /datum/pipe_info/disposal))
|
||||
found=1
|
||||
if(found)
|
||||
preview=new /icon(I.icon,I.icon_state)
|
||||
@@ -510,7 +508,8 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
|
||||
if(href_list["makepipe"])
|
||||
p_type = text2path(href_list["makepipe"])
|
||||
p_dir = text2num(href_list["dir"])
|
||||
p_conntype = text2num(href_list["type"])
|
||||
var/obj/item/pipe/path = text2path(href_list["type"])
|
||||
p_conntype = initial(path.RPD_type)
|
||||
p_class = ATMOS_MODE
|
||||
spark_system.start()
|
||||
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
|
||||
@@ -581,7 +580,9 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
|
||||
if(do_after(user, 2, target = A))
|
||||
activate()
|
||||
var/obj/item/pipe/P = new(A, queued_p_type, queued_p_dir)
|
||||
P.flipped = queued_p_flipped
|
||||
if(queued_p_flipped)
|
||||
var/obj/item/pipe/trinary/flippable/F = P
|
||||
F.flipped = queued_p_flipped
|
||||
P.update()
|
||||
P.add_fingerprint(usr)
|
||||
if(!isnull(temp_piping_layer))
|
||||
@@ -627,12 +628,6 @@ GLOBAL_LIST_INIT(RPD_recipes, list(
|
||||
/obj/item/pipe_dispenser/proc/activate()
|
||||
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
|
||||
#undef PIPE_BINARY
|
||||
#undef PIPE_BENT
|
||||
#undef PIPE_TRINARY
|
||||
#undef PIPE_TRIN_M
|
||||
#undef PIPE_UNARY
|
||||
#undef PIPE_QUAD
|
||||
#undef PAINT_MODE
|
||||
#undef EATING_MODE
|
||||
#undef ATMOS_MODE
|
||||
|
||||
@@ -316,13 +316,15 @@
|
||||
if(actually_paints)
|
||||
switch(paint_mode)
|
||||
if(PAINT_NORMAL)
|
||||
new /obj/effect/decal/cleanable/crayon(target, paint_color, drawing, temp, graf_rot)
|
||||
var/obj/effect/decal/cleanable/crayon/C = new(target, paint_color, drawing, temp, graf_rot)
|
||||
C.add_hiddenprint(user)
|
||||
affected_turfs += target
|
||||
if(PAINT_LARGE_HORIZONTAL)
|
||||
var/turf/left = locate(target.x-1,target.y,target.z)
|
||||
var/turf/right = locate(target.x+1,target.y,target.z)
|
||||
if(is_type_in_list(left, validSurfaces) && is_type_in_list(right, validSurfaces))
|
||||
new /obj/effect/decal/cleanable/crayon(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON)
|
||||
var/obj/effect/decal/cleanable/crayon/C = new(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON)
|
||||
C.add_hiddenprint(user)
|
||||
affected_turfs += left
|
||||
affected_turfs += right
|
||||
affected_turfs += target
|
||||
|
||||
@@ -286,6 +286,7 @@
|
||||
var/req_defib = 1
|
||||
var/combat = 0 //If it penetrates armor and gives additional functionality
|
||||
var/grab_ghost = FALSE
|
||||
var/tlimit = DEFIB_TIME_LIMIT * 10
|
||||
|
||||
/obj/item/twohanded/shockpaddles/proc/recharge(var/time)
|
||||
if(req_defib || !time)
|
||||
@@ -387,11 +388,14 @@
|
||||
if((!req_defib && grab_ghost) || (req_defib && defib.grab_ghost))
|
||||
H.notify_ghost_cloning("Your heart is being defibrillated!")
|
||||
H.grab_ghost() // Shove them back in their body.
|
||||
else if(!H.suiciding && !(H.disabilities & NOCLONE)&& !H.hellbound)
|
||||
else if(can_defib(H))
|
||||
H.notify_ghost_cloning("Your heart is being defibrillated. Re-enter your corpse if you want to be revived!", source = src)
|
||||
|
||||
do_help(H, user)
|
||||
|
||||
/obj/item/twohanded/shockpaddles/proc/can_defib(mob/living/carbon/human/H)
|
||||
var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain)
|
||||
return (!H.suiciding && !(H.disabilities & NOCLONE) && !H.hellbound && ((world.time - H.timeofdeath) < tlimit) && (H.getBruteLoss() < 180) && (H.getFireLoss() < 180) && H.getorgan(/obj/item/organ/heart) && BR && !BR.damaged_brain)
|
||||
|
||||
/obj/item/twohanded/shockpaddles/proc/do_disarm(mob/living/M, mob/living/user)
|
||||
if(req_defib && defib.safety)
|
||||
@@ -481,7 +485,6 @@
|
||||
var/tplus = world.time - H.timeofdeath
|
||||
// past this much time the patient is unrecoverable
|
||||
// (in deciseconds)
|
||||
var/tlimit = DEFIB_TIME_LIMIT * 10
|
||||
// brain damage starts setting in on the patient after
|
||||
// some time left rotting
|
||||
var/tloss = DEFIB_TIME_LOSS * 10
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
C.activate(usr, saved_appearance, src)
|
||||
to_chat(usr, "<span class='notice'>You activate \the [src].</span>")
|
||||
new /obj/effect/temp_visual/emp/pulse(get_turf(src))
|
||||
usr.cancel_camera()
|
||||
|
||||
/obj/item/device/chameleon/proc/disrupt(delete_dummy = 1)
|
||||
if(active_dummy)
|
||||
|
||||
@@ -88,8 +88,9 @@
|
||||
/obj/item/restraints/handcuffs/cable
|
||||
name = "cable restraints"
|
||||
desc = "Looks like some cables tied together. Could be used to tie something up."
|
||||
icon_state = "cuff_red"
|
||||
item_state = "coil_red"
|
||||
icon_state = "cuff"
|
||||
item_state = "coil"
|
||||
item_color = "red"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
materials = list(MAT_METAL=150, MAT_GLASS=75)
|
||||
@@ -98,6 +99,18 @@
|
||||
cuffsound = 'sound/weapons/cablecuff.ogg'
|
||||
var/datum/robot_energy_storage/wirestorage = null
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/Initialize(mapload, param_color)
|
||||
. = ..()
|
||||
|
||||
var/list/cable_colors = GLOB.cable_colors
|
||||
item_color = param_color || item_color || pick(cable_colors)
|
||||
if(cable_colors[item_color])
|
||||
item_color = cable_colors[item_color]
|
||||
update_icon()
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/update_icon()
|
||||
add_atom_colour(item_color, FIXED_COLOUR_PRIORITY)
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/attack(mob/living/carbon/C, mob/living/carbon/human/user)
|
||||
if(!istype(C))
|
||||
return
|
||||
@@ -116,36 +129,28 @@
|
||||
return ..()
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/red
|
||||
icon_state = "cuff_red"
|
||||
item_state = "coil_red"
|
||||
item_color = "red"
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/yellow
|
||||
icon_state = "cuff_yellow"
|
||||
item_state = "coil_yellow"
|
||||
item_color = "yellow"
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/blue
|
||||
icon_state = "cuff_blue"
|
||||
item_state = "coil_blue"
|
||||
item_color = "blue"
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/green
|
||||
icon_state = "cuff_green"
|
||||
item_state = "coil_green"
|
||||
item_color = "green"
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/pink
|
||||
icon_state = "cuff_pink"
|
||||
item_state = "coil_pink"
|
||||
item_color = "pink"
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/orange
|
||||
icon_state = "cuff_orange"
|
||||
item_state = "coil_orange"
|
||||
item_color = "orange"
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/cyan
|
||||
icon_state = "cuff_cyan"
|
||||
item_state = "coil_cyan"
|
||||
item_color = "cyan"
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/white
|
||||
icon_state = "cuff_white"
|
||||
item_state = "coil_white"
|
||||
item_color = "white"
|
||||
|
||||
/obj/item/restraints/handcuffs/alien
|
||||
icon_state = "handcuffAlien"
|
||||
@@ -209,17 +214,18 @@
|
||||
/obj/item/restraints/handcuffs/cable/zipties
|
||||
name = "zipties"
|
||||
desc = "Plastic, disposable zipties that can be used to restrain temporarily but are destroyed after use."
|
||||
icon_state = "cuff_white"
|
||||
icon_state = "cuff"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
||||
materials = list()
|
||||
breakouttime = 450 //Deciseconds = 45s
|
||||
trashtype = /obj/item/restraints/handcuffs/cable/zipties/used
|
||||
item_color = "white"
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/zipties/used
|
||||
desc = "A pair of broken zipties."
|
||||
icon_state = "cuff_white_used"
|
||||
item_state = "cuff_white"
|
||||
icon_state = "cuff_used"
|
||||
item_state = "cuff"
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/zipties/used/attack()
|
||||
return
|
||||
|
||||
@@ -169,6 +169,11 @@
|
||||
W.ini_dir = W.dir
|
||||
//END: oh fuck i'm so sorry
|
||||
|
||||
else if(istype(O, /obj/item/restraints/handcuffs/cable))
|
||||
var/obj/item/cuffs = O
|
||||
cuffs.item_color = item_color
|
||||
cuffs.update_icon()
|
||||
|
||||
if (QDELETED(O))
|
||||
return //It's a stack and has already been merged
|
||||
|
||||
@@ -245,6 +250,7 @@
|
||||
S.copy_evidences(src)
|
||||
use(transfer, TRUE)
|
||||
S.add(transfer)
|
||||
return transfer
|
||||
|
||||
/obj/item/stack/Crossed(obj/o)
|
||||
if(istype(o, merge_type) && !o.throwing)
|
||||
@@ -260,7 +266,7 @@
|
||||
if (user.get_inactive_held_item() == src)
|
||||
if(zero_amount())
|
||||
return
|
||||
change_stack(user,1)
|
||||
return change_stack(user,1)
|
||||
else
|
||||
..()
|
||||
|
||||
@@ -297,10 +303,10 @@
|
||||
|
||||
|
||||
/obj/item/stack/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, merge_type) && amount < max_amount)
|
||||
if(istype(W, merge_type))
|
||||
var/obj/item/stack/S = W
|
||||
merge(S)
|
||||
to_chat(user, "<span class='notice'>Your [S.name] stack now contains [S.get_amount()] [S.singular_name]\s.</span>")
|
||||
if(merge(S))
|
||||
to_chat(user, "<span class='notice'>Your [S.name] stack now contains [S.get_amount()] [S.singular_name]\s.</span>")
|
||||
else
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -1,202 +1,202 @@
|
||||
/obj/item/melee/baton
|
||||
name = "stunbaton"
|
||||
desc = "A stun baton for incapacitating people with."
|
||||
icon_state = "stunbaton"
|
||||
item_state = "baton"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
||||
slot_flags = SLOT_BELT
|
||||
force = 10
|
||||
throwforce = 7
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
origin_tech = "combat=2"
|
||||
attack_verb = list("beaten")
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 50, bio = 0, rad = 0, fire = 80, acid = 80)
|
||||
|
||||
var/stunforce = 140
|
||||
var/status = 0
|
||||
var/obj/item/stock_parts/cell/high/cell
|
||||
var/hitcost = 1000
|
||||
var/throw_hit_chance = 35
|
||||
|
||||
/obj/item/melee/baton/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/item/melee/baton/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return (FIRELOSS)
|
||||
|
||||
/obj/item/melee/baton/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/melee/baton/throw_impact(atom/hit_atom)
|
||||
..()
|
||||
//Only mob/living types have stun handling
|
||||
if(status && prob(throw_hit_chance) && iscarbon(hit_atom))
|
||||
baton_stun(hit_atom)
|
||||
|
||||
/obj/item/melee/baton/loaded/Initialize() //this one starts with a cell pre-installed.
|
||||
cell = new(src)
|
||||
update_icon()
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/baton/proc/deductcharge(chrgdeductamt)
|
||||
if(cell)
|
||||
//Note this value returned is significant, as it will determine
|
||||
//if a stun is applied or not
|
||||
. = cell.use(chrgdeductamt)
|
||||
if(status && cell.charge < hitcost)
|
||||
//we're below minimum, turn off
|
||||
status = 0
|
||||
update_icon()
|
||||
playsound(loc, "sparks", 75, 1, -1)
|
||||
|
||||
|
||||
/obj/item/melee/baton/update_icon()
|
||||
if(status)
|
||||
icon_state = "[initial(name)]_active"
|
||||
else if(!cell)
|
||||
icon_state = "[initial(name)]_nocell"
|
||||
else
|
||||
icon_state = "[initial(name)]"
|
||||
|
||||
/obj/item/melee/baton/examine(mob/user)
|
||||
..()
|
||||
if(cell)
|
||||
to_chat(user, "<span class='notice'>The baton is [round(cell.percent())]% charged.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The baton does not have a power source installed.</span>")
|
||||
|
||||
/obj/item/melee/baton/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/stock_parts/cell))
|
||||
var/obj/item/stock_parts/cell/C = W
|
||||
if(cell)
|
||||
to_chat(user, "<span class='notice'>[src] already has a cell.</span>")
|
||||
else
|
||||
if(C.maxcharge < hitcost)
|
||||
to_chat(user, "<span class='notice'>[src] requires a higher capacity cell.</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
cell = W
|
||||
to_chat(user, "<span class='notice'>You install a cell in [src].</span>")
|
||||
update_icon()
|
||||
|
||||
else if(istype(W, /obj/item/screwdriver))
|
||||
if(cell)
|
||||
cell.update_icon()
|
||||
cell.forceMove(get_turf(src))
|
||||
cell = null
|
||||
to_chat(user, "<span class='notice'>You remove the cell from [src].</span>")
|
||||
status = 0
|
||||
update_icon()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/baton/attack_self(mob/user)
|
||||
if(cell && cell.charge > hitcost)
|
||||
status = !status
|
||||
to_chat(user, "<span class='notice'>[src] is now [status ? "on" : "off"].</span>")
|
||||
playsound(loc, "sparks", 75, 1, -1)
|
||||
else
|
||||
status = 0
|
||||
if(!cell)
|
||||
to_chat(user, "<span class='warning'>[src] does not have a power source!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] is out of charge.</span>")
|
||||
update_icon()
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/item/melee/baton/attack(mob/M, mob/living/carbon/human/user)
|
||||
if(status && user.disabilities & CLUMSY && prob(50))
|
||||
user.visible_message("<span class='danger'>[user] accidentally hits themself with [src]!</span>", \
|
||||
"<span class='userdanger'>You accidentally hit yourself with [src]!</span>")
|
||||
user.Knockdown(stunforce*3)
|
||||
deductcharge(hitcost)
|
||||
return
|
||||
|
||||
if(iscyborg(M))
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/L = M
|
||||
if(check_martial_counter(L, user))
|
||||
return
|
||||
|
||||
if(user.a_intent != INTENT_HARM)
|
||||
if(status)
|
||||
if(baton_stun(M, user))
|
||||
user.do_attack_animation(M)
|
||||
return
|
||||
else
|
||||
M.visible_message("<span class='warning'>[user] has prodded [M] with [src]. Luckily it was off.</span>", \
|
||||
"<span class='warning'>[user] has prodded you with [src]. Luckily it was off</span>")
|
||||
else
|
||||
if(status)
|
||||
baton_stun(M, user)
|
||||
..()
|
||||
|
||||
|
||||
/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user)
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
|
||||
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
return 0
|
||||
if(iscyborg(loc))
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
if(!R || !R.cell || !R.cell.use(hitcost))
|
||||
return 0
|
||||
else
|
||||
if(!deductcharge(hitcost))
|
||||
return 0
|
||||
|
||||
L.Knockdown(stunforce)
|
||||
L.apply_effect(STUTTER, stunforce)
|
||||
if(user)
|
||||
user.lastattacked = L
|
||||
L.lastattacker = user
|
||||
L.visible_message("<span class='danger'>[user] has stunned [L] with [src]!</span>", \
|
||||
"<span class='userdanger'>[user] has stunned you with [src]!</span>")
|
||||
add_logs(user, L, "stunned")
|
||||
|
||||
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
|
||||
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
H.forcesay(GLOB.hit_appends)
|
||||
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/melee/baton/emp_act(severity)
|
||||
deductcharge(1000 / severity)
|
||||
..()
|
||||
|
||||
//Makeshift stun baton. Replacement for stun gloves.
|
||||
/obj/item/melee/baton/cattleprod
|
||||
name = "stunprod"
|
||||
desc = "An improvised stun baton."
|
||||
icon_state = "stunprod_nocell"
|
||||
item_state = "prod"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 3
|
||||
throwforce = 5
|
||||
stunforce = 100
|
||||
hitcost = 2000
|
||||
throw_hit_chance = 10
|
||||
slot_flags = SLOT_BACK
|
||||
var/obj/item/device/assembly/igniter/sparkler = 0
|
||||
|
||||
/obj/item/melee/baton/cattleprod/Initialize()
|
||||
. = ..()
|
||||
sparkler = new (src)
|
||||
|
||||
/obj/item/melee/baton/cattleprod/baton_stun()
|
||||
if(sparkler.activate())
|
||||
..()
|
||||
/obj/item/melee/baton
|
||||
name = "stunbaton"
|
||||
desc = "A stun baton for incapacitating people with."
|
||||
icon_state = "stunbaton"
|
||||
item_state = "baton"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
||||
slot_flags = SLOT_BELT
|
||||
force = 10
|
||||
throwforce = 7
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
origin_tech = "combat=2"
|
||||
attack_verb = list("beaten")
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 50, bio = 0, rad = 0, fire = 80, acid = 80)
|
||||
|
||||
var/stunforce = 140
|
||||
var/status = 0
|
||||
var/obj/item/stock_parts/cell/high/cell
|
||||
var/hitcost = 1000
|
||||
var/throw_hit_chance = 35
|
||||
|
||||
/obj/item/melee/baton/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/item/melee/baton/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return (FIRELOSS)
|
||||
|
||||
/obj/item/melee/baton/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/melee/baton/throw_impact(atom/hit_atom)
|
||||
..()
|
||||
//Only mob/living types have stun handling
|
||||
if(status && prob(throw_hit_chance) && iscarbon(hit_atom))
|
||||
baton_stun(hit_atom)
|
||||
|
||||
/obj/item/melee/baton/loaded/Initialize() //this one starts with a cell pre-installed.
|
||||
cell = new(src)
|
||||
update_icon()
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/baton/proc/deductcharge(chrgdeductamt)
|
||||
if(cell)
|
||||
//Note this value returned is significant, as it will determine
|
||||
//if a stun is applied or not
|
||||
. = cell.use(chrgdeductamt)
|
||||
if(status && cell.charge < hitcost)
|
||||
//we're below minimum, turn off
|
||||
status = 0
|
||||
update_icon()
|
||||
playsound(loc, "sparks", 75, 1, -1)
|
||||
|
||||
|
||||
/obj/item/melee/baton/update_icon()
|
||||
if(status)
|
||||
icon_state = "[initial(name)]_active"
|
||||
else if(!cell)
|
||||
icon_state = "[initial(name)]_nocell"
|
||||
else
|
||||
icon_state = "[initial(name)]"
|
||||
|
||||
/obj/item/melee/baton/examine(mob/user)
|
||||
..()
|
||||
if(cell)
|
||||
to_chat(user, "<span class='notice'>The baton is [round(cell.percent())]% charged.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The baton does not have a power source installed.</span>")
|
||||
|
||||
/obj/item/melee/baton/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/stock_parts/cell))
|
||||
var/obj/item/stock_parts/cell/C = W
|
||||
if(cell)
|
||||
to_chat(user, "<span class='notice'>[src] already has a cell.</span>")
|
||||
else
|
||||
if(C.maxcharge < hitcost)
|
||||
to_chat(user, "<span class='notice'>[src] requires a higher capacity cell.</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
cell = W
|
||||
to_chat(user, "<span class='notice'>You install a cell in [src].</span>")
|
||||
update_icon()
|
||||
|
||||
else if(istype(W, /obj/item/screwdriver))
|
||||
if(cell)
|
||||
cell.update_icon()
|
||||
cell.forceMove(get_turf(src))
|
||||
cell = null
|
||||
to_chat(user, "<span class='notice'>You remove the cell from [src].</span>")
|
||||
status = 0
|
||||
update_icon()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/baton/attack_self(mob/user)
|
||||
if(cell && cell.charge > hitcost)
|
||||
status = !status
|
||||
to_chat(user, "<span class='notice'>[src] is now [status ? "on" : "off"].</span>")
|
||||
playsound(loc, "sparks", 75, 1, -1)
|
||||
else
|
||||
status = 0
|
||||
if(!cell)
|
||||
to_chat(user, "<span class='warning'>[src] does not have a power source!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] is out of charge.</span>")
|
||||
update_icon()
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/item/melee/baton/attack(mob/M, mob/living/carbon/human/user)
|
||||
if(status && user.disabilities & CLUMSY && prob(50))
|
||||
user.visible_message("<span class='danger'>[user] accidentally hits themself with [src]!</span>", \
|
||||
"<span class='userdanger'>You accidentally hit yourself with [src]!</span>")
|
||||
user.Knockdown(stunforce*3)
|
||||
deductcharge(hitcost)
|
||||
return
|
||||
|
||||
if(iscyborg(M))
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/L = M
|
||||
if(check_martial_counter(L, user))
|
||||
return
|
||||
|
||||
if(user.a_intent != INTENT_HARM)
|
||||
if(status)
|
||||
if(baton_stun(M, user))
|
||||
user.do_attack_animation(M)
|
||||
return
|
||||
else
|
||||
M.visible_message("<span class='warning'>[user] has prodded [M] with [src]. Luckily it was off.</span>", \
|
||||
"<span class='warning'>[user] has prodded you with [src]. Luckily it was off</span>")
|
||||
else
|
||||
if(status)
|
||||
baton_stun(M, user)
|
||||
..()
|
||||
|
||||
|
||||
/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user)
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
|
||||
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
return 0
|
||||
if(iscyborg(loc))
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
if(!R || !R.cell || !R.cell.use(hitcost))
|
||||
return 0
|
||||
else
|
||||
if(!deductcharge(hitcost))
|
||||
return 0
|
||||
|
||||
L.Knockdown(stunforce)
|
||||
L.apply_effect(STUTTER, stunforce)
|
||||
if(user)
|
||||
L.lastattacker = user.real_name
|
||||
L.lastattackerckey = user.ckey
|
||||
L.visible_message("<span class='danger'>[user] has stunned [L] with [src]!</span>", \
|
||||
"<span class='userdanger'>[user] has stunned you with [src]!</span>")
|
||||
add_logs(user, L, "stunned")
|
||||
|
||||
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
|
||||
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
H.forcesay(GLOB.hit_appends)
|
||||
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/melee/baton/emp_act(severity)
|
||||
deductcharge(1000 / severity)
|
||||
..()
|
||||
|
||||
//Makeshift stun baton. Replacement for stun gloves.
|
||||
/obj/item/melee/baton/cattleprod
|
||||
name = "stunprod"
|
||||
desc = "An improvised stun baton."
|
||||
icon_state = "stunprod_nocell"
|
||||
item_state = "prod"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 3
|
||||
throwforce = 5
|
||||
stunforce = 100
|
||||
hitcost = 2000
|
||||
throw_hit_chance = 10
|
||||
slot_flags = SLOT_BACK
|
||||
var/obj/item/device/assembly/igniter/sparkler = 0
|
||||
|
||||
/obj/item/melee/baton/cattleprod/Initialize()
|
||||
. = ..()
|
||||
sparkler = new (src)
|
||||
|
||||
/obj/item/melee/baton/cattleprod/baton_stun()
|
||||
if(sparkler.activate())
|
||||
..()
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
|
||||
/obj/item/nuke_core_container/supermatter
|
||||
name = "supermatter bin"
|
||||
desc = "A tiny receptacle that releases an inert freon mix upon sealing, allowing a sliver of a supermatter crystal to be safely stored.."
|
||||
desc = "A tiny receptacle that releases an inert hyper-noblium mix upon sealing, allowing a sliver of a supermatter crystal to be safely stored.."
|
||||
var/obj/item/nuke_core/supermatter_sliver/sliver
|
||||
|
||||
/obj/item/nuke_core_container/supermatter/Destroy()
|
||||
@@ -193,7 +193,7 @@
|
||||
|
||||
/obj/item/scalpel/supermatter
|
||||
name = "supermatter scalpel"
|
||||
desc = "A scalpel with a tip of condensed freon gas, searingly cold to the touch, that can safely shave a sliver off a supermatter crystal."
|
||||
desc = "A scalpel with a tip of condensed hyper-noblium gas, searingly cold to the touch, that can safely shave a sliver off a supermatter crystal."
|
||||
icon = 'icons/obj/nuke_tools.dmi'
|
||||
icon_state = "supermatter_scalpel"
|
||||
toolspeed = 0.5
|
||||
@@ -202,7 +202,7 @@
|
||||
|
||||
/obj/item/hemostat/supermatter
|
||||
name = "supermatter extraction tongs"
|
||||
desc = "A pair of tongs made from condensed freon gas, searingly cold to the touch, that can safely grip a supermatter sliver."
|
||||
desc = "A pair of tongs made from condensed hyper-noblium gas, searingly cold to the touch, that can safely grip a supermatter sliver."
|
||||
icon = 'icons/obj/nuke_tools.dmi'
|
||||
icon_state = "supermatter_tongs"
|
||||
toolspeed = 0.75
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
flags_1 = CONDUCT_1 | NODROP_1 | DROPDEL_1
|
||||
slot_flags = null
|
||||
block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY
|
||||
luminosity = 3
|
||||
light_range = 3
|
||||
attack_verb = list("brutalized", "eviscerated", "disemboweled", "hacked", "carved", "cleaved") //ONLY THE MOST VISCERAL ATTACK VERBS
|
||||
var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE
|
||||
var/obj/item/disk/nuclear/nuke_disk //OUR STORED NUKE DISK
|
||||
@@ -601,12 +601,11 @@
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/L = M
|
||||
L.endTailWag()
|
||||
if(user.a_intent != INTENT_HARM)
|
||||
var/aim_for_face = ((user.zone_selected == "mouth") || (user.zone_selected == "eyes") || (user.zone_selected == "head"))
|
||||
if(user.a_intent != INTENT_HARM && ((user.zone_selected == "mouth") || (user.zone_selected == "eyes") || (user.zone_selected == "head")))
|
||||
user.do_attack_animation(M)
|
||||
playsound(M, 'sound/weapons/slap.ogg', 50, 1, -1)
|
||||
user.visible_message("<span class='danger'>[user] slaps [M] in the [(aim_for_face)?"face":user.zone_selected]!</span>",
|
||||
"<span class='notice'>You slap [M] in the [(aim_for_face)?"face":user.zone_selected]! </span>",\
|
||||
user.visible_message("<span class='danger'>[user] slaps [M]!</span>",
|
||||
"<span class='notice'>You slap [M]!</span>",\
|
||||
"You hear a slap.")
|
||||
return
|
||||
else
|
||||
|
||||
@@ -201,8 +201,8 @@
|
||||
O.attacked_by(src, user)
|
||||
|
||||
/obj/item/gun_control/attack(mob/living/M, mob/living/user)
|
||||
user.lastattacked = M
|
||||
M.lastattacker = user
|
||||
M.lastattacker = user.real_name
|
||||
M.lastattackerckey = user.ckey
|
||||
M.attacked_by(src, user)
|
||||
add_fingerprint(user)
|
||||
|
||||
|
||||
@@ -58,7 +58,8 @@
|
||||
playsound(src.loc, W.usesound, 50, 1)
|
||||
to_chat(user, "You dismantle [src].")
|
||||
new framebuildstacktype(loc, framebuildstackamount)
|
||||
new buildstacktype(loc, buildstackamount)
|
||||
if(buildstackamount)
|
||||
new buildstacktype(loc, buildstackamount)
|
||||
qdel(src)
|
||||
else if(istype(W, /obj/item/weldingtool))
|
||||
var/obj/item/weldingtool/WT = W
|
||||
|
||||
@@ -177,11 +177,6 @@
|
||||
for(var/obj/effect/O in src)
|
||||
if(is_cleanable(O))
|
||||
qdel(O)
|
||||
|
||||
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in src)
|
||||
if(hotspot && !isspaceturf(src))
|
||||
air.temperature = max(min(air.temperature-2000,air.temperature/2),0)
|
||||
qdel(hotspot)
|
||||
return 1
|
||||
|
||||
/turf/open/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube)
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
return
|
||||
|
||||
//Hangars and pods covered in oil.
|
||||
var/static/list/oily_areas = typecacheof(list(/area/quartermaster))
|
||||
var/static/list/oily_areas = typecacheof(/area/quartermaster)
|
||||
if(is_type_in_typecache(A, oily_areas))
|
||||
if(prob(25))
|
||||
new /obj/effect/decal/cleanable/oil(src)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
dir = SOUTH
|
||||
baseturf = /turf/open/space/transit
|
||||
flags_1 = NOJAUNT_1 //This line goes out to every wizard that ever managed to escape the den. I'm sorry.
|
||||
explosion_block = INFINITY
|
||||
|
||||
/turf/open/space/transit/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
|
||||
. = ..()
|
||||
|
||||
Reference in New Issue
Block a user