Merge remote-tracking branch 'upstream/master' into haha
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
))
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
))
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -178,6 +180,7 @@
|
||||
#define TRAIT_FREERUNNING "freerunning"
|
||||
#define TRAIT_SKITTISH "skittish"
|
||||
#define TRAIT_POOR_AIM "poor_aim"
|
||||
#define TRAIT_INSANE_AIM "insane_aim" //they don't miss. they never miss. it was all part of their immaculate plan.
|
||||
#define TRAIT_PROSOPAGNOSIA "prosopagnosia"
|
||||
#define TRAIT_DRUNK_HEALING "drunk_healing"
|
||||
#define TRAIT_TAGGER "tagger"
|
||||
@@ -202,7 +205,7 @@
|
||||
#define TRAIT_NO_ALCOHOL "alcohol_intolerance"
|
||||
#define TRAIT_MUTATION_STASIS "mutation_stasis" //Prevents processed genetics mutations from processing.
|
||||
#define TRAIT_FAST_PUMP "fast_pump"
|
||||
#define TRAIT_NICE_SHOT "nice_shot" //hnnnnnnnggggg..... you're pretty good....
|
||||
#define TRAIT_NICE_SHOT "nice_shot" //hnnnnnnnggggg..... you're pretty good...
|
||||
|
||||
// mobility flag traits
|
||||
// IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it)
|
||||
@@ -256,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"
|
||||
@@ -310,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
|
||||
|
||||
@@ -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]")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -231,4 +231,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"))
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
|
||||
/datum/crafting_recipe/brute_pack
|
||||
name = "Suture Pack"
|
||||
result = /obj/item/stack/medical/suture/one
|
||||
result = /obj/item/stack/medical/suture/five
|
||||
time = 1
|
||||
reqs = list(/obj/item/stack/medical/gauze = 1,
|
||||
/datum/reagent/medicine/styptic_powder = 10)
|
||||
@@ -135,7 +135,7 @@
|
||||
|
||||
/datum/crafting_recipe/burn_pack
|
||||
name = "Regenerative Mesh"
|
||||
result = /obj/item/stack/medical/mesh/one
|
||||
result = /obj/item/stack/medical/mesh/five
|
||||
time = 1
|
||||
reqs = list(/obj/item/stack/medical/gauze = 1,
|
||||
/datum/reagent/medicine/silver_sulfadiazine = 10)
|
||||
@@ -188,7 +188,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 +200,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 +212,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 +224,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 +236,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 +269,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//
|
||||
////////////
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
+2
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1121,3 +1121,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
|
||||
|
||||
@@ -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 //
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -92,6 +92,7 @@ Class Procs:
|
||||
pressure_resistance = 15
|
||||
max_integrity = 200
|
||||
layer = BELOW_OBJ_LAYER //keeps shit coming out of the machine from ending up underneath it.
|
||||
flags_1 = DEFAULT_RICOCHET_1
|
||||
flags_ricochet = RICOCHET_HARD
|
||||
ricochet_chance_mod = 0.3
|
||||
|
||||
@@ -546,3 +547,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
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
max_integrity = 350
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 70)
|
||||
CanAtmosPass = ATMOS_PASS_DENSITY
|
||||
flags_1 = PREVENT_CLICK_UNDER_1
|
||||
flags_1 = PREVENT_CLICK_UNDER_1|DEFAULT_RICOCHET_1
|
||||
ricochet_chance_mod = 0.8
|
||||
|
||||
interaction_flags_atom = INTERACT_ATOM_UI_INTERACT
|
||||
|
||||
@@ -298,7 +298,7 @@
|
||||
|
||||
/obj/machinery/door/firedoor/border_only
|
||||
icon = 'icons/obj/doors/edge_Doorfire.dmi'
|
||||
flags_1 = ON_BORDER_1
|
||||
flags_1 = ON_BORDER_1|DEFAULT_RICOCHET_1
|
||||
CanAtmosPass = ATMOS_PASS_PROC
|
||||
|
||||
/obj/machinery/door/firedoor/border_only/closed
|
||||
@@ -320,7 +320,7 @@
|
||||
to_chat(M, "<span class='notice'>You pull [M.pulling] through [src] right as it closes</span>")
|
||||
M.pulling.forceMove(T1)
|
||||
M.start_pulling(M2)
|
||||
|
||||
|
||||
for(var/mob/living/M in T2)
|
||||
if(M.stat == CONSCIOUS && M.pulling && M.pulling.loc == T1 && !M.pulling.anchored && M.pulling.move_resist <= M.move_force)
|
||||
var/mob/living/M2 = M.pulling
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
integrity_failure = 0
|
||||
armor = list("melee" = 20, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 70, "acid" = 100)
|
||||
visible = FALSE
|
||||
flags_1 = ON_BORDER_1
|
||||
flags_1 = ON_BORDER_1|DEFAULT_RICOCHET_1
|
||||
opacity = 0
|
||||
CanAtmosPass = ATMOS_PASS_PROC
|
||||
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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, \
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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)"
|
||||
|
||||
@@ -240,7 +240,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 +272,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 +301,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 +331,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])"
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -239,6 +239,9 @@
|
||||
/obj/item/stack/medical/suture/one
|
||||
amount = 1
|
||||
|
||||
/obj/item/stack/medical/suture/five
|
||||
amount = 5
|
||||
|
||||
/obj/item/stack/medical/suture/medicated
|
||||
name = "medicated suture"
|
||||
icon_state = "suture_purp"
|
||||
@@ -319,6 +322,9 @@
|
||||
/obj/item/stack/medical/mesh/one
|
||||
amount = 1
|
||||
|
||||
/obj/item/stack/medical/mesh/five
|
||||
amount = 5
|
||||
|
||||
/obj/item/stack/medical/mesh/advanced
|
||||
name = "advanced regenerative mesh"
|
||||
desc = "An advanced mesh made with aloe extracts and sterilizing chemicals, used to treat burns."
|
||||
|
||||
@@ -672,6 +672,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 +683,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 +695,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
|
||||
|
||||
/*
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -122,11 +122,14 @@
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/item/hand_tele/proc/try_dispel_portal(atom/target, mob/user)
|
||||
if(is_parent_of_portal(target))
|
||||
/obj/item/hand_tele/proc/try_dispel_portal(atom/target, mob/user, delay = 30)
|
||||
var/datum/beam/B = user.Beam(target, icon_state = "rped_upgrade", maxdistance = 50)
|
||||
if(is_parent_of_portal(target) && (!delay || do_after(user, delay, target = target)))
|
||||
qdel(target)
|
||||
to_chat(user, "<span class='notice'>You dispel [target] with \the [src]!</span>")
|
||||
qdel(B)
|
||||
return TRUE
|
||||
qdel(B)
|
||||
return FALSE
|
||||
|
||||
/obj/item/hand_tele/afterattack(atom/target, mob/user)
|
||||
|
||||
@@ -252,6 +252,8 @@ 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."
|
||||
block_chance = 0 // oops
|
||||
force = 27.5 // oops
|
||||
item_flags = ITEM_CAN_PARRY
|
||||
block_parry_data = /datum/block_parry_data/bokken/quick_parry/proj
|
||||
|
||||
@@ -259,7 +261,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/flynn = owner
|
||||
flynn.emote("smirk")
|
||||
new /obj/effect/timestop(get_turf(owner), 2, 50, list(owner))
|
||||
new /obj/effect/timestop/magic(get_turf(owner), 1, 50, list(owner)) // null roddies counter
|
||||
|
||||
/obj/item/melee/bokken // parrying stick
|
||||
name = "bokken"
|
||||
@@ -295,7 +297,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(
|
||||
@@ -304,13 +306,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
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
var/mob/living/structureclimber
|
||||
var/broken = 0 //similar to machinery's stat BROKEN
|
||||
layer = BELOW_OBJ_LAYER
|
||||
flags_ricochet = RICOCHET_HARD
|
||||
ricochet_chance_mod = 0.5
|
||||
//ricochets on structures commented out for now because there's a lot of structures that /shouldnt/ be ricocheting and those need to be reviewed first
|
||||
//flags_1 = DEFAULT_RICOCHET_1
|
||||
//flags_ricochet = RICOCHET_HARD
|
||||
//ricochet_chance_mod = 0.5
|
||||
|
||||
/obj/structure/Initialize()
|
||||
if (!armor)
|
||||
@@ -110,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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#define STAIR_TERMINATOR_YES 2
|
||||
|
||||
// dir determines the direction of travel to go upwards (due to lack of sprites, currently only 1 and 2 make sense)
|
||||
// stairs require /turf/open/openspace as the tile above them to work
|
||||
// stairs require /turf/open/transparent/openspace as the tile above them to work
|
||||
// multiple stair objects can be chained together; the Z level transition will happen on the final stair object in the chain
|
||||
|
||||
/obj/structure/stairs
|
||||
@@ -12,7 +12,7 @@
|
||||
icon_state = "stairs"
|
||||
anchored = TRUE
|
||||
|
||||
var/force_open_above = FALSE // replaces the turf above this stair obj with /turf/open/openspace
|
||||
var/force_open_above = FALSE // replaces the turf above this stair obj with /turf/open/transparent/openspace
|
||||
var/terminator_mode = STAIR_TERMINATOR_AUTOMATIC
|
||||
var/turf/listeningTo
|
||||
|
||||
@@ -95,20 +95,20 @@
|
||||
/obj/structure/stairs/proc/build_signal_listener()
|
||||
if(listeningTo)
|
||||
UnregisterSignal(listeningTo, COMSIG_TURF_MULTIZ_NEW)
|
||||
var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
|
||||
var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP)
|
||||
RegisterSignal(T, COMSIG_TURF_MULTIZ_NEW, .proc/on_multiz_new)
|
||||
listeningTo = T
|
||||
|
||||
/obj/structure/stairs/proc/force_open_above()
|
||||
var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
|
||||
var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP)
|
||||
if(T && !istype(T))
|
||||
T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR)
|
||||
T.ChangeTurf(/turf/open/transparent/openspace, flags = CHANGETURF_INHERIT_AIR)
|
||||
|
||||
/obj/structure/stairs/proc/on_multiz_new(turf/source, dir)
|
||||
if(dir == UP)
|
||||
var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP)
|
||||
var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP)
|
||||
if(T && !istype(T))
|
||||
T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR)
|
||||
T.ChangeTurf(/turf/open/transparent/openspace, flags = CHANGETURF_INHERIT_AIR)
|
||||
|
||||
/obj/structure/stairs/intercept_zImpact(atom/movable/AM, levels = 1)
|
||||
. = ..()
|
||||
|
||||
@@ -597,7 +597,7 @@
|
||||
icon = 'icons/obj/smooth_structures/brass_table.dmi'
|
||||
icon_state = "brass_table"
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
buildstack = /obj/item/stack/tile/bronze
|
||||
buildstack = /obj/item/stack/sheet/bronze
|
||||
canSmoothWith = list(/obj/structure/table/reinforced/brass, /obj/structure/table/bronze)
|
||||
|
||||
/obj/structure/table/bronze/tablelimbsmash(mob/living/user, mob/living/pushed_mob)
|
||||
|
||||
@@ -17,7 +17,6 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
|
||||
layer = ABOVE_OBJ_LAYER //Just above doors
|
||||
pressure_resistance = 4*ONE_ATMOSPHERE
|
||||
anchored = TRUE //initially is 0 for tile smoothing
|
||||
flags_1 = ON_BORDER_1
|
||||
max_integrity = 25
|
||||
var/ini_dir = null
|
||||
var/state = WINDOW_OUT_OF_FRAME
|
||||
@@ -38,7 +37,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
|
||||
var/hitsound = 'sound/effects/Glasshit.ogg'
|
||||
rad_insulation = RAD_VERY_LIGHT_INSULATION
|
||||
rad_flags = RAD_PROTECT_CONTENTS
|
||||
flags_ricochet = RICOCHET_HARD
|
||||
flags_1 = ON_BORDER_1|DEFAULT_RICOCHET_1
|
||||
flags_ricochet = RICOCHET_HARD
|
||||
ricochet_chance_mod = 0.4
|
||||
attack_hand_speed = CLICK_CD_MELEE
|
||||
attack_hand_is_action = TRUE
|
||||
@@ -875,3 +875,26 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
|
||||
return
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/structure/window/bronze
|
||||
name = "brass window"
|
||||
desc = "A paper-thin pane of translucent yet reinforced brass. Nevermind, this is just weak bronze!"
|
||||
icon = 'icons/obj/smooth_structures/clockwork_window.dmi'
|
||||
icon_state = "clockwork_window_single"
|
||||
glass_type = /obj/item/stack/tile/bronze
|
||||
|
||||
/obj/structure/window/bronze/unanchored
|
||||
anchored = FALSE
|
||||
|
||||
/obj/structure/window/bronze/fulltile
|
||||
icon_state = "clockwork_window"
|
||||
canSmoothWith = null
|
||||
smooth = SMOOTH_TRUE
|
||||
fulltile = TRUE
|
||||
flags_1 = PREVENT_CLICK_UNDER_1
|
||||
dir = FULLTILE_WINDOW_DIR
|
||||
max_integrity = 50
|
||||
glass_amount = 2
|
||||
|
||||
/obj/structure/window/bronze/fulltile/unanchored
|
||||
anchored = FALSE
|
||||
|
||||
@@ -226,5 +226,9 @@
|
||||
soundin = pick('sound/effects/clangsmall1.ogg', 'sound/effects/clangsmall2.ogg')
|
||||
if("slosh")
|
||||
soundin = pick('sound/effects/slosh1.ogg', 'sound/effects/slosh2.ogg')
|
||||
if("smcalm")
|
||||
soundin = pick('sound/machines/sm/accent/normal/1.ogg', 'sound/machines/sm/accent/normal/2.ogg', 'sound/machines/sm/accent/normal/3.ogg', 'sound/machines/sm/accent/normal/4.ogg', 'sound/machines/sm/accent/normal/5.ogg', 'sound/machines/sm/accent/normal/6.ogg', 'sound/machines/sm/accent/normal/7.ogg', 'sound/machines/sm/accent/normal/8.ogg', 'sound/machines/sm/accent/normal/9.ogg', 'sound/machines/sm/accent/normal/10.ogg', 'sound/machines/sm/accent/normal/11.ogg', 'sound/machines/sm/accent/normal/12.ogg', 'sound/machines/sm/accent/normal/13.ogg', 'sound/machines/sm/accent/normal/14.ogg', 'sound/machines/sm/accent/normal/15.ogg', 'sound/machines/sm/accent/normal/16.ogg', 'sound/machines/sm/accent/normal/17.ogg', 'sound/machines/sm/accent/normal/18.ogg', 'sound/machines/sm/accent/normal/19.ogg', 'sound/machines/sm/accent/normal/20.ogg', 'sound/machines/sm/accent/normal/21.ogg', 'sound/machines/sm/accent/normal/22.ogg', 'sound/machines/sm/accent/normal/23.ogg', 'sound/machines/sm/accent/normal/24.ogg', 'sound/machines/sm/accent/normal/25.ogg', 'sound/machines/sm/accent/normal/26.ogg', 'sound/machines/sm/accent/normal/27.ogg', 'sound/machines/sm/accent/normal/28.ogg', 'sound/machines/sm/accent/normal/29.ogg', 'sound/machines/sm/accent/normal/30.ogg', 'sound/machines/sm/accent/normal/31.ogg', 'sound/machines/sm/accent/normal/32.ogg', 'sound/machines/sm/accent/normal/33.ogg')
|
||||
if("smdelam")
|
||||
soundin = pick('sound/machines/sm/accent/delam/1.ogg', 'sound/machines/sm/accent/normal/2.ogg', 'sound/machines/sm/accent/normal/3.ogg', 'sound/machines/sm/accent/normal/4.ogg', 'sound/machines/sm/accent/normal/5.ogg', 'sound/machines/sm/accent/normal/6.ogg', 'sound/machines/sm/accent/normal/7.ogg', 'sound/machines/sm/accent/normal/8.ogg', 'sound/machines/sm/accent/normal/9.ogg', 'sound/machines/sm/accent/normal/10.ogg', 'sound/machines/sm/accent/normal/11.ogg', 'sound/machines/sm/accent/normal/12.ogg', 'sound/machines/sm/accent/normal/13.ogg', 'sound/machines/sm/accent/normal/14.ogg', 'sound/machines/sm/accent/normal/15.ogg', 'sound/machines/sm/accent/normal/16.ogg', 'sound/machines/sm/accent/normal/17.ogg', 'sound/machines/sm/accent/normal/18.ogg', 'sound/machines/sm/accent/normal/19.ogg', 'sound/machines/sm/accent/normal/20.ogg', 'sound/machines/sm/accent/normal/21.ogg', 'sound/machines/sm/accent/normal/22.ogg', 'sound/machines/sm/accent/normal/23.ogg', 'sound/machines/sm/accent/normal/24.ogg', 'sound/machines/sm/accent/normal/25.ogg', 'sound/machines/sm/accent/normal/26.ogg', 'sound/machines/sm/accent/normal/27.ogg', 'sound/machines/sm/accent/normal/28.ogg', 'sound/machines/sm/accent/normal/29.ogg', 'sound/machines/sm/accent/normal/30.ogg', 'sound/machines/sm/accent/normal/31.ogg', 'sound/machines/sm/accent/normal/32.ogg', 'sound/machines/sm/accent/normal/33.ogg')
|
||||
//END OF CIT CHANGES
|
||||
return soundin
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
icon = 'icons/turf/walls.dmi'
|
||||
explosion_block = 50
|
||||
|
||||
/turf/closed/indestructible/rust_heretic_act()
|
||||
return
|
||||
|
||||
/turf/closed/indestructible/TerraformTurf(path, new_baseturf, flags, defer_change = FALSE, ignore_air = FALSE)
|
||||
return
|
||||
|
||||
@@ -198,13 +201,13 @@
|
||||
|
||||
/turf/closed/indestructible/rock/glacierrock
|
||||
name = "unaturally hard ice wall"
|
||||
desc = "Ice, hardened over thousands of years, you're not breaking through this."
|
||||
desc = "Ice, hardened over thousands of years, you're not breaking through this."
|
||||
icon = 'icons/turf/walls.dmi'
|
||||
icon_state = "snow_rock"
|
||||
|
||||
/turf/closed/indestructible/rock/glacierrock/blue
|
||||
name = "blue ice wall"
|
||||
desc = "The incredible compressive forces that formed this sturdy ice wall gave it a blue color."
|
||||
desc = "The incredible compressive forces that formed this sturdy ice wall gave it a blue color."
|
||||
icon = 'icons/turf/walls.dmi'
|
||||
icon_state = "ice"
|
||||
canSmoothWith = list(/turf/closed/indestructible/rock/glacierrock/blue)
|
||||
|
||||
@@ -11,66 +11,47 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
layer = SPLASHSCREEN_LAYER
|
||||
|
||||
/turf/open/openspace
|
||||
/turf/open/transparent/openspace
|
||||
name = "open space"
|
||||
desc = "Watch your step!"
|
||||
icon_state = "transparent"
|
||||
baseturfs = /turf/open/openspace
|
||||
baseturfs = /turf/open/transparent/openspace
|
||||
CanAtmosPassVertical = ATMOS_PASS_YES
|
||||
//mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
var/can_cover_up = TRUE
|
||||
var/can_build_on = TRUE
|
||||
|
||||
/turf/open/openspace/debug/update_multiz()
|
||||
/turf/open/transparent/openspace/airless
|
||||
initial_gas_mix = AIRLESS_ATMOS
|
||||
|
||||
/turf/open/transparent/openspace/debug/update_multiz()
|
||||
..()
|
||||
return TRUE
|
||||
|
||||
/turf/open/openspace/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
|
||||
///No bottom level for openspace.
|
||||
/turf/open/transparent/openspace/show_bottom_level()
|
||||
return FALSE
|
||||
|
||||
/turf/open/transparent/openspace/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
|
||||
. = ..()
|
||||
plane = OPENSPACE_PLANE
|
||||
layer = OPENSPACE_LAYER
|
||||
|
||||
vis_contents += GLOB.openspace_backdrop_one_for_all //Special grey square for projecting backdrop darkness filter on it.
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/turf/open/openspace/LateInitialize()
|
||||
update_multiz(TRUE, TRUE)
|
||||
/turf/open/transparent/openspace/can_have_cabling()
|
||||
if(locate(/obj/structure/lattice/catwalk, src))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/turf/open/openspace/Destroy()
|
||||
vis_contents.len = 0
|
||||
return ..()
|
||||
|
||||
/turf/open/openspace/update_multiz(prune_on_fail = FALSE, init = FALSE)
|
||||
. = ..()
|
||||
var/turf/T = below()
|
||||
if(!T)
|
||||
vis_contents.len = 0
|
||||
if(prune_on_fail)
|
||||
ChangeTurf(/turf/open/floor/plating)
|
||||
return FALSE
|
||||
if(init)
|
||||
vis_contents += T
|
||||
/turf/open/transparent/openspace/zAirIn()
|
||||
return TRUE
|
||||
|
||||
/turf/open/openspace/multiz_turf_del(turf/T, dir)
|
||||
if(dir != DOWN)
|
||||
return
|
||||
update_multiz()
|
||||
|
||||
/turf/open/openspace/multiz_turf_new(turf/T, dir)
|
||||
if(dir != DOWN)
|
||||
return
|
||||
update_multiz()
|
||||
|
||||
/turf/open/openspace/zAirIn()
|
||||
/turf/open/transparent/openspace/zAirOut()
|
||||
return TRUE
|
||||
|
||||
/turf/open/openspace/zAirOut()
|
||||
/turf/open/transparent/openspace/zPassIn(atom/movable/A, direction, turf/source)
|
||||
return TRUE
|
||||
|
||||
/turf/open/openspace/zPassIn(atom/movable/A, direction, turf/source)
|
||||
return TRUE
|
||||
|
||||
/turf/open/openspace/zPassOut(atom/movable/A, direction, turf/destination)
|
||||
/turf/open/transparent/openspace/zPassOut(atom/movable/A, direction, turf/destination)
|
||||
if(A.anchored)
|
||||
return FALSE
|
||||
for(var/obj/O in contents)
|
||||
@@ -78,13 +59,13 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/turf/open/openspace/proc/CanCoverUp()
|
||||
/turf/open/transparent/openspace/proc/CanCoverUp()
|
||||
return can_cover_up
|
||||
|
||||
/turf/open/openspace/proc/CanBuildHere()
|
||||
/turf/open/transparent/openspace/proc/CanBuildHere()
|
||||
return can_build_on
|
||||
|
||||
/turf/open/openspace/attackby(obj/item/C, mob/user, params)
|
||||
/turf/open/transparent/openspace/attackby(obj/item/C, mob/user, params)
|
||||
..()
|
||||
if(!CanBuildHere())
|
||||
return
|
||||
@@ -98,14 +79,14 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
|
||||
if(L)
|
||||
if(R.use(1))
|
||||
to_chat(user, "<span class='notice'>You construct a catwalk.</span>")
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
new/obj/structure/lattice/catwalk(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need two rods to build a catwalk!</span>")
|
||||
return
|
||||
if(R.use(1))
|
||||
to_chat(user, "<span class='notice'>You construct a lattice.</span>")
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
ReplaceWithLattice()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need one rod to build a lattice.</span>")
|
||||
@@ -118,7 +99,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
|
||||
var/obj/item/stack/tile/plasteel/S = C
|
||||
if(S.use(1))
|
||||
qdel(L)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
to_chat(user, "<span class='notice'>You build a floor.</span>")
|
||||
PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
@@ -126,7 +107,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The plating is going to need some support! Place metal rods first.</span>")
|
||||
|
||||
/turf/open/openspace/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
|
||||
/turf/open/transparent/openspace/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
|
||||
if(!CanBuildHere())
|
||||
return FALSE
|
||||
|
||||
@@ -139,7 +120,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
|
||||
return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 3)
|
||||
return FALSE
|
||||
|
||||
/turf/open/openspace/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
|
||||
/turf/open/transparent/openspace/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
|
||||
switch(passed_mode)
|
||||
if(RCD_FLOORWALL)
|
||||
to_chat(user, "<span class='notice'>You build a floor.</span>")
|
||||
@@ -147,12 +128,12 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/turf/open/openspace/icemoon
|
||||
/turf/open/transparent/openspace/icemoon
|
||||
name = "ice chasm"
|
||||
baseturfs = /turf/open/openspace/icemoon
|
||||
can_cover_up = FALSE
|
||||
can_build_on = FALSE
|
||||
baseturfs = /turf/open/transparent/openspace/icemoon
|
||||
can_cover_up = TRUE
|
||||
can_build_on = TRUE
|
||||
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
|
||||
|
||||
/turf/open/openspace/icemoon/can_zFall(atom/movable/A, levels = 1, turf/target)
|
||||
/turf/open/transparent/openspace/icemoon/can_zFall(atom/movable/A, levels = 1, turf/target)
|
||||
return TRUE
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/turf/open/transparent
|
||||
baseturfs = /turf/open/transparent/openspace
|
||||
intact = FALSE //this means wires go on top
|
||||
|
||||
/turf/open/transparent/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
|
||||
. = ..()
|
||||
plane = OPENSPACE_PLANE
|
||||
layer = OPENSPACE_LAYER
|
||||
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/turf/open/transparent/LateInitialize()
|
||||
update_multiz(TRUE, TRUE)
|
||||
|
||||
/turf/open/transparent/Destroy()
|
||||
vis_contents.len = 0
|
||||
return ..()
|
||||
|
||||
/turf/open/transparent/update_multiz(prune_on_fail = FALSE, init = FALSE)
|
||||
. = ..()
|
||||
var/turf/T = below()
|
||||
if(!T)
|
||||
vis_contents.len = 0
|
||||
if(!show_bottom_level() && prune_on_fail) //If we cant show whats below, and we prune on fail, change the turf to plating as a fallback
|
||||
ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
|
||||
return FALSE
|
||||
if(init)
|
||||
vis_contents += T
|
||||
return TRUE
|
||||
|
||||
/turf/open/transparent/multiz_turf_del(turf/T, dir)
|
||||
if(dir != DOWN)
|
||||
return
|
||||
update_multiz()
|
||||
|
||||
/turf/open/transparent/multiz_turf_new(turf/T, dir)
|
||||
if(dir != DOWN)
|
||||
return
|
||||
update_multiz()
|
||||
|
||||
///Called when there is no real turf below this turf
|
||||
/turf/open/transparent/proc/show_bottom_level()
|
||||
var/turf/path = SSmapping.level_trait(z, ZTRAIT_BASETURF) || /turf/open/space
|
||||
if(!ispath(path))
|
||||
path = text2path(path)
|
||||
if(!ispath(path))
|
||||
warning("Z-level [z] has invalid baseturf '[SSmapping.level_trait(z, ZTRAIT_BASETURF)]'")
|
||||
path = /turf/open/space
|
||||
var/mutable_appearance/underlay_appearance = mutable_appearance(initial(path.icon), initial(path.icon_state), layer = TURF_LAYER, plane = PLANE_SPACE)
|
||||
underlays += underlay_appearance
|
||||
return TRUE
|
||||
|
||||
|
||||
/turf/open/transparent/glass
|
||||
name = "Glass floor"
|
||||
desc = "Dont jump on it, or do, I'm not your mom."
|
||||
icon = 'icons/turf/floors/glass.dmi'
|
||||
icon_state = "floor_glass"
|
||||
smooth = SMOOTH_MORE
|
||||
var/floor_tile = /obj/item/stack/sheet/glass
|
||||
canSmoothWith = list(/turf/open/transparent/glass, /turf/open/transparent/glass/reinforced)
|
||||
footstep = FOOTSTEP_PLATING
|
||||
barefootstep = FOOTSTEP_HARD_BAREFOOT
|
||||
clawfootstep = FOOTSTEP_HARD_CLAW
|
||||
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
|
||||
|
||||
/turf/open/transparent/glass/Initialize()
|
||||
icon_state = "" //Prevent the normal icon from appearing behind the smooth overlays
|
||||
return ..()
|
||||
|
||||
/turf/open/transparent/glass/wrench_act(mob/living/user, obj/item/I)
|
||||
to_chat(user, "<span class='notice'>You begin removing glass...</span>")
|
||||
if(I.use_tool(src, user, 30, volume=80))
|
||||
if(!istype(src, /turf/open/transparent/glass))
|
||||
return TRUE
|
||||
if(floor_tile)
|
||||
new floor_tile(src, 2)
|
||||
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
|
||||
return TRUE
|
||||
|
||||
/turf/open/transparent/glass/reinforced
|
||||
name = "Reinforced glass floor"
|
||||
desc = "Do jump on it, it can take it."
|
||||
icon = 'icons/turf/floors/reinf_glass.dmi'
|
||||
floor_tile = /obj/item/stack/sheet/rglass
|
||||
|
||||
/turf/open/transparent/glass/reinforced/wrench_act(mob/living/user, obj/item/I)
|
||||
to_chat(user, "<span class='notice'>You begin removing reinforced glass...</span>")
|
||||
if(I.use_tool(src, user, 30, volume=80))
|
||||
if(!istype(src, /turf/open/transparent/glass/reinforced))
|
||||
return TRUE
|
||||
if(floor_tile)
|
||||
new floor_tile(src, 2)
|
||||
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
|
||||
return TRUE
|
||||
@@ -63,6 +63,11 @@
|
||||
to_chat(user, "<span class='notice'>You forcefully pry off the planks, destroying them in the process.</span>")
|
||||
return make_plating()
|
||||
|
||||
/turf/open/floor/wood/rust_heretic_act()
|
||||
if(prob(70))
|
||||
new /obj/effect/temp_visual/glowing_rune(src)
|
||||
ChangeTurf(/turf/open/floor/plating/rust)
|
||||
|
||||
/turf/open/floor/wood/cold
|
||||
temperature = 255.37
|
||||
|
||||
|
||||
@@ -58,6 +58,12 @@
|
||||
if(exposed_temperature > 300)
|
||||
PlasmaBurn(exposed_temperature)
|
||||
|
||||
// Plasma floor that can't be removed, for disco
|
||||
|
||||
/turf/open/floor/mineral/plasma/disco
|
||||
name = "disco floor"
|
||||
/turf/open/floor/mineral/plasma/disco/crowbar_act(mob/living/user, obj/item/I)
|
||||
return
|
||||
|
||||
//GOLD
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@
|
||||
desc = "Some heavy bronze tiles."
|
||||
icon = 'icons/obj/clockwork_objects.dmi'
|
||||
icon_state = "clockwork_floor"
|
||||
floor_tile = /obj/item/stack/tile/bronze
|
||||
floor_tile = /obj/item/stack/sheet/bronze
|
||||
|
||||
/turf/open/floor/padded
|
||||
name = "padded floor"
|
||||
@@ -267,3 +267,15 @@
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "floor_padded"
|
||||
floor_tile = /obj/item/stack/tile/padded
|
||||
|
||||
/turf/open/floor/plating/rust
|
||||
name = "rusted plating"
|
||||
desc = "Corrupted steel."
|
||||
icon_state = "plating_rust"
|
||||
footstep = FOOTSTEP_RUST
|
||||
barefootstep = FOOTSTEP_RUST
|
||||
clawfootstep = FOOTSTEP_RUST
|
||||
heavyfootstep = FOOTSTEP_RUST
|
||||
|
||||
/turf/open/floor/plating/rust/rust_heretic_act()
|
||||
return
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
. = ..()
|
||||
. += "<span class='notice'>There's a <b>small crack</b> on the edge of it.</span>"
|
||||
|
||||
/turf/open/floor/plasteel/rust_heretic_act()
|
||||
if(prob(70))
|
||||
new /obj/effect/temp_visual/glowing_rune(src)
|
||||
ChangeTurf(/turf/open/floor/plating/rust)
|
||||
|
||||
/turf/open/floor/plasteel/update_icon()
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
@@ -66,6 +66,40 @@
|
||||
R.use(2)
|
||||
to_chat(user, "<span class='notice'>You reinforce the floor.</span>")
|
||||
return
|
||||
if(istype(C, /obj/item/stack/sheet/glass))
|
||||
if(broken || burnt)
|
||||
to_chat(user, "<span class='warning'>Repair the plating first!</span>")
|
||||
return
|
||||
var/obj/item/stack/sheet/glass/G = C
|
||||
if (G.get_amount() < 2)
|
||||
to_chat(user, "<span class='warning'>You need two glass sheets to make a glass floor!</span>")
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You begin adding glass to the floor...</span>")
|
||||
if(do_after(user, 5, target = src))
|
||||
if (G.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass))
|
||||
PlaceOnTop(/turf/open/transparent/glass, flags = CHANGETURF_INHERIT_AIR)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
|
||||
G.use(2)
|
||||
to_chat(user, "<span class='notice'>You add glass to the floor.</span>")
|
||||
return
|
||||
if(istype(C, /obj/item/stack/sheet/rglass))
|
||||
if(broken || burnt)
|
||||
to_chat(user, "<span class='warning'>Repair the plating first!</span>")
|
||||
return
|
||||
var/obj/item/stack/sheet/rglass/RG = C
|
||||
if (RG.get_amount() < 2)
|
||||
to_chat(user, "<span class='warning'>You need two reinforced glass sheets to make a reinforced glass floor!</span>")
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You begin adding reinforced glass to the floor...</span>")
|
||||
if(do_after(user, 10, target = src))
|
||||
if (RG.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass/reinforced))
|
||||
PlaceOnTop(/turf/open/transparent/glass/reinforced, flags = CHANGETURF_INHERIT_AIR)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
|
||||
RG.use(2)
|
||||
to_chat(user, "<span class='notice'>You add reinforced glass to the floor.</span>")
|
||||
return
|
||||
else if(istype(C, /obj/item/stack/tile))
|
||||
if(!broken && !burnt)
|
||||
for(var/obj/O in src)
|
||||
@@ -98,6 +132,11 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
/turf/open/floor/plating/rust_heretic_act()
|
||||
if(prob(70))
|
||||
new /obj/effect/temp_visual/glowing_rune(src)
|
||||
ChangeTurf(/turf/open/floor/plating/rust)
|
||||
|
||||
/turf/open/floor/plating/make_plating()
|
||||
return
|
||||
|
||||
|
||||
@@ -192,6 +192,7 @@
|
||||
icon_state = "map-shuttle"
|
||||
explosion_block = 3
|
||||
flags_1 = CAN_BE_DIRTY_1 | DEFAULT_RICOCHET_1
|
||||
flags_ricochet = RICOCHET_SHINY | RICOCHET_HARD
|
||||
sheet_type = /obj/item/stack/sheet/mineral/titanium
|
||||
smooth = SMOOTH_MORE|SMOOTH_DIAGONAL
|
||||
canSmoothWith = list(/turf/closed/wall/mineral/titanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock, /obj/structure/window/shuttle, /obj/structure/shuttle/engine/heater, /obj/structure/falsewall/titanium)
|
||||
|
||||
@@ -188,17 +188,25 @@
|
||||
icon = 'icons/turf/walls/rusty_wall.dmi'
|
||||
hardness = 45
|
||||
|
||||
/turf/closed/wall/rust/rust_heretic_act()
|
||||
ScrapeAway()
|
||||
|
||||
/turf/closed/wall/r_wall/rust
|
||||
name = "rusted reinforced wall"
|
||||
desc = "A huge chunk of rusted reinforced metal."
|
||||
icon = 'icons/turf/walls/rusty_reinforced_wall.dmi'
|
||||
hardness = 15
|
||||
|
||||
/turf/closed/wall/r_wall/rust/rust_heretic_act()
|
||||
if(prob(50))
|
||||
return
|
||||
ScrapeAway()
|
||||
|
||||
/turf/closed/wall/mineral/bronze
|
||||
name = "clockwork wall"
|
||||
desc = "A huge chunk of bronze, decorated like gears and cogs."
|
||||
icon = 'icons/turf/walls/clockwork_wall.dmi'
|
||||
icon_state = "clockwork_wall"
|
||||
sheet_type = /obj/item/stack/tile/bronze
|
||||
sheet_type = /obj/item/stack/sheet/bronze
|
||||
sheet_amount = 2
|
||||
girder_type = /obj/structure/girder/bronze
|
||||
|
||||
@@ -235,6 +235,13 @@
|
||||
if(the_rcd.canRturf)
|
||||
return ..()
|
||||
|
||||
/turf/closed/wall/r_wall/rust_heretic_act()
|
||||
if(prob(50))
|
||||
return
|
||||
if(prob(70))
|
||||
new /obj/effect/temp_visual/glowing_rune(src)
|
||||
ChangeTurf(/turf/closed/wall/r_wall/rust)
|
||||
|
||||
/turf/closed/wall/r_wall/syndicate
|
||||
name = "hull"
|
||||
desc = "The armored hull of an ominous looking ship."
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
icon = 'icons/turf/walls/wall.dmi'
|
||||
icon_state = "wall"
|
||||
explosion_block = 1
|
||||
|
||||
flags_1 = DEFAULT_RICOCHET_1
|
||||
flags_ricochet = RICOCHET_HARD
|
||||
thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
|
||||
heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m plasteel wall
|
||||
attack_hand_speed = 8
|
||||
@@ -324,4 +325,9 @@
|
||||
|
||||
add_overlay(dent_decals)
|
||||
|
||||
/turf/closed/wall/rust_heretic_act()
|
||||
if(prob(70))
|
||||
new /obj/effect/temp_visual/glowing_rune(src)
|
||||
ChangeTurf(/turf/closed/wall/rust)
|
||||
|
||||
#undef MAX_DENT_DECALS
|
||||
|
||||
@@ -14,6 +14,8 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
var/list/objectives = list()
|
||||
var/antag_memory = ""//These will be removed with antag datum
|
||||
var/antag_moodlet //typepath of moodlet that the mob will gain with their status
|
||||
var/antag_hud_type
|
||||
var/antag_hud_name
|
||||
/// If above 0, this is the multiplier for the speed at which we hijack the shuttle. Do not directly read, use hijack_speed().
|
||||
var/hijack_speed = 0
|
||||
|
||||
@@ -77,6 +79,17 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
hud.leave_hud(mob_override)
|
||||
set_antag_hud(mob_override, null)
|
||||
|
||||
// Handles adding and removing the clumsy mutation from clown antags. Gets called in apply/remove_innate_effects
|
||||
/datum/antagonist/proc/handle_clown_mutation(mob/living/mob_override, message, removing = TRUE)
|
||||
var/mob/living/carbon/human/H = mob_override
|
||||
if(H && istype(H) && owner.assigned_role == "Clown")
|
||||
if(removing) // They're a clown becoming an antag, remove clumsy
|
||||
H.dna.remove_mutation(CLOWNMUT)
|
||||
if(!silent && message)
|
||||
to_chat(H, "<span class='boldnotice'>[message]</span>")
|
||||
else
|
||||
H.dna.add_mutation(CLOWNMUT) // We're removing their antag status, add back clumsy
|
||||
|
||||
//Assign default team and creates one for one of a kind team antagonists
|
||||
/datum/antagonist/proc/create_team(datum/team/team)
|
||||
return
|
||||
|
||||
@@ -37,14 +37,14 @@ GLOBAL_LIST_INIT(abductor_gear, subtypesof(/datum/abductor_gear))
|
||||
description = "A dual-mode tool for retrieving specimens and scanning appearances. Scanning can be done through cameras."
|
||||
id = "science_tool"
|
||||
build_path = /obj/item/abductor/gizmo
|
||||
/*
|
||||
|
||||
/datum/abductor_gear/advanced_baton
|
||||
name = "Advanced Baton"
|
||||
description = "A quad-mode baton used for incapacitation and restraining of specimens."
|
||||
id = "advanced_baton"
|
||||
cost = 2
|
||||
build_path = /obj/item/melee/baton/abductor //does not exist?
|
||||
*/
|
||||
build_path = /obj/item/abductor/baton //does not exist?
|
||||
|
||||
/datum/abductor_gear/superlingual_matrix
|
||||
name = "Superlingual Matrix"
|
||||
description = "A mysterious structure that allows for instant communication between users. Pretty impressive until you need to eat something."
|
||||
|
||||
@@ -30,6 +30,22 @@
|
||||
/// Possible gear to be dispensed
|
||||
var/list/possible_gear
|
||||
|
||||
/obj/machinery/abductor/console/Initialize(mapload)
|
||||
. = ..()
|
||||
possible_gear = get_abductor_gear()
|
||||
|
||||
/**
|
||||
* get_abductor_gear: Returns a list of a filtered abductor gear sorted by categories
|
||||
*/
|
||||
/obj/machinery/abductor/console/proc/get_abductor_gear()
|
||||
var/list/filtered_modules = list()
|
||||
for(var/path in GLOB.abductor_gear)
|
||||
var/datum/abductor_gear/AG = new path
|
||||
if(!filtered_modules[AG.category])
|
||||
filtered_modules[AG.category] = list()
|
||||
filtered_modules[AG.category][AG] = AG
|
||||
return filtered_modules
|
||||
|
||||
/obj/machinery/abductor/console/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING) && !HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
|
||||
to_chat(user, "<span class='warning'>You start mashing alien buttons at random!</span>")
|
||||
|
||||
@@ -45,11 +45,8 @@
|
||||
desc = "A solid wall of slightly twitching tendrils with a reflective glow."
|
||||
damaged_desc = "A wall of twitching tendrils with a reflective glow."
|
||||
icon_state = "blob_glow"
|
||||
flags_ricochet = RICOCHET_SHINY
|
||||
point_return = 8
|
||||
max_integrity = 100
|
||||
brute_resist = 1
|
||||
explosion_block = 2
|
||||
|
||||
/obj/structure/blob/shield/reflective/check_projectile_ricochet(obj/item/projectile/P)
|
||||
return PROJECTILE_RICOCHET_FORCE
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
if(istype(owner.current.loc, /obj/structure/closet/crate/coffin))
|
||||
Torpor_Begin()
|
||||
// Wait before next pass
|
||||
FreeAllVassals() // Free my Vassals! (if I haven't yet)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -308,6 +307,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// HUMAN FOOD
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
ADD_TRAIT(user, TRAIT_PIERCEIMMUNE, "fortitude")
|
||||
ADD_TRAIT(user, TRAIT_NODISMEMBER, "fortitude")
|
||||
ADD_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude")
|
||||
ADD_TRAIT(user, TRAIT_NORUNNING, "fortitude")
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
fortitude_resist = max(0.3, 0.7 - level_current * 0.1)
|
||||
@@ -53,6 +54,7 @@
|
||||
REMOVE_TRAIT(user, TRAIT_PIERCEIMMUNE, "fortitude")
|
||||
REMOVE_TRAIT(user, TRAIT_NODISMEMBER, "fortitude")
|
||||
REMOVE_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude")
|
||||
REMOVE_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude")
|
||||
if(!ishuman(owner))
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner
|
||||
|
||||
@@ -89,17 +89,17 @@
|
||||
creation_message = "<span class='alloy bold'>The cogscarab clicks and whirrs as it hops up and springs to life!</span>"
|
||||
construct_type = /mob/living/simple_animal/drone/cogscarab
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/infinite_resources = TRUE
|
||||
var/infinite_resources = FALSE //No.
|
||||
var/static/obj/item/seasonal_hat //Share it with all other scarabs, since we're from the same cult!
|
||||
|
||||
/obj/item/clockwork/construct_chassis/cogscarab/Initialize()
|
||||
. = ..()
|
||||
if(GLOB.servants_active)
|
||||
infinite_resources = FALSE //For any that are somehow spawned in late
|
||||
infinite_resources = FALSE //This check is relatively irrelevant until *someone* makes the infinite resources var default to true again, so, leaving it in.
|
||||
|
||||
/obj/item/clockwork/construct_chassis/cogscarab/pre_spawn()
|
||||
if(infinite_resources)
|
||||
//During rounds where they can't interact with the station, let them experiment with builds
|
||||
//During rounds where they can't interact with the station, let them experiment with builds, if an admin allows them to.
|
||||
construct_type = /mob/living/simple_animal/drone/cogscarab/ratvar
|
||||
if(!seasonal_hat)
|
||||
var/obj/item/drone_shell/D = locate() in GLOB.poi_list
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
desc = "Charges your slab with divine energy, allowing you to overwhelm a target with Ratvar's light."
|
||||
invocations = list("Divinity, show them your light!")
|
||||
whispered = TRUE
|
||||
channel_time = 15 // I think making kindle channel a third of the time less is a good make up for the fact that it silences people for such a little amount of time.
|
||||
channel_time = 25 //2.5 seconds should be a okay compromise between being able to use it when needed, and not being able to just pause in combat for a second and hardstunning your enemy
|
||||
power_cost = 125
|
||||
usage_tip = "The light can be used from up to two tiles away. Damage taken will GREATLY REDUCE the stun's duration."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
@@ -137,6 +137,30 @@
|
||||
quickbind_desc = "Applies handcuffs to a struck target."
|
||||
|
||||
|
||||
//Belligerent: Channeled for up to fifteen times over thirty seconds. Forces non-servants that can hear the chant to walk, doing minor damage. Nar-Sian cultists are burned.
|
||||
/datum/clockwork_scripture/channeled/belligerent
|
||||
descname = "Channeled, Area Slowdown"
|
||||
name = "Belligerent"
|
||||
desc = "Forces all nearby non-servants to walk rather than run, doing minor damage. Chanted every two seconds for up to thirty seconds."
|
||||
chant_invocations = list("Punish their blindness!", "Take time, make slow!", "Kneel before The Justiciar!", "Halt their charges!", "Cease the tides!")
|
||||
chant_amount = 15
|
||||
chant_interval = 20
|
||||
channel_time = 20
|
||||
power_cost = 300
|
||||
usage_tip = "Useful for crowd control in a populated area and disrupting mass movement."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
primary_component = BELLIGERENT_EYE
|
||||
sort_priority = 7
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Forces nearby non-Servants to walk, doing minor damage with each chant.<br><b>Maximum 15 chants.</b>"
|
||||
|
||||
/datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number)
|
||||
for(var/mob/living/carbon/C in hearers(7, invoker))
|
||||
C.apply_status_effect(STATUS_EFFECT_BELLIGERENT)
|
||||
new /obj/effect/temp_visual/ratvar/belligerent(get_turf(invoker))
|
||||
return TRUE
|
||||
|
||||
|
||||
//Vanguard: Provides twenty seconds of greatly increased stamina regeneration and stun immunity. At the end of the twenty seconds, 25% of all stuns absorbed aswell as 50% of healed stamloss are applied to the invoker.
|
||||
/datum/clockwork_scripture/vanguard
|
||||
descname = "Self Stun Immunity"
|
||||
@@ -149,7 +173,7 @@
|
||||
usage_tip = "You cannot reactivate Vanguard while still shielded by it."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
primary_component = VANGUARD_COGWHEEL
|
||||
sort_priority = 7
|
||||
sort_priority = 8
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Allows you to temporarily have quickly regenerating stamina and absorb stuns. Part of the stuns absorbed and staminaloss healed will affect you when disabled."
|
||||
|
||||
@@ -181,7 +205,7 @@
|
||||
usage_tip = "The Compromise is very fast to invoke, and will remove holy water from the target Servant."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
primary_component = VANGUARD_COGWHEEL
|
||||
sort_priority = 8
|
||||
sort_priority = 9
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Allows you to convert a Servant's brute, burn, and oxygen damage to half toxin damage.<br><b>Click your slab to disable.</b>"
|
||||
slab_overlay = "compromise"
|
||||
@@ -255,7 +279,7 @@
|
||||
tier = SCRIPTURE_DRIVER
|
||||
space_allowed = TRUE
|
||||
primary_component = GEIS_CAPACITOR
|
||||
sort_priority = 10
|
||||
sort_priority = 11
|
||||
important = TRUE
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Creates a new Clockwork Slab."
|
||||
@@ -276,7 +300,7 @@
|
||||
tier = SCRIPTURE_DRIVER
|
||||
space_allowed = TRUE
|
||||
primary_component = GEIS_CAPACITOR
|
||||
sort_priority = 11
|
||||
sort_priority = 12
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Creates a pair of Wraith Spectacles, which grant true sight but cause gradual vision loss."
|
||||
|
||||
@@ -295,7 +319,7 @@
|
||||
usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
primary_component = GEIS_CAPACITOR
|
||||
sort_priority = 9
|
||||
sort_priority = 10
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Allows you to create a one-way Spatial Gateway to a living Servant or Clockwork Obelisk."
|
||||
|
||||
|
||||
@@ -459,26 +459,3 @@
|
||||
invoker.light_range = 0
|
||||
invoker.update_light()
|
||||
return ..()
|
||||
|
||||
//Belligerent: Channeled for up to fifteen times over thirty seconds. Forces non-servants that can hear the chant to walk, doing minor damage. Nar-Sian cultists are burned.
|
||||
/datum/clockwork_scripture/channeled/belligerent
|
||||
descname = "Channeled, Area Slowdown"
|
||||
name = "Belligerent"
|
||||
desc = "Forces all nearby non-servants to walk rather than run, doing minor damage. Chanted every two seconds for up to thirty seconds."
|
||||
chant_invocations = list("Punish their blindness!", "Take time, make slow!", "Kneel before The Justiciar!", "Halt their charges!", "Cease the tides!")
|
||||
chant_amount = 15
|
||||
chant_interval = 20
|
||||
channel_time = 20
|
||||
power_cost = 300
|
||||
usage_tip = "Useful for crowd control in a populated area and disrupting mass movement."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
primary_component = BELLIGERENT_EYE
|
||||
sort_priority = 1
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Forces nearby non-Servants to walk, doing minor damage with each chant.<br><b>Maximum 15 chants.</b>"
|
||||
|
||||
/datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number)
|
||||
for(var/mob/living/carbon/C in hearers(7, invoker))
|
||||
C.apply_status_effect(STATUS_EFFECT_BELLIGERENT)
|
||||
new /obj/effect/temp_visual/ratvar/belligerent(get_turf(invoker))
|
||||
return TRUE
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
/datum/antagonist/heretic
|
||||
name = "Heretic"
|
||||
roundend_category = "Heretics"
|
||||
antagpanel_category = "Heretic"
|
||||
antag_moodlet = /datum/mood_event/heretics
|
||||
job_rank = ROLE_HERETIC
|
||||
antag_hud_type = ANTAG_HUD_HERETIC
|
||||
antag_hud_name = "heretic"
|
||||
var/give_equipment = TRUE
|
||||
var/list/researched_knowledge = list()
|
||||
var/total_sacrifices = 0
|
||||
var/ascended = FALSE
|
||||
|
||||
/datum/antagonist/heretic/admin_add(datum/mind/new_owner,mob/admin)
|
||||
give_equipment = TRUE
|
||||
new_owner.add_antag_datum(src)
|
||||
message_admins("[key_name_admin(admin)] has heresized [key_name_admin(new_owner)].")
|
||||
log_admin("[key_name(admin)] has heresized [key_name(new_owner)].")
|
||||
|
||||
/datum/antagonist/heretic/greet()
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ecult_op.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change
|
||||
to_chat(owner, "<span class='boldannounce'>You are the Heretic!</span><br>\
|
||||
<B>The old ones gave you these tasks to fulfill:</B>")
|
||||
owner.announce_objectives()
|
||||
to_chat(owner, "<span class='cult'>The book whispers, the forbidden knowledge walks once again!<br>\
|
||||
Your book allows you to research abilities, but be careful, you cannot undo what has been done.<br>\
|
||||
You gain charges by either collecting influences or sacrificing people tracked by the living heart<br> \
|
||||
You can find a basic guide at : https://tgstation13.org/wiki/Heresy_101 </span>")
|
||||
|
||||
/datum/antagonist/heretic/on_gain()
|
||||
var/mob/living/current = owner.current
|
||||
if(ishuman(current))
|
||||
forge_primary_objectives()
|
||||
gain_knowledge(/datum/eldritch_knowledge/spell/basic)
|
||||
gain_knowledge(/datum/eldritch_knowledge/living_heart)
|
||||
gain_knowledge(/datum/eldritch_knowledge/codex_cicatrix)
|
||||
gain_knowledge(/datum/eldritch_knowledge/eldritch_blade)
|
||||
current.log_message("has been converted to the cult of the forgotten ones!", LOG_ATTACK, color="#960000")
|
||||
GLOB.reality_smash_track.AddMind(owner)
|
||||
START_PROCESSING(SSprocessing,src)
|
||||
if(give_equipment)
|
||||
equip_cultist()
|
||||
owner.teach_crafting_recipe(/datum/crafting_recipe/heretic/codex)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/heretic/on_removal()
|
||||
|
||||
for(var/X in researched_knowledge)
|
||||
var/datum/eldritch_knowledge/EK = researched_knowledge[X]
|
||||
EK.on_lose(owner.current)
|
||||
|
||||
if(!silent)
|
||||
to_chat(owner.current, "<span class='userdanger'>Your mind begins to flare as the otherwordly knowledge escapes your grasp!</span>")
|
||||
owner.current.log_message("has renounced the cult of the old ones!", LOG_ATTACK, color="#960000")
|
||||
GLOB.reality_smash_track.RemoveMind(owner)
|
||||
STOP_PROCESSING(SSprocessing,src)
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/antagonist/heretic/proc/equip_cultist()
|
||||
var/mob/living/carbon/H = owner.current
|
||||
if(!istype(H))
|
||||
return
|
||||
. += ecult_give_item(/obj/item/forbidden_book, H)
|
||||
. += ecult_give_item(/obj/item/living_heart, H)
|
||||
|
||||
/datum/antagonist/heretic/proc/ecult_give_item(obj/item/item_path, mob/living/carbon/human/H)
|
||||
var/list/slots = list(
|
||||
"backpack" = SLOT_IN_BACKPACK,
|
||||
"left pocket" = SLOT_L_STORE,
|
||||
"right pocket" = SLOT_R_STORE
|
||||
)
|
||||
|
||||
var/T = new item_path(H)
|
||||
var/item_name = initial(item_path.name)
|
||||
var/where = H.equip_in_one_of_slots(T, slots)
|
||||
if(!where)
|
||||
to_chat(H, "<span class='userdanger'>Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).</span>")
|
||||
return FALSE
|
||||
else
|
||||
to_chat(H, "<span class='danger'>You have a [item_name] in your [where].</span>")
|
||||
if(where == "backpack")
|
||||
SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H)
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/heretic/process()
|
||||
|
||||
for(var/X in researched_knowledge)
|
||||
var/datum/eldritch_knowledge/EK = researched_knowledge[X]
|
||||
EK.on_life(owner.current)
|
||||
|
||||
/datum/antagonist/heretic/proc/forge_primary_objectives()
|
||||
var/list/assasination = list()
|
||||
var/list/protection = list()
|
||||
for(var/i in 1 to 2)
|
||||
var/pck = pick("assasinate","protect")
|
||||
switch(pck)
|
||||
if("assasinate")
|
||||
var/datum/objective/assassinate/A = new
|
||||
A.owner = owner
|
||||
var/list/owners = A.get_owners()
|
||||
A.find_target(owners,protection)
|
||||
assasination += A.target
|
||||
objectives += A
|
||||
if("protect")
|
||||
var/datum/objective/protect/P = new
|
||||
P.owner = owner
|
||||
var/list/owners = P.get_owners()
|
||||
P.find_target(owners,assasination)
|
||||
protection += P.target
|
||||
objectives += P
|
||||
|
||||
|
||||
var/datum/objective/sacrifice_ecult/SE = new
|
||||
SE.owner = owner
|
||||
SE.update_explanation_text()
|
||||
objectives += SE
|
||||
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = owner
|
||||
objectives += escape_objective
|
||||
|
||||
/datum/antagonist/heretic/apply_innate_effects(mob/living/mob_override)
|
||||
. = ..()
|
||||
var/mob/living/current = owner.current
|
||||
if(mob_override)
|
||||
current = mob_override
|
||||
add_antag_hud(antag_hud_type, antag_hud_name, current)
|
||||
handle_clown_mutation(current, mob_override ? null : "Knowledge described in the book allowed you to overcome your clownish nature, allowing you to use complex items effectively.")
|
||||
current.faction |= "heretics"
|
||||
|
||||
/datum/antagonist/heretic/remove_innate_effects(mob/living/mob_override)
|
||||
. = ..()
|
||||
var/mob/living/current = owner.current
|
||||
if(mob_override)
|
||||
current = mob_override
|
||||
remove_antag_hud(antag_hud_type, current)
|
||||
handle_clown_mutation(current, removing = FALSE)
|
||||
current.faction -= "heretics"
|
||||
|
||||
/datum/antagonist/heretic/get_admin_commands()
|
||||
. = ..()
|
||||
.["Equip"] = CALLBACK(src,.proc/equip_cultist)
|
||||
|
||||
/datum/antagonist/heretic/roundend_report()
|
||||
var/list/parts = list()
|
||||
|
||||
var/cultiewin = TRUE
|
||||
|
||||
parts += printplayer(owner)
|
||||
parts += "<b>Sacrifices Made:</b> [total_sacrifices]"
|
||||
|
||||
if(length(objectives))
|
||||
var/count = 1
|
||||
for(var/o in objectives)
|
||||
var/datum/objective/objective = o
|
||||
if(objective.check_completion())
|
||||
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</b></span>"
|
||||
else
|
||||
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
cultiewin = FALSE
|
||||
count++
|
||||
if(ascended)
|
||||
parts += "<span class='greentext big'>HERETIC HAS ASCENDED!</span>"
|
||||
else
|
||||
if(cultiewin)
|
||||
parts += "<span class='greentext'>The heretic was successful!</span>"
|
||||
else
|
||||
parts += "<span class='redtext'>The heretic has failed.</span>"
|
||||
|
||||
parts += "<b>Knowledge Researched:</b> "
|
||||
|
||||
var/list/knowledge_message = list()
|
||||
var/list/knowledge = get_all_knowledge()
|
||||
for(var/X in knowledge)
|
||||
var/datum/eldritch_knowledge/EK = knowledge[X]
|
||||
knowledge_message += "[EK.name]"
|
||||
parts += knowledge_message.Join(", ")
|
||||
|
||||
return parts.Join("<br>")
|
||||
////////////////
|
||||
// Knowledge //
|
||||
////////////////
|
||||
|
||||
/datum/antagonist/heretic/proc/gain_knowledge(datum/eldritch_knowledge/EK)
|
||||
if(get_knowledge(EK))
|
||||
return FALSE
|
||||
var/datum/eldritch_knowledge/initialized_knowledge = new EK
|
||||
researched_knowledge[initialized_knowledge.type] = initialized_knowledge
|
||||
initialized_knowledge.on_gain(owner.current)
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/heretic/proc/get_researchable_knowledge()
|
||||
var/list/researchable_knowledge = list()
|
||||
var/list/banned_knowledge = list()
|
||||
for(var/X in researched_knowledge)
|
||||
var/datum/eldritch_knowledge/EK = researched_knowledge[X]
|
||||
researchable_knowledge |= EK.next_knowledge
|
||||
banned_knowledge |= EK.banned_knowledge
|
||||
banned_knowledge |= EK.type
|
||||
researchable_knowledge -= banned_knowledge
|
||||
return researchable_knowledge
|
||||
|
||||
/datum/antagonist/heretic/proc/get_knowledge(wanted)
|
||||
return researched_knowledge[wanted]
|
||||
|
||||
/datum/antagonist/heretic/proc/get_all_knowledge()
|
||||
return researched_knowledge
|
||||
|
||||
////////////////
|
||||
// Objectives //
|
||||
////////////////
|
||||
|
||||
/datum/objective/sacrifice_ecult
|
||||
name = "sacrifice"
|
||||
|
||||
/datum/objective/sacrifice_ecult/update_explanation_text()
|
||||
. = ..()
|
||||
target_amount = rand(2,4)
|
||||
explanation_text = "Sacrifice at least [target_amount] people."
|
||||
|
||||
/datum/objective/sacrifice_ecult/check_completion()
|
||||
if(!owner)
|
||||
return FALSE
|
||||
var/datum/antagonist/heretic/cultie = owner.has_antag_datum(/datum/antagonist/heretic)
|
||||
if(!cultie)
|
||||
return FALSE
|
||||
return cultie.total_sacrifices >= target_amount
|
||||
@@ -0,0 +1,145 @@
|
||||
/obj/item/forbidden_book
|
||||
name = "Codex Cicatrix"
|
||||
desc = "Book describing the secrets of the veil."
|
||||
icon = 'icons/obj/eldritch.dmi'
|
||||
icon_state = "book"
|
||||
item_state = "book"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
///Last person that touched this
|
||||
var/mob/living/last_user
|
||||
///how many charges do we have?
|
||||
var/charge = 0
|
||||
///Where we cannot create the rune?
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(/turf/closed,/turf/open/space,/turf/open/lava))
|
||||
|
||||
/obj/item/forbidden_book/Destroy()
|
||||
last_user = null
|
||||
. = ..()
|
||||
|
||||
|
||||
/obj/item/forbidden_book/examine(mob/user)
|
||||
. = ..()
|
||||
if(!IS_HERETIC(user))
|
||||
return
|
||||
. += "The Tome holds [charge] charges."
|
||||
. += "Use it on the floor to create a transmutation rune, used to perform rituals."
|
||||
. += "Hit an influence in the black part with it to gain a charge."
|
||||
. += "Hit a transmutation rune to destroy it."
|
||||
|
||||
/obj/item/forbidden_book/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag || !IS_HERETIC(user))
|
||||
return
|
||||
if(istype(target,/obj/effect/eldritch))
|
||||
remove_rune(target,user)
|
||||
if(istype(target,/obj/effect/reality_smash))
|
||||
get_power_from_influence(target,user)
|
||||
if(istype(target,/turf/open))
|
||||
draw_rune(target,user)
|
||||
|
||||
///Gives you a charge and destroys a corresponding influence
|
||||
/obj/item/forbidden_book/proc/get_power_from_influence(atom/target, mob/user)
|
||||
var/obj/effect/reality_smash/RS = target
|
||||
to_chat(target, "<span class='danger'>You start drawing power from influence...</span>")
|
||||
if(do_after(user,10 SECONDS,TRUE,RS))
|
||||
qdel(RS)
|
||||
charge += 1
|
||||
|
||||
///Draws a rune on a selected turf
|
||||
/obj/item/forbidden_book/proc/draw_rune(atom/target,mob/user)
|
||||
|
||||
for(var/turf/T in range(1,target))
|
||||
if(is_type_in_typecache(T, blacklisted_turfs))
|
||||
to_chat(target, "<span class='warning'>The terrain doesn't support runes!</span>")
|
||||
return
|
||||
var/A = get_turf(target)
|
||||
to_chat(user, "<span class='danger'>You start drawing a rune...</span>")
|
||||
|
||||
if(do_after(user,30 SECONDS,FALSE, user))
|
||||
|
||||
new /obj/effect/eldritch/big(A)
|
||||
|
||||
///Removes runes from the selected turf
|
||||
/obj/item/forbidden_book/proc/remove_rune(atom/target,mob/user)
|
||||
|
||||
to_chat(user, "<span class='danger'>You start removing a rune...</span>")
|
||||
if(do_after(user,2 SECONDS,FALSE, user))
|
||||
qdel(target)
|
||||
|
||||
/obj/item/forbidden_book/ui_interact(mob/user, datum/tgui/ui = null)
|
||||
if(!IS_HERETIC(user))
|
||||
return FALSE
|
||||
last_user = user
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
icon_state = "book_open"
|
||||
flick("book_opening", src)
|
||||
ui = new(user, src, "ForbiddenLore", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/forbidden_book/ui_data(mob/user)
|
||||
var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
var/list/to_know = list()
|
||||
for(var/Y in cultie.get_researchable_knowledge())
|
||||
to_know += new Y
|
||||
var/list/known = cultie.get_all_knowledge()
|
||||
var/list/data = list()
|
||||
var/list/lore = list()
|
||||
|
||||
data["charges"] = charge
|
||||
|
||||
for(var/X in to_know)
|
||||
lore = list()
|
||||
var/datum/eldritch_knowledge/EK = X
|
||||
lore["type"] = EK.type
|
||||
lore["name"] = EK.name
|
||||
lore["cost"] = EK.cost
|
||||
lore["disabled"] = EK.cost <= charge ? FALSE : TRUE
|
||||
lore["path"] = EK.route
|
||||
lore["state"] = "Research"
|
||||
lore["flavour"] = EK.gain_text
|
||||
lore["desc"] = EK.desc
|
||||
data["to_know"] += list(lore)
|
||||
|
||||
for(var/X in known)
|
||||
lore = list()
|
||||
var/datum/eldritch_knowledge/EK = known[X]
|
||||
lore["name"] = EK.name
|
||||
lore["cost"] = EK.cost
|
||||
lore["disabled"] = TRUE
|
||||
lore["path"] = EK.route
|
||||
lore["state"] = "Researched"
|
||||
lore["flavour"] = EK.gain_text
|
||||
lore["desc"] = EK.desc
|
||||
data["to_know"] += list(lore)
|
||||
|
||||
if(!length(data["to_know"]))
|
||||
data["to_know"] = null
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/forbidden_book/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if("research")
|
||||
var/datum/antagonist/heretic/cultie = last_user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
var/ekname = params["name"]
|
||||
for(var/X in cultie.get_researchable_knowledge())
|
||||
var/datum/eldritch_knowledge/EK = X
|
||||
if(initial(EK.name) != ekname)
|
||||
continue
|
||||
if(cultie.gain_knowledge(EK))
|
||||
charge -= text2num(params["cost"])
|
||||
return TRUE
|
||||
|
||||
update_icon() // Not applicable to all objects.
|
||||
|
||||
/obj/item/forbidden_book/ui_close(mob/user)
|
||||
flick("book_closing",src)
|
||||
icon_state = initial(icon_state)
|
||||
return ..()
|
||||
|
||||
/obj/item/forbidden_book/debug
|
||||
charge = 100
|
||||
@@ -0,0 +1,289 @@
|
||||
/obj/effect/eldritch
|
||||
name = "Generic rune"
|
||||
desc = "Weird combination of shapes and symbols etched into the floor itself. The indentation is filled with thick black tar-like fluid."
|
||||
anchored = TRUE
|
||||
icon_state = ""
|
||||
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
layer = SIGIL_LAYER
|
||||
///Used mainly for summoning ritual to prevent spamming the rune to create millions of monsters.
|
||||
var/is_in_use = FALSE
|
||||
|
||||
/obj/effect/eldritch/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
try_activate(user)
|
||||
|
||||
/obj/effect/eldritch/proc/try_activate(mob/living/user)
|
||||
if(!IS_HERETIC(user))
|
||||
return
|
||||
if(!is_in_use)
|
||||
INVOKE_ASYNC(src, .proc/activate , user)
|
||||
|
||||
/obj/effect/eldritch/attacked_by(obj/item/I, mob/living/user)
|
||||
. = ..()
|
||||
if(istype(I,/obj/item/nullrod))
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/eldritch/proc/activate(mob/living/user)
|
||||
is_in_use = TRUE
|
||||
// Have fun trying to read this proc.
|
||||
var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
var/list/knowledge = cultie.get_all_knowledge()
|
||||
var/list/atoms_in_range = list()
|
||||
|
||||
for(var/A in range(1, src))
|
||||
var/atom/atom_in_range = A
|
||||
if(istype(atom_in_range,/area))
|
||||
continue
|
||||
if(istype(atom_in_range,/turf)) // we dont want turfs
|
||||
continue
|
||||
if(istype(atom_in_range,/mob/living))
|
||||
var/mob/living/living_in_range = atom_in_range
|
||||
if(living_in_range.stat != DEAD || living_in_range == user) // we only accept corpses, no living beings allowed.
|
||||
continue
|
||||
atoms_in_range += atom_in_range
|
||||
for(var/X in knowledge)
|
||||
var/datum/eldritch_knowledge/current_eldritch_knowledge = knowledge[X]
|
||||
|
||||
//has to be done so that we can freely edit the local_required_atoms without fucking up the eldritch knowledge
|
||||
var/list/local_required_atoms = list()
|
||||
|
||||
if(!current_eldritch_knowledge.required_atoms || current_eldritch_knowledge.required_atoms.len == 0)
|
||||
continue
|
||||
|
||||
local_required_atoms += current_eldritch_knowledge.required_atoms
|
||||
|
||||
var/list/selected_atoms = list()
|
||||
|
||||
if(!current_eldritch_knowledge.recipe_snowflake_check(atoms_in_range,drop_location(),selected_atoms))
|
||||
continue
|
||||
|
||||
for(var/LR in local_required_atoms)
|
||||
var/list/local_required_atom_list = LR
|
||||
|
||||
for(var/LAIR in atoms_in_range)
|
||||
var/atom/local_atom_in_range = LAIR
|
||||
if(is_type_in_list(local_atom_in_range,local_required_atom_list))
|
||||
selected_atoms |= local_atom_in_range
|
||||
local_required_atoms -= list(local_required_atom_list)
|
||||
|
||||
if(length(local_required_atoms) > 0)
|
||||
continue
|
||||
|
||||
flick("[icon_state]_active",src)
|
||||
playsound(user, 'sound/magic/castsummon.ogg', 75, TRUE)
|
||||
//we are doing this since some on_finished_recipe subtract the atoms from selected_atoms making them invisible permanently.
|
||||
var/list/atoms_to_disappear = selected_atoms.Copy()
|
||||
for(var/to_disappear in atoms_to_disappear)
|
||||
var/atom/atom_to_disappear = to_disappear
|
||||
//temporary so we dont have to deal with the bs of someone picking those up when they may be deleted
|
||||
atom_to_disappear.invisibility = INVISIBILITY_ABSTRACT
|
||||
if(current_eldritch_knowledge.on_finished_recipe(user,selected_atoms,loc))
|
||||
current_eldritch_knowledge.cleanup_atoms(selected_atoms)
|
||||
is_in_use = FALSE
|
||||
|
||||
for(var/to_appear in atoms_to_disappear)
|
||||
var/atom/atom_to_appear = to_appear
|
||||
//we need to reappear the item just in case the ritual didnt consume everything... or something.
|
||||
atom_to_appear.invisibility = initial(atom_to_appear.invisibility)
|
||||
|
||||
return
|
||||
is_in_use = FALSE
|
||||
to_chat(user,"<span class='warning'>Your ritual failed! You used either wrong components or are missing something important!</span>")
|
||||
|
||||
/obj/effect/eldritch/big
|
||||
name = "transmutation circle"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "eldritch_rune1"
|
||||
pixel_x = -32 //So the big ol' 96x96 sprite shows up right
|
||||
pixel_y = -32
|
||||
|
||||
/**
|
||||
* #Reality smash tracker
|
||||
*
|
||||
* Stupid fucking list holder, DONT create new ones, it will break the game, this is automnatically created whenever eldritch cultists are created.
|
||||
*
|
||||
* Tracks relevant data, generates relevant data, useful tool
|
||||
*/
|
||||
/datum/reality_smash_tracker
|
||||
///list of tracked reality smashes
|
||||
var/list/smashes = list()
|
||||
///List of mobs with ability to see the smashes
|
||||
var/list/targets = list()
|
||||
|
||||
/datum/reality_smash_tracker/Destroy(force, ...)
|
||||
if(GLOB.reality_smash_track == src)
|
||||
stack_trace("/datum/reality_smash_tracker was deleted. Heretics may no longer access any influences. Fix it or call coder support")
|
||||
QDEL_LIST(smashes)
|
||||
targets.Cut()
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Automatically fixes the target and smash network
|
||||
*
|
||||
* Fixes any bugs that are caused by late Generate() or exchanging clients
|
||||
*/
|
||||
/datum/reality_smash_tracker/proc/ReworkNetwork()
|
||||
listclearnulls(smashes)
|
||||
for(var/mind in targets)
|
||||
if(isnull(mind))
|
||||
stack_trace("A null somehow landed in a list of minds")
|
||||
continue
|
||||
for(var/X in smashes)
|
||||
var/obj/effect/reality_smash/reality_smash = X
|
||||
reality_smash.AddMind(mind)
|
||||
|
||||
/**
|
||||
* Generates a set amount of reality smashes based on the N value
|
||||
*
|
||||
* Automatically creates more reality smashes
|
||||
*/
|
||||
/datum/reality_smash_tracker/proc/_Generate()
|
||||
var/targ_len = length(targets)
|
||||
var/smash_len = length(smashes)
|
||||
var/number = targ_len * 6 - smash_len
|
||||
|
||||
for(var/i in 0 to number)
|
||||
|
||||
var/turf/chosen_location = get_safe_random_station_turf()
|
||||
//we also dont want them close to each other, at least 1 tile of seperation
|
||||
var/obj/effect/reality_smash/what_if_i_have_one = locate() in range(1, chosen_location)
|
||||
var/obj/effect/broken_illusion/what_if_i_had_one_but_got_used = locate() in range(1, chosen_location)
|
||||
if(what_if_i_have_one || what_if_i_had_one_but_got_used) //we dont want to spawn
|
||||
continue
|
||||
var/obj/effect/reality_smash/RS = new/obj/effect/reality_smash(chosen_location)
|
||||
smashes += RS
|
||||
ReworkNetwork()
|
||||
|
||||
|
||||
/**
|
||||
* Adds a mind to the list of people that can see the reality smashes
|
||||
*
|
||||
* Use this whenever you want to add someone to the list
|
||||
*/
|
||||
/datum/reality_smash_tracker/proc/AddMind(var/datum/mind/M)
|
||||
RegisterSignal(M.current,COMSIG_MOB_CLIENT_LOGIN,.proc/ReworkNetwork)
|
||||
targets |= M
|
||||
_Generate()
|
||||
for(var/X in smashes)
|
||||
var/obj/effect/reality_smash/reality_smash = X
|
||||
reality_smash.AddMind(M)
|
||||
|
||||
|
||||
/**
|
||||
* Removes a mind from the list of people that can see the reality smashes
|
||||
*
|
||||
* Use this whenever you want to remove someone from the list
|
||||
*/
|
||||
/datum/reality_smash_tracker/proc/RemoveMind(var/datum/mind/M)
|
||||
UnregisterSignal(M.current,COMSIG_MOB_CLIENT_LOGIN)
|
||||
targets -= M
|
||||
for(var/obj/effect/reality_smash/RS in smashes)
|
||||
RS.RemoveMind(M)
|
||||
|
||||
/obj/effect/broken_illusion
|
||||
name = "pierced reality"
|
||||
icon = 'icons/effects/eldritch.dmi'
|
||||
icon_state = "pierced_illusion"
|
||||
anchored = TRUE
|
||||
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
/obj/effect/broken_illusion/attack_hand(mob/living/user)
|
||||
if(!ishuman(user))
|
||||
return ..()
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
if(IS_HERETIC(human_user))
|
||||
to_chat(human_user,"<span class='boldwarning'>You know better than to tempt forces out of your control.</span>")
|
||||
else
|
||||
var/obj/item/bodypart/arm = human_user.get_active_hand()
|
||||
if(prob(25))
|
||||
to_chat(human_user,"<span class='userdanger'>An otherwordly presence tears your arm apart into atoms as you try to touch the hole in the very fabric of reality!</span>")
|
||||
arm.dismember()
|
||||
qdel(arm)
|
||||
else
|
||||
to_chat(human_user,"<span class='danger'>You pull your hand away from the hole as eldritch energy flails out, trying to latch onto existence itself!</span>")
|
||||
|
||||
/obj/effect/broken_illusion/attack_tk(mob/user)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
if(IS_HERETIC(human_user))
|
||||
to_chat(human_user,"<span class='boldwarning'>You know better than to tempt forces out of your control.</span>")
|
||||
else
|
||||
//a very elaborate way to suicide
|
||||
to_chat(human_user,"<span class='userdanger'>Eldritch energy lashes out, piercing your fragile mind, tearing it to pieces!</span>")
|
||||
human_user.ghostize()
|
||||
var/obj/item/bodypart/head/head = locate() in human_user.bodyparts
|
||||
if(head)
|
||||
head.dismember()
|
||||
qdel(head)
|
||||
else
|
||||
human_user.gib()
|
||||
|
||||
var/datum/effect_system/reagents_explosion/explosion = new()
|
||||
explosion.set_up(1, get_turf(human_user), 1, 0)
|
||||
explosion.start()
|
||||
|
||||
/obj/effect/broken_illusion/examine(mob/user)
|
||||
if(!IS_HERETIC(user) && ishuman(user))
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
to_chat(human_user,"<span class='userdanger'>Your brain hurts when you look at this!</span>")
|
||||
human_user.adjustOrganLoss(ORGAN_SLOT_BRAIN,30)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/reality_smash
|
||||
name = "/improper reality smash"
|
||||
icon = 'icons/effects/eldritch.dmi'
|
||||
anchored = TRUE
|
||||
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
///We cannot use icon_state since this is invisible, functions the same way but with custom behaviour.
|
||||
var/image_state = "reality_smash"
|
||||
///Who can see us?
|
||||
var/list/minds = list()
|
||||
///Tracked image
|
||||
var/image/img
|
||||
|
||||
/obj/effect/reality_smash/Initialize()
|
||||
. = ..()
|
||||
img = image(icon, src, image_state, OBJ_LAYER)
|
||||
generate_name()
|
||||
|
||||
/obj/effect/reality_smash/Destroy()
|
||||
on_destroy()
|
||||
return ..()
|
||||
|
||||
///Custom effect that happens on destruction
|
||||
/obj/effect/reality_smash/proc/on_destroy()
|
||||
for(var/cm in minds)
|
||||
var/datum/mind/cultie = cm
|
||||
if(cultie.current?.client)
|
||||
cultie.current.client.images -= img
|
||||
//clear the list
|
||||
minds -= cultie
|
||||
GLOB.reality_smash_track.smashes -= src
|
||||
img = null
|
||||
new /obj/effect/broken_illusion(drop_location())
|
||||
|
||||
///Makes the mind able to see this effect
|
||||
/obj/effect/reality_smash/proc/AddMind(var/datum/mind/cultie)
|
||||
minds |= cultie
|
||||
if(cultie.current.client)
|
||||
cultie.current.client.images |= img
|
||||
|
||||
|
||||
|
||||
///Makes the mind not able to see this effect
|
||||
/obj/effect/reality_smash/proc/RemoveMind(var/datum/mind/cultie)
|
||||
minds -= cultie
|
||||
if(cultie.current.client)
|
||||
cultie.current.client.images -= img
|
||||
|
||||
|
||||
|
||||
///Generates random name
|
||||
/obj/effect/reality_smash/proc/generate_name()
|
||||
var/static/list/prefix = list("Omniscient","Thundering","Enlightening","Intrusive","Rejectful","Atomized","Subtle","Rising","Lowering","Fleeting","Towering","Blissful","Arrogant","Threatening","Peaceful","Aggressive")
|
||||
var/static/list/postfix = list("Flaw","Presence","Crack","Heat","Cold","Memory","Reminder","Breeze","Grasp","Sight","Whisper","Flow","Touch","Veil","Thought","Imperfection","Blemish","Blush")
|
||||
|
||||
name = pick(prefix) + " " + pick(postfix)
|
||||
@@ -0,0 +1,142 @@
|
||||
/obj/item/living_heart
|
||||
name = "living heart"
|
||||
desc = "Link to the worlds beyond."
|
||||
icon = 'icons/obj/eldritch.dmi'
|
||||
icon_state = "living_heart"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
///Target
|
||||
var/mob/living/carbon/human/target
|
||||
|
||||
/obj/item/living_heart/attack_self(mob/user)
|
||||
. = ..()
|
||||
if(!IS_HERETIC(user))
|
||||
return
|
||||
if(!target)
|
||||
to_chat(user,"<span class='warning'>No target could be found. Put the living heart on the rune and use the rune to recieve a target.</span>")
|
||||
return
|
||||
var/dist = get_dist(user.loc,target.loc)
|
||||
var/dir = get_dir(user.loc,target.loc)
|
||||
|
||||
switch(dist)
|
||||
if(0 to 15)
|
||||
to_chat(user,"<span class='warning'>[target.real_name] is near you. They are to the [dir2text(dir)] of you!</span>")
|
||||
if(16 to 31)
|
||||
to_chat(user,"<span class='warning'>[target.real_name] is somewhere in your vicinty. They are to the [dir2text(dir)] of you!</span>")
|
||||
if(32 to 127)
|
||||
to_chat(user,"<span class='warning'>[target.real_name] is far away from you. They are to the [dir2text(dir)] of you!</span>")
|
||||
else
|
||||
to_chat(user,"<span class='warning'>[target.real_name] is beyond our reach.</span>")
|
||||
|
||||
if(target.stat == DEAD)
|
||||
to_chat(user,"<span class='warning'>[target.real_name] is dead. Bring them onto a transmutation rune!</span>")
|
||||
|
||||
/obj/item/melee/sickly_blade
|
||||
name = "eldritch blade"
|
||||
desc = "A sickly green crescent blade, decorated with an ornamental eye. You feel like you're being watched..."
|
||||
icon = 'icons/obj/eldritch.dmi'
|
||||
icon_state = "eldritch_blade"
|
||||
item_state = "eldritch_blade"
|
||||
lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
|
||||
inhand_x_dimension = 64
|
||||
inhand_y_dimension = 64
|
||||
flags_1 = CONDUCT_1
|
||||
sharpness = SHARP_EDGED
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
force = 17
|
||||
throwforce = 10
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "rended")
|
||||
|
||||
/obj/item/melee/sickly_blade/attack(mob/living/M, mob/living/user)
|
||||
if(!IS_HERETIC(user))
|
||||
to_chat(user,"<span class='danger'>You feel a pulse of some alien intellect lash out at your mind!</span>")
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
human_user.AdjustParalyzed(5 SECONDS)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/sickly_blade/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
if(!cultie || !proximity_flag)
|
||||
return
|
||||
var/list/knowledge = cultie.get_all_knowledge()
|
||||
for(var/X in knowledge)
|
||||
var/datum/eldritch_knowledge/eldritch_knowledge_datum = knowledge[X]
|
||||
eldritch_knowledge_datum.on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
|
||||
/obj/item/melee/sickly_blade/rust
|
||||
name = "rusted blade"
|
||||
desc = "This crescent blade is decrepit, wasting to dust. Yet still it bites, catching flesh with jagged, rotten teeth."
|
||||
icon_state = "rust_blade"
|
||||
item_state = "rust_blade"
|
||||
embedding = list("pain_mult" = 4, "embed_chance" = 75, "fall_chance" = 10, "ignore_throwspeed_threshold" = TRUE)
|
||||
throwforce = 17
|
||||
|
||||
/obj/item/melee/sickly_blade/ash
|
||||
name = "ashen blade"
|
||||
desc = "Molten and unwrought, a hunk of metal warped to cinders and slag. Unmade, it aspires to be more than it is, and shears soot-filled wounds with a blunt edge."
|
||||
icon_state = "ash_blade"
|
||||
item_state = "ash_blade"
|
||||
force = 20
|
||||
|
||||
/obj/item/melee/sickly_blade/flesh
|
||||
name = "flesh blade"
|
||||
desc = "A crescent blade born from a fleshwarped creature. Keenly aware, it seeks to spread to others the excruciations it has endured from dead origins."
|
||||
icon_state = "flesh_blade"
|
||||
item_state = "flesh_blade"
|
||||
wound_bonus = 5
|
||||
bare_wound_bonus = 15
|
||||
|
||||
/obj/item/clothing/neck/eldritch_amulet
|
||||
name = "warm eldritch medallion"
|
||||
desc = "A strange medallion. Peering through the crystalline surface, the world around you melts away. You see your own beating heart, and the pulse of a thousand others."
|
||||
icon = 'icons/obj/eldritch.dmi'
|
||||
icon_state = "eye_medalion"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
///What trait do we want to add upon equipiing
|
||||
var/trait = TRAIT_THERMAL_VISION
|
||||
|
||||
/obj/item/clothing/neck/eldritch_amulet/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(ishuman(user) && user.mind && slot == SLOT_NECK && IS_HERETIC(user))
|
||||
ADD_TRAIT(user, trait, CLOTHING_TRAIT)
|
||||
user.update_sight()
|
||||
|
||||
/obj/item/clothing/neck/eldritch_amulet/dropped(mob/user)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(user, trait, CLOTHING_TRAIT)
|
||||
user.update_sight()
|
||||
|
||||
/obj/item/clothing/neck/eldritch_amulet/piercing
|
||||
name = "piercing eldritch medallion"
|
||||
desc = "A strange medallion. Peering through the crystalline surface, the light refracts into new and terrifying spectrums of color. You see yourself, reflected off cascading mirrors, warped into improbable shapes."
|
||||
trait = TRAIT_XRAY_VISION
|
||||
|
||||
/obj/item/clothing/head/hooded/cult_hoodie/eldritch
|
||||
name = "ominous hood"
|
||||
icon_state = "eldritch"
|
||||
desc = "A torn, dust-caked hood. Strange eyes line the inside."
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
flash_protect = 2
|
||||
|
||||
/obj/item/clothing/suit/hooded/cultrobes/eldritch
|
||||
name = "ominous armor"
|
||||
desc = "A ragged, dusty set of robes. Strange eyes line the inside."
|
||||
icon_state = "eldritch_armor"
|
||||
item_state = "eldritch_armor"
|
||||
flags_inv = HIDESHOES|HIDEJUMPSUIT
|
||||
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS
|
||||
allowed = list(/obj/item/melee/sickly_blade, /obj/item/forbidden_book)
|
||||
hoodtype = /obj/item/clothing/head/hooded/cult_hoodie/eldritch
|
||||
// slightly better than normal cult robes
|
||||
armor = list("melee" = 50, "bullet" = 50, "laser" = 50,"energy" = 50, "bomb" = 35, "bio" = 20, "rad" = 0, "fire" = 20, "acid" = 20)
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/eldritch
|
||||
name = "flask of eldritch essence"
|
||||
desc = "Toxic to the close minded. Healing to those with knowledge of the beyond."
|
||||
icon = 'icons/obj/eldritch.dmi'
|
||||
icon_state = "eldrich_flask"
|
||||
list_reagents = list(/datum/reagent/eldritch = 50)
|
||||
@@ -0,0 +1,303 @@
|
||||
|
||||
/**
|
||||
* #Eldritch Knwoledge
|
||||
*
|
||||
* Datum that makes eldritch cultist interesting.
|
||||
*
|
||||
* Eldritch knowledge aren't instantiated anywhere roundstart, and are initalized and destroyed as the round goes on.
|
||||
*/
|
||||
/datum/eldritch_knowledge
|
||||
///Name of the knowledge
|
||||
var/name = "Basic knowledge"
|
||||
///Description of the knowledge
|
||||
var/desc = "Basic knowledge of forbidden arts."
|
||||
///What shows up
|
||||
var/gain_text = ""
|
||||
///Cost of knowledge in souls
|
||||
var/cost = 0
|
||||
///Next knowledge in the research tree
|
||||
var/list/next_knowledge = list()
|
||||
///What knowledge is incompatible with this. This will simply make it impossible to research knowledges that are in banned_knowledge once this gets researched.
|
||||
var/list/banned_knowledge = list()
|
||||
///Used with rituals, how many items this needs
|
||||
var/list/required_atoms = list()
|
||||
///What do we get out of this
|
||||
var/list/result_atoms = list()
|
||||
///What path is this on defaults to "Side"
|
||||
var/route = PATH_SIDE
|
||||
|
||||
/datum/eldritch_knowledge/New()
|
||||
. = ..()
|
||||
var/list/temp_list
|
||||
for(var/X in required_atoms)
|
||||
var/atom/A = X
|
||||
temp_list += list(typesof(A))
|
||||
required_atoms = temp_list
|
||||
|
||||
/**
|
||||
* What happens when this is assigned to an antag datum
|
||||
*
|
||||
* This proc is called whenever a new eldritch knowledge is added to an antag datum
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_gain(mob/user)
|
||||
to_chat(user, "<span class='warning'>[gain_text]</span>")
|
||||
return
|
||||
/**
|
||||
* What happens when you loose this
|
||||
*
|
||||
* This proc is called whenever antagonist looses his antag datum, put cleanup code in here
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_lose(mob/user)
|
||||
return
|
||||
/**
|
||||
* What happens every tick
|
||||
*
|
||||
* This proc is called on SSprocess in eldritch cultist antag datum. SSprocess happens roughly every second
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_life(mob/user)
|
||||
return
|
||||
|
||||
/**
|
||||
* Special check for recipes
|
||||
*
|
||||
* If you are adding a more complex summoning or something that requires a special check that parses through all the atoms in an area override this.
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/recipe_snowflake_check(list/atoms,loc)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* What happens once the recipe is succesfully finished
|
||||
*
|
||||
* By default this proc creates atoms from result_atoms list. Override this is you want something else to happen.
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_finished_recipe(mob/living/user,list/atoms,loc)
|
||||
if(result_atoms.len == 0)
|
||||
return FALSE
|
||||
|
||||
for(var/A in result_atoms)
|
||||
new A(loc)
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Used atom cleanup
|
||||
*
|
||||
* Overide this proc if you dont want ALL ATOMS to be destroyed. useful in many situations.
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/cleanup_atoms(list/atoms)
|
||||
for(var/X in atoms)
|
||||
var/atom/A = X
|
||||
if(!isliving(A))
|
||||
atoms -= A
|
||||
qdel(A)
|
||||
return
|
||||
|
||||
/**
|
||||
* Mansus grasp act
|
||||
*
|
||||
* Gives addtional effects to mansus grasp spell
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
return FALSE
|
||||
|
||||
|
||||
/**
|
||||
* Sickly blade act
|
||||
*
|
||||
* Gives addtional effects to sickly blade weapon
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
return
|
||||
|
||||
//////////////
|
||||
///Subtypes///
|
||||
//////////////
|
||||
|
||||
/datum/eldritch_knowledge/spell
|
||||
var/obj/effect/proc_holder/spell/spell_to_add
|
||||
|
||||
/datum/eldritch_knowledge/spell/on_gain(mob/user)
|
||||
var/obj/effect/proc_holder/S = new spell_to_add
|
||||
user.mind.AddSpell(S)
|
||||
return ..()
|
||||
|
||||
/datum/eldritch_knowledge/spell/on_lose(mob/user)
|
||||
user.mind.RemoveSpell(spell_to_add)
|
||||
return ..()
|
||||
|
||||
/datum/eldritch_knowledge/curse
|
||||
var/timer = 5 MINUTES
|
||||
var/list/fingerprints = list()
|
||||
|
||||
/datum/eldritch_knowledge/curse/recipe_snowflake_check(list/atoms, loc)
|
||||
fingerprints = list()
|
||||
for(var/X in atoms)
|
||||
var/atom/A = X
|
||||
fingerprints |= A.fingerprints
|
||||
listclearnulls(fingerprints)
|
||||
if(fingerprints.len == 0)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/eldritch_knowledge/curse/on_finished_recipe(mob/living/user,list/atoms,loc)
|
||||
|
||||
var/list/compiled_list = list()
|
||||
|
||||
for(var/H in GLOB.human_list)
|
||||
var/mob/living/carbon/human/human_to_check = H
|
||||
if(fingerprints[md5(human_to_check.dna.uni_identity)])
|
||||
compiled_list |= human_to_check.real_name
|
||||
compiled_list[human_to_check.real_name] = human_to_check
|
||||
|
||||
if(compiled_list.len == 0)
|
||||
to_chat(user, "<span class='warning'>The items don't posses required fingerprints.</span>")
|
||||
return FALSE
|
||||
|
||||
var/chosen_mob = input("Select the person you wish to curse","Your target") as null|anything in sortList(compiled_list, /proc/cmp_mob_realname_dsc)
|
||||
if(!chosen_mob)
|
||||
return FALSE
|
||||
curse(compiled_list[chosen_mob])
|
||||
addtimer(CALLBACK(src, .proc/uncurse, compiled_list[chosen_mob]),timer)
|
||||
return TRUE
|
||||
|
||||
/datum/eldritch_knowledge/curse/proc/curse(mob/living/chosen_mob)
|
||||
return
|
||||
|
||||
/datum/eldritch_knowledge/curse/proc/uncurse(mob/living/chosen_mob)
|
||||
return
|
||||
|
||||
/datum/eldritch_knowledge/summon
|
||||
//Mob to summon
|
||||
var/mob/living/mob_to_summon
|
||||
|
||||
|
||||
/datum/eldritch_knowledge/summon/on_finished_recipe(mob/living/user,list/atoms,loc)
|
||||
//we need to spawn the mob first so that we can use it in pollCandidatesForMob, we will move it from nullspace down the code
|
||||
var/mob/living/summoned = new mob_to_summon(loc)
|
||||
message_admins("[summoned.name] is being summoned by [user.real_name] in [loc]")
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [summoned.name]", ROLE_HERETIC, null, FALSE, 100, summoned)
|
||||
if(!LAZYLEN(candidates))
|
||||
to_chat(user,"<span class='warning'>No ghost could be found...</span>")
|
||||
qdel(summoned)
|
||||
return FALSE
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
log_game("[key_name_admin(C)] has taken control of ([key_name_admin(summoned)]), their master is [user.real_name]")
|
||||
summoned.ghostize(FALSE)
|
||||
summoned.key = C.key
|
||||
summoned.mind.add_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic_monster/heretic_monster = summoned.mind.has_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
heretic_monster.set_owner(master)
|
||||
return TRUE
|
||||
|
||||
//Ascension knowledge
|
||||
/datum/eldritch_knowledge/final
|
||||
var/finished = FALSE
|
||||
|
||||
/datum/eldritch_knowledge/final/recipe_snowflake_check(list/atoms, loc,selected_atoms)
|
||||
if(finished)
|
||||
return FALSE
|
||||
var/counter = 0
|
||||
for(var/mob/living/carbon/human/H in atoms)
|
||||
selected_atoms |= H
|
||||
counter++
|
||||
if(counter == 3)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/eldritch_knowledge/final/on_finished_recipe( mob/living/user, list/atoms, loc)
|
||||
finished = TRUE
|
||||
return TRUE
|
||||
|
||||
/datum/eldritch_knowledge/final/cleanup_atoms(list/atoms)
|
||||
. = ..()
|
||||
for(var/mob/living/carbon/human/H in atoms)
|
||||
atoms -= H
|
||||
H.gib()
|
||||
|
||||
|
||||
///////////////
|
||||
///Base lore///
|
||||
///////////////
|
||||
|
||||
/datum/eldritch_knowledge/spell/basic
|
||||
name = "Break of Dawn"
|
||||
desc = "Starts your journey in the mansus. Allows you to select a target using a living heart on a transmutation rune."
|
||||
gain_text = "Gates of Mansus open up to your mind."
|
||||
next_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh)
|
||||
cost = 0
|
||||
spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/mansus_grasp
|
||||
required_atoms = list(/obj/item/living_heart)
|
||||
route = "Start"
|
||||
|
||||
/datum/eldritch_knowledge/spell/basic/recipe_snowflake_check(list/atoms, loc)
|
||||
. = ..()
|
||||
for(var/obj/item/living_heart/LH in atoms)
|
||||
if(!LH.target)
|
||||
return TRUE
|
||||
if(LH.target in atoms)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/eldritch_knowledge/spell/basic/on_finished_recipe(mob/living/user, list/atoms, loc)
|
||||
. = TRUE
|
||||
var/mob/living/carbon/carbon_user = user
|
||||
for(var/obj/item/living_heart/LH in atoms)
|
||||
|
||||
if(LH.target && LH.target.stat == DEAD)
|
||||
to_chat(carbon_user,"<span class='danger'>Your patrons accepts your offer...</span>")
|
||||
var/mob/living/carbon/human/H = LH.target
|
||||
H.become_husk()
|
||||
LH.target = null
|
||||
var/datum/antagonist/heretic/EC = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
|
||||
EC.total_sacrifices++
|
||||
for(var/X in carbon_user.get_all_gear())
|
||||
if(!istype(X,/obj/item/forbidden_book))
|
||||
continue
|
||||
var/obj/item/forbidden_book/FB = X
|
||||
FB.charge++
|
||||
FB.charge++
|
||||
break
|
||||
|
||||
if(!LH.target)
|
||||
var/datum/objective/A = new
|
||||
A.owner = user.mind
|
||||
var/datum/mind/targeted = A.find_target()//easy way, i dont feel like copy pasting that entire block of code
|
||||
LH.target = targeted.current
|
||||
qdel(A)
|
||||
if(LH.target)
|
||||
to_chat(user,"<span class='warning'>Your new target has been selected, go and sacrifice [LH.target.real_name]!</span>")
|
||||
|
||||
else
|
||||
to_chat(user,"<span class='warning'>target could not be found for living heart.</span>")
|
||||
|
||||
/datum/eldritch_knowledge/spell/basic/cleanup_atoms(list/atoms)
|
||||
return
|
||||
|
||||
/datum/eldritch_knowledge/living_heart
|
||||
name = "Living Heart"
|
||||
desc = "Allows you to create additional living hearts, using a heart, a pool of blood and a poppy. Living hearts when used on a transmutation rune will grant you a person to hunt and sacrifice on the rune. Every sacrifice gives you an additional charge in the book."
|
||||
gain_text = "Disconnected, yet it still beats."
|
||||
cost = 0
|
||||
required_atoms = list(/obj/item/organ/heart,/obj/effect/decal/cleanable/blood,/obj/item/reagent_containers/food/snacks/grown/poppy)
|
||||
result_atoms = list(/obj/item/living_heart)
|
||||
route = "Start"
|
||||
|
||||
/datum/eldritch_knowledge/codex_cicatrix
|
||||
name = "Codex Cicatrix"
|
||||
desc = "Allows you to create a spare Codex Cicatrix if you have lost one, using a bible, human skin, a pen and a pair of eyes."
|
||||
gain_text = "Their hands are at your throat, yet you see them not."
|
||||
cost = 0
|
||||
required_atoms = list(/obj/item/organ/eyes,/obj/item/stack/sheet/animalhide/human,/obj/item/storage/book/bible,/obj/item/pen)
|
||||
result_atoms = list(/obj/item/forbidden_book)
|
||||
route = "Start"
|
||||
|
||||
/datum/eldritch_knowledge/eldritch_blade
|
||||
name = "Eldritch Blade"
|
||||
desc = "Allows you to create a sickly, eldritch blade by transmuting a glass shard and a metal rod atop a transmutation rune."
|
||||
gain_text = "The first step starts with sacrifice."
|
||||
cost = 0
|
||||
required_atoms = list(/obj/item/shard,/obj/item/stack/rods)
|
||||
result_atoms = list(/obj/item/melee/sickly_blade)
|
||||
route = "Start"
|
||||
@@ -0,0 +1,668 @@
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash
|
||||
name = "Ashen Passage"
|
||||
desc = "Low range spell allowing you to pass through a few walls."
|
||||
school = "transmutation"
|
||||
invocation = "DULK'ES PRE'ZIMAS"
|
||||
invocation_type = "whisper"
|
||||
charge_max = 150
|
||||
range = -1
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "ash_shift"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
jaunt_in_time = 13
|
||||
jaunt_duration = 10
|
||||
jaunt_in_type = /obj/effect/temp_visual/dir_setting/ash_shift
|
||||
jaunt_out_type = /obj/effect/temp_visual/dir_setting/ash_shift/out
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/long
|
||||
jaunt_duration = 50
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/play_sound()
|
||||
return
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/ash_shift
|
||||
name = "ash_shift"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "ash_shift2"
|
||||
duration = 13
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/ash_shift/out
|
||||
icon_state = "ash_shift"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp
|
||||
name = "Mansus Grasp"
|
||||
desc = "Touch spell that allows you to channel the power of the Old Gods through you."
|
||||
hand_path = /obj/item/melee/touch_attack/mansus_fist
|
||||
school = "evocation"
|
||||
charge_max = 150
|
||||
clothes_req = FALSE
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "mansus_grasp"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/item/melee/touch_attack/mansus_fist
|
||||
name = "Mansus Grasp"
|
||||
desc = "A sinister looking aura that distorts the flow of reality around it. Causes knockdown, major stamina damage aswell as some Brute. It gains additional beneficial effects with certain knowledges you can research."
|
||||
icon_state = "disintegrate"
|
||||
item_state = "disintegrate"
|
||||
catchphrase = "T'IESA SIE'KTI VISATA"
|
||||
|
||||
/obj/item/melee/touch_attack/mansus_fist/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
|
||||
if(!proximity_flag || target == user)
|
||||
return
|
||||
playsound(user, 'sound/items/welder.ogg', 75, TRUE)
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/tar = target
|
||||
if(tar.anti_magic_check())
|
||||
tar.visible_message("<span class='danger'>Spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
|
||||
return ..()
|
||||
var/datum/mind/M = user.mind
|
||||
var/datum/antagonist/heretic/cultie = M.has_antag_datum(/datum/antagonist/heretic)
|
||||
|
||||
var/use_charge = FALSE
|
||||
if(iscarbon(target))
|
||||
use_charge = TRUE
|
||||
var/mob/living/carbon/C = target
|
||||
C.adjustBruteLoss(15)
|
||||
C.DefaultCombatKnockdown(50, override_stamdmg = 0)
|
||||
C.adjustStaminaLoss(60)
|
||||
var/list/knowledge = cultie.get_all_knowledge()
|
||||
|
||||
for(var/X in knowledge)
|
||||
var/datum/eldritch_knowledge/EK = knowledge[X]
|
||||
if(EK.on_mansus_grasp(target, user, proximity_flag, click_parameters))
|
||||
use_charge = TRUE
|
||||
if(use_charge)
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/rust_conversion
|
||||
name = "Aggressive Spread"
|
||||
desc = "Spreads rust onto nearby turfs."
|
||||
school = "transmutation"
|
||||
charge_max = 300 //twice as long as mansus grasp
|
||||
clothes_req = FALSE
|
||||
invocation = "PLI'STI MINO DOMI'KA"
|
||||
invocation_type = "whisper"
|
||||
range = 3
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "corrode"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/cast(list/targets, mob/user = usr)
|
||||
playsound(user, 'sound/items/welder.ogg', 75, TRUE)
|
||||
for(var/turf/T in targets)
|
||||
///What we want is the 3 tiles around the user and the tile under him to be rusted, so min(dist,1)-1 causes us to get 0 for these tiles, rest of the tiles are based on chance
|
||||
var/chance = 100 - (max(get_dist(T,user),1)-1)*100/(range+1)
|
||||
if(!prob(chance))
|
||||
continue
|
||||
T.rust_heretic_act()
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/small
|
||||
name = "Rust Conversion"
|
||||
desc = "Spreads rust onto nearby turfs."
|
||||
range = 2
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/blood_siphon
|
||||
name = "Blood Siphon"
|
||||
desc = "Touch spell that heals you while damaging the enemy, has a chance to transfer wounds between you and your enemy."
|
||||
hand_path = /obj/item/melee/touch_attack/blood_siphon
|
||||
school = "evocation"
|
||||
charge_max = 150
|
||||
clothes_req = FALSE
|
||||
invocation_type = "none"
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "blood_siphon"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/item/melee/touch_attack/blood_siphon
|
||||
name = "Blood Siphon"
|
||||
desc = "A sinister looking aura that distorts the flow of reality around it."
|
||||
icon_state = "disintegrate"
|
||||
item_state = "disintegrate"
|
||||
catchphrase = "SUN'AI'KINI'MAS"
|
||||
|
||||
/obj/item/melee/touch_attack/blood_siphon/afterattack(atom/target, mob/user, proximity_flag, proximity)
|
||||
if(!proximity_flag)
|
||||
return
|
||||
playsound(user, 'sound/effects/curseattack.ogg', 75, TRUE)
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/tar = target
|
||||
if(tar.anti_magic_check())
|
||||
tar.visible_message("<span class='danger'>Spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
|
||||
return ..()
|
||||
var/mob/living/carbon/C2 = user
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
L.adjustBruteLoss(20)
|
||||
C2.adjustBruteLoss(-20)
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C1 = target
|
||||
for(var/obj/item/bodypart/bodypart in C2.bodyparts)
|
||||
for(var/i in bodypart.wounds)
|
||||
var/datum/wound/iter_wound = i
|
||||
if(prob(50))
|
||||
continue
|
||||
var/obj/item/bodypart/target_bodypart = locate(bodypart.type) in C1.bodyparts
|
||||
if(!target_bodypart)
|
||||
continue
|
||||
iter_wound.remove_wound()
|
||||
iter_wound.apply_wound(target_bodypart)
|
||||
|
||||
C1.blood_volume -= 20
|
||||
if(C2.blood_volume < BLOOD_VOLUME_MAXIMUM) //we dont want to explode after all
|
||||
C2.blood_volume += 20
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/rust_wave
|
||||
name = "Patron's Reach"
|
||||
desc = "Channels energy into your gauntlet - firing it results in a wave of rust being created in it's wake."
|
||||
projectile_type = /obj/item/projectile/magic/spell/rust_wave
|
||||
charge_max = 350
|
||||
clothes_req = FALSE
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
base_icon_state = "rust_wave"
|
||||
action_icon_state = "rust_wave"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
sound = 'sound/effects/curse5.ogg'
|
||||
active_msg = "You extend your hand out, preparing to send out a wave of rust."
|
||||
deactive_msg = "You extinguish that energy, for now..."
|
||||
invocation = "RUD'ZI VAR'ZTAS"
|
||||
invocation_type = "whisper"
|
||||
|
||||
/obj/item/projectile/magic/spell/rust_wave
|
||||
name = "rust bolt"
|
||||
icon_state = "eldritch_projectile"
|
||||
alpha = 180
|
||||
damage = 30
|
||||
damage_type = TOX
|
||||
nodamage = 0
|
||||
hitsound = 'sound/effects/curseattack.ogg'
|
||||
range = 15
|
||||
|
||||
/obj/item/projectile/magic/spell/rust_wave/Moved(atom/OldLoc, Dir)
|
||||
. = ..()
|
||||
playsound(src, 'sound/items/welder.ogg', 75, TRUE)
|
||||
var/list/turflist = list()
|
||||
var/turf/T1
|
||||
turflist += get_turf(src)
|
||||
T1 = get_step(src,turn(dir,90))
|
||||
turflist += T1
|
||||
turflist += get_step(T1,turn(dir,90))
|
||||
T1 = get_step(src,turn(dir,-90))
|
||||
turflist += T1
|
||||
turflist += get_step(T1,turn(dir,-90))
|
||||
for(var/X in turflist)
|
||||
if(!X || prob(25))
|
||||
continue
|
||||
var/turf/T = X
|
||||
T.rust_heretic_act()
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/rust_wave/short
|
||||
name = "Small Patron's Reach"
|
||||
projectile_type = /obj/item/projectile/magic/spell/rust_wave/short
|
||||
|
||||
/obj/item/projectile/magic/spell/rust_wave/short
|
||||
range = 7
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/cleave
|
||||
name = "Cleave"
|
||||
desc = "Causes severe bleeding on a target and people around them"
|
||||
school = "transmutation"
|
||||
charge_max = 350
|
||||
clothes_req = FALSE
|
||||
invocation = "PLES'TI VI'RIBUS"
|
||||
invocation_type = "whisper"
|
||||
range = 9
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "cleave"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/cleave/cast(list/targets, mob/user)
|
||||
if(!targets.len)
|
||||
to_chat(user, "<span class='warning'>No target found in range!</span>")
|
||||
return FALSE
|
||||
if(!can_target(targets[1], user))
|
||||
return FALSE
|
||||
|
||||
for(var/mob/living/carbon/human/C in range(1,targets[1]))
|
||||
targets |= C
|
||||
|
||||
|
||||
for(var/X in targets)
|
||||
var/mob/living/carbon/human/target = X
|
||||
if(target == user)
|
||||
continue
|
||||
if(target.anti_magic_check())
|
||||
to_chat(user, "<span class='warning'>The spell had no effect!</span>")
|
||||
target.visible_message("<span class='danger'>[target]'s veins flash with fire, but their magic protection repulses the blaze!</span>", \
|
||||
"<span class='danger'>Your veins flash with fire, but your magic protection repels the blaze!</span>")
|
||||
continue
|
||||
|
||||
target.visible_message("<span class='danger'>[target]'s veins are shredded from within as an unholy blaze erupts from their blood!</span>", \
|
||||
"<span class='danger'>Your veins burst from within and unholy flame erupts from your blood!</span>")
|
||||
var/obj/item/bodypart/bodypart = pick(target.bodyparts)
|
||||
var/datum/wound/slash/critical/crit_wound = new
|
||||
crit_wound.apply_wound(bodypart)
|
||||
target.adjustFireLoss(20)
|
||||
new /obj/effect/temp_visual/cleave(target.drop_location())
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/cleave/can_target(atom/target, mob/user, silent)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!istype(target,/mob/living/carbon/human))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You are unable to cleave [target]!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/cleave/long
|
||||
charge_max = 650
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/touch/mad_touch
|
||||
name = "Touch of Madness"
|
||||
desc = "Touch spell that drains your enemies sanity."
|
||||
school = "transmutation"
|
||||
charge_max = 150
|
||||
clothes_req = FALSE
|
||||
invocation_type = "none"
|
||||
range = 2
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "mad_touch"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/touch/mad_touch/can_target(atom/target, mob/user, silent)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!istype(target,/mob/living/carbon/human))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You are unable to touch [target]!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/touch/mad_touch/cast(list/targets, mob/user)
|
||||
. = ..()
|
||||
for(var/mob/living/carbon/target in targets)
|
||||
if(ishuman(targets))
|
||||
var/mob/living/carbon/human/tar = target
|
||||
if(tar.anti_magic_check())
|
||||
tar.visible_message("<span class='danger'>Spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
|
||||
return
|
||||
if(target.mind && !target.mind.has_antag_datum(/datum/antagonist/heretic))
|
||||
to_chat(user,"<span class='warning'>[target.name] has been cursed!</span>")
|
||||
SEND_SIGNAL(target, COMSIG_ADD_MOOD_EVENT, "gates_of_mansus", /datum/mood_event/gates_of_mansus)
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/ash_final
|
||||
name = "Nightwatcher's Rite"
|
||||
desc = "Powerful spell that releases 5 streams of fire away from you."
|
||||
school = "transmutation"
|
||||
invocation = "IGNIS'INTI"
|
||||
invocation_type = "whisper"
|
||||
charge_max = 300
|
||||
range = 15
|
||||
clothes_req = FALSE
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "flames"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/ash_final/cast(list/targets, mob/user)
|
||||
for(var/X in targets)
|
||||
var/T
|
||||
T = line_target(-25, range, X, user)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, user,T)
|
||||
T = line_target(10, range, X, user)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, user,T)
|
||||
T = line_target(0, range, X, user)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, user,T)
|
||||
T = line_target(-10, range, X, user)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, user,T)
|
||||
T = line_target(25, range, X, user)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, user,T)
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/ash_final/proc/line_target(offset, range, atom/at , atom/user)
|
||||
if(!at)
|
||||
return
|
||||
var/angle = ATAN2(at.x - user.x, at.y - user.y) + offset
|
||||
var/turf/T = get_turf(user)
|
||||
for(var/i in 1 to range)
|
||||
var/turf/check = locate(user.x + cos(angle) * i, user.y + sin(angle) * i, user.z)
|
||||
if(!check)
|
||||
break
|
||||
T = check
|
||||
return (getline(user, T) - get_turf(user))
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/ash_final/proc/fire_line(atom/source, list/turfs)
|
||||
var/list/hit_list = list()
|
||||
for(var/turf/T in turfs)
|
||||
if(istype(T, /turf/closed))
|
||||
break
|
||||
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L.anti_magic_check())
|
||||
L.visible_message("<span class='danger'>Spell bounces off of [L]!</span>","<span class='danger'>The spell bounces off of you!</span>")
|
||||
continue
|
||||
if(L in hit_list || L == source)
|
||||
continue
|
||||
hit_list += L
|
||||
L.adjustFireLoss(20)
|
||||
to_chat(L, "<span class='userdanger'>You're hit by [source]'s fire breath!</span>")
|
||||
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700,50,1)
|
||||
// deals damage to mechs
|
||||
for(var/obj/mecha/M in T.contents)
|
||||
if(M in hit_list)
|
||||
continue
|
||||
hit_list += M
|
||||
M.take_damage(45, BURN, "melee", 1)
|
||||
sleep(1.5)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shapeshift/eldritch
|
||||
invocation_type = "none"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
sound = 'sound/magic/enter_blood.ogg'
|
||||
possible_shapes = list(/mob/living/simple_animal/mouse,\
|
||||
/mob/living/simple_animal/pet/dog/corgi,\
|
||||
/mob/living/simple_animal/hostile/carp,\
|
||||
/mob/living/simple_animal/bot/secbot, \
|
||||
/mob/living/simple_animal/pet/fox,\
|
||||
/mob/living/simple_animal/pet/cat )
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/emplosion/eldritch
|
||||
name = "Energetic Pulse"
|
||||
invocation_type = "none"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
charge_max = 300
|
||||
emp_heavy = 6
|
||||
emp_light = 10
|
||||
sound = 'sound/effects/lingscreech.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/fire_cascade
|
||||
name = "Fire Cascade"
|
||||
desc = "creates hot turfs around you."
|
||||
school = "transmutation"
|
||||
charge_max = 300 //twice as long as mansus grasp
|
||||
clothes_req = FALSE
|
||||
invocation = "IGNIS'SAVARIN"
|
||||
invocation_type = "whisper"
|
||||
range = 4
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "fire_ring"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/cast(list/targets, mob/user = usr)
|
||||
INVOKE_ASYNC(src, .proc/fire_cascade, user,range)
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/proc/fire_cascade(atom/centre,max_range)
|
||||
playsound(get_turf(centre), 'sound/items/welder.ogg', 75, TRUE)
|
||||
var/_range = 1
|
||||
for(var/i = 0, i <= max_range,i++)
|
||||
for(var/turf/T in spiral_range_turfs(_range,centre))
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700,50,1)
|
||||
for(var/mob/living/livies in T.contents - centre)
|
||||
livies.adjustFireLoss(10)
|
||||
_range++
|
||||
sleep(3)
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/big
|
||||
range = 6
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/telepathy/eldritch
|
||||
invocation = ""
|
||||
invocation_type = "whisper"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fire_sworn
|
||||
name = "Oath of Fire"
|
||||
desc = "For a minute you will passively create a ring of fire around you."
|
||||
invocation = "IGNIS'AISTRA'LISTRE"
|
||||
invocation_type = "whisper"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
charge_max = 700
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "fire_ring"
|
||||
///how long it lasts
|
||||
var/duration = 1 MINUTES
|
||||
///who casted it right now
|
||||
var/mob/current_user
|
||||
///Determines if you get the fire ring effect
|
||||
var/has_fire_ring = FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fire_sworn/cast(list/targets, mob/user)
|
||||
. = ..()
|
||||
current_user = user
|
||||
has_fire_ring = TRUE
|
||||
addtimer(CALLBACK(src, .proc/remove, user), duration, TIMER_OVERRIDE|TIMER_UNIQUE)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fire_sworn/proc/remove()
|
||||
has_fire_ring = FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fire_sworn/process()
|
||||
. = ..()
|
||||
if(!has_fire_ring)
|
||||
return
|
||||
for(var/turf/T in range(1,current_user))
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700,50,1)
|
||||
for(var/mob/living/livies in T.contents - current_user)
|
||||
livies.adjustFireLoss(5)
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/worm_contract
|
||||
name = "Force Contract"
|
||||
desc = "Forces all the worm parts to collapse onto a single turf"
|
||||
invocation_type = "none"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
charge_max = 300
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "worm_contract"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/worm_contract/cast(list/targets, mob/user)
|
||||
. = ..()
|
||||
if(!istype(user,/mob/living/simple_animal/hostile/eldritch/armsy))
|
||||
to_chat(user, "<span class='userdanger'>You try to contract your muscles but nothing happens...</span>")
|
||||
var/mob/living/simple_animal/hostile/eldritch/armsy/armsy = user
|
||||
armsy.contract_next_chain_into_single_tile()
|
||||
|
||||
/obj/effect/temp_visual/cleave
|
||||
icon = 'icons/effects/eldritch.dmi'
|
||||
icon_state = "cleave"
|
||||
duration = 6
|
||||
|
||||
/obj/effect/temp_visual/eldritch_smoke
|
||||
icon = 'icons/effects/eldritch.dmi'
|
||||
icon_state = "smoke"
|
||||
duration = 10
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fiery_rebirth
|
||||
name = "Nightwatcher's Rebirth"
|
||||
desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a person is in critical condition it finishes them off."
|
||||
invocation = "PETHRO'MINO'IGNI"
|
||||
invocation_type = "whisper"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
charge_max = 600
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "smoke"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fiery_rebirth/cast(list/targets, mob/user)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
for(var/mob/living/carbon/target in view(7,user))
|
||||
if(target.stat == DEAD || !target.on_fire)
|
||||
continue
|
||||
//This is essentially a death mark, use this to finish your opponent quicker.
|
||||
if(target.InCritical())
|
||||
target.death()
|
||||
target.adjustFireLoss(20)
|
||||
new /obj/effect/temp_visual/eldritch_smoke(target.drop_location())
|
||||
human_user.ExtinguishMob()
|
||||
human_user.adjustBruteLoss(-10, FALSE)
|
||||
human_user.adjustFireLoss(-10, FALSE)
|
||||
human_user.adjustStaminaLoss(-10, FALSE)
|
||||
human_user.adjustToxLoss(-10, FALSE)
|
||||
human_user.adjustOxyLoss(-10)
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/manse_link
|
||||
name = "Mansus Link"
|
||||
desc = "Piercing through reality, connecting minds. This spell allows you to add people to a mansus net, allowing them to communicate with eachother"
|
||||
school = "transmutation"
|
||||
charge_max = 300
|
||||
clothes_req = FALSE
|
||||
invocation = "SUSEI' METO MIN'TIS"
|
||||
invocation_type = "whisper"
|
||||
range = 10
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "mansus_link"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/manse_link/can_target(atom/target, mob/user, silent)
|
||||
if(!isliving(target))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/manse_link/cast(list/targets, mob/user)
|
||||
var/mob/living/simple_animal/hostile/eldritch/raw_prophet/originator = user
|
||||
|
||||
var/mob/living/target = targets[1]
|
||||
|
||||
to_chat(originator, "<span class='notice'>You begin linking [target]'s mind to yours...</span>")
|
||||
to_chat(target, "<span class='warning'>You feel your mind being pulled... connected... intertwined with the very fabric of reality...</span>")
|
||||
if(!do_after(originator, 6 SECONDS, target))
|
||||
return
|
||||
if(!originator.link_mob(target))
|
||||
to_chat(originator, "<span class='warning'>You can't seem to link [target]'s mind...</span>")
|
||||
to_chat(target, "<span class='warning'>The foreign presence leaves your mind.</span>")
|
||||
return
|
||||
to_chat(originator, "<span class='notice'>You connect [target]'s mind to your mansus link!</span>")
|
||||
|
||||
|
||||
/datum/action/innate/mansus_speech
|
||||
name = "Mansus Link"
|
||||
desc = "Send a psychic message to everyone connected to your mansus link."
|
||||
button_icon_state = "link_speech"
|
||||
icon_icon = 'icons/mob/actions/actions_slime.dmi'
|
||||
background_icon_state = "bg_ecult"
|
||||
var/mob/living/simple_animal/hostile/eldritch/raw_prophet/originator
|
||||
|
||||
/datum/action/innate/mansus_speech/New(_originator)
|
||||
. = ..()
|
||||
originator = _originator
|
||||
|
||||
/datum/action/innate/mansus_speech/Activate()
|
||||
var/mob/living/living_owner = owner
|
||||
if(!originator?.linked_mobs[living_owner])
|
||||
CRASH("Uh oh the mansus link got somehow activated without it being linked to a raw prophet or the mob not being in a list of mobs that should be able to do it.")
|
||||
|
||||
var/message = sanitize(input("Message:", "Telepathy from the Manse") as text|null)
|
||||
|
||||
if(QDELETED(living_owner))
|
||||
return
|
||||
|
||||
if(!originator?.linked_mobs[living_owner])
|
||||
to_chat(living_owner, "<span class='warning'>The link seems to have been severed...</span>")
|
||||
Remove(living_owner)
|
||||
return
|
||||
if(message)
|
||||
var/msg = "<i><font color=#568b00>\[Mansus Link\] <b>[living_owner]:</b> [message]</font></i>"
|
||||
log_directed_talk(living_owner, originator, msg, LOG_SAY, "Mansus Link")
|
||||
to_chat(originator.linked_mobs, msg)
|
||||
|
||||
for(var/dead_mob in GLOB.dead_mob_list)
|
||||
var/link = FOLLOW_LINK(dead_mob, living_owner)
|
||||
to_chat(dead_mob, "[link] [msg]")
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/trigger/blind/eldritch
|
||||
range = 10
|
||||
invocation = "AK'LIS"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/entropic
|
||||
icon = 'icons/effects/160x160.dmi'
|
||||
icon_state = "entropic_plume"
|
||||
duration = 3 SECONDS
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/entropic/setDir(dir)
|
||||
. = ..()
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
pixel_x = -64
|
||||
if(SOUTH)
|
||||
pixel_x = -64
|
||||
pixel_y = -128
|
||||
if(EAST)
|
||||
pixel_y = -64
|
||||
if(WEST)
|
||||
pixel_y = -64
|
||||
pixel_x = -128
|
||||
|
||||
/obj/effect/temp_visual/glowing_rune
|
||||
icon = 'icons/effects/eldritch.dmi'
|
||||
icon_state = "small_rune_1"
|
||||
duration = 1 MINUTES
|
||||
layer = LOW_SIGIL_LAYER
|
||||
|
||||
/obj/effect/temp_visual/glowing_rune/Initialize()
|
||||
. = ..()
|
||||
pixel_y = rand(-6,6)
|
||||
pixel_x = rand(-6,6)
|
||||
icon_state = "small_rune_[rand(12)]"
|
||||
update_icon()
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/staggered/entropic_plume
|
||||
name = "Entropic Plume"
|
||||
desc = "Spews forth a disorienting plume that causes enemies to strike each other, briefly blinds them(increasing with range) and poisons them(decreasing with range). Also spreads rust in the path of the plume."
|
||||
school = "illusion"
|
||||
invocation = "RU'KAS NU'DYTI"
|
||||
invocation_type = "whisper"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "entropic_plume"
|
||||
charge_max = 300
|
||||
cone_levels = 5
|
||||
respect_density = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/cast(list/targets,mob/user = usr)
|
||||
. = ..()
|
||||
new /obj/effect/temp_visual/dir_setting/entropic(get_step(user,user.dir), user.dir)
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/do_turf_cone_effect(turf/target_turf, level)
|
||||
. = ..()
|
||||
target_turf.rust_heretic_act()
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/do_mob_cone_effect(mob/living/victim, level)
|
||||
. = ..()
|
||||
if(victim.anti_magic_check() || IS_HERETIC(victim) || victim.mind?.has_antag_datum(/datum/antagonist/heretic_monster))
|
||||
return
|
||||
victim.apply_status_effect(STATUS_EFFECT_AMOK)
|
||||
victim.apply_status_effect(STATUS_EFFECT_CLOUDSTRUCK, (level*10))
|
||||
if(iscarbon(victim))
|
||||
var/mob/living/carbon/carbon_victim = victim
|
||||
carbon_victim.reagents.add_reagent(/datum/reagent/eldritch, min(1, 6-level))
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/calculate_cone_shape(current_level)
|
||||
if(current_level == cone_levels)
|
||||
return 5
|
||||
else if(current_level == cone_levels-1)
|
||||
return 3
|
||||
else
|
||||
return 2
|
||||
@@ -0,0 +1,43 @@
|
||||
///Tracking reasons
|
||||
/datum/antagonist/heretic_monster
|
||||
name = "Eldritch Horror"
|
||||
roundend_category = "Heretics"
|
||||
antagpanel_category = "Heretic Beast"
|
||||
antag_moodlet = /datum/mood_event/heretics
|
||||
job_rank = ROLE_HERETIC
|
||||
antag_hud_type = ANTAG_HUD_HERETIC
|
||||
antag_hud_name = "heretic_beast"
|
||||
var/datum/antagonist/master
|
||||
|
||||
/datum/antagonist/heretic_monster/admin_add(datum/mind/new_owner,mob/admin)
|
||||
new_owner.add_antag_datum(src)
|
||||
message_admins("[key_name_admin(admin)] has heresized [key_name_admin(new_owner)].")
|
||||
log_admin("[key_name(admin)] has heresized [key_name(new_owner)].")
|
||||
|
||||
/datum/antagonist/heretic_monster/greet()
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ecult_op.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change
|
||||
to_chat(owner, "<span class='boldannounce'>You became an Eldritch Horror!</span>")
|
||||
|
||||
/datum/antagonist/heretic_monster/on_removal()
|
||||
if(owner)
|
||||
to_chat(owner, "<span class='boldannounce'>Your master is no longer [master.owner.current.real_name]</span>")
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/heretic_monster/proc/set_owner(datum/antagonist/_master)
|
||||
master = _master
|
||||
var/datum/objective/master_obj = new
|
||||
master_obj.owner = src
|
||||
master_obj.explanation_text = "Assist your master in any way you can!"
|
||||
objectives += master_obj
|
||||
owner.announce_objectives()
|
||||
to_chat(owner, "<span class='boldannounce'>Your master is [master.owner.current.real_name]</span>")
|
||||
return
|
||||
|
||||
/datum/antagonist/heretic_monster/apply_innate_effects(mob/living/mob_override)
|
||||
. = ..()
|
||||
add_antag_hud(antag_hud_type, antag_hud_name, owner.current)
|
||||
|
||||
/datum/antagonist/heretic_monster/remove_innate_effects(mob/living/mob_override)
|
||||
. = ..()
|
||||
remove_antag_hud(antag_hud_type, owner.current)
|
||||
@@ -0,0 +1,183 @@
|
||||
/datum/eldritch_knowledge/base_ash
|
||||
name = "Nightwatcher's Secret"
|
||||
desc = "Inducts you into the Path of Ash. Allows you to transmute a match with an eldritch blade into an ashen blade."
|
||||
gain_text = "The City guard knows their watch. If you ask them at night they may tell you about the ashy lantern."
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/rust_final,/datum/eldritch_knowledge/final/flesh_final)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/ashen_grasp)
|
||||
required_atoms = list(/obj/item/melee/sickly_blade,/obj/item/match)
|
||||
result_atoms = list(/obj/item/melee/sickly_blade/ash)
|
||||
cost = 1
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/spell/ashen_shift
|
||||
name = "Ashen Shift"
|
||||
gain_text = "Ash is all the same, how can one man master it all?"
|
||||
desc = "A short range jaunt that will enable you to escape from danger."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash
|
||||
next_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/essence,/datum/eldritch_knowledge/ashen_eyes)
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/ashen_grasp
|
||||
name = "Grasp of Ash"
|
||||
gain_text = "Gates have opened, minds have flooded, yet I remain."
|
||||
desc = "Empowers your mansus grasp to knock enemies down and throw them away."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/ashen_shift)
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/ashen_grasp/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!iscarbon(target))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/C = target
|
||||
var/datum/status_effect/eldritch/E = C.has_status_effect(/datum/status_effect/eldritch/rust) || C.has_status_effect(/datum/status_effect/eldritch/ash) || C.has_status_effect(/datum/status_effect/eldritch/flesh)
|
||||
if(E)
|
||||
. = TRUE
|
||||
E.on_effect()
|
||||
for(var/X in user.mind.spell_list)
|
||||
if(!istype(X,/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp))
|
||||
continue
|
||||
var/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp/MG = X
|
||||
MG.charge_counter = min(round(MG.charge_counter + MG.charge_max * 0.75),MG.charge_max) // refunds 75% of charge.
|
||||
var/atom/throw_target = get_edge_target_turf(C, user.dir)
|
||||
if(!C.anchored)
|
||||
. = TRUE
|
||||
C.throw_at(throw_target, rand(4,8), 14, user)
|
||||
return
|
||||
|
||||
/datum/eldritch_knowledge/ashen_eyes
|
||||
name = "Ashen Eyes"
|
||||
gain_text = "Piercing eyes may guide me through the mundane."
|
||||
desc = "Allows you to craft thermal vision amulet by transmutating eyes with a glass shard."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/ashen_shift,/datum/eldritch_knowledge/flesh_ghoul)
|
||||
required_atoms = list(/obj/item/organ/eyes,/obj/item/shard)
|
||||
result_atoms = list(/obj/item/clothing/neck/eldritch_amulet)
|
||||
|
||||
/datum/eldritch_knowledge/ash_mark
|
||||
name = "Mark of Ash"
|
||||
gain_text = "Spread the famine."
|
||||
desc = "Your sickly blade now applies ash mark on hit. Use your mansus grasp to proc the mark. Mark of Ash causes stamina damage, and fire loss, and spreads to a nearby carbon. Damage decreases with how many times the mark has spread."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/curse/blindness)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/flesh_mark)
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/ash_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(isliving(target))
|
||||
var/mob/living/living_target = target
|
||||
living_target.apply_status_effect(/datum/status_effect/eldritch/ash,5)
|
||||
|
||||
/datum/eldritch_knowledge/curse/blindness
|
||||
name = "Curse of Blindness"
|
||||
gain_text = "The blind man walks through the world, unnoticed by the masses."
|
||||
desc = "Curse someone with 2 minutes of complete blindness by sacrificing a pair of eyes, a screwdriver and a pool of blood, with an object that the victim has touched with their bare hands."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/item/organ/eyes,/obj/item/screwdriver,/obj/effect/decal/cleanable/blood)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/curse/corrosion,/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/curse/paralysis)
|
||||
timer = 2 MINUTES
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/curse/blindness/curse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
chosen_mob.become_blind(MAGIC_TRAIT)
|
||||
|
||||
/datum/eldritch_knowledge/curse/blindness/uncurse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
chosen_mob.cure_blind(MAGIC_TRAIT)
|
||||
|
||||
/datum/eldritch_knowledge/spell/flame_birth
|
||||
name = "Fiery Rebirth"
|
||||
gain_text = "Nightwatcher was a man of principles, and yet he arose from the chaos he vowed to protect from."
|
||||
desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a person is in critical condition it finishes them off."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/targeted/fiery_rebirth
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/cleave,/datum/eldritch_knowledge/summon/ashy,/datum/eldritch_knowledge/final/ash_final)
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/ash_blade_upgrade
|
||||
name = "Blazing Steel"
|
||||
gain_text = "May the sun burn the heretics."
|
||||
desc = "Your blade of choice will now add firestacks."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/flame_birth)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade)
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/ash_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C = target
|
||||
C.adjust_fire_stacks(1)
|
||||
C.IgniteMob()
|
||||
|
||||
/datum/eldritch_knowledge/curse/corrosion
|
||||
name = "Curse of Corrosion"
|
||||
gain_text = "Cursed land, cursed man, cursed mind."
|
||||
desc = "Curse someone for 2 minutes of vomiting and major organ damage. Using a wirecutter, a spill of blood, a heart, left arm and a right arm, and an item that the victim touched with their bare hands."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/item/wirecutters,/obj/effect/decal/cleanable/blood,/obj/item/organ/heart,/obj/item/bodypart/l_arm,/obj/item/bodypart/r_arm)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/curse/blindness,/datum/eldritch_knowledge/spell/area_conversion)
|
||||
timer = 2 MINUTES
|
||||
|
||||
/datum/eldritch_knowledge/curse/corrosion/curse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
chosen_mob.apply_status_effect(/datum/status_effect/corrosion_curse)
|
||||
|
||||
/datum/eldritch_knowledge/curse/corrosion/uncurse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
chosen_mob.remove_status_effect(/datum/status_effect/corrosion_curse)
|
||||
|
||||
/datum/eldritch_knowledge/curse/paralysis
|
||||
name = "Curse of Paralysis"
|
||||
gain_text = "Corrupt their flesh, make them bleed."
|
||||
desc = "Curse someone for 5 minutes of inability to walk. Using a knife, pool of blood, left leg, right leg, a hatchet and an item that the victim touched with their bare hands. "
|
||||
cost = 1
|
||||
required_atoms = list(/obj/item/kitchen/knife,/obj/effect/decal/cleanable/blood,/obj/item/bodypart/l_leg,/obj/item/bodypart/r_leg,/obj/item/hatchet)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/curse/blindness,/datum/eldritch_knowledge/summon/raw_prophet)
|
||||
timer = 5 MINUTES
|
||||
|
||||
/datum/eldritch_knowledge/curse/paralysis/curse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
ADD_TRAIT(chosen_mob,TRAIT_PARALYSIS_L_LEG,MAGIC_TRAIT)
|
||||
ADD_TRAIT(chosen_mob,TRAIT_PARALYSIS_R_LEG,MAGIC_TRAIT)
|
||||
chosen_mob.update_mobility()
|
||||
|
||||
/datum/eldritch_knowledge/curse/paralysis/uncurse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(chosen_mob,TRAIT_PARALYSIS_L_LEG,MAGIC_TRAIT)
|
||||
REMOVE_TRAIT(chosen_mob,TRAIT_PARALYSIS_R_LEG,MAGIC_TRAIT)
|
||||
chosen_mob.update_mobility()
|
||||
|
||||
/datum/eldritch_knowledge/spell/cleave
|
||||
name = "Blood Cleave"
|
||||
gain_text = "At first I was unfamiliar with these instruments of war, but the priest told me how to use them."
|
||||
desc = "Grants a spell that will inflict wounds and bleeding upon the target, as well as in a short radius around them."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/pointed/cleave
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/entropic_plume,/datum/eldritch_knowledge/spell/flame_birth)
|
||||
|
||||
/datum/eldritch_knowledge/final/ash_final
|
||||
name = "Ashlord's Rite"
|
||||
gain_text = "The forgotten lords have spoken! The Lord of Ash has come! Fear the flame!"
|
||||
desc = "Bring three corpses onto a transmutation rune, after ascending you will become immune to fire, space, temperature and other environmental hazards. You will develop resistance to all other damages. You will be granted two spells, one which can bring forth a cascade of massive fire, and another which will surround your body in precious flames for a minute."
|
||||
required_atoms = list(/mob/living/carbon/human)
|
||||
cost = 5
|
||||
route = PATH_ASH
|
||||
var/list/trait_list = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_GENELESS,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_BOMBIMMUNE)
|
||||
|
||||
/datum/eldritch_knowledge/final/ash_final/on_finished_recipe(mob/living/user, list/atoms, loc)
|
||||
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the blaze, for Ashbringer [user.real_name] has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
|
||||
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/fire_cascade/big)
|
||||
user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/fire_sworn)
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.physiology.brute_mod *= 0.5
|
||||
H.physiology.burn_mod *= 0.5
|
||||
var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
ascension.ascended = TRUE
|
||||
for(var/X in trait_list)
|
||||
ADD_TRAIT(user,X,MAGIC_TRAIT)
|
||||
return ..()
|
||||
@@ -0,0 +1,252 @@
|
||||
/datum/eldritch_knowledge/base_flesh
|
||||
name = "Principle of Hunger"
|
||||
desc = "Inducts you into the Path of Flesh. Allows you to transmute a pool of blood with your eldritch blade into a Blade of Flesh."
|
||||
gain_text = "Hundred's of us starved, but I.. I found the strength in my greed."
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/rust_final)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/flesh_grasp)
|
||||
required_atoms = list(/obj/item/melee/sickly_blade,/obj/effect/decal/cleanable/blood)
|
||||
result_atoms = list(/obj/item/melee/sickly_blade/flesh)
|
||||
cost = 1
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/flesh_ghoul
|
||||
name = "Imperfect Ritual"
|
||||
desc = "Allows you to resurrect the dead as voiceless dead by sacrificing them on the transmutation rune with a poppy. Voiceless dead are mute and have 50 HP. You can only have 2 at a time."
|
||||
gain_text = "I found notes... notes of a ritual, scraps, unfinished, and yet... I still did it."
|
||||
cost = 1
|
||||
required_atoms = list(/mob/living/carbon/human,/obj/item/reagent_containers/food/snacks/grown/poppy)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/flesh_mark,/datum/eldritch_knowledge/armor,/datum/eldritch_knowledge/ashen_eyes)
|
||||
route = PATH_FLESH
|
||||
var/max_amt = 2
|
||||
var/current_amt = 0
|
||||
var/list/ghouls = list()
|
||||
|
||||
/datum/eldritch_knowledge/flesh_ghoul/on_finished_recipe(mob/living/user,list/atoms,loc)
|
||||
var/mob/living/carbon/human/humie = locate() in atoms
|
||||
if(QDELETED(humie) || humie.stat != DEAD)
|
||||
return
|
||||
|
||||
if(length(ghouls) >= max_amt)
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(humie,TRAIT_HUSK))
|
||||
return
|
||||
|
||||
humie.grab_ghost()
|
||||
|
||||
if(!humie.mind || !humie.client)
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [humie.real_name], a voiceless dead.", ROLE_HERETIC, null, ROLE_HERETIC, 50,humie)
|
||||
if(!LAZYLEN(candidates))
|
||||
return
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(humie)]) to replace an AFK player.")
|
||||
humie.ghostize(0)
|
||||
humie.key = C.key
|
||||
|
||||
ADD_TRAIT(humie,TRAIT_MUTE,MAGIC_TRAIT)
|
||||
log_game("[key_name_admin(humie)] has become a voiceless dead, their master is [user.real_name]")
|
||||
humie.revive(full_heal = TRUE, admin_revive = TRUE)
|
||||
humie.setMaxHealth(75)
|
||||
humie.health = 75 // Voiceless dead are much tougher than ghouls
|
||||
humie.become_husk()
|
||||
humie.faction |= "heretics"
|
||||
|
||||
var/datum/antagonist/heretic_monster/heretic_monster = humie.mind.add_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
heretic_monster.set_owner(master)
|
||||
atoms -= humie
|
||||
RegisterSignal(humie,COMSIG_MOB_DEATH,.proc/remove_ghoul)
|
||||
ghouls += humie
|
||||
|
||||
/datum/eldritch_knowledge/flesh_ghoul/proc/remove_ghoul(datum/source)
|
||||
var/mob/living/carbon/human/humie = source
|
||||
ghouls -= humie
|
||||
humie.mind.remove_antag_datum(/datum/antagonist/heretic_monster)
|
||||
UnregisterSignal(source,COMSIG_MOB_DEATH)
|
||||
|
||||
/datum/eldritch_knowledge/flesh_grasp
|
||||
name = "Grasp of Flesh"
|
||||
gain_text = "'My newfound desire, it drove me to do great things,' The Priest said."
|
||||
desc = "Empowers your Mansus Grasp to be able to create a single ghoul out of a dead player. You cannot raise the same person twice. Ghouls have only 50 HP and look like husks."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/flesh_ghoul)
|
||||
var/ghoul_amt = 6
|
||||
var/list/spooky_scaries
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/flesh_grasp/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!ishuman(target) || target == user)
|
||||
return
|
||||
var/mob/living/carbon/human/human_target = target
|
||||
var/datum/status_effect/eldritch/eldritch_effect = human_target.has_status_effect(/datum/status_effect/eldritch/rust) || human_target.has_status_effect(/datum/status_effect/eldritch/ash) || human_target.has_status_effect(/datum/status_effect/eldritch/flesh)
|
||||
if(eldritch_effect)
|
||||
. = TRUE
|
||||
eldritch_effect.on_effect()
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts)
|
||||
var/datum/wound/slash/severe/crit_wound = new
|
||||
crit_wound.apply_wound(bodypart)
|
||||
|
||||
if(QDELETED(human_target) || human_target.stat != DEAD)
|
||||
return
|
||||
|
||||
human_target.grab_ghost()
|
||||
|
||||
if(!human_target.mind || !human_target.client)
|
||||
to_chat(user, "<span class='warning'>There is no soul connected to this body...</span>")
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(human_target, TRAIT_HUSK))
|
||||
to_chat(user, "<span class='warning'>You cannot revive a dead ghoul!</span>")
|
||||
return
|
||||
|
||||
if(LAZYLEN(spooky_scaries) >= ghoul_amt)
|
||||
to_chat(user, "<span class='warning'>Your patron cannot support more ghouls on this plane!</span>")
|
||||
return
|
||||
|
||||
LAZYADD(spooky_scaries, human_target)
|
||||
log_game("[key_name_admin(human_target)] has become a ghoul, their master is [user.real_name]")
|
||||
//we change it to true only after we know they passed all the checks
|
||||
. = TRUE
|
||||
RegisterSignal(human_target,COMSIG_MOB_DEATH,.proc/remove_ghoul)
|
||||
human_target.revive(full_heal = TRUE, admin_revive = TRUE)
|
||||
human_target.setMaxHealth(40)
|
||||
human_target.health = 40
|
||||
human_target.become_husk()
|
||||
human_target.faction |= "heretics"
|
||||
var/datum/antagonist/heretic_monster/heretic_monster = human_target.mind.add_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
heretic_monster.set_owner(master)
|
||||
return
|
||||
|
||||
|
||||
/datum/eldritch_knowledge/flesh_grasp/proc/remove_ghoul(datum/source)
|
||||
var/mob/living/carbon/human/humie = source
|
||||
spooky_scaries -= humie
|
||||
humie.mind.remove_antag_datum(/datum/antagonist/heretic_monster)
|
||||
UnregisterSignal(source, COMSIG_MOB_DEATH)
|
||||
|
||||
/datum/eldritch_knowledge/flesh_mark
|
||||
name = "Mark of Flesh"
|
||||
gain_text = "I saw them, the marked ones. The screams... the silence."
|
||||
desc = "Your sickly blade now applies a mark of flesh to those cut by it. Once marked, using your Mansus Grasp upon them will cause additional bleeding from the target."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/raw_prophet)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/ash_mark)
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/flesh_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(isliving(target))
|
||||
var/mob/living/living_target = target
|
||||
living_target.apply_status_effect(/datum/status_effect/eldritch/flesh)
|
||||
|
||||
/datum/eldritch_knowledge/flesh_blade_upgrade
|
||||
name = "Bleeding Steel"
|
||||
gain_text = "It rained blood, that's when I understood the gravekeeper's advice."
|
||||
desc = "Your blade will now cause additional bleeding to those hit by it."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/stalker)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/rust_blade_upgrade)
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/flesh_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts)
|
||||
var/datum/wound/slash/severe/crit_wound = new
|
||||
crit_wound.apply_wound(bodypart)
|
||||
|
||||
/datum/eldritch_knowledge/summon/raw_prophet
|
||||
name = "Raw Ritual"
|
||||
gain_text = "The uncanny man walks alone in the valley, I was able to call his aid."
|
||||
desc = "You can now summon a Raw Prophet using eyes, a left arm, right arm and a pool of blood using a transmutation circle. Raw prophets have increased seeing range, and can see through walls. They can jaunt long distances, though they are fragile."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/item/organ/eyes,/obj/item/bodypart/l_arm,/obj/item/bodypart/r_arm,/obj/effect/decal/cleanable/blood)
|
||||
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/raw_prophet
|
||||
next_knowledge = list(/datum/eldritch_knowledge/flesh_blade_upgrade,/datum/eldritch_knowledge/spell/blood_siphon,/datum/eldritch_knowledge/curse/paralysis)
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/summon/stalker
|
||||
name = "Lonely Ritual"
|
||||
gain_text = "I was able to combine my greed and desires to summon an eldritch beast I have not seen before."
|
||||
desc = "You can now summon a Stalker using a knife, a flower, a pen and a piece of paper using a transmutation circle. Stalkers possess the ability to shapeshift into various forms while assuming the vigor and powers of that form."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/item/kitchen/knife,/obj/item/reagent_containers/food/snacks/grown/poppy,/obj/item/pen,/obj/item/paper)
|
||||
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/stalker
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/ashy,/datum/eldritch_knowledge/summon/rusty,/datum/eldritch_knowledge/final/flesh_final)
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/summon/ashy
|
||||
name = "Ashen Ritual"
|
||||
gain_text = "I combined principle of hunger with desire of destruction. The eyeful lords have noticed me."
|
||||
desc = "You can now summon an Ashen One by transmuting a pile of ash, a head and a book using a transmutation circle. They possess the ability to jaunt short distances and create a cascade of flames."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/effect/decal/cleanable/ash,/obj/item/bodypart/head,/obj/item/book)
|
||||
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/ash_spirit
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/stalker,/datum/eldritch_knowledge/spell/flame_birth)
|
||||
|
||||
/datum/eldritch_knowledge/summon/rusty
|
||||
name = "Rusted Ritual"
|
||||
gain_text = "I combined principle of hunger with desire of corruption. The rusted hills call my name."
|
||||
desc = "You can now summon a Rust Walker transmuting a vomit pool, a head, and a book using a transmutation circle. Rust Walkers possess the ability to spread rust and can fire bolts of rust to further corrode the area."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/effect/decal/cleanable/vomit,/obj/item/bodypart/head,/obj/item/book)
|
||||
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/rust_spirit
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/stalker,/datum/eldritch_knowledge/spell/entropic_plume)
|
||||
|
||||
/datum/eldritch_knowledge/spell/blood_siphon
|
||||
name = "Blood Siphon"
|
||||
gain_text = "Our blood is all the same after all, the owl told me."
|
||||
desc = "You are granted a spell that drains some of the targets health, and returns it to you. It also has a chance to transfer any wounds you possess onto the target."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/blood_siphon
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/raw_prophet,/datum/eldritch_knowledge/spell/area_conversion)
|
||||
|
||||
/datum/eldritch_knowledge/final/flesh_final
|
||||
name = "Priest's Final Hymn"
|
||||
gain_text = "Man of this world. Hear me! For the time of the lord of arms has come!"
|
||||
desc = "Bring three corpses to a transmutation rune to either ascend as The Lord of the Night or summon a single Terror of the Night, however you cannot ascend more than once."
|
||||
required_atoms = list(/mob/living/carbon/human)
|
||||
cost = 5
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/final/flesh_final/on_finished_recipe(mob/living/user, list/atoms, loc)
|
||||
var/alert_ = alert(user,"Do you want to ascend as the lord of the night or just summon a terror of the night?","...","Yes","No")
|
||||
user.SetImmobilized(10 HOURS) // no way someone will stand 10 hours in a spot, just so he can move while the alert is still showing.
|
||||
switch(alert_)
|
||||
if("No")
|
||||
var/mob/living/summoned = new /mob/living/simple_animal/hostile/eldritch/armsy(loc)
|
||||
message_admins("[summoned.name] is being summoned by [user.real_name] in [loc]")
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [summoned.real_name]", ROLE_HERETIC, null, ROLE_HERETIC, 100,summoned)
|
||||
user.SetImmobilized(0)
|
||||
if(LAZYLEN(candidates) == 0)
|
||||
to_chat(user,"<span class='warning'>No ghost could be found...</span>")
|
||||
qdel(summoned)
|
||||
return FALSE
|
||||
var/mob/dead/observer/ghost_candidate = pick(candidates)
|
||||
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the dark, for vassal of arms has ascended! Terror of the night has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
|
||||
log_game("[key_name_admin(ghost_candidate)] has taken control of ([key_name_admin(summoned)]).")
|
||||
summoned.ghostize(FALSE)
|
||||
summoned.key = ghost_candidate.key
|
||||
summoned.mind.add_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic_monster/monster = summoned.mind.has_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
monster.set_owner(master)
|
||||
master.ascended = TRUE
|
||||
if("Yes")
|
||||
var/mob/living/summoned = new /mob/living/simple_animal/hostile/eldritch/armsy/prime(loc,TRUE,10)
|
||||
summoned.ghostize(0)
|
||||
user.SetImmobilized(0)
|
||||
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the dark, for king of arms has ascended! Lord of the night has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
|
||||
log_game("[user.real_name] ascended as [summoned.real_name]")
|
||||
var/mob/living/carbon/carbon_user = user
|
||||
var/datum/antagonist/heretic/ascension = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
ascension.ascended = TRUE
|
||||
carbon_user.mind.transfer_to(summoned, TRUE)
|
||||
carbon_user.gib()
|
||||
|
||||
return ..()
|
||||
@@ -0,0 +1,209 @@
|
||||
/datum/eldritch_knowledge/base_rust
|
||||
name = "Blacksmith's Tale"
|
||||
desc = "Inducts you into the Path of Rust. Allows you to transmute an eldritch blade with any trash item into a Blade of Rust."
|
||||
gain_text = "'Let me tell you a story,' The Blacksmith said as he gazed into his rusty blade."
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/flesh_final)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_fist)
|
||||
required_atoms = list(/obj/item/melee/sickly_blade,/obj/item/trash)
|
||||
result_atoms = list(/obj/item/melee/sickly_blade/rust)
|
||||
cost = 1
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_fist
|
||||
name = "Grasp of Rust"
|
||||
desc = "Empowers your Mansus Grasp to deal 500 damage to non-living matter and rust any structure it touches. Destroys already rusted structures."
|
||||
gain_text = "Rust grows on the ceiling of the mansus."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_regen)
|
||||
var/rust_force = 500
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(/turf/closed,/turf/open/space,/turf/open/lava,/turf/open/chasm,/turf/open/floor/plating/rust))
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_fist/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
var/datum/status_effect/eldritch/E = H.has_status_effect(/datum/status_effect/eldritch/rust) || H.has_status_effect(/datum/status_effect/eldritch/ash) || H.has_status_effect(/datum/status_effect/eldritch/flesh)
|
||||
if(E)
|
||||
E.on_effect()
|
||||
H.adjustOrganLoss(pick(ORGAN_SLOT_BRAIN,ORGAN_SLOT_EARS,ORGAN_SLOT_EYES,ORGAN_SLOT_LIVER,ORGAN_SLOT_LUNGS,ORGAN_SLOT_STOMACH,ORGAN_SLOT_HEART),25)
|
||||
target.rust_heretic_act()
|
||||
target.emp_act(EMP_HEAVY)
|
||||
return TRUE
|
||||
|
||||
/datum/eldritch_knowledge/spell/area_conversion
|
||||
name = "Aggressive Spread"
|
||||
desc = "Spreads rust to nearby turfs. Destroys already rusted walls."
|
||||
gain_text = "All wise men know not to touch the bound king."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/aoe_turf/rust_conversion
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/curse/corrosion,/datum/eldritch_knowledge/spell/blood_siphon,/datum/eldritch_knowledge/spell/rust_wave)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/spell/rust_wave
|
||||
name = "Patron's Reach"
|
||||
desc = "You can now send a bolt of rust that corrupts the immediate area, and poisons the first target hit."
|
||||
gain_text = "Messengers of hope fear the rustbringer."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/aimed/rust_wave
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_regen
|
||||
name = "Leeching Walk"
|
||||
desc = "Passively heals you when you are on rusted tiles."
|
||||
gain_text = "'The strength was unparalleled, unnatural.' The Blacksmith was smiling."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/armor,/datum/eldritch_knowledge/essence)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_regen/on_life(mob/user)
|
||||
. = ..()
|
||||
var/turf/user_loc_turf = get_turf(user)
|
||||
if(!istype(user_loc_turf, /turf/open/floor/plating/rust) || !isliving(user))
|
||||
return
|
||||
var/mob/living/living_user = user
|
||||
living_user.adjustBruteLoss(-3, FALSE)
|
||||
living_user.adjustFireLoss(-3, FALSE)
|
||||
living_user.adjustToxLoss(-3, FALSE)
|
||||
living_user.adjustOxyLoss(-1, FALSE)
|
||||
living_user.adjustStaminaLoss(-6)
|
||||
|
||||
/datum/eldritch_knowledge/rust_mark
|
||||
name = "Mark of Rust"
|
||||
desc = "Your eldritch blade now applies a rust mark. Rust marks have a chance to deal between 0 to 200 damage to 75% of enemies items. To activate the mark use your Mansus Grasp on it."
|
||||
gain_text = "Lords of the depths help those in dire need at a cost."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/area_conversion)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/flesh_mark)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(isliving(target))
|
||||
var/mob/living/living_target = target
|
||||
living_target.apply_status_effect(/datum/status_effect/eldritch/rust)
|
||||
|
||||
/datum/eldritch_knowledge/rust_blade_upgrade
|
||||
name = "Toxic Steel"
|
||||
gain_text = "Let the blade guide you through the flesh."
|
||||
desc = "Your blade of choice will now add toxin to enemies bloodstream."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/entropic_plume)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
carbon_target.reagents.add_reagent(/datum/reagent/eldritch, 5)
|
||||
|
||||
/datum/eldritch_knowledge/spell/entropic_plume
|
||||
name = "Entropic Plume"
|
||||
desc = "You can now send a befuddling plume that blinds, poisons and makes enemies strike each other, while also converting the immediate area into rust."
|
||||
gain_text = "Messengers of hope fear the rustbringer."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/cone/staggered/entropic_plume
|
||||
next_knowledge = list(/datum/eldritch_knowledge/final/rust_final,/datum/eldritch_knowledge/spell/cleave,/datum/eldritch_knowledge/summon/rusty)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/armor
|
||||
name = "Armorer's Ritual"
|
||||
desc = "You can now create eldritch armor using a built table and a gas mask on top of a transmutation rune."
|
||||
gain_text = "For I am the heir to the throne of doom."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_regen,/datum/eldritch_knowledge/flesh_ghoul)
|
||||
required_atoms = list(/obj/structure/table,/obj/item/clothing/mask/gas)
|
||||
result_atoms = list(/obj/item/clothing/suit/hooded/cultrobes/eldritch)
|
||||
|
||||
/datum/eldritch_knowledge/essence
|
||||
name = "Priest's Ritual"
|
||||
desc = "You can now transmute a tank of water into a bottle of eldritch fluid."
|
||||
gain_text = "This is an old recipe, i got it from an owl."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_regen,/datum/eldritch_knowledge/spell/ashen_shift)
|
||||
required_atoms = list(/obj/structure/reagent_dispensers/watertank)
|
||||
result_atoms = list(/obj/item/reagent_containers/glass/beaker/eldritch)
|
||||
|
||||
/datum/eldritch_knowledge/final/rust_final
|
||||
name = "Rustbringer's Oath"
|
||||
desc = "Bring three corpses onto a transmutation rune. After you finish the ritual, rust will now automatically spread from the rune. Your healing on rust is also tripled, while you become more resilient overall."
|
||||
gain_text = "Champion of rust. Corruptor of steel. Fear the dark for Rustbringer has come!"
|
||||
cost = 5
|
||||
required_atoms = list(/mob/living/carbon/human)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/final/rust_final/on_finished_recipe(mob/living/user, list/atoms, loc)
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.physiology.brute_mod *= 0.5
|
||||
H.physiology.burn_mod *= 0.5
|
||||
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the decay, for Rustbringer [user.real_name] has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
|
||||
new /datum/rust_spread(loc)
|
||||
var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
ascension.ascended = TRUE
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/eldritch_knowledge/final/rust_final/on_life(mob/user)
|
||||
. = ..()
|
||||
if(!finished)
|
||||
return
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
human_user.adjustBruteLoss(-6, FALSE)
|
||||
human_user.adjustFireLoss(-6, FALSE)
|
||||
human_user.adjustToxLoss(-6, FALSE)
|
||||
human_user.adjustOxyLoss(-6, FALSE)
|
||||
human_user.adjustStaminaLoss(-20)
|
||||
|
||||
|
||||
/**
|
||||
* #Rust spread datum
|
||||
*
|
||||
* Simple datum that automatically spreads rust around it
|
||||
*
|
||||
* Simple implementation of automatically growing entity
|
||||
*/
|
||||
/datum/rust_spread
|
||||
var/list/edge_turfs = list()
|
||||
var/list/turfs = list()
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(/turf/open/indestructible,/turf/closed/indestructible,/turf/open/space,/turf/open/lava,/turf/open/chasm))
|
||||
var/spread_per_tick = 6
|
||||
|
||||
|
||||
/datum/rust_spread/New(loc)
|
||||
. = ..()
|
||||
var/turf/turf_loc = get_turf(loc)
|
||||
turf_loc.rust_heretic_act()
|
||||
turfs += turf_loc
|
||||
START_PROCESSING(SSprocessing,src)
|
||||
|
||||
|
||||
/datum/rust_spread/Destroy(force, ...)
|
||||
STOP_PROCESSING(SSprocessing,src)
|
||||
return ..()
|
||||
|
||||
/datum/rust_spread/process()
|
||||
compile_turfs()
|
||||
var/turf/T
|
||||
for(var/i in 0 to spread_per_tick)
|
||||
T = pick(edge_turfs)
|
||||
T.rust_heretic_act()
|
||||
turfs += get_turf(T)
|
||||
|
||||
/**
|
||||
* Compile turfs
|
||||
*
|
||||
* Recreates all edge_turfs as well as normal turfs.
|
||||
*/
|
||||
/datum/rust_spread/proc/compile_turfs()
|
||||
edge_turfs = list()
|
||||
for(var/X in turfs)
|
||||
if(!istype(X,/turf/closed/wall/rust) && !istype(X,/turf/closed/wall/r_wall/rust) && !istype(X,/turf/open/floor/plating/rust))
|
||||
turfs -=X
|
||||
continue
|
||||
for(var/turf/T in range(1,X))
|
||||
if(T in turfs)
|
||||
continue
|
||||
if(is_type_in_typecache(T,blacklisted_turfs))
|
||||
continue
|
||||
edge_turfs += T
|
||||
@@ -28,6 +28,7 @@
|
||||
throwforce = 0
|
||||
blood_volume = 0
|
||||
has_field_of_vision = FALSE //we are a spoopy ghost
|
||||
rad_flags = RAD_NO_CONTAMINATE | RAD_PROTECT_CONTENTS
|
||||
|
||||
see_in_dark = 8
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
icon_state = "daemon"
|
||||
icon_living = "daemon"
|
||||
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
speed = 1
|
||||
a_intent = INTENT_HARM
|
||||
stop_automated_movement = 1
|
||||
|
||||
@@ -161,12 +161,12 @@
|
||||
|
||||
/datum/spellbook_entry/blind
|
||||
name = "Blind"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/trigger/blind
|
||||
spell_type = /obj/effect/proc_holder/spell/pointed/trigger/blind
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/mindswap
|
||||
name = "Mindswap"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer
|
||||
spell_type = /obj/effect/proc_holder/spell/pointed/mind_transfer
|
||||
category = "Mobility"
|
||||
|
||||
/datum/spellbook_entry/forcewall
|
||||
@@ -246,7 +246,7 @@
|
||||
|
||||
/datum/spellbook_entry/barnyard
|
||||
name = "Barnyard Curse"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/barnyardcurse
|
||||
spell_type = /obj/effect/proc_holder/spell/pointed/barnyardcurse
|
||||
|
||||
/datum/spellbook_entry/charge
|
||||
name = "Charge"
|
||||
|
||||
@@ -177,7 +177,7 @@
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall.")
|
||||
if(APPRENTICE_ROBELESS)
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/mind_transfer(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/pointed/mind_transfer(null))
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap.")
|
||||
if(APPRENTICE_MARTIAL)
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/touch/nuclear_fist(null))
|
||||
|
||||
@@ -232,23 +232,6 @@
|
||||
/obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H)
|
||||
return
|
||||
|
||||
|
||||
//procs to handle sprite overlays being applied to humans
|
||||
|
||||
/mob/living/carbon/human/equip_to_slot(obj/item/I, slot)
|
||||
. = ..()
|
||||
if(!. && I && slot && !(slot in GLOB.no_genitals_update_slots)) //the item was successfully equipped, and the chosen slot wasn't merely storage, hands or cuffs.
|
||||
update_genitals()
|
||||
|
||||
/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE)
|
||||
var/no_update = FALSE
|
||||
if(!I || I == l_store || I == r_store || I == s_store || I == handcuffed || I == legcuffed || get_held_index_of_item(I)) //stops storages, cuffs and held items from triggering it.
|
||||
no_update = TRUE
|
||||
. = ..()
|
||||
if(!. || no_update)
|
||||
return
|
||||
update_genitals()
|
||||
|
||||
/mob/living/carbon/human/proc/update_genitals()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
|
||||
@@ -122,6 +122,7 @@ obj/item/dildo/flared/huge
|
||||
name = "literal horse cock"
|
||||
desc = "THIS THING IS HUGE!"
|
||||
dildo_size = 4
|
||||
force = 10
|
||||
|
||||
obj/item/dildo/custom
|
||||
name = "customizable dildo"
|
||||
|
||||
@@ -388,3 +388,9 @@
|
||||
Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal")
|
||||
..()
|
||||
|
||||
/datum/asset/spritesheet/mafia
|
||||
name = "mafia"
|
||||
|
||||
/datum/asset/spritesheet/mafia/register()
|
||||
InsertAll("", 'icons/obj/mafia.dmi')
|
||||
..()
|
||||
|
||||
@@ -310,7 +310,7 @@
|
||||
/datum/export/gear/combatgloves
|
||||
cost = 80
|
||||
unit_name = "combat gloves"
|
||||
export_types = list(/obj/item/clothing/gloves/tackler/combat, /obj/item/clothing/gloves/tackler/dolphin, /obj/item/clothing/gloves/fingerless/pugilist/rapid, /obj/item/clothing/gloves/krav_maga)
|
||||
export_types = list(/obj/item/clothing/gloves/tackler/combat, /obj/item/clothing/gloves/tackler/dolphin, /obj/item/clothing/gloves/krav_maga)
|
||||
include_subtypes = TRUE
|
||||
|
||||
/datum/export/gear/bonegloves
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user