diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm
index df83ba66ec2..ae3773be74c 100644
--- a/code/__defines/dcs/signals.dm
+++ b/code/__defines/dcs/signals.dm
@@ -58,8 +58,8 @@
#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE "atom_init_success"
///from base of atom/attackby(): (/obj/item, /mob/living, params)
#define COMSIG_PARENT_ATTACKBY "atom_attackby"
-///Return this in response if you don't want afterattack to be called
- #define COMPONENT_NO_AFTERATTACK (1<<0)
+///Return this in response if you don't want later item attack procs to be called.
+ #define COMPONENT_CANCEL_ATTACK_CHAIN (1<<0)
///from base of atom/attack_hulk(): (/mob/living/carbon/human)
#define COMSIG_ATOM_HULK_ATTACK "hulk_attack"
///from base of atom/animal_attack(): (/mob/user)
@@ -94,6 +94,7 @@
#define COMSIG_ATOM_BUMPED "atom_bumped"
///from base of atom/ex_act(): (severity, target)
#define COMSIG_ATOM_EX_ACT "atom_ex_act"
+ #define COMPONENT_IGNORE_EXPLOSION (1<<0)
///from base of atom/emp_act(): (severity)
#define COMSIG_ATOM_EMP_ACT "atom_emp_act"
///from base of atom/fire_act(): (exposed_temperature, exposed_volume)
@@ -225,7 +226,7 @@
// /atom/movable signals
-///from base of atom/movable/Moved(): (/atom)
+///from base of atom/movable/Move(): (atom/newloc, dir, movetime)
#define COMSIG_MOVABLE_PRE_MOVE "movable_pre_move"
#define COMPONENT_MOVABLE_BLOCK_PRE_MOVE (1<<0)
///from base of atom/movable/Moved(): (/atom, dir)
@@ -778,3 +779,5 @@
#define COMSIG_CONFLICT_ELEMENT_CHECK "conflict_element_check"
/// A conflict was found
#define ELEMENT_CONFLICT_FOUND (1<<0)
+//From reagents touch_x.
+#define COMSIG_REAGENTS_TOUCH "reagent_touch"
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 48accdb7fa8..c55ec430e3d 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -25,28 +25,48 @@ avoid code duplication. This includes items that may sometimes act as a standard
return
return
-// Called at the start of resolve_attackby(), before the actual attack.
-/obj/item/proc/pre_attack(atom/a, mob/user)
- return
+/**
+ * Called at the start of resolve_attackby(), before the actual attack.
+ *
+ * Arguments:
+ * * atom/A - The atom about to be hit
+ * * mob/living/user - The mob doing the htting
+ * * params - click params such as alt/shift etc
+ *
+ * See: [/obj/item/proc/melee_attack_chain]
+ */
+
+/obj/item/proc/pre_attack(atom/A, mob/user, params) //do stuff before attackby!
+ if(SEND_SIGNAL(src, COMSIG_ITEM_PRE_ATTACK, A, user, params) & COMPONENT_CANCEL_ATTACK_CHAIN)
+ return TRUE
+ return FALSE //return TRUE to avoid calling attackby after this proc does stuff
//I would prefer to rename this to attack(), but that would involve touching hundreds of files.
/obj/item/proc/resolve_attackby(atom/A, mob/user, var/attack_modifier = 1, var/click_parameters)
- pre_attack(A, user)
add_fingerprint(user)
+ . = pre_attack(A, user, click_parameters)
+ if(.) // We're returning the value of pre_attack, important if it has a special return.
+ return
return A.attackby(src, user, attack_modifier, click_parameters)
// No comment
/atom/proc/attackby(obj/item/W, mob/user, var/attack_modifier, var/click_parameters)
- if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, W, user, click_parameters) & COMPONENT_NO_AFTERATTACK)
+ if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, W, user, click_parameters) & COMPONENT_CANCEL_ATTACK_CHAIN)
return TRUE
return FALSE
/mob/living/attackby(obj/item/I, mob/user, var/attack_modifier, var/click_parameters)
if(!ismob(user))
- return 0
+ return FALSE
+
+ if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, I, user, click_parameters) & COMPONENT_CANCEL_ATTACK_CHAIN)
+ return FALSE
+
if(can_operate(src, user) && I.do_surgery(src,user))
- return 1
+ return TRUE
+
if(attempt_vr(src,"vore_attackby",args)) return //VOREStation Add - The vore, of course.
+
return I.attack(src, user, user.zone_sel.selecting, attack_modifier)
// Used to get how fast a mob should attack, and influences click delay.
diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm
index 3bd1a0afb2d..5351139540f 100644
--- a/code/_onclick/other_mobs.dm
+++ b/code/_onclick/other_mobs.dm
@@ -26,7 +26,9 @@
A.attack_hand(src)
/atom/proc/attack_hand(mob/user as mob)
- return
+ if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_HAND, user) & COMPONENT_CANCEL_ATTACK_CHAIN)
+ return TRUE
+ return FALSE
/mob/living/carbon/human/RestrainedClickOn(var/atom/A)
return
diff --git a/code/datums/components/material_container.dm b/code/datums/components/material_container.dm
index 86573474e69..fbad2752ee9 100644
--- a/code/datums/components/material_container.dm
+++ b/code/datums/components/material_container.dm
@@ -115,7 +115,7 @@
if(!(mat_container_flags & MATCONTAINER_SILENT))
to_chat(user, "[parent] won't accept [I]!")
return
- . = COMPONENT_NO_AFTERATTACK
+ . = COMPONENT_CANCEL_ATTACK_CHAIN
var/datum/callback/pc = precondition
if(pc && !pc.Invoke(user))
return
@@ -168,7 +168,7 @@
// It shouldn't be possible to add more matter than our max
ASSERT((total_amount + (matter_per_sheet * sheets_to_use)) <= max_amount)
-
+
// Use the amount of sheets from the stack
if(!S.use(sheets_to_use))
to_chat(user, "Something went wrong with your stack. Split it manually and try again.")
@@ -358,7 +358,7 @@
if(materials[M] < (sheet_amt * SHEET_MATERIAL_AMOUNT))
sheet_amt = round(materials[M] / SHEET_MATERIAL_AMOUNT)
- var/obj/item/stack/S = M.stack_type
+ var/obj/item/stack/S = M.stack_type
var/max_stack_size = initial(S.max_amount)
var/count = 0
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 55b6938a7cc..3df1820fa9b 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -125,6 +125,8 @@
/atom/proc/Bumped(AM as mob|obj)
set waitfor = FALSE
+ SEND_SIGNAL(src, COMSIG_ATOM_BUMPED, AM)
+
// Convenience proc to see if a container is open for chemistry handling
// returns true if open
// false if closed
@@ -166,6 +168,9 @@
return
/atom/proc/bullet_act(obj/item/projectile/P, def_zone)
+ if(SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, P, def_zone) & COMPONENT_CANCEL_ATTACK_CHAIN)
+ return
+
P.on_hit(src, 0, def_zone)
. = 0
@@ -260,8 +265,8 @@
invisibility = new_invisibility
return TRUE
-/atom/proc/ex_act()
- return
+/atom/proc/ex_act(var/strength = 3)
+ return (SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, strength, src) & COMPONENT_IGNORE_EXPLOSION)
/atom/proc/emag_act(var/remaining_charges, var/mob/user, var/emag_source)
return -1
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 195e02e8fa4..ef50823c48c 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -85,6 +85,9 @@
if(!loc || !newloc)
return FALSE
+ if(SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, newloc, direct, movetime) & COMPONENT_MOVABLE_BLOCK_PRE_MOVE)
+ return FALSE
+
// Store this early before we might move, it's used several places
var/atom/oldloc = loc
@@ -232,6 +235,9 @@
riding_datum.handle_vehicle_offsets()
for (var/datum/light_source/light as anything in light_sources) // Cycle through the light sources on this atom and tell them to update.
light.source_atom.update_light()
+
+ SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, old_loc, direction)
+
return TRUE
/atom/movable/set_dir(newdir)
@@ -265,6 +271,9 @@
throwing = 0
if(QDELETED(A))
return
+
+ SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A)
+
A.Bumped(src)
A.last_bumped = world.time
diff --git a/code/modules/reagents/reagents/_reagents.dm b/code/modules/reagents/reagents/_reagents.dm
index 08e34c9eb92..2ad46f225b3 100644
--- a/code/modules/reagents/reagents/_reagents.dm
+++ b/code/modules/reagents/reagents/_reagents.dm
@@ -48,12 +48,15 @@
// This doesn't apply to skin contact - this is for, e.g. extinguishers and sprays. The difference is that reagent is not directly on the mob's skin - it might just be on their clothing.
/datum/reagent/proc/touch_mob(var/mob/M, var/amount)
+ SEND_SIGNAL(M, COMSIG_REAGENTS_TOUCH, src, amount)
return
/datum/reagent/proc/touch_obj(var/obj/O, var/amount) // Acid melting, cleaner cleaning, etc
+ SEND_SIGNAL(O, COMSIG_REAGENTS_TOUCH, src, amount)
return
/datum/reagent/proc/touch_turf(var/turf/T, var/amount) // Cleaner cleaning, lube lubbing, etc, all go here
+ SEND_SIGNAL(T, COMSIG_REAGENTS_TOUCH, src, amount)
return
/datum/reagent/proc/on_mob_life(var/mob/living/carbon/M, var/alien, var/datum/reagents/metabolism/location) // Currently, on_mob_life is called on carbons. Any interaction with non-carbon mobs (lube) will need to be done in touch_mob.
diff --git a/code/modules/reagents/reagents/core.dm b/code/modules/reagents/reagents/core.dm
index a235a617552..3eb3e06cfb1 100644
--- a/code/modules/reagents/reagents/core.dm
+++ b/code/modules/reagents/reagents/core.dm
@@ -31,6 +31,9 @@
/datum/reagent/blood/touch_turf(var/turf/simulated/T)
if(!istype(T) || volume < 3)
return
+
+ ..()
+
if(!data["donor"] || istype(data["donor"], /mob/living/carbon/human))
blood_splatter(T, src, 1)
else if(istype(data["donor"], /mob/living/carbon/alien))
@@ -169,6 +172,8 @@
if(!istype(T))
return
+ ..()
+
var/datum/gas_mixture/environment = T.return_air()
var/min_temperature = T0C + 100 // 100C, the boiling point of water
@@ -190,14 +195,19 @@
T.wet_floor(1)
/datum/reagent/water/touch_obj(var/obj/O, var/amount)
+ ..()
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/monkeycube))
var/obj/item/weapon/reagent_containers/food/snacks/monkeycube/cube = O
if(!cube.wrapped)
cube.Expand()
+ else if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/cube))
+ var/obj/item/weapon/reagent_containers/food/snacks/cube/cube = O
+ cube.Expand()
else
O.water_act(amount / 5)
/datum/reagent/water/touch_mob(var/mob/living/L, var/amount)
+ ..()
if(istype(L))
// First, kill slimes.
if(istype(L, /mob/living/simple_mob/slime))
@@ -252,6 +262,7 @@
glass_desc = "Unless you are an industrial tool, this is probably not safe for consumption."
/datum/reagent/fuel/touch_turf(var/turf/T, var/amount)
+ ..()
new /obj/effect/decal/cleanable/liquid_fuel(T, amount, FALSE)
remove_self(amount)
return
@@ -261,5 +272,6 @@
M.adjustToxLoss(4 * removed)
/datum/reagent/fuel/touch_mob(var/mob/living/L, var/amount)
+ ..()
if(istype(L))
L.adjust_fire_stacks(amount / 10) // Splashing people with welding fuel to make them easy to ignite!
diff --git a/code/modules/reagents/reagents/dispenser.dm b/code/modules/reagents/reagents/dispenser.dm
index 6dd8a79285a..abc05228862 100644
--- a/code/modules/reagents/reagents/dispenser.dm
+++ b/code/modules/reagents/reagents/dispenser.dm
@@ -49,6 +49,7 @@
M.ingested.remove_reagent(R.id, removed * effect)
/datum/reagent/carbon/touch_turf(var/turf/T)
+ ..()
if(!istype(T, /turf/space))
var/obj/effect/decal/cleanable/dirt/dirtoverlay = locate(/obj/effect/decal/cleanable/dirt, T)
if (!dirtoverlay)
@@ -106,6 +107,7 @@
allergen_factor = 0.5 //simulates mixed drinks containing less of the allergen, as they have only a single actual reagent unlike food
/datum/reagent/ethanol/touch_mob(var/mob/living/L, var/amount)
+ ..()
if(istype(L))
L.adjust_fire_stacks(amount / 15)
@@ -199,6 +201,7 @@
M.hallucination = max(M.hallucination, halluci)
/datum/reagent/ethanol/touch_obj(var/obj/O)
+ ..()
if(istype(O, /obj/item/weapon/paper))
var/obj/item/weapon/paper/paperaffected = O
paperaffected.clearpaper()
@@ -342,6 +345,7 @@
M.adjustToxLoss(100)
/datum/reagent/radium/touch_turf(var/turf/T)
+ ..()
if(volume >= 3)
if(!istype(T, /turf/space))
var/obj/effect/decal/cleanable/greenglow/glow = locate(/obj/effect/decal/cleanable/greenglow, T)
@@ -426,6 +430,7 @@
M.take_organ_damage(0, removed * power * 0.1) // Balance. The damage is instant, so it's weaker. 10 units -> 5 damage, double for pacid. 120 units beaker could deal 60, but a) it's burn, which is not as dangerous, b) it's a one-use weapon, c) missing with it will splash it over the ground and d) clothes give some protection, so not everything will hit
/datum/reagent/acid/touch_obj(var/obj/O)
+ ..()
if(O.unacidable)
return
if((istype(O, /obj/item) || istype(O, /obj/effect/plant)) && (volume > meltdose))
diff --git a/code/modules/reagents/reagents/food_drinks.dm b/code/modules/reagents/reagents/food_drinks.dm
index 8de9abd0b35..b72aafbacd0 100644
--- a/code/modules/reagents/reagents/food_drinks.dm
+++ b/code/modules/reagents/reagents/food_drinks.dm
@@ -170,6 +170,8 @@
if(!istype(T))
return
+ ..()
+
var/hotspot = (locate(/obj/fire) in T)
if(hotspot && !istype(T, /turf/space))
var/datum/gas_mixture/lowertemp = T.remove_air(T:air:total_moles)
@@ -386,6 +388,7 @@
allergen_type = ALLERGEN_GRAINS //Flour is made from grain
/datum/reagent/nutriment/flour/touch_turf(var/turf/simulated/T)
+ ..()
if(!istype(T, /turf/space))
new /obj/effect/decal/cleanable/flour(T)
@@ -565,6 +568,7 @@
glass_desc = "Durian paste. It smells horrific."
/datum/reagent/nutriment/durian/touch_mob(var/mob/M, var/amount)
+ ..()
if(iscarbon(M) && !M.isSynthetic())
var/message = pick("Oh god, it smells disgusting here.", "What is that stench?", "That's an awful odor.")
to_chat(M, "[message]")
@@ -574,6 +578,7 @@
return ..()
/datum/reagent/nutriment/durian/touch_turf(var/turf/T, var/amount)
+ ..()
if(istype(T))
var/obj/effect/decal/cleanable/chemcoating/C = new /obj/effect/decal/cleanable/chemcoating(T)
C.reagents.add_reagent(id, amount)
diff --git a/code/modules/reagents/reagents/medicine.dm b/code/modules/reagents/reagents/medicine.dm
index 54d7c6e305b..a18a2a1a734 100644
--- a/code/modules/reagents/reagents/medicine.dm
+++ b/code/modules/reagents/reagents/medicine.dm
@@ -339,6 +339,7 @@
M.adjustToxLoss(3 * removed)
/datum/reagent/tricorlidaze/touch_obj(var/obj/O)
+ ..()
if(istype(O, /obj/item/stack/medical/bruise_pack) && round(volume) >= 5)
var/obj/item/stack/medical/bruise_pack/C = O
var/packname = C.name
@@ -1248,6 +1249,7 @@
M.add_chemical_effect(CE_PAINKILLER, 20 * M.species.chem_strength_pain) // 5 less than paracetamol.
/datum/reagent/spacomycaze/touch_obj(var/obj/O)
+ ..()
if(istype(O, /obj/item/stack/medical/crude_pack) && round(volume) >= 1)
var/obj/item/stack/medical/crude_pack/C = O
var/packname = C.name
@@ -1284,10 +1286,12 @@
M.adjustToxLoss(2 * removed)
/datum/reagent/sterilizine/touch_obj(var/obj/O)
+ ..()
O.germ_level -= min(volume*20, O.germ_level)
O.was_bloodied = null
/datum/reagent/sterilizine/touch_turf(var/turf/T)
+ ..()
T.germ_level -= min(volume*20, T.germ_level)
for(var/obj/item/I in T.contents)
I.was_bloodied = null
@@ -1301,6 +1305,7 @@
//VOREstation edit end
/datum/reagent/sterilizine/touch_mob(var/mob/living/L, var/amount)
+ ..()
if(istype(L))
if(istype(L, /mob/living/simple_mob/slime))
var/mob/living/simple_mob/slime/S = L
diff --git a/code/modules/reagents/reagents/modifiers.dm b/code/modules/reagents/reagents/modifiers.dm
index bed5da5f477..22b1f047c71 100644
--- a/code/modules/reagents/reagents/modifiers.dm
+++ b/code/modules/reagents/reagents/modifiers.dm
@@ -42,6 +42,7 @@
affect_blood(M, alien, removed * 0.6)
/datum/reagent/modapplying/cryofluid/touch_mob(var/mob/M, var/amount)
+ ..()
if(isliving(M))
var/mob/living/L = M
for(var/I = 1 to rand(1, round(amount + 1)))
@@ -49,6 +50,7 @@
return
/datum/reagent/modapplying/cryofluid/touch_turf(var/turf/T, var/amount)
+ ..()
if(istype(T, /turf/simulated/floor/water) && prob(amount))
T.visible_message("\The [T] crackles loudly as the cryogenic fluid causes it to boil away, leaving behind a hard layer of ice.")
T.ChangeTurf(/turf/simulated/floor/outdoors/ice, 1, 1, TRUE)
diff --git a/code/modules/reagents/reagents/other.dm b/code/modules/reagents/reagents/other.dm
index b6775e1759f..fb5468d3ee7 100644
--- a/code/modules/reagents/reagents/other.dm
+++ b/code/modules/reagents/reagents/other.dm
@@ -114,14 +114,17 @@
color_weight = 20
/datum/reagent/paint/touch_turf(var/turf/T)
+ ..()
if(istype(T) && !istype(T, /turf/space))
T.color = color
/datum/reagent/paint/touch_obj(var/obj/O)
+ ..()
if(istype(O))
O.color = color
/datum/reagent/paint/touch_mob(var/mob/M)
+ ..()
if(istype(M) && !istype(M, /mob/observer)) //painting ghosts: not allowed
M.color = color //maybe someday change this to paint only clothes and exposed body parts for human mobs.
@@ -267,6 +270,7 @@
M.apply_effect(5 * removed, IRRADIATE, 0)
/datum/reagent/uranium/touch_turf(var/turf/T)
+ ..()
if(volume >= 3)
if(!istype(T, /turf/space))
var/obj/effect/decal/cleanable/greenglow/glow = locate(/obj/effect/decal/cleanable/greenglow, T)
@@ -288,7 +292,7 @@
name = "Lithium-6"
id = "lithium6"
description = "An isotope of lithium. It has 3 neutrons, but shares all chemical characteristics with regular lithium."
-
+
/datum/reagent/helium/helium3
name = "Helium-3"
id = "helium3"
@@ -321,11 +325,11 @@
/datum/reagent/supermatter/affect_ingest(mob/living/carbon/M, alien, removed)
. = ..()
M.ash()
-
+
/datum/reagent/supermatter/affect_blood(mob/living/carbon/M, alien, removed)
. = ..()
M.ash()
-
+
/datum/reagent/adrenaline
name = "Adrenaline"
@@ -361,6 +365,7 @@
cult.remove_antagonist(M.mind)
/datum/reagent/water/holywater/touch_turf(var/turf/T)
+ ..()
if(volume >= 5)
T.holy = 1
return
@@ -408,6 +413,7 @@
touch_met = 50
/datum/reagent/thermite/touch_turf(var/turf/T)
+ ..()
if(volume >= 5)
if(istype(T, /turf/simulated/wall))
var/turf/simulated/wall/W = T
@@ -417,6 +423,7 @@
return
/datum/reagent/thermite/touch_mob(var/mob/living/L, var/amount)
+ ..()
if(istype(L))
L.adjust_fire_stacks(amount / 5)
@@ -433,14 +440,17 @@
touch_met = 50
/datum/reagent/space_cleaner/touch_mob(var/mob/M)
+ ..()
if(iscarbon(M))
var/mob/living/carbon/C = M
C.clean_blood()
/datum/reagent/space_cleaner/touch_obj(var/obj/O)
+ ..()
O.clean_blood()
/datum/reagent/space_cleaner/touch_turf(var/turf/T)
+ ..()
if(volume >= 1)
if(istype(T, /turf/simulated))
var/turf/simulated/S = T
@@ -488,6 +498,7 @@
M.vomit()
/datum/reagent/space_cleaner/touch_mob(var/mob/living/L, var/amount)
+ ..()
if(istype(L, /mob/living/carbon/human))
var/mob/living/carbon/human/H = L
if(H.wear_mask)
@@ -506,6 +517,7 @@
color = "#009CA8"
/datum/reagent/lube/touch_turf(var/turf/simulated/T)
+ ..()
if(!istype(T))
return
if(volume >= 1)
@@ -520,6 +532,7 @@
color = "#C7FFFF"
/datum/reagent/silicate/touch_obj(var/obj/O)
+ ..()
if(istype(O, /obj/structure/window))
var/obj/structure/window/W = O
W.apply_silicate(volume)
@@ -593,9 +606,11 @@
color = "#F2F3F4"
/datum/reagent/luminol/touch_obj(var/obj/O)
+ ..()
O.reveal_blood()
/datum/reagent/luminol/touch_mob(var/mob/living/L)
+ ..()
L.reveal_blood()
/datum/reagent/nutriment/biomass
diff --git a/code/modules/reagents/reagents/toxins.dm b/code/modules/reagents/reagents/toxins.dm
index 23fc080e8c6..91a7ed12b42 100644
--- a/code/modules/reagents/reagents/toxins.dm
+++ b/code/modules/reagents/reagents/toxins.dm
@@ -96,6 +96,7 @@
var/fire_mult = 30
/datum/reagent/toxin/hydrophoron/touch_mob(var/mob/living/L, var/amount)
+ ..()
if(istype(L))
L.adjust_fire_stacks(amount / fire_mult)
@@ -107,6 +108,7 @@
/datum/reagent/toxin/hydrophoron/touch_turf(var/turf/simulated/T)
if(!istype(T))
return
+ ..()
T.assume_gas("phoron", CEILING(volume/2, 1), T20C)
for(var/turf/simulated/floor/target_tile in range(0,T))
target_tile.assume_gas("phoron", volume/2, 400+T0C)
@@ -148,6 +150,7 @@
skin_danger = 1
/datum/reagent/toxin/phoron/touch_mob(var/mob/living/L, var/amount)
+ ..()
if(istype(L))
L.adjust_fire_stacks(amount / 5)
@@ -169,6 +172,7 @@
..()
/datum/reagent/toxin/phoron/touch_turf(var/turf/simulated/T, var/amount)
+ ..()
if(!istype(T))
return
T.assume_gas("volatile_fuel", amount, T20C)
@@ -390,6 +394,7 @@
color = "#e67819"
/datum/reagent/toxin/fertilizer/tannin/touch_obj(var/obj/O, var/volume)
+ ..()
if(istype(O, /obj/item/stack/hairlesshide))
var/obj/item/stack/hairlesshide/HH = O
HH.rapidcure(round(volume))
@@ -405,6 +410,7 @@
strength = 4
/datum/reagent/toxin/plantbgone/touch_turf(var/turf/T)
+ ..()
if(istype(T, /turf/simulated/wall))
var/turf/simulated/wall/W = T
if(locate(/obj/effect/overlay/wallrot) in W)
@@ -413,6 +419,7 @@
W.visible_message("The fungi are completely dissolved by the solution!")
/datum/reagent/toxin/plantbgone/touch_obj(var/obj/O, var/volume)
+ ..()
if(istype(O, /obj/effect/plant))
qdel(O)
else if(istype(O, /obj/effect/alien/weeds/))
diff --git a/code/modules/xenoarcheaology/anomaly_container.dm b/code/modules/xenoarcheaology/anomaly_container.dm
index f9ac6ef4f5e..e725254f0b6 100644
--- a/code/modules/xenoarcheaology/anomaly_container.dm
+++ b/code/modules/xenoarcheaology/anomaly_container.dm
@@ -14,6 +14,15 @@
if(A)
contain(A)
+ else
+ for(var/obj/Ob in loc)
+ if(can_contain(Ob))
+ contain(Ob)
+ break
+
+/obj/structure/anomaly_container/proc/can_contain(var/obj/O)
+ return O.is_anomalous()
+
/obj/structure/anomaly_container/attack_hand(var/mob/user)
release()
@@ -37,7 +46,11 @@
underlays.Cut()
desc = initial(desc)
-/obj/machinery/artifact/MouseDrop(var/obj/structure/anomaly_container/over_object)
- if(istype(over_object) && Adjacent(over_object) && CanMouseDrop(over_object, usr))
- Bumped(usr)
- over_object.contain(src)
\ No newline at end of file
+/atom/MouseDrop(var/obj/structure/anomaly_container/over_object)
+ . = ..()
+
+ if(istype(over_object))
+ if(!QDELETED(src) && istype(loc, /turf) && is_anomalous() && Adjacent(over_object) && CanMouseDrop(over_object, usr))
+ Bumped(usr)
+ over_object.contain(src)
+
diff --git a/code/modules/xenoarcheaology/artifacts/artifact.dm b/code/modules/xenoarcheaology/artifacts/artifact.dm
index e723561a73c..7a2d73474a0 100644
--- a/code/modules/xenoarcheaology/artifacts/artifact.dm
+++ b/code/modules/xenoarcheaology/artifacts/artifact.dm
@@ -5,42 +5,25 @@
icon_state = "ano00"
var/icon_num = 0
density = TRUE
- var/datum/artifact_effect/my_effect
- var/datum/artifact_effect/secondary_effect
- var/being_used = 0
-
- var/predefined_effects = FALSE
-
- var/predefined_primary
- var/predefined_secondary
var/predefined_icon_num
- var/predefined_triggers = FALSE
+ var/datum/component/artifact_master/artifact_master = /datum/component/artifact_master
- var/predefined_trig_primary
- var/predefined_trig_secondary
+ var/being_used = 0
/obj/machinery/artifact/New()
..()
- if(predefined_effects && predefined_primary)
- my_effect = new predefined_primary(src)
+ if(ispath(artifact_master))
+ AddComponent(artifact_master)
- if(predefined_secondary)
- secondary_effect = new predefined_secondary(src)
- if(prob(75))
- secondary_effect.ToggleActivate(0)
+ artifact_master = GetComponent(artifact_master)
- else
- var/effecttype = pick(subtypesof(/datum/artifact_effect))
- my_effect = new effecttype(src)
+ if(!istype(artifact_master))
+ return
- if(prob(75))
- effecttype = pick(subtypesof(/datum/artifact_effect))
- secondary_effect = new effecttype(src)
- if(prob(75))
- secondary_effect.ToggleActivate(0)
+ var/datum/artifact_effect/my_effect = artifact_master.get_primary()
if(!isnull(predefined_icon_num))
icon_num = predefined_icon_num
@@ -77,299 +60,10 @@
if(prob(60))
my_effect.trigger = pick(TRIGGER_TOUCH, TRIGGER_HEAT, TRIGGER_COLD, TRIGGER_PHORON, TRIGGER_OXY, TRIGGER_CO2, TRIGGER_NITRO)
- if(predefined_triggers)
- if(predefined_trig_primary && my_effect)
- my_effect.trigger = predefined_trig_primary
-
- if(predefined_trig_secondary && secondary_effect)
- secondary_effect.trigger = predefined_trig_secondary
-
-/obj/machinery/artifact/proc/choose_effect()
- var/effect_type = tgui_input_list(usr, "What type do you want?", "Effect Type", subtypesof(/datum/artifact_effect))
- if(effect_type)
- my_effect = new effect_type(src)
- if(tgui_alert(usr, "Do you want a secondary effect?", "Second Effect", list("No", "Yes")) == "Yes")
- var/second_effect_type = tgui_input_list(usr, "What type do you want as well?", "Second Effect Type", subtypesof(/datum/artifact_effect) - effect_type)
- secondary_effect = new second_effect_type(src)
- else
- secondary_effect = null
-
-
-/obj/machinery/artifact/process()
- var/turf/L = loc
- if(!istype(L)) // We're inside a container or on null turf, either way stop processing effects
- return
-
- if(my_effect)
- my_effect.process()
- if(secondary_effect)
- secondary_effect.process()
-
- if(pulledby)
- Bumped(pulledby)
-
- //if either of our effects rely on environmental factors, work that out
- var/trigger_cold = 0
- var/trigger_hot = 0
- var/trigger_phoron = 0
- var/trigger_oxy = 0
- var/trigger_co2 = 0
- var/trigger_nitro = 0
- if( (my_effect.trigger >= TRIGGER_HEAT && my_effect.trigger <= TRIGGER_NITRO) || (my_effect.trigger >= TRIGGER_HEAT && my_effect.trigger <= TRIGGER_NITRO) )
- var/turf/T = get_turf(src)
- var/datum/gas_mixture/env = T.return_air()
- if(env)
- if(env.temperature < 225)
- trigger_cold = 1
- else if(env.temperature > 375)
- trigger_hot = 1
-
- if(env.gas["phoron"] >= 10)
- trigger_phoron = 1
- if(env.gas["oxygen"] >= 10)
- trigger_oxy = 1
- if(env.gas["carbon_dioxide"] >= 10)
- trigger_co2 = 1
- if(env.gas["nitrogen"] >= 10)
- trigger_nitro = 1
-
- //COLD ACTIVATION
- if(trigger_cold)
- if(my_effect.trigger == TRIGGER_COLD && !my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_COLD && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
- else
- if(my_effect.trigger == TRIGGER_COLD && my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_COLD && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
-
- //HEAT ACTIVATION
- if(trigger_hot)
- if(my_effect.trigger == TRIGGER_HEAT && !my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_HEAT && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
- else
- if(my_effect.trigger == TRIGGER_HEAT && my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_HEAT && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
-
- //PHORON GAS ACTIVATION
- if(trigger_phoron)
- if(my_effect.trigger == TRIGGER_PHORON && !my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_PHORON && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
- else
- if(my_effect.trigger == TRIGGER_PHORON && my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_PHORON && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
-
- //OXYGEN GAS ACTIVATION
- if(trigger_oxy)
- if(my_effect.trigger == TRIGGER_OXY && !my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_OXY && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
- else
- if(my_effect.trigger == TRIGGER_OXY && my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_OXY && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
-
- //CO2 GAS ACTIVATION
- if(trigger_co2)
- if(my_effect.trigger == TRIGGER_CO2 && !my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_CO2 && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
- else
- if(my_effect.trigger == TRIGGER_CO2 && my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_CO2 && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
-
- //NITROGEN GAS ACTIVATION
- if(trigger_nitro)
- if(my_effect.trigger == TRIGGER_NITRO && !my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_NITRO && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
- else
- if(my_effect.trigger == TRIGGER_NITRO && my_effect.activated)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_NITRO && !secondary_effect.activated)
- secondary_effect.ToggleActivate(0)
-
-/obj/machinery/artifact/attack_hand(var/mob/user as mob)
- if (get_dist(user, src) > 1)
- to_chat(user, "You can't reach [src] from here.")
- return
- if(ishuman(user) && user:gloves)
- to_chat(user, "You touch [src] with your gloved hands, [pick("but nothing of note happens","but nothing happens","but nothing interesting happens","but you notice nothing different","but nothing seems to have happened")].")
- return
-
- src.add_fingerprint(user)
-
- if(my_effect.trigger == TRIGGER_TOUCH)
- to_chat(user, "You touch [src].")
- my_effect.ToggleActivate()
- else
- to_chat(user, "You touch [src], [pick("but nothing of note happens","but nothing happens","but nothing interesting happens","but you notice nothing different","but nothing seems to have happened")].")
-
- if(prob(25) && secondary_effect && secondary_effect.trigger == TRIGGER_TOUCH)
- secondary_effect.ToggleActivate(0)
-
- if (my_effect.effect == EFFECT_TOUCH)
- my_effect.DoEffectTouch(user)
-
- if(secondary_effect && secondary_effect.effect == EFFECT_TOUCH && secondary_effect.activated)
- secondary_effect.DoEffectTouch(user)
-
-/obj/machinery/artifact/attackby(obj/item/weapon/W as obj, mob/living/user as mob)
-
- if (istype(W, /obj/item/weapon/reagent_containers/))
- if(W.reagents.has_reagent("hydrogen", 1) || W.reagents.has_reagent("water", 1))
- if(my_effect.trigger == TRIGGER_WATER)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_WATER && prob(25))
- secondary_effect.ToggleActivate(0)
- else if(W.reagents.has_reagent("sacid", 1) || W.reagents.has_reagent("pacid", 1) || W.reagents.has_reagent("diethylamine", 1))
- if(my_effect.trigger == TRIGGER_ACID)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_ACID && prob(25))
- secondary_effect.ToggleActivate(0)
- else if(W.reagents.has_reagent("phoron", 1) || W.reagents.has_reagent("thermite", 1))
- if(my_effect.trigger == TRIGGER_VOLATILE)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_VOLATILE && prob(25))
- secondary_effect.ToggleActivate(0)
- else if(W.reagents.has_reagent("toxin", 1) || W.reagents.has_reagent("cyanide", 1) || W.reagents.has_reagent("amatoxin", 1) || W.reagents.has_reagent("neurotoxin", 1))
- if(my_effect.trigger == TRIGGER_TOXIN)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_TOXIN && prob(25))
- secondary_effect.ToggleActivate(0)
- else if(istype(W,/obj/item/weapon/melee/baton) && W:status ||\
- istype(W,/obj/item/weapon/melee/energy) ||\
- istype(W,/obj/item/weapon/melee/cultblade) ||\
- istype(W,/obj/item/weapon/card/emag) ||\
- istype(W,/obj/item/device/multitool))
- if (my_effect.trigger == TRIGGER_ENERGY)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_ENERGY && prob(25))
- secondary_effect.ToggleActivate(0)
-
- else if (istype(W,/obj/item/weapon/flame) && W:lit ||\
- istype(W,/obj/item/weapon/weldingtool) && W:welding)
- if(my_effect.trigger == TRIGGER_HEAT)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_HEAT && prob(25))
- secondary_effect.ToggleActivate(0)
- else
- ..()
- if (my_effect.trigger == TRIGGER_FORCE && W.force >= 10)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
- secondary_effect.ToggleActivate(0)
-
-/obj/machinery/artifact/Bumped(M as mob|obj)
- ..()
- if(istype(M,/obj))
- if(M:throwforce >= 10)
- if(my_effect.trigger == TRIGGER_FORCE)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
- secondary_effect.ToggleActivate(0)
- else if(ishuman(M) && !istype(M:gloves,/obj/item/clothing/gloves))
- var/warn = 0
-
- if (my_effect.trigger == TRIGGER_TOUCH && prob(50))
- my_effect.ToggleActivate()
- warn = 1
- if(secondary_effect && secondary_effect.trigger == TRIGGER_TOUCH && prob(25))
- secondary_effect.ToggleActivate(0)
- warn = 1
-
- if (my_effect.effect == EFFECT_TOUCH && prob(50))
- my_effect.DoEffectTouch(M)
- warn = 1
- if(secondary_effect && secondary_effect.effect == EFFECT_TOUCH && secondary_effect.activated && prob(50))
- secondary_effect.DoEffectTouch(M)
- warn = 1
-
- if(warn)
- to_chat(M, "You accidentally touch \the [src].")
+/obj/machinery/artifact/update_icon()
..()
-/obj/machinery/artifact/Bump(var/atom/bumped)
- if(istype(bumped,/obj))
- if(bumped:throwforce >= 10)
- if(my_effect.trigger == TRIGGER_FORCE)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
- secondary_effect.ToggleActivate(0)
- else if(ishuman(bumped) && GetAnomalySusceptibility(bumped) >= 0.5)
- var/warn = 0
-
- if (my_effect.trigger == TRIGGER_TOUCH && prob(50))
- my_effect.ToggleActivate()
- warn = 1
- if(secondary_effect && secondary_effect.trigger == TRIGGER_TOUCH && prob(25))
- secondary_effect.ToggleActivate(0)
- warn = 1
-
- if (my_effect.effect == EFFECT_TOUCH && prob(50))
- my_effect.DoEffectTouch(bumped)
- warn = 1
- if(secondary_effect && secondary_effect.effect == EFFECT_TOUCH && secondary_effect.activated && prob(50))
- secondary_effect.DoEffectTouch(bumped)
- warn = 1
-
- if(warn)
- to_chat(bumped, "You accidentally touch \the [src] as it hits you.")
-
- ..()
-
-/obj/machinery/artifact/bullet_act(var/obj/item/projectile/P)
- if(istype(P,/obj/item/projectile/bullet))
- if(my_effect.trigger == TRIGGER_FORCE)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
- secondary_effect.ToggleActivate(0)
-
- else if(istype(P,/obj/item/projectile/beam) ||\
- istype(P,/obj/item/projectile/ion) ||\
- istype(P,/obj/item/projectile/energy))
- if(my_effect.trigger == TRIGGER_ENERGY)
- my_effect.ToggleActivate()
- if(secondary_effect && secondary_effect.trigger == TRIGGER_ENERGY && prob(25))
- secondary_effect.ToggleActivate(0)
-
-/obj/machinery/artifact/ex_act(severity)
- switch(severity)
- if(1.0) qdel(src)
- if(2.0)
- if (prob(50))
- qdel(src)
- else
- if(my_effect.trigger == TRIGGER_FORCE || my_effect.trigger == TRIGGER_HEAT)
- my_effect.ToggleActivate()
- if(secondary_effect && (secondary_effect.trigger == TRIGGER_FORCE || secondary_effect.trigger == TRIGGER_HEAT) && prob(25))
- secondary_effect.ToggleActivate(0)
- if(3.0)
- if (my_effect.trigger == TRIGGER_FORCE || my_effect.trigger == TRIGGER_HEAT)
- my_effect.ToggleActivate()
- if(secondary_effect && (secondary_effect.trigger == TRIGGER_FORCE || secondary_effect.trigger == TRIGGER_HEAT) && prob(25))
- secondary_effect.ToggleActivate(0)
- return
-
-/obj/machinery/artifact/Moved()
- . = ..()
- if(my_effect)
- my_effect.UpdateMove()
- if(secondary_effect)
- secondary_effect.UpdateMove()
+ if(LAZYLEN(artifact_master.get_active_effects()))
+ icon_state = "ano[icon_num]1"
+ else
+ icon_state = "ano[icon_num]0"
diff --git a/code/modules/xenoarcheaology/artifacts/predefined/_predefined.dm b/code/modules/xenoarcheaology/artifacts/predefined/_predefined.dm
index edec0dd052f..bc0fa926456 100644
--- a/code/modules/xenoarcheaology/artifacts/predefined/_predefined.dm
+++ b/code/modules/xenoarcheaology/artifacts/predefined/_predefined.dm
@@ -1,15 +1,3 @@
/obj/machinery/artifact/predefined
name = "alien artifact"
- desc = "A large alien device."
-
- predefined_effects = TRUE
-
- predefined_primary = null
- predefined_secondary = null
-
- predefined_icon_num = null
-
- predefined_triggers = FALSE
-
- predefined_trig_primary = null
- predefined_trig_secondary = null
+ desc = "A large alien device."
\ No newline at end of file
diff --git a/code/modules/xenoarcheaology/artifacts/predefined/hungry_statue.dm b/code/modules/xenoarcheaology/artifacts/predefined/hungry_statue.dm
index 6a81c02b8ba..c4141ff1925 100644
--- a/code/modules/xenoarcheaology/artifacts/predefined/hungry_statue.dm
+++ b/code/modules/xenoarcheaology/artifacts/predefined/hungry_statue.dm
@@ -2,14 +2,12 @@
name = "alien artifact"
desc = "A large alien device."
- predefined_effects = TRUE
-
- predefined_primary = /datum/artifact_effect/animate_anomaly
- predefined_secondary = /datum/artifact_effect/vampire
+ artifact_master = /datum/component/artifact_master/hungry_statue
predefined_icon_num = 14
- predefined_triggers = TRUE
-
- predefined_trig_primary = TRIGGER_OXY
- predefined_trig_secondary = TRIGGER_OXY
+/datum/component/artifact_master/hungry_statue
+ make_effects = list(
+ /datum/artifact_effect/animate_anomaly,
+ /datum/artifact_effect/vampire
+ )
diff --git a/code/modules/xenoarcheaology/boulder.dm b/code/modules/xenoarcheaology/boulder.dm
index 7baa2546430..b260f0b62a0 100644
--- a/code/modules/xenoarcheaology/boulder.dm
+++ b/code/modules/xenoarcheaology/boulder.dm
@@ -75,8 +75,8 @@
var/obj/O = new spawn_type(get_turf(src))
if(istype(O, /obj/machinery/artifact))
var/obj/machinery/artifact/X = O
- if(X.my_effect)
- X.my_effect.artifact_id = artifact_find.artifact_id
+ if(X.artifact_master)
+ X.artifact_master.artifact_id = artifact_find.artifact_id
O.anchored = FALSE // Anchored finds are lame.
src.visible_message("\The [src] suddenly crumbles away.")
else
diff --git a/code/modules/xenoarcheaology/effect.dm b/code/modules/xenoarcheaology/effect.dm
index 8b9dd625c1e..145bd3e2583 100644
--- a/code/modules/xenoarcheaology/effect.dm
+++ b/code/modules/xenoarcheaology/effect.dm
@@ -3,19 +3,47 @@
var/effect = EFFECT_TOUCH
var/effectrange = 4
var/trigger = TRIGGER_TOUCH
- var/atom/holder
+ var/datum/component/artifact_master/master
var/activated = 0
- var/chargelevel = 0
+ var/chargelevel = 1
var/chargelevelmax = 10
var/artifact_id = ""
var/effect_type = 0
-/datum/artifact_effect/New(var/atom/location)
+ var/req_type = /atom/movable
+
+ var/image/active_effect
+ var/effect_icon = 'icons/effects/effects.dmi'
+ var/effect_state = "sparkles"
+ var/effect_color = "#ffffff"
+
+ // The last time the effect was toggled.
+ var/last_activation = 0
+
+/datum/artifact_effect/Destroy()
+ if(master)
+ master = null
..()
- holder = location
+
+/datum/artifact_effect/proc/get_master_holder() // Return the effectmaster's holder, if it is set to an effectmaster. Otherwise, master is the target object.
+ if(istype(master))
+ return master.holder
+ else
+ return master
+
+/datum/artifact_effect/New(var/datum/component/artifact_master/newmaster)
+ ..()
+
+ master = newmaster
effect = rand(0, MAX_EFFECT)
trigger = rand(0, MAX_TRIGGER)
+ if(effect_icon && effect_state)
+ if(effect_state == "sparkles")
+ effect_state = "sparkles_[rand(1,4)]"
+ active_effect = image(effect_icon, effect_state)
+ active_effect.color = effect_color
+
//this will be replaced by the excavation code later, but it's here just in case
artifact_id = "[pick("kappa","sigma","antaeres","beta","omicron","iota","epsilon","omega","gamma","delta","tau","alpha")]-[rand(100,999)]"
@@ -36,21 +64,32 @@
/datum/artifact_effect/proc/ToggleActivate(var/reveal_toggle = 1)
//so that other stuff happens first
- spawn(0)
+ set waitfor = FALSE
+
+ var/atom/target = get_master_holder()
+
+ if(world.time - last_activation > 1 SECOND)
+ last_activation = world.time
if(activated)
activated = 0
else
activated = 1
- if(reveal_toggle && holder)
- if(istype(holder, /obj/machinery/artifact))
- var/obj/machinery/artifact/A = holder
- A.icon_state = "ano[A.icon_num][activated]"
+ if(reveal_toggle && target)
+ if(!isliving(target))
+ target.update_icon()
var/display_msg
if(activated)
display_msg = pick("momentarily glows brightly!","distorts slightly for a moment!","flickers slightly!","vibrates!","shimmers slightly for a moment!")
else
display_msg = pick("grows dull!","fades in intensity!","suddenly becomes very still!","suddenly becomes very quiet!")
- var/atom/toplevelholder = holder
+
+ if(active_effect)
+ if(activated)
+ target.underlays.Add(active_effect)
+ else
+ target.underlays.Remove(active_effect)
+
+ var/atom/toplevelholder = target
while(!istype(toplevelholder.loc, /turf))
toplevelholder = toplevelholder.loc
toplevelholder.visible_message("[bicon(toplevelholder)] [toplevelholder] [display_msg]")
diff --git a/code/modules/xenoarcheaology/effect_master.dm b/code/modules/xenoarcheaology/effect_master.dm
new file mode 100644
index 00000000000..f654724b328
--- /dev/null
+++ b/code/modules/xenoarcheaology/effect_master.dm
@@ -0,0 +1,421 @@
+
+/*
+ * Here there be the base component for artifacts.
+ */
+
+/atom/proc/is_anomalous()
+ return (GetComponent(/datum/component/artifact_master))
+
+/atom/proc/become_anomalous()
+ if(!is_anomalous())
+ AddComponent(/datum/component/artifact_master)
+ if(istype(src, /obj/item))
+ var/obj/item/I = src
+ LAZYINITLIST(I.origin_tech)
+ if(prob(50))
+ I.origin_tech[TECH_PRECURSOR] += 1
+ else
+ I.origin_tech[TECH_ARCANE] += 1
+ var/rand_tech = pick(\
+ TECH_MATERIAL,\
+ TECH_ENGINEERING,\
+ TECH_PHORON,\
+ TECH_POWER,\
+ TECH_BLUESPACE,\
+ TECH_BIO,\
+ TECH_COMBAT,\
+ TECH_MAGNET,\
+ TECH_DATA,\
+ TECH_ILLEGAL\
+ )
+ LAZYSET(I.origin_tech, rand_tech, rand(4,7))
+
+/datum/component/artifact_master
+ var/atom/holder
+ var/list/my_effects
+
+ dupe_type = /datum/component/artifact_master
+
+ var/effect_generation_chance = 100
+
+ var/list/make_effects
+
+ var/artifact_id
+
+/datum/component/artifact_master/New()
+ . = ..()
+ holder = parent
+
+ if(!holder)
+ qdel(src)
+ return
+
+ my_effects = list()
+
+ START_PROCESSING(SSobj, src)
+
+ do_setup()
+ return
+
+/*
+ * Component System Registry.
+ * Here be dragons.
+ */
+
+/datum/component/artifact_master/proc/DoRegistry()
+//Melee Hit
+ RegisterSignal(holder, COMSIG_PARENT_ATTACKBY, /datum/component/artifact_master/proc/on_attackby, override = FALSE)
+//Explosions
+ RegisterSignal(holder, COMSIG_ATOM_EX_ACT, /datum/component/artifact_master/proc/on_exact, override = FALSE)
+//Bullets
+ RegisterSignal(holder, COMSIG_ATOM_BULLET_ACT, /datum/component/artifact_master/proc/on_bullet, override = FALSE)
+
+//Attackhand
+ RegisterSignal(holder, COMSIG_ATOM_ATTACK_HAND, /datum/component/artifact_master/proc/on_attack_hand, override = FALSE)
+
+//Bumped / Bumping
+ RegisterSignal(holder, COMSIG_MOVABLE_BUMP, /datum/component/artifact_master/proc/on_bump, override = FALSE)
+ RegisterSignal(holder, COMSIG_ATOM_BUMPED, /datum/component/artifact_master/proc/on_bumped, override = FALSE)
+
+//Moved
+ RegisterSignal(holder, COMSIG_MOVABLE_MOVED, /datum/component/artifact_master/proc/on_moved, override = FALSE)
+
+//Splashed with a reagent.
+ RegisterSignal(holder, COMSIG_REAGENTS_TOUCH, /datum/component/artifact_master/proc/on_reagent, override = FALSE)
+
+/*
+ *
+ */
+
+/datum/component/artifact_master/proc/get_active_effects()
+ var/list/active_effects = list()
+ for(var/datum/artifact_effect/my_effect in my_effects)
+ if(my_effect.activated)
+ active_effects |= my_effect
+
+ return active_effects
+
+/datum/component/artifact_master/proc/add_effect()
+ var/effect_type = input(usr, "What type do you want?", "Effect Type") as null|anything in subtypesof(/datum/artifact_effect)
+ if(effect_type)
+ var/datum/artifact_effect/my_effect = new effect_type(src)
+ if(istype(holder, my_effect.req_type))
+ my_effects += my_effect
+
+ else
+ to_chat(usr, "This effect can not be applied to this atom type.")
+ qdel(my_effect)
+
+/datum/component/artifact_master/proc/remove_effect()
+ var/to_remove_effect = input(usr, "What effect do you want to remove?", "Remove Effect") as null|anything in my_effects
+
+ if(to_remove_effect)
+ var/datum/artifact_effect/AE = to_remove_effect
+ my_effects.Remove(to_remove_effect)
+ qdel(AE)
+
+/datum/component/artifact_master/Destroy()
+ holder = null
+ for(var/datum/artifact_effect/AE in my_effects)
+ AE.master = null
+ qdel(AE)
+
+ STOP_PROCESSING(SSobj,src)
+
+ . = ..()
+
+/datum/component/artifact_master/proc/do_setup()
+ if(LAZYLEN(make_effects))
+ for(var/path in make_effects)
+ var/datum/artifact_effect/new_effect = new path(src)
+ if(istype(holder, new_effect.req_type))
+ my_effects += new_effect
+
+ else
+ generate_effects()
+
+ DoRegistry()
+
+/datum/component/artifact_master/proc/generate_effects()
+ while(effect_generation_chance > 0)
+ var/chosen_path = pick(subtypesof(/datum/artifact_effect))
+ if(effect_generation_chance >= 100) // If we're above 100 percent, just cut a flat amount and add an effect.
+ var/datum/artifact_effect/AE = new chosen_path(src)
+ if(istype(holder, AE.req_type))
+ my_effects += AE
+ effect_generation_chance -= 30
+ else
+ AE.master = src
+ qdel(AE)
+ continue
+
+ effect_generation_chance /= 2
+
+ if(prob(effect_generation_chance)) // Otherwise, add effects as normal, with decreasing probability.
+ my_effects += new chosen_path(src)
+
+ effect_generation_chance = round(effect_generation_chance)
+
+/datum/component/artifact_master/proc/get_holder() // Returns the holder.
+ return holder
+
+/datum/component/artifact_master/proc/get_primary()
+ if(LAZYLEN(my_effects))
+ return my_effects[1]
+ return FALSE
+
+/*
+ * Trigger code.
+ */
+
+/datum/component/artifact_master/proc/on_exact()
+ var/severity = args[2]
+ var/triggered = FALSE
+ for(var/datum/artifact_effect/my_effect in my_effects)
+ switch(severity)
+ if(1.0)
+ if(my_effect.trigger == TRIGGER_FORCE || my_effect.trigger == TRIGGER_HEAT || my_effect.trigger == TRIGGER_ENERGY)
+ my_effect.ToggleActivate()
+ triggered = TRUE
+ if(2.0)
+ if(my_effect.trigger == TRIGGER_FORCE || my_effect.trigger == TRIGGER_HEAT)
+ my_effect.ToggleActivate()
+ triggered = TRUE
+ if(3.0)
+ if (my_effect.trigger == TRIGGER_FORCE)
+ my_effect.ToggleActivate()
+ triggered = TRUE
+
+ if(triggered)
+ return COMPONENT_IGNORE_EXPLOSION
+
+ return
+
+/datum/component/artifact_master/proc/on_bullet()
+ var/obj/item/projectile/P = args[2]
+ var/triggered = TRUE
+ for(var/datum/artifact_effect/my_effect in my_effects)
+ if(istype(P,/obj/item/projectile/bullet))
+ if(my_effect.trigger == TRIGGER_FORCE)
+ my_effect.ToggleActivate()
+ triggered = TRUE
+
+ else if(istype(P,/obj/item/projectile/beam) ||\
+ istype(P,/obj/item/projectile/ion) ||\
+ istype(P,/obj/item/projectile/energy))
+ if(my_effect.trigger == TRIGGER_ENERGY)
+ my_effect.ToggleActivate()
+ triggered = TRUE
+
+ if(triggered)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
+
+ return
+
+/datum/component/artifact_master/proc/on_bump()
+ var/atom/bumped = args[2]
+ var/warn = FALSE
+ for(var/datum/artifact_effect/my_effect in my_effects)
+ if(istype(bumped,/obj))
+ if(bumped:throwforce >= 10)
+ if(my_effect.trigger == TRIGGER_FORCE)
+ my_effect.ToggleActivate()
+
+ else if(ishuman(bumped) && GetAnomalySusceptibility(bumped) >= 0.5)
+ if (my_effect.trigger == TRIGGER_TOUCH && prob(50))
+ my_effect.ToggleActivate()
+ warn = 1
+
+ if (my_effect.effect == EFFECT_TOUCH && prob(50))
+ my_effect.DoEffectTouch(bumped)
+ warn = 1
+
+ if(warn && isliving(bumped))
+ to_chat(bumped, "You accidentally touch \the [holder] as it hits you.")
+
+/datum/component/artifact_master/proc/on_bumped()
+ var/atom/movable/M = args[2]
+ var/warn = FALSE
+ for(var/datum/artifact_effect/my_effect in my_effects)
+ if(istype(M,/obj))
+ if(M:throwforce >= 10)
+ if(my_effect.trigger == TRIGGER_FORCE)
+ my_effect.ToggleActivate()
+
+ else if(ishuman(M) && !istype(M:gloves,/obj/item/clothing/gloves))
+ if (my_effect.trigger == TRIGGER_TOUCH && prob(50))
+ my_effect.ToggleActivate()
+ warn = 1
+
+ if (my_effect.effect == EFFECT_TOUCH && prob(50))
+ my_effect.DoEffectTouch(M)
+ warn = 1
+
+ if(warn && isliving(M))
+ to_chat(M, "You accidentally touch \the [holder].")
+
+/datum/component/artifact_master/proc/on_attack_hand()
+ var/mob/living/user = args[2]
+ if(!istype(user))
+ return
+
+ if (get_dist(user, holder) > 1)
+ to_chat(user, "You can't reach [holder] from here.")
+ return
+ if(ishuman(user) && user:gloves)
+ to_chat(user, "You touch [holder] with your gloved hands, [pick("but nothing of note happens","but nothing happens","but nothing interesting happens","but you notice nothing different","but nothing seems to have happened")].")
+ return
+
+ var/triggered = FALSE
+
+ for(var/datum/artifact_effect/my_effect in my_effects)
+
+ if(my_effect.trigger == TRIGGER_TOUCH)
+ triggered = TRUE
+ my_effect.ToggleActivate()
+
+ if (my_effect.effect == EFFECT_TOUCH)
+ triggered = TRUE
+ my_effect.DoEffectTouch(user)
+
+ if(triggered)
+ to_chat(user, "You touch [holder].")
+
+ else
+ to_chat(user, "You touch [holder], [pick("but nothing of note happens","but nothing happens","but nothing interesting happens","but you notice nothing different","but nothing seems to have happened")].")
+
+
+/datum/component/artifact_master/proc/on_attackby()
+ var/obj/item/weapon/W = args[2]
+ for(var/datum/artifact_effect/my_effect in my_effects)
+
+ if (istype(W, /obj/item/weapon/reagent_containers))
+ if(W.reagents.has_reagent("hydrogen", 1) || W.reagents.has_reagent("water", 1))
+ if(my_effect.trigger == TRIGGER_WATER)
+ my_effect.ToggleActivate()
+ else if(W.reagents.has_reagent("sacid", 1) || W.reagents.has_reagent("pacid", 1) || W.reagents.has_reagent("diethylamine", 1))
+ if(my_effect.trigger == TRIGGER_ACID)
+ my_effect.ToggleActivate()
+ else if(W.reagents.has_reagent("phoron", 1) || W.reagents.has_reagent("thermite", 1))
+ if(my_effect.trigger == TRIGGER_VOLATILE)
+ my_effect.ToggleActivate()
+ else if(W.reagents.has_reagent("toxin", 1) || W.reagents.has_reagent("cyanide", 1) || W.reagents.has_reagent("amatoxin", 1) || W.reagents.has_reagent("neurotoxin", 1))
+ if(my_effect.trigger == TRIGGER_TOXIN)
+ my_effect.ToggleActivate()
+ else if(istype(W,/obj/item/weapon/melee/baton) && W:status ||\
+ istype(W,/obj/item/weapon/melee/energy) ||\
+ istype(W,/obj/item/weapon/melee/cultblade) ||\
+ istype(W,/obj/item/weapon/card/emag) ||\
+ istype(W,/obj/item/device/multitool))
+ if (my_effect.trigger == TRIGGER_ENERGY)
+ my_effect.ToggleActivate()
+
+ else if (istype(W,/obj/item/weapon/flame) && W:lit ||\
+ istype(W,/obj/item/weapon/weldingtool) && W:welding)
+ if(my_effect.trigger == TRIGGER_HEAT)
+ my_effect.ToggleActivate()
+ else
+ if (my_effect.trigger == TRIGGER_FORCE && W.force >= 10)
+ my_effect.ToggleActivate()
+
+/datum/component/artifact_master/proc/on_reagent()
+ var/datum/reagent/Touching = args[2]
+
+ var/list/water = list("hydrogen", "water")
+ var/list/acid = list("sacid", "pacid", "diethylamine")
+ var/list/volatile = list("phoron","thermite")
+ var/list/toxic = list("toxin","cyanide","amatoxin","neurotoxin")
+
+ for(var/datum/artifact_effect/my_effect in my_effects)
+ if(Touching.id in water)
+ if(my_effect.trigger == TRIGGER_WATER)
+ my_effect.ToggleActivate()
+ else if(Touching.id in acid)
+ if(my_effect.trigger == TRIGGER_ACID)
+ my_effect.ToggleActivate()
+ else if(Touching.id in volatile)
+ if(my_effect.trigger == TRIGGER_VOLATILE)
+ my_effect.ToggleActivate()
+ else if(Touching.id in toxic)
+ if(my_effect.trigger == TRIGGER_TOXIN)
+ my_effect.ToggleActivate()
+
+/datum/component/artifact_master/proc/on_moved()
+ for(var/datum/artifact_effect/my_effect in my_effects)
+ if(my_effect)
+ my_effect.UpdateMove()
+
+/datum/component/artifact_master/process()
+ if(!holder) // Some instances can be created and rapidly lose their holder, if they are destroyed rapidly on creation. IE, during excavation.
+ STOP_PROCESSING(SSobj, src)
+ if(!QDELETED(src))
+ qdel(src)
+ return
+
+ var/turf/L = holder.loc
+ if(!istype(L) && !isliving(L)) // We're inside a non-mob container or on null turf, either way stop processing effects
+ return
+
+ if(istype(holder, /atom/movable))
+ var/atom/movable/HA = holder
+ if(HA.pulledby)
+ on_bumped(holder, HA.pulledby)
+
+ for(var/datum/artifact_effect/my_effect in my_effects)
+ if(my_effect)
+ my_effect.UpdateMove()
+
+ //if any of our effects rely on environmental factors, work that out
+ var/trigger_cold = 0
+ var/trigger_hot = 0
+ var/trigger_phoron = 0
+ var/trigger_oxy = 0
+ var/trigger_co2 = 0
+ var/trigger_nitro = 0
+
+ var/turf/T = get_turf(holder)
+ var/datum/gas_mixture/env = T.return_air()
+ if(env)
+ if(env.temperature < 225)
+ trigger_cold = 1
+ else if(env.temperature > 375)
+ trigger_hot = 1
+
+ if(env.gas["phoron"] >= 10)
+ trigger_phoron = 1
+ if(env.gas["oxygen"] >= 10)
+ trigger_oxy = 1
+ if(env.gas["carbon_dioxide"] >= 10)
+ trigger_co2 = 1
+ if(env.gas["nitrogen"] >= 10)
+ trigger_nitro = 1
+
+ for(var/datum/artifact_effect/my_effect in my_effects)
+ my_effect.artifact_id = artifact_id
+
+ my_effect.process()
+
+ //COLD ACTIVATION
+ if(my_effect.trigger == TRIGGER_COLD && (trigger_cold ^ my_effect.activated))
+ my_effect.ToggleActivate()
+
+ //HEAT ACTIVATION
+ if(my_effect.trigger == TRIGGER_HEAT && (trigger_hot ^ my_effect.activated))
+ my_effect.ToggleActivate()
+
+ //PHORON GAS ACTIVATION
+ if(my_effect.trigger == TRIGGER_PHORON && (trigger_phoron ^ my_effect.activated))
+ my_effect.ToggleActivate()
+
+ //OXYGEN GAS ACTIVATION
+ if(my_effect.trigger == TRIGGER_OXY && (trigger_oxy ^ my_effect.activated))
+ my_effect.ToggleActivate()
+
+ //CO2 GAS ACTIVATION
+ if(my_effect.trigger == TRIGGER_CO2 && (trigger_co2 ^ my_effect.activated))
+ my_effect.ToggleActivate()
+
+ //NITROGEN GAS ACTIVATION
+ if(my_effect.trigger == TRIGGER_NITRO && (trigger_nitro ^ my_effect.activated))
+ my_effect.ToggleActivate()
+
diff --git a/code/modules/xenoarcheaology/effects/animate_anomaly.dm b/code/modules/xenoarcheaology/effects/animate_anomaly.dm
index c0c17e4aafd..7cf3e408e91 100644
--- a/code/modules/xenoarcheaology/effects/animate_anomaly.dm
+++ b/code/modules/xenoarcheaology/effects/animate_anomaly.dm
@@ -4,6 +4,9 @@
effect_type = EFFECT_PSIONIC
var/mob/living/target = null
+ effect_state = "pulsing"
+ effect_color = "#00c3ff"
+
/datum/artifact_effect/animate_anomaly/ToggleActivate(var/reveal_toggle = 1)
..()
find_target()
@@ -13,21 +16,24 @@
effectrange = max(3, effectrange)
/datum/artifact_effect/animate_anomaly/proc/find_target()
- if(!target || target.z != holder.z || get_dist(target, holder) > effectrange)
+ var/atom/masterholder = get_master_holder()
+
+ if(!target || target.z != masterholder.z || get_dist(target, masterholder) > effectrange)
var/mob/living/ClosestMob = null
- for(var/mob/living/L in range(effectrange, holder))
+ for(var/mob/living/L in range(effectrange, get_turf(masterholder)))
if(!L.mind)
continue
if(!ClosestMob)
ClosestMob = L
continue
if(!L.stat)
- if(get_dist(holder, L) < get_dist(holder, ClosestMob))
+ if(get_dist(masterholder, L) < get_dist(masterholder, ClosestMob))
ClosestMob = L
target = ClosestMob
/datum/artifact_effect/animate_anomaly/DoEffectTouch(var/mob/living/user)
+ var/atom/holder = get_master_holder()
var/obj/O = holder
var/turf/T = get_step_away(O, user)
@@ -36,25 +42,23 @@
O.visible_message("\The [holder] lurches away from [user]")
/datum/artifact_effect/animate_anomaly/DoEffectAura()
- var/obj/O = holder
- if(!target || target.z != O.z || get_dist(target, O) > effectrange)
- target = null
- find_target()
- var/turf/T = get_step_to(O, target)
+ var/obj/O = get_master_holder()
+ find_target()
- if(target && istype(T) && istype(O.loc, /turf))
- if(get_dist(O, T) > 1)
- O.Move(T)
- O.visible_message("\The [holder] lurches toward [target]")
+ if(!target || !istype(O))
+ return
+
+ O.dir = get_dir(O, target)
+
+ if(!target || !istype(O))
+ return
+
+ O.dir = get_dir(O, target)
+
+ if(istype(O.loc, /turf))
+ if(get_dist(O.loc, target.loc) > 1)
+ O.Move(get_step_to(O, target))
+ O.visible_message("\The [O] lurches toward [target]")
/datum/artifact_effect/animate_anomaly/DoEffectPulse()
- var/obj/O = holder
- if(!target || target.z != O.z || get_dist(target, O) > effectrange)
- target = null
- find_target()
- var/turf/T = get_step_to(O, target)
-
- if(target && istype(T) && istype(O.loc, /turf))
- if(get_dist(O, T) > 1)
- O.Move(T)
- O.visible_message("\The [holder] lurches toward [target]")
+ DoEffectAura()
diff --git a/code/modules/xenoarcheaology/effects/badfeeling.dm b/code/modules/xenoarcheaology/effects/badfeeling.dm
index a0aa7dc7754..2a7e480e18d 100644
--- a/code/modules/xenoarcheaology/effects/badfeeling.dm
+++ b/code/modules/xenoarcheaology/effects/badfeeling.dm
@@ -25,6 +25,9 @@
"OH GOD!",
"HELP ME!")
+ effect_state = "summoning"
+ effect_color = "#643232"
+
/datum/artifact_effect/badfeeling/DoEffectTouch(var/mob/user)
if(user)
if (istype(user, /mob/living/carbon/human))
@@ -39,6 +42,7 @@
H.dizziness += rand(3,5)
/datum/artifact_effect/badfeeling/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,T))
@@ -53,6 +57,7 @@
return 1
/datum/artifact_effect/badfeeling/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,T))
diff --git a/code/modules/xenoarcheaology/effects/berserk.dm b/code/modules/xenoarcheaology/effects/berserk.dm
index a221c9104c2..4965747909c 100644
--- a/code/modules/xenoarcheaology/effects/berserk.dm
+++ b/code/modules/xenoarcheaology/effects/berserk.dm
@@ -2,6 +2,9 @@
name = "berserk"
effect_type = EFFECT_PSIONIC
+ effect_state = "summoning"
+ effect_color = "#5f0000"
+
/datum/artifact_effect/berserk/proc/apply_berserk(var/mob/living/L)
if(!istype(L))
return FALSE
@@ -28,6 +31,7 @@
return TRUE
/datum/artifact_effect/berserk/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for(var/mob/living/L in range(src.effectrange,T))
@@ -36,6 +40,7 @@
return TRUE
/datum/artifact_effect/berserk/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for(var/mob/living/L in range(src.effectrange,T))
diff --git a/code/modules/xenoarcheaology/effects/cannibal.dm b/code/modules/xenoarcheaology/effects/cannibal.dm
index 04a0b5a9e8e..ad584ccc7cd 100644
--- a/code/modules/xenoarcheaology/effects/cannibal.dm
+++ b/code/modules/xenoarcheaology/effects/cannibal.dm
@@ -25,6 +25,9 @@
"Butcher them!",
"Feast!")
+ effect_state = "summoning"
+ effect_color = "#c50303"
+
/datum/artifact_effect/cannibalfeeling/DoEffectTouch(var/mob/user)
if(user)
if (istype(user, /mob/living/carbon/human))
@@ -41,6 +44,7 @@
H.nutrition = H.nutrition / 1.5
/datum/artifact_effect/cannibalfeeling/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,T))
@@ -57,6 +61,7 @@
return 1
/datum/artifact_effect/cannibalfeeling/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,T))
diff --git a/code/modules/xenoarcheaology/effects/cellcharge.dm b/code/modules/xenoarcheaology/effects/cellcharge.dm
index b5c8e6224b4..42f64eb8dd4 100644
--- a/code/modules/xenoarcheaology/effects/cellcharge.dm
+++ b/code/modules/xenoarcheaology/effects/cellcharge.dm
@@ -4,6 +4,8 @@
effect_type = EFFECT_ELECTRO
var/last_message
+ effect_color = "#ffee06"
+
/datum/artifact_effect/cellcharge/DoEffectTouch(var/mob/user)
if(user)
if(isrobot(user))
@@ -14,6 +16,7 @@
return 1
/datum/artifact_effect/cellcharge/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/obj/machinery/power/apc/C in GLOB.apcs)
@@ -42,6 +45,7 @@
return 1
/datum/artifact_effect/cellcharge/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/obj/machinery/power/apc/C in GLOB.apcs)
diff --git a/code/modules/xenoarcheaology/effects/celldrain.dm b/code/modules/xenoarcheaology/effects/celldrain.dm
index ee279032ec5..c8a270c0595 100644
--- a/code/modules/xenoarcheaology/effects/celldrain.dm
+++ b/code/modules/xenoarcheaology/effects/celldrain.dm
@@ -4,6 +4,9 @@
effect_type = EFFECT_ELECTRO
var/last_message
+ effect_state = "pulsing"
+ effect_color = "#fbff02"
+
/datum/artifact_effect/celldrain/DoEffectTouch(var/mob/user)
if(user)
if(istype(user, /mob/living/silicon/robot))
@@ -16,6 +19,7 @@
return 1
/datum/artifact_effect/celldrain/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/obj/machinery/power/apc/C in GLOB.apcs)
@@ -44,6 +48,7 @@
return 1
/datum/artifact_effect/celldrain/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/obj/machinery/power/apc/C in GLOB.apcs)
diff --git a/code/modules/xenoarcheaology/effects/cold.dm b/code/modules/xenoarcheaology/effects/cold.dm
index 9855ac280b0..f20fdf00d55 100644
--- a/code/modules/xenoarcheaology/effects/cold.dm
+++ b/code/modules/xenoarcheaology/effects/cold.dm
@@ -3,6 +3,8 @@
name = "cold"
var/target_temp
+ effect_color = "#b3f6ff"
+
/datum/artifact_effect/cold/New()
..()
target_temp = rand(0, 250)
@@ -10,6 +12,7 @@
effect_type = pick(EFFECT_ORGANIC, EFFECT_BLUESPACE, EFFECT_SYNTH)
/datum/artifact_effect/cold/DoEffectTouch(var/mob/user)
+ var/atom/holder = get_master_holder()
if(holder)
to_chat(user, "A chill passes up your spine!")
var/datum/gas_mixture/env = holder.loc.return_air()
@@ -17,6 +20,7 @@
env.temperature = max(env.temperature - rand(5,50), 0)
/datum/artifact_effect/cold/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env && env.temperature > target_temp)
diff --git a/code/modules/xenoarcheaology/effects/dnaswitch.dm b/code/modules/xenoarcheaology/effects/dnaswitch.dm
index c4c36cb5b10..f9d20475f75 100644
--- a/code/modules/xenoarcheaology/effects/dnaswitch.dm
+++ b/code/modules/xenoarcheaology/effects/dnaswitch.dm
@@ -4,6 +4,9 @@
effect_type = EFFECT_ORGANIC
var/severity
+ effect_state = "smoke"
+ effect_color = "#77ff83"
+
/datum/artifact_effect/dnaswitch/New()
..()
if(effect == EFFECT_AURA)
@@ -28,6 +31,7 @@
return 1
/datum/artifact_effect/dnaswitch/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for(var/mob/living/carbon/human/H in range(src.effectrange,T))
@@ -47,6 +51,7 @@
scramble(0, H, weakness * severity)
/datum/artifact_effect/dnaswitch/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for(var/mob/living/carbon/human/H in range(200, T))
diff --git a/code/modules/xenoarcheaology/effects/electric_field.dm b/code/modules/xenoarcheaology/effects/electric_field.dm
index 3b27e8fe42e..1ba181bb456 100644
--- a/code/modules/xenoarcheaology/effects/electric_field.dm
+++ b/code/modules/xenoarcheaology/effects/electric_field.dm
@@ -3,7 +3,10 @@
name = "electric field"
effect_type = EFFECT_ENERGY
+ effect_color = "#ffff00"
+
/datum/artifact_effect/electric_field/DoEffectTouch(var/mob/user)
+ var/atom/holder = get_master_holder()
var/list/nearby_mobs = list()
for(var/mob/living/L in oview(effectrange, get_turf(holder)))
if(L == user) // You're "grounded" when you contact the artifact.
@@ -27,6 +30,7 @@
L.electrocute_act(rand(25, 40), holder, 0.75, BP_TORSO)
/datum/artifact_effect/electric_field/DoEffectAura()
+ var/atom/holder = get_master_holder()
var/list/nearby_mobs = list()
for(var/mob/living/L in oview(effectrange, get_turf(holder)))
if(!L.stat)
@@ -48,6 +52,7 @@
L.electrocute_act(rand(1, 10), holder, 0.75, BP_TORSO)
/datum/artifact_effect/electric_field/DoEffectPulse()
+ var/atom/holder = get_master_holder()
var/list/nearby_mobs = list()
for(var/mob/living/L in oview(effectrange, get_turf(holder)))
if(!L.stat)
diff --git a/code/modules/xenoarcheaology/effects/emp.dm b/code/modules/xenoarcheaology/effects/emp.dm
index fd30420b577..8b9d969a3e9 100644
--- a/code/modules/xenoarcheaology/effects/emp.dm
+++ b/code/modules/xenoarcheaology/effects/emp.dm
@@ -2,11 +2,14 @@
name = "emp"
effect_type = EFFECT_ELECTRO
+ effect_state = "empdisable"
+
/datum/artifact_effect/emp/New()
..()
effect = EFFECT_PULSE
/datum/artifact_effect/emp/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
empulse(T, effectrange/4, effectrange/3, effectrange/2, effectrange)
diff --git a/code/modules/xenoarcheaology/effects/feysight.dm b/code/modules/xenoarcheaology/effects/feysight.dm
index 379dc0cc542..70bceb7bcca 100644
--- a/code/modules/xenoarcheaology/effects/feysight.dm
+++ b/code/modules/xenoarcheaology/effects/feysight.dm
@@ -2,6 +2,9 @@
name = "feysight"
effect_type = EFFECT_PSIONIC
+ effect_state = "pulsing"
+ effect_color = "#00c763"
+
/datum/artifact_effect/feysight/proc/apply_modifier(var/mob/living/L)
if(!istype(L))
return FALSE
@@ -28,6 +31,7 @@
return TRUE
/datum/artifact_effect/feysight/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for(var/mob/living/L in range(src.effectrange,T))
@@ -36,6 +40,7 @@
return TRUE
/datum/artifact_effect/feysight/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for(var/mob/living/L in range(src.effectrange,T))
diff --git a/code/modules/xenoarcheaology/effects/forcefield.dm b/code/modules/xenoarcheaology/effects/forcefield.dm
index f4f1a3ab073..661563ccc70 100644
--- a/code/modules/xenoarcheaology/effects/forcefield.dm
+++ b/code/modules/xenoarcheaology/effects/forcefield.dm
@@ -3,11 +3,15 @@
var/list/created_field = list()
effect_type = EFFECT_PARTICLE
+ effect_state = "shield-old"
+ effect_color = "#00b7ff"
+
/datum/artifact_effect/forcefield/New()
..()
trigger = TRIGGER_TOUCH
/datum/artifact_effect/forcefield/ToggleActivate()
+ var/atom/holder = get_master_holder()
..()
if(created_field.len)
for(var/obj/effect/energy_field/F in created_field)
@@ -35,6 +39,7 @@
E.adjust_strength(0.25, 0)
/datum/artifact_effect/forcefield/UpdateMove()
+ var/atom/holder = get_master_holder()
if(created_field.len && holder)
var/turf/T = get_turf(holder)
while(created_field.len < 16)
diff --git a/code/modules/xenoarcheaology/effects/gaia.dm b/code/modules/xenoarcheaology/effects/gaia.dm
index 1a89149818e..42869fd5568 100644
--- a/code/modules/xenoarcheaology/effects/gaia.dm
+++ b/code/modules/xenoarcheaology/effects/gaia.dm
@@ -5,6 +5,8 @@
var/list/my_glitterflies = list()
+ effect_color = "#8cd448"
+
/datum/artifact_effect/gaia/proc/age_plantlife(var/obj/machinery/portable_atmospherics/hydroponics/Tray = null)
if(istype(Tray) && Tray.seed)
Tray.health += rand(1,3) * HYDRO_SPEED_MULTIPLIER
@@ -30,6 +32,7 @@
P.update_icon()
/datum/artifact_effect/gaia/DoEffectTouch(var/mob/user)
+ var/atom/holder = get_master_holder()
to_chat(user, "You feel the presence of something long forgotten.")
for(var/obj/machinery/portable_atmospherics/hydroponics/Tray in view(world.view,get_turf(holder)))
age_plantlife(Tray)
@@ -44,6 +47,7 @@
age_plantlife(P)
/datum/artifact_effect/gaia/DoEffectAura()
+ var/atom/holder = get_master_holder()
for(var/obj/machinery/portable_atmospherics/hydroponics/Tray in view(effectrange,holder))
age_plantlife(Tray)
if(prob(2))
@@ -57,6 +61,7 @@
age_plantlife(P)
/datum/artifact_effect/gaia/DoEffectPulse()
+ var/atom/holder = get_master_holder()
for(var/obj/machinery/portable_atmospherics/hydroponics/Tray in view(effectrange,holder))
age_plantlife(Tray)
if(prob(10))
@@ -70,6 +75,7 @@
age_plantlife(P)
/datum/artifact_effect/gaia/process()
+ var/atom/holder = get_master_holder()
..()
listclearnulls(my_glitterflies)
diff --git a/code/modules/xenoarcheaology/effects/gasco2.dm b/code/modules/xenoarcheaology/effects/gasco2.dm
index 264dca7352c..5543517dac2 100644
--- a/code/modules/xenoarcheaology/effects/gasco2.dm
+++ b/code/modules/xenoarcheaology/effects/gasco2.dm
@@ -1,18 +1,22 @@
/datum/artifact_effect/gasco2
name = "CO2 creation"
+ effect_color = "#a5a5a5"
+
/datum/artifact_effect/gasco2/New()
..()
effect = pick(EFFECT_TOUCH, EFFECT_AURA)
effect_type = pick(EFFECT_BLUESPACE, EFFECT_SYNTH)
/datum/artifact_effect/gasco2/DoEffectTouch(var/mob/user)
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/holder_loc = holder.loc
if(istype(holder_loc))
holder_loc.assume_gas("carbon_dioxide", rand(2, 15))
/datum/artifact_effect/gasco2/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/holder_loc = holder.loc
if(istype(holder_loc))
diff --git a/code/modules/xenoarcheaology/effects/gasnitro.dm b/code/modules/xenoarcheaology/effects/gasnitro.dm
index 42b440fc1cb..e076ff3aa3b 100644
--- a/code/modules/xenoarcheaology/effects/gasnitro.dm
+++ b/code/modules/xenoarcheaology/effects/gasnitro.dm
@@ -1,18 +1,22 @@
/datum/artifact_effect/gasnitro
name = "N2 creation"
+ effect_color = "#c2d3d8"
+
/datum/artifact_effect/gasnitro/New()
..()
effect = pick(EFFECT_TOUCH, EFFECT_AURA)
effect_type = pick(EFFECT_BLUESPACE, EFFECT_SYNTH)
/datum/artifact_effect/gasnitro/DoEffectTouch(var/mob/user)
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/holder_loc = holder.loc
if(istype(holder_loc))
holder_loc.assume_gas("nitrogen", rand(2, 15))
/datum/artifact_effect/gasnitro/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/holder_loc = holder.loc
if(istype(holder_loc))
diff --git a/code/modules/xenoarcheaology/effects/gasoxy.dm b/code/modules/xenoarcheaology/effects/gasoxy.dm
index bb159509dc8..798154e38aa 100644
--- a/code/modules/xenoarcheaology/effects/gasoxy.dm
+++ b/code/modules/xenoarcheaology/effects/gasoxy.dm
@@ -7,12 +7,14 @@
effect_type = pick(EFFECT_BLUESPACE, EFFECT_SYNTH)
/datum/artifact_effect/gasoxy/DoEffectTouch(var/mob/user)
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/holder_loc = holder.loc
if(istype(holder_loc))
holder_loc.assume_gas("oxygen", rand(2, 15))
/datum/artifact_effect/gasoxy/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/holder_loc = holder.loc
if(istype(holder_loc))
diff --git a/code/modules/xenoarcheaology/effects/gasphoron.dm b/code/modules/xenoarcheaology/effects/gasphoron.dm
index b84296fbb8a..66cdee98c27 100644
--- a/code/modules/xenoarcheaology/effects/gasphoron.dm
+++ b/code/modules/xenoarcheaology/effects/gasphoron.dm
@@ -1,18 +1,22 @@
/datum/artifact_effect/gasphoron
name = "phoron creation"
+ effect_color = "#c408ba"
+
/datum/artifact_effect/gasphoron/New()
..()
effect = pick(EFFECT_TOUCH, EFFECT_AURA)
effect_type = pick(EFFECT_BLUESPACE, EFFECT_SYNTH)
/datum/artifact_effect/gasphoron/DoEffectTouch(var/mob/user)
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/holder_loc = holder.loc
if(istype(holder_loc))
holder_loc.assume_gas("phoron", rand(2, 15))
/datum/artifact_effect/gasphoron/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/holder_loc = holder.loc
if(istype(holder_loc))
diff --git a/code/modules/xenoarcheaology/effects/gassleeping.dm b/code/modules/xenoarcheaology/effects/gassleeping.dm
index 3c12f8f91c1..a77ca5b88d7 100644
--- a/code/modules/xenoarcheaology/effects/gassleeping.dm
+++ b/code/modules/xenoarcheaology/effects/gassleeping.dm
@@ -7,12 +7,14 @@
effect_type = pick(EFFECT_BLUESPACE, EFFECT_SYNTH)
/datum/artifact_effect/gassleeping/DoEffectTouch(var/mob/user)
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/holder_loc = holder.loc
if(istype(holder_loc))
holder_loc.assume_gas("nitrous_oxide", rand(2, 15))
/datum/artifact_effect/gassleeping/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/holder_loc = holder.loc
if(istype(holder_loc))
diff --git a/code/modules/xenoarcheaology/effects/goodfeeling.dm b/code/modules/xenoarcheaology/effects/goodfeeling.dm
index c5d05adc5e3..42b1be7e3a2 100644
--- a/code/modules/xenoarcheaology/effects/goodfeeling.dm
+++ b/code/modules/xenoarcheaology/effects/goodfeeling.dm
@@ -23,6 +23,9 @@
"You're so happy suddenly, you almost want to dance and sing.",
"You feel like the world is out to help you.")
+ effect_state = "summoning"
+ effect_color = "#009118"
+
/datum/artifact_effect/goodfeeling/DoEffectTouch(var/mob/user)
if(user)
if (istype(user, /mob/living/carbon/human))
@@ -37,6 +40,7 @@
H.dizziness += rand(3,5)
/datum/artifact_effect/goodfeeling/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,T))
@@ -51,6 +55,7 @@
return 1
/datum/artifact_effect/goodfeeling/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,T))
diff --git a/code/modules/xenoarcheaology/effects/gravitational_waves.dm b/code/modules/xenoarcheaology/effects/gravitational_waves.dm
index 6798eef64c6..d34b352ea09 100644
--- a/code/modules/xenoarcheaology/effects/gravitational_waves.dm
+++ b/code/modules/xenoarcheaology/effects/gravitational_waves.dm
@@ -5,10 +5,14 @@
var/last_wave_pull = 0
+ effect_state = "gravisphere"
+ effect_color = "#d8c3ff"
+
/datum/artifact_effect/gravity_wave/DoEffectTouch(var/mob/user)
gravwave(user, effectrange, STAGE_TWO)
/datum/artifact_effect/gravity_wave/DoEffectAura()
+ var/atom/holder = get_master_holder()
var/seconds_since_last_pull = max(0, round((last_wave_pull - world.time) / 10))
if(prob(10 + seconds_since_last_pull))
@@ -17,6 +21,7 @@
gravwave(get_turf(holder), effectrange, STAGE_TWO)
/datum/artifact_effect/gravity_wave/DoEffectPulse()
+ var/atom/holder = get_master_holder()
holder.visible_message("\The [holder] distorts as local gravity intensifies, and shifts toward it.")
gravwave(get_turf(holder), effectrange, STAGE_TWO)
diff --git a/code/modules/xenoarcheaology/effects/heal.dm b/code/modules/xenoarcheaology/effects/heal.dm
index 39bb09d04e1..313bbc011e5 100644
--- a/code/modules/xenoarcheaology/effects/heal.dm
+++ b/code/modules/xenoarcheaology/effects/heal.dm
@@ -1,6 +1,7 @@
/datum/artifact_effect/heal
name = "heal"
effect_type = EFFECT_ORGANIC
+ effect_color = "#4649ff"
/datum/artifact_effect/heal/DoEffectTouch(var/mob/toucher)
//todo: check over this properly
@@ -33,6 +34,7 @@
return 1
/datum/artifact_effect/heal/DoEffectAura()
+ var/atom/holder = get_master_holder()
//todo: check over this properly
if(holder)
var/turf/T = get_turf(holder)
@@ -49,6 +51,7 @@
C.updatehealth()
/datum/artifact_effect/heal/DoEffectPulse()
+ var/atom/holder = get_master_holder()
//todo: check over this properly
if(holder)
var/turf/T = get_turf(holder)
diff --git a/code/modules/xenoarcheaology/effects/heat.dm b/code/modules/xenoarcheaology/effects/heat.dm
index 720d1464433..0bb3ae1f104 100644
--- a/code/modules/xenoarcheaology/effects/heat.dm
+++ b/code/modules/xenoarcheaology/effects/heat.dm
@@ -2,6 +2,7 @@
/datum/artifact_effect/heat
name = "heat"
var/target_temp
+ effect_color = "#ff6600"
/datum/artifact_effect/heat/New()
..()
@@ -10,6 +11,7 @@
target_temp = rand(300, 600)
/datum/artifact_effect/heat/DoEffectTouch(var/mob/user)
+ var/atom/holder = get_master_holder()
if(holder)
to_chat(user, " You feel a wave of heat travel up your spine!")
var/datum/gas_mixture/env = holder.loc.return_air()
@@ -17,6 +19,7 @@
env.temperature += rand(5,50)
/datum/artifact_effect/heat/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/datum/gas_mixture/env = holder.loc.return_air()
if(env && env.temperature < target_temp)
diff --git a/code/modules/xenoarcheaology/effects/hurt.dm b/code/modules/xenoarcheaology/effects/hurt.dm
index 14aff4e6248..a2c8d54163f 100644
--- a/code/modules/xenoarcheaology/effects/hurt.dm
+++ b/code/modules/xenoarcheaology/effects/hurt.dm
@@ -2,6 +2,8 @@
name = "hurt"
effect_type = EFFECT_ORGANIC
+ effect_color = "#6d1212"
+
/datum/artifact_effect/hurt/DoEffectTouch(var/mob/toucher)
if(toucher)
var/weakness = GetAnomalySusceptibility(toucher)
@@ -20,6 +22,7 @@
C.weakened += 6 * weakness
/datum/artifact_effect/hurt/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/carbon/C in range(src.effectrange,T))
@@ -35,6 +38,7 @@
C.updatehealth()
/datum/artifact_effect/hurt/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/carbon/C in range(effectrange, T))
diff --git a/code/modules/xenoarcheaology/effects/poltergeist.dm b/code/modules/xenoarcheaology/effects/poltergeist.dm
index 189c0ea4cdb..5b270fd38c0 100644
--- a/code/modules/xenoarcheaology/effects/poltergeist.dm
+++ b/code/modules/xenoarcheaology/effects/poltergeist.dm
@@ -3,6 +3,9 @@
name = "poltergeist"
effect_type = EFFECT_ENERGY
+ effect_state = "shield2"
+ effect_color = "#a824c9"
+
/datum/artifact_effect/poltergeist/proc/throw_at_mob(var/mob/living/target, var/damage = 20)
var/list/valid_targets = list()
@@ -19,6 +22,7 @@
throw_at_mob(user, rand(10, 30))
/datum/artifact_effect/poltergeist/DoEffectAura()
+ var/atom/holder = get_master_holder()
var/mob/living/target = null
for(var/mob/living/L in oview(get_turf(holder), effectrange))
if(L.stat || !L.mind)
@@ -33,6 +37,7 @@
throw_at_mob(target, rand(15, 30))
/datum/artifact_effect/poltergeist/DoEffectPulse()
+ var/atom/holder = get_master_holder()
var/mob/living/target = null
for(var/mob/living/L in oview(get_turf(holder), effectrange))
if(L.stat || !L.mind)
diff --git a/code/modules/xenoarcheaology/effects/radiate.dm b/code/modules/xenoarcheaology/effects/radiate.dm
index e38540eb045..88a37b3e067 100644
--- a/code/modules/xenoarcheaology/effects/radiate.dm
+++ b/code/modules/xenoarcheaology/effects/radiate.dm
@@ -2,6 +2,8 @@
name = "radiation"
var/radiation_amount
+ effect_color = "#007006"
+
/datum/artifact_effect/radiate/New()
..()
radiation_amount = rand(1, 10)
@@ -14,11 +16,13 @@
return 1
/datum/artifact_effect/radiate/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
SSradiation.flat_radiate(holder, radiation_amount, src.effectrange)
return 1
/datum/artifact_effect/radiate/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
SSradiation.radiate(holder, ((radiation_amount * 3) * (sqrt(src.effectrange)))) //Need to get feedback on this //VOREStation Edit - Was too crazy-strong.
return 1
diff --git a/code/modules/xenoarcheaology/effects/resurrect.dm b/code/modules/xenoarcheaology/effects/resurrect.dm
index e54ca276ea8..0fbb8c6aef4 100644
--- a/code/modules/xenoarcheaology/effects/resurrect.dm
+++ b/code/modules/xenoarcheaology/effects/resurrect.dm
@@ -4,7 +4,11 @@
var/stored_life = 0
+ effect_state = "pulsing"
+ effect_color = "#ff0000"
+
/datum/artifact_effect/resurrect/proc/steal_life(var/mob/living/target = null)
+ var/atom/holder = get_master_holder()
if(!istype(target))
return 0
@@ -16,6 +20,7 @@
return 0
/datum/artifact_effect/resurrect/proc/give_life(var/mob/living/target = null)
+ var/atom/holder = get_master_holder()
if(!istype(target))
return
@@ -34,6 +39,7 @@
stored_life = 0
/datum/artifact_effect/resurrect/proc/attempt_revive(var/mob/living/L = null)
+ var/atom/holder = get_master_holder()
spawn()
if(istype(L, /mob/living/simple_mob))
var/mob/living/simple_mob/SM = L
@@ -70,6 +76,7 @@
holder.visible_message("\The [H]'s eyes open in a flash of light!")
/datum/artifact_effect/resurrect/DoEffectTouch(var/mob/user)
+ var/atom/holder = get_master_holder()
for(var/mob/living/L in oview(effectrange, get_turf(holder)))
stored_life += 4 * steal_life(L)
@@ -80,6 +87,7 @@
break
/datum/artifact_effect/resurrect/DoEffectAura()
+ var/atom/holder = get_master_holder()
for(var/mob/living/L in oview(effectrange, get_turf(holder)))
stored_life += steal_life(L)
@@ -90,6 +98,7 @@
break
/datum/artifact_effect/resurrect/DoEffectPulse()
+ var/atom/holder = get_master_holder()
for(var/mob/living/L in oview(effectrange, get_turf(holder)))
stored_life += 2 * steal_life(L)
diff --git a/code/modules/xenoarcheaology/effects/roboheal.dm b/code/modules/xenoarcheaology/effects/roboheal.dm
index 0052a539793..16660029b77 100644
--- a/code/modules/xenoarcheaology/effects/roboheal.dm
+++ b/code/modules/xenoarcheaology/effects/roboheal.dm
@@ -2,6 +2,8 @@
name = "robotic healing"
var/last_message
+ effect_color = "#3879ad"
+
/datum/artifact_effect/roboheal/New()
..()
effect_type = pick(EFFECT_ELECTRO, EFFECT_PARTICLE)
@@ -16,6 +18,7 @@
return 1
/datum/artifact_effect/roboheal/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/silicon/robot/M in range(src.effectrange,T))
@@ -28,6 +31,7 @@
return 1
/datum/artifact_effect/roboheal/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/silicon/robot/M in range(src.effectrange,T))
diff --git a/code/modules/xenoarcheaology/effects/robohurt.dm b/code/modules/xenoarcheaology/effects/robohurt.dm
index 8ed47a9e281..8b93e04ead4 100644
--- a/code/modules/xenoarcheaology/effects/robohurt.dm
+++ b/code/modules/xenoarcheaology/effects/robohurt.dm
@@ -2,6 +2,8 @@
name = "robotic harm"
var/last_message
+ effect_color = "#5432cf"
+
/datum/artifact_effect/robohurt/New()
..()
effect_type = pick(EFFECT_ELECTRO, EFFECT_PARTICLE)
@@ -16,6 +18,7 @@
return 1
/datum/artifact_effect/robohurt/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/silicon/robot/M in range(src.effectrange,T))
@@ -28,6 +31,7 @@
return 1
/datum/artifact_effect/robohurt/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/silicon/robot/M in range(src.effectrange,T))
diff --git a/code/modules/xenoarcheaology/effects/sleepy.dm b/code/modules/xenoarcheaology/effects/sleepy.dm
index 6a0439460a1..244814a1da7 100644
--- a/code/modules/xenoarcheaology/effects/sleepy.dm
+++ b/code/modules/xenoarcheaology/effects/sleepy.dm
@@ -1,6 +1,7 @@
//todo
/datum/artifact_effect/sleepy
name = "sleepy"
+ effect_color = "#a36fa1"
/datum/artifact_effect/sleepy/New()
..()
@@ -20,6 +21,7 @@
return 1
/datum/artifact_effect/sleepy/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/carbon/human/H in range(src.effectrange,T))
@@ -34,6 +36,7 @@
return 1
/datum/artifact_effect/sleepy/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for(var/mob/living/carbon/human/H in range(src.effectrange, T))
diff --git a/code/modules/xenoarcheaology/effects/stun.dm b/code/modules/xenoarcheaology/effects/stun.dm
index ab00465477e..12ca276b93d 100644
--- a/code/modules/xenoarcheaology/effects/stun.dm
+++ b/code/modules/xenoarcheaology/effects/stun.dm
@@ -1,5 +1,6 @@
/datum/artifact_effect/stun
name = "stun"
+ effect_color = "#00eeff"
/datum/artifact_effect/stun/New()
..()
@@ -16,6 +17,7 @@
C.Stun(rand(1,10) * susceptibility)
/datum/artifact_effect/stun/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/carbon/C in range(src.effectrange,T))
@@ -30,6 +32,7 @@
to_chat(C, "You feel numb.")
/datum/artifact_effect/stun/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/carbon/C in range(src.effectrange,T))
diff --git a/code/modules/xenoarcheaology/effects/teleport.dm b/code/modules/xenoarcheaology/effects/teleport.dm
index 36b90afd31b..2c766323db1 100644
--- a/code/modules/xenoarcheaology/effects/teleport.dm
+++ b/code/modules/xenoarcheaology/effects/teleport.dm
@@ -1,8 +1,11 @@
/datum/artifact_effect/teleport
name = "teleport"
effect_type = EFFECT_BLUESPACE
+ effect_state = "pulsing"
+ effect_color = "#88ffdb"
/datum/artifact_effect/teleport/DoEffectTouch(var/mob/user)
+ var/atom/holder = get_master_holder()
var/weakness = GetAnomalySusceptibility(user)
if(prob(100 * weakness))
to_chat(user, "You are suddenly zapped away elsewhere!")
@@ -20,6 +23,7 @@
sparks.start()
/datum/artifact_effect/teleport/DoEffectAura()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/M in range(src.effectrange,T))
@@ -39,6 +43,7 @@
sparks.start()
/datum/artifact_effect/teleport/DoEffectPulse()
+ var/atom/holder = get_master_holder()
if(holder)
var/turf/T = get_turf(holder)
for (var/mob/living/M in range(src.effectrange, T))
diff --git a/code/modules/xenoarcheaology/effects/vampire.dm b/code/modules/xenoarcheaology/effects/vampire.dm
index e5a069b9351..7c6ed91a5f4 100644
--- a/code/modules/xenoarcheaology/effects/vampire.dm
+++ b/code/modules/xenoarcheaology/effects/vampire.dm
@@ -9,7 +9,11 @@
var/charges = 0
var/list/nearby_mobs = list()
+ effect_state = "gravisphere"
+ effect_color = "#ff0000"
+
/datum/artifact_effect/vampire/proc/bloodcall(var/mob/living/carbon/human/M)
+ var/atom/holder = get_master_holder()
last_bloodcall = world.time
if(istype(M))
playsound(holder, pick('sound/hallucinations/wail.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/far_noise.ogg'), 50, 1, -3)
@@ -23,30 +27,29 @@
B.target_turf = pick(range(1, get_turf(holder)))
B.blood_DNA = list()
B.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type
- M.vessel.remove_reagent("blood",rand(25,50))
+ M.vessel.remove_reagent("blood",rand(10,30))
/datum/artifact_effect/vampire/DoEffectTouch(var/mob/user)
bloodcall(user)
DoEffectAura()
/datum/artifact_effect/vampire/DoEffectAura()
- if (nearby_mobs.len)
+ var/atom/holder = get_master_holder()
+ if(nearby_mobs.len)
nearby_mobs.Cut()
-
var/turf/T = get_turf(holder)
for(var/mob/living/L in oview(effectrange, T))
if(!L.stat && L.mind)
nearby_mobs |= L
- if(world.time - last_bloodcall > bloodcall_interval && nearby_mobs.len)
+ if(world.time - bloodcall_interval >= last_bloodcall && LAZYLEN(nearby_mobs))
var/mob/living/carbon/human/M = pick(nearby_mobs)
- if(M in view(effectrange,holder) && M.health > 20)
- if(prob(50))
- bloodcall(M)
- holder.Beam(M, icon_state = "drainbeam", time = 1 SECOND)
+ if(get_dist(M, T) <= effectrange && M.health > 20)
+ bloodcall(M)
+ holder.Beam(M, icon_state = "drainbeam", time = 1 SECOND)
- if(world.time - last_eat > eat_interval)
+ if(world.time - last_eat >= eat_interval)
var/obj/effect/decal/cleanable/blood/B = locate() in range(2,holder)
if(B)
last_eat = world.time
@@ -62,13 +65,13 @@
if(charges >= 10)
charges -= 10
var/manifestation = pick(/obj/item/device/soulstone, /mob/living/simple_mob/faithless/cult/strong, /mob/living/simple_mob/creature/cult/strong, /mob/living/simple_mob/animal/space/bats/cult/strong)
- new manifestation(get_turf(pick(view(1,T))))
+ new manifestation(pick(RANGE_TURFS(1,T)))
if(charges >= 3)
if(prob(5))
charges -= 1
var/spawn_type = pick(/mob/living/simple_mob/animal/space/bats, /mob/living/simple_mob/creature, /mob/living/simple_mob/faithless)
- new spawn_type(get_turf(pick(view(1,T))))
+ new spawn_type(pick(RANGE_TURFS(1,T)))
playsound(holder, pick('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg'), 50, 1, -3)
if(charges >= 1 && nearby_mobs.len && prob(15 * nearby_mobs.len))
diff --git a/code/modules/xenoarcheaology/finds/find_spawning.dm b/code/modules/xenoarcheaology/finds/find_spawning.dm
index 2b6e1258551..354c160a8a6 100644
--- a/code/modules/xenoarcheaology/finds/find_spawning.dm
+++ b/code/modules/xenoarcheaology/finds/find_spawning.dm
@@ -15,18 +15,20 @@
var/additional_desc = ""
var/obj/item/weapon/new_item
var/source_material = ""
- var/apply_material_decorations = 1
- var/apply_image_decorations = 0
+ var/apply_material_decorations = TRUE
+ var/apply_image_decorations = FALSE
var/material_descriptor = ""
- var/apply_prefix = 1
+ var/apply_prefix = TRUE
+
+ var/become_anomalous = FALSE
if(prob(40))
material_descriptor = pick("rusted ","dusty ","archaic ","fragile ", "damaged", "pristine")
source_material = pick("cordite","quadrinium","steel","titanium","aluminium","ferritic-alloy","plasteel","duranium")
- var/talkative = 0
+ var/talkative = FALSE
if(prob(5))
- talkative = 1
+ talkative = TRUE
//for all items here:
//icon_state
@@ -41,7 +43,7 @@
new_item = new /obj/item/weapon/reagent_containers/glass/beaker(src.loc)
new_item.icon = 'icons/obj/xenoarchaeology.dmi'
new_item.icon_state = "bowl"
- apply_image_decorations = 1
+ apply_image_decorations = TRUE
if(prob(40))
new_item.color = rgb(rand(0,255),rand(0,255),rand(0,255))
if(prob(20))
@@ -55,7 +57,7 @@
new_item = new /obj/item/weapon/reagent_containers/glass/beaker(src.loc)
new_item.icon = 'icons/obj/xenoarchaeology.dmi'
new_item.icon_state = "urn[rand(1,2)]"
- apply_image_decorations = 1
+ apply_image_decorations = TRUE
if(prob(20))
additional_desc = "It [pick("whispers faintly","makes a quiet roaring sound","whistles softly","thrums quietly","throbs")] if you put it to your ear."
if(ARCHAEO_CUTLERY)
@@ -88,7 +90,9 @@
item_type = "instrument"
icon_state = "instrument"
if(prob(30))
- apply_image_decorations = 1
+ become_anomalous = TRUE
+ if(prob(30))
+ apply_image_decorations = TRUE
additional_desc = "[pick("You're not sure how anyone could have played this",\
"You wonder how many mouths the creator had",\
"You wonder what it sounds like",\
@@ -109,16 +113,16 @@
chance += 10
item_type = new_item.name
- apply_prefix = 0
- apply_material_decorations = 0
- apply_image_decorations = 1
+ apply_prefix = FALSE
+ apply_material_decorations = FALSE
+ apply_image_decorations = TRUE
if(ARCHAEO_HANDCUFFS)
item_type = "handcuffs"
new_item = new /obj/item/weapon/handcuffs(src.loc)
additional_desc = "[pick("They appear to be for securing two things together","Looks kinky","Doesn't seem like a children's toy")]."
if(ARCHAEO_BEARTRAP)
item_type = "[pick("wicked","evil","byzantine","dangerous")] looking [pick("device","contraption","thing","trap")]"
- apply_prefix = 0
+ apply_prefix = FALSE
new_item = new /obj/item/weapon/beartrap(src.loc)
if(prob(40))
new_item.color = rgb(rand(0,255),rand(0,255),rand(0,255))
@@ -130,7 +134,7 @@
new_item = new /obj/item/weapon/flame/lighter(src.loc)
additional_desc = "There is a tiny device attached."
if(prob(30))
- apply_image_decorations = 1
+ apply_image_decorations = TRUE
if(ARCHAEO_BOX)
item_type = "box"
new_item = new /obj/item/weapon/storage/box(src.loc)
@@ -142,7 +146,7 @@
new_box.max_storage_space = rand(storage_amount, storage_amount * 10)
if(prob(30))
LAZYSET(new_item.origin_tech, TECH_ARCANE, 1)
- apply_image_decorations = 1
+ apply_image_decorations = TRUE
if(ARCHAEO_GASTANK)
item_type = "[pick("cylinder","tank","chamber")]"
if(prob(25))
@@ -163,12 +167,12 @@
new_item = new /obj/item/weapon/tool/screwdriver(src.loc)
if(prob(40))
new_item.color = rgb(rand(0,255),rand(0,255),rand(0,255))
- apply_image_decorations = 1
+ apply_image_decorations = TRUE
additional_desc = "[pick("It doesn't look safe.",\
"You wonder what it was used for",\
"There appear to be [pick("dark red","dark purple","dark green","dark blue")] stains on it")]."
if(ARCHAEO_METAL)
- apply_material_decorations = 0
+ apply_material_decorations = FALSE
var/list/possible_spawns = list()
possible_spawns += /obj/item/stack/material/steel
possible_spawns += /obj/item/stack/material/plasteel
@@ -193,9 +197,11 @@
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "pen1"
LAZYSET(new_item.origin_tech, TECH_ARCANE, 1)
- apply_image_decorations = 1
+ apply_image_decorations = TRUE
if(ARCHAEO_CRYSTAL)
- apply_prefix = 0
+ if(prob(40))
+ become_anomalous = TRUE
+ apply_prefix = FALSE
if(prob(25))
icon = 'icons/obj/xenoarchaeology.dmi'
item_type = "smooth green crystal"
@@ -210,9 +216,9 @@
icon_state = "changerock"
additional_desc = pick("It shines faintly as it catches the light.","It appears to have a faint inner glow.","It seems to draw you inward as you look it at.","Something twinkles faintly as you look at it.","It's mesmerizing to behold.")
- apply_material_decorations = 0
+ apply_material_decorations = FALSE
if(prob(10))
- apply_image_decorations = 1
+ apply_image_decorations = TRUE
if(prob(25))
new_item = new /obj/item/device/soulstone(src.loc)
new_item.icon = 'icons/obj/xenoarchaeology.dmi'
@@ -220,18 +226,18 @@
LAZYSET(new_item.origin_tech, TECH_ARCANE, 2)
if(ARCHAEO_CULTBLADE)
//cultblade
- apply_prefix = 0
+ apply_prefix = FALSE
new_item = new /obj/item/weapon/melee/cultblade(src.loc)
- apply_material_decorations = 0
- apply_image_decorations = 0
+ apply_material_decorations = FALSE
+ apply_image_decorations = FALSE
if(ARCHAEO_TELEBEACON)
new_item = new /obj/item/device/radio/beacon(src.loc)
- talkative = 0
+ talkative = FALSE
new_item.icon = 'icons/obj/xenoarchaeology.dmi'
new_item.icon_state = "unknown[rand(1,4)]"
new_item.desc = ""
if(ARCHAEO_CLAYMORE)
- apply_prefix = 0
+ apply_prefix = FALSE
new_item = new /obj/item/weapon/material/sword(src.loc)
new_item.force = 10
new_item.name = pick("great-sword","claymore","longsword","broadsword","shortsword","gladius")
@@ -241,7 +247,7 @@
new_item.icon_state = "blade1"
if(ARCHAEO_CULTROBES)
//arcane clothing
- apply_prefix = 0
+ apply_prefix = FALSE
var/list/possible_spawns = list(/obj/item/clothing/head/culthood,
/obj/item/clothing/head/culthood/magus,
/obj/item/clothing/head/culthood/alt,
@@ -252,25 +258,28 @@
LAZYSET(new_item.origin_tech, TECH_ARCANE, 1)
if(ARCHAEO_SOULSTONE)
//soulstone
- apply_prefix = 0
+ become_anomalous = TRUE
+ apply_prefix = FALSE
new_item = new /obj/item/device/soulstone(src.loc)
item_type = new_item.name
- apply_material_decorations = 0
+ apply_material_decorations = FALSE
LAZYSET(new_item.origin_tech, TECH_ARCANE, 2)
if(ARCHAEO_SHARD)
if(prob(50))
new_item = new /obj/item/weapon/material/shard(src.loc)
else
new_item = new /obj/item/weapon/material/shard/phoron(src.loc)
- apply_prefix = 0
- apply_image_decorations = 0
- apply_material_decorations = 0
+ apply_prefix = FALSE
+ apply_image_decorations = FALSE
+ apply_material_decorations = FALSE
if(ARCHAEO_RODS)
- apply_prefix = 0
+ apply_prefix = FALSE
new_item = new /obj/item/stack/rods(src.loc)
- apply_image_decorations = 0
- apply_material_decorations = 0
+ apply_image_decorations = FALSE
+ apply_material_decorations = FALSE
if(ARCHAEO_STOCKPARTS)
+ if(prob(30))
+ become_anomalous = TRUE
var/list/possible_spawns = typesof(/obj/item/weapon/stock_parts)
possible_spawns -= /obj/item/weapon/stock_parts
possible_spawns -= /obj/item/weapon/stock_parts/subspace
@@ -278,9 +287,9 @@
var/new_type = pick(possible_spawns)
new_item = new new_type(src.loc)
item_type = new_item.name
- apply_material_decorations = 0
+ apply_material_decorations = FALSE
if(ARCHAEO_KATANA)
- apply_prefix = 0
+ apply_prefix = FALSE
new_item = new /obj/item/weapon/material/sword/katana(src.loc)
new_item.force = 10
new_item.name = "katana"
@@ -349,9 +358,11 @@
item_type = "gun"
if(ARCHAEO_UNKNOWN)
+ if(prob(20))
+ become_anomalous = TRUE
//completely unknown alien device
if(prob(50))
- apply_image_decorations = 0
+ apply_image_decorations = FALSE
if(ARCHAEO_FOSSIL)
//fossil bone/skull
//new_item = new /obj/item/weapon/fossil/base(src.loc)
@@ -362,30 +373,30 @@
var/spawn_type = pickweight(candidates)
new_item = new spawn_type(src.loc)
- apply_prefix = 0
+ apply_prefix = FALSE
additional_desc = "A fossilised part of an alien, long dead."
- apply_image_decorations = 0
- apply_material_decorations = 0
+ apply_image_decorations = FALSE
+ apply_material_decorations = FALSE
if(ARCHAEO_SHELL)
//fossil shell
new_item = new /obj/item/weapon/fossil/shell(src.loc)
- apply_prefix = 0
+ apply_prefix = FALSE
additional_desc = "A fossilised, pre-Stygian alien crustacean."
- apply_image_decorations = 0
- apply_material_decorations = 0
+ apply_image_decorations = FALSE
+ apply_material_decorations = FALSE
if(prob(10))
- apply_image_decorations = 1
+ apply_image_decorations = TRUE
if(ARCHAEO_PLANT)
//fossil plant
new_item = new /obj/item/weapon/fossil/plant(src.loc)
item_type = new_item.name
additional_desc = "A fossilised shred of alien plant matter."
- apply_image_decorations = 0
- apply_material_decorations = 0
- apply_prefix = 0
+ apply_image_decorations = FALSE
+ apply_material_decorations = FALSE
+ apply_prefix = FALSE
if(ARCHAEO_REMAINS_HUMANOID)
//humanoid remains
- apply_prefix = 0
+ apply_prefix = FALSE
item_type = "humanoid [pick("remains","skeleton")]"
icon = 'icons/effects/blood.dmi'
icon_state = "remains"
@@ -396,11 +407,11 @@
"The bones are scored by numerous burns and partially melted.",\
"The are battered and broken, in some cases less than splinters are left.",\
"The mouth is wide open in a death rictus, the victim would appear to have died screaming.")
- apply_image_decorations = 0
- apply_material_decorations = 0
+ apply_image_decorations = FALSE
+ apply_material_decorations = FALSE
if(ARCHAEO_REMAINS_ROBOT)
//robot remains
- apply_prefix = 0
+ apply_prefix = FALSE
item_type = "[pick("mechanical","robotic","cyborg")] [pick("remains","chassis","debris")]"
icon = 'icons/mob/robots.dmi'
icon_state = "remainsrobot"
@@ -411,11 +422,11 @@
"The chassis is scored by numerous burns and partially melted.",\
"The chassis is battered and broken, in some cases only chunks of metal are left.",\
"A pile of wires and crap metal that looks vaguely robotic.")
- apply_image_decorations = 0
- apply_material_decorations = 0
+ apply_image_decorations = FALSE
+ apply_material_decorations = FALSE
if(ARCHAEO_REMAINS_XENO)
//xenos remains
- apply_prefix = 0
+ apply_prefix = FALSE
item_type = "alien [pick("remains","skeleton")]"
icon = 'icons/effects/blood.dmi'
icon_state = "remainsxeno"
@@ -427,8 +438,8 @@
"The are battered and broken, in some cases less than splinters are left.",\
"This creature would have been twisted and monstrous when it was alive.",\
"It doesn't look human.")
- apply_image_decorations = 0
- apply_material_decorations = 0
+ apply_image_decorations = FALSE
+ apply_material_decorations = FALSE
if(ARCHAEO_GASMASK)
//gas mask
if(prob(25))
@@ -551,7 +562,7 @@
var/obj/item/weapon/reagent_containers/syringe/S = new_item
S.volume = 30
- //If S hasn't initialized yet, S.reagents will be null.
+ //If S hasn't initialized yet, S.reagents will be null.
//However, in that case Initialize will set the maximum volume to the volume for us, so we don't need to do anything.
S.reagents?.maximum_volume = 30
@@ -680,6 +691,9 @@
new_item.origin_tech[TECH_ARCANE] += 1
new_item.origin_tech[TECH_PRECURSOR] += 1
+ if(become_anomalous)
+ new_item.become_anomalous()
+
var/turf/simulated/mineral/T = get_turf(new_item)
if(istype(T))
T.last_find = new_item
@@ -691,3 +705,6 @@
LAZYINITLIST(origin_tech)
origin_tech[TECH_ARCANE] += 1
origin_tech[TECH_PRECURSOR] += 1
+
+ if(become_anomalous)
+ become_anomalous()
diff --git a/code/modules/xenoarcheaology/tools/artifact_analyser.dm b/code/modules/xenoarcheaology/tools/artifact_analyser.dm
index 44afa6ea2c7..32259e774a5 100644
--- a/code/modules/xenoarcheaology/tools/artifact_analyser.dm
+++ b/code/modules/xenoarcheaology/tools/artifact_analyser.dm
@@ -138,13 +138,37 @@
var/obj/machinery/artifact/A = scanned_obj
var/out = "Anomalous alien device - composed of an unknown alloy.
"
- if(A.my_effect)
- out += A.my_effect.getDescription()
+ var/datum/component/artifact_master/AMast = A.artifact_master
+ var/datum/artifact_effect/AEff = AMast.get_primary()
- if(A.secondary_effect && A.secondary_effect.activated)
+ out += AEff.getDescription()
+
+ if(AMast.my_effects.len > 1)
out += "
Internal scans indicate ongoing secondary activity operating independently from primary systems.
"
- out += A.secondary_effect.getDescription()
+ for(var/datum/artifact_effect/my_effect in A.artifact_master.my_effects - AEff)
+
+ if(my_effect)
+ out += my_effect.getDescription()
return out
else
+
+ var/datum/component/artifact_master/ScannedMaster = scanned_obj.GetComponent(/datum/component/artifact_master)
+
+ if(istype(ScannedMaster))
+ var/out = "Anomalous reality warp - Object has been altered to disobey known laws of physics.
"
+
+ var/datum/artifact_effect/AEff = ScannedMaster.get_primary()
+
+ out += AEff.getDescription()
+
+ if(ScannedMaster.my_effects.len > 1)
+ out += "
Resonant scans indicate asynchronous reality modulation:
"
+ for(var/datum/artifact_effect/my_effect in ScannedMaster.my_effects - AEff)
+
+ if(my_effect)
+ out += my_effect.getDescription()
+
+ return out
+
return "[scanned_obj.name] - mundane application."
diff --git a/code/modules/xenoarcheaology/tools/artifact_harvester.dm b/code/modules/xenoarcheaology/tools/artifact_harvester.dm
index 05aa87442d0..03f0fdb4843 100644
--- a/code/modules/xenoarcheaology/tools/artifact_harvester.dm
+++ b/code/modules/xenoarcheaology/tools/artifact_harvester.dm
@@ -148,10 +148,12 @@
cur_artifact = analysed
//if both effects are active, we can't harvest either
- if(cur_artifact.my_effect && cur_artifact.my_effect.activated && cur_artifact.secondary_effect && cur_artifact.secondary_effect.activated)
+ var/list/active_effects = cur_artifact.artifact_master.get_active_effects()
+
+ if(active_effects.len > 1)
atom_say("Cannot harvest. Source is emitting conflicting energy signatures.")
return
- if(!cur_artifact.my_effect.activated && !(cur_artifact.secondary_effect && cur_artifact.secondary_effect.activated))
+ else if(!active_effects.len)
atom_say("Cannot harvest. No energy emitting from source.")
return
@@ -163,34 +165,24 @@
//
var/datum/artifact_effect/source_effect
+ var/datum/artifact_effect/active_effect = active_effects[1]
//if we already have charge in the battery, we can only recharge it from the source artifact
if(inserted_battery.stored_charge > 0)
var/battery_matches_primary_id = 0
- if(inserted_battery.battery_effect && inserted_battery.battery_effect.artifact_id == cur_artifact.my_effect.artifact_id)
+ if(inserted_battery.battery_effect && inserted_battery.battery_effect.artifact_id == cur_artifact.artifact_master.artifact_id)
battery_matches_primary_id = 1
- if(battery_matches_primary_id && cur_artifact.my_effect.activated)
+ if(battery_matches_primary_id && active_effect.activated)
//we're good to recharge the primary effect!
- source_effect = cur_artifact.my_effect
-
- var/battery_matches_secondary_id = 0
- if(inserted_battery.battery_effect && inserted_battery.battery_effect.artifact_id == cur_artifact.secondary_effect.artifact_id)
- battery_matches_secondary_id = 1
- if(battery_matches_secondary_id && cur_artifact.secondary_effect.activated)
- //we're good to recharge the secondary effect!
- source_effect = cur_artifact.secondary_effect
+ source_effect = active_effect
if(!source_effect)
atom_say("Cannot harvest. Battery is charged with a different energy signature.")
else
//we're good to charge either
- if(cur_artifact.my_effect.activated)
+ if(active_effect.activated)
//charge the primary effect
- source_effect = cur_artifact.my_effect
-
- else if(cur_artifact.secondary_effect.activated)
- //charge the secondary effect
- source_effect = cur_artifact.secondary_effect
+ source_effect = active_effect
if(source_effect)
@@ -258,3 +250,134 @@
inserted_battery.battery_effect.ToggleActivate()
src.visible_message("[name] states, \"Battery dump completed.\"")
icon_state = "incubator"
+
+/obj/machinery/artifact_harvester/Topic(href, href_list)
+
+ if (href_list["harvest"])
+ if(!inserted_battery)
+ src.visible_message("[src] states, \"Cannot harvest. No battery inserted.\"")
+
+ else if(inserted_battery.stored_charge >= inserted_battery.capacity)
+ src.visible_message("[src] states, \"Cannot harvest. battery is full.\"")
+
+ else
+
+ //locate artifact on analysis pad
+ cur_artifact = null
+ var/articount = 0
+ var/obj/machinery/artifact/analysed
+ for(var/obj/machinery/artifact/A in get_turf(owned_scanner))
+ analysed = A
+ articount++
+
+ if(articount <= 0)
+ var/message = "[src] states, \"Cannot harvest. No noteworthy energy signature isolated.\""
+ src.visible_message(message)
+
+ else if(analysed && analysed.being_used)
+ src.visible_message("[src] states, \"Cannot harvest. Source already being harvested.\"")
+
+ else
+ if(articount > 1)
+ state("Cannot harvest. Too many artifacts on the pad.")
+ else if(analysed)
+ cur_artifact = analysed
+
+ //if both effects are active, we can't harvest either
+ var/list/active_effects = cur_artifact.artifact_master.get_active_effects()
+
+ if(active_effects.len > 1)
+ src.visible_message("[src] states, \"Cannot harvest. Source is emitting conflicting energy signatures.\"")
+ else if(!active_effects.len)
+ src.visible_message("[src] states, \"Cannot harvest. No energy emitting from source.\"")
+
+ else
+ //see if we can clear out an old effect
+ //delete it when the ids match to account for duplicate ids having different effects
+ if(inserted_battery.battery_effect && inserted_battery.stored_charge <= 0)
+ qdel(inserted_battery.battery_effect)
+ inserted_battery.battery_effect = null
+
+ //
+ var/datum/artifact_effect/source_effect
+ var/datum/artifact_effect/active_effect = active_effects[1]
+
+ //if we already have charge in the battery, we can only recharge it from the source artifact
+ if(inserted_battery.stored_charge > 0)
+ var/battery_matches_primary_id = 0
+ if(inserted_battery.battery_effect && inserted_battery.battery_effect.artifact_id == cur_artifact.artifact_master.artifact_id)
+ battery_matches_primary_id = 1
+ if(battery_matches_primary_id && active_effect.activated)
+ //we're good to recharge the primary effect!
+ source_effect = active_effect
+
+ if(!source_effect)
+ src.visible_message("[src] states, \"Cannot harvest. Battery is charged with a different energy signature.\"")
+ else
+ //we're good to charge either
+ if(active_effect.activated)
+ //charge the primary effect
+ source_effect = active_effect
+
+ if(source_effect)
+ harvesting = 1
+ update_use_power(USE_POWER_ACTIVE)
+ cur_artifact.anchored = 1
+ cur_artifact.being_used = 1
+ icon_state = "incubator_on"
+ var/message = "[src] states, \"Beginning energy harvesting.\""
+ src.visible_message(message)
+ last_process = world.time
+
+ //duplicate the artifact's effect datum
+ if(!inserted_battery.battery_effect)
+ var/effecttype = source_effect.type
+ var/datum/artifact_effect/E = new effecttype(inserted_battery)
+
+ //duplicate it's unique settings
+ for(var/varname in list("chargelevelmax","artifact_id","effect","effectrange","trigger"))
+ E.vars[varname] = source_effect.vars[varname]
+
+ //copy the new datum into the battery
+ inserted_battery.battery_effect = E
+ inserted_battery.stored_charge = 0
+
+ if (href_list["stopharvest"])
+ if(harvesting)
+ if(harvesting < 0 && inserted_battery.battery_effect && inserted_battery.battery_effect.activated)
+ inserted_battery.battery_effect.ToggleActivate()
+ harvesting = 0
+ cur_artifact.anchored = 0
+ cur_artifact.being_used = 0
+ cur_artifact = null
+ src.visible_message("[name] states, \"Energy harvesting interrupted.\"")
+ icon_state = "incubator"
+
+ if (href_list["ejectbattery"])
+ src.inserted_battery.loc = src.loc
+ src.inserted_battery = null
+
+ if (href_list["drainbattery"])
+ if(inserted_battery)
+ if(inserted_battery.battery_effect && inserted_battery.stored_charge > 0)
+ if(alert("This action will dump all charge, safety gear is recommended before proceeding","Warning","Continue","Cancel"))
+ if(!inserted_battery.battery_effect.activated)
+ inserted_battery.battery_effect.ToggleActivate(1)
+ last_process = world.time
+ harvesting = -1
+ update_use_power(USE_POWER_ACTIVE)
+ icon_state = "incubator_on"
+ var/message = "[src] states, \"Warning, battery charge dump commencing.\""
+ src.visible_message(message)
+ else
+ var/message = "[src] states, \"Cannot dump energy. Battery is drained of charge already.\""
+ src.visible_message(message)
+ else
+ var/message = "[src] states, \"Cannot dump energy. No battery inserted.\""
+ src.visible_message(message)
+
+ if(href_list["close"])
+ usr << browse(null, "window=artharvester")
+ usr.unset_machine(src)
+
+ updateDialog()
diff --git a/vorestation.dme b/vorestation.dme
index c03aab5deb8..fb41ed7c48e 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -3981,6 +3981,7 @@
#include "code\modules\xenoarcheaology\anomaly_container.dm"
#include "code\modules\xenoarcheaology\boulder.dm"
#include "code\modules\xenoarcheaology\effect.dm"
+#include "code\modules\xenoarcheaology\effect_master.dm"
#include "code\modules\xenoarcheaology\manuals.dm"
#include "code\modules\xenoarcheaology\misc.dm"
#include "code\modules\xenoarcheaology\sampling.dm"