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