Makes Xenobiology Simpler. Removes Slimes (#12398)

This commit is contained in:
Fox McCloud
2019-09-24 19:17:33 -04:00
committed by variableundefined
parent 69e3a08a06
commit cb8529cdb8
81 changed files with 1774 additions and 1903 deletions
+1 -1
View File
@@ -345,7 +345,7 @@
var/mob/living/carbon/human/newmob = M.change_mob_type(/mob/living/carbon/human, null, null, delmob, 1)
if(posttransformoutfit && istype(newmob))
newmob.equipOutfit(posttransformoutfit)
if("slime") M.change_mob_type( /mob/living/carbon/slime , null, null, delmob, 1 )
if("slime") M.change_mob_type( /mob/living/simple_animal/slime , null, null, delmob, 1 )
if("monkey") M.change_mob_type( /mob/living/carbon/human/monkey , null, null, delmob, 1 )
if("robot") M.change_mob_type( /mob/living/silicon/robot , null, null, delmob, 1 )
if("cat") M.change_mob_type( /mob/living/simple_animal/pet/cat , null, null, delmob, 1 )
+10
View File
@@ -95,6 +95,16 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
to_chat(usr, "<font color='blue'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</font>")
feedback_add_details("admin_verb","APC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
GLOBAL_VAR(AdminProcCaller)
GLOBAL_PROTECT(AdminProcCaller)
/proc/IsAdminAdvancedProcCall()
#ifdef TESTING
return FALSE
#else
return usr && usr.client && GLOB.AdminProcCaller == usr.client.ckey
#endif
/client/proc/callproc_datum(var/A as null|area|mob|obj|turf)
set category = "Debug"
set name = "Atom ProcCall"
+3 -5
View File
@@ -61,14 +61,12 @@ var/global/list/frozen_mob_list = list()
update_icons()
/mob/living/carbon/slime/admin_Freeze(admin)
/mob/living/simple_animal/slime/admin_Freeze(admin)
..(admin)
adjustToxLoss(1010101010) //arbitrary large value
adjustHealth(1000) //arbitrary large value
/mob/living/carbon/slime/admin_unFreeze(admin)
/mob/living/simple_animal/slime/admin_unFreeze(admin)
..(admin)
adjustToxLoss(-1010101010)
stat = 0
revive()
+6 -3
View File
@@ -22,7 +22,10 @@
if(newAnomaly.loc)
explosion(get_turf(newAnomaly), -1,0,3, flame_range = 4)
var/mob/living/carbon/slime/S = new/mob/living/carbon/slime(get_turf(newAnomaly))
S.colour = pick("red", "orange")
var/turf/T = get_turf(src)
var/new_colour = pick("red", "orange")
var/mob/living/simple_animal/slime/S = new(T, new_colour)
S.rabid = TRUE
S.amount_grown = SLIME_EVOLUTION_THRESHOLD
S.Evolve()
qdel(newAnomaly)
@@ -30,13 +30,10 @@
rating_speed = M.rating
/obj/machinery/processor/process()
..()
// The irony
// To be clear, if it's grinding, then it can't suck them up
if(processing)
return
var/mob/living/carbon/slime/picked_slime
for(var/mob/living/carbon/slime/slime in range(1, src))
var/mob/living/simple_animal/slime/picked_slime
for(var/mob/living/simple_animal/slime/slime in range(1, src))
if(slime.loc == src)
continue
if(slime.stat)
@@ -48,7 +45,7 @@
if(!P)
return
visible_message("[picked_slime] is sucked into \the [src].")
visible_message("<span class='notice'>[picked_slime] is sucked into [src].</span>")
picked_slime.forceMove(src)
//RECIPE DATUMS
@@ -110,18 +107,18 @@
/////MOB RECIPIES/////
//////////////////////
/datum/food_processor_process/mob/slime
input = /mob/living/carbon/slime
input = /mob/living/simple_animal/slime
output = null
/datum/food_processor_process/mob/slime/process_food(loc, what, obj/machinery/processor/processor)
var/mob/living/carbon/slime/S = what
var/mob/living/simple_animal/slime/S = what
var/C = S.cores
if(S.stat != DEAD)
S.loc = loc
S.forceMove(processor.drop_location())
S.visible_message("<span class='notice'>[S] crawls free of the processor!</span>")
return
for(var/i in 1 to (C+processor.rating_amount-1))
new S.coretype(loc)
new S.coretype(processor.drop_location())
feedback_add_details("slime_core_harvested","[replacetext(S.colour," ","_")]")
..()
@@ -75,3 +75,12 @@ In all, this is a lot like the monkey code. /N
adjustCloneLoss(damage)
if(STAMINA)
adjustStaminaLoss(damage)
/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(10, 40)
adjustBruteLoss(damage)
add_attack_logs(src, M, "Slime'd for [damage] damage")
updatehealth("slime attack")
@@ -65,15 +65,6 @@
take_overall_damage(b_loss, f_loss)
/mob/living/carbon/alien/humanoid/attack_slime(mob/living/carbon/slime/M)
..()
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(10, 40)
adjustBruteLoss(damage)
add_attack_logs(src, M, "Slime'd for [damage] damage")
return
/mob/living/carbon/alien/humanoid/restrained()
if(handcuffed)
return 1
@@ -71,16 +71,6 @@
/mob/living/carbon/alien/larva/attack_ui(slot_id)
return
/mob/living/carbon/alien/larva/attack_slime(mob/living/carbon/slime/M)
..()
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(20, 40)
adjustBruteLoss(damage)
add_attack_logs(src, M, "Slime'd for [damage] damage")
updatehealth()
return
/mob/living/carbon/alien/larva/restrained()
return 0
@@ -41,7 +41,7 @@
return 1
if(istype(other, /mob/living/carbon/human))
return 1
if(istype(other, /mob/living/carbon/slime))
if(istype(other, /mob/living/simple_animal/slime))
return 1
return ..()
@@ -48,16 +48,25 @@
return 1
return 0
/mob/living/carbon/attack_slime(mob/living/carbon/slime/M)
if(..())
var/power = M.powerlevel + rand(0,3)
Weaken(power)
Stuttering(power)
Stun(power)
var/stunprob = M.powerlevel * 7 + 10
if(prob(stunprob) && M.powerlevel >= 8)
adjustFireLoss(M.powerlevel * rand(6,10))
updatehealth("slime attack")
/mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
if(M.powerlevel > 0)
var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10
if(prob(stunprob))
M.powerlevel -= 3
if(M.powerlevel < 0)
M.powerlevel = 0
visible_message("<span class='danger'>The [M.name] has shocked [src]!</span>", "<span class='userdanger'>The [M.name] has shocked you!</span>")
do_sparks(5, TRUE, src)
var/power = M.powerlevel + rand(0,3)
Stun(power)
if(stuttering < power)
stuttering = power
if (prob(stunprob) && M.powerlevel >= 8)
adjustFireLoss(M.powerlevel * rand(6,10))
updatehealth("slime attack")
return 1
/mob/living/carbon/is_mouth_covered(head_only = FALSE, mask_only = FALSE)
@@ -451,22 +451,22 @@ emp_act
apply_damage(damage, M.melee_damage_type, affecting, armor)
updatehealth("animal attack")
/mob/living/carbon/human/attack_slime(mob/living/carbon/slime/M)
..()
var/damage = rand(1, 3)
/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 25)
if(M.is_adult)
damage = rand(10, 35)
if(M.is_adult)
damage = rand(10, 35)
else
damage = rand(5, 25)
if(check_shields(M, damage, "the [M.name]"))
return FALSE
var/dam_zone = pick("head", "chest", "groin", "l_arm", "l_hand", "r_arm", "r_hand", "l_leg", "l_foot", "r_leg", "r_foot")
var/dam_zone = pick("head", "chest", "groin", "l_arm", "l_hand", "r_arm", "r_hand", "l_leg", "l_foot", "r_leg", "r_foot")
var/obj/item/organ/external/affecting = get_organ(ran_zone(dam_zone))
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
return
var/obj/item/organ/external/affecting = get_organ(ran_zone(dam_zone))
if(!affecting)
affecting = get_organ("chest")
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == INTENT_HARM)
@@ -1,21 +0,0 @@
/mob/living/carbon/slime/death(gibbed)
// Only execute the below if we successfully died
. = ..()
if(!.)
return FALSE
if(!gibbed)
if(is_adult)
var/mob/living/carbon/slime/M = new /mob/living/carbon/slime(loc)
M.colour = colour
M.rabid = 1
is_adult = 0
maxHealth = 150
revive()
regenerate_icons()
number = rand(1, 1000)
name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
return
else
visible_message("<b>The [name]</b> seizes up and falls limp...")
icon_state = "[colour] baby slime dead"
overlays.Cut()
@@ -1,45 +0,0 @@
/mob/living/carbon/slime/examine(mob/user)
to_chat(user, "<span class='info'>*---------*</span>")
..(user)
var/msg = "<span class='info'>"
if(src.stat == DEAD)
msg += "<span class='deadsay'>It is limp and unresponsive.</span>\n"
else
if(src.getBruteLoss())
msg += "<span class='warning'>"
if(src.getBruteLoss() < 40)
msg += "It has some punctures in its flesh!"
else
msg += "<B>It has severe punctures and tears in its flesh!</B>"
msg += "</span>\n"
switch(powerlevel)
if(2 to 3)
msg += "It is flickering gently with a little electrical activity.\n"
if(4 to 5)
msg += "It is glowing gently with moderate levels of electrical activity.\n"
if(6 to 9)
msg += "<span class='warning'>It is glowing brightly with high levels of electrical activity.</span>\n"
if(10)
msg += "<span class='warning'><B>It is radiating with massive levels of electrical activity!</B></span>\n"
msg += "<span class='warning'>"
switch(wetlevel)
if(1)
msg += "It looks a bit damp.\n"
if(2)
msg += "It looks a little bit wet.\n"
if(3)
msg += "It looks wet.\n"
if(4)
msg += "It looks very wet.\n"
if(5)
msg += "It looks absolutely soaked.\n"
msg += "</span>"
msg += "*---------*</span>"
to_chat(user, msg)
@@ -1,570 +0,0 @@
/mob/living/carbon/slime
var/AIproc = 0 // determines if the AI loop is activated
var/Atkcool = 0 // attack cooldown
var/Tempstun = 0 // temporary temperature stuns
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
/mob/living/carbon/slime/Life(seconds, times_fired)
if(..())
handle_nutrition()
handle_targets()
if(!ckey)
handle_speech_and_mood()
/mob/living/carbon/slime/breathe()
return
/mob/living/carbon/slime/proc/AIprocess() // the master AI process
if(AIproc || stat == DEAD || client) return
var/hungry = 0
if(nutrition < get_starve_nutrition())
hungry = 2
else if(nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
hungry = 1
AIproc = 1
while(AIproc && stat != 2 && (attacked || hungry || rabid || Victim))
if(Victim) // can't eat AND have this little process at the same time
break
if(!Target || client)
break
if(Target.health <= -70 || Target.stat == 2)
Target = null
AIproc = 0
break
if(Target)
for(var/mob/living/carbon/slime/M in view(1,Target))
if(M.Victim == Target)
Target = null
AIproc = 0
break
if(!AIproc)
break
if(Target in view(1,src))
if(istype(Target, /mob/living/silicon))
if(!Atkcool)
Atkcool = 1
spawn(45)
Atkcool = 0
if(Target.Adjacent(src))
Target.attack_slime(src)
return
if(!Target.lying && prob(80))
if(Target.client && Target.health >= 20)
if(!Atkcool)
Atkcool = 1
spawn(45)
Atkcool = 0
if(Target.Adjacent(src))
Target.attack_slime(src)
else
if(!Atkcool && Target.Adjacent(src))
Feedon(Target)
else
if(!Atkcool && Target.Adjacent(src))
Feedon(Target)
else
if(Target in view(7, src))
if(!Target.Adjacent(src)) // Bug of the month candidate: slimes were attempting to move to target only if it was directly next to them, which caused them to target things, but not approach them
step_to(src, Target)
sleep(5)
else
Target = null
AIproc = 0
break
var/sleeptime = movement_delay()
if(sleeptime <= 0) sleeptime = 1
sleep(sleeptime + 2) // this is about as fast as a player slime can go
AIproc = 0
/mob/living/carbon/slime/handle_environment(datum/gas_mixture/environment)
if(!environment)
adjustToxLoss(rand(10,20))
return
//var/environment_heat_capacity = environment.heat_capacity()
var/loc_temp = T0C
if(istype(get_turf(src), /turf/space))
//environment_heat_capacity = loc:heat_capacity
var/turf/heat_turf = get_turf(src)
loc_temp = heat_turf.temperature
else if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell))
loc_temp = loc:air_contents.temperature
else
loc_temp = environment.temperature
//Account for massive pressure differences
if(bodytemperature < (T0C + 5)) // start calculating temperature damage etc
if(bodytemperature <= (T0C - 40)) // stun temperature
Tempstun = 1
if(bodytemperature <= (T0C - 50)) // hurt temperature
if(bodytemperature <= 50) // sqrting negative numbers is bad
adjustToxLoss(301) //The config.health_threshold_dead is -100 by default, and slimes have 150hp (200hp for adults),
else //so the ToxLoss needs to be 300 or above to guarrantee an instant death
adjustToxLoss(round(sqrt(bodytemperature)) * 2)
else
Tempstun = 0
/*moved after the temperature damage code so freeze beams can instantly kill slimes -Deity Link*/
if(loc_temp < 310.15) // a cold place
bodytemperature += adjust_body_temperature(bodytemperature, loc_temp, 1)
else // a hot place
bodytemperature += adjust_body_temperature(bodytemperature, loc_temp, 1)
updatehealth("handle environment")
return //TODO: DEFERRED
/mob/living/carbon/slime/proc/adjust_body_temperature(current, loc_temp, boost)
var/temperature = current
var/difference = abs(current-loc_temp) //get difference
var/increments// = difference/10 //find how many increments apart they are
if(difference > 50)
increments = difference/5
else
increments = difference/10
var/change = increments*boost // Get the amount to change by (x per increment)
var/temp_change
if(current < loc_temp)
temperature = min(loc_temp, temperature+change)
else if(current > loc_temp)
temperature = max(loc_temp, temperature-change)
temp_change = (temperature - current)
return temp_change
/mob/living/carbon/slime/handle_chemicals_in_body()
if(reagents)
reagents.metabolize(src)
if(reagents.get_reagent_amount("plasma")>=5)
mutation_chance = min(mutation_chance + 5,50) //Prevents mutation chance going >50%
reagents.remove_reagent("plasma", 5)
if(reagents.get_reagent_amount("epinephrine")>=5)
mutation_chance = max(mutation_chance - 5,0) //Prevents mutation chance going <0%
reagents.remove_reagent("epinephrine", 5)
updatehealth("handle chemicals in body")
return //TODO: DEFERRED
/mob/living/carbon/slime/handle_regular_status_updates()
if(is_adult)
health = 200 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
else
health = 150 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
if(health < HEALTH_THRESHOLD_DEAD && check_death_method() && stat != DEAD)
death()
return
else if(src.health <= HEALTH_THRESHOLD_CRIT && check_death_method())
if(!src.reagents.has_reagent("epinephrine"))
src.adjustOxyLoss(10)
if(src.stat != DEAD)
src.stat = UNCONSCIOUS
if(prob(30)) //I think this is meant to allow slimes to starve to death
adjustOxyLoss(-1)
adjustToxLoss(-1)
adjustFireLoss(-1)
adjustCloneLoss(-1)
adjustBruteLoss(-1)
if(src.stat == DEAD)
src.lying = 1
else
if(src.paralysis || src.stunned || src.weakened || (status_flags && FAKEDEATH)) //Stunned etc.
if(src.stunned > 0)
AdjustStunned(-1)
src.stat = 0
if(src.weakened > 0)
AdjustWeakened(-1)
src.lying = 0
src.stat = 0
if(src.paralysis > 0)
AdjustParalysis(-1)
src.lying = 0
src.stat = 0
else
src.lying = 0
src.stat = 0
if(src.stuttering) src.stuttering = 0
if(src.eye_blind)
src.SetEyeBlind(0)
src.density = !( src.lying )
if(src.eye_blurry > 0)
SetEyeBlurry(0)
if(src.druggy > 0)
SetDruggy(0)
return 1
/mob/living/carbon/slime/proc/handle_nutrition()
if(docile) //God as my witness, I will never go hungry again
nutrition = 700
return
if(prob(15))
nutrition -= 1 + is_adult
if(nutrition <= 0)
nutrition = 0
if(prob(75))
adjustToxLoss(rand(0,5))
else if(nutrition >= get_grow_nutrition() && amount_grown < 10)
nutrition -= 20
amount_grown++
update_action_buttons_icon()
if(amount_grown >= 10 && !Victim && !Target && !ckey)
if(is_adult)
Reproduce()
else
Evolve()
/mob/living/carbon/slime/proc/add_nutrition(nutrition_to_add = 0, lastnut = 0)
nutrition = min((nutrition + nutrition_to_add), get_max_nutrition())
if(nutrition >= (lastnut + 50))
if(prob(80))
lastnut = nutrition
powerlevel++
if(powerlevel > 10)
powerlevel = 10
adjustToxLoss(-10)
/mob/living/carbon/slime/proc/handle_targets()
if(Tempstun)
if(!Victim) // not while they're eating!
canmove = 0
else
canmove = 1
if(attacked > 50) attacked = 50
if(attacked > 0)
attacked--
if(Discipline > 0)
if(Discipline >= 5 && rabid)
if(prob(60)) rabid = 0
if(prob(10))
Discipline--
if(!client)
if(!canmove) return
if(Victim) return // if it's eating someone already, continue eating!
if(Target)
--target_patience
if(target_patience <= 0 || SStun || Discipline || attacked || docile) // Tired of chasing or something draws out attention
target_patience = 0
Target = null
if(AIproc && SStun) return
var/hungry = 0 // determines if the slime is hungry
if(nutrition < get_starve_nutrition())
hungry = 2
else if(nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
hungry = 1
if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends
if(Friends.len > 0 && prob(1))
var/mob/nofriend = pick(Friends)
--Friends[nofriend]
if(!Target)
if(will_hunt() && hungry || attacked || rabid) // Only add to the list if we need to
var/list/targets = list()
for(var/mob/living/L in view(7,src))
if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs
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(istype(L, /mob/living/carbon/human)) //Ignore slime(wo)men
var/mob/living/carbon/human/H = L
if(isslimeperson(H))
continue
if(!L.canmove) // Only one slime can latch on at a time.
var/notarget = 0
for(var/mob/living/carbon/slime/M in view(1,L))
if(M.Victim == L)
notarget = 1
if(notarget)
continue
targets += L // Possible target found!
if(targets.len > 0)
if(attacked || rabid || hungry == 2)
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 && prob(5))
if(ishuman(C) || isalienadult(C))
Target = C
break
if(islarva(C) || issmall(C))
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 - 1, 0)
else if(canmove && isturf(loc))
step_to(src, Leader)
else if(hungry)
if(holding_still)
holding_still = max(holding_still - hungry, 0)
else if(canmove && isturf(loc) && prob(50))
step(src, pick(cardinal))
else
if(holding_still)
holding_still = max(holding_still - 1, 0)
else if(docile && pulledby)
holding_still = 10
else if(canmove && isturf(loc) && prob(33))
step(src, pick(cardinal))
else if(!AIproc)
spawn()
AIprocess()
/mob/living/carbon/slime/proc/handle_speech_and_mood()
//Mood starts here
var/newmood = ""
if(rabid || attacked)
newmood = "angry"
else if(docile)
newmood = ":3"
else if(Target)
newmood = "mischevous"
if(!newmood)
if(Discipline && prob(25))
newmood = "pout"
else if(prob(1))
newmood = pick("sad", ":3", "pout")
if((mood == "sad" || mood == ":3" || mood == "pout") && !newmood)
if(prob(75)) newmood = mood
if(newmood != mood) // This is so we don't redraw them every time
mood = newmood
regenerate_icons()
//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, "hello") || findtext(phrase, "hi"))
to_say = pick("Hello...", "Hi...")
else if(findtext(phrase, "follow"))
if(Leader)
if(Leader == who) // Already following him
to_say = pick("Yes...", "Lead...", "Following...")
else if(Friends[who] > Friends[Leader]) // VIVA
Leader = who
to_say = "Yes... I follow [who]..."
else
to_say = "No... I follow [Leader]..."
else
if(Friends[who] > 2)
Leader = who
to_say = "I follow..."
else // Not friendly enough
to_say = pick("No...", "I won't follow...")
else if(findtext(phrase, "stop"))
if(Victim) // We are asked to stop feeding
if(Friends[who] > 4)
Victim = null
Target = null
if(Friends[who] < 7)
--Friends[who]
to_say = "Grrr..." // I'm angry but I do it
else
to_say = "Fine..."
else if(Target) // We are asked to stop chasing
if(Friends[who] > 3)
Target = null
if(Friends[who] < 6)
--Friends[who]
to_say = "Grrr..." // I'm angry but I do it
else
to_say = "Fine..."
else if(Leader) // We are asked to stop following
if(Leader == who)
to_say = "Yes... I'll stay..."
Leader = null
else
if(Friends[who] > Friends[Leader])
Leader = null
to_say = "Yes... I'll stop..."
else
to_say = "No... I'll keep following..."
else if(findtext(phrase, "stay"))
if(Leader)
if(Leader == who)
holding_still = Friends[who] * 10
to_say = "Yes... Staying..."
else if(Friends[who] > Friends[Leader])
holding_still = (Friends[who] - Friends[Leader]) * 10
to_say = "Yes... Staying..."
else
to_say = "No... I'll keep following..."
else
if(Friends[who] > 2)
holding_still = Friends[who] * 10
to_say = "Yes... Staying..."
else
to_say = "No... I won't stay..."
speech_buffer = list()
//Speech starts here
if(to_say)
say (to_say)
else if(prob(1))
emote(pick("bounce","sway","light","vibrate","jiggle"))
else
var/t = 10
var/slimes_near = -1 // Don't count myself
var/dead_slimes = 0
var/friends_near = list()
for(var/mob/living/carbon/M in view(7,src))
if(isslime(M))
++slimes_near
if(M.stat == DEAD)
++dead_slimes
if(M in Friends)
t += 20
friends_near += M
if(nutrition < get_hunger_nutrition()) t += 10
if(nutrition < get_starve_nutrition()) t += 10
if(prob(2) && prob(t))
var/phrases = list()
if(Target) phrases += "[Target]... looks tasty..."
if(nutrition < get_starve_nutrition())
phrases += "So... hungry..."
phrases += "Very... hungry..."
phrases += "Need... food..."
phrases += "Must... eat..."
else if(nutrition < get_hunger_nutrition())
phrases += "Hungry..."
phrases += "Where is the food?"
phrases += "I want to eat..."
phrases += "Rawr..."
phrases += "Blop..."
phrases += "Blorble..."
if(rabid || attacked)
phrases += "Hrr..."
phrases += "Nhuu..."
phrases += "Unn..."
if(mood == ":3")
phrases += "Purr..."
if(attacked)
phrases += "Grrr..."
if(getToxLoss() > 30)
phrases += "Cold..."
if(getToxLoss() > 60)
phrases += "So... cold..."
phrases += "Very... cold..."
if(getToxLoss() > 90)
phrases += "..."
phrases += "C... c..."
if(Victim)
phrases += "Nom..."
phrases += "Tasty..."
if(powerlevel > 3) phrases += "Bzzz..."
if(powerlevel > 5) phrases += "Zap..."
if(powerlevel > 8) phrases += "Zap... Bzz..."
if(mood == "sad") phrases += "Bored..."
if(slimes_near) phrases += "Brother..."
if(slimes_near > 1) phrases += "Brothers..."
if(dead_slimes) phrases += "What happened?"
if(!slimes_near)
phrases += "Lonely..."
for(var/M in friends_near)
phrases += "[M]... friend..."
if(nutrition < get_hunger_nutrition())
phrases += "[M]... feed me..."
say (pick(phrases))
/mob/living/carbon/slime/proc/get_max_nutrition() // Can't go above it
if(is_adult) return 1200
else return 1000
/mob/living/carbon/slime/proc/get_grow_nutrition() // Above it we grow, below it we can eat
if(is_adult) return 1000
else return 800
/mob/living/carbon/slime/proc/get_hunger_nutrition() // Below it we will always eat
if(is_adult) return 600
else return 500
/mob/living/carbon/slime/proc/get_starve_nutrition() // Below it we will eat before everything else
if(is_adult) return 300
else return 200
/mob/living/carbon/slime/proc/will_hunt(hunger = -1) // Check for being stopped from feeding and chasing
if(docile)
return 0
if(hunger == 2 || rabid || attacked)
return 1
if(Leader)
return 0
if(holding_still)
return 0
return 1
@@ -1,233 +0,0 @@
/mob/living/carbon/slime/verb/Feed()
set category = "Slime"
set desc = "This will let you feed on any valid creature in the surrounding area. This should also be used to halt the feeding process."
if(Victim)
Feedstop()
return 0
if(docile)
to_chat(src, "<span class='notice'><i>I'm not hungry anymore...</i></span>")
return 0
if(stat)
to_chat(src, "<i>I must be conscious to do this...</i>")
return 0
var/list/choices = list()
for(var/mob/living/C in view(1,src))
if(C!=src && !istype(C,/mob/living/carbon/slime) && Adjacent(C))
choices += C
var/mob/living/M = input(src,"Who do you wish to feed on?") in null|choices
if(!M)
return 0
if(Adjacent(M))
if(isbrain(M))
to_chat(src, "<i>This subject does not have an edible life energy...</i>")
return 0
if(iscarbon(M) && (M.health < -70))
to_chat(src, "<i>This subject does not have a strong enough life energy...</i>")
return 0
if(isanimal(M) && (M.health < 1))//animals don't go into crit, stupid; fixes infinite energy exploit
to_chat(src, "<i>This subject does not have a strong enough life energy...</i>")
return 0
for(var/mob/living/carbon/slime/met in view())
if(met.Victim == M && met != src)
to_chat(src, "<i>The [met.name] is already feeding on this subject...</i>")
return 0
to_chat(src, "<span class='notice'><i>I have latched onto the subject and begun feeding...</i></span>")
to_chat(M, "<span class='danger'>The [name] has latched onto your head!</span>")
Feedon(M)
return 1
/mob/living/carbon/slime/proc/Feedon(var/mob/living/M)
Victim = M
forceMove(M.loc)
canmove = 0
anchored = 1
var/lastnut = nutrition
var/fed_succesfully = 0
var/health_minimum = -70
if(is_adult)
icon_state = "[colour] adult slime eat"
else
icon_state = "[colour] baby slime eat"
if(isanimal(Victim))
health_minimum = 0
while(Victim && Victim.health > health_minimum && stat != DEAD)
canmove = 0
if(Adjacent(Victim))
forceMove(M.loc)
if(iscarbon(Victim))
Victim.adjustCloneLoss(rand(5,6))
Victim.adjustToxLoss(rand(1,2))
if(Victim.health <= 0)
Victim.adjustToxLoss(rand(2,4))
if(prob(15) && Victim.client)
to_chat(Victim, "<span class='danger'>[pick("You can feel your body becoming weak!", \
"You feel like you're about to die!", \
"You feel every part of your body screaming in agony!", \
"A low, rolling pain passes through your body!", \
"Your body feels as if it's falling apart!", \
"You feel extremely weak!", \
"A sharp, deep pain bathes every inch of your body!")]</span>")
fed_succesfully = 1
else if(health_minimum == 0) //we already know it's a simple_animal from above
Victim.adjustBruteLoss(is_adult ? rand(7, 15) : rand(4, 12))
fed_succesfully = 1
else
to_chat(src, "<span class='warning'>[pick("This subject is incompatable", \
"This subject does not have a life energy", "This subject is empty", \
"I am not satisified", "I can not feed from this subject", \
"I do not feel nourished", "This subject is not food")]...</span>")
if(fed_succesfully)
add_nutrition(rand(15,30), lastnut)
//Heal yourself.
adjustOxyLoss(-10)
adjustBruteLoss(-10)
adjustFireLoss(-10)
adjustCloneLoss(-10)
updatehealth("slime feeding")
if(Victim)
Victim.updatehealth("slime feeding")
sleep(rand(15,45))
else
break
if(stat == 2)
if(!is_adult)
icon_state = "[colour] baby slime dead"
else
if(is_adult)
icon_state = "[colour] adult slime"
else
icon_state = "[colour] baby slime"
canmove = 1
anchored = 0
if(M)
if(M.health <= health_minimum)
M.canmove = 0
if(!client)
if(Victim && !rabid && !attacked)
if(Victim.LAssailant && Victim.LAssailant != Victim)
if(prob(50))
if(!(Victim.LAssailant in Friends))
Friends[Victim.LAssailant] = 1
//Friends.Add(Victim.LAssailant) // no idea why i was using the |= operator
else
++Friends[Victim.LAssailant]
if(M.client && istype(src, /mob/living/carbon/human))
if(prob(85))
rabid = 1 // UUUNNBGHHHH GONNA EAT JUUUUUU
if(client)
to_chat(src, "<i>This subject does not have a strong enough life energy anymore...</i>")
else
M.canmove = 1
if(client)
to_chat(src, "<i>I have stopped feeding...</i>")
else
if(client)
to_chat(src, "<i>I have stopped feeding...</i>")
Victim = null
/mob/living/carbon/slime/proc/Feedstop()
if(Victim)
if(Victim.client)
to_chat(Victim, "[src] has let go of your head!")
Victim = null
/mob/living/carbon/slime/proc/UpdateFeed(var/mob/M)
if(Victim)
if(Victim == M)
forceMove(M.loc) // simple "attach to head" effect!
/mob/living/carbon/slime/verb/Evolve()
set category = "Slime"
set desc = "This will let you evolve from baby to adult slime."
if(stat)
to_chat(src, "<i>I must be conscious to do this...</i>")
return
if(!is_adult)
if(amount_grown >= 10)
is_adult = 1
maxHealth = 200
amount_grown = 0
regenerate_icons()
name = text("[colour] [is_adult ? "adult" : "baby"] slime ([number])")
else
to_chat(src, "<i>I am not ready to evolve yet...</i>")
else
to_chat(src, "<i>I have already evolved...</i>")
/mob/living/carbon/slime/verb/Reproduce()
set category = "Slime"
set desc = "This will make you split into four Slimes."
if(stat)
to_chat(src, "<i>I must be conscious to do this...</i>")
return
if(is_adult)
if(amount_grown >= 10)
if(stat)
to_chat(src, "<i>I must be conscious to do this...</i>")
return
var/list/babies = list()
var/new_nutrition = round(nutrition * 0.9)
var/new_powerlevel = round(powerlevel / 4)
for(var/i=1,i<=4,i++)
var/mob/living/carbon/slime/M = new /mob/living/carbon/slime/(loc)
if(mutation_chance >= 100)
M.colour = "rainbow"
else if(prob(mutation_chance))
M.colour = slime_mutation[rand(1,4)]
else
M.colour = colour
if(ckey)
M.nutrition = new_nutrition //Player slimes are more robust at spliting. Once an oversight of poor copypasta, now a feature!
M.powerlevel = new_powerlevel
if(i != 1)
step_away(M,src)
M.Friends = Friends.Copy()
babies += M
M.mutation_chance = Clamp(mutation_chance+(rand(5,-5)),0,100)
feedback_add_details("slime_babies_born","slimebirth_[replacetext(M.colour," ","_")]")
var/mob/living/carbon/slime/new_slime = pick(babies)
new_slime.universal_speak = universal_speak
if(src.mind)
src.mind.transfer_to(new_slime)
else
new_slime.key = src.key
qdel(src)
else
to_chat(src, "<i>I am not ready to reproduce yet...</i>")
else
to_chat(src, "<i>I am not old enough to reproduce yet...</i>")
@@ -1,29 +0,0 @@
/mob/living/carbon/slime/say_quote(var/text, var/datum/language/speaking)
var/verb = "telepathically chirps"
var/ending = copytext(text, length(text))
if(ending == "?")
verb = "telepathically asks"
else if(ending == "!")
verb = "telepathically cries"
return verb
/mob/living/carbon/slime/say_understands(var/other)
if(istype(other, /mob/living/carbon/slime))
return 1
return ..()
/mob/living/carbon/slime/hear_say(list/message_pieces, var/verb = "says", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
if(speaker in Friends)
speech_buffer = list()
speech_buffer.Add(speaker)
speech_buffer.Add(lowertext(html_decode(multilingual_to_message(message_pieces))))
..()
/mob/living/carbon/slime/hear_radio(list/message_pieces, var/verb="says", var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="", var/atom/follow_target)
if(speaker in Friends)
speech_buffer = list()
speech_buffer.Add(speaker)
speech_buffer.Add(lowertext(html_decode(multilingual_to_message(message_pieces))))
..()
@@ -1,546 +0,0 @@
/mob/living/carbon/slime
name = "baby slime"
icon = 'icons/mob/slimes.dmi'
icon_state = "grey baby slime"
pass_flags = PASSTABLE
ventcrawler = 2
speak_emote = list("telepathically chirps")
layer = 5
maxHealth = 150
health = 150
gender = NEUTER
nutrition = 700
see_in_dark = 8
update_slimes = 0
faction = list("slime","neutral")
// canstun and canweaken don't affect slimes because they ignore stun and weakened variables
// for the sake of cleanliness, though, here they are.
status_flags = CANPARALYSE|CANPUSH
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/Victim = null // the person the slime is currently feeding on
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/is_adult = 0
var/docile = 0
var/core_removal_stage = 0 //For removing cores.
var/mutator_used = FALSE //So you can't shove a dozen mutators into a single slime
///////////TIME FOR SUBSPECIES
var/colour = "grey"
var/coretype = /obj/item/slime_extract/grey
var/list/slime_mutation[4]
/mob/living/carbon/slime/New()
create_reagents(100)
spawn (0)
number = rand(1, 1000)
name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
icon_state = "[colour] [is_adult ? "adult" : "baby"] slime"
real_name = name
slime_mutation = mutation_table(colour)
var/sanitizedcolour = replacetext(colour, " ", "")
coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
..()
/mob/living/carbon/slime/random/New()
colour = pick("grey","orange", "metal", "blue", "purple", "dark purple", "dark blue", "green", "silver", "yellow", "gold", "yellow", "red", "silver", "pink", "cerulean", "sepia", "bluespace", "pyrite", "light pink", "oil", "adamantine", "black")
..()
/mob/living/carbon/slime/Destroy()
for(var/obj/machinery/computer/camera_advanced/xenobio/X in GLOB.machines)
if(src in X.stored_slimes)
X.stored_slimes -= src
return ..()
/mob/living/carbon/slime/can_unbuckle()
return FALSE
/mob/living/carbon/slime/can_buckle()
return FALSE
/mob/living/carbon/slime/get_mob_buckling_height(mob/seat)
if(..())
return 3
/mob/living/carbon/slime/regenerate_icons()
icon_state = "[colour] [is_adult ? "adult" : "baby"] slime"
overlays.len = 0
if(mood)
overlays += image('icons/mob/slimes.dmi', icon_state = "aslime-[mood]")
..()
/mob/living/carbon/slime/movement_delay()
if(bodytemperature >= 330.23) // 135 F
return -1 // slimes become supercharged at high temperatures
. = ..()
var/health_deficiency = (100 - health)
if(health_deficiency >= 45)
. += (health_deficiency / 25)
if(bodytemperature < 183.222)
. += (283.222 - bodytemperature) / 10 * 1.75
if(reagents)
if(reagents.has_reagent("methamphetamine")) // Meth slows slimes down
. *= 2
if(reagents.has_reagent("frostoil")) // Frostoil also makes them move VEEERRYYYYY slow
. *= 5
if(health <= 0) // if damaged, the slime moves twice as slow
. *= 2
. += config.slime_delay
/mob/living/carbon/slime/ObjBump(obj/O)
if(!client && powerlevel > 0)
var/chance = 10
switch(powerlevel)
if(1 to 2) chance = 20
if(3 to 4) chance = 30
if(5 to 6) chance = 40
if(7 to 8) chance = 60
if(9) chance = 70
if(10) chance = 95
if(prob(chance))
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/carbon/slime/Process_Spacemove(var/movement_dir = 0)
return 2
/mob/living/carbon/slime/Stat()
..()
statpanel("Status")
if(is_adult)
stat(null, "Health: [round((health / 200) * 100)]%")
else
stat(null, "Health: [round((health / 150) * 100)]%")
if(client.statpanel == "Status")
if(!docile)
stat(null, "Nutrition: [nutrition]/[get_max_nutrition()]")
if(amount_grown >= 10)
if(is_adult)
stat(null, "You can reproduce!")
else
stat(null, "You can evolve!")
stat(null,"Power Level: [powerlevel]")
/mob/living/carbon/slime/updatehealth(reason)
. = ..()
update_health_hud()
/mob/living/carbon/slime/proc/update_health_hud()
if(hud_used)
var/severity = 0
var/healthpercent = (health/maxHealth) * 100
if(stat != DEAD)
switch(healthpercent)
if(100 to INFINITY)
healths.icon_state = "slime_health0"
if(80 to 100)
healths.icon_state = "slime_health1"
severity = 1
if(60 to 80)
healths.icon_state = "slime_health2"
severity = 2
if(40 to 60)
healths.icon_state = "slime_health3"
severity = 3
if(20 to 40)
healths.icon_state = "slime_health4"
severity = 4
if(0 to 20)
healths.icon_state = "slime_health5"
severity = 5
if(-199 to 0)
healths.icon_state = "slime_health6"
severity = 6
else
healths.icon_state = "slime_health7"
severity = 6
if(severity > 0)
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
/mob/living/carbon/slime/adjustFireLoss(amount)
..(-abs(amount)) // Heals them
return
/mob/living/carbon/slime/bullet_act(var/obj/item/projectile/Proj)
attacked += 10
..(Proj)
return 0
/mob/living/carbon/slime/emp_act(severity)
powerlevel = 0 // oh no, the power!
..()
/mob/living/carbon/slime/ex_act(severity)
..()
var/b_loss = null
var/f_loss = null
switch(severity)
if(1.0)
qdel(src)
return
if(2.0)
b_loss += 60
f_loss += 60
if(3.0)
b_loss += 30
adjustBruteLoss(b_loss)
adjustFireLoss(f_loss)
updatehealth()
/mob/living/carbon/slime/blob_act()
show_message("<span class='userdanger'> The blob attacks you!</span>")
adjustBruteLoss(20)
updatehealth()
return
/mob/living/carbon/slime/MouseDrop(atom/movable/A)
if(isliving(A) && A != src && usr == src)
var/mob/living/Food = A
if(Food.Adjacent(src) && !stat && Food.stat != DEAD) //messy
Feedon(Food)
..()
/mob/living/carbon/slime/unEquip(obj/item/W as obj, force)
return
/mob/living/carbon/slime/attack_ui(slot)
return
/mob/living/carbon/slime/attack_slime(mob/living/carbon/slime/M)
..()
if(Victim)
Victim = null
visible_message("<span class='danger'>[M] pulls [src] off!</span>")
return
attacked += 5
if(nutrition >= 100) //steal some nutrition. negval handled in life()
nutrition -= (50 + (5 * M.amount_grown))
M.add_nutrition(50 + (5 * M.amount_grown))
if(health > 0)
adjustBruteLoss(4 + (2 * M.amount_grown)) //amt_grown isn't very linear but it works
updatehealth()
M.adjustBruteLoss(-4 + (-2 * M.amount_grown))
M.updatehealth()
/mob/living/carbon/slime/attack_animal(mob/living/simple_animal/M)
. = ..()
if(.)
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
attacked += 10
adjustBruteLoss(damage)
updatehealth()
/mob/living/carbon/slime/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite.
var/damage = rand(1, 3)
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
adjustBruteLoss(damage)
updatehealth()
/mob/living/carbon/slime/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(user.a_intent == INTENT_HARM)
if(Victim || Target)
Victim = null
Target = null
anchored = 0
if(prob(80) && !client)
Discipline++
spawn(0)
step_away(src, user, 15)
sleep(3)
step_away(src, user, 15)
..(user, TRUE)
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[user] has punched [src]!</span>", "<span class='userdanger'>[user] has punched [src]!</span>")
adjustBruteLoss(15)
return TRUE
/mob/living/carbon/slime/attack_hand(mob/living/carbon/human/M)
if(Victim)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
if(Victim == M)
if(prob(60))
visible_message("<span class='warning'>[M] attempts to wrestle \the [name] off!</span>")
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
else
visible_message("<span class='warning'> [M] manages to wrestle \the [name] off!</span>")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(prob(90) && !client)
Discipline++
SStun = 1
spawn(rand(45,60))
SStun = 0
Victim = null
anchored = 0
step_away(src,M)
return
else
if(prob(30))
visible_message("<span class='warning'>[M] attempts to wrestle \the [name] off of [Victim]!</span>")
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
else
visible_message("<span class='warning'> [M] manages to wrestle \the [name] off of [Victim]!</span>")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(prob(80) && !client)
Discipline++
if(!is_adult)
if(Discipline == 1)
attacked = 0
SStun = 1
spawn(rand(55,65))
SStun = 0
Victim = null
anchored = 0
step_away(src,M)
return
if(..()) //To allow surgery to return properly.
return
switch(M.a_intent)
if(INTENT_HELP)
help_shake_act(M)
if(INTENT_GRAB)
grabbedby(M)
else
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
var/damage = rand(1, 9)
attacked += 10
if(prob(90))
playsound(loc, "punch", 25, 1, -1)
add_attack_logs(M, src, "Melee attacked with fists")
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
"<span class='userdanger'>[M] has punched [src]!</span>")
if(stat != DEAD)
adjustBruteLoss(damage)
updatehealth()
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to punch [src]!</span>")
return
/mob/living/carbon/slime/attack_alien(mob/living/carbon/alien/humanoid/M)
if(..()) //if harm or disarm intent.
if(M.a_intent == INTENT_HARM)
if(prob(95))
attacked += 10
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
var/damage = rand(15, 30)
if(damage >= 25)
damage = rand(20, 40)
visible_message("<span class='danger'>[M] has slashed [name]!</span>", \
"<span class='userdanger'>[M] has slashed [name]!</span>")
else
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
"<span class='userdanger'>)[M] has wounded [name]!</span>")
add_attack_logs(M, src, "Alien attacked")
if(stat != DEAD)
adjustBruteLoss(damage)
updatehealth()
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>")
if(M.a_intent == INTENT_DISARM)
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
var/damage = 5
attacked += 10
if(prob(95))
visible_message("<span class='danger'>[M] has tackled [name]!</span>", \
"<span class='userdanger'>[M] has tackled [name]!</span>")
if(Victim || Target)
Victim = null
Target = null
anchored = 0
if(prob(80) && !client)
Discipline++
if(!isslime(src))
if(Discipline == 1)
attacked = 0
SStun = 1
spawn(rand(5,20))
SStun = 0
spawn(0)
step_away(src,M,15)
sleep(3)
step_away(src,M,15)
else
drop_item()
visible_message("<span class='danger'>[M] has disarmed [name]!</span>",
"<span class='userdanger'>[M] has disarmed [name]!</span>")
add_attack_logs(M, src, "Alien disarmed")
adjustBruteLoss(damage)
updatehealth()
return
/mob/living/carbon/slime/attackby(obj/item/W, mob/living/user, params)
if(istype(W,/obj/item/stack/sheet/mineral/plasma)) //Lets you feed slimes plasma.
if(user in Friends)
++Friends[user]
else
Friends[user] = 1
to_chat(user, "You feed the slime the plasma. It chirps happily.")
var/obj/item/stack/sheet/mineral/plasma/S = W
S.use(1)
return
else if(W.force > 0)
attacked += 10
if(prob(25))
user.do_attack_animation(src)
to_chat(user, "<span class='danger'>[W] passes right through [src]!</span>")
return
if(Discipline && prob(50)) // wow, buddy, why am I getting attacked??
Discipline = 0
else if(W.force >= 3)
if(is_adult)
if(prob(5 + round(W.force/2)))
if(Victim || Target)
if(prob(80) && !client)
Discipline++
Victim = null
Target = null
anchored = 0
SStun = 1
spawn(rand(5,20))
SStun = 0
spawn(0)
if(user)
canmove = 0
step_away(src, user)
if(prob(25 + W.force))
sleep(2)
if(user)
step_away(src, user)
canmove = 1
else
if(prob(10 + W.force*2))
if(Victim || Target)
if(prob(80) && !client)
Discipline++
if(Discipline == 1)
attacked = 0
SStun = 1
spawn(rand(5,20))
SStun = 0
Victim = null
Target = null
anchored = 0
spawn(0)
if(user)
canmove = 0
step_away(src, user)
if(prob(25 + W.force*4))
sleep(2)
if(user)
step_away(src, user)
canmove = 1
..()
/mob/living/carbon/slime/restrained()
return 0
mob/living/carbon/slime/var/temperature_resistance = T0C+75
/mob/living/carbon/slime/show_inv(mob/user)
return
/mob/living/carbon/slime/toggle_throw_mode()
return
/mob/living/carbon/slime/water_act(volume, temperature, source, method = TOUCH)
. = ..()
var/water_damage = rand(10, 15) * volume
adjustToxLoss(water_damage)
if(!client && Target && volume >= 3)
Target = null
++Discipline
/mob/living/carbon/slime/can_use_vents()
if(Victim)
return "You cannot ventcrawl while feeding."
..()
/mob/living/carbon/slime/forceFed(var/obj/item/reagent_containers/food/toEat, mob/user, fullness)
if(istype(toEat, /obj/item/reagent_containers/food/drinks))
return 1
to_chat(user, "This creature does not seem to have a mouth!")
return 0
/mob/living/carbon/slime/can_hear()
. = TRUE //honestly fuck slimes and organ bullshit
@@ -1 +0,0 @@
//no special icon processing
-4
View File
@@ -541,10 +541,6 @@
if(s_active && !(s_active in contents) && get_turf(s_active) != get_turf(src)) //check !( s_active in contents ) first so we hopefully don't have to call get_turf() so much.
s_active.close(src)
if(update_slimes)
for(var/mob/living/carbon/slime/M in view(1,src))
M.UpdateFeed(src)
/mob/living/proc/handle_footstep(turf/T)
if(istype(T))
+7 -19
View File
@@ -277,33 +277,21 @@
return G
/mob/living/attack_slime(mob/living/carbon/slime/M)
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
if(!SSticker)
to_chat(M, "You cannot attack people before the game has started.")
return
if(M.Victim)
if(M.buckled)
if(M in buckled_mobs)
M.Feedstop()
return // can't attack while eating!
if(stat != DEAD)
add_attack_logs(src, M, "Slime'd")
M.do_attack_animation(src)
visible_message("<span class='danger'>The [M.name] glomps [src]!</span>", \
"<span class='userdanger'>The [M.name] glomps [src]!</span>")
if(M.powerlevel > 0)
var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10
if(prob(stunprob))
M.powerlevel -= 3
if(M.powerlevel < 0)
M.powerlevel = 0
visible_message("<span class='danger'>The [M.name] has shocked [src]!</span>", \
"<span class='userdanger'>The [M.name] has shocked [src]!</span>")
do_sparks(5, 1, src)
return 1
add_attack_logs(src, M, "Slime'd")
return
visible_message("<span class='danger'>\The [M.name] glomps [src]!</span>", "<span class='userdanger'>\The [M.name] glomps you!</span>")
return TRUE
/mob/living/attack_animal(mob/living/simple_animal/M)
M.face_atom(src)
@@ -28,7 +28,6 @@
var/on_fire = 0 //The "Are we on fire?" var
var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20
var/update_slimes = 1
var/implanting = 0 //Used for the mind-slave implant
var/floating = 0
var/mob_size = MOB_SIZE_HUMAN
@@ -4,5 +4,5 @@
return
..()
/mob/living/silicon/ai/attack_slime(mob/living/carbon/slime/user)
/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user)
return //immune to slimes
@@ -19,7 +19,7 @@
..()
return
/mob/living/silicon/robot/attack_slime(mob/living/carbon/slime/M)
/mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime shock
flash_eyes(affect_silicon = 1)
var/stunprob = M.powerlevel * 7 + 10
@@ -58,12 +58,12 @@
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
return attack_threshold_check(damage, M.melee_damage_type)
/mob/living/simple_animal/attack_slime(mob/living/carbon/slime/M)
..()
var/damage = rand(15, 25)
if(M.is_adult)
damage = rand(20, 35)
attack_threshold_check(damage)
/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(15, 25)
if(M.is_adult)
damage = rand(20, 35)
return attack_threshold_check(damage)
/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE, armorcheck = "melee")
var/temp_damage = damage
@@ -1,60 +0,0 @@
/mob/living/simple_animal/slime
name = "pet slime"
desc = "A lovable, domesticated slime."
icon = 'icons/mob/slimes.dmi'
icon_state = "grey baby slime"
icon_living = "grey baby slime"
icon_dead = "grey baby slime dead"
speak_emote = list("chirps")
health = 100
maxHealth = 100
response_help = "pets"
response_disarm = "shoos"
response_harm = "stomps on"
emote_see = list("jiggles", "bounces in place")
pass_flags = PASSTABLE
var/colour = "grey"
/mob/living/simple_animal/slime/adult
health = 200
maxHealth = 200
icon_state = "grey adult slime"
icon_living = "grey adult slime"
/mob/living/simple_animal/slime/New()
..()
overlays += "aslime-:33"
/mob/living/simple_animal/slime/updatehealth(reason)
. = ..()
update_health_hud()
/mob/living/simple_animal/slime/proc/update_health_hud()
if(hud_used)
var/severity = 0
var/healthpercent = (health/maxHealth) * 100
switch(healthpercent)
if(100 to INFINITY)
healths.icon_state = "slime_health0"
if(80 to 100)
healths.icon_state = "slime_health1"
severity = 1
if(60 to 80)
healths.icon_state = "slime_health2"
severity = 2
if(40 to 60)
healths.icon_state = "slime_health3"
severity = 3
if(20 to 40)
healths.icon_state = "slime_health4"
severity = 4
if(1 to 20)
healths.icon_state = "slime_health5"
severity = 5
else
healths.icon_state = "slime_health7"
severity = 6
if(severity > 0)
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
@@ -605,7 +605,7 @@
real_name = P.tagname
/mob/living/simple_animal/regenerate_icons()
cut_overlays()
if(pcollar && collar_type)
cut_overlays()
add_overlay("[collar_type]collar")
add_overlay("[collar_type]tag")
@@ -0,0 +1,32 @@
/mob/living/simple_animal/slime/death(gibbed)
if(stat == DEAD)
return
if(!gibbed)
if(is_adult)
var/mob/living/simple_animal/slime/M = new(loc, colour)
M.rabid = TRUE
M.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)
revive()
regenerate_icons()
update_name()
return
if(buckled)
Feedstop(silent = TRUE) //releases ourselves from the mob we fed on.
stat = DEAD //Temporarily set to dead for icon updates
regenerate_icons()
stat = CONSCIOUS
return ..(gibbed)
/mob/living/simple_animal/slime/gib()
death(TRUE)
qdel(src)
@@ -1,4 +1,7 @@
/mob/living/carbon/slime/emote(act, m_type = 1, message = null, force)
/mob/living/simple_animal/slime/emote(act, m_type = 1, message = null, force)
if(stat)
return
if(findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
//param = copytext(act, t1 + 1, length(act) + 1)
@@ -99,6 +102,4 @@
loc.audible_message(message)
if(regenerate_icons)
regenerate_icons()
return
regenerate_icons()
@@ -0,0 +1,617 @@
/mob/living/simple_animal/slime
var/AIproc = 0 // determines if the AI loop is activated
var/Atkcool = 0 // attack cooldown
var/Tempstun = 0 // temporary temperature stuns
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
/mob/living/simple_animal/slime/Life()
set invisibility = 0
if(notransform)
return
if(..())
if(buckled)
handle_feeding()
if(!stat) // Slimes in stasis don't lose nutrition, don't change mood and don't respond to speech
handle_nutrition()
if(QDELETED(src)) // Stop if the slime split during handle_nutrition()
return
reagents.remove_all(0.5 * REAGENTS_METABOLISM * reagents.reagent_list.len) //Slimes are such snowflakes
handle_targets()
if(!ckey)
handle_mood()
handle_speech()
// Unlike most of the simple animals, slimes support UNCONSCIOUS
/mob/living/simple_animal/slime/update_stat()
if(stat == UNCONSCIOUS && health > 0)
return
..()
/mob/living/simple_animal/slime/proc/AIprocess() // the master AI process
if(AIproc || stat || client)
return
var/hungry = 0
if (nutrition < get_starve_nutrition())
hungry = 2
else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
hungry = 1
AIproc = 1
while(AIproc && stat != DEAD && (attacked || hungry || rabid || buckled))
if(!canmove) //also covers buckling. Not sure why buckled is in the while condition if we're going to immediately break, honestly
break
if(!Target || client)
break
if(Target.health <= -70 || Target.stat == DEAD)
Target = null
AIproc = 0
break
if(Target)
if(locate(/mob/living/simple_animal/slime) in Target.buckled_mobs)
Target = null
AIproc = 0
break
if(!AIproc)
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(Target.Adjacent(src))
Target.attack_slime(src)
break
if(!Target.lying && prob(80))
if(Target.client && Target.health >= 20)
if(!Atkcool)
Atkcool = TRUE
addtimer(VARSET_CALLBACK(src, Atkcool, FALSE), 4.5 SECONDS)
if(Target.Adjacent(src))
Target.attack_slime(src)
else
if(!Atkcool && Target.Adjacent(src))
Feedon(Target)
else
if(!Atkcool && Target.Adjacent(src))
Feedon(Target)
else if(Target in view(7, src))
if(!Target.Adjacent(src))
// Bug of the month candidate: slimes were attempting to move to target only if it was directly next to them, which caused them to target things, but not approach them
step_to(src, Target)
else
Target = null
AIproc = 0
break
var/sleeptime = movement_delay()
if(sleeptime <= 0)
sleeptime = 1
sleep(sleeptime + 2) // this is about as fast as a player slime can go
AIproc = 0
/mob/living/simple_animal/slime/handle_environment(datum/gas_mixture/environment)
if(!environment)
return
var/loc_temp = get_temperature(environment)
adjust_bodytemperature(adjust_body_temperature(bodytemperature, loc_temp, 1))
//Account for massive pressure differences
if(bodytemperature < (T0C + 5)) // start calculating temperature damage etc
if(bodytemperature <= (T0C - 40)) // stun temperature
Tempstun = 1
if(bodytemperature <= (T0C - 50)) // hurt temperature
if(bodytemperature <= 50) // sqrting negative numbers is bad
adjustBruteLoss(200)
else
adjustBruteLoss(round(sqrt(bodytemperature)) * 2)
else
Tempstun = 0
updatehealth("handle environment")
return //TODO: DEFERRED
/mob/living/simple_animal/slime/proc/adjust_body_temperature(current, loc_temp, boost)
var/temperature = current
var/difference = abs(current - loc_temp) //get difference
var/increments// = difference/10 //find how many increments apart they are
if(difference > 50)
increments = difference / 5
else
increments = difference / 10
var/change = increments * boost // Get the amount to change by (x per increment)
var/temp_change
if(current < loc_temp)
temperature = min(loc_temp, temperature+change)
else if(current > loc_temp)
temperature = max(loc_temp, temperature-change)
temp_change = (temperature - current)
return temp_change
/mob/living/simple_animal/slime/handle_status_effects()
..()
if(prob(30) && !stat)
adjustBruteLoss(-1)
/mob/living/simple_animal/slime/proc/handle_feeding()
if(!ismob(buckled))
return
var/mob/M = buckled
if(stat)
Feedstop(silent = TRUE)
if(M.stat == DEAD) // our victim died
if(!client)
if(!rabid && !attacked)
if(M.LAssailant && M.LAssailant != M)
if(prob(50))
if(!(M.LAssailant in Friends))
Friends[M.LAssailant] = 1
else
++Friends[M.LAssailant]
else
to_chat(src, "<i>This subject does not have a strong enough life energy anymore...</i>")
if(M.client && ishuman(M))
if(prob(85))
rabid = 1 //we go rabid after finishing to feed on a human with a client.
Feedstop()
return
if(iscarbon(M))
var/mob/living/carbon/C = M
C.adjustCloneLoss(rand(2, 4))
C.adjustToxLoss(rand(1, 2))
if(prob(10) && C.client)
to_chat(C, "<span class='userdanger'>[pick("You can feel your body becoming weak!", \
"You feel like you're about to die!", \
"You feel every part of your body screaming in agony!", \
"A low, rolling pain passes through your body!", \
"Your body feels as if it's falling apart!", \
"You feel extremely weak!", \
"A sharp, deep pain bathes every inch of your body!")]</span>")
else if(isanimal(M))
var/mob/living/simple_animal/SA = M
var/totaldamage = 0 //total damage done to this unfortunate animal
totaldamage += SA.adjustCloneLoss(rand(2, 4))
totaldamage += SA.adjustToxLoss(rand(1, 2))
if(totaldamage <= 0) //if we did no(or negative!) damage to it, stop
Feedstop(0, 0)
return
else
Feedstop(0, 0)
return
add_nutrition(rand(7, 15))
//Heal yourself.
adjustBruteLoss(-3)
/mob/living/simple_animal/slime/proc/handle_nutrition()
if(docile) //God as my witness, I will never go hungry again
set_nutrition(700) //fuck you for using the base nutrition var
return
if(prob(15))
adjust_nutrition(-(1 + is_adult))
if(nutrition <= 0)
set_nutrition(0)
if(prob(75))
adjustBruteLoss(rand(0, 5))
else if(nutrition >= get_grow_nutrition() && amount_grown < SLIME_EVOLUTION_THRESHOLD)
adjust_nutrition(-20)
amount_grown++
update_action_buttons_icon()
if(amount_grown >= SLIME_EVOLUTION_THRESHOLD && !buckled && !Target && !ckey)
if(is_adult)
Reproduce()
else
Evolve()
/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())
if(powerlevel<10)
if(prob(30-powerlevel*2))
powerlevel++
else if(nutrition >= get_hunger_nutrition() + 100) //can't get power levels unless you're a bit above hunger level.
if(powerlevel<5)
if(prob(25-powerlevel*5))
powerlevel++
/mob/living/simple_animal/slime/proc/handle_targets()
update_canmove()
if(Tempstun)
if(!buckled) // not while they're eating!
canmove = 0
else
canmove = 1
if(attacked > 50)
attacked = 50
if(attacked > 0)
attacked--
if(Discipline > 0)
if(Discipline >= 5 && rabid)
if(prob(60))
rabid = 0
if(prob(10))
Discipline--
if(!client)
if(!canmove)
return
if(buckled)
return // if it's eating someone already, continue eating!
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
Target = null
if(AIproc && SStun > world.time)
return
var/hungry = 0 // determines if the slime is hungry
if (nutrition < get_starve_nutrition())
hungry = 2
else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
hungry = 1
if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends
if(Friends.len > 0 && prob(1))
var/mob/nofriend = pick(Friends)
--Friends[nofriend]
if(!Target)
if(will_hunt() && hungry || attacked || rabid) // Only add to the list if we need to
var/list/targets = list()
for(var/mob/living/L in view(7,src))
if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs
continue
if(L in Friends) // No eating friends!
continue
var/ally = FALSE
for(var/F in faction)
if(F == "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)) // 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.
continue
targets += L // Possible target found!
if(targets.len > 0)
if(attacked || rabid || hungry == 2)
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 && prob(5))
if(ishuman(C) || isalienadult(C))
Target = C
break
if(islarva(C) || issmall(C))
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 - 1, 0)
else if(canmove && isturf(loc))
step_to(src, Leader)
else if(hungry)
if (holding_still)
holding_still = max(holding_still - hungry, 0)
else if(canmove && isturf(loc) && prob(50))
step(src, pick(cardinal))
else
if(holding_still)
holding_still = max(holding_still - 1, 0)
else if (docile && pulledby)
holding_still = 10
else if(canmove && isturf(loc) && prob(33))
step(src, pick(cardinal))
else if(!AIproc)
INVOKE_ASYNC(src, .proc/AIprocess)
/mob/living/simple_animal/slime/handle_automated_movement()
return //slime random movement is currently handled in handle_targets()
/mob/living/simple_animal/slime/handle_automated_speech()
return //slime random speech is currently handled in handle_speech()
/mob/living/simple_animal/slime/proc/handle_mood()
var/newmood = ""
if (rabid || attacked)
newmood = "angry"
else if (docile)
newmood = ":3"
else if (Target)
newmood = "mischievous"
if (!newmood)
if (Discipline && prob(25))
newmood = "pout"
else if (prob(1))
newmood = pick("sad", ":3", "pout")
if ((mood == "sad" || mood == ":3" || mood == "pout") && !newmood)
if(prob(75))
newmood = mood
if(newmood != mood) // This is so we don't redraw them every time
mood = newmood
regenerate_icons()
/mob/living/simple_animal/slime/proc/handle_speech()
//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, "hello") || findtext(phrase, "hi"))
to_say = pick("Hello...", "Hi...")
else if(findtext(phrase, "follow"))
if(Leader)
if(Leader == who) // Already following him
to_say = pick("Yes...", "Lead...", "Follow...")
else if(Friends[who] > Friends[Leader]) // VIVA
Leader = who
to_say = "Yes... I follow [who]..."
else
to_say = "No... I follow [Leader]..."
else
if(Friends[who] >= SLIME_FRIENDSHIP_FOLLOW)
Leader = who
to_say = "I follow..."
else // Not friendly enough
to_say = pick("No...", "I no follow...")
else if(findtext(phrase, "stop"))
if(buckled) // We are asked to stop feeding
if (Friends[who] >= SLIME_FRIENDSHIP_STOPEAT)
Feedstop()
Target = null
if (Friends[who] < SLIME_FRIENDSHIP_STOPEAT_NOANGRY)
--Friends[who]
to_say = "Grrr..." // I'm angry but I do it
else
to_say = "Fine..."
else if(Target) // We are asked to stop chasing
if(Friends[who] >= SLIME_FRIENDSHIP_STOPCHASE)
Target = null
if(Friends[who] < SLIME_FRIENDSHIP_STOPCHASE_NOANGRY)
--Friends[who]
to_say = "Grrr..." // I'm angry but I do it
else
to_say = "Fine..."
else if(Leader) // We are asked to stop following
if(Leader == who)
to_say = "Yes... I stay..."
Leader = null
else
if(Friends[who] > Friends[Leader])
Leader = null
to_say = "Yes... I stop..."
else
to_say = "No... keep follow..."
else if(findtext(phrase, "stay"))
if(Leader)
if (Leader == who)
holding_still = Friends[who] * 10
to_say = "Yes... stay..."
else if(Friends[who] > Friends[Leader])
holding_still = (Friends[who] - Friends[Leader]) * 10
to_say = "Yes... stay..."
else
to_say = "No... keep follow..."
else
if(Friends[who] >= SLIME_FRIENDSHIP_STAY)
holding_still = Friends[who] * 10
to_say = "Yes... stay..."
else
to_say = "No... won't stay..."
else if(findtext(phrase, "attack"))
if(rabid && prob(20))
Target = who
AIprocess() //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"
--Friends[who] //Don't ask a slime to attack its friend
else if(!Friends[L] || Friends[L] < 1)
Target = L
AIprocess()//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] ..."
--Friends[who] //Don't ask a slime to attack its friend
break
else
to_say = "No... no listen"
speech_buffer = list()
//Speech starts here
if(to_say)
say (to_say)
else if(prob(1))
emote(pick("bounce", "sway", "light", "vibrate", "jiggle"))
else
var/t = 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)
++slimes_near
if (L.stat == DEAD)
++dead_slimes
if(L in Friends)
t += 20
friends_near += L
if(nutrition < get_hunger_nutrition())
t += 10
if(nutrition < get_starve_nutrition())
t += 10
if(prob(2) && prob(t))
var/phrases = list()
if(Target)
phrases += "[Target]... look yummy..."
if(nutrition < get_starve_nutrition())
phrases += "So... hungry..."
phrases += "Very... hungry..."
phrases += "Need... food..."
phrases += "Must... eat..."
else if(nutrition < get_hunger_nutrition())
phrases += "Hungry..."
phrases += "Where food?"
phrases += "I want to eat..."
phrases += "Rawr..."
phrases += "Blop..."
phrases += "Blorble..."
if(rabid || attacked)
phrases += "Hrr..."
phrases += "Nhuu..."
phrases += "Unn..."
if(mood == ":3")
phrases += "Purr..."
if(attacked)
phrases += "Grrr..."
if(bodytemperature < T0C)
phrases += "Cold..."
if(bodytemperature < T0C - 30)
phrases += "So... cold..."
phrases += "Very... cold..."
if(bodytemperature < T0C - 50)
phrases += "..."
phrases += "C... c..."
if(buckled)
phrases += "Nom..."
phrases += "Yummy..."
if(powerlevel > 3)
phrases += "Bzzz..."
if(powerlevel > 5)
phrases += "Zap..."
if(powerlevel > 8)
phrases += "Zap... Bzz..."
if(mood == "sad")
phrases += "Bored..."
if(slimes_near)
phrases += "Slime friend..."
if(slimes_near > 1)
phrases += "Slime friends..."
if(dead_slimes)
phrases += "What happened?"
if(!slimes_near)
phrases += "Lonely..."
for(var/M in friends_near)
phrases += "[M]... friend..."
if(nutrition < get_hunger_nutrition())
phrases += "[M]... feed me..."
if(!stat)
say (pick(phrases))
/mob/living/simple_animal/slime/proc/get_max_nutrition() // Can't go above it
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
if(is_adult)
return 1000
else
return 800
/mob/living/simple_animal/slime/proc/get_hunger_nutrition() // Below it we will always eat
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
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
if(docile)
return 0
if(hunger == 2 || rabid || attacked)
return 1
if(Leader)
return 0
if(holding_still)
return 0
return 1
@@ -0,0 +1,215 @@
#define SIZE_DOESNT_MATTER -1
#define BABIES_ONLY 0
#define ADULTS_ONLY 1
#define NO_GROWTH_NEEDED 0
#define GROWTH_NEEDED 1
/datum/action/innate/slime
check_flags = AB_CHECK_CONSCIOUS
icon_icon = 'icons/mob/actions/actions_slime.dmi'
background_icon_state = "bg_alien"
var/needs_growth = NO_GROWTH_NEEDED
/datum/action/innate/slime/IsAvailable()
if(..())
var/mob/living/simple_animal/slime/S = owner
if(needs_growth == GROWTH_NEEDED)
if(S.amount_grown >= SLIME_EVOLUTION_THRESHOLD)
return 1
return 0
return 1
/mob/living/simple_animal/slime/verb/Feed()
set category = "Slime"
set desc = "This will let you feed on any valid creature in the surrounding area. This should also be used to halt the feeding process."
if(stat)
return 0
var/list/choices = list()
for(var/mob/living/C in view(1,src))
if(C!=src && Adjacent(C))
choices += C
var/mob/living/M = input(src,"Who do you wish to feed on?") in null|choices
if(!M)
return 0
if(CanFeedon(M))
Feedon(M)
return 1
/datum/action/innate/slime/feed
name = "Feed"
button_icon_state = "slimeeat"
/datum/action/innate/slime/feed/Activate()
var/mob/living/simple_animal/slime/S = owner
S.Feed()
/mob/living/simple_animal/slime/proc/CanFeedon(mob/living/M, silent = FALSE)
if(!Adjacent(M))
return FALSE
if(buckled)
Feedstop()
return FALSE
if(issilicon(M))
return FALSE
if(isanimal(M))
var/mob/living/simple_animal/S = M
if(S.damage_coeff[TOX] <= 0 && S.damage_coeff[CLONE] <= 0) //The creature wouldn't take any damage, it must be too weird even for us.
if(silent)
return FALSE
to_chat(src, "<span class='warning'>[pick("This subject is incompatible", \
"This subject does not have life energy", "This subject is empty", \
"I am not satisified", "I can not feed from this subject", \
"I do not feel nourished", "This subject is not food")]!</span>")
return FALSE
if(isslime(M))
if(silent)
return FALSE
to_chat(src, "<span class='warning'><i>I can't latch onto another slime...</i></span>")
return FALSE
if(docile)
if(silent)
return FALSE
to_chat(src, "<span class='notice'><i>I'm not hungry anymore...</i></span>")
return FALSE
if(stat)
if(silent)
return FALSE
to_chat(src, "<span class='warning'><i>I must be conscious to do this...</i></span>")
return FALSE
if(M.stat == DEAD)
if(silent)
return FALSE
to_chat(src, "<span class='warning'><i>This subject does not have a strong enough life energy...</i></span>")
return FALSE
if(locate(/mob/living/simple_animal/slime) in M.buckled_mobs)
if(silent)
return FALSE
to_chat(src, "<span class='warning'><i>Another slime is already feeding on this subject...</i></span>")
return FALSE
return TRUE
/mob/living/simple_animal/slime/proc/Feedon(mob/living/M)
M.unbuckle_all_mobs(force = TRUE) //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 class='danger'>[name] has latched onto [M]!</span>", \
"<span class='userdanger'>[name] has latched onto [M]!</span>")
else
to_chat(src, "<span class='warning'><i>I have failed to latch onto the subject!</i></span>")
/mob/living/simple_animal/slime/proc/Feedstop(silent = FALSE, living = 1)
if(buckled)
if(!living)
to_chat(src, "<span class='warning'>[pick("This subject is incompatible", \
"This subject does not have life energy", "This subject is empty", \
"I am not satisified", "I can not feed from this subject", \
"I do not feel nourished", "This subject is not food")]!</span>")
if(!silent)
visible_message("<span class='warning'>[src] has let go of [buckled]!</span>", \
"<span class='notice'><i>I stopped feeding.</i></span>")
layer = initial(layer)
buckled.unbuckle_mob(src,force=TRUE)
/mob/living/simple_animal/slime/verb/Evolve()
set category = "Slime"
set desc = "This will let you evolve from baby to adult slime."
if(stat)
to_chat(src, "<i>I must be conscious to do this...</i>")
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)
regenerate_icons()
update_name()
else
to_chat(src, "<i>I am not ready to evolve yet...</i>")
else
to_chat(src, "<i>I have already evolved...</i>")
/datum/action/innate/slime/evolve
name = "Evolve"
button_icon_state = "slimegrow"
needs_growth = GROWTH_NEEDED
/datum/action/innate/slime/evolve/Activate()
var/mob/living/simple_animal/slime/S = owner
S.Evolve()
if(S.is_adult)
var/datum/action/innate/slime/reproduce/A = new
A.Grant(S)
/mob/living/simple_animal/slime/verb/Reproduce()
set category = "Slime"
set desc = "This will make you split into four Slimes."
if(stat)
to_chat(src, "<i>I must be conscious to do this...</i>")
return
if(is_adult)
if(amount_grown >= SLIME_EVOLUTION_THRESHOLD)
if(stat)
to_chat(src, "<i>I must be conscious to do this...</i>")
return
var/list/babies = list()
var/new_nutrition = round(nutrition * 0.9)
var/new_powerlevel = round(powerlevel / 4)
for(var/i=1,i<=4,i++)
var/child_colour
if(mutation_chance >= 100)
child_colour = "rainbow"
else if(prob(mutation_chance))
child_colour = slime_mutation[rand(1,4)]
else
child_colour = colour
var/mob/living/simple_animal/slime/M
M = new(loc, child_colour)
if(ckey)
M.set_nutrition(new_nutrition) //Player slimes are more robust at spliting. Once an oversight of poor copypasta, now a feature!
M.powerlevel = new_powerlevel
if(i != 1)
step_away(M,src)
M.Friends = Friends.Copy()
babies += M
M.mutation_chance = Clamp(mutation_chance+(rand(5,-5)),0,100)
feedback_add_details("slime_babies_born", "slimebirth_[replacetext(M.colour," ","_")]")
var/mob/living/simple_animal/slime/new_slime = pick(babies)
new_slime.a_intent = INTENT_HARM
if(src.mind)
src.mind.transfer_to(new_slime)
else
new_slime.key = src.key
qdel(src)
else
to_chat(src, "<i>I am not ready to reproduce yet...</i>")
else
to_chat(src, "<i>I am not old enough to reproduce yet...</i>")
/datum/action/innate/slime/reproduce
name = "Reproduce"
button_icon_state = "slimesplit"
needs_growth = GROWTH_NEEDED
/datum/action/innate/slime/reproduce/Activate()
var/mob/living/simple_animal/slime/S = owner
S.Reproduce()
@@ -0,0 +1,18 @@
/mob/living/simple_animal/slime/say_quote(text, datum/language/speaking)
var/verb = "blorbles"
var/ending = copytext(text, length(text))
if(ending == "?")
verb = "inquisitively blorbles"
else if(ending == "!")
verb = "loudly blorbles"
return verb
/mob/living/simple_animal/slime/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol)
if(speaker != src && !stat)
if(speaker in Friends)
speech_buffer = list()
speech_buffer.Add(speaker)
speech_buffer.Add(lowertext(html_decode(multilingual_to_message(message_pieces))))
..()
@@ -0,0 +1,505 @@
/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")
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
// 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 = CANPARALYSE | CANPUSH
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
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)
add_language("Bubblish")
/mob/living/simple_animal/slime/Destroy()
for(var/A in actions)
var/datum/action/AC = A
AC.Remove(src)
for(var/obj/machinery/computer/camera_advanced/xenobio/X in GLOB.machines)
if(src in X.stored_slimes)
X.stored_slimes -= src
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/movement_delay()
if(bodytemperature >= 330.23) // 135 F or 57.08 C
return -1 // slimes become supercharged at high temperatures
. = ..()
var/health_deficiency = (maxHealth - health)
if(health_deficiency >= 45)
. += (health_deficiency / 25)
if(bodytemperature < 183.222)
. += (283.222 - bodytemperature) / 10 * 1.75
if(reagents)
if(reagents.has_reagent("morphine")) // morphine slows slimes down
. *= 2
if(reagents.has_reagent("frostoil")) // Frostoil also makes them move VEEERRYYYYY slow
. *= 5
if(health <= 0) // if damaged, the slime moves twice as slow
. *= 2
. += config.slime_delay
/mob/living/simple_animal/slime/handle_hud_icons_health()
if(hud_used)
if(!client)
return
if(healths)
var/severity = 0
var/healthpercent = (health / maxHealth) * 100
switch(healthpercent)
if(100 to INFINITY)
healths.icon_state = "slime_health0"
if(80 to 100)
healths.icon_state = "slime_health1"
severity = 1
if(60 to 80)
healths.icon_state = "slime_health2"
severity = 2
if(40 to 60)
healths.icon_state = "slime_health3"
severity = 3
if(20 to 40)
healths.icon_state = "slime_health4"
severity = 4
if(1 to 20)
healths.icon_state = "slime_health5"
severity = 5
else
healths.icon_state = "slime_health7"
severity = 6
if(severity > 0)
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
/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 = TRUE
addtimer(VARSET_CALLBACK(src, Atkcool, FALSE), 4.5 SECONDS)
/mob/living/simple_animal/slime/Process_Spacemove(movement_dir = 0)
return 2
/mob/living/simple_animal/slime/Stat()
if(..())
if(!docile)
stat(null, "Nutrition: [nutrition]/[get_max_nutrition()]")
if(amount_grown >= SLIME_EVOLUTION_THRESHOLD)
if(is_adult)
stat(null, "You can reproduce!")
else
stat(null, "You can evolve!")
if(stat == UNCONSCIOUS)
stat(null,"You are knocked out by high levels of BZ!")
else
stat(null,"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)
if(!Proj)
return
attacked += 10
if((Proj.damage_type == BURN))
adjustBruteLoss(-abs(Proj.damage)) //fire projectiles heals slimes.
Proj.on_hit(src)
else
..(Proj)
return FALSE
/mob/living/simple_animal/slime/emp_act(severity)
..()
powerlevel = 0 // oh no, the power!
/mob/living/simple_animal/slime/MouseDrop(atom/movable/A)
if(isliving(A) && A != src && usr == src)
var/mob/living/Food = A
if(CanFeedon(Food))
Feedon(Food)
return ..()
/mob/living/simple_animal/slime/unEquip(obj/item/I)
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 class='danger'>[M] pulls [src] off!</span>", \
"<span class='danger'>You pull [src] off!</span>")
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_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)
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))
M.visible_message("<span class='warning'>[M] attempts to wrestle \the [name] off!</span>", \
"<span class='danger'>You attempt to wrestle \the [name] off!</span>")
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, TRUE, -1)
else
M.visible_message("<span class='warning'>[M] manages to wrestle \the [name] off!</span>", \
"<span class='notice'>You manage to wrestle \the [name] off!</span>")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
discipline_slime(M)
else
if(prob(30))
buckled.visible_message("<span class='warning'>[M] attempts to wrestle \the [name] off of [buckled]!</span>", \
"<span class='warning'>[M] attempts to wrestle \the [name] off of you!</span>")
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, TRUE, -1)
else
buckled.visible_message("<span class='warning'>[M] manages to wrestle \the [name] off of [buckled]!</span>", \
"<span class='notice'>[M] manage to wrestle \the [name] off of you!</span>")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -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, src))
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/I, 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, src))
return 1
if(istype(I, /obj/item/stack/sheet/mineral/plasma) && !stat) //Let's you feed slimes plasma.
if(user in Friends)
++Friends[user]
else
Friends[user] = 1
to_chat(user, "<span class='notice'>You feed the slime the plasma. It chirps happily.</span>")
var/obj/item/stack/sheet/mineral/plasma/S = I
S.use(1)
return
if(I.force > 0)
attacked += 10
if(prob(25))
user.do_attack_animation(src)
user.changeNext_move(CLICK_CD_MELEE)
to_chat(user, "<span class='danger'>[I] passes right through [src]!</span>")
return
if(Discipline && prob(50)) // wow, buddy, why am I getting attacked??
Discipline = 0
if(I.force >= 3)
var/force_effect = 2 * I.force
if(is_adult)
force_effect = round(I.force / 2)
if(prob(10 + force_effect))
discipline_slime(user)
/* if(istype(I, /obj/item/storage/bag/bio))
var/obj/item/storage/P = I
if(!effectmod)
to_chat(user, "<span class='warning'>The slime is not currently being mutated.</span>")
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 class='notice'>You feed the slime as many of the extracts from the bag as you can, and it mutates!</span>")
playsound(src, 'sound/effects/attackblob.ogg', 50, TRUE)
spawn_corecross()
hasOutput = TRUE
break
if(!hasOutput)
if(!hasFound)
to_chat(user, "<span class='warning'>There are no extracts in the bag that this slime will accept!</span>")
else
to_chat(user, "<span class='notice'>You feed the slime some extracts from the bag.</span>")
playsound(src, 'sound/effects/attackblob.ogg', 50, TRUE)
return */
..()
/*
/mob/living/simple_animal/slime/proc/spawn_corecross()
var/static/list/crossbreeds = subtypesof(/obj/item/slimecross)
visible_message("<span class='danger'>[src] shudders, its mutated core consuming the rest of its body!</span>")
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
break
if(crosspath)
new crosspath(loc)
else
visible_message("<span class='warning'>The mutated core shudders, and collapses into a puddle, unable to maintain its form.</span>")
qdel(src)
*/
/mob/living/simple_animal/slime/water_act(volume, temperature, source, method = TOUCH)
. = ..()
var/water_damage = rand(10, 15) * volume
adjustBruteLoss(water_damage)
if(!client && Target && volume >= 3) // Like cats
Target = null
++Discipline
/mob/living/simple_animal/slime/examine(mob/user)
to_chat(user, "<span class='info'>*---------*\nThis is [bicon(src)] \a <EM>[src]</EM>!")
if(stat == DEAD)
to_chat(user, "<span class='deadsay'>It is limp and unresponsive.</span>")
else
if(stat == UNCONSCIOUS) // Slime stasis
to_chat(user, "<span class='deadsay'>It appears to be alive but unresponsive.</span>")
if(getBruteLoss())
to_chat(user, "<span class='warning'>")
if (getBruteLoss() < 40)
to_chat(user, "It has some punctures in its flesh!")
else
to_chat(user, "<B>It has severe punctures and tears in its flesh!</B>")
to_chat(user, "</span>\n")
switch(powerlevel)
if(2 to 3)
to_chat(user, "It is flickering gently with a little electrical activity.")
if(4 to 5)
to_chat(user, "It is glowing gently with moderate levels of electrical activity.")
if(6 to 9)
to_chat(user, "<span class='warning'>It is glowing brightly with high levels of electrical activity.</span>")
if(10)
to_chat(user, "<span class='warning'><B>It is radiating with massive levels of electrical activity!</B></span>")
to_chat(user, "*---------*</span>")
/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
if(Target)
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)
canmove = FALSE
if(user)
step_away(src,user,15)
sleep(3)
if(user)
step_away(src,user,15)
update_canmove()
/mob/living/simple_animal/slime/pet
docile = TRUE
/mob/living/simple_animal/slime/can_unbuckle()
return FALSE
/mob/living/simple_animal/slime/can_buckle()
return FALSE
/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/handle_ventcrawl(atom/A)
if(buckled)
to_chat(src, "<i>I can't vent crawl while feeding...</i>")
return
..()
@@ -1,4 +1,4 @@
proc/mutation_table(var/colour)
/mob/living/simple_animal/slime/proc/mutation_table(colour)
var/list/slime_mutation[4]
switch(colour)
//Tier 1
@@ -76,4 +76,4 @@ proc/mutation_table(var/colour)
slime_mutation[2] = colour
slime_mutation[3] = colour
slime_mutation[4] = colour
return(slime_mutation)
return(slime_mutation)
+12 -15
View File
@@ -135,41 +135,38 @@
qdel(src)
return
/mob/living/carbon/human/proc/slimeize(adult as num, reproduce as num)
/mob/living/carbon/human/proc/slimeize(reproduce as num)
if(notransform)
return
for(var/obj/item/W in src)
unEquip(W)
notransform = TRUE
canmove = FALSE
for(var/obj/item/I in src)
unEquip(I)
regenerate_icons()
notransform = 1
canmove = 0
icon = null
invisibility = 101
invisibility = INVISIBILITY_MAXIMUM
for(var/t in bodyparts)
qdel(t)
var/mob/living/carbon/slime/new_slime
var/mob/living/simple_animal/slime/new_slime
if(reproduce)
var/number = pick(14;2,3,4) //reproduce (has a small chance of producing 3 or 4 offspring)
var/list/babies = list()
for(var/i=1,i<=number,i++)
var/mob/living/carbon/slime/M = new/mob/living/carbon/slime(loc)
var/mob/living/simple_animal/slime/M = new/mob/living/simple_animal/slime(loc)
M.set_nutrition(round(nutrition / number))
step_away(M,src)
babies += M
new_slime = pick(babies)
else
new_slime = new /mob/living/carbon/slime(loc)
if(adult)
new_slime.is_adult = 1
else
new_slime = new /mob/living/simple_animal/slime(loc)
new_slime.a_intent = INTENT_HARM
new_slime.key = key
to_chat(new_slime, "<B>You are now a slime. Skreee!</B>")
new_slime.update_pipe_vision()
spawn(0)//To prevent the proc from returning null.
qdel(src)
return
. = new_slime
qdel(src)
/mob/living/carbon/human/proc/corgize()
if(notransform)
+1 -1
View File
@@ -202,7 +202,7 @@
if(ishuman(M))
Robot.mmi.transfer_identity(M) //Does not transfer key/client.
if("slime")
new_mob = new /mob/living/carbon/slime/random(M.loc)
new_mob = new /mob/living/simple_animal/slime/random(M.loc)
new_mob.universal_speak = TRUE
if("xeno")
if(prob(50))
+13 -1
View File
@@ -74,6 +74,18 @@ var/const/INGEST = 2
handle_reactions()
return total_transfered
/datum/reagents/proc/remove_all(amount = 1)
var/list/cached_reagents = reagent_list
if(total_volume > 0)
var/part = amount / total_volume
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
remove_reagent(R.id, R.volume * part)
update_total()
handle_reactions()
return amount
/datum/reagents/proc/get_master_reagent()
var/the_reagent = null
var/the_volume = 0
@@ -803,7 +815,7 @@ var/const/INGEST = 2
if(!R.taste_mult)
continue
//nutriment carries a list of tastes that originates from the snack food that the nutriment came from
if(istype(R, /datum/reagent/consumable/nutriment))
if(istype(R, /datum/reagent/consumable/nutriment))
var/list/nutriment_taste_data = R.data
for(var/nutriment_taste in nutriment_taste_data)
var/ratio = nutriment_taste_data[nutriment_taste]
@@ -279,8 +279,8 @@
/datum/reagent/consumable/frostoil/reaction_turf(turf/T, volume)
if(volume >= 5)
for(var/mob/living/carbon/slime/M in T)
M.adjustToxLoss(rand(15,30))
for(var/mob/living/simple_animal/slime/M in T)
M.adjustToxLoss(rand(15, 30))
/datum/reagent/consumable/sodiumchloride
name = "Salt"
@@ -356,7 +356,7 @@
if(volume >= 3)
T.MakeSlippery(TURF_WET_ICE)
if(volume >= 5)
for(var/mob/living/carbon/slime/M in T)
for(var/mob/living/simple_animal/slime/M in T)
M.adjustToxLoss(rand(15,30))
/datum/reagent/pyrosium
@@ -76,8 +76,8 @@
if(floor_only)
T.clean_blood()
for(var/mob/living/carbon/slime/M in T)
M.adjustToxLoss(rand(5,10))
for(var/mob/living/simple_animal/slime/M in T)
M.adjustToxLoss(rand(5, 10))
if(istype(T, /turf/simulated))
var/turf/simulated/S = T
S.dirt = 0
@@ -11,9 +11,8 @@
/datum/chemical_reaction/slimespawn/on_reaction(datum/reagents/holder)
feedback_add_details("slime_cores_used","[type]")
var/mob/living/carbon/slime/S = new /mob/living/carbon/slime
S.forceMove(get_turf(holder.my_atom))
S.visible_message("<span class='danger'>Infused with plasma, the core begins to quiver and grow, and soon a new baby slime emerges from it!</span>")
var/mob/living/simple_animal/slime/S = new(get_turf(holder.my_atom), "grey")
S.visible_message("<span class='danger'>Infused with plasma, the core begins to quiver and grow, and a new baby slime emerges from it!</span>")
/datum/chemical_reaction/slimeinaprov
name = "Slime epinephrine"
@@ -425,7 +424,12 @@
/datum/chemical_reaction/slimebloodlust/on_reaction(datum/reagents/holder)
feedback_add_details("slime_cores_used","[type]")
for(var/mob/living/carbon/slime/slime in viewers(get_turf(holder.my_atom), null))
for(var/mob/living/simple_animal/slime/slime in viewers(get_turf(holder.my_atom), null))
if(slime.docile) //Undoes docility, but doesn't make rabid.
slime.visible_message("<span class='danger'>[slime] forgets its training, becoming wild once again!</span>")
slime.docile = FALSE
slime.update_name()
continue
slime.rabid = 1
slime.visible_message("<span class='danger'>The [slime] is driven into a frenzy!</span>")
@@ -667,9 +671,8 @@
/datum/chemical_reaction/slimeRNG/on_reaction(datum/reagents/holder)
feedback_add_details("slime_cores_used","[type]")
var/mob/living/carbon/slime/random/S = new /mob/living/carbon/slime/random
S.forceMove(get_turf(holder.my_atom))
S.visible_message("<span class='danger'>Infused with plasma, the core begins to quiver and grow, and soon a new baby slime emerges from it!</span>")
var/mob/living/simple_animal/slime/random/S = new (get_turf(holder.my_atom))
S.visible_message("<span class='danger'>Infused with plasma, the core begins to quiver and grow, and a new baby slime emerges from it!</span>")
/datum/chemical_reaction/slime_transfer
name = "Transfer Potion"
+1 -1
View File
@@ -175,7 +175,7 @@
// mouse drop another mob or self
//
/obj/machinery/disposal/MouseDrop_T(mob/target, mob/user)
if(!istype(target) || target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || istype(user, /mob/living/silicon/ai))
if(!istype(target) || target.buckled || target.has_buckled_mobs() || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || istype(user, /mob/living/silicon/ai))
return
if(isanimal(user) && target != user) return //animals cannot put mobs other than themselves into disposal
src.add_fingerprint(user)
@@ -48,7 +48,7 @@
/obj/machinery/computer/camera_advanced/xenobio/Destroy()
QDEL_NULL(current_potion)
for(var/mob/living/carbon/slime/S in stored_slimes)
for(var/mob/living/simple_animal/slime/S in stored_slimes)
S.forceMove(drop_location())
stored_slimes.Cut()
return ..()
@@ -173,7 +173,7 @@
var/obj/machinery/computer/camera_advanced/xenobio/X = target
if(cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/carbon/slime/S in X.stored_slimes)
for(var/mob/living/simple_animal/slime/S in X.stored_slimes)
S.forceMove(remote_eye.loc)
S.visible_message("[S] warps in!")
X.stored_slimes -= S
@@ -192,14 +192,13 @@
var/obj/machinery/computer/camera_advanced/xenobio/X = target
if(cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/carbon/slime/S in 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.buckled.unbuckle_mob(S, force = TRUE)
S.Feedstop()
S.visible_message("[S] vanishes in a flash of light!")
S.Feedstop(silent = TRUE)
S.visible_message("<span class='notice'>[S] vanishes in a flash of light!</span>")
S.forceMove(X)
X.stored_slimes += S
else
@@ -265,7 +264,7 @@
var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control
if(cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/carbon/slime/S in remote_eye.loc)
for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
slime_scan(S, C)
else
to_chat(owner, "<span class='warning'>Target is not near a camera. Cannot proceed.</span>")
@@ -287,7 +286,7 @@
return
if(cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/carbon/slime/S in remote_eye.loc)
for(var/mob/living/simple_animal/slime/S in remote_eye.loc)
X.current_potion.attack(S, C)
break
else
@@ -310,17 +309,17 @@
// Alternate clicks for slime, monkey and open turf if using a xenobio console
// Scans slime
/mob/living/carbon/slime/CtrlClick(mob/user)
/mob/living/simple_animal/slime/CtrlClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_CTRL, src)
..()
//Feeds a potion to slime
/mob/living/carbon/slime/AltClick(mob/user)
/mob/living/simple_animal/slime/AltClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_ALT, src)
..()
//Picks up slime
/mob/living/carbon/slime/ShiftClick(mob/user)
/mob/living/simple_animal/slime/ShiftClick(mob/user)
SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_SHIFT, src)
..()
@@ -341,7 +340,7 @@
..()
// Scans slime
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickCtrl(mob/living/user, mob/living/carbon/slime/S)
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickCtrl(mob/living/user, mob/living/simple_animal/slime/S)
if(!cameranet.checkTurfVis(S.loc))
to_chat(user, "<span class='warning'>Target is not near a camera. Cannot proceed.</span>")
return
@@ -352,7 +351,7 @@
slime_scan(S, C)
//Feeds a potion to slime
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickAlt(mob/living/user, mob/living/carbon/slime/S)
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickAlt(mob/living/user, mob/living/simple_animal/slime/S)
if(!cameranet.checkTurfVis(S.loc))
to_chat(user, "<span class='warning'>Target is not near a camera. Cannot proceed.</span>")
return
@@ -367,7 +366,7 @@
X.current_potion.attack(S, C)
//Picks up slime
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/carbon/slime/S)
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/simple_animal/slime/S)
if(!cameranet.checkTurfVis(S.loc))
to_chat(user, "<span class='warning'>Target is not near a camera. Cannot proceed.</span>")
return
@@ -377,14 +376,16 @@
var/area/mobarea = get_area(S.loc)
if(mobarea.name == E.allowed_area || mobarea.xenobiology_compatible)
if(X.stored_slimes.len >= X.max_slimes)
to_chat(C, "<span class='warning'>Slime storage is full.</span>")
return
if(!S.ckey)
if(S.buckled)
S.buckled.unbuckle_mob(S, force = TRUE)
S.Feedstop()
S.visible_message("[S] vanishes in a flash of light!")
S.forceMove(X)
X.stored_slimes += S
if(S.ckey)
to_chat(C, "<span class='warning'>The slime wiggled free!</span>")
return
if(S.buckled)
S.Feedstop(silent = TRUE)
S.visible_message("<span class='notice'>[S] vanishes in a flash of light!</span>")
S.forceMove(X)
X.stored_slimes += S
//Place slimes
/obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickShift(mob/living/user, turf/T)
@@ -396,9 +397,9 @@
var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
var/area/turfarea = get_area(T)
if(turfarea.name == E.allowed_area || turfarea.xenobiology_compatible)
for(var/mob/living/carbon/slime/S in X.stored_slimes)
for(var/mob/living/simple_animal/slime/S in X.stored_slimes)
S.forceMove(T)
S.visible_message("[S] warps in!")
S.visible_message("<span class='notice'>[S] warps in!</span>")
X.stored_slimes -= S
//Place monkey
@@ -139,7 +139,7 @@
icon_state = "bottle19"
var/being_used = 0
/obj/item/slimepotion/slime/docility/attack(mob/living/carbon/slime/M, mob/user)
/obj/item/slimepotion/slime/docility/attack(mob/living/simple_animal/slime/M, mob/user)
if(!isslime(M))
to_chat(user, "<span class='warning'>The potion only works on slimes!</span>")
return
@@ -149,7 +149,12 @@
if(being_used)
to_chat(user, "<span class='warning'>You're already using this on another slime!</span>")
return
if(M.rabid) //Stops being rabid, but doesn't become truly docile.
to_chat(M, "<span class='warning'>You absorb the potion, and your rabid hunger finally settles to a normal desire to feed.</span>")
to_chat(user, "<span class='notice'>You feed the slime the potion, calming its rabid rage.</span>")
M.rabid = FALSE
qdel(src)
return
M.docile = 1
M.set_nutrition(700)
to_chat(M, "<span class='warning'>You absorb the potion and feel your intense desire to feed melt away.</span>")
@@ -272,7 +277,7 @@
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
/obj/item/slimepotion/slime/steroid/attack(mob/living/carbon/slime/M, mob/user)
/obj/item/slimepotion/slime/steroid/attack(mob/living/simple_animal/slime/M, mob/user)
if(!isslime(M))//If target is not a slime.
to_chat(user, "<span class='warning'>The steroid only works on baby slimes!</span>")
return ..()
@@ -302,7 +307,7 @@
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle15"
/obj/item/slimepotion/slime/stabilizer/attack(mob/living/carbon/slime/M, mob/user)
/obj/item/slimepotion/slime/stabilizer/attack(mob/living/simple_animal/slime/M, mob/user)
if(!isslime(M))
to_chat(user, "<span class='warning'>The stabilizer only works on slimes!</span>")
return ..()
@@ -323,7 +328,7 @@
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle3"
/obj/item/slimepotion/slime/mutator/attack(mob/living/carbon/slime/M, mob/user)
/obj/item/slimepotion/slime/mutator/attack(mob/living/simple_animal/slime/M, mob/user)
if(!isslime(M))
to_chat(user, "<span class='warning'>The mutator only works on slimes!</span>")
return ..()
+3 -4
View File
@@ -765,10 +765,9 @@ obj/spacepod/proc/add_equipment(mob/user, var/obj/item/spacepod_equipment/SPE, v
to_chat(user, "<span class='danger'><B>The nuke-disk is locking the door every time you try to open it. You get the feeling that it doesn't want to go into the spacepod.</b></span>")
return 0
for(var/mob/living/carbon/slime/S in range(1,usr))
if(S.Victim == user)
to_chat(user, "You're too busy getting your life sucked out of you.")
return 0
if(user.has_buckled_mobs()) //mob attached to us
to_chat(user, "<span class='warning'>[user] will not fit into [src] because [user.p_they()] [user.p_have()] creatures attached to [user.p_them()]!</span>")
return
move_inside(user)
+61
View File
@@ -0,0 +1,61 @@
/datum/surgery/core_removal
name = "core removal"
steps = list(/datum/surgery_step/slime/cut_flesh, /datum/surgery_step/slime/extract_core)
allowed_mob = list(/mob/living/simple_animal/slime)
possible_locs = list("chest", "head", "l_arm", "l_hand", "r_arm", "r_hand", "r_leg", "r_foot", "l_leg", "l_foot", "groin")
/datum/surgery_step/slime
/datum/surgery_step/slime/is_valid_target(mob/living/simple_animal/slime/target)
return istype(target, /mob/living/simple_animal/slime)
/datum/surgery_step/slime/can_use(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
return istype(target) && target.stat == DEAD
/datum/surgery_step/slime/cut_flesh
allowed_tools = list(/obj/item/scalpel = 100, /obj/item/melee/energy/sword = 75, /obj/item/kitchen/knife = 65, /obj/item/shard = 45)
time = 16
/datum/surgery_step/slime/cut_flesh/begin_step(mob/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
user.visible_message("[user] starts cutting through [target]'s flesh with \the [tool].", "You start cutting through [target]'s flesh with \the [tool].")
/datum/surgery_step/slime/cut_flesh/end_step(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
user.visible_message("<span class='notice'> [user] cuts through [target]'s flesh with \the [tool].</span>",
"<span class='notice'> You cut through [target]'s flesh with \the [tool], revealing its silky innards.</span>")
return TRUE
/datum/surgery_step/slime/cut_flesh/fail_step(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
user.visible_message("<span class='warning'> [user]'s hand slips, tearing [target]'s flesh with \the [tool]!</span>", \
"<span class='warning'> Your hand slips, tearing [target]'s flesh with \the [tool]!</span>")
return FALSE
/datum/surgery_step/slime/extract_core
name = "extract core"
allowed_tools = list(/obj/item/hemostat = 100, /obj/item/crowbar = 100)
time = 16
/datum/surgery_step/slime/extract_core/begin_step(mob/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
user.visible_message("<span class='notice'>[user] begins to extract a core from [target].</span>",
"<span class='notice'>You begin to extract a core from [target]...</span>")
/datum/surgery_step/slime/extract_core/end_step(mob/user, mob/living/simple_animal/slime/slime, target_zone, obj/item/tool)
if(slime.cores > 0)
slime.cores--
user.visible_message("<span class='notice'>[user] successfully extracts a core from [slime]!</span>",
"<span class='notice'>You successfully extract a core from [slime]. [slime.cores] core\s remaining.</span>")
new slime.coretype(slime.loc)
if(slime.cores <= 0)
slime.icon_state = "[slime.colour] baby slime dead-nocore"
return TRUE
else
return FALSE
else
to_chat(user, "<span class='warning'>There aren't any cores left in [slime]!</span>")
return TRUE
/datum/surgery_step/slime/extract_core/fail_step(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
user.visible_message("<span class='warning'> [user]'s hand slips, tearing [target]'s flesh with \the [tool]!</span>", \
"<span class='warning'> Your hand slips, tearing [target]'s flesh with \the [tool]!</span>")
return FALSE
-103
View File
@@ -1,103 +0,0 @@
//////////////////////////////////////////////////////////////////
// SLIME CORE EXTRACTION //
//////////////////////////////////////////////////////////////////
/datum/surgery/core_removal
name = "core removal"
steps = list(/datum/surgery_step/slime/cut_flesh, /datum/surgery_step/slime/cut_innards, /datum/surgery_step/slime/saw_core)
allowed_mob = list(/mob/living/carbon/slime)
possible_locs = list("chest")//urgghhhhhhhhhhhh
/datum/surgery_step/slime
is_valid_target(mob/living/carbon/slime/target)
return istype(target, /mob/living/carbon/slime/)
can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
return target.stat == DEAD
/datum/surgery_step/slime/cut_flesh
allowed_tools = list(
/obj/item/scalpel = 100, \
/obj/item/kitchen/knife = 90, \
/obj/item/shard = 60, \
)
time = 16
/datum/surgery_step/slime/cut_flesh/can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
return ..() && istype(target) && target.core_removal_stage == 0
/datum/surgery_step/slime/cut_flesh/begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
user.visible_message("[user] starts cutting through [target]'s flesh with \the [tool].", \
"You start cutting through [target]'s flesh with \the [tool].")
/datum/surgery_step/slime/cut_flesh/end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
user.visible_message("<span class='notice'> [user] cuts through [target]'s flesh with \the [tool].</span>", \
"<span class='notice'> You cut through [target]'s flesh with \the [tool], revealing its silky innards.</span>")
target.core_removal_stage = 1
return 1
/datum/surgery_step/slime/cut_flesh/fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
user.visible_message("<span class='warning'> [user]'s hand slips, tearing [target]'s flesh with \the [tool]!</span>", \
"<span class='warning'> Your hand slips, tearing [target]'s flesh with \the [tool]!</span>")
return 0
/datum/surgery_step/slime/cut_innards
allowed_tools = list(
/obj/item/scalpel = 100, \
/obj/item/kitchen/knife = 90, \
/obj/item/shard = 60, \
)
time = 16
/datum/surgery_step/slime/cut_innards/can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
return ..() && istype(target) && target.core_removal_stage == 1
/datum/surgery_step/slime/cut_innards/begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
user.visible_message("[user] starts cutting [target]'s silky innards apart with \the [tool].", \
"You start cutting [target]'s silky innards apart with \the [tool].")
/datum/surgery_step/slime/cut_innards/end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
user.visible_message("<span class='notice'> [user] cuts [target]'s innards apart with \the [tool], exposing the cores.</span>", \
"<span class='notice'> You cut [target]'s innards apart with \the [tool], exposing the cores.</span>")
target.core_removal_stage = 2
return 1
/datum/surgery_step/slime/cut_innards/fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
user.visible_message("<span class='warning'> [user]'s hand slips, tearing [target]'s innards with \the [tool]!</span>", \
"<span class='warning'> Your hand slips, tearing [target]'s innards with \the [tool]!</span>")
return 0
/datum/surgery_step/slime/saw_core
allowed_tools = list(
/obj/item/circular_saw = 100, \
/obj/item/hatchet = 90
)
time = 16
/datum/surgery_step/slime/saw_core/can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
return ..() && (istype(target) && target.core_removal_stage == 2 && target.cores > 0) //This is being passed a human as target, unsure why.
/datum/surgery_step/slime/saw_core/begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
user.visible_message("[user] starts cutting out one of [target]'s cores with \the [tool].", \
"You start cutting out one of [target]'s cores with \the [tool].")
/datum/surgery_step/slime/saw_core/end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
target.cores--
user.visible_message("<span class='notice'> [user] cuts out one of [target]'s cores with \the [tool].</span>", \
"<span class='notice'> You cut out one of [target]'s cores with \the [tool]. [target.cores] cores left.</span>")
if(target.cores >= 0)
new target.coretype(target.loc)
if(target.cores <= 0)
target.icon_state = "[target.colour] baby slime dead-nocore"
return 1
/datum/surgery_step/slime/saw_core/fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
user.visible_message("<span class='warning'> [user]'s hand slips, causing [user.p_them()] to miss the core!</span>", \
"<span class='warning'> Your hand slips, causing you to miss the core!</span>")
return 0