Merge remote-tracking branch 'origin/master' into hardsync-1.5

This commit is contained in:
Letter N
2021-02-16 19:41:53 +08:00
71 changed files with 513 additions and 171 deletions

View File

@@ -24,3 +24,4 @@
#define LANGUAGE_STONER "stoner"
#define LANGUAGE_VASSAL "vassal"
#define LANGUAGE_VOICECHANGE "voicechange"
#define LANGUAGE_MULTILINGUAL "multilingual"

View File

@@ -204,7 +204,7 @@
///Compile all the overlays for an atom from the cache lists
// |= on overlays is not actually guaranteed to not add same appearances but we're optimistically using it anyway.
#define COMPILE_OVERLAYS(A)\
if (TRUE) {\
do {\
var/list/ad = A.add_overlays;\
var/list/rm = A.remove_overlays;\
if(LAZYLEN(rm)){\
@@ -216,7 +216,7 @@
ad.Cut();\
}\
A.flags_1 &= ~OVERLAY_QUEUED_1;\
}
} while(FALSE)
/**

View File

@@ -66,7 +66,7 @@
} while(FALSE)
//Returns a list in plain english as a string
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "")
var/total = length(input)
switch(total)
if (0)
@@ -87,6 +87,34 @@
return "[output][and_text][input[index]]"
/**
* English_list but associative supporting. Higher overhead.
*/
/proc/english_list_assoc(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "")
var/total = length(input)
switch(total)
if (0)
return "[nothing_text]"
if (1)
var/assoc = input[input[1]] == null? "" : " = [input[input[1]]]"
return "[input[1]][assoc]"
if (2)
var/assoc = input[input[1]] == null? "" : " = [input[input[1]]]"
var/assoc2 = input[input[2]] == null? "" : " = [input[input[2]]]"
return "[input[1]][assoc][and_text][input[2]][assoc2]"
else
var/output = ""
var/index = 1
var/assoc
while (index < total)
if (index == total - 1)
comma_text = final_comma_text
assoc = input[input[index]] == null? "" : " = [input[input[index]]]"
output += "[input[index]][assoc][comma_text]"
++index
assoc = input[input[index]] == null? "" : " = [input[input[index]]]"
return "[output][and_text][input[index]]"
//Returns list element or null. Should prevent "index out of bounds" error.
/proc/listgetindex(list/L, index)
if(LAZYLEN(L))

View File

@@ -231,10 +231,10 @@
src_object = window.locked_by.src_object
// Insert src_object info
if(src_object)
entry += "\nUsing: [src_object.type] [REF(src_object)]"
entry += "Using: [src_object.type] [REF(src_object)]"
// Insert message
if(message)
entry += "\n[message]"
entry += "[message]"
WRITE_LOG(GLOB.tgui_log, entry)
/* Close open log handles. This should be called as late as possible, and no logging should hapen after. */

View File

@@ -118,27 +118,7 @@
action_intent.hud = src
static_inventory += action_intent
using = new /obj/screen/mov_intent
using.icon = tg_ui_icon_to_cit_ui(ui_style) // CIT CHANGE - overrides mov intent icon
using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
//CITADEL CHANGES - sprint button
using = new /obj/screen/sprintbutton
using.icon = tg_ui_icon_to_cit_ui(ui_style)
using.icon_state = ((owner.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) ? "act_sprint_on" : "act_sprint")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
//END OF CITADEL CHANGES
//same as above but buffer.
sprint_buffer = new /obj/screen/sprint_buffer
sprint_buffer.screen_loc = ui_sprintbufferloc
sprint_buffer.hud = src
static_inventory += sprint_buffer
assert_move_intent_ui(owner, TRUE)
// clickdelay
clickdelay = new
@@ -393,6 +373,51 @@
update_locked_slots()
/datum/hud/human/proc/assert_move_intent_ui(mob/living/carbon/human/owner = mymob, on_new = FALSE)
var/obj/screen/using
// delete old ones
var/list/obj/screen/victims = list()
victims += locate(/obj/screen/mov_intent) in static_inventory
victims += locate(/obj/screen/sprintbutton) in static_inventory
victims += locate(/obj/screen/sprint_buffer) in static_inventory
if(victims)
static_inventory -= victims
if(mymob?.client)
mymob.client.screen -= victims
QDEL_LIST(victims)
// make new ones
// walk/run
using = new /obj/screen/mov_intent
using.icon = tg_ui_icon_to_cit_ui(ui_style) // CIT CHANGE - overrides mov intent icon
using.screen_loc = ui_movi
using.hud = src
using.update_icon()
static_inventory += using
if(!on_new)
owner?.client?.screen += using
if(!CONFIG_GET(flag/sprint_enabled))
return
// sprint button
using = new /obj/screen/sprintbutton
using.icon = tg_ui_icon_to_cit_ui(ui_style)
using.icon_state = ((owner.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) ? "act_sprint_on" : "act_sprint")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
if(!on_new)
owner?.client?.screen += using
// same as above but buffer.
sprint_buffer = new /obj/screen/sprint_buffer
sprint_buffer.screen_loc = ui_sprintbufferloc
sprint_buffer.hud = src
static_inventory += sprint_buffer
if(!on_new)
owner?.client?.screen += using
/datum/hud/human/update_locked_slots()
if(!mymob)
return

View File

@@ -351,6 +351,10 @@
icon = 'icons/mob/screen_midnight.dmi'
icon_state = "running"
/obj/screen/mov_intent/Initialize(mapload)
. = ..()
update_icon()
/obj/screen/mov_intent/Click()
toggle(usr)
@@ -359,7 +363,7 @@
if(MOVE_INTENT_WALK)
icon_state = "walking"
if(MOVE_INTENT_RUN)
icon_state = "running"
icon_state = CONFIG_GET(flag/sprint_enabled)? "running" : "running_nosprint"
/obj/screen/mov_intent/proc/toggle(mob/user)
if(isobserver(user))

View File

@@ -290,6 +290,17 @@
var/datum/movespeed_modifier/config_walk_run/M = get_cached_movespeed_modifier(/datum/movespeed_modifier/config_walk_run/walk)
M.sync()
/datum/config_entry/flag/sprint_enabled
config_entry_value = TRUE
/datum/config_entry/flag/sprint_enabled/ValidateAndSet(str_val)
. = ..()
for(var/datum/hud/human/H)
H.assert_move_intent_ui()
if(!config_entry_value) // disabled
for(var/mob/living/L in world)
L.disable_intentional_sprint_mode()
/datum/config_entry/number/movedelay/sprint_speed_increase
config_entry_value = 1

