Merge branch 'master' into misc-recreation

This commit is contained in:
sarcoph
2022-04-25 23:06:45 -08:00
committed by GitHub
270 changed files with 4170 additions and 1411 deletions
+4
View File
@@ -156,3 +156,7 @@
//belly sound pref things
#define NORMIE_HEARCHECK 4
#define BORGBELLY_NONE 0
#define BORGBELLY_RED 1
#define BORGBELLY_GREEN 2
+1
View File
@@ -10,6 +10,7 @@
#define CLONE "clone"
#define STAMINA "stamina"
#define BRAIN "brain"
#define PAIN "pain"
//bitflag damage defines used for suicide_act
#define BRUTELOSS (1<<0)
+3
View File
@@ -736,6 +736,9 @@
///from datum/action/cyborg_small_sprite and sends when a cyborg changes modules
#define COMSIG_CYBORG_MODULE_CHANGE "cyborg_module_change"
// /datum/element/ventcrawling signals
#define COMSIG_HANDLE_VENTCRAWL "handle_ventcrawl" //when atom with ventcrawling element attempts to ventcrawl
#define COMSIG_CHECK_VENTCRAWL "check_ventcrawl" //to check an atom's ventcrawling element tier (if applicable)
/* Attack signals. They should share the returned flags, to standardize the attack chain. */
/// tool_act -> pre_attack -> target.attackby (item.attack) -> afterattack
+4
View File
@@ -285,3 +285,7 @@
#define HUMAN_CARRY_SLOWDOWN 0
#define TYPING_INDICATOR_TIMEOUT 10 MINUTES
//Gremlins
#define NPC_TAMPER_ACT_FORGET 1 //Don't try to tamper with this again
#define NPC_TAMPER_ACT_NOMSG 2 //Don't produce a visible message
+1
View File
@@ -36,6 +36,7 @@ Ask ninjanomnom if they're around
#define RAD_MEDIUM_INSULATION 0.7 // What common walls have
#define RAD_HEAVY_INSULATION 0.6 // What reinforced walls have
#define RAD_EXTREME_INSULATION 0.5 // What rad collectors have
#define RAD_NEAR_FULL_INSULATION 0.2 // What radiation shutters and specialised walls for the RBMK use.
#define RAD_FULL_INSULATION 0 // Unused
// WARNING: The deines below could have disastrous consequences if tweaked incorrectly. See: The great SM purge of Oct.6.2017
+2
View File
@@ -206,6 +206,8 @@
#define TRAIT_ZAOCORP_NOGUNS "zao_no_guns"
#define INNATE_TRAIT "innate"
// common trait sources
#define TRAIT_GENERIC "generic"
#define EYE_DAMAGE "eye_damage"
+61
View File
@@ -0,0 +1,61 @@
#define MAXIMUM_MARKOV_LENGTH 25000
/proc/markov_chain(var/text, var/order = 4, var/length = 250)
if(!text || order < 0 || order > 20 || length < 1 || length > MAXIMUM_MARKOV_LENGTH)
return
var/table = markov_table(text, order)
var/markov = markov_text(length, table, order)
return markov
/proc/markov_table(var/text, var/look_forward = 4)
if(!text)
return
var/list/table = list()
for(var/i = 1, i <= length(text), i++)
var/char = copytext(text, i, look_forward+i)
if(!table[char])
table[char] = list()
for(var/i = 1, i <= (length(text) - look_forward), i++)
var/char_index = copytext(text, i, look_forward+i)
var/char_count = copytext(text, i+look_forward, (look_forward*2)+i)
if(table[char_index][char_count])
table[char_index][char_count]++
else
table[char_index][char_count] = 1
return table
/proc/markov_text(var/length = 250, var/table, var/look_forward = 4)
if(!table)
return
var/char = pick(table)
var/o = char
for(var/i = 0, i <= (length / look_forward), i++)
var/newchar = markov_weighted_char(table[char])
if(newchar)
char = newchar
o += "[newchar]"
else
char = pick(table)
return o
/proc/markov_weighted_char(var/list/array)
if(!array || !array.len)
return
var/total = 0
for(var/i in array)
total += array[i]
var/r = rand(1, total)
for(var/i in array)
var/weight = array[i]
if(r <= weight)
return i
r -= weight
+15
View File
@@ -177,6 +177,21 @@
desc = "You're severely dehydrated."
icon_state = "dehydrated"
/obj/screen/alert/pain
name = "Pain"
desc = "You're in pain!"
icon_state = "pain"
/obj/screen/alert/painmajor
name = "Major Pain"
desc = "You're in major pain!"
icon_state = "pain_major"
/obj/screen/alert/painshock
name = "Neurogenic Shock"
desc = "You are in so much pain, you risk going into shock!"
icon_state = "pain_shock"
/obj/screen/alert/gross
name = "Grossed out."
desc = "That was kind of gross..."
+3 -3
View File
@@ -35,7 +35,7 @@ SUBSYSTEM_DEF(nightshift)
if(!emergency)
announce("Restoring night lighting configuration to normal operation.")
else
announce("Disabling night lighting: Station is in a state of emergency.")
announce("Disabling night lighting: Station is in a state of emergency.")
if(emergency)
night_time = FALSE
if(nightshift_active != night_time)
@@ -45,9 +45,9 @@ SUBSYSTEM_DEF(nightshift)
nightshift_active = active
if(announce)
if (active)
announce("Good evening, crew. To reduce power consumption and stimulate the circadian rhythms of some species, all of the lights aboard the station have been dimmed for the night.")
priority_announce("Good evening, crew. To reduce power consumption and stimulate the circadian rhythms of some species, all of the lights aboard the station have been dimmed for the night.", sound='sound/AI/night.ogg', sender_override="Automated Lighting System Announcement")
else
announce("Good morning, crew. As it is now day time, all of the lights aboard the station have been restored to their former brightness.")
priority_announce("Good morning, crew. As it is now day time, all of the lights aboard the station have been restored to their former brightness.", sound='sound/AI/night2.ogg', sender_override="Automated Lighting System Announcement")
for(var/A in GLOB.apcs_list)
var/obj/machinery/power/apc/APC = A
if (APC.area && (APC.area.type in GLOB.the_station_areas))
+1 -1
View File
@@ -44,7 +44,7 @@ SUBSYSTEM_DEF(ticker)
var/start_at
var/gametime_offset = 432000 //Deciseconds to add to world.time for station time.
var/station_time_rate_multiplier = 12 //factor of station time progressal vs real time.
var/station_time_rate_multiplier = 20 //factor of station time progressal vs real time.
var/totalPlayers = 0 //used for pregame stats on statpanel
var/totalPlayersReady = 0 //used for pregame stats on statpanel
+36
View File
@@ -0,0 +1,36 @@
/datum/element/ventcrawling
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 2
var/tier
/datum/element/ventcrawling/Attach(datum/target, duration = 0, given_tier = VENTCRAWLER_NUDE)
. = ..()
var/mob/living/person = target
if(!istype(person))
return FALSE
src.tier = given_tier
RegisterSignal(target, COMSIG_HANDLE_VENTCRAWL, .proc/handle_ventcrawl)
RegisterSignal(target, COMSIG_CHECK_VENTCRAWL, .proc/check_ventcrawl)
to_chat(target, "<span class='notice'>You can ventcrawl! Use alt+click on vents to quickly travel about the station.</span>")
if(duration!=0)
addtimer(CALLBACK(src, .proc/Detach, target), duration)
/datum/element/ventcrawling/Detach(datum/target)
UnregisterSignal(target, list(COMSIG_HANDLE_VENTCRAWL, COMSIG_CHECK_VENTCRAWL))
to_chat(target, "<span class='notice'>You can no longer ventcrawl.</span>")
return ..()
/datum/element/ventcrawling/proc/handle_ventcrawl(datum/target,atom/A)
var/mob/living/person = target
if(!istype(person))
return FALSE
person.handle_ventcrawl(A,tier)
/datum/element/ventcrawling/proc/check_ventcrawl()
return tier
+8
View File
@@ -255,3 +255,11 @@
suffix = "lavaland_surface_cozy_cabin.dmm"
allow_duplicates = FALSE
cost = 0
/datum/map_template/ruin/lavaland/jettisoned_reactor
name = "Jettisoned Reactor"
id = "jettreactor"
description = "An incredibly dangerous ruin, filled with radiation and unknown lifeforms."
suffix = "lavaland_surface_jettisoned_reactor.dmm"
allow_duplicates = FALSE
cost = 15//Not too important, if you disregard the rads and facehugger.
+12
View File
@@ -295,3 +295,15 @@
to_chat(L, "<span class='warning'>You need an attachable assembly!</span>")
#undef MAXIMUM_EMP_WIRES
//gremlins
/datum/wires/proc/npc_tamper(mob/living/L)
if(!wires.len)
return
var/wire_to_screw = pick(wires)
if(is_color_cut(wire_to_screw) || prob(50)) //CutWireColour() proc handles both cutting and mending wires. If the wire is already cut, always mend it back. Otherwise, 50% to cut it and 50% to pulse it
cut(wire_to_screw)
else
pulse(wire_to_screw, L)
+5 -2
View File
@@ -81,7 +81,6 @@
icon_state = "red"
//Xeno Nest
/area/ruin/unpowered/xenonest
name = "The Hive"
always_unpowered = TRUE
@@ -90,6 +89,10 @@
power_light = FALSE
poweralm = FALSE
//ash walker nest
//Ash Walker Nest
/area/ruin/unpowered/ash_walkers
icon_state = "red"
//Jettisoned Reactor
/area/ruin/unpowered/reactor
icon_state = "red"
+19
View File
@@ -342,6 +342,25 @@
. += "<span class='danger'>It's empty.</span>"
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
//////////////////////////////////////////////////////////////
//Examine Tab stuff - Hyperstation
var/examineTabOutput = ""
examineTabOutput = "<center>"
examineTabOutput += "[icon2html(icon, world, icon_state)]"
examineTabOutput += " [url_encode(name)]" //url_encode for safty!
examineTabOutput += "</center>"
examineTabOutput += "<br>[url_encode(desc)]"
user.client << output(examineTabOutput, "statbrowser:update_examine") //open the examine window
user.client << output(null, "statbrowser:create_mobexamine") //open the examine window
//////////////////////////////////////////////////////////
/// Updates the icon of the atom
/atom/proc/update_icon()
// I expect we're going to need more return flags and options in this proc
@@ -176,7 +176,7 @@
/datum/dynamic_ruleset/event/crystals
name = "Crystal Invasion"
typepath = /datum/round_event/crystalloid_entities
weight = 4
weight = 5
repeatable_weight_decrease = 1
cost = 3
enemy_roles = list("AI","Security Officer","Head of Security","Captain","Assistant","Scientist","Station Engineer")
@@ -844,7 +844,7 @@
typepath = /datum/round_event/spontaneous_appendicitis
enemy_roles = list("Medical Doctor","Chief Medical Officer")
required_enemies = list(2,2,2,2,2,2,2,1,1,1)
requirements = list(5,5,5,5,5,5,5,5,0,0)
requirements = list(101,101,20,18,16,14,12,10,8,6)
high_population_requirement = 10
weight = 5
cost = 6
+52
View File
@@ -91,3 +91,55 @@
/obj/machinery/door/poddoor/try_to_crowbar(obj/item/I, mob/user)
if(stat & NOPOWER)
open(1)
//Multi-tile poddoors don't turn invisible automatically, so we change the opacity of the turfs below instead one by one.
/obj/machinery/door/poddoor/multi_tile/proc/apply_opacity_to_my_turfs(var/new_opacity)
for(var/turf/T in locs)
T.opacity = new_opacity
T.has_opaque_atom = new_opacity
T.reconsider_lights()
T.air_update_turf(1)
update_freelook_sight()
/obj/machinery/door/poddoor/multi_tile
rad_insulation = RAD_NEAR_FULL_INSULATION
/obj/machinery/door/poddoor/multi_tile/open()
. = ..()
rad_insulation = RAD_NO_INSULATION
apply_opacity_to_my_turfs(0)
/obj/machinery/door/poddoor/multi_tile/close()
. = ..()
rad_insulation = RAD_NEAR_FULL_INSULATION
apply_opacity_to_my_turfs(1)
/obj/machinery/door/poddoor/multi_tile/four_tile_ver/
icon = 'icons/obj/doors/1x4blast_vert.dmi'
bound_height = 128
dir = NORTH
/obj/machinery/door/poddoor/multi_tile/three_tile_ver/
icon = 'icons/obj/doors/1x3blast_vert.dmi'
bound_height = 96
dir = NORTH
/obj/machinery/door/poddoor/multi_tile/two_tile_ver/
icon = 'icons/obj/doors/1x2blast_vert.dmi'
bound_height = 64
dir = NORTH
/obj/machinery/door/poddoor/multi_tile/four_tile_hor/
icon = 'icons/obj/doors/1x4blast_hor.dmi'
bound_width = 128
dir = EAST
/obj/machinery/door/poddoor/multi_tile/three_tile_hor/
icon = 'icons/obj/doors/1x3blast_hor.dmi'
bound_width = 96
dir = EAST
/obj/machinery/door/poddoor/multi_tile/two_tile_hor/
icon = 'icons/obj/doors/1x2blast_hor.dmi'
bound_width = 64
dir = EAST
+9 -11
View File
@@ -41,23 +41,21 @@
desc = "Lead-lined shutters painted yellow with a radioactive hazard symbol on it. Blocks out most radiation"
icon = 'icons/obj/doors/shutters_radiation.dmi'
icon_state = "closed"
rad_insulation = 0.2
rad_insulation = RAD_NEAR_FULL_INSULATION
/obj/machinery/door/poddoor/shutters/radiation/preopen
icon_state = "open"
density = FALSE
opacity = 0
rad_insulation = 1
opacity = FALSE
rad_insulation = RAD_NO_INSULATION
/obj/machinery/door/poddoor/shutters/radiation/do_animate(animation)
..()
switch(animation)
if("opening")
rad_insulation = 1
if("closing")
rad_insulation = -0.5
/obj/machinery/door/poddoor/shutters/radiation/open()
. = ..()
rad_insulation = RAD_NO_INSULATION
// A 3x3 N2 SM setup won't irradiate you if you're behind the shutter at -0.9 insulation. If it starts to delam, it'll start irradiating you slowly. Keep the value between -0.1 to -0.9
/obj/machinery/door/poddoor/shutters/radiation/close()
. = ..()
rad_insulation = RAD_NEAR_FULL_INSULATION
/obj/machinery/door/poddoor/shutters/window
name = "windowed shutters"
@@ -11,7 +11,6 @@
var/min_health = -100
var/cleaning = FALSE
var/cleaning_cycles = 10
var/patient_laststat = null
var/list/injection_chems = list(/datum/reagent/medicine/antitoxin, /datum/reagent/medicine/epinephrine,
/datum/reagent/medicine/salbutamol, /datum/reagent/medicine/bicaridine, /datum/reagent/medicine/kelotane)
var/eject_port = "ingestion"
@@ -86,16 +85,16 @@
if(patient)
to_chat(user, "<span class='warning'>Your [src] is already occupied.</span>")
return
user.visible_message("<span class='warning'>[hound.name] is carefully inserting [target.name] into their [src].</span>", "<span class='notice'>You start placing [target] into your [src]...</span>")
user.visible_message("<span class='warning'>[hound.name] is carefully inserting [target.name] into their [src].</span>",
"<span class='notice'>You start placing [target] into your [src]...</span>")
if(!patient && iscarbon(target) && !target.buckled && do_after (user, 100, target = target))
if(!in_range(src, target)) //Proximity is probably old news by now, do a new check.
return //If they moved away, you can't eat them.
if(!in_range(src, target))
return
if(patient)
return //If you try to eat two people at once, you can only eat one.
else //If you don't have someone in you, proceed.
return
else
if(!isjellyperson(target) && ("toxin" in injection_chems))
injection_chems -= "toxin"
injection_chems += "antitoxin"
@@ -104,8 +103,8 @@
injection_chems += "toxin"
target.forceMove(src)
target.reset_perspective(src)
target.ExtinguishMob() //The tongue already puts out fire stacks but being put into the sleeper shouldn't allow you to keep burning.
update_gut(hound)
target.ExtinguishMob()
UpdateGut(hound)
user.visible_message("<span class='warning'>[voracious ? "[hound]'s [src.name] lights up and expands as [target] slips inside into their [src.name]." : "[hound]'s sleeper indicator lights up as [target] is scooped up into [hound.p_their()] [src]."]</span>", \
"<span class='notice'>Your [voracious ? "[src.name] lights up as [target] slips into" : "sleeper indicator light shines brightly as [target] is scooped inside"] your [src]. Life support functions engaged.</span>")
message_admins("[key_name(hound)] has sleeper'd [key_name(patient)] as a dogborg. [ADMIN_JMP(src)]")
@@ -156,7 +155,7 @@
items_preserved.Cut()
cleaning = FALSE
if(hound)
update_gut(hound)
UpdateGut(hound)
/obj/item/dogborg/sleeper/attack_self(mob/user)
@@ -170,13 +169,18 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
// TGUI TODO: do something about this UI
ui = new(user, src, ui_key, "dogborg_sleeper", name, 375, 550, master_ui, state)
ui = new(user, src, ui_key, "DogborgSleeper", name, 375, 550, master_ui, state)
ui.open()
/obj/item/dogborg/sleeper/ui_data()
var/list/data = list()
var/chemical_list = list()
var/blood_percent = 0
data["occupied"] = patient ? 1 : 0
data["blood_levels"] = blood_percent
data["blood_status"] = "Patient either has no blood, or does not require it to function."
data["chemical_list"] = chemical_list
if(cleaning && length(contents - items_preserved))
data["items"] = "Self-cleaning mode active: [length(contents - items_preserved)] object(s) remaining."
@@ -185,7 +189,7 @@
data["chem"] = list()
for(var/chem in injection_chems)
var/datum/reagent/R = GLOB.chemical_reagents_list[chem]
data["chem"] += list(list("name" = R.name, "id" = R.type))
data["chem"] += list(list("name" = R.name, "id" = R.type, "allowed" = TRUE))
data["occupant"] = list()
var/mob/living/mob_occupant = patient
@@ -213,10 +217,41 @@
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
data["occupant"]["reagents"] = list()
if(mob_occupant.reagents.reagent_list.len)
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
chemical_list += list(list("name" = R.name, "volume" = R.volume))
else
chemical_list = "Patient has no reagents."
data["occupant"]["failing_organs"] = list()
var/mob/living/carbon/C = mob_occupant
if(C)
for(var/obj/item/organ/Or in C.getFailingOrgans())
if(istype(Or, /obj/item/organ/brain))
continue
data["occupant"]["failing_organs"] += list(list("name" = Or.name))
if(istype(C)) //Non-carbons shouldn't be able to enter sleepers, but this is to prevent runtimes if something ever breaks
if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner.
blood_percent = round((C.blood_volume / BLOOD_VOLUME_NORMAL)*100)
var/blood_id = C.get_blood_id()
var/blood_warning = ""
if(blood_percent < 80)
blood_warning = "Patient has low blood levels."
if(blood_percent < 60)
blood_warning = "Patient has DANGEROUSLY low blood levels."
if(blood_id)
var/blood_type = C.dna.blood_type
if(!(blood_id in GLOB.blood_reagent_types)) // special blood substance
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
if(R)
blood_type = R.name
else
blood_type = blood_id
data["blood_status"] = "Patient has [blood_type] type blood. [blood_warning]"
data["blood_levels"] = blood_percent
return data
/obj/item/dogborg/sleeper/ui_act(action, params)
@@ -239,81 +274,42 @@
to_chat(src, "Your [src] is already cleaned.")
return
if(patient)
to_chat(patient, "<span class='danger'>[usr.name]'s [src] fills with caustic enzymes around you!</span>")
to_chat(patient, "<span class='userdanger'>[usr.name]'s [src] fills with caustic enzymes around you!</span>")
to_chat(src, "<span class='danger'>Cleaning process enabled.</span>")
clean_cycle(usr)
. = TRUE
/obj/item/dogborg/sleeper/proc/update_gut(mob/living/silicon/robot/hound)
//Well, we HAD one, what happened to them?
if(!hound) //runetime error fix with dogborgs with no sleepers
return
var/prociconupdate = FALSE
var/currentenvy = hound.sleeper_nv
hound.sleeper_nv = FALSE
if(patient in contents)
if(patient_laststat != patient.stat)
if(patient.stat & DEAD)
hound.sleeper_r = 1
hound.sleeper_g = 0
patient_laststat = patient.stat
else
hound.sleeper_r = 0
hound.sleeper_g = 1
patient_laststat = patient.stat
prociconupdate = TRUE
if(!patient.client || !(patient.client.prefs.cit_toggles & MEDIHOUND_SLEEPER) || !hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
hound.sleeper_nv = TRUE
else
hound.sleeper_nv = FALSE
if(hound.sleeper_nv != currentenvy)
prociconupdate = TRUE
//Update icon
if(prociconupdate)
hound.update_icons()
//Return original patient
return(patient)
//Check for a new patient
else
for(var/mob/living/carbon/human/C in contents)
patient = C
if(patient.stat & DEAD)
hound.sleeper_r = 1
hound.sleeper_g = 0
patient_laststat = patient.stat
else
hound.sleeper_r = 0
hound.sleeper_g = 1
patient_laststat = patient.stat
if(!patient.client || !(patient.client.prefs.cit_toggles & MEDIHOUND_SLEEPER) || !hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
hound.sleeper_nv = TRUE
else
hound.sleeper_nv = FALSE
//Update icon and return new patient
hound.update_icons()
return
//Cleaning looks better with red on, even with nobody in it
if(cleaning && !patient)
hound.sleeper_r = 1
hound.sleeper_g = 0
//Couldn't find anyone, and not cleaning
else if(!cleaning && !patient)
hound.sleeper_r = 0
hound.sleeper_g = 0
patient_laststat = null
/obj/item/dogborg/sleeper/proc/UpdatePatient(mob/living/silicon/robot/hound)
patient = null
hound.update_icons()
for(var/mob/living/carbon/human/C in contents)
patient = C
break
return patient
/obj/item/dogborg/sleeper/proc/CheckNeedsGutUpdate(mob/living/silicon/robot/hound)
if(!hound) return
var/current_belly = BORGBELLY_NONE
UpdatePatient(hound)
if(patient)
var/patient_vore_enabled = patient.client?.prefs?.cit_toggles & MEDIHOUND_SLEEPER
var/hound_vore_enabled = hound.client?.prefs?.cit_toggles & MEDIHOUND_SLEEPER
if(patient_vore_enabled && hound_vore_enabled)
if(patient.stat & DEAD)
current_belly = BORGBELLY_RED
else
current_belly = BORGBELLY_GREEN
else
if(cleaning)
current_belly = BORGBELLY_RED
return current_belly
/obj/item/dogborg/sleeper/proc/UpdateGut(mob/living/silicon/robot/hound)
var/new_belly = CheckNeedsGutUpdate(hound)
if(hound.sleeper_state != new_belly)
hound.sleeper_state = new_belly
hound.update_icons()
//Gurgleborg process
/obj/item/dogborg/sleeper/proc/clean_cycle(mob/living/silicon/robot/hound)
//Sanity
if(!hound)
return
for(var/I in items_preserved)
@@ -365,15 +361,13 @@
if(!T.dropItemToGround(W))
qdel(W)
qdel(T)
//Handle the target being anything but a mob
else if(isobj(target))
var/obj/T = target
if(T.type in important_items) //If the object is in the items_preserved global list
items_preserved += T
//If the object is not one to preserve
else
qdel(T)
update_gut()
UpdateGut(hound)
hound.cell.give(10)
else
cleaning_cycles = initial(cleaning_cycles)
@@ -399,9 +393,8 @@
H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
else if(H in contents)
H.playsound_local(source, null, 65, falloff = 0, S = prey_digest)
update_gut(hound)
UpdateGut(hound)
if(cleaning)
addtimer(CALLBACK(src, .proc/clean_cycle, hound), 50)
@@ -462,7 +455,7 @@
if(do_after(user, 30, target = target) && !patient && !target.buckled)
target.forceMove(src)
target.reset_perspective(src)
update_gut(hound)
UpdateGut(hound)
user.visible_message("<span class='warning'>[hound.name]'s mobile brig clunks in series as [target] slips inside.</span>", "<span class='notice'>Your mobile brig groans lightly as [target] slips inside.</span>")
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots
@@ -490,31 +483,25 @@
if(length(contents) > (max_item_count - 1))
to_chat(user,"<span class='warning'>Your [src] is full. Eject or process contents to continue.</span>")
return
if(isitem(target))
var/obj/item/I = target
if(CheckAccepted(I))
to_chat(user,"<span class='warning'>[I] registers an error code to your [src]</span>")
to_chat(user,"<span class='warning'>[I] registers an error code to your [src].</span>")
return
if(I.w_class > WEIGHT_CLASS_NORMAL)
to_chat(user,"<span class='warning'>[I] is too large to fit into your [src]</span>")
to_chat(user,"<span class='warning'>[I] is too large to fit into your [src].</span>")
return
user.visible_message("<span class='warning'>[hound.name] is ingesting [I] into their [src.name].</span>", "<span class='notice'>You start ingesting [target] into your [src.name]...</span>")
if(do_after(user, 15, target = target) && length(contents) < max_item_count)
I.forceMove(src)
I.visible_message("<span class='warning'>[hound.name]'s garbage processor groans lightly as [I] slips inside.</span>", "<span class='notice'>Your garbage compactor groans lightly as [I] slips inside.</span>")
playsound(hound, 'sound/machines/disposalflush.ogg', 50, 1)
if(length(contents) > 11) //grow that tum after a certain junk amount
hound.sleeper_r = 1
hound.update_icons()
else
hound.sleeper_r = 0
hound.update_icons()
return
if(iscarbon(target) || issilicon(target))
else if(iscarbon(target) || issilicon(target))
var/mob/living/trashman = target
if(!trashman.devourable)
to_chat(user, "<span class='warning'>[target] registers an error code to your [src]</span>")
to_chat(user, "<span class='warning'>[target] registers an error code to your [src].</span>")
return
if(patient)
to_chat(user,"<span class='warning'>Your [src] is already occupied.</span>")
@@ -526,6 +513,14 @@
if(do_after(user, 30, target = trashman) && !patient && !trashman.buckled && length(contents) < max_item_count)
trashman.forceMove(src)
trashman.reset_perspective(src)
update_gut()
user.visible_message("<span class='warning'>[hound.name]'s garbage processor groans lightly as [trashman] slips inside.</span>", "<span class='notice'>Your garbage compactor groans lightly as [trashman] slips inside.</span>")
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1)
UpdateGut(hound)
/obj/item/dogborg/sleeper/compactor/CheckNeedsGutUpdate(mob/living/silicon/robot/hound)
var/current_belly = ..()
if(length(contents) > 11)
current_belly = BORGBELLY_RED
return current_belly
@@ -135,6 +135,9 @@ GENE SCANNER
if(ishuman(M))
var/mob/living/carbon/human/H = M
if (user.stat == 0) //no more ghost scans
H.scan_animation()
if(H.undergoing_cardiac_arrest() && H.stat != DEAD)
to_chat(user, "<span class='danger'>Subject suffering from heart attack: Apply defibrillation or other electric shock immediately!</span>")
if(H.undergoing_liver_failure() && H.stat != DEAD) //might be depreciated BUG_PROBABLE_CAUSE
@@ -43,7 +43,7 @@
deliveryamt = 10
/obj/item/grenade/spawnergrenade/clustaur
desc = "A very strange grenade often found in maintanance. Use of this may constitute a war crime in your area, consult your local captain."
desc = "A very strange grenade often found in maintenance. Use of this may constitute a war crime in your area, consult your local captain."
name = "clustaur grenade"
icon_state = "clustaur"
item_state = "clustaur"
-225
View File
@@ -1,225 +0,0 @@
/obj/item/book/lorebooks
icon = 'icons/obj/library.dmi'
due_date = 0 // Game time in 1/10th seconds
unique = TRUE // FALSE - Normal book, TRUE - Should not be treated as normal book, unable to be copied, unable to be modified
/obj/item/book/lorebooks/welcome_to_kinaris
name = "Welcome to Kinaris!"
icon_state = "bookwelcometokinaris"
desc = "An introductory book given to immigrants of people who changed their Nanotrasen ways, and accepted the light of Kinaris, Radiance, and the Azurean Government."
author = "V. Kinaris"
title = "Welcome to Kinaris!"
dat = {"<html>
<head>
<style>
h1 {font-size: 18px; margin: 15px 0px 5px;}
h2 {font-size: 15px; margin: 15px 0px 5px;}
li {margin: 2px 0px 2px 15px;}
ul {list-style: none; margin: 5px; padding: 0px;}
ol {margin: 5px; padding: 0px 15px;}
</style>
</head>
<body>
<h3 style="text-align: center;">Welcome to Kinaris!</h3>
<hr>
If you're reading this datapad, you probably have gained an interest in what the daily commodities and rights of a Kinaris worker may be, or you have recently been employed and are looking for further information. Under the latter's case; welcome! It's not an easy transition to working under a larger corporation for any Azurean, and we are here to alleviate that stress. Whether or not you fall under any of these categories, or are clueless at all to who we are, please do take a read!
<p>
<h2>Table of Contents...</h2>
<ol>
<li>What is Kinaris?
<li>How Kinaris Came to be
<li>How Kinaris Operates Today
<li>Workers' Rights
<li>Usage of Radiance
</ol>
<p>
<hr>
<h1><u>Chapter 1</u></h1>
<h2>What is Kinaris? </h2>
<p>
If you are unfamiliar to Azurean space, then you are most definitely unfamiliar with the entirety of Kinaris itself. Kinaris is the primary company under the rule of Azurea, who not only manufactures goods, but is a forefront of Radiant Technology, space exploration, exo-colony development, and asset protection. As such, it is a very expensive operation that almost entirely depends on it's own manufactured goods- and selling of such- towards it's own colonies, which is an extent of colony taxation and revenue collection after they've initially been set up. The sheer stability of it's exponential growth and safety has piqued the interest from other regions and promising even more imports and exports between Kinaris and other affiliates (including but not limited to; Lancaster Industries, CorpraTek, Grinlok Conglomerate, <s>and Nanotrasen</s>). The dependable and and noble nature of the heads at Kinaris had inevitably led to constant backing by the Azurean Government, and increased fortitude in asset protection. This ultimately ended up in Kinaris being the leading, and most-trusted government under Azurea law.
<p>
The word Kinaris means "of kin", which translates to "of family", and that is the intent of Kinaris. A family nourishes you and helps you grow, through hardship and every step of the way along the road of becoming an individual. With every lesson learned, you grow. With every riddled situation, you learn anew. Kinaris is no different from that of the teachings of a mother or a father; intent to ensure that you can be a successor, and be better than your previous self. You are as important as everyone else in the world, yet you are unique. These rights are protected under Kinaris.
<p>
<hr>
<h1><u>Chapter 2</u></h1>
<h2>How Kinaris Came to be</h2>
<p>
Rising up to mega-corporation status and being backed as the most trustable force within several sectors is not a simple task whatsoever. There are mistakes along the road, and there are plenty of issues forthwrought with even considering such a task. Kinaris begun as nothing more than a simple cargo company nearly two centuries from the date of March 5th, 2560. Initially, the company began as nothing more than a delivery service by none other than Centurian Kinaris, within a low-tech sector out of Azurean Gov's grasp. Due to the unfortunate events of resistance against The Phoenix at the time, most sectors like this were outright ravaged and decimated into a smoldering pulp of mud and ash, where individuals kept to themselves and were cut-throat towards one another. This led to imports and exports often being outright mistrusted due to one scandallous event of poisoned rations after another. This was an opportunity for Centurian, who was one of the most trusted individuals within the sector, and opened up his shipping goods company after months of hauling for others. This in time spread word and opened further opportunities for Centurian himself, who saw these as nothing more than help to give towards those who needed it. Kinaris outright spent a good portion of it's early life as another small company with a few workers trickling in every now and then, indifferent to the thousands of others littering the frontier.
<p>
What eventually settled Kinaris off from the norm of other companies was nothing more than the surge of artificial interest in becoming Radiant across Azurean space. Unlike most companies who resisted and fought against The Phoenix, Kinaris heeded it's will. It was said that Centurian himself was a vissionare in his early days, led by the golden light, as he called it. In most frontier sectors, this was appalled and shunned by most communties, who aimed to flee as far as they could from Azurea itself, to escape Radiance. This was a short downfall in Kinaris's momentum, as it's trust rapidly decimated into nothing in due time, and prompted anger within it's customers. However, Centurian prevailed, and in a simple matter of days, sectors begun following in Radiance in the bulk, and as a result, formed a bond with the company. It is unclear how exactly Centurian managed to pull off such a dangerous feat, but that is just more evidence towards his Radiance.
<p>
As the interest in Radiance surged across Azurean space, so did the success of Kinaris. One sector converted, one sector gained trust. More trust, more revenue. More revenue, more improvements. Rinse and repeat, for a hundred years. For a while, Radiance was nothing more than a melody that went with the chorus of Kinaris; a simple cargo company turned head over heels into a Pristine Zealot of Light, converting those within it's path instead of decimating it to smoldering ash, feeding back into the acceptance of Radiance as a whole for the people of Azurean Space. Centurian was nothing more than the leader of peace and safety, giving to those who needed help the most, branching off far beyond that of simple freight shipments. With trust, he smote down those who did not heed to peace, rather violence. Some did not believe in his ways. This led to his death after a Nanotrasen Assault on his capital freighter.
<p>
Today, his tomb drifts within the gas clouds of Myril Majoris, Azurea's gas giant. In memoriam of the one person who heeded unity with individualism into Azurea's people. He was nothing more than Radiant, nothing less.
<p>
<hr>
<h1><u>Chapter 3</u></h1>
<h2>How Kinaris Operates Today</h2>
<p>
Modern-day Kinaris is a different story than that of previous-century Kinaris, with less aggression and more protection, yet it is the other side of one coin. Having gone past the days of aggression and forthright domination, KN's goal these days is that of a stalwart. Reliable, hardworking, and most of all: loyal. Having gone far from it's roots of zealot-like exports, imports, and radical conversion, Kinaris is that of an expanded mindset and reach, especially due to the usage of Radiant Technology. Today, Kinaris offers not only jobs in freight, but that of common commodities such as food growth and production, alongside processing. Further down the line includes industrial production and that of factory-assisted work, robotics, research, asset protection, and more. When a new sector, area or ship is attained, it is assigned a Commander, in which they ensure it is secured with it's own technological advances and supplies, to ensure the working condition of any outpost, station, or ship that KN may claim ownership of. After initial supplying and resource distribution, workers are given a period of time to get set up before sending shipments out for Kinaris to collect and maintain as exports elsewhere, ultimately with profit in mind. This may not be the case for every new sector attained, but it is often standard protocol, with more upgrades to the sector coming forth as a the Commander may see fit; and often times, Commanders are rotated in and out from the sector.
<p>
Kinaris Officials and Commanders are often protected by a multitude of laws that allow them to display their power and ensure that workers are making profits, and may even be escorted by KN Elites and Zealots, if suspected threats are within the area. Usage of force is often permitted in the instance of non-compliance with a Commander, who is above any captain or high-ranking individual in control of that sector, and is more often than not, above KN Law, but below Radiance Protocol. Kinaris Officials do not get this benefit.
<p>Above Commanders, there may be a regional director who controls and permits what Commanders do in their sectors, and above that, there will be a member of the board who represents certain regions. There is no distinct "CEO" of Kinaris, rather a board of directors who have fully committed to Radiance, and have the near-full extent of Radiant Technology within their system. The closest personnel to a higher rank above that would be Valarie Kinaris, the daughter of the founder. She still answers to other board members, as they answer to her, however.
<p>
<hr>
<h1><u>Chapter 4</u></h1>
<h2>Workers' Rights</h2>
<p>
Please refer to Kinaris Law for a full extent of these rights.
<p>
<hr>
<h1><u>Chapter 5</u></h1>
<h2>Usage of Radiance</h2>
<p>
If you've been blessed by The Phoenix's light, then we commend you for such a noble hierarchy to achieve! As Radiance Protocol is rather straightforward in the eyes of Kinaris and we do not doubt the usage of the beholder, it is permitted to use Radiant Technology within Kinaris-owned space, so as long as it involves a more efficient workflow. Usage of smiting should be used with caution.
<p>
<hr>
</body>
</html>
"}
/obj/item/book/lorebooks/layenia_crystals
name = "Layenia Crystal Cycles"
icon_state = "booklayeniacrystals"
desc = "Curious about all those crystals you see on Layenia? Wait no further, this datapad contains all public information so far!"
author = "W. Ryyn-Kinar"
title = "Layenia Crystal Cycles"
dat = {"<html>
<head>
<style>
h1 {font-size: 18px; margin: 15px 0px 5px;}
h2 {font-size: 15px; margin: 15px 0px 5px;}
li {margin: 2px 0px 2px 15px;}
ul {list-style: none; margin: 5px; padding: 0px;}
ol {margin: 5px; padding: 0px 15px;}
</style>
</head>
<body>
<h3 style="text-align: center;">Layenia Crystal Cycles</h3>
<hr>
Layenia is a prominent interest in recent times for the likes of Azurean civilizations. While the concepts of negative mass and spacetime-altering properties are nothing new for Kinaris R&D, Layenia holds a special key for Weave-integrated technology. If you are familiar with The Weave, then you may know why Layenian Crystals (also referred to as lattice crystals) are such a focal point. If not, this datapad may prove useful to you.
<p>
<h2>Table of Contents...</h2>
<ol>
<li>Creation of Crystals
<li>Crystal Purities
<li>Floating Islands
<li>Floating Island Cycles
<li>Speculation
</ol>
<p>
<hr>
<h1><u>Chapter 1</u></h1>
<h2>Creation of Crystals</h2>
<p>
On the outside, a Layenian crystal seems to be nothing special short of a blue geode if broken open; more often sharply squared off with fine tips. Layenian crystals resemble that of volcanic geodes; where empty space in basaltic lava flow is often filled up with deposits of material carried by groundwater. In Layenia, a similar process happens with the intense heat and pressure of the inner planet boiling away trace gaseous minerals in the atmosphere into a Weave-infused shell of what can only be defined as Weave-basalt. Further infusion with Weave energy will make Layenian crystals.
<p>
We do not fully understand just how The Weave manages to manifest itself so strongly within the deeper reaches of Layenia, as we have only seen the effects on our side of the dimension as Layenian crystals. What we do know is that the crystals- despite occupying multidimensional space- seem to lean more towards our reality despite the majority of its shell being born in another.
<p>
<hr>
<h1><u>Chapter 2</u></h1>
<h2>Crystal Purities</h2>
<p>
How you can decipher the purity of Weave-basalt is relatively simple without prodding at the Weave itself; just look at its color and shape. Incomplete infusions with Weave energy will leave the basalt-esque rock not porous and filled, with a reddish-iron hue occupying its coloration. The rock in question will be rough, made up of multiple mineral deposits, and does not react with acid; much similar to other gaseo-igneous rocks of its family. However, more purely-infused with Weave energy will cause drastic change to the crystals structure once it solidifies itself between two dimensions. Compared to the coarse status of its impurity version, a refined Layenian crystal will lack a portion of excess mineral deposits, where it is theorized that energy from the Weave can freely bounce between the two dimensions across its glassy surface. The crystalline structure will be leaning more towards a reflective-cobalt, shining towards ultramarine in most lights. Most obvious of all, its negative mass will correlate directly with how pure it is; this contributes to its floating properties within Layenia. If it is too pure however, it will start to resonate with the Weave. We will get back to that later.
<p>
<hr>
<h1><u>Chapter 3</u></h1>
<h2>Floating Islands</h2>
<p>
As masses of crystals are born within Layenia all with varying purities, they will become attracted to each other due to innate Weave energy manifesting as a gravitational tug. This causes them to conglomerate together with an electrified fusion process via Weave, keeping trace amounts of crystalline dust and minerals extremely minimal, as they cling to one another. A completely pure crystal will accelerate itself away from any point of mass and gravity, which prompts the crystal to float up through Layenias atmosphere. However, as it accumulates impurities in the form of Weave-basalt, its ability to accelerate and keep its distance from gravitational sources gets reduced, until the mass inevitably finds a stable point amidst the clouds. This is how most floating islands are formed within Layenia.
<p>
<hr>
<h1><u>Chapter 4</u></h1>
<h2>Floating Island Cycles</h2>
<p>
As the constant influx of more varying purities of crystals flows from the inner atmosphere to the upper, this leads to inevitable island collisions, which advances the stages of floating islands in their life cycles. As islands crash into one another, they release immense bursts of Weave energy as electricity-- their rocks fusing together like metal would weld. Sometimes floating islands crash into one another with enough velocity to outright explode, forgoing island merging altogether. If one does merge however, they will ascend or descend in the atmosphere where it can stabilize again with its new mass. If it goes too low and accumulates too much impure Weave-basalt, the pressure will crush and split the island apart, giving it a new opportunity to repeat the cycle anew.
<p>
However, if the island has an extremely-high ratio of Layenian crystals to Weave-basalt, the floating island/mass will accelerate through the atmosphere and even leave it altogether, flinging itself far into space as a result. Sometimes the rocks donate to Layenias local ring system, however they sometimes come crashing back down as a meteor after gaining mass from dust and rock within the ring itself. This only occurs if a Layenian crystal accelerates at a steady rate, the unlucky few of crystals may undergo a process of Weave resonance, where their acceleration only speeds up through the atmosphere as its fought by less drag in its rise through density. If the mass accelerates above ~150kph, the pure crystals will start to resonate and ring out in the natural frequency of the Weave- producing an ear-splitting metallic hum for those who are not Attuned as they vibrate intensely. As the mass speeds up, the crystals will begin to build up Weave energy, glowing brighter in unison with the louder ringing that the rock resonates in. Left unchecked, this will lead the mass to a critical point, where it will promptly detonate in a swathe of Weave energy, piercing the clouds with a golden light that superheats anything caught within its wake. Its theorized that this is the ultimate end of Layenia crystals, where the Radiance itself harvests the energy.
<p>
<br>
<h1><u>Chapter 5</u></h1>
<h2>Speculation</h2>
<p>
While Layenian crystals have been discovered elsewhere in the universe, their frequency and abundance was extremely lackluster; never before have they been found in such quantity as they have in Layenia, which led to them being renamed into Layenian crystals in the first place. While Layenia is carefully monitored by Kinaris, we cannot help but speculate just why the Radiance chose to pick this specific planet to manifest its Weave energy so prominently, as well as why it wanted gravity-altering crystals, of all things. Speculation has it that the Radiance uses the crystals as an anchor on our reality to see and feel it, to experience and memorize it in crystalline form, as it does with the living flesh of people in Attunement. When a crystal finally detonates for the last time, we cannot help but think that the Radiance does this to extract every bit of information about our dimensional plane as it can. While no confirmations have been made on any of this, it is a likely explanation approved by Valarie Kinaris herself, who is a prominent speaker for Radiance and Attuned alike.
<p>
<hr>
</body>
</html>
"}
/obj/item/book/lorebooks/engrams
name = "The Engram: Securing Your Technology"
icon_state = "bookengrams"
desc = "Ever wondered why technology seems locked in some places, or more modular in others? Learn about the Engram with this crash-course datapad!"
author = "P. LYNN"
title = "The Engram: Securing Your Technology"
dat = {"<html>
<head>
<style>
h1 {font-size: 18px; margin: 15px 0px 5px;}
h2 {font-size: 15px; margin: 15px 0px 5px;}
li {margin: 2px 0px 2px 15px;}
ul {list-style: none; margin: 5px; padding: 0px;}
ol {margin: 5px; padding: 0px 15px;}
</style>
</head>
<body>
<h3 style="text-align: center;">The Engram</h3>
<h2 style="text-align: center;">Securing Your Technology</h2>
<hr>
Have you ever looked at your workplace surroundings and wondered why it feels so modular? Ever wondered why you can't just get a screwdriver and pick apart your local armory weapons, and rebuild them? Or perhaps you're wondering why certain items simply refuse to go together? This is all thanks to the Andromeda-class Patented Engram System (APES), which is capable of modifying the physical manifestation of technology, as if it were a blueprint! This datapad will cover the basics of what an Engram actually is, and what it does for those involved.
<p>
<h2>Table of Contents...</h2>
<ol>
<li>The Engram; What Is It?
<li>Why Are Engrams Made?
<li>Why Are Engrams Necessary?
<li>Engrams Used Today
</ol>
<p>
<hr>
<h1><u>Chapter 1</u></h1>
<h2>The Engram; What Is It?</h2>
<p>
In the Eight Era of the Seventh Cycle, technology has flourished beyond the means of standard Euclidian definitions. Weave-integrated processing in conjunction with infused metals are often the specular highlight of focus for most folk willing to learn how our galaxy operates, but that is often just the tip of the iceberg for the standing Azurean scholar. Far beyond the point of quantum and bluespace, technologies had started to become too complex for any single organization to keep track of, even with the help of multidimensional-threaded computing. Thus, a standardized solution was needed: The Engram.
<p>
An Engram is more often than not an umbrella of technologies, secured beneath a data-chit for usage within a colony, region of space, or entire sector. Most brands of Engrams tend to consist of a Weave-altercated core with a deactivated shell, for usage into a type of infusion engine. Depending on the power plugged into it, it's range of influence can span very little, or very far! Most high-end Engrams tend to be galaxy-wide, and service as a focal point for editing the material blueprint of anything in real time.
<p>
The Engram itself serves the whole purpose of ensuring that a technology can become easy to contain, should it's complexity become numbing to even the most bright of minds. As a result, this can also "lock down" or change features of the technology, should it be required and programmed correctly, which is more often than not the case for companies who wish to ensure that their technologies can be distributed without illegal modifications-- after all, an Engram can be controlled only by it's main chit, so technology can be revoked or changed on the fly without any needs for recalling and redistribution!
<p>
<hr>
<h1><u>Chapter 2</u></h1>
<h2>Why Are Engrams Made?</h2>
<p>
As stated in the chapter before, Engrams were made out of the necessity of simplifying relentlessly-complex technologies, but they suffice much more purpose than just ease of access. When an Engram is successfully applied to a technology or a branch of such, it effectively can alter the material blueprint of said tech in realtime, should the correct commodoties be applied to it. This ease of updating manufactured goods in realtime can be applicable to simply updating software on one's computer, only with realtime hardware modification, for the sake of analogy. This means any issues can be ironed out post-distribution.
<p>
Not only that, but this effectively helps technology to be more free and easily accessible for those interested in purchasing. Shareholders can use and keep an Engram knowing full well that this allows their technology to be safe and secure, even if it does end up in the wrong hands! Engrams are often tied to a company's TOS, where breaking said terms can often revoke and restrain the usage of technology remotely. Even any attempts to modify technology without the correct permissions can all be result in failures, as Engrams effectively can turn technology into an encrypted blueprint in realtime-- meaning that you'll see little to no plaigiarized and ill-modified tech, without the correct permits from the user.
<p>
<hr>
<h1><u>Chapter 3</u></h1>
<h2>Why Are Engrams Necessary?</h2>
<p>
By this point in reading, it may seem obvious as to why Engrams can be necessary in this day and age, but many civilizations and societies can often reject and turn down the nature and ideals that an Engram can not only bring, but encourage as well. Many fears can be stricken across societies about how dangerous it is to put too much power in the hands of purchasable items, which is why regulation via the Azurean Engram Act of the Eighth Era was put in-place. To put it short without delving into the act's details, this allowed Engrams to be under government control and regulated to meet "humane" standards, as one would put it bluntly. This act is especially useful for any body-enhancing augments, especially for live-saving ones.
<p>
Not only for the safety of the people, Engrams can also suffice and serve the purpose of ensuring that standardized and regulated technology spread across regions as massive as an entire star cluster can be controlled and easily used, providing much more user access than a traditional tinkering mindset one may want. Of course, there is a value of wanting more skills to argue over, but that is not for this datapad.
<p>
<hr>
<h1><u>Chapter 4</u></h1>
<h2>Engrams Used Today</h2>
<p>
Engrams are used widely across the galaxy, from small startup companies to larger galactic-spanning mega-corporations like Kinaris and Dzar. Many companies patent all of their technology beneath their own Engrams, and Kinaris is prominent for mimicking technology of previous civilizations into an Engram for their conversion process; such is the example of the crew of Layenia Station at Hyperion. Just about everywhere you look in Andromeda can be using at least a dozen Engrams in day to day technologies. From things as small as coffee machines and booze dispensers, to even full-blown vessels and capital ships, Engrams can dictate the shape and function of many day-to-day things!
<p>
<hr>
</body>
</html>
"}
@@ -478,8 +478,8 @@ GLOBAL_LIST_INIT(cardboard_recipes, list ( \
null, \
new/datum/stack_recipe("colored brown", /obj/item/storage/box/brown), \
new/datum/stack_recipe("colored green", /obj/item/storage/box/green), \
new/datum/stack_recipe("colored red", /obj/item/storage/box/blue), \
new/datum/stack_recipe("colored blue", /obj/item/storage/box/red), \
new/datum/stack_recipe("colored red", /obj/item/storage/box/red), \
new/datum/stack_recipe("colored blue", /obj/item/storage/box/blue), \
new/datum/stack_recipe("colored yellow", /obj/item/storage/box/yellow), \
new/datum/stack_recipe("colored pink", /obj/item/storage/box/pink), \
new/datum/stack_recipe("colored purple", /obj/item/storage/box/purple), \
@@ -209,3 +209,15 @@
sheet_type = /obj/item/stack/tile/bronze
sheet_amount = 2
girder_type = /obj/structure/girder/bronze
/turf/closed/wall/mineral/lead
name = "lead lined metal wall"
desc = "A hefty wall with lead inserts."
icon = 'icons/turf/walls/riveted.dmi'
icon_state = "riveted"
sheet_type = /obj/item/stack/rods
hardness = 10
girder_type = /obj/structure/girder/reinforced
explosion_block = 2
rad_insulation = RAD_NEAR_FULL_INSULATION
canSmoothWith = list(/turf/closed/wall/mineral/lead)
+4 -4
View File
@@ -107,21 +107,21 @@
/datum/bounty/item/medical/advhealthscaner
name = "Advanced Health Analyzer"
description = "A ERT Medical unit needs the new 'advanced health analyzer', for a mission at a Station 4. Can you send some?."
description = "An ERT Medical unit needs the new 'advanced health analyzer' for a mission at a Station 4. Can you send some?."
reward = 3000
required_count = 5
wanted_types = list(/obj/item/healthanalyzer/advanced)
/datum/bounty/item/medical/wallmounts
name = "Defibrillator wall mounts"
description = "New Space OSHA regulation state that are new cloning medical wing needs a few 'Easy to access defibrillartors'. Can you send a few before we get a lawsuit?"
description = "New Safety Review Board regulations state that our new medical wing needs 'easy to access defibrillators'. Can you send a few before we get a lawsuit?"
reward = 2000
required_count = 3
wanted_types = list(/obj/machinery/defibrillator_mount)
/datum/bounty/item/medical/defibrillator
name = "New defibillators"
description = "After years of storage are defibrillator units have become more liabilities then we want. Please send us some new ones to replace these old ones."
name = "New defibrillators"
description = "After years of storage our defibrillator units have become more of a liability then we want. Please send us some new ones to replace them."
reward = 2250
required_count = 5
wanted_types = list(/obj/item/defibrillator)
+1 -1
View File
@@ -61,7 +61,7 @@
/datum/supply_pack/security/russianclothing
name = "Russian Surplus Clothing"
desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproff armor, a few union suits and some warm hats!"
desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproof armor, a few union suits and some warm hats!"
contraband = TRUE
cost = 5750 // Its basicly sec suits, good boots/gloves
contains = list(/obj/item/clothing/suit/security/officer/russian,
+1 -1
View File
@@ -12,7 +12,7 @@
var/removeDontImproveChance = 10 //chance the randomly created law replaces a random law instead of simply being added
var/shuffleLawsChance = 10 //chance the AI's laws are shuffled afterwards
var/botEmagChance = 10
var/announceEvent = ION_RANDOM // -1 means don't announce, 0 means have it randomly announce, 1 means it is announced
var/announceEvent = 1 // -1 means don't announce, 0 means have it randomly announce, 1 means it is announced
var/ionMessage = null
var/ionAnnounceChance = 33
announceWhen = 1
+1 -1
View File
@@ -448,7 +448,7 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
return FALSE
/datum/holiday/ramadan/getStationPrefix()
return pick("Harm","Halaal","Jihad","Muslim")
return pick("Fasting","Enlightenment","Prayer","Muslim")
/datum/holiday/ramadan/end
name = "End of Ramadan"
@@ -40,7 +40,6 @@
update_damage_overlays()
else
adjustStaminaLoss(damage * hit_percent)
//citadel code
if(AROUSAL)
adjustArousalLoss(damage * hit_percent)
return TRUE
@@ -62,7 +61,6 @@
amount += BP.burn_dam
return amount
/mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
if (!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL))
return FALSE
+12 -1
View File
@@ -729,8 +729,19 @@
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#000000")
cut_overlay(MA)
//medical scan animation
/mob/living/carbon/human/proc/scan_animation()
var/mutable_appearance/scan_anim
scan_anim = mutable_appearance(icon, "mediscan")
add_overlay(scan_anim)
addtimer(CALLBACK(src, .proc/end_scan_animation, scan_anim), 10)
flick(icon,src)
/mob/living/carbon/human/proc/end_scan_animation(mutable_appearance/MA)
cut_overlay(MA)
/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated() || lying )
if(incapacitated())
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
return FALSE
if(!Adjacent(M) && (M.loc != src))
+3 -1
View File
@@ -57,7 +57,6 @@
if(STAMINA)
return getStaminaLoss()
/mob/living/proc/apply_damages(brute = 0, burn = 0, tox = 0, oxy = 0, clone = 0, def_zone = null, blocked = FALSE, stamina = 0, brain = 0)
if(blocked >= 100)
return 0
@@ -230,6 +229,9 @@
/mob/living/proc/setStaminaLoss(amount, updating_stamina = TRUE, forced = FALSE)
return
/mob/living/proc/adjustPainLoss(amount, updating_health = TRUE, forced = FALSE)
return
// heal ONE external organ, organ gets randomly selected from damaged ones.
/mob/living/proc/heal_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE)
adjustBruteLoss(-brute, FALSE) //zero as argument for no instant health update
-45
View File
@@ -160,15 +160,6 @@
emote_type = EMOTE_AUDIBLE
stat_allowed = UNCONSCIOUS
/datum/emote/living/gasp/run_emote(mob/user, params)
. = ..()
if(. && ishuman(user))
var/mob/living/carbon/C = user
if(user.gender == FEMALE)
playsound(C, pick('hyperstation/sound/voice/emotes/gasp_female1.ogg', 'hyperstation/sound/voice/emotes/gasp_female2.ogg', 'hyperstation/sound/voice/emotes/gasp_female3.ogg', 'hyperstation/sound/voice/emotes/gasp_female4.ogg', 'hyperstation/sound/voice/emotes/gasp_female5.ogg', 'hyperstation/sound/voice/emotes/gasp_female6.ogg', 'hyperstation/sound/voice/emotes/gasp_female7.ogg'), 50, 1)
else
playsound(C, pick('hyperstation/sound/voice/emotes/gasp_male1.ogg', 'hyperstation/sound/voice/emotes/gasp_male2.ogg', 'hyperstation/sound/voice/emotes/gasp_male3.ogg', 'hyperstation/sound/voice/emotes/gasp_male4.ogg', 'hyperstation/sound/voice/emotes/gasp_male5.ogg', 'hyperstation/sound/voice/emotes/gasp_male6.ogg', 'hyperstation/sound/voice/emotes/gasp_male7.ogg'), 50, 1)
/datum/emote/living/giggle
key = "giggle"
key_third_person = "giggles"
@@ -176,17 +167,6 @@
message_mime = "giggles silently!"
emote_type = EMOTE_AUDIBLE
/datum/emote/living/giggle/run_emote(mob/user, params)
. = ..()
if(. && ishuman(user))
var/mob/living/carbon/C = user
if(!C.mind || C.mind.miming)
return
if(user.gender == FEMALE)
playsound(C, pick('hyperstation/sound/voice/emotes/female_giggle1.ogg', 'hyperstation/sound/voice/emotes/female_giggle2.ogg'), 50, 1)
else
playsound(C, pick('hyperstation/sound/voice/emotes/male_laugh3b.ogg'), 50, 1)
/datum/emote/living/glare
key = "glare"
key_third_person = "glares"
@@ -249,11 +229,6 @@
'sound/voice/catpeople/nyahehe.ogg'),
50, 1)
return
if(ishumanbasic(C))
if(user.gender == FEMALE)
playsound(C, pick('hyperstation/sound/voice/emotes/female_laugh1.ogg', 'hyperstation/sound/voice/emotes/female_laugh2.ogg', 'hyperstation/sound/voice/emotes/female_laugh3.ogg', 'hyperstation/sound/voice/emotes/female_laugh4.ogg'), 50, 1)
else
playsound(C, pick('hyperstation/sound/voice/emotes/male_laugh1.ogg', 'hyperstation/sound/voice/emotes/male_laugh1b.ogg', 'hyperstation/sound/voice/emotes/male_laugh2.ogg', 'hyperstation/sound/voice/emotes/male_laugh2b.ogg',/*'hyperstation/sound/voice/emotes/male_laugh3.ogg',*/'hyperstation/sound/voice/emotes/male_laugh3b.ogg', 'hyperstation/sound/voice/emotes/male_laugh4.ogg'), 50, 1)
/datum/emote/living/look
key = "look"
@@ -330,11 +305,6 @@
var/mob/living/carbon/C = user
if(!C.mind || C.mind.miming)
return
if(ishumanbasic(C))
if(user.gender == FEMALE)
playsound(C, pick('hyperstation/sound/voice/emotes/sigh_female.ogg'), 50, 1)
else
playsound(C, pick('hyperstation/sound/voice/emotes/sigh_male.ogg'), 50, 1)
/datum/emote/living/sit
key = "sit"
@@ -364,11 +334,6 @@
var/mob/living/carbon/C = user
if(!C.mind || C.mind.miming)//mimes can't sneeze because fuck you that's why
return
if(ishumanbasic(C))
if(user.gender == FEMALE)
playsound(C, pick('hyperstation/sound/voice/emotes/sneezef1.ogg', 'hyperstation/sound/voice/emotes/sneezef2.ogg'), 50, 1)
else
playsound(C, pick('hyperstation/sound/voice/emotes/sneezem1.ogg', 'hyperstation/sound/voice/emotes/sneezem2.ogg'), 50, 1)
/datum/emote/living/smug
key = "smug"
@@ -462,11 +427,6 @@
var/mob/living/carbon/C = user
if(!C.mind || C.mind.miming)
return
if(ishumanbasic(C))
if(user.gender == FEMALE)
playsound(C, pick('hyperstation/sound/voice/emotes/whimper_female1.ogg', 'hyperstation/sound/voice/emotes/whimper_female2.ogg', 'hyperstation/sound/voice/emotes/whimper_female3.ogg'), 50, 1)
else
playsound(C, pick('hyperstation/sound/voice/emotes/whimper_male1.ogg', 'hyperstation/sound/voice/emotes/whimper_male2.ogg', 'hyperstation/sound/voice/emotes/whimper_male3.ogg'), 50, 1)
/datum/emote/living/wsmile
key = "wsmile"
@@ -485,11 +445,6 @@
var/mob/living/carbon/C = user
if(!C.mind || C.mind.miming)
return
if(ishumanbasic(C))
if(user.gender == FEMALE)
playsound(C, pick('hyperstation/sound/voice/emotes/female_yawn1.ogg', 'hyperstation/sound/voice/emotes/female_yawn2.ogg', 'hyperstation/sound/voice/emotes/female_yawn3.ogg'), 50, 1)
else
playsound(C, pick('hyperstation/sound/voice/emotes/male_yawn1.ogg', 'hyperstation/sound/voice/emotes/male_yawn2.ogg'), 50, 1)
/datum/emote/living/custom
key = "me"
+16 -1
View File
@@ -502,6 +502,10 @@
var/obj/effect/proc_holder/spell/spell = S
spell.updateButtonIcon()
if(iscarbon(src)) //pain cooldown
var/mob/living/carbon/C = src
C.pain_cooldown = 20
//proc used to completely heal a mob.
/mob/living/proc/fully_heal(admin_revive = 0)
restore_blood()
@@ -542,6 +546,13 @@
for(var/organ in C.internal_organs)
var/obj/item/organ/O = organ
O.setOrganDamage(0)
//Heal pain
if(iscarbon(src))
var/mob/living/carbon/C = src
for(var/obj/item/bodypart/X in C.bodyparts)
X.pain_dam = 0
SEND_SIGNAL(src, COMSIG_LIVING_FULLY_HEAL, admin_revive)
//fuck shitcode I hate shitcode
@@ -1086,7 +1097,11 @@
lying = 90*buckle_lying
else if(!lying)
if(resting)
lying = pick(90, 270) // Cit change - makes resting not force you to drop your held items
if(dir == 2 || dir == 4)
lying = 90
else
lying = 270
if(has_gravity()) // Cit change - Ditto
playsound(src, "bodyfall", 50, 1) // Cit change - Ditto!
else if(ko || move_and_fall || (!has_legs && !ignore_legs) || chokehold)
@@ -25,8 +25,7 @@
disabler = FALSE
update_icons() //PUT THE GUN AWAY
else if(istype(O,/obj/item/dogborg/sleeper))
sleeper_g = FALSE
sleeper_r = FALSE
sleeper_state = BORGBELLY_NONE
update_icons()
var/obj/item/dogborg/sleeper/S = O
S.go_out() //this should stop edgecase deletions
@@ -654,10 +654,14 @@
if(disabler)
add_overlay("disabler")//ditto
if(sleeper_g && module.sleeper_overlay)
add_overlay("[module.sleeper_overlay]_g[sleeper_nv ? "_nv" : ""]")
if(sleeper_r && module.sleeper_overlay)
add_overlay("[module.sleeper_overlay]_r[sleeper_nv ? "_nv" : ""]")
if(module.sleeper_overlay)
var/sleeper_overlay_state = ""
switch(sleeper_state)
if(BORGBELLY_NONE) sleeper_overlay_state = ""
if(BORGBELLY_GREEN) sleeper_overlay_state = "_g"
if(BORGBELLY_RED) sleeper_overlay_state = "_r"
add_overlay("[module.sleeper_overlay][sleeper_overlay_state]")
if(module.dogborg == TRUE)
if(resting)
cut_overlays()
@@ -0,0 +1,263 @@
#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/body_color
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)
ADD_TRAIT(src, TRAIT_SHOCKIMMUNE, INNATE_TRAIT)
access_card = new /obj/item/card/id(src)
var/datum/job/captain/C = new /datum/job/captain
access_card.access = C.get_access()
if(!body_color)
body_color = pick(list("orange","blue","purple", "green", "crystal"))
AddElement(/datum/element/mob_holder, "gremlin_[body_color]")
icon_state = "gremlin_[body_color]"
icon_living = "gremlin_[body_color]"
icon_dead = "gremlin_[body_color]_dead"
/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)
QDEL_NULL(access_card)
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/ai/beep.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
+4 -4
View File
@@ -197,7 +197,7 @@
var/static_power_used = 0
var/brightness = 8 // luminosity when on, also used in power calculation
var/bulb_power = 1 // basically the alpha of the emitted light source
var/bulb_colour = "#FFFFFF" // befault colour of the light.
var/bulb_colour = "#ffefda" // befault colour of the light.
var/status = LIGHT_OK // LIGHT_OK, _EMPTY, _BURNED or _BROKEN
var/flickering = FALSE
var/light_type = /obj/item/light/tube // the type of light item
@@ -212,13 +212,13 @@
var/nightshift_enabled = FALSE //Currently in night shift mode?
var/nightshift_allowed = TRUE //Set to FALSE to never let this light get switched to night mode.
var/nightshift_brightness = 8
var/nightshift_brightness = 7
var/nightshift_light_power = 0.45
var/nightshift_light_color = "#FFDDCC"
var/nightshift_light_color = "#dafcff"
var/emergency_mode = FALSE // if true, the light is in emergency mode
var/no_emergency = FALSE // if true, this light cannot ever have an emergency mode
var/bulb_emergency_brightness_mul = 0.25 // multiplier for this light's base brightness in emergency power mode
var/bulb_emergency_brightness_mul = 0.6 // multiplier for this light's base brightness in emergency power mode
var/bulb_emergency_colour = "#FF3232" // determines the colour of the light while it's in emergency mode
var/bulb_emergency_pow_mul = 0.75 // the multiplier for determining the light's power in emergency mode
var/bulb_emergency_pow_min = 0.5 // the minimum value for the light's power in emergency mode
@@ -36,6 +36,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
*/
/datum/reagent/consumable/ethanol/on_mob_life(mob/living/carbon/C)
C.adjustPainLoss(-0.25*REM, 0) //alchol dulls pain
if(C.drunkenness < volume * boozepwr * ALCOHOL_THRESHOLD_MODIFIER)
var/booze_power = boozepwr
if(HAS_TRAIT(C, TRAIT_ALCOHOL_TOLERANCE)) //we're an accomplished drinker
@@ -1001,3 +1001,5 @@
glass_desc = "A Summer time drink that can be frozen and eaten or Drinked from a glass!"
glass_name = "Orange Creamsicle"
hydration = 4
@@ -391,6 +391,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
/datum/reagent/medicine/mine_salve/on_mob_life(mob/living/carbon/C)
C.hal_screwyhud = SCREWYHUD_HEALTHY
C.adjustBruteLoss(-0.25*REM, 0)
C.adjustPainLoss(-1*REM, 0)
C.adjustFireLoss(-0.25*REM, 0)
C.adjustStaminaLoss(-0.5*REM, 0)
..()
@@ -698,7 +699,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
/datum/reagent/medicine/morphine
name = "Morphine"
description = "A painkiller that allows the patient to move at full speed even in bulky objects. Causes drowsiness and eventually unconsciousness in high doses. Overdose will cause a variety of effects, ranging from minor to lethal."
description = "A painkiller. Causes drowsiness and eventually unconsciousness in high doses. Overdose will cause a variety of effects, ranging from minor to lethal."
reagent_state = LIQUID
color = "#A9FBFB"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
@@ -706,23 +707,8 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
addiction_threshold = 25
pH = 8.96
/datum/reagent/medicine/morphine/on_mob_metabolize(mob/living/L)
..()
L.ignore_slowdown(type)
/datum/reagent/medicine/morphine/on_mob_end_metabolize(mob/living/L)
L.unignore_slowdown(type)
..()
/datum/reagent/medicine/morphine/on_mob_life(mob/living/carbon/M)
switch(current_cycle)
if(11)
to_chat(M, "<span class='warning'>You start to feel tired...</span>" )
if(12 to 24)
M.drowsyness += 1
if(24 to INFINITY)
M.Sleeping(40, 0)
. = 1
M.adjustPainLoss(-3*REM, 0)// very good pain killer.
..()
/datum/reagent/medicine/morphine/overdose_process(mob/living/M)
@@ -1022,6 +1008,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
/datum/reagent/medicine/bicaridine/on_mob_life(mob/living/carbon/M)
M.adjustBruteLoss(-2*REM, 0)
M.adjustPainLoss(-1*REM, 0) //stabilize pain at threshold. and bring it down faster if above.
..()
. = 1
@@ -158,10 +158,10 @@
var/altered_height
altered_height = input(user, "Choose your desired sprite size:\n([MIN_BODYSIZE]-400%)", "Height Alteration") as num|null
if(altered_height)
H.size_multiplier = (max(min( round(text2num(altered_height)),400),MIN_BODYSIZE))/100
H.size_multiplier = (max(min( round(text2num(altered_height)),1000),MIN_BODYSIZE))/100
playsound(user.loc, pshoom_or_beepboopblorpzingshadashwoosh, 40, 1)
do_sparks(5, FALSE, user.loc)
H.visible_message("<span class='danger'>[pick("[H] shifts in size!", "[H] alters in height!", "[H] reshapes into a new stature!")]</span>")
else
return
return
@@ -31,6 +31,7 @@
var/burnstate = 0
var/brute_dam = 0
var/burn_dam = 0
var/pain_dam = 0
var/stamina_dam = 0
var/max_stamina_damage = 0
var/max_damage = 0
@@ -193,6 +194,9 @@
brute_dam += brute
burn_dam += burn
if(status == BODYPART_ORGANIC) //pain is only applied to organic organs, because nerves.
pain_dam += (brute+burn)*1.2 //add the total damage applied to the limb as pain damage, build pain quicker, because sudden pain is more.. painful.
//We've dealt the physical damages, if there's room lets apply the stamina damage.
var/current_damage = get_damage(TRUE) //This time around, count stamina loss too.
var/available_damage = max_damage - current_damage
+8 -3
View File
@@ -172,9 +172,14 @@
// lipstick
if(lip_style)
var/image/lips_overlay = image('icons/mob/human_face.dmi', "lips_[lip_style]", -BODY_LAYER, SOUTH)
lips_overlay.color = lip_color
. += lips_overlay
if (species_id == "human")
var/image/lips_overlay = image('icons/mob/human_face.dmi', "lips_[lip_style]", -BODY_LAYER, SOUTH)
lips_overlay.color = lip_color
. += lips_overlay
else //for animal species, because they have slightly bigger heads.
var/image/lips_overlay = image('icons/mob/human_face.dmi', "lips_[lip_style]_mam", -BODY_LAYER, SOUTH)
lips_overlay.color = lip_color
. += lips_overlay
// eyes
var/image/eyes_overlay = image('icons/mob/human_face.dmi', "eyes", -BODY_LAYER, SOUTH)
+2 -2
View File
@@ -1,8 +1,8 @@
//make incision
/datum/surgery_step/incise
name = "make incision"
implements = list(TOOL_SCALPEL = 100, /obj/item/melee/transforming/energy/sword = 75, /obj/item/kitchen/knife = 65,
/obj/item/shard = 45, /obj/item = 30) // 30% success with any sharp item.
implements = list(TOOL_SCALPEL = 100, /obj/item/melee/transforming/energy/sword = 85, /obj/item/kitchen/knife = 75,
/obj/item/shard = 65, /obj/item = 40) // 40% success with any sharp item. (Hyper change, raised chances with basic items, because if user is awake it has a higher chance to fail)
time = 16
/datum/surgery_step/incise/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+16 -5
View File
@@ -9,6 +9,7 @@
var/list/chems_needed = list() //list of chems needed to complete the step. Even on success, the step will have no effect if there aren't the chems required in the mob.
var/require_all_chems = TRUE //any on the list or all on the list?
var/silicons_obey_prob = FALSE
var/pain_failure = 10 //how painful it is if you fail.
/datum/surgery_step/proc/try_op(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
var/success = FALSE
@@ -62,14 +63,21 @@
var/prob_chance = 100
if(implement_type) //this means it isn't a require hand or any item step.
prob_chance = implements[implement_type]
prob_chance *= surgery.get_propability_multiplier()
//if human and awake
if (ishuman(target))
var/mob/living/carbon/human/H = target
if(H.stat == 0) //victorian surgery
prob_chance = prob_chance *0.65 //deminish your chances, they are awake!
if((prob(prob_chance) || (iscyborg(user) && !silicons_obey_prob)) && chem_check(target) && !try_to_fail)
if(success(user, target, target_zone, tool, surgery))
advance = TRUE
else
if(failure(user, target, target_zone, tool, surgery))
advance = TRUE
advance = FALSE
if(advance && !repeatable)
surgery.status++
if(surgery.status > surgery.steps.len)
@@ -83,15 +91,18 @@
"[user] begins to perform surgery on [target].")
/datum/surgery_step/proc/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "<span class='notice'>You succeed.</span>",
"[user] succeeds!",
display_results(user, target, "<span class='notice'>You complete the procedure.</span>",
"[user] completes the procedure!",
"[user] finishes.")
return TRUE
/datum/surgery_step/proc/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "<span class='warning'>You screw up!</span>",
"<span class='warning'>[user] screws up!</span>",
display_results(user, target, "<span class='warning'>You failed the procedure!</span>",
"<span class='warning'>[user] failed the procedure!</span>",
"[user] finishes.", TRUE) //By default the patient will notice if the wrong thing has been cut
if (ishuman(target)) //pain on humans for messing up.
var/obj/item/bodypart/L = target.get_bodypart(target_zone)
L.pain_dam += pain_failure
return FALSE
/datum/surgery_step/proc/tool_check(mob/user, obj/item/tool)
+2 -1
View File
@@ -46,7 +46,8 @@
/obj/item/seeds/tower = 3,
/obj/item/seeds/watermelon = 3,
/obj/item/seeds/wheat = 3,
/obj/item/seeds/whitebeet = 3)
/obj/item/seeds/whitebeet = 3,
/obj/item/seeds/kalyna = 3) //Hyperstation addition
contraband=list(/obj/item/seeds/amanita = 2,
/obj/item/seeds/glowshroom = 2,