Merge remote-tracking branch 'citadel/master' into combat_v7

This commit is contained in:
silicons
2021-06-07 16:47:11 -07:00
247 changed files with 7302 additions and 2875 deletions
+36 -1
View File
@@ -36,6 +36,14 @@
///Value used to increment ex_act() if reactionary_explosions is on
var/explosion_block = 0
/// Flags for explosions
var/explosion_flags = NONE
/// Amount to decrease wave explosions by
var/wave_explosion_block = 0
/// Amount to multiply wave explosions by
var/wave_explosion_multiply = 1
//its inherent color, the colored paint applied on it, special color effect etc...
/**
* used to store the different colors on an atom
*
@@ -43,7 +51,6 @@
*/
var/list/atom_colours
/// a very temporary list of overlays to remove
var/list/remove_overlays
/// a very temporary list of overlays to add
@@ -556,6 +563,34 @@
contents_explosion(severity, target)
SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, severity, target)
/**
* Called when a wave explosion hits this atom. Do not override this.
*
* Returns explosion power to "allow through".
*/
/atom/proc/wave_explode(power, datum/wave_explosion/explosion, dir)
set waitfor = FALSE
// SHOULD_NOT_SLEEP(TRUE)
SHOULD_NOT_OVERRIDE(TRUE)
SEND_SIGNAL(src, COMSIG_ATOM_WAVE_EX_ACT, args)
. = wave_ex_act(power, explosion, dir) // this must happen first for stuff like destruction/damage to tick.
if(isnull(.))
stack_trace("wave_ex_act on [type] failed to return a number. defaulting to no blocking.")
return power
if((explosion_flags & EXPLOSION_FLAG_DENSITY_DEPENDENT) && !density)
return power // no block
else if((explosion_flags & EXPLOSION_FLAG_HARD_OBSTACLE) && !QDELETED(src))
return 0 // fully blocked
/**
* Called when a wave explosion hits this atom.
*
* Returns explosion power to "allow through". Standard handling and flag overrides in [wave_explode()].
*/
/atom/proc/wave_ex_act(power, datum/wave_explosion/explosion, dir)
// SHOULD_NOT_SLEEP(TRUE)
return power * wave_explosion_multiply - wave_explosion_block
/atom/proc/blob_act(obj/structure/blob/B)
SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, B)
return
+4 -1
View File
@@ -55,6 +55,9 @@
///Internal holder for emissive blocker object, do not use directly use blocks_emissive
var/atom/movable/emissive_blocker/em_block
/// Should we use tooltips, if the thing does not have the code implemented `get_tooltip_data()`, it will default to examine(src)
var/tooltips = FALSE
/atom/movable/Initialize(mapload)
. = ..()
@@ -576,7 +579,7 @@
//TODO: Better floating
/atom/movable/proc/float(on, throw_override)
if(throwing || !throw_override)
if(throwing && !throw_override)
return
if(on && !(movement_type & FLOATING))
animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
+4
View File
@@ -96,6 +96,10 @@ Class Procs:
flags_ricochet = RICOCHET_HARD
ricochet_chance_mod = 0.3
explosion_flags = EXPLOSION_FLAG_DENSITY_DEPENDENT
wave_explosion_block = EXPLOSION_BLOCK_MACHINE
wave_explosion_multiply = EXPLOSION_DAMPEN_MACHINE
anchored = TRUE
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT
@@ -79,10 +79,12 @@
if (obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
SSshuttle.shuttle_purchase_requirements_met |= "emagged"
if (authenticated)
authorize_access = get_all_accesses()
to_chat(user, "<span class='danger'>You scramble the communication routing circuits!</span>")
playsound(src, 'sound/machines/terminal_alert.ogg', 50, FALSE)
SSshuttle.shuttle_purchase_requirements_met["emagged"] = TRUE
return
/obj/machinery/computer/communications/ui_act(action, list/params)
+3 -1
View File
@@ -54,6 +54,8 @@
assemblytype = /obj/structure/door_assembly
normalspeed = 1
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_WALL
wave_explosion_multiply = EXPLOSION_DAMPEN_WALL
hud_possible = list(DIAG_AIRLOCK_HUD)
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN
@@ -686,7 +688,7 @@
else
. += "It looks very robust."
if(hasSiliconAccessInArea(user) && (!stat & BROKEN))
if(hasSiliconAccessInArea(user) && !(stat & BROKEN))
. += "<span class='notice'>Shift-click [src] to [ density ? "open" : "close"] it.</span>"
. += "<span class='notice'>Ctrl-click [src] to [ locked ? "raise" : "drop"] its bolts.</span>"
. += "<span class='notice'>Alt-click [src] to [ secondsElectrified ? "un-electrify" : "permanently electrify"] it.</span>"
+10
View File
@@ -16,6 +16,11 @@
interaction_flags_atom = INTERACT_ATOM_UI_INTERACT
wave_explosion_block = EXPLOSION_BLOCK_DENSE_FILLER
wave_explosion_multiply = EXPLOSION_DAMPEN_DENSE_FILLER
explosion_flags = EXPLOSION_FLAG_HARD_OBSTACLE | EXPLOSION_FLAG_DENSITY_DEPENDENT
var/secondsElectrified = 0
var/air_tight = FALSE //TRUE means density will be set as soon as the door begins to close
var/shockedby
@@ -412,3 +417,8 @@
/obj/machinery/door/GetExplosionBlock()
return density ? real_explosion_block : 0
/obj/machinery/door/wave_explosion_damage(power, datum/wave_explosion/explosion)
. = ..()
if(!density)
return . * EXPLOSION_DAMAGE_OPEN_DOOR_FACTOR
@@ -71,3 +71,6 @@
/obj/machinery/door/password/ex_act(severity, target)
return
/obj/machinery/door/password/wave_ex_act(power, datum/wave_explosion/explosion, dir)
return 0 //no.
+2
View File
@@ -8,6 +8,8 @@
closingLayer = CLOSED_BLASTDOOR_LAYER
sub_door = TRUE
explosion_block = 3
wave_explosion_block = EXPLOSION_BLOCK_BLAST_PROOF
wave_explosion_multiply = EXPLOSION_DAMPEN_BLAST_PROOF
heat_proof = TRUE
safe = FALSE
max_integrity = 600
+2
View File
@@ -360,6 +360,8 @@
max_integrity = 300 //Stronger doors for prison (regular window door health is 200)
reinf = 1
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_REINFORCED_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_REINFORCED_WINDOW
/obj/machinery/door/window/brigdoor/security/cell
name = "cell door"
+38
View File
@@ -114,6 +114,44 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
LAZYADD(message_log, messages.Join(" "))
return TRUE
/obj/machinery/doppler_array/proc/sense_wave_explosion(turf/epicenter, power, speed)
if(stat & NOPOWER)
return FALSE
var/turf/zone = get_turf(src)
if(zone.z != epicenter.z)
return FALSE
if(next_announce > world.time)
return FALSE
next_announce = world.time + cooldown
var/distance = get_dist(epicenter, zone)
var/direct = get_dir(zone, epicenter)
if(distance > max_dist)
return FALSE
if(!(direct & dir) && !integrated)
return FALSE
var/list/messages = list("Explosive shockwave detected.", \
"Epicenter at: grid ([epicenter.x],[epicenter.y]). Shockwave expanding at a theoretical speed of [speed] m/s.", \
"Wave energy: [power]MJ.")
if(integrated)
var/obj/item/clothing/head/helmet/space/hardsuit/helm = loc
if(!helm || !istype(helm, /obj/item/clothing/head/helmet/space/hardsuit))
return FALSE
helm.display_visor_message("Waveform explosion detected! Wave energy: [power]MJ.")
else
for(var/message in messages)
say(message)
if(LAZYLEN(message_log) > list_limit)
say("Storage buffer is full! Clearing buffers...")
LAZYCLEARLIST(message_log)
LAZYADD(message_log, messages.Join(" "))
return TRUE
/obj/machinery/doppler_array/examine(mob/user)
. = ..()
. += "<span class='notice'>Its dish is facing to the [dir2text(dir)].</span>"
+234 -195
View File
@@ -1,9 +1,5 @@
#define LIMBGROWER_MAIN_MENU 1
#define LIMBGROWER_CATEGORY_MENU 2
#define LIMBGROWER_CHEMICAL_MENU 3
//use these for the menu system
/// The limbgrower. Makes organd and limbs with synthflesh and chems.
/// See [limbgrower_designs.dm] for everything we can make.
/obj/machinery/limbgrower
name = "limb grower"
desc = "It grows new limbs using Synthflesh."
@@ -15,161 +11,235 @@
active_power_usage = 100
circuit = /obj/item/circuitboard/machine/limbgrower
var/operating = FALSE
var/disabled = FALSE
/// The category of limbs we're browing in our UI.
var/selected_category = "human"
/// If we're currently printing something.
var/busy = FALSE
var/prod_coeff = 1
/// How efficient our machine is. Better parts = less chemicals used and less power used. Range of 1 to 0.25.
var/production_coefficient = 1
/// How long it takes for us to print a limb. Affected by production_coefficient.
var/production_speed = 3 SECONDS
/// The design we're printing currently.
var/datum/design/being_built
/// Our internal techweb for limbgrower designs.
var/datum/techweb/stored_research
var/selected_category
var/screen = 1
/// All the categories of organs we can print.
var/list/categories = list(
"human" = /datum/species/human,
"lizard" = /datum/species/lizard,
"mammal" = /datum/species/mammal,
"insect" = /datum/species/insect,
"fly" = /datum/species/fly,
"plasmaman" = /datum/species/plasmaman,
"xeno" = /datum/species/xeno,
"other" = /datum/species,
)
var/list/stored_species = list()
"human",
"lizard",
"mammal",
"insect",
"fly",
"plasmaman",
"xeno",
"other",
)
var/obj/item/disk/data/dna_disk
/obj/machinery/limbgrower/Initialize()
create_reagents(100, OPENCONTAINER)
stored_research = new /datum/techweb/specialized/autounlocking/limbgrower
for(var/i in categories)
var/species = categories[i]
stored_species[i] = new species()
. = ..()
AddComponent(/datum/component/plumbing/simple_demand)
AddComponent(/datum/component/simple_rotation, ROTATION_WRENCH | ROTATION_CLOCKWISE, null, CALLBACK(src, .proc/can_be_rotated))
/obj/machinery/limbgrower/ui_interact(mob/user)
/obj/machinery/limbgrower/ui_interact(mob/user, datum/tgui/ui)
. = ..()
if(!is_operational())
return
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Limbgrower", src)
ui.open()
var/dat = main_win(user)
/obj/machinery/limbgrower/ui_data(mob/user)
var/list/data = list()
switch(screen)
if(LIMBGROWER_MAIN_MENU)
dat = main_win(user)
if(LIMBGROWER_CATEGORY_MENU)
dat = category_win(user,selected_category)
if(LIMBGROWER_CHEMICAL_MENU)
dat = chemical_win(user)
for(var/datum/reagent/reagent_id in reagents.reagent_list)
var/list/reagent_data = list(
reagent_name = reagent_id.name,
reagent_amount = reagent_id.volume,
reagent_type = reagent_id.type
)
data["reagents"] += list(reagent_data)
var/datum/browser/popup = new(user, "Limb Grower", name, 400, 500)
popup.set_content(dat)
popup.open()
data["total_reagents"] = reagents.total_volume
data["max_reagents"] = reagents.maximum_volume
data["busy"] = busy
var/list/disk_data = list()
disk_data["disk"] = dna_disk //Do i, the machine, have a disk?
disk_data["name"] = dna_disk?.fields["name"] //Name for the human saved if there is one
data["disk"] = disk_data
return data
/obj/machinery/limbgrower/ui_static_data(mob/user)
var/list/data = list()
data["categories"] = list()
var/species_categories = categories.Copy()
for(var/species in species_categories)
species_categories[species] = list()
for(var/design_id in stored_research.researched_designs)
var/datum/design/limb_design = SSresearch.techweb_design_by_id(design_id)
for(var/found_category in species_categories)
if(found_category in limb_design.category)
species_categories[found_category] += limb_design
for(var/category in species_categories)
var/list/category_data = list(
name = category,
designs = list(),
)
for(var/datum/design/found_design in species_categories[category])
var/list/all_reagents = list()
for(var/reagent_typepath in found_design.reagents_list)
var/datum/reagent/reagent_id = find_reagent_object_from_type(reagent_typepath)
var/list/reagent_data = list(
name = reagent_id.name,
amount = (found_design.reagents_list[reagent_typepath] * production_coefficient),
)
all_reagents += list(reagent_data)
category_data["designs"] += list(list(
parent_category = category,
name = found_design.name,
id = found_design.id,
needed_reagents = all_reagents,
))
data["categories"] += list(category_data)
return data
/obj/machinery/limbgrower/on_deconstruction()
for(var/obj/item/reagent_containers/glass/G in component_parts)
reagents.trans_to(G, G.reagents.maximum_volume)
for(var/obj/item/reagent_containers/glass/our_beaker in component_parts)
reagents.trans_to(our_beaker, our_beaker.reagents.maximum_volume)
..()
/obj/machinery/limbgrower/attackby(obj/item/O, mob/user, params)
if(busy)
/obj/machinery/limbgrower/attackby(obj/item/user_item, mob/living/user, params)
if (busy)
to_chat(user, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
return
if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", O))
updateUsrDialog()
if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", user_item))
ui_close(user)
return
if(panel_open && default_deconstruction_crowbar(O))
return
if(user.a_intent == INTENT_HARM) //so we can hit the machine
if(user_item.tool_behaviour == TOOL_WRENCH && panel_open)
return ..()
if(istype(O, /obj/item/disk))
if(panel_open && default_deconstruction_crowbar(user_item))
return
if(istype(user_item, /obj/item/disk))
if(dna_disk)
to_chat(user, "<span class='warning'>\The [src] already has a dna disk, take it out first!</span>")
return
else
O.forceMove(src)
dna_disk = O
to_chat(user, "<span class='notice'>You insert \the [O] into \the [src].</span>")
user_item.forceMove(src)
dna_disk = user_item
to_chat(user, "<span class='notice'>You insert \the [user_item] into \the [src].</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
return
/obj/machinery/limbgrower/Topic(href, href_list)
if(..())
if(user.a_intent != INTENT_HELP)
return ..()
/obj/machinery/limbgrower/proc/can_be_rotated()
if(panel_open)
return TRUE
return FALSE
/obj/machinery/limbgrower/ui_act(action, list/params)
. = ..()
if(.)
return
if (!busy)
if(href_list["menu"])
screen = text2num(href_list["menu"])
if(href_list["category"])
selected_category = href_list["category"]
if (busy)
to_chat(usr, "<span class='danger'>\The [src] is busy. Please wait for completion of previous operation.</span>")
return
if(href_list["disposeI"]) //Get rid of a reagent incase you add the wrong one by mistake
reagents.del_reagent(text2path(href_list["disposeI"]))
switch(action)
if(href_list["make"])
if("empty_reagent")
reagents.del_reagent(text2path(params["reagent_type"]))
. = TRUE
/////////////////
//href protection
being_built = stored_research.isDesignResearchedID(href_list["make"]) //check if it's a valid design
if("eject_disk")
eject_disk(usr)
if("make_limb")
being_built = stored_research.isDesignResearchedID(params["design_id"])
if(!being_built)
return
CRASH("[src] was passed an invalid design id!")
/// All the reagents we're using to make our organ.
var/list/consumed_reagents_list = being_built.reagents_list.Copy()
/// The amount of power we're going to use, based on how much reagent we use.
var/power = 0
var/synth_cost = being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff
var/power = max(2000, synth_cost/5)
for(var/reagent_id in consumed_reagents_list)
consumed_reagents_list[reagent_id] *= production_coefficient
if(!reagents.has_reagent(reagent_id, consumed_reagents_list[reagent_id]))
audible_message("<span class='notice'>\The [src] buzzes.</span>")
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
return
if(reagents.has_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff))
busy = TRUE
use_power(power)
flick("limbgrower_fill",src)
icon_state = "limbgrower_idleon"
addtimer(CALLBACK(src, .proc/build_item),32*prod_coeff)
power = max(2000, (power + consumed_reagents_list[reagent_id]))
if(href_list["dna_disk"])
var/mob/living/carbon/user = usr
if(istype(user))
if(!dna_disk)
var/obj/item/disk/diskette = user.get_active_held_item()
if(istype(diskette))
diskette.forceMove(src)
dna_disk = diskette
to_chat(user, "<span class='notice'>You insert \the [diskette] into \the [src].</span>")
else
dna_disk.forceMove(src.loc)
user.put_in_active_hand(dna_disk)
to_chat(user, "<span class='notice'>You remove \the [dna_disk] from \the [src].</span>")
dna_disk = null
else
to_chat(user, "<span class='warning'>You are unable to grasp \the [dna_disk] disk from \the [src].</span>")
else
to_chat(usr, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
busy = TRUE
use_power(power)
flick("limbgrower_fill",src)
icon_state = "limbgrower_idleon"
selected_category = params["active_tab"]
addtimer(CALLBACK(src, .proc/build_item, consumed_reagents_list), production_speed * production_coefficient)
. = TRUE
updateUsrDialog()
return
/obj/machinery/limbgrower/proc/build_item()
if(reagents.has_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)) //sanity check, if this happens we are in big trouble
reagents.remove_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)
var/buildpath = being_built.build_path
if(ispath(buildpath, /obj/item/bodypart)) //This feels like spaghetti code, but i need to initiliaze a limb somehow
build_limb(buildpath)
else if(ispath(buildpath, /obj/item/organ/genital)) //genitals are uhh... customizable
build_genital(buildpath)
else
//Just build whatever it is
new buildpath(loc)
else
src.visible_message("<span class=\"error\"> Something went very wrong and there isnt enough synthflesh anymore!</span>")
busy = FALSE
flick("limbgrower_unfill",src)
icon_state = "limbgrower_idleoff"
updateUsrDialog()
/*
* The process of beginning to build a limb or organ.
* Goes through and sanity checks that we actually have enough reagent to build our item.
* Then, remove those reagents from our reagents datum.
*
* After the reagents are handled, we can proceede with making the limb or organ. (Limbs are handled in a separate proc)
*
* modified_consumed_reagents_list - the list of reagents we will consume on build, modified by the production coefficient.
*/
/obj/machinery/limbgrower/proc/build_item(list/modified_consumed_reagents_list)
for(var/reagent_id in modified_consumed_reagents_list)
if(!reagents.has_reagent(reagent_id, modified_consumed_reagents_list[reagent_id]))
audible_message("<span class='notice'>\The [src] buzzes.</span>")
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
break
/obj/machinery/limbgrower/proc/build_limb(buildpath)
reagents.remove_reagent(reagent_id, modified_consumed_reagents_list[reagent_id])
var/built_typepath = being_built.build_path
// If we have a bodypart, we need to initialize the limb on its own. Otherwise we can build it here.
if(ispath(built_typepath, /obj/item/bodypart))
build_limb(built_typepath)
else if(ispath(built_typepath, /obj/item/organ/genital)) //genitals are uhh... customizable
build_genital(built_typepath)
else
new built_typepath(loc)
busy = FALSE
flick("limbgrower_unfill", src)
icon_state = "limbgrower_idleoff"
/*
* The process of putting together a limb.
* This is called from after we remove the reagents, so this proc is just initializing the limb type.
*
* This proc handles skin / mutant color, greyscaling, names and descriptions, and various other limb creation steps.
*
* built_typepath - the path of the bodypart we're building.
*/
/obj/machinery/limbgrower/proc/build_limb(built_typepath)
//i need to create a body part manually using a set icon (otherwise it doesnt appear)
var/obj/item/bodypart/limb
var/datum/species/selected = stored_species[selected_category]
limb = new buildpath(loc)
var/datum/species/selected = GLOB.species_datums[selected_category]
limb = new built_typepath(loc)
limb.base_bp_icon = selected.icon_limbs || DEFAULT_BODYPART_ICON_ORGANIC
limb.species_id = selected.limbs_id
limb.color_src = (MUTCOLORS in selected.species_traits ? MUTCOLORS : (selected.use_skintones ? SKINTONE : FALSE))
@@ -189,135 +259,103 @@
BP.name = "\improper synthetic [lowertext(selected.name)] [limb.name]"
BP.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]."
/obj/machinery/limbgrower/proc/build_genital(buildpath)
/*
* Builds genitals, modifies to be the same
* as the person's cloning data on the data disk
*/
/obj/machinery/limbgrower/proc/build_genital(built_typepath)
//i needed to create a way to customize gene tools using dna
var/list/features = dna_disk?.fields["features"]
if(length(features))
switch(buildpath)
switch(built_typepath)
if(/obj/item/organ/genital/penis)
var/obj/item/organ/genital/penis/penis = new(loc)
if(features["has_cock"])
penis.shape = features["cock_shape"]
penis.length = features["cock_shape"]
penis.diameter_ratio = features["cock_diameter_ratio"]
penis.color = sanitize_hexcolor(features["cock_color"], 6)
penis.update_icon()
penis.color = sanitize_hexcolor(features["cock_color"], 6, TRUE)
penis.update()
if(/obj/item/organ/genital/testicles)
var/obj/item/organ/genital/testicles/balls = new(loc)
if(features["has_balls"])
balls.color = sanitize_hexcolor(features["balls_color"], 6)
balls.color = sanitize_hexcolor(features["balls_color"], 6, TRUE)
balls.shape = features["balls_shape"]
balls.size = features["balls_size"]
balls.fluid_rate = features["balls_cum_rate"]
balls.fluid_mult = features["balls_cum_mult"]
balls.fluid_efficiency = features["balls_efficiency"]
balls.update()
if(/obj/item/organ/genital/vagina)
var/obj/item/organ/genital/vagina/vegana = new(loc)
if(features["has_vagina"])
vegana.color = sanitize_hexcolor(features["vag_color"], 6)
if(features["has_vag"])
vegana.color = sanitize_hexcolor(features["vag_color"], 6, TRUE)
vegana.shape = features["vag_shape"]
vegana.update()
if(/obj/item/organ/genital/breasts)
var/obj/item/organ/genital/breasts/boobs = new(loc)
if(features["has_breasts"])
boobs.color = sanitize_hexcolor(features["breasts_color"], 6)
boobs.color = sanitize_hexcolor(features["breasts_color"], 6, TRUE)
boobs.size = features["breasts_size"]
boobs.shape = features["breasts_shape"]
if(!features["breasts_producing"])
boobs.genital_flags &= ~(GENITAL_FUID_PRODUCTION|CAN_CLIMAX_WITH|CAN_MASTURBATE_WITH)
boobs.update()
else
new buildpath(loc)
new built_typepath(loc)
else
new buildpath(loc)
new built_typepath(loc)
/obj/machinery/limbgrower/RefreshParts()
reagents.maximum_volume = 0
for(var/obj/item/reagent_containers/glass/G in component_parts)
reagents.maximum_volume += G.volume
G.reagents.trans_to(src, G.reagents.total_volume)
var/T=1.2
for(var/obj/item/stock_parts/manipulator/M in component_parts)
T -= M.rating*0.2
prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
for(var/obj/item/reagent_containers/glass/our_beaker in component_parts)
reagents.maximum_volume += our_beaker.volume
our_beaker.reagents.trans_to(src, our_beaker.reagents.total_volume)
production_coefficient = 1.2
for(var/obj/item/stock_parts/manipulator/our_manipulator in component_parts)
production_coefficient -= our_manipulator.rating * 0.2
production_coefficient = clamp(production_coefficient, 0, 1) // coefficient goes from 1 -> 0.8 -> 0.6 -> 0.4
/obj/machinery/limbgrower/examine(mob/user)
. = ..()
if(!panel_open)
. += "<span class='notice'>It looks like as if the panel were open you could rotate it with a <b>wrench</b>.</span>"
else
. += "<span class='notice'>The panel is open.</span>"
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Storing up to <b>[reagents.maximum_volume]u</b> of synthflesh.<br>Synthflesh consumption at <b>[prod_coeff*100]%</b>.<span>"
. += "<span class='notice'>The status display reads: Storing up to <b>[reagents.maximum_volume]u</b> of reagents.<br>Reagent consumption rate at <b>[production_coefficient * 100]%</b>.</span>"
/obj/machinery/limbgrower/proc/main_win(mob/user)
var/dat = "<div class='statusDisplay'><h3>[src] Menu:</h3><br>"
dat += "<A href='?src=[REF(src)];dna_disk=1'>[dna_disk ? "Remove" : "Insert"] cloning data disk</A>"
dat += "<hr>"
dat += "<A href='?src=[REF(src)];menu=[LIMBGROWER_CHEMICAL_MENU]'>Chemical Storage</A>"
dat += materials_printout()
dat += "<table style='width:100%' align='center'><tr>"
for(var/C in categories)
dat += "<td><A href='?src=[REF(src)];category=[C];menu=[LIMBGROWER_CATEGORY_MENU]'>[C]</A></td>"
dat += "</tr><tr>"
//one category per line
dat += "</tr></table></div>"
return dat
/obj/machinery/limbgrower/proc/category_win(mob/user,selected_category)
var/dat = "<A href='?src=[REF(src)];menu=[LIMBGROWER_MAIN_MENU]'>Return to main menu</A>"
dat += "<div class='statusDisplay'><h3>Browsing [selected_category]:</h3><br>"
dat += materials_printout()
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(!(selected_category in D.category))
continue
if(disabled || !can_build(D))
dat += "<span class='linkOff'>[D.name]</span>"
else
dat += "<a href='?src=[REF(src)];make=[D.id];multiplier=1'>[D.name]</a>"
dat += "[get_design_cost(D)]<br>"
dat += "</div>"
return dat
/obj/machinery/limbgrower/proc/chemical_win(mob/user)
var/dat = "<A href='?src=[REF(src)];menu=[LIMBGROWER_MAIN_MENU]'>Return to main menu</A>"
dat += "<div class='statusDisplay'><h3>Browsing Chemical Storage:</h3><br>"
dat += materials_printout()
for(var/datum/reagent/R in reagents.reagent_list)
dat += "[R.name]: [R.volume]"
dat += "<A href='?src=[REF(src)];disposeI=[R]'>Purge</A><BR>"
dat += "</div>"
return dat
/obj/machinery/limbgrower/proc/materials_printout()
var/dat = "<b>Total amount:></b> [reagents.total_volume] / [reagents.maximum_volume] cm<sup>3</sup><br>"
return dat
/obj/machinery/limbgrower/proc/can_build(datum/design/D)
return (reagents.has_reagent(/datum/reagent/medicine/synthflesh, D.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)) //Return whether the machine has enough synthflesh to produce the design
/obj/machinery/limbgrower/proc/get_design_cost(datum/design/D)
var/dat
if(D.reagents_list[/datum/reagent/medicine/synthflesh])
dat += "[D.reagents_list[/datum/reagent/medicine/synthflesh] * prod_coeff] Synthetic flesh "
return dat
/*
* Checks our reagent list to see if a design can be built.
*
* limb_design - the design we're checking for buildability.
*
* returns TRUE if we have enough reagent to build it. Returns FALSE if we do not.
*/
/obj/machinery/limbgrower/proc/can_build(datum/design/limb_design)
for(var/datum/reagent/reagent_id in limb_design.reagents_list)
if(!reagents.has_reagent(reagent_id, limb_design.reagents_list[reagent_id] * production_coefficient))
return FALSE
return TRUE
/// Emagging a limbgrower allows you to build synthetic armblades.
/obj/machinery/limbgrower/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
return
for(var/id in SSresearch.techweb_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(id)
if((D.build_type & LIMBGROWER) && ("emagged" in D.category))
stored_research.add_design(D)
for(var/design_id in SSresearch.techweb_designs)
var/datum/design/found_design = SSresearch.techweb_design_by_id(design_id)
if((found_design.build_type & LIMBGROWER) && ("emagged" in found_design.category))
stored_research.add_design(found_design)
to_chat(user, "<span class='warning'>A warning flashes onto the screen, stating that safety overrides have been deactivated!</span>")
obj_flags |= EMAGGED
return TRUE
update_static_data(user)
/obj/machinery/limbgrower/AltClick(mob/living/user)
. = ..()
eject_disk(user)
/obj/machinery/limbgrower/proc/eject_disk(mob/user)
if(istype(user) && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
if(busy)
to_chat(user, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
@@ -326,6 +364,7 @@
dna_disk.forceMove(src.loc)
user.put_in_active_hand(dna_disk)
to_chat(user, "<span class='notice'>You remove \the [dna_disk] from \the [src].</span>")
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
dna_disk = null
else
to_chat(user, "<span class='warning'>\The [src] has doesn't have a disk on it!")
@@ -50,6 +50,10 @@
/obj/effect/decal/cleanable/glass/ex_act()
qdel(src)
/obj/effect/decal/cleanable/glass/wave_ex_act(power, datum/wave_explosion/explosion, dir)
qdel(src)
return power
/obj/effect/decal/cleanable/glass/plasma
icon_state = "plasmatiny"
@@ -131,6 +135,9 @@
/obj/effect/decal/cleanable/greenglow/ex_act()
return
/obj/effect/decal/cleanable/greenglow/wave_ex_act(power, datum/wave_explosion/explosion, dir)
return power
/obj/effect/decal/cleanable/cobweb
name = "cobweb"
desc = "Somebody should remove that."
@@ -253,6 +260,11 @@
if(severity == 1) //so shreds created during an explosion aren't deleted by the explosion.
qdel(src)
/obj/effect/decal/cleanable/shreds/wave_ex_act(power, datum/wave_explosion/explosion, dir)
if(power > EXPLOSION_POWER_ERASE_SHREDS)
qdel(src)
return power // no block
/obj/effect/decal/cleanable/shreds/Initialize()
pixel_x = rand(-10, 10)
pixel_y = rand(-10, 10)
@@ -309,6 +309,10 @@
/obj/structure/foamedmetal/resin/Initialize()
. = ..()
neutralize_air()
addtimer(CALLBACK(src, .proc/neutralize_air), 5) // yeah this sucks, maybe when auxmos is out
/obj/structure/foamedmetal/resin/proc/neutralize_air()
if(isopenturf(loc))
var/turf/open/O = loc
O.ClearWet()
+8
View File
@@ -248,6 +248,14 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
loc = null
loc = T
/obj/item/wave_ex_act(power, datum/wave_explosion/explosion, dir)
. = ..()
if(!anchored)
var/throw_dist = round(rand(3, max(3, 2.5 * sqrt(power))), 1)
throw_speed = EXPLOSION_THROW_SPEED
var/turf/target = get_ranged_target_turf(src, dir, throw_dist)
throw_at(target, throw_dist, EXPLOSION_THROW_SPEED)
/obj/item/examine(mob/user) //This might be spammy. Remove?
. = ..()
+7 -1
View File
@@ -157,7 +157,7 @@
to_chat(user, "<span class='notice'>You need to get closer!</span>")
return
if(use_paint(user) && isturf(F))
F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, turn(stored_dir, -dir2angle(F.dir)), CLEAN_STRONG, color, null, null, alpha)
F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_STRONG, color, null, null, alpha)
/obj/item/airlock_painter/decal/attack_self(mob/user)
if((ink) && (ink.charges >= 1))
@@ -180,6 +180,11 @@
stored_decal_total = "[stored_decal][yellow_fix][stored_color]"
return
/obj/item/airlock_painter/decal/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/decals)
)
/obj/item/airlock_painter/decal/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -189,6 +194,7 @@
/obj/item/airlock_painter/decal/ui_data(mob/user)
var/list/data = list()
data["decal_direction"] = stored_dir
data["decal_dir_text"] = dir2text(stored_dir)
data["decal_color"] = stored_color
data["decal_style"] = stored_decal
data["decal_list"] = list()
+3
View File
@@ -553,6 +553,9 @@
/obj/item/card/id/syndicate/locked_banking
bank_support = ID_LOCKED_BANK_ACCOUNT
/obj/item/card/id/pirate
access = list(ACCESS_SYNDICATE)
/obj/item/card/id/captains_spare
name = "captain's spare ID"
desc = "The spare ID of the High Lord himself."
-15
View File
@@ -75,18 +75,3 @@
desc = "A chromosome that reduces action based mutation cooldowns by by 50%."
icon_state = "energy"
energy_coeff = 0.5
/obj/item/chromosome/reinforcer
name = "reinforcement chromosome"
desc = "A chromosome that renders mutations immune to mutadone."
icon_state = "reinforcer"
weight = 3
/obj/item/chromosome/reinforcer/can_apply(datum/mutation/human/HM)
if(!HM || !(HM.can_chromosome == CHROMOSOME_NONE))
return FALSE
return !HM.mutadone_proof
/obj/item/chromosome/reinforcer/apply(datum/mutation/human/HM)
HM.mutadone_proof = TRUE
..()
+6 -1
View File
@@ -649,6 +649,9 @@
pre_noise = TRUE
post_noise = FALSE
var/stun_delay = 0 // how long it takes for you to be able to stun someone with the spraycan again
var/last_stun_time = 0
/obj/item/toy/crayon/spraycan/isValidSurface(surface)
return (istype(surface, /turf/open/floor) || istype(surface, /turf/closed/wall))
@@ -716,7 +719,8 @@
if(C.client)
C.blur_eyes(3)
C.blind_eyes(1)
if(C.get_eye_protection() <= 0) // no eye protection? ARGH IT BURNS.
if(C.get_eye_protection() <= 0 && (last_stun_time + stun_delay) <= world.time) // no eye protection? ARGH IT BURNS.
last_stun_time = world.time
C.confused = max(C.confused, 3)
C.DefaultCombatKnockdown(60)
if(ishuman(C) && actually_paints)
@@ -771,6 +775,7 @@
name = "cyborg spraycan"
desc = "A metallic container containing shiny synthesised paint."
charges = -1
stun_delay = 5 SECONDS
/obj/item/toy/crayon/spraycan/borg/draw_on(atom/target,mob/user,proximity, params)
var/diff = ..()
+54
View File
@@ -100,6 +100,42 @@
"<span class='suicide'>[user] is slitting [user.p_their()] stomach open with the [src.name]! It looks like [user.p_theyre()] trying to commit seppuku.</span>"))
return (BRUTELOSS)
/obj/item/kitchen/efink
name = "E-Fink"
icon_state = "efink"
desc = "The E-Fink is a product by Mending Solutions Inc. Unfortunately it can only mend sliced meat, fruits and dough back to their original state. Unbutchering is not possible."
flags_1 = CONDUCT_1
force = 10
w_class = WEIGHT_CLASS_SMALL
throwforce = 10
hitsound = 'sound/weapons/bladesliceb.ogg'
throw_speed = 3
throw_range = 6
custom_materials = list(/datum/material/iron=12000)
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
sharpness = SHARP_POINTY
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
var/bayonet = FALSE //Can this be attached to a gun?
wound_bonus = -5
bare_wound_bonus = 10
custom_price = PRICE_NORMAL
/obj/item/kitchen/efink/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 80 - force, 100, force - 10) //bonus chance increases depending on force
/obj/item/kitchen/efink/attack(mob/living/carbon/M, mob/living/carbon/user)
if(user.zone_selected == BODY_ZONE_PRECISE_EYES)
return eyestab(M,user)
else
return ..()
/obj/item/kitchen/efink/suicide_act(mob/user)
user.visible_message(pick("<span class='suicide'>[user] is slitting [user.p_their()] wrists with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.</span>", \
"<span class='suicide'>[user] is slitting [user.p_their()] throat with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.</span>", \
"<span class='suicide'>[user] is slitting [user.p_their()] stomach open with the [src.name]! It looks like [user.p_theyre()] trying to commit seppuku.</span>"))
return (BRUTELOSS)
/obj/item/kitchen/knife/ritual
name = "ritual knife"
desc = "The unearthly energies that once powered this blade are now dormant."
@@ -248,6 +284,24 @@
/obj/item/kitchen/rollingpin/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins flattening [user.p_their()] head with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return BRUTELOSS
/obj/item/kitchen/unrollingpin
name = "unrolling pin"
desc = "For when you accidentally flattened something."
icon_state = "unrolling_pin"
force = 8
throwforce = 5
throw_speed = 3
throw_range = 7
w_class = WEIGHT_CLASS_NORMAL
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 1.5)
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked")
custom_price = PRICE_ALMOST_CHEAP
/obj/item/kitchen/unrollingpin/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins unflattening [user.p_their()] head with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return BRUTELOSS
/* Trays moved to /obj/item/storage/bag */
/obj/item/kitchen/knife/scimitar
+2 -2
View File
@@ -135,8 +135,8 @@
/obj/item/organ/cyberimp/arm/toolset,
/obj/item/organ/cyberimp/arm/surgery,
/obj/item/organ/cyberimp/chest/thrusters,
/obj/item/organ/lungs/cybernetic,
/obj/item/organ/liver/cybernetic) //cyberimplants range from a nice bonus to fucking broken bullshit so no subtypesof
/obj/item/organ/lungs/cybernetic/tier3,
/obj/item/organ/liver/cybernetic/tier3) //cyberimplants range from a nice bonus to fucking broken bullshit so no subtypesof
for(var/V in templist)
var/atom/A = V
augment_list[initial(A.name)] = A
+1 -1
View File
@@ -383,7 +383,7 @@
. = ..()
/obj/item/stack/medical/mesh/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!is_open & user.get_inactive_held_item() == src)
if(!is_open && (user.get_inactive_held_item() == src))
to_chat(user, "<span class='warning'>You need to open [src] first.</span>")
return
. = ..()
@@ -248,6 +248,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
null, \
new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 20), \
new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 30), \
new/datum/stack_recipe("unrolling pin", /obj/item/kitchen/unrollingpin, 2, time = 30), \
new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wood, 2, time = 30), \
new/datum/stack_recipe("painting frame", /obj/item/wallframe/painting, 1, time = 10),\
new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \
+4 -1
View File
@@ -367,7 +367,7 @@
/obj/item/storage/fancy/cigarettes/derringer/AltClick(mob/living/carbon/user)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
var/obj/item/W = (locate(/obj/item/ammo_casing/a357) in contents) || (locate(/obj/item/clothing/mask/cigarette) in contents) || locate(/obj/item/ammo_casing/g4570) //Easy access smokes and bullets
var/obj/item/W = (locate(/obj/item/ammo_casing/a357) in contents) || (locate(/obj/item/clothing/mask/cigarette) in contents) ||(locate(/obj/item/gun/ballistic/derringer) in contents) || (locate(/obj/item/ammo_casing/c38) in contents) || locate(/obj/item/ammo_casing/g4570) in contents//Easy access smokes and bullets
if(W && contents.len > 0)
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_TAKE, W, user)
user.put_in_hands(W)
@@ -382,6 +382,7 @@
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/clothing/mask/cigarette/syndicate(src)
//For traitors with luck/class
@@ -404,6 +405,7 @@
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/clothing/mask/cigarette/xeno(src)
//For Cargomen, looking for a good deal on arms, with no quarrels as to where they're from.
@@ -419,6 +421,7 @@
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/clothing/mask/cigarette/shadyjims (src)
/////////////
//CIGAR BOX//
+13
View File
@@ -71,6 +71,19 @@
if(3)
take_damage(rand(10, 90), BRUTE, "bomb", 0)
/obj/wave_ex_act(power, datum/wave_explosion/explosion, dir)
if(resistance_flags & INDESTRUCTIBLE)
return power
. = ..()
if(explosion.source == src)
obj_integrity = 0
qdel(src)
return
take_damage(wave_explosion_damage(power, explosion), BRUTE, "bomb", 0)
/obj/proc/wave_explosion_damage(power, datum/wave_explosion/explosion)
return (explosion_flags & EXPLOSION_FLAG_HARD_OBSTACLE)? EXPLOSION_POWER_STANDARD_SCALE_HARD_OBSTACLE_DAMAGE(power, explosion.hard_obstacle_mod) : EXPLOSION_POWER_STANDARD_SCALE_OBJECT_DAMAGE(power, explosion.object_damage_mod)
/obj/bullet_act(obj/item/projectile/P)
. = ..()
playsound(src, P.hitsound, 50, 1)
@@ -56,6 +56,11 @@
name = "gear crate"
icon_state = "secgearcrate"
/obj/structure/closet/crate/secure/soviet
desc = "A crate, purportedly from Space Russia."
name = "soviet crate"
icon_state = "sovietcrate"
/obj/structure/closet/crate/secure/hydroponics
desc = "A crate with a lock on it, painted in the scheme of the station's botanists."
name = "secure hydroponics crate"
+12
View File
@@ -73,3 +73,15 @@
name = "wumborian fugu den"
desc = "A den housing a nest of wumborian fugus, how do they all even fit in there?"
mob_types = list(/mob/living/simple_animal/hostile/asteroid/fugu)
/obj/structure/spawner/clown
name = "Laughing Larry"
desc = "A laughing, jovial figure. Something seems stuck in his throat."
icon_state = "clownbeacon"
icon = 'icons/obj/device.dmi'
max_integrity = 200
max_mobs = 15
spawn_time = 150
mob_types = list(/mob/living/simple_animal/hostile/retaliate/clown, /mob/living/simple_animal/hostile/retaliate/clown/fleshclown, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk, /mob/living/simple_animal/hostile/retaliate/clown/longface, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/chlown, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/honcmunculus, /mob/living/simple_animal/hostile/retaliate/clown/mutant/blob)
spawn_text = "climbs out of"
faction = list("clown")
+1 -1
View File
@@ -127,7 +127,7 @@
to_chat(user, "<span class='danger'>Throwing [pushed_mob] onto the table might hurt them!</span>")
return
var/added_passtable = FALSE
if(!pushed_mob.pass_flags & PASSTABLE)
if(!(pushed_mob.pass_flags & PASSTABLE))
added_passtable = TRUE
pushed_mob.pass_flags |= PASSTABLE
pushed_mob.Move(src.loc)
+15
View File
@@ -43,6 +43,10 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
attack_hand_speed = CLICK_CD_MELEE
attack_hand_is_action = TRUE
explosion_flags = EXPLOSION_FLAG_HARD_OBSTACLE
wave_explosion_block = EXPLOSION_BLOCK_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_WINDOW
/// Electrochromatic status
var/electrochromatic_status = NOT_ELECTROCHROMATIC
/// Electrochromatic ID. Set the first character to ! to replace with a SSmapping generated pseudorandom obfuscated ID for mapping purposes.
@@ -111,6 +115,9 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
return TRUE
return FALSE
/obj/structure/window/wave_explosion_damage(power, datum/wave_explosion/explosion)
return EXPLOSION_POWER_STANDARD_SCALE_WINDOW_DAMAGE(power, explosion.window_shatter_mod)
/obj/structure/window/narsie_act()
add_atom_colour(NARSIE_WINDOW_COLOUR, FIXED_COLOUR_PRIORITY)
@@ -520,6 +527,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 100)
max_integrity = 50
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_REINFORCED_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_REINFORCED_WINDOW
glass_type = /obj/item/stack/sheet/rglass
rad_insulation = RAD_HEAVY_INSULATION
ricochet_chance_mod = 0.8
@@ -545,6 +554,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
armor = list("melee" = 75, "bullet" = 5, "laser" = 0, "energy" = 0, "bomb" = 45, "bio" = 100, "rad" = 100, "fire" = 99, "acid" = 100)
max_integrity = 150
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_BOROSILICATE_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_BOROSILICATE_WINDOW
glass_type = /obj/item/stack/sheet/plasmaglass
cleanable_type = /obj/effect/decal/cleanable/glass/plasma
rad_insulation = RAD_NO_INSULATION
@@ -570,6 +581,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
armor = list("melee" = 85, "bullet" = 20, "laser" = 0, "energy" = 0, "bomb" = 60, "bio" = 100, "rad" = 100, "fire" = 99, "acid" = 100)
max_integrity = 500
explosion_block = 2
wave_explosion_block = EXPLOSION_BLOCK_EXTREME
wave_explosion_multiply = EXPLOSION_BLOCK_EXTREME
glass_type = /obj/item/stack/sheet/plasmarglass
/obj/structure/window/plasma/reinforced/spawner/east
@@ -742,6 +755,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
max_integrity = 80
armor = list("melee" = 60, "bullet" = 25, "laser" = 0, "energy" = 0, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 100)
explosion_block = 2 //fancy AND hard to destroy. the most useful combination.
wave_explosion_block = EXPLOSION_BLOCK_BOROSILICATE_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_BOROSILICATE_WINDOW
decon_speed = 40
glass_type = /obj/item/stack/tile/brass
glass_amount = 1
+3
View File
@@ -6,6 +6,8 @@
blocks_air = 1
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
rad_insulation = RAD_MEDIUM_INSULATION
wave_explosion_block = 10
wave_explosion_multiply = 0.75
/// How much we block yelling
var/yelling_resistance = 40
@@ -30,6 +32,7 @@
name = "wall"
icon = 'icons/turf/walls.dmi'
explosion_block = 50
wave_explosion_block = INFINITY
/turf/closed/indestructible/rust_heretic_act()
return
+55
View File
@@ -12,6 +12,19 @@
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
/// Minimum explosion power to break tile
var/explosion_power_break_tile = EXPLOSION_POWER_FLOOR_TILE_BREAK
/// Minimum explosion power to break turf
var/explosion_power_break_turf = EXPLOSION_POWER_FLOOR_TURF_BREAK
//// Minimum explosion power to scrape away the floor
var/explosion_power_turf_scrape = EXPLOSION_POWER_FLOOR_TURF_SCRAPE
//// Shielded turfs are completely protected from anything under this
var/explosion_power_protect_shielded = EXPLOSION_POWER_FLOOR_SHIELDED_IMMUNITY
/// Starting from here, there's a chance for this to break
var/explosion_power_minimum_chance_break = EXPLOSION_POWER_FLOOR_MINIMUM_TURF_BREAK
/// Starting from here, +20% chance to break turf.
var/explosion_power_break_turf_bonus = EXPLOSION_POWER_FLOOR_TURF_BREAK_BONUS
var/icon_regular_floor = "floor" //used to remember what icon the tile should have by default
var/icon_plating = "plating"
thermal_conductivity = 0.004
@@ -98,6 +111,48 @@
src.break_tile()
src.hotspot_expose(1000,CELL_VOLUME)
/turf/open/floor/wave_ex_act(power, datum/wave_explosion/explosion, dir)
var/shielded = is_shielded()
. = ..()
if(shielded)
if(power < explosion_power_protect_shielded)
return
else
power -= explosion_power_protect_shielded
hotspot_expose(1000, CELL_VOLUME)
if(power < explosion_power_break_tile)
return
if(power < explosion_power_minimum_chance_break)
if(prob(33 + ((explosion_power_break_turf - power) / (explosion_power_break_turf - explosion_power_break_tile))))
break_tile()
return
if((power < explosion_power_turf_scrape) && ((power >= explosion_power_break_turf) || prob((1 - ((explosion_power_break_turf - power) / (explosion_power_break_turf - explosion_power_minimum_chance_break))) * 100 + ((power > explosion_power_break_turf_bonus)? 20 : 0))))
switch(pick(1, 2;75, 3))
if(1)
if(!length(baseturfs) || !ispath(baseturfs[baseturfs.len-1], /turf/open/floor))
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
ReplaceWithLattice()
else
ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR)
if(prob(33))
new /obj/item/stack/sheet/metal(src)
return
if(2)
ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR)
return
if(3)
if(prob(80))
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
return
else
break_tile()
hotspot_expose(1000,CELL_VOLUME)
if(prob(33))
new /obj/item/stack/sheet/metal(src)
if(power >= explosion_power_turf_scrape)
ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR)
return
/turf/open/floor/is_shielded()
for(var/obj/structure/A in contents)
if(A.level == 3)
@@ -12,6 +12,11 @@
sheet_amount = 1
girder_type = /obj/structure/girder/reinforced
explosion_block = 2
wave_explosion_block = EXPLOSION_BLOCK_BLAST_PROOF
wave_explosion_multiply = EXPLOSION_DAMPEN_BLAST_PROOF
explosion_power_to_scrape = EXPLOSION_POWER_RWALL_SCRAPE
explosion_power_to_dismantle = EXPLOSION_POWER_RWALL_DISMANTLE
explosion_power_minimum_chance_dismantle = EXPLOSION_POWER_RWALL_MINIMUM_DISMANTLE
rad_insulation = RAD_HEAVY_INSULATION
/turf/closed/wall/r_wall/deconstruction_hints(mob/user)
+17
View File
@@ -6,6 +6,8 @@
icon = 'icons/turf/walls/wall.dmi'
icon_state = "wall"
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_WALL
wave_explosion_multiply = EXPLOSION_DAMPEN_WALL
flags_1 = DEFAULT_RICOCHET_1
flags_ricochet = RICOCHET_HARD
thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
@@ -15,6 +17,14 @@
baseturfs = /turf/open/floor/plating
explosion_flags = EXPLOSION_FLAG_HARD_OBSTACLE
/// Explosion power to disintegrate the wall
var/explosion_power_to_scrape = EXPLOSION_POWER_WALL_SCRAPE
/// Explosion power to dismantle the wall
var/explosion_power_to_dismantle = EXPLOSION_POWER_WALL_DISMANTLE
/// Explosion power to potentially dismantle the wall
var/explosion_power_minimum_chance_dismantle = EXPLOSION_POWER_WALL_MINIMUM_DISMANTLE
var/hardness = 40 //lower numbers are harder. Used to determine the probability of a hulk smashing through.
var/slicing_duration = 100 //default time taken to slice the wall
var/sheet_type = /obj/item/stack/sheet/metal
@@ -91,6 +101,13 @@
if(!density)
..()
/turf/closed/wall/wave_ex_act(power, datum/wave_explosion/explosion, dir)
. = ..()
var/resultant_power = power * explosion.wall_destroy_mod
if(resultant_power >= explosion_power_to_scrape)
ScrapeAway()
else if((resultant_power >= explosion_power_to_dismantle) || ((resultant_power >= explosion_power_minimum_chance_dismantle) && prob(((resultant_power - explosion_power_minimum_chance_dismantle) / (explosion_power_to_dismantle - explosion_power_minimum_chance_dismantle)) * 100)))
dismantle_wall(prob((resultant_power - explosion_power_to_dismantle)/(explosion_power_to_scrape - explosion_power_to_dismantle)), TRUE)
/turf/closed/wall/blob_act(obj/structure/blob/B)
if(prob(50))
+2
View File
@@ -8,6 +8,8 @@
temperature = TCMB
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
heat_capacity = 700000
wave_explosion_multiply = EXPLOSION_DAMPEN_SPACE
wave_explosion_block = EXPLOSION_BLOCK_SPACE
var/destination_z
var/destination_x
+18
View File
@@ -462,6 +462,24 @@ GLOBAL_LIST_EMPTY(station_turfs)
A.ex_act(severity, target)
CHECK_TICK
/turf/wave_ex_act(power, datum/wave_explosion/explosion, dir)
. = ..()
var/affecting_level
if(is_shielded())
affecting_level = 3
else if(intact)
affecting_level = 2
else
affecting_level = 1
var/atom/A
for(var/i in contents)
if(. <= 0)
return 0
A = i
if(!QDELETED(A) && A.level >= affecting_level)
. = A.wave_explode(., explosion, dir)
maptext = "[.]"
/turf/narsie_act(force, ignore_mobs, probability = 20)
. = (prob(probability) || force)
for(var/I in src)