View File

@@ -26,50 +26,6 @@
/datum/config_entry/flag/hub // if the game appears on the hub or not
/datum/config_entry/flag/log_ooc // log OOC channel
/datum/config_entry/flag/log_access // log login/logout
/datum/config_entry/flag/log_say // log client say
/datum/config_entry/flag/log_admin // log admin actions
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_prayer // log prayers
/datum/config_entry/flag/log_law // log lawchanges
/datum/config_entry/flag/log_game // log game events
/datum/config_entry/flag/log_virus // log virology data
/datum/config_entry/flag/log_vote // log voting
/datum/config_entry/flag/log_craft // log crafting
/datum/config_entry/flag/log_whisper // log client whisper
/datum/config_entry/flag/log_attack // log attack messages
/datum/config_entry/flag/log_emote // log emotes
/datum/config_entry/flag/log_adminchat // log admin chat messages
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_shuttle // log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
/datum/config_entry/flag/log_pda // log pda messages
/datum/config_entry/flag/log_telecomms // log telecomms messages
/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
/datum/config_entry/flag/log_manifest // log crew manifest to seperate file
/datum/config_entry/flag/log_job_debug // log roundstart divide occupations debug information to a file
/datum/config_entry/flag/allow_admin_ooccolor // Allows admins with relevant permissions to have their own ooc colour
/datum/config_entry/flag/allow_vote_restart // allow votes to restart
@@ -472,10 +428,6 @@
/datum/config_entry/string/default_view_square
config_entry_value = "15x15"
/datum/config_entry/flag/log_pictures
/datum/config_entry/flag/picture_logging_camera
/datum/config_entry/number/max_bunker_days
config_entry_value = 7
min_val = 1

View File

@@ -0,0 +1,70 @@
/datum/config_entry/flag/log_ooc // log OOC channel
config_entry_value = TRUE
/datum/config_entry/flag/log_access // log login/logout
config_entry_value = TRUE
/datum/config_entry/flag/log_say // log client say
config_entry_value = TRUE
/datum/config_entry/flag/log_admin // log admin actions
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_prayer // log prayers
config_entry_value = TRUE
/datum/config_entry/flag/log_law // log lawchanges
config_entry_value = TRUE
/datum/config_entry/flag/log_game // log game events
config_entry_value = TRUE
/datum/config_entry/flag/log_virus // log virology data
config_entry_value = TRUE
/datum/config_entry/flag/log_vote // log voting
config_entry_value = TRUE
/datum/config_entry/flag/log_craft // log crafting
config_entry_value = TRUE
/datum/config_entry/flag/log_whisper // log client whisper
config_entry_value = TRUE
/datum/config_entry/flag/log_attack // log attack messages
config_entry_value = TRUE
/datum/config_entry/flag/log_emote // log emotes
config_entry_value = TRUE
/datum/config_entry/flag/log_adminchat // log admin chat messages
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_shuttle // log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
config_entry_value = TRUE
/datum/config_entry/flag/log_pda // log pda messages
config_entry_value = TRUE
/datum/config_entry/flag/log_telecomms // log telecomms messages
config_entry_value = TRUE
/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
config_entry_value = TRUE
/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
config_entry_value = TRUE
/datum/config_entry/flag/log_manifest // log crew manifest to seperate file
config_entry_value = TRUE
/datum/config_entry/flag/log_job_debug // log roundstart divide occupations debug information to a file
config_entry_value = TRUE
/datum/config_entry/flag/log_pictures
/datum/config_entry/flag/picture_logging_camera
/// forces log_href for tgui
/datum/config_entry/flag/emergency_tgui_logging
config_entry_value = FALSE

View File

@@ -228,10 +228,10 @@
gain_text = "You've learned an extra language!"
lose_text = "You've forgotten your extra language."
/datum/quirk/multilingual/add()
/datum/quirk/multilingual/post_add()
var/mob/living/carbon/human/H = quirk_holder
H.grant_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MIND)
H.grant_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MULTILINGUAL)
/datum/quirk/multilingual/remove()
var/mob/living/carbon/human/H = quirk_holder
H.remove_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MIND)
H.remove_language(H.client.prefs.language, TRUE, TRUE, LANGUAGE_MULTILINGUAL)

View File

@@ -264,6 +264,8 @@ What a mess.*/
active1 = null
if(!( GLOB.data_core.security.Find(active2) ))
active2 = null
if(!authenticated && href_list["choice"] != "Log In") // logging in is the only action you can do if not logged in
return
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))
usr.set_machine(src)
switch(href_list["choice"])

View File

@@ -10,35 +10,41 @@
/obj/item/armorkit/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
// yeah have fun making subtypes and modifying the afterattack if you want to make variants
// idiot
// - hatter
var/used = FALSE
if(isobj(target) && istype(target, /obj/item/clothing/under))
var/obj/item/clothing/under/C = target
if(C.armor.melee < 10)
C.armor.melee = 10
if(C.damaged_clothes)
to_chat(user,"<span class='warning'>You should repair the damage done to [C] first.</span>")
return
if(C.attached_accessory)
to_chat(user,"<span class='warning'>Kind of hard to sew around [C.attached_accessory].</span>")
return
if(C.armor.getRating("melee") < 10)
C.armor = C.armor.setRating("melee" = 10)
used = TRUE
if(C.armor.laser < 10)
C.armor.laser = 10
if(C.armor.getRating("laser") < 10)
C.armor = C.armor.setRating("laser" = 10)
used = TRUE
if(C.armor.fire < 40)
C.armor.fire = 40
if(C.armor.getRating("fire") < 40)
C.armor = C.armor.setRating("fire" = 40)
used = TRUE
if(C.armor.acid < 10)
C.armor.acid = 10
if(C.armor.getRating("acid") < 10)
C.armor = C.armor.setRating("acid" = 10)
used = TRUE
if(C.armor.bomb < 5)
C.armor.bomb = 5
if(C.armor.getRating("bomb") < 5)
C.armor = C.armor.setRating("bomb" = 5)
used = TRUE
if(used)
user.visible_message("<span class = 'notice'>[user] uses [src] on [C], reinforcing it and tossing the empty case away afterwards.</span>", \
"<span class = 'notice'>You reinforce [C] with [src], making it a little more protective! You toss the empty casing away afterwards.</span>")
C.name = "durathread [C.name]" // this disappears if it gets repaired, which is annoying
user.visible_message("<span class = 'notice'>[user] reinforces [C] with [src].</span>", \
"<span class = 'notice'>You reinforce [C] with [src], making it as protective as a durathread jumpsuit.</span>")
C.name = "durathread [C.name]"
C.upgrade_prefix = "durathread" // god i hope this works
qdel(src)
return
else
to_chat(user, "<span class = 'notice'>You stare at [src] and [C], coming to the conclusion that you probably don't need to reinforce it any further.")
to_chat(user, "<span class = 'notice'>You don't need to reinforce [C] any further.")
return
else
return

