diff --git a/code/__DEFINES/~monkestation/artifact.dm b/code/__DEFINES/~monkestation/artifact.dm
index e4fcd4ff9c4f..8c5ed4744bfa 100644
--- a/code/__DEFINES/~monkestation/artifact.dm
+++ b/code/__DEFINES/~monkestation/artifact.dm
@@ -15,15 +15,19 @@
#define ARTIFACT_UNCOMMON 400
#define ARTIFACT_VERYUNCOMMON 300
#define ARTIFACT_RARE 250
-#define ARTIFACT_VERYRARE 140
+#define ARTIFACT_VERYRARE 125
-//cuts down on boiler plate code
-#define ARTIFACT_SETUP(X,subsystem) ##X/Initialize(mapload, var/forced_origin = null){\
+//cuts down on boiler plate code, last 3 args can be null.
+#define ARTIFACT_SETUP(X,subsystem,forced_origin,forced_effect,forced_size) ##X/Initialize(mapload){\
. = ..();\
START_PROCESSING(subsystem, src);\
if(assoc_comp) {\
- assoc_comp = AddComponent(assoc_comp, forced_origin);\
+ assoc_comp = AddComponent(assoc_comp, forced_origin, forced_effect, forced_size);\
RegisterSignal(src, COMSIG_QDELETING, PROC_REF(on_delete));\
+ if(isitem(src)) {\
+ RegisterSignal(src,COMSIG_ITEM_POST_EQUIPPED,PROC_REF(on_artifact_touched));\
+ RegisterSignal(src,COMSIG_MOB_ITEM_ATTACK,PROC_REF(on_artifact_attack));\
+ }\
}\
} \
##X/proc/on_delete(atom/source){\
@@ -33,17 +37,39 @@
##X/process(){\
assoc_comp?.stimulate_from_turf_heat(get_turf(src));\
if(assoc_comp?.active) {\
- assoc_comp.effect_process();\
+ for(var/datum/artifact_effect/eff in assoc_comp.artifact_effects) {\
+ eff.effect_process();\
+ }\
+ }\
+} \
+##X/proc/on_artifact_touched(obj/item/the_item,mob/toucher,slot){ \
+ SIGNAL_HANDLER; \
+ if(assoc_comp) { \
+ for(var/datum/artifact_effect/eff in assoc_comp.artifact_effects) {\
+ eff.effect_touched(toucher);\
+ }\
+ }\
+}\
+##X/proc/on_artifact_attack(mob/target, mob/user, params){ \
+ SIGNAL_HANDLER; \
+ if(assoc_comp) { \
+ for(var/datum/artifact_effect/eff in assoc_comp.artifact_effects) {\
+ eff.effect_touched(target);\
+ if(prob(10)){ \
+ eff.effect_touched(user);\
+ } \
+ }\
}\
} \
##X/rad_act(intensity){\
assoc_comp?.stimulate_from_rad_act(intensity)\
}
-#define STIMULUS_CARBON_TOUCH (1<<0)
-#define STIMULUS_SILICON_TOUCH (1<<1)
-#define STIMULUS_FORCE (1<<2)
-#define STIMULUS_HEAT (1<<3)
-#define STIMULUS_SHOCK (1<<4)
-#define STIMULUS_RADIATION (1<<5)
-#define STIMULUS_DATA (1<<6)
+
+#define STIMULUS_CARBON_TOUCH (1<<1)
+#define STIMULUS_SILICON_TOUCH (1<<2)
+#define STIMULUS_FORCE (1<<3)
+#define STIMULUS_HEAT (1<<4)
+#define STIMULUS_SHOCK (1<<5)
+#define STIMULUS_RADIATION (1<<6)
+#define STIMULUS_DATA (1<<7)
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index bd68bed5b46c..a42422215636 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -677,11 +677,24 @@
design_ids = list(
"anomaly_neutralizer",
"reactive_armour",
+ //"artifact_heater", //MONKESTATION EDIT REMOVAL
+ //"artifact_xray", //MONKESTATION EDIT REMOVAL
+ )
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
+//MONKEYSTATION ADDITION START
+/datum/techweb_node/artifact
+ id = "artifact_research"
+ display_name = "Artifact Research"
+ description = "Properly concuct research on the various artifacts found around."
+ prereq_ids = list("base")
+ design_ids = list(
"artifact_heater",
"artifact_xray",
+ "disk_artifact",
+ "artifact_wand"
)
- research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
-
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
+//MONKESTATION ADDITION END
/datum/techweb_node/high_efficiency
id = "high_efficiency"
display_name = "High Efficiency Parts"
diff --git a/icons/obj/machines/artifact_machines.dmi b/icons/obj/machines/artifact_machines.dmi
index 004e7539d4e5..8cbd0b5ff0ba 100644
Binary files a/icons/obj/machines/artifact_machines.dmi and b/icons/obj/machines/artifact_machines.dmi differ
diff --git a/monkestation/code/modules/art_sci_overrides/activators/_base.dm b/monkestation/code/modules/art_sci_overrides/activators/_base.dm
index 57c25345fc73..34f1ecd81594 100644
--- a/monkestation/code/modules/art_sci_overrides/activators/_base.dm
+++ b/monkestation/code/modules/art_sci_overrides/activators/_base.dm
@@ -5,12 +5,16 @@
var/required_stimuli = NONE
/// our baseline amount needed to even think about triggering (do this in setup otherwise its gonna be static)
var/base_trigger_amount = 0
- ///the highest number our trigger can be
+ ///the highest number our trigger can be
var/highest_trigger_amount = 0
///the end goal of the amount we need set by setup below
var/amount = 0
///the hint we want to pass into the componenet for when we hit hint triggers
- var/list/hint_texts = list("emits a faint noise..")
+ var/list/hint_texts = list("Emits a faint noise..")
+ ///what it says on inspect when discovered
+ var/discovered_text = "Activated by ... coderbus"
+ ///Research value when discovered
+ var/research_value = 0
/datum/artifact_activator/proc/setup(potency)
amount = round(max(base_trigger_amount, base_trigger_amount + (highest_trigger_amount - base_trigger_amount) * (potency/100)))
diff --git a/monkestation/code/modules/art_sci_overrides/activators/range.dm b/monkestation/code/modules/art_sci_overrides/activators/range.dm
index dd946af80fbe..11a8c7237d48 100644
--- a/monkestation/code/modules/art_sci_overrides/activators/range.dm
+++ b/monkestation/code/modules/art_sci_overrides/activators/range.dm
@@ -3,7 +3,7 @@
/datum/artifact_activator/range
name = "Generic Range Trigger"
- //the upper range of the weapon basically between amount, and upper_range
+
var/upper_range = 0
///Hint range goes like amount - hint_range to upper_range + hint_range
var/hint_range = 0
@@ -12,40 +12,46 @@
/datum/artifact_activator/range/setup(potency)
. = ..()
- upper_range = amount + (hint_range * 2)
/datum/artifact_activator/range/force
name = "Physical Trauma"
required_stimuli = STIMULUS_FORCE
- highest_trigger_amount = 30 //any higher than this and its gonna be practically impossible to trigger
+ highest_trigger_amount = 10 //*meaty thwack* *both chuckle*
hint_prob = 50
- hint_range = 10
- hint_texts = list("you almost want to start hitting things.", "a good whack might fix this.")
+ hint_range = 5
+ hint_texts = list("You almost want to start hitting things.", "A good whack might fix this.")
+ discovered_text = "Activated by Kinetic Energy"
+
+/datum/artifact_activator/range/force/New()
+ base_trigger_amount = rand(2,highest_trigger_amount)
/datum/artifact_activator/range/heat
name = "Heat Sensisty"
required_stimuli = STIMULUS_HEAT
hint_range = 20
- highest_trigger_amount = 15000
- hint_texts = list("it feels like someone messed with the thermostat.", "it feels unpleasent being near")
+ highest_trigger_amount = 750
+ hint_texts = list("It feels like someone messed with the thermostat.", "It feels unpleasent being near")
+ discovered_text = "Activated by Thermal Energy"
/datum/artifact_activator/range/heat/New()
- base_trigger_amount = rand(350, 1000)
+ base_trigger_amount = rand(350, highest_trigger_amount)
/datum/artifact_activator/range/shock
name = "Electrical Charged"
required_stimuli = STIMULUS_SHOCK
- highest_trigger_amount = 10000 // requires atleast t2 parts to trigger a max roll one
+ highest_trigger_amount = 1200
hint_range = 500
- hint_texts = list("you can feel the static in the air", "your hairs stand on their ends")
+ hint_texts = list("You can feel the static in the air", "Your hairs stand on their ends")
+ discovered_text = "Activated by Electrical Energy"
/datum/artifact_activator/range/shock/New()
- base_trigger_amount = rand(400, 1200)
+ base_trigger_amount = rand(400, highest_trigger_amount)
/datum/artifact_activator/range/radiation
name = "Radioactivity"
required_stimuli = STIMULUS_RADIATION
- highest_trigger_amount = 10
+ highest_trigger_amount = 5
hint_range = 2
base_trigger_amount = 1 //x-ray machine goes from 1-10
- hint_texts = list("emits a hum that resembles the Super Matter", "you could swear you saw your bones for a second")
+ hint_texts = list("Emits a hum that resembles the Super Matter", "You could swear you saw your bones for a second")
+ discovered_text = "Activated by Radiation"
diff --git a/monkestation/code/modules/art_sci_overrides/activators/touch.dm b/monkestation/code/modules/art_sci_overrides/activators/touch.dm
index 4cdee177fd24..7d365b6f94b8 100644
--- a/monkestation/code/modules/art_sci_overrides/activators/touch.dm
+++ b/monkestation/code/modules/art_sci_overrides/activators/touch.dm
@@ -8,13 +8,16 @@
name = "Data"
required_stimuli = STIMULUS_DATA
hint_texts = list("It yearns for information")
+ discovered_text = "Activated by Information"
/datum/artifact_activator/touch/carbon
name = "Carbon Touch"
required_stimuli = STIMULUS_CARBON_TOUCH
hint_texts = list("You swear you hear the artifact saying it yearns for flesh.", "One touch couldn't hurt could it?")
+ discovered_text = "Activated by Organic Contact"
/datum/artifact_activator/touch/silicon
name = "Silicon Touch"
required_stimuli = STIMULUS_SILICON_TOUCH
hint_texts = list("It feels like it's malfunctioning")
+ discovered_text = "Activated by Silicon Contact"
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/_base_component.dm b/monkestation/code/modules/art_sci_overrides/artifact_components/_base_component.dm
index 1e0520de7d1d..8ed960ebe0ea 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/_base_component.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_components/_base_component.dm
@@ -1,13 +1,11 @@
#define BASE_MAX_ACTIVATORS 2
+#define BASE_MAX_EFFECTS 2
+#define STIMULI_CD_TIME 5 SECONDS
/datum/component/artifact
dupe_mode = COMPONENT_DUPE_UNIQUE
- ///object related to this datum for spawning
- var/obj/associated_object
- ///actual specific object for this instance
+ //The object we are attached to
var/obj/holder
- ///list weight for picking this artifact datum (0 = never)
- var/weight = 0
///size class for visuals (ARTIFACT_SIZE_TINY,ARTIFACT_SIZE_SMALL,ARTIFACT_SIZE_LARGE)
var/artifact_size = ARTIFACT_SIZE_LARGE
///type name for displaying on analysis forms
@@ -21,7 +19,7 @@
///activators that activate the artifact
var/list/datum/artifact_activator/activators = list()
var/max_activators = BASE_MAX_ACTIVATORS
- ///Valid activators to pick
+ ///Valid activators to pick,mostly legacy code.
var/list/valid_activators = list(
/datum/artifact_activator/touch/carbon,
/datum/artifact_activator/touch/silicon,
@@ -32,71 +30,82 @@
/datum/artifact_activator/range/shock,
/datum/artifact_activator/range/radiation,
)
- ///valid list of faults with their weights [10 is base]
- var/list/valid_faults = list(
- /datum/artifact_fault/ignite = 10,
- /datum/artifact_fault/warp = 10,
- /datum/artifact_fault/reagent/poison = 10,
- /datum/artifact_fault/death = 2,
- /datum/artifact_fault/tesla_zap = 5,
- /datum/artifact_fault/shrink = 10,
- /datum/artifact_fault/explosion = 2,
- )
- ///origin datum
+ ///this artifacts origin
var/datum/artifact_origin/artifact_origin
- ///origin datums to pick
+ ///Just any effect that is real and can be added to an artifact. Mostly legacy
var/list/valid_origins = list(
/datum/artifact_origin/narsie,
/datum/artifact_origin/wizard,
/datum/artifact_origin/silicon,
/datum/artifact_origin/precursor,
- /datum/artifact_origin/martian,
+ /datum/artifact_origin/martian
)
var/activation_message
var/activation_sound
var/deactivation_message
var/deactivation_sound
- var/hint_text = "emits a faint noise.."
- var/examine_hint
var/mutable_appearance/act_effect
- /// Potency in percentage, used for making more strong artifacts need more stimulus. (1% - 100%) 100 is strongest.
- var/potency = 1
+ ///Have we been xray scanned at least once?
+ var/researched = FALSE
- ///structure description from x-ray machines
- var/xray_result = "NONE"
///we store our analysis form var here
var/obj/item/sticker/analysis_form/analysis
var/mutable_appearance/extra_effect
- ///the fault we picked from the listed ones
+ ///the fault we picked from the listed ones. Can be null!
var/datum/artifact_fault/chosen_fault
- ///the amount of freebies we get
+ ///the amount of times an artifact WONT do something bad, even though it should have
var/freebies = 3
///if we have a special examine IE borgers
var/explict_examine
+ ///Fault = weight
+ var/static/list/datum/artifact_fault/fault_weight_list
+
+ ///The activators we have discovered.
+ var/list/datum/artifact_activator/discovered_activators = list()
+ ///Have we discovered what the bad is?
+ var/fault_discovered = FALSE
+ ///A list of effects the artifact has
+ var/list/datum/artifact_effect/artifact_effects = list()
+ ///A list of effects that have been discovered
+ var/list/datum/artifact_effect/discovered_effects = list()
+
+ COOLDOWN_DECLARE(reactivate_cooldown)
-/datum/component/artifact/Initialize(forced_origin = null)
- . = ..()
+/datum/component/artifact/Initialize(forced_origin,forced_effect,forced_size)
if(!isobj(parent))
return COMPONENT_INCOMPATIBLE
holder = parent
GLOB.running_artifact_list[holder] = src
+ if(forced_size != null)
+ artifact_size = forced_size
+
+ if(!length(fault_weight_list))
+ var/list/datum/artifact_fault/valid_faults_pre = typecacheof(/datum/artifact_fault,ignore_root_path = TRUE)
+ var/list/datum/artifact_fault/valid_faults = list()
+ for(var/datum/artifact_fault/fault as anything in valid_faults_pre)
+ valid_faults += fault
+ valid_faults[fault] = fault.weight
+ fault_weight_list = valid_faults
if(forced_origin)
valid_origins = list(forced_origin)
- var/picked_origin = pick(valid_origins)
+ var/datum/artifact_origin/picked_origin = pick(valid_origins)
artifact_origin = new picked_origin
fake_name = "[pick(artifact_origin.name_vars["adjectives"])] [pick(isitem(holder) ? artifact_origin.name_vars["small-nouns"] : artifact_origin.name_vars["large-nouns"])]"
- var/picked_fault = pick_weight(valid_faults)
- chosen_fault = new picked_fault
+ if(prob(95))
+ var/picked_fault = pick_weight(fault_weight_list)
+ chosen_fault = new picked_fault
+ chosen_fault.our_artifact = src
+ chosen_fault.on_added(src)
generated_name = artifact_origin.generate_name()
if(!generated_name)
generated_name = "[pick(artifact_origin.name_vars["adjectives"])] [pick(isitem(holder) ? artifact_origin.name_vars["small-nouns"] : artifact_origin.name_vars["large-nouns"])]"
holder.name = fake_name
- holder.desc = "You have absolutely no clue what this thing is or how it got here."
+ holder.desc = "Some sort of artifact from a time long past."
var/dat_icon
switch(artifact_size)
@@ -124,20 +133,35 @@
activation_sound = pick(artifact_origin.activation_sounds)
if(LAZYLEN(artifact_origin.deactivation_sounds))
deactivation_sound = pick(artifact_origin.deactivation_sounds)
-
+ setup()
var/activator_amount = rand(1,max_activators)
- while(activator_amount>0)
+ for(var/i in 1 to activator_amount)
var/selection = pick(valid_activators)
valid_activators -= selection
- activators += new selection()
- activator_amount--
-
- ADD_TRAIT(holder, TRAIT_HIDDEN_EXPORT_VALUE, INNATE_TRAIT)
- setup()
- potency = clamp(potency, 0, 100)
- for(var/datum/artifact_activator/activator in activators)
+ var/datum/artifact_activator/activator = new selection()
+ activators += activator
+ var/potency = rand(0,100)
activator.setup(potency)
- hint_text = activator.grab_hint()
+ if(forced_effect)
+ var/datum/artifact_effect/added_boogaloo = new forced_effect
+ artifact_effects += added_boogaloo
+ added_boogaloo.our_artifact = src
+ added_boogaloo.setup()
+ if(!length(GLOB.artifact_effect_rarity["all"]))
+ build_weighted_rarities()
+ var/list/datum/artifact_effect/dont_touch = GLOB.artifact_effect_rarity["all"] //Dont touch because below.
+ var/list/datum/artifact_effect/all_possible_effects = dont_touch.Copy() //If you touch it, it actually edits the list, we need a copy. We cant call copy directly because its not a static type list.
+ var/effects_amount = rand(1,BASE_MAX_EFFECTS)
+
+ while(effects_amount > 0)
+ if(effects_amount <= 0)
+ logger.Log(LOG_CATEGORY_ARTIFACT, "[src] has ran out of possible artifact effects! It may not have any at all!")
+ break
+ var/datum/artifact_effect/effect = pick_weight(all_possible_effects)
+ all_possible_effects -= effect
+ if(try_add_effect(effect))
+ effects_amount--
+
/datum/component/artifact/RegisterWithParent()
RegisterSignals(parent, list(COMSIG_ATOM_DESTRUCTION, COMSIG_QDELETING), PROC_REF(on_destroy))
@@ -168,10 +192,122 @@
COMSIG_ATOM_NO_LONGER_PULLED,
COMSIG_ATOM_PULLED,
))
+///This just clears all the effects,activators,and faults of the artifact, so we can add new ones with a proc.
+/datum/component/artifact/proc/clear_out()
+ QDEL_LIST(activators)
+ QDEL_NULL(chosen_fault)
+ QDEL_LIST(artifact_effects)
+ fault_discovered = FALSE
+ discovered_effects = list()
+ return
+///Adds an activator, returns TRUE/FALSE based on success.
+/datum/component/artifact/proc/add_activator(datum/artifact_activator/new_activator,forced_potency = 0)
+ if(!new_activator)
+ return FALSE
+ if(length(activators) >= BASE_MAX_ACTIVATORS)
+ return FALSE
+ var/datum/artifact_activator/created
+ if(ispath(new_activator))
+ created = new new_activator()
+ else
+ created = new new_activator.type
+ activators += created
+ if(forced_potency > 0 )
+ created.setup(forced_potency)
+ else
+ created.setup(rand(1,100))
+ return TRUE
+///changes the fault of the artifact, returns TRUE/FALSE based on success.
+/datum/component/artifact/proc/change_fault(datum/artifact_fault/new_fault)
+ if(new_fault)
+ return force_replace_fault(new_fault.type)
+ else
+ qdel(chosen_fault)
+ chosen_fault = new new_fault
+ return TRUE
+
+/*
+* Long function, but basically:
+* For given effect:
+* If it has valid types, check to make sure its of the right type path. So you cant roll something that requires a structure on an item.
+* If it has valid origins, and the artifact isnt that origin, return FALSE.
+* If it has valid activators, and the artifact has none of them, return FALSE.
+* If it has a valid size, and the artifact isnt that size, return FALSE.
+* Then, if all is well, slam it on the artifact, call setup() on the effect, return TRUE
+*/
+/datum/component/artifact/proc/try_add_effect(datum/artifact_effect/effect)
+ var/datum/artifact_effect/added
+ if(ispath(effect))
+ added = new effect //We need it now, becasue for some reason we cant read the lists from just the raw datum.
+ else
+ added = new effect.type //Skip the checks, just add it.
+ artifact_effects += added
+ added.our_artifact = src
+ added.setup()
+ return TRUE
+ if(length(added.valid_type_paths))
+ var/bad_path = FALSE
+ for(var/path in added.valid_type_paths)
+ if(!istype(holder,path))
+ bad_path = TRUE
+ break
+ if(bad_path)
+ QDEL_NULL(added)
+ return FALSE
+ if(length(added.valid_origins))
+ if(!(artifact_origin.type_name in added.valid_origins))
+ QDEL_NULL(added)
+ return FALSE
+ if(length(added.valid_activators))
+ var/good_activators = FALSE
+ for(var/datum/artifact_activator/activator as anything in activators) //Only need one to be correct.
+ if(activator.type in added.valid_activators)
+ good_activators = TRUE
+ break
+ if(!good_activators)
+ QDEL_NULL(added)
+ return FALSE
+ if(added.artifact_size)
+ if(artifact_size != added.artifact_size)
+ QDEL_NULL(added)
+ return FALSE
+ artifact_effects += added
+ added.our_artifact = src
+ added.setup()
+ return TRUE
+///Kinda a legacy proc, but if you need something super special I guess.
/datum/component/artifact/proc/setup()
return
+///Replaces the fault on the artifact with a new one.
+/datum/component/artifact/proc/force_replace_fault(new_fault)
+ if(new_fault)
+ qdel(chosen_fault)
+ if(ispath(new_fault))
+ chosen_fault = new new_fault
+ chosen_fault.our_artifact = src
+ chosen_fault.on_added(src)
+ else
+ chosen_fault = new_fault
+ chosen_fault.our_artifact = src
+ chosen_fault.on_added(src)
+ return TRUE
+ return FALSE
+
+///Adds a new artifact effect to the artifact. Ignores all normal checks. Admin Proc. Not called.
+/datum/component/artifact/proc/force_add_effect(new_effect_path,effect_power = null)
+ if(new_effect_path && ispath(new_effect_path,/datum/artifact_effect))
+ var/datum/artifact_effect/added_boogaloo = new new_effect_path
+ artifact_effects += added_boogaloo
+ added_boogaloo.our_artifact = src
+ if(effect_power)
+ added_boogaloo.potency = effect_power
+ added_boogaloo.setup()
+ return TRUE
+ return FALSE
+
+///Activates the artifact.
/datum/component/artifact/proc/artifact_activate(silent)
if(active) //dont activate activated objects
return FALSE
@@ -183,10 +319,12 @@
active = TRUE
holder.add_overlay(act_effect)
logger.Log(LOG_CATEGORY_ARTIFACT, "[parent] has been activated")
- effect_activate(silent)
+ for(var/datum/artifact_effect/effect in artifact_effects)
+ effect.effect_activate(silent)
return TRUE
-/datum/component/artifact/proc/artifact_deactivate(silent)
+///The opposite of activates the artifact
+/datum/component/artifact/proc/artifact_deactivate(silent = FALSE)
if(!active)
return
if(deactivation_sound && !silent)
@@ -196,14 +334,22 @@
active = FALSE
holder.cut_overlay(act_effect)
logger.Log(LOG_CATEGORY_ARTIFACT, "[parent] has been deactivated")
- effect_deactivate(silent)
+ for(var/datum/artifact_effect/effect in artifact_effects)
+ effect.effect_deactivate(silent)
+/datum/component/artifact/effect_touched(mob/living/user)
+ for(var/datum/artifact_effect/effect in artifact_effects)
+ effect.effect_touched(user)
+ return
+
+///Called when the artifact gets something that may activate it. Skips re-activation of artifacts, but passes their triggers to faults.
/datum/component/artifact/proc/process_stimuli(stimuli, stimuli_value, triggers_faults = TRUE)
- if(!stimuli || active) // if called without a stimuli dont bother, if active we dont wanna reactivate
+ if(!stimuli)
return
var/checked_fault = FALSE
+ var/correct_trigger = FALSE
for(var/datum/artifact_activator/listed_activator in activators)
- if(!(listed_activator.required_stimuli & stimuli))
+ if(!(listed_activator.required_stimuli & stimuli) && chosen_fault)
if(!triggers_faults)
continue
if(freebies >= 1)
@@ -219,17 +365,16 @@
holder.visible_message("[holder] [chosen_fault.visible_message]")
continue
checked_fault = TRUE
- if(istype(listed_activator, /datum/artifact_activator/range))
- var/datum/artifact_activator/range/ranged_activator = listed_activator
- //if we fail the range check check if we are in hint range to send out the hint
- if(!ISINRANGE(stimuli_value, ranged_activator.amount, ranged_activator.upper_range))
- if(hint_text && !ISINRANGE(stimuli_value, ranged_activator.amount - ranged_activator.hint_range, ranged_activator.upper_range + ranged_activator.hint_range))
- continue
- if(!prob(ranged_activator.hint_prob))
- continue
- holder.visible_message(span_notice("[hint_text]"))
+ if((listed_activator.required_stimuli & stimuli) && istype(listed_activator, /datum/artifact_activator/range))
+ if(stimuli_value < listed_activator.amount)
continue
+ correct_trigger = TRUE
+ break
+ if(active || !correct_trigger)
+ return
+ if(COOLDOWN_FINISHED(src,reactivate_cooldown))
artifact_activate()
+ COOLDOWN_START(src,reactivate_cooldown,STIMULI_CD_TIME)
/datum/component/artifact/proc/stimulate_from_turf_heat(turf/target)
if(!QDELETED(target))
@@ -239,3 +384,5 @@
process_stimuli(STIMULUS_RADIATION, intensity)
#undef BASE_MAX_ACTIVATORS
+#undef BASE_MAX_EFFECTS
+#undef STIMULI_CD_TIME
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/_base_component_signal_procs.dm b/monkestation/code/modules/art_sci_overrides/artifact_components/_base_component_signal_procs.dm
index 03874852ae2a..9b89fd631f0f 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/_base_component_signal_procs.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_components/_base_component_signal_procs.dm
@@ -4,15 +4,29 @@
if(!QDELETED(holder))
holder.loc.visible_message(span_warning("[holder] [artifact_origin.destroy_message]"))
artifact_deactivate(TRUE)
+ for(var/datum/artifact_effect/effect in artifact_effects)
+ effect.on_destroy(source)
if(!QDELETED(holder))
qdel(holder)
/datum/component/artifact/proc/on_examine(atom/source, mob/user, list/examine_list)
SIGNAL_HANDLER
- if(examine_hint)
- examine_list += examine_hint
if(explict_examine)
examine_list += explict_examine
+ for(var/datum/artifact_effect/effect in artifact_effects)
+ if(discovered_effects.Find(effect.type) && effect.examine_discovered)
+ examine_list += span_info(effect.examine_discovered)
+ else if (effect.examine_hint)
+ examine_list += span_info(effect.examine_hint)
+
+ for(var/datum/artifact_activator/act in activators)
+ if(discovered_activators.Find(act.type) && act.discovered_text)
+ examine_list += span_info(act.discovered_text)
+ else if(length(act.hint_texts))
+ examine_list += span_info(pick(act.hint_texts))
+
+ if(chosen_fault && chosen_fault.inspect_warning)
+ examine_list += span_warning(pick(chosen_fault.inspect_warning))
/datum/component/artifact/proc/on_sticker(atom/source, obj/item/sticker/sticker, mob/user)
SIGNAL_HANDLER
@@ -75,7 +89,8 @@
logger.Log(LOG_CATEGORY_ARTIFACT, "[user] has touched [parent]")
if(active)
- effect_touched(user)
+ for(var/datum/artifact_effect/effect in artifact_effects)
+ effect.effect_touched(user)
return
if(LAZYLEN(artifact_origin.touch_descriptors))
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), user, span_notice("[pick(artifact_origin.touch_descriptors)]")), 0.5 SECONDS)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/bomb.dm b/monkestation/code/modules/art_sci_overrides/artifact_components/bomb.dm
deleted file mode 100644
index 476af7185a04..000000000000
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/bomb.dm
+++ /dev/null
@@ -1,152 +0,0 @@
-/datum/component/artifact/bomb
- examine_hint = span_warning("It is covered in very conspicuous markings.")
- valid_activators = list(
- /datum/artifact_activator/range/force,
- /datum/artifact_activator/range/heat,
- /datum/artifact_activator/range/shock,
- /datum/artifact_activator/range/radiation
- )
- deactivation_message = "sputters a bit, and falls silent once more."
- xray_result = "COMPLEX"
- var/dud = FALSE
- var/dud_message = "sputters, failing to activate! Its a dud!"
- var/initial_warning = "begins overloading, rattling violenty!"
- var/explode_delay = 1 MINUTES // also delayed by finale_delay for fluff
- var/explode_cooldown_time = 1 MINUTES
- var/finale_delay = 6 SECONDS //delay before we actually deliver the payload for fluff
- var/final_message = "reaches a catastrophic overload, cracks forming at its surface!"
- var/sound/active_alarm = 'sound/effects/alert.ogg' // plays every alarm_cooldown_time when active
- var/alarm_cooldown_time = 3 SECONDS
- var/sound/final_sound = 'sound/misc/bloblarm.ogg'
- COOLDOWN_DECLARE(activation_cooldown)
- COOLDOWN_DECLARE(alarm_cooldown)
- var/timer_id
- var/do_alert = FALSE //do we send an announcement on activation
-
-/datum/component/artifact/bomb/setup()
- if(prob(20))
- dud = TRUE
-
-/datum/component/artifact/bomb/effect_activate()
- if(!COOLDOWN_FINISHED(src,explode_cooldown_time))
- holder.visible_message(span_warning("[holder] [deactivation_message]")) //rekt
- addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/component/artifact, artifact_deactivate)), 1 SECONDS)
- return
- holder.visible_message(span_bolddanger("[holder] [initial_warning]"))
- COOLDOWN_START(src,activation_cooldown,explode_cooldown_time)
- timer_id = addtimer(CALLBACK(src, PROC_REF(finale)), explode_delay, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE)
- if(do_alert && is_station_level(holder.z))
- priority_announce("A highly unstable object of type [type_name] has been activated at [get_area(holder)]. It has been marked on GPS, The crew is advised to get rid of it IMMEDIATELY.", null, SSstation.announcer.get_rand_report_sound(), has_important_message = TRUE)
- holder.AddComponent(/datum/component/gps, "Unstable Object")
-
-/datum/component/artifact/bomb/effect_deactivate()
- deltimer(timer_id)
-
-/datum/component/artifact/bomb/effect_process()
- . = ..()
- if(active && COOLDOWN_FINISHED(src,alarm_cooldown) && (COOLDOWN_TIMELEFT(src,alarm_cooldown) <= finale_delay))
- playsound(holder, active_alarm, 30, 1)
- holder.Shake(duration = 1 SECONDS, shake_interval = 0.08 SECONDS)
- COOLDOWN_START(src,alarm_cooldown, alarm_cooldown_time)
-
-/datum/component/artifact/bomb/proc/finale()
- if(final_sound)
- playsound(holder.loc, final_sound, 100, 1, -1)
- if(finale_delay)
- holder.visible_message(span_bolddanger("[holder] [final_message]"))
- addtimer(CALLBACK(src, PROC_REF(payload)), finale_delay)
- else
- payload()
-
-/datum/component/artifact/bomb/on_destroy(/datum/source)
- . = ..()
- if(active)
- payload()
- deltimer(timer_id)
-
-/datum/component/artifact/bomb/proc/payload()
- . = TRUE
- if(dud || !active)
- holder.visible_message(span_notice("[holder] [dud_message]"))
- artifact_deactivate(TRUE)
- return FALSE
-
-/// EXPLOSIVE BOMB
-
-/datum/component/artifact/bomb/explosive
- associated_object = /obj/structure/artifact/bomb
- type_name = "Bomb (explosive)"
- weight = ARTIFACT_RARE
- var/devast
- var/heavy
- var/light
-
-/datum/component/artifact/bomb/explosive/New()
- . = ..()
- devast = rand(1,3)
- heavy = rand(2,4)
- light = rand(3,10)
- potency = (light + heavy + devast) * 2
-
-/datum/component/artifact/bomb/explosive/payload()
- if(!..())
- return FALSE
- explosion(holder, devast,heavy,light,light*1.5)
- on_destroy()
-
-/// DEVESTATING BOMB
-
-/datum/component/artifact/bomb/explosive/devastating
- associated_object = /obj/structure/artifact/bomb/devastating
- type_name = "Bomb (explosive, devastating)"
- do_alert = TRUE
- weight = ARTIFACT_VERYRARE
- xray_result = "DENSE"
- explode_delay = 2 MINUTES
-
-/datum/component/artifact/bomb/explosive/devastating/New()
- ..()
- devast = rand(3,7)
- heavy = rand(7,12)
- light = rand(10,25)
- potency = (devast + heavy + light) * 2.25 // get real
-
-/// GAS BOMB
-
-/datum/component/artifact/bomb/gas
- associated_object = /obj/structure/artifact/bomb/gas
- type_name = "Bomb (gas)"
- weight = ARTIFACT_RARE
- xray_result = "POROUS"
- initial_warning = "begins rattling violenty!"
- final_message = "reaches a critical pressure, cracks forming at its surface!"
- var/datum/gas/payload_gas
- var/list/weighted_gas = list(
- /datum/gas/plasma = 5,
- /datum/gas/carbon_dioxide = 10,
- /datum/gas/nitrous_oxide = 10,
- /datum/gas/tritium = 5,
- /datum/gas/hydrogen = 5,
- /datum/gas/zauker = 2,
- )
-
-/datum/component/artifact/bomb/gas/setup()
- . = ..()
- payload_gas = pick_weight(weighted_gas)
-
-/datum/component/artifact/bomb/gas/payload()
- if(!..())
- artifact_deactivate()
- return FALSE
- var/turf/open/O = get_turf(holder)
- if(!isopenturf(O))
- artifact_deactivate()
- return FALSE
- var/datum/gas_mixture/merger = new
- merger.assert_gas(payload_gas)
- merger.assert_gas(/datum/gas/oxygen)
- merger.gases[payload_gas][MOLES] = rand(150,2000)
- merger.gases[/datum/gas/oxygen][MOLES] = 350
- merger.temperature = rand(200,3000)
- O.assume_air(merger)
- qdel(holder)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/bonk.dm b/monkestation/code/modules/art_sci_overrides/artifact_components/bonk.dm
deleted file mode 100644
index 39b6136e894d..000000000000
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/bonk.dm
+++ /dev/null
@@ -1,38 +0,0 @@
-/datum/component/artifact/bonk
- associated_object = /obj/structure/artifact/bonk
- weight = ARTIFACT_UNCOMMON
- type_name = "Slammer"
- activation_message = "opens up!"
- deactivation_message = "closes up."
- valid_activators = list(
- /datum/artifact_activator/touch/carbon,
- /datum/artifact_activator/touch/silicon
- )
- ///force of the hit
- var/hit_power = 1
- COOLDOWN_DECLARE(bonk_cooldown)
-
-/datum/component/artifact/bonk/setup()
- hit_power = rand(0,35)
- potency += hit_power
-
-/datum/component/artifact/bonk/effect_touched(mob/living/user)
- if(!COOLDOWN_FINISHED(src, bonk_cooldown))
- return
-
- if(iscarbon(user))
- var/mob/living/carbon/carbon = user
- if(!carbon.get_bodypart(BODY_ZONE_HEAD))
- holder.say("My condolences to your missing head.") //they can speak uhh galactic common because alien tech idk
- holder.visible_message(span_notice("[holder] shakes [user][p_s()] hands with an apparatus."))
- playsound(get_turf(holder), 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
- artifact_deactivate()
- return
- else
- carbon.apply_damage(hit_power, BRUTE, BODY_ZONE_HEAD, carbon.run_armor_check(BODY_ZONE_HEAD, MELEE))
- holder.visible_message(span_danger("[holder] hits [carbon] over the head!"))
- else
- holder.visible_message(span_danger("[holder] slams [user]!"))
- user.adjustBruteLoss(hit_power)
- playsound(get_turf(holder), 'sound/misc/bonk.ogg', 80, FALSE)
- COOLDOWN_START(src, bonk_cooldown, 1.5 SECONDS)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/cell.dm b/monkestation/code/modules/art_sci_overrides/artifact_components/cell.dm
deleted file mode 100644
index 2c3ee53a1886..000000000000
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/cell.dm
+++ /dev/null
@@ -1,37 +0,0 @@
-/datum/component/artifact/cell
- associated_object = /obj/item/stock_parts/cell/artifact
- artifact_size = ARTIFACT_SIZE_TINY
- type_name = "Power Cell"
- weight = ARTIFACT_UNCOMMON
- xray_result = "SEGMENTED"
- valid_activators = list(
- /datum/artifact_activator/range/heat,
- /datum/artifact_activator/range/shock,
- /datum/artifact_activator/range/radiation
- )
- valid_faults = list(
- /datum/artifact_fault/ignite = 10,
- /datum/artifact_fault/warp = 10,
- /datum/artifact_fault/reagent/poison = 10,
- /datum/artifact_fault/death = 2,
- /datum/artifact_fault/tesla_zap = 5,
- /datum/artifact_fault/grow = 10,
- /datum/artifact_fault/explosion = 2,
- )
-
-/datum/component/artifact/cell/setup()
- var/obj/item/stock_parts/cell/artifact/cell = holder
- cell.corrupted = prob(10) //trolled
- cell.maxcharge = rand(5 KW, 500 MW) // the heavenly battery
- cell.charge = cell.maxcharge / 2
- cell.chargerate = rand(5000, round(cell.maxcharge * 0.4))
- potency += cell.maxcharge / 900
- potency += cell.chargerate / 4000
-
-/datum/component/artifact/cell/effect_activate()
- var/obj/item/stock_parts/cell/artifact/cell = holder
- cell.ratingdesc = TRUE
-
-/datum/component/artifact/cell/effect_deactivate()
- var/obj/item/stock_parts/cell/artifact/cell = holder
- cell.ratingdesc = FALSE
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/ghost_object.dm b/monkestation/code/modules/art_sci_overrides/artifact_components/ghost_object.dm
new file mode 100644
index 000000000000..38c66f0e7863
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_components/ghost_object.dm
@@ -0,0 +1,118 @@
+///This is straight up an object version of the spirit plade one
+/datum/component/ghost_object_control
+ var/attempting_awakening = FALSE
+ ///mob contained in the item,null untill controlled!
+ var/mob/living/basic/shade/bound_spirit
+ ///do we make a callback to retry untill someone posesses it?
+ var/repolling= FALSE
+ ///How often can this thing move in seconds
+ var/speed= 1.25
+ COOLDOWN_DECLARE(move_cooldown)
+/datum/component/ghost_object_control/Initialize(repoll = FALSE,move_speed = null)
+ if(!ismovable(parent)) //you may apply this to mobs, I take no responsibility for how that works out
+ return COMPONENT_INCOMPATIBLE
+ if(move_speed)
+ speed = move_speed
+
+/datum/component/ghost_object_control/Destroy(force, silent)
+ . = ..()
+ if(bound_spirit)
+ QDEL_NULL(bound_spirit)
+
+/datum/component/ghost_object_control/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
+ RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(on_destroy))
+ RegisterSignal(parent, COMSIG_ATOM_RELAYMOVE, TYPE_PROC_REF(/datum/component/ghost_object_control,move_host))
+ //RegisterSignal(parent, COMSIG_RIDDEN_DRIVER_MOVE, TYPE_PROC_REF(/datum/component/ghost_object_control,move_host))
+
+/datum/component/ghost_object_control/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_ATOM_EXAMINE, COMSIG_QDELETING, COMSIG_ATOM_RELAYMOVE))
+
+///Moves the object. Yippee!
+/datum/component/ghost_object_control/proc/move_host(atom/movable/movable_parent,mob/buckled_mob,dir_to_move)
+ SIGNAL_HANDLER
+
+ if(!COOLDOWN_FINISHED(src, move_cooldown))
+ return COMSIG_BLOCK_RELAYMOVE
+ var/turf/next = get_step(movable_parent, dir_to_move)
+ var/turf/current = get_turf(movable_parent)
+ if(!istype(next) || !istype(current))
+ return COMSIG_BLOCK_RELAYMOVE
+ if(next.density)
+ return COMSIG_BLOCK_RELAYMOVE
+ if(!isturf(movable_parent.loc))
+ return COMSIG_BLOCK_RELAYMOVE
+
+ step(movable_parent, dir_to_move)
+ var/last_move_diagonal = ((dir_to_move & (dir_to_move - 1)) && (movable_parent.loc == next))
+ COOLDOWN_START(src, move_cooldown, ((last_move_diagonal ? 2 : 1) * speed) SECOND)
+
+ if(QDELETED(src))
+ return COMSIG_BLOCK_RELAYMOVE
+ return TRUE
+
+///signal fired on examining the parent
+/datum/component/ghost_object_control/proc/on_examine(datum/source, mob/user, list/examine_list)
+ SIGNAL_HANDLER
+ if(!bound_spirit)
+ return
+ examine_list += span_notice("[parent] is moving somehow?")
+
+///Call to poll for ghost role
+/datum/component/ghost_object_control/proc/request_control(movement_speed)
+ if(attempting_awakening)
+ return
+ if(!(GLOB.ghost_role_flags & GHOSTROLE_STATION_SENTIENCE))
+ return
+
+ attempting_awakening = TRUE
+
+ var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates(
+ "Do you want to play as [parent]?",
+ check_jobban = ROLE_SENTIENCE,
+ poll_time = 10 SECONDS,
+ ignore_category = POLL_IGNORE_SENTIENCE_POTION,
+ alert_pic = parent,
+ role_name_text = "[parent]",
+ )
+ if(!LAZYLEN(candidates))
+ if(repolling)
+ addtimer(CALLBACK(src,PROC_REF(request_control),2.5 MINUTE))
+ attempting_awakening = FALSE
+ return
+
+ var/mob/dead/observer/chosen_spirit = pick(candidates)
+ bound_spirit = new(parent)
+ bound_spirit.ckey = chosen_spirit.ckey
+ bound_spirit.fully_replace_character_name(null, "[parent]")
+ bound_spirit.status_flags |= GODMODE
+ bound_spirit.grant_all_languages(FALSE, FALSE, TRUE) //Grants omnitongue
+ bound_spirit.update_atom_languages()
+ speed = movement_speed
+
+ //Add new signals for parent and stop attempting to awaken
+
+ // Now that all of the important things are in place for our spirit, it's time for them to choose their name.
+ var/valid_input_name = custom_name(bound_spirit)
+ if(valid_input_name)
+ bound_spirit.fully_replace_character_name(null, "[valid_input_name]")
+
+ attempting_awakening = FALSE
+
+/**
+ * custom_name : Simply sends a tgui input text box to the blade asking what name they want to be called, and retries it if the input is invalid.
+ *
+ * Arguments:
+ * * awakener: user who interacted with the blade
+ */
+/datum/component/ghost_object_control/proc/custom_name(mob/subject)
+ var/chosen_name = sanitize_name(tgui_input_text(bound_spirit, "What are you named?", "Spectral Nomenclature", max_length = MAX_NAME_LEN))
+ if(!chosen_name) // with the way that sanitize_name works, it'll actually send the error message to the awakener as well.
+ return custom_name(subject) //YOU WILL PICK A NAME.
+ return chosen_name
+
+///signal fired from parent being destroyed
+/datum/component/ghost_object_control/proc/on_destroy(datum/source)
+ SIGNAL_HANDLER
+ to_chat(bound_spirit, span_userdanger("You were destroyed!"))
+ QDEL_NULL(bound_spirit)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/lamp.dm b/monkestation/code/modules/art_sci_overrides/artifact_components/lamp.dm
deleted file mode 100644
index c62124f20c62..000000000000
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/lamp.dm
+++ /dev/null
@@ -1,34 +0,0 @@
-
-/datum/component/artifact/lamp
- associated_object = /obj/structure/artifact/lamp
- weight = ARTIFACT_COMMON
- type_name = "Lamp"
- activation_message = "starts shining!"
- deactivation_message = "stops shining."
-
-/datum/component/artifact/lamp/setup()
- var/power
- var/color = pick(COLOR_RED, COLOR_BLUE, COLOR_YELLOW, COLOR_GREEN, COLOR_PURPLE, COLOR_ORANGE)
- var/range
- switch(rand(1,100))
- if(1 to 75)
- power = rand(2,5)
- range = rand(2,5)
- if(76 to 100)
- range = rand(4,10)
- power = rand(2,10) // the sun
-
- if(artifact_origin.type_name == ORIGIN_NARSIE && prob(40))
- color = COLOR_BLACK
- holder.set_light_range_power_color(range, power, color)
- potency += (range + power) * 2
-
-/datum/component/artifact/lamp/effect_touched(mob/user)
- holder.set_light_on(!holder.light_on) //toggle
- to_chat(user, span_hear("[holder] clicks."))
-
-/datum/component/artifact/lamp/effect_activate()
- holder.set_light_on(TRUE)
-
-/datum/component/artifact/lamp/effect_deactivate()
- holder.set_light_on(FALSE)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/repulsor.dm b/monkestation/code/modules/art_sci_overrides/artifact_components/repulsor.dm
deleted file mode 100644
index 412b52123822..000000000000
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/repulsor.dm
+++ /dev/null
@@ -1,59 +0,0 @@
-
-/datum/component/artifact/repulsor
- associated_object = /obj/structure/artifact/repulsor
- weight = ARTIFACT_COMMON
- type_name = "Repulsor/Impulsor"
- activation_message = "opens up, a weird aura starts emitting from it!"
- deactivation_message = "closes up."
- xray_result = "SEGMENTED"
- var/attract = FALSE //if FALSE, repulse, otherwise, attract
- var/strength
- var/range
- var/cooldown_time
- COOLDOWN_DECLARE(cooldown)
-
-/datum/component/artifact/repulsor/setup()
- attract = prob(40)
- range = rand(1,3)
- cooldown_time = rand(3,5) SECONDS
- strength = rand(MOVE_FORCE_DEFAULT,MOVE_FORCE_OVERPOWERING)
- potency += cooldown_time / 4 + strength / 3000
- addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/component/artifact, artifact_deactivate)), round(20 * (potency * 10) SECONDS))
-
-/datum/component/artifact/repulsor/effect_touched(mob/user)
- if(!COOLDOWN_FINISHED(src,cooldown))
- return
- pulse()
- COOLDOWN_START(src,cooldown,cooldown_time)
-
-/datum/component/artifact/repulsor/effect_process()
- . = ..()
- if(prob(100 - potency))
- return
- pulse()
-
-/datum/component/artifact/repulsor/RegisterWithParent()
- . = ..()
- RegisterSignal(parent, COMSIG_ATOM_HITBY, PROC_REF(pulse))
-
-/datum/component/artifact/repulsor/UnregisterFromParent()
- . = ..()
- UnregisterSignal(parent, COMSIG_ATOM_HITBY)
-
-/datum/component/artifact/repulsor/proc/pulse(datum/source,atom/movable/thrown, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
- SIGNAL_HANDLER
- if(!active)
- return
- holder.visible_message(span_warning("[holder] emits a pulse of energy, throwing things [attract ? "towards it!" : "away from it!"]"))
- var/owner_turf = get_turf(holder)
- if(isnull(thrown))
- for(var/atom/movable/throwee in oview(range,holder))
- if(throwee.anchored)
- continue
- if(attract)
- throwee.safe_throw_at(holder, strength / 3000, 1, force = strength)
- else
- var/throwtarget = get_edge_target_turf(get_turf(throwee), get_dir(owner_turf, get_step_away(throwee, owner_turf)))
- throwee.safe_throw_at(throwtarget, strength / 3000, 1, force = strength)
- else if(throwingdatum?.thrower)
- thrown.safe_throw_at(throwingdatum.thrower, get_dist(holder, throwingdatum.thrower), 1, force = strength)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/_artifact_effect.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/_artifact_effect.dm
new file mode 100644
index 000000000000..cc94aacc97c6
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/_artifact_effect.dm
@@ -0,0 +1,69 @@
+/datum/artifact_effect
+ ///string added to artifact desc, if not discovered.
+ var/examine_hint
+ ///string added to artifact desc, if the effect has been discovered
+ var/examine_discovered
+ ///When you discover this, how many credits does it add to the sell price?
+ var/discovered_credits = CARGO_CRATE_VALUE*0.75
+ ///how likely is it that this effect is added to an artifact?
+ var/weight = ARTIFACT_COMMON
+ ///if defined, artifact must be this size to roll
+ var/artifact_size
+ ///how strong is this effect,1-100
+ var/potency
+ ///If the artifact doesnt have the right activator, cant be put on. If null, assume any.
+ var/list/valid_activators
+ ///If the artifact doesnt have this origin, cant be put on. If null, assume any.
+ var/list/valid_origins
+ ///sent on activation
+ var/activation_message
+ ///played on activation
+ var/activation_sound
+ ///sent on deactivation
+ var/deactivation_message
+ ///played on deactivation
+ var/deactivation_sound
+ ///list of paths the artifacts holder is allowed to be, if null, may be on any artifact datum holder.
+ var/list/valid_type_paths
+ ///Does this show up on the artifact fourm?
+ var/super_secret = FALSE
+
+ ///Research value when discovered For reference,5000 is one node
+ var/research_value = 100
+ ///The artifact we're on.
+ var/datum/component/artifact/our_artifact
+ ///Type of effect, shows up in Xray Machine
+ var/type_name = "Generic Artifact Effect"
+
+/datum/artifact_effect/New()
+ . = ..()
+ potency = rand(1,100)
+
+
+///Called when the artifact has been created
+/datum/artifact_effect/proc/setup()
+ return
+///Called when the artifact has been activated
+/datum/artifact_effect/proc/effect_activate(silent)
+ return
+///Called when the artifact has been de-activated
+/datum/artifact_effect/proc/effect_deactivate(silent)
+ return
+///Called when the artifact has been touched by a living mob,does NOT call faults or activate artifact unless it has the correct touch component!
+/datum/artifact_effect/proc/effect_touched(mob/living/user)
+ return
+///Called on process() IF the artifact is active.
+/datum/artifact_effect/proc/effect_process()
+ return
+///Called when the artifact/effect is destroyed is destroyed
+/datum/artifact_effect/proc/on_destroy(atom/source)
+ return
+///Util, can be called to activate, then de-activate the artifact as a whole swiftly. Wont Re activate already active artifacts.
+/datum/artifact_effect/proc/flick_active(silent)
+ if(!our_artifact.active)
+ our_artifact.artifact_activate(silent)
+ our_artifact.artifact_deactivate(silent)
+ return
+///Util, can be called to swap the artifacts active status quickly.
+/datum/artifact_effect/proc/toggle_active(silent)
+ our_artifact.active ? our_artifact.artifact_deactivate(silent) : our_artifact.artifact_activate(silent)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/bomb.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/bomb.dm
new file mode 100644
index 000000000000..56ec1504836b
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/bomb.dm
@@ -0,0 +1,155 @@
+/datum/artifact_effect/bomb
+ examine_hint = span_warning("It is covered in very conspicuous markings.")
+ valid_activators = list(
+ /datum/artifact_activator/range/force,
+ /datum/artifact_activator/range/heat,
+ /datum/artifact_activator/range/shock,
+ /datum/artifact_activator/range/radiation
+ )
+ research_value = 1000
+
+ type_name = "Explosive Effect"
+ examine_discovered = span_warning("It appears to explode.")
+
+
+ var/dud = FALSE
+ var/dud_message = "sputters, failing to activate! Its a dud!"
+ var/initial_warning = "begins overloading, rattling violenty!"
+ var/explode_delay = 1 MINUTES // also delayed by finale_delay for fluff
+ var/explode_cooldown_time = 1 MINUTES
+ var/finale_delay = 6 SECONDS //delay before we actually deliver the payload for fluff
+ var/final_message = "reaches a catastrophic overload, cracks forming at its surface!"
+ var/sound/active_alarm = 'sound/effects/alert.ogg' // plays every alarm_cooldown_time when active
+ var/alarm_cooldown_time = 3 SECONDS
+ var/sound/final_sound = 'sound/misc/bloblarm.ogg'
+ COOLDOWN_DECLARE(activation_cooldown)
+ COOLDOWN_DECLARE(alarm_cooldown)
+ var/timer_id
+ var/do_alert = FALSE //do we send an announcement on activation
+
+/datum/artifact_effect/bomb/setup()
+ if(prob(20))
+ dud = TRUE
+
+/datum/artifact_effect/bomb/effect_activate()
+ if(!our_artifact || !our_artifact.holder)
+ return
+ if(!COOLDOWN_FINISHED(src,activation_cooldown))
+ our_artifact.holder.visible_message(span_warning("[our_artifact.holder] [deactivation_message]")) //rekt
+ addtimer(CALLBACK(src.our_artifact, TYPE_PROC_REF(/datum/component/artifact, artifact_deactivate)), 1 SECONDS)
+ return
+ our_artifact.holder.visible_message(span_bolddanger("[our_artifact.holder] [initial_warning]"))
+ COOLDOWN_START(src,activation_cooldown,explode_cooldown_time)
+ timer_id = addtimer(CALLBACK(src, PROC_REF(finale)), explode_delay, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE)
+ if(do_alert && is_station_level(our_artifact.holder.z))
+ priority_announce("A highly unstable object has been activated at [get_area(our_artifact.holder)]. It has been marked on GPS, The crew is advised to get rid of it IMMEDIATELY.", null, SSstation.announcer.get_rand_report_sound(), has_important_message = TRUE)
+ our_artifact.holder.AddComponent(/datum/component/gps, "Unstable Object")
+
+/datum/artifact_effect/bomb/effect_deactivate()
+ deltimer(timer_id)
+
+/datum/artifact_effect/bomb/effect_process()
+ . = ..()
+ if(our_artifact.active && (COOLDOWN_FINISHED(src,alarm_cooldown) || (COOLDOWN_TIMELEFT(src,alarm_cooldown) <= finale_delay)))
+ playsound(our_artifact, active_alarm, 30, 1)
+ our_artifact.holder.Shake(duration = 1 SECONDS, shake_interval = 0.08 SECONDS)
+ COOLDOWN_START(src,alarm_cooldown, alarm_cooldown_time)
+
+/datum/artifact_effect/bomb/proc/finale()
+ if(final_sound)
+ playsound(our_artifact.holder.loc, final_sound, 100, 1, -1)
+ if(finale_delay)
+ our_artifact.holder.visible_message(span_bolddanger("[our_artifact.holder] [final_message]"))
+ addtimer(CALLBACK(src, PROC_REF(payload)), finale_delay)
+ else
+ payload()
+
+/datum/artifact_effect/bomb/on_destroy(datum/source)
+ . = ..()
+ if(our_artifact.active && source != src)//Prevents infinite bakoom.
+ payload()
+ deltimer(timer_id)
+
+/datum/artifact_effect/bomb/proc/payload()
+ . = TRUE
+ if(dud || !our_artifact.active)
+ our_artifact.holder.visible_message(span_notice("[our_artifact.holder] [dud_message]"))
+ our_artifact.artifact_deactivate(TRUE)
+ return FALSE
+
+/// EXPLOSIVE BOMB
+
+/datum/artifact_effect/bomb/explosive
+ type_name = "Bomb"
+ weight = ARTIFACT_RARE
+ var/devast
+ var/heavy
+ var/light
+ examine_discovered = span_danger("It appears to explode in a large radius!")
+
+/datum/artifact_effect/bomb/explosive/New()
+ . = ..()
+ devast = rand(1,3)
+ heavy = rand(2,4)
+ light = rand(3,10)
+ potency = (light + heavy + devast) * 2
+
+/datum/artifact_effect/bomb/explosive/payload()
+ if(!..())
+ return FALSE
+ explosion(our_artifact.holder, devast,heavy,light,light*1.5)
+ on_destroy(src)
+
+/// DEVESTATING BOMB
+
+/datum/artifact_effect/bomb/explosive/devastating
+ type_name = "Large Bomb"
+ do_alert = TRUE
+ weight = ARTIFACT_VERYRARE
+ explode_delay = 2 MINUTES
+
+/datum/artifact_effect/bomb/explosive/devastating/New()
+ ..()
+ devast = rand(2,4)
+ heavy = rand(4,6)
+ light = rand(6,16)
+ potency = (devast + heavy + light) * 2.25 // get real
+
+/// GAS BOMB
+
+/datum/artifact_effect/bomb/gas
+ type_name = "Atmospheric Bomb"
+ weight = ARTIFACT_RARE
+ examine_discovered = span_warning("It appears to explode, leaving gasses in its wake!")
+ initial_warning = "begins rattling violenty!"
+ final_message = "reaches a critical pressure, cracks forming at its surface!"
+ var/datum/gas/payload_gas
+ var/list/weighted_gas = list(
+ /datum/gas/plasma = 5,
+ /datum/gas/carbon_dioxide = 10,
+ /datum/gas/nitrous_oxide = 10,
+ /datum/gas/tritium = 5,
+ /datum/gas/hydrogen = 5,
+ /datum/gas/zauker = 2,
+ )
+
+/datum/artifact_effect/bomb/gas/setup()
+ . = ..()
+ payload_gas = pick_weight(weighted_gas)
+
+/datum/artifact_effect/bomb/gas/payload()
+ if(!..())
+ our_artifact.artifact_deactivate()
+ return FALSE
+ var/turf/open/O = get_turf(our_artifact.holder)
+ if(!isopenturf(O))
+ our_artifact.artifact_deactivate()
+ return FALSE
+ var/datum/gas_mixture/merger = new
+ merger.assert_gas(payload_gas)
+ merger.assert_gas(/datum/gas/oxygen)
+ merger.gases[payload_gas][MOLES] = rand(150,2000)
+ merger.gases[/datum/gas/oxygen][MOLES] = 350
+ merger.temperature = rand(200,3000)
+ O.assume_air(merger)
+ qdel(our_artifact)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/bonk.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/bonk.dm
new file mode 100644
index 000000000000..b2fc28a51026
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/bonk.dm
@@ -0,0 +1,40 @@
+/datum/artifact_effect/bonk
+ weight = ARTIFACT_UNCOMMON
+ type_name = "Slammer Effect"
+ activation_message = "opens up!"
+ deactivation_message = "closes up."
+ valid_activators = list(
+ /datum/artifact_activator/touch/carbon,
+ /datum/artifact_activator/touch/silicon
+ )
+ ///force of the hit
+ var/hit_power = 1
+ artifact_size = ARTIFACT_SIZE_LARGE
+ COOLDOWN_DECLARE(bonk_cooldown)
+ research_value = 500
+ examine_discovered = span_warning("It appears to bonk those with heads on said head.")
+
+/datum/artifact_effect/bonk/setup()
+ hit_power = rand(0,35)
+ potency += hit_power
+
+/datum/artifact_effect/bonk/effect_touched(mob/living/user)
+ if(!COOLDOWN_FINISHED(src, bonk_cooldown))
+ return
+
+ if(iscarbon(user))
+ var/mob/living/carbon/carbon = user
+ if(!carbon.get_bodypart(BODY_ZONE_HEAD))
+ our_artifact.holder.say("My condolences to your missing head.") //they can speak uhh galactic common because alien tech idk
+ our_artifact.holder.visible_message(span_notice("[our_artifact.holder] shakes [user][p_s()] hands with an apparatus."))
+ playsound(get_turf(our_artifact.holder), 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
+ our_artifact.artifact_deactivate()
+ return
+ else
+ carbon.apply_damage(hit_power, BRUTE, BODY_ZONE_HEAD, carbon.run_armor_check(BODY_ZONE_HEAD, MELEE))
+ our_artifact.holder.visible_message(span_danger("[our_artifact.holder] hits [carbon] over the head!"))
+ else
+ our_artifact.holder.visible_message(span_danger("[our_artifact.holder] slams [user]!"))
+ user.adjustBruteLoss(hit_power)
+ playsound(get_turf(our_artifact.holder), 'sound/misc/bonk.ogg', 80, FALSE)
+ COOLDOWN_START(src, bonk_cooldown, 1.5 SECONDS)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/borger.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/borger.dm
similarity index 73%
rename from monkestation/code/modules/art_sci_overrides/artifact_components/borger.dm
rename to monkestation/code/modules/art_sci_overrides/artifact_effects/borger.dm
index e87a58fbe398..ef3e1ded89aa 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/borger.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/borger.dm
@@ -1,14 +1,15 @@
-/datum/component/artifact/borger
- associated_object = /obj/structure/artifact/borger
- weight = ARTIFACT_UNCOMMON
- type_name = "Borger"
+/datum/artifact_effect/borger
+ weight = ARTIFACT_RARE
+ type_name = "Borger Effect"
activation_message = "opens up!"
deactivation_message = "closes up."
valid_activators = list(
/datum/artifact_activator/touch/carbon,
/datum/artifact_activator/touch/silicon
)
- explict_examine = span_bolddanger("It is vaguely forboding, touching this might be a bad idea...")
+ research_value = 2500
+ examine_hint = span_bolddanger("It is vaguely forboding, touching this might be a bad idea...")
+ examine_discovered = span_bolddanger("It will turn a random limb robotic if touched, touching this might be a bad idea...")
/// The time between each limb replacement
var/limb_replace_time = 1 SECONDS
/// People who've already touched it once. Touching it again will cause it to react.
@@ -16,9 +17,9 @@
/// The cooldown between borgings.
COOLDOWN_DECLARE(borg_cooldown)
-/datum/component/artifact/borger/effect_touched(mob/living/user)
+/datum/artifact_effect/borger/effect_touched(mob/living/user)
if(!iscarbon(user) || !COOLDOWN_FINISHED(src, borg_cooldown) || QDELETED(user.client) || did_robot_touch(user))
- holder.visible_message(span_smallnoticeital("[holder] does not react to [user]."))
+ our_artifact.holder.visible_message(span_smallnoticeital("[our_artifact.holder] does not react to [user]."))
return
if(!LAZYACCESS(first_touched, user))
@@ -54,14 +55,14 @@
addtimer(CALLBACK(carbon_target, TYPE_PROC_REF(/mob/, Robotize)), timer + 5)
COOLDOWN_START(src, borg_cooldown, 10 SECONDS)
-/datum/component/artifact/borger/proc/eat_limb(mob/living/carbon/victim)
+/datum/artifact_effect/borger/proc/eat_limb(mob/living/carbon/victim)
var/arm_name = victim.get_held_index_name(victim.active_hand_index)
- victim.visible_message(span_warning("[holder] lashes out and clamps down on [victim], rapidly transmuting [victim.p_their()] [arm_name]!"), \
- span_userdanger("[holder] lashes out and clamps down onto your [arm_name], rapidly transmuting it into cold metal!"))
+ victim.visible_message(span_warning("[our_artifact.holder] lashes out and clamps down on [victim], rapidly transmuting [victim.p_their()] [arm_name]!"), \
+ span_userdanger("[our_artifact.holder] lashes out and clamps down onto your [arm_name], rapidly transmuting it into cold metal!"))
var/new_arm_type = (victim.active_hand_index % 2) ? /obj/item/bodypart/arm/left/robot : /obj/item/bodypart/arm/right/robot
victim.del_and_replace_bodypart(new new_arm_type)
victim.emote("scream")
-/datum/component/artifact/borger/proc/did_robot_touch(mob/living/carbon/user)
+/datum/artifact_effect/borger/proc/did_robot_touch(mob/living/carbon/user)
var/obj/item/bodypart/arm/active_arm = user.get_active_hand()
return istype(active_arm) && (active_arm.bodytype & BODYTYPE_ROBOTIC)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/bread.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/bread.dm
new file mode 100644
index 000000000000..47e9791fbd5b
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/bread.dm
@@ -0,0 +1,52 @@
+/datum/artifact_effect/bread
+ examine_discovered = "Summons bread?"
+ weight = ARTIFACT_UNCOMMON
+ discovered_credits = CARGO_CRATE_VALUE * 2 //Mmm bread
+ activation_message = "begins baking some fresh eldritch brand bread!"
+ deactivation_message = "runs out of bread!"
+ research_value = 500
+ type_name = "Bread Teleportation Effect"
+
+ COOLDOWN_DECLARE(bread_cd)
+
+ var/bread_counter = 0
+
+ ///We sell BREAD. We sell LOAF. TOASTED, ROASTED...
+ var/static/list/obj/item/food/validbread = list(
+ /obj/item/food/bread/plain = 20,
+ /obj/item/food/bread/meat = 15,
+ /obj/item/food/bread/banana = 15,
+ /obj/item/food/bread/tofu = 10,
+ /obj/item/food/croissant = 10,
+ /obj/item/food/baguette = 10,
+ /obj/item/food/garlicbread = 10,
+ /obj/item/food/bread/creamcheese = 10,
+ /obj/item/food/frenchtoast = 8,
+ /obj/item/food/breadstick = 8,
+ /obj/item/food/butterbiscuit = 5,
+ /obj/item/food/bread/mimana = 5,
+ /obj/item/food/bread/sausage = 5,
+ /obj/item/food/bread/xenomeat = 1,
+ /obj/item/food/bread/spidermeat = 1
+ )
+
+/datum/artifact_effect/bread/effect_process()
+ if(!COOLDOWN_FINISHED(src,bread_cd))
+ return
+ var/center_turf = get_turf(our_artifact.parent)
+ var/list/turf/valid_turfs = list()
+ if(!center_turf)
+ CRASH("[src] had attempted to trigger, but failed to find the center turf!")
+ for(var/turf/boi in range(3,center_turf))
+ if(boi.density)
+ continue
+ valid_turfs += boi
+ var/obj/item/food/pickedbread = pick_weight(validbread)
+ new pickedbread(pick(valid_turfs))
+ bread_counter++
+ if(bread_counter > round(potency/10))
+ bread_counter = 0
+ toggle_active(FALSE)
+ return
+ COOLDOWN_START(src,bread_cd,(7.5 SECONDS))
+
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/cell.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/cell.dm
new file mode 100644
index 000000000000..2da2af3b00ff
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/cell.dm
@@ -0,0 +1,28 @@
+/datum/artifact_effect/cell
+ type_name = "Power Cell Effect"
+ weight = ARTIFACT_UNCOMMON
+ artifact_size = ARTIFACT_SIZE_TINY
+ valid_activators = list(
+ /datum/artifact_activator/range/heat,
+ /datum/artifact_activator/range/shock,
+ /datum/artifact_activator/range/radiation
+ )
+ valid_type_paths = list(/obj/item/stock_parts/cell/artifact)
+ research_value = 500
+ examine_discovered = span_warning("It appears to hold power")
+
+/datum/artifact_effect/cell/setup()
+ var/obj/item/stock_parts/cell/artifact/cell = our_artifact.holder
+ cell.maxcharge = rand(5 KW, 500 MW) // the heavenly battery
+ cell.charge = cell.maxcharge / 2
+ cell.chargerate = rand(5000, round(cell.maxcharge * 0.4))
+ potency += cell.maxcharge / 900
+ potency += cell.chargerate / 4000
+
+/datum/artifact_effect/cell/effect_activate()
+ var/obj/item/stock_parts/cell/artifact/cell = our_artifact.holder
+ cell.ratingdesc = TRUE
+
+/datum/artifact_effect/cell/effect_deactivate()
+ var/obj/item/stock_parts/cell/artifact/cell = our_artifact.holder
+ cell.ratingdesc = FALSE
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/cleaning.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/cleaning.dm
new file mode 100644
index 000000000000..1b61aad86c44
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/cleaning.dm
@@ -0,0 +1,17 @@
+/datum/artifact_effect/soap
+ examine_hint = "Smells nice."
+ examine_discovered = "Seems to clean things."
+ artifact_size = ARTIFACT_SIZE_TINY
+ type_name = "Cleaning Effect"
+
+/datum/artifact_effect/soap/setup()
+ our_artifact.holder.AddComponent(/datum/component/slippery, 80)
+ our_artifact.holder.AddComponent(/datum/component/cleaner, 2 SECOND, 0.1, pre_clean_callback=CALLBACK(src, PROC_REF(should_clean)), on_cleaned_callback=CALLBACK(src, TYPE_PROC_REF(/datum/artifact_effect/soap,sorry_nothing)))
+
+/datum/artifact_effect/soap/proc/should_clean(datum/cleaning_source, atom/atom_to_clean, mob/living/cleaner)
+ if(isitem(our_artifact.holder))
+ var/obj/item/yep_its_an_item = our_artifact.holder
+ return yep_its_an_item.check_allowed_items(atom_to_clean)
+ return FALSE
+/datum/artifact_effect/soap/proc/sorry_nothing(datum/source, atom/target, mob/living/user, clean_succeeded)
+ return
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/emoter.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/emoter.dm
similarity index 60%
rename from monkestation/code/modules/art_sci_overrides/artifact_components/emoter.dm
rename to monkestation/code/modules/art_sci_overrides/artifact_effects/emoter.dm
index 88c88d374bb0..772bd97c0ad5 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/emoter.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/emoter.dm
@@ -1,7 +1,6 @@
-/datum/component/artifact/emotegen
- associated_object = /obj/structure/artifact/emotegen
+/datum/artifact_effect/emotegen
weight = ARTIFACT_UNCOMMON
- type_name = "Emote Forcefield"
+ type_name = "Emote Forcefield Effect"
activation_message = "springs to life and starts emitting a forcefield!"
deactivation_message = "shuts down, its forcefields shutting down with it."
valid_activators = list(
@@ -9,6 +8,9 @@
/datum/artifact_activator/touch/silicon,
/datum/artifact_activator/range/force
)
+
+ research_value = 150
+
var/cooldown_time //cooldown AFTER the shield lowers
var/radius
var/shield_time
@@ -25,10 +27,13 @@
"snore",
"cry",
)
+
+ examine_discovered = span_warning("It appears to radiate an emotional field")
+
var/list/picked_emotes = list()
COOLDOWN_DECLARE(cooldown)
-/datum/component/artifact/emotegen/setup()
+/datum/artifact_effect/emotegen/setup()
for(var/i = 1 to rand(3,4))
picked_emotes += pick(all_emotes)
@@ -39,24 +44,24 @@
cooldown_time = shield_time / 3
potency += radius * 3 + shield_time / 30
-/datum/component/artifact/emotegen/effect_activate(silent)
+/datum/artifact_effect/emotegen/effect_activate(silent)
if(!COOLDOWN_FINISHED(src,cooldown))
- holder.visible_message(span_notice("[holder] wheezes, shutting down."))
- artifact_deactivate(TRUE)
+ our_artifact.holder.visible_message(span_notice("[our_artifact.holder] wheezes, shutting down."))
+ our_artifact.artifact_deactivate(TRUE)
return
- addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/component/artifact, artifact_deactivate)), shield_time)
+ addtimer(CALLBACK(our_artifact, TYPE_PROC_REF(/datum/component/artifact, artifact_deactivate)), shield_time)
COOLDOWN_START(src,cooldown,shield_time + cooldown_time)
-/datum/component/artifact/emotegen/effect_process()
+/datum/artifact_effect/emotegen/effect_process()
var/current_emote = pick(picked_emotes)
- holder.anchored = TRUE
- var/turf/our_turf = get_turf(holder)
- for(var/turf/open/floor in range(radius,holder))
+ our_artifact.holder.anchored = TRUE
+ var/turf/our_turf = get_turf(our_artifact.holder)
+ for(var/turf/open/floor in range(radius,our_artifact.holder))
if(floor == our_turf)
continue
for(var/mob/living/living in floor)
living.emote(current_emote, intentional = FALSE)
-/datum/component/artifact/emotegen/effect_deactivate()
- holder.anchored = FALSE
+/datum/artifact_effect/emotegen/effect_deactivate()
+ our_artifact.holder.anchored = FALSE
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/false_rod.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/false_rod.dm
new file mode 100644
index 000000000000..27030a251101
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/false_rod.dm
@@ -0,0 +1,93 @@
+/datum/artifact_effect/false_rod
+ examine_hint = span_warning("You feel a binding aura connected to this.")
+ examine_discovered = span_warning("Will bind it self to the wearer, forcing upon them an oath to heal!")
+ weight = ARTIFACT_UNCOMMON
+
+ artifact_size = ARTIFACT_SIZE_SMALL
+ type_name = "Oath-Bearing Rod Effect"
+
+ var/list/first_touched
+
+ var/mob/living/our_victim
+
+ COOLDOWN_DECLARE(touch_cooldown)
+
+/datum/artifact_effect/false_rod/setup()
+ RegisterSignal(our_artifact.holder,COMSIG_ITEM_POST_EQUIPPED,TYPE_PROC_REF(/datum/artifact_effect/false_rod,on_pickup))
+
+/datum/artifact_effect/false_rod/proc/on_pickup(obj/item/the_item,mob/taker,slot)
+ SIGNAL_HANDLER
+ if(!isliving(taker))
+ return COMPONENT_EQUIPPED_FAILED
+ var/mob/living/user = taker
+ if(!(isitem(our_artifact.holder)) || !COOLDOWN_FINISHED(src,touch_cooldown))
+ return COMPONENT_EQUIPPED_FAILED
+ if(!LAZYACCESS(first_touched, user))
+ to_chat(user,span_bolddanger("You hesitate before touching [our_artifact.holder], feeling it will do something that cannot be un-done easily!"))
+ LAZYSET(first_touched, user, TRUE)
+ COOLDOWN_START(src, touch_cooldown, 7.5 SECONDS) // so you don't get fucked over by spam-clicking it
+ return COMPONENT_EQUIPPED_FAILED
+ addtimer(CALLBACK(src,PROC_REF(post_pickup),user),(0.2 SECOND))
+ return
+
+/datum/artifact_effect/false_rod/on_destroy(atom/source)
+ our_victim?.remove_status_effect(/datum/status_effect/forced_oath)
+ . = ..()
+
+/datum/artifact_effect/false_rod/proc/post_pickup(mob/living/user)
+ to_chat(user,span_danger("[our_artifact.holder] forcefully melds with you, and a healing aura surrounds you!"))
+ ADD_TRAIT(our_artifact.holder,TRAIT_NODROP,CURSED_ITEM_TRAIT(our_artifact.holder.type))
+ user.apply_status_effect(/datum/status_effect/forced_oath)
+ our_victim = user
+ return
+
+/datum/status_effect/forced_oath
+ id = "Forced Oath"
+ status_type = STATUS_EFFECT_UNIQUE
+ duration = -1
+ tick_interval = 25
+ alert_type = null
+ var/datum/component/aura_healing/our_aura
+
+/datum/status_effect/forced_oath/on_apply()
+ var/static/list/organ_healing = list(
+ ORGAN_SLOT_BRAIN = 0.7,
+ )
+ //This is literally shitty Rod of Ascep.
+ our_aura = owner.AddComponent( \
+ /datum/component/aura_healing, \
+ range = 5, \
+ brute_heal = 1, \
+ burn_heal = 1, \
+ toxin_heal = 1, \
+ suffocation_heal = 1, \
+ stamina_heal = 1, \
+ clone_heal = 0.2, \
+ simple_heal = 1, \
+ organ_healing = organ_healing, \
+ healing_color = "#375637", \
+ )
+
+ var/datum/atom_hud/med_hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
+ med_hud.show_to(owner)
+ return TRUE
+/datum/status_effect/forced_oath/on_remove()
+ QDEL_NULL(our_aura)
+ var/datum/atom_hud/med_hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
+ med_hud.hide_from(owner)
+/datum/status_effect/forced_oath/get_examine_text()
+ return span_notice("[owner.p_they(TRUE)] seem[owner.p_s()] to have an aura of healing around [owner.p_them()].")
+/datum/status_effect/forced_oath/tick()
+ if(owner.stat ==DEAD)
+ return
+ else
+ if(iscarbon(owner))
+ if(owner.health < owner.maxHealth)
+ new /obj/effect/temp_visual/heal(get_turf(owner), "#375637")
+ owner.adjustBruteLoss(-1)
+ owner.adjustFireLoss(-1)
+ owner.adjustToxLoss(-1, forced = TRUE) //Because Slime People are people too
+ owner.adjustOxyLoss(-1, forced = TRUE)
+ owner.stamina.adjust(1)
+ owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1)
+ owner.adjustCloneLoss(-0.25) //Becasue apparently clone damage is the bastion of all health
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/forcegen.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/forcegen.dm
similarity index 68%
rename from monkestation/code/modules/art_sci_overrides/artifact_components/forcegen.dm
rename to monkestation/code/modules/art_sci_overrides/artifact_effects/forcegen.dm
index 95be5fbb3305..04608b5b8764 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/forcegen.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/forcegen.dm
@@ -11,13 +11,13 @@
resistance_flags = INDESTRUCTIBLE
can_atmos_pass = ATMOS_PASS_DENSITY
+
/obj/structure/artifact_forcefield/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
playsound(loc, 'sound/weapons/egloves.ogg', 80, TRUE)
-/datum/component/artifact/forcegen
- associated_object = /obj/structure/artifact/forcegen
+/datum/artifact_effect/forcegen
weight = ARTIFACT_UNCOMMON
- type_name = "Forcefield Generator"
+ type_name = "Forcefield Generator Effect"
activation_message = "springs to life and starts emitting a forcefield!"
deactivation_message = "shuts down, its forcefields shutting down with it."
valid_activators = list(
@@ -25,6 +25,11 @@
/datum/artifact_activator/touch/silicon,
/datum/artifact_activator/range/force
)
+
+ research_value = 5000
+
+ examine_discovered = span_warning("It appears to generate some kind of forcefield")
+
var/cooldown_time //cooldown AFTER the shield lowers
var/shield_iconstate
var/list/projected_forcefields = list()
@@ -32,26 +37,25 @@
var/shield_time
COOLDOWN_DECLARE(cooldown)
-/datum/component/artifact/forcegen/setup()
+/datum/artifact_effect/forcegen/setup()
shield_iconstate = pick("shieldsparkles","empdisable","shield2","shield-old","shield-red","shield-green","shield-yellow")
activation_sound = pick('sound/mecha/mech_shield_drop.ogg')
deactivation_sound = pick('sound/mecha/mech_shield_raise.ogg','sound/magic/forcewall.ogg')
- shield_time = rand(10,40) SECONDS
+ shield_time = rand(10,30) SECONDS
radius = rand(1,3)
cooldown_time = shield_time / 3
- potency += radius * 3 + shield_time / 30
-/datum/component/artifact/forcegen/effect_activate()
+/datum/artifact_effect/forcegen/effect_activate()
if(!COOLDOWN_FINISHED(src,cooldown))
- holder.visible_message(span_notice("[holder] wheezes, shutting down."))
- artifact_deactivate(TRUE)
+ our_artifact.holder.visible_message(span_notice("[our_artifact.holder] wheezes, shutting down."))
+ our_artifact.artifact_deactivate(TRUE)
return
- holder.anchored = TRUE
- var/turf/our_turf = get_turf(holder)
+ our_artifact.holder.anchored = TRUE
+ var/turf/our_turf = get_turf(our_artifact.holder)
var/list/bad_turfs
if(radius > 1)
- bad_turfs = range(radius - 1, holder)
- for(var/turf/open/floor in range(radius,holder))
+ bad_turfs = range(radius - 1, our_artifact.holder)
+ for(var/turf/open/floor in range(radius,our_artifact.holder))
if(floor in bad_turfs)
continue
if(floor == our_turf)
@@ -59,11 +63,11 @@
var/obj/field = new /obj/structure/artifact_forcefield(floor)
field.icon_state = shield_iconstate
projected_forcefields += field
- addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/component/artifact, artifact_deactivate)), shield_time)
+ addtimer(CALLBACK(our_artifact, TYPE_PROC_REF(/datum/component/artifact, artifact_deactivate)), shield_time)
COOLDOWN_START(src,cooldown,shield_time + cooldown_time)
-/datum/component/artifact/forcegen/effect_deactivate()
- holder.anchored = FALSE
+/datum/artifact_effect/forcegen/effect_deactivate()
+ our_artifact.holder.anchored = FALSE
for(var/obj/field in projected_forcefields)
projected_forcefields -= field
qdel(field)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/gun.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/gun.dm
similarity index 75%
rename from monkestation/code/modules/art_sci_overrides/artifact_components/gun.dm
rename to monkestation/code/modules/art_sci_overrides/artifact_effects/gun.dm
index 7425c524e47a..a574230764ad 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/gun.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/gun.dm
@@ -1,26 +1,20 @@
#define LOWEST_POSSIBLE_CLICK_CD 3
#define HIGHEST_POSSIBLE_CLICK_CD 15
-/datum/component/artifact/gun
- associated_object = /obj/item/gun/magic/artifact
+/datum/artifact_effect/gun
artifact_size = ARTIFACT_SIZE_SMALL
- type_name = "Ranged Weapon"
+ type_name = "Ranged Weapon Effect"
weight = ARTIFACT_VERYUNCOMMON //rare
- xray_result = "COMPLEX"
valid_activators = list(
/datum/artifact_activator/range/heat,
/datum/artifact_activator/range/shock,
/datum/artifact_activator/range/radiation
)
- valid_faults = list(
- /datum/artifact_fault/ignite = 10,
- /datum/artifact_fault/warp = 10,
- /datum/artifact_fault/reagent/poison = 10,
- /datum/artifact_fault/death = 2,
- /datum/artifact_fault/tesla_zap = 5,
- /datum/artifact_fault/grow = 10,
- /datum/artifact_fault/explosion = 2,
- )
+ valid_type_paths = list(/obj/item/gun/magic/artifact)
+
+ research_value = 500
+
+ examine_discovered = span_warning("It appears to be some sort of projectile weapon!")
//list of projectile exclusive projectiles
///damage each shot does
@@ -46,14 +40,11 @@
var/list/damage_types = list(
BRUTE,
BURN,
- TOX,
- OXY,
- BRAIN,
- STAMINA
+ TOX
)
-/datum/component/artifact/gun/setup()
- var/obj/item/gun/magic/artifact/our_wand = holder
+/datum/artifact_effect/gun/setup()
+ var/obj/item/gun/magic/artifact/our_wand = our_artifact.holder
var/obj/item/ammo_casing/casing = our_wand.chambered
//randomize our casing
casing.click_cooldown_override = rand(LOWEST_POSSIBLE_CLICK_CD, HIGHEST_POSSIBLE_CLICK_CD)
@@ -62,7 +53,7 @@
spread += 0.1
spread += prob(65) ? rand(0.0, 0.2) : rand(0.3, 1.0)
- damage = rand(-5, 25)
+ damage = rand(-10, 30)
projectile_icon = pick("energy","scatterlaser","toxin","energy","spell","pulse1","bluespace","gauss","gaussweak","gaussstrong","redtrac","omnilaser","heavylaser","laser","infernoshot","cryoshot","arcane_barrage")
dam_type = pick(damage_types)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/heal.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/heal.dm
similarity index 59%
rename from monkestation/code/modules/art_sci_overrides/artifact_components/heal.dm
rename to monkestation/code/modules/art_sci_overrides/artifact_effects/heal.dm
index 9177d7dea38e..67c2e1a535f3 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/heal.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/heal.dm
@@ -1,22 +1,23 @@
#define PROCESSES_PER_HEAL 5
-/datum/component/artifact/heal
- associated_object = /obj/structure/artifact/heal
+/datum/artifact_effect/heal
weight = ARTIFACT_VERYUNCOMMON
- type_name = "Single Healer"
+ type_name = "Single Healer Effect"
activation_message = "starts emitting a soothing aura!"
deactivation_message = "becomes silent."
valid_activators = list(
/datum/artifact_activator/touch/carbon,
/datum/artifact_activator/touch/silicon
)
- ///list of damage types we heal, this is randomly removed from at setup
+
+ examine_discovered = span_warning("It appears to heal those who touch it.")
+
+ research_value = 250
+
+ ///list of what we heal
var/list/damage_types = list(
BRUTE,
BURN,
- TOX,
- OXY,
- BRAIN,
- CLONE,
+ TOX
)
///how much do we heal
var/heal_amount
@@ -24,29 +25,19 @@
var/process_count = 0
COOLDOWN_DECLARE(heal_cooldown)
-/datum/component/artifact/heal/setup()
- heal_amount = rand(1,15)
- potency += heal_amount
- var/type_amount = prob(75) ? 4 : rand(2,4) //75% to remove 4 types for 1 heal type or 25% for 2 or 4 types removed
- while(type_amount)
- type_amount--
- damage_types -= pick(damage_types)
- potency += 5 * (length(damage_types) - 1)
+/datum/artifact_effect/heal/setup()
+ heal_amount = rand(5,10)
-/datum/component/artifact/heal/effect_touched(mob/living/user)
+/datum/artifact_effect/heal/effect_touched(mob/living/user)
if(!COOLDOWN_FINISHED(src, heal_cooldown))
return
- var/damage_length = length(damage_types)
for(var/dam_type in damage_types)
- user.heal_damage_type( (heal_amount / damage_length), dam_type)
+ user.heal_damage_type( (heal_amount), dam_type)
to_chat(user, span_notice("You feel slightly refreshed!"))
new /obj/effect/temp_visual/heal(get_turf(user), COLOR_HEALING_CYAN)
COOLDOWN_START(src, heal_cooldown, 5 SECONDS)
-/datum/component/artifact/heal/effect_process()
- if(potency < 75)
- return
-
+/datum/artifact_effect/heal/effect_process()
process_count++
if(process_count < PROCESSES_PER_HEAL)
return
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/injector.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/injector.dm
similarity index 64%
rename from monkestation/code/modules/art_sci_overrides/artifact_components/injector.dm
rename to monkestation/code/modules/art_sci_overrides/artifact_effects/injector.dm
index dc30a0192443..3d82ebf98ed0 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/injector.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/injector.dm
@@ -1,18 +1,20 @@
-/datum/component/artifact/injector
- associated_object = /obj/structure/artifact/injector
+/datum/artifact_effect/injector
weight = ARTIFACT_UNCOMMON
- type_name = "Injector"
+ type_name = "Injector Effect"
activation_message = "opens up to reveal a large needle!"
deactivation_message = "pulls its needle inside, closing itself up."
- xray_result = "SEGMENTED"
var/max_reagents // the total amount to dose the victim with
var/reagent_amount
var/list/reagent_datums = list()
var/cooldown_time = 10 SECONDS
COOLDOWN_DECLARE(activation_cooldown)
-/datum/component/artifact/injector/setup()
- holder.create_reagents(200, NO_REACT | SEALED_CONTAINER)
+ research_value = 250
+
+ examine_discovered = span_warning("It appears to be some sort of chemical injector")
+
+/datum/artifact_effect/injector/setup()
+ our_artifact.holder.create_reagents(200, NO_REACT | SEALED_CONTAINER)
reagent_amount = rand(10,25)
max_reagents = rand(1,2)
var/static/list/poisons_and_medicines = list()
@@ -20,7 +22,7 @@
for(var/datum/reagent/reagent as anything in (subtypesof(/datum/reagent/toxin) + subtypesof(/datum/reagent/medicine)))
if(initial(reagent.chemical_flags) & REAGENT_CAN_BE_SYNTHESIZED)
poisons_and_medicines += reagent
- switch(artifact_origin.type_name)
+ switch(our_artifact.artifact_origin.type_name)
if(ORIGIN_NARSIE)
for(var/i in 1 to max_reagents)
reagent_datums += pick(poisons_and_medicines) //cult likes killing people ok
@@ -36,12 +38,12 @@
reagent_datums += pick(silicon_reagents)
potency += reagent_amount + max_reagents
-/datum/component/artifact/injector/effect_touched(mob/living/user)
+/datum/artifact_effect/injector/effect_touched(mob/living/user)
if(!ishuman(user) || !COOLDOWN_FINISHED(src,activation_cooldown))
- holder.visible_message(span_smallnoticeital("[holder] does not react to [user]."))
+ our_artifact.holder.visible_message(span_smallnoticeital("[our_artifact.holder] does not react to [user]."))
return
for(var/reagent in reagent_datums)
- holder.reagents.add_reagent(reagent, reagent_amount / reagent_datums.len)
- holder.visible_message(span_danger("[holder] pricks [user] with its needle!"), span_userdanger("OW! You are pricked by [holder]!"))
- holder.reagents.trans_to(user, holder.reagents.total_volume, transfered_by = holder, methods = INJECT)
+ our_artifact.holder.reagents.add_reagent(reagent, reagent_amount / reagent_datums.len)
+ our_artifact.holder.visible_message(span_danger("[our_artifact.holder] pricks [user] with its needle!"), span_userdanger("OW! You are pricked by [our_artifact.holder]!"))
+ our_artifact.holder.reagents.trans_to(user, our_artifact.holder.reagents.total_volume, transfered_by = our_artifact.holder, methods = INJECT)
COOLDOWN_START(src,activation_cooldown,cooldown_time)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/itsasecret.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/itsasecret.dm
new file mode 100644
index 000000000000..bcda23c9678a
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/itsasecret.dm
@@ -0,0 +1,44 @@
+/datum/artifact_effect/toeverybody
+ examine_hint = "Seems...off somehow."
+ examine_discovered = "Temporarily tears holes in reality."
+ discovered_credits = CARGO_CRATE_VALUE * 100 //GDM
+ weight = ARTIFACT_VERYRARE/5 //Super rare
+ activation_message = "tears open the fabric of reality!"
+
+ research_value = 10000
+
+ type_name = "Its a Secret to Everybody"
+
+ super_secret = TRUE
+
+ COOLDOWN_DECLARE(trigger_cd)
+
+/datum/artifact_effect/toeverybody/proc/returnthey(mob/living/carbon/human,turf/last_position)
+ human.forceMove(last_position)
+ return
+
+/datum/artifact_effect/toeverybody/effect_activate(silent)
+ if(!COOLDOWN_FINISHED(src,trigger_cd))
+ return
+ var/list/mobs = list()
+ var/mob/living/carbon/human
+
+ var/center_turf = get_turf(our_artifact.parent)
+
+ if(!center_turf)
+ CRASH("[src] had attempted to trigger, but failed to find the center turf!")
+
+ for(var/mob/living/carbon/mob in range(rand(3, 4), center_turf))
+ mobs += mob
+ if(!length(mobs))
+ return
+ human = pick(mobs)
+ if(!human)
+ return
+
+ var/last_position = get_turf(human)
+ human.move_to_error_room()
+ COOLDOWN_START(src,trigger_cd,5 MINUTE)
+ addtimer(CALLBACK(src,PROC_REF(returnthey),human,last_position),5 SECOND)
+ return
+
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/lamp.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/lamp.dm
new file mode 100644
index 000000000000..9e4d4ae0dd1e
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/lamp.dm
@@ -0,0 +1,38 @@
+
+/datum/artifact_effect/lamp
+ weight = ARTIFACT_COMMON
+ type_name = "Lamp"
+ activation_message = "starts shining!"
+ deactivation_message = "stops shining."
+ examine_discovered = span_warning("It appears to be some sort of light source")
+
+ artifact_size = ARTIFACT_SIZE_LARGE
+
+ research_value = 250
+
+/datum/artifact_effect/lamp/setup()
+ var/power
+ var/color = pick(COLOR_RED, COLOR_BLUE, COLOR_YELLOW, COLOR_GREEN, COLOR_PURPLE, COLOR_ORANGE)
+ var/range
+ switch(rand(1,100))
+ if(1 to 75)
+ power = rand(2,5)
+ range = rand(2,5)
+ if(76 to 100)
+ range = rand(4,10)
+ power = rand(5,10) // the sun
+
+ if(our_artifact.artifact_origin.type_name == ORIGIN_NARSIE && prob(40))
+ color = COLOR_BLACK
+ our_artifact.holder.light_system = COMPLEX_LIGHT //We need this to avoid a crash for wrong lighting system.
+ our_artifact.holder.set_light(range, round(range*1.25),power,l_color = color,l_on = FALSE)
+
+/datum/artifact_effect/lamp/effect_touched(mob/user)
+ our_artifact.holder.set_light_on(!our_artifact.holder.light_on) //toggle
+ to_chat(user, span_hear("[our_artifact.holder] clicks."))
+
+/datum/artifact_effect/lamp/effect_activate()
+ our_artifact.holder.set_light_on(TRUE)
+
+/datum/artifact_effect/lamp/effect_deactivate()
+ our_artifact.holder.set_light_on(FALSE)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/meat.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/meat.dm
new file mode 100644
index 000000000000..5781d29458ca
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/meat.dm
@@ -0,0 +1,54 @@
+/datum/artifact_effect/meat
+ examine_discovered = "Summons meat?"
+ weight = ARTIFACT_UNCOMMON
+ discovered_credits = CARGO_CRATE_VALUE * 2 //ME A T
+ activation_message = "begins stealing meat!"
+ deactivation_message = "gets caught stealing meat!"
+ research_value = 500
+ type_name = "Meat Teleportation Effect"
+
+ COOLDOWN_DECLARE(meat_cd)
+
+ var/meat_counter = 0
+
+ ///MY MEAT BYCICLE IS BIGGER THAN YOURS - Kreig borderlands
+ var/static/list/obj/item/food/validmeat = list(
+ /obj/item/food/meat/slab = 20,
+ /obj/item/food/meat/slab/meatwheat = 20,
+ /obj/item/food/meat/slab/monkey = 15,
+ /obj/item/food/meat/slab/bugmeat = 15,
+ /obj/item/food/meat/slab/mothroach = 15,
+ /obj/item/food/meat/slab/mouse = 15,
+ /obj/item/food/meat/slab/pug = 10,
+ /obj/item/food/meat/slab/goliath = 10,
+ /obj/item/food/meat/slab/corgi = 10,
+ /obj/item/food/meat/slab/gorilla = 5,
+ /obj/item/food/meat/slab/bear = 5,
+ /obj/item/food/meat/slab/xeno = 5,
+ /obj/item/food/meat/slab/spider = 5,
+ /obj/item/food/meat/slab/human/mutant/slime = 1,
+ /obj/item/food/meat/slab/human/mutant/lizard = 1,
+ /obj/item/food/meat/slab/human = 1,
+ /obj/item/food/meat/slab/human/mutant/skeleton = 1,
+ )
+
+/datum/artifact_effect/meat/effect_process()
+ if(!COOLDOWN_FINISHED(src,meat_cd))
+ return
+ var/center_turf = get_turf(our_artifact.parent)
+ var/list/turf/valid_turfs = list()
+ if(!center_turf)
+ CRASH("[src] had attempted to trigger, but failed to find the center turf!")
+ for(var/turf/boi in range(3,center_turf))
+ if(boi.density)
+ continue
+ valid_turfs += boi
+ var/obj/item/food/pickedmeat = pick_weight(validmeat)
+ new pickedmeat(pick(valid_turfs))
+ meat_counter++
+ if(meat_counter > round(potency/10))
+ meat_counter = 0
+ toggle_active(FALSE)
+ return
+ COOLDOWN_START(src,meat_cd,(10 SECONDS))
+
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/melee.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/melee.dm
similarity index 72%
rename from monkestation/code/modules/art_sci_overrides/artifact_components/melee.dm
rename to monkestation/code/modules/art_sci_overrides/artifact_effects/melee.dm
index ea9e5a93e826..2d64f29344e3 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/melee.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/melee.dm
@@ -2,33 +2,27 @@
#define SPECIAL_IGNITE "ignite"
#define SPECIAL_TELEPORT "teleport"
-/datum/component/artifact/melee
- associated_object = /obj/item/melee/artifact
+/datum/artifact_effect/melee
artifact_size = ARTIFACT_SIZE_SMALL
- type_name = "Melee Weapon"
+ type_name = "Melee Weapon Effect"
weight = ARTIFACT_VERYUNCOMMON //rare
- xray_result = "DENSE"
valid_activators = list(
/datum/artifact_activator/touch/silicon,
/datum/artifact_activator/range/heat,
/datum/artifact_activator/range/shock,
/datum/artifact_activator/range/radiation
)
- valid_faults = list(
- /datum/artifact_fault/ignite = 10,
- /datum/artifact_fault/warp = 10,
- /datum/artifact_fault/reagent/poison = 10,
- /datum/artifact_fault/death = 2,
- /datum/artifact_fault/tesla_zap = 5,
- /datum/artifact_fault/grow = 10,
- /datum/artifact_fault/explosion = 2,
- )
var/active_force //force when active
var/active_reach
var/active_woundbonus = 0
-/datum/component/artifact/melee/setup() //RNG incarnate
- var/obj/item/melee/artifact/weapon = holder
+ valid_type_paths = list(/obj/item/melee/artifact)
+ research_value = 500
+
+ examine_discovered = span_warning("It appears to be some sort of melee weapon")
+
+/datum/artifact_effect/melee/setup() //RNG incarnate
+ var/obj/item/melee/artifact/weapon = our_artifact.holder
weapon.special_cooldown_time = rand(3,8) SECONDS
active_force = rand(-10,30)
weapon.demolition_mod = rand(-1.0, 2.0)
@@ -58,15 +52,15 @@
potency += 15
weapon.special = pick(SPECIAL_LAUNCH, SPECIAL_IGNITE, SPECIAL_TELEPORT)
-/datum/component/artifact/melee/effect_activate()
- var/obj/item/melee/artifact/weapon = holder
+/datum/artifact_effect/melee/effect_activate()
+ var/obj/item/melee/artifact/weapon = our_artifact.holder
weapon.reach = active_reach
weapon.force = active_force
weapon.wound_bonus = active_woundbonus
weapon.throwforce = weapon.force
-/datum/component/artifact/melee/effect_deactivate()
- var/obj/item/melee/artifact/weapon = holder
+/datum/artifact_effect/melee/effect_deactivate()
+ var/obj/item/melee/artifact/weapon = our_artifact.holder
weapon.force = active_force / 3
weapon.throwforce = weapon.force
weapon.reach = 1
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/money.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/money.dm
new file mode 100644
index 000000000000..6f40d0405932
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/money.dm
@@ -0,0 +1,12 @@
+/datum/artifact_effect/lodedsamoney
+ examine_hint = "Might sell well."
+ examine_discovered = "Generates an aura of value."
+ discovered_credits = CARGO_CRATE_VALUE * 25 //LODESA
+ weight = ARTIFACT_UNCOMMON
+
+ type_name = "Economical Aura Effect"
+ research_value = 250
+
+/datum/artifact_effect/lodedsamoney/setup()
+ discovered_credits *= ((potency+50)/75)
+ discovered_credits = round(discovered_credits)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/narsieoffering.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/narsieoffering.dm
new file mode 100644
index 000000000000..6d1cc4510108
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/narsieoffering.dm
@@ -0,0 +1,52 @@
+/datum/artifact_effect/narsieoffering
+ examine_discovered = "Makes an offering to the dark gods."
+ type_name = "Dark Altar Effect"
+ weight = ARTIFACT_COMMON //Common because can only be on carbon touch narsie
+
+ examine_hint = span_warning("You feel safe and complacent around this...")
+ valid_origins = list(ORIGIN_NARSIE)
+
+ valid_activators = list(/datum/artifact_activator/touch/carbon)
+
+ research_value = 250
+
+ var/blood_to_take = 1
+
+ var/stored_blood = 0
+
+ COOLDOWN_DECLARE(force_take_cooldown)
+ ///List of valid items this artifact can spawn when full on blood (needs 5 bodys of blood.)
+ var/static/list/obj/valid_spawns = list(
+ /obj/item/soulstone/anybody = 1, //Lucky you.
+ /obj/item/clothing/suit/hooded/cultrobes = 20,
+ /obj/item/clothing/suit/hooded/cultrobes/alt = 20,
+ /obj/item/clothing/suit/hooded/cultrobes/hardened = 10,
+ /obj/item/sharpener/cult = 35,
+ /obj/item/shield/mirror = 15
+ )
+
+/datum/artifact_effect/narsieoffering/setup()
+ blood_to_take = round(rand(BLOOD_VOLUME_NORMAL*0.1,BLOOD_VOLUME_NORMAL*0.9))
+
+/datum/artifact_effect/narsieoffering/effect_touched(mob/living/user)
+ if(!COOLDOWN_FINISHED(src,force_take_cooldown))
+ to_chat(user,"You feel [our_artifact.holder] is not yet ready for what it has planned...")
+ if(!user.blood_volume || !iscarbon(user))
+ to_chat(user, span_info("You feel a need to give your non existant blood."))
+ if(user.blood_volume <= blood_to_take)
+ to_chat(user,span_info("You feel a need to give more blood, but [our_artifact.holder] deems you too weak to do so!"))
+ var/yoinked_blood = min(blood_to_take,user.blood_volume)
+ user.blood_volume -= yoinked_blood
+ stored_blood += yoinked_blood
+ to_chat(user,span_boldwarning("You are compelled to give blood to the [our_artifact.holder]; and feel your blood volume lower somehow!"))
+ COOLDOWN_START(src,force_take_cooldown,5 SECOND)
+
+ if(stored_blood >= BLOOD_VOLUME_NORMAL*5)
+ var/obj/tomake = pick_weight(valid_spawns)
+ var/obj/chosen = new tomake(our_artifact.holder.loc)
+ chosen.forceMove(our_artifact.holder.loc)
+ to_chat(user,span_info("[our_artifact.holder] is pleased with your work, and [chosen] appears from seemingly nowhere!"))
+ stored_blood -= BLOOD_VOLUME_NORMAL*5
+ return
+
+
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/plushie_vendor.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/plushie_vendor.dm
new file mode 100644
index 000000000000..9e3642f159fa
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/plushie_vendor.dm
@@ -0,0 +1,30 @@
+/datum/artifact_effect/plushie
+ examine_hint = "Has some sort of claw mechanism."
+
+ examine_discovered = "Its a claw machine of some kind"
+
+ weight = ARTIFACT_UNCOMMON
+
+ activation_message = "summons a toy of some kind!"
+
+ type_name = "Toy Vender Effect"
+ research_value = 250
+
+ var/static/list/obj/item/toy/plush/plushies = list()
+
+ COOLDOWN_DECLARE(plushiefact)
+
+/datum/artifact_effect/plushie/effect_activate(silent)
+ if(!length(plushies))
+ plushies = typecacheof(/obj/item/toy/plush,ignore_root_path = TRUE) //I am not responsible for if this is a bad idea.
+ if(!COOLDOWN_FINISHED(src,plushiefact))
+ return
+ var/obj/item/toy/plush/boi_path = pick(plushies)
+ var/obj/item/toy/plush/boi = new boi_path
+ boi.forceMove(our_artifact.holder.loc)
+ if(prob(clamp(potency-50,0,100)))
+ boi.AddComponent(/datum/component/ghost_object_control,boi,TRUE)
+ var/datum/component/ghost_object_control/spiritholder = boi.GetComponent(/datum/component/ghost_object_control)
+ if(!(spiritholder.bound_spirit))
+ spiritholder.request_control(0.6)
+ COOLDOWN_START(src,plushiefact,3 MINUTE)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_effects/repulsor.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/repulsor.dm
new file mode 100644
index 000000000000..8cefc3bbcfde
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/repulsor.dm
@@ -0,0 +1,55 @@
+
+/datum/artifact_effect/repulsor
+ weight = ARTIFACT_UNCOMMON
+ type_name = "Repulsor/Impulsor Effect"
+ activation_message = "opens up, a weird aura starts emitting from it!"
+ deactivation_message = "closes up."
+ var/attract = FALSE //if FALSE, repulse, otherwise, attract
+ var/strength
+ var/range
+ var/cooldown_time
+ COOLDOWN_DECLARE(cooldown)
+
+ research_value = 1000
+
+ examine_discovered = span_warning("It appears to be some object mover")
+
+/datum/artifact_effect/repulsor/setup()
+ attract = prob(40)
+ range = rand(1,3)
+ cooldown_time = rand(3,5) SECONDS
+ strength = rand(MOVE_FORCE_DEFAULT,MOVE_FORCE_OVERPOWERING)
+ potency += cooldown_time / 4 + strength / 3000
+
+/datum/artifact_effect/repulsor/effect_activate(silent)
+ addtimer(CALLBACK(our_artifact, TYPE_PROC_REF(/datum/component/artifact, artifact_deactivate)), 10 SECONDS)
+
+/datum/artifact_effect/repulsor/effect_touched(mob/user)
+ if(!COOLDOWN_FINISHED(src,cooldown))
+ return
+ pulse()
+ COOLDOWN_START(src,cooldown,cooldown_time)
+
+/datum/artifact_effect/repulsor/effect_process()
+ . = ..()
+ if(prob(100 - potency))
+ return
+ pulse()
+
+/datum/artifact_effect/repulsor/proc/pulse(datum/source,atom/movable/thrown, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
+ SIGNAL_HANDLER
+ if(!our_artifact.active)
+ return
+ our_artifact.holder.visible_message(span_warning("[our_artifact.holder] emits a pulse of energy, throwing things [attract ? "towards it!" : "away from it!"]"))
+ var/owner_turf = get_turf(our_artifact.holder)
+ if(isnull(thrown))
+ for(var/atom/movable/throwee in oview(range,our_artifact.holder))
+ if(throwee.anchored)
+ continue
+ if(attract)
+ throwee.safe_throw_at(our_artifact.holder, strength / 3000, 1, force = strength)
+ else
+ var/throwtarget = get_edge_target_turf(get_turf(throwee), get_dir(owner_turf, get_step_away(throwee, owner_turf)))
+ throwee.safe_throw_at(throwtarget, strength / 3000, 1, force = strength)
+ else if(throwingdatum?.thrower)
+ thrown.safe_throw_at(throwingdatum.thrower, get_dist(our_artifact.holder, throwingdatum.thrower), 1, force = strength)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/smoke_artifacts.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/smoke_artifacts.dm
similarity index 55%
rename from monkestation/code/modules/art_sci_overrides/artifact_components/smoke_artifacts.dm
rename to monkestation/code/modules/art_sci_overrides/artifact_effects/smoke_artifacts.dm
index 9255e0a53706..5a1e83890be3 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/smoke_artifacts.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/smoke_artifacts.dm
@@ -1,10 +1,13 @@
-/datum/component/artifact/smoke
- associated_object = /obj/structure/artifact/smoke
+/datum/artifact_effect/smoke
weight = ARTIFACT_UNCOMMON
- type_name = "Smoke Machine"
- activation_message = "starts spewing out smoke!"
+ type_name = "Smoke Machine (Colorful) Effect"
+ activation_message = "starts spewing out colorful smoke!"
deactivation_message = "becomes silent."
+ research_value = 250
+
+ examine_discovered = span_warning("It appears to be some sort of checmical aerolyzer for coloring things")
+
var/list/valid_chemicals = list(
/datum/reagent/colorful_reagent,
/datum/reagent/colorful_reagent/powder/black,
@@ -19,7 +22,7 @@
var/list/chemicals = list()
var/smoke_range = 3
-/datum/component/artifact/smoke/setup()
+/datum/artifact_effect/smoke/setup()
per_chemical_amount = rand(5, 10)
chemicals_chosen = rand(1, 5)
smoke_range = rand(1, 5)
@@ -28,14 +31,15 @@
for(var/i = 1 to chemicals_chosen)
chemicals += pick(valid_chemicals)
-/datum/component/artifact/smoke/effect_activate(silent)
- for(var/chemical in chemicals)
- do_chem_smoke(smoke_range, holder = holder, location = get_turf(holder), reagent_type = chemical, reagent_volume = per_chemical_amount, log = TRUE)
- artifact_deactivate()
+/datum/artifact_effect/smoke/effect_activate(silent)
+ if(our_artifact.holder)
+ for(var/chemical in chemicals)
+ do_chem_smoke(smoke_range, holder = our_artifact.holder, location = get_turf(our_artifact.holder), reagent_type = chemical, reagent_volume = per_chemical_amount, log = TRUE)
+ our_artifact.artifact_deactivate()
-/datum/component/artifact/smoke/toxin
- associated_object = /obj/structure/artifact/smoke/toxin
+/datum/artifact_effect/smoke/toxin
weight = ARTIFACT_RARE
+ type_name = "Smoke Machine (Harmful) Effect"
activation_message = "starts spewing out toxic smoke!"
valid_chemicals = list(
/datum/reagent/toxin/bonehurtingjuice,
@@ -43,19 +47,23 @@
/datum/reagent/toxin/mindbreaker,
/datum/reagent/toxin/spewium,
)
+ examine_discovered = span_danger("It appears to be some sort of checmical aerolyzer for harming things!")
-/datum/component/artifact/smoke/flesh
- associated_object = /obj/structure/artifact/smoke/flesh
+/datum/artifact_effect/smoke/flesh
+ type_name = "Smoke Machine (Synthflesh) Effect"
weight = ARTIFACT_RARE
activation_message = "starts spewing out flesh mending smoke!"
valid_chemicals = list(
/datum/reagent/medicine/c2/synthflesh
)
+ examine_discovered = span_info("It appears to be some sort of checmical aerolyzer for healing things!")
-/datum/component/artifact/smoke/exotic
- associated_object = /obj/structure/artifact/smoke/exotic
+/datum/artifact_effect/smoke/exotic
+ type_name = "Smoke Machine (Exotic) Effect"
weight = ARTIFACT_RARE
activation_message = "starts spewing out exotic smoke!"
+
+ examine_discovered = span_warning("It appears to be some sort of checmical aerolyzer for... not sure actually.")
valid_chemicals = list(
/datum/reagent/wittel,
/datum/reagent/medicine/omnizine/protozine,
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/surgery.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/surgery.dm
similarity index 52%
rename from monkestation/code/modules/art_sci_overrides/artifact_components/surgery.dm
rename to monkestation/code/modules/art_sci_overrides/artifact_effects/surgery.dm
index 8164e16fce72..c7bca8396e73 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/surgery.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/surgery.dm
@@ -1,7 +1,6 @@
-/datum/component/artifact/surgery
- associated_object = /obj/structure/artifact/surgery
+/datum/artifact_effect/surgery
weight = ARTIFACT_VERYUNCOMMON
- type_name = "Surgery Object"
+ type_name = "Surgery Object Effect"
activation_message = "springs to life!"
deactivation_message = "becomes silent."
valid_activators = list(
@@ -10,14 +9,17 @@
)
COOLDOWN_DECLARE(surgery_cooldown)
+ research_value = 1250
-/datum/component/artifact/surgery/effect_touched(mob/living/user)
+ examine_discovered = span_warning("It appears to be some sort of automated surgery device")
+
+/datum/artifact_effect/surgery/effect_touched(mob/living/user)
if(!COOLDOWN_FINISHED(src, surgery_cooldown))
- holder.visible_message(span_notice("[holder] wheezes, shutting down."))
+ our_artifact.holder.visible_message(span_notice("[our_artifact.holder] wheezes, shutting down."))
return
if(!ishuman(user))
return
var/mob/living/carbon/human/human = user
- human.bioscramble(holder.name)
+ human.bioscramble(our_artifact.holder.name)
COOLDOWN_START(src,surgery_cooldown, 5 SECONDS)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_components/vomit.dm b/monkestation/code/modules/art_sci_overrides/artifact_effects/vomit.dm
similarity index 54%
rename from monkestation/code/modules/art_sci_overrides/artifact_components/vomit.dm
rename to monkestation/code/modules/art_sci_overrides/artifact_effects/vomit.dm
index 24b901492867..b3154d75e0d4 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_components/vomit.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_effects/vomit.dm
@@ -1,7 +1,6 @@
-/datum/component/artifact/vomit
- associated_object = /obj/structure/artifact/vomit
+/datum/artifact_effect/vomit
weight = ARTIFACT_UNCOMMON
- type_name = "Vomiting Inducer"
+ type_name = "Vomiting Inducer Effect"
activation_message = "starts emitting disgusting imagery!"
deactivation_message = "falls silent, its aura dissipating!"
valid_origins = list(
@@ -15,7 +14,12 @@
var/bloody_vomit = FALSE
COOLDOWN_DECLARE(cooldown)
-/datum/component/artifact/vomit/setup()
+ research_value = 100 //To busy vomiting cant research
+
+
+ examine_discovered = span_warning("It appears to be some sort of sick prank")
+
+/datum/artifact_effect/vomit/setup()
switch(rand(1,100))
if(1 to 84)
range = rand(2,3)
@@ -29,18 +33,12 @@
potency += spew_range
bloody_vomit = prob(50)
potency += (range) * 4
- addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/component/artifact, artifact_deactivate)), round(30 * (potency * 10) SECONDS))
-/datum/component/artifact/vomit/on_examine(atom/source, mob/user, list/examine_list)
- . = ..()
- var/mob/living/carbon/carbon = user
- if(active && istype(carbon) && carbon.stat < UNCONSCIOUS)
- examine_list += span_warning("It has an [spew_organs ? "extremely" : ""] disgusting aura! [prob(20) ? "..is that a felinid?" : ""]")
- carbon.vomit(blood = bloody_vomit, stun = (spew_organs ? TRUE : prob(25)), distance = spew_range)
- if(spew_organs && prob(40))
- carbon.spew_organ()
-/datum/component/artifact/vomit/effect_process()
+/datum/artifact_effect/vomit/effect_activate(silent)
+ addtimer(CALLBACK(our_artifact, TYPE_PROC_REF(/datum/component/artifact,artifact_deactivate)),30 SECONDS)
+
+/datum/artifact_effect/vomit/effect_process()
for(var/mob/living/carbon/viewed in view(range, src))
if(prob(100 - potency))
continue
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_cell.dm b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_cell.dm
index 5f20f628b830..092275d14b2e 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_cell.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_cell.dm
@@ -4,11 +4,17 @@
resistance_flags = LAVA_PROOF | ACID_PROOF | INDESTRUCTIBLE
ratingdesc = FALSE
charge_light_type = null
- var/datum/component/artifact/assoc_comp = /datum/component/artifact/cell
+ obj_flags = CAN_BE_HIT
+ var/datum/component/artifact/assoc_comp = /datum/component/artifact
-ARTIFACT_SETUP(/obj/item/stock_parts/cell/artifact, SSobj)
+ARTIFACT_SETUP(/obj/item/stock_parts/cell/artifact, SSobj, null, /datum/artifact_effect/cell, ARTIFACT_SIZE_TINY)
/obj/item/stock_parts/cell/artifact/use(amount, force) //dont use power unless active
. = FALSE
if(assoc_comp.active)
return ..()
+
+/obj/item/stock_parts/cell/artifact/attack_self(mob/user, modifiers)
+ . = ..()
+ to_chat(user,span_notice("You squeeze the [src] tightly."))
+ on_artifact_touched(src,user,modifiers)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_effect_disk.dm b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_effect_disk.dm
new file mode 100644
index 000000000000..f1c2820e49cb
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_effect_disk.dm
@@ -0,0 +1,28 @@
+/obj/item/disk/artifact
+ name = "artifact data disk"
+ desc = "A disk for storing an artifacts effect data. Can be put into an xray machine to maybe copy artifact data, or an artifact wand for it's effect."
+ icon_state = "rndmajordisk"
+ custom_materials = list(/datum/material/iron=30, /datum/material/glass=10)
+ var/datum/artifact_effect/effect
+ var/datum/artifact_activator/activator
+ var/datum/artifact_fault/fault
+ var/read_only = FALSE //Well, it's still a floppy disk
+ obj_flags = UNIQUE_RENAME
+/obj/item/disk/artifact/update_name(updates)
+ . = ..()
+ var/newname = ""
+ if(effect)
+ newname += " ([effect.type_name]) "
+ if(activator)
+ newname += " |[activator.name]| "
+ if(fault)
+ newname += " ![fault.name]! "
+ name = initial(name) + newname
+
+/obj/item/disk/artifact/attack_self(mob/user)
+ read_only = !read_only
+ to_chat(user, "You flip the write-protect tab to [src.read_only ? "protected" : "unprotected"].")
+
+/obj/item/disk/artifact/examine(mob/user)
+ . = ..()
+ . += "The write-protect tab is set to [src.read_only ? "protected" : "unprotected"]."
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_gun.dm b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_gun.dm
index 37c02bba1e0d..f337be6fb181 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_gun.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_gun.dm
@@ -1,10 +1,21 @@
/obj/item/ammo_casing/magic/artifact
projectile_type = /obj/projectile/magic/artifact
-
+ var/datum/artifact_effect/gun/stored_comp
/obj/item/ammo_casing/magic/artifact/ready_proj(atom/target, mob/living/user, quiet, zone_override = "", atom/fired_from)
if(!loaded_projectile)
return
- var/datum/component/artifact/gun/gun = fired_from.GetComponent(/datum/component/artifact/gun)
+ var/datum/component/artifact/component = fired_from.GetComponent(/datum/component/artifact)
+ var/datum/artifact_effect/gun/gun
+ if(!stored_comp)
+ for(var/datum/artifact_effect/eff in component.artifact_effects)
+ if(istype(eff,/datum/artifact_effect/gun))
+ gun = eff
+ stored_comp = gun
+ break
+ else
+ gun = stored_comp
+ if(!gun)
+ return
loaded_projectile.damage = gun.damage / pellets
loaded_projectile.icon_state = gun.projectile_icon
loaded_projectile.damage_type = gun.dam_type
@@ -39,9 +50,15 @@
pinless = TRUE
recharge_rate = 1
antimagic_flags = null
- var/datum/component/artifact/assoc_comp = /datum/component/artifact/gun
+ obj_flags = CAN_BE_HIT
+ var/datum/component/artifact/assoc_comp = /datum/component/artifact
+
+ARTIFACT_SETUP(/obj/item/gun/magic/artifact, SSobj, null, /datum/artifact_effect/gun, ARTIFACT_SIZE_SMALL)
-ARTIFACT_SETUP(/obj/item/gun/magic/artifact, SSobj)
+/obj/item/gun/magic/artifact/attack_self(mob/user, modifiers)
+ . = ..()
+ to_chat(user,span_notice("You squeeze the [src] tightly."))
+ on_artifact_touched(src,user,modifiers)
/obj/item/gun/magic/artifact/can_shoot()
return assoc_comp.active
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_item.dm b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_item.dm
new file mode 100644
index 000000000000..e6eaf3e204db
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_item.dm
@@ -0,0 +1,37 @@
+/obj/item/artifact_item
+ //This is literally just an artifact, but item sized for item generation of traits that require it.
+
+ icon = 'icons/obj/artifacts.dmi'
+ icon_state = "narnar-1"
+ resistance_flags = LAVA_PROOF | ACID_PROOF | INDESTRUCTIBLE
+ icon = 'icons/obj/artifacts.dmi'
+ inhand_icon_state = "plasmashiv"
+ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ obj_flags = CAN_BE_HIT
+ var/datum/component/artifact/assoc_comp = /datum/component/artifact
+
+ARTIFACT_SETUP(/obj/item/artifact_item, SSobj, null, null, ARTIFACT_SIZE_SMALL)
+
+/obj/item/artifact_item/attack_self(mob/user, modifiers)
+ . = ..()
+ to_chat(user,span_notice("You squeeze the [src] tightly."))
+ on_artifact_touched(src,user,modifiers)
+
+
+/obj/item/artifact_item_tiny
+ //This is literally just an artifact, but s m o l for item generation of traits that require it.
+
+ icon = 'icons/obj/artifacts.dmi'
+ icon_state = "narnar-1"
+ resistance_flags = LAVA_PROOF | ACID_PROOF | INDESTRUCTIBLE
+ icon = 'icons/obj/artifacts.dmi'
+ var/datum/component/artifact/assoc_comp = /datum/component/artifact
+ obj_flags = CAN_BE_HIT
+
+ARTIFACT_SETUP(/obj/item/artifact_item_tiny, SSobj, null, null, ARTIFACT_SIZE_TINY)
+
+/obj/item/artifact_item_tiny/attack_self(mob/user, modifiers)
+ . = ..()
+ to_chat(user,span_notice("You squeeze the [src] tightly."))
+ on_artifact_touched(src,user,modifiers)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_manipulators.dm b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_manipulators.dm
new file mode 100644
index 000000000000..13661ae0735b
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_manipulators.dm
@@ -0,0 +1,158 @@
+/obj/item/artifact_summon_wand
+ name = "artifact manipulation wand"
+ desc = "A one-use device capable of summoning an artifact from... somewhere.Use the item in hand to change modes. Right Click a disk onto it to load the disk. Right Click the item to attempt to summon an artifact, or slap an existing one to modify it."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "memorizer2"
+ inhand_icon_state = "electronic"
+ worn_icon_state = "electronic"
+ lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi'
+ w_class = WEIGHT_CLASS_SMALL
+ slot_flags = ITEM_SLOT_BELT
+ item_flags = NOBLUDGEON
+ var/obj/item/disk/artifact/slotted_disk
+ var/selected_mode = 0
+ /// modes are- 0 = random, 1 = blank artifact,2 = disk copy, 3 = disc activator, 4 = disc fault, 5 = disc effect.
+ var/max_modes = 5
+
+/obj/item/artifact_summon_wand/attack_self(mob/user, modifiers)
+ . = ..()
+ selected_mode++
+ if(selected_mode > max_modes)
+ selected_mode = 0
+ var/display_text = "cause a bug. Tell the coders quick!"
+ switch(selected_mode)
+ if(0)
+ display_text = "create a random artifact."
+ if(1)
+ display_text = "create a blank artifact."
+ if(2)
+ display_text = "create a copy of inserted disk"
+ if(3)
+ display_text = "create or modify an artifact with just the inserted disks activator."
+ if(4)
+ display_text = "create or modify an artifact with just the inserted disks fault."
+ if(5)
+ display_text = "create or modify an artifact with just the inserted disks effect."
+ to_chat(user,span_notice("You set [src] to [display_text]"))
+
+/obj/item/artifact_summon_wand/attackby_secondary(obj/item/weapon, mob/user, params)
+ . = ..()
+ if(istype(weapon,/obj/item/disk/artifact))
+ if(slotted_disk)
+ to_chat(user,span_notice("You swap the disk inside [src]"))
+ weapon.forceMove(src)
+ if(!user.put_in_hand(slotted_disk))
+ slotted_disk.forceMove(get_turf(user))
+ slotted_disk = weapon
+ else
+ to_chat(user,span_notice("You slot [weapon] inside [src]"))
+ weapon.forceMove(src)
+ slotted_disk = weapon
+/obj/item/artifact_summon_wand/attack_self_secondary(mob/user, modifiers)
+ . = ..()
+ summon_artifact(user)
+
+/obj/item/artifact_summon_wand/proc/summon_artifact(mob/user)
+ var/turf/attempt_location = get_turf(get_step(user,user.dir))
+ if(attempt_location.density)
+ return
+ visible_message(span_notice("[user] begins to summon an artifact using [src]!"),span_notice("You begin attempting to summon an artifact using [src]..."))
+ if(do_after(user,5 SECOND))
+ var/obj/new_artifact = spawn_artifact(attempt_location)
+ var/datum/component/artifact/art_comp = new_artifact.GetComponent(/datum/component/artifact)
+ if(!art_comp)
+ visible_message(span_notice("Something goes wrong, and [src] fizzles!"))
+ return
+ switch(selected_mode)//0 left blank, as we don't need to do anything else.
+ if(1)
+ art_comp.clear_out()
+ if(2)
+ art_comp.clear_out()
+ if(slotted_disk.activator)
+ art_comp.add_activator(slotted_disk.activator)
+ if(slotted_disk.fault)
+ art_comp.change_fault(slotted_disk.fault)
+ if(slotted_disk.effect)
+ art_comp.try_add_effect(slotted_disk.effect)
+ if(3)
+ art_comp.clear_out()
+ if(slotted_disk.activator)
+ art_comp.add_activator(slotted_disk.activator)
+ if(4)
+ art_comp.clear_out()
+ if(slotted_disk.fault)
+ art_comp.change_fault(slotted_disk.fault)
+ if(5)
+ art_comp.clear_out()
+ if(slotted_disk.effect)
+ art_comp.try_add_effect(slotted_disk.effect)
+ visible_message(span_notice("[new_artifact] appears from nowhere!"),span_notice("You summon [new_artifact], and [src] disintegrates!"))
+ if(slotted_disk)
+ if(!user.put_in_active_hand(slotted_disk))
+ slotted_disk.forceMove(get_turf(user))
+ slotted_disk = null
+ qdel(src)
+ else
+ visible_message(span_notice("Something goes wrong, and [src] fizzles!"))
+
+/obj/item/artifact_summon_wand/examine(mob/user)
+ . = ..()
+ if(slotted_disk)
+ . += span_notice("Contains [slotted_disk]")
+ switch (selected_mode)
+ if(0)
+ . += span_notice("Will currently try to summon a random artifact.")
+ if(1)
+ . += span_notice("Will currently try to summon a blank artifact")
+ if(2)
+ . += span_notice("Will currently try to copy the disk to a new or existing artifact.")
+ if(3)
+ . += span_notice("Will currently try to copy the disk activator to a new or existing artifact.")
+ if(4)
+ . += span_notice("Will currently try to copy the disk fault to a new or existing artifact.")
+ if(5)
+ . += span_notice("Will currently try to copy the disk effect to a new or existing artifact.")
+
+/obj/item/artifact_summon_wand/attack_atom(atom/attacked_atom, mob/living/user, params)
+ var/datum/component/artifact/art_comp = attacked_atom.GetComponent(/datum/component/artifact)
+ if(art_comp && slotted_disk)
+ visible_message(span_notice("[user] begins trying to configure [attacked_atom] with [src]!"),span_notice("You begin trying to configure the [attacked_atom] with [src]..."))
+ if(do_after(user,5 SECOND))
+ var/added_anything = FALSE
+ switch(selected_mode)
+ if(0)
+ visible_message(span_notice("...but nothing changed!"))
+ if(1)
+ art_comp.clear_out()
+ visible_message(span_notice("[attacked_atom] is rendered inert!"))
+ added_anything = TRUE
+ if(2)
+ if(slotted_disk.activator)
+ added_anything |= art_comp.add_activator(slotted_disk.activator)
+ if(slotted_disk.fault)
+ added_anything |= art_comp.change_fault(slotted_disk.fault)
+ if(slotted_disk.effect)
+ added_anything |= art_comp.try_add_effect(slotted_disk.effect)
+ if(3)
+ if(slotted_disk.activator)
+ added_anything |= art_comp.add_activator(slotted_disk.activator)
+ if(4)
+ if(slotted_disk.fault)
+ added_anything |= art_comp.change_fault(slotted_disk.fault)
+ if(5)
+ if(slotted_disk.effect)
+ added_anything |= art_comp.try_add_effect(slotted_disk.effect)
+ if(added_anything)
+ visible_message(span_notice("[user] configures the [attacked_atom] with [src]!"),span_notice("You configure the [attacked_atom] with [src], which switftly disintegrates!"))
+ if(slotted_disk)
+ if(!user.put_in_active_hand(slotted_disk))
+ slotted_disk.forceMove(get_turf(user))
+ slotted_disk = null
+ qdel(src)
+ else
+ visible_message(span_notice("...but nothing changed!"))
+ else
+ visible_message(span_notice("Something goes wrong, and [src] fizzles!"))
+ return ..() //I TAKE NO RESPONSIBILITY FOR CALLING THIS L A S T.
+
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_melee.dm b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_melee.dm
index 3ad1b89385d4..c8ef4201b472 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_melee.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_items/artifact_melee.dm
@@ -10,12 +10,18 @@
inhand_icon_state = "plasmashiv"
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
+ obj_flags = CAN_BE_HIT
var/special_cooldown_time
var/special
- var/datum/component/artifact/assoc_comp = /datum/component/artifact/melee
+ var/datum/component/artifact/assoc_comp = /datum/component/artifact
COOLDOWN_DECLARE(special_cooldown)
-ARTIFACT_SETUP(/obj/item/melee/artifact, SSobj)
+ARTIFACT_SETUP(/obj/item/melee/artifact, SSobj, null, /datum/artifact_effect/melee, ARTIFACT_SIZE_SMALL)
+
+/obj/item/melee/artifact/attack_self(mob/user, modifiers)
+ . = ..()
+ to_chat(user,span_notice("You squeeze the [src] tightly."))
+ on_artifact_touched(src,user,modifiers)
/obj/item/melee/artifact/afterattack(mob/living/victim, mob/user, proximity)
if(!istype(victim) || !assoc_comp.active || !COOLDOWN_FINISHED(src,special_cooldown) || !special || !proximity)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_objects/artifact_powergen.dm b/monkestation/code/modules/art_sci_overrides/artifact_objects/artifact_powergen.dm
index b2a37bb18adc..b06a9c3d0a65 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_objects/artifact_powergen.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_objects/artifact_powergen.dm
@@ -10,12 +10,10 @@
circuit = null
density = TRUE
anchored = FALSE
- var/datum/component/artifact/assoc_comp = /datum/component/artifact/generator
+ var/datum/component/artifact/assoc_comp = /datum/component/artifact
+ARTIFACT_SETUP(/obj/machinery/power/generator_artifact, SSmachines, null, /datum/artifact_effect/generator, null)
-ARTIFACT_SETUP(/obj/machinery/power/generator_artifact, SSmachines)
-
-/datum/component/artifact/generator
- associated_object = /obj/machinery/power/generator_artifact
+/datum/artifact_effect/generator
type_name = "Power Generator"
weight = ARTIFACT_RARE
valid_activators = list(
@@ -29,16 +27,18 @@ ARTIFACT_SETUP(/obj/machinery/power/generator_artifact, SSmachines)
/datum/artifact_origin/precursor,
/datum/artifact_origin/martian,
) //narnar doesnt need power
+
+ valid_type_paths = list(/obj/machinery/power/generator_artifact)
+ research_value = 10000 //Holy moly lucky you!
activation_message = "begins emitting a faint, droning hum."
deactivation_message = "shortcircuits!"
- xray_result = "COMPLEX"
COOLDOWN_DECLARE(sideeffect_cooldown)
var/power_gen = 0
///does the power output fluctuate
var/unstable_generation = FALSE
-/datum/component/artifact/generator/setup() //TODO: Make this use some weird scaling math to have it pick higher numbers at lower odds
+/datum/artifact_effect/generator/setup() //TODO: Make this use some weird scaling math to have it pick higher numbers at lower odds
if(prob(65))
power_gen = rand(1 KW, MAX_POSSIBLE_GEN / 2)
else
@@ -46,42 +46,42 @@ ARTIFACT_SETUP(/obj/machinery/power/generator_artifact, SSmachines)
unstable_generation = prob(40)
potency = power_gen / (6 KW) // 100 potency at 600kw generation
-/datum/component/artifact/generator/effect_touched(mob/living/user)
- var/obj/machinery/power/generator_artifact/powerholder = holder
+/datum/artifact_effect/generator/effect_touched(mob/living/user)
+ var/obj/machinery/power/generator_artifact/powerholder = our_artifact.holder
//if on cable and not setup, connect and setup
if(!powerholder.anchored && locate(/obj/structure/cable) in get_turf(powerholder))
- powerholder.visible_message(span_warning("[holder] seems to snap to the cable!"))
+ powerholder.visible_message(span_warning("[our_artifact.holder] seems to snap to the cable!"))
playsound(get_turf(powerholder), 'sound/items/deconstruct.ogg', 50, TRUE)
powerholder.anchored = TRUE
powerholder.connect_to_network()
return
- holder.Beam(user, icon_state = "lightning[rand(1,12)]", time = 0.5 SECONDS)
+ our_artifact.holder.Beam(user, icon_state = "lightning[rand(1,12)]", time = 0.5 SECONDS)
playsound(get_turf(powerholder), 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5)
var/damage = user.electrocute_act(power_gen / 2 KW, powerholder, flags = SHOCK_NOSTUN)
- to_chat(user, span_userdanger("You are hit by a burst of electricity from [holder]!"))
+ to_chat(user, span_userdanger("You are hit by a burst of electricity from [our_artifact.holder]!"))
if(damage > 80)
- var/turf/owner_turf = get_turf(holder)
+ var/turf/owner_turf = get_turf(our_artifact.holder)
var/throwtarget = get_edge_target_turf(get_turf(user), get_dir(owner_turf, get_step_away(user, owner_turf)))
user.safe_throw_at(throwtarget, power_gen / 38 KW, 1, force = MOVE_FORCE_EXTREMELY_STRONG)
if(damage > 400 && prob(50))
- user.dust(just_ash = TRUE, drop_items = TRUE)
- artifact_deactivate() //shortcircuit
+ user.death(FALSE)
+ our_artifact.artifact_deactivate() //shortcircuit
if(prob(20)) //try to get yourself shocked with insuls many times to shortcircuit it (in retrospect this sucks)
- artifact_deactivate()
+ our_artifact.artifact_deactivate()
-/datum/component/artifact/generator/effect_process() //todo add more
- if(!holder.anchored)
+/datum/artifact_effect/generator/effect_process() //todo add more
+ if(!our_artifact.holder.anchored)
return
- var/obj/machinery/power/generator_artifact/powerholder = holder
+ var/obj/machinery/power/generator_artifact/powerholder = our_artifact.holder
powerholder.add_avail(power_gen * (unstable_generation ? rand(0.1, 1) : 1))
if(power_gen < SIDEEFFECT_THRESHOLD || !COOLDOWN_FINISHED(src,sideeffect_cooldown)) //sorry boss no can do
return
COOLDOWN_START(src,sideeffect_cooldown,rand(4,8) SECONDS)
//minor to medium side effects
if(power_gen >= (SHITFUCK_THRESHOLD / 3))
- powerholder.visible_message(span_danger("\The [holder] lets out a shower of thunder!"), span_hear("You hear a loud electrical crack!"))
+ powerholder.visible_message(span_danger("\The [our_artifact.holder] lets out a shower of thunder!"), span_hear("You hear a loud electrical crack!"))
playsound(get_turf(powerholder), 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5)
tesla_zap(powerholder, rand(2,3), power_gen / 3500)
@@ -97,12 +97,12 @@ ARTIFACT_SETUP(/obj/machinery/power/generator_artifact, SSmachines)
merger.assert_gas(/datum/gas/carbon_dioxide)
merger.gases[/datum/gas/carbon_dioxide][MOLES] = rand(10,120)
merger.temperature = rand(200,1000)
- var/turf/holder_turf = get_turf(holder)
+ var/turf/holder_turf = get_turf(our_artifact.holder)
holder_turf.assume_air(merger)
-/datum/component/artifact/generator/effect_deactivate()
- var/obj/machinery/power/generator_artifact/powerholder = holder
+/datum/artifact_effect/generator/effect_deactivate()
+ var/obj/machinery/power/generator_artifact/powerholder = our_artifact.holder
powerholder.disconnect_from_network()
powerholder.anchored = FALSE
playsound(get_turf(powerholder), 'sound/items/deconstruct.ogg', 50, TRUE)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_proto_datums.dm b/monkestation/code/modules/art_sci_overrides/artifact_proto_datums.dm
new file mode 100644
index 000000000000..be213e1102cc
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/artifact_proto_datums.dm
@@ -0,0 +1,25 @@
+/datum/design/artifact_summon_wand
+ name = "Artifact Wand"
+ desc = "A wand used to create or modify artifacts."
+ id = "artifact_wand"
+ build_type = PROTOLATHE | AWAY_LATHE
+ materials = list(/datum/material/iron =HALF_SHEET_MATERIAL_AMOUNT, /datum/material/gold =SHEET_MATERIAL_AMOUNT, /datum/material/plasma =SHEET_MATERIAL_AMOUNT * 4, /datum/material/uranium =SHEET_MATERIAL_AMOUNT)
+ build_path = /obj/item/artifact_summon_wand
+ category = list(
+ RND_CATEGORY_EQUIPMENT
+ )
+ lathe_time_factor = 0.2
+ departmental_flags = DEPARTMENT_BITFLAG_SCIENCE
+
+/datum/design/disk/artifact
+ name = "Artifact Disk"
+ desc = "A disk used to store artifact data."
+ id = "disk_artifact"
+ build_type = PROTOLATHE | AWAY_LATHE
+ materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT, /datum/material/glass = SMALL_MATERIAL_AMOUNT/2)
+ build_path = /obj/item/disk/artifact
+ category = list(
+ RND_CATEGORY_EQUIPMENT
+ )
+ lathe_time_factor = 0.1
+ departmental_flags = DEPARTMENT_BITFLAG_SCIENCE
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_testers/analysis_form.dm b/monkestation/code/modules/art_sci_overrides/artifact_testers/analysis_form.dm
index 871bd0f8eb03..7d11430f2492 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_testers/analysis_form.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_testers/analysis_form.dm
@@ -34,7 +34,8 @@
contraband = STICKER_NOSPAWN
var/chosen_origin = ""
var/list/chosentriggers = list()
- var/chosentype = ""
+ var/list/chosen_effects = list()
+ var/chosen_fault = ""
/obj/item/sticker/analysis_form/attackby(obj/item/item, mob/living/user, params)
if(istype(item, /obj/item/pen))
@@ -59,31 +60,44 @@
if("origin")
chosen_origin = params["origin"]
if("type")
- chosentype = params["type"]
+ var/trig_type = params["type"]
+ if(trig_type in chosen_effects)
+ chosen_effects -= trig_type
+ else
+ chosen_effects += trig_type
+ if("fault")
+ chosen_fault = params["fault"]
if("trigger")
- var/trig = params["trigger"]
- if(trig in chosentriggers)
- chosentriggers -= trig
+ var/trig_act = params["trigger"]
+ if(trig_act in chosentriggers)
+ chosentriggers -= trig_act
else
- chosentriggers += trig
+ chosentriggers += trig_act
if(attached)
analyze_attached()
/obj/item/sticker/analysis_form/ui_static_data(mob/user)
. = ..()
var/list/origins_names = list()
- for(var/datum/artifact_origin/subtype as anything in subtypesof(/datum/artifact_origin))
+ for(var/datum/artifact_origin/subtype as anything in subtypesof(/datum/artifact_origin))
origins_names += initial(subtype.name)
+ var/list/allfaults = list()
+ for(var/datum/artifact_fault/subtype as anything in subtypesof(/datum/artifact_fault))
+ allfaults += initial(subtype.name)
+
var/list/trigger_names = list()
for(var/datum/artifact_activator/subtype as anything in subtypesof(/datum/artifact_activator))
trigger_names += initial(subtype.name)
var/list/artifact_names = list()
- for(var/datum/component/artifact/subtype as anything in subtypesof(/datum/component/artifact))
+ for(var/datum/artifact_effect/subtype as anything in subtypesof(/datum/artifact_effect))
+ if(subtype.super_secret)
+ continue //shhhhh
artifact_names += initial(subtype.type_name)
.["allorigins"] = origins_names
+ .["allfaults"] = allfaults
.["alltypes"] = artifact_names
.["alltriggers"] = trigger_names
return
@@ -91,7 +105,8 @@
/obj/item/sticker/analysis_form/ui_data(mob/user)
. = ..()
.["chosenorigin"] = chosen_origin
- .["chosentype"] = chosentype
+ .["chosenfault"] = chosen_fault
+ .["chosentype"] = chosen_effects
.["chosentriggers"] = chosentriggers
return .
@@ -149,46 +164,60 @@
..()
/obj/item/sticker/analysis_form/proc/analyze_attached()
+ if(!attached)
+ return
var/datum/component/artifact/to_analyze = attached.GetComponent(/datum/component/artifact)
if(!to_analyze)
return
if(chosen_origin)
to_analyze.holder.name = to_analyze.generated_name
- if(chosentype)
- to_analyze.holder.name += " ([chosentype])"
+ if(chosen_fault)
+ to_analyze.holder.name += " ![chosen_fault]! "
+ if(chosen_effects)
+ for(var/effect as anything in chosen_effects)
+ to_analyze.holder.name += " ([effect]) "
+ to_analyze.analysis = src
+ to_analyze.process_stimuli(STIMULUS_DATA,TRUE)
/obj/item/sticker/analysis_form/proc/deanalyze_attached()
var/datum/component/artifact/to_analyze = attached.GetComponent(/datum/component/artifact)
if(!to_analyze)
return
to_analyze.holder.name = to_analyze.fake_name
+ QDEL_NULL(to_analyze.analysis)
/obj/item/sticker/analysis_form/proc/get_export_value(datum/component/artifact/art)
- var/correct = 0
- var/total_guesses = 0
-
+ var/baseval = CARGO_CRATE_VALUE
+ var/labeling_bonus = round(CARGO_CRATE_VALUE * 2.5)
+ var/bonus = 0
+ for(var/datum/artifact_effect/discovered as anything in art.discovered_effects)
+ if(discovered.discovered_credits)
+ bonus += round(discovered.discovered_credits * ((discovered.potency + 25)/50))
+ if(art.chosen_fault && art.fault_discovered)
+ bonus += art.chosen_fault.discovered_credits
if(art.artifact_origin.type_name == chosen_origin)
- correct ++
- if(chosen_origin)
- total_guesses ++
- if(chosentype)
- total_guesses ++
- if(art.type_name == chosentype)
- correct ++
- for(var/name in chosentriggers)
- total_guesses++
-
- for(var/datum/artifact_activator/listed in art.activators)
- if(listed.name != name)
- continue
- correct++
-
- var/incorrect = total_guesses - correct
- return round((CARGO_CRATE_VALUE/4) * art.potency * (max((ARTIFACT_COMMON - art.weight) * 0.01, 0.01) * max(correct - incorrect, 0.01)))
+ bonus += labeling_bonus
+ else
+ bonus -= labeling_bonus
+ if(chosen_effects)
+ for(var/name_effect in chosen_effects)
+ for(var/datum/artifact_effect/effect as anything in art.artifact_effects)
+ if(effect.type_name != name_effect)
+ bonus -= labeling_bonus
+ else
+ bonus += labeling_bonus
+ if(chosentriggers)
+ for(var/name_trigger in chosentriggers)
+ for(var/datum/artifact_activator/activator as anything in art.activators)
+ if(activator.name != name_trigger)
+ bonus -= labeling_bonus
+ else
+ bonus += labeling_bonus
+ return round(baseval + bonus)
/obj/item/analysis_bin
name = "analysis bin"
- desc = "A bin made out of material to resist adhesion, for artifact analysis forms."
+ desc = "A bin containing a seemingly endless supply of fourms for artifact labeling. Correctly labeled artifacts sell for more!"
icon = 'icons/obj/service/bureaucracy.dmi'
icon_state = "analysisbin1"
base_icon_state = "analysisbin"
@@ -196,33 +225,24 @@
lefthand_file = 'icons/mob/inhands/items/sheets_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items/sheets_righthand.dmi'
w_class = WEIGHT_CLASS_NORMAL
- var/forms = 15
- var/form_type = /obj/item/sticker/analysis_form
+ var/form_type = /obj/item/sticker/analysis_form
/obj/item/analysis_bin/Initialize(mapload)
. = ..()
interaction_flags_item &= ~INTERACT_ITEM_ATTACK_HAND_PICKUP
AddElement(/datum/element/drag_pickup)
-/obj/item/analysis_bin/update_icon_state()
- icon_state = "[base_icon_state][forms > 0]"
- return ..()
-
/obj/item/analysis_bin/attack_hand(mob/user, list/modifiers)
if(isliving(user))
var/mob/living/living_mob = user
if(!(living_mob.mobility_flags & MOBILITY_PICKUP))
return
- if(forms)
- forms--
- var/obj/item/form = new form_type
- form.add_fingerprint(user)
- form.forceMove(user.loc)
- user.put_in_hands(form)
- balloon_alert(user, "took form")
- update_appearance()
- else
- balloon_alert(user, "empty!")
+ var/obj/item/form = new form_type
+ form.add_fingerprint(user)
+ form.forceMove(user.loc)
+ user.put_in_hands(form)
+ balloon_alert(user, "took form")
+ update_appearance()
add_fingerprint(user)
return ..()
@@ -232,7 +252,6 @@
return
qdel(item)
balloon_alert(user, "form returned")
- forms++
update_appearance()
else
return ..()
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_testers/xray.dm b/monkestation/code/modules/art_sci_overrides/artifact_testers/xray.dm
index 70d25ee3243d..12cb72675d26 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_testers/xray.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_testers/xray.dm
@@ -1,6 +1,6 @@
/obj/machinery/artifact_xray
name = "artifact x-ray machine"
- desc = "An x-ray machine, used to scan artifacts."
+ desc = "An x-ray machine, used to scan artifacts for what they do and research them. Can be Wrenched to turn on Destructive Scan mode, which when given a disk, may record artifact data."
icon = 'icons/obj/machines/artifact_machines.dmi'
icon_state = "xray-0"
base_icon_state = "xray"
@@ -8,27 +8,59 @@
circuit = /obj/item/circuitboard/machine/artifactxray
use_power = IDLE_POWER_USE
///max radiation level
- var/max_radiation = 3
+ var/max_radiation = 4
///chosen radiation level
var/chosen_level = 1
var/pulse_time = 4 SECONDS
var/pulse_cooldown_time = 3 SECONDS
var/list/last_results = list("NO DATA")
var/pulsing = FALSE
+ var/datum/techweb/stored_research
+ ///Chance to get a disk for an artifact trait on scan. Better scanner, better chance.
+ var/disk_chance = 20
+ ///Are we going for disks, at the risk of destorying artifact?
+ var/destroy_artifact_mode = FALSE
+ ///Chance we accidentally destory the artifact on destuctive scan. Better laser, less chance.
+ var/destroy_chance = 75
+ ///The disk we have inside of us, maybe.
+ var/obj/item/disk/artifact/our_disk
COOLDOWN_DECLARE(message_cooldown)
COOLDOWN_DECLARE(pulse_cooldown)
/obj/machinery/artifact_xray/Initialize(mapload)
. = ..()
+ if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
+ connect_techweb(SSresearch.science_tech)
RefreshParts()
+/obj/machinery/artifact_xray/Destroy()
+ if(stored_research)
+ log_research("[src] disconnected from techweb [stored_research] (destroyed).")
+ stored_research = null
+ QDEL_NULL(wires)
+ return ..()
+
+
+/obj/machinery/artifact_xray/proc/connect_techweb(datum/techweb/new_techweb)
+ if(stored_research)
+ log_research("[src] disconnected from techweb [stored_research] when connected to [new_techweb].")
+ stored_research = new_techweb
+
+/obj/machinery/artifact_xray/multitool_act(mob/living/user, obj/item/multitool/tool)
+ if(!QDELETED(tool.buffer) && istype(tool.buffer, /datum/techweb))
+ connect_techweb(tool.buffer)
+ return TRUE
+ return FALSE
/obj/machinery/artifact_xray/RefreshParts()
. = ..()
var/power_usage = 250
- for(var/obj/item/stock_parts/micro_laser/laser in component_parts)
- max_radiation = round(2.5 * laser.rating)
+ for(var/datum/stock_part/micro_laser/laser in component_parts)
+ max_radiation = laser.tier
+ destroy_chance = round(75 - (15* laser.tier))
for(var/datum/stock_part/capacitor/capac in component_parts)
- power_usage -= 30 * capac.tier
+ power_usage -= round(30 * capac.tier)
+ for(var/datum/stock_part/scanning_module/scanner in component_parts)
+ disk_chance = round(20 * scanner.tier)
update_mode_power_usage(ACTIVE_POWER_USE, power_usage)
/obj/machinery/artifact_xray/update_icon_state()
@@ -39,6 +71,12 @@
. = ..()
if(!can_interact(user))
return
+ if(our_disk)
+ to_chat(user,"You eject the [our_disk.name]")
+ if(!user.put_in_active_hand(our_disk))
+ our_disk.forceMove(get_turf(user))
+ our_disk = null
+ return
toggle_open()
/obj/machinery/artifact_xray/proc/toggle_open()
if(!COOLDOWN_FINISHED(src,pulse_cooldown))
@@ -49,14 +87,29 @@
else
flick("xray-opening", src)
open_machine()
+ if(our_disk)
+ our_disk.forceMove(src)//Hacky way of keeping the disk inside.
/obj/machinery/artifact_xray/attackby(obj/item/item, mob/living/user, params)
if(HAS_TRAIT(item, TRAIT_NODROP))
to_chat(user, span_warning("[item] is stuck to your hand, you can't put it inside [src]!"))
return
- if(state_open && COOLDOWN_FINISHED(src,pulse_cooldown))
- close_machine(item)
+ if(istype(item,/obj/item/disk/artifact))
+ if(our_disk)
+ to_chat(user,"You swap [our_disk.name] for [item.name]")
+ if(!user.put_in_inactive_hand(our_disk))
+ our_disk.forceMove(get_turf(user))
+ item.forceMove(src)
+ our_disk = item
+ else
+ to_chat(user,"You insert [item.name]")
+ item.forceMove(src)
+ our_disk = item
return
+ if(state_open)
+ if(COOLDOWN_FINISHED(src,pulse_cooldown))
+ close_machine(item)
+ return
..()
/obj/machinery/artifact_xray/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
@@ -89,7 +142,7 @@
return
if(isliving(occupant))
if(!(obj_flags & EMAGGED))
- say("Cannot pulse with a living being inside!")
+ say("ERROR: Life-signs detected in chamber!")
return
var/datum/component/artifact/component = occupant.GetComponent(/datum/component/artifact)
if(component)
@@ -106,11 +159,52 @@
playsound(loc, 'sound/machines/chime.ogg', 30, FALSE)
COOLDOWN_START(src,pulse_cooldown,pulse_cooldown_time)
pulsing = FALSE
- if(artifact)
- last_results = list("STRUCTURAL ABNORMALITY ANALYSIS: [artifact.xray_result]", "SIZE: [artifact.artifact_size < ARTIFACT_SIZE_LARGE ? "SMALL" : "LARGE" ]")
+ if(artifact && stored_research)
+ var/research_added = 0
+ if(!artifact.fault_discovered && artifact.chosen_fault)
+ artifact.freebies = 0 //No more freebies, you know what it does now.
+ artifact.fault_discovered = TRUE
+ research_added += artifact.chosen_fault.research_value
+ if(artifact.chosen_fault)
+ last_results = list("ARTIFACT FAULT DISCOVERED: [artifact.chosen_fault.name]", "SIZE: [artifact.artifact_size < ARTIFACT_SIZE_LARGE ? "SMALL" : "LARGE" ]")
+ else
+ research_added += 2500
+ last_results = list("FLAWLESS ARTIFACT. NO FAULTS.", "SIZE: [artifact.artifact_size < ARTIFACT_SIZE_LARGE ? "SMALL" : "LARGE" ]")
+ if(length(artifact.discovered_effects) != length(artifact.artifact_effects))
+ for(var/datum/artifact_effect/eff in artifact.artifact_effects)
+ artifact.discovered_effects += eff.type
+ research_added += eff.research_value
+ last_results += "ARTIFACT EFFECTS REVEALED."
+ if(!length(artifact.artifact_effects))
+ last_results += "MUNDANE ARTIFACT DETECTED. NO NOTEABLE EFFECTS."
+ if(length(artifact.activators) != length(artifact.activators))
+ for(var/datum/artifact_activator/activator in artifact.activators)
+ artifact.discovered_activators += activator.type
+ research_added += activator.research_value
+ last_results += "ARTIFACT ACTIVATORS REVEALED."
+ last_results+= "WARNING: ARTIFACT FAULT NOW ACTIVE."
+ if(research_added > 0 && !artifact.researched)
+ artifact.researched = TRUE
+ src.visible_message(span_notice("[src] blares: ") + span_robot("ARTIFACT RESEARCHED:[research_added] ADDED TO LINKED CONSOLE"))
+ stored_research.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = research_added))
+ if(our_disk && destroy_artifact_mode)
+ destructive_scan_artifact(artifact)
else
- last_results = list("INCONCLUSIVE;", "NO SPECIAL PROPERTIES DETECTED")
-
+ last_results = list("INCONCLUSIVE;", "NO SPECIAL PROPERTIES DETECTED OR NO RESEARCH CONSOLE LINKED.")
+ return
+
+/obj/machinery/artifact_xray/proc/destructive_scan_artifact(datum/component/artifact/the_artifact)
+ if(prob(disk_chance + (5*chosen_level)))
+ our_disk.effect = pick(the_artifact.artifact_effects)
+ our_disk.activator = pick(the_artifact.activators)
+ if(prob(100-destroy_chance)) //Better scanners means better chance of NOT getting fault
+ our_disk.fault = the_artifact.chosen_fault
+ our_disk.update_name()
+ src.visible_message(span_robot("NOTICE: DATA DISK RECORDED."))
+ if(prob(destroy_chance + round(2.5 * chosen_level)))
+ the_artifact.clear_out()
+ src.visible_message(span_robot("WARNING: ARTIFACT RENDERED INERT."))
+ return
/obj/machinery/artifact_xray/ui_data(mob/user)
. = ..()
@@ -145,11 +239,17 @@
else if(!occupant_atom.anchored)
return TRUE
-/obj/machinery/artifact_xray/screwdriver_act(mob/living/user, obj/item/tool)
+/obj/machinery/artifact_xray/wrench_act(mob/living/user, obj/item/tool)
if(pulsing)
return TOOL_ACT_SIGNAL_BLOCKING
- . = default_deconstruction_screwdriver(user, base_icon_state, base_icon_state, tool)
+ destroy_artifact_mode = !destroy_artifact_mode
+ var/modestring = destroy_artifact_mode ? "DESTRUCTIVE SCAN" : "NON-DESTRUCTIVE SCAN"
+ to_chat(user,span_notice("[src] switched to [modestring] mode."))
+ return TOOL_ACT_MELEE_CHAIN_BLOCKING
+
+/obj/machinery/artifact_xray/screwdriver_act(mob/living/user, obj/item/tool)
+ return pulsing ? TOOL_ACT_SIGNAL_BLOCKING : default_deconstruction_screwdriver(user, "xray-maint", "xray-1", tool)
/obj/machinery/artifact_xray/crowbar_act(mob/living/user, obj/item/tool)
return pulsing ? TOOL_ACT_SIGNAL_BLOCKING : default_deconstruction_crowbar(tool)
diff --git a/monkestation/code/modules/art_sci_overrides/artifact_testers/zapper.dm b/monkestation/code/modules/art_sci_overrides/artifact_testers/zapper.dm
index b877d2b4fe91..ca12f10a415c 100644
--- a/monkestation/code/modules/art_sci_overrides/artifact_testers/zapper.dm
+++ b/monkestation/code/modules/art_sci_overrides/artifact_testers/zapper.dm
@@ -1,6 +1,6 @@
/obj/machinery/artifact_zapper
name = "artifact zapper"
- desc = "A directed tesla coil, zaps the artifact that it is facing. VERY power-consuming."
+ desc = "A directed tesla coil, zaps the object that it is facing. VERY power-consuming. Can attempt to turn artifacts into wands if hit with a multi-tool."
icon = 'icons/obj/machines/artifact_machines.dmi'
icon_state = "zapper"
base_icon_state = "zapper"
@@ -12,6 +12,8 @@
///chosen level
var/chosen_level = 100
var/pulse_cooldown_time = 4 SECONDS
+
+ var/into_wand_mode = FALSE
COOLDOWN_DECLARE(pulse_cooldown)
/obj/machinery/artifact_zapper/Initialize(mapload)
@@ -59,14 +61,21 @@
component = object.GetComponent(/datum/component/artifact)
if(component)
break
-
if(!component)
return
Beam(component.parent, icon_state="lightning[rand(1,12)]", time = pulse_cooldown_time)
playsound(get_turf(src), 'sound/magic/lightningshock.ogg', 60, TRUE, extrarange = 2)
use_power(chosen_level)
- component.process_stimuli(STIMULUS_SHOCK, chosen_level)
+ if(!into_wand_mode)
+ component.process_stimuli(STIMULUS_SHOCK, chosen_level)
+ else
+ if(prob(round(chosen_level/100)))
+ var/obj/item/artifact_summon_wand/wand = new(target_turf)
+ visible_message("[component.holder] is shocked into [wand]!")
+ else
+ visible_message("[component.holder] is shocked into oblivion!")
+ qdel(component.holder)
COOLDOWN_START(src,pulse_cooldown, pulse_cooldown_time)
@@ -84,11 +93,20 @@
to_chat(user,span_notice("You short out the safety sensors on the [src]."))
playsound(src, SFX_SPARKS, 75, TRUE, SILENCED_SOUND_EXTRARANGE)
+
+/obj/machinery/artifact_zapper/multitool_act(mob/living/user, obj/item/tool)
+ if(!COOLDOWN_FINISHED(src,pulse_cooldown))
+ return TOOL_ACT_SIGNAL_BLOCKING
+ into_wand_mode = !into_wand_mode
+ visible_message(span_info("[src] switches to [into_wand_mode ? "attempting to break down artifacts." : "just zapping artifacts." ]"))
+ return TOOL_ACT_MELEE_CHAIN_BLOCKING
/obj/machinery/artifact_zapper/screwdriver_act(mob/living/user, obj/item/tool)
if(!COOLDOWN_FINISHED(src,pulse_cooldown))
return TOOL_ACT_SIGNAL_BLOCKING
. = default_deconstruction_screwdriver(user, base_icon_state, base_icon_state, tool)
-
/obj/machinery/artifact_zapper/crowbar_act(mob/living/user, obj/item/tool)
return !COOLDOWN_FINISHED(src,pulse_cooldown) ? TOOL_ACT_SIGNAL_BLOCKING : default_deconstruction_crowbar(tool)
+
+/obj/machinery/artifact_zapper/wrench_act_secondary(mob/living/user, obj/item/tool)
+ return !COOLDOWN_FINISHED(src,pulse_cooldown) ? TOOL_ACT_SIGNAL_BLOCKING : default_unfasten_wrench(user, tool)
diff --git a/monkestation/code/modules/art_sci_overrides/faults/_fault.dm b/monkestation/code/modules/art_sci_overrides/faults/_fault.dm
index 607340139449..ee1961047340 100644
--- a/monkestation/code/modules/art_sci_overrides/faults/_fault.dm
+++ b/monkestation/code/modules/art_sci_overrides/faults/_fault.dm
@@ -4,12 +4,30 @@
var/visible_message
///the chance of us triggering on bad info
var/trigger_chance = 0
+ //how many credits do we get for discovering this? Should be negative.
+ var/discovered_credits = 0
+ //If availible, warns users that this WILL fuck you up. Picks randomly from list
+ var/list/inspect_warning
+ ///Added by xray machine when discovered.
+ var/research_value = 0
+ ///How likely the fault is to roll.
+ var/weight = ARTIFACT_COMMON
+ ///Our Artifact
+ var/datum/component/artifact/our_artifact
-/datum/artifact_fault/proc/on_trigger(datum/component/artifact/component)
+///called when the artifact gets a stimulus, and passes its trigger chance effect.
+/datum/artifact_fault/proc/on_trigger()
+ return
+
+///Called when the artifact trait comes into existance
+/datum/artifact_fault/proc/on_added()
return
/datum/artifact_fault/shutdown
- name = "Generic Shutdown Fault"
+ name = "Random Shutdown Fault"
+ visible_message = "has something malfunction and shuts down!"
+ trigger_chance = 1
+
/datum/artifact_fault/on_trigger(datum/component/artifact/component)
if(component.active)
diff --git a/monkestation/code/modules/art_sci_overrides/faults/bioscrambler.dm b/monkestation/code/modules/art_sci_overrides/faults/bioscrambler.dm
new file mode 100644
index 000000000000..f6ee86615c5e
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/faults/bioscrambler.dm
@@ -0,0 +1,21 @@
+/datum/artifact_fault/bioscramble
+ name = "Bioscrambling Fault"
+ trigger_chance = 3
+ visible_message = "corrupts nearby biological life!"
+
+ inspect_warning = list(span_danger("It looks like its made of patchwork flesh!"),
+ span_danger("It looks Frankenstien like!"))
+
+ research_value = 250
+
+ weight = ARTIFACT_UNCOMMON
+
+/datum/artifact_fault/bioscramble/on_trigger()
+ var/center_turf = get_turf(our_artifact.parent)
+
+ if(!center_turf)
+ CRASH("[src] had attempted to trigger, but failed to find the center turf!")
+
+ for(var/mob/living/carbon/mob in range(rand(3, 4), center_turf))
+ for(var/i in 1 to 3)
+ mob.bioscramble(our_artifact.holder)
diff --git a/monkestation/code/modules/art_sci_overrides/faults/clowning.dm b/monkestation/code/modules/art_sci_overrides/faults/clowning.dm
new file mode 100644
index 000000000000..891e99e825ab
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/faults/clowning.dm
@@ -0,0 +1,19 @@
+/datum/artifact_fault/clown
+ name = "Funny Fault"
+ trigger_chance = 5
+ inspect_warning = list("Smells faintly of bananas","Looks Funny.","Hates mimes.")
+ visible_message = "summons a portal to the HONK DIMENSION!"
+ discovered_credits = -500
+ research_value = 250
+
+ weight = ARTIFACT_VERYRARE
+
+/datum/artifact_fault/clown/on_trigger()
+ var/center_turf = get_turf(our_artifact.parent)
+
+ if(!center_turf)
+ CRASH("[src] had attempted to trigger, but failed to find the center turf!")
+
+ var/obj/structure/spawner/clown/hehe = new(src)
+
+ addtimer(CALLBACK(hehe,PROC_REF(Destroy)),3 MINUTE)
diff --git a/monkestation/code/modules/art_sci_overrides/faults/explosion.dm b/monkestation/code/modules/art_sci_overrides/faults/explosion.dm
index f7c028e58860..e75032695910 100644
--- a/monkestation/code/modules/art_sci_overrides/faults/explosion.dm
+++ b/monkestation/code/modules/art_sci_overrides/faults/explosion.dm
@@ -1,12 +1,16 @@
/datum/artifact_fault/explosion
- name = "Explode"
+ name = "Exploding Fault"
trigger_chance = 3
visible_message = "reaches a catastrophic overload, cracks forming at its surface!"
-/datum/artifact_fault/explosion/on_trigger(datum/component/artifact/component)
- component.holder.Shake(duration = 5 SECONDS, shake_interval = 0.08 SECONDS)
- addtimer(CALLBACK(src, PROC_REF(payload), component), 5 SECONDS)
+ research_value = 500 //nanotrasen always likes weapons IMO
-/datum/artifact_fault/explosion/proc/payload(datum/component/artifact/component)
- explosion(component.holder, light_impact_range = 2, explosion_cause = src)
- qdel(component.holder)
+ weight = ARTIFACT_UNCOMMON
+
+/datum/artifact_fault/explosion/on_trigger()
+ our_artifact.holder.Shake(duration = 5 SECONDS, shake_interval = 0.08 SECONDS)
+ addtimer(CALLBACK(src, PROC_REF(payload), our_artifact), 5 SECONDS)
+
+/datum/artifact_fault/explosion/proc/payload()
+ explosion(our_artifact.holder, light_impact_range = 2, explosion_cause = src)
+ qdel(our_artifact.holder)
diff --git a/monkestation/code/modules/art_sci_overrides/faults/greg.dm b/monkestation/code/modules/art_sci_overrides/faults/greg.dm
new file mode 100644
index 000000000000..84b18480cf62
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/faults/greg.dm
@@ -0,0 +1,16 @@
+/datum/artifact_fault/greg
+ name = "Greg Fault"
+ discovered_credits = 250
+ research_value = 1000
+ trigger_chance = 5
+ weight = ARTIFACT_RARE
+
+/datum/artifact_fault/greg/on_added()
+ our_artifact.holder.AddComponent(/datum/component/ghost_object_control,our_artifact.holder,TRUE)
+
+/datum/artifact_fault/greg/on_trigger()
+ var/datum/component/ghost_object_control/spiritholder = our_artifact.holder.GetComponent(/datum/component/ghost_object_control)
+
+ if(!(spiritholder.bound_spirit))
+ spiritholder.request_control(0.8)
+
diff --git a/monkestation/code/modules/art_sci_overrides/faults/ignite.dm b/monkestation/code/modules/art_sci_overrides/faults/ignite.dm
index 631f17f850ae..be0cb8498d11 100644
--- a/monkestation/code/modules/art_sci_overrides/faults/ignite.dm
+++ b/monkestation/code/modules/art_sci_overrides/faults/ignite.dm
@@ -1,10 +1,14 @@
/datum/artifact_fault/ignite
- name = "Combust"
- trigger_chance = 9
+ name = "Combustion Fault"
+ trigger_chance = 10
visible_message = "starts rapidly heating up while covering everything around it in something that seems to be oil."
-/datum/artifact_fault/ignite/on_trigger(datum/component/artifact/component)
- var/center_turf = get_turf(component.parent)
+ research_value = 200
+
+ weight = ARTIFACT_UNCOMMON
+
+/datum/artifact_fault/ignite/on_trigger()
+ var/center_turf = get_turf(our_artifact.parent)
if(!center_turf)
CRASH("[src] had attempted to trigger, but failed to find the center turf!")
diff --git a/monkestation/code/modules/art_sci_overrides/faults/just_death.dm b/monkestation/code/modules/art_sci_overrides/faults/just_death.dm
index 8b7b2f8d3c45..c2585b17aef3 100644
--- a/monkestation/code/modules/art_sci_overrides/faults/just_death.dm
+++ b/monkestation/code/modules/art_sci_overrides/faults/just_death.dm
@@ -1,21 +1,29 @@
/datum/artifact_fault/death
- name = "Instant Death"
- trigger_chance = 1
+ name = "Instant Death Fault"
+ trigger_chance = 50 //God forbid this actually rolls on a touch artifact,like it did during my testing.
visible_message = "blows someone up with mind."
+ inspect_warning = list(span_danger("The grim reapers scythe seems to be reflected in its surface!"),
+ span_danger("An Aura of death surrounds this object!"),
+ span_danger("I'd bet 50/50 someone dies if this turns on!"))
-/datum/artifact_fault/death/on_trigger(datum/component/artifact/component)
+ research_value = 10000 //Wow, this would make a fucking amazing weapon
+
+ weight = ARTIFACT_VERYRARE
+/datum/artifact_fault/death/on_trigger()
var/list/mobs = list()
var/mob/living/carbon/human
- var/center_turf = get_turf(component.parent)
+ var/center_turf = get_turf(our_artifact.parent)
if(!center_turf)
CRASH("[src] had attempted to trigger, but failed to find the center turf!")
- for(var/mob/living/carbon/mob in range(rand(3, 4), center_turf))
+ for(var/mob/living/carbon/mob in range(rand(2, 3), center_turf))
mobs += mob
+ if(!length(mobs))
+ return
human = pick(mobs)
if(!human)
return
- component.holder.Beam(human, icon_state = "lightning[rand(1,12)]", time = 0.5 SECONDS)
+ our_artifact.holder.Beam(human, icon_state = "lightning[rand(1,12)]", time = 0.5 SECONDS)
human.death(FALSE)
diff --git a/monkestation/code/modules/art_sci_overrides/faults/monkey_mode.dm b/monkestation/code/modules/art_sci_overrides/faults/monkey_mode.dm
new file mode 100644
index 000000000000..753de53424a5
--- /dev/null
+++ b/monkestation/code/modules/art_sci_overrides/faults/monkey_mode.dm
@@ -0,0 +1,34 @@
+/datum/artifact_fault/monkey_mode
+ name = "Simian Spawner Fault"
+ trigger_chance = 5
+ visible_message = "summons a mass of simians!"
+
+ research_value = 250
+
+ weight = ARTIFACT_VERYUNCOMMON
+
+/datum/artifact_fault/monkey_mode/on_trigger()
+ var/monkey = rand(1,4)
+ var/center_turf = get_turf(our_artifact.parent)
+ var/list/turf/valid_turfs = list()
+ if(!center_turf)
+ CRASH("[src] had attempted to trigger, but failed to find the center turf!")
+ for(var/turf/boi in range(rand(3,6),center_turf))
+ if(boi.density)
+ continue
+ valid_turfs += boi
+ for(var/i in 1 to monkey)
+ var/turf/spawnon = pick(valid_turfs)
+ valid_turfs -= spawnon
+ var/pain = roll(1,100)
+ var/mob/living/M //For monkey
+ switch(pain)
+ if(1 to 75)
+ M = new /mob/living/carbon/human/species/monkey/angry(spawnon)
+ if(75 to 95)
+ M = new /mob/living/basic/gorilla(spawnon)
+ if(95 to 100)
+ M = new /mob/living/basic/gorilla/lesser(spawnon)//OH GOD ITS TINY
+ if(M) //Just in case.
+ M.forceMove(spawnon)
+
diff --git a/monkestation/code/modules/art_sci_overrides/faults/reagents.dm b/monkestation/code/modules/art_sci_overrides/faults/reagents.dm
index c2ab103e18cb..1b9840223db5 100644
--- a/monkestation/code/modules/art_sci_overrides/faults/reagents.dm
+++ b/monkestation/code/modules/art_sci_overrides/faults/reagents.dm
@@ -1,15 +1,17 @@
/datum/artifact_fault/reagent
- name = "Generic Reagent Injector"
+ name = "Chemical Force Injector Fault"
trigger_chance = 15
visible_message = "shoots a syringe out."
var/list/reagents = list()
-/datum/artifact_fault/reagent/on_trigger(datum/component/artifact/component)
+ research_value = 100
+
+/datum/artifact_fault/reagent/on_trigger()
. = ..()
if(!length(reagents))
return
- var/center_turf = get_turf(component.parent)
+ var/center_turf = get_turf(our_artifact.parent)
if(!center_turf)
CRASH("[src] had attempted to trigger, but failed to find the center turf!")
@@ -21,7 +23,7 @@
/datum/artifact_fault/reagent/poison
name = "Poison"
-/datum/artifact_fault/reagent/poison/on_trigger(datum/component/artifact/component)
+/datum/artifact_fault/reagent/poison/on_trigger()
if(!reagents.len) //mostly copied from reagents.dm but oh well
for(var/datum/reagent/reagent as anything in subtypesof(/datum/reagent/toxin))
if(initial(reagent.chemical_flags) & REAGENT_CAN_BE_SYNTHESIZED)
diff --git a/monkestation/code/modules/art_sci_overrides/faults/say.dm b/monkestation/code/modules/art_sci_overrides/faults/say.dm
index fca9f1d6e653..f9b56de690a1 100644
--- a/monkestation/code/modules/art_sci_overrides/faults/say.dm
+++ b/monkestation/code/modules/art_sci_overrides/faults/say.dm
@@ -1,19 +1,21 @@
/datum/artifact_fault/speech
- name = "Generic Speech"
- trigger_chance = 30
- var/list/speech = list()
+ name = "Talkative Fault"
+ trigger_chance = 25
+ var/list/speech = list("Hello there.","I see you.","I know what you've done.","So hows your shift?","HELP ARTIFACT IS MAKING ME SPEAK","All is one.","One is all.")
-/datum/artifact_fault/speech/on_trigger(datum/component/artifact/component)
+ research_value = 50
+
+/datum/artifact_fault/speech/on_trigger()
if(!length(speech))
return
- var/center_turf = get_turf(component.parent)
+ var/center_turf = get_turf(our_artifact.parent)
if(!center_turf)
CRASH("[src] had attempted to trigger, but failed to find the center turf!")
for(var/mob/living/living in range(rand(7, 10), center_turf))
- if(prob(50))
+ if(prob(10))
living.say("; [pick(speech)]")
else
living.say("[pick(speech)]")
diff --git a/monkestation/code/modules/art_sci_overrides/faults/size_change.dm b/monkestation/code/modules/art_sci_overrides/faults/size_change.dm
index 847a555801ef..cfe4599826c4 100644
--- a/monkestation/code/modules/art_sci_overrides/faults/size_change.dm
+++ b/monkestation/code/modules/art_sci_overrides/faults/size_change.dm
@@ -1,33 +1,40 @@
/datum/artifact_fault/shrink
- name = "Shrink"
+ name = "Shrinking Fault"
trigger_chance = 13
visible_message = "starts to shrink."
-/datum/artifact_fault/shrink/on_trigger(datum/component/artifact/component)
- component.holder.transform = matrix(component.holder.transform, 0.9, 0.9, MATRIX_SCALE)
- if(!isstructure(component.holder))
+ research_value = 200
+
+/datum/artifact_fault/shrink/on_trigger()
+ our_artifact.holder.transform = matrix(our_artifact.holder.transform, 0.9, 0.9, MATRIX_SCALE)
+ if(!isstructure(our_artifact.holder))
return
- var/obj/structure/structure = component.holder
+ var/obj/structure/structure = our_artifact.holder
structure.w_class--
if(structure.w_class < WEIGHT_CLASS_TINY)
- component.holder.visible_message("[component.holder] vanishes into thin air!")
- qdel(component.holder)
+ our_artifact.holder.visible_message("[our_artifact.holder] vanishes into thin air!")
+ qdel(our_artifact.holder)
/datum/artifact_fault/grow
- name = "Grow"
+ name = "Growing Fault"
trigger_chance = 13
visible_message = "starts to grow."
-/datum/artifact_fault/grow/on_trigger(datum/component/artifact/component)
- if(!isitem(component.holder))
+ var/trigger_count = 0
+/datum/artifact_fault/grow/on_trigger()
+ trigger_count++
+ if(trigger_count<5)
+ our_artifact.holder.transform = matrix(our_artifact.holder.transform, 1.1, 1.1, MATRIX_SCALE)
+ else
+ our_artifact.holder.visible_message("[our_artifact.holder] can't possibly grow any larger!")
+ return
+ if(!isitem(our_artifact.holder))
return
- var/obj/item/item = component.holder
+ var/obj/item/item = our_artifact.holder
if(item.w_class > WEIGHT_CLASS_HUGE)
return
- component.holder.transform = matrix(component.holder.transform, 1.1, 1.1, MATRIX_SCALE)
-
item.w_class++
if(item.w_class > WEIGHT_CLASS_HUGE)
- component.holder.visible_message("[component.holder] becomes to cumbersome to carry!")
- component.holder.anchored = TRUE
+ our_artifact.holder.visible_message("[our_artifact.holder] becomes to cumbersome to carry!")
+ our_artifact.holder.anchored = TRUE
diff --git a/monkestation/code/modules/art_sci_overrides/faults/warps.dm b/monkestation/code/modules/art_sci_overrides/faults/warps.dm
index 6014fc2a03eb..72b8b99fbce4 100644
--- a/monkestation/code/modules/art_sci_overrides/faults/warps.dm
+++ b/monkestation/code/modules/art_sci_overrides/faults/warps.dm
@@ -1,14 +1,18 @@
/datum/artifact_fault/warp
- name = "Generic Warp Artifact"
+ name = "Warping Fault"
trigger_chance = 12
visible_message = "warps space sending everyone away."
var/list/warp_areas = list()
-/datum/artifact_fault/warp/on_trigger(datum/component/artifact/component)
+ research_value = 250
+
+ weight = ARTIFACT_UNCOMMON
+
+/datum/artifact_fault/warp/on_trigger()
if(!length(warp_areas))
warp_areas = GLOB.the_station_areas
var/turf/safe_turf = get_safe_random_station_turf(warp_areas)
- var/center_turf = get_turf(component.parent)
+ var/center_turf = get_turf(our_artifact.parent)
if(!center_turf)
CRASH("[src] had attempted to trigger, but failed to find the center turf!")
diff --git a/monkestation/code/modules/art_sci_overrides/faults/whispers.dm b/monkestation/code/modules/art_sci_overrides/faults/whispers.dm
index b85fd5b57427..727c88a3f55c 100644
--- a/monkestation/code/modules/art_sci_overrides/faults/whispers.dm
+++ b/monkestation/code/modules/art_sci_overrides/faults/whispers.dm
@@ -1,13 +1,15 @@
/datum/artifact_fault/whisper
- name = "Generic Whisper"
- trigger_chance = 30
- var/list/whispers = list()
+ name = "Wispering Fault"
+ trigger_chance = 75
+ var/list/whispers = list("Help me!","I've seen your sins","Egg.")
-/datum/artifact_fault/whisper/on_trigger(datum/component/artifact/component)
+ research_value = 50
+
+/datum/artifact_fault/whisper/on_trigger()
if(!length(whispers))
return
- var/center_turf = get_turf(component.parent)
+ var/center_turf = get_turf(our_artifact.parent)
if(!center_turf)
CRASH("[src] had attempted to trigger, but failed to find the center turf!")
diff --git a/monkestation/code/modules/art_sci_overrides/faults/zap.dm b/monkestation/code/modules/art_sci_overrides/faults/zap.dm
index 303bb44c248c..e09cadc74f5b 100644
--- a/monkestation/code/modules/art_sci_overrides/faults/zap.dm
+++ b/monkestation/code/modules/art_sci_overrides/faults/zap.dm
@@ -1,8 +1,23 @@
/datum/artifact_fault/tesla_zap
- name = "Tesla Zap"
+ name = "Energetic Discharge Fault"
trigger_chance = 12
- visible_message = "discharges a large amount of electricity."
+ visible_message = "discharges a large amount of electricity!"
-/datum/artifact_fault/tesla_zap/on_trigger(datum/component/artifact/component)
- . = ..()
- tesla_zap(component.holder, rand(4, 7), ZAP_MOB_DAMAGE)
+ research_value = 200
+
+ weight = ARTIFACT_RARE
+
+/datum/artifact_fault/tesla_zap/on_trigger()
+ var/list/mobs = list()
+
+ var/center_turf = get_turf(our_artifact.parent)
+
+ if(!center_turf)
+ CRASH("[src] had attempted to trigger, but failed to find the center turf!")
+ var/shock_range = rand(4, 7)
+ for(var/mob/living/carbon/mob in range(shock_range, center_turf))
+ mobs += mob
+ if(!length(mobs))
+ return
+
+ tesla_zap(our_artifact.holder, shock_range, ZAP_MOB_DAMAGE,shocked_targets = mobs)
diff --git a/monkestation/code/modules/art_sci_overrides/generic_artifact_objects.dm b/monkestation/code/modules/art_sci_overrides/generic_artifact_objects.dm
index 6443ef06db38..3192c5dd3e98 100644
--- a/monkestation/code/modules/art_sci_overrides/generic_artifact_objects.dm
+++ b/monkestation/code/modules/art_sci_overrides/generic_artifact_objects.dm
@@ -6,10 +6,11 @@
resistance_flags = LAVA_PROOF | ACID_PROOF | INDESTRUCTIBLE
anchored = FALSE
density = TRUE
- var/datum/component/artifact/assoc_comp
+ var/datum/artifact_effect/forced_effect
+ var/datum/component/artifact/assoc_comp = /datum/component/artifact
var/mutable_appearance/extra_effect
-ARTIFACT_SETUP(/obj/structure/artifact, SSobj)
+ARTIFACT_SETUP(/obj/structure/artifact, SSobj, null, forced_effect, null)
/obj/effect/artifact_spawner
name = "Random Artifact Spawner"
@@ -22,54 +23,54 @@ ARTIFACT_SETUP(/obj/structure/artifact, SSobj)
qdel(src)
/obj/structure/artifact/bonk
- assoc_comp = /datum/component/artifact/bonk
+ forced_effect = /datum/artifact_effect/bonk
/obj/structure/artifact/bomb
- assoc_comp = /datum/component/artifact/bomb/explosive
+ forced_effect = /datum/artifact_effect/bomb/explosive
/obj/structure/artifact/bomb/devastating
- assoc_comp = /datum/component/artifact/bomb/explosive/devastating
+ forced_effect = /datum/artifact_effect/bomb/explosive/devastating
/obj/structure/artifact/bomb/gas
- assoc_comp = /datum/component/artifact/bomb/gas
+ forced_effect = /datum/artifact_effect/bomb/gas
/obj/structure/artifact/forcegen
- assoc_comp = /datum/component/artifact/forcegen
+ forced_effect = /datum/artifact_effect/forcegen
/obj/structure/artifact/heal
- assoc_comp = /datum/component/artifact/heal
+ forced_effect = /datum/artifact_effect/heal
/obj/structure/artifact/injector
- assoc_comp = /datum/component/artifact/injector
+ forced_effect = /datum/artifact_effect/injector
/obj/structure/artifact/lamp
- assoc_comp = /datum/component/artifact/lamp
+ forced_effect = /datum/artifact_effect/lamp
light_system = OVERLAY_LIGHT
light_on = FALSE
/obj/structure/artifact/repulsor
- assoc_comp = /datum/component/artifact/repulsor
+ forced_effect = /datum/artifact_effect/repulsor
/obj/structure/artifact/vomit
- assoc_comp = /datum/component/artifact/vomit
+ forced_effect = /datum/artifact_effect/vomit
/obj/structure/artifact/borger
- assoc_comp = /datum/component/artifact/borger
+ forced_effect = /datum/artifact_effect/borger
/obj/structure/artifact/emotegen
- assoc_comp = /datum/component/artifact/emotegen
+ forced_effect = /datum/artifact_effect/emotegen
/obj/structure/artifact/surgery
- assoc_comp = /datum/component/artifact/surgery
+ forced_effect = /datum/artifact_effect/surgery
/obj/structure/artifact/smoke
- assoc_comp = /datum/component/artifact/smoke
+ forced_effect = /datum/artifact_effect/smoke
/obj/structure/artifact/smoke/toxin
- assoc_comp = /datum/component/artifact/smoke/toxin
+ forced_effect = /datum/artifact_effect/smoke/toxin
/obj/structure/artifact/smoke/flesh
- assoc_comp = /datum/component/artifact/smoke/flesh
+ forced_effect = /datum/artifact_effect/smoke/flesh
/obj/structure/artifact/smoke/exotic
- assoc_comp = /datum/component/artifact/smoke/exotic
+ forced_effect = /datum/artifact_effect/smoke/exotic
diff --git a/monkestation/code/modules/art_sci_overrides/globals.dm b/monkestation/code/modules/art_sci_overrides/globals.dm
index 25627d3e71a6..c8353234392e 100644
--- a/monkestation/code/modules/art_sci_overrides/globals.dm
+++ b/monkestation/code/modules/art_sci_overrides/globals.dm
@@ -1,2 +1,2 @@
-GLOBAL_LIST_INIT(artifact_rarity, list())
+GLOBAL_LIST_INIT(artifact_effect_rarity, list())
GLOBAL_LIST_INIT(running_artifact_list, list())
diff --git a/monkestation/code/modules/art_sci_overrides/new_procs.dm b/monkestation/code/modules/art_sci_overrides/new_procs.dm
index 18826afdf0db..dd481d85caca 100644
--- a/monkestation/code/modules/art_sci_overrides/new_procs.dm
+++ b/monkestation/code/modules/art_sci_overrides/new_procs.dm
@@ -1,7 +1,7 @@
/proc/random_rgb_pairlists(list/red_pairs, list/green_pairs, list/blue_pairs, list/alpha_pairs)
if(!length(red_pairs) || !length(blue_pairs) || !length(green_pairs) || !length(alpha_pairs))
return COLOR_CULT_RED
-
+
if(!length(red_pairs) >= 2)
red_pairs[2] = 255
if(!length(blue_pairs) >= 2)
@@ -18,35 +18,37 @@
return rgb(red, green, blue, alpha)
-
-/proc/spawn_artifact(turf/loc, forced_origin)
+///Spawn a new artifact
+/proc/spawn_artifact(turf/loc, forced_origin = null, forced_effect = null)
if (!loc)
return
- if(!length(GLOB.artifact_rarity))
+ if(!length(GLOB.artifact_effect_rarity))
build_weighted_rarities()
- var/list/weighted_list
-
- if(forced_origin)
- weighted_list = GLOB.artifact_rarity[forced_origin]
- else
- weighted_list = GLOB.artifact_rarity["all"]
+ var/obj/type_of_artifact = pick_weight(list(
+ /obj/structure/artifact = 70,
+ /obj/item/artifact_item = 10,
+ /obj/item/artifact_item_tiny = 10,
+ /obj/item/stock_parts/cell/artifact = 2.5,
+ /obj/item/gun/magic/artifact = 2.5,
+ /obj/item/melee/artifact = 2.5,
+ /obj/machinery/power/generator_artifact = 2.5
+ ))
- var/datum/component/artifact/picked = pick_weight(weighted_list)
- var/type = initial(picked.associated_object)
- return new type(loc)
+ var/obj/A = new type_of_artifact(loc,forced_origin,forced_effect)
+ return A
/proc/build_weighted_rarities()
- GLOB.artifact_rarity["all"] = list() ///this needs to be created first for indexing sake
+ GLOB.artifact_effect_rarity["all"] = list() ///this needs to be created first for indexing sake
for(var/datum/artifact_origin/origin as anything in subtypesof(/datum/artifact_origin))
- GLOB.artifact_rarity[initial(origin.type_name)] = list()
+ GLOB.artifact_effect_rarity[initial(origin.type_name)] = list()
- for(var/datum/component/artifact/artifact_type as anything in subtypesof(/datum/component/artifact))
- var/weight = initial(artifact_type.weight)
+ for(var/datum/artifact_effect/artifact_effect as anything in subtypesof(/datum/artifact_effect))
+ var/weight = initial(artifact_effect.weight)
if(!weight)
continue
- GLOB.artifact_rarity["all"][artifact_type] = weight
- for(var/origin in GLOB.artifact_rarity)
- if(origin in initial(artifact_type.valid_origins))
- GLOB.artifact_rarity[origin][artifact_type] = weight
+ GLOB.artifact_effect_rarity["all"][artifact_effect] = weight
+ for(var/origin in GLOB.artifact_effect_rarity)
+ if(origin in initial(artifact_effect.valid_origins))
+ GLOB.artifact_effect_rarity[origin][artifact_effect] = weight
diff --git a/monkestation/code/modules/client/preferences/alt_jobs/titles.dm b/monkestation/code/modules/client/preferences/alt_jobs/titles.dm
index f132695cbf6d..1e45300b1627 100644
--- a/monkestation/code/modules/client/preferences/alt_jobs/titles.dm
+++ b/monkestation/code/modules/client/preferences/alt_jobs/titles.dm
@@ -292,6 +292,7 @@
"Biorobotics Director",
"Research Supervisor",
"Chief Science Officer",
+ "Chief Artificer",
)
/datum/job/roboticist
@@ -318,6 +319,7 @@
"Xenoarchaeologist",
"Research Assistant",
"Graduate Student",
+ "Artificer"
)
/datum/job/security_officer
diff --git a/tgstation.dme b/tgstation.dme
index e4d55f060368..54cff14c806e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -6191,6 +6191,7 @@
#include "monkestation\code\modules\antimatter\code\control.dm"
#include "monkestation\code\modules\antimatter\code\shielding.dm"
#include "monkestation\code\modules\art_sci_overrides\artifact_origins.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_proto_datums.dm"
#include "monkestation\code\modules\art_sci_overrides\generic_artifact_objects.dm"
#include "monkestation\code\modules\art_sci_overrides\globals.dm"
#include "monkestation\code\modules\art_sci_overrides\item_stimuli.dm"
@@ -6201,23 +6202,36 @@
#include "monkestation\code\modules\art_sci_overrides\artifact_components\_base_component.dm"
#include "monkestation\code\modules\art_sci_overrides\artifact_components\_base_component_signal_procs.dm"
#include "monkestation\code\modules\art_sci_overrides\artifact_components\_base_subtype_helpers.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\bomb.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\bonk.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\borger.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\cell.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\emoter.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\forcegen.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\gun.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\heal.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\injector.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\lamp.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\melee.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\repulsor.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\smoke_artifacts.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\surgery.dm"
-#include "monkestation\code\modules\art_sci_overrides\artifact_components\vomit.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_components\ghost_object.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\_artifact_effect.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\bomb.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\bonk.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\borger.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\bread.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\cell.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\cleaning.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\emoter.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\false_rod.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\forcegen.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\gun.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\heal.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\injector.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\itsasecret.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\lamp.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\meat.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\melee.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\money.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\narsieoffering.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\plushie_vendor.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\repulsor.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\smoke_artifacts.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\surgery.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_effects\vomit.dm"
#include "monkestation\code\modules\art_sci_overrides\artifact_items\artifact_cell.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_items\artifact_effect_disk.dm"
#include "monkestation\code\modules\art_sci_overrides\artifact_items\artifact_gun.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_items\artifact_item.dm"
+#include "monkestation\code\modules\art_sci_overrides\artifact_items\artifact_manipulators.dm"
#include "monkestation\code\modules\art_sci_overrides\artifact_items\artifact_melee.dm"
#include "monkestation\code\modules\art_sci_overrides\artifact_objects\artifact_powergen.dm"
#include "monkestation\code\modules\art_sci_overrides\artifact_testers\analysis_form.dm"
@@ -6231,9 +6245,13 @@
#include "monkestation\code\modules\art_sci_overrides\asteroids\cartesian_plane.dm"
#include "monkestation\code\modules\art_sci_overrides\asteroids\simple_asteroid.dm"
#include "monkestation\code\modules\art_sci_overrides\faults\_fault.dm"
+#include "monkestation\code\modules\art_sci_overrides\faults\bioscrambler.dm"
+#include "monkestation\code\modules\art_sci_overrides\faults\clowning.dm"
#include "monkestation\code\modules\art_sci_overrides\faults\explosion.dm"
+#include "monkestation\code\modules\art_sci_overrides\faults\greg.dm"
#include "monkestation\code\modules\art_sci_overrides\faults\ignite.dm"
#include "monkestation\code\modules\art_sci_overrides\faults\just_death.dm"
+#include "monkestation\code\modules\art_sci_overrides\faults\monkey_mode.dm"
#include "monkestation\code\modules\art_sci_overrides\faults\reagents.dm"
#include "monkestation\code\modules\art_sci_overrides\faults\say.dm"
#include "monkestation\code\modules\art_sci_overrides\faults\size_change.dm"
diff --git a/tgui/packages/tgui/interfaces/ArtifactForm.jsx b/tgui/packages/tgui/interfaces/ArtifactForm.jsx
index 6da89c9386e4..1ce1a8e36154 100644
--- a/tgui/packages/tgui/interfaces/ArtifactForm.jsx
+++ b/tgui/packages/tgui/interfaces/ArtifactForm.jsx
@@ -8,13 +8,15 @@ export const ArtifactForm = (props) => {
const {
allorigins,
chosenorigin,
+ allfaults,
+ chosenfault,
alltypes,
chosentype,
alltriggers,
chosentriggers,
} = data;
return (
-
+
{allorigins.map((key) => (
@@ -31,13 +33,28 @@ export const ArtifactForm = (props) => {
/>
))}
+
+ {allfaults.map((thing) => (
+
{alltypes.map((x) => (