"
- dat += "Scan ID [active_record.fields["id"]] \
- [!body_only ? "Clone" : "" ]\
- Empty Clone "
+ dat += "
[src.active_record.fields["name"]]
"
+ dat += "Scan ID [src.active_record.fields["id"]] Clone "
var/obj/item/implant/health/H = locate(src.active_record.fields["imp"])
@@ -250,14 +239,7 @@
dat += "Unable to locate Health Implant.
"
dat += "Unique Identifier: [src.active_record.fields["UI"]] "
- dat += "Structural Enzymes: "
- for(var/key in active_record.fields["SE"])
- if(key != RACEMUT)
- var/val = active_record.fields["SE"][key]
- var/alias = GLOB.all_mutations[key].alias
- dat +="[alias]: [val] "
-
- dat += " "
+ dat += "Structural Enzymes: [src.active_record.fields["SE"]] "
if(diskette && diskette.fields)
dat += "
"
@@ -314,13 +296,18 @@
else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational())
scantemp = ""
- var/body_only = href_list["body_only"]
+
loading = 1
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
- addtimer(CALLBACK(src, .proc/do_scan, usr, body_only), 2 SECONDS)
+ spawn(20)
+ src.scan_occupant(scanner.occupant)
+
+ loading = 0
+ src.updateUsrDialog()
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
//No locking an open scanner.
@@ -336,42 +323,34 @@
playsound(src, "terminal_type", 25, 0)
src.active_record = find_record("id", href_list["view_rec"], records)
if(active_record)
- menu = 3
+ if(!active_record.fields["ckey"])
+ records -= active_record
+ active_record = null
+ src.temp = "Record Corrupt"
+ else
+ src.menu = 3
else
- temp = "Record missing."
+ src.temp = "Record missing."
else if (href_list["del_rec"])
if ((!src.active_record) || (src.menu < 3))
return
if (src.menu == 3) //If we are viewing a record, confirm deletion
- var/has_access = FALSE
- if(ishuman(usr))
- var/mob/living/carbon/human/user = usr
- var/obj/item/card/id/C = user.get_idcard(TRUE)
- if(C)
- if(check_access(C))
- has_access = TRUE
- if(active_record.fields["body_only"]) //Body-only scans are not as important and can be deleted freely
- has_access = TRUE
- if(has_access)
- temp = "Delete record?"
- menu = 4
- playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
- else
- temp = "Access Denied"
- menu = 2
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ src.temp = "Delete record?"
+ src.menu = 4
+ playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
else if (src.menu == 4)
var/obj/item/card/id/C = usr.get_active_held_item()
if (istype(C)||istype(C, /obj/item/pda))
if(src.check_access(C))
- log_cloning("[key_name(usr)] deleted [key_name(active_record.fields["mindref"])]'s cloning records from [src] at [AREACOORD(src)].")
src.temp = "[src.active_record.fields["name"]] => Record deleted."
src.records.Remove(active_record)
active_record = null
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
src.menu = 2
+ var/obj/item/circuitboard/computer/cloning/board = circuit
+ board.records = records
else
src.temp = "Access Denied."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
@@ -421,14 +400,9 @@
else if (href_list["clone"])
var/datum/data/record/C = find_record("id", href_list["clone"], records)
- var/empty = href_list["empty"]
//Look for that player! They better be dead!
if(C)
- if(C.fields["body_only"] && !empty)
- temp = "Cannot initiate regular cloning with body-only scans."
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
var/obj/machinery/clonepod/pod = GetAvailablePod()
- var/success = FALSE
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
if(!LAZYLEN(pods))
temp = "No Clonepods detected."
@@ -436,33 +410,20 @@
else if(!pod)
temp = "No Clonepods available."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
- else if(!CONFIG_GET(flag/revival_cloning) && !empty)
+ else if(!CONFIG_GET(flag/revival_cloning))
temp = "Unable to initiate cloning cycle."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else if(pod.occupant)
temp = "Cloning cycle already in progress."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"]))
+ temp = "[C.fields["name"]] => Cloning cycle in progress..."
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ records.Remove(C)
+ if(active_record == C)
+ active_record = null
+ menu = 1
else
- var/result = grow_clone_from_record(pod, C, empty)
- if(result & CLONING_SUCCESS)
- temp = "[C.fields["name"]] => Cloning cycle in progress..."
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
- records.Remove(C)
- if(active_record == C)
- active_record = null
- menu = 1
- success = TRUE
- if(!empty)
- log_cloning("[key_name(usr)] initiated cloning of [key_name(C.fields["mindref"])] via [src] at [AREACOORD(src)]. Pod: [pod] at [AREACOORD(pod)].")
- else
- log_cloning("[key_name(usr)] initiated EMPTY cloning of [key_name(C.fields["mindref"])] via [src] at [AREACOORD(src)]. Pod: [pod] at [AREACOORD(pod)].")
- if(result & CLONING_DELETE_RECORD)
- if(active_record == C)
- active_record = null
- menu = 1
- records -= C
-
- if(!success)
temp = "[C.fields["name"]] => Initialisation failure."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
@@ -478,31 +439,21 @@
src.updateUsrDialog()
return
-/obj/machinery/computer/cloning/proc/do_scan(mob/user, body_only)
- scan_occupant(scanner.occupant, user, body_only)
-
- loading = FALSE
- updateUsrDialog()
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
-
-/obj/machinery/computer/cloning/proc/scan_occupant(occupant, mob/M, body_only)
+/obj/machinery/computer/cloning/proc/scan_occupant(occupant)
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
var/datum/dna/dna
-
- // Do not use unless you know what they are.
- var/mob/living/carbon/C = mob_occupant
- var/mob/living/brain/B = mob_occupant
-
if(ishuman(mob_occupant))
+ var/mob/living/carbon/C = mob_occupant
dna = C.has_dna()
if(isbrain(mob_occupant))
+ var/mob/living/brain/B = mob_occupant
dna = B.stored_dna
if(!istype(dna))
scantemp = "Unable to locate valid genetic data."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
- if(!body_only && (mob_occupant.suiciding || mob_occupant.hellbound))
+ if(mob_occupant.suiciding || mob_occupant.hellbound)
scantemp = "Subject's brain is not responding to scanning stimuli."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
@@ -510,14 +461,14 @@
scantemp = "Subject no longer contains the fundamental materials required to create a living clone."
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
return
- if (!body_only && isnull(mob_occupant.mind))
+ if ((!mob_occupant.ckey) || (!mob_occupant.client))
scantemp = "Mental interface failure."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
return
-// if (find_record("ckey", mob_occupant.ckey, records))
-// scantemp = "Subject already in database."
-// playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
-// return
+ if (find_record("ckey", mob_occupant.ckey, records))
+ scantemp = "Subject already in database."
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ return
var/datum/data/record/R = new()
if(dna.species)
@@ -530,7 +481,7 @@
var/datum/species/rando_race = pick(GLOB.roundstart_races)
R.fields["mrace"] = rando_race.type
- //R.fields["ckey"] = mob_occupant.ckey
+ R.fields["ckey"] = mob_occupant.ckey
R.fields["name"] = mob_occupant.real_name
R.fields["id"] = copytext(md5(mob_occupant.real_name), 2, 6)
R.fields["UE"] = dna.unique_enzymes
@@ -544,32 +495,22 @@
var/datum/quirk/T = V
R.fields["quirks"][T.type] = T.clone_data()
- R.fields["mindref"] = "[REF(mob_occupant.mind)]"
- R.fields["last_death"] = mob_occupant.stat == DEAD ? mob_occupant.mind.last_death : -1
- R.fields["body_only"] = body_only
+ if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning.
+ R.fields["mind"] = "[REF(mob_occupant.mind)]"
- if(!body_only)
- //Add an implant if needed
- var/obj/item/implant/health/imp
- for(var/obj/item/implant/health/HI in mob_occupant.implants)
- imp = HI
- break
- if(!imp)
- imp = new /obj/item/implant/health(mob_occupant)
- imp.implant(mob_occupant)
- R.fields["imp"] = "[REF(imp)]"
+ //Add an implant if needed
+ var/obj/item/implant/health/imp
+ for(var/obj/item/implant/health/HI in mob_occupant.implants)
+ imp = HI
+ break
+ if(!imp)
+ imp = new /obj/item/implant/health(mob_occupant)
+ imp.implant(mob_occupant)
+ R.fields["imp"] = "[REF(imp)]"
- var/datum/data/record/old_record = find_record("mindref", REF(mob_occupant.mind), records)
- if(body_only)
- old_record = find_record("UE", dna.unique_enzymes, records) //Body-only records cannot be identified by mind, so we use the DNA
- if(old_record && ((old_record.fields["UI"] != dna.uni_identity) || (!old_record.fields["body_only"]))) //Never overwrite a mind-and-body record if it exists
- old_record = null
- if(old_record)
- records -= old_record
- scantemp = "Record updated."
- else
- scantemp = "Subject successfully scanned."
src.records += R
- log_cloning("[M ? key_name(M) : "Autoprocess"] added the [body_only ? "body-only " : ""]record of [key_name(mob_occupant)] to [src] at [AREACOORD(src)].")
+ var/obj/item/circuitboard/computer/cloning/board = circuit
+ board.records = records
+ scantemp = "Subject successfully scanned."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm
index b9b95eec..e53e3cb4 100644
--- a/code/game/machinery/computer/teleporter.dm
+++ b/code/game/machinery/computer/teleporter.dm
@@ -124,12 +124,12 @@
L[avoid_assoc_duplicate_keys(A.name, areaindex)] = R
for(var/obj/item/implant/tracking/I in GLOB.tracked_implants)
- if(!I.imp_in || !isliving(I.loc))
+ if(!I.imp_in || !I.allow_teleport || !isliving(I.imp_in))
continue
else
var/mob/living/M = I.loc
if(M.stat == DEAD)
- if(M.timeofdeath + 6000 < world.time)
+ if(M.timeofdeath + I.lifespan_postmortem < world.time)
continue
if(is_eligible(I))
L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = I
diff --git a/code/game/machinery/exp_cloner.dm b/code/game/machinery/exp_cloner.dm
index d5388035..baa7ed27 100644
--- a/code/game/machinery/exp_cloner.dm
+++ b/code/game/machinery/exp_cloner.dm
@@ -9,7 +9,7 @@
internal_radio = FALSE
//Start growing a human clone in the pod!
-/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance)
+/obj/machinery/clonepod/experimental/growclone(ckey, clonename, ui, se, datum/species/mrace, list/features, factions)
if(panel_open)
return FALSE
if(mess || attempting)
@@ -20,7 +20,7 @@
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
- H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
+ H.hardset_dna(ui, se, H.real_name, null, mrace, features)
if(efficiency > 2)
var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations)
@@ -292,7 +292,7 @@
temp = "Cloning cycle already in progress."
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
- pod.growclone(mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
+ pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.mutation_index, clone_species, dna.features, mob_occupant.faction)
temp = "[mob_occupant.real_name] => Cloning data sent to pod."
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index 6bf9930e..566613b1 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -180,7 +180,7 @@ GLOBAL_LIST_EMPTY(allCasters)
/obj/machinery/newscaster
name = "newscaster"
- desc = "A standard Nanotrasen-licensed newsfeed handler for use in commercial space stations. All the news you absolutely have no use for, in one place!"
+ desc = "A standard Kinaris-licensed newsfeed handler for use in commercial space stations. All the news you absolutely have no use for, in one place!"
icon = 'icons/obj/terminals.dmi'
icon_state = "newscaster_normal"
verb_say = "beeps"
@@ -271,7 +271,7 @@ GLOBAL_LIST_EMPTY(allCasters)
switch(screen)
if(0)
dat += "Welcome to Newscasting Unit #[unit_no]. Interface & News networks Operational."
- dat += " Property of Nanotrasen Inc"
+ dat += " Property of Kinaris Corp"
if(GLOB.news_network.wanted_issue.active)
dat+= "Read Wanted Issue"
dat+= " Create Feed Channel"
@@ -616,14 +616,14 @@ GLOBAL_LIST_EMPTY(allCasters)
screen = 15
else
if(GLOB.news_network.wanted_issue.isAdminMsg)
- alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot edit it.","Ok")
+ alert("The wanted issue has been distributed by a Kinaris higherup. You cannot edit it.","Ok")
return
GLOB.news_network.submitWanted(channel_name, msg, scanned_user, picture)
screen = 19
updateUsrDialog()
else if(href_list["cancel_wanted"])
if(GLOB.news_network.wanted_issue.isAdminMsg)
- alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot take it down.","Ok")
+ alert("The wanted issue has been distributed by a Kinaris higherup. You cannot take it down.","Ok")
return
var/choice = alert("Please confirm Wanted Issue removal","Network Security Handler","Confirm","Cancel")
if(choice=="Confirm")
@@ -636,21 +636,21 @@ GLOBAL_LIST_EMPTY(allCasters)
else if(href_list["censor_channel_author"])
var/datum/newscaster/feed_channel/FC = locate(href_list["censor_channel_author"])
if(FC.is_admin_channel)
- alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok")
+ alert("This channel was created by a Kinaris Officer. You cannot censor it.","Ok")
return
FC.toggleCensorAuthor()
updateUsrDialog()
else if(href_list["censor_channel_story_author"])
var/datum/newscaster/feed_message/MSG = locate(href_list["censor_channel_story_author"])
if(MSG.is_admin_message)
- alert("This message was created by a Nanotrasen Officer. You cannot censor its author.","Ok")
+ alert("This message was created by a Kinaris Officer. You cannot censor its author.","Ok")
return
MSG.toggleCensorAuthor()
updateUsrDialog()
else if(href_list["censor_channel_story_body"])
var/datum/newscaster/feed_message/MSG = locate(href_list["censor_channel_story_body"])
if(MSG.is_admin_message)
- alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok")
+ alert("This channel was created by a Kinaris Officer. You cannot censor it.","Ok")
return
MSG.toggleCensorBody()
updateUsrDialog()
@@ -662,7 +662,7 @@ GLOBAL_LIST_EMPTY(allCasters)
else if(href_list["toggle_d_notice"])
var/datum/newscaster/feed_channel/FC = locate(href_list["toggle_d_notice"])
if(FC.is_admin_channel)
- alert("This channel was created by a Nanotrasen Officer. You cannot place a D-Notice upon it.","Ok")
+ alert("This channel was created by a Kinaris Officer. You cannot place a D-Notice upon it.","Ok")
return
FC.toggleCensorDclass()
updateUsrDialog()
@@ -864,7 +864,7 @@ GLOBAL_LIST_EMPTY(allCasters)
/obj/item/newspaper
name = "newspaper"
- desc = "An issue of The Griffon, the newspaper circulating aboard Nanotrasen Space Stations."
+ desc = "An issue of The Griffon, the newspaper circulating aboard Kin.Co Space Stations."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "newspaper"
lefthand_file = 'icons/mob/inhands/misc/books_lefthand.dmi'
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index 3051a72d..19e71bcf 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -210,13 +210,13 @@
add_fingerprint(user)
/obj/machinery/suit_storage_unit/proc/cook()
+ var/mob/living/mob_occupant = occupant
if(uv_cycles)
uv_cycles--
uv = TRUE
locked = TRUE
update_icon()
if(occupant)
- var/mob/living/mob_occupant = occupant
if(uv_super)
mob_occupant.adjustFireLoss(rand(20, 36))
else
@@ -245,6 +245,7 @@
visible_message("[src]'s door slides open. The glowing yellow lights dim to a gentle green.")
else
visible_message("[src]'s door slides open, barraging you with the nauseating smell of charred flesh.")
+ mob_occupant.radiation = 0
playsound(src, 'sound/machines/airlockclose.ogg', 25, 1)
for(var/obj/item/I in src) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
@@ -307,6 +308,9 @@
/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params)
if(state_open && is_operational())
+ if(istype(I, /obj/item/clothing/head/mob_holder))
+ to_chat(user, "You can't quite fit that while you hold it!")
+ return
if(istype(I, /obj/item/clothing/suit))
if(suit)
to_chat(user, "The unit already contains a suit!.")
diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm
index c52a0334..1da89fb3 100644
--- a/code/game/machinery/syndicatebeacon.dm
+++ b/code/game/machinery/syndicatebeacon.dm
@@ -1,3 +1,7 @@
+GLOBAL_VAR_INIT(singularity_counter, 0)
+
+#define METEOR_DISASTER_MODIFIER 0.5
+
////////////////////////////////////////
//Singularity beacon
////////////////////////////////////////
@@ -14,38 +18,58 @@
verb_say = "states"
var/cooldown = 0
- var/active = 0
+ var/active = FALSE
+ var/meteor_buff = FALSE
var/icontype = "beacon"
-
/obj/machinery/power/singularity_beacon/proc/Activate(mob/user = null)
+ if(active)
+ return FALSE
if(surplus() < 1500)
if(user)
to_chat(user, "The connected wire doesn't have enough current.")
- return
+ return FALSE
+ if(is_station_level(z))
+ increment_meteor_waves()
for(var/obj/singularity/singulo in GLOB.singularities)
if(singulo.z == z)
singulo.target = src
icon_state = "[icontype]1"
- active = 1
+ active = TRUE
if(user)
to_chat(user, "You activate the beacon.")
+ return TRUE
-
-/obj/machinery/power/singularity_beacon/proc/Deactivate(mob/user = null)
+/obj/machinery/power/singularity_beacon/proc/Deactivate(mob/user)
+ if(!active)
+ return FALSE
for(var/obj/singularity/singulo in GLOB.singularities)
if(singulo.target == src)
singulo.target = null
icon_state = "[icontype]0"
- active = 0
+ active = FALSE
if(user)
to_chat(user, "You deactivate the beacon.")
+ if(meteor_buff)
+ decrement_meteor_waves()
+ return TRUE
+
+/obj/machinery/power/singularity_beacon/proc/increment_meteor_waves()
+ meteor_buff = TRUE
+ GLOB.singularity_counter++
+ for(var/datum/round_event_control/meteor_wave/W in SSevents.control)
+ W.weight += round(initial(W.weight) * METEOR_DISASTER_MODIFIER)
+
+/obj/machinery/power/singularity_beacon/proc/decrement_meteor_waves()
+ meteor_buff = FALSE
+ GLOB.singularity_counter--
+ for(var/datum/round_event_control/meteor_wave/W in SSevents.control)
+ W.weight -= round(initial(W.weight) * METEOR_DISASTER_MODIFIER)
/obj/machinery/power/singularity_beacon/attack_ai(mob/user)
return
-
/obj/machinery/power/singularity_beacon/attack_hand(mob/user)
. = ..()
if(.)
@@ -86,6 +110,12 @@
if(!active)
return
+ var/is_on_station = is_station_level(z)
+ if(meteor_buff && !is_on_station)
+ decrement_meteor_waves()
+ else if(!meteor_buff && is_on_station)
+ increment_meteor_waves()
+
if(surplus() >= 1500)
add_load(1500)
if(cooldown <= world.time)
@@ -133,3 +163,5 @@
/obj/item/sbeacondrop/clownbomb
desc = "A label on it reads: Warning: Activating this device will send a silly explosive to your location."
droptype = /obj/machinery/syndicatebomb/badmin/clown
+
+#undef METEOR_DISASTER_MODIFIER
\ No newline at end of file
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index af9e47f5..69e244a6 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -219,6 +219,10 @@
update_icon()
return
+ if(istype(W, /obj/item/clothing/head/mob_holder))
+ to_chat(user, "It's too unweildy to put in this way.")
+ return 1
+
else if(user.a_intent != INTENT_HARM)
if (!state_open)
diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm
index fbe25c5d..a5fb01a9 100644
--- a/code/game/objects/effects/anomalies.dm
+++ b/code/game/objects/effects/anomalies.dm
@@ -11,7 +11,7 @@
var/obj/item/assembly/signaler/anomaly/aSignal
var/area/impact_area
- var/lifespan = 990
+ var/lifespan = 1190
var/death_time
var/countdown_colour
diff --git a/code/game/objects/effects/contraband.dm b/code/game/objects/effects/contraband.dm
index 50d40697..884fe7b3 100644
--- a/code/game/objects/effects/contraband.dm
+++ b/code/game/objects/effects/contraband.dm
@@ -178,7 +178,7 @@
/obj/structure/sign/poster/contraband
poster_item_name = "contraband poster"
- poster_item_desc = "This poster comes with its own automatic adhesive mechanism, for easy pinning to any vertical surface. Its vulgar themes have marked it as contraband aboard Nanotrasen space facilities."
+ poster_item_desc = "This poster comes with its own automatic adhesive mechanism, for easy pinning to any vertical surface. Its vulgar themes have marked it as contraband aboard space facilities."
poster_item_icon_state = "rolled_poster"
/obj/structure/sign/poster/contraband/random
@@ -264,7 +264,7 @@
/obj/structure/sign/poster/contraband/power
name = "Power"
- desc = "A poster that positions the seat of power outside Nanotrasen."
+ desc = "A poster that positions the seat of power outside Kinaris.Co."
icon_state = "poster16"
/obj/structure/sign/poster/contraband/space_cube
@@ -425,8 +425,8 @@
icon_state = "poster1_legit"
/obj/structure/sign/poster/official/nanotrasen_logo
- name = "Nanotrasen Logo"
- desc = "A poster depicting the Nanotrasen logo."
+ name = "Kinaris Logo"
+ desc = "A poster depicting the Kinaris.Co logo."
icon_state = "poster2_legit"
/obj/structure/sign/poster/official/cleanliness
@@ -556,12 +556,12 @@
/obj/structure/sign/poster/official/pda_ad
name = "PDA Ad"
- desc = "A poster advertising the latest PDA from Nanotrasen suppliers."
+ desc = "A poster advertising the latest PDA from Think-a-tronic suppliers."
icon_state = "poster28_legit"
/obj/structure/sign/poster/official/enlist
name = "Enlist" // but I thought deathsquad was never acknowledged
- desc = "Enlist in the Nanotrasen Deathsquadron reserves today!"
+ desc = "Enlist in the Kinaris Deathsquadron reserves today!"
icon_state = "poster29_legit"
/obj/structure/sign/poster/official/nanomichi_ad
@@ -586,7 +586,7 @@
/obj/structure/sign/poster/official/no_erp
name = "No ERP"
- desc = "This poster reminds the crew that Eroticism, Rape and Pornography are banned on Nanotrasen stations."
+ desc = "This poster reminds the crew that Eroticism, Rape and Pornography are banned on Kinaris stations."
icon_state = "poster34_legit"
/obj/structure/sign/poster/official/wtf_is_co2
diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm
index b78a2192..5466d9ff 100644
--- a/code/game/objects/effects/spawners/lootdrop.dm
+++ b/code/game/objects/effects/spawners/lootdrop.dm
@@ -172,6 +172,53 @@
/obj/item/organ/body_egg/alien_embryo = 1,
/obj/item/organ/regenerative_core = 2)
lootcount = 3
+/obj/effect/spawner/lootdrop/teratoma/minor
+ name = "teratoma spawner"
+ loot = list(
+ /obj/item/organ/tongue = 5,
+ /obj/item/organ/tongue/lizard = 1,
+ /obj/item/organ/tail/cat = 1,
+ /obj/item/organ/stomach = 5,
+ /obj/item/organ/tongue/zombie = 1,
+ /obj/item/organ/tongue/fly = 1,
+ /obj/item/organ/stomach/fly = 1,
+ /obj/item/organ/ears = 5,
+ /obj/item/organ/ears/cat = 1,
+ /obj/item/organ/eyes = 5,
+ /obj/item/organ/heart = 5,
+ /obj/item/organ/liver = 5,
+ /obj/item/organ/tail/lizard = 1,
+ /obj/item/organ/appendix = 5,
+ /obj/effect/gibspawner/human = 1)
+
+/obj/effect/spawner/lootdrop/teratoma/major
+ name = "advanced teratoma spawner"
+ loot = list(
+ /obj/item/organ/adamantine_resonator = 2,
+ /obj/item/organ/heart/gland/viral = 1,
+ /obj/item/organ/eyes/night_vision = 1,
+ /obj/item/organ/liver/plasmaman = 3,
+ /obj/item/organ/stomach/plasmaman = 3,
+ /obj/item/organ/lungs/plasmaman = 3,
+ /obj/item/organ/lungs/slime = 3,
+ /obj/item/organ/tongue/abductor = 1,
+ /obj/item/organ/tongue/bone = 3,
+ /obj/item/organ/tongue/bone/plasmaman = 1,
+ /obj/item/organ/vocal_cords/adamantine = 1,
+ /obj/effect/gibspawner/xeno = 1,
+ /obj/effect/mob_spawn/human/corpse/assistant = 1,
+ /obj/effect/mob_spawn/teratomamonkey = 5)
+
+/obj/effect/spawner/lootdrop/teratoma/major/clown
+ name = "funny teratoma spawner"
+ loot = list(
+ /mob/living/simple_animal/hostile/retaliate/frog = 1,
+ /mob/living/simple_animal/hostile/retaliate/clown = 1,
+ /mob/living/simple_animal/hostile/retaliate/spaceman = 1,
+ /obj/item/clothing/mask/gas/clown_hat = 4,
+ /obj/item/clothing/shoes/clown_shoes = 3,
+ /obj/item/bikehorn = 5,
+ /obj/item/reagent_containers/food/snacks/pie/cream = 3)
/obj/effect/spawner/lootdrop/two_percent_xeno_egg_spawner
name = "2% chance xeno egg spawner"
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index 5e02ceeb..7bef90c0 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -160,6 +160,7 @@ RLD
var/mode = 1
var/ranged = FALSE
var/computer_dir = 1
+ var/airlock_dir = 1
var/airlock_type = /obj/machinery/door/airlock
var/airlock_glass = FALSE // So the floor's rcd_act knows how much ammo to use
var/window_type = /obj/structure/window/fulltile
@@ -281,6 +282,22 @@ RLD
return FALSE
return TRUE
+/obj/item/construction/rcd/proc/change_airlock_direction(mob/user)
+ if(!user)
+ return
+ var/list/airlock_dirs = list(
+ "North/South" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlocknorthsouth"),
+ "East/West" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlockeastwest")
+ )
+ var/airlockdirs = show_radial_menu(user, src, airlock_dirs, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
+ if(!check_menu(user))
+ return
+ switch(airlockdirs)
+ if("North/South")
+ airlock_dir = 1
+ if("East/West")
+ airlock_dir = 4
+
/obj/item/construction/rcd/proc/change_computer_dir(mob/user)
if(!user)
return
@@ -486,6 +503,7 @@ RLD
if(mode == RCD_AIRLOCK)
choices += list(
"Change Access" = image(icon = 'icons/mob/radial.dmi', icon_state = "access"),
+ "Change Direction" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlockrotation"),
"Change Airlock Type" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlocktype")
)
else if(mode == RCD_WINDOWGRILLE)
@@ -513,6 +531,9 @@ RLD
if("Change Access")
change_airlock_access(user)
return
+ if("Change Direction")
+ change_airlock_direction(user)
+ return
if("Change Airlock Type")
change_airlock_setting(user)
return
diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm
index 3a881a0f..770d1805 100644
--- a/code/game/objects/items/clown_items.dm
+++ b/code/game/objects/items/clown_items.dm
@@ -32,7 +32,7 @@
AddComponent(/datum/component/slippery, 80)
/obj/item/soap/nanotrasen
- desc = "A Nanotrasen brand bar of soap. Smells of plasma."
+ desc = "A Kinaris.Co brand bar of soap. Smells of plasma."
icon_state = "soapnt"
/obj/item/soap/homemade
diff --git a/code/game/objects/items/devices/forcefieldprojector.dm b/code/game/objects/items/devices/forcefieldprojector.dm
index de62869e..73db32eb 100644
--- a/code/game/objects/items/devices/forcefieldprojector.dm
+++ b/code/game/objects/items/devices/forcefieldprojector.dm
@@ -2,7 +2,7 @@
name = "forcefield projector"
desc = "An experimental device that can create several forcefields at a distance."
icon = 'icons/obj/device.dmi'
- icon_state = "signmaker_engi"
+ icon_state = "signmaker_forcefield"
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
item_flags = NOBLUDGEON
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index e9fd4a06..779aef86 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -453,7 +453,7 @@ GENE SCANNER
if(M.reagents.reagent_list.len)
var/list/datum/reagent/reagents = list()
for(var/datum/reagent/R in M.reagents.reagent_list)
- if(R.invisible)
+ if(R.chemical_flags & REAGENT_INVISIBLE)
continue
reagents += R
@@ -475,6 +475,20 @@ GENE SCANNER
msg += "*---------*"
to_chat(user, msg)
+ if(M.reagents.has_reagent("fermiTox"))
+ var/datum/reagent/fermiTox = M.reagents.has_reagent("fermiTox")
+ switch(fermiTox.volume)
+ if(5 to 10)
+ msg += "Subject contains a low amount of toxic isomers.\n"
+ if(10 to 25)
+ msg += "Subject contains toxic isomers.\n"
+ if(25 to 50)
+ msg += "Subject contains a substantial amount of toxic isomers.\n"
+ if(50 to 95)
+ msg += "Subject contains a high amount of toxic isomers.\n"
+ if(95 to INFINITY)
+ msg += "Subject contains a extremely dangerous amount of toxic isomers.\n"
+
/obj/item/healthanalyzer/verb/toggle_mode()
set name = "Switch Verbosity"
set category = "Object"
diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm
index c567a6e7..849e14b4 100644
--- a/code/game/objects/items/handcuffs.dm
+++ b/code/game/objects/items/handcuffs.dm
@@ -1,5 +1,6 @@
/obj/item/restraints
breakouttime = 600
+ var/demoralize_criminals = TRUE // checked on carbon/carbon.dm to decide wheter to apply the handcuffed negative moodlet or not.
/obj/item/restraints/suicide_act(mob/living/carbon/user)
user.visible_message("[user] is strangling [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")
@@ -220,6 +221,7 @@
name = "fake handcuffs"
desc = "Fake handcuffs meant for gag purposes."
breakouttime = 10 //Deciseconds = 1s
+ demoralize_criminals = FALSE
/obj/item/restraints/handcuffs/fake/kinky
name = "kinky handcuffs"
diff --git a/code/game/objects/items/holosign_creator.dm b/code/game/objects/items/holosign_creator.dm
index 78881d90..a8850b67 100644
--- a/code/game/objects/items/holosign_creator.dm
+++ b/code/game/objects/items/holosign_creator.dm
@@ -78,8 +78,8 @@
/obj/item/holosign_creator/atmos
name = "ATMOS holofan projector"
- desc = "A holographic projector that creates holographic barriers that prevent changes in atmosphere conditions."
- icon_state = "signmaker_engi"
+ desc = "A holographic projector that creates holographic fans that prevent changes in atmosphere conditions."
+ icon_state = "signmaker_atmos"
holosign_type = /obj/structure/holosign/barrier/atmos
creation_time = 0
max_signs = 3
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index ad4384f9..65478a84 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -249,7 +249,7 @@
return
var/obj/item/nullrod/holy_weapon
var/list/holy_weapons_list = typesof(/obj/item/nullrod) + list(
- /obj/item/melee/transforming/energy/sword/cx/chaplain
+ /obj/item/twohanded/dualsaber/hypereutactic/chaplain
)
var/list/display_names = list()
for(var/V in holy_weapons_list)
@@ -710,3 +710,32 @@
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
w_class = WEIGHT_CLASS_NORMAL
attack_verb = list("bashes", "smacks", "whacks")
+
+/obj/item/nullrod/hypertool
+ icon = 'icons/obj/device.dmi'
+ icon_state = "hypertool"
+ item_state = "hypertool"
+ lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
+ slot_flags = ITEM_SLOT_BELT
+ name = "hypertool"
+ desc = "A tool so powerful even you cannot perfectly use it."
+ armour_penetration = 35
+ damtype = BRAIN
+ attack_verb = list("pulsed", "mended", "cut")
+ hitsound = 'sound/effects/sparks4.ogg'
+
+/obj/item/nullrod/spear
+ name = "ancient spear"
+ desc = "An ancient spear made of brass, I mean gold, I mean bronze."
+ icon_state = "ratvarian_spear"
+ item_state = "ratvarian_spear"
+ lefthand_file = 'icons/mob/inhands/antag/clockwork_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi'
+ icon = 'icons/obj/clockwork_objects.dmi'
+ slot_flags = ITEM_SLOT_BELT
+ armour_penetration = 10
+ sharpness = IS_SHARP_ACCURATE
+ w_class = WEIGHT_CLASS_BULKY
+ attack_verb = list("stabbed", "poked", "slashed", "clocked")
+ hitsound = 'sound/weapons/bladeslice.ogg'
\ No newline at end of file
diff --git a/code/game/objects/items/implants/implant_track.dm b/code/game/objects/items/implants/implant_track.dm
index 913c577f..4398688c 100644
--- a/code/game/objects/items/implants/implant_track.dm
+++ b/code/game/objects/items/implants/implant_track.dm
@@ -1,7 +1,19 @@
/obj/item/implant/tracking
name = "tracking implant"
desc = "Track with this."
- activated = 0
+ activated = FALSE
+ var/lifespan_postmortem = 10 MINUTES //for how many deciseconds after user death will the implant work?
+ var/allow_teleport = TRUE //will people implanted with this act as teleporter beacons?
+
+/obj/item/implant/tracking/c38
+ name = "TRAC implant"
+ desc = "A smaller tracking implant that supplies power for only a few minutes."
+ var/lifespan = 5 MINUTES //how many deciseconds does the implant last?
+ allow_teleport = FALSE
+
+/obj/item/implant/tracking/c38/Initialize()
+ . = ..()
+ QDEL_IN(src, lifespan)
/obj/item/implant/tracking/New()
..()
@@ -21,7 +33,7 @@
var/dat = {"Implant Specifications: Name: Tracking Beacon Life: 10 minutes after death of host
- Important Notes: None
+ Important Notes: Implant also works as a teleporter beacon. Implant Details: Function: Continuously transmits low power signal. Useful for tracking.
diff --git a/code/game/objects/items/manuals.dm b/code/game/objects/items/manuals.dm
index 801ca707..8706870b 100644
--- a/code/game/objects/items/manuals.dm
+++ b/code/game/objects/items/manuals.dm
@@ -271,10 +271,10 @@
"}
/obj/item/book/manual/wiki/chemistry
- name = "Chemistry Textbook"
+ name = "Guide to chems"
icon_state ="chemistrybook"
- author = "Nanotrasen"
- title = "Chemistry Textbook"
+ author = "Kin-Chems"
+ title = "Guide to chems"
page_link = "Guide_to_chemistry"
/obj/item/book/manual/wiki/engineering_construction
@@ -292,17 +292,17 @@
page_link = "Guide_to_engineering"
/obj/item/book/manual/wiki/engineering_singulo_tesla
- name = "Singularity and Tesla for Dummies"
+ name = "Singularity 101"
icon_state ="bookEngineeringSingularitySafety"
author = "Engineering Encyclopedia"
- title = "Singularity and Tesla for Dummies"
+ title = "Singularity 101"
page_link = "Singularity_and_Tesla_engines"
/obj/item/book/manual/wiki/security_space_law
name = "Space Law"
- desc = "A set of Nanotrasen guidelines for keeping law and order on their space stations."
+ desc = "A set of Kin-Station guidelines for keeping law and order on their space stations."
icon_state = "bookSpaceLaw"
- author = "Nanotrasen"
+ author = "Kin.Co PMC"
title = "Space Law"
page_link = "Space_Law"
@@ -311,10 +311,10 @@
return OXYLOSS
/obj/item/book/manual/wiki/infections
- name = "Infections - Making your own pandemic!"
+ name = "Space CDC: Infections and you!"
icon_state = "bookInfections"
author = "Infections Encyclopedia"
- title = "Infections - Making your own pandemic!"
+ title = "Space CDC: Infections and you!"
page_link = "Infections"
/obj/item/book/manual/wiki/telescience
@@ -325,16 +325,16 @@
page_link = "Guide_to_telescience"
/obj/item/book/manual/wiki/engineering_hacking
- name = "Hacking"
+ name = "Hacking: A greytider's manual"
icon_state ="bookHacking"
- author = "Engineering Encyclopedia"
- title = "Hacking"
+ author = "The Greytider"
+ title = "Hacking: A greytider's manual"
page_link = "Hacking"
/obj/item/book/manual/wiki/detective
name = "The Film Noir: Proper Procedures for Investigations"
icon_state ="bookDetective"
- author = "Nanotrasen"
+ author = "The Stranger"
title = "The Film Noir: Proper Procedures for Investigations"
page_link = "Detective"
@@ -346,17 +346,17 @@
page_link = "Guide_to_food_and_drinks"
/obj/item/book/manual/wiki/robotics_cyborgs
- name = "Robotics for Dummies"
+ name = "The offical Robotics manual"
icon_state = "borgbook"
author = "XISC"
- title = "Robotics for Dummies"
+ title = "The offical Robotics manual"
page_link = "Guide_to_robotics"
/obj/item/book/manual/wiki/research_and_development
- name = "Research and Development 101"
+ name = "RnD: safe sciences"
icon_state = "rdbook"
author = "Dr. L. Ight"
- title = "Research and Development 101"
+ title = "RnD: safe sciences"
page_link = "Guide_to_Research_and_Development"
/obj/item/book/manual/wiki/experimentor
@@ -369,37 +369,37 @@
/obj/item/book/manual/wiki/medical_cloning
name = "Cloning techniques of the 26th century"
icon_state ="bookCloning"
- author = "Medical Journal, volume 3"
+ author = "Angel Paulson"
title = "Cloning techniques of the 26th century"
page_link = "Guide_to_genetics#Cloning"
/obj/item/book/manual/wiki/cooking_to_serve_man
- name = "To Serve Man"
- desc = "It's a cookbook!"
+ name = "Cooking for kids!"
+ desc = "It's a cooking datapad!"
icon_state ="cooked_book"
- author = "the Kanamitan Empire"
- title = "To Serve Man"
+ author = "Gordon Ramsay"
+ title = "Cooking for kids!"
page_link = "Guide_to_food_and_drinks"
/obj/item/book/manual/wiki/circuitry
- name = "Circuitry for Dummies"
+ name = "Wiring and safety manual"
icon_state = "book1"
author = "Dr. Hans Asperger"
- title = "Circuitry for Dummies"
+ title = "Wiring and safety manual"
page_link = "Guide_to_circuits"
/obj/item/book/manual/wiki/tcomms
- name = "Subspace Telecommunications And You"
+ name = "Keeping communications"
icon_state = "book3"
author = "Engineering Encyclopedia"
- title = "Subspace Telecommunications And You"
+ title = "Keeping communications"
page_link = "Guide_to_Telecommunications"
/obj/item/book/manual/wiki/atmospherics
- name = "Lexica Atmosia"
+ name = "O2 & You"
icon_state = "book5"
- author = "the City-state of Atmosia"
- title = "Lexica Atmosia"
+ author = "the department of NT-Atmos"
+ title = "O2 & You"
page_link = "Guide_to_Atmospherics"
/obj/item/book/manual/wiki/medicine
@@ -410,10 +410,10 @@
page_link = "Guide_to_medicine"
/obj/item/book/manual/wiki/surgery
- name = "Brain Surgery for Dummies"
+ name = "Surgery: step by step"
icon_state = "book4"
author = "Dr. F. Fran"
- title = "Brain Surgery for Dummies"
+ title = "Surgery: step by step"
page_link = "Surgery"
/obj/item/book/manual/wiki/grenades
diff --git a/code/game/objects/items/mesmetron.dm b/code/game/objects/items/mesmetron.dm
new file mode 100644
index 00000000..7983125f
--- /dev/null
+++ b/code/game/objects/items/mesmetron.dm
@@ -0,0 +1,91 @@
+/obj/item/mesmetron
+ name = "Mesmetron"
+ desc = "An elaborate pocketwatch, with a captivating gold etching and an enchanting face..."
+ icon = 'icons/obj/pocketwatch.dmi'
+ icon_state = "pocketwatch"
+ item_state = "pocketwatch"
+ w_class = WEIGHT_CLASS_SMALL
+ throw_range = 7
+ throw_speed = 3
+ var/mob/living/carbon/subject = null
+ var/closed = FALSE
+
+
+
+//Hypnotize someone
+/obj/item/mesmetron/attack(mob/living/carbon/human/H, mob/living/user)
+ if(closed)
+ return
+ if(H.IsSleeping())
+ to_chat(user, "You can't hypnotize [H] whilst they're asleep!")
+ return
+
+ user.visible_message("[user] begins to mesmerizingly wave [src] like a pendulum before [H]'s very eyes!")
+
+ if(!do_mob(user, H, 12 SECONDS))
+ return
+ if(!(user in view(1, loc)))
+ return
+
+ var/response = alert(H, "Do you wish to fall into a hypnotic sleep? (This will allow [user] to issue hypnotic suggestions)", "Hypnosis", "Yes", "No")
+
+ if(response == "Yes")
+ H.visible_message("[H] falls into a deep slumber!", "Your eyelids gently shut as you fall into a deep slumber. All you can hear is [user]'s voice as you commit to following all of their suggestions")
+
+ H.SetSleeping(1200)
+ H.drowsyness = max(H.drowsyness, 40)
+ subject = H
+ return
+
+ //No
+ H.visible_message("[H]'s attention breaks, despite your attempts to hypnotize them! They clearly don't want this", "Your concentration breaks as you realise you have no interest in following [user]'s words!")
+
+
+
+//If there's a subject, open the suggestion interface
+/obj/item/mesmetron/attack_self(mob/user)
+ if(closed)
+ return
+ if(!subject)
+ return
+ if(!subject.IsSleeping())
+ to_chat(user, "[subject] is awake and no longer under hypnosis!")
+ subject = null
+ return
+
+ var/response = alert(user, "Would you like to release your subject or give them a suggestion?", "Mesmetron", "Suggestion", "Release")
+ if(response == "Suggestion")
+ if(get_dist(user, subject) > 1)
+ to_chat(user, "You must stand in whisper range of [subject].")
+ return
+
+ text = input("What would you like to suggest?", "Hypnotic suggestion", null, null)
+ text = sanitize(text)
+ if(!text)
+ return
+
+ to_chat(user, "You whisper your suggestion in a smooth calming voice to [subject]")
+ to_chat(subject, "...[text]...")
+ return
+ //Release
+ subject.visible_message("[subject] wakes up from their deep slumber!", "Your eyelids gently open as you see [user]'s face staring back at you")
+ subject.SetSleeping(0)
+ subject = null
+
+
+
+//Toggle open/close
+/obj/item/mesmetron/AltClick(mob/user)
+ //Close it
+ if(icon_state == "pocketwatch")
+ icon_state = "pocketwatch_closed"
+ item_state = "pocketwatch_closed"
+ desc = "An elaborate pocketwatch, with a captivating gold etching. It's closed however and you can't see it's face"
+ closed = TRUE
+ return
+ //Open it
+ icon_state = "pocketwatch"
+ item_state = "pocketwatch"
+ desc = "An elaborate pocketwatch, with a captivating gold etching and an enchanting face..."
+ closed = FALSE
+
diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm
index 0debc38f..5aebf2aa 100644
--- a/code/game/objects/items/plushes.dm
+++ b/code/game/objects/items/plushes.dm
@@ -840,12 +840,6 @@
icon_state = "rae"
item_state = "rae"
-/obj/item/toy/plush/mammal/winfre
- desc = "An adorable stuffed toy of a pissed hyena. She looks unamused."
- icon_state = "winfre"
- item_state = "winfre"
- attack_verb = list("cackled", "swirlie'd", "stepped on")
-
/obj/item/toy/plush/mammal/zed
desc = "A masked stuffed toy that resembles a fierce miner. He even comes with his own little crusher!"
icon_state = "zed"
@@ -931,11 +925,6 @@
icon_state = "marisol"
item_state = "marisol"
-/obj/item/toy/plush/mammal/marilyn
- desc = "A cute stuffed fox toy. Now, about that sponge bath..."
- icon_state = "marilyn"
- item_state = "marilyn"
-
/obj/item/toy/plush/catgirl
name = "feline plushie"
desc = "An adorable stuffed toy that resembles a feline."
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 794e3e76..af6f02cd 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -95,8 +95,9 @@
if(affecting.heal_damage(heal_brute, heal_burn))
C.update_damage_overlays()
if (fix_bone) //Fix broken bones on targeted limb
- affecting.broken = 0
- affecting.disabled = 0
+ if(affecting.broken == 1)
+ affecting.broken = 0
+ affecting.disabled = 0
else
to_chat(user, "Medicine won't work on a robotic limb!")
else
@@ -108,7 +109,7 @@
name = "plaster gauze"
gender = PLURAL
singular_name = "plaster gauze"
- desc = "A roll of plaster of paris that is extremely effective at aiding bone fratcutres, but does not heal wounds."
+ desc = "A roll of plaster of paris that is extremely effective at aiding bone fractures, but does not heal wounds."
icon_state = "pgauze"
self_delay = 300
max_amount = 10
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 6d010369..e1d06aa2 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -128,62 +128,6 @@
turf_type = /turf/open/floor/carpet/monochrome
tableVariant = /obj/structure/table/wood/fancy/monochrome
-/obj/item/stack/tile/carpet/blue
- name = "blue carpet"
- icon_state = "tile-carpet-blue"
- item_state = "tile-carpet-blue"
- turf_type = /turf/open/floor/carpet/blue
- tableVariant = /obj/structure/table/wood/fancy/blue
-
-/obj/item/stack/tile/carpet/cyan
- name = "cyan carpet"
- icon_state = "tile-carpet-cyan"
- item_state = "tile-carpet-cyan"
- turf_type = /turf/open/floor/carpet/cyan
- tableVariant = /obj/structure/table/wood/fancy/cyan
-
-/obj/item/stack/tile/carpet/green
- name = "green carpet"
- icon_state = "tile-carpet-green"
- item_state = "tile-carpet-green"
- turf_type = /turf/open/floor/carpet/green
- tableVariant = /obj/structure/table/wood/fancy/green
-
-/obj/item/stack/tile/carpet/orange
- name = "orange carpet"
- icon_state = "tile-carpet-orange"
- item_state = "tile-carpet-orange"
- turf_type = /turf/open/floor/carpet/orange
- tableVariant = /obj/structure/table/wood/fancy/orange
-
-/obj/item/stack/tile/carpet/purple
- name = "purple carpet"
- icon_state = "tile-carpet-purple"
- item_state = "tile-carpet-purple"
- turf_type = /turf/open/floor/carpet/purple
- tableVariant = /obj/structure/table/wood/fancy/purple
-
-/obj/item/stack/tile/carpet/red
- name = "red carpet"
- icon_state = "tile-carpet-red"
- item_state = "tile-carpet-red"
- turf_type = /turf/open/floor/carpet/red
- tableVariant = /obj/structure/table/wood/fancy/red
-
-/obj/item/stack/tile/carpet/royalblack
- name = "royal black carpet"
- icon_state = "tile-carpet-royalblack"
- item_state = "tile-carpet-royalblack"
- turf_type = /turf/open/floor/carpet/royalblack
- tableVariant = /obj/structure/table/wood/fancy/royalblack
-
-/obj/item/stack/tile/carpet/royalblue
- name = "royal blue carpet"
- icon_state = "tile-carpet-royalblue"
- item_state = "tile-carpet-royalblue"
- turf_type = /turf/open/floor/carpet/royalblue
- tableVariant = /obj/structure/table/wood/fancy/royalblue
-
/obj/item/stack/tile/carpet/fifty
amount = 50
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index 1f68d476..4b2ce220 100644
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -60,6 +60,7 @@
/obj/item/radio,
/obj/item/clothing/gloves,
/obj/item/holosign_creator,
+ /obj/item/forcefield_projector,
/obj/item/assembly/signaler
))
STR.can_hold = can_hold
diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm
index 5a4fc697..dd64c671 100644
--- a/code/game/objects/items/teleportation.dm
+++ b/code/game/objects/items/teleportation.dm
@@ -75,15 +75,14 @@
temp += "Implant Signals: "
for (var/obj/item/implant/tracking/W in GLOB.tracked_implants)
- if (!W.imp_in || !isliving(W.loc))
+ if (!isliving(W.imp_in))
continue
- else
- var/mob/living/M = W.loc
- if (M.stat == DEAD)
- if (M.timeofdeath + 6000 < world.time)
- continue
+ var/mob/living/M = W.imp_in
+ if (M.stat == DEAD)
+ if (M.timeofdeath + W.lifespan_postmortem < world.time)
+ continue
- var/turf/tr = get_turf(W)
+ var/turf/tr = get_turf(M)
if (tr.z == sr.z && tr)
var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
if (direct < 20)
@@ -188,8 +187,13 @@
user.show_message("\The [src] is recharging!")
return
var/atom/T = L[t1]
+ var/implantcheckmate = FALSE
+ if(isliving(T))
+ var/mob/living/M = T
+ if(!locate(/obj/item/implant/tracking) in M.implants) //The user was too slow and let the target mob's tracking implant expire or get removed.
+ implantcheckmate = TRUE
var/area/A = get_area(T)
- if(A.noteleport)
+ if(A.noteleport || implantcheckmate)
to_chat(user, "\The [src] is malfunctioning.")
return
current_location = get_turf(user) //Recheck.
@@ -233,4 +237,4 @@
itemUser.visible_message("The portal snaps closed taking [user]'s head with it!")
else
itemUser.visible_message("[user] looks even further depressed as they realize they do not have a head...and suddenly dies of shame!")
- return (BRUTELOSS)
+ return (BRUTELOSS)
\ No newline at end of file
diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm
index 0c74f610..b99be7e9 100644
--- a/code/game/objects/items/theft_tools.dm
+++ b/code/game/objects/items/theft_tools.dm
@@ -232,7 +232,7 @@
. = ..()
if(!sliver)
return
- if(ismovableatom(O) && O != sliver)
+ if(proximity && ismovableatom(O) && O != sliver)
Consume(O, user)
/obj/item/hemostat/supermatter/throw_impact(atom/hit_atom) // no instakill supermatter javelins
diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm
index 1ab28a33..9b6fa2c6 100644
--- a/code/game/objects/structures/barsigns.dm
+++ b/code/game/objects/structures/barsigns.dm
@@ -304,6 +304,21 @@
icon = "meow_mix"
desc = "No, we don't serve catnip, officer!"
+/datum/barsign/goose
+ name = "The Loose Goose"
+ icon = "goose"
+ desc = "Drink till you puke and/or break the laws of reality!"
+
+/datum/barsign/the_hive
+ name = "The Hive"
+ icon = "thehive"
+ desc = "Comb in for some sweet drinks! Not known for serving any sappy drink."
+
+/datum/barsign/kinariscorp
+ name = "Kinaris.Co"
+ icon = "kinariscorp"
+ desc = "Provided in saturated olive, Much like the drinks."
+
/datum/barsign/hiddensigns
hidden = TRUE
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index a8ba2597..3008e98c 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -115,7 +115,7 @@ LINEN BINS
/obj/item/bedsheet/captain
name = "captain's bedsheet"
- desc = "It has a Nanotrasen symbol on it, and was woven with a revolutionary new kind of thread guaranteed to have 0.01% permeability for most non-chemical substances, popular among most modern captains."
+ desc = "It has a Kinaris symbol on it, and was woven with a revolutionary new kind of thread guaranteed to have 0.01% permeability for most non-chemical substances, popular among most modern captains."
icon_state = "sheetcaptain"
item_color = "captain"
dream_messages = list("authority", "a golden ID", "sunglasses", "a green disc", "an antique gun", "the captain")
@@ -214,8 +214,8 @@ LINEN BINS
dream_messages = list("a book", "an explosion", "lightning", "a staff", "a skeleton", "a robe", "magic")
/obj/item/bedsheet/nanotrasen
- name = "nanotrasen bedsheet"
- desc = "It has the Nanotrasen logo on it and has an aura of duty."
+ name = "Kinaris bedsheet"
+ desc = "It has the Kinaris.Co logo on it and has an aura of duty."
icon_state = "sheetNT"
item_color = "nanotrasen"
dream_messages = list("authority", "an ending")
diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
index aad68b21..645d1e5d 100644
--- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
+++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
@@ -22,7 +22,9 @@
if(opened || move_delay || user.stat || user.IsStun() || user.IsKnockdown() || user.IsUnconscious() || !isturf(loc) || !has_gravity(loc))
return
move_delay = TRUE
- if(step(src, direction))
+ var/oldloc = loc
+ step(src, direction)
+ if(oldloc != loc)
addtimer(CALLBACK(src, .proc/ResetMoveDelay), (use_mob_movespeed ? user.movement_delay() : CONFIG_GET(number/movedelay/walk_delay)) * move_speed_multiplier)
else
ResetMoveDelay()
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index 4cc433e9..cd596502 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -10,7 +10,7 @@
new /obj/item/clothing/under/rank/chief_engineer(src)
new /obj/item/clothing/under/rank/chief_engineer/skirt(src)
new /obj/item/clothing/head/hardhat/white(src)
- new /obj/item/clothing/head/welding(src)
+ new /obj/item/clothing/head/hardhat/weldhat/white(src)
new /obj/item/clothing/gloves/color/yellow(src)
new /obj/item/clothing/shoes/sneakers/brown(src)
new /obj/item/tank/jetpack/suit(src)
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index d52ec81a..47fb6f87 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -7,7 +7,7 @@
anchored = TRUE
icon = 'icons/turf/walls/wall.dmi'
icon_state = "wall"
- layer = CLOSED_TURF_LAYER
+ layer = LOW_OBJ_LAYER
density = TRUE
opacity = 1
max_integrity = 100
diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm
index 12827a0a..4a56272a 100644
--- a/code/game/objects/structures/ghost_role_spawners.dm
+++ b/code/game/objects/structures/ghost_role_spawners.dm
@@ -561,7 +561,7 @@
icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper"
mob_name = "a space pirate"
- mob_species = /datum/species/skeleton/pirate
+ mob_species = /datum/species/skeleton/space
outfit = /datum/outfit/pirate/space
roundstart = FALSE
death = FALSE
diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm
index 609384cd..b6ad8e27 100644
--- a/code/game/objects/structures/holosign.dm
+++ b/code/game/objects/structures/holosign.dm
@@ -69,7 +69,7 @@
/obj/structure/holosign/barrier/atmos
name = "holo firelock"
desc = "A holographic barrier resembling a firelock. Though it does not prevent solid objects from passing through, gas is kept out."
- icon_state = "holo_firelock"
+ icon_state = "holo_fan"
density = FALSE
layer = ABOVE_MOB_LAYER
anchored = TRUE
@@ -81,6 +81,9 @@
. = ..()
air_update_turf(TRUE)
+/obj/structure/holosign/barrier/atmos/blocksTemperature()
+ return TRUE
+
/obj/structure/holosign/barrier/cyborg
name = "Energy Field"
desc = "A fragile energy field that blocks movement. Excels at blocking lethal projectiles."
diff --git a/code/game/objects/structures/showcase.dm b/code/game/objects/structures/showcase.dm
index 5de3f0fc..84a382c7 100644
--- a/code/game/objects/structures/showcase.dm
+++ b/code/game/objects/structures/showcase.dm
@@ -58,7 +58,7 @@
/obj/structure/showcase/mecha/marauder
name = "combat mech exhibit"
- desc = "A stand with an empty old Nanotrasen Corporation combat mech bolted to it. It is described as the premier unit used to defend corporate interests and employees."
+ desc = "A stand with an empty old Kinaris.Co combat mech bolted to it. It is described as the premier unit used to defend corporate interests and employees."
icon = 'icons/mecha/mecha.dmi'
icon_state = "marauder"
@@ -69,30 +69,30 @@
icon_state = "firefighter"
/obj/structure/showcase/machinery/implanter
- name = "Nanotrasen automated mindshield implanter exhibit"
- desc = "A flimsy model of a standard Nanotrasen automated mindshield implant machine. With secure positioning harnesses and a robotic surgical injector, brain damage and other serious medical anomalies are now up to 60% less likely!"
+ name = "Kinaris automated mindshield implanter exhibit"
+ desc = "A flimsy model of a standard Kinaris automated mindshield implant machine. With secure positioning harnesses and a robotic surgical injector, brain damage and other serious medical anomalies are now up to 60% less likely!"
icon = 'icons/obj/machines/implantchair.dmi'
icon_state = "implantchair"
/obj/structure/showcase/machinery/microwave
- name = "Nanotrasen-brand microwave"
- desc = "The famous Nanotrasen-brand microwave, the multi-purpose cooking appliance every station needs! This one appears to be drawn onto a cardboard box."
+ name = "Kinaris-brand microwave"
+ desc = "The famous Kinaris.Co microwave, the multi-purpose cooking appliance every station needs! This one appears to be drawn onto a cardboard box."
icon = 'icons/obj/kitchen.dmi'
icon_state = "mw"
/obj/structure/showcase/machinery/cloning_pod
name = "cloning pod exhibit"
- desc = "Signs describe how cloning pods like these ensure that every Nanotrasen employee can carry out their contracts in full, even in the unlikely event of their catastrophic death. Hopefully they aren't all made of cardboard, like this one."
+ desc = "Signs describe how cloning pods like these ensure that every Kin.Co employee can carry out their contracts in full, even in the unlikely event of their catastrophic death. Hopefully they aren't all made of cardboard, like this one."
icon = 'icons/obj/machines/cloning.dmi'
icon_state = "pod_0"
/obj/structure/showcase/perfect_employee
name = "'Perfect Man' employee exhibit"
- desc = "A stand with a model of the perfect Nanotrasen Employee bolted to it. Signs indicate it is robustly genetically engineered, as well as being ruthlessly loyal."
+ desc = "A stand with a model of the perfect Kinaris Employee bolted to it. Signs indicate it is robustly genetically engineered, as well as being ruthlessly loyal."
/obj/structure/showcase/machinery/tv
- name = "Nanotrasen corporate newsfeed"
- desc = "A slightly battered looking TV. Various Nanotrasen infomercials play on a loop, accompanied by a jaunty tune."
+ name = "Kinaris-Co brand newsfeed"
+ desc = "A slightly battered looking TV. Various galactic infomercials play on a loop, accompanied by a jaunty tune."
icon = 'icons/obj/computer.dmi'
icon_state = "television"
diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm
index 84add2f6..152385f9 100644
--- a/code/game/objects/structures/signs/_signs.dm
+++ b/code/game/objects/structures/signs/_signs.dm
@@ -121,11 +121,11 @@
setDir(turn(dir, 90))
/obj/structure/sign/nanotrasen
- name = "\improper Nanotrasen Logo"
- desc = "A sign with the Nanotrasen Logo on it. Glory to Nanotrasen!"
+ name = "\improper Kinaris.Corp Logo"
+ desc = "A sign with the Kinaris Logo on it. Blessed be Kinaris!"
icon_state = "nanotrasen"
/obj/structure/sign/logo
- name = "nanotrasen logo"
- desc = "The Nanotrasen corporate logo."
+ name = "Kinaris.Co Logo"
+ desc = "The Kinaris corporate logo."
icon_state = "nanotrasen_sign1"
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index bec51dce..31b229a9 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -136,17 +136,6 @@
var/mob/living/carbon/human/H = pushed_mob
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "table", /datum/mood_event/table)
-/* You don't shove people onto a table frame.
-/obj/structure/table/shove_act(mob/living/target, mob/living/user)
- if(!target.resting)
- target.Knockdown(SHOVE_KNOCKDOWN_TABLE)
- user.visible_message("[user.name] shoves [target.name] onto \the [src]!",
- "You shove [target.name] onto \the [src]!", null, COMBAT_MESSAGE_RANGE)
- target.forceMove(src.loc)
- log_combat(user, target, "shoved", "onto [src] (table)")
- return TRUE
-*/
-
/obj/structure/table/attackby(obj/item/I, mob/user, params)
if(!(flags_1 & NODECONSTRUCT_1))
if(istype(I, /obj/item/screwdriver) && deconstruction_ready)
@@ -272,52 +261,6 @@
for(var/obj/item/shard/S in debris)
S.color = NARSIE_WINDOW_COLOUR
-/*
- * Plasmaglass tables
- */
-/obj/structure/table/plasmaglass
- name = "plasmaglass table"
- desc = "A glasstable, but it's pink and more sturdy. What will Nanotrasen design next with plasma?"
- icon = 'icons/obj/smooth_structures/plasmaglass_table.dmi'
- icon_state = "plasmaglass_table"
- climbable = TRUE
- buildstack = /obj/item/stack/sheet/plasmaglass
- canSmoothWith = null
- max_integrity = 270
- resistance_flags = ACID_PROOF
- armor = list("melee" = 10, "bullet" = 5, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
- var/list/debris = list()
-
-/obj/structure/table/plasmaglass/New()
- . = ..()
- debris += new frame
-
-/obj/structure/table/plasmaglass/Destroy()
- QDEL_LIST(debris)
- . = ..()
-
-/obj/structure/table/plasmaglass/proc/check_break(mob/living/M)
- return
-
-/obj/structure/table/plasmaglass/deconstruct(disassembled = TRUE, wrench_disassembly = 0)
- if(!(flags_1 & NODECONSTRUCT_1))
- if(disassembled)
- ..()
- return
- else
- var/turf/T = get_turf(src)
- playsound(T, "shatter", 50, 1)
- for(var/X in debris)
- var/atom/movable/AM = X
- AM.forceMove(T)
- debris -= AM
- qdel(src)
-
-/obj/structure/table/plasmaglass/narsie_act()
- color = NARSIE_WINDOW_COLOUR
- for(var/obj/item/shard/S in debris)
- S.color = NARSIE_WINDOW_COLOUR
-
/*
* Wooden tables
*/
@@ -358,83 +301,44 @@
frame = /obj/structure/table_frame
framestack = /obj/item/stack/rods
buildstack = /obj/item/stack/tile/carpet
- canSmoothWith = list(/obj/structure/table/wood/fancy,
- /obj/structure/table/wood/fancy/black,
- /obj/structure/table/wood/fancy/blackred,
- /obj/structure/table/wood/fancy/monochrome,
- /obj/structure/table/wood/fancy/blue,
- /obj/structure/table/wood/fancy/cyan,
- /obj/structure/table/wood/fancy/green,
- /obj/structure/table/wood/fancy/orange,
- /obj/structure/table/wood/fancy/purple,
- /obj/structure/table/wood/fancy/red,
- /obj/structure/table/wood/fancy/royalblack,
- /obj/structure/table/wood/fancy/royalblue)
- var/smooth_icon = 'icons/obj/smooth_structures/fancy_table.dmi' // see Initialize()
+ canSmoothWith = list(/obj/structure/table/wood/fancy, /obj/structure/table/wood/fancy/black, /obj/structure/table/wood/fancy/blackred, /obj/structure/table/wood/fancy/monochrome)
-/obj/structure/table/wood/fancy/Initialize()
+/obj/structure/table/wood/fancy/New()
+ // New() is used so that the /black subtype can override `icon` easily and
+ // the correct value will be used by the smoothing subsystem.
. = ..()
// Needs to be set dynamically because table smooth sprites are 32x34,
// which the editor treats as a two-tile-tall object. The sprites are that
// size so that the north/south corners look nice - examine the detail on
// the sprites in the editor to see why.
- icon = smooth_icon
+ icon = 'icons/obj/smooth_structures/fancy_table.dmi'
/obj/structure/table/wood/fancy/black
icon_state = "fancy_table_black"
buildstack = /obj/item/stack/tile/carpet/black
- smooth_icon = 'icons/obj/smooth_structures/fancy_table_black.dmi'
/obj/structure/table/wood/fancy/blackred
- icon_state = "fancy_table_blackred"
- buildstack = /obj/item/stack/tile/carpet/blackred
- smooth_icon = 'icons/obj/smooth_structures/fancy_table_blackred.dmi'
+ icon = 'icons/obj/structures.dmi'
+ icon_state = "fancy_table_blackred"
+ buildstack = /obj/item/stack/tile/carpet/blackred
+
+/obj/structure/table/wood/fancy/blackred/New()
+ . = ..()
+ icon = 'icons/obj/smooth_structures/fancy_table_blackred.dmi'
/obj/structure/table/wood/fancy/monochrome
- icon_state = "fancy_table_monochrome"
- buildstack = /obj/item/stack/tile/carpet/monochrome
- smooth_icon = 'icons/obj/smooth_structures/fancy_table_monochrome.dmi'
+ icon = 'icons/obj/structures.dmi'
+ icon_state = "fancy_table_monochrome"
+ buildstack = /obj/item/stack/tile/carpet/monochrome
-/obj/structure/table/wood/fancy/blue
- icon_state = "fancy_table_blue"
- buildstack = /obj/item/stack/tile/carpet/blue
- smooth_icon = 'icons/obj/smooth_structures/fancy_table_blue.dmi'
-
-/obj/structure/table/wood/fancy/cyan
- icon_state = "fancy_table_cyan"
- buildstack = /obj/item/stack/tile/carpet/cyan
- smooth_icon = 'icons/obj/smooth_structures/fancy_table_cyan.dmi'
-
-/obj/structure/table/wood/fancy/green
- icon_state = "fancy_table_green"
- buildstack = /obj/item/stack/tile/carpet/green
- smooth_icon = 'icons/obj/smooth_structures/fancy_table_green.dmi'
-
-/obj/structure/table/wood/fancy/orange
- icon_state = "fancy_table_orange"
- buildstack = /obj/item/stack/tile/carpet/orange
- smooth_icon = 'icons/obj/smooth_structures/fancy_table_orange.dmi'
-
-/obj/structure/table/wood/fancy/purple
- icon_state = "fancy_table_purple"
- buildstack = /obj/item/stack/tile/carpet/purple
- smooth_icon = 'icons/obj/smooth_structures/fancy_table_purple.dmi'
-
-/obj/structure/table/wood/fancy/red
- icon_state = "fancy_table_red"
- buildstack = /obj/item/stack/tile/carpet/red
- smooth_icon = 'icons/obj/smooth_structures/fancy_table_red.dmi'
-
-/obj/structure/table/wood/fancy/royalblack
- icon_state = "fancy_table_royalblack"
- buildstack = /obj/item/stack/tile/carpet/royalblack
- smooth_icon = 'icons/obj/smooth_structures/fancy_table_royalblack.dmi'
-
-/obj/structure/table/wood/fancy/royalblue
- icon_state = "fancy_table_royalblue"
- buildstack = /obj/item/stack/tile/carpet/royalblue
- smooth_icon = 'icons/obj/smooth_structures/fancy_table_royalblue.dmi'
+/obj/structure/table/wood/fancy/monochrome/New()
+ . = ..()
+ icon = 'icons/obj/smooth_structures/fancy_table_monochrome.dmi'
+/obj/structure/table/wood/fancy/black/New()
+ . = ..()
+ // Ditto above.
+ icon = 'icons/obj/smooth_structures/fancy_table_black.dmi'
/*
* Reinforced tables
*/
@@ -687,4 +591,4 @@
", "You assemble \a [R].")
R.add_fingerprint(user)
qdel(src)
- building = FALSE
+ building = FALSE
\ No newline at end of file
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index c01f72af..5466775b 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -28,6 +28,8 @@
rad_insulation = RAD_VERY_LIGHT_INSULATION
rad_flags = RAD_PROTECT_CONTENTS
+
+
/obj/structure/window/examine(mob/user)
..()
if(reinf)
@@ -471,11 +473,12 @@
/turf/closed/wall/rust,
/turf/closed/wall/r_wall/rust,
/turf/closed/wall/clockwork,
+ /turf/closed/indestructible/riveted/,
+ /turf/closed/indestructible/riveted/uranium,
/obj/structure/window/fulltile,
/obj/structure/window/reinforced/fulltile,
/obj/structure/window/reinforced/tinted/fulltile,
- /obj/structure/window/plasma/fulltile,
- /obj/structure/window/plasma/reinforced/fulltile,
+ /obj/machinery/door,
/obj/machinery/door/airlock/,
/obj/machinery/door/airlock/mining,
/obj/machinery/door/airlock/mining/glass,
@@ -503,7 +506,10 @@
/obj/machinery/door/window/northright,
/obj/machinery/door/airlock/external,
/obj/machinery/door/airlock,
- /obj/machinery/door)
+ /obj/machinery/door/airlock/hatch,
+ /obj/machinery/door/airlock/engineering/glass/critical,
+ /obj/machinery/door/airlock/atmos,
+ /obj/machinery/door/airlock/highsecurity,)
// canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile, /obj/structure/window/reinforced/tinted/fulltile, /obj/structure/window/plasma/fulltile, /obj/structure/window/plasma/reinforced/fulltile)
glass_amount = 2
@@ -529,11 +535,9 @@
/turf/closed/wall/rust,
/turf/closed/wall/r_wall/rust,
/turf/closed/wall/clockwork,
- /obj/structure/window/fulltile,
- /obj/structure/window/reinforced/fulltile,
- /obj/structure/window/reinforced/tinted/fulltile,
/obj/structure/window/plasma/fulltile,
/obj/structure/window/plasma/reinforced/fulltile,
+ /obj/machinery/door,
/obj/machinery/door/airlock/,
/obj/machinery/door/airlock/mining,
/obj/machinery/door/airlock/mining/glass,
@@ -561,7 +565,13 @@
/obj/machinery/door/window/northright,
/obj/machinery/door/airlock/external,
/obj/machinery/door/airlock,
- /obj/machinery/door)
+ /obj/machinery/door/airlock/hatch,
+ /obj/machinery/door/airlock/engineering/glass/critical,
+ /obj/machinery/door/airlock/atmos,
+ /obj/machinery/door/airlock/highsecurity,
+ /turf/closed/indestructible/,
+ /turf/closed/indestructible/riveted,
+ /turf/closed/indestructible/fakeglass)
glass_amount = 2
/obj/structure/window/plasma/fulltile/unanchored
@@ -577,31 +587,12 @@
smooth = SMOOTH_TRUE
glass_amount = 2
-/obj/structure/window/plasma/reinforced/fulltile/unanchored
- anchored = FALSE
-
-/obj/structure/window/reinforced/fulltile
- icon = 'icons/obj/smooth_structures/reinforced_window.dmi'
- icon_state = "r_window"
- dir = FULLTILE_WINDOW_DIR
- max_integrity = 100
- fulltile = TRUE
- flags_1 = PREVENT_CLICK_UNDER_1
- smooth = SMOOTH_TRUE
canSmoothWith = list(
/turf/closed/wall,
/turf/closed/wall/r_wall,
- /obj/structure/falsewall,
- /obj/structure/falsewall/brass,
- /obj/structure/falsewall/reinforced,
- /turf/closed/wall/rust,
- /turf/closed/wall/r_wall/rust,
- /turf/closed/wall/clockwork,
- /obj/structure/window/fulltile,
- /obj/structure/window/reinforced/fulltile,
- /obj/structure/window/reinforced/tinted/fulltile,
/obj/structure/window/plasma/fulltile,
/obj/structure/window/plasma/reinforced/fulltile,
+ /obj/machinery/door,
/obj/machinery/door/airlock/,
/obj/machinery/door/airlock/mining,
/obj/machinery/door/airlock/mining/glass,
@@ -629,7 +620,70 @@
/obj/machinery/door/window/northright,
/obj/machinery/door/airlock/external,
/obj/machinery/door/airlock,
- /obj/machinery/door)
+ /obj/machinery/door/airlock/hatch,
+ /obj/machinery/door/airlock/engineering/glass/critical,
+ /obj/machinery/door/airlock/atmos,
+ /obj/machinery/door/airlock/highsecurity
+ )
+
+/obj/structure/window/plasma/reinforced/fulltile/unanchored
+ anchored = FALSE
+
+/obj/structure/window/reinforced/fulltile
+ icon = 'icons/obj/smooth_structures/reinforced_window.dmi'
+ icon_state = "r_window"
+ dir = FULLTILE_WINDOW_DIR
+ max_integrity = 100
+ fulltile = TRUE
+ flags_1 = PREVENT_CLICK_UNDER_1
+ smooth = SMOOTH_TRUE
+
+ canSmoothWith = list(
+ /turf/closed/wall,
+ /turf/closed/wall/r_wall,
+ /obj/structure/falsewall,
+ /obj/structure/falsewall/brass,
+ /obj/structure/falsewall/reinforced,
+ /turf/closed/wall/rust,
+ /turf/closed/wall/r_wall/rust,
+ /turf/closed/wall/clockwork,
+ /turf/closed/indestructible/riveted/,
+ /turf/closed/indestructible/riveted/uranium,
+ /obj/structure/window/fulltile,
+ /obj/structure/window/reinforced/fulltile,
+ /obj/structure/window/reinforced/tinted/fulltile,
+ /obj/machinery/door,
+ /obj/machinery/door/airlock/,
+ /obj/machinery/door/airlock/mining,
+ /obj/machinery/door/airlock/mining/glass,
+ /obj/machinery/door/airlock/medical,
+ /obj/machinery/door/airlock/medical/glass,
+ /obj/machinery/door/airlock/public,
+ /obj/machinery/door/airlock/public/glass,
+ /obj/machinery/door/airlock/research,
+ /obj/machinery/door/airlock/research/glass,
+ /obj/machinery/door/airlock/maintenance,
+ /obj/machinery/door/airlock/maintenance/glass,
+ /obj/machinery/door/airlock/command/,
+ /obj/machinery/door/airlock/command/glass,
+ /obj/machinery/door/airlock/engineering,
+ /obj/machinery/door/airlock/engineering/glass,
+ /obj/machinery/door/airlock/engineering/abandoned,
+ /obj/machinery/door/airlock/security,
+ /obj/machinery/door/airlock/security/glass,
+ /obj/machinery/door/airlock/maintenance/abandoned,
+ /obj/machinery/door/poddoor/shutters/preopen,
+ /obj/machinery/door/poddoor/shutters,
+ /obj/machinery/door/window/eastright,
+ /obj/machinery/door/window/eastleft,
+ /obj/machinery/door/window/northleft,
+ /obj/machinery/door/window/northright,
+ /obj/machinery/door/airlock/external,
+ /obj/machinery/door/airlock,
+ /obj/machinery/door/airlock/hatch,
+ /obj/machinery/door/airlock/engineering/glass/critical,
+ /obj/machinery/door/airlock/atmos,
+ /obj/machinery/door/airlock/highsecurity,)
level = 3
glass_amount = 2
@@ -654,11 +708,12 @@
/turf/closed/wall/rust,
/turf/closed/wall/r_wall/rust,
/turf/closed/wall/clockwork,
+ /turf/closed/indestructible/riveted/,
+ /turf/closed/indestructible/riveted/uranium,
/obj/structure/window/fulltile,
/obj/structure/window/reinforced/fulltile,
/obj/structure/window/reinforced/tinted/fulltile,
- /obj/structure/window/plasma/fulltile,
- /obj/structure/window/plasma/reinforced/fulltile,
+ /obj/machinery/door,
/obj/machinery/door/airlock/,
/obj/machinery/door/airlock/mining,
/obj/machinery/door/airlock/mining/glass,
@@ -686,8 +741,10 @@
/obj/machinery/door/window/northright,
/obj/machinery/door/airlock/external,
/obj/machinery/door/airlock,
- /obj/machinery/door)
-
+ /obj/machinery/door/airlock/hatch,
+ /obj/machinery/door/airlock/engineering/glass/critical,
+ /obj/machinery/door/airlock/atmos,
+ /obj/machinery/door/airlock/highsecurity,)
//Old code left of reference
//canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile, /obj/structure/window/reinforced/tinted/fulltile, /obj/structure/window/plasma/fulltile, /obj/structure/window/plasma/reinforced/fulltile)
level = 3
diff --git a/code/game/say.dm b/code/game/say.dm
index 4ce1d3c7..2bb67dfc 100644
--- a/code/game/say.dm
+++ b/code/game/say.dm
@@ -94,21 +94,21 @@ GLOBAL_LIST_INIT(freqtospan, list(
return "[say_mod(input, message_mode)][spanned ? ", \"[spanned]\"" : ""]"
// Citadel edit [spanned ? ", \"[spanned]\"" : ""]"
-/atom/movable/proc/lang_treat(atom/movable/speaker, datum/language/language, raw_message, list/spans, message_mode)
+/atom/movable/proc/lang_treat(atom/movable/speaker, datum/language/language, raw_message, list/spans, message_mode, no_quote = FALSE)
if(has_language(language))
var/atom/movable/AM = speaker.GetSource()
if(AM) //Basically means "if the speaker is virtual"
- return AM.say_quote(raw_message, spans, message_mode)
+ return no_quote ? raw_message : AM.say_quote(raw_message, spans, message_mode)
else
- return speaker.say_quote(raw_message, spans, message_mode)
+ return no_quote ? raw_message : speaker.say_quote(raw_message, spans, message_mode)
else if(language)
var/atom/movable/AM = speaker.GetSource()
var/datum/language/D = GLOB.language_datum_instances[language]
raw_message = D.scramble(raw_message)
if(AM)
- return AM.say_quote(raw_message, spans, message_mode)
+ return no_quote ? raw_message : AM.say_quote(raw_message, spans, message_mode)
else
- return speaker.say_quote(raw_message, spans, message_mode)
+ return no_quote ? raw_message : speaker.say_quote(raw_message, spans, message_mode)
else
return "makes a strange sound."
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 5503c610..e7562476 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -182,6 +182,8 @@
soundin = pick('sound/voice/beepsky/god.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/beepsky/secureday.ogg', 'sound/voice/beepsky/radio.ogg', 'sound/voice/beepsky/insult.ogg', 'sound/voice/beepsky/creep.ogg')
if("honkbot_e")
soundin = pick('sound/items/bikehorn.ogg', 'sound/items/AirHorn2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/items/AirHorn.ogg', 'sound/effects/reee.ogg', 'sound/items/WEEOO1.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/beepsky/creep.ogg','sound/magic/Fireball.ogg' ,'sound/effects/pray.ogg', 'sound/voice/hiss1.ogg','sound/machines/buzz-sigh.ogg', 'sound/machines/ping.ogg', 'sound/weapons/flashbang.ogg', 'sound/weapons/bladeslice.ogg')
+ if("goose")
+ soundin = pick('sound/creatures/goose1.ogg', 'sound/creatures/goose2.ogg', 'sound/creatures/goose3.ogg', 'sound/creatures/goose4.ogg')
//START OF CIT CHANGES - adds random vore sounds
if ("struggle_sound")
soundin = pick( 'sound/vore/pred/struggle_01.ogg','sound/vore/pred/struggle_02.ogg','sound/vore/pred/struggle_03.ogg',
diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm
index 6297cadc..29f039aa 100644
--- a/code/game/turfs/closed.dm
+++ b/code/game/turfs/closed.dm
@@ -86,9 +86,108 @@
smooth = SMOOTH_TRUE
explosion_block = INFINITY
+ canSmoothWith = list(
+ /turf/closed/wall,
+ /turf/closed/wall/r_wall,
+ /obj/structure/falsewall,
+ /obj/structure/falsewall/brass,
+ /obj/structure/falsewall/reinforced,
+ /turf/closed/wall/rust,
+ /turf/closed/wall/r_wall/rust,
+ /turf/closed/wall/clockwork,
+ /turf/closed/indestructible/riveted/,
+ /turf/closed/indestructible/riveted/uranium,
+ /obj/structure/window/fulltile,
+ /obj/structure/window/reinforced/fulltile,
+ /obj/structure/window/reinforced/tinted/fulltile,
+ /obj/structure/window/plasma/fulltile,
+ /obj/structure/window/plasma/reinforced/fulltile,
+ /obj/machinery/door,
+ /obj/machinery/door/airlock/,
+ /obj/machinery/door/airlock/mining,
+ /obj/machinery/door/airlock/mining/glass,
+ /obj/machinery/door/airlock/medical,
+ /obj/machinery/door/airlock/medical/glass,
+ /obj/machinery/door/airlock/public,
+ /obj/machinery/door/airlock/public/glass,
+ /obj/machinery/door/airlock/research,
+ /obj/machinery/door/airlock/research/glass,
+ /obj/machinery/door/airlock/maintenance,
+ /obj/machinery/door/airlock/maintenance/glass,
+ /obj/machinery/door/airlock/command/,
+ /obj/machinery/door/airlock/command/glass,
+ /obj/machinery/door/airlock/engineering,
+ /obj/machinery/door/airlock/engineering/glass,
+ /obj/machinery/door/airlock/engineering/abandoned,
+ /obj/machinery/door/airlock/security,
+ /obj/machinery/door/airlock/security/glass,
+ /obj/machinery/door/airlock/maintenance/abandoned,
+ /obj/machinery/door/poddoor/shutters/preopen,
+ /obj/machinery/door/poddoor/shutters,
+ /obj/machinery/door/window/eastright,
+ /obj/machinery/door/window/eastleft,
+ /obj/machinery/door/window/northleft,
+ /obj/machinery/door/window/northright,
+ /obj/machinery/door/airlock/external,
+ /obj/machinery/door/airlock,
+ /obj/machinery/door/airlock/hatch,
+ /obj/machinery/door/airlock/engineering/glass/critical,
+ /obj/machinery/door/airlock/atmos,
+ /obj/machinery/door/airlock/highsecurity,
+ /obj/machinery/door/airlock/centcom)
+
/turf/closed/indestructible/riveted/uranium
icon = 'icons/turf/walls/uranium_wall.dmi'
icon_state = "uranium"
+ canSmoothWith = list(
+ /turf/closed/wall,
+ /turf/closed/wall/r_wall,
+ /obj/structure/falsewall,
+ /obj/structure/falsewall/brass,
+ /obj/structure/falsewall/reinforced,
+ /turf/closed/wall/rust,
+ /turf/closed/wall/r_wall/rust,
+ /turf/closed/wall/clockwork,
+ /turf/closed/indestructible/riveted/,
+ /turf/closed/indestructible/riveted/uranium,
+ /obj/structure/window/fulltile,
+ /obj/structure/window/reinforced/fulltile,
+ /obj/structure/window/reinforced/tinted/fulltile,
+ /obj/structure/window/plasma/fulltile,
+ /obj/structure/window/plasma/reinforced/fulltile,
+ /obj/machinery/door,
+ /obj/machinery/door/airlock/,
+ /obj/machinery/door/airlock/mining,
+ /obj/machinery/door/airlock/mining/glass,
+ /obj/machinery/door/airlock/medical,
+ /obj/machinery/door/airlock/medical/glass,
+ /obj/machinery/door/airlock/public,
+ /obj/machinery/door/airlock/public/glass,
+ /obj/machinery/door/airlock/research,
+ /obj/machinery/door/airlock/research/glass,
+ /obj/machinery/door/airlock/maintenance,
+ /obj/machinery/door/airlock/maintenance/glass,
+ /obj/machinery/door/airlock/command/,
+ /obj/machinery/door/airlock/command/glass,
+ /obj/machinery/door/airlock/engineering,
+ /obj/machinery/door/airlock/engineering/glass,
+ /obj/machinery/door/airlock/engineering/abandoned,
+ /obj/machinery/door/airlock/security,
+ /obj/machinery/door/airlock/security/glass,
+ /obj/machinery/door/airlock/maintenance/abandoned,
+ /obj/machinery/door/poddoor/shutters/preopen,
+ /obj/machinery/door/poddoor/shutters,
+ /obj/machinery/door/window/eastright,
+ /obj/machinery/door/window/eastleft,
+ /obj/machinery/door/window/northleft,
+ /obj/machinery/door/window/northright,
+ /obj/machinery/door/airlock/external,
+ /obj/machinery/door/airlock,
+ /obj/machinery/door/airlock/hatch,
+ /obj/machinery/door/airlock/engineering/glass/critical,
+ /obj/machinery/door/airlock/atmos,
+ /obj/machinery/door/airlock/highsecurity,
+ /obj/machinery/door/airlock/centcom)
/turf/closed/indestructible/abductor
icon_state = "alien1"
@@ -102,6 +201,55 @@
opacity = 0
smooth = SMOOTH_TRUE
icon = 'icons/obj/smooth_structures/reinforced_window.dmi'
+ canSmoothWith = list(
+ /turf/closed/wall,
+ /turf/closed/wall/r_wall,
+ /obj/structure/falsewall,
+ /obj/structure/falsewall/brass,
+ /obj/structure/falsewall/reinforced,
+ /turf/closed/wall/rust,
+ /turf/closed/wall/r_wall/rust,
+ /turf/closed/wall/clockwork,
+ /turf/closed/indestructible/riveted/,
+ /turf/closed/indestructible/riveted/uranium,
+ /obj/structure/window/fulltile,
+ /obj/structure/window/reinforced/fulltile,
+ /obj/structure/window/reinforced/tinted/fulltile,
+ /obj/structure/window/plasma/fulltile,
+ /obj/structure/window/plasma/reinforced/fulltile,
+ /obj/machinery/door,
+ /obj/machinery/door/airlock/,
+ /obj/machinery/door/airlock/mining,
+ /obj/machinery/door/airlock/mining/glass,
+ /obj/machinery/door/airlock/medical,
+ /obj/machinery/door/airlock/medical/glass,
+ /obj/machinery/door/airlock/public,
+ /obj/machinery/door/airlock/public/glass,
+ /obj/machinery/door/airlock/research,
+ /obj/machinery/door/airlock/research/glass,
+ /obj/machinery/door/airlock/maintenance,
+ /obj/machinery/door/airlock/maintenance/glass,
+ /obj/machinery/door/airlock/command/,
+ /obj/machinery/door/airlock/command/glass,
+ /obj/machinery/door/airlock/engineering,
+ /obj/machinery/door/airlock/engineering/glass,
+ /obj/machinery/door/airlock/engineering/abandoned,
+ /obj/machinery/door/airlock/security,
+ /obj/machinery/door/airlock/security/glass,
+ /obj/machinery/door/airlock/maintenance/abandoned,
+ /obj/machinery/door/poddoor/shutters/preopen,
+ /obj/machinery/door/poddoor/shutters,
+ /obj/machinery/door/window/eastright,
+ /obj/machinery/door/window/eastleft,
+ /obj/machinery/door/window/northleft,
+ /obj/machinery/door/window/northright,
+ /obj/machinery/door/airlock/external,
+ /obj/machinery/door/airlock,
+ /obj/machinery/door/airlock/hatch,
+ /obj/machinery/door/airlock/engineering/glass/critical,
+ /obj/machinery/door/airlock/atmos,
+ /obj/machinery/door/airlock/highsecurity,
+ /obj/machinery/door/airlock/centcom)
/turf/closed/indestructible/fakeglass/Initialize()
. = ..()
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index 4fbcddf2..9940de06 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -253,7 +253,7 @@
return FALSE
to_chat(user, "You build an airlock.")
var/obj/machinery/door/airlock/A = new the_rcd.airlock_type(src)
-
+ A.setDir(the_rcd.airlock_dir)
A.electronics = new/obj/item/electronics/airlock(A)
if(the_rcd.conf_access)
diff --git a/code/game/turfs/simulated/wall/mineral_walls.dm b/code/game/turfs/simulated/wall/mineral_walls.dm
index dbffd101..4913fdb9 100644
--- a/code/game/turfs/simulated/wall/mineral_walls.dm
+++ b/code/game/turfs/simulated/wall/mineral_walls.dm
@@ -192,7 +192,7 @@
explosion_block = 3
flags_1 = CAN_BE_DIRTY_1 | CHECK_RICOCHET_1
sheet_type = /obj/item/stack/sheet/mineral/titanium
- smooth = SMOOTH_MORE|SMOOTH_DIAGONAL
+ smooth = SMOOTH_MORE
canSmoothWith = list(/turf/closed/wall/mineral/titanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock, /obj/structure/window/shuttle, /obj/structure/shuttle/engine/heater, /obj/structure/falsewall/titanium)
/turf/closed/wall/mineral/titanium/nodiagonal
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index 138c3b8b..42bd0c61 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -27,11 +27,14 @@
/turf/closed/wall/rust,
/turf/closed/wall/r_wall/rust,
/turf/closed/wall/clockwork,
+ /turf/closed/indestructible/riveted/,
+ /turf/closed/indestructible/riveted/uranium,
/obj/structure/window/fulltile,
/obj/structure/window/reinforced/fulltile,
/obj/structure/window/reinforced/tinted/fulltile,
/obj/structure/window/plasma/fulltile,
/obj/structure/window/plasma/reinforced/fulltile,
+ /obj/machinery/door,
/obj/machinery/door/airlock/,
/obj/machinery/door/airlock/mining,
/obj/machinery/door/airlock/mining/glass,
@@ -59,7 +62,10 @@
/obj/machinery/door/window/northright,
/obj/machinery/door/airlock/external,
/obj/machinery/door/airlock,
- /obj/machinery/door)
+ /obj/machinery/door/airlock/hatch,
+ /obj/machinery/door/airlock/engineering/glass/critical,
+ /obj/machinery/door/airlock/atmos,
+ /obj/machinery/door/airlock/highsecurity)
smooth = SMOOTH_TRUE
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 7110ff44..19e6fc68 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -452,16 +452,21 @@
/turf/AllowDrop()
return TRUE
-/turf/proc/add_vomit_floor(mob/living/carbon/M, toxvomit = NONE)
+/turf/proc/add_vomit_floor(mob/living/M, toxvomit = NONE)
+
var/obj/effect/decal/cleanable/vomit/V = new /obj/effect/decal/cleanable/vomit(src, M.get_static_viruses())
- // If the vomit combined, apply toxicity and reagents to the old vomit
+ //if the vomit combined, apply toxicity and reagents to the old vomit
if (QDELETED(V))
V = locate() in src
// Make toxins and blazaam vomit look different
if(toxvomit == VOMIT_PURPLE)
V.icon_state = "vomitpurp_[pick(1,4)]"
- else if(toxvomit == VOMIT_TOXIC)
+ else if (toxvomit == VOMIT_TOXIC)
V.icon_state = "vomittox_[pick(1,4)]"
+ if (iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(C.reagents)
+ clear_reagents_to_vomit_pool(C,V)
/proc/clear_reagents_to_vomit_pool(mob/living/carbon/M, obj/effect/decal/cleanable/vomit/V)
M.reagents.trans_to(V, M.reagents.total_volume / 10)
diff --git a/code/game/world.dm b/code/game/world.dm
index 9c1f4780..88166c4b 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -102,7 +102,6 @@ GLOBAL_VAR(restart_counter)
GLOB.picture_log_directory = "data/picture_logs/[override_dir]"
GLOB.world_game_log = "[GLOB.log_directory]/game.log"
- GLOB.world_cloning_log = "[GLOB.log_directory]/cloning.log"
GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index d6727f78..d0ec5920 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -413,9 +413,9 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
dat += "CLOSED"
else
dat += "UNKNOWN"
- dat += "[GLOB.TAB][TicketHref("Refresh", ref_src)][GLOB.TAB][TicketHref("Re-Title", ref_src, "retitle")]"
+ dat += "[FOURSPACES][TicketHref("Refresh", ref_src)][FOURSPACES][TicketHref("Re-Title", ref_src, "retitle")]"
if(state != AHELP_ACTIVE)
- dat += "[GLOB.TAB][TicketHref("Reopen", ref_src, "reopen")]"
+ dat += "[FOURSPACES][TicketHref("Reopen", ref_src, "reopen")]"
dat += "
Opened at: [GAMETIMESTAMP("hh:mm:ss", closed_at)] (Approx [DisplayTimeText(world.time - opened_at)] ago)"
if(closed_at)
dat += " Closed at: [GAMETIMESTAMP("hh:mm:ss", closed_at)] (Approx [DisplayTimeText(world.time - closed_at)] ago)"
@@ -423,7 +423,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(initiator)
dat += "Actions: [FullMonty(ref_src)] "
else
- dat += "DISCONNECTED[GLOB.TAB][ClosureLinks(ref_src)] "
+ dat += "DISCONNECTED[FOURSPACES][ClosureLinks(ref_src)] "
dat += " Log:
"
for(var/I in _interactions)
dat += "[I] "
diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm
index a22933be..3f1c437f 100644
--- a/code/modules/antagonists/_common/antag_spawner.dm
+++ b/code/modules/antagonists/_common/antag_spawner.dm
@@ -56,7 +56,7 @@
if(used)
to_chat(H, "You already used this contract!")
return
- var/list/candidates = pollCandidatesForMob("Do you want to play as a wizard's [href_list["school"]] apprentice?", ROLE_WIZARD, null, ROLE_WIZARD, 150, src)
+ var/list/candidates = pollCandidatesForMob("Do you want to play as a wizard's [href_list["school"]] apprentice?", ROLE_WIZARD, null, ROLE_WIZARD, 150, src, ignore_category = POLL_IGNORE_WIZARD)
if(LAZYLEN(candidates))
if(QDELETED(src))
return
@@ -235,7 +235,7 @@
return
if(used)
return
- var/list/candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, src)
+ var/list/candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, src, ignore_category = POLL_IGNORE_DEMON)
if(LAZYLEN(candidates))
if(used || QDELETED(src))
return
diff --git a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm
index 819dbafd..98164de0 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_surgery.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_surgery.dm
@@ -1,5 +1,5 @@
/datum/surgery/organ_extraction
- name = "experimental dissection"
+ name = "experimental organ replacement"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/incise, /datum/surgery_step/extract_organ, /datum/surgery_step/gland_insert)
possible_locs = list(BODY_ZONE_CHEST)
ignore_clothes = 1
diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm
index 1dbae4ca..a1bfc067 100644
--- a/code/modules/antagonists/cult/blood_magic.dm
+++ b/code/modules/antagonists/cult/blood_magic.dm
@@ -644,6 +644,11 @@
desc = "A spell that will absorb blood from anything you touch. Touching cultists and constructs can heal them. Clicking the hand will potentially let you focus the spell into something stronger."
color = "#7D1717"
+/obj/item/melee/blood_magic/manipulator/examine(mob/user)
+ . = ..()
+ if(iscultist(user))
+ to_chat(user, "The [name] currently has [uses] blood charges left.")
+
/obj/item/melee/blood_magic/manipulator/afterattack(atom/target, mob/living/carbon/human/user, proximity)
if(proximity)
if(ishuman(target))
@@ -678,9 +683,9 @@
if(ratio>1)
ratio = 1
uses -= round(overall_damage)
- H.visible_message("[H] is fully healed by [H==user ? "[H.p_their()]":"[H]'s"]'s blood magic!")
+ H.visible_message("[H] is fully healed by [H==user ? "[H.p_their()]":"[user]'s"] blood magic!")
else
- H.visible_message("[H] is partially healed by [H==user ? "[H.p_their()]":"[H]'s"] blood magic.")
+ H.visible_message("[H] is partially healed by [H==user ? "[H.p_their()]":"[user]'s"] blood magic.")
uses = 0
ratio *= -1
H.adjustOxyLoss((overall_damage*ratio) * (H.getOxyLoss() / overall_damage), 0)
@@ -762,7 +767,7 @@
switch(choice)
if("Blood Spear (150)")
if(uses < 150)
- to_chat(user, "You need 200 charges to perform this rite.")
+ to_chat(user, "You need 150 charges to perform this rite.")
else
uses -= 150
var/turf/T = get_turf(user)
@@ -778,7 +783,7 @@
"A [rite.name] materializes at your feet.")
if("Blood Bolt Barrage (300)")
if(uses < 300)
- to_chat(user, "You need 400 charges to perform this rite.")
+ to_chat(user, "You need 300 charges to perform this rite.")
else
var/obj/rite = new /obj/item/gun/ballistic/shotgun/boltaction/enchanted/arcane_barrage/blood()
uses -= 300
@@ -790,7 +795,7 @@
qdel(rite)
if("Blood Beam (500)")
if(uses < 500)
- to_chat(user, "You need 600 charges to perform this rite.")
+ to_chat(user, "You need 500 charges to perform this rite.")
else
var/obj/rite = new /obj/item/blood_beam()
uses -= 500
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index 25e3663c..10759afc 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -666,6 +666,7 @@
righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi'
slot_flags = 0
force = 17
+ force_unwielded = 17
force_wielded = 24
throwforce = 40
throw_speed = 2
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index a69694ce..927d4c73 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -22,7 +22,7 @@ Runes can either be invoked by one's self or with many different cultists. Each
icon = 'icons/obj/rune.dmi'
icon_state = "1"
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
- layer = LOW_OBJ_LAYER
+ layer = SIGIL_LAYER
color = RUNE_COLOR_RED
var/invocation = "Aiy ele-mayo." //This is said by cultists when the rune is invoked.
@@ -185,9 +185,6 @@ structure_check() searches for nearby cultist structures required for the invoca
color = RUNE_COLOR_OFFER
req_cultists = 1
rune_in_use = FALSE
- var/mob/living/currentconversionman
- var/conversiontimeout
- var/conversionresult
/obj/effect/rune/convert/do_invoke_glow()
return
@@ -236,34 +233,14 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/convert/proc/do_convert(mob/living/convertee, list/invokers)
if(invokers.len < 2)
for(var/M in invokers)
- to_chat(M, "You need at least two invokers to convert [convertee]!")
+ to_chat(M, "You need at least two invokers to convert [convertee]!")
log_game("Offer rune failed - tried conversion with one invoker")
return 0
- if(convertee.anti_magic_check(TRUE, TRUE))
+ if(convertee.anti_magic_check(TRUE, TRUE, FALSE, 0)) //Not chargecost because it can be spammed
for(var/M in invokers)
to_chat(M, "Something is shielding [convertee]'s mind!")
log_game("Offer rune failed - convertee had anti-magic")
return 0
- to_chat(convertee, "The world goes red. All at once you are aware of an evil, eldritch truth taking roots into your mind.\n\
- Click here to become a follower of Nar'sie, or suffer a fate worse than death.")
- INVOKE_ASYNC(src, .proc/optinalert, convertee)
- currentconversionman = convertee
- conversiontimeout = world.time + (14 SECONDS)
- convertee.Stun(140)
- ADD_TRAIT(convertee, TRAIT_MUTE, "conversionrune")
- flash_color(convertee, list("#960000", "#960000", "#960000", rgb(0,0,0)), 50)
- conversionresult = FALSE
- while(world.time < conversiontimeout && convertee && !conversionresult)
- stoplag(1)
- currentconversionman = null
- if(!convertee)
- return FALSE
- REMOVE_TRAIT(convertee, TRAIT_MUTE, "conversionrune")
- if(get_turf(convertee) != get_turf(src))
- return FALSE
- if(!conversionresult)
- do_sacrifice(convertee, invokers, TRUE)
- return FALSE
var/brutedamage = convertee.getBruteLoss()
var/burndamage = convertee.getFireLoss()
if(brutedamage || burndamage)
@@ -275,6 +252,8 @@ structure_check() searches for nearby cultist structures required for the invoca
SSticker.mode.add_cultist(convertee.mind, 1)
new /obj/item/melee/cultblade/dagger(get_turf(src))
convertee.mind.special_role = ROLE_CULTIST
+ to_chat(convertee, "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
+ and something evil takes root.")
to_chat(convertee, "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.\
")
if(ishuman(convertee))
@@ -284,18 +263,7 @@ structure_check() searches for nearby cultist structures required for the invoca
H.cultslurring = 0
return 1
-/obj/effect/rune/convert/proc/optinalert(mob/living/convertee)
- var/alert = alert(convertee, "Will you embrace the Geometer of Blood or perish in futile resistance?", "Choose your own fate", "Join the Blood Cult", "Suffer a horrible demise")
- if(alert == "Join the Blood Cult")
- signmeup(convertee)
-
-/obj/effect/rune/convert/proc/signmeup(mob/living/convertee)
- if(currentconversionman == usr)
- conversionresult = TRUE
- else
- to_chat(usr, "Your fate has already been set in stone.")
-
-/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers, force_a_sac)
+/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers)
var/mob/living/first_invoker = invokers[1]
if(!first_invoker)
return FALSE
@@ -305,7 +273,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/big_sac = FALSE
- if(!force_a_sac && (((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || C.cult_team.is_sacrifice_target(sacrificial.mind)) && invokers.len < 3)
+ if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || C.cult_team.is_sacrifice_target(sacrificial.mind)) && invokers.len < 3)
for(var/M in invokers)
to_chat(M, "[sacrificial] is too greatly linked to the world! You need three acolytes!")
log_game("Offer rune failed - not enough acolytes and target is living or sac target")
@@ -345,10 +313,6 @@ structure_check() searches for nearby cultist structures required for the invoca
sacrificial.gib()
return TRUE
-/obj/effect/rune/convert/Topic(href, href_list)
- if(href_list["signmeup"])
- signmeup(usr)
-
/obj/effect/rune/empower
cultist_name = "Empower"
cultist_desc = "allows cultists to prepare greater amounts of blood magic at far less of a cost."
diff --git a/code/modules/antagonists/devil/devil.dm b/code/modules/antagonists/devil/devil.dm
index 3f2bd003..dc649025 100644
--- a/code/modules/antagonists/devil/devil.dm
+++ b/code/modules/antagonists/devil/devil.dm
@@ -539,10 +539,10 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
var/list/parts = list()
parts += "The devil's true name is: [truename]"
parts += "The devil's bans were:"
- parts += "[GLOB.TAB][GLOB.lawlorify[LORE][ban]]"
- parts += "[GLOB.TAB][GLOB.lawlorify[LORE][bane]]"
- parts += "[GLOB.TAB][GLOB.lawlorify[LORE][obligation]]"
- parts += "[GLOB.TAB][GLOB.lawlorify[LORE][banish]]"
+ parts += "[FOURSPACES][GLOB.lawlorify[LORE][ban]]"
+ parts += "[FOURSPACES][GLOB.lawlorify[LORE][bane]]"
+ parts += "[FOURSPACES][GLOB.lawlorify[LORE][obligation]]"
+ parts += "[FOURSPACES][GLOB.lawlorify[LORE][banish]]"
return parts.Join(" ")
/datum/antagonist/devil/roundend_report()
diff --git a/code/modules/antagonists/disease/disease_abilities.dm b/code/modules/antagonists/disease/disease_abilities.dm
index 07cd3030..ccab2be3 100644
--- a/code/modules/antagonists/disease/disease_abilities.dm
+++ b/code/modules/antagonists/disease/disease_abilities.dm
@@ -5,26 +5,48 @@ is currently following.
*/
GLOBAL_LIST_INIT(disease_ability_singletons, list(
- new /datum/disease_ability/action/cough(),
- new /datum/disease_ability/action/sneeze(),
- new /datum/disease_ability/action/infect(),
- new /datum/disease_ability/symptom/cough(),
- new /datum/disease_ability/symptom/sneeze(),\
- new /datum/disease_ability/symptom/hallucigen(),
- new /datum/disease_ability/symptom/choking(),
- new /datum/disease_ability/symptom/confusion(),
- new /datum/disease_ability/symptom/youth(),
- new /datum/disease_ability/symptom/vomit(),
- new /datum/disease_ability/symptom/voice_change(),
- new /datum/disease_ability/symptom/visionloss(),
- new /datum/disease_ability/symptom/viraladaptation(),
- new /datum/disease_ability/symptom/vitiligo(),
- new /datum/disease_ability/symptom/sensory_restoration(),
- new /datum/disease_ability/symptom/itching(),
- new /datum/disease_ability/symptom/weight_loss(),
- new /datum/disease_ability/symptom/metabolism_heal(),
- new /datum/disease_ability/symptom/coma_heal()
- ))
+new /datum/disease_ability/action/cough,
+new /datum/disease_ability/action/sneeze,
+new /datum/disease_ability/action/infect,
+new /datum/disease_ability/symptom/mild/cough,
+new /datum/disease_ability/symptom/mild/sneeze,
+new /datum/disease_ability/symptom/medium/beard,
+new /datum/disease_ability/symptom/medium/hallucigen,
+new /datum/disease_ability/symptom/medium/confusion,
+new /datum/disease_ability/symptom/medium/vomit,
+new /datum/disease_ability/symptom/medium/voice_change,
+new /datum/disease_ability/symptom/medium/visionloss,
+new /datum/disease_ability/symptom/medium/deafness,
+new /datum/disease_ability/symptom/powerful/narcolepsy,
+new /datum/disease_ability/symptom/medium/fever,
+new /datum/disease_ability/symptom/medium/shivering,
+new /datum/disease_ability/symptom/medium/headache,
+new /datum/disease_ability/symptom/medium/nano_boost,
+new /datum/disease_ability/symptom/medium/nano_destroy,
+new /datum/disease_ability/symptom/medium/viraladaptation,
+new /datum/disease_ability/symptom/medium/viralevolution,
+new /datum/disease_ability/symptom/medium/vitiligo,
+new /datum/disease_ability/symptom/medium/revitiligo,
+new /datum/disease_ability/symptom/medium/itching,
+new /datum/disease_ability/symptom/medium/heal/weight_loss,
+new /datum/disease_ability/symptom/medium/heal/sensory_restoration,
+new /datum/disease_ability/symptom/medium/heal/mind_restoration,
+new /datum/disease_ability/symptom/powerful/fire,
+new /datum/disease_ability/symptom/powerful/flesh_eating,
+new /datum/disease_ability/symptom/powerful/genetic_mutation,
+new /datum/disease_ability/symptom/powerful/inorganic_adaptation,
+new /datum/disease_ability/symptom/powerful/heal/oxygen,
+new /datum/disease_ability/symptom/powerful/heal/chem,
+new /datum/disease_ability/symptom/powerful/heal/coma,
+new /datum/disease_ability/symptom/powerful/heal/teleport,
+new /datum/disease_ability/symptom/powerful/heal/growth,
+new /datum/disease_ability/symptom/powerful/heal/EMP,
+new /datum/disease_ability/symptom/powerful/heal/sweat,
+new /datum/disease_ability/symptom/powerful/wizarditis,
+new /datum/disease_ability/symptom/medium/pierrot,
+new /datum/disease_ability/symptom/medium/cockroach,
+new /datum/disease_ability/symptom/powerful/youth
+))
/datum/disease_ability
var/name
@@ -234,155 +256,180 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
O.AddComponent(/datum/component/infective, D.disease_template, 300)
StartCooldown()
return TRUE
+/*******************BASE SYMPTOM TYPES*******************/
+// cost is for convenience and can be changed. If you're changing req_tot_points then don't use the subtype...
+//healing no longer costs more, sans regen coma, due to how healing symptoms have been made scary
-//passive symptom abilities
-
-/datum/disease_ability/symptom/cough
- name = "Involuntary Coughing"
- symptoms = list(/datum/symptom/cough)
+/datum/disease_ability/symptom/mild
cost = 2
required_total_points = 4
+ category = "Symptom (Weak)"
+
+/datum/disease_ability/symptom/medium
+ cost = 4
+ required_total_points = 8
+ category = "Symptom"
+
+/datum/disease_ability/symptom/medium/heal
+ cost = 5
+ category = "Symptom (+)"
+
+/datum/disease_ability/symptom/powerful
+ cost = 4
+ required_total_points = 16
+ category = "Symptom (Strong)"
+
+/datum/disease_ability/symptom/powerful/heal
+ cost = 8
+ category = "Symptom (Strong+)"
+
+/******MILD******/
+
+/datum/disease_ability/symptom/mild/cough
+ name = "Involuntary Coughing"
+ symptoms = list(/datum/symptom/cough)
short_desc = "Cause victims to cough intermittently."
long_desc = "Cause victims to cough intermittently, spreading your infection if your transmissibility is high."
-/datum/disease_ability/symptom/sneeze
+/datum/disease_ability/symptom/mild/sneeze
name = "Involuntary Sneezing"
symptoms = list(/datum/symptom/sneeze)
- cost = 2
- required_total_points = 4
short_desc = "Cause victims to sneeze intermittently."
long_desc = "Cause victims to sneeze intermittently, spreading your infection and also increasing transmissibility and resistance, at the cost of stealth."
-/datum/disease_ability/symptom/beard
- //I don't think I need to justify the fact that this is the best symptom
- name = "Beard Growth"
- symptoms = list(/datum/symptom/beard)
- cost = 1
- required_total_points = 8
- short_desc = "Cause all victims to grow a luscious beard."
- long_desc = "Cause all victims to grow a luscious beard. Decreases stats slightly. Ineffective against Santa Claus."
+/******MEDIUM******/
-/datum/disease_ability/symptom/hallucigen
- name = "Hallucinations"
+/datum/disease_ability/symptom/medium/beard
+ symptoms = list(/datum/symptom/beard)
+ short_desc = "Cause all victims to grow a luscious beard."
+ long_desc = "Cause all victims to grow a luscious beard. Ineffective against Santa Claus."
+
+/datum/disease_ability/symptom/medium/hallucigen
symptoms = list(/datum/symptom/hallucigen)
- cost = 4
- required_total_points = 8
short_desc = "Cause victims to hallucinate."
long_desc = "Cause victims to hallucinate. Decreases stats, especially resistance."
-
-/datum/disease_ability/symptom/choking
- name = "Choking"
- symptoms = list(/datum/symptom/choking)
- cost = 4
- required_total_points = 8
- short_desc = "Cause victims to choke."
- long_desc = "Cause victims to choke, threatening asphyxiation. Decreases stats, especially transmissibility."
-
-
-/datum/disease_ability/symptom/confusion
- name = "Confusion"
+/datum/disease_ability/symptom/medium/confusion
symptoms = list(/datum/symptom/confusion)
- cost = 4
- required_total_points = 8
short_desc = "Cause victims to become confused."
long_desc = "Cause victims to become confused intermittently."
-
-/datum/disease_ability/symptom/youth
- name = "Eternal Youth"
- symptoms = list(/datum/symptom/youth)
- cost = 4
- required_total_points = 8
- short_desc = "Cause victims to become eternally young."
- long_desc = "Cause victims to become eternally young. Provides boosts to all stats except transmissibility."
-
-
-/datum/disease_ability/symptom/vomit
- name = "Vomiting"
+/datum/disease_ability/symptom/medium/vomit
symptoms = list(/datum/symptom/vomit)
- cost = 4
- required_total_points = 8
short_desc = "Cause victims to vomit."
long_desc = "Cause victims to vomit. Slightly increases transmissibility. Vomiting also also causes the victims to lose nutrition and removes some toxin damage."
-
-/datum/disease_ability/symptom/voice_change
- name = "Voice Changing"
+/datum/disease_ability/symptom/medium/voice_change
symptoms = list(/datum/symptom/voice_change)
- cost = 4
- required_total_points = 8
short_desc = "Change the voice of victims."
long_desc = "Change the voice of victims, causing confusion in communications."
-
-/datum/disease_ability/symptom/visionloss
- name = "Vision Loss"
+/datum/disease_ability/symptom/medium/visionloss
symptoms = list(/datum/symptom/visionloss)
- cost = 4
- required_total_points = 8
short_desc = "Damage the eyes of victims, eventually causing blindness."
long_desc = "Damage the eyes of victims, eventually causing blindness. Decreases all stats."
+/datum/disease_ability/symptom/medium/deafness
+ symptoms = list(/datum/symptom/deafness)
-/datum/disease_ability/symptom/viraladaptation
- name = "Self-Adaptation"
+/datum/disease_ability/symptom/medium/fever
+ symptoms = list(/datum/symptom/fever)
+
+/datum/disease_ability/symptom/medium/shivering
+ symptoms = list(/datum/symptom/shivering)
+
+/datum/disease_ability/symptom/medium/headache
+ symptoms = list(/datum/symptom/headache)
+
+/datum/disease_ability/symptom/medium/nano_boost
+ symptoms = list(/datum/symptom/nano_boost)
+
+/datum/disease_ability/symptom/medium/nano_destroy
+ symptoms = list(/datum/symptom/nano_destroy)
+
+/datum/disease_ability/symptom/medium/viraladaptation
symptoms = list(/datum/symptom/viraladaptation)
- cost = 4
- required_total_points = 8
short_desc = "Cause your infection to become more resistant to detection and eradication."
long_desc = "Cause your infection to mimic the function of normal body cells, becoming much harder to spot and to eradicate, but reducing its speed."
+/datum/disease_ability/symptom/medium/viralevolution
+ symptoms = list(/datum/symptom/viralevolution)
-/datum/disease_ability/symptom/vitiligo
- name = "Skin Paleness"
+/datum/disease_ability/symptom/medium/vitiligo
symptoms = list(/datum/symptom/vitiligo)
- cost = 1
- required_total_points = 8
- short_desc = "Cause victims to become pale."
- long_desc = "Cause victims to become pale. Decreases all stats."
+/datum/disease_ability/symptom/medium/revitiligo
+ symptoms = list(/datum/symptom/revitiligo)
-/datum/disease_ability/symptom/sensory_restoration
- name = "Sensory Restoration"
- symptoms = list(/datum/symptom/sensory_restoration)
- cost = 4
- required_total_points = 8
- short_desc = "Regenerate eye and ear damage of victims."
- long_desc = "Regenerate eye and ear damage of victims."
+/datum/disease_ability/symptom/medium/pierrot
+ symptoms = list(/datum/symptom/pierrot)
+/datum/disease_ability/symptom/medium/cockroach
+ symptoms = list(/datum/symptom/cockroach)
-/datum/disease_ability/symptom/itching
- name = "Itching"
+/datum/disease_ability/symptom/medium/itching
symptoms = list(/datum/symptom/itching)
- cost = 4
- required_total_points = 8
short_desc = "Cause victims to itch."
long_desc = "Cause victims to itch, increasing all stats except stealth."
-
-/datum/disease_ability/symptom/weight_loss
- name = "Weight Loss"
+/datum/disease_ability/symptom/medium/heal/weight_loss
symptoms = list(/datum/symptom/weight_loss)
- cost = 4
- required_total_points = 8
short_desc = "Cause victims to lose weight."
long_desc = "Cause victims to lose weight, and make it almost impossible for them to gain nutrition from food. Reduced nutrition allows your infection to spread more easily from hosts, especially by sneezing."
+/datum/disease_ability/symptom/medium/heal/sensory_restoration
+ symptoms = list(/datum/symptom/sensory_restoration)
+ short_desc = "Regenerate eye and ear damage of victims."
+ long_desc = "Regenerate eye and ear damage of victims."
-/datum/disease_ability/symptom/metabolism_heal
- name = "Metabolic Boost"
- symptoms = list(/datum/symptom/heal/metabolism)
+/datum/disease_ability/symptom/medium/heal/mind_restoration
+ symptoms = list(/datum/symptom/mind_restoration)
+
+/******POWERFUL******/
+
+/datum/disease_ability/symptom/powerful/fire
+ symptoms = list(/datum/symptom/fire)
+
+/datum/disease_ability/symptom/powerful/flesh_eating
+ symptoms = list(/datum/symptom/flesh_eating)
+
+/datum/disease_ability/symptom/powerful/wizarditis //strong because it can remove hardsuits and bio protection
+ symptoms = list(/datum/symptom/wizarditis)
+
+/datum/disease_ability/symptom/powerful/genetic_mutation
+ symptoms = list(/datum/symptom/genetic_mutation)
+
+/datum/disease_ability/symptom/powerful/inorganic_adaptation
+ symptoms = list(/datum/symptom/inorganic_adaptation)
+
+/datum/disease_ability/symptom/powerful/narcolepsy
+ symptoms = list(/datum/symptom/narcolepsy)
+
+/datum/disease_ability/symptom/powerful/youth
+ symptoms = list(/datum/symptom/youth)
+ short_desc = "Cause victims to become eternally young."
+ long_desc = "Cause victims to become eternally young. Provides boosts to all stats except transmissibility."
+
+/****HEALING SUBTYPE****/
+
+/datum/disease_ability/symptom/powerful/heal/oxygen
+ symptoms = list(/datum/symptom/oxygen)
+
+/datum/disease_ability/symptom/powerful/heal/chem
+ symptoms = list(/datum/symptom/heal/chem)
cost = 4
- required_total_points = 16
- short_desc = "Increase the metabolism of victims, causing them to process chemicals and grow hungry faster."
- long_desc = "Increase the metabolism of victims, causing them to process chemicals twice as fast and grow hungry more quickly."
-
-/datum/disease_ability/symptom/coma_heal
- name = "Regenerative Coma"
+/datum/disease_ability/symptom/powerful/heal/coma
symptoms = list(/datum/symptom/heal/coma)
- cost = 8
- required_total_points = 16
- short_desc = "Cause victims to fall into a healing coma when hurt."
- long_desc = "Cause victims to fall into a healing coma when hurt."
+
+/datum/disease_ability/symptom/powerful/heal/teleport
+ symptoms = list(/datum/symptom/teleport)
+
+/datum/disease_ability/symptom/powerful/heal/growth
+ symptoms = list(/datum/symptom/growth)
+
+/datum/disease_ability/symptom/powerful/heal/EMP
+ symptoms = list(/datum/symptom/EMP)
+
+/datum/disease_ability/symptom/powerful/heal/sweat
+ symptoms = list(/datum/symptom/sweat)
diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm
index edae8a42..daa38767 100644
--- a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm
+++ b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm
@@ -1,7 +1,8 @@
#define CHALLENGE_TELECRYSTALS 280
#define PLAYER_SCALING 1.5
#define CHALLENGE_TIME_LIMIT 3000
-#define CHALLENGE_MIN_PLAYERS 50
+#define CHALLENGE_PLAYERS_TARGET 50 //target players population. anything below is a malus to the challenge tc bonus.
+#define TELECRYSTALS_MALUS_SCALING 1 //the higher the value, the bigger the malus.
#define CHALLENGE_SHUTTLE_DELAY 15000 // 25 minutes, so the ops have at least 5 minutes before the shuttle is callable.
GLOBAL_LIST_EMPTY(jam_on_wardec)
@@ -62,12 +63,15 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
for(var/obj/machinery/computer/camera_advanced/shuttle_docker/D in GLOB.jam_on_wardec)
D.jammed = TRUE
-
+
GLOB.war_declared = TRUE
var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
var/actual_players = GLOB.joined_player_list.len - nukeops.len
+ var/tc_malus = 0
+ if(actual_players < CHALLENGE_PLAYERS_TARGET)
+ tc_malus = FLOOR((CHALLENGE_TELECRYSTALS - actual_players * INVERSE(CHALLENGE_PLAYERS_TARGET)) * TELECRYSTALS_MALUS_SCALING, 1)
- new uplink_type(get_turf(user), user.key, CHALLENGE_TELECRYSTALS + CEILING(PLAYER_SCALING * actual_players, 1))
+ new uplink_type(get_turf(user), user.key, CHALLENGE_TELECRYSTALS - tc_malus + CEILING(PLAYER_SCALING * actual_players, 1))
CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY))
SSblackbox.record_feedback("amount", "nuclear_challenge_mode", 1)
@@ -79,11 +83,6 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
to_chat(user, "You are already in the process of declaring war! Make your mind up.")
return FALSE
- var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
- var/actual_players = GLOB.joined_player_list.len - nukeops.len
- if(actual_players < CHALLENGE_MIN_PLAYERS)
- to_chat(user, "The enemy crew is too small to be worth declaring war on.")
- return FALSE
if(!user.onSyndieBase())
to_chat(user, "You have to be at your base to use this.")
return FALSE
@@ -102,5 +101,6 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
#undef CHALLENGE_TELECRYSTALS
#undef CHALLENGE_TIME_LIMIT
-#undef CHALLENGE_MIN_PLAYERS
+#undef CHALLENGE_PLAYERS_TARGET
+#undef TELECRYSTALS_MALUS_SCALING
#undef CHALLENGE_SHUTTLE_DELAY
diff --git a/code/modules/antagonists/revenant/revenant_blight.dm b/code/modules/antagonists/revenant/revenant_blight.dm
index 7037ecae..89d8de28 100644
--- a/code/modules/antagonists/revenant/revenant_blight.dm
+++ b/code/modules/antagonists/revenant/revenant_blight.dm
@@ -11,9 +11,9 @@
viable_mobtypes = list(/mob/living/carbon/human)
disease_flags = CURABLE
permeability_mod = 1
- severity = DISEASE_SEVERITY_HARMFUL
- var/stagedamage = 0 //Highest stage reached.
+ severity = DISEASE_SEVERITY_DANGEROUS
var/finalstage = 0 //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.
+ var/datum/mood_event/revenant_blight/depression
/datum/disease/revblight/cure()
if(affected_mob)
@@ -21,12 +21,13 @@
if(affected_mob.dna && affected_mob.dna.species)
affected_mob.dna.species.handle_mutant_bodyparts(affected_mob)
affected_mob.dna.species.handle_hair(affected_mob)
- to_chat(affected_mob, "You feel better.")
+ SEND_SIGNAL(affected_mob, COMSIG_CLEAR_MOOD_EVENT, "rev_blight")
..()
/datum/disease/revblight/stage_act()
if(!finalstage)
- if(affected_mob.lying && prob(stage*6))
+ if(affected_mob.lying && prob(stage*4))
+ to_chat(affected_mob, "You feel better.")
cure()
return
if(prob(stage*3))
@@ -34,10 +35,6 @@
affected_mob.confused += 8
affected_mob.adjustStaminaLoss(8)
new /obj/effect/temp_visual/revenant(affected_mob.loc)
- if(stagedamage < stage)
- stagedamage++
- affected_mob.adjustToxLoss(stage*2) //should, normally, do about 30 toxin damage.
- new /obj/effect/temp_visual/revenant(affected_mob.loc)
if(prob(45))
affected_mob.adjustStaminaLoss(stage)
..() //So we don't increase a stage before applying the stage damage.
@@ -46,9 +43,13 @@
if(prob(5))
affected_mob.emote("pale")
if(3)
+ if(!depression)
+ depression = SEND_SIGNAL(affected_mob, COMSIG_ADD_MOOD_EVENT, "rev_blight", /datum/mood_event/revenant_blight)
+ SEND_SIGNAL(affected_mob, COMSIG_DECREASE_SANITY, 0.12, SANITY_CRAZY)
if(prob(10))
affected_mob.emote(pick("pale","shiver"))
if(4)
+ SEND_SIGNAL(affected_mob, COMSIG_DECREASE_SANITY, 0.18, SANITY_CRAZY)
if(prob(15))
affected_mob.emote(pick("pale","shiver","cries"))
if(5)
@@ -56,12 +57,18 @@
finalstage = TRUE
to_chat(affected_mob, "You feel like [pick("nothing's worth it anymore", "nobody ever needed your help", "nothing you did mattered", "everything you tried to do was worthless")].")
affected_mob.adjustStaminaLoss(45)
- new /obj/effect/temp_visual/revenant(affected_mob.loc)
- if(affected_mob.dna && affected_mob.dna.species)
+ if(affected_mob.dna?.species)
affected_mob.dna.species.handle_mutant_bodyparts(affected_mob,"#1d2953")
affected_mob.dna.species.handle_hair(affected_mob,"#1d2953")
affected_mob.visible_message("[affected_mob] looks terrifyingly gaunt...", "You suddenly feel like your skin is wrong...")
affected_mob.add_atom_colour("#1d2953", TEMPORARY_COLOUR_PRIORITY)
- addtimer(CALLBACK(src, .proc/cure), 100)
- else
- return
+ new /obj/effect/temp_visual/revenant(affected_mob.loc)
+ addtimer(CALLBACK(src, .proc/curses), 150)
+
+/datum/disease/revblight/proc/curses()
+ if(QDELETED(affected_mob))
+ return
+ affected_mob.playsound_local(affected_mob, 'sound/effects/curse5.ogg', 40, 1, -1)
+ to_chat(affected_mob, "You sense the terrific curse of a vengeful ghost befall upon you...")
+ affected_mob.apply_necropolis_curse(null, 7 MINUTES) //Once the blight has done its course without being cured beforehand, it will cast a necrocurse to compensate how underpowered it's.
+ cure()
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index 562d6f25..7207adc4 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -198,7 +198,7 @@
to_chat(user, "This artifact can only affect three undead at a time!")
return
- M.set_species(/datum/species/skeleton, icon_update=0)
+ M.set_species(/datum/species/skeleton/space, icon_update=0)
M.revive(full_heal = 1, admin_revive = 1)
spooky_scaries |= M
to_chat(M, "You have been revived by [user.real_name]!")
diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
index ea555c94..9c64328b 100644
--- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
+++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm
@@ -357,6 +357,9 @@
SSair.excited_groups -= src
////////////////////////SUPERCONDUCTIVITY/////////////////////////////
+/atom/movable/proc/blocksTemperature()
+ return FALSE
+
/turf/proc/conductivity_directions()
if(archived_cycle < SSair.times_fired)
archive()
@@ -371,6 +374,9 @@
. |= direction
/turf/proc/neighbor_conduct_with_src(turf/open/other)
+ for (var/atom/movable/G in src)
+ if (G.blocksTemperature())
+ return
if(!other.blocks_air) //Open but neighbor is solid
other.temperature_share_open_to_solid(src)
else //Both tiles are solid
@@ -382,6 +388,10 @@
..()
return
+
+ for (var/atom/movable/G in src)
+ if (G.blocksTemperature())
+ return
if(!other.blocks_air) //Both tiles are open
var/turf/open/T = other
T.air.temperature_share(air, WINDOW_HEAT_TRANSFER_COEFFICIENT)
diff --git a/code/modules/awaymissions/pamphlet.dm b/code/modules/awaymissions/pamphlet.dm
index 7cbbde09..399a6cda 100644
--- a/code/modules/awaymissions/pamphlet.dm
+++ b/code/modules/awaymissions/pamphlet.dm
@@ -3,18 +3,18 @@
icon_state = "pamphlet"
/obj/item/paper/pamphlet/gateway
- info = "Welcome to the Nanotrasen Gateway project... \
+ info = "Welcome to the Kinaris Gateway project... \
Congratulations! If you're reading this, you and your superiors have decided that you're \
ready to commit to a life spent colonising the rolling hills of far away worlds. You \
must be ready for a lifetime of adventure, a little bit of hard work, and an award \
- winning dental plan- but that's not all the Nanotrasen Gateway project has to offer. \
+ winning dental plan- but that's not all the Kinaris Gateway project has to offer. \
Because we care about you, we feel it is only fair to make sure you know the risks \
- before you commit to joining the Nanotrasen Gateway project. All away destinations have \
- been fully scanned by a Nanotrasen expeditionary team, and are certified to be 100% safe. \
+ before you commit to joining the Kinaris Gateway project. All away destinations have \
+ been fully scanned by a Kinaris expeditionary team, and are certified to be 100% safe. \
We've even left a case of space beer along with the basic materials you'll need to expand \
- Nanotrasen's operational area and start your new life.
\
+ Kinaris's operational area and start your new life.
\
Gateway Operation Basics \
- All Nanotrasen approved Gateways operate on the same basic principals. They operate off \
+ All Kinaris approved Gateways operate on the same basic principals. They operate off \
area equipment power as you would expect, and without this supply, it cannot safely function, \
causinng it to reject all attempts at operation.
\
Once it is correctly setup, and once it has enough power to operate, the Gateway will begin \
@@ -30,7 +30,7 @@
number of cases, the Gateway they have established may not be immediately obvious. \
Do not panic if you cannot locate the return Gateway. Begin colonisation of the destination. \
A New World \
- As a participant in the Nanotrasen Gateway Project, you will be on the frontiers of space. \
+ As a participant in the Kinaris Gateway Project, you will be on the frontiers of space. \
Though complete safety is assured, participants are advised to prepare for inhospitable \
environs."
diff --git a/code/modules/cargo/bounties/assistant.dm b/code/modules/cargo/bounties/assistant.dm
index cf4efaa8..6d85973f 100644
--- a/code/modules/cargo/bounties/assistant.dm
+++ b/code/modules/cargo/bounties/assistant.dm
@@ -1,19 +1,19 @@
/datum/bounty/item/assistant/strange_object
name = "Strange Object"
- description = "Nanotrasen has taken an interest in strange objects. Find one in maint, and ship it off to CentCom right away."
+ description = "Kinaris has taken an interest in strange objects. Find one in maint, and ship it off to CentCom right away."
reward = 1200
wanted_types = list(/obj/item/relic)
/datum/bounty/item/assistant/scooter
name = "Scooter"
- description = "Nanotrasen has determined walking to be wasteful. Ship a scooter to CentCom to speed operations up."
+ description = "Kinaris has determined walking to be wasteful. Ship a scooter to CentCom to speed operations up."
reward = 1080 // the mat hoffman
wanted_types = list(/obj/vehicle/ridden/scooter)
include_subtypes = FALSE
/datum/bounty/item/assistant/skateboard
name = "Skateboard"
- description = "Nanotrasen has determined walking to be wasteful. Ship a skateboard to CentCom to speed operations up."
+ description = "Kinaris has determined walking to be wasteful. Ship a skateboard to CentCom to speed operations up."
reward = 900 // the tony hawk
wanted_types = list(/obj/vehicle/ridden/scooter/skateboard)
@@ -180,7 +180,7 @@
/datum/bounty/item/assistant/ied
name = "IED"
- description = "Nanotrasen's maximum security prison at CentCom is undergoing personnel training. Ship a handful of IEDs to serve as a training tools."
+ description = "Kinaris's prison at CentCom is undergoing personnel training. Ship a handful of IEDs to serve as a training tools."
reward = 2000
required_count = 3
wanted_types = list(/obj/item/grenade/iedcasing)
diff --git a/code/modules/cargo/bounties/chef.dm b/code/modules/cargo/bounties/chef.dm
index b9d9ebc1..50da3c67 100644
--- a/code/modules/cargo/bounties/chef.dm
+++ b/code/modules/cargo/bounties/chef.dm
@@ -1,12 +1,12 @@
/datum/bounty/item/chef/birthday_cake
name = "Birthday Cake"
- description = "Nanotrasen's birthday is coming up! Ship them a birthday cake to celebrate!"
+ description = "Winfre's birthday is coming up! Ship them a birthday cake to celebrate!"
reward = 4000
wanted_types = list(/obj/item/reagent_containers/food/snacks/store/cake/birthday, /obj/item/reagent_containers/food/snacks/cakeslice/birthday)
/datum/bounty/item/chef/soup
name = "Soup"
- description = "To quell the homeless uprising, Nanotrasen will be serving soup to all underpaid workers. Ship any type of soup."
+ description = "To quell the homeless uprising, Kinaris will be serving soup to all underpaid workers. Ship any type of soup."
reward = 3000
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/soup)
@@ -20,7 +20,7 @@
/datum/bounty/item/chef/onionrings
name = "Onion Rings"
- description = "Nanotrasen is remembering Saturn day. Ship onion rings to show the station's support."
+ description = "Kinaris.co is remembering Saturn day. Ship onion rings to show the station's support."
reward = 3000
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/onionrings)
@@ -36,7 +36,7 @@
name = "Bread"
description = "Problems with central planning have led to bread prices skyrocketing. Ship some bread to ease tensions."
reward = 1000
- wanted_types = list(/obj/item/reagent_containers/food/snacks/store/bread, /obj/item/reagent_containers/food/snacks/breadslice, /obj/item/reagent_containers/food/snacks/bun, /obj/item/reagent_containers/food/snacks/pizzabread, /obj/item/reagent_containers/food/snacks/rawpastrybase)
+ wanted_types = list(/obj/item/reagent_containers/food/snacks/store/bread, /obj/item/reagent_containers/food/snacks/breadslice, /obj/item/reagent_containers/food/snacks/bun, /obj/item/reagent_containers/food/snacks/pizzabread, /obj/item/reagent_containers/food/snacks/rawpastrybase)
/datum/bounty/item/chef/pie
name = "Pie"
@@ -78,7 +78,7 @@
/datum/bounty/item/chef/hotdog
name = "Hot Dog"
- description = "Nanotrasen is conducting taste tests to determine the best hot dog recipe. Ship your station's version to participate."
+ description = "Kinaris.co is conducting taste tests to determine the best hot dog recipe. Ship your station's version to participate."
reward = 8000
wanted_types = list(/obj/item/reagent_containers/food/snacks/hotdog)
@@ -98,7 +98,7 @@
/datum/bounty/item/chef/chawanmushi
name = "Chawanmushi"
- description = "Nanotrasen wants to improve relations with its sister company, Japanotrasen. Ship Chawanmushi immediately."
+ description = "Kinaris.Co wants to improve relations with its sister company, Donk.Co. Ship Chawanmushi immediately."
reward = 8000
wanted_types = list(/obj/item/reagent_containers/food/snacks/chawanmushi)
@@ -117,7 +117,7 @@
/datum/bounty/item/chef/pancakes
name = "Pancakes"
- description = "Here at Nanotrasen we consider employees to be family. And you know what families love? Pancakes. Ship a baker's dozen."
+ description = "Here at Kinaris.Co we consider employees to be family. And you know what families love? Pancakes. Ship a baker's dozen."
reward = 5000
required_count = 13
wanted_types = list(/datum/crafting_recipe/food/pancakes)
diff --git a/code/modules/cargo/bounties/engineering.dm b/code/modules/cargo/bounties/engineering.dm
index cf2cd7d9..a0c3c577 100644
--- a/code/modules/cargo/bounties/engineering.dm
+++ b/code/modules/cargo/bounties/engineering.dm
@@ -21,7 +21,7 @@
/datum/bounty/item/engineering/gas/tritium_tank
name = "Full Tank of Tritium"
- description = "Station 49 is looking to kickstart their research program. Ship them a tank full of Tritium."
+ description = "Station 42 is looking to kickstart their research program. Ship them a tank full of Tritium."
gas_type = /datum/gas/tritium
/datum/bounty/item/engineering/pacman
diff --git a/code/modules/cargo/bounties/medical.dm b/code/modules/cargo/bounties/medical.dm
index 31290517..2e849792 100644
--- a/code/modules/cargo/bounties/medical.dm
+++ b/code/modules/cargo/bounties/medical.dm
@@ -48,7 +48,7 @@
/datum/bounty/item/medical/lizard_tail
name = "Lizard Tail"
- description = "The Wizard Federation has made off with Nanotrasen's supply of lizard tails. While CentCom is dealing with the wizards, can the station spare a tail of their own?"
+ description = "The Wizard Federation has made off with Kinaris.Co's supply of lizard tails. While CentCom is dealing with the wizards, can the station spare a tail of their own?"
reward = 3000
wanted_types = list(/obj/item/organ/tail/lizard)
@@ -60,7 +60,7 @@
/datum/bounty/item/medical/blood
name = "Generic Blood"
- description = "Nanotrasen's annual blood drive is back up to full speed, following the garlic incident. Good blood in good volumes accepted for Credit returns."
+ description = "The Kinaris annual blood drive is back up to full speed, following the garlic incident. Good blood in good volumes accepted for Credit returns."
reward = 3500
required_count = 600
wanted_types = list(/datum/reagent/blood)
@@ -79,7 +79,7 @@
required_count = 200
wanted_types = (L,/datum/reagent/blood)
if(istype(L,/datum/reagent/blood))
- wanted_types += L
+ wanted_types += L
/datum/bounty/item/medical/bloodu //Dosnt work do to how blood is yet*
name = "U-Type Blood"
@@ -88,7 +88,7 @@
required_count = 200
wanted_types = (U,/datum/reagent/blood)
if(istype(U,/datum/reagent/blood))
- wanted_types += U
+ wanted_types += U
*/
diff --git a/code/modules/cargo/bounties/reagent.dm b/code/modules/cargo/bounties/reagent.dm
index 3f458e2b..e6d2e91a 100644
--- a/code/modules/cargo/bounties/reagent.dm
+++ b/code/modules/cargo/bounties/reagent.dm
@@ -84,7 +84,7 @@ datum/bounty/reagent/simple_drink/New()
var/reagent_type = pick(possible_reagents)
wanted_reagent = new reagent_type
name = wanted_reagent.name
- description = "CentCom is thirsty! Send a shipment of [name] to CentCom to quench the company's thirst."
+ description = "Winfre is thirsty, Send a shipment of [name] to CentCom to quench her thirst."
reward += rand(0, 2) * 500
/datum/bounty/reagent/complex_drink
@@ -112,7 +112,7 @@ datum/bounty/reagent/complex_drink/New()
/datum/reagent/consumable/bluecherryshake,\
/datum/reagent/consumable/doctor_delight,\
/datum/reagent/consumable/ethanol/silencer)
-
+
var/reagent_type = pick(possible_reagents)
wanted_reagent = new reagent_type
name = wanted_reagent.name
diff --git a/code/modules/cargo/bounties/security.dm b/code/modules/cargo/bounties/security.dm
index cae8d10c..34c9856b 100644
--- a/code/modules/cargo/bounties/security.dm
+++ b/code/modules/cargo/bounties/security.dm
@@ -7,14 +7,14 @@
/datum/bounty/item/security/recharger
name = "Rechargers"
- description = "Nanotrasen military academy is conducting marksmanship exercises. They request that rechargers be shipped."
+ description = "Kinaris PMC is conducting marksmanship exercises. They request that rechargers be shipped."
reward = 2000
required_count = 3
wanted_types = list(/obj/machinery/recharger)
/datum/bounty/item/security/practice
name = "Practice Laser Gun"
- description = "Nanotrasen Military Academy is conducting routine marksmanship exercises. The clown hid all the practice lasers, and we're not using live weapons after last time."
+ description = "Kinaris PMC is conducting routine marksmanship exercises. The clown hid all the practice lasers, and we're not using live weapons after last time."
reward = 3000
required_count = 3
wanted_types = list(/obj/item/gun/energy/laser/practice)
@@ -27,28 +27,28 @@
/datum/bounty/item/security/sechuds
name = "Sec HUDs"
- description = "Nanotrasen military academy has started to train officers how to use Sec HUDs to the fullest affect. Please send spare Sec HUDs so we can teach the men."
+ description = "Nanotrasen PMC has started to train officers how to use Sec HUDs to the fullest affect. Please send spare Sec HUDs so we can teach the men."
reward = 3000
required_count = 5
wanted_types = list(/obj/item/clothing/glasses/hud/security)
/datum/bounty/item/security/techslugs
name = "Tech Slugs"
- description = "Nanotrasen Military Academy is conducting an ammo loading and use lessons, on the new 'Tech Slugs'. Problem is we don't have any, please fix this..."
+ description = "Kinaris PMC is conducting an ammo loading and use lessons, on the new 'Tech Slugs'. Problem is we don't have any, please fix this..."
reward = 7500
required_count = 15
wanted_types = list(/obj/item/ammo_casing/shotgun/techshell)
/datum/bounty/item/security/WT550
name = "Spare WT-550 clips"
- description = "Nanotrasen Military Academy's ammunition is running low, please send in spare ammo for practice."
+ description = "Kinaris Military Academy's ammunition is running low, please send in spare ammo for practice."
reward = 7500
required_count = 5
wanted_types = list(/obj/item/ammo_box/magazine/wt550m9)
/datum/bounty/item/security/pins
name = "Test range firing pins"
- description = "Nanotrasen Military Academy just got a new set of guns, sadly they didn't come with any pins. Can you send us some Test range locked firing pins?"
+ description = "Kinaris PMC just got a new set of guns, sadly they didn't come with any pins. Can you send us some Test range locked firing pins?"
reward = 5000
required_count = 3
wanted_types = list(/obj/item/firing_pin/test_range)
diff --git a/code/modules/cargo/bounties/slime.dm b/code/modules/cargo/bounties/slime.dm
index 4aa0797c..80b2dc4d 100644
--- a/code/modules/cargo/bounties/slime.dm
+++ b/code/modules/cargo/bounties/slime.dm
@@ -3,7 +3,7 @@
/datum/bounty/item/slime/New()
..()
- description = "Nanotrasen's science lead is hunting for the rare and exotic [name]. A bounty has been offered for finding it."
+ description = "Kinaris's head xenobiologist team is hunting for the rare and exotic [name]. A bounty has been offered for finding it."
reward += rand(0, 4) * 500
/datum/bounty/item/slime/green
diff --git a/code/modules/cargo/bounties/virus.dm b/code/modules/cargo/bounties/virus.dm
index 8f078a26..d514c3e3 100644
--- a/code/modules/cargo/bounties/virus.dm
+++ b/code/modules/cargo/bounties/virus.dm
@@ -10,7 +10,7 @@
if(rand(3) == 1)
stat_value *= -1
name = "Virus ([stat_name] of [stat_value])"
- description = "Nanotrasen is interested in a virus with a [stat_name] stat of exactly [stat_value]. Central Command will pay handsomely for such a virus."
+ description = "Kinaris.Co is interested in a virus with a [stat_name] stat of exactly [stat_value]. Central Command will pay handsomely for such a virus."
reward += rand(0, 4) * 500
/datum/bounty/virus/completion_string()
diff --git a/code/modules/cargo/bounty_console.dm b/code/modules/cargo/bounty_console.dm
index 2e5d943d..39465df7 100644
--- a/code/modules/cargo/bounty_console.dm
+++ b/code/modules/cargo/bounty_console.dm
@@ -1,8 +1,8 @@
#define PRINTER_TIMEOUT 10
/obj/machinery/computer/bounty
- name = "Nanotrasen bounty console"
- desc = "Used to check and claim bounties offered by Nanotrasen"
+ name = "Kinaris.Co bounty console"
+ desc = "Used to check and claim bounties offered by Kinaris"
icon_screen = "bounty"
circuit = /obj/item/circuitboard/computer/bounty
light_color = "#E2853D"//orange
@@ -20,7 +20,7 @@
/obj/item/paper/bounty_printout/Initialize()
. = ..()
- info = "
Nanotrasen Cargo Bounties
"
+ info = "
Kinaris.Co Cargo Bounties
"
for(var/datum/bounty/B in GLOB.bounties_list)
if(B.claimed)
continue
@@ -67,7 +67,7 @@
dat += ""
dat += ""
- var/datum/browser/popup = new(user, "bounties", "Nanotrasen Bounties", 700, 600)
+ var/datum/browser/popup = new(user, "bounties", "Kinaris Bounties", 700, 600)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 6f85668b..149416bf 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -2924,9 +2924,9 @@
name = "Kinkmate construction kit"
cost = 2000
contraband = TRUE
- contains = list(/obj/item/vending_refill/kink,
- /obj/item/vending_refill/kink,
- /obj/item/vending_refill/kink,
+ contains = list(/obj/item/vending_refill/kink,
+ /obj/item/vending_refill/kink,
+ /obj/item/vending_refill/kink,
/obj/item/circuitboard/machine/kinkmate)
crate_name = "Kinkmate construction kit"
@@ -2966,6 +2966,36 @@
crate_name = "captain pen"
crate_type = /obj/structure/closet/crate/secure/weapon //It is a combat pen
+/datum/supply_pack/misc/dueling_stam
+ name = "Dueling Pistols"
+ desc = "Resolve all your quarrels with some nonlethal fun."
+ cost = 2000
+ contains = list(/obj/item/storage/lockbox/dueling/hugbox/stamina,
+ /obj/item/storage/lockbox/dueling/hugbox/stamina,
+ /obj/item/storage/lockbox/dueling/hugbox/stamina,
+ /obj/item/storage/lockbox/dueling/hugbox/stamina,
+ /obj/item/storage/lockbox/dueling/hugbox/stamina)
+ crate_name = "dueling pistols"
+
+/datum/supply_pack/misc/dueling_lethal
+ name = "Lethal Dueling Pistols"
+ desc = "Settle your differences the true spaceman way."
+ cost = 3000
+ contraband = TRUE
+ contains = list(/obj/item/storage/lockbox/dueling/hugbox,
+ /obj/item/storage/lockbox/dueling/hugbox,
+ /obj/item/storage/lockbox/dueling/hugbox)
+ crate_name = "dueling pistols (lethal)"
+
+/datum/supply_pack/misc/dueling_death
+ name = "Elimination Dueling Pistols"
+ desc = "It's high noon."
+ cost = 5000
+ hidden = TRUE
+ contains = list(/obj/item/storage/lockbox/dueling)
+ crate_name = "dueling pistols (elimination)"
+
+
/datum/supply_pack/misc/exoticfootwear
name = "Exotic Footwear Crate"
desc = "Popularised by lizards and exotic dancers, the footwear included in this shipment is sure to give your feet the breathing room they deserve. Sweet Kicks Inc. is not responsible for any damage, distress, or @r0u$a1 caused by this shipment."
@@ -3006,7 +3036,7 @@
/obj/item/bedsheet/purple,
/obj/item/bedsheet/red,
/obj/item/bedsheet/yellow,
- /obj/item/bedsheet/brown,
+ /obj/item/bedsheet/brown,
/obj/item/bedsheet/black,
/obj/item/bedsheet/rainbow)
crate_name = "colored bedsheet crate"
diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm
index 0b83304f..3ddcdf80 100644
--- a/code/modules/client/asset_cache.dm
+++ b/code/modules/client/asset_cache.dm
@@ -571,6 +571,8 @@ GLOBAL_LIST_EMPTY(asset_datums)
"fontawesome-webfont.woff" = 'tgui/assets/fonts/fontawesome-webfont.woff',
"font-awesome.css" = 'code/modules/goonchat/browserassets/css/font-awesome.css',
"browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css',
+ "browserOutput_dark.css" = 'code/modules/goonchat/browserassets/css/browserOutput_dark.css',
+ "browserOutput_light.css" = 'code/modules/goonchat/browserassets/css/browserOutput_light.css'
)
/datum/asset/spritesheet/goonchat
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index 4e7ec45b..3dd76c75 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -80,4 +80,7 @@
var/client_keysend_amount = 0
var/next_keysend_reset = 0
var/next_keysend_trip_reset = 0
- var/keysend_tripped = FALSE
\ No newline at end of file
+ var/keysend_tripped = FALSE
+
+ /// Messages currently seen by this client
+ var/list/seen_messages
\ No newline at end of file
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 1713df90..94c9798d 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -458,6 +458,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
if(movingmob != null)
movingmob.client_mobs_in_contents -= mob
UNSETEMPTY(movingmob.client_mobs_in_contents)
+ seen_messages = null
Master.UpdateTickRate()
return ..()
diff --git a/code/modules/client/darkmode.dm b/code/modules/client/darkmode.dm
index 8d586100..f806e5c9 100644
--- a/code/modules/client/darkmode.dm
+++ b/code/modules/client/darkmode.dm
@@ -16,7 +16,7 @@ Thanks to spacemaniac and mcdonald for help with the JS side of this.
//Main windows
winset(src, "infowindow", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]")
winset(src, "info", "background-color = [COLOR_WHITEMODE_BACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]")
- winset(src, "browseroutput", "background-color = [COLOR_DARKMODE_INFO_BUTTONS_BG];text-color = [COLOR_WHITEMODE_TEXT]")
+ winset(src, "browseroutput", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]")
winset(src, "outputwindow", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]")
winset(src, "mainwindow", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND]")
winset(src, "split", "background-color = [COLOR_WHITEMODE_BACKGROUND]")
@@ -30,7 +30,9 @@ Thanks to spacemaniac and mcdonald for help with the JS side of this.
//Status and verb tabs
winset(src, "output", "background-color = [COLOR_WHITEMODE_BACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]")
winset(src, "statwindow", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]")
- winset(src, "stat", "background-color = [COLOR_WHITEMODE_BACKGROUND];tab-background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT];tab-text-color = [COLOR_WHITEMODE_TEXT];prefix-color = [COLOR_WHITEMODE_TEXT];suffix-color = [COLOR_WHITEMODE_TEXT]")
+ winset(src, "stat", "background-color = [COLOR_WHITEMODE_BACKGROUND];tab-background-color = [COLOR_WHITEMODE_DARKBACKGROUND];\
+ text-color = [COLOR_WHITEMODE_TEXT];tab-text-color = [COLOR_WHITEMODE_TEXT];\
+ prefix-color = [COLOR_WHITEMODE_TEXT];suffix-color = [COLOR_WHITEMODE_TEXT]")
//Etc.
winset(src, "say", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]")
winset(src, "asset_cache_browser", "background-color = [COLOR_WHITEMODE_DARKBACKGROUND];text-color = [COLOR_WHITEMODE_TEXT]")
@@ -54,24 +56,10 @@ Thanks to spacemaniac and mcdonald for help with the JS side of this.
//Status and verb tabs
winset(src, "output", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]")
winset(src, "statwindow", "background-color = [COLOR_DARKMODE_DARKBACKGROUND];text-color = [COLOR_DARKMODE_TEXT]")
- winset(src, "stat", "background-color = [COLOR_DARKMODE_DARKBACKGROUND];tab-background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT];tab-text-color = [COLOR_DARKMODE_TEXT];prefix-color = [COLOR_DARKMODE_TEXT];suffix-color = [COLOR_DARKMODE_TEXT]")
+ winset(src, "stat", "background-color = [COLOR_DARKMODE_DARKBACKGROUND];tab-background-color = [COLOR_DARKMODE_BACKGROUND];\
+ text-color = [COLOR_DARKMODE_TEXT];tab-text-color = [COLOR_DARKMODE_TEXT];\
+ prefix-color = [COLOR_DARKMODE_TEXT];suffix-color = [COLOR_DARKMODE_TEXT]")
//Etc.
winset(src, "say", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]")
winset(src, "asset_cache_browser", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]")
- winset(src, "tooltip", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]")
-
-
-/datum/asset/simple/goonchat
- verify = FALSE
- assets = list(
- "json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js',
- "errorHandler.js" = 'code/modules/goonchat/browserassets/js/errorHandler.js',
- "browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js',
- "fontawesome-webfont.eot" = 'tgui/assets/fonts/fontawesome-webfont.eot',
- "fontawesome-webfont.svg" = 'tgui/assets/fonts/fontawesome-webfont.svg',
- "fontawesome-webfont.ttf" = 'tgui/assets/fonts/fontawesome-webfont.ttf',
- "fontawesome-webfont.woff" = 'tgui/assets/fonts/fontawesome-webfont.woff',
- "font-awesome.css" = 'code/modules/goonchat/browserassets/css/font-awesome.css',
- "browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css',
- "browserOutput_white.css" = 'code/modules/goonchat/browserassets/css/browserOutput_white.css',
- )
\ No newline at end of file
+ winset(src, "tooltip", "background-color = [COLOR_DARKMODE_BACKGROUND];text-color = [COLOR_DARKMODE_TEXT]")
\ No newline at end of file
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 48673f47..78196e6a 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -45,6 +45,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/UI_style = null
var/buttons_locked = FALSE
var/hotkeys = FALSE
+ var/chat_on_map = TRUE
+ var/max_chat_length = CHAT_MESSAGE_MAX_LENGTH
+ var/see_chat_non_mob = TRUE
var/tgui_fancy = TRUE
var/tgui_lock = TRUE
var/windowflashing = TRUE
@@ -776,7 +779,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
dat += "Testicles Color: "
dat += "Change "
+ //dat += "Ball Circumference:[features["balls_size"]] inch(es)" // The menu works but doesn't do anything yet. Need to figure it out.
dat += "Testicles showing:[features["balls_shape"]]"
+ dat += "Produces:[features["balls_fluid"]]"
dat += APPEARANCE_CATEGORY_COLUMN
dat += "
Vagina
"
dat += "[features["has_vag"] == TRUE ? "Yes" : "No"]"
@@ -807,7 +812,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Lactates:[features["breasts_producing"] == TRUE ? "Yes" : "No"]"
if(features["breasts_producing"] == TRUE)
dat += "Produces:[features["breasts_fluid"]]"
-
+
dat += ""
dat += ""
dat += ""
@@ -818,6 +823,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "UI Style:[UI_style] "
dat += "tgui Monitors:[(tgui_lock) ? "Primary" : "All"] "
dat += "tgui Style:[(tgui_fancy) ? "Fancy" : "No Frills"] "
+ dat += "Show Runechat Chat Bubbles:[chat_on_map ? "Enabled" : "Disabled"] "
+ dat += "Runechat message char limit:[max_chat_length] "
+ dat += "See Runechat for non-mobs:[see_chat_non_mob ? "Enabled" : "Disabled"] "
dat += " "
dat += "Action Buttons:[(buttons_locked) ? "Locked In Place" : "Unlocked"] "
dat += "Keybindings:[(hotkeys) ? "Hotkeys" : "Default"] "
@@ -1973,6 +1981,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(new_length)
features["cock_length"] = max(min( round(text2num(new_length)), COCK_SIZE_MAX),COCK_SIZE_MIN)
+ if("balls_size")
+ var/new_balls_size = input(user, "Testicle circumference in inches:\n([BALLS_SIZE_MIN]-[BALLS_SIZE_MAX])", "Character Preference") as num|null
+ if(new_balls_size)
+ features["balls_size"] = max(min( round(text2num(new_balls_size)), BALLS_SIZE_MAX),BALLS_SIZE_MIN)
+
if("cock_shape")
var/new_shape
new_shape = input(user, "Penis shape:", "Character Preference") as null|anything in GLOB.cock_shapes_list
@@ -1996,6 +2009,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(new_shape)
features["balls_shape"] = new_shape
+ if("balls_fluid")
+ var/new_shape
+ new_shape = input(user, "Balls Fluid", "Character Preference") as null|anything in GLOB.genital_fluids_list
+ if(new_shape)
+ features["balls_fluid"] = new_shape
+
if("egg_size")
var/new_size
var/list/egg_sizes = list(1,2,3)
@@ -2023,7 +2042,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
new_shape = input(user, "Breast Shape", "Character Preference") as null|anything in GLOB.breasts_shapes_list
if(new_shape)
features["breasts_shape"] = new_shape
-
+
if("breasts_fluid")
var/new_shape
new_shape = input(user, "Breast Fluid", "Character Preference") as null|anything in GLOB.genital_fluids_list
@@ -2144,6 +2163,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/pickedPDASkin = input(user, "Choose your PDA reskin.", "Character Preference", pda_skin) as null|anything in GLOB.pda_reskins
if(pickedPDASkin)
pda_skin = pickedPDASkin
+ if ("max_chat_length")
+ var/desiredlength = input(user, "Choose the max character length of shown Runechat messages. Valid range is 1 to [CHAT_MESSAGE_MAX_LENGTH] (default: [initial(max_chat_length)]))", "Character Preference", max_chat_length) as null|num
+ if (!isnull(desiredlength))
+ max_chat_length = clamp(desiredlength, 1, CHAT_MESSAGE_MAX_LENGTH)
else
switch(href_list["preference"])
@@ -2229,6 +2252,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
winset(user, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=old_default")
if("action_buttons")
buttons_locked = !buttons_locked
+ if("chat_on_map")
+ chat_on_map = !chat_on_map
+ if("see_chat_non_mob")
+ see_chat_non_mob = !see_chat_non_mob
if("tgui_fancy")
tgui_fancy = !tgui_fancy
if("tgui_lock")
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index d9ec2c66..fc619515 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -100,6 +100,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["inquisitive_ghost"] >> inquisitive_ghost
S["uses_glasses_colour"]>> uses_glasses_colour
S["clientfps"] >> clientfps
+ S["chat_on_map"] >> chat_on_map
+ S["max_chat_length"] >> max_chat_length
+ S["see_chat_non_mob"] >> see_chat_non_mob
+
S["parallax"] >> parallax
S["ambientocclusion"] >> ambientocclusion
@@ -129,6 +133,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
UI_style = sanitize_inlist(UI_style, GLOB.available_ui_styles, GLOB.available_ui_styles[1])
hotkeys = sanitize_integer(hotkeys, 0, 1, initial(hotkeys))
+ chat_on_map = sanitize_integer(chat_on_map, 0, 1, initial(chat_on_map))
+ max_chat_length = sanitize_integer(max_chat_length, 1, CHAT_MESSAGE_MAX_LENGTH, initial(max_chat_length))
+ see_chat_non_mob = sanitize_integer(see_chat_non_mob, 0, 1, initial(see_chat_non_mob))
tgui_fancy = sanitize_integer(tgui_fancy, 0, 1, initial(tgui_fancy))
tgui_lock = sanitize_integer(tgui_lock, 0, 1, initial(tgui_lock))
buttons_locked = sanitize_integer(buttons_locked, 0, 1, initial(buttons_locked))
@@ -180,6 +187,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["lastchangelog"], lastchangelog)
WRITE_FILE(S["UI_style"], UI_style)
WRITE_FILE(S["hotkeys"], hotkeys)
+ WRITE_FILE(S["chat_on_map"], chat_on_map)
+ WRITE_FILE(S["max_chat_length"], max_chat_length)
+ WRITE_FILE(S["see_chat_non_mob"], see_chat_non_mob)
WRITE_FILE(S["tgui_fancy"], tgui_fancy)
WRITE_FILE(S["tgui_lock"], tgui_lock)
WRITE_FILE(S["buttons_locked"], buttons_locked)
diff --git a/code/modules/client/verbs/looc.dm b/code/modules/client/verbs/looc.dm
index c365af2e..84d1c3af 100644
--- a/code/modules/client/verbs/looc.dm
+++ b/code/modules/client/verbs/looc.dm
@@ -1,3 +1,4 @@
+
GLOBAL_VAR_INIT(LOOC_COLOR, null)//If this is null, use the CSS for OOC. Otherwise, use a custom colour.
GLOBAL_VAR_INIT(normal_looc_colour, "#6699CC")
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 08adb8e5..b51b6a5e 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -47,8 +47,8 @@
//Basically syntax is species_restricted = list("Species Name","Species Name")
//Add a "exclude" string to do the opposite, making it only only species listed that can't wear it.
//You append this to clothing objects.
-
-
+ //Hyper change// - Variables for HS13 checks
+ var/roomy = 0 //0 For false
/obj/item/clothing/Initialize()
@@ -95,6 +95,18 @@
obj_integrity = max_integrity
to_chat(user, "You fix the damage on [src] with [C].")
return 1
+ //Hyper Change//
+ if(istype(W, /obj/item/bluespace_thread))
+ var/obj/item/bluespace_thread/B = W
+ if ((istype(src, /obj/item/clothing/under) || istype(src, /obj/item/clothing/suit)) && roomy != 1) //Make sure the thread is used on an item that could be ripped off in the first place
+ roomy = 1 //True
+ user.show_message("You add a few stiches to your clothing, and find them to fit a little looser.", 1)
+ B.uses -= 1 //One use has been used
+ if(B.uses <= 0)
+ user.show_message("The thread has been used up!", 1)
+ qdel(B)
+ else
+ user.show_message("You probably don't need any more room in that.", 1)
return ..()
/obj/item/clothing/Destroy()
diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index 67303fe9..40d01607 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -16,19 +16,26 @@
dog_fashion = /datum/dog_fashion/head
-/obj/item/clothing/head/hardhat/attack_self(mob/user)
- on = !on
- icon_state = "hardhat[on]_[item_color]"
- item_state = "hardhat[on]_[item_color]"
- user.update_inv_head() //so our mob-overlays update
+/obj/item/clothing/head/hardhat/attack_self(mob/living/user)
+ toggle_helmet_light(user)
+/obj/item/clothing/head/hardhat/proc/toggle_helmet_light(mob/living/user)
+ on = !on
if(on)
turn_on(user)
else
turn_off(user)
+ update_icon()
+
+/obj/item/clothing/head/hardhat/update_icon()
+ icon_state = "hardhat[on]_[item_color]"
+ item_state = "hardhat[on]_[item_color]"
+ if(ishuman(loc))
+ var/mob/living/carbon/human/H = loc
+ H.update_inv_head()
for(var/X in actions)
var/datum/action/A = X
- A.UpdateButtonIcon()
+ A.UpdateButtonIcon(force = TRUE)
/obj/item/clothing/head/hardhat/proc/turn_on(mob/user)
set_light(brightness_on, power_on)
@@ -85,3 +92,68 @@
cold_protection = HEAD
min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
mutantrace_variation = MUTANTRACE_VARIATION
+
+/obj/item/clothing/head/hardhat/weldhat
+ name = "welding hard hat"
+ desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight AND welding shield! The bulb seems a little smaller though."
+ brightness_on = 3 //Needs a little bit of tradeoff
+ dog_fashion = null
+ actions_types = list(/datum/action/item_action/toggle_helmet_light, /datum/action/item_action/toggle_welding_screen)
+ flash_protect = 2
+ tint = 2
+ flags_inv = HIDEEYES | HIDEFACE
+ flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
+ visor_vars_to_toggle = VISOR_FLASHPROTECT | VISOR_TINT
+ visor_flags_inv = HIDEEYES | HIDEFACE
+ visor_flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
+
+/obj/item/clothing/head/hardhat/weldhat/Initialize()
+ . = ..()
+ update_icon()
+
+/obj/item/clothing/head/hardhat/weldhat/attack_self(mob/living/user)
+ toggle_helmet_light(user)
+
+/obj/item/clothing/head/hardhat/weldhat/AltClick(mob/user)
+ if(user.canUseTopic(src, BE_CLOSE))
+ toggle_welding_screen(user)
+
+/obj/item/clothing/head/hardhat/weldhat/proc/toggle_welding_screen(mob/living/user)
+ if(weldingvisortoggle(user))
+ playsound(src, 'sound/mecha/mechmove03.ogg', 30, TRUE) //Visors don't just come from nothing
+ update_icon()
+
+/obj/item/clothing/head/hardhat/weldhat/worn_overlays(isinhands)
+ . = ..()
+ if(!isinhands)
+ . += mutable_appearance('icons/mob/head.dmi', "weldhelmet")
+ if(!up)
+ . += mutable_appearance('icons/mob/head.dmi', "weldvisor")
+
+/obj/item/clothing/head/hardhat/weldhat/update_icon()
+ cut_overlays()
+ if(!up)
+ add_overlay("weldvisor")
+ ..()
+
+/obj/item/clothing/head/hardhat/weldhat/orange
+ icon_state = "hardhat0_orange"
+ item_state = "hardhat0_orange"
+ item_color = "orange"
+
+/obj/item/clothing/head/hardhat/weldhat/white
+ desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight AND welding shield!" //This bulb is not smaller
+ icon_state = "hardhat0_white"
+ item_state = "hardhat0_white"
+ brightness_on = 4 //Boss always takes the best stuff
+ item_color = "white"
+ clothing_flags = STOPSPRESSUREDAMAGE
+ heat_protection = HEAD
+ max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT
+ cold_protection = HEAD
+ min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
+
+/obj/item/clothing/head/hardhat/weldhat/dblue
+ icon_state = "hardhat0_dblue"
+ item_state = "hardhat0_dblue"
+ item_color = "dblue"
\ No newline at end of file
diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm
index 325c1248..ae5da913 100644
--- a/code/modules/clothing/outfits/standard.dm
+++ b/code/modules/clothing/outfits/standard.dm
@@ -203,16 +203,18 @@
name = "CentCom Commander"
uniform = /obj/item/clothing/under/rank/centcom_commander
- suit = /obj/item/clothing/suit/armor/bulletproof
+ suit = /obj/item/clothing/suit/hooded/wintercoat/centcom
shoes = /obj/item/clothing/shoes/combat/swat
gloves = /obj/item/clothing/gloves/combat
ears = /obj/item/radio/headset/headset_cent/commander
- glasses = /obj/item/clothing/glasses/eyepatch
+ glasses = /obj/item/clothing/glasses/thermal/eyepatch
mask = /obj/item/clothing/mask/cigarette/cigar/cohiba
head = /obj/item/clothing/head/centhat
- belt = /obj/item/gun/ballistic/revolver/mateba
+ neck = /obj/item/clothing/neck/cloak/centcom
+ belt = /obj/item/gun/ballistic/automatic/pistol/lato
r_pocket = /obj/item/lighter
- l_pocket = /obj/item/ammo_box/a357
+ l_pocket = /obj/item/ammo_box/magazine/latomag
+ l_hand = /obj/item/ammo_box/magazine/latomag
back = /obj/item/storage/backpack/satchel/leather
id = /obj/item/card/id
diff --git a/code/modules/clothing/shoes/vg_shoes.dm b/code/modules/clothing/shoes/vg_shoes.dm
index 931c25b8..3c2931a1 100644
--- a/code/modules/clothing/shoes/vg_shoes.dm
+++ b/code/modules/clothing/shoes/vg_shoes.dm
@@ -14,19 +14,20 @@
icon_state = "DS-magboots0"
magboot_state = "DS-magboots"
icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/head.dmi'
+ alternate_worn_icon = 'icons/mob/feet.dmi'
+ slowdown_active = SHOES_SLOWDOWN
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- mutantrace_variation = NO_MUTANTRACE_VARIATION
+ mutantrace_variation = MUTANTRACE_VARIATION
/obj/item/clothing/shoes/magboots/atmos
desc = "Magnetic boots, often used during extravehicular activity to ensure the user remains safely attached to the vehicle. These are painted in the colors of an atmospheric technician."
name = "atmospherics magboots"
icon_state = "atmosmagboots0"
icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
- alternate_worn_icon = 'modular_citadel/icons/mob/citadel/head.dmi'
+ alternate_worn_icon = 'icons/mob/feet.dmi'
magboot_state = "atmosmagboots"
resistance_flags = FIRE_PROOF
- mutantrace_variation = NO_MUTANTRACE_VARIATION
+ mutantrace_variation = MUTANTRACE_VARIATION
/obj/item/clothing/shoes/simonshoes
name = "Simon's Shoes"
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 85503c72..9bb9453b 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -556,7 +556,7 @@
/obj/item/clothing/suit/space/hardsuit/captain
name = "captain's SWAT suit"
- desc = "A MK.II SWAT suit with streamlined joints and armor made out of superior materials, insulated against intense heat. The most advanced tactical armor available Usually reserved for heavy hitter corporate security, this one has a regal finish in Nanotrasen company colors. Better not let the assistants get a hold of it."
+ desc = "A MK.II SWAT suit with streamlined joints and armor made out of superior materials, insulated against intense heat. The most advanced tactical armor available Usually reserved for heavy hitter corporate security. Better not let the assistants get a hold of it."
icon_state = "caparmor"
item_state = "capspacesuit"
armor = list("melee" = 40, "bullet" = 50, "laser" = 50, "energy" = 25, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100)
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 0840288e..07d76fe3 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -249,3 +249,13 @@
max_integrity = 200
resistance_flags = FLAMMABLE
armor = list("melee" = 20, "bullet" = 10, "laser" = 30, "energy" = 5, "bomb" = 15, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 50)
+
+/obj/item/clothing/suit/armor/monolith
+ name = "Monolith suit"
+ desc = "The producer is unknown. Its protective properties are slightly worse then those of the bulletproof vest. Its structure combines a bulletproof vest and radiation protection plates. It provides good protection from gunfire."
+ icon_state = "monolit"
+ item_state = "monolit"
+ blood_overlay_type = "armor"
+ armor = list("melee" = 15, "bullet" = 55, "laser" = 5, "energy" = 5, "bomb" = 40, "bio" = 30, "rad" = 30, "fire" = 50, "acid" = 50)
+ strip_delay = 70
+ equip_delay_other = 50
diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm
index c3276213..4e7fce0f 100644
--- a/code/modules/clothing/suits/cloaks.dm
+++ b/code/modules/clothing/suits/cloaks.dm
@@ -55,6 +55,13 @@
desc = "Worn by the Head of Personnel. It smells faintly of bureaucracy."
icon_state = "hopcloak"
+/obj/item/clothing/neck/cloak/centcom
+ name = "central command's cloak"
+ desc = "Worn by High-Ranking Central Command Personnel. I guess they needed one too."
+ icon_state = "centcomcloak"
+ armor = list("melee" = 35, "bullet" = 40, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 20, "rad" = 20, "fire" = 60, "acid" = 60)
+ body_parts_covered = CHEST|GROIN|ARMS
+
/obj/item/clothing/suit/hooded/cloak/goliath
name = "goliath cloak"
icon_state = "goliath_cloak"
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index b3b9c0c5..8eb8c08f 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -113,15 +113,15 @@
item_color = "vice"
can_adjust = FALSE
/obj/item/clothing/under/rank/centcom_officer
- desc = "It's a jumpsuit worn by CentCom Officers."
- name = "\improper CentCom officer's jumpsuit"
+ desc = "CentCom officer's jumpsuit, adorned with a golden K and a star, signifying work under Kinaris."
+ name = "\improper CentCom Officer's jumpsuit"
icon_state = "officer"
item_state = "g_suit"
item_color = "officer"
alt_covers_chest = TRUE
/obj/item/clothing/under/rank/centcom_commander
- desc = "It's a jumpsuit worn by CentCom's highest-tier Commanders."
- name = "\improper CentCom officer's jumpsuit"
+ desc = "It's a jumpsuit worn by CentCom's highest-tier Commanders, adorned with a golden K and a star. signifying work under Kinaris."
+ name = "\improper CentCom Commander's jumpsuit"
icon_state = "centcom"
item_state = "dg_suit"
item_color = "centcom"
@@ -755,4 +755,14 @@
icon_state = "christmasfemaleg"
item_state = "christmasfemaleg"
body_parts_covered = CHEST|GROIN
- can_adjust = FALSE
\ No newline at end of file
+ can_adjust = FALSE
+
+/obj/item/clothing/under/zone/monolith
+ name = "Urban BDU"
+ desc = "A splinter urban camouflage Battle-Dress uniform."
+ icon_state = "camourban"
+ item_state = "camourban"
+ body_parts_covered = CHEST|GROIN|ARMS|LEGS
+ fitted = NO_FEMALE_UNIFORM
+ can_adjust = FALSE
+ resistance_flags = NONE
diff --git a/code/modules/events/aurora_caelus.dm b/code/modules/events/aurora_caelus.dm
index 89a84d34..85bb7960 100644
--- a/code/modules/events/aurora_caelus.dm
+++ b/code/modules/events/aurora_caelus.dm
@@ -14,13 +14,13 @@
announceWhen = 1
startWhen = 9
endWhen = 50
- var/list/aurora_colors = list("#A2FF80", "#A2FF8B", "#A2FF96", "#A2FFA5", "#A2FFB6", "#A2FFC7", "#A2FFDE", "#A2FFEE")
+ var/list/aurora_colors = list("#ffd980", "#eaff80", "#eaff80", "#ffd980", "#eaff80", "#A2FFC7", "#A2FFDE", "#ffd980")
var/aurora_progress = 0 //this cycles from 1 to 8, slowly changing colors from gentle green to gentle blue
/datum/round_event/aurora_caelus/announce()
- priority_announce("[station_name()]: A harmless cloud of ions is approaching your station, and will exhaust their energy battering the hull. Nanotrasen has approved a short break for all employees to relax and observe this very rare event. During this time, starlight will be bright but gentle, shifting between quiet green and blue colors. Any staff who would like to view these lights for themselves may proceed to the area nearest to them with viewing ports to open space. We hope you enjoy the lights.",
+ priority_announce("[station_name()]: A harmless cloud of ions is approaching your station, and will exhaust their energy battering the hull. Kinaris Command has approved a short break for all employees to relax and observe this very rare event. During this time, starlight will be bright but gentle, shifting between quiet green and blue colors. Any staff who would like to view these lights for themselves may proceed to the area nearest to them with viewing ports to open space. We hope you enjoy the lights.",
sound = 'sound/misc/notice2.ogg',
- sender_override = "Nanotrasen Meteorology Division")
+ sender_override = "Kinaris Meteorology Division")
for(var/V in GLOB.player_list)
var/mob/M = V
if((M.client.prefs.toggles & SOUND_MIDI) && is_station_level(M.z))
@@ -51,7 +51,7 @@
fade_to_black(S)
priority_announce("The aurora caelus event is now ending. Starlight conditions will slowly return to normal. When this has concluded, please return to your workplace and continue work as normal. Have a pleasant shift, [station_name()], and thank you for watching with us.",
sound = 'sound/misc/notice2.ogg',
- sender_override = "Nanotrasen Meteorology Division")
+ sender_override = "Kinaris Meteorology Division")
/datum/round_event/aurora_caelus/proc/fade_to_black(turf/open/space/S)
set waitfor = FALSE
diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm
index 6081bb36..4ffa6b21 100644
--- a/code/modules/events/carp_migration.dm
+++ b/code/modules/events/carp_migration.dm
@@ -1,8 +1,8 @@
/datum/round_event_control/carp_migration
name = "Carp Migration"
typepath = /datum/round_event/carp_migration
- weight = 15
- min_players = 2
+ weight = 10 //decreased weight from 15 to 10
+ min_players = 5 //increased min players from 2 to 5 to reduce chances of half the crew dying in a carp breach
earliest_start = 10 MINUTES
max_occurrences = 6
diff --git a/code/modules/events/high_priority_bounty.dm b/code/modules/events/high_priority_bounty.dm
index ffdcd884..d629a0b8 100644
--- a/code/modules/events/high_priority_bounty.dm
+++ b/code/modules/events/high_priority_bounty.dm
@@ -6,7 +6,7 @@
earliest_start = 10
/datum/round_event/high_priority_bounty/announce(fake)
- priority_announce("Central Command has issued a high-priority cargo bounty. Details have been sent to all bounty consoles.", "Nanotrasen Bounty Program")
+ priority_announce("C.C has issued a high-priority bounty. Details have been uploaded to all bounty consoles.", "Kinaris Corp Bounty Program")
/datum/round_event/high_priority_bounty/start()
var/datum/bounty/B
diff --git a/code/modules/events/meteor_wave.dm b/code/modules/events/meteor_wave.dm
index 743f2edf..662053f8 100644
--- a/code/modules/events/meteor_wave.dm
+++ b/code/modules/events/meteor_wave.dm
@@ -1,5 +1,8 @@
// Normal strength
+#define SINGULO_BEACON_DISTURBANCE 0.2 //singularity beacon also improve the odds of meteor waves and speed them up a little.
+#define SINGULO_BEACON_MAX_DISTURBANCE 0.6 //maximum cap due to how meteor waves can be potentially round ending.
+
/datum/round_event_control/meteor_wave
name = "Meteor Wave: Normal"
typepath = /datum/round_event/meteor_wave
@@ -18,6 +21,8 @@
/datum/round_event/meteor_wave/setup()
announceWhen = 1
startWhen = rand(300, 600) //Yeah for SOME REASON this is measured in seconds and not deciseconds???
+ if(GLOB.singularity_counter)
+ startWhen *= 1 - min(GLOB.singularity_counter * SINGULO_BEACON_DISTURBANCE, SINGULO_BEACON_MAX_DISTURBANCE)
endWhen = startWhen + 60
@@ -52,7 +57,7 @@
kill()
/datum/round_event/meteor_wave/announce(fake)
- priority_announce("Meteors have been detected on collision course with the station. Estimated time until impact: [round(startWhen/60)] minutes.", "Meteor Alert", 'sound/ai/meteors.ogg')
+ priority_announce("Meteors have been detected on collision course with the station. Estimated time until impact: [round(startWhen/60)] minutes.[GLOB.singularity_counter ? " Warning: Anomalous gravity pulse detected, Syndicate technology interference likely." : ""]", "Meteor Alert", 'sound/ai/meteors.ogg')
/datum/round_event/meteor_wave/tick()
if(ISMULTIPLE(activeFor, 3))
@@ -79,3 +84,6 @@
/datum/round_event/meteor_wave/catastrophic
wave_name = "catastrophic"
+
+#undef SINGULO_BEACON_DISTURBANCE
+#undef SINGULO_BEACON_MAX_DISTURBANCE
\ No newline at end of file
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 88f72d27..54ca1808 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -683,31 +683,27 @@ GLOBAL_LIST_INIT(hallucination_list, list(
if(get_dist(target,H)This does not fit in the fryer.") // TODO: Deepfrying instakills mobs, spawns a whole deep-fried mob.
+ return
if(!reagents.has_reagent("cooking_oil"))
to_chat(user, "[src] has no cooking oil to fry with!")
return
diff --git a/code/modules/food_and_drinks/recipes/drinks_recipes.dm b/code/modules/food_and_drinks/recipes/drinks_recipes.dm
index a74f73ed..e66870dc 100644
--- a/code/modules/food_and_drinks/recipes/drinks_recipes.dm
+++ b/code/modules/food_and_drinks/recipes/drinks_recipes.dm
@@ -259,10 +259,10 @@
required_reagents = list("gin" = 2, "sodawater" = 1, "limejuice" = 1)
/datum/chemical_reaction/bahama_mama
- name = "Bahama mama"
+ name = "Bahama Mama"
id = "bahama_mama"
- results = list("bahama_mama" = 6)
- required_reagents = list("rum" = 2, "orangejuice" = 2, "limejuice" = 1, "ice" = 1)
+ results = list("bahama_mama" = 5)
+ required_reagents = list("rum" = 2, "creme_de_coconut" = 1, "kahlua" = 1, "pineapplejuice" = 1)
/datum/chemical_reaction/singulo
name = "Singulo"
@@ -301,6 +301,19 @@
required_reagents = list("berryjuice" = 1, "cream" = 1, "vermouth" = 1)
+/datum/chemical_reaction/painkiller
+ name = "Painkiller"
+ id = "painkiller"
+ results = list("painkiller" = 10)
+ required_reagents = list("creme_de_coconut" = 5, "pineapplejuice" = 4, "orangejuice" = 1)
+
+/datum/chemical_reaction/pina_colada
+ name = "Pina Colada"
+ id = "pina_colada"
+ results = list("pina_colada" = 5)
+ required_reagents = list("creme_de_coconut" = 1, "pineapplejuice" = 2, "rum" = 1, "limejuice" = 1)
+
+
////DRINKS THAT REQUIRED IMPROVED SPRITES BELOW:: -Agouri/////
/datum/chemical_reaction/sbiten
@@ -381,6 +394,33 @@
id = "neurotoxin"
results = list("neurotoxin" = 2)
required_reagents = list("gargleblaster" = 1, "morphine" = 1)
+ //FermiChem vars: Easy to make, but hard to make potent
+ OptimalTempMin = 200 // Lower area of bell curve for determining heat based rate reactions
+ OptimalTempMax = 950 // Upper end for above
+ ExplodeTemp = 999 //Temperature at which reaction explodes
+ OptimalpHMin = 2 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase)
+ OptimalpHMax = 3 // Higest value for above
+ ReactpHLim = 5 // How far out pH wil react, giving impurity place (Exponential phase)
+ CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst)
+ CurveSharpT = 2 // How sharp the temperature exponential curve is (to the power of value)
+ CurveSharppH = 4 // How sharp the pH exponential curve is (to the power of value)
+ ThermicConstant = 10 //Temperature change per 1u produced
+ HIonRelease = 0.02 //pH change per 1u reaction
+ RateUpLim = 5 //Optimal/max rate possible if all conditions are perfect
+ FermiChem = TRUE//If the chemical uses the Fermichem reaction mechanics
+ FermiExplode = FALSE //If the chemical explodes in a special way
+ PurityMin = 0 //The minimum purity something has to be above, otherwise it explodes.
+ clear_conversion = REACTION_CLEAR_INVERSE
+
+/*
+/datum/chemical_reaction/neurotoxin/FermiFinish(datum/reagents/holder, var/atom/my_atom)
+ var/datum/reagent/consumable/ethanol/neurotoxin/Nt = locate(/datum/reagent/consumable/ethanol/neurotoxin) in my_atom.reagents.reagent_list
+ if(Nt)
+ var/cached_volume = Nt.volume
+ if(Nt.purity < 0.5)
+ holder.remove_reagent(src.id, cached_volume)
+ holder.add_reagent("neurosmash", cached_volume)
+*/
/datum/chemical_reaction/snowwhite
name = "Snow White"
@@ -806,8 +846,8 @@
/datum/chemical_reaction/hellfire
name = "Hellfire"
id = "hellfire"
- results = list("hellfire" = 5)
- required_reagents = list("rum" = 1, "beer" = 1, "ice" = 1, "capsaicin" = 1, "limejuice" = 1)
+ results = list("hellfire" = 4)
+ required_reagents = list("rum" = 2, "ice" = 1, "crevice_spike" = 1)
mix_message = "The liquid begins to churn as it changes to an amber orange and catches on fire."
/datum/chemical_reaction/sins_delight
@@ -816,3 +856,33 @@
results = list("sins_delight" = 5)
required_reagents = list("demonsblood" = 2, "triple_sec" = 1, "martini" = 1, "changelingsting" = 1)
mix_message = "The liquid starts swirling, before forming a pink cloud that dissipates in the air."
+
+/datum/chemical_reaction/strawberry_daiquiri
+ name = "Strawberry Daiquiri"
+ id = "strawberry_daiquiri"
+ results = list("strawberry_daiquiri" = 7)
+ required_reagents = list("rum" = 2, "limejuice" = 1, "sugar" = 1, "strawberryjuice" = 2, "ice" = 1)
+
+/datum/chemical_reaction/miami_vice
+ name = "Miami Vice"
+ id = "miami_vice"
+ results = list("miami_vice" = 2)
+ required_reagents = list("pina_colada" = 1, "strawberry_daiquiri" = 1)
+
+/datum/chemical_reaction/malibu_sunset
+ name = "Malibu Sunset"
+ id = "malibu_sunset"
+ results = list("malibu_sunset" = 5)
+ required_reagents = list("creme_de_coconut" = 1, "pineapplejuice" = 1, "grenadine" = 1, "orangejuice" = 1, "ice" = 1)
+
+/datum/chemical_reaction/liz_fizz
+ name = "Liz Fizz"
+ id = "liz_fizz"
+ results = list("liz_fizz" = 5)
+ required_reagents = list("triple_citrus" = 3, "ice" = 1, "cream" = 1)
+
+/datum/chemical_reaction/hotlime_miami
+ name = "Hotlime Miami"
+ id = "hotlime_miami"
+ results = list("hotlime_miami" = 2)
+ required_reagents = list("ephedrine" = 1, "pina_colada" = 1)
\ No newline at end of file
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
index d7beebf4..806358b6 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
@@ -176,7 +176,7 @@
)
result = /obj/item/reagent_containers/food/snacks/burger/purple
subcategory = CAT_BURGER
-
+
/datum/crafting_recipe/food/blackburger
name = "Black burger"
reqs = list(
@@ -186,7 +186,7 @@
)
result = /obj/item/reagent_containers/food/snacks/burger/black
subcategory = CAT_BURGER
-
+
/datum/crafting_recipe/food/whiteburger
name = "White burger"
reqs = list(
@@ -293,3 +293,12 @@
result = /obj/item/reagent_containers/food/snacks/burger/baconburger
subcategory = CAT_BURGER
+
+/datum/crafting_recipe/food/cumburger
+ name = "Cumburger"
+ reqs = list(
+ /datum/reagent/consumable/semen = 10,
+ /obj/item/reagent_containers/food/snacks/bun = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/burger/cumburger
+ subcategory = CAT_BURGER
\ No newline at end of file
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_frozen.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_frozen.dm
index 73b09df6..1d32ae57 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_frozen.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_frozen.dm
@@ -60,7 +60,7 @@
/obj/item/reagent_containers/food/drinks/sillycup = 1,
/datum/reagent/water = 5,
/datum/reagent/consumable/ice = 15,
- /obj/item/reagent_containers/food/snacks/pineappleslice = 2
+ /datum/reagent/consumable/pineapplejuice = 5
)
result = /obj/item/reagent_containers/food/snacks/snowcones/pineapple
subcategory = CAT_ICE
diff --git a/code/modules/goonchat/browserOutput.dm b/code/modules/goonchat/browserOutput.dm
index 7fe6b41b..ac3886b8 100644
--- a/code/modules/goonchat/browserOutput.dm
+++ b/code/modules/goonchat/browserOutput.dm
@@ -5,17 +5,9 @@ For the main html chat area
//Precaching a bunch of shit
GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of icons for the browser output
-//Should match the value set in the browser js
-#define MAX_COOKIE_LENGTH 5
-
-
//On client, created on login
/datum/chatOutput
var/client/owner //client ref
- // How many times client data has been checked
- var/total_checks = 0
- // When to next clear the client data checks counter
- var/next_time_to_clear = 0
var/loaded = FALSE // Has the client loaded the browser output area?
var/list/messageQueue //If they haven't loaded chat, this is where messages will go until they do
var/cookieSent = FALSE // Has the client sent a cookie for analysis
@@ -90,11 +82,13 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
if("setMusicVolume")
data = setMusicVolume(arglist(params))
- if("swaptodarkmode")
- swaptodarkmode()
+ if("colorPresetPost") //User just swapped color presets in their goonchat preferences. Do we do anything else?
+ switch(href_list["preset"])
+ if("light")
+ owner.force_white_theme()
+ if("dark" || "normal")
+ owner.force_dark_theme()
- if("swaptolightmode")
- swaptolightmode()
if(data)
ehjax_send(data = data)
@@ -156,19 +150,6 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
//Called by client, sent data to investigate (cookie history so far)
/datum/chatOutput/proc/analyzeClientData(cookie = "")
- //Spam check
- if(world.time > next_time_to_clear)
- next_time_to_clear = world.time + (3 SECONDS)
- total_checks = 0
-
- total_checks += 1
-
- if(total_checks > SPAM_TRIGGER_AUTOMUTE)
- message_admins("[key_name(owner)] kicked for goonchat topic spam")
- qdel(owner)
- return
-
-
if(!cookie)
return
@@ -177,24 +158,13 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
if (connData && islist(connData) && connData.len > 0 && connData["connData"])
connectionHistory = connData["connData"] //lol fuck
var/list/found = new()
-
- if(connectionHistory.len > MAX_COOKIE_LENGTH)
- message_admins("[key_name(src.owner)] was kicked for an invalid ban cookie)")
- qdel(owner)
- return
-
-
for(var/i in connectionHistory.len to 1 step -1)
- if(QDELETED(owner))
- //he got cleaned up before we were done
- return
var/list/row = src.connectionHistory[i]
if (!row || row.len < 3 || (!row["ckey"] || !row["compid"] || !row["ip"])) //Passed malformed history object
return
if (world.IsBanned(row["ckey"], row["ip"], row["compid"], real_bans_only=TRUE))
found = row
break
- CHECK_TICK
//Uh oh this fucker has a history of playing on a banned account!!
if (found.len > 0)
@@ -213,8 +183,8 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
log_world("\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client: [(src.owner.key ? src.owner.key : src.owner)] triggered JS error: [error]")
//Global chat procs
-/proc/to_chat(target, message, handle_whitespace=TRUE)
- if(!target)
+/proc/to_chat_immediate(target, message, handle_whitespace=TRUE)
+ if(!target || !message)
return
//Ok so I did my best but I accept that some calls to this will be for shit like sound and images
@@ -236,7 +206,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
message = replacetext(message, "\proper", "")
if(handle_whitespace)
message = replacetext(message, "\n", " ")
- message = replacetext(message, "\t", "[GLOB.TAB][GLOB.TAB]")
+ message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]")
if(islist(target))
// Do the double-encoding outside the loop to save nanoseconds
@@ -279,12 +249,8 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
// url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript.
C << output(url_encode(url_encode(message)), "browseroutput:output")
-
-/datum/chatOutput/proc/swaptolightmode() //Dark mode light mode stuff. Yell at KMC if this breaks! (See darkmode.dm for documentation)
- owner.force_white_theme()
-
-/datum/chatOutput/proc/swaptodarkmode()
- owner.force_dark_theme()
-
-
-#undef MAX_COOKIE_LENGTH
+/proc/to_chat(target, message, handle_whitespace = TRUE)
+ if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized)
+ to_chat_immediate(target, message, handle_whitespace)
+ return
+ SSchat.queue(target, message, handle_whitespace)
\ No newline at end of file
diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css
index d10b3359..cca54377 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput.css
@@ -7,20 +7,16 @@ html, body {
padding: 0;
margin: 0;
height: 100%;
- color: #f0f0f0;
+ color: #000000;
}
body {
- background: #171717;
+ background: #E0E0E0; /*CIT CHANGE - darkens chatbox a lil*/
font-family: Verdana, sans-serif;
font-size: 9pt;
- font-color: #f0f0f0;
line-height: 1.2;
overflow-x: hidden;
overflow-y: scroll;
- word-wrap: break-word;
- scrollbar-face-color:#1A1A1A;
- scrollbar-track-color:#171717;
- scrollbar-highlight-color:#171717;
+ word-wrap: break-word;
}
em {
@@ -60,9 +56,9 @@ img.icon {
border-radius: 10px;
}
-a {color: #397ea5;}
-a.visited {color: #7c00e6;}
-a:visited {color: #7c00e6;}
+a {color: #0000ff;}
+a.visited {color: #ff00ff;}
+a:visited {color: #ff00ff;}
a.popt {text-decoration: none;}
/*****************************************
@@ -93,21 +89,21 @@ a.popt {text-decoration: none;}
bottom: 0;
right: 0;
padding: 8px;
- background: #202020;
+ background: #d0d0d0;
text-decoration: none;
font-variant: small-caps;
font-size: 1.1em;
font-weight: bold;
- color: #a4bad6;
+ color: #333;
}
-#newMessages:hover {background: #171717;}
+#newMessages:hover {background: #ccc;}
#newMessages i {vertical-align: middle; padding-left: 3px;}
#ping {
position: fixed;
top: 0;
right: 115px;
width: 45px;
- background: #202020;
+ background: #d0d0d0;
height: 30px;
padding: 8px 0 2px 0;
}
@@ -124,19 +120,19 @@ a.popt {text-decoration: none;}
right: 0;
}
#userBar .subCell {
- background: #202020;
+ background: #d0d0d0;
height: 30px;
padding: 5px 0;
display: block;
- color: #a4bad6;
+ color: #333;
text-decoration: none;
line-height: 28px;
- border-top: 1px solid #171717;
+ border-top: 1px solid #b4b4b4;
}
-#userBar .subCell:hover {background: #202020;}
+#userBar .subCell:hover {background: #ccc;}
#userBar .toggle {
width: 40px;
- background: #202020;
+ background: #ccc;
border-top: 0;
float: right;
text-align: center;
@@ -172,7 +168,7 @@ a.popt {text-decoration: none;}
position: fixed;
top: 50%;
left: 50%;
- background: #ddd;
+ background: #d0d0d0;
}
.popup .close {
position: absolute;
@@ -189,7 +185,7 @@ a.popt {text-decoration: none;}
.popup .close:hover {background: #999;}
.popup .head {
background: #999;
- color: #ddd;
+ color: #d0d0d0;
padding: 0 10px;
height: 30px;
line-height: 30px;
@@ -200,7 +196,7 @@ a.popt {text-decoration: none;}
}
.popup input {border: 1px solid #999; background: #fff; margin: 0; padding: 5px; outline: none; color: #333;}
.popup input[type=text]:hover, .popup input[type=text]:active, .popup input[type=text]:focus {border-color: green;}
-.popup input[type=submit] {padding: 5px 10px; background: #999; color: #ddd; text-transform: uppercase; font-size: 0.9em; font-weight: bold;}
+.popup input[type=submit] {padding: 5px 10px; background: #999; color: #d0d0d0; text-transform: uppercase; font-size: 0.9em; font-weight: bold;}
.popup input[type=submit]:hover, .popup input[type=submit]:focus, .popup input[type=submit]:active {background: #aaa; cursor: pointer;}
.changeFont {padding: 10px;}
@@ -214,7 +210,7 @@ a.popt {text-decoration: none;}
/* ADMIN CONTEXT MENU */
.contextMenu {
- background-color: #ddd;
+ background-color: #d0d0d0;
position: fixed;
margin: 2px;
width: 150px;
@@ -246,9 +242,9 @@ a.popt {text-decoration: none;}
******************************************/
/* MOTD */
-.motd {color: #a4bad6; font-family: Verdana, sans-serif;}
-.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #a4bad6; text-decoration: underline;}
-.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #a4bad6;}
+.motd {color: #638500; font-family: Verdana, sans-serif;}
+.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #638500; text-decoration: underline;}
+.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #638500;}
/* ADD HERE FOR BOLD */
.bold, .name, .prefix, .ooc, .looc, .adminooc, .admin, .medal, .yell {font-weight: bold;}
@@ -259,91 +255,91 @@ a.popt {text-decoration: none;}
/* OUTPUT COLORS */
.highlight {background: yellow;}
-h1, h2, h3, h4, h5, h6 {color: #a4bad6;font-family: Georgia, Verdana, sans-serif;}
-h1.alert, h2.alert {color: #a4bad6;}
+h1, h2, h3, h4, h5, h6 {color: #0000ff;font-family: Georgia, Verdana, sans-serif;}
+h1.alert, h2.alert {color: #000000;}
em {font-style: normal; font-weight: bold;}
-.ooc {color: #cca300; font-weight: bold;}
-.looc {color: #d8b555; font-weight: bold;}
-.antagooc {color: #ce254f; font-weight: bold;}
+.ooc {color: #002eb8; font-weight: bold;}
+.looc {color: #6699CC; font-weight: bold;}
+.antagooc {color: #b8002e; font-weight: bold;}
.adminobserverooc {color: #0099cc; font-weight: bold;}
-.adminooc {color: #3d5bc3; font-weight: bold;}
+.adminooc {color: #700038; font-weight: bold;}
-.adminsay {color: #ff4500; font-weight: bold;}
-.admin {color: #5975da; font-weight: bold;}
+.adminsay {color: #FF4500}
+.admin {color: #386aff; font-weight: bold;}
.name { font-weight: bold;}
.say {}
-.deadsay {color: #e2c1ff;}
+.deadsay {color: #5c00e6;}
.binarysay {color: #20c20e; background-color: #000000; display: block;}
.binarysay a {color: #00ff00;}
.binarysay a:active, .binarysay a:visited {color: #88ff88;}
-.radio {color: #1ecc43;}
-.sciradio {color: #c68cfa;}
-.comradio {color: #5177ff;}
-.secradio {color: #dd3535;}
-.medradio {color: #57b8f0;}
-.engradio {color: #f37746;}
-.suppradio {color: #b88646;}
-.servradio {color: #6ca729;}
-.syndradio {color: #8f4a4b;}
-.centcomradio {color: #2681a5;}
-.aiprivradio {color: #d65d95;}
-.redteamradio {color: #ff4444;}
-.blueteamradio {color: #3434fd;}
+.radio {color: #008000;}
+.sciradio {color: #993399;}
+.comradio {color: #948f02;}
+.secradio {color: #a30000;}
+.medradio {color: #337296;}
+.engradio {color: #fb5613;}
+.suppradio {color: #a8732b;}
+.servradio {color: #6eaa2c;}
+.syndradio {color: #6d3f40;}
+.centcomradio {color: #686868;}
+.aiprivradio {color: #ff00ff;}
+.redteamradio {color: #ff0000;}
+.blueteamradio {color: #0000ff;}
.yell { font-weight: bold;}
-.alert {color: #d82020;}
-h1.alert, h2.alert {color: #99aab5;}
+.alert {color: #ff0000;}
+h1.alert, h2.alert {color: #000000;}
.emote { font-style: italic;}
.selecteddna {color: #ffffff; background-color: #001B1B}
-.attack {color: #e01c1c;}
-.disarm {color: #b42525;}
-.passive {color: #a00f0f;}
+.attack {color: #ff0000;}
+.disarm {color: #990000;}
+.passive {color: #660000;}
-.userdanger {color: #c51e1e; font-weight: bold; font-size: 24px;}
-.danger {color: #c51e1e;}
-.warning {color: #c51e1e; font-style: italic;}
+.userdanger {color: #ff0000; font-weight: bold; font-size: 24px;}
+.danger {color: #ff0000;}
+.warning {color: #ff0000; font-style: italic;}
.alertwarning {color: #FF0000; font-weight: bold}
-.boldwarning {color: #c51e1e; font-style: italic; font-weight: bold}
-.announce {color: #c51e1e; font-weight: bold;}
-.boldannounce {color: #c51e1e; font-weight: bold;}
-.greenannounce {color: #059223; font-weight: bold;}
+.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
+.announce {color: #228b22; font-weight: bold;}
+.boldannounce {color: #ff0000; font-weight: bold;}
+.greenannounce {color: #00ff00; font-weight: bold;}
.rose {color: #ff5050;}
-.info {color: #6685f5;}
-.notice {color: #6685f5;}
-.boldnotice {color: #6685f5; font-weight: bold;}
-.adminnotice {color: #6685f5;}
+.info {color: #0000CC;}
+.notice {color: #000099;}
+.boldnotice {color: #000099; font-weight: bold;}
+.adminnotice {color: #0000ff;}
.adminhelp {color: #ff0000; font-weight: bold;}
-.unconscious {color: #a4bad6; font-weight: bold;}
+.unconscious {color: #0000ff; font-weight: bold;}}
.suicide {color: #ff5050; font-style: italic;}
-.red {color: #FF0000}
-.pink {color: #ff70c1;}
-.blue {color: #215cff}
-.green {color: #059223;}
-.nicegreen {color: #059223;}
+.green {color: #03ff39;}
+.red {color: #FF0000;}
+.pink {color: #FF69Bf;}
+.blue {color: #0000FF;}
+.nicegreen {color: #14a833;}
.userlove {color: #ff42a6; font-style: italic; font-weight: bold; text-shadow: 0 0 6px #82365e;}
.love {color: #ff4591; font-style: italic; text-shadow: 0 0 6px #994449;}
-.shadowling {color: #8e8a99;}
-.cult {color: #aa1c1c;}
+.shadowling {color: #3b2769;}
+.cult {color: #960000;}
-.cultitalic {color: #aa1c1c; font-style: italic;}
-.cultbold {color: #aa1c1c; font-style: italic; font-weight: bold;}
-.cultboldtalic {color: #aa1c1c; font-weight: bold; font-size: 24px;}
+.cultitalic {color: #960000; font-style: italic;}
+.cultbold {color: #960000; font-style: italic; font-weight: bold;}
+.cultboldtalic {color: #960000; font-weight: bold; font-size: 24px;}
-.cultlarge {color: #aa1c1c; font-weight: bold; font-size: 24px;}
-.narsie {color: #aa1c1c; font-weight: bold; font-size: 120px;}
-.narsiesmall {color: #aa1c1c; font-weight: bold; font-size: 48px;}
+.cultlarge {color: #960000; font-weight: bold; font-size: 24px;}
+.narsie {color: #960000; font-weight: bold; font-size: 120px;}
+.narsiesmall {color: #960000; font-weight: bold; font-size: 48px;}
.colossus {color: #7F282A; font-size: 40px;}
-.hierophant {color: #b441ee; font-weight: bold; font-style: italic;}
-.hierophant_warning {color: #c56bf1; font-style: italic;}
-.purple {color: #9956d3;}
-.holoparasite {color: #88809c;}
+.hierophant {color: #660099; font-weight: bold; font-style: italic;}
+.hierophant_warning {color: #660099; font-style: italic;}
+.purple {color: #5e2d79;}
+.holoparasite {color: #35333a;}
.revennotice {color: #1d2953;}
.revenboldnotice {color: #1d2953; font-weight: bold;}
@@ -351,11 +347,11 @@ h1.alert, h2.alert {color: #99aab5;}
.revenminor {color: #823abb}
.revenwarning {color: #760fbb; font-style: italic;}
.revendanger {color: #760fbb; font-weight: bold; font-size: 24px;}
-.umbra {color: #7c00e6;}
-.umbra_emphasis {color: #7c00e6; font-weight: bold; font-style: italic;}
-.umbra_large {color: #7c00e6; font-size: 24px; font-weight: bold; font-style: italic;}
+.umbra {color: #5000A0;}
+.umbra_emphasis {color: #5000A0; font-weight: bold; font-style: italic;}
+.umbra_large {color: #5000A0; font-size: 24px; font-weight: bold; font-style: italic;}
-.deconversion_message {color: #a947ff; font-size: 24px; font-style: italic;}
+.deconversion_message {color: #5000A0; font-size: 24px; font-style: italic;}
.brass {color: #BE8700;}
.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;}
@@ -380,17 +376,17 @@ h1.alert, h2.alert {color: #99aab5;}
.neovgre {color: #6E001A; font-weight: bold; font-style: italic;}
.neovgre_small {color: #6E001A;}
-.newscaster {color: #c05d5d;}
-.ghostalert {color: #6600ff; font-style: italic; font-weight: bold;}
+.newscaster {color: #800000;}
+.ghostalert {color: #5c00e6; font-style: italic; font-weight: bold;}
-.alien {color: #855d85;}
-.noticealien {color: #059223;}
-.alertalien {color: #059223; font-weight: bold;}
-.changeling {color: #059223; font-style: italic;}
+.alien {color: #543354;}
+.noticealien {color: #00c000;}
+.alertalien {color: #00c000; font-weight: bold;}
+.changeling {color: #800080; font-style: italic;}
-.spider {color: #8800ff;}
+.spider {color: #4d004d;}
-.interface {color: #750e75;}
+.interface {color: #330033;}
.sans {font-family: "Comic Sans MS", cursive, sans-serif;}
.papyrus {font-family: "Papyrus", cursive, sans-serif;}
@@ -401,9 +397,9 @@ h1.alert, h2.alert {color: #99aab5;}
.big {font-size: 24px;}
.reallybig {font-size: 32px;}
.extremelybig {font-size: 40px;}
-.greentext {color: #059223; font-size: 24px;}
-.redtext {color: #c51e1e; font-size: 24px;}
-.clown {color: #ff70c1; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
+.greentext {color: #00FF00; font-size: 24px;}
+.redtext {color: #FF0000; font-size: 24px;}
+.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
.velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;}
@keyframes velvet {
@@ -435,20 +431,20 @@ h1.alert, h2.alert {color: #99aab5;}
.memo {color: #638500; text-align: center;}
.memoedit {text-align: center; font-size: 16px;}
-.abductor {color: #c204c2; font-style: italic;}
-.mind_control {color: #df3da9; font-size: 3; font-weight: bold; font-style: italic;}
+.abductor {color: #800080; font-style: italic;}
+.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;}
.slime {color: #00CED1;}
.drone {color: #848482;}
.monkey {color: #975032;}
.swarmer {color: #2C75FF;}
.resonate {color: #298F85;}
-.monkeyhive {color: #a56408;}
-.monkeylead {color: #af6805; font-size: 2;}
+.monkeyhive {color: #774704;}
+.monkeylead {color: #774704; font-size: 2;}
.connectionClosed, .fatalError {background: red; color: white; padding: 5px;}
.connectionClosed.restored {background: green;}
-.internal.boldnshit {color: #3d5bc3; font-weight: bold;}
+.internal.boldnshit {color: #000099; font-weight: bold;}
/* HELPER CLASSES */
.text-normal {font-weight: normal; font-style: normal;}
diff --git a/code/modules/goonchat/browserassets/css/browserOutput_dark.css b/code/modules/goonchat/browserassets/css/browserOutput_dark.css
new file mode 100644
index 00000000..d143dfc3
--- /dev/null
+++ b/code/modules/goonchat/browserassets/css/browserOutput_dark.css
@@ -0,0 +1,159 @@
+html, body {color: #E0E0E0;}
+body {
+ background: #171717;
+ font-color: #E0E0E0;
+ scrollbar-face-color:#1A1A1A;
+ scrollbar-track-color:#171717;
+ scrollbar-highlight-color:#171717;
+}
+
+a {color: #397ea5;}
+a.visited {color: #7c00e6;}
+a:visited {color: #7c00e6;}
+
+#newMessages {
+ background: #242424;
+ color: #E0E0E0;
+}
+#newMessages:hover {background: #272727;}
+
+#ping {background: #272727;}
+
+#userBar .subCell {
+ background: #272727;
+ color: #E0E0E0;
+ border-top: 1px solid #171717;
+}
+#userBar .subCell:hover {background: #272727;}
+#userBar .toggle {background: #272727;}
+
+/* MOTD */
+.motd {color: #E0E0E0; font-family: Verdana, sans-serif;}
+.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #E0E0E0; text-decoration: underline;}
+.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #E0E0E0;}
+
+h1, h2, h3, h4, h5, h6 {color: #E0E0E0;font-family: Georgia, Verdana, sans-serif;}
+h1.alert, h2.alert {color: #E0E0E0;}
+
+.ooc {color: #cca300; font-weight: bold;}
+.looc {color: #d8b555; font-weight: bold;}
+.antagooc {color: #ce254f; font-weight: bold;}
+.adminobserverooc {color: #0099cc; font-weight: bold;}
+.adminooc {color: #3d5bc3; font-weight: bold;}
+
+.admin {color: #5975da; font-weight: bold;}
+
+.deadsay {color: #e2c1ff;}
+.radio {color: #1ecc43;}
+.sciradio {color: #c68cfa;}
+.comradio {color: #5177ff;}
+.secradio {color: #dd3535;}
+.medradio {color: #57b8f0;}
+.engradio {color: #f37746;}
+.suppradio {color: #b88646;}
+.servradio {color: #6ca729;}
+.syndradio {color: #8f4a4b;}
+.centcomradio {color: #2681a5;}
+.aiprivradio {color: #d65d95;}
+.redteamradio {color: #ff4444;}
+.blueteamradio {color: #3434fd;}
+
+.alert {color: #d82020;}
+h1.alert, h2.alert {color: #99aab5;}
+
+.attack {color: #e01c1c;}
+.disarm {color: #b42525;}
+.passive {color: #a00f0f;}
+
+.userdanger {color: #c51e1e; font-weight: bold; font-size: 24px;}
+.danger {color: #c51e1e;}
+.warning {color: #c51e1e; font-style: italic;}
+.alertwarning {color: #c51e1e; font-weight: bold}
+.boldwarning {color: #c51e1e; font-style: italic; font-weight: bold}
+.announce {color: #c51e1e; font-weight: bold;}
+.boldannounce {color: #c51e1e; font-weight: bold;}
+.greenannounce {color: #059223; font-weight: bold;}
+.info {color: #6685f5;}
+.notice {color: #6685f5;}
+.boldnotice {color: #6685f5; font-weight: bold;}
+.adminnotice {color: #6685f5;}
+.adminhelp {color: #ff0000; font-weight: bold;}
+.unconscious {color: #E0E0E0; font-weight: bold;}
+.red {color: #FF0000}
+.pink {color: #ff70c1;}
+.blue {color: #215cff}
+.green {color: #059223;}
+.nicegreen {color: #059223;}
+.userlove {color: #ff42a6; font-style: italic; font-weight: bold; text-shadow: 0 0 6px #82365e;}
+.love {color: #ff4591; font-style: italic; text-shadow: 0 0 6px #994449;}
+.shadowling {color: #8e8a99;}
+.cult {color: #aa1c1c;}
+
+.cultitalic {color: #aa1c1c; font-style: italic;}
+.cultbold {color: #aa1c1c; font-style: italic; font-weight: bold;}
+.cultboldtalic {color: #aa1c1c; font-weight: bold; font-size: 24px;}
+
+.cultlarge {color: #aa1c1c; font-weight: bold; font-size: 24px;}
+.narsie {color: #aa1c1c; font-weight: bold; font-size: 120px;}
+.narsiesmall {color: #aa1c1c; font-weight: bold; font-size: 48px;}
+.hierophant {color: #b441ee; font-weight: bold; font-style: italic;}
+.hierophant_warning {color: #c56bf1; font-style: italic;}
+.purple {color: #9956d3;}
+.holoparasite {color: #88809c;}
+
+.revennotice {color: #3645aa;}
+.revenboldnotice {color: #3645aa; font-weight: bold;}
+.revenbignotice {color: #3645aa; font-weight: bold; font-size: 24px;}
+.revenminor {color: #823ddd}
+.revenwarning {color: #8911d9; font-style: italic;}
+.revendanger {color: #8911d9; font-weight: bold; font-size: 24px;}
+.umbra {color: #7c00e6;}
+.umbra_emphasis {color: #7c00e6; font-weight: bold; font-style: italic;}
+.umbra_large {color: #7c00e6; font-size: 24px; font-weight: bold; font-style: italic;}
+
+.deconversion_message {color: #a947ff; font-size: 24px; font-style: italic;}
+
+.alloy {color: #545b64;}
+.heavy_alloy {color: #545b64; font-weight: bold; font-style: italic;}
+.nezbere_large {color: #545b64; font-size: 24px; font-weight: bold; font-style: italic;}
+.nezbere {color: #545b64; font-weight: bold; font-style: italic;}
+.nezbere_small {color: #545b64;}
+.inathneq_large {color: #1d7dc7; font-size: 24px; font-weight: bold; font-style: italic;}
+.inathneq {color: #1d7dc7; font-weight: bold; font-style: italic;}
+.inathneq_small {color: #1d7dc7;}
+.neovgre_large {color: #7c0622; font-size: 24px; font-weight: bold; font-style: italic;}
+.neovgre {color: #7c0622; font-weight: bold; font-style: italic;}
+.neovgre_small {color: #7c0622;}
+
+.newscaster {color: #c05d5d;}
+.ghostalert {color: #6600ff; font-style: italic; font-weight: bold;}
+
+.alien {color: #855d85;}
+.noticealien {color: #059223;}
+.alertalien {color: #059223; font-weight: bold;}
+.changeling {color: #059223; font-style: italic;}
+
+.spider {color: #8800ff;}
+
+.interface {color: #750e75;}
+
+.greentext {color: #059223; font-size: 24px;}
+.redtext {color: #c51e1e; font-size: 24px;}
+.clown {color: #ff70c1; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
+.velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;}
+@keyframes velvet {
+ 0% { color: #890020; }
+ 40% { color: #c51e1e; }
+ 50% { color: #FF8888; }
+ 60% { color: #c51e1e; }
+ 100% { color: #890020; }
+}
+
+.abductor {color: #c204c2; font-style: italic;}
+.mind_control {color: #df3da9; font-size: 3; font-weight: bold; font-style: italic;}
+.drone {color: #979795;}
+
+.monkeyhive {color: #a56408;}
+.monkeylead {color: #af6805; font-size: 2;}
+
+.internal.boldnshit {color: #3d5bc3; font-weight: bold;}
\ No newline at end of file
diff --git a/code/modules/goonchat/browserassets/css/browserOutput_white.css b/code/modules/goonchat/browserassets/css/browserOutput_light.css
similarity index 58%
rename from code/modules/goonchat/browserassets/css/browserOutput_white.css
rename to code/modules/goonchat/browserassets/css/browserOutput_light.css
index 91f00312..098bd253 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput_white.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput_light.css
@@ -1,236 +1,18 @@
-/*****************************************
-*
-* GLOBAL STYLES
-*
-******************************************/
-html, body {
- padding: 0;
- margin: 0;
- height: 100%;
- color: #000000;
-}
-body {
- background: #eeeeee;
- font-family: Verdana, sans-serif;
- font-size: 9pt;
- line-height: 1.2;
- overflow-x: hidden;
- overflow-y: scroll;
- word-wrap: break-word;
-}
+body {background: #F1F1F1;}
-em {
- font-style: normal;
- font-weight: bold;
-}
+#newMessages {background: #ddd;}
+#ping {background: #ddd;}
-img {
- margin: 0;
- padding: 0;
- line-height: 1;
- -ms-interpolation-mode: nearest-neighbor;
- image-rendering: pixelated;
-}
-img.icon {
- height: 1em;
- min-height: 16px;
- width: auto;
- vertical-align: bottom;
-}
-
-
-.r:before { /* "repeated" badge class for combined messages */
- content: 'x';
-}
-.r {
- display: inline-block;
- min-width: 0.5em;
- font-size: 0.7em;
- padding: 0.2em 0.3em;
- line-height: 1;
- color: white;
- text-align: center;
- white-space: nowrap;
- vertical-align: middle;
- background-color: crimson;
- border-radius: 10px;
-}
-
-a {color: #0000ff;}
-a.visited {color: #ff00ff;}
-a:visited {color: #ff00ff;}
-a.popt {text-decoration: none;}
-
-/*****************************************
-*
-* OUTPUT NOT RELATED TO ACTUAL MESSAGES
-*
-******************************************/
-#loading {
- position: fixed;
- width: 300px;
- height: 150px;
- text-align: center;
- left: 50%;
- top: 50%;
- margin: -75px 0 0 -150px;
-}
-#loading i {display: block; padding-bottom: 3px;}
-
-#messages {
- font-size: 13px;
- padding: 3px;
- margin: 0;
- word-wrap: break-word;
-}
-#newMessages {
- position: fixed;
- display: block;
- bottom: 0;
- right: 0;
- padding: 8px;
- background: #ddd;
- text-decoration: none;
- font-variant: small-caps;
- font-size: 1.1em;
- font-weight: bold;
- color: #333;
-}
-#newMessages:hover {background: #ccc;}
-#newMessages i {vertical-align: middle; padding-left: 3px;}
-#ping {
- position: fixed;
- top: 0;
- right: 115px;
- width: 45px;
- background: #ddd;
- height: 30px;
- padding: 8px 0 2px 0;
-}
-#ping i {display: block; text-align: center;}
-#ping .ms {
- display: block;
- text-align: center;
- font-size: 8pt;
- padding-top: 2px;
-}
-#userBar {
- position: fixed;
- top: 0;
- right: 0;
-}
-#userBar .subCell {
- background: #ddd;
- height: 30px;
- padding: 5px 0;
- display: block;
- color: #333;
- text-decoration: none;
- line-height: 28px;
- border-top: 1px solid #b4b4b4;
-}
-#userBar .subCell:hover {background: #ccc;}
-#userBar .toggle {
- width: 40px;
- background: #ccc;
- border-top: 0;
- float: right;
- text-align: center;
-}
-#userBar .sub {clear: both; display: none; width: 160px;}
-#userBar .sub.scroll {overflow-y: scroll;}
-#userBar .sub.subCell {padding: 3px 0 3px 8px; line-height: 30px; font-size: 0.9em; clear: both;}
-#userBar .sub span {
- display: block;
- line-height: 30px;
- float: left;
-}
-#userBar .sub i {
- display: block;
- padding: 0 5px;
- font-size: 1.1em;
- width: 22px;
- text-align: center;
- line-height: 30px;
- float: right;
-}
-#userBar .sub input {
- position: absolute;
- padding: 7px 5px;
- width: 121px;
- line-height: 30px;
- float: left;
-}
-#userBar .topCell {border-top: 0;}
+#userBar .subCell {background: #ddd;}
/* POPUPS */
-.popup {
- position: fixed;
- top: 50%;
- left: 50%;
- background: #ddd;
-}
-.popup .close {
- position: absolute;
- background: #aaa;
- top: 0;
- right: 0;
- color: #333;
- text-decoration: none;
- z-index: 2;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
-}
-.popup .close:hover {background: #999;}
-.popup .head {
- background: #999;
- color: #ddd;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
- text-transform: uppercase;
- font-size: 0.9em;
- font-weight: bold;
- border-bottom: 2px solid green;
-}
-.popup input {border: 1px solid #999; background: #fff; margin: 0; padding: 5px; outline: none; color: #333;}
-.popup input[type=text]:hover, .popup input[type=text]:active, .popup input[type=text]:focus {border-color: green;}
-.popup input[type=submit] {padding: 5px 10px; background: #999; color: #ddd; text-transform: uppercase; font-size: 0.9em; font-weight: bold;}
-.popup input[type=submit]:hover, .popup input[type=submit]:focus, .popup input[type=submit]:active {background: #aaa; cursor: pointer;}
-
-.changeFont {padding: 10px;}
-.changeFont a {display: block; text-decoration: none; padding: 3px; color: #333;}
-.changeFont a:hover {background: #ccc;}
-
-.highlightPopup {padding: 10px; text-align: center;}
-.highlightPopup input[type=text] {display: block; width: 215px; text-align: left; margin-top: 5px;}
-.highlightPopup input.highlightColor {background-color: #FFFF00;}
-.highlightPopup input.highlightTermSubmit {margin-top: 5px;}
+.popup {background: #ddd;}
+.popup .head {color: #ddd;}
+.popup input[type=submit] {color: #ddd;}
/* ADMIN CONTEXT MENU */
-.contextMenu {
- background-color: #ddd;
- position: fixed;
- margin: 2px;
- width: 150px;
-}
-.contextMenu a {
- display: block;
- padding: 2px 5px;
- text-decoration: none;
- color: #333;
-}
+.contextMenu {background-color: #ddd;}
-.contextMenu a:hover {
- background-color: #ccc;
-}
-
-/* ADMIN FILTER MESSAGES MENU */
-.filterMessages {padding: 5px;}
-.filterMessages div {padding: 2px 0;}
-.filterMessages input {}
-.filterMessages label {}
.icon-stack {height: 1em; line-height: 1em; width: 1em; vertical-align: middle; margin-top: -2px;}
@@ -266,8 +48,8 @@ em {font-style: normal; font-weight: bold;}
.adminobserverooc {color: #0099cc; font-weight: bold;}
.adminooc {color: #700038; font-weight: bold;}
-.adminsay {color: #ff4500; font-weight: bold;}
-.admin {color: #4473ff; font-weight: bold;}
+.adminsay {color: #FF4500}
+.admin {color: #386aff; font-weight: bold;}
.name { font-weight: bold;}
@@ -305,7 +87,7 @@ h1.alert, h2.alert {color: #000000;}
.userdanger {color: #ff0000; font-weight: bold; font-size: 24px;}
.danger {color: #ff0000;}
.warning {color: #ff0000; font-style: italic;}
-.alertwarning {color: #FF0000; font-weight: bold}
+.alertwarning {color: #FF0000; font-weight: bold}
.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
.announce {color: #228b22; font-weight: bold;}
.boldannounce {color: #ff0000; font-weight: bold;}
@@ -318,10 +100,10 @@ h1.alert, h2.alert {color: #000000;}
.adminhelp {color: #ff0000; font-weight: bold;}
.unconscious {color: #0000ff; font-weight: bold;}
.suicide {color: #ff5050; font-style: italic;}
-.green {color: #03ff39;}
-.red {color: #FF0000}
+.green {color: #03ff39;}
+.red {color: #FF0000;}
.pink {color: #FF69Bf;}
-.blue {color: #0000FF}
+.blue {color: #0000FF;}
.nicegreen {color: #14a833;}
.userlove {color: #FF1493; font-style: italic; font-weight: bold; text-shadow: 0 0 6px #ff6dbc;}
.love {color: #ff006a; font-style: italic; text-shadow: 0 0 6px #ff6d6d;}
@@ -330,7 +112,7 @@ h1.alert, h2.alert {color: #000000;}
.cultitalic {color: #960000; font-style: italic;}
.cultbold {color: #960000; font-style: italic; font-weight: bold;}
-.cultboldtalic {color: #960000; font-weight: bold; font-size: 24px;}
+.cultboldtalic {color: #960000; font-weight: bold; font-size: 24px;}
.cultlarge {color: #960000; font-weight: bold; font-size: 24px;}
.narsie {color: #960000; font-weight: bold; font-size: 120px;}
@@ -401,13 +183,38 @@ h1.alert, h2.alert {color: #000000;}
.redtext {color: #FF0000; font-size: 24px;}
.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
+.velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;}
+@keyframes velvet {
+ 0% { color: #400020; }
+ 40% { color: #FF0000; }
+ 50% { color: #FF8888; }
+ 60% { color: #FF0000; }
+ 100% { color: #400020; }
+}
+
+.hypnophrase {color: #202020; font-weight: bold; animation: hypnocolor 1500ms infinite;}
+@keyframes hypnocolor {
+ 0% { color: #202020; }
+ 25% { color: #4b02ac; }
+ 50% { color: #9f41f1; }
+ 75% { color: #541c9c; }
+ 100% { color: #7adbf3; }
+}
+
+.phobia {color: #dd0000; font-weight: bold; animation: phobia 750ms infinite;}
+@keyframes phobia {
+ 0% { color: #f75a5a; }
+ 50% { color: #dd0000; }
+ 100% { color: #f75a5a; }
+}
+
.icon {height: 1em; width: auto;}
.memo {color: #638500; text-align: center;}
.memoedit {text-align: center; font-size: 16px;}
.abductor {color: #800080; font-style: italic;}
-.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;}
+.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;}
.slime {color: #00CED1;}
.drone {color: #848482;}
.monkey {color: #975032;}
@@ -419,9 +226,8 @@ h1.alert, h2.alert {color: #000000;}
.connectionClosed, .fatalError {background: red; color: white; padding: 5px;}
.connectionClosed.restored {background: green;}
-.internal.boldnshit {color: blue; font-weight: bold;}
+.internal.boldnshit {color: #000099; font-weight: bold;}
/* HELPER CLASSES */
.text-normal {font-weight: normal; font-style: normal;}
.hidden {display: none; visibility: hidden;}
-
diff --git a/code/modules/goonchat/browserassets/html/browserOutput.html b/code/modules/goonchat/browserassets/html/browserOutput.html
index 9c6d462a..68da2517 100644
--- a/code/modules/goonchat/browserassets/html/browserOutput.html
+++ b/code/modules/goonchat/browserassets/html/browserOutput.html
@@ -5,8 +5,9 @@
-
+
+
@@ -29,7 +30,7 @@
--ms
-
+
diff --git a/code/modules/goonchat/browserassets/js/browserOutput.js b/code/modules/goonchat/browserassets/js/browserOutput.js
index 4375926c..06e735d1 100644
--- a/code/modules/goonchat/browserassets/js/browserOutput.js
+++ b/code/modules/goonchat/browserassets/js/browserOutput.js
@@ -35,7 +35,7 @@ var opts = {
'wasd': false, //Is the user in wasd mode?
'priorChatHeight': 0, //Thing for height-resizing detection
'restarting': false, //Is the round restarting?
- 'darkmode':false, //Are we using darkmode? If not WHY ARE YOU LIVING IN 2009???
+ 'colorPreset': 0, // index in the color presets list.
//Options menu
'selectedSubLoop': null, //Contains the interval loop for closing the selected sub menu
@@ -73,6 +73,14 @@ var opts = {
};
+// Array of names for chat display color presets.
+// If not set to normal, a CSS file `browserOutput_${name}.css` will be added to the head.
+var colorPresets = [
+ 'normal',
+ 'light',
+ 'dark'
+]
+
function clamp(val, min, max) {
return Math.max(min, Math.min(val, max))
}
@@ -96,6 +104,12 @@ if (typeof String.prototype.trim !== 'function') {
};
}
+function updateColorPreset() {
+ var el = $("#colorPresetLink")[0];
+ el.href = "browserOutput_"+colorPresets[opts.colorPreset]+".css";
+ runByond('?_src_=chat&proc=colorPresetPost&preset='+colorPresets[opts.colorPreset]);
+}
+
// Linkify the contents of a node, within its parent.
function linkify(parent, insertBefore, text) {
var start = 0;
@@ -395,19 +409,6 @@ function toHex(n) {
return "0123456789ABCDEF".charAt((n-n%16)/16) + "0123456789ABCDEF".charAt(n%16);
}
-function swap() { //Swap to darkmode
- if (opts.darkmode){
- document.getElementById("sheetofstyles").href = "browserOutput_white.css";
- opts.darkmode = false;
- runByond('?_src_=chat&proc=swaptolightmode');
- } else {
- document.getElementById("sheetofstyles").href = "browserOutput.css";
- opts.darkmode = true;
- runByond('?_src_=chat&proc=swaptodarkmode');
- }
- setCookie('darkmode', (opts.darkmode ? 'true' : 'false'), 365);
-}
-
function handleClientData(ckey, ip, compid) {
//byond sends player info to here
var currentData = {'ckey': ckey, 'ip': ip, 'compid': compid};
@@ -615,7 +616,7 @@ $(function() {
'shighlightColor': getCookie('highlightcolor'),
'smusicVolume': getCookie('musicVolume'),
'smessagecombining': getCookie('messagecombining'),
- 'sdarkmode': getCookie('darkmode'),
+ 'scolorPreset': getCookie('colorpreset'),
};
if (savedConfig.sfontSize) {
@@ -626,9 +627,6 @@ $(function() {
$("body").css('line-height', savedConfig.slineHeight);
internalOutput('Loaded line height setting of: '+savedConfig.slineHeight+'', 'internal');
}
- if(savedConfig.sdarkmode == 'true'){
- swap();
- }
if (savedConfig.spingDisabled) {
if (savedConfig.spingDisabled == 'true') {
opts.pingDisabled = true;
@@ -654,6 +652,13 @@ $(function() {
opts.highlightColor = savedConfig.shighlightColor;
internalOutput('Loaded highlight color of: '+savedConfig.shighlightColor+'', 'internal');
}
+
+ if (savedConfig.scolorPreset) {
+ opts.colorPreset = Number(savedConfig.scolorPreset);
+ updateColorPreset();
+ internalOutput('Loaded color preset of: '+colorPresets[opts.colorPreset]+'', 'internal');
+ }
+
if (savedConfig.smusicVolume) {
var newVolume = clamp(savedConfig.smusicVolume, 0, 100);
$('#adminMusic').prop('volume', newVolume / 100);
@@ -839,9 +844,6 @@ $(function() {
$('#toggleOptions').click(function(e) {
handleToggleClick($subOptions, $(this));
});
- $('#darkmodetoggle').click(function(e) {
- swap();
- });
$('#toggleAudio').click(function(e) {
handleToggleClick($subAudio, $(this));
});
@@ -913,7 +915,7 @@ $(function() {
$.ajax({
type: 'GET',
- url: 'browserOutput_white.css',
+ url: 'browserOutput.css',
success: function(styleData) {
var blob = new Blob(['Chat Log', $messages.html(), '']);
@@ -991,7 +993,14 @@ $(function() {
$messages.empty();
opts.messageCount = 0;
});
-
+
+ $('#changeColorPreset').click(function() {
+ opts.colorPreset = (opts.colorPreset+1) % colorPresets.length;
+ updateColorPreset();
+ setCookie('colorpreset', opts.colorPreset, 365);
+ internalOutput('Changed color preset to: '+colorPresets[opts.colorPreset]);
+ });
+
$('#musicVolumeSpan').hover(function() {
$('#musicVolumeText').addClass('hidden');
$('#musicVolume').removeClass('hidden');
diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm
index e26dab07..e9ec7eff 100644
--- a/code/modules/hydroponics/beekeeping/beebox.dm
+++ b/code/modules/hydroponics/beekeeping/beebox.dm
@@ -23,6 +23,8 @@
var/obj/item/clothing/CH = head
if (CS.clothing_flags & CH.clothing_flags & THICKMATERIAL)
return 1
+ if(HAS_TRAIT(src, TRAIT_BEEFRIEND))
+ return 1
return 0
diff --git a/code/modules/hydroponics/grown/berries.dm b/code/modules/hydroponics/grown/berries.dm
index a16ce949..9b93bc57 100644
--- a/code/modules/hydroponics/grown/berries.dm
+++ b/code/modules/hydroponics/grown/berries.dm
@@ -262,5 +262,6 @@
name = "strawberry"
icon_state = "strawberry"
filling_color = "#7FFF00"
+ juice_results = list("strawberryjuice" = 0)
tastes = list("strawberries" = 1)
wine_power = 20
diff --git a/code/modules/hydroponics/grown/misc.dm b/code/modules/hydroponics/grown/misc.dm
index 879f71cd..4b8dbef8 100644
--- a/code/modules/hydroponics/grown/misc.dm
+++ b/code/modules/hydroponics/grown/misc.dm
@@ -273,6 +273,7 @@
throwforce = 5
hitsound = 'sound/weapons/klonk.ogg'
attack_verb = list("klonked", "donked", "bonked")
+ distill_reagent = "creme_de_coconut"
var/opened = FALSE
var/carved = FALSE
var/chopped = FALSE
diff --git a/code/modules/hydroponics/grown/pineapple.dm b/code/modules/hydroponics/grown/pineapple.dm
index e52c2612..0ca4242c 100644
--- a/code/modules/hydroponics/grown/pineapple.dm
+++ b/code/modules/hydroponics/grown/pineapple.dm
@@ -30,5 +30,6 @@
filling_color = "#F6CB0B"
w_class = WEIGHT_CLASS_NORMAL
foodtype = FRUIT | PINEAPPLE
+ juice_results = list("pineapplejuice" = 0)
tastes = list("pineapple" = 1)
wine_power = 40
diff --git a/code/modules/language/aphasia.dm b/code/modules/language/aphasia.dm
index 91f14f91..d63054e2 100644
--- a/code/modules/language/aphasia.dm
+++ b/code/modules/language/aphasia.dm
@@ -4,6 +4,7 @@
speech_verb = "garbles"
ask_verb = "mumbles"
whisper_verb = "mutters"
+ sing_verb = "gibbers"
exclaim_verb = "screams incoherently"
flags = LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD
key = "i"
diff --git a/code/modules/language/beachbum.dm b/code/modules/language/beachbum.dm
index 528e9a8d..42d3114f 100644
--- a/code/modules/language/beachbum.dm
+++ b/code/modules/language/beachbum.dm
@@ -2,6 +2,7 @@
name = "Beachtongue"
desc = "An ancient language from the distant Beach Planet. People magically learn to speak it under the influence of space drugs."
speech_verb = "mumbles"
+ sing_verb = "parties"
ask_verb = "grills"
exclaim_verb = "hollers"
key = "u"
diff --git a/code/modules/language/common.dm b/code/modules/language/common.dm
index 8d06dd8f..436c8cb9 100644
--- a/code/modules/language/common.dm
+++ b/code/modules/language/common.dm
@@ -4,6 +4,7 @@
desc = "The common galactic tongue."
speech_verb = "says"
whisper_verb = "whispers"
+ sing_verb = "sings"
key = "0"
flags = TONGUELESS_SPEECH | LANGUAGE_HIDE_ICON_IF_UNDERSTOOD
default_priority = 100
diff --git a/code/modules/language/draconic.dm b/code/modules/language/draconic.dm
index aaa998c2..0e1bb2e0 100644
--- a/code/modules/language/draconic.dm
+++ b/code/modules/language/draconic.dm
@@ -3,6 +3,7 @@
desc = "The common language of lizard-people, composed of sibilant hisses and rattles."
speech_verb = "hisses"
ask_verb = "hisses"
+ sing_verb = "sings"
exclaim_verb = "roars"
key = "o"
flags = TONGUELESS_SPEECH
diff --git a/code/modules/language/drone.dm b/code/modules/language/drone.dm
index 390e0027..29a91b21 100644
--- a/code/modules/language/drone.dm
+++ b/code/modules/language/drone.dm
@@ -3,6 +3,7 @@
desc = "A heavily encoded damage control coordination stream, with special flags for hats."
speech_verb = "chitters"
ask_verb = "chitters inquisitively"
+ sing_verb = "chimes"
exclaim_verb = "chitters loudly"
spans = list(SPAN_ROBOT)
key = "d"
diff --git a/code/modules/language/language.dm b/code/modules/language/language.dm
index e4488fc7..a2508785 100644
--- a/code/modules/language/language.dm
+++ b/code/modules/language/language.dm
@@ -11,6 +11,7 @@
var/ask_verb = "asks" // Used when sentence ends in a ?
var/exclaim_verb = "exclaims" // Used when sentence ends in a !
var/whisper_verb = "whispers" // Optional. When not specified speech_verb + quietly/softly is used instead.
+ var/sing_verb = "sings" // Used for singing.
var/list/signlang_verb = list("signs", "gestures") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags
var/key // Character used to speak in language
// If key is null, then the language isn't real or learnable.
diff --git a/code/modules/language/machine.dm b/code/modules/language/machine.dm
index b7ef701e..c251de75 100644
--- a/code/modules/language/machine.dm
+++ b/code/modules/language/machine.dm
@@ -4,6 +4,7 @@
speech_verb = "whistles"
ask_verb = "chirps"
exclaim_verb = "whistles loudly"
+ sing_verb = "whistles melodically"
spans = list(SPAN_ROBOT)
key = "6"
flags = NO_STUTTER
diff --git a/code/modules/language/monkey.dm b/code/modules/language/monkey.dm
index 53e598b0..5e78a37a 100644
--- a/code/modules/language/monkey.dm
+++ b/code/modules/language/monkey.dm
@@ -4,6 +4,7 @@
speech_verb = "chimpers"
ask_verb = "chimpers"
exclaim_verb = "screeches"
+ sing_verb = "chimpers tunefully"
key = "1"
space_chance = 100
syllables = list("oop", "aak", "chee", "eek")
diff --git a/code/modules/language/mushroom.dm b/code/modules/language/mushroom.dm
index b896d114..97287ea5 100644
--- a/code/modules/language/mushroom.dm
+++ b/code/modules/language/mushroom.dm
@@ -5,6 +5,7 @@
ask_verb = "puffs inquisitively"
exclaim_verb = "poofs loudly"
whisper_verb = "puffs quietly"
+ sing_verb = "puffs musically"
key = "y"
sentence_chance = 0
default_priority = 80
diff --git a/code/modules/language/narsian.dm b/code/modules/language/narsian.dm
index 42d0a065..deff8926 100644
--- a/code/modules/language/narsian.dm
+++ b/code/modules/language/narsian.dm
@@ -4,6 +4,7 @@
speech_verb = "intones"
ask_verb = "inquires"
exclaim_verb = "invokes"
+ sing_verb = "intones"
key = "n"
sentence_chance = 8
space_chance = 95 //very high due to the potential length of each syllable
diff --git a/code/modules/language/swarmer.dm b/code/modules/language/swarmer.dm
index e3b78267..c0ede4bb 100644
--- a/code/modules/language/swarmer.dm
+++ b/code/modules/language/swarmer.dm
@@ -4,6 +4,7 @@
speech_verb = "tones"
ask_verb = "tones inquisitively"
exclaim_verb = "tones loudly"
+ sing_verb = "tones"
spans = list(SPAN_ROBOT)
key = "s"
flags = NO_STUTTER
diff --git a/code/modules/language/xenocommon.dm b/code/modules/language/xenocommon.dm
index f046ecd3..8b5bb78d 100644
--- a/code/modules/language/xenocommon.dm
+++ b/code/modules/language/xenocommon.dm
@@ -4,6 +4,7 @@
speech_verb = "hisses"
ask_verb = "hisses"
exclaim_verb = "hisses"
+ sing_verb = "hisses musically"
key = "4"
syllables = list("sss","sSs","SSS")
default_priority = 50
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index 537cf703..d4904069 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -179,15 +179,14 @@
* Book
*/
/obj/item/book
- name = "book"
+ name = "Datapad"
icon = 'icons/obj/library.dmi'
icon_state ="book"
- desc = "Crack it open, inhale the musk of its pages, and learn something new."
+ desc = "A fancy new state of the art Digital-Readpad(tm) provided by Kinaris.Co, No more 20th century paper!"
throw_speed = 1
throw_range = 5
w_class = WEIGHT_CLASS_NORMAL //upped to three because books are, y'know, pretty big. (and you could hide them inside eachother recursively forever)
attack_verb = list("bashed", "whacked", "educated")
- resistance_flags = FLAMMABLE
var/dat //Actual page content
var/due_date = 0 //Game time in 1/10th seconds
var/author //Who wrote the thing, can be changed by pen or PC. It is not automatically assigned
@@ -200,28 +199,28 @@
to_chat(user, "As you are trying to read, you suddenly feel very stupid!")
return
if(ismonkey(user))
- to_chat(user, "You skim through the book but can't comprehend any of it.")
+ to_chat(user, "You skim through the datapad but can't comprehend any of it.")
return
if(dat)
- user << browse("Penned by [author]. " + "[dat]", "window=book[window_size != null ? ";size=[window_size]" : ""]")
- user.visible_message("[user] opens a book titled \"[title]\" and begins reading intently.")
+ user << browse("Created by [author]. " + "[dat]", "window=book[window_size != null ? ";size=[window_size]" : ""]")
+ user.visible_message("[user] begins reading a datapad titled \"[title]\" intently.")
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "book_nerd", /datum/mood_event/book_nerd)
onclose(user, "book")
else
- to_chat(user, "This book is completely blank!")
+ to_chat(user, "This datapad is completely blank!")
/obj/item/book/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/pen))
if(is_blind(user))
- to_chat(user, " As you are trying to write on the book, you suddenly feel very stupid!")
+ to_chat(user, " As you are trying to edit the datapad, you suddenly feel very stupid!")
return
if(unique)
- to_chat(user, "These pages don't seem to take the ink well! Looks like you can't modify it.")
+ to_chat(user, "These entries don't seem to be editable! Looks like you can't modify it.")
return
var/literate = user.is_literate()
if(!literate)
- to_chat(user, "You scribble illegibly on the cover of [src]!")
+ to_chat(user, "You enter illegible text on the cover page of [src]!")
return
var/choice = input("What would you like to change?") in list("Title", "Contents", "Author", "Cancel")
if(!user.canUseTopic(src, BE_CLOSE, literate))
@@ -232,7 +231,7 @@
if(!user.canUseTopic(src, BE_CLOSE, literate))
return
if (length(newtitle) > 20)
- to_chat(user, "That title won't fit on the cover!")
+ to_chat(user, "That title is too large for the datapad's memory!")
return
if(!newtitle)
to_chat(user, "That title is invalid.")
@@ -241,7 +240,7 @@
name = newtitle
title = newtitle
if("Contents")
- var/content = stripped_input(user, "Write your book's contents (HTML NOT allowed):","","",8192)
+ var/content = stripped_input(user, "Write your datapad's contents (HTML NOT allowed):","","",8192)
if(!user.canUseTopic(src, BE_CLOSE, literate))
return
if(!content)
@@ -250,7 +249,7 @@
else
dat += content
if("Author")
- var/newauthor = stripped_input(user, "Write the author's name:")
+ var/newauthor = stripped_input(user, "Enter the author's name:")
if(!user.canUseTopic(src, BE_CLOSE, literate))
return
if(!newauthor)
@@ -291,10 +290,10 @@
scanner.computer.inventory.Add(src)
to_chat(user, "[I]'s screen flashes: 'Book stored in buffer. Title added to general inventory.'")
- else if(istype(I, /obj/item/kitchen/knife) || istype(I, /obj/item/wirecutters))
- to_chat(user, "You begin to carve out [title]...")
+ else if(istype(I, /obj/item/multitool))
+ to_chat(user, "You begin to erase the data from [title] with your PDA!...")
if(do_after(user, 30, target = src))
- to_chat(user, "You carve out the pages from [title]! You didn't want to read it anyway.")
+ to_chat(user, "You erase all the page data from [title] with your PDA! You didn't want to read it anyway.")
var/obj/item/storage/book/B = new
B.name = src.name
B.title = src.title
diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm
index 49986e71..92cb0ecd 100644
--- a/code/modules/library/lib_machines.dm
+++ b/code/modules/library/lib_machines.dm
@@ -564,10 +564,10 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
* Book binder
*/
/obj/machinery/bookbinder
- name = "book binder"
+ name = "Datapad transcriptor"
icon = 'icons/obj/library.dmi'
icon_state = "binder"
- desc = "Only intended for binding paper products."
+ desc = "Reads and scans papers placed into it for text to datapad conversion."
density = TRUE
var/busy = FALSE
diff --git a/code/modules/library/random_books.dm b/code/modules/library/random_books.dm
index accd4773..a3e9b11f 100644
--- a/code/modules/library/random_books.dm
+++ b/code/modules/library/random_books.dm
@@ -58,7 +58,7 @@
B.author = query_get_random_books.item[2]
B.title = query_get_random_books.item[3]
B.dat = query_get_random_books.item[4]
- B.name = "Book: [B.title]"
+ B.name = "Datapad: [B.title]"
B.icon_state= "book[rand(1,8)]"
qdel(query_get_random_books)
diff --git a/code/modules/library/soapstone.dm b/code/modules/library/soapstone.dm
index 88d1248a..cf872cc8 100644
--- a/code/modules/library/soapstone.dm
+++ b/code/modules/library/soapstone.dm
@@ -153,6 +153,7 @@
var/newcolor = copytext(hash, 1, 7)
add_atom_colour("#[newcolor]", FIXED_COLOUR_PRIORITY)
light_color = "#[newcolor]"
+ light_power = 0.3
set_light(1)
/obj/structure/chisel_message/proc/pack()
diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm
index 23ec0297..bf1fe383 100644
--- a/code/modules/mining/equipment/explorer_gear.dm
+++ b/code/modules/mining/equipment/explorer_gear.dm
@@ -136,7 +136,7 @@
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
hoodtype = /obj/item/clothing/head/hooded/explorer/seva
- armor = list("melee" = 15, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 25, "bio" = 50, "rad" = 25, "fire" = 100, "acid" = 25)
+ armor = list("melee" = 15, "bullet" = 5, "laser" = 20, "energy" = 10, "bomb" = 25, "bio" = 100, "rad" = 25, "fire" = 100, "acid" = 25)
resistance_flags = FIRE_PROOF | GOLIATH_WEAKNESS
/obj/item/clothing/head/hooded/explorer/seva
@@ -145,7 +145,7 @@
icon_state = "seva"
item_state = "seva"
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 25, "bio" = 50, "rad" = 25, "fire" = 100, "acid" = 25)
+ armor = list("melee" = 10, "bullet" = 5, "laser" = 20, "energy" = 10, "bomb" = 25, "bio" = 100, "rad" = 25, "fire" = 100, "acid" = 25)
resistance_flags = FIRE_PROOF | GOLIATH_WEAKNESS
/obj/item/clothing/mask/gas/seva
@@ -153,32 +153,38 @@
desc = "A face-covering plate that can be connected to an air supply. Intended for use with the SEVA Suit."
icon_state = "seva"
item_state = "seva"
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 10, "energy" = 5, "bomb" = 0, "bio" = 100, "rad" = 30, "fire" = 100, "acid" = 25)
resistance_flags = FIRE_PROOF
/****************Exo-Suit and Mask****************/
/obj/item/clothing/suit/hooded/explorer/exo
- name = "Exo-suit"
- desc = "A robust suit for exploring dangerous environments."
+ name = "Explorer Exoskeleton"
+ desc = "A very robust military exosuit. It is composed of two separate pieces of equipment: the Radiation suit which boasts heavy military kevlar around the entire body, along with composite plates on some of the outer regions of the armour."
icon_state = "exo"
item_state = "exo"
w_class = WEIGHT_CLASS_BULKY
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
hoodtype = /obj/item/clothing/head/hooded/explorer/exo
- armor = list("melee" = 65, "bullet" = 5, "laser" = 5, "energy" = 5, "bomb" = 60, "bio" = 25, "rad" = 10, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 60, "bullet" = 15, "laser" = 5, "energy" = 5, "bomb" = 60, "bio" = 25, "rad" = 10, "fire" = 0, "acid" = 0)
resistance_flags = FIRE_PROOF | GOLIATH_RESISTANCE
/obj/item/clothing/head/hooded/explorer/exo
- name = "Exo-hood"
- desc = "A robust helmet for exploring dangerous environments."
+ name = "Tactical Exo-Helmet"
+ desc = "A recent model of a tactical helmet that lacks camouflage. It is not known how it made its way into NT. The helmet is designed to provide a squad leader with strategic superiority over the enemy via its many scanners and satellite communications devices, which have not been installed in this particular helmet. Comes with multi-layered Kevlar protection and armored elements."
icon_state = "exo"
item_state = "exo"
- armor = list("melee" = 65, "bullet" = 5, "laser" = 5, "energy" = 5, "bomb" = 60, "bio" = 25, "rad" = 10, "fire" = 0, "acid" = 0)
+ armor = list("melee" = 60, "bullet" = 15, "laser" = 5, "energy" = 5, "bomb" = 60, "bio" = 25, "rad" = 10, "fire" = 0, "acid" = 0)
resistance_flags = FIRE_PROOF | GOLIATH_RESISTANCE
/obj/item/clothing/mask/gas/exo
- name = "Exosuit Mask"
- desc = "A face-covering mask that can be connected to an air supply. Intended for use with the Exosuit."
+ name = "M40 Gasmask"
+ desc = "One of various gas masks used by the ancient U.S.A.F. and its allies to protect from field concentrations of chemical and biological agents, along with radiological fallout particles. It is not effective in an oxygen deficient environment, so it must be connected to an air supply."
icon_state = "exo"
item_state = "exo"
+ visor_flags = BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS
+ visor_flags_inv = HIDEFACIALHAIR
+ visor_flags_cover = MASKCOVERSMOUTH
+ actions_types = list(/datum/action/item_action/adjust)
+ armor = list("melee" = 10, "bullet" = 5, "laser" = 5, "energy" = 5, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 20, "acid" = 40)
resistance_flags = FIRE_PROOF
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index 3fdbacc9..eb70ab82 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -261,7 +261,7 @@
desc = "A wing ripped from a watcher. Suitable as a trophy for a kinetic crusher."
icon_state = "watcher_wing"
denied_type = /obj/item/crusher_trophy/watcher_wing
- bonus_value = 50
+ bonus_value = 30
/obj/item/crusher_trophy/watcher_wing/effect_desc()
return "mark detonation to prevent certain creatures from using certain attacks for [bonus_value*0.1] second\s"
@@ -442,4 +442,4 @@
new /obj/effect/temp_visual/hierophant/wall/crusher(otherT, user)
/obj/effect/temp_visual/hierophant/wall/crusher
- duration = 75
+ duration = 55
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index 47fd657c..bfe42b5a 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -582,7 +582,7 @@
//h13 assign your characters custom height.
if (H.custom_body_size > 0)
- H.resize = (H.custom_body_size * 0.01)
+ H.size_multiplier = (H.custom_body_size * 0.01)
//h13 give your starting impregchance (30%)
if (H.breedable == TRUE)
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm
index 31faabf6..84c9feaa 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm
@@ -43,13 +43,668 @@
/datum/sprite_accessory/tails_animated/human/none
name = "None"
icon_state = "none"
-/*
+
+/datum/sprite_accessory/tails/lizard/axolotl
+ name = "Axolotl"
+ icon_state = "axolotl"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/lizard/axolotl
+ name = "Axolotl"
+ icon_state = "axolotl"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/body_markings/guilmon
+ name = "Guilmon"
+ icon_state = "guilmon"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/markings_notmammals.dmi'
+
+/datum/sprite_accessory/tails/lizard/guilmon
+ name = "Guilmon"
+ icon_state = "guilmon"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/lizard/guilmon
+ name = "Guilmon"
+ icon_state = "guilmon"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/******************************************
+************** Human Tails ****************
+*******************************************/
+
+/datum/sprite_accessory/tails/human/none
+ name = "None"
+ icon_state = "none"
+
+/datum/sprite_accessory/tails_animated/human/none
+ name = "None"
+ icon_state = "none"
+
+/datum/sprite_accessory/tails/human/ailurus
+ name = "Red Panda"
+ icon_state = "wah"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails_animated/human/ailurus
+ name = "Red Panda"
+ icon_state = "wah"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails/human/axolotl
+ name = "Axolotl"
+ icon_state = "axolotl"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails_animated/human/axolotl
+ name = "Axolotl"
+ icon_state = "axolotl"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails/human/bee
+ name = "Bee"
+ icon_state = "bee"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails_animated/human/bee
+ name = "Bee"
+ icon_state = "bee"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
/datum/sprite_accessory/tails/human/cat
name = "Cat"
icon_state = "cat"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
color_src = HAIR
/datum/sprite_accessory/tails_animated/human/cat
name = "Cat"
icon_state = "cat"
- color_src = HAIR*/
\ No newline at end of file
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = HAIR
+
+/datum/sprite_accessory/tails/human/catbig
+ name = "Cat, Big"
+ icon_state = "catbig"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails_animated/human/catbig
+ name = "Cat, Big"
+ icon_state = "catbig"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails/human/cow
+ name = "Cow"
+ icon_state = "cow"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails_animated/human/cow
+ name = "Cow"
+ icon_state = "cow"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails/human/corvid
+ name = "Corvid"
+ icon_state = "crow"
+
+/datum/sprite_accessory/tails_animated/human/corvid
+ name = "Corvid"
+ icon_state = "crow"
+
+/datum/sprite_accessory/tails/human/eevee
+ name = "Eevee"
+ icon_state = "eevee"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails_animated/human/eevee
+ name = "Eevee"
+ icon_state = "eevee"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails/human/fennec
+ name = "Fennec"
+ icon_state = "fennec"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails_animated/human/fennec
+ name = "Fennec"
+ icon_state = "fennec"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails/human/fish
+ name = "Fish"
+ icon_state = "fish"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails_animated/human/fish
+ name = "Fish"
+ icon_state = "fish"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails/human/fox
+ name = "Fox"
+ icon_state = "fox"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails_animated/human/fox
+ name = "Fox"
+ icon_state = "fox"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails/human/horse
+ name = "Horse"
+ icon_state = "horse"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = HAIR
+
+/datum/sprite_accessory/tails_animated/human/horse
+ name = "Horse"
+ icon_state = "horse"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = HAIR
+
+/datum/sprite_accessory/tails/human/husky
+ name = "Husky"
+ icon_state = "husky"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails_animated/human/husky
+ name = "Husky"
+ icon_state = "husky"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails/human/insect
+ name = "Insect"
+ icon_state = "insect"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails_animated/human/insect
+ name = "insect"
+ icon_state = "insect"
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+ color_src = MATRIXED
+
+/datum/sprite_accessory/tails/human/kitsune
+ name = "Kitsune"
+ icon_state = "kitsune"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/kitsune
+ name = "Kitsune"
+ icon_state = "kitsune"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/murid
+ name = "Murid"
+ icon_state = "murid"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/murid
+ name = "Murid"
+ icon_state = "murid"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/otie
+ name = "Otusian"
+ icon_state = "otie"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/otie
+ name = "Otusian"
+ icon_state = "otie"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/orca
+ name = "Orca"
+ icon_state = "orca"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/orca
+ name = "Orca"
+ icon_state = "orca"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/pede
+ name = "Scolipede"
+ icon_state = "pede"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/pede
+ name = "Scolipede"
+ icon_state = "pede"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/rabbit
+ name = "Rabbit"
+ icon_state = "rabbit"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/rabbit
+ name = "Rabbit"
+ icon_state = "rabbit"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/sergal
+ name = "Sergal"
+ icon_state = "sergal"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/sergal
+ name = "Sergal"
+ icon_state = "sergal"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/skunk
+ name = "skunk"
+ icon_state = "skunk"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/skunk
+ name = "skunk"
+ icon_state = "skunk"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/shark
+ name = "Shark"
+ icon_state = "shark"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/shark
+ name = "Shark"
+ icon_state = "shark"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/datashark
+ name = "datashark"
+ icon_state = "datashark"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/datashark
+ name = "datashark"
+ icon_state = "datashark"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/straighttail
+ name = "Straight Tail"
+ icon_state = "straighttail"
+
+/datum/sprite_accessory/tails_animated/human/straighttail
+ name = "Straight Tail"
+ icon_state = "straighttail"
+
+/datum/sprite_accessory/tails/human/squirrel
+ name = "Squirrel"
+ icon_state = "squirrel"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/squirrel
+ name = "Squirrel"
+ icon_state = "squirrel"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/tentacle
+ name = "Tentacle"
+ icon_state = "tentacle"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/tentacle
+ name = "Tentacle"
+ icon_state = "tentacle"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/tiger
+ name = "Tiger"
+ icon_state = "tiger"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/tiger
+ name = "Tiger"
+ icon_state = "tiger"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails/human/wolf
+ name = "Wolf"
+ icon_state = "wolf"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/tails_animated/human/wolf
+ name = "Wolf"
+ icon_state = "wolf"
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/******************************************
+************** Furry Tails ****************
+*******************************************/
+
+/datum/sprite_accessory/mam_tails
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/mam_tails/none
+ name = "None"
+ icon_state = "none"
+
+/datum/sprite_accessory/mam_tails_animated
+ color_src = MATRIXED
+ icon = 'modular_citadel/icons/mob/mam_tails.dmi'
+
+/datum/sprite_accessory/mam_tails_animated/none
+ name = "None"
+ icon_state = "none"
+ color_src = MATRIXED
+
+/datum/sprite_accessory/mam_tails/ailurus
+ name = "Red Panda"
+ icon_state = "wah"
+ extra = TRUE
+
+/datum/sprite_accessory/mam_tails_animated/ailurus
+ name = "Red Panda"
+ icon_state = "wah"
+ extra = TRUE
+
+/datum/sprite_accessory/mam_tails/axolotl
+ name = "Axolotl"
+ icon_state = "axolotl"
+
+/datum/sprite_accessory/mam_tails_animated/axolotl
+ name = "Axolotl"
+ icon_state = "axolotl"
+
+/datum/sprite_accessory/mam_tails/bee
+ name = "Bee"
+ icon_state = "bee"
+
+/datum/sprite_accessory/mam_tails_animated/bee
+ name = "Bee"
+ icon_state = "bee"
+
+/datum/sprite_accessory/mam_tails/cat
+ name = "Cat"
+ icon_state = "cat"
+ color_src = HAIR
+
+/datum/sprite_accessory/mam_tails_animated/cat
+ name = "Cat"
+ icon_state = "cat"
+ color_src = HAIR
+
+/datum/sprite_accessory/mam_tails/catbig
+ name = "Cat, Big"
+ icon_state = "catbig"
+
+/datum/sprite_accessory/mam_tails_animated/catbig
+ name = "Cat, Big"
+ icon_state = "catbig"
+
+/datum/sprite_accessory/mam_tails/corvid
+ name = "Corvid"
+ icon_state = "crow"
+
+/datum/sprite_accessory/mam_tails_animated/corvid
+ name = "Corvid"
+ icon_state = "crow"
+
+/datum/sprite_accessory/mam_tail/cow
+ name = "Cow"
+ icon_state = "cow"
+
+/datum/sprite_accessory/mam_tails_animated/cow
+ name = "Cow"
+ icon_state = "cow"
+
+/datum/sprite_accessory/mam_tails/eevee
+ name = "Eevee"
+ icon_state = "eevee"
+
+/datum/sprite_accessory/mam_tails_animated/eevee
+ name = "Eevee"
+ icon_state = "eevee"
+
+/datum/sprite_accessory/mam_tails/fennec
+ name = "Fennec"
+ icon_state = "fennec"
+
+/datum/sprite_accessory/mam_tails_animated/fennec
+ name = "Fennec"
+ icon_state = "fennec"
+
+/datum/sprite_accessory/mam_tails/human/fish
+ name = "Fish"
+ icon_state = "fish"
+
+/datum/sprite_accessory/mam_tails_animated/human/fish
+ name = "Fish"
+ icon_state = "fish"
+
+/datum/sprite_accessory/mam_tails/fox
+ name = "Fox"
+ icon_state = "fox"
+
+/datum/sprite_accessory/mam_tails_animated/fox
+ name = "Fox"
+ icon_state = "fox"
+
+/datum/sprite_accessory/mam_tails/hawk
+ name = "Hawk"
+ icon_state = "hawk"
+
+/datum/sprite_accessory/mam_tails_animated/hawk
+ name = "Hawk"
+ icon_state = "hawk"
+
+/datum/sprite_accessory/mam_tails/horse
+ name = "Horse"
+ icon_state = "horse"
+ color_src = HAIR
+
+/datum/sprite_accessory/mam_tails_animated/horse
+ name = "Horse"
+ icon_state = "horse"
+ color_src = HAIR
+
+/datum/sprite_accessory/mam_tails/husky
+ name = "Husky"
+ icon_state = "husky"
+
+/datum/sprite_accessory/mam_tails_animated/husky
+ name = "Husky"
+ icon_state = "husky"
+
+datum/sprite_accessory/mam_tails/insect
+ name = "Insect"
+ icon_state = "insect"
+
+/datum/sprite_accessory/mam_tails_animated/insect
+ name = "Insect"
+ icon_state = "insect"
+
+/datum/sprite_accessory/mam_tails/kangaroo
+ name = "kangaroo"
+ icon_state = "kangaroo"
+
+/datum/sprite_accessory/mam_tails_animated/kangaroo
+ name = "kangaroo"
+ icon_state = "kangaroo"
+
+/datum/sprite_accessory/mam_tails/kitsune
+ name = "Kitsune"
+ icon_state = "kitsune"
+
+/datum/sprite_accessory/mam_tails_animated/kitsune
+ name = "Kitsune"
+ icon_state = "kitsune"
+
+/datum/sprite_accessory/mam_tails/lab
+ name = "Lab"
+ icon_state = "lab"
+
+/datum/sprite_accessory/mam_tails_animated/lab
+ name = "Lab"
+ icon_state = "lab"
+
+/datum/sprite_accessory/mam_tails/murid
+ name = "Murid"
+ icon_state = "murid"
+
+/datum/sprite_accessory/mam_tails_animated/murid
+ name = "Murid"
+ icon_state = "murid"
+
+/datum/sprite_accessory/mam_tails/otie
+ name = "Otusian"
+ icon_state = "otie"
+
+/datum/sprite_accessory/mam_tails_animated/otie
+ name = "Otusian"
+ icon_state = "otie"
+
+/datum/sprite_accessory/mam_tails/orca
+ name = "Orca"
+ icon_state = "orca"
+
+/datum/sprite_accessory/mam_tails_animated/orca
+ name = "Orca"
+ icon_state = "orca"
+
+/datum/sprite_accessory/mam_tails/pede
+ name = "Scolipede"
+ icon_state = "pede"
+
+/datum/sprite_accessory/mam_tails_animated/pede
+ name = "Scolipede"
+ icon_state = "pede"
+
+/datum/sprite_accessory/mam_tails/rabbit
+ name = "Rabbit"
+ icon_state = "rabbit"
+
+/datum/sprite_accessory/mam_tails_animated/rabbit
+ name = "Rabbit"
+ icon_state = "rabbit"
+
+/datum/sprite_accessory/mam_tails/sergal
+ name = "Sergal"
+ icon_state = "sergal"
+
+/datum/sprite_accessory/mam_tails_animated/sergal
+ name = "Sergal"
+ icon_state = "sergal"
+
+/datum/sprite_accessory/mam_tails/skunk
+ name = "Skunk"
+ icon_state = "skunk"
+
+/datum/sprite_accessory/mam_tails_animated/skunk
+ name = "Skunk"
+ icon_state = "skunk"
+
+/datum/sprite_accessory/mam_tails/shark
+ name = "Shark"
+ icon_state = "shark"
+
+/datum/sprite_accessory/mam_tails_animated/shark
+ name = "Shark"
+ icon_state = "shark"
+
+/datum/sprite_accessory/mam_tails/shepherd
+ name = "Shepherd"
+ icon_state = "shepherd"
+
+/datum/sprite_accessory/mam_tails_animated/shepherd
+ name = "Shepherd"
+ icon_state = "shepherd"
+
+/datum/sprite_accessory/mam_tails/straighttail
+ name = "Straight Tail"
+ icon_state = "straighttail"
+
+/datum/sprite_accessory/mam_tails_animated/straighttail
+ name = "Straight Tail"
+ icon_state = "straighttail"
+
+/datum/sprite_accessory/mam_tails/squirrel
+ name = "Squirrel"
+ icon_state = "squirrel"
+
+/datum/sprite_accessory/mam_tails_animated/squirrel
+ name = "Squirrel"
+ icon_state = "squirrel"
+
+/datum/sprite_accessory/mam_tails/tentacle
+ name = "Tentacle"
+ icon_state = "tentacle"
+
+/datum/sprite_accessory/mam_tails_animated/tentacle
+ name = "Tentacle"
+ icon_state = "tentacle"
+
+/datum/sprite_accessory/mam_tails/tiger
+ name = "Tiger"
+ icon_state = "tiger"
+
+/datum/sprite_accessory/mam_tails_animated/tiger
+ name = "Tiger"
+ icon_state = "tiger"
+
+/datum/sprite_accessory/mam_tails/wolf
+ name = "Wolf"
+ icon_state = "wolf"
+
+/datum/sprite_accessory/mam_tails_animated/wolf
+ name = "Wolf"
+ icon_state = "wolf"
\ No newline at end of file
diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm
index 6dd7a109..70fbba8d 100644
--- a/code/modules/mob/dead/observer/say.dm
+++ b/code/modules/mob/dead/observer/say.dm
@@ -34,6 +34,9 @@
else
to_follow = V.source
var/link = FOLLOW_LINK(src, to_follow)
+ // Create map text prior to modifying message for goonchat
+ if (client?.prefs.chat_on_map && (client.prefs.see_chat_non_mob || ismob(speaker)))
+ create_chat_message(speaker, message_language, raw_message, spans, message_mode)
// Recompose the message, because it's scrambled by default
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
to_chat(src, "[link] [message]")
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 89a7ec25..0afe2d08 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -159,22 +159,35 @@
return
//END OF CIT CHANGES
- var/atom/movable/thrown_thing
var/obj/item/I = src.get_active_held_item()
- if(!I)
- if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
- var/mob/living/throwable_mob = pulling
- if(!throwable_mob.buckled)
- thrown_thing = throwable_mob
+ var/atom/movable/thrown_thing
+ var/mob/living/throwable_mob
+
+ if(istype(I, /obj/item/clothing/head/mob_holder))
+ var/obj/item/clothing/head/mob_holder/holder = I
+ if(holder.held_mob)
+ throwable_mob = holder.held_mob
+ holder.release()
+
+ if(!I || throwable_mob)
+ if(!throwable_mob && pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
+ throwable_mob = pulling
+
+ if(throwable_mob && !throwable_mob.buckled)
+ thrown_thing = throwable_mob
+ if(pulling)
stop_pulling()
- if(HAS_TRAIT(src, TRAIT_PACIFISM))
- to_chat(src, "You gently let go of [throwable_mob].")
- adjustStaminaLossBuffered(25)//CIT CHANGE - throwing an entire person shall be very tiring
- var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
- var/turf/end_T = get_turf(target)
- if(start_T && end_T)
- log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
+ if(HAS_TRAIT(src, TRAIT_PACIFISM))
+ to_chat(src, "You gently let go of [throwable_mob].")
+ return
+
+ adjustStaminaLossBuffered(25)//CIT CHANGE - throwing an entire person shall be very tiring
+ var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
+ var/turf/end_T = get_turf(target)
+ if(start_T && end_T)
+
+ log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
else if(!CHECK_BITFIELD(I.item_flags, ABSTRACT) && !HAS_TRAIT(I, TRAIT_NODROP))
thrown_thing = I
@@ -194,6 +207,8 @@
newtonian_move(get_dir(target, src))
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src)
+
+
/mob/living/carbon/restrained(ignore_grab)
. = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))
@@ -271,9 +286,13 @@
if(restrained())
changeNext_move(CLICK_CD_BREAKOUT)
last_special = world.time + CLICK_CD_BREAKOUT
+ var/buckle_cd = 600
+ if(handcuffed)
+ var/obj/item/restraints/O = src.get_item_by_slot(SLOT_HANDCUFFED)
+ buckle_cd = O.breakouttime
visible_message("[src] attempts to unbuckle [p_them()]self!", \
- "You attempt to unbuckle yourself... (This will take around one minute and you need to stay still.)")
- if(do_after(src, 600, 0, target = src))
+ "You attempt to unbuckle yourself... (This will take around [round(buckle_cd/600,1)] minute\s, and you need to stay still.)")
+ if(do_after(src, buckle_cd, 0, target = src))
if(!buckled)
return
buckled.user_unbuckle_mob(src,src)
@@ -809,7 +828,8 @@
drop_all_held_items()
stop_pulling()
throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = src.handcuffed)
- SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "handcuffed", /datum/mood_event/handcuffed)
+ if(handcuffed.demoralize_criminals)
+ SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "handcuffed", /datum/mood_event/handcuffed)
else
clear_alert("handcuffed")
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "handcuffed")
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 1dbf6b69..bd9c20ae 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -282,10 +282,17 @@
else if(check_zone(M.zone_selected) == "head")
var/mob/living/carbon/human/H = src
var/datum/species/pref_species = H.dna.species
-
- M.visible_message("[M] gives [H] a pat on the head to make [p_them()] feel better!", \
+
+ if(HAS_TRAIT(H, TRAIT_HEADPAT_SLUT))
+ M.visible_message("[M] gives [H] a pat on the head to make [p_them()] feel better! They seem incredibly pleased!", \
+ "You give [H] a pat on the head to make [p_them()] feel better! They seem to like it way too much")
+ SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "lewd_headpat", /datum/mood_event/lewd_headpat)
+ H.adjustArousalLoss(5) //Headpats are hot af
+ else
+ M.visible_message("[M] gives [H] a pat on the head to make [p_them()] feel better!", \
"You give [H] a pat on the head to make [p_them()] feel better!")
- SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat)
+ SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat)
+
if(HAS_TRAIT(M, TRAIT_FRIENDLY))
GET_COMPONENT_FROM(mood, /datum/component/mood, M)
if (mood.sanity >= SANITY_GREAT)
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index 22da4634..b4ce85c0 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -16,6 +16,10 @@
msg += "[t_He] [t_is] wearing [wear_mask.get_examine_string(user)] on [t_his] face.\n"
if (wear_neck)
msg += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
+ if(can_be_held)
+ msg += "[t_He] looks small enough to be picked up with Alt+Click!\n"
+
+
for(var/obj/item/I in held_items)
if(!(I.item_flags & ABSTRACT))
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 1bfff1a9..50f63044 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -107,6 +107,10 @@
//Status effects
msg += status_effect_examines()
+ //Can be picked up?
+ if(can_be_held)
+ msg += "[t_He] looks small enough to be picked up with Alt+Click!\n"
+
//CIT CHANGES START HERE - adds genital details to examine text
if(LAZYLEN(internal_organs))
for(var/obj/item/organ/genital/dicc in internal_organs)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index dcb1980c..7ae413ec 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -854,52 +854,84 @@
.["Copy outfit"] = "?_src_=vars;[HrefToken()];copyoutfit=[REF(src)]"
/mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user)
- //If they dragged themselves and we're currently aggressively grabbing them try to piggyback
- if(user == target && can_piggyback(target) && pulling == target && (HAS_TRAIT(src, TRAIT_PACIFISM) || grab_state >= GRAB_AGGRESSIVE) && stat == CONSCIOUS)
- buckle_mob(target,TRUE,TRUE)
+ if(pulling == target && grab_state >= GRAB_AGGRESSIVE && stat == CONSCIOUS)
+ //If they dragged themselves and we're currently aggressively grabbing them try to piggyback
+ if(user == target && can_piggyback(target))
+ piggyback(target)
+ return
+ //If you dragged them to you and you're aggressively grabbing try to fireman carry them
+ else if(user != target)
+ fireman_carry(target)
+ return
. = ..()
-/mob/living/carbon/human/proc/piggyback_instant(mob/living/M)
- return buckle_mob(M, TRUE, TRUE, FALSE, TRUE)
+//src is the user that will be carrying, target is the mob to be carried
+/mob/living/carbon/human/proc/can_piggyback(mob/living/carbon/target)
+ return (istype(target) && target.stat == CONSCIOUS)
-//Can C try to piggyback at all.
-/mob/living/carbon/human/proc/can_piggyback(mob/living/carbon/C)
- if(istype(C) && C.stat == CONSCIOUS)
- return TRUE
- return FALSE
+/mob/living/carbon/human/proc/can_be_firemanned(mob/living/carbon/target)
+ return (ishuman(target) && target.lying)
-/mob/living/carbon/human/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE, bypass_piggybacking = FALSE, no_delay = FALSE)
+/mob/living/carbon/human/proc/fireman_carry(mob/living/carbon/target)
+ if(can_be_firemanned(target))
+ visible_message("[src] starts lifting [target] onto their back...",
+ "You start lifting [target] onto your back...")
+ if(do_after(src, 30, TRUE, target))
+ //Second check to make sure they're still valid to be carried
+ if(can_be_firemanned(target) && !incapacitated(FALSE, TRUE))
+ target.resting = FALSE
+ buckle_mob(target, TRUE, TRUE, 90, 1, 0)
+ return
+ visible_message("[src] fails to fireman carry [target]!")
+ else
+ to_chat(src, "You can't fireman carry [target] while they're standing!")
+
+/mob/living/carbon/human/proc/piggyback(mob/living/carbon/target)
+ if(can_piggyback(target))
+ visible_message("[target] starts to climb onto [src]...")
+ if(do_after(target, 15, target = src))
+ if(can_piggyback(target))
+ if(target.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
+ target.visible_message("[target] can't hang onto [src]!")
+ return
+ buckle_mob(target, TRUE, TRUE, FALSE, 0, 2)
+ else
+ visible_message("[target] fails to climb onto [src]!")
+ else
+ to_chat(target, "You can't piggyback ride [src] right now!")
+
+/mob/living/carbon/human/buckle_mob(mob/living/target, force = FALSE, check_loc = TRUE, lying_buckle = FALSE, hands_needed = 0, target_hands_needed = 0)
if(!force)//humans are only meant to be ridden through piggybacking and special cases
return
- if(bypass_piggybacking)
- return ..()
- if(!is_type_in_typecache(M, can_ride_typecache))
- M.visible_message("[M] really can't seem to mount [src]...")
+ if(!is_type_in_typecache(target, can_ride_typecache))
+ target.visible_message("[target] really can't seem to mount [src]...")
return
+ buckle_lying = lying_buckle
var/datum/component/riding/human/riding_datum = LoadComponent(/datum/component/riding/human)
- riding_datum.ride_check_rider_incapacitated = TRUE
- riding_datum.ride_check_rider_restrained = TRUE
- riding_datum.set_riding_offsets(RIDING_OFFSET_ALL, list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(-6, 4), TEXT_WEST = list( 6, 4)))
- if(buckled_mobs && ((M in buckled_mobs) || (buckled_mobs.len >= max_buckled_mobs)) || buckled || (M.stat != CONSCIOUS))
+ if(target_hands_needed)
+ riding_datum.ride_check_rider_restrained = TRUE
+ if(buckled_mobs && ((target in buckled_mobs) || (buckled_mobs.len >= max_buckled_mobs)) || buckled)
return
- if(can_piggyback(M))
- riding_datum.ride_check_ridden_incapacitated = TRUE
- visible_message("[M] starts to climb onto [src]...")
- if(no_delay || do_after(M, 15, target = src))
- if(can_piggyback(M))
- if(M.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
- M.visible_message("[M] can't hang onto [src]!")
- return
- if(!riding_datum.equip_buckle_inhands(M, 2)) //MAKE SURE THIS IS LAST!!
- M.visible_message("[M] can't climb onto [src]!")
- return
- . = ..(M, force, check_loc)
- stop_pulling()
- else
- visible_message("[M] fails to climb onto [src]!")
- else
- . = ..(M,force,check_loc)
- stop_pulling()
+ var/equipped_hands_self
+ var/equipped_hands_target
+ if(hands_needed)
+ equipped_hands_self = riding_datum.equip_buckle_inhands(src, hands_needed, target)
+ if(target_hands_needed)
+ equipped_hands_target = riding_datum.equip_buckle_inhands(target, target_hands_needed)
+
+ if(hands_needed || target_hands_needed)
+ if(hands_needed && !equipped_hands_self)
+ src.visible_message("[src] can't get a grip on [target] because their hands are full!",
+ "You can't get a grip on [target] because your hands are full!")
+ return
+ else if(target_hands_needed && !equipped_hands_target)
+ target.visible_message("[target] can't get a grip on [src] because their hands are full!",
+ "You can't get a grip on [src] because your hands are full!")
+ return
+
+ stop_pulling()
+ riding_datum.handle_vehicle_layer()
+ . = ..(target, force, check_loc)
/mob/living/carbon/human/proc/is_shove_knockdown_blocked() //If you want to add more things that block shove knockdown, extend this
for(var/obj/item/clothing/C in get_equipped_items()) //doesn't include pockets
@@ -1067,3 +1099,9 @@
/mob/living/carbon/human/species/zombie/krokodil_addict
race = /datum/species/krokodil_addict
+
+//define holder_type on nerds we wanna commit scoop to
+/mob/living/carbon/human
+ var/holder_type = /obj/item/clothing/head/mob_holder/micro
+ can_be_held = "micro"
+
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 63f1bd08..d0a16ea0 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -65,3 +65,5 @@
var/static/list/can_ride_typecache = typecacheof(list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot))
var/lastpuke = 0
var/last_fire_update
+
+ can_be_held = "micro"
diff --git a/code/modules/mob/living/carbon/human/species_types/corporate.dm b/code/modules/mob/living/carbon/human/species_types/corporate.dm
index 620f0b25..146090b3 100644
--- a/code/modules/mob/living/carbon/human/species_types/corporate.dm
+++ b/code/modules/mob/living/carbon/human/species_types/corporate.dm
@@ -16,5 +16,5 @@
blacklisted = 1
use_skintones = 0
species_traits = list(NOBLOOD,EYECOLOR,NOGENITALS)
- inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER)
+ inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER)
sexes = 0
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
index 0345fe82..b59869e1 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -12,9 +12,9 @@
mutantliver = /obj/item/organ/liver/plasmaman
mutantstomach = /obj/item/organ/stomach/plasmaman
burnmod = 1.5
+ brutemod = 1.5
heatmod = 1.5
breathid = "tox"
- speedmod = 1
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
var/internal_fire = FALSE //If the bones themselves are burning clothes won't help you much
disliked_food = FRUIT
diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
index dcb875e1..6c9d95e8 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -3,7 +3,7 @@
name = "Spooky Scary Skeleton"
id = "skeleton"
say_mod = "rattles"
- blacklisted = 1
+ blacklisted = 0
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL)
@@ -12,13 +12,18 @@
mutanttongue = /obj/item/organ/tongue/bone
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
disliked_food = NONE
- liked_food = GROSS | MEAT | RAW
+ liked_food = GROSS | MEAT | RAW | DAIRY
/datum/species/skeleton/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
return TRUE
return ..()
-/datum/species/skeleton/pirate
- name = "Space Queen's Skeleton"
+/datum/species/skeleton/space
+ name = "Spooky Spacey Skeleton"
+ id = "spaceskeleton"
+ blacklisted = 1
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER)
+
+/datum/species/skeleton/pirate/check_roundstart_eligible()
+ return FALSE
diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm
index 378b97db..915e85f1 100644
--- a/code/modules/mob/living/carbon/human/species_types/synths.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synths.dm
@@ -12,7 +12,7 @@
damage_overlay_type = "synth"
limbs_id = "synth"
var/list/initial_species_traits = list(NOTRANSSTING) //for getting these values back for assume_disguise()
- var/list/initial_inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER,TRAIT_NOBREATH)
+ var/list/initial_inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER,TRAIT_NOLIMBDISABLE,TRAIT_NOBREATH)
var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off
var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged
diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm
index 61454150..9263aea9 100644
--- a/code/modules/mob/living/carbon/human/species_types/zombies.dm
+++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm
@@ -16,7 +16,12 @@
disliked_food = NONE
liked_food = GROSS | MEAT | RAW
-/datum/species/zombie/check_roundstart_eligible()
+/datum/species/zombie/notspaceproof
+ id = "notspaceproofzombie"
+ blacklisted = 0
+ inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH)
+
+/datum/species/zombie/notspaceproof/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
return TRUE
return ..()
@@ -47,7 +52,7 @@
/datum/species/zombie/infectious/spec_life(mob/living/carbon/C)
. = ..()
C.a_intent = INTENT_HARM // THE SUFFERING MUST FLOW
-
+
//Zombies never actually die, they just fall down until they regenerate enough to rise back up.
//They must be restrained, beheaded or gibbed to stop being a threat.
if(regen_cooldown < world.time)
@@ -58,7 +63,7 @@
C.adjustToxLoss(-heal_amt)
if(!C.InCritical() && prob(4))
playsound(C, pick(spooks), 50, TRUE, 10)
-
+
//Congrats you somehow died so hard you stopped being a zombie
/datum/species/zombie/infectious/spec_death(mob/living/carbon/C)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 72ff7e7a..3df86ce4 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -123,15 +123,16 @@ There are several things that need to be remembered:
if(U.adjusted == ALT_STYLE)
t_color = "[t_color]_d"
- if(U.mutantrace_variation)
- if(U.suit_style == DIGITIGRADE_SUIT_STYLE)
- U.alternate_worn_icon = 'modular_citadel/icons/mob/uniform_digi.dmi'
- if(U.adjusted == ALT_STYLE)
- t_color = "[t_color]_d_l"
- else if(U.adjusted == NORMAL_STYLE)
- t_color = "[t_color]_l"
- else
- U.alternate_worn_icon = null
+ if(!U.force_alternate_icon)
+ if(U.mutantrace_variation)
+ if(U.suit_style == DIGITIGRADE_SUIT_STYLE)
+ U.alternate_worn_icon = 'modular_citadel/icons/mob/uniform_digi.dmi'
+ if(U.adjusted == ALT_STYLE)
+ t_color = "[t_color]_d_l"
+ else if(U.adjusted == NORMAL_STYLE)
+ t_color = "[t_color]_l"
+ else
+ U.alternate_worn_icon = null
var/mutable_appearance/uniform_overlay
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 1c2234bb..801a6cd2 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -35,6 +35,7 @@
*/
if(stat == DEAD)
stop_sound_channel(CHANNEL_HEARTBEAT)
+ handle_death()
rot()
//Updates the number of stored chemicals for powers
@@ -43,6 +44,12 @@
if(stat != DEAD)
return 1
+//Procs called while dead
+/mob/living/carbon/proc/handle_death()
+ for(var/datum/reagent/R in reagents.reagent_list)
+ if(R.chemical_flags & REAGENT_DEAD_PROCESS)
+ R.on_mob_dead(src)
+
///////////////
// BREATHING //
///////////////
diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm
index 25bc243f..92ad87f6 100644
--- a/code/modules/mob/living/carbon/monkey/combat.dm
+++ b/code/modules/mob/living/carbon/monkey/combat.dm
@@ -132,6 +132,10 @@
pickupTarget = null
pickupTimer = 0
else if(ismob(pickupTarget.loc)) // in someones hand
+ if(istype(pickupTarget, /obj/item/clothing/head/mob_holder/))
+ var/obj/item/clothing/head/mob_holder/h = pickupTarget
+ if(h && h.held_mob==src)
+ return//dont let them pickpocket themselves
var/mob/M = pickupTarget.loc
if(!pickpocketing)
pickpocketing = TRUE
diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm
index 0796b713..f8d05ec1 100644
--- a/code/modules/mob/living/carbon/monkey/monkey.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey.dm
@@ -1,171 +1,188 @@
-/mob/living/carbon/monkey
- name = "monkey"
- verb_say = "chimpers"
- initial_language_holder = /datum/language_holder/monkey
- icon = 'icons/mob/monkey.dmi'
- icon_state = ""
- gender = NEUTER
- pass_flags = PASSTABLE
- ventcrawler = VENTCRAWLER_NUDE
- mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID)
- butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
- type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab/monkey
- gib_type = /obj/effect/decal/cleanable/blood/gibs
- unique_name = TRUE
- bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
- /obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
- hud_type = /datum/hud/monkey
-
-/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
- verbs += /mob/living/proc/mob_sleep
- verbs += /mob/living/proc/lay_down
-
- if(unique_name) //used to exclude pun pun
- gender = pick(MALE, FEMALE)
- real_name = name
-
- //initialize limbs
- create_bodyparts()
- create_internal_organs()
-
- . = ..()
-
- if (cubespawned)
- var/cap = CONFIG_GET(number/monkeycap)
- if (LAZYLEN(SSmobs.cubemonkeys) > cap)
- if (spawner)
- to_chat(spawner, "Bluespace harmonics prevent the spawning of more than [cap] monkeys on the station at one time!")
- return INITIALIZE_HINT_QDEL
- SSmobs.cubemonkeys += src
-
- create_dna(src)
- dna.initialize_dna(random_blood_type())
-
-/mob/living/carbon/monkey/Destroy()
- SSmobs.cubemonkeys -= src
- return ..()
-
-/mob/living/carbon/monkey/create_internal_organs()
- internal_organs += new /obj/item/organ/appendix
- internal_organs += new /obj/item/organ/lungs
- internal_organs += new /obj/item/organ/heart
- internal_organs += new /obj/item/organ/brain
- internal_organs += new /obj/item/organ/tongue
- internal_organs += new /obj/item/organ/eyes
- internal_organs += new /obj/item/organ/ears
- internal_organs += new /obj/item/organ/liver
- internal_organs += new /obj/item/organ/stomach
- ..()
-
-/mob/living/carbon/monkey/on_reagent_change()
- . = ..()
- remove_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE)
- var/amount
- if(reagents.has_reagent("morphine"))
- amount = -1
- if(reagents.has_reagent("nuka_cola"))
- amount = -1
- if(amount)
- add_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
-
-/mob/living/carbon/monkey/updatehealth()
- . = ..()
- var/slow = 0
- var/health_deficiency = (100 - health)
- if(health_deficiency >= 45)
- slow += (health_deficiency / 25)
- add_movespeed_modifier(MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = slow)
-
-/mob/living/carbon/monkey/adjust_bodytemperature(amount)
- . = ..()
- var/slow = 0
- if (bodytemperature < 283.222)
- slow += (283.222 - bodytemperature) / 10 * 1.75
- if(slow <= 0)
- return
- add_movespeed_modifier(MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
-
-/mob/living/carbon/monkey/Stat()
- ..()
- if(statpanel("Status"))
- stat(null, "Intent: [a_intent]")
- stat(null, "Move Mode: [m_intent]")
- if(client && mind)
- var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
- if(changeling)
- stat("Chemical Storage", "[changeling.chem_charges]/[changeling.chem_storage]")
- stat("Absorbed DNA", changeling.absorbedcount)
- return
-
-
-/mob/living/carbon/monkey/verb/removeinternal()
- set name = "Remove Internals"
- set category = "IC"
- internal = null
- return
-
-
-/mob/living/carbon/monkey/IsAdvancedToolUser()//Unless its monkey mode monkeys cant use advanced tools
- if(mind && is_monkey(mind))
- return TRUE
- return FALSE
-
-/mob/living/carbon/monkey/reagent_check(datum/reagent/R) //can metabolize all reagents
- return FALSE
-
-/mob/living/carbon/monkey/canBeHandcuffed()
- return TRUE
-
-/mob/living/carbon/monkey/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
- if(judgement_criteria & JUDGE_EMAGGED)
- return 10 //Everyone is a criminal!
-
- var/threatcount = 0
-
- //Securitrons can't identify monkeys
- if( !(judgement_criteria & JUDGE_IGNOREMONKEYS) && (judgement_criteria & JUDGE_IDCHECK) )
- threatcount += 4
-
- //Lasertag bullshit
- if(lasercolor)
- if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
- if(is_holding_item_of_type(/obj/item/gun/energy/laser/redtag))
- threatcount += 4
-
- if(lasercolor == "r")
- if(is_holding_item_of_type(/obj/item/gun/energy/laser/bluetag))
- threatcount += 4
-
- return threatcount
-
- //Check for weapons
- if( (judgement_criteria & JUDGE_WEAPONCHECK) && weaponcheck )
- for(var/obj/item/I in held_items) //if they're holding a gun
- if(weaponcheck.Invoke(I))
- threatcount += 4
- if(weaponcheck.Invoke(back)) //if a weapon is present in the back slot
- threatcount += 4 //trigger look_for_perp() since they're nonhuman and very likely hostile
-
- //mindshield implants imply trustworthyness
- if(HAS_TRAIT(src, TRAIT_MINDSHIELD))
- threatcount -= 1
-
- return threatcount
-
-/mob/living/carbon/monkey/IsVocal()
- if(!getorganslot(ORGAN_SLOT_LUNGS))
- return 0
- return 1
-
-/mob/living/carbon/monkey/can_use_guns(obj/item/G)
- return TRUE
-
-/mob/living/carbon/monkey/angry
- aggressive = TRUE
-
-/mob/living/carbon/monkey/angry/Initialize()
- . = ..()
- if(prob(10))
- var/obj/item/clothing/head/helmet/justice/escape/helmet = new(src)
- equip_to_slot_or_del(helmet,SLOT_HEAD)
- helmet.attack_self(src) // todo encapsulate toggle
+/mob/living/carbon/monkey
+ name = "monkey"
+ verb_say = "chimpers"
+ initial_language_holder = /datum/language_holder/monkey
+ icon = 'icons/mob/monkey.dmi'
+ icon_state = ""
+ gender = NEUTER
+ pass_flags = PASSTABLE
+ ventcrawler = VENTCRAWLER_NUDE
+ mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID)
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
+ type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab/monkey
+ gib_type = /obj/effect/decal/cleanable/blood/gibs
+ unique_name = TRUE
+ bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
+ /obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
+ hud_type = /datum/hud/monkey
+ can_be_held = "monkey"
+
+/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
+ verbs += /mob/living/proc/mob_sleep
+ verbs += /mob/living/proc/lay_down
+
+ if(unique_name) //used to exclude pun pun
+ gender = pick(MALE, FEMALE)
+ real_name = name
+
+ //initialize limbs
+ create_bodyparts()
+ create_internal_organs()
+
+ . = ..()
+
+ if (cubespawned)
+ var/cap = CONFIG_GET(number/monkeycap)
+ if (LAZYLEN(SSmobs.cubemonkeys) > cap)
+ if (spawner)
+ to_chat(spawner, "Bluespace harmonics prevent the spawning of more than [cap] monkeys on the station at one time!")
+ return INITIALIZE_HINT_QDEL
+ SSmobs.cubemonkeys += src
+
+ create_dna(src)
+ dna.initialize_dna(random_blood_type())
+
+/mob/living/carbon/monkey/Destroy()
+ SSmobs.cubemonkeys -= src
+ return ..()
+
+/mob/living/carbon/monkey/generate_mob_holder()
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "monkey", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
+ return holder
+
+/mob/living/carbon/monkey/create_internal_organs()
+ internal_organs += new /obj/item/organ/appendix
+ internal_organs += new /obj/item/organ/lungs
+ internal_organs += new /obj/item/organ/heart
+ internal_organs += new /obj/item/organ/brain
+ internal_organs += new /obj/item/organ/tongue
+ internal_organs += new /obj/item/organ/eyes
+ internal_organs += new /obj/item/organ/ears
+ internal_organs += new /obj/item/organ/liver
+ internal_organs += new /obj/item/organ/stomach
+ ..()
+
+/mob/living/carbon/monkey/on_reagent_change()
+ . = ..()
+ remove_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE)
+ var/amount
+ if(reagents.has_reagent("morphine"))
+ amount = -1
+ if(reagents.has_reagent("nuka_cola"))
+ amount = -1
+ if(amount)
+ add_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
+
+/mob/living/carbon/monkey/updatehealth()
+ . = ..()
+ var/slow = 0
+ var/health_deficiency = (100 - health)
+ if(health_deficiency >= 45)
+ slow += (health_deficiency / 25)
+ add_movespeed_modifier(MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = slow)
+
+/mob/living/carbon/monkey/adjust_bodytemperature(amount)
+ . = ..()
+ var/slow = 0
+ if (bodytemperature < 283.222)
+ slow += (283.222 - bodytemperature) / 10 * 1.75
+ if(slow <= 0)
+ return
+ add_movespeed_modifier(MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
+
+/mob/living/carbon/monkey/Stat()
+ ..()
+ if(statpanel("Status"))
+ stat(null, "Intent: [a_intent]")
+ stat(null, "Move Mode: [m_intent]")
+ if(client && mind)
+ var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
+ if(changeling)
+ stat("Chemical Storage", "[changeling.chem_charges]/[changeling.chem_storage]")
+ stat("Absorbed DNA", changeling.absorbedcount)
+ return
+
+
+/mob/living/carbon/monkey/verb/removeinternal()
+ set name = "Remove Internals"
+ set category = "IC"
+ internal = null
+ return
+
+
+/mob/living/carbon/monkey/IsAdvancedToolUser()//Unless its monkey mode monkeys cant use advanced tools
+ if(mind && is_monkey(mind))
+ return TRUE
+ return FALSE
+
+/mob/living/carbon/monkey/reagent_check(datum/reagent/R) //can metabolize all reagents
+ return FALSE
+
+/mob/living/carbon/monkey/canBeHandcuffed()
+ return TRUE
+
+/mob/living/carbon/monkey/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
+ if(judgement_criteria & JUDGE_EMAGGED)
+ return 10 //Everyone is a criminal!
+
+ var/threatcount = 0
+
+ //Securitrons can't identify monkeys
+ if( !(judgement_criteria & JUDGE_IGNOREMONKEYS) && (judgement_criteria & JUDGE_IDCHECK) )
+ threatcount += 4
+
+ //Lasertag bullshit
+ if(lasercolor)
+ if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
+ if(is_holding_item_of_type(/obj/item/gun/energy/laser/redtag))
+ threatcount += 4
+
+ if(lasercolor == "r")
+ if(is_holding_item_of_type(/obj/item/gun/energy/laser/bluetag))
+ threatcount += 4
+
+ return threatcount
+
+ //Check for weapons
+ if( (judgement_criteria & JUDGE_WEAPONCHECK) && weaponcheck )
+ for(var/obj/item/I in held_items) //if they're holding a gun
+ if(weaponcheck.Invoke(I))
+ threatcount += 4
+ if(weaponcheck.Invoke(back)) //if a weapon is present in the back slot
+ threatcount += 4 //trigger look_for_perp() since they're nonhuman and very likely hostile
+
+ //mindshield implants imply trustworthyness
+ if(HAS_TRAIT(src, TRAIT_MINDSHIELD))
+ threatcount -= 1
+
+ return threatcount
+
+/mob/living/carbon/monkey/IsVocal()
+ if(!getorganslot(ORGAN_SLOT_LUNGS))
+ return 0
+ return 1
+
+/mob/living/carbon/monkey/can_use_guns(obj/item/G)
+ return TRUE
+
+/mob/living/carbon/monkey/angry
+ aggressive = TRUE
+
+/mob/living/carbon/monkey/angry/Initialize()
+ . = ..()
+ if(prob(10))
+ var/obj/item/clothing/head/helmet/justice/escape/helmet = new(src)
+ equip_to_slot_or_del(helmet,SLOT_HEAD)
+ helmet.attack_self(src) // todo encapsulate toggle
+
+/mob/living/carbon/monkey/tumor
+ name = "living teratoma"
+ verb_say = "blabbers"
+ initial_language_holder = /datum/language_holder/monkey
+ icon = 'icons/mob/monkey.dmi'
+ icon_state = ""
+ butcher_results = list(/obj/effect/spawner/lootdrop/teratoma/minor = 5, /obj/effect/spawner/lootdrop/teratoma/major = 1)
+ type_of_meat = /obj/effect/spawner/lootdrop/teratoma/minor
+ aggressive = TRUE
+ bodyparts = list(/obj/item/bodypart/chest/monkey/teratoma, /obj/item/bodypart/head/monkey/teratoma, /obj/item/bodypart/l_arm/monkey/teratoma,
+ /obj/item/bodypart/r_arm/monkey/teratoma, /obj/item/bodypart/r_leg/monkey/teratoma, /obj/item/bodypart/l_leg/monkey/teratoma)
diff --git a/code/modules/mob/living/carbon/monkey/update_icons.dm b/code/modules/mob/living/carbon/monkey/update_icons.dm
index ff83b00f..8c3e905b 100644
--- a/code/modules/mob/living/carbon/monkey/update_icons.dm
+++ b/code/modules/mob/living/carbon/monkey/update_icons.dm
@@ -1,4 +1,3 @@
-
/mob/living/carbon/monkey/regenerate_icons()
if(!..())
update_body_parts()
@@ -77,4 +76,4 @@
/mob/living/carbon/monkey/update_hud_back(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
I.screen_loc = ui_monkey_back
- client.screen += I
\ No newline at end of file
+ client.screen += I
diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm
index aec1c86b..03df1cab 100644
--- a/code/modules/mob/living/carbon/update_icons.dm
+++ b/code/modules/mob/living/carbon/update_icons.dm
@@ -10,10 +10,29 @@
ntransform.TurnTo(lying_prev,lying)
if(lying == 0) //Lying to standing
final_pixel_y = get_standard_pixel_y_offset()
+ if(size_multiplier >= 1) //if its bigger than normal
+ ntransform.Translate(0,16 * (size_multiplier-1))
+ else
+ if(lying_prev == 90)
+ ntransform.Translate(16 * (size_multiplier-1),16 * (size_multiplier-1))
+
+ if(lying_prev == 270)
+ ntransform.Translate(-16 * (size_multiplier-1),16 * (size_multiplier-1))
+
else //if(lying != 0)
if(lying_prev == 0) //Standing to lying
pixel_y = get_standard_pixel_y_offset()
final_pixel_y = get_standard_pixel_y_offset(lying)
+ if(lying == 90) //Check the angle of the sprite to offset it accordingly.
+ ntransform.Translate(-16 * (size_multiplier-1),0)
+ if(size_multiplier < 1) //if its smaller than normal
+ ntransform.Translate(0,16 * (size_multiplier-1)) //we additionally offset the sprite downwards
+
+ if(lying == 270) //check the angle of the sprite to offset it accordingly
+ ntransform.Translate(16 * (size_multiplier-1),0)
+ if(size_multiplier < 1) //if its smaller than normal
+ ntransform.Translate(0,16 * (size_multiplier-1)) //we additionally offset the sprite downwards
+
if(dir & (EAST|WEST)) //Facing east or west
final_dir = pick(NORTH, SOUTH) //So you fall on your side rather than your face or ass
@@ -22,11 +41,40 @@
ntransform.Scale(resize)
resize = RESIZE_DEFAULT_SIZE
+ //Apply size multiplier, thank NeverExisted for this
+ if(size_multiplier != previous_size)
+ changed++
+ //now we offset the sprite
+ //Scaling affects offset. There's probably a smarter and easier way to do this, but this way it works for sure (?)
+ //Just to be clear. All this bullshit is needed because someone wanted to store the old transform matrix instead of using a new one each iteration
+ //Winfre is currently doing a great job at coating my nuts in slobber while i code this
+ if(!lying) //when standing. People of all sizes are affected equally
+ ntransform.Translate(0,-16 * (previous_size-1)) //reset the sprite
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly.
+ ntransform.Translate(0,16 * (size_multiplier-1)) //apply the new offset
+ else //when lying. Macros dont get an offset, Micros do. We must also check the cases when a micro becomes a macro and viceversa
+ if(previous_size <= 1 && size_multiplier <= 1) //micro stays a micro. We modify the side-offset
+ ntransform.Translate(0,-16 * (previous_size-1)) //reset the sprite
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly
+ ntransform.Translate(0,16 * (size_multiplier-1)) //apply the new offset
+
+ if(previous_size <= 1 && size_multiplier > 1) //micro becomes a macro. We remove the side-offset
+ ntransform.Translate(0,-16 * (previous_size-1)) //reset the sprite
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly
+
+ if(previous_size > 1 && size_multiplier <= 1) //macro becomes a micro. We add an offset
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly.
+ ntransform.Translate(0,16 * (size_multiplier-1)) //apply the new offset
+
+ if(previous_size > 1 && size_multiplier > 1) //macro stays a macro. We just scale the sprite with no offset changes
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly
+
+ previous_size = size_multiplier
+
if(changed)
animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, dir = final_dir, easing = EASE_IN|EASE_OUT)
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life().
-
/mob/living/carbon
var/list/overlays_standing[TOTAL_LAYERS]
diff --git a/code/modules/mob/living/inhand_holder.dm b/code/modules/mob/living/inhand_holder.dm
index b82e8cc4..e68260de 100644
--- a/code/modules/mob/living/inhand_holder.dm
+++ b/code/modules/mob/living/inhand_holder.dm
@@ -5,80 +5,125 @@
desc = "Yell at coderbrush."
icon = null
icon_state = ""
- item_flags = DROPDEL
var/mob/living/held_mob
- var/can_head = TRUE
- var/destroying = FALSE
+ var/can_head = FALSE
+ w_class = WEIGHT_CLASS_BULKY
-/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/M, _worn_state, head_icon, lh_icon, rh_icon, _can_head = TRUE)
+/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/M, _worn_state, alt_worn, lh_icon, rh_icon, _can_head_override = FALSE)
. = ..()
- can_head = _can_head
- if(head_icon)
- alternate_worn_icon = head_icon
+
+ if(M)
+ M.setDir(SOUTH)
+ held_mob = M
+ M.forceMove(src)
+ appearance = M.appearance
+ name = M.name
+ desc = M.desc
+
+ if(_can_head_override)
+ can_head = _can_head_override
+ if(alt_worn)
+ alternate_worn_icon = alt_worn
if(_worn_state)
item_state = _worn_state
+ icon_state = _worn_state
if(lh_icon)
lefthand_file = lh_icon
if(rh_icon)
righthand_file = rh_icon
if(!can_head)
slot_flags = NONE
- deposit(M)
/obj/item/clothing/head/mob_holder/Destroy()
- destroying = TRUE
if(held_mob)
- release(FALSE)
+ release()
return ..()
-/obj/item/clothing/head/mob_holder/proc/deposit(mob/living/L)
- if(!istype(L))
- return FALSE
- L.setDir(SOUTH)
- update_visuals(L)
- held_mob = L
- L.forceMove(src)
- name = L.name
- desc = L.desc
- return TRUE
+/obj/item/clothing/head/mob_holder/dropped()
+ ..()
+ if(isturf(loc))//don't release on soft-drops
+ release()
-/obj/item/clothing/head/mob_holder/proc/update_visuals(mob/living/L)
- appearance = L.appearance
-
-/obj/item/clothing/head/mob_holder/proc/release(del_on_release = TRUE)
- if(!held_mob)
- if(del_on_release && !destroying)
- qdel(src)
- return FALSE
+/obj/item/clothing/head/mob_holder/proc/release()
if(isliving(loc))
var/mob/living/L = loc
- to_chat(L, "[held_mob] wriggles free!")
L.dropItemToGround(src)
- held_mob.forceMove(get_turf(held_mob))
- held_mob.reset_perspective()
- held_mob.setDir(SOUTH)
- held_mob.visible_message("[held_mob] uncurls!")
- held_mob = null
- if(del_on_release && !destroying)
- qdel(src)
- return TRUE
+ if(held_mob)
+ var/mob/living/m = held_mob
+ m.forceMove(get_turf(m))
+ m.reset_perspective()
+ m.setDir(SOUTH)
+ held_mob = null
+ qdel(src)
/obj/item/clothing/head/mob_holder/relaymove(mob/user)
- release()
+ return
/obj/item/clothing/head/mob_holder/container_resist()
+ if(isliving(loc))
+ var/mob/living/L = loc
+ visible_message("[src] escapes [L]!")
release()
-/obj/item/clothing/head/mob_holder/drone/deposit(mob/living/L)
- . = ..()
- if(!isdrone(L))
- qdel(src)
- name = "drone (hiding)"
- desc = "This drone is scared and has curled up into a ball!"
+/mob/living/proc/mob_pickup(mob/living/L)
+ var/obj/item/clothing/head/mob_holder/holder = generate_mob_holder()
+ if(!holder)
+ return
+ drop_all_held_items()
+ L.put_in_hands(holder)
+ return
-/obj/item/clothing/head/mob_holder/drone/update_visuals(mob/living/L)
- var/mob/living/simple_animal/drone/D = L
- if(!D)
- return ..()
- icon = 'icons/mob/drone.dmi'
- icon_state = "[D.visualAppearence]_hat"
+/mob/living/proc/mob_try_pickup(mob/living/user)
+ if(!ishuman(user) || !src.Adjacent(user) || user.incapacitated() || !can_be_held)
+ return FALSE
+ if(src.can_be_held == "micro")
+ return FALSE
+ if(user.get_active_held_item())
+ to_chat(user, "Your hands are full!")
+ return FALSE
+ if(buckled)
+ to_chat(user, "[src] is buckled to something!")
+ return FALSE
+ if(src == user)
+ to_chat(user, "You can't pick yourself up.")
+ return FALSE
+ visible_message("[user] starts picking up [src].", \
+ "[user] starts picking you up!")
+ if(!do_after(user, 20, target = src))
+ return FALSE
+
+ if(user.get_active_held_item()||buckled)
+ return FALSE
+
+ visible_message("[user] picks up [src]!", \
+ "[user] picks you up!")
+ to_chat(user, "You pick [src] up.")
+ mob_pickup(user)
+ return TRUE
+
+/mob/living/AltClick(mob/user)
+ . = ..()
+ if(mob_try_pickup(user))
+ return TRUE
+
+/obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env)
+ var/atom/location = loc
+ if(!loc)
+ return //null
+ var/turf/T = get_turf(loc)
+ while(location != T)
+ location = location.loc
+ if(ismob(location))
+ return location.loc.assume_air(env)
+ return location.assume_air(env)
+
+/obj/item/clothing/head/mob_holder/remove_air(amount)
+ var/atom/location = loc
+ if(!loc)
+ return //null
+ var/turf/T = get_turf(loc)
+ while(location != T)
+ location = location.loc
+ if(ismob(location))
+ return location.loc.remove_air(amount)
+ return location.remove_air(amount)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 5be545a0..d1c3492a 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -40,6 +40,15 @@
QDEL_LIST(diseases)
return ..()
+
+/mob/living/proc/generate_mob_holder()
+ if(ishuman(src))
+ var/obj/item/clothing/head/mob_holder/micro/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
+ return holder
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
+ return holder
+
+
/mob/living/proc/OpenCraftingMenu()
return
@@ -136,6 +145,11 @@
else if((M.restrained() || M.a_intent == INTENT_HELP) && (restrained() || a_intent == INTENT_HELP))
mob_swap = 1
if(mob_swap)
+
+ //handle micro bumping on help intent
+ if(handle_micro_bump_helping(M))
+ return 1
+
//switch our position with M
if(loc && !loc.Adjacent(M.loc))
return 1
@@ -168,6 +182,11 @@
//not if he's not CANPUSH of course
if(!(M.status_flags & CANPUSH))
return 1
+
+ //handle micro bumping on other intents
+ if(handle_micro_bump_other(M))
+ return 1
+
if(isliving(M))
var/mob/living/L = M
if(HAS_TRAIT(L, TRAIT_PUSHIMMUNE))
@@ -1128,23 +1147,6 @@
if(can_be_held)
mob_try_pickup(over)
-/mob/living/proc/mob_pickup(mob/living/L)
- return
-
-/mob/living/proc/mob_try_pickup(mob/living/user)
- if(!ishuman(user))
- return
- if(user.get_active_held_item())
- to_chat(user, "Your hands are full!")
- return FALSE
- if(buckled)
- to_chat(user, "[src] is buckled to something!")
- return FALSE
- user.visible_message("[user] starts trying to scoop up [src]!")
- if(!do_after(user, 20, target = src))
- return FALSE
- mob_pickup(user)
- return TRUE
/mob/living/proc/get_static_viruses() //used when creating blood and other infective objects
if(!LAZYLEN(diseases))
@@ -1240,3 +1242,8 @@
update_canmove()
for(var/chem in healing_chems)
reagents.add_reagent(chem, healing_chems[chem])
+
+//retard edits below
+/mob/living
+ var/size_multiplier = 1 //multiplier for the mob's icon size atm
+ var/previous_size = 1
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index b6e2c16a..3ae1e305 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -108,7 +108,7 @@
var/list/obj/effect/proc_holder/abilities = list()
- var/can_be_held = FALSE //whether this can be picked up and held.
+ var/can_be_held = FALSE
var/radiation = 0 //If the mob is irradiated.
var/ventcrawl_layer = PIPING_LAYER_DEFAULT
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index a3256412..c608e584 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -86,7 +86,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
var/talk_key = get_key(message)
- var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)
+ var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE, MODE_SING = TRUE)
if(sanitize)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
@@ -190,6 +190,15 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/datum/language/L = GLOB.language_datum_instances[language]
spans |= L.spans
+ if(message_mode == MODE_SING)
+ #if DM_VERSION < 513
+ var/randomnote = "~"
+ #else
+ var/randomnote = pick("\u2669", "\u266A", "\u266B")
+ #endif
+ spans |= SPAN_SINGING
+ message = "[randomnote] [message] [randomnote]"
+
var/radio_return = radio(message, message_mode, spans, language)
if(radio_return & ITALICS)
spans |= SPAN_ITALICS
@@ -229,6 +238,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
else
deaf_message = "You can't hear yourself!"
deaf_type = 2 // Since you should be able to hear yourself without looking
+ // Create map text prior to modifying message for goonchat
+ if (client?.prefs.chat_on_map && stat != UNCONSCIOUS && (client.prefs.see_chat_non_mob || ismob(speaker)) && can_hear())
+ create_chat_message(speaker, message_language, raw_message, spans, message_mode)
// Recompose message for AI hrefs, language incomprehension.
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
@@ -286,7 +298,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
//speech bubble
var/list/speech_bubble_recipients = list()
for(var/mob/M in listening)
- if(M.client)
+ if(M.client && !M.client.prefs.chat_on_map)
speech_bubble_recipients.Add(M.client)
var/image/I = image('icons/mob/talk.dmi', src, "[bubble_type][say_test(message)]", FLY_LAYER)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
@@ -399,6 +411,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
. = "stammers"
else if(derpspeech)
. = "gibbers"
+ else if(message_mode == MODE_SING)
+ . = verb_sing
else
. = ..()
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index e86315eb..7f12e037 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -808,7 +808,7 @@
return get_dist(src, A) <= max(viewscale[1]*0.5,viewscale[2]*0.5)
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
- raw_message = lang_treat(speaker, message_language, raw_message, spans, message_mode)
+ var/treated_message = lang_treat(speaker, message_language, raw_message, spans, message_mode)
var/start = "Relayed Speech: "
var/namepart = "[speaker.GetVoice()][speaker.get_alt_name()]"
var/hrefpart = ""
@@ -821,9 +821,11 @@
else
jobpart = "Unknown"
- var/rendered = "[start][hrefpart][namepart] ([jobpart])[raw_message]"
+ var/rendered = "[start][hrefpart][namepart] ([jobpart]) [treated_message]"
+ if (client?.prefs.chat_on_map && (client.prefs.see_chat_non_mob || ismob(speaker)))
+ create_chat_message(speaker, message_language, raw_message, spans, message_mode)
- show_message(rendered, 2)
+ show_message(rendered, 2)
/mob/living/silicon/ai/fully_replace_character_name(oldname,newname)
..()
diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
index bd53e824..9e72c22a 100644
--- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
@@ -282,6 +282,9 @@
/obj/effect/decal/cleanable/greenglow,
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/insectguts,
+ /obj/effect/decal/cleanable/semen,
+ /obj/effect/decal/cleanable/milk,
+ /obj/effect/decal/cleanable/femcum,
/obj/effect/decal/remains
)
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index 7df851ec..4c47a606 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -31,6 +31,8 @@
var/mob/living/simple_animal/mouse/movement_target
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "cat"
+ can_be_held = "cat2"
+ size_multiplier = 0.5
do_footstep = TRUE
@@ -80,6 +82,7 @@
pass_flags = PASSMOB
mob_size = MOB_SIZE_SMALL
collar_type = "kitten"
+ can_be_held = "cat"
//RUNTIME IS ALIVE! SQUEEEEEEEE~
/mob/living/simple_animal/pet/cat/Runtime
@@ -262,6 +265,7 @@
attacked_sound = 'sound/items/eatfood.ogg'
deathmessage = "loses its false life and collapses!"
death_sound = "bodyfall"
+ can_be_held = "cak"
/mob/living/simple_animal/pet/cat/cak/CheckParts(list/parts)
..()
diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm
index c194233c..00f9350d 100644
--- a/code/modules/mob/living/simple_animal/friendly/dog.dm
+++ b/code/modules/mob/living/simple_animal/friendly/dog.dm
@@ -13,8 +13,10 @@
see_in_dark = 5
speak_chance = 1
turns_per_move = 10
+ size_multiplier = 0.5
do_footstep = TRUE
+ can_be_held = TRUE
//Corgis and pugs are now under one dog subtype
@@ -35,6 +37,7 @@
var/obj/item/inventory_back
var/shaved = FALSE
var/nofur = FALSE //Corgis that have risen past the material plane of existence.
+ can_be_held = "corgi"
/mob/living/simple_animal/pet/dog/corgi/Destroy()
QDEL_NULL(inventory_head)
@@ -63,6 +66,7 @@
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/pug = 3)
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "pug"
+ can_be_held = "pug"
/mob/living/simple_animal/pet/dog/corgi/exoticcorgi
name = "Exotic Corgi"
@@ -360,6 +364,7 @@
icon_dead = "old_corgi_dead"
desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
turns_per_move = 20
+ can_be_held = "old_corgi"
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
@@ -582,6 +587,7 @@
unsuitable_atmos_damage = 0
minbodytemp = TCMB
maxbodytemp = T0C + 40
+ can_be_held = "void_puppy"
/mob/living/simple_animal/pet/dog/corgi/puppy/void/Process_Spacemove(movement_dir = 0)
return 1 //Void puppies can navigate space.
@@ -603,6 +609,7 @@
response_harm = "kicks"
var/turns_since_scan = 0
var/puppies = 0
+ can_be_held = "lisa"
//Lisa already has a cute bow!
/mob/living/simple_animal/pet/dog/corgi/Lisa/Topic(href, href_list)
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index 6d312147..f880adb7 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -274,3 +274,7 @@
/mob/living/simple_animal/drone/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
return 0 //So they don't die trying to fix wiring
+
+/mob/living/simple_animal/drone/generate_mob_holder()
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "[visualAppearence]_hat", null, null, null, TRUE)
+ return holder
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
index 33031fd8..e40eb585 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
@@ -29,28 +29,11 @@
if("Nothing")
return
-//ATTACK HAND IGNORING PARENT RETURN VALUE
+//picky up the drone c:
/mob/living/simple_animal/drone/attack_hand(mob/user)
- if(ishuman(user))
- if(stat == DEAD || status_flags & GODMODE || !can_be_held)
- ..()
- return
- if(user.get_active_held_item())
- to_chat(user, "Your hands are full!")
- return
- visible_message("[user] starts picking up [src].", \
- "[user] starts picking you up!")
- if(!do_after(user, 20, target = src))
- return
- visible_message("[user] picks up [src]!", \
- "[user] picks you up!")
- if(buckled)
- to_chat(user, "[src] is buckled to [buckled] and cannot be picked up!")
- return
- to_chat(user, "You pick [src] up.")
- drop_all_held_items()
- var/obj/item/clothing/head/mob_holder/drone/DH = new(get_turf(src), src)
- user.put_in_hands(DH)
+ ..()
+ if(user.a_intent == INTENT_HELP)
+ mob_try_pickup(user)
/mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user)
var/mob/dead/observer/G = get_ghost()
diff --git a/code/modules/mob/living/simple_animal/friendly/fox.dm b/code/modules/mob/living/simple_animal/friendly/fox.dm
index 28b66c26..3f58ca59 100644
--- a/code/modules/mob/living/simple_animal/friendly/fox.dm
+++ b/code/modules/mob/living/simple_animal/friendly/fox.dm
@@ -18,7 +18,7 @@
response_disarm = "gently pushes aside"
response_harm = "kicks"
gold_core_spawnable = FRIENDLY_SPAWN
-
+ can_be_held = "fox"
do_footstep = TRUE
//Captain fox
diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm
index e329dd3f..6076e412 100644
--- a/code/modules/mob/living/simple_animal/friendly/lizard.dm
+++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm
@@ -23,6 +23,8 @@
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
var/static/list/edibles = typecacheof(list(/mob/living/simple_animal/butterfly, /mob/living/simple_animal/cockroach)) //list of atoms, however turfs won't affect AI, but will affect consumption.
+ can_be_held = "lizard"
+ size_multiplier = 0.5
/mob/living/simple_animal/hostile/lizard/CanAttack(atom/the_target)//Can we actually attack a possible target?
if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
@@ -39,3 +41,7 @@
return TRUE
else
return ..()
+
+/mob/living/simple_animal/hostile/lizard/generate_mob_holder()
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "lizard", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
+ return holder
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index bf45c9cc..028bada0 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -25,6 +25,8 @@
var/body_color //brown, gray and white, leave blank for random
gold_core_spawnable = FRIENDLY_SPAWN
var/chew_probability = 1
+ can_be_held = TRUE
+ size_multiplier = 0.5
/mob/living/simple_animal/mouse/Initialize()
. = ..()
@@ -34,7 +36,7 @@
icon_state = "mouse_[body_color]"
icon_living = "mouse_[body_color]"
icon_dead = "mouse_[body_color]_dead"
-
+ can_be_held = "mouse_[body_color]"
/mob/living/simple_animal/mouse/proc/splat()
src.health = 0
@@ -87,14 +89,17 @@
/mob/living/simple_animal/mouse/white
body_color = "white"
icon_state = "mouse_white"
+ can_be_held = "mouse_white"
/mob/living/simple_animal/mouse/gray
body_color = "gray"
icon_state = "mouse_gray"
+ can_be_held = "mouse_gray"
/mob/living/simple_animal/mouse/brown
body_color = "brown"
icon_state = "mouse_brown"
+ can_be_held = "mouse_brown"
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_animal/mouse/brown/Tom
@@ -118,3 +123,8 @@
/obj/item/reagent_containers/food/snacks/deadmouse/on_grind()
reagents.clear_reagents()
+
+/mob/living/simple_animal/mouse/generate_mob_holder()
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
+ holder.w_class = WEIGHT_CLASS_TINY
+ return holder
diff --git a/code/modules/mob/living/simple_animal/friendly/sloth.dm b/code/modules/mob/living/simple_animal/friendly/sloth.dm
index 324fa107..fb114ace 100644
--- a/code/modules/mob/living/simple_animal/friendly/sloth.dm
+++ b/code/modules/mob/living/simple_animal/friendly/sloth.dm
@@ -22,7 +22,8 @@
maxHealth = 50
speed = 10
glide_size = 2
-
+ can_be_held = "sloth" //finally oranges can be held
+ size_multiplier = 0.5
do_footstep = TRUE
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index 73274dcf..5aec56b1 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -44,7 +44,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
var/reset = 0 //if the summoner has reset the guardian already
var/cooldown = 0
var/mob/living/carbon/summoner
- var/range = 10 //how far from the user the spirit can be
+ var/range = 13 //how far from the user the spirit can be
var/toggle_button_type = /obj/screen/guardian/ToggleMode/Inactive //what sort of toggle button the hud uses
var/datum/guardianname/namedatum = new/datum/guardianname()
var/playstyle_string = "You are a standard Guardian. You shouldn't exist!"
diff --git a/code/modules/mob/living/simple_animal/guardian/types/assassin.dm b/code/modules/mob/living/simple_animal/guardian/types/assassin.dm
index 45d8c17d..e507a4c8 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/assassin.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/assassin.dm
@@ -1,7 +1,5 @@
//Assassin
/mob/living/simple_animal/hostile/guardian/assassin
- melee_damage_lower = 15
- melee_damage_upper = 15
attacktext = "slashes"
attack_sound = 'sound/weapons/bladeslice.ogg'
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
@@ -12,7 +10,7 @@
toggle_button_type = /obj/screen/guardian/ToggleMode/Assassin
var/toggle = FALSE
- var/stealthcooldown = 160
+ var/stealthcooldown = 100
var/obj/screen/alert/canstealthalert
var/obj/screen/alert/instealthalert
diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm
index 7a4c454f..3ece5d4e 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm
@@ -1,13 +1,10 @@
//Charger
/mob/living/simple_animal/hostile/guardian/charger
- melee_damage_lower = 15
- melee_damage_upper = 15
ranged = 1 //technically
ranged_message = "charges"
- ranged_cooldown_time = 40
- speed = -1
- damage_coeff = list(BRUTE = 0.6, BURN = 0.6, TOX = 0.6, CLONE = 0.6, STAMINA = 0, OXY = 0.6)
- playstyle_string = "As a charger type you do medium damage, have medium damage resistance, move very fast, and can charge at a location, damaging any target hit and forcing them to drop any items they are holding."
+ ranged_cooldown_time = 20
+ damage_coeff = list(BRUTE = 0, BURN = 0.5, TOX = 0.5, CLONE = 0.5, STAMINA = 0, OXY = 0.5)
+ playstyle_string = "As a charger type you do medium damage, take half damage, immunity to brute damage, move very fast, and can charge at a location, damaging any target hit and forcing them to drop any items they are holding."
magic_fluff_string = "..And draw the Hunter, an alien master of rapid assault."
tech_fluff_string = "Boot sequence complete. Charge modules loaded. Holoparasite swarm online."
carp_fluff_string = "CARP CARP CARP! Caught one! It's a charger carp, that likes running at people. But it doesn't have any legs..."
diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
index e7dbbda2..a43d4b6d 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
@@ -3,7 +3,7 @@
melee_damage_lower = 10
melee_damage_upper = 10
damage_coeff = list(BRUTE = 0.75, BURN = 0.75, TOX = 0.75, CLONE = 0.75, STAMINA = 0, OXY = 0.75)
- playstyle_string = "As a dextrous type you can hold items, store an item within yourself, and have medium damage resistance, but do low damage on attacks. Recalling and leashing will force you to drop unstored items!"
+ playstyle_string = "As a dextrous type you can hold items, store an item within yourself, and take half damage, but do low damage on attacks. Recalling and leashing will force you to drop unstored items!"
magic_fluff_string = "..And draw the Drone, a dextrous master of construction and repair."
tech_fluff_string = "Boot sequence complete. Dextrous combat modules loaded. Holoparasite swarm online."
carp_fluff_string = "CARP CARP CARP! You caught one! It can hold stuff in its fins, sort of."
diff --git a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm
index ff2f4532..531c5138 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm
@@ -1,10 +1,7 @@
//Bomb
/mob/living/simple_animal/hostile/guardian/bomb
- melee_damage_lower = 15
- melee_damage_upper = 15
damage_coeff = list(BRUTE = 0.6, BURN = 0.6, TOX = 0.6, CLONE = 0.6, STAMINA = 0, OXY = 0.6)
- range = 13
- playstyle_string = "As an explosive type, you have moderate close combat abilities, may explosively teleport targets on attack, and are capable of converting nearby items and objects into disguised bombs via alt click."
+ playstyle_string = "As an explosive type, you have moderate close combat abilities, take half damage, may explosively teleport targets on attack, and are capable of converting nearby items and objects into disguised bombs via alt click."
magic_fluff_string = "..And draw the Scientist, master of explosive death."
tech_fluff_string = "Boot sequence complete. Explosive modules active. Holoparasite swarm online."
carp_fluff_string = "CARP CARP CARP! Caught one! It's an explosive carp! Boom goes the fishy."
diff --git a/code/modules/mob/living/simple_animal/guardian/types/fire.dm b/code/modules/mob/living/simple_animal/guardian/types/fire.dm
index 7a469dd1..b111caae 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/fire.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/fire.dm
@@ -1,13 +1,13 @@
//Fire
/mob/living/simple_animal/hostile/guardian/fire
a_intent = INTENT_HELP
- melee_damage_lower = 7
- melee_damage_upper = 7
+ melee_damage_lower = 10
+ melee_damage_upper = 10
attack_sound = 'sound/items/welder.ogg'
attacktext = "ignites"
- damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7)
- range = 7
- playstyle_string = "As a chaos type, you have only light damage resistance, but will ignite any enemy you bump into. In addition, your melee attacks will cause human targets to see everyone as you."
+ melee_damage_type = BURN
+ damage_coeff = list(BRUTE = 0.7, BURN = 0, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7)
+ playstyle_string = "As a chaos type, you take 30% damage reduction to all but burn, which you are immune to. You will ignite any enemy you bump into. in addition, your melee attacks will cause human targets to see everyone as you."
magic_fluff_string = "..And draw the Wizard, bringer of endless chaos!"
tech_fluff_string = "Boot sequence complete. Crowd control modules activated. Holoparasite swarm online."
carp_fluff_string = "CARP CARP CARP! You caught one! OH GOD, EVERYTHING'S ON FIRE. Except you and the fish."
@@ -38,6 +38,6 @@
/mob/living/simple_animal/hostile/guardian/fire/proc/collision_ignite(AM as mob|obj)
if(isliving(AM))
var/mob/living/M = AM
- if(!hasmatchingsummoner(M) && M != summoner && M.fire_stacks < 7)
- M.fire_stacks = 7
+ if(!hasmatchingsummoner(M) && M != summoner && M.fire_stacks < 10)
+ M.fire_stacks = 10
M.IgniteMob()
diff --git a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm b/code/modules/mob/living/simple_animal/guardian/types/lightning.dm
index ad1c4773..7b765182 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/lightning.dm
@@ -4,14 +4,13 @@
layer = LYING_MOB_LAYER
/mob/living/simple_animal/hostile/guardian/beam
- melee_damage_lower = 7
- melee_damage_upper = 7
+ melee_damage_lower = 10
+ melee_damage_upper = 10
attacktext = "shocks"
melee_damage_type = BURN
attack_sound = 'sound/machines/defib_zap.ogg'
damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7)
- range = 7
- playstyle_string = "As a lightning type, you will apply lightning chains to targets on attack and have a lightning chain to your summoner. Lightning chains will shock anyone near them."
+ playstyle_string = "As a lightning type, you have 30% damage reduction, apply lightning chains to targets on attack and have a lightning chain to your summoner. Lightning chains will shock anyone near them."
magic_fluff_string = "..And draw the Tesla, a shocking, lethal source of power."
tech_fluff_string = "Boot sequence complete. Lightning modules active. Holoparasite swarm online."
carp_fluff_string = "CARP CARP CARP! Caught one! It's a lightning carp! Everyone else goes zap zap."
@@ -31,7 +30,7 @@
var/datum/beam/C = pick(enemychains)
qdel(C)
enemychains -= C
- enemychains += Beam(target, "lightning[rand(1,12)]", time=70, maxdistance=7, beam_type=/obj/effect/ebeam/chain)
+ enemychains += Beam(target, "lightning[rand(1,12)]", time=70, maxdistance=13, beam_type=/obj/effect/ebeam/chain)
/mob/living/simple_animal/hostile/guardian/beam/Destroy()
removechains()
diff --git a/code/modules/mob/living/simple_animal/guardian/types/protector.dm b/code/modules/mob/living/simple_animal/guardian/types/protector.dm
index 14430bb2..53964254 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/protector.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/protector.dm
@@ -1,7 +1,5 @@
//Protector
/mob/living/simple_animal/hostile/guardian/protector
- melee_damage_lower = 15
- melee_damage_upper = 15
range = 15 //worse for it due to how it leashes
damage_coeff = list(BRUTE = 0.4, BURN = 0.4, TOX = 0.4, CLONE = 0.4, STAMINA = 0, OXY = 0.4)
playstyle_string = "As a protector type you cause your summoner to leash to you instead of you leashing to them and have two modes; Combat Mode, where you do and take medium damage, and Protection Mode, where you do and take almost no damage, but move slightly slower."
@@ -33,9 +31,9 @@
cooldown = world.time + 10
if(toggle)
cut_overlays()
- melee_damage_lower = initial(melee_damage_lower)
- melee_damage_upper = initial(melee_damage_upper)
- speed = initial(speed)
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ speed = 0
damage_coeff = list(BRUTE = 0.4, BURN = 0.4, TOX = 0.4, CLONE = 0.4, STAMINA = 0, OXY = 0.4)
to_chat(src, "You switch to combat mode.")
toggle = FALSE
@@ -44,8 +42,8 @@
if(namedatum)
shield_overlay.color = namedatum.colour
add_overlay(shield_overlay)
- melee_damage_lower = 2
- melee_damage_upper = 2
+ melee_damage_lower = 5
+ melee_damage_upper = 5
speed = 1
damage_coeff = list(BRUTE = 0.05, BURN = 0.05, TOX = 0.05, CLONE = 0.05, STAMINA = 0, OXY = 0.05) //damage? what's damage?
to_chat(src, "You switch to protection mode.")
diff --git a/code/modules/mob/living/simple_animal/guardian/types/ranged.dm b/code/modules/mob/living/simple_animal/guardian/types/ranged.dm
index 5adcc8b2..0e8f632d 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/ranged.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/ranged.dm
@@ -16,8 +16,7 @@
ranged_cooldown_time = 1 //fast!
projectilesound = 'sound/effects/hit_on_shattered_glass.ogg'
ranged = 1
- range = 13
- playstyle_string = "As a ranged type, you have only light damage resistance, but are capable of spraying shards of crystal at incredibly high speed. You can also deploy surveillance snares to monitor enemy movement. Finally, you can switch to scout mode, in which you can't attack, but can move without limit."
+ playstyle_string = "As a ranged type, you have 10% damage reduction, but are capable of spraying shards of crystal at incredibly high speed. You can also deploy surveillance snares to monitor enemy movement. Finally, you can switch to scout mode, in which you can't attack, but can move without limit."
magic_fluff_string = "..And draw the Sentinel, an alien master of ranged combat."
tech_fluff_string = "Boot sequence complete. Ranged combat modules active. Holoparasite swarm online."
carp_fluff_string = "CARP CARP CARP! Caught one, it's a ranged carp. This fishy can watch people pee in the ocean."
@@ -36,7 +35,7 @@
obj_damage = initial(obj_damage)
environment_smash = initial(environment_smash)
alpha = 255
- range = initial(range)
+ range = 13
to_chat(src, "You switch to combat mode.")
toggle = FALSE
else
diff --git a/code/modules/mob/living/simple_animal/guardian/types/standard.dm b/code/modules/mob/living/simple_animal/guardian/types/standard.dm
index 4edd9d9e..2285167d 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/standard.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/standard.dm
@@ -3,9 +3,9 @@
melee_damage_lower = 20
melee_damage_upper = 20
obj_damage = 80
- next_move_modifier = 0.8 //attacks 20% faster
+ next_move_modifier = 0.5 //attacks 50% faster
environment_smash = ENVIRONMENT_SMASH_WALLS
- playstyle_string = "As a standard type you have no special abilities, but have a high damage resistance and a powerful attack capable of smashing through walls."
+ playstyle_string = "As a standard type you have no special abilities, but take half damage and have powerful attack capable of smashing through walls."
magic_fluff_string = "..And draw the Assistant, faceless and generic, but never to be underestimated."
tech_fluff_string = "Boot sequence complete. Standard combat modules loaded. Holoparasite swarm online."
carp_fluff_string = "CARP CARP CARP! You caught one! It's really boring and standard. Better punch some walls to ease the tension."
diff --git a/code/modules/mob/living/simple_animal/guardian/types/support.dm b/code/modules/mob/living/simple_animal/guardian/types/support.dm
index 794683e6..8bf1874d 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/support.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/support.dm
@@ -2,11 +2,8 @@
/mob/living/simple_animal/hostile/guardian/healer
a_intent = INTENT_HARM
friendly = "heals"
- speed = 0
damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7)
- melee_damage_lower = 15
- melee_damage_upper = 15
- playstyle_string = "As a support type, you may toggle your basic attacks to a healing mode. In addition, Alt-Clicking on an adjacent object or mob will warp them to your bluespace beacon after a short delay."
+ playstyle_string = "As a support type, you have 30% damage reduction and may toggle your basic attacks to a healing mode. In addition, Alt-Clicking on an adjacent object or mob will warp them to your bluespace beacon after a short delay."
magic_fluff_string = "..And draw the CMO, a potent force of life... and death."
carp_fluff_string = "CARP CARP CARP! You caught a support carp. It's a kleptocarp!"
tech_fluff_string = "Boot sequence complete. Support modules active. Holoparasite swarm online."
diff --git a/code/modules/mob/living/simple_animal/hostile/goose.dm b/code/modules/mob/living/simple_animal/hostile/goose.dm
new file mode 100644
index 00000000..6f6dc992
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/goose.dm
@@ -0,0 +1,173 @@
+#define GOOSE_SATIATED 50
+
+/mob/living/simple_animal/hostile/retaliate/goose
+ name = "goose"
+ desc = "It's loose"
+ icon_state = "goose" // sprites by cogwerks from goonstation, used with permission
+ icon_living = "goose"
+ icon_dead = "goose_dead"
+ mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
+ speak_chance = 0
+ turns_per_move = 5
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = 2)
+ response_help = "pets"
+ response_disarm = "gently pushes aside"
+ response_harm = "kicks"
+ emote_taunt = list("hisses")
+ taunt_chance = 30
+ speed = 0
+ maxHealth = 25
+ health = 25
+ harm_intent_damage = 5
+ melee_damage_lower = 5
+ melee_damage_upper = 5
+ attacktext = "pecks"
+ attack_sound = "goose"
+ speak_emote = list("honks")
+ faction = list("neutral")
+ attack_same = TRUE
+ gold_core_spawnable = HOSTILE_SPAWN
+ var/random_retaliate = TRUE
+ var/icon_vomit_start = "vomit_start"
+ var/icon_vomit = "vomit"
+ var/icon_vomit_end = "vomit_end"
+
+/mob/living/simple_animal/hostile/retaliate/goose/handle_automated_movement()
+ . = ..()
+ if(prob(5) && random_retaliate == TRUE)
+ Retaliate()
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit
+ name = "Birdboat"
+ real_name = "Birdboat"
+ desc = "It's a sick-looking goose, probably ate too much maintenance trash. Best not to move it around too much."
+ gender = MALE
+ response_help = "pets"
+ response_disarm = "gently pushes aside"
+ response_harm = "kicks"
+ gold_core_spawnable = NO_SPAWN
+ random_retaliate = FALSE
+ var/vomiting = FALSE
+ var/vomitCoefficient = 1
+ var/vomitTimeBonus = 0
+ var/datum/action/cooldown/vomit/goosevomit
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/cargo
+ name = "Sickly Goose"
+ real_name = "Sickly Goose"
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/Initialize()
+ . = ..()
+ goosevomit = new
+ goosevomit.Grant(src)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/Destroy()
+ QDEL_NULL(goosevomit)
+ return ..()
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/examine(user)
+ . = ..()
+ . += "Somehow, it still looks hungry."
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/attacked_by(obj/item/O, mob/user)
+ . = ..()
+ feed(O)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/feed(obj/item/O)
+ var/obj/item/reagent_containers/food/tasty = O
+ if(!istype(O))
+ return
+ if (contents.len > GOOSE_SATIATED)
+ visible_message("[src] looks too full to eat \the [tasty]!")
+ return
+ if (tasty.foodtype & GROSS)
+ visible_message("[src] hungrily gobbles up \the [tasty]!")
+ tasty.forceMove(src)
+ playsound(src,'sound/items/eatfood.ogg', 70, 1)
+ vomitCoefficient += 3
+ vomitTimeBonus += 2
+ else
+ visible_message("[src] refuses to eat \the [tasty].")
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/vomit()
+ var/turf/T = get_turf(src)
+ var/obj/item/reagent_containers/food/consumed = locate() in contents //Barf out a single food item from our guts
+ if (prob(50) && consumed)
+ barf_food(consumed)
+ else
+ playsound(T, 'sound/effects/splat.ogg', 50, 1)
+ T.add_vomit_floor(src)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/barf_food(var/atom/A, var/hard = FALSE)
+ if(!istype(A, /obj/item/reagent_containers/food))
+ return
+ var/turf/currentTurf = get_turf(src)
+ var/obj/item/reagent_containers/food/consumed = A
+ consumed.forceMove(currentTurf)
+ var/destination = get_edge_target_turf(currentTurf, pick(GLOB.alldirs)) //Pick a random direction to toss them in
+ var/throwRange = hard ? rand(2,8) : 1
+ consumed.safe_throw_at(destination, throwRange, 2) //Thow the food at a random tile 1 spot away
+ sleep(2)
+ if (QDELETED(src) || QDELETED(consumed))
+ return
+ currentTurf = get_turf(consumed)
+ currentTurf.add_vomit_floor(src)
+ playsound(currentTurf, 'sound/effects/splat.ogg', 50, 1)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/vomit_prestart(duration)
+ flick("vomit_start",src)
+ addtimer(CALLBACK(src, .proc/vomit_start, duration), 13) //13 is the length of the vomit_start animation in gooseloose.dmi
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/vomit_start(duration)
+ vomiting = TRUE
+ icon_state = "vomit"
+ vomit()
+ addtimer(CALLBACK(src, .proc/vomit_preend), duration)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/vomit_preend()
+ for (var/obj/item/consumed in contents) //Get rid of any food left in the poor thing
+ barf_food(consumed, TRUE)
+ sleep(1)
+ if (QDELETED(src))
+ return
+ vomit_end()
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/vomit_end()
+ flick("vomit_end",src)
+ vomiting = FALSE
+ icon_state = initial(icon_state)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/Moved(oldLoc, dir)
+ . = ..()
+ if(vomiting)
+ vomit() // its supposed to keep vomiting if you move
+ return
+ var/turf/currentTurf = get_turf(src)
+ while (currentTurf == get_turf(src))
+ var/obj/item/reagent_containers/food/tasty = locate() in currentTurf
+ if (tasty)
+ feed(tasty)
+ stoplag(20)
+ if(prob(vomitCoefficient * 0.2))
+ vomit_prestart(vomitTimeBonus + 25)
+ vomitCoefficient = 1
+ vomitTimeBonus = 0
+
+/datum/action/cooldown/vomit
+ name = "Vomit"
+ check_flags = AB_CHECK_CONSCIOUS
+ button_icon_state = "vomit"
+ icon_icon = 'icons/mob/animal.dmi'
+ cooldown_time = 250
+
+/datum/action/cooldown/vomit/Trigger()
+ if(!..())
+ return FALSE
+ if(!istype(owner, /mob/living/simple_animal/hostile/retaliate/goose/vomit))
+ return FALSE
+ var/mob/living/simple_animal/hostile/retaliate/goose/vomit/vomit = owner
+ if(!vomit.vomiting)
+ vomit.vomit_prestart(vomit.vomitTimeBonus + 25)
+ vomit.vomitCoefficient = 1
+ vomit.vomitTimeBonus = 0
+ return TRUE
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index b529d826..b88db1fa 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -125,6 +125,8 @@ Difficulty: Very Hard
if(H.mind)
if(H.mind.martial_art && prob(H.mind.martial_art.deflection_chance))
. = TRUE
+ if (is_species(H, /datum/species/golem/sand))
+ . = TRUE
/mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots()
dir_shots(GLOB.diagonals)
diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm
index 5744a2cd..5c795242 100644
--- a/code/modules/mob/say.dm
+++ b/code/modules/mob/say.dm
@@ -90,6 +90,8 @@
var/key = copytext(message, 1, 2)
if(key == "#")
return MODE_WHISPER
+ else if(key == "%")
+ return MODE_SING
else if(key == ";")
return MODE_HEADSET
else if(length(message) > 2 && (key in GLOB.department_radio_prefixes))
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index 9706526a..aa1fd7db 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -67,6 +67,9 @@
/obj/structure/filingcabinet/ui_interact(mob/user)
. = ..()
+ if(isobserver(user))
+ return
+
if(contents.len <= 0)
to_chat(user, "[src] is empty.")
return
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 1b060583..6acc68cf 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -11,7 +11,7 @@
* Pens
*/
/obj/item/pen
- desc = "It's a normal black ink pen."
+ desc = "It's a black ink pen, modified for use with both paper and Nanotransen-brand Digital-Readpadsâ„¢!"
name = "pen"
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "pen"
@@ -33,12 +33,12 @@
return(BRUTELOSS)
/obj/item/pen/blue
- desc = "It's a normal blue ink pen."
+ desc = "It's a blue ink pen, modified for use with both paper and Nanotransen-brand Digital-Readpadsâ„¢!"
icon_state = "pen_blue"
colour = "blue"
/obj/item/pen/red
- desc = "It's a normal red ink pen."
+ desc = "It's a red ink pen, modified for use with both paper and Nanotransen-brand Digital-Readpadsâ„¢!"
icon_state = "pen_red"
colour = "red"
@@ -48,7 +48,7 @@
colour = "white"
/obj/item/pen/fourcolor
- desc = "It's a fancy four-color ink pen, set to black."
+ desc = "It's a fancy four-color ink pen, set to black. Modified to be compatible with Nanotransen-brand Digital-Readpadsâ„¢"
name = "four-color pen"
colour = "black"
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 135d9b85..19ff4728 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -267,7 +267,7 @@
to_chat(user, "There is an integration cog installed!")
to_chat(user, "Alt-Click the APC to [ locked ? "unlock" : "lock"] the interface.")
-
+
if(issilicon(user))
to_chat(user, "Ctrl-Click the APC to switch the breaker [ operating ? "off" : "on"].")
@@ -793,7 +793,7 @@
if(damage_flag == "melee" && damage_amount < damage_deflection)
return 0
. = ..()
-
+
/obj/machinery/power/apc/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
if(!(stat & BROKEN))
@@ -846,8 +846,6 @@
if(!ui)
ui = new(user, src, ui_key, "apc", name, 535, 515, master_ui, state)
ui.open()
- if(ui)
- ui.set_autoupdate(state = (failure_timer ? 1 : 0))
/obj/machinery/power/apc/ui_data(mob/user)
var/list/data = list(
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index 7f6306e3..9837d4e7 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -329,6 +329,12 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
if(power)
soundloop.volume = min(40, (round(power/100)/50)+1) // 5 +1 volume per 20 power. 2500 power is max
+ if(isclosedturf(T))
+ var/turf/did_it_melt = T.Melt()
+ if(!isclosedturf(did_it_melt)) //In case some joker finds way to place these on indestructible walls
+ visible_message("[src] melts through [T]!")
+ return
+
//Ok, get the air from the turf
var/datum/gas_mixture/env = T.return_air()
diff --git a/code/modules/projectiles/ammunition/ballistic/pistol.dm b/code/modules/projectiles/ammunition/ballistic/pistol.dm
index 13a284e9..ad962ebb 100644
--- a/code/modules/projectiles/ammunition/ballistic/pistol.dm
+++ b/code/modules/projectiles/ammunition/ballistic/pistol.dm
@@ -1,3 +1,9 @@
+// lato
+/obj/item/ammo_casing/latob
+ name = "Lato-class bullet casing"
+ desc = "A Lato-class bullet casing. Signiature with lotus engravings."
+ projectile_type = /obj/item/projectile/bullet/latob
+
// 10mm (Stechkin)
/obj/item/ammo_casing/c10mm
diff --git a/code/modules/projectiles/ammunition/ballistic/revolver.dm b/code/modules/projectiles/ammunition/ballistic/revolver.dm
index 9e2fa3a9..d5a9fab4 100644
--- a/code/modules/projectiles/ammunition/ballistic/revolver.dm
+++ b/code/modules/projectiles/ammunition/ballistic/revolver.dm
@@ -6,6 +6,11 @@
caliber = "357"
projectile_type = /obj/item/projectile/bullet/a357
+/obj/item/ammo_casing/a357/ap
+ name = ".357 armor-piercing bullet casing"
+ desc = "A .357 armor-piercing bullet casing."
+ projectile_type = /obj/item/projectile/bullet/a357/ap
+
// 7.62x38mmR (Nagant Revolver)
/obj/item/ammo_casing/n762
@@ -20,9 +25,26 @@
name = ".38 rubber bullet casing"
desc = "A .38 rubber bullet casing."
caliber = "38"
- projectile_type = /obj/item/projectile/bullet/c38
+ projectile_type = /obj/item/projectile/bullet/c38/rubber
/obj/item/ammo_casing/c38/lethal
name = ".38 bullet casing"
desc = "A .38 bullet casing"
- projectile_type = /obj/item/projectile/bullet/c38lethal
+ projectile_type = /obj/item/projectile/bullet/c38
+
+/obj/item/ammo_casing/c38/trac
+ name = ".38 TRAC bullet casing"
+ desc = "A .38 \"TRAC\" bullet casing."
+ projectile_type = /obj/item/projectile/bullet/c38/trac
+
+/obj/item/ammo_casing/c38/hotshot
+ name = ".38 Hot Shot bullet casing"
+ desc = "A .38 Hot Shot bullet casing."
+ caliber = "38"
+ projectile_type = /obj/item/projectile/bullet/c38/hotshot
+
+/obj/item/ammo_casing/c38/iceblox
+ name = ".38 Iceblox bullet casing"
+ desc = "A .38 Iceblox bullet casing."
+ caliber = "38"
+ projectile_type = /obj/item/projectile/bullet/c38/iceblox
\ No newline at end of file
diff --git a/code/modules/projectiles/ammunition/ballistic/rifle.dm b/code/modules/projectiles/ammunition/ballistic/rifle.dm
index 47c5c6d6..9c151667 100644
--- a/code/modules/projectiles/ammunition/ballistic/rifle.dm
+++ b/code/modules/projectiles/ammunition/ballistic/rifle.dm
@@ -26,3 +26,10 @@
caliber = "40mm"
icon_state = "40mmHE"
projectile_type = /obj/item/projectile/bullet/a40mm
+
+// bratonmag (Braton)
+/obj/item/ammo_casing/bratonmag
+ name = "Braton-class bullet casing"
+ desc = "A signiature shell from a Braton, lined with engravings."
+ caliber = "bratonb"
+ projectile_type = /obj/item/projectile/bullet/bratonb
diff --git a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
index 7cd27e85..b0e699a4 100644
--- a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
+++ b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm
@@ -3,18 +3,39 @@
desc = "Designed to quickly reload revolvers."
icon_state = "357"
ammo_type = /obj/item/ammo_casing/a357
+ caliber = "357"
max_ammo = 7
multiple_sprites = 1
+/obj/item/ammo_box/a357/ap
+ name = "speed loader (.357 AP)"
+ ammo_type = /obj/item/ammo_casing/a357/ap
+
/obj/item/ammo_box/c38
name = "speed loader (.38 rubber)"
desc = "Designed to quickly reload revolvers."
icon_state = "38"
+ caliber = "38"
ammo_type = /obj/item/ammo_casing/c38
max_ammo = 6
multiple_sprites = 1
materials = list(MAT_METAL = 20000)
+/obj/item/ammo_box/c38/trac
+ name = "speed loader (.38 TRAC)"
+ desc = "Designed to quickly reload revolvers. TRAC bullets embed a tracking implant within the target's body."
+ ammo_type = /obj/item/ammo_casing/c38/trac
+
+/obj/item/ammo_box/c38/hotshot
+ name = "speed loader (.38 Hot Shot)"
+ desc = "Designed to quickly reload revolvers. Hot Shot bullets contain an incendiary payload."
+ ammo_type = /obj/item/ammo_casing/c38/hotshot
+
+/obj/item/ammo_box/c38/iceblox
+ name = "speed loader (.38 Iceblox)"
+ desc = "Designed to quickly reload revolvers. Iceblox bullets contain a cryogenic payload."
+ ammo_type = /obj/item/ammo_casing/c38/iceblox
+
/obj/item/ammo_box/c38/lethal
name = "speed loader (.38)"
ammo_type = /obj/item/ammo_casing/c38/lethal
diff --git a/code/modules/projectiles/boxes_magazines/external/pistol.dm b/code/modules/projectiles/boxes_magazines/external/pistol.dm
index dbde572d..93f3c86f 100644
--- a/code/modules/projectiles/boxes_magazines/external/pistol.dm
+++ b/code/modules/projectiles/boxes_magazines/external/pistol.dm
@@ -1,3 +1,11 @@
+//Lato Ammo
+/obj/item/ammo_box/magazine/latomag
+ name = "pistol magazine (lato)"
+ desc = "A magazine fitted for lato-class weapons. A lotus decal is inscribed on the backside."
+ icon_state = "latomag"
+ ammo_type = /obj/item/ammo_casing/latob
+ max_ammo = 15
+
/obj/item/ammo_box/magazine/m10mm
name = "pistol magazine (10mm)"
desc = "A gun magazine."
diff --git a/code/modules/projectiles/boxes_magazines/external/rifle.dm b/code/modules/projectiles/boxes_magazines/external/rifle.dm
index 4512ba58..436822ef 100644
--- a/code/modules/projectiles/boxes_magazines/external/rifle.dm
+++ b/code/modules/projectiles/boxes_magazines/external/rifle.dm
@@ -19,3 +19,11 @@
caliber = "a556"
max_ammo = 30
multiple_sprites = 2
+
+//braton
+/obj/item/ammo_box/magazine/bratonmag
+ name = "toploader magazine (braton)"
+ icon_state = "bratonmag"
+ ammo_type = /obj/item/ammo_casing/bratonmag
+ caliber = "bratonb"
+ max_ammo = 60
\ No newline at end of file
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 8c44ca45..b0f9a7b4 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -235,7 +235,7 @@
sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread))
else //Smart spread
sprd = round((((rand_spr/burst_size) * iteration) - (0.5 + (rand_spr * 0.25))) * (randomized_gun_spread + randomized_bonus_spread))
-
+ before_firing(target,user)
if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, sprd))
shoot_with_empty_chamber(user)
firing_burst = FALSE
@@ -281,6 +281,7 @@
to_chat(user, " [src] is lethally chambered! You don't want to risk harming anyone...")
return
sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread))
+ before_firing(target,user)
if(!chambered.fire_casing(target, user, params, , suppressed, zone_override, sprd))
shoot_with_empty_chamber(user)
return
@@ -470,6 +471,9 @@
qdel(pin)
pin = new /obj/item/firing_pin
+//Happens before the actual projectile creation
+/obj/item/gun/proc/before_firing(atom/target,mob/user)
+ return
/////////////
// ZOOMING //
/////////////
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index 4bd65a7b..36f1fcfd 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -208,6 +208,21 @@
update_icon()
return
+//WARFRAME WEAPONS INSERT
+/obj/item/gun/ballistic/automatic/braton
+ name = "\improper Braton"
+ desc = "An unusual weapon in design; sporting a high firing rate and capacity, but low damage. There is a lotus decal on the underside of the barrel."
+ icon_state = "braton"
+ item_state = "braton"
+ w_class = WEIGHT_CLASS_HUGE
+ slot_flags = 0
+ mag_type = /obj/item/ammo_box/magazine/bratonmag
+ fire_sound = 'sound/weapons/gunshot_braton.ogg'
+ can_suppress = FALSE
+ burst_size = 5
+ fire_delay = 1
+//ENDS HERE
+
/obj/item/gun/ballistic/automatic/tommygun
name = "\improper Thompson SMG"
desc = "Based on the classic 'Chicago Typewriter'."
diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm
index 5f67194b..43e98d6f 100644
--- a/code/modules/projectiles/guns/ballistic/pistol.dm
+++ b/code/modules/projectiles/guns/ballistic/pistol.dm
@@ -21,6 +21,20 @@
var/obj/item/suppressor/S = new(src)
install_suppressor(S)
+//WARFRAME WEAPONS INSERT
+/obj/item/gun/ballistic/automatic/pistol/lato
+ name = "\improper Lato"
+ desc = "A strange sidearm, sporting low damage but a high firing rate and capacity. There is a lotus decal on the barrel."
+ icon_state = "lato"
+ item_state = "lato"
+ w_class = WEIGHT_CLASS_NORMAL
+ mag_type = /obj/item/ammo_box/magazine/latomag
+ can_suppress = FALSE
+ fire_sound = 'sound/weapons/gunshot_lato.ogg'
+ fire_delay = 0
+//ENDS HERE
+
+
/obj/item/gun/ballistic/automatic/pistol/m1911
name = "\improper M1911"
desc = "A classic .45 handgun with a small magazine capacity."
diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm
index 856dfed7..035a6cde 100644
--- a/code/modules/projectiles/guns/ballistic/shotgun.dm
+++ b/code/modules/projectiles/guns/ballistic/shotgun.dm
@@ -85,11 +85,9 @@
name = "riot shotgun"
desc = "A sturdy shotgun with a longer magazine and a fixed tactical stock designed for non-lethal riot control."
icon_state = "riotshotgun"
+ item_state = "riotshotgun"
mag_type = /obj/item/ammo_box/magazine/internal/shot/riot
sawn_desc = "Come with me if you want to live."
- unique_reskin = list("Tatical" = "riotshotgun",
- "Wood Stock" = "wood_riotshotgun"
- )
/obj/item/gun/ballistic/shotgun/riot/attackby(obj/item/A, mob/user, params)
..()
@@ -205,6 +203,7 @@
name = "combat shotgun"
desc = "A semi automatic shotgun with tactical furniture and a six-shell capacity underneath."
icon_state = "cshotgun"
+ item_state = "combatshotgun"
mag_type = /obj/item/ammo_box/magazine/internal/shot/com
w_class = WEIGHT_CLASS_HUGE
unique_reskin = list("Tatical" = "cshotgun",
@@ -215,6 +214,7 @@
name = "warden's combat shotgun"
desc = "A modified version of the semi automatic combat shotgun with a collapsible stock. For close encounters."
icon_state = "cshotgunc"
+ item_state = "combatshotgun"
mag_type = /obj/item/ammo_box/magazine/internal/shot/com
w_class = WEIGHT_CLASS_NORMAL
var/stock = FALSE
diff --git a/code/modules/projectiles/guns/energy/dueling.dm b/code/modules/projectiles/guns/energy/dueling.dm
new file mode 100644
index 00000000..23968fe1
--- /dev/null
+++ b/code/modules/projectiles/guns/energy/dueling.dm
@@ -0,0 +1,389 @@
+#define DUEL_IDLE 1
+#define DUEL_PREPARATION 2
+#define DUEL_READY 3
+#define DUEL_COUNTDOWN 4
+#define DUEL_FIRING 5
+
+//paper rock scissors
+#define DUEL_SETTING_A "wide"
+#define DUEL_SETTING_B "cone"
+#define DUEL_SETTING_C "pinpoint"
+
+#define DUEL_HUGBOX_NONE 0 //dismember head
+#define DUEL_HUGBOX_LETHAL 1 //200 damage to chest
+#define DUEL_HUGBOX_NONLETHAL 2 //stamcrit
+
+/datum/duel
+ var/obj/item/gun/energy/dueling/gun_A
+ var/obj/item/gun/energy/dueling/gun_B
+ var/state = DUEL_IDLE
+ var/required_distance = 5
+ var/list/confirmations = list()
+ var/list/fired = list()
+ var/countdown_length = 10
+ var/countdown_step = 0
+ var/static/next_id = 1
+ var/id
+
+/datum/duel/New()
+ id = next_id++
+
+/datum/duel/proc/try_begin()
+ //Check if both guns are held and if so begin.
+ var/mob/living/A = get_duelist(gun_A)
+ var/mob/living/B = get_duelist(gun_B)
+ if(!A || !B)
+ message_duelists("To begin the duel, both participants need to be holding paired dueling pistols.")
+ return
+ begin()
+
+/datum/duel/proc/begin()
+ state = DUEL_PREPARATION
+ confirmations.Cut()
+ fired.Cut()
+ countdown_step = countdown_length
+
+ message_duelists("Set your gun setting and move [required_distance] steps away from your opponent.")
+
+ START_PROCESSING(SSobj,src)
+
+/datum/duel/proc/get_duelist(obj/gun)
+ var/mob/living/G = gun.loc
+ if(!istype(G) || !G.is_holding(gun))
+ return null
+ return G
+
+/datum/duel/proc/message_duelists(message)
+ var/mob/living/LA = get_duelist(gun_A)
+ if(LA)
+ to_chat(LA,message)
+ var/mob/living/LB = get_duelist(gun_B)
+ if(LB)
+ to_chat(LB,message)
+
+/datum/duel/proc/other_gun(obj/item/gun/energy/dueling/G)
+ return G == gun_A ? gun_B : gun_A
+
+/datum/duel/proc/end()
+ message_duelists("Duel finished. Re-engaging safety.")
+ STOP_PROCESSING(SSobj,src)
+ state = DUEL_IDLE
+
+/datum/duel/process()
+ switch(state)
+ if(DUEL_PREPARATION)
+ if(check_positioning())
+ confirm_positioning()
+ else if (!get_duelist(gun_A) && !get_duelist(gun_B))
+ end()
+ if(DUEL_READY)
+ if(!check_positioning())
+ back_to_prep()
+ else if(confirmations.len == 2)
+ confirm_ready()
+ if(DUEL_COUNTDOWN)
+ if(!check_positioning())
+ back_to_prep()
+ else
+ countdown_step()
+ if(DUEL_FIRING)
+ if(check_fired())
+ end()
+
+/datum/duel/proc/back_to_prep()
+ message_duelists("Positions invalid. Please move to valid positions [required_distance] steps aways from each other to continue.")
+ state = DUEL_PREPARATION
+ confirmations.Cut()
+ countdown_step = countdown_length
+
+/datum/duel/proc/confirm_positioning()
+ message_duelists("Position confirmed. Confirm readiness by pulling the trigger once.")
+ state = DUEL_READY
+
+/datum/duel/proc/confirm_ready()
+ message_duelists("Readiness confirmed. Starting countdown. Commence firing at zero mark.")
+ state = DUEL_COUNTDOWN
+
+/datum/duel/proc/countdown_step()
+ countdown_step--
+ if(countdown_step == 0)
+ state = DUEL_FIRING
+ message_duelists("Fire!")
+ else
+ message_duelists("[countdown_step]!")
+
+/datum/duel/proc/check_fired()
+ if(fired.len == 2)
+ return TRUE
+ //Let's say if gun was dropped/stowed the user is finished
+ if(!get_duelist(gun_A))
+ return TRUE
+ if(!get_duelist(gun_B))
+ return TRUE
+ return FALSE
+
+/datum/duel/proc/check_positioning()
+ var/mob/living/A = get_duelist(gun_A)
+ var/mob/living/B = get_duelist(gun_B)
+ if(!A || !B)
+ return FALSE
+ if(!isturf(A.loc) || !isturf(B.loc))
+ return FALSE
+ if(get_dist(A,B) != required_distance)
+ return FALSE
+ for(var/turf/T in getline(get_turf(A),get_turf(B)))
+ if(is_blocked_turf(T,TRUE))
+ return FALSE
+ return TRUE
+
+/obj/item/gun/energy/dueling
+ name = "dueling pistol"
+ desc = "High-tech dueling pistol. Launches chaff and projectile according to preset settings."
+ icon_state = "dueling_pistol"
+ item_state = "gun"
+ ammo_x_offset = 2
+ w_class = WEIGHT_CLASS_SMALL
+ ammo_type = list(/obj/item/ammo_casing/energy/duel)
+ automatic_charge_overlays = FALSE
+ var/unlocked = FALSE
+ var/setting = DUEL_SETTING_A
+ var/datum/duel/duel
+ var/mutable_appearance/setting_overlay
+ var/hugbox = DUEL_HUGBOX_NONE
+
+/obj/item/gun/energy/dueling/hugbox
+ hugbox = DUEL_HUGBOX_LETHAL
+
+/obj/item/gun/energy/dueling/hugbox/stamina
+ hugbox = DUEL_HUGBOX_NONLETHAL
+
+/obj/item/gun/energy/dueling/Initialize()
+ . = ..()
+ setting_overlay = mutable_appearance(icon,setting_iconstate())
+ add_overlay(setting_overlay)
+
+/obj/item/gun/energy/dueling/examine(mob/user)
+ . = ..()
+ if(duel)
+ . += "Its linking number is [duel.id]."
+ else
+ . += "ERROR: No linking number on gun."
+
+/obj/item/gun/energy/dueling/proc/setting_iconstate()
+ switch(setting)
+ if(DUEL_SETTING_A)
+ return "duel_red"
+ if(DUEL_SETTING_B)
+ return "duel_green"
+ if(DUEL_SETTING_C)
+ return "duel_blue"
+ return "duel_red"
+
+/obj/item/gun/energy/dueling/attack_self(mob/living/user)
+ . = ..()
+ if(duel.state == DUEL_IDLE)
+ duel.try_begin()
+ else
+ toggle_setting(user)
+
+/obj/item/gun/energy/dueling/proc/toggle_setting(mob/living/user)
+ switch(setting)
+ if(DUEL_SETTING_A)
+ setting = DUEL_SETTING_B
+ if(DUEL_SETTING_B)
+ setting = DUEL_SETTING_C
+ if(DUEL_SETTING_C)
+ setting = DUEL_SETTING_A
+ to_chat(user,"You switch [src] setting to [setting] mode.")
+ update_icon()
+
+/obj/item/gun/energy/dueling/update_icon(force_update)
+ . = ..()
+ if(setting_overlay)
+ cut_overlay(setting_overlay)
+ setting_overlay.icon_state = setting_iconstate()
+ add_overlay(setting_overlay)
+
+/obj/item/gun/energy/dueling/Destroy()
+ . = ..()
+ if(duel.gun_A == src)
+ duel.gun_A = null
+ if(duel.gun_B == src)
+ duel.gun_B = null
+ duel = null
+
+/obj/item/gun/energy/dueling/can_trigger_gun(mob/living/user)
+ . = ..()
+ switch(duel.state)
+ if(DUEL_FIRING)
+ return . && !duel.fired[src]
+ if(DUEL_READY)
+ return .
+ else
+ to_chat(user,"[src] is locked. Wait for FIRE signal before shooting.")
+ return FALSE
+
+/obj/item/gun/energy/dueling/proc/is_duelist(mob/living/L)
+ if(!istype(L))
+ return FALSE
+ if(!L.is_holding(duel.other_gun(src)))
+ return FALSE
+ return TRUE
+
+/obj/item/gun/energy/dueling/process_fire(atom/target, mob/living/user, message, params, zone_override, bonus_spread)
+ if(duel.state == DUEL_READY)
+ duel.confirmations[src] = TRUE
+ to_chat(user,"You confirm your readiness.")
+ return
+ else if(!is_duelist(target)) //I kinda want to leave this out just to see someone shoot a bystander or missing.
+ to_chat(user,"[src] safety system prevents shooting anyone but your designated opponent.")
+ return
+ else
+ duel.fired[src] = TRUE
+ . = ..()
+
+/obj/item/gun/energy/dueling/before_firing(target,user)
+ var/obj/item/ammo_casing/energy/duel/D = chambered
+ D.setting = setting
+ D.hugbox = hugbox
+
+/obj/effect/temp_visual/dueling_chaff
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "shield-old"
+ duration = 30
+ var/setting
+
+/obj/effect/temp_visual/dueling_chaff/update_icon()
+ . = ..()
+ switch(setting)
+ if(DUEL_SETTING_A)
+ color = "red"
+ if(DUEL_SETTING_B)
+ color = "green"
+ if(DUEL_SETTING_C)
+ color = "blue"
+
+//Casing
+
+/obj/item/ammo_casing/energy/duel
+ e_cost = 0
+ projectile_type = /obj/item/projectile/energy/duel
+ var/setting
+ var/hugbox = DUEL_HUGBOX_NONE
+
+/obj/item/ammo_casing/energy/duel/ready_proj(atom/target, mob/living/user, quiet, zone_override)
+ . = ..()
+ var/obj/item/projectile/energy/duel/D = BB
+ D.setting = setting
+ D.hugbox = hugbox
+ D.update_icon()
+
+/obj/item/ammo_casing/energy/duel/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from)
+ . = ..()
+ var/obj/effect/temp_visual/dueling_chaff/C = new(get_turf(user))
+ C.setting = setting
+ C.update_icon()
+
+//Projectile
+
+/obj/item/projectile/energy/duel
+ name = "dueling beam"
+ icon_state = "declone"
+ is_reflectable = FALSE
+ homing = TRUE
+ var/setting
+ var/hugbox = DUEL_HUGBOX_NONE
+
+/obj/item/projectile/energy/duel/update_icon()
+ . = ..()
+ switch(setting)
+ if(DUEL_SETTING_A)
+ color = "red"
+ if(DUEL_SETTING_B)
+ color = "green"
+ if(DUEL_SETTING_C)
+ color = "blue"
+
+/obj/item/projectile/energy/duel/on_hit(atom/target, blocked)
+ . = ..()
+ var/turf/T = get_turf(target)
+ var/obj/effect/temp_visual/dueling_chaff/C = locate() in T
+ if(C)
+ var/counter_setting
+ switch(setting)
+ if(DUEL_SETTING_A)
+ counter_setting = DUEL_SETTING_B
+ if(DUEL_SETTING_B)
+ counter_setting = DUEL_SETTING_C
+ if(DUEL_SETTING_C)
+ counter_setting = DUEL_SETTING_A
+ if(C.setting == counter_setting)
+ return BULLET_ACT_BLOCK
+
+ var/mob/living/L = target
+ if(!istype(target))
+ return BULLET_ACT_BLOCK
+
+ switch(hugbox)
+ if(DUEL_HUGBOX_NONE)
+ var/obj/item/bodypart/B = L.get_bodypart(BODY_ZONE_HEAD)
+ B.dismember()
+ qdel(B)
+ if(DUEL_HUGBOX_LETHAL)
+ L.adjustBruteLoss(180)
+ L.death() //Die, powergamers.
+ if(DUEL_HUGBOX_NONLETHAL)
+ L.adjustStaminaLoss(200, forced = TRUE) //Die, powergamers x 2
+ L.Knockdown(100, override_hardstun = 100) //For good measure.
+
+//Storage case.
+/obj/item/storage/lockbox/dueling
+ name = "dueling pistol case"
+ desc = "Let's solve this like gentlespacemen."
+ icon_state = "medalbox+l"
+ item_state = "syringe_kit"
+ lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+ w_class = WEIGHT_CLASS_NORMAL
+ req_access = list(ACCESS_CAPTAIN)
+ icon_locked = "medalbox+l"
+ icon_closed = "medalbox"
+ icon_broken = "medalbox+b"
+ var/gun_type = /obj/item/gun/energy/dueling
+
+/obj/item/storage/lockbox/dueling/ComponentInitialize()
+ . = ..()
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
+ STR.max_w_class = WEIGHT_CLASS_SMALL
+ STR.max_items = 2
+ STR.can_hold = typecacheof(/obj/item/gun/energy/dueling)
+
+/obj/item/storage/lockbox/dueling/update_icon()
+ cut_overlays()
+ var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
+ if(locked)
+ icon_state = "medalbox+l"
+ else
+ icon_state = "medalbox"
+ if(open)
+ icon_state += "open"
+ if(broken)
+ icon_state += "+b"
+
+/obj/item/storage/lockbox/dueling/PopulateContents()
+ . = ..()
+ var/obj/item/gun/energy/dueling/gun_A = new gun_type(src)
+ var/obj/item/gun/energy/dueling/gun_B = new gun_type(src)
+ var/datum/duel/D = new
+ gun_A.duel = D
+ gun_B.duel = D
+ D.gun_A = gun_A
+ D.gun_B = gun_B
+
+/obj/item/storage/lockbox/dueling/hugbox
+ gun_type = /obj/item/gun/energy/dueling/hugbox
+ req_access = list(ACCESS_ARMORY)
+
+/obj/item/storage/lockbox/dueling/hugbox/stamina
+ gun_type = /obj/item/gun/energy/dueling/hugbox/stamina
+ req_access = null
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm
index 54cb9fe5..de738c90 100644
--- a/code/modules/projectiles/guns/energy/energy_gun.dm
+++ b/code/modules/projectiles/guns/energy/energy_gun.dm
@@ -118,11 +118,11 @@
switch(fail_tick)
if(0 to 200)
fail_tick += (2*(fail_chance))
- M.rad_act(40)
+ M.rad_act(400)
to_chat(M, "Your [name] feels warmer.")
if(201 to INFINITY)
SSobj.processing.Remove(src)
- M.rad_act(80)
+ M.rad_act(800)
crit_fail = 1
to_chat(M, "Your [name]'s reactor overloads!")
diff --git a/code/modules/projectiles/projectile/bullets/pistol.dm b/code/modules/projectiles/projectile/bullets/pistol.dm
index b68c3847..1f94de17 100644
--- a/code/modules/projectiles/projectile/bullets/pistol.dm
+++ b/code/modules/projectiles/projectile/bullets/pistol.dm
@@ -14,6 +14,11 @@
damage = 10
fire_stacks = 1
+// lato
+/obj/item/projectile/bullet/latob
+ name = "Lato-class bullet"
+ damage = 13
+
// 10mm (Stechkin)
/obj/item/projectile/bullet/c10mm
diff --git a/code/modules/projectiles/projectile/bullets/revolver.dm b/code/modules/projectiles/projectile/bullets/revolver.dm
index 68d51361..8ba2ba97 100644
--- a/code/modules/projectiles/projectile/bullets/revolver.dm
+++ b/code/modules/projectiles/projectile/bullets/revolver.dm
@@ -14,15 +14,58 @@
/obj/item/projectile/bullet/c38
name = ".38 rubber bullet"
+ damage = 25
+ stamina = 48
+
+/obj/item/projectile/bullet/c38/rubber
+ name = ".38 bullet"
damage = 15
stamina = 48
-/obj/item/projectile/bullet/c38lethal
- name = ".38 bullet"
- damage = 25
+/obj/item/projectile/bullet/c38/trac
+ name = ".38 TRAC bullet"
+ damage = 10
+
+/obj/item/projectile/bullet/c38/trac/on_hit(atom/target, blocked = FALSE)
+ . = ..()
+ var/mob/living/carbon/M = target
+ var/obj/item/implant/tracking/c38/imp
+ for(var/obj/item/implant/tracking/c38/TI in M.implants) //checks if the target already contains a tracking implant
+ imp = TI
+ return
+ if(!imp)
+ imp = new /obj/item/implant/tracking/c38(M)
+ imp.implant(M)
+
+/obj/item/projectile/bullet/c38/hotshot //similar to incendiary bullets, but do not leave a flaming trail
+ name = ".38 Hot Shot bullet"
+ damage = 20
+
+/obj/item/projectile/bullet/c38/hotshot/on_hit(atom/target, blocked = FALSE)
+ . = ..()
+ if(iscarbon(target))
+ var/mob/living/carbon/M = target
+ M.adjust_fire_stacks(6)
+ M.IgniteMob()
+
+/obj/item/projectile/bullet/c38/iceblox //see /obj/item/projectile/temp for the original code
+ name = ".38 Iceblox bullet"
+ damage = 20
+ var/temperature = 100
+
+/obj/item/projectile/bullet/c38/iceblox/on_hit(atom/target, blocked = FALSE)
+ . = ..()
+ if(isliving(target))
+ var/mob/living/M = target
+ M.adjust_bodytemperature(((100-blocked)/100)*(temperature - M.bodytemperature))
// .357 (Syndie Revolver)
/obj/item/projectile/bullet/a357
name = ".357 bullet"
damage = 60
+
+/obj/item/projectile/bullet/a357/ap
+ name = ".357 armor-piercing bullet"
+ damage = 45
+ armour_penetration = 45
\ No newline at end of file
diff --git a/code/modules/projectiles/projectile/bullets/rifle.dm b/code/modules/projectiles/projectile/bullets/rifle.dm
index ae1611cb..e54d3141 100644
--- a/code/modules/projectiles/projectile/bullets/rifle.dm
+++ b/code/modules/projectiles/projectile/bullets/rifle.dm
@@ -14,3 +14,8 @@
name = "enchanted 7.62 bullet"
damage = 5
stamina = 80
+
+// bratonmag (Braton)
+/obj/item/projectile/bullet/bratonb
+ name = "braton bullet"
+ damage = 10
\ No newline at end of file
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index 476fc60c..8074bb67 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -1,4 +1,4 @@
-#define CHEMICAL_QUANTISATION_LEVEL 0.0001
+ #define CHEMICAL_QUANTISATION_LEVEL 0.001
/proc/build_chemical_reagent_list()
//Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
@@ -466,7 +466,7 @@
if (C.FermiChem == TRUE && !continue_reacting)
if (chem_temp > C.ExplodeTemp) //This is first to ensure explosions.
- var/datum/chemical_reaction/fermi/Ferm = selected_reaction
+ var/datum/chemical_reaction/Ferm = selected_reaction
fermiIsReacting = FALSE
SSblackbox.record_feedback("tally", "fermi_chem", 1, ("[Ferm] explosion"))
Ferm.FermiExplode(src, my_atom, volume = total_volume, temp = chem_temp, pH = pH)
@@ -496,7 +496,12 @@
//Standard reaction mechanics:
else
- if (C.FermiChem == TRUE)//Just to make sure
+ if (C.FermiChem == TRUE)//Just to make sure, should only proc when grenades are combining.
+ if (chem_temp > C.ExplodeTemp) //To allow fermigrenades
+ var/datum/chemical_reaction/fermi/Ferm = selected_reaction
+ fermiIsReacting = FALSE
+ SSblackbox.record_feedback("tally", "fermi_chem", 1, ("[Ferm] explosion"))
+ Ferm.FermiExplode(src, my_atom, volume = total_volume, temp = chem_temp, pH = pH)
return 0
for(var/B in cached_required_reagents) //
@@ -539,7 +544,7 @@
return 0
/datum/reagents/process()
- var/datum/chemical_reaction/fermi/C = fermiReactID
+ var/datum/chemical_reaction/C = fermiReactID
var/list/cached_required_reagents = C.required_reagents//update reagents list
var/list/cached_results = C.results//resultant chemical list
@@ -575,16 +580,16 @@
return
/datum/reagents/proc/fermiEnd()
- var/datum/chemical_reaction/fermi/C = fermiReactID
+ var/datum/chemical_reaction/C = fermiReactID
STOP_PROCESSING(SSprocessing, src)
fermiIsReacting = FALSE
- reactedVol = 0
- targetVol = 0
//pH check, handled at the end to reduce calls.
if(istype(my_atom, /obj/item/reagent_containers))
var/obj/item/reagent_containers/RC = my_atom
RC.pH_check()
- C.FermiFinish(src, my_atom)
+ C.FermiFinish(src, my_atom, reactedVol)
+ reactedVol = 0
+ targetVol = 0
handle_reactions()
update_total()
//Reaction sounds and words
@@ -595,7 +600,7 @@
to_chat(M, "[iconhtml] [C.mix_message]")
/datum/reagents/proc/fermiReact(selected_reaction, cached_temp, cached_pH, reactedVol, targetVol, cached_required_reagents, cached_results, multiplier)
- var/datum/chemical_reaction/fermi/C = selected_reaction
+ var/datum/chemical_reaction/C = selected_reaction
var/deltaT = 0
var/deltapH = 0
var/stepChemAmmount = 0
@@ -704,7 +709,7 @@
return (reactedVol)
//Currently calculates it irrespective of required reagents at the start
-/datum/reagents/proc/reactant_purity(var/datum/chemical_reaction/fermi/C, holder)
+/datum/reagents/proc/reactant_purity(var/datum/chemical_reaction/C, holder)
var/list/cached_reagents = reagent_list
var/i = 0
var/cachedPurity
@@ -714,6 +719,14 @@
i++
return cachedPurity/i
+/datum/reagents/proc/uncache_purity(id)
+ var/datum/reagent/R = has_reagent("[id]")
+ if(!R)
+ return
+ if(R.cached_purity == 1)
+ return
+ R.purity = R.cached_purity
+
/datum/reagents/proc/isolate_reagent(reagent)
var/list/cached_reagents = reagent_list
for(var/_reagent in cached_reagents)
@@ -745,11 +758,14 @@
total_volume = 0
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
- if(R.volume < CHEMICAL_QUANTISATION_LEVEL)
+ if(R.volume == 0)
+ del_reagent(R.id)
+ if((R.volume < 0.01) && !fermiIsReacting)
del_reagent(R.id)
else
total_volume += R.volume
-
+ if(!reagent_list)
+ pH = 7
return 0
/datum/reagents/proc/clear_reagents()
@@ -878,17 +894,15 @@
var/datum/reagent/R = A
if (R.id == reagent) //IF MERGING
//Add amount and equalize purity
- R.volume += amount
+ R.volume += round(amount, CHEMICAL_QUANTISATION_LEVEL)
R.purity = ((R.purity * R.volume) + (other_purity * amount)) /((R.volume + amount)) //This should add the purity to the product
update_total()
if(my_atom)
my_atom.on_reagent_change(ADD_REAGENT)
if(isliving(my_atom))
- if(R.OnMobMergeCheck == TRUE)//Forces on_mob_add proc when a chem is merged
+ if(R.chemical_flags & REAGENT_ONMOBMERGE)//Forces on_mob_add proc when a chem is merged
R.on_mob_add(my_atom, amount)
- //else
- // R.on_merge(data, amount, my_atom, other_purity)
R.on_merge(data, amount, my_atom, other_purity)
if(!no_react)
handle_reactions()
@@ -900,13 +914,13 @@
var/datum/reagent/R = new D.type(data)
cached_reagents += R
R.holder = src
- R.volume = amount
+ R.volume = round(amount, CHEMICAL_QUANTISATION_LEVEL)
R.purity = other_purity
R.loc = get_turf(my_atom)
if(data)
R.data = data
R.on_new(data)
- if(R.addProc == TRUE)//Allows on new without data overhead.
+ if(R.chemical_flags & REAGENT_FORCEONNEW)//Allows on new without data overhead.
R.on_new(pH) //Add more as desired.
@@ -1134,4 +1148,4 @@
if(initial(R.can_synth))
random_reagents += initial(R.id)
var/picked_reagent = pick(random_reagents)
- return picked_reagent
+ return picked_reagent
\ No newline at end of file
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index bc998c66..8cd53152 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -488,6 +488,7 @@
"pwr_game",
"shamblers",
"sugar",
+ "pineapplejuice",
"orangejuice",
"grenadine",
"limejuice",
@@ -502,7 +503,8 @@
)
upgrade_reagents2 = list(
"banana",
- "berryjuice"
+ "berryjuice",
+ "strawberryjuice"
)
upgrade_reagents3 = null
emagged_reagents = list(
@@ -554,6 +556,7 @@
"hcider",
"creme_de_menthe",
"creme_de_cacao",
+ "creme_de_coconut",
"triple_sec",
"sake",
"applejack"
diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm
index 436ee80e..5af53789 100644
--- a/code/modules/reagents/chemistry/machinery/chem_heater.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm
@@ -79,6 +79,15 @@
return
return ..()
+ if(beaker)
+ if(istype(I, /obj/item/reagent_containers/dropper))
+ var/obj/item/reagent_containers/dropper/D = I
+ D.afterattack(beaker, user, 1)
+
+ if(istype(I, /obj/item/reagent_containers/syringe))
+ var/obj/item/reagent_containers/syringe/S = I
+ S.afterattack(beaker, user, 1)
+
/obj/machinery/chem_heater/on_deconstruction()
replace_beaker()
return ..()
diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm
index 002c54be..567c1873 100644
--- a/code/modules/reagents/chemistry/machinery/chem_master.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_master.dm
@@ -233,6 +233,12 @@
else
reagents.remove_reagent(id, amount)
. = TRUE
+ else if (amount == -1) // -1 means custom amount
+ useramount = input("Enter the Amount you want to transfer:", name, useramount) as num|null
+ if (useramount > 0)
+ end_fermi_reaction()
+ reagents.trans_id_to(beaker, id, useramount)
+ . = TRUE
if("toggleMode")
mode = !mode
@@ -332,7 +338,7 @@
var/vol_part = min(reagents.total_volume, 30)
if(text2num(many))
amount_full = round(reagents.total_volume / 30)
- vol_part = reagents.total_volume % 30
+ vol_part = ((reagents.total_volume*1000) % 30000) / 1000 //% operator doesn't support decimals.
var/name = stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
@@ -379,7 +385,34 @@
reagents.trans_to(P, vol_part)
. = TRUE
//END CITADEL ADDITIONS
- if("analyze")
+ if("analyzeBeak")
+ var/datum/reagent/R = GLOB.chemical_reagents_list[params["id"]]
+ if(R)
+ var/state = "Unknown"
+ if(initial(R.reagent_state) == 1)
+ state = "Solid"
+ else if(initial(R.reagent_state) == 2)
+ state = "Liquid"
+ else if(initial(R.reagent_state) == 3)
+ state = "Gas"
+ var/const/P = 3 //The number of seconds between life ticks
+ var/T = initial(R.metabolization_rate) * (60 / P)
+ var/datum/chemical_reaction/Rcr = get_chemical_reaction(R.id)
+ if(Rcr && Rcr.FermiChem)
+ fermianalyze = TRUE
+ var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2
+ var/datum/reagent/targetReagent = beaker.reagents.has_reagent("[R.id]")
+
+ if(!targetReagent)
+ CRASH("Tried to find a reagent that doesn't exist in the chem_master!")
+ analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = targetReagent.purity, "inverseRatioF" = initial(R.inverse_chem_val), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache)
+ else
+ fermianalyze = FALSE
+ analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold))
+ screen = "analyze"
+ return
+
+ if("analyzeBuff")
var/datum/reagent/R = GLOB.chemical_reagents_list[params["id"]]
if(R)
var/state = "Unknown"
@@ -395,7 +428,11 @@
fermianalyze = TRUE
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R.id)
var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2
- analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = initial(R.purity), "inverseRatioF" = initial(R.InverseChemVal), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache)
+ var/datum/reagent/targetReagent = reagents.has_reagent("[R.id]")
+
+ if(!targetReagent)
+ CRASH("Tried to find a reagent that doesn't exist in the chem_master!")
+ analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = targetReagent.purity, "inverseRatioF" = initial(R.inverse_chem_val), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache)
else
fermianalyze = FALSE
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold))
@@ -451,4 +488,4 @@
condi = TRUE
#undef PILL_STYLE_COUNT
-#undef RANDOM_PILL_STYLE
+#undef RANDOM_PILL_STYLE
\ No newline at end of file
diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm
index 0e482f8c..720d411d 100644
--- a/code/modules/reagents/chemistry/machinery/pandemic.dm
+++ b/code/modules/reagents/chemistry/machinery/pandemic.dm
@@ -125,12 +125,6 @@
else
cut_overlays()
-/obj/machinery/computer/pandemic/proc/eject_beaker()
- if(beaker)
- beaker.forceMove(drop_location())
- beaker = null
- update_icon()
-
/obj/machinery/computer/pandemic/ui_interact(mob/user, ui_key = "main", datum/tgui/ui, force_open = FALSE, datum/tgui/master_ui, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -165,7 +159,7 @@
return
switch(action)
if("eject_beaker")
- eject_beaker()
+ replace_beaker(usr)
. = TRUE
if("empty_beaker")
if(beaker)
@@ -174,7 +168,7 @@
if("empty_eject_beaker")
if(beaker)
beaker.reagents.clear_reagents()
- eject_beaker()
+ replace_beaker(usr)
. = TRUE
if("rename_disease")
var/id = get_virus_id_by_index(text2num(params["index"]))
@@ -232,18 +226,32 @@
. = TRUE //no afterattack
if(stat & (NOPOWER|BROKEN))
return
- if(beaker)
- to_chat(user, "A container is already loaded into [src]!")
+ var/obj/item/reagent_containers/B = I
+ if(!user.transferItemToLoc(B, src))
return
- if(!user.transferItemToLoc(I, src))
- return
-
- beaker = I
+ replace_beaker(user, B)
to_chat(user, "You insert [I] into [src].")
- update_icon()
else
return ..()
+/obj/machinery/computer/pandemic/AltClick(mob/living/user)
+ if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
+ return
+ replace_beaker(user)
+ return
+
+/obj/machinery/computer/pandemic/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
+ if(beaker)
+ beaker.forceMove(drop_location())
+ if(user && Adjacent(user) && !issiliconoradminghost(user))
+ user.put_in_hands(beaker)
+ if(new_beaker)
+ beaker = new_beaker
+ else
+ beaker = null
+ update_icon()
+ return TRUE
+
/obj/machinery/computer/pandemic/on_deconstruction()
- eject_beaker()
+ replace_beaker(usr)
. = ..()
diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm
index c21629ce..aaccc6d0 100644
--- a/code/modules/reagents/chemistry/reagents.dm
+++ b/code/modules/reagents/chemistry/reagents.dm
@@ -32,19 +32,19 @@
var/addiction_stage3_end = 30
var/addiction_stage4_end = 40
var/overdosed = 0 // You fucked up and this is now triggering its overdose effects, purge that shit quick.
- var/self_consuming = FALSE
+ var/self_consuming = FALSE //I think this uhhh, makes weird stuff happen when metabolising, but... doesn't seem to do what I think, so I'm gonna leave it.
//Fermichem vars:
- var/purity = 1 //How pure a chemical is from 0 - 1.
- var/addProc = FALSE //If the chemical should force an on_new() call
+ var/purity = 1 //How pure a chemical is from 0 - 1.
+ var/cached_purity = 1
var/turf/loc = null //Should be the creation location!
var/pH = 7 //pH of the specific reagent, used for calculating the sum pH of a holder.
- var/ImpureChem = "fermiTox"// What chemical is metabolised with an inpure reaction
- var/InverseChemVal = 0.25 // If the impurity is below 0.5, replace ALL of the chem with InverseChem upon metabolising
- var/InverseChem = "fermiTox"// What chem is metabolised when purity is below InverseChemVal, this shouldn't be made, but if it does, well, I guess I'll know about it.
- var/DoNotSplit = FALSE // If impurity is handled within the main chem itself
- var/OnMobMergeCheck = FALSE //Call on_mob_life proc when reagents are merging.
+ //var/SplitChem = FALSE //If the chem splits on metabolism
+ var/impure_chem // What chemical is metabolised with an inpure reaction
+ var/inverse_chem_val = 0 // If the impurity is below 0.5, replace ALL of the chem with inverse_chemupon metabolising
+ var/inverse_chem // What chem is metabolised when purity is below inverse_chem_val, this shouldn't be made, but if it does, well, I guess I'll know about it.
var/metabolizing = FALSE
- var/invisible = FALSE //Set to true if it doesn't appear on handheld health analyzers.
+ var/chemical_flags // See fermi/readme.dm REAGENT_DEAD_PROCESS, REAGENT_DONOTSPLIT, REAGENT_ONLYINVERSE, REAGENT_ONMOBMERGE, REAGENT_INVISIBLE, REAGENT_FORCEONNEW, REAGENT_SNEAKYNAME
+
/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
. = ..()
@@ -73,8 +73,47 @@
holder.remove_reagent(src.id, metabolization_rate * M.metabolism_efficiency) //By default it slowly disappears.
return
+//called when a mob processes chems when dead.
+/datum/reagent/proc/on_mob_dead(mob/living/carbon/M)
+ if(!(chemical_flags & REAGENT_DEAD_PROCESS)) //justincase
+ return
+ current_cycle++
+ if(holder)
+ holder.remove_reagent(src.id, metabolization_rate * M.metabolism_efficiency) //By default it slowly disappears.
+ return
+
// Called when this reagent is first added to a mob
-/datum/reagent/proc/on_mob_add(mob/living/L)
+/datum/reagent/proc/on_mob_add(mob/living/L, amount)
+ if(!iscarbon(L))
+ return
+ var/mob/living/carbon/M = L
+ if (purity == 1)
+ log_game("CHEM: [L] ckey: [L.key] has ingested [volume]u of [id]")
+ return
+ if(cached_purity == 1)
+ cached_purity = purity
+ else if(purity < 0)
+ CRASH("Purity below 0 for chem: [id], Please let Fermis Know!")
+ if(chemical_flags & REAGENT_DONOTSPLIT)
+ return
+
+ if ((inverse_chem_val > purity) && (inverse_chem))//Turns all of a added reagent into the inverse chem
+ M.reagents.remove_reagent(id, amount, FALSE)
+ M.reagents.add_reagent(inverse_chem, amount, FALSE, other_purity = 1-cached_purity)
+ var/datum/reagent/R = M.reagents.has_reagent("[inverse_chem]")
+ if(R.chemical_flags & REAGENT_SNEAKYNAME)
+ R.name = name//Negative effects are hidden
+ if(R.chemical_flags & REAGENT_INVISIBLE)
+ R.chemical_flags |= (REAGENT_INVISIBLE)
+ log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [inverse_chem]")
+ return
+ else if (impure_chem)
+ var/impureVol = amount * (1 - purity) //turns impure ratio into impure chem
+ if(!(chemical_flags & REAGENT_SPLITRETAINVOL))
+ M.reagents.remove_reagent(id, (impureVol), FALSE)
+ M.reagents.add_reagent(impure_chem, impureVol, FALSE, other_purity = 1-cached_purity)
+ log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume - impureVol]u of [id]")
+ log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [impure_chem]")
return
// Called when this reagent is removed while inside a mob
@@ -97,7 +136,35 @@
return
// Called when two reagents of the same are mixing.
-/datum/reagent/proc/on_merge(data)
+/datum/reagent/proc/on_merge(data, amount, mob/living/carbon/M, purity)
+ if(!iscarbon(M))
+ return
+ if (purity == 1)
+ log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [id]")
+ return
+ cached_purity = purity //purity SHOULD be precalculated from the add_reagent, update cache.
+ if (purity < 0)
+ CRASH("Purity below 0 for chem: [id], Please let Fermis Know!")
+ if(chemical_flags & REAGENT_DONOTSPLIT)
+ return
+
+ if ((inverse_chem_val > purity) && (inverse_chem)) //INVERT
+ M.reagents.remove_reagent(id, amount, FALSE)
+ M.reagents.add_reagent(inverse_chem, amount, FALSE, other_purity = 1-cached_purity)
+ var/datum/reagent/R = M.reagents.has_reagent("[inverse_chem]")
+ if(R.chemical_flags & REAGENT_SNEAKYNAME)
+ R.name = name//Negative effects are hidden
+ if(R.chemical_flags & REAGENT_INVISIBLE)
+ R.chemical_flags |= (REAGENT_INVISIBLE)
+ log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [inverse_chem]")
+ return
+ else if (impure_chem) //SPLIT
+ var/impureVol = amount * (1 - purity)
+ if(!(chemical_flags & REAGENT_SPLITRETAINVOL))
+ M.reagents.remove_reagent(id, impureVol, FALSE)
+ M.reagents.add_reagent(impure_chem, impureVol, FALSE, other_purity = 1-cached_purity)
+ log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume - impureVol]u of [id]")
+ log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [impure_chem]")
return
/datum/reagent/proc/on_update(atom/A)
@@ -146,4 +213,4 @@
for (var/datum/reagent/R in reagent_list)
rs += "[R.name], [R.volume]"
- return rs.Join(" | ")
+ return rs.Join(" | ")
\ No newline at end of file
diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
index a3194cee..b447802c 100644
--- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
@@ -959,14 +959,14 @@ All effects don't start immediately, but rather get worse over time; the rate is
/datum/reagent/consumable/ethanol/bahama_mama
name = "Bahama Mama"
id = "bahama_mama"
- description = "Tropical cocktail."
+ description = "A tropical cocktail with a complex blend of flavors."
color = "#FF7F3B" // rgb: 255, 127, 59
boozepwr = 35
quality = DRINK_GOOD
- taste_description = "lime and orange"
+ taste_description = "pineapple, coconut, and a hint of coffee"
glass_icon_state = "bahama_mama"
glass_name = "Bahama Mama"
- glass_desc = "Tropical cocktail."
+ glass_desc = "A tropical cocktail with a complex blend of flavors."
/datum/reagent/consumable/ethanol/singulo
name = "Singulo"
@@ -1373,6 +1373,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
/datum/reagent/consumable/ethanol/neurotoxin
name = "Neurotoxin"
+ id = "neurotoxin"
description = "A strong neurotoxin that puts the subject into a death-like state."
color = "#2E2E61" // rgb: 46, 46, 97
boozepwr = 50
@@ -1382,6 +1383,11 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_icon_state = "neurotoxinglass"
glass_name = "Neurotoxin"
glass_desc = "A drink that is guaranteed to knock you silly."
+ pH = 4.3
+ //SplitChem = TRUE
+ impure_chem = "neuroweak"
+ inverse_chem_val = 0.5 //Clear conversion
+ inverse_chem = "neuroweak"
/datum/reagent/consumable/ethanol/neurotoxin/proc/pickt()
return (pick(TRAIT_PARALYSIS_L_ARM,TRAIT_PARALYSIS_R_ARM,TRAIT_PARALYSIS_R_LEG,TRAIT_PARALYSIS_L_LEG))
@@ -1417,6 +1423,26 @@ All effects don't start immediately, but rather get worse over time; the rate is
M.adjustStaminaLoss(10)
..()
+/datum/reagent/consumable/ethanol/neurosmash
+ name = "Neurosmash"
+ id = "neurosmash"
+ description = "A mostly safe alcoholic drink for the true daredevils. Do not mix with Neurotoxin."
+ color = "#2E2E61" // rgb: 46, 46, 97
+ boozepwr = 60
+ quality = DRINK_VERYGOOD
+ taste_description = "a numbing sensation"
+ glass_icon_state = "neurosmashglass"
+ glass_name = "Neurosmash"
+ glass_desc = "A mostly safe alcoholic drink for the true daredevils. Do not mix with Neurotoxin."
+
+/datum/reagent/consumable/ethanol/neurosmash/on_mob_life(mob/living/carbon/M)
+ if(holder.has_reagent("neurotoxin"))
+ M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.5*REM, 150)
+ else
+ M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1.0*REM, 150)
+ M.dizziness +=2
+ ..()
+
/datum/reagent/consumable/ethanol/hippies_delight
name = "Hippie's Delight"
id = "hippiesdelight"
@@ -1526,6 +1552,17 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Creme de Cacao"
glass_desc = "A million hazing lawsuits and alcohol poisonings have started with this humble ingredient."
+datum/reagent/consumable/ethanol/creme_de_coconut
+ name = "Creme de Coconut"
+ id = "creme_de_coconut"
+ description = "A coconut liqueur for smooth, creamy, tropical drinks."
+ color = "#F7F0D0"
+ boozepwr = 20
+ taste_description = "a sweet milky flavor with notes of toasted sugar"
+ glass_icon_state = "glass_white"
+ glass_name = "Creme de Coconut"
+ glass_desc = "An unintimidating glass of coconut liqueur."
+
/datum/reagent/consumable/ethanol/quadruple_sec
name = "Quadruple Sec"
id = "quadruple_sec"
@@ -2240,7 +2277,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Gunfire"
glass_desc = "It pops constantly as you look at it, giving off tiny sparks."
-/datum/reagent/consumable/ethanol/hellfire/on_mob_life(mob/living/carbon/M)
+/datum/reagent/consumable/ethanol/gunfire/on_mob_life(mob/living/carbon/M)
if (prob(3))
to_chat(M,"You feel the gunfire pop in your mouth.")
return ..()
@@ -2272,3 +2309,91 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_icon_state = "sins_delight"
glass_name = "Sin's Delight"
glass_desc = "You can smell the seven sins rolling off the top of the glass."
+
+/datum/reagent/consumable/ethanol/painkiller
+ name = "Painkiller"
+ id = "painkiller"
+ description = "Dulls your pain. Your emotional pain, that is."
+ boozepwr = 20
+ color = "#EAD677"
+ quality = DRINK_NICE
+ taste_description = "sugary tartness"
+ glass_icon_state = "painkiller"
+ glass_name = "Painkiller"
+ glass_desc = "A combination of tropical juices and rum. Surely this will make you feel better."
+
+/datum/reagent/consumable/ethanol/pina_colada
+ name = "Pina Colada"
+ id = "pina_colada"
+ description = "A fresh pineapple drink with coconut rum. Yum."
+ boozepwr = 40
+ color = "#FFF1B2"
+ quality = DRINK_NICE
+ taste_description = "pineapple, coconut, and a hint of the ocean"
+ glass_icon_state = "pina_colada"
+ glass_name = "Pina Colada"
+ glass_desc = "If you like pina coladas, and getting caught in the rain... well, you'll like this drink."
+
+/datum/reagent/consumable/ethanol/strawberry_daiquiri
+ name = "Strawberry Daiquiri"
+ id = "strawberry_daiquiri"
+ description = "Pink looking alcoholic drink."
+ boozepwr = 20
+ color = "#FF4A74"
+ quality = DRINK_NICE
+ taste_description = "sweet strawberry, lime and the ocean breeze"
+ glass_icon_state = "strawberry_daiquiri"
+ glass_name = "Strawberry Daiquiri"
+ glass_desc = "Pink looking drink with flowers and a big straw to sip it. Looks sweet and refreshing, perfect for warm days."
+
+/datum/reagent/consumable/ethanol/liz_fizz
+ name = "Liz Fizz"
+ id = "liz_fizz"
+ description = "Triple citrus layered with some ice and cream."
+ boozepwr = 0
+ color = "#D8FF59"
+ taste_description = "brain freezing sourness"
+ glass_icon_state = "liz_fizz"
+ glass_name = "Liz Fizz"
+ glass_desc = "Looks like a citrus sherbet seperated in layers? Why would anyone want that is beyond you."
+
+/datum/reagent/consumable/ethanol/miami_vice
+ name = "Miami Vice"
+ id = "miami_vice"
+ description = "A drink layering Pina Colada and Strawberry Daiquiri"
+ boozepwr = 30
+ color = "#D8FF59"
+ quality = DRINK_FANTASTIC
+ taste_description = "sweet and refreshing flavor, complemented with strawberries and coconut, and hints of citrus"
+ glass_icon_state = "miami_vice"
+ glass_name = "Miami Vice"
+ glass_desc = "Strawberries and coconut, like yin and yang."
+
+/datum/reagent/consumable/ethanol/malibu_sunset
+ name = "Malibu Sunset"
+ id = "malibu_sunset"
+ description = "A drink consisting of creme de coconut and tropical juices"
+ boozepwr = 20
+ color = "#FF9473"
+ quality = DRINK_NICE
+ taste_description = "coconut, with orange and grenadine accents"
+ glass_icon_state = "malibu_sunset"
+ glass_name = "Malibu Sunset"
+ glass_desc = "Tropical looking drinks, with ice cubes hovering on the surface and grenadine coloring the bottom."
+
+/datum/reagent/consumable/ethanol/hotlime_miami
+ name = "Hotlime Miami"
+ id = "hotlime_miami"
+ description = "The essence of the 90's, if they were a bloody mess that is."
+ boozepwr = 40
+ color = "#A7FAE8"
+ quality = DRINK_FANTASTIC
+ taste_description = "coconut and aesthetic violence"
+ glass_icon_state = "hotlime_miami"
+ glass_name = "Hotlime Miami"
+ glass_desc = "This looks very aesthetically pleasing."
+
+/datum/reagent/consumable/ethanol/hotlime_miami/on_mob_life(mob/living/carbon/M)
+ M.set_drugginess(50)
+ M.adjustStaminaLoss(-2)
+ return ..()
\ No newline at end of file
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index b4e61faa..cce2ba84 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -126,6 +126,15 @@
glass_name = "glass of lemon juice"
glass_desc = "Sour..."
+/datum/reagent/consumable/strawberryjuice
+ name = "Strawberry Juice"
+ id = "strawberryjuice"
+ description = "Refreshing seasonal summer drink."
+ color = "#F2163A"
+ taste_description = "strawberry"
+ glass_name = "glass of strawberry juice"
+ glass_desc = "Refreshing seasonal summer drink."
+
/datum/reagent/consumable/banana
name = "Banana Juice"
id = "banana"
@@ -210,8 +219,8 @@
description = "An opaque white liquid produced by the mammary glands of mammals."
color = "#DFDFDF" // rgb: 223, 223, 223
taste_description = "milk"
- glass_icon_state = "glass_white"
- glass_name = "glass of milk"
+ glass_icon_state = "milkglass"
+ glass_name = "milk drum"
glass_desc = "White and nutritious goodness!"
/datum/reagent/consumable/milk/on_mob_life(mob/living/carbon/M)
@@ -816,6 +825,15 @@
taste_description = "parsnip"
glass_name = "glass of parsnip juice"
+/datum/reagent/consumable/pineapplejuice
+ name = "Pineapple Juice"
+ id = "pineapplejuice"
+ description = "Tart, tropical, and hotly debated."
+ color = "#F7D435"
+ taste_description = "pineapple"
+ glass_name = "glass of pineapple juice"
+ glass_desc = "Tart, tropical, and hotly debated."
+
/datum/reagent/consumable/peachjuice //Intended to be extremely rare due to being the limiting ingredients in the blazaam drink
name = "Peach Juice"
id = "peachjuice"
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index 1095e60e..e203bc94 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -604,21 +604,23 @@
..()
/datum/reagent/consumable/honey
- name = "honey"
+ name = "Honey"
id = "honey"
description = "Sweet sweet honey that decays into sugar. Has antibacterial and natural healing properties."
color = "#d3a308"
nutriment_factor = 15 * REAGENTS_METABOLISM
metabolization_rate = 1 * REAGENTS_METABOLISM
taste_description = "sweetness"
+ var/power = 0
/datum/reagent/consumable/honey/on_mob_life(mob/living/carbon/M)
- M.reagents.add_reagent("sugar",3)
+ if(power == 0)
+ M.reagents.add_reagent(/datum/reagent/consumable/sugar,3)
if(prob(55))
- M.adjustBruteLoss(-1*REM, 0)
- M.adjustFireLoss(-1*REM, 0)
- M.adjustOxyLoss(-1*REM, 0)
- M.adjustToxLoss(-1*REM, 0)
+ M.adjustBruteLoss(-1*REM+power, 0)
+ M.adjustFireLoss(-1*REM+power, 0)
+ M.adjustOxyLoss(-1*REM+power, 0)
+ M.adjustToxLoss(-1*REM+power, 0)
..()
/datum/reagent/consumable/honey/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
@@ -629,6 +631,12 @@
S.success_multiplier = max(0.6, S.success_multiplier) // +60% success probability on each step, compared to bacchus' blessing's ~46%
..()
+/datum/reagent/consumable/honey/special
+ name = "Royal Honey"
+ id = "royalhoney"
+ description = "A special honey which heals the imbiber far faster than normal honey"
+ power = 1
+
/datum/reagent/consumable/mayonnaise
name = "Mayonnaise"
id = "mayonnaise"
diff --git a/code/modules/reagents/chemistry/reagents/impure_reagents.dm b/code/modules/reagents/chemistry/reagents/impure_reagents.dm
new file mode 100644
index 00000000..6251fbf7
--- /dev/null
+++ b/code/modules/reagents/chemistry/reagents/impure_reagents.dm
@@ -0,0 +1,26 @@
+//Reagents produced by metabolising/reacting fermichems inoptimally, i.e. inverse_chems or impure_chems
+//Inverse = Splitting
+//Invert = Whole conversion
+
+/datum/reagent/impure
+ chemical_flags = REAGENT_INVISIBLE | REAGENT_SNEAKYNAME //by default, it will stay hidden on splitting, but take the name of the source on inverting
+
+
+/datum/reagent/impure/fermiTox
+ name = "Chemical Isomers"
+ id = "fermiTox"
+ description = "Toxic chemical isomers made from impure reactions. At low volumes will cause light toxin damage, but as the volume increases, it deals larger amounts, damages the liver, then eventually the heart."
+ data = "merge"
+ color = "FFFFFF"
+ can_synth = FALSE
+ var/potency = 1 //potency multiplies the volume when added.
+
+
+//I'm concerned this is too weak, but I also don't want deathmixes.
+//TODO: liver damage, 100+ heart
+/datum/reagent/impure/fermiTox/on_mob_life(mob/living/carbon/C, method)
+ if(C.dna && istype(C.dna.species, /datum/species/jelly))
+ C.adjustToxLoss(-2)
+ else
+ C.adjustToxLoss(2)
+ ..()
\ No newline at end of file
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index aa8faa5f..7ff2a40d 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -236,10 +236,12 @@
/datum/reagent/medicine/silver_sulfadiazine
name = "Silver Sulfadiazine"
id = "silver_sulfadiazine"
- description = "If used in touch-based applications, immediately restores burn wounds as well as restoring more over time. If ingested through other means, deals minor toxin damage."
+ description = "If used in touch-based applications, immediately restores burn wounds as well as restoring more over time. It is mildly poisonous taken orally or by injection. If overdosed, deals brute and minor liver damage."
reagent_state = LIQUID
pH = 7.2
color = "#ffeac9"
+ metabolization_rate = 5 * REAGENTS_METABOLISM
+ overdose_threshold = 50
/datum/reagent/medicine/silver_sulfadiazine/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(iscarbon(M) && M.stat != DEAD)
@@ -260,6 +262,15 @@
..()
. = 1
+/datum/reagent/medicine/silver_sulfadiazine/overdose_start(mob/living/M)
+ metabolization_rate = 15 * REAGENTS_METABOLISM
+ M.adjustBruteLoss(2*REM, 0)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ C.applyLiverDamage(1)
+ ..()
+ . = 1
+
/datum/reagent/medicine/oxandrolone
name = "Oxandrolone"
id = "oxandrolone"
@@ -287,10 +298,12 @@
/datum/reagent/medicine/styptic_powder
name = "Styptic Powder"
id = "styptic_powder"
- description = "If used in touch-based applications, immediately restores bruising as well as restoring more over time. If ingested through other means, deals minor toxin damage."
+ description = "If used in touch-based applications, immediately restores bruising as well as restoring more over time. It is poisonous if taken orally or by injection. If overdosed, deals brute and minor liver damage."
reagent_state = LIQUID
color = "#FF9696"
pH = 6.7
+ metabolization_rate = 5 * REAGENTS_METABOLISM
+ overdose_threshold = 50
/datum/reagent/medicine/styptic_powder/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(iscarbon(M) && M.stat != DEAD)
@@ -312,6 +325,15 @@
..()
. = 1
+datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
+ metabolization_rate = 15 * REAGENTS_METABOLISM
+ M.adjustBruteLoss(2*REM, 0)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ C.applyLiverDamage(1)
+ ..()
+ . = 1
+
/datum/reagent/medicine/salglu_solution
name = "Saline-Glucose Solution"
id = "salglu_solution"
@@ -398,23 +420,35 @@
/datum/reagent/medicine/synthflesh
name = "Synthflesh"
id = "synthflesh"
- description = "Has a 100% chance of instantly healing brute and burn damage. One unit of the chemical will heal one point of damage. Touch application only."
+ description = "Has a 100% chance of healing large amounts of brute and burn damage very quickly. One unit of the chemical will heal one point of damage. Touch application only."
reagent_state = LIQUID
color = "#FFEBEB"
pH = 11.5
+ metabolization_rate = 5 * REAGENTS_METABOLISM
+ overdose_threshold = 40
/datum/reagent/medicine/synthflesh/reaction_mob(mob/living/M, method=TOUCH, reac_volume,show_message = 1)
if(iscarbon(M))
if (M.stat == DEAD)
show_message = 0
- if(method in list(PATCH, TOUCH))
- M.adjustBruteLoss(-1.25 * reac_volume)
- M.adjustFireLoss(-1.25 * reac_volume)
+ if(method in list(INGEST, VAPOR))
+ var/mob/living/carbon/C = M
+ C.losebreath++
+ C.emote("cough")
+ to_chat(M, "You feel your throat closing up!")
+ else if(method == INJECT)
+ return
+ else if(method in list(PATCH, TOUCH))
+ M.adjustBruteLoss(-1 * reac_volume)
+ M.adjustFireLoss(-1 * reac_volume)
if(show_message)
to_chat(M, "You feel your burns and bruises healing! It stings like hell!")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine)
..()
+/datum/reagent/medicine/synthflesh/overdose_start(mob/living/M)
+ metabolization_rate = 15 * REAGENTS_METABOLISM
+
/datum/reagent/medicine/charcoal
name = "Charcoal"
id = "charcoal"
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 409ba76d..aebeed65 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -1586,17 +1586,20 @@
name = "anomolous virus food"
color = "#ffa6ff" //rgb: 255,166,255
taste_description = "a bad idea"
-
+ id = "laughtervirusfood"
+
/datum/reagent/consumable/virus_food/advvirusfood
name = "highly unstable virus food"
color = "#ffffff" //rgb: 255,255,255 ITS PURE WHITE CMON
taste_description = "an EXTREMELY bad idea"
+ id = "advvirusfood"
/datum/reagent/consumable/virus_food/viralbase
name = "Experimental viral base"
description = "Recently discovered by Nanotrasen's top scientists after years of research, this substance can be used as the base for extremely rare and extremely dangerous viruses once exposed to uranium."
color = "#fff0da"
taste_description = "tears of scientists"
+ id = "viralbase"
/datum/reagent/colorful_reagent/on_mob_life(mob/living/carbon/M)
if(!no_mob_color)
@@ -2148,7 +2151,7 @@
can_synth = FALSE
var/datum/dna/original_dna
var/reagent_ticks = 0
- invisible = TRUE
+ chemical_flags = REAGENT_INVISIBLE
/datum/reagent/changeling_string/on_mob_metabolize(mob/living/carbon/C)
if(C && C.dna && data["desired_dna"])
diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm
index 32155c9b..a9150874 100644
--- a/code/modules/reagents/chemistry/recipes.dm
+++ b/code/modules/reagents/chemistry/recipes.dm
@@ -32,6 +32,7 @@
var/RateUpLim = 10 // Optimal/max rate possible if all conditions are perfect
var/FermiChem = FALSE // If the chemical uses the Fermichem reaction mechanics//If the chemical uses the Fermichem reaction mechanics
var/FermiExplode = FALSE // If the chemical explodes in a special way
+ var/clear_conversion //bitflags for clear conversions; REACTION_CLEAR_IMPURE or REACTION_CLEAR_INVERSE
var/PurityMin = 0.15 //If purity is below 0.15, it explodes too. Set to 0 to disable this.
diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm
index d5692d3b..ff520378 100644
--- a/code/modules/reagents/chemistry/recipes/others.dm
+++ b/code/modules/reagents/chemistry/recipes/others.dm
@@ -234,7 +234,7 @@
name = "Anomolous virus food"
id = "virusfood_laughter"
results = list("laughtervirusfood" = 1)
- required_reagents = list("laughter" = 5, "virus_food" = 1)
+ required_reagents = list("laughter" = 5, "virusfood" = 1)
/datum/chemical_reaction/virus_food_admin
name = "Highly unstable virus Food"
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index 93a8f1f5..5521c40c 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -17,6 +17,7 @@
var/spillable = FALSE
var/beaker_weakness_bitflag = NONE//Bitflag!
var/container_HP = 2
+ var/cached_icon
var/splashable = FALSE
/obj/item/reagent_containers/Initialize(mapload, vol)
@@ -83,11 +84,11 @@
SplashReagents(target, TRUE)
/obj/item/reagent_containers/proc/bartender_check(atom/target)
- . = FALSE
if(target.CanPass(src, get_turf(src)) && thrownby && thrownby.actions)
for(var/datum/action/innate/drink_fling/D in thrownby.actions)
if(D.active)
return TRUE
+ return FALSE
/obj/item/reagent_containers/proc/ForceResetRotation()
transform = initial(transform)
@@ -149,30 +150,71 @@
/obj/item/reagent_containers/proc/temp_check()
if(beaker_weakness_bitflag & TEMP_WEAK)
if(reagents.chem_temp >= 444)//assuming polypropylene
- var/list/seen = viewers(5, get_turf(src))
- var/iconhtml = icon2html(src, seen)
- for(var/mob/M in seen)
- to_chat(M, "[iconhtml] \The [src]'s melts from the temperature!")
- playsound(get_turf(src), 'sound/FermiChem/heatmelt.ogg', 80, 1)
- to_chat(M, "[iconhtml] Have you tried using glass or meta beakers for high temperature reactions? These are immune to temperature effects.")
- SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times beakers have melted from temperature")
- qdel(src)
+ START_PROCESSING(SSobj, src)
//melts glass beakers
/obj/item/reagent_containers/proc/pH_check()
if(beaker_weakness_bitflag & PH_WEAK)
- if((reagents.pH < 0.5) || (reagents.pH > 13.5))
- var/list/seen = viewers(5, get_turf(src))
- var/iconhtml = icon2html(src, seen)
- container_HP--
- if(container_HP <= 0)
- for(var/mob/M in seen)
- to_chat(M, "[iconhtml] \The [src]'s melts from the extreme pH!")
- playsound(get_turf(src), 'sound/FermiChem/acidmelt.ogg', 80, 1)
- SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times beakers have melted from pH")
- qdel(src)
+ if((reagents.pH < 1.5) || (reagents.pH > 12.5))
+ START_PROCESSING(SSobj, src)
+
+
+/obj/item/reagent_containers/process()
+ if(!cached_icon)
+ cached_icon = icon_state
+ var/damage
+ var/cause
+ if(beaker_weakness_bitflag & PH_WEAK)
+ if(reagents.pH < 2)
+ damage = (2 - reagents.pH)/20
+ cause = "from the extreme pH"
+ playsound(get_turf(src), 'sound/FermiChem/bufferadd.ogg', 50, 1)
+
+ if(reagents.pH > 12)
+ damage = (reagents.pH - 12)/20
+ cause = "from the extreme pH"
+ playsound(get_turf(src), 'sound/FermiChem/bufferadd.ogg', 50, 1)
+
+ if(beaker_weakness_bitflag & TEMP_WEAK)
+ if(reagents.chem_temp >= 444)
+ if(damage)
+ damage += (reagents.chem_temp/444)/5
else
- for(var/mob/M in seen)
- to_chat(M, "[iconhtml] \The [src]'s is damaged by the extreme pH and begins to deform!")
- playsound(get_turf(src), 'sound/FermiChem/bufferadd.ogg', 50, 1)
- to_chat(M, "[iconhtml] Have you tried using plastic beakers (XL) or metabeakers for high pH reactions? These beakers are immune to pH effects.")
+ damage = (reagents.chem_temp/444)/5
+ if(cause)
+ cause += " and "
+ cause += "from the high temperature"
+ playsound(get_turf(src), 'sound/FermiChem/heatdam.ogg', 50, 1)
+
+ if(!damage || damage <= 0)
+ STOP_PROCESSING(SSobj, src)
+
+ container_HP -= damage
+
+ var/list/seen = viewers(5, get_turf(src))
+ var/iconhtml = icon2html(src, seen)
+
+ var/damage_percent = ((container_HP / initial(container_HP)*100))
+ switch(damage_percent)
+ if(-INFINITY to 0)
+ for(var/mob/M in seen)
+ to_chat(M, "[iconhtml] \The [src]'s melts [cause]!")
+ playsound(get_turf(src), 'sound/FermiChem/acidmelt.ogg', 80, 1)
+ SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times beakers have melted")
+ STOP_PROCESSING(SSobj, src)
+ qdel(src)
+ return
+ if(0 to 35)
+ icon_state = "[cached_icon]_m3"
+ desc = "[initial(desc)] It is severely deformed."
+ if(35 to 70)
+ icon_state = "[cached_icon]_m2"
+ desc = "[initial(desc)] It is deformed."
+ if(70 to 85)
+ desc = "[initial(desc)] It is mildly deformed."
+ icon_state = "[cached_icon]_m1"
+
+ update_icon()
+ if(prob(25))
+ for(var/mob/M in seen)
+ to_chat(M, "[iconhtml] \The [src]'s is damaged by [cause] and begins to deform!")
\ No newline at end of file
diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm
index 31e893aa..3e555f38 100644
--- a/code/modules/reagents/reagent_containers/blood_pack.dm
+++ b/code/modules/reagents/reagent_containers/blood_pack.dm
@@ -90,3 +90,9 @@
update_pack_name()
else
return ..()
+
+/obj/item/reagent_containers/blood/bluespace
+ name = "bluespace blood pack"
+ desc = "Contains blood used for transfusion, this one has been made with bluespace technology to hold much more blood. Must be attached to an IV drip."
+ icon_state = "bsbloodpack"
+ volume = 600 //its a blood bath!
\ No newline at end of file
diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm
index 31b2ea0c..472efb40 100644
--- a/code/modules/reagents/reagent_containers/glass.dm
+++ b/code/modules/reagents/reagent_containers/glass.dm
@@ -6,7 +6,7 @@
reagent_flags = OPENCONTAINER
spillable = TRUE
resistance_flags = ACID_PROOF
- container_HP = 3
+ container_HP = 2
/obj/item/reagent_containers/glass/attack(mob/M, mob/user, obj/target)
@@ -115,7 +115,6 @@
item_state = "beaker"
materials = list(MAT_GLASS=500)
beaker_weakness_bitflag = PH_WEAK
- container_HP = 5
/obj/item/reagent_containers/glass/beaker/Initialize()
. = ..()
@@ -133,27 +132,29 @@
list_reagents = list("viralbase" = 1)
/obj/item/reagent_containers/glass/beaker/update_icon()
+ if(!cached_icon)
+ cached_icon = icon_state
cut_overlays()
if(reagents.total_volume)
- var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "[icon_state]10")
+ var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "[cached_icon]10")
var/percent = round((reagents.total_volume / volume) * 100)
switch(percent)
if(0 to 9)
- filling.icon_state = "[icon_state]-10"
+ filling.icon_state = "[cached_icon]-10"
if(10 to 24)
- filling.icon_state = "[icon_state]10"
+ filling.icon_state = "[cached_icon]10"
if(25 to 49)
- filling.icon_state = "[icon_state]25"
+ filling.icon_state = "[cached_icon]25"
if(50 to 74)
- filling.icon_state = "[icon_state]50"
+ filling.icon_state = "[cached_icon]50"
if(75 to 79)
- filling.icon_state = "[icon_state]75"
+ filling.icon_state = "[cached_icon]75"
if(80 to 90)
- filling.icon_state = "[icon_state]80"
+ filling.icon_state = "[cached_icon]80"
if(91 to INFINITY)
- filling.icon_state = "[icon_state]100"
+ filling.icon_state = "[cached_icon]100"
filling.color = mix_color_from_reagents(reagents.reagent_list)
add_overlay(filling)
@@ -172,7 +173,7 @@
volume = 100
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,20,25,30,50,100)
- container_HP = 6
+ container_HP = 3
/obj/item/reagent_containers/glass/beaker/plastic
name = "x-large beaker"
@@ -232,7 +233,7 @@
volume = 300
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,300)
- container_HP = 8
+ container_HP = 4
/obj/item/reagent_containers/glass/beaker/cryoxadone
list_reagents = list("cryoxadone" = 30)
@@ -289,7 +290,7 @@
SLOT_L_STORE, SLOT_R_STORE,\
SLOT_GENERC_DEXTROUS_STORAGE
)
- container_HP = 2
+ container_HP = 1
/obj/item/reagent_containers/glass/bucket/Initialize()
beaker_weakness_bitflag |= TEMP_WEAK
@@ -343,7 +344,7 @@
materials = list(MAT_GLASS=0)
volume = 50
amount_per_transfer_from_this = 10
- container_HP = 2
+ container_HP = 1
/obj/item/reagent_containers/glass/beaker/waterbottle/Initialize()
beaker_weakness_bitflag |= TEMP_WEAK
@@ -359,7 +360,7 @@
list_reagents = list("water" = 100)
volume = 100
amount_per_transfer_from_this = 20
- container_HP = 2
+ container_HP = 1
/obj/item/reagent_containers/glass/beaker/waterbottle/large/empty
list_reagents = list()
diff --git a/code/modules/reagents/reagent_containers/medspray.dm b/code/modules/reagents/reagent_containers/medspray.dm
index 54a38eef..df7c7af2 100644
--- a/code/modules/reagents/reagent_containers/medspray.dm
+++ b/code/modules/reagents/reagent_containers/medspray.dm
@@ -19,8 +19,8 @@
var/can_fill_from_container = TRUE
var/apply_type = PATCH
var/apply_method = "spray"
- var/self_delay = 30
- var/squirt_mode = 0
+ var/self_delay = 3 SECONDS
+ var/squirt_mode = FALSE
var/squirt_amount = 5
/obj/item/reagent_containers/medspray/attack_self(mob/user)
@@ -31,40 +31,51 @@
amount_per_transfer_from_this = initial(amount_per_transfer_from_this)
to_chat(user, "You will now apply the medspray's contents in [squirt_mode ? "short bursts":"extended sprays"]. You'll now use [amount_per_transfer_from_this] units per use.")
-/obj/item/reagent_containers/medspray/attack(mob/M, mob/user, def_zone)
+/obj/item/reagent_containers/medspray/attack(mob/living/L, mob/user, def_zone)
if(!reagents || !reagents.total_volume)
to_chat(user, "[src] is empty!")
return
- if(M == user)
- M.visible_message("[user] attempts to [apply_method] [src] on [user.p_them()]self.")
+ if(ishuman(L))
+ var/obj/item/bodypart/affecting = L.get_bodypart(check_zone(user.zone_selected))
+ if(!affecting)
+ to_chat(user, "The limb is missing!")
+ return
+ if(!L.can_inject(user, TRUE, user.zone_selected, FALSE, TRUE)) //stopped by clothing, like patches
+ return
+ if(affecting.status != BODYPART_ORGANIC)
+ to_chat(user, "Medicine won't work on a robotic limb!")
+ return
+
+ if(L == user)
+ L.visible_message("[user] attempts to [apply_method] [src] on [user.p_them()]self.")
if(self_delay)
- if(!do_mob(user, M, self_delay))
+ if(!do_mob(user, L, self_delay))
return
if(!reagents || !reagents.total_volume)
return
- to_chat(M, "You [apply_method] yourself with [src].")
+ to_chat(L, "You [apply_method] yourself with [src].")
else
- log_combat(user, M, "attempted to apply", src, reagents.log_list())
- M.visible_message("[user] attempts to [apply_method] [src] on [M].", \
- "[user] attempts to [apply_method] [src] on [M].")
- if(!do_mob(user, M))
+ log_combat(user, L, "attempted to apply", src, reagents.log_list())
+ L.visible_message("[user] attempts to [apply_method] [src] on [L].", \
+ "[user] attempts to [apply_method] [src] on [L].")
+ if(!do_mob(user, L))
return
if(!reagents || !reagents.total_volume)
return
- M.visible_message("[user] [apply_method]s [M] down with [src].", \
- "[user] [apply_method]s [M] down with [src].")
+ L.visible_message("[user] [apply_method]s [L] down with [src].", \
+ "[user] [apply_method]s [L] down with [src].")
if(!reagents || !reagents.total_volume)
return
else
- log_combat(user, M, "applied", src, reagents.log_list())
+ log_combat(user, L, "applied", src, reagents.log_list())
playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6)
var/fraction = min(amount_per_transfer_from_this/reagents.total_volume, 1)
- reagents.reaction(M, apply_type, fraction)
- reagents.trans_to(M, amount_per_transfer_from_this)
+ reagents.reaction(L, apply_type, fraction)
+ reagents.trans_to(L, amount_per_transfer_from_this)
return
/obj/item/reagent_containers/medspray/styptic
diff --git a/code/modules/reagents/reagent_containers/rags.dm b/code/modules/reagents/reagent_containers/rags.dm
index 92a4b155..713b6a62 100644
--- a/code/modules/reagents/reagent_containers/rags.dm
+++ b/code/modules/reagents/reagent_containers/rags.dm
@@ -115,6 +115,8 @@
var/flat_icon = "towel_flat"
var/folded_icon = "towel"
var/list/possible_colors
+ //Hyper Change
+ var/roomy = 1 //To cover XL bits
/obj/item/reagent_containers/rag/towel/Initialize()
. = ..()
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index 871fd32b..1d152f72 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -102,9 +102,17 @@
return ..()
/obj/machinery/disposal/proc/place_item_in_disposal(obj/item/I, mob/user)
- I.forceMove(src)
- user.visible_message("[user.name] places \the [I] into \the [src].", "You place \the [I] into \the [src].")
-
+ if(istype(I, /obj/item/clothing/head/mob_holder))
+ var/obj/item/clothing/head/mob_holder/H = I
+ var/mob/living/m = H.held_mob
+ H.release()
+ if(m)
+ user.start_pulling(m, 1)
+ stuff_mob_in(m,user)
+ return//you don't want this going into disposals ever
+ if(user.temporarilyRemoveItemFromInventory(I)) //double-checks never hurt
+ I.forceMove(src)
+ user.visible_message("[user.name] places \the [I] into \the [src].", "You place \the [I] into \the [src].")
//mouse drop another mob or self
/obj/machinery/disposal/MouseDrop_T(mob/living/target, mob/living/user)
if(istype(target))
diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index b24b0cff..d95f4eeb 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -738,6 +738,13 @@
research_icon_state = "surgery_any"
var/surgery
+/datum/design/surgery/experimental_dissection
+ name = "Experimental Dissection"
+ desc = "A surgical procedure which deeply analyzes the biology of a corpse, and automatically adds new findings to the research database."
+ id = "surgery_exp_dissection"
+ surgery = /datum/surgery/advanced/bioware/experimental_dissection
+ research_icon_state = "surgery_chest"
+
/datum/design/surgery/lobotomy
name = "Lobotomy"
desc = "An invasive surgical procedure which guarantees removal of almost all brain traumas, but might cause another permanent trauma in return."
@@ -808,6 +815,22 @@
surgery = /datum/surgery/advanced/bioware/vein_threading
research_icon_state = "surgery_chest"
+/datum/design/surgery/ligament_hook
+ name = "Ligament Hook"
+ desc = "A surgical procedure which reshapes the connections between torso and limbs, making it so limbs can be attached manually if severed. \
+ However this weakens the connection, making them easier to detach as well."
+ id = "surgery_ligament_hook"
+ surgery = /datum/surgery/advanced/bioware/ligament_hook
+ research_icon_state = "surgery_chest"
+
+/datum/design/surgery/ligament_reinforcement
+ name = "Ligament Reinforcement"
+ desc = "A surgical procedure which adds a protective tissue and bone cage around the connections between the torso and limbs, preventing dismemberment. \
+ However, the nerve connections as a result are more easily interrupted, making it easier to disable limbs with damage."
+ id = "surgery_ligament_reinforcement"
+ surgery = /datum/surgery/advanced/bioware/ligament_reinforcement
+ research_icon_state = "surgery_chest"
+
/datum/design/surgery/necrotic_revival
name = "Necrotic Revival"
desc = "An experimental surgical procedure that stimulates the growth of a Romerol tumor inside the patient's brain. Requires zombie powder or rezadone."
@@ -907,7 +930,15 @@
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
-
+/datum/design/bsblood_bag
+ name = "Blue Space Empty Blood Bag"
+ desc = "A large sterilized plastic bag for blood."
+ id = "bsblood_bag"
+ build_path = /obj/item/reagent_containers/blood/bluespace
+ build_type = PROTOLATHE
+ materials = list(MAT_GLASS = 2500, MAT_PLASTIC = 4500, MAT_BLUESPACE = 250)
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/datum/design/adv_dis_hypo
name = "Disposable Hypospray MK.II"
diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm
index 214ef36a..7dd85ea1 100644
--- a/code/modules/research/designs/weapon_designs.dm
+++ b/code/modules/research/designs/weapon_designs.dm
@@ -17,6 +17,36 @@
id = "sec_38lethal"
build_path = /obj/item/ammo_box/c38/lethal
+/datum/design/c38_trac
+ name = "Speed Loader (.38 TRAC)"
+ desc = "Designed to quickly reload revolvers. TRAC bullets embed a tracking implant within the target's body."
+ id = "c38_trac"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 20000, MAT_SILVER = 5000, MAT_GOLD = 1000)
+ build_path = /obj/item/ammo_box/c38/trac
+ category = list("Ammo")
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY
+
+/datum/design/c38_hotshot
+ name = "Speed Loader (.38 Hot Shot)"
+ desc = "Designed to quickly reload revolvers. Hot Shot bullets contain an incendiary payload."
+ id = "c38_hotshot"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 20000, MAT_PLASMA = 5000)
+ build_path = /obj/item/ammo_box/c38/hotshot
+ category = list("Ammo")
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY
+
+/datum/design/c38_iceblox
+ name = "Speed Loader (.38 Iceblox)"
+ desc = "Designed to quickly reload revolvers. Iceblox bullets contain a cryogenic payload."
+ id = "c38_iceblox"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 20000, MAT_PLASMA = 5000)
+ build_path = /obj/item/ammo_box/c38/iceblox
+ category = list("Ammo")
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY
+
//////////////
//WT550 Mags//
//////////////
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index a9eaf107..843244c5 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -116,7 +116,7 @@
display_name = "Advanced Surgery"
description = "When simple medicine doesn't cut it."
prereq_ids = list("adv_biotech")
- design_ids = list("surgery_lobotomy", "surgery_reconstruction","surgery_toxinhealing", "organbox",)
+ design_ids = list("surgery_lobotomy", "surgery_reconstruction","surgery_toxinhealing", "organbox", "surgery_exp_dissection")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -125,7 +125,7 @@
display_name = "Experimental Surgery"
description = "When evolution isn't fast enough."
prereq_ids = list("adv_surgery")
- design_ids = list("surgery_revival","surgery_pacify","surgery_vein_thread","surgery_nerve_splice","surgery_nerve_ground","surgery_viral_bond")
+ design_ids = list("surgery_revival","surgery_pacify","surgery_vein_thread","surgery_nerve_splice","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_nerve_ground","surgery_viral_bond")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
export_price = 5000
@@ -273,7 +273,7 @@
display_name = "Bluespace Pockets"
description = "Studies into the mysterious alternate dimension known as bluespace and how to place items in the threads of reality."
prereq_ids = list("adv_power", "adv_bluespace", "adv_biotech", "adv_plasma")
- design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding")
+ design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5500)
export_price = 5000
@@ -518,7 +518,7 @@
display_name = "Subdermal Implants"
description = "Electronic implants buried beneath the skin."
prereq_ids = list("biotech", "datatheory")
- design_ids = list("implanter", "implantcase", "implant_chem", "implant_tracking", "locator")
+ design_ids = list("implanter", "implantcase", "implant_chem", "implant_tracking", "locator", "c38_trac")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -694,12 +694,12 @@
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750)
export_price = 5000
-/datum/techweb_node/tech_shell
- id = "tech_shell"
- display_name = "Technological Shells"
- description = "They're more technological than regular shot."
+/datum/techweb_node/exotic_ammo
+ id = "exotic_ammo"
+ display_name = "Exotic Ammunition"
+ description = "They won't know what hit em."
prereq_ids = list("weaponry", "ballistic_weapons")
- design_ids = list("techshotshell")
+ design_ids = list("techshotshell", "c38_hotshot", "c38_iceblox")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500)
export_price = 5000
@@ -1017,7 +1017,7 @@
prereq_ids = list("biotech","engineering")
boost_item_paths = list(/obj/item/gun/energy/alien, /obj/item/scalpel/alien, /obj/item/hemostat/alien, /obj/item/retractor/alien, /obj/item/circular_saw/alien,
/obj/item/cautery/alien, /obj/item/surgicaldrill/alien, /obj/item/screwdriver/abductor, /obj/item/wrench/abductor, /obj/item/crowbar/abductor, /obj/item/multitool/abductor,
- /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor, /obj/item/stack/sheet/mineral/abductor)
+ /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor, /obj/item/stack/sheet/mineral/abductor, /obj/item/stock_parts/cell/infinite/abductor)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
export_price = 20000
hidden = TRUE
@@ -1031,7 +1031,7 @@
design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery")
boost_item_paths = list(/obj/item/gun/energy/alien, /obj/item/scalpel/alien, /obj/item/hemostat/alien, /obj/item/retractor/alien, /obj/item/circular_saw/alien,
/obj/item/cautery/alien, /obj/item/surgicaldrill/alien, /obj/item/screwdriver/abductor, /obj/item/wrench/abductor, /obj/item/crowbar/abductor, /obj/item/multitool/abductor,
- /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor)
+ /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor, /obj/item/stock_parts/cell/infinite/abductor)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 20000
hidden = TRUE
@@ -1043,7 +1043,7 @@
prereq_ids = list("alientech", "adv_engi")
design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool")
boost_item_paths = list(/obj/item/screwdriver/abductor, /obj/item/wrench/abductor, /obj/item/crowbar/abductor, /obj/item/multitool/abductor,
- /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor)
+ /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor, /obj/item/stock_parts/cell/infinite/abductor)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 20000
hidden = TRUE
@@ -1070,7 +1070,7 @@
/datum/techweb_node/advanced_illegl_ballistics
id = "advanced_illegal_ballistics"
display_name = "Advanced Illegal Ballistics"
- description = "Advanced Ballistic for Illegal weaponds."
+ description = "Advanced Ballistics for Illegal weapons."
design_ids = list("10mm","10mmap","10mminc","10mmhp","pistolm9mm","m45","bolt_clip")
prereq_ids = list("ballistic_weapons","syndicate_basic","explosive_weapons")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 25000) //This gives sec lethal mags/clips for guns form traitors or space.
diff --git a/code/modules/research/xenobiology/crossbreeding/_weapons.dm b/code/modules/research/xenobiology/crossbreeding/_weapons.dm
index 4753abff..1b2f43c5 100644
--- a/code/modules/research/xenobiology/crossbreeding/_weapons.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_weapons.dm
@@ -27,9 +27,9 @@
return 0
charge_tick = 0
var/mob/living/M = loc
- if(istype(M) && M.blood_volume >= 20)
+ if(istype(M) && M.blood_volume >= 5)
charges++
- M.blood_volume -= 20
+ M.blood_volume -= 5
if(charges == 1)
recharge_newshot()
return 1
diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm
index efc80101..0cbb3a82 100644
--- a/code/modules/spells/spell_types/lichdom.dm
+++ b/code/modules/spells/spell_types/lichdom.dm
@@ -57,7 +57,7 @@
new /obj/item/phylactery(marked_item, M.mind)
to_chat(M, "With a hideous feeling of emptiness you watch in horrified fascination as skin sloughs off bone! Blood boils, nerves disintegrate, eyes boil in their sockets! As your organs crumble to dust in your fleshless chest you come to terms with your choice. You're a lich!")
- M.set_species(/datum/species/skeleton)
+ M.set_species(/datum/species/skeleton/space)
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.dropItemToGround(H.w_uniform)
@@ -132,7 +132,7 @@
lich.real_name = mind.name
mind.transfer_to(lich)
mind.grab_ghost(force=TRUE)
- lich.hardset_dna(null,null,lich.real_name,null, new /datum/species/skeleton)
+ lich.hardset_dna(null,null,lich.real_name,null, new /datum/species/skeleton/space)
to_chat(lich, "Your bones clatter and shudder as you are pulled back into this world!")
var/turf/body_turf = get_turf(old_body)
lich.Knockdown(200 + 200*resurrections)
diff --git a/code/modules/spells/spell_types/voice_of_god.dm b/code/modules/spells/spell_types/voice_of_god.dm
index eb895008..86424b81 100644
--- a/code/modules/spells/spell_types/voice_of_god.dm
+++ b/code/modules/spells/spell_types/voice_of_god.dm
@@ -11,7 +11,7 @@
var/cooldown_mod = 1
var/power_mod = 1
var/list/spans = list("colossus","yell")
- var/speech_sound = 'sound/magic/clockwork/invoke_general.ogg'
+ var/invoke_sound = 'sound/magic/clockwork/invoke_general.ogg'
/obj/effect/proc_holder/spell/voice_of_god/can_cast(mob/user = usr)
if(!user.can_speak())
@@ -31,7 +31,7 @@
..()
/obj/effect/proc_holder/spell/voice_of_god/cast(list/targets, mob/user = usr)
- playsound(get_turf(user), speech_sound, 300, 1, 5)
+ playsound(get_turf(user), invoke_sound, 300, 1, 5)
var/cooldown = voice_of_god(uppertext(command), user, spans, base_multiplier = power_mod)
charge_max = (cooldown * cooldown_mod)
@@ -41,4 +41,4 @@
power_mod = 0.1
cooldown_mod = 0.5
spans = list("clown")
- speech_sound = 'sound/spookoween/scary_horn2.ogg'
\ No newline at end of file
+ invoke_sound = 'sound/spookoween/scary_horn2.ogg'
\ No newline at end of file
diff --git a/code/modules/surgery/advanced/bioware/experimental_dissection..dm b/code/modules/surgery/advanced/bioware/experimental_dissection..dm
new file mode 100644
index 00000000..6266480b
--- /dev/null
+++ b/code/modules/surgery/advanced/bioware/experimental_dissection..dm
@@ -0,0 +1,72 @@
+/datum/surgery/advanced/bioware/experimental_dissection
+ name = "Experimental Dissection"
+ desc = "A surgical procedure which deeply analyzes the biology of a corpse, and automatically adds new findings to the research database."
+ steps = list(/datum/surgery_step/incise,
+ /datum/surgery_step/retract_skin,
+ /datum/surgery_step/clamp_bleeders,
+ /datum/surgery_step/incise,
+ /datum/surgery_step/dissection,
+ /datum/surgery_step/close)
+ possible_locs = list(BODY_ZONE_CHEST)
+ bioware_target = BIOWARE_DISSECTION
+
+/datum/surgery/advanced/bioware/experimental_dissection/can_start(mob/user, mob/living/carbon/target)
+ . = ..()
+ if(iscyborg(user))
+ return FALSE //robots cannot be creative
+ //(also this surgery shouldn't be consistently successful, and cyborgs have a 100% success rate on surgery)
+ if(target.stat != DEAD)
+ return FALSE
+
+/datum/surgery_step/dissection
+ name = "dissection"
+ implements = list(/obj/item/scalpel = 60, /obj/item/kitchen/knife = 30, /obj/item/shard = 15)
+ time = 125
+
+/datum/surgery_step/dissection/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You start dissecting [target].",
+ "[user] starts dissecting [target].",
+ "[user] starts dissecting [target].")
+
+/datum/surgery_step/dissection/proc/check_value(mob/living/carbon/target)
+ if(isalienroyal(target))
+ return 10000
+ else if(isalienadult(target))
+ return 5000
+ else if(ismonkey(target))
+ return 1000
+ else if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ if(H.dna && H.dna.species)
+ if(isabductor(H))
+ return 8000
+ if(isgolem(H) || iszombie(H))
+ return 4000
+ if(isjellyperson(H) || ispodperson(H))
+ return 3000
+ return 2000
+
+/datum/surgery_step/dissection/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You dissect [target], and add your discoveries to the research database!",
+ "[user] dissects [target], adding [user.p_their()] discoveries to the research database!",
+ "[user] dissects [target]!")
+ SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = check_value(target)))
+ var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST)
+ target.apply_damage(80, BRUTE, L)
+ new /datum/bioware/dissected(target)
+ return TRUE
+
+/datum/surgery_step/dissection/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You dissect [target], but do not find anything particularly interesting.",
+ "[user] dissects [target], however it seems [user.p_they()] didn't find anything useful.",
+ "[user] dissects [target], but looks a little dissapointed.")
+ SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = (check_value(target) * 0.2)))
+ var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST)
+ target.apply_damage(80, BRUTE, L)
+ new /datum/bioware/dissected(target)
+ return TRUE
+
+/datum/bioware/dissected
+ name = "Dissected"
+ desc = "This body has been dissected and analyzed. It is no longer worth experimenting on."
+ mod_type = BIOWARE_DISSECTION
\ No newline at end of file
diff --git a/code/modules/surgery/advanced/bioware/ligament_hook.dm b/code/modules/surgery/advanced/bioware/ligament_hook.dm
new file mode 100644
index 00000000..2c154436
--- /dev/null
+++ b/code/modules/surgery/advanced/bioware/ligament_hook.dm
@@ -0,0 +1,45 @@
+/datum/surgery/advanced/bioware/ligament_hook
+ name = "Ligament Hook"
+ desc = "A surgical procedure which reshapes the connections between torso and limbs, making it so limbs can be attached manually if severed. \
+ However this weakens the connection, making them easier to detach as well."
+ steps = list(/datum/surgery_step/incise,
+ /datum/surgery_step/retract_skin,
+ /datum/surgery_step/clamp_bleeders,
+ /datum/surgery_step/incise,
+ /datum/surgery_step/incise,
+ /datum/surgery_step/reshape_ligaments,
+ /datum/surgery_step/close)
+ possible_locs = list(BODY_ZONE_CHEST)
+ bioware_target = BIOWARE_LIGAMENTS
+
+/datum/surgery_step/reshape_ligaments
+ name = "reshape ligaments"
+ accept_hand = TRUE
+ time = 125
+
+/datum/surgery_step/reshape_ligaments/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You start reshaping [target]'s ligaments into a hook-like shape.",
+ "[user] starts reshaping [target]'s ligaments into a hook-like shape.",
+ "[user] starts manipulating [target]'s ligaments.")
+
+/datum/surgery_step/reshape_ligaments/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You finish reshaping [target]'s ligaments into a connective hook!",
+ "[user] finishes reshaping [target]'s ligaments into a connective hook!",
+ "[user] finishes manipulating [target]'s ligaments!")
+ new /datum/bioware/hooked_ligaments(target)
+ return TRUE
+
+/datum/bioware/hooked_ligaments
+ name = "Hooked Ligaments"
+ desc = "The ligaments and nerve endings that connect the torso to the limbs are formed into a hook-like shape, so limbs can be attached without requiring surgery, but are easier to sever."
+ mod_type = BIOWARE_LIGAMENTS
+
+/datum/bioware/hooked_ligaments/on_gain()
+ ..()
+ ADD_TRAIT(owner, TRAIT_LIMBATTACHMENT, "ligament_hook")
+ ADD_TRAIT(owner, TRAIT_EASYDISMEMBER, "ligament_hook")
+
+/datum/bioware/hooked_ligaments/on_lose()
+ ..()
+ REMOVE_TRAIT(owner, TRAIT_LIMBATTACHMENT, "ligament_hook")
+ REMOVE_TRAIT(owner, TRAIT_EASYDISMEMBER, "ligament_hook")
\ No newline at end of file
diff --git a/code/modules/surgery/advanced/bioware/ligament_reinforcement.dm b/code/modules/surgery/advanced/bioware/ligament_reinforcement.dm
new file mode 100644
index 00000000..ac034fce
--- /dev/null
+++ b/code/modules/surgery/advanced/bioware/ligament_reinforcement.dm
@@ -0,0 +1,45 @@
+/datum/surgery/advanced/bioware/ligament_reinforcement
+ name = "Ligament Reinforcement"
+ desc = "A surgical procedure which adds a protective tissue and bone cage around the connections between the torso and limbs, preventing dismemberment. \
+ However, the nerve connections as a result are more easily interrupted, making it easier to disable limbs with damage."
+ steps = list(/datum/surgery_step/incise,
+ /datum/surgery_step/retract_skin,
+ /datum/surgery_step/clamp_bleeders,
+ /datum/surgery_step/incise,
+ /datum/surgery_step/incise,
+ /datum/surgery_step/reinforce_ligaments,
+ /datum/surgery_step/close)
+ possible_locs = list(BODY_ZONE_CHEST)
+ bioware_target = BIOWARE_LIGAMENTS
+
+/datum/surgery_step/reinforce_ligaments
+ name = "reinforce ligaments"
+ accept_hand = TRUE
+ time = 125
+
+/datum/surgery_step/reinforce_ligaments/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You start reinforcing [target]'s ligaments.",
+ "[user] starts reinforcing [target]'s ligaments.",
+ "[user] starts manipulating [target]'s ligaments.")
+
+/datum/surgery_step/reinforce_ligaments/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You finish reinforcing [target]'s ligaments!",
+ "[user] finishes reinforcing [target]'s ligaments!",
+ "[user] finishes manipulating [target]'s ligaments!")
+ new /datum/bioware/reinforced_ligaments(target)
+ return TRUE
+
+/datum/bioware/reinforced_ligaments
+ name = "Reinforced Ligaments"
+ desc = "The ligaments and nerve endings that connect the torso to the limbs are protected by a mix of bone and tissues, and are much harder to separate from the body, but are also easier to disable."
+ mod_type = BIOWARE_LIGAMENTS
+
+/datum/bioware/reinforced_ligaments/on_gain()
+ ..()
+ ADD_TRAIT(owner, TRAIT_NODISMEMBER, "reinforced_ligaments")
+ ADD_TRAIT(owner, TRAIT_EASYLIMBDISABLE, "reinforced_ligaments")
+
+/datum/bioware/reinforced_ligaments/on_lose()
+ ..()
+ REMOVE_TRAIT(owner, TRAIT_NODISMEMBER, "reinforced_ligaments")
+ REMOVE_TRAIT(owner, TRAIT_EASYLIMBDISABLE, "reinforced_ligaments")
\ No newline at end of file
diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm
index da8efcab..4a853ff0 100644
--- a/code/modules/surgery/bodyparts/bodyparts.dm
+++ b/code/modules/surgery/bodyparts/bodyparts.dm
@@ -235,7 +235,7 @@
return BODYPART_DISABLED_PARALYSIS
if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NODISMEMBER))
. = disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled
- if((get_damage(TRUE) >= max_damage))
+ if((get_damage(TRUE) >= max_damage) || (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) && (get_damage(TRUE) >= (max_damage * 0.6)))) //Easy limb disable disables the limb at 40% health instead of 0%
return BODYPART_DISABLED_DAMAGE
if(disabled && (get_damage(TRUE) <= (max_damage * 0.5)))
return BODYPART_NOT_DISABLED
@@ -477,7 +477,7 @@
limb.icon_state = "[species_id]_[body_zone]"
// Body markings
- if(!isnull(body_markings))
+ if(body_markings)
if(species_id == "husk")
marking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[body_zone]", -MARKING_LAYER, image_dir)
else if(species_id == "husk" && use_digitigrade)
@@ -497,7 +497,7 @@
if(aux_zone)
aux = image(limb.icon, "[species_id]_[aux_zone]", -aux_layer, image_dir)
. += aux
- if(!isnull(auxmarking))
+ if(body_markings)
if(species_id == "husk")
auxmarking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[aux_zone]", -aux_layer, image_dir)
else
@@ -591,6 +591,10 @@
icon_state = "default_monkey_chest"
animal_origin = MONKEY_BODYPART
+/obj/item/bodypart/chest/monkey/teratoma
+ icon_state = "teratoma_chest"
+ animal_origin = TERATOMA_BODYPART
+
/obj/item/bodypart/chest/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_chest"
@@ -663,6 +667,10 @@
px_x = -5
px_y = -3
+/obj/item/bodypart/l_arm/monkey/teratoma
+ icon_state = "teratoma_l_arm"
+ animal_origin = TERATOMA_BODYPART
+
/obj/item/bodypart/l_arm/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_l_arm"
@@ -729,6 +737,10 @@
px_x = 5
px_y = -3
+/obj/item/bodypart/r_arm/monkey/teratoma
+ icon_state = "teratoma_r_arm"
+ animal_origin = TERATOMA_BODYPART
+
/obj/item/bodypart/r_arm/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_r_arm"
@@ -787,6 +799,10 @@
animal_origin = MONKEY_BODYPART
px_y = 4
+/obj/item/bodypart/l_leg/monkey/teratoma
+ icon_state = "teratoma_l_leg"
+ animal_origin = TERATOMA_BODYPART
+
/obj/item/bodypart/l_leg/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_l_leg"
@@ -846,6 +862,10 @@
animal_origin = MONKEY_BODYPART
px_y = 4
+/obj/item/bodypart/r_leg/monkey/teratoma
+ icon_state = "teratoma_r_leg"
+ animal_origin = TERATOMA_BODYPART
+
/obj/item/bodypart/r_leg/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_r_leg"
diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm
index 46ee10a3..9057ceca 100644
--- a/code/modules/surgery/bodyparts/head.dm
+++ b/code/modules/surgery/bodyparts/head.dm
@@ -184,6 +184,10 @@
icon_state = "default_monkey_head"
animal_origin = MONKEY_BODYPART
+/obj/item/bodypart/head/monkey/teratoma
+ icon_state = "teratoma_head"
+ animal_origin = TERATOMA_BODYPART
+
/obj/item/bodypart/head/alien
icon = 'icons/mob/animal_parts.dmi'
icon_state = "alien_head"
diff --git a/code/modules/surgery/breast_augmentation.dm b/code/modules/surgery/breast_augmentation.dm
new file mode 100644
index 00000000..10899dc2
--- /dev/null
+++ b/code/modules/surgery/breast_augmentation.dm
@@ -0,0 +1,78 @@
+/datum/surgery/breast_augmentation
+ name = "Breast augmentation"
+ steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/augment_breasts, /datum/surgery_step/close)
+ species = list(/mob/living/carbon/human)
+ possible_locs = list(BODY_ZONE_CHEST)
+
+/datum/surgery_step/augment_breasts
+ name = "augment breasts"
+ implements = list(/obj/item/scalpel = 100, /obj/item/stack/sheet/plastic = 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.
+ time = 32
+ repeatable = TRUE
+
+/datum/surgery_step/augment_breasts/tool_check(mob/user, obj/item/tool)
+ if(istype(tool, /obj/item/cautery) || istype(tool, /obj/item/gun/energy/laser))
+ return FALSE
+ return !tool.is_hot()
+
+/datum/surgery_step/augment_breasts/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ //Patient has titties
+ if(target.has_breasts())
+ if(tool.is_sharp())
+ display_results(user, target, "You begin to cut the excess out of [target]'s breasts, bringing them down a cup size...",
+ "[user] begins to augment [target]'s breasts.",
+ "[user] begins to augment [target]'s breasts.")
+ if(istype(tool, /obj/item/stack/sheet/plastic))
+ display_results(user, target, "You begin to mold, shape, and then add plastic to [target]'s breasts, increasing their cup size by 1...",
+ "[user] begins to augment [target]'s breasts.",
+ "[user] begins to augment [target]'s breasts.")
+ //Patient does not have titties
+ else
+ if(istype(tool, /obj/item/stack/sheet/plastic))
+ display_results(user, target, "You begin to remodel [target]'s chest, creating a new pair of breasts which are barely A cups...",
+ "[user] begins to perform plastic surgery on [target].",
+ "[user] begins to perform plastic surgery on [target].")
+
+/datum/surgery_step/augment_breasts/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/obj/item/organ/genital/breasts/B = target.getorganslot("breasts")
+ //Patient has titties
+ if(B)
+ //Reduce their size (you fucking monster)
+ if(tool.is_sharp())
+ B.cached_size = B.cached_size - 1
+ B.update()
+ return 1
+ //Increase the size (that's more like it!)
+ if(istype(tool, /obj/item/stack/sheet/plastic))
+ var/obj/item/stack/sheet/plastic/pS = tool
+ pS.amount = pS.amount - 1
+ if(pS.amount < 1)
+ pS.Destroy()
+
+ B.cached_size = B.cached_size + 1
+ B.update()
+ return 1
+ //Patient does not have titties
+ else
+ //Give 'em titties
+ if(istype(tool, /obj/item/stack/sheet/plastic))
+ //Makes it so no one has any weird coloured tits
+ var/mob/living/carbon/human/H = target
+ if(H.dna.species.use_skintones)
+ H.dna.features["breasts_color"] = skintone2hex(H.skin_tone)
+ else
+ H.dna.features["breasts_color"] = H.dna.features["mcolor"]
+
+ var/obj/item/stack/sheet/plastic/pS = tool
+ pS.amount = pS.amount - 1
+ if(pS.amount < 1)
+ pS.Destroy()
+
+ var/obj/item/organ/genital/breasts/nB = new
+ nB.size = "flat"
+ nB.cached_size = 0
+ nB.prev_size = 0
+ nB.Insert(target)
+ nB.update()
+ return 1
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 95258c70..9d1c0e0c 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -374,3 +374,7 @@
name = "insect eyes"
desc = "These eyes seem to have increased sensitivity to bright light, with no improvement to low light vision."
flash_protect = -1
+
+/obj/item/organ/eyes/ipc
+ name = "ipc eyes"
+ icon_state = "cybernetic_eyeballs"
\ No newline at end of file
diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm
index 0f9017fb..977a33b8 100644
--- a/code/modules/surgery/organs/heart.dm
+++ b/code/modules/surgery/organs/heart.dm
@@ -210,7 +210,10 @@ obj/item/organ/heart/cybernetic/upgraded/on_life()
addtimer(VARSET_CALLBACK(src, dose_available, TRUE), 5 MINUTES)
ramount = 0
-
+/obj/item/organ/heart/ipc
+ name = "IPC heart"
+ desc = "An electronic pump that regulates hydraulic functions, the electronics have EMP shielding."
+ icon_state = "heart-c"
/obj/item/organ/heart/freedom
name = "heart of freedom"
diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm
index bfffe9b6..3c80838f 100644
--- a/code/modules/surgery/organs/liver.dm
+++ b/code/modules/surgery/organs/liver.dm
@@ -96,6 +96,10 @@
icon_state = "liver-p"
desc = "A large crystal that is somehow capable of metabolizing chemicals, these are found in plasmamen."
+/obj/item/organ/liver/ipc
+ name = "reagent processing liver"
+ icon_state = "liver-c"
+
/obj/item/organ/liver/cybernetic
name = "cybernetic liver"
icon_state = "liver-c"
diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm
index d3805c5c..5452a1aa 100644
--- a/code/modules/surgery/organs/lungs.dm
+++ b/code/modules/surgery/organs/lungs.dm
@@ -2,6 +2,7 @@
/obj/item/organ/lungs
name = "lungs"
+ desc = "Looking at them makes you start manual breathing."
icon_state = "lungs"
zone = BODY_ZONE_CHEST
slot = ORGAN_SLOT_LUNGS
@@ -461,6 +462,10 @@
S.reagents.add_reagent("salbutamol", 5)
return S
+/obj/item/organ/lungs/ipc
+ name = "ipc lungs"
+ icon_state = "lungs-c"
+
/obj/item/organ/lungs/plasmaman
name = "plasma filter"
desc = "A spongy rib-shaped mass for filtering plasma from the air."
diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm
index 93210fe3..1d1aa3d6 100644
--- a/code/modules/surgery/organs/stomach.dm
+++ b/code/modules/surgery/organs/stomach.dm
@@ -96,3 +96,7 @@
name = "digestive crystal"
icon_state = "stomach-p"
desc = "A strange crystal that is responsible for metabolizing the unseen energy force that feeds plasmamen."
+
+/obj/item/organ/stomach/ipc
+ name = "ipc stomach"
+ icon_state = "stomach-ipc"
\ No newline at end of file
diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm
index 914c8cad..f09d61e5 100644
--- a/code/modules/surgery/organs/tongue.dm
+++ b/code/modules/surgery/organs/tongue.dm
@@ -212,6 +212,8 @@
phomeme_type = pick(phomeme_types)
/obj/item/organ/tongue/bone/applyOrganDamage(var/d, var/maximum = maxHealth)
+ if(d < 0)
+ return
if(!owner)
return
var/target = owner.get_bodypart(BODY_ZONE_HEAD)
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm
index 009cfce0..df8ce65b 100644
--- a/code/modules/surgery/organs/vocal_cords.dm
+++ b/code/modules/surgery/organs/vocal_cords.dm
@@ -1105,7 +1105,8 @@
//teir 2
- /* removed for now
+ //removed for now
+ //Hyper change - Unremoved for now
//ORGASM
else if((findtext(message, orgasm_words)))
for(var/V in listeners)
@@ -1122,7 +1123,7 @@
E.cooldown += 6
else
H.throw_at(get_step_towards(user,H), 3 * power_multiplier, 1 * power_multiplier)
- */
+
//awoo
diff --git a/code/modules/surgery/penis_augmentation.dm b/code/modules/surgery/penis_augmentation.dm
new file mode 100644
index 00000000..fc431e69
--- /dev/null
+++ b/code/modules/surgery/penis_augmentation.dm
@@ -0,0 +1,78 @@
+/datum/surgery/penis_augmentation
+ name = "Penis augmentation"
+ steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/augment_penis, /datum/surgery_step/close)
+ species = list(/mob/living/carbon/human)
+ possible_locs = list(BODY_ZONE_PRECISE_GROIN)
+
+/datum/surgery_step/augment_penis
+ name = "augment penis"
+ implements = list(/obj/item/scalpel = 100, /obj/item/stack/sheet/plastic = 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.
+ time = 32
+ repeatable = TRUE
+
+/datum/surgery_step/augment_penis/tool_check(mob/user, obj/item/tool)
+ if(istype(tool, /obj/item/cautery) || istype(tool, /obj/item/gun/energy/laser))
+ return FALSE
+ return !tool.is_hot()
+
+/datum/surgery_step/augment_penis/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ //Patient has a cock
+ if(target.has_penis())
+ if(tool.is_sharp())
+ display_results(user, target, "You begin to reshape [target]'s penis, decreasing it's length by an inch...",
+ "[user] begins to augment [target]'s penis.",
+ "[user] begins to augment [target]'s penis.")
+ if(istype(tool, /obj/item/stack/sheet/plastic))
+ display_results(user, target, "You begin to mold, shape, and then add plastic to [target]'s penis, making it one inch bigger...",
+ "[user] begins to augment [target]'s penis.",
+ "[user] begins to augment [target]'s penis.")
+ //Patient does not have a cock
+ else
+ if(istype(tool, /obj/item/stack/sheet/plastic))
+ display_results(user, target, "You begin to remodel [target]'s groin, creating a new penis of length 1 inch...",
+ "[user] begins to perform plastic surgery on [target].",
+ "[user] begins to perform plastic surgery on [target].")
+
+/datum/surgery_step/augment_penis/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/obj/item/organ/genital/penis/P = target.getorganslot("penis")
+ //Patient has a cock
+ if(P)
+ //Reduce their size
+ if(tool.is_sharp())
+ P.cached_length = P.cached_length - 1
+ P.update()
+ return 1
+ //Increase the size
+ if(istype(tool, /obj/item/stack/sheet/plastic))
+ var/obj/item/stack/sheet/plastic/pS = tool
+ pS.amount = pS.amount - 1
+ if(pS.amount < 1)
+ pS.Destroy()
+
+ P.cached_length = P.cached_length + 1
+ P.update()
+ return 1
+ //Patient does not have a cock
+ else
+ //Give 'em a cock
+ if(istype(tool, /obj/item/stack/sheet/plastic))
+ //Makes it so no one has a weird coloured dick
+ var/mob/living/carbon/human/H = target
+ if(H.dna.species.use_skintones)
+ H.dna.features["penis_color"] = skintone2hex(H.skin_tone)
+ else
+ H.dna.features["penis_color"] = H.dna.features["mcolor"]
+
+ var/obj/item/stack/sheet/plastic/pS = tool
+ pS.amount = pS.amount - 1
+ if(pS.amount < 1)
+ pS.Destroy()
+
+ var/obj/item/organ/genital/penis/nP = new
+ nP.length = 1
+ nP.cached_length = 1
+ nP.prev_length = 0
+ nP.Insert(target)
+ nP.update()
+ return 1
diff --git a/code/modules/tooltip/tooltip.html b/code/modules/tooltip/tooltip.html
index 3e2f26a0..3cab68da 100644
--- a/code/modules/tooltip/tooltip.html
+++ b/code/modules/tooltip/tooltip.html
@@ -122,8 +122,8 @@
//Get the real icon size according to the client view
var mapWidth = map['view-size'].x,
mapHeight = map['view-size'].y,
- tilesShown = tooltip.client_view_w
- realIconSize = mapWidth / tilesShown,
+ tilesShown = tooltip.client_view_h
+ realIconSize = mapHeight / tilesShown,
resizeRatio = realIconSize / tooltip.tileSize,
//Calculate letterboxing offsets
leftOffset = (map.size.x - mapWidth) / 2,
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index 781fdb24..f93bdbae 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -767,9 +767,15 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
desc = "A speed loader that contains seven additional .357 Magnum rounds; usable with the Syndicate revolver. \
For when you really need a lot of things dead."
item = /obj/item/ammo_box/a357
- cost = 4
+ cost = 3
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
+/datum/uplink_item/ammo/revolver/ap
+ name = ".357 Armor Piercing Speed Loader"
+ desc = "A speed loader that contains seven additional .357 AP Magnum rounds; usable with the Syndicate revolver. \
+ Cuts through like a hot knife through butter."
+ item = /obj/item/ammo_box/a357/ap
+
/datum/uplink_item/ammo/a40mm
name = "40mm Grenade"
desc = "A 40mm HE grenade for use with the M-90gl's under-barrel grenade launcher. \
@@ -1487,9 +1493,10 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
/datum/uplink_item/device_tools/singularity_beacon
name = "Power Beacon"
desc = "When screwed to wiring attached to an electric grid and activated, this large device pulls any \
- active gravitational singularities or tesla balls towards it. This will not work when the engine is still \
- in containment. Because of its size, it cannot be carried. Ordering this \
- sends you a small beacon that will teleport the larger beacon to your location upon activation."
+ active gravitational singularities or tesla balls towards it (provided they are not safely \
+ contained), as well as increasing the odds of incoming meteor waves. \
+ Because of its size, it cannot be carried. Ordering this sends you a small beacon \
+ that will teleport the larger beacon to your location upon activation."
item = /obj/item/sbeacondrop
cost = 14
diff --git a/code/modules/vending/clothesmate.dm b/code/modules/vending/clothesmate.dm
index 0e4252bb..4c77e09f 100644
--- a/code/modules/vending/clothesmate.dm
+++ b/code/modules/vending/clothesmate.dm
@@ -130,7 +130,8 @@
/obj/item/clothing/suit/jacket/leather/overcoat = 4,
/obj/item/clothing/under/pants/mustangjeans = 3,
/obj/item/clothing/neck/necklace/dope = 5,
- /obj/item/clothing/suit/jacket/letterman_nanotrasen = 5)
+ /obj/item/clothing/suit/jacket/letterman_nanotrasen = 5,
+ /obj/item/bluespace_thread = 3)
refill_canister = /obj/item/vending_refill/clothing
/obj/item/vending_refill/clothing
diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm
index 9cd59bde..83607cf7 100644
--- a/code/modules/vending/wardrobes.dm
+++ b/code/modules/vending/wardrobes.dm
@@ -63,7 +63,7 @@
product_ads = "Guaranteed to protect your feet from industrial accidents!;Afraid of radiation? Then wear yellow!"
vend_reply = "Thank you for using the EngiDrobe!"
products = list(/obj/item/clothing/accessory/pocketprotector = 5,
- /obj/item/storage/backpack/duffelbag/engineering = 2,
+ /obj/item/storage/backpack/duffelbag/engineering = 3,
/obj/item/storage/backpack/industrial = 3,
/obj/item/storage/backpack/satchel/eng = 3,
/obj/item/clothing/suit/hooded/wintercoat/engineering = 3,
@@ -71,7 +71,8 @@
/obj/item/clothing/under/rank/engineer/skirt = 5,
/obj/item/clothing/suit/hazardvest = 5,
/obj/item/clothing/shoes/workboots = 5,
- /obj/item/clothing/head/hardhat = 5)
+ /obj/item/clothing/head/hardhat = 5,
+ /obj/item/clothing/head/hardhat/weldhat = 3)
refill_canister = /obj/item/vending_refill/wardrobe/engi_wardrobe
/obj/item/vending_refill/wardrobe/engi_wardrobe
@@ -87,7 +88,8 @@
/obj/item/storage/backpack/duffelbag/engineering = 3,
/obj/item/storage/backpack/satchel/eng = 3,
/obj/item/storage/backpack/industrial = 3,
- /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos = 5,
+ /obj/item/clothing/head/hardhat/weldhat/dblue = 3,
+ /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos = 3,
/obj/item/clothing/under/rank/atmospheric_technician = 5,
/obj/item/clothing/under/rank/atmospheric_technician/skirt = 5,
/obj/item/clothing/shoes/sneakers/black = 5)
diff --git a/code/world.dm b/code/world.dm
index ab3b32b6..dc300e06 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -1,3 +1,4 @@
+
//This file is just for the necessary /world definition
//Try looking in game/world.dm
diff --git a/config/config.txt b/config/config.txt
index a6820cef..d6a6f18f 100644
--- a/config/config.txt
+++ b/config/config.txt
@@ -146,9 +146,6 @@ LOG_MANIFEST
## Enable logging pictures
# LOG_PICTURES
-## log cloning actions
-LOG_CLONING
-
##Log camera pictures - Must have picture logging enabled
PICTURE_LOGGING_CAMERA
@@ -245,10 +242,10 @@ CHECK_RANDOMIZER
# WIKIURL http://www.tgstation13.org/wiki
## Rules address
-# RULESURL http://www.tgstation13.org/wiki/Rules
+# RULESURL https://hyperstation13.com/rules
## Github address
-# GITHUBURL https://www.github.com/tgstation/tgstation
+# GITHUBURL https://github.com/quotefox/Hyper-Station-13
## Round specific stats address
## Link to round specific parsed logs; IE statbus. It is appended with the RoundID automatically by ticker/Reboot()
@@ -303,7 +300,7 @@ TICK_LIMIT_MC_INIT 500
#TICKLAG 0.5
##Can also be set as per-second value, the following value is identical to the above.
-FPS 10
+FPS 20
## Comment this out to disable automuting
#AUTOMUTE_ON
diff --git a/goon/browserassets/css/browserOutput.css b/goon/browserassets/css/browserOutput.css
index 58129ac1..f907fcfc 100644
--- a/goon/browserassets/css/browserOutput.css
+++ b/goon/browserassets/css/browserOutput.css
@@ -835,6 +835,7 @@ h1.alert, h2.alert {color: #000000;}
.greentext {color: #00FF00; font-size: 24px;}
.redtext {color: #FF0000; font-size: 24px;}
.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
+.singing {font-family: "Trebuchet MS", cursive, sans-serif; font-style: italic;}
.hypnophrase {color: #202020; font-weight: bold; animation: hypnocolor 1500ms infinite;}
@keyframes hypnocolor {
0% { color: #202020; }
diff --git a/hyperstation/code/mobs/hugbot.dm b/hyperstation/code/mobs/hugbot.dm
new file mode 100644
index 00000000..89d7acbe
--- /dev/null
+++ b/hyperstation/code/mobs/hugbot.dm
@@ -0,0 +1,311 @@
+//HUGBOT
+//HUGBOT PATHFINDING
+//HUGBOT ASSEMBLY
+
+
+/mob/living/simple_animal/bot/hugbot
+ name = "\improper Hugbot"
+ desc = "A little cudly robot. He looks excited."
+ icon = 'hyperstation/icons/mobs/aibots.dmi'
+ icon_state = "hugbot0"
+ density = FALSE
+ anchored = FALSE
+ health = 20
+ maxHealth = 20
+ pass_flags = PASSMOB
+
+ status_flags = (CANPUSH | CANSTUN)
+
+ bot_type = HUG_BOT
+ model = "Hugbot"
+ bot_core_type = /obj/machinery/bot_core/hugbot
+ window_id = "autohug"
+ window_name = "Automatic Hugging Unit v1.0 Alpha"
+ path_image_color = "#FFDDDD"
+
+ base_speed = 4
+
+ var/stationary_mode = 0 //If enabled, the Hugbot will not move automatically.
+ var/mob/living/carbon/patient = null
+ var/mob/living/carbon/oldpatient = null
+ var/last_found = 0
+
+
+/mob/living/simple_animal/bot/hugbot/update_icon()
+ cut_overlays()
+ if(!on)
+ icon_state = "hugbot0"
+ return
+ if(IsStun())
+ icon_state = "hugbota"
+ return
+ if(mode == BOT_HEALING)
+ icon_state = "hugbots[stationary_mode]"
+ return
+ else if(stationary_mode) //Bot has yellow light to indicate stationary mode.
+ icon_state = "hugbot2"
+ else
+ icon_state = "hugbot1"
+
+/mob/living/simple_animal/bot/medbot/Initialize(mapload, new_skin)
+ . = ..()
+ update_icon()
+
+
+/mob/living/simple_animal/bot/hugbot/update_canmove()
+ . = ..()
+ update_icon()
+
+/mob/living/simple_animal/bot/hugbot/bot_reset()
+ ..()
+ update_icon()
+
+/mob/living/simple_animal/bot/hugbot/proc/soft_reset() //Allows the medibot to still actively perform its medical duties without being completely halted as a hard reset does.
+ path = list()
+ patient = null
+ mode = BOT_IDLE
+ last_found = world.time
+ update_icon()
+
+/mob/living/simple_animal/bot/hugbot/set_custom_texts()
+
+ text_hack = "You bypass [name]'s manipulator pressure sensors."
+ text_dehack = "You rewire [name]'s manipulator pressure sensors."
+ text_dehack_fail = "[name] seems damaged and does not respond to reprogramming!"
+
+/mob/living/simple_animal/bot/hugbot/attack_paw(mob/user)
+ return attack_hand(user)
+
+/mob/living/simple_animal/bot/hugbot/get_controls(mob/user)
+ var/dat
+ dat += hack(user)
+ dat += showpai(user)
+ dat += "Hugging Unit Controls v1.0 Alpha
"
+ dat += "Status: [on ? "On" : "Off"] "
+ dat += "Maintenance panel panel is [open ? "opened" : "closed"] "
+ dat += "Behaviour controls are [locked ? "locked" : "unlocked"]"
+ if(!locked || issilicon(user) || IsAdminGhost(user))
+ dat += "Patrol Station: [auto_patrol ? "Yes" : "No"] "
+ dat += "Stationary Mode: [stationary_mode ? "Yes" : "No"] "
+
+ return dat
+
+/mob/living/simple_animal/bot/hugbot/Topic(href, href_list)
+ if(..())
+ return 1
+
+ update_controls()
+ return
+
+/mob/living/simple_animal/bot/hugbot/attackby(obj/item/W as obj, mob/user as mob, params)
+ var/current_health = health
+ ..()
+ if(health < current_health) //if medbot took some damage
+ step_to(src, (get_step_away(src,user)))
+
+/mob/living/simple_animal/bot/hugbot/emag_act(mob/user)
+ ..()
+ if(emagged == 2)
+ if(user)
+ to_chat(user, "You short out [src]'s manipulator pressure sensors.")
+ audible_message("[src]'s arm twitches violently!")
+ flick("medibot_spark", src)
+ playsound(src, "sparks", 75, 1)
+
+
+/mob/living/simple_animal/bot/hugbot/proc/assess_patient(mob/living/carbon/C)
+ //Time to see if they need medical help!
+ if(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_FAKEDEATH)))
+ return FALSE //welp too late for them!
+
+ if(!(loc == C.loc) && !(isturf(C.loc) && isturf(loc)))
+ return FALSE
+
+ if(ishuman(C))
+ var/mob/living/carbon/human/H = C
+ GET_COMPONENT_FROM(mood, /datum/component/mood, H)
+ if(emagged != 2) // EVERYONE GETS HUGS!
+ for(var/datum/mood_event/i in mood.mood_events)
+ if (i.description == "Hugs are nice.\n" )
+ return FALSE
+ else if (C.IsKnockdown())
+ return FALSE
+ return TRUE
+
+ return FALSE
+
+/mob/living/simple_animal/bot/hugbot/process_scan(mob/living/carbon/human/H)
+ if(H.stat == DEAD)
+ return
+
+ if((H == oldpatient) && (world.time < last_found + 200))
+ return
+
+ if(assess_patient(H))
+ last_found = world.time
+ return H
+ else
+ return
+
+/mob/living/simple_animal/bot/hugbot/handle_automated_action()
+ if(!..())
+ return
+
+ if(mode == BOT_HEALING)
+ medicate_patient(patient)
+ return
+
+ if(IsStun())
+ oldpatient = patient
+ patient = null
+ mode = BOT_IDLE
+ update_icon()
+ return
+
+ if(frustration > 8)
+ oldpatient = patient
+ soft_reset()
+
+ if(QDELETED(patient))
+ var/scan_range = (stationary_mode ? 1 : DEFAULT_SCAN_RANGE) //If in stationary mode, scan range is limited to adjacent patients.
+ patient = scan(/mob/living/carbon/human, oldpatient, scan_range)
+ oldpatient = patient
+
+ if(patient && (get_dist(src,patient) <= 1)) //Patient is next to us, begin treatment!
+ if(mode != BOT_HEALING)
+ mode = BOT_HEALING
+ update_icon()
+ frustration = 0
+ medicate_patient(patient)
+ return
+
+ //Patient has moved away from us!
+ else if(patient && path.len && (get_dist(patient,path[path.len]) > 2))
+ path = list()
+ mode = BOT_IDLE
+ last_found = world.time
+
+ else if(stationary_mode && patient) //Since we cannot move in this mode, ignore the patient and wait for another.
+ soft_reset()
+ return
+
+ if(patient && path.len == 0 && (get_dist(src,patient) > 1))
+ path = get_path_to(src, get_turf(patient), /turf/proc/Distance_cardinal, 0, 30,id=access_card)
+ mode = BOT_MOVING
+ if(!path.len) //try to get closer if you can't reach the patient directly
+ path = get_path_to(src, get_turf(patient), /turf/proc/Distance_cardinal, 0, 30,1,id=access_card)
+ if(!path.len) //Do not chase a patient we cannot reach.
+ soft_reset()
+
+ if(path.len > 0 && patient)
+ if(!bot_move(path[path.len]))
+ oldpatient = patient
+ soft_reset()
+ return
+
+ if(path.len > 8 && patient)
+ frustration++
+
+ if(auto_patrol && !stationary_mode && !patient)
+ if(mode == BOT_IDLE || mode == BOT_START_PATROL)
+ start_patrol()
+
+ if(mode == BOT_PATROL)
+ bot_patrol()
+
+ return
+
+/mob/living/simple_animal/bot/hugbot/UnarmedAttack(atom/A)
+ if(iscarbon(A))
+ var/mob/living/carbon/C = A
+ patient = C
+ mode = BOT_HEALING
+ update_icon()
+ medicate_patient(C)
+ update_icon()
+ else
+ ..()
+
+/mob/living/simple_animal/bot/hugbot/proc/medicate_patient(mob/living/carbon/C)
+ if(!on)
+ return
+
+ if(!istype(C))
+ oldpatient = patient
+ soft_reset()
+ return
+
+ if(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_FAKEDEATH)))
+ oldpatient = patient
+ soft_reset()
+ return
+
+ visible_message("[src] hugs [C] to make [C.p_them()] feel better!", \
+ "You hug [C] to make [C.p_them()] feel better!")
+ SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/hug)
+
+ if (emagged != 2)
+ C.AdjustStun(-60)
+ C.AdjustKnockdown(-60)
+ C.AdjustUnconscious(-60)
+ C.AdjustSleeping(-100)
+ if(recoveringstam)
+ C.adjustStaminaLoss(-15)
+ else if(resting)
+ C.resting = 0
+ C.update_canmove()
+ else
+ C.Knockdown(100)
+ C.Stun(100)
+ C.update_canmove()
+
+ playsound(C.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+
+ oldpatient = patient
+ patient = null
+ mode = BOT_IDLE
+ update_icon()
+ return
+
+/mob/living/simple_animal/bot/hugbot/explode()
+ on = FALSE
+ visible_message("[src] blows apart!")
+ do_sparks(3, TRUE, src)
+ ..()
+
+/obj/machinery/bot_core/hugbot
+ req_one_access = list(ACCESS_ROBOTICS)
+
+/obj/item/bot_assembly/hugbot
+ desc = "It's a box of hugs with an arm attached."
+ name = "incomplete hugbot assembly"
+ icon = 'hyperstation/icons/mobs/aibots.dmi'
+ icon_state = "hugbot_arm"
+ created_name = "Hugbot"
+
+/obj/item/bot_assembly/hugbot/attackby(obj/item/W, mob/user, params)
+ ..()
+ if(istype(W, /obj/item/assembly/prox_sensor))
+ if(!can_finish_build(W, user))
+ return
+ var/mob/living/simple_animal/bot/hugbot/A = new(drop_location())
+ A.name = created_name
+ A.robot_arm = W.type
+ to_chat(user, "You add [W] to [src]. Beep boop!")
+ qdel(W)
+ qdel(src)
+
+/obj/item/storage/box/hug/attackby(obj/item/I, mob/user, params)
+ if((istype(I, /obj/item/bodypart/l_arm/robot)) || (istype(I, /obj/item/bodypart/r_arm/robot)))
+ if(contents.len) //prevent accidently deleting contents
+ to_chat(user, "You need to empty [src] out first!")
+ return
+ if(!user.temporarilyRemoveItemFromInventory(I))
+ return
+ qdel(I)
+ to_chat(user, "You add [I] to the [src]! You've got a hugbot assembly now!")
+ var/obj/item/bot_assembly/hugbot/A = new
+ qdel(src)
+ user.put_in_hands(A)
+ else
+ return ..()
diff --git a/hyperstation/code/modules/clothing/head.dm b/hyperstation/code/modules/clothing/head.dm
new file mode 100644
index 00000000..1e5dfe5a
--- /dev/null
+++ b/hyperstation/code/modules/clothing/head.dm
@@ -0,0 +1,8 @@
+/obj/item/clothing/head/maidband
+ name = "maid head-band"
+ desc = "To complete the maid look."
+ icon_state = "maid_head"
+ item_state = "maid_head"
+ icon = 'hyperstation/icons/obj/clothing/head.dmi'
+ alternate_worn_icon = 'hyperstation/icons/mobs/head.dmi'
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
\ No newline at end of file
diff --git a/hyperstation/code/modules/crafting/recipes.dm b/hyperstation/code/modules/crafting/recipes.dm
new file mode 100644
index 00000000..5be10633
--- /dev/null
+++ b/hyperstation/code/modules/crafting/recipes.dm
@@ -0,0 +1,11 @@
+/datum/crafting_recipe/milking_machine
+ name = "Milking Machine"
+ reqs = list(/obj/item/stack/cable_coil = 5, /obj/item/stack/rods = 2, /obj/item/stack/sheet/cardboard = 1, /obj/item/reagent_containers/glass/beaker = 2, /obj/item/stock_parts/manipulator = 1)
+ result = /obj/item/milking_machine
+ tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
+ category = CAT_MISC
+
+/datum/crafting_recipe/milking_machine/penis
+ name = "Penis Milking Machine"
+ reqs = list(/obj/item/stack/cable_coil = 5, /obj/item/stack/rods = 1, /obj/item/stack/sheet/cardboard = 1, /obj/item/reagent_containers/glass/beaker/large = 1, /obj/item/stock_parts/manipulator = 1)
+ result = /obj/item/milking_machine/penis
diff --git a/hyperstation/code/modules/resize/holder_micro.dm b/hyperstation/code/modules/resize/holder_micro.dm
new file mode 100644
index 00000000..31193594
--- /dev/null
+++ b/hyperstation/code/modules/resize/holder_micro.dm
@@ -0,0 +1,158 @@
+// Micro Holders - Extends /obj/item/holder... TO:DO, just use most of the already-set procs in inhand_holder.dm
+
+/obj/item/clothing/head/mob_holder/micro
+ name = "micro"
+ desc = "Another person, small enough to fit in your hand."
+ icon = null
+ icon_state = ""
+ slot_flags = ITEM_SLOT_FEET | ITEM_SLOT_HEAD | ITEM_SLOT_ID | ITEM_SLOT_BACK | ITEM_SLOT_NECK
+ w_class = WEIGHT_CLASS_NORMAL
+ can_head = TRUE
+
+/obj/item/clothing/head/mob_holder/micro/Initialize(mapload, mob/living/M, _worn_state, alt_worn, lh_icon, rh_icon, _can_head_override = FALSE)
+ . = ..()
+
+ if(M)
+ M.setDir(SOUTH)
+ held_mob = M
+ M.forceMove(src)
+ appearance = M.appearance
+ name = M.name
+ desc = M.desc
+ assimilate(M)
+
+ if(_can_head_override)
+ can_head = _can_head_override
+ if(alt_worn)
+ alternate_worn_icon = alt_worn
+ if(_worn_state)
+ item_state = _worn_state
+ icon_state = _worn_state
+ if(lh_icon)
+ lefthand_file = lh_icon
+ if(rh_icon)
+ righthand_file = rh_icon
+
+/obj/item/clothing/head/mob_holder/micro/proc/assimilate(mob/living/M)
+ switch(M.mob_size)
+ if(MOB_SIZE_TINY)
+ w_class = WEIGHT_CLASS_TINY
+ if(MOB_SIZE_SMALL)
+ w_class = WEIGHT_CLASS_SMALL
+ if(MOB_SIZE_LARGE)
+ w_class = WEIGHT_CLASS_HUGE
+
+
+/obj/item/clothing/head/mob_holder/micro/Destroy()
+ if(held_mob)
+ release()
+ return ..()
+
+/obj/item/clothing/head/mob_holder/micro/dropped()
+ ..()
+ if(isturf(loc))//don't release on soft-drops
+ release()
+
+/obj/item/clothing/head/mob_holder/micro/relaymove(mob/user)
+ return
+
+//TODO: add a timer to escape someone's grip dependant on size diff
+/obj/item/clothing/head/mob_holder/micro/container_resist()
+ if(isliving(loc))
+ var/mob/living/L = loc
+ visible_message("[src] escapes [L]!")
+ release()
+
+/mob/living/proc/mob_pickup_micro(mob/living/L)
+ var/obj/item/clothing/head/mob_holder/micro/holder = generate_mob_holder()
+ if(!holder)
+ return
+ drop_all_held_items()
+ L.put_in_hands(holder)
+ return
+
+//shoehorned (get it?) and lazy way to do instant foot pickups cause haha funny.
+/mob/living/proc/mob_pickup_micro_feet(mob/living/L)
+ var/obj/item/clothing/head/mob_holder/micro/holder = generate_mob_holder()
+ if(!holder)
+ return
+ drop_all_held_items()
+ L.equip_to_slot(holder, SLOT_SHOES)
+ return
+
+/mob/living/proc/mob_try_pickup_micro(mob/living/user)
+ if(!ishuman(user) || !src.Adjacent(user) || user.incapacitated() || !can_be_held)
+ return FALSE
+ if(abs(user.get_effective_size()/src.get_effective_size()) < 2.0 )
+ to_chat(user, "They're too big to pick up!")
+ return FALSE
+ if(user.get_active_held_item())
+ to_chat(user, "Your hands are full!")
+ return FALSE
+ if(buckled)
+ to_chat(user, "[src] is buckled to something!")
+ return FALSE
+ if(src == user)
+ to_chat(user, "You can't pick yourself up.")
+ return FALSE
+ visible_message("[user] starts picking up [src].", \
+ "[user] starts picking you up!")
+ if(!do_after(user, 20, target = src))
+ return FALSE
+
+ if(user.get_active_held_item()||buckled)
+ return FALSE
+
+ visible_message("[user] picks up [src]!", \
+ "[user] picks you up!")
+ to_chat(user, "You pick [src] up.")
+ mob_pickup_micro(user)
+ return TRUE
+
+/mob/living/AltClick(mob/user)
+ . = ..()
+ if(mob_try_pickup_micro(user))
+ return TRUE
+
+/obj/item/clothing/head/mob_holder/micro/assume_air(datum/gas_mixture/env)
+ var/atom/location = loc
+ if(!loc)
+ return //null
+ var/turf/T = get_turf(loc)
+ while(location != T)
+ location = location.loc
+ if(ismob(location))
+ return location.loc.assume_air(env)
+ return location.assume_air(env)
+
+/obj/item/clothing/head/mob_holder/micro/remove_air(amount)
+ var/atom/location = loc
+ if(!loc)
+ return //null
+ var/turf/T = get_turf(loc)
+ while(location != T)
+ location = location.loc
+ if(ismob(location))
+ return location.loc.remove_air(amount)
+ return location.remove_air(amount)
+
+/obj/item/clothing/head/mob_holder/micro/examine(var/mob/user)
+ for(var/mob/living/M in contents)
+ M.examine(user)
+
+/obj/item/clothing/head/mob_holder/micro/MouseDrop(mob/M as mob)
+ ..()
+ if(M != usr) return
+ if(usr == src) return
+ if(!Adjacent(usr)) return
+ if(istype(M,/mob/living/silicon/ai)) return
+ for(var/mob/living/carbon/human/O in contents)
+ O.show_inv(usr)
+
+/obj/item/clothing/head/mob_holder/micro/attack_self(var/mob/living/user)
+ for(var/mob/living/carbon/human/M in contents)
+ M.help_shake_act(user)
+
+/obj/item/clothing/head/mob_holder/micro/attacked_by(obj/item/I, mob/living/user)
+ for(var/mob/living/carbon/human/M in contents)
+ M.attacked_by(I, user)
diff --git a/hyperstation/code/modules/resize/resizing.dm b/hyperstation/code/modules/resize/resizing.dm
new file mode 100644
index 00000000..86254176
--- /dev/null
+++ b/hyperstation/code/modules/resize/resizing.dm
@@ -0,0 +1,186 @@
+//I am not a coder. Please fucking tear apart my code, and insult me for how awful I am at coding. Please and thank you. -Dahlular
+var/const/RESIZE_MACRO = 6
+var/const/RESIZE_HUGE = 4
+var/const/RESIZE_BIG = 2
+var/const/RESIZE_NORMAL = 1
+var/const/RESIZE_SMALL = 0.75
+var/const/RESIZE_TINY = 0.50
+var/const/RESIZE_MICRO = 0.25
+
+//averages
+var/const/RESIZE_A_MACROHUGE = (RESIZE_MACRO + RESIZE_HUGE) / 2
+var/const/RESIZE_A_HUGEBIG = (RESIZE_HUGE + RESIZE_BIG) / 2
+var/const/RESIZE_A_BIGNORMAL = (RESIZE_BIG + RESIZE_NORMAL) / 2
+var/const/RESIZE_A_NORMALSMALL = (RESIZE_NORMAL + RESIZE_SMALL) / 2
+var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
+var/const/RESIZE_A_TINYMICRO = (RESIZE_TINY + RESIZE_MICRO) / 2
+
+//Scale up a mob's icon by the size_multiplier
+/mob/living/update_transform()
+ ASSERT(!iscarbon(src)) //the source isnt carbon should always be true
+ var/matrix/M = matrix() //matrix (M) variable
+ M.Scale(size_multiplier)
+ M.Translate(0, 16*(size_multiplier-1)) //translate by 16 * size_multiplier - 1 on Y axis
+ src.transform = M //the source of transform is M
+ src.update_mobsize() //Doesn't work yet
+
+/mob/proc/get_effective_size()
+ return 100000
+
+mob/living/get_effective_size()
+ return src.size_multiplier
+
+/mob/living/proc/resize(var/new_size, var/animate = TRUE)
+ if(size_multiplier == new_size)
+ return 1
+
+ size_multiplier = new_size //Change size_multiplier so that other items can interact with them
+ src.update_transform() //WORK DAMN YOU
+
+//handle the big steppy, except nice
+/mob/living/proc/handle_micro_bump_helping(var/mob/living/tmob)
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+
+ //Both small.
+ if(H.get_effective_size() <= RESIZE_A_SMALLTINY && tmob.get_effective_size() <= RESIZE_A_SMALLTINY)
+ now_pushing = 0
+ H.forceMove(tmob.loc)
+ return 1
+
+ //Doing messages
+ if(abs(get_effective_size()/tmob.get_effective_size()) >= 2) //if the initiator is twice the size of the micro
+ now_pushing = 0
+ H.forceMove(tmob.loc)
+
+ //Smaller person being stepped on
+ if(get_effective_size() > tmob.get_effective_size() && iscarbon(src))
+ if(istype(H) && H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle")
+ to_chat(H,"You carefully slither around [tmob].")
+ to_chat(tmob,"[H]'s huge tail slithers beside you!")
+ else
+ to_chat(H,"You carefully step over [tmob].")
+ to_chat(tmob,"[H] steps over you carefully!")
+ return 1
+
+ //Smaller person stepping under a larger person
+ if(tmob.get_effective_size() > get_effective_size())
+ H.forceMove(tmob.loc)
+ now_pushing = 0
+ micro_step_under(tmob)
+ return 1
+
+//Stepping on disarm intent -- TO DO, OPTIMIZE ALL OF THIS SHIT
+/mob/living/proc/handle_micro_bump_other(var/mob/living/tmob)
+ ASSERT(isliving(tmob))
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+
+ //Both small
+ if(H.get_effective_size() <= RESIZE_A_SMALLTINY && tmob.get_effective_size() <= RESIZE_A_SMALLTINY)
+ now_pushing = 0
+ H.forceMove(tmob.loc)
+ return 1
+
+ if(abs(get_effective_size()/tmob.get_effective_size()) >= 2)
+ if(H.a_intent == "disarm" && H.canmove && !H.buckled)
+ now_pushing = 0
+ H.forceMove(tmob.loc)
+ sizediffStamLoss(tmob)
+ if(get_effective_size() > tmob.get_effective_size() && iscarbon(H))
+ if(istype(H) && H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle")
+ to_chat(H,"You carefully roll over [tmob] with your tail!")
+ to_chat(tmob,"[H]'s huge tail rolls over you!")
+ else
+ to_chat(H,"You painfully but harmlessly step on [tmob]!")
+ to_chat(tmob,"[H] steps onto you with force!")
+ return 1
+
+ if(H.a_intent == "harm" && H.canmove && !H.buckled)
+ now_pushing = 0
+ H.forceMove(tmob.loc)
+ sizediffStamLoss(tmob)
+ sizediffBruteloss(tmob)
+ if(get_effective_size() > tmob.get_effective_size() && iscarbon(H))
+ if(istype(H) && H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle")
+ to_chat(H,"You grind [tmob] into the floor with your tail!")
+ to_chat(tmob,"[H]'s massive tail plows you into the floor!")
+ else
+ to_chat(H,"You pound [tmob] into the floor underfoot!")
+ to_chat(tmob,"[H] slams you into the ground, crushing you!")
+ return 1
+
+ if(H.a_intent == "grab" && H.canmove && !H.buckled)
+ now_pushing = 0
+ H.forceMove(tmob.loc)
+ sizediffStamLoss(tmob)
+ sizediffStun(tmob)
+ if(get_effective_size() > tmob.get_effective_size() && iscarbon(H))
+ var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET) || (H.shoes && (H.shoes.body_parts_covered & FEET)))
+ if(feetCover)
+ if(istype(H) && H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle")
+ to_chat(H,"You pin [tmob] underneath your tail!")
+ to_chat(tmob,"[H]'s plows you into the ground, pinning you helplessly!")
+ else
+ to_chat(H,"You pin [tmob] helplessly to the floor with your foot!")
+ to_chat(tmob,"[H] weightfully pins you to the ground!")
+ return 1
+ else
+ if(istype(H) && H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle")
+ to_chat(H,"You curl [tmob] up in the coils of your tail!")
+ to_chat(tmob,"[H]'s tail winds around you and snatches you in its coils!")
+ tmob.mob_pickup_micro_feet(H)
+ else
+ to_chat(H,"You stomp your foot into [tmob], curling your toes and picking them up!")
+ to_chat(tmob,"[H]'s toes pin you down and curl around you, picking you up!'")
+ tmob.mob_pickup_micro_feet(H)
+ return 1
+
+ if(tmob.get_effective_size() > get_effective_size())
+ H.forceMove(tmob.loc)
+ now_pushing = 0
+ micro_step_under(tmob)
+ return 1
+
+//smaller person stepping under another person... TO DO, fix and allow special interactions with naga legs to be seen
+/mob/living/proc/micro_step_under(var/mob/living/tmob)
+ if(istype(tmob) && istype(tmob, /datum/sprite_accessory/taur/naga))
+ to_chat(src,"You jump over [tmob]'s thick tail.")
+ to_chat(tmob,"[src] bounds over your tail.")
+ else
+ to_chat(src,"You run between [tmob]'s legs.")
+ to_chat(tmob,"[src] runs between your legs.")
+
+//Proc for scaling stamina damage on size difference
+/mob/living/proc/sizediffStamLoss(var/mob/living/tmob)
+ var/S = (get_effective_size()/tmob.get_effective_size()*25) //macro divided by micro, times 25
+ tmob.Knockdown(S) //final result in stamina knockdown
+
+//Proc for scaling stuns on size difference (for grab intent)
+/mob/living/proc/sizediffStun(var/mob/living/tmob)
+ var/T = (get_effective_size()/tmob.get_effective_size()*15) //Macro divided by micro, times 15
+ tmob.Stun(T)
+
+//Proc for scaling brute damage on size difference
+/mob/living/proc/sizediffBruteloss(var/mob/living/tmob)
+ var/B = (get_effective_size()/tmob.get_effective_size()*2) //macro divided by micro, times 2
+ tmob.adjustBruteLoss(B) //final result in brute loss
+
+//Proc for changing mob_size to be grabbed for item weight classes
+/mob/living/proc/update_mobsize()
+ if(size_multiplier <= 0.50)
+ mob_size = MOB_SIZE_TINY
+ if(size_multiplier <= 1)
+ mob_size = MOB_SIZE_SMALL
+ if(size_multiplier >= 2)
+ mob_size = MOB_SIZE_LARGE
+
+//Proc for instantly grabbing valid size difference. Code optimizations soon(TM)
+/*
+/mob/living/proc/sizeinteractioncheck(var/mob/living/tmob)
+ if(abs(get_effective_size()/tmob.get_effective_size())>=2.0 && get_effective_size()>tmob.get_effective_size())
+ return 0
+ else
+ return 1
+*/
+//Clothes coming off at different sizes, and health/speed/stam changes as well
diff --git a/hyperstation/code/modules/resize/sizechems.dm b/hyperstation/code/modules/resize/sizechems.dm
new file mode 100644
index 00000000..90deb236
--- /dev/null
+++ b/hyperstation/code/modules/resize/sizechems.dm
@@ -0,0 +1,40 @@
+//Size Chemicals, now with better and less cringy names.
+
+/datum/reagent/dahl/growthchem
+ name = "Prospacillin"
+ id = "growthchem"
+ description = "A stabilized altercation of size-altering liquids, this one appears to increase cell volume."
+ color = "#E70C0C"
+ taste_description = "a sharp, fiery and intoxicating flavour."
+ overdose_threshold = 10
+ metabolization_rate = 0.25
+ can_synth = FALSE //DO NOT MAKE THIS SNYTHESIZABLE, THESE CHEMS ARE SUPPOSED TO NOT BE USED COMMONLY
+
+/datum/reagent/dahl/growthchem/on_mob_add(mob/living/carbon/M)
+ log_game("SIZECODE: [M] ckey: [M.key] has ingested growthchem.")
+
+/datum/reagent/dahl/growthchem/on_mob_life(mob/living/carbon/M)
+ if(M.size_multiplier < RESIZE_MACRO)
+ M.resize(M.size_multiplier+0.01)
+
+ return
+
+/datum/reagent/dahl/shrinkchem
+ name = "Diminicillin"
+ id = "shrinkchem"
+ description = "A stabilized altercation of size-altering liquids, this one appears to decrease cell volume."
+ color = "#0C26E7"
+ taste_description = "a pungent, acidic and jittery flavour."
+ overdose_threshold = 10
+ metabolization_rate = 0.25
+ can_synth = FALSE //SAME STORY AS ABOVE
+
+/datum/reagent/dahl/shrinkchem/on_mob_add(mob/living/carbon/M)
+ log_game("SIZECODE: [M] ckey: [M.key] has ingested shrinkchem.")
+
+/datum/reagent/dahl/shrinkchem/on_mob_life(mob/living/carbon/M)
+ if(M.size_multiplier > RESIZE_MICRO)
+ M.resize(M.size_multiplier-0.01)
+
+ return
+
diff --git a/hyperstation/code/modules/resize/sizegun.dm b/hyperstation/code/modules/resize/sizegun.dm
new file mode 100644
index 00000000..d1154838
--- /dev/null
+++ b/hyperstation/code/modules/resize/sizegun.dm
@@ -0,0 +1,86 @@
+/obj/item/projectile/sizelaser
+ name = "sizeray laser"
+ icon_state = "omnilaser"
+ hitsound = null
+ damage = 5
+ damage_type = STAMINA
+ flag = "laser"
+ pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
+
+/obj/item/projectile/sizelaser/shrinkray
+ icon_state="bluelaser"
+
+/obj/item/projectile/sizelaser/growthray
+ icon_state="laser"
+
+/obj/item/projectile/sizelaser/shrinkray/on_hit(var/atom/target, var/blocked = 0)
+ if(istype(target, /mob/living/carbon/human))
+ var/mob/living/M = target
+ switch(M.size_multiplier)
+ if(RESIZE_MACRO to INFINITY)
+ M.resize(RESIZE_HUGE)
+ if(RESIZE_HUGE to RESIZE_MACRO)
+ M.resize(RESIZE_BIG)
+ if(RESIZE_BIG to RESIZE_HUGE)
+ M.resize(RESIZE_NORMAL)
+ if(RESIZE_NORMAL to RESIZE_BIG)
+ M.resize(RESIZE_SMALL)
+ if(RESIZE_SMALL to RESIZE_NORMAL)
+ M.resize(RESIZE_TINY)
+ if(RESIZE_TINY to RESIZE_SMALL)
+ M.resize(RESIZE_MICRO)
+ if((0 - INFINITY) to RESIZE_NORMAL)
+ M.resize(RESIZE_MICRO)
+ M.update_transform()
+ return 1
+
+/obj/item/projectile/sizelaser/growthray/on_hit(var/atom/target, var/blocked = 0 )
+ if(istype(target, /mob/living/carbon/human))
+ var/mob/living/M = target
+ switch(M.size_multiplier)
+ if(RESIZE_HUGE to RESIZE_MACRO)
+ M.resize(RESIZE_MACRO)
+ if(RESIZE_BIG to RESIZE_HUGE)
+ M.resize(RESIZE_HUGE)
+ if(RESIZE_NORMAL to RESIZE_BIG)
+ M.resize(RESIZE_BIG)
+ if(RESIZE_SMALL to RESIZE_NORMAL)
+ M.resize(RESIZE_NORMAL)
+ if(RESIZE_TINY to RESIZE_SMALL)
+ M.resize(RESIZE_SMALL)
+ if(RESIZE_MICRO to RESIZE_TINY)
+ M.resize(RESIZE_TINY)
+ if((0 - INFINITY) to RESIZE_MICRO)
+ M.resize(RESIZE_MICRO)
+ M.update_transform()
+ return 1
+
+/obj/item/ammo_casing/energy/laser/growthray
+ projectile_type = /obj/item/projectile/sizelaser/growthray
+ select_name = "Growth"
+
+/obj/item/ammo_casing/energy/laser/shrinkray
+ projectile_type = /obj/item/projectile/sizelaser/shrinkray
+ select_name = "Shrink"
+
+//Gun
+/obj/item/gun/energy/laser/sizeray
+ name = "size ray"
+ icon_state = "bluetag"
+ desc = "Debug size manipulator. You probably shouldn't have this!"
+ item_state = null
+ ammo_type = list(/obj/item/ammo_casing/energy/laser/shrinkray, /obj/item/ammo_casing/energy/laser/growthray)
+ selfcharge = EGUN_SELFCHARGE
+ charge_delay = 5
+ ammo_x_offset = 2
+ clumsy_check = 1
+
+ attackby(obj/item/W, mob/user)
+ if(W==src)
+ if(icon_state=="bluetag")
+ icon_state="redtag"
+ ammo_type = list(/obj/item/ammo_casing/energy/laser/growthray)
+ else
+ icon_state="bluetag"
+ ammo_type = list(/obj/item/ammo_casing/energy/laser/shrinkray)
+ return ..()
diff --git a/hyperstation/code/modules/traits.dm b/hyperstation/code/modules/traits.dm
new file mode 100644
index 00000000..136e0892
--- /dev/null
+++ b/hyperstation/code/modules/traits.dm
@@ -0,0 +1,34 @@
+#define TRAIT_CUM_PLUS "cum_plus"
+
+
+//Jay - Coooooom
+/datum/quirk/cum_plus
+ name = "Extra productive genitals"
+ desc = "Your lower bits produce more and hold more than normal."
+ value = 0
+ mob_trait = TRAIT_CUM_PLUS
+ gain_text = "You feel pressure in your groin."
+ lose_text = "You feel a weight lifted from your groin."
+ medical_record_text = "Patient has greatly increased production of sexual fluids"
+
+/datum/quirk/cum_plus/add()
+ var/mob/living/carbon/M = quirk_holder
+ if(M.getorganslot("testicles"))
+ var/obj/item/organ/genital/testicles/T = M.getorganslot("testicles")
+ T.fluid_mult = 1.5 //Base is 1
+ T.fluid_max_volume = 5
+
+/datum/quirk/cum_plus/remove()
+ var/mob/living/carbon/M = quirk_holder
+ if(quirk_holder.getorganslot("testicles"))
+ var/obj/item/organ/genital/testicles/T = M.getorganslot("testicles")
+ T.fluid_mult = 1 //Base is 1
+ T.fluid_max_volume = 3 //Base is 3
+
+/datum/quirk/cum_plus/on_process()
+ var/mob/living/carbon/M = quirk_holder //If you get balls later, then this will still proc
+ if(M.getorganslot("testicles"))
+ var/obj/item/organ/genital/testicles/T = M.getorganslot("testicles")
+ if(T.fluid_max_volume <= 5 || T.fluid_mult <= 0.2) //INVALID EXPRESSION?
+ T.fluid_mult = 1.5 //Base is 0.133
+ T.fluid_max_volume = 5
\ No newline at end of file
diff --git a/hyperstation/code/obj/bluespace sewing kit.dm b/hyperstation/code/obj/bluespace sewing kit.dm
new file mode 100644
index 00000000..7bb4fe72
--- /dev/null
+++ b/hyperstation/code/obj/bluespace sewing kit.dm
@@ -0,0 +1,35 @@
+//Jay Sparrow
+#define ROOMY = "ROOMY"
+
+/obj/item/bluespace_thread
+ name = "Bluespace Sewing Kit"
+ desc = "Thread infused with bluespace dust to make your clothes a little more roomy."
+ icon = 'hyperstation/icons/obj/bluespace_thread.dmi'
+ icon_state = "thread"
+ item_state = "thread"
+ var/uses = 5 //Give it a few charges so it can last through the shift
+ w_class = WEIGHT_CLASS_TINY
+
+/obj/item/bluespace_thread/attack_obj(obj/O, mob/living/user)
+ . = ..()
+ if(!istype(O, /obj/item/clothing))
+ user.show_message("You find yourself unable to stitch this.", 1)
+ return
+
+/obj/item/bluespace_thread/attack_self(mob/living/user)
+ user.show_message("The spool has [uses] uses remaining.", 1)
+
+//Let's add this to the loadout screen
+/datum/gear/bluespace_thread
+ name = "Bluespace Sewing Kit"
+ category = SLOT_IN_BACKPACK
+ path = /obj/item/bluespace_thread
+
+//Crafting recipe
+/datum/crafting_recipe/bluespace_thread
+ name = "Bluespace Sewing Kit"
+ result = /obj/item/bluespace_thread
+ time = 40
+ reqs = list(/obj/item/stack/ore/bluespace_crystal = 1,
+ /obj/item/stack/sheet/cloth = 3)
+ category = CAT_MISC
\ No newline at end of file
diff --git a/hyperstation/code/obj/fluff.dm b/hyperstation/code/obj/fluff.dm
new file mode 100644
index 00000000..43d74459
--- /dev/null
+++ b/hyperstation/code/obj/fluff.dm
@@ -0,0 +1,17 @@
+/obj/structure/medscreen/
+ name = "medical screen"
+ desc = "No peaking now!"
+ icon_state = "screen"
+ icon = 'hyperstation/icons/obj/medical.dmi'
+ anchored = TRUE
+ resistance_flags = FLAMMABLE
+ max_integrity = 100
+ integrity_failure = 30
+ var/buildstacktype = /obj/item/stack/sheet/metal
+ var/buildstackamount = 2
+ density = TRUE
+
+/obj/structure/medscreen/Moved()
+ . = ..()
+ if(has_gravity())
+ playsound(src, 'sound/effects/roll.ogg', 100, 1)
diff --git a/hyperstation/code/obj/kinkyclothes.dm b/hyperstation/code/obj/kinkyclothes.dm
new file mode 100644
index 00000000..209b2dfc
--- /dev/null
+++ b/hyperstation/code/obj/kinkyclothes.dm
@@ -0,0 +1,24 @@
+/obj/item/clothing/gloves/latexsleeves
+ name = "latex sleeves"
+ desc = "A pair of shiny latex sleeves that covers ones arms."
+ icon_state = "latex"
+ item_state = "latex"
+ icon = 'hyperstation/icons/obj/clothing/gloves.dmi'
+ alternate_worn_icon = 'hyperstation/icons/mobs/gloves.dmi'
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
+
+/obj/item/clothing/head/dominatrixcap
+ name = "dominatrix cap"
+ desc = "A sign of authority, over the body."
+ icon_state = "dominatrix"
+ item_state = "dominatrix"
+ icon = 'hyperstation/icons/obj/clothing/head.dmi'
+ alternate_worn_icon = 'hyperstation/icons/mobs/head.dmi'
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
+
+/obj/item/clothing/shoes/highheels
+ name = "high heels"
+ desc = "They make the wearer appear taller, and noisey!"
+ icon_state = "highheels"
+ item_state = "highheels"
+ icon = 'hyperstation/icons/obj/clothing/shoes.dmi'
diff --git a/hyperstation/code/obj/leash.dm b/hyperstation/code/obj/leash.dm
new file mode 100644
index 00000000..75ce8c00
--- /dev/null
+++ b/hyperstation/code/obj/leash.dm
@@ -0,0 +1,403 @@
+//Jay Sparrow
+//TODO
+/*
+Icons, maybe?
+*/
+
+#define STATUS_EFFECT_LEASH_PET /datum/status_effect/leash_pet
+#define STATUS_EFFECT_LEASH_DOM /datum/status_effect/leash_dom
+#define STATUS_EFFECT_LEASH_FREEPET /datum/status_effect/leash_freepet
+#define MOVESPEED_ID_LEASH "LEASH"
+
+/////STATUS EFFECTS/////
+//These are mostly used as flags for the states each member can be in
+
+/datum/status_effect/leash_dom
+ status_type = STATUS_EFFECT_UNIQUE
+ alert_type = /obj/screen/alert/status_effect/leash_dom
+
+/obj/screen/alert/status_effect/leash_dom
+ name = "Leash Master"
+ desc = "You've got a leash, and a cute pet on the other end."
+ icon_state = "leash_master" //These call icons that don't exist, so no icon comes up. Which is good.
+ //As a result, the descriptions also don't proc, which is fine.
+
+/datum/status_effect/leash_freepet
+ status_type = STATUS_EFFECT_UNIQUE
+ alert_type = /obj/screen/alert/status_effect/leash_freepet
+
+/obj/screen/alert/status_effect/leash_freepet
+ name = "Escaped Pet"
+ desc = "You're on a leash, but you've no master. If anyone grabs the leash they'll gain control!"
+ icon_state = "leash_freepet"
+
+
+/datum/status_effect/leash_pet
+ id = "leashed"
+ status_type = STATUS_EFFECT_UNIQUE
+ var/datum/weakref/redirect_component
+ alert_type = /obj/screen/alert/status_effect/leash_pet
+
+/obj/screen/alert/status_effect/leash_pet
+ name = "Leashed Pet"
+ desc = "You're on the hook now! Be good for your master."
+ icon_state = "leash_pet"
+
+
+/datum/status_effect/leash_pet/on_apply()
+ redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/owner_resist))))
+ if(!owner.stat)
+ to_chat(owner, "You have been leashed!")
+ return ..()
+
+//This lets the pet resist their leash
+/datum/status_effect/leash_pet/proc/owner_resist()
+ to_chat(owner, "You reach for the hook on your collar...")
+ //Determine how long it takes to remove the leash
+ var/deleash = 15
+ //if(owner.get_item_by_slot(SLOT_HANDCUFFED)) //Commented out because there is no clear way to make this proc BEFORE decuff on resist.
+ //deleash = 100
+ if(do_mob(owner, owner, deleash))//do_mob creates a progress bar and then enacts the code after. Owner, owner, because it's an act on themself
+ if(!QDELETED(src))
+ to_chat(owner, "[owner] has removed their leash!")
+ owner.remove_status_effect(/datum/status_effect/leash_pet)
+
+///// OBJECT /////
+//The leash object itself
+//The component variables are used for hooks, used later.
+
+/obj/item/leash
+ name = "leash"
+ desc = "A simple tether that can easily be hooked onto a collar. Perfect for your pet."
+ icon = 'hyperstation/icons/obj/leash.dmi'
+ icon_state = "leash"
+ item_state = "leash"
+ throw_range = 4
+ slot_flags = ITEM_SLOT_BELT
+ force = 1
+ throwforce = 1
+ w_class = WEIGHT_CLASS_SMALL
+ var/leash_used = 0 //A flag to see if the leash has been used yet, because for some reason picking up an unused leash is weird
+ var/mob/living/leash_pet = "null" //Variable to store our pet later
+ var/mob/living/leash_master = "null" //And our master too
+ var/datum/component/mobhook_leash_pet
+ var/datum/component/mobhook_leash_master //Needed to watch for these entities to move
+ var/datum/component/mobhook_leash_freepet
+ var/leash_location[3] //Three digit list for us to store coordinates later
+
+//Called when someone is clicked with the leash
+/obj/item/leash/attack(mob/living/carbon/C, mob/living/user) //C is the target, user is the one with the leash
+ if(istype(C.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/petcollar) || istype(C.get_item_by_slot(SLOT_NECK), /obj/item/electropack/shockcollar))
+ var/leashtime = 50
+ if(C.handcuffed)
+ leashtime = 5
+ if(do_mob(user, C, leashtime)) //do_mob adds a progress bar, but then we also check to see if they have a collar
+ log_combat(user, C, "leashed", addition="playfully")
+ //TODO: Figure out how to make an easy breakout for leashed leash_pets
+ C.apply_status_effect(/datum/status_effect/leash_pet)//Has now been leashed
+ user.apply_status_effect(/datum/status_effect/leash_dom) //Is the leasher
+ leash_pet = C //Save pet reference for later
+ leash_master = user //Save dom reference for later
+ mobhook_leash_pet = leash_pet.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_pet_move)))
+ mobhook_leash_master = leash_master.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_master_move)))
+ leash_used = 1
+ if(!leash_pet.has_status_effect(/datum/status_effect/leash_dom)) //Add slowdown if the pet didn't leash themselves
+ leash_pet.add_movespeed_modifier(MOVESPEED_ID_LEASH, multiplicative_slowdown = 5)
+ for(var/mob/viewing in viewers(user, null))
+ if(viewing == leash_master)
+ to_chat(leash_master, "You have hooked a leash onto [leash_pet]!")
+ else
+ viewing.show_message("[leash_pet] has been leashed by [leash_master]!", 1)
+ if(leash_pet.has_status_effect(/datum/status_effect/leash_dom)) //Pet leashed themself. They are not the dom
+ leash_pet.apply_status_effect(/datum/status_effect/leash_freepet)
+ leash_pet.remove_status_effect(/datum/status_effect/leash_dom)
+ while(1) //While true loop. The mark of a genius coder. ##MAINLOOP START
+ sleep(2) //Check every other tick
+ if(leash_pet == "null") //No pet, break loop
+ return
+ if(!(leash_pet.get_item_by_slot(SLOT_NECK))) //The pet has slipped their collar and is not the pet anymore.
+ for(var/mob/viewing in viewers(user, null))
+ viewing.show_message("[leash_pet] has slipped out of their collar!!", 1)
+ to_chat(leash_pet, "You have slipped out of your collar!")
+ to_chat(loc, "[leash_pet] has slipped out of their collar!")
+ leash_pet.remove_status_effect(/datum/status_effect/leash_pet)
+
+ if(!leash_pet.has_status_effect(/datum/status_effect/leash_pet)) //If there is no pet, there is no dom. Loop breaks.
+ QDEL_NULL(mobhook_leash_master)
+ QDEL_NULL(mobhook_leash_pet)
+ QDEL_NULL(mobhook_leash_freepet)
+ if(leash_pet.has_status_effect(/datum/status_effect/leash_freepet))
+ leash_pet.remove_status_effect(/datum/status_effect/leash_freepet)
+ if(leash_pet.has_movespeed_modifier(MOVESPEED_ID_LEASH))
+ leash_pet.remove_movespeed_modifier(MOVESPEED_ID_LEASH)
+ if(!leash_master == "null")
+ leash_master.remove_status_effect(/datum/status_effect/leash_dom)
+ leash_used = 0 //reset the leash to neutral
+ leash_pet = "null"
+ return
+
+ else //No collar, no fun
+ var/leash_message = pick("Your pet needs a collar")
+ to_chat(user, "[leash_message]")
+
+//Called when the leash is used in hand
+//Tugs the pet closer
+/obj/item/leash/attack_self(mob/living/user)
+ if(!leash_pet == "null") //No pet, no tug.
+ return
+ //Yank the pet. Yank em in close.
+ if(leash_pet.x > leash_master.x + 1)
+ step(leash_pet, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
+ if(leash_pet.y > leash_master.y)//Check the other axis, and tug them into alignment so they are behind the master
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.y < leash_master.y)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.x < leash_master.x - 1)
+ step(leash_pet, EAST, 1)
+ if(leash_pet.y > leash_master.y)//Check the other axis, and tug them into alignment so they are behind the master
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.y < leash_master.y)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.y > leash_master.y + 1)
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.x > leash_master.x)//Check the other axis, and tug them into alignment so they are behind the master
+ step(leash_pet, WEST, 1)
+ if(leash_pet.x < leash_master.x)
+ step(leash_pet, EAST, 1)
+ if(leash_pet.y < leash_master.y - 1)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.x > leash_master.x)//Check the other axis, and tug them into alignment so they are behind the master
+ step(leash_pet, WEST, 1)
+ if(leash_pet.x < leash_master.x)
+ step(leash_pet, EAST, 1)
+
+/obj/item/leash/proc/on_master_move()
+ //Make sure the dom still has a pet
+ if(leash_master == "null") //There must be a master
+ return
+ if(leash_pet == "null") //There must be a pet
+ return
+ if(leash_pet == leash_master) //Pet is the master
+ return
+ if(!leash_pet.has_status_effect(/datum/status_effect/leash_pet))
+ QDEL_NULL(mobhook_leash_master) //Probably redundant, but it's nice to be safe
+ leash_master.remove_status_effect(/datum/status_effect/leash_dom)
+ return
+
+ //If the master moves, pull the pet in behind
+ sleep(2) //A small sleep so the pet kind of bounces back after they make the step
+ //Also, the sleep means that the distance check for master happens before the pet, to prevent both from proccing.
+
+ if(leash_master == "null") //Just to stop error messages
+ return
+ if(leash_pet == "null")
+ return
+ if(leash_pet.x > leash_master.x + 2)
+ step(leash_pet, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
+ if(leash_pet.y > leash_master.y)//Check the other axis, and tug them into alignment so they are behind the master
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.y < leash_master.y)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.x < leash_master.x - 2)
+ step(leash_pet, EAST, 1)
+ if(leash_pet.y > leash_master.y)
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.y < leash_master.y)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.y > leash_master.y + 2)
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.x > leash_master.x)
+ step(leash_pet, WEST, 1)
+ if(leash_pet.x < leash_master.x)
+ step(leash_pet, EAST, 1)
+ if(leash_pet.y < leash_master.y - 2)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.x > leash_master.x)
+ step(leash_pet, WEST, 1)
+ if(leash_pet.x < leash_master.x)
+ step(leash_pet, EAST, 1)
+
+ //Knock the pet over if they get further behind. Shouldn't happen too often.
+ sleep(3) //This way running normally won't just yank the pet to the ground.
+ if(leash_master == "null") //Just to stop error messages. Break the loop early if something removed the master
+ return
+ if(leash_pet == "null")
+ return
+ if(leash_pet.x > leash_master.x + 3 || leash_pet.x < leash_master.x - 3 || leash_pet.y > leash_master.y + 3 || leash_pet.y < leash_master.y - 3)
+ //var/leash_knockdown_message = "[leash_pet] got pulled to the ground by their leash!"
+ //to_chat(leash_master, "[leash_knockdown_message]")
+ //to_chat(leash_pet, "[leash_knockdown_message]")
+ leash_pet.apply_effect(20, EFFECT_KNOCKDOWN, 0)
+
+ //This code is to check if the pet has gotten too far away, and then break the leash.
+ sleep(3) //Wait to snap the leash
+ if(leash_master == "null") //Just to stop error messages
+ return
+ if(leash_pet == "null")
+ return
+ if(leash_pet.x > leash_master.x + 5 || leash_pet.x < leash_master.x - 5 || leash_pet.y > leash_master.y + 5 || leash_pet.y < leash_master.y - 5)
+ var/leash_break_message = "The leash snapped free from [leash_pet]!"
+ for(var/mob/viewing in viewers(leash_pet, null))
+ if(viewing == leash_master)
+ to_chat(leash_master, "The leash snapped free from your pet!")
+ if(viewing == leash_pet)
+ to_chat(leash_pet, "Your leash has popped from your collar!")
+ else
+ viewing.show_message("[leash_break_message]", 1)
+ leash_pet.apply_effect(20, EFFECT_KNOCKDOWN, 0)
+ leash_pet.adjustOxyLoss(5)
+ leash_pet.remove_status_effect(/datum/status_effect/leash_pet)
+ leash_pet.remove_movespeed_modifier(MOVESPEED_ID_LEASH)
+ leash_master.remove_status_effect(/datum/status_effect/leash_dom)
+ QDEL_NULL(mobhook_leash_master)
+ QDEL_NULL(mobhook_leash_pet)
+ leash_pet = "null"
+ leash_master = "null"
+ leash_used = 0
+
+/obj/item/leash/proc/on_pet_move()
+ //This should only work if there is a pet and a master.
+ //This is here pretty much just to stop the console from flooding with errors
+ if(leash_master == "null")
+ return
+ if(leash_pet == "null")
+ return
+ //Make sure the pet is still a pet
+ if(!leash_pet.has_status_effect(/datum/status_effect/leash_pet))
+ QDEL_NULL(mobhook_leash_pet) //Probably redundant, but it's nice to be safe
+ return
+
+ //The pet has escaped. There is no DOM. GO PET RUN.
+ if(leash_pet.has_status_effect(/datum/status_effect/leash_freepet))//If the pet is free, break
+ return
+
+ //If the pet gets too far away, they get tugged back
+ sleep(3)//A small sleep so the pet kind of bounces back after they make the step
+ if(leash_master == "null")
+ return
+ if(leash_pet == "null")
+ return
+ //West tug
+ if(leash_pet.x > leash_master.x + 2)
+ step(leash_pet, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
+ //East tug
+ if(leash_pet.x < leash_master.x - 2)
+ step(leash_pet, EAST, 1)
+ //South tug
+ if(leash_pet.y > leash_master.y + 2)
+ step(leash_pet, SOUTH, 1)
+ //North tug
+ if(leash_pet.y < leash_master.y - 2)
+ step(leash_pet, NORTH, 1)
+
+/obj/item/leash/proc/on_freepet_move()
+ . = ..()
+ //Pet is on the run. Let's drag the leash behind them.
+ if(!leash_master == "null") //If there is a master, don't do this
+ return
+ if(leash_pet == "null") //If there is no pet, don't do this
+ return
+ if(leash_pet.is_holding_item_of_type(/obj/item/leash)) //If the pet is holding the leash, don't do this
+ return
+
+ sleep(2)
+ if(leash_pet == "null")
+ return
+ //Double move to catch the leash up to the pet
+ if(src.x > leash_pet.x + 2)
+ . = step(src, WEST, 1)
+ if(src.x < leash_pet.x - 2)
+ . = step(src, EAST, 1)
+ if(src.y > leash_pet.y + 2)
+ . = step(src, SOUTH, 1)
+ if(src.y < leash_pet.y - 2)
+ . = step(src, NORTH, 1)
+ //Primary dragging code
+ if(src.x > leash_pet.x + 1)
+ . = step(src, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
+ if(src.y > leash_pet.y)//Check the other axis, and tug them into alignment so they are behind the pet
+ . = step(src, SOUTH, 1)
+ if(src.y < leash_pet.y)
+ . = step(src, NORTH, 1)
+ if(src.x < leash_pet.x - 1)
+ . = step(src, EAST, 1)
+ if(src.y > leash_pet.y)
+ . = step(src, SOUTH, 1)
+ if(src.y < leash_pet.y)
+ . = step(src, NORTH, 1)
+ if(src.y > leash_pet.y + 1)
+ . = step(src, SOUTH, 1)
+ if(src.x > leash_pet.x)
+ . = step(src, WEST, 1)
+ if(src.x < leash_pet.x)
+ . = step(src, EAST, 1)
+ if(src.y < leash_pet.y - 1)
+ . = step(src, NORTH, 1)
+ if(src.x > leash_pet.x)
+ . = step(src, WEST, 1)
+ if(src.x < leash_pet.x)
+ . = step(src, EAST, 1)
+
+ sleep(1)
+ //Just to prevent error messages
+ if(leash_pet == "null")
+ return
+ if(src.x > leash_pet.x + 5 || src.x < leash_pet.x - 5 || src.y > leash_pet.y + 5 || src.y < leash_pet.y - 5)
+ var/leash_break_message = "The leash snapped free from [leash_pet]!"
+ for(var/mob/viewing in viewers(leash_pet, null))
+ if(viewing == leash_pet)
+ to_chat(leash_pet, "Your leash has popped from your collar!")
+ else
+ viewing.show_message("[leash_break_message]", 1)
+ leash_pet.apply_effect(20, EFFECT_KNOCKDOWN, 0)
+ leash_pet.adjustOxyLoss(5)
+ leash_pet.remove_status_effect(/datum/status_effect/leash_pet)
+ leash_pet.remove_status_effect(/datum/status_effect/leash_freepet)
+ QDEL_NULL(mobhook_leash_pet)
+ QDEL_NULL(mobhook_leash_freepet)
+ leash_pet = "null"
+ leash_used = 0
+
+/obj/item/leash/dropped() //Drop the leash, and the leash effects stop
+ . = ..()
+ if(leash_pet == "null") //There is no pet. Stop this silliness
+ return
+ if(leash_master == "null")
+ return
+ //Dropping procs any time the leash changes slots. So, we will wait a tick and see if the leash was actually dropped
+ sleep(1)
+ if(leash_master.is_holding_item_of_type(/obj/item/leash) || istype(leash_master.get_item_by_slot(SLOT_BELT), /obj/item/leash))
+ return //Dom still has the leash as it turns out. Cancel the proc.
+ for(var/mob/viewing in viewers(leash_master, null))
+ viewing.show_message("[leash_master] has dropped the leash.", 1)
+ //DOM HAS DROPPED LEASH. PET IS FREE. SCP HAS BREACHED CONTAINMENT.
+ leash_pet.remove_movespeed_modifier(MOVESPEED_ID_LEASH)
+ mobhook_leash_freepet = leash_pet.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_freepet_move)))
+ leash_master.remove_status_effect(/datum/status_effect/leash_dom) //No dom with no leash. We will get a new dom if the leash is picked back up.
+ leash_master = "null"
+ QDEL_NULL(mobhook_leash_master)
+
+/obj/item/leash/equipped(mob/user)
+ . = ..()
+ if(leash_used == 0) //Don't apply statuses with a fresh leash. Keeps things clean on the backend.
+ return
+ sleep(2)
+ if(leash_pet == "null")
+ return
+ leash_master = user
+ if(leash_master.has_status_effect(/datum/status_effect/leash_freepet) || leash_master.has_status_effect(/datum/status_effect/leash_pet)) //Pet picked up their own leash.
+ leash_master = "null"
+ return
+ leash_master.apply_status_effect(/datum/status_effect/leash_dom)
+ mobhook_leash_master = leash_master.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_master_move)))
+ leash_pet.remove_status_effect(/datum/status_effect/leash_freepet)
+ QDEL_NULL(mobhook_leash_freepet)
+ leash_pet.add_movespeed_modifier(MOVESPEED_ID_LEASH, multiplicative_slowdown = 5)
+
+/datum/crafting_recipe/leash
+ name = "Leash"
+ result = /obj/item/leash
+ time = 40
+ reqs = list(/obj/item/stack/sheet/metal = 1,
+ /obj/item/stack/sheet/cloth = 3)
+ category = CAT_MISC
\ No newline at end of file
diff --git a/hyperstation/code/obj/milking machine.dm b/hyperstation/code/obj/milking machine.dm
new file mode 100644
index 00000000..5783ad6f
--- /dev/null
+++ b/hyperstation/code/obj/milking machine.dm
@@ -0,0 +1,83 @@
+/obj/item/milking_machine
+ icon = 'hyperstation/icons/obj/milking_machine.dmi'
+ name = "milking machine"
+ icon_state = "Off"
+ item_state = "Off"
+ desc = "A pocket sized pump and tubing assembly designed to collect and store products from mammary glands."
+
+ slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_POCKET
+
+ var/on = FALSE
+ var/obj/item/reagent_containers/glass/inserted_item = null
+
+ var/transfer_rate = 0.25 // How much we transfer every 2 seconds
+ var/target_organ = "breasts" // What organ we are transfering from
+
+/obj/item/milking_machine/examine(mob/user)
+ . = ..()
+ to_chat(user, "[src] is currently [on ? "on" : "off"].")
+ if (inserted_item)
+ to_chat(user, "[inserted_item] contains [inserted_item.reagents.total_volume]/[inserted_item.reagents.maximum_volume] units")
+
+/obj/item/milking_machine/attackby(obj/item/W, mob/user, params)
+ add_fingerprint(user)
+ if(istype(W, /obj/item/reagent_containers/glass) && !inserted_item)
+ if(!user.transferItemToLoc(W, src))
+ return ..()
+ inserted_item = W
+ UpdateIcon()
+ else
+ return ..()
+
+/obj/item/milking_machine/interact(mob/user)
+ if(!isAI(user) && inserted_item)
+ add_fingerprint(user)
+ on = !on
+ if (on)
+ to_chat(user, "You turn [src] on.")
+ START_PROCESSING(SSobj, src)
+ else
+ to_chat(user, "You turn [src] off.")
+ STOP_PROCESSING(SSobj, src)
+ UpdateIcon()
+ else
+ ..()
+
+/obj/item/milking_machine/proc/UpdateIcon()
+ icon_state = "[on ? "On" : "Off"][inserted_item ? "Beaker" : ""]"
+ item_state = icon_state
+
+
+/obj/item/milking_machine/AltClick(mob/living/user)
+ add_fingerprint(user)
+ user.put_in_hands(inserted_item)
+ inserted_item = null
+ on = FALSE
+ STOP_PROCESSING(SSobj, src)
+ UpdateIcon()
+
+/obj/item/milking_machine/process()
+ var/mob/living/carbon/W = loc
+ if (W)
+ var/obj/item/organ/genital/breasts/O = W.getorganslot(target_organ)
+ if (O)
+ if (O.reagents.total_volume >= transfer_rate * 2)
+ if (inserted_item.reagents.total_volume < inserted_item.reagents.maximum_volume)
+ O.reagents.trans_to(inserted_item.reagents, amount = transfer_rate)
+ else
+ to_chat(W, "[src] stops pumping. [inserted_item] is full.")
+ on = FALSE
+ STOP_PROCESSING(SSobj, src)
+ UpdateIcon()
+
+/obj/item/milking_machine/penis
+ name = "penis milking machine"
+ icon_state = "PenisOff"
+ item_state = "PenisOff"
+ desc = "A pocket sized pump and tubing assembly designed to collect and store products from the penis."
+
+ target_organ = "testicles" // Since semen is stored in the balls
+
+/obj/item/milking_machine/penis/UpdateIcon()
+ icon_state = "Penis[on ? "On" : "Off"][inserted_item ? "Beaker" : ""]"
+ item_state = icon_state
diff --git a/hyperstation/code/obj/plushes.dm b/hyperstation/code/obj/plushes.dm
new file mode 100644
index 00000000..fd604f8b
--- /dev/null
+++ b/hyperstation/code/obj/plushes.dm
@@ -0,0 +1,54 @@
+/obj/item/toy/plush/mammal/winfre
+ desc = "An adorable stuffed toy of a pissed hyena. She looks unamused."
+ icon = 'hyperstation/icons/obj/plushes.dmi'
+ icon_state = "winfre"
+ item_state = "winfre"
+ attack_verb = list("cackled", "swirlie'd", "stepped on")
+
+/obj/item/toy/plush/mammal/marilyn
+ desc = "A cute stuffed fox toy. Now, about that sponge bath..."
+ icon = 'hyperstation/icons/obj/plushes.dmi'
+ icon_state = "marilyn"
+ item_state = "marilyn"
+
+/obj/item/toy/plush/mammal/winterbloo
+ name = "Will, the biggest dog"
+ desc = "A plush made to look like a thick as hell shiba, looks a little bigger than average too."
+ icon = 'hyperstation/icons/obj/plushes.dmi'
+ icon_state = "winterbloo"
+ item_state = "winterbloo"
+ attack_verb = list("hugged", "cuddled", "embraced")
+
+/obj/item/toy/plush/lizardplushie/chris
+ name = "Chris Plushie"
+ desc = "An adorable stuffed toy of an angry ashwalker. He even comes with his own little crusher!" // CHRIS CHRIS CHRIS!
+ icon = 'hyperstation/icons/obj/plushes.dmi'
+ gender = MALE
+ icon_state = "chris"
+ item_state = "chris"
+ squeak_override = list('sound/weapons/plasma_cutter.ogg' = 1) // The sound the crusher uses is the same as the plasma cutter :P
+
+
+/obj/item/toy/plush/slimeplushie/tania
+ desc = "An adorable stuffed toy of a slimegirl. She seems oddly damp..." // Milky slime
+ icon = 'hyperstation/icons/obj/plushes.dmi'
+ icon_state = "tania"
+ item_state = "tania"
+ attack_verb = list("hugged", "cuddled", "embraced")
+ squeak_override = list('sound/weapons/thudswoosh.ogg' = 1)
+
+/obj/item/toy/plush/slimeplushie/tania/love(obj/item/toy/plush/Kisser, mob/living/user)
+ /* if (istype(Kisser, /obj/item/toy/plush/vladin) ) // Vladin plushie isn't real, Vladin plushie cannot hug you ;-;
+ ..()
+ else */
+ user.show_message("[src] hugs [Kisser]!", 1,
+ "[src] hugs [Kisser]!", 0)
+
+/obj/item/toy/plush/mammal/grug
+ name = "Grug S. Cavemannington Plushie"
+ desc = " Everybody's favorite space faring caveman in plushie form. You feel an overwhelming urge to break things while holding it."
+ icon = 'hyperstation/icons/obj/plushes.dmi'
+ icon_state = "grug"
+ item_state = "grug"
+ attack_verb = list("thomped", "ook'd", "stoned")
+ squeak_override = list('sound/voice/gorillaplush.ogg' = 1)
\ No newline at end of file
diff --git a/hyperstation/code/obj/pregnancytester.dm b/hyperstation/code/obj/pregnancytester.dm
index 6b751747..974fda3a 100644
--- a/hyperstation/code/obj/pregnancytester.dm
+++ b/hyperstation/code/obj/pregnancytester.dm
@@ -1,6 +1,6 @@
/obj/item/pregnancytest
name = "pregnancy test"
- desc = "a one time use small device, used to determine if someone is pregnant or not."
+ desc = "A one time use small device, used to determine whether someone is pregnant or not."
icon = 'hyperstation/icons/obj/pregnancytest.dmi'
throwforce = 0
icon_state = "ptest"
@@ -27,7 +27,7 @@
icon_state = "negative"
name = "[results] pregnancy test"
status = 1
- to_chat(user, "You use the pregnancy test, the display reads positive!")
+ to_chat(user, "You use the pregnancy test, the display reads negative!")
/obj/item/pregnancytest/proc/test(mob/living/user)
diff --git a/hyperstation/code/obj/rewards.dm b/hyperstation/code/obj/rewards.dm
new file mode 100644
index 00000000..7fa8da30
--- /dev/null
+++ b/hyperstation/code/obj/rewards.dm
@@ -0,0 +1,27 @@
+/obj/item/pen/bluemarker
+ name = "blue marker"
+ desc = "A simple blueberry scented marker."
+ icon_state = "marker_blue"
+ colour = "blue"
+
+/obj/item/pen/bluemarker/attack_self(mob/user)
+ user.emote("sniff")
+ to_chat(user, "Ahh~ blueberries!")
+
+/obj/item/clothing/suit/napoleonic
+ name = "napoleonic uniform"
+ desc = "An heirloom passed down from the Gruber family dynasty."
+ icon_state = "napoleonic"
+ item_state = "napoleonic"
+ body_parts_covered = CHEST|GROIN|ARMS
+ cold_protection = CHEST|GROIN|ARMS
+
+/obj/item/clothing/suit/shackles
+ name = "Plastitanium Shackles"
+ desc = "A set of heavy plastitanium shackles, there are chains still attatched"
+ icon_state = "shackles"
+ item_state = "shackles"
+ icon = 'hyperstation/icons/mobs/rewards.dmi'
+ alternate_worn_icon = 'hyperstation/icons/mobs/rewards.dmi'
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
+
diff --git a/hyperstation/code/obj/rope.dm b/hyperstation/code/obj/rope.dm
new file mode 100644
index 00000000..98c933a2
--- /dev/null
+++ b/hyperstation/code/obj/rope.dm
@@ -0,0 +1,55 @@
+//Jay
+//TODO: Better sprites
+//Rope
+/obj/item/restraints/handcuffs/rope/ //Fun
+ name = "soft rope"
+ desc = "A comfortable rope that would be easy to slip out of if you needed. Kinky."
+ breakouttime = 10 //Easy to break out. It's not for gaming.
+ icon = 'hyperstation/icons/obj/rope.dmi'
+ icon_state = "rope"
+ item_state = "rope_hands" //This sprite is in restraints.dmi until I figure out how to refrence somewhere else
+ cuffsound = 'sound/weapons/cablecuff.ogg'
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
+
+/mob/living/proc/rope_add(source) //Check to see if the rope is on, and then add effects
+ var/mob/living/carbon/M = source
+ if(M.handcuffed)
+ var/rope_message = pick("The rope is tightly tied onto you")
+ to_chat(M, "[rope_message]")
+ M.min_arousal = 33
+ M.arousal_rate += 2
+ update_stat()
+
+/mob/living/proc/rope_remove(list/sources, temp_min_arousal, temp_max_arousal, temp_arousal_rate) //Check to see it the rope is gone, and reset effects
+ var/mob/living/carbon/M = sources
+ if (!M.handcuffed)
+ var/rope_message = pick("The rope has been removed")
+ to_chat(M, "[rope_message]")
+ M.min_arousal = temp_min_arousal
+ M.max_arousal = temp_max_arousal
+ M.arousal_rate = temp_arousal_rate
+ update_stat()
+
+/obj/item/restraints/handcuffs/rope/attack(mob/living/carbon/C, mob/living/user)
+ . = ..()
+ var/temp_min_arousal = C.min_arousal //Temp variables to hold original arousal values
+ var/temp_max_arousal = C.max_arousal
+ var/temp_arousal_rate = C.arousal_rate
+ var/datum/callback/Cback = new(user, /mob/living/proc/rope_add, C)//Put the rope on
+ addtimer(Cback, 6, TIMER_UNIQUE)//We are going to call this proc six seconds after the click. The rope tying takes 5 seconds
+ var/datum/callback/Cback2 = new(user, /mob/living/proc/rope_remove, C, temp_min_arousal, temp_max_arousal, temp_arousal_rate)
+ while(1) //Loop until break - Because I can't figure out any better way to do it.
+ var/rope_emote = pick("moan", "blush")
+ sleep(50) //5 second wait
+ addtimer(Cback2, 1, TIMER_UNIQUE) //Just keep calling this timer proc
+ if (prob(10))
+ C.emote(rope_emote)
+ if (!C.handcuffed)
+ return //Break when the rope is removed
+
+/datum/crafting_recipe/rope
+ name = "Soft Rope"
+ result = /obj/item/restraints/handcuffs/rope
+ time = 40
+ reqs = list(/obj/item/stack/sheet/cloth = 5)
+ category = CAT_MISC
\ No newline at end of file
diff --git a/hyperstation/icons/mobs/aibots.dmi b/hyperstation/icons/mobs/aibots.dmi
new file mode 100644
index 00000000..1710d3ad
Binary files /dev/null and b/hyperstation/icons/mobs/aibots.dmi differ
diff --git a/hyperstation/icons/mobs/feet.dmi b/hyperstation/icons/mobs/feet.dmi
new file mode 100644
index 00000000..cf74d737
Binary files /dev/null and b/hyperstation/icons/mobs/feet.dmi differ
diff --git a/hyperstation/icons/mobs/gloves.dmi b/hyperstation/icons/mobs/gloves.dmi
new file mode 100644
index 00000000..39e9b9b2
Binary files /dev/null and b/hyperstation/icons/mobs/gloves.dmi differ
diff --git a/hyperstation/icons/mobs/head.dmi b/hyperstation/icons/mobs/head.dmi
new file mode 100644
index 00000000..15994e69
Binary files /dev/null and b/hyperstation/icons/mobs/head.dmi differ
diff --git a/hyperstation/icons/mobs/rewards.dmi b/hyperstation/icons/mobs/rewards.dmi
new file mode 100644
index 00000000..2e44d0c2
Binary files /dev/null and b/hyperstation/icons/mobs/rewards.dmi differ
diff --git a/hyperstation/icons/mobs/suit.dmi b/hyperstation/icons/mobs/suit.dmi
new file mode 100644
index 00000000..f082396a
Binary files /dev/null and b/hyperstation/icons/mobs/suit.dmi differ
diff --git a/hyperstation/icons/obj/bluespace_thread.dmi b/hyperstation/icons/obj/bluespace_thread.dmi
new file mode 100644
index 00000000..77b9e6d5
Binary files /dev/null and b/hyperstation/icons/obj/bluespace_thread.dmi differ
diff --git a/hyperstation/icons/obj/clothing/gloves.dmi b/hyperstation/icons/obj/clothing/gloves.dmi
new file mode 100644
index 00000000..3f3f8f0a
Binary files /dev/null and b/hyperstation/icons/obj/clothing/gloves.dmi differ
diff --git a/hyperstation/icons/obj/clothing/head.dmi b/hyperstation/icons/obj/clothing/head.dmi
new file mode 100644
index 00000000..7fee1914
Binary files /dev/null and b/hyperstation/icons/obj/clothing/head.dmi differ
diff --git a/hyperstation/icons/obj/clothing/rewards.dmi b/hyperstation/icons/obj/clothing/rewards.dmi
new file mode 100644
index 00000000..d9500000
Binary files /dev/null and b/hyperstation/icons/obj/clothing/rewards.dmi differ
diff --git a/hyperstation/icons/obj/clothing/shoes.dmi b/hyperstation/icons/obj/clothing/shoes.dmi
new file mode 100644
index 00000000..af087b73
Binary files /dev/null and b/hyperstation/icons/obj/clothing/shoes.dmi differ
diff --git a/hyperstation/icons/obj/condom.dmi b/hyperstation/icons/obj/condom.dmi
new file mode 100644
index 00000000..cf74d737
Binary files /dev/null and b/hyperstation/icons/obj/condom.dmi differ
diff --git a/hyperstation/icons/obj/leash.dmi b/hyperstation/icons/obj/leash.dmi
new file mode 100644
index 00000000..08a9ae3f
Binary files /dev/null and b/hyperstation/icons/obj/leash.dmi differ
diff --git a/hyperstation/icons/obj/medical.dmi b/hyperstation/icons/obj/medical.dmi
new file mode 100644
index 00000000..9b1b3f34
Binary files /dev/null and b/hyperstation/icons/obj/medical.dmi differ
diff --git a/hyperstation/icons/obj/milking_machine.dmi b/hyperstation/icons/obj/milking_machine.dmi
new file mode 100644
index 00000000..8e8ccd73
Binary files /dev/null and b/hyperstation/icons/obj/milking_machine.dmi differ
diff --git a/hyperstation/icons/obj/plushes.dmi b/hyperstation/icons/obj/plushes.dmi
new file mode 100644
index 00000000..c2c73411
Binary files /dev/null and b/hyperstation/icons/obj/plushes.dmi differ
diff --git a/hyperstation/icons/obj/rope.dmi b/hyperstation/icons/obj/rope.dmi
new file mode 100644
index 00000000..9937b8ea
Binary files /dev/null and b/hyperstation/icons/obj/rope.dmi differ
diff --git a/icons/UI_Icons/chat/chat_icons.dmi b/icons/UI_Icons/chat/chat_icons.dmi
new file mode 100644
index 00000000..7040b396
Binary files /dev/null and b/icons/UI_Icons/chat/chat_icons.dmi differ
diff --git a/icons/effects/crayondecal.dmi b/icons/effects/crayondecal.dmi
index fcd27698..8c42e661 100644
Binary files a/icons/effects/crayondecal.dmi and b/icons/effects/crayondecal.dmi differ
diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi
index 2a85f8a4..e9343c7e 100644
Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ
diff --git a/icons/mob/animal_parts.dmi b/icons/mob/animal_parts.dmi
index 375df934..d51bd882 100644
Binary files a/icons/mob/animal_parts.dmi and b/icons/mob/animal_parts.dmi differ
diff --git a/icons/mob/animals_held.dmi b/icons/mob/animals_held.dmi
new file mode 100644
index 00000000..82a065d9
Binary files /dev/null and b/icons/mob/animals_held.dmi differ
diff --git a/icons/mob/animals_held_lh.dmi b/icons/mob/animals_held_lh.dmi
new file mode 100644
index 00000000..6c407c85
Binary files /dev/null and b/icons/mob/animals_held_lh.dmi differ
diff --git a/icons/mob/animals_held_rh.dmi b/icons/mob/animals_held_rh.dmi
new file mode 100644
index 00000000..322dad06
Binary files /dev/null and b/icons/mob/animals_held_rh.dmi differ
diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi
index 38c0132e..ee0069e5 100644
Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ
diff --git a/icons/mob/feet_digi.dmi b/icons/mob/feet_digi.dmi
index e0a9cd46..c726bf84 100644
Binary files a/icons/mob/feet_digi.dmi and b/icons/mob/feet_digi.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 9eb5de65..f8957bde 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi
index 9ccd2c8c..923762bb 100644
Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ
diff --git a/icons/mob/human_parts_greyscale.dmi b/icons/mob/human_parts_greyscale.dmi
index 3df9fe5f..03b829e4 100644
Binary files a/icons/mob/human_parts_greyscale.dmi and b/icons/mob/human_parts_greyscale.dmi differ
diff --git a/icons/mob/inhands/equipment/tools_lefthand.dmi b/icons/mob/inhands/equipment/tools_lefthand.dmi
index 72b99432..fb7c44e9 100644
Binary files a/icons/mob/inhands/equipment/tools_lefthand.dmi and b/icons/mob/inhands/equipment/tools_lefthand.dmi differ
diff --git a/icons/mob/inhands/equipment/tools_righthand.dmi b/icons/mob/inhands/equipment/tools_righthand.dmi
index ef1001c4..dd9d2e72 100644
Binary files a/icons/mob/inhands/equipment/tools_righthand.dmi and b/icons/mob/inhands/equipment/tools_righthand.dmi differ
diff --git a/icons/mob/inhands/weapons/guns_lefthand.dmi b/icons/mob/inhands/weapons/guns_lefthand.dmi
index ea185c5a..7c411c33 100644
Binary files a/icons/mob/inhands/weapons/guns_lefthand.dmi and b/icons/mob/inhands/weapons/guns_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/guns_righthand.dmi b/icons/mob/inhands/weapons/guns_righthand.dmi
index 1d380e34..f1152c77 100644
Binary files a/icons/mob/inhands/weapons/guns_righthand.dmi and b/icons/mob/inhands/weapons/guns_righthand.dmi differ
diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi
index c88b7eb8..3edd2e2a 100644
Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ
diff --git a/icons/mob/monkey.dmi b/icons/mob/monkey.dmi
index 77a21eed..8c25a3dc 100644
Binary files a/icons/mob/monkey.dmi and b/icons/mob/monkey.dmi differ
diff --git a/icons/mob/neck.dmi b/icons/mob/neck.dmi
index 5eb270d2..2e832ddb 100644
Binary files a/icons/mob/neck.dmi and b/icons/mob/neck.dmi differ
diff --git a/icons/mob/radial.dmi b/icons/mob/radial.dmi
index cfdd0e54..3dfdd2fd 100644
Binary files a/icons/mob/radial.dmi and b/icons/mob/radial.dmi differ
diff --git a/icons/mob/restraints.dmi b/icons/mob/restraints.dmi
index fa7eb43a..5a44b749 100644
Binary files a/icons/mob/restraints.dmi and b/icons/mob/restraints.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index e4b6f7da..d37ceb0e 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/mob/suit_digi.dmi b/icons/mob/suit_digi.dmi
index 58dd2f57..a3c0405f 100644
Binary files a/icons/mob/suit_digi.dmi and b/icons/mob/suit_digi.dmi differ
diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi
index 700d05fc..96f47ace 100644
Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ
diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi
index 6282e555..e31c340a 100644
Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ
diff --git a/icons/obj/barsigns.dmi b/icons/obj/barsigns.dmi
index 2c4d4010..5dd7d2af 100644
Binary files a/icons/obj/barsigns.dmi and b/icons/obj/barsigns.dmi differ
diff --git a/icons/obj/bedsheets.dmi b/icons/obj/bedsheets.dmi
index 1cc99e09..855ce6d1 100644
Binary files a/icons/obj/bedsheets.dmi and b/icons/obj/bedsheets.dmi differ
diff --git a/icons/obj/bloodpack.dmi b/icons/obj/bloodpack.dmi
index 3a5b9fd7..82b4c2e5 100644
Binary files a/icons/obj/bloodpack.dmi and b/icons/obj/bloodpack.dmi differ
diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi
index 1169888b..70607d58 100644
Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ
diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi
index b63e9344..e96de94c 100644
Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ
diff --git a/icons/obj/clothing/cloaks.dmi b/icons/obj/clothing/cloaks.dmi
index dd1ae7d7..9543c12c 100644
Binary files a/icons/obj/clothing/cloaks.dmi and b/icons/obj/clothing/cloaks.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index 57530d4c..ae5a8539 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi
index f34fe3be..7ed165f9 100644
Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index 60b6d2b7..fd795c48 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index ac2eff6d..3322094c 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/contraband.dmi b/icons/obj/contraband.dmi
index f86dd2e7..b99429ae 100644
Binary files a/icons/obj/contraband.dmi and b/icons/obj/contraband.dmi differ
diff --git a/icons/obj/decals.dmi b/icons/obj/decals.dmi
index b13ae0b8..96cfe577 100644
Binary files a/icons/obj/decals.dmi and b/icons/obj/decals.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 6bbdc188..6ff1c199 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/doors/airlocks/station/command.dmi b/icons/obj/doors/airlocks/station/command.dmi
index 1a82b9ca..265ea041 100644
Binary files a/icons/obj/doors/airlocks/station/command.dmi and b/icons/obj/doors/airlocks/station/command.dmi differ
diff --git a/icons/obj/doors/airlocks/station/science.dmi b/icons/obj/doors/airlocks/station/science.dmi
index 586e561f..172c8205 100644
Binary files a/icons/obj/doors/airlocks/station/science.dmi and b/icons/obj/doors/airlocks/station/science.dmi differ
diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi
index 7c154c61..5566a8f5 100644
Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ
diff --git a/icons/obj/food/burgerbread.dmi b/icons/obj/food/burgerbread.dmi
index 9eafd6c2..6e6d9555 100644
Binary files a/icons/obj/food/burgerbread.dmi and b/icons/obj/food/burgerbread.dmi differ
diff --git a/icons/obj/guns/energy.dmi b/icons/obj/guns/energy.dmi
index a6d5c8a5..8fafce6a 100644
Binary files a/icons/obj/guns/energy.dmi and b/icons/obj/guns/energy.dmi differ
diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi
index 588f58e5..6975fa1a 100644
Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ
diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi
index 3a6d8023..6b9c96c4 100644
Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ
diff --git a/icons/obj/janitor.dmi b/icons/obj/janitor.dmi
index 687fef60..6aa4615d 100644
Binary files a/icons/obj/janitor.dmi and b/icons/obj/janitor.dmi differ
diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi
index f28b8be5..1aba5d22 100644
Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ
diff --git a/icons/obj/modular_console.dmi b/icons/obj/modular_console.dmi
index 8d4ec3e2..93357237 100644
Binary files a/icons/obj/modular_console.dmi and b/icons/obj/modular_console.dmi differ
diff --git a/icons/obj/pocketwatch.dmi b/icons/obj/pocketwatch.dmi
new file mode 100644
index 00000000..1fe0c975
Binary files /dev/null and b/icons/obj/pocketwatch.dmi differ
diff --git a/icons/obj/smooth_structures/rplasma_window.dmi b/icons/obj/smooth_structures/rplasma_window.dmi
index e0ef705e..c4cb3f9b 100644
Binary files a/icons/obj/smooth_structures/rplasma_window.dmi and b/icons/obj/smooth_structures/rplasma_window.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index 0722b079..76ac0c71 100644
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/icons/obj/terminals.dmi b/icons/obj/terminals.dmi
index a3ad5538..e9ccfad9 100644
Binary files a/icons/obj/terminals.dmi and b/icons/obj/terminals.dmi differ
diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi
index d5cae1db..1b7bc3f4 100644
Binary files a/icons/obj/toy.dmi and b/icons/obj/toy.dmi differ
diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi
index 71339f5f..293d7788 100644
Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ
diff --git a/icons/turf/walls/riveted.dmi b/icons/turf/walls/riveted.dmi
index 90d1e962..466f4063 100644
Binary files a/icons/turf/walls/riveted.dmi and b/icons/turf/walls/riveted.dmi differ
diff --git a/icons/turf/walls/shuttle_wall.dmi b/icons/turf/walls/shuttle_wall.dmi
index cce97b24..2e9dd392 100644
Binary files a/icons/turf/walls/shuttle_wall.dmi and b/icons/turf/walls/shuttle_wall.dmi differ
diff --git a/icons/turf/walls/wall.dmi b/icons/turf/walls/wall.dmi
index 894caf0f..15522af6 100644
Binary files a/icons/turf/walls/wall.dmi and b/icons/turf/walls/wall.dmi differ
diff --git a/icons/turf/walls/wood_wall.dmi b/icons/turf/walls/wood_wall.dmi
index 84e1c083..a2fe12cf 100644
Binary files a/icons/turf/walls/wood_wall.dmi and b/icons/turf/walls/wood_wall.dmi differ
diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm
index 2ecd9f90..eb943521 100644
--- a/interface/stylesheet.dm
+++ b/interface/stylesheet.dm
@@ -152,6 +152,7 @@ h1.alert, h2.alert {color: #000000;}
.greentext {color: #00FF00; font-size: 3;}
.redtext {color: #FF0000; font-size: 3;}
.clown {color: #FF69Bf; font-size: 3; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
+.singing {font-family: "Trebuchet MS", cursive, sans-serif; font-style: italic;}
.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
.velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;}
@keyframes velvet {
diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm
index 099d4559..599a590a 100644
--- a/modular_citadel/code/datums/status_effects/chems.dm
+++ b/modular_citadel/code/datums/status_effects/chems.dm
@@ -44,12 +44,16 @@
var/items = o.get_contents()
for(var/obj/item/W in items)
if(W == o.w_uniform || W == o.wear_suit)
- o.dropItemToGround(W, TRUE)
- playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
- to_chat(o, "Your clothes give, ripping into pieces under the strain of your swelling breasts! Unless you manage to reduce the size of your breasts, there's no way you're going to be able to put anything on over these melons..!")
- o.visible_message("[o]'s chest suddenly bursts forth, ripping their clothes off!'")
- else
- to_chat(o, "Your bountiful bosom is so rich with mass, you seriously doubt you'll be able to fit any clothes over it.")
+ //Hyper change
+ var/obj/item/clothing/W2 = W
+ if(!W2.roomy == 1) //If the clothes are "roomy" then don't do this.
+ //Hyper change end
+ o.dropItemToGround(W, TRUE)
+ playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
+ to_chat(o, "Your clothes give, ripping into pieces under the strain of your swelling breasts! Unless you manage to reduce the size of your breasts, there's no way you're going to be able to put anything on over these melons..!")
+ o.visible_message("[o]'s chest suddenly bursts forth, ripping their clothes off!'")
+ else
+ to_chat(o, "Your bountiful bosom is so rich with mass, you seriously doubt you'll be able to fit any clothes over it.")
return ..()
/datum/status_effect/chem/breast_enlarger/tick(mob/living/carbon/human/H)//If you try to wear clothes, you fail. Slows you down if you're comically huge
@@ -66,9 +70,13 @@
var/items = o.get_contents()
for(var/obj/item/W in items)
if(W == o.w_uniform || W == o.wear_suit)
- o.dropItemToGround(W, TRUE)
- playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
- to_chat(owner, "Your enormous breasts are way too large to fit anything over them!")
+ //Hyper change// Check for a flag before we remove clothes.
+ var/obj/item/clothing/W2 = W
+ if(!W2.roomy == 1) //If the clothes are "roomy" then don't do this.
+ //End Hyper Change//
+ o.dropItemToGround(W, TRUE)
+ playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
+ to_chat(owner, "Your enormous breasts are way too large to fit anything over them!")
/*
if (B.size == "huge")
if(prob(1))
@@ -125,14 +133,23 @@
var/mob/living/carbon/human/o = owner
var/items = o.get_contents()
if(o.w_uniform || o.wear_suit)
- to_chat(o, "Your clothes give, ripping into peices under the strain of your swelling pecker! Unless you manage to reduce the size of your emancipated trouser snake, there's no way you're going to be able to put anything on over this girth..!")
- owner.visible_message("[o]'s schlong suddenly bursts forth, ripping their clothes off!'")
+ //Hyper change// Check for a flag before we remove clothes.
+ var/obj/item/clothing/suit = o.get_item_by_slot(SLOT_W_UNIFORM)
+ var/obj/item/clothing/jacket = o.get_item_by_slot(SLOT_WEAR_SUIT)
+ if(!suit.roomy == 1 || !jacket.roomy == 1) //If the clothes are "roomy" then don't do this.
+ //End Hyper Change//
+ to_chat(o, "Your clothes give, ripping into peices under the strain of your swelling pecker! Unless you manage to reduce the size of your emancipated trouser snake, there's no way you're going to be able to put anything on over this girth..!")
+ owner.visible_message("[o]'s schlong suddenly bursts forth, ripping their clothes off!'")
else
to_chat(o, "Your emancipated trouser snake is so ripe with girth, you seriously doubt you'll be able to fit any clothes over it.")
for(var/obj/item/W in items)
if(W == o.w_uniform || W == o.wear_suit)
- o.dropItemToGround(W, TRUE)
- playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
+ //Hyper change// Check for a flag before we remove clothes.
+ var/obj/item/clothing/W2 = W
+ if(!W2.roomy == 1) //If the clothes are "roomy" then don't do this.
+ //End Hyper Change//
+ o.dropItemToGround(W, TRUE)
+ playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
return ..()
@@ -151,14 +168,19 @@
var/items = o.get_contents()
for(var/obj/item/W in items)
- if (o.arousalloss > 32) // warning that your shaft is getting errect!
- if(W == o.w_uniform || W == o.wear_suit )
- to_chat(M, "Your swelling cock begins to strain against your clothes tightly!")
- if (o.arousalloss > 33)
- if(W == o.w_uniform || W == o.wear_suit )
- o.dropItemToGround(W, TRUE)
- playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
- to_chat(owner, "Your erect member is way to large to fit anything over! You will need to be flaccid again to wear clothes!")
+ //Hyper change// Check for a flag before we remove clothes.
+ if(istype(W, /obj/item/clothing))
+ var/obj/item/clothing/W2 = W
+ if(!W2.roomy == 1) //If the clothes are "roomy" then don't do this.
+ //End Hyper Change//
+ if (o.arousalloss > 32) // warning that your shaft is getting errect!
+ if(W == o.w_uniform || W == o.wear_suit )
+ to_chat(M, "Your swelling cock begins to strain against your clothes tightly!")
+ if (o.arousalloss > 33)
+ if(W == o.w_uniform || W == o.wear_suit )
+ o.dropItemToGround(W, TRUE)
+ playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
+ to_chat(owner, "Your erect member is way to large to fit anything over! You will need to be flaccid again to wear clothes!")
/*
switch(round(P.cached_length))
if(21)
diff --git a/modular_citadel/code/datums/traits/neutral.dm b/modular_citadel/code/datums/traits/neutral.dm
index 197c9b94..f064f757 100644
--- a/modular_citadel/code/datums/traits/neutral.dm
+++ b/modular_citadel/code/datums/traits/neutral.dm
@@ -41,3 +41,12 @@
var/active = FALSE
var/power = 0
var/cachedmoveCalc = 1
+
+/datum/quirk/fluid_leak
+ name = "Leaky breasts"
+ desc = "You don't stop making milk, and you have a habit of leaking everywhere when your breasts are full"
+ mob_trait = TRAIT_FLUID_LEAK
+ value = 0
+ medical_record_text = "Patient poorly controls their fluids."
+ gain_text = "You feel like your leaking everywhere."
+ lose_text = "You feel like you can control your fluids."
diff --git a/modular_citadel/code/game/machinery/vending.dm b/modular_citadel/code/game/machinery/vending.dm
index c67dda83..fd6294dd 100644
--- a/modular_citadel/code/game/machinery/vending.dm
+++ b/modular_citadel/code/game/machinery/vending.dm
@@ -43,22 +43,29 @@
product_slogans = "Kinky!;Sexy!;Check me out, big boy!"
vend_reply = "Have fun, you shameless pervert!"
products = list(
+ /obj/item/clothing/head/maidband = 5,
/obj/item/clothing/under/maid = 5,
/obj/item/clothing/under/stripper_pink = 5,
/obj/item/clothing/under/stripper_green = 5,
/obj/item/dildo/custom = 5,
/obj/item/reagent_containers/pill/penis_enlargement = 3,
- /obj/item/reagent_containers/pill/breast_enlargement = 3
+ /obj/item/reagent_containers/pill/breast_enlargement = 3,
+ /obj/item/clothing/gloves/latexsleeves = 3,
+ /obj/item/clothing/shoes/highheels = 3
)
contraband = list(/obj/item/restraints/handcuffs/fake/kinky = 5,
/obj/item/clothing/neck/petcollar = 5,
/obj/item/clothing/under/mankini = 1,
- /obj/item/dildo/flared/huge = 1
+ /obj/item/dildo/flared/huge = 1,
+ /obj/item/clothing/head/dominatrixcap = 1,
+ /obj/item/mesmetron = 1
)
premium = list(
/obj/item/electropack/shockcollar = 3,
- /obj/item/clothing/neck/petcollar/locked = 1
+ /obj/item/clothing/neck/petcollar/locked = 1,
+ /obj/item/restraints/handcuffs/rope = 1,
+ /obj/item/leash = 1
)
refill_canister = /obj/item/vending_refill/kink
/*
diff --git a/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm b/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
index 68ab229f..033057ba 100644
--- a/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
+++ b/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
@@ -130,15 +130,6 @@
else
return ..()
-/obj/item/melee/transforming/energy/sword/cx/chaplain
- name = "divine lightblade"
- force_on = 20 //haha i'll regret this
- block_chance = 50
-
-/obj/item/melee/transforming/energy/sword/cx/chaplain/Initialize()
- . = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
-
//OBLIGATORY TOY MEMES /////////////////////////////////////
/obj/item/toy/sword/cx
@@ -271,6 +262,24 @@
spinnable = FALSE
total_mass_on = 4
+/obj/item/twohanded/dualsaber/hypereutactic/chaplain
+ name = "\improper divine lightblade"
+ desc = "A giant blade of bright and holy light, said to cut down the wicked with ease."
+ force = 5
+ force_unwielded = 5
+ force_wielded = 20
+ block_chance = 50
+ armour_penetration = 0
+ var/chaplain_spawnable = TRUE
+ obj_flags = UNIQUE_RENAME
+
+/obj/item/twohanded/dualsaber/hypereutactic/chaplain/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+
+/obj/item/twohanded/dualsaber/hypereutactic/chaplain/IsReflect()
+ return FALSE
+
/obj/item/twohanded/dualsaber/hypereutactic/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
altafterattack(A, user, TRUE, params)
return TRUE
diff --git a/modular_citadel/code/modules/arousal/arousal.dm b/modular_citadel/code/modules/arousal/arousal.dm
index 58db9c4e..4044f146 100644
--- a/modular_citadel/code/modules/arousal/arousal.dm
+++ b/modular_citadel/code/modules/arousal/arousal.dm
@@ -349,10 +349,17 @@
if(impreg)
//Role them odds, only people with the dicks can send the chance to the person with the settings enabled at the momment.
- if (rand(0,100) < L.impregchance && L.breedable == 1)
+ var/obj/item/organ/genital/womb/W = L.getorganslot("womb")
+ if (L.breedable == 1 && W.pregnant == 0) //Dont get pregnant again, if you are pregnant.
log_game("Debug: [L] has been impregnated by [src]")
- var/obj/item/organ/genital/womb/W = L.getorganslot("womb")
- W.pregnant = 1
+ to_chat(L, "You feel your hormones change, and a motherly instinct take over.") //leting them know magic has happened.
+ W.pregnant = 1 //self insert fetish
+
+ var/obj/item/organ/genital/breasts/B = L.getorganslot("womb")
+
+ if (B.fluid_mult < 0.5 && B) //pregnancy causes mammals to produce milk faster. no point setting their fluid, lower if they are already higher.
+ B.fluid_mult = 0.5
+
/mob/living/carbon/human/proc/mob_fill_container(obj/item/organ/genital/G, obj/item/reagent_containers/container, mb_time = 30) //For beaker-filling, beware the bartender
diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm
index da8a142f..8ca1e450 100644
--- a/modular_citadel/code/modules/arousal/organs/breasts.dm
+++ b/modular_citadel/code/modules/arousal/organs/breasts.dm
@@ -9,12 +9,13 @@
size = BREASTS_SIZE_DEF //SHOULD BE A LETTER, starts as a number...???
var/cached_size = null //for enlargement SHOULD BE A NUMBER
var/prev_size //For flavour texts SHOULD BE A LETTER
- //var/breast_sizes = list ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "huge", "flat")
- var/breast_values = list ("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "flat" = 0)
+ //var/breast_sizes = list ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "huge", "massive", "giga", "flat")
+ var/breast_values = list ("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "massive" = 17, "giga" = 25, "flat" = 0) // Note: Do not forget to define new sizes.
var/statuscheck = FALSE
fluid_id = "milk"
var/amount = 2
fluid_mult = 0.25 // Set to a lower value due to production scaling with size (I.E. D cups produce the "normal" amount)
+ fluid_max_volume = 10
producing = TRUE
shape = "Pair"
can_masturbate_with = TRUE
@@ -28,10 +29,10 @@
return
if(!reagents || !owner)
return
- reagents.maximum_volume = fluid_max_volume * cached_size * fluid_mult // fluid amount is also scaled by the size of the organ
+ reagents.maximum_volume = fluid_max_volume * cached_size// fluid amount is also scaled by the size of the organ
if(fluid_id && producing)
if(reagents.total_volume == 0) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
- fluid_rate = 0.1
+ reagents.total_volume = 0.1
else
fluid_rate = CUM_RATE * cached_size * fluid_mult // fluid rate is scaled by the size of the organ
generate_milk()
@@ -43,6 +44,9 @@
if(!sent_full_message)
send_full_message()
sent_full_message = TRUE
+ if(HAS_TRAIT(owner, TRAIT_FLUID_LEAK))
+ reagents.get_master_reagent().reaction_turf(get_turf(owner), 3)
+ reagents.remove_reagent(fluid_id, 3)
return FALSE
sent_full_message = FALSE
reagents.isolate_reagent(fluid_id)
@@ -64,7 +68,7 @@
desc = "You see three sets of breasts, running from their chest to their belly."
else
desc = "You see some breasts, they seem to be quite exotic."
- if(cached_size > 16)
+ if(cached_size > 18 && cached_size != 25)
desc = "You see [pick("some serious honkers", "a real set of badonkers", "some dobonhonkeros", "massive dohoonkabhankoloos", "two big old tonhongerekoogers", "a couple of giant bonkhonagahoogs", "a pair of humongous hungolomghnonoloughongous")]. Their volume is way beyond cupsize now, measuring in about [round(cached_size)]cm in diameter."
else if (!isnum(size))
if (size == "flat")
@@ -121,10 +125,20 @@
if(!owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
owner.apply_status_effect(/datum/status_effect/chem/breast_enlarger)
statuscheck = TRUE
- if(16 to INFINITY) //if Rediculous
- size = cached_size
+ if(16 to 18) //if Ridiculous
+ size = breast_values[round(cached_size)]
+ if(!owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
+ owner.apply_status_effect(/datum/status_effect/chem/breast_enlarger)
+ statuscheck = TRUE
- if(round(cached_size) < 16)//Because byond doesn't count from 0, I have to do this.
+ if(19 to INFINITY) //if Hyper-Ridiculous
+ size = cached_size
+ if(!owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
+ owner.apply_status_effect(/datum/status_effect/chem/breast_enlarger)
+ statuscheck = TRUE
+
+
+ if(round(cached_size) < 19 && round(cached_size) == 25)//Because byond doesn't count from 0, I have to do this.
if (prev_size == 0)
prev_size = "flat"
if(size == 0)//Bloody byond with it's counting from 1
@@ -140,5 +154,7 @@
var/mob/living/carbon/human/H = owner
H.Force_update_genitals()
prev_size = size
- else if (cached_size >= 16)
- size = "huge"
+ else if (cached_size >= 18 && cached_size < 25)
+ size = "massive"
+ else if (cached_size >= 25)
+ size = "giga"
\ No newline at end of file
diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm
index 43a512ac..9d38d0d8 100644
--- a/modular_citadel/code/modules/arousal/organs/penis.dm
+++ b/modular_citadel/code/modules/arousal/organs/penis.dm
@@ -12,7 +12,7 @@
size = 2 //arbitrary value derived from length and girth for sprites.
var/length = 6 //inches
var/cached_length //used to detect a change in length
- var/girth = 4.38
+ var/girth = 3.38
var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm
var/knot_girth_ratio = KNOT_GIRTH_RATIO_DEF
var/list/dickflags = list()
@@ -47,12 +47,12 @@
size = 3
if(owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
o.remove_status_effect(/datum/status_effect/chem/penis_enlarger)
- if(21 to 35) //If massive and due for large effects
+ if(21 to 28) //If massive and due for large effects
length = cached_length
size = 3
if(!owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
o.apply_status_effect(/datum/status_effect/chem/penis_enlarger)
- if(36 to INFINITY) //If comical
+ if(28 to INFINITY) //If comical
length = cached_length
size = 4 //no new sprites for anything larger yet
if(!owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm
index f4ef4b50..eac9832b 100644
--- a/modular_citadel/code/modules/arousal/organs/testicles.dm
+++ b/modular_citadel/code/modules/arousal/organs/testicles.dm
@@ -9,6 +9,10 @@
var/size_name = "average"
shape = "single"
var/sack_size = BALLS_SACK_SIZE_DEF
+ var/cached_size = 6
+ //fluid_mult = 0.133 // Set to a lower value due to production scaling with size (I.E. 6 inches the "normal" amount)
+ fluid_mult = 1.0 //Defaults to 1 no matter what you do. It just does. Just gonna adapt I guess.
+ fluid_max_volume = 3
fluid_id = "semen"
producing = TRUE
can_masturbate_with = FALSE
@@ -19,20 +23,21 @@
/obj/item/organ/genital/testicles/on_life()
if(QDELETED(src))
return
- if(reagents && producing)
+ if(!reagents || !owner)
+ return
+ //reagents.maximum_volume = fluid_max_volume * cached_size// fluid amount is also scaled by the size of the organ
+ reagents.maximum_volume = fluid_max_volume * ((cached_size / 2) + 1) * ((size / 2) + 1) * fluid_mult //Hyper - New calculation for more dynamic fluid levels. I can't believe I typed that.
+ if(fluid_id && producing)
if(reagents.total_volume == 0) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
fluid_rate = 0.1
else
- fluid_rate = CUM_RATE
- if(reagents.total_volume >= 5)
- fluid_mult = 0.5
- else
- fluid_mult = 1
+ //fluid_rate = CUM_RATE * cached_size * fluid_mult // fluid rate is scaled by the size of the organ
+ fluid_rate = ((CUM_RATE / 5) * (cached_size / 3) * (size / 4) * fluid_mult) / 10 //Hyper - Production was way too high by default. This should drop it back down, but allow for it to get really high
generate_cum()
/obj/item/organ/genital/testicles/proc/generate_cum()
- reagents.maximum_volume = fluid_max_volume
- if(reagents.total_volume >= reagents.maximum_volume)
+ //reagents.maximum_volume = fluid_max_volume //This is the line that broke cum for so long
+ if(reagents.total_volume >= reagents.maximum_volume - 0.1) //Hyper - Check for it being close to the maximum. It sometimes doesn't proc due to a rounding error.
if(!sent_full_message)
send_full_message()
sent_full_message = TRUE
@@ -42,7 +47,7 @@
if(!linked_organ)
return FALSE
reagents.isolate_reagent(fluid_id)//remove old reagents if it changed and just clean up generally
- reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate))//generate the cum
+ reagents.add_reagent(fluid_id, (fluid_rate))//generate the cum
/obj/item/organ/genital/testicles/update_link()
if(owner && !QDELETED(src))
@@ -50,7 +55,8 @@
if(linked_organ)
linked_organ.linked_organ = src
size = linked_organ.size
-
+ var/obj/item/organ/genital/penis/O = linked_organ
+ cached_size = O.length
else
if(linked_organ)
linked_organ.linked_organ = null
@@ -63,11 +69,14 @@
/obj/item/organ/genital/testicles/update_appearance()
switch(size)
- if(0.1 to 1)
+ //if(0.1 to 1) //Hyper - Change the displayed ball sizes
+ if(0.1 to 3)
size_name = "average"
- if(1.1 to 2)
+ //if(1.1 to 2)
+ if(3.1 to 8)
size_name = "enlarged"
- if(2.1 to INFINITY)
+ //if(2.1 to INFINITY)
+ if(8.1 to INFINITY)
size_name = "engorged"
else
size_name = "nonexistant"
diff --git a/modular_citadel/code/modules/arousal/organs/womb.dm b/modular_citadel/code/modules/arousal/organs/womb.dm
index c8dbfed0..28d7bb43 100644
--- a/modular_citadel/code/modules/arousal/organs/womb.dm
+++ b/modular_citadel/code/modules/arousal/organs/womb.dm
@@ -20,7 +20,7 @@
else
fluid_rate = CUM_RATE
if(reagents.total_volume >= 5)
- fluid_mult = 0.5
+ fluid_mult = 0.8
else
fluid_mult = 1
generate_femcum()
diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm
index 9f1a6945..705a5b91 100644
--- a/modular_citadel/code/modules/client/loadout/__donator.dm
+++ b/modular_citadel/code/modules/client/loadout/__donator.dm
@@ -1,13 +1,66 @@
//This is the file that handles donator loadout items.
+
/datum/gear/pingcoderfailsafe
name = "IF YOU SEE THIS, PING A CODER RIGHT NOW!"
category = SLOT_IN_BACKPACK
path = /obj/item/bikehorn/golden
ckeywhitelist = list("This entry should never appear with this variable set.") //If it does, then that means somebody fucked up the whitelist system pretty hard
-/datum/gear/donortestingbikehorn
- name = "Donor item testing bikehorn"
+/datum/gear/testreward
+ //Just so admins can test the recent rewards added.
+ name = "Plastitanium Shackles"
category = SLOT_IN_BACKPACK
- path = /obj/item/bikehorn
- geargroupID = list("DONORTEST") //This is a list mainly for the sake of testing, but geargroupID works just fine with ordinary strings
+ path = /obj/item/clothing/suit/shackles
+ ckeywhitelist = list("quotefox")
+
+/datum/gear/testrewardtwo
+ name = "Napoleonic Uniform"
+ category = SLOT_W_UNIFORM
+ path = /obj/item/clothing/suit/napoleonic
+ ckeywhitelist = list("quotefox")
+
+/datum/gear/winterblooplush
+ name = "Will Plush"
+ category = SLOT_IN_BACKPACK
+ path = /obj/item/toy/plush/mammal/winterbloo
+ ckeywhitelist = list("wolfy_wolf967")
+
+/datum/gear/winterblooplushextra
+ //for some reason bloo has had issues with his plushie
+ name = "Will Plush"
+ category = SLOT_IN_BACKPACK
+ path = /obj/item/toy/plush/mammal/winterbloo
+ ckeywhitelist = list("wolfywolf967")
+
+/datum/gear/helioplush
+ name = "Chris Plushie"
+ category = SLOT_IN_BACKPACK
+ path = /obj/item/toy/plush/lizardplushie/chris
+ ckeywhitelist = list("heliocintrini")
+
+/datum/gear/seramarker
+ name = "Blueberry Marker"
+ category = SLOT_IN_BACKPACK
+ path = /obj/item/pen/bluemarker
+ ckeywhitelist = list("blooberri")
+
+/datum/gear/hubertsuit
+ name = "Napoleonic Uniform"
+ category = SLOT_IN_BACKPACK
+ path = /obj/item/clothing/suit/napoleonic
+ ckeywhitelist = list("hackertdog")
+
+/datum/gear/grug
+ name = "Caveman Plushie"
+ category = SLOT_IN_BACKPACK
+ path = /obj/item/toy/plush/mammal/grug
+ ckeywhitelist = list("herrdoktah")
+
+
+/datum/gear/hshack
+ name = "Plastitanium Shackles"
+ category = SLOT_W_UNIFORM
+ path = /obj/item/clothing/suit/shackles
+ ckeywhitelist = list("heliocintrini")
+
diff --git a/modular_citadel/code/modules/clothing/clothing.dm b/modular_citadel/code/modules/clothing/clothing.dm
index fc71d5bd..7f366ecf 100644
--- a/modular_citadel/code/modules/clothing/clothing.dm
+++ b/modular_citadel/code/modules/clothing/clothing.dm
@@ -38,6 +38,8 @@
var/secondary_color = "#FFFFFF"
var/tertiary_color = "#808080"
+ var/force_alternate_icon = FALSE
+
/obj/item/clothing/update_icon() // picks the colored overlays from the ICON file
..()
if(hasprimary) //Checks if the overlay is enabled
diff --git a/modular_citadel/code/modules/clothing/under/trek_under.dm b/modular_citadel/code/modules/clothing/under/trek_under.dm
index a60f7653..e29fd1a6 100644
--- a/modular_citadel/code/modules/clothing/under/trek_under.dm
+++ b/modular_citadel/code/modules/clothing/under/trek_under.dm
@@ -14,6 +14,7 @@
desc = "Oooh... right."
icon = 'modular_citadel/icons/obj/clothing/trek_item_icon.dmi'
alternate_worn_icon = 'modular_citadel/icons/mob/clothing/trek_mob_icon.dmi'
+ force_alternate_icon = TRUE
item_state = ""
can_adjust = FALSE //to prevent you from "wearing it casually"
@@ -23,17 +24,20 @@
desc = "The uniform worn by command officers in the mid 2260s."
icon_state = "trek_command"
item_state = "trek_command"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
+ force_alternate_icon = TRUE
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
/obj/item/clothing/under/rank/trek/engsec
name = "Operations Uniform"
desc = "The uniform worn by operations officers of the mid 2260s. You feel strangely vulnerable just seeing this..."
+ force_alternate_icon = TRUE
icon_state = "trek_engsec"
item_state = "trek_engsec"
/obj/item/clothing/under/rank/trek/medsci
name = "MedSci Uniform"
desc = "The uniform worn by medsci officers in the mid 2260s."
+ force_alternate_icon = TRUE
icon_state = "trek_medsci"
item_state = "trek_medsci"
permeability_coefficient = 0.50
diff --git a/modular_citadel/code/modules/crafting/recipes.dm b/modular_citadel/code/modules/crafting/recipes.dm
index 6c6001b0..bf04f706 100644
--- a/modular_citadel/code/modules/crafting/recipes.dm
+++ b/modular_citadel/code/modules/crafting/recipes.dm
@@ -8,4 +8,5 @@
name = "Potat-OS"
reqs = list(/obj/item/stack/cable_coil = 1, /obj/item/stack/rods = 1, /obj/item/reagent_containers/food/snacks/grown/potato = 1, /obj/item/aicard = 1 )
result = /obj/item/aicard/potato
- category = CAT_ROBOT
\ No newline at end of file
+ category = CAT_ROBOT
+
diff --git a/modular_citadel/code/modules/mob/living/carbon/human/species_types/ipc.dm b/modular_citadel/code/modules/mob/living/carbon/human/species_types/ipc.dm
index 25b8daf2..8fd01393 100644
--- a/modular_citadel/code/modules/mob/living/carbon/human/species_types/ipc.dm
+++ b/modular_citadel/code/modules/mob/living/carbon/human/species_types/ipc.dm
@@ -1,5 +1,5 @@
/datum/species/ipc
- name = "IPC"
+ name = "I.P.C"
id = "ipc"
say_mod = "beeps"
default_color = "00FF00"
@@ -10,10 +10,16 @@
inherent_biotypes = list(MOB_ROBOTIC, MOB_HUMANOID)
mutant_bodyparts = list("ipc_screen", "ipc_antenna")
default_features = list("ipc_screen" = "Blank", "ipc_antenna" = "None")
- meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
- mutanttongue = /obj/item/organ/tongue/robot/ipc
+ meat = null //robots can't make meat silly!
+//Just robo looking parts.
+ mutant_heart = /obj/item/organ/heart/ipc
+ mutantlungs = /obj/item/organ/lungs/ipc
+ mutantliver = /obj/item/organ/liver/ipc
+ mutantstomach = /obj/item/organ/stomach/ipc
+ mutanteyes = /obj/item/organ/eyes/ipc
+ mutanttongue = /obj/item/organ/tongue/robot
- exotic_blood = "oil"
+ exotic_bloodtype = "oil"
var/datum/action/innate/monitor_change/screen
diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
index c413644b..a3213ef1 100644
--- a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
+++ b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
@@ -18,7 +18,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
name = "combat jaws"
desc = "The jaws of the law. Very sharp."
icon_state = "jaws"
- force = 12
+ force = 10 //Lowered to match secborg. No reason it should be more than a secborg's baton.
attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced")
/obj/item/dogborg/jaws/small
@@ -32,7 +32,6 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
/obj/item/dogborg/jaws/attack(atom/A, mob/living/silicon/robot/user)
..()
user.do_attack_animation(A, ATTACK_EFFECT_BITE)
- log_combat(user, A, "bit")
/obj/item/dogborg/jaws/small/attack_self(mob/user)
var/mob/living/silicon/robot.R = user
@@ -307,8 +306,8 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
/mob/living/silicon/robot
var/leaping = 0
var/pounce_cooldown = 0
- var/pounce_cooldown_time = 50 //Nearly doubled, u happy?
- var/pounce_spoolup = 3
+ var/pounce_cooldown_time = 20 //Buffed to counter balance changes
+ var/pounce_spoolup = 1
var/leap_at
var/disabler
var/laser
@@ -338,7 +337,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
//It's also extremely buggy visually, so it's balance+bugfix
return
- if(cell.charge <= 500)
+ if(cell.charge <= 750)
to_chat(src,"Insufficent reserves for jump actuators!")
return
@@ -348,7 +347,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
pixel_y = 10
update_icons()
throw_at(A, MAX_K9_LEAP_DIST, 1, spin=0, diagonals_first = 1)
- cell.use(500) //Doubled the energy consumption
+ cell.use(750) //Less than a stunbaton since stunbatons hit everytime.
weather_immunities -= "lava"
/mob/living/silicon/robot/throw_impact(atom/A)
@@ -366,13 +365,13 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
blocked = 1
if(!blocked)
L.visible_message("[src] pounces on [L]!", "[src] pounces on you!")
- L.Knockdown(iscarbon(L) ? 450 : 45) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice.
+ L.Knockdown(iscarbon(L) ? 225 : 45) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice.
playsound(src, 'sound/weapons/Egloves.ogg', 50, 1)
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
step_towards(src,L)
log_combat(src, L, "borg pounced")
else
- Knockdown(45, 1, 1)
+ Knockdown(15, 1, 1)
pounce_cooldown = !pounce_cooldown
spawn(pounce_cooldown_time) //3s by default
@@ -380,7 +379,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
else if(A.density && !A.CanPass(src))
visible_message("[src] smashes into [A]!", "You smash into [A]!")
playsound(src, 'sound/items/trayhit1.ogg', 50, 1)
- Knockdown(45, 1, 1)
+ Knockdown(15, 1, 1)
if(leaping)
leaping = 0
diff --git a/modular_citadel/code/modules/power/lighting.dm b/modular_citadel/code/modules/power/lighting.dm
index e326d84e..8d2519e2 100644
--- a/modular_citadel/code/modules/power/lighting.dm
+++ b/modular_citadel/code/modules/power/lighting.dm
@@ -1,7 +1,7 @@
/obj/machinery/light
bulb_colour = "#FFEEDD"
- bulb_power = 0.75
+ bulb_power = 0.95
/obj/machinery/light/small
bulb_colour = "#FFDDBB"
- bulb_power = 0.75
+ bulb_power = 0.8
diff --git a/modular_citadel/code/modules/reagents/chemistry/fermi/fermi.md b/modular_citadel/code/modules/reagents/chemistry/fermi/fermi.md
new file mode 100644
index 00000000..dfc89fb4
--- /dev/null
+++ b/modular_citadel/code/modules/reagents/chemistry/fermi/fermi.md
@@ -0,0 +1,23 @@
+How to code fermichem reactions:
+First off, probably read though the readme for standard reagent mechanisms, this builds on top of that.
+
+#bitflags
+for `datum/reagent/` you have the following options with `var/chemical_flags`:
+
+```
+REAGENT_DEAD_PROCESS calls on_mob_dead() if present in a dead body
+REAGENT_DONOTSPLIT Do not split the chem at all during processing
+REAGENT_ONLYINVERSE Only invert chem, no splitting
+REAGENT_ONMOBMERGE Call on_mob_life proc when reagents are merging.
+REAGENT_INVISIBLE Doesn't appear on handheld health analyzers.
+REAGENT_FORCEONNEW Forces a on_new() call without a data overhead
+REAGENT_SNEAKYNAME When inverted, the inverted chem uses the name of the original chem
+REAGENT_SPLITRETAINVOL Retains initial volume of chem when splitting
+```
+
+for `datum/chemical_reaction/` under `var/clear_conversion`
+
+```
+REACTION_CLEAR_IMPURE Convert into impure/pure on reaction completion
+REACTION_CLEAR_INVERSE Convert into inverse on reaction completion when purity is low enough
+```
\ No newline at end of file
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm
index 76d0951d..4e80f42d 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm
@@ -136,7 +136,6 @@ Creating a chem with a low purity will make you permanently fall in love with so
color = "#660015" // rgb: , 0, 255
taste_description = "synthetic chocolate, a base tone of alcohol, and high notes of roses"
overdose_threshold = 100 //If this is too easy to get 100u of this, then double it please.
- DoNotSplit = TRUE
metabolization_rate = 0.1//It has to be slow, so there's time for the effect.
data = list("creatorID" = null, "creatorGender" = null, "creatorName" = null)
var/creatorID //ckey
@@ -144,20 +143,19 @@ Creating a chem with a low purity will make you permanently fall in love with so
var/creatorName
var/mob/living/creator
pH = 10
- OnMobMergeCheck = TRUE //Procs on_mob_add when merging into a human
+ chemical_flags = REAGENT_ONMOBMERGE | REAGENT_DONOTSPLIT //Procs on_mob_add when merging into a human
can_synth = FALSE
/datum/reagent/fermi/enthrall/test
name = "MKUltraTest"
id = "enthrallTest"
- description = "A forbidden deep red mixture that overwhelms a foreign body with waves of joy, intoxicating them into servitude. When taken by the creator, it will enhance the draw of their voice to those affected by it."
+ description = "A forbidden deep red mixture that makes you like Fermis a little too much. Unobtainable and due to be removed from the wiki."
data = list("creatorID" = "honkatonkbramblesnatch", "creatorGender" = "Mistress", "creatorName" = "Fermis Yakumo")
creatorID = "honkatonkbramblesnatch"//ckey
creatorGender = "Mistress"
creatorName = "Fermis Yakumo"
purity = 1
- DoNotSplit = TRUE
/datum/reagent/fermi/enthrall/test/on_new()
id = "enthrall"
@@ -300,13 +298,13 @@ Creating a chem with a low purity will make you permanently fall in love with so
//Creates a gas cloud when the reaction blows up, causing everyone in it to fall in love with someone/something while it's in their system.
/datum/reagent/fermi/enthrallExplo//Created in a gas cloud when it explodes
- name = "MKUltra"
+ name = "Gaseous MKUltra"
id = "enthrallExplo"
- description = "A forbidden deep red mixture that overwhelms a foreign body with waves of desire, inducing a chemial love for another. Also, how the HECC did you get this?"
+ description = "A forbidden deep red gas that overwhelms a foreign body, causing the person they next lay their eyes on to become more interesting. Studies have shown that people are 66% more likely to make friends with this in the air. Produced when MKUltra explodes."
color = "#2C051A" // rgb: , 0, 255
metabolization_rate = 0.1
taste_description = "synthetic chocolate, a base tone of alcohol, and high notes of roses."
- DoNotSplit = TRUE
+ chemical_flags = REAGENT_DONOTSPLIT
can_synth = FALSE
var/mob/living/carbon/love
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
index 0924f00f..3414e65b 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm
@@ -54,9 +54,9 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
var/pollStarted = FALSE
var/location_created
var/startHunger
- ImpureChem = "SDGFtox"
- InverseChemVal = 0.5
- InverseChem = "SDZF"
+ impure_chem = "SDGFtox"
+ inverse_chem_val = 0.5
+ inverse_chem = "SDZF"
can_synth = TRUE
@@ -270,8 +270,9 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
//Unobtainable, used in clone spawn.
/datum/reagent/fermi/SDGFheal
- name = "synthetic-derived growth factor"
+ name = "synthetic-derived healing factor"
id = "SDGFheal"
+ description = "Leftover SDGF is transferred into the resulting clone, which quickly heals up the stresses from suddenly splitting. Restores blood, nutrition, and repaires brain and clone damage quickly. Only obtainable from using excess SDGF, and only enters the cloned body."
metabolization_rate = 1
can_synth = FALSE
@@ -284,29 +285,30 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
..()
//Unobtainable, used if SDGF is impure but not too impure
-/datum/reagent/fermi/SDGFtox
- name = "synthetic-derived growth factor"
+/datum/reagent/impure/SDGFtox
+ name = "Synthetic-derived apoptosis factor"
id = "SDGFtox"
- description = "A chem that makes a certain chemcat angry at you if you're reading this, how did you get this???"//i.e. tell me please, figure it's a good way to get pinged for bugfixes.
+ description = "Impure synthetic-derived growth factor causes certain cells to undergo cell death, causing clone damage, and damaging blood cells."//i.e. tell me please, figure it's a good way to get pinged for bugfixes.
metabolization_rate = 1
can_synth = FALSE
-/datum/reagent/fermi/SDGFtox/on_mob_life(mob/living/carbon/M)//Damages the taker if their purity is low. Extended use of impure chemicals will make the original die. (thus can't be spammed unless you've very good)
+/datum/reagent/impure/SDGFtox/on_mob_life(mob/living/carbon/M)//Damages the taker if their purity is low. Extended use of impure chemicals will make the original die. (thus can't be spammed unless you've very good)
M.blood_volume -= 10
M.adjustCloneLoss(2, 0)
..()
//Fail state of SDGF
-/datum/reagent/fermi/SDZF
- name = "synthetic-derived growth factor"
+/datum/reagent/impure/SDZF
+ name = "synthetic-derived zombie factor"
id = "SDZF"
- description = "A horribly peverse mass of Embryonic stem cells made real by the hands of a failed chemist. This message should never appear, how did you manage to get a hold of this?"
+ description = "A horribly peverse mass of Embryonic stem cells made real by the hands of a failed chemist. Emulates normal synthetic-derived growth factor, but produces a hostile zombie at the end of it."
color = "#a502e0" // rgb: 96, 0, 255
metabolization_rate = 0.5 * REAGENTS_METABOLISM
var/startHunger
can_synth = TRUE
+ chemical_flags = REAGENT_SNEAKYNAME
-/datum/reagent/fermi/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead.
+/datum/reagent/impure/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead.
switch(current_cycle)//Pretends to be normal
if(20)
to_chat(M, "You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.")
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm
index d05cfb55..88586b42 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm
@@ -28,7 +28,7 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die
var/datum/mind/originalmind
var/antiGenetics = 255
var/sleepytime = 0
- InverseChemVal = 0.25
+ inverse_chem_val = 0.25
can_synth = FALSE
/datum/action/chem/astral
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm
index 7c22d9d1..3a2928ec 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm
@@ -26,9 +26,9 @@
taste_description = "a milky ice cream like flavour."
overdose_threshold = 17
metabolization_rate = 0.25
- ImpureChem = "BEsmaller" //If you make an inpure chem, it stalls growth
- InverseChemVal = 0.35
- InverseChem = "BEsmaller" //At really impure vols, it just becomes 100% inverse
+ impure_chem = "BEsmaller" //If you make an inpure chem, it stalls growth
+ inverse_chem_val = 0.35
+ inverse_chem = "BEsmaller" //At really impure vols, it just becomes 100% inverse
can_synth = FALSE
/datum/reagent/fermi/breast_enlarger/on_mob_add(mob/living/carbon/M)
@@ -98,10 +98,15 @@
B.cached_size = B.cached_size + 0.05
if (B.cached_size >= 8.5 && B.cached_size < 9)
if(H.w_uniform || H.wear_suit)
- var/target = M.get_bodypart(BODY_ZONE_CHEST)
- to_chat(M, "Your breasts begin to strain against your clothes tightly!")
- M.adjustOxyLoss(5, 0)
- M.apply_damage(1, BRUTE, target)
+ //Hyper change// Check for a flag before we remove clothes.
+ var/obj/item/clothing/suit = H.get_item_by_slot(SLOT_W_UNIFORM)
+ var/obj/item/clothing/jacket = H.get_item_by_slot(SLOT_WEAR_SUIT)
+ if(!suit.roomy == 1 || !jacket.roomy == 1) //If the clothes are "roomy" then don't do this.
+ //End Hyper Change//
+ var/target = M.get_bodypart(BODY_ZONE_CHEST)
+ to_chat(M, "Your breasts begin to strain against your clothes tightly!")
+ M.adjustOxyLoss(5, 0)
+ M.apply_damage(1, BRUTE, target)
B.update()
..()
@@ -140,7 +145,7 @@
/datum/reagent/fermi/BEsmaller
name = "Modesty milk"
id = "BEsmaller"
- description = "A volatile collodial mixture derived from milk that encourages mammary reduction via a potent estrogen mix."
+ description = "A volatile collodial mixture derived from milk that encourages mammary reduction via a potent estrogen mix. Produced by reacting impure Succubus milk."
color = "#E60584" // rgb: 96, 0, 255
taste_description = "a milky ice cream like flavour."
metabolization_rate = 0.25
@@ -211,9 +216,9 @@
taste_description = "chinese dragon powder"
overdose_threshold = 17 //ODing makes you male and removes female genitals
metabolization_rate = 0.5
- ImpureChem = "PEsmaller" //If you make an inpure chem, it stalls growth
- InverseChemVal = 0.35
- InverseChem = "PEsmaller" //At really impure vols, it just becomes 100% inverse and shrinks instead.
+ impure_chem = "PEsmaller" //If you make an inpure chem, it stalls growth
+ inverse_chem_val = 0.35
+ inverse_chem = "PEsmaller" //At really impure vols, it just becomes 100% inverse and shrinks instead.
can_synth = FALSE
/datum/reagent/fermi/penis_enlarger/on_mob_add(mob/living/carbon/M)
@@ -246,6 +251,7 @@
return
var/mob/living/carbon/human/H = M
var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
+ var/obj/item/organ/genital/testicles/T = M.getorganslot("testicles") //Hyper Change
if(!P)//They do have a preponderance for escapism, or so I've heard.
//If they have Acute hepatic pharmacokinesis, then route processing though liver.
@@ -268,14 +274,45 @@
nP.prev_length = 1
M.reagents.remove_reagent(id, 5)
P = nP
+
+ if(!T)//Hyper change// Adds testicles if there are none.
+
+ //If they have Acute hepatic pharmacokinesis, then route processing though liver.
+ if(HAS_TRAIT(M, TRAIT_PHARMA))
+ var/obj/item/organ/liver/L = M.getorganslot("liver")
+ if(L)
+ L.swelling+= 0.05
+ return..()
+ else
+ M.adjustToxLoss(1)
+ return..()
+
+ //otherwise proceed as normal
+ var/obj/item/organ/genital/testicles/nT = new
+ nT.Insert(M)
+ if(nT)
+ nT.size = BALLS_SIZE_MIN
+ to_chat(M, "Your groin feels warm, as you feel two sensitive orbs taking shape below.")
+ nT.cached_size = 1
+ nT.sack_size = BALLS_SACK_SIZE_DEF
+ T = nT
P.cached_length = P.cached_length + 0.1
+ //Hyper change// Increase ball size too
+ T.size = T.size + 0.1
+
if (P.cached_length >= 20.5 && P.cached_length < 21)
if(H.w_uniform || H.wear_suit|| H.arousalloss > 33)
- var/target = M.get_bodypart(BODY_ZONE_CHEST)
- to_chat(M, "Your cock begins to strain against your clothes tightly!")
- M.apply_damage(1, BRUTE, target)
+ //Hyper change// Check for a flag before we remove clothes.
+ var/obj/item/clothing/suit = H.get_item_by_slot(SLOT_W_UNIFORM)
+ var/obj/item/clothing/jacket = H.get_item_by_slot(SLOT_WEAR_SUIT)
+ if(!suit.roomy == 1 || !jacket.roomy == 1) //If the clothes are "roomy" then don't do this.
+ //End Hyper Change//
+ var/target = M.get_bodypart(BODY_ZONE_CHEST)
+ to_chat(M, "Your cock begins to strain against your clothes tightly!")
+ M.apply_damage(1, BRUTE, target)
+ T.update() //Hyper change - Make the ball size update
P.update()
..()
@@ -311,7 +348,7 @@
/datum/reagent/fermi/PEsmaller // Due to cozmo's request...!
name = "Chastity draft"
id = "PEsmaller"
- description = "A volatile collodial mixture derived from various masculine solutions that encourages a smaller gentleman's package via a potent testosterone mix, formula derived from a collaboration from Fermichem and Doctor Ronald Hyatt, who is well known for his phallus palace."
+ description = "A volatile collodial mixture derived from various masculine solutions that encourages a smaller gentleman's package via a potent testosterone mix. Produced by reacting impure Incubus draft."
color = "#888888" // This is greyish..?
taste_description = "chinese dragon powder"
metabolization_rate = 0.5
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm
index a7c4ea00..4cb8ea0c 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm
@@ -6,58 +6,20 @@
id = "fermi"
taste_description = "affection and love!"
can_synth = FALSE
+ //SplitChem = TRUE
+ impure_chem = "fermiTox"// What chemical is metabolised with an inpure reaction
+ inverse_chem_val = 0.25 // If the impurity is below 0.5, replace ALL of the chem with inverse_chemupon metabolising
+ inverse_chem = "fermiTox"
//This should process fermichems to find out how pure they are and what effect to do.
/datum/reagent/fermi/on_mob_add(mob/living/carbon/M, amount)
. = ..()
- if(!M)
- return
- if(purity < 0)
- CRASH("Purity below 0 for chem: [id], Please let Fermis Know!")
- if (purity == 1 || DoNotSplit == TRUE)
- log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [id]")
- return
- else if (InverseChemVal > purity)//Turns all of a added reagent into the inverse chem
- M.reagents.remove_reagent(id, amount, FALSE)
- M.reagents.add_reagent(InverseChem, amount, FALSE, other_purity = 1)
- log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [InverseChem]")
- return
- else
- var/impureVol = amount * (1 - purity) //turns impure ratio into impure chem
- M.reagents.remove_reagent(id, (impureVol), FALSE)
- M.reagents.add_reagent(ImpureChem, impureVol, FALSE, other_purity = 1)
- log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume - impureVol]u of [id]")
- log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [ImpureChem]")
- return
+
//When merging two fermichems, see above
/datum/reagent/fermi/on_merge(data, amount, mob/living/carbon/M, purity)//basically on_mob_add but for merging
. = ..()
- if(!ishuman(M))
- return
- if (purity < 0)
- CRASH("Purity below 0 for chem: [id], Please let Fermis Know!")
- if (purity == 1 || DoNotSplit == TRUE)
- log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [id] in themselves")
- return
- else if (InverseChemVal > purity)
- M.reagents.remove_reagent(id, amount, FALSE)
- M.reagents.add_reagent(InverseChem, amount, FALSE, other_purity = 1)
- for(var/datum/reagent/fermi/R in M.reagents.reagent_list)
- if(R.name == "")
- R.name = name//Negative effects are hidden
- log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [InverseChem]")
- return
- else
- var/impureVol = amount * (1 - purity)
- M.reagents.remove_reagent(id, impureVol, FALSE)
- M.reagents.add_reagent(ImpureChem, impureVol, FALSE, other_purity = 1)
- for(var/datum/reagent/fermi/R in M.reagents.reagent_list)
- if(R.name == "")
- R.name = name//Negative effects are hidden
- log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume - impureVol]u of [id]")
- log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [ImpureChem]")
- return
+
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -77,7 +39,7 @@
taste_description = "like jerky, whiskey and an off aftertaste of a crypt."
metabolization_rate = 0.2
overdose_threshold = 25
- DoNotSplit = TRUE
+ chemical_flags = REAGENT_DONOTSPLIT
pH = 4
can_synth = TRUE
@@ -122,9 +84,9 @@
color = "#f9b9bc" // rgb: , 0, 255
taste_description = "dewicious degenyewacy"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
- InverseChemVal = 0
+ inverse_chem_val = 0
var/obj/item/organ/tongue/nT
- DoNotSplit = TRUE
+ chemical_flags = REAGENT_DONOTSPLIT
pH = 5
var/obj/item/organ/tongue/T
can_synth = TRUE
@@ -211,9 +173,9 @@
description = "A stablised EMP that is highly volatile, shocking small nano machines that will kill them off at a rapid rate in a patient's system."
color = "#708f8f"
overdose_threshold = 15
- ImpureChem = "nanite_b_goneTox" //If you make an inpure chem, it stalls growth
- InverseChemVal = 0.25
- InverseChem = "nanite_b_goneTox" //At really impure vols, it just becomes 100% inverse
+ impure_chem = "nanite_b_goneTox" //If you make an inpure chem, it stalls growth
+ inverse_chem_val = 0.25
+ inverse_chem = "nanite_b_goneTox" //At really impure vols, it just becomes 100% inverse
taste_description = "what can only be described as licking a battery."
pH = 9
can_synth = FALSE
@@ -236,7 +198,7 @@
//empulse((get_turf(C)), 3, 2)//So the nanites randomize
var/atom/T = C
T.emp_act(EMP_HEAVY)
- to_chat(C, "The nanites short circuit within your system!")
+ to_chat(C, "You feel a strange tingling sensation come from your core.")
if(isnull(N))
return ..()
N.nanite_volume = -2
@@ -246,10 +208,11 @@
O.emp_act(EMP_HEAVY)
/datum/reagent/fermi/nanite_b_goneTox
- name = "Naninte bain"
+ name = "Electromagnetic crystals"
id = "nanite_b_goneTox"
- description = "Poorly made, and shocks you!"
- metabolization_rate = 1
+ description = "Causes items upon the patient to sometimes short out, as well as causing a shock in the patient, if the residual charge between the crystals builds up to sufficient quantities"
+ metabolization_rate = 0.5
+ chemical_flags = REAGENT_INVISIBLE
//Increases shock events.
/datum/reagent/fermi/nanite_b_goneTox/on_mob_life(mob/living/carbon/C)//Damages the taker if their purity is low. Extended use of impure chemicals will make the original die. (thus can't be spammed unless you've very good)
@@ -314,7 +277,7 @@
name = "Fermis Test Reagent"
id = "fermiTest"
description = "You should be really careful with this...! Also, how did you get this?"
- addProc = TRUE
+ chemical_flags = REAGENT_FORCEONNEW
can_synth = FALSE
/datum/reagent/fermi/fermiTest/on_new(datum/reagents/holder)
@@ -345,22 +308,6 @@
playsound(get_turf(M), 'modular_citadel/sound/voice/merowr.ogg', 50, 1)
holder.clear_reagents()
-/datum/reagent/fermi/fermiTox
- name = "FermiTox"
- id = "fermiTox"
- description = "You should be really careful with this...! Also, how did you get this? You shouldn't have this!"
- data = "merge"
- color = "FFFFFF"
- can_synth = FALSE
-
-//I'm concerned this is too weak, but I also don't want deathmixes.
-/datum/reagent/fermi/fermiTox/on_mob_life(mob/living/carbon/C, method)
- if(C.dna && istype(C.dna.species, /datum/species/jelly))
- C.adjustToxLoss(-2)
- else
- C.adjustToxLoss(2)
- ..()
-
/datum/reagent/fermi/acidic_buffer
name = "Acidic buffer"
id = "acidic_buffer"
@@ -371,9 +318,11 @@
//Consumes self on addition and shifts pH
/datum/reagent/fermi/acidic_buffer/on_new(datapH)
+ if(holder.has_reagent("stabilizing_agent"))
+ return ..()
data = datapH
if(LAZYLEN(holder.reagent_list) == 1)
- return
+ return ..()
holder.pH = ((holder.pH * holder.total_volume)+(pH * (volume)))/(holder.total_volume + (volume))
var/list/seen = viewers(5, get_turf(holder))
for(var/mob/M in seen)
@@ -391,9 +340,11 @@
can_synth = TRUE
/datum/reagent/fermi/basic_buffer/on_new(datapH)
+ if(holder.has_reagent("stabilizing_agent"))
+ return ..()
data = datapH
if(LAZYLEN(holder.reagent_list) == 1)
- return
+ return ..()
holder.pH = ((holder.pH * holder.total_volume)+(pH * (volume)))/(holder.total_volume + (volume))
var/list/seen = viewers(5, get_turf(holder))
for(var/mob/M in seen)
@@ -458,4 +409,4 @@
H.say("*wag")//force update sprites.
to_chat(H, "[words]")
qdel(catto)
- log_game("FERMICHEM: [H] ckey: [H.key] has returned to normal")
+ log_game("FERMICHEM: [H] ckey: [H.key] has returned to normal")
\ No newline at end of file
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm
index d5c675ea..12c0ef43 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm
@@ -6,9 +6,9 @@
color = "#68e83a"
pH = 8.6
overdose_threshold = 35
- ImpureChem = "yamerol_tox"
- InverseChemVal = 0.4
- InverseChem = "yamerol_tox"
+ impure_chem = "yamerol_tox"
+ inverse_chem_val = 0.4
+ inverse_chem = "yamerol_tox"
can_synth = TRUE
/datum/reagent/fermi/yamerol/on_mob_life(mob/living/carbon/C)
@@ -73,15 +73,15 @@
C.adjustOxyLoss(-3)
..()
-/datum/reagent/fermi/yamerol_tox
- name = "Yamerol"
+/datum/reagent/impure/yamerol_tox
+ name = "Yamer oh no"
id = "yamerol_tox"
- description = "For when you've trouble speaking or breathing, just yell YAMEROL! A chem that helps soothe any congestion problems and at high concentrations restores damaged lungs and tongues!"
+ description = "A dangerous, cloying toxin that stucks to a patient’s respiratory system, damaging their tongue, lungs and causing suffocation."
taste_description = "a weird, syrupy flavour, yamero"
color = "#68e83a"
pH = 8.6
-/datum/reagent/fermi/yamerol_tox/on_mob_life(mob/living/carbon/C)
+/datum/reagent/impure/yamerol_tox/on_mob_life(mob/living/carbon/C)
var/obj/item/organ/tongue/T = C.getorganslot(ORGAN_SLOT_TONGUE)
var/obj/item/organ/lungs/L = C.getorganslot(ORGAN_SLOT_LUNGS)
diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
index 2a32276b..fbad8c8f 100644
--- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm
@@ -6,11 +6,29 @@
return
//Called when reaction STOP_PROCESSING
-/datum/chemical_reaction/fermi/proc/FermiFinish(datum/reagents/holder)
+/datum/chemical_reaction/proc/FermiFinish(datum/reagents/holder, var/atom/my_atom, reactVol)
+ if(clear_conversion == REACTION_CLEAR_IMPURE | REACTION_CLEAR_INVERSE)
+ for(var/id in results)
+ var/datum/reagent/R = my_atom.reagents.has_reagent("[id]")
+ if(R.purity == 1)
+ continue
+
+ var/cached_volume = R.volume
+ if(clear_conversion == REACTION_CLEAR_INVERSE && R.inverse_chem)
+ if(R.inverse_chem_val > R.purity)
+ my_atom.reagents.remove_reagent(R.id, cached_volume, FALSE)
+ my_atom.reagents.add_reagent(R.inverse_chem, cached_volume, FALSE, other_purity = 1)
+
+ else if (clear_conversion == REACTION_CLEAR_IMPURE && R.impure_chem)
+ var/impureVol = cached_volume * (1 - R.purity)
+ my_atom.reagents.remove_reagent(R.id, (impureVol), FALSE)
+ my_atom.reagents.add_reagent(R.impure_chem, impureVol, FALSE, other_purity = 1)
+ R.cached_purity = R.purity
+ R.purity = 1
return
//Called when temperature is above a certain threshold, or if purity is too low.
-/datum/chemical_reaction/fermi/proc/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH, Exploding = FALSE)
+/datum/chemical_reaction/proc/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH, Exploding = FALSE)
if (Exploding == TRUE)
return
diff --git a/modular_citadel/code/modules/reagents/reagent container/milking machine.dm b/modular_citadel/code/modules/reagents/reagent container/milking machine.dm
new file mode 100644
index 00000000..4aa6520d
--- /dev/null
+++ b/modular_citadel/code/modules/reagents/reagent container/milking machine.dm
@@ -0,0 +1,83 @@
+/obj/item/milker
+ icon = 'modular_citadel/icons/obj/milking machine.dmi'
+ name = "milking machine"
+ icon_state = "Off"
+ item_state = "Off"
+ desc = "A pocket sized pump and tubing assembly designed to collect and store products from mammary glands."
+
+ slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_POCKET
+
+ var/on = FALSE
+ var/obj/item/reagent_containers/glass/inserted_item = null
+
+ var/transfer_rate = 1 // How much we transfer every 2 seconds
+ var/target_organ = "breasts" // What organ we are transfering from
+
+/obj/item/milker/examine(mob/user)
+ . = ..()
+ to_chat(user, "[src] is currently [on ? "on" : "off"].")
+ if (inserted_item)
+ to_chat(user, "[inserted_item] contains [inserted_item.reagents.total_volume]/[inserted_item.reagents.maximum_volume] units")
+
+/obj/item/milker/attackby(obj/item/W, mob/user, params)
+ add_fingerprint(user)
+ if(istype(W, /obj/item/reagent_containers/glass) && !inserted_item)
+ if(!user.transferItemToLoc(W, src))
+ return ..()
+ inserted_item = W
+ UpdateIcon()
+ else
+ return ..()
+
+/obj/item/milker/interact(mob/user)
+ if(!isAI(user) && inserted_item)
+ add_fingerprint(user)
+ on = !on
+ if (on)
+ to_chat(user, "You turn [src] on.")
+ START_PROCESSING(SSobj, src)
+ else
+ to_chat(user, "You turn [src] off.")
+ STOP_PROCESSING(SSobj, src)
+ UpdateIcon()
+ else
+ ..()
+
+/obj/item/milker/proc/UpdateIcon()
+ icon_state = "[on ? "On" : "Off"][inserted_item ? "Beaker" : ""]"
+ item_state = icon_state
+
+
+/obj/item/milker/AltClick(mob/living/user)
+ add_fingerprint(user)
+ user.put_in_hands(inserted_item)
+ inserted_item = null
+ on = FALSE
+ STOP_PROCESSING(SSobj, src)
+ UpdateIcon()
+
+/obj/item/milker/process()
+ var/mob/living/carbon/W = loc
+ if (W)
+ var/obj/item/organ/genital/breasts/O = W.getorganslot(target_organ)
+ if (O)
+ if (O.reagents.total_volume >= transfer_rate * 2)
+ if (inserted_item.reagents.total_volume < inserted_item.reagents.maximum_volume)
+ O.reagents.trans_to(inserted_item.reagents, amount = transfer_rate)
+ else
+ to_chat(W, "[src] stops pumping. [inserted_item] is full.")
+ on = FALSE
+ STOP_PROCESSING(SSobj, src)
+ UpdateIcon()
+
+/obj/item/milker/penis
+ name = "penis milking machine"
+ icon_state = "PenisOff"
+ item_state = "PenisOff"
+ desc = "A pocket sized pump and tubing assembly designed to collect and store products from the penis."
+
+ target_organ = "testicles" // Since semen is stored in the balls
+
+/obj/item/milker/penis/UpdateIcon()
+ icon_state = "Penis[on ? "On" : "Off"][inserted_item ? "Beaker" : ""]"
+ item_state = icon_state
diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
index 38751db9..0337d213 100644
--- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
+++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm
@@ -10,6 +10,9 @@
color = "#FFFFFF" // rgb: 255, 255, 255
can_synth = FALSE
nutriment_factor = 0.5 * REAGENTS_METABOLISM
+ glass_icon_state = "semen"
+ glass_name = "chalice of semen"
+ glass_desc = "In the Sumerian mythology, Enki - the God of water, was believed to have created the Tigris and Euphrates rivers by masturbating and ejaculating into their empty riverbeds."
/datum/reagent/consumable/semen/reaction_turf(turf/T, reac_volume)
if(!istype(T))
@@ -85,7 +88,7 @@
S = new(T)
if(data["blood_DNA"])
S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
-
+
/datum/reagent/consumable/milk/reaction_turf(turf/T, reac_volume)
if(!istype(T))
return
diff --git a/modular_citadel/icons/mob/digishoes.dmi b/modular_citadel/icons/mob/digishoes.dmi
index 3d568863..ee4414b6 100644
Binary files a/modular_citadel/icons/mob/digishoes.dmi and b/modular_citadel/icons/mob/digishoes.dmi differ
diff --git a/modular_citadel/icons/mob/mam_markings.dmi b/modular_citadel/icons/mob/mam_markings.dmi
index 8327be6e..cd1afeb4 100644
Binary files a/modular_citadel/icons/mob/mam_markings.dmi and b/modular_citadel/icons/mob/mam_markings.dmi differ
diff --git a/modular_citadel/icons/mob/mam_tails.dmi b/modular_citadel/icons/mob/mam_tails.dmi
index b16de1c0..ec52ccfc 100644
Binary files a/modular_citadel/icons/mob/mam_tails.dmi and b/modular_citadel/icons/mob/mam_tails.dmi differ
diff --git a/modular_citadel/icons/mob/markings_notmammals.dmi b/modular_citadel/icons/mob/markings_notmammals.dmi
index 59b10e93..9ef0b9ef 100644
Binary files a/modular_citadel/icons/mob/markings_notmammals.dmi and b/modular_citadel/icons/mob/markings_notmammals.dmi differ
diff --git a/modular_citadel/icons/mob/mutant_bodyparts.dmi b/modular_citadel/icons/mob/mutant_bodyparts.dmi
index 0b195e55..f2edf133 100644
Binary files a/modular_citadel/icons/mob/mutant_bodyparts.dmi and b/modular_citadel/icons/mob/mutant_bodyparts.dmi differ
diff --git a/modular_citadel/icons/mob/muzzled_mask.dmi b/modular_citadel/icons/mob/muzzled_mask.dmi
index 9e8ac12e..fafc1576 100644
Binary files a/modular_citadel/icons/mob/muzzled_mask.dmi and b/modular_citadel/icons/mob/muzzled_mask.dmi differ
diff --git a/modular_citadel/icons/mob/suit_digi.dmi b/modular_citadel/icons/mob/suit_digi.dmi
index d348d71d..eeda8c37 100644
Binary files a/modular_citadel/icons/mob/suit_digi.dmi and b/modular_citadel/icons/mob/suit_digi.dmi differ
diff --git a/modular_citadel/icons/mob/uniform_digi.dmi b/modular_citadel/icons/mob/uniform_digi.dmi
index a741fbff..eaa4245f 100644
Binary files a/modular_citadel/icons/mob/uniform_digi.dmi and b/modular_citadel/icons/mob/uniform_digi.dmi differ
diff --git a/modular_citadel/icons/obj/clothing/trek_item_icon.dmi b/modular_citadel/icons/obj/clothing/trek_item_icon.dmi
index ed328661..570acbf4 100644
Binary files a/modular_citadel/icons/obj/clothing/trek_item_icon.dmi and b/modular_citadel/icons/obj/clothing/trek_item_icon.dmi differ
diff --git a/modular_citadel/icons/obj/genitals/breasts_onmob.dmi b/modular_citadel/icons/obj/genitals/breasts_onmob.dmi
index 371041b6..e4bcaa1f 100644
Binary files a/modular_citadel/icons/obj/genitals/breasts_onmob.dmi and b/modular_citadel/icons/obj/genitals/breasts_onmob.dmi differ
diff --git a/modular_citadel/icons/obj/genitals/effects.dmi b/modular_citadel/icons/obj/genitals/effects.dmi
index 00d934a6..e5e62738 100644
Binary files a/modular_citadel/icons/obj/genitals/effects.dmi and b/modular_citadel/icons/obj/genitals/effects.dmi differ
diff --git a/modular_citadel/icons/obj/genitals/penis_onmob.dmi b/modular_citadel/icons/obj/genitals/penis_onmob.dmi
index 6ad0628d..1373fc0f 100644
Binary files a/modular_citadel/icons/obj/genitals/penis_onmob.dmi and b/modular_citadel/icons/obj/genitals/penis_onmob.dmi differ
diff --git a/modular_citadel/icons/obj/genitals/testicles_onmob.dmi b/modular_citadel/icons/obj/genitals/testicles_onmob.dmi
index 33659cf1..4b75abbc 100644
Binary files a/modular_citadel/icons/obj/genitals/testicles_onmob.dmi and b/modular_citadel/icons/obj/genitals/testicles_onmob.dmi differ
diff --git a/modular_citadel/interface/skin.dmf b/modular_citadel/interface/skin.dmf
index 3c766db6..b822aa46 100644
--- a/modular_citadel/interface/skin.dmf
+++ b/modular_citadel/interface/skin.dmf
@@ -54,7 +54,7 @@ window "mainwindow"
size = 640x440
anchor1 = none
anchor2 = none
- background-color = #eeeeee
+ background-color = #242424
is-default = true
saved-params = "pos;size;is-minimized;is-maximized"
icon = 'icons\\ss13_64.png'
@@ -66,7 +66,7 @@ window "mainwindow"
size = 637x440
anchor1 = 0,0
anchor2 = 100,100
- background-color = #eeeeee
+ background-color = #272727
saved-params = "splitter"
left = "mapwindow"
right = "infowindow"
@@ -78,7 +78,7 @@ window "mainwindow"
size = 200x200
anchor1 = none
anchor2 = none
- background-color = #ffffff
+ background-color = #272727
is-visible = false
saved-params = ""
elem "tooltip"
@@ -87,7 +87,7 @@ window "mainwindow"
size = 999x999
anchor1 = none
anchor2 = none
- background-color = #ffffff
+ background-color = #272727
is-visible = false
saved-params = ""
@@ -111,6 +111,7 @@ window "mapwindow"
is-default = true
saved-params = "icon-size"
zoom-mode = distort
+ style=".center { text-align: center; } .maptext { font-family: 'Small Fonts'; font-size: 7px; -dm-text-outline: 1px black; color: white; line-height: 1.1; } .command_headset { font-weight: bold; font-size: 8px; } .small { font-size: 6px; } .big { font-size: 8px; } .reallybig { font-size: 8px; } .extremelybig { font-size: 8px; } .greentext { color: #00FF00; font-size: 7px; } .redtext { color: #FF0000; font-size: 7px; } .clown { color: #FF69Bf; font-size: 7px; font-weight: bold; } .his_grace { color: #15D512; } .hypnophrase { color: #0d0d0d; font-weight: bold; } .yell { font-weight: bold; } .italics { font-size: 6px; }"
window "infowindow"
elem "infowindow"
@@ -119,7 +120,7 @@ window "infowindow"
size = 640x480
anchor1 = none
anchor2 = none
- background-color = #eeeeee
+ background-color = #242424
saved-params = "pos;size;is-minimized;is-maximized"
is-pane = true
elem "info"
@@ -128,6 +129,7 @@ window "infowindow"
size = 640x445
anchor1 = 0,0
anchor2 = 100,100
+ background-color = #272727
saved-params = "splitter"
left = "statwindow"
right = "outputwindow"
@@ -138,7 +140,8 @@ window "infowindow"
size = 104x20
anchor1 = 3,0
anchor2 = 19,0
- background-color = #90b3dd
+ text-color = #e0e0e0
+ background-color = #40628a
saved-params = "is-checked"
text = "Changelog"
command = "changelog"
@@ -148,7 +151,8 @@ window "infowindow"
size = 100x20
anchor1 = 19,0
anchor2 = 34,0
- background-color = #90b3dd
+ text-color = #e0e0e0
+ background-color = #40628a
saved-params = "is-checked"
text = "Rules"
command = "rules"
@@ -158,7 +162,8 @@ window "infowindow"
size = 100x20
anchor1 = 34,0
anchor2 = 50,0
- background-color = #90b3dd
+ text-color = #e0e0e0
+ background-color = #40628a
saved-params = "is-checked"
text = "Wiki"
command = "wiki"
@@ -168,7 +173,8 @@ window "infowindow"
size = 100x20
anchor1 = 50,0
anchor2 = 66,0
- background-color = #90b3dd
+ text-color = #e0e0e0
+ background-color = #40628a
saved-params = "is-checked"
text = "Forum"
command = "forum"
@@ -178,7 +184,8 @@ window "infowindow"
size = 100x20
anchor1 = 66,0
anchor2 = 81,0
- background-color = #90b3dd
+ text-color = #e0e0e0
+ background-color = #40628a
saved-params = "is-checked"
text = "GitHub"
command = "github"
@@ -189,7 +196,8 @@ window "infowindow"
anchor1 = 81,0
anchor2 = 97,0
font-size = 8
- background-color = #ef7f7f
+ text-color = #e0e0e0
+ background-color = #A92c2c
saved-params = "is-checked"
text = "Report Issue"
command = "report-issue"
@@ -201,7 +209,7 @@ window "outputwindow"
size = 640x480
anchor1 = none
anchor2 = none
- background-color = #eeeeee
+ background-color = #272727
saved-params = "pos;size;is-minimized;is-maximized"
titlebar = false
statusbar = false
@@ -225,7 +233,8 @@ window "outputwindow"
size = 37x20
anchor1 = 100,100
anchor2 = none
- background-color = #eeeeee
+ text-color = #e0e0e0
+ background-color = #272727
saved-params = "is-checked"
text = "Chat"
command = ".winset \"say.is-checked=true ? input.command=\"!say \\\"\" : input.command=\""
@@ -237,7 +246,7 @@ window "outputwindow"
size = 640x456
anchor1 = 0,0
anchor2 = 100,100
- background-color = #ffffff
+ background-color = #272727
is-visible = false
is-disabled = true
saved-params = ""
@@ -248,6 +257,8 @@ window "outputwindow"
size = 640x456
anchor1 = 0,0
anchor2 = 100,100
+ text-color = #e0e0e0
+ background-color = #272727
is-default = true
saved-params = ""
@@ -258,7 +269,7 @@ window "statwindow"
size = 640x480
anchor1 = none
anchor2 = none
- background-color = #eeeeee
+ background-color = #242424
saved-params = "pos;size;is-minimized;is-maximized"
is-pane = true
elem "stat"
@@ -267,9 +278,14 @@ window "statwindow"
size = 640x480
anchor1 = 0,0
anchor2 = 100,100
+ text-color = #e0e0e0
+ background-color = #272727
is-default = true
saved-params = ""
- tab-background-color = #eeeeee
+ tab-text-color = #e0e0e0
+ tab-background-color = #242424
+ prefix-color = #e0e0e0
+ suffix-color = #e0e0e0
window "preferences_window"
elem "preferences_window"
diff --git a/sound/FermiChem/SoundSources.txt b/sound/FermiChem/SoundSources.txt
index bd45f866..1420814d 100644
--- a/sound/FermiChem/SoundSources.txt
+++ b/sound/FermiChem/SoundSources.txt
@@ -6,5 +6,6 @@ heatacid.ogg - from https://freesound.org/people/klankbeeld/sounds/233697/
from bubbles2.ogg
from fuse.ogg
bufferadd.ogg- https://freesound.org/people/toiletrolltube/sounds/181483/
+heatdamn.ogg - from https://freesound.org/people/klankbeeld/sounds/233697/
Work is licensed under the Creative Commons and Attribution License.
\ No newline at end of file
diff --git a/sound/FermiChem/heatdam.ogg b/sound/FermiChem/heatdam.ogg
new file mode 100644
index 00000000..ab8492e9
Binary files /dev/null and b/sound/FermiChem/heatdam.ogg differ
diff --git a/sound/creatures/goose1.ogg b/sound/creatures/goose1.ogg
new file mode 100644
index 00000000..3d605ad6
Binary files /dev/null and b/sound/creatures/goose1.ogg differ
diff --git a/sound/creatures/goose2.ogg b/sound/creatures/goose2.ogg
new file mode 100644
index 00000000..735faba7
Binary files /dev/null and b/sound/creatures/goose2.ogg differ
diff --git a/sound/creatures/goose3.ogg b/sound/creatures/goose3.ogg
new file mode 100644
index 00000000..1aeec773
Binary files /dev/null and b/sound/creatures/goose3.ogg differ
diff --git a/sound/creatures/goose4.ogg b/sound/creatures/goose4.ogg
new file mode 100644
index 00000000..699f143b
Binary files /dev/null and b/sound/creatures/goose4.ogg differ
diff --git a/sound/effects/footstep/heels.ogg b/sound/effects/footstep/heels.ogg
new file mode 100644
index 00000000..64006f00
Binary files /dev/null and b/sound/effects/footstep/heels.ogg differ
diff --git a/sound/music/allstarss13.ogg b/sound/music/allstarss13.ogg
new file mode 100644
index 00000000..aba3770b
Binary files /dev/null and b/sound/music/allstarss13.ogg differ
diff --git a/sound/music/bilegoatcargonia1.ogg b/sound/music/bilegoatcargonia1.ogg
new file mode 100644
index 00000000..be6c25b6
Binary files /dev/null and b/sound/music/bilegoatcargonia1.ogg differ
diff --git a/sound/music/bilegoatcargonia2.ogg b/sound/music/bilegoatcargonia2.ogg
new file mode 100644
index 00000000..11429e80
Binary files /dev/null and b/sound/music/bilegoatcargonia2.ogg differ
diff --git a/sound/music/goodbyemoonmen.ogg b/sound/music/goodbyemoonmen.ogg
deleted file mode 100644
index 3cf5d05c..00000000
Binary files a/sound/music/goodbyemoonmen.ogg and /dev/null differ
diff --git a/sound/music/goodbyespaceman.ogg b/sound/music/goodbyespaceman.ogg
new file mode 100644
index 00000000..e57de8f8
Binary files /dev/null and b/sound/music/goodbyespaceman.ogg differ
diff --git a/sound/music/sacredgeometry.ogg b/sound/music/sacredgeometry.ogg
new file mode 100644
index 00000000..635db4da
Binary files /dev/null and b/sound/music/sacredgeometry.ogg differ
diff --git a/sound/roundend/LAPD.ogg b/sound/roundend/LAPD.ogg
new file mode 100644
index 00000000..35213c85
Binary files /dev/null and b/sound/roundend/LAPD.ogg differ
diff --git a/sound/roundend/certifiedtittyman.ogg b/sound/roundend/certifiedtittyman.ogg
new file mode 100644
index 00000000..f808dcf8
Binary files /dev/null and b/sound/roundend/certifiedtittyman.ogg differ
diff --git a/sound/roundend/competitivejackingoff.ogg b/sound/roundend/competitivejackingoff.ogg
new file mode 100644
index 00000000..b6f40b45
Binary files /dev/null and b/sound/roundend/competitivejackingoff.ogg differ
diff --git a/sound/roundend/idbecryingtoobro.ogg b/sound/roundend/idbecryingtoobro.ogg
new file mode 100644
index 00000000..291a5836
Binary files /dev/null and b/sound/roundend/idbecryingtoobro.ogg differ
diff --git a/sound/roundend/quakingnuts.ogg b/sound/roundend/quakingnuts.ogg
new file mode 100644
index 00000000..42316991
Binary files /dev/null and b/sound/roundend/quakingnuts.ogg differ
diff --git a/sound/voice/gorillaplush.ogg b/sound/voice/gorillaplush.ogg
new file mode 100644
index 00000000..97823bd0
Binary files /dev/null and b/sound/voice/gorillaplush.ogg differ
diff --git a/sound/weapons/gunshot_braton.ogg b/sound/weapons/gunshot_braton.ogg
new file mode 100644
index 00000000..6929d4d6
Binary files /dev/null and b/sound/weapons/gunshot_braton.ogg differ
diff --git a/sound/weapons/gunshot_lato.ogg b/sound/weapons/gunshot_lato.ogg
new file mode 100644
index 00000000..c29201eb
Binary files /dev/null and b/sound/weapons/gunshot_lato.ogg differ
diff --git a/strings/names/verbs.txt b/strings/names/verbs.txt
index fc90f89e..623cf018 100644
--- a/strings/names/verbs.txt
+++ b/strings/names/verbs.txt
@@ -486,6 +486,7 @@ sigh
sign
signal
sin
+sing
sip
ski
skip
diff --git a/strings/round_start_sounds.txt b/strings/round_start_sounds.txt
index a8409188..03ff64cc 100644
--- a/strings/round_start_sounds.txt
+++ b/strings/round_start_sounds.txt
@@ -4,6 +4,7 @@ sound/ambience/title3.ogg
sound/ambience/title4.ogg
sound/misc/i_did_not_grief_them.ogg
sound/ambience/clown.ogg
+sound/music/sacredgeometry.ogg
sound/music/1.ogg
sound/music/carmenmirandasghost.ogg
sound/music/century21march.ogg
diff --git a/tgstation.dme b/tgstation.dme
index f257f5cf..e80c01fc 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -109,6 +109,7 @@
#include "code\__DEFINES\vv.dm"
#include "code\__DEFINES\wall_dents.dm"
#include "code\__DEFINES\wires.dm"
+#include "code\__DEFINES\dcs\signals.dm"
#include "code\__HELPERS\_cit_helpers.dm"
#include "code\__HELPERS\_lists.dm"
#include "code\__HELPERS\_logging.dm"
@@ -231,6 +232,7 @@
#include "code\controllers\subsystem\augury.dm"
#include "code\controllers\subsystem\autotransfer.dm"
#include "code\controllers\subsystem\blackbox.dm"
+#include "code\controllers\subsystem\chat.dm"
#include "code\controllers\subsystem\communications.dm"
#include "code\controllers\subsystem\dbcore.dm"
#include "code\controllers\subsystem\dcs.dm"
@@ -296,6 +298,7 @@
#include "code\datums\beam.dm"
#include "code\datums\browser.dm"
#include "code\datums\callback.dm"
+#include "code\datums\chatmessage.dm"
#include "code\datums\cinematic.dm"
#include "code\datums\dash_weapon.dm"
#include "code\datums\datacore.dm"
@@ -828,6 +831,7 @@
#include "code\game\objects\items\kitchen.dm"
#include "code\game\objects\items\latexballoon.dm"
#include "code\game\objects\items\manuals.dm"
+#include "code\game\objects\items\mesmetron.dm"
#include "code\game\objects\items\miscellaneous.dm"
#include "code\game\objects\items\mop.dm"
#include "code\game\objects\items\paint.dm"
@@ -2183,6 +2187,7 @@
#include "code\modules\mob\living\simple_animal\hostile\eyeballs.dm"
#include "code\modules\mob\living\simple_animal\hostile\faithless.dm"
#include "code\modules\mob\living\simple_animal\hostile\giant_spider.dm"
+#include "code\modules\mob\living\simple_animal\hostile\goose.dm"
#include "code\modules\mob\living\simple_animal\hostile\headcrab.dm"
#include "code\modules\mob\living\simple_animal\hostile\heart.dm"
#include "code\modules\mob\living\simple_animal\hostile\hivebot.dm"
@@ -2443,6 +2448,7 @@
#include "code\modules\projectiles\guns\ballistic\revolver.dm"
#include "code\modules\projectiles\guns\ballistic\shotgun.dm"
#include "code\modules\projectiles\guns\ballistic\toy.dm"
+#include "code\modules\projectiles\guns\energy\dueling.dm"
#include "code\modules\projectiles\guns\energy\energy_gun.dm"
#include "code\modules\projectiles\guns\energy\kinetic_accelerator.dm"
#include "code\modules\projectiles\guns\energy\laser.dm"
@@ -2519,6 +2525,7 @@
#include "code\modules\reagents\chemistry\reagents\drink_reagents.dm"
#include "code\modules\reagents\chemistry\reagents\drug_reagents.dm"
#include "code\modules\reagents\chemistry\reagents\food_reagents.dm"
+#include "code\modules\reagents\chemistry\reagents\impure_reagents.dm"
#include "code\modules\reagents\chemistry\reagents\medicine_reagents.dm"
#include "code\modules\reagents\chemistry\reagents\other_reagents.dm"
#include "code\modules\reagents\chemistry\reagents\pyrotechnic_reagents.dm"
@@ -2736,6 +2743,7 @@
#include "code\modules\station_goals\station_goal.dm"
#include "code\modules\surgery\amputation.dm"
#include "code\modules\surgery\brain_surgery.dm"
+#include "code\modules\surgery\breast_augmentation.dm"
#include "code\modules\surgery\cavity_implant.dm"
#include "code\modules\surgery\core_removal.dm"
#include "code\modules\surgery\coronary_bypass.dm"
@@ -2752,6 +2760,7 @@
#include "code\modules\surgery\nutcracker.dm"
#include "code\modules\surgery\organ_manipulation.dm"
#include "code\modules\surgery\organic_steps.dm"
+#include "code\modules\surgery\penis_augmentation.dm"
#include "code\modules\surgery\plastic_surgery.dm"
#include "code\modules\surgery\prosthetic_replacement.dm"
#include "code\modules\surgery\remove_embedded_object.dm"
@@ -2768,6 +2777,9 @@
#include "code\modules\surgery\advanced\viral_bonding.dm"
#include "code\modules\surgery\advanced\bioware\bioware.dm"
#include "code\modules\surgery\advanced\bioware\bioware_surgery.dm"
+#include "code\modules\surgery\advanced\bioware\experimental_dissection..dm"
+#include "code\modules\surgery\advanced\bioware\ligament_hook.dm"
+#include "code\modules\surgery\advanced\bioware\ligament_reinforcement.dm"
#include "code\modules\surgery\advanced\bioware\nerve_grounding.dm"
#include "code\modules\surgery\advanced\bioware\nerve_splicing.dm"
#include "code\modules\surgery\advanced\bioware\vein_threading.dm"
@@ -2870,11 +2882,26 @@
#include "code\modules\zombie\items.dm"
#include "code\modules\zombie\organs.dm"
#include "hyperstation\code\gamemode\werewolf\werewolf.dm"
+#include "hyperstation\code\mobs\hugbot.dm"
#include "hyperstation\code\mobs\mimic.dm"
#include "hyperstation\code\mobs\werewolf.dm"
+#include "hyperstation\code\modules\traits.dm"
#include "hyperstation\code\modules\antagonists\werewolf\werewolf.dm"
+#include "hyperstation\code\modules\clothing\head.dm"
+#include "hyperstation\code\modules\crafting\recipes.dm"
+#include "hyperstation\code\modules\resize\holder_micro.dm"
+#include "hyperstation\code\modules\resize\resizing.dm"
+#include "hyperstation\code\modules\resize\sizegun.dm"
+#include "hyperstation\code\obj\bluespace sewing kit.dm"
#include "hyperstation\code\obj\decal.dm"
+#include "hyperstation\code\obj\fluff.dm"
+#include "hyperstation\code\obj\kinkyclothes.dm"
+#include "hyperstation\code\obj\leash.dm"
+#include "hyperstation\code\obj\milking machine.dm"
+#include "hyperstation\code\obj\plushes.dm"
#include "hyperstation\code\obj\pregnancytester.dm"
+#include "hyperstation\code\obj\rewards.dm"
+#include "hyperstation\code\obj\rope.dm"
#include "interface\interface.dm"
#include "interface\menu.dm"
#include "interface\stylesheet.dm"
@@ -3012,6 +3039,7 @@
#include "modular_citadel\code\modules\clothing\under\trek_under.dm"
#include "modular_citadel\code\modules\clothing\under\turtlenecks.dm"
#include "modular_citadel\code\modules\clothing\under\under.dm"
+#include "modular_citadel\code\modules\crafting\recipes.dm"
#include "modular_citadel\code\modules\custom_loadout\custom_items.dm"
#include "modular_citadel\code\modules\custom_loadout\load_to_mob.dm"
#include "modular_citadel\code\modules\custom_loadout\read_from_file.dm"
diff --git a/tgui/package-lock.json b/tgui/package-lock.json
index 3c1cad4b..6b370093 100644
--- a/tgui/package-lock.json
+++ b/tgui/package-lock.json
@@ -340,21 +340,14 @@
"integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
},
"async-done": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz",
- "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==",
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz",
+ "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==",
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.2",
- "process-nextick-args": "^1.0.7",
+ "process-nextick-args": "^2.0.0",
"stream-exhaust": "^1.0.1"
- },
- "dependencies": {
- "process-nextick-args": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
- "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
- }
}
},
"async-each": {
@@ -2004,11 +1997,12 @@
}
},
"d": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
- "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+ "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
"requires": {
- "es5-ext": "^0.10.9"
+ "es5-ext": "^0.10.50",
+ "type": "^1.0.1"
}
},
"date-now": {
@@ -2279,13 +2273,13 @@
}
},
"es5-ext": {
- "version": "0.10.50",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz",
- "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==",
+ "version": "0.10.53",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
+ "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
"requires": {
"es6-iterator": "~2.0.3",
- "es6-symbol": "~3.1.1",
- "next-tick": "^1.0.0"
+ "es6-symbol": "~3.1.3",
+ "next-tick": "~1.0.0"
}
},
"es6-iterator": {
@@ -2304,22 +2298,22 @@
"integrity": "sha1-lu258v2wGZWCKyY92KratnSBgbw="
},
"es6-symbol": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
- "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
+ "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
"requires": {
- "d": "1",
- "es5-ext": "~0.10.14"
+ "d": "^1.0.1",
+ "ext": "^1.1.2"
}
},
"es6-weak-map": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz",
- "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
+ "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
"requires": {
"d": "1",
- "es5-ext": "^0.10.14",
- "es6-iterator": "^2.0.1",
+ "es5-ext": "^0.10.46",
+ "es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.1"
}
},
@@ -2376,6 +2370,21 @@
"homedir-polyfill": "^1.0.1"
}
},
+ "ext": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
+ "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
+ "requires": {
+ "type": "^2.0.0"
+ },
+ "dependencies": {
+ "type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz",
+ "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow=="
+ }
+ }
+ },
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -2749,9 +2758,9 @@
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
},
"kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
},
"micromatch": {
"version": "3.1.10",
@@ -3409,9 +3418,9 @@
},
"dependencies": {
"glob": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
- "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -3892,9 +3901,9 @@
}
},
"has-symbols": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
- "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
},
"has-value": {
"version": "1.0.0",
@@ -4727,9 +4736,9 @@
},
"dependencies": {
"kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
}
}
},
@@ -5015,9 +5024,9 @@
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
},
"kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
},
"micromatch": {
"version": "3.1.10",
@@ -5133,9 +5142,9 @@
}
},
"minimist": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.3.tgz",
+ "integrity": "sha512-+bMdgqjMN/Z77a6NlY/I3U5LlRDbnmaAk6lDveAPKwSpcPM4tKAuYsvYF8xjhOPXhOYGe/73vVLVez5PW+jqhw=="
},
"mixin-deep": {
"version": "1.3.1",
@@ -6537,9 +6546,9 @@
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
},
"kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
},
"micromatch": {
"version": "3.1.10",
@@ -7434,6 +7443,11 @@
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
"integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw=="
},
+ "type": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+ "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
+ },
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
diff --git a/tgui/package.json b/tgui/package.json
index f26e29c9..a1fbb9fb 100644
--- a/tgui/package.json
+++ b/tgui/package.json
@@ -34,7 +34,7 @@
"gulplog": "1.0.0",
"html5shiv": "3.7.3",
"ie8": "0.8.0",
- "minimist": "1.2.0",
+ "minimist": "1.2.3",
"paths-js": "0.4.2",
"pleeease-filters": "2.0.0",
"postcss": "5.0.16",
diff --git a/tools/deploy.sh b/tools/deploy.sh
old mode 100644
new mode 100755
diff --git a/tools/travis/before_build_byond.sh b/tools/travis/before_build_byond.sh
old mode 100644
new mode 100755
diff --git a/tools/travis/before_build_tools.sh b/tools/travis/before_build_tools.sh
old mode 100644
new mode 100755
diff --git a/tools/travis/build_byond.sh b/tools/travis/build_byond.sh
old mode 100644
new mode 100755
diff --git a/tools/travis/build_dependencies.sh b/tools/travis/build_dependencies.sh
old mode 100644
new mode 100755
diff --git a/tools/travis/build_tools.sh b/tools/travis/build_tools.sh
old mode 100644
new mode 100755
diff --git a/tools/travis/check_filedirs.sh b/tools/travis/check_filedirs.sh
old mode 100644
new mode 100755
diff --git a/tools/travis/dm.sh b/tools/travis/dm.sh
old mode 100644
new mode 100755
diff --git a/tools/travis/install_build_tools.sh b/tools/travis/install_build_tools.sh
old mode 100644
new mode 100755