View File

@@ -8,7 +8,7 @@
descname = "Powers Nearby Structures"
name = "Sigil of Transmission"
desc = "Places a sigil that can drain and will store energy to power clockwork structures."
invocations = list("Divinity...", "...power our creations!")
invocations = list("Divinity...", "...power our creations.")
channel_time = 70
power_cost = 200
whispered = TRUE
@@ -28,7 +28,7 @@
descname = "Powered Structure, Delay Emergency Shuttles"
name = "Prolonging Prism"
desc = "Creates a mechanized prism which will delay the arrival of an emergency shuttle by 2 minutes at a massive power cost."
invocations = list("May this prism...", "...grant us time to enact his will!")
invocations = list("May this prism...", "...grant us time to enact his will.")
channel_time = 80
power_cost = 300
object_path = /obj/structure/destructible/clockwork/powered/prolonging_prism
@@ -60,7 +60,7 @@
descname = "Powered Structure, Area Denial"
name = "Mania Motor"
desc = "Creates a mania motor which causes minor damage and a variety of negative mental effects in nearby non-Servant humans, potentially up to and including conversion."
invocations = list("May this transmitter...", "...break the will of all who oppose us!")
invocations = list("May this transmitter...", "...break the will of all who oppose us.")
channel_time = 80
power_cost = 750
object_path = /obj/structure/destructible/clockwork/powered/mania_motor
@@ -83,7 +83,7 @@
descname = "Powered Structure, Teleportation Hub"
name = "Clockwork Obelisk"
desc = "Creates a clockwork obelisk that can broadcast messages over the Hierophant Network or open a Spatial Gateway to any living Servant or clockwork obelisk."
invocations = list("May this obelisk...", "...take us to all places!")
invocations = list("May this obelisk...", "...take us to all places.")
channel_time = 80
power_cost = 300
object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk
@@ -163,7 +163,7 @@
descname = "Well-Rounded Combat Construct"
name = "Clockwork Marauder"
desc = "Creates a shell for a clockwork marauder, a balanced frontline construct that can deflect projectiles with its shield."
invocations = list("Arise, avatar of Arbiter!", "Defend the Ark with vengeful zeal.")
invocations = list("Arise, avatar of Arbiter!", "Defend the Ark with vengeful zeal!")
channel_time = 80
power_cost = 8000
creator_message = "<span class='brass'>Your slab disgorges several chunks of replicant alloy that form into a suit of thrumming armor.</span>"

View File

@@ -7,7 +7,7 @@
descname = "Generates Power From Starlight"
name = "Stargazer"
desc = "Forms a weak structure that generates power every second while within three tiles of starlight."
invocations = list("Capture their inferior light for us!")
invocations = list("Capture their inferior light for us.")
channel_time = 50
power_cost = 200
object_path = /obj/structure/destructible/clockwork/stargazer
@@ -16,6 +16,7 @@
usage_tip = "For obvious reasons, make sure to place this near a window or somewhere else that can see space!"
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
whispered = TRUE
primary_component = HIEROPHANT_ANSIBLE
sort_priority = 1
quickbind = TRUE
@@ -34,7 +35,7 @@
descname = "Power Generation"
name = "Integration Cog"
desc = "Fabricates an integration cog, which can be used on an open APC to replace its innards and passively siphon its power."
invocations = list("Take that which sustains them!")
invocations = list("Take that which sustains them.")
channel_time = 10
power_cost = 10
whispered = TRUE
@@ -55,7 +56,7 @@
descname = "Trap, Stunning"
name = "Sigil of Transgression"
desc = "Wards a tile with a sigil, which will briefly stun the next non-Servant to cross it and apply Belligerent to them."
invocations = list("Divinity, smite...", "...those who trespass here!")
invocations = list("Divinity, smite...", "...those who trespass here.")
channel_time = 50
power_cost = 50
whispered = TRUE
@@ -75,7 +76,7 @@
descname = "Trap, Conversion"
name = "Sigil of Submission"
desc = "Places a luminous sigil that will convert any non-Servants that remain on it for 8 seconds."
invocations = list("Divinity, enlighten...", "...those who trespass here!")
invocations = list("Divinity, enlighten...", "...those who trespass here.")
channel_time = 60
power_cost = 125
whispered = TRUE
@@ -95,7 +96,7 @@
descname = "Short-Range Single-Target Stun"
name = "Kindle"
desc = "Charges your slab with divine energy, allowing you to overwhelm a target with Ratvar's light."
invocations = list("Divinity, show them your light!")
invocations = list("Divinity, show them your light.")
whispered = TRUE
channel_time = 25 //2.5 seconds should be a okay compromise between being able to use it when needed, and not being able to just pause in combat for a second and hardstunning your enemy
power_cost = 125
@@ -118,7 +119,7 @@
descname = "Handcuffs"
name = "Hateful Manacles"
desc = "Forms replicant manacles around a target's wrists that function like handcuffs."
invocations = list("Shackle the heretic!", "Break them in body and spirit!")
invocations = list("Shackle the heretic!", "Break them in body and spirit.")
channel_time = 15
power_cost = 25
whispered = TRUE
@@ -269,7 +270,7 @@
descname = "New Clockwork Slab"
name = "Replicant"
desc = "Creates a new clockwork slab."
invocations = list("Metal, become greater!")
invocations = list("Metal, become greater.")
channel_time = 10
power_cost = 25
whispered = TRUE
@@ -290,7 +291,7 @@
descname = "Limited Xray Vision Glasses"
name = "Wraith Spectacles"
desc = "Fabricates a pair of glasses which grant true sight but cause gradual vision loss."
invocations = list("Show the truth of this world to me!")
invocations = list("Show the truth of this world to me.")
channel_time = 10
power_cost = 50
whispered = TRUE
@@ -310,7 +311,7 @@
name = "Spatial Gateway"
desc = "Tears open a miniaturized gateway in spacetime to any conscious servant that can transport objects or creatures to its destination. \
Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration."
invocations = list("Spatial Gateway...", "...activate!")
invocations = list("Spatial Gateway...", "...activate.")
channel_time = 30
power_cost = 400
whispered = TRUE

