Merge remote-tracking branch 'upstream/master'

This commit is contained in:
DeltaFire
2021-08-29 19:32:17 +02:00
67 changed files with 3034 additions and 1008 deletions
@@ -129,13 +129,12 @@
/mob/living/simple_animal/slaughter/proc/release_victims()
if(!consumed_mobs)
return
var/turf/T = get_turf(src)
if(!T)
T = find_safe_turf()
for(var/mob/living/M in consumed_mobs)
if(!M)
continue
var/turf/T = find_safe_turf()
if(!T)
T = get_turf(src)
M.forceMove(T)
/mob/living/simple_animal/slaughter/proc/refresh_consumed_buff()
@@ -263,12 +262,12 @@
if(!consumed_mobs)
return
var/turf/T = get_turf(src)
if(!T)
T = find_safe_turf()
for(var/mob/living/M in consumed_mobs)
if(!M)
continue
var/turf/T = find_safe_turf()
if(!T)
T = get_turf(src)
continue
M.forceMove(T)
if(M.revive(full_heal = TRUE, admin_revive = TRUE))
M.grab_ghost(force = TRUE)
@@ -157,6 +157,8 @@
id = GAS_METHANE
specific_heat = 30
name = "Methane"
powerloss_inhibition = 1
heat_resistance = 3
breath_results = GAS_METHYL_BROMIDE
fire_products = list(GAS_CO2 = 1, GAS_H2O = 2)
fire_burn_rate = 0.5
@@ -177,6 +179,8 @@
id = GAS_METHYL_BROMIDE
specific_heat = 42
name = "Methyl Bromide"
powermix = 1
heat_penalty = -1
flags = GAS_FLAG_DANGEROUS
breath_alert_info = list(
not_enough_alert = list(
@@ -32,6 +32,11 @@
if(!blocks_air)
air = new(2500,src)
air.copy_from_turf(src)
if(planetary_atmos && !(initial_gas_mix in SSair.planetary))
var/datum/gas_mixture/mix = new
mix.parse_gas_string(initial_gas_mix)
mix.mark_immutable()
SSair.planetary[initial_gas_mix] = mix
update_air_ref(planetary_atmos ? 1 : 2)
. = ..()
@@ -261,6 +261,8 @@ we use a hook instead
return 1
/datum/gas_mixture/parse_gas_string(gas_string)
gas_string = SSair.preprocess_gas_string(gas_string)
var/list/gas = params2list(gas_string)
if(gas["TEMP"])
var/temp = text2num(gas["TEMP"])
@@ -648,7 +648,7 @@
//Replace miasma with oxygen
var/cleaned_air = min(air.get_moles(GAS_MIASMA), 20 + (air.return_temperature() - FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 70) / 20)
air.adjust_moles(GAS_MIASMA, -cleaned_air)
air.adjust_moles(GAS_O2, cleaned_air)
air.adjust_moles(GAS_METHANE, cleaned_air)
//Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable
air.set_temperature(air.return_temperature() + cleaned_air * 0.002)
+9 -15
View File
@@ -172,15 +172,13 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
/// bumper object, the thing that starts actual teleport
var/obj/effect/gateway_portal_bumper/portal
/// Visual object for handling the viscontents
/// DISABLED DUE TO BYOND BUG CAUSING STACK OVERFLOWS OF ANY HUMAN INSTANTIATION NEAR AN ACTIVATED GATEWAY.
/// Probably due to it referencing each other through the gateway (there's a deep loop, maybe BYOND isn't catching something when it usually would)
// var/obj/effect/gateway_portal_effect/portal_visuals
var/obj/effect/gateway_portal_effect/portal_visuals
/obj/machinery/gateway/Initialize()
generate_destination()
update_icon()
// portal_visuals = new
// vis_contents += portal_visuals
portal_visuals = new
vis_contents += portal_visuals
return ..()
/obj/machinery/gateway/proc/generate_destination()
@@ -197,7 +195,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
if(use_power == ACTIVE_POWER_USE)
use_power = IDLE_POWER_USE
update_icon()
// portal_visuals.reset_visuals()
portal_visuals.reset_visuals()
/obj/machinery/gateway/process()
if((stat & (NOPOWER)) && use_power)
@@ -205,12 +203,6 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
deactivate()
return
/obj/machinery/gateway/update_icon_state()
if(target)
icon_state = "on_old"
else
icon_state = "portal_frame"
/obj/machinery/gateway/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE)
return
@@ -223,7 +215,7 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
return
target = D
target.activate(destination)
// portal_visuals.setup_visuals(target)
portal_visuals.setup_visuals(target)
generate_bumper()
use_power = ACTIVE_POWER_USE
update_icon()
@@ -365,6 +357,8 @@ GLOBAL_LIST_EMPTY(gateway_destinations)
animate(get_filter("portal_ripple"), time = 1.3 SECONDS, loop = -1, easing = LINEAR_EASING, radius = 32)
var/turf/center_turf = our_destination.get_target_turf()
/// DISABLED DUE TO BYOND BUG CAUSING STACK OVERFLOWS OF ANY HUMAN INSTANTIATION NEAR AN ACTIVATED GATEWAY.
/// Probably due to it referencing each other through the gateway (there's a deep loop, maybe BYOND isn't catching something when it usually would)
//var/turf/center_turf = our_destination.get_target_turf()
vis_contents += block(locate(center_turf.x - 1, center_turf.y - 1, center_turf.z), locate(center_turf.x + 1, center_turf.y + 1, center_turf.z))
//vis_contents += block(locate(center_turf.x - 1, center_turf.y - 1, center_turf.z), locate(center_turf.x + 1, center_turf.y + 1, center_turf.z))
+10
View File
@@ -60,6 +60,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
//autocorrected this round, not that you'd need to check that.
var/UI_style = null
var/outline_enabled = TRUE
var/outline_color = COLOR_BLUE_GRAY
var/buttons_locked = FALSE
var/hotkeys = FALSE
@@ -774,6 +776,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>General Settings</h2>"
dat += "<b>UI Style:</b> <a href='?_src_=prefs;task=input;preference=ui'>[UI_style]</a><br>"
dat += "<b>Outline:</b> <a href='?_src_=prefs;preference=outline_enabled'>[outline_enabled ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Outline Color:</b> <span style='border:1px solid #161616; background-color: [outline_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=outline_color'>Change</a><BR>"
dat += "<b>tgui Monitors:</b> <a href='?_src_=prefs;preference=tgui_lock'>[(tgui_lock) ? "Primary" : "All"]</a><br>"
dat += "<b>tgui Style:</b> <a href='?_src_=prefs;preference=tgui_fancy'>[(tgui_fancy) ? "Fancy" : "No Frills"]</a><br>"
dat += "<b>Show Runechat Chat Bubbles:</b> <a href='?_src_=prefs;preference=chat_on_map'>[chat_on_map ? "Enabled" : "Disabled"]</a><br>"
@@ -2706,6 +2710,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
buttons_locked = !buttons_locked
if("tgui_fancy")
tgui_fancy = !tgui_fancy
if("outline_enabled")
outline_enabled = !outline_enabled
if("outline_color")
var/pickedOutlineColor = input(user, "Choose your outline color.", "General Preference", outline_color) as color|null
if(pickedOutlineColor)
outline_color = pickedOutlineColor
if("tgui_lock")
tgui_lock = !tgui_lock
if("winflash")
@@ -45,6 +45,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(current_version < 46) //If you remove this, remove force_reset_keybindings() too.
force_reset_keybindings_direct(TRUE)
addtimer(CALLBACK(src, .proc/force_reset_keybindings), 30) //No mob available when this is run, timer allows user choice.
if(current_version < 30)
outline_enabled = TRUE
outline_color = COLOR_BLUE_GRAY
/datum/preferences/proc/update_character(current_version, savefile/S)
if(current_version < 19)
@@ -377,6 +380,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ooccolor"] >> ooccolor
S["lastchangelog"] >> lastchangelog
S["UI_style"] >> UI_style
S["outline_color"] >> outline_color
S["outline_enabled"] >> outline_enabled
S["hotkeys"] >> hotkeys
S["chat_on_map"] >> chat_on_map
S["max_chat_length"] >> max_chat_length
@@ -555,6 +560,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["ooccolor"], ooccolor)
WRITE_FILE(S["lastchangelog"], lastchangelog)
WRITE_FILE(S["UI_style"], UI_style)
WRITE_FILE(S["outline_enabled"], outline_enabled)
WRITE_FILE(S["outline_color"], outline_color)
WRITE_FILE(S["hotkeys"], hotkeys)
WRITE_FILE(S["chat_on_map"], chat_on_map)
WRITE_FILE(S["max_chat_length"], max_chat_length)
+18 -4
View File
@@ -27,13 +27,27 @@
if(prob(low_threat_perc))
severity = "low; the supermatter should return to normal operation shortly."
else
severity = "medium; the supermatter should return to normal operation, but check NT CIMS to ensure this."
severity = "medium; the supermatter should return to normal operation, but regardless, check if the emitters may need to be turned off temporarily."
else
severity = "high; if the supermatter's cooling is not fortified, coolant may need to be added."
severity = "high; the emitters likely need to be turned off, and if the supermatter's cooling loop is not fortified, pre-cooled gas may need to be added."
if(100000 to INFINITY)
severity = "extreme; emergency action is likely to be required even if coolant loop is fine."
severity = "extreme; emergency action is likely to be required even if coolant loop is fine. Turn off the emitters and make sure the loop is properly cooling gases."
if(power > 20000 || prob(round(power/200)))
priority_announce("Supermatter surge detected. Estimated severity is [severity]", "Anomaly Alert")
/datum/round_event/supermatter_surge/start()
GLOB.main_supermatter_engine.matter_power += power
var/obj/machinery/power/supermatter_crystal/supermatter = GLOB.main_supermatter_engine
var/power_proportion = supermatter.powerloss_inhibitor/2 // what % of the power goes into matter power, at most 50%
// we reduce the proportion that goes into actual matter power based on powerloss inhibitor
// primarily so the supermatter doesn't tesla the instant these happen
supermatter.matter_power += power * power_proportion
var/datum/gas_mixture/methane_puff = new
var/selected_gas = pick(4;GAS_CO2, 10;GAS_METHANE, 4;GAS_H2O, 1;GAS_BZ, 1;GAS_METHYL_BROMIDE)
methane_puff.set_moles(selected_gas, 500)
methane_puff.set_temperature(500)
var/energy_ratio = (power * 500 * (1-power_proportion)) / methane_puff.thermal_energy()
if(energy_ratio < 1) // energy output we want is lower than current energy, reduce the amount of gas we puff out
methane_puff.set_moles(GAS_METHANE, energy_ratio * 500)
else // energy output we want is higher than current energy, increase its actual heat
methane_puff.set_temperature(energy_ratio * 500)
supermatter.assume_air(methane_puff)
@@ -497,6 +497,72 @@
/obj/item/reagent_containers/food/drinks/bottle/grenadine/empty
list_reagents = null
/obj/item/reagent_containers/food/drinks/bottle/blank //Don't let players print these from a lathe, bottles should be obtained in mass from the bar only.
name = "glass bottle"
desc = "This blank bottle is unyieldingly anonymous, offering no clues to it's contents."
icon_state = "glassbottle"
volume = 90
spillable = TRUE
obj_flags = UNIQUE_RENAME
/obj/item/reagent_containers/food/drinks/bottle/blank/update_icon()
..()
add_overlay("[initial(icon_state)]shine")
/obj/item/reagent_containers/food/drinks/bottle/blank/Initialize()
. = ..()
update_icon()
/obj/item/reagent_containers/food/drinks/bottle/blank/get_part_rating()
return reagents.maximum_volume
/obj/item/reagent_containers/food/drinks/bottle/blank/on_reagent_change(changetype)
update_icon()
/obj/item/reagent_containers/food/drinks/bottle/blank/update_overlays()
. = ..()
if(!cached_icon)
cached_icon = icon_state
if(reagents.total_volume)
var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "[cached_icon]10", color = mix_color_from_reagents(reagents.reagent_list))
var/percent = round((reagents.total_volume / volume) * 100)
switch(percent)
if(0 to 9)
filling.icon_state = "[cached_icon]0"
if(10 to 19)
filling.icon_state = "[cached_icon]10"
if(20 to 29)
filling.icon_state = "[cached_icon]20"
if(30 to 39)
filling.icon_state = "[cached_icon]30"
if(40 to 49)
filling.icon_state = "[cached_icon]40"
if(50 to 59)
filling.icon_state = "[cached_icon]50"
if(60 to 69)
filling.icon_state = "[cached_icon]60"
if(70 to 79)
filling.icon_state = "[cached_icon]70"
if(80 to 89)
filling.icon_state = "[cached_icon]80"
if(90 to INFINITY)
filling.icon_state = "[cached_icon]90"
. += filling
/obj/item/reagent_containers/food/drinks/bottle/blank/small
name = "small glass bottle"
desc = "This small bottle is unyieldingly anonymous, offering no clues to it's contents."
icon_state = "glassbottlesmall"
volume = 60
/obj/item/reagent_containers/food/drinks/bottle/blank/pitcher
name = "glass pitcher"
desc = "This is a pitcher for large amounts of liquid of any kind."
icon_state = "unipitcher"
volume = 120
////////////////////////// MOLOTOV ///////////////////////
/obj/item/reagent_containers/food/drinks/bottle/molotov
name = "molotov cocktail"
@@ -436,13 +436,27 @@
/datum/sprite_accessory/tails/human/shark
name = "Shark"
icon_state = "shark"
icon_state = "carp"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/shark
name = "Shark"
icon_state = "carp"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/sharkalt
name = "Shark (alt)"
icon_state = "shark"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/sharkalt
name = "Shark (alt)"
icon_state = "shark"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
@@ -528,6 +542,20 @@
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/takahiro_kitsune
name = "Takahiro Kitsune Tails" //takahiro had five tails i just wanted to follow the 'T' naming convention vs. tamamo and triple
icon_state = "7sune"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails_animated/human/takahiro_kitsune
name = "Takahiro Kitsune Tails"
icon_state = "7sune"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED_GREEN
/datum/sprite_accessory/tails/human/tentacle
name = "Tentacle"
icon_state = "tentacle"
@@ -897,11 +925,21 @@
/datum/sprite_accessory/tails/mam_tails/shark
name = "Shark"
icon_state = "shark"
icon_state = "carp"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/shark
name = "Shark"
icon_state = "carp"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/sharkalt
name = "Shark (alt)"
icon_state = "shark"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/sharkalt
name = "Shark (alt)"
icon_state = "shark"
matrixed_sections = MATRIX_RED
@@ -98,6 +98,16 @@
qdel(bigcheese)
evolve()
return
for(var/obj/item/trash/garbage in range(1, src))
if(prob(2))
qdel(garbage)
evolve_plague()
return
for(var/obj/effect/decal/cleanable/blood/gibs/leftovers in range(1, src))
if(prob(2))
qdel(leftovers)
evolve_plague()
return
/**
*Checks the mouse cap, if it's above the cap, doesn't spawn a mouse. If below, spawns a mouse and adds it to cheeserats.
@@ -123,6 +133,13 @@
mind.transfer_to(regalrat)
qdel(src)
/mob/living/simple_animal/mouse/proc/evolve_plague()
var/mob/living/simple_animal/hostile/plaguerat = new /mob/living/simple_animal/hostile/plaguerat(loc)
visible_message("<span class='warning'>[src] devours the food! He rots into something worse!</span>")
if(mind)
mind.transfer_to(plaguerat)
qdel(src)
/*
* Mouse types
*/
@@ -169,3 +186,16 @@ GLOBAL_VAR(tom_existed)
/obj/item/reagent_containers/food/snacks/deadmouse/on_grind()
reagents.clear_reagents()
/mob/living/simple_animal/mouse/proc/miasma(datum/gas_mixture/environment, check_temp = FALSE)
if(isturf(src.loc) && isopenturf(src.loc))
var/turf/open/ST = src.loc
var/miasma_moles = ST.air.get_moles(GAS_MIASMA)
if(prob(5) && miasma_moles >= 5)
evolve_plague()
else if(miasma_moles >= 20)
evolve_plague()
return
/mob/living/simple_animal/mouse/handle_environment(datum/gas_mixture/environment)
. = ..()
miasma()
@@ -0,0 +1,253 @@
#define GREMLIN_VENT_CHANCE 1.75
//Gremlins
//Small monsters that don't attack humans or other animals. Instead they mess with electronics, computers and machinery
//List of objects that gremlins can't tamper with (because nobody coded an interaction for it)
//List starts out empty. Whenever a gremlin finds a machine that it couldn't tamper with, the machine's type is added here, and all machines of such type are ignored from then on (NOT SUBTYPES)
GLOBAL_LIST(bad_gremlin_items)
/mob/living/simple_animal/hostile/gremlin
name = "gremlin"
desc = "This tiny creature finds great joy in discovering and using technology. Nothing excites it more than pushing random buttons on a computer to see what it might do."
icon = 'icons/mob/mob.dmi'
icon_state = "gremlin"
icon_living = "gremlin"
icon_dead = "gremlin_dead"
var/in_vent = FALSE
health = 20
maxHealth = 20
search_objects = 3 //Completely ignore mobs
//Tampering is handled by the 'npc_tamper()' obj proc
wanted_objects = list(
/obj/machinery,
/obj/item/reagent_containers/food,
/obj/structure/sink
)
var/obj/machinery/atmospherics/components/unary/vent_pump/entry_vent
var/obj/machinery/atmospherics/components/unary/vent_pump/exit_vent
dextrous = TRUE
possible_a_intents = list(INTENT_HELP, INTENT_GRAB, INTENT_DISARM, INTENT_HARM)
faction = list("meme", "gremlin")
speed = 0.5
gold_core_spawnable = 2
unique_name = TRUE
//Ensure gremlins don't attack other mobs
melee_damage_upper = 0
melee_damage_lower = 0
attack_sound = null
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
//List of objects that we don't even want to try to tamper with
//Subtypes of these are calculated too
var/list/unwanted_objects = list(/obj/machinery/atmospherics/pipe, /turf, /obj/structure) //ensure gremlins dont try to fuck with walls / normal pipes / glass / etc
var/min_next_vent = 0
//Amount of ticks spent pathing to the target. If it gets above a certain amount, assume that the target is unreachable and stop
var/time_chasing_target = 0
//If you're going to make gremlins slower, increase this value - otherwise gremlins will abandon their targets too early
var/max_time_chasing_target = 2
var/next_eat = 0
//Last 20 heard messages are remembered by gremlins, and will be used to generate messages for comms console tampering, etc...
var/list/hear_memory = list()
var/const/max_hear_memory = 20
/mob/living/simple_animal/hostile/gremlin/Initialize()
. = ..()
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
access_card = new /obj/item/card/id(src)
var/datum/job/captain/C = new /datum/job/captain
access_card.access = C.get_access()
/mob/living/simple_animal/hostile/gremlin/AttackingTarget()
var/is_hungry = world.time >= next_eat || prob(25)
if(istype(target, /obj/item/reagent_containers/food) && is_hungry) //eat food if we're hungry or bored
visible_message("<span class='danger'>[src] hungrily devours [target]!</span>")
playsound(src, 'sound/items/eatfood.ogg', 50, 1)
qdel(target)
LoseTarget()
next_eat = world.time + rand(700, 3000) //anywhere from 70 seconds to 5 minutes until the gremlin is hungry again
return
if(istype(target, /obj))
var/obj/M = target
tamper(M)
if(prob(50)) //50% chance to move to the next machine
LoseTarget()
/mob/living/simple_animal/hostile/gremlin/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode)
. = ..()
if(message)
hear_memory.Insert(1, raw_message)
if(hear_memory.len > max_hear_memory)
hear_memory.Cut(hear_memory.len)
/mob/living/simple_animal/hostile/gremlin/proc/generate_markov_input()
var/result = ""
for(var/memory in hear_memory)
result += memory + " "
return result
/mob/living/simple_animal/hostile/gremlin/proc/generate_markov_chain()
return markov_chain(generate_markov_input(), rand(2,5), rand(100,700)) //The numbers are chosen arbitarily
/mob/living/simple_animal/hostile/gremlin/proc/tamper(obj/M)
switch(M.npc_tamper_act(src))
if(NPC_TAMPER_ACT_FORGET)
visible_message(pick(
"<span class='notice'>\The [src] plays around with \the [M], but finds it rather boring.</span>",
"<span class='notice'>\The [src] tries to think of some more ways to screw \the [M] up, but fails miserably.</span>",
"<span class='notice'>\The [src] decides to ignore \the [M], and starts looking for something more fun.</span>"))
LAZYADD(GLOB.bad_gremlin_items,M.type)
return FALSE
if(NPC_TAMPER_ACT_NOMSG)
//Don't create a visible message
return TRUE
else
visible_message(pick(
"<span class='danger'>\The [src]'s eyes light up as \he tampers with \the [M].</span>",
"<span class='danger'>\The [src] twists some knobs around on \the [M] and bursts into laughter!</span>",
"<span class='danger'>\The [src] presses a few buttons on \the [M] and giggles mischievously.</span>",
"<span class='danger'>\The [src] rubs its hands devilishly and starts messing with \the [M].</span>",
"<span class='danger'>\The [src] turns a small valve on \the [M].</span>"))
//Add a clue for detectives to find. The clue is only added if no such clue already existed on that machine
return TRUE
/mob/living/simple_animal/hostile/gremlin/CanAttack(atom/new_target)
if(LAZYFIND(GLOB.bad_gremlin_items,new_target.type))
return FALSE
if(is_type_in_list(new_target, unwanted_objects))
return FALSE
if(istype(new_target, /obj/machinery))
var/obj/machinery/M = new_target
if(M.stat) //Unpowered or broken
return FALSE
else if(istype(new_target, /obj/machinery/door/firedoor))
var/obj/machinery/door/firedoor/F = new_target
//Only tamper with firelocks that are closed, opening them!
if(!F.density)
return FALSE
return ..()
/mob/living/simple_animal/hostile/gremlin/death(gibbed)
walk(src,0)
return ..()
/mob/living/simple_animal/hostile/gremlin/Life()
. = ..()
if(!health || stat == DEAD)
return
//Don't try to path to one target for too long. If it takes longer than a certain amount of time, assume it can't be reached and find a new one
if(!client) //don't do this shit if there's a client, they're capable of ventcrawling manually
if(in_vent)
target = null
if(entry_vent && get_dist(src, entry_vent) <= 1)
var/list/vents = list()
var/datum/pipeline/entry_vent_parent = entry_vent.parents[1]
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in entry_vent_parent.other_atmosmch)
vents += temp_vent
if(!vents.len)
entry_vent = null
in_vent = FALSE
return
exit_vent = pick(vents)
visible_message("<span class='notice'>[src] crawls into the ventilation ducts!</span>")
loc = exit_vent
var/travel_time = round(get_dist(loc, exit_vent.loc) / 2)
addtimer(CALLBACK(src, .proc/exit_vents), travel_time) //come out at exit vent in 2 to 20 seconds
if(world.time > min_next_vent && !entry_vent && !in_vent && prob(GREMLIN_VENT_CHANCE)) //small chance to go into a vent
for(var/obj/machinery/atmospherics/components/unary/vent_pump/v in view(7,src))
if(!v.welded)
entry_vent = v
in_vent = TRUE
walk_to(src, entry_vent)
break
if(!target)
time_chasing_target = 0
else
if(++time_chasing_target > max_time_chasing_target)
LoseTarget()
time_chasing_target = 0
. = ..()
/mob/living/simple_animal/hostile/gremlin/EscapeConfinement()
if(istype(loc, /obj) && CanAttack(loc)) //If we're inside a machine, screw with it
var/obj/M = loc
tamper(M)
return ..()
/mob/living/simple_animal/hostile/gremlin/proc/exit_vents()
if(!exit_vent || exit_vent.welded)
loc = entry_vent
entry_vent = null
return
loc = exit_vent.loc
entry_vent = null
exit_vent = null
in_vent = FALSE
var/area/new_area = get_area(loc)
message_admins("[src] came out at [new_area][ADMIN_JMP(loc)]!")
if(new_area)
new_area.Entered(src)
visible_message("<span class='notice'>[src] climbs out of the ventilation ducts!</span>")
min_next_vent = world.time + 900 //90 seconds between ventcrawls
//This allows player-controlled gremlins to tamper with machinery
/mob/living/simple_animal/hostile/gremlin/UnarmedAttack(var/atom/A)
if(istype(A, /obj/machinery) || istype(A, /obj/structure))
tamper(A)
if(istype(target, /obj/item/reagent_containers/food)) //eat food
visible_message("<span class='danger'>[src] hungrily devours [target]!</span>", "<span class='danger'>You hungrily devour [target]!</span>")
playsound(src, 'sound/items/eatfood.ogg', 50, 1)
qdel(target)
LoseTarget()
next_eat = world.time + rand(700, 3000) //anywhere from 70 seconds to 5 minutes until the gremlin is hungry again
return ..()
/mob/living/simple_animal/hostile/gremlin/IsAdvancedToolUser()
return 1
/mob/living/simple_animal/hostile/gremlin/proc/divide()
//Health is halved and then reduced by 2. A new gremlin is spawned with the same health as the parent
//Need to have at least 6 health for this, otherwise resulting health would be less than 1
if(health < 7.5)
return
visible_message("<span class='notice'>\The [src] splits into two!</span>")
var/mob/living/simple_animal/hostile/gremlin/G = new /mob/living/simple_animal/hostile/gremlin(get_turf(src))
if(mind)
mind.transfer_to(G)
health = round(health * 0.5) - 2
maxHealth = health
resize *= 0.9
G.health = health
G.maxHealth = maxHealth
/mob/living/simple_animal/hostile/gremlin/traitor
health = 85
maxHealth = 85
gold_core_spawnable = 0
@@ -0,0 +1,214 @@
/obj/proc/npc_tamper_act(mob/living/L)
return NPC_TAMPER_ACT_FORGET
/obj/machinery/atmospherics/components/binary/passive_gate/npc_tamper_act(mob/living/L)
if(prob(50)) //Turn on/off
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(L)]", INVESTIGATE_ATMOS)
else //Change pressure
target_pressure = rand(0, MAX_OUTPUT_PRESSURE)
investigate_log("was set to [target_pressure] kPa by [key_name(L)]", INVESTIGATE_ATMOS)
update_icon()
/obj/machinery/atmospherics/components/binary/pump/npc_tamper_act(mob/living/L)
if(prob(50)) //Turn on/off
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(L)]", INVESTIGATE_ATMOS)
else //Change pressure
target_pressure = rand(0, MAX_OUTPUT_PRESSURE)
investigate_log("was set to [target_pressure] kPa by [key_name(L)]", INVESTIGATE_ATMOS)
update_icon()
/obj/machinery/atmospherics/components/binary/volume_pump/npc_tamper_act(mob/living/L)
if(prob(50)) //Turn on/off
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(L)]", INVESTIGATE_ATMOS)
else //Change pressure
transfer_rate = rand(0, MAX_TRANSFER_RATE)
investigate_log("was set to [transfer_rate] L/s by [key_name(L)]", INVESTIGATE_ATMOS)
update_icon()
/obj/machinery/atmospherics/components/binary/valve/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/space_heater/npc_tamper_act(mob/living/L)
var/list/choose_modes = list("standby", "heat", "cool")
if(prob(50))
choose_modes -= mode
mode = pick(choose_modes)
else
on = !on
update_icon()
/obj/machinery/shield_gen/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/firealarm/npc_tamper_act(mob/living/L)
alarm()
/obj/machinery/airalarm/npc_tamper_act(mob/living/L)
if(panel_open)
wires.npc_tamper(L)
else
panel_open = !panel_open
/obj/machinery/ignition_switch/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/flasher_button/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/crema_switch/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/camera/npc_tamper_act(mob/living/L)
if(!panel_open)
panel_open = !panel_open
if(wires)
wires.npc_tamper(L)
/obj/machinery/atmospherics/components/unary/cryo_cell/npc_tamper_act(mob/living/L)
if(prob(50))
if(beaker)
beaker.forceMove(loc)
beaker = null
else
if(occupant)
if(state_open)
if (close_machine() == usr)
on = TRUE
else
open_machine()
/obj/machinery/door_control/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/door/airlock/npc_tamper_act(mob/living/L)
//Open the firelocks as well, otherwise they block the way for our gremlin which isn't fun
for(var/obj/machinery/door/firedoor/F in get_turf(src))
if(F.density)
F.npc_tamper_act(L)
if(prob(40)) //40% - mess with wires
if(!panel_open)
panel_open = !panel_open
if(wires)
wires.npc_tamper(L)
else //60% - just open it
open()
/obj/machinery/gibber/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/light_switch/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/turretid/npc_tamper_act(mob/living/L)
enabled = rand(0, 1)
lethal = rand(0, 1)
updateTurrets()
/obj/machinery/vending/npc_tamper_act(mob/living/L)
if(!panel_open)
panel_open = !panel_open
if(wires)
wires.npc_tamper(L)
/obj/machinery/shower/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/deepfryer/npc_tamper_act(mob/living/L)
//Deepfry a random nearby item
var/list/pickable_items = list()
for(var/obj/item/I in range(1, L))
pickable_items.Add(I)
if(!pickable_items.len)
return
var/obj/item/I = pick(pickable_items)
attackby(I, L) //shove the item in, even if it can't be deepfried normally
/obj/machinery/power/apc/npc_tamper_act(mob/living/L)
if(!panel_open)
panel_open = !panel_open
if(wires)
wires.npc_tamper(L)
/obj/machinery/power/rad_collector/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/power/emitter/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/particle_accelerator/control_box/npc_tamper_act(mob/living/L)
if(!panel_open)
panel_open = !panel_open
if(wires)
wires.npc_tamper(L)
/obj/machinery/computer/communications/npc_tamper_act(mob/living/user)
if(!authenticated)
if(prob(20)) //20% chance to log in
authenticated = TRUE
else //Already logged in
if(prob(50)) //50% chance to log off
authenticated = FALSE
else if(istype(user, /mob/living/simple_animal/hostile/gremlin)) //make a hilarious public message
var/mob/living/simple_animal/hostile/gremlin/G = user
var/result = G.generate_markov_chain()
if(result)
if(prob(85))
SScommunications.make_announcement(G, FALSE, result)
var/turf/T = get_turf(G)
log_say("[key_name(usr)] ([ADMIN_JMP(T)]) has made a captain announcement: [result]")
message_admins("[key_name_admin(G)] has made a captain announcement.", 1)
else
if(SSshuttle.emergency.mode == SHUTTLE_IDLE)
SSshuttle.requestEvac(G, result)
else if(SSshuttle.emergency.mode == SHUTTLE_ESCAPE)
SSshuttle.cancelEvac(G)
/obj/machinery/button/door/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/sleeper/npc_tamper_act(mob/living/L)
if(prob(75))
inject_chem(pick(available_chems))
else
if(state_open)
close_machine()
else
open_machine()
/obj/machinery/power/smes/npc_tamper_act(mob/living/L)
if(prob(50)) //mess with input
input_level = rand(0, input_level_max)
else //mess with output
output_level = rand(0, output_level_max)
/obj/machinery/syndicatebomb/npc_tamper_act(mob/living/L) //suicide bomber gremlins
if(!open_panel)
open_panel = !open_panel
if(wires)
wires.npc_tamper(L)
/obj/machinery/computer/bank_machine/npc_tamper_act(mob/living/L)
siphoning = !siphoning
/obj/machinery/computer/slot_machine/npc_tamper_act(mob/living/L)
spin(L)
/obj/structure/sink/npc_tamper_act(mob/living/L)
if(istype(L, /mob/living/simple_animal/hostile/gremlin))
visible_message("<span class='danger'>\The [L] climbs into \the [src] and turns the faucet on!</span>")
var/mob/living/simple_animal/hostile/gremlin/G = L
G.divide()
return NPC_TAMPER_ACT_NOMSG
@@ -0,0 +1,44 @@
/datum/round_event_control/gremlin
name = "Spawn Gremlins"
typepath = /datum/round_event/gremlin
weight = 15
max_occurrences = 2
earliest_start = 20 MINUTES
min_players = 5
/datum/round_event/gremlin
var/static/list/acceptable_spawns = list("xeno_spawn", "generic event spawn", "blobstart", "Assistant")
/datum/round_event/gremlin/announce()
priority_announce("Bioscans indicate that some gremlins entered through the vents. Deal with them!", "Gremlin Alert", 'sound/announcer/classic/attention.ogg')
/datum/round_event/gremlin/start()
var/list/spawn_locs = list()
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
if(isturf(L.loc) && !isspaceturf(L.loc))
if(L.name in acceptable_spawns)
spawn_locs += L.loc
if(!spawn_locs.len) //If we can't find any gremlin spawns, try the xeno spawns
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
if(isturf(L.loc))
switch(L.name)
if("Assistant")
spawn_locs += L.loc
if(!spawn_locs.len) //If we can't find THAT, then just give up and cry
return MAP_ERROR
var/gremlins_to_spawn = rand(2,5)
var/list/gremlin_areas = list()
for(var/i = 0, i <= gremlins_to_spawn, i++)
var/spawnat = pick(spawn_locs)
spawn_locs -= spawnat
gremlin_areas += get_area(spawnat)
new /mob/living/simple_animal/hostile/gremlin(spawnat)
var/grems = gremlin_areas.Join(", ")
message_admins("Gremlins have been spawned at the areas: [grems]")
log_game("Gremlins have been spawned at the areas: [grems]")
return SUCCESSFUL_SPAWN
@@ -0,0 +1,131 @@
/mob/living/simple_animal/hostile/plaguerat
name = "plague rat"
desc = "A large decaying rat. It spreads its filth and emits a putrid odor to create more of its kind."
icon_state = "plaguerat"
icon_living = "plaguerat"
icon_dead = "plaguerat_dead"
speak = list("Skree!","SKREEE!","Squeak?")
speak_emote = list("squeaks")
emote_hear = list("Hisses.")
emote_see = list("runs in a circle.", "stands on its hind legs.")
gender = NEUTER
speak_chance = 1
turns_per_move = 5
maxHealth = 15
health = 15
see_in_dark = 6
obj_damage = 10
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1)
response_help_continuous = "glares at"
response_help_simple = "glare at"
response_disarm_continuous = "skoffs at"
response_disarm_simple = "skoff at"
response_harm_continuous = "slashes"
response_harm_simple = "slash"
melee_damage_lower = 5
melee_damage_upper = 7
attack_verb_continuous = "slashes"
attack_verb_simple = "slash"
attack_sound = 'sound/weapons/punch1.ogg'
faction = list("rat")
density = FALSE
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
mob_biotypes = MOB_ORGANIC|MOB_BEAST
var/datum/action/cooldown/scavenge
var/last_spawn_time = 0
///Number assigned to rats and mice, checked when determining infighting.
/mob/living/simple_animal/hostile/plaguerat/Initialize()
. = ..()
SSmobs.cheeserats += src
AddComponent(/datum/component/swarming)
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
scavenge = new /datum/action/cooldown/scavenge
scavenge.Grant(src)
/mob/living/simple_animal/hostile/plaguerat/Destroy()
SSmobs.cheeserats -= src
return ..()
/mob/living/simple_animal/hostile/plaguerat/BiologicalLife(seconds, times_fired)
if(!(. = ..()))
return
if(isopenturf(loc))
var/turf/open/T = src.loc
if(T.air)
T.atmos_spawn_air("miasma=5;TEMP=293.15")
if(prob(40))
scavenge.Trigger()
if(prob(50))
var/turf/open/floor/F = get_turf(src)
if(istype(F) && !F.intact)
var/obj/structure/cable/C = locate() in F
if(C && C.avail())
visible_message("<span class='warning'>[src] chews through the [C]. It looks unharmed!</span>")
playsound(src, 'sound/effects/sparks2.ogg', 100, TRUE)
C.deconstruct()
for(var/obj/O in range(1,src))
if(istype(O, /obj/item/trash) || istype(O, /obj/effect/decal/cleanable/blood/gibs))
qdel(O)
be_fruitful()
/mob/living/simple_animal/hostile/plaguerat/CanAttack(atom/the_target)
if(istype(the_target,/mob/living/simple_animal))
var/mob/living/A = the_target
if(istype(the_target, /mob/living/simple_animal/hostile/plaguerat) && A.stat == CONSCIOUS)
var/mob/living/simple_animal/hostile/plaguerat/R = the_target
if(R.faction_check_mob(src, TRUE))
return FALSE
else
return TRUE
return ..()
/**
*Checks the mouse cap, if it's above the cap, doesn't spawn a mouse. If below, spawns a mouse and adds it to cheeserats.
*/
/mob/living/simple_animal/hostile/plaguerat/proc/be_fruitful()
var/cap = CONFIG_GET(number/ratcap)
if(LAZYLEN(SSmobs.cheeserats) >= cap)
visible_message("<span class='warning'>[src] gnaws into its food, [cap] rats are now on the station!</span>")
return
var/mob/living/newmouse = new /mob/living/simple_animal/hostile/plaguerat(loc)
SSmobs.cheeserats += newmouse
visible_message("<span class='notice'>[src] gnaws into its food, attracting another rat!</span>")
/**
*Creates a chance to spawn more trash or gibs to repopulate. Otherwise, spawns a corpse or dirt.
*/
/datum/action/cooldown/scavenge
name = "Scavenge"
desc = "Spread the plague, scavenge for trash and fresh meat to reproduce."
icon_icon = 'icons/mob/actions/actions_animal.dmi'
background_icon_state = "bg_clock"
button_icon_state = "coffer"
cooldown_time = 50
/datum/action/cooldown/scavenge/Trigger()
. = ..()
if(!.)
return
var/turf/T = get_turf(owner)
var/loot = rand(1,100)
switch(loot)
if(1 to 3)
var/pickedtrash = pick(GLOB.ratking_trash)
to_chat(owner, "<span class='notice'>Excellent, you find more trash to spread your filth!</span>")
new /obj/effect/decal/cleanable/dirt(T)
new pickedtrash(T)
if(4 to 6)
to_chat(owner, "<span class='notice'>You find blood and gibs to feed your young!</span>")
new /obj/effect/decal/cleanable/blood/gibs(T)
new /obj/effect/decal/cleanable/blood/(T)
if(7 to 18)
to_chat(owner, "<span class='notice'>A corpse rises from the ground. Best to leave it alone.</span>")
new /obj/effect/mob_spawn/human/corpse/assistant(T)
if(19 to 100)
to_chat(owner, "<span class='notice'>Drat. Nothing.</span>")
new /obj/effect/decal/cleanable/dirt(T)
StartCooldown()
@@ -109,7 +109,7 @@
continue
playsound(src, 'sound/effects/splat.ogg', 50, TRUE)
visible_message("<span class='danger'>[src] vomits up [consumed_mob]!</span>")
consumed_mob.forceMove(loc)
consumed_mob.forceMove(get_turf(src))
consumed_mob.Paralyze(50)
if((rifts_charged == 3 || (SSshuttle.emergency.mode == SHUTTLE_DOCKED && rifts_charged > 0)) && !objective_complete)
victory()
@@ -123,6 +123,7 @@
to_chat(src, "<span class='boldwarning'>You've failed to summon the rift in a timely manner! You're being pulled back from whence you came!</span>")
destroy_rifts()
playsound(src, 'sound/magic/demon_dies.ogg', 100, TRUE)
empty_contents()
QDEL_NULL(src)
/mob/living/simple_animal/hostile/space_dragon/AttackingTarget()
@@ -351,7 +352,7 @@
*/
/mob/living/simple_animal/hostile/space_dragon/proc/empty_contents()
for(var/atom/movable/AM in src)
AM.forceMove(loc)
AM.forceMove(get_turf(src))
if(prob(90))
step(AM, pick(GLOB.alldirs))
@@ -529,7 +530,7 @@
/obj/structure/carp_rift
name = "carp rift"
desc = "A rift akin to the ones space carp use to travel long distances."
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 100, BOMB = 50, BIO = 100, RAD = 100, FIRE = 100, ACID = 100)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
max_integrity = 300
icon = 'icons/obj/carp_rift.dmi'
icon_state = "carp_rift_carpspawn"
@@ -636,7 +637,7 @@
icon_state = "carp_rift_charged"
light_color = LIGHT_COLOR_YELLOW
update_light()
armor = list(MELEE = 100, BULLET = 100, LASER = 100, ENERGY = 100, BOMB = 100, BIO = 100, RAD = 100, FIRE = 100, ACID = 100)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
resistance_flags = INDESTRUCTIBLE
dragon.rifts_charged += 1
if(dragon.rifts_charged != 3 && !dragon.objective_complete)
+1
View File
@@ -238,6 +238,7 @@
if(istype(W))
if(equip_to_slot_if_possible(W, slot, FALSE, FALSE, FALSE, FALSE, TRUE))
W.apply_outline()
return TRUE
if(!W)
+12 -6
View File
@@ -39,7 +39,8 @@
#define DAMAGE_INCREASE_MULTIPLIER 0.25
#define THERMAL_RELEASE_MODIFIER 5 //Higher == less heat released during reaction, not to be confused with the above values
#define THERMAL_RELEASE_MODIFIER 350 //Higher == more heat released during reaction, not to be confused with the above values
#define THERMAL_RELEASE_CAP_MODIFIER 250 //Higher == lower cap on how much heat can be released per tick--currently 1.3x old value
#define PLASMA_RELEASE_MODIFIER 750 //Higher == less plasma released by reaction
#define OXYGEN_RELEASE_MODIFIER 325 //Higher == less oxygen released at high temperature/power
@@ -500,7 +501,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling + clamp(powerloss_inhibition_gas - powerloss_dynamic_scaling, -0.02, 0.02), 0, 1)
else
powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling - 0.05, 0, 1)
//Ranges from 0 to 1(1-(value between 0 and 1 * ranges from 1 to 1.5(mol / 500)))
//Ranges from 0 to 1 (1-(value between 0 and 1 * ranges from 1 to 1.5(mol / 500)))
//0 means full inhibition, 1 means no inhibition
//We take the mol count, and scale it to be our inhibitor
powerloss_inhibitor = clamp(1-(powerloss_dynamic_scaling * clamp(combined_gas/POWERLOSS_INHIBITION_MOLE_BOOST_THRESHOLD, 1, 1.5)), 0, 1)
@@ -536,15 +538,19 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
//Power * 0.55 * a value between 1 and 0.8
var/device_energy = power * REACTION_POWER_MODIFIER
removed.set_temperature(removed.return_temperature() + ((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER))
//We don't want our output to be too hot
removed.set_temperature(max(0, min(removed.return_temperature(), 2500 * dynamic_heat_modifier)))
var/effective_temperature = min(removed.return_temperature(), 2500 * dynamic_heat_modifier)
var/max_temp_increase = effective_temperature + ((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_CAP_MODIFIER)
//Calculate how much gas to release
//Varies based on power and gas content
removed.adjust_moles(GAS_PLASMA, max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0))
//Varies based on power, gas content, and heat
removed.adjust_moles(GAS_O2, max(((device_energy + removed.return_temperature() * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0))
removed.adjust_moles(GAS_O2, max(((device_energy + effective_temperature * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0))
if(removed.return_temperature() < max_temp_increase)
removed.adjust_heat(device_energy * dynamic_heat_modifier * THERMAL_RELEASE_MODIFIER)
removed.set_temperature(min(removed.return_temperature(), max_temp_increase))
if(produces_gas)
env.merge(removed)
@@ -245,6 +245,36 @@
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
/datum/design/emptybottle
name = "Glass Bottle"
desc = "A small, empty bottle for storing liquids."
id = "emptyglassbottle"
build_type = PROTOLATHE
materials = list(/datum/material/glass = 400)
build_path = /obj/item/reagent_containers/food/drinks/bottle/blank/small
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
/datum/design/largeemptybottle
name = "Large Glass Bottle"
desc = "A large, empty bottle for storing liquids."
id = "largeemptyglassbottle"
build_type = PROTOLATHE
materials = list(/datum/material/glass = 2000)
build_path = /obj/item/reagent_containers/food/drinks/bottle/blank
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
/datum/design/emptypitcher
name = "Pitcher"
desc = "A large Pitcher to hold vast amounts of liquid."
id = "emptypitcher"
build_type = PROTOLATHE
materials = list(/datum/material/glass = 3600)
build_path = /obj/item/reagent_containers/food/drinks/bottle/blank/pitcher
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
/datum/design/air_horn
name = "Air Horn"
desc = "Damn son, where'd you find this?"
@@ -14,8 +14,8 @@
/datum/techweb_node/bottle_exports
id = "bottle_exports"
display_name = "Legal Bottling"
display_name = "Advanced Bottling"
prereq_ids = list("blueprinted_bottles")
description = "New bottles for printing and selling."
design_ids = list("minikeg", "blooddrop", "slim_gold", "white_bloodmoon", "greenroad")
description = "New bottles for printing, storage and selling."
design_ids = list("minikeg", "blooddrop", "slim_gold", "white_bloodmoon", "greenroad", "emptyglassbottle", "largeemptyglassbottle", "emptypitcher")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 250)
+27 -5
View File
@@ -54,7 +54,8 @@
var/SA_para_min = 1 //nitrous values
var/SA_sleep_min = 5
var/BZ_trip_balls_min = 1 //BZ gas
var/BZ_trip_balls_min = 0.1 //BZ gas
var/BZ_brain_damage_min = 1
var/gas_stimulation_min = 0.002 //Nitryl and Stimulum
var/cold_message = "your face freezing and an icicle forming"
@@ -269,13 +270,13 @@
// BZ
var/bz_pp = PP(breath, GAS_BZ)
if(bz_pp > BZ_trip_balls_min)
if(bz_pp > BZ_brain_damage_min)
H.hallucination += 10
H.reagents.add_reagent(/datum/reagent/bz_metabolites,5)
if(prob(33))
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 150)
else if(bz_pp > 0.01)
else if(bz_pp > BZ_trip_balls_min)
H.hallucination += 5
H.reagents.add_reagent(/datum/reagent/bz_metabolites,1)
@@ -476,7 +477,7 @@
)
SA_para_min = 30
SA_sleep_min = 50
BZ_trip_balls_min = 30
BZ_brain_damage_min = 30
emp_vulnerability = 3
cold_level_1_threshold = 200
@@ -509,8 +510,29 @@
heat_level_2_threshold = 600 // up 200 from level 1, 1000 is silly but w/e for level 3
/obj/item/organ/lungs/ashwalker/populate_gas_info()
// humans usually breathe 21 but require 16/17, so 80% - 1, which is more lenient but it's fine
#define SAFE_THRESHOLD_RATIO 0.8
var/datum/gas_mixture/breath = SSair.planetary[LAVALAND_DEFAULT_ATMOS] // y'all know
var/pressure = breath.return_pressure()
var/total_moles = breath.total_moles()
for(var/id in breath.get_gases())
var/this_pressure = PP(breath, id)
var/req_pressure = (this_pressure * SAFE_THRESHOLD_RATIO) - 1
if(req_pressure > 0)
gas_min[id] = req_pressure
if(id in gas_max)
gas_max[id] += this_pressure
var/bz = breath.get_moles(GAS_BZ)
if(bz)
BZ_trip_balls_min += bz
BZ_brain_damage_min += bz
gas_max[GAS_N2] = PP(breath, GAS_N2) + 5
var/o2_pp = PP(breath, GAS_O2)
safe_breath_min = 0.3 * o2_pp
safe_breath_max = 1.3 * o2_pp
..()
gas_max[GAS_N2] = 28
#undef SAFE_THRESHOLD_RATIO
/obj/item/organ/lungs/slime
name = "vacuole"
+3
View File
@@ -5,6 +5,9 @@
icon_deny = "boozeomat-deny"
products = list(/obj/item/reagent_containers/food/drinks/drinkingglass = 30,
/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass = 12,
/obj/item/reagent_containers/food/drinks/bottle/blank = 5,
/obj/item/reagent_containers/food/drinks/bottle/blank/small = 10,
/obj/item/reagent_containers/food/drinks/bottle/blank/pitcher = 2,
/obj/item/reagent_containers/food/drinks/bottle/gin = 5,
/obj/item/reagent_containers/food/drinks/bottle/whiskey = 5,
/obj/item/reagent_containers/food/drinks/bottle/tequila = 5,