#define SLIME_CARES_ABOUT(to_check) (to_check && (to_check == Target || to_check == Leader || (to_check in Friends))) /mob/living/simple_animal/slime name = "grey baby slime (123)" icon = 'icons/mob/slimes.dmi' icon_state = "grey baby slime" pass_flags = PASSTABLE | PASSGRILLE ventcrawler = VENTCRAWLER_ALWAYS gender = NEUTER var/is_adult = 0 var/docile = 0 faction = list("slime","neutral") harm_intent_damage = 5 icon_living = "grey baby slime" icon_dead = "grey baby slime dead" response_help = "pets" response_disarm = "shoos" response_harm = "stomps on" emote_see = list("jiggles", "bounces in place") speak_emote = list("blorbles") bubble_icon = "slime" initial_language_holder = /datum/language_holder/slime atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) maxHealth = 150 health = 150 healable = 0 gender = NEUTER see_in_dark = 8 verb_say = "blorbles" verb_ask = "inquisitively blorbles" verb_exclaim = "loudly blorbles" verb_yell = "loudly blorbles" // canstun and canknockdown don't affect slimes because they ignore stun and knockdown variables // for the sake of cleanliness, though, here they are. status_flags = CANUNCONSCIOUS|CANPUSH hud_type = /datum/hud/slime 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 var/number = 0 // Used to understand when someone is talking to it 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 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 var/list/Friends = list() // A list of friends; they are not considered targets for feeding; passed down after splitting var/list/speech_buffer = list() // Last phrase said near it and person who said it var/mood = "" // To show its face var/mutator_used = FALSE //So you can't shove a dozen mutators into a single slime var/force_stasis = FALSE //do_footstep = TRUE //yogs change var/static/regex/slime_name_regex = new("\\w+ (baby|adult) slime \\(\\d+\\)") ///////////TIME FOR SUBSPECIES var/colour = "grey" var/coretype = /obj/item/slime_extract/grey var/list/slime_mutation[4] var/static/list/slime_colours = list("rainbow", "grey", "purple", "metal", "orange", "blue", "dark blue", "dark purple", "yellow", "silver", "pink", "red", "gold", "green", "adamantine", "oil", "light pink", "bluespace", "cerulean", "sepia", "black", "pyrite") ///////////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="grey", new_is_adult=FALSE) var/datum/action/innate/slime/feed/F = new F.Grant(src) is_adult = new_is_adult if(is_adult) var/datum/action/innate/slime/reproduce/R = new R.Grant(src) health = 200 maxHealth = 200 else var/datum/action/innate/slime/evolve/E = new E.Grant(src) create_reagents(100) set_colour(new_colour) . = ..() set_nutrition(700) /mob/living/simple_animal/slime/Destroy() for (var/A in actions) var/datum/action/AC = A AC.Remove(src) set_target(null) set_leader(null) clear_friends() return ..() /mob/living/simple_animal/slime/proc/set_colour(new_colour) colour = new_colour 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/proc/update_name() if(slime_name_regex.Find(name)) number = rand(1, 1000) name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])" real_name = name /mob/living/simple_animal/slime/proc/random_colour() set_colour(pick(slime_colours)) /mob/living/simple_animal/slime/regenerate_icons() cut_overlays() var/icon_text = "[colour] [is_adult ? "adult" : "baby"] slime" icon_dead = "[icon_text] dead" if(stat != DEAD) icon_state = icon_text if(mood && !stat) add_overlay("aslime-[mood]") else icon_state = icon_dead ..() /mob/living/simple_animal/slime/on_reagent_change() . = ..() remove_movespeed_modifier(MOVESPEED_ID_SLIME_REAGENTMOD, TRUE) var/amount = 0 if(reagents.has_reagent(/datum/reagent/medicine/morphine)) // morphine slows slimes down amount = 2 if(reagents.has_reagent(/datum/reagent/consumable/frostoil)) // Frostoil also makes them move VEEERRYYYYY slow amount = 5 if(amount) add_movespeed_modifier(MOVESPEED_ID_SLIME_REAGENTMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount) /mob/living/simple_animal/slime/updatehealth() . = ..() var/mod = 0 if(!HAS_TRAIT(src, TRAIT_IGNOREDAMAGESLOWDOWN)) var/health_deficiency = (maxHealth - health) if(health_deficiency >= 45) mod += (health_deficiency / 25) if(health <= 0) mod += 2 add_movespeed_modifier(MOVESPEED_ID_SLIME_HEALTHMOD, TRUE, 100, multiplicative_slowdown = mod, override = TRUE) update_health_hud() /mob/living/simple_animal/slime/update_health_hud() if(hud_used) var/severity = 0 var/healthpercent = (health/maxHealth) * 100 switch(healthpercent) if(100 to INFINITY) hud_used.healths.icon_state = "slime_health0" if(80 to 100) hud_used.healths.icon_state = "slime_health1" severity = 1 if(60 to 80) hud_used.healths.icon_state = "slime_health2" severity = 2 if(40 to 60) hud_used.healths.icon_state = "slime_health3" severity = 3 if(20 to 40) hud_used.healths.icon_state = "slime_health4" severity = 4 if(1 to 20) hud_used.healths.icon_state = "slime_health5" severity = 5 else hud_used.healths.icon_state = "slime_health7" severity = 6 if(severity > 0) overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity) else clear_fullscreen("brute") /mob/living/simple_animal/slime/adjust_bodytemperature() . = ..() var/mod = 0 if(bodytemperature >= 330.23) // 135 F or 57.08 C mod = -1 // slimes become supercharged at high temperatures else if(bodytemperature < 283.222) mod = ((283.222 - bodytemperature) / 10) * 1.75 if(mod) add_movespeed_modifier(MOVESPEED_ID_SLIME_TEMPMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = mod) /mob/living/simple_animal/slime/ObjBump(obj/O) if(!client && powerlevel > 0) var/probab = 10 switch(powerlevel) if(1 to 2) probab = 20 if(3 to 4) probab = 30 if(5 to 6) probab = 40 if(7 to 8) probab = 60 if(9) probab = 70 if(10) probab = 95 if(prob(probab)) if(istype(O, /obj/structure/window) || istype(O, /obj/structure/grille)) if(nutrition <= get_hunger_nutrition() && !Atkcool) if (is_adult || prob(5)) O.attack_slime(src) Atkcool = 1 spawn(45) Atkcool = 0 /mob/living/simple_animal/slime/Process_Spacemove(movement_dir = 0) return 2 /mob/living/simple_animal/slime/get_status_tab_items() . = ..() if(!docile) . += "Nutrition: [nutrition]/[get_max_nutrition()]" if(amount_grown >= SLIME_EVOLUTION_THRESHOLD) if(is_adult) . += "You can reproduce!" else . += "You can evolve!" if(stat == UNCONSCIOUS) . += "You are knocked out by high levels of BZ!" else . += "Power Level: [powerlevel]" /mob/living/simple_animal/slime/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE) if(!forced) amount = -abs(amount) return ..() //Heals them /mob/living/simple_animal/slime/bullet_act(obj/item/projectile/Proj) attacked += 10 if((Proj.damage_type == BURN)) adjustBruteLoss(-abs(Proj.damage)) //fire projectiles heals slimes. Proj.on_hit(src) else . = ..(Proj) . = . || BULLET_ACT_BLOCK /mob/living/simple_animal/slime/emp_act(severity) . = ..() if(. & EMP_PROTECT_SELF) 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) return ..() /mob/living/simple_animal/slime/doUnEquip(obj/item/W, 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) return /mob/living/simple_animal/slime/attack_ui(slot) return /mob/living/simple_animal/slime/attack_slime(mob/living/simple_animal/slime/M) if(..()) //successful slime attack if(M == src) return if(buckled) Feedstop(silent = TRUE) visible_message(span_danger("[M] pulls [src] off!")) return attacked += 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)) if(health > 0) M.adjustBruteLoss(-10 + (-10 * M.is_adult)) M.updatehealth() /mob/living/simple_animal/slime/attack_animal(mob/living/simple_animal/M) . = ..() if(.) attacked += 10 /mob/living/simple_animal/slime/attack_paw(mob/living/carbon/monkey/M) if(..()) //successful monkey bite. attacked += 10 /mob/living/simple_animal/slime/attack_larva(mob/living/carbon/alien/larva/L) if(..()) //successful larva bite. attacked += 10 /mob/living/simple_animal/slime/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) if(user.a_intent == INTENT_HARM) discipline_slime(user) return ..() /mob/living/simple_animal/slime/attack_hand(mob/living/carbon/human/M) if(buckled) M.do_attack_animation(src, ATTACK_EFFECT_DISARM) if(buckled == M) if(prob(60)) visible_message(span_warning("[M] attempts to wrestle \the [name] off!")) playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) else visible_message(span_warning("[M] manages to wrestle \the [name] off!")) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) discipline_slime(M) else if(prob(30)) visible_message(span_warning("[M] attempts to wrestle \the [name] off of [buckled]!")) playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) else visible_message(span_warning("[M] manages to wrestle \the [name] off of [buckled]!")) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) discipline_slime(M) else if(stat == DEAD && surgeries.len) if(M.a_intent == INTENT_HELP || M.a_intent == INTENT_DISARM) for(var/datum/surgery/S in surgeries) if(S.next_step(M,M.a_intent)) return 1 if(..()) //successful attack attacked += 10 /mob/living/simple_animal/slime/attack_alien(mob/living/carbon/alien/humanoid/M) if(..()) //if harm or disarm intent. attacked += 10 discipline_slime(M) /mob/living/simple_animal/slime/attackby(obj/item/W, mob/living/user, params) if(stat == DEAD && surgeries.len) if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM) for(var/datum/surgery/S in surgeries) if(S.next_step(user,user.a_intent)) return 1 if(istype(W, /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) return if(W.force > 0) attacked += 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]!")) 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(is_adult) force_effect = round(W.force/2) if(prob(10 + force_effect)) discipline_slime(user) if(istype(W, /obj/item/storage/bag/bio)) 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) SEND_SIGNAL(P, COMSIG_TRY_STORAGE_TAKE, S, get_turf(src), 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, 1) 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, 1) return ..() /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, 1) var/crosspath for(var/X in crossbreeds) var/obj/item/slimecross/S = X if(initial(S.colour) == colour && initial(S.effect) == effectmod) crosspath = S break if(crosspath) new crosspath(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 return /mob/living/simple_animal/slime/examine(mob/user) . = list("This is [icon2html(src, user)] \a [src]!") if (stat == DEAD) . += span_deadsay("It is limp and unresponsive.") else if (stat == UNCONSCIOUS) // Slime stasis . += span_deadsay("It appears to be alive but unresponsive.") if (getBruteLoss()) . += "" if (getBruteLoss() < 40) . += "It has some punctures in its flesh!" else . += "It has severe punctures and tears in its flesh!" . += "\n" switch(powerlevel) if(2 to 3) . += "It is flickering gently with a little electrical activity." if(4 to 5) . += "It is glowing gently with moderate levels of electrical activity." if(6 to 9) . += span_warning("It is glowing brightly with high levels of electrical activity.") if(10) . += span_warning("It is radiating with massive levels of electrical activity!") . += "" /mob/living/simple_animal/slime/proc/discipline_slime(mob/user) if(stat) return if(prob(80) && !client) Discipline++ if(!is_adult) if(Discipline == 1) attacked = 0 set_target(null) if(buckled) Feedstop(silent = TRUE) //we unbuckle the slime from the mob it latched onto. SStun = world.time + rand(20,60) spawn(0) mobility_flags &= ~MOBILITY_MOVE if(user) step_away(src,user,15) sleep(0.3 SECONDS) if(user) step_away(src,user,15) update_mobility() /mob/living/simple_animal/slime/pet docile = 1 /mob/living/simple_animal/slime/can_unbuckle() return 0 /mob/living/simple_animal/slime/can_buckle() return 0 /mob/living/simple_animal/slime/get_mob_buckling_height(mob/seat) if(..()) return 3 /mob/living/simple_animal/slime/can_be_implanted() return TRUE /mob/living/simple_animal/slime/proc/set_target(new_target) var/old_target = Target Target = new_target if(old_target && !SLIME_CARES_ABOUT(old_target)) UnregisterSignal(old_target, COMSIG_PARENT_QDELETING) if(Target) RegisterSignal(Target, COMSIG_PARENT_QDELETING, .proc/clear_memories_of, override = TRUE) /mob/living/simple_animal/slime/proc/set_leader(new_leader) var/old_leader = Leader Leader = new_leader if(old_leader && !SLIME_CARES_ABOUT(old_leader)) UnregisterSignal(old_leader, COMSIG_PARENT_QDELETING) if(Leader) RegisterSignal(Leader, COMSIG_PARENT_QDELETING, .proc/clear_memories_of, override = TRUE) /mob/living/simple_animal/slime/proc/add_friendship(new_friend, amount = 1) if(!Friends[new_friend]) Friends[new_friend] = 0 Friends[new_friend] += amount if(new_friend) RegisterSignal(new_friend, COMSIG_PARENT_QDELETING, .proc/clear_memories_of, override = TRUE) /mob/living/simple_animal/slime/proc/set_friendship(new_friend, amount = 1) Friends[new_friend] = amount if(new_friend) RegisterSignal(new_friend, COMSIG_PARENT_QDELETING, .proc/clear_memories_of, override = TRUE) /mob/living/simple_animal/slime/proc/remove_friend(friend) Friends -= friend if(friend && !SLIME_CARES_ABOUT(friend)) UnregisterSignal(friend, COMSIG_PARENT_QDELETING) /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]) /mob/living/simple_animal/slime/proc/clear_friends() for(var/mob/friend as anything in Friends) remove_friend(friend) /mob/living/simple_animal/slime/proc/clear_memories_of(datum/source) SIGNAL_HANDLER if(source == Target) set_target(null) if(source == Leader) set_leader(null) remove_friend(source) /mob/living/simple_animal/slime/random/Initialize(mapload, new_colour, new_is_adult) . = ..(mapload, pick(slime_colours), prob(50)) #undef SLIME_CARES_ABOUT