Refresh"
+ dat += "[PDAIMG(refresh)]Refresh"
if ((!isnull(cartridge)) && (mode == 0))
- dat += " |
Eject [cartridge]"
+ dat += " | [PDAIMG(eject)]Eject [cartridge]"
if (mode)
- dat += " |
Return"
+ dat += " | [PDAIMG(menu)]Return"
if (mode == 0)
dat += "
Retry"
+ dat += "[PDAIMG(refresh)]Retry"
else
switch (mode)
if (0)
@@ -221,38 +221,38 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += "
Notekeeper
Messenger
Honk Synthesizer
Sad Trombone
View Crew Manifest
Set Status Display
Power Monitor
Medical Records
[scanmode == 1 ? "Disable" : "Enable"] Medical Scanner
Security Records
Supply Records
Bots Access
Custodial Locator
Signaler System
Newscaster Access
[scanmode == 3 ? "Disable" : "Enable"] Reagent Scanner
[scanmode == 4 ? "Disable" : "Enable"] Halogen Counter
[scanmode == 5 ? "Disable" : "Enable"] Gas Scanner
Toggle Remote Door
Drone Phone
Atmospheric Scan
[fon ? "Disable" : "Enable"] Flashlight
Notekeeper V2.2
SpaceMessenger V3.9.6
Ringer: [silent == 1 ? "Off" : "On"] | "
- dat += "
Send / Receive: [toff == 1 ? "Off" : "On"] | "
- dat += "
Set Ringtone | "
- dat += "
Messages
Detected PDAs
SpaceMessenger V3.9.6
Clear Messages"
+ dat += "
Messages
Atmospheric Readings
Remote Signaling System
Crew Manifest
Station Status Display Interlink
Power Monitors - Please select one
Power Monitor
Medical Record List
Medical Record
Medical Data
Security Record List
Security Record
Security Data
Supply Record Interlink
Persistent Custodial Object Locator
Newscaster Access
Bots Interlink
refresh)
Return to bot list"
+ menu += "
Scan for active bots| "
if(jobban_isbanned(user, "appearance"))
@@ -490,6 +492,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "High"
dat += " " + dat += "Ambient Occlusion: [ambientocclusion ? "Enabled" : "Disabled"] " + dat += " | "
dat += "Special Role Settings" @@ -855,72 +859,72 @@ GLOBAL_LIST_EMPTY(preferences_datums) return job_engsec_low return 0 -/datum/preferences/proc/SetTraits(mob/user) - if(!SStraits) - to_chat(user, "The trait subsystem is still initializing! Try again in a minute.") +/datum/preferences/proc/SetQuirks(mob/user) + if(!SSquirks) + to_chat(user, "The quirk subsystem is still initializing! Try again in a minute.") return var/list/dat = list() - if(!SStraits.traits.len) - dat += "The trait subsystem hasn't finished initializing, please hold..." + if(!SSquirks.quirks.len) + dat += "The quirk subsystem hasn't finished initializing, please hold..." dat += "" else - dat += " " - dat += " Left-click to add or remove traits. You need one negative trait for every positive trait. "
+ dat += "\ - Traits are applied at roundstart and cannot normally be removed. " + dat += " Left-click to add or remove quirks. You need negative quirks to have positive ones. "
dat += "\ + Quirks are applied at roundstart and cannot normally be removed. " - dat += " \ - Trait balance remaining: [GetTraitBalance()] " - for(var/V in SStraits.traits) - var/datum/trait/T = SStraits.traits[V] - var/trait_name = initial(T.name) - var/has_trait - var/trait_cost = initial(T.value) * -1 + dat += " \ + Quirk balance remaining: [GetQuirkBalance()] " + for(var/V in SSquirks.quirks) + var/datum/quirk/T = SSquirks.quirks[V] + var/quirk_name = initial(T.name) + var/has_quirk + var/quirk_cost = initial(T.value) * -1 var/lock_reason = "This trait is unavailable." - var/trait_conflict = FALSE - for(var/_V in all_traits) - if(_V == trait_name) - has_trait = TRUE - if(initial(T.mood_trait) && CONFIG_GET(flag/disable_human_mood)) + var/quirk_conflict = FALSE + for(var/_V in all_quirks) + if(_V == quirk_name) + has_quirk = TRUE + if(initial(T.mood_quirk) && CONFIG_GET(flag/disable_human_mood)) lock_reason = "Mood is disabled." - trait_conflict = TRUE - if(has_trait) - if(trait_conflict) - all_traits -= trait_name - has_trait = FALSE + quirk_conflict = TRUE + if(has_quirk) + if(quirk_conflict) + all_quirks -= quirk_name + has_quirk = FALSE else - trait_cost *= -1 //invert it back, since we'd be regaining this amount - if(trait_cost > 0) - trait_cost = "+[trait_cost]" + quirk_cost *= -1 //invert it back, since we'd be regaining this amount + if(quirk_cost > 0) + quirk_cost = "+[quirk_cost]" var/font_color = "#AAAAFF" if(initial(T.value) != 0) font_color = initial(T.value) > 0 ? "#AAFFAA" : "#FFAAAA" - if(trait_conflict) - dat += "[trait_name] - [initial(T.desc)] \ + if(quirk_conflict) + dat += "[quirk_name] - [initial(T.desc)] \ LOCKED: [lock_reason] " else - if(has_trait) - dat += "[trait_name] - [initial(T.desc)] \ - [has_trait ? "Lose" : "Take"] ([trait_cost] pts.) " + if(has_quirk) + dat += "[quirk_name] - [initial(T.desc)] \ + [has_quirk ? "Lose" : "Take"] ([quirk_cost] pts.) " else - dat += "[trait_name] - [initial(T.desc)] \ - [has_trait ? "Lose" : "Take"] ([trait_cost] pts.) " + dat += "[quirk_name] - [initial(T.desc)] \ + [has_quirk ? "Lose" : "Take"] ([quirk_cost] pts.) " dat += " Trait Preferences ", 900, 600) //no reason not to reuse the occupation window, as it's cleaner that way
+ var/datum/browser/popup = new(user, "mob_occupation", "Quirk Preferences ", 900, 600) //no reason not to reuse the occupation window, as it's cleaner that way
popup.set_window_options("can_close=0")
popup.set_content(dat.Join())
popup.open(0)
return
-/datum/preferences/proc/GetTraitBalance()
+/datum/preferences/proc/GetQuirkBalance()
var/bal = 0
- for(var/V in all_traits)
- var/datum/trait/T = SStraits.traits[V]
+ for(var/V in all_quirks)
+ var/datum/quirk/T = SSquirks.quirks[V]
bal -= initial(T.value)
return bal
@@ -977,55 +981,49 @@ GLOBAL_LIST_EMPTY(preferences_datums)
user << browse(null, "window=mob_occupation")
ShowChoices(user)
if("update")
- var/trait = href_list["trait"]
- if(!SStraits.traits[trait])
+ var/quirk = href_list["trait"]
+ if(!SSquirks.quirks[quirk])
return
- var/value = SStraits.trait_points[trait]
+ var/value = SSquirks.quirk_points[quirk]
if(value == 0)
- if(trait in neutral_traits)
- neutral_traits -= trait
- all_traits -= trait
+ if(quirk in neutral_quirks)
+ neutral_quirks -= quirk
+ all_quirks -= quirk
else
- if(all_traits.len >= MAX_TRAITS)
- to_chat(user, "You can't have more than [MAX_TRAITS] traits!")
- return
- neutral_traits += trait
- all_traits += trait
+ neutral_quirks += quirk
+ all_quirks += quirk
else
- var/balance = GetTraitBalance()
- if(trait in positive_traits)
- positive_traits -= trait
- all_traits -= trait
- else if(trait in negative_traits)
+ var/balance = GetQuirkBalance()
+ if(quirk in positive_quirks)
+ positive_quirks -= quirk
+ all_quirks -= quirk
+ else if(quirk in negative_quirks)
if(balance + value < 0)
to_chat(user, "Refunding this would cause you to go below your balance!")
return
- negative_traits -= trait
- all_traits -= trait
+ negative_quirks -= quirk
+ all_quirks -= quirk
else if(value > 0)
- if(all_traits.len >= MAX_TRAITS)
- to_chat(user, "You can't have more than [MAX_TRAITS] traits!")
+ if(positive_quirks.len >= MAX_QUIRKS)
+ to_chat(user, "You can't have more than [MAX_QUIRKS] positive quirks!")
return
if(balance - value < 0)
- to_chat(user, "You don't have enough balance to gain this trait!")
+ to_chat(user, "You don't have enough balance to gain this quirk!")
return
- positive_traits += trait
- all_traits += trait
+ positive_quirks += quirk
+ all_quirks += quirk
else
- if(all_traits.len >= MAX_TRAITS)
- to_chat(user, "You can't have more than [MAX_TRAITS] traits!")
- return
- negative_traits += trait
- all_traits += trait
- SetTraits(user)
+ negative_quirks += quirk
+ all_quirks += quirk
+ SetQuirks(user)
if("reset")
- all_traits = list()
- positive_traits = list()
- negative_traits = list()
- neutral_traits = list()
- SetTraits(user)
+ all_quirks = list()
+ positive_quirks = list()
+ negative_quirks = list()
+ neutral_quirks = list()
+ SetQuirks(user)
else
- SetTraits(user)
+ SetQuirks(user)
return TRUE
switch(href_list["task"])
@@ -1535,6 +1533,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
cit_toggles ^= DIGESTION_NOISES
//END CITADEL EDIT
+ if("ambientocclusion")
+ ambientocclusion = !ambientocclusion
+ if(parent && parent.screen && parent.screen.len)
+ var/obj/screen/plane_master/game_world/PM = locate(/obj/screen/plane_master/game_world) in parent.screen
+ PM.filters -= AMBIENT_OCCLUSION
+ if(ambientocclusion)
+ PM.filters += AMBIENT_OCCLUSION
+
if("save")
save_preferences()
save_character()
@@ -1642,4 +1648,4 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(icon_updates)
character.update_body()
character.update_hair()
- character.update_body_parts()
\ No newline at end of file
+ character.update_body_parts()
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index d2efc477c6..f17ddf8b7c 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -130,6 +130,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["uses_glasses_colour"]>> uses_glasses_colour
S["clientfps"] >> clientfps
S["parallax"] >> parallax
+ S["ambientocclusion"] >> ambientocclusion
S["menuoptions"] >> menuoptions
S["enable_tips"] >> enable_tips
S["tip_delay"] >> tip_delay
@@ -160,6 +161,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
toggles = sanitize_integer(toggles, 0, 65535, initial(toggles))
clientfps = sanitize_integer(clientfps, 0, 1000, 0)
parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null)
+ ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form))
ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit))
ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION)
@@ -210,6 +212,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["uses_glasses_colour"], uses_glasses_colour)
WRITE_FILE(S["clientfps"], clientfps)
WRITE_FILE(S["parallax"], parallax)
+ WRITE_FILE(S["ambientocclusion"], ambientocclusion)
WRITE_FILE(S["menuoptions"], menuoptions)
WRITE_FILE(S["enable_tips"], enable_tips)
WRITE_FILE(S["tip_delay"], tip_delay)
@@ -310,11 +313,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["job_engsec_med"] >> job_engsec_med
S["job_engsec_low"] >> job_engsec_low
- //Traits
- S["all_traits"] >> all_traits
- S["positive_traits"] >> positive_traits
- S["negative_traits"] >> negative_traits
- S["neutral_traits"] >> neutral_traits
+ //Quirks
+ S["all_quirks"] >> all_quirks
+ S["positive_quirks"] >> positive_quirks
+ S["negative_quirks"] >> negative_quirks
+ S["neutral_quirks"] >> neutral_quirks
//Citadel code
S["feature_genitals_use_skintone"] >> features["genitals_use_skintone"]
@@ -421,10 +424,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
job_engsec_med = sanitize_integer(job_engsec_med, 0, 65535, initial(job_engsec_med))
job_engsec_low = sanitize_integer(job_engsec_low, 0, 65535, initial(job_engsec_low))
- all_traits = SANITIZE_LIST(all_traits)
- positive_traits = SANITIZE_LIST(positive_traits)
- negative_traits = SANITIZE_LIST(negative_traits)
- neutral_traits = SANITIZE_LIST(neutral_traits)
+ all_quirks = SANITIZE_LIST(all_quirks)
+ positive_quirks = SANITIZE_LIST(positive_quirks)
+ negative_quirks = SANITIZE_LIST(negative_quirks)
+ neutral_quirks = SANITIZE_LIST(neutral_quirks)
cit_character_pref_load(S)
@@ -491,11 +494,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["job_engsec_med"] , job_engsec_med)
WRITE_FILE(S["job_engsec_low"] , job_engsec_low)
- //Traits
- WRITE_FILE(S["all_traits"] , all_traits)
- WRITE_FILE(S["positive_traits"] , positive_traits)
- WRITE_FILE(S["negative_traits"] , negative_traits)
- WRITE_FILE(S["neutral_traits"] , neutral_traits)
+ //Quirks
+ WRITE_FILE(S["all_quirks"] , all_quirks)
+ WRITE_FILE(S["positive_quirks"] , positive_quirks)
+ WRITE_FILE(S["negative_quirks"] , negative_quirks)
+ WRITE_FILE(S["neutral_quirks"] , neutral_quirks)
cit_character_pref_save(S)
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index b15109bcb1..9ab929ba20 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -81,12 +81,14 @@
/obj/item/clothing/equipped(mob/user, slot)
..()
-
+ if (!istype(user))
+ return
if(slot_flags & slotdefine2slotbit(slot)) //Was equipped to a valid slot for this item?
- for(var/variable in user_vars_to_edit)
- if(variable in user.vars)
- user_vars_remembered[variable] = user.vars[variable]
- user.vars[variable] = user_vars_to_edit[variable]
+ if (LAZYLEN(user_vars_to_edit))
+ for(var/variable in user_vars_to_edit)
+ if(variable in user.vars)
+ LAZYSET(user_vars_remembered, variable, user.vars[variable])
+ user.vv_edit_var(variable, user_vars_to_edit[variable])
/obj/item/clothing/examine(mob/user)
..()
@@ -285,4 +287,4 @@ BLIND // can't see anything
Shreds.desc = "The sad remains of what used to be [name]."
deconstruct(FALSE)
else
- ..()
\ No newline at end of file
+ ..()
diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm
index f9be63420f..44bba64d2f 100644
--- a/code/modules/clothing/glasses/_glasses.dm
+++ b/code/modules/clothing/glasses/_glasses.dm
@@ -365,6 +365,7 @@
scan_reagents = 1
flags_1 = NODROP_1
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
+ resistance_flags = LAVA_PROOF | FIRE_PROOF
/obj/item/clothing/glasses/godeye/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, src) && W != src && W.loc == user)
diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm
index 5e5e7a9c55..336881106e 100644
--- a/code/modules/clothing/glasses/engine_goggles.dm
+++ b/code/modules/clothing/glasses/engine_goggles.dm
@@ -93,7 +93,7 @@
MA.alpha = 180
MA.maptext = "[strength]k"
MA.color = "#64C864"
- MA.layer = AREA_LAYER
+ MA.layer = FLY_LAYER
pic.appearance = MA
flick_overlay(pic, list(user.client), 8)
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 2e9b7f83f2..4bf68c3bd0 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -158,12 +158,20 @@
strip_delay = 100
dog_fashion = null
+/obj/item/clothing/head/helmet/roman/fake
+ desc = "An ancient helmet made of plastic and leather."
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
+
/obj/item/clothing/head/helmet/roman/legionaire
name = "roman legionaire helmet"
desc = "An ancient helmet made of bronze and leather. Has a red crest on top of it."
icon_state = "roman_c"
item_state = "roman_c"
+/obj/item/clothing/head/helmet/roman/legionaire/fake
+ desc = "An ancient helmet made of plastic and leather. Has a red crest on top of it."
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
+
/obj/item/clothing/head/helmet/gladiator
name = "gladiator helmet"
desc = "Ave, Imperator, morituri te salutant."
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 74d8a43347..2c03997a4a 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -321,4 +321,27 @@
name = "headress of Nemes"
desc = "Lavish space tomb not included."
icon_state = "nemes_headdress"
- icon_state = "nemes_headdress"
\ No newline at end of file
+ icon_state = "nemes_headdress"
+
+/obj/item/clothing/head/frenchberet
+ name = "french beret"
+ desc = "A quality beret, infused with the aroma of chain-smoking, wine-swilling Parisians. You feel less inclined to engage military conflict, for some reason."
+ icon_state = "beretblack"
+
+/obj/item/clothing/head/frenchberet/speechModification(M)
+ if(copytext(M, 1, 2) != "*")
+ M = " [M]"
+ var/list/french_words = strings("french_replacement.json", "french")
+
+ for(var/key in french_words)
+ var/value = french_words[key]
+ if(islist(value))
+ value = pick(value)
+
+ M = replacetextEx(M, " [uppertext(key)]", " [uppertext(value)]")
+ M = replacetextEx(M, " [capitalize(key)]", " [capitalize(value)]")
+ M = replacetextEx(M, " [key]", " [value]")
+
+ if(prob(3))
+ M += pick(" Honh honh honh!"," Honh!"," Zut Alors!")
+ return trim(M)
\ No newline at end of file
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index 285639d64a..ad77f1d350 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -47,7 +47,7 @@
/obj/item/clothing/mask/fakemoustache/italian/speechModification(M)
if(copytext(M, 1, 2) != "*")
M = " [M]"
- var/list/italian_words = strings("word_replacement.json", "italian")
+ var/list/italian_words = strings("italian_replacement.json", "italian")
for(var/key in italian_words)
var/value = italian_words[key]
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 7a35a4761d..5a79cfdae3 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -126,7 +126,7 @@
if(user.transferItemToLoc(I, src))
jetpack = I
to_chat(user, "You successfully install the jetpack into [src].")
-
+ return
else if(istype(I, /obj/item/screwdriver))
if(!jetpack)
to_chat(user, "[src] has no jetpack installed.")
@@ -139,6 +139,8 @@
jetpack.forceMove(drop_location())
jetpack = null
to_chat(user, "You successfully remove the jetpack from [src].")
+ return
+ return ..()
/obj/item/clothing/suit/space/hardsuit/equipped(mob/user, slot)
@@ -237,6 +239,9 @@
brightness_on = 7
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator)
+/obj/item/clothing/head/helmet/space/hardsuit/mining/Initialize()
+ . = ..()
+ AddComponent(/datum/component/armor_plate)
/obj/item/clothing/suit/space/hardsuit/mining
icon_state = "hardsuit-mining"
@@ -250,6 +255,10 @@
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/mining
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+/obj/item/clothing/suit/space/hardsuit/mining/Initialize()
+ . = ..()
+ AddComponent(/datum/component/armor_plate)
+
//Syndicate hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/syndi
name = "blood-red hardsuit helmet"
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 37d48b484e..af6d2b6c5e 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -165,186 +165,6 @@
. = ..()
allowed = GLOB.detective_vest_allowed
-//Reactive armor
-/obj/item/clothing/suit/armor/reactive
- name = "reactive armor"
- desc = "Doesn't seem to do much for some reason."
- var/active = 0
- var/reactivearmor_cooldown_duration = 0 //cooldown specific to reactive armor
- var/reactivearmor_cooldown = 0
- icon_state = "reactiveoff"
- item_state = "reactiveoff"
- blood_overlay_type = "armor"
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
- actions_types = list(/datum/action/item_action/toggle)
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- hit_reaction_chance = 50
-
-
-/obj/item/clothing/suit/armor/reactive/attack_self(mob/user)
- src.active = !( src.active )
- if (src.active)
- to_chat(user, "[src] is now active.")
- src.icon_state = "reactive"
- src.item_state = "reactive"
- else
- to_chat(user, "[src] is now inactive.")
- src.icon_state = "reactiveoff"
- src.item_state = "reactiveoff"
- src.add_fingerprint(user)
- return
-
-/obj/item/clothing/suit/armor/reactive/emp_act(severity)
- active = 0
- src.icon_state = "reactiveoff"
- src.item_state = "reactiveoff"
- reactivearmor_cooldown = world.time + 200
- ..()
-
-//When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!)
-/obj/item/clothing/suit/armor/reactive/teleport
- name = "reactive teleport armor"
- desc = "Someone separated our Research Director from his own head!"
- var/tele_range = 6
- var/rad_amount= 15
- reactivearmor_cooldown_duration = 100
-
-/obj/item/clothing/suit/armor/reactive/teleport/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
- if(!active)
- return 0
- if(prob(hit_reaction_chance))
- var/mob/living/carbon/human/H = owner
- if(world.time < reactivearmor_cooldown)
- owner.visible_message("The reactive teleport system is still recharging! It fails to teleport [H]!")
- return
- owner.visible_message("The reactive teleport system flings [H] clear of [attack_text], shutting itself off in the process!")
- var/list/turfs = new/list()
- for(var/turf/T in orange(tele_range, H))
- if(T.density)
- continue
- if(T.x>world.maxx-tele_range || T.x\ You are armed with powerful medical tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \ Your hypospray will produce Restorative Nanites, a wonder-drug that will heal most types of bodily damages, including clone and brain damage. It also produces morphine for offense. \ diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index bdcde185d7..9926bc35fc 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -1,7 +1,7 @@ /obj/item/robot_module name = "Default" icon = 'icons/obj/module.dmi' - icon_state = "std_module" + icon_state = "std_mod" w_class = WEIGHT_CLASS_GIGANTIC item_state = "electronic" lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index f0cc8285e8..f47f936db7 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -164,12 +164,7 @@ update_controls() /mob/living/simple_animal/bot/floorbot/proc/empty_tiles() - var/atom/Tsec = drop_location() - - while(specialtiles > initial(tiletype.max_amount)) - new tiletype(Tsec,initial(tiletype.max_amount)) - specialtiles -= initial(tiletype.max_amount) - new tiletype(Tsec,specialtiles) + new tiletype(drop_location(), specialtiles) specialtiles = 0 tiletype = null @@ -378,8 +373,7 @@ if(prob(50)) drop_part(robot_arm, Tsec) - var/obj/item/stack/tile/plasteel/T = new (Tsec) - T.amount = 1 + new /obj/item/stack/tile/plasteel(Tsec, 1) do_sparks(3, TRUE, src) ..() diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index de7874351a..65b78bf844 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -2,7 +2,7 @@ name = "\improper honkbot" desc = "A little robot. It looks happy with its bike horn." icon = 'icons/mob/aibots.dmi' - icon_state = "honkbot" + icon_state = "honkbot1" density = FALSE anchored = FALSE health = 25 diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm index 6dc76bb6a7..214ced3613 100644 --- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm +++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm @@ -27,6 +27,7 @@ attacktext = "pummels" attack_sound = 'sound/weapons/punch1.ogg' dextrous = TRUE + held_items = list(null, null) possible_a_intents = list(INTENT_HELP, INTENT_GRAB, INTENT_DISARM, INTENT_HARM) faction = list("jungle") robust_searching = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm index 4c9c916085..4917d3b74d 100644 --- a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm +++ b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm @@ -9,7 +9,7 @@ icon_dead = "Fugu_dead" icon_gib = "syndicate_gib" mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) - mouse_opacity = MOUSE_OPACITY_OPAQUE + mouse_opacity = MOUSE_OPACITY_ICON move_to_delay = 5 friendly = "floats near" speak_emote = list("puffs") diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 106381bade..0a0f27f123 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -146,12 +146,12 @@ else status_traits[trait] |= list(source) -/mob/living/proc/add_trait_datum(trait, spawn_effects) //separate proc due to the way these ones are handled - if(has_trait(trait)) +/mob/living/proc/add_quirk(quirk, spawn_effects) //separate proc due to the way these ones are handled + if(has_trait(quirk)) return - if(!SStraits || !SStraits.traits[trait]) + if(!SSquirks || !SSquirks.quirks[quirk]) return - var/datum/trait/T = SStraits.traits[trait] + var/datum/quirk/T = SSquirks.quirks[quirk] new T (src, spawn_effects) return TRUE @@ -180,8 +180,8 @@ if(!LAZYLEN(status_traits[trait])) status_traits -= trait -/mob/living/proc/remove_trait_datum(trait) - var/datum/trait/T = roundstart_traits[trait] +/mob/living/proc/remove_quirk(quirk) + var/datum/quirk/T = roundstart_quirks[quirk] if(T) qdel(T) return TRUE @@ -201,8 +201,8 @@ else if(LAZYLEN(status_traits[trait])) return TRUE -/mob/living/proc/has_trait_datum(trait) - return roundstart_traits[trait] +/mob/living/proc/has_quirk(quirk) + return roundstart_quirks[quirk] /mob/living/proc/remove_all_traits() status_traits = list() diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index 9ad832debe..2718392b69 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -70,7 +70,7 @@ message = src.say_quote(message, get_spans()) var/rendered = "DEAD: [name][alt_name] " - + log_message("DEAD: [message]", INDIVIDUAL_SAY_LOG) deadchat_broadcast(rendered, follow_target = src, speaker_key = K) /mob/proc/check_emote(message) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index c425ab8c61..ddfd878e2d 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -66,7 +66,7 @@ ..() to_chat(user, "Alt-click to fold it.") - var/datum/asset/assets = get_asset_datum(/datum/asset/simple/paper) + var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/simple/paper) assets.send(user) if(in_range(user, src) || isobserver(user)) @@ -300,7 +300,10 @@ if(!in_range(src, user)) return - stamps += " "
+ var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/research_designs)
+ sheet.send(user)
+ return sheet.icon_tag(id)
////////////////////////////////////////
//Disks for transporting design datums//
diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm
index d1bcb952aa..28609e921d 100644
--- a/code/modules/research/designs/autolathe_designs.dm
+++ b/code/modules/research/designs/autolathe_designs.dm
@@ -126,42 +126,47 @@
/datum/design/apc_board
name = "APC Module"
id = "power control"
- build_type = AUTOLATHE
+ build_type = AUTOLATHE | PROTOLATHE
materials = list(MAT_METAL = 100, MAT_GLASS = 100)
build_path = /obj/item/electronics/apc
category = list("initial", "Electronics")
+ departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
/datum/design/airlock_board
name = "Airlock Electronics"
id = "airlock_board"
- build_type = AUTOLATHE
+ build_type = AUTOLATHE | PROTOLATHE
materials = list(MAT_METAL = 50, MAT_GLASS = 50)
build_path = /obj/item/electronics/airlock
category = list("initial", "Electronics")
+ departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
/datum/design/firelock_board
name = "Firelock Circuitry"
id = "firelock_board"
- build_type = AUTOLATHE
+ build_type = AUTOLATHE | PROTOLATHE
materials = list(MAT_METAL = 50, MAT_GLASS = 50)
build_path = /obj/item/electronics/firelock
category = list("initial", "Electronics")
+ departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
/datum/design/airalarm_electronics
name = "Air Alarm Electronics"
id = "airalarm_electronics"
- build_type = AUTOLATHE
+ build_type = AUTOLATHE | PROTOLATHE
materials = list(MAT_METAL = 50, MAT_GLASS = 50)
build_path = /obj/item/electronics/airalarm
category = list("initial", "Electronics")
+ departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
/datum/design/firealarm_electronics
name = "Fire Alarm Electronics"
id = "firealarm_electronics"
- build_type = AUTOLATHE
+ build_type = AUTOLATHE | PROTOLATHE
materials = list(MAT_METAL = 50, MAT_GLASS = 50)
build_path = /obj/item/electronics/firealarm
category = list("initial", "Electronics")
+ departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
/datum/design/camera
name = "Camera"
diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm
index 8f79bb9a6d..fd3eefbde1 100644
--- a/code/modules/research/designs/misc_designs.dm
+++ b/code/modules/research/designs/misc_designs.dm
@@ -354,3 +354,17 @@
build_path = /obj/item/weldingtool/experimental
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
+
+/////////////////////////////////////////
+////////////Armour//////////////
+/////////////////////////////////////////
+
+/datum/design/reactive_armour
+ name = "Reactive Armour Shell"
+ desc = "An experimental suit of armour capable of utilizing an implanted anomaly core to protect the user."
+ id = "reactive_armour"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 10000, MAT_DIAMOND = 5000, MAT_URANIUM = 8000, MAT_SILVER = 4500, MAT_GOLD = 5000)
+ build_path = /obj/item/reactive_armour_shell
+ category = list("Equipment")
+ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
\ No newline at end of file
diff --git a/code/modules/research/designs/smelting_designs.dm b/code/modules/research/designs/smelting_designs.dm
index 821e6cee38..79a9748b08 100644
--- a/code/modules/research/designs/smelting_designs.dm
+++ b/code/modules/research/designs/smelting_designs.dm
@@ -21,15 +21,23 @@
name = "Plasma + Glass alloy"
id = "plasmaglass"
build_type = SMELTER
- materials = list(MAT_PLASMA = MINERAL_MATERIAL_AMOUNT, MAT_GLASS = MINERAL_MATERIAL_AMOUNT)
+ materials = list(MAT_PLASMA = MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS = MINERAL_MATERIAL_AMOUNT)
build_path = /obj/item/stack/sheet/plasmaglass
category = list("initial")
+/datum/design/plasmarglass_alloy
+ name = "Plasma + Metal + Glass alloy"
+ id = "plasmareinforcedglass"
+ build_type = SMELTER
+ materials = list(MAT_PLASMA = MINERAL_MATERIAL_AMOUNT * 0.5, MAT_METAL = MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS = MINERAL_MATERIAL_AMOUNT)
+ build_path = /obj/item/stack/sheet/plasmarglass
+ category = list("initial")
+
/datum/design/titaniumglass_alloy
name = "Titanium + Glass alloy"
id = "titaniumglass"
build_type = SMELTER
- materials = list(MAT_TITANIUM = MINERAL_MATERIAL_AMOUNT, MAT_GLASS = MINERAL_MATERIAL_AMOUNT)
+ materials = list(MAT_TITANIUM = MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS = MINERAL_MATERIAL_AMOUNT)
build_path = /obj/item/stack/sheet/titaniumglass
category = list("initial")
@@ -37,7 +45,7 @@
name = "Plasma + Titanium + Glass alloy"
id = "plastitaniumglass"
build_type = SMELTER
- materials = list(MAT_PLASMA = MINERAL_MATERIAL_AMOUNT, MAT_TITANIUM = MINERAL_MATERIAL_AMOUNT, MAT_GLASS = MINERAL_MATERIAL_AMOUNT)
+ materials = list(MAT_PLASMA = MINERAL_MATERIAL_AMOUNT * 0.5, MAT_TITANIUM = MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS = MINERAL_MATERIAL_AMOUNT)
build_path = /obj/item/stack/sheet/plastitaniumglass
category = list("initial")
diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm
index 6c85a16498..db08c9b950 100644
--- a/code/modules/research/rdconsole.dm
+++ b/code/modules/research/rdconsole.dm
@@ -217,6 +217,8 @@ doesn't have toxins access.
/obj/machinery/computer/rdconsole/proc/ui_header()
var/list/l = list()
+ var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/research_designs)
+ l += "[sheet.css_tag()][RDSCREEN_NOBREAK]"
l += "[stored_research.organization] Research and Development Network"
l += "Available points: [round(stored_research.research_points)] (+[round(stored_research.last_bitcoins * 60)] / minute)"
l += "Security protocols: [obj_flags & EMAGGED ? "Disabled" : "Enabled"]"
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index e8ba52495b..c29c8b7732 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -93,7 +93,7 @@
description = "A refresher course on modern engineering technology."
prereq_ids = list("base")
design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "emitter", "high_cell", "adv_matter_bin",
- "atmosalerts", "atmos_control", "recycler", "autolathe", "high_micro_laser", "nano_mani", "mesons", "thermomachine", "rad_collector", "tesla_coil", "grounding_rod", "apc_control", "cell_charger")
+ "atmosalerts", "atmos_control", "recycler", "autolathe", "high_micro_laser", "nano_mani", "mesons", "thermomachine", "rad_collector", "tesla_coil", "grounding_rod", "apc_control", "cell_charger", "power control", "airlock_board", "firelock_board", "airalarm_electronics", "firealarm_electronics")
research_cost = 7500
export_price = 5000
@@ -106,6 +106,15 @@
research_cost = 2500
export_price = 5000
+/datum/techweb_node/anomaly
+ id = "anomaly_research"
+ display_name = "Anomaly Research"
+ description = "Unlock the potential of the mysterious anomalies that appear on station."
+ prereq_ids = list("adv_engi", "practical_bluespace")
+ design_ids = list("reactive_armour")
+ research_cost = 2500
+ export_price = 5000
+
/datum/techweb_node/high_efficiency
id = "high_efficiency"
display_name = "High Efficiency Parts"
@@ -153,7 +162,6 @@
research_cost = 5000
export_price = 5000
-
/datum/techweb_node/bluespace_power
id = "bluespace_power"
display_name = "Bluespace Power Technology"
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index ddbfdb8471..1c8e9ac350 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -448,8 +448,7 @@ datum/status_effect/stabilized/blue/on_remove()
else if(istype(O, /obj/item/stack/sheet/hairlesshide))
to_chat(owner, "[linked_extract] kept your hands wet! It wets [O]!")
var/obj/item/stack/sheet/hairlesshide/HH = O
- var/obj/item/stack/sheet/wetleather/WL = new(get_turf(HH))
- WL.amount = HH.amount
+ new /obj/item/stack/sheet/wetleather(get_turf(HH), HH.amount)
qdel(HH)
..()
diff --git a/code/modules/research/xenobiology/crossbreeding/charged.dm b/code/modules/research/xenobiology/crossbreeding/charged.dm
index 68aff64ee9..18b4e81398 100644
--- a/code/modules/research/xenobiology/crossbreeding/charged.dm
+++ b/code/modules/research/xenobiology/crossbreeding/charged.dm
@@ -66,10 +66,8 @@ Charged extracts:
colour = "metal"
/obj/item/slimecross/charged/metal/do_effect(mob/user)
- var/obj/item/stack/sheet/metal/M = new(get_turf(user))
- M.amount = 25
- var/obj/item/stack/sheet/plasteel/P = new(get_turf(user))
- P.amount = 10
+ new /obj/item/stack/sheet/metal(get_turf(user), 25)
+ new /obj/item/stack/sheet/plasteel(get_turf(user), 10)
user.visible_message("[src] grows into a plethora of metals!")
..()
@@ -85,8 +83,7 @@ Charged extracts:
colour = "dark purple"
/obj/item/slimecross/charged/darkpurple/do_effect(mob/user)
- var/obj/item/stack/sheet/mineral/plasma/M = new(get_turf(user))
- M.amount = 10
+ new /obj/item/stack/sheet/mineral/plasma(get_turf(user), 10)
user.visible_message("[src] produces a large amount of plasma!")
..()
@@ -113,8 +110,7 @@ Charged extracts:
colour = "bluespace"
/obj/item/slimecross/charged/bluespace/do_effect(mob/user)
- var/obj/item/stack/sheet/bluespace_crystal/M = new(get_turf(user))
- M.amount = 10
+ new /obj/item/stack/sheet/bluespace_crystal(get_turf(user), 10)
user.visible_message("[src] produces several sheets of polycrystal!")
..()
@@ -138,8 +134,7 @@ Charged extracts:
colour = "pyrite"
/obj/item/slimecross/charged/pyrite/do_effect(mob/user)
- var/obj/item/stack/sheet/mineral/bananium/M = new(get_turf(user))
- M.amount = 10
+ new /obj/item/stack/sheet/mineral/bananium(get_turf(user), 10)
user.visible_message("[src] solidifies with a horrifying banana stench!")
..()
diff --git a/code/modules/research/xenobiology/crossbreeding/industrial.dm b/code/modules/research/xenobiology/crossbreeding/industrial.dm
index 2503219e83..95f87ede0a 100644
--- a/code/modules/research/xenobiology/crossbreeding/industrial.dm
+++ b/code/modules/research/xenobiology/crossbreeding/industrial.dm
@@ -75,12 +75,7 @@ Industrial extracts:
/obj/item/slimecross/industrial/metal
colour = "metal"
plasmarequired = 3
- itempath = /obj/item/stack/sheet/metal
-
-/obj/item/slimecross/industrial/metal/do_after_spawn(obj/item/spawned)
- var/obj/item/stack/sheet/metal/M = spawned
- if(istype(M))
- M.amount = 10
+ itempath = /obj/item/stack/sheet/metal/ten
/obj/item/slimecross/industrial/yellow
colour = "yellow"
diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm
index ee02bd524f..89e513fd60 100644
--- a/code/modules/spells/spell.dm
+++ b/code/modules/spells/spell.dm
@@ -144,7 +144,6 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
var/smoke_spread = 0 //1 - harmless, 2 - harmful
var/smoke_amt = 0 //cropped at 10
- var/critfailchance = 0
var/centcom_cancast = 1 //Whether or not the spell should be allowed on z2
action_icon = 'icons/mob/actions/actions_spells.dmi'
@@ -153,7 +152,6 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
base_action = /datum/action/spell_action/spell
/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
-
if(player_lock)
if(!user.mind || !(src in user.mind.spell_list) && !(src in user.mob_spell_list))
to_chat(user, "You shouldn't have this spell! Something's wrong.")
@@ -168,15 +166,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
return 0
if(!skipcharge)
- switch(charge_type)
- if("recharge")
- if(charge_counter < charge_max)
- to_chat(user, still_recharging_msg)
- return 0
- if("charges")
- if(!charge_counter)
- to_chat(user, "[name] has no charges left.")
- return 0
+ if(!charge_check(user))
+ return 0
if(user.stat && !stat_allowed)
to_chat(user, "Not when you're incapacitated.")
@@ -236,6 +227,20 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
action.UpdateButtonIcon()
return 1
+/obj/effect/proc_holder/spell/proc/charge_check(mob/user, silent = FALSE)
+ switch(charge_type)
+ if("recharge")
+ if(charge_counter < charge_max)
+ if(!silent)
+ to_chat(user, still_recharging_msg)
+ return FALSE
+ if("charges")
+ if(!charge_counter)
+ if(!silent)
+ to_chat(user, "[name] has no charges left.")
+ return FALSE
+ return TRUE
+
/obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount
switch(invocation_type)
if("shout")
@@ -297,10 +302,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
recharging = TRUE
if(sound)
playMagSound()
- if(prob(critfailchance))
- critfail(targets)
- else
- cast(targets,user=user)
+ cast(targets,user=user)
after_cast(targets)
if(action)
action.UpdateButtonIcon()
@@ -349,9 +351,6 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
/obj/effect/proc_holder/spell/proc/cast(list/targets,mob/user = usr)
return
-/obj/effect/proc_holder/spell/proc/critfail(list/targets)
- return
-
/obj/effect/proc_holder/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge
switch(charge_type)
if("recharge")
@@ -500,25 +499,20 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr)
if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list))
- return 0
+ return FALSE
- switch(charge_type)
- if("recharge")
- if(charge_counter < charge_max)
- return 0
- if("charges")
- if(!charge_counter)
- return 0
+ if(!charge_check(user,TRUE))
+ return FALSE
if(user.stat && !stat_allowed)
- return 0
+ return FALSE
if(!ishuman(user))
if(clothes_req || human_req)
- return 0
+ return FALSE
if(nonabstract_req && (isbrain(user) || ispAI(user)))
- return 0
- return 1
+ return FALSE
+ return TRUE
/obj/effect/proc_holder/spell/self //Targets only the caster. Good for buffs and heals, but probably not wise for fireballs (although they usually fireball themselves anyway, honke)
range = -1 //Duh
diff --git a/code/modules/spells/spell_types/godhand.dm b/code/modules/spells/spell_types/godhand.dm
index 2def02b4c0..bf402b7a6a 100644
--- a/code/modules/spells/spell_types/godhand.dm
+++ b/code/modules/spells/spell_types/godhand.dm
@@ -13,10 +13,7 @@
throwforce = 0
throw_range = 0
throw_speed = 0
-
-/obj/item/melee/touch_attack/Initialize()
- attached_spell = loc
- . = ..()
+ var/charges = 1
/obj/item/melee/touch_attack/attack(mob/target, mob/living/carbon/user)
if(!iscarbon(user)) //Look ma, no hands
@@ -29,13 +26,13 @@
/obj/item/melee/touch_attack/afterattack(atom/target, mob/user, proximity)
user.say(catchphrase)
playsound(get_turf(user), on_use_sound,50,1)
- if(attached_spell)
- attached_spell.attached_hand = null
- qdel(src)
+ charges--
+ if(charges <= 0)
+ qdel(src)
/obj/item/melee/touch_attack/Destroy()
if(attached_spell)
- attached_spell.attached_hand = null
+ attached_spell.on_hand_destroy(src)
return ..()
/obj/item/melee/touch_attack/disintegrate
diff --git a/code/modules/spells/spell_types/touch_attacks.dm b/code/modules/spells/spell_types/touch_attacks.dm
index 2000d8daea..0ffe02cec2 100644
--- a/code/modules/spells/spell_types/touch_attacks.dm
+++ b/code/modules/spells/spell_types/touch_attacks.dm
@@ -1,37 +1,46 @@
/obj/effect/proc_holder/spell/targeted/touch
- var/hand_path = "/obj/item/melee/touch_attack"
+ var/hand_path = /obj/item/melee/touch_attack
var/obj/item/melee/touch_attack/attached_hand = null
invocation_type = "none" //you scream on connecting, not summoning
include_user = 1
range = -1
-/obj/effect/proc_holder/spell/targeted/touch/Click(mob/user = usr)
- if(attached_hand)
- qdel(attached_hand)
+/obj/effect/proc_holder/spell/targeted/touch/proc/remove_hand(recharge = FALSE)
+ QDEL_NULL(attached_hand)
+ if(recharge)
charge_counter = charge_max
- attached_hand = null
- to_chat(user, "You draw the power out of your hand.")
- return FALSE
- ..()
+
+/obj/effect/proc_holder/spell/targeted/touch/proc/on_hand_destroy(obj/item/melee/touch_attack/hand)
+ if(hand != attached_hand)
+ CRASH("Incorrect touch spell hand.")
+ //Start recharging.
+ attached_hand = null
+ recharging = TRUE
+ action.UpdateButtonIcon()
/obj/effect/proc_holder/spell/targeted/touch/cast(list/targets,mob/user = usr)
+ if(!QDELETED(attached_hand))
+ remove_hand(TRUE)
+ to_chat(user, "You draw the power out of your hand.")
+ return
+
for(var/mob/living/carbon/C in targets)
if(!attached_hand)
- if(!ChargeHand(C))
- return FALSE
- while(attached_hand)
- charge_counter = 0
- stoplag(1)
+ if(ChargeHand(C))
+ recharging = FALSE
+ return
-/obj/effect/proc_holder/spell/targeted/touch/can_cast(mob/user = usr)
- return ..() && attached_hand
+/obj/effect/proc_holder/spell/targeted/touch/charge_check(mob/user,silent = FALSE)
+ if(!QDELETED(attached_hand)) //Charge doesn't matter when putting the hand away.
+ return TRUE
+ else
+ return ..()
/obj/effect/proc_holder/spell/targeted/touch/proc/ChargeHand(mob/living/carbon/user)
attached_hand = new hand_path(src)
+ attached_hand.attached_spell = src
if(!user.put_in_hands(attached_hand))
- qdel(attached_hand)
- charge_counter = charge_max
- attached_hand = null
+ remove_hand(TRUE)
to_chat(user, "Your hands are full!")
return FALSE
to_chat(user, "You channel the power of the spell to your hand.")
@@ -41,7 +50,7 @@
/obj/effect/proc_holder/spell/targeted/touch/disintegrate
name = "Disintegrate"
desc = "This spell charges your hand with vile energy that can be used to violently explode victims."
- hand_path = "/obj/item/melee/touch_attack/disintegrate"
+ hand_path = /obj/item/melee/touch_attack/disintegrate
school = "evocation"
charge_max = 600
@@ -53,7 +62,7 @@
/obj/effect/proc_holder/spell/targeted/touch/flesh_to_stone
name = "Flesh to Stone"
desc = "This spell charges your hand with the power to turn victims into inert statues for a long period of time."
- hand_path = "/obj/item/melee/touch_attack/fleshtostone"
+ hand_path = /obj/item/melee/touch_attack/fleshtostone
school = "transmutation"
charge_max = 600
diff --git a/code/modules/tooltip/tooltip.dm b/code/modules/tooltip/tooltip.dm
index 5110b98e8e..ab7dc91739 100644
--- a/code/modules/tooltip/tooltip.dm
+++ b/code/modules/tooltip/tooltip.dm
@@ -42,6 +42,8 @@ Notes:
/datum/tooltip/New(client/C)
if (C)
owner = C
+ var/datum/asset/stuff = get_asset_datum(/datum/asset/simple/jquery)
+ stuff.send(owner)
owner << browse(file2text('code/modules/tooltip/tooltip.html'), "window=[control]")
..()
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index 92ce23c6c4..6a8ccefd19 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -453,7 +453,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/ammo/shotgun/buck
name = "12g Buckshot Drum"
desc = "An additional 8-round buckshot magazine for use with the Bulldog shotgun. Front towards enemy."
- item = /obj/item/ammo_box/magazine/m12g/buckshot
+ item = /obj/item/ammo_box/magazine/m12g
/datum/uplink_item/ammo/shotgun/slug
name = "12g Slug Drum"
@@ -466,7 +466,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
name = "12g Stun Slug Drum"
desc = "An alternative 8-round stun slug magazine for use with the Bulldog shotgun. \
Saying that they're completely non-lethal would be lying."
- item = /obj/item/ammo_box/magazine/m12g
+ item = /obj/item/ammo_box/magazine/m12g/stun
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/shotgun/dragon
diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm
index 889b159762..c0cfe661d7 100644
--- a/code/modules/vending/autodrobe.dm
+++ b/code/modules/vending/autodrobe.dm
@@ -114,11 +114,11 @@
/obj/item/clothing/mask/muzzle = 2)
premium = list(/obj/item/clothing/suit/pirate/captain = 2,
/obj/item/clothing/head/pirate/captain = 2,
- /obj/item/clothing/head/helmet/roman = 1,
- /obj/item/clothing/head/helmet/roman/legionaire = 1,
+ /obj/item/clothing/head/helmet/roman/fake = 1,
+ /obj/item/clothing/head/helmet/roman/legionaire/fake = 1,
/obj/item/clothing/under/roman = 1,
/obj/item/clothing/shoes/roman = 1,
- /obj/item/shield/riot/roman = 1,
+ /obj/item/shield/riot/roman/fake = 1,
/obj/item/skub = 1)
refill_canister = /obj/item/vending_refill/autodrobe
diff --git a/code/modules/vending/boozeomat.dm b/code/modules/vending/boozeomat.dm
index eddb01171b..59b41d4cef 100644
--- a/code/modules/vending/boozeomat.dm
+++ b/code/modules/vending/boozeomat.dm
@@ -19,6 +19,7 @@
/obj/item/reagent_containers/food/drinks/bottle/orangejuice = 4,
/obj/item/reagent_containers/food/drinks/bottle/tomatojuice = 4,
/obj/item/reagent_containers/food/drinks/bottle/limejuice = 4,
+ /obj/item/reagent_containers/food/drinks/bottle/menthol = 4,
/obj/item/reagent_containers/food/drinks/bottle/cream = 4,
/obj/item/reagent_containers/food/drinks/soda_cans/tonic = 8,
/obj/item/reagent_containers/food/drinks/soda_cans/cola = 8,
@@ -37,5 +38,5 @@
/obj/item/vending_refill/boozeomat
machine_name = "Booze-O-Mat"
icon_state = "refill_booze"
- charges = list(58, 4, 0)//of 174 standard, 12 contraband
- init_charges = list(58, 4, 0)
+ charges = list(59, 4, 0)//of 178 standard, 12 contraband
+ init_charges = list(59, 4, 0)
diff --git a/code/modules/vending/engivend.dm b/code/modules/vending/engivend.dm
index a990ee901f..0e2b31037f 100644
--- a/code/modules/vending/engivend.dm
+++ b/code/modules/vending/engivend.dm
@@ -13,7 +13,10 @@
/obj/item/stock_parts/cell/high = 10,
/obj/item/electronics/airlock = 10,
/obj/item/electronics/apc = 10,
- /obj/item/electronics/airalarm = 10)
+ /obj/item/electronics/airalarm = 10,
+ /obj/item/electronics/firealarm = 10,
+ /obj/item/electronics/firelock = 10
+ )
contraband = list(/obj/item/stock_parts/cell/potato = 3)
premium = list(/obj/item/storage/belt/utility = 3,
/obj/item/storage/box/smart_metal_foam = 1)
diff --git a/config/admins.txt b/config/admins.txt
index ca77fd3f4a..807b4d89d5 100644
--- a/config/admins.txt
+++ b/config/admins.txt
@@ -7,3 +7,133 @@
# NOTE: if the rank-name cannot be found in admin_ranks.txt, they will not be adminned! ~Carn #
# NOTE: syntax was changed to allow hyphenation of ranknames, since spaces are stripped. #
###############################################################################################
+<<<<<<< HEAD
+=======
+Optimumtact = Host
+NewSta = Game Master
+Expletives = Game Master
+kingofkosmos = Game Master
+MrStonedOne = Lazy Master
+microscopics = Game Master
+Gun Hog = Game Master
+KorPhaeron = Game Master
+razharas = Game Master
+Lordpidey = Game Master
+Niknakflak = Game Master
+rolan7 = Game Master
+quarxink = Game Master
+adrix89 = Game Master
+tle = Game Master
+xsi = Game Master
+scaredofshadows = Game Master
+neofite = Game Master
+trubblebass = Game Master
+mport2004 = Game Master
+deuryn = Game Master
+agouri = Game Master
+errorage = Game Master
+superxpdude = Game Master
+petethegoat = Game Master
+nodrak = Game Master
+carnwennan = Game Master
+ikarrus = Game Master
+cheridan = Game Master
+giacomand = Game Master
+rockdtben = Game Master
+sieve = Game Master
+aranclanos = Game Master
+intigracy = Game Master
+dumpdavidson = Game Master
+kazeespada = Game Master
+malkevin = Game Master
+incoming = Game Master
+demas = Game Master
+fleure = Game Master
+ricotez = Game Master
+misterperson = Game Master
+crimsonvision = Game Master
+iamgoofball = Game Master
+zelacks = Game Master
+androidsfv = Game Master
+miggles = Game Master
+jordie0608 = Game Master
+s0ldi3rkr4s0 = Game Master
+ergovisavi = Game Master
+vistapowa = Game Master
+miauw62 = Game Master
+rumia29 = Game Master
+bobylein = Game Master
+sirbayer = Game Master
+hornygranny = Game Master
+yota = Game Master
+firecage = Game Master
+donkieyo = Game Master
+argoneus = Game Master
+paprka = Game Master
+cookingboy3 = Game Master
+limeliz = Game Master
+steelpoint = Game Master
+phil235 = Game Master
+CorruptComputer = Game Master
+xxnoob = Game Master
+tkdrg = Game Master
+Cuboos = Game Master
+thunder12345 = Game Master
+wjohnston = Game Master
+mandurrh = Game Master
+thurgatar = Game Master
+xerux = Game Master
+dannno = Game Master
+lo6a4evskiy = Game Master
+vekter = Game Master
+Ahammer18 = Game Master
+ACCount12 = Game Master
+fayrik = Game Master
+shadowlight213 = Game Master
+drovidicorv = Game Master
+Dunc = Game Master
+MMMiracles = Game Master
+bear1ake = Game Master
+CoreOverload = Game Master
+Jalleo = Game Master
+ChangelingRain = Game Master
+FoxPMcCloud = Game Master
+Xhuis = Game Master
+Astralenigma = Game Master
+Tokiko1 = Game Master
+SuperSayu = Game Master
+Lzimann = Game Master
+As334 = Game Master
+neersighted = Game Master
+Swankcookie = Game Master
+Ressler = Game Master
+Folix = Game Master
+Bawhoppennn = Game Master
+Anturke = Host
+Lumipharon = Game Master
+bgobandit = Game Master
+coiax = Game Master
+RandomMarine = Game Master
+PKPenguin321 = Game Master
+TechnoAlchemist = Game Master
+Aloraydrel = Game Master
+Quiltyquilty = Game Master
+SnipeDragon = Game Master
+Fjeld = Game Master
+kevinz000 = Game Master
+Tacolizard = Game Master
+TrustyGun = Game Master
+Cyberboss = Game Master
+PJB3005 = Game Master
+Sweaterkittens = Game Master
+Feemjmeem = Game Master
+JStheguy = Game Master
+excessiveuseofcobby = Game Master
+Plizzard = Game Master
+octareenroon91 = Game Master
+Serpentarium = Game Master
+Averagejoe82 = Game Master
+The Dreamweaver = Game Master
+88Naoki = Game Master
+Naksuasdf = Game Master
+>>>>>>> 3653239... Merge pull request #37785 from 81Denton/circboard_spawners
diff --git a/config/game_options.txt b/config/game_options.txt
index 5f080a7f0f..6ecec1fc9e 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -536,7 +536,8 @@ ALLOW_MISCREANTS
## Determines if players are allowed to print integrated circuits, uncomment to allow.
#IC_PRINTING
-## Uncomment to allow roundstart trait selection in the character setup menu.
+## Uncomment to allow roundstart quirk selection in the character setup menu.
+## This used to be named traits, hence the config name, but it handles quirks, not the other kind of trait!
ROUNDSTART_TRAITS
## Uncomment to disable human moods.
diff --git a/html/changelogs/AutoChangeLog-pr-6663.yml b/html/changelogs/AutoChangeLog-pr-6663.yml
new file mode 100644
index 0000000000..97e977b062
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-6663.yml
@@ -0,0 +1,4 @@
+author: "Xhuis"
+delete-after: True
+changes:
+ - tweak: "Character traits are now called character quirks. Functionality remains unaffected."
diff --git a/html/changelogs/AutoChangeLog-pr-6731.yml b/html/changelogs/AutoChangeLog-pr-6731.yml
new file mode 100644
index 0000000000..255a2ba3ad
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-6731.yml
@@ -0,0 +1,4 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - tweak: "You may now take unlimited neutral and negative quirks"
diff --git a/html/changelogs/AutoChangeLog-pr-6744.yml b/html/changelogs/AutoChangeLog-pr-6744.yml
new file mode 100644
index 0000000000..761f59fb39
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-6744.yml
@@ -0,0 +1,4 @@
+author: "Dax Dupont"
+delete-after: True
+changes:
+ - bugfix: "Fixes missing curator hud icon."
diff --git a/html/changelogs/AutoChangeLog-pr-6745.yml b/html/changelogs/AutoChangeLog-pr-6745.yml
new file mode 100644
index 0000000000..2f3648f00a
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-6745.yml
@@ -0,0 +1,4 @@
+author: "Denton"
+delete-after: True
+changes:
+ - rscadd: "APC/air alarm/airlock/fire alarm/firelock electronics are now available once Industrial Engineering is researched.."
diff --git a/html/changelogs/AutoChangeLog-pr-6746.yml b/html/changelogs/AutoChangeLog-pr-6746.yml
new file mode 100644
index 0000000000..80c93a7305
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-6746.yml
@@ -0,0 +1,5 @@
+author: "Denton"
+delete-after: True
+changes:
+ - tweak: "Engi-Vend machines now contain fire alarm and firelock electronics!"
+ - code_imp: "Loose tech storage circuit boards have been replaced with spawners."
diff --git a/icons/mob/custom_w.dmi b/icons/mob/custom_w.dmi
index 6b17cc3acb..7c7499ee42 100644
Binary files a/icons/mob/custom_w.dmi and b/icons/mob/custom_w.dmi differ
diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi
index d694c0243a..8fa3cefbb7 100644
Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ
diff --git a/icons/mob/lavaland/64x64megafauna.dmi b/icons/mob/lavaland/64x64megafauna.dmi
index 64304fdcd1..1794c789de 100644
Binary files a/icons/mob/lavaland/64x64megafauna.dmi and b/icons/mob/lavaland/64x64megafauna.dmi differ
diff --git a/icons/mob/lavaland/lavaland_monsters.dmi b/icons/mob/lavaland/lavaland_monsters.dmi
index dac70998f5..f8394dd235 100644
Binary files a/icons/mob/lavaland/lavaland_monsters.dmi and b/icons/mob/lavaland/lavaland_monsters.dmi differ
diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi
index f35ef2c1a5..23541a8e40 100644
Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ
diff --git a/icons/obj/assemblies.dmi b/icons/obj/assemblies.dmi
index 5714953e3f..9cbc085624 100644
Binary files a/icons/obj/assemblies.dmi and b/icons/obj/assemblies.dmi differ
diff --git a/icons/obj/assemblies/new_assemblies.dmi b/icons/obj/assemblies/new_assemblies.dmi
index 0e561b6ff8..df9517aeaa 100644
Binary files a/icons/obj/assemblies/new_assemblies.dmi and b/icons/obj/assemblies/new_assemblies.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 3635744b6f..c6f6798076 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/custom.dmi b/icons/obj/custom.dmi
index de5fce96a5..419b14f526 100644
Binary files a/icons/obj/custom.dmi and b/icons/obj/custom.dmi differ
diff --git a/icons/obj/food/burgerbread.dmi b/icons/obj/food/burgerbread.dmi
index 64fac1c3eb..c40dfaaa22 100644
Binary files a/icons/obj/food/burgerbread.dmi and b/icons/obj/food/burgerbread.dmi differ
diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi
index b3774b26ab..a053eab792 100644
Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ
diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi
index e94228f701..b4431daf83 100644
Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ
diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi
index 2d0d35f8a5..84e9f78add 100644
Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ
diff --git a/icons/obj/smooth_structures/clockwork_window.dmi b/icons/obj/smooth_structures/clockwork_window.dmi
index 90309ac3d5..10d5bcf631 100644
Binary files a/icons/obj/smooth_structures/clockwork_window.dmi and b/icons/obj/smooth_structures/clockwork_window.dmi differ
diff --git a/icons/obj/smooth_structures/sandbags.dmi b/icons/obj/smooth_structures/sandbags.dmi
index 2e8c2e3352..8ac099555a 100644
Binary files a/icons/obj/smooth_structures/sandbags.dmi and b/icons/obj/smooth_structures/sandbags.dmi differ
diff --git a/icons/obj/vending.dmi b/icons/obj/vending.dmi
index a1471e6418..f66480f3aa 100644
Binary files a/icons/obj/vending.dmi and b/icons/obj/vending.dmi differ
diff --git a/icons/turf/areas.dmi b/icons/turf/areas.dmi
index a8a71e891d..4e78e0444b 100644
Binary files a/icons/turf/areas.dmi and b/icons/turf/areas.dmi differ
diff --git a/modular_citadel/code/datums/traits/neutral.dm b/modular_citadel/code/datums/traits/neutral.dm
index 2bb9c3a356..264dbfef0a 100644
--- a/modular_citadel/code/datums/traits/neutral.dm
+++ b/modular_citadel/code/datums/traits/neutral.dm
@@ -1,24 +1,24 @@
// Citadel-specific Neutral Traits
-/datum/trait/libido
+/datum/quirk/libido
name = "Nymphomania"
desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual."
value = 0
gain_text = "You are feeling extra wild."
lose_text = "You don't feel that burning sensation anymore."
-/datum/trait/libido/add()
- var/mob/living/M = trait_holder
+/datum/quirk/libido/add()
+ var/mob/living/M = quirk_holder
M.min_arousal = 16
M.arousal_rate = 3
-/datum/trait/libido/remove()
- var/mob/living/M = trait_holder
+/datum/quirk/libido/remove()
+ var/mob/living/M = quirk_holder
M.min_arousal = initial(M.min_arousal)
M.arousal_rate = initial(M.arousal_rate)
-/datum/trait/libido/on_process()
- var/mob/living/M = trait_holder
+/datum/quirk/libido/on_process()
+ var/mob/living/M = quirk_holder
if(M.canbearoused == FALSE)
- to_chat(trait_holder, "Having high libido is useless when you can't feel arousal at all!")
+ to_chat(quirk_holder, "Having high libido is useless when you can't feel arousal at all!")
qdel(src)
diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm
index d3910d5554..6c2bd35020 100644
--- a/modular_citadel/code/modules/client/loadout/__donator.dm
+++ b/modular_citadel/code/modules/client/loadout/__donator.dm
@@ -278,3 +278,9 @@ datum/gear/darksabresheath
path = /obj/item/ssword_kit
ckeywhitelist = list("phillip458")
+/datum/gear/techcoat
+ name = "Techomancers Labcoat"
+ category = slot_in_backpack
+ path = /obj/item/clothing/suit/toggle/labcoat/mad/techcoat
+ ckeywhitelist = list("wilchen")
+
diff --git a/modular_citadel/code/modules/custom_loadout/custom_items.dm b/modular_citadel/code/modules/custom_loadout/custom_items.dm
index 0abbba1845..c192804552 100644
--- a/modular_citadel/code/modules/custom_loadout/custom_items.dm
+++ b/modular_citadel/code/modules/custom_loadout/custom_items.dm
@@ -343,3 +343,11 @@
desc = "A piece of paper folded into neat little hat."
icon_state = "paperhat"
item_state = "paperhat"
+
+/obj/item/clothing/suit/toggle/labcoat/mad/techcoat
+ name = "Techomancers Labcoat"
+ desc = "An oddly special looking coat."
+ icon = 'icons/obj/custom.dmi'
+ icon_state = "rdcoat"
+ icon_override = 'icons/mob/custom_w.dmi'
+ item_state = "rdcoat"
diff --git a/rust_g.dll b/rust_g.dll
index 4e1df5afbd..44e38ef0dd 100644
Binary files a/rust_g.dll and b/rust_g.dll differ
diff --git a/strings/french_replacement.json b/strings/french_replacement.json
new file mode 100644
index 0000000000..4c89d98812
--- /dev/null
+++ b/strings/french_replacement.json
@@ -0,0 +1,91 @@
+{
+
+ "french": {
+ "yes": "oui",
+ "no": "non",
+ "I'm": "j'",
+ "am": "suis",
+ "a": "un",
+ "and": "et",
+ "the": "l'",
+ "I": "j'",
+ "for": "pour",
+ "with": "avec",
+ "of": "de",
+
+
+ "assistant": "ravageur",
+ "assistants": "ravageurs",
+ "baby": [
+ "enfant",
+ "petit baguette"
+ ],
+ "bad": "mal",
+ "bye": [
+ "bon voyage",
+ "adieu",
+ "au revoir"
+ ],
+ "cake": "gateau",
+ "captain": "capitaine",
+ "changeling": "changeur",
+ "cheese": [
+ "brie",
+ "roquefort",
+ "camembert"
+ ],
+ "cigarette": "clope",
+ "cook": "cuisinier",
+ "dad": "papa",
+ "enemy": "silly english dog",
+ "friend": "ami",
+ "good": "bon",
+ "greytide": "les gitans",
+ "greytider": "les gitans",
+ "greytiders": "les gitans",
+ "hardsuit": "burkini",
+ "hello": [
+ "'allo",
+ "bonjour",
+ "salut"
+ ],
+ "maint": "les banlieues",
+ "meat": [
+ "coq au vin",
+ "boeuf"
+ ],
+ "mom": "maman",
+ "my": "mon",
+ "nuke": [
+ "grand bombe",
+ "la baguette ultime"
+ ],
+ "op": "boche",
+ "operative": "boche",
+ "operatives": "boches",
+ "ops": "boches",
+ "urity": "urite",
+ "security": "securite",
+ "shit": "merde",
+ "shitcurity": [
+ "gendarmerie",
+ "les keufs"
+ ],
+ "shitsec": [
+ "gendarmerie",
+ "les keufs"
+ ],
+ "spaghetti": "macaroni",
+ "spicy": "epice",
+ "thanks": "merci",
+ "tomato": "tomate",
+ "traitor": "collaborateur",
+ "want": "envie",
+ "what's": "quel est",
+ "who's": "qui est",
+ "why": "porquois",
+ "wine": "vin",
+ "wizard": "sorcier"
+ }
+
+}
\ No newline at end of file
diff --git a/strings/word_replacement.json b/strings/italian_replacement.json
similarity index 99%
rename from strings/word_replacement.json
rename to strings/italian_replacement.json
index 9565ebe94a..42bef05a22 100644
--- a/strings/word_replacement.json
+++ b/strings/italian_replacement.json
@@ -1,4 +1,5 @@
{
+
"italian": {
"I'm": "I'm-a",
"am": "am-a",
@@ -62,5 +63,7 @@
"whose": "whose-a",
"why": "for-a what reason",
"wine": "vino"
- }
-}
+ }
+
+
+}
\ No newline at end of file
diff --git a/strings/names/wizardfirst.txt b/strings/names/wizardfirst.txt
index 8c9e1e35fe..f1e9a10a58 100644
--- a/strings/names/wizardfirst.txt
+++ b/strings/names/wizardfirst.txt
@@ -24,6 +24,7 @@ Prospero
Radagast
Raistlin
Rasputin
+Rincewind
Saruman
Tenser
Terefi
diff --git a/strings/names/wizardsecond.txt b/strings/names/wizardsecond.txt
index 4233ad5430..dd191cfa2b 100644
--- a/strings/names/wizardsecond.txt
+++ b/strings/names/wizardsecond.txt
@@ -34,6 +34,7 @@ the Unstoppable
the Weeping
the White
the Wise
+the Wizzard
Unseen
Weatherwax
Yagg
\ No newline at end of file
diff --git a/tgstation.dme b/tgstation.dme
index fd1de72cff..d356f887a4 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -261,7 +261,7 @@
#include "code\controllers\subsystem\processing\obj.dm"
#include "code\controllers\subsystem\processing\processing.dm"
#include "code\controllers\subsystem\processing\projectiles.dm"
-#include "code\controllers\subsystem\processing\traits.dm"
+#include "code\controllers\subsystem\processing\quirks.dm"
#include "code\controllers\subsystem\processing\wet_floors.dm"
#include "code\datums\action.dm"
#include "code\datums\ai_laws.dm"
@@ -316,6 +316,7 @@
#include "code\datums\components\_component.dm"
#include "code\datums\components\anti_magic.dm"
#include "code\datums\components\archaeology.dm"
+#include "code\datums\components\armor_plate.dm"
#include "code\datums\components\beauty.dm"
#include "code\datums\components\butchering.dm"
#include "code\datums\components\caltrop.dm"
@@ -444,7 +445,7 @@
#include "code\datums\status_effects\gas.dm"
#include "code\datums\status_effects\neutral.dm"
#include "code\datums\status_effects\status_effect.dm"
-#include "code\datums\traits\_trait.dm"
+#include "code\datums\traits\_quirk.dm"
#include "code\datums\traits\good.dm"
#include "code\datums\traits\negative.dm"
#include "code\datums\traits\neutral.dm"
@@ -559,7 +560,6 @@
#include "code\game\machinery\rechargestation.dm"
#include "code\game\machinery\recycler.dm"
#include "code\game\machinery\requests_console.dm"
-#include "code\game\machinery\robot_fabricator.dm"
#include "code\game\machinery\shieldgen.dm"
#include "code\game\machinery\Sleeper.dm"
#include "code\game\machinery\slotmachine.dm"
@@ -1433,6 +1433,7 @@
#include "code\modules\clothing\suits\jobs.dm"
#include "code\modules\clothing\suits\labcoat.dm"
#include "code\modules\clothing\suits\miscellaneous.dm"
+#include "code\modules\clothing\suits\reactive_armour.dm"
#include "code\modules\clothing\suits\toggles.dm"
#include "code\modules\clothing\suits\utility.dm"
#include "code\modules\clothing\suits\vg_suits.dm"
@@ -2332,6 +2333,7 @@
#include "code\modules\reagents\chemistry\machinery\chem_dispenser.dm"
#include "code\modules\reagents\chemistry\machinery\chem_heater.dm"
#include "code\modules\reagents\chemistry\machinery\chem_master.dm"
+#include "code\modules\reagents\chemistry\machinery\chem_synthesizer.dm"
#include "code\modules\reagents\chemistry\machinery\pandemic.dm"
#include "code\modules\reagents\chemistry\machinery\reagentgrinder.dm"
#include "code\modules\reagents\chemistry\machinery\smoke_machine.dm"
diff --git a/tgui/src/interfaces/chem_synthesizer.ract b/tgui/src/interfaces/chem_synthesizer.ract
new file mode 100644
index 0000000000..f57bd4ba71
--- /dev/null
+++ b/tgui/src/interfaces/chem_synthesizer.ract
@@ -0,0 +1,21 @@
+ + {{else}} + Recipient Empty + {{/each}} + {{else}} + No Recipient + {{/if}} + |