View File

@@ -29,7 +29,7 @@
descname = "Structure, Turret"
name = "Ocular Warden"
desc = "Forms an automatic short-range turret which will automatically attack nearby unrestrained non-Servants that can see it."
invocations = list("Guardians of Engine...", "...judge those who would harm us!")
invocations = list("Guardians of Engine...", "...judge those who would harm us.")
channel_time = 100
power_cost = 250
object_path = /obj/structure/destructible/clockwork/ocular_warden
@@ -105,7 +105,7 @@
descname = "Delayed Area Knockdown Glasses"
name = "Judicial Visor"
desc = "Creates a visor that can smite an area, applying Belligerent and briefly stunning. The smote area will explode after 3 seconds."
invocations = list("Grant me the flames of Engine!")
invocations = list("Grant me the flames of Engine.")
channel_time = 10
power_cost = 400
whispered = TRUE
@@ -124,7 +124,7 @@
descname = "Shield with empowerable bashes"
name = "Nezbere's shield"
desc = "Creates a shield which generates charge from blocking damage, using it to empower its bashes tremendously. It is repaired with brass, and while very durable, extremely weak to lasers and, even more so, to energy weaponry."
invocations = list("Shield me...", "... from the coming dark!")
invocations = list("Shield me...", "... from the coming dark.")
channel_time = 20
power_cost = 600 //Shouldn't be too spammable but not too hard to get either
whispered = TRUE
@@ -143,7 +143,7 @@
descname = "Summonable Armor and Weapons"
name = "Clockwork Armaments"
desc = "Allows the invoker to summon clockwork armor and a Ratvarian spear at will. The spear's attacks will generate Vitality, used for healing."
invocations = list("Grant me armaments...", "...from the forge of Armorer!")
invocations = list("Grant me armaments...", "...from the forge of Armorer.")
channel_time = 20
power_cost = 250
whispered = TRUE

View File

@@ -15,13 +15,16 @@
var/ignore_holy_water = FALSE
/datum/antagonist/clockcult/silent
name = "Silent Clock Cultist"
silent = TRUE
show_in_antagpanel = FALSE //internal
/datum/antagonist/clockcult/neutered
name = "Neutered Clock Cultist"
neutered = TRUE
/datum/antagonist/clockcult/neutered/traitor
name = "Traitor Clock Cultist"
ignore_eligibility_check = TRUE
ignore_holy_water = TRUE
show_in_roundend = FALSE
@@ -185,7 +188,7 @@
/datum/antagonist/clockcult/admin_add(datum/mind/new_owner,mob/admin)
add_servant_of_ratvar(new_owner.current, TRUE)
add_servant_of_ratvar(new_owner.current, TRUE, override_type = type)
message_admins("[key_name_admin(admin)] has made [new_owner.current] into a servant of Ratvar.")
log_admin("[key_name(admin)] has made [new_owner.current] into a servant of Ratvar.")

View File

@@ -19,9 +19,11 @@
var/ignore_holy_water = FALSE
/datum/antagonist/cult/neutered
name = "Neutered Cultist"
neutered = TRUE
/datum/antagonist/cult/neutered/traitor
name = "Traitor Cultist"
ignore_eligibility_checks = TRUE
ignore_holy_water = TRUE
show_in_roundend = FALSE

View File

@@ -76,9 +76,15 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
to_chat(src, "<span class='danger'>Your previous action was ignored because you've done too many in a second</span>")
return
//Logs all hrefs, except chat pings
if(!(href_list["_src_"] == "chat" && href_list["proc"] == "ping" && LAZYLEN(href_list) == 2))
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
// Tgui Topic middleware
if(tgui_Topic(href_list))
if(CONFIG_GET(flag/emergency_tgui_logging))
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
return
//Logs all hrefs
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
//byond bug ID:2256651
if (asset_cache_job && (asset_cache_job in completed_asset_jobs))
@@ -105,10 +111,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
handle_statpanel_click(href_list)
return
// Tgui Topic middleware
if(tgui_Topic(href_list))
return
// Admin PM
if(href_list["priv_msg"])
cmd_admin_pm(href_list["priv_msg"],null)

View File

@@ -31,6 +31,9 @@
// What items can be consumed to repair this clothing (must by an /obj/item/stack)
var/repairable_by = /obj/item/stack/sheet/cloth
// has this item been upgraded by an upgrade kit (see: durathread armor kits)
var/upgrade_prefix
//Var modification - PLEASE be careful with this I know who you are and where you live
var/list/user_vars_to_edit //VARNAME = VARVALUE eg: "name" = "butts"
var/list/user_vars_remembered //Auto built by the above + dropped() + equipped()
@@ -120,6 +123,8 @@
update_clothes_damaged_state(CLOTHING_PRISTINE)
obj_integrity = max_integrity
name = initial(name) // remove "tattered" or "shredded" if there's a prefix
if(upgrade_prefix)
name = upgrade_prefix + " " + initial(name)
body_parts_covered = initial(body_parts_covered)
slot_flags = initial(slot_flags)
damage_by_parts = null

View File

@@ -220,8 +220,8 @@
parry_max_attacks = INFINITY
parry_failed_cooldown_duration = 2.25 SECONDS
parry_failed_stagger_duration = 2.25 SECONDS
parry_cooldown = 0
parry_failed_clickcd_duration = 0
parry_cooldown = 3 SECONDS
parry_failed_clickcd_duration = 0.5 SECONDS
/obj/item/clothing/gloves/botanic_leather
name = "botanist's leather gloves"

View File

@@ -51,6 +51,17 @@
desc = "Very gay shoes."
icon_state = "rain_bow"
/obj/item/clothing/shoes/sneakers/poly/polychromic
name = "polychromic shoes"
desc = "Every color."
icon_state = "poly"
item_state = "poly"
var/list/poly_colors = list("#FFFFFF", "#1D1D1D")
/obj/item/clothing/shoes/sneakers/poly/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 2)
/obj/item/clothing/shoes/sneakers/orange
name = "orange shoes"
icon_state = "orange"

View File

@@ -102,7 +102,18 @@
/obj/item/clothing/neck/cloak/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 3)
/obj/item/clothing/neck/cancloak/polychromic
name = "canvas cloak"
desc = "A rugged cloak made of canvas."
icon_state = "cancloak"
item_state = "cancloak"
var/list/poly_colors = list("#585858", "#373737", "#BEBEBE")
/obj/item/clothing/neck/cancloak/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 3)
/obj/item/clothing/neck/cloak/alt
name = "cloak"
desc = "A ragged up white cloak. It reminds you of a place not far from here."

