Merge branch 'master' into spike-loot-differentces

This commit is contained in:
Trilbyspaceclone
2020-08-27 03:41:14 -04:00
committed by GitHub
560 changed files with 13682 additions and 5938 deletions
+1 -1
View File
@@ -98,7 +98,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define ZAP_MOB_DAMAGE (1<<3)
#define ZAP_MOB_STUN (1<<4)
#define ZAP_DEFAULT_FLAGS ALL
#define ZAP_DEFAULT_FLAGS ZAP_MOB_STUN | ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE
#define ZAP_FUSION_FLAGS ZAP_OBJ_DAMAGE | ZAP_MOB_DAMAGE | ZAP_MOB_STUN
#define ZAP_SUPERMATTER_FLAGS NONE
+11 -1
View File
@@ -63,6 +63,16 @@
#define CONTRACT_UPLINK_PAGE_CONTRACTS "CONTRACTS"
#define CONTRACT_UPLINK_PAGE_HUB "HUB"
///Heretics --
#define IS_HERETIC(mob) (mob.mind?.has_antag_datum(/datum/antagonist/heretic))
#define PATH_SIDE "Side"
#define PATH_ASH "Ash"
#define PATH_RUST "Rust"
#define PATH_FLESH "Flesh"
//Overthrow time to update heads obj
#define OBJECTIVE_UPDATING_TIME 300
@@ -91,4 +101,4 @@
#define BLOB_REROLL_TIME 2400 // blob gets a free reroll every X time
#define BLOB_SPREAD_COST 4
#define BLOB_ATTACK_REFUND 2 //blob refunds this much if it attacks and doesn't spread
#define BLOB_REFLECTOR_COST 15
#define BLOB_REFLECTOR_COST 15
+1
View File
@@ -60,6 +60,7 @@
#define ANTAG_HUD_BROTHER 23
#define ANTAG_HUD_BLOODSUCKER 24
#define ANTAG_HUD_FUGITIVE 25
#define ANTAG_HUD_HERETIC 26
// Notification action types
#define NOTIFY_JUMP "jump"
+68 -34
View File
@@ -15,22 +15,31 @@
//////////////////////////////////////////////////////////////////
// /datum signals
#define COMSIG_COMPONENT_ADDED "component_added" //sent to the new datum parent when a component is added to them: (/datum/component)
#define COMSIG_COMPONENT_REMOVING "component_removing" //sent to the datum parent before a component is removed from them because of RemoveComponent: (/datum/component)
#define COMSIG_COMPONENT_UNREGISTER_PARENT "component_unregister_parent" //sent to the component itself when unregistered from a parent
#define COMSIG_COMPONENT_REGISTER_PARENT "component_register_parent" //sent to the component itself when registered to a parent
#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation
#define COMSIG_PARENT_QDELETING "parent_qdeleting" //just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called
/// Trait signals
#define COMPONENT_ADD_TRAIT (1<<0)
#define COMPONENT_REMOVE_TRAIT (1<<1)
/// when a component is added to a datum: (/datum/component)
#define COMSIG_COMPONENT_ADDED "component_added"
/// before a component is removed from a datum because of RemoveComponent: (/datum/component)
#define COMSIG_COMPONENT_REMOVING "component_removing"
/// before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation
#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted"
/// just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called
#define COMSIG_PARENT_QDELETING "parent_qdeleting"
/// generic topic handler (usr, href_list)
#define COMSIG_TOPIC "handle_topic"
/// fires on the target datum when an element is attached to it (/datum/element)
#define COMSIG_ELEMENT_ATTACH "element_attach"
/// fires on the target datum when an element is attached to it (/datum/element)
#define COMSIG_ELEMENT_DETACH "element_detach"
/// sent to the component itself when unregistered from a parent
#define COMSIG_COMPONENT_UNREGISTER_PARENT "component_unregister_parent"
/// sent to the component itself when registered to a parent
#define COMSIG_COMPONENT_REGISTER_PARENT "component_register_parent"
/// Trait signals
#define COMPONENT_ADD_TRAIT (1<<0)
#define COMPONENT_REMOVE_TRAIT (1<<1)
// /atom signals
//from base of atom/proc/Initialize(): sent any time a new atom is created
#define COMSIG_ATOM_CREATED "atom_created"
@@ -56,30 +65,54 @@
#define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc)
#define COMPONENT_ATOM_BLOCK_EXIT 1
#define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc)
#define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target)
#define COMSIG_ATOM_EMP_ACT "atom_emp_act" //from base of atom/emp_act(): (severity)
#define COMSIG_ATOM_FIRE_ACT "atom_fire_act" //from base of atom/fire_act(): (exposed_temperature, exposed_volume)
#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" //from base of atom/bullet_act(): (/obj/item/projectile, def_zone)
#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" //from base of atom/blob_act(): (/obj/structure/blob)
#define COMSIG_ATOM_ACID_ACT "atom_acid_act" //from base of atom/acid_act(): (acidpwr, acid_volume)
#define COMSIG_ATOM_EMAG_ACT "atom_emag_act" //from base of atom/emag_act(): ()
#define COMSIG_ATOM_RAD_ACT "atom_rad_act" //from base of atom/rad_act(intensity)
#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act" //from base of atom/narsie_act(): ()
#define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act" //from base of atom/ratvar_act(): ()
#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" //from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode)
#define COMSIG_ATOM_SING_PULL "atom_sing_pull" //from base of atom/singularity_pull(): (S, current_size)
#define COMSIG_ATOM_SET_LIGHT "atom_set_light" //from base of atom/set_light(): (l_range, l_power, l_color)
#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change" //from base of atom/setDir(): (old_dir, new_dir)
#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del" //from base of atom/handle_atom_del(): (atom/deleted)
#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity" //from base of atom/has_gravity(): (turf/location, list/forced_gravities)
#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe" //from proc/get_rad_contents(): ()
#define COMPONENT_BLOCK_RADIATION 1
#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam" //from base of datum/radiation_wave/radiate(): (strength)
#define COMPONENT_BLOCK_CONTAMINATION 1
#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass" //from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width)
#define COMPONENT_RAD_WAVE_HANDLED 1
#define COMSIG_ATOM_CANREACH "atom_can_reach" //from internal loop in atom/movable/proc/CanReach(): (list/next)
#define COMPONENT_BLOCK_REACH 1
///from base of atom/ex_act(): (severity, target)
#define COMSIG_ATOM_EX_ACT "atom_ex_act"
///from base of atom/emp_act(): (severity)
#define COMSIG_ATOM_EMP_ACT "atom_emp_act"
///from base of atom/fire_act(): (exposed_temperature, exposed_volume)
#define COMSIG_ATOM_FIRE_ACT "atom_fire_act"
///from base of atom/bullet_act(): (/obj/projectile, def_zone)
#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act"
///from base of atom/blob_act(): (/obj/structure/blob)
#define COMSIG_ATOM_BLOB_ACT "atom_blob_act"
///from base of atom/acid_act(): (acidpwr, acid_volume)
#define COMSIG_ATOM_ACID_ACT "atom_acid_act"
///from base of atom/emag_act(): (/mob/user)
#define COMSIG_ATOM_EMAG_ACT "atom_emag_act"
///from base of atom/rad_act(intensity)
#define COMSIG_ATOM_RAD_ACT "atom_rad_act"
///from base of atom/narsie_act(): ()
#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act"
///from base of atom/ratvar_act(): ()
#define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act"
///from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode)
#define COMSIG_ATOM_RCD_ACT "atom_rcd_act"
///from base of atom/singularity_pull(): (S, current_size)
#define COMSIG_ATOM_SING_PULL "atom_sing_pull"
///from obj/machinery/bsa/full/proc/fire(): ()
#define COMSIG_ATOM_BSA_BEAM "atom_bsa_beam_pass"
#define COMSIG_ATOM_BLOCKS_BSA_BEAM (1<<0)
///from base of atom/set_light(): (l_range, l_power, l_color)
#define COMSIG_ATOM_SET_LIGHT "atom_set_light"
///from base of atom/setDir(): (old_dir, new_dir). Called before the direction changes.
#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change"
///from base of atom/handle_atom_del(): (atom/deleted)
#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del"
///from base of atom/has_gravity(): (turf/location, list/forced_gravities)
#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity"
///from proc/get_rad_contents(): ()
#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe"
#define COMPONENT_BLOCK_RADIATION (1<<0)
///from base of datum/radiation_wave/radiate(): (strength)
#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam"
#define COMPONENT_BLOCK_CONTAMINATION (1<<0)
///from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width)
#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass"
#define COMPONENT_RAD_WAVE_HANDLED (1<<0)
///from internal loop in atom/movable/proc/CanReach(): (list/next)
#define COMSIG_ATOM_CANREACH "atom_can_reach"
#define COMPONENT_BLOCK_REACH (1<<0)
#define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" //from base of atom/screwdriver_act(): (mob/living/user, obj/item/I)
#define COMSIG_ATOM_INTERCEPT_TELEPORT "intercept_teleport" //called when teleporting into a protected turf: (channel, turf/origin, turf/destination)
#define COMPONENT_BLOCK_TELEPORT 1
@@ -279,6 +312,7 @@
#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
#define COMSIG_OBJ_BREAK "obj_break" //from base of /obj/obj_break(): (damage_flag)
#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value)
#define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench" //called exclusively in plumbing, for now
#define COMSIG_OBJ_ATTACK_GENERIC "obj_attack_generic" //from base of atom/animal_attack(): (/mob/user)
#define COMPONENT_STOP_GENERIC_ATTACK 1
+14 -4
View File
@@ -7,6 +7,8 @@
#define FOOTSTEP_WATER "water"
#define FOOTSTEP_LAVA "lava"
#define FOOTSTEP_MEAT "meat"
#define FOOTSTEP_RUST "rust"
//barefoot sounds
#define FOOTSTEP_WOOD_BAREFOOT "woodbarefoot"
#define FOOTSTEP_WOOD_CLAW "woodclaw"
@@ -91,7 +93,9 @@ GLOBAL_LIST_INIT(footstep, list(
'sound/effects/footstep/lava2.ogg',
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
'sound/effects/meatslap.ogg'), 100, 0)
'sound/effects/meatslap.ogg'), 100, 0),
FOOTSTEP_RUST = list(list(
'sound/effects/footstep/rustystep1.ogg'), 100, 0)
))
//bare footsteps lists
@@ -135,7 +139,9 @@ GLOBAL_LIST_INIT(barefootstep, list(
'sound/effects/footstep/lava2.ogg',
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
'sound/effects/meatslap.ogg'), 100, 0)
'sound/effects/meatslap.ogg'), 100, 0),
FOOTSTEP_RUST = list(list(
'sound/effects/footstep/rustystep1.ogg'), 100, 0)
))
//claw footsteps lists
@@ -179,7 +185,9 @@ GLOBAL_LIST_INIT(clawfootstep, list(
'sound/effects/footstep/lava2.ogg',
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
'sound/effects/meatslap.ogg'), 100, 0)
'sound/effects/meatslap.ogg'), 100, 0),
FOOTSTEP_RUST = list(list(
'sound/effects/footstep/rustystep1.ogg'), 100, 0)
))
//heavy footsteps list
@@ -197,5 +205,7 @@ GLOBAL_LIST_INIT(heavyfootstep, list(
'sound/effects/footstep/lava2.ogg',
'sound/effects/footstep/lava3.ogg'), 100, 0),
FOOTSTEP_MEAT = list(list(
'sound/effects/meatslap.ogg'), 100, 0)
'sound/effects/meatslap.ogg'), 100, 0),
FOOTSTEP_RUST = list(list(
'sound/effects/footstep/rustystep1.ogg'), 150, 2)
))
+3 -1
View File
@@ -17,7 +17,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
/turf/open/chasm,
/turf/open/lava,
/turf/open/water,
/turf/open/openspace
/turf/open/transparent/openspace
)))
#define isgroundlessturf(A) (is_type_in_typecache(A, GLOB.turfs_without_ground))
@@ -44,6 +44,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define isplatingturf(A) (istype(A, /turf/open/floor/plating))
#define istransparentturf(A) (istype(A, /turf/open/transparent))
//Mobs
#define isliving(A) (istype(A, /mob/living))
+1
View File
@@ -19,6 +19,7 @@
#define INVESTIGATE_FERMICHEM "fermichem"
#define INVESTIGATE_RCD "rcd"
#define INVESTIGATE_CRYOGENICS "cryogenics"
#define INVESTIGATE_GHOST "ghost"
// Logging types for log_message()
#define LOG_ATTACK (1 << 0)
+2
View File
@@ -46,6 +46,8 @@
// Cosecant
#define CSC(x) (1 / sin(x))
#define ATAN2(x, y) ( !(x) && !(y) ? 0 : (y) >= 0 ? arccos((x) / sqrt((x)*(x) + (y)*(y))) : -arccos((x) / sqrt((x)*(x) + (y)*(y))) )
// Greatest Common Divisor - Euclid's algorithm
/proc/Gcd(a, b)
return b ? Gcd(b, (a) % (b)) : a
+2
View File
@@ -332,3 +332,5 @@
/// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine()
#define EXAMINE_MORE_TIME 1 SECONDS
#define SILENCE_RANGED_MESSAGE (1<<0)
+9
View File
@@ -0,0 +1,9 @@
#define FIRST_DUCT_LAYER 1
#define SECOND_DUCT_LAYER 2
#define THIRD_DUCT_LAYER 4
#define FOURTH_DUCT_LAYER 8
#define FIFTH_DUCT_LAYER 16
#define DUCT_LAYER_DEFAULT THIRD_DUCT_LAYER
#define MACHINE_REAGENT_TRANSFER 10
+1 -1
View File
@@ -8,5 +8,5 @@
GLOBAL_LIST_INIT(blacklisted_pool_reagents, list(
/datum/reagent/toxin/plasma, /datum/reagent/oxygen, /datum/reagent/nitrous_oxide, /datum/reagent/nitrogen, //gases
/datum/reagent/fermi, //blanket fermichem ban sorry. this also covers mkultra, genital enlargers, etc etc.
/datum/reagent/consumable/femcum, /datum/reagent/consumable/semen //NO.
/datum/reagent/consumable/semen //NO.
))
+11 -4
View File
@@ -6,10 +6,17 @@
#define QDEL_HINT_IWILLGC 2 //functionally the same as the above. qdel should assume the object will gc on its own, and not check it.
#define QDEL_HINT_HARDDEL 3 //qdel should assume this object won't gc, and queue a hard delete using a hard reference.
#define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste.
#define QDEL_HINT_FINDREFERENCE 5 //functionally identical to QDEL_HINT_QUEUE if TESTING is not enabled in _compiler_options.dm.
//if TESTING is enabled, qdel will call this object's find_references() verb.
#define QDEL_HINT_IFFAIL_FINDREFERENCE 6 //Above but only if gc fails.
//defines for the gc_destroyed var
#ifdef LEGACY_REFERENCE_TRACKING
/** If LEGACY_REFERENCE_TRACKING is enabled, qdel will call this object's find_references() verb.
*
* Functionally identical to QDEL_HINT_QUEUE if GC_FAILURE_HARD_LOOKUP is not enabled in _compiler_options.dm.
*/
#define QDEL_HINT_FINDREFERENCE 5
/// Behavior as QDEL_HINT_FINDREFERENCE, but only if the GC fails and a hard delete is forced.
#define QDEL_HINT_IFFAIL_FINDREFERENCE 6
#endif
#define GC_QUEUE_CHECK 1
#define GC_QUEUE_HARDDELETE 2
+4
View File
@@ -57,6 +57,10 @@
#define ADD_REAGENT 2 // reagent added
#define REM_REAGENT 3 // reagent removed (may still exist)
#define PILL_STYLE_COUNT 22 //Update this if you add more pill icons or you die (literally, we'll toss a nuke at whever your ip turns up)
#define RANDOM_PILL_STYLE 22 //Dont change this one though
#define THRESHOLD_UNHUSK 50 // health threshold for synthflesh/rezadone to unhusk someone
//reagent bitflags, used for altering how they works
+2
View File
@@ -17,6 +17,7 @@
#define ROLE_ALIEN "xenomorph"
#define ROLE_PAI "pAI"
#define ROLE_CULTIST "cultist"
#define ROLE_HERETIC "Heretic"
#define ROLE_BLOB "blob"
#define ROLE_NINJA "space ninja"
#define ROLE_MONKEY "monkey"
@@ -64,6 +65,7 @@ GLOBAL_LIST_INIT(special_roles, list(
ROLE_INTERNAL_AFFAIRS = /datum/game_mode/traitor/internal_affairs,
ROLE_SENTIENCE,
ROLE_GANG = /datum/game_mode/gang,
ROLE_HERETIC = /datum/game_mode/heretics,
ROLE_BLOODSUCKER = /datum/game_mode/bloodsucker
//ROLE_MONSTERHUNTER Disabled for now
))
+4
View File
@@ -111,6 +111,10 @@
#define STATUS_EFFECT_LIMP /datum/status_effect/limp //For when you have a busted leg (or two!) and want additional slowdown when walking on that leg
#define STATUS_EFFECT_AMOK /datum/status_effect/amok //Makes the target automatically strike out at adjecent non-heretics.
#define STATUS_EFFECT_CLOUDSTRUCK /datum/status_effect/cloudstruck //blinds and applies an overlay.
/// shoves inflict this to indicate the next shove while this is in effect should disarm guns
#define STATUS_EFFECT_OFF_BALANCE /datum/status_effect/off_balance
+3
View File
@@ -24,7 +24,10 @@ GLOBAL_LIST_INIT(default_weight_class_to_volume, list(
// Let's keep all of this in one place. given what we put above anyways..
// volume amount for items
/// volume for a data disk
#define ITEM_VOLUME_DISK 1
/// volume for a shotgun stripper clip holding 4 shells
#define ITEM_VOLUME_STRIPPER_CLIP (DEFAULT_VOLUME_NORMAL * 0.5)
// #define SAMPLE_VOLUME_AMOUNT 2
+1 -7
View File
@@ -146,11 +146,11 @@
#define SSAIR_EQUALIZE 8
#define SSAIR_ACTIVETURFS 9
// |= on overlays is not actually guaranteed to not add same appearances but we're optimistically using it anyway.
#define COMPILE_OVERLAYS(A)\
if (TRUE) {\
var/list/ad = A.add_overlays;\
var/list/rm = A.remove_overlays;\
var/list/po = A.priority_overlays;\
if(LAZYLEN(rm)){\
A.overlays -= rm;\
A.remove_overlays = null;\
@@ -159,11 +159,5 @@
A.overlays |= ad;\
A.add_overlays = null;\
}\
if(LAZYLEN(po)){\
A.overlays |= po;\
}\
else{\
A.priority_overlays = null;\
}\
A.flags_1 &= ~OVERLAY_QUEUED_1;\
}
+4 -1
View File
@@ -104,7 +104,9 @@
#define TRAIT_RESISTCOLD "resist_cold"
#define TRAIT_RESISTHIGHPRESSURE "resist_high_pressure"
#define TRAIT_RESISTLOWPRESSURE "resist_low_pressure"
#define TRAIT_BOMBIMMUNE "bomb_immunity"
#define TRAIT_RADIMMUNE "rad_immunity"
#define TRAIT_GENELESS "geneless"
#define TRAIT_VIRUSIMMUNE "virus_immunity"
#define TRAIT_PIERCEIMMUNE "pierce_immunity"
#define TRAIT_NODISMEMBER "dismember_immunity"
@@ -257,6 +259,7 @@
#define CURSED_ITEM_TRAIT "cursed-item" // The item is magically cursed
#define ABSTRACT_ITEM_TRAIT "abstract-item"
#define STATUS_EFFECT_TRAIT "status-effect"
#define CLOTHING_TRAIT "clothing"
#define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention
#define GHOSTROLE_TRAIT "ghostrole"
#define APHRO_TRAIT "aphro"
@@ -311,4 +314,4 @@
#define ACTIVE_BLOCK_TRAIT "active_block"
/// This trait is added by the parry system.
#define ACTIVE_PARRY_TRAIT "active_parry"
#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name
#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name
+1
View File
@@ -75,6 +75,7 @@
#define VV_HK_MARK "mark"
#define VV_HK_ADDCOMPONENT "addcomponent"
#define VV_HK_MODIFY_TRAITS "modtraits"
#define VV_HK_VIEW_REFERENCES "viewreferences"
// /datum/gas_mixture
#define VV_HK_SET_MOLES "set_moles"
+5 -1
View File
@@ -128,6 +128,10 @@ GLOBAL_VAR_INIT(cmp_field, "name")
else
return B.required_temp - A.required_temp //return hottest
/proc/cmp_mob_realname_dsc(mob/A,mob/B)
return sorttext(A.real_name,B.real_name)
/proc/cmp_job_display_asc(datum/job/A, datum/job/B)
return A.display_order - B.display_order
@@ -135,4 +139,4 @@ GLOBAL_VAR_INIT(cmp_field, "name")
return sorttext(initial(b.name),initial(a.name))
/proc/cmp_typepaths_asc(A, B)
return sorttext("[B]","[A]")
return sorttext("[B]","[A]")
+5 -5
View File
@@ -17,9 +17,9 @@ For fast lookups, this is generated using regenerate_donator_grouping_list()
/proc/regenerate_donator_grouping_list()
GLOB.donators_by_group = list() //reinit everything
var/list/donator_list = GLOB.donators_by_group //cache
var/list/tier_1 = TIER_1_DONATORS
donator_list[DONATOR_GROUP_TIER_1] = tier_1.Copy() //The .Copy() is to "decouple"/make a new list, rather than letting the global list impact the config list.
var/list/tier_2 = tier_1 + TIER_2_DONATORS //Using + on lists implies making new lists, so we don't need to manually Copy().
var/list/tier_3 = TIER_3_DONATORS
donator_list[DONATOR_GROUP_TIER_3] = tier_3.Copy() //The .Copy() is to "decouple"/make a new list, rather than letting the global list impact the config list.
var/list/tier_2 = tier_3 + TIER_2_DONATORS //Using + on lists implies making new lists, so we don't need to manually Copy().
donator_list[DONATOR_GROUP_TIER_2] = tier_2
var/list/tier_3 = tier_2 + TIER_3_DONATORS
donator_list[DONATOR_GROUP_TIER_3] = tier_3
var/list/tier_1 = tier_2 + TIER_1_DONATORS
donator_list[DONATOR_GROUP_TIER_1] = tier_1
+4 -4
View File
@@ -37,10 +37,10 @@
//CIT CHANGES START HERE, ADDS SNOWFLAKE BODYPARTS AND MORE
//mammal bodyparts (fucking furries)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_snouts, GLOB.mam_snouts_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails_animated, GLOB.mam_tails_animated_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/mam_tails, GLOB.mam_tails_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/ears/mam_ears, GLOB.mam_ears_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts/mam_snouts, GLOB.mam_snouts_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails_animated/mam_tails_animated, GLOB.mam_tails_animated_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/taur, GLOB.taur_list)
//xeno parts (hiss?)
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_head, GLOB.xeno_head_list)
+7 -7
View File
@@ -93,16 +93,16 @@
if(!GLOB.mam_body_markings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list)
if(!GLOB.mam_tails_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/mam_tails, GLOB.mam_tails_list)
if(!GLOB.mam_ears_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/ears/mam_ears, GLOB.mam_ears_list)
if(!GLOB.mam_snouts_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_snouts, GLOB.mam_snouts_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts/mam_snouts, GLOB.mam_snouts_list)
//snowflake check so people's ckey features don't get randomly put on unmonkeys/spawns
var/list/snowflake_mam_tails_list = list()
for(var/mtpath in GLOB.mam_tails_list)
var/datum/sprite_accessory/mam_tails/instance = GLOB.mam_tails_list[mtpath]
var/datum/sprite_accessory/tails/mam_tails/instance = GLOB.mam_tails_list[mtpath]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
@@ -120,7 +120,7 @@
snowflake_markings_list[S.name] = mmpath
var/list/snowflake_ears_list = list()
for(var/mepath in GLOB.mam_ears_list)
var/datum/sprite_accessory/mam_ears/instance = GLOB.mam_ears_list[mepath]
var/datum/sprite_accessory/ears/mam_ears/instance = GLOB.mam_ears_list[mepath]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
@@ -129,7 +129,7 @@
snowflake_ears_list[S.name] = mepath
var/list/snowflake_mam_snouts_list = list()
for(var/mspath in GLOB.mam_snouts_list)
var/datum/sprite_accessory/mam_snouts/instance = GLOB.mam_snouts_list[mspath]
var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.mam_snouts_list[mspath]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
@@ -138,7 +138,7 @@
snowflake_mam_snouts_list[S.name] = mspath
var/list/snowflake_ipc_antenna_list = list()
for(var/mspath in GLOB.ipc_antennas_list)
var/datum/sprite_accessory/mam_snouts/instance = GLOB.ipc_antennas_list[mspath]
var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.ipc_antennas_list[mspath]
if(istype(instance, /datum/sprite_accessory))
var/datum/sprite_accessory/S = instance
if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies))
+17 -4
View File
@@ -11,15 +11,28 @@
#ifdef TESTING
#define DATUMVAR_DEBUGGING_MODE
//#define GC_FAILURE_HARD_LOOKUP //makes paths that fail to GC call find_references before del'ing.
//implies FIND_REF_NO_CHECK_TICK
/*
* Enables extools-powered reference tracking system, letting you see what is referencing objects that refuse to hard delete.
*
* * Requires TESTING to be defined to work.
*/
//#define REFERENCE_TRACKING
//#define FIND_REF_NO_CHECK_TICK //Sets world.loop_checks to false and prevents find references from sleeping
///Method of tracking references without using extools. Slower, kept to avoid over-reliance on extools.
//#define LEGACY_REFERENCE_TRACKING
#ifdef LEGACY_REFERENCE_TRACKING
///Use the legacy reference on things hard deleting by default.
//#define GC_FAILURE_HARD_LOOKUP
#ifdef GC_FAILURE_HARD_LOOKUP
#define FIND_REF_NO_CHECK_TICK
#endif //ifdef GC_FAILURE_HARD_LOOKUP
#endif //ifdef LEGACY_REFERENCE_TRACKING
//#define VISUALIZE_ACTIVE_TURFS //Highlights atmos active turfs in green
#endif
#endif //ifdef TESTING
//#define UNIT_TESTS //Enables unit tests via TEST_RUN_PARAMETER
#ifndef PRELOAD_RSC //set to:
+5 -1
View File
@@ -9,4 +9,8 @@ GLOBAL_DATUM(start_state, /datum/station_state) // Used in round-end report
//TODO clear this one up too
GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
///We want reality_smash_tracker to exist only once and be accesable from anywhere.
GLOBAL_DATUM_INIT(reality_smash_track, /datum/reality_smash_tracker, new)
+47 -1
View File
@@ -40,6 +40,46 @@ GLOBAL_LIST_EMPTY(insect_fluffs_list)
GLOBAL_LIST_EMPTY(insect_markings_list)
GLOBAL_LIST_EMPTY(caps_list)
//a way to index the right bodypart list given the type of bodypart
GLOBAL_LIST_INIT(mutant_reference_list, list(
"tail_lizard" = GLOB.tails_list_lizard,
"waggingtail_lizard" = GLOB.animated_tails_list_lizard,
"tail_human" = GLOB.tails_list_human,
"waggingtail_human" = GLOB.animated_tails_list_human,
"spines" = GLOB.spines_list,
"waggingspines" = GLOB.animated_spines_list,
"snout" = GLOB.snouts_list,
"frills" = GLOB.frills_list,
"horns" = GLOB.horns_list,
"ears" = GLOB.ears_list,
"body_markings" = GLOB.body_markings_list,
"wings" = GLOB.wings_list,
"wingsopen" = GLOB.wings_open_list,
"deco_wings" = GLOB.deco_wings_list,
"legs" = GLOB.legs_list,
"insect_wings" = GLOB.insect_wings_list,
"insect_fluff" = GLOB.insect_fluffs_list,
"insect_markings" = GLOB.insect_markings_list,
"caps" = GLOB.caps_list,
"ipc_screen" = GLOB.ipc_screens_list,
"ipc_antenna" = GLOB.ipc_antennas_list,
"mam_tail" = GLOB.mam_tails_list,
"mam_waggingtail" = GLOB.mam_tails_animated_list,
"mam_body_markings" = GLOB.mam_body_markings_list,
"mam_ears" = GLOB.mam_ears_list,
"mam_snouts" = GLOB.mam_snouts_list,
"taur" = GLOB.taur_list,
"xenodorsal" = GLOB.xeno_dorsal_list,
"xenohead" = GLOB.xeno_head_list,
"xenotail" = GLOB.xeno_tail_list))
//references wag types to regular types, wings open to wings, etc
GLOBAL_LIST_INIT(mutant_transform_list, list("wingsopen" = "wings",
"waggingtail_human" = "tail_human",
"waggingtail_lizard" = "tail_lizard",
"waggingspines" = "spines",
"mam_waggingtail" = "mam_tail"))
GLOBAL_LIST_INIT(ghost_forms_with_directions_list, list("ghost")) //stores the ghost forms that support directional sprites
GLOBAL_LIST_INIT(ghost_forms_with_accessories_list, list("ghost")) //stores the ghost forms that support hair and other such things
@@ -231,4 +271,10 @@ GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitt
GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc))
//locked parts are those that your picked species requires to have
//unlocked parts are those that anyone can choose on customisation regardless
//parts not in unlocked, but in all, are thus locked
GLOBAL_LIST_INIT(all_mutant_parts, list("tail_lizard" = "Tail", "mam_tail" = "Tail", "tail_human" = "Tail", "snout" = "Snout", "frills" = "Frills", "spines" = "Spines", "body_markings" = "Body Markings", "mam_body_markings" = "Species Markings" , "mam_ears" = "Ears", "ears" = "Ears", "mam_snouts" = "Snout", "legs" = "Legs", "deco_wings" = "Decorative Wings", "insect_wings" = "Insect Wings", "insect_fluff" = "Insect Fluff", "taur" = "Tauric Body", "insect_markings" = "Insect Markings", "wings" = "Wings", "xenohead" = "Caste Head", "xenotail" = "Tail", "xenodorsal" = "Dorsal Spines", "ipc_screen" = "Screen", "ipc_antenna" = "Antenna", "meat_type" = "Meat Type", "horns" = "Horns"))
GLOBAL_LIST_INIT(unlocked_mutant_parts, list("horns", "insect_fluff"))
//parts in either of the above two lists that require a second option that allows them to be coloured
GLOBAL_LIST_INIT(colored_mutant_parts, list("insect_wings" = "wings_color", "deco_wings" = "wings_color", "horns" = "horns_color"))
+2
View File
@@ -37,7 +37,9 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_RESISTCOLD" = TRAIT_RESISTCOLD,
"TRAIT_RESISTHIGHPRESSURE" = TRAIT_RESISTHIGHPRESSURE,
"TRAIT_RESISTLOWPRESSURE" = TRAIT_RESISTLOWPRESSURE,
"TRAIT_BOMBIMMUNE" = TRAIT_BOMBIMMUNE,
"TRAIT_RADIMMUNE" = TRAIT_RADIMMUNE,
"TRAIT_GENELESS" = TRAIT_GENELESS,
"TRAIT_VIRUSIMMUNE" = TRAIT_VIRUSIMMUNE,
"TRAIT_PIERCEIMMUNE" = TRAIT_PIERCEIMMUNE,
"TRAIT_NODISMEMBER" = TRAIT_NODISMEMBER,
+3 -3
View File
@@ -122,13 +122,13 @@
if(pixel_size == pixels)
return
pixel_size = pixels
cut_overlays(TRUE)
cut_overlays()
//our icon size is 32 pixels.
transform = matrix((pixels - (VOLUMETRIC_STORAGE_BOX_BORDER_SIZE * 2)) / VOLUMETRIC_STORAGE_BOX_ICON_SIZE, 0, 0, 0, 1, 0)
left.pixel_x = -((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE
right.pixel_x = ((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE
add_overlay(left, TRUE)
add_overlay(right, TRUE)
add_overlay(left)
add_overlay(right)
/obj/screen/storage/volumetric_edge
layer = VOLUMETRIC_STORAGE_BOX_LAYER
+1 -1
View File
@@ -32,4 +32,4 @@
/mob/camera/blob/AltClickOn(atom/A) //Remove a blob
var/turf/T = get_turf(A)
if(T)
remove_blob(T)
remove_blob(T)
@@ -98,6 +98,11 @@
config_entry_value = 6
min_val = 1
/datum/config_entry/number/ecult_scaling_coeff //how much does the amount of players get divided by to determine e_cult
config_entry_value = 6
integer = FALSE
min_val = 1
/datum/config_entry/number/security_scaling_coeff //how much does the amount of players get divided by to determine open security officer positions
config_entry_value = 8
min_val = 1
@@ -529,4 +534,4 @@
config_entry_value = 6
/datum/config_entry/number/max_shuttle_size
config_entry_value = 250
config_entry_value = 500
+1 -1
View File
@@ -29,7 +29,7 @@ SUBSYSTEM_DEF(acid)
if(O.acid_level && O.acid_processing())
else
O.cut_overlay(GLOB.acid_overlay, TRUE)
O.update_icon()
processing -= O
if (MC_TICK_CHECK)
+5
View File
@@ -0,0 +1,5 @@
PROCESSING_SUBSYSTEM_DEF(fluids)
name = "Fluids"
wait = 20
stat_tag = "FD" //its actually Fluid Ducts
flags = SS_NO_INIT | SS_TICKER
+22 -130
View File
@@ -25,7 +25,7 @@ SUBSYSTEM_DEF(garbage)
//Queue
var/list/queues
#ifdef TESTING
#ifdef LEGACY_REFERENCE_TRACKING
var/list/reference_find_on_fail = list()
var/list/reference_find_on_fail_types = list()
#endif
@@ -134,7 +134,7 @@ SUBSYSTEM_DEF(garbage)
++gcedlasttick
++totalgcs
pass_counts[level]++
#ifdef TESTING
#ifdef LEGACY_REFERENCE_TRACKING
reference_find_on_fail -= refID //It's deleted we don't care anymore.
#endif
if (MC_TICK_CHECK)
@@ -145,7 +145,9 @@ SUBSYSTEM_DEF(garbage)
fail_counts[level]++
switch (level)
if (GC_QUEUE_CHECK)
#ifdef TESTING
#ifdef REFERENCE_TRACKING
D.find_references()
#elif defined(LEGACY_REFERENCE_TRACKING)
if(reference_find_on_fail[refID])
D.find_references()
#ifdef GC_FAILURE_HARD_LOOKUP
@@ -156,7 +158,19 @@ SUBSYSTEM_DEF(garbage)
#endif
var/type = D.type
var/datum/qdel_item/I = items[type]
#ifdef TESTING
log_world("## TESTING: GC: -- \ref[D] | [type] was unable to be GC'd --")
for(var/c in GLOB.admins) //Using testing() here would fill the logs with ADMIN_VV garbage
var/client/admin = c
if(!check_rights_for(admin, R_ADMIN))
continue
to_chat(admin, "## TESTING: GC: -- [ADMIN_VV(D)] | [type] was unable to be GC'd --")
testing("GC: -- \ref[src] | [type] was unable to be GC'd --")
#endif
#ifdef REFERENCE_TRACKING
GLOB.deletion_failures += D //It should no longer be bothered by the GC, manual deletion only.
continue
#endif
I.failures++
if (GC_QUEUE_HARDDELETE)
HardDelete(D)
@@ -181,7 +195,7 @@ SUBSYSTEM_DEF(garbage)
var/gctime = world.time
var/refid = "\ref[D]"
#ifdef TESTING
#ifdef LEGACY_REFERENCE_TRACKING
if(reference_find_on_fail_types[D.type])
reference_find_on_fail["\ref[D]"] = TRUE
#endif
@@ -193,7 +207,7 @@ SUBSYSTEM_DEF(garbage)
queue[refid] = gctime
#ifdef TESTING
#ifdef LEGACY_REFERENCE_TRACKING
/datum/controller/subsystem/garbage/proc/add_type_to_findref(type)
if(!ispath(type))
return "NOT A VAILD PATH"
@@ -260,12 +274,6 @@ SUBSYSTEM_DEF(garbage)
/datum/qdel_item/New(mytype)
name = "[mytype]"
#ifdef TESTING
/proc/qdel_and_find_ref_if_fail(datum/D, force = FALSE)
SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE
qdel(D, force)
#endif
// Should be treated as a replacement for the 'del' keyword.
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
/proc/qdel(datum/D, force=FALSE, ...)
@@ -319,16 +327,13 @@ SUBSYSTEM_DEF(garbage)
SSgarbage.Queue(D, GC_QUEUE_HARDDELETE)
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
SSgarbage.HardDelete(D)
if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
#ifdef LEGACY_REFERENCE_TRACKING
if (QDEL_HINT_FINDREFERENCE) //qdel will, if LEGACY_REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion.
SSgarbage.Queue(D)
#ifdef TESTING
D.find_references()
#endif
if (QDEL_HINT_IFFAIL_FINDREFERENCE)
SSgarbage.Queue(D)
#ifdef TESTING
SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE
#endif
#endif
else
#ifdef TESTING
if(!I.no_hint)
@@ -339,119 +344,6 @@ SUBSYSTEM_DEF(garbage)
else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")
#ifdef TESTING
/datum/verb/find_refs()
set category = "Debug"
set name = "Find References"
set src in world
find_references(FALSE)
/datum/proc/find_references(skip_alert)
running_find_references = type
if(usr && usr.client)
if(usr.client.running_find_references)
testing("CANCELLED search for references to a [usr.client.running_find_references].")
usr.client.running_find_references = null
running_find_references = null
//restart the garbage collector
SSgarbage.can_fire = 1
SSgarbage.next_fire = world.time + world.tick_lag
return
if(!skip_alert)
if(alert("Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", "Yes", "No") == "No")
running_find_references = null
return
//this keeps the garbage collector from failing to collect objects being searched for in here
SSgarbage.can_fire = 0
if(usr && usr.client)
usr.client.running_find_references = type
testing("Beginning search for references to a [type].")
last_find_references = world.time
DoSearchVar(GLOB) //globals
for(var/datum/thing in world) //atoms (don't beleive it's lies)
DoSearchVar(thing, "World -> [thing]")
for (var/datum/thing) //datums
DoSearchVar(thing, "World -> [thing]")
for (var/client/thing) //clients
DoSearchVar(thing, "World -> [thing]")
testing("Completed search for references to a [type].")
if(usr && usr.client)
usr.client.running_find_references = null
running_find_references = null
//restart the garbage collector
SSgarbage.can_fire = 1
SSgarbage.next_fire = world.time + world.tick_lag
/datum/verb/qdel_then_find_references()
set category = "Debug"
set name = "qdel() then Find References"
set src in world
qdel(src, TRUE) //Force.
if(!running_find_references)
find_references(TRUE)
/datum/verb/qdel_then_if_fail_find_references()
set category = "Debug"
set name = "qdel() then Find References if GC failure"
set src in world
qdel_and_find_ref_if_fail(src, TRUE)
/datum/proc/DoSearchVar(X, Xname, recursive_limit = 64)
if(usr && usr.client && !usr.client.running_find_references)
return
if (!recursive_limit)
return
if(istype(X, /datum))
var/datum/D = X
if(D.last_find_references == last_find_references)
return
D.last_find_references = last_find_references
var/list/L = D.vars
for(var/varname in L)
if (varname == "vars")
continue
var/variable = L[varname]
if(variable == src)
testing("Found [src.type] \ref[src] in [D.type]'s [varname] var. [Xname]")
else if(islist(variable))
DoSearchVar(variable, "[Xname] -> list", recursive_limit-1)
else if(islist(X))
var/normal = IS_NORMAL_LIST(X)
for(var/I in X)
if (I == src)
testing("Found [src.type] \ref[src] in list [Xname].")
else if (I && !isnum(I) && normal && X[I] == src)
testing("Found [src.type] \ref[src] in list [Xname]\[[I]\]")
else if (islist(I))
DoSearchVar(I, "[Xname] -> list", recursive_limit-1)
#ifndef FIND_REF_NO_CHECK_TICK
CHECK_TICK
#endif
#endif
#ifdef TESTING
/proc/writeDatumCount()
var/list/datums = list()
+1 -1
View File
@@ -113,7 +113,7 @@ SUBSYSTEM_DEF(mapping)
// needs to be whitelisted for underground too so place_below ruins work
seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored, /area/icemoon/underground/unexplored), ice_ruins_templates)
for (var/ice_z in ice_ruins)
spawn_rivers(ice_z, 4, /turf/open/openspace/icemoon, /area/icemoon/surface/outdoors/unexplored/rivers)
spawn_rivers(ice_z, 4, /turf/open/transparent/openspace/icemoon, /area/icemoon/surface/outdoors/unexplored/rivers)
var/list/ice_ruins_underground = levels_by_trait(ZTRAIT_ICE_RUINS_UNDERGROUND)
if (ice_ruins_underground.len)
+8 -28
View File
@@ -114,67 +114,47 @@ SUBSYSTEM_DEF(overlays)
#define NOT_QUEUED_ALREADY (!(flags_1 & OVERLAY_QUEUED_1))
#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.queue += src;
/atom/proc/cut_overlays(priority = FALSE)
LAZYINITLIST(priority_overlays)
/atom/proc/cut_overlays()
LAZYINITLIST(remove_overlays)
LAZYINITLIST(add_overlays)
remove_overlays = overlays.Copy()
add_overlays.Cut()
if(priority)
priority_overlays.Cut()
//If not already queued for work and there are overlays to remove
if(NOT_QUEUED_ALREADY && remove_overlays.len)
QUEUE_FOR_COMPILE
/atom/proc/cut_overlay(list/overlays, priority)
/atom/proc/cut_overlay(list/overlays)
if(!overlays)
return
overlays = build_appearance_list(overlays)
LAZYINITLIST(add_overlays) //always initialized after this point
LAZYINITLIST(priority_overlays)
LAZYINITLIST(remove_overlays)
var/a_len = add_overlays.len
var/r_len = remove_overlays.len
var/p_len = priority_overlays.len
remove_overlays += overlays
add_overlays -= overlays
if(priority)
var/list/cached_priority = priority_overlays
LAZYREMOVE(cached_priority, overlays)
var/fa_len = add_overlays.len
var/fr_len = remove_overlays.len
var/fp_len = priority_overlays.len
//If not already queued and there is work to be done
if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len || fp_len != p_len))
if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len))
QUEUE_FOR_COMPILE
/atom/proc/add_overlay(list/overlays, priority = FALSE)
/atom/proc/add_overlay(list/overlays)
if(!overlays)
return
overlays = build_appearance_list(overlays)
LAZYINITLIST(add_overlays) //always initialized after this point
LAZYINITLIST(priority_overlays)
var/a_len = add_overlays.len
var/p_len = priority_overlays.len
if(priority)
priority_overlays += overlays //or in the image. Can we use [image] = image?
var/fp_len = priority_overlays.len
if(NOT_QUEUED_ALREADY && fp_len != p_len)
QUEUE_FOR_COMPILE
else
add_overlays += overlays
var/fa_len = add_overlays.len
if(NOT_QUEUED_ALREADY && fa_len != a_len)
QUEUE_FOR_COMPILE
add_overlays += overlays
var/fa_len = add_overlays.len
if(NOT_QUEUED_ALREADY && fa_len != a_len)
QUEUE_FOR_COMPILE
/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
if(!other)
@@ -4,16 +4,26 @@ PROCESSING_SUBSYSTEM_DEF(instruments)
init_order = INIT_ORDER_INSTRUMENTS
flags = SS_KEEP_TIMING
priority = FIRE_PRIORITY_INSTRUMENTS
var/static/list/datum/instrument/instrument_data = list() //id = datum
/// List of all instrument data, associative id = datum
var/static/list/datum/instrument/instrument_data = list()
/// List of all song datums.
var/static/list/datum/song/songs = list()
/// Max lines in songs
var/static/musician_maxlines = 600
/// Max characters per line in songs
var/static/musician_maxlinechars = 300
/// Deciseconds between hearchecks. Too high and instruments seem to lag when people are moving around in terms of who can hear it. Too low and the server lags from this.
var/static/musician_hearcheck_mindelay = 5
/// Maximum instrument channels total instruments are allowed to use. This is so you don't have instruments deadlocking all sound channels.
var/static/max_instrument_channels = MAX_INSTRUMENT_CHANNELS
/// Current number of channels allocated for instruments
var/static/current_instrument_channels = 0
/// Single cached list for synthesizer instrument ids, so you don't have to have a new list with every synthesizer.
var/static/list/synthesizer_instrument_ids
/datum/controller/subsystem/processing/instruments/Initialize()
initialize_instrument_data()
synthesizer_instrument_ids = get_allowed_instrument_ids()
return ..()
/datum/controller/subsystem/processing/instruments/proc/on_song_new(datum/song/S)
@@ -29,7 +39,10 @@ PROCESSING_SUBSYSTEM_DEF(instruments)
continue
I = new path
I.Initialize()
instrument_data[I.id || "[I.type]"] = I
if(!I.id)
qdel(I)
continue
instrument_data[I.id] = I
CHECK_TICK
/datum/controller/subsystem/processing/instruments/proc/get_instrument(id_or_path)
+1 -1
View File
@@ -157,7 +157,7 @@
/datum/action/proc/ApplyIcon(obj/screen/movable/action_button/current_button, force = FALSE)
if(icon_icon && button_icon_state && ((current_button.button_icon_state != button_icon_state) || force))
current_button.cut_overlays(TRUE)
current_button.cut_overlays()
current_button.add_overlay(mutable_appearance(icon_icon, button_icon_state))
current_button.button_icon_state = button_icon_state
@@ -40,13 +40,23 @@
reqs = list(/obj/item/paper = 20)
category = CAT_CLOTHING
/datum/crafting_recipe/balaclavabreath
name = "Breathaclava"
result = /obj/item/clothing/mask/balaclava/breath
time = 10
reqs = list(/obj/item/clothing/mask/balaclava = 1,
/obj/item/clothing/mask/breath = 1)
category = CAT_CLOTHING
/datum/crafting_recipe/armwraps
name = "Armwraps"
result = /obj/item/clothing/gloves/fingerless/pugilist
time = 60
tools = list(TOOL_WIRECUTTER)
reqs = list(/obj/item/stack/sheet/cloth = 4,
/obj/item/stack/sheet/durathread = 2,
/obj/item/stack/sticky_tape = 2,
/obj/item/stack/sheet/leather = 2)
category = CAT_CLOTHING
@@ -2,6 +2,15 @@
//Large Objects//
/////////////////
/datum/crafting_recipe/plunger
name = "Plunger"
result = /obj/item/plunger
time = 1
reqs = list(/obj/item/stack/sheet/plastic = 1,
/obj/item/stack/sheet/mineral/wood = 1)
category = CAT_MISC
subcategory = CAT_TOOL
/datum/crafting_recipe/showercurtain
name = "Shower Curtains"
reqs = list(/obj/item/stack/sheet/cloth = 2,
@@ -188,7 +197,7 @@
result = /obj/item/screwdriver/bronze
reqs = list(/obj/item/screwdriver = 1,
/obj/item/stack/cable_coil = 10,
/obj/item/stack/tile/bronze = 1,
/obj/item/stack/sheet/bronze = 1,
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
@@ -200,7 +209,7 @@
result = /obj/item/weldingtool/bronze
reqs = list(/obj/item/weldingtool = 1,
/obj/item/stack/cable_coil = 10,
/obj/item/stack/tile/bronze = 1,
/obj/item/stack/sheet/bronze = 1,
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
@@ -212,7 +221,7 @@
result = /obj/item/wirecutters/bronze
reqs = list(/obj/item/wirecutters = 1,
/obj/item/stack/cable_coil = 10,
/obj/item/stack/tile/bronze = 1,
/obj/item/stack/sheet/bronze = 1,
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
@@ -224,7 +233,7 @@
result = /obj/item/crowbar/bronze
reqs = list(/obj/item/crowbar = 1,
/obj/item/stack/cable_coil = 10,
/obj/item/stack/tile/bronze = 1,
/obj/item/stack/sheet/bronze = 1,
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
@@ -236,7 +245,7 @@
result = /obj/item/wrench/bronze
reqs = list(/obj/item/wrench = 1,
/obj/item/stack/cable_coil = 10,
/obj/item/stack/tile/bronze = 1,
/obj/item/stack/sheet/bronze = 1,
/datum/reagent/water = 15)
time = 40
subcategory = CAT_TOOL
@@ -269,6 +278,19 @@
subcategory = CAT_TOOL
category = CAT_MISC
/datum/crafting_recipe/heretic/codex
name = "Codex Cicatrix"
result = /obj/item/forbidden_book
tools = list(/obj/item/pen)
reqs = list(/obj/item/paper = 5,
/obj/item/organ/eyes = 1,
/obj/item/organ/heart = 1,
/obj/item/stack/sheet/animalhide/human = 1)
time = 150
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
always_availible = FALSE
////////////
//Vehicles//
////////////
@@ -324,7 +346,7 @@
result = /obj/item/toy/sword/cx
subcategory = CAT_MISCELLANEOUS
category = CAT_MISC
/datum/crafting_recipe/catgirlplushie
name = "Catgirl Plushie"
reqs = list(/obj/item/toy/plush/hairball = 3)
+5 -2
View File
@@ -119,7 +119,7 @@
UnregisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING))
if(overlay)
var/atom/A = parent
A.cut_overlay(overlay, TRUE)
UnregisterSignal(A,COMSIG_ATOM_UPDATE_OVERLAYS)
qdel(overlay)
return ..()
@@ -326,7 +326,8 @@
var/matrix/M = matrix()
M.Translate(pixelX, pixelY)
overlay.transform = M
hit.add_overlay(overlay, TRUE)
RegisterSignal(hit,COMSIG_ATOM_UPDATE_OVERLAYS,.proc/apply_overlay)
hit.update_icon()
if(harmful)
hit.visible_message("<span class='danger'>[weapon] embeds itself in [hit]!</span>")
@@ -339,6 +340,8 @@
else
hit.visible_message("<span class='danger'>[weapon] sticks itself to [hit]!</span>")
/datum/component/embedded/proc/apply_overlay(atom/source, list/overlay_list)
overlay_list += overlay
/datum/component/embedded/proc/examineTurf(datum/source, mob/user, list/examine_list)
if(harmful)
@@ -0,0 +1,215 @@
/datum/component/plumbing
///Index with "1" = /datum/ductnet/theductpointingnorth etc. "1" being the num2text from NORTH define
var/list/datum/ductnet/ducts = list()
///shortcut to our parents' reagent holder
var/datum/reagents/reagents
///TRUE if we wanna add proper pipe outless under our parent object. this is pretty good if i may so so myself
var/use_overlays = TRUE
///We can't just cut all of the parents' overlays, so we'll track them here
var/list/image/ducterlays
///directions in wich we act as a supplier
var/supply_connects
///direction in wich we act as a demander
var/demand_connects
///FALSE to pretty much just not exist in the plumbing world so we can be moved, TRUE to go plumbo mode
var/active = FALSE
///if TRUE connects will spin with the parent object visually and codually, so you can have it work in any direction. FALSE if you want it to be static
var/turn_connects = TRUE
/datum/component/plumbing/Initialize(start=TRUE, _turn_connects=TRUE) //turn_connects for wheter or not we spin with the object to change our pipes
if(parent && !istype(parent, /atom/movable))
return COMPONENT_INCOMPATIBLE
var/atom/movable/AM = parent
if(!AM.reagents)
return COMPONENT_INCOMPATIBLE
reagents = AM.reagents
turn_connects = _turn_connects
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED,COMSIG_PARENT_PREQDELETED), .proc/disable)
RegisterSignal(parent, list(COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH), .proc/toggle_active)
if(start)
enable()
if(use_overlays)
create_overlays()
/datum/component/plumbing/process()
if(!demand_connects || !reagents)
STOP_PROCESSING(SSfluids, src)
return
if(reagents.total_volume < reagents.maximum_volume)
for(var/D in GLOB.cardinals)
if(D & demand_connects)
send_request(D)
///Can we be added to the ductnet?
/datum/component/plumbing/proc/can_add(datum/ductnet/D, dir)
if(!active)
return
if(!dir || !D)
return FALSE
if(num2text(dir) in ducts)
return FALSE
return TRUE
///called from in process(). only calls process_request(), but can be overwritten for children with special behaviour
/datum/component/plumbing/proc/send_request(dir)
process_request(amount = MACHINE_REAGENT_TRANSFER, reagent = null, dir = dir)
///check who can give us what we want, and how many each of them will give us
/datum/component/plumbing/proc/process_request(amount, reagent, dir)
var/list/valid_suppliers = list()
var/datum/ductnet/net
if(!ducts.Find(num2text(dir)))
return
net = ducts[num2text(dir)]
for(var/A in net.suppliers)
var/datum/component/plumbing/supplier = A
if(supplier.can_give(amount, reagent, net))
valid_suppliers += supplier
for(var/A in valid_suppliers)
var/datum/component/plumbing/give = A
give.transfer_to(src, amount / valid_suppliers.len, reagent, net)
///returns TRUE when they can give the specified amount and reagent. called by process request
/datum/component/plumbing/proc/can_give(amount, reagent, datum/ductnet/net)
if(amount <= 0)
return
if(reagent) //only asked for one type of reagent
for(var/A in reagents.reagent_list)
var/datum/reagent/R = A
if(R.type == reagent)
return TRUE
else if(reagents.total_volume > 0) //take whatever
return TRUE
///this is where the reagent is actually transferred and is thus the finish point of our process()
/datum/component/plumbing/proc/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net)
if(!reagents || !target || !target.reagents)
return FALSE
if(reagent)
reagents.trans_id_to(target.parent, reagent, amount)
else
reagents.trans_to(target.parent, amount)
///We create our luxurious piping overlays/underlays, to indicate where we do what. only called once if use_overlays = TRUE in Initialize()
/datum/component/plumbing/proc/create_overlays()
var/atom/movable/AM = parent
for(var/image/I in ducterlays)
AM.overlays.Remove(I)
qdel(I)
ducterlays = list()
for(var/D in GLOB.cardinals)
var/color
var/direction
if(D & demand_connects)
color = "red" //red because red is mean and it takes
else if(D & supply_connects)
color = "blue" //blue is nice and gives
else
continue
var/image/I
if(turn_connects)
switch(D)
if(NORTH)
direction = "north"
if(SOUTH)
direction = "south"
if(EAST)
direction = "east"
if(WEST)
direction = "west"
I = image('icons/obj/plumbing/plumbers.dmi', "[direction]-[color]", layer = AM.layer - 1)
else
I = image('icons/obj/plumbing/plumbers.dmi', color, layer = AM.layer - 1) //color is not color as in the var, it's just the name
I.dir = D
AM.add_overlay(I)
ducterlays += I
///we stop acting like a plumbing thing and disconnect if we are, so we can safely be moved and stuff
/datum/component/plumbing/proc/disable()
if(!active)
return
STOP_PROCESSING(SSfluids, src)
for(var/A in ducts)
var/datum/ductnet/D = ducts[A]
D.remove_plumber(src)
active = FALSE
for(var/D in GLOB.cardinals)
if(D & (demand_connects | supply_connects))
for(var/obj/machinery/duct/duct in get_step(parent, D))
duct.attempt_connect()
///settle wherever we are, and start behaving like a piece of plumbing
/datum/component/plumbing/proc/enable()
if(active)
return
update_dir()
active = TRUE
var/atom/movable/AM = parent
for(var/obj/machinery/duct/D in AM.loc) //Destroy any ducts under us. Ducts also self destruct if placed under a plumbing machine. machines disable when they get moved
if(D.anchored) //that should cover everything
D.disconnect_duct()
if(demand_connects)
START_PROCESSING(SSfluids, src)
for(var/D in GLOB.cardinals)
if(D & (demand_connects | supply_connects))
for(var/atom/movable/A in get_step(parent, D))
if(istype(A, /obj/machinery/duct))
var/obj/machinery/duct/duct = A
duct.attempt_connect()
else
var/datum/component/plumbing/P = A.GetComponent(/datum/component/plumbing)
if(P)
direct_connect(P, D)
/// Toggle our machinery on or off. This is called by a hook from default_unfasten_wrench with anchored as only param, so we dont have to copypaste this on every object that can move
/datum/component/plumbing/proc/toggle_active(obj/O, new_state)
if(new_state)
enable()
else
disable()
/** We update our connects only when we settle down by taking our current and original direction to find our new connects
* If someone wants it to fucking spin while connected to something go actually knock yourself out
*/
/datum/component/plumbing/proc/update_dir()
if(!turn_connects)
return
var/atom/movable/AM = parent
var/new_demand_connects
var/new_supply_connects
var/new_dir = AM.dir
var/angle = 180 - dir2angle(new_dir)
if(new_dir == SOUTH)
demand_connects = initial(demand_connects)
supply_connects = initial(supply_connects)
else
for(var/D in GLOB.cardinals)
if(D & initial(demand_connects))
new_demand_connects += turn(D, angle)
if(D & initial(supply_connects))
new_supply_connects += turn(D, angle)
demand_connects = new_demand_connects
supply_connects = new_supply_connects
///Give the direction of a pipe, and it'll return wich direction it originally was when it's object pointed SOUTH
/datum/component/plumbing/proc/get_original_direction(dir)
var/atom/movable/AM = parent
return turn(dir, dir2angle(AM.dir) - 180)
//special case in-case we want to connect directly with another machine without a duct
/datum/component/plumbing/proc/direct_connect(datum/component/plumbing/P, dir)
if(!P.active)
return
var/opposite_dir = turn(dir, 180)
if(P.demand_connects & opposite_dir && supply_connects & dir || P.supply_connects & opposite_dir && demand_connects & dir) //make sure we arent connecting two supplies or demands
var/datum/ductnet/net = new()
net.add_plumber(src, dir)
net.add_plumber(P, opposite_dir)
///has one pipe input that only takes, example is manual output pipe
/datum/component/plumbing/simple_demand
demand_connects = NORTH
///has one pipe output that only supplies. example is liquid pump and manual input pipe
/datum/component/plumbing/simple_supply
supply_connects = NORTH
///input and output, like a holding tank
/datum/component/plumbing/tank
demand_connects = WEST
supply_connects = EAST
@@ -0,0 +1,21 @@
/datum/component/plumbing/acclimator
demand_connects = WEST
supply_connects = EAST
var/obj/machinery/plumbing/acclimator/AC
/datum/component/plumbing/acclimator/Initialize(start=TRUE, _turn_connects=TRUE)
. = ..()
if(!istype(parent, /obj/machinery/plumbing/acclimator))
return COMPONENT_INCOMPATIBLE
AC = parent
/datum/component/plumbing/acclimator/can_give(amount, reagent)
. = ..()
if(. && AC.emptying)
return TRUE
return FALSE
///We're overriding process and not send_request, because all process does is do the requests, so we might aswell cut out the middle man and save some code from running
/datum/component/plumbing/acclimator/process()
if(AC.emptying)
return
. = ..()
+59
View File
@@ -0,0 +1,59 @@
///The magical plumbing component used by the chemical filters. The different supply connects behave differently depending on the filters set on the chemical filter
/datum/component/plumbing/filter
demand_connects = NORTH
supply_connects = SOUTH | EAST | WEST //SOUTH is straight, EAST is left and WEST is right. We look from the perspective of the insert
/datum/component/plumbing/filter/Initialize()
. = ..()
if(!istype(parent, /obj/machinery/plumbing/filter))
return COMPONENT_INCOMPATIBLE
/datum/component/plumbing/filter/can_give(amount, reagent, datum/ductnet/net)
. = ..()
if(.)
var/direction
for(var/A in ducts)
if(ducts[A] == net)
direction = get_original_direction(text2num(A)) //we need it relative to the direction, so filters don't change when we turn the filter
break
if(!direction)
return FALSE
if(reagent)
if(!can_give_in_direction(direction, reagent))
return FALSE
/datum/component/plumbing/filter/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net)
if(!reagents || !target || !target.reagents)
return FALSE
var/direction
for(var/A in ducts)
if(ducts[A] == net)
direction = get_original_direction(text2num(A))
break
if(reagent)
reagents.trans_id_to(target.parent, reagent, amount)
else
for(var/A in reagents.reagent_list)
var/datum/reagent/R = A
if(!can_give_in_direction(direction, R.type))
continue
var/new_amount
if(R.volume < amount)
new_amount = amount - R.volume
reagents.trans_id_to(target.parent, R.type, amount)
amount = new_amount
if(amount <= 0)
break
///We check if the direction and reagent are valid to give. Needed for filters since different outputs have different behaviours
/datum/component/plumbing/filter/proc/can_give_in_direction(dir, reagent)
var/obj/machinery/plumbing/filter/F = parent
switch(dir)
if(SOUTH) //straight
if(!F.left.Find(reagent) && !F.right.Find(reagent))
return TRUE
if(WEST) //right
if(F.right.Find(reagent))
return TRUE
if(EAST) //left
if(F.left.Find(reagent))
return TRUE
@@ -0,0 +1,38 @@
/datum/component/plumbing/reaction_chamber
demand_connects = WEST
supply_connects = EAST
/datum/component/plumbing/reaction_chamber/Initialize(start=TRUE, _turn_connects=TRUE)
. = ..()
if(!istype(parent, /obj/machinery/plumbing/reaction_chamber))
return COMPONENT_INCOMPATIBLE
/datum/component/plumbing/reaction_chamber/can_give(amount, reagent, datum/ductnet/net)
. = ..()
var/obj/machinery/plumbing/reaction_chamber/RC = parent
if(!. || !RC.emptying)
return FALSE
/datum/component/plumbing/reaction_chamber/send_request(dir)
var/obj/machinery/plumbing/reaction_chamber/RC = parent
if(RC.emptying || !LAZYLEN(RC.required_reagents))
return
for(var/RT in RC.required_reagents)
var/has_reagent = FALSE
for(var/A in reagents.reagent_list)
var/datum/reagent/RD = A
if(RT == RD.type)
has_reagent = TRUE
if(RD.volume < RC.required_reagents[RT])
process_request(min(RC.required_reagents[RT] - RD.volume, MACHINE_REAGENT_TRANSFER) , RT, dir)
return
if(!has_reagent)
process_request(min(RC.required_reagents[RT], MACHINE_REAGENT_TRANSFER), RT, dir)
return
RC.reagent_flags &= ~NO_REACT
reagents.handle_reactions()
RC.emptying = TRUE //If we move this up, it'll instantly get turned off since any reaction always sets the reagent_total to zero. Other option is make the reaction update
//everything for every chemical removed, wich isn't a good option either.
RC.on_reagent_change() //We need to check it now, because some reactions leave nothing left.
@@ -0,0 +1,45 @@
/datum/component/plumbing/splitter
demand_connects = NORTH
supply_connects = SOUTH | EAST
/datum/component/plumbing/splitter/Initialize()
. = ..()
if(. && !istype(parent, /obj/machinery/plumbing/splitter))
return FALSE
/datum/component/plumbing/splitter/can_give(amount, reagent, datum/ductnet/net)
. = ..()
if(!.)
return
. = FALSE
var/direction
for(var/A in ducts)
if(ducts[A] == net)
direction = get_original_direction(text2num(A))
break
var/obj/machinery/plumbing/splitter/S = parent
switch(direction)
if(SOUTH)
if(S.turn_straight && S.transfer_straight <= amount)
S.turn_straight = FALSE
return TRUE
if(EAST)
if(!S.turn_straight && S.transfer_side <= amount)
S.turn_straight = TRUE
return TRUE
/datum/component/plumbing/splitter/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net)
var/direction
for(var/A in ducts)
if(ducts[A] == net)
direction = get_original_direction(text2num(A))
break
var/obj/machinery/plumbing/splitter/S = parent
switch(direction)
if(SOUTH)
if(amount >= S.transfer_straight)
amount = S.transfer_straight
if(EAST)
if(amount >= S.transfer_side)
amount = S.transfer_side
. = ..()
+18 -20
View File
@@ -14,6 +14,7 @@
var/mob/living/holder //who is currently benefiting from the shield.
var/dissipating = FALSE //Is this shield meant to dissipate over time instead of recharging.
var/del_on_overload = FALSE //will delete itself once it has no charges left.
var/cached_vis_overlay //text identifier of the visual overlay.
/datum/component/shielded/Initialize(current, max = 3, delay = 20 SECONDS, rate = 1, slots, state = "shield-old", broken, \
sound = 'sound/magic/charge.ogg', end_sound = 'sound/machines/ding.ogg', diss = FALSE, del_overload = FALSE)
@@ -47,9 +48,8 @@
holder = L
var/to_add = charges >= 1 ? shield_state : broken_state
if(to_add)
var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add)
M.layer = (L.layer > MOB_LAYER ? L.layer : MOB_LAYER) + 0.01
holder.add_overlay(M, TRUE)
var/layer = (L.layer > MOB_LAYER ? L.layer : MOB_LAYER) + 0.01
SSvis_overlays.add_vis_overlay(L, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, L.dir)
/datum/component/shielded/UnregisterFromParent()
. = ..()
@@ -57,9 +57,9 @@
UnregisterSignal(parent, list(COMSIG_ITEM_RUN_BLOCK,COMSIG_ITEM_CHECK_BLOCK,COMSIG_ITEM_EQUIPPED,COMSIG_ITEM_DROPPED))
if(holder)
UnregisterSignal(holder, list(COMSIG_LIVING_RUN_BLOCK, COMSIG_LIVING_GET_BLOCKING_ITEMS))
var/to_remove = charges >= 1 ? shield_state : broken_state
if(to_remove)
holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE)
if(cached_vis_overlay)
SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay)
cached_vis_overlay = null
holder = null
/datum/component/shielded/process()
@@ -80,7 +80,7 @@
holder.visible_message("[holder]'s shield overloads!")
qdel(src)
return
if(holder && (old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1))
if(holder && ((old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1)))
update_shield_overlay(charges < 1)
/datum/component/shielded/proc/adjust_charges(amount)
@@ -93,20 +93,19 @@
holder.visible_message("[holder]'s shield overloads!")
qdel(src)
return
if(holder && (old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1))
if(holder && ((old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1)))
update_shield_overlay(charges < 1)
/datum/component/shielded/proc/update_shield_overlay(broken)
if(!holder)
return
var/to_remove = broken ? shield_state : broken_state
var/to_add = broken ? broken_state : shield_state
if(to_remove)
holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE)
if(cached_vis_overlay)
SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay)
cached_vis_overlay = null
if(to_add)
var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add)
M.layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
holder.add_overlay(M, TRUE)
var/layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
SSvis_overlays.add_vis_overlay(holder, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, holder.dir)
/datum/component/shielded/proc/on_equip(obj/item/source, mob/living/equipper, slot)
if(!(accepted_slots & slotdefine2slotbit(slot)))
@@ -117,17 +116,16 @@
RegisterSignal(equipper, COMSIG_LIVING_GET_BLOCKING_ITEMS, .proc/include_shield)
var/to_add = charges >= 1 ? shield_state : broken_state
if(to_add)
var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add)
M.layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
equipper.add_overlay(M, TRUE)
var/layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01
cached_vis_overlay = SSvis_overlays.add_vis_overlay(holder, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, holder.dir)
/datum/component/shielded/proc/on_drop(obj/item/source, mob/dropper)
if(holder == dropper)
UnregisterSignal(holder, COMSIG_LIVING_GET_BLOCKING_ITEMS)
UnregisterSignal(parent, list(COMSIG_ITEM_RUN_BLOCK, COMSIG_ITEM_CHECK_BLOCK))
var/to_remove = charges >= 1 ? shield_state : broken_state
if(to_remove)
holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE)
if(cached_vis_overlay)
SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay)
cached_vis_overlay = null
holder = null
/datum/component/shielded/proc/include_shield(mob/source, list/items)
+4 -2
View File
@@ -29,8 +29,8 @@ GLOBAL_LIST_EMPTY(uplinks)
var/saved_player_population = 0
var/list/filters = list()
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate, datum/traitor_class/traitor_class)
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/traitor_class/traitor_class)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
@@ -144,6 +144,8 @@ GLOBAL_LIST_EMPTY(uplinks)
return COMPONENT_NO_INTERACT
/datum/component/uplink/ui_state(mob/user)
if(istype(parent, /obj/item/implant/uplink))
return GLOB.not_incapacitated_state
return GLOB.inventory_state
/datum/component/uplink/ui_interact(mob/user, datum/tgui/ui)
+3
View File
@@ -31,6 +31,9 @@
VV_DROPDOWN_OPTION(VV_HK_EXPOSE, "Show VV To Player")
VV_DROPDOWN_OPTION(VV_HK_ADDCOMPONENT, "Add Component/Element")
VV_DROPDOWN_OPTION(VV_HK_MODIFY_TRAITS, "Modify Traits")
#ifdef REFERENCE_TRACKING
VV_DROPDOWN_OPTION(VV_HK_VIEW_REFERENCES, "View References")
#endif
//This proc is only called if everything topic-wise is verified. The only verifications that should happen here is things like permission checks!
//href_list is a reference, modifying it in these procs WILL change the rest of the proc in topic.dm of admin/view_variables!
@@ -31,4 +31,3 @@
/datum/symptom/inorganic_adaptation/OnRemove(datum/disease/advance/A)
A.infectable_biotypes &= ~MOB_MINERAL
+2 -2
View File
@@ -137,10 +137,10 @@
L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"], 6)
L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"], 6)
if(!GLOB.mam_tails_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/mam_tails, GLOB.mam_tails_list)
L[DNA_MUTANTTAIL_BLOCK] = construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len)
if(!GLOB.mam_ears_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/ears/mam_ears, GLOB.mam_ears_list)
L[DNA_MUTANTEAR_BLOCK] = construct_block(GLOB.mam_ears_list.Find(features["mam_ears"]), GLOB.mam_ears_list.len)
if(!GLOB.mam_body_markings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list)
+65
View File
@@ -0,0 +1,65 @@
///We handle the unity part of plumbing. We track who is connected to who.
/datum/ductnet
var/list/suppliers = list()
var/list/demanders = list()
var/list/obj/machinery/duct/ducts = list()
var/capacity
///Add a duct to our network
/datum/ductnet/proc/add_duct(obj/machinery/duct/D)
if(!D || (D in ducts))
return
ducts += D
D.duct = src
///Remove a duct from our network and commit suicide, because this is probably easier than to check who that duct was connected to and what part of us was lost
/datum/ductnet/proc/remove_duct(obj/machinery/duct/ducting)
destroy_network(FALSE)
for(var/obj/machinery/duct/D in ducting.neighbours)
addtimer(CALLBACK(D, /obj/machinery/duct/proc/reconnect), 0) //all needs to happen after the original duct that was destroyed finishes destroying itself
addtimer(CALLBACK(D, /obj/machinery/duct/proc/generate_connects), 0)
qdel(src)
///add a plumbing object to either demanders or suppliers
/datum/ductnet/proc/add_plumber(datum/component/plumbing/P, dir)
if(!P.can_add(src, dir))
return FALSE
P.ducts[num2text(dir)] = src
if(dir & P.supply_connects)
suppliers += P
else if(dir & P.demand_connects)
demanders += P
return TRUE
///remove a plumber. we dont delete ourselves because ductnets dont persist through plumbing objects
/datum/ductnet/proc/remove_plumber(datum/component/plumbing/P)
suppliers.Remove(P) //we're probably only in one of these, but Remove() is inherently sane so this is fine
demanders.Remove(P)
for(var/dir in P.ducts)
if(P.ducts[dir] == src)
P.ducts -= dir
if(!ducts.len) //there were no ducts, so it was a direct connection. we destroy ourselves since a ductnet with only one plumber and no ducts is worthless
destroy_network()
///we combine ductnets. this occurs when someone connects to seperate sets of fluid ducts
/datum/ductnet/proc/assimilate(datum/ductnet/D)
ducts.Add(D.ducts)
suppliers.Add(D.suppliers)
demanders.Add(D.demanders)
for(var/A in D.suppliers + D.demanders)
var/datum/component/plumbing/P = A
for(var/s in P.ducts)
if(P.ducts[s] != D)
continue
P.ducts[s] = src //all your ducts are belong to us
for(var/A in D.ducts)
var/obj/machinery/duct/M = A
M.duct = src //forget your old master
destroy_network()
///destroy the network and tell all our ducts and plumbers we are gone
/datum/ductnet/proc/destroy_network(delete=TRUE)
for(var/A in suppliers + demanders)
remove_plumber(A)
for(var/A in ducts)
var/obj/machinery/duct/D = A
D.duct = null
if(delete) //I don't want code to run with qdeleted objects because that can never be good, so keep this in-case the ductnet has some business left to attend to before commiting suicide
qdel(src)
+10
View File
@@ -0,0 +1,10 @@
//blocks bluespace artillery beams that try to fly through
//look not all elements need to be fancy
/datum/element/bsa_blocker/Attach(datum/target)
if(!isatom(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_ATOM_BSA_BEAM, .proc/block_bsa)
return ..()
/datum/element/bsa_blocker/proc/block_bsa()
return COMSIG_ATOM_BLOCKS_BSA_BEAM
+16 -21
View File
@@ -33,39 +33,34 @@
if(description)
RegisterSignal(A, COMSIG_PARENT_EXAMINE, .proc/examine)
apply(A, TRUE)
num_decals_per_atom[A]++
apply(A)
/datum/element/decal/Detach(datum/target)
var/atom/A = target
remove(A, A.dir)
UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE))
LAZYREMOVE(num_decals_per_atom, A)
num_decals_per_atom[A]--
apply(A, TRUE)
if(!num_decals_per_atom[A])
UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS))
LAZYREMOVE(num_decals_per_atom, A)
return ..()
/datum/element/decal/proc/remove(atom/target, old_dir)
pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(old_dir))
for(var/i in 1 to num_decals_per_atom[target])
target.cut_overlay(pic, TRUE)
/datum/element/decal/proc/apply(atom/target, removing = FALSE)
if(num_decals_per_atom[target] == 1 && !removing)
RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_overlay, TRUE)
target.update_icon()
if(isitem(target))
addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
/datum/element/decal/proc/apply(atom/target, init = FALSE)
pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(target.dir))
if(init)
target.add_overlay(pic, TRUE)
else
for(var/i in 1 to num_decals_per_atom[target])
target.add_overlay(pic, TRUE)
if(isitem(target))
addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
/datum/element/decal/proc/apply_overlay(atom/source, list/overlay_list)
pic.dir = first_dir == NORTH ? source.dir : turn(first_dir, dir2angle(source.dir))
for(var/i in 1 to num_decals_per_atom[source])
overlay_list += pic
/datum/element/decal/proc/rotate_react(datum/source, old_dir, new_dir)
/datum/element/decal/proc/rotate_react(atom/source, old_dir, new_dir)
if(old_dir == new_dir)
return
remove(source, old_dir)
apply(source)
source.update_icon()
/datum/element/decal/proc/clean_react(datum/source, strength)
if(strength >= cleanable)
+2 -1
View File
@@ -28,7 +28,8 @@ GLOBAL_LIST_INIT(huds, list(
ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(),
ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_BLOODSUCKER = new/datum/atom_hud/antag/bloodsucker(),
ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag()
ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag(),
ANTAG_HUD_HERETIC = new/datum/atom_hud/antag/hidden()
))
/datum/atom_hud
+1 -1
View File
@@ -287,7 +287,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
desc = "Clock Cult? Never heard of it."
color = "#92661A"
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
sheet_type = /obj/item/stack/tile/bronze
sheet_type = /obj/item/stack/sheet/bronze
value_per_unit = 0.025
armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5)
beauty_modifier = 0.2
@@ -162,6 +162,11 @@
mood_change = -8
timeout = 3 MINUTES
/datum/mood_event/gates_of_mansus
description = "<span class='boldwarning'>LIVING IN A PERFORMANCE IS WORSE THAN DEATH</span>\n"
mood_change = -25
timeout = 4 MINUTES
//These are unused so far but I want to remember them to use them later
/datum/mood_event/cloned_corpse
@@ -70,6 +70,11 @@
mood_change = 40 //maybe being a cultist isnt that bad after all
hidden = TRUE
/datum/mood_event/heretics
description = "<span class='nicegreen'>THE HIGHER I RISE, THE MORE I SEE.</span>\n"
mood_change = 12 //maybe being a cultist isnt that bad after all
hidden = TRUE
/datum/mood_event/family_heirloom
description = "<span class='nicegreen'>My family heirloom is safe with me.</span>\n"
mood_change = 1
+6
View File
@@ -325,6 +325,12 @@
name = "Abductor Replication Lab"
description = "Some scientists tried and almost succeeded to recreate abductor tools. Somewhat slower and a bit less modern than their originals, these tools are the best you can get if you aren't an alien."
/datum/map_template/ruin/space/spacediner
id = "spacediner"
suffix = "spacediner.dmm"
name = "Space Diner"
description = "Come, traveler of the bluespace planes. Sit, enjoy a drink and take one of the fair maidens for a night. The exit is the way you came in, via that teleporter thingy, but do remember to stay safe."
//Space ruins for the station z
/datum/map_template/ruin/spacenearstation
prefix = "_maps/RandomRuins/SpaceRuinsStation/"
+191
View File
@@ -403,6 +403,197 @@
owner.underlays -= marked_underlay //if this is being called, we should have an owner at this point.
..()
/datum/status_effect/eldritch
duration = 15 SECONDS
status_type = STATUS_EFFECT_REPLACE
alert_type = null
on_remove_on_mob_delete = TRUE
///underlay used to indicate that someone is marked
var/mutable_appearance/marked_underlay
///path for the underlay
var/effect_sprite = ""
/datum/status_effect/eldritch/on_creation(mob/living/new_owner, ...)
marked_underlay = mutable_appearance('icons/effects/effects.dmi', effect_sprite,BELOW_MOB_LAYER)
return ..()
/datum/status_effect/eldritch/on_apply()
. = ..()
if(owner.mob_size >= MOB_SIZE_HUMAN)
RegisterSignal(owner,COMSIG_ATOM_UPDATE_OVERLAYS,.proc/update_owner_underlay)
owner.update_icon()
return TRUE
return FALSE
/datum/status_effect/eldritch/on_remove()
UnregisterSignal(owner,COMSIG_ATOM_UPDATE_OVERLAYS)
owner.update_icon()
return ..()
/datum/status_effect/eldritch/proc/update_owner_underlay(atom/source, list/overlays)
overlays += marked_underlay
/datum/status_effect/eldritch/Destroy()
QDEL_NULL(marked_underlay)
return ..()
/**
* What happens when this mark gets popped
*
* Adds actual functionality to each mark
*/
/datum/status_effect/eldritch/proc/on_effect()
playsound(owner, 'sound/magic/repulse.ogg', 75, TRUE)
qdel(src) //what happens when this is procced.
//Each mark has diffrent effects when it is destroyed that combine with the mansus grasp effect.
/datum/status_effect/eldritch/flesh
id = "flesh_mark"
effect_sprite = "emark1"
/datum/status_effect/eldritch/flesh/on_effect()
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
var/obj/item/bodypart/bodypart = pick(H.bodyparts)
var/datum/wound/slash/severe/crit_wound = new
crit_wound.apply_wound(bodypart)
return ..()
/datum/status_effect/eldritch/ash
id = "ash_mark"
effect_sprite = "emark2"
///Dictates how much damage and stamina loss this mark will cause.
var/repetitions = 1
/datum/status_effect/eldritch/ash/on_creation(mob/living/new_owner, _repetition = 5)
. = ..()
repetitions = min(1,_repetition)
/datum/status_effect/eldritch/ash/on_effect()
if(iscarbon(owner))
var/mob/living/carbon/carbon_owner = owner
carbon_owner.adjustStaminaLoss(10 * repetitions)
carbon_owner.adjustFireLoss(5 * repetitions)
for(var/mob/living/carbon/victim in range(1,carbon_owner))
if(IS_HERETIC(victim) || victim == carbon_owner)
continue
victim.apply_status_effect(type,repetitions-1)
break
return ..()
/datum/status_effect/eldritch/rust
id = "rust_mark"
effect_sprite = "emark3"
/datum/status_effect/eldritch/rust/on_effect()
if(!iscarbon(owner))
return
var/mob/living/carbon/carbon_owner = owner
for(var/obj/item/I in carbon_owner.get_all_gear()) //Affects roughly 75% of items
if(!QDELETED(I) && prob(75)) //Just in case
I.take_damage(100)
return ..()
/datum/status_effect/corrosion_curse
id = "corrosion_curse"
status_type = STATUS_EFFECT_REPLACE
alert_type = null
tick_interval = 1 SECONDS
/datum/status_effect/corrosion_curse/on_creation(mob/living/new_owner, ...)
. = ..()
to_chat(owner, "<span class='danger'>Your feel your body starting to break apart...</span>")
/datum/status_effect/corrosion_curse/tick()
. = ..()
if(!ishuman(owner))
return
var/mob/living/carbon/human/H = owner
var/chance = rand(0,100)
switch(chance)
if(0 to 19)
H.vomit()
if(20 to 29)
H.Dizzy(10)
if(30 to 39)
H.adjustOrganLoss(ORGAN_SLOT_LIVER,5)
if(40 to 49)
H.adjustOrganLoss(ORGAN_SLOT_HEART,5)
if(50 to 59)
H.adjustOrganLoss(ORGAN_SLOT_STOMACH,5)
if(60 to 69)
H.adjustOrganLoss(ORGAN_SLOT_EYES,10)
if(70 to 79)
H.adjustOrganLoss(ORGAN_SLOT_EARS,10)
if(80 to 89)
H.adjustOrganLoss(ORGAN_SLOT_LUNGS,10)
if(90 to 99)
H.adjustOrganLoss(ORGAN_SLOT_TONGUE,10)
if(100)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN,20)
/datum/status_effect/amok
id = "amok"
status_type = STATUS_EFFECT_REPLACE
alert_type = null
duration = 10 SECONDS
tick_interval = 1 SECONDS
/datum/status_effect/amok/on_apply(mob/living/afflicted)
. = ..()
to_chat(owner, "<span class='boldwarning'>Your feel filled with a rage that is not your own!</span>")
/datum/status_effect/amok/tick()
. = ..()
var/prev_intent = owner.a_intent
owner.a_intent = INTENT_HARM
var/list/mob/living/targets = list()
for(var/mob/living/potential_target in oview(owner, 1))
if(IS_HERETIC(potential_target) || potential_target.mind?.has_antag_datum(/datum/antagonist/heretic_monster))
continue
targets += potential_target
if(LAZYLEN(targets))
owner.log_message(" attacked someone due to the amok debuff.", LOG_ATTACK) //the following attack will log itself
owner.ClickOn(pick(targets))
owner.a_intent = prev_intent
/datum/status_effect/cloudstruck
id = "cloudstruck"
status_type = STATUS_EFFECT_REPLACE
duration = 3 SECONDS
on_remove_on_mob_delete = TRUE
///This overlay is applied to the owner for the duration of the effect.
var/mutable_appearance/mob_overlay
/datum/status_effect/cloudstruck/on_creation(mob/living/new_owner, set_duration)
if(isnum(set_duration))
duration = set_duration
. = ..()
/datum/status_effect/cloudstruck/on_apply()
. = ..()
mob_overlay = mutable_appearance('icons/effects/eldritch.dmi', "cloud_swirl", ABOVE_MOB_LAYER)
owner.overlays += mob_overlay
owner.update_icon()
ADD_TRAIT(owner, TRAIT_BLIND, "cloudstruck")
return TRUE
/datum/status_effect/cloudstruck/on_remove()
. = ..()
if(QDELETED(owner))
return
REMOVE_TRAIT(owner, TRAIT_BLIND, "cloudstruck")
if(owner)
owner.overlays -= mob_overlay
owner.update_icon()
/datum/status_effect/cloudstruck/Destroy()
. = ..()
QDEL_NULL(mob_overlay)
/datum/status_effect/stacking/saw_bleed
id = "saw_bleed"
tick_interval = 6
+5 -3
View File
@@ -53,8 +53,6 @@
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
if(!A.hasSiliconAccessInArea(user) && A.isElectrified() && A.shock(user, 100))
return FALSE
if(A.panel_open)
return TRUE
@@ -73,6 +71,8 @@
/datum/wires/airlock/on_pulse(wire)
set waitfor = FALSE
var/obj/machinery/door/airlock/A = holder
if(!A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100))
return FALSE
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power.
A.loseMainPower()
@@ -127,6 +127,8 @@
/datum/wires/airlock/on_cut(wire, mend)
var/obj/machinery/door/airlock/A = holder
if(!A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100))
return FALSE
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power.
if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2))
@@ -174,4 +176,4 @@
A.update_icon()
if(WIRE_ZAP1, WIRE_ZAP2) // Ouch.
if(isliving(usr))
A.shock(usr, 50)
A.shock(usr, 50)
+8 -2
View File
@@ -26,7 +26,6 @@
var/list/atom_colours //used to store the different colors on an atom
//its inherent color, the colored paint applied on it, special color effect etc...
var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
var/list/remove_overlays // a very temporary list of overlays to remove
var/list/add_overlays // a very temporary list of overlays to add
@@ -145,7 +144,6 @@
qdel(reagents)
LAZYCLEARLIST(overlays)
LAZYCLEARLIST(priority_overlays)
for(var/i in targeted_by)
var/mob/M = i
@@ -1121,3 +1119,11 @@
max_grav = max(G.setting,max_grav)
return max_grav
return SSmapping.level_trait(T.z, ZTRAIT_GRAVITY)
/**
* Causes effects when the atom gets hit by a rust effect from heretics
*
* Override this if you want custom behaviour in whatever gets hit by the rust
*/
/atom/proc/rust_heretic_act()
return
+7
View File
@@ -646,3 +646,10 @@
animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING)
sleep(1)
animate(I, alpha = 0, transform = matrix(), time = 1)
/atom/movable/proc/set_anchored(anchorvalue) //literally only for plumbing ran
SHOULD_CALL_PARENT(TRUE)
if(anchored == anchorvalue)
return
. = anchored
anchored = anchorvalue
+1 -2
View File
@@ -224,8 +224,7 @@ Credit where due:
qdel(S)
if(S && !QDELETED(S))
to_chat(L, "<span class='alloy'>[slot] is a <b>clockwork slab</b>, a multipurpose tool used to construct machines and invoke ancient words of power. If this is your first time \
as a servant, you can find a concise tutorial in the Recollection category of its interface.</span>")
to_chat(L, "<span class='alloy italics'>If you want more information, you can read <a href=\"https://tgstation13.org/wiki/Clockwork_Cult\">the wiki page</a> to learn more.</span>")
as a servant, you can read <a href=\"https://citadel-station.net/wikimain/index.php?title=Clockwork_Cult\">the wiki page</a> to learn more.</span>")
return TRUE
return FALSE
@@ -191,6 +191,24 @@
SSticker.mode_result = "loss - rev heads killed"
SSticker.news_report = REVS_LOSE
//////////////////////////////////////////////
// //
// HERETIC SMUGGLER //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/latejoin/heretic_smuggler
name = "Heretic Smuggler"
antag_datum = /datum/antagonist/heretic
antag_flag = ROLE_HERETIC
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
restricted_roles = list("AI","Cyborg")
required_candidates = 1
weight = 4
cost = 10
requirements = list(40,30,20,10,10,10,10,10,10,10)
repeatable = TRUE
//////////////////////////////////////////////
// //
// BLOODSUCKERS //
@@ -143,6 +143,46 @@
changeling.add_antag_datum(new_antag)
return TRUE
//////////////////////////////////////////////
// //
// ELDRITCH CULT //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/roundstart/heretics
name = "Heretics"
antag_flag = ROLE_HERETIC
antag_datum = /datum/antagonist/heretic
protected_roles = list("Prisoner","Security Officer", "Warden", "Detective", "Head of Security", "Captain")
restricted_roles = list("AI", "Cyborg")
required_candidates = 1
weight = 3
cost = 20
scaling_cost = 15
requirements = list(50,45,45,40,35,20,20,15,10,10)
antag_cap = list(1,1,1,1,2,2,2,2,3,3)
/datum/dynamic_ruleset/roundstart/heretics/pre_execute()
. = ..()
var/num_ecult = antag_cap[indice_pop] * (scaled_times + 1)
for (var/i = 1 to num_ecult)
var/mob/picked_candidate = pick_n_take(candidates)
assigned += picked_candidate.mind
picked_candidate.mind.restricted_roles = restricted_roles
picked_candidate.mind.special_role = ROLE_HERETIC
return TRUE
/datum/dynamic_ruleset/roundstart/heretics/execute()
for(var/c in assigned)
var/datum/mind/cultie = c
var/datum/antagonist/heretic/new_antag = new antag_datum()
cultie.add_antag_datum(new_antag)
return TRUE
//////////////////////////////////////////////
// //
// WIZARDS //
@@ -50,10 +50,6 @@ Property weights are:
for(var/r in SSevents.running)
var/datum/round_event/R = r
threat += R.threat()
for(var/mob/living/simple_animal/hostile/H in GLOB.mob_living_list)
var/turf/T = get_turf(H)
if(H.stat != DEAD && is_station_level(T.z) && !("Station" in H.faction))
threat += H.threat()
for(var/obj/item/phylactery/P in GLOB.poi_list)
threat += 25 // can't be giving them too much of a break
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
@@ -91,6 +87,8 @@ Property weights are:
mean += 2.5
if(CHAOS_MAX)
mean += 5
else
voters += 0.5
if(voters)
GLOB.dynamic_curve_centre += (mean/voters)
if(flags & USE_PREV_ROUND_WEIGHTS)
@@ -128,7 +126,8 @@ Property weights are:
for(var/property in property_weights)
if(property in rule.property_weights) // just treat it as 0 if it's not in there
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = (rule.get_weight() * property_weight)*rule.weight_mult
if(property_weight > 0)
drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult
return drafted_rules
/datum/dynamic_storyteller/proc/midround_draft()
@@ -140,25 +139,26 @@ Property weights are:
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
rule.trim_candidates()
var/threat_weight = 1
if(!(rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
/* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
pick this particular ruleset.
Let's use a toy example: there's 60 threat level and 10 threat spent.
We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1
is 2.26 times as likely to be picked, all other things considered.
Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
*/
threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
if (rule.ready())
var/property_weight = 0
for(var/property in property_weights)
if(property in rule.property_weights)
if(property in rule.property_weights) // just treat it as 0 if it's not in there
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
if(property_weight > 0)
var/threat_weight = 1
if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
/* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
pick this particular ruleset.
Let's use a toy example: there's 60 threat level and 10 threat spent.
We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1
is 2.26 times as likely to be picked, all other things considered.
Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
*/
threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult * threat_weight
return drafted_rules
/datum/dynamic_storyteller/proc/latejoin_draft(mob/living/carbon/human/newPlayer)
@@ -175,28 +175,29 @@ Property weights are:
rule.candidates = list(newPlayer)
rule.trim_candidates()
var/threat_weight = 1
if(!(rule.flags & MINOR_RULESET))
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
if (rule.ready())
var/property_weight = 0
for(var/property in property_weights)
if(property in rule.property_weights)
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
if(property_weight > 0)
var/threat_weight = 1
if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult * threat_weight
return drafted_rules
/datum/dynamic_storyteller/proc/event_draft()
var/list/drafted_rules = list()
for(var/datum/dynamic_ruleset/event/rule in mode.events)
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level - mode.threat) >= rule.cost)
if(rule.ready())
var/property_weight = 0
for(var/property in property_weights)
if(property in rule.property_weights)
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level + 20 - mode.threat) >= rule.cost && rule.ready())
var/property_weight = 0
for(var/property in property_weights)
if(property in rule.property_weights)
property_weight += rule.property_weights[property] * property_weights[property]
if(property_weight > 0)
drafted_rules[rule] = rule.get_weight() + property_weight * rule.weight_mult
return drafted_rules
@@ -313,9 +314,8 @@ Property weights are:
/datum/dynamic_storyteller/random/event_draft()
var/list/drafted_rules = list()
for(var/datum/dynamic_ruleset/event/rule in mode.events)
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
if(rule.ready())
drafted_rules[rule] = 1
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && rule.ready())
drafted_rules[rule] = 1
return drafted_rules
/datum/dynamic_storyteller/story
@@ -330,7 +330,7 @@ Property weights are:
/datum/dynamic_storyteller/story/calculate_threat()
var/current_time = (world.time / SSautotransfer.targettime)*180
mode.threat_level = round(mode.initial_threat_level*(sin(current_time)+0.25),0.1)
mode.threat_level = round((mode.initial_threat_level*(sin(current_time)/2)+0.75),0.1)
return ..()
/datum/dynamic_storyteller/classic
@@ -0,0 +1,67 @@
/datum/game_mode/heretics
name = "heresy"
config_tag = "heresy"
antag_flag = ROLE_HERETIC
false_report_weight = 5
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to heretic role blacklist
required_players = 15
required_enemies = 1
recommended_enemies = 4
reroll_friendly = 1
enemy_minimum_age = 0
round_ends_with_antag_death = 0
announce_span = "danger"
announce_text = "Heretics have been spotted on the station!\n\
<span class='danger'>Heretics</span>: Accomplish your objectives.\n\
<span class='notice'>Crew</span>: Do not let the madman succeed!"
var/ecult_possible = 4 //hard limit on culties if scaling is turned off
var/num_ecult = 1
var/list/culties = list()
/datum/game_mode/heretics/pre_setup()
if(CONFIG_GET(flag/protect_roles_from_antagonist))
restricted_jobs += protected_jobs
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
restricted_jobs += "Assistant"
var/esc = CONFIG_GET(number/ecult_scaling_coeff)
if(esc)
num_ecult = min(max(1, min(round(num_players() / (esc * 2)) + 2, round(num_players() / esc))),4)
else
num_ecult = max(1, min(num_players(), ecult_possible))
for(var/i in 1 to num_ecult)
if(!antag_candidates.len)
break
var/datum/mind/cultie = antag_pick(antag_candidates)
antag_candidates -= cultie
cultie.special_role = ROLE_HERETIC
cultie.restricted_roles = restricted_jobs
culties += cultie
var/enough_heretics = culties.len > 0
if(!enough_heretics)
setup_error = "Not enough heretic candidates"
return FALSE
else
for(var/antag in culties)
return TRUE
/datum/game_mode/heretics/post_setup()
for(var/c in culties)
var/datum/mind/cultie = c
log_game("[key_name(cultie)] has been selected as a heretic!")
var/datum/antagonist/heretic/new_antag = new()
cultie.add_antag_datum(new_antag)
return ..()
/datum/game_mode/heretics/generate_report()
return "Cybersun Industries has announced that they have successfully raided a high-security library. The library contained a very dangerous book that was \
shown to posses anomalous properties. We suspect that the book has been copied over, Stay vigilant!"
+59 -175
View File
@@ -12,9 +12,9 @@
density = FALSE
state_open = TRUE
circuit = /obj/item/circuitboard/machine/sleeper
req_access = list(ACCESS_CMO) //Used for reagent deletion and addition of non medicines
var/efficiency = 1
var/min_health = 30
var/min_health = -25
var/list/available_chems
var/controls_inside = FALSE
var/list/possible_chems = list(
@@ -31,32 +31,13 @@
/obj/machinery/sleeper/Initialize()
. = ..()
create_reagents(500, NO_REACT)
// if(mapload)
// component_parts -= circuit
// QDEL_NULL(circuit)
occupant_typecache = GLOB.typecache_living
update_icon()
reset_chem_buttons()
RefreshParts()
add_inital_chems()
new_occupant_dir = dir
/obj/machinery/sleeper/setDir(newdir)
. = ..()
new_occupant_dir = dir
/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)
var/datum/reagent/R = reagents.has_reagent(i)
if(!R)
reagents.add_reagent(i, (20))
continue
if(R.volume < 20)
reagents.add_reagent(i, (20 - R.volume))
/obj/machinery/sleeper/RefreshParts()
var/E
@@ -73,15 +54,11 @@
available_chems |= possible_chems[i]
reset_chem_buttons()
//Total container size 500 - 2000u
if(reagents)
reagents.maximum_volume = (500*E)
/obj/machinery/sleeper/update_icon_state()
icon_state = initial(icon_state)
if(state_open)
icon_state += "-open"
icon_state = "[initial(icon_state)]-open"
else
icon_state = initial(icon_state)
/obj/machinery/sleeper/container_resist(mob/living/user)
visible_message("<span class='notice'>[occupant] emerges from [src]!</span>",
@@ -98,10 +75,12 @@
/obj/machinery/sleeper/open_machine()
if(!state_open && !panel_open)
// flick("[initial(icon_state)]-anim", src)
..()
/obj/machinery/sleeper/close_machine(mob/user)
if((isnull(user) || istype(user)) && state_open && !panel_open)
// flick("[initial(icon_state)]-anim", src)
..(user)
var/mob/living/mob_occupant = occupant
if(mob_occupant && mob_occupant.stat != DEAD)
@@ -112,46 +91,23 @@
if (. & EMP_PROTECT_SELF)
return
if(is_operational() && occupant)
var/datum/reagent/R = pick(reagents.reagent_list)
var/datum/reagent/R = pick(reagents.reagent_list) //cit specific
inject_chem(R.type, occupant)
open_machine()
//Is this too much?
//Is this too much? Cit specific
if(severity == EMP_HEAVY)
var/chem = pick(available_chems)
available_chems -= chem
available_chems += get_random_reagent_id()
reset_chem_buttons()
/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/reagent_containers/sleeper_buffer))
var/obj/item/reagent_containers/sleeper_buffer/SB = I
if((SB.reagents.total_volume + reagents.total_volume) < reagents.maximum_volume)
SB.reagents.trans_to(reagents, SB.reagents.total_volume)
visible_message("[user] places the [SB] into the [src].")
qdel(SB)
return
else
SB.reagents.trans_to(reagents, SB.reagents.total_volume)
visible_message("[user] adds as much as they can to the [src] from the [SB].")
return
if(istype(I, /obj/item/reagent_containers))
var/obj/item/reagent_containers/RC = I
if(RC.reagents.total_volume == 0)
to_chat(user, "<span class='notice'>The [I] is empty!</span>")
for(var/datum/reagent/R in RC.reagents.reagent_list)
if((obj_flags & EMAGGED) || (allowed(usr)))
break
if(!istype(R, /datum/reagent/medicine))
visible_message("The [src] gives out a hearty boop and rejects the [I]. The Sleeper's screen flashes with a pompous \"Medicines only, please.\"")
return
RC.reagents.trans_to(reagents, 1000)
visible_message("[user] adds as much as they can to the [src] from the [I].")
return
/obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
if(user.stat || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
return
if(isliving(user))
var/mob/living/L = user
if(!(L.mobility_flags & MOBILITY_STAND))
return
close_machine(target)
/obj/machinery/sleeper/screwdriver_act(mob/living/user, obj/item/I)
@@ -187,23 +143,9 @@
visible_message("<span class='notice'>[usr] pries open [src].</span>", "<span class='notice'>You pry open [src].</span>")
open_machine()
/obj/machinery/sleeper/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
if(state_open)
close_machine()
else
open_machine()
return TRUE
/obj/machinery/sleeper/examine(mob/user)
. = ..()
. += "<span class='notice'>Alt-click [src] to [state_open ? "close" : "open"] it.</span>"
/obj/machinery/sleeper/ui_state(mob/user)
if(controls_inside)
return GLOB.notcontained_state
return GLOB.contained_state
return GLOB.default_state
/obj/machinery/sleeper/ui_interact(mob/user, datum/tgui/ui)
@@ -212,6 +154,18 @@
ui = new(user, src, "Sleeper", name)
ui.open()
/obj/machinery/sleeper/AltClick(mob/user)
if(!user.canUseTopic(src, !issilicon(user)))
return
if(state_open)
close_machine()
else
open_machine()
/obj/machinery/sleeper/examine(mob/user)
. = ..()
. += "<span class='notice'>Alt-click [src] to [state_open ? "close" : "open"] it.</span>"
/obj/machinery/sleeper/process()
..()
check_nap_violations()
@@ -221,22 +175,13 @@
/obj/machinery/sleeper/ui_data()
var/list/data = list()
var/chemical_list = list()
var/blood_percent = 0
data["occupied"] = occupant ? 1 : 0
data["open"] = state_open
data["blood_levels"] = blood_percent
data["blood_status"] = "Patient either has no blood, or does not require it to function."
data["chemical_list"] = chemical_list
data["chems"] = list()
for(var/chem in available_chems)
var/datum/reagent/R = reagents.has_reagent(chem)
R = GLOB.chemical_reagents_list[chem]
data["synthchems"] += list(list("name" = R.name, "id" = R.type, "synth_allowed" = synth_allowed(chem)))
for(var/datum/reagent/R in reagents.reagent_list)
data["chems"] += list(list("name" = R.name, "id" = R.type, "vol" = R.volume, "purity" = R.purity, "allowed" = chem_allowed(R.type)))
var/datum/reagent/R = GLOB.chemical_reagents_list[chem]
data["chems"] += list(list("name" = R.name, "id" = R.type, "allowed" = chem_allowed(chem)))
data["occupant"] = list()
var/mob/living/mob_occupant = occupant
@@ -264,40 +209,10 @@
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
if(mob_occupant.reagents.reagent_list.len)
data["occupant"]["reagents"] = list()
if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len)
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
chemical_list += list(list("name" = R.name, "volume" = R.volume))
else
chemical_list = "Patient has no reagents."
data["occupant"]["failing_organs"] = list()
var/mob/living/carbon/C = mob_occupant
if(C)
for(var/obj/item/organ/Or in C.getFailingOrgans())
if(istype(Or, /obj/item/organ/brain))
continue
data["occupant"]["failing_organs"] += list(list("name" = Or.name))
if(istype(C)) //Non-carbons shouldn't be able to enter sleepers, but this is to prevent runtimes if something ever breaks
if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner.
blood_percent = round((C.blood_volume / BLOOD_VOLUME_NORMAL)*100)
var/blood_id = C.get_blood_id()
var/blood_warning = ""
if(blood_percent < 80)
blood_warning = "Patient has low blood levels."
if(blood_percent < 60)
blood_warning = "Patient has DANGEROUSLY low blood levels."
if(blood_id)
var/blood_type = C.dna.blood_type
if(!(blood_id in GLOB.blood_reagent_types)) // special blood substance
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
if(R)
blood_type = R.name
else
blood_type = blood_id
data["blood_status"] = "Patient has [blood_type] type blood. [blood_warning]"
data["blood_levels"] = blood_percent
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
return data
/obj/machinery/sleeper/ui_act(action, params)
@@ -314,37 +229,14 @@
. = TRUE
if("inject")
var/chem = text2path(params["chem"])
var/amount = text2num(params["volume"])
if(!is_operational() || !mob_occupant || isnull(chem))
return
if(mob_occupant.health < min_health && chem != /datum/reagent/medicine/epinephrine)
return
if(inject_chem(chem, usr, amount))
if(inject_chem(chem, usr))
. = TRUE
if(scrambled_chems && prob(5))
to_chat(usr, "<span class='warning'>Chemical system re-route detected, results may not be as expected!</span>")
if("synth")
var/chem = text2path(params["chem"])
if(!is_operational())
return
reagents.add_reagent(chem_buttons[chem], 10) //other_purity = 0.75 for when the mechanics are in
if("purge")
var/chem = text2path(params["chem"])
if(allowed(usr))
if(!is_operational())
return
reagents.remove_reagent(chem, 1000)
return
if(chem in available_chems)
if(!is_operational())
return
/*var/datum/reagent/R = reagents.has_reagent(chem) //For when purity effects are in
if(R.purity < 0.8)*/
reagents.remove_reagent(chem, 1000)
else
visible_message("<span class='warning'>Access Denied.</span>")
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
/obj/machinery/sleeper/emag_act(mob/user)
. = ..()
@@ -353,10 +245,9 @@
to_chat(user, "<span class='warning'>You scramble the sleeper's user interface!</span>")
return TRUE
//trans to
/obj/machinery/sleeper/proc/inject_chem(chem, mob/user, volume = 10)
if(chem_allowed(chem))
reagents.trans_id_to(occupant, chem, volume)//emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU
/obj/machinery/sleeper/proc/inject_chem(chem, mob/user)
if((chem in available_chems) && chem_allowed(chem))
occupant.reagents.add_reagent(chem_buttons[chem], 10) //emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU
if(user)
log_combat(user, occupant, "injected [chem] into", addition = "via [src]")
return TRUE
@@ -369,14 +260,6 @@
var/occ_health = mob_occupant.health > min_health || chem == /datum/reagent/medicine/epinephrine
return amount && occ_health
/obj/machinery/sleeper/proc/synth_allowed(chem)
var/datum/reagent/R = reagents.has_reagent(chem)
if(!R)
return TRUE
if(R.volume < 50)
return TRUE
return FALSE
/obj/machinery/sleeper/proc/reset_chem_buttons()
scrambled_chems = FALSE
LAZYINITLIST(chem_buttons)
@@ -416,23 +299,6 @@
component_parts += new /obj/item/stack/cable_coil(null)
RefreshParts()
/obj/machinery/sleeper/clockwork
name = "soothing sleeper"
desc = "A large cryogenics unit built from brass. Its surface is pleasantly cool the touch."
icon_state = "sleeper_clockwork"
enter_message = "<span class='bold inathneq_small'>You hear the gentle hum and click of machinery, and are lulled into a sense of peace.</span>"
possible_chems = list(list(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/salbutamol, /datum/reagent/medicine/bicaridine,
/datum/reagent/medicine/kelotane, /datum/reagent/medicine/oculine, /datum/reagent/medicine/inacusiate, /datum/reagent/medicine/mannitol))
/obj/machinery/sleeper/clockwork/process()
if(occupant && isliving(occupant))
var/mob/living/L = occupant
if(GLOB.clockwork_vitality) //If there's Vitality, the sleeper has passive healing
GLOB.clockwork_vitality = max(0, GLOB.clockwork_vitality - 1)
L.adjustBruteLoss(-1)
L.adjustFireLoss(-1)
L.adjustOxyLoss(-5)
/obj/machinery/sleeper/old
icon_state = "oldpod"
@@ -443,8 +309,6 @@
idle_power_usage = 3000
circuit = /obj/item/circuitboard/machine/sleeper/party
var/leddit = FALSE //Get it like reddit and lead alright fine
ui_x = 310
ui_y = 400
controls_inside = TRUE
possible_chems = list(
@@ -477,3 +341,23 @@
/obj/machinery/sleeper/party/emag_act(mob/user)
..()
leddit = TRUE
/obj/machinery/sleeper/clockwork
name = "soothing sleeper"
desc = "A large cryogenics unit built from brass. Its surface is pleasantly cool the touch."
icon_state = "sleeper_clockwork"
enter_message = "<span class='bold inathneq_small'>You hear the gentle hum and click of machinery, and are lulled into a sense of peace.</span>"
possible_chems = list(
list(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/salbutamol, /datum/reagent/medicine/bicaridine, /datum/reagent/medicine/kelotane, /datum/reagent/medicine/oculine, /datum/reagent/medicine/inacusiate, /datum/reagent/medicine/mannitol)
) //everything is available at start
fair_market_price = 0 //it's free
/obj/machinery/sleeper/clockwork/process()
..()
if(occupant && isliving(occupant))
var/mob/living/L = occupant
if(GLOB.clockwork_vitality) //If there's Vitality, the sleeper has passive healing
GLOB.clockwork_vitality = max(0, GLOB.clockwork_vitality - 1)
L.adjustBruteLoss(-1)
L.adjustFireLoss(-1)
L.adjustOxyLoss(-5)
+5
View File
@@ -117,6 +117,7 @@ Class Procs:
var/new_occupant_dir = SOUTH //The direction the occupant will be set to look at when entering the machine.
var/speed_process = FALSE // Process as fast as possible?
var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created
var/wire_compatible = FALSE
// For storing and overriding ui id and dimensions
var/tgui_id // ID of TGUI interface
var/ui_style // ID of custom TGUI style (optional)
@@ -433,6 +434,7 @@ Class Procs:
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [src].</span>")
setAnchored(!anchored)
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
SEND_SIGNAL(src, COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH, anchored)
return SUCCESSFUL_UNFASTEN
return FAILED_UNFASTEN
return CANT_UNFASTEN
@@ -547,3 +549,6 @@ Class Procs:
. = . % 9
AM.pixel_x = -8 + ((.%3)*8)
AM.pixel_y = -8 + (round( . / 3)*8)
/obj/machinery/rust_heretic_act()
take_damage(500, BRUTE, "melee", 1)
@@ -310,6 +310,17 @@
opacity = 0
glass = TRUE
/obj/machinery/door/airlock/bronze
name = "bronze airlock"
icon = 'icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi'
overlays_file = 'icons/obj/doors/airlocks/clockwork/overlays.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_bronze
/obj/machinery/door/airlock/bronze/seethru
assemblytype = /obj/structure/door_assembly/door_assembly_bronze/seethru
opacity = 0
glass = TRUE
//////////////////////////////////
/*
Station2 Airlocks
+3
View File
@@ -153,6 +153,9 @@
/obj/mecha/get_cell()
return cell
/obj/mecha/rust_heretic_act()
take_damage(500, BRUTE)
/obj/mecha/Destroy()
go_out()
var/mob/living/silicon/ai/AI
@@ -63,3 +63,23 @@
/datum/effect_system/lightning_spread
effect_type = /obj/effect/particle_effect/sparks/electricity
//fake sparks, not subtyped because we don't want light/heat, nor checks inside an often used proc for a rare subcase for saving like 10 lines of code
/obj/effect/particle_effect/fake_sparks
name = "lightning"
icon_state = "electricity"
/obj/effect/particle_effect/fake_sparks/Initialize()
. = ..()
flick(icon_state, src) // replay the animation
playsound(src, "sparks", 100, TRUE)
QDEL_IN(src, 20)
/datum/effect_system/fake_spark_spread
effect_type = /obj/effect/particle_effect/fake_sparks
/proc/do_fake_sparks(n, c, source)
var/datum/effect_system/fake_spark_spread/sparks = new
sparks.set_up(n, c, source)
sparks.autocleanup = TRUE
sparks.start()
@@ -168,3 +168,26 @@
items = list(
/obj/item/clothing/mask/gas/sexymime,
/obj/item/clothing/under/rank/civilian/mime/sexy)
/obj/effect/spawner/bundle/crate/Initialize(mapload)
if(items && items.len)
var/turf/T = get_turf(src)
var/obj/structure/closet/LC = locate(/obj/structure/closet) in T
if(LC)
for(var/path in items)
new path(LC)
return INITIALIZE_HINT_QDEL
/obj/effect/spawner/bundle/crate/mosin
name = "Mosin-Nagant spawner"
items = list(
/obj/item/gun/ballistic/shotgun/boltaction,
/obj/item/ammo_box/a762
)
/obj/effect/spawner/bundle/crate/surplusrifle
name = "surplus rifle spawner"
items = list(
/obj/item/gun/ballistic/automatic/surplus,
/obj/item/ammo_box/magazine/m10mm/rifle
)
@@ -139,6 +139,23 @@
/obj/effect/temp_visual/dir_setting/curse/hand
icon_state = "cursehand"
/obj/effect/temp_visual/bsa_splash
name = "\improper Bluespace energy wave"
desc = "A massive, rippling wave of bluepace energy, all rapidly exhausting itself the moment it leaves the concentrated beam of light."
icon = 'icons/effects/beam_splash.dmi'
icon_state = "beam_splash_l"
layer = ABOVE_ALL_MOB_LAYER
pixel_y = -16
duration = 50
/obj/effect/temp_visual/bsa_splash/Initialize(mapload, dir)
. = ..()
switch(dir)
if(WEST)
icon_state = "beam_splash_w"
if(EAST)
icon_state = "beam_splash_e"
/obj/effect/temp_visual/wizard
name = "water"
icon = 'icons/mob/mob.dmi'
+84 -7
View File
@@ -135,6 +135,14 @@ RLD
flick("[icon_state]_empty", src) //somewhat hacky thing to make RCDs with ammo counters actually have a blinking yellow light
return .
/obj/item/construction/proc/check_menu(mob/living/user)
if(!istype(user))
return FALSE
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
return TRUE
/obj/item/construction/proc/range_check(atom/A, mob/user)
if(!(A in range(custom_range, get_turf(user))))
to_chat(user, "<span class='warning'>The \'Out of Range\' light on [src] blinks red.</span>")
@@ -276,13 +284,6 @@ RLD
//Not scaling these down to button size because they look horrible then, instead just bumping up radius.
return MA
/obj/item/construction/rcd/proc/check_menu(mob/living/user)
if(!istype(user))
return FALSE
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
return TRUE
/obj/item/construction/rcd/proc/change_computer_dir(mob/user)
if(!user)
return
@@ -856,6 +857,82 @@ RLD
desc = "It contains the design for firelock, air alarm, fire alarm, apc circuits and crap power cells."
upgrade = RCD_UPGRADE_SIMPLE_CIRCUITS
/obj/item/construction/plumbing
name = "Plumbing Constructor"
desc = "An expertly modified RCD outfitted to construct plumbing machinery. Reload with compressed matter cartridges."
icon = 'icons/obj/tools.dmi'
icon_state = "arcd"
item_state = "oldrcd"
has_ammobar = FALSE
matter = 200
max_matter = 200
///type of the plumbing machine
var/blueprint = null
///index, used in the attack self to get the type. stored here since it doesnt change
var/list/choices = list()
///index, used in the attack self to get the type. stored here since it doesnt change
var/list/name_to_type = list()
///
var/list/machinery_data = list("cost" = list(), "delay" = list())
/obj/item/construction/plumbing/attack_self(mob/user)
..()
if(!choices.len)
for(var/A in subtypesof(/obj/machinery/plumbing))
var/obj/machinery/plumbing/M = A
if(initial(M.rcd_constructable))
choices += list(initial(M.name) = image(icon = initial(M.icon), icon_state = initial(M.icon_state)))
name_to_type[initial(M.name)] = M
machinery_data["cost"][A] = initial(M.rcd_cost)
machinery_data["delay"][A] = initial(M.rcd_delay)
var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
if(!check_menu(user))
return
blueprint = name_to_type[choice]
playsound(src, 'sound/effects/pop.ogg', 50, FALSE)
to_chat(user, "<span class='notice'>You change [name]s blueprint to '[choice]'.</span>")
///pretty much rcd_create, but named differently to make myself feel less bad for copypasting from a sibling-type
/obj/item/construction/plumbing/proc/create_machine(atom/A, mob/user)
if(!machinery_data || !isopenturf(A))
return FALSE
if(checkResource(machinery_data["cost"][blueprint], user) && blueprint)
if(do_after(user, machinery_data["delay"][blueprint], target = A))
if(checkResource(machinery_data["cost"][blueprint], user) && canPlace(A))
useResource(machinery_data["cost"][blueprint], user)
activate()
playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE)
new blueprint (A, FALSE, FALSE)
return TRUE
/obj/item/construction/plumbing/proc/canPlace(turf/T)
if(!isopenturf(T))
return FALSE
. = TRUE
for(var/obj/O in T.contents)
if(O.density) //let's not built ontop of dense stuff, like big machines and other obstacles, it kills my immershion
return FALSE
/obj/item/construction/plumbing/afterattack(atom/A, mob/user)
. = ..()
if(!range_check(A, user))
return
if(istype(A, /obj/machinery/plumbing))
var/obj/machinery/plumbing/P = A
if(P.anchored)
to_chat(user, "<span class='warning'>The [P.name] needs to be unanchored!</span>")
return
if(do_after(user, 20, target = P))
P.deconstruct() //Let's not substract matter
playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) //this is just such a great sound effect
else
create_machine(A, user)
#undef GLOW_MODE
#undef LIGHT_MODE
#undef REMOVE_MODE
+71 -3
View File
@@ -6,6 +6,7 @@ RPD
#define ATMOS_CATEGORY 0
#define DISPOSALS_CATEGORY 1
#define TRANSIT_CATEGORY 2
#define PLUMBING_CATEGORY 3
#define BUILD_MODE (1<<0)
#define WRENCH_MODE (1<<1)
@@ -75,6 +76,13 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
)
))
GLOBAL_LIST_INIT(fluid_duct_recipes, list(
"Fluid Ducts" = list(
new /datum/pipe_info/plumbing("Duct", /obj/machinery/duct, PIPE_ONEDIR),
new /datum/pipe_info/plumbing/multilayer("Duct Layer-Manifold",/obj/machinery/duct/multilayered, PIPE_STRAIGHT)
)
))
/datum/pipe_info
var/name
var/icon_state
@@ -175,6 +183,15 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
if(dt == PIPE_UNARY_FLIPPABLE)
icon_state = "[icon_state]_preview"
/datum/pipe_info/plumbing/New(label, obj/path, dt=PIPE_UNARY)
name = label
id = path
icon_state = initial(path.icon_state)
dirtype = dt
/datum/pipe_info/plumbing/multilayer //exists as identifier so we can see the difference between multi_layer and just ducts properly later on
/obj/item/pipe_dispenser
name = "Rapid Piping Device (RPD)"
desc = "A device used to rapidly pipe things."
@@ -200,15 +217,19 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
var/atmos_build_speed = 5 //deciseconds (500ms)
var/disposal_build_speed = 5
var/transit_build_speed = 5
var/plumbing_build_speed = 5
var/destroy_speed = 5
var/paint_speed = 5
var/category = ATMOS_CATEGORY
var/piping_layer = PIPING_LAYER_DEFAULT
var/ducting_layer = DUCT_LAYER_DEFAULT
var/datum/pipe_info/recipe
var/static/datum/pipe_info/first_atmos
var/static/datum/pipe_info/first_disposal
var/static/datum/pipe_info/first_transit
var/mode = BUILD_MODE | DESTROY_MODE | WRENCH_MODE
var/static/datum/pipe_info/first_plumbing
var/locked = FALSE //wheter we can change categories. Useful for the plumber
/obj/item/pipe_dispenser/New()
. = ..()
@@ -253,12 +274,15 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
var/list/data = list(
"category" = category,
"piping_layer" = piping_layer,
// "ducting_layer" = ducting_layer, //uhh is this for chem thing?
"ducting_layer" = ducting_layer,
"preview_rows" = recipe.get_preview(p_dir),
"categories" = list(),
"selected_color" = paint_color,
"paint_colors" = GLOB.pipe_paint_colors,
"mode" = mode
"mode" = mode,
"locked" = locked
)
var/list/recipes
@@ -269,6 +293,8 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
recipes = GLOB.disposal_pipe_recipes
if(TRANSIT_CATEGORY)
recipes = GLOB.transit_tube_recipes
if(PLUMBING_CATEGORY)
recipes = GLOB.fluid_duct_recipes
for(var/c in recipes)
var/list/cat = recipes[c]
var/list/r = list()
@@ -297,6 +323,8 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
recipe = first_atmos
if(TRANSIT_CATEGORY)
recipe = first_transit
if(PLUMBING_CATEGORY)
recipe = first_plumbing
p_dir = NORTH
playeffect = FALSE
if("piping_layer")
@@ -468,16 +496,56 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
if(mode & WRENCH_MODE)
tube.wrench_act(user, src)
return
if(PLUMBING_CATEGORY) //Plumbing.
if(!can_make_pipe)
return ..()
A = get_turf(A)
if(isclosedturf(A))
to_chat(user, "<span class='warning'>[src]'s error light flickers; there's something in the way!</span>")
return
to_chat(user, "<span class='notice'>You start building a fluid duct...</span>")
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if(do_after(user, plumbing_build_speed, target = A))
var/obj/machinery/duct/D
if(recipe.type == /datum/pipe_info/plumbing/multilayer)
var/temp_connects = NORTH + SOUTH
if(queued_p_dir == EAST)
temp_connects = EAST + WEST
D = new queued_p_type (A, TRUE, GLOB.pipe_paint_colors[paint_color], ducting_layer, temp_connects)
else
D = new queued_p_type (A, TRUE, GLOB.pipe_paint_colors[paint_color], ducting_layer)
D.add_fingerprint(usr)
if(mode & WRENCH_MODE)
D.wrench_act(user, src)
else
return ..()
/obj/item/pipe_dispenser/proc/activate()
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
/* unneeded, you can craft ducts from plastic
/obj/item/pipe_dispenser/plumbing
name = "Plumberinator"
desc = "A crude device to rapidly plumb things."
icon_state = "plumberer"
category = PLUMBING_CATEGORY
locked = TRUE
/obj/item/pipe_dispenser/plumbing/Initialize()
. = ..()
spark_system = new
spark_system.set_up(5, 0, src)
spark_system.attach(src)
if(!first_plumbing)
first_plumbing = GLOB.fluid_duct_recipes[GLOB.fluid_duct_recipes[1]][1]
recipe = first_plumbing
*/
#undef ATMOS_CATEGORY
#undef DISPOSALS_CATEGORY
#undef TRANSIT_CATEGORY
#undef PLUMBING_CATEGORY
#undef BUILD_MODE
#undef DESTROY_MODE
@@ -48,6 +48,13 @@
/obj/item/stack/cable_coil = 5,
/obj/item/stack/sheet/glass = 1)
/obj/item/circuitboard/machine/medipen_refiller
name = "Medipen Refiller (Machine Board)"
icon_state = "medical"
build_path = /obj/machinery/medipen_refiller
req_components = list(
/obj/item/stock_parts/matter_bin = 1)
/obj/item/circuitboard/machine/clonepod
name = "Clone Pod (Machine Board)"
build_path = /obj/machinery/clonepod
@@ -512,6 +519,10 @@
/obj/item/stack/sheet/glass = 1)
needs_anchored = FALSE
/obj/item/circuitboard/machine/hydroponics/automagic
name = "Automatic Hydroponics Tray (Machine Board)"
build_path = /obj/machinery/hydroponics/constructable/automagic
/obj/item/circuitboard/machine/seed_extractor
name = "Seed Extractor (Machine Board)"
build_path = /obj/machinery/seed_extractor
+34 -6
View File
@@ -51,6 +51,10 @@
// no attacking while blocking
block_lock_attacking = TRUE
block_projectile_mitigation = 75
// more efficient vs projectiles
block_stamina_efficiency_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 4
)
parry_time_windup = 0
parry_time_active = 8
@@ -65,14 +69,20 @@
parry_imperfect_falloff_percent = 10
parry_efficiency_to_counterattack = 100
parry_efficiency_considered_successful = 25 // VERY generous
parry_efficiency_perfect = 90
parry_failed_stagger_duration = 3 SECONDS
parry_failed_clickcd_duration = CLICK_CD_MELEE
// more efficient vs projectiles
block_stamina_efficiency_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 4
)
/obj/item/dualsaber/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object))
block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER
return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT
return ..()
/obj/item/dualsaber/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
. = ..()
if(parry_efficiency >= 90) // perfect parry
block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER
. |= BLOCK_SHOULD_REDIRECT
/obj/item/dualsaber/Initialize()
. = ..()
@@ -342,12 +352,30 @@
name = "divine lightblade"
desc = "A giant blade of bright and holy light, said to cut down the wicked with ease."
force = 5
block_chance = 50
armour_penetration = 0
block_parry_data = /datum/block_parry_data/chaplain
var/chaplain_spawnable = TRUE
can_reflect = FALSE
obj_flags = UNIQUE_RENAME
/datum/block_parry_data/chaplain
parry_stamina_cost = 12
parry_time_windup = 2
parry_time_active = 5
parry_time_spindown = 3
// parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK
parry_time_perfect = 1
parry_time_perfect_leeway = 1
parry_imperfect_falloff_percent = 7.5
parry_efficiency_to_counterattack = 100
parry_efficiency_considered_successful = 80
parry_efficiency_perfect = 120
parry_efficiency_perfect_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 30,
)
parry_failed_stagger_duration = 3 SECONDS
parry_failed_clickcd_duration = 2 SECONDS
/obj/item/dualsaber/hypereutactic/chaplain/ComponentInitialize()
. = ..()
AddComponent(/datum/component/two_handed, force_unwielded=5, force_wielded=20, \
+4 -4
View File
@@ -253,7 +253,7 @@
user.set_nutrition(NUTRITION_LEVEL_STARVING + 50)
/obj/item/book/granter/spell/blind
spell = /obj/effect/proc_holder/spell/targeted/trigger/blind
spell = /obj/effect/proc_holder/spell/pointed/trigger/blind
spellname = "blind"
icon_state ="bookblind"
desc = "This book looks blurry, no matter how you look at it."
@@ -265,7 +265,7 @@
user.blind_eyes(10)
/obj/item/book/granter/spell/mindswap
spell = /obj/effect/proc_holder/spell/targeted/mind_transfer
spell = /obj/effect/proc_holder/spell/pointed/mind_transfer
spellname = "mindswap"
icon_state ="bookmindswap"
desc = "This book's cover is pristine, though its pages look ragged and torn."
@@ -289,7 +289,7 @@
if(stored_swap == user)
to_chat(user,"<span class='notice'>You stare at the book some more, but there doesn't seem to be anything else to learn...</span>")
return
var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new
var/obj/effect/proc_holder/spell/pointed/mind_transfer/swapper = new
if(swapper.cast(list(stored_swap), user, TRUE, TRUE))
to_chat(user,"<span class='warning'>You're suddenly somewhere else... and someone else?!</span>")
to_chat(stored_swap,"<span class='warning'>Suddenly you're staring at [src] again... where are you, who are you?!</span>")
@@ -324,7 +324,7 @@
user.DefaultCombatKnockdown(40)
/obj/item/book/granter/spell/barnyard
spell = /obj/effect/proc_holder/spell/targeted/barnyardcurse
spell = /obj/effect/proc_holder/spell/pointed/barnyardcurse
spellname = "barnyard"
icon_state ="bookhorses"
desc = "This book is more horse than your mind has room for."
+7 -2
View File
@@ -60,7 +60,8 @@
if(target)
if(!QDELETED(target))
location = get_turf(target)
target.cut_overlay(plastic_overlay, TRUE)
target.cut_overlay(plastic_overlay)
UnregisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/add_plastic_overlay)
if(!ismob(target) || full_damage_on_mobs)
target.ex_act(EXPLODE_HEAVY, target)
else
@@ -126,13 +127,17 @@
I.embedding["embed_chance"] = 0
I.updateEmbedding()
target.add_overlay(plastic_overlay, TRUE)
RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/add_plastic_overlay)
target.update_icon()
if(!nadeassembly)
to_chat(user, "<span class='notice'>You plant the bomb. Timer counting down from [det_time].</span>")
addtimer(CALLBACK(src, .proc/prime), det_time*10)
else
qdel(src) //How?
/obj/item/grenade/plastic/proc/add_plastic_overlay(atom/source, list/overlay_list)
overlay_list += plastic_overlay
/obj/item/grenade/plastic/proc/shout_syndicate_crap(mob/M)
if(!M)
return
@@ -9,7 +9,7 @@
/obj/item/implant/uplink/Initialize(mapload, _owner)
. = ..()
AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc, GLOB.not_incapacitated_state)
AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc)
/obj/item/implanter/uplink
name = "implanter (uplink)"
+77 -13
View File
@@ -47,8 +47,11 @@
spawn_option(stored_options[choice],M)
qdel(src)
/obj/item/choice_beacon/proc/spawn_option(obj/choice,mob/living/M)
var/obj/new_item = new choice()
/obj/item/choice_beacon/proc/create_choice_atom(atom/choice, mob/owner)
return new choice()
/obj/item/choice_beacon/proc/spawn_option(atom/choice,mob/living/M)
var/obj/new_item = create_choice_atom(choice, M)
var/obj/structure/closet/supplypod/bluespacepod/pod = new()
pod.explosionSize = list(0,0,0,0)
new_item.forceMove(pod)
@@ -152,10 +155,50 @@
augment_list[initial(A.name)] = A
return augment_list
/obj/item/choice_beacon/augments/spawn_option(obj/choice,mob/living/M)
/obj/item/choice_beacon/augments/spawn_option(atom/choice,mob/living/M)
new choice(get_turf(M))
to_chat(M, "<span class='hear'>You hear something crackle from the beacon for a moment before a voice speaks. \"Please stand by for a message from S.E.L.F. Message as follows: <b>Item request received. Your package has been transported, use the autosurgeon supplied to apply the upgrade.</b> Message ends.\"</span>")
/obj/item/choice_beacon/pet //donator beacon that summons a small friendly animal
name = "pet beacon"
desc = "Straight from the outerspace pet shop to your feet."
var/static/list/pets = list("Crab" = /mob/living/simple_animal/crab,
"Cat" = /mob/living/simple_animal/pet/cat,
"Space cat" = /mob/living/simple_animal/pet/cat/space,
"Kitten" = /mob/living/simple_animal/pet/cat/kitten,
"Dog" = /mob/living/simple_animal/pet/dog,
"Corgi" = /mob/living/simple_animal/pet/dog/corgi,
"Pug" = /mob/living/simple_animal/pet/dog/pug,
"Exotic Corgi" = /mob/living/simple_animal/pet/dog/corgi/exoticcorgi,
"Fox" = /mob/living/simple_animal/pet/fox,
"Red Panda" = /mob/living/simple_animal/pet/redpanda,
"Possum" = /mob/living/simple_animal/opossum)
var/pet_name
/obj/item/choice_beacon/pet/generate_display_names()
return pets
/obj/item/choice_beacon/pet/create_choice_atom(atom/choice, mob/owner)
var/mob/living/simple_animal/new_choice = new choice()
new_choice.butcher_results = null //please don't eat your pet, chef
var/obj/item/pet_carrier/donator/carrier = new() //a donator pet carrier is just a carrier that can't be shoved in an autolathe for metal
carrier.add_occupant(new_choice)
new_choice.mob_size = MOB_SIZE_TINY //yeah we're not letting you use this roundstart pet to hurt people / knock them down
new_choice.pass_flags = PASSTABLE | PASSMOB //your pet is not a bullet/person shield
new_choice.density = FALSE
new_choice.blood_volume = 0 //your pet cannot be used to drain blood from for a bloodsucker
new_choice.desc = "A pet [initial(choice.name)], owned by [owner]!"
new_choice.can_have_ai = FALSE //no it cant be sentient damnit
if(pet_name)
new_choice.name = pet_name
new_choice.unique_name = TRUE
return carrier
/obj/item/choice_beacon/pet/spawn_option(atom/choice,mob/living/M)
pet_name = input(M, "What would you like to name the pet? (leave blank for default name)", "Pet Name")
..()
//choice boxes (they just open in your hand instead of making a pod)
/obj/item/choice_beacon/box
name = "choice box (default)"
desc = "Think really hard about what you want, and then rip it open!"
@@ -163,21 +206,17 @@
icon_state = "deliverypackage3"
item_state = "deliverypackage3"
/obj/item/choice_beacon/box/spawn_option(obj/choice,mob/living/M)
to_chat(M, "<span class='hear'>The box opens, revealing the [choice]!</span>")
/obj/item/choice_beacon/box/spawn_option(atom/choice,mob/living/M)
var/choice_text = choice
if(ispath(choice_text))
choice_text = initial(choice.name)
to_chat(M, "<span class='hear'>The box opens, revealing the [choice_text]!</span>")
playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1)
M.temporarilyRemoveItemFromInventory(src, TRUE)
M.put_in_hands(new choice)
qdel(src)
/obj/item/choice_beacon/box/plushie
name = "choice box (plushie)"
desc = "Using the power of quantum entanglement, this box contains every plush, until the moment it is opened!"
icon = 'icons/obj/plushes.dmi'
icon_state = "box"
item_state = "box"
/obj/item/choice_beacon/box/spawn_option(choice,mob/living/M)
/obj/item/choice_beacon/box/plushie/spawn_option(choice,mob/living/M)
if(ispath(choice, /obj/item/toy/plush))
..() //regular plush, spawn it naturally
else
@@ -188,6 +227,31 @@
M.put_in_hands(new choice)
qdel(src)
/obj/item/choice_beacon/box/carpet //donator carpet beacon
name = "choice box (carpet)"
desc = "Contains 50 of a selected carpet inside!"
var/static/list/carpet_list = list(/obj/item/stack/tile/carpet/black/fifty = "Black Carpet",
"Black & Red Carpet" = /obj/item/stack/tile/carpet/blackred/fifty,
"Monochrome Carpet" = /obj/item/stack/tile/carpet/monochrome/fifty,
"Blue Carpet" = /obj/item/stack/tile/carpet/blue/fifty,
"Cyan Carpet" = /obj/item/stack/tile/carpet/cyan/fifty,
"Green Carpet" = /obj/item/stack/tile/carpet/green/fifty,
"Orange Carpet" = /obj/item/stack/tile/carpet/orange/fifty,
"Purple Carpet" = /obj/item/stack/tile/carpet/purple/fifty,
"Red Carpet" = /obj/item/stack/tile/carpet/red/fifty,
"Royal Black Carpet" = /obj/item/stack/tile/carpet/royalblack/fifty,
"Royal Blue Carpet" = /obj/item/stack/tile/carpet/royalblue/fifty)
/obj/item/choice_beacon/box/carpet/generate_display_names()
return carpet_list
/obj/item/choice_beacon/box/plushie
name = "choice box (plushie)"
desc = "Using the power of quantum entanglement, this box contains every plush, until the moment it is opened!"
icon = 'icons/obj/plushes.dmi'
icon_state = "box"
item_state = "box"
/obj/item/choice_beacon/box/plushie/generate_display_names()
var/list/plushie_list = list()
//plushie set 1: just subtypes of /obj/item/toy/plush
+67 -8
View File
@@ -29,6 +29,9 @@
var/has_lock_sprites = TRUE //whether to load the lock overlays or not
var/allows_hostiles = FALSE //does the pet carrier allow hostile entities to be held within it?
/obj/item/pet_carrier/donator
custom_materials = null //you cant just use the loadout item to get free metal!
/obj/item/pet_carrier/Destroy()
if(occupants.len)
for(var/V in occupants)
@@ -240,7 +243,31 @@
custom_materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
escape_time = 200 //equal to the time of a bluespace bodybag
alternate_escape_time = 100
///gas supply for simplemobs so they don't die
var/datum/gas_mixture/occupant_gas_supply
///level until the reagent gets INGEST ed instead of TOUCH
var/sipping_level = 150
///prob50 level of sipping
var/sipping_probably = 99
///chem transfer rate / second
var/transfer_rate = 5
/obj/item/pet_carrier/bluespace/Initialize()
. = ..()
create_reagents(300, OPENCONTAINER, DEFAULT_REAGENTS_VALUE) //equivalent of bsbeakers
/obj/item/pet_carrier/bluespace/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/pet_carrier/bluespace/attack_self(mob/living/user)
..()
if(reagents)
if(open)
reagents.reagents_holder_flags = OPENCONTAINER
else
reagents.reagents_holder_flags = NONE
/obj/item/pet_carrier/bluespace/update_icon_state()
if(open)
@@ -248,11 +275,28 @@
else
icon_state = "bluespace_jar"
/obj/item/pet_carrier/bluespace/throw_impact()
/obj/item/pet_carrier/bluespace/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
. = ..()
//delete the item upon impact, releasing the creature inside (this is handled by its deletion)
if(occupants.len)
loc.visible_message("<span class='warning'>The bluespace jar smashes, releasing [occupants[1]]!</span>")
if(reagents?.total_volume && ismob(hit_atom) && hit_atom.reagents)
reagents.total_volume *= rand(5,10) * 0.1 //Not all of it makes contact with the target
var/mob/M = hit_atom
var/R = reagents.log_list()
hit_atom.visible_message("<span class='danger'>[M] has been splashed with something!</span>", \
"<span class='userdanger'>[M] has been splashed with something!</span>")
var/turf/TT = get_turf(hit_atom)
var/throwerstring
if(thrownby)
log_combat(thrownby, M, "splashed", R)
var/turf/AT = get_turf(thrownby)
throwerstring = " THROWN BY [key_name(thrownby)] at [AT] (AREACOORD(AT)]"
log_reagent("SPLASH: [src] mob throw_impact() onto [key_name(hit_atom)] at [TT] ([AREACOORD(TT)])[throwerstring] - [R]")
reagents.reaction(hit_atom, TOUCH)
reagents.clear_reagents()
playsound(src, "shatter", 70, 1)
qdel(src)
@@ -260,21 +304,24 @@
. = ..()
if(!occupant_gas_supply)
occupant_gas_supply = new
if(isanimal(occupant))
var/mob/living/simple_animal/animal = occupant
occupant_gas_supply[/datum/gas/oxygen] = 0.0064 //make sure it has some gas in so it isn't depressurized
occupant_gas_supply.set_temperature(animal.minbodytemp) //simple animals only care about temperature/pressure when their turf isnt a location
else
if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside
ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
ADD_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
ADD_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
ADD_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
ADD_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside
START_PROCESSING(SSobj, src)
ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
ADD_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
ADD_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
ADD_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
ADD_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
/obj/item/pet_carrier/bluespace/remove_occupant(mob/living/occupant)
. = ..()
if(ishuman(occupant))
STOP_PROCESSING(SSobj, src)
REMOVE_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
REMOVE_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist")
REMOVE_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
@@ -287,6 +334,18 @@
occupant_gas_supply = new
return occupant_gas_supply
/obj/item/pet_carrier/bluespace/process()
if(!reagents)
return
for(var/mob/living/L in occupants)
if(!ishuman(L))
continue
if((reagents.total_volume >= sipping_level) || ((reagents.total_volume >= sipping_probably) && prob(50))) //sipp
reagents.reaction(L, INGEST) //consume
reagents.trans_to(L, transfer_rate)
else
reagents.reaction(L, TOUCH, show_message = FALSE)
/obj/item/pet_carrier/bluespace/load_occupant(mob/living/user, mob/living/target)
if(..())
name = "[initial(name)] ([target])"
+12
View File
@@ -688,6 +688,18 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
icon_state = "scrubpuppy"
item_state = "scrubpuppy"
/obj/item/toy/plush/borgplushie/meddrake
name = "MediDrake Plushie"
desc = "An adorable stuffed toy of a Medidrake."
icon_state = "meddrake"
item_state = "meddrake"
/obj/item/toy/plush/borgplushie/secdrake
name = "SecDrake Plushie"
desc = "An adorable stuffed toy of a Secdrake."
icon_state = "secdrake"
item_state = "secdrake"
/obj/item/toy/plush/aiplush
name = "AI plushie"
desc = "A little stuffed toy AI core... it appears to be malfunctioning."
@@ -128,6 +128,7 @@
absorption_capacity = 5
splint_factor = 0.35
custom_price = PRICE_REALLY_CHEAP
grind_results = list(/datum/reagent/cellulose = 2)
// gauze is only relevant for wounds, which are handled in the wounds themselves
/obj/item/stack/medical/gauze/try_heal(mob/living/M, mob/user, silent)
@@ -412,6 +412,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
force = 0
throwforce = 0
merge_type = /obj/item/stack/sheet/cloth
grind_results = list(/datum/reagent/cellulose = 2)
/obj/item/stack/sheet/cloth/get_main_recipes()
. = ..()
@@ -672,6 +673,10 @@ GLOBAL_LIST_INIT(brass_recipes, list ( \
GLOBAL_LIST_INIT(bronze_recipes, list ( \
new/datum/stack_recipe("wall gear", /obj/structure/girder/bronze, 2, time = 20, one_per_turf = TRUE, on_floor = TRUE), \
null,
new/datum/stack_recipe("directional bronze window", /obj/structure/window/bronze/unanchored, time = 0, on_floor = TRUE, window_checks = TRUE), \
new/datum/stack_recipe("fulltile bronze window", /obj/structure/window/bronze/fulltile/unanchored, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \
new/datum/stack_recipe("pinion airlock assembly", /obj/structure/door_assembly/door_assembly_bronze, 4, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("bronze pinion airlock assembly", /obj/structure/door_assembly/door_assembly_bronze/seethru, 4, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("bronze hat", /obj/item/clothing/head/bronze), \
new/datum/stack_recipe("bronze suit", /obj/item/clothing/suit/bronze), \
new/datum/stack_recipe("bronze boots", /obj/item/clothing/shoes/bronze), \
@@ -679,9 +684,10 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
new/datum/stack_recipe("bronze chair", /obj/structure/chair/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("bronze bar stool", /obj/structure/chair/stool/bar/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("bronze stool", /obj/structure/chair/stool/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \
new /datum/stack_recipe("bronze floor tiles", /obj/item/stack/tile/bronze, 1, 4, 20), \
))
/obj/item/stack/tile/bronze
/obj/item/stack/sheet/bronze
name = "brass"
desc = "On closer inspection, what appears to be wholly-unsuitable-for-building brass is actually more structurally stable bronze."
singular_name = "bronze sheet"
@@ -690,27 +696,21 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
icon = 'icons/obj/stack_objects.dmi'
custom_materials = list(/datum/material/bronze = MINERAL_MATERIAL_AMOUNT)
resistance_flags = FIRE_PROOF | ACID_PROOF
throwforce = 10
max_amount = 50
throw_speed = 1
throw_range = 3
turf_type = /turf/open/floor/bronze
novariants = FALSE
grind_results = list(/datum/reagent/iron = 5, /datum/reagent/copper = 3) //we have no "tin" reagent so this is the closest thing
merge_type = /obj/item/stack/tile/bronze
merge_type = /obj/item/stack/sheet/bronze
tableVariant = /obj/structure/table/bronze
material_type = /datum/material/bronze
/obj/item/stack/tile/bronze/attack_self(mob/living/user)
/obj/item/stack/sheet/bronze/attack_self(mob/living/user)
if(is_servant_of_ratvar(user)) //still lets them build with it, just gives a message
to_chat(user, "<span class='danger'>Wha... what is this cheap imitation crap? This isn't brass at all!</span>")
..()
/obj/item/stack/tile/bronze/get_main_recipes()
/obj/item/stack/sheet/bronze/get_main_recipes()
. = ..()
. += GLOB.bronze_recipes
/obj/item/stack/tile/bronze/thirty
/obj/item/stack/sheet/bronze/thirty
amount = 30
/*
@@ -774,6 +774,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list(
new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \
new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \
new /datum/stack_recipe("shower curtain", /obj/structure/curtain, 10, time = 10, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("duct", /obj/item/stack/ducts,1), \
new /datum/stack_recipe("laser pointer case", /obj/item/glasswork/glass_base/laserpointer_shell, 30), \
new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2)))
@@ -842,6 +843,7 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
merge_type = /obj/item/stack/sheet/cotton
var/pull_effort = 30
var/loom_result = /obj/item/stack/sheet/cloth
grind_results = list(/datum/reagent/cellulose = 5)
/obj/item/stack/sheet/cotton/ten
amount = 10
@@ -857,6 +859,7 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
merge_type = /obj/item/stack/sheet/cotton/durathread
pull_effort = 70
loom_result = /obj/item/stack/sheet/durathread
grind_results = list(/datum/reagent/cellulose = 10)
/obj/item/stack/sheet/meat
name = "meat sheets"
@@ -513,3 +513,12 @@
icon_state = "material_tile"
turf_type = /turf/open/floor/material
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
/obj/item/stack/tile/bronze
name = "bronze tile"
singular_name = "bronze floor tile"
desc = "A tile made out of bronze. Looks like clockwork."
icon_state = "material_tile"
color = "#92661A"
turf_type = /turf/open/floor/bronze
custom_materials = list(/datum/material/bronze = 250)
+2 -2
View File
@@ -478,7 +478,7 @@
/obj/item/assembly/signaler,
/obj/item/lightreplacer,
/obj/item/rcd_ammo,
/obj/item/construction/rcd,
/obj/item/construction,
/obj/item/pipe_dispenser,
/obj/item/stack/rods,
/obj/item/stack/tile/plasteel,
@@ -492,7 +492,7 @@
icon_state = "grenadebeltnew"
item_state = "security"
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
/obj/item/storage/belt/grenade/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
+47 -30
View File
@@ -47,41 +47,58 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
user.visible_message("<span class='suicide'>[user] is offering [user.p_them()]self to [deity_name]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return (BRUTELOSS)
/obj/item/storage/book/bible/attack_self(mob/living/carbon/human/H)
if(!istype(H))
/obj/item/storage/book/bible/attack_self(mob/living/carbon/human/user)
if(!istype(user))
return
// If H is the Chaplain, we can set the icon_state of the bible (but only once!)
if(!GLOB.bible_icon_state && H.job == "Chaplain")
var/dat = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>Pick Bible Style</title></head><body><center><h2>Pick a bible style</h2></center><table>"
for(var/i in 1 to GLOB.biblestates.len)
var/icon/bibleicon = icon('icons/obj/storage.dmi', GLOB.biblestates[i])
var/nicename = GLOB.biblenames[i]
H << browse_rsc(bibleicon, nicename)
dat += {"<tr><td><img src="[nicename]"></td><td><a href="?src=[REF(src)];seticon=[i]">[nicename]</a></td></tr>"}
dat += "</table></body></html>"
H << browse(dat, "window=editicon;can_close=0;can_minimize=0;size=250x650")
if(GLOB.bible_icon_state) // if there is already a bible icon return FALSE
return FALSE
if(user.job != "Chaplain") // if the user is not the chaplain, return FALSE
return FALSE
/obj/item/storage/book/bible/Topic(href, href_list)
if(!usr.canUseTopic(src))
return
if(href_list["seticon"] && GLOB && !GLOB.bible_icon_state)
var/iconi = text2num(href_list["seticon"])
var/biblename = GLOB.biblenames[iconi]
var/obj/item/storage/book/bible/B = locate(href_list["src"])
B.icon_state = GLOB.biblestates[iconi]
B.item_state = GLOB.bibleitemstates[iconi]
var/list/skins = list()
for(var/i in 1 to GLOB.biblestates.len)
var/image/bible_image = image(icon = 'icons/obj/storage.dmi', icon_state = GLOB.biblestates[i])
skins += list("[GLOB.biblenames[i]]" = bible_image)
if(B.icon_state == "honk1" || B.icon_state == "honk2")
var/mob/living/carbon/human/H = usr
H.dna.add_mutation(CLOWNMUT)
H.dna.add_mutation(SMILE)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), SLOT_WEAR_MASK)
var/choice = show_radial_menu(user, src, skins, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 40, require_near = TRUE)
if(!choice)
return FALSE
var/bible_index = GLOB.biblenames.Find(choice)
if(!bible_index)
return FALSE
icon_state = GLOB.biblestates[bible_index]
item_state = GLOB.bibleitemstates[bible_index]
GLOB.bible_icon_state = B.icon_state
GLOB.bible_item_state = B.item_state
if(icon_state == "honk1" || icon_state == "honk2")
var/mob/living/carbon/human/H = usr
H.dna.add_mutation(CLOWNMUT)
H.dna.add_mutation(SMILE)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), SLOT_WEAR_MASK)
SSblackbox.record_feedback("text", "religion_book", 1, "[biblename]")
usr << browse(null, "window=editicon")
GLOB.bible_icon_state = icon_state
GLOB.bibleitemstates = item_state
SSblackbox.record_feedback("text", "religion_book", 1, "[choice]")
/**
* Checks if we are allowed to interact with the radial
*
* Arguements: user The mob interacting with the menu
*/
/obj/item/storage/book/bible/proc/check_menu(mob/living/carbon/human/user)
if(GLOB.bible_icon_state)
return FALSE
if(!istype(user))
return FALSE
if(!user.is_holding(src))
return FALSE
if(!user.can_read(src))
return FALSE
if(user.incapacitated())
return FALSE
if(user.job != "Chaplain")
return FALSE
return TRUE
/obj/item/storage/book/bible/proc/bless(mob/living/carbon/human/H, mob/living/user)
for(var/X in H.bodyparts)
+12 -10
View File
@@ -245,19 +245,20 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
new /obj/item/stack/cable_coil/white(src)
/obj/item/storage/toolbox/ammo
name = "ammo box"
desc = "It contains a few clips."
name = "ammunition case (7.62mm stripper clips)"
desc = "It contains a few 7.62 stripper clips."
icon_state = "ammobox"
item_state = "ammobox"
var/ammotype = /obj/item/ammo_box/a762 // make sure this is a typepath thanks
/obj/item/storage/toolbox/ammo/PopulateContents()
new /obj/item/ammo_box/a762(src)
new /obj/item/ammo_box/a762(src)
new /obj/item/ammo_box/a762(src)
new /obj/item/ammo_box/a762(src)
new /obj/item/ammo_box/a762(src)
new /obj/item/ammo_box/a762(src)
new /obj/item/ammo_box/a762(src)
for (var/i = 0, i < 7, i++)
new ammotype(src)
/obj/item/storage/toolbox/ammo/surplus
name = "ammunition case (10mm rifle magazines)"
desc = "It contains a few 10mm rifle magazines."
ammotype = /obj/item/ammo_box/magazine/m10mm/rifle
/obj/item/storage/toolbox/infiltrator
name = "insidious case"
@@ -280,6 +281,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/clothing/suit/armor/vest/infiltrator,
/obj/item/clothing/under/syndicate/bloodred,
/obj/item/clothing/gloves/color/latex/nitrile/infiltrator,
/obj/item/clothing/gloves/tackler/combat/insulated/infiltrator,
/obj/item/clothing/mask/infiltrator,
/obj/item/clothing/shoes/combat/sneakboots,
/obj/item/gun/ballistic/automatic/pistol,
@@ -291,7 +293,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
new /obj/item/clothing/head/helmet/infiltrator(src)
new /obj/item/clothing/suit/armor/vest/infiltrator(src)
new /obj/item/clothing/under/syndicate/bloodred(src)
new /obj/item/clothing/gloves/color/latex/nitrile/infiltrator(src)
new /obj/item/clothing/gloves/tackler/combat/insulated/infiltrator(src)
new /obj/item/clothing/mask/infiltrator(src)
new /obj/item/clothing/shoes/combat/sneakboots(src)
+22 -3
View File
@@ -257,6 +257,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/katana/timestop
name = "temporal katana"
desc = "Delicately balanced, this finely-crafted blade hums with barely-restrained potential."
icon_state = "temporalkatana"
item_state = "temporalkatana"
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
block_chance = 0 // oops
force = 27.5 // oops
item_flags = ITEM_CAN_PARRY
@@ -268,6 +272,21 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
flynn.emote("smirk")
new /obj/effect/timestop/magic(get_turf(owner), 1, 50, list(owner)) // null roddies counter
/obj/item/katana/timestop/suicide_act(mob/living/user) // stolen from hierophant staff
new /obj/effect/timestop/magic(get_turf(user), 1, 50, list(user)) // free usage for dying
user.visible_message("<span class='suicide'>[user] poses menacingly with the [src]! It looks like [user.p_theyre()] trying to teleport behind someone!</span>")
user.say("Heh.. Nothing personnel, kid..", forced = "temporal katana suicide")
sleep(20)
if(!user)
return
user.visible_message("<span class='hierophant_warning'>[user] vanishes into a cloud of falling dust and burning embers, likely off to style on some poor sod in the distance!</span>")
playsound(user,'sound/magic/blink.ogg', 75, TRUE)
for(var/obj/item/I in user)
if(I != src)
user.dropItemToGround(I)
user.dropItemToGround(src) //Drop us last, so it goes on top of their stuff
qdel(user)
/obj/item/melee/bokken // parrying stick
name = "bokken"
desc = "A space-Japanese training sword made of wood and shaped like a katana."
@@ -302,7 +321,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
parry_time_perfect = 1.5
parry_time_perfect_leeway = 1
parry_imperfect_falloff_percent = 7.5
parry_efficiency_to_counterattack = 100
parry_efficiency_to_counterattack = 120
parry_efficiency_considered_successful = 65 // VERY generous
parry_efficiency_perfect = 120
parry_efficiency_perfect_override = list(
@@ -311,13 +330,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
parry_failed_stagger_duration = 3 SECONDS
parry_data = list(
PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25
)
)
/datum/block_parry_data/bokken/quick_parry // emphasizing REALLY SHORT PARRIES
parry_stamina_cost = 6 // still more costly than most parries, but less than a full bokken parry
parry_time_active = 5 // REALLY small parry window
parry_time_perfect = 2.5 // however...
parry_time_perfect_leeway = 2.5 // the entire time, the parry is perfect
parry_time_perfect_leeway = 2 // the entire time, the parry is perfect
parry_failed_stagger_duration = 1 SECONDS
parry_failed_clickcd_duration = 1 SECONDS // more forgiving punishments for missed parries
// still, don't fucking miss your parries or you're down stamina and staggered to shit
+3 -3
View File
@@ -186,7 +186,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
if(!acid_level)
SSacid.processing[src] = src
add_overlay(GLOB.acid_overlay, TRUE)
update_icon()
var/acid_cap = acidpwr * 300 //so we cannot use huge amounts of weak acids to do as well as strong acids.
if(acid_level < acid_cap)
acid_level = min(acid_level + acidpwr * acid_volume, acid_cap)
@@ -224,7 +224,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE))
resistance_flags |= ON_FIRE
SSfire_burning.processing[src] = src
add_overlay(GLOB.fire_overlay, TRUE)
update_icon()
return 1
//called when the obj is destroyed by fire
@@ -236,7 +236,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
/obj/proc/extinguish()
if(resistance_flags & ON_FIRE)
resistance_flags &= ~ON_FIRE
cut_overlay(GLOB.fire_overlay, TRUE)
update_icon()
SSfire_burning.processing -= src
/obj/zap_act(power, zap_flags, shocked_targets)
+10
View File
@@ -317,6 +317,13 @@
icon_state = unique_reskin[choice]
to_chat(M, "[src] is now skinned as '[choice]'.")
/obj/update_overlays()
. = ..()
if(acid_level)
. += GLOB.acid_overlay
if(resistance_flags & ON_FIRE)
. += GLOB.fire_overlay
//Called when the object is constructed by an autolathe
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
/obj/proc/autolathe_crafted(obj/machinery/autolathe/A)
@@ -329,3 +336,6 @@
. = ..()
if(. && ricochet_damage_mod)
take_damage(P.damage * ricochet_damage_mod, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration) // pass along ricochet_damage_mod damage to the structure for the ricochet
/obj/proc/plunger_act(obj/item/plunger/P, mob/living/user, reinforced)
return
+3
View File
@@ -112,3 +112,6 @@
if(0 to 25)
if(!broken)
return "<span class='warning'>It's falling apart!</span>"
/obj/structure/rust_heretic_act()
take_damage(500, BRUTE, "melee", 1)
@@ -487,7 +487,7 @@
desc = "A bronze bar stool with red silk for a pillow."
icon_state = "barbrass"
item_chair = /obj/item/chair/stool/bar/bronze
buildstacktype = /obj/item/stack/tile/bronze
buildstacktype = /obj/item/stack/sheet/bronze
buildstackamount = 1
/obj/structure/chair/stool/brass
@@ -503,7 +503,7 @@
desc = "A bronze stool with a silk top for comfort."
icon_state = "stoolbrass"
item_chair = /obj/item/chair/stool/bronze
buildstacktype = /obj/item/stack/tile/bronze
buildstacktype = /obj/item/stack/sheet/bronze
buildstackamount = 1
/obj/item/chair/stool/brass
@@ -569,7 +569,6 @@
buildstacktype = /obj/item/stack/tile/brass
buildstackamount = 1
item_chair = null
var/turns = 0
/obj/structure/chair/brass/ComponentInitialize()
return //it spins with the power of ratvar, not components.
@@ -581,16 +580,12 @@
/obj/structure/chair/brass/process()
setDir(turn(dir,-90))
playsound(src, 'sound/effects/servostep.ogg', 50, FALSE)
turns++
if(turns >= 8)
STOP_PROCESSING(SSfastprocess, src)
/obj/structure/chair/brass/ratvar_act()
return
/obj/structure/chair/brass/AltClick(mob/living/user)
. = ..()
turns = 0
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if(!(datum_flags & DF_ISPROCESSING))
@@ -608,7 +603,7 @@
desc = "A spinny chair made of bronze. It has little cogs for wheels!"
anchored = FALSE
icon_state = "brass_chair"
buildstacktype = /obj/item/stack/tile/bronze
buildstacktype = /obj/item/stack/sheet/bronze
buildstackamount = 1
item_chair = null
+15 -1
View File
@@ -243,10 +243,24 @@ LINEN BINS
/obj/item/bedsheet/random/Initialize()
..()
var/type = pick(typesof(/obj/item/bedsheet) - /obj/item/bedsheet/random)
var/type = pick(typesof(/obj/item/bedsheet) - list(/obj/item/bedsheet/random, /obj/item/bedsheet/chameleon))
new type(loc)
return INITIALIZE_HINT_QDEL
/obj/item/bedsheet/chameleon //donator chameleon bedsheet
name = "chameleon bedsheet"
desc = "Bedsheet technology has truly gone too far."
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/bedsheet/chameleon/New()
..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/bedsheet
chameleon_action.chameleon_name = "Bedsheet"
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/bedsheet/chameleon, /obj/item/bedsheet/random), only_root_path = TRUE)
chameleon_action.initialize_disguises()
//bedsheet bin
/obj/structure/bedsheetbin
name = "linen bin"
desc = "It looks rather cosy."
@@ -111,6 +111,9 @@
var/mob/living/L = user
if(HAS_TRAIT(L, TRAIT_SKITTISH))
. += "<span class='notice'>Ctrl-Shift-click [src] to jump inside.</span>"
if(isobserver(user))
. += "<span class='info'>It contains: [english_list(contents)].</span>"
investigate_log("had its contents examined by [user] as a ghost.", INVESTIGATE_GHOST)
/obj/structure/closet/CanPass(atom/movable/mover, turf/target)
if(wall_mounted)
@@ -240,3 +240,14 @@
airlock_type = /obj/machinery/door/airlock/wood
mineral = "wood"
glass_type = /obj/machinery/door/airlock/wood/glass
/obj/structure/door_assembly/door_assembly_bronze
name = "bronze airlock assembly"
icon = 'icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi'
base_name = "bronze airlock"
airlock_type = /obj/machinery/door/airlock/bronze
noglass = TRUE
material_type = /obj/item/stack/tile/bronze
/obj/structure/door_assembly/door_assembly_bronze/seethru
airlock_type = /obj/machinery/door/airlock/bronze/seethru
+4 -4
View File
@@ -442,19 +442,19 @@
to_chat(user, "<span class='notice'>You start slicing apart [src]...</span>")
if(W.use_tool(src, user, 40, volume=50))
to_chat(user, "<span class='notice'>You slice apart [src].</span>")
var/obj/item/stack/tile/bronze/B = new(drop_location(), 2)
var/obj/item/stack/sheet/bronze/B = new(drop_location(), 2)
transfer_fingerprints_to(B)
qdel(src)
else if(istype(W, /obj/item/pickaxe/drill/jackhammer))
to_chat(user, "<span class='notice'>Your jackhammer smashes through the girder!</span>")
var/obj/item/stack/tile/bronze/B = new(drop_location(), 2)
var/obj/item/stack/sheet/bronze/B = new(drop_location(), 2)
transfer_fingerprints_to(B)
W.play_tool_sound(src)
qdel(src)
else if(istype(W, /obj/item/stack/tile/bronze))
var/obj/item/stack/tile/bronze/B = W
else if(istype(W, /obj/item/stack/sheet/bronze))
var/obj/item/stack/sheet/bronze/B = W
if(B.get_amount() < 2)
to_chat(user, "<span class='warning'>You need at least two bronze sheets to build a bronze wall!</span>")
return 0
+5 -1
View File
@@ -86,6 +86,10 @@
/obj/structure/grille/attack_animal(mob/user)
. = ..()
if(!user.CheckActionCooldown(CLICK_CD_MELEE))
return
user.DelayNextAction(flush = TRUE)
user.do_attack_animation(src)
if(!shock(user, 70) && !QDELETED(src)) //Last hit still shocks but shouldn't deal damage to the grille)
take_damage(rand(5,10), BRUTE, "melee", 1)
@@ -114,12 +118,12 @@
/obj/structure/grille/attack_alien(mob/living/user)
if(!user.CheckActionCooldown(CLICK_CD_MELEE))
return
user.DelayNextAction(flush = TRUE)
user.do_attack_animation(src)
user.visible_message("<span class='warning'>[user] mangles [src].</span>", null, null, COMBAT_MESSAGE_RANGE)
if(!shock(user, 70))
take_damage(20, BRUTE, "melee", 1)
/obj/structure/grille/CanPass(atom/movable/mover, turf/target)
if(istype(mover) && (mover.pass_flags & PASSGRILLE))
return TRUE

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