Merge branch 'master' into upstream-merge-31737

This commit is contained in:
LetterJay
2017-10-28 02:20:25 -04:00
committed by GitHub
291 changed files with 204450 additions and 223168 deletions
+4
View File
@@ -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
+1 -1
View File
@@ -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>")
-72
View File
@@ -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
-42
View File
@@ -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
+6 -33
View File
@@ -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
+61 -17
View File
@@ -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)
+2 -1
View File
@@ -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()
+11 -11
View File
@@ -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
+7
View File
@@ -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)
+13
View File
@@ -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()
+5 -1
View File
@@ -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)
+6
View File
@@ -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)
+4 -3
View File
@@ -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)
+71 -72
View File
@@ -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)
+10 -2
View File
@@ -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
+8 -2
View File
@@ -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))
+45 -49
View File
@@ -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())
+1
View File
@@ -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)
+28 -28
View File
@@ -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
+4 -5
View File
@@ -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)
+67 -68
View File
@@ -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()
..()
+80 -162
View File
@@ -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
+21 -21
View File
@@ -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//
////////////////////////
+1 -1
View File
@@ -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()
+2
View File
@@ -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"
+45 -50
View File
@@ -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
+4 -2
View File
@@ -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
+5 -2
View File
@@ -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)
+27 -21
View File
@@ -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
+10 -4
View File
@@ -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
. = ..()
+202 -202
View File
@@ -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())
..()
+3 -3
View File
@@ -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
+4 -5
View File
@@ -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)
+2 -1
View File
@@ -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
-5
View File
@@ -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)
+1 -1
View File
@@ -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)
+1
View File
@@ -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)
. = ..()