View File

@@ -1030,6 +1030,16 @@
alternate_worn_layer = UNDER_HEAD_LAYER
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/clothing/suit/toggle/wbreakpoly
name = "polychromic windbreaker"
desc = "Perfect for windy days."
icon_state = "wbreakpoly"
item_state = "wbreakpoly"
/obj/item/clothing/suit/toggle/wbreakpoly/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, list("#464F65", "#916035", "#474747"), 3)
/obj/item/clothing/suit/flakjack
name = "flak jacket"
desc = "A dilapidated jacket made of a supposedly bullet-proof material (Hint: It isn't.). Smells faintly of napalm."

View File

@@ -32,6 +32,9 @@
/obj/item/clothing/under/attackby(obj/item/I, mob/user, params)
if((has_sensor == BROKEN_SENSORS) && istype(I, /obj/item/stack/cable_coil))
if(damaged_clothes)
to_chat(user,"<span class='warning'>You should repair the damage done to [src] first.</span>")
return 0
var/obj/item/stack/cable_coil/C = I
I.use_tool(src, user, 0, 1)
has_sensor = HAS_SENSORS

View File

@@ -54,7 +54,7 @@
H.visible_message("<span class='warning'>[H] is creamed by [src]!</span>", "<span class='userdanger'>You've been creamed by [src]!</span>")
playsound(H, "desceration", 50, TRUE)
if(!H.is_mouth_covered())
reagents.trans_to(H, 15, log = TRUE) //Cream pie combat
reagents.trans_to(H, 15, log = "creampie hit") //Cream pie combat
if(!H.creamed) // one layer at a time
H.add_overlay(creamoverlay)
H.creamed = TRUE

View File

@@ -79,7 +79,7 @@ God bless America.
to_chat(user, "<span class='warning'>There's nothing to dissolve [I] in!</span>")
return
user.visible_message("<span class='notice'>[user] drops [I] into [src].</span>", "<span class='notice'>You dissolve [I] in [src].</span>")
I.reagents.trans_to(src, I.reagents.total_volume)
I.reagents.trans_to(src, I.reagents.total_volume, log = "pill into deep fryer")
qdel(I)
return
if(istype(I,/obj/item/clothing/head/mob_holder))

View File

@@ -527,12 +527,13 @@
else if(istype(O, /obj/item/seeds) && !istype(O, /obj/item/seeds/sample))
if(!myseed)
if(istype(O, /obj/item/seeds/kudzu))
investigate_log("had Kudzu planted in it by [key_name(user)] at [AREACOORD(src)]","kudzu")
investigate_log("had Kudzu planted in it by [key_name(user)] at [AREACOORD(src)]", INVESTIGATE_BOTANY)
if(!user.transferItemToLoc(O, src))
return
to_chat(user, "<span class='notice'>You plant [O].</span>")
dead = FALSE
myseed = O
investigate_log("planting: [user] planted [O] with traits [english_list(myseed)] and reagents [english_list_assoc(myseed.reagents_add)] and potency [myseed.potency]", INVESTIGATE_BOTANY)
TRAY_NAME_UPDATE
age = 1
plant_health = myseed.endurance

View File

@@ -188,6 +188,8 @@
///The Number of products produced by the plant, typically the yield.
var/product_count = getYield()
parent.investigate_log("manual harvest by [key_name(user)] of [getYield()] of [src], with seed traits [english_list(genes)] and reagents_add [english_list_assoc(reagents_add)] and potency [potency].", INVESTIGATE_BOTANY)
while(t_amount < product_count)
var/obj/item/reagent_containers/food/snacks/grown/t_prod
if(instability >= 30 && (seed_flags & MUTATE_EARLY) && LAZYLEN(mutatelist) && prob(instability/3))

View File

@@ -128,10 +128,58 @@
if(dbflags & DB_FLAG_AGE_CONFIRMATION_INCOMPLETE) //they have not completed age gate
var/age_verification = age_gate()
if(age_verification != 1)
client.add_system_note("Automated-Age-Gate", "Failed automatic age gate process")
client.add_system_note("Automated-Age-Gate", "Failed automatic age gate process.")
//ban them and kick them
AddBan(client.ckey, client.computer_id, "SYSTEM BAN - Inputted date during join verification was under 18 years of age. Contact administration on discord for verification.", "SYSTEM", FALSE, null, client.address)
//parameters used by sql line, easier to read:
var/bantype_str = "ADMIN_PERMABAN"
var/reason = "SYSTEM BAN - Inputted date during join verification was under 18 years of age. Contact administration on discord for verification."
var/duration = -1
var/sql_ckey = sanitizeSQL(client.ckey)
var/computerid = client.computer_id
if(!computerid)
computerid = "0"
var/sql_computerid = sanitizeSQL(computerid)
var/ip = client.address
if(!ip)
ip = "0.0.0.0"
var/sql_ip = sanitizeSQL(ip)
//parameter not used as there's no job but i want to fill out all parameters for the insert line
var/sql_job
// these are typically the banning admin's, but it's the system so we leave them null, but they're still here for the sake of a full set of values
var/sql_a_ckey
var/sql_a_computerid
var/sql_a_ip
// record all admins and non-admins online at the time
var/who
for(var/client/C in GLOB.clients)
if(!who)
who = "[C]"
else
who += ", [C]"
var/adminwho
for(var/client/C in GLOB.admins)
if(!adminwho)
adminwho = "[C]"
else
adminwho += ", [C]"
var/sql = "INSERT INTO [format_table_name("ban")] (`bantime`,`server_ip`,`server_port`,`round_id`,`bantype`,`reason`,`job`,`duration`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]', '[bantype_str]', '[reason]', '[sql_job]', [(duration)?"[duration]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[sql_ckey]', '[sql_computerid]', INET_ATON('[sql_ip]'), '[sql_a_ckey]', '[sql_a_computerid]', INET_ATON('[sql_a_ip]'), '[who]', '[adminwho]')"
var/datum/DBQuery/query_add_ban = SSdbcore.NewQuery(sql)
qdel(query_add_ban)
// announce this
message_admins("[html_encode(client.ckey)] has been banned for failing the automatic age gate.")
send2irc("[html_encode(client.ckey)] has been banned for failing the automatic age gate.")
// removing the client disconnects them
qdel(client)
return FALSE
else
//they claim to be of age, so allow them to continue and update their flags

View File

@@ -11,6 +11,8 @@
maxHealth = 25
health = 25
can_ventcrawl = TRUE
var/amount_grown = 0
var/max_grown = 100
var/time_of_birth

View File

@@ -96,9 +96,10 @@
parry_efficiency_considered_successful = 0.01
parry_efficiency_to_counterattack = 0.01
parry_max_attacks = 3
parry_cooldown = 30
parry_failed_stagger_duration = 0
parry_failed_clickcd_duration = 0.4
parry_cooldown = 3 SECONDS
parry_failed_cooldown_duration = 1.5 SECONDS
parry_failed_stagger_duration = 1 SECONDS
parry_failed_clickcd_duration = 0.4 SECONDS
parry_data = list( // yeah it's snowflake
"UNARMED_PARRY_STAGGER" = 3 SECONDS,
@@ -136,16 +137,16 @@
parry_imperfect_falloff_percent = 20
parry_efficiency_perfect = 100
parry_efficiency_perfect_override = list(
ATTACK_TYPE_PROJECTILE_TEXT = 60,
TEXT_ATTACK_TYPE_PROJECTILE = 60,
)
parry_efficiency_considered_successful = 0.01
parry_efficiency_to_counterattack = 0.01
parry_max_attacks = INFINITY
parry_failed_cooldown_duration = 1.5 SECONDS
parry_failed_stagger_duration = 0
parry_cooldown = 0
parry_failed_clickcd_duration = 0.8
parry_failed_cooldown_duration = 3 SECONDS
parry_failed_stagger_duration = 2 SECONDS
parry_cooldown = 3 SECONDS
parry_failed_clickcd_duration = 0.8 SECONDS
parry_data = list( // yeah it's snowflake
"UNARMED_PARRY_STAGGER" = 3 SECONDS,

View File

@@ -1425,8 +1425,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/damage = rand(user.dna.species.punchdamagelow, user.dna.species.punchdamagehigh)
var/punchwoundbonus = user.dna.species.punchwoundbonus
var/puncherstam = user.getStaminaLoss()
var/puncherbrute = user.getBruteLoss()
var/punchedstam = target.getStaminaLoss()
var/punchedbrute = target.getBruteLoss()
@@ -1434,7 +1432,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 1.2
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
damage *= 0.8
damage *= 0.65
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 0.8
//END OF CITADEL CHANGES
@@ -1446,19 +1444,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!affecting) //Maybe the bodypart is missing? Or things just went wrong..
affecting = target.get_bodypart(BODY_ZONE_CHEST) //target chest instead, as failsafe. Or hugbox? You decide.
var/miss_chance = 100//calculate the odds that a punch misses entirely. considers stamina and brute damage of the puncher. punches miss by default to prevent weird cases
if(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)
miss_chance = 0
else
if(user.dna.species.punchdamagelow)
if(atk_verb == ATTACK_EFFECT_KICK) //kicks never miss (provided your species deals more than 0 damage)
miss_chance = 0
else if(HAS_TRAIT(user, TRAIT_PUGILIST)) //pugilists, being good at Punching People, also never miss
miss_chance = 0
else
miss_chance = min(10 + max(puncherstam * 0.5, puncherbrute * 0.5), 100) //probability of miss has a base of 10, and modified based on half brute total. Capped at max 100 to prevent weirdness in prob()
if(!damage || !affecting || prob(miss_chance))//future-proofing for species that have 0 damage/weird cases where no zone is targeted
if(!damage || !affecting)//future-proofing for species that have 0 damage/weird cases where no zone is targeted
playsound(target.loc, user.dna.species.miss_sound, 25, TRUE, -1)
target.visible_message("<span class='danger'>[user]'s [atk_verb] misses [target]!</span>", \
"<span class='danger'>You avoid [user]'s [atk_verb]!</span>", "<span class='hear'>You hear a swoosh!</span>", null, COMBAT_MESSAGE_RANGE, null, \

View File

@@ -26,6 +26,8 @@
update_sprint_icon()
/mob/living/proc/enable_sprint_mode(update_icon = TRUE)
if(!CONFIG_GET(flag/sprint_enabled))
return
if(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE)
return
ENABLE_BITFIELD(combat_flags, COMBAT_FLAG_SPRINT_ACTIVE)
@@ -61,6 +63,8 @@
update_sprint_icon()
/mob/living/proc/user_toggle_intentional_sprint_mode()
if(!CONFIG_GET(flag/sprint_enabled))
return
var/old = (combat_flags & COMBAT_FLAG_SPRINT_TOGGLED)
if(old)
if(combat_flags & COMBAT_FLAG_SPRINT_FORCED)

View File

@@ -1,4 +1,7 @@
/mob/living/silicon/robot/default_toggle_sprint(shutdown = FALSE)
if(!CONFIG_GET(flag/sprint_enabled))
disable_intentional_sprint_mode()
return
var/current = (combat_flags & COMBAT_FLAG_SPRINT_ACTIVE)
if(current || shutdown || !cell || (cell.charge < 25) || !cansprint)
disable_intentional_sprint_mode()

View File

@@ -146,7 +146,7 @@
return
reagents.clear_reagents()
// This also reacts them. No nitroglycerin deathpools, sorry gamers :(
W.reagents.trans_to(reagents, max_beaker_transfer)
W.reagents.trans_to(reagents, max_beaker_transfer, log = "pool fill from reagent container")
user.visible_message("<span class='notice'>[src] makes a slurping noise.</span>", "<span class='notice'>All of the contents of [W] are quickly suctioned out by the machine!</span")
updateUsrDialog()
var/list/reagent_names = list()

View File

@@ -48,7 +48,7 @@
safe_thing.create_reagents(100, NONE, NO_REAGENTS_VALUE)
reagents.reaction(safe_thing, TOUCH, fraction)
trans = reagents.trans_to(safe_thing, amount_per_transfer_from_this)
trans = reagents.trans_to(safe_thing, amount_per_transfer_from_this, log = "failed squirt")
target.visible_message("<span class='danger'>[user] tries to squirt something into [target]'s eyes, but fails!</span>", \
"<span class='userdanger'>[user] tries to squirt something into [target]'s eyes, but fails!</span>")
@@ -67,7 +67,7 @@
var/mob/M = target
log_combat(user, M, "squirted", reagents.log_list())
trans = src.reagents.trans_to(target, amount_per_transfer_from_this)
trans = src.reagents.trans_to(target, amount_per_transfer_from_this, log = "dropper drop")
to_chat(user, "<span class='notice'>You transfer [trans] unit\s of the solution.</span>")
update_icon()
@@ -81,7 +81,7 @@
to_chat(user, "<span class='warning'>[target] is empty!</span>")
return
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, log = "dropper fill")
to_chat(user, "<span class='notice'>You fill [src] with [trans] unit\s of the solution.</span>")

View File

@@ -41,7 +41,7 @@
if(M.reagents)
var/trans = 0
if(!infinite)
trans = reagents.trans_to(M, amount_per_transfer_from_this, log = TRUE)
trans = reagents.trans_to(M, amount_per_transfer_from_this, log = "hypospray injection")
else
trans = reagents.copy_to(M, amount_per_transfer_from_this)
@@ -427,7 +427,7 @@
var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
vial.reagents.reaction(L, method, fraction)
vial.reagents.trans_to(target, vial.amount_per_transfer_from_this, log = TRUE)
vial.reagents.trans_to(target, vial.amount_per_transfer_from_this, log = "hypospray fill")
var/long_sound = vial.amount_per_transfer_from_this >= 15
playsound(loc, long_sound ? 'sound/items/hypospray_long.ogg' : pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
to_chat(user, "<span class='notice'>You [fp_verb] [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.</span>")

View File

@@ -39,7 +39,7 @@
C.visible_message("<span class='danger'>[user] is trying to smother \the [C] with \the [src]!</span>", "<span class='userdanger'>[user] is trying to smother you with \the [src]!</span>", "<span class='italics'>You hear some struggling and muffled cries of surprise.</span>")
if(do_after(user, 20, target = C))
reagents.reaction(C, INGEST)
reagents.trans_to(C, 5, log = TRUE)
reagents.trans_to(C, 5, log = "rag smother")
C.visible_message("<span class='danger'>[user] has smothered \the [C] with \the [src]!</span>", "<span class='userdanger'>[user] has smothered you with \the [src]!</span>", "<span class='italics'>You hear some struggling and a heavy breath taken.</span>")
log_combat(user, C, "smothered", log_object)
else
@@ -107,7 +107,7 @@
reagents.clear_reagents()
else
msg += "'s liquids into \the [target]"
reagents.trans_to(target, reagents.total_volume, log = TRUE)
reagents.trans_to(target, reagents.total_volume, log = "rag squeeze dry")
to_chat(user, "<span class='notice'>[msg].</span>")
return TRUE

View File

@@ -36,6 +36,6 @@
log_combat(owner, null, "swallowed an implanted pill", target)
if(target.reagents.total_volume)
target.reagents.reaction(owner, INGEST)
target.reagents.trans_to(owner, target.reagents.total_volume, log = TRUE)
target.reagents.trans_to(owner, target.reagents.total_volume, log = "dental pill swallow")
qdel(target)
return 1

View File

@@ -21,6 +21,7 @@
/obj/item/clothing/suit/jacket/puffer/vest = 4,
/obj/item/clothing/suit/jacket/puffer = 4,
/obj/item/clothing/suit/hooded/cloak/david = 4,
/obj/item/clothing/neck/cancloak = 4,
/obj/item/clothing/suit/bomber = 5,
/obj/item/clothing/under/suit/turtle/teal = 3,
/obj/item/clothing/under/suit/turtle/grey = 3,
@@ -212,7 +213,9 @@
/obj/item/clothing/neck/necklace/dope = 5,
/obj/item/clothing/suit/jacket/letterman_nanotrasen = 5,
/obj/item/clothing/under/misc/corporateuniform = 5,
/obj/item/clothing/suit/hooded/wintercoat/polychromic = 5)
/obj/item/clothing/suit/hooded/wintercoat/polychromic = 5,
/obj/item/clothing/suit/toggle/wbreakpoly/polychromic = 5,
/obj/item/clothing/shoes/sneakers/poly/polychromic = 10)
refill_canister = /obj/item/vending_refill/clothing
default_price = PRICE_CHEAP
extra_price = PRICE_BELOW_NORMAL

View File

@@ -50,6 +50,68 @@
-->
<div class="commit sansserif">
<h2 class="date">16 February 2021</h2>
<h3 class="author">silicons updated:</h3>
<ul class="changes bgimages16">
<li class="config">sprint removal entry added, UI will revert to old UI while this is active.</li>
</ul>
<h2 class="date">15 February 2021</h2>
<h3 class="author">Adelphon updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">polychromatic shoes</li>
<li class="rscadd">polychromatic windbreaker</li>
<li class="rscadd">polychromatic canvas cloak</li>
<li class="bugfix">digitigrade charismatic suit texture</li>
</ul>
<h3 class="author">DeltaFire15 updated:</h3>
<ul class="changes bgimages16">
<li class="balance">Kneecapped pugilist parries somewhat.</li>
<li class="balance">Slightly nerfed default unarmed parries.</li>
<li class="balance">Slightly nerfed traitor armwrap parries.</li>
<li class="bugfix">Pugilist parries now cannot perfectly defend against projectiles, as they were supposed to.</li>
<li class="bugfix">Some parrying numbers that one would think were in seconds didn't have the SECONDS. I added those.</li>
<li class="balance">Clock cultists now yell alot less when invoking scripture.</li>
</ul>
<h3 class="author">dzahlus updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added new emote</li>
<li class="soundadd">added a new emote sound</li>
</ul>
<h3 class="author">silicons updated:</h3>
<ul class="changes bgimages16">
<li class="balance">people on the ground hit less hard in unarmed combat. rng miss remove from punches.</li>
<li class="bugfix">chat highlighting no longer drops half your entered words.</li>
</ul>
<h2 class="date">14 February 2021</h2>
<h3 class="author">DeltaFire15 updated:</h3>
<ul class="changes bgimages16">
<li class="admin">The antag panel now correctly shows the names of cultist / clockcult datum subtypes.</li>
<li class="bugfix">Adding clock cultists via the admin panel now works correctly.</li>
<li class="bugfix">Xeno larvae should now be able to ventcrawl again.</li>
</ul>
<h3 class="author">Hatterhat updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Repairing sensors on jumpsuits now requires a fully-intact jumpsuit. Find some cloth.</li>
<li class="tweak">Durathread armor kits now require you to have a fully-repaired jumpsuit, first, with no attachments.</li>
<li class="bugfix">Durathread armor kits now no longer weave the entirety of the jumpsuit armor universe into having armor.</li>
</ul>
<h3 class="author">TyrianTyrell updated:</h3>
<ul class="changes bgimages16">
<li class="code_imp">added a define for multilingual granted languages, and changed the multilingual trait to use it.</li>
</ul>
<h2 class="date">13 February 2021</h2>
<h3 class="author">Hatterhat updated:</h3>
<ul class="changes bgimages16">
<li class="balance">Energy bolas now take 2.5 seconds to remove and dissipate on removal.</li>
</ul>
<h3 class="author">timothyteakettle updated:</h3>
<ul class="changes bgimages16">
<li class="admin">migration error to version 39+ of savefiles is now logged instead of messaging all online admins in the chat</li>
</ul>
<h2 class="date">12 February 2021</h2>
<h3 class="author">Hatterhat updated:</h3>
<ul class="changes bgimages16">

View File

@@ -28454,3 +28454,50 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
silicons:
- balance: Voice of God - sleep removed, stun staggers instead, knockdown is faster
but does not do stamina damage, vomit is faster but doesn't stun
2021-02-13:
Hatterhat:
- balance: Energy bolas now take 2.5 seconds to remove and dissipate on removal.
timothyteakettle:
- admin: migration error to version 39+ of savefiles is now logged instead of messaging
all online admins in the chat
2021-02-14:
DeltaFire15:
- admin: The antag panel now correctly shows the names of cultist / clockcult datum
subtypes.
- bugfix: Adding clock cultists via the admin panel now works correctly.
- bugfix: Xeno larvae should now be able to ventcrawl again.
Hatterhat:
- tweak: Repairing sensors on jumpsuits now requires a fully-intact jumpsuit. Find
some cloth.
- tweak: Durathread armor kits now require you to have a fully-repaired jumpsuit,
first, with no attachments.
- bugfix: Durathread armor kits now no longer weave the entirety of the jumpsuit
armor universe into having armor.
TyrianTyrell:
- code_imp: added a define for multilingual granted languages, and changed the multilingual
trait to use it.
2021-02-15:
Adelphon:
- rscadd: polychromatic shoes
- rscadd: polychromatic windbreaker
- rscadd: polychromatic canvas cloak
- bugfix: digitigrade charismatic suit texture
DeltaFire15:
- balance: Kneecapped pugilist parries somewhat.
- balance: Slightly nerfed default unarmed parries.
- balance: Slightly nerfed traitor armwrap parries.
- bugfix: Pugilist parries now cannot perfectly defend against projectiles, as they
were supposed to.
- bugfix: Some parrying numbers that one would think were in seconds didn't have
the SECONDS. I added those.
- balance: Clock cultists now yell alot less when invoking scripture.
dzahlus:
- rscadd: Added new emote
- soundadd: added a new emote sound
silicons:
- balance: people on the ground hit less hard in unarmed combat. rng miss remove
from punches.
- bugfix: chat highlighting no longer drops half your entered words.
2021-02-16:
silicons:
- config: sprint removal entry added, UI will revert to old UI while this is active.

View File

@@ -1,4 +0,0 @@
author: "Hatterhat"
delete-after: True
changes:
- balance: "Energy bolas now take 2.5 seconds to remove and dissipate on removal."

View File

@@ -1,4 +0,0 @@
author: "timothyteakettle"
delete-after: True
changes:
- admin: "migration error to version 39+ of savefiles is now logged instead of messaging all online admins in the chat"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 460 KiB

After

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

After

Width:  |  Height:  |  Size: 313 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 167 KiB

View File

@@ -98,3 +98,9 @@
path = /obj/item/clothing/neck/cloak/alt/polychromic
loadout_flags = LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#FFFFFF", "#676767", "#4C4C4C")
/datum/gear/neck/cancloak
name = "Canvas Cloak"
path = /obj/item/clothing/neck/cancloak/polychromic
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#585858", "#373737", "#BEBEBE")

View File

@@ -34,6 +34,12 @@
name = "White shoes"
path = /obj/item/clothing/shoes/sneakers/white
/datum/gear/shoes/poly
name = "Polychromic shoes"
path = /obj/item/clothing/shoes/sneakers/poly/polychromic
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#FFFFFF", "#1D1D1D")
/datum/gear/shoes/gildedcuffs
name = "Gilded leg wraps"
path= /obj/item/clothing/shoes/wraps

View File

@@ -104,6 +104,13 @@
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#6A6964", "#C4B8A6", "#0000FF")
/datum/gear/suit/coat/wbreakpoly
name = "Polychromic windbreaker"
path = /obj/item/clothing/suit/toggle/wbreakpoly/polychromic
cost = 4
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#464F65", "#916035", "#474747")
/datum/gear/suit/coat/med
name = "Medical winter coat"
path = /obj/item/clothing/suit/hooded/wintercoat/medical

View File

@@ -300,3 +300,24 @@
user.nextsoundemote = world.time + 7
var/sound = pick('sound/voice/slime_squish.ogg')
playsound(user, sound, 50, 1, -1)
/datum/emote/living/pain
key = "pain"
key_third_person = "cries out in pain!"
message = "cries out in pain!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = FALSE
restraint_check = FALSE
/datum/emote/living/pain/run_emote(mob/living/user, params)
if(!(. = ..()))
return
if(user.nextsoundemote >= world.time)
return
user.nextsoundemote = world.time + 7
var/sound
if(user.gender == MALE)
sound = pick('modular_citadel/sound/voice/human_male_pain_1.ogg', 'modular_citadel/sound/voice/human_male_pain_2.ogg', 'modular_citadel/sound/voice/human_male_pain_3.ogg', 'modular_citadel/sound/voice/human_male_pain_rare.ogg')
else
sound = pick('modular_citadel/sound/voice/human_female_pain_1.ogg', 'modular_citadel/sound/voice/human_female_pain_2.ogg', 'modular_citadel/sound/voice/human_female_pain_3.ogg')
playsound(user, sound, 50, 0, 0)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
pain emote sound ported from https://gitlab.com/cmdevs/colonial-warfare

View File

@@ -294,6 +294,7 @@
#include "code\controllers\configuration\entries\fail2topic.dm"
#include "code\controllers\configuration\entries\game_options.dm"
#include "code\controllers\configuration\entries\general.dm"
#include "code\controllers\configuration\entries\logging.dm"
#include "code\controllers\configuration\entries\persistence.dm"
#include "code\controllers\configuration\entries\plushies.dm"
#include "code\controllers\configuration\entries\policy.dm"

View File

@@ -176,7 +176,9 @@ class ChatRenderer {
this.highlightColor = null;
return;
}
const allowedRegex = /^[a-z0-9_\-\s]+$/ig;
// citadel update - ig changed to i for flags,
// to fix issues with highlighting only working for every other word.
const allowedRegex = /^[a-z0-9_\-\s]+$/i;
const lines = String(text)
.split(',')
.map(str => str.trim())

File diff suppressed because one or more lines are too long