Merge remote-tracking branch 'ParadiseSS13/master' into client-data-loading

This commit is contained in:
AffectedArc07
2021-09-08 14:15:17 +01:00
237 changed files with 3490 additions and 3099 deletions
+3 -3
View File
@@ -1,9 +1,9 @@
# This file has all the information on what versions of libraries are thrown into the code
# For dreamchecker
export SPACEMANDMM_TAG=suite-1.6
export SPACEMANDMM_TAG=suite-1.7
# For TGUI
export NODE_VERSION=12
# Byond Major
export BYOND_MAJOR=513
export BYOND_MAJOR=514
# Byond Minor
export BYOND_MINOR=1528
export BYOND_MINOR=1566
File diff suppressed because it is too large Load Diff
@@ -3395,16 +3395,12 @@
/area/ruin/space/ancientstation/rnd)
"hU" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/particle_accelerator/control_box{
icon = 'icons/obj/machines/particle_accelerator3.dmi'
},
/obj/machinery/particle_accelerator/control_box,
/turf/simulated/floor/plating,
/area/ruin/space/ancientstation/thetacorridor)
"hV" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/particle_accelerator/particle_emitter/right{
icon = 'icons/obj/machines/particle_accelerator3.dmi'
},
/obj/structure/particle_accelerator/particle_emitter/right,
/turf/simulated/floor/plating,
/area/ruin/space/ancientstation/thetacorridor)
"hW" = (
@@ -4029,9 +4025,7 @@
/area/ruin/space/ancientstation/thetacorridor)
"jm" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/particle_accelerator/particle_emitter/center{
icon = 'icons/obj/machines/particle_accelerator3.dmi'
},
/obj/structure/particle_accelerator/particle_emitter/center,
/turf/simulated/floor/plating,
/area/ruin/space/ancientstation/thetacorridor)
"jn" = (
@@ -4747,23 +4741,17 @@
/area/ruin/space/ancientstation/thetacorridor)
"kT" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/particle_accelerator/particle_emitter/left{
icon = 'icons/obj/machines/particle_accelerator3.dmi'
},
/obj/structure/particle_accelerator/particle_emitter/left,
/turf/simulated/floor/plating,
/area/ruin/space/ancientstation/thetacorridor)
"kU" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/particle_accelerator/fuel_chamber{
icon = 'icons/obj/machines/particle_accelerator3.dmi'
},
/obj/structure/particle_accelerator/fuel_chamber,
/turf/simulated/floor/plating,
/area/ruin/space/ancientstation/thetacorridor)
"kV" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/particle_accelerator/end_cap{
icon = 'icons/obj/machines/particle_accelerator3.dmi'
},
/obj/structure/particle_accelerator/end_cap,
/turf/simulated/floor/plating,
/area/ruin/space/ancientstation/thetacorridor)
"kW" = (
@@ -4785,9 +4773,7 @@
/area/ruin/space/ancientstation/rnd)
"kY" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/particle_accelerator/power_box{
icon = 'icons/obj/machines/particle_accelerator3.dmi'
},
/obj/structure/particle_accelerator/power_box,
/turf/simulated/floor/plating,
/area/ruin/space/ancientstation/thetacorridor)
"kZ" = (
+9
View File
@@ -114,3 +114,12 @@
#define PIPE_COLOR_GREEN "#00ff00"
#define PIPE_COLOR_YELLOW "#ffcc00"
#define PIPE_COLOR_PURPLE "#5c1ec0"
///Main colors for UI themes
#define COLOR_THEME_MIDNIGHT "#6086A0"
#define COLOR_THEME_PLASMAFIRE "#FFB200"
#define COLOR_THEME_RETRO "#24CA00"
#define COLOR_THEME_SLIMECORE "#4FB259"
#define COLOR_THEME_OPERATIVE "#B8221F"
#define COLOR_THEME_GLASS "#75A4C4"
#define COLOR_THEME_CLOCKWORK "#CFBA47"
+15 -1
View File
@@ -7,12 +7,14 @@
#define FOOTSTEP_WATER "water"
#define FOOTSTEP_LAVA "lava"
#define FOOTSTEP_MEAT "meat"
#define FOOTSTEP_GLASS "glass"
//barefoot sounds
#define FOOTSTEP_WOOD_BAREFOOT "woodbarefoot"
#define FOOTSTEP_WOOD_CLAW "woodclaw"
#define FOOTSTEP_HARD_BAREFOOT "hardbarefoot"
#define FOOTSTEP_HARD_CLAW "hardclaw"
#define FOOTSTEP_CARPET_BAREFOOT "carpetbarefoot"
#define FOOTSTEP_GLASS_BAREFOOT "glassbarefoot"
//misc footstep sounds
#define FOOTSTEP_GENERIC_HEAVY "heavy"
@@ -83,7 +85,11 @@ GLOBAL_LIST_INIT(footstep, list(
'sound/effects/footstep/lava2.ogg',
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
'sound/effects/meatslap.ogg'), 100, 0)
'sound/effects/meatslap.ogg'), 100, 0),
FOOTSTEP_GLASS = list(list(
'sound/effects/footstep/glass1.ogg',
'sound/effects/footstep/glass2.ogg',
'sound/effects/footstep/glass3.ogg'), 100, 1),
))
//bare footsteps lists
GLOBAL_LIST_INIT(barefootstep, list(
@@ -127,6 +133,10 @@ GLOBAL_LIST_INIT(barefootstep, list(
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
'sound/effects/meatslap.ogg'), 100, 0),
FOOTSTEP_GLASS_BAREFOOT = list(list(
'sound/effects/footstep/glassbarefoot1.ogg',
'sound/effects/footstep/glassbarefoot2.ogg',
'sound/effects/footstep/glassbarefoot3.ogg'), 100, 1),
))
//claw footsteps lists
@@ -171,6 +181,10 @@ GLOBAL_LIST_INIT(clawfootstep, list(
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
'sound/effects/meatslap.ogg'), 100, 0),
FOOTSTEP_GLASS = list(list(
'sound/effects/footstep/glassbarefoot1.ogg',
'sound/effects/footstep/glassbarefoot2.ogg',
'sound/effects/footstep/glassbarefoot3.ogg'), 100, 1),
))
//heavy footsteps list
-1
View File
@@ -74,7 +74,6 @@
//Species traits.
#define NO_BLOOD "no_blood"
#define NOTRANSSTING "no_trans_sting"
#define IS_WHITELISTED "whitelisted"
#define LIPS "lips"
#define EXOTIC_COLOR "exotic_blood_color"
+2
View File
@@ -26,11 +26,13 @@
#define DISPOSAL_PIPE_LAYER 2.3
#define GAS_PIPE_HIDDEN_LAYER 2.35
#define WIRE_LAYER 2.4
#define TRANSPARENT_TURF_LAYER 2.41
#define WIRE_TERMINAL_LAYER 2.45
#define GAS_SCRUBBER_LAYER 2.46
#define GAS_PIPE_VISIBLE_LAYER 2.47
#define GAS_FILTER_LAYER 2.48
#define GAS_PUMP_LAYER 2.49
#define HOLOPAD_LAYER 2.491
#define CONVEYOR_LAYER 2.495
#define LOW_OBJ_LAYER 2.5
#define LOW_SIGIL_LAYER 2.52
+3 -2
View File
@@ -56,10 +56,11 @@
#define PREFTOGGLE_2_REVERB_DISABLE 512
#define PREFTOGGLE_2_FORCE_WHITE_RUNECHAT 1024
#define PREFTOGGLE_2_SIMPLE_STAT_PANEL 2048
#define PREFTOGGLE_2_SEE_ITEM_OUTLINES 4096
#define TOGGLES_2_TOTAL 4095 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
#define TOGGLES_2_TOTAL 8191 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
#define TOGGLES_2_DEFAULT (PREFTOGGLE_2_FANCYUI|PREFTOGGLE_2_ITEMATTACK|PREFTOGGLE_2_WINDOWFLASHING|PREFTOGGLE_2_RUNECHAT|PREFTOGGLE_2_DEATHMESSAGE|PREFTOGGLE_2_EMOTE_BUBBLE)
#define TOGGLES_2_DEFAULT (PREFTOGGLE_2_FANCYUI|PREFTOGGLE_2_ITEMATTACK|PREFTOGGLE_2_WINDOWFLASHING|PREFTOGGLE_2_RUNECHAT|PREFTOGGLE_2_DEATHMESSAGE|PREFTOGGLE_2_EMOTE_BUBBLE|PREFTOGGLE_2_SEE_ITEM_OUTLINES)
// Sanity checks
#if TOGGLES_TOTAL > 16777215
+3
View File
@@ -164,6 +164,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_BLOODCRAWL_EAT "bloodcrawl_eat"
#define TRAIT_DWARF "dwarf"
#define TRAIT_SILENT_FOOTSTEPS "silent_footsteps" //makes your footsteps completely silent
#define TRAIT_MESON_VISION "meson_vision"
#define TRAIT_FLASH_PROTECTION "flash_protection"
#define TRAIT_NIGHT_VISION "night_vision"
#define TRAIT_COMIC_SANS "comic_sans"
#define TRAIT_NOFINGERPRINTS "no_fingerprints"
+3 -3
View File
@@ -22,12 +22,12 @@
#define IS_MODE_COMPILED(MODE) (ispath(text2path("/datum/game_mode/"+(MODE))))
//Update this whenever you need to take advantage of more recent byond features
#define MIN_COMPILER_VERSION 513
#define MIN_COMPILER_BUILD 1514
#define MIN_COMPILER_VERSION 514
#define MIN_COMPILER_BUILD 1554
#if DM_VERSION < MIN_COMPILER_VERSION || DM_BUILD < MIN_COMPILER_BUILD
//Don't forget to update this part
#error Your version of BYOND is too out-of-date to compile this project. Go to https://secure.byond.com/download and update.
#error You need version 513.1514 or higher
#error You need version 514.1554 or higher
#endif
// Macros that must exist before world.dm
+3 -1
View File
@@ -5,7 +5,6 @@ GLOBAL_VAR_INIT(deafblock, 0)
GLOBAL_VAR_INIT(hulkblock, 0)
GLOBAL_VAR_INIT(teleblock, 0)
GLOBAL_VAR_INIT(fireblock, 0)
GLOBAL_VAR_INIT(xrayblock, 0)
GLOBAL_VAR_INIT(clumsyblock, 0)
GLOBAL_VAR_INIT(fakeblock, 0)
GLOBAL_VAR_INIT(coughblock, 0)
@@ -30,6 +29,9 @@ GLOBAL_VAR_INIT(hallucinationblock, 0)
GLOBAL_VAR_INIT(noprintsblock, 0)
GLOBAL_VAR_INIT(shockimmunityblock, 0)
GLOBAL_VAR_INIT(smallsizeblock, 0)
GLOBAL_VAR_INIT(mesonblock, 0)
GLOBAL_VAR_INIT(noflashblock, 0)
GLOBAL_VAR_INIT(nightvisionblock, 0)
///////////////////////////////
// Goon Stuff
+3
View File
@@ -46,6 +46,9 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_DWARF" = TRAIT_DWARF,
"TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS,
"TRAIT_ALCOHOL_TOLERANCE" = TRAIT_ALCOHOL_TOLERANCE,
"TRAIT_MESON_VISION" = TRAIT_MESON_VISION,
"TRAIT_FLASH_PROTECTION" = TRAIT_FLASH_PROTECTION,
"TRAIT_NIGHT_VISION" = TRAIT_NIGHT_VISION,
"TRAIT_COMIC_SANS" = TRAIT_COMIC_SANS,
"TRAIT_NOFINGERPRINTS" = TRAIT_NOFINGERPRINTS,
+1 -1
View File
@@ -23,7 +23,7 @@ SUBSYSTEM_DEF(metrics)
var/list/out = list()
out["@timestamp"] = time_stamp() // This is required by ElasticSearch, complete with this name. DO NOT REMOVE THIS.
out["cpu"] = world.cpu
// out["maptick"] = world.map_cpu // TODO: 514
out["maptick"] = world.map_cpu
out["elapsed_processed"] = world.time
out["elapsed_real"] = (REALTIMEOFDAY - world_init_time)
out["client_count"] = length(GLOB.clients)
@@ -49,6 +49,10 @@
var/mat_path = possible_mats[id]
materials[id] = new mat_path()
/datum/component/material_container/Destroy(force, silent)
QDEL_LIST_ASSOC_VAL(materials)
return ..()
/datum/component/material_container/proc/OnExamine(datum/source, mob/user, list/examine_list)
if(show_on_examine)
for(var/I in materials)
+3 -1
View File
@@ -44,12 +44,13 @@ GLOBAL_DATUM_INIT(event_announcement, /datum/announcement/priority/command/event
title = "Security Announcement"
announcement_type = "Security Announcement"
/datum/announcement/proc/Announce(message as text, new_title = "", new_sound = null, do_newscast = newscast, msg_sanitized = 0, from, msg_language)
/datum/announcement/proc/Announce(message as text, new_title = "", new_sound = null, do_newscast = newscast, msg_sanitized = 0, from, msg_language, new_sound2 = null)
if(!message)
return
var/message_title = new_title ? new_title : title
var/message_sound = new_sound ? sound(new_sound) : sound
var/message_sound2 = new_sound2 ? sound(new_sound2) : sound
if(!msg_sanitized)
message = trim_strip_html_properly(message, allow_lines = 1)
@@ -74,6 +75,7 @@ GLOBAL_DATUM_INIT(event_announcement, /datum/announcement/priority/command/event
NewsCast(message, message_title)
Sound(message_sound, combined_receivers[1] + combined_receivers[2])
Sound(message_sound2, combined_receivers[1] + combined_receivers[2])
Log(message, message_title)
/datum/announcement/proc/Get_Receivers(datum/language/message_language)
+2 -2
View File
@@ -346,7 +346,7 @@
var/obj/machinery/firealarm/F = alarm
F.update_fire_light(fire)
for(var/obj/machinery/light/L in src)
L.update()
L.update(TRUE, TRUE, FALSE)
/**
* unset the fire alarm visual affects in an area
@@ -360,7 +360,7 @@
var/obj/machinery/firealarm/F = alarm
F.update_fire_light(fire)
for(var/obj/machinery/light/L in src)
L.update()
L.update(TRUE, TRUE, FALSE)
/area/proc/updateicon()
var/weather_icon
+6 -2
View File
@@ -140,12 +140,16 @@
/datum/mutation/disability/colourblindness/activate(mob/M)
..()
M.update_client_colour() //Handle the activation of the colourblindness on the mob.
M.update_icons() //Apply eyeshine as needed.
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_misc_effects()
/datum/mutation/disability/colourblindness/deactivate(mob/M)
..()
M.update_client_colour() //Handle the deactivation of the colourblindness on the mob.
M.update_icons() //Remove eyeshine as needed.
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_misc_effects()
/datum/mutation/disability/deaf
name = "Deafness"
+55 -22
View File
@@ -158,28 +158,6 @@
M.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH //temporary fix until the problem can be solved.
to_chat(M, "<span class='danger'>You suddenly feel very weak.</span>")
/datum/mutation/xray
name = "X-Ray Vision"
activation_messages = list("The walls suddenly disappear.")
deactivation_messages = list("The walls around you re-appear.")
instability = GENE_INSTABILITY_MAJOR
traits_to_add = list(TRAIT_XRAY_VISION)
activation_prob = 15
/datum/mutation/xray/New()
..()
block = GLOB.xrayblock
/datum/mutation/xray/activate(mob/living/M)
..()
M.update_sight()
M.update_icons() //Apply eyeshine as needed.
/datum/mutation/xray/deactivate(mob/living/M)
..()
M.update_sight()
M.update_icons() //Remove eyeshine as needed.
/datum/mutation/tk
name = "Telekenesis"
activation_messages = list("You feel smarter.")
@@ -1181,3 +1159,58 @@
else
H.remoteview_target = null
H.reset_perspective()
/datum/mutation/meson_vision
name = "Meson Vision"
activation_messages = list("More information seems to reach your eyes...")
deactivation_messages = list("The amount of information reaching your eyes fades...")
instability = GENE_INSTABILITY_MINOR
traits_to_add = list(TRAIT_MESON_VISION)
/datum/mutation/meson_vision/New()
..()
block = GLOB.mesonblock
/datum/mutation/meson_vision/activate(mob/living/M)
..()
M.update_sight()
/datum/mutation/meson_vision/deactivate(mob/living/M)
..()
M.update_sight()
/datum/mutation/night_vision
name = "Night Vision"
activation_messages = list("Were the lights always that bright?")
deactivation_messages = list("The ambient light level returns to normal...")
instability = GENE_INSTABILITY_MODERATE
traits_to_add = list(TRAIT_NIGHT_VISION)
/datum/mutation/night_vision/New()
..()
block = GLOB.nightvisionblock
/datum/mutation/night_vision/activate(mob/living/M)
..()
M.update_sight()
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_misc_effects()
/datum/mutation/night_vision/deactivate(mob/living/M)
..()
M.update_sight()
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_misc_effects()
/datum/mutation/flash_protection
name = "Flash Protection"
activation_messages = list("You stop noticing the glare from lights...")
deactivation_messages = list("Lights begin glaring again...")
instability = GENE_INSTABILITY_MINOR
traits_to_add = list(TRAIT_FLASH_PROTECTION)
/datum/mutation/flash_protection/New()
..()
block = GLOB.noflashblock
+2 -2
View File
@@ -66,10 +66,10 @@
return
if(src.client)
if(client.prefs.muted & MUTE_IC)
if(check_mute(client.ckey, MUTE_IC))
to_chat(src, "You cannot send IC messages (muted).")
return
if(src.client.handle_spam_prevention(message,MUTE_IC))
if(src.client.handle_spam_prevention(message, MUTE_IC))
return
if(stat)
@@ -66,60 +66,6 @@
add_attack_logs(user, target, "Unsuccessful sting (changeling)")
return 1
/datum/action/changeling/sting/transformation
name = "Transformation Sting"
desc = "We silently sting a human, injecting a retrovirus that forces them to transform. Costs 50 chemicals."
helptext = "The victim will transform much like a changeling would. The effects will be obvious to the victim, and the process will damage our genomes."
button_icon_state = "sting_transform"
sting_icon = "sting_transform"
chemical_cost = 50
dna_cost = 3
genetic_damage = 100
var/datum/dna/selected_dna = null
/datum/action/changeling/sting/transformation/Trigger()
var/mob/user = usr
var/datum/changeling/changeling = user.mind.changeling
if(changeling.chosen_sting)
unset_sting(user)
return
selected_dna = changeling.select_dna("Select the target DNA: ", "Target DNA")
if(!selected_dna)
return
if((NOTRANSSTING in selected_dna.species.species_traits) || selected_dna.species.is_small)
to_chat(user, "<span class='warning'>The selected DNA is incompatible with our sting.</span>")
return
..()
/datum/action/changeling/sting/transformation/can_sting(mob/user, mob/target)
if(!..())
return
if(HAS_TRAIT(target, TRAIT_HUSK) || !ishuman(target) || (NOTRANSSTING in target.dna.species.species_traits))
to_chat(user, "<span class='warning'>Our sting appears ineffective against its DNA.</span>")
return FALSE
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(HAS_TRAIT(H, TRAIT_GENELESS))
to_chat(user, "<span class='warning'>This won't work on a creature without DNA.</span>")
return FALSE
return TRUE
/datum/action/changeling/sting/transformation/sting_action(mob/user, mob/target)
add_attack_logs(user, target, "Transformation sting (changeling) (new identity is [selected_dna.real_name])")
if(issmall(target))
to_chat(user, "<span class='notice'>Our genes cry out as we sting [target.name]!</span>")
if(iscarbon(target) && (target.status_flags & CANWEAKEN))
var/mob/living/carbon/C = target
C.do_jitter_animation(500)
target.visible_message("<span class='danger'>[target] begins to violenty convulse!</span>","<span class='userdanger'>You feel a tiny prick and a begin to uncontrollably convulse!</span>")
spawn(10)
transform_dna(target,selected_dna)//target is always human so no problem here
SSblackbox.record_feedback("nested tally", "changeling_powers", 1, list("[name]"))
return TRUE
/datum/action/changeling/sting/extract_dna
name = "Extract DNA Sting"
desc = "We stealthily sting a target and extract their DNA. Costs 25 chemicals."
+3
View File
@@ -73,6 +73,9 @@
var/airlock_unruned_icon_file = 'icons/obj/doors/airlocks/cult/unruned/cult.dmi'
var/airlock_unruned_overlays_file = 'icons/obj/doors/airlocks/cult/unruned/cult-overlays.dmi'
/// Are cultist mirror shields active yet?
var/mirror_shields_active = FALSE
/datum/cult_info/fire
name = "Cult of Kha'Rin"
+5
View File
@@ -444,6 +444,11 @@
* The illusion has a 60% chance to be hostile and attack non-cultists, and a 40% chance to just run away from the user.
*/
/obj/item/shield/mirror/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
// Incase they get one by some magic
if(!SSticker.cultdat.mirror_shields_active)
to_chat(owner, "<span class='warning'>This shield is powerless! You must perform the required sacrifice to empower it!</span>")
return
if(iscultist(owner) && !owner.holy_check()) // Cultist holding the shield
// Hit by a projectile
+21 -4
View File
@@ -86,8 +86,10 @@
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [get_ETA()].</span>")
return
var/choice = show_radial_menu(user, src, choosable_items, require_near = TRUE)
var/picked_type = choosable_items[choice]
var/list/pickable_items = get_choosable_items()
var/choice = show_radial_menu(user, src, pickable_items, require_near = TRUE)
var/picked_type = pickable_items[choice]
if(!QDELETED(src) && picked_type && Adjacent(user) && !user.incapacitated() && cooldowntime <= world.time)
cooldowntime = world.time + creation_delay
var/obj/O = new picked_type
@@ -95,6 +97,14 @@
O.forceMove(get_turf(src))
to_chat(user, replacetext("[creation_message]", "%ITEM%", "[O.name]"))
/**
* Returns the items the cult can craft from this forge.
*
* Override on children for logic regarding game state.
*/
/obj/structure/cult/functional/proc/get_choosable_items()
return choosable_items.Copy() // Copied incase its modified on children
/**
* Returns the cooldown time in minutes and seconds
*/
@@ -159,8 +169,15 @@
selection_prompt = "You study the schematics etched on the forge..."
selection_title = "Forge"
creation_message = "<span class='cultitalic'>You work the forge as dark knowledge guides your hands, creating a %ITEM%!</span>"
choosable_items = list("Shielded Robe" = /obj/item/clothing/suit/hooded/cultrobes/cult_shield, "Flagellant's Robe" = /obj/item/clothing/suit/hooded/cultrobes/flagellant_robe,
"Mirror Shield" = /obj/item/shield/mirror)
choosable_items = list("Shielded Robe" = /obj/item/clothing/suit/hooded/cultrobes/cult_shield, "Flagellant's Robe" = /obj/item/clothing/suit/hooded/cultrobes/flagellant_robe)
/obj/structure/cult/functional/forge/get_choosable_items()
. = ..()
if(SSticker.cultdat.mirror_shields_active)
// Both lines here are needed. If you do it without, youll get issues.
. += "Mirror Shield"
.["Mirror Shield"] = /obj/item/shield/mirror
/obj/structure/cult/functional/forge/Initialize(mapload)
. = ..()
+3
View File
@@ -384,6 +384,9 @@ structure_check() searches for nearby cultist structures required for the invoca
for(var/M in invokers)
if(sacrifice_fulfilled)
to_chat(M, "<span class='cultlarge'>\"Yes! This is the one I desire! You have done well.\"</span>")
if(!SSticker.cultdat.mirror_shields_active) // Only show once
to_chat(M, "<span class='cultitalic'>You are now able to construct mirror shields inside the daemon forge.</span>")
SSticker.cultdat.mirror_shields_active = TRUE
else
if(ishuman(offering) && offering.mind.offstation_role && offering.mind.special_role != SPECIAL_ROLE_ERT) //If you try it on a ghost role, you get nothing
to_chat(M, "<span class='cultlarge'>\"This soul is of no use to either of us.\"</span>")
@@ -248,7 +248,7 @@
/datum/action/innate/ai/nuke_station/proc/set_us_up_the_bomb()
to_chat(owner_AI, "<span class='notice'>Nuclear device armed.</span>")
GLOB.event_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg')
GLOB.event_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", 'sound/AI/aimalf.ogg')
set_security_level("delta")
owner_AI.nuking = TRUE
var/obj/machinery/doomsday_device/DOOM = new /obj/machinery/doomsday_device(owner_AI)
@@ -280,7 +280,7 @@
if(SSshuttle.emergency.mode == SHUTTLE_STRANDED)
SSshuttle.emergency.mode = SHUTTLE_DOCKED
SSshuttle.emergency.timer = world.time
GLOB.priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg')
GLOB.priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/eshuttle_dock.ogg')
return ..()
/obj/machinery/doomsday_device/proc/start()
@@ -300,7 +300,7 @@
if(SSshuttle.emergency.mode == SHUTTLE_STRANDED)
SSshuttle.emergency.mode = SHUTTLE_DOCKED
SSshuttle.emergency.timer = world.time
GLOB.priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg')
GLOB.priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/eshuttle_dock.ogg')
qdel(src)
if(!timing)
STOP_PROCESSING(SSfastprocess, src)
@@ -4,10 +4,10 @@
/mob/living/captive_brain/say(message)
if(client)
if(client.prefs.muted & MUTE_IC)
if(check_mute(client.ckey, MUTE_IC))
to_chat(src, "<span class='warning'>You cannot speak in IC (muted).</span>")
return
if(client.handle_spam_prevention(message,MUTE_IC))
if(client.handle_spam_prevention(message, MUTE_IC))
return
if(istype(loc,/mob/living/simple_animal/borer))
+1 -1
View File
@@ -220,7 +220,7 @@
if(SSshuttle.emergency.mode == SHUTTLE_STRANDED)
SSshuttle.emergency.mode = SHUTTLE_DOCKED
SSshuttle.emergency.timer = world.time
GLOB.command_announcement.Announce("Hostile enviroment resolved. You have 3 minutes to board the Emergency Shuttle.", null, 'sound/AI/shuttledock.ogg')
GLOB.command_announcement.Announce("Hostile enviroment resolved. You have 3 minutes to board the Emergency Shuttle.", null, 'sound/AI/eshuttle_dock.ogg')
return ..()
if(finished != 0)
return TRUE
+4 -2
View File
@@ -40,7 +40,6 @@
GLOB.hulkblock = getAssignedBlock("HULK", numsToAssign, DNA_HARD_BOUNDS, good=1)
GLOB.teleblock = getAssignedBlock("TELE", numsToAssign, DNA_HARD_BOUNDS, good=1)
GLOB.fireblock = getAssignedBlock("FIRE", numsToAssign, DNA_HARDER_BOUNDS, good=1)
GLOB.xrayblock = getAssignedBlock("XRAY", numsToAssign, DNA_HARDER_BOUNDS, good=1)
GLOB.clumsyblock = getAssignedBlock("CLUMSY", numsToAssign)
GLOB.fakeblock = getAssignedBlock("FAKE", numsToAssign)
GLOB.coughblock = getAssignedBlock("COUGH", numsToAssign)
@@ -49,6 +48,10 @@
GLOB.twitchblock = getAssignedBlock("TWITCH", numsToAssign)
GLOB.nervousblock = getAssignedBlock("NERVOUS", numsToAssign)
GLOB.wingdingsblock = getAssignedBlock("WINGDINGS", numsToAssign)
GLOB.mesonblock = getAssignedBlock("MESONS", numsToAssign, good=1)
GLOB.noflashblock = getAssignedBlock("NOFLASH", numsToAssign, DNA_HARDER_BOUNDS, good=1)
GLOB.nightvisionblock = getAssignedBlock("NIGHTVISION", numsToAssign, DNA_HARDER_BOUNDS, good=1)
// Bay muts
GLOB.breathlessblock = getAssignedBlock("BREATHLESS", numsToAssign, DNA_HARD_BOUNDS, good=1)
@@ -62,7 +65,6 @@
GLOB.noprintsblock = getAssignedBlock("NOPRINTS", numsToAssign, DNA_HARD_BOUNDS, good=1)
GLOB.shockimmunityblock = getAssignedBlock("SHOCKIMMUNITY", numsToAssign, good=1)
GLOB.smallsizeblock = getAssignedBlock("SMALLSIZE", numsToAssign, DNA_HARD_BOUNDS, good=1)
//
// Goon muts
/////////////////////////////////////////////
+2 -2
View File
@@ -74,8 +74,8 @@
return 0
/datum/theft_objective/defib
name = "a compact defibrillator"
typepath = /obj/item/defibrillator/compact
name = "the chief medical officer's advanced compact defibrillator"
typepath = /obj/item/defibrillator/compact/advanced
protected_jobs = list("Chief Medical Officer", "Paramedic")
location_override = "the Chief Medical Officer's Office"
+4 -2
View File
@@ -4,7 +4,8 @@
name = "Bluespace Gigabeacon"
desc = "A device that draws power from bluespace and creates a permanent tracking beacon."
level = 1 // underfloor
layer = 2.5
layer = WIRE_LAYER
plane = FLOOR_PLANE
anchored = 1
use_power = IDLE_POWER_USE
idle_power_usage = 0
@@ -26,7 +27,8 @@
Beacon.syndicate = syndicate
Beacon.area_bypass = area_bypass
Beacon.cc_beacon = cc_beacon
hide(T.intact)
if(!T.transparent_floor)
hide(T.intact)
/obj/machinery/bluespace_beacon/proc/destroy_beacon()
QDEL_NULL(Beacon)
+1
View File
@@ -100,6 +100,7 @@ GLOBAL_LIST_INIT(cloner_biomass_items, list(\
/obj/machinery/clonepod/Destroy()
if(connected)
connected.pods -= src
connected = null
if(clonemind)
UnregisterSignal(clonemind.current, COMSIG_LIVING_REVIVE)
UnregisterSignal(clonemind, COMSIG_MIND_TRANSER_TO)
+29 -19
View File
@@ -34,6 +34,24 @@
light_color = LIGHT_COLOR_DARKGREEN
/obj/machinery/computer/message_monitor/Initialize()
..()
return INITIALIZE_HINT_LATELOAD // Give the message server time to initialize
/obj/machinery/computer/message_monitor/LateInitialize()
//If the monitor isn't linked to a server, and there's a server available, default it to the first one in the list.
if(!linkedServer && length(GLOB.message_servers))
linkedServer = GLOB.message_servers[1]
RegisterSignal(linkedServer, COMSIG_PARENT_QDELETING, .proc/unlink_server)
/obj/machinery/computer/message_monitor/proc/unlink_server()
SIGNAL_HANDLER
linkedServer = null
/obj/machinery/computer/message_monitor/Destroy()
customrecepient = null
linkedServer = null
return ..()
/obj/machinery/computer/message_monitor/screwdriver_act(mob/user, obj/item/I)
if(emag) //Stops people from just unscrewing the monitor and putting it back to get the console working again.
@@ -71,14 +89,6 @@
..()
/obj/machinery/computer/message_monitor/Initialize()
..()
//Is the server isn't linked to a server, and there's a server available, default it to the first one in the list.
if(!linkedServer)
if(GLOB.message_servers && GLOB.message_servers.len > 0)
linkedServer = GLOB.message_servers[1]
return
/obj/machinery/computer/message_monitor/attack_hand(mob/user as mob)
if(..())
return
@@ -490,18 +500,18 @@
/obj/item/paper/monitorkey
//..()
name = "Monitor Decryption Key"
var/obj/machinery/message_server/server = null
/obj/item/paper/monitorkey/New()
/obj/item/paper/monitorkey/Initialize(mapload)
..()
spawn(10)
if(GLOB.message_servers)
for(var/obj/machinery/message_server/server in GLOB.message_servers)
if(!isnull(server))
if(!isnull(server.decryptkey))
info = "<center><h2>Daily Key Reset</h2></center>\n\t<br>The new message monitor key is '[server.decryptkey]'.<br>Please keep this a secret and away from the clown.<br>If necessary, change the password to a more secure one."
info_links = info
overlays += "paper_words"
break
return INITIALIZE_HINT_LATELOAD
/obj/item/paper/monitorkey/LateInitialize()
for(var/obj/machinery/message_server/server in GLOB.message_servers)
if(!isnull(server))
if(!isnull(server.decryptkey))
info = "<center><h2>Daily Key Reset</h2></center>\n\t<br>The new message monitor key is '[server.decryptkey]'.<br>Please keep this a secret and away from the clown.<br>If necessary, change the password to a more secure one."
info_links = info
overlays += "paper_words"
break
+2 -2
View File
@@ -34,8 +34,8 @@
if(building)
set_pixel_offsets_from_dir(30, -30, 30, -30)
/obj/machinery/defibrillator_mount/loaded/New() //loaded subtype for mapping use
..()
/obj/machinery/defibrillator_mount/loaded/Initialize(mapload) //loaded subtype for mapping use
. = ..()
defib = new/obj/item/defibrillator/loaded(src)
update_icon()
+1 -1
View File
@@ -43,7 +43,7 @@ GLOBAL_LIST_EMPTY(holopads)
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 100
layer = TURF_LAYER+0.1 //Preventing mice and drones from sneaking under them.
layer = HOLOPAD_LAYER //Preventing mice and drones from sneaking under them.
plane = FLOOR_PLANE
max_integrity = 300
armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 0)
+1
View File
@@ -77,6 +77,7 @@
/obj/machinery/light_switch/attack_hand(mob/user)
on = !on
playsound(src, 'sound/machines/lightswitch.ogg', 10, TRUE)
updateicon()
if(light_connect)
+3 -2
View File
@@ -11,7 +11,7 @@
name = "Electromagnetic Generator"
desc = "A device that uses station power to create points of magnetic energy."
level = 1 // underfloor
layer = 2.5
layer = WIRE_LAYER+0.001
anchored = 1
use_power = IDLE_POWER_USE
idle_power_usage = 50
@@ -32,7 +32,8 @@
/obj/machinery/magnetic_module/New()
..()
var/turf/T = loc
hide(T.intact)
if(!T.transparent_floor)
hide(T.intact)
center = T
spawn(10) // must wait for map loading to finish
+4 -2
View File
@@ -8,7 +8,8 @@
name = "navigation beacon"
desc = "A radio beacon used for bot navigation."
level = 1 // underfloor
layer = 2.5
layer = WIRE_LAYER
plane = FLOOR_PLANE
anchored = 1
max_integrity = 500
armor = list(melee = 70, bullet = 70, laser = 70, energy = 70, bomb = 0, bio = 0, rad = 0, fire = 80, acid = 80)
@@ -26,7 +27,8 @@
set_codes()
var/turf/T = loc
hide(T.intact)
if(!T.transparent_floor)
hide(T.intact)
if(!codes || !codes.len)
log_runtime(EXCEPTION("Empty codes datum at ([x],[y],[z])"), src, list("codes_txt: '[codes_txt]'"))
if("patrol" in codes)
+6
View File
@@ -337,12 +337,18 @@
fixdir()
var/pipe_dir = get_pipe_dir()
var/turf/T = get_turf(loc)
for(var/obj/machinery/atmospherics/M in src.loc)
if((M.initialize_directions & pipe_dir) && M.check_connect_types_construction(M,src)) // matches at least one direction on either type of pipe
to_chat(user, "<span class='warning'>There is already a pipe of the same type at this location.</span>")
return 1
if(pipe_type in list(PIPE_SUPPLY_STRAIGHT, PIPE_SUPPLY_BENT, PIPE_SCRUBBERS_STRAIGHT, PIPE_SCRUBBERS_BENT, PIPE_HE_STRAIGHT, PIPE_HE_BENT, PIPE_SUPPLY_MANIFOLD, PIPE_SCRUBBERS_MANIFOLD, PIPE_SUPPLY_MANIFOLD4W, PIPE_SCRUBBERS_MANIFOLD4W, PIPE_UVENT, PIPE_SUPPLY_CAP, PIPE_SCRUBBERS_CAP, PIPE_PASV_VENT, PIPE_DP_VENT, PIPE_PASSIVE_GATE))
if(T.transparent_floor) //stops jank with transparent floors and pipes
to_chat(user, "<span class='warning'>You can only fix simple pipes and devices over glass floors!</span>")
return 1
switch(pipe_type) //What kind of heartless person thought of doing this?
if(PIPE_SIMPLE_STRAIGHT, PIPE_SIMPLE_BENT)
var/obj/machinery/atmospherics/pipe/simple/P = new( src.loc )
+61 -2
View File
@@ -117,6 +117,12 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
var/in_inventory = FALSE //is this item equipped into an inventory slot or hand of a mob?
var/tip_timer = 0
// item hover FX
/// Is this item inside a storage object?
var/in_storage = FALSE
/// Holder var for the item outline filter, null when no outline filter on the item.
var/outline_filter
/obj/item/New()
..()
for(var/path in actions_types)
@@ -131,6 +137,11 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
if(!move_resist)
determine_move_resist()
/obj/item/Initialize(mapload)
. = ..()
if(istype(loc, /obj/item/storage)) //marks all items in storage as being such
in_storage = TRUE
/obj/item/proc/determine_move_resist()
switch(w_class)
if(WEIGHT_CLASS_TINY)
@@ -406,6 +417,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
if((flags & NODROP) && !(initial(flags) & NODROP)) //Remove NODROP is dropped
flags &= ~NODROP
in_inventory = FALSE
remove_outline()
SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user)
if(!silent)
playsound(src, drop_sound, DROP_SOUND_VOLUME, ignore_walls = FALSE)
@@ -418,10 +430,12 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
// called when this item is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
/obj/item/proc/on_exit_storage(obj/item/storage/S as obj)
in_storage = FALSE
return
// called when this item is added into a storage item, which is passed on as S. The loc variable is already set to the storage item.
/obj/item/proc/on_enter_storage(obj/item/storage/S as obj)
in_storage = TRUE
return
/**
@@ -691,14 +705,24 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
openToolTip(user, src, params, title = name, content = "[desc]", theme = "")
/obj/item/MouseEntered(location, control, params)
if(in_inventory)
if(in_inventory || in_storage)
var/timedelay = 8
var/user = usr
var/mob/user = usr
tip_timer = addtimer(CALLBACK(src, .proc/openTip, location, control, params, user), timedelay, TIMER_STOPPABLE)
if(QDELETED(src))
return
var/mob/living/L = user
if(!(user.client.prefs.toggles2 & PREFTOGGLE_2_SEE_ITEM_OUTLINES))
return
if(istype(L) && L.incapacitated(ignore_lying = TRUE))
apply_outline(L, COLOR_RED_GRAY) //if they're dead or handcuffed, let's show the outline as red to indicate that they can't interact with that right now
else
apply_outline(L) //if the player's alive and well we send the command with no color set, so it uses the theme's color
/obj/item/MouseExited()
deltimer(tip_timer) //delete any in-progress timer if the mouse is moved off the item before it finishes
closeToolTip(usr)
remove_outline()
/obj/item/MouseDrop_T(obj/item/I, mob/user)
if(!user || user.incapacitated(ignore_lying = TRUE) || src == I)
@@ -707,6 +731,41 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
if(loc && I.loc == loc && istype(loc, /obj/item/storage) && loc.Adjacent(user)) // Are we trying to swap two items in the storage?
var/obj/item/storage/S = loc
S.swap_items(src, I, user)
remove_outline() //get rid of the hover effect in case the mouse exit isn't called if someone drags and drops an item and somthing goes wrong
/obj/item/proc/apply_outline(mob/user, outline_color = null)
if(!(in_inventory || in_storage) || QDELETED(src) || isobserver(user)) //cancel if the item isn't in an inventory, is being deleted, or if the person hovering is a ghost (so that people spectating you don't randomly make your items glow)
return
var/theme = lowertext(user.client.prefs.UI_style)
if(!outline_color) //if we weren't provided with a color, take the theme's color
switch(theme) //yeah it kinda has to be this way
if("midnight")
outline_color = COLOR_THEME_MIDNIGHT
if("plasmafire")
outline_color = COLOR_THEME_PLASMAFIRE
if("retro")
outline_color = COLOR_THEME_RETRO //just as garish as the rest of this theme
if("slimecore")
outline_color = COLOR_THEME_SLIMECORE
if("operative")
outline_color = COLOR_THEME_OPERATIVE
if("clockwork")
outline_color = COLOR_THEME_CLOCKWORK //if you want free gbp go fix the fact that clockwork's tooltip css is glass'
if("glass")
outline_color = COLOR_THEME_GLASS
else //this should never happen, hopefully
outline_color = COLOR_WHITE
if(color)
outline_color = COLOR_WHITE //if the item is recolored then the outline will be too, let's make the outline white so it becomes the same color instead of some ugly mix of the theme and the tint
if(outline_filter)
filters -= outline_filter
outline_filter = filter(type = "outline", size = 1, color = outline_color)
filters += outline_filter
/obj/item/proc/remove_outline()
if(outline_filter)
filters -= outline_filter
outline_filter = null
// Returns a numeric value for sorting items used as parts in machines, so they can be replaced by the rped
/obj/item/proc/get_part_rating()
@@ -195,23 +195,16 @@
if(target.status != LIGHT_EMPTY)
AddShards(1, U)
target.status = LIGHT_EMPTY
target.update()
var/obj/item/light/L2 = new target.light_type()
target.status = L2.status
target.switchcount = L2.switchcount
var/obj/item/light/replacement = target.light_type
target.status = LIGHT_OK
target.switchcount = 0
target.rigged = emagged
target.brightness_range = L2.brightness_range
target.brightness_power = L2.brightness_power
target.brightness_color = L2.brightness_color
target.brightness_range = initial(replacement.brightness_range)
target.brightness_power = initial(replacement.brightness_power)
target.brightness_color = initial(replacement.brightness_color)
target.on = target.has_power()
target.update()
qdel(L2)
if(target.on && target.rigged)
target.explode()
return
target.update(TRUE, TRUE, FALSE)
else
to_chat(U, "[src]'s refill light blinks red.")
+1 -1
View File
@@ -13,7 +13,7 @@
var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TATER!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "FOR THE SYNDICATE!")
/obj/item/megaphone/attack_self(mob/living/user as mob)
if(user.client && (user.client.prefs.muted & MUTE_IC))
if(check_mute(user.ckey, MUTE_IC))
to_chat(src, "<span class='warning'>You cannot speak in IC (muted).</span>")
return
if(!ishuman(user))
@@ -27,8 +27,8 @@
return
var/turf/T = get_turf(P)
if(P.level < 2 && T.level == 1 && T.intact)
to_chat(user, "<span class='warning'>You must remove the plating first.</span>")
if(P.level < 2 && T.level == 1 && T.intact && !T.transparent_floor)
to_chat(user, "<span class='warning'>You must remove the flooring first.</span>")
return
P.change_color(GLOB.pipe_colors[paint_setting])
+77 -32
View File
@@ -3,6 +3,7 @@
/obj/item/defibrillator
name = "defibrillator"
desc = "A device that delivers powerful shocks to detachable paddles that resuscitate incapacitated patients."
icon = 'icons/obj/defib.dmi'
icon_state = "defibunit"
item_state = "defibunit"
slot_flags = SLOT_BACK
@@ -17,27 +18,27 @@
)
var/paddles_on_defib = TRUE //if the paddles are on the defib (TRUE)
var/safety = TRUE //if you can zap people with the defibs on harm mode
var/powered = FALSE //if there's a cell in the defib with enough power for a revive, blocks paddles from reviving otherwise
var/obj/item/twohanded/shockpaddles/paddles
var/obj/item/stock_parts/cell/high/cell = null
var/safety = TRUE //if you can zap people with the defibs on harm mode
var/combat = FALSE //can we revive through space suits?
var/heart_attack = FALSE //can it give instant heart attacks when zapped on harm intent with combat?
var/base_icon_state = "defibpaddles"
var/obj/item/twohanded/shockpaddles/paddle_type = /obj/item/twohanded/shockpaddles
/obj/item/defibrillator/get_cell()
return cell
/obj/item/defibrillator/New() //starts without a cell for rnd
..()
paddles = make_paddles()
/obj/item/defibrillator/Initialize(mapload) //starts without a cell for rnd
. = ..()
paddles = new paddle_type(src)
update_icon()
return
/obj/item/defibrillator/loaded/New() //starts with hicap
..()
paddles = make_paddles()
/obj/item/defibrillator/loaded/Initialize(mapload) //starts with hicap
. = ..()
cell = new(src)
update_icon()
return
/obj/item/defibrillator/update_icon()
update_power()
@@ -158,9 +159,6 @@
var/datum/action/A = X
A.UpdateButtonIcon()
/obj/item/defibrillator/proc/make_paddles()
return new /obj/item/twohanded/shockpaddles(src)
/obj/item/defibrillator/equipped(mob/user, slot)
..()
if(slot != slot_back)
@@ -214,38 +212,68 @@
/obj/item/defibrillator/compact
name = "compact defibrillator"
desc = "A belt-equipped defibrillator that can be rapidly deployed."
desc = "A belt-mounted defibrillator that can be rapidly deployed."
icon_state = "defibcompact"
item_state = "defibcompact"
sprite_sheets = null //Because Vox had the belt defibrillator sprites in back.dm
w_class = WEIGHT_CLASS_NORMAL
slot_flags = SLOT_BELT
origin_tech = "biotech=5"
/obj/item/defibrillator/compact/loaded/Initialize(mapload)
. = ..()
cell = new(src)
update_icon()
/obj/item/defibrillator/compact/item_action_slot_check(slot, mob/user)
if(slot == slot_belt)
return TRUE
/obj/item/defibrillator/compact/loaded/New()
..()
paddles = make_paddles()
cell = new(src)
update_icon()
return
/obj/item/defibrillator/compact/combat
name = "combat defibrillator"
desc = "A belt-equipped blood-red defibrillator that can be rapidly deployed. Does not have the restrictions or safeties of conventional defibrillators and can revive through space suits."
desc = "A belt-mounted blood-red defibrillator that can be rapidly deployed. Does not have the restrictions or safeties of conventional defibrillators and can revive through space suits."
icon_state = "defibcombat"
item_state = "defibcombat"
paddle_type = /obj/item/twohanded/shockpaddles/syndicate
combat = TRUE
safety = FALSE
/obj/item/defibrillator/compact/combat/loaded/New()
..()
paddles = make_paddles()
/obj/item/defibrillator/compact/combat/loaded/Initialize(mapload)
. = ..()
cell = new(src)
update_icon()
return
/obj/item/defibrillator/compact/combat/attackby(obj/item/W, mob/user, params)
/obj/item/defibrillator/compact/advanced
name = "advanced compact defibrillator"
desc = "A belt-mounted state-of-the-art defibrillator that can be rapidly deployed in all environments. Uses an experimental self-charging cell, meaning that it will (probably) never stop working. Can be used to defibrillate through space suits. It is impossible to damage."
icon_state = "defibnt"
item_state = "defibnt"
paddle_type = /obj/item/twohanded/shockpaddles/advanced
combat = TRUE
safety = TRUE
heart_attack = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF //Objective item, better not have it destroyed.
var/next_emp_message //to prevent spam from the emagging message on the advanced defibrillator
/obj/item/defibrillator/compact/advanced/attackby(obj/item/W, mob/user, params)
if(W == paddles)
paddles.unwield()
toggle_paddles()
update_icon()
/obj/item/defibrillator/compact/advanced/loaded/Initialize(mapload)
. = ..()
cell = new /obj/item/stock_parts/cell/bluespace/charging(src)
update_icon()
/obj/item/defibrillator/compact/advanced/emp_act(severity)
if(world.time > next_emp_message)
atom_say("Warning: Electromagnetic pulse detected. Integrated shielding prevented all potential hardware damage.")
playsound(src, 'sound/machines/defib_saftyon.ogg', 50)
next_emp_message = world.time + 5 SECONDS
/obj/item/defibrillator/compact/advanced/attackby(obj/item/W, mob/user, params)
if(W == paddles)
paddles.unwield()
toggle_paddles()
@@ -257,6 +285,7 @@
/obj/item/twohanded/shockpaddles
name = "defibrillator paddles"
desc = "A pair of plastic-gripped paddles with flat metal surfaces that are used to deliver powerful electric shocks."
icon = 'icons/obj/defib.dmi'
icon_state = "defibpaddles"
item_state = "defibpaddles"
force = 0
@@ -268,6 +297,7 @@
var/revivecost = 1000
var/cooldown = FALSE
var/busy = FALSE
var/base_icon_state = "defibpaddles"
var/obj/item/defibrillator/defib
/obj/item/twohanded/shockpaddles/New(mainunit)
@@ -280,10 +310,10 @@
return
/obj/item/twohanded/shockpaddles/update_icon()
icon_state = "defibpaddles[wielded]"
item_state = "defibpaddles[wielded]"
icon_state = "[base_icon_state][wielded]"
item_state = "[base_icon_state][wielded]"
if(cooldown)
icon_state = "defibpaddles[wielded]_cooldown"
icon_state = "[base_icon_state][wielded]_cooldown"
/obj/item/twohanded/shockpaddles/suicide_act(mob/user)
user.visible_message("<span class='danger'>[user] is putting the live paddles on [user.p_their()] chest! It looks like [user.p_theyre()] trying to commit suicide.</span>")
@@ -336,7 +366,7 @@
to_chat(user, "<span class='notice'>[defib] is recharging.</span>")
return
if(!ishuman(M))
to_chat(user, "<span class='notice'>The instructions on [defib] don't mention how to revive that...</span>")
to_chat(user, "<span class='notice'>The instructions on [defib] don't mention how to defibrillate that...</span>")
return
else
if(user.a_intent == INTENT_HARM && !defib.safety)
@@ -347,7 +377,7 @@
H.Weaken(5)
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
H.emote("gasp")
if(!H.undergoing_cardiac_arrest() && (prob(10) || defib.combat)) // Your heart explodes.
if(!H.undergoing_cardiac_arrest() && (prob(10) || (defib.combat && !defib.heart_attack) || prob(10) && (defib.combat && defib.heart_attack))) // Your heart explodes.
H.set_heartattack(TRUE)
SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK, 100)
add_attack_logs(user, M, "Stunned with [src]")
@@ -470,7 +500,8 @@
/obj/item/borg_defib
name = "defibrillator paddles"
desc = "A pair of mounted paddles with flat metal surfaces that are used to deliver powerful electric shocks."
desc = "A pair of paddles with flat metal surfaces that are used to deliver powerful electric shocks."
icon = 'icons/obj/defib.dmi'
icon_state = "defibpaddles0"
item_state = "defibpaddles0"
force = 0
@@ -590,3 +621,17 @@
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
busy = FALSE
update_icon()
/obj/item/twohanded/shockpaddles/syndicate
name = "combat defibrillator paddles"
desc = "A pair of high-tech paddles with flat plasteel surfaces to revive deceased operatives (unless they exploded). They possess both the ability to penetrate armor and to deliver powerful or disabling shocks offensively."
icon_state = "syndiepaddles0"
item_state = "syndiepaddles0"
base_icon_state = "syndiepaddles"
/obj/item/twohanded/shockpaddles/advanced
name = "advanced defibrillator paddles"
desc = "A pair of high-tech paddles with flat plasteel surfaces that are used to deliver powerful electric shocks. They possess the ability to penetrate armor to deliver shock."
icon_state = "ntpaddles0"
item_state = "ntpaddles0"
base_icon_state = "ntpaddles"
@@ -170,28 +170,6 @@
block = GLOB.hulkblock
..()
/obj/item/dnainjector/xraymut
name = "DNA-Injector (Xray)"
desc = "Finally you can see what the Captain does."
datatype = DNA2_BUF_SE
value = 0xFFF
forcedmutation = TRUE
/obj/item/dnainjector/xraymut/Initialize()
block = GLOB.xrayblock
..()
/obj/item/dnainjector/antixray
name = "DNA-Injector (Anti-Xray)"
desc = "It will make you see harder."
datatype = DNA2_BUF_SE
value = 0x001
forcedmutation = TRUE
/obj/item/dnainjector/antixray/Initialize()
block = GLOB.xrayblock
..()
/obj/item/dnainjector/firemut
name = "DNA-Injector (Fire)"
desc = "Gives you fire."
@@ -716,7 +716,6 @@
new /obj/item/stack/cable_coil(src)
new /obj/item/restraints/handcuffs(src)
new /obj/item/dnainjector/xraymut(src)
new /obj/item/dnainjector/firemut(src)
new /obj/item/dnainjector/telemut(src)
new /obj/item/dnainjector/hulkmut(src)
+2 -2
View File
@@ -90,7 +90,7 @@
/obj/blob_act(obj/structure/blob/B)
if(isturf(loc))
var/turf/T = loc
if(T.intact && level == 1) //the blob doesn't destroy thing below the floor
if((T.intact && level == 1) || T.transparent_floor) //the blob doesn't destroy thing below the floor
return
take_damage(400, BRUTE, "melee", 0, get_dir(src, B))
@@ -199,7 +199,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
/obj/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
if(isturf(loc))
var/turf/T = loc
if(T.intact && level == 1) //fire can't damage things hidden below the floor.
if((T.intact && level == 1) || T.transparent_floor) //fire can't damage things hidden below the floor.
return
..()
if(exposed_temperature && !(resistance_flags & FIRE_PROOF))
@@ -182,7 +182,7 @@
new /obj/item/clothing/shoes/brown (src)
new /obj/item/radio/headset/heads/cmo(src)
new /obj/item/clothing/gloves/color/latex/nitrile(src)
new /obj/item/defibrillator/compact/loaded(src)
new /obj/item/defibrillator/compact/advanced/loaded(src)
new /obj/item/handheld_defibrillator(src)
new /obj/item/storage/belt/medical(src)
new /obj/item/flash(src)
+2 -1
View File
@@ -368,7 +368,8 @@ GLOBAL_LIST_EMPTY(safes)
/obj/structure/safe/floor/Initialize()
. = ..()
var/turf/T = loc
hide(T.intact)
if(!T.transparent_floor)
hide(T.intact)
/obj/structure/safe/floor/hide(intact)
invisibility = intact ? INVISIBILITY_MAXIMUM : 0
+9 -1
View File
@@ -27,6 +27,7 @@ GLOBAL_LIST_INIT(icons_to_ignore_at_floor_init, list("damaged1","damaged2","dama
var/list/broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5")
var/list/burnt_states = list("floorscorched1", "floorscorched2")
var/list/prying_tool_list = list(TOOL_CROWBAR) //What tool/s can we use to pry up the tile?
var/keep_dir = TRUE //When false, resets dir to default on changeturf()
var/footstep = FOOTSTEP_FLOOR
var/barefootstep = FOOTSTEP_HARD_BAREFOOT
@@ -124,11 +125,18 @@ GLOBAL_LIST_INIT(icons_to_ignore_at_floor_init, list("damaged1","damaged2","dama
var/turf/simulated/floor/W = ..()
var/obj/machinery/atmospherics/R
if(keep_icon)
W.icon_regular_floor = old_icon
W.icon_plating = old_plating
if(W.keep_dir)
W.dir = old_dir
if(W.transparent_floor)
for(R in W)
R.update_icon()
for(R in W)
R.update_underlays()
W.update_icon()
return W
@@ -70,6 +70,35 @@
to_chat(user, "<span class='warning'>This section is too damaged to support a tile! Use a welder to fix the damage.</span>")
return TRUE
else if(is_glass_sheet(C))
if(broken || burnt)
to_chat(user, "<span class='warning'>Repair the plating first!</span>")
return TRUE
var/obj/item/stack/sheet/R = C
if(R.get_amount() < 2)
to_chat(user, "<span class='warning'>You need two sheets to build a [C.name] floor!</span>")
return TRUE
to_chat(user, "<span class='notice'>You begin swapping the plating for [C]...</span>")
if(do_after(user, 3 SECONDS * C.toolspeed, target = src))
if(R.get_amount() >= 2 && !transparent_floor)
if(istype(C, /obj/item/stack/sheet/plasmaglass)) //So, what type of glass floor do we want today?
ChangeTurf(/turf/simulated/floor/transparent/glass/plasma)
else if(istype(C, /obj/item/stack/sheet/plasmarglass))
ChangeTurf(/turf/simulated/floor/transparent/glass/reinforced/plasma)
else if(istype(C, /obj/item/stack/sheet/glass))
ChangeTurf(/turf/simulated/floor/transparent/glass)
else if(istype(C, /obj/item/stack/sheet/rglass))
ChangeTurf(/turf/simulated/floor/transparent/glass/reinforced)
else if(istype(C, /obj/item/stack/sheet/titaniumglass))
ChangeTurf(/turf/simulated/floor/transparent/glass/titanium)
else if(istype(C, /obj/item/stack/sheet/plastitaniumglass))
ChangeTurf(/turf/simulated/floor/transparent/glass/titanium/plasma)
playsound(src, C.usesound, 80, TRUE)
R.use(2)
to_chat(user, "<span class='notice'>You swap the plating for [C].</span>")
new /obj/item/stack/sheet/metal(src, 2)
return TRUE
/turf/simulated/floor/plating/screwdriver_act(mob/user, obj/item/I)
. = TRUE
if(!I.tool_use_check(user, 0))
@@ -0,0 +1,112 @@
/turf/simulated/floor/transparent/glass
name = "glass floor"
desc = "Don't jump on it... Or do, I'm not your mom."
icon = 'icons/turf/floors/glass.dmi'
icon_state = "unsmooth"
baseturf = /turf/space
smooth = SMOOTH_TRUE
canSmoothWith = list(/turf/simulated/floor/transparent/glass, /turf/simulated/floor/transparent/glass/reinforced, /turf/simulated/floor/transparent/glass/plasma, /turf/simulated/floor/transparent/glass/reinforced/plasma)
footstep = FOOTSTEP_GLASS
barefootstep = FOOTSTEP_GLASS_BAREFOOT
clawfootstep = FOOTSTEP_GLASS_BAREFOOT
heavyfootstep = FOOTSTEP_GLASS_BAREFOOT
light_power = 0.25
light_range = 2
layer = TRANSPARENT_TURF_LAYER
keep_dir = FALSE
intact = FALSE
transparent_floor = TRUE
heat_capacity = 800
/turf/simulated/floor/transparent/glass/Initialize(mapload)
. = ..()
var/image/I = image('icons/turf/space.dmi', src, SPACE_ICON_STATE)
I.plane = PLANE_SPACE
underlays += I
dir = SOUTH //dirs that are not 2/south cause smoothing jank
icon_state = "" //Prevents default icon appearing behind the glass
/turf/simulated/floor/transparent/glass/welder_act(mob/user, obj/item/I)
if(!broken && !burnt)
return
if(!I.tool_use_check(user, 0))
return
if(I.use_tool(src, user, volume = I.tool_volume))
to_chat(user, "<span class='notice'>You fix some cracks in the glass.</span>")
overlays -= current_overlay
current_overlay = null
burnt = FALSE
broken = FALSE
update_icon()
/turf/simulated/floor/transparent/glass/crowbar_act(mob/user, obj/item/I)
if(!I || !user)
return
var/obj/item/stack/R = user.get_inactive_hand()
if(istype(R, /obj/item/stack/sheet/metal))
if(R.get_amount() < 2) //not enough metal in the stack
to_chat(user, "<span class='danger'>You also need to hold two sheets of metal to dismantle [src]!</span>")
return
else
to_chat(user, "<span class='notice'>You begin replacing [src]...</span>")
playsound(src, I.usesound, 80, TRUE)
if(do_after(user, 3 SECONDS * I.toolspeed, target = src))
if(R.get_amount() < 2 || !transparent_floor)
return
else //not holding metal at all
to_chat(user, "<span class='danger'>You also need to hold two sheets of metal to dismantle \the [src]!</span>")
return
switch(type) //What material is returned? Depends on the turf
if(/turf/simulated/floor/transparent/glass/reinforced)
new /obj/item/stack/sheet/rglass(src, 2)
if(/turf/simulated/floor/transparent/glass)
new /obj/item/stack/sheet/glass(src, 2)
if(/turf/simulated/floor/transparent/glass/plasma)
new /obj/item/stack/sheet/plasmaglass(src, 2)
if(/turf/simulated/floor/transparent/glass/reinforced/plasma)
new /obj/item/stack/sheet/plasmarglass(src, 2)
if(/turf/simulated/floor/transparent/glass/titanium)
new /obj/item/stack/sheet/titaniumglass(src, 2)
if(/turf/simulated/floor/transparent/glass/titanium/plasma)
new /obj/item/stack/sheet/plastitaniumglass(src, 2)
R.use(2)
playsound(src, 'sound/items/deconstruct.ogg', 80, TRUE)
ChangeTurf(/turf/simulated/floor/plating)
/turf/simulated/floor/transparent/glass/reinforced
name = "reinforced glass floor"
desc = "Jump on it, it can cope. Promise..."
icon = 'icons/turf/floors/reinf_glass.dmi'
thermal_conductivity = 0.035
heat_capacity = 1600
/turf/simulated/floor/transparent/glass/reinforced/acid_act(acidpwr, acid_volume)
acidpwr = min(acidpwr, 50)
. = ..()
/turf/simulated/floor/transparent/glass/plasma
name = "plasma glass floor"
desc = "Wait, was space always that color?"
icon = 'icons/turf/floors/plasmaglass.dmi'
thermal_conductivity = 0.030
heat_capacity = 32000
/turf/simulated/floor/transparent/glass/reinforced/plasma
name = "reinforced plasma glass floor"
desc = "For when you REALLY don't want your floor choice to suffocate everyone."
icon = 'icons/turf/floors/reinf_plasmaglass.dmi'
thermal_conductivity = 0.025
heat_capacity = 325000
/turf/simulated/floor/transparent/glass/titanium
name = "titanium glass floor"
desc = "Stylish AND strong!"
icon = 'icons/turf/floors/titaniumglass.dmi'
canSmoothWith = list(/turf/simulated/floor/transparent/glass/titanium, /turf/simulated/floor/transparent/glass/titanium/plasma)
thermal_conductivity = 0.025
heat_capacity = 1600
/turf/simulated/floor/transparent/glass/titanium/plasma
name = "plastitanium glass floor"
icon = 'icons/turf/floors/plastitaniumglass.dmi'
+1
View File
@@ -6,6 +6,7 @@
var/intact = TRUE
var/turf/baseturf = /turf/space
var/slowdown = 0 //negative for faster, positive for slower
var/transparent_floor = FALSE //used to check if pipes should be visible under the turf or not
///Properties for open tiles (/floor)
/// All the gas vars, on the turf, are meant to be utilized for initializing a gas datum and setting its first gas values; the turf vars are never further modified at runtime; it is never directly used for calculations by the atmospherics system.
+2 -2
View File
@@ -25,7 +25,7 @@ GLOBAL_VAR_INIT(admin_ooc_colour, "#b82e00")
if(!GLOB.dooc_enabled && (mob.stat == DEAD))
to_chat(usr, "<span class='danger'>OOC for dead mobs has been turned off.</span>")
return
if(prefs.muted & MUTE_OOC)
if(check_mute(ckey, MUTE_OOC))
to_chat(src, "<span class='danger'>You cannot use OOC (muted).</span>")
return
@@ -181,7 +181,7 @@ GLOBAL_VAR_INIT(admin_ooc_colour, "#b82e00")
if(!GLOB.dooc_enabled && (mob.stat == DEAD))
to_chat(usr, "<span class='danger'>LOOC for dead mobs has been turned off.</span>")
return
if(prefs.muted & MUTE_OOC)
if(check_mute(ckey, MUTE_OOC))
to_chat(src, "<span class='danger'>You cannot use LOOC (muted).</span>")
return
+6 -8
View File
@@ -122,7 +122,6 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(M.ckey)
body += "<A href='?_src_=holder;boot2=[M.UID()]'>Kick</A> | "
body += "<A href='?_src_=holder;warn=[M.ckey]'>Warn</A> | "
body += "<A href='?_src_=holder;newban=[M.UID()];dbbanaddckey=[M.ckey]'>Ban</A> | "
body += "<A href='?_src_=holder;jobban2=[M.UID()];dbbanaddckey=[M.ckey]'>Jobban</A> | "
body += "<A href='?_src_=holder;appearanceban=[M.UID()];dbbanaddckey=[M.ckey]'>Appearance Ban</A> | "
@@ -141,14 +140,13 @@ GLOBAL_VAR_INIT(nologevent, 0)
body += "\ <A href='?_src_=holder;sendbacktolobby=[M.UID()]'>Send back to Lobby</A> | "
body += "\ <A href='?_src_=holder;eraseflavortext=[M.UID()]'>Erase Flavor Text</A> | "
body += "\ <A href='?_src_=holder;userandomname=[M.UID()]'>Use Random Name</A> | "
var/muted = M.client.prefs.muted
body += {"<br><b>Mute: </b>
\[<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_IC]'><font color='[(muted & MUTE_IC)?"red":"#6685f5"]'>IC</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_OOC]'><font color='[(muted & MUTE_OOC)?"red":"#6685f5"]'>OOC</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_PRAY]'><font color='[(muted & MUTE_PRAY)?"red":"#6685f5"]'>PRAY</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ADMINHELP]'><font color='[(muted & MUTE_ADMINHELP)?"red":"#6685f5"]'>ADMINHELP</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_DEADCHAT]'><font color='[(muted & MUTE_DEADCHAT)?"red":"#6685f5"]'>DEADCHAT</font></a>\]
(<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ALL]'><font color='[(muted & MUTE_ALL)?"red":"#6685f5"]'>toggle all</font></a>)
\[<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_IC]'><font color='[check_mute(M.client.ckey, MUTE_IC) ? "red" : "#6685f5"]'>IC</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_OOC]'><font color='[check_mute(M.client.ckey, MUTE_OOC) ? "red" : "#6685f5"]'>OOC</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_PRAY]'><font color='[check_mute(M.client.ckey, MUTE_PRAY) ? "red" : "#6685f5"]'>PRAY</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ADMINHELP]'><font color='[check_mute(M.client.ckey, MUTE_ADMINHELP) ? "red" : "#6685f5"]'>ADMINHELP</font></a> |
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_DEADCHAT]'><font color='[check_mute(M.client.ckey, MUTE_DEADCHAT) ?" red" : "#6685f5"]'>DEADCHAT</font></a>]
(<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ALL]'><font color='[check_mute(M.client.ckey, MUTE_ALL) ? "red" : "#6685f5"]'>toggle all</font></a>)
"}
var/jumptoeye = ""
-45
View File
@@ -492,51 +492,6 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
log_admin("[key_name(usr)] has turned BB mode [holder.fakekey ? "ON" : "OFF"]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Big Brother Mode")
#define MAX_WARNS 3
#define AUTOBANTIME 10
/client/proc/warn(warned_ckey)
if(!check_rights(R_ADMIN))
return
if(!warned_ckey || !istext(warned_ckey)) return
if(warned_ckey in GLOB.admin_datums)
to_chat(usr, "<font color='red'>Error: warn(): You can't warn admins.</font>")
return
var/datum/preferences/D
var/client/C = GLOB.directory[warned_ckey]
if(C) D = C.prefs
else D = GLOB.preferences_datums[warned_ckey]
if(!D)
to_chat(src, "<font color='red'>Error: warn(): No such ckey found.</font>")
return
if(++D.warns >= MAX_WARNS) //uh ohhhh...you'reee iiiiin trouuuubble O:)
if(C)
message_admins("[key_name_admin(src)] has warned [key_name_admin(C)] resulting in a [AUTOBANTIME] minute ban")
log_admin("[key_name(src)] has warned [key_name(C)] resulting in a [AUTOBANTIME] minute ban")
to_chat(C, "<font color='red'><BIG><B>You have been autobanned due to a warning by [ckey].</B></BIG><br>This is a temporary ban, it will be removed in [AUTOBANTIME] minutes.")
qdel(C)
else
message_admins("[key_name_admin(src)] has warned [warned_ckey] resulting in a [AUTOBANTIME] minute ban")
log_admin("[key_name(src)] has warned [warned_ckey] resulting in a [AUTOBANTIME] minute ban")
AddBan(warned_ckey, D.last_id, "Autobanning due to too many formal warnings", ckey, 1, AUTOBANTIME)
else
if(C)
to_chat(C, "<font color='red'><BIG><B>You have been formally warned by an administrator.</B></BIG><br>Further warnings will result in an autoban.</font>")
message_admins("[key_name_admin(src)] has warned [key_name_admin(C)]. They have [MAX_WARNS-D.warns] strikes remaining.")
log_admin("[key_name(src)] has warned [key_name(C)]. They have [MAX_WARNS-D.warns] strikes remaining.")
else
message_admins("[key_name_admin(src)] has warned [warned_ckey] (DC). They have [MAX_WARNS-D.warns] strikes remaining.")
log_admin("[key_name(src)] has warned [warned_ckey] (DC). They have [MAX_WARNS-D.warns] strikes remaining.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Warning") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
#undef MAX_WARNS
#undef AUTOBANTIME
/client/proc/drop_bomb() // Some admin dickery that can probably be done better -- TLE
set category = "Event"
set name = "Drop Bomb"
+32
View File
@@ -0,0 +1,32 @@
/// Associative list of people who are muted via admin mutes
GLOBAL_LIST_EMPTY(admin_mutes_assoc)
/proc/check_mute(ckey, muteflag)
if(isnull(GLOB.admin_mutes_assoc[ckey]))
return FALSE
if(GLOB.admin_mutes_assoc[ckey] & muteflag)
return TRUE
return FALSE
/proc/toggle_mute(ckey, muteflag)
if(isnull(GLOB.admin_mutes_assoc[ckey]))
GLOB.admin_mutes_assoc[ckey] = 0
if(GLOB.admin_mutes_assoc[ckey] & muteflag)
GLOB.admin_mutes_assoc[ckey] &= ~muteflag
else
GLOB.admin_mutes_assoc[ckey] |= muteflag
/proc/force_add_mute(ckey, muteflag)
if(isnull(GLOB.admin_mutes_assoc[ckey]))
GLOB.admin_mutes_assoc[ckey] = 0
GLOB.admin_mutes_assoc[ckey] |= muteflag
/proc/force_remove_mute(ckey, muteflag)
if(isnull(GLOB.admin_mutes_assoc[ckey]))
GLOB.admin_mutes_assoc[ckey] = 0
GLOB.admin_mutes_assoc[ckey] &= ~muteflag
-3
View File
@@ -446,9 +446,6 @@
alert(usr, "This ban has already been lifted / does not exist.", "Error", "Ok")
unbanpanel()
else if(href_list["warn"])
usr.client.warn(href_list["warn"])
else if(href_list["unbane"])
if(!check_rights(R_BAN)) return
+1 -1
View File
@@ -6,7 +6,7 @@ GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown", "the", "a", "an", "of"
set name = "Adminhelp"
//handle muting and automuting
if(prefs.muted & MUTE_ADMINHELP)
if(check_mute(ckey, MUTE_ADMINHELP))
to_chat(src, "<font color='red'>Error: Admin-PM: You cannot send adminhelps (Muted).</font>")
return
+2 -2
View File
@@ -58,7 +58,7 @@
//takes input from cmd_admin_pm_context, cmd_admin_pm_panel or /client/Topic and sends them a PM.
//Fetching a message if needed. src is the sender and C is the target client
/client/proc/cmd_admin_pm(whom, msg, type = "PM")
if(prefs.muted & MUTE_ADMINHELP)
if(check_mute(ckey, MUTE_ADMINHELP))
to_chat(src, "<span class='danger'>Error: Private-Message: You are unable to use PM-s (muted).</span>")
return
@@ -212,7 +212,7 @@
return
/client/proc/cmd_admin_discord_pm()
if(prefs.muted & MUTE_ADMINHELP)
if(check_mute(ckey, MUTE_ADMINHELP))
to_chat(src, "<span class='danger'>Error: Private-Message: You are unable to use PMs (muted).</span>")
return
+1 -1
View File
@@ -9,7 +9,7 @@
if(!src.mob)
return
if(prefs.muted & MUTE_DEADCHAT)
if(check_mute(ckey, MUTE_DEADCHAT))
to_chat(src, "<span class='warning'>You cannot send DSAY messages (muted).</span>")
return
+1 -1
View File
@@ -7,7 +7,7 @@
return
if(usr.client)
if(usr.client.prefs.muted & MUTE_PRAY)
if(check_mute(client.ckey, MUTE_PRAY))
to_chat(usr, "<span class='warning'>You cannot pray (muted).</span>")
return
if(client.handle_spam_prevention(msg, MUTE_PRAY, OOC_COOLDOWN))
+7 -7
View File
@@ -230,19 +230,19 @@
if(automute)
muteunmute = "auto-muted"
M.client.prefs.muted |= mute_type
force_add_mute(M.client.ckey, mute_type)
log_admin("SPAM AUTOMUTE: [muteunmute] [key_name(M)] from [mute_string]")
message_admins("SPAM AUTOMUTE: [muteunmute] [key_name_admin(M)] from [mute_string].", 1)
to_chat(M, "You have been [muteunmute] from [mute_string] by the SPAM AUTOMUTE system. Contact an admin.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Automute") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
if(M.client.prefs.muted & mute_type)
muteunmute = "unmuted"
M.client.prefs.muted &= ~mute_type
else
toggle_mute(M.client.ckey, mute_type)
if(check_mute(M.client.ckey, mute_type))
muteunmute = "muted"
M.client.prefs.muted |= mute_type
else
muteunmute = "unmuted"
log_admin("[key_name(usr)] has [muteunmute] [key_name(M)] from [mute_string]")
message_admins("[key_name_admin(usr)] has [muteunmute] [key_name_admin(M)] from [mute_string].", 1)
@@ -608,7 +608,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
"Custom" = "Cryptic Message")
var/list/MsgSound = list("Beep" = 'sound/misc/notice2.ogg',
"Enemy Communications Intercepted" = 'sound/AI/intercept2.ogg',
"Enemy Communications Intercepted" = 'sound/AI/intercept.ogg',
"New Command Report Created" = 'sound/AI/commandreport.ogg')
var/type = input(usr, "Pick a type of report to send", "Report Type", "") as anything in MsgType
@@ -25,9 +25,6 @@
H.dna.SetSEState(GLOB.hulkblock, TRUE)
singlemutcheck(H, GLOB.hulkblock, MUTCHK_FORCED)
H.dna.SetSEState(GLOB.xrayblock, TRUE)
singlemutcheck(H, GLOB.xrayblock, MUTCHK_FORCED)
H.dna.SetSEState(GLOB.fireblock, TRUE)
singlemutcheck(H, GLOB.fireblock, MUTCHK_FORCED)
+16 -11
View File
@@ -1,4 +1,3 @@
/obj/effect/nanomob
name = "Nano-Mob Avatar" //will be overridden by the mob datum name value when created
desc = "A wild Nano-Mob appeared! Hit it with your PDA with the game open to attempt to capture it!"
@@ -12,17 +11,29 @@
var/list/clients_encountered = list() //tracks who has already interacted with us, so they can't attempt a second capture
var/image/avatar
/obj/effect/nanomob/New(loc, datum/mob_hunt/new_info)
..()
/obj/effect/nanomob/Initialize(mapload, datum/mob_hunt/new_info)
. = ..()
if(!new_info)
qdel(src)
return
return INITIALIZE_HINT_QDEL
mob_info = new_info
RegisterSignal(mob_info, COMSIG_PARENT_QDELETING, .proc/delete_wrapper)
update_self()
forceMove(mob_info.spawn_point)
if(!mob_info.is_trap)
addtimer(CALLBACK(src, .proc/despawn), mob_info.lifetime)
/obj/effect/nanomob/Destroy()
SSmob_hunt.trap_spawns -= src
SSmob_hunt.normal_spawns -= src
mob_info = null // Can't delete this since multiple players can get the exact same /datum/mob_hunt. (This should be refactored)
clients_encountered.Cut()
QDEL_NULL(avatar)
return ..()
/obj/effect/nanomob/proc/delete_wrapper()
SIGNAL_HANDLER
qdel(src)
/obj/effect/nanomob/proc/update_self()
if(!mob_info)
return
@@ -132,12 +143,6 @@
icon_state = "placeholder"
var/obj/machinery/computer/mob_battle_terminal/my_terminal
/obj/effect/nanomob/battle/New(loc, datum/mob_hunt/new_info)
. = ..()
if(new_info)
mob_info = new_info
update_self()
/obj/effect/nanomob/battle/update_self()
if(!mob_info)
name = "Nano-Mob Battle Avatar"
@@ -71,10 +71,13 @@ Pipelines + Other Objects -> Pipe network
// Icons/overlays/underlays
/obj/machinery/atmospherics/update_icon()
var/turf/T = get_turf(loc)
if(!T || level == 2 || !T.intact)
plane = GAME_PLANE
else
if(T.transparent_floor)
plane = FLOOR_PLANE
else
if(!T || level == 2 || !T.intact)
plane = GAME_PLANE
else
plane = FLOOR_PLANE
/obj/machinery/atmospherics/proc/update_pipe_image()
pipe_image = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir) //the 20 puts it above Byond's darkness (not its opacity view)
@@ -95,15 +98,18 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/proc/add_underlay(turf/T, obj/machinery/atmospherics/node, direction, icon_connect_type)
if(node)
if(T.intact && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
if(T.intact && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe) && !T.transparent_floor)
//underlays += SSair.icon_manager.get_atmos_icon("underlay_down", direction, color_cache_name(node))
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
else
//underlays += SSair.icon_manager.get_atmos_icon("underlay_intact", direction, color_cache_name(node))
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
else
//underlays += SSair.icon_manager.get_atmos_icon("underlay_exposed", direction, pipe_color)
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "exposed" + icon_connect_type)
if(T.transparent_floor) //we want to keep pipes under transparent floors connected normally
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
else
//underlays += SSair.icon_manager.get_atmos_icon("underlay_exposed", direction, pipe_color)
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "exposed" + icon_connect_type)
/obj/machinery/atmospherics/proc/update_underlays()
if(check_icon_cache())
@@ -166,11 +172,14 @@ Pipelines + Other Objects -> Pipe network
//(De)construction
/obj/machinery/atmospherics/attackby(obj/item/W, mob/user)
var/turf/T = get_turf(src)
if(can_unwrench && istype(W, /obj/item/wrench))
var/turf/T = get_turf(src)
if(T.transparent_floor && istype(src, /obj/machinery/atmospherics/pipe) && layer != GAS_PIPE_VISIBLE_LAYER) //pipes on GAS_PIPE_VISIBLE_LAYER are above the transparent floor and should be interactable
to_chat(user, "<span class='danger'>You can't interact with something that's under the floor!</span>")
return
if(level == 1 && isturf(T) && T.intact)
to_chat(user, "<span class='danger'>You must remove the plating first.</span>")
return 1
return
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
add_fingerprint(user)
@@ -184,14 +193,14 @@ Pipelines + Other Objects -> Pipe network
playsound(src.loc, W.usesound, 50, 1)
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
if(internal_pressure > 2*ONE_ATMOSPHERE)
to_chat(user, "<span class='warning'>As you begin unwrenching \the [src] a gush of air blows in your face... maybe you should reconsider?</span>")
to_chat(user, "<span class='warning'>As you begin unwrenching \the [src] a gust of air blows in your face... maybe you should reconsider?</span>")
unsafe_wrenching = TRUE //Oh dear oh dear
if(do_after(user, 40 * W.toolspeed, target = src) && !QDELETED(src))
user.visible_message( \
"[user] unfastens \the [src].", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"<span class='italics'>You hear ratchet.</span>")
"<span class='italics'>You hear ratcheting.</span>")
investigate_log("was <span class='warning'>REMOVED</span> by [key_name(usr)]", "atmos")
for(var/obj/item/clothing/shoes/magboots/usermagboots in user.get_equipped_items())
@@ -206,6 +215,9 @@ Pipelines + Other Objects -> Pipe network
unsafe_pressure_release(user,internal_pressure)
deconstruct(TRUE)
else
if(T.transparent_floor)
to_chat(user, "<span class='danger'>You can't interact with something that's under the floor!</span>")
return TRUE
return ..()
//Called when an atmospherics object is unwrenched while having a large pressure difference
@@ -240,7 +252,12 @@ Pipelines + Other Objects -> Pipe network
dir = D
initialize_directions = P
var/turf/T = loc
level = T.intact ? 2 : 1
if(!T.transparent_floor)
level = T.intact ? 2 : 1
else
level = 2
plane = GAME_PLANE
layer = GAS_PIPE_VISIBLE_LAYER
add_fingerprint(usr)
if(!SSair.initialized) //If there's no atmos subsystem, we can't really initialize pipenets
SSair.machinery_to_construct.Add(src)
@@ -337,12 +354,15 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/proc/add_underlay_adapter(turf/T, obj/machinery/atmospherics/node, direction, icon_connect_type) //modified from add_underlay, does not make exposed underlays
if(node)
if(T.intact && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
if(T.intact && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe) && !T.transparent_floor)
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
else
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
else
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "retracted" + icon_connect_type)
if(T.transparent_floor) //we want to keep pipes under transparent floors connected normally
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
else
underlays += SSair.icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "retracted" + icon_connect_type)
/obj/machinery/atmospherics/singularity_pull(S, current_size)
if(current_size >= STAGE_FIVE)
@@ -2,6 +2,7 @@
icon = 'icons/atmos/vent_pump.dmi'
icon_state = "map_vent"
plane = FLOOR_PLANE
layer = GAS_SCRUBBER_LAYER
name = "passive vent"
desc = "A large air vent"
@@ -1,7 +1,7 @@
/obj/machinery/atmospherics/unary/tank
icon = 'icons/atmos/tank.dmi'
icon_state = "air_map"
layer = GAS_PIPE_VISIBLE_LAYER
name = "pressure tank"
desc = "A large vessel containing pressurized gas."
@@ -159,9 +159,9 @@
var/cache_name = state
for(var/D in GLOB.cardinal)
var/image/I = image(icon('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D))
var/image/I = image(icon('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D), layer = GAS_PIPE_HIDDEN_LAYER)
underlays[cache_name + "[D]"] = I
for(var/pipe_color in GLOB.pipe_colors)
I = image(icon('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D))
I = image(icon('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D), layer = GAS_PIPE_HIDDEN_LAYER)
I.color = GLOB.pipe_colors[pipe_color]
underlays[state + "[D]" + "[GLOB.pipe_colors[pipe_color]]"] = I
@@ -79,7 +79,8 @@
break
var/turf/T = get_turf(src) // hide if turf is not intact
if(!istype(T)) return
if(!istype(T) || T.transparent_floor)
return
hide(T.intact)
update_icon()
@@ -57,6 +57,8 @@
node3 = target
break
var/turf/T = src.loc // hide if turf is not intact
if(T.transparent_floor)
return
hide(T.intact)
update_icon()
@@ -165,7 +165,8 @@
break
var/turf/T = src.loc // hide if turf is not intact
hide(T.intact)
if(!T.transparent_floor)
hide(T.intact)
update_icon()
/obj/machinery/atmospherics/pipe/manifold4w/visible
@@ -46,10 +46,6 @@
if(istype(W, /obj/item/analyzer))
atmosanalyzer_scan(parent.air, user)
return
if(istype(W, /obj/item/painter))
return
return ..()
/obj/machinery/atmospherics/proc/pipeline_expansion()
@@ -68,7 +68,8 @@
break
var/turf/T = loc // hide if turf is not intact
hide(T.intact)
if(!T.transparent_floor)
hide(T.intact)
update_icon()
/obj/machinery/atmospherics/pipe/simple/check_pressure(pressure)
@@ -79,8 +79,6 @@
ADD_TRAIT(user, TRAIT_LASEREYES, "ww_wishgranter")
user.dna.SetSEState(GLOB.fireblock, TRUE)
singlemutcheck(user, GLOB.fireblock, MUTCHK_FORCED)
user.dna.SetSEState(GLOB.xrayblock, TRUE)
singlemutcheck(user, GLOB.xrayblock, MUTCHK_FORCED)
if(ishuman(user))
var/mob/living/carbon/human/human = user
if(!isshadowperson(human))
+3 -3
View File
@@ -8,8 +8,8 @@
#define UPLOAD_LIMIT 10485760 //Restricts client uploads to the server to 10MB //Boosted this thing. What's the worst that can happen?
#define MIN_CLIENT_VERSION 513 // Minimum byond major version required to play.
//I would just like the code ready should it ever need to be used.
#define SUGGESTED_CLIENT_VERSION 513 // only integers (e.g: 513, 514) are useful here. This is the part BEFORE the ".", IE 513 out of 513.1542
#define SUGGESTED_CLIENT_BUILD 1542 // only integers (e.g: 1542, 1543) are useful here. This is the part AFTER the ".", IE 1542 out of 513.1542
#define SUGGESTED_CLIENT_VERSION 514 // only integers (e.g: 513, 514) are useful here. This is the part BEFORE the ".", IE 513 out of 513.1542
#define SUGGESTED_CLIENT_BUILD 1566 // only integers (e.g: 1542, 1543) are useful here. This is the part AFTER the ".", IE 1542 out of 513.1542
#define SSD_WARNING_TIMER 30 // cycles, not seconds, so 30=60s
@@ -113,7 +113,7 @@
if(!holder && received_discord_pm < world.time - 6000) // Worse they can do is spam discord for 10 minutes
to_chat(usr, "<span class='warning'>You are no longer able to use this, it's been more then 10 minutes since an admin on Discord has responded to you</span>")
return
if(prefs.muted & MUTE_ADMINHELP)
if(check_mute(ckey, MUTE_ADMINHELP))
to_chat(usr, "<span class='warning'>You cannot use this as your client has been muted from sending messages to the admins on Discord</span>")
return
cmd_admin_discord_pm()
@@ -62,8 +62,6 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
var/max_gear_slots = 0
//non-preference stuff
var/warns = 0
var/muted = 0
var/last_ip
var/last_id
@@ -356,3 +356,11 @@
prefs.toggles2 ^= PREFTOGGLE_2_SIMPLE_STAT_PANEL
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles2 & PREFTOGGLE_2_SIMPLE_STAT_PANEL) ? "no longer" : "now"] get detailed information on the status panel.")
/client/verb/toggle_item_outlines()
set name = "Toggle Item Outlines"
set category = "Preferences"
set desc = "Toggles seeing item outlines on hover."
prefs.toggles2 ^= PREFTOGGLE_2_SEE_ITEM_OUTLINES
prefs.save_preferences(src)
to_chat(usr, "You will [(prefs.toggles2 & PREFTOGGLE_2_SEE_ITEM_OUTLINES) ? "now" : "no longer"] see item outlines on hover.")
+17 -4
View File
@@ -5,6 +5,13 @@
/datum/event/anomaly/proc/findEventArea()
var/static/list/allowed_areas
var/static/list/existing_areas
if(!existing_areas)
existing_areas = list()
for(var/area/AR in world)
var/turf/picked = safepick(get_area_turfs(AR.type))
if(picked && is_station_level(picked.z))
existing_areas += AR
if(!allowed_areas)
//Places that shouldn't explode
var/list/safe_area_types = typecacheof(list(
@@ -20,10 +27,16 @@
)
//Subtypes from the above that actually should explode.
var/list/unsafe_area_subtypes = typecacheof(list(/area/engine/break_room))
var/list/unsafe_area_subtypes = typecacheof(list(
/area/engine/break_room,
/area/engine/equipmentstorage,
/area/engine/chiefs_office,
/area/engine/controlroom,
/area/engine/mechanic_workshop
))
allowed_areas = make_associative(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes
var/list/possible_areas = typecache_filter_list(GLOB.all_areas, allowed_areas)
allowed_areas = typecacheof(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes
var/list/possible_areas = typecache_filter_list(existing_areas, allowed_areas)
if(length(possible_areas))
return pick(possible_areas)
@@ -36,7 +49,7 @@
CRASH("Anomaly: No valid turfs found for [impact_area] - [impact_area.type]")
/datum/event/anomaly/announce()
GLOB.event_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly.ogg')
/datum/event/anomaly/start()
var/turf/T = pick(get_area_turfs(impact_area))
+1 -1
View File
@@ -5,4 +5,4 @@
anomaly_path = /obj/effect/anomaly/bluespace
/datum/event/anomaly/anomaly_bluespace/announce()
GLOB.event_announcement.Announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly.ogg')
+1 -1
View File
@@ -5,4 +5,4 @@
anomaly_path = /obj/effect/anomaly/flux
/datum/event/anomaly/anomaly_flux/announce()
GLOB.event_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly.ogg')
+1 -1
View File
@@ -5,4 +5,4 @@
anomaly_path = /obj/effect/anomaly/grav
/datum/event/anomaly/anomaly_grav/announce()
GLOB.event_announcement.Announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly.ogg')
+1 -1
View File
@@ -5,4 +5,4 @@
anomaly_path = /obj/effect/anomaly/pyro
/datum/event/anomaly/anomaly_pyro/announce()
GLOB.event_announcement.Announce("Atmospheric anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("Atmospheric anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly.ogg')
+1 -1
View File
@@ -5,4 +5,4 @@
anomaly_path = /obj/effect/anomaly/bhole
/datum/event/anomaly/anomaly_vortex/announce()
GLOB.event_announcement.Announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert")
GLOB.event_announcement.Announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert", 'sound/AI/anomaly.ogg')
+2 -2
View File
@@ -21,7 +21,7 @@
SEND_SOUND(M, S)
/datum/event/apc_overload/announce()
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please check all underfloor APC terminals.", "Critical Power Failure", new_sound = 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please check all underfloor APC terminals.", "Critical Power Failure", 'sound/AI/power_overload.ogg')
/datum/event/apc_overload/end()
return TRUE
@@ -33,7 +33,7 @@
/area/turret_protected/ai)
if(announce)
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please check all underfloor APC terminals.", "Critical Power Failure", new_sound = 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please check all underfloor APC terminals.", "Critical Power Failure", 'sound/AI/power_overload.ogg')
// break APC_BREAK_PROBABILITY% of all of the APCs on the station
var/affected_apc_count = 0
+7 -7
View File
@@ -20,7 +20,7 @@
SEND_SOUND(M, S)
/datum/event/apc_short/announce()
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please repair shorted APCs.", "Systems Power Failure", new_sound = 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please repair shorted APCs.", "Systems Power Failure", 'sound/AI/power_overload.ogg')
/datum/event/apc_short/end()
return TRUE
@@ -30,7 +30,7 @@
/area/engine/engineering,
/area/engine/supermatter,
/area/turret_protected/ai)
GLOB.event_announcement.Announce("Power failure detected in [station_name()]'s powernet. All APCs have lost power. Gravity systems likely to fail.", "Systems Power Failure", new_sound = 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("Power failure detected in [station_name()]'s powernet. All APCs have lost power. Gravity systems likely to fail.", "Systems Power Failure", 'sound/AI/attention.ogg')
for(var/thing in GLOB.apcs)
var/obj/machinery/power/apc/A = thing
var/area/current_area = get_area(A)
@@ -49,7 +49,7 @@
/area/engine/supermatter,
/area/turret_protected/ai)
if(announce)
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please repair shorted APCs.", "Systems Power Failure", new_sound = 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("Overload detected in [station_name()]'s powernet. Engineering, please repair shorted APCs.", "Systems Power Failure", 'sound/AI/power_overload.ogg')
// break APC_BREAK_PROBABILITY% of all of the APCs on the station
var/affected_apc_count = 0
for(var/thing in GLOB.apcs)
@@ -76,7 +76,7 @@
/proc/power_restore(announce = TRUE, power_type)
if(power_type == 0) //Power without Repairing
if(announce)
GLOB.event_announcement.Announce("All operational APCs on \the [station_name()] have been fully charged.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
GLOB.event_announcement.Announce("All operational APCs on \the [station_name()] have been fully charged.", "Power Systems Nominal", 'sound/AI/attention.ogg')
var/affected_apc_count = 0
for(var/thing in GLOB.apcs)
var/obj/machinery/power/apc/A = thing
@@ -90,7 +90,7 @@
log_and_message_admins("Power has been restored to [affected_apc_count] APCs.")
if(power_type == 1) //Repair without charging
if(announce)
GLOB.event_announcement.Announce("All APCs on \the [station_name()] have been repaired.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
GLOB.event_announcement.Announce("All APCs on \the [station_name()] have been repaired.", "Power Systems Nominal", 'sound/AI/attention.ogg')
for(var/thing in GLOB.apcs)
var/obj/machinery/power/apc/A = thing
var/area/current_area = get_area(A)
@@ -101,7 +101,7 @@
log_and_message_admins("Power has been restored to all APCs.")
if(power_type == 2) //Repair and Power APCs
if(announce)
GLOB.event_announcement.Announce("All APCs on \the [station_name()] have been repaired and recharged. We apologize for the inconvenience.", "Power Systems Optimal", new_sound = 'sound/AI/poweron.ogg')
GLOB.event_announcement.Announce("All APCs on \the [station_name()] have been repaired and recharged. We apologize for the inconvenience.", "Power Systems Optimal", 'sound/AI/attention.ogg')
// repair the APCs and recharge them
for(var/thing in GLOB.apcs)
var/obj/machinery/power/apc/A = thing
@@ -115,7 +115,7 @@
/proc/power_restore_quick(announce = TRUE)
if(announce)
GLOB.event_announcement.Announce("All SMESs on \the [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
GLOB.event_announcement.Announce("All SMESs on \the [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", 'sound/AI/attention.ogg')
// fix all of the SMESs
for(var/obj/machinery/power/smes/S in GLOB.machines)
if(!is_station_level(S.z))
+1 -1
View File
@@ -14,7 +14,7 @@
"You don't want to buy anything? Yeah, well I didn't want to buy your mom either.")
/datum/event/brand_intelligence/announce()
GLOB.event_announcement.Announce("Rampant brand intelligence has been detected aboard [station_name()], please stand-by. The origin is believed to be \a [originMachine.name].", "Machine Learning Alert")
GLOB.event_announcement.Announce("Rampant brand intelligence has been detected aboard [station_name()], please stand-by. The origin is believed to be \a [originMachine.name].", "Machine Learning Alert", 'sound/AI/brand_intelligence.ogg')
/datum/event/brand_intelligence/start()
for(var/obj/machinery/vending/V in GLOB.machines)
+1 -1
View File
@@ -20,7 +20,7 @@
D.carrier = TRUE
/datum/event/disease_outbreak/announce()
GLOB.event_announcement.Announce("Confirmed outbreak of level 7 major viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
GLOB.event_announcement.Announce("Confirmed outbreak of level 7 major viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak7.ogg')
for(var/p in GLOB.dead_mob_list)
var/mob/M = p
to_chat(M, "<span class='deadsay'><b>[patient_zero]</b> has been infected with <b>[D.name]</b> ([ghost_follow_link(patient_zero, M)])</span>")
+2 -2
View File
@@ -1,7 +1,7 @@
/datum/event/door_runtime
/datum/event/door_runtime/announce()
GLOB.minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.", "Network Alert")
GLOB.minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.", "Network Alert", 'sound/AI/door_runtimes.ogg')
/datum/event/door_runtime/start()
for(var/obj/machinery/door/D in GLOB.airlocks)
@@ -13,4 +13,4 @@
post_status("alert", "lockdown")
/datum/event/door_runtime/proc/reboot()
GLOB.minor_announcement.Announce("Automatic system reboot complete. Have a secure day.","Network reset:")
GLOB.minor_announcement.Announce("Automatic system reboot complete. Have a secure day.","Network reset:", 'sound/AI/door_runtimes_fix.ogg')
+1 -2
View File
@@ -3,7 +3,7 @@
var/lightsoutRange = 25
/datum/event/electrical_storm/announce()
GLOB.event_announcement.Announce("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert")
GLOB.event_announcement.Announce("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert", 'sound/AI/elec_storm.ogg')
/datum/event/electrical_storm/start()
var/list/epicentreList = list()
@@ -26,4 +26,3 @@
var/obj/effect/landmark/epicentre = thing
for(var/obj/machinery/power/apc/apc in range(epicentre, lightsoutRange))
INVOKE_ASYNC(apc, /obj/machinery/power/apc.proc/overload_lighting)
+1 -1
View File
@@ -18,7 +18,7 @@
/datum/event/ion_storm/announce()
if(announceEvent == ION_ANNOUNCE || (announceEvent == ION_RANDOM && prob(ionAnnounceChance)))
GLOB.event_announcement.Announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", 'sound/AI/ionstorm.ogg')
GLOB.event_announcement.Announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", 'sound/AI/ions.ogg')
/datum/event/ion_storm/start()
//AI laws
+1 -1
View File
@@ -4,7 +4,7 @@
announceWhen = 1
/datum/event/solar_flare/announce()
GLOB.event_announcement.Announce("A solar flare has been detected on collision course with the station.", "Incoming Solar Flare", 'sound/AI/attention.ogg')
GLOB.event_announcement.Announce("A solar flare has been detected on collision course with the station.", "Incoming Solar Flare", 'sound/AI/flare.ogg')
/datum/event/solar_flare/start()
SSweather.run_weather(/datum/weather/solar_flare)
+1 -2
View File
@@ -11,7 +11,7 @@
/datum/event/spider_terror/announce()
if(successSpawn)
GLOB.command_announcement.Announce("Confirmed outbreak of level 3 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/effects/siren-spooky.ogg')
GLOB.command_announcement.Announce("Confirmed outbreak of level 3 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/effects/siren-spooky.ogg', new_sound2 = 'sound/AI/outbreak3.ogg')
else
log_and_message_admins("Warning: Could not spawn any mobs for event Terror Spiders")
@@ -61,4 +61,3 @@
successSpawn = TRUE
#undef TS_HIGHPOP_TRIGGER
+1 -1
View File
@@ -5,7 +5,7 @@
var/obj/effect/tear/TE
/datum/event/tear/announce()
GLOB.event_announcement.Announce("A tear in the fabric of space and time has opened. Expected location: [impact_area.name].", "Anomaly Alert")
GLOB.event_announcement.Announce("A tear in the fabric of space and time has opened. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly.ogg')
/datum/event/tear/start()
var/turf/T = pick(get_area_turfs(impact_area))
+1 -1
View File
@@ -6,7 +6,7 @@
var/list/vents = list()
/datum/event/vent_clog/announce()
GLOB.event_announcement.Announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert")
GLOB.event_announcement.Announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert", 'sound/AI/scrubbers.ogg')
/datum/event/vent_clog/setup()
endWhen = rand(25, 100)
+17
View File
@@ -277,6 +277,13 @@
if(can_insert && istype(disk.gene, /datum/plant_gene/trait))
dat += "<a href='?src=[UID()];op=insert'>Insert: [disk.gene.get_name()]</a>"
dat += "</div>"
dat += "<div class='line'><h3>Variant</h3></div><div class='statusDisplay'><table>"
dat += "<tr><td width='260px'>[seed.variant ? seed.variant : "None"]</td>"
dat += "<td><a href='?src=[UID()];set_v=1'>Edit</a></td>"
if(seed.variant)
dat += "<td><a href='?src=[UID()];del_v=1'>Remove</a></td>"
dat += "</tr></table></div>"
else
dat += "<br>No sample found.<br><span class='highlight'>Please, insert a plant sample to use this device.</span>"
popup.set_content(dat)
@@ -391,6 +398,16 @@
else if(href_list["abort"])
operation = ""
target = null
else if(href_list["set_v"])
if(!seed)
return
seed.variant_prompt(usr, src)
else if(href_list["del_v"])
if(!seed)
return
seed.variant = null
seed.apply_variant_name()
to_chat(usr, "<span class='notice'>You remove the [seed.plantname]'s variant designation.</span>")
interact(usr)
+2
View File
@@ -42,6 +42,8 @@
seed.prepare_result(src)
transform *= TRANSFORM_USING_VARIABLE(seed.potency, 100) + 0.5 //Makes the resulting produce's sprite larger or smaller based on potency!
add_juice()
if(seed.variant)
name += " \[[seed.variant]]"
/obj/item/reagent_containers/food/snacks/grown/Destroy()
QDEL_NULL(seed)
+6 -2
View File
@@ -344,7 +344,10 @@
/obj/machinery/hydroponics/examine(user)
. = ..()
if(myseed)
. += "<span class='info'>It has <span class='name'>[myseed.plantname]</span> planted.</span>"
if(myseed.variant)
. += "<span class='info'>It has the <span class='name'>[myseed.variant]</span> variant of <span class='name'>[myseed.plantname]</span> planted.</span>"
else
. += "<span class='info'>It has <span class='name'>[myseed.plantname]</span> planted.</span>"
if (dead)
. += "<span class='warning'>It's dead!</span>"
else if (harvest)
@@ -875,7 +878,8 @@
plant_hud_set_status()
adjustWeeds(-10) //Has a side effect of cleaning up those nasty weeds
update_icon()
else if(istype(O, /obj/item/pen) && myseed)
myseed.variant_prompt(user, src)
else
return ..()
+7 -5
View File
@@ -109,6 +109,7 @@
/datum/seed_pile
var/name = ""
var/variant = ""
var/lifespan = 0 //Saved stats
var/endurance = 0
var/maturation = 0
@@ -117,8 +118,9 @@
var/potency = 0
var/amount = 0
/datum/seed_pile/New(name, life, endur, matur, prod, yie, poten, am = 1)
/datum/seed_pile/New(name, variant, life, endur, matur, prod, yie, poten, am = 1)
src.name = name
src.variant = variant
src.lifespan = life
src.endurance = endur
src.maturation = matur
@@ -145,9 +147,9 @@
if (contents.len == 0)
dat += "<font color='red'>No seeds</font>"
else
dat += "<table cellpadding='3' style='text-align:center;'><tr><td>Name</td><td>Lifespan</td><td>Endurance</td><td>Maturation</td><td>Production</td><td>Yield</td><td>Potency</td><td>Stock</td></tr>"
dat += "<table cellpadding='3' style='text-align:center;'><tr><td>Name</td><td>Variant</td><td>Lifespan</td><td>Endurance</td><td>Maturation</td><td>Production</td><td>Yield</td><td>Potency</td><td>Stock</td></tr>"
for (var/datum/seed_pile/O in piles)
dat += "<tr><td>[O.name]</td><td>[O.lifespan]</td><td>[O.endurance]</td><td>[O.maturation]</td>"
dat += "<tr><td>[O.name]</td><td>[O.variant]</td><td>[O.lifespan]</td><td>[O.endurance]</td><td>[O.maturation]</td>"
dat += "<td>[O.production]</td><td>[O.yield]</td><td>[O.potency]</td><td>"
dat += "<a href='byond://?src=[src.UID()];name=[O.name];li=[O.lifespan];en=[O.endurance];ma=[O.maturation];pr=[O.production];yi=[O.yield];pot=[O.potency]'>Vend</a> ([O.amount] left)</td></tr>"
dat += "</table>"
@@ -203,9 +205,9 @@
O.forceMove(src)
. = 1
for (var/datum/seed_pile/N in piles)
if (O.plantname == N.name && O.lifespan == N.lifespan && O.endurance == N.endurance && O.maturation == N.maturation && O.production == N.production && O.yield == N.yield && O.potency == N.potency)
if (O.plantname == N.name && O.variant == N.variant && O.lifespan == N.lifespan && O.endurance == N.endurance && O.maturation == N.maturation && O.production == N.production && O.yield == N.yield && O.potency == N.potency)
++N.amount
return
piles += new /datum/seed_pile(O.plantname, O.lifespan, O.endurance, O.maturation, O.production, O.yield, O.potency)
piles += new /datum/seed_pile(O.plantname, O.variant, O.lifespan, O.endurance, O.maturation, O.production, O.yield, O.potency)
return
+31 -1
View File
@@ -10,6 +10,7 @@
var/plantname = "Plants" // Name of plant when planted.
var/product // A type path. The thing that is created when the plant is harvested.
var/species = "" // Used to update icons. Should match the name in the sprites unless all icon_* are overriden.
var/variant = null // Optional custom name to track modified plants. Can be set with pen or from gene modder.
var/growing_icon = 'icons/obj/hydroponics/growing.dmi' //the file that stores the sprites of the growing plant from this seed.
var/icon_grow // Used to override grow icon (default is "[species]-grow"). You can use one grow icon for multiple closely related plants with it.
@@ -83,6 +84,8 @@
S.potency = potency
S.weed_rate = weed_rate
S.weed_chance = weed_chance
S.variant = variant
S.apply_variant_name()
S.genes = list()
for(var/g in genes)
var/datum/plant_gene/G = g
@@ -317,16 +320,43 @@
return
/obj/item/seeds/attackby(obj/item/O, mob/user, params)
if (istype(O, /obj/item/plant_analyzer))
if(istype(O, /obj/item/plant_analyzer))
to_chat(user, "<span class='info'>*---------*\n This is \a <span class='name'>[src]</span>.</span>")
var/text = get_analyzer_text()
if(text)
to_chat(user, "<span class='notice'>[text]</span>")
return
if(istype(O, /obj/item/pen))
variant_prompt(user)
return
..() // Fallthrough to item/attackby() so that bags can pick seeds up
/obj/item/seeds/proc/variant_prompt(mob/user, obj/item/container = null)
var/prev = variant
var/V = input(user, "Choose variant name:", "Plant Variant Naming", variant) as text|null
if(isnull(V)) // Did the user cancel?
return
if(container && (loc != container)) // Was the seed removed from the container, if there is a container?
return
if(!(container ? container : src).Adjacent(user)) // Is the user next to the seed/container?
return
variant = copytext(sanitize(html_encode(trim(V))), 1, 64) // Sanitization must happen after null check because it converts nulls to empty strings
if(variant == "")
variant = null
if(prev != variant)
to_chat(user, "<span class='notice'>You [variant ? "change" : "remove"] the [plantname]'s variant designation.</span>")
apply_variant_name()
/obj/item/seeds/proc/apply_variant_name()
var/V = variant ? " \[[variant]]" : "" // If we have a non-empty variant add it to the name
var/N = initial(name)
if(copytext(name, 1, 13) == "experimental") // Don't delete 'experimental'
N = "experimental " + N
name = N + V
if(GetComponent(/datum/component/label))
GetComponent(/datum/component/label).apply_label() // Don't delete labels
+13 -15
View File
@@ -104,21 +104,7 @@
new /obj/item/toy/katana(src)
if(85 to 86)
new /obj/item/defibrillator/compact(src)
if(87) //1% chance
new /obj/item/weed_extract(src)
if(88)
new /obj/item/organ/internal/brain(src)
if(89)
new /obj/item/organ/internal/brain/xeno(src)
if(90)
new /obj/item/organ/internal/heart(src)
if(91)
new /obj/item/soulstone/anybody(src)
if(92)
new /obj/item/katana(src)
if(93)
new /obj/item/dnainjector/xraymut(src)
if(94)
if(87 to 88)
new /obj/item/storage/backpack/clown(src)
new /obj/item/clothing/under/rank/clown(src)
new /obj/item/clothing/shoes/clown_shoes(src)
@@ -128,6 +114,18 @@
new /obj/item/toy/crayon/rainbow(src)
new /obj/item/reagent_containers/spray/waterflower(src)
new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(src)
if(89) //1% chance
new /obj/item/weed_extract(src)
if(90)
new /obj/item/organ/internal/brain(src)
if(91)
new /obj/item/organ/internal/brain/xeno(src)
if(92)
new /obj/item/organ/internal/heart(src)
if(93)
new /obj/item/soulstone/anybody(src)
if(94)
new /obj/item/katana(src)
if(95)
new /obj/item/clothing/under/mime(src)
new /obj/item/clothing/shoes/black(src)

Some files were not shown because too many files have changed in this diff Show More