mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-19 02:54:41 +01:00
Makes Xenobiology Simpler. Removes Slimes (#12398)
This commit is contained in:
committed by
variableundefined
parent
69e3a08a06
commit
cb8529cdb8
@@ -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 )
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
+5
-4
@@ -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
|
||||
..()
|
||||
+2
-2
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user