diff --git a/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm b/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm
index 01009e41349..470cd2d8379 100644
--- a/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm
+++ b/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm
@@ -356,8 +356,8 @@
/area/ruin/space/has_grav/powered/hilbertresearchfacility)
"jC" = (
/mob/living/simple_animal/slime{
- colour = "bluespace";
- rabid = 1
+ rabid = 1;
+ slime_type = /datum/slime_type/bluespace
},
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/mineral/titanium/tiled/purple,
@@ -899,8 +899,8 @@
/area/ruin/space/has_grav/powered/hilbertresearchfacility)
"wY" = (
/mob/living/simple_animal/slime{
- colour = "bluespace";
- rabid = 1
+ rabid = 1;
+ slime_type = /datum/slime_type/bluespace
},
/turf/open/floor/mineral/plastitanium,
/area/ruin/space/has_grav/powered/hilbertresearchfacility)
@@ -2186,8 +2186,8 @@
},
/obj/effect/decal/cleanable/dirt,
/mob/living/simple_animal/slime{
- colour = "bluespace";
- rabid = 1
+ rabid = 1;
+ slime_type = /datum/slime_type/bluespace
},
/turf/open/floor/mineral/titanium/tiled/purple,
/area/ruin/space/has_grav/powered/hilbertresearchfacility)
@@ -2312,8 +2312,8 @@
/area/ruin/space/has_grav/powered/hilbertresearchfacility)
"Ze" = (
/mob/living/simple_animal/slime{
- colour = "bluespace";
- rabid = 1
+ rabid = 1;
+ slime_type = /datum/slime_type/bluespace
},
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/mineral/plastitanium,
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index acd01f2488c..d14d519efb1 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -494,7 +494,7 @@
reactants += G.reagents
for(var/obj/item/slime_extract/S in beakers)
- if(S.Uses)
+ if(S.extract_uses)
for(var/obj/item/reagent_containers/cup/G in beakers)
G.reagents.trans_to(S, G.reagents.total_volume)
diff --git a/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm b/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm
index b290c23ac3f..d3ee84181ed 100644
--- a/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm
+++ b/code/game/objects/effects/anomalies/anomalies_pyroclastic.dm
@@ -31,7 +31,7 @@
if(istype(tile))
tile.atmos_spawn_air("[GAS_O2]=500;[GAS_PLASMA]=500;[TURF_TEMPERATURE(1000)]") //Make it hot and burny for the new slime
- var/new_colour = pick("red", "orange")
+ var/new_colour = pick(/datum/slime_type/red, /datum/slime_type/orange)
var/mob/living/simple_animal/slime/pyro = new(tile, new_colour)
pyro.rabid = TRUE
pyro.amount_grown = SLIME_EVOLUTION_THRESHOLD
diff --git a/code/game/objects/items/devices/scanners/slime_scanner.dm b/code/game/objects/items/devices/scanners/slime_scanner.dm
index 6dcf600cbad..b05a0f31d1c 100644
--- a/code/game/objects/items/devices/scanners/slime_scanner.dm
+++ b/code/game/objects/items/devices/scanners/slime_scanner.dm
@@ -13,41 +13,44 @@
throw_range = 7
custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*0.30, /datum/material/glass=SMALL_MATERIAL_AMOUNT * 0.20)
-/obj/item/slime_scanner/attack(mob/living/M, mob/living/user)
- if(user.stat || !user.can_read(src)) //SKYRAT EDIT: Blind People Can Analyze Again
+/obj/item/slime_scanner/attack(mob/living/living_mob, mob/living/user)
+ if(user.stat || !user.can_read(src)) //SKYRAT EDIT CHANGE - Blind People Can Analyze Again - ORIGINAL : if(user.stat || !user.can_read(src) || user.is_blind())
return
- if (!isslime(M))
+ if (!isslime(living_mob))
to_chat(user, span_warning("This device can only scan slimes!"))
return
- var/mob/living/simple_animal/slime/T = M
- slime_scan(T, user)
+ var/mob/living/simple_animal/slime/scanned_slime = living_mob
+ slime_scan(scanned_slime, user)
-/proc/slime_scan(mob/living/simple_animal/slime/T, mob/living/user)
+/proc/slime_scan(mob/living/simple_animal/slime/scanned_slime, mob/living/user)
var/to_render = "Slime scan results:\
- \n[span_notice("[T.colour] [T.is_adult ? "adult" : "baby"] slime")]\
- \nNutrition: [T.nutrition]/[T.get_max_nutrition()]"
- if (T.nutrition < T.get_starve_nutrition())
+ \n[span_notice("[scanned_slime.slime_type.colour] [scanned_slime.is_adult ? "adult" : "baby"] slime")]\
+ \nNutrition: [scanned_slime.nutrition]/[scanned_slime.get_max_nutrition()]"
+
+ if (scanned_slime.nutrition < scanned_slime.get_starve_nutrition())
to_render += "\n[span_warning("Warning: slime is starving!")]"
- else if (T.nutrition < T.get_hunger_nutrition())
+ else if (scanned_slime.nutrition < scanned_slime.get_hunger_nutrition())
to_render += "\n[span_warning("Warning: slime is hungry")]"
- to_render += "\nElectric change strength: [T.powerlevel]\nHealth: [round(T.health/T.maxHealth,0.01)*100]%"
- if (T.slime_mutation[4] == T.colour)
- to_render += "\nThis slime does not evolve any further."
- else
- if (T.slime_mutation[3] == T.slime_mutation[4])
- if (T.slime_mutation[2] == T.slime_mutation[1])
- to_render += "\nPossible mutation: [T.slime_mutation[3]]\
- \nGenetic destability: [T.mutation_chance/2] % chance of mutation on splitting"
- else
- to_render += "\nPossible mutations: [T.slime_mutation[1]], [T.slime_mutation[2]], [T.slime_mutation[3]] (x2)\
- \nGenetic destability: [T.mutation_chance] % chance of mutation on splitting"
- else
- to_render += "\nPossible mutations: [T.slime_mutation[1]], [T.slime_mutation[2]], [T.slime_mutation[3]], [T.slime_mutation[4]]\
- \nGenetic destability: [T.mutation_chance] % chance of mutation on splitting"
- if (T.cores > 1)
+
+ to_render += "\nElectric charge strength: [scanned_slime.powerlevel]\nHealth: [round(scanned_slime.health/scanned_slime.maxHealth,0.01)*100]%"
+
+ to_render += "\nPossible mutation[scanned_slime.slime_type.mutations.len > 1 ? "s" : ""]: "
+ var/list/mutation_text = list()
+ for(var/datum/slime_type/key as anything in scanned_slime.slime_type.mutations)
+ mutation_text += initial(key.colour)
+
+ if(!mutation_text.len)
+ to_render += " None detected."
+
+ to_render += "[mutation_text.Join(", ")]"
+ to_render += "\nGenetic instability: [scanned_slime.mutation_chance] % chance of mutation attempt on splitting."
+
+ if (scanned_slime.cores > 1)
to_render += "\nMultiple cores detected"
- to_render += "\nGrowth progress: [T.amount_grown]/[SLIME_EVOLUTION_THRESHOLD]"
- if(T.effectmod)
- to_render += "\n[span_notice("Core mutation in progress: [T.effectmod]")]\
- \n[span_notice("Progress in core mutation: [T.applied] / [SLIME_EXTRACT_CROSSING_REQUIRED]")]"
- to_chat(user, examine_block(to_render))
+ to_render += "\nGrowth progress: [scanned_slime.amount_grown]/[SLIME_EVOLUTION_THRESHOLD]"
+
+ if(scanned_slime.crossbreed_modification)
+ to_render += "\n[span_notice("Core mutation in progress: [scanned_slime.crossbreed_modification]")]\
+ \n[span_notice("Progress in core mutation: [scanned_slime.applied_crossbreed_amount] / [SLIME_EXTRACT_CROSSING_REQUIRED]")]"
+
+ to_chat(user, examine_block(jointext(to_render,"")))
diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm
index f8ac3748de9..2c01ad53ede 100644
--- a/code/game/objects/items/grenades/chem_grenade.dm
+++ b/code/game/objects/items/grenades/chem_grenade.dm
@@ -295,7 +295,7 @@
if(istype(thing, /obj/item/slime_extract))
var/obj/item/slime_extract/extract = thing
- if(!extract.Uses)
+ if(!extract.extract_uses)
continue
extract_total_volume += extract.reagents.total_volume
diff --git a/code/modules/antagonists/abductor/equipment/glands/slime.dm b/code/modules/antagonists/abductor/equipment/glands/slime.dm
index faebce9fc87..60e680bc2a9 100644
--- a/code/modules/antagonists/abductor/equipment/glands/slime.dm
+++ b/code/modules/antagonists/abductor/equipment/glands/slime.dm
@@ -21,6 +21,6 @@
to_chat(owner, span_warning("You feel nauseated!"))
owner.vomit(VOMIT_CATEGORY_DEFAULT, lost_nutrition = 20)
- var/mob/living/simple_animal/slime/Slime = new(get_turf(owner), "grey")
+ var/mob/living/simple_animal/slime/Slime = new(get_turf(owner), /datum/slime_type/grey)
Slime.set_friends(list(owner))
Slime.set_leader(owner)
diff --git a/code/modules/food_and_drinks/machinery/processor.dm b/code/modules/food_and_drinks/machinery/processor.dm
index 60679f89345..6520478a1fb 100644
--- a/code/modules/food_and_drinks/machinery/processor.dm
+++ b/code/modules/food_and_drinks/machinery/processor.dm
@@ -236,9 +236,9 @@
return
var/core_count = processed_slime.cores
for(var/i in 1 to (core_count+rating_amount-1))
- var/atom/movable/item = new processed_slime.coretype(drop_location())
+ var/atom/movable/item = new processed_slime.slime_type.core_type(drop_location())
adjust_item_drop_location(item)
- SSblackbox.record_feedback("tally", "slime_core_harvested", 1, processed_slime.colour)
+ SSblackbox.record_feedback("tally", "slime_core_harvested", 1, processed_slime.slime_type.colour)
return ..()
#undef PROCESSOR_SELECT_RECIPE
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index 1708220cbf0..96f91f6a379 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -613,7 +613,7 @@
else
var/obj/item/slime_extract/to_integrate = human_owner.get_active_held_item()
- if(!istype(to_integrate) || to_integrate.Uses <= 0)
+ if(!istype(to_integrate) || to_integrate.extract_uses <= 0)
human_owner.balloon_alert(human_owner, "need an unused slime extract!")
return
if(!human_owner.temporarilyRemoveItemFromInventory(to_integrate))
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 60991f9e7a4..ccdcc18390f 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -297,25 +297,25 @@
return TRUE
-/mob/living/attack_slime(mob/living/simple_animal/slime/M, list/modifiers)
- if(M.buckled)
- if(M in buckled_mobs)
- M.Feedstop()
+/mob/living/attack_slime(mob/living/simple_animal/slime/attacking_slime, list/modifiers)
+ if(attacking_slime.buckled)
+ if(attacking_slime in buckled_mobs)
+ attacking_slime.stop_feeding()
return // can't attack while eating!
- if(HAS_TRAIT(src, TRAIT_PACIFISM))
- to_chat(M, span_warning("You don't want to hurt anyone!"))
+ if(HAS_TRAIT(attacking_slime, TRAIT_PACIFISM))
+ to_chat(attacking_slime, span_warning("You don't want to hurt anyone!"))
return FALSE
- if(check_block(src, M.melee_damage_upper, "[M]'s glomp", MELEE_ATTACK, M.armour_penetration, M.melee_damage_type))
+ if(check_block(src, attacking_slime.melee_damage_upper, "[attacking_slime]'s glomp", MELEE_ATTACK, attacking_slime.armour_penetration, attacking_slime.melee_damage_type))
return FALSE
if (stat != DEAD)
- log_combat(M, src, "attacked")
- M.do_attack_animation(src)
- visible_message(span_danger("\The [M.name] glomps [src]!"), \
- span_userdanger("\The [M.name] glomps you!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, M)
- to_chat(M, span_danger("You glomp [src]!"))
+ log_combat(attacking_slime, src, "attacked")
+ attacking_slime.do_attack_animation(src)
+ visible_message(span_danger("\The [attacking_slime.name] glomps [src]!"), \
+ span_userdanger("\The [attacking_slime.name] glomps you!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, attacking_slime)
+ to_chat(attacking_slime, span_danger("You glomp [src]!"))
return TRUE
return FALSE
diff --git a/code/modules/mob/living/simple_animal/slime/death.dm b/code/modules/mob/living/simple_animal/slime/death.dm
index 03cb70cbc47..033d7d2414e 100644
--- a/code/modules/mob/living/simple_animal/slime/death.dm
+++ b/code/modules/mob/living/simple_animal/slime/death.dm
@@ -3,23 +3,23 @@
return
if(!gibbed)
if(is_adult)
- var/mob/living/simple_animal/slime/M = new(drop_location(), colour)
- M.rabid = TRUE
- M.regenerate_icons()
+ var/mob/living/simple_animal/slime/new_slime = new(drop_location(), slime_type.type)
+ new_slime.rabid = TRUE
+ new_slime.regenerate_icons()
is_adult = FALSE
maxHealth = 150
- for(var/datum/action/innate/slime/reproduce/R in actions)
- R.Remove(src)
- var/datum/action/innate/slime/evolve/E = new
- E.Grant(src)
+ for(var/datum/action/innate/slime/reproduce/reproduce_action in actions)
+ reproduce_action.Remove(src)
+ var/datum/action/innate/slime/evolve/evolve_action = new
+ evolve_action.Grant(src)
revive(HEAL_ALL)
regenerate_icons()
update_name()
return
if(buckled)
- Feedstop(silent = TRUE) //releases ourselves from the mob we fed on.
+ stop_feeding(silent = TRUE) //releases ourselves from the mob we fed on.
cut_overlays()
diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm
index 3c34a68d6a2..078ec2749b5 100644
--- a/code/modules/mob/living/simple_animal/slime/life.dm
+++ b/code/modules/mob/living/simple_animal/slime/life.dm
@@ -1,3 +1,7 @@
+#define SLIME_HUNGER_NONE 0
+#define SLIME_HUNGER_HUNGRY 1
+#define SLIME_HUNGER_STARVING 2
+
/mob/living/simple_animal/slime/Life(seconds_per_tick = SSMOBS_DT, times_fired)
if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
return
@@ -31,21 +35,21 @@
return
return ..()
+/// the master AI process
+/mob/living/simple_animal/slime/proc/process_slime_ai()
-/mob/living/simple_animal/slime/proc/AIprocess() // the master AI process
-
- if(AIproc || stat || client)
+ if(slime_ai_processing || stat || client)
return
- var/hungry = 0
+ var/hungry = SLIME_HUNGER_NONE
if (nutrition < get_starve_nutrition())
- hungry = 2
+ hungry = SLIME_HUNGER_STARVING
else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
- hungry = 1
+ hungry = SLIME_HUNGER_HUNGRY
- AIproc = 1
+ slime_ai_processing = TRUE
- while(AIproc && stat != DEAD && (attacked || hungry || rabid || buckled))
+ while(slime_ai_processing && stat != DEAD && (attacked_stacks || hungry || rabid || buckled))
if(!(mobility_flags & MOBILITY_MOVE)) //also covers buckling. Not sure why buckled is in the while condition if we're going to immediately break, honestly
break
@@ -54,22 +58,22 @@
if(Target.health <= -70 || Target.stat == DEAD)
set_target(null)
- AIproc = 0
+ slime_ai_processing = FALSE
break
if(Target)
if(locate(/mob/living/simple_animal/slime) in Target.buckled_mobs)
set_target(null)
- AIproc = 0
+ slime_ai_processing = FALSE
break
- if(!AIproc)
+ if(!slime_ai_processing)
break
if(Target in view(1,src))
- if(!CanFeedon(Target)) //If they're not able to be fed upon, ignore them.
- if(!Atkcool)
- Atkcool = TRUE
- addtimer(VARSET_CALLBACK(src, Atkcool, FALSE), 4.5 SECONDS)
+ if(!can_feed_on(Target)) //If they're not able to be fed upon, ignore them.
+ if(!is_attack_on_cooldown)
+ is_attack_on_cooldown = TRUE
+ addtimer(VARSET_CALLBACK(src, is_attack_on_cooldown, FALSE), 4.5 SECONDS)
if(Target.Adjacent(src))
Target.attack_slime(src)
@@ -77,20 +81,20 @@
if((Target.body_position == STANDING_UP) && prob(80))
if(Target.client && Target.health >= 20)
- if(!Atkcool)
- Atkcool = TRUE
- addtimer(VARSET_CALLBACK(src, Atkcool, FALSE), 4.5 SECONDS)
+ if(!is_attack_on_cooldown)
+ is_attack_on_cooldown = TRUE
+ addtimer(VARSET_CALLBACK(src, is_attack_on_cooldown, FALSE), 4.5 SECONDS)
if(Target.Adjacent(src))
Target.attack_slime(src)
else
- if(!Atkcool && Target.Adjacent(src))
- Feedon(Target)
+ if(!is_attack_on_cooldown && Target.Adjacent(src))
+ start_feeding(Target)
else
- if(!Atkcool && Target.Adjacent(src))
- Feedon(Target)
+ if(!is_attack_on_cooldown && Target.Adjacent(src))
+ start_feeding(Target)
else if(Target in view(7, src))
if(!Target.Adjacent(src))
@@ -98,7 +102,7 @@
step_to(src, Target)
else
set_target(null)
- AIproc = 0
+ slime_ai_processing = FALSE
break
var/sleeptime = cached_multiplicative_slowdown
@@ -107,7 +111,7 @@
sleep(sleeptime + 2) // this is about as fast as a player slime can go
- AIproc = 0
+ slime_ai_processing = FALSE
/mob/living/simple_animal/slime/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired)
var/loc_temp = get_temperature(environment)
@@ -159,15 +163,16 @@
updatehealth()
+///Handles the slime draining the target it is attached to
/mob/living/simple_animal/slime/proc/handle_feeding(seconds_per_tick, times_fired)
var/mob/living/prey = buckled
if(stat)
- Feedstop(silent = TRUE)
+ stop_feeding(silent = TRUE)
if(prey.stat == DEAD) // our victim died
if(!client)
- if(!rabid && !attacked)
+ if(!rabid && !attacked_stacks)
var/mob/last_to_hurt = prey.LAssailant?.resolve()
if(last_to_hurt && last_to_hurt != prey)
if(SPT_PROB(30, seconds_per_tick))
@@ -177,9 +182,9 @@
if(prey.client && ishuman(prey))
if(SPT_PROB(61, seconds_per_tick))
- rabid = 1 //we go rabid after finishing to feed on a human with a client.
+ rabid = TRUE //we go rabid after finishing to feed on a human with a client.
- Feedstop()
+ stop_feeding()
return
if(iscarbon(prey))
@@ -206,11 +211,11 @@
animal_victim.updatehealth()
if(totaldamage <= 0) //if we did no(or negative!) damage to it, stop
- Feedstop(0, 0)
+ stop_feeding(FALSE, FALSE)
return
else
- Feedstop(0, 0)
+ stop_feeding(FALSE, FALSE)
return
add_nutrition((rand(7, 15) * 0.5 * seconds_per_tick * CONFIG_GET(number/damage_multiplier)))
@@ -218,6 +223,7 @@
//Heal yourself.
adjustBruteLoss(-1.5 * seconds_per_tick)
+///Handles the slime's nutirion level
/mob/living/simple_animal/slime/proc/handle_nutrition(seconds_per_tick, times_fired)
if(docile) //God as my witness, I will never go hungry again
@@ -243,6 +249,7 @@
else
Evolve()
+///Adds nutrition to the slime's nutrition level. Has a chance to increase its electric levels.
/mob/living/simple_animal/slime/proc/add_nutrition(nutrition_to_add = 0)
set_nutrition(min((nutrition + nutrition_to_add), get_max_nutrition()))
if(nutrition >= get_grow_nutrition())
@@ -254,124 +261,124 @@
if(prob(25-powerlevel*5))
powerlevel++
-
-
-
+///Handles selecting targets
/mob/living/simple_animal/slime/proc/handle_targets(seconds_per_tick, times_fired)
- if(attacked > 50)
- attacked = 50
+ if(attacked_stacks > 50)
+ attacked_stacks = 50
- if(attacked > 0)
- attacked--
+ if(attacked_stacks > 0)
+ attacked_stacks--
- if(Discipline > 0)
+ if(discipline_stacks > 0)
- if(Discipline >= 5 && rabid)
+ if(discipline_stacks >= 5 && rabid)
if(SPT_PROB(37, seconds_per_tick))
- rabid = 0
+ rabid = FALSE
if(SPT_PROB(5, seconds_per_tick))
- Discipline--
+ discipline_stacks--
- if(!client)
- if(!(mobility_flags & MOBILITY_MOVE))
- return
+ if(client) //player controlled slimes can decide for themselves
+ return
- if(buckled)
- return // if it's eating someone already, continue eating!
+ if(!(mobility_flags & MOBILITY_MOVE))
+ return
- if(Target)
- --target_patience
- if (target_patience <= 0 || SStun > world.time || Discipline || attacked || docile) // Tired of chasing or something draws out attention
- target_patience = 0
- set_target(null)
+ if(buckled)
+ return // if it's eating someone already, continue eating!
- if(AIproc && SStun > world.time)
- return
+ if(Target)
+ --target_patience
+ if (target_patience <= 0 || stunned_until > world.time || discipline_stacks || attacked_stacks || docile) // Tired of chasing or something draws out attention
+ target_patience = 0
+ set_target(null)
- var/hungry = 0 // determines if the slime is hungry
+ if(slime_ai_processing && stunned_until > world.time)
+ return
- if (nutrition < get_starve_nutrition())
- hungry = 2
- else if (nutrition < get_grow_nutrition() && SPT_PROB(13, seconds_per_tick) || nutrition < get_hunger_nutrition())
- hungry = 1
+ var/hungry = SLIME_HUNGER_NONE // determines if the slime is hungry
- if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends
- if(Friends.len > 0 && SPT_PROB(0.5, seconds_per_tick))
- var/mob/nofriend = pick(Friends)
- add_friendship(nofriend, -1)
+ if (nutrition < get_starve_nutrition())
+ hungry = SLIME_HUNGER_STARVING
+ else if (nutrition < get_grow_nutrition() && SPT_PROB(13, seconds_per_tick) || nutrition < get_hunger_nutrition())
+ hungry = SLIME_HUNGER_HUNGRY
- if(!Target)
- if(will_hunt() && hungry || attacked || rabid) // Only add to the list if we need to
- var/list/targets = list()
+ if(hungry == SLIME_HUNGER_STARVING && !client) // if a slime is starving, it starts losing its friends
+ if(Friends.len > 0 && SPT_PROB(0.5, seconds_per_tick))
+ var/mob/nofriend = pick(Friends)
+ add_friendship(nofriend, -1)
- for(var/mob/living/L in view(7,src))
+ if(!Target) //If we have no target, try to add a target
+ if(will_hunt() && hungry || attacked_stacks || rabid) // Only add to the list if we need to
+ var/list/targets = list()
- if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs
- continue
+ for(var/mob/living/L in view(7,src))
- if(L in Friends) // No eating friends!
- continue
+ if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs
+ continue
- var/ally = FALSE
- for(var/F in faction)
- if(F == FACTION_NEUTRAL) //slimes are neutral so other mobs not target them, but they can target neutral mobs
- continue
- if(F in L.faction)
- ally = TRUE
- break
- if(ally)
- continue
+ if(L in Friends) // No eating friends!
+ continue
- if(issilicon(L) && (rabid || attacked)) // They can't eat silicons, but they can glomp them in defence
- targets += L // Possible target found!
-
- if(locate(/mob/living/simple_animal/slime) in L.buckled_mobs) // Only one slime can latch on at a time.
+ var/ally = FALSE
+ for(var/F in faction)
+ if(F == FACTION_NEUTRAL) //slimes are neutral so other mobs not target them, but they can target neutral mobs
continue
+ if(F in L.faction)
+ ally = TRUE
+ break
+ if(ally)
+ continue
+ if(issilicon(L) && (rabid || attacked_stacks)) // They can't eat silicons, but they can glomp them in defence
targets += L // Possible target found!
- if(targets.len > 0)
- if(attacked || rabid || hungry == 2)
- set_target(targets[1]) // I am attacked and am fighting back or so hungry I don't even care
- else
- for(var/mob/living/carbon/C in targets)
- if(!Discipline && SPT_PROB(2.5, seconds_per_tick))
- if(ishuman(C) || isalienadult(C))
- set_target(C)
- break
+ if(locate(/mob/living/simple_animal/slime) in L.buckled_mobs) // Only one slime can latch on at a time.
+ continue
- if(islarva(C) || ismonkey(C))
+ targets += L // Possible target found!
+
+ if(targets.len > 0)
+ if(attacked_stacks || rabid || hungry == SLIME_HUNGER_STARVING)
+ set_target(targets[1]) // I am attacked and am fighting back or so hungry I don't even care
+ else
+ for(var/mob/living/carbon/C in targets)
+ if(!discipline_stacks && SPT_PROB(2.5, seconds_per_tick))
+ if(ishuman(C) || isalienadult(C))
set_target(C)
break
- if (Target)
- target_patience = rand(5, 7)
- if (is_adult)
- target_patience += 3
-
- if(!Target) // If we have no target, we are wandering or following orders
- if (Leader)
- if(holding_still)
- holding_still = max(holding_still - (0.5 * seconds_per_tick), 0)
- else if(!HAS_TRAIT(src, TRAIT_IMMOBILIZED) && isturf(loc))
- step_to(src, Leader)
-
- else if(hungry)
- if (holding_still)
- holding_still = max(holding_still - (0.5 * hungry * seconds_per_tick), 0)
- else if(!HAS_TRAIT(src, TRAIT_IMMOBILIZED) && isturf(loc) && prob(50))
- step(src, pick(GLOB.cardinals))
+ if(islarva(C) || ismonkey(C))
+ set_target(C)
+ break
- else
- if(holding_still)
- holding_still = max(holding_still - (0.5 * seconds_per_tick), 0)
- else if (docile && pulledby)
- holding_still = 10
- else if(!HAS_TRAIT(src, TRAIT_IMMOBILIZED) && isturf(loc) && prob(33))
- step(src, pick(GLOB.cardinals))
- else if(!AIproc)
- INVOKE_ASYNC(src, PROC_REF(AIprocess))
+ if (Target)
+ target_patience = rand(5, 7)
+ if (is_adult)
+ target_patience += 3
+
+ if(!Target) // If we have no target, we are wandering or following orders
+ if (Leader)
+ if(holding_still)
+ holding_still = max(holding_still - (0.5 * seconds_per_tick), 0)
+ else if(!HAS_TRAIT(src, TRAIT_IMMOBILIZED) && isturf(loc))
+ step_to(src, Leader)
+
+ else if(hungry)
+ if (holding_still)
+ holding_still = max(holding_still - (0.5 * hungry * seconds_per_tick), 0)
+ else if(!HAS_TRAIT(src, TRAIT_IMMOBILIZED) && isturf(loc) && prob(50))
+ step(src, pick(GLOB.cardinals))
+
+ else
+ if(holding_still)
+ holding_still = max(holding_still - (0.5 * seconds_per_tick), 0)
+ else if (docile && pulledby)
+ holding_still = 10
+ else if(!HAS_TRAIT(src, TRAIT_IMMOBILIZED) && isturf(loc) && prob(33))
+ step(src, pick(GLOB.cardinals))
+ else if(!slime_ai_processing)
+ INVOKE_ASYNC(src, PROC_REF(process_slime_ai))
/mob/living/simple_animal/slime/handle_automated_movement()
return //slime random movement is currently handled in handle_targets()
@@ -379,22 +386,30 @@
/mob/living/simple_animal/slime/handle_automated_speech()
return //slime random speech is currently handled in handle_speech()
+///Handles slime mood
/mob/living/simple_animal/slime/proc/handle_mood(seconds_per_tick, times_fired)
- var/newmood = ""
- if (rabid || attacked)
- newmood = "angry"
+ #define SLIME_MOOD_NONE ""
+ #define SLIME_MOOD_ANGRY "angry"
+ #define SLIME_MOOD_MISCHIEVOUS "mischievous"
+ #define SLIME_MOOD_POUT "pout"
+ #define SLIME_MOOD_SAD "sad"
+ #define SLIME_MOOD_SMILE ":3"
+
+ var/newmood = SLIME_MOOD_NONE
+ if (rabid || attacked_stacks)
+ newmood = SLIME_MOOD_ANGRY
else if (docile)
- newmood = ":3"
+ newmood = SLIME_MOOD_SMILE
else if (Target)
- newmood = "mischievous"
+ newmood = SLIME_MOOD_MISCHIEVOUS
if (!newmood)
- if (Discipline && SPT_PROB(13, seconds_per_tick))
- newmood = "pout"
+ if (discipline_stacks && SPT_PROB(13, seconds_per_tick))
+ newmood = SLIME_MOOD_POUT
else if (SPT_PROB(0.5, seconds_per_tick))
- newmood = pick("sad", ":3", "pout")
+ newmood = pick(SLIME_MOOD_SAD, ":3", SLIME_MOOD_POUT)
- if ((current_mood == "sad" || current_mood == ":3" || current_mood == "pout") && !newmood)
+ if ((current_mood == SLIME_MOOD_SAD || current_mood == SLIME_MOOD_SMILE || current_mood == SLIME_MOOD_POUT) && !newmood)
if(SPT_PROB(50, seconds_per_tick))
newmood = current_mood
@@ -402,13 +417,21 @@
current_mood = newmood
regenerate_icons()
+ #undef SLIME_MOOD_NONE
+ #undef SLIME_MOOD_ANGRY
+ #undef SLIME_MOOD_MISCHIEVOUS
+ #undef SLIME_MOOD_POUT
+ #undef SLIME_MOOD_SAD
+ #undef SLIME_MOOD_SMILE
+
+///Handles the slime understanding commends spoken to it
/mob/living/simple_animal/slime/proc/handle_speech(seconds_per_tick, times_fired)
//Speech understanding starts here
var/to_say
if (speech_buffer.len > 0)
var/who = speech_buffer[1] // Who said it?
var/phrase = speech_buffer[2] // What did they say?
- if ((findtext(phrase, num2text(number)) || findtext(phrase, "slimes"))) // Talking to us
+ if ((findtext(phrase, num2text(slime_id)) || findtext(phrase, "slimes"))) // Talking to us
if (findtext(phrase, "hello") || findtext(phrase, "hi"))
to_say = pick("Hello...", "Hi...")
else if (findtext(phrase, "follow"))
@@ -429,7 +452,7 @@
else if (findtext(phrase, "stop"))
if (buckled) // We are asked to stop feeding
if (Friends[who] >= SLIME_FRIENDSHIP_STOPEAT)
- Feedstop()
+ stop_feeding()
set_target(null)
if (Friends[who] < SLIME_FRIENDSHIP_STOPEAT_NOANGRY)
add_friendship(who, -1)
@@ -473,20 +496,20 @@
else if (findtext(phrase, "attack"))
if (rabid && prob(20))
set_target(who)
- AIprocess() //Wake up the slime's Target AI, needed otherwise this doesn't work
+ process_slime_ai() //Wake up the slime's Target AI, needed otherwise this doesn't work
to_say = "ATTACK!?!?"
else if (Friends[who] >= SLIME_FRIENDSHIP_ATTACK)
- for (var/mob/living/L in view(7,src)-list(src,who))
- if (findtext(phrase, lowertext(L.name)))
- if (isslime(L))
- to_say = "NO... [L] slime friend"
+ for (var/mob/living/possible_target in view(7,src)-list(src,who))
+ if (findtext(phrase, lowertext(possible_target.name)))
+ if (isslime(possible_target))
+ to_say = "NO... [possible_target] slime friend"
add_friendship(who, -1) //Don't ask a slime to attack its friend
- else if(!Friends[L] || Friends[L] < 1)
- set_target(L)
- AIprocess()//Wake up the slime's Target AI, needed otherwise this doesn't work
+ else if(!Friends[possible_target] || Friends[possible_target] < 1)
+ set_target(possible_target)
+ process_slime_ai()//Wake up the slime's Target AI, needed otherwise this doesn't work
to_say = "Ok... I attack [Target]"
else
- to_say = "No... like [L] ..."
+ to_say = "No... like [possible_target] ..."
add_friendship(who, -1) //Don't ask a slime to attack its friend
break
else
@@ -500,23 +523,23 @@
else if(SPT_PROB(0.5, seconds_per_tick))
emote(pick("bounce","sway","light","vibrate","jiggle"))
else
- var/t = 10
+ var/speech_chance = 10
var/slimes_near = 0
var/dead_slimes = 0
var/friends_near = list()
- for (var/mob/living/L in view(7,src))
- if(isslime(L) && L != src)
+ for (var/mob/living/seen_mob in view(7,src))
+ if(isslime(seen_mob) && seen_mob != src)
++slimes_near
- if (L.stat == DEAD)
+ if (seen_mob.stat == DEAD)
++dead_slimes
- if (L in Friends)
- t += 20
- friends_near += L
+ if (seen_mob in Friends)
+ speech_chance += 20
+ friends_near += seen_mob
if (nutrition < get_hunger_nutrition())
- t += 10
+ speech_chance += 10
if (nutrition < get_starve_nutrition())
- t += 10
- if (SPT_PROB(1, seconds_per_tick) && prob(t))
+ speech_chance += 10
+ if (SPT_PROB(1, seconds_per_tick) && prob(speech_chance))
var/phrases = list()
if (Target)
phrases += "[Target]... look yummy..."
@@ -532,13 +555,13 @@
phrases += "Rawr..."
phrases += "Blop..."
phrases += "Blorble..."
- if (rabid || attacked)
+ if (rabid || attacked_stacks)
phrases += "Hrr..."
phrases += "Nhuu..."
phrases += "Unn..."
if (current_mood == ":3")
phrases += "Purr..."
- if (attacked)
+ if (attacked_stacks)
phrases += "Grrr..."
if (bodytemperature < T0C)
phrases += "Cold..."
@@ -567,44 +590,52 @@
phrases += "What happened?"
if (!slimes_near)
phrases += "Lonely..."
- for (var/M in friends_near)
- phrases += "[M]... friend..."
+ for (var/friend in friends_near)
+ phrases += "[friend]... friend..."
if (nutrition < get_hunger_nutrition())
- phrases += "[M]... feed me..."
+ phrases += "[friend]... feed me..."
if(!stat)
say (pick(phrases))
-/mob/living/simple_animal/slime/proc/get_max_nutrition() // Can't go above it
+/// Can't go above it
+/mob/living/simple_animal/slime/proc/get_max_nutrition()
if (is_adult)
return 1200
else
return 1000
-/mob/living/simple_animal/slime/proc/get_grow_nutrition() // Above it we grow, below it we can eat
+/// Above it we grow, below it we can eat
+/mob/living/simple_animal/slime/proc/get_grow_nutrition()
if (is_adult)
return 1000
else
return 800
-/mob/living/simple_animal/slime/proc/get_hunger_nutrition() // Below it we will always eat
+/// Below it we will always eat
+/mob/living/simple_animal/slime/proc/get_hunger_nutrition()
if (is_adult)
return 600
else
return 500
-/mob/living/simple_animal/slime/proc/get_starve_nutrition() // Below it we will eat before everything else
+/// Below it we will eat before everything else
+/mob/living/simple_animal/slime/proc/get_starve_nutrition()
if(is_adult)
return 300
else
return 200
-
-/mob/living/simple_animal/slime/proc/will_hunt(hunger = -1) // Check for being stopped from feeding and chasing
+/// Check for being stopped from feeding and chasing
+/mob/living/simple_animal/slime/proc/will_hunt(hunger = -1)
if (docile)
return FALSE
- if (hunger == 2 || rabid || attacked)
+ if (hunger == SLIME_HUNGER_STARVING || rabid || attacked_stacks)
return TRUE
if (Leader)
return FALSE
if (holding_still)
return FALSE
return TRUE
+
+#undef SLIME_HUNGER_NONE
+#undef SLIME_HUNGER_HUNGRY
+#undef SLIME_HUNGER_STARVING
diff --git a/code/modules/mob/living/simple_animal/slime/powers.dm b/code/modules/mob/living/simple_animal/slime/powers.dm
index a485b8342ca..32c60f63adc 100644
--- a/code/modules/mob/living/simple_animal/slime/powers.dm
+++ b/code/modules/mob/living/simple_animal/slime/powers.dm
@@ -16,9 +16,9 @@
. = ..()
if(!.)
return
- var/mob/living/simple_animal/slime/S = owner
+ var/mob/living/simple_animal/slime/slime_owner = owner
if(needs_growth == GROWTH_NEEDED)
- if(S.amount_grown >= SLIME_EVOLUTION_THRESHOLD)
+ if(slime_owner.amount_grown >= SLIME_EVOLUTION_THRESHOLD)
return TRUE
return FALSE
return TRUE
@@ -39,8 +39,8 @@
if(isnull(choice))
return FALSE
var/mob/living/victim = choice
- if(CanFeedon(victim))
- Feedon(victim)
+ if(can_feed_on(victim))
+ start_feeding(victim)
return TRUE
return FALSE
@@ -50,15 +50,16 @@
/datum/action/innate/slime/feed/Activate()
- var/mob/living/simple_animal/slime/S = owner
- S.Feed()
+ var/mob/living/simple_animal/slime/slime_owner = owner
+ slime_owner.Feed()
-/mob/living/simple_animal/slime/proc/CanFeedon(mob/living/meal, silent = FALSE)
+///Can the slime leech life energy from the target?
+/mob/living/simple_animal/slime/proc/can_feed_on(mob/living/meal, silent = FALSE)
if(!Adjacent(meal))
return FALSE
if(buckled)
- Feedstop()
+ stop_feeding()
return FALSE
if(issilicon(meal) || meal.mob_biotypes & MOB_ROBOTIC)
@@ -120,16 +121,18 @@
return FALSE
return TRUE
-/mob/living/simple_animal/slime/proc/Feedon(mob/living/M)
- M.unbuckle_all_mobs(force=1) //Slimes rip other mobs (eg: shoulder parrots) off (Slimes Vs Slimes is already handled in CanFeedon())
- if(M.buckle_mob(src, force=TRUE))
- layer = M.layer+0.01 //appear above the target mob
- M.visible_message(span_danger("[name] latches onto [M]!"), \
- span_userdanger("[name] latches onto [M]!"))
+///The slime will start feeding on the target
+/mob/living/simple_animal/slime/proc/start_feeding(mob/living/target_mob)
+ target_mob.unbuckle_all_mobs(force=TRUE) //Slimes rip other mobs (eg: shoulder parrots) off (Slimes Vs Slimes is already handled in can_feed_on())
+ if(target_mob.buckle_mob(src, force=TRUE))
+ layer = target_mob.layer+0.01 //appear above the target mob
+ target_mob.visible_message(span_danger("[name] latches onto [target_mob]!"), \
+ span_userdanger("[name] latches onto [target_mob]!"))
else
to_chat(src, span_warning("I have failed to latch onto the subject!"))
-/mob/living/simple_animal/slime/proc/Feedstop(silent = FALSE, living=1)
+///The slime will stop feeding
+/mob/living/simple_animal/slime/proc/stop_feeding(silent = FALSE, living=TRUE)
if(buckled)
if(!living)
to_chat(src, "[pick("This subject is incompatible", \
@@ -142,7 +145,7 @@
if(istype(victim))
var/bio_protection = 100 - victim.getarmor(null, BIO)
if(prob(bio_protection))
- victim.apply_status_effect(/datum/status_effect/slimed, slime_colours_to_rgb[colour], colour == SLIME_TYPE_RAINBOW)
+ victim.apply_status_effect(/datum/status_effect/slimed, slime_type.rgb_code, slime_type.colour == SLIME_TYPE_RAINBOW)
if(!silent)
visible_message(span_warning("[src] lets go of [buckled]!"), \
@@ -157,20 +160,21 @@
if(stat)
to_chat(src, "I must be conscious to do this...")
return
- if(!is_adult)
- if(amount_grown >= SLIME_EVOLUTION_THRESHOLD)
- is_adult = 1
- maxHealth = 200
- amount_grown = 0
- for(var/datum/action/innate/slime/evolve/E in actions)
- E.Remove(src)
- GRANT_ACTION(/datum/action/innate/slime/reproduce)
- regenerate_icons()
- update_name()
- else
- to_chat(src, "I am not ready to evolve yet...")
- else
+ if(is_adult)
to_chat(src, "I have already evolved...")
+ return
+ if(amount_grown < SLIME_EVOLUTION_THRESHOLD)
+ to_chat(src, "I am not ready to evolve yet...")
+ return
+
+ is_adult = TRUE
+ maxHealth = 200
+ amount_grown = 0
+ for(var/datum/action/innate/slime/evolve/evolve_action in actions)
+ evolve_action.Remove(src)
+ GRANT_ACTION(/datum/action/innate/slime/reproduce)
+ regenerate_icons()
+ update_name()
/datum/action/innate/slime/evolve
name = "Evolve"
@@ -178,8 +182,8 @@
needs_growth = GROWTH_NEEDED
/datum/action/innate/slime/evolve/Activate()
- var/mob/living/simple_animal/slime/S = owner
- S.Evolve()
+ var/mob/living/simple_animal/slime/slime_owner = owner
+ slime_owner.Evolve()
/mob/living/simple_animal/slime/verb/Reproduce()
set category = "Slime"
@@ -209,11 +213,11 @@
var/child_colour
if(mutation_chance >= 100)
- child_colour = SLIME_TYPE_RAINBOW
+ child_colour = /datum/slime_type/rainbow
else if(prob(mutation_chance))
- child_colour = slime_mutation[rand(1,4)]
+ child_colour = pick_weight(slime_type.mutations)
else
- child_colour = colour
+ child_colour = slime_type.type
var/mob/living/simple_animal/slime/baby
baby = new(drop_loc, child_colour)
@@ -228,7 +232,7 @@
baby.set_friends(Friends)
babies += baby
baby.mutation_chance = clamp(mutation_chance+(rand(5,-5)),0,100)
- SSblackbox.record_feedback("tally", "slime_babies_born", 1, baby.colour)
+ SSblackbox.record_feedback("tally", "slime_babies_born", 1, baby.slime_type.colour)
var/mob/living/simple_animal/slime/new_slime = pick(babies) // slime that the OG slime will move into.
new_slime.set_combat_mode(TRUE)
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 3e5d714746b..b03f46d5a44 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -40,126 +40,95 @@
footstep_type = FOOTSTEP_MOB_SLIME
- ///The current mood of the slime, set randomly or through emotes (if sentient).
- var/current_mood
-
- var/AIproc = 0 // determines if the AI loop is activated
- var/Atkcool = 0 // attack cooldown
- var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while
- var/SStun = 0 // stun variable
-
- var/is_adult = 0
- var/docile = 0
-
- var/cores = 1 // the number of /obj/item/slime_extract's the slime has left inside
- var/mutation_chance = 30 // Chance of mutating, should be between 25 and 35
-
- var/powerlevel = 0 // 1-10 controls how much electricity they are generating
- var/amount_grown = 0 // controls how long the slime has been overfed, if 10, grows or reproduces
+ //Physiology
+
+ ///Is the slime an adult slime?
+ var/is_adult = TRUE
+
+ ///The number of /obj/item/slime_extract's the slime has left inside
+ var/cores = 1
+ ///Chance of mutating, should be between 25 and 35
+ var/mutation_chance = 30
+ ///1-10 controls how much electricity they are generating
+ var/powerlevel = 0
+ ///Controls how long the slime has been overfed, if 10, grows or reproduces
+ var/amount_grown = 0
+
+ ///Has a mutator been used on the slime? Only one is allowed
+ var/mutator_used = FALSE
+ ///Is the slime forced into being immobile, despite the gases present?
+ var/force_stasis = FALSE
- var/number = 0 // Used to understand when someone is talking to it
+ //The datum that handles the slime colour's core and possible mutations
+ var/datum/slime_type/slime_type
- var/mob/living/Target = null // AI variable - tells the slime to hunt this down
- var/mob/living/Leader = null // AI variable - tells the slime to follow this person
+ //CORE-CROSSING CODE
- var/attacked = 0 // Determines if it's been attacked recently. Can be any number, is a cooloff-ish variable
- var/rabid = 0 // If set to 1, the slime will attack and eat anything it comes in contact with
- var/holding_still = 0 // AI variable, cooloff-ish for how long it's going to stay in one place
- var/target_patience = 0 // AI variable, cooloff-ish for how long it's going to follow its target
+ ///What cross core modification is being used.
+ var/crossbreed_modification
+ ///How many extracts of the modtype have been applied.
+ var/applied_crossbreed_amount = 0
- var/list/Friends = list() // A list of friends; they are not considered targets for feeding; passed down after splitting
+ //AI related traits
- var/list/speech_buffer = list() // Last phrase said near it and person who said it
+ ///The current mood of the slime, set randomly or through emotes (if sentient).
+ var/current_mood
- var/mutator_used = FALSE //So you can't shove a dozen mutators into a single slime
- var/force_stasis = FALSE
-
- var/static/regex/slime_name_regex = new("\\w+ (baby|adult) slime \\(\\d+\\)")
- ///////////TIME FOR SUBSPECIES
-
- var/colour = SLIME_TYPE_GREY
- var/coretype = /obj/item/slime_extract/grey
- var/list/slime_mutation[4]
-
- var/static/list/slime_colours = list(
- SLIME_TYPE_ADAMANTINE,
- SLIME_TYPE_BLACK,
- SLIME_TYPE_BLUE,
- SLIME_TYPE_BLUESPACE,
- SLIME_TYPE_CERULEAN,
- SLIME_TYPE_DARK_BLUE,
- SLIME_TYPE_DARK_PURPLE,
- SLIME_TYPE_GOLD,
- SLIME_TYPE_GREEN,
- SLIME_TYPE_GREY,
- SLIME_TYPE_LIGHT_PINK,
- SLIME_TYPE_METAL,
- SLIME_TYPE_OIL,
- SLIME_TYPE_ORANGE,
- SLIME_TYPE_PINK,
- SLIME_TYPE_PURPLE,
- SLIME_TYPE_PYRITE,
- SLIME_TYPE_RAINBOW,
- SLIME_TYPE_RED,
- SLIME_TYPE_SEPIA,
- SLIME_TYPE_SILVER,
- SLIME_TYPE_YELLOW,
- )
-
- var/static/list/slime_colours_to_rgb = list(
- SLIME_TYPE_ADAMANTINE = COLOR_SLIME_ADAMANTINE,
- SLIME_TYPE_BLACK = COLOR_SLIME_BLACK,
- SLIME_TYPE_BLUE = COLOR_SLIME_BLUE,
- SLIME_TYPE_BLUESPACE = COLOR_SLIME_BLUESPACE,
- SLIME_TYPE_CERULEAN = COLOR_SLIME_CERULEAN,
- SLIME_TYPE_DARK_BLUE = COLOR_SLIME_DARK_BLUE,
- SLIME_TYPE_DARK_PURPLE = COLOR_SLIME_DARK_PURPLE,
- SLIME_TYPE_GOLD = COLOR_SLIME_GOLD,
- SLIME_TYPE_GREEN = COLOR_SLIME_GREEN,
- SLIME_TYPE_GREY = COLOR_SLIME_GREY,
- SLIME_TYPE_LIGHT_PINK = COLOR_SLIME_LIGHT_PINK,
- SLIME_TYPE_METAL = COLOR_SLIME_METAL,
- SLIME_TYPE_OIL = COLOR_SLIME_OIL,
- SLIME_TYPE_ORANGE = COLOR_SLIME_ORANGE,
- SLIME_TYPE_PINK = COLOR_SLIME_PINK,
- SLIME_TYPE_PURPLE = COLOR_SLIME_PURPLE,
- SLIME_TYPE_PYRITE = COLOR_SLIME_PYRITE,
- SLIME_TYPE_RAINBOW = COLOR_SLIME_RAINBOW,
- SLIME_TYPE_RED = COLOR_SLIME_RED,
- SLIME_TYPE_SEPIA = COLOR_SLIME_SEPIA,
- SLIME_TYPE_SILVER = COLOR_SLIME_SILVER,
- SLIME_TYPE_YELLOW = COLOR_SLIME_YELLOW,
- )
-
- ///////////CORE-CROSSING CODE
-
- var/effectmod //What core modification is being used.
- var/applied = 0 //How many extracts of the modtype have been applied.
-
-
-/mob/living/simple_animal/slime/Initialize(mapload, new_colour=colour, new_is_adult=FALSE)
- var/datum/action/innate/slime/feed/F = new
- F.Grant(src)
- ADD_TRAIT(src, TRAIT_CANT_RIDE, INNATE_TRAIT)
+ ///Determines if the AI loop is activated
+ var/slime_ai_processing = FALSE
+ ///Attack cooldown
+ var/is_attack_on_cooldown = FALSE
+ ///If a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while
+ var/discipline_stacks = 0
+ ///Stored the world time when the slime's stun wears off
+ var/stunned_until = 0
+
+ ///Is the slime docile?
+ var/docile = FALSE
+
+ ///Used to understand when someone is talking to it
+ var/slime_id = 0
+ ///AI variable - tells the slime to hunt this down
+ var/mob/living/Target = null
+ ///AI variable - tells the slime to follow this person
+ var/mob/living/Leader = null
+
+ ///Determines if it's been attacked recently. Can be any number, is a cooloff-ish variable
+ var/attacked_stacks = 0
+ ///If set to 1, the slime will attack and eat anything it comes in contact with
+ var/rabid = FALSE
+ ///AI variable, cooloff-ish for how long it's going to stay in one place
+ var/holding_still = 0
+ ///AI variable, cooloff-ish for how long it's going to follow its target
+ var/target_patience = 0
+ ///A list of friends; they are not considered targets for feeding; passed down after splitting
+ var/list/Friends = list()
+ ///Last phrase said near it and person who said it
+ var/list/speech_buffer = list()
+
+/mob/living/simple_animal/slime/Initialize(mapload, new_type=/datum/slime_type/grey, new_is_adult=FALSE)
+ var/datum/action/innate/slime/feed/feeding_action = new
+ feeding_action.Grant(src)
is_adult = new_is_adult
if(is_adult)
- var/datum/action/innate/slime/reproduce/R = new
- R.Grant(src)
+ var/datum/action/innate/slime/reproduce/reproduce_action = new
+ reproduce_action.Grant(src)
health = 200
maxHealth = 200
else
- var/datum/action/innate/slime/evolve/E = new
- E.Grant(src)
+ var/datum/action/innate/slime/evolve/evolve_action = new
+ evolve_action.Grant(src)
create_reagents(100)
- set_colour(new_colour)
+ set_slime_type(new_type)
. = ..()
set_nutrition(700)
- add_cell_sample()
- ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
AddElement(/datum/element/soft_landing)
+ AddElement(/datum/element/swabable, CELL_LINE_TABLE_SLIME, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5)
+ ADD_TRAIT(src, TRAIT_CANT_RIDE, INNATE_TRAIT)
+ ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
/mob/living/simple_animal/slime/Destroy()
for (var/A in actions)
@@ -170,6 +139,14 @@
clear_friends()
return ..()
+///Random slime subtype
+/mob/living/simple_animal/slime/random/Initialize(mapload, new_colour, new_is_adult)
+ . = ..(mapload, pick(subtypesof(/datum/slime_type)), prob(50))
+
+///Friendly docile subtype
+/mob/living/simple_animal/slime/pet
+ docile = TRUE
+
/mob/living/simple_animal/slime/create_reagents(max_vol, flags)
. = ..()
RegisterSignals(reagents, list(COMSIG_REAGENTS_NEW_REAGENT, COMSIG_REAGENTS_DEL_REAGENT), PROC_REF(on_reagent_change))
@@ -181,27 +158,27 @@
UnregisterSignal(reagents, list(COMSIG_REAGENTS_NEW_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_QDELETING))
return NONE
-/mob/living/simple_animal/slime/proc/set_colour(new_colour)
- colour = new_colour
+/mob/living/simple_animal/slime/proc/set_slime_type(new_type)
+ slime_type = new new_type
update_name()
- slime_mutation = mutation_table(colour)
- var/sanitizedcolour = replacetext(colour, " ", "")
- coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
regenerate_icons()
/mob/living/simple_animal/slime/update_name()
+ ///Checks if the slime has a generic name, in the format of baby/adult slime (123)
+ var/static/regex/slime_name_regex = new("\\w+ (baby|adult) slime \\(\\d+\\)")
if(slime_name_regex.Find(name))
- number = rand(1, 1000)
- name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
+ slime_id = rand(1, 1000)
+ name = "[slime_type.colour] [is_adult ? "adult" : "baby"] slime ([slime_id])"
real_name = name
return ..()
+///randomizes the colour of a slime
/mob/living/simple_animal/slime/proc/random_colour()
- set_colour(pick(slime_colours))
+ set_slime_type(pick(subtypesof(/datum/slime_type)))
/mob/living/simple_animal/slime/regenerate_icons()
cut_overlays()
- var/icon_text = "[colour] [is_adult ? "adult" : "baby"] slime"
+ var/icon_text = "[slime_type.colour] [is_adult ? "adult" : "baby"] slime"
icon_dead = "[icon_text] dead"
if(stat != DEAD)
icon_state = icon_text
@@ -267,11 +244,11 @@
probab = 95
if(prob(probab))
if(istype(O, /obj/structure/window) || istype(O, /obj/structure/grille))
- if(nutrition <= get_hunger_nutrition() && !Atkcool)
+ if(nutrition <= get_hunger_nutrition() && !is_attack_on_cooldown)
if (is_adult || prob(5))
O.attack_slime(src)
- Atkcool = TRUE
- addtimer(VARSET_CALLBACK(src, Atkcool, FALSE), 4.5 SECONDS)
+ is_attack_on_cooldown = TRUE
+ addtimer(VARSET_CALLBACK(src, is_attack_on_cooldown, FALSE), 4.5 SECONDS)
/mob/living/simple_animal/slime/Process_Spacemove(movement_dir = 0, continuous_move = FALSE)
return 2
@@ -304,51 +281,51 @@
return
powerlevel = 0 // oh no, the power!
-/mob/living/simple_animal/slime/MouseDrop(atom/movable/A as mob|obj)
- if(isliving(A) && A != src && usr == src)
- var/mob/living/Food = A
- if(CanFeedon(Food))
- Feedon(Food)
+/mob/living/simple_animal/slime/MouseDrop(atom/movable/target_atom as mob|obj)
+ if(isliving(target_atom) && target_atom != src && usr == src)
+ var/mob/living/Food = target_atom
+ if(can_feed_on(Food))
+ start_feeding(Food)
return ..()
-/mob/living/simple_animal/slime/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE, silent = FALSE)
+/mob/living/simple_animal/slime/doUnEquip(obj/item/unequipped_item, force, newloc, no_move, invdrop = TRUE, silent = FALSE)
return
-/mob/living/simple_animal/slime/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
+/mob/living/simple_animal/slime/start_pulling(atom/movable/moveable_atom, state, force = move_force, supress_message = FALSE)
return
/mob/living/simple_animal/slime/attack_ui(slot, params)
return
-/mob/living/simple_animal/slime/attack_slime(mob/living/simple_animal/slime/M, list/modifiers)
+/mob/living/simple_animal/slime/attack_slime(mob/living/simple_animal/slime/attacking_slime, list/modifiers)
if(..()) //successful slime attack
- if(M == src)
+ if(attacking_slime == src)
return
if(buckled)
- Feedstop(silent = TRUE)
- visible_message(span_danger("[M] pulls [src] off!"), \
+ stop_feeding(silent = TRUE)
+ visible_message(span_danger("[attacking_slime] pulls [src] off!"), \
span_danger("You pull [src] off!"))
return
- attacked += 5
+ attacked_stacks += 5
if(nutrition >= 100) //steal some nutrition. negval handled in life()
- adjust_nutrition(-(50 + (40 * M.is_adult)))
- M.add_nutrition(50 + (40 * M.is_adult))
+ adjust_nutrition(-(50 + (40 * attacking_slime.is_adult)))
+ attacking_slime.add_nutrition(50 + (40 * attacking_slime.is_adult))
if(health > 0)
- M.adjustBruteLoss(-10 + (-10 * M.is_adult))
- M.updatehealth()
+ attacking_slime.adjustBruteLoss(-10 + (-10 * attacking_slime.is_adult))
+ attacking_slime.updatehealth()
/mob/living/simple_animal/slime/attack_animal(mob/living/simple_animal/user, list/modifiers)
. = ..()
if(.)
- attacked += 10
+ attacked_stacks += 10
/mob/living/simple_animal/slime/attack_paw(mob/living/carbon/human/user, list/modifiers)
if(..()) //successful monkey bite.
- attacked += 10
+ attacked_stacks += 10
/mob/living/simple_animal/slime/attack_larva(mob/living/carbon/alien/larva/L, list/modifiers)
if(..()) //successful larva bite.
- attacked += 10
+ attacked_stacks += 10
/mob/living/simple_animal/slime/attack_hulk(mob/living/carbon/human/user)
. = ..()
@@ -391,92 +368,101 @@
if(operations.next_step(user, modifiers))
return TRUE
if(..()) //successful attack
- attacked += 10
+ attacked_stacks += 10
/mob/living/simple_animal/slime/attack_alien(mob/living/carbon/alien/adult/user, list/modifiers)
if(..()) //if harm or disarm intent.
- attacked += 10
+ attacked_stacks += 10
discipline_slime(user)
-/mob/living/simple_animal/slime/attackby(obj/item/W, mob/living/user, params)
+/mob/living/simple_animal/slime/attackby(obj/item/attacking_item, mob/living/user, params)
if(stat == DEAD && surgeries.len)
var/list/modifiers = params2list(params)
if(!user.combat_mode || (LAZYACCESS(modifiers, RIGHT_CLICK)))
for(var/datum/surgery/operations as anything in surgeries)
if(operations.next_step(user, modifiers))
return TRUE
- if(istype(W, /obj/item/stack/sheet/mineral/plasma) && !stat) //Let's you feed slimes plasma.
+ if(istype(attacking_item, /obj/item/stack/sheet/mineral/plasma) && !stat) //Let's you feed slimes plasma.
add_friendship(user, 1)
to_chat(user, span_notice("You feed the slime the plasma. It chirps happily."))
- var/obj/item/stack/sheet/mineral/plasma/S = W
- S.use(1)
+ var/obj/item/stack/sheet/mineral/plasma/sheet = attacking_item
+ sheet.use(1)
return
- if(W.force > 0)
- attacked += 10
+ if(attacking_item.force > 0)
+ attacked_stacks += 10
if(prob(25))
user.do_attack_animation(src)
user.changeNext_move(CLICK_CD_MELEE)
- to_chat(user, span_danger("[W] passes right through [src]!"))
+ to_chat(user, span_danger("[attacking_item] passes right through [src]!"))
return
- if(Discipline && prob(50)) // wow, buddy, why am I getting attacked??
- Discipline = 0
- if(W.force >= 3)
- var/force_effect = 2 * W.force
+ if(discipline_stacks && prob(50)) // wow, buddy, why am I getting attacked??
+ discipline_stacks = 0
+ if(attacking_item.force >= 3)
+ var/force_effect = 2 * attacking_item.force
if(is_adult)
- force_effect = round(W.force/2)
+ force_effect = round(attacking_item.force/2)
if(prob(10 + force_effect))
discipline_slime(user)
- if(istype(W, /obj/item/storage/bag/xeno))
- var/obj/item/storage/P = W
- if(!effectmod)
- to_chat(user, span_warning("The slime is not currently being mutated."))
- return
- var/hasOutput = FALSE //Have we outputted text?
- var/hasFound = FALSE //Have we found an extract to be added?
- for(var/obj/item/slime_extract/S in P.contents)
- if(S.effectmod == effectmod)
- P.atom_storage.attempt_remove(S, get_turf(src), silent = TRUE)
- qdel(S)
- applied++
- hasFound = TRUE
- if(applied >= SLIME_EXTRACT_CROSSING_REQUIRED)
- to_chat(user, span_notice("You feed the slime as many of the extracts from the bag as you can, and it mutates!"))
- playsound(src, 'sound/effects/attackblob.ogg', 50, TRUE)
- spawn_corecross()
- hasOutput = TRUE
- break
- if(!hasOutput)
- if(!hasFound)
- to_chat(user, span_warning("There are no extracts in the bag that this slime will accept!"))
- else
- to_chat(user, span_notice("You feed the slime some extracts from the bag."))
- playsound(src, 'sound/effects/attackblob.ogg', 50, TRUE)
+
+ if(!istype(attacking_item, /obj/item/storage/bag/xeno))
+ return ..()
+
+ var/obj/item/storage/xeno_bag = attacking_item
+ if(!crossbreed_modification)
+ to_chat(user, span_warning("The slime is not currently being mutated."))
return
- ..()
+ var/has_output = FALSE //Have we outputted text?
+ var/has_found = FALSE //Have we found an extract to be added?
+ for(var/obj/item/slime_extract/extract in xeno_bag.contents)
+ if(extract.crossbreed_modification == crossbreed_modification)
+ xeno_bag.atom_storage.attempt_remove(extract, get_turf(src), silent = TRUE)
+ qdel(extract)
+ applied_crossbreed_amount++
+ has_found = TRUE
+ if(applied_crossbreed_amount >= SLIME_EXTRACT_CROSSING_REQUIRED)
+ to_chat(user, span_notice("You feed the slime as many of the extracts from the bag as you can, and it mutates!"))
+ playsound(src, 'sound/effects/attackblob.ogg', 50, TRUE)
+ spawn_corecross()
+ has_output = TRUE
+ break
+
+ if(has_output)
+ return
+
+ if(!has_found)
+ to_chat(user, span_warning("There are no extracts in the bag that this slime will accept!"))
+ else
+ to_chat(user, span_notice("You feed the slime some extracts from the bag."))
+ playsound(src, 'sound/effects/attackblob.ogg', 50, TRUE)
+ return
+
+///Spawns a crossed slimecore item
/mob/living/simple_animal/slime/proc/spawn_corecross()
var/static/list/crossbreeds = subtypesof(/obj/item/slimecross)
visible_message(span_danger("[src] shudders, its mutated core consuming the rest of its body!"))
playsound(src, 'sound/magic/smoke.ogg', 50, TRUE)
- var/crosspath
- for(var/X in crossbreeds)
- var/obj/item/slimecross/S = X
- if(initial(S.colour) == colour && initial(S.effect) == effectmod)
- crosspath = S
+ var/selected_crossbreed_path
+ for(var/crossbreed_path in crossbreeds)
+ var/obj/item/slimecross/cross_item = crossbreed_path
+ if(initial(cross_item.colour) == slime_type.colour && initial(cross_item.effect) == crossbreed_modification)
+ selected_crossbreed_path = cross_item
break
- if(crosspath)
- new crosspath(loc)
+ if(selected_crossbreed_path)
+ new selected_crossbreed_path(loc)
else
visible_message(span_warning("The mutated core shudders, and collapses into a puddle, unable to maintain its form."))
qdel(src)
/mob/living/simple_animal/slime/proc/apply_water()
adjustBruteLoss(rand(15,20))
- if(!client)
- if(Target) // Like cats
- set_target(null)
- ++Discipline
+ if(client)
+ return
+
+ if(Target) // Like cats
+ set_target(null)
+ ++discipline_stacks
return
/mob/living/simple_animal/slime/examine(mob/user)
@@ -509,22 +495,22 @@
. += ""
+///Makes a slime not attack people for a while
/mob/living/simple_animal/slime/proc/discipline_slime(mob/user)
if(stat)
return
if(prob(80) && !client)
- Discipline++
+ discipline_stacks++
- if(!is_adult)
- if(Discipline == 1)
- attacked = 0
+ if(!is_adult && discipline_stacks == 1) //if the slime is a baby and has not been overly disciplined, it will give up its grudge
+ attacked_stacks = 0
set_target(null)
if(buckled)
- Feedstop(silent = TRUE) //we unbuckle the slime from the mob it latched onto.
+ stop_feeding(silent = TRUE) //we unbuckle the slime from the mob it latched onto.
- SStun = world.time + rand(20,60)
+ stunned_until = world.time + rand(2 SECONDS, 6 SECONDS)
Stun(3)
if(user)
@@ -532,25 +518,16 @@
addtimer(CALLBACK(src, PROC_REF(slime_move), user), 0.3 SECONDS)
-
+///Makes a slime move away, used for a timed callback
/mob/living/simple_animal/slime/proc/slime_move(mob/user)
if(user)
step_away(src,user,15)
-
-/mob/living/simple_animal/slime/pet
- docile = 1
-
/mob/living/simple_animal/slime/get_mob_buckling_height(mob/seat)
if(..())
return 3
-/mob/living/simple_animal/slime/random/Initialize(mapload, new_colour, new_is_adult)
- . = ..(mapload, pick(slime_colours), prob(50))
-
-/mob/living/simple_animal/slime/add_cell_sample()
- AddElement(/datum/element/swabable, CELL_LINE_TABLE_SLIME, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5)
-
+///Sets the slime's current attack target
/mob/living/simple_animal/slime/proc/set_target(new_target)
var/old_target = Target
Target = new_target
@@ -559,6 +536,7 @@
if(Target)
RegisterSignal(Target, COMSIG_QDELETING, PROC_REF(clear_memories_of), override = TRUE)
+///Sets the person the slime is following around
/mob/living/simple_animal/slime/proc/set_leader(new_leader)
var/old_leader = Leader
Leader = new_leader
@@ -567,6 +545,7 @@
if(Leader)
RegisterSignal(Leader, COMSIG_QDELETING, PROC_REF(clear_memories_of), override = TRUE)
+///Alters the friendship value of the target
/mob/living/simple_animal/slime/proc/add_friendship(new_friend, amount = 1)
if(!Friends[new_friend])
Friends[new_friend] = 0
@@ -574,25 +553,30 @@
if(new_friend)
RegisterSignal(new_friend, COMSIG_QDELETING, PROC_REF(clear_memories_of), override = TRUE)
+///Sets the friendship value of the target
/mob/living/simple_animal/slime/proc/set_friendship(new_friend, amount = 1)
Friends[new_friend] = amount
if(new_friend)
RegisterSignal(new_friend, COMSIG_QDELETING, PROC_REF(clear_memories_of), override = TRUE)
+///Removes someone from the friendlist
/mob/living/simple_animal/slime/proc/remove_friend(friend)
Friends -= friend
if(friend && !SLIME_CARES_ABOUT(friend))
UnregisterSignal(friend, COMSIG_QDELETING)
+///Adds someone to the friend list
/mob/living/simple_animal/slime/proc/set_friends(new_buds)
clear_friends()
for(var/mob/friend as anything in new_buds)
set_friendship(friend, new_buds[friend])
+///Removes everyone from the friend list
/mob/living/simple_animal/slime/proc/clear_friends()
for(var/mob/friend as anything in Friends)
remove_friend(friend)
+///The passed source will be no longer be the slime's target, leader, or one of its friends
/mob/living/simple_animal/slime/proc/clear_memories_of(datum/source)
SIGNAL_HANDLER
if(source == Target)
diff --git a/code/modules/mob/living/simple_animal/slime/slime_type.dm b/code/modules/mob/living/simple_animal/slime/slime_type.dm
new file mode 100644
index 00000000000..11f37988040
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/slime/slime_type.dm
@@ -0,0 +1,224 @@
+/datum/slime_type
+ ///Our slime's colour as text. Used by both description, and icon
+ var/colour
+ ///The type our slime spawns
+ var/core_type
+ ///The possible mutations of our slime
+ var/list/mutations
+ ///The hexcode used by the slime to colour their victims
+ var/rgb_code
+
+//TIER 0
+
+/datum/slime_type/grey
+ colour = SLIME_TYPE_GREY
+ core_type = /obj/item/slime_extract/grey
+ mutations = list(
+ /datum/slime_type/blue = 1,
+ /datum/slime_type/metal = 1,
+ /datum/slime_type/orange = 1,
+ /datum/slime_type/purple = 1,
+ )
+ rgb_code = COLOR_SLIME_GREY
+
+
+//TIER 1
+
+/datum/slime_type/blue
+ colour = SLIME_TYPE_BLUE
+ core_type = /obj/item/slime_extract/blue
+ mutations = list(
+ /datum/slime_type/darkblue = 1,
+ /datum/slime_type/pink = 2,
+ /datum/slime_type/silver = 1,
+ )
+ rgb_code = COLOR_SLIME_BLUE
+
+/datum/slime_type/metal
+ colour = SLIME_TYPE_METAL
+ core_type = /obj/item/slime_extract/metal
+ mutations = list(
+ /datum/slime_type/gold = 2,
+ /datum/slime_type/silver = 1,
+ /datum/slime_type/yellow = 1,
+ )
+ rgb_code = COLOR_SLIME_METAL
+
+/datum/slime_type/purple
+ colour = SLIME_TYPE_PURPLE
+ core_type = /obj/item/slime_extract/purple
+ mutations = list(
+ /datum/slime_type/darkblue = 1,
+ /datum/slime_type/darkpurple = 1,
+ /datum/slime_type/green = 2,
+ )
+ rgb_code = COLOR_SLIME_PURPLE
+
+/datum/slime_type/orange
+ colour = SLIME_TYPE_ORANGE
+ core_type = /obj/item/slime_extract/orange
+ mutations = list(
+ /datum/slime_type/darkpurple = 1,
+ /datum/slime_type/red = 2,
+ /datum/slime_type/yellow = 1,
+ )
+ rgb_code = COLOR_SLIME_ORANGE
+
+//TIER 2
+
+/datum/slime_type/darkblue
+ colour = SLIME_TYPE_DARK_BLUE
+ core_type = /obj/item/slime_extract/darkblue
+ mutations = list(
+ /datum/slime_type/blue = 1,
+ /datum/slime_type/cerulean = 2,
+ /datum/slime_type/purple = 1,
+ )
+ rgb_code = COLOR_SLIME_BLUE
+
+/datum/slime_type/darkpurple
+ colour = SLIME_TYPE_DARK_PURPLE
+ core_type = /obj/item/slime_extract/darkpurple
+ mutations = list(
+ /datum/slime_type/orange = 1,
+ /datum/slime_type/purple = 1,
+ /datum/slime_type/sepia = 2,
+ )
+ rgb_code = COLOR_SLIME_PURPLE
+
+/datum/slime_type/silver
+ colour = SLIME_TYPE_SILVER
+ core_type = /obj/item/slime_extract/silver
+ mutations = list(
+ /datum/slime_type/blue = 1,
+ /datum/slime_type/metal = 1,
+ /datum/slime_type/pyrite = 2,
+ )
+ rgb_code = COLOR_SLIME_SILVER
+
+/datum/slime_type/yellow
+ colour = SLIME_TYPE_YELLOW
+ core_type = /obj/item/slime_extract/yellow
+ mutations = list(
+ /datum/slime_type/bluespace = 2,
+ /datum/slime_type/metal = 1,
+ /datum/slime_type/orange = 1,
+ )
+ rgb_code = COLOR_SLIME_YELLOW
+
+//TIER 3
+
+/datum/slime_type/bluespace
+ colour = SLIME_TYPE_BLUESPACE
+ core_type = /obj/item/slime_extract/bluespace
+ mutations = list(
+ /datum/slime_type/bluespace = 1,
+ )
+ rgb_code = COLOR_SLIME_BLUESPACE
+
+
+/datum/slime_type/cerulean
+ colour = SLIME_TYPE_CERULEAN
+ core_type = /obj/item/slime_extract/cerulean
+ mutations = list(
+ /datum/slime_type/cerulean = 1,
+ )
+ rgb_code = COLOR_SLIME_CERULEAN
+
+/datum/slime_type/pyrite
+ colour = SLIME_TYPE_PYRITE
+ core_type = /obj/item/slime_extract/pyrite
+ mutations = list(
+ /datum/slime_type/pyrite = 1,
+ )
+ rgb_code = COLOR_SLIME_PYRITE
+
+/datum/slime_type/sepia
+ colour = SLIME_TYPE_SEPIA
+ core_type = /obj/item/slime_extract/sepia
+ mutations = list(
+ /datum/slime_type/sepia = 1,
+ )
+ rgb_code = COLOR_SLIME_SEPIA
+
+//TIER 4
+
+/datum/slime_type/gold
+ colour = SLIME_TYPE_GOLD
+ core_type = /obj/item/slime_extract/gold
+ mutations = list(
+ /datum/slime_type/adamantine = 1,
+ /datum/slime_type/gold = 1,
+ )
+ rgb_code = COLOR_SLIME_GOLD
+
+/datum/slime_type/green
+ colour = SLIME_TYPE_GREEN
+ core_type = /obj/item/slime_extract/green
+ mutations = list(
+ /datum/slime_type/black = 1,
+ /datum/slime_type/green = 1,
+ )
+ rgb_code = COLOR_SLIME_GREEN
+
+/datum/slime_type/pink
+ colour = SLIME_TYPE_PINK
+ core_type = /obj/item/slime_extract/pink
+ mutations = list(
+ /datum/slime_type/lightpink = 1,
+ /datum/slime_type/pink = 1,
+ )
+ rgb_code = COLOR_SLIME_PINK
+
+/datum/slime_type/red
+ colour = SLIME_TYPE_RED
+ core_type = /obj/item/slime_extract/red
+ mutations = list(
+ /datum/slime_type/oil = 1,
+ /datum/slime_type/red = 1,
+ )
+ rgb_code = COLOR_SLIME_RED
+
+//TIER 5
+
+/datum/slime_type/adamantine
+ colour = SLIME_TYPE_ADAMANTINE
+ core_type = /obj/item/slime_extract/adamantine
+ mutations = list(
+ /datum/slime_type/adamantine = 1,
+ )
+ rgb_code = COLOR_SLIME_ADAMANTINE
+
+/datum/slime_type/black
+ colour = SLIME_TYPE_BLACK
+ core_type = /obj/item/slime_extract/black
+ mutations = list(
+ /datum/slime_type/black = 1,
+ )
+ rgb_code = COLOR_SLIME_BLACK
+
+/datum/slime_type/lightpink
+ colour = SLIME_TYPE_LIGHT_PINK
+ core_type = /obj/item/slime_extract/lightpink
+ mutations = list(
+ /datum/slime_type/lightpink = 1,
+ )
+ rgb_code = COLOR_SLIME_LIGHT_PINK
+
+/datum/slime_type/oil
+ colour = SLIME_TYPE_OIL
+ core_type = /obj/item/slime_extract/oil
+ mutations = list(
+ /datum/slime_type/oil = 1,
+ )
+ rgb_code = COLOR_SLIME_OIL
+
+//Tier Special
+
+/datum/slime_type/rainbow
+ colour = SLIME_TYPE_RAINBOW
+ core_type = /obj/item/slime_extract/rainbow
+ mutations = list(
+ /datum/slime_type/rainbow = 1,
+ )
+ rgb_code = COLOR_SLIME_RAINBOW
diff --git a/code/modules/mob/living/simple_animal/slime/subtypes.dm b/code/modules/mob/living/simple_animal/slime/subtypes.dm
deleted file mode 100644
index e948de7cd4d..00000000000
--- a/code/modules/mob/living/simple_animal/slime/subtypes.dm
+++ /dev/null
@@ -1,79 +0,0 @@
-/mob/living/simple_animal/slime/proc/mutation_table(colour)
- var/list/slime_mutation_colors[4]
- switch(colour)
- //Tier 1
- if(SLIME_TYPE_GREY)
- slime_mutation_colors[1] = SLIME_TYPE_ORANGE
- slime_mutation_colors[2] = SLIME_TYPE_METAL
- slime_mutation_colors[3] = SLIME_TYPE_BLUE
- slime_mutation_colors[4] = SLIME_TYPE_PURPLE
- //Tier 2
- if(SLIME_TYPE_PURPLE)
- slime_mutation_colors[1] = SLIME_TYPE_DARK_PURPLE
- slime_mutation_colors[2] = SLIME_TYPE_DARK_BLUE
- slime_mutation_colors[3] = SLIME_TYPE_GREEN
- slime_mutation_colors[4] = SLIME_TYPE_GREEN
- if(SLIME_TYPE_METAL)
- slime_mutation_colors[1] = SLIME_TYPE_SILVER
- slime_mutation_colors[2] = SLIME_TYPE_YELLOW
- slime_mutation_colors[3] = SLIME_TYPE_GOLD
- slime_mutation_colors[4] = SLIME_TYPE_GOLD
- if(SLIME_TYPE_ORANGE)
- slime_mutation_colors[1] = SLIME_TYPE_DARK_PURPLE
- slime_mutation_colors[2] = SLIME_TYPE_YELLOW
- slime_mutation_colors[3] = SLIME_TYPE_RED
- slime_mutation_colors[4] = SLIME_TYPE_RED
- if(SLIME_TYPE_BLUE)
- slime_mutation_colors[1] = SLIME_TYPE_DARK_BLUE
- slime_mutation_colors[2] = SLIME_TYPE_SILVER
- slime_mutation_colors[3] = SLIME_TYPE_PINK
- slime_mutation_colors[4] = SLIME_TYPE_PINK
- //Tier 3
- if(SLIME_TYPE_DARK_BLUE)
- slime_mutation_colors[1] = SLIME_TYPE_PURPLE
- slime_mutation_colors[2] = SLIME_TYPE_BLUE
- slime_mutation_colors[3] = SLIME_TYPE_CERULEAN
- slime_mutation_colors[4] = SLIME_TYPE_CERULEAN
- if(SLIME_TYPE_DARK_PURPLE)
- slime_mutation_colors[1] = SLIME_TYPE_PURPLE
- slime_mutation_colors[2] = SLIME_TYPE_ORANGE
- slime_mutation_colors[3] = SLIME_TYPE_SEPIA
- slime_mutation_colors[4] = SLIME_TYPE_SEPIA
- if(SLIME_TYPE_YELLOW)
- slime_mutation_colors[1] = SLIME_TYPE_METAL
- slime_mutation_colors[2] = SLIME_TYPE_ORANGE
- slime_mutation_colors[3] = SLIME_TYPE_BLUESPACE
- slime_mutation_colors[4] = SLIME_TYPE_BLUESPACE
- if(SLIME_TYPE_SILVER)
- slime_mutation_colors[1] = SLIME_TYPE_METAL
- slime_mutation_colors[2] = SLIME_TYPE_BLUE
- slime_mutation_colors[3] = SLIME_TYPE_PYRITE
- slime_mutation_colors[4] = SLIME_TYPE_PYRITE
- //Tier 4
- if(SLIME_TYPE_PINK)
- slime_mutation_colors[1] = SLIME_TYPE_PINK
- slime_mutation_colors[2] = SLIME_TYPE_PINK
- slime_mutation_colors[3] = SLIME_TYPE_LIGHT_PINK
- slime_mutation_colors[4] = SLIME_TYPE_LIGHT_PINK
- if(SLIME_TYPE_RED)
- slime_mutation_colors[1] = SLIME_TYPE_RED
- slime_mutation_colors[2] = SLIME_TYPE_RED
- slime_mutation_colors[3] = SLIME_TYPE_OIL
- slime_mutation_colors[4] = SLIME_TYPE_OIL
- if(SLIME_TYPE_GOLD)
- slime_mutation_colors[1] = SLIME_TYPE_GOLD
- slime_mutation_colors[2] = SLIME_TYPE_GOLD
- slime_mutation_colors[3] = SLIME_TYPE_ADAMANTINE
- slime_mutation_colors[4] = SLIME_TYPE_ADAMANTINE
- if(SLIME_TYPE_GREEN)
- slime_mutation_colors[1] = SLIME_TYPE_GREEN
- slime_mutation_colors[2] = SLIME_TYPE_GREEN
- slime_mutation_colors[3] = SLIME_TYPE_BLACK
- slime_mutation_colors[4] = SLIME_TYPE_BLACK
- // Tier 5
- else
- slime_mutation_colors[1] = colour
- slime_mutation_colors[2] = colour
- slime_mutation_colors[3] = colour
- slime_mutation_colors[4] = colour
- return(slime_mutation_colors)
diff --git a/code/modules/mob_spawn/corpses/nonhuman_corpses.dm b/code/modules/mob_spawn/corpses/nonhuman_corpses.dm
index ce02c6894ae..3a63a246035 100644
--- a/code/modules/mob_spawn/corpses/nonhuman_corpses.dm
+++ b/code/modules/mob_spawn/corpses/nonhuman_corpses.dm
@@ -22,11 +22,11 @@
icon = 'icons/mob/simple/slimes.dmi'
icon_state = "grey baby slime" //sets the icon in the map editor
///the color of the slime you're spawning.
- var/slime_species = "grey"
+ var/slime_species = /datum/slime_type/grey
/obj/effect/mob_spawn/corpse/slime/special(mob/living/simple_animal/slime/spawned_slime)
. = ..()
- spawned_slime.set_colour(slime_species)
+ spawned_slime.set_slime_type(slime_species)
///dead facehuggers, great for xeno ruins so you can have a cool ruin without spiraling the entire round into xenomorph hell. also, this is a terrible terrible artifact of time
/obj/effect/mob_spawn/corpse/facehugger
diff --git a/code/modules/reagents/chemistry/holder/reactions.dm b/code/modules/reagents/chemistry/holder/reactions.dm
index 503b1b87bd6..3aff4db3d5b 100644
--- a/code/modules/reagents/chemistry/holder/reactions.dm
+++ b/code/modules/reagents/chemistry/holder/reactions.dm
@@ -342,8 +342,8 @@
if(istype(cached_my_atom, /obj/item/slime_extract))
var/obj/item/slime_extract/extract = my_atom
- extract.Uses--
- if(extract.Uses <= 0) // give the notification that the slime core is dead
+ extract.extract_uses--
+ if(extract.extract_uses <= 0) // give the notification that the slime core is dead
my_atom.visible_message(span_notice("[iconhtml] \The [my_atom]'s power is consumed in the reaction."))
extract.name = "used slime extract"
extract.desc = "This extract has been used up."
diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm
index 6b5ddfc14e3..f37f9ebb081 100644
--- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm
+++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm
@@ -10,7 +10,7 @@
if(!istype(extract))
return FALSE
- return extract.Uses > 0
+ return extract.extract_uses > 0
/datum/chemical_reaction/slime/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume)
use_slime_core(holder)
@@ -22,7 +22,7 @@
/datum/chemical_reaction/slime/proc/delete_extract(datum/reagents/holder)
var/obj/item/slime_extract/M = holder.my_atom
- if(M.Uses <= 0 && !results.len) //if the slime doesn't output chemicals
+ if(M.extract_uses <= 0 && !results.len) //if the slime doesn't output chemicals
qdel(M)
//Grey
@@ -31,8 +31,8 @@
required_container = /obj/item/slime_extract/grey
/datum/chemical_reaction/slime/slimespawn/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume)
- var/mob/living/simple_animal/slime/S = new(get_turf(holder.my_atom), "grey")
- S.visible_message(span_danger("Infused with plasma, the core begins to quiver and grow, and a new baby slime emerges from it!"))
+ var/mob/living/simple_animal/slime/spawning_slime = new(get_turf(holder.my_atom), /datum/slime_type/grey)
+ spawning_slime.visible_message(span_danger("Infused with plasma, the core begins to quiver and grow, and a new baby slime emerges from it!"))
..()
/datum/chemical_reaction/slime/slimeinaprov
@@ -319,7 +319,7 @@
slime.docile = FALSE
slime.update_name()
continue
- slime.rabid = 1
+ slime.rabid = TRUE
slime.visible_message(span_danger("The [slime] is driven into a frenzy!"))
..()
@@ -472,7 +472,7 @@
var/turf/T = get_turf(holder.my_atom)
new /obj/effect/timestop(T, null, null, null)
if(istype(extract))
- if(extract.Uses > 0)
+ if(extract.extract_uses > 0)
var/mob/lastheld = get_mob_by_key(holder.my_atom.fingerprintslast)
if(lastheld && !lastheld.equip_to_slot_if_possible(extract, ITEM_SLOT_HANDS, disable_warning = TRUE))
extract.forceMove(get_turf(lastheld))
@@ -527,8 +527,8 @@
S.active = TRUE
addtimer(CALLBACK(S, TYPE_PROC_REF(/obj/item/grenade, detonate)), rand(15,60))
else
- var/mob/living/simple_animal/slime/random/S = new (get_turf(holder.my_atom))
- S.visible_message(span_danger("Infused with plasma, the core begins to quiver and grow, and a new baby slime emerges from it!"))
+ var/mob/living/simple_animal/slime/random/random_slime = new (get_turf(holder.my_atom))
+ random_slime.visible_message(span_danger("Infused with plasma, the core begins to quiver and grow, and a new baby slime emerges from it!"))
..()
/datum/chemical_reaction/slime/slimebomb
diff --git a/code/modules/research/xenobiology/crossbreeding/_potions.dm b/code/modules/research/xenobiology/crossbreeding/_potions.dm
index 0b5368f5372..7fb7f10849d 100644
--- a/code/modules/research/xenobiology/crossbreeding/_potions.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_potions.dm
@@ -28,7 +28,7 @@ Slimecrossing Potions
return
var/path = S.type
var/obj/item/slime_extract/C = new path(get_turf(target))
- C.Uses = S.Uses
+ C.extract_uses = S.extract_uses
to_chat(user, span_notice("You pour the potion onto [target], and the fluid solidifies into a copy of it!"))
qdel(src)
return
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index 04d37c62b7c..5669aab44f2 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -473,10 +473,10 @@
colour = SLIME_TYPE_GREY
/datum/status_effect/stabilized/grey/tick(seconds_between_ticks)
- for(var/mob/living/simple_animal/slime/S in range(1, get_turf(owner)))
- if(!(owner in S.Friends))
- to_chat(owner, span_notice("[linked_extract] pulses gently as it communicates with [S]."))
- S.set_friendship(owner, 1)
+ for(var/mob/living/simple_animal/slime/slimes_in_range in range(1, get_turf(owner)))
+ if(!(owner in slimes_in_range.Friends))
+ to_chat(owner, span_notice("[linked_extract] pulses gently as it communicates with [slimes_in_range]."))
+ slimes_in_range.set_friendship(owner, 1)
return ..()
/datum/status_effect/stabilized/orange
diff --git a/code/modules/research/xenobiology/crossbreeding/burning.dm b/code/modules/research/xenobiology/crossbreeding/burning.dm
index 7c27399b03e..8d849c36569 100644
--- a/code/modules/research/xenobiology/crossbreeding/burning.dm
+++ b/code/modules/research/xenobiology/crossbreeding/burning.dm
@@ -32,11 +32,11 @@ Burning extracts:
effect_desc = "Creates a hungry and speedy slime that will love you forever."
/obj/item/slimecross/burning/grey/do_effect(mob/user)
- var/mob/living/simple_animal/slime/S = new(get_turf(user),SLIME_TYPE_GREY)
- S.visible_message(span_danger("A baby slime emerges from [src], and it nuzzles [user] before burbling hungrily!"))
- S.set_friendship(user, 20) //Gas, gas, gas
- S.bodytemperature = T0C + 400 //We gonna step on the gas.
- S.set_nutrition(S.get_hunger_nutrition()) //Tonight, we fight!
+ var/mob/living/simple_animal/slime/new_slime = new(get_turf(user),/datum/slime_type/grey)
+ new_slime.visible_message(span_danger("A baby slime emerges from [src], and it nuzzles [user] before burbling hungrily!"))
+ new_slime.set_friendship(user, 20) //Gas, gas, gas
+ new_slime.bodytemperature = T0C + 400 //We gonna step on the gas.
+ new_slime.set_nutrition(new_slime.get_hunger_nutrition()) //Tonight, we fight!
..()
/obj/item/slimecross/burning/orange
@@ -197,15 +197,15 @@ Burning extracts:
/obj/item/slimecross/burning/red/do_effect(mob/user)
user.visible_message(span_danger("[src] pulses a hazy red aura for a moment, which wraps around [user]!"))
- for(var/mob/living/simple_animal/slime/S in view(7, get_turf(user)))
- if(user in S.Friends)
- var/friendliness = S.Friends[user]
- S.clear_friends()
- S.set_friendship(user, friendliness)
+ for(var/mob/living/simple_animal/slime/slimes_in_view in view(7, get_turf(user)))
+ if(user in slimes_in_view.Friends)
+ var/friendliness = slimes_in_view.Friends[user]
+ slimes_in_view.clear_friends()
+ slimes_in_view.set_friendship(user, friendliness)
else
- S.clear_friends()
- S.rabid = 1
- S.visible_message(span_danger("The [S] is driven into a dangerous frenzy!"))
+ slimes_in_view.clear_friends()
+ slimes_in_view.rabid = TRUE
+ slimes_in_view.visible_message(span_danger("The [slimes_in_view] is driven into a dangerous frenzy!"))
..()
/obj/item/slimecross/burning/green
diff --git a/code/modules/research/xenobiology/crossbreeding/charged.dm b/code/modules/research/xenobiology/crossbreeding/charged.dm
index 586a33d2dff..cde5e234afd 100644
--- a/code/modules/research/xenobiology/crossbreeding/charged.dm
+++ b/code/modules/research/xenobiology/crossbreeding/charged.dm
@@ -278,6 +278,6 @@ Charged extracts:
/obj/item/slimecross/charged/rainbow/do_effect(mob/user)
user.visible_message(span_warning("[src] swells and splits into three new slimes!"))
for(var/i in 1 to 3)
- var/mob/living/simple_animal/slime/S = new(get_turf(user))
- S.random_colour()
+ var/mob/living/simple_animal/slime/new_slime = new(get_turf(user))
+ new_slime.random_colour()
return ..()
diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm
index 65c7199a7f0..84b184bf892 100644
--- a/code/modules/research/xenobiology/crossbreeding/chilling.dm
+++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm
@@ -231,9 +231,9 @@ Chilling extracts:
/obj/item/slimecross/chilling/red/do_effect(mob/user)
var/slimesfound = FALSE
- for(var/mob/living/simple_animal/slime/S in view(get_turf(user), 7))
+ for(var/mob/living/simple_animal/slime/slimes_in_view in view(get_turf(user), 7))
slimesfound = TRUE
- S.docile = TRUE
+ slimes_in_view.docile = TRUE
if(slimesfound)
user.visible_message(span_notice("[src] lets out a peaceful ring as it shatters, and nearby slimes seem calm."))
else
diff --git a/code/modules/research/xenobiology/crossbreeding/recurring.dm b/code/modules/research/xenobiology/crossbreeding/recurring.dm
index c6ca420cc04..3279e26c920 100644
--- a/code/modules/research/xenobiology/crossbreeding/recurring.dm
+++ b/code/modules/research/xenobiology/crossbreeding/recurring.dm
@@ -29,10 +29,10 @@ Recurring extracts:
/obj/item/slimecross/recurring/process(seconds_per_tick)
if(cooldown > 0)
cooldown -= seconds_per_tick
- else if(extract.Uses < 10 && extract.Uses > 0)
- extract.Uses++
+ else if(extract.extract_uses < 10 && extract.extract_uses > 0)
+ extract.extract_uses++
cooldown = max_cooldown
- else if(extract.Uses <= 0)
+ else if(extract.extract_uses <= 0)
extract.visible_message(span_warning("The light inside [extract] flickers and dies out."))
extract.desc = "A tiny, inert core, bleeding dark, cerulean-colored goo."
extract.icon_state = "prismatic"
diff --git a/code/modules/research/xenobiology/crossbreeding/regenerative.dm b/code/modules/research/xenobiology/crossbreeding/regenerative.dm
index f0f395b33a6..4a222e8e982 100644
--- a/code/modules/research/xenobiology/crossbreeding/regenerative.dm
+++ b/code/modules/research/xenobiology/crossbreeding/regenerative.dm
@@ -197,8 +197,8 @@ Regenerative extracts:
/obj/item/slimecross/regenerative/green/core_effect(mob/living/target, mob/user)
if(isslime(target))
target.visible_message(span_warning("The [target] suddenly changes color!"))
- var/mob/living/simple_animal/slime/S = target
- S.random_colour()
+ var/mob/living/simple_animal/slime/target_slime = target
+ target_slime.random_colour()
if(isjellyperson(target))
target.reagents.add_reagent(/datum/reagent/mutationtoxin/jelly,5)
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index ac148161b03..97e78121908 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -6,16 +6,15 @@
var/allowed_area = null
/mob/camera/ai_eye/remote/xenobio/Initialize(mapload)
- var/area/A = get_area(loc)
- allowed_area = A.name
+ var/area/our_area = get_area(loc)
+ allowed_area = our_area.name
. = ..()
/mob/camera/ai_eye/remote/xenobio/setLoc(turf/destination, force_update = FALSE)
var/area/new_area = get_area(destination)
+
if(new_area && new_area.name == allowed_area || new_area && (new_area.area_flags & XENOBIOLOGY_COMPATIBLE))
return ..()
- else
- return
/mob/camera/ai_eye/remote/xenobio/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider)
. = ..()
@@ -31,10 +30,15 @@
networks = list("ss13")
circuit = /obj/item/circuitboard/computer/xenobiology
+ ///The recycler connected to the camera console
var/obj/machinery/monkey_recycler/connected_recycler
+ ///The slimes stored inside the console
var/list/stored_slimes
+ ///The single slime potion stored inside the console
var/obj/item/slimepotion/slime/current_potion
+ ///The maximum amount of slimes that fit in the machine
var/max_slimes = 5
+ ///The amount of monkey cubes inside the machine
var/monkeys = 0
icon_screen = "slime_comp"
@@ -53,6 +57,9 @@
actions += new /datum/action/innate/hotkey_help(src)
stored_slimes = list()
+
+/obj/machinery/computer/camera_advanced/xenobio/LateInitialize(mapload)
+ . = ..()
for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers)
if(get_area(recycler.loc) == get_area(loc))
connected_recycler = recycler
@@ -61,8 +68,8 @@
/obj/machinery/computer/camera_advanced/xenobio/Destroy()
QDEL_NULL(current_potion)
for(var/thing in stored_slimes)
- var/mob/living/simple_animal/slime/S = thing
- S.forceMove(drop_location())
+ var/mob/living/simple_animal/slime/stored_slime = thing
+ stored_slime.forceMove(drop_location())
stored_slimes.Cut()
if(connected_recycler)
connected_recycler.connected -= src
@@ -92,13 +99,6 @@
RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_SHIFT, PROC_REF(XenoSlimeClickShift))
RegisterSignal(user, COMSIG_XENO_TURF_CLICK_SHIFT, PROC_REF(XenoTurfClickShift))
- //Checks for recycler on every interact, prevents issues with load order on certain maps.
- if(!connected_recycler)
- for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers)
- if(get_area(recycler.loc) == get_area(loc))
- connected_recycler = recycler
- connected_recycler.connected += src
-
/obj/machinery/computer/camera_advanced/xenobio/remove_eye_control(mob/living/user)
UnregisterSignal(user, COMSIG_XENO_SLIME_CLICK_CTRL)
UnregisterSignal(user, COMSIG_XENO_TURF_CLICK_CTRL)
@@ -108,43 +108,116 @@
UnregisterSignal(user, COMSIG_XENO_TURF_CLICK_SHIFT)
..()
-/obj/machinery/computer/camera_advanced/xenobio/attackby(obj/item/O, mob/user, params)
- if(istype(O, /obj/item/food/monkeycube))
+/obj/machinery/computer/camera_advanced/xenobio/attackby(obj/item/used_item, mob/user, params)
+ if(istype(used_item, /obj/item/food/monkeycube))
monkeys++
- to_chat(user, span_notice("You feed [O] to [src]. It now has [monkeys] monkey cubes stored."))
- qdel(O)
+ to_chat(user, span_notice("You feed [used_item] to [src]. It now has [monkeys] monkey cubes stored."))
+ qdel(used_item)
return
- else if(istype(O, /obj/item/storage/bag))
- var/obj/item/storage/P = O
+
+ if(istype(used_item, /obj/item/storage/bag))
+ var/obj/item/storage/storage_bag = used_item
var/loaded = FALSE
- for(var/obj/G in P.contents)
- if(istype(G, /obj/item/food/monkeycube))
+ for(var/obj/item_in_bag in storage_bag.contents)
+ if(istype(item_in_bag, /obj/item/food/monkeycube))
loaded = TRUE
monkeys++
- qdel(G)
+ qdel(item_in_bag)
if(loaded)
- to_chat(user, span_notice("You fill [src] with the monkey cubes stored in [O]. [src] now has [monkeys] monkey cubes stored."))
+ to_chat(user, span_notice("You fill [src] with the monkey cubes stored in [used_item]. [src] now has [monkeys] monkey cubes stored."))
return
- else if(istype(O, /obj/item/slimepotion/slime))
+
+ if(istype(used_item, /obj/item/slimepotion/slime))
var/replaced = FALSE
- if(user && !user.transferItemToLoc(O, src))
+ if(user && !user.transferItemToLoc(used_item, src))
return
if(!QDELETED(current_potion))
current_potion.forceMove(drop_location())
replaced = TRUE
- current_potion = O
- to_chat(user, span_notice("You load [O] in the console's potion slot[replaced ? ", replacing the one that was there before" : ""]."))
+ current_potion = used_item
+ to_chat(user, span_notice("You load [used_item] in the console's potion slot[replaced ? ", replacing the one that was there before" : ""]."))
return
+
..()
-/obj/machinery/computer/camera_advanced/xenobio/multitool_act(mob/living/user, obj/item/multitool/I)
+/obj/machinery/computer/camera_advanced/xenobio/multitool_act(mob/living/user, obj/item/multitool/used_multitool)
. = ..()
- if (istype(I) && istype(I.buffer,/obj/machinery/monkey_recycler))
- to_chat(user, span_notice("You link [src] with [I.buffer] in [I] buffer."))
- connected_recycler = I.buffer
+ if (istype(used_multitool) && istype(used_multitool.buffer,/obj/machinery/monkey_recycler))
+ to_chat(user, span_notice("You link [src] with [used_multitool.buffer] in [used_multitool] buffer."))
+ connected_recycler = used_multitool.buffer
connected_recycler.connected += src
return TRUE
+/*
+Boilerplate check for a valid area to perform a camera action in.
+Checks if the AI eye is on a valid turf and then checks if the target turf is xenobiology compatible
+Due to keyboard shortcuts, the second one is not necessarily the remote eye's location.
+*/
+/obj/machinery/computer/camera_advanced/xenobio/proc/validate_area(mob/living/user, mob/camera/ai_eye/remote/xenobio/remote_eye, turf/open/target_turf)
+ if(!GLOB.cameranet.checkTurfVis(remote_eye.loc))
+ to_chat(user, span_warning("Target is not near a camera. Cannot proceed."))
+ return FALSE
+
+ var/area/turfarea = get_area(target_turf)
+ if(turfarea.name != remote_eye.allowed_area && !(turfarea.area_flags & XENOBIOLOGY_COMPATIBLE))
+ to_chat(user, span_warning("Invalid area. Cannot proceed."))
+ return FALSE
+
+ return TRUE
+
+///Places every slime in storage on target turf
+/obj/machinery/computer/camera_advanced/xenobio/proc/slime_place(turf/open/target_turf)
+ for(var/mob/living/simple_animal/slime/stored_slime in stored_slimes)
+ stored_slime.forceMove(target_turf)
+ stored_slime.visible_message(span_notice("[stored_slime] warps in!"))
+ stored_slimes -= stored_slime
+
+///Places every slime not controlled by a player into the internal storage, respecting its limits
+///Returns TRUE to signal it hitting the limit, in case its being called from a loop and we want it to stop
+/obj/machinery/computer/camera_advanced/xenobio/proc/slime_pickup(mob/living/user, mob/living/simple_animal/slime/target_slime)
+ if(stored_slimes.len >= max_slimes)
+ to_chat(user, span_warning("Slime storage is full."))
+ return TRUE
+ if(target_slime.ckey)
+ to_chat(user, span_warning("The slime wiggled free!"))
+ return FALSE
+ if(target_slime.buckled)
+ target_slime.stop_feeding(silent = TRUE)
+ target_slime.visible_message(span_notice("[target_slime] vanishes in a flash of light!"))
+ target_slime.forceMove(src)
+ stored_slimes += target_slime
+
+ return FALSE
+
+///Places one monkey, if possible
+/obj/machinery/computer/camera_advanced/xenobio/proc/feed_slime(mob/living/user, turf/open/target_turf)
+ if(monkeys < 1)
+ to_chat(user, span_warning("[src] needs to have at least 1 monkey stored. Currently has [monkeys] monkeys stored."))
+ return
+
+ var/mob/living/carbon/human/species/monkey/food = new /mob/living/carbon/human/species/monkey(target_turf, TRUE, user)
+ if (QDELETED(food))
+ return
+
+ food.LAssailant = WEAKREF(user)
+ monkeys--
+ monkeys = round(monkeys, 0.1) //Prevents rounding errors
+ to_chat(user, span_notice("[src] now has [monkeys] monkeys stored."))
+
+///Recycles the target monkey
+/obj/machinery/computer/camera_advanced/xenobio/proc/monkey_recycle(mob/living/user, mob/living/target_mob)
+ if(!ismonkey(target_mob))
+ return
+ if(!target_mob.stat)
+ return
+
+ target_mob.visible_message(span_notice("[target_mob] vanishes as [p_theyre()] reclaimed for recycling!"))
+ connected_recycler.use_power(500)
+ monkeys += connected_recycler.cube_production
+ monkeys = round(monkeys, 0.1) //Prevents rounding errors
+ qdel(target_mob)
+ to_chat(user, span_notice("[src] now has [monkeys] monkeys stored."))
+
/datum/action/innate/slime_place
name = "Place Slimes"
button_icon = 'icons/mob/actions/actions_silicon.dmi'
@@ -153,17 +226,14 @@
/datum/action/innate/slime_place/Activate()
if(!target || !isliving(owner))
return
- var/mob/living/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
- var/obj/machinery/computer/camera_advanced/xenobio/X = target
+ var/mob/living/owner_mob = owner
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
+
+ if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc))
+ return
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
- for(var/mob/living/simple_animal/slime/S in X.stored_slimes)
- S.forceMove(remote_eye.loc)
- S.visible_message(span_notice("[S] warps in!"))
- X.stored_slimes -= S
- else
- to_chat(owner, span_warning("Target is not near a camera. Cannot proceed."))
+ xeno_console.slime_place(remote_eye.loc)
/datum/action/innate/slime_pick_up
name = "Pick up Slime"
@@ -173,23 +243,16 @@
/datum/action/innate/slime_pick_up/Activate()
if(!target || !isliving(owner))
return
- var/mob/living/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
- var/obj/machinery/computer/camera_advanced/xenobio/X = target
+ var/mob/living/owner_mob = owner
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
- for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
- if(X.stored_slimes.len >= X.max_slimes)
- break
- if(!S.ckey)
- if(S.buckled)
- S.Feedstop(silent = TRUE)
- S.visible_message(span_notice("[S] vanishes in a flash of light!"))
- S.forceMove(X)
- X.stored_slimes += S
- else
- to_chat(owner, span_warning("Target is not near a camera. Cannot proceed."))
+ if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc))
+ return
+ for(var/mob/living/simple_animal/slime/target_slime in remote_eye.loc)
+ if(xeno_console.slime_pickup(owner_mob, target_slime)) ///Returns true if we hit our slime pickup limit
+ break
/datum/action/innate/feed_slime
name = "Feed Slimes"
@@ -199,22 +262,14 @@
/datum/action/innate/feed_slime/Activate()
if(!target || !isliving(owner))
return
- var/mob/living/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
- var/obj/machinery/computer/camera_advanced/xenobio/X = target
+ var/mob/living/living_owner = owner
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = living_owner.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
- if(X.monkeys >= 1)
- var/mob/living/carbon/human/species/monkey/food = new /mob/living/carbon/human/species/monkey(remote_eye.loc, TRUE, owner)
- if (!QDELETED(food))
- food.LAssailant = WEAKREF(C)
- X.monkeys--
- X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors
- to_chat(owner, span_notice("[X] now has [X.monkeys] monkeys stored."))
- else
- to_chat(owner, span_warning("[X] needs to have at least 1 monkey stored. Currently has [X.monkeys] monkeys stored."))
- else
- to_chat(owner, span_warning("Target is not near a camera. Cannot proceed."))
+ if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc))
+ return
+
+ xeno_console.feed_slime(living_owner, remote_eye.loc)
/datum/action/innate/monkey_recycle
@@ -225,27 +280,20 @@
/datum/action/innate/monkey_recycle/Activate()
if(!target || !isliving(owner))
return
- var/mob/living/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
- var/obj/machinery/computer/camera_advanced/xenobio/X = target
- var/obj/machinery/monkey_recycler/recycler = X.connected_recycler
+ var/mob/living/owner_mob = owner
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
+ var/obj/machinery/monkey_recycler/recycler = xeno_console.connected_recycler
+
+ if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc))
+ return
if(!recycler)
to_chat(owner, span_warning("There is no connected monkey recycler. Use a multitool to link one."))
return
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
- for(var/mob/living/carbon/human/M in remote_eye.loc)
- if(!ismonkey(M))
- continue
- if(M.stat)
- M.visible_message(span_notice("[M] vanishes as [M.p_theyre()] reclaimed for recycling!"))
- recycler.use_power(500)
- X.monkeys += recycler.cube_production
- X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors
- qdel(M)
- to_chat(owner, span_notice("[X] now has [X.monkeys] monkeys available."))
- else
- to_chat(owner, span_warning("Target is not near a camera. Cannot proceed."))
+
+ for(var/mob/living/carbon/human/target_mob in remote_eye.loc)
+ xeno_console.monkey_recycle(owner, target_mob)
/datum/action/innate/slime_scan
name = "Scan Slime"
@@ -255,14 +303,15 @@
/datum/action/innate/slime_scan/Activate()
if(!target || !isliving(owner))
return
- var/mob/living/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
+ var/mob/living/owner_mob = owner
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
+
+ if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc))
+ return
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
- for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
- slime_scan(S, C)
- else
- to_chat(owner, span_warning("Target is not near a camera. Cannot proceed."))
+ for(var/mob/living/simple_animal/slime/scanned_slime in remote_eye.loc)
+ slime_scan(scanned_slime, owner_mob)
/datum/action/innate/feed_potion
name = "Apply Potion"
@@ -273,20 +322,20 @@
if(!target || !isliving(owner))
return
- var/mob/living/C = owner
- var/mob/camera/ai_eye/remote/xenobio/remote_eye = C.remote_control
- var/obj/machinery/computer/camera_advanced/xenobio/X = target
+ var/mob/living/owner_mob = owner
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target
- if(QDELETED(X.current_potion))
+ if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc))
+ return
+
+ if(QDELETED(xeno_console.current_potion))
to_chat(owner, span_warning("No potion loaded."))
return
- if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
- for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
- X.current_potion.attack(S, C)
- break
- else
- to_chat(owner, span_warning("Target is not near a camera. Cannot proceed."))
+ for(var/mob/living/simple_animal/slime/potioned_slime in remote_eye.loc)
+ xeno_console.current_potion.attack(potioned_slime, owner_mob)
+ break
/datum/action/innate/hotkey_help
name = "Hotkey Help"
@@ -296,156 +345,123 @@
/datum/action/innate/hotkey_help/Activate()
if(!target || !isliving(owner))
return
- to_chat(owner, "Click shortcuts:")
- to_chat(owner, "Shift-click a slime to pick it up, or the floor to drop all held slimes.")
- to_chat(owner, "Ctrl-click a slime to scan it.")
- to_chat(owner, "Alt-click a slime to feed it a potion.")
- to_chat(owner, "Ctrl-click or a dead monkey to recycle it, or the floor to place a new monkey.")
+
+ var/render_list = list()
+ render_list += "Click shortcuts:"
+ render_list += "• Shift-click a slime to pick it up, or the floor to drop all held slimes."
+ render_list += "• Ctrl-click a slime to scan it."
+ render_list += "• Alt-click a slime to feed it a potion."
+ render_list += "• Ctrl-click or a dead monkey to recycle it, or the floor to place a new monkey."
+
+ to_chat(owner, examine_block(jointext(render_list, "\n")))
//
// Alternate clicks for slime, monkey and open turf if using a xenobio console
-//Feeds a potion to slime
/mob/living/simple_animal/slime/AltClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_ALT, src)
..()
-//Picks up slime
/mob/living/simple_animal/slime/ShiftClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_SHIFT, src)
..()
-//Place slimes
/turf/open/ShiftClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_TURF_CLICK_SHIFT, src)
..()
-//scans slimes
/mob/living/simple_animal/slime/CtrlClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_CTRL, src)
..()
-//picks up dead monkies
/mob/living/carbon/human/species/monkey/CtrlClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_MONKEY_CLICK_CTRL, src)
..()
-//places monkies
/turf/open/CtrlClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_TURF_CLICK_CTRL, src)
..()
-// Scans slime
-/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickCtrl(mob/living/user, mob/living/simple_animal/slime/S)
+/// Scans the target slime
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickCtrl(mob/living/user, mob/living/simple_animal/slime/target_slime)
SIGNAL_HANDLER
- if(!GLOB.cameranet.checkTurfVis(S.loc))
- to_chat(user, span_warning("Target is not near a camera. Cannot proceed."))
+
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
+
+ if(!xeno_console.validate_area(user, remote_eye, target_slime.loc))
return
- var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
- var/area/mobarea = get_area(S.loc)
- if(mobarea.name == E.allowed_area || (mobarea.area_flags & XENOBIOLOGY_COMPATIBLE))
- slime_scan(S, C)
-//Feeds a potion to slime
-/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickAlt(mob/living/user, mob/living/simple_animal/slime/S)
+ slime_scan(target_slime, user)
+
+///Feeds a stored potion to a slime
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickAlt(mob/living/user, mob/living/simple_animal/slime/target_slime)
SIGNAL_HANDLER
- if(!GLOB.cameranet.checkTurfVis(S.loc))
- to_chat(user, span_warning("Target is not near a camera. Cannot proceed."))
+
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
+
+ if(!xeno_console.validate_area(user, remote_eye, target_slime.loc))
return
- var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
- var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
- var/area/mobarea = get_area(S.loc)
- if(QDELETED(X.current_potion))
- to_chat(C, span_warning("No potion loaded."))
+
+ if(QDELETED(xeno_console.current_potion))
+ to_chat(user, span_warning("No potion loaded."))
return
- if(mobarea.name == E.allowed_area || (mobarea.area_flags & XENOBIOLOGY_COMPATIBLE))
- INVOKE_ASYNC(X.current_potion, TYPE_PROC_REF(/obj/item/slimepotion/slime, attack), S, C)
-//Picks up slime
-/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/simple_animal/slime/S)
+ INVOKE_ASYNC(xeno_console.current_potion, TYPE_PROC_REF(/obj/item/slimepotion/slime, attack), target_slime, user)
+
+///Picks up a slime, and places them in the internal storage
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/simple_animal/slime/target_slime)
SIGNAL_HANDLER
- if(!GLOB.cameranet.checkTurfVis(S.loc))
- to_chat(user, span_warning("Target is not near a camera. Cannot proceed."))
+
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
+
+ if(!xeno_console.validate_area(user, remote_eye, target_slime.loc))
return
- var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
- var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
- var/area/mobarea = get_area(S.loc)
- if(mobarea.name == E.allowed_area || (mobarea.area_flags & XENOBIOLOGY_COMPATIBLE))
- if(X.stored_slimes.len >= X.max_slimes)
- to_chat(C, span_warning("Slime storage is full."))
- return
- if(S.ckey)
- to_chat(C, span_warning("The slime wiggled free!"))
- return
- if(S.buckled)
- S.Feedstop(silent = TRUE)
- S.visible_message(span_notice("[S] vanishes in a flash of light!"))
- S.forceMove(X)
- X.stored_slimes += S
-
-//Place slimes
-/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickShift(mob/living/user, turf/open/T)
+
+ xeno_console.slime_pickup(user, target_slime)
+
+///Places all slimes from the internal storage
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickShift(mob/living/user, turf/open/target_turf)
SIGNAL_HANDLER
- if(!GLOB.cameranet.checkTurfVis(T))
- to_chat(user, span_warning("Target is not near a camera. Cannot proceed."))
+ var/mob/living/user_mob = user
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = user_mob.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
+
+ if(!xeno_console.validate_area(user, remote_eye, target_turf))
return
- var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
- var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
- var/area/turfarea = get_area(T)
- if(turfarea.name == E.allowed_area || (turfarea.area_flags & XENOBIOLOGY_COMPATIBLE))
- for(var/mob/living/simple_animal/slime/S in X.stored_slimes)
- S.forceMove(T)
- S.visible_message(span_notice("[S] warps in!"))
- X.stored_slimes -= S
-
-//Place monkey
-/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickCtrl(mob/living/user, turf/open/T)
+
+ slime_place(target_turf)
+
+///Places a monkey from the internal storage
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickCtrl(mob/living/user, turf/open/target_turf)
SIGNAL_HANDLER
- if(!GLOB.cameranet.checkTurfVis(T))
- to_chat(user, span_warning("Target is not near a camera. Cannot proceed."))
+
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
+
+ if(!xeno_console.validate_area(user, remote_eye, target_turf))
return
- var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
- var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
- var/area/turfarea = get_area(T)
- if(turfarea.name == E.allowed_area || (turfarea.area_flags & XENOBIOLOGY_COMPATIBLE))
- if(X.monkeys >= 1)
- var/mob/living/carbon/human/food = new /mob/living/carbon/human/species/monkey(T, TRUE, C)
- if (!QDELETED(food))
- food.LAssailant = WEAKREF(C)
- X.monkeys--
- X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors
- to_chat(C, span_notice("[X] now has [X.monkeys] monkeys stored."))
- else
- to_chat(C, span_warning("[X] needs to have at least 1 monkey stored. Currently has [X.monkeys] monkeys stored."))
-
-//Pick up monkey
-/obj/machinery/computer/camera_advanced/xenobio/proc/XenoMonkeyClickCtrl(mob/living/user, mob/living/carbon/human/M)
+
+ xeno_console.feed_slime(user, target_turf)
+
+///Picks up a dead monkey for recycling
+/obj/machinery/computer/camera_advanced/xenobio/proc/XenoMonkeyClickCtrl(mob/living/user, mob/living/carbon/human/target_mob)
SIGNAL_HANDLER
- if(!ismonkey(M))
+ if(!ismonkey(target_mob))
return
- if(!isturf(M.loc) || !GLOB.cameranet.checkTurfVis(M.loc))
- to_chat(user, span_warning("Target is not near a camera. Cannot proceed."))
+
+ var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control
+ var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin
+
+ if(!xeno_console.validate_area(user, remote_eye, target_mob.loc))
return
- var/mob/living/C = user
- var/mob/camera/ai_eye/remote/xenobio/E = C.remote_control
- var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
- var/area/mobarea = get_area(M.loc)
- if(!X.connected_recycler)
- to_chat(C, span_warning("There is no connected monkey recycler. Use a multitool to link one."))
+
+ if(!xeno_console.connected_recycler)
+ to_chat(user, span_warning("There is no connected monkey recycler. Use a multitool to link one."))
return
- if(mobarea.name == E.allowed_area || (mobarea.area_flags & XENOBIOLOGY_COMPATIBLE))
- if(!M.stat)
- return
- M.visible_message(span_notice("[M] vanishes as [p_theyre()] reclaimed for recycling!"))
- X.connected_recycler.use_power(500)
- X.monkeys += connected_recycler.cube_production
- X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors
- qdel(M)
- to_chat(C, span_notice("[X] now has [X.monkeys] monkeys available."))
+
+ xeno_console.monkey_recycle(user, target_mob)
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index 2bbefb64ec3..1ce7f080d0f 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -11,28 +11,32 @@
throw_speed = 3
throw_range = 6
grind_results = list()
- var/Uses = 1 ///uses before it goes inert
- var/qdel_timer = null ///deletion timer, for delayed reactions
- var/effectmod ///Which type of crossbred
- var/list/activate_reagents = list() ///Reagents required for activation
+ ///uses before it goes inert
+ var/extract_uses = 1
+ ///deletion timer, for delayed reactions
+ var/qdel_timer = null
+ ///Which type of crossbred
+ var/crossbreed_modification
+ ///Reagents required for activation
+ var/list/activate_reagents = list()
var/recurring = FALSE
/obj/item/slime_extract/examine(mob/user)
. = ..()
- if(Uses > 1)
- . += "It has [Uses] uses remaining."
+ if(extract_uses > 1)
+ . += "It has [extract_uses] uses remaining."
/obj/item/slime_extract/attackby(obj/item/O, mob/user)
if(istype(O, /obj/item/slimepotion/enhancer))
- if(Uses >= 5 || recurring)
+ if(extract_uses >= 5 || recurring)
to_chat(user, span_warning("You cannot enhance this extract further!"))
return ..()
if(O.type == /obj/item/slimepotion/enhancer) //Seriously, why is this defined here...?
to_chat(user, span_notice("You apply the enhancer to the slime extract. It may now be reused one more time."))
- Uses++
+ extract_uses++
if(O.type == /obj/item/slimepotion/enhancer/max)
to_chat(user, span_notice("You dump the maximizer on the slime extract. It can now be used a total of 5 times!"))
- Uses = 5
+ extract_uses = 5
qdel(O)
..()
@@ -42,7 +46,7 @@
/obj/item/slime_extract/on_grind()
. = ..()
- if(Uses)
+ if(extract_uses)
grind_results[/datum/reagent/toxin/slimejelly] = 20
/**
@@ -63,34 +67,34 @@
*
* By using a valid core on a living adult slime, then feeding it nine more of the same type, you can mutate it into more useful items. Not every slime type has an implemented core cross.
*/
-/obj/item/slime_extract/attack(mob/living/simple_animal/slime/M, mob/user)
- if(!isslime(M))
+/obj/item/slime_extract/attack(mob/living/simple_animal/slime/target_slime, mob/user)
+ if(!isslime(target_slime))
return ..()
- if(M.stat)
+ if(target_slime.stat)
to_chat(user, span_warning("The slime is dead!"))
return
- if(!M.is_adult)
+ if(!target_slime.is_adult)
to_chat(user, span_warning("The slime must be an adult to cross its core!"))
return
- if(M.effectmod && M.effectmod != effectmod)
+ if(target_slime.crossbreed_modification && target_slime.crossbreed_modification != crossbreed_modification)
to_chat(user, span_warning("The slime is already being crossed with a different extract!"))
return
- if(!M.effectmod)
- M.effectmod = effectmod
+ if(!target_slime.crossbreed_modification)
+ target_slime.crossbreed_modification = crossbreed_modification
- M.applied++
+ target_slime.applied_crossbreed_amount++
qdel(src)
- to_chat(user, span_notice("You feed the slime [src], [M.applied == 1 ? "starting to mutate its core." : "further mutating its core."]"))
- playsound(M, 'sound/effects/attackblob.ogg', 50, TRUE)
+ to_chat(user, span_notice("You feed the slime [src], [target_slime.applied_crossbreed_amount == 1 ? "starting to mutate its core." : "further mutating its core."]"))
+ playsound(target_slime, 'sound/effects/attackblob.ogg', 50, TRUE)
- if(M.applied >= SLIME_EXTRACT_CROSSING_REQUIRED)
- M.spawn_corecross()
+ if(target_slime.applied_crossbreed_amount >= SLIME_EXTRACT_CROSSING_REQUIRED)
+ target_slime.spawn_corecross()
/obj/item/slime_extract/grey
name = "grey slime extract"
icon_state = "grey slime extract"
- effectmod = "reproductive"
+ crossbreed_modification = "reproductive"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma,/datum/reagent/water)
/obj/item/slime_extract/grey/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -105,7 +109,7 @@
if(SLIME_ACTIVATE_MAJOR)
to_chat(user, span_notice("Your [name] starts pulsing..."))
if(do_after(user, 40, target = user))
- var/mob/living/simple_animal/slime/S = new(get_turf(user), SLIME_TYPE_GREY)
+ var/mob/living/simple_animal/slime/S = new(get_turf(user), /datum/slime_type/grey)
playsound(user, 'sound/effects/splat.ogg', 50, TRUE)
to_chat(user, span_notice("You spit out [S]."))
return 350
@@ -115,7 +119,7 @@
/obj/item/slime_extract/gold
name = "gold slime extract"
icon_state = "gold slime extract"
- effectmod = "symbiont"
+ crossbreed_modification = "symbiont"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma,/datum/reagent/water)
@@ -146,7 +150,7 @@
/obj/item/slime_extract/silver
name = "silver slime extract"
icon_state = "silver slime extract"
- effectmod = "consuming"
+ crossbreed_modification = "consuming"
activate_reagents = list(/datum/reagent/toxin/plasma,/datum/reagent/water)
@@ -174,7 +178,7 @@
/obj/item/slime_extract/metal
name = "metal slime extract"
icon_state = "metal slime extract"
- effectmod = "industrial"
+ crossbreed_modification = "industrial"
activate_reagents = list(/datum/reagent/toxin/plasma,/datum/reagent/water)
/obj/item/slime_extract/metal/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -198,7 +202,7 @@
/obj/item/slime_extract/purple
name = "purple slime extract"
icon_state = "purple slime extract"
- effectmod = "regenerative"
+ crossbreed_modification = "regenerative"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma)
/obj/item/slime_extract/purple/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -217,7 +221,7 @@
/obj/item/slime_extract/darkpurple
name = "dark purple slime extract"
icon_state = "dark purple slime extract"
- effectmod = "self-sustaining"
+ crossbreed_modification = "self-sustaining"
activate_reagents = list(/datum/reagent/toxin/plasma)
/obj/item/slime_extract/darkpurple/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -240,7 +244,7 @@
/obj/item/slime_extract/orange
name = "orange slime extract"
icon_state = "orange slime extract"
- effectmod = "burning"
+ crossbreed_modification = "burning"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma,/datum/reagent/water)
/obj/item/slime_extract/orange/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -260,7 +264,7 @@
/obj/item/slime_extract/yellow
name = "yellow slime extract"
icon_state = "yellow slime extract"
- effectmod = "charged"
+ crossbreed_modification = "charged"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma,/datum/reagent/water)
/obj/item/slime_extract/yellow/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -283,7 +287,7 @@
/obj/item/slime_extract/red
name = "red slime extract"
icon_state = "red slime extract"
- effectmod = "sanguine"
+ crossbreed_modification = "sanguine"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma,/datum/reagent/water)
/obj/item/slime_extract/red/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -303,7 +307,7 @@
/obj/item/slime_extract/blue
name = "blue slime extract"
icon_state = "blue slime extract"
- effectmod = "stabilized"
+ crossbreed_modification = "stabilized"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma,/datum/reagent/water)
/obj/item/slime_extract/blue/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -323,7 +327,7 @@
/obj/item/slime_extract/darkblue
name = "dark blue slime extract"
icon_state = "dark blue slime extract"
- effectmod = "chilling"
+ crossbreed_modification = "chilling"
activate_reagents = list(/datum/reagent/toxin/plasma,/datum/reagent/water)
/obj/item/slime_extract/darkblue/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -346,7 +350,7 @@
/obj/item/slime_extract/pink
name = "pink slime extract"
icon_state = "pink slime extract"
- effectmod = "gentle"
+ crossbreed_modification = "gentle"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma)
/obj/item/slime_extract/pink/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -374,7 +378,7 @@
/obj/item/slime_extract/green
name = "green slime extract"
icon_state = "green slime extract"
- effectmod = "mutative"
+ crossbreed_modification = "mutative"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma,/datum/reagent/uranium/radium)
/obj/item/slime_extract/green/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -398,7 +402,7 @@
/obj/item/slime_extract/lightpink
name = "light pink slime extract"
icon_state = "light pink slime extract"
- effectmod = "loyal"
+ crossbreed_modification = "loyal"
activate_reagents = list(/datum/reagent/toxin/plasma)
/obj/item/slime_extract/lightpink/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -422,7 +426,7 @@
/obj/item/slime_extract/black
name = "black slime extract"
icon_state = "black slime extract"
- effectmod = "transformative"
+ crossbreed_modification = "transformative"
activate_reagents = list(/datum/reagent/toxin/plasma)
/obj/item/slime_extract/black/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -443,7 +447,7 @@
/obj/item/slime_extract/oil
name = "oil slime extract"
icon_state = "oil slime extract"
- effectmod = "detonating"
+ crossbreed_modification = "detonating"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma)
/obj/item/slime_extract/oil/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -467,7 +471,7 @@
/obj/item/slime_extract/adamantine
name = "adamantine slime extract"
icon_state = "adamantine slime extract"
- effectmod = "crystalline"
+ crossbreed_modification = "crystalline"
activate_reagents = list(/datum/reagent/toxin/plasma)
/obj/item/slime_extract/adamantine/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -497,7 +501,7 @@
/obj/item/slime_extract/bluespace
name = "bluespace slime extract"
icon_state = "bluespace slime extract"
- effectmod = "warping"
+ crossbreed_modification = "warping"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma)
var/teleport_ready = FALSE
var/teleport_x = 0
@@ -533,7 +537,7 @@
/obj/item/slime_extract/pyrite
name = "pyrite slime extract"
icon_state = "pyrite slime extract"
- effectmod = "prismatic"
+ crossbreed_modification = "prismatic"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma)
/obj/item/slime_extract/pyrite/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -560,7 +564,7 @@
/obj/item/slime_extract/cerulean
name = "cerulean slime extract"
icon_state = "cerulean slime extract"
- effectmod = "recurring"
+ crossbreed_modification = "recurring"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma)
/obj/item/slime_extract/cerulean/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -580,7 +584,7 @@
/obj/item/slime_extract/sepia
name = "sepia slime extract"
icon_state = "sepia slime extract"
- effectmod = "lengthened"
+ crossbreed_modification = "lengthened"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma,/datum/reagent/water)
/obj/item/slime_extract/sepia/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -602,7 +606,7 @@
/obj/item/slime_extract/rainbow
name = "rainbow slime extract"
icon_state = "rainbow slime extract"
- effectmod = "hyperchromatic"
+ crossbreed_modification = "hyperchromatic"
activate_reagents = list(/datum/reagent/blood,/datum/reagent/toxin/plasma,"lesser plasma",/datum/reagent/toxin/slimejelly,"holy water and uranium") //Curse this snowflake reagent list.
/obj/item/slime_extract/rainbow/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type)
@@ -668,7 +672,7 @@
M.rabid = FALSE
qdel(src)
return
- M.docile = 1
+ M.docile = TRUE
M.set_nutrition(700)
to_chat(M, span_warning("You absorb the potion and feel your intense desire to feed melt away."))
to_chat(user, span_notice("You feed the slime the potion, removing its hunger and calming it."))
diff --git a/code/modules/surgery/core_removal.dm b/code/modules/surgery/core_removal.dm
index 4ada9e7b59a..47f1e983f19 100644
--- a/code/modules/surgery/core_removal.dm
+++ b/code/modules/surgery/core_removal.dm
@@ -49,10 +49,10 @@
span_notice("[user] successfully extracts a core from [target]!"),
)
- new target_slime.coretype(target_slime.loc)
+ new target_slime.slime_type.core_type(target_slime.loc)
if(target_slime.cores <= 0)
- target_slime.icon_state = "[target_slime.colour] baby slime dead-nocore"
+ target_slime.icon_state = "[target_slime.slime_type.colour] baby slime dead-nocore"
return ..()
else
return FALSE
diff --git a/tgstation.dme b/tgstation.dme
index 39fd1400db5..1a158914a7e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -5004,7 +5004,7 @@
#include "code\modules\mob\living\simple_animal\slime\powers.dm"
#include "code\modules\mob\living\simple_animal\slime\slime.dm"
#include "code\modules\mob\living\simple_animal\slime\slime_say.dm"
-#include "code\modules\mob\living\simple_animal\slime\subtypes.dm"
+#include "code\modules\mob\living\simple_animal\slime\slime_type.dm"
#include "code\modules\mob_spawn\mob_spawn.dm"
#include "code\modules\mob_spawn\corpses\job_corpses.dm"
#include "code\modules\mob_spawn\corpses\mining_corpses.dm"
diff --git a/tools/UpdatePaths/Scripts/79852_slime_colour_renames.txt b/tools/UpdatePaths/Scripts/79852_slime_colour_renames.txt
new file mode 100644
index 00000000000..a8e59fb6a88
--- /dev/null
+++ b/tools/UpdatePaths/Scripts/79852_slime_colour_renames.txt
@@ -0,0 +1,22 @@
+
+/mob/living/simple_animal/slime{colour="grey"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/grey}
+/mob/living/simple_animal/slime{colour="metal"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/blue}
+/mob/living/simple_animal/slime{colour="purple"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/purple}
+/mob/living/simple_animal/slime{colour="orange"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/orange}
+/mob/living/simple_animal/slime{colour="dark blue"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/darkblue}
+/mob/living/simple_animal/slime{colour="dark purple"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/darkpurple}
+/mob/living/simple_animal/slime{colour="silver"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/silver}
+/mob/living/simple_animal/slime{colour="yellow"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/yellow}
+/mob/living/simple_animal/slime{colour="bluespace"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/bluespace}
+/mob/living/simple_animal/slime{colour="cerulean"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/cerulean}
+/mob/living/simple_animal/slime{colour="pyrite"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/pyrite}
+/mob/living/simple_animal/slime{colour="sepia"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/sepia}
+/mob/living/simple_animal/slime{colour="gold"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/gold}
+/mob/living/simple_animal/slime{colour="green"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/green}
+/mob/living/simple_animal/slime{colour="pick"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/pick}
+/mob/living/simple_animal/slime{colour="red"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/red}
+/mob/living/simple_animal/slime{colour="adamantine"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/adamantine}
+/mob/living/simple_animal/slime{colour="black"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/black}
+/mob/living/simple_animal/slime{colour="light pink"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/lightpink}
+/mob/living/simple_animal/slime{colour="oil"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/oil}
+/mob/living/simple_animal/slime{colour="rainbow"} : /mob/living/simple_animal/slime{@OLD;colour=@SKIP;slime_type=/datum/slime_type/rainbow}
\ No newline at end of file