From dc88d0d01551dc6170bbbcced17f3e2989c83c44 Mon Sep 17 00:00:00 2001
From: Darius <5933805+LeDrascol@users.noreply.github.com>
Date: Sat, 21 Jan 2023 12:21:25 -0500
Subject: [PATCH 01/61] Adds a radiation immunity quirk
Adds the Lead Blooded quirk, which renders a user immune to radiation.
---
modular_splurt/code/datums/traits/good.dm | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/modular_splurt/code/datums/traits/good.dm b/modular_splurt/code/datums/traits/good.dm
index b305c79997..dbcf9efbc1 100644
--- a/modular_splurt/code/datums/traits/good.dm
+++ b/modular_splurt/code/datums/traits/good.dm
@@ -33,6 +33,14 @@
quirk_holder.weather_immunities -= "ash"
*/
+/datum/quirk/immunity_rads
+ name = "Lead Blooded"
+ desc = "Your body been rendered completely immune to the effects of radiation. Bask in the supermatter\'s warming glow without worry! Contains less than 1% actual lead."
+ value = 3
+ mob_trait = TRAIT_RADIMMUNE
+ gain_text = span_notice("You feel drawn to Cherenkov's glow.")
+ lose_text = span_notice("You realize that rads aren't so rad.")
+
/datum/quirk/dominant_aura
name = "Dominant Aura"
desc = "Your mere presence is assertive enough to appear as powerful to other people, so much in fact that the weaker kind can't help but throw themselves at your feet at the snap of a finger."
From f591ccdc3012fff0574a4ef3879b3d3b477bb273 Mon Sep 17 00:00:00 2001
From: Darius <5933805+LeDrascol@users.noreply.github.com>
Date: Mon, 23 Jan 2023 15:20:57 -0500
Subject: [PATCH 02/61] Convert quirk Lead Blooded to Rad Fiend
Instead of granting immunity, this new revision of the quirk grants a high level of radiation resistance. In addition, the player gains a customizable glow effect.
---
code/__SPLURTCODE/DEFINES/traits.dm | 2 +
modular_splurt/code/datums/traits/good.dm | 50 +++++++++++++--
.../code/datums/traits/trait_actions.dm | 64 +++++++++++++++++++
.../mob/living/carbon/human/species.dm | 9 +++
4 files changed, 119 insertions(+), 6 deletions(-)
diff --git a/code/__SPLURTCODE/DEFINES/traits.dm b/code/__SPLURTCODE/DEFINES/traits.dm
index 9f0c41e694..f4d988258a 100644
--- a/code/__SPLURTCODE/DEFINES/traits.dm
+++ b/code/__SPLURTCODE/DEFINES/traits.dm
@@ -27,3 +27,5 @@
#define TRAIT_NUDIST "Nudist"
+#define TRAIT_RAD_FIEND "RadFiend"
+
diff --git a/modular_splurt/code/datums/traits/good.dm b/modular_splurt/code/datums/traits/good.dm
index dbcf9efbc1..9bca9d5017 100644
--- a/modular_splurt/code/datums/traits/good.dm
+++ b/modular_splurt/code/datums/traits/good.dm
@@ -33,14 +33,52 @@
quirk_holder.weather_immunities -= "ash"
*/
-/datum/quirk/immunity_rads
- name = "Lead Blooded"
- desc = "Your body been rendered completely immune to the effects of radiation. Bask in the supermatter\'s warming glow without worry! Contains less than 1% actual lead."
- value = 3
- mob_trait = TRAIT_RADIMMUNE
- gain_text = span_notice("You feel drawn to Cherenkov's glow.")
+/datum/quirk/rad_fiend
+ name = "Rad Fiend"
+ desc = "You've been blessed by Cherenkov's warming light, causing you to emit a subtle glow at all times. Only intense radiation is capable of penetrating your protective barrier."
+ value = 2
+ mob_trait = TRAIT_RAD_FIEND
+ gain_text = span_notice("You feel empowered by Cherenkov's glow.")
lose_text = span_notice("You realize that rads aren't so rad.")
+ // Variable for the radiation immunity check
+ var/can_gain = TRUE
+
+/datum/quirk/rad_fiend/add()
+ // Define quirk holder mob
+ var/mob/living/carbon/human/quirk_mob = quirk_holder
+
+ // Check for any radiation immunity
+ if(HAS_TRAIT(quirk_mob, TRAIT_RADIMMUNE))
+ // Set gain status
+ can_gain = FALSE
+
+ // Return without doing anything
+ return
+
+ // Add glow control action
+ var/datum/action/rad_fiend/update_glow/quirk_action = new
+ quirk_action.Grant(quirk_mob)
+
+/datum/quirk/rad_fiend/post_add()
+ // Check if quirk effect was gained
+ if(can_gain)
+ return
+
+ // Alert quirk holder of gain status
+ to_chat(quirk_holder, span_warning("As you are immune to radiation, you were unable to gain Cherenkov's blessing. Please discuss alternatives with a medical professional."))
+
+/datum/quirk/rad_fiend/remove()
+ // Define quirk holder mob
+ var/mob/living/carbon/human/quirk_mob = quirk_holder
+
+ // Remove glow control action
+ var/datum/action/rad_fiend/update_glow/quirk_action = locate() in quirk_mob.actions
+ quirk_action.Remove(quirk_mob)
+
+ // Remove glow effect
+ quirk_mob.remove_filter("rad_fiend_glow")
+
/datum/quirk/dominant_aura
name = "Dominant Aura"
desc = "Your mere presence is assertive enough to appear as powerful to other people, so much in fact that the weaker kind can't help but throw themselves at your feet at the snap of a finger."
diff --git a/modular_splurt/code/datums/traits/trait_actions.dm b/modular_splurt/code/datums/traits/trait_actions.dm
index 792f7b8e8f..ed9c4faf14 100644
--- a/modular_splurt/code/datums/traits/trait_actions.dm
+++ b/modular_splurt/code/datums/traits/trait_actions.dm
@@ -341,3 +341,67 @@
return
else
to_chat(H, span_warning("You are already conserving your energy!"))
+
+//
+// Quirk: Rad Fiend
+//
+
+/datum/action/rad_fiend
+ name = "Broken Rad Action"
+ desc = "Report this to a coder."
+ icon_icon = 'icons/effects/effects.dmi'
+ button_icon_state = "static"
+
+/datum/action/rad_fiend/update_glow
+ name = "Modify Glow"
+ desc = "Change your radioactive glow color."
+ button_icon_state = "blank"
+
+ // Glow color to use
+ var/glow_color = "#39ff14" // Neon green
+
+ // Thickness of glow outline
+ var/glow_range = 2
+
+/datum/action/rad_fiend/update_glow/Grant()
+ . = ..()
+
+ // Define user mob
+ var/mob/living/carbon/human/action_mob = owner
+
+ // Add outline effect
+ action_mob.add_filter("rad_fiend_glow", 1, list("type" = "outline", "color" = glow_color+"30", "size" = glow_range))
+
+/datum/action/rad_fiend/update_glow/Remove()
+ . = ..()
+
+ // Define user mob
+ var/mob/living/carbon/human/action_mob = owner
+
+ // Remove glow
+ action_mob.remove_filter("rad_fiend_glow")
+
+/datum/action/rad_fiend/update_glow/Trigger()
+ . = ..()
+
+ // Define user mob
+ var/mob/living/carbon/human/action_mob = owner
+
+ // Ask user for color input
+ var/input_color = input(action_mob, "Select a color to use for your glow outline.", "Select Glow Color", glow_color) as color|null
+
+ // Check if color input was given
+ // Reset to stored color when not given input
+ glow_color = (input_color ? input_color : glow_color)
+
+ // Ask user for range input
+ var/input_range = input(action_mob, "How much do you glow? Value may range between 1 to 2.", "Select Glow Range", glow_range) as num|null
+
+ // Check if range input was given
+ // Reset to stored color when not given input
+ // Input is clamped in the 1-2 range
+ glow_range = (input_range ? clamp(input_range, 1, 2) : glow_range)
+
+ // Update outline effect
+ action_mob.remove_filter("rad_fiend_glow")
+ action_mob.add_filter("rad_fiend_glow", 1, list("type" = "outline", "color" = glow_color+"30", "size" = glow_range))
diff --git a/modular_splurt/code/modules/mob/living/carbon/human/species.dm b/modular_splurt/code/modules/mob/living/carbon/human/species.dm
index 5fec507149..bf8ee799cd 100644
--- a/modular_splurt/code/modules/mob/living/carbon/human/species.dm
+++ b/modular_splurt/code/modules/mob/living/carbon/human/species.dm
@@ -33,3 +33,12 @@
*/
thirst_rate *= H.physiology.thirst_mod
H.adjust_thirst(-thirst_rate)
+
+/datum/species/handle_mutations_and_radiation(mob/living/carbon/human/H)
+ // Check for rad fiend quirk
+ // Check for radiation resist threshold
+ if(HAS_TRAIT(H, TRAIT_RAD_FIEND) && (H.radiation < RAD_BURN_THRESHOLD))
+ // Return without effects
+ return TRUE
+
+ . = ..()
From 02047df9d4bd6c4b2c4f0cf02660f259911250ca Mon Sep 17 00:00:00 2001
From: Comicao1 <33708588+Comicao1@users.noreply.github.com>
Date: Wed, 8 Feb 2023 22:13:41 -0300
Subject: [PATCH 03/61] Wendigo Fix
---
.../datums/interactions/lewd_definitions.dm | 8 +++
.../antagonists/wendigo/mob/defines_init.dm | 14 ++++-
.../wendigo/mob/organs_bodyparts.dm | 2 +-
.../wendigo/mob/wendigo_defense.dm | 63 +++++++++++++++++++
.../mob/living/carbon/carbon_defense.dm | 13 ++++
.../mob/living/carbon/human/human_defense.dm | 52 +++++++++++++++
.../code/modules/mob/living/living.dm | 9 +++
tgstation.dme | 4 ++
8 files changed, 163 insertions(+), 2 deletions(-)
create mode 100644 modular_splurt/code/datums/interactions/lewd_definitions.dm
create mode 100644 modular_splurt/code/modules/antagonists/wendigo/mob/wendigo_defense.dm
create mode 100644 modular_splurt/code/modules/mob/living/carbon/carbon_defense.dm
create mode 100644 modular_splurt/code/modules/mob/living/carbon/human/human_defense.dm
diff --git a/modular_splurt/code/datums/interactions/lewd_definitions.dm b/modular_splurt/code/datums/interactions/lewd_definitions.dm
new file mode 100644
index 0000000000..7e5f7c044d
--- /dev/null
+++ b/modular_splurt/code/datums/interactions/lewd_definitions.dm
@@ -0,0 +1,8 @@
+
+/mob/living/cum(mob/living/partner, target_orifice)
+ . = ..()
+ if(src != partner)
+ if(iswendigo(partner) && partner.pulling == src)
+ var/mob/living/carbon/wendigo/W = partner
+ W.slaves |= src
+ to_chat(src, " You are now [W]'s slave! Serve your master properly! ")
\ No newline at end of file
diff --git a/modular_splurt/code/modules/antagonists/wendigo/mob/defines_init.dm b/modular_splurt/code/modules/antagonists/wendigo/mob/defines_init.dm
index 3b2fb09aa3..09886b7daa 100644
--- a/modular_splurt/code/modules/antagonists/wendigo/mob/defines_init.dm
+++ b/modular_splurt/code/modules/antagonists/wendigo/mob/defines_init.dm
@@ -37,6 +37,8 @@
var/obj/item/ears_extra = null
var/obj/item/wrists = null
+ var/list/slaves = list() //people enslaved
+
/mob/living/carbon/wendigo/Initialize()
. = ..()
/* //TODO: Uncomment when objectives + forest get finished
@@ -79,6 +81,7 @@
/mob/living/carbon/wendigo/Destroy()
QDEL_NULL(physiology)
+ slaves.Cut()
return ..()
/mob/living/carbon/wendigo/update_body_parts()
@@ -122,7 +125,7 @@
//ORGANS
//
/mob/living/carbon/wendigo/create_internal_organs()
- internal_organs += new /obj/item/organ/eyes/wendigo
+ internal_organs += new /obj/item/organ/eyes/night_vision/wendigo
internal_organs += new /obj/item/organ/liver/wendigo
internal_organs += new /obj/item/organ/tongue
@@ -131,3 +134,12 @@
internal_organs += new /obj/item/organ/stomach
internal_organs += new /obj/item/organ/ears
..()
+
+/mob/living/carbon/wendigo/movement_delay()
+ . = ..()
+ var/adding = 0
+ var/turf/T = get_turf(src)
+ if(T.get_lumcount() < 0.2)
+ adding += 1
+ . += adding
+
diff --git a/modular_splurt/code/modules/antagonists/wendigo/mob/organs_bodyparts.dm b/modular_splurt/code/modules/antagonists/wendigo/mob/organs_bodyparts.dm
index 11c74a7573..5fba7e8215 100644
--- a/modular_splurt/code/modules/antagonists/wendigo/mob/organs_bodyparts.dm
+++ b/modular_splurt/code/modules/antagonists/wendigo/mob/organs_bodyparts.dm
@@ -20,7 +20,7 @@
var/mob/living/carbon/wendigo/A = C
A.metabolize_hunger()
-/obj/item/organ/eyes/wendigo
+/obj/item/organ/eyes/night_vision/wendigo
sight_flags = SEE_MOBS
/obj/item/bodypart/head/wendigo
diff --git a/modular_splurt/code/modules/antagonists/wendigo/mob/wendigo_defense.dm b/modular_splurt/code/modules/antagonists/wendigo/mob/wendigo_defense.dm
new file mode 100644
index 0000000000..d6a9a2314e
--- /dev/null
+++ b/modular_splurt/code/modules/antagonists/wendigo/mob/wendigo_defense.dm
@@ -0,0 +1,63 @@
+/mob/living/carbon/wendigo/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
+ if(user.a_intent == INTENT_HARM)
+ . = ..(user, TRUE)
+ if(.)
+ return
+ adjustBruteLoss(15)
+ var/hitverb = "punched"
+ if(mob_size < MOB_SIZE_LARGE)
+ step_away(src,user,15)
+ sleep(1)
+ step_away(src,user,15)
+ hitverb = "slammed"
+ playsound(loc, "punch", 25, 1, -1)
+ visible_message("[user] has [hitverb] [src]!", \
+ "[user] has [hitverb] [src]!", null, COMBAT_MESSAGE_RANGE)
+ return 1
+
+/mob/living/carbon/wendigo/on_attack_hand(mob/living/carbon/human/M)
+ . = ..()
+ if(.) //To allow surgery to return properly.
+ return
+ switch(M.a_intent)
+ if (INTENT_HARM)
+ if(M != pulling && !src.slaves.Find(M))
+ var/damage = rand(1, 9)
+ if (prob(90))
+ playsound(loc, "punch", 25, 1, -1)
+ visible_message("[M] has punched [src]!", \
+ "[M] has punched [src]!", null, COMBAT_MESSAGE_RANGE)
+ var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
+ apply_damage(damage, BRUTE, affecting)
+ log_combat(M, src, "attacked")
+ M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
+ else
+ playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
+ visible_message("[M] has attempted to punch [src]!", \
+ "[M] has attempted to punch [src]!", null, COMBAT_MESSAGE_RANGE)
+
+ if (INTENT_DISARM)
+ if (!lying && M != pulling && !src.slaves.Find(M))
+ M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
+ if (prob(5))
+ Unconscious(40)
+ playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ log_combat(M, src, "pushed")
+ visible_message("[M] has pushed down [src]!", \
+ "[M] has pushed down [src]!")
+ else
+ if (prob(50))
+ dropItemToGround(get_active_held_item())
+ playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ visible_message("[M] has disarmed [src]!", \
+ "[M] has disarmed [src]!", null, COMBAT_MESSAGE_RANGE)
+ else
+ playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
+ visible_message("[M] has attempted to disarm [src]!",\
+ "[M] has attempted to disarm [src]!", null, COMBAT_MESSAGE_RANGE)
+
+/mob/living/carbon/wendigo/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
+ if(!no_effect && !visual_effect_icon)
+ visual_effect_icon = ATTACK_EFFECT_CLAW
+ ..()
+
diff --git a/modular_splurt/code/modules/mob/living/carbon/carbon_defense.dm b/modular_splurt/code/modules/mob/living/carbon/carbon_defense.dm
new file mode 100644
index 0000000000..2939e1f545
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/carbon/carbon_defense.dm
@@ -0,0 +1,13 @@
+
+/mob/living/carbon/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
+ . = ..()
+ if(iswendigo(src) && user == pulling)
+ to_chat(src, "I can't hit them, their grip is too strong!")
+ return FALSE
+ if(iswendigo(src))
+ var/mob/living/carbon/wendigo/W = src
+ if(W.slaves.Find(user))
+ to_chat(src, "I can't hit them, they're my master!")
+ return FALSE
+
+
diff --git a/modular_splurt/code/modules/mob/living/carbon/human/human_defense.dm b/modular_splurt/code/modules/mob/living/carbon/human/human_defense.dm
new file mode 100644
index 0000000000..fb1ddf88b3
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/carbon/human/human_defense.dm
@@ -0,0 +1,52 @@
+
+/mob/living/carbon/human/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
+ . = ..()
+ if(.) //To allow surgery to return properly.
+ return
+ if(iswendigo(user))
+ var/mob/living/carbon/wendigo/M = user
+ switch(M.a_intent)
+ if (INTENT_HARM)
+ var/damage = rand(1, 9)
+ var/turf/T = get_turf(user)
+ if(T.get_lumcount() < 0.2)
+ damage += rand(4,10)
+ if (prob(90))
+ playsound(loc, "punch", 25, 1, -1)
+ visible_message("[M] has punched [src]!", \
+ "[M] has punched [src]!", null, COMBAT_MESSAGE_RANGE)
+ var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
+ apply_damage(damage, BRUTE, affecting)
+ log_combat(M, src, "attacked")
+ M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
+ else
+ playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
+ visible_message("[M] has attempted to punch [src]!", \
+ "[M] has attempted to punch [src]!", null, COMBAT_MESSAGE_RANGE)
+ if(INTENT_GRAB)
+ grabbedby(M)
+ if(INTENT_HELP)
+ if(M == src && check_self_for_injuries())
+ return
+ help_shake_act(M)
+ if (INTENT_DISARM)
+ if (!lying)
+ M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
+ if (prob(5))
+ Unconscious(40)
+ playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ log_combat(M, src, "pushed")
+ visible_message("[M] has pushed down [src]!", \
+ "[M] has pushed down [src]!")
+ else
+ if (prob(50))
+ dropItemToGround(get_active_held_item())
+ playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ visible_message("[M] has disarmed [src]!", \
+ "[M] has disarmed [src]!", null, COMBAT_MESSAGE_RANGE)
+ else
+ playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
+ visible_message("[M] has attempted to disarm [src]!",\
+ "[M] has attempted to disarm [src]!", null, COMBAT_MESSAGE_RANGE)
+
+
diff --git a/modular_splurt/code/modules/mob/living/living.dm b/modular_splurt/code/modules/mob/living/living.dm
index c2b04a0d84..6d36fd208a 100644
--- a/modular_splurt/code/modules/mob/living/living.dm
+++ b/modular_splurt/code/modules/mob/living/living.dm
@@ -64,3 +64,12 @@
AddElement(/datum/element/smalltalk)
else
RemoveElement(/datum/element/smalltalk)
+
+/mob/living/do_resist_grab(moving_resist, forced, silent = FALSE)
+ . = ..()
+ if(iswendigo(pulledby)) //Grip is too strong, nonetheless.
+ to_chat(src, "The grip is too strong! I need some time...")
+ if(do_after(src, 200, target=pulledby))
+ to_chat(src, "I break free off [pulledby]'s grip!")
+ return TRUE
+
diff --git a/tgstation.dme b/tgstation.dme
index 3e90f99ab4..1e2527a8ab 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -4321,6 +4321,7 @@
#include "modular_splurt\code\datums\elements\spooky.dm"
#include "modular_splurt\code\datums\elements\wuv.dm"
#include "modular_splurt\code\datums\interactions\cuddling.dm"
+#include "modular_splurt\code\datums\interactions\lewd_definitions.dm"
#include "modular_splurt\code\datums\interactions\rope.dm"
#include "modular_splurt\code\datums\interactions\lewd\_lewd.dm"
#include "modular_splurt\code\datums\interactions\lewd\lewd_datums.dm"
@@ -4492,6 +4493,7 @@
#include "modular_splurt\code\modules\antagonists\wendigo\mob\mob_equip.dm"
#include "modular_splurt\code\modules\antagonists\wendigo\mob\organs_bodyparts.dm"
#include "modular_splurt\code\modules\antagonists\wendigo\mob\update_icons.dm"
+#include "modular_splurt\code\modules\antagonists\wendigo\mob\wendigo_defense.dm"
#include "modular_splurt\code\modules\arousal\arousal.dm"
#include "modular_splurt\code\modules\arousal\genitals.dm"
#include "modular_splurt\code\modules\arousal\genitals_sprite_accessories.dm"
@@ -4682,7 +4684,9 @@
#include "modular_splurt\code\modules\mob\living\say.dm"
#include "modular_splurt\code\modules\mob\living\brain\brain_item.dm"
#include "modular_splurt\code\modules\mob\living\carbon\carbon.dm"
+#include "modular_splurt\code\modules\mob\living\carbon\carbon_defense.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\human.dm"
+#include "modular_splurt\code\modules\mob\living\carbon\human\human_defense.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\human_defines.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\inventory.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\physiology.dm"
From e588d52fb598059adce8103d69cedb0097ae3679 Mon Sep 17 00:00:00 2001
From: Comicao1 <33708588+Comicao1@users.noreply.github.com>
Date: Wed, 8 Feb 2023 22:25:56 -0300
Subject: [PATCH 04/61] Update lewd_definitions.dm
---
modular_splurt/code/datums/interactions/lewd_definitions.dm | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/modular_splurt/code/datums/interactions/lewd_definitions.dm b/modular_splurt/code/datums/interactions/lewd_definitions.dm
index 7e5f7c044d..4af638e579 100644
--- a/modular_splurt/code/datums/interactions/lewd_definitions.dm
+++ b/modular_splurt/code/datums/interactions/lewd_definitions.dm
@@ -5,4 +5,5 @@
if(iswendigo(partner) && partner.pulling == src)
var/mob/living/carbon/wendigo/W = partner
W.slaves |= src
- to_chat(src, " You are now [W]'s slave! Serve your master properly! ")
\ No newline at end of file
+ to_chat(src, " You are now [W]'s slave! Serve your master properly! ")
+
From eb051adc4503b0be605ae6525b98cc4c0f4e86aa Mon Sep 17 00:00:00 2001
From: Comicao1 <33708588+Comicao1@users.noreply.github.com>
Date: Wed, 8 Feb 2023 23:26:45 -0300
Subject: [PATCH 05/61] More
---
code/modules/arousal/arousal.dm | 6 ++++++
modular_splurt/code/datums/interactions/lewd/_lewd.dm | 5 +++++
.../code/datums/interactions/lewd_definitions.dm | 9 ---------
.../code/modules/antagonists/wendigo/mob/defines_init.dm | 2 ++
tgstation.dme | 1 -
5 files changed, 13 insertions(+), 10 deletions(-)
delete mode 100644 modular_splurt/code/datums/interactions/lewd_definitions.dm
diff --git a/code/modules/arousal/arousal.dm b/code/modules/arousal/arousal.dm
index b1d8815696..86b6a38faa 100644
--- a/code/modules/arousal/arousal.dm
+++ b/code/modules/arousal/arousal.dm
@@ -84,6 +84,12 @@
R.reaction(turfing ? target : target.loc, TOUCH, 1, 0)
if(!turfing)
R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1), log = TRUE)
+ if(iswendigo(target))
+ var/mob/living/carbon/wendigo/W = target
+ if(W.pulling == src)
+ W.slaves |= src
+ to_chat(src, " You are now [W]'s slave! Serve your master properly! ")
+
G.last_orgasmed = world.time
R.clear_reagents()
//skyrat edit - chock i am going to beat you to death
diff --git a/modular_splurt/code/datums/interactions/lewd/_lewd.dm b/modular_splurt/code/datums/interactions/lewd/_lewd.dm
index a5579511b5..2cd1a55817 100644
--- a/modular_splurt/code/datums/interactions/lewd/_lewd.dm
+++ b/modular_splurt/code/datums/interactions/lewd/_lewd.dm
@@ -127,6 +127,7 @@
ass = new
ass.Insert(partner)
ass.climax_modify_size(src, getorganslot(ORGAN_SLOT_PENIS))
+
else
switch(last_genital.type)
if(/obj/item/organ/genital/penis)
@@ -193,6 +194,10 @@
ass = new
ass.Insert(partner)
ass.climax_modify_size(src, last_genital)
+ if(iswendigo(partner) && partner.pulling == src)
+ var/mob/living/carbon/wendigo/W = partner
+ W.slaves |= src
+ to_chat(src, " You are now [W]'s slave! Serve your master properly! ")
if(!message)
return ..()
if(gender == MALE)
diff --git a/modular_splurt/code/datums/interactions/lewd_definitions.dm b/modular_splurt/code/datums/interactions/lewd_definitions.dm
deleted file mode 100644
index 4af638e579..0000000000
--- a/modular_splurt/code/datums/interactions/lewd_definitions.dm
+++ /dev/null
@@ -1,9 +0,0 @@
-
-/mob/living/cum(mob/living/partner, target_orifice)
- . = ..()
- if(src != partner)
- if(iswendigo(partner) && partner.pulling == src)
- var/mob/living/carbon/wendigo/W = partner
- W.slaves |= src
- to_chat(src, " You are now [W]'s slave! Serve your master properly! ")
-
diff --git a/modular_splurt/code/modules/antagonists/wendigo/mob/defines_init.dm b/modular_splurt/code/modules/antagonists/wendigo/mob/defines_init.dm
index 09886b7daa..9cc5b9de67 100644
--- a/modular_splurt/code/modules/antagonists/wendigo/mob/defines_init.dm
+++ b/modular_splurt/code/modules/antagonists/wendigo/mob/defines_init.dm
@@ -110,8 +110,10 @@
return TRUE
/mob/living/carbon/wendigo/IsAdvancedToolUser()
return TRUE
+/* So they can be pulled.
/mob/living/carbon/wendigo/can_be_pulled()
return FALSE
+*/
/mob/living/carbon/wendigo/is_literate()
return TRUE
/mob/living/carbon/wendigo/canBeHandcuffed()
diff --git a/tgstation.dme b/tgstation.dme
index 1e2527a8ab..dbd4068123 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -4321,7 +4321,6 @@
#include "modular_splurt\code\datums\elements\spooky.dm"
#include "modular_splurt\code\datums\elements\wuv.dm"
#include "modular_splurt\code\datums\interactions\cuddling.dm"
-#include "modular_splurt\code\datums\interactions\lewd_definitions.dm"
#include "modular_splurt\code\datums\interactions\rope.dm"
#include "modular_splurt\code\datums\interactions\lewd\_lewd.dm"
#include "modular_splurt\code\datums\interactions\lewd\lewd_datums.dm"
From e63b40b7cb15710b6b5870bf564d465b1342e185 Mon Sep 17 00:00:00 2001
From: Comicao1 <33708588+Comicao1@users.noreply.github.com>
Date: Thu, 9 Feb 2023 00:18:49 -0300
Subject: [PATCH 06/61] Update arousal.dm
---
code/modules/arousal/arousal.dm | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/code/modules/arousal/arousal.dm b/code/modules/arousal/arousal.dm
index 86b6a38faa..43c816a7ba 100644
--- a/code/modules/arousal/arousal.dm
+++ b/code/modules/arousal/arousal.dm
@@ -84,11 +84,6 @@
R.reaction(turfing ? target : target.loc, TOUCH, 1, 0)
if(!turfing)
R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1), log = TRUE)
- if(iswendigo(target))
- var/mob/living/carbon/wendigo/W = target
- if(W.pulling == src)
- W.slaves |= src
- to_chat(src, " You are now [W]'s slave! Serve your master properly! ")
G.last_orgasmed = world.time
R.clear_reagents()
@@ -127,6 +122,11 @@
to_chat(src, span_userlove("You climax [(Lgen) ? "in [L]'s [Lgen.name]" : "with [L]"], your [G.name] spilling nothing."))
to_chat(L, span_userlove("[src] climaxes [(Lgen) ? "in your [Lgen.name]" : "with you"], [p_their()] [G.name] spilling nothing!"))
//SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) //Sandstorm edit
+ if(iswendigo(L))
+ var/mob/living/carbon/wendigo/W = L
+ if(L.pulling == src)
+ L.slaves |= src
+ to_chat(src, " You are now [W]'s slave! Serve your master properly! ")
do_climax(fluid_source, spillage ? loc : L, G, spillage,, Lgen)
//L.receive_climax(src, Lgen, G, spillage)
From ca5b8fd5269b6010de062592fe4694bdacb352c3 Mon Sep 17 00:00:00 2001
From: Comicao1 <33708588+Comicao1@users.noreply.github.com>
Date: Thu, 9 Feb 2023 00:23:23 -0300
Subject: [PATCH 07/61] D'oh
---
code/modules/arousal/arousal.dm | 5 -----
modular_splurt/code/modules/arousal/arousal.dm | 5 +++++
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/code/modules/arousal/arousal.dm b/code/modules/arousal/arousal.dm
index 43c816a7ba..f78f64fdb0 100644
--- a/code/modules/arousal/arousal.dm
+++ b/code/modules/arousal/arousal.dm
@@ -122,11 +122,6 @@
to_chat(src, span_userlove("You climax [(Lgen) ? "in [L]'s [Lgen.name]" : "with [L]"], your [G.name] spilling nothing."))
to_chat(L, span_userlove("[src] climaxes [(Lgen) ? "in your [Lgen.name]" : "with you"], [p_their()] [G.name] spilling nothing!"))
//SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) //Sandstorm edit
- if(iswendigo(L))
- var/mob/living/carbon/wendigo/W = L
- if(L.pulling == src)
- L.slaves |= src
- to_chat(src, " You are now [W]'s slave! Serve your master properly! ")
do_climax(fluid_source, spillage ? loc : L, G, spillage,, Lgen)
//L.receive_climax(src, Lgen, G, spillage)
diff --git a/modular_splurt/code/modules/arousal/arousal.dm b/modular_splurt/code/modules/arousal/arousal.dm
index b60b8e95e1..2fb47ccef0 100644
--- a/modular_splurt/code/modules/arousal/arousal.dm
+++ b/modular_splurt/code/modules/arousal/arousal.dm
@@ -1,6 +1,11 @@
/mob/living/carbon/human/mob_climax_partner(obj/item/organ/genital/G, mob/living/L, spillage, mb_time, obj/item/organ/genital/Lgen, forced = FALSE)
. = ..()
L.receive_climax(src, Lgen, G, spillage, forced = forced)
+ if(iswendigo(L))
+ var/mob/living/carbon/wendigo/W = L
+ if(W.pulling == src)
+ W.slaves |= src
+ to_chat(src, " You are now [W]'s slave! Serve your master properly! ")
/mob/living/proc/receive_climax(mob/living/partner, obj/item/organ/genital/receiver, obj/item/organ/genital/source, spill, forced)
//gregnancy...
From 5971ee7884357e0c7299a6902b003a273840d580 Mon Sep 17 00:00:00 2001
From: Comicao1 <33708588+Comicao1@users.noreply.github.com>
Date: Thu, 9 Feb 2023 01:01:07 -0300
Subject: [PATCH 08/61] Update arousal.dm
---
code/modules/arousal/arousal.dm | 1 -
1 file changed, 1 deletion(-)
diff --git a/code/modules/arousal/arousal.dm b/code/modules/arousal/arousal.dm
index f78f64fdb0..b1d8815696 100644
--- a/code/modules/arousal/arousal.dm
+++ b/code/modules/arousal/arousal.dm
@@ -84,7 +84,6 @@
R.reaction(turfing ? target : target.loc, TOUCH, 1, 0)
if(!turfing)
R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1), log = TRUE)
-
G.last_orgasmed = world.time
R.clear_reagents()
//skyrat edit - chock i am going to beat you to death
From e7bb7b85cd56811ab73205c4757912dccc11285e Mon Sep 17 00:00:00 2001
From: Darius <5933805+LeDrascol@users.noreply.github.com>
Date: Sun, 12 Feb 2023 13:25:09 -0500
Subject: [PATCH 09/61] Remove duplicate TRAIT_CLOTH_EATER
Removes a duplicate define for TRAIT_CLOTH_EATER caused during a merge.
---
code/__SPLURTCODE/DEFINES/traits.dm | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/code/__SPLURTCODE/DEFINES/traits.dm b/code/__SPLURTCODE/DEFINES/traits.dm
index 97e8f534bb..bd9157a9bb 100644
--- a/code/__SPLURTCODE/DEFINES/traits.dm
+++ b/code/__SPLURTCODE/DEFINES/traits.dm
@@ -25,7 +25,6 @@
#define TRAIT_ARACHNID "Arachnid"
#define TRAIT_FLUTTER "flutter"
#define TRAIT_NUDIST "Nudist"
-#define TRAIT_CLOTH_EATER "cloth_eater"
#define TRAIT_CLOTH_EATER "cloth_eater"
#define TRAIT_WEREWOLF "Werewolf"
-#define TRAIT_RAD_FIEND "RadFiend"
+#define TRAIT_RAD_FIEND "RadFiend"
From 58aa56c57b50ee21db77bafb6021aa0c6f198898 Mon Sep 17 00:00:00 2001
From: BongaTheProto <93835010+BongaTheProto@users.noreply.github.com>
Date: Fri, 17 Feb 2023 22:52:32 -0500
Subject: [PATCH 10/61] frankenstein
---
code/__SPLURTCODE/DEFINES/loadout.dm | 8 +
code/modules/client/preferences.dm | 1 +
code/modules/client/preferences_savefile.dm | 5 +-
.../code/modules/client/preferences.dm | 1182 +++++++++++++++++
.../modules/client/preferences_savefile.dm | 5 +
tgstation.dme | 1 +
6 files changed, 1201 insertions(+), 1 deletion(-)
create mode 100644 code/__SPLURTCODE/DEFINES/loadout.dm
diff --git a/code/__SPLURTCODE/DEFINES/loadout.dm b/code/__SPLURTCODE/DEFINES/loadout.dm
new file mode 100644
index 0000000000..881080f664
--- /dev/null
+++ b/code/__SPLURTCODE/DEFINES/loadout.dm
@@ -0,0 +1,8 @@
+//the names of the customization tabs
+//#define SETTINGS_TAB 0 //Already exists
+#define GAME_PREFERENCES_TAB 1
+#define APPEARANCE_TAB 2
+#define SPEECH_TAB 3
+#define LOADOUT_TAB 4
+#define CONTENT_PREFERENCES_TAB 5
+#define KEYBINDINGS_TAB_OLD 6
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 7a5f4a0e3e..06a0cadebd 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -1402,6 +1402,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Be Antagonist Victim: [be_victim ? be_victim : BEVICTIM_ASK]
"
dat += "Disable combat mode cursor: [disable_combat_cursor?"Yes":"No"]
"
dat += "Splashscreen Player Panel Style: [(toggles & TG_PLAYER_PANEL)?"TG":"Old"]
"
+ dat += "Character Creation Menu Style: [new_character_creator ? "New" : "Old"]
"
//SPLURT Edit end
dat += "
"
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index c265604f81..e2dcb8454d 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
-#define SAVEFILE_VERSION_MAX 57
+#define SAVEFILE_VERSION_MAX 57.01
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -490,6 +490,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["disable_combat_cursor"] >> disable_combat_cursor
S["use_new_playerpanel"] >> use_new_playerpanel
S["gfluid_blacklist"] >> gfluid_blacklist
+ S["new_character_creator"] >> new_character_creator
+
//favorite outfits
S["favorite_outfits"] >> favorite_outfits
@@ -692,6 +694,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["disable_combat_cursor"], disable_combat_cursor)
WRITE_FILE(S["use_new_playerpanel"], use_new_playerpanel)
WRITE_FILE(S["gfluid_blacklist"], gfluid_blacklist)
+ WRITE_FILE(S["new_character_creator"], new_character_creator)
var/mob/living/carbon/human/H = parent.mob
if(istype(H))
diff --git a/modular_splurt/code/modules/client/preferences.dm b/modular_splurt/code/modules/client/preferences.dm
index 13b9bc882b..9931dd1a2b 100644
--- a/modular_splurt/code/modules/client/preferences.dm
+++ b/modular_splurt/code/modules/client/preferences.dm
@@ -1,7 +1,11 @@
+#define APPEARANCE_CATEGORY_COLUMN "
| "
+ if(jobban_isbanned(user, "appearance"))
+ dat += "You are banned from using custom names and appearances. You can continue to adjust your characters, but you will be randomised once you join the game. " + dat += "Random Name " + dat += "Always Random Name:[be_random_name ? "Yes" : "No"] " + + dat += "[nameless ? "Default designation" : "Name"]:" + dat += "[real_name] " + dat += "Be nameless: [nameless ? "Yes" : "No"] " + + dat += "Gender: [gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))] " + dat += "Age: [age] " + + dat += "Special Names: " + var/old_group + for(var/custom_name_id in GLOB.preferences_custom_names) + var/namedata = GLOB.preferences_custom_names[custom_name_id] + if(!old_group) + old_group = namedata["group"] + else if(old_group != namedata["group"]) + old_group = namedata["group"] + dat += " " + dat += "[namedata["pref_name"]]: [custom_names[custom_name_id]] " + dat += " " + + dat += "Custom job preferences: " + dat += "Preferred AI Core Display: [preferred_ai_core_display] " + dat += "Preferred Security Department: [prefered_security_department] | "
+ dat += "
"
+ dat += "Flavor Text" + dat += "Set Examine Text" + if(length(features["flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN) + if(!length(features["flavor_text"])) + dat += "\[...\] " //skyrat - adds //come to brazil or brazil comes to you + else + dat += "[html_encode(features["flavor_text"])] " //skyrat - adds and uses html_encode + else + dat += "[TextPreview(html_encode(features["flavor_text"]))]... " //skyrat edit, uses html_encode + //SPLURT edit - naked flavor text + dat += " Naked Flavor Text" + dat += "Set Naked Examine Text" + if(length(features["naked_flavor_text"]) <= 40) + if(!length(features["naked_flavor_text"])) + dat += "\[...\] " + else + dat += "[html_encode(features["naked_flavor_text"])] " + else + dat += "[TextPreview(html_encode(features["naked_flavor_text"]))]... " + //SPLURT edit end + dat += " Silicon Flavor Text" + dat += "Set Silicon Examine Text" + if(length(features["silicon_flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN) + if(!length(features["silicon_flavor_text"])) + dat += "\[...\] " + else + dat += "[features["silicon_flavor_text"]] " + else + dat += "[TextPreview(features["silicon_flavor_text"])]... " + dat += " OOC notes" + dat += "Set OOC notes" + var/ooc_notes_len = length(features["ooc_notes"]) + if(ooc_notes_len <= MAX_FLAVOR_PREVIEW_LEN) + if(!ooc_notes_len) + dat += "\[...\] " + else + dat += "[features["ooc_notes"]] " + else + dat += "[TextPreview(features["ooc_notes"])]... " + //SPLURT EDIT + dat += " Headshot Image" + dat += "Set Headshot Image" + if(features["headshot_link"]) + dat += " " + //SPLURT EDIT END + //SKYRAT EDIT + dat += "ERP : [erppref] " + dat += "Non-Con : [nonconpref] " + dat += "Vore : [vorepref] " + //END OF SKYRAT EDIT + + dat += " Records" + dat += "Security Records " + if(length_char(security_records) <= 40) + if(!length(security_records)) + dat += "\[...\]" + else + dat += "[security_records]" + else + dat += "[TextPreview(security_records)]... " + + dat += " Medical Records " + if(length_char(medical_records) <= 40) + if(!length(medical_records)) + dat += "\[...\] " + else + dat += "[medical_records]" + else + dat += "[TextPreview(medical_records)]... " + + dat += APPEARANCE_CATEGORY_COLUMN //body moves right sandstorm change + + dat += " Body" + dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]" + if(gender != NEUTER && pref_species.sexes) + dat += "Body Model:[features["body_model"] == MALE ? "Masculine" : "Feminine"] " + dat += "Limb Modification: " + dat += "Modify Limbs " + for(var/modification in modified_limbs) + if(modified_limbs[modification][1] == LOADOUT_LIMB_PROSTHETIC) + dat += "[modification]: [modified_limbs[modification][2]] " + else + dat += "[modification]: [modified_limbs[modification][1]] " + dat += " " + dat += "Species:[pref_species.name] " + dat += "Custom Species Name:[custom_species ? custom_species : "None"] " + dat += "Random Body:Randomize! " + dat += "Always Random Body:[be_random_body ? "Yes" : "No"] " + dat += " Cycle background:[bgstate] " + + dat += " | " //body moves right sandstorm change
+
+ var/use_skintones = pref_species.use_skintones
+ if(use_skintones)
+ dat += APPEARANCE_CATEGORY_COLUMN
+
+ dat += "
| [marking_list[2]] - [actual_name] | ˄ ˅ X [color_marking_dat] |
"
+ dat += "Clothing & Equipment" + /* skyrat change + dat += "Underwear:[underwear]" + if(GLOB.underwear_list[underwear]?.has_color) + dat += "Underwear Color: #[undie_color] Change" + dat += "Undershirt:[undershirt]" + if(GLOB.undershirt_list[undershirt]?.has_color) + dat += "Undershirt Color: #[shirt_color] Change " + dat += "Socks:[socks]" + if(GLOB.socks_list[socks]?.has_color) + dat += "Socks Color: #[socks_color] Change " + */ + dat += "Backpack:[backbag]" + dat += "Jumpsuit: [jumpsuit_style] " + if((HAS_FLESH in pref_species.species_traits) || (HAS_BONE in pref_species.species_traits)) + dat += " Temporal Scarring: [(persistent_scars) ? "Enabled" : "Disabled"]" + dat += "Clear scar slots " + dat += "Uplink Location:[uplink_spawn_loc]" + dat += " | "
+
+ dat += ""
+ dat += "Lewd preferences" + dat += "Lust tolerance:[lust_tolerance]" + dat += "Sexual potency:[sexual_potency]" + dat += " | "
+
+ //SPLURT EDIT BEGIN - gregnancy preferences
+ dat += ""
+ dat += "Pregnancy preferences" + dat += "Chance of impregnation:[virility ? virility : "Disabled"]" + dat += "Chance of getting pregnant:[fertility ? fertility : "Disabled"]" + dat += "Lay inert eggs:[features["inert_eggs"] == TRUE ? "Enabled" : "Disabled"]" + if(fertility) + dat += "Pregnancy inflation:[pregnancy_inflation ? "Enabled" : "Disabled"]" + dat += "Pregnancy breast growth:[pregnancy_breast_growth ? "Enabled" : "Disabled"]" + if(fertility || features["inert_eggs"]) + dat += "Egg shell:[egg_shell]" + dat += " | "
+ //SPLURT EDIT END
+ dat += APPEARANCE_CATEGORY_COLUMN
+ if(NOGENITALS in pref_species.species_traits)
+ dat += "Your species ([pref_species.name]) does not support genitals!
"
+ dat += "Speech preferences" + dat += "Custom Speech Verb:" + dat += "[custom_speech_verb] " + dat += "Custom Tongue: " + dat += "[custom_tongue] " + //SANDSTORM EDIT - additional language + runechat color + dat += "Additional Language " + var/list/languages_sorted = sortList(language) + dat += "[language.len ? languages_sorted.Join(", ") : "None"] " + dat += "Custom runechat color: [enable_personal_chat_color ? "Enabled" : "Disabled"] [enable_personal_chat_color ? "[personal_chat_color] Change" : ""] " + dat += " | "
+ //END OF SANDSTORM EDIT
+ dat += ""
+ dat += "Vocal Bark preferences" + var/datum/bark/B = GLOB.bark_list[bark_id] + dat += "Vocal Bark Sound:" + dat += "[B ? initial(B.name) : "INVALID"] " + dat += "Vocal Bark Speed: [bark_speed] " + dat += "Vocal Bark Pitch: [bark_pitch] " + dat += "Vocal Bark Variance: [bark_variance] " + dat += " Preview Bark " + dat += " | "
+ dat += "
"
+ dat += "General Settings" + dat += "UI Style: [UI_style]" + dat += "Outline: [outline_enabled ? "Enabled" : "Disabled"] " + dat += "Outline Color: [outline_color ? "" : "Theme-based (null)"][outline_color] Change " + dat += "Screentip: [screentip_pref] " + dat += "Screentip Color: [screentip_color] Change " + dat += "tgui Monitors: [(tgui_lock) ? "Primary" : "All"] " + dat += "tgui Style: [(tgui_fancy) ? "Fancy" : "No Frills"] " + dat += "Input Framework: [(tgui_input_mode) ? "tgui" : "BYOND"] " + dat += "tgui Button Size: [(tgui_large_buttons) ? "Large" : "Small"] " + dat += "tgui Buttons Swapped: [(tgui_swapped_buttons) ? "Yes" : "No"] " + 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"] " + //SKYRAT CHANGES BEGIN + dat += "See Runechat for emotes: [see_chat_emotes ? "Enabled" : "Disabled"] " + //SKYRAT CHANGES END + dat += " " + dat += "Action Buttons: [(buttons_locked) ? "Locked In Place" : "Unlocked"] " + dat += " " + dat += "PDA Color: [pda_color] Change " + dat += "PDA Style: [pda_style] " + dat += "PDA Reskin: [pda_skin] " + dat += " " + dat += "Ghost Ears: [(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"] " + dat += "Ghost Radio: [(chat_toggles & CHAT_GHOSTRADIO) ? "All Messages":"No Messages"] " + dat += "Ghost Sight: [(chat_toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"] " + dat += "Ghost Whispers: [(chat_toggles & CHAT_GHOSTWHISPER) ? "All Speech" : "Nearest Creatures"] " + dat += "Ghost PDA: [(chat_toggles & CHAT_GHOSTPDA) ? "All Messages" : "Nearest Creatures"] " + dat += "Window Flashing: [(windowflashing) ? "Enabled":"Disabled"] " + dat += " " + dat += "Play Admin MIDIs: [(toggles & SOUND_MIDI) ? "Enabled":"Disabled"] " + dat += "Play Lobby Music: [(toggles & SOUND_LOBBY) ? "Enabled":"Disabled"] " + dat += "See Pull Requests: [(chat_toggles & CHAT_PULLR) ? "Enabled":"Disabled"] " + dat += " " + if(user.client) + if(unlock_content) + dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"] " + if(unlock_content || check_rights_for(user.client, R_ADMIN)) + dat += "OOC Color: [ooccolor ? ooccolor : GLOB.normal_ooc_colour] Change " + dat += "Antag OOC Color: [aooccolor ? aooccolor : GLOB.normal_aooc_colour] Change " + + dat += " | "
+
+ dat += ""
+
+ dat += "Special Role Settings" + + if(jobban_isbanned(user, ROLE_SYNDICATE)) + dat += "You are banned from antagonist roles." + src.be_special = list() + + dat += "DISABLE ALL ANTAGONISM [(toggles & NO_ANTAG) ? "YES" : "NO"]" + + for (var/i in GLOB.special_roles) + if(jobban_isbanned(user, i)) + dat += "Be [capitalize(i)]: BANNED " + else + var/days_remaining = null + if(ispath(GLOB.special_roles[i]) && CONFIG_GET(flag/use_age_restriction_for_jobs)) //If it's a game mode antag, check if the player meets the minimum age + var/mode_path = GLOB.special_roles[i] + var/datum/game_mode/temp_mode = new mode_path + days_remaining = temp_mode.get_remaining_days(user.client) + + if(days_remaining) + dat += "Be [capitalize(i)]: \[IN [days_remaining] DAYS] " + else + var/enabled_text = "" + if(i in be_special) + if(be_special[i] >= 1) + enabled_text = "Enabled" + else + enabled_text = "Low" + else + enabled_text = "Disabled" + dat += "Be [capitalize(i)]: [enabled_text] " + dat += "Midround Antagonist: [(toggles & MIDROUND_ANTAG) ? "Enabled" : "Disabled"] " + + dat += " " + + dat += " | "
+
+ if(user.client.holder) // sandstorm start - moves admin prefs to the right
+ dat += "Admin Settings" + dat += "Adminhelp Sounds: [(toggles & SOUND_ADMINHELP)?"Enabled":"Disabled"]" + dat += "Announce Login: [(toggles & ANNOUNCE_LOGIN)?"Enabled":"Disabled"] " + dat += " " + dat += "Combo HUD Lighting: [(toggles & COMBOHUD_LIGHTING)?"Full-bright":"No Change"] " + dat += "Use Modern Player Panel: [use_new_playerpanel ? "Yes" : "No"] " // sandstorm end - moves admins prefs to the right + + //deadmin + dat += " Deadmin While Playing" + if(CONFIG_GET(flag/auto_deadmin_players)) + dat += "Always Deadmin: FORCED" + else + dat += "Always Deadmin: [(deadmin & DEADMIN_ALWAYS)?"Enabled":"Disabled"] " + if(!(deadmin & DEADMIN_ALWAYS)) + dat += " " + if(!CONFIG_GET(flag/auto_deadmin_antagonists)) + dat += "As Antag: [(deadmin & DEADMIN_ANTAGONIST)?"Deadmin":"Keep Admin"] " + else + dat += "As Antag: FORCED " + + if(!CONFIG_GET(flag/auto_deadmin_heads)) + dat += "As Command: [(deadmin & DEADMIN_POSITION_HEAD)?"Deadmin":"Keep Admin"] " + else + dat += "As Command: FORCED " + + if(!CONFIG_GET(flag/auto_deadmin_security)) + dat += "As Security: [(deadmin & DEADMIN_POSITION_SECURITY)?"Deadmin":"Keep Admin"] " + else + dat += "As Security: FORCED " + + if(!CONFIG_GET(flag/auto_deadmin_silicons)) + dat += "As Silicon: [(deadmin & DEADMIN_POSITION_SILICON)?"Deadmin":"Keep Admin"] " + else + dat += "As Silicon: FORCED " + + dat += " Citadel Preferences" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe. + dat += "Widescreen: [widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"]" + dat += "Long strip menu: [long_strip_menu ? "Enabled" : "Disabled"] " + dat += "Auto stand: [autostand ? "Enabled" : "Disabled"] " + dat += "Auto OOC: [auto_ooc ? "Enabled" : "Disabled"] " + dat += "Force Slot Storage HUD: [no_tetris_storage ? "Enabled" : "Disabled"] " + dat += "Screen Shake: [(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")] " + if (user && user.client && !user.client.prefs.screenshake==0) + dat += "Damage Screen Shake: [(damagescreenshake==1) ? "On" : ((damagescreenshake==0) ? "Off" : "Only when down")] " + dat += "Recoil Screen Push: [(recoil_screenshake==100) ? "Full" : ((recoil_screenshake==0) ? "None" : "[screenshake]")] " + var/p_chaos + if (!preferred_chaos) + p_chaos = "No preference" + else + p_chaos = preferred_chaos + dat += "Preferred Chaos Amount: [p_chaos] " + + dat += " S.P.L.U.R.T. Preferences" + dat += "Be Antagonist Victim: [be_victim ? be_victim : BEVICTIM_ASK]" + dat += "Disable combat mode cursor: [disable_combat_cursor?"Yes":"No"] " + dat += "Splashscreen Player Panel Style: [(toggles & TG_PLAYER_PANEL)?"TG":"Old"] " + dat += "Character Creation Menu Style: [new_character_creator ? "New" : "Old"] " + dat += " " + + dat += " | "
+ dat += "
| Name | " + dat += "Cost | " + dat += "Restrictions | " + dat += "Description |
| [name][extra_loadout_data] | " + dat += "[gear.cost] | " + if(islist(gear.restricted_roles)) + if(gear.restricted_roles.len) + if(gear.restricted_desc) + dat += "" + dat += gear.restricted_desc + dat += "" + else + dat += "" + dat += gear.restricted_roles.Join(";") + dat += "" + if(!istype(gear, /datum/gear/unlockable)) + // the below line essentially means "if the loadout item is picked by the user and has a custom description, give it the custom description, otherwise give it the default description" + dat += " | [loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] | [loadout_item ? (loadout_item[LOADOUT_CUSTOM_DESCRIPTION] ? loadout_item[LOADOUT_CUSTOM_DESCRIPTION] : gear.description) : gear.description] Progress: [min(progress_made, unlockable.progress_required)]/[unlockable.progress_required] | " + + dat += "
"
+ dat += "Fetish content prefs" + dat += "Allow Lewd Verbs: [(toggles & VERB_CONSENT) ? "Yes":"No"]" // Skyrat - ERP Mechanic Addition + dat += "Mute Lewd Verb Sounds: [(toggles & LEWD_VERB_SOUNDS) ? "Yes":"No"] " // Skyrat - ERP Mechanic Addition + dat += "Arousal:[arousable == TRUE ? "Enabled" : "Disabled"] " + dat += "Genital examine text:[(cit_toggles & GENITAL_EXAMINE) ? "Enabled" : "Disabled"] " + dat += "Vore examine text:[(cit_toggles & VORE_EXAMINE) ? "Enabled" : "Disabled"] " + dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"] " + dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"] " + dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"] " + dat += "Allow trash forcefeeding (requires Trashcan quirk) [(cit_toggles & TRASH_FORCEFEED) ? "Yes" : "No"] " + dat += "Forced Feminization: [(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"] " + dat += "Forced Masculinization: [(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"] " + dat += "Lewd Hypno: [(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"] " + dat += "Bimbofication: [(cit_toggles & BIMBOFICATION) ? "Allowed" : "Disallowed"] " + dat += " | "
+ dat +=""
+ dat += "Other content prefs" + dat += "Breast Enlargement: [(cit_toggles & BREAST_ENLARGEMENT) ? "Allowed" : "Disallowed"]" + dat += "Penis Enlargement: [(cit_toggles & PENIS_ENLARGEMENT) ? "Allowed" : "Disallowed"] " + dat += "Butt Enlargement: [(cit_toggles & BUTT_ENLARGEMENT) ? "Allowed" : "Disallowed"] " + dat += "Belly Inflation: [(cit_toggles & BELLY_INFLATION) ? "Allowed" : "Disallowed"] " + dat += "Hypno: [(cit_toggles & NEVER_HYPNO) ? "Disallowed" : "Allowed"] " + dat += "Aphrodisiacs: [(cit_toggles & NO_APHRO) ? "Disallowed" : "Allowed"] " + dat += "Ass Slapping: [(cit_toggles & NO_ASS_SLAP) ? "Disallowed" : "Allowed"] " + //SPLURT EDIT + dat += "? " + dat += "Unholy ERP verbs : [unholypref] " //https://www.youtube.com/watch?v=OHKARc-GObU + //END OF SPLURT EDIT + //SKYRAT EDIT + dat += "? " + dat += "Extreme ERP verbs : [extremepref] " // https://youtu.be/0YrU9ASVw6w + if(extremepref != "No") + dat += "? " + dat += "Harmful ERP verbs : [extremeharm] " + //END OF SKYRAT EDIT + dat += "Automatic Wagging: [(cit_toggles & NO_AUTO_WAG) ? "Disabled" : "Enabled"] " + dat += "? " + dat += "Genital Fluid Blacklist " + if(gfluid_blacklist?.len) + dat += "? " + dat += "Genital Fluid Un-Blacklist " + dat += " |
7X6=UoO^&VEalqSymksZGFucLjgFfIp(t?3s_uvM@AT@T=fF`;C0000< KMNUMnLSTZN<-%D2 literal 0 HcmV?d00001 diff --git a/icons/UI_Icons/screentips/cursor_hints_outline.dmi b/icons/UI_Icons/screentips/cursor_hints_outline.dmi new file mode 100644 index 0000000000000000000000000000000000000000..32e0b8f67cd949ff155bd2e4d8d91e387b57e1d3 GIT binary patch literal 490 zcmVh(O0RI30z`($+MRoW90004WQchC V=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#atzJ5I5Sc+ z(=$pSoZ^zil2jm5DJds0FI$O=GbOXA7$n8TnO2mTn+jpWRr&Zj=_ck?5~VI9HK%|m zg(;cEiAA|YDNQd*Od`&5VoVGo(l Kiix Date: Sun, 19 Feb 2023 07:03:06 +0000 Subject: [PATCH 17/61] Cryptominer account setting tweaks (#304) This commit makes changes to how cryptominers handle changing accounts. The following is changed: - Added interaction time for linking new account - Added more text balloons - Added fail messages for linking and resetting - Added radio notice when linking a standard cryptominer - Added more visible chat messages - Added interaction logging - - Only displays if the previous account was Cargo - Updated descriptions for standard and Syndicate cryptominer - Update description to only display added information while in range --- .../code/game/machinery/cryptominers.dm | 131 +++++++++++++++--- 1 file changed, 110 insertions(+), 21 deletions(-) diff --git a/modular_sand/code/game/machinery/cryptominers.dm b/modular_sand/code/game/machinery/cryptominers.dm index 6738511b4f..20f5bd69b4 100644 --- a/modular_sand/code/game/machinery/cryptominers.dm +++ b/modular_sand/code/game/machinery/cryptominers.dm @@ -19,7 +19,7 @@ /obj/machinery/cryptominer name = "cryptocurrency miner" - desc = "This handy-dandy machine will produce credits for your enjoyment." + desc = "This handy-dandy machine will produce credits for Cargo's enjoyment." icon = 'modular_sand/icons/obj/machines/cryptominer.dmi' icon_state = "off" density = TRUE @@ -32,9 +32,23 @@ var/miningtime = 3000 var/miningpoints = 50 var/datum/bank_account/pay_me = null + var/obj/item/radio/cargo_radio + // Should this machine send messages on cargo radio? + var/radio_snitch = TRUE /obj/machinery/cryptominer/Initialize(mapload) . = ..() + + // Create new radio + cargo_radio = new /obj/item/radio(src) + + // Prevent radio listening + cargo_radio.listening = 0 + + // Set radio frequency + cargo_radio.set_frequency(FREQ_SUPPLY) + + // Set default account pay_me = SSeconomy.get_dep_account(ACCOUNT_CAR) /obj/machinery/cryptominer/update_icon() @@ -48,6 +62,7 @@ /obj/machinery/cryptominer/Destroy() STOP_PROCESSING(SSmachines,src) + QDEL_NULL(cargo_radio) return ..() /obj/machinery/cryptominer/deconstruct() @@ -61,35 +76,107 @@ return if(default_unfasten_wrench(user, W)) return + + // Check if disabled + // Check if panel is open + // Check if user is in HELP intent if(!mining && panel_open && user.a_intent == INTENT_HELP) + // Attempt to locate user's ID var/id_card = W.GetID() - if(id_card) - var/obj/item/card/id/CARD = id_card - if(CARD.bank_support != ID_FREE_BANK_ACCOUNT) - to_chat(user, span_warning("This ID has no banking support whatsover, must be an older model...")) - return - if(!CARD.registered_account) - to_chat(user, span_warning("ERROR: No bank account found.")) - return - to_chat(user, span_notice("You link \the [CARD] to \the [src].")) - pay_me = CARD.registered_account - say("Now using [pay_me.account_holder ? "[pay_me.account_holder]s" : span_boldwarning("ERROR")] account.") + + // Check if ID exists + if(!id_card) return + // Define ID card + var/obj/item/card/id/CARD = id_card + + // Check if ID card has banking support + if(CARD.bank_support != ID_FREE_BANK_ACCOUNT) + // Warn in local chat and return + say("ERROR: No banking support found on provided ID card.") + return + + // Check if ID card has a linked account + if(!CARD.registered_account) + // Warn in local chat and return + say("ERROR: No bank account found on provided ID card.") + return + + // Display message in local chat + user.visible_message(span_notice("[user] begins setting \the [src] to use \the [CARD]."), span_notice("[user] begins setting \the [src] to use \the [CARD].")) + + // Display alert balloon + balloon_alert(user, "Configuring new account...") + + // Perform interaction timer + if(!do_after(user, 5 SECONDS, target = src)) + // Warn in local chat + user.visible_message(span_warning("[user] fails to link \the [src] to a new account!"), span_warning("You fail to link \the [src] to a new account!")) + + // Display alert balloon + balloon_alert(user, "Configuration failed!") + + // Return with no further effects + return + + // Alert user of linking success + to_chat(user, span_notice("You link \the [CARD] to \the [src].")) + + // Define previous account + var/old_account = pay_me + + // Set payment account to ID card's account + pay_me = CARD.registered_account + + // Say in local chat + say("Now using [pay_me.account_holder ? "[pay_me.account_holder]s" : span_boldwarning("ERROR")] account.") + + // Log interaction + log_game("[user] set \the [src] in [get_area(src)] to pay into their personal account. Previous account was [old_account].") + + // Check if old account was cargo + // Check if this machine should report over radio + if(radio_snitch && (old_account == SSeconomy.get_dep_account(ACCOUNT_CAR))) + // Send radio notice + cargo_radio.talk_into(src, "CRYPTO ALERT: Crew member [user] has set \the [src] in [get_area(src)] to use [pay_me.account_holder]\'s account, instead of Cargo!", FREQ_SUPPLY) + /obj/machinery/cryptominer/AltClick(mob/user) - user.visible_message(span_warning("[user] begins resetting \the [src]."), - span_warning("You begin resetting \the [src].")) - balloon_alert(user, "resetting") - if(do_after(user, 5 SECONDS, target = src)) - pay_me = SSeconomy.get_dep_account(ACCOUNT_CAR) - say("Now using [pay_me.account_holder]s account.") + // Alert user in chat + user.visible_message(span_warning("[user] begins resetting \the [src]."), span_warning("You begin resetting \the [src].")) + + // Display alert balloon + balloon_alert(user, "Resetting account...") + + // Perform interaction timer + if(!do_after(user, 5 SECONDS, target = src)) + // Warn in local chat + user.visible_message(span_warning("[user] fails to reset \the [src]."), span_warning("You fail to reset \the [src].")) + + // Display alert balloon + balloon_alert(user, "Reset failed!") + + // Return with no further effects + return + + // Define previous account + var/old_account = pay_me + + // Reset account to Cargo + pay_me = SSeconomy.get_dep_account(ACCOUNT_CAR) + + // Say in local chat + say("Now using [pay_me.account_holder]s account.") + + // Log interaction + log_game("[user] reset the \the [src] in [get_area(src)] to pay Cargo's departmental account. Previous account was [old_account]") /obj/machinery/cryptominer/examine(mob/user) . = ..() if(in_range(user, src) || isobserver(user)) . += span_notice("A little screen on the machine reads: Currently the linked bank account is [pay_me.account_holder ? "[pay_me.account_holder]s" : span_boldwarning("ERROR")].") - . += "Modify the destination of the credits using your id on it while it is inactive and has its panel open." - . += "Alt-Click to reset to the Cargo budget." + . += "Modify the destination of the credits using your id on it while it is inactive and has its panel open." + . += "Alt-Click to reset to the Cargo budget." /obj/machinery/cryptominer/process() // Get turf @@ -190,7 +277,7 @@ /obj/machinery/cryptominer/syndie name = "syndicate cryptocurrency miner" - desc = "This handy-dandy machine will produce credits for your enjoyment. It lasts a little longer." + desc = "This handy-dandy machine will produce credits for your own personal enjoyment. This one won't snitch on you to Cargo." icon_state = "off_syndie" density = TRUE use_power = IDLE_POWER_USE @@ -199,6 +286,7 @@ circuit = /obj/item/circuitboard/machine/cryptominer/syndie miningtime = 6000 miningpoints = 100 + radio_snitch = FALSE // Illegal tech! /obj/machinery/cryptominer/syndie/update_icon() . = ..() @@ -219,6 +307,7 @@ active_power_usage = 1 miningtime = 600000 miningpoints = 1000 + radio_snitch = FALSE // None of cargo's business! /obj/machinery/cryptominer/nanotrasen/update_icon() . = ..() From b178ee0e0825efa82325295c6a7e9dbdf7b2090f Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Sun, 19 Feb 2023 07:03:59 +0000 Subject: [PATCH 18/61] Automatic changelog generation for PR #304 [ci skip] --- html/changelogs/AutoChangeLog-pr-304.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-304.yml diff --git a/html/changelogs/AutoChangeLog-pr-304.yml b/html/changelogs/AutoChangeLog-pr-304.yml new file mode 100644 index 0000000000..fbd70ebe0f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-304.yml @@ -0,0 +1,7 @@ +author: LeDrascol +delete-after: true +changes: + - rscadd: Added more feedback messages to Cryptominer account changing + - tweak: Standard cryptominers will report account changes on Cargo radio + - balance: Setting a cryptominer's account now takes five seconds + - admin: Added game logging for Cryptominer account changes From 945c31fd70052319df12c6ec513ff949fcced370 Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Sun, 19 Feb 2023 07:05:03 +0000 Subject: [PATCH 19/61] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-304.yml | 7 ------- html/changelogs/archive/2023-02.yml | 4 ++++ 2 files changed, 4 insertions(+), 7 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-304.yml diff --git a/html/changelogs/AutoChangeLog-pr-304.yml b/html/changelogs/AutoChangeLog-pr-304.yml deleted file mode 100644 index fbd70ebe0f..0000000000 --- a/html/changelogs/AutoChangeLog-pr-304.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: LeDrascol -delete-after: true -changes: - - rscadd: Added more feedback messages to Cryptominer account changing - - tweak: Standard cryptominers will report account changes on Cargo radio - - balance: Setting a cryptominer's account now takes five seconds - - admin: Added game logging for Cryptominer account changes diff --git a/html/changelogs/archive/2023-02.yml b/html/changelogs/archive/2023-02.yml index 8f554dce73..f6ecf6c9f0 100644 --- a/html/changelogs/archive/2023-02.yml +++ b/html/changelogs/archive/2023-02.yml @@ -20,3 +20,7 @@ 2023-02-19: LeDrascol: - bugfix: Fixed techweb exploit with 357 speed loader + - rscadd: Added more feedback messages to Cryptominer account changing + - tweak: Standard cryptominers will report account changes on Cargo radio + - balance: Setting a cryptominer's account now takes five seconds + - admin: Added game logging for Cryptominer account changes From 2aad51d60bf80fd17ef6d4a662771425183e1fc0 Mon Sep 17 00:00:00 2001 From: SandPoot <43283559+SandPoot@users.noreply.github.com> Date: Sun, 19 Feb 2023 14:55:14 -0300 Subject: [PATCH 20/61] [HURRY-UP] Screentips context help now have advanced, fancy icons (with a way to disable it for only text) (#307) * new icon with adjustments for it * lizard content --- code/__DEFINES/screentips.dm | 2 +- code/__HELPERS/screentips.dm | 41 ++++++++++---------- code/game/atoms.dm | 25 ++++++------ code/modules/client/preferences.dm | 6 +++ code/modules/client/preferences_savefile.dm | 2 + icons/UI_Icons/screentips/cursor_hints.dmi | Bin 0 -> 414 bytes icons/UI_Icons/screentips/full_mouse.dmi | Bin 0 -> 490 bytes 7 files changed, 42 insertions(+), 34 deletions(-) create mode 100644 icons/UI_Icons/screentips/cursor_hints.dmi create mode 100644 icons/UI_Icons/screentips/full_mouse.dmi diff --git a/code/__DEFINES/screentips.dm b/code/__DEFINES/screentips.dm index a3b1018352..4918db85ce 100644 --- a/code/__DEFINES/screentips.dm +++ b/code/__DEFINES/screentips.dm @@ -32,4 +32,4 @@ #define SCREENTIP_PREFERENCE_CONTEXT_ONLY "Only with tips" /// Regardless of intent -#define INTENT_ANY "intent_any" +#define INTENT_ANY "any" diff --git a/code/__HELPERS/screentips.dm b/code/__HELPERS/screentips.dm index 967e1c3bb6..dfd3390ab4 100644 --- a/code/__HELPERS/screentips.dm +++ b/code/__HELPERS/screentips.dm @@ -1,31 +1,30 @@ +#define HINT_ICON_FILE 'icons/UI_Icons/screentips/cursor_hints.dmi' + // Generate intent icons -/// Help intent icon for screentip context -GLOBAL_DATUM_INIT(icon_intent_help, /image, image('icons/emoji.dmi', icon_state = INTENT_HELP)) -/// Disarm intent icon for screentip context -GLOBAL_DATUM_INIT(icon_intent_disarm, /image, image('icons/emoji.dmi', icon_state = INTENT_DISARM)) -/// Grab intent icon for screentip context -GLOBAL_DATUM_INIT(icon_intent_grab, /image, image('icons/emoji.dmi', icon_state = INTENT_GRAB)) -/// Harm intent icon for screentip context -GLOBAL_DATUM_INIT(icon_intent_harm, /image, image('icons/emoji.dmi', icon_state = INTENT_HARM)) +GLOBAL_LIST_INIT_TYPED(screentip_context_icons, /image, prepare_screentip_context_icons()) + +/proc/prepare_screentip_context_icons() + . = list() + for(var/state in icon_states(HINT_ICON_FILE)) + .[state] = image(HINT_ICON_FILE, icon_state = state) /* * # Builds context with each intent for this key * Args: * - context = list (REQUIRED) * - key = string (REQUIRED) + * - allow_image = boolean (not required) */ -/proc/build_context(list/context, key) +/proc/build_context(list/context, key, allow_image) var/list/to_add for(var/intent in context[key]) - switch(intent) - if(INTENT_HELP) - LAZYADD(to_add, "\icon[GLOB.icon_intent_help] [key]: [context[key][INTENT_HELP]]") - if(INTENT_DISARM) - LAZYADD(to_add, "\icon[GLOB.icon_intent_disarm] [key]: [context[key][INTENT_DISARM]]") - if(INTENT_GRAB) - LAZYADD(to_add, "\icon[GLOB.icon_intent_grab] [key]: [context[key][INTENT_GRAB]]") - if(INTENT_HARM) - LAZYADD(to_add, "\icon[GLOB.icon_intent_harm] [key]: [context[key][INTENT_HARM]]") - else // If you're adding intent-less YOU BETTER ADD IT FIRST IN THE LIST - LAZYADD(to_add, "[key]: [context[key][intent]]") - return english_list(to_add, "", " ", " ") + var/key_help = "[length(key) > 3 ? copytext(key, 1, -3) : ""]" + var/icon = "[copytext(key, -3)]-[intent]" + if(allow_image) + icon = "\icon[GLOB.screentip_context_icons[icon]]" + LAZYADD(to_add, "[key_help][icon]: [context[key][intent]]") + + var/separator = "[allow_image ? " " : " | "]" + return english_list(to_add, "", separator, separator) + +#undef HINT_ICON_FILE diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 0b0843c67e..03338e9eaa 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1486,6 +1486,7 @@ if (isliving(user) || isovermind(user) || isaicamera(user)) var/obj/item/held_item = user.get_active_held_item() + var/allow_images = user.client.prefs.screentip_allow_images if (flags_1 & HAS_CONTEXTUAL_SCREENTIPS_1 || held_item?.item_flags & ITEM_HAS_CONTEXTUAL_SCREENTIPS) var/list/context = list() @@ -1498,15 +1499,15 @@ // LMB and RMB on one line... var/lmb_text = "" if((SCREENTIP_CONTEXT_LMB in context) && (length(context[SCREENTIP_CONTEXT_LMB]) > 0)) - lmb_text = build_context(context, SCREENTIP_CONTEXT_LMB) + lmb_text = build_context(context, SCREENTIP_CONTEXT_LMB, allow_images) var/rmb_text = "" if((SCREENTIP_CONTEXT_RMB in context) && (length(context[SCREENTIP_CONTEXT_RMB]) > 0)) - rmb_text = build_context(context, SCREENTIP_CONTEXT_RMB) + rmb_text = build_context(context, SCREENTIP_CONTEXT_RMB, allow_images) if (lmb_text) lmb_rmb_line = lmb_text if (rmb_text) - lmb_rmb_line += " | [rmb_text]" + lmb_rmb_line += " | [allow_images ? " " : ""][rmb_text]" else if (rmb_text) lmb_rmb_line = rmb_text @@ -1515,37 +1516,37 @@ lmb_rmb_line += "
" extra_lines++ if((SCREENTIP_CONTEXT_CTRL_LMB in context) && (length(context[SCREENTIP_CONTEXT_CTRL_LMB]) > 0)) - ctrl_lmb_ctrl_rmb_line = build_context(context, SCREENTIP_CONTEXT_CTRL_LMB) + ctrl_lmb_ctrl_rmb_line = build_context(context, SCREENTIP_CONTEXT_CTRL_LMB, allow_images) if((SCREENTIP_CONTEXT_CTRL_RMB in context) && (length(context[SCREENTIP_CONTEXT_CTRL_RMB]) > 0)) if (ctrl_lmb_ctrl_rmb_line != "") - ctrl_lmb_ctrl_rmb_line += " | " + ctrl_lmb_ctrl_rmb_line += " | [allow_images ? " " : ""]" ctrl_lmb_ctrl_rmb_line += "[SCREENTIP_CONTEXT_CTRL_RMB]: [context[SCREENTIP_CONTEXT_CTRL_RMB]]" - ctrl_lmb_ctrl_rmb_line = build_context(context, SCREENTIP_CONTEXT_CTRL_RMB) + ctrl_lmb_ctrl_rmb_line = build_context(context, SCREENTIP_CONTEXT_CTRL_RMB, allow_images) // Alt-LMB, Alt-RMB on one line... if (ctrl_lmb_ctrl_rmb_line != "") ctrl_lmb_ctrl_rmb_line += "
" extra_lines++ if((SCREENTIP_CONTEXT_ALT_LMB in context) && (length(context[SCREENTIP_CONTEXT_ALT_LMB]) > 0)) - alt_lmb_alt_rmb_line = build_context(context, SCREENTIP_CONTEXT_ALT_LMB) + alt_lmb_alt_rmb_line = build_context(context, SCREENTIP_CONTEXT_ALT_LMB, allow_images) if((SCREENTIP_CONTEXT_ALT_RMB in context) && (length(context[SCREENTIP_CONTEXT_ALT_RMB]) > 0)) if (alt_lmb_alt_rmb_line != "") - alt_lmb_alt_rmb_line += " | " - alt_lmb_alt_rmb_line = build_context(context, SCREENTIP_CONTEXT_ALT_RMB) + alt_lmb_alt_rmb_line += " | [allow_images ? " " : ""]" + alt_lmb_alt_rmb_line = build_context(context, SCREENTIP_CONTEXT_ALT_RMB, allow_images) // Shift-LMB, Ctrl-Shift-LMB on one line... if (alt_lmb_alt_rmb_line != "") alt_lmb_alt_rmb_line += "
" extra_lines++ if((SCREENTIP_CONTEXT_SHIFT_LMB in context) && (length(context[SCREENTIP_CONTEXT_SHIFT_LMB]) > 0)) - shift_lmb_ctrl_shift_lmb_line = build_context(context, SCREENTIP_CONTEXT_SHIFT_LMB) + shift_lmb_ctrl_shift_lmb_line = build_context(context, SCREENTIP_CONTEXT_SHIFT_LMB, allow_images) if((SCREENTIP_CONTEXT_CTRL_SHIFT_LMB in context) && (length(context[SCREENTIP_CONTEXT_CTRL_SHIFT_LMB]) > 0)) if (shift_lmb_ctrl_shift_lmb_line != "") - shift_lmb_ctrl_shift_lmb_line += " | " + shift_lmb_ctrl_shift_lmb_line += " | [allow_images ? " " : ""]" shift_lmb_ctrl_shift_lmb_line += "[SCREENTIP_CONTEXT_CTRL_SHIFT_LMB]: [context[SCREENTIP_CONTEXT_CTRL_SHIFT_LMB]]" - shift_lmb_ctrl_shift_lmb_line = build_context(context, SCREENTIP_CONTEXT_CTRL_SHIFT_LMB) + shift_lmb_ctrl_shift_lmb_line = build_context(context, SCREENTIP_CONTEXT_CTRL_SHIFT_LMB, allow_images) if (shift_lmb_ctrl_shift_lmb_line != "") extra_lines++ diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 2a63aa0384..31a066830d 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -64,6 +64,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/outline_color = COLOR_THEME_MIDNIGHT var/screentip_pref = SCREENTIP_PREFERENCE_ENABLED var/screentip_color = "#ffd391" + var/screentip_allow_images = FALSE var/buttons_locked = FALSE var/hotkeys = FALSE @@ -1048,6 +1049,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Outline Color: [outline_color ? "" : "Theme-based (null)"][outline_color] Change
" dat += "Screentip: [screentip_pref]
" dat += "Screentip Color: [screentip_color] Change
" + dat += "\ + Screentip context with images: [screentip_allow_images ? "Allowed" : "Disallowed"]
" 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"]
" @@ -3132,6 +3136,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/pickedScreentipColor = input(user, "Choose your screentip color.", "General Preference", screentip_color) as color|null if(pickedScreentipColor) screentip_color = pickedScreentipColor + if("screentip_allow_images") + screentip_allow_images = !screentip_allow_images if("tgui_lock") tgui_lock = !tgui_lock if("winflash") diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 6d42fd3441..c499fc764f 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -423,6 +423,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["outline_enabled"] >> outline_enabled S["screentip_pref"] >> screentip_pref S["screentip_color"] >> screentip_color + S["screentip_allow_images"] >> screentip_allow_images S["hotkeys"] >> hotkeys S["chat_on_map"] >> chat_on_map S["max_chat_length"] >> max_chat_length @@ -618,6 +619,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["outline_color"], outline_color) WRITE_FILE(S["screentip_pref"], screentip_pref) WRITE_FILE(S["screentip_color"], screentip_color) + WRITE_FILE(S["screentip_allow_images"], screentip_allow_images) WRITE_FILE(S["hotkeys"], hotkeys) WRITE_FILE(S["chat_on_map"], chat_on_map) WRITE_FILE(S["max_chat_length"], max_chat_length) diff --git a/icons/UI_Icons/screentips/cursor_hints.dmi b/icons/UI_Icons/screentips/cursor_hints.dmi new file mode 100644 index 0000000000000000000000000000000000000000..9533d240a59921308927ac79c7eaad268af32cd8 GIT binary patch literal 414 zcmV;P0b%}$P)h(O0RI30z`($Zm&CdN0004WQchC V=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#axAzwGg33t zGfIGLQ?BBY#FA7XODQQQF)v$*i!&v&s2IpM ^u;i2e}pLFCGWEG0O b%707*qo IM6N<$f;P0R%K!iX literal 0 HcmV?d00001 diff --git a/icons/UI_Icons/screentips/full_mouse.dmi b/icons/UI_Icons/screentips/full_mouse.dmi new file mode 100644 index 0000000000000000000000000000000000000000..32e0b8f67cd949ff155bd2e4d8d91e387b57e1d3 GIT binary patch literal 490 zcmV h(O0RI30z`($+MRoW90004WQchC V=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#atzJ5I5Sc+ z(=$pSoZ^zil2jm5DJds0FI$O=GbOXA7$n8TnO2mTn+jpWRr&Zj=_ck?5~VI9HK%|m zg(;cEiAA|YDNQd*Od`&5VoVGo(l Kiix Date: Sun, 19 Feb 2023 17:56:06 +0000 Subject: [PATCH 21/61] Automatic changelog generation for PR #307 [ci skip] --- html/changelogs/AutoChangeLog-pr-307.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-307.yml diff --git a/html/changelogs/AutoChangeLog-pr-307.yml b/html/changelogs/AutoChangeLog-pr-307.yml new file mode 100644 index 0000000000..057e548a54 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-307.yml @@ -0,0 +1,5 @@ +author: SandPoot +delete-after: true +changes: + - imageadd: Changed screentips icons to something a lot fancier unified with the + LMB / RMB text. From 50600f6b0e24792a518af374bdcb2438a197cbd1 Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Sun, 19 Feb 2023 17:57:03 +0000 Subject: [PATCH 22/61] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-307.yml | 5 ----- html/changelogs/archive/2023-02.yml | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-307.yml diff --git a/html/changelogs/AutoChangeLog-pr-307.yml b/html/changelogs/AutoChangeLog-pr-307.yml deleted file mode 100644 index 057e548a54..0000000000 --- a/html/changelogs/AutoChangeLog-pr-307.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: SandPoot -delete-after: true -changes: - - imageadd: Changed screentips icons to something a lot fancier unified with the - LMB / RMB text. diff --git a/html/changelogs/archive/2023-02.yml b/html/changelogs/archive/2023-02.yml index f6ecf6c9f0..e64467bd6a 100644 --- a/html/changelogs/archive/2023-02.yml +++ b/html/changelogs/archive/2023-02.yml @@ -24,3 +24,6 @@ - tweak: Standard cryptominers will report account changes on Cargo radio - balance: Setting a cryptominer's account now takes five seconds - admin: Added game logging for Cryptominer account changes + SandPoot: + - imageadd: Changed screentips icons to something a lot fancier unified with the + LMB / RMB text. From 50e0ed8105ef172e1fd9a49c3a1a8f459cbf1d6f Mon Sep 17 00:00:00 2001 From: Darius <5933805+LeDrascol@users.noreply.github.com> Date: Sun, 19 Feb 2023 18:05:44 +0000 Subject: [PATCH 23/61] Job Restricted Protolathes (#303) * Block protolathe use without job access Prevents opening the UI for any R&D production machinery without proper job access on the mob's mind. This change impacts protolathes and circuit imprinters. * Check protolathe access using face and ID Changes the protolathe access check to use ID card or face name, instead of mind. * Always allow Captain protolathe use Allows the captain to use any protolathe or circuit imprinter. * Check protolathe access using only ID Updates the RND production machine access checks to only use the ID card, instead of checking face or security records. * Lock RND console by default Sets the R&D console locked variable to TRUE by default to prevent unauthorized access exploits. * Use req_access for RND production machines Converts the ID check used by RND production machines to use req_access flags. * Check Topic for protolathe restrictions Moves protolathe access checks into a mob proc, and checks Topic call the same way UI open is checked. * Production restriction low-population improvements This commit fixes potential problems for low-population servers using production machinery restrictions. The following changes are made: - Allow skeleton crew to ignore research machinery restrictions - Option to check all living crew IDs for access (disabled by default) - Configuration options for using global ID checks and skeleton crew access * Production machine locking feedback commit This commit makes changes requested by Sandpoot: - Renames 'nonmin' to 'lowpop' - Removes all global ID check code * Fix improper configuration defines Fixes an oversight that caused some variable names to not be updated. * Remove obsolete mob defines Removes the obsolete PROTOLOCK_CHECK_ALL_IDS define, which related to a removed feature. * Reverse protolock check ordering Reverses the configuration check order for PROTOLOCK_DURING_LOWPOP and JOB_MINIMAL_ACCESS at the request of SandPoot. Co-authored-by: SandPoot <43283559+SandPoot@users.noreply.github.com> --------- Co-authored-by: SandPoot <43283559+SandPoot@users.noreply.github.com> --- config/sandstorm/balance.txt | 8 ++++ .../entries/sandstorm_balance.dm | 4 ++ modular_sand/code/modules/mob/mob.dm | 45 +++++++++++++++++++ .../modules/research/machinery/_production.dm | 29 ++++++++++++ .../departmental_circuit_imprinter.dm | 2 + .../machinery/departmental_protolathe.dm | 17 +++++++ .../machinery/departmental_techfab.dm | 17 +++++++ .../code/modules/research/rdconsole.dm | 2 + tgstation.dme | 5 +++ 9 files changed, 129 insertions(+) create mode 100644 modular_sand/code/modules/research/machinery/_production.dm create mode 100644 modular_sand/code/modules/research/machinery/departmental_circuit_imprinter.dm create mode 100644 modular_sand/code/modules/research/machinery/departmental_protolathe.dm create mode 100644 modular_sand/code/modules/research/machinery/departmental_techfab.dm create mode 100644 modular_sand/code/modules/research/rdconsole.dm diff --git a/config/sandstorm/balance.txt b/config/sandstorm/balance.txt index bc10b7a471..9df8fcebd6 100644 --- a/config/sandstorm/balance.txt +++ b/config/sandstorm/balance.txt @@ -90,3 +90,11 @@ TETRIS_SCORE_MAX_SCI 10000 ## This applies to both prizes and research points ## Time is measured in ticks TETRIS_TIME_COOLDOWN 600 + +## +## PROTOLATHE RESTRICTIONS +### + +## Should production machinery be restricted for skeleton crews? +## Uncomment this to enable +#PROTOLOCK_DURING_LOWPOP diff --git a/modular_sand/code/controllers/configuration/entries/sandstorm_balance.dm b/modular_sand/code/controllers/configuration/entries/sandstorm_balance.dm index 8d738c425a..f181b9bffe 100644 --- a/modular_sand/code/controllers/configuration/entries/sandstorm_balance.dm +++ b/modular_sand/code/controllers/configuration/entries/sandstorm_balance.dm @@ -92,3 +92,7 @@ // Minimum time between giving rewards /datum/config_entry/number/tetris_time_cooldown config_entry_value = 600 + +/// R&D Machinery /// +// Should production machinery be restricted for skeleton crews? +/datum/config_entry/flag/protolock_during_lowpop diff --git a/modular_sand/code/modules/mob/mob.dm b/modular_sand/code/modules/mob/mob.dm index 7957645e54..ec6412f591 100644 --- a/modular_sand/code/modules/mob/mob.dm +++ b/modular_sand/code/modules/mob/mob.dm @@ -1,3 +1,7 @@ +// Configuration defines +#define JOB_MINIMAL_ACCESS CONFIG_GET(flag/jobs_have_minimal_access) +#define PROTOLOCK_DURING_LOWPOP CONFIG_GET(flag/protolock_during_lowpop) + // Only Clients should have a panel for them, okay? /mob/Login() . = ..() @@ -23,3 +27,44 @@ /mob/proc/set_thirst(change) thirst = max(0, change) + +/mob/proc/can_use_production(obj/machinery/rnd/production/machine_target) + // Check if server is NOT using minimal access + // This is intended for low populations + if((!PROTOLOCK_DURING_LOWPOP) && (!JOB_MINIMAL_ACCESS)) + // Allow unrestricted use + return TRUE + + // Define machine user + var/mob/living/carbon/human/machine_user = src + + // Check if user exists + if(!istype(machine_user)) + return TRUE + + // Define user ID card + var/obj/item/card/id/user_id = machine_user.get_idcard() + + // Check if ID card was found + if(!istype(user_id)) + // Warn in local chat, then return + machine_target.say("Access denied: Unable to scan user ID card.") + return FALSE + + // Check for Captain + if(ACCESS_CAPTAIN in user_id.access) + // Allow usage + return TRUE + + // Check if access requirements are met + if(machine_target.check_access(user_id)) + // Allow use + return TRUE + + // User does not have access + // Warn in local chat, then return + machine_target.say("Access denied: No valid departmental credentials detected.") + return FALSE + +#undef JOB_MINIMAL_ACCESS +#undef PROTOLOCK_DURING_LOWPOP diff --git a/modular_sand/code/modules/research/machinery/_production.dm b/modular_sand/code/modules/research/machinery/_production.dm new file mode 100644 index 0000000000..936840ad4a --- /dev/null +++ b/modular_sand/code/modules/research/machinery/_production.dm @@ -0,0 +1,29 @@ +/obj/machinery/rnd/production/Initialize(mapload) + . = ..() + + // Generate access lists + gen_access() + +/obj/machinery/rnd/production/ui_interact(mob/user) + // Check if access is required + if(!req_access) + return ..() + + // Check if user can use machine + if(!user.can_use_production(src)) + return + + // Return normally + . = ..() + +/obj/machinery/rnd/production/Topic(raw, ls) + // Check if access is required + if(!req_access) + return ..() + + // Check if user can use machine + if(!usr.can_use_production(src)) + return + + // Return normally + . = ..() diff --git a/modular_sand/code/modules/research/machinery/departmental_circuit_imprinter.dm b/modular_sand/code/modules/research/machinery/departmental_circuit_imprinter.dm new file mode 100644 index 0000000000..712ea33cda --- /dev/null +++ b/modular_sand/code/modules/research/machinery/departmental_circuit_imprinter.dm @@ -0,0 +1,2 @@ +/obj/machinery/rnd/production/circuit_imprinter/department/science + req_access = list(ACCESS_RESEARCH) diff --git a/modular_sand/code/modules/research/machinery/departmental_protolathe.dm b/modular_sand/code/modules/research/machinery/departmental_protolathe.dm new file mode 100644 index 0000000000..4904828374 --- /dev/null +++ b/modular_sand/code/modules/research/machinery/departmental_protolathe.dm @@ -0,0 +1,17 @@ +/obj/machinery/rnd/production/protolathe/department/engineering + req_access = list(ACCESS_ENGINE) + +/obj/machinery/rnd/production/protolathe/department/service + req_one_access = list(ACCESS_BAR, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_JANITOR) + +/obj/machinery/rnd/production/protolathe/department/medical + req_access = list(ACCESS_MEDICAL) + +/obj/machinery/rnd/production/protolathe/department/cargo + req_access = list(ACCESS_CARGO) + +/obj/machinery/rnd/production/protolathe/department/science + req_access = list(ACCESS_RESEARCH) + +/obj/machinery/rnd/production/protolathe/department/security + req_access = list(ACCESS_SECURITY) diff --git a/modular_sand/code/modules/research/machinery/departmental_techfab.dm b/modular_sand/code/modules/research/machinery/departmental_techfab.dm new file mode 100644 index 0000000000..7f9601ab3a --- /dev/null +++ b/modular_sand/code/modules/research/machinery/departmental_techfab.dm @@ -0,0 +1,17 @@ +/obj/machinery/rnd/production/techfab/department/engineering + req_access = list(ACCESS_ENGINE) + +/obj/machinery/rnd/production/techfab/department/service + req_one_access = list(ACCESS_BAR, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_JANITOR) + +/obj/machinery/rnd/production/techfab/department/medical + req_access = list(ACCESS_MEDICAL) + +/obj/machinery/rnd/production/techfab/department/cargo + req_access = list(ACCESS_CARGO) + +/obj/machinery/rnd/production/techfab/department/science + req_access = list(ACCESS_RESEARCH) + +/obj/machinery/rnd/production/techfab/department/security + req_access = list(ACCESS_SECURITY) diff --git a/modular_sand/code/modules/research/rdconsole.dm b/modular_sand/code/modules/research/rdconsole.dm new file mode 100644 index 0000000000..0248ae315b --- /dev/null +++ b/modular_sand/code/modules/research/rdconsole.dm @@ -0,0 +1,2 @@ +/obj/machinery/computer/rdconsole + locked = TRUE diff --git a/tgstation.dme b/tgstation.dme index 384f7be73e..f2da193dae 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4209,6 +4209,11 @@ #include "modular_sand\code\modules\reagents\reagent_containers\glass.dm" #include "modular_sand\code\modules\reagents\reagent_containers\spray.dm" #include "modular_sand\code\modules\research\stock_parts.dm" +#include "modular_sand\code\modules\research\rdconsole.dm" +#include "modular_sand\code\modules\research\machinery\_production.dm" +#include "modular_sand\code\modules\research\machinery\departmental_circuit_imprinter.dm" +#include "modular_sand\code\modules\research\machinery\departmental_protolathe.dm" +#include "modular_sand\code\modules\research\machinery\departmental_techfab.dm" #include "modular_sand\code\modules\research\designs\autolathe_designs.dm" #include "modular_sand\code\modules\research\designs\biogenerator_designs.dm" #include "modular_sand\code\modules\research\designs\machine_designs.dm" From 574348f4f828d1d3b5211656c4590142a5eeaf91 Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Sun, 19 Feb 2023 18:06:40 +0000 Subject: [PATCH 24/61] Automatic changelog generation for PR #303 [ci skip] --- html/changelogs/AutoChangeLog-pr-303.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-303.yml diff --git a/html/changelogs/AutoChangeLog-pr-303.yml b/html/changelogs/AutoChangeLog-pr-303.yml new file mode 100644 index 0000000000..ecf604a76c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-303.yml @@ -0,0 +1,6 @@ +author: LeDrascol +delete-after: true +changes: + - balance: Production machines now check ID cards for access + - balance: R&D console starts locked by default + - config: Added new configuration options for production machine access From cd0dabc6f31c1b3b18a07d956164c54ec4ea06ab Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Sun, 19 Feb 2023 18:07:40 +0000 Subject: [PATCH 25/61] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-303.yml | 6 ------ html/changelogs/archive/2023-02.yml | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-303.yml diff --git a/html/changelogs/AutoChangeLog-pr-303.yml b/html/changelogs/AutoChangeLog-pr-303.yml deleted file mode 100644 index ecf604a76c..0000000000 --- a/html/changelogs/AutoChangeLog-pr-303.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: LeDrascol -delete-after: true -changes: - - balance: Production machines now check ID cards for access - - balance: R&D console starts locked by default - - config: Added new configuration options for production machine access diff --git a/html/changelogs/archive/2023-02.yml b/html/changelogs/archive/2023-02.yml index e64467bd6a..41a0dd34cd 100644 --- a/html/changelogs/archive/2023-02.yml +++ b/html/changelogs/archive/2023-02.yml @@ -24,6 +24,9 @@ - tweak: Standard cryptominers will report account changes on Cargo radio - balance: Setting a cryptominer's account now takes five seconds - admin: Added game logging for Cryptominer account changes + - balance: Production machines now check ID cards for access + - balance: R&D console starts locked by default + - config: Added new configuration options for production machine access SandPoot: - imageadd: Changed screentips icons to something a lot fancier unified with the LMB / RMB text. From 93147fe800a8f625a62437f792c2759418bad2ca Mon Sep 17 00:00:00 2001 From: Darius <5933805+LeDrascol@users.noreply.github.com> Date: Sun, 19 Feb 2023 18:14:11 +0000 Subject: [PATCH 26/61] Add organ-specific In Estrous quirk text (#305) * Add organ-specific estrous messages Adds differing messages for the In Estrous quirk based on what reproductive organs the quirk holder possesses. Adds support for changing the message ending, which is intended for use downstream. Changes the gain text to be less specific. * Fix minor typo for In Estrous examine text Fixes a potential case of "currently in influenced" that could occur due to a text oversight. * Use signals for Estrous organ change Updates for the In Estrous quirk to use signal handlers. This commit does the following - Adds signal for organ insertion - Adds signal for organ removal - Adds quirk function for updating organs - Adds quirk signal handlers for organ adding and removing - Adds quirk check for no valid organs * Fix positional argument use for organ signals Removes improper use of positional arguments from the organ insertion and removal functions, and improves the variable name for mob. * Organ manipulation argument fixes Restores missing arguments and adds additional signal arguments for organ insertion and removal. * Unregister In Estrous quirk signals as a list Combines the UnregisterSignal functions in the In Estrous quirk removal. Co-authored-by: SandPoot <43283559+SandPoot@users.noreply.github.com> --------- Co-authored-by: SandPoot <43283559+SandPoot@users.noreply.github.com> --- code/__SANDCODE/DEFINES/dcs/signals.dm | 13 +++++ modular_sand/code/datums/traits/neutral.dm | 49 +++++++++++++++++-- .../modules/surgery/organs/organ_internal.dm | 22 +++++++++ tgstation.dme | 2 + 4 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 code/__SANDCODE/DEFINES/dcs/signals.dm create mode 100644 modular_sand/code/modules/surgery/organs/organ_internal.dm diff --git a/code/__SANDCODE/DEFINES/dcs/signals.dm b/code/__SANDCODE/DEFINES/dcs/signals.dm new file mode 100644 index 0000000000..a5381c42a8 --- /dev/null +++ b/code/__SANDCODE/DEFINES/dcs/signals.dm @@ -0,0 +1,13 @@ +/* + * # COMSIG_MOB_ORGAN_ADD + * From modular_sand\code\modules\surgery\organs + * Used by signals for determining when an organ was inserted +*/ +#define COMSIG_MOB_ORGAN_ADD "mob_organ_added" + +/* + * # COMSIG_MOB_ORGAN_REMOVE + * From modular_sand\code\modules\surgery\organs + * Used by signals for determining when an organ was removed +*/ +#define COMSIG_MOB_ORGAN_REMOVE "mob_organ_removed" diff --git a/modular_sand/code/datums/traits/neutral.dm b/modular_sand/code/datums/traits/neutral.dm index 4877c1c832..b18a15e99a 100644 --- a/modular_sand/code/datums/traits/neutral.dm +++ b/modular_sand/code/datums/traits/neutral.dm @@ -35,16 +35,57 @@ desc = "Your system burns with the desire to be bred. Satisfying your lust will make you happy, while ignoring it may cause you to become sad and needy." value = 0 mob_trait = TRAIT_ESTROUS_ACTIVE - gain_text = span_love("You body burns with the desire to be bred.") + gain_text = span_love("You body burns with the desire to engage in breeding.") lose_text = span_notice("You feel more in control of your body and thoughts.") + // Default heat message for examine text + var/heat_type = "influenced by the estrous cycle" + + // Type of interaction to be performed + // Intended for use with downstream quirks + var/positional_orientation = "engage in breeding" + /datum/quirk/estrous_active/add() // Add examine hook RegisterSignal(quirk_holder, COMSIG_PARENT_EXAMINE, .proc/quirk_examine_estrous_active) + // Add organ change hooks + RegisterSignal(quirk_holder, COMSIG_MOB_ORGAN_ADD, .proc/update_heat_type) + RegisterSignal(quirk_holder, COMSIG_MOB_ORGAN_REMOVE, .proc/update_heat_type) + /datum/quirk/estrous_active/remove() - // Remove examine hook - UnregisterSignal(quirk_holder, COMSIG_PARENT_EXAMINE) + // Remove signals + UnregisterSignal(quirk_holder, list(COMSIG_MOB_ORGAN_ADD, COMSIG_MOB_ORGAN_REMOVE, COMSIG_PARENT_EXAMINE)) + +/datum/quirk/estrous_active/post_add() + // Update text used by message + update_heat_type() + +/datum/quirk/estrous_active/proc/update_heat_type() + // Check for male reproductive organs + var/breed_male = quirk_holder.has_balls() + + // Define possible womb + var/obj/item/organ/genital/womb/organ_womb = quirk_holder.getorganslot(ORGAN_SLOT_WOMB) + + // Check for female reproductive organs + var/breed_female = (quirk_holder.has_vagina() && istype(organ_womb)) + + // Set variable for both reproductive types + if(breed_male && breed_female) + heat_type = "in both estrous and rut" + + // Set variable for male-only + else if(breed_male) + heat_type = "in rut" + + // Set variable for female-only + else if(breed_female) + heat_type = "in estrous" + + // Set variable for none + else + positional_orientation = "engage in breeding" /datum/quirk/estrous_active/proc/quirk_examine_estrous_active(atom/examine_target, mob/living/carbon/human/examiner, list/examine_list) SIGNAL_HANDLER @@ -58,4 +99,4 @@ return // Add quirk message - examine_list += span_love("[quirk_holder.p_they(TRUE)] [quirk_holder.p_are()] currently influenced by the estrous cycle, and long for breeding.") + examine_list += span_love("[quirk_holder.p_they(TRUE)] [quirk_holder.p_are()] currently [heat_type], and longs to [positional_orientation].") diff --git a/modular_sand/code/modules/surgery/organs/organ_internal.dm b/modular_sand/code/modules/surgery/organs/organ_internal.dm new file mode 100644 index 0000000000..1492bce86b --- /dev/null +++ b/modular_sand/code/modules/surgery/organs/organ_internal.dm @@ -0,0 +1,22 @@ +/obj/item/organ/Insert(mob/living/carbon/organ_mob, special, drop_if_replaced) + . = ..() + + // Check parent return + if(!.) + return + + // Send signal to mob + SEND_SIGNAL(organ_mob, COMSIG_MOB_ORGAN_ADD, src, special, drop_if_replaced) + +/obj/item/organ/Remove(special) + . = ..() + + // Define organ mob + var/mob/living/carbon/organ_mob = . || null + + // Check if organ mob exists + if(!istype(organ_mob)) + return + + // Send signal to mob + SEND_SIGNAL(organ_mob, COMSIG_MOB_ORGAN_REMOVE, src, special) diff --git a/tgstation.dme b/tgstation.dme index f2da193dae..d199642d7d 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -254,6 +254,7 @@ #include "code\__SANDCODE\DEFINES\wires.dm" #include "code\__SANDCODE\DEFINES\dcs\signals\signals_mob_main.dm" #include "code\__SANDCODE\DEFINES\dcs\signals\sizecode.dm" +#include "code\__SANDCODE\DEFINES\dcs\signals.dm" #include "code\__SANDCODE\HELPERS\sizecode.dm" #include "code\_globalvars\admin.dm" #include "code\_globalvars\bitfields.dm" @@ -4245,6 +4246,7 @@ #include "modular_sand\code\modules\spells\spell.dm" #include "modular_sand\code\modules\spells\spell_types\shapeshift.dm" #include "modular_sand\code\modules\surgery\organs\augments_arms.dm" +#include "modular_sand\code\modules\surgery\organs\organ_internal.dm" #include "modular_sand\code\modules\telescience\telepad.dm" #include "modular_sand\code\modules\telescience\telesci.dm" #include "modular_sand\code\modules\telescience\telesci_computer.dm" From 147962b2c21d7a217979593e62e5ce83a0efa286 Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Sun, 19 Feb 2023 18:15:06 +0000 Subject: [PATCH 27/61] Automatic changelog generation for PR #305 [ci skip] --- html/changelogs/AutoChangeLog-pr-305.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-305.yml diff --git a/html/changelogs/AutoChangeLog-pr-305.yml b/html/changelogs/AutoChangeLog-pr-305.yml new file mode 100644 index 0000000000..918dae651b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-305.yml @@ -0,0 +1,7 @@ +author: LeDrascol +delete-after: true +changes: + - tweak: In Estrous examine text is now based on the holder's reproductive organs + - tweak: In Estrous gain text no longer implies the holder intends to be an organ + recipient + - code_imp: Added signals for organ insertion and removal From 5f0f431ea56e8c9c28bab5e7ab47aa5473064b6d Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Sun, 19 Feb 2023 18:16:08 +0000 Subject: [PATCH 28/61] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-305.yml | 7 ------- html/changelogs/archive/2023-02.yml | 4 ++++ 2 files changed, 4 insertions(+), 7 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-305.yml diff --git a/html/changelogs/AutoChangeLog-pr-305.yml b/html/changelogs/AutoChangeLog-pr-305.yml deleted file mode 100644 index 918dae651b..0000000000 --- a/html/changelogs/AutoChangeLog-pr-305.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: LeDrascol -delete-after: true -changes: - - tweak: In Estrous examine text is now based on the holder's reproductive organs - - tweak: In Estrous gain text no longer implies the holder intends to be an organ - recipient - - code_imp: Added signals for organ insertion and removal diff --git a/html/changelogs/archive/2023-02.yml b/html/changelogs/archive/2023-02.yml index 41a0dd34cd..c8f45dfb34 100644 --- a/html/changelogs/archive/2023-02.yml +++ b/html/changelogs/archive/2023-02.yml @@ -27,6 +27,10 @@ - balance: Production machines now check ID cards for access - balance: R&D console starts locked by default - config: Added new configuration options for production machine access + - tweak: In Estrous examine text is now based on the holder's reproductive organs + - tweak: In Estrous gain text no longer implies the holder intends to be an organ + recipient + - code_imp: Added signals for organ insertion and removal SandPoot: - imageadd: Changed screentips icons to something a lot fancier unified with the LMB / RMB text. From 8f5584eec4c9a840f38f7048b11f4de584afd626 Mon Sep 17 00:00:00 2001 From: Darius <5933805+LeDrascol@users.noreply.github.com> Date: Sun, 19 Feb 2023 19:42:35 +0000 Subject: [PATCH 29/61] Make gear harness non-covering (#309) Sets the gear harness to non-covering by default, and removes the ability to adjust it. The toggle function has been updated to prevent false feedback. --- modular_sand/code/modules/clothing/under/miscellaneous.dm | 8 ++++++++ tgstation.dme | 1 + 2 files changed, 9 insertions(+) create mode 100644 modular_sand/code/modules/clothing/under/miscellaneous.dm diff --git a/modular_sand/code/modules/clothing/under/miscellaneous.dm b/modular_sand/code/modules/clothing/under/miscellaneous.dm new file mode 100644 index 0000000000..dd965b8111 --- /dev/null +++ b/modular_sand/code/modules/clothing/under/miscellaneous.dm @@ -0,0 +1,8 @@ +/obj/item/clothing/under/misc/gear_harness + can_adjust = FALSE + body_parts_covered = NONE + +/obj/item/clothing/under/misc/gear_harness/toggle_jumpsuit_adjust() + // Alert user and return + to_chat(usr, span_notice("[src] cannot be adjusted!")) + return FALSE diff --git a/tgstation.dme b/tgstation.dme index d199642d7d..c5e710ef84 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4102,6 +4102,7 @@ #include "modular_sand\code\modules\clothing\suits\miscellaneous.dm" #include "modular_sand\code\modules\clothing\under\_under.dm" #include "modular_sand\code\modules\clothing\under\costumes.dm" +#include "modular_sand\code\modules\clothing\under\miscellaneous.dm" #include "modular_sand\code\modules\clothing\under\uniform.dm" #include "modular_sand\code\modules\clothing\underwear\_underwear.dm" #include "modular_sand\code\modules\clothing\underwear\boxers.dm" From 45328f7093a10f843a0bc222e47f06716fca1e76 Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Sun, 19 Feb 2023 19:43:32 +0000 Subject: [PATCH 30/61] Automatic changelog generation for PR #309 [ci skip] --- html/changelogs/AutoChangeLog-pr-309.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-309.yml diff --git a/html/changelogs/AutoChangeLog-pr-309.yml b/html/changelogs/AutoChangeLog-pr-309.yml new file mode 100644 index 0000000000..a231e22ebd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-309.yml @@ -0,0 +1,4 @@ +author: LeDrascol +delete-after: true +changes: + - tweak: The Gear Harness is now non-covering From fcb5f9a5bdd9825ff00dee6d064efc88521d8512 Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Sun, 19 Feb 2023 19:44:29 +0000 Subject: [PATCH 31/61] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-309.yml | 4 ---- html/changelogs/archive/2023-02.yml | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-309.yml diff --git a/html/changelogs/AutoChangeLog-pr-309.yml b/html/changelogs/AutoChangeLog-pr-309.yml deleted file mode 100644 index a231e22ebd..0000000000 --- a/html/changelogs/AutoChangeLog-pr-309.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: LeDrascol -delete-after: true -changes: - - tweak: The Gear Harness is now non-covering diff --git a/html/changelogs/archive/2023-02.yml b/html/changelogs/archive/2023-02.yml index c8f45dfb34..9c6680ce5d 100644 --- a/html/changelogs/archive/2023-02.yml +++ b/html/changelogs/archive/2023-02.yml @@ -31,6 +31,7 @@ - tweak: In Estrous gain text no longer implies the holder intends to be an organ recipient - code_imp: Added signals for organ insertion and removal + - tweak: The Gear Harness is now non-covering SandPoot: - imageadd: Changed screentips icons to something a lot fancier unified with the LMB / RMB text. From e11aa3fb1d2b1fce9e60dd3a5eaa78b974ba88c5 Mon Sep 17 00:00:00 2001 From: Darius <5933805+LeDrascol@users.noreply.github.com> Date: Sun, 19 Feb 2023 22:34:41 +0000 Subject: [PATCH 32/61] Use english list for In Estrous examine text (#308) * Convert In Estrous text to english lists This commit does the following for In Estrous examine text: - Adds English list support - Adds support for synthetic species - Removes check for Vagina organ - Updates text to prevent double "and" * Reduce In Estrous sub-list usage Removes unnecessary sub-list generation for the In Estrous quirk, and reduces the length of the synth message. --- modular_sand/code/datums/traits/neutral.dm | 35 +++++++++------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/modular_sand/code/datums/traits/neutral.dm b/modular_sand/code/datums/traits/neutral.dm index b18a15e99a..eba51e9a5c 100644 --- a/modular_sand/code/datums/traits/neutral.dm +++ b/modular_sand/code/datums/traits/neutral.dm @@ -62,30 +62,23 @@ update_heat_type() /datum/quirk/estrous_active/proc/update_heat_type() - // Check for male reproductive organs - var/breed_male = quirk_holder.has_balls() + // Define temporary list of heat phrases + var/list/heat_phrases = list() - // Define possible womb - var/obj/item/organ/genital/womb/organ_womb = quirk_holder.getorganslot(ORGAN_SLOT_WOMB) + // Check for male hormonal organ + if(quirk_holder.has_balls()) + heat_phrases += "in rut" - // Check for female reproductive organs - var/breed_female = (quirk_holder.has_vagina() && istype(organ_womb)) + // Check for female hormonal organ + if(quirk_holder.getorganslot(ORGAN_SLOT_WOMB)) + heat_phrases += "in estrous" - // Set variable for both reproductive types - if(breed_male && breed_female) - heat_type = "in both estrous and rut" + // Check for synthetic + if(isrobotic(quirk_holder)) + heat_phrases += "simulating hormones" - // Set variable for male-only - else if(breed_male) - heat_type = "in rut" - - // Set variable for female-only - else if(breed_female) - heat_type = "in estrous" - - // Set variable for none - else - positional_orientation = "engage in breeding" + // Build English list + heat_type = english_list(heat_phrases, nothing_text = "experiencing high hormonal levels") /datum/quirk/estrous_active/proc/quirk_examine_estrous_active(atom/examine_target, mob/living/carbon/human/examiner, list/examine_list) SIGNAL_HANDLER @@ -99,4 +92,4 @@ return // Add quirk message - examine_list += span_love("[quirk_holder.p_they(TRUE)] [quirk_holder.p_are()] currently [heat_type], and longs to [positional_orientation].") + examine_list += span_love("[quirk_holder.p_they(TRUE)] [quirk_holder.p_are()] currently [heat_type], with a longing to [positional_orientation].") From 465ed968e4c0ac6a80e0e82245ec93b0ebab2a9a Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Sun, 19 Feb 2023 22:35:39 +0000 Subject: [PATCH 33/61] Automatic changelog generation for PR #308 [ci skip] --- html/changelogs/AutoChangeLog-pr-308.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-308.yml diff --git a/html/changelogs/AutoChangeLog-pr-308.yml b/html/changelogs/AutoChangeLog-pr-308.yml new file mode 100644 index 0000000000..4709689377 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-308.yml @@ -0,0 +1,6 @@ +author: LeDrascol +delete-after: true +changes: + - rscadd: Added Synthetic species flavor text for In Estrous + - tweak: In Estrous no longer requires both female organs + - code_imp: In Estrous examine text uses English lists From 235d24c08d614c9106651beaad7b36cc7cf1ba82 Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Sun, 19 Feb 2023 22:36:38 +0000 Subject: [PATCH 34/61] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-308.yml | 6 ------ html/changelogs/archive/2023-02.yml | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-308.yml diff --git a/html/changelogs/AutoChangeLog-pr-308.yml b/html/changelogs/AutoChangeLog-pr-308.yml deleted file mode 100644 index 4709689377..0000000000 --- a/html/changelogs/AutoChangeLog-pr-308.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: LeDrascol -delete-after: true -changes: - - rscadd: Added Synthetic species flavor text for In Estrous - - tweak: In Estrous no longer requires both female organs - - code_imp: In Estrous examine text uses English lists diff --git a/html/changelogs/archive/2023-02.yml b/html/changelogs/archive/2023-02.yml index 9c6680ce5d..debca2d179 100644 --- a/html/changelogs/archive/2023-02.yml +++ b/html/changelogs/archive/2023-02.yml @@ -32,6 +32,9 @@ recipient - code_imp: Added signals for organ insertion and removal - tweak: The Gear Harness is now non-covering + - rscadd: Added Synthetic species flavor text for In Estrous + - tweak: In Estrous no longer requires both female organs + - code_imp: In Estrous examine text uses English lists SandPoot: - imageadd: Changed screentips icons to something a lot fancier unified with the LMB / RMB text. From 51818478c5f93e784dad916c188902e5f110d1ab Mon Sep 17 00:00:00 2001 From: SandPoot Date: Tue, 21 Feb 2023 14:20:48 -0300 Subject: [PATCH 35/61] pixelshift + layering --- code/__SANDCODE/DEFINES/keybindings.dm | 1 + code/game/atoms.dm | 5 + code/modules/keybindings/keybind/movement.dm | 4 +- code/modules/mob/mob.dm | 4 +- code/modules/mob/mob_defines.dm | 2 + code/modules/mob/mob_movement.dm | 8 ++ .../modules/mob/living/living_movement.dm | 2 + .../code/modules/pixel_shift/pixel_shift.dm | 101 ++++++++++++++++++ tgstation.dme | 2 + 9 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 code/__SANDCODE/DEFINES/keybindings.dm create mode 100644 modular_sand/code/modules/pixel_shift/pixel_shift.dm diff --git a/code/__SANDCODE/DEFINES/keybindings.dm b/code/__SANDCODE/DEFINES/keybindings.dm new file mode 100644 index 0000000000..ac65f5acdb --- /dev/null +++ b/code/__SANDCODE/DEFINES/keybindings.dm @@ -0,0 +1 @@ +#define COMSIG_KB_MOB_PIXELSHIFT "keybinding_mob_pixelshift" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 03338e9eaa..ad7b29ebab 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -106,6 +106,11 @@ /// A luminescence-shifted value of the last color calculated for chatmessage overlays var/chat_color_darkened + // Use SET_BASE_PIXEL(x, y) to set these in typepath definitions, it'll handle pixel_x and y for you + ///Default pixel x shifting for the atom's icon. + var/base_pixel_x = 0 + ///Default pixel y shifting for the atom's icon. + var/base_pixel_y = 0 ///Used for changing icon states for different base sprites. var/base_icon_state diff --git a/code/modules/keybindings/keybind/movement.dm b/code/modules/keybindings/keybind/movement.dm index 296b127cb4..4e14b69ae9 100644 --- a/code/modules/keybindings/keybind/movement.dm +++ b/code/modules/keybindings/keybind/movement.dm @@ -74,7 +74,7 @@ var/mob/M = user.mob M.westface() return TRUE - +/* /datum/keybinding/mob/shift_north hotkey_keys = list("CtrlShiftW", "CtrlShiftNorth") name = "pixel_shift_north" @@ -122,7 +122,7 @@ var/mob/M = user.mob M.westshift() return TRUE - +*/ /datum/keybinding/living/hold_sprint hotkey_keys = list() classic_keys = list() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 63021287e5..8794f2f9a3 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -669,7 +669,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) setDir(SOUTH) client.last_turn = world.time + MOB_FACE_DIRECTION_DELAY return TRUE - +/* /mob/verb/eastshift() set hidden = TRUE if(!canface()) @@ -701,7 +701,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) if(pixel_y >= -32) pixel_y-- is_shifted = TRUE - +*/ /mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check return FALSE diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 138a3b9662..4f61a0260b 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -54,6 +54,8 @@ var/resting = 0 //Carbon var/lying = 0 var/lying_prev = 0 + + /// Whether the mob is pixel shifted or not var/is_shifted = FALSE /// List of movement speed modifiers applying to this mob diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 1da355a419..83f7bbbd82 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -45,6 +45,14 @@ if(mob.force_moving) return FALSE + // Sandstorm Edit + if(mob.shifting) + mob.pixel_shift(direction) + return FALSE + else if(mob.is_shifted) + mob.unpixel_shift() + // + var/mob/living/L = mob //Already checked for isliving earlier if(L.incorporeal_move) //Move though walls Process_Incorpmove(direction) diff --git a/modular_sand/code/modules/mob/living/living_movement.dm b/modular_sand/code/modules/mob/living/living_movement.dm index bf9c5e2912..4a0464ef6b 100644 --- a/modular_sand/code/modules/mob/living/living_movement.dm +++ b/modular_sand/code/modules/mob/living/living_movement.dm @@ -15,6 +15,7 @@ to_chat(src, span_warning("You cannot increase your layer priority any further.")) return + layer = clamp(layer, MOB_LAYER_SHIFT_MIN, MOB_LAYER_SHIFT_MAX) layer += MOB_LAYER_SHIFT_INCREMENT var/layer_priority = FLOOR((layer - MOB_LAYER) * 100, 1) // Just for text feedback to_chat(src, span_notice("Your layer priority is now [layer_priority].")) @@ -31,6 +32,7 @@ to_chat(src, span_warning("You cannot decrease your layer priority any further.")) return + layer = clamp(layer, MOB_LAYER_SHIFT_MIN, MOB_LAYER_SHIFT_MAX) layer -= MOB_LAYER_SHIFT_INCREMENT var/layer_priority = FLOOR((layer - MOB_LAYER) * 100, 1) // Just for text feedback to_chat(src, span_notice("Your layer priority is now [layer_priority].")) diff --git a/modular_sand/code/modules/pixel_shift/pixel_shift.dm b/modular_sand/code/modules/pixel_shift/pixel_shift.dm new file mode 100644 index 0000000000..253ab050f3 --- /dev/null +++ b/modular_sand/code/modules/pixel_shift/pixel_shift.dm @@ -0,0 +1,101 @@ +#define MAXIMUM_PIXEL_SHIFT 16 +#define PASSABLE_SHIFT_THRESHOLD 8 + +/mob + /// If we are in the shifting setting. + var/shifting = FALSE + + /// Takes the four cardinal direction defines. Any atoms moving into this atom's tile will be allowed to from the added directions. + var/passthroughable = NONE + +/datum/keybinding/mob/pixel_shift + hotkey_keys = list("B") + name = "pixel_shift" + full_name = "Pixel Shift" + description = "Shift your characters offset." + category = CATEGORY_MOVEMENT + keybind_signal = COMSIG_KB_MOB_PIXELSHIFT + +/datum/keybinding/mob/pixel_shift/down(client/user) + . = ..() + if(.) + return + var/mob/M = user.mob + M.shifting = TRUE + return TRUE + +/datum/keybinding/mob/pixel_shift/up(client/user) + . = ..() + if(.) + return + var/mob/M = user.mob + M.shifting = FALSE + return TRUE + +/mob/proc/unpixel_shift() + return + +/mob/living/unpixel_shift() + . = ..() + passthroughable = NONE + if(is_shifted) + is_shifted = FALSE + pixel_x = get_standard_pixel_x_offset() + base_pixel_x + client?.pixel_x = 0 + pixel_y = get_standard_pixel_y_offset() + base_pixel_y + client?.pixel_y = 0 + +/mob/proc/pixel_shift(direction) + return + +/mob/living/set_pull_offsets(mob/living/pull_target, grab_state) + pull_target.unpixel_shift() + return ..() + +/mob/living/reset_pull_offsets(mob/living/pull_target, override) + pull_target.unpixel_shift() + return ..() + +/mob/living/pixel_shift(direction) + passthroughable = NONE + // switch(direction) // diagonal pixel-shifting, rejoice + if(CHECK_BITFIELD(direction, NORTH)) + if(pixel_y <= MAXIMUM_PIXEL_SHIFT + base_pixel_y) + pixel_y++ + client?.pixel_y++ + is_shifted = TRUE + if(CHECK_BITFIELD(direction, EAST)) + if(pixel_x <= MAXIMUM_PIXEL_SHIFT + base_pixel_x) + pixel_x++ + client?.pixel_x++ + is_shifted = TRUE + if(CHECK_BITFIELD(direction, SOUTH)) + if(pixel_y >= -MAXIMUM_PIXEL_SHIFT + base_pixel_y) + pixel_y-- + client?.pixel_y-- + is_shifted = TRUE + if(CHECK_BITFIELD(direction, WEST)) + if(pixel_x >= -MAXIMUM_PIXEL_SHIFT + base_pixel_x) + pixel_x-- + client?.pixel_x-- + is_shifted = TRUE + + // Yes, I know this sets it to true for everything if more than one is matched. + // Movement doesn't check diagonals, and instead just checks EAST or WEST, depending on where you are for those. + if(pixel_y > PASSABLE_SHIFT_THRESHOLD) + passthroughable |= EAST | SOUTH | WEST + if(pixel_x > PASSABLE_SHIFT_THRESHOLD) + passthroughable |= NORTH | SOUTH | WEST + if(pixel_y < -PASSABLE_SHIFT_THRESHOLD) + passthroughable |= NORTH | EAST | WEST + if(pixel_x < -PASSABLE_SHIFT_THRESHOLD) + passthroughable |= NORTH | EAST | SOUTH + +/mob/living/CanAllowThrough(atom/movable/mover, turf/target) + // Make sure to not allow projectiles of any kind past where they normally wouldn't. + if(!istype(mover, /obj/item/projectile) && !mover.throwing && passthroughable & mover.dir) + return TRUE + return ..() + +#undef MAXIMUM_PIXEL_SHIFT +#undef PASSABLE_SHIFT_THRESHOLD diff --git a/tgstation.dme b/tgstation.dme index c5e710ef84..4c22ae184f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -237,6 +237,7 @@ #include "code\__HELPERS\sorts\TimSort.dm" #include "code\__SANDCODE\DEFINES\chat.dm" #include "code\__SANDCODE\DEFINES\DNA.dm" +#include "code\__SANDCODE\DEFINES\keybindings.dm" #include "code\__SANDCODE\DEFINES\language.dm" #include "code\__SANDCODE\DEFINES\lewd.dm" #include "code\__SANDCODE\DEFINES\loadout.dm" @@ -4191,6 +4192,7 @@ #include "modular_sand\code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\legionnaire.dm" #include "modular_sand\code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\pandora.dm" #include "modular_sand\code\modules\movespeed\modifiers\components.dm" +#include "modular_sand\code\modules\pixel_shift\pixel_shift.dm" #include "modular_sand\code\modules\power\cell.dm" #include "modular_sand\code\modules\power\lightning.dm" #include "modular_sand\code\modules\power\port_gen.dm" From 992d25ea081152faf9fe004bfc3369e493f641ad Mon Sep 17 00:00:00 2001 From: SandPoot Date: Tue, 21 Feb 2023 14:25:29 -0300 Subject: [PATCH 36/61] Revert "pixelshift + layering" This reverts commit 51818478c5f93e784dad916c188902e5f110d1ab. --- code/__SANDCODE/DEFINES/keybindings.dm | 1 - code/game/atoms.dm | 5 - code/modules/keybindings/keybind/movement.dm | 4 +- code/modules/mob/mob.dm | 4 +- code/modules/mob/mob_defines.dm | 2 - code/modules/mob/mob_movement.dm | 8 -- .../modules/mob/living/living_movement.dm | 2 - .../code/modules/pixel_shift/pixel_shift.dm | 101 ------------------ tgstation.dme | 2 - 9 files changed, 4 insertions(+), 125 deletions(-) delete mode 100644 code/__SANDCODE/DEFINES/keybindings.dm delete mode 100644 modular_sand/code/modules/pixel_shift/pixel_shift.dm diff --git a/code/__SANDCODE/DEFINES/keybindings.dm b/code/__SANDCODE/DEFINES/keybindings.dm deleted file mode 100644 index ac65f5acdb..0000000000 --- a/code/__SANDCODE/DEFINES/keybindings.dm +++ /dev/null @@ -1 +0,0 @@ -#define COMSIG_KB_MOB_PIXELSHIFT "keybinding_mob_pixelshift" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index ad7b29ebab..03338e9eaa 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -106,11 +106,6 @@ /// A luminescence-shifted value of the last color calculated for chatmessage overlays var/chat_color_darkened - // Use SET_BASE_PIXEL(x, y) to set these in typepath definitions, it'll handle pixel_x and y for you - ///Default pixel x shifting for the atom's icon. - var/base_pixel_x = 0 - ///Default pixel y shifting for the atom's icon. - var/base_pixel_y = 0 ///Used for changing icon states for different base sprites. var/base_icon_state diff --git a/code/modules/keybindings/keybind/movement.dm b/code/modules/keybindings/keybind/movement.dm index 4e14b69ae9..296b127cb4 100644 --- a/code/modules/keybindings/keybind/movement.dm +++ b/code/modules/keybindings/keybind/movement.dm @@ -74,7 +74,7 @@ var/mob/M = user.mob M.westface() return TRUE -/* + /datum/keybinding/mob/shift_north hotkey_keys = list("CtrlShiftW", "CtrlShiftNorth") name = "pixel_shift_north" @@ -122,7 +122,7 @@ var/mob/M = user.mob M.westshift() return TRUE -*/ + /datum/keybinding/living/hold_sprint hotkey_keys = list() classic_keys = list() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 8794f2f9a3..63021287e5 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -669,7 +669,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) setDir(SOUTH) client.last_turn = world.time + MOB_FACE_DIRECTION_DELAY return TRUE -/* + /mob/verb/eastshift() set hidden = TRUE if(!canface()) @@ -701,7 +701,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) if(pixel_y >= -32) pixel_y-- is_shifted = TRUE -*/ + /mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check return FALSE diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 4f61a0260b..138a3b9662 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -54,8 +54,6 @@ var/resting = 0 //Carbon var/lying = 0 var/lying_prev = 0 - - /// Whether the mob is pixel shifted or not var/is_shifted = FALSE /// List of movement speed modifiers applying to this mob diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 83f7bbbd82..1da355a419 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -45,14 +45,6 @@ if(mob.force_moving) return FALSE - // Sandstorm Edit - if(mob.shifting) - mob.pixel_shift(direction) - return FALSE - else if(mob.is_shifted) - mob.unpixel_shift() - // - var/mob/living/L = mob //Already checked for isliving earlier if(L.incorporeal_move) //Move though walls Process_Incorpmove(direction) diff --git a/modular_sand/code/modules/mob/living/living_movement.dm b/modular_sand/code/modules/mob/living/living_movement.dm index 4a0464ef6b..bf9c5e2912 100644 --- a/modular_sand/code/modules/mob/living/living_movement.dm +++ b/modular_sand/code/modules/mob/living/living_movement.dm @@ -15,7 +15,6 @@ to_chat(src, span_warning("You cannot increase your layer priority any further.")) return - layer = clamp(layer, MOB_LAYER_SHIFT_MIN, MOB_LAYER_SHIFT_MAX) layer += MOB_LAYER_SHIFT_INCREMENT var/layer_priority = FLOOR((layer - MOB_LAYER) * 100, 1) // Just for text feedback to_chat(src, span_notice("Your layer priority is now [layer_priority].")) @@ -32,7 +31,6 @@ to_chat(src, span_warning("You cannot decrease your layer priority any further.")) return - layer = clamp(layer, MOB_LAYER_SHIFT_MIN, MOB_LAYER_SHIFT_MAX) layer -= MOB_LAYER_SHIFT_INCREMENT var/layer_priority = FLOOR((layer - MOB_LAYER) * 100, 1) // Just for text feedback to_chat(src, span_notice("Your layer priority is now [layer_priority].")) diff --git a/modular_sand/code/modules/pixel_shift/pixel_shift.dm b/modular_sand/code/modules/pixel_shift/pixel_shift.dm deleted file mode 100644 index 253ab050f3..0000000000 --- a/modular_sand/code/modules/pixel_shift/pixel_shift.dm +++ /dev/null @@ -1,101 +0,0 @@ -#define MAXIMUM_PIXEL_SHIFT 16 -#define PASSABLE_SHIFT_THRESHOLD 8 - -/mob - /// If we are in the shifting setting. - var/shifting = FALSE - - /// Takes the four cardinal direction defines. Any atoms moving into this atom's tile will be allowed to from the added directions. - var/passthroughable = NONE - -/datum/keybinding/mob/pixel_shift - hotkey_keys = list("B") - name = "pixel_shift" - full_name = "Pixel Shift" - description = "Shift your characters offset." - category = CATEGORY_MOVEMENT - keybind_signal = COMSIG_KB_MOB_PIXELSHIFT - -/datum/keybinding/mob/pixel_shift/down(client/user) - . = ..() - if(.) - return - var/mob/M = user.mob - M.shifting = TRUE - return TRUE - -/datum/keybinding/mob/pixel_shift/up(client/user) - . = ..() - if(.) - return - var/mob/M = user.mob - M.shifting = FALSE - return TRUE - -/mob/proc/unpixel_shift() - return - -/mob/living/unpixel_shift() - . = ..() - passthroughable = NONE - if(is_shifted) - is_shifted = FALSE - pixel_x = get_standard_pixel_x_offset() + base_pixel_x - client?.pixel_x = 0 - pixel_y = get_standard_pixel_y_offset() + base_pixel_y - client?.pixel_y = 0 - -/mob/proc/pixel_shift(direction) - return - -/mob/living/set_pull_offsets(mob/living/pull_target, grab_state) - pull_target.unpixel_shift() - return ..() - -/mob/living/reset_pull_offsets(mob/living/pull_target, override) - pull_target.unpixel_shift() - return ..() - -/mob/living/pixel_shift(direction) - passthroughable = NONE - // switch(direction) // diagonal pixel-shifting, rejoice - if(CHECK_BITFIELD(direction, NORTH)) - if(pixel_y <= MAXIMUM_PIXEL_SHIFT + base_pixel_y) - pixel_y++ - client?.pixel_y++ - is_shifted = TRUE - if(CHECK_BITFIELD(direction, EAST)) - if(pixel_x <= MAXIMUM_PIXEL_SHIFT + base_pixel_x) - pixel_x++ - client?.pixel_x++ - is_shifted = TRUE - if(CHECK_BITFIELD(direction, SOUTH)) - if(pixel_y >= -MAXIMUM_PIXEL_SHIFT + base_pixel_y) - pixel_y-- - client?.pixel_y-- - is_shifted = TRUE - if(CHECK_BITFIELD(direction, WEST)) - if(pixel_x >= -MAXIMUM_PIXEL_SHIFT + base_pixel_x) - pixel_x-- - client?.pixel_x-- - is_shifted = TRUE - - // Yes, I know this sets it to true for everything if more than one is matched. - // Movement doesn't check diagonals, and instead just checks EAST or WEST, depending on where you are for those. - if(pixel_y > PASSABLE_SHIFT_THRESHOLD) - passthroughable |= EAST | SOUTH | WEST - if(pixel_x > PASSABLE_SHIFT_THRESHOLD) - passthroughable |= NORTH | SOUTH | WEST - if(pixel_y < -PASSABLE_SHIFT_THRESHOLD) - passthroughable |= NORTH | EAST | WEST - if(pixel_x < -PASSABLE_SHIFT_THRESHOLD) - passthroughable |= NORTH | EAST | SOUTH - -/mob/living/CanAllowThrough(atom/movable/mover, turf/target) - // Make sure to not allow projectiles of any kind past where they normally wouldn't. - if(!istype(mover, /obj/item/projectile) && !mover.throwing && passthroughable & mover.dir) - return TRUE - return ..() - -#undef MAXIMUM_PIXEL_SHIFT -#undef PASSABLE_SHIFT_THRESHOLD diff --git a/tgstation.dme b/tgstation.dme index 4c22ae184f..c5e710ef84 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -237,7 +237,6 @@ #include "code\__HELPERS\sorts\TimSort.dm" #include "code\__SANDCODE\DEFINES\chat.dm" #include "code\__SANDCODE\DEFINES\DNA.dm" -#include "code\__SANDCODE\DEFINES\keybindings.dm" #include "code\__SANDCODE\DEFINES\language.dm" #include "code\__SANDCODE\DEFINES\lewd.dm" #include "code\__SANDCODE\DEFINES\loadout.dm" @@ -4192,7 +4191,6 @@ #include "modular_sand\code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\legionnaire.dm" #include "modular_sand\code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\pandora.dm" #include "modular_sand\code\modules\movespeed\modifiers\components.dm" -#include "modular_sand\code\modules\pixel_shift\pixel_shift.dm" #include "modular_sand\code\modules\power\cell.dm" #include "modular_sand\code\modules\power\lightning.dm" #include "modular_sand\code\modules\power\port_gen.dm" From 11a06b16866d4dd6046a59bf908afd40324eef4c Mon Sep 17 00:00:00 2001 From: SandPoot Date: Tue, 21 Feb 2023 14:27:10 -0300 Subject: [PATCH 37/61] pixelshift + layering --- code/__SANDCODE/DEFINES/keybindings.dm | 1 + code/game/atoms.dm | 5 + code/modules/keybindings/keybind/movement.dm | 4 +- code/modules/mob/mob.dm | 4 +- code/modules/mob/mob_defines.dm | 2 + code/modules/mob/mob_movement.dm | 8 ++ .../modules/mob/living/living_movement.dm | 2 + .../code/modules/pixel_shift/pixel_shift.dm | 101 ++++++++++++++++++ tgstation.dme | 2 + 9 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 code/__SANDCODE/DEFINES/keybindings.dm create mode 100644 modular_sand/code/modules/pixel_shift/pixel_shift.dm diff --git a/code/__SANDCODE/DEFINES/keybindings.dm b/code/__SANDCODE/DEFINES/keybindings.dm new file mode 100644 index 0000000000..ac65f5acdb --- /dev/null +++ b/code/__SANDCODE/DEFINES/keybindings.dm @@ -0,0 +1 @@ +#define COMSIG_KB_MOB_PIXELSHIFT "keybinding_mob_pixelshift" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 03338e9eaa..ad7b29ebab 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -106,6 +106,11 @@ /// A luminescence-shifted value of the last color calculated for chatmessage overlays var/chat_color_darkened + // Use SET_BASE_PIXEL(x, y) to set these in typepath definitions, it'll handle pixel_x and y for you + ///Default pixel x shifting for the atom's icon. + var/base_pixel_x = 0 + ///Default pixel y shifting for the atom's icon. + var/base_pixel_y = 0 ///Used for changing icon states for different base sprites. var/base_icon_state diff --git a/code/modules/keybindings/keybind/movement.dm b/code/modules/keybindings/keybind/movement.dm index 296b127cb4..4e14b69ae9 100644 --- a/code/modules/keybindings/keybind/movement.dm +++ b/code/modules/keybindings/keybind/movement.dm @@ -74,7 +74,7 @@ var/mob/M = user.mob M.westface() return TRUE - +/* /datum/keybinding/mob/shift_north hotkey_keys = list("CtrlShiftW", "CtrlShiftNorth") name = "pixel_shift_north" @@ -122,7 +122,7 @@ var/mob/M = user.mob M.westshift() return TRUE - +*/ /datum/keybinding/living/hold_sprint hotkey_keys = list() classic_keys = list() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 63021287e5..8794f2f9a3 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -669,7 +669,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) setDir(SOUTH) client.last_turn = world.time + MOB_FACE_DIRECTION_DELAY return TRUE - +/* /mob/verb/eastshift() set hidden = TRUE if(!canface()) @@ -701,7 +701,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) if(pixel_y >= -32) pixel_y-- is_shifted = TRUE - +*/ /mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check return FALSE diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 138a3b9662..4f61a0260b 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -54,6 +54,8 @@ var/resting = 0 //Carbon var/lying = 0 var/lying_prev = 0 + + /// Whether the mob is pixel shifted or not var/is_shifted = FALSE /// List of movement speed modifiers applying to this mob diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 1da355a419..83f7bbbd82 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -45,6 +45,14 @@ if(mob.force_moving) return FALSE + // Sandstorm Edit + if(mob.shifting) + mob.pixel_shift(direction) + return FALSE + else if(mob.is_shifted) + mob.unpixel_shift() + // + var/mob/living/L = mob //Already checked for isliving earlier if(L.incorporeal_move) //Move though walls Process_Incorpmove(direction) diff --git a/modular_sand/code/modules/mob/living/living_movement.dm b/modular_sand/code/modules/mob/living/living_movement.dm index bf9c5e2912..4a0464ef6b 100644 --- a/modular_sand/code/modules/mob/living/living_movement.dm +++ b/modular_sand/code/modules/mob/living/living_movement.dm @@ -15,6 +15,7 @@ to_chat(src, span_warning("You cannot increase your layer priority any further.")) return + layer = clamp(layer, MOB_LAYER_SHIFT_MIN, MOB_LAYER_SHIFT_MAX) layer += MOB_LAYER_SHIFT_INCREMENT var/layer_priority = FLOOR((layer - MOB_LAYER) * 100, 1) // Just for text feedback to_chat(src, span_notice("Your layer priority is now [layer_priority].")) @@ -31,6 +32,7 @@ to_chat(src, span_warning("You cannot decrease your layer priority any further.")) return + layer = clamp(layer, MOB_LAYER_SHIFT_MIN, MOB_LAYER_SHIFT_MAX) layer -= MOB_LAYER_SHIFT_INCREMENT var/layer_priority = FLOOR((layer - MOB_LAYER) * 100, 1) // Just for text feedback to_chat(src, span_notice("Your layer priority is now [layer_priority].")) diff --git a/modular_sand/code/modules/pixel_shift/pixel_shift.dm b/modular_sand/code/modules/pixel_shift/pixel_shift.dm new file mode 100644 index 0000000000..253ab050f3 --- /dev/null +++ b/modular_sand/code/modules/pixel_shift/pixel_shift.dm @@ -0,0 +1,101 @@ +#define MAXIMUM_PIXEL_SHIFT 16 +#define PASSABLE_SHIFT_THRESHOLD 8 + +/mob + /// If we are in the shifting setting. + var/shifting = FALSE + + /// Takes the four cardinal direction defines. Any atoms moving into this atom's tile will be allowed to from the added directions. + var/passthroughable = NONE + +/datum/keybinding/mob/pixel_shift + hotkey_keys = list("B") + name = "pixel_shift" + full_name = "Pixel Shift" + description = "Shift your characters offset." + category = CATEGORY_MOVEMENT + keybind_signal = COMSIG_KB_MOB_PIXELSHIFT + +/datum/keybinding/mob/pixel_shift/down(client/user) + . = ..() + if(.) + return + var/mob/M = user.mob + M.shifting = TRUE + return TRUE + +/datum/keybinding/mob/pixel_shift/up(client/user) + . = ..() + if(.) + return + var/mob/M = user.mob + M.shifting = FALSE + return TRUE + +/mob/proc/unpixel_shift() + return + +/mob/living/unpixel_shift() + . = ..() + passthroughable = NONE + if(is_shifted) + is_shifted = FALSE + pixel_x = get_standard_pixel_x_offset() + base_pixel_x + client?.pixel_x = 0 + pixel_y = get_standard_pixel_y_offset() + base_pixel_y + client?.pixel_y = 0 + +/mob/proc/pixel_shift(direction) + return + +/mob/living/set_pull_offsets(mob/living/pull_target, grab_state) + pull_target.unpixel_shift() + return ..() + +/mob/living/reset_pull_offsets(mob/living/pull_target, override) + pull_target.unpixel_shift() + return ..() + +/mob/living/pixel_shift(direction) + passthroughable = NONE + // switch(direction) // diagonal pixel-shifting, rejoice + if(CHECK_BITFIELD(direction, NORTH)) + if(pixel_y <= MAXIMUM_PIXEL_SHIFT + base_pixel_y) + pixel_y++ + client?.pixel_y++ + is_shifted = TRUE + if(CHECK_BITFIELD(direction, EAST)) + if(pixel_x <= MAXIMUM_PIXEL_SHIFT + base_pixel_x) + pixel_x++ + client?.pixel_x++ + is_shifted = TRUE + if(CHECK_BITFIELD(direction, SOUTH)) + if(pixel_y >= -MAXIMUM_PIXEL_SHIFT + base_pixel_y) + pixel_y-- + client?.pixel_y-- + is_shifted = TRUE + if(CHECK_BITFIELD(direction, WEST)) + if(pixel_x >= -MAXIMUM_PIXEL_SHIFT + base_pixel_x) + pixel_x-- + client?.pixel_x-- + is_shifted = TRUE + + // Yes, I know this sets it to true for everything if more than one is matched. + // Movement doesn't check diagonals, and instead just checks EAST or WEST, depending on where you are for those. + if(pixel_y > PASSABLE_SHIFT_THRESHOLD) + passthroughable |= EAST | SOUTH | WEST + if(pixel_x > PASSABLE_SHIFT_THRESHOLD) + passthroughable |= NORTH | SOUTH | WEST + if(pixel_y < -PASSABLE_SHIFT_THRESHOLD) + passthroughable |= NORTH | EAST | WEST + if(pixel_x < -PASSABLE_SHIFT_THRESHOLD) + passthroughable |= NORTH | EAST | SOUTH + +/mob/living/CanAllowThrough(atom/movable/mover, turf/target) + // Make sure to not allow projectiles of any kind past where they normally wouldn't. + if(!istype(mover, /obj/item/projectile) && !mover.throwing && passthroughable & mover.dir) + return TRUE + return ..() + +#undef MAXIMUM_PIXEL_SHIFT +#undef PASSABLE_SHIFT_THRESHOLD diff --git a/tgstation.dme b/tgstation.dme index c5e710ef84..4c22ae184f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -237,6 +237,7 @@ #include "code\__HELPERS\sorts\TimSort.dm" #include "code\__SANDCODE\DEFINES\chat.dm" #include "code\__SANDCODE\DEFINES\DNA.dm" +#include "code\__SANDCODE\DEFINES\keybindings.dm" #include "code\__SANDCODE\DEFINES\language.dm" #include "code\__SANDCODE\DEFINES\lewd.dm" #include "code\__SANDCODE\DEFINES\loadout.dm" @@ -4191,6 +4192,7 @@ #include "modular_sand\code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\legionnaire.dm" #include "modular_sand\code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\pandora.dm" #include "modular_sand\code\modules\movespeed\modifiers\components.dm" +#include "modular_sand\code\modules\pixel_shift\pixel_shift.dm" #include "modular_sand\code\modules\power\cell.dm" #include "modular_sand\code\modules\power\lightning.dm" #include "modular_sand\code\modules\power\port_gen.dm" From ef75d6b45539c02b83f345b70d8883d46edd21b8 Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Tue, 21 Feb 2023 17:41:09 +0000 Subject: [PATCH 38/61] Automatic changelog generation for PR #310 [ci skip] --- html/changelogs/AutoChangeLog-pr-310.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-310.yml diff --git a/html/changelogs/AutoChangeLog-pr-310.yml b/html/changelogs/AutoChangeLog-pr-310.yml new file mode 100644 index 0000000000..ab96942914 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-310.yml @@ -0,0 +1,4 @@ +author: SandPoot +delete-after: true +changes: + - tweak: Tweaked pixelshifting. (Default keybinding is B, check your keybinds!) From 460802cb1daf16eadaa1e4aa83188e42f8fe6351 Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Tue, 21 Feb 2023 17:42:10 +0000 Subject: [PATCH 39/61] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-310.yml | 4 ---- html/changelogs/archive/2023-02.yml | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-310.yml diff --git a/html/changelogs/AutoChangeLog-pr-310.yml b/html/changelogs/AutoChangeLog-pr-310.yml deleted file mode 100644 index ab96942914..0000000000 --- a/html/changelogs/AutoChangeLog-pr-310.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: SandPoot -delete-after: true -changes: - - tweak: Tweaked pixelshifting. (Default keybinding is B, check your keybinds!) diff --git a/html/changelogs/archive/2023-02.yml b/html/changelogs/archive/2023-02.yml index debca2d179..fb46f8833b 100644 --- a/html/changelogs/archive/2023-02.yml +++ b/html/changelogs/archive/2023-02.yml @@ -38,3 +38,6 @@ SandPoot: - imageadd: Changed screentips icons to something a lot fancier unified with the LMB / RMB text. +2023-02-21: + SandPoot: + - tweak: Tweaked pixelshifting. (Default keybinding is B, check your keybinds!) From e0c8419cdd766451b37868fbaff26ccd9340d2fe Mon Sep 17 00:00:00 2001 From: SandPoot Date: Tue, 21 Feb 2023 16:09:35 -0300 Subject: [PATCH 40/61] deal with duct pipes --- code/game/objects/items/stacks/sheets/sheet_types.dm | 2 +- code/modules/plumbing/ducts.dm | 2 +- code/modules/research/machinery/_production.dm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index cd65dc6bc7..428db871d9 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -808,7 +808,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list( new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \ new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \ new /datum/stack_recipe("shower curtain", /obj/structure/curtain, 10, time = 10, one_per_turf = 1, on_floor = 1), \ - new /datum/stack_recipe("duct", /obj/item/stack/ducts,1), \ + new /datum/stack_recipe("duct", /obj/item/stack/ducts, 1, 1, 20), \ new /datum/stack_recipe("laser pointer case", /obj/item/glasswork/glass_base/laserpointer_shell, 30), \ new /datum/stack_recipe("wet floor sign", /obj/item/clothing/suit/caution, 2))) diff --git a/code/modules/plumbing/ducts.dm b/code/modules/plumbing/ducts.dm index 8a27f2669c..59816544ab 100644 --- a/code/modules/plumbing/ducts.dm +++ b/code/modules/plumbing/ducts.dm @@ -388,7 +388,7 @@ All the important duct code: singular_name = "duct" icon = 'icons/obj/plumbing/fluid_ducts.dmi' icon_state = "ducts" - custom_materials = list(/datum/material/iron=500) + custom_materials = list(/datum/material/plastic = 400) w_class = WEIGHT_CLASS_TINY novariants = FALSE max_amount = 50 diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm index 7862f24715..30d0c70566 100644 --- a/code/modules/research/machinery/_production.dm +++ b/code/modules/research/machinery/_production.dm @@ -120,7 +120,7 @@ return round(A / max(1, all_materials[mat] * ef)) /obj/machinery/rnd/production/proc/efficient_with(path) - return !ispath(path, /obj/item/stack/sheet) && !ispath(path, /obj/item/stack/ore/bluespace_crystal) + return !ispath(path, /obj/item/stack/sheet) && !ispath(path, /obj/item/stack/ore/bluespace_crystal) && !ispath(path, /obj/item/stack/ducts) /obj/machinery/rnd/production/proc/user_try_print_id(id, amount) if((!istype(linked_console) && requires_console) || !id) From c9055c4d656e1bca38a952e317c96e327657b9d0 Mon Sep 17 00:00:00 2001 From: SandPoot Date: Tue, 21 Feb 2023 16:34:10 -0300 Subject: [PATCH 41/61] minor issue --- .../items/stacks/sheets/sheet_types.dm | 2 +- code/game/objects/items/stacks/stack.dm | 41 ----------- .../game/objects/items/stacks/stack_recipe.dm | 69 +++++++++++++++++++ tgstation.dme | 1 + 4 files changed, 71 insertions(+), 42 deletions(-) create mode 100644 code/game/objects/items/stacks/stack_recipe.dm diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 428db871d9..4064fe9db6 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -808,7 +808,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list( new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \ new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \ new /datum/stack_recipe("shower curtain", /obj/structure/curtain, 10, time = 10, one_per_turf = 1, on_floor = 1), \ - new /datum/stack_recipe("duct", /obj/item/stack/ducts, 1, 1, 20), \ + new /datum/stack_recipe("duct", /obj/item/stack/ducts, 1, 5, 50), \ new /datum/stack_recipe("laser pointer case", /obj/item/glasswork/glass_base/laserpointer_shell, 30), \ new /datum/stack_recipe("wet floor sign", /obj/item/clothing/suit/caution, 2))) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 266d8b7b86..b2cd0f481b 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -514,44 +514,3 @@ /obj/item/stack/microwave_act(obj/machinery/microwave/M) if(istype(M) && M.dirty < 100) M.dirty += amount - -/* - * Recipe datum - */ -/datum/stack_recipe - var/title = "ERROR" - var/result_type - var/req_amount = 1 - var/res_amount = 1 - var/max_res_amount = 1 - var/time = 0 - var/one_per_turf = FALSE - var/on_floor = FALSE - var/placement_checks = FALSE - var/applies_mats = FALSE - var/trait_booster = null - var/trait_modifier = 1 - -/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1,time = 0, one_per_turf = FALSE, on_floor = FALSE, window_checks = FALSE, placement_checks = FALSE, applies_mats = FALSE, trait_booster = null, trait_modifier = 1) - src.title = title - src.result_type = result_type - src.req_amount = req_amount - src.res_amount = res_amount - src.max_res_amount = max_res_amount - src.time = time - src.one_per_turf = one_per_turf - src.on_floor = on_floor - src.placement_checks = placement_checks - src.applies_mats = applies_mats - src.trait_booster = trait_booster - src.trait_modifier = trait_modifier -/* - * Recipe list datum - */ -/datum/stack_recipe_list - var/title = "ERROR" - var/list/recipes - -/datum/stack_recipe_list/New(title, recipes) - src.title = title - src.recipes = recipes diff --git a/code/game/objects/items/stacks/stack_recipe.dm b/code/game/objects/items/stacks/stack_recipe.dm new file mode 100644 index 0000000000..b8cbfe3b61 --- /dev/null +++ b/code/game/objects/items/stacks/stack_recipe.dm @@ -0,0 +1,69 @@ + +/* + * Recipe datum + */ +/datum/stack_recipe + /// The title of the recipe + var/title = "ERROR" + /// What atom the recipe makes, typepath + var/atom/result_type + /// Amount of stack required to make + var/req_amount = 1 + /// Amount of resulting atoms made + var/res_amount = 1 + /// Max amount of resulting atoms made + var/max_res_amount = 1 + /// How long it takes to make + var/time = 0 + /// If only one of the resulting atom is allowed per turf + var/one_per_turf = FALSE + /// If the atom requires a floor below + var/on_floor = FALSE + /// Bitflag of additional placement checks required to place. (STACK_CHECK_CARDINALS|STACK_CHECK_ADJACENT) + var/placement_checks = NONE + /// If TRUE, the created atom will gain custom mat datums + var/applies_mats = FALSE + /// What trait, if any, boosts the construction speed of this item + var/trait_booster + /// How much the trait above, if supplied, boosts the construct speed of this item + var/trait_modifier = 1 + +/datum/stack_recipe/New( + title, + result_type, + req_amount = 1, + res_amount = 1, + max_res_amount = 1, + time = 0, + one_per_turf = FALSE, + on_floor = FALSE, + window_checks = FALSE, + placement_checks = NONE, + applies_mats = FALSE, + trait_booster, + trait_modifier = 1, +) + + src.title = title + src.result_type = result_type + src.req_amount = req_amount + src.res_amount = res_amount + src.max_res_amount = max_res_amount + src.time = time + src.one_per_turf = one_per_turf + src.on_floor = on_floor + src.placement_checks = placement_checks + src.applies_mats = applies_mats + src.trait_booster = trait_booster + src.trait_modifier = trait_modifier + +/* + * Recipe list datum + */ +/datum/stack_recipe_list + var/title = "ERROR" + var/list/recipes + +/datum/stack_recipe_list/New(title, recipes) + src.title = title + src.recipes = recipes diff --git a/tgstation.dme b/tgstation.dme index 4c22ae184f..343485ce72 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1305,6 +1305,7 @@ #include "code\game\objects\items\stacks\medical.dm" #include "code\game\objects\items\stacks\rods.dm" #include "code\game\objects\items\stacks\stack.dm" +#include "code\game\objects\items\stacks\stack_recipe.dm" #include "code\game\objects\items\stacks\tape.dm" #include "code\game\objects\items\stacks\telecrystal.dm" #include "code\game\objects\items\stacks\tickets.dm" From 4d4ebfb3664ef6eec59c13f925641d1a429a550c Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Tue, 21 Feb 2023 19:43:58 +0000 Subject: [PATCH 42/61] Automatic changelog generation for PR #311 [ci skip] --- html/changelogs/AutoChangeLog-pr-311.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-311.yml diff --git a/html/changelogs/AutoChangeLog-pr-311.yml b/html/changelogs/AutoChangeLog-pr-311.yml new file mode 100644 index 0000000000..8a4493090e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-311.yml @@ -0,0 +1,5 @@ +author: SandPoot +delete-after: true +changes: + - bugfix: Duct pipes will always have the same cost no matter where you make it. + - bugfix: Hand-made duct pipes will properly stack with machine made ones. From 6be4c7acf5030e3df2492a078151f70b68b43326 Mon Sep 17 00:00:00 2001 From: Sandstorm Bot <85452301+Sandstorm-Bot@users.noreply.github.com> Date: Tue, 21 Feb 2023 19:45:28 +0000 Subject: [PATCH 43/61] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-311.yml | 5 ----- html/changelogs/archive/2023-02.yml | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-311.yml diff --git a/html/changelogs/AutoChangeLog-pr-311.yml b/html/changelogs/AutoChangeLog-pr-311.yml deleted file mode 100644 index 8a4493090e..0000000000 --- a/html/changelogs/AutoChangeLog-pr-311.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: SandPoot -delete-after: true -changes: - - bugfix: Duct pipes will always have the same cost no matter where you make it. - - bugfix: Hand-made duct pipes will properly stack with machine made ones. diff --git a/html/changelogs/archive/2023-02.yml b/html/changelogs/archive/2023-02.yml index fb46f8833b..0ee15bc89e 100644 --- a/html/changelogs/archive/2023-02.yml +++ b/html/changelogs/archive/2023-02.yml @@ -41,3 +41,5 @@ 2023-02-21: SandPoot: - tweak: Tweaked pixelshifting. (Default keybinding is B, check your keybinds!) + - bugfix: Duct pipes will always have the same cost no matter where you make it. + - bugfix: Hand-made duct pipes will properly stack with machine made ones. From 90249e36801b715a2f63778491efa9d826c44786 Mon Sep 17 00:00:00 2001 From: WoolyAypa Date: Tue, 21 Feb 2023 20:39:46 -0300 Subject: [PATCH 44/61] tajaran snout --- .../new_player/sprite_accesories/snouts.dm | 6 ++++++ modular_splurt/icons/mob/mam_snouts.dmi | Bin 9889 -> 10523 bytes 2 files changed, 6 insertions(+) diff --git a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/snouts.dm b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/snouts.dm index 549793e24f..f531ba1548 100644 --- a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/snouts.dm +++ b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/snouts.dm @@ -243,3 +243,9 @@ name = "Sloog (lips)" icon_state = "slooglips" matrixed_sections = MATRIX_RED_GREEN + +/datum/sprite_accessory/snouts/mam_snouts/tajaran + name = "Tajaran" + icon = 'modular_splurt/icons/mob/mam_snouts.dmi' + icon_state = "tajaran" + matrixed_sections = MATRIX_RED_GREEN diff --git a/modular_splurt/icons/mob/mam_snouts.dmi b/modular_splurt/icons/mob/mam_snouts.dmi index fb6071b8c284f6174991b7beeeb83dbeb0950e9e..4abff36de879d4753f47f7e9383bfcd1aa4f6b4c 100644 GIT binary patch literal 10523 zcmc(FcTkgC*Ka^UrK(5~1oTJ~2#87%gdm_0iYUDk=|LbOy@V(cITqj;N{|-7P(vqx z(gGrI1OW{lgop?TA=J SN?Hsc8l)Urc3OHxM&-PP$TaU&qvUQp-@;501%mzn?7*o zqT0!)LvKoIzPCHYRfRx=^>6-R@@LG5R78)Q)L!ZI9Zt(34vxfhJLl`kKP_#CZG$i^ zpr$=sgR@>$vo22dQdPt_Aui&jA&+|VtgCDI%fF$ocDB0|ZNuAivNi0mqZW9_^1z@B zLEo7_WYou7$U(KXSrabnD$LuBkDd-XL#2fCUDT2kUYs(WmFIhYZ$!*+c2ep7@$^Lr z5pYh~(YuT3&m_H-#iko_;KZ8uF>y|WL&Oczxj#fRg|{`0@*atMaxoYW|IGRIcp&z{ z>rg3~m+{<9ij_~TO>hHr&A*E+=Z$1#Ftv5lM%OV$gNkkeCJtn!OX*WrMB)c7J#MRe zl2#*GtR}qqSvcoo`@&gnl?(Bo6d#;8R?z|yv+Gc;$|<$K+xh(VL- Lndiz&4Qm6x5wvo5^D zid#>2YH1Yn5qhd5bJX_7BUoBPZ?1>vGSwmmukQ`Ul2oBuOL^p|yd}M%_d`oJmS!&~ zWB~vhKBhPc06<^q #*zD+eKt~aDo<>pcq++?iM2k+U`P815XAP5DuH&g& zO#pGHV(+BlKi$V1(Ld4C&e?j&!9D9S-OeYGRye$o>XooTPU(#HxV!-J1~2S T`)jMuTLRi(^YG3<~o>snBOvtNKswpp>%cV?o*9$D91?IA65)o2J G|m5PJ#rs!A;m zXc4nq)d!JQ<^6v1>vs`deI>)hiM`wf(VmOB_PP8QXC|KYEeJ7WqF5 9a6~6)Je-ducNf`k{l0xj`f}#UEGs_yAV~uJYjpR zc*wy%8R+f_^168$7@*bI_M`n>`~43(`D0YjJczb$Hkx}R$x~I0IX_|p;4~3AIt-Zt zISm_KzG(4OGV4p~5Vm9A(r=zFqVU~SNiILOP}eDD!0#iw?NE}f9kQG!0pCw^90xpn z4mb*UX9VB`xcmX&0H~b$Ka}WyuG_HF3;>X6675mr%#+e&;v@>hm+SgTDe1q;?uLjU zEyidMgYtR^^4!i74+HLN&%W4)XEqZXyM1(RQQL#oYqz8XlTqPig$oFa88_O2v9 zG1h&<`ReGNE{~e?Ww!H#yTmKrOD)83N9{FN1YfZZ5_ =CwwC&`n7z?yzqhvDOPA@oU|zS=}tN#Ogu#35^6S04pl0uWVYI_)gOkFT+) z%pgb?1zf_{7e>G6uMo*S(jp6djTMyvS~?%(a=O{?hDW**IlxXT6c;z 7!GY&3RZ2b=Ig8{evw`+O}1>fFuq zy_5^Cx^v)bs>=AFo7WTf{uwDj$7YR-WQ4bO6kDyRkq&qILMm>Dz2^V=VKH;DjRVYE zU*?DG8pWiw?arXMWh?2)bs> M(7Z}-zA9f@(Jzo Mj*J_i#sABepbVL3VylY-^%p+H) z1j)asaBzx~!(^_-9X8gx-%r f e1%%| 4zsIwU*- u_ku6(jZ1qP7ulkKycielyb}KDufe{y${q6S)wtHmQu>*gHK9!?I0m|jk zpny9|IcYPr45xQnZYRzA)451T^XS>U`uvuETOFh_o~m7RAhlVIM-b=5_0nd~Ap=cz zcHnL+(GJ9WB@99QguO?NL^_w1uoCMldz-n_;X57k3C3@-1oQy_xhu?*QvY#x_4xTp z_jF!eEbC%QwZQBOf?nk+2bR35k}AVE> xH@&NwokIi&B&;8<=)`2poA& zkC}NczA%^Ne*dW`ET+$AFb<=w(r$!YmmJnHX10xifBpV!zeuQng&sX_>+KX7bDa)1 zOwnO?vVy1H)jJSqj|lkXkn7p8PnSZNOU*ZPO-Ukmx*?3^l8W28mTvCud}FSjZ76D& zx^8%{WW>st`$0t`Yx`>Rj=dgEXYHLe$Yt2tOlRv8Y@^Ln{06O 3T=O*Uug7g)~<3ydtb`_WmS>0>XPClBn>K-rTPS2)?n@ zI2)hK!hICB`+Un))U0FWY>FeFi+fkxD 2%0oITm4E8HLMv- zLhYK0o3p-eZmI{FVDNYPh(Wb7Tx6Gvlcvkgs718Rz(HuJOJRSNLxHi>fe?KEVxl>% zB5oHWFiEI75ONK_wRF}VYa6+}!@N5C>zJVFHg~m+aj$IpxT?31WgPEDIj-uf^kFAj z9p;t-&K1{s=Z>P*$9Q|gRoFK{N4Ki9c)xCR*r@He7cPG I$S-PgQl9PV{% z8FNAyv^{z7WBX!W|McDQ2fl}i !`5ODPYGE$1CrJ7d-Ab$jt{4`} z&CQgM=4j_A#tO+^op)~?u;29p-D9gM#x{(xSs=Cwvt9GghCNB{nvS4ckpmIL5D<@x zzhlfzL_EiT)B_XocA9{WkJ}H~4wobW#Mc4!>m4{a#j<1KfoW;1UwLzvLznU(z$iv# zc?9YLfWzfoOgyv^uV>Llwjc%^@O6%eW&xp|H3PLYy@_*3sAqv&3d60imJ5=0sjqoh zKV_nLNzu=fZd!dEv`NUM&53%}xGQfCT()sbgR7;tycdQK?x%!iY_cBm?arO AvM-QogA9M~GW|CDMP#VI^c9i02n4u$@OZP)Xj-WKsMnuEL z!t_Y5I;%3S6}|QRHL=`zlafl!7J9hayDOVX5y3*V&*2%5L*ZzAn QnhR%+cF z{XRL?3@YxruA9T`Px+!ckz!mWTbvlMnfTP*V?78N-+2TK|3wnXZ_?ZpvA@5V?s#>~ zvg1UJqc3@Phc26IlVNI^VLkqA)@JTnS j*`xn^$oC)2 ztRRK8VilVXe~LJL6#)$JzVK~DbL4dU&7rr&;u&S2c2y|cqMD$?-J(W`&|VEmD;aUl z*HxR)9JYM3U~1(SWXa{NiOZcL3PdZ4(_L`A1hKfN31P!^mpQGoJECsuG{1tDXX7ME zq%g9P 8vdI(}MFPX{4*nGLd-|6Vqa?eF3C|Y8MM&D)i!9PKemY-D1OJ4ppbm z_6}fH#Jry;1(Qnk`Xv989oiObL?&W;ogWgbPZSF*x2r6tN=imYKfEir3l_IIsE#V! zxW s7g(({@FRdV&6?(-T=VFX&Wt z;bBo9t>yDpFM;!$n7NJ(>^RmoGo!2-XW=5&Lju0+H1OQF)s>PM{)x7WA9Gwsr!@9J z9>`Mc8&7}g+Bjj`wDm^e1>Abkv_>q>dvAN6#aAdSbXV`Ip4&f}eT#4*m#$Mt5&x3& zpX%e7RmA|&hT;=}ON)L5FWA}CPKa=m{lV4a05N1NO7+hEtUW?V_#Xm*B`p5`L2duV zQ4KJEjEO0e2-lqyO0EN@X4u>C8p}X!QAR&=OraM)meUGXwt9)lx3bR7lSX(RKHzJ- zMo}I8`!Y4)0iT_>yNxT;VP^DpAXGG>8)8c}vt39Y9lLe_CRX8HWfmXbI3ohpDwVT3 z5cRK1LJYGrAN7E?X>nwwZJ6lMgIm2*FZztHOFb81|NHoGEgm(k-|G6#rLY67U}?S8 z@t a+&sKlQ0 zbluog(cI-y4}sF=LtgdC9*{!gp>D#7awTqZcD{U^@K$=3O%Ul!zv9@FT@>j}nId1g z3PM>=8VQ$o`n#zz$g=*pe!h__6s1W2kYE0YW9VPd@}D7Xvc^`}w6k2sdJhD4Mv5c^ z9C2i6dep?S9)SsCUW^I=N1FeGtei#>xw3EtoH@JOfhBI*s>zqP`ao!Ti78H>V~QzP zN8mM*xHyhqE1Qv92oDay-}NB{By|Q=MI{8QID6FSLRq!ccj=Te>)?e31L7t% @;+Yo(-Ym#-V6)DZx|JPvvUSQQ|g@arOl^xm*0tkGD3~I3hGU} zn$Ck{p;dK53w@8G6t}IHH|rBN=urRulx*b|Jm4EU#zWy1C}`Ut*M$^YsUFIgjPN-M zryl|*@#Qw#jLp)y+#To8{e~MSz-FUUFOzjqdJ4-PV0W|WDE2UDCFePC*M)umId&AN z5PY~@Cr z%HU>SvmHJeuZqx$5><*i(WZPerr$N?p)zIZF! z&hhf-L0Q30(e%p0)~D`kPyFUEX$fDHy_=-BzvH%sE^KX)Ou`0D1NY_C2|xH=EDTIX z9k&UKw__XXGzu|YDLHinAeL ag;AcGo=_rYBhKlCmD&{I4j{F|fUa{tdn zh-_Apo#wTuO-Lm4?iulhjj@t`qmc`-dej93Fb}n;29T0Ew=h>EuARE!965k70qu=X z2=4VlqT1dzoB%wGyBWN?y_g{uP=FOQjW#EGqk@9#I1g^~H5w3cs4B&CBspktx%-K@ zi`+5B#PScdt-zu2y960Fr*0<8$i-TMr(~hIshdMPJrGGK;x4fWB?6LLE_y+qn}Wo^ z(6bpf6$tMn#?by%W~%q$Z&v#>vN8j&>@;z4nfL35mC#n|SVI}cG|M%z)q)8B`hmwA zS5Nn>(J@<1(XoEBSF+Kj>NH^&85izvEvcM)`0{N6f7@g@RNKv3$f-)zBCcgPC2hxW zh=S6SG{*>xIeQ?eJr(9~ZHFO>qpRWw>GhP29enA-@A09By@zMNv(1oR6rocudKko) zp{vps7)b8z(~C&OHW+qEtqMsDuPG53FZ*!okHCVfXlmT@6Pt0kL=jy^_Z0RbYF3M0 zjb4#Q>E*9lyx$V7ryL^&3(`Dlp5O`B0;`D|M<4EcPClg?eA IfNI1bVkFBh(jey zvnu#X+z+MT9?T}jd>*tY{GA$zs`{%qo2u^Z?D{%cC-{9`ha(+@)m{Fs1VyA^MT?G^ z-Z&-wrwG-f;Lx5Z6jP_sS}> ;~_Wm4m|}kI2 @;({cT>6E>GL>8I|V3gu`+=Mm<(y^-t`QOm5mW!pGW7X<&}I_fjfp&88{MB0kJK z?)1FsffV8ry|r44DYUZ 1MeRiXRXeI-dtlvJQgsl{$=?#0hErV z083j>;vabOt|VfktDC3a^Sd<|l9~)9*i4M&<$tP7uRi%Tc^KfQb>ZBhdft1+Ix`+# zheNO{DJ-vHHd_q I;jM{rEs(RxS?RDg#2D6%L+-}0~FW(zQYyrv4~Z{_$f>Ha z1&w-sVT`1$%jHT(`zxxK0jo)!+C*kP)=U-{XHGN|CY-I}Z`=!C4g`18?0aalPuYRG z6&NAEY>f&BJK1|OC>`7ThFx>RE4GjU%HLf}MWPt{`NrgviengDJ+s}p@r_Japri0s z@Ajgr_K2Wu;`av;t2M1v$YUg_ugM-QDmK<6PKp^@uc#NnY&^)DmW69)>Pc2;J|kvi zw5cgsvvD9K#tzN16M@x8w {qSrypyirm^;>56_o&0yR0qGP{n2m9?C~ZW zq#X;CKws3)XkcRJc<1^ALzjQgIqNB|ik(TIo_#1;p-D`m#_d;Aw12{9Cz5?$MR84t zBKfflv*BGuaQ!gzHGZaYtEw-?vqlz5a2UctSrmM(Y8mcFddIBT>Je04Dt?P)+SX*M zX+nGcOn&jxXZn5 5guduu2BcEAH90m*Hi8YQPpRcKk=bKf}a zJj>X6V@BnpYj^6lttB$b+dsjA@in(5e-bET0WG)mK3IAjI#XKQ+a{`RL|OGGOOF$J zAir jr1&Skt6ARJFn2ZmjT*C|RMZSsa6NlG6IUH)oiJqTIIMlEB^> zXXA)kdPhFnb0YiXFo!(41X;UX-zx{e1`pjMeL;u@k1g^gzPhF%mP`*Jow@m>Ob#4k zi5V-nG^xIdXl2<1R Fgdo!U=-?t-l?57Qo6Ea@}fkEcujB0c~uOKdu( zX?CYWmI_tc_6Er)V)sqQ`BTWY-Bdj=vHNQET^6(5>Vu{DQj Z)U z-JzO)4{rQdY5c#dGXGbK?l 6JAf)<&-(%wgG$_?L?Gr%V+R zzPIi?o0UFh{`)L|Puy~ug>`_>+@=o74t7Jb4@&&F({)d-gmrl^uB`C$refnI5-cox zs`CdPxN9jqFNjBKuE+JO(8uCWFxmxQ473q6dM{I7N)%fBx}(r#on1VU66ocgF{;|# zo`Dri__D>DT*4z1f}17^ _)C< zG)A6d8TO`NHotwt(656>lMs_(k9b4R+38-~vlnE4GZkyhTD`(JkRBR!g;DLt >B@hf1PnpSR5;2cC^4S(I2<|rNEHJAVoDb(jFaTBd!g!bI2Et?&b1T z4`dbDv&|7#Vo7FNm&ic<=n}oj>Eb4dY&3wK)6pnQrd#HUm$Moi>+!Vq)b#2OG1luX zraSzKL~1PkYv)!k>n*bP_DC)5=f-}DaT&+{;tcFfU`3FvmxMQLmSNX#S(hq*M<8Lg zJPAkn`8>5U$jZzDqvsm3G?*@vs})>W7rj-tG? y~ znCg@ygejO1-7}$-&u^MpBV|_`z0X#zHeB^xQT==yU*!K=P_!nCSULoc+E#skmUZ}J ziRAP7i>9<=Rie+p$VzI-;6#QuzD_zz-I^5Z^`05n^Qz!wzE7ISW43%5K!=+AiXVgi zo$*}$VaKIF!7lQaIca%Lm29b3_D@L5GvEJw68iOsJFX(Rb=B@EMuw69)= ziP2N*84X#nVK=>%rTC{`3R(1H%SlUkYrIo*@^--ZV2-1c?ozpDU(WTS(GWe*uU}uJ z1NYGdqb6(YWuqEPFpIV}5x>awgV)z{*AK45QX`Ia{ho4c-2C!+aMLUu6*u?m9^BVd ztQPKP7d6lNQt{^PSTMOw6^zm&Y=*v@ZxTrG(L3_f?6O7k@*Z>eZm;h4C~Jvb>%QIi z6Smsv4hOHdXV0K+g#P+V>foh+`|*%*^jc$V(RDa2bY@R;Tyd2->O^N2R1ejq2nr-S z%>A6(BO&M|K|{#(fGiIb6?WCfW=v2J4$okG`1%%A2d;jht%Bv3mOgi`_Cu7v6Pzv7 zxbLLjP7Wn NC0qBcxKlG@H=bwUx4(D^OkkHByxf7{^#PF-c$yaMlw$!uOVAms%9y$U@h*B zNUmEtECMG__(zDe@{QSx&^K>SM4It6YE#z1(@VDQ$K!OkonP;62S=J(JUfr!_@EZ_ z#KU|x@HpsF_EQqD;<$W0OtW=Ruoxr!_J+MJLy2c64;Kg+Oagr5qKETkR7Vz #mUW6Qk53JUr-({gg9Bx9epR4DbfJ`JAh9^ zH_&+|%`SUZ32ISeebo}IX;%Kj;5_&60I}>%30A$ccrU~4$oD%T9GRBXZs0T9Q}MRk zWG K*io{N$1nloF&)MwqqcXh0L<~1N z9OL*qCe>N8nYTLeM#La69c~`Gl omI5H4=P3vYxZ%llym$XJ-@ln3 bq_Q})RdXwA8J;@;_78mPj!~5XB>sN^V>P>Y literal 9889 zcmc(Ec{G&&-}jJgB}!6+7A1rd5t*@6wot;@M }Ez~DMGSmtq9q&jTnrqp^SYn z#$+A)*v5=mAK%}7-@oU%&$*x9dH%S+_j8?dUFTe%^SQ2buFv&)y*}^P>;2||u`VC4 z2rmEt;M3Q;V+sJUwH}=L+?)p^8iV!H2RDJCW|q(IIQu(3bMt-f=Hm?j1ZU@@nV58( z6X-;*7r6!!?}01Dm5?8l{fyp{IeBfqrMNwHU{RL6lvjRqQ1&=^K-1TDPG^AYOKGGp z*1(Fs9Otc*rK>9|YfV@8rX^L3<%OMR%6#mo*?Oiu3GG%8!-8ygsY91aeA4)9s;}ib zPky|LC<|4OSAbo#QPW(#^faEg_}w)=-M7cfYWGgh-aB4(di$xe?9qpgEs7Q=REk|S zGr^ SmHh!@&(d^ex z|4Eb9_2-qA_JBsVjkK)mf qMqQ1{>;o@F)8_hr>o+t`Cb3jTiX!&wqIpk;Waa z>6%#Q>SdlD-XY&q^<4FdZo1~k?48X+Uxo#UO_|0d;hU8fSqt5uC9&HV(DM#Y?e+lx z$wmD;T4ur7>r?P|;+;^!mblgUw^OeL<23uupDGa0M~qcPoD Ho=YcFw{IB;5kMCC1+fdiW@@;zv#noCIyyzF zo;s=> zqXw5ysTC2gXL{=H~Eb zZJb?rM1vAjzm#=U8^6|?RqY=*liwtsggGQs9-;QKjJ}JztnPdlVa4t{A|c`L?b_h~ zs!^g8q(m<`9d6HD>fw*y)6X#tk_nJ9ui(J!$1y~Tz==wli0*J?pr{Buy|RP${C?U( zWlVCDjeSzN3ICn5@aCqp?@gtcn8Y Ab7FFTy`7&pH;e9g4y_1k#Qs%{9ngdjgw7~tY% z3EmQ;n9cbNxDNN~f|4i36YuW`KW&GAp+*;RQ_(|FZ(s@GOdET)uQ@}@SwTPhMbewM za%{4(o^B*5)8$w2l zor1)8#xqpcUlkg4=gK!I$oqWQJcbOV=56JL(#@?fnmgmNU2uy@UQIx*F^40JRUUi! z vv^Keg<%8`~%Kx%MS&K&`d{Jk@c>Qn?G>Mxh|xyDo~trB_AZe8^Gn z3*mLP>xnihU+4U4JmZ{g1pGWtQT%%wbT1}`%!;h%nTQUPo7S%OL1JhU&8oELQe$FC zBR6C^Pq3af9XVzonr3Kcjt{}f$XPDYi|i4O)zHo*93IhjIAkDQ@$z67aNr0l1cfT| z4G-&NFhz$FVCj&z>dx4;?IX;0o^YQ{5z5 ;`e262ErKq&AxUnZ zPwyJG2(S)fw^O-A-+glb9xn)fWw!I2Pc@MfKd2F6XVqNo?4^1Y6xP%hM~v_UH@?|a ze_-`Hhw$fQ_eSb^`A^bRSgcxUb?d@R5rl5LWXRB7(u?={YD2j#W5>HLTar7gSo+07 z6SN}x+@;dfBYb(ym@Sl8-;o|eirDRGQQlIBxcUGp)*Pkg;$b1%>S;CEv CFM4GCbwJT@Jn+#{j1R5)mrz7wg>Tuckmfy~uGl KO}H=hvsY){`=HPi&p`W5&-Ne;g|T$vr6-aHhCsCN|rAF2`t%hM}e@A+aI6@ zSRRO?$UXRX5&Un#@INK>U%zd!o>YHIssvfFNySz-r(J$%J>q;%bV%49^7#X>__Hw} z!{Y=-&x8RHa-+zlJ~Nsbx1Tts9(Mk_0rgXNJh?L$NEk~ys~09oA4{MLPZAxg*Kdpw z#hw(s?c|jXW2}DliAeYvsEPP(j_2@7p;o2@>Xkz$-%B}Ty(l7U>CErey{L*}e&9ut z#`%Tw?ND+3)kIAl3Qi#h-jVJ>_cOHEH_zZi*}om)_Xt`{PWHYSWj^T{Pw`**65s@7 zMph!n)4qE4t%|}E>n&{ITmzfKVG?}j_+DJ4d+QCIUr&DR2&$Mt%LTaFSr?7r=CCK4 zTauGD{jrSs(uLI2vFV4^E&Ma&Ox`Z7)q%!}ipNvUn+-nl$cKHhnmLiQK-F|_>Fhi9 ziQd=uRK3kxPKaBnSFsP!*l-xBwnjxui4stBAv&NMS@A%(*vBEU@71@j=J}Dh+?pM` zkX7$QP}82#{+w)J7eq>8on_->SSvW+x#S>jATu`3)ed_ |89ccKt(9gF5TWc8*JtxhXmkvr>h^gfiV;Ruw zz$`V&k(@6vO4 j)yu%;#oTm4>$bW7&u~tuSw8Xyx`v& z;a^E{lnJCn`5&VVjON?Tu8NCiaN}go%CD_bVm8%pli $3GX4TF{l@gv`CV%692ORnW`uHsWt%X*I^Yk0=T$?(QC^mKg% zJJ(K}VmM&LVP4<&XC*+1tZjElCnQSk)FB}}bQS008dIkZ4?s4teDR+*O1|@ZE7 YO|DWZ{zvkNiBPIXkv=5M=Lye;~Dz`sGGx$NZ=c_DOt9kgmQGCsx zrZo~5(ay|G6c&gbEMr#H!?K%! 7w0w?sJhL;PXNh(Z>X#^Khp_z{g1XXP q zPG4gpx+VM#v9g+cC~@g-C* 36bu6tZxgbQ*k($!`Vz{M`^U#Sa6TsJGxBE@!q|t% z;WJTvxX$!&r7#91h#A-fvZsT?hNu0hHFH%GZ=!VVb*EM5<*B90bI_KJx&8Ul()@J$ z(COvij YJmAGKHGF4$D- zGQTV8(-8V00}F2o#6Q^0b;VOOM{8}qsGDN$5r*peq3uRxntfjce}@=W_>ysCbMi<2 zRj%#&DKrqK#3+h~q|QMnILr_dD8-fMC*(ut_z3-Hkmo!gLeD?(Bmx2ye@VgZ&g?o1 zrcfum 276_%%2$yuv&65>52 XBo|^X zB(Ny^?&5IhTEmVf>j@IRwrr>Y^Eu2mpx;H))(7o2(rdoeM8dcU>!bjqiRf6q-!Ha| zZ9hkmeH)q{Ll>{VYwTO7Y>`D4_3YKcICY)wA6q@5gXi*0VOpMFn1}*~KbmF=4w=6i z5=v?jZLpQEEsAj>tVpk@om<$5r8c?I@oBglXXkvJ>B@gX3r6%QzBAwLPv|;{`Uke~ zPaSV_6`7Q j<4@^}LNoMQ2rL zKW}UHLU(M5dF(v(+-T$ZW;Yx_Th!U^4wE-2#QCjER(FH1)R6j_ne~N7Ap;1#Juk7- z{un)O;N_X1`hK=hvfwhqqNGm9VUTb8#fVC|3OoNq!=}_=w+UKG5S(xPGIS 4- zcf*J232++Q>oxT}6t^%eRrXvCcjcbfJN`Dv>BgN6$+sx48Dz^ 8Bg6Tvyz{wJK#f5!O`y-^hKJgYXT;CJ`?dmlyyPXX2qZRgT~eSk05%_)aZ>G+P2 zy9E#Sg(U_tMXhp=2IZuk-MRziP?Hp1#4t|nG|6NK6-WBlmnKgR@kASl(DFC76rv&A z$R|rVSI-hY4YtunH?dYfXc)CvEp_)Y^l@;l(4Te)(;@H^F+RSb(-d}oJ15f^R;j;V zm7BXps)Nw2 |9*#DqesN zs&{TFf?sx~LI#gdaK7DDpN-uS`@^Rnx{hdDJ*ZN}7JkjOd^-?qQ*zh#A@t82yv`_O z*Gk>#*tFWU#fqdJ%Js}mqWISDSb8opI%x~tw*C|~YdO13F7XQOjG1KwUY>bEiN~K@ zYVOgVK%_q+JYC;+lt*&3@#*^8eBFLI&D}>5=oR@e;8&}#XBgt8&)E8w4KGZ&P7B*h z)O6nVFD(r3S`gH}xt}_~7TWI%EBC0YM7mEN+Xqa`32swos>*(~qnBb@Cn>@@8@+A` zqMt%kr0HLaze!cr#IAh#BnU;}iR4NTcZ2TWadM9V3evStnqnlOK{VZbY{7N4^X6yR zMGK7?t;>?%af= pj(ud)W|<6b?0M{(xu=r}eYm%8L)t&)Zdfz`l>Q9qRr4to-%HM$B=*6& z&kAUN#2ay#tK`7HEKXAD8Qis~l3HVh2&0N7(U-o%RV4*G7ZYgn#+LONj|&OBg!q8| z3Dx=fMd-Ni&)+#)KC%E(65%3@b-erH10kvtOPbZUx7?s!f?@^X_?9%CD~8k_A1=n^ z+Q-m}#w+WcNkhPc#}yYNs?nfF{$6xJOflm|l)Ume!EL>Cdx|r+tTHZfLZ#DRXjRjN z$K+`*@2hGwJ~pdBj$cn*+bSq*@-Be=I3Gn{W-ngLig5Vq#lI4jE#lvltNa)00a%j9 zyGt&YMq%o24i)rLQ5Q%tj2&m1Sr(~=okL)>9ri5r`!)T5wuUF6x|4#4MyzQa@znH= zISg6T1{-M9Zhll(BE)fS;EQoqih5_=GZpa~pIuvwMN^w
CG}g|XnP8Qr zH1dwj<*ntvlOHy5vat--xQew1AvW?Jk=26U4uuymzgzW(wBRwVNCUKN_ZZFb2sCT* zxH15;>BF3TFCSTr=Kqyq{PXdXje=2q+|7N{c7=PW$Wf=QrhuW%;ZaEN?tTJ<&%3zJ ze3bg44;A#trRR%Q?KHVt$|+3d8PpncL8WR^7Pv9;M}2X-)l0WlH($h i(9RC?`1X_(x4LVdn*icxe zXK08?@RcfBbj&o-9P_^4EiL2|2?V8kWhvk{yFI)t@9x%XkQ;9M_HTE`YVCfNC8%hV zvS;X>YUpjR3Cz>xHy$0ChHYZ`yb_UDq$-x^<+VDi#{{bp%THJtUDVIt2DqGe?`9Ib z!BTaHM?=5(3O>C=kA &X2$|6zi-2-6NVp;zlXT(tlAE zJLD#)2yj^Z1Y{pQH-2U((kQU8pBp4JIVio(2B^Kf!YcrX@cyCj1Mv4nhW~_i!T!NN zuz{8)6;z(G$4}}d%dE0uM FbY#F#G^q#k$ZRbw#!qxu>rhe*_&N?#rNXR*ylh zb|0rpCOH7Absfsqc`89YPDry}NYZ*%b&eEPD!xqf`9eTcib7A|;~B~~PnX7R@Jnl! zNue!7_0;6H* Uo-q_K!hA%cwNOz8(Nrp)BHS1n5F2}o~9AfFeFh~%u^@2m5gUYNw3G8&&-(e zF#!EUNIii&5w;1VYH9mDmq+k(*psC#$&cx0SO;mm+=2Oj97HYlC+;rzSW3KDto&SG z?#O6ez#~hH=Gt=$z+O8@1p|S-?oyN0#?^Opzoe9wigHto#YEU0Aa8d;cmNe8KAPx+ z>{yWKt&`~KGo+dH(6vEE!BS1>+yH2k%seYfp+cOwXk+1W}Jb?bH?}c0pmy1Be&z zi5+L)U2yq$c%N+RaKLia9fLC)VYc>9D`QNygb4zCl6=`l=pG5sE*E5%)~F$?CA6je ztDodKLsy_m(69NlmwI1#*Y_nT{23})WBW`CP(c^hVYh5sBzV8FPYRS19Lm^oY#HG( zkovlCeARa2@@3Q$yXF=?Sq5w(Iq%8A64-ffQ;5%S>P#;v*V0%Iu3tF{li0Ht92BUj zzWZ=qCLO H3F`ulaf3T=x${gd;;_sKs?-ZC>b zvdwSrshQgxl+}w=3i{GIOI`ETM{vQ59c5fdV|4EkEo8|<9mdb+Z5_irUf;e7Qd p2sBX*a27NyABxpcZB_JFdQF1 zt>58&0+GK^e}OPzK?%dUJcJ_&Z_MFR8HU8egO@6ja;Yfxt1`y9?w18!)!{B`uZ##E z^j{-(g1)MPQyc4W#b?>LvkfvHD9E0b<+QoJ%S=>oG;W-s&rGEoJ%n$${9cc dg#!`~&K~0%KEXt}-udPde!LG}>Z}D*%JP8u`%t{OOt#gki~3=7 zW`-xB7qOPL-R*w~ep=pW=v7|eM! #7Jz<~c-`_CDco4|#PKj!q4xS_FuU|oUe3_)m z4IBsUi*06EUltsAcmMu|%EHSOBdMQ({Tiujw#+8$Zbi^U6g4b7>&a-4VhKOU>p$e- z6Vuosgg)c;XG9DpRIej7;rSlr =sA{=gT6cJf;G;6+vm5}J!g!*gu+P9iCuFgjJ+d!e4W$_tgqtGj zSUQt|&HmtCX5v&w$L(}036}9@IcQ&V?;~SGf^l1V18f&0MEY$ew9YG7UJ?9Z+5Jvk zBfDD>^Fd4nr_N?AlHDB~e6)n9zN Y{w85 sXKw11TmHr6l}vgx?<>!B8ps(+U)@D*ghIxI -sV zh}j-fIk;{*oq(={UOL@oLYvhQvO6>rroh*l4p&lKMqcrVmHpAeWFzn7wY(QYdmnoe zA7kq?iC#J6BJcM(=H92sybq&3FIFTi$^RsC!p)@un`}xJB)$9*`?cbW+&Y_w%{lW| zBH_^k`r2?;&G;CH0+{s96#WKw{t-9sXh7Kw`b!y|Z@2!sZvG^SpUG1VW0hgT0h}Th zB4#ocsK}PF%{XX{)?aPCS$H(x|Gb&~_uk?iER(hu;)e5DlAM%q-qW8T_>3mAwssTT z42!PRm@E+~i}gF{;;H;InNb)}s#iNgP(S-}KqWlm$ula+YR~WtA-nuZRvQfGwZhRC zZnc)D*d?*V0cu&O+imi>y0L {I9zR?~`<$R=;}+Ms z1q!886d0a^G<;sFb3A-aji=ShlJ(s%26O9%Fw;zlUfVRskMFUUU<9F7H`Gy;DZqVt z>F4E7tZkPGW;%0c*~%(_J8(#*Kt6F=gH@1xZ%u#GDH$>tT~17$W{q`2@T`)qj}=>( zP@D2(-Fz=gl$VZL6JyY+5i{mW5z`1Ak+ZHXeow8fP-prM26J0n3a7Mlg_~y0e`ij$ zNfvAE`~eFWN==8~2xAc3RyIQMw5c2v<*o%2TaWMWwXF4NZ-`qUN``>Z>NL-wIif_l zB>gmtM CK4uTm$GeEhtx_>U7jsj+Ioch z*njD~uM+)cPRP?eW>%l&7q$8{>!2z*=ix2JYyu=}+a+|Wmx2l(v$CQv@Q05~VTd+! zOiI~}8clb3$IO)}Yj@lvr&k=JL~M}#!7I0|+0H6s6}j@y8v?hP8(UX7aGyo1O(8bI z?8~*t4e9a(-wm}k6X-!~7asNKq{VHjzv1(RLakjiK2+8wUdT{Gysu|v;HKH#ZgQUu z^SaH<$>oD8V2{Gu%F7KH3L%<-61BkJL)-m^5rPv&-K2Vr^!TWXuGm6Ov#X&MB`X7s zsffGSj-Uu3YqG9{1o3+}YhL}Sc$ktQm~IqG_5l&5L%QKy!MnvsBD!z?ZU&mwFXv|I z=FaWS$TGBh_NQKUJuJrwc=P5>w rX(FK(VBhOb)3=L6rerZoRe>Y_OR zKB@bQqz@`t`wFN>L4tt%Q)U0!*S{?R>ErHA^nN<9d|PyYgI*Zh>C4n7Z+M&|9WsCL z0yyi0BVvX+#NIuN^5mj>%pU}pPaUHC#Z)`tT!4(K4&|rUO;$UavNl(r(hq`mOJyVx mzyktkrq8DT-LZQCi=S~SOGl^i^&;Tl(7$VZr$XD|<^KY&FuY0t From 13846e500fbfccb4317de34bf9aba52a7ea4eded Mon Sep 17 00:00:00 2001 From: WoolyAypa Date: Tue, 21 Feb 2023 20:40:06 -0300 Subject: [PATCH 45/61] alt dragon wings --- .../new_player/sprite_accesories/wings.dm | 7 +++++++ modular_splurt/icons/mob/wings.dmi | Bin 19828 -> 20686 bytes 2 files changed, 7 insertions(+) diff --git a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/wings.dm b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/wings.dm index 18ea553f13..fb30d13ae3 100644 --- a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/wings.dm +++ b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/wings.dm @@ -166,3 +166,10 @@ icon_state = "angelmoth" icon = 'modular_splurt/icons/mob/wings.dmi' upgrade_to = SPECIES_WINGS_MOTH + +// Dragon wings but using WINGCOLOR instead +/datum/sprite_accessory/deco_wings/dragonalt + name = "Dragon (Alt)" + icon_state = "dragonalt" + icon = 'modular_splurt/icons/mob/wings.dmi' + upgrade_to = SPECIES_WINGS_DRAGON diff --git a/modular_splurt/icons/mob/wings.dmi b/modular_splurt/icons/mob/wings.dmi index 4f6d68199ddad373e42d921d3138e79361ff779d..b79cb3f4ac09585cca53cbaf078f34b6fde03601 100644 GIT binary patch literal 20686 zcmcG0bzGFe+V&EHw1j{lp-886haxBq(v5U?ER6`L2#9nejdU)ZA}!sqD9zH%Qr~dS zd%iy3`~CCo@3%G2v-iw%&pp?5-81v-Clw`GJZuVV2n2%n=C!mM1cI^$p7ZxHK*_D; z)8F8Wkhi+Fo3y#Bsf)Ffo3*0@1mcyN8~a?jlj}jq`ngu>ER__NX*|n4Zr;})#aw#2 z#Cx4t=6JVSEi>8EB)zE}&v$)>DjgK(7Uaj&njOcZU&hY7eYLvK%tHF;TkhvRMh$IJ zQ(}!{?H`G5?|xYEx&NgL$a5fcd?)ZJ!7zXK;=1HoyYSuD2ZdQ`4^4-OWq)k^G4g8k zv7e>*E<4%l(sq(?Py55O8+2G}Tb*#x^$sdq2Q+Yd9fkO8p!Ye0c$Ls!#YiaHkFYlH z%Hl9PYHW$}7}_H(=@TvLQG}N#A_n221=B-(l6JfuGAE`al zpHbz;dN8`6Cy=(;_@E#sE7~Dhl>_&yhUfEUSk5P+2ye9o3YMzx!d2PQVj{Uadb|{b zwd6T&rM%cbA5@Ng)m%u@$n|=pVwd|O)rLud0(<%Uu-muA)ftIxcwu*b L z?aJZ7!GSBa#L$sX`g#*N?bHA4k+m=6vhvYp4Y^{(Mp;4_?~Bv#{|#1MpB88#2o4DQ zoZ2bw3Hh9|v6|d3x2u*ByV%xZqp5lOD#9?q*UrX9uEmy*k8gDYr)*tpMdHpxo+!>( z3%?vY^w$+0)^)hJ|CQGSXY=GqZ|io8E#sc)Oo73jk;%h99^O}yhYE)!x|hXeb6eHk zI+=NcWNg}j#EeRbL&~XwLEyvEe7!6ETh7C?de`*<_v14*?efftH~9=z@pzqFxQu&a zQ^24Sb8hhob3ued;%SX)US8h#Ct}8OvtA-Lol5jgHwqk5wsQN7JIiju_N6|5e`1v% zi7xZQh==Xu #$0T1a9)^W&Q(f}1wgrO7GFY<-D*D*D#vxSfLj zSAzYo@JN9fdii)->Zp|d(M?{+fK3KUY%$|r{(H%YrY=zN{`qoL%00;**T&T-i5sup zo-gkU7bS_tA>#_(m_h{| 1kYN1tQM7(O4om|NHNQt?~tx|(VjOJ#=XGAhJfxfGKaXNb@;+TnQ za=B{EM+03p2vkXyxWBpgrSY<++A~e(R7I|f59AU)Yv_fc7EJd2?2{eWHYt2-GNYUo zU%1MlJE(-CN`9}|;hx{^$N!2)L7}>8_Ehd8lRg;Nj%_xTkW0?H77d@Y_u=N*{`L-x znU6p;#V){I4H7IqFvB~l%OX5hdI;T5w`V>hQpJ4YBi!y+*bTGEF}q)#JKsHJjT(yk zqvKq?slzkx)fN^qyTY|)Z1UHQa!=mt`WJ{YQz}iG&)ok6j@+FdCzor3tbAJ-D-5Cw z=hI6$W>7M4D}`rcGBYGIhUS_3YiiS* ge?3ks<%@-wKL~NkMG5-S1DX z6>`<=q#u{3R18xtxl~a|amuSRQI_}`sodL2gsI6HG V(vpKnp!A_M4IY$4l zFOv5hA$2aRpNsYgaC-AIF&&;<_8zJxq3?oG0fEG`>Abs9&L8_4I>&`em!_1^#DU-m z#Edb>FV$qD W)^*M``nr8QAoeCNYi>Chav%j@#^J4@$xiEHJw*zEqqL62c5wPyP@y zwwG!iT+rS@`m>|9HA1cAz Utu zG=={ILaWC9{;0AX;trhZebe=B6^AiCVl6p2S ?Spjw3} zlSY=*VPUa&jEG9RaarcvNE(S!wL VhHSiI(g za=jtli^T4BE%_x F9--M$Q_#M*Sp+ny*VjEAvtvE{YDQ7^b*B~Xg7I1 z2Y`7b*tT}KKoM$EZYRiiVtw$p%YiYs5a32A=yG&_3Ca#(s${ub)P=c`vzYA8J~Q5u zv(Ws!ygnt%URxy7_jGHG!xk9@zbZSy>~(kYS<684Yz7nDMTh(@P8(}c?Te2Tti>lx z#g_&NT#qe{mr4zqFS>jgp4vonp*zCHB>xLT;eRqM1v~?J`qbu&mLc?2FI)mS5`~L! z^;CN`s4|ssu}pKTjnXF1*=)8EAi!<1qRd7)NS5P^H`-FS6Q^aUn!<073Q 53?>jS_ Rin!G%S3Mf9#yx#95XiQB0HFCCGzn*RiDeGJtOaWu@`Sa(h&SFV& z@Fu9MEs>0(d&=0u+yg<^HQc}?Im;4X2uYMt2u?pnw2x+)VT6}xBpN3EfVU#S24G{o zT01G>GzXKd0-eX0j!#{}6cRFoTrmj5jvxF^6$&29S8hxz4*h!l_4?bUtH+@Y%)FnJ zC$RNmEk)4hwD@2tn1JPxwc|`>*Wik3uuw98*|=A#xL<>rP?Q0vQpQ&Fc=#p#P%zPa z@ukUv@(;Eoh4{yNi 9G3lPZ%qFc9LM=sn_pKpqy2tX z=AIFcw(P>h`^p<(S@_Mm*NQ=jOT}RbS-*_y=EdpoOM-iAUNAvFq+4$>ZvQ9O$-t7R zh7k8-`!n%F8rk+n-R1T^GD8pomV>RCkM~G9n~%Slu*<58FeZFfbrQs0oS-1kY}tP| zW5rQF&w s}qRJ54g328Sv5^uqfBOStPxtOTCzBbgmIz9L baL%{lcJR_0xkV z?Uf@G;3J;zVu%S%%9A7omJ9gD6DH$Sbv97LyP5x7SN> 0#(XuB6nhyI|&u85Vq6~agzDfw;x1UuXRe8JfEaRjJA9aQ?K1yhq($Y9j z)$lv}+=tO$Ass>H*?iA3#D+!TYi7BaG`=cb%g&F5Tz=~3VUqblMX9^*#?9|^v3_d9 zh+?W7T9)06zxSJDL^2 QhH*d6X$b9 zuIJB9;;At9g}3EVQ^N5MKVu^lGr0^JII%K|IzE$-r=ZNoNcTRjuRwdf%PP9%x_S02 z$c(JKtjqdX1Q>B*eZupYFTK}Ht!p`V;Ray#+k7RHldXwzpOT`YaJ;IQWle{llUk+3 z0@}P=&{dcirDnU= Bclmy-t4hb_s=J!>R5axgUhyC2yB&x0&2K4&MeaI9%Z^Z zlRVnCT48@%kL-Dq*VWk2fGgJ4-@x6FHETChc@I+VePZM0es4W-wWzE`7_pB%@$S`u zbJlr*vY*GJ+=z2*dn)Xfhh5#D{?hf!j3rX7@Xm|p=lt!N6W*HS#Hq?|{XGJ61-`YP ztuC~=!2p=eT5dhY5KkamOjq*lrcF?qk}Z*BG3N__MA z3#gW!@$tmFtn-bCO)(qN_=w3u# s+>y=$WaB+JjHD61 2}3@?x0d8zLxufn4i9gR&(4aX#F4KT>YQKt9goQV zXl;d8S?7{Q%lxI!86SROeiMMjJj72sF}l*l`_}fn!tT5RUryKPg&b69L+HsR?d7tE zx7+pgHTa>?osmt4`MU2be6TSq4R*y6xg-0M^9Qi`D2E#SxqXfKsE0Vq^kpU5 JYriD1`0LjE7ltFXt8}sTL)m)r&X8H^uwjAUiCbZq;G= z!g5^@yvzsH`T6;l>}TILH?6B-FjG6b;%9;KOYz47dU~C;u^+f^eWWq{LsYi~GUN%= zX;8krlMvo7iq9`e1%B|Nlwh*XF>jEkSce^;c@-Y2{)fX+LsYk>$i#zHx4Y-ggC0Rv zTc`3eLSpY-NIZ}GHFu68Q$b^7bpB;s298NUjjnQkoEz!j=qP{&YubGX`sUZ4&M 6mp0|Up(ViBNIIr4s}-yW+S!;F57=E^%?9Gdgc_Vu`Lj^?g;8>- n8e2 U-Ak}Fe5@uWCRXPzvX4Y?E{BjALIS_F zT_X`?%af-D8|fJMDA;8?#|n?8P^&9-CW#{O7KtI6B)1;V13i}m)aJ@7%#w}|OS%K4 zo&DVJ-*)ocL*KW_Rxn&zt^6}3tewdI@q56Q^|7gev$b`8NB@OG2LGlsJLj$z?&U$I zPt{{i{KD3ao%T)Zr6L#^sX>eHjHt7{x3~A?!R}qTkvCf)S_#2)!!N3%-S;ThPJQTs zf=j=j?_WS#G_QPwkc6E~rzzcmX35TZ-M2M=Z!b!eSyX8+YVhSU^|ag-C0Mo-!v9gr z?v5BFFl;VpY^<$hr_pJDNy>HW>TtDR&}*O8!5$tmHWqRM$@K9d*#G<0(o#&f xXuoXOIC$dvP+^dB{K}8_L!2v6`faP)UF{b3;v=ed*o^VI3ufz##^9kg&lO z{DgTp4*j&oWA@5*J`!>Mxi+Wz3?5{pLlKem!jH 0xl@xYQfv2g1jr%*@x~y2W1aDY!%e zkIF&^De8Q@1^w`Og}oBAgZ}E+viGl8Lt?saC3yVtA@mX5{$G|J+=Nxo&<#`KRrH?= zF@(=O$(jY7;7_%%MLBJeXW*;sm*2%~O?@G5M$;N(f8HRUmXl9LLQUg DxMZ;K-Vey Z z8+E5A@u^L#h_3PL%ySTGtgj1u5x13ASX$(YeLVI}mo{nDi|)3a#TkRUY$K1|oX4B{ z{KwhHe{^i< Fs+Z*6(;qA{wR!I3L4m<4Wu= zdQ(DnQ2tQ+2|V%gd{lxz&rR<(FlxKVcZyqE>SwF@YFrjeZ>lB4pi7Q5vffGbW6#i) zJ|_JRB`9kJ&5&UAVBpt|T)=F{SYAJ$ndUj4tFSD0-qHI=DdFf%ttZ=CC9|;Ve^FI8 zFO1}XEtFdyV%e5F iR zJI}}4ooOC$5z1(5;`aKNq&H4GdgoykmQMFBqisiKj=6O?u;y(cq8e*>%I!^SdZ=|R zY2~)R%Rbj=154JD5s}Ri0Y>_@6@rS44~Zmu5BRNVZ@z0Mnj1jQ@dDj#Gk!Vx`G2~v zT6ErwuS6zs^wh$E@hHqZ4|y$z%C9m#1kZG@3TJdg4a>(4^4Z{nyktUO>tsT=MwI#Y zxk9g>aUD~XlllxdH)ATZ+o^Vlu{~(lb0cM)` MYmlyygehK`)j#=3{(cC%s+mQawvg z3$blNA))qsaq{J4;7gzR^^^xi7$jsTPT7qv +$i}k!-SS)XR^LehBPVR~M zLfO*#!zsqBzAHn}S>NylMu*wh;V`l=^)sDZfVrc}ER-Ez)n3XK-gMkPna*(H|M0|> ziqA}^tWMGOk_1=nB8_xd_a6rIF`K_dT3B7Q#9 kfr z#{!E93S& @*%lJYI`rY? 7^mJ1$?Phj%1Fm$se%1EfMcGcdu@u0HT;XTvuDcq; z@wKyv;tSL>Fm)>5_dzrv^EXD+mE>OFZ1Z9tzO`PJM4*j;m{ RpT PDy7t`)OyzqqIgRpV(+w>=JhUr${ z2j5>gxDeeQ_Zu}Ni9VH$x1YBn*DB52=_J5OQ?_TY2939;@&7o#@(diBK0Zxqp9_8# zNF(a?U}tBCoQ6i$$43O8T6CkgZ9$@$1XAv1{YRAsis&~N uY_P;jJUm4s+Q z2K5+(r-s|bVLXO?`_hiHp_OmHxAW`kSB?Zq%4kN-&E @{`w1MF z`!}1plFuQFvn@CTXo6-2-JKVP9QFjTY(b=deR+B~57o=L+QQO>MoV^qQo|6?VF^kZ zq0Xyvy|#CbxvwH}ws&T?NW7^_Rql?vsGf0$0;klFkW6Q93NNoqj>o>s=B|CG|3jW> zcr`mQJzkjenWqdQ8}lnlj2~MRJuBm= ERjRk^ 2K*o zQL{*w)C!oaRd4+J5zNNK(g)Iv%G5}j98Z f z^wag6j}=#Nm9?`Qd{52)sJ^eg!h o?hf28V{YL-_I>ekISQp zIlYvjRhb3k$vo2B#A6D2G~k-GMc!nsly0cv `7iEQeIVLc9xBa`oX(Gz2 zNzWLv(P8Yn1uL$1`wZ*Vs%NX5f$6zzfHY}MA{$KG(#3qriA5sBd`=-19e?jst {!E#Aqn{zMYB`rz49{$Vo 6G$I5YyF@+j& zvgI}!Celn}h{_1QL439@CD|dh6yAg+=6#W*&Eca4OY3mu2hXzd-tFgY0be9vgqRlA zR@SgfKdGV6n0MGl4~rP>bTP5{o2v=xD-Wjj9g!ChQQbdMFa9XHrbkO=QD$=-9B zv(Nj+n}D!8H>mYB6qtkWO$W8YD>_f?AKaq~7MM_w>8B6!!3)gqYx={SIOQv^G6EaJ zuFcS39`w&$ttpLz; B+-o1U?FzAlJm$EuPfLzl z4>Q4t`#y!e7XZ!T8=GNt{GBtm?X+QypZv~HUiQsly$-b5_12&6qLU_hh*Q7$GY-Gh zWm?7+I^1{rIiyX1#s}Afu|x-+a`lHmc57< T>@fBB@u(Amxgb-oR0#gWLU zAA^L(3TYTVZr`2JsryAK`Nx@2eMoy~;J(&mfPKF6eU<6OtC(NMZUoI3nXSBo-wa#l zKBdVJc*mwsy(~i!slY7hv4os+UY?>bMdpM{X}@=y+Fj@&3!or@r2F1Lk7^h*0;qpY z6nR<0#pfDJ300Xf99>rSNd`7|zfmT$g$TW07;ClEq@DkihB5i# (dy!Q8(M4s7CG~0{d8C3KX|s# z)#ofe=Z@9yIM^L50)3k*o} VZjfny57&*U^lfU=H4akSp)nlR6;Ojcdwh-*0Pag~7 zRt$e8L{e)20RZ$sgV({k86PsAE=GU;$Owdpu^-^-eFyF|W?}VmQGnuOKo97YiJ@ zjCM`wLx##mv`yB9!ISGGxRJ6>cUS3IVu)8`MHp{Ox7XYIhRvwu@jvnQ^SaEEcSF}y z%PHSb&QM`E8E5jt;X3b!z?+Ba;@J=C0`5UVQH|RI->Y?zP_*r})6wl4kx*7KLsD4B zg9K1&%FoYW&9@>DPu3+Z!#+!#vV4NT+x}lEfk=FdsrHQQ!<( H0P$@LMFY`oW0p=S{V?vc>A0TQch2Ioj9=BI=UhadJM)y{pDO)IcGm zVT-TOc-E_))=Lh+t>^hhH@Thb#{3 z*5?Ymy$|8qry0D3eC{`(vEPhvW#2oJqbsSFJllD<&xDZ-uPWXsaj}0hWU+L1e2f-? z|0(4HaaQ?+AMMvrP)9-Ic~thUu?tC47>KfH#`Lz6xB0YmI**|J*=&2W&6I}c?1o~4 zk|rJyNNI*}NG*ZH2j>%(aj@*jP{C5;_54eb*2w9fu-Z#P=wB@5l^Tm2@&ehF*3)^7 z(K-ru{&%7M5!IFG_Wk{2xL8XeN-;2strriXBj<~)j~p9CKcD!_lviTdVC)+IuwG$r zSCN6cH0jBNfQDGfJzak>$~J~1@I7n%RT)7Ufyh@%LK!J~7ICLQR?cg6t9z=T24;BU zrI-$?j?41}XG0osLkW=Gq^nx;LXW1o!7E@sbHBc17W;oA@E%cB#i<$}flx>d04FW% zYJ=pH ;ucA-ohOo7@~w+dkJ@ zFjuG<*+QA*(E5ihOsO#GR Fgk&qP4P-SoHkxjQxy z&h2+vHn4xWRFL-nHi@eJ_#>vzxcz64B<_8?cI;` Pcb dpo0>Q4zMXKNKVE!i{X8nq0Xyi^s_g>wP+>JhaL0R(1HPP |E4?(Iezq#)Ml{>T1D!A zbFqHn5cSb!xlvfqaZ&W-Vm-r$+x}#K^hP0bpLLM+vF}+;@ti_UPIkPzo^{8n+aOYG zk40US8WZA++{|C=@Y$`$gnU)Xe<&K?E{*a}Gfk2=`Xywj=jfTG6Xh+%A}9q9IpSil zX!2%kP*sTS?L!!04)xzcb-6q2cz@<+_}lPPJWW%YYA|@}^2^g*1r;_YRr+Xt5%%dF z#F`T$iVwf#D5h)VubUpF=6u7%q3SYv=FQQtg3<1ZQufxm=k?6`8s*JUYx+9!zV8cy zc?fl@dw(OHV{WYX?e&>_yx;95T;TR*Q#nBQa2D2b!fsAJ(Ms~vMTR+-J4vCpGC$qB z@9J{@PbYnuyPKO=7XG5^keJtUgh08&f-o#*)T#Aqm9xU{(qogYX8Z%cx0pufrP;!z z3i*gqwG*$1D(<}e?|`5c&PAsyaUB?9ZtkG cH1+mj9)3B~RGCWYV5E1vV?t5Ht7$Uz4i)`rH zyZXJi1i#sV+ZkO>!df)WAq2-apRVM#mcWY2eixb1fcN!mjjeXMaeMKq=e#p!Ji8u7 zTeGmBu<(y}732`(i^J6*TTBK<#)lBIDxG3ISgHA?ry7p_n7#e^`6PRHJ0%l(%VqVZ zN83#7rG6^9y0Y^)9*OLjQm_D|_>r0ce9=Mt8h+z#I5uWySqg=}HkVzTK=tH16o>iT zO8e8huY<+Py6e+9=WZ&`rAU$8wztY+AtJkV*=7cQ7gV0}L356+R9a<*>@!NNih!Ym zL^j@4BtGiVvu-Ha`f2?ZPGe!%)A*UWK)^|0>ss1`5k )6?6Gg`(AxdDIGJ#;Qg9INoc$6_Hvr-)vDj@aA?bRzg)}h_?>1Yh0D0@BkRRVRiPthoUk;xkZl-wEFR$hh8%j zZbc7IHLQPIsNN~@1tqnByHU8({~Gyi)5&(JR?optId@0k+rnwpj2(}}D4)mW#1{YV zvM_3Ss?~%X=gsjg8srMOC}Pu~ppf6X7Z5OVBfY8lgK>}2dXjO9d#hz9qgKc;p}X}{ z>WJ)u3)|eT*J-7B|9%gheU*&w UF~_}4sQZ$j#A)~ XnYhu^(Q9H{QGe|S$`ABYdQ)YObt B{-u)^lDl9IJ(_!(qboGjm`v8B1W7R)CuttfTMcQ*$i4_l%K2x?D% z5^S@H#?gYjsts8wSJqp}{xbJ6K`9^2vlAl=gQ?!Le&N36`)c%EJARz{^jT!GQihA8 zj7pM#WBNCrV!bi;P2^Ir9(!}ro2oC7kt|qClXpvz$79MV-a|(KLv2b0?nkH8RBtWL z8w8xz|F~FV)9i|w`W7HIRO2%KvB~j+4h;vR{xc%19JO0ArQ1QxBfiE=``oAwnwv3` zXG8&ZN}Wdzw$c+ih|J# ${Mh6PJatNaaw?b=om1{bZeQ1~a`v-MF9scUV7rO#`zW9*7bLGWz9ZhTo9xwT* zR@I=nt*eV8?OMA>v1;k(g)g3#6}m-~BfBYJ8Yb5=Q&RQP3Qe~+m-GVhScmS5$c@YE zGq`Nld9VT`Q~k3&72lwJ;Nv3UPh$a956{Gp0?@4N9wclYjRg>QcLoT5@e(cdQut^k z17h|(BuM_&q|)rdXRkR-I>h=&mfAX)U!|QSi6jGkEK}OK%l4SUJv8 zo)NhnqQKf=Oqm;ct{mo!biA>Iw52fxyifMGfadZHn=i0hTGVoC7kpB%pwd4bahZcS z&@;+C`lXxg6cw5jGsB`-#Cd5|f8x5XhB@fQDGVdmqG7^Y@?OI4Gk^CtT6XsH)bw12 zCvC#&!$H1`PZrMuXA(a3CS@U$)-(xjttsw6uH~e}@y{{*Cu_0R{pm>rn9uwq7pu=; zA=W>?NI@QILXtOE1TW}v;pZJr49o)iZo&Y!=f6wFGqqpZYIIB920_D?5RQU7|8M7| z|8<~*M^v= VS$^QcVRb=XeeE1GE@dkgYhKcaFkYzo%7iW>BV(hh zBt7_CP_W=vclX57l5xL?EbgMT_{h|h00P$HUa3EsjRbq5V^jX@r #V1ly240*V`h%egC&+BH$uSRIDqj!XnE`EML6pf5Bb0R_Rsrp8>x*MuP?C9BqF+x0_9O3@oyQwumY6Tk){L5DH7#xnPw!7o4iaul zJO9Lk tAjfe*>WO!~4QNV_yb30vOYFAD*dL&YyO>MKBqoCjF-~1Ob z*mpEX(JTegUicDGd(N{kjoFIrZCGCsFlq%<1pug{bMt3JQoI!RR0KO~va>sV(F654 z!hFREbOhq$k|MgnOtsAx Ff~9@Dbe{AtFJ2nTVcA Qu9x*YV_^VzJnJ0=5#M- z9$N$It$E~Q*SntequOTQB!(f2s*lo7dn~Hfj_aEo9)@?xQ4lC42@mbr@grVrtts_| z4ENvb4;GV{XcxlV%RsT=3$!Lt+D~$@ cuS8$N*0_x5R8T{^@&4hk6votxDe!oAKOjhbrmtE#sGY zgZXo_qVAyw-CZ&;Qo}i5i*c_xZ^Hb$S~kkG@&s0W>0G4$J8;X)t7k+>6PJ$rrRN>` zhjT;P)O|;$RCceG5z=}oNTBcLwd{^}ZEZW3VGcFbWCH))t5aLoj~+i(M?NY+9_!H~ zS51|6^XTW|s)kJ~v YAhIScs|4d*di4}A=4g|8=x zO> 8|UP_L@zYuZC(_-!MumpvN>b#RQz0n?r_moSBDe>1LKQ2i^l1B@(HwlvB4c$ zzhlPzC`XOC8>WXxkq^Qnx?mf#|0UGFI2f;4ecLAxg)Coza-^rBnZW;HY-WkAyUy3o zj`k26tfwBWQdF_D<5m$pj;+J}uO6J0sa~mLLem7IF>!Hm$q!T7PYjb+R{Un{NJTuh zC8s%YY^41!U*%q#LKFYMgvpVdUwY(kE;4R)G>{WnatXN~|NQw=Y1s_!Hz9(b{}RyN z3ujq{#WbCUyO_UUHL106e^8*$&oUtq2vs7{?(FRRp^LT@Vvq5P{D|Spr9RH2)W1mt z|IgyX@`D3sjZJ73-}YHkp>t?hm eUa3uccI^HKyb{vPZ?}%Y(OAxAjta@;o}n%=IY*ycDRewV^dT45aVm) zNo`rbi%!(m6! X#0FU0>&aEnI5U8mYj52I(>5UgKU9 zsE=r$dwIMW?}GBmXmN}9+53UAw^{y*Fs%vQd~M85b6;Qmh{#AyeM>jDYWmgp;N(6k zS?h5mFCDm3O69CbLmRV~)4^2)MV(7ryfl(ZBs3@}=ySK?@iL3c(?Nhyy57a~_j5+@ zIx6Ia@KfY+$raWlw`f&b^zSZd&6FkX1w#x9!dUS2#m3GK`=x>W<^1Pbu(C(@J3}JM zj$d!gr*ejk5+S@1;r1XBYSijaRj-c^xwBFhyxP|VBos>9fa7HQ{w4zPHZ3g;To*u` zk22Xkt1bYAfYYpI9!jP1p9O+WjO#TUURW>~yKHD|9Q@Vr<_%5`=p)m?WIhMRZ05;g zolavl%t@&q(!y6tnA#u|yCbP=ZR(BpPa&HJ@@0#KAc3k{H=?u7DFbfQW(!qkF;@yf z#wq;y_3k;?8Hy1zyWy_FNj6#eohIw+l?ByttINrq4>x(-E3^lE*@-^I78gk*oIDHE zn)PqCw%GSbs_EW4PBztv61$z F<$@2X{9a@Cyrnw&S;5y#JIU z;+>O|iiR-r-P;?f==6Y^eln}PN;eM=RHhYoHqy?Xp4V@pW*whht1+y2J&y7dG1bD% z)qkxsqH~nu&L#M)PEI8*(w~i#C(2Q;_ky6|pA_LM?&$Ec7Th*R9SjS9mgwf`nQ**c zGWJ|^a;mYh(fM%Y4gaKuHl=l@TlJRgjNPQ2c5(kBg$lm?tq&X3xwM;NXg2K4%W1 zhdp!<7EJr*Y|d=wW`pRd>=CA{5vHfnAMGF9f{pqELq(YRg9hrm+Gmp`daRoM2!!aa z<^mXGed|Y6GHM{efkU?Fy$$)exQxxJW_0M@|NgB6oTId=X;Kml1UYA5l1udKX9Jbb z!5M&BH!j!_Rrnaei&FB>h(LrSYQThrg$EjU-(<#jD=@s}7KC7%7iMRpeUe56-FEe* z{@uREn`TQ`eCM)5+=MH0I{bN}x~4pp8+S73<1#!-{=|TUl&3>rOa-L5b7?q;Jqkh4 zd0xBPb}j7?31MZaGRnUh3gBRrM33VgU5zwiAi^S3n-B!@<#bl a1bMJ zGPoOll{3ZmQSi-sHy#LgPfxm(!ODtSCQm<$2dFS6vbIMG+aRkkSSroYhgeb_!+gb! z_>8Br^l1~S#@E5fzURT%1F5-3-1rNLJV9*i?pm0ZM9a*At;t6XvqBh#jGHi4VlcvR z8TeDj+g(<()ciriQqXk~pGq{NUz<%<*UdYZjMkbro_JumiOw~3-RagAze@{0=*bt< z+=F4X7=?v{;wjYYQ7*!qHuhQ|^Kc0WSR1)VW@dVgvnq;$?{cU@eeEN?Zs83hq^FKO z>G g2d*g;x% zuV31{IG6-obZsX~20ccu8*U||jVjQ_tqSPkkQHN(bPIvt$ycX%q|nDlja(1WNkoMi zOICCXzm@_k?e8tniTNi_JIL=0L5qV|JiprvG-Z~RDfd$OCKD wo13|K?pi6do`%y|;PBZM(=_)*FRHBGv1SYC!&=*`#4x{$cC1AUHU< zg{=v|HVxQLS_Fb71u6>i1^}T$5TzDw@DZpuFsQ!un!TA(WQbv*h C46C-?&}a?#fXQ ~e*bEq^;!IS40_5mLY zgoO+ZI3SkXk6g#?)5Q8#UDm8-9dr#)VgB=}O`QAfln}K-5@8V$KN0%m{?*}`nNR90 zs~&2oCIINEfb<9Vpz$VvYdLDw2J{U$@fSXEJp*ZY+?739n|Xtt1RHsT%yVI3UGA9J z*Uu~zTM L6D9&M&QC;%W5#<4vbVh+(O{Hq0Sy z$3+KDQFpR=^7`56zTfv>*lzprgrq8h2Xq-jjj35k0DVX3M3Lz0GJPM$h+P1G9;ND= z?x@V(bMhN6NwB@ n=hdmOu&@*PQyL=?Pc69t~BmDLWlo>(^-7z;D-a<|h9nvp&$j>{!F#cd2o`>qqo> zU=HRvoNlfh!+A}DF9zMx7P7a!E&Vi_iMjDbq$fg4eFH&Hgayd!H}*WyeDCF*^oX#) zoBt&JRE5#I_vSJ1KPA82(#JB~=Eo48u~3i|MZf;(p*y_$LB@KZIE>?Xh}I^rL=Q&c z=jX=)It6`0&N5W~q87uC6>)H=&JrRg;QVCozWV-RvyT8ZbcGPYg$A1+6S%*!*yRnu z3?vXgZ<}{aHo%8mW|k!2Jc>Xh^!FfKu05X-Rp9*{2(YOI;hqf!{To@eU39?&;{KK2 z?<=V=90IV^_c7#@2fl{tViy<%*Ue{2z5h(z)|(y^T^oxd6v~7^%Y`XCTzxO7%DRE_ zIMI*QXqezM9|9o|y!&4OtQ8mQVvw6!h&>oZ`Fi%;=~CG^66!cz-hQPgQy}@B5KMY# zB3raANsg}xcx;8rapu28O}gA=&z-&AL~Tj8<2Gn$XfiBu-1!|P>kb=3Cz~#|VqZ@{ z@1enz?=g7wlUM*p*Be&cWt)p2eeFkO*^KuaDZ7j{6jV-RDUV09WmMuMM)v3)YID*d zy(cB9BV>|pSFptb=L~Krz(9h(0E4_D&3Rz`2zOqbtj_uf=mgS@%*Cy!R$q-YL;S${ zgnQT513oS(3f~bDPqREV&CS@; >~K)OH_#G4 =hvc3gufp_nK6JWv;1 z`(qcC5`}3+R^i^g%y_;-f=5C91tJOkPhxr#!vg-nKKS@7*NFnM^X(53m(m6;D*Ug# zkD%ag*YQD&;>)Z(njz5)Rb`>_^n%H`IoqDSCkdTbjAdUTi!(Dq2uu5*(U; 3<;ZEDrV3SFOX?MBR$kWGyPLK(IWb}J$pa;9&Rp>}$+{rD#4;Yx3I^t`u z4~3Hykm8&GBoA%szt--8eU$7vHyhbel_j>B0MctrIx*%w;eO>FvAWE|?Q^ACD{hZ2 zv}!_YfCJ2{X1>9NYRCS`5bimvU7_==$4%6a9yyB$x$<*!|E<%n9{msPh6?inciuz~ zt sSqx;2nCtpn7mP*A<7l)z%hxr{KPP`2r|rx-_QO zjEkH5U8zXI5Dt%6S#ZajdMkQsM2-PsYm4Pgg6Q7HhOwT2EcaIJFH!+?ZZAEYqwFa0 z&qZ2gfMQJC+( Zn zR9-Y5w7I=~d~I?+>84DbL$^6#vbL0>*4>pZNH2;#J3G5Hhu*1Ok8^;#vd@hBe8({$ z9Q<_yIgqC`0awrcFX!MONY%-4+_^vwM@t$GqA(V33Eb=zN9m5kxEIy+E|T&$Z4ob; z$)K&o T3wSGT+0}>n(q$wgV4=Ru7IO zD#^(IGkI=H;<0@2Nm{!A?M0+~ysZ^rT>JV5YU0}zFR^5lB2&U% yX*B!?PLozP>Gv%yk9}eO}it%S(oZ_Sl%oE z$^%3fTRik)$I+W>60MwCCFeU8IXRcNkB@zn-s$Nn#oZX?Bj3DZHWN#M @-h|kP n&?p42|htDcB zs<`528+0p5T=P`Za%CC^chCnk>N|Yb(>y1usr>wAB1yKuE>-B?VznO}Ko4aMr3?Xe z4JN@%(&vVOU<9lSrfC8F1JDKkp8=Sc3W$k8SsjkIW`H|v%*@ayiQ~-}x_5Y#7c2yp z|63i`9?oR{#)lkpNUAquDu*abC8wMzYvqvSd?=DR4oz5kMU#4a-%ydM vvthe}4Zx*YoUozPt9_bALYf=e|ETFsh%1I%sDG z@VzhIst)?<(v2{Uj(}>vmghEg*BZ=+n$6s8n&(fV14`D!r`J-wxJ7%f<&Kp%0T-b% ztJUM9p^H5TPT+gE(1=7fRb>Z=YwRk(xIfWNB){?!YEymu0rTkgY`K=(i$yxh?d#ih z%U&THDDJ~}_NT^B=G=%(F2)GoLOQdhW?;52BetXzAYE~7WOKwHj -fB~t!>^gXJD0>u=>6F%g^s&l jOj^B z`K9N7&e@)Sk!TRawOysc!apVFuS<)sP(a~QK^iJKRU3;6v999uECw_1ozzl~ZAV?e zo4>1(SoqUz_Sqf&9?|QYYY7ugLsH?{ieT9iaM!kcy>^gnu2BDEM_OLgh}0rInvmx2 z{ahG1xn*detY;ehxnX%%N-?&6Qr-#R#Lh-0oaVo4Lqi?my|0~a4oX<%G~ci#ckql}OK=!}zDVM*V> zW`oHH^qCFEn3|8zGtS-Yy41a+2+`MWgXTkubYDE4wuEt;+Tm^_twA8PYdej9=$TaO zO~eXn4v24%P%p%mu{V0qeeuyypVSNpUbFJ2!x*fC^Z8lN%9NpX=8Et319}5419t8i z*E;)_m=(Oro*5DN9b&uTH%Nkhy9zP$?Cb(DpVPtP(0AxL6f9x4=eUw3=2$7jTSZRi z$6;_MfPk=0D4|~Pe?beY@E);F7-3}(o-_@T!#2jcNtiv1c0m3V5*4S$u*wjQmg42n zQbQ*e8xF9nYTUY_zdWR_j;L-9Jo1qg7$7b4x4);!yh`O{4vVN|BLi@nD(`zy{@Gez zy@Tqz@|G9`Yfx>79;aT=YV|OBX@(cqar@V&mOQ%s!$V^-dlmL#$vyl0_ldTxuS>PT z>py4f4)W#U7WhuQic0gL;ac zlEfy_Nb0C zkq|``v=wRi;qD1{2cUn@1xOhS%jEUO=+YkpK@SD9E%R?*)tgi7$$#ug <&dEL``pRy3qGtLj=UW+#_65Y5w8qHCfaDw0= zIh_@D+Kk_H$G?Rw8trpZ+zmk1y&Lh=5swbzUvStv5>nwkV2XloAy^7Ik2*%4mJz_+ zMh9SdRE06Mf&LV8PtU`LJ-zFq1>!PtIiMEus3``<<^QCL|2;i;1~@~Xkjd#@)|oMH zthz2rEyHsXt*@)grtf|}3G`M~SBE;UZbtHqxs{XQqcM&Ys#?ar^&cG-HFL;E5`g{q z;evsR9fj!`h%2F$rw9yh+d;QbJ3Biie`(!H%8jbQwb^ckZj_!G0#@@4SGMWJkPv>` z{ohPRjBbB`0hcs%ZL(M9DH?!|heMvZI$eHDCI?u?ja_8dc(TYn3f!#PsH%SMt4j(D zrT8+?QjinQY$LFzN&Sy%fxZ3;Wr0T7!EFYQaF@lh9{t31*_MuW<(JaJit~ITG{Pg^ zWwpeO>|X$S6o964OM;v0<|`|A^cwx<&eDTI&DVBjaT`;NrH=x0FM1^_gJfdL3{&CZ zKASnA;cQ!P;##29k7#DwML-3B7uW<+0f?{aq%S2{C$GZV+#)Bcs Nz@EsXT4n+LhA|7{jl`);jx$rM@Q2$P%`Eh_bV!HA`4un_ zrY(2 aO0|y yA50sw3)RfClll@VH|va*|V!B=QhVK35pe& {&PLiV&eTkURyVJPN&rZ`q zX{m6is~l=BEOW|o{M1)o0OX=H*ul$aEY_yTVDVVq+2+otg8a;3VdIqA_w>Oz{*qV# zZdc;3YPL7Mb78S!MH0~rp(+_-WSw*!Q6;Tq&4}`TbhTnZp^zVk>}f9Ov{_}){S>_{ zKQ^7y#{_f~Trl3K45ILX-}o}Rkfc(TqWgZA-nYw(zNI$f AdR%>m*rcdY3JMAzPw6Dg0;@F*tkr_uaJ2J!6b_0tpt)4|E8s^gIjk8z{!ORkHt7s#WkHybVgASk z(`8sg!pl>EhzDRS)OJG3qSr&8tsrPaoN*-kVZ2PMv~thm@mN+{!CoQ^3ZjDPO0G4m zQJa-(r>yRs>wsy8H6#@6PLD--M;mnu@N9Qqy4@#Ts@NI599kSj45I%1RtLWQ9>UA7 zVZZv8Vzp)YJ=u!rtoHh-^g!bJFA>!R&!H3Cq2r;EIRY@|ZJs5vg?F}ySEn9x%dr=I z^;H}w?=+K5_b@hr{=K++D9?y ?(PuWy>Sg8ftLWmT@u`##wEB1cMDF_NCQC{ znd1BJKXcc;Ywq{YomtZ>bh?{<>Zv+)&fdFDog!38L6QKM3>N}{5J*djt3V)V2jFMn z9ya*o)`DgjykYZF({dFzb1`wYa&)zFu!lfAQgdQC9D>*%1Y2A&DfAiCFi>jKNDVw- zR9}o@z!AAGXWIDu#`o)MdQ~RjNIsvlW(#dtp2?ApMr?*GPt`G}c0awZhgu(v9eb?u z< Zqo6hNV zNh0#p!7Pr}wMXEYTis19B RMn>Xtp6K{v6B5YyOyBp z=6(P8%q%VXqvEt}Y!O282w_b}9j~DDPJ*6wJj1uu T#%GW=3Wxo7#waYIJ2Pq`Q20mW7`oHuI!KX zBi`tsdW5kMS-~T@Uuzt~p%SsQ;q)4`)wNYc7Prs+EvVA@UlQ@Z9Kma)7F#(44}PMI ztqb817lV5b9{#(BGK$|5nQgs!xo*fzUNXvhF~y3KUK(3 }6^zHzyak?% zKidVEW%2CxS+p8o cr}vP zYWME;r(%YP{;6yk)ECLtcre$8(&Dw&R1`tQ)%et 9xX%uS(x(bAYHfL%_z?EVGX}r_IE}Qr>p6M=M=kHtA zK4H>;K*n~s{jTAL81!nK3=bfK8xvGFD?~SK$}3aT7Fl|td6chOIq*B)_+D}kd?1Kt z*8T*pdj2#lX#iXZ8MMhji!G)*$oup*ys0aR%i{2SEiwh`ZLdq?Mx^MCM_=!^PX$YF zA5B0e coo6aYRT_eG7Ejeo=wOI{dDDNE{){g3wS)Lm &`h{F7 z<{BX1WpX?i(3OL>q3qi;ZW9WkHcewW#* g_vsDM?kPRS_^kA$^6%KkkwId`OrOqz(V4)~cHO<;vPn{K40 z_t01d+L@boFYv`j&Fx%hS~X|JQ!^^|e~E!=^Uie+4t^8xy{wkWQQ`5OEl|6=J~_Da zMNTaEWb-x?yT)yHL}DDnJ*Rtm$BUSv2GhR1auhqeqGYStHZ?6NDTxC^TaW^8>WnK+ zrsAPfn|=2?hk$`0Ys_Y5`H zNMP$Zg-@fk`QS79iYBlbMu0e}OQms8l_>zh7t0*87443+gi*l_9T{?BKR$!jjC}d{ zjG5d8{Yewr3h c7t4v--yh^@6MKcSSac{H?&GHy zn$8yHzaG}+4IwLD{G`>0aL7`#@tJ+|_ znjl1J6%o=gr3rbe=+`;^n6+}648|jQ)&^hCHm*R{(8Y&uCMP8+yZPft3+|bW4-O8} z=fvV#cVqe9CQBnrRWOQMhlT8^Rd`d22P&1Rb7KFSw>*Jo8up3gs4ze;Pj=c6hN}El zsn-$hIU*{&C*2+P!ZsTwR5*q#fx6|k6XwAEioFZe7|T8RxVTLA*LKG9Fd8!m=)@2w zJL7@F?Dv_)5SiRTRCPH=zmJs;9_++LdQ$kD`t>lA4@>9OQO>dWVp5&>LU$u%*cfvr z{u{i(==t{r0gT3~^aBt^RC^?;$mEP$`RvFV{)&Dj3xVvol4+J1bd~vE+dzVw^Z*n? z0AQj)?xxyRU`U9tJlF^JFJ~H-_SFH9GcRpb2%uvPcvax?$d_`3uemA(Z_nILuGhEA zIZ5T=&8xuUE625w$s#iO7CLcFWe-)CK_|C87YPwuZI#L~Zum>~d0lMQRzg}AA!J4R zaOK8*cm285Hy9Z1h}|K!O|FN^Vb$*s-2@55|9^Q96Mvb%|D5J$x5vdsLfqB$^@0C# zxrjTR`UF1IH%auooroCHbp9vo%Z)qjV~Ly2%26M&{^{q4uz3T&3$q%#d0t4{!~`*j z5aWtxQ^ndCkT;&lmlz%at`nEo1-1$aswksb%a+VdGo`a4^^-P&HvAdnJ;;2m9TRC% zOzR|ZlmB55b^cdszh@&NDBC`yMTYNFBGD^$CL?kaaG|s3o;x!w-tkHhQK1&|rsX0C zG8}53?-vvhp2()q{8K-0IlZu@=+$8dYi_R7$+gGdSqsuOc)2giEqmNbPF`MJPce54 z=CHh!{8?Fban<#MmC$g8D3MX=m^KqNq-#wR5o{LJD-32 pS5W^sJe$F!@T_ zw(PM+pjYSE?s3?T6Zfs!eQ##f9GTxvA)lgYEi{}as9BlXQ#yw?AYmhP^85X(k)THl z#i);qiiONca`6-gOBE(KZhJF ~5b z{D+Jvp_+L8mv9PSRK{AAdrf~=|8$EMZ?fzN3=E8(y{EAY3{1w{OiLlP3ftCqf~7di zq46y0_6_dRBpH!L%ik{G15;Oc{YUmkf5O w!KZMm1HN_2;Y6(8gc28+CR zxw-PRU2Nb{s=^z3j^=4?-S5O64`ssg!u_tAr%<3Mav|=E?4v6jyDl >7^5`Y{rn7vA9AIO*K%tgzTR!?O z<$r#tOe&oSC0u0R6wbRd3$OJhr{VuHEHE%j-V;|}JE=dyo&U#Q5lsps1Wij-&+UvdGd#4?TS`E+ D*ALjFPJy+JP< zrK0boC?#hq^-s(yu6=ISAvMgRy6EB$9}wL)pUqFG30mirZ1+a}MM&k1&j7#XAG^6; zzV)?TZlMHm%6xN?aZCF4Bjfe l)W5??1KCvy%EVt7yz z(gh;Aus!92Pji(LS%p(Ef9rqzfcp&r*_Z!m8nG~g@sfyy>a_mEJLYXA`J075+?Q#f zk@~pr{1Id$rkn-F6=U{*sJqY4-%OPm5;aZ(FP~)>JONXYazQ?Ej8nWN3ki09l _Fp@lEEV*4{yI0{9>lUjl`dW=fkCFr^$n zqMDQ(AcscBdZ(Xx8kOC7fW`55hXH@KYqk0b-vuuK4_5)oy0*XF cQPDZ`u07&WQ+ z`>H+M-C;j)JhU|>G}Tf7CP5&;5Rv=)D-=~e8*!SOlm)X|Ruz=`WqvDGjlxq`a`Dpaqua?e|D_vil3bzPe69M>a;8?5IRS9A zZsckR)U+nI{}Q0XM=WySjxW_$vs-!W>9WNqtz2y0RtS=oG&atcM^w+hdcgC~pmni! z)$8wcSJI>v!+*X%wqYJYD7@L_-HgmFKFC_pHt`&;9Hmh0>ft%;zwaO6Fov$?;5hqy zx~KH`v8&i#W_9-jx?$c*vd#+Jbfolnt);MCm#8<6OwR^l{Jc!Rab3G{&tgr^%3pK$ zRF^!70X0egHn+M}n>X2}AAuR0@9`@+^_#{3HbTKVYj?NLMl{;{PnGSPS9BDU#)aqG z;XA_CPvgU<3h2sGigsr=Yp|b?`c^rW>I-5zV()uR%sKYn3%j830c*;&W{AT7E4mdq zgLuWBw$5A8Skw6x1+md=?3_&Y51_`Ur}IS4S1_Q*oARe1I`dmvL`HJsbi~O*NupGO zWaBPwKV%Ed2dK%$kc`WftoBr{_6X2h`95UW*vQ=ayce_=IlnV{dU{#_F1%|br_u8` zH+p(OAxpi6yM}Sdz537l1ti34;`QDyl0(Q8b9h`+t+^Gx;?UI-k#-a$bE(IvBTigL zDmmkqVFC4X5jJ@?nw+M1b87<8cmmNWF%F&>-tntHa{as`&HEp+WA{2H QXdphXB=yW` z!2@rZ#VXsZL6&R_cBt=BfK;|QudqF@AVd#V-c3jl30J0Q*F7&Kg>1A==Vk=QVqJ*x z#B}SPvr0H&8X8 d#(*{LKk@bT?GAlRCxd=Il)@KBRi~Kx zCQxILnA>f=x#T?Y^E*C0ySHA4nRCHqnMB%E6&-R`ifR%JjfYPlN(CdS4yJfY*qNbXk}1Ud8{6bcp*cf`E?4EpPG@p{jhLw$IgGMC;jRR0|J z(mef_>NyjMs(PV=+p9}~GNX 5>%vrpf8I`Nc0(ItA zgQ=T1n;T_xl8cZ*g)iw#^i<4A64Pe`JZ$)dOG^d|Ess4AH3^5nIWXQzulONqrX9V{ z{7weZd(eV4&%AQK*`VpnGTVf9V;?X;Z2s|YeAecDC|aODqf;s8bune~_Gev-K*a58 z5<0p^jq+=@L+9B;8%pNEr{cf)j)^bJ3+k$?RaZBBV2UZOKQ&0sm_E^Z{BG8cAi wBKYglS@7yKiWasAQwsf@LIx`*CdZGov(V;Gfh6`>k5@1}e#xg)S+R{u` z!q9vw&d;n*UVKuf;D|))<6hH?ybbHR4b#m~`}r1WLmB%PR *e9m^S+P(QI6Ro3qaHp3I45;Jn^)7Of*6xBWT+F*>y2ycK1V zDR`g49#MUfSNE9jaDFa&Y{{RvwVIpECHNBCk38eg@Y9@F`ot?8oL7rERzy^@l6=UE zm=V0lN7Wk+keQ6d$T(l73em<^(|VE1_%qe4ptDs|4om-q-$Md5q{6!?U0h-r8s611 zZ>BwZs}o!FaF1b=d`I$ozs!l2jzW8hKB?fm5*FM3Et{8pg0igmbKkn{3c@NzK`ukR z!DF+skJvcj|GmAUZ%puyMM({Fj0Kt;$?a|DIRhk?n@W=X)7m+8_rq^*9k@IF*76cr z?Z1XtZ%qrFo1NsB86_mS9od}@J 4Gkc{X$nkGsP)Sb%XCm>u}l=wL8BY$+EX2NIKo-mqKYeZtesKML(XsOL%?fH%1 z`uVU^lO08;KOZ@PP4MC$;~%e)Mb9V2xY|gCJ$gDU5(JM3Bgp;3XwPde&84Ye-*|Uh zkfgsGAHDG|dhmTn*&XwZ$Kmt8#$`^2D`L-8w0!Jq%a>+#gU|FYipx{84ss)!0{^rh z#1mg>6Dx#W82-~N`y%f5T+FoOy$0E?TMFODliedw$ER(wyD4>QJ~t`>5(~zyf17(- zYB?ic9kxIzXUd;>SQWn6^=q1T^F8(Wcyc|a_VF54nqZ%|$iv~G$m1~n6uE};j ~Oc$a8HaMOA+z|Z`)^%q4i&gRF-Qy^di+Vztxt#GAl;592|Kymwx?o1l zod``yEIPaKvy+6RMW3G9Rim~WrQ5x6ODLerzx0T19BR7XF|PPidXtUV`HUBbR6)|` z&tKobXU2~uaCQIbS;!5WfAw?sN)N{YZASF(NmDgWRQkv`{hm7$(&N3w$4lJ^{frcr zh=%Fe$cA7Y&1b#?Ck?hHLGJe5Tgk7n4yLf|nVSD#v@w||u8r`uST*ivIQTp+`zB0~ zsbr 2~9j2&)uqk#tJ!1 z= VrY;J&_)Z^|1d$GoI#v-!1@ICUcBbmgmQ4T&gqHd z;Taer5f~!&5ol0=o$_3}Z6U9Oe7Td_-siEu=wI&AKlhwj1X2tn23`evV+7C*G_6V} zPW#A0reWjz$;U;;Eb$#qCQp^JOdM91NfPW>6vm~4F_oN~ *`AtflR$0=+H%7c zSNTL*#Xsk(Um4(7gk^Z%cY(!Rba1L(`@KQ~l6I^02ec~8!U2uW95>MWP#qFPkGc7n z9@7e5=GX7ydCkmz&RG5sXSAx3M3L1_`Ij*BgLYllCrtApIXy&~* &`n2~Q)B8@Mdn=ZV0;ZDh*WmJm5U_?>k_={4c7mbbf*sIt`^ z8*LUhl>qf87cHq1d8od52Gmi4YhBbAbE}J%X7+q9R{CHP>^MJ_+2`1CWNI>}Pi}~Q z-F&VR!%v3iiw$^n*(J~C8GY|Rs1BHFxNBfbU^~v0`~ARKiJVbfn;xs9ph09{N=QgP zv=D1wXPTDg-#@G)fEfFinoHqxC?pa&e+vYf=jFbXfudnaQ-df85v59kVjAb|z;W1D zLQl?SadDoaDTsGP;64ylKrrlX4yDMr12y-mtUgVm2(*?Hs{%f^wzVB}*(vIpnMoWw z>p`4svr-9U=l1kWZm8x>oSfIG$P|El_`iO3j-0R^k#W`=aU1pWeZ4h$?4;!6#|t4E z)OPbnyYzYtIY5xbsuUWhd#A