mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2025-12-17 05:31:53 +00:00
Blob Chunks 2 (#9143)
* Restore blob chunks to the world. Blobs have chunks they spawn on death, carrying an artifact effect related to the blob type. The chunk carries a copy of the parent blob's type datum, to prevent modification of a blob causing issues with the chunk, and vice versa, if both somehow exist at the same time. * Organization, origin tech. * Convert to List Based system, drop transferring type datums directly as discussed in DMs * Added Volatile Alluvium chunk effect. Nanite swarm chunks exist, but don't do anything special for now. Blob Chunks can sniff a mob to take their faction. * Copy requires static * Chunk and effect code cleanliness lifemerger now utilizes a timer&callback instead of spawn()
This commit is contained in:
@@ -8,6 +8,3 @@
|
||||
#define BLOB_DIFFICULTY_MEDIUM 1
|
||||
#define BLOB_DIFFICULTY_HARD 2
|
||||
#define BLOB_DIFFICULTY_SUPERHARD 3
|
||||
|
||||
#define BLOB_CHUNK_CONSTANT 0
|
||||
#define BLOB_CHUNK_TOGGLE 1
|
||||
|
||||
@@ -113,6 +113,7 @@ var/global/list/blob_cores = list()
|
||||
blob_cores -= src
|
||||
if(overmind)
|
||||
overmind.blob_core = null
|
||||
overmind.blob_type.make_chunk(get_turf(src))
|
||||
qdel(overmind)
|
||||
overmind = null
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
117
code/modules/blob2/overmind/chunks.dm
Normal file
117
code/modules/blob2/overmind/chunks.dm
Normal file
@@ -0,0 +1,117 @@
|
||||
|
||||
// Blob Type Modification to allow for chunks. //
|
||||
|
||||
/datum/blob_type
|
||||
var/list/core_tech = list(TECH_BIO = 4, TECH_MATERIAL = 3) // Tech for the item created when a core is destroyed.
|
||||
|
||||
var/chunk_type = /obj/item/blob_chunk
|
||||
var/chunk_effect_cooldown = 10
|
||||
var/chunk_effect_range = 1 // Tile range of the effect.
|
||||
|
||||
var/generation = 0 // How many times has this blob been chunked
|
||||
|
||||
/datum/blob_type/proc/make_chunk(var/turf/T)
|
||||
if(!T)
|
||||
return
|
||||
|
||||
if(ispath(chunk_type, /obj/item/blob_chunk))
|
||||
return new chunk_type(T, listify_vars())
|
||||
|
||||
return new chunk_type(T)
|
||||
|
||||
// Base chunk. //
|
||||
|
||||
/obj/item/blob_chunk
|
||||
name = "chunk"
|
||||
desc = "A piece of a blob's core."
|
||||
|
||||
description_info = "Blob core chunks can be 'revived' with the help of Xenobio. \
|
||||
40 units of Blood, 40 units of Phoron, and 10 units of Slime Jelly will cause the chunk \
|
||||
to produce a new core on the turf it is on. The chunk remains, but unable to produce another. \
|
||||
You can change the faction of the blob created pre-emptively by using the chunk on a mob, imprinting \
|
||||
its faction upon the chunk."
|
||||
|
||||
icon = 'icons/mob/blob.dmi'
|
||||
icon_state = "blobcore"
|
||||
|
||||
unacidable = TRUE
|
||||
|
||||
var/can_revive = TRUE
|
||||
|
||||
var/list/blob_type_vars
|
||||
|
||||
var/datum/blob_type/default_blob = /datum/blob_type/classic
|
||||
|
||||
var/blob_effect_master_type = /datum/component/artifact_master/blob
|
||||
|
||||
/obj/item/blob_chunk/Initialize(var/newloc, var/list/transfer_vars)
|
||||
. = ..()
|
||||
|
||||
create_reagents(120)
|
||||
|
||||
if(!transfer_vars)
|
||||
default_blob = new default_blob()
|
||||
transfer_vars = default_blob.listify_vars()
|
||||
|
||||
blob_type_vars = transfer_vars
|
||||
color = transfer_vars["color"]
|
||||
|
||||
name = "[blob_type_vars["name"]] [initial(name)]"
|
||||
|
||||
AddComponent(blob_effect_master_type)
|
||||
|
||||
/obj/item/blob_chunk/is_open_container()
|
||||
return TRUE
|
||||
|
||||
/obj/item/blob_chunk/afterattack(var/atom/target, var/mob/user, var/proximity)
|
||||
if(proximity && Adjacent(target))
|
||||
user.visible_message(SPAN_WARNING("[user] holds \the [src] toward [target]."))
|
||||
if(isliving(target) && do_after(user, 3 SECONDS, target))
|
||||
var/mob/living/L = target
|
||||
|
||||
user.visible_message(SPAN_WARNING("[bicon(src)] \the [src] inflates slighty, before it releases a puff of gas toward [L]."))
|
||||
to_chat(user, SPAN_NOTICE("[bicon(src)] [src] has registered \the [L.faction] pheromone as its own, forgetting \the [blob_type_vars["faction"]] pheromone."))
|
||||
|
||||
blob_type_vars["faction"] = L.faction
|
||||
|
||||
return
|
||||
|
||||
/obj/item/blob_chunk/proc/reviveBlob(var/ask_player = FALSE)
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
var/obj/structure/blob/core/C = new(T, null, 2, 0)
|
||||
|
||||
C.desired_blob_type = blob_type_vars["blob_type"]
|
||||
C.create_overmind()
|
||||
|
||||
var/datum/blob_type/to_modify = C.overmind.blob_type
|
||||
to_modify.apply_vars(blob_type_vars)
|
||||
|
||||
C.update_icon()
|
||||
|
||||
if(!can_revive)
|
||||
name = "weakened [name]"
|
||||
desc += " It can no longer reproduce."
|
||||
|
||||
if(C?.overmind)
|
||||
return TRUE
|
||||
|
||||
return
|
||||
|
||||
// Artifact master solely for blobs. //
|
||||
|
||||
/datum/component/artifact_master/blob
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/uncommon/fortify
|
||||
)
|
||||
|
||||
/datum/component/artifact_master/blob/do_setup()
|
||||
..()
|
||||
if(istype(holder, /obj/item/blob_chunk))
|
||||
var/obj/item/blob_chunk/type_source = holder
|
||||
|
||||
for(var/datum/artifact_effect/AE in my_effects)
|
||||
AE.trigger = TRIGGER_TOUCH
|
||||
AE.effect = EFFECT_PULSE
|
||||
AE.effectrange = type_source.blob_type_vars["chunk_effect_range"]
|
||||
AE.chargelevelmax = type_source.blob_type_vars["chunk_effect_cooldown"]
|
||||
@@ -47,10 +47,6 @@
|
||||
var/node_type = /obj/structure/blob/node
|
||||
var/shield_type = /obj/structure/blob/shield
|
||||
|
||||
var/list/core_tech = list(TECH_BIO = 4, TECH_MATERIAL = 3) // Tech for the item created when a core is destroyed.
|
||||
var/chunk_active_type = BLOB_CHUNK_TOGGLE
|
||||
var/chunk_active_ability_cooldown = 20 SECONDS
|
||||
var/chunk_passive_ability_cooldown = 5 SECONDS
|
||||
|
||||
// Called when a blob receives damage. This needs to return the final damage or blobs will be immortal.
|
||||
/datum/blob_type/proc/on_received_damage(var/obj/structure/blob/B, damage, damage_type)
|
||||
@@ -95,3 +91,112 @@
|
||||
// Spore handle_special call.
|
||||
/datum/blob_type/proc/on_spore_lifetick(mob/living/simple_mob/blob/spore/S)
|
||||
return
|
||||
|
||||
/datum/blob_type/proc/listify_vars()
|
||||
var/list/transfer_vars = list()
|
||||
|
||||
transfer_vars["blob_type"] = type
|
||||
transfer_vars["name"] = name
|
||||
transfer_vars["desc"] = desc
|
||||
transfer_vars["effect_desc"] = effect_desc
|
||||
transfer_vars["ai_desc"] = ai_desc
|
||||
transfer_vars["color"] = color
|
||||
transfer_vars["complementary_color"] = complementary_color
|
||||
|
||||
transfer_vars["faction"] = faction
|
||||
|
||||
transfer_vars["attack_message"] = attack_message
|
||||
transfer_vars["attack_message_living"] = attack_message_living
|
||||
transfer_vars["attack_message_synth"] = attack_message_synth
|
||||
transfer_vars["attack_verb"] = attack_verb
|
||||
transfer_vars["damage_type"] = damage_type
|
||||
transfer_vars["armor_check"] = armor_check
|
||||
transfer_vars["armor_pen"] = armor_pen
|
||||
transfer_vars["damage_lower"] = damage_lower
|
||||
transfer_vars["damage_upper"] = damage_upper
|
||||
|
||||
transfer_vars["brute_multiplier"] = brute_multiplier
|
||||
transfer_vars["burn_multiplier"] = burn_multiplier
|
||||
transfer_vars["spread_modifier"] = spread_modifier
|
||||
transfer_vars["slow_spread_with_size"] = slow_spread_with_size
|
||||
transfer_vars["ai_aggressiveness"] = ai_aggressiveness
|
||||
|
||||
transfer_vars["can_build_factories"] = can_build_factories
|
||||
transfer_vars["can_build_resources"] = can_build_resources
|
||||
transfer_vars["can_build_nodes"] = can_build_nodes
|
||||
|
||||
transfer_vars["spore_type"] = spore_type
|
||||
transfer_vars["ranged_spores"] = ranged_spores
|
||||
transfer_vars["spore_firesound"] = spore_firesound
|
||||
transfer_vars["spore_range"] = spore_range
|
||||
transfer_vars["spore_projectile"] = spore_projectile
|
||||
transfer_vars["spore_accuracy"] = spore_accuracy
|
||||
transfer_vars["spore_dispersion"] = spore_dispersion
|
||||
|
||||
transfer_vars["factory_type"] = factory_type
|
||||
transfer_vars["resource_type"] = resource_type
|
||||
transfer_vars["node_type"] = node_type
|
||||
transfer_vars["shield_type"] = shield_type
|
||||
|
||||
transfer_vars["core_tech"] = core_tech.Copy()
|
||||
|
||||
transfer_vars["chunk_type"] = chunk_type
|
||||
transfer_vars["chunk_effect_cooldown"] = chunk_effect_cooldown
|
||||
transfer_vars["chunk_effect_range"] = chunk_effect_range
|
||||
|
||||
transfer_vars["generation"] = generation
|
||||
|
||||
return transfer_vars
|
||||
|
||||
/datum/blob_type/proc/apply_vars(var/list/incoming_vars)
|
||||
if(LAZYLEN(incoming_vars))
|
||||
name = incoming_vars["name"]
|
||||
desc = incoming_vars["desc"]
|
||||
effect_desc = incoming_vars["effect_desc"]
|
||||
ai_desc = incoming_vars["ai_desc"]
|
||||
color = incoming_vars["color"]
|
||||
complementary_color = incoming_vars["complementary_color"]
|
||||
|
||||
faction = incoming_vars["faction"]
|
||||
|
||||
attack_message = incoming_vars["attack_message"]
|
||||
attack_message_living = incoming_vars["attack_message_living"]
|
||||
attack_message_synth = incoming_vars["attack_message_synth"]
|
||||
attack_verb = incoming_vars["attack_verb"]
|
||||
damage_type = incoming_vars["damage_type"]
|
||||
armor_check = incoming_vars["armor_check"]
|
||||
armor_pen = incoming_vars["armor_pen"]
|
||||
damage_lower = incoming_vars["damage_lower"]
|
||||
damage_upper = incoming_vars["damage_upper"]
|
||||
|
||||
brute_multiplier = incoming_vars["brute_multiplier"]
|
||||
burn_multiplier = incoming_vars["burn_multiplier"]
|
||||
spread_modifier = incoming_vars["spread_modifier"]
|
||||
slow_spread_with_size = incoming_vars["slow_spread_with_size"]
|
||||
ai_aggressiveness = incoming_vars["ai_aggressiveness"]
|
||||
|
||||
can_build_factories = incoming_vars["can_build_factories"]
|
||||
can_build_resources = incoming_vars["can_build_resources"]
|
||||
can_build_nodes = incoming_vars["can_build_nodes"]
|
||||
|
||||
spore_type = incoming_vars["spore_type"]
|
||||
ranged_spores = incoming_vars["ranged_spores"]
|
||||
spore_firesound = incoming_vars["spore_firesound"]
|
||||
spore_range = incoming_vars["spore_range"]
|
||||
spore_projectile = incoming_vars["spore_projectile"]
|
||||
spore_accuracy = incoming_vars["spore_accuracy"]
|
||||
spore_dispersion = incoming_vars["spore_dispersion"]
|
||||
|
||||
factory_type = incoming_vars["factory_type"]
|
||||
resource_type = incoming_vars["resource_type"]
|
||||
node_type = incoming_vars["node_type"]
|
||||
shield_type = incoming_vars["shield_type"]
|
||||
|
||||
var/list/new_core_tech = incoming_vars["core_tech"]
|
||||
core_tech = islist(new_core_tech) ? new_core_tech : list()
|
||||
|
||||
chunk_type = incoming_vars["chunk_type"]
|
||||
chunk_effect_cooldown = incoming_vars["chunk_effect_cooldown"]
|
||||
chunk_effect_range = incoming_vars["chunk_effect_range"]
|
||||
|
||||
generation = incoming_vars["generation"] + 1
|
||||
|
||||
@@ -13,3 +13,9 @@
|
||||
|
||||
brute_multiplier = 0.35
|
||||
burn_multiplier = 0.8
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/barnacle
|
||||
|
||||
/obj/item/blob_chunk/barnacle
|
||||
default_blob = /datum/blob_type/barnacle
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob
|
||||
|
||||
@@ -11,15 +11,26 @@
|
||||
ai_aggressiveness = 50
|
||||
damage_type = BURN
|
||||
burn_multiplier = 0 // Fire immunity
|
||||
chunk_active_ability_cooldown = 4 MINUTES
|
||||
chunk_effect_cooldown = 4 MINUTES
|
||||
attack_message = "The blazing oil splashes you with its burning oil"
|
||||
attack_message_living = ", and you feel your skin char and melt"
|
||||
attack_message_synth = ", and your external plating melts"
|
||||
attack_verb = "splashes"
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/blazing_oil
|
||||
|
||||
/obj/item/blob_chunk/blazing_oil
|
||||
default_blob = /datum/blob_type/blazing_oil
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/blazing_oil
|
||||
|
||||
/datum/blob_type/blazing_oil/on_attack(obj/structure/blob/B, mob/living/victim)
|
||||
victim.fire_act() // Burn them.
|
||||
|
||||
/datum/blob_type/blazing_oil/on_water(obj/structure/blob/B, amount)
|
||||
spawn(1)
|
||||
B.adjust_integrity(-(amount * 5))
|
||||
|
||||
/datum/component/artifact_master/blob/blazing_oil
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/common/heat
|
||||
)
|
||||
|
||||
@@ -10,3 +10,14 @@
|
||||
can_build_nodes = FALSE
|
||||
spread_modifier = 1.0
|
||||
ai_aggressiveness = 0
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/classic
|
||||
|
||||
/obj/item/blob_chunk/classic
|
||||
default_blob = /datum/blob_type/classic
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/classic
|
||||
|
||||
/datum/component/artifact_master/blob/classic
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/common/sweating
|
||||
)
|
||||
|
||||
@@ -14,12 +14,18 @@
|
||||
burn_multiplier = 1.2
|
||||
spread_modifier = 0.5
|
||||
ai_aggressiveness = 50
|
||||
chunk_active_ability_cooldown = 4 MINUTES
|
||||
chunk_effect_cooldown = 4 MINUTES
|
||||
attack_message = "The goo stabs you"
|
||||
attack_message_living = ", and you feel an intense chill from within"
|
||||
attack_message_synth = ", and your system reports lower internal temperatures"
|
||||
attack_verb = "stabs"
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/cryogenic_goo
|
||||
|
||||
/obj/item/blob_chunk/cryogenic_goo
|
||||
default_blob = /datum/blob_type/cryogenic_goo
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/cryogenic_goo
|
||||
|
||||
/datum/blob_type/cryogenic_goo/on_attack(obj/structure/blob/B, mob/living/victim)
|
||||
if(ishuman(victim))
|
||||
var/mob/living/carbon/human/H = victim
|
||||
@@ -35,3 +41,8 @@
|
||||
H.bodytemperature = max(H.bodytemperature - temp_change, temp_cap)
|
||||
else // Just do some extra burn for mobs who don't process bodytemp
|
||||
victim.adjustFireLoss(20)
|
||||
|
||||
/datum/component/artifact_master/blob/cryogenic_goo
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/common/cold
|
||||
)
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
|
||||
var/list/active_beams = list()
|
||||
|
||||
chunk_effect_range = 6
|
||||
chunk_type = /obj/item/blob_chunk/ectoplasmic_horror
|
||||
|
||||
/obj/item/blob_chunk/ectoplasmic_horror
|
||||
default_blob = /datum/blob_type/ectoplasmic_horror
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/ectoplasmic_horror
|
||||
|
||||
/datum/blob_type/ectoplasmic_horror/on_pulse(var/obj/structure/blob/B)
|
||||
if(B.type == /obj/structure/blob && (locate(/obj/structure/blob/node) in oview(2, get_turf(B))))
|
||||
B.visible_message("<span class='alien'>The [name] quakes, before hardening.</span>")
|
||||
@@ -67,3 +74,8 @@
|
||||
animate(B,alpha = 10, alpha = initial_alpha, time = 10)
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/datum/component/artifact_master/blob/ectoplasmic_horror
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/rare/lifedrain
|
||||
)
|
||||
|
||||
@@ -13,14 +13,25 @@
|
||||
brute_multiplier = 3
|
||||
burn_multiplier = 2
|
||||
ai_aggressiveness = 60
|
||||
chunk_active_type = BLOB_CHUNK_CONSTANT
|
||||
attack_message = "The web lashes you"
|
||||
attack_message_living = ", and you hear a faint buzzing"
|
||||
attack_message_synth = ", and your electronics get badly damaged"
|
||||
attack_verb = "lashes"
|
||||
|
||||
chunk_effect_range = 3
|
||||
chunk_type = /obj/item/blob_chunk/electromagnetic_web
|
||||
|
||||
/obj/item/blob_chunk/electromagnetic_web
|
||||
default_blob = /datum/blob_type/electromagnetic_web
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/electromagnetic_web
|
||||
|
||||
/datum/blob_type/electromagnetic_web/on_death(obj/structure/blob/B)
|
||||
empulse(B.loc, 0, 1, 2)
|
||||
|
||||
/datum/blob_type/electromagnetic_web/on_attack(obj/structure/blob/B, mob/living/victim)
|
||||
victim.emp_act(2)
|
||||
|
||||
/datum/component/artifact_master/blob/electromagnetic_web
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/rare/emp
|
||||
)
|
||||
|
||||
@@ -20,6 +20,17 @@
|
||||
attack_verb = "prods"
|
||||
spore_projectile = /obj/item/projectile/beam/shock
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/energized_jelly
|
||||
|
||||
/obj/item/blob_chunk/energized_jelly
|
||||
default_blob = /datum/blob_type/energized_jelly
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/energized_jelly
|
||||
|
||||
/datum/blob_type/energized_jelly/on_attack(obj/structure/blob/B, mob/living/victim, def_zone)
|
||||
victim.electrocute_act(10, src, 1, def_zone)
|
||||
victim.stun_effect_act(0, 40, BP_TORSO, src)
|
||||
|
||||
/datum/component/artifact_master/blob/energized_jelly
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/uncommon/faraday
|
||||
)
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
attack_verb = "blasts"
|
||||
var/exploding = FALSE
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/explosive_lattice
|
||||
|
||||
/obj/item/blob_chunk/explosive_lattice
|
||||
default_blob = /datum/blob_type/explosive_lattice
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/explosive_lattice
|
||||
|
||||
/datum/blob_type/explosive_lattice/on_attack(obj/structure/blob/B, mob/living/victim, def_zone) // This doesn't use actual bombs since they're too strong and it would hurt the blob.
|
||||
if(exploding) // We're busy, don't infinite loop us.
|
||||
return
|
||||
@@ -48,3 +54,8 @@
|
||||
M << 'sound/effects/explosionfar.ogg'
|
||||
|
||||
exploding = FALSE
|
||||
|
||||
/datum/component/artifact_master/blob/explosive_lattice
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/uncommon/blast_shielding
|
||||
)
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
ai_aggressiveness = 50 //Really doesn't like you near it.
|
||||
spore_type = /mob/living/simple_mob/mechanical/hivebot/swarm
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/fabrication_swarm
|
||||
|
||||
/obj/item/blob_chunk/fabrication_swarm
|
||||
default_blob = /datum/blob_type/fabrication_swarm
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob
|
||||
|
||||
/datum/blob_type/fabrication_swarm/on_received_damage(var/obj/structure/blob/B, damage, damage_type, mob/living/attacker)
|
||||
if(istype(B, /obj/structure/blob/normal))
|
||||
if(damage > 0)
|
||||
|
||||
@@ -17,7 +17,13 @@
|
||||
ai_aggressiveness = 30 // The spores do most of the fighting.
|
||||
can_build_factories = TRUE
|
||||
spore_type = /mob/living/simple_mob/blob/spore/weak
|
||||
chunk_active_ability_cooldown = 60 SECONDS
|
||||
chunk_effect_cooldown = 60
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/fulminant_organism
|
||||
|
||||
/obj/item/blob_chunk/fulminant_organism
|
||||
default_blob = /datum/blob_type/fulminant_organism
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/fulminant_organism
|
||||
|
||||
/datum/blob_type/fulminant_organism/on_expand(var/obj/structure/blob/B, var/obj/structure/blob/new_B, var/turf/T, var/mob/observer/blob/O)
|
||||
if(prob(10)) // 10% chance to make a weak spore when expanding.
|
||||
@@ -41,3 +47,8 @@
|
||||
else
|
||||
S.faction = faction
|
||||
S.update_icons()
|
||||
|
||||
/datum/component/artifact_master/blob/fulminant_organism
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/uncommon/berserk
|
||||
)
|
||||
|
||||
@@ -16,7 +16,12 @@
|
||||
ai_aggressiveness = 40
|
||||
can_build_factories = TRUE
|
||||
spore_type = /mob/living/simple_mob/blob/spore/infesting
|
||||
chunk_active_ability_cooldown = 2 MINUTES
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/fungal_bloom
|
||||
|
||||
/obj/item/blob_chunk/fungal_bloom
|
||||
default_blob = /datum/blob_type/fungal_bloom
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/fungal_bloom
|
||||
|
||||
/datum/blob_type/fungal_bloom/on_spore_death(mob/living/simple_mob/blob/spore/S)
|
||||
if(S.is_infesting)
|
||||
@@ -28,3 +33,8 @@
|
||||
else
|
||||
B = new /obj/structure/blob/normal(T, S.overmind) // Otherwise spread it.
|
||||
B.visible_message("<span class='danger'>\A [B] forms on \the [T] as \the [S] bursts!</span>")
|
||||
|
||||
/datum/component/artifact_master/blob/fungal_bloom
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/extreme/resurrect
|
||||
)
|
||||
|
||||
@@ -16,5 +16,13 @@
|
||||
attack_message_synth = ", and your external plating dissolves"
|
||||
faction = "nanomachines"
|
||||
|
||||
core_tech = list(TECH_ENGINEERING = 10, TECH_MATERIAL = 10, TECH_ILLEGAL = 10)
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/grey_goo
|
||||
|
||||
/obj/item/blob_chunk/grey_goo
|
||||
default_blob = /datum/blob_type/grey_goo
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob
|
||||
|
||||
/datum/blob_type/grey_goo/on_emp(obj/structure/blob/B, severity)
|
||||
B.adjust_integrity(-(20 / severity))
|
||||
|
||||
@@ -20,6 +20,12 @@
|
||||
attack_message_synth = ", and the fluid wears down on your components"
|
||||
attack_verb = "splashes"
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/pressurized_slime
|
||||
|
||||
/obj/item/blob_chunk/pressurized_slime
|
||||
default_blob = /datum/blob_type/pressurized_slime
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/pressurized_slime
|
||||
|
||||
/datum/blob_type/pressurized_slime/on_attack(obj/structure/blob/B, mob/living/victim, def_zone)
|
||||
victim.water_act(5)
|
||||
var/turf/simulated/T = get_turf(victim)
|
||||
@@ -46,3 +52,8 @@
|
||||
T.wet_floor()
|
||||
for(var/atom/movable/AM in T)
|
||||
AM.water_act(2)
|
||||
|
||||
/datum/component/artifact_master/blob/pressurized_slime
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/common/extinguisher
|
||||
)
|
||||
|
||||
@@ -20,5 +20,16 @@
|
||||
attack_message_synth = ", and your internal systems are bombarded by ionizing radiation"
|
||||
attack_verb = "splashes"
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/radioactive_ooze
|
||||
|
||||
/obj/item/blob_chunk/radioactive_ooze
|
||||
default_blob = /datum/blob_type/radioactive_ooze
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/radioactive_ooze
|
||||
|
||||
/datum/blob_type/radioactive_ooze/on_pulse(var/obj/structure/blob/B)
|
||||
SSradiation.radiate(B, 200)
|
||||
|
||||
/datum/component/artifact_master/blob/radioactive_ooze
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/rare/radiate
|
||||
)
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
attack_message_synth = ", and your body begins to corrode"
|
||||
attack_verb = "splashes"
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/ravenous_macrophage
|
||||
|
||||
/obj/item/blob_chunk/ravenous_macrophage
|
||||
default_blob = /datum/blob_type/ravenous_macrophage
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/ravenous_macrophage
|
||||
|
||||
/datum/blob_type/ravenous_macrophage/on_pulse(var/obj/structure/blob/B)
|
||||
var/mob/living/L = locate() in range(world.view, B)
|
||||
if(L && prob(1) && L.mind && !L.stat) // There's some active living thing nearby, produce offgas.
|
||||
@@ -37,3 +43,8 @@
|
||||
B.visible_message("<span class='danger'>The dying mass is rapidly consumed by the nearby [other]!</span>")
|
||||
if(other.overmind)
|
||||
other.overmind.add_points(rand(1,4))
|
||||
|
||||
/datum/component/artifact_master/blob/ravenous_macrophage
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/common/noxious
|
||||
)
|
||||
|
||||
@@ -16,13 +16,20 @@
|
||||
brute_multiplier = 2.0
|
||||
spread_modifier = 0.35 // Ranged projectiles tend to have a higher material cost, so ease up on the spreading.
|
||||
ai_aggressiveness = 40
|
||||
chunk_passive_ability_cooldown = 0.5 SECONDS
|
||||
chunk_effect_cooldown = 0.5 SECONDS
|
||||
attack_message = "The blob stabs you"
|
||||
attack_message_living = ", and you feel sharp spines pierce your flesh"
|
||||
attack_message_synth = ", and your external plating is pierced by sharp spines"
|
||||
attack_verb = "stabs"
|
||||
spore_projectile = /obj/item/projectile/bullet/thorn
|
||||
|
||||
chunk_effect_range = 3
|
||||
chunk_type = /obj/item/blob_chunk/reactive_spines
|
||||
|
||||
/obj/item/blob_chunk/reactive_spines
|
||||
default_blob = /datum/blob_type/reactive_spines
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/reactive_spines
|
||||
|
||||
// Even if the melee attack is enough to one-shot this blob, it gets to retaliate at least once.
|
||||
/datum/blob_type/reactive_spines/on_received_damage(var/obj/structure/blob/B, damage, damage_type, mob/living/attacker)
|
||||
if(damage > 0 && attacker && get_dist(B, attacker) <= 1)
|
||||
@@ -30,3 +37,8 @@
|
||||
B.blob_attack_animation(attacker, B.overmind)
|
||||
attacker.blob_act(B)
|
||||
return ..()
|
||||
|
||||
/datum/component/artifact_master/blob/reactive_spines
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/extreme/spines
|
||||
)
|
||||
|
||||
@@ -22,3 +22,15 @@
|
||||
attack_verb = "lashes"
|
||||
spore_projectile = /obj/item/projectile/arc/spore
|
||||
factory_type = /obj/structure/blob/factory/turret
|
||||
|
||||
chunk_effect_range = 2
|
||||
chunk_type = /obj/item/blob_chunk/roiling_mold
|
||||
|
||||
/obj/item/blob_chunk/roiling_mold
|
||||
default_blob = /datum/blob_type/roiling_mold
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/roiling_mold
|
||||
|
||||
/datum/component/artifact_master/blob/roiling_mold
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/extreme/spines/spore
|
||||
)
|
||||
|
||||
@@ -13,10 +13,16 @@
|
||||
burn_multiplier = 0.5
|
||||
spread_modifier = 0.5
|
||||
ai_aggressiveness = 30
|
||||
chunk_active_ability_cooldown = 3 MINUTES
|
||||
chunk_effect_cooldown = 3 MINUTES
|
||||
attack_message = "A fragment strikes you"
|
||||
attack_verb = "strikes"
|
||||
|
||||
chunk_type = /obj/item/blob_chunk/shifting_fragments
|
||||
|
||||
/obj/item/blob_chunk/shifting_fragments
|
||||
default_blob = /datum/blob_type/shifting_fragments
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/shifting_fragments
|
||||
|
||||
/datum/blob_type/shifting_fragments/on_received_damage(var/obj/structure/blob/B, damage, damage_type)
|
||||
if(damage > 0 && prob(60))
|
||||
var/list/available_blobs = list()
|
||||
@@ -34,3 +40,8 @@
|
||||
if(istype(B, /obj/structure/blob/normal) || (istype(B, /obj/structure/blob/shield) && prob(25)))
|
||||
new_B.forceMove(get_turf(B))
|
||||
B.forceMove(T)
|
||||
|
||||
/datum/component/artifact_master/blob/shifting_fragments
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/common/sprinting
|
||||
)
|
||||
|
||||
@@ -18,6 +18,13 @@
|
||||
attack_verb = "synchronously strikes"
|
||||
var/synchronously_attacking = FALSE
|
||||
|
||||
chunk_effect_range = 3
|
||||
chunk_type = /obj/item/blob_chunk/synchronous_mesh
|
||||
|
||||
/obj/item/blob_chunk/synchronous_mesh
|
||||
default_blob = /datum/blob_type/synchronous_mesh
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/synchronous_mesh
|
||||
|
||||
/datum/blob_type/synchronous_mesh/on_attack(obj/structure/blob/B, mob/living/victim)
|
||||
if(synchronously_attacking)
|
||||
return
|
||||
@@ -42,3 +49,8 @@
|
||||
C.adjust_integrity(-(damage / blobs_to_hurt.len))
|
||||
|
||||
return damage / max(blobs_to_hurt.len, 1) // To hurt the blob that got hit.
|
||||
|
||||
/datum/component/artifact_master/blob/synchronous_mesh
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/extreme/lifemerger
|
||||
)
|
||||
|
||||
@@ -26,7 +26,13 @@
|
||||
spore_dispersion = 45
|
||||
factory_type = /obj/structure/blob/factory/sluggish
|
||||
resource_type = /obj/structure/blob/resource/sluggish
|
||||
chunk_active_ability_cooldown = 2 MINUTES
|
||||
|
||||
chunk_effect_range = 3
|
||||
chunk_type = /obj/item/blob_chunk/volatile_alluvium
|
||||
|
||||
/obj/item/blob_chunk/volatile_alluvium
|
||||
default_blob = /datum/blob_type/volatile_alluvium
|
||||
blob_effect_master_type = /datum/component/artifact_master/blob/volatile_alluvium
|
||||
|
||||
/datum/blob_type/volatile_alluvium/on_received_damage(var/obj/structure/blob/B, damage, damage_type, mob/living/attacker)
|
||||
if(damage > 0 && attacker && get_dist(B, attacker) <= 2 && prob(min(damage, 70)) && istype(attacker, /mob/living/carbon/human)) // Melee weapons of any type carried by a human will have a high chance of being stolen.
|
||||
@@ -49,3 +55,8 @@
|
||||
B.adjust_integrity(-(damage))
|
||||
if(B && prob(damage))
|
||||
B.visible_message("<span class='danger'>The [name] begins to crumble!</span>")
|
||||
|
||||
/datum/component/artifact_master/blob/volatile_alluvium
|
||||
make_effects = list(
|
||||
/datum/artifact_effect/uncommon/disarmament
|
||||
)
|
||||
|
||||
20
code/modules/reagents/reactions/instant/blob.dm
Normal file
20
code/modules/reagents/reactions/instant/blob.dm
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
// Reactions for Blob Chunks. //
|
||||
|
||||
/decl/chemical_reaction/instant/blob_chunk_revival
|
||||
name = "Blob Chunk Revival"
|
||||
id = "blob_revival"
|
||||
result = null
|
||||
required_reagents = list("blood" = 40, "phoron" = 40, "slimejelly" = 10)
|
||||
result_amount = 1
|
||||
|
||||
/decl/chemical_reaction/instant/blob_chunk_revival/can_happen(var/datum/reagents/holder)
|
||||
if(holder.my_atom && istype(holder.my_atom, /obj/item/blob_chunk))
|
||||
return ..()
|
||||
return FALSE
|
||||
|
||||
/decl/chemical_reaction/instant/blob_chunk_revival/on_reaction(var/datum/reagents/holder)
|
||||
var/obj/item/blob_chunk/chunk = holder.my_atom
|
||||
if(chunk.can_revive)
|
||||
chunk.can_revive = FALSE
|
||||
chunk.reviveBlob()
|
||||
32
code/modules/xenoarcheaology/effects/disarm.dm
Normal file
32
code/modules/xenoarcheaology/effects/disarm.dm
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
/datum/artifact_effect/uncommon/disarmament
|
||||
name = "disarmament"
|
||||
effect_type = EFFECT_PSIONIC
|
||||
effect_state = "impact_laser_monochrome"
|
||||
effect_color = "#e17ceb"
|
||||
|
||||
/datum/artifact_effect/uncommon/disarmament/proc/disarm(var/mob/living/L)
|
||||
if(istype(L) && L.is_sentient())
|
||||
var/obj/item/Item = L.get_active_hand()
|
||||
if(istype(Item))
|
||||
to_chat(L, SPAN_WARNING("Something forces you to drop \the [Item]."))
|
||||
L.drop_item()
|
||||
|
||||
/datum/artifact_effect/uncommon/disarmament/DoEffectTouch(mob/living/user)
|
||||
var/weakness = GetAnomalySusceptibility(user)
|
||||
if(prob(weakness * 100))
|
||||
disarm(user)
|
||||
|
||||
/datum/artifact_effect/uncommon/disarmament/DoEffectPulse()
|
||||
var/turf/T = get_turf(get_master_holder())
|
||||
for(var/mob/living/L in oview(src.effectrange, T))
|
||||
var/weakness = GetAnomalySusceptibility(L)
|
||||
if(prob(weakness * 100))
|
||||
disarm(L)
|
||||
|
||||
/datum/artifact_effect/uncommon/disarmament/DoEffectAura()
|
||||
var/turf/T = get_turf(get_master_holder())
|
||||
for(var/mob/living/L in oview(src.effectrange, T))
|
||||
var/weakness = GetAnomalySusceptibility(L)
|
||||
if(prob(10) && prob(weakness * 100))
|
||||
disarm(L)
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "N2O creation"
|
||||
|
||||
|
||||
/datum/artifact_effect/gassleeping/New()
|
||||
/datum/artifact_effect/rare/gassleeping/New()
|
||||
..()
|
||||
effect = pick(EFFECT_TOUCH, EFFECT_AURA)
|
||||
effect_type = pick(EFFECT_BLUESPACE, EFFECT_SYNTH)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/datum/artifact_effect/rare/spines
|
||||
/datum/artifact_effect/extreme/spines
|
||||
name = "spines"
|
||||
effect_color = "#8db6b2"
|
||||
effect_type = EFFECT_ORGANIC
|
||||
|
||||
var/obj/item/projectile_type = /obj/item/projectile/bullet/thorn
|
||||
|
||||
|
||||
/datum/artifact_effect/extreme/spines/New()
|
||||
. = ..()
|
||||
@@ -12,13 +14,13 @@
|
||||
/datum/artifact_effect/extreme/spines/proc/shoot(var/list/exempt = list())
|
||||
var/atom/A = get_master_holder()
|
||||
A.visible_message("<span class='danger'>\The [get_master_holder()] fires spines wildly in all directions!</span>")
|
||||
for(var/i in range(1, round(chargelevel / 3)))
|
||||
for(var/i in rand(1, round(chargelevel / 3)))
|
||||
var/atom/target = pick(oview(world.view, get_turf(get_master_holder())))
|
||||
|
||||
if(target in exempt)
|
||||
continue
|
||||
|
||||
var/obj/item/projectile/P = new /obj/item/projectile/bullet/thorn(get_turf(get_master_holder()))
|
||||
var/obj/item/projectile/P = new projectile_type(get_turf(get_master_holder()))
|
||||
P.launch_projectile(target, BP_TORSO, get_master_holder())
|
||||
chargelevel -= 3
|
||||
|
||||
@@ -33,3 +35,21 @@
|
||||
if(chargelevel < 3)
|
||||
return
|
||||
shoot()
|
||||
|
||||
/datum/artifact_effect/extreme/spines/spore
|
||||
name = "bombarding"
|
||||
|
||||
projectile_type = /obj/item/projectile/arc/spore
|
||||
|
||||
/datum/artifact_effect/extreme/spines/spore/shoot(var/list/exempt = list())
|
||||
var/atom/A = get_master_holder()
|
||||
A.visible_message("<span class='danger'>\The [get_master_holder()] launches spores wildly in all directions!</span>")
|
||||
for(var/i in rand(1, round(chargelevel / 3)))
|
||||
var/atom/target = check_trajectory(pick(oview(world.view, get_turf(get_master_holder()))), get_master_holder(), PASSTABLE)
|
||||
|
||||
if(target in exempt)
|
||||
continue
|
||||
|
||||
var/obj/item/projectile/P = new projectile_type(get_turf(get_master_holder()))
|
||||
P.launch_projectile(target, BP_TORSO, get_master_holder())
|
||||
chargelevel -= 3
|
||||
|
||||
91
code/modules/xenoarcheaology/effects/lifemerger.dm
Normal file
91
code/modules/xenoarcheaology/effects/lifemerger.dm
Normal file
@@ -0,0 +1,91 @@
|
||||
/datum/artifact_effect/extreme/lifemerger
|
||||
name = "lifemerger"
|
||||
effect_color = "#3b1f3b"
|
||||
effect_type = EFFECT_ENERGY
|
||||
var/list/active_beams
|
||||
var/merging = FALSE
|
||||
|
||||
/datum/artifact_effect/extreme/lifemerger/DoEffectTouch()
|
||||
mergelife()
|
||||
|
||||
/datum/artifact_effect/extreme/lifemerger/DoEffectPulse()
|
||||
mergelife()
|
||||
|
||||
/datum/artifact_effect/extreme/lifemerger/DoEffectAura()
|
||||
mergelife()
|
||||
|
||||
/datum/artifact_effect/extreme/lifemerger/proc/mergelife()
|
||||
var/atom/holder = get_master_holder()
|
||||
|
||||
if(!holder)
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(holder)
|
||||
|
||||
var/list/nearby_mobs = list()
|
||||
for(var/mob/living/L in view(world.view, T) - holder)
|
||||
if(L.stat != DEAD)
|
||||
nearby_mobs |= L
|
||||
|
||||
if(nearby_mobs.len > 2)
|
||||
listclearnulls(active_beams)
|
||||
for(var/mob/living/L in nearby_mobs)
|
||||
if(L.stat == DEAD)
|
||||
continue
|
||||
if(!prob(5))
|
||||
continue
|
||||
var/beamtarget_exists = FALSE
|
||||
|
||||
if(active_beams.len)
|
||||
for(var/datum/beam/Beam in active_beams)
|
||||
if(Beam.target == L)
|
||||
beamtarget_exists = TRUE
|
||||
break
|
||||
|
||||
if(beamtarget_exists || GetAnomalySusceptibility(L) < 0.5)
|
||||
continue
|
||||
|
||||
holder.visible_message(
|
||||
"<span class='danger'>A bright beam beam lashes out from [bicon(get_master_holder())] \the [get_master_holder()] at \the [L]!</span>")
|
||||
var/datum/beam/drain_beam = holder.Beam(L, icon_state = "medbeam", time = 3 SECONDS * nearby_mobs.len)
|
||||
active_beams |= drain_beam
|
||||
if(!merging) // Don't add a ton of timers if this procs faster than 2 seconds, just average every 2.
|
||||
merging = TRUE
|
||||
addtimer(CALLBACK(src, .proc/averagelife), 2 SECONDS)
|
||||
|
||||
/datum/artifact_effect/extreme/lifemerger/proc/averagelife()
|
||||
listclearnulls(active_beams) // Clear nulls from mobs leaving the range.
|
||||
if(active_beams.len >= 2) // Work with remaining beams to find still-valid targets, if we still have 2 or more.
|
||||
var/list/remaining_mobs = list()
|
||||
var/brute_avg = 0
|
||||
var/burn_avg = 0
|
||||
var/oxy_avg = 0
|
||||
var/tox_avg = 0
|
||||
for(var/datum/beam/Beam in active_beams) // Find remaining beams' targets and their damage values.
|
||||
if(isliving(Beam.target))
|
||||
remaining_mobs |= Beam.target
|
||||
var/mob/living/L = Beam.target
|
||||
brute_avg += L.getBruteLoss()
|
||||
burn_avg += L.getFireLoss()
|
||||
oxy_avg += L.getOxyLoss()
|
||||
tox_avg += L.getToxLoss()
|
||||
|
||||
if(remaining_mobs.len) // Average by the number of remaining mobs.
|
||||
brute_avg /= remaining_mobs.len
|
||||
burn_avg /= remaining_mobs.len
|
||||
oxy_avg /= remaining_mobs.len
|
||||
tox_avg /= remaining_mobs.len
|
||||
|
||||
for(var/mob/living/L in remaining_mobs) // Adjust brute, burn, oxy, and tox of remaining mobs to the average
|
||||
L.adjustBruteLoss(brute_avg - L.getBruteLoss())
|
||||
L.adjustFireLoss(burn_avg - L.getFireLoss())
|
||||
L.adjustOxyLoss(oxy_avg - L.getOxyLoss())
|
||||
L.adjustToxLoss(tox_avg - L.getToxLoss())
|
||||
|
||||
L.add_modifier(/datum/modifier/berserk_exhaustion, remaining_mobs.len * 2 SECONDS)
|
||||
|
||||
for(var/datum/beam/Beam in active_beams) // Cull the beams.
|
||||
Beam.End()
|
||||
|
||||
listclearnulls(active_beams) // Cull the nulls.
|
||||
merging = FALSE // We're done!
|
||||
@@ -1551,6 +1551,7 @@
|
||||
#include "code\modules\blob2\blobs\normal.dm"
|
||||
#include "code\modules\blob2\blobs\resource.dm"
|
||||
#include "code\modules\blob2\blobs\shield.dm"
|
||||
#include "code\modules\blob2\overmind\chunks.dm"
|
||||
#include "code\modules\blob2\overmind\overmind.dm"
|
||||
#include "code\modules\blob2\overmind\powers.dm"
|
||||
#include "code\modules\blob2\overmind\types.dm"
|
||||
@@ -2983,6 +2984,7 @@
|
||||
#include "code\modules\reagents\reactions\_reactions.dm"
|
||||
#include "code\modules\reagents\reactions\distilling\distilling.dm"
|
||||
#include "code\modules\reagents\reactions\fusion\fusion.dm"
|
||||
#include "code\modules\reagents\reactions\instant\blob.dm"
|
||||
#include "code\modules\reagents\reactions\instant\drinks.dm"
|
||||
#include "code\modules\reagents\reactions\instant\food.dm"
|
||||
#include "code\modules\reagents\reactions\instant\instant.dm"
|
||||
@@ -3259,6 +3261,7 @@
|
||||
#include "code\modules\xenoarcheaology\effects\cellcharge.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\celldrain.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\cold.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\disarm.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\electric_field.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\emp.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\extinguisher.dm"
|
||||
@@ -3279,6 +3282,7 @@
|
||||
#include "code\modules\xenoarcheaology\effects\hurt.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\indiscriminate_spines.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\lifedrain.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\lifemerger.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\lifesteal.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\noxious.dm"
|
||||
#include "code\modules\xenoarcheaology\effects\poltergeist.dm"
|
||||
|
||||
Reference in New Issue
Block a user