Merge branch 'master' into xantholne-christmas01

This commit is contained in:
Unknown
2019-12-06 17:21:08 -07:00
269 changed files with 10257 additions and 7157 deletions
File diff suppressed because it is too large Load Diff
@@ -103794,10 +103794,10 @@
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"dsI" = (
/obj/structure/sign/warning/nosmoking,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/machinery/smartfridge/organ/preloaded,
/turf/closed/wall,
/area/medical/surgery)
"dsJ" = (
@@ -127428,6 +127428,10 @@
/obj/item/assembly/signaler,
/turf/open/floor/plating,
/area/crew_quarters/abandoned_gambling_den)
"mMC" = (
/obj/structure/sign/warning/nosmoking,
/turf/closed/wall,
/area/medical/surgery)
"mQE" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -174919,7 +174923,7 @@ dkv
dma
dma
dma
dma
mMC
dsI
dro
dvz
+8 -4
View File
@@ -62776,6 +62776,9 @@
"cro" = (
/obj/structure/bed/roller,
/obj/machinery/iv_drip,
/obj/structure/sign/warning/nosmoking{
pixel_x = -28
},
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"crq" = (
@@ -63296,9 +63299,6 @@
dir = 1;
pixel_y = -22
},
/obj/structure/sign/warning/nosmoking{
pixel_x = -28
},
/obj/machinery/iv_drip,
/obj/effect/turf_decal/tile/blue,
/obj/effect/turf_decal/tile/blue{
@@ -83997,6 +83997,10 @@
},
/turf/open/floor/plating,
/area/maintenance/port)
"qnB" = (
/obj/machinery/smartfridge/organ/preloaded,
/turf/closed/wall,
/area/medical/surgery)
"qqg" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 6
@@ -104229,7 +104233,7 @@ cia
cia
cpX
cia
cia
qnB
cia
ceu
dyg
@@ -42880,6 +42880,12 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall/r_wall,
/area/maintenance/disposal/incinerator)
"uvp" = (
/obj/machinery/smartfridge/organ/preloaded{
pixel_y = 2
},
/turf/closed/wall,
/area/medical/medbay/zone3)
"uxJ" = (
/obj/machinery/door/firedoor,
/obj/machinery/door/airlock/public/glass{
@@ -81595,7 +81601,7 @@ aSh
bcf
bcW
blt
aSh
uvp
aOL
bfA
bfX
+12 -8
View File
@@ -37749,6 +37749,9 @@
/obj/effect/turf_decal/tile/blue{
dir = 8
},
/obj/machinery/light_switch{
pixel_x = -22
},
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"bIp" = (
@@ -38828,10 +38831,6 @@
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 1
},
/obj/machinery/firealarm{
dir = 8;
pixel_x = -26
},
/obj/effect/turf_decal/tile/blue{
dir = 1
},
@@ -39305,15 +39304,16 @@
/obj/item/clothing/gloves/color/latex,
/obj/item/clothing/mask/surgical,
/obj/item/clothing/suit/apron/surgical,
/obj/machinery/light_switch{
pixel_x = -22
},
/obj/effect/turf_decal/tile/blue{
dir = 1
},
/obj/effect/turf_decal/tile/blue{
dir = 8
},
/obj/machinery/firealarm{
dir = 8;
pixel_x = -26
},
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"bLN" = (
@@ -55674,6 +55674,10 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/central)
"jdA" = (
/obj/machinery/smartfridge/organ/preloaded,
/turf/closed/wall,
/area/medical/surgery)
"jeq" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -92221,7 +92225,7 @@ bFU
bFU
bIn
bJt
bFU
jdA
bFU
bFU
bFU
+2 -15
View File
@@ -379,15 +379,6 @@
/obj/item/camera,
/turf/open/indestructible/clock_spawn_room,
/area/reebe/city_of_cogs)
"Nz" = (
/obj/structure/table/bronze,
/obj/item/implantcase,
/obj/item/implantcase,
/obj/item/implantcase,
/obj/item/implanter,
/obj/item/storage/backpack/duffelbag/sec/surgery,
/turf/open/floor/clockwork/reebe,
/area/reebe/city_of_cogs)
"NH" = (
/obj/structure/table/bronze,
/obj/item/taperecorder,
@@ -409,10 +400,6 @@
"WT" = (
/turf/closed/wall/clockwork,
/area/reebe)
"Yy" = (
/obj/structure/table/optable,
/turf/open/floor/clockwork/reebe,
/area/reebe/city_of_cogs)
(1,1,1) = {"
zb
@@ -33918,7 +33905,7 @@ ab
ai
bE
aj
Yy
aj
aj
aj
aA
@@ -34175,7 +34162,7 @@ ab
ah
al
aj
Nz
aj
aj
aC
ah
+1
View File
@@ -69,6 +69,7 @@
#define ADMIN_PUNISHMENT_BSA "Bluespace Artillery Device"
#define ADMIN_PUNISHMENT_FIREBALL "Fireball"
#define ADMIN_PUNISHMENT_ROD "Immovable Rod"
#define ADMIN_PUNISHMENT_SUPPLYPOD_QUICK "Supply Pod (Quick)"
#define ADMIN_PUNISHMENT_SUPPLYPOD "Supply Pod"
#define ADMIN_PUNISHMENT_MAZING "Puzzle"
#define ADMIN_PUNISHMENT_PIE "Cream Pie"
+3 -1
View File
@@ -11,6 +11,7 @@
#define STYLE_FRUIT 11
#define STYLE_INVISIBLE 12
#define STYLE_GONDOLA 13
#define STYLE_SEETHROUGH 14
#define POD_ICON_STATE 1
#define POD_NAME 2
@@ -29,5 +30,6 @@
list("honkpod", "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\
list("fruitpod", "\improper Orange", "An angry orange."),\
list("", "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\
list("gondolapod", "gondola", "The silent walker. This one seems to be part of a delivery agency.")\
list("gondolapod", "gondola", "The silent walker. This one seems to be part of a delivery agency."),\
list("", "", "")\
)
+1
View File
@@ -98,6 +98,7 @@
//the define for visible message range in combat
#define COMBAT_MESSAGE_RANGE 3
#define DEFAULT_MESSAGE_RANGE 7
//Shove knockdown lengths (deciseconds)
#define SHOVE_KNOCKDOWN_SOLID 30
+15
View File
@@ -8,7 +8,13 @@
#define ELEMENT_INCOMPATIBLE 1 // Return value to cancel attaching
// /datum/element flags
/// Causes the detach proc to be called when the host object is being deleted
#define ELEMENT_DETACH (1 << 0)
/**
* Only elements created with the same arguments given after `id_arg_index` share an element instance
* The arguments are the same when the text and number values are the same and all other values have the same ref
*/
#define ELEMENT_BESPOKE (1 << 1)
// How multiple components of the exact same type are handled in the same datum
@@ -153,6 +159,7 @@
#define COMSIG_MOB_HUD_CREATED "mob_hud_created" //from base of mob/create_mob_hud(): ()
#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" //from base of
#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" //from base of /obj/item/attack(): (mob/M, mob/user)
#define COMPONENT_ITEM_NO_ATTACK 1
#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters)
#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" //from base of mob/RangedAttack(): (atom/A, params)
#define COMSIG_MOB_THROW "mob_throw" //from base of /mob/throw_item(): (atom/target)
@@ -318,3 +325,11 @@
//Ouch my toes!
#define CALTROP_BYPASS_SHOES 1
#define CALTROP_IGNORE_WALKERS 2
//Xenobio hotkeys
#define COMSIG_XENO_SLIME_CLICK_CTRL "xeno_slime_click_ctrl" //from slime CtrlClickOn(): (/mob)
#define COMSIG_XENO_SLIME_CLICK_ALT "xeno_slime_click_alt" //from slime AltClickOn(): (/mob)
#define COMSIG_XENO_SLIME_CLICK_SHIFT "xeno_slime_click_shift" //from slime ShiftClickOn(): (/mob)
#define COMSIG_XENO_TURF_CLICK_SHIFT "xeno_turf_click_shift" //from turf ShiftClickOn(): (/mob)
#define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt" //from turf AltClickOn(): (/mob)
#define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl" //from monkey CtrlClickOn(): (/mob)
+1
View File
@@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define TESLA_IGNORE_1 (1<<13) // TESLA_IGNORE grants immunity from being targeted by tesla-style electricity
#define INITIALIZED_1 (1<<14) //Whether /atom/Initialize() has already run for the object
#define ADMIN_SPAWNED_1 (1<<15) //was this spawned by an admin? used for stat tracking stuff.
#define PREVENT_CONTENTS_EXPLOSION_1 (1<<16) /// should not get harmed if this gets caught by an explosion?
//turf-only flags
#define NOJAUNT_1 (1<<0)
+8
View File
@@ -75,8 +75,16 @@
#define LINGHIVE_LING 2
#define LINGHIVE_LINK 3
//whether the emote is visible or audible.
#define EMOTE_VISIBLE 1
#define EMOTE_AUDIBLE 2
//Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam
#define MAX_MESSAGE_LEN 2048 //Citadel edit: What's the WORST that could happen?
#define MAX_NAME_LEN 42
#define MAX_BROADCAST_LEN 512
#define MAX_CHARTER_LEN 80
// Audio/Visual Flags. Used to determine what sense are required to notice a message.
#define MSG_VISUAL (1<<0)
#define MSG_AUDIBLE (1<<1)
+2
View File
@@ -58,6 +58,8 @@
#define MAX_MANIA_SEVERITY 100 //how high the mania severity can go
#define MANIA_DAMAGE_TO_CONVERT 90 //how much damage is required before it'll convert affected targets
#define STATUS_EFFECT_CHOKINGSTRAND /datum/status_effect/strandling //Choking Strand
#define STATUS_EFFECT_HISWRATH /datum/status_effect/his_wrath //His Wrath.
#define STATUS_EFFECT_SUMMONEDGHOST /datum/status_effect/cultghost //is a cult ghost and can't use manifest runes
+5 -3
View File
@@ -120,8 +120,9 @@
#define TRAIT_UNINTELLIGIBLE_SPEECH "unintelligible-speech"
#define TRAIT_SOOTHED_THROAT "soothed-throat"
#define TRAIT_LAW_ENFORCEMENT_METABOLISM "law-enforcement-metabolism"
#define TRAIT_STRONG_GRABBER "strong_grabber"
#define TRAIT_CALCIUM_HEALER "calcium_healer"
#define TRAIT_STRONG_GRABBER "strong_grabber"
#define TRAIT_CALCIUM_HEALER "calcium_healer"
#define TRAIT_MAGIC_CHOKE "magic_choke"
#define TRAIT_CAPTAIN_METABOLISM "captain-metabolism"
#define TRAIT_ABDUCTOR_TRAINING "abductor-training"
#define TRAIT_ABDUCTOR_SCIENTIST_TRAINING "abductor-scientist-training"
@@ -162,6 +163,7 @@
#define TRAIT_FRIENDLY "friendly"
#define TRAIT_ASSBLASTUSA "assblastusa"
#define TRAIT_CULT_EYES "cult_eyes"
#define TRAIT_FREESPRINT "free_sprinting"
// common trait sources
@@ -216,4 +218,4 @@
#define NINJA_SUIT_TRAIT "ninja-suit"
#define ANTI_DROP_IMPLANT_TRAIT "anti-drop-implant"
#define ABDUCTOR_ANTAGONIST "abductor-antagonist"
#define MADE_UNCLONEABLE "made-uncloneable"
#define MADE_UNCLONEABLE "made-uncloneable"
+3
View File
@@ -85,6 +85,9 @@ GLOBAL_VAR_INIT(cmp_field, "name")
/proc/cmp_job_display_asc(datum/job/A, datum/job/B)
return A.display_order - B.display_order
/proc/cmp_uplink_items_dsc(datum/uplink_item/A, datum/uplink_item/B)
return sorttext(initial(B.name), initial(A.name))
/proc/cmp_numbered_displays_name_asc(datum/numbered_display/A, datum/numbered_display/B)
return sorttext(A.sample_object.name, B.sample_object.name)
+10
View File
@@ -97,6 +97,16 @@
var/datum/emote/E = new path()
E.emote_list[E.key] = E
//Uplink Items
for(var/path in subtypesof(/datum/uplink_item))
var/datum/uplink_item/I = path
if(!initial(I.item)) //We add categories to a separate list.
GLOB.uplink_categories |= initial(I.category)
continue
GLOB.uplink_items += path
//(sub)typesof entries are listed by the order they are loaded in the code, so we'll have to rearrange them here.
GLOB.uplink_items = sortList(GLOB.uplink_items, /proc/cmp_uplink_items_dsc)
init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
//creates every subtype of prototype (excluding prototype) and adds it to list L.
+3 -4
View File
@@ -313,14 +313,13 @@
parts += "[FOURSPACES]Threat level: [mode.threat_level]"
parts += "[FOURSPACES]Threat left: [mode.threat]"
parts += "[FOURSPACES]Executed rules:"
for(var/datum/dynamic_ruleset/rule in mode.executed_rules)
parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - <b>[rule.name]</b>: -[rule.cost + rule.scaled_times * rule.scaling_cost] threat"
parts += "[FOURSPACES]Other threat changes:"
for(var/str in mode.threat_log)
parts += "[FOURSPACES][FOURSPACES][str]"
for(var/entry in mode.threat_tallies)
parts += "[FOURSPACES][FOURSPACES][entry] added [mode.threat_tallies[entry]]"
/*
for(var/datum/dynamic_ruleset/rule in mode.executed_rules)
parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - <b>[rule.name]</b>: -[rule.cost + rule.scaled_times * rule.scaling_cost] threat"
*/
return parts.Join("<br>")
/client/proc/roundend_report_file()
+2
View File
@@ -19,6 +19,8 @@ GLOBAL_LIST(chemical_reagents_list) //list of all /datum/reagent datums index
GLOBAL_LIST_EMPTY(materials_list) //list of all /datum/material datums indexed by material id.
GLOBAL_LIST_EMPTY(tech_list) //list of all /datum/tech datums indexed by id.
GLOBAL_LIST_EMPTY(surgeries_list) //list of all surgeries by name, associated with their path.
GLOBAL_LIST_EMPTY(uplink_items) //list of all uplink item typepaths, ascendingly sorted by their initial name.
GLOBAL_LIST_EMPTY(uplink_categories) //list of all uplink categories, listed by the order they are loaded in code. Be careful.
GLOBAL_LIST_EMPTY(crafting_recipes) //list of all table craft recipes
GLOBAL_LIST_EMPTY(rcd_list) //list of Rapid Construction Devices.
GLOBAL_LIST_EMPTY(apcs_list) //list of all Area Power Controller machines, separate from machines for powernet speeeeeeed.
+2
View File
@@ -10,3 +10,5 @@ GLOBAL_LIST_INIT(typecache_living, typecacheof(/mob/living))
GLOBAL_LIST_INIT(typecache_stack, typecacheof(/obj/item/stack))
GLOBAL_LIST_INIT(typecache_machine_or_structure, typecacheof(list(/obj/machinery, /obj/structure)))
GLOBAL_LIST_INIT(freezing_objects, typecacheof(list(/obj/structure/closet/crate/freezer, /obj/structure/closet/secure_closet/freezer, /obj/structure/bodycontainer, /obj/item/autosurgeon, /obj/machinery/smartfridge/organ))) //list of all cold objects, that freeze organs when inside
+2 -13
View File
@@ -39,23 +39,12 @@
if(..())
return TRUE
user.changeNext_move(CLICK_CD_MELEE)
if(user.a_intent == INTENT_HARM && stat == DEAD && (butcher_results || guaranteed_butcher_results)) //can we butcher it?
var/datum/component/butchering/butchering = I.GetComponent(/datum/component/butchering)
if(butchering && butchering.butchering_enabled)
to_chat(user, "<span class='notice'>You begin to butcher [src]...</span>")
playsound(loc, butchering.butcher_sound, 50, TRUE, -1)
if(do_mob(user, src, butchering.speed) && Adjacent(I))
butchering.Butcher(user, src)
return 1
else if(I.get_sharpness() && !butchering) //give sharp objects butchering functionality, for consistency
I.AddComponent(/datum/component/butchering, 80 * I.toolspeed)
attackby(I, user, params) //call the attackby again to refresh and do the butchering check again
return
return I.attack(src, user)
/obj/item/proc/attack(mob/living/M, mob/living/user)
SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK)
return
SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
if(item_flags & NOBLUDGEON)
return
+15 -3
View File
@@ -6,10 +6,22 @@ PROCESSING_SUBSYSTEM_DEF(dcs)
/datum/controller/subsystem/processing/dcs/Recover()
comp_lookup = SSdcs.comp_lookup
/datum/controller/subsystem/processing/dcs/proc/GetElement(eletype)
. = elements_by_type[eletype]
/datum/controller/subsystem/processing/dcs/proc/GetElement(datum/element/eletype, ...)
var/element_id = eletype
if(initial(eletype.element_flags) & ELEMENT_BESPOKE)
var/list/fullid = list("[eletype]")
for(var/i in initial(eletype.id_arg_index) to length(args))
var/argument = args[i]
if(istext(argument) || isnum(argument))
fullid += "[argument]"
else
fullid += "[REF(argument)]"
element_id = fullid.Join("&")
. = elements_by_type[element_id]
if(.)
return
if(!ispath(eletype, /datum/element))
CRASH("Attempted to instantiate [eletype] as a /datum/element")
. = elements_by_type[eletype] = new eletype
. = elements_by_type[element_id] = new eletype
+1 -1
View File
@@ -87,7 +87,7 @@ SUBSYSTEM_DEF(traumas)
"skeletons" = typecacheof(list(/obj/item/organ/tongue/bone, /obj/item/clothing/suit/armor/bone, /obj/item/stack/sheet/bone,
/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton,
/obj/effect/decal/remains/human)),
"conspiracies" = typecacheof(list(/obj/item/clothing/under/rank/captain, /obj/item/clothing/under/rank/head_of_security,
"conspiracies" = typecacheof(list(/obj/item/clothing/under/rank/captain, /obj/item/clothing/under/rank/head_of_security,
/obj/item/clothing/under/rank/chief_engineer, /obj/item/clothing/under/rank/chief_medical_officer,
/obj/item/clothing/under/rank/head_of_personnel, /obj/item/clothing/under/rank/research_director,
/obj/item/clothing/under/rank/head_of_security/grey, /obj/item/clothing/under/rank/head_of_security/alt,
+1 -1
View File
@@ -68,4 +68,4 @@
new /datum/hallucination/chat(owner, TRUE, FALSE, "<span class='hypnophrase'>[hypnotic_phrase]</span>")
/datum/brain_trauma/hypnosis/handle_hearing(datum/source, list/hearing_args)
hearing_args[HEARING_MESSAGE] = target_phrase.Replace(hearing_args[HEARING_MESSAGE], "<span class='hypnophrase'>$1</span>")
hearing_args[HEARING_RAW_MESSAGE] = target_phrase.Replace(hearing_args[HEARING_RAW_MESSAGE], "<span class='hypnophrase'>$1</span>")
+1 -1
View File
@@ -241,7 +241,7 @@
if(prob(25))
var/deja_vu = pick_n_take(hear_dejavu)
var/static/regex/quoted_spoken_message = regex("\".+\"", "gi")
hearing_args[HEARING_MESSAGE] = quoted_spoken_message.Replace(hearing_args[HEARING_MESSAGE], "\"[deja_vu]\"") //Quotes included to avoid cases where someone says part of their name
hearing_args[HEARING_RAW_MESSAGE] = quoted_spoken_message.Replace(hearing_args[HEARING_RAW_MESSAGE], "\"[deja_vu]\"") //Quotes included to avoid cases where someone says part of their name
return
if(hear_dejavu.len >= 15)
if(prob(50))
+1 -1
View File
@@ -88,7 +88,7 @@
if(findtext(hearing_args[HEARING_RAW_MESSAGE], reg))
addtimer(CALLBACK(src, .proc/freak_out, null, word), 10) //to react AFTER the chat message
hearing_args[HEARING_MESSAGE] = reg.Replace(hearing_args[HEARING_MESSAGE], "<span class='phobia'>$1</span>")
hearing_args[HEARING_RAW_MESSAGE] = reg.Replace(hearing_args[HEARING_RAW_MESSAGE], "<span class='phobia'>$1</span>")
break
/datum/brain_trauma/mild/phobia/handle_speech(datum/source, list/speech_args)
@@ -198,9 +198,9 @@
/datum/brain_trauma/severe/split_personality/brainwashing/handle_hearing(datum/source, list/hearing_args)
if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == hearing_args[HEARING_SPEAKER])
return
var/message = hearing_args[HEARING_MESSAGE]
var/message = hearing_args[HEARING_RAW_MESSAGE]
if(findtext(message, codeword))
hearing_args[HEARING_MESSAGE] = replacetext(message, codeword, "<span class='warning'>[codeword]</span>")
hearing_args[HEARING_RAW_MESSAGE] = replacetext(message, codeword, "<span class='warning'>[codeword]</span>")
addtimer(CALLBACK(src, /datum/brain_trauma/severe/split_personality.proc/switch_personalities), 10)
/datum/brain_trauma/severe/split_personality/brainwashing/handle_speech(datum/source, list/speech_args)
+1
View File
@@ -184,6 +184,7 @@
// The type arg is casted so initial works, you shouldn't be passing a real instance into this
/datum/proc/GetComponent(datum/component/c_type)
RETURN_TYPE(c_type)
if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED)
stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]")
var/list/dc = datum_components
+38 -1
View File
@@ -4,8 +4,9 @@
var/bonus_modifier = 0 //percentage increase to bonus item chance
var/butcher_sound = 'sound/weapons/slice.ogg' //sound played when butchering
var/butchering_enabled = TRUE
var/can_be_blunt = FALSE
/datum/component/butchering/Initialize(_speed, _effectiveness, _bonus_modifier, _butcher_sound, disabled)
/datum/component/butchering/Initialize(_speed, _effectiveness, _bonus_modifier, _butcher_sound, disabled, _can_be_blunt)
if(_speed)
speed = _speed
if(_effectiveness)
@@ -16,6 +17,22 @@
butcher_sound = _butcher_sound
if(disabled)
butchering_enabled = FALSE
if(_can_be_blunt)
can_be_blunt = _can_be_blunt
if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/onItemAttack)
/datum/component/butchering/proc/onItemAttack(obj/item/source, mob/living/M, mob/living/user)
if(user.a_intent == INTENT_HARM && M.stat == DEAD && (M.butcher_results || M.guaranteed_butcher_results)) //can we butcher it?
if(butchering_enabled && (can_be_blunt || source.get_sharpness()))
INVOKE_ASYNC(src, .proc/startButcher, source, M, user)
return COMPONENT_ITEM_NO_ATTACK
/datum/component/butchering/proc/startButcher(obj/item/source, mob/living/M, mob/living/user)
to_chat(user, "<span class='notice'>You begin to butcher [M]...</span>")
playsound(M.loc, butcher_sound, 50, TRUE, -1)
if(do_mob(user, M, speed) && M.Adjacent(source))
Butcher(user, M)
/datum/component/butchering/proc/Butcher(mob/living/butcher, mob/living/meat)
var/turf/T = meat.drop_location()
@@ -50,3 +67,23 @@
/datum/component/butchering/proc/ButcherEffects(mob/living/meat) //extra effects called on butchering, override this via subtypes
return
///Special snowflake component only used for the recycler.
/datum/component/butchering/recycler
/datum/component/butchering/recycler/Initialize(_speed, _effectiveness, _bonus_modifier, _butcher_sound, disabled, _can_be_blunt)
if(!istype(parent, /obj/machinery/recycler)) //EWWW
return COMPONENT_INCOMPATIBLE
. = ..()
if(. == COMPONENT_INCOMPATIBLE)
return
RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/onCrossed)
/datum/component/butchering/recycler/proc/onCrossed(datum/source, mob/living/L)
if(!istype(L))
return
var/obj/machinery/recycler/eater = parent
if(eater.safety_mode || (eater.stat & (BROKEN|NOPOWER))) //I'm so sorry.
return
if(L.stat == DEAD && (L.butcher_results || L.guaranteed_butcher_results))
Butcher(parent, L)
+3 -3
View File
@@ -57,7 +57,7 @@
var/screen_start_x = 4 //These two are where the storage starts being rendered, screen_loc wise.
var/screen_start_y = 2
//End
var/limited_random_access = FALSE //Quick if statement in accessible_items to determine if we care at all about what people can access at once.
var/limited_random_access_stack_position = 0 //If >0, can only access top <x> items
var/limited_random_access_stack_bottom_up = FALSE //If TRUE, above becomes bottom <x> items
@@ -647,9 +647,9 @@
if(M == viewing)
to_chat(usr, "<span class='notice'>You put [I] [insert_preposition]to [parent].</span>")
else if(in_range(M, viewing)) //If someone is standing close enough, they can tell what it is...
viewing.show_message("<span class='notice'>[M] puts [I] [insert_preposition]to [parent].</span>", 1)
viewing.show_message("<span class='notice'>[M] puts [I] [insert_preposition]to [parent].</span>", MSG_VISUAL)
else if(I && I.w_class >= 3) //Otherwise they can only see large or normal items from a distance...
viewing.show_message("<span class='notice'>[M] puts [I] [insert_preposition]to [parent].</span>", 1)
viewing.show_message("<span class='notice'>[M] puts [I] [insert_preposition]to [parent].</span>", MSG_VISUAL)
/datum/component/storage/proc/update_icon()
if(isobj(parent))
+10
View File
@@ -174,3 +174,13 @@
/datum/dog_fashion/back/deathsquad
name = "Trooper REAL_NAME"
desc = "That's not red paint. That's real corgi blood."
/datum/dog_fashion/head/colour
name = "Stylish REAL_NAME"
desc = "From the tips of their paws to the top of their head, they look like a made bed."
emote_see = list("tries to tap dances.","looks sadly at others outfits...","barks at bad fashion!")
/datum/dog_fashion/head/telegram
name = "Messenger REAL_NAME"
desc = "Dont shoot the messenger..."
emote_see = list("licks an envelope.","looks ready to set off to send a letter...","works on barking!")
+14 -4
View File
@@ -1,5 +1,11 @@
/datum/element
var/element_flags = NONE
/**
* The index of the first attach argument to consider for duplicate elements
* Is only used when flags contains ELEMENT_BESPOKE
* This is infinity so you must explicitly set this
*/
var/id_arg_index = INFINITY
/datum/element/proc/Attach(datum/target)
if(type == /datum/element)
@@ -19,11 +25,15 @@
//DATUM PROCS
/datum/proc/AddElement(eletype, ...)
var/datum/element/ele = SSdcs.GetElement(eletype)
var/datum/element/ele = SSdcs.GetElement(arglist(args))
args[1] = src
if(ele.Attach(arglist(args)) == ELEMENT_INCOMPATIBLE)
CRASH("Incompatible [eletype] assigned to a [type]! args: [json_encode(args)]")
/datum/proc/RemoveElement(eletype)
var/datum/element/ele = SSdcs.GetElement(eletype)
ele.Detach(src)
/**
* Finds the singleton for the element type given and detaches it from src
* You only need additional arguments beyond the type if you're using ELEMENT_BESPOKE
*/
/datum/proc/RemoveElement(eletype, ...)
var/datum/element/ele = SSdcs.GetElement(arglist(args))
ele.Detach(src)
-3
View File
@@ -1,6 +1,3 @@
#define EMOTE_VISIBLE 1
#define EMOTE_AUDIBLE 2
/datum/emote
var/key = "" //What calls the emote
var/key_third_person = "" //This will also call the emote
+1 -1
View File
@@ -198,7 +198,7 @@ GLOBAL_LIST_EMPTY(explosions)
var/list/items = list()
for(var/I in T)
var/atom/A = I
if (!A.prevent_content_explosion()) //The atom/contents_explosion() proc returns null if the contents ex_acting has been handled by the atom, and TRUE if it hasn't.
if (!(A.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)) //The atom/contents_explosion() proc returns null if the contents ex_acting has been handled by the atom, and TRUE if it hasn't.
items += A.GetAllContents()
for(var/O in items)
var/atom/A = O
+60
View File
@@ -53,3 +53,63 @@
mood_change = -20
timeout = 300
//special_screen_obj = "mood_happiness_bad" Originally in tg
/datum/mood_event/eigenstate
mood_change = -3
description = "<span class='warning'>Where the hell am I? Is this an alternative dimension ?</span>\n"
/datum/mood_event/enthrall
mood_change = 5
/datum/mood_event/enthrall/add_effects(message)
description = "<span class='nicegreen'>[message]</span>\n"
/datum/mood_event/enthrallpraise
mood_change = 10
timeout = 1 MINUTES
/datum/mood_event/enthrallpraise/add_effects(message)
description = "<span class='nicegreen'>[message]</span>\n"
/datum/mood_event/enthrallscold
mood_change = -10
timeout = 1 MINUTES
/datum/mood_event/enthrallscold/add_effects(message)
description = "<span class='warning'>[message]</span>\n"//aaa I'm not kinky enough for this
/datum/mood_event/enthrallmissing1
mood_change = -5
/datum/mood_event/enthrallmissing1/add_effects(message)
description = "<span class='warning'>[message]</span>\n"
/datum/mood_event/enthrallmissing2
mood_change = -10
/datum/mood_event/enthrallmissing2/add_effects(message)
description = "<span class='warning'>[message]</span>\n"
/datum/mood_event/enthrallmissing3
mood_change = -15
/datum/mood_event/enthrallmissing3/add_effects(message)
description = "<span class='warning'>[message]</span>\n"
/datum/mood_event/enthrallmissing4
mood_change = -25
/datum/mood_event/enthrallmissing4/add_effects(message)
description = "<span class='warning'>[message]</span>\n"
/datum/mood_event/InLove
mood_change = 10
/datum/mood_event/InLove/add_effects(message)
description = "<span class='nicegreen'>[message]</span>\n"
/datum/mood_event/MissingLove
mood_change = -10
/datum/mood_event/MissingLove/add_effects(message)
description = "<span class='warning'>[message]</span>\n"
@@ -176,3 +176,25 @@
/datum/mood_event/revenant_blight/add_effects()
description = "<span class='umbra'>Just give up, [pick("no one will miss you", "there is nothing you can do to help", "even a clown would be more useful than you", "does it even matter in the end?")]...</span>\n"
/datum/mood_event/plushjack
description = "<span class='warning'>I have butchered a plush recently.</span>\n"
mood_change = -1
timeout = 2 MINUTES
/datum/mood_event/plush_nostuffing
description = "<span class='warning'>A plush I tried to pet had no stuffing...</span>\n"
mood_change = -1
timeout = 2 MINUTES
//Cursed stuff below
/datum/mood_event/emptypred
description = "<span class='nicegreen'>I had to let someone out.</span>\n"
mood_change = -2
timeout = 1 MINUTES
/datum/mood_event/emptyprey
description = "<span class='nicegreen'>It feels quite cold out here.</span>\n"
mood_change = -2
timeout = 1 MINUTES
@@ -113,3 +113,38 @@
/datum/mood_event/happy_empath/add_effects(var/mob/happytarget)
description = "<span class='nicegreen'>[happytarget.name]'s happiness is infectious!</span>\n"
/datum/mood_event/headpat
description = "<span class='nicegreen'>Headpats are nice.</span>\n"
mood_change = 2
timeout = 2 MINUTES
/datum/mood_event/hugbox
description = "<span class='nicegreen'>I hugged a box of hugs recently.</span>\n"
mood_change = 1
timeout = 2 MINUTES
/datum/mood_event/plushpet
description = "<span class='nicegreen'>I pet a plush recently.</span>\n"
mood_change = 1
timeout = 3000
/datum/mood_event/plushplay
description = "<span class='nicegreen'>I've played with plushes recently.</span>\n"
mood_change = 3
timeout = 3000
//Cursed stuff below.
/datum/mood_event/orgasm
description = "<span class='userlove'>I came!</span>\n" //funny meme haha
mood_change = 3
timeout = 100 SECONDS
/datum/mood_event/fedpred
description = "<span class='nicegreen'>I've devoured someone!</span>\n"
mood_change = 3
/datum/mood_event/fedprey
description = "<span class='nicegreen'>It feels quite cozy in here.</span>\n"
mood_change = 3
+32
View File
@@ -541,6 +541,38 @@
icon_state = "ichorial_stain"
alerttooltipstyle = "clockcult"
//GOLEM GANG
/datum/status_effect/strandling //get it, strand as in durathread strand + strangling = strandling hahahahahahahahahahhahahaha i want to die
id = "strandling"
status_type = STATUS_EFFECT_UNIQUE
alert_type = /obj/screen/alert/status_effect/strandling
/datum/status_effect/strandling/on_apply()
ADD_TRAIT(owner, TRAIT_MAGIC_CHOKE, "dumbmoron")
return ..()
/datum/status_effect/strandling/on_remove()
REMOVE_TRAIT(owner, TRAIT_MAGIC_CHOKE, "dumbmoron")
return ..()
/obj/screen/alert/status_effect/strandling
name = "Choking strand"
desc = "A magical strand of Durathread is wrapped around your neck, preventing you from breathing! Click this icon to remove the strand."
icon_state = "his_grace"
alerttooltipstyle = "hisgrace"
/obj/screen/alert/status_effect/strandling/Click(location, control, params)
. = ..()
to_chat(mob_viewer, "<span class='notice'>You attempt to remove the durathread strand from around your neck.</span>")
if(do_after(mob_viewer, 35, null, mob_viewer))
if(isliving(mob_viewer))
var/mob/living/L = mob_viewer
to_chat(mob_viewer, "<span class='notice'>You succesfuly remove the durathread strand.</span>")
L.remove_status_effect(STATUS_EFFECT_CHOKINGSTRAND)
datum/status_effect/pacify
id = "pacify"
status_type = STATUS_EFFECT_REPLACE
-3
View File
@@ -316,9 +316,6 @@
to_chat(user, "<span class='warning'>You can't move while buckled to [src]!</span>")
return
/atom/proc/prevent_content_explosion()
return FALSE
/atom/proc/contents_explosion(severity, target)
return //For handling the effects of explosions on contents that would not normally be effected
+7 -1
View File
@@ -189,7 +189,13 @@
if(tod)
var/tdelta = round(world.time - timeofdeath)
if(tdelta < (DEFIB_TIME_LIMIT * 10))
holder.icon_state = "huddefib"
var/obj/item/organ/heart/He = getorgan(/obj/item/organ/heart)
if(He)
holder.icon_state = "huddefib"
if(He.organ_flags & ORGAN_FAILING)
holder.icon_state = "huddefibheart"
else
holder.icon_state = "huddefibheart"
return
holder.icon_state = "huddead"
else
+6 -3
View File
@@ -510,7 +510,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
var/added_threat = starting_rule.scale_up(extra_rulesets_amount, threat)
if (starting_rule.pre_execute())
spend_threat(starting_rule.cost + added_threat)
log_threat("[starting_rule.ruletype] - <b>[starting_rule.name]</b> -[starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat")
log_threat("[starting_rule.ruletype] - <b>[starting_rule.name]</b> -[starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat", verbose = TRUE)
if(starting_rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
else if(starting_rule.flags & ONLY_RULESET)
@@ -605,7 +605,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
new_rule.trim_candidates()
if (new_rule.ready(forced))
spend_threat(new_rule.cost)
log_threat("[new_rule.ruletype] - <b>[new_rule.name]</b> -[new_rule.cost] threat")
log_threat("[new_rule.ruletype] - <b>[new_rule.name]</b> -[new_rule.cost] threat", verbose = TRUE)
if (new_rule.execute()) // This should never fail since ready() returned 1
if(new_rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
@@ -626,7 +626,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if (rule.execute())
log_game("DYNAMIC: Injected a [rule.ruletype == "latejoin" ? "latejoin" : "midround"] ruleset [rule.name].")
spend_threat(rule.cost)
log_threat("[rule.ruletype] [rule.name] spent [rule.cost]")
log_threat("[rule.ruletype] [rule.name] spent [rule.cost]", verbose = TRUE)
if(rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
else if(rule.flags & ONLY_RULESET)
@@ -815,16 +815,19 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
/// Refund threat, but no more than threat_level.
/datum/game_mode/dynamic/proc/refund_threat(regain)
threat = min(threat_level,threat+regain)
log_threat("[regain] refunded. Threat is now [threat].", verbose = TRUE)
/// Generate threat and increase the threat_level if it goes beyond, capped at 100
/datum/game_mode/dynamic/proc/create_threat(gain)
threat = min(100, threat+gain)
if(threat > threat_level)
threat_level = threat
log_threat("[gain] created. Threat is now [threat] and threat level is now [threat_level].", verbose = TRUE)
/// Expend threat, can't fall under 0.
/datum/game_mode/dynamic/proc/spend_threat(cost)
threat = max(threat-cost,0)
log_threat("[cost] spent. Threat is now [threat].", verbose = TRUE)
/// Turns the value generated by lorentz distribution to threat value between 0 and 100.
/datum/game_mode/dynamic/proc/lorentz_to_threat(x)
+2 -3
View File
@@ -36,12 +36,11 @@
RefreshParts()
add_inital_chems()
/obj/machinery/sleeper/Destroy()
var/obj/item/reagent_containers/sleeper_buffer/buffer = new /obj/item/reagent_containers/sleeper_buffer(loc)
/obj/machinery/sleeper/on_deconstruction()
var/obj/item/reagent_containers/sleeper_buffer/buffer = new (loc)
buffer.volume = reagents.maximum_volume
buffer.reagents.maximum_volume = reagents.maximum_volume
reagents.trans_to(buffer.reagents, reagents.total_volume)
..()
/obj/machinery/sleeper/proc/add_inital_chems()
for(var/i in available_chems)
+13 -12
View File
@@ -18,8 +18,8 @@
var/item_recycle_sound = 'sound/items/welder.ogg'
/obj/machinery/recycler/Initialize()
AddComponent(/datum/component/butchering/recycler, 1, amount_produced,amount_produced/5)
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC), INFINITY, FALSE, null, null, null, TRUE)
AddComponent(/datum/component/butchering, 1, amount_produced,amount_produced/5)
. = ..()
update_icon()
req_one_access = get_all_accesses() + get_all_centcom_access()
@@ -35,7 +35,7 @@
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = mat_mod
amount_produced = min(50, amt_made) + 50
var/datum/component/butchering/butchering = GetComponent(/datum/component/butchering)
var/datum/component/butchering/butchering = GetComponent(/datum/component/butchering/recycler)
butchering.effectiveness = amount_produced
butchering.bonus_modifier = amount_produced/5
@@ -83,20 +83,24 @@
is_powered = FALSE
icon_state = icon_name + "[is_powered]" + "[(blood ? "bld" : "")]" // add the blood tag at the end
/obj/machinery/recycler/Bumped(atom/movable/AM)
if(stat & (BROKEN|NOPOWER))
return
/obj/machinery/recycler/CanPass(atom/movable/AM)
. = ..()
if(!anchored)
return
if(safety_mode)
return
var/move_dir = get_dir(loc, AM.loc)
if(move_dir == eat_dir)
eat(AM)
return TRUE
/obj/machinery/recycler/Crossed(atom/movable/AM)
eat(AM)
. = ..()
/obj/machinery/recycler/proc/eat(atom/AM0, sound=TRUE)
if(stat & (BROKEN|NOPOWER))
return
if(safety_mode)
return
var/list/to_eat
if(isitem(AM0))
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
@@ -194,9 +198,6 @@
// Instantly lie down, also go unconscious from the pain, before you die.
L.Unconscious(100)
L.adjustBruteLoss(crush_damage)
if(L.stat == DEAD && (L.butcher_results || L.guaranteed_butcher_results))
var/datum/component/butchering/butchering = GetComponent(/datum/component/butchering)
butchering.Butcher(src,L)
/obj/machinery/recycler/deathtrap
name = "dangerous old crusher"
@@ -20,7 +20,7 @@
/obj/item/mecha_parts/mecha_equipment/drill/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 50, 100)
AddComponent(/datum/component/butchering, 50, 100, null, null, TRUE)
/obj/item/mecha_parts/mecha_equipment/drill/action(atom/target)
if(!action_checks(target))
+7 -2
View File
@@ -81,6 +81,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES
var/heat = 0
///All items with sharpness of IS_SHARP or higher will automatically get the butchering component.
var/sharpness = IS_BLUNT
var/tool_behaviour = NONE
@@ -139,6 +140,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
else if (!istype(embedding, /datum/embedding_behavior))
stack_trace("Invalid type [embedding.type] found in .embedding during /obj/item Initialize()")
if(sharpness) //give sharp objects butchering functionality, for consistency
AddComponent(/datum/component/butchering, 80 * toolspeed)
/obj/item/Destroy()
item_flags &= ~DROPDEL //prevent reqdels
if(ismob(loc))
@@ -393,13 +397,14 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
return
if(over == src)
return usr.client.Click(src, src_location, src_control, params)
var/list/directaccess = usr.DirectAccess()
var/list/directaccess = usr.DirectAccess() //This, specifically, is what requires the copypaste. If this were after the adjacency check, then it'd be impossible to use items in your inventory, among other things.
//If this were before the above checks, then trying to click on items would act a little funky and signal overrides wouldn't work.
if((usr.CanReach(src) || (src in directaccess)) && (usr.CanReach(over) || (over in directaccess)))
if(!usr.get_active_held_item())
usr.UnarmedAttack(src, TRUE)
if(usr.get_active_held_item() == src)
melee_attack_chain(usr, over)
return
return TRUE //returning TRUE as a "is this overridden?" flag
if(!Adjacent(usr) || !over.Adjacent(usr))
return // should stop you from dragging through windows
+1 -3
View File
@@ -104,7 +104,7 @@
/obj/item/defibrillator/MouseDrop(obj/over_object)
. = ..()
if(ismob(loc))
if(!. && ismob(loc) && loc == usr)
var/mob/M = loc
if(!M.incapacitated() && istype(over_object, /obj/screen/inventory/hand))
var/obj/screen/inventory/hand/H = over_object
@@ -762,5 +762,3 @@
desc = "An upgrade to the defibrillator capacitors, which let it charge faster"
icon_state = "fast_disk"
materials = list(MAT_METAL=16000, MAT_GLASS = 8000, MAT_GOLD = 26000, MAT_SILVER = 26000)
#undef HALFWAYCRITDEATH
+1 -1
View File
@@ -1044,7 +1044,7 @@ GLOBAL_LIST_EMPTY(PDAs)
if (ismob(loc))
var/mob/M = loc
M.show_message("<span class='userdanger'>Your [src] explodes!</span>", 1)
M.show_message("<span class='userdanger'>Your [src] explodes!</span>", MSG_VISUAL, "<span class='warning'>You hear a loud *pop*!</span>", MSG_AUDIBLE)
else
visible_message("<span class='danger'>[src] explodes!</span>", "<span class='warning'>You hear a loud *pop*!</span>")
+6 -4
View File
@@ -24,6 +24,7 @@
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
w_class = WEIGHT_CLASS_TINY
rad_flags = RAD_PROTECT_CONTENTS //So the cartridges dont annoyingly get irradiated, and the signallers inside being radded as well
var/obj/item/integrated_signaler/radio = null
@@ -689,15 +690,16 @@ Code:
active_bot = null
if("summon") //Args are in the correct order, they are stated here just as an easy reminder.
active_bot.bot_control(command= "summon", user_turf= get_turf(usr), user_access= host_pda.GetAccess())
active_bot.bot_control("summon", usr, host_pda.GetAccess())
else //Forward all other bot commands to the bot itself!
active_bot.bot_control(command= href_list["op"], user= usr)
active_bot.bot_control(href_list["op"], usr)
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
if(href_list["mule"]) //MULEbots are special snowflakes, and need different args due to how they work.
active_bot.bot_control(href_list["mule"], usr, TRUE)
var/mob/living/simple_animal/bot/mulebot/mule = active_bot
if (istype(mule))
active_bot.bot_control(href_list["mule"], usr, TRUE)
if(!host_pda)
return
@@ -72,12 +72,12 @@
difficulty += 2
var/datum/component/uplink/hidden_uplink = target.GetComponent(/datum/component/uplink)
if(!target.detonatable || prob(difficulty * 15) || (hidden_uplink))
U.show_message("<span class='danger'>An error flashes on your [src].</span>", 1)
U.show_message("<span class='danger'>An error flashes on your [src].</span>", MSG_VISUAL)
else
message_admins("[!is_special_character(U) ? "Non-antag " : ""][ADMIN_LOOKUPFLW(U)] triggered a PDA explosion on [target.name] at [ADMIN_VERBOSEJMP(target)].")
var/message_log = "triggered a PDA explosion on [target.name] at [AREACOORD(target)]."
U.log_message(message_log, LOG_ATTACK)
U.show_message("<span class='notice'>Success!</span>", 1)
U.show_message("<span class='notice'>Success!</span>", MSG_VISUAL)
target.explode()
else
to_chat(U, "PDA not found.")
@@ -431,6 +431,7 @@
icon_state = "glowstick"
item_state = "glowstick"
grind_results = list("phenol" = 15, "hydrogen" = 10, "oxygen" = 5) //Meth-in-a-stick
rad_flags = RAD_NO_CONTAMINATE
var/fuel = 0
/obj/item/flashlight/glowstick/Initialize()
+205 -202
View File
@@ -131,232 +131,228 @@ SLIME SCANNER
mob_status = "<span class='alert'><b>Deceased</b></span>"
oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.undergoing_cardiac_arrest() && H.stat != DEAD)
to_chat(user, "<span class='danger'>Subject suffering from heart attack: Apply defibrillation or other electric shock immediately!</span>")
if(H.undergoing_liver_failure() && H.stat != DEAD) //might be depreciated BUG_PROBABLE_CAUSE
to_chat(user, "<span class='danger'>Subject is suffering from liver failure: Apply Corazone and begin a liver transplant immediately!</span>")
var/msg = "<span class='info'>*---------*\nAnalyzing results for [M]:\n\tOverall status: [mob_status]\n"
var/msg = "<span class='info'>*---------*\nAnalyzing results for [M]:\n\tOverall status: [mob_status]"
// Damage descriptions
if(brute_loss > 10)
msg += "\t<span class='alert'>[brute_loss > 50 ? "Severe" : "Minor"] tissue damage detected.</span>\n"
msg += "\n\t<span class='alert'>[brute_loss > 50 ? "Severe" : "Minor"] tissue damage detected.</span>"
if(fire_loss > 10)
msg += "\t<span class='alert'>[fire_loss > 50 ? "Severe" : "Minor"] burn damage detected.</span>\n"
msg += "\n\t<span class='alert'>[fire_loss > 50 ? "Severe" : "Minor"] burn damage detected.</span>"
if(oxy_loss > 10)
msg += "\t<span class='info'><span class='alert'>[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.</span>\n"
msg += "\n\t<span class='info'><span class='alert'>[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.</span>"
if(tox_loss > 10)
msg += "\t<span class='alert'>[tox_loss > 50 ? "Severe" : "Minor"] amount of toxin damage detected.</span>\n"
msg += "\n\t<span class='alert'>[tox_loss > 50 ? "Severe" : "Minor"] amount of toxin damage detected.</span>"
if(M.getStaminaLoss())
msg += "\t<span class='alert'>Subject appears to be suffering from fatigue.</span>\n"
msg += "\n\t<span class='alert'>Subject appears to be suffering from fatigue.</span>"
if(advanced)
msg += "\t<span class='info'>Fatigue Level: [M.getStaminaLoss()]%.</span>\n"
msg += "\n\t<span class='info'>Fatigue Level: [M.getStaminaLoss()]%.</span>"
if (M.getCloneLoss())
msg += "\t<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.</span>\n"
msg += "\n\t<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.</span>"
if(advanced)
msg += "\t<span class='info'>Cellular Damage Level: [M.getCloneLoss()].</span>\n"
if (!M.getorgan(/obj/item/organ/brain))
to_chat(user, "\t<span class='alert'>Subject lacks a brain.</span>") //Unsure how this won't proc for 50% of the cit playerbase (This is a joke everyone on cit a cute.)
if(ishuman(M) && advanced) // Should I make this not advanced?
var/mob/living/carbon/human/H = M
var/obj/item/organ/liver/L = H.getorganslot("liver")
if(L)
if(L.swelling > 20)
msg += "\t<span class='danger'>Subject is suffering from an enlarged liver.</span>\n" //i.e. shrink their liver or give them a transplant.
else
msg += "\t<span class='danger'>Subject's liver is missing.</span>\n"
var/obj/item/organ/tongue/T = H.getorganslot("tongue")
if(T)
if(T.damage > 40)
msg += "\t<span class='danger'>Subject is suffering from severe burn tissue on their tongue.</span>\n" //i.e. their tongue is shot
if(T.name == "fluffy tongue")
msg += "\t<span class='danger'>Subject is suffering from a fluffified tongue. Suggested cure: Yamerol or a tongue transplant.</span>\n"
else
msg += "\t<span class='danger'>Subject's tongue is missing.</span>\n"
var/obj/item/organ/lungs/Lung = H.getorganslot("lungs")
if(Lung)
if(Lung.damage > 150)
msg += "\t<span class='danger'>Subject is suffering from acute emphysema leading to trouble breathing.</span>\n" //i.e. Their lungs are shot
else
msg += "\t<span class='danger'>Subject's lungs have collapsed from trauma!</span>\n"
var/obj/item/organ/genital/penis/P = H.getorganslot("penis")
if(P)
if(P.length>20)
msg += "\t<span class='info'>Subject has a sizeable gentleman's organ at [P.length] inches.</span>\n"
var/obj/item/organ/genital/breasts/Br = H.getorganslot("breasts")
if(Br)
if(Br.cached_size>5)
msg += "\t<span class='info'>Subject has a sizeable bosom with a [Br.size] cup.</span>\n"
if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 200 || !M.getorgan(/obj/item/organ/brain))
msg += "\t<span class='alert'>Subject's brain function is non-existent.</span>\n"
else if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 120)
msg += "\t<span class='alert'>Severe brain damage detected. Subject likely to have mental traumas.</span>\n"
else if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 45)
msg += "\t<span class='alert'>Brain damage detected.</span>\n"
if(iscarbon(M))
var/mob/living/carbon/C = M
if(LAZYLEN(C.get_traumas()))
var/list/trauma_text = list()
for(var/datum/brain_trauma/B in C.get_traumas())
var/trauma_desc = ""
switch(B.resilience)
if(TRAUMA_RESILIENCE_SURGERY)
trauma_desc += "severe "
if(TRAUMA_RESILIENCE_LOBOTOMY)
trauma_desc += "deep-rooted "
if(TRAUMA_RESILIENCE_MAGIC, TRAUMA_RESILIENCE_ABSOLUTE)
trauma_desc += "permanent "
trauma_desc += B.scan_desc
trauma_text += trauma_desc
msg += "\t<span class='alert'>Cerebral traumas detected: subject appears to be suffering from [english_list(trauma_text)].</span>\n"
if(C.roundstart_quirks.len)
msg += "\t<span class='info'>Subject has the following physiological traits: [C.get_trait_string()].</span>\n"
if(advanced)
msg += "\t<span class='info'>Brain Activity Level: [(200 - M.getOrganLoss(ORGAN_SLOT_BRAIN))/2]%.</span>\n"
if(M.radiation)
msg += "\t<span class='alert'>Subject is irradiated.</span>\n"
msg += "\t<span class='info'>Radiation Level: [M.radiation] rad</span>\n"
if(advanced && M.hallucinating())
msg += "\t<span class='info'>Subject is hallucinating.</span>\n"
//MKUltra
if(advanced && M.has_status_effect(/datum/status_effect/chem/enthrall))
msg += "\t<span class='info'>Subject has abnormal brain fuctions.</span>\n"
//Astrogen shenanigans
if(advanced && M.reagents.has_reagent("astral"))
if(M.mind)
msg += "\t<span class='danger'>Warning: subject may be possesed.</span>\n"
else
msg += "\t<span class='notice'>Subject appears to be astrally projecting.</span>\n"
//Eyes and ears
if(advanced)
if(iscarbon(M))
var/mob/living/carbon/C = M
var/obj/item/organ/ears/ears = C.getorganslot(ORGAN_SLOT_EARS)
msg += "\t<span class='info'><b>==EAR STATUS==</b></span>\n"
if(istype(ears))
var/healthy = TRUE
if(HAS_TRAIT_FROM(C, TRAIT_DEAF, GENETIC_MUTATION))
healthy = FALSE
msg += "\t<span class='alert'>Subject is genetically deaf.</span>\n"
else if(HAS_TRAIT(C, TRAIT_DEAF))
healthy = FALSE
msg += "\t<span class='alert'>Subject is deaf.</span>\n"
else
if(ears.damage)
to_chat(user, "\t<span class='alert'>Subject has [ears.damage > ears.maxHealth ? "permanent ": "temporary "]hearing damage.</span>")
healthy = FALSE
if(ears.deaf)
to_chat(user, "\t<span class='alert'>Subject is [ears.damage > ears.maxHealth ? "permanently ": "temporarily "] deaf.</span>")
healthy = FALSE
if(healthy)
msg += "\t<span class='info'>Healthy.</span>\n"
else
msg += "\t<span class='alert'>Subject does not have ears.</span>\n"
var/obj/item/organ/eyes/eyes = C.getorganslot(ORGAN_SLOT_EYES)
msg += "\t<span class='info'><b>==EYE STATUS==</b></span>\n"
if(istype(eyes))
var/healthy = TRUE
if(HAS_TRAIT(C, TRAIT_BLIND))
msg += "\t<span class='alert'>Subject is blind.</span>\n"
healthy = FALSE
if(HAS_TRAIT(C, TRAIT_NEARSIGHT))
msg += "\t<span class='alert'>Subject is nearsighted.</span>\n"
healthy = FALSE
if(eyes.damage > 30)
msg += "\t<span class='alert'>Subject has severe eye damage.</span>\n"
healthy = FALSE
else if(eyes.damage > 20)
msg += "\t<span class='alert'>Subject has significant eye damage.</span>\n"
healthy = FALSE
else if(eyes.damage)
msg += "\t<span class='alert'>Subject has minor eye damage.</span>\n"
healthy = FALSE
if(healthy)
msg += "\t<span class='info'>Healthy.</span>\n"
else
msg += "\t<span class='alert'>Subject does not have eyes.</span>\n"
msg += "\n\t<span class='info'>Cellular Damage Level: [M.getCloneLoss()].</span>"
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/ldamage = H.return_liver_damage()
if(ldamage > 10)
msg += "\t<span class='alert'>[ldamage > 45 ? "Severe" : "Minor"] liver damage detected.</span>\n"
to_chat(user, msg)
msg = ""
// Body part damage report
var/list/dmgreport = list()
if(iscarbon(M) && mode == 1)
var/mob/living/carbon/C = M
var/list/damaged = C.get_damaged_bodyparts(1,1)
if(length(damaged)>0 || oxy_loss>0 || tox_loss>0 || fire_loss>0)
msg += "<span class='info'>\tDamage: <span class='info'><font color='red'>Brute</font></span>-<font color='#FF8000'>Burn</font>-<font color='green'>Toxin</font>-<font color='blue'>Suffocation</font>\n\t\tSpecifics: <font color='red'>[brute_loss]</font>-<font color='#FF8000'>[fire_loss]</font>-<font color='green'>[tox_loss]</font>-<font color='blue'>[oxy_loss]</font></span>\n"
for(var/obj/item/bodypart/org in damaged)
msg += "\t\t<span class='info'>[capitalize(org.name)]: [(org.brute_dam > 0) ? "<font color='red'>[org.brute_dam]</font></span>" : "<font color='red'>0</font>"]-[(org.burn_dam > 0) ? "<font color='#FF8000'>[org.burn_dam]</font>" : "<font color='#FF8000'>0</font>"]\n"
dmgreport += "<table style='margin-left:33px'><tr><font face='Verdana'>\
<td style='width: 90px;'><font color='#0000CC'>Damage:</font></td>\
<td style='width: 55px;'><font color='red'><b>Brute</b></font></td>\
<td style='width: 45px;'><font color='orange'><b>Burn</b></font></td>\
<td style='width: 45px;'><font color='green'><b>Toxin</b></font></td>\
<td style='width: 90px;'><font color='purple'><b>Suffocation</b></font></td></tr>\
<tr><td><font color='#0000CC'>Overall:</font></td>\
<td><font color='red'>[brute_loss]</font></td>\
<td><font color='orange'>[fire_loss]</font></td>\
<td><font color='green'>[tox_loss]</font></td>\
<td><font color='purple'>[oxy_loss]</font></td></tr>"
for(var/o in damaged)
var/obj/item/bodypart/org = o //head, left arm, right arm, etc.
dmgreport += "<tr><td><font color='#0000CC'>[capitalize(org.name)]:</font></td>\
<td><font color='red'>[(org.brute_dam > 0) ? "[org.brute_dam]" : "0"]</font></td>\
<td><font color='orange'>[(org.burn_dam > 0) ? "[org.burn_dam]" : "0"]</font></td></tr>"
dmgreport += "</table>"
to_chat(user, dmgreport.Join())
//Organ damages report
if(ishuman(M))
var/heart_ded = FALSE
if(iscarbon(M))
var/mob/living/carbon/C = M
var/mob/living/carbon/human/H = M
var/minor_damage
var/major_damage
var/max_damage
var/report_organs = FALSE
for(var/organ in C.internal_organs)
var/temp_message
var/damage_message
var/obj/item/organ/O = organ
//Piece together the lists to be reported
for(var/O in H.internal_organs)
var/obj/item/organ/organ = O
if(organ.organ_flags & ORGAN_FAILING)
report_organs = TRUE //if we report one organ, we report all organs, even if the lists are empty, just for consistency
if(max_damage)
max_damage += ", " //prelude the organ if we've already reported an organ
max_damage += organ.name //this just slaps the organ name into the string of text
else
max_damage = "\t<span class='alert'>Non-Functional Organs: " //our initial statement
max_damage += organ.name
else if(organ.damage > organ.high_threshold)
report_organs = TRUE
if(major_damage)
major_damage += ", "
major_damage += organ.name
else
major_damage = "\t<span class='info'>Severely Damaged Organs: "
major_damage += organ.name
else if(organ.damage > organ.low_threshold)
report_organs = TRUE
if(minor_damage)
minor_damage += ", "
minor_damage += organ.name
else
minor_damage = "\t<span class='info'>Mildly Damaged Organs: "
minor_damage += organ.name
//EYES
if(istype(O, /obj/item/organ/eyes))
var/obj/item/organ/eyes/eyes = O
if(advanced)
if(HAS_TRAIT(C, TRAIT_BLIND))
temp_message += " <span class='alert'>Subject is blind.</span>"
if(HAS_TRAIT(C, TRAIT_NEARSIGHT))
temp_message += " <span class='alert'>Subject is nearsighted.</span>"
if(eyes.damage > 30)
damage_message += " <span class='alert'>Subject has severe eye damage.</span>"
else if(eyes.damage > 20)
damage_message += " <span class='alert'>Subject has significant eye damage.</span>"
else if(eyes.damage)
damage_message += " <span class='alert'>Subject has minor eye damage.</span>"
//EARS
else if(istype(O, /obj/item/organ/ears))
var/obj/item/organ/ears/ears = O
if(advanced)
if(HAS_TRAIT_FROM(C, TRAIT_DEAF, GENETIC_MUTATION))
temp_message += " <span class='alert'>Subject is genetically deaf.</span>"
else if(HAS_TRAIT(C, TRAIT_DEAF))
temp_message += " <span class='alert'>Subject is deaf.</span>"
else
if(ears.damage)
damage_message += " <span class='alert'>Subject has [ears.damage > ears.maxHealth ? "permanent ": "temporary "]hearing damage.</span>"
if(ears.deaf)
damage_message += " <span class='alert'>Subject is [ears.damage > ears.maxHealth ? "permanently ": "temporarily "] deaf.</span>"
//BRAIN
else if(istype(O, /obj/item/organ/brain))
if (C.getOrganLoss(ORGAN_SLOT_BRAIN) >= 200)
damage_message += " <span class='alert'>Subject's brain non-functional. Neurine injection recomended.</span>"
else if (C.getOrganLoss(ORGAN_SLOT_BRAIN) >= 120)
damage_message += " <span class='alert'>Severe brain damage detected. Subject likely to have mental traumas.</span>"
else if (C.getOrganLoss(ORGAN_SLOT_BRAIN) >= 45)
damage_message += " <span class='alert'>Brain damage detected.</span>"
if(advanced)
temp_message += " <span class='info'>Brain Activity Level: [(200 - M.getOrganLoss(ORGAN_SLOT_BRAIN))/2]%.</span>"
//TRAUMAS
if(LAZYLEN(C.get_traumas()))
var/list/trauma_text = list()
for(var/datum/brain_trauma/B in C.get_traumas())
var/trauma_desc = ""
switch(B.resilience)
if(TRAUMA_RESILIENCE_SURGERY)
trauma_desc += "severe "
if(TRAUMA_RESILIENCE_LOBOTOMY)
trauma_desc += "deep-rooted "
if(TRAUMA_RESILIENCE_MAGIC, TRAUMA_RESILIENCE_ABSOLUTE)
trauma_desc += "permanent "
trauma_desc += B.scan_desc
trauma_text += trauma_desc
temp_message += " <span class='alert'>Cerebral traumas detected: subject appears to be suffering from [english_list(trauma_text)].</span>"
if(C.roundstart_quirks.len)
temp_message += " <span class='info'>Subject has the following physiological traits: [C.get_trait_string()].</span>"
if(ishuman(C) && advanced)
//MON PETIT CHAUFFEUR
if(H.hallucinating())
temp_message += " <span class='info'>Subject is hallucinating.</span>"
//MKUltra
if(H.has_status_effect(/datum/status_effect/chem/enthrall))
temp_message += " <span class='info'>Subject has abnormal brain fuctions.</span>"
//Astrogen shenanigans
if(H.reagents.has_reagent("astral"))
if(H.mind)
temp_message += " <span class='danger'>Warning: subject may be possesed.</span>"
else
temp_message += " <span class='notice'>Subject appears to be astrally projecting.</span>"
//LIVER
else if(istype(O, /obj/item/organ/liver))
var/obj/item/organ/liver/L = O
if(H.undergoing_liver_failure() && H.stat != DEAD) //might be depreciated
temp_message += "<span class='danger'>Subject is suffering from liver failure: Apply Corazone and begin a liver transplant immediately!</span>"
if(L.swelling > 20)
temp_message += " <span class='danger'>Subject is suffering from an enlarged liver.</span>" //i.e. shrink their liver or give them a transplant.
//HEART
else if(ishuman(M) && (istype(O, /obj/item/organ/heart)))
var/obj/item/organ/heart/He = O
if(H.undergoing_cardiac_arrest() && H.stat != DEAD)
temp_message += " <span class='danger'>Subject suffering from heart attack: Apply defibrillation or other electric shock <b>immediately!</b></span>"
if(He.organ_flags & ORGAN_FAILING)
heart_ded = TRUE
//TONGUE
else if(istype(O, /obj/item/organ/tongue))
var/obj/item/organ/tongue/T = O
if(T.name == "fluffy tongue")
temp_message += " <span class='danger'>Subject is suffering from a fluffified tongue. Suggested cure: Yamerol or a tongue transplant.</span>"
//HECK
else if(istype(O, /obj/item/organ/genital/penis))
var/obj/item/organ/genital/penis/P = O
if(P.length>20)
temp_message += " <span class='info'>Subject has a sizeable gentleman's organ at [P.length] inches.</span>"
else if(istype(O, /obj/item/organ/genital/breasts))
var/obj/item/organ/genital/breasts/Br = O
if(Br.cached_size>5)
temp_message += " <span class='info'>Subject has a sizeable bosom with a [Br.size] cup.</span>"
//GENERAL HANDLER
if(!damage_message)
if(O.organ_flags & ORGAN_FAILING)
damage_message += " <span class='alert'><b>End Stage [O.name] failure detected.</b></span>"
else if(O.damage > O.high_threshold)
damage_message += " <span class='alert'>Chronic [O.name] failure detected.</span>"
else if(O.damage > O.low_threshold && advanced)
damage_message += " <font color='red'>Acute [O.name] failure detected.</span>"
if(temp_message || damage_message)
msg += "\t<b><span class='info'>[uppertext(O.name)]:</b></span> [damage_message] [temp_message]\n"
//END; LOOK FOR MISSING ORGANS?
var/breathes = TRUE
var/blooded = TRUE
if(C.dna && C.dna.species)
if(HAS_TRAIT_FROM(C, TRAIT_NOBREATH, SPECIES_TRAIT))
breathes = FALSE
if(NOBLOOD in C.dna.species.species_traits)
blooded = FALSE
var/has_liver = (!(NOLIVER in C.dna.species.species_traits))
var/has_stomach = (!(NOSTOMACH in C.dna.species.species_traits))
if(!M.getorganslot(ORGAN_SLOT_EYES))
msg += "\t<span class='alert'><b>Subject does not have eyes.</b></span>\n"
if(!M.getorganslot(ORGAN_SLOT_EARS))
msg += "\t<span class='alert'><b>Subject does not have ears.</b></span>\n"
if(!M.getorganslot(ORGAN_SLOT_BRAIN))
msg += "\t<span class='alert'><b>Subject's brain function is non-existent!</b></span>\n"
if(has_liver && !M.getorganslot(ORGAN_SLOT_LIVER))
msg += "\t<span class='alert'><b>Subject's liver is missing!</b></span>\n"
if(blooded && !M.getorganslot(ORGAN_SLOT_HEART))
msg += "\t<span class='alert'><b>Subject's heart is missing!</b></span>\n"
if(breathes && !M.getorganslot(ORGAN_SLOT_LUNGS))
msg += "\t<span class='alert'><b>Subject's lungs have collapsed from trauma!</b></span>\n"
if(has_stomach && !M.getorganslot(ORGAN_SLOT_STOMACH))
msg += "\t<span class='alert'><b>Subject's stomach is missing!</span>\n"
if(M.radiation)
msg += "\t<span class='alert'>Subject is irradiated.</span>\n"
msg += "\t<span class='info'>Radiation Level: [M.radiation] rad</span>\n"
if(report_organs) //we either finish the list, or set it to be empty if no organs were reported in that category
if(!max_damage)
max_damage = "\t<span class='alert'>Non-Functional Organs: </span>\n"
else
max_damage += "</span>\n"
if(!major_damage)
major_damage = "\t<span class='info'>Severely Damaged Organs: </span>\n"
else
major_damage += "</span>\n"
if(!minor_damage)
minor_damage = "\t<span class='info'>Mildly Damaged Organs: </span>\n"
else
minor_damage += "</span>\n"
msg += "[minor_damage]"
msg += "[major_damage]"
msg += "[max_damage]"
// Species and body temperature
var/mob/living/carbon/human/H = M //Start to use human only stuff here
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/datum/species/S = H.dna.species
var/mutant = FALSE
if (H.dna.check_mutation(HULK))
@@ -393,7 +389,15 @@ SLIME SCANNER
msg += "<span class='info'>Time of Death:</span> [M.tod]\n"
var/tdelta = round(world.time - M.timeofdeath)
if(tdelta < (DEFIB_TIME_LIMIT * 10))
msg += "<span class='danger'>Subject died [DisplayTimeText(tdelta)] ago, defibrillation may be possible!</span>\n"
if(heart_ded)
msg += "<span class='danger'>Subject died [DisplayTimeText(tdelta)] ago, heart requires surgical intervention for defibrillation.</span>"
else
msg += "<span class='danger'>Subject died [DisplayTimeText(tdelta)] ago, defibrillation may be possible!</span>"
if(advanced)
if(H.get_ghost() || H.key || H.client)//Since it can last a while.
msg += "<span class='danger'> Intervention recommended.</span>\n"
else
msg += "\n"
for(var/thing in M.diseases)
var/datum/disease/D = thing
@@ -406,7 +410,6 @@ SLIME SCANNER
var/blood_id = C.get_blood_id()
if(blood_id)
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(H.bleed_rate)
msg += "<span class='danger'>Subject is bleeding!</span>\n"
var/blood_percent = round((C.blood_volume / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100)
@@ -431,7 +434,7 @@ SLIME SCANNER
if(cyberimp_detect)
msg += "<span class='notice'>Detected cybernetic modifications:</span>\n"
msg += "<span class='notice'>[cyberimp_detect]</span>\n"
msg += "*---------*</span>"
msg += "<span class='notice'>*---------*</span>"
to_chat(user, msg)
SEND_SIGNAL(M, COMSIG_NANITE_SCAN, user, FALSE)
@@ -21,7 +21,7 @@
/obj/item/grenade/flashbang/proc/bang(turf/T , mob/living/M)
if(M.stat == DEAD) //They're dead!
return
M.show_message("<span class='warning'>BANG</span>", 2)
M.show_message("<span class='warning'>BANG</span>", MSG_AUDIBLE)
var/distance = max(0,get_dist(get_turf(src),T))
//Flash
+1 -1
View File
@@ -107,7 +107,7 @@
return ..()
/obj/item/implant/proc/get_data()
return "No information available"
return "No information available about this implant."
/obj/item/implant/dropped(mob/user)
. = 1
+12 -15
View File
@@ -13,34 +13,31 @@
var/broadcasting = null
var/listening = 1
/obj/item/implantpad/examine(mob/user)
. = ..()
if(case)
. += "<span class='notice'>Alt-click [src] to remove the inserted implant case.</span>"
/obj/item/implantpad/update_icon()
if(case)
icon_state = "implantpad-1"
else
icon_state = "implantpad-0"
icon_state = "implantpad-[case ? TRUE : FALSE]"
/obj/item/implantpad/attack_hand(mob/user)
/obj/item/implantpad/AltClick(mob/user)
. = ..()
if(.)
return
if(case && user.is_holding(src))
user.put_in_active_hand(case)
if(case && user.can_hold_items() && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
user.put_in_hands(case)
case.add_fingerprint(user)
case = null
add_fingerprint(user)
update_icon()
return TRUE
/obj/item/implantpad/attackby(obj/item/implantcase/C, mob/user, params)
if(istype(C, /obj/item/implantcase))
if(!case)
if(!user.transferItemToLoc(C, src))
return
if(istype(C))
if(!case && user.transferItemToLoc(C, src))
case = C
update_icon()
update_icon()
else
return ..()
+4
View File
@@ -205,3 +205,7 @@
/obj/item/inducer/sci/combat/Initialize()
. = ..()
update_icon()
/obj/item/inducer/sci/supply
opened = FALSE
cell_type = /obj/item/stock_parts/cell/inducer_supply
@@ -23,8 +23,8 @@
else
if(attack_verb_off.len)
attack_verb = attack_verb_off
if(get_sharpness())
AddComponent(/datum/component/butchering, 50, 100, 0, hitsound, !active)
if(sharpness)
AddComponent(/datum/component/butchering, 50, 100, 0, hitsound)
/obj/item/melee/transforming/attack_self(mob/living/carbon/user)
if(transform_weapon(user))
@@ -65,13 +65,6 @@
icon_state = initial(icon_state)
w_class = initial(w_class)
total_mass = initial(total_mass)
if(get_sharpness())
var/datum/component/butchering/BT = LoadComponent(/datum/component/butchering)
BT.butchering_enabled = TRUE
else
var/datum/component/butchering/BT = GetComponent(/datum/component/butchering)
if(BT)
BT.butchering_enabled = FALSE
transform_messages(user, supress_message_text)
add_fingerprint(user)
return TRUE
+2 -1
View File
@@ -151,12 +151,13 @@
add_overlay("[locked ? "" : "un"]locked")
/obj/item/pet_carrier/MouseDrop(atom/over_atom)
. = ..()
if(isopenturf(over_atom) && usr.canUseTopic(src, BE_CLOSE, ismonkey(usr)) && usr.Adjacent(over_atom) && open && occupants.len)
usr.visible_message("<span class='notice'>[usr] unloads [src].</span>", \
"<span class='notice'>You unload [src] onto [over_atom].</span>")
for(var/V in occupants)
remove_occupant(V, over_atom)
else
return ..()
/obj/item/pet_carrier/proc/load_occupant(mob/living/user, mob/living/target)
if(pet_carrier_full(src))
+9 -5
View File
@@ -113,8 +113,10 @@
return
log_game("[key_name(user)] activated a hidden grenade in [src].")
grenade.preprime(user, msg = FALSE, volume = 10)
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plushpet", /datum/mood_event/plushpet)
else
to_chat(user, "<span class='notice'>You try to pet [src], but it has no stuffing. Aww...</span>")
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plush_nostuffing", /datum/mood_event/plush_nostuffing)
/obj/item/toy/plush/attackby(obj/item/I, mob/living/user, params)
if(I.get_sharpness())
@@ -125,6 +127,7 @@
user.visible_message("<span class='notice'>[user] tears out the stuffing from [src]!</span>", "<span class='notice'>You rip a bunch of the stuffing from [src]. Murderer.</span>")
I.play_tool_sound(src)
stuffed = FALSE
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plushjack", /datum/mood_event/plushjack)
else
to_chat(user, "<span class='notice'>You remove the grenade from [src].</span>")
user.put_in_hands(grenade)
@@ -147,6 +150,7 @@
return
if(istype(I, /obj/item/toy/plush))
love(I, user)
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plushplay", /datum/mood_event/plushplay)
return
return ..()
@@ -158,7 +162,7 @@
//we are not catholic
if(young == TRUE || Kisser.young == TRUE)
user.show_message("<span class='notice'>[src] plays tag with [Kisser].</span>", 1,
user.show_message("<span class='notice'>[src] plays tag with [Kisser].</span>", MSG_VISUAL,
"<span class='notice'>They're happy.</span>", 0)
Kisser.cheer_up()
cheer_up()
@@ -166,10 +170,10 @@
//never again
else if(Kisser in scorned)
//message, visible, alternate message, neither visible nor audible
user.show_message("<span class='notice'>[src] rejects the advances of [Kisser]!</span>", 1,
user.show_message("<span class='notice'>[src] rejects the advances of [Kisser]!</span>", MSG_VISUAL,
"<span class='notice'>That didn't feel like it worked.</span>", 0)
else if(src in Kisser.scorned)
user.show_message("<span class='notice'>[Kisser] realises who [src] is and turns away.</span>", 1,
user.show_message("<span class='notice'>[Kisser] realises who [src] is and turns away.</span>", MSG_VISUAL,
"<span class='notice'>That didn't feel like it worked.</span>", 0)
//first comes love
@@ -190,7 +194,7 @@
new_lover(Kisser)
Kisser.new_lover(src)
else
user.show_message("<span class='notice'>[src] rejects the advances of [Kisser], maybe next time?</span>", 1,
user.show_message("<span class='notice'>[src] rejects the advances of [Kisser], maybe next time?</span>", MSG_VISUAL,
"<span class='notice'>That didn't feel like it worked, this time.</span>", 0)
//then comes marriage
@@ -1014,7 +1018,7 @@
icon_state = "maya"
item_state = "maya"
attack_verb = list("nuked", "arrested", "harmbatonned")
/obj/item/toy/plush/catgirl/marisa
desc = "An adorable stuffed toy that resembles a crew member, or maybe a witch. Having it makes you feel you can win."
icon_state = "marisa"
@@ -620,6 +620,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list(
new /datum/stack_recipe("plastic flaps", /obj/structure/plasticflaps, 5, one_per_turf = TRUE, on_floor = TRUE, time = 40), \
new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \
new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \
new /datum/stack_recipe("large trash cart", /obj/structure/closet/crate/bin,50),\
new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2)))
/obj/item/stack/sheet/plastic
@@ -82,6 +82,55 @@
item_state = "tile-fairygrass"
turf_type = /turf/open/floor/grass/fairy
resistance_flags = FLAMMABLE
color = "#33CCFF"
/obj/item/stack/tile/fairygrass/white
name = "white fairygrass tile"
singular_name = "white fairygrass floor tile"
desc = "A patch of odd, glowing white grass."
turf_type = /turf/open/floor/grass/fairy/white
color = "#FFFFFF"
/obj/item/stack/tile/fairygrass/red
name = "red fairygrass tile"
singular_name = "red fairygrass floor tile"
desc = "A patch of odd, glowing red grass."
turf_type = /turf/open/floor/grass/fairy/red
color = "#FF3333"
/obj/item/stack/tile/fairygrass/yellow
name = "yellow fairygrass tile"
singular_name = "yellow fairygrass floor tile"
desc = "A patch of odd, glowing yellow grass."
turf_type = /turf/open/floor/grass/fairy/yellow
color = "#FFFF66"
/obj/item/stack/tile/fairygrass/green
name = "green fairygrass tile"
singular_name = "green fairygrass floor tile"
desc = "A patch of odd, glowing green grass."
turf_type = /turf/open/floor/grass/fairy/green
color = "#99FF99"
/obj/item/stack/tile/fairygrass/blue
name = "blue fairygrass tile"
singular_name = "blue fairygrass floor tile"
desc = "A patch of odd, glowing blue grass."
turf_type = /turf/open/floor/grass/fairy/blue
/obj/item/stack/tile/fairygrass/purple
name = "purple fairygrass tile"
singular_name = "purple fairygrass floor tile"
desc = "A patch of odd, glowing purple grass."
turf_type = /turf/open/floor/grass/fairy/purple
color = "#D966FF"
/obj/item/stack/tile/fairygrass/pink
name = "pink fairygrass tile"
singular_name = "pink fairygrass floor tile"
desc = "A patch of odd, glowing pink grass."
turf_type = /turf/open/floor/grass/fairy/pink
color = "#FFB3DA"
//Wood
/obj/item/stack/tile/wood
+1 -1
View File
@@ -253,7 +253,7 @@
/obj/item/storage/backpack/satchel/bone
name = "bone satchel"
desc = "A bone satchel fashend with watcher wings and large bones from goliath. Can be worn on the belt."
desc = "A grotesque satchel made of sinews and bones."
icon = 'icons/obj/mining.dmi'
icon_state = "goliath_saddle"
slot_flags = ITEM_SLOT_BACK
+3 -1
View File
@@ -575,7 +575,9 @@
/obj/item/clothing/gloves,
/obj/item/melee/flyswatter,
/obj/item/paint/paint_remover,
/obj/item/assembly/mousetrap
/obj/item/assembly/mousetrap,
/obj/item/screwdriver,
/obj/item/stack/cable_coil
))
/obj/item/storage/belt/bandolier
+3 -2
View File
@@ -699,6 +699,7 @@
user.changeNext_move(CLICK_CD_MELEE)
playsound(loc, "rustle", 50, 1, -5)
user.visible_message("<span class='notice'>[user] hugs \the [src].</span>","<span class='notice'>You hug \the [src].</span>")
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"hugbox", /datum/mood_event/hugbox)
/////clown box & honkbot assembly
/obj/item/storage/box/clown
@@ -883,12 +884,12 @@
else if(W.get_sharpness())
if(!contents.len)
if(item_state == "paperbag_None")
user.show_message("<span class='notice'>You cut eyeholes into [src].</span>", 1)
user.show_message("<span class='notice'>You cut eyeholes into [src].</span>", MSG_VISUAL)
new /obj/item/clothing/head/papersack(user.loc)
qdel(src)
return 0
else if(item_state == "paperbag_SmileyFace")
user.show_message("<span class='notice'>You cut eyeholes into [src] and modify the design.</span>", 1)
user.show_message("<span class='notice'>You cut eyeholes into [src] and modify the design.</span>", MSG_VISUAL)
new /obj/item/clothing/head/papersack/smiley(user.loc)
qdel(src)
return 0
+155 -13
View File
@@ -18,6 +18,12 @@
throw_speed = 3
throw_range = 7
var/empty = FALSE
var/list/possible_icons = list("firstaid","firstaid2","firstaid3","firstaid4")
/obj/item/storage/firstaid/Initialize(mapload)
. = ..()
if(LAZYLEN(possible_icons))
icon_state = pick(possible_icons)
/obj/item/storage/firstaid/regular
icon_state = "firstaid"
@@ -56,17 +62,14 @@
/obj/item/storage/firstaid/fire
name = "burn treatment kit"
desc = "A specialized medical kit for when the toxins lab <i>-spontaneously-</i> burns down."
icon_state = "ointment"
icon_state = "burn"
item_state = "firstaid-ointment"
possible_icons = list("burn","burn2","burn3","burn4")
/obj/item/storage/firstaid/fire/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins rubbing \the [src] against [user.p_them()]self! It looks like [user.p_theyre()] trying to start a fire!</span>")
return FIRELOSS
/obj/item/storage/firstaid/fire/Initialize(mapload)
. = ..()
icon_state = pick("ointment","firefirstaid")
/obj/item/storage/firstaid/fire/PopulateContents()
if(empty)
return
@@ -80,17 +83,14 @@
/obj/item/storage/firstaid/toxin
name = "toxin treatment kit"
desc = "Used to treat toxic blood content and radiation poisoning."
icon_state = "antitoxin"
icon_state = "toxin"
item_state = "firstaid-toxin"
possible_icons = list("toxin","toxin2","toxin3","toxin4")
/obj/item/storage/firstaid/toxin/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins licking the lead paint off \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return TOXLOSS
/obj/item/storage/firstaid/toxin/Initialize(mapload)
. = ..()
icon_state = pick("antitoxin","antitoxfirstaid","antitoxfirstaid2","antitoxfirstaid3")
/obj/item/storage/firstaid/toxin/PopulateContents()
if(empty)
return
@@ -103,8 +103,9 @@
/obj/item/storage/firstaid/radbgone
name = "radiation treatment kit"
desc = "Used to treat minor toxic blood content and major radiation poisoning."
icon_state = "antitoxin"
icon_state = "rad"
item_state = "firstaid-toxin"
possible_icons = list("rad","rad2","rad3")
/obj/item/storage/firstaid/radbgone/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins licking the lead paint off \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -128,8 +129,9 @@
/obj/item/storage/firstaid/o2
name = "oxygen deprivation treatment kit"
desc = "A box full of oxygen goodies."
icon_state = "o2"
icon_state = "oxy"
item_state = "firstaid-o2"
possible_icons = list("oxy", "oxy2", "oxy3", "oxy4")
/obj/item/storage/firstaid/o2/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins hitting [user.p_their()] neck with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -149,6 +151,7 @@
desc = "A first aid kit for when you get toolboxed."
icon_state = "brute"
item_state = "firstaid-brute"
possible_icons = list("brute", "brute2", "brute3", "brute4")
/obj/item/storage/firstaid/brute/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins beating [user.p_them()]self over the head with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -166,7 +169,8 @@
/obj/item/storage/firstaid/tactical
name = "combat medical kit"
desc = "I hope you've got insurance."
icon_state = "bezerk"
icon_state = "tactical"
possible_icons = null
/obj/item/storage/firstaid/tactical/ComponentInitialize()
. = ..()
@@ -389,3 +393,141 @@
/obj/item/organ_storage
))
//hijacking the minature first aids for hypospray boxes. <3
/obj/item/storage/hypospraykit
name = "hypospray kit"
desc = "It's a kit containing a hypospray and specific treatment chemical-filled vials."
icon_state = "firstaid-mini"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
throw_speed = 3
throw_range = 7
var/empty = FALSE
item_state = "firstaid"
/obj/item/storage/hypospraykit/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 12
STR.can_hold = typecacheof(list(
/obj/item/hypospray/mkii,
/obj/item/reagent_containers/glass/bottle/vial))
/obj/item/storage/hypospraykit/regular
icon_state = "firstaid-mini"
desc = "A hypospray kit with general use vials."
/obj/item/storage/hypospraykit/regular/PopulateContents()
if(empty)
return
new /obj/item/hypospray/mkii/tricord(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/tricord(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/tricord(src)
/obj/item/storage/hypospraykit/fire
name = "burn treatment hypospray kit"
desc = "A specialized hypospray kit for burn treatments. Apply with sass."
icon_state = "burn-mini"
item_state = "firstaid-ointment"
/obj/item/storage/hypospraykit/fire/PopulateContents()
if(empty)
return
new /obj/item/hypospray/mkii/burn(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/kelotane(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/kelotane(src)
/obj/item/storage/hypospraykit/toxin
name = "toxin treatment hypospray kit"
icon_state = "toxin-mini"
item_state = "firstaid-toxin"
/obj/item/storage/hypospraykit/toxin/PopulateContents()
if(empty)
return
new /obj/item/hypospray/mkii/toxin(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/antitoxin(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/antitoxin(src)
/obj/item/storage/hypospraykit/o2
name = "oxygen deprivation hypospray kit"
icon_state = "oxy-mini"
item_state = "firstaid-o2"
/obj/item/storage/hypospraykit/o2/PopulateContents()
if(empty)
return
new /obj/item/hypospray/mkii/oxygen(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/dexalin(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/dexalin(src)
/obj/item/storage/hypospraykit/enlarge
name = "organomegaly trauma hypospray kit"
icon_state = "enlarge-mini"
item_state = "firstaid-brute"
/obj/item/storage/hypospraykit/enlarge/PopulateContents()
if(empty)
return
new /obj/item/hypospray/mkii/enlarge(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/breastreduction(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/breastreduction(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/breastreduction(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/penisreduction(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/penisreduction(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/penisreduction(src)
/obj/item/storage/hypospraykit/brute
name = "brute trauma hypospray kit"
icon_state = "brute-mini"
item_state = "firstaid-brute"
/obj/item/storage/hypospraykit/brute/PopulateContents()
if(empty)
return
new /obj/item/hypospray/mkii/brute(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/bicaridine(src)
new /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/bicaridine(src)
/obj/item/storage/hypospraykit/tactical
name = "combat hypospray kit"
desc = "A hypospray kit best suited for combat situations."
icon_state = "tactical-mini"
/obj/item/storage/hypospraykit/tactical/PopulateContents()
if(empty)
return
new /obj/item/defibrillator/compact/combat/loaded(src)
new /obj/item/hypospray/mkii/CMO/combat(src)
new /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/combat(src)
new /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/combat(src)
/obj/item/storage/hypospraykit/cmo
name = "deluxe hypospray kit"
desc = "A kit containing a Deluxe hypospray and Vials."
icon_state = "tactical-mini"
/obj/item/storage/hypospraykit/cmo/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(
/obj/item/hypospray/mkii,
/obj/item/reagent_containers/glass/bottle/vial))
/obj/item/storage/hypospraykit/cmo/PopulateContents()
if(empty)
return
new /obj/item/hypospray/mkii/CMO(src)
new /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/tricord(src)
new /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/charcoal(src)
new /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/salglu(src)
new /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/dexalin(src)
new /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/synthflesh(src)
/obj/item/storage/box/vials
name = "box of hypovials"
/obj/item/storage/box/vials/PopulateContents()
for(var/i in 1 to 7)
new /obj/item/reagent_containers/glass/bottle/vial/small( src )
+9 -1
View File
@@ -37,7 +37,15 @@
/obj/item/screwdriver,
/obj/item/valentine,
/obj/item/stamp,
/obj/item/key))
/obj/item/key,
/obj/item/cartridge,
/obj/item/camera_film,
/obj/item/stack/ore/bluespace_crystal,
/obj/item/reagent_containers/food/snacks/grown/poppy,
/obj/item/instrument/harmonica,
/obj/item/mining_voucher,
/obj/item/suit_voucher,
/obj/item/reagent_containers/pill))
/obj/item/storage/wallet/Exited(atom/movable/AM)
. = ..()
+1 -1
View File
@@ -201,7 +201,7 @@
if(!current_location || current_area.noteleport || is_away_level(current_location.z) || !isturf(user.loc))//If turf was not found or they're on z level 2 or >7 which does not currently exist. or if user is not located on a turf
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
return
user.show_message("<span class='notice'>Locked In.</span>", 2)
user.show_message("<span class='notice'>Locked In.</span>", MSG_AUDIBLE)
var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), src, 300, 1, null, atmos_link_override)
if(!(LAZYLEN(created) == 2))
return
+15 -6
View File
@@ -122,12 +122,21 @@
user.put_in_active_hand(pryjaws)
/obj/item/wirecutters/power/attack(mob/living/carbon/C, mob/user)
if(istype(C) && C.handcuffed)
user.visible_message("<span class='notice'>[user] cuts [C]'s restraints with [src]!</span>")
qdel(C.handcuffed)
return
else
..()
if(istype(C))
if(C.handcuffed)
user.visible_message("<span class='notice'>[user] cuts [C]'s restraints with [src]!</span>")
qdel(C.handcuffed)
return
else if(C.has_status_effect(STATUS_EFFECT_CHOKINGSTRAND))
var/man = C == user ? "your" : "[C]'\s"
user.visible_message("<span class='notice'>[user] attempts to remove the durathread strand from around [man] neck.</span>", \
"<span class='notice'>You attempt to remove the durathread strand from around [man] neck.</span>")
if(do_after(user, 15, null, C))
user.visible_message("<span class='notice'>[user] succesfuly removes the durathread strand.</span>",
"<span class='notice'>You succesfuly remove the durathread strand.</span>")
C.remove_status_effect(STATUS_EFFECT_CHOKINGSTRAND)
return
..()
/obj/item/wirecutters/advanced
name = "advanced wirecutters"
+5 -4
View File
@@ -182,7 +182,7 @@
return
src.add_fingerprint(user)
if (src.bullets < 1)
user.show_message("<span class='warning'>*click*</span>", 2)
user.show_message("<span class='warning'>*click*</span>", MSG_AUDIBLE)
playsound(src, "gun_dry_fire", 30, 1)
return
playsound(user, 'sound/weapons/gunshot.ogg', 100, 1)
@@ -864,10 +864,9 @@
return ..()
/obj/item/toy/cards/deck/MouseDrop(atom/over_object)
. = ..()
var/mob/living/M = usr
if(!istype(M) || usr.incapacitated() || usr.lying)
return
return ..()
if(Adjacent(usr))
if(over_object == M && loc != M)
M.put_in_hands(src)
@@ -879,7 +878,9 @@
to_chat(usr, "<span class='notice'>You pick up the deck.</span>")
else
to_chat(usr, "<span class='warning'>You can't reach it from here!</span>")
. = ..()
if(!.)
to_chat(usr, "<span class='warning'>You can't reach it from here!</span>")
@@ -498,7 +498,7 @@
var/mutable_appearance/armrest
/obj/structure/chair/sofa/Initialize()
armrest = mutable_appearance(icon, "[icon_state]_armrest")
armrest = mutable_appearance(icon, "[icon_state]_armrest", ABOVE_MOB_LAYER)
return ..()
/obj/structure/chair/sofa/post_buckle_mob(mob/living/M)
@@ -9,12 +9,19 @@
if(registered_name)
. += "<span class='notice'>The display reads, \"Owned by [registered_name]\".</span>"
/obj/structure/closet/secure_closet/personal/check_access(obj/item/card/id/I)
/obj/structure/closet/secure_closet/personal/check_access(obj/item/I)
. = ..()
if(!I || !istype(I))
return
if(registered_name == I.registered_name)
if(istype(I,/obj/item/modular_computer/tablet))
var/obj/item/modular_computer/tablet/ourTablet = I
var/obj/item/computer_hardware/card_slot/card_slot = ourTablet.all_components[MC_CARD]
if(card_slot)
return registered_name == card_slot.stored_card.registered_name || registered_name == card_slot.stored_card2.registered_name
var/obj/item/card/id/ID = I.GetID()
if(ID && registered_name == ID.registered_name)
return TRUE
return FALSE
/obj/structure/closet/secure_closet/personal/PopulateContents()
..()
@@ -42,6 +49,7 @@
new /obj/item/storage/backpack/satchel/leather/withwallet( src )
new /obj/item/instrument/piano_synth(src)
new /obj/item/radio/headset( src )
new /obj/item/clothing/head/colour(src)
/obj/structure/closet/secure_closet/personal/attackby(obj/item/W, mob/user, params)
var/obj/item/card/id/I = W.GetID()
@@ -4,6 +4,8 @@
icon_state = "largebins"
open_sound = 'sound/effects/bin_open.ogg'
close_sound = 'sound/effects/bin_close.ogg'
material_drop = /obj/item/stack/sheet/plastic
material_drop_amount = 40
anchored = TRUE
horizontal = FALSE
delivery_icon = null
@@ -151,6 +151,9 @@
log_admin("[key_name(new_spawn)] possessed a golem shell enslaved to [key_name(owner)].")
if(ishuman(new_spawn))
var/mob/living/carbon/human/H = new_spawn
if(has_owner)
var/datum/species/golem/G = H.dna.species
G.owner = owner
H.set_cloned_appearance()
if(!name)
if(has_owner)
@@ -321,8 +324,9 @@
/datum/outfit/hotelstaff
name = "Hotel Staff"
uniform = /obj/item/clothing/under/assistantformal
uniform = /obj/item/clothing/under/telegram
shoes = /obj/item/clothing/shoes/laceup
head = /obj/item/clothing/head/hotel
r_pocket = /obj/item/radio/off
back = /obj/item/storage/backpack
implants = list(/obj/item/implant/mindshield)
+35 -12
View File
@@ -1,5 +1,7 @@
//Loom, turns raw cotton and durathread into their respective fabrics.
#define FABRIC_PER_SHEET 4
///This is a loom. It's usually made out of wood and used to weave fabric like durathread or cotton into their respective cloth types.
/obj/structure/loom
name = "loom"
desc = "A simple device used to weave cloth and other thread-based fabrics together into usable material."
@@ -8,14 +10,35 @@
density = TRUE
anchored = TRUE
/obj/structure/loom/attackby(obj/item/stack/sheet/W, mob/user)
if(W.is_fabric && W.amount > 1)
user.show_message("<span class='notice'>You start weaving the [W.name] through the loom..</span>", 1)
if(W.use_tool(src, user, W.pull_effort))
new W.loom_result(drop_location())
user.show_message("<span class='notice'>You weave the [W.name] into a workable fabric.</span>", 1)
W.amount = (W.amount - 2)
if(W.amount < 1)
qdel(W)
else
user.show_message("<span class='notice'>You need a valid fabric and at least 2 of said fabric before using this.</span>", 1)
/obj/structure/loom/attackby(obj/item/I, mob/user)
if(weave(I, user))
return
return ..()
/obj/structure/loom/wrench_act(mob/living/user, obj/item/I)
..()
default_unfasten_wrench(user, I, 5)
return TRUE
///Handles the weaving.
/obj/structure/loom/proc/weave(obj/item/stack/sheet/S, mob/user)
if(!istype(S) || !S.is_fabric)
return FALSE
if(!anchored)
user.show_message("<span class='notice'>The loom needs to be wrenched down.</span>", MSG_VISUAL)
return FALSE
if(S.amount < FABRIC_PER_SHEET)
user.show_message("<span class='notice'>You need at least [FABRIC_PER_SHEET] units of fabric before using this.</span>", 1)
return FALSE
user.show_message("<span class='notice'>You start weaving \the [S.name] through the loom..</span>", MSG_VISUAL)
if(S.use_tool(src, user, S.pull_effort))
if(S.amount >= FABRIC_PER_SHEET)
new S.loom_result(drop_location())
S.use(FABRIC_PER_SHEET)
user.show_message("<span class='notice'>You weave \the [S.name] into a workable fabric.</span>", MSG_VISUAL)
return TRUE
/obj/structure/loom/unanchored
anchored = FALSE
#undef FABRIC_PER_SHEET
@@ -15,6 +15,15 @@
var/flipped_build_type
var/base_icon
/obj/structure/c_transit_tube/proc/can_wrench_in_loc(mob/user)
var/turf/source_turf = get_turf(loc)
var/existing_tubes = 0
for(var/obj/structure/transit_tube/tube in source_turf)
existing_tubes++
if(existing_tubes >= 2)
to_chat(user, "<span class='warning'>You cannot wrench any more transit tubes!</span>")
return FALSE
return TRUE
/obj/structure/c_transit_tube/ComponentInitialize()
. = ..()
@@ -32,9 +41,11 @@
icon_state = "[base_icon][flipped]"
/obj/structure/c_transit_tube/wrench_act(mob/living/user, obj/item/I)
if(!can_wrench_in_loc(user))
return
to_chat(user, "<span class='notice'>You start attaching the [name]...</span>")
add_fingerprint(user)
if(I.use_tool(src, user, time_to_unwrench, volume=50))
if(I.use_tool(src, user, time_to_unwrench, volume=50, extra_checks=CALLBACK(src, .proc/can_wrench_in_loc, user)))
to_chat(user, "<span class='notice'>You attach the [name].</span>")
var/obj/structure/transit_tube/R = new build_type(loc, dir)
transfer_fingerprints_to(R)
@@ -104,6 +104,47 @@
light_range = 2
light_power = 0.80
light_color = "#33CCFF"
color = "#33CCFF"
/turf/open/floor/grass/fairy/white
name = "white fairygrass patch"
light_color = "#FFFFFF"
color = "#FFFFFF"
floor_tile = /obj/item/stack/tile/fairygrass/white
/turf/open/floor/grass/fairy/red
name = "red fairygrass patch"
light_color = "#FF3333"
color = "#FF3333"
floor_tile = /obj/item/stack/tile/fairygrass/red
/turf/open/floor/grass/fairy/yellow
name = "yellow fairygrass patch"
light_color = "#FFFF66"
color = "#FFFF66"
floor_tile = /obj/item/stack/tile/fairygrass/yellow
/turf/open/floor/grass/fairy/green
name = "green fairygrass patch"
light_color = "#99FF99"
color = "#99FF99"
floor_tile = /obj/item/stack/tile/fairygrass/green
/turf/open/floor/grass/fairy/blue
name = "blue fairygrass patch"
floor_tile = /obj/item/stack/tile/fairygrass/blue
/turf/open/floor/grass/fairy/purple
name = "purple fairygrass patch"
light_color = "#D966FF"
color = "#D966FF"
floor_tile = /obj/item/stack/tile/fairygrass/purple
/turf/open/floor/grass/fairy/pink
name = "pink fairygrass patch"
light_color = "#FFB3DA"
color = "#FFB3DA"
floor_tile = /obj/item/stack/tile/fairygrass/pink
/turf/open/floor/grass/snow
gender = PLURAL
+2
View File
@@ -27,6 +27,8 @@
/turf/open/space/Initialize()
icon_state = SPACE_ICON_STATE
air = space_gas
vis_contents.Cut() //removes inherited overlays
visibilityChanged()
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
+27 -3
View File
@@ -720,20 +720,44 @@
if(!check_rights(R_SPAWN))
return
var/turf/T = get_turf(usr)
var/chosen = pick_closest_path(object)
if(!chosen)
return
if(ispath(chosen, /turf))
var/turf/T = get_turf(usr.loc)
T.ChangeTurf(chosen)
else
var/atom/A = new chosen(usr.loc)
var/atom/A = new chosen(T)
A.flags_1 |= ADMIN_SPAWNED_1
log_admin("[key_name(usr)] spawned [chosen] at [AREACOORD(usr)]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Spawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/podspawn_atom(object as text)
set category = "Debug"
set desc = "(atom path) Spawn an atom via supply drop"
set name = "Podspawn"
if(!check_rights(R_SPAWN))
return
var/chosen = pick_closest_path(object)
if(!chosen)
return
var/turf/T = get_turf(usr)
if(ispath(chosen, /turf))
T.ChangeTurf(chosen)
else
var/obj/structure/closet/supplypod/centcompod/pod = new()
var/atom/A = new chosen(pod)
A.flags_1 |= ADMIN_SPAWNED_1
new /obj/effect/abstract/DPtarget(T, pod)
log_admin("[key_name(usr)] pod-spawned [chosen] at [AREACOORD(usr)]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Podspawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/spawn_cargo(object as text)
set category = "Debug"
set desc = "(atom path) Spawn a cargo crate"
@@ -875,7 +899,7 @@
/datum/admins/proc/dynamic_mode_options(mob/user)
var/dat = {"
<center><B><h2>Dynamic Mode Options</h2></B></center><hr>
<br/>
<br/>
<h3>Common options</h3>
<i>All these options can be changed midround.</i> <br/>
<br/>
+1 -1
View File
@@ -108,7 +108,7 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list(
/client/proc/roll_dices //CIT CHANGE - Adds dice verb
))
GLOBAL_PROTECT(admin_verbs_fun)
GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom, /datum/admins/proc/spawn_cargo, /datum/admins/proc/spawn_objasmob, /client/proc/respawn_character))
GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom, /datum/admins/proc/podspawn_atom, /datum/admins/proc/spawn_cargo, /datum/admins/proc/spawn_objasmob, /client/proc/respawn_character))
GLOBAL_PROTECT(admin_verbs_spawn)
GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer())
/world/proc/AVerbsServer()
+12 -3
View File
@@ -2355,7 +2355,7 @@
var/atom/target //Where the object will be spawned
var/where = href_list["object_where"]
if (!( where in list("onfloor","inhand","inmarked") ))
if (!( where in list("onfloor","frompod","inhand","inmarked") ))
where = "onfloor"
@@ -2366,7 +2366,7 @@
where = "onfloor"
target = usr
if("onfloor")
if("onfloor", "frompod")
switch(href_list["offset_type"])
if ("absolute")
target = locate(0 + X,0 + Y,0 + Z)
@@ -2382,7 +2382,10 @@
else
target = marked_datum
var/obj/structure/closet/supplypod/centcompod/pod
if(target)
if(where == "frompod")
pod = new()
for (var/path in paths)
for (var/i = 0; i < number; i++)
if(path in typesof(/turf))
@@ -2391,7 +2394,11 @@
if(N && obj_name)
N.name = obj_name
else
var/atom/O = new path(target)
var/atom/O
if(where == "frompod")
O = new path(pod)
else
O = new path(target)
if(!QDELETED(O))
O.flags_1 |= ADMIN_SPAWNED_1
if(obj_dir)
@@ -2411,6 +2418,8 @@
R.module.add_module(I, TRUE, TRUE)
R.activate_module(I)
if(pod)
new /obj/effect/abstract/DPtarget(target, pod)
if (number == 1)
log_admin("[key_name(usr)] created a [english_list(paths)]")
+24 -5
View File
@@ -1249,7 +1249,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
if(!check_rights(R_ADMIN) || !check_rights(R_FUN))
return
var/list/punishment_list = list(ADMIN_PUNISHMENT_PIE, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING, ADMIN_PUNISHMENT_ROD)
var/list/punishment_list = list(ADMIN_PUNISHMENT_PIE, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_SUPPLYPOD_QUICK, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING, ADMIN_PUNISHMENT_ROD)
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
@@ -1277,6 +1277,22 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
var/turf/startT = spaceDebrisStartLoc(startside, T.z)
var/turf/endT = spaceDebrisFinishLoc(startside, T.z)
new /obj/effect/immovablerod(startT, endT,target)
if(ADMIN_PUNISHMENT_SUPPLYPOD_QUICK)
var/target_path = input(usr,"Enter typepath of an atom you'd like to send with the pod (type \"empty\" to send an empty pod):" ,"Typepath","/obj/item/reagent_containers/food/snacks/grown/harebell") as null|text
var/obj/structure/closet/supplypod/centcompod/pod = new()
pod.damage = 40
pod.explosionSize = list(0,0,0,2)
pod.effectStun = TRUE
if (isnull(target_path)) //The user pressed "Cancel"
return
if (target_path != "empty")//if you didn't type empty, we want to load the pod with a delivery
var/delivery = text2path(target_path)
if(!ispath(delivery))
delivery = pick_closest_path(target_path)
if(!delivery)
alert("ERROR: Incorrect / improper path given.")
new delivery(pod)
new /obj/effect/abstract/DPtarget(get_turf(target), pod)
if(ADMIN_PUNISHMENT_SUPPLYPOD)
var/datum/centcom_podlauncher/plaunch = new(usr)
if(!holder)
@@ -1289,6 +1305,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
plaunch.temp_pod.explosionSize = list(0,0,0,2)
plaunch.temp_pod.effectStun = TRUE
plaunch.ui_interact(usr)
return //We return here because punish_log() is handled by the centcom_podlauncher datum
if(ADMIN_PUNISHMENT_MAZING)
if(!puzzle_imprison(target))
@@ -1298,11 +1315,13 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target))
creamy.splat(target)
var/msg = "[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment]."
message_admins(msg)
admin_ticket_log(target, msg)
log_admin("[key_name(usr)] punished [key_name(target)] with [punishment].")
punish_log(target, punishment)
/client/proc/punish_log(var/whom, var/punishment)
var/msg = "[key_name_admin(usr)] punished [key_name_admin(whom)] with [punishment]."
message_admins(msg)
admin_ticket_log(whom, msg)
log_admin("[key_name(usr)] punished [key_name(whom)] with [punishment].")
/client/proc/trigger_centcom_recall()
if(!check_rights(R_ADMIN))
@@ -244,6 +244,7 @@
return ..()
/obj/structure/blob/proc/chemeffectreport()
RETURN_TYPE(/list)
. = list()
if(overmind)
. += "<b>Material: <font color=\"[overmind.blob_reagent_datum.color]\">[overmind.blob_reagent_datum.name]</font><span class='notice'>.</span></b>"
@@ -253,6 +254,7 @@
. += "<b>No Material Detected!</b><br>"
/obj/structure/blob/proc/typereport()
RETURN_TYPE(/list)
. = list("<b>Blob Type:</b> <span class='notice'>[uppertext(initial(name))]</span>")
. += "<b>Health:</b> <span class='notice'>[obj_integrity]/[max_integrity]</span>"
. += "<b>Effects:</b> <span class='notice'>[scannerreport()]</span>"
@@ -48,18 +48,17 @@
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
A.malf_picker.remove_malf_verbs(A)
qdel(A.malf_picker)
/datum/antagonist/traitor/proc/handle_hearing(datum/source, list/hearing_args)
var/message = hearing_args[HEARING_MESSAGE]
message = GLOB.syndicate_code_phrase_regex.Replace(message, "<span class='blue'>$1</span>")
message = GLOB.syndicate_code_response_regex.Replace(message, "<span class='red'>$1</span>")
hearing_args[HEARING_MESSAGE] = message
SSticker.mode.traitors -= owner
if(!silent && owner.current)
to_chat(owner.current,"<span class='userdanger'> You are no longer the [special_role]! </span>")
owner.special_role = null
..()
. = ..()
/datum/antagonist/traitor/proc/handle_hearing(datum/source, list/hearing_args)
var/message = hearing_args[HEARING_RAW_MESSAGE]
message = GLOB.syndicate_code_phrase_regex.Replace(message, "<span class='blue'>$1</span>")
message = GLOB.syndicate_code_response_regex.Replace(message, "<span class='red'>$1</span>")
hearing_args[HEARING_RAW_MESSAGE] = message
/datum/antagonist/traitor/proc/add_objective(datum/objective/O)
objectives += O
@@ -261,16 +260,20 @@
/datum/antagonist/traitor/apply_innate_effects(mob/living/mob_override)
. = ..()
update_traitor_icons_added()
var/mob/living/silicon/ai/A = mob_override || owner.current
if(istype(A) && traitor_kind == TRAITOR_AI)
var/mob/M = mob_override || owner.current
if(isAI(M) && traitor_kind == TRAITOR_AI)
var/mob/living/silicon/ai/A = M
A.hack_software = TRUE
RegisterSignal(M, COMSIG_MOVABLE_HEAR, .proc/handle_hearing)
/datum/antagonist/traitor/remove_innate_effects(mob/living/mob_override)
. = ..()
update_traitor_icons_removed()
var/mob/living/silicon/ai/A = mob_override || owner.current
if(istype(A) && traitor_kind == TRAITOR_AI)
var/mob/M = mob_override || owner.current
if(isAI(M) && traitor_kind == TRAITOR_AI)
var/mob/living/silicon/ai/A = M
A.hack_software = FALSE
UnregisterSignal(M, COMSIG_MOVABLE_HEAR)
/datum/antagonist/traitor/proc/give_codewords()
if(!owner.current)
@@ -72,11 +72,13 @@
air.copy_from(copy)
/turf/return_air()
RETURN_TYPE(/datum/gas_mixture)
var/datum/gas_mixture/GM = new
GM.copy_from_turf(src)
return GM
/turf/open/return_air()
RETURN_TYPE(/datum/gas_mixture)
return air
/turf/temperature_expose()
@@ -4,7 +4,7 @@
desc = "Very useful for filtering gasses."
density = FALSE
can_unwrench = TRUE
var/target_pressure = ONE_ATMOSPHERE
var/transfer_rate = MAX_TRANSFER_RATE
var/filter_type = null
var/frequency = 0
var/datum/radio_frequency/radio_connection
@@ -15,7 +15,7 @@
/obj/machinery/atmospherics/components/trinary/filter/examine(mob/user)
. = ..()
. += "<span class='notice'>You can hold <b>Ctrl</b> and click on it to toggle it on and off.</span>"
. += "<span class='notice'>You can hold <b>Alt</b> and click on it to maximize its pressure.</span>"
. += "<span class='notice'>You can hold <b>Alt</b> and click on it to maximize its flow rate.</span>"
/obj/machinery/atmospherics/components/trinary/filter/CtrlClick(mob/user)
var/area/A = get_area(src)
@@ -31,8 +31,8 @@
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
target_pressure = MAX_OUTPUT_PRESSURE
to_chat(user,"<span class='notice'>You maximize the pressure on the [src].</span>")
transfer_rate = MAX_TRANSFER_RATE
to_chat(user,"<span class='notice'>You maximize the flow rate on the [src].</span>")
investigate_log("Filter, [src.name], was maximized by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Filter, [src.name], was maximized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
@@ -150,24 +150,19 @@
var/datum/gas_mixture/air2 = airs[2]
var/datum/gas_mixture/air3 = airs[3]
var/output_starting_pressure = air3.return_pressure()
var/input_starting_pressure = air1.return_pressure()
if(output_starting_pressure >= target_pressure)
//No need to transfer if target is already full!
if((input_starting_pressure < 0.01))
return
//Calculate necessary moles to transfer using PV=nRT
var/pressure_delta = target_pressure - output_starting_pressure
var/transfer_moles
if(air1.temperature > 0)
transfer_moles = pressure_delta*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
var/transfer_ratio = transfer_rate/air1.volume
//Actually transfer the gas
if(transfer_moles > 0)
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
if(transfer_ratio > 0)
var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio)
if(!removed)
return
@@ -188,10 +183,13 @@
removed.gases[filter_type] = 0
GAS_GARBAGE_COLLECT(removed.gases)
var/datum/gas_mixture/target = (air2.return_pressure() < target_pressure ? air2 : air1) //if there's no room for the filtered gas; just leave it in air1
var/datum/gas_mixture/target = (air2.return_pressure() < 9000 ? air2 : air1)
target.merge(filtered_out)
air3.merge(removed)
if(air3.return_pressure() <= 9000)
air3.merge(removed)
else
air1.merge(removed) // essentially just leaving it in
update_parents()
@@ -209,8 +207,8 @@
/obj/machinery/atmospherics/components/trinary/filter/ui_data()
var/data = list()
data["on"] = on
data["pressure"] = round(target_pressure)
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
data["rate"] = round(transfer_rate)
data["max_rate"] = round(MAX_TRANSFER_RATE)
data["filter_types"] = list()
data["filter_types"] += list(list("name" = "Nothing", "path" = "", "selected" = !filter_type))
@@ -227,21 +225,21 @@
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", INVESTIGATE_ATMOS)
. = TRUE
if("pressure")
var/pressure = params["pressure"]
if(pressure == "max")
pressure = MAX_OUTPUT_PRESSURE
if("rate")
var/rate = params["rate"]
if(rate == "max")
rate = MAX_TRANSFER_RATE
. = TRUE
else if(pressure == "input")
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
if(!isnull(pressure) && !..())
else if(rate == "input")
rate = input("New transfer rate (0-[MAX_TRANSFER_RATE] L/s):", name, transfer_rate) as num|null
if(!isnull(rate) && !..())
. = TRUE
else if(text2num(pressure) != null)
pressure = text2num(pressure)
else if(text2num(rate) != null)
rate = text2num(rate)
. = TRUE
if(.)
target_pressure = CLAMP(pressure, 0, MAX_OUTPUT_PRESSURE)
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS)
transfer_rate = CLAMP(rate, 0, MAX_TRANSFER_RATE)
investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", INVESTIGATE_ATMOS)
if("filter")
filter_type = null
var/filter_name = "nothing"
+3 -3
View File
@@ -201,10 +201,10 @@
wanted_types = list(/obj/item/restraints/legcuffs/bola)
/datum/bounty/item/assistant/metalshields
name = "Metal Shields"
name = "Metal Shields" //I didnt realise how much work it was to make these, you need 2 Cloth, 3 Leather, Tools, 10 Metal, and a Cable Coil Stack for each one.
description = "NT is testing the effects of electricity on clowns wielding metal shields. We have clowns, and we have electricity. Send us the shields."
reward = 1400
required_count = 4
reward = 3000
required_count = 2
wanted_types = list(/obj/item/shield/makeshift)
/datum/bounty/item/assistant/toolbelts
+98 -20
View File
@@ -19,7 +19,7 @@
//Variables declared to change how items in the launch bay are picked and launched. (Almost) all of these are changed in the ui_act proc
//Some effect groups are choices, while other are booleans. This is because some effects can stack, while others dont (ex: you can stack explosion and quiet, but you cant stack ordered launch and random launch)
/datum/centcom_podlauncher
var/static/list/ignored_atoms = typecacheof(list(null, /mob/dead, /obj/effect/landmark, /obj/docking_port, /atom/movable/lighting_object, /obj/effect/particle_effect/sparks, /obj/effect/DPtarget, /obj/effect/supplypod_selector ))
var/static/list/ignored_atoms = typecacheof(list(null, /mob/dead, /obj/effect/landmark, /obj/docking_port, /atom/movable/lighting_object, /obj/effect/particle_effect/sparks, /obj/effect/abstract/DPtarget, /obj/effect/supplypod_selector ))
var/turf/oldTurf //Keeps track of where the user was at if they use the "teleport to centcom" button, so they can go back
var/client/holder //client of whoever is using this datum
var/area/bay //What bay we're using to launch shit from.
@@ -29,9 +29,10 @@
var/damageChoice = 0 //Determines if we do no damage (0), custom amnt of damage (1), or gib + 5000dmg (2)
var/launcherActivated = FALSE //check if we've entered "launch mode" (when we click a pod is launched). Used for updating mouse cursor
var/effectBurst = FALSE //Effect that launches 5 at once in a 3x3 area centered on the target
var/effectAnnounce = TRUE
var/numTurfs = 0 //Counts the number of turfs with things we can launch in the chosen bay (in the centcom map)
var/launchCounter = 1 //Used with the "Ordered" launch mode (launchChoice = 1) to see what item is launched
var/specificTarget //Do we want to target a specific mob instead of where we click? Also used for smiting
var/atom/specificTarget //Do we want to target a specific mob instead of where we click? Also used for smiting
var/list/orderedArea = list() //Contains an ordered list of turfs in an area (filled in the createOrderedArea() proc), read top-left to bottom-right. Used for the "ordered" launch mode (launchChoice = 1)
var/list/turf/acceptableTurfs = list() //Contians a list of turfs (in the "bay" area on centcom) that have items that can be launched. Taken from orderedArea
var/list/launchList = list() //Contains whatever is going to be put in the supplypod and fired. Taken from acceptableTurfs
@@ -66,12 +67,14 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
data["launchChoice"] = launchChoice //Launch turfs all at once (0), ordered (1), or randomly(1)
data["explosionChoice"] = explosionChoice //An explosion that occurs when landing. Can be no explosion (0), custom explosion (1), or maxcap (2)
data["damageChoice"] = damageChoice //Damage that occurs to any mob under the pod when it lands. Can be no damage (0), custom damage (1), or gib+5000dmg (2)
data["fallDuration"] = temp_pod.fallDuration //How long the pod's falling animation lasts
data["landingDelay"] = temp_pod.landingDelay //How long the pod takes to land after launching
data["openingDelay"] = temp_pod.openingDelay //How long the pod takes to open after landing
data["departureDelay"] = temp_pod.departureDelay //How long the pod takes to leave after opening (if bluespace=true, it deletes. if reversing=true, it flies back to centcom)
data["styleChoice"] = temp_pod.style //Style is a variable that keeps track of what the pod is supposed to look like. It acts as an index to the POD_STYLES list in cargo.dm defines to get the proper icon/name/desc for the pod.
data["effectStun"] = temp_pod.effectStun //If true, stuns anyone under the pod when it launches until it lands, forcing them to get hit by the pod. Devilish!
data["effectLimb"] = temp_pod.effectLimb //If true, pops off a limb (if applicable) from anyone caught under the pod when it lands
data["effectOrgans"] = temp_pod.effectOrgans //If true, yeets the organs out of any bodies caught under the pod when it lands
data["effectBluespace"] = temp_pod.bluespace //If true, the pod deletes (in a shower of sparks) after landing
data["effectStealth"] = temp_pod.effectStealth //If true, a target icon isnt displayed on the turf where the pod will land
data["effectQuiet"] = temp_pod.effectQuiet //The female sniper. If true, the pod makes no noise (including related explosions, opening sounds, etc)
@@ -81,12 +84,14 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
data["effectReverse"] = temp_pod.reversing //If true, the pod will not send any items. Instead, after opening, it will close again (picking up items/mobs) and fly back to centcom
data["effectTarget"] = specificTarget //Launches the pod at the turf of a specific mob target, rather than wherever the user clicked. Useful for smites
data["effectName"] = temp_pod.adminNamed //Determines whether or not the pod has been named by an admin. If true, the pod's name will not get overridden when the style of the pod changes (changing the style of the pod normally also changes the name+desc)
data["effectAnnounce"] = effectAnnounce
data["giveLauncher"] = launcherActivated //If true, the user is in launch mode, and whenever they click a pod will be launched (either at their mouse position or at a specific target)
data["numObjects"] = numTurfs //Counts the number of turfs that contain a launchable object in the centcom supplypod bay
data["fallingSound"] = temp_pod.fallingSound != initial(temp_pod.fallingSound)//Admin sound to play as the pod falls
data["landingSound"] = temp_pod.landingSound //Admin sound to play when the pod lands
data["openingSound"] = temp_pod.openingSound //Admin sound to play when the pod opens
data["leavingSound"] = temp_pod.leavingSound //Admin sound to play when the pod leaves
data["soundVolume"] = temp_pod.soundVolume != 50 //Admin sound to play when the pod leaves
data["soundVolume"] = temp_pod.soundVolume != initial(temp_pod.soundVolume) //Admin sound to play when the pod leaves
return data
/datum/centcom_podlauncher/ui_act(action, params)
@@ -227,6 +232,9 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if("effectLimb") //Toggle: Anyone carbon mob under the pod loses a limb when it lands
temp_pod.effectLimb = !temp_pod.effectLimb
. = TRUE
if("effectOrgans") //Toggle: Any carbon mob under the pod loses every limb and organ
temp_pod.effectOrgans = !temp_pod.effectOrgans
. = TRUE
if("effectBluespace") //Toggle: Deletes the pod after landing
temp_pod.bluespace = !temp_pod.bluespace
. = TRUE
@@ -245,6 +253,9 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if("effectBurst") //Toggle: Launch 5 pods (with a very slight delay between) in a 3x3 area centered around the target
effectBurst = !effectBurst
. = TRUE
if("effectAnnounce") //Toggle: Sends a ghost announcement.
effectAnnounce = !effectAnnounce
. = TRUE
if("effectReverse") //Toggle: Don't send any items. Instead, after landing, close (taking any objects inside) and go back to the centcom bay it came from
temp_pod.reversing = !temp_pod.reversing
. = TRUE
@@ -261,11 +272,23 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
. = TRUE
////////////////////////////TIMER DELAYS//////////////////
if("fallDuration") //Change the falling animation duration
if (temp_pod.fallDuration != initial(temp_pod.fallDuration)) //If the fall duration has already been changed when we push the "change value" button, then set it to default
temp_pod.fallDuration = initial(temp_pod.fallDuration)
return
var/timeInput = input("Enter the duration of the pod's falling animation, in seconds", "Delay Time", initial(temp_pod.fallDuration) * 0.1) as null|num
if (isnull(timeInput))
return
if (!isnum(timeInput)) //Sanitize input, if it doesnt check out, error and set to default
alert(usr, "That wasnt a number! Value set to default ([initial(temp_pod.fallDuration)*0.1]) instead.")
timeInput = initial(temp_pod.fallDuration)
temp_pod.fallDuration = 10 * timeInput
. = TRUE
if("landingDelay") //Change the time it takes the pod to land, after firing
if (temp_pod.landingDelay != initial(temp_pod.landingDelay)) //If the landing delay has already been changed when we push the "change value" button, then set it to default
temp_pod.landingDelay = initial(temp_pod.landingDelay)
return
var/timeInput = input("Delay Time", "Enter the time it takes for the pod to land, in seconds", 0.5) as null|num
var/timeInput = input("Enter the time it takes for the pod to land, in seconds", "Delay Time", initial(temp_pod.landingDelay) * 0.1) as null|num
if (isnull(timeInput))
return
if (!isnum(timeInput)) //Sanitize input, if it doesnt check out, error and set to default
@@ -277,7 +300,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if (temp_pod.openingDelay != initial(temp_pod.openingDelay)) //If the opening delay has already been changed when we push the "change value" button, then set it to default
temp_pod.openingDelay = initial(temp_pod.openingDelay)
return
var/timeInput = input("Delay Time", "Enter the time it takes for the pod to open after landing, in seconds", 3) as null|num
var/timeInput = input("Enter the time it takes for the pod to open after landing, in seconds", "Delay Time", initial(temp_pod.openingDelay) * 0.1) as null|num
if (isnull(timeInput))
return
if (!isnum(timeInput)) //Sanitize input
@@ -289,7 +312,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if (temp_pod.departureDelay != initial(temp_pod.departureDelay)) //If the departure delay has already been changed when we push the "change value" button, then set it to default
temp_pod.departureDelay = initial(temp_pod.departureDelay)
return
var/timeInput = input("Delay Time", "Enter the time it takes for the pod to leave after opening, in seconds", 3) as null|num
var/timeInput = input("Enter the time it takes for the pod to leave after opening, in seconds", "Delay Time", initial(temp_pod.departureDelay) * 0.1) as null|num
if (isnull(timeInput))
return
if (!isnum(timeInput))
@@ -299,31 +322,57 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
. = TRUE
////////////////////////////ADMIN SOUNDS//////////////////
if("fallingSound") //Admin sound from a local file that plays when the pod falls
if ((temp_pod.fallingSound) != initial(temp_pod.fallingSound))
temp_pod.fallingSound = initial(temp_pod.fallingSound)
temp_pod.fallingSoundLength = initial(temp_pod.fallingSoundLength)
return
var/soundInput = input(holder, "Please pick a sound file to play when the pod lands! NOTICE: Take a note of exactly how long the sound is.", "Pick a Sound File") as null|sound
if (isnull(soundInput))
return
var/timeInput = input(holder, "What is the exact length of the sound file, in seconds. This number will be used to line the sound up so that it finishes right as the pod lands!", "Pick a Sound File", 0.3) as null|num
if (isnull(timeInput))
return
if (!isnum(timeInput))
alert(usr, "That wasnt a number! Value set to default ([initial(temp_pod.fallingSoundLength)*0.1]) instead.")
temp_pod.fallingSound = soundInput
temp_pod.fallingSoundLength = 10 * timeInput
. = TRUE
if("landingSound") //Admin sound from a local file that plays when the pod lands
if (!isnull(temp_pod.landingSound))
temp_pod.landingSound = null
return
temp_pod.landingSound = input(holder, "Please pick a sound file to play when the pod lands! I reccomend a nice \"oh shit, i'm sorry\", incase you hit someone with the pod.", "Pick a Sound File") as null|sound
var/soundInput = input(holder, "Please pick a sound file to play when the pod lands! I reccomend a nice \"oh shit, i'm sorry\", incase you hit someone with the pod.", "Pick a Sound File") as null|sound
if (isnull(soundInput))
return
temp_pod.landingSound = soundInput
. = TRUE
if("openingSound") //Admin sound from a local file that plays when the pod opens
if (!isnull(temp_pod.openingSound))
temp_pod.openingSound = null
return
temp_pod.openingSound = input(holder, "Please pick a sound file to play when the pod opens! I reccomend a stock sound effect of kids cheering at a party, incase your pod is full of fun exciting stuff!", "Pick a Sound File") as null|sound
var/soundInput = input(holder, "Please pick a sound file to play when the pod opens! I reccomend a stock sound effect of kids cheering at a party, incase your pod is full of fun exciting stuff!", "Pick a Sound File") as null|sound
if (isnull(soundInput))
return
temp_pod.openingSound = soundInput
. = TRUE
if("leavingSound") //Admin sound from a local file that plays when the pod leaves
if (!isnull(temp_pod.leavingSound))
temp_pod.leavingSound = null
return
temp_pod.leavingSound = input(holder, "Please pick a sound file to play when the pod leaves! I reccomend a nice slide whistle sound, especially if you're using the reverse pod effect.", "Pick a Sound File") as null|sound
var/soundInput = input(holder, "Please pick a sound file to play when the pod leaves! I reccomend a nice slide whistle sound, especially if you're using the reverse pod effect.", "Pick a Sound File") as null|sound
if (isnull(soundInput))
return
temp_pod.leavingSound = soundInput
. = TRUE
if("soundVolume") //Admin sound from a local file that plays when the pod leaves
if (temp_pod.soundVolume != 50)
temp_pod.soundVolume = 50
if (temp_pod.soundVolume != initial(temp_pod.soundVolume))
temp_pod.soundVolume = initial(temp_pod.soundVolume)
return
temp_pod.soundVolume = input(holder, "Please pick a volume. Default is between 1 and 100 with 50 being average, but pick whatever. I'm a notification, not a cop. If you still cant hear your sound, consider turning on the Quiet effect. It will silence all pod sounds except for the custom admin ones set by the previous three buttons.", "Pick Admin Sound Volume") as null|num
if (isnull(temp_pod.soundVolume))
temp_pod.soundVolume = 50
var/soundInput = input(holder, "Please pick a volume. Default is between 1 and 100 with 80 being average, but pick whatever. I'm a notification, not a cop. If you still cant hear your sound, consider turning on the Quiet effect. It will silence all pod sounds except for the custom admin ones set by the previous three buttons.", "Pick Admin Sound Volume") as null|num
if (isnull(soundInput))
return
temp_pod.soundVolume = soundInput
. = TRUE
////////////////////////////STYLE CHANGES//////////////////
//Style is a value that is used to keep track of what the pod is supposed to look like. It can be used with the POD_STYLES list (in cargo.dm defines)
@@ -364,6 +413,9 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if("styleGondola")
temp_pod.setStyle(STYLE_GONDOLA)
. = TRUE
if("styleSeeThrough")
temp_pod.setStyle(STYLE_SEETHROUGH)
. = TRUE
if("refresh") //Refresh the Pod bay. User should press this if they spawn something new in the centcom bay. Automatically called whenever the user launches a pod
refreshBay()
. = TRUE
@@ -403,12 +455,17 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if(left_click) //When we left click:
preLaunch() //Fill the acceptableTurfs list from the orderedArea list. Then, fill up the launchList list with items from the acceptableTurfs list based on the manner of launch (ordered, random, etc)
if (!isnull(specificTarget))
target = get_turf(specificTarget) //if we have a specific mob target, then always launch the pod at the turf of the mob
target = get_turf(specificTarget) //if we have a specific target, then always launch the pod at the turf of the target
else if (target)
target = get_turf(target) //Make sure we're aiming at a turf rather than an item or effect or something
else
return //if target is null and we don't have a specific target, cancel
if (effectAnnounce)
deadchat_broadcast("<span class='deadsay'>A special package is being launched at the station!</span>", turf_target = target)
var/list/bouttaDie = list()
for (var/mob/living/M in target)
bouttaDie.Add(M)
supplypod_punish_log(bouttaDie)
if (!effectBurst) //If we're not using burst mode, just launch normally.
launch(target)
else
@@ -422,7 +479,6 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
else
launch(target) //If we couldn't locate an adjacent turf, just launch at the normal target
sleep(rand()*2) //looks cooler than them all appearing at once. Gives the impression of burst fire.
log_admin("Centcom Supplypod Launch: [key_name(user)] launched a supplypod in [AREACOORD(target)]")
/datum/centcom_podlauncher/proc/refreshBay() //Called whenever the bay is switched, as well as wheneber a pod is launched
orderedArea = createOrderedArea(bay) //Create an ordered list full of turfs form the bay
@@ -486,11 +542,11 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
if (launchClone) //We arent launching the actual items from the bay, rather we are creating clones and launching those
for (var/atom/movable/O in launchList)
DuplicateObject(O).forceMove(toLaunch) //Duplicate each atom/movable in launchList and forceMove them into the supplypod
new /obj/effect/DPtarget(A, toLaunch) //Create the DPTarget, which will eventually forceMove the temp_pod to it's location
new /obj/effect/abstract/DPtarget(A, toLaunch) //Create the DPTarget, which will eventually forceMove the temp_pod to it's location
else
for (var/atom/movable/O in launchList) //If we aren't cloning the objects, just go through the launchList
O.forceMove(toLaunch) //and forceMove any atom/moveable into the supplypod
new /obj/effect/DPtarget(A, toLaunch) //Then, create the DPTarget effect, which will eventually forceMove the temp_pod to it's location
new /obj/effect/abstract/DPtarget(A, toLaunch) //Then, create the DPTarget effect, which will eventually forceMove the temp_pod to it's location
if (launchClone)
launchCounter++ //We only need to increment launchCounter if we are cloning objects.
//If we aren't cloning objects, taking and removing the first item each time from the acceptableTurfs list will inherently iterate through the list in order
@@ -508,4 +564,26 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm
updateCursor(FALSE) //Make sure our moues cursor resets to default. False means we are not in launch mode
qdel(temp_pod) //Delete the temp_pod
qdel(selector) //Delete the selector effect
. = ..()
. = ..()
/datum/centcom_podlauncher/proc/supplypod_punish_log(var/list/whoDyin)
var/podString = effectBurst ? "5 pods" : "a pod"
var/whomString = ""
if (LAZYLEN(whoDyin))
for (var/mob/living/M in whoDyin)
whomString += "[key_name(M)], "
var/delayString = temp_pod.landingDelay == initial(temp_pod.landingDelay) ? "" : " Delay=[temp_pod.landingDelay*0.1]s"
var/damageString = temp_pod.damage == 0 ? "" : " Dmg=[temp_pod.damage]"
var/explosionString = ""
var/explosion_sum = temp_pod.explosionSize[1] + temp_pod.explosionSize[2] + temp_pod.explosionSize[3] + temp_pod.explosionSize[4]
if (explosion_sum != 0)
explosionString = " Boom=|"
for (var/X in temp_pod.explosionSize)
explosionString += "[X]|"
var/msg = "launched [podString][whomString].[delayString][damageString][explosionString]]"
message_admins("[key_name_admin(usr)] [msg] in [AREACOORD(specificTarget)].")
if (!isemptylist(whoDyin))
for (var/mob/living/M in whoDyin)
admin_ticket_log(M, "[key_name_admin(usr)] [msg]")
+2 -2
View File
@@ -183,7 +183,7 @@
LZ = pick(empty_turfs)
if (SO.pack.cost <= SSshuttle.points && LZ)//we need to call the cost check again because of the CHECK_TICK call
SSshuttle.points -= SO.pack.cost
new /obj/effect/DPtarget(LZ, podType, SO)
new /obj/effect/abstract/DPtarget(LZ, podType, SO)
. = TRUE
update_icon()
else
@@ -200,7 +200,7 @@
for(var/i in 1 to MAX_EMAG_ROCKETS)
var/LZ = pick(empty_turfs)
LAZYREMOVE(empty_turfs, LZ)
new /obj/effect/DPtarget(LZ, podType, SO)
new /obj/effect/abstract/DPtarget(LZ, podType, SO)
. = TRUE
update_icon()
CHECK_TICK
+9 -2
View File
@@ -39,7 +39,14 @@
set name = "Release Contents"
set category = "Gondola"
set desc = "Release any contents stored within your vast belly."
linked_pod.open(src)
linked_pod.open(src, forced = TRUE)
/mob/living/simple_animal/pet/gondola/gondolapod/examine(mob/user)
..()
if (contents.len)
to_chat(user, "<span class='notice'>It looks like it hasn't made its delivery yet.</b><span>")
else
to_chat(user, "<span class='notice'>It looks like it has already made its delivery.</b><span>")
/mob/living/simple_animal/pet/gondola/gondolapod/verb/check()
set name = "Count Contents"
@@ -47,7 +54,7 @@
set desc = "Take a deep look inside youself, and count up what's inside"
var/total = contents.len
if (total)
to_chat(src, "<span class='notice'>You detect [total] object[total > 1 ? "s" : ""] within your incredibly vast belly.</span>")
to_chat(src, "<span class='notice'>You detect [total] object\s within your incredibly vast belly.</span>")
else
to_chat(src, "<span class='notice'>A closer look inside yourself reveals... nothing.</span>")
+1 -33
View File
@@ -91,15 +91,11 @@
crate_name = "insulated gloves crate"
crate_type = /obj/structure/closet/crate/engineering/electrical
/obj/item/stock_parts/cell/inducer_supply
maxcharge = 5000
charge = 5000
/datum/supply_pack/engineering/inducers
name = "NT-75 Electromagnetic Power Inducers Crate"
desc = "No rechargers? No problem, with the NT-75 EPI, you can recharge any standard cell-based equipment anytime, anywhere. Contains two Inducers."
cost = 2300
contains = list(/obj/item/inducer/sci {cell_type = /obj/item/stock_parts/cell/inducer_supply; opened = 0}, /obj/item/inducer/sci {cell_type = /obj/item/stock_parts/cell/inducer_supply; opened = 0}) //FALSE doesn't work in modified type paths apparently.
contains = list(/obj/item/inducer/sci/supply, /obj/item/inducer/sci/supply)
crate_name = "inducer crate"
crate_type = /obj/structure/closet/crate/engineering/electrical
@@ -121,18 +117,6 @@
crate_name = "power cell crate"
crate_type = /obj/structure/closet/crate/engineering/electrical
/datum/supply_pack/engineering/siezedpower
name = "Siezed Power Cell Crate"
desc = "We took the means of power! Contains three high-voltage plus power cells."
cost = 1300
contraband = TRUE
contains = list(/obj/item/stock_parts/cell/high/plus,
/obj/item/stock_parts/cell/high/plus,
/obj/item/stock_parts/cell/high/plus)
crate_name = "siezed crate"
crate_type = /obj/structure/closet/crate/engineering/electrical
/datum/supply_pack/engineering/shuttle_engine
name = "Shuttle Engine Crate"
desc = "Through advanced bluespace-shenanigans, our engineers have managed to fit an entire shuttle engine into one tiny little crate. Requires CE access to open."
@@ -142,22 +126,6 @@
crate_name = "shuttle engine crate"
crate_type = /obj/structure/closet/crate/secure/engineering
/datum/supply_pack/engineering/siezedproduction
name = "The Means of Production"
desc = "We will win for we have took over the production! S five metal sheets, five wire, three matter bins, one manipulater and one sheet of glass."
cost = 1500
contraband = TRUE
contains = list(/obj/item/stock_parts/cell/high/plus,
/obj/item/circuitboard/machine/autolathe,
/obj/item/stack/cable_coil/random/five,
/obj/item/stack/sheet/metal/five,
/obj/item/stock_parts/matter_bin,
/obj/item/stock_parts/matter_bin,
/obj/item/stock_parts/matter_bin,
/obj/item/stock_parts/manipulator,
/obj/item/stack/sheet/glass,)
crate_name = "siezed crate"
/datum/supply_pack/engineering/tools
name = "Toolbox Crate"
desc = "Any robust spaceman is never far from their trusty toolbox. Contains three electrical toolboxes and three mechanical toolboxes."
+1 -1
View File
@@ -195,7 +195,7 @@
name = "Loom"
desc = "A large pre-made loom."
cost = 1000
contains = list(/obj/structure/loom)
contains = list(/obj/structure/loom/unanchored)
crate_name = "loom crate"
crate_type = /obj/structure/closet/crate/large
+3 -14
View File
@@ -30,9 +30,10 @@
/datum/supply_pack/medical/bloodpacks
name = "Blood Pack Variety Crate"
desc = "Contains ten different blood packs for reintroducing blood to patients."
desc = "Contains nine different blood packs for reintroducing blood to patients, plus two universal synthetic blood packs."
cost = 3000
contains = list(/obj/item/reagent_containers/blood/random,
contains = list(/obj/item/reagent_containers/blood/synthetics,
/obj/item/reagent_containers/blood/synthetics,
/obj/item/reagent_containers/blood/random,
/obj/item/reagent_containers/blood/APlus,
/obj/item/reagent_containers/blood/AMinus,
@@ -46,18 +47,6 @@
crate_name = "blood freezer"
crate_type = /obj/structure/closet/crate/freezer
/datum/supply_pack/medical/bloodpackssynth
name = "Synthetics Blood Pack Crate"
desc = "Contains five synthetics blood packs for reintroducing blood to patients."
cost = 3000
contains = list(/obj/item/reagent_containers/blood/synthetics,
/obj/item/reagent_containers/blood/synthetics,
/obj/item/reagent_containers/blood/synthetics,
/obj/item/reagent_containers/blood/synthetics,
/obj/item/reagent_containers/blood/synthetics)
crate_name = "blood freezer"
crate_type = /obj/structure/closet/crate/freezer
/datum/supply_pack/medical/defibs
name = "Defibrillator Crate"
desc = "Contains two defibrillators for bringing the recently deceased back to life."
-13
View File
@@ -204,19 +204,6 @@
)
crate_name = "religious supplies crate"
/datum/supply_pack/misc/randomised/promiscuous
name = "Promiscuous Organs"
desc = "Do YOU want to have more genital? Well we have just the thing for you~. This crate has two autosurgeon, that will let you have a new sex, organ to impress that hot stud and or chick."
cost = 4000 //Only get 2!
contraband = TRUE
var/num_contained = 2
contains = list(/obj/item/autosurgeon/penis,
/obj/item/autosurgeon/testicles,
/obj/item/autosurgeon/vagina,
/obj/item/autosurgeon/breasts,
/obj/item/autosurgeon/womb)
crate_name = "promiscuous organs"
/datum/supply_pack/misc/toner
name = "Toner Crate"
desc = "Spent too much ink printing butt pictures? Fret not, with these six toner refills, you'll be printing butts 'till the cows come home!'"
+25 -35
View File
@@ -33,32 +33,6 @@
/obj/item/stack/packageWrap)
crate_name = "cargo supplies crate"
/datum/supply_pack/service/carpet_exotic
name = "Exotic Carpet Crate"
desc = "Exotic carpets straight from Space Russia, for all your decorating needs. Contains 100 tiles each of 10 different flooring patterns."
cost = 7000
contains = list(/obj/item/stack/tile/carpet/blue/fifty,
/obj/item/stack/tile/carpet/blue/fifty,
/obj/item/stack/tile/carpet/cyan/fifty,
/obj/item/stack/tile/carpet/cyan/fifty,
/obj/item/stack/tile/carpet/green/fifty,
/obj/item/stack/tile/carpet/green/fifty,
/obj/item/stack/tile/carpet/orange/fifty,
/obj/item/stack/tile/carpet/orange/fifty,
/obj/item/stack/tile/carpet/purple/fifty,
/obj/item/stack/tile/carpet/purple/fifty,
/obj/item/stack/tile/carpet/red/fifty,
/obj/item/stack/tile/carpet/red/fifty,
/obj/item/stack/tile/carpet/royalblue/fifty,
/obj/item/stack/tile/carpet/royalblue/fifty,
/obj/item/stack/tile/carpet/royalblack/fifty,
/obj/item/stack/tile/carpet/royalblack/fifty,
/obj/item/stack/tile/carpet/blackred/fifty,
/obj/item/stack/tile/carpet/blackred/fifty,
/obj/item/stack/tile/carpet/monochrome/fifty,
/obj/item/stack/tile/carpet/monochrome/fifty)
crate_name = "exotic carpet crate"
/datum/supply_pack/service/food_cart
name = "Food Cart Crate"
desc = "Want to sell food on the go? Cook lost their cart? Well we just so happen to have a few carts to spare!"
@@ -179,23 +153,39 @@
/datum/supply_pack/service/carpet
name = "Premium Carpet Crate"
desc = "Plasteel floor tiles getting on your nerves? These stacks of extra soft carpet will tie any room together. Contains the classics."
desc = "Plasteel floor tiles getting on your nerves? These stacks of extra soft carpet will tie any room together. Contains one of each pattern: classic, black, black-red and monochrome."
cost = 1000
contains = list(/obj/item/stack/tile/carpet/fifty,
/obj/item/stack/tile/carpet/fifty,
/obj/item/stack/tile/carpet/blackred/fifty,
/obj/item/stack/tile/carpet/black/fifty,
/obj/item/stack/tile/carpet/black/fifty)
/obj/item/stack/tile/carpet/monochrome/fifty)
crate_name = "premium carpet crate"
/datum/supply_pack/service/carpet2
name = "Premium Carpet Crate #2"
desc = "Plasteel floor tiles getting on your nerves? These stacks of extra soft carpet will tie any room together. Contains red, and monochrome"
cost = 1000
contains = list(/obj/item/stack/tile/carpet/blackred/fifty,
/datum/supply_pack/service/carpet_exotic
name = "Exotic Carpet Crate"
desc = "Exotic carpets straight from Space Russia, for all your decorating needs. Contains 100 tiles each of 10 different flooring patterns."
cost = 7000
contains = list(/obj/item/stack/tile/carpet/blue/fifty,
/obj/item/stack/tile/carpet/blue/fifty,
/obj/item/stack/tile/carpet/cyan/fifty,
/obj/item/stack/tile/carpet/cyan/fifty,
/obj/item/stack/tile/carpet/green/fifty,
/obj/item/stack/tile/carpet/green/fifty,
/obj/item/stack/tile/carpet/orange/fifty,
/obj/item/stack/tile/carpet/orange/fifty,
/obj/item/stack/tile/carpet/purple/fifty,
/obj/item/stack/tile/carpet/purple/fifty,
/obj/item/stack/tile/carpet/red/fifty,
/obj/item/stack/tile/carpet/red/fifty,
/obj/item/stack/tile/carpet/royalblue/fifty,
/obj/item/stack/tile/carpet/royalblue/fifty,
/obj/item/stack/tile/carpet/royalblack/fifty,
/obj/item/stack/tile/carpet/royalblack/fifty,
/obj/item/stack/tile/carpet/blackred/fifty,
/obj/item/stack/tile/carpet/blackred/fifty,
/obj/item/stack/tile/carpet/monochrome/fifty,
/obj/item/stack/tile/carpet/monochrome/fifty)
crate_name = "premium carpet crate #2"
crate_name = "exotic carpet crate"
/datum/supply_pack/service/lightbulbs
name = "Replacement Lights"
+94 -45
View File
@@ -15,15 +15,17 @@
armor = list("melee" = 30, "bullet" = 50, "laser" = 50, "energy" = 100, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 80)
anchored = TRUE //So it cant slide around after landing
anchorable = FALSE
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
//*****NOTE*****: Many of these comments are similarly described in centcom_podlauncher.dm. If you change them here, please consider doing so in the centcom podlauncher code as well!
var/adminNamed = FALSE //Determines whether or not the pod has been named by an admin. If true, the pod's name will not get overridden when the style of the pod changes (changing the style of the pod normally also changes the name+desc)
var/bluespace = FALSE //If true, the pod deletes (in a shower of sparks) after landing
var/landingDelay = 30 //How long the pod takes to land after launching
var/openingDelay = 30 //How long the pod takes to open after landing
var/departureDelay = 30 //How long the pod takes to leave after opening (if bluespace=true, it deletes. if reversing=true, it flies back to centcom)
var/departureDelay = 30 //How long the pod takes to leave after opening. If bluespace = TRUE, it deletes. If reversing = TRUE, it flies back to centcom.
var/damage = 0 //Damage that occurs to any mob under the pod when it lands.
var/effectStun = FALSE //If true, stuns anyone under the pod when it launches until it lands, forcing them to get hit by the pod. Devilish!
var/effectLimb = FALSE //If true, pops off a limb (if applicable) from anyone caught under the pod when it lands
var/effectOrgans = FALSE //If true, yeets out every limb and organ from anyone caught under the pod when it lands
var/effectGib = FALSE //If true, anyone under the pod will be gibbed when it lands
var/effectStealth = FALSE //If true, a target icon isnt displayed on the turf where the pod will land
var/effectQuiet = FALSE //The female sniper. If true, the pod makes no noise (including related explosions, opening sounds, etc)
@@ -31,10 +33,13 @@
var/effectCircle = FALSE //If true, allows the pod to come in at any angle. Bit of a weird feature but whatever its here
var/style = STYLE_STANDARD //Style is a variable that keeps track of what the pod is supposed to look like. It acts as an index to the POD_STYLES list in cargo.dm defines to get the proper icon/name/desc for the pod.
var/reversing = FALSE //If true, the pod will not send any items. Instead, after opening, it will close again (picking up items/mobs) and fly back to centcom
var/fallDuration = 4
var/fallingSoundLength = 11
var/fallingSound = 'sound/weapons/mortar_long_whistle.ogg'//Admin sound to play before the pod lands
var/landingSound //Admin sound to play when the pod lands
var/openingSound //Admin sound to play when the pod opens
var/leavingSound //Admin sound to play when the pod leaves
var/soundVolume = 50 //Volume to play sounds at. Ignores the cap
var/soundVolume = 80 //Volume to play sounds at. Ignores the cap
var/bay //Used specifically for the centcom_podlauncher datum. Holds the current bay the user is launching objects from. Bays are specific rooms on the centcom map.
var/list/explosionSize = list(0,0,2,3)
@@ -48,16 +53,18 @@
style = STYLE_CENTCOM
bluespace = TRUE
explosionSize = list(0,0,0,0)
landingDelay = 5 //Very speedy!
landingDelay = 20 //Very speedy!
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/obj/structure/closet/supplypod/Initialize()
..()
. = ..()
setStyle(style, TRUE) //Upon initialization, give the supplypod an iconstate, name, and description based on the "style" variable. This system is important for the centcom_podlauncher to function correctly
/obj/structure/closet/supplypod/update_icon()
cut_overlays()
if (style != STYLE_INVISIBLE) //If we're invisible, we dont bother adding any overlays
if (style == STYLE_SEETHROUGH || style == STYLE_INVISIBLE) //If we're invisible, we dont bother adding any overlays
return
else
if (opened)
add_overlay("[icon_state]_open")
else
@@ -75,7 +82,7 @@
update_icon()
/obj/structure/closet/supplypod/tool_interact(obj/item/W, mob/user)
if (bluespace) //We dont want to worry about interacting with bluespace pods, as they are due to delete themselves soon anyways.
if(bluespace) //We dont want to worry about interacting with bluespace pods, as they are due to delete themselves soon anyways.
return FALSE
else
..()
@@ -86,9 +93,6 @@
/obj/structure/closet/supplypod/contents_explosion() //Supplypods also protect their contents from the harmful effects of fucking exploding.
return
/obj/structure/closet/supplypod/prevent_content_explosion() //Useful for preventing epicenter explosions from damaging contents
return TRUE
/obj/structure/closet/supplypod/toggle(mob/living/user) //Supplypods shouldn't be able to be manually opened under any circumstances, as the open() proc generates supply order datums
return
@@ -101,17 +105,33 @@
if (effectLimb && iscarbon(M)) //If effectLimb is true (which means we pop limbs off when we hit people):
var/mob/living/carbon/CM = M
for (var/obj/item/bodypart/bodypart in CM.bodyparts) //Look at the bodyparts in our poor mob beneath our pod as it lands
if(bodypart.body_part != HEAD && bodypart.body_zone != CHEST)//we dont want to kill him, just teach em a lesson!
if(bodypart.body_part != HEAD && bodypart.body_part != CHEST)//we dont want to kill him, just teach em a lesson!
if (bodypart.dismemberable)
bodypart.dismember() //Using the power of flextape i've sawed this man's limb in half!
break
if (effectOrgans && iscarbon(M)) //effectOrgans means remove every organ in our mob
var/mob/living/carbon/CM = M
for(var/X in CM.internal_organs)
var/destination = get_edge_target_turf(T, pick(GLOB.alldirs)) //Pick a random direction to toss them in
var/obj/item/organ/O = X
O.Remove(CM) //Note that this isn't the same proc as for lists
O.forceMove(T) //Move the organ outta the body
O.throw_at(destination, 2, 3) //Thow the organ at a random tile 3 spots away
sleep(1)
for (var/obj/item/bodypart/bodypart in CM.bodyparts) //Look at the bodyparts in our poor mob beneath our pod as it lands
var/destination = get_edge_target_turf(T, pick(GLOB.alldirs))
if (bodypart.dismemberable)
bodypart.dismember() //Using the power of flextape i've sawed this man's bodypart in half!
bodypart.throw_at(destination, 2, 3)
sleep(1)
if (effectGib) //effectGib is on, that means whatever's underneath us better be fucking oof'd on
M.adjustBruteLoss(5000) //THATS A LOT OF DAMAGE (called just in case gib() doesnt work on em)
M.gib() //After adjusting the fuck outta that brute loss we finish the job with some satisfying gibs
M.adjustBruteLoss(damage)
if (B[1] || B[2] || B[3] || B[4]) //If the explosion list isn't all zeroes, call an explosion
else
M.adjustBruteLoss(damage)
var/explosion_sum = B[1] + B[2] + B[3] + B[4]
if (explosion_sum != 0) //If the explosion list isn't all zeroes, call an explosion
explosion(get_turf(src), B[1], B[2], B[3], flame_range = B[4], silent = effectQuiet, ignorecap = istype(src, /obj/structure/closet/supplypod/centcompod)) //less advanced equipment than bluespace pod, so larger explosion when landing
else if (!effectQuiet) //If our explosion list IS all zeroes, we still make a nice explosion sound (unless the effectQuiet var is true)
playsound(src, "explosion", landingSound ? 15 : 80, 1)
@@ -128,22 +148,31 @@
/obj/structure/closet/supplypod/open(atom/movable/holder, var/broken = FALSE, var/forced = FALSE) //The holder var represents an atom whose contents we will be working with
var/turf/T = get_turf(holder) //Get the turf of whoever's contents we're talking about
if (!holder)
return
if(opened)
return
opened = TRUE //This is to ensure we don't open something that has already been opened
var/mob/M
if (istype(holder, /mob)) //Allows mobs to assume the role of the holder, meaning we look at the mob's contents rather than the supplypod's contents. Typically by this point the supplypod's contents have already been moved over to the mob's contents
M = holder
if (M.key && !forced && !broken) //If we are player controlled, then we shouldnt open unless the opening is manual, or if it is due to being destroyed (represented by the "broken" parameter)
return
opened = TRUE //This is to ensure we don't open something that has already been opened
if (openingSound)
playsound(get_turf(holder), openingSound, soundVolume, 0, 0)
playsound(get_turf(holder), openingSound, soundVolume, 0, 0) //Special admin sound to play
INVOKE_ASYNC(holder, .proc/setOpened) //Use the INVOKE_ASYNC proc to call setOpened() on whatever the holder may be, without giving the atom/movable base class a setOpened() proc definition
if (style == STYLE_SEETHROUGH)
update_icon()
for (var/atom/movable/O in holder.contents) //Go through the contents of the holder
O.forceMove(T) //move everything from the contents of the holder to the turf of the holder
if (!effectQuiet) //If we aren't being quiet, play an open sound
if (!effectQuiet && !openingSound && style != STYLE_SEETHROUGH) //If we aren't being quiet, play the default pod open sound
playsound(get_turf(holder), open_sound, 15, 1, -3)
if (broken) //If the pod is opening because it's been destroyed, we end here
return
addtimer(CALLBACK(src, .proc/depart, holder), departureDelay) //Finish up the pod's duties after a certain amount of time
if (style == STYLE_SEETHROUGH)
depart(src)
else
addtimer(CALLBACK(src, .proc/depart, holder), departureDelay) //Finish up the pod's duties after a certain amount of time
/obj/structure/closet/supplypod/proc/depart(atom/movable/holder)
if (leavingSound)
@@ -151,7 +180,7 @@
if (reversing) //If we're reversing, we call the close proc. This sends the pod back up to centcom
close(holder)
else if (bluespace) //If we're a bluespace pod, then delete ourselves (along with our holder, if a seperate holder exists)
if (style != STYLE_INVISIBLE)
if (!effectQuiet && style != STYLE_INVISIBLE && style != STYLE_SEETHROUGH)
do_sparks(5, TRUE, holder) //Create some sparks right before closing
qdel(src) //Delete ourselves and the holder
if (holder != src)
@@ -164,13 +193,14 @@
if (ismob(O) && !isliving(O)) //We dont want to take ghosts with us
continue
O.forceMove(holder) //Put objects inside before we close
var/obj/effect/temp_visual/risingPod = new /obj/effect/temp_visual/DPfall(get_turf(holder), src) //Make a nice animation of flying back up
var/obj/effect/temp_visual/risingPod = new /obj/effect/abstract/DPfall(get_turf(holder), src) //Make a nice animation of flying back up
risingPod.pixel_z = 0 //The initial value of risingPod's pixel_z is 200 because it normally comes down from a high spot
holder.forceMove(bay) //Move the pod back to centcom, where it belongs
animate(risingPod, pixel_z = 200, time = 10, easing = LINEAR_EASING) //Animate our rising pod
QDEL_IN(risingPod, 10)
reversing = FALSE //Now that we're done reversing, we set this to false (otherwise we would get stuck in an infinite loop of calling the close proc at the bottom of open() )
bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever
open(holder, forced = TRUE)
return
/obj/structure/closet/supplypod/proc/setOpened() //Proc exists here, as well as in any atom that can assume the role of a "holder" of a supplypod. Check the open() proc for more details
update_icon()
@@ -179,12 +209,11 @@
update_icon()
/obj/structure/closet/supplypod/Destroy()
if (!opened) //If we havent opened yet, we're opening because we've been destroyed. Lets dump our contents by opening up
open(src, broken = TRUE)
return ..()
open(src, broken = TRUE) //Lets dump our contents by opening up
. = ..()
//------------------------------------FALLING SUPPLY POD-------------------------------------//
/obj/effect/temp_visual/DPfall //Falling pod
/obj/effect/abstract/DPfall //Falling pod
name = ""
icon = 'icons/obj/supplypods.dmi'
pixel_x = -16
@@ -192,17 +221,22 @@
pixel_z = 200
desc = "Get out of the way!"
layer = FLY_LAYER//that wasnt flying, that was falling with style!
randomdir = FALSE
icon_state = ""
/obj/effect/temp_visual/DPfall/Initialize(dropLocation, obj/structure/closet/supplypod/pod)
if (pod.style != STYLE_INVISIBLE) //Check to ensure the pod isn't invisible
/obj/effect/abstract/DPfall/Initialize(dropLocation, obj/structure/closet/supplypod/pod)
if (pod.style == STYLE_SEETHROUGH)
pixel_x = -16
pixel_y = 0
for (var/atom/movable/O in pod.contents)
var/icon/I = getFlatIcon(O) //im so sorry
add_overlay(I)
else if (pod.style != STYLE_INVISIBLE) //Check to ensure the pod isn't invisible
icon_state = "[pod.icon_state]_falling"
name = pod.name
. = ..()
//------------------------------------TEMPORARY_VISUAL-------------------------------------//
/obj/effect/DPtarget //This is the object that forceMoves the supplypod to it's location
/obj/effect/abstract/DPtarget //This is the object that forceMoves the supplypod to it's location
name = "Landing Zone Indicator"
desc = "A holographic projection designating the landing zone of something. It's probably best to stand back."
icon = 'icons/mob/actions/actions_items.dmi'
@@ -212,45 +246,60 @@
var/obj/effect/temp_visual/fallingPod //Temporary "falling pod" that we animate
var/obj/structure/closet/supplypod/pod //The supplyPod that will be landing ontop of this target
/obj/effect/ex_act()
return
/obj/effect/DPtarget/Initialize(mapload, podParam, var/datum/supply_order/SO = null)
/obj/effect/abstract/DPtarget/Initialize(mapload, podParam, single_order = null)
. = ..()
if (ispath(podParam)) //We can pass either a path for a pod (as expressconsoles do), or a reference to an instantiated pod (as the centcom_podlauncher does)
podParam = new podParam() //If its just a path, instantiate it
pod = podParam
if (SO)
SO.generate(pod)
for (var/mob/living/M in podParam) //If there are any mobs in the supplypod, we want to forceMove them into the target. This is so that they can see where they are about to land, AND so that they don't get sent to the nullspace error room (as the pod is currently in nullspace)
if (single_order)
if (istype(single_order, /datum/supply_order))
var/datum/supply_order/SO = single_order
SO.generate(pod)
else if (istype(single_order, /atom/movable))
var/atom/movable/O = single_order
O.forceMove(pod)
for (var/mob/living/M in pod) //If there are any mobs in the supplypod, we want to forceMove them into the target. This is so that they can see where they are about to land, AND so that they don't get sent to the nullspace error room (as the pod is currently in nullspace)
M.forceMove(src)
if(pod.effectStun) //If effectStun is true, stun any mobs caught on this target until the pod gets a chance to hit them
for (var/mob/living/M in get_turf(src))
M.Stun(pod.landingDelay+10, ignore_canstun = TRUE)//you aint goin nowhere, kid.
if (pod.effectStealth) //If effectStealth is true we want to be invisible
alpha = 255
icon_state = ""
if (pod.fallDuration == initial(pod.fallDuration) && pod.landingDelay + pod.fallDuration < pod.fallingSoundLength)
pod.fallingSoundLength = 3 //The default falling sound is a little long, so if the landing time is shorter than the default falling sound, use a special, shorter default falling sound
pod.fallingSound = 'sound/weapons/mortar_whistle.ogg'
var/soundStartTime = pod.landingDelay - pod.fallingSoundLength + pod.fallDuration
if (soundStartTime < 0)
soundStartTime = 1
if (!pod.effectQuiet)
addtimer(CALLBACK(src, .proc/playFallingSound), soundStartTime)
addtimer(CALLBACK(src, .proc/beginLaunch, pod.effectCircle), pod.landingDelay)
/obj/effect/DPtarget/proc/beginLaunch(effectCircle) //Begin the animation for the pod falling. The effectCircle param determines whether the pod gets to come in from any descent angle
fallingPod = new /obj/effect/temp_visual/DPfall(drop_location(), pod)
/obj/effect/abstract/DPtarget/proc/playFallingSound()
playsound(src, pod.fallingSound, pod.soundVolume, 1, 6)
/obj/effect/abstract/DPtarget/proc/beginLaunch(effectCircle) //Begin the animation for the pod falling. The effectCircle param determines whether the pod gets to come in from any descent angle
fallingPod = new /obj/effect/abstract/DPfall(drop_location(), pod)
var/matrix/M = matrix(fallingPod.transform) //Create a new matrix that we can rotate
var/angle = effectCircle ? rand(0,360) : rand(70,110) //The angle that we can come in from
fallingPod.pixel_x = cos(angle)*200 //Use some ADVANCED MATHEMATICS to set the animated pod's position to somewhere on the edge of a circle with the center being the target
fallingPod.pixel_z = sin(angle)*200
fallingPod.pixel_x = cos(angle)*400 //Use some ADVANCED MATHEMATICS to set the animated pod's position to somewhere on the edge of a circle with the center being the target
fallingPod.pixel_z = sin(angle)*400
var/rotation = Get_Pixel_Angle(fallingPod.pixel_z, fallingPod.pixel_x) //CUSTOM HOMEBREWED proc that is just arctan with extra steps
M.Turn(rotation) //Turn our matrix accordingly
fallingPod.transform = M //Transform the animated pod according to the matrix
M = matrix(pod.transform) //Make another matrix based on the pod
M.Turn(rotation) //Turn the matrix
pod.transform = M //Turn the actual pod (Won't be visible until endLaunch() proc tho)
animate(fallingPod, pixel_z = 0, pixel_x = -16, time = 3, , easing = LINEAR_EASING) //Make the pod fall! At an angle!
addtimer(CALLBACK(src, .proc/endLaunch), 3, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation
animate(fallingPod, pixel_z = 0, pixel_x = -16, time = pod.fallDuration, , easing = LINEAR_EASING) //Make the pod fall! At an angle!
addtimer(CALLBACK(src, .proc/endLaunch), pod.fallDuration, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation
/obj/effect/DPtarget/proc/endLaunch()
/obj/effect/abstract/DPtarget/proc/endLaunch()
pod.update_icon()
pod.forceMove(drop_location()) //The fallingPod animation is over, now's a good time to forceMove the actual pod into position
QDEL_NULL(fallingPod) //Delete the falling pod effect, because at this point its animation is over. We dont use temp_visual because we want to manually delete it as soon as the pod appears
for (var/mob/living/M in src) //Remember earlier (initialization) when we moved mobs into the DPTarget so they wouldnt get lost in nullspace? Time to get them out
M.forceMove(pod)
pod.preOpen() //Begin supplypod open procedures. Here effects like explosions, damage, and other dangerous (and potentially admin-caused, if the centcom_podlauncher datum was used) memes will take place
QDEL_NULL(fallingPod) //The fallingPod's (the animated effect, not the actual pod) purpose is complete. It can rest easy now
qdel(src) //ditto
//------------------------------------UPGRADES-------------------------------------//
+1 -1
View File
@@ -62,7 +62,7 @@
if(ismecha(M.loc)) // stops inventory actions in a mech
return
if(!M.incapacitated() && loc == M && istype(over_object, /obj/screen/inventory/hand))
if(!. && !M.incapacitated() && loc == M && istype(over_object, /obj/screen/inventory/hand))
var/obj/screen/inventory/hand/H = over_object
if(M.putItemFromInventoryInHandIfPossible(src, H.held_index))
add_fingerprint(usr)
@@ -27,7 +27,6 @@
icon_state = "chef"
item_state = "chef"
dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/chef
/obj/item/clothing/head/collectable/paper
+13 -3
View File
@@ -113,10 +113,8 @@
desc = "Wearing these makes you look useless, and only good for your sex appeal."
icon_state = "bunny"
dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/rabbit
/obj/item/clothing/head/flatcap
name = "flat cap"
desc = "A working man's cap."
@@ -205,7 +203,6 @@
item_state = "sombrero"
desc = "You can practically taste the fiesta."
flags_inv = HIDEHAIR
dog_fashion = /datum/dog_fashion/head/sombrero
/obj/item/clothing/head/sombrero/green
@@ -370,6 +367,19 @@
desc = "A cheap replica of old riot helmet without visor. It has \"D.A.B.\" written on the front."
flags_inv = HIDEHAIR
/obj/item/clothing/head/hotel
name = "Telegram cap"
desc = "A bright red cap warn by hotel staff. Or people who want to be a singing telegram"
icon_state = "telegramhat"
item_color = "telegramhat"
dog_fashion = null
/obj/item/clothing/head/colour
name = "Singer cap"
desc = "A light white hat that has bands of color. Just makes you want to sing and dance!"
icon_state = "colour"
item_color = "colour"
dog_fashion = /datum/dog_fashion/head/colour
/obj/item/clothing/head/christmashat
name = "red santa hat"
desc = "A red Christmas Hat! How festive!"
+2 -2
View File
@@ -254,8 +254,8 @@
return
if(paranoia)
QDEL_NULL(paranoia)
paranoia = new()
user.gain_trauma(paranoia, TRAUMA_RESILIENCE_MAGIC, "conspiracies")
paranoia = new("conspiracies")
user.gain_trauma(paranoia, TRAUMA_RESILIENCE_MAGIC)
to_chat(user, "<span class='warning'>As you don the foiled hat, an entire world of conspiracy theories and seemingly insane ideas suddenly rush into your mind. What you once thought unbelievable suddenly seems.. undeniable. Everything is connected and nothing happens just by accident. You know too much and now they're out to get you. </span>")
/obj/item/clothing/head/foilhat/MouseDrop(atom/over_object)
+1 -1
View File
@@ -139,4 +139,4 @@
flags_inv = HIDEEYES|HIDEFACE
armor = list("melee" = 35, "bullet" = 35, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 90)
strip_delay = 90 //You dont take a Major Leage cap
dog_fashion = null
dog_fashion = null
+1 -1
View File
@@ -65,7 +65,7 @@
/obj/item/clothing/head/helmet/space/hardsuit/proc/display_visor_message(var/msg)
var/mob/wearer = loc
if(msg && ishuman(wearer))
wearer.show_message("[icon2html(src, wearer)]<b><span class='robot'>[msg]</span></b>", 1)
wearer.show_message("[icon2html(src, wearer)]<b><span class='robot'>[msg]</span></b>", MSG_VISUAL)
/obj/item/clothing/head/helmet/space/hardsuit/rad_act(severity)
. = ..()
@@ -505,6 +505,21 @@
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
flags_inv = HIDEHAIR|HIDEEARS
/obj/item/clothing/suit/hooded/wintercoat/centcom
name = "centcom winter coat"
icon_state = "coatcentcom"
item_state = "coatcentcom"
armor = list("melee" = 40, "bullet" = 45, "laser" = 45, "energy" = 35, "bomb" = 40, "bio" = 25, "rad" = 25, "fire" = 35, "acid" = 50)
hoodtype = /obj/item/clothing/head/hooded/winterhood/centcom
/obj/item/clothing/suit/hooded/wintercoat/centcom/Initialize()
. = ..()
allowed = GLOB.security_wintercoat_allowed
/obj/item/clothing/head/hooded/winterhood/centcom
icon_state = "winterhood_centcom"
armor = list("melee" = 40, "bullet" = 45, "laser" = 45, "energy" = 35, "bomb" = 40, "bio" = 25, "rad" = 25, "fire" = 35, "acid" = 50)
/obj/item/clothing/suit/hooded/wintercoat/captain
name = "captain's winter coat"
icon_state = "coatcaptain"
@@ -723,6 +738,15 @@
/obj/item/clothing/head/hooded/winterhood/qm
icon_state = "winterhood_qm"
/obj/item/clothing/suit/hooded/wintercoat/aformal
name = "assistant's formal winter coat"
icon_state = "coataformal"
item_state = "coataformal"
hoodtype = /obj/item/clothing/head/hooded/winterhood/aformal
/obj/item/clothing/head/hooded/winterhood/aformal
icon_state = "winterhood_aformal"
/obj/item/clothing/suit/hooded/wintercoat/miner
name = "mining winter coat"
icon_state = "coatminer"
@@ -734,6 +758,27 @@
/obj/item/clothing/head/hooded/winterhood/miner
icon_state = "winterhood_miner"
/obj/item/clothing/suit/hooded/wintercoat/ratvar
name = "ratvarian winter coat"
icon_state = "coatratvar"
item_state = "coatratvar"
hoodtype = /obj/item/clothing/head/hooded/winterhood/ratvar
/obj/item/clothing/head/hooded/winterhood/ratvar
icon_state = "winterhood_ratvar"
light_range = 3
light_power = 1
light_color = "#B18B25" //clockwork slab background top color
/obj/item/clothing/suit/hooded/wintercoat/narsie
name = "narsian winter coat"
icon_state = "coatnarsie"
item_state = "coatnarsie"
hoodtype = /obj/item/clothing/head/hooded/winterhood/narsie
/obj/item/clothing/head/hooded/winterhood/narsie
icon_state = "winterhood_narsie"
/obj/item/clothing/suit/spookyghost
name = "spooky ghost"
desc = "This is obviously just a bedsheet, but maybe try it on?"

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