Merge pull request #3767 from Neerti/8/10/2017_make_xenobio_old_again

Make Xenobiology Old(ish) Again
This commit is contained in:
Anewbe
2017-09-10 17:12:38 -04:00
committed by GitHub
140 changed files with 6307 additions and 2782 deletions
+1 -2
View File
@@ -114,8 +114,7 @@ proc/admin_notice(var/message, var/rights)
else if(ishuman(M))
body += {"<A href='?src=\ref[src];makeai=\ref[M]'>Make AI</A> |
<A href='?src=\ref[src];makerobot=\ref[M]'>Make Robot</A> |
<A href='?src=\ref[src];makealien=\ref[M]'>Make Alien</A> |
<A href='?src=\ref[src];makeslime=\ref[M]'>Make slime</A>
<A href='?src=\ref[src];makealien=\ref[M]'>Make Alien</A>
"}
//Simple Animals
-1
View File
@@ -191,7 +191,6 @@ var/list/admin_verbs_debug = list(
/client/proc/overlay_random_map,
/client/proc/delete_random_map,
/client/proc/show_plant_genes,
/client/proc/show_xenobio_genes,
/client/proc/enable_debug_verbs,
/client/proc/callproc,
/client/proc/callproc_target,
+1 -11
View File
@@ -266,7 +266,7 @@
if("larva") M.change_mob_type( /mob/living/carbon/alien/larva , null, null, delmob )
if("nymph") M.change_mob_type( /mob/living/carbon/alien/diona , null, null, delmob )
if("human") M.change_mob_type( /mob/living/carbon/human , null, null, delmob, href_list["species"])
if("slime") M.change_mob_type( /mob/living/carbon/slime , null, null, delmob )
if("slime") M.change_mob_type( /mob/living/simple_animal/slime , null, null, delmob )
if("monkey") M.change_mob_type( /mob/living/carbon/human/monkey , null, null, delmob )
if("robot") M.change_mob_type( /mob/living/silicon/robot , null, null, delmob )
if("cat") M.change_mob_type( /mob/living/simple_animal/cat , null, null, delmob )
@@ -1156,16 +1156,6 @@
usr.client.cmd_admin_alienize(H)
else if(href_list["makeslime"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makeslime"])
if(!istype(H))
usr << "This can only be used on instances of type /mob/living/carbon/human"
return
usr.client.cmd_admin_slimeize(H)
else if(href_list["makerobot"])
if(!check_rights(R_SPAWN)) return
-18
View File
@@ -117,24 +117,6 @@
else
alert("Invalid mob")
/client/proc/cmd_admin_slimeize(var/mob/M in mob_list)
set category = "Fun"
set name = "Make slime"
if(!ticker)
alert("Wait until the game starts")
return
if(ishuman(M))
log_admin("[key_name(src)] has slimeized [M.key].")
spawn(10)
M:slimeize()
feedback_add_details("admin_verb","MKMET") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] made [key_name(M)] into a slime.")
message_admins("<font color='blue'>[key_name_admin(usr)] made [key_name(M)] into a slime.</font>", 1)
else
alert("Invalid mob")
/*
/client/proc/cmd_admin_monkeyize(var/mob/M in world)
set category = "Fun"
@@ -69,7 +69,6 @@
<option value='?_src_=vars;makerobot=\ref[src]'>Make cyborg</option>
<option value='?_src_=vars;makemonkey=\ref[src]'>Make monkey</option>
<option value='?_src_=vars;makealien=\ref[src]'>Make alien</option>
<option value='?_src_=vars;makeslime=\ref[src]'>Make slime</option>
"}
/obj/get_view_variables_options()
@@ -281,20 +281,6 @@
return
holder.Topic(href, list("makealien"=href_list["makealien"]))
else if(href_list["makeslime"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makeslime"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makeslime"=href_list["makeslime"]))
else if(href_list["makeai"])
if(!check_rights(R_SPAWN)) return
+3 -1
View File
@@ -78,7 +78,8 @@
name = "Radiation Hood"
icon_state = "rad"
desc = "A hood with radiation protective properties. Label: Made with lead, do not eat insulation"
flags_inv = BLOCKHAIR
// flags_inv = BLOCKHAIR
item_flags = THICKMATERIAL
body_parts_covered = HEAD|FACE|EYES
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100)
@@ -94,3 +95,4 @@
slowdown = 1.5
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100)
flags_inv = HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER
item_flags = THICKMATERIAL
+9 -1
View File
@@ -8,6 +8,8 @@ var/global/list/description_icons = list(
"radiation_armor" = image(icon='icons/mob/screen1_stats.dmi',icon_state="radiation_protection"),
"biohazard_armor" = image(icon='icons/mob/screen1_stats.dmi',icon_state="biohazard_protection"),
"offhand" = image(icon='icons/mob/screen1_stats.dmi',icon_state="offhand"),
"welder" = image(icon='icons/obj/tools.dmi',icon_state="welder"),
"wirecutters" = image(icon='icons/obj/tools.dmi',icon_state="cutters"),
"screwdriver" = image(icon='icons/obj/tools.dmi',icon_state="screwdriver"),
@@ -19,6 +21,12 @@ var/global/list/description_icons = list(
"plasteel sheet" = image(icon='icons/obj/items.dmi',icon_state="sheet-plasteel"),
"air tank" = image(icon='icons/obj/tank.dmi',icon_state="oxygen"),
"connector" = image(icon='icons/obj/pipes.dmi',icon_state="connector"),
"connector" = image(icon='icons/obj/pipes.dmi',icon_state="connector")
"stunbaton" = image(icon='icons/obj/weapons.dmi',icon_state="stunbaton_active"),
"slimebaton" = image(icon='icons/obj/weapons.dmi',icon_state="slimebaton_active"),
"power cell" = image(icon='icons/obj/power.dmi',icon_state="hcell"),
"device cell" = image(icon='icons/obj/power.dmi',icon_state="dcell"),
"weapon cell" = image(icon='icons/obj/power.dmi',icon_state="wcell"),
)
+15
View File
@@ -128,6 +128,9 @@
..(message, null, verb)
/mob/living/bot/speech_bubble_appearance()
return "machine"
/mob/living/bot/Bump(var/atom/A)
if(on && botcard && istype(A, /obj/machinery/door))
var/obj/machinery/door/D = A
@@ -313,6 +316,18 @@
return L
// Similar to above but not restricted to just cardinal directions.
/turf/proc/TurfsWithAccess(var/obj/item/weapon/card/id/ID)
var/L[] = new()
for(var/d in alldirs)
var/turf/T = get_step(src, d)
if(istype(T) && !T.density)
if(!LinkBlockedWithAccess(src, T, ID))
L.Add(T)
return L
// Returns true if a link between A and B is blocked
// Movement through doors allowed if ID has access
/proc/LinkBlockedWithAccess(turf/A, turf/B, obj/item/weapon/card/id/ID)
+67 -9
View File
@@ -13,6 +13,7 @@
patrol_speed = 2
target_speed = 3
var/default_icon_state = "secbot"
var/idcheck = 0 // If true, arrests for having weapons without authorization.
var/check_records = 0 // If true, arrests people without a record.
var/check_arrest = 1 // If true, arrests people who are set to arrest.
@@ -21,23 +22,44 @@
var/is_ranged = 0
var/awaiting_surrender = 0
var/can_next_insult = 0 // Uses world.time
var/stun_strength = 60 // For humans.
var/xeno_stun_strength = 0 // For simple mobs.
var/xeno_harm_strength = 15 // Ditto.
var/baton_glow = "#FF6A00"
var/list/threat_found_sounds = list('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg')
var/list/preparing_arrest_sounds = list('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/bcreep.ogg')
var/list/fighting_sounds = list('sound/voice/biamthelaw.ogg', 'sound/voice/bradio.ogg', 'sound/voice/bjustice.ogg')
/mob/living/bot/secbot/beepsky
name = "Officer Beepsky"
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
will_patrol = 1
/mob/living/bot/secbot/slime
name = "Slime Securitron"
desc = "A little security robot, with a slime baton subsituted for the regular one."
default_icon_state = "slimesecbot"
stun_strength = 10 // Slimebatons aren't meant for humans.
xeno_stun_strength = 5
xeno_harm_strength = 9
baton_glow = "#33CCFF"
req_one_access = list(access_research, access_robotics)
botcard_access = list(access_research, access_robotics, access_xenobiology, access_xenoarch, access_tox, access_tox_storage, access_maint_tunnels)
/mob/living/bot/secbot/slime/slimesky
name = "Doctor Slimesky"
desc = "An old friend of Officer Beep O'sky. He prescribes beatings to rowdy slimes so that real doctors don't need to treat the xenobiologists."
/mob/living/bot/secbot/update_icons()
if(on && busy)
icon_state = "secbot-c"
icon_state = "[default_icon_state]-c"
else
icon_state = "secbot[on]"
icon_state = "[default_icon_state][on]"
if(on)
set_light(2, 1, "#FF6A00")
set_light(2, 1, baton_glow)
else
set_light(0)
@@ -114,6 +136,11 @@
if(!target && health < curhealth && shooter && (shooter in view(world.view, src)))
react_to_attack(shooter)
/mob/living/bot/secbot/attack_generic(var/mob/attacker)
if(attacker)
react_to_attack(attacker)
..()
/mob/living/bot/secbot/proc/react_to_attack(mob/attacker)
if(!target)
playsound(src.loc, pick(threat_found_sounds), 50)
@@ -163,6 +190,7 @@
awaiting_surrender = -1
say("Level [threat] infraction alert!")
custom_emote(1, "points at [M.name]!")
playsound(src.loc, pick(threat_found_sounds), 50)
return
/mob/living/bot/secbot/handleAdjacentTarget()
@@ -174,9 +202,25 @@
++awaiting_surrender
else
if(declare_arrests)
broadcast_security_hud_message("[src] is [arrest_type ? "detaining" : "arresting"] a level [threat] suspect <b>[target_name(target)]</b> in <b>[get_area(src)]</b>.", src)
var/action = arrest_type ? "detaining" : "arresting"
if(istype(target, /mob/living/simple_animal))
action = "fighting"
broadcast_security_hud_message("[src] is [action] a level [threat] [action != "fighting" ? "suspect" : "threat"] <b>[target_name(target)]</b> in <b>[get_area(src)]</b>.", src)
UnarmedAttack(target)
// So Beepsky talks while beating up simple mobs.
/mob/living/bot/secbot/proc/insult(var/mob/living/L)
if(can_next_insult > world.time)
return
var/threat = check_threat(L)
if(threat >= 10)
playsound(src.loc, 'sound/voice/binsult.ogg', 75)
can_next_insult = world.time + 20 SECONDS
else
playsound(src.loc, pick(fighting_sounds), 75)
can_next_insult = world.time + 5 SECONDS
/mob/living/bot/secbot/UnarmedAttack(var/mob/M, var/proximity)
if(!..())
return
@@ -194,7 +238,7 @@
if(!C.lying || C.handcuffed || arrest_type)
cuff = 0
if(!cuff)
C.stun_effect_act(0, 60, null)
C.stun_effect_act(0, stun_strength, null)
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
do_attack_animation(C)
busy = 1
@@ -203,6 +247,7 @@
busy = 0
update_icons()
visible_message("<span class='warning'>\The [C] was prodded by \the [src] with a stun baton!</span>")
insult(C)
else
playsound(loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2)
visible_message("<span class='warning'>\The [src] is trying to put handcuffs on \the [C]!</span>")
@@ -214,8 +259,8 @@
busy = 0
else if(istype(M, /mob/living/simple_animal))
var/mob/living/simple_animal/S = M
S.AdjustStunned(10)
S.adjustBruteLoss(15)
S.Weaken(xeno_stun_strength)
S.adjustBruteLoss(xeno_harm_strength)
do_attack_animation(M)
playsound(loc, "swing_hit", 50, 1, -1)
busy = 1
@@ -224,6 +269,15 @@
busy = 0
update_icons()
visible_message("<span class='warning'>\The [M] was beaten by \the [src] with a stun baton!</span>")
insult(S)
/mob/living/bot/secbot/slime/UnarmedAttack(var/mob/living/L, var/proximity)
..()
if(istype(L, /mob/living/simple_animal/slime))
var/mob/living/simple_animal/slime/S = L
S.adjust_discipline(2)
/mob/living/bot/secbot/explode()
@@ -323,8 +377,12 @@
else if(istype(W, /obj/item/weapon/melee/baton) && build_step == 3)
user.drop_item()
user << "You complete the Securitron! Beep boop."
var/mob/living/bot/secbot/S = new /mob/living/bot/secbot(get_turf(src))
S.name = created_name
if(istype(W, /obj/item/weapon/melee/baton/slime))
var/mob/living/bot/secbot/slime/S = new /mob/living/bot/secbot/slime(get_turf(src))
S.name = created_name
else
var/mob/living/bot/secbot/S = new /mob/living/bot/secbot(get_turf(src))
S.name = created_name
qdel(W)
qdel(src)
@@ -45,7 +45,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 ..()
@@ -355,6 +355,9 @@ emp_act
//this proc handles being hit by a thrown atom
/mob/living/carbon/human/hitby(atom/movable/AM as mob|obj,var/speed = THROWFORCE_SPEED_DIVISOR)
// if(buckled && buckled == AM)
// return // Don't get hit by the thing we're buckled to.
if(istype(AM,/obj/))
var/obj/O = AM
+10 -1
View File
@@ -38,6 +38,15 @@
say(temp)
winset(client, "input", "text=[null]")
/mob/living/carbon/human/speech_bubble_appearance()
if(isSynthetic())
var/datum/robolimb/robo = isSynthetic()
return robo.speech_bubble_appearance
else
if(species)
return species.speech_bubble_appearance
return "normal"
/mob/living/carbon/human/say_understands(var/mob/other,var/datum/language/speaking = null)
if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak.
@@ -55,7 +64,7 @@
return 1
if (istype(other, /mob/living/carbon/brain))
return 1
if (istype(other, /mob/living/carbon/slime))
if (istype(other, /mob/living/simple_animal/slime))
return 1
//This is already covered by mob/say_understands()
@@ -13,6 +13,8 @@
var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set.
var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set.
var/speech_bubble_appearance = "normal" // Part of icon_state to use for speech bubbles when talking. See talk.dmi for available icons.
// Damage overlay and masks.
var/damage_overlays = 'icons/mob/human_races/masks/dam_human.dmi'
var/damage_mask = 'icons/mob/human_races/masks/dam_mask_human.dmi'
@@ -28,6 +28,8 @@ var/datum/species/shapeshifter/promethean/prometheans
breath_type = null
poison_type = null
speech_bubble_appearance = "slime"
male_cough_sounds = list('sound/effects/slime_squish.ogg')
female_cough_sounds = list('sound/effects/slime_squish.ogg')
+76 -51
View File
@@ -9,27 +9,27 @@
throw_speed = 3
throw_range = 6
origin_tech = list(TECH_BIO = 4)
var/Uses = 1 // uses before it goes inert
var/uses = 1 // uses before it goes inert
var/enhanced = 0 //has it been enhanced before?
flags = OPENCONTAINER
attackby(obj/item/O as obj, mob/user as mob)
if(istype(O, /obj/item/weapon/slimesteroid2))
if(enhanced == 1)
user << "<span class='warning'> This extract has already been enhanced!</span>"
return ..()
if(Uses == 0)
user << "<span class='warning'> You can't enhance a used extract!</span>"
return ..()
user <<"You apply the enhancer. It now has triple the amount of uses."
Uses = 3
enhanced = 1
qdel(O)
/*
/obj/item/slime_extract/attackby(obj/item/O as obj, mob/user as mob)
if(istype(O, /obj/item/weapon/slimesteroid2))
if(enhanced == 1)
user << "<span class='warning'> This extract has already been enhanced!</span>"
return ..()
if(Uses == 0)
user << "<span class='warning'> You can't enhance a used extract!</span>"
return ..()
user <<"You apply the enhancer. It now has triple the amount of uses."
Uses = 3
enhanced = 1
qdel(O)
*/
/obj/item/slime_extract/New()
..()
create_reagents(100)
reagents.add_reagent("slimejelly", 30)
create_reagents(5)
// reagents.add_reagent("slimejelly", 30)
/obj/item/slime_extract/grey
name = "grey slime extract"
@@ -51,7 +51,7 @@
name = "purple slime extract"
icon_state = "purple slime extract"
/obj/item/slime_extract/darkpurple
/obj/item/slime_extract/dark_purple
name = "dark purple slime extract"
icon_state = "dark purple slime extract"
@@ -71,7 +71,7 @@
name = "blue slime extract"
icon_state = "blue slime extract"
/obj/item/slime_extract/darkblue
/obj/item/slime_extract/dark_blue
name = "dark blue slime extract"
icon_state = "dark blue slime extract"
@@ -119,41 +119,66 @@
name = "rainbow slime extract"
icon_state = "rainbow slime extract"
////Pet Slime Creation///
/obj/item/slimepotion
icon = 'icons/obj/chemical.dmi'
/obj/item/weapon/slimepotion
////Pet Slime Creation///
/*
/obj/item/slimepotion/docility
name = "docility potion"
desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle19"
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
user << "<span class='warning'> The potion only works on baby slimes!</span>"
return ..()
if(M.is_adult) //Can't tame adults
user << "<span class='warning'> Only baby slimes can be tamed!</span>"
return..()
if(M.stat)
user << "<span class='warning'> The slime is dead!</span>"
return..()
if(M.mind)
user << "<span class='warning'> The slime resists!</span>"
return ..()
var/mob/living/simple_animal/slime/pet = new /mob/living/simple_animal/slime(M.loc)
pet.icon_state = "[M.colour] baby slime"
pet.icon_living = "[M.colour] baby slime"
pet.icon_dead = "[M.colour] baby slime dead"
pet.colour = "[M.colour]"
user <<"You feed the slime the potion, removing it's powers and calming it."
qdel(M)
var/newname = sanitize(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text, MAX_NAME_LEN)
/obj/item/slimepotion/docility/attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
user << "<span class='warning'> The potion only works on slimes!</span>"
return ..()
// if(M.is_adult) //Can't tame adults
// user << "<span class='warning'> Only baby slimes can be tamed!</span>"
// return..()
if(M.stat)
user << "<span class='warning'> The slime is dead!</span>"
return..()
if(M.mind)
user << "<span class='warning'> The slime resists!</span>"
return ..()
var/mob/living/simple_animal/slime/pet = new /mob/living/simple_animal/slime(M.loc)
pet.icon_state = "[M.colour] [M.is_adult ? "adult" : "baby"] slime"
pet.icon_living = "[M.colour] [M.is_adult ? "adult" : "baby"] slime"
pet.icon_dead = "[M.colour] [M.is_adult ? "adult" : "baby"] slime dead"
pet.colour = "[M.colour]"
to_chat(user, "You feed the slime the potion, removing it's powers and calming it.")
qdel(M)
var/newname = sanitize(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text, MAX_NAME_LEN)
if (!newname)
newname = "pet slime"
pet.name = newname
pet.real_name = newname
qdel(src)
/obj/item/slimepotion/stabilizer
name = "slime stabilizer"
desc = "A potent chemical mix that will reduce the chance of a slime mutating."
icon_state = "potcyan"
/obj/item/slimepotion/stabilizer/attack(mob/living/carbon/slime/M, mob/user)
if(!isslime(M))
to_chat(user, "<span class='warning'>The stabilizer only works on slimes!</span>")
return ..()
if(M.stat)
to_chat(user, "<span class='warning'>The slime is dead!</span>")
return ..()
if(M.mutation_chance == 0)
to_chat(user, "<span class='warning'>The slime already has no chance of mutating!</span>")
return ..()
to_chat(user, "<span class='notice'>You feed the slime the stabilizer. It is now less likely to mutate.</span>")
M.mutation_chance = Clamp(M.mutation_chance-15,0,100)
qdel(src)
if (!newname)
newname = "pet slime"
pet.name = newname
pet.real_name = newname
qdel(src)
/obj/item/weapon/slimepotion2
name = "advanced docility potion"
@@ -187,7 +212,7 @@
qdel(src)
/obj/item/weapon/slimesteroid
/obj/item/slimesteroid
name = "slime steroid"
desc = "A potent chemical mix that will cause a slime to generate more extract."
icon = 'icons/obj/chemical.dmi'
@@ -211,7 +236,7 @@
M.cores = 3
qdel(src)
/obj/item/weapon/slimesteroid2
/obj/item/slimesteroid2
name = "extract enhancer"
desc = "A potent chemical mix that will give a slime extract three uses."
icon = 'icons/obj/chemical.dmi'
@@ -229,7 +254,7 @@
target.Uses = 3
target.enahnced = 1
qdel(src)*/
*/
/obj/effect/golemrune
anchored = 1
desc = "a strange rune used to create golems. It glows when spirits are nearby."
+8 -10
View File
@@ -90,9 +90,6 @@ default behaviour is:
forceMove(tmob.loc)
tmob.forceMove(oldloc)
now_pushing = 0
for(var/mob/living/carbon/slime/slime in view(1,tmob))
if(slime.Victim == tmob)
slime.UpdateFeed()
return
if(!can_move_mob(tmob, 0, 0))
@@ -571,7 +568,8 @@ default behaviour is:
fire_stacks = 0
/mob/living/proc/rejuvenate()
reagents.clear_reagents()
if(reagents)
reagents.clear_reagents()
// shut down various types of badness
setToxLoss(0)
@@ -642,8 +640,12 @@ default behaviour is:
return
/mob/living/Move(a, b, flag)
if (buckled)
return
if (buckled && buckled.loc != a) //not updating position
if (!buckled.anchored)
return buckled.Move(a, b)
else
return 0
if (restrained())
stop_pulling()
@@ -724,10 +726,6 @@ default behaviour is:
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)
return FALSE
+5 -1
View File
@@ -298,7 +298,8 @@ proc/get_radio_key_from_channel(var/channel)
//The 'post-say' static speech bubble
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
var/speech_type = speech_bubble_appearance()
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"[speech_type][speech_bubble_test]")
spawn(30) qdel(speech_bubble)
//Main 'say' and 'whisper' message delivery
@@ -341,3 +342,6 @@ proc/get_radio_key_from_channel(var/channel)
/mob/living/proc/GetVoice()
return name
/mob/proc/speech_bubble_appearance()
return "normal"
@@ -76,11 +76,14 @@
/obj/item/weapon/disk,
/obj/item/weapon/circuitboard,
/obj/item/weapon/reagent_containers/glass,
/obj/item/weapon/reagent_containers/food/snacks/monkeycube,
/obj/item/xenoproduct/slime/core,
/obj/item/device/assembly/prox_sensor,
/obj/item/device/healthanalyzer //to build medibots
// /obj/item/slime_extract, ### Outdated
/obj/item/device/healthanalyzer, //to build medibots,
/obj/item/slime_cube,
/obj/item/slime_crystal,
/obj/item/weapon/disposable_teleporter/slime,
/obj/item/slimepotion,
/obj/item/slime_extract,
/obj/item/weapon/reagent_containers/food/snacks/monkeycube,
)
@@ -719,6 +719,8 @@ var/global/list/robot_modules = list(
src.modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
src.modules += new /obj/item/weapon/storage/part_replacer(src)
src.modules += new /obj/item/weapon/shockpaddles/robot/jumper(src)
src.modules += new /obj/item/weapon/melee/baton/slime/robot(src)
src.modules += new /obj/item/weapon/gun/energy/taser/xeno/robot(src)
src.emag = new /obj/item/weapon/hand_tele(src)
var/datum/matter_synth/nanite = new /datum/matter_synth/nanite(10000)
+3
View File
@@ -14,6 +14,9 @@
message_mode = null
return radio.talk_into(src,message,message_mode,verb,speaking)
/mob/living/silicon/speech_bubble_appearance()
return "synthetic"
/mob/living/silicon/ai/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
..()
if(message_mode == "department")
@@ -8,6 +8,7 @@
icon_gib = "syndicate_gib"
faction = "xeno"
intelligence_level = SA_HUMANOID
cooperative = 1
run_at_them = 0
@@ -7,6 +7,7 @@
icon_dead = "otherthing-dead"
faction = "creature"
intelligence_level = SA_ANIMAL
maxHealth = 40
health = 40
speed = 8
@@ -8,6 +8,7 @@
icon_dead = "drone_dead"
faction = "malf_drone"
intelligence_level = SA_ROBOTIC
maxHealth = 300
health = 300
speed = 8
@@ -6,6 +6,7 @@
icon_dead = "faithless_dead"
faction = "faithless"
intelligence_level = SA_HUMANOID
maxHealth = 50
health = 50
speed = 8
@@ -14,7 +15,7 @@
response_help = "passes through"
response_disarm = "shoves"
response_harm = "hits"
harm_intent_damage = 10
melee_damage_lower = 5
melee_damage_upper = 5
@@ -7,6 +7,7 @@
icon_dead = "basic"
faction = "hivebot"
intelligence_level = SA_ROBOTIC
maxHealth = 15
health = 15
speed = 4
@@ -10,6 +10,7 @@
icon_living = "crate"
faction = "mimic"
intelligence_level = SA_ANIMAL
maxHealth = 250
health = 250
@@ -8,6 +8,7 @@
icon_dead = "shade_dead"
faction = "cult"
intelligence_level = SA_HUMANOID
maxHealth = 50
health = 50
@@ -8,6 +8,7 @@
icon_gib = "bat_dead"
faction = "scarybat"
intelligence_level = SA_ANIMAL
maxHealth = 20
health = 20
@@ -8,6 +8,7 @@
icon_gib = "bear_gib"
faction = "russian"
intelligence_level = SA_ANIMAL
cooperative = 1
maxHealth = 60
@@ -7,6 +7,7 @@
icon_gib = "carp_gib"
faction = "carp"
intelligence_level = SA_ANIMAL
maxHealth = 25
health = 25
speed = 4
@@ -2,6 +2,7 @@
/mob/living/simple_animal/cat
name = "cat"
desc = "A domesticated, feline pet. Has a tendency to adopt crewmembers."
intelligence_level = SA_ANIMAL
icon_state = "cat2"
item_state = "cat2"
icon_living = "cat2"
@@ -3,6 +3,7 @@
name = "\improper corgi"
real_name = "corgi"
desc = "It's a corgi."
intelligence_level = SA_ANIMAL
icon_state = "corgi"
icon_living = "corgi"
icon_dead = "corgi_dead"
@@ -5,6 +5,7 @@
icon_state = "crab"
icon_living = "crab"
icon_dead = "crab_dead"
intelligence_level = SA_ANIMAL
wander = 0
stop_automated_movement = 1
@@ -7,6 +7,7 @@
icon_dead = "goat_dead"
faction = "goat"
intelligence_level = SA_ANIMAL
health = 40
turns_per_move = 5
@@ -88,6 +89,7 @@
icon_living = "cow"
icon_dead = "cow_dead"
icon_gib = "cow_gib"
intelligence_level = SA_ANIMAL
health = 50
turns_per_move = 5
@@ -155,6 +157,7 @@
icon_living = "chick"
icon_dead = "chick_dead"
icon_gib = "chick_gib"
intelligence_level = SA_ANIMAL
health = 1
turns_per_move = 2
@@ -203,6 +206,7 @@ var/global/chicken_count = 0
icon_state = "chicken"
icon_living = "chicken"
icon_dead = "chicken_dead"
intelligence_level = SA_ANIMAL
health = 10
turns_per_move = 3
@@ -4,6 +4,7 @@
desc = "Its a fishy. No touchy fishy."
icon = 'icons/mob/fish.dmi'
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
intelligence_level = SA_ANIMAL
// By defautl they can be in any water turf. Subtypes might restrict to deep/shallow etc
var/global/list/suitable_turf_types = list(
@@ -13,6 +13,7 @@
icon_dead = "guard_dead"
faction = "spiders"
intelligence_level = SA_ANIMAL
maxHealth = 200
health = 200
pass_flags = PASSTABLE
@@ -7,6 +7,7 @@
icon_gib = "generic_gib"
faction = "geese"
intelligence_level = SA_ANIMAL
maxHealth = 15
health = 15
@@ -5,6 +5,7 @@
icon_state = "lizard"
icon_living = "lizard"
icon_dead = "lizard-dead"
intelligence_level = SA_ANIMAL
health = 5
maxHealth = 5
@@ -6,6 +6,7 @@
item_state = "mouse_gray"
icon_living = "mouse_gray"
icon_dead = "mouse_gray_dead"
intelligence_level = SA_ANIMAL
maxHealth = 5
health = 5
@@ -35,6 +35,7 @@
icon_state = "parrot_fly"
icon_living = "parrot_fly"
icon_dead = "parrot_dead"
intelligence_level = SA_ANIMAL
turns_per_move = 5
pass_flags = PASSTABLE
@@ -5,6 +5,7 @@
icon_living = "penguin"
icon_dead = "penguin_dead"
icon_gib = "generic_gib"
intelligence_level = SA_ANIMAL
maxHealth = 20
health = 20
@@ -5,6 +5,7 @@
icon_state = "spiderbot-chassis"
icon_living = "spiderbot-chassis"
icon_dead = "spiderbot-smashed"
intelligence_level = SA_HUMANOID // Because its piloted by players.
health = 10
maxHealth = 10
@@ -4,6 +4,7 @@
icon_state = "tomato"
icon_living = "tomato"
icon_dead = "tomato_dead"
intelligence_level = SA_PLANT
faction = "plants"
maxHealth = 15
@@ -6,6 +6,7 @@
icon_living = "pine_1"
icon_dead = "pine_1"
icon_gib = "pine_1"
intelligence_level = SA_PLANT
faction = "carp" //Trees can be carp friends?
maxHealth = 250
@@ -5,6 +5,7 @@
icon_state = "spaceworm"
icon_living = "spaceworm"
icon_dead = "spacewormdead"
intelligence_level = SA_ANIMAL
maxHealth = 30
@@ -4,6 +4,7 @@
desc = "A small, quivering sluglike creature."
speak_emote = list("chirrups")
emote_hear = list("chirrups")
intelligence_level = SA_HUMANOID // Player controlled.
response_help = "pokes"
response_disarm = "prods"
response_harm = "stomps on"
@@ -7,6 +7,7 @@
response_help = "thinks better of touching"
response_disarm = "flailed at"
response_harm = "punched"
intelligence_level = SA_HUMANOID // Player controlled.
icon_dead = "shade_dead"
speed = -1
a_intent = I_HURT
@@ -5,6 +5,7 @@
icon_living = "clown"
icon_dead = "clown_dead"
icon_gib = "clown_gib"
intelligence_level = SA_HUMANOID
faction = "clown"
maxHealth = 75
@@ -5,6 +5,7 @@
icon_state = "crab"
icon_living = "crab"
icon_dead = "crab_dead"
intelligence_level = SA_ANIMAL
wander = 0
stop_automated_movement = 1
@@ -6,6 +6,7 @@
icon_state = "kobold_idle"
icon_living = "kobold_idle"
icon_dead = "kobold_dead"
intelligence_level = SA_HUMANOID
run_at_them = 0
cooperative = 1
@@ -5,6 +5,7 @@
icon_state = "darkgygax"
icon_living = "darkgygax"
icon_dead = "darkgygax-broken"
intelligence_level = SA_HUMANOID // Piloted by a human.
faction = "syndicate"
maxHealth = 300
@@ -4,6 +4,7 @@
icon_state = "piratemelee"
icon_living = "piratemelee"
icon_dead = "piratemelee_dead"
intelligence_level = SA_HUMANOID
faction = "pirate"
maxHealth = 100
@@ -5,6 +5,7 @@
icon_living = "russianmelee"
icon_dead = "russianmelee_dead"
icon_gib = "syndicate_gib"
intelligence_level = SA_HUMANOID
faction = "russian"
maxHealth = 100
@@ -5,6 +5,7 @@
icon_living = "syndicate"
icon_dead = "syndicate_dead"
icon_gib = "syndicate_gib"
intelligence_level = SA_HUMANOID
faction = "syndicate"
maxHealth = 100
@@ -165,6 +166,7 @@
icon = 'icons/mob/critter.dmi'
icon_state = "viscerator_attack"
icon_living = "viscerator_attack"
intelligence_level = SA_ROBOTIC
faction = "syndicate"
maxHealth = 15
@@ -17,11 +17,12 @@
var/show_stat_health = 1 // Does the percentage health show in the stat panel for the mob
var/ai_inactive = 0 // Set to 1 to turn off most AI actions
//Mob icon settings
//Mob icon/appearance settings
var/icon_living = "" // The iconstate if we're alive, required
var/icon_dead = "" // The iconstate if we're dead, required
var/icon_gib = null // The iconstate for being gibbed, optional
var/icon_rest = null // The iconstate for resting, optional
var/image/modifier_overlay = null // Holds overlays from modifiers.
//Mob talking settings
universal_speak = 0 // Can all mobs in the entire universe understand this one?
@@ -59,6 +60,7 @@
var/list/loot_list = list() // The list of lootable objects to drop, with "/path = prob%" structure
var/recruitable = 0 // Mob can be bossed around
var/recruit_cmd_str = "Hey," // The thing you prefix commands with when bossing them around
var/intelligence_level = SA_ANIMAL// How 'smart' the mob is ICly, used to deliniate between animal, robot, and humanoid SAs.
//Mob environment settings
var/minbodytemp = 250 // Minimum "okay" temperature in kelvin
@@ -116,6 +118,7 @@
var/run_at_them = 1 // Don't use A* pathfinding, use walk_to
var/move_to_delay = 4 // Delay for the automated movement (deciseconds)
var/destroy_surroundings = 1 // Should I smash things to get to my target?
var/astar_adjacent_proc = /turf/proc/CardinalTurfsWithAccess // Proc to use when A* pathfinding. Default makes them bound to cardinals.
//Damage resistances
var/resistance = 0 // Damage reduction for all types
@@ -205,6 +208,7 @@
src.client.screen += src.client.void
ai_inactive = 1
handle_stance(STANCE_IDLE)
LoseTarget()
src.client << "<span class='notice'>Mob AI disabled while you are controlling the mob.</span>"
..()
@@ -241,7 +245,7 @@
/mob/living/simple_animal/update_icon()
..()
//Awake and normal
if((stat == CONSCIOUS) && (!icon_rest || !resting))
if((stat == CONSCIOUS) && (!icon_rest || !resting || !incapacitated(INCAPACITATION_DISABLED) ))
icon_state = icon_living
//Dead
@@ -249,13 +253,33 @@
icon_state = icon_dead
//Resting or KO'd
else if(((stat == UNCONSCIOUS) || resting) && icon_rest)
else if(((stat == UNCONSCIOUS) || resting || incapacitated(INCAPACITATION_DISABLED) ) && icon_rest)
icon_state = icon_rest
//Backup
else
icon_state = initial(icon_state)
// If your simple mob's update_icon() call calls overlays.Cut(), this needs to be called after this, or manually apply modifier_overly to overlays.
/mob/living/simple_animal/update_modifier_visuals()
var/image/effects = null
if(modifier_overlay)
overlays -= modifier_overlay
modifier_overlay.overlays.Cut()
effects = modifier_overlay
else
effects = new()
for(var/datum/modifier/M in modifiers)
if(M.mob_overlay_state)
var/image/I = image("icon" = 'icons/mob/modifier_effects.dmi', "icon_state" = M.mob_overlay_state)
I.appearance_flags = RESET_COLOR // So colored mobs don't affect the overlay.
effects.overlays += I
modifier_overlay = effects
overlays += modifier_overlay
/mob/living/simple_animal/Life()
..()
@@ -288,7 +312,7 @@
//Resisting out buckles
if(stance != STANCE_IDLE && incapacitated(INCAPACITATION_BUCKLED_PARTIALLY))
resist()
handle_resist()
//Resisting out of closets
if(istype(loc,/obj/structure/closet))
@@ -300,6 +324,11 @@
return 1
// Resists out of things.
// Sometimes there are times you want SAs to be buckled to something, so override this for when that is needed.
/mob/living/simple_animal/proc/handle_resist()
resist()
// Peforms the random walk wandering
/mob/living/simple_animal/proc/handle_wander_movement()
if(isturf(src.loc) && !resting && !buckled && canmove) //Physically capable of moving?
@@ -482,6 +511,8 @@
if(Proj.firer)
react_to_attack(Proj.firer)
Proj.on_hit(src)
return 0
// When someone clicks us with an empty hand
@@ -550,11 +581,9 @@
if(istype(O, /obj/item/weapon/material/knife) || istype(O, /obj/item/weapon/material/knife/butch))
harvest(user)
else
if(!O.force)
visible_message("<span class='notice'>[user] gently taps [src] with \the [O].</span>")
else
O.attack(src, user, user.zone_sel.selecting)
ai_log("attackby() I was weapon'd by: [user]",2)
O.attack(src, user, user.zone_sel.selecting)
ai_log("attackby() I was weapon'd by: [user]",2)
if(O.force)
react_to_attack(user)
/mob/living/simple_animal/hit_with_weapon(obj/item/O, mob/living/user, var/effective_force, var/hit_zone)
@@ -645,18 +674,58 @@
if(3.0)
adjustBruteLoss(30)
// Don't understand why simple animals don't use the regular /mob/living health system.
/mob/living/simple_animal/adjustBruteLoss(damage)
if(damage > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
damage *= M.incoming_damage_percent
if(!isnull(M.incoming_brute_damage_percent))
damage *= M.incoming_brute_damage_percent
else if(damage < 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
damage *= M.incoming_healing_percent
health = Clamp(health - damage, 0, getMaxHealth())
updatehealth()
/mob/living/simple_animal/adjustFireLoss(damage)
if(damage > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
damage *= M.incoming_damage_percent
if(!isnull(M.incoming_fire_damage_percent))
damage *= M.incoming_brute_damage_percent
else if(damage < 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
damage *= M.incoming_healing_percent
health = Clamp(health - damage, 0, getMaxHealth())
updatehealth()
/mob/living/simple_animal/adjustToxLoss(damage)
if(damage > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
damage *= M.incoming_damage_percent
if(!isnull(M.incoming_tox_damage_percent))
damage *= M.incoming_brute_damage_percent
else if(damage < 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
damage *= M.incoming_healing_percent
health = Clamp(health - damage, 0, getMaxHealth())
updatehealth()
// Check target_mob if worthy of attack (i.e. check if they are dead or empty mecha)
/mob/living/simple_animal/proc/SA_attackable(target_mob)
ai_log("SA_attackable([target_mob])",3)
if (isliving(target_mob))
var/mob/living/L = target_mob
if(!L.stat)
if(L.stat != DEAD)
return 1
if (istype(target_mob,/obj/mecha))
var/obj/mecha/M = target_mob
@@ -777,6 +846,8 @@
continue
else if(!SA_attackable(L))
continue
else if(!special_target_check(L))
continue
else
T = L
break
@@ -785,6 +856,8 @@
var/obj/mecha/M = A
if(!SA_attackable(M))
continue
else if(!special_target_check(M))
continue
if((M.occupant.faction != src.faction) || attack_same)
T = M
break
@@ -801,6 +874,10 @@
/mob/living/simple_animal/proc/Found(var/atom/A)
return
// Used for somewhat special targeting, but not to the extent of using Found()
/mob/living/simple_animal/proc/special_target_check(var/atom/A)
return TRUE
//Requesting help from like-minded individuals
/mob/living/simple_animal/proc/RequestHelp()
if(!cooperative || ((world.time - last_helpask_time) < 10 SECONDS))
@@ -833,6 +910,12 @@
if(set_follow(F, 10 SECONDS))
handle_stance(STANCE_FOLLOW)
// Can be used to conditionally do a ranged or melee attack.
// Note that the SA must be able to do an attack at the specified range or else it may get trapped in a loop of switching
// between STANCE_ATTACK and STANCE_ATTACKING, due to being told by MoveToTarget() that they're in range but being told by AttackTarget() that they're not.
/mob/living/simple_animal/proc/ClosestDistance()
return ranged ? shoot_range - 1 : 1 // Shoot range -1 just because we don't want to constantly get kited
//Move to a target (or near if we're ranged)
/mob/living/simple_animal/proc/MoveToTarget()
if(incapacitated(INCAPACITATION_DISABLED))
@@ -857,9 +940,9 @@
ForgetPath()
//Find out where we're getting to
var/get_to = ranged ? shoot_range-1 : 1 //Shoot range -1 just because we don't want to constantly get kited
var/get_to = ClosestDistance()
var/distance = get_dist(src,target_mob)
ai_log("MoveToTarget() [src] [get_to] [distance]",2)
ai_log("MoveToTarget() [src] get_to: [get_to] distance: [distance]",2)
//We're here!
if(distance <= get_to)
@@ -919,6 +1002,7 @@
if(incapacitated(INCAPACITATION_DISABLED))
ai_log("FollowTarget() Bailing because we're disabled",2)
LoseFollow()
return
if((get_dist(src,follow_mob) <= follow_dist))
@@ -972,7 +1056,7 @@
/mob/living/simple_animal/proc/GetPath(var/turf/target,var/get_to = 1,var/max_distance = world.view*6)
ai_log("GetPath([target],[get_to],[max_distance])",2)
ForgetPath()
var/list/new_path = AStar(get_turf(loc), target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, min_target_dist = get_to, max_node_depth = max_distance, id = myid, exclude = obstacles)
var/list/new_path = AStar(get_turf(loc), target, astar_adjacent_proc, /turf/proc/Distance, min_target_dist = get_to, max_node_depth = max_distance, id = myid, exclude = obstacles)
if(new_path && new_path.len)
walk_list = new_path
@@ -1082,6 +1166,10 @@
//Get into attack mode on a target
/mob/living/simple_animal/proc/AttackTarget()
stop_automated_movement = 1
if(incapacitated(INCAPACITATION_DISABLED))
ai_log("AttackTarget() Bailing because we're disabled",2)
LoseTarget()
return 0
if(!target_mob || !SA_attackable(target_mob))
LoseTarget()
return 0
@@ -1111,6 +1199,7 @@
//They ran away!
else
ai_log("AttackTarget() out of range!",3)
sleep(1) // Unfortunately this is needed to protect from ClosestDistance() sometimes not updating fast enough to prevent an infinite loop.
handle_stance(STANCE_ATTACK)
return 0
@@ -1118,7 +1207,8 @@
/mob/living/simple_animal/proc/PunchTarget()
if(!Adjacent(target_mob))
return
sleep(rand(8) + 8)
if(!client)
sleep(rand(8) + 8)
if(isliving(target_mob))
var/mob/living/L = target_mob
@@ -1129,39 +1219,51 @@
src.do_attack_animation(src)
return L
else
L.attack_generic(src,rand(melee_damage_lower,melee_damage_upper),attacktext)
DoPunch(L)
return L
if(istype(target_mob,/obj/mecha))
var/obj/mecha/M = target_mob
M.attack_generic(src,rand(melee_damage_lower,melee_damage_upper),attacktext)
DoPunch(M)
return M
// This is the actual act of 'punching'. Override for special behaviour.
/mob/living/simple_animal/proc/DoPunch(var/atom/A)
if(!Adjacent(target_mob)) // They could've moved in the meantime.
return
var/damage_to_do = rand(melee_damage_lower, melee_damage_upper)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.outgoing_melee_damage_percent))
damage_to_do *= M.outgoing_melee_damage_percent
A.attack_generic(src, damage_to_do, attacktext)
//The actual top-level ranged attack proc
/mob/living/simple_animal/proc/ShootTarget()
var/target = target_mob
var/tturf = get_turf(target)
if(firing_lines && !CheckFiringLine(tturf))
if((firing_lines && !client) && !CheckFiringLine(tturf))
step_rand(src)
face_atom(tturf)
return 0
visible_message("<span class='danger'><b>[src]</b> fires at [target]!</span>", 1)
visible_message("<span class='danger'><b>[src]</b> fires at [target]!</span>")
if(rapid)
spawn(1)
Shoot(tturf, src.loc, src)
Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
spawn(4)
Shoot(tturf, src.loc, src)
Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
spawn(6)
Shoot(tturf, src.loc, src)
Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
else
Shoot(tturf, src.loc, src)
Shoot(target, src.loc, src)
if(casingtype)
new casingtype
@@ -1201,9 +1303,9 @@
playsound(user, projectilesound, 100, 1)
if(!A) return
if (!istype(target, /turf))
qdel(A)
return
// if (!istype(target, /turf))
// qdel(A)
// return
A.launch(target)
return
@@ -1226,6 +1328,43 @@
handle_stance(STANCE_IDLE)
GiveUpMoving()
// Makes the simple mob stop everything. Useful for when it get stunned.
/mob/living/simple_animal/proc/Disable()
ai_log("Disable() [target_mob]",2)
spawn(0)
LoseTarget()
LoseFollow()
/mob/living/simple_animal/Stun(amount)
if(amount > 0)
Disable()
..(amount)
/mob/living/simple_animal/AdjustStunned(amount)
if(amount > 0)
Disable()
..(amount)
/mob/living/simple_animal/Weaken(amount)
if(amount > 0)
Disable()
..(amount)
/mob/living/simple_animal/AdjustWeakened(amount)
if(amount > 0)
Disable()
..(amount)
/mob/living/simple_animal/Paralyse(amount)
if(amount > 0)
Disable()
..(amount)
/mob/living/simple_animal/AdjustParalysis(amount)
if(amount > 0)
Disable()
..(amount)
//Find me some targets
/mob/living/simple_animal/proc/ListTargets(var/dist = view_range)
var/list/L = hearers(src, dist)
@@ -1244,22 +1383,32 @@
var/turf/problem_turf = get_step(src, direction)
ai_log("DestroySurroundings([direction])",3)
var/damage_to_do = rand(melee_damage_lower, melee_damage_upper)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.outgoing_melee_damage_percent))
damage_to_do *= M.outgoing_melee_damage_percent
for(var/obj/structure/window/obstacle in problem_turf)
if(obstacle.dir == reverse_dir[dir]) // So that windows get smashed in the right order
ai_log("DestroySurroundings() directional window hit",3)
obstacle.attack_generic(src,rand(melee_damage_lower,melee_damage_upper),attacktext)
obstacle.attack_generic(src, damage_to_do, attacktext)
return
else if(obstacle.is_fulltile())
ai_log("DestroySurroundings() full tile window hit",3)
obstacle.attack_generic(src, damage_to_do, attacktext)
return
var/obj/structure/obstacle = locate(/obj/structure, problem_turf)
if(istype(obstacle, /obj/structure/window) || istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table) || istype(obstacle, /obj/structure/grille))
ai_log("DestroySurroundings() generic structure hit [obstacle]",3)
obstacle.attack_generic(src,rand(melee_damage_lower,melee_damage_upper),attacktext)
obstacle.attack_generic(src, damage_to_do ,attacktext)
return
for(var/obj/machinery/door/baddoor in problem_turf) //Required since firelocks take up the same turf
if(baddoor.density)
ai_log("DestroySurroundings() door hit [baddoor]",3)
baddoor.attack_generic(src,rand(melee_damage_lower,melee_damage_upper),attacktext)
baddoor.attack_generic(src, damage_to_do ,attacktext)
return
//Check for shuttle bumrush
@@ -0,0 +1,58 @@
/mob/living/simple_animal/slime/FindTarget()
if(victim) // Don't worry about finding another target if we're eatting someone.
return
// if(!will_hunt())
// return
..()
/mob/living/simple_animal/slime/special_target_check(mob/living/L)
if(istype(L, /mob/living/simple_animal/slime))
var/mob/living/simple_animal/slime/buddy = L
if(buddy.slime_color == src.slime_color || discipline || unity || buddy.unity)
return FALSE // Don't hurt same colored slimes.
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.species && H.species.name == "Promethean")
return FALSE // Prometheans are always our friends.
else if(istype(H.species, /datum/species/monkey)) // istype() is so they'll eat the alien monkeys too.
return TRUE // Monkeys are always food.
if(discipline && !rabid)
return FALSE // We're a good slime. For now at least
if(issilicon(L) || isbot(L) )
if(discipline && !rabid)
return FALSE // We're a good slime. For now at least.
return ..() // Other colors and nonslimes are jerks however.
/mob/living/simple_animal/slime/ClosestDistance()
if(target_mob.stat == DEAD)
return 1 // Melee (eat) the target if dead, don't shoot it.
return ..()
/mob/living/simple_animal/slime/HelpRequested(var/mob/living/simple_animal/slime/buddy)
if(istype(buddy))
if(buddy.slime_color != src.slime_color && (!unity || !buddy.unity)) // We only help slimes of the same color, if it's another slime calling for help.
ai_log("HelpRequested() by [buddy] but they are a [buddy.slime_color] while we are a [src.slime_color].",2)
return
if(buddy.target_mob)
if(!special_target_check(buddy.target_mob))
ai_log("HelpRequested() by [buddy] but special_target_check() failed when passed [buddy.target_mob].",2)
return
..()
/mob/living/simple_animal/slime/handle_resist()
if(buckled && victim && isliving(buckled) && victim == buckled) // If it's buckled to a living thing it's probably eating it.
return
else
..()
/*
/mob/living/simple_animal/slime/proc/will_hunt() // Check for being stopped from feeding and chasing
if(nutrition <= get_starve_nutrition() || rabid)
return TRUE
if(nutrition <= get_hunger_nutrition() || prob(25))
return TRUE
return FALSE
*/
@@ -0,0 +1,276 @@
/*
// Check target_mob if worthy of attack
/mob/living/simple_animal/slime/SA_attackable(target_mob)
ai_log("SA_attackable([target_mob])",3)
if(isliving(target_mob))
var/mob/living/L = target_mob
if(L.stat == DEAD)
if(can_consume(L)) // If we can eat them, then it doesn't matter if they're dead.
return TRUE
..()
*/
/mob/living/simple_animal/slime/PunchTarget()
if(victim)
return // Already eatting someone.
if(!client) // AI controlled.
if( (!target_mob.lying && prob(60 + (power_charge * 4) ) || (!target_mob.lying && optimal_combat) )) // "Smart" slimes always stun first.
a_intent = I_DISARM // Stun them first.
else if(can_consume(target_mob) && target_mob.lying)
a_intent = I_GRAB // Then eat them.
else
a_intent = I_HURT // Otherwise robust them.
ai_log("PunchTarget() will [a_intent] [target_mob]",2)
..()
/mob/living/simple_animal/slime/proc/can_consume(var/mob/living/L)
if(!L || !istype(L))
to_chat(src, "This subject is incomparable...")
return FALSE
if(L.isSynthetic())
to_chat(src, "This subject is not biological...")
return FALSE
if(L.getarmor(null, "bio") >= 75)
to_chat(src, "I cannot reach this subject's biological matter...")
return FALSE
if(istype(L, /mob/living/simple_animal/slime))
to_chat(src, "I cannot feed on other slimes...")
return FALSE
if(!Adjacent(L))
to_chat(src, "This subject is too far away...")
return FALSE
if(istype(L, /mob/living/carbon) && L.getCloneLoss() >= L.getMaxHealth() * 1.5 || istype(L, /mob/living/simple_animal) && L.stat == DEAD)
to_chat(src, "This subject does not have an edible life energy...")
return FALSE
if(L.buckled_mob)
if(istype(L.buckled_mob, /mob/living/simple_animal/slime))
if(L.buckled_mob != src)
to_chat(src, "\The [L.buckled_mob] is already feeding on this subject...")
return FALSE
return TRUE
/mob/living/simple_animal/slime/proc/start_consuming(var/mob/living/L)
if(!can_consume(L))
return
if(!Adjacent(L))
return
step_towards(src, L) // Get on top of them to feed.
if(loc != L.loc)
return
if(L.buckle_mob(src, forced = TRUE))
victim = L
update_icon()
victim.visible_message("<span class='danger'>\The [src] latches onto [victim]!</span>",
"<span class='danger'>\The [src] latches onto you!</span>")
/mob/living/simple_animal/slime/proc/stop_consumption()
if(!victim)
return
victim.unbuckle_mob()
victim.visible_message("<span class='notice'>\The [src] slides off of [victim]!</span>",
"<span class='notice'>\The [src] slides off of you!</span>")
victim = null
update_icon()
/mob/living/simple_animal/slime/proc/handle_consumption()
if(victim && can_consume(victim) && !stat)
var/armor_modifier = abs((victim.getarmor(null, "bio") / 100) - 1)
if(istype(victim, /mob/living/carbon))
victim.adjustCloneLoss(rand(5,6) * armor_modifier)
victim.adjustToxLoss(rand(1,2) * armor_modifier)
if(victim.health <= 0)
victim.adjustToxLoss(rand(2,4) * armor_modifier)
else if(istype(victim, /mob/living/simple_animal))
victim.adjustBruteLoss(is_adult ? rand(7, 15) : rand(4, 12))
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>")
stop_consumption()
adjust_nutrition(50 * armor_modifier)
adjustOxyLoss(-10 * armor_modifier) //Heal yourself
adjustBruteLoss(-10 * armor_modifier)
adjustFireLoss(-10 * armor_modifier)
adjustCloneLoss(-10 * armor_modifier)
updatehealth()
if(victim)
victim.updatehealth()
else
stop_consumption()
/mob/living/simple_animal/slime/DoPunch(var/mob/living/L)
if(!Adjacent(L)) // Might've moved away in the meantime.
return
if(istype(L))
if(ishuman(L))
var/mob/living/carbon/human/H = L
// Slime attacks can be blocked with shields.
if(H.check_shields(damage = 0, damage_source = null, attacker = src, def_zone = null, attack_text = "the attack"))
return
switch(a_intent)
if(I_HELP)
ai_log("DoPunch() against [L], helping.",2)
L.visible_message("<span class='notice'>[src] gently pokes [L]!</span>",
"<span class='notice'>[src] gently pokes you!</span>")
do_attack_animation(L)
post_attack(L, a_intent)
if(I_DISARM)
ai_log("DoPunch() against [L], disarming.",2)
var/stun_power = between(0, power_charge + rand(0, 3), 10)
if(ishuman(L))
var/mob/living/carbon/human/H = L
stun_power *= max(H.species.siemens_coefficient,0)
if(prob(stun_power * 10))
power_charge = max(0, power_charge - 3)
L.visible_message("<span class='danger'>[src] has shocked [L]!</span>", "<span class='danger'>[src] has shocked you!</span>")
playsound(src, 'sound/weapons/Egloves.ogg', 75, 1)
L.Weaken(4)
L.Stun(4)
do_attack_animation(L)
if(L.buckled)
L.buckled.unbuckle_mob() // To prevent an exploit where being buckled prevents slimes from jumping on you.
L.stuttering = max(L.stuttering, stun_power)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, L)
s.start()
if(prob(stun_power * 10) && stun_power >= 8)
L.adjustFireLoss(power_charge * rand(1, 2))
post_attack(L, a_intent)
else if(prob(40))
L.visible_message("<span class='danger'>[src] has pounced at [L]!</span>", "<span class='danger'>[src] has pounced at you!</span>")
playsound(src, 'sound/weapons/thudswoosh.ogg', 75, 1)
L.Weaken(2)
do_attack_animation(L)
if(L.buckled)
L.buckled.unbuckle_mob() // To prevent an exploit where being buckled prevents slimes from jumping on you.
post_attack(L, a_intent)
else
L.visible_message("<span class='danger'>[src] has tried to pounce at [L]!</span>", "<span class='danger'>[src] has tried to pounce at you!</span>")
playsound(src, 'sound/weapons/punchmiss.ogg', 75, 1)
do_attack_animation(L)
L.updatehealth()
return L
if(I_GRAB)
ai_log("DoPunch() against [L], grabbing.",2)
start_consuming(L)
post_attack(L, a_intent)
if(I_HURT)
ai_log("DoPunch() against [L], hurting.",2)
var/damage_to_do = rand(melee_damage_lower, melee_damage_upper)
var/armor_modifier = abs((L.getarmor(null, "bio") / 100) - 1)
L.attack_generic(src, damage_to_do, attacktext)
playsound(src, 'sound/weapons/bite.ogg', 75, 1)
// Give the slime some nutrition, if applicable.
if(!L.isSynthetic())
if(ishuman(L))
if(L.getCloneLoss() < L.getMaxHealth() * 1.5)
adjust_nutrition(damage_to_do * armor_modifier)
else if(istype(L, /mob/living/simple_animal))
if(!isslime(L))
var/mob/living/simple_animal/SA = L
if(!SA.stat)
adjust_nutrition(damage_to_do)
post_attack(L, a_intent)
if(istype(L,/obj/mecha))
var/obj/mecha/M = L
M.attack_generic(src, rand(melee_damage_lower, melee_damage_upper), attacktext)
/mob/living/simple_animal/slime/proc/post_attack(var/mob/living/L, var/intent = I_HURT)
if(intent != I_HELP)
if(L.reagents && L.can_inject() && reagent_injected)
L.reagents.add_reagent(reagent_injected, injection_amount)
/mob/living/simple_animal/slime/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/clothing/head)) // Handle hat simulator.
give_hat(W, user)
return
// Otherwise they're probably fighting the slime.
if(prob(25))
visible_message("<span class='danger'>\The [user]'s [W] passes right through [src]!</span>")
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
return
..()
/mob/living/simple_animal/slime/hit_with_weapon(obj/item/O, mob/living/user, var/effective_force, var/hit_zone)
..()
if(!stat)
if(O.force > 0 && discipline && !rabid) // wow, buddy, why am I getting attacked??
adjust_discipline(1)
return
if(O.force >= 3)
if(victim || target_mob) // We've been a bad slime.
if(is_adult)
if(prob(5 + round(O.force / 2)) )
if(prob(80) && !client)
adjust_discipline(2)
if(user)
step_away(src, user)
else
if(prob(10 + O.force * 2))
if(prob(80) && !client)
adjust_discipline(2)
if(user)
step_away(src, user)
else
if(user in friends) // Friend attacking us for no reason.
if(prob(25))
friends -= user
say("[user]... not friend...")
/mob/living/simple_animal/slime/attack_hand(mob/living/carbon/human/M as mob)
if(victim) // Are we eating someone?
var/fail_odds = 30
if(victim == M) // Harder to get the slime off if its eating you right now.
fail_odds = 60
if(prob(fail_odds))
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(40) && !client)
adjust_discipline(1)
stop_consumption()
step_away(src,M)
else
if(M.a_intent == I_HELP)
if(hat)
remove_hat(M)
else
..()
else
..()
// Shocked grilles don't hurt slimes, and in fact give them charge.
/mob/living/simple_animal/slime/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null)
power_charge = between(0, power_charge + round(shock_damage / 10), 10)
to_chat(src, "<span class='notice'>\The [source] shocks you, and it charges you.</span>")
@@ -0,0 +1,24 @@
/mob/living/simple_animal/slime/death(gibbed)
if(stat == DEAD)
return
if(!gibbed && is_adult)
var/mob/living/simple_animal/slime/S = make_new_slime()
S.rabid = TRUE
step_away(S, src)
is_adult = FALSE
maxHealth = initial(maxHealth)
revive()
if(!client)
rabid = TRUE
number = rand(1, 1000)
update_name()
return
stop_consumption()
. = ..(gibbed, "stops moving and partially dissolves...")
update_icon()
return
@@ -0,0 +1,174 @@
/mob/living/simple_animal/slime/proc/adjust_nutrition(input)
nutrition = between(0, nutrition + input, get_max_nutrition())
if(input > 0)
if(prob(input * 2)) // Gain around one level per 50 nutrition
power_charge = min(power_charge++, 10)
if(power_charge == 10)
adjustToxLoss(-10)
/mob/living/simple_animal/slime/proc/get_max_nutrition() // Can't go above it
if(is_adult)
return 1200
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
return 800
/mob/living/simple_animal/slime/proc/get_hunger_nutrition() // Below it we will always eat
if(is_adult)
return 600
return 500
/mob/living/simple_animal/slime/proc/get_starve_nutrition() // Below it we will eat before everything else
if(is_adult)
return 300
return 200
/mob/living/simple_animal/slime/proc/handle_nutrition()
if(docile)
return
if(prob(15))
adjust_nutrition(-1 - is_adult)
if(nutrition <= get_starve_nutrition())
handle_starvation()
else if(nutrition >= get_grow_nutrition() && amount_grown < 10)
adjust_nutrition(-20)
amount_grown = between(0, amount_grown + 1, 10)
/mob/living/simple_animal/slime/proc/handle_starvation()
if(nutrition < get_starve_nutrition() && !client) // if a slime is starving, it starts losing its friends
if(friends.len && prob(1))
var/mob/nofriend = pick(friends)
if(nofriend)
friends -= nofriend
say("[nofriend]... food now...")
if(nutrition <= 0)
adjustToxLoss(rand(1,3))
if(client && prob(5))
to_chat(src, "<span class='danger'>You are starving!</span>")
/mob/living/simple_animal/slime/proc/handle_discipline()
if(discipline > 0)
update_mood()
// if(discipline >= 5 && rabid)
// if(prob(60))
// rabid = 0
// adjust_discipline(1) // So it stops trying to murder everyone.
// Handle discipline decay.
if(!prob(75 + (obedience * 5)))
adjust_discipline(-1)
if(!discipline)
update_mood()
/mob/living/simple_animal/slime/handle_regular_status_updates()
if(stat != DEAD)
handle_nutrition()
handle_discipline()
if(prob(30))
adjustOxyLoss(-1)
adjustToxLoss(-1)
adjustFireLoss(-1)
adjustCloneLoss(-1)
adjustBruteLoss(-1)
if(victim)
handle_consumption()
if(amount_grown >= 10 && !target_mob && !client)
if(is_adult)
reproduce()
else
evolve()
handle_stuttering()
..()
// This is to make slime responses feel a bit more natural and not instant.
/mob/living/simple_animal/slime/proc/delayed_say(var/message, var/mob/target)
sleep(rand(1 SECOND, 2 SECONDS))
if(target)
face_atom(target)
say(message)
//Commands, reactions, etc
/mob/living/simple_animal/slime/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
..()
if((findtext(message, num2text(number)) || findtext(message, name) || findtext(message, "slimes"))) // Talking to us
// Say hello back.
if(findtext(message, "hello") || findtext(message, "hi") || findtext(message, "greetings"))
delayed_say(pick("Hello...", "Hi..."), speaker)
// Follow request.
if(findtext(message, "follow") || findtext(message, "come with me"))
if(!can_command(speaker))
delayed_say(pick("No...", "I won't follow..."), speaker)
return
delayed_say("Yes... I follow \the [speaker]...", speaker)
set_follow(speaker)
FollowTarget()
// Stop request.
if(findtext(message, "stop") || findtext(message, "halt") || findtext(message, "cease"))
if(victim) // We're being asked to stop eatting someone.
if(!can_command(speaker))
delayed_say("No...", speaker)
return
else
delayed_say("Fine...", speaker)
stop_consumption()
adjust_discipline(1, TRUE)
if(target_mob) // We're being asked to stop chasing someone.
if(!can_command(speaker))
delayed_say("No...", speaker)
return
else
delayed_say("Fine...", speaker)
LoseTarget()
adjust_discipline(1, TRUE)
if(follow_mob) // We're being asked to stop following someone.
if(follow_mob == speaker)
delayed_say("Yes... I'll stop...", speaker)
LoseFollow()
else
delayed_say("No... I'll keep following \the [follow_mob]...", speaker)
// Help request
if(findtext(message, "help"))
if(!can_command(speaker))
delayed_say("No...", speaker)
return
else
delayed_say("I will protect \the [speaker].", speaker)
// Murder request
if(findtext(message, "harm") || findtext(message, "kill") || findtext(message, "murder") || findtext(message, "eat") || findtext(message, "consume"))
if(!can_command(speaker))
delayed_say("No...", speaker)
return
//LoseFollow()
/*
if(reacts && speaker && (message in reactions) && (!hostile || isliving(speaker)) && say_understands(speaker,language))
var/mob/living/L = speaker
if(L.faction == faction)
spawn(10)
face_atom(speaker)
say(reactions[message])
*/
@@ -0,0 +1,436 @@
/mob/living/simple_animal/slime
name = "baby slime"
desc = "The most basic of slimes. The grey slime has no remarkable qualities, however it remains one of the most useful colors for scientists."
icon = 'icons/mob/slime2.dmi'
icon_state = "grey baby slime"
intelligence_level = SA_ANIMAL
pass_flags = PASSTABLE
var/shiny = FALSE // If true, will add a 'shiny' overlay.
var/glows = FALSE // If true, will glow in the same color as the color var.
var/icon_state_override = null // Used for special slime appearances like the rainbow slime.
pass_flags = PASSTABLE
speak_emote = list("chirps")
maxHealth = 150
var/maxHealth_adult = 200
melee_damage_lower = 5
melee_damage_upper = 25
melee_miss_chance = 0
gender = NEUTER
// Atmos stuff.
minbodytemp = T0C-30
heat_damage_per_tick = 0
cold_damage_per_tick = 40
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
unsuitable_atoms_damage = 0
speak = list(
"Blorp...",
"Blop..."
)
emote_hear = list(
)
emote_see = list(
"bounces",
"jiggles",
"sways"
)
hostile = 1
retaliate = 1
attack_same = 1
cooperative = 1
faction = "slime" // Slimes will help other slimes, provided they share the same color.
color = "#CACACA"
var/is_adult = FALSE
var/cores = 1 // How many cores you get when placed in a Processor.
var/power_charge = 0 // 0-10 controls how much electricity they are generating. High numbers encourage the slime to stun someone with electricity.
var/amount_grown = 0 // controls how long the slime has been overfed, if 10, grows or reproduces
var/number = 0 // This is used to make the slime semi-unique for indentification.
var/mob/living/victim = null // the person the slime is currently feeding on
var/rabid = FALSE // If true, will attack anyone and everyone.
var/docile = FALSE // Basically the opposite of above. If true, will never harm anything and won't get hungry.
var/discipline = 0 // Beating slimes makes them less likely to lash out. In theory.
var/resentment = 0 // 'Unjustified' beatings make this go up, and makes it more likely for abused slimes to go berserk.
var/obedience = 0 // Conversely, 'justified' beatings make this go up, and makes discipline decay slowly, potentially making it not decay at all.
var/unity = FALSE // If true, slimes will consider other colors as their own. Other slimes will see this slime as the same color as well. A rainbow slime is required to get this.
var/optimal_combat = FALSE // Used to dumb down the combat AI somewhat. If true, the slime tends to be really dangerous to fight alone due to stunlocking.
var/mood = ":3" // Icon to use to display 'mood'.
var/obj/item/clothing/head/hat = null // The hat the slime may be wearing.
var/slime_color = "grey"
var/mutation_chance = 25 // Odds of spawning as a new color when reproducing. Can be modified by certain xenobio products. Carried across generations of slimes.
var/coretype = /obj/item/slime_extract/grey
// List of potential slime color mutations. This must have exactly four types.
var/list/slime_mutation = list(
/mob/living/simple_animal/slime/orange,
/mob/living/simple_animal/slime/metal,
/mob/living/simple_animal/slime/blue,
/mob/living/simple_animal/slime/purple
)
var/reagent_injected = null // Some slimes inject reagents on attack. This tells the game what reagent to use.
var/injection_amount = 5 // This determines how much.
/mob/living/simple_animal/slime/New(var/location, var/start_as_adult = FALSE)
verbs += /mob/living/proc/ventcrawl
if(start_as_adult)
make_adult()
health = maxHealth
// slime_mutation = mutation_table(slime_color)
update_icon()
number = rand(1, 1000)
update_name()
..(location)
/mob/living/simple_animal/slime/Destroy()
if(hat)
drop_hat()
return ..()
/mob/living/simple_animal/slime/proc/make_adult()
if(is_adult)
return
is_adult = TRUE
melee_damage_lower = 20
melee_damage_upper = 40
maxHealth = maxHealth_adult
amount_grown = 0
update_icon()
update_name()
/mob/living/simple_animal/slime/proc/update_name()
if(docile) // Docile slimes are generally named, so we shouldn't mess with it.
return
name = "[slime_color] [is_adult ? "adult" : "baby"] slime ([number])"
real_name = name
/mob/living/simple_animal/slime/update_icon()
if(stat == DEAD)
icon_state = "[icon_state_override ? "[icon_state_override] slime" : "slime"] [is_adult ? "adult" : "baby"] dead"
set_light(0)
else
if(incapacitated(INCAPACITATION_DISABLED))
icon_state = "[icon_state_override ? "[icon_state_override] slime" : "slime"] [is_adult ? "adult" : "baby"] dead"
else
icon_state = "[icon_state_override ? "[icon_state_override] slime" : "slime"] [is_adult ? "adult" : "baby"][victim ? " eating":""]"
overlays.Cut()
if(stat != DEAD)
var/image/I = image(icon, src, "slime light")
I.appearance_flags = RESET_COLOR
overlays += I
if(shiny)
I = image(icon, src, "slime shiny")
I.appearance_flags = RESET_COLOR
overlays += I
I = image(icon, src, "aslime-[mood]")
I.appearance_flags = RESET_COLOR
overlays += I
if(glows)
set_light(3, 2, color)
if(hat)
var/hat_state = hat.item_state ? hat.item_state : hat.icon_state
var/image/I = image('icons/mob/head.dmi', src, hat_state)
I.pixel_y = -7 // Slimes are small.
I.appearance_flags = RESET_COLOR
overlays += I
if(modifier_overlay) // Restore our modifier overlay.
overlays += modifier_overlay
/mob/living/simple_animal/slime/proc/update_mood()
var/old_mood = mood
if(incapacitated(INCAPACITATION_DISABLED))
mood = "sad"
else if(rabid)
mood = "angry"
else if(target_mob)
mood = "mischevous"
else if(discipline)
mood = "pout"
else if(docile)
mood = ":33"
else
mood = ":3"
if(old_mood != mood)
update_icon()
// Makes the slime very angry and dangerous.
/mob/living/simple_animal/slime/proc/enrage()
if(docile)
return
rabid = TRUE
update_mood()
visible_message("<span class='danger'>\The [src] enrages!</span>")
// Makes the slime safe and harmless.
/mob/living/simple_animal/slime/proc/pacify()
rabid = FALSE
docile = TRUE
hostile = FALSE
retaliate = FALSE
cooperative = FALSE
// If for whatever reason the mob AI decides to try to attack something anyways.
melee_damage_upper = 0
melee_damage_lower = 0
update_mood()
/mob/living/simple_animal/slime/proc/unify()
unity = TRUE
attack_same = FALSE
/mob/living/simple_animal/slime/examine(mob/user)
..()
if(hat)
to_chat(user, "It is wearing \a [hat].")
if(stat == DEAD)
to_chat(user, "It appears to be dead.")
else if(incapacitated(INCAPACITATION_DISABLED))
to_chat(user, "It appears to be incapacitated.")
else if(rabid)
to_chat(user, "It seems very, very angry and upset.")
else if(obedience >= 5)
to_chat(user, "It looks rather obedient.")
else if(discipline)
to_chat(user, "It has been subjugated by force, at least for now.")
else if(docile)
to_chat(user, "It appears to have been pacified.")
/mob/living/simple_animal/slime/water_act(amount) // This is called if a slime enters a water tile.
adjustBruteLoss(40 * amount)
/mob/living/simple_animal/slime/proc/adjust_discipline(amount, silent)
if(amount > 0)
if(!rabid)
var/justified = is_justified_to_discipline()
spawn(0)
stop_consumption()
LoseTarget()
if(!silent)
if(justified)
say(pick("Fine...", "Okay...", "Sorry...", "I yield...", "Mercy..."))
else
say(pick("Why...?", "I don't understand...?", "Cruel...", "Stop...", "Nooo..."))
if(justified)
obedience++
else
if(prob(resentment * 20))
enrage() // Pushed the slime too far.
say(pick("Evil...", "Kill...", "Tyrant..."))
resentment++ // Done after check so first time will never enrage.
discipline = between(0, discipline + amount, 10)
/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
. += config.slime_delay
/mob/living/simple_animal/slime/Process_Spacemove()
return 2
/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, "<span class='notice'>I must be conscious to do this...</span>")
return
if(docile)
to_chat(src, "<span class='notice'>I have been pacified. I cannot evolve...</span>")
return
if(!is_adult)
if(amount_grown >= 10)
make_adult()
else
to_chat(src, "<span class='notice'>I am not ready to evolve yet...</span>")
else
to_chat(src, "<span class='notice'>I have already evolved...</span>")
/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, "<span class='notice'>I must be conscious to do this...</span>")
return
if(docile)
to_chat(src, "<span class='notice'>I have been pacified. I cannot reproduce...</span>")
return
if(is_adult)
if(amount_grown >= 10)
var/list/babies = list()
for(var/i = 1 to 4)
babies.Add(make_new_slime())
var/mob/living/simple_animal/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, "<span class='notice'>I am not ready to reproduce yet...</span>")
else
to_chat(src, "<span class='notice'>I am not old enough to reproduce yet...</span>")
// Used for reproducing and dying.
/mob/living/simple_animal/slime/proc/make_new_slime()
var/t = src.type
if(prob(mutation_chance / 10))
t = /mob/living/simple_animal/slime/rainbow
else if(prob(mutation_chance) && slime_mutation.len)
t = slime_mutation[rand(1, slime_mutation.len)]
var/mob/living/simple_animal/slime/baby = new t(loc)
// Handle 'inheriting' from parent slime.
baby.mutation_chance = mutation_chance
baby.power_charge = round(power_charge / 4)
baby.resentment = max(resentment - 1, 0)
baby.discipline = max(discipline - 1, 0)
baby.obedience = max(obedience - 1, 0)
baby.unity = unity
baby.faction = faction
baby.friends = friends.Copy()
if(rabid)
baby.enrage()
step_away(baby, src)
return baby
/mob/living/simple_animal/slime/speech_bubble_appearance()
return "slime"
// Called after they finish eatting someone.
/mob/living/simple_animal/slime/proc/befriend(var/mob/living/friend)
if(!(friend in friends))
friends |= friend
say("[friend]... friend...")
/mob/living/simple_animal/slime/proc/can_command(var/mob/living/commander)
if(rabid)
return FALSE
if(docile)
return TRUE
if(commander in friends)
return TRUE
if(faction == commander.faction)
return TRUE
if(discipline > resentment && obedience >= 5)
return TRUE
return FALSE
/mob/living/simple_animal/slime/proc/give_hat(var/obj/item/clothing/head/new_hat, var/mob/living/user)
if(!istype(new_hat))
to_chat(user, "<span class='warning'>\The [new_hat] isn't a hat.</span>")
return
if(hat)
to_chat(user, "<span class='warning'>\The [src] is already wearing \a [hat].</span>")
return
else
user.drop_item(new_hat)
hat = new_hat
new_hat.forceMove(src)
to_chat(user, "<span class='notice'>You place \a [new_hat] on \the [src]. How adorable!</span>")
update_icon()
return
/mob/living/simple_animal/slime/proc/remove_hat(var/mob/living/user)
if(!hat)
to_chat(user, "<span class='warning'>\The [src] doesn't have a hat to remove.</span>")
else
hat.forceMove(get_turf(src))
user.put_in_hands(hat)
to_chat(user, "<span class='warning'>You take away \the [src]'s [hat.name]. How mean.</span>")
hat = null
update_icon()
/mob/living/simple_animal/slime/proc/drop_hat()
if(!hat)
return
hat.forceMove(get_turf(src))
hat = null
update_icon()
// Checks if disciplining the slime would be 'justified' right now.
/mob/living/simple_animal/slime/proc/is_justified_to_discipline()
if(rabid)
return TRUE
if(target_mob)
if(ishuman(target_mob))
var/mob/living/carbon/human/H = target_mob
if(istype(H.species, /datum/species/monkey))
return FALSE
return TRUE
return FALSE
/mob/living/simple_animal/slime/get_description_interaction()
var/list/results = list()
if(!stat)
results += "[desc_panel_image("slimebaton")]to stun the slime, if it's being bad."
results += ..()
return results
/mob/living/simple_animal/slime/get_description_info()
var/list/lines = list()
var/intro_line = "Slimes are generally the test subjects of Xenobiology, with different colors having different properties. \
They can be extremely dangerous if not handled properly."
lines.Add(intro_line)
lines.Add(null) // To pad the line breaks.
var/list/rewards = list()
for(var/potential_color in slime_mutation)
var/mob/living/simple_animal/slime/S = potential_color
rewards.Add(initial(S.slime_color))
var/reward_line = "This color of slime can mutate into [english_list(rewards)] colors, when it reproduces. It will do so when it has eatten enough."
lines.Add(reward_line)
lines.Add(null)
lines.Add(description_info)
return lines.Join("\n")
@@ -0,0 +1,709 @@
// Tier 1
/mob/living/simple_animal/slime/purple
desc = "This slime is rather toxic to handle, as it is poisonous."
color = "#CC23FF"
slime_color = "purple"
coretype = /obj/item/slime_extract/purple
reagent_injected = "toxin"
description_info = "This slime spreads a toxin when it attacks. A biosuit or other thick armor can protect from the toxic attack."
slime_mutation = list(
/mob/living/simple_animal/slime/dark_purple,
/mob/living/simple_animal/slime/dark_blue,
/mob/living/simple_animal/slime/green,
/mob/living/simple_animal/slime
)
/mob/living/simple_animal/slime/orange
desc = "This slime is known to be flammable and can ignite enemies."
color = "#FFA723"
slime_color = "orange"
coretype = /obj/item/slime_extract/orange
description_info = "Attacks from this slime can ignite you. A firesuit can protect from the burning attacks of this slime."
slime_mutation = list(
/mob/living/simple_animal/slime/dark_purple,
/mob/living/simple_animal/slime/yellow,
/mob/living/simple_animal/slime/red,
/mob/living/simple_animal/slime
)
/mob/living/simple_animal/slime/orange/post_attack(mob/living/L, intent)
if(intent != I_HELP)
L.adjust_fire_stacks(1)
if(prob(25))
L.IgniteMob()
..()
/mob/living/simple_animal/slime/blue
desc = "This slime produces 'cryotoxin' and uses it against their foes. Very deadly to other slimes."
color = "#19FFFF"
slime_color = "blue"
coretype = /obj/item/slime_extract/blue
reagent_injected = "cryotoxin"
description_info = "Attacks from this slime can chill you. A biosuit or other thick armor can protect from the chilling attack."
slime_mutation = list(
/mob/living/simple_animal/slime/dark_blue,
/mob/living/simple_animal/slime/silver,
/mob/living/simple_animal/slime/pink,
/mob/living/simple_animal/slime
)
/mob/living/simple_animal/slime/metal
desc = "This slime is a lot more resilient than the others, due to having a metamorphic metallic and sloped surface."
color = "#5F5F5F"
slime_color = "metal"
shiny = 1
coretype = /obj/item/slime_extract/metal
description_info = "This slime is a lot more durable and tough to damage than the others."
resistance = 10 // Sloped armor is strong.
maxHealth = 250
maxHealth_adult = 350
slime_mutation = list(
/mob/living/simple_animal/slime/silver,
/mob/living/simple_animal/slime/yellow,
/mob/living/simple_animal/slime/gold,
/mob/living/simple_animal/slime
)
// Tier 2
/mob/living/simple_animal/slime/yellow
desc = "This slime is very conductive, and is known to use electricity as a means of defense moreso than usual for slimes."
color = "#FFF423"
slime_color = "yellow"
coretype = /obj/item/slime_extract/yellow
ranged = 1
shoot_range = 3
firing_lines = 1
projectiletype = /obj/item/projectile/beam/lightning/slime
projectilesound = 'sound/weapons/gauss_shoot.ogg' // Closest thing to a 'thunderstrike' sound we have.
glows = TRUE
description_info = "This slime will fire lightning attacks at enemies if they are at range, and generate electricity \
for their stun attack faster than usual. Insulative or reflective armor can protect from the lightning."
slime_mutation = list(
/mob/living/simple_animal/slime/bluespace,
/mob/living/simple_animal/slime/bluespace,
/mob/living/simple_animal/slime/metal,
/mob/living/simple_animal/slime/orange
)
/mob/living/simple_animal/slime/yellow/handle_regular_status_updates()
if(stat == CONSCIOUS)
if(prob(25))
power_charge = between(0, power_charge + 1, 10)
..()
/obj/item/projectile/beam/lightning/slime
power = 15
/mob/living/simple_animal/slime/yellow/ClosestDistance() // Needed or else they won't eat monkeys outside of melee range.
if(target_mob && ishuman(target_mob))
var/mob/living/carbon/human/H = target_mob
if(istype(H.species, /datum/species/monkey))
return 1
return ..()
/mob/living/simple_animal/slime/dark_purple
desc = "This slime produces ever-coveted phoron. Risky to handle but very much worth it."
color = "#CC23FF"
slime_color = "dark purple"
coretype = /obj/item/slime_extract/dark_purple
reagent_injected = "phoron"
description_info = "This slime applies phoron to enemies it attacks. A biosuit or other thick armor can protect from the toxic attack. \
If hit with a burning attack, it will erupt in flames."
slime_mutation = list(
/mob/living/simple_animal/slime/purple,
/mob/living/simple_animal/slime/orange,
/mob/living/simple_animal/slime/ruby,
/mob/living/simple_animal/slime/ruby
)
/mob/living/simple_animal/slime/dark_purple/proc/ignite()
visible_message("<span class='danger'>\The [src] erupts in an inferno!</span>")
for(var/turf/simulated/target_turf in view(2, src))
target_turf.assume_gas("phoron", 30, 1500+T0C)
spawn(0)
target_turf.hotspot_expose(1500+T0C, 400)
qdel(src)
/mob/living/simple_animal/slime/dark_purple/ex_act(severity)
log_and_message_admins("[src] ignited due to a chain reaction with an explosion.")
ignite()
/mob/living/simple_animal/slime/dark_purple/fire_act(datum/gas_mixture/air, temperature, volume)
log_and_message_admins("[src] ignited due to exposure to fire.")
ignite()
/mob/living/simple_animal/slime/dark_purple/bullet_act(var/obj/item/projectile/P, var/def_zone)
if(P.damage_type && P.damage_type == BURN && P.damage) // Most bullets won't trigger the explosion, as a mercy towards Security.
log_and_message_admins("[src] ignited due to bring hit by a burning projectile[P.firer ? " by [key_name(P.firer)]" : ""].")
ignite()
else
..()
/mob/living/simple_animal/slime/dark_purple/attackby(var/obj/item/weapon/W, var/mob/user)
if(istype(W) && W.force && W.damtype == BURN)
log_and_message_admins("[src] ignited due to being hit with a burning weapon ([W]) by [key_name(user)].")
ignite()
else
..()
/mob/living/simple_animal/slime/dark_blue
desc = "This slime makes other entities near it feel much colder, and is more resilient to the cold. It tends to kill other slimes rather quickly."
color = "#2398FF"
glows = TRUE
slime_color = "dark blue"
coretype = /obj/item/slime_extract/dark_blue
description_info = "This slime is immune to the cold, however water will still kill it. A winter coat or other cold-resistant clothing can protect from the chilling aura."
slime_mutation = list(
/mob/living/simple_animal/slime/purple,
/mob/living/simple_animal/slime/blue,
/mob/living/simple_animal/slime/cerulean,
/mob/living/simple_animal/slime/cerulean
)
minbodytemp = 0
cold_damage_per_tick = 0
/mob/living/simple_animal/slime/dark_blue/Life()
if(stat != DEAD)
cold_aura()
..()
/mob/living/simple_animal/slime/dark_blue/proc/cold_aura()
for(var/mob/living/L in view(2, src))
var/protection = L.get_cold_protection()
if(protection < 1)
var/cold_factor = abs(protection - 1)
var/delta = -20
delta *= cold_factor
L.bodytemperature = max(50, delta)
var/turf/T = get_turf(src)
var/datum/gas_mixture/env = T.return_air()
if(env)
env.add_thermal_energy(-10 * 1000)
/mob/living/simple_animal/slime/silver
desc = "This slime is shiny, and can deflect lasers or other energy weapons directed at it."
color = "#AAAAAA"
slime_color = "silver"
coretype = /obj/item/slime_extract/silver
shiny = TRUE
description_info = "Tasers, including the slime version, are ineffective against this slime. The slimebation still works."
slime_mutation = list(
/mob/living/simple_animal/slime/metal,
/mob/living/simple_animal/slime/blue,
/mob/living/simple_animal/slime/amber,
/mob/living/simple_animal/slime/amber
)
/mob/living/simple_animal/slime/silver/bullet_act(var/obj/item/projectile/P, var/def_zone)
if(istype(P,/obj/item/projectile/beam) || istype(P, /obj/item/projectile/energy))
visible_message("<span class='danger'>\The [src] reflects \the [P]!</span>")
// Find a turf near or on the original location to bounce to
var/new_x = P.starting.x + pick(0, 0, 0, -1, 1, -2, 2)
var/new_y = P.starting.y + pick(0, 0, 0, -1, 1, -2, 2)
var/turf/curloc = get_turf(src)
// redirect the projectile
P.redirect(new_x, new_y, curloc, src)
return PROJECTILE_CONTINUE // complete projectile permutation
else
..()
// Tier 3
/mob/living/simple_animal/slime/bluespace
desc = "Trapping this slime in a cell is generally futile, as it can teleport at will."
color = null
slime_color = "bluespace"
icon_state_override = "bluespace"
coretype = /obj/item/slime_extract/bluespace
description_info = "This slime will teleport to attack something if it is within a range of seven tiles. The teleport has a cooldown of five seconds."
slime_mutation = list(
/mob/living/simple_animal/slime/bluespace,
/mob/living/simple_animal/slime/bluespace,
/mob/living/simple_animal/slime/yellow,
/mob/living/simple_animal/slime/yellow
)
spattack_prob = 100
spattack_min_range = 3
spattack_max_range = 7
var/last_tele = null // Uses world.time
var/tele_cooldown = 5 SECONDS
/mob/living/simple_animal/slime/bluespace/ClosestDistance() // Needed or the SA AI won't ever try to teleport.
if(world.time > last_tele + tele_cooldown)
return spattack_max_range - 1
return ..()
/mob/living/simple_animal/slime/bluespace/SpecialAtkTarget()
// Teleport attack.
if(!target_mob)
to_chat(src, "<span class='warning'>There's nothing to teleport to.</span>")
return FALSE
if(world.time < last_tele + tele_cooldown)
to_chat(src, "<span class='warning'>You can't teleport right now, wait a few seconds.</span>")
return FALSE
var/list/nearby_things = range(1, target_mob)
var/list/valid_turfs = list()
// All this work to just go to a non-dense tile.
for(var/turf/potential_turf in nearby_things)
var/valid_turf = TRUE
if(potential_turf.density)
continue
for(var/atom/movable/AM in potential_turf)
if(AM.density)
valid_turf = FALSE
if(valid_turf)
valid_turfs.Add(potential_turf)
var/turf/T = get_turf(src)
var/turf/target_turf = pick(valid_turfs)
if(!target_turf)
to_chat(src, "<span class='warning'>There wasn't an unoccupied spot to teleport to.</span>")
return FALSE
var/datum/effect/effect/system/spark_spread/s1 = new /datum/effect/effect/system/spark_spread
s1.set_up(5, 1, T)
var/datum/effect/effect/system/spark_spread/s2 = new /datum/effect/effect/system/spark_spread
s2.set_up(5, 1, target_turf)
T.visible_message("<span class='notice'>\The [src] vanishes!</span>")
s1.start()
forceMove(target_turf)
playsound(target_turf, 'sound/effects/phasein.ogg', 50, 1)
to_chat(src, "<span class='notice'>You teleport to \the [target_turf].</span>")
target_turf.visible_message("<span class='warning'>\The [src] appears!</span>")
s2.start()
last_tele = world.time
if(Adjacent(target_mob))
PunchTarget()
return TRUE
/mob/living/simple_animal/slime/ruby
desc = "This slime has great physical strength."
color = "#FF3333"
slime_color = "ruby"
shiny = TRUE
glows = TRUE
coretype = /obj/item/slime_extract/ruby
description_info = "This slime is unnaturally stronger, allowing it to hit much harder, take less damage, and be stunned for less time. \
Their glomp attacks also send the victim flying."
slime_mutation = list(
/mob/living/simple_animal/slime/dark_purple,
/mob/living/simple_animal/slime/dark_purple,
/mob/living/simple_animal/slime/ruby,
/mob/living/simple_animal/slime/ruby
)
/mob/living/simple_animal/slime/ruby/New()
..()
add_modifier(/datum/modifier/slime_strength, null, src) // Slime is always swole.
/mob/living/simple_animal/slime/ruby/DoPunch(var/mob/living/L)
..() // Do regular attacks.
if(istype(L))
if(a_intent == I_HURT)
visible_message("<span class='danger'>\The [src] sends \the [L] flying with the impact!</span>")
playsound(src, "punch", 50, 1)
L.Weaken(1)
var/throwdir = get_dir(src, L)
L.throw_at(get_edge_target_turf(L, throwdir), 3, 1, src)
/mob/living/simple_animal/slime/amber
desc = "This slime seems to be an expert in the culinary arts, as they create their own food to share with others. \
They would probably be very important to other slimes, if the other colors didn't try to kill them."
color = "#FFBB00"
slime_color = "amber"
shiny = TRUE
glows = TRUE
coretype = /obj/item/slime_extract/amber
description_info = "This slime feeds nearby entities passively while it is alive. This can cause uncontrollable \
slime growth and reproduction if not kept in check. The amber slime cannot feed itself, but can be fed by other amber slimes."
slime_mutation = list(
/mob/living/simple_animal/slime/silver,
/mob/living/simple_animal/slime/silver,
/mob/living/simple_animal/slime/amber,
/mob/living/simple_animal/slime/amber
)
/mob/living/simple_animal/slime/amber/Life()
if(stat != DEAD)
feed_aura()
..()
/mob/living/simple_animal/slime/amber/proc/feed_aura()
for(var/mob/living/L in view(2, src))
if(L == src) // Don't feed themselves, or it is impossible to stop infinite slimes without killing all of the ambers.
continue
if(isslime(L))
var/mob/living/simple_animal/slime/S = L
S.adjust_nutrition(rand(15, 25))
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.isSynthetic())
continue
H.nutrition = between(0, H.nutrition + rand(15, 25), 600)
/mob/living/simple_animal/slime/cerulean
desc = "This slime is generally superior in a wide range of attributes, compared to the common slime. The jack of all trades, but master of none."
color = "#4F7EAA"
slime_color = "cerulean"
coretype = /obj/item/slime_extract/cerulean
// Less than the specialized slimes, but higher than the rest.
maxHealth = 200
maxHealth_adult = 250
melee_damage_lower = 10
melee_damage_upper = 30
move_to_delay = 3
slime_mutation = list(
/mob/living/simple_animal/slime/dark_blue,
/mob/living/simple_animal/slime/dark_blue,
/mob/living/simple_animal/slime/cerulean,
/mob/living/simple_animal/slime/cerulean
)
// Tier 4
/mob/living/simple_animal/slime/red
desc = "This slime is full of energy, and very aggressive. 'The red ones go faster.' seems to apply here."
color = "#FF3333"
slime_color = "red"
coretype = /obj/item/slime_extract/red
move_to_delay = 3 // The red ones go faster.
description_info = "This slime is faster than the others. Attempting to discipline this slime will always cause it to go berserk."
slime_mutation = list(
/mob/living/simple_animal/slime/red,
/mob/living/simple_animal/slime/oil,
/mob/living/simple_animal/slime/oil,
/mob/living/simple_animal/slime/orange
)
/mob/living/simple_animal/slime/red/adjust_discipline(amount)
if(amount > 0)
if(!rabid)
enrage() // How dare you try to control the red slime.
say("Grrr...!")
/mob/living/simple_animal/slime/green
desc = "This slime is radioactive."
color = "#14FF20"
slime_color = "green"
coretype = /obj/item/slime_extract/green
glows = TRUE
reagent_injected = "radium"
var/rads = 25
description_info = "This slime will irradiate anything nearby passively, and will inject radium on attack. \
A radsuit or other thick and radiation-hardened armor can protect from this. It will only radiate while alive."
slime_mutation = list(
/mob/living/simple_animal/slime/purple,
/mob/living/simple_animal/slime/green,
/mob/living/simple_animal/slime/emerald,
/mob/living/simple_animal/slime/emerald
)
/mob/living/simple_animal/slime/green/Life()
if(stat != DEAD)
irradiate()
..()
/mob/living/simple_animal/slime/green/proc/irradiate()
radiation_repository.radiate(src, rads)
/mob/living/simple_animal/slime/pink
desc = "This slime has regenerative properties."
color = "#FF0080"
slime_color = "pink"
coretype = /obj/item/slime_extract/pink
glows = TRUE
description_info = "This slime will passively heal nearby entities within two tiles, including itself. It will only do this while alive."
slime_mutation = list(
/mob/living/simple_animal/slime/blue,
/mob/living/simple_animal/slime/light_pink,
/mob/living/simple_animal/slime/light_pink,
/mob/living/simple_animal/slime/pink
)
/mob/living/simple_animal/slime/pink/Life()
if(stat != DEAD)
heal_aura()
..()
/mob/living/simple_animal/slime/pink/proc/heal_aura()
for(var/mob/living/L in view(src, 2))
if(L.stat == DEAD || L == target_mob)
continue
L.add_modifier(/datum/modifier/slime_heal, 5 SECONDS, src)
/datum/modifier/slime_heal
name = "slime mending"
desc = "You feel somewhat gooy."
mob_overlay_state = "pink_sparkles"
on_created_text = "<span class='warning'>Twinkling spores of goo surround you. It makes you feel healthier.</span>"
on_expired_text = "<span class='notice'>The spores of goo have faded, although you feel much healthier than before.</span>"
stacks = MODIFIER_STACK_EXTEND
/datum/modifier/slime_heal/tick()
if(holder.stat == DEAD) // Required or else simple animals become immortal.
expire()
holder.adjustBruteLoss(-2)
holder.adjustFireLoss(-2)
holder.adjustToxLoss(-2)
holder.adjustOxyLoss(-2)
holder.adjustCloneLoss(-1)
/mob/living/simple_animal/slime/gold
desc = "This slime absorbs energy, and cannot be stunned by normal means."
color = "#EEAA00"
shiny = TRUE
slime_color = "gold"
coretype = /obj/item/slime_extract/gold
description_info = "This slime is immune to the slimebaton and taser, and will actually charge the slime, however it will still discipline the slime."
slime_mutation = list(
/mob/living/simple_animal/slime/metal,
/mob/living/simple_animal/slime/gold,
/mob/living/simple_animal/slime/sapphire,
/mob/living/simple_animal/slime/sapphire
)
/mob/living/simple_animal/slime/gold/Weaken(amount)
power_charge = between(0, power_charge + amount, 10)
return
/mob/living/simple_animal/slime/gold/Stun(amount)
power_charge = between(0, power_charge + amount, 10)
return
/mob/living/simple_animal/slime/gold/get_description_interaction() // So it doesn't say to use a baton on them.
return list()
// Tier 5
/mob/living/simple_animal/slime/oil
desc = "This slime is explosive and volatile. Smoking near it is probably a bad idea."
color = "#333333"
slime_color = "oil"
shiny = TRUE
coretype = /obj/item/slime_extract/oil
description_info = "If this slime suffers damage from a fire or heat based source, or if it is caught inside \
an explosion, it will explode. Rabid oil slimes will charge at enemies, then suicide-bomb themselves. \
Bomb suits can protect from the explosion."
slime_mutation = list(
/mob/living/simple_animal/slime/oil,
/mob/living/simple_animal/slime/oil,
/mob/living/simple_animal/slime/red,
/mob/living/simple_animal/slime/red
)
/mob/living/simple_animal/slime/oil/proc/explode()
if(stat != DEAD)
// explosion(src.loc, 1, 2, 4)
explosion(src.loc, 0, 2, 4) // A bit weaker since the suicide charger tended to gib the poor sod being targeted.
if(src) // Delete ourselves if the explosion didn't do it.
qdel(src)
/mob/living/simple_animal/slime/oil/post_attack(var/mob/living/L, var/intent = I_HURT)
if(!rabid)
return ..()
if(intent == I_HURT || intent == I_GRAB)
say(pick("Sacrifice...!", "Sssss...", "Boom...!"))
sleep(2 SECOND)
log_and_message_admins("[src] has suicide-bombed themselves while trying to kill \the [L].")
explode()
/mob/living/simple_animal/slime/oil/ex_act(severity)
log_and_message_admins("[src] exploded due to a chain reaction with another explosion.")
explode()
/mob/living/simple_animal/slime/oil/fire_act(datum/gas_mixture/air, temperature, volume)
log_and_message_admins("[src] exploded due to exposure to fire.")
explode()
/mob/living/simple_animal/slime/oil/bullet_act(var/obj/item/projectile/P, var/def_zone)
if(P.damage_type && P.damage_type == BURN && P.damage) // Most bullets won't trigger the explosion, as a mercy towards Security.
log_and_message_admins("[src] exploded due to bring hit by a burning projectile[P.firer ? " by [key_name(P.firer)]" : ""].")
explode()
else
..()
/mob/living/simple_animal/slime/oil/attackby(var/obj/item/weapon/W, var/mob/user)
if(istype(W) && W.force && W.damtype == BURN)
log_and_message_admins("[src] exploded due to being hit with a burning weapon ([W]) by [key_name(user)].")
explode()
else
..()
/mob/living/simple_animal/slime/sapphire
desc = "This slime seems a bit brighter than the rest, both figuratively and literally."
color = "#2398FF"
slime_color = "sapphire"
shiny = TRUE
glows = TRUE
coretype = /obj/item/slime_extract/sapphire
optimal_combat = TRUE // Lift combat AI restrictions to look smarter.
run_at_them = FALSE // Use fancy A* pathing.
astar_adjacent_proc = /turf/proc/TurfsWithAccess // Normal slimes don't care about cardinals (because BYOND) so smart slimes shouldn't as well.
move_to_delay = 3 // A* chasing is slightly slower in terms of movement speed than regular pathing so reducing this hopefully makes up for that.
description_info = "This slime uses more robust tactics when fighting and won't hold back, so it is dangerous to be alone \
with one if hostile, and especially dangerous if they outnumber you."
slime_mutation = list(
/mob/living/simple_animal/slime/sapphire,
/mob/living/simple_animal/slime/sapphire,
/mob/living/simple_animal/slime/gold,
/mob/living/simple_animal/slime/gold
)
/mob/living/simple_animal/slime/emerald
desc = "This slime is faster than usual, even more so than the red slimes."
color = "#22FF22"
shiny = TRUE
glows = TRUE
slime_color = "emerald"
coretype = /obj/item/slime_extract/emerald
description_info = "This slime will make everything around it, and itself, faster for a few seconds, if close by."
move_to_delay = 2
slime_mutation = list(
/mob/living/simple_animal/slime/green,
/mob/living/simple_animal/slime/green,
/mob/living/simple_animal/slime/emerald,
/mob/living/simple_animal/slime/emerald
)
/mob/living/simple_animal/slime/emerald/Life()
if(stat != DEAD)
zoom_aura()
..()
/mob/living/simple_animal/slime/emerald/proc/zoom_aura()
for(var/mob/living/L in view(src, 2))
if(L.stat == DEAD || L == target_mob)
continue
L.add_modifier(/datum/modifier/technomancer/haste, 5 SECONDS, src)
/mob/living/simple_animal/slime/light_pink
desc = "This slime seems a lot more peaceful than the others."
color = "#FF8888"
slime_color = "light pink"
coretype = /obj/item/slime_extract/light_pink
description_info = "This slime is effectively always disciplined initially."
obedience = 5
discipline = 5
slime_mutation = list(
/mob/living/simple_animal/slime/pink,
/mob/living/simple_animal/slime/pink,
/mob/living/simple_animal/slime/light_pink,
/mob/living/simple_animal/slime/light_pink
)
// Special
/mob/living/simple_animal/slime/rainbow
desc = "This slime changes colors constantly."
color = null // Only slime subtype that uses a different icon_state.
slime_color = "rainbow"
coretype = /obj/item/slime_extract/rainbow
icon_state_override = "rainbow"
description_info = "This slime is considered to be the same color as all other slime colors at the same time for the purposes of \
other slimes being friendly to them, and therefore will never be harmed by another slime. \
Attacking this slime will provoke the wrath of all slimes within range."
slime_mutation = list(
/mob/living/simple_animal/slime/rainbow,
/mob/living/simple_animal/slime/rainbow,
/mob/living/simple_animal/slime/rainbow,
/mob/living/simple_animal/slime/rainbow
)
/mob/living/simple_animal/slime/rainbow/New()
unify()
..()
// The RD's pet slime.
/mob/living/simple_animal/slime/rainbow/kendrick
name = "Kendrick"
desc = "The Research Director's pet slime. It shifts colors constantly."
/mob/living/simple_animal/slime/rainbow/kendrick/New()
pacify()
..()
+8 -1
View File
@@ -111,7 +111,8 @@
//Speech bubbles.
if(comm)
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',comm,"h[speech_bubble_test]")
var/speech_type = speech_bubble_appearance()
var/image/speech_bubble = image('icons/mob/talk.dmi',comm,"[speech_type][speech_bubble_test]")
spawn(30)
qdel(speech_bubble)
@@ -121,6 +122,12 @@
..(message, speaking, verb, alt_name, whispering) //mob/living/say() can do the actual talking.
// Proc: speech_bubble_appearance()
// Parameters: 0
// Description: Gets the correct icon_state information for chat bubbles to work.
/mob/living/voice/speech_bubble_appearance()
return "comm"
/mob/living/voice/say_understands(var/other,var/datum/language/speaking = null)
//These only pertain to common. Languages are handled by mob/say_understands()
if (!speaking)
+28 -1
View File
@@ -542,13 +542,40 @@ proc/is_blind(A)
return threatcount
/mob/living/simple_animal/hostile/assess_perp(var/obj/access_obj, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
/mob/living/simple_animal/assess_perp(var/obj/access_obj, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
var/threatcount = ..()
if(. == SAFE_PERP)
return SAFE_PERP
if(!istype(src, /mob/living/simple_animal/retaliate/goat))
if(hostile)
if(faction != "neutral") // Otherwise Runtime gets killed.
threatcount += 4
return threatcount
// Beepsky will (try to) only beat 'bad' slimes.
/mob/living/simple_animal/slime/assess_perp(var/obj/access_obj, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
var/threatcount = 0
if(stat == DEAD)
return SAFE_PERP
if(is_justified_to_discipline())
threatcount += 4
/*
if(discipline && !rabid)
if(!target_mob || istype(target_mob, /mob/living/carbon/human/monkey))
return SAFE_PERP
if(target_mob)
threatcount += 4
if(victim)
threatcount += 4
*/
if(rabid)
threatcount = 10
return threatcount
#undef SAFE_PERP
+1 -1
View File
@@ -92,7 +92,7 @@
/mob/living/proc/add_modifier(var/modifier_type, var/expire_at = null, var/mob/living/origin = null)
// First, check if the mob already has this modifier.
for(var/datum/modifier/M in modifiers)
if(istype(modifier_type, M))
if(ispath(modifier_type, M))
switch(M.stacks)
if(MODIFIER_STACK_FORBID)
return // Stop here.
+3
View File
@@ -35,6 +35,9 @@
usr << "<span class='danger'>Speech is currently admin-disabled.</span>"
return
if(!client)
return // Clientless mobs shouldn't be trying to talk in deadchat.
if(!src.client.holder)
if(!config.dsay_allowed)
src << "<span class='danger'>Deadchat is globally muted.</span>"
-33
View File
@@ -185,39 +185,6 @@
qdel(src)
return
/mob/living/carbon/human/proc/slimeize(adult as num, reproduce as num)
if (transforming)
return
for(var/obj/item/W in src)
drop_from_inventory(W)
regenerate_icons()
transforming = 1
canmove = 0
icon = null
invisibility = 101
for(var/t in organs)
qdel(t)
var/mob/living/carbon/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)
M.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.key = key
new_slime << "<B>You are now a slime. Skreee!</B>"
qdel(src)
return
/mob/living/carbon/human/proc/corgize()
if (transforming)
+1 -1
View File
@@ -12,7 +12,7 @@ mob/var/obj/effect/decal/typing_indicator
if(!typing_indicator)
typing_indicator = new
typing_indicator.icon = 'icons/mob/talk.dmi'
typing_indicator.icon_state = "typing"
typing_indicator.icon_state = "[speech_bubble_appearance()]_typing"
if(client && !stat)
typing_indicator.invisibility = invisibility
+2
View File
@@ -46,6 +46,7 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\
var/parts = BP_ALL //Defines what parts said brand can replace on a body.
var/health_hud_intensity = 1 // Intensity modifier for the health GUI indicator.
var/suggested_species = "Human" //If it should make the torso a species
var/speech_bubble_appearance = "synthetic" // What icon_state to use for speech bubbles when talking. Check talk.dmi for all the icons.
/datum/robolimb/unbranded_monitor
company = "Unbranded Monitor"
@@ -166,6 +167,7 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\
unavailable_to_build = 1
lifelike = 1
blood_color = "#CCCCCC"
speech_bubble_appearance = "normal"
/datum/robolimb/wardtakahashi
company = "Ward-Takahashi"
+1 -1
View File
@@ -19,7 +19,7 @@
/obj/item/weapon/paper_bin/MouseDrop(mob/user as mob)
if((user == usr && (!( usr.restrained() ) && (!( usr.stat ) && (usr.contents.Find(src) || in_range(src, usr))))))
if(!istype(usr, /mob/living/carbon/slime) && !istype(usr, /mob/living/simple_animal))
if(!istype(usr, /mob/living/simple_animal))
if( !usr.get_active_hand() ) //if active hand is empty
var/mob/living/carbon/human/H = user
var/obj/item/organ/external/temp = H.organs_by_name["r_hand"]
+13
View File
@@ -6,6 +6,19 @@
..()
charge = maxcharge
update_icon()
if(self_recharge)
processing_objects |= src
/obj/item/weapon/cell/Destroy()
if(self_recharge)
processing_objects -= src
return ..()
/obj/item/weapon/cell/process()
if(self_recharge)
give(charge_amount / CELLRATE)
else
return PROCESS_KILL
/obj/item/weapon/cell/drain_power(var/drain_check, var/surge, var/power = 0)
+14 -1
View File
@@ -174,4 +174,17 @@
power_supply = new /obj/item/weapon/cell/device/weapon(src)
self_recharge = 1
processing_objects.Add(src)
update_icon()
update_icon()
/obj/item/weapon/gun/energy/get_description_interaction()
var/list/results = list()
if(!battery_lock && !self_recharge)
if(power_supply)
results += "[desc_panel_image("offhand")]to remove the weapon cell."
else
results += "[desc_panel_image("weapon cell")]to add a new weapon cell."
results += ..()
return results
@@ -2,78 +2,14 @@
name = "temperature gun"
icon_state = "freezegun"
fire_sound = 'sound/weapons/pulse3.ogg'
desc = "A gun that changes temperatures. It has a small label on the side, 'More extreme temperatures will cost more charge!'"
var/temperature = T20C
var/current_temperature = T20C
charge_cost = 24
desc = "A gun that can add or remove heat from entities it hits. In other words, it can fire 'cold', and 'hot' beams."
charge_cost = 240
origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 4, TECH_POWER = 3, TECH_MAGNET = 2)
slot_flags = SLOT_BELT|SLOT_BACK
projectile_type = /obj/item/projectile/temp
cell_type = /obj/item/weapon/cell/high
/obj/item/weapon/gun/energy/temperature/New()
..()
processing_objects.Add(src)
/obj/item/weapon/gun/energy/temperature/Destroy()
processing_objects.Remove(src)
..()
/obj/item/weapon/gun/energy/temperature/attack_self(mob/living/user as mob)
user.set_machine(src)
var/temp_text = ""
if(temperature > (T0C - 50))
temp_text = "<FONT color=black>[temperature] ([round(temperature-T0C)]&deg;C) ([round(temperature*1.8-459.67)]&deg;F)</FONT>"
else
temp_text = "<FONT color=blue>[temperature] ([round(temperature-T0C)]&deg;C) ([round(temperature*1.8-459.67)]&deg;F)</FONT>"
var/dat = {"<B>Freeze Gun Configuration: </B><BR>
Current output temperature: [temp_text]<BR>
Target output temperature: <A href='?src=\ref[src];temp=-100'>-</A> <A href='?src=\ref[src];temp=-10'>-</A> <A href='?src=\ref[src];temp=-1'>-</A> [current_temperature] <A href='?src=\ref[src];temp=1'>+</A> <A href='?src=\ref[src];temp=10'>+</A> <A href='?src=\ref[src];temp=100'>+</A><BR>
"}
user << browse(dat, "window=freezegun;size=450x300;can_resize=1;can_close=1;can_minimize=1")
onclose(user, "window=freezegun", src)
/obj/item/weapon/gun/energy/temperature/Topic(href, href_list)
if (..())
return 1
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["temp"])
var/amount = text2num(href_list["temp"])
if(amount > 0)
src.current_temperature = min(500, src.current_temperature+amount)
else
src.current_temperature = max(0, src.current_temperature+amount)
if (istype(src.loc, /mob))
attack_self(src.loc)
src.add_fingerprint(usr)
return
/obj/item/weapon/gun/energy/temperature/process()
switch(temperature)
if(0 to 100) charge_cost = 1000
if(100 to 250) charge_cost = 500
if(251 to 300) charge_cost = 100
if(301 to 400) charge_cost = 500
if(401 to 500) charge_cost = 1000
if(current_temperature != temperature)
var/difference = abs(current_temperature - temperature)
if(difference >= 10)
if(current_temperature < temperature)
temperature -= 10
else
temperature += 10
else
temperature = current_temperature
firemodes = list(
list(mode_name="endothermic beam", projectile_type = /obj/item/projectile/temp, charge_cost = 240),
list(mode_name="exothermic beam", projectile_type = /obj/item/projectile/temp/hot, charge_cost = 240),
)
+1 -1
View File
@@ -76,7 +76,7 @@
/obj/item/projectile/proc/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null)
if(blocked >= 100) return 0//Full block
if(!isliving(target)) return 0
if(isanimal(target)) return 0
// if(isanimal(target)) return 0
var/mob/living/L = target
L.apply_effects(stun, weaken, paralyze, irradiate, stutter, eyeblur, drowsy, agony, blocked) // add in AGONY!
return 1
@@ -52,7 +52,7 @@
Robot.mmi = new /obj/item/device/mmi(new_mob)
Robot.mmi.transfer_identity(M) //Does not transfer key/client.
if("slime")
new_mob = new /mob/living/carbon/slime(M.loc)
new_mob = new /mob/living/simple_animal/slime(M.loc)
new_mob.universal_speak = 1
else
var/mob/living/carbon/human/H
+30 -7
View File
@@ -35,19 +35,42 @@
icon_state = "ice_2"
damage = 0
damage_type = BURN
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
nodamage = 1
check_armour = "energy"
var/temperature = 300
check_armour = "energy" // It actually checks heat/cold protection.
var/target_temperature = 50
light_range = 2
light_power = 0.5
light_color = "#55AAFF"
/obj/item/projectile/temp/on_hit(atom/target, blocked = FALSE)
..()
if(isliving(target))
var/mob/living/L = target
on_hit(var/atom/target, var/blocked = 0)//These two could likely check temp protection on the mob
if(istype(target, /mob/living))
var/mob/M = target
M.bodytemperature = temperature
return 1
var/protection = null
var/potential_temperature_delta = null
var/new_temperature = L.bodytemperature
if(target_temperature >= T20C) // Make it cold.
protection = L.get_cold_protection(target_temperature)
potential_temperature_delta = 75
new_temperature = max(new_temperature - potential_temperature_delta, target_temperature)
else // Make it hot.
protection = L.get_heat_protection(target_temperature)
potential_temperature_delta = 200 // Because spacemen temperature needs stupid numbers to actually hurt people.
new_temperature = min(new_temperature + potential_temperature_delta, target_temperature)
var/temp_factor = abs(protection - 1)
new_temperature = round(new_temperature * temp_factor)
L.bodytemperature = new_temperature
return 1
/obj/item/projectile/temp/hot
name = "heat beam"
target_temperature = 1000
/obj/item/projectile/meteor
name = "meteor"
@@ -381,10 +381,6 @@
if(type == CHEM_TOUCH)
var/datum/reagents/R = C.touching
return trans_to_holder(R, amount, multiplier, copy)
else if(isxeno(target))
var/mob/living/simple_animal/xeno/X = target
var/datum/reagents/R = X.reagents
return trans_to_holder(R, amount, multiplier, copy)
else
var/datum/reagents/R = new /datum/reagents(amount)
. = trans_to_holder(R, amount, multiplier, copy)
+2 -3
View File
@@ -2,7 +2,7 @@
#define LIQUID 2
#define GAS 3
#define REAGENTS_PER_SHEET 20
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -294,6 +294,7 @@
/obj/item/stack/material/phoron = "phoron",
/obj/item/stack/material/gold = "gold",
/obj/item/stack/material/silver = "silver",
/obj/item/stack/material/platinum = "platinum",
/obj/item/stack/material/mhydrogen = "hydrogen"
)
@@ -511,5 +512,3 @@
qdel(O)
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
break
#undef REAGENTS_PER_SHEET
@@ -133,23 +133,19 @@
/datum/reagent/water/touch_mob(var/mob/living/L, var/amount)
if(istype(L))
// First, kill slimes.
if(istype(L, /mob/living/simple_animal/slime))
var/mob/living/simple_animal/slime/S = L
S.adjustToxLoss(15 * amount)
S.visible_message("<span class='warning'>[S]'s flesh sizzles where the water touches it!</span>", "<span class='danger'>Your flesh burns in the water!</span>")
// Then extinguish people on fire.
var/needed = L.fire_stacks * 5
if(amount > needed)
L.ExtinguishMob()
L.adjust_fire_stacks(-(amount / 5))
remove_self(needed)
/datum/reagent/water/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
if(istype(M, /mob/living/carbon/slime))
var/mob/living/carbon/slime/S = M
S.adjustToxLoss(15 * removed) // Babies have 150 health, adults have 200; So, 10 units and 13.5
if(!S.client)
if(S.Target) // Like cats
S.Target = null
++S.Discipline
if(dose == removed)
S.visible_message("<span class='warning'>[S]'s flesh sizzles where the water touches it!</span>", "<span class='danger'>Your flesh burns in the water!</span>")
/datum/reagent/fuel
name = "Welding fuel"
id = "fuel"
@@ -287,7 +287,7 @@
M.bodytemperature = max(M.bodytemperature - 10 * TEMPERATURE_DAMAGE_COEFFICIENT, 0)
if(prob(1))
M.emote("shiver")
if(istype(M, /mob/living/carbon/slime))
if(istype(M, /mob/living/simple_animal/slime))
M.bodytemperature = max(M.bodytemperature - rand(10,20), 0)
holder.remove_reagent("capsaicin", 5)
@@ -319,7 +319,7 @@
M.apply_effect(2, AGONY, 0)
if(prob(5))
M.visible_message("<span class='warning'>[M] [pick("dry heaves!","coughs!","splutters!")]</span>", "<span class='danger'>You feel like your insides are burning!</span>")
if(istype(M, /mob/living/carbon/slime))
if(istype(M, /mob/living/simple_animal/slime))
M.bodytemperature += rand(10, 25)
holder.remove_reagent("frostoil", 5)
@@ -404,7 +404,7 @@
M.apply_effect(4, AGONY, 0)
if(prob(5))
M.visible_message("<span class='warning'>[M] [pick("dry heaves!","coughs!","splutters!")]</span>", "<span class='danger'>You feel like your insides are burning!</span>")
if(istype(M, /mob/living/carbon/slime))
if(istype(M, /mob/living/simple_animal/slime))
M.bodytemperature += rand(15, 30)
holder.remove_reagent("frostoil", 5)
@@ -169,6 +169,14 @@
reagent_state = SOLID
color = "#B8B8C0"
/datum/reagent/platinum
name = "Platinum"
id = "platinum"
description = "Platinum is a dense, malleable, ductile, highly unreactive, precious, gray-white transition metal. It is very resistant to corrosion."
taste_description = "metal"
reagent_state = SOLID
color = "#777777"
/datum/reagent/uranium/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
affect_ingest(M, alien, removed)
@@ -298,7 +306,7 @@
S.dirt = 0
T.clean_blood()
for(var/mob/living/carbon/slime/M in T)
for(var/mob/living/simple_animal/slime/M in T)
M.adjustToxLoss(rand(5, 10))
/datum/reagent/space_cleaner/affect_touch(var/mob/living/carbon/M, var/alien, var/removed)
+66 -31
View File
@@ -604,16 +604,75 @@
/* Solidification */
/datum/chemical_reaction/phoronsolidification
/datum/chemical_reaction/solidification
name = "Solid Iron"
id = "solidiron"
result = null
required_reagents = list("frostoil" = 5, "iron" = REAGENTS_PER_SHEET)
result_amount = 1
var/sheet_to_give = /obj/item/stack/material/iron
/datum/chemical_reaction/solidification/on_reaction(var/datum/reagents/holder, var/created_volume)
new sheet_to_give(get_turf(holder.my_atom), created_volume)
return
/datum/chemical_reaction/solidification/phoron
name = "Solid Phoron"
id = "solidphoron"
result = null
required_reagents = list("iron" = 5, "frostoil" = 5, "phoron" = 20)
result_amount = 1
required_reagents = list("frostoil" = 5, "phoron" = REAGENTS_PER_SHEET)
sheet_to_give = /obj/item/stack/material/phoron
/datum/chemical_reaction/solidification/silver
name = "Solid Silver"
id = "solidsilver"
required_reagents = list("frostoil" = 5, "silver" = REAGENTS_PER_SHEET)
sheet_to_give = /obj/item/stack/material/silver
/datum/chemical_reaction/solidification/gold
name = "Solid Gold"
id = "solidgold"
required_reagents = list("frostoil" = 5, "gold" = REAGENTS_PER_SHEET)
sheet_to_give = /obj/item/stack/material/gold
/datum/chemical_reaction/solidification/platinum
name = "Solid Platinum"
id = "solidplatinum"
required_reagents = list("frostoil" = 5, "platinum" = REAGENTS_PER_SHEET)
sheet_to_give = /obj/item/stack/material/platinum
/datum/chemical_reaction/solidification/uranium
name = "Solid Uranium"
id = "soliduranium"
required_reagents = list("frostoil" = 5, "uranium" = REAGENTS_PER_SHEET)
sheet_to_give = /obj/item/stack/material/uranium
/datum/chemical_reaction/solidification/hydrogen
name = "Solid Hydrogen"
id = "solidhydrogen"
required_reagents = list("frostoil" = 100, "hydrogen" = REAGENTS_PER_SHEET)
sheet_to_give = /obj/item/stack/material/mhydrogen
// These are from Xenobio.
/datum/chemical_reaction/solidification/steel
name = "Solid Steel"
id = "solidsteel"
required_reagents = list("frostoil" = 5, "steel" = REAGENTS_PER_SHEET)
sheet_to_give = /obj/item/stack/material/steel
/datum/chemical_reaction/solidification/plasteel
name = "Solid Plasteel"
id = "solidplasteel"
required_reagents = list("frostoil" = 10, "plasteel" = REAGENTS_PER_SHEET)
sheet_to_give = /obj/item/stack/material/plasteel
/datum/chemical_reaction/phoronsolidification/on_reaction(var/datum/reagents/holder, var/created_volume)
new /obj/item/stack/material/phoron(get_turf(holder.my_atom), created_volume)
return
/datum/chemical_reaction/plastication
name = "Plastic"
@@ -1038,30 +1097,6 @@
/datum/chemical_reaction/aluminum_paint/send_data()
return "#F0F8FF"
/* Slime cores */
/datum/chemical_reaction/slime
var/required = null
//Slimed monkeys
/datum/chemical_reaction/slime/can_happen(var/datum/reagents/holder)
if(holder.my_atom && istype(holder.my_atom, required))
return ..()
return 0
/datum/chemical_reaction/slime/golem
name = "Prometheans"
id = "m_promethean"
result = null
required_reagents = list("mutationtoxin" = 1)
result_amount = 1
required = /obj/item/weapon/reagent_containers/food/snacks/monkeycube
/datum/chemical_reaction/slime/golem/on_reaction(var/datum/reagents/holder)
var/location = get_turf(holder.my_atom)
new /obj/item/slime_cube(location)
qdel(holder.my_atom)
/* Food */
/datum/chemical_reaction/food/tofu
@@ -90,8 +90,6 @@
user << "<span class='warning'>\The [blocked] is in the way!</span>"
return
if(!istype(M, /mob/living/carbon/slime)) //If you're feeding it to someone else.
if (fullness <= (550 * (1 + M.overeatduration / 1000)))
user.visible_message("<span class='danger'>[user] attempts to feed [M] [src].</span>")
else
@@ -42,8 +42,7 @@
/obj/machinery/smartfridge/,
/obj/machinery/biogenerator,
/obj/structure/frame,
/obj/machinery/radiocarbon_spectrometer,
/obj/machinery/xenobio2/manualinjector
/obj/machinery/radiocarbon_spectrometer
)
/obj/item/weapon/reagent_containers/glass/New()
@@ -79,9 +79,6 @@
user << "<span class='notice'>There is already a blood sample in this syringe.</span>"
return
if(istype(target, /mob/living/carbon))
if(istype(target, /mob/living/carbon/slime))
user << "<span class='warning'>You are unable to locate any blood.</span>"
return
var/amount = reagents.get_free_space()
var/mob/living/carbon/T = target
if(!T.dna)
+2
View File
@@ -471,6 +471,8 @@
qdel(H)
/obj/machinery/disposal/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover, /obj/item/projectile))
return 1
if (istype(mover,/obj/item) && mover.throwing)
var/obj/item/I = mover
if(istype(I, /obj/item/projectile))
+14
View File
@@ -592,6 +592,20 @@ other types of metals and chemistry for reagents).
build_path = /obj/item/weapon/gun/energy/floragun
sort_string = "TBAAA"
/datum/design/item/weapon/slimebation
id = "slimebation"
req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3, TECH_POWER = 3, TECH_COMBAT = 3)
materials = list(DEFAULT_WALL_MATERIAL = 5000)
build_path = /obj/item/weapon/melee/baton/slime
sort_string = "TBAAB"
/datum/design/item/weapon/slimetaser
id = "slimetaser"
req_tech = list(TECH_MATERIAL = 3, TECH_BIO = 4, TECH_POWER = 4, TECH_COMBAT = 4)
materials = list(DEFAULT_WALL_MATERIAL = 5000)
build_path = /obj/item/weapon/gun/energy/taser/xeno
sort_string = "TBAAC"
/datum/design/item/stock_part/subspace_ansible
id = "s-ansible"
req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
+16 -16
View File
@@ -3,10 +3,10 @@
//////////////////////////////////////////////////////////////////
/datum/surgery_step/slime
is_valid_target(mob/living/carbon/slime/target)
return istype(target, /mob/living/carbon/slime/)
is_valid_target(mob/living/simple_animal/slime/target)
return istype(target, /mob/living/simple_animal/slime/)
can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
can_use(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
return target.stat == 2
/datum/surgery_step/slime/cut_flesh
@@ -19,19 +19,19 @@
min_duration = 30
max_duration = 50
can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
can_use(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
return ..() && istype(target) && target.core_removal_stage == 0
begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
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].")
end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
end_step(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
user.visible_message("<font color='blue'>[user] cuts through [target]'s flesh with \the [tool].</font>", \
"<font color='blue'>You cut through [target]'s flesh with \the [tool], revealing its silky innards.</font>")
target.core_removal_stage = 1
fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
fail_step(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
user.visible_message("<font color='red'>[user]'s hand slips, tearing [target]'s flesh with \the [tool]!</font>", \
"<font color='red'>Your hand slips, tearing [target]'s flesh with \the [tool]!</font>")
@@ -45,19 +45,19 @@
min_duration = 30
max_duration = 50
can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
can_use(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
return ..() && istype(target) && target.core_removal_stage == 1
begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
begin_step(mob/user, mob/living/simple_animal/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].")
end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
end_step(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
user.visible_message("<font color='blue'>[user] cuts [target]'s innards apart with \the [tool], exposing the cores.</font>", \
"<font color='blue'>You cut [target]'s innards apart with \the [tool], exposing the cores.</font>")
target.core_removal_stage = 2
fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
fail_step(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
user.visible_message("<font color='red'>[user]'s hand slips, tearing [target]'s innards with \the [tool]!</font>", \
"<font color='red'>Your hand slips, tearing [target]'s innards with \the [tool]!</font>")
@@ -70,14 +70,14 @@
min_duration = 50
max_duration = 70
can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
can_use(mob/living/user, mob/living/simple_animal/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.
begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
begin_step(mob/user, mob/living/simple_animal/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].")
end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
end_step(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
target.cores--
user.visible_message("<font color='blue'>[user] cuts out one of [target]'s cores with \the [tool].</font>",, \
"<font color='blue'>You cut out one of [target]'s cores with \the [tool]. [target.cores] cores left.</font>")
@@ -85,9 +85,9 @@
if(target.cores >= 0)
new target.coretype(target.loc)
if(target.cores <= 0)
target.icon_state = "[target.colour] baby slime dead-nocore"
target.icon_state = "slime extracted"
fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool)
fail_step(mob/living/user, mob/living/simple_animal/slime/target, target_zone, obj/item/tool)
user.visible_message("<font color='red'>[user]'s hand slips, causing \him to miss the core!</font>", \
"<font color='red'>Your hand slips, causing you to miss the core!</font>")
+2 -2
View File
@@ -35,8 +35,8 @@ var/list/ventcrawl_machinery = list(
remove_ventcrawl()
add_ventcrawl(loc)
/mob/living/carbon/slime/can_ventcrawl()
if(Victim)
/mob/living/simple_animal/slime/can_ventcrawl()
if(victim)
to_chat(src, "<span class='warning'>You cannot ventcrawl while feeding.</span>")
return FALSE
. = ..()
+973
View File
@@ -0,0 +1,973 @@
// Base
/obj/item/slime_extract
name = "slime extract"
desc = "Goo extracted from a slime, which can do different things depending on its color and what it is injected with."
icon = 'icons/mob/slimes.dmi'
icon_state = "grey slime extract"
force = 1
w_class = ITEMSIZE_TINY
throwforce = 0
throw_speed = 3
throw_range = 6
origin_tech = list(TECH_BIO = 4)
var/uses = 1 // uses before it goes inert
var/enhanced = FALSE
flags = OPENCONTAINER
/obj/item/slime_extract/New()
..()
create_reagents(60)
/obj/item/slime_extract/attackby(obj/item/O, mob/user)
if(istype(O, /obj/item/slimepotion/enhancer))
if(enhanced)
to_chat(user, "<span class='warning'>You cannot enhance this extract further!</span>")
return ..()
to_chat(user, "<span class='notice'>You apply the enhancer to the slime extract. It may now be reused one more time.</span>")
playsound(src, 'sound/effects/bubbles.ogg', 50, 1)
uses += 2
enhanced = TRUE
name = initial(name) // To remove the 'inert' part of the name.
qdel(O)
..()
/obj/item/slime_extract/examine(mob/user)
..()
if(uses)
to_chat(user, "This extract has [uses] more use\s.")
else
to_chat(user, "This extract is inert.")
/datum/chemical_reaction/slime
var/required = null
/datum/chemical_reaction/slime/can_happen(var/datum/reagents/holder)
if(holder.my_atom && istype(holder.my_atom, required))
var/obj/item/slime_extract/T = holder.my_atom
if(T.uses > 0)
return ..()
return FALSE
/datum/chemical_reaction/slime/on_reaction(var/datum/reagents/holder)
var/obj/item/slime_extract/T = holder.my_atom
T.uses--
if(T.uses <= 0)
T.visible_message("\icon[T]<span class='notice'>\The [T] goes inert.</span>")
T.name = "inert [initial(T.name)]"
// ***************
// * Grey slimes *
// ***************
/obj/item/slime_extract/grey
name = "grey slime extract"
icon_state = "grey slime extract"
description_info = "This extract will create a new grey baby slime if injected with phoron, or some new monkey cubes if injected with blood."
/datum/chemical_reaction/slime/grey_new_slime
name = "Slime Spawn"
id = "m_spawn"
result = null
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/grey
/datum/chemical_reaction/slime/grey_new_slime/on_reaction(var/datum/reagents/holder)
holder.my_atom.visible_message("<span class='warning'>Infused with phoron, the core begins to quiver and grow, and soon a new baby slime emerges from it!</span>")
new /mob/living/simple_animal/slime(get_turf(holder.my_atom))
..()
/datum/chemical_reaction/slime/grey_monkey
name = "Slime Monkey"
id = "m_monkey"
result = null
required_reagents = list("blood" = 5)
result_amount = 1
required = /obj/item/slime_extract/grey
/datum/chemical_reaction/slime/grey_monkey/on_reaction(var/datum/reagents/holder)
for(var/i = 1 to 4)
new /obj/item/weapon/reagent_containers/food/snacks/monkeycube(get_turf(holder.my_atom))
..()
// ****************
// * Metal slimes *
// ****************
/obj/item/slime_extract/metal
name = "metal slime extract"
icon_state = "metal slime extract"
description_info = "This extract will create a metamorphic liquid which will transform into metallic liquid it comes into contact with, when injected with phoron. \
It can also create a metallic binding liquid which will force metallic liquids to mix to form alloys when solified, when injected with water."
// 'Duplicates' liquid metals, consuming itself in the process.
/datum/reagent/toxin/metamorphic_metal
name = "Metamorphic Metal"
id = "metamorphic"
description = "A strange metallic liquid which can rearrange itself to take the form of other metals it touches."
taste_description = "metallic"
taste_mult = 1.1
reagent_state = LIQUID
color = "#666666"
strength = 20
/datum/chemical_reaction/slime/metal_metamorphic
name = "Slime Metal"
id = "m_metal"
required_reagents = list("phoron" = 5)
result = "metamorphic"
result_amount = REAGENTS_PER_SHEET // Makes enough to make one sheet of any metal.
required = /obj/item/slime_extract/metal
/datum/chemical_reaction/metamorphic
result_amount = REAGENTS_PER_SHEET * 2
/obj/item/weapon/reagent_containers/glass/bottle/metamorphic
name = "Metamorphic Metal Bottle"
desc = "A small bottle. Contains some really weird liquid metal."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
/obj/item/weapon/reagent_containers/glass/bottle/metamorphic/New()
..()
reagents.add_reagent("metamorphic", 60)
update_icon()
// This is kind of a waste since iron is in the chem dispenser but it would be inconsistent if this wasn't here.
/datum/chemical_reaction/metamorphic/iron
name = "Morph into Iron"
id = "morph_iron"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "iron" = REAGENTS_PER_SHEET)
result = "iron"
/datum/chemical_reaction/metamorphic/silver
name = "Morph into Silver"
id = "morph_silver"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "silver" = REAGENTS_PER_SHEET)
result = "silver"
/datum/chemical_reaction/metamorphic/gold
name = "Morph into Gold"
id = "morph_gold"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "gold" = REAGENTS_PER_SHEET)
result = "gold"
/datum/chemical_reaction/metamorphic/platinum
name = "Morph into Platinum"
id = "morph_platinum"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "platinum" = REAGENTS_PER_SHEET)
result = "platinum"
/datum/chemical_reaction/metamorphic/uranium
name = "Morph into Uranium"
id = "morph_uranium"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "uranium" = REAGENTS_PER_SHEET)
result = "uranium"
/datum/chemical_reaction/metamorphic/phoron
name = "Morph into Phoron"
id = "morph_phoron"
required_reagents = list("metamorphic" = REAGENTS_PER_SHEET, "phoron" = REAGENTS_PER_SHEET)
result = "phoron"
// Creates 'alloys' which can be finalized with frost oil.
/datum/chemical_reaction/slime/metal_binding
name = "Slime Binding"
id = "m_binding"
required_reagents = list("water" = 5)
result = "binding"
result_amount = REAGENTS_PER_SHEET // Makes enough to make one sheet of any metal.
required = /obj/item/slime_extract/metal
/datum/reagent/toxin/binding_metal
name = "Binding Metal"
id = "binding"
description = "A strange metallic liquid which can bind other metals together that would otherwise require intense heat to alloy."
taste_description = "metallic"
taste_mult = 1.1
reagent_state = LIQUID
color = "#666666"
strength = 20
/obj/item/weapon/reagent_containers/glass/bottle/binding
name = "Binding Metal Bottle"
desc = "A small bottle. Contains some really weird liquid metal."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
/obj/item/weapon/reagent_containers/glass/bottle/binding/New()
..()
reagents.add_reagent("binding", 60)
update_icon()
/datum/chemical_reaction/binding
name = "Bind into Steel"
id = "bind_steel"
result = "steel"
required_reagents = list("binding" = REAGENTS_PER_SHEET, "iron" = REAGENTS_PER_SHEET, "carbon" = REAGENTS_PER_SHEET)
result_amount = REAGENTS_PER_SHEET
/datum/reagent/steel
name = "Liquid Steel"
id = "steel"
description = "An 'alloy' of iron and carbon, forced to bind together by another strange metallic liquid."
taste_description = "metallic"
reagent_state = LIQUID
color = "#888888"
/datum/chemical_reaction/binding/plasteel // Two parts 'steel', one part platnium matches the smelter alloy recipe.
name = "Bind into Plasteel"
id = "bind_plasteel"
required_reagents = list("binding" = REAGENTS_PER_SHEET, "steel" = REAGENTS_PER_SHEET * 2, "platinum" = REAGENTS_PER_SHEET)
result = "plasteel"
/datum/reagent/plasteel
name = "Liquid Plasteel"
id = "plasteel"
description = "An 'alloy' of iron, carbon, and platinum, forced to bind together by another strange metallic liquid."
taste_description = "metallic"
reagent_state = LIQUID
color = "#AAAAAA"
// ***************
// * Blue slimes *
// ***************
/obj/item/slime_extract/blue
name = "blue slime extract"
icon_state = "blue slime extract"
description_info = "This extract will create frost oil when injected with phoron, which can be used to solidify liquid metals. \
The extract can also create a slime stability agent when injected with blood, which reduces the odds of newly created slimes mutating into \
a different color when a slime reproduces."
/datum/chemical_reaction/slime/blue_frostoil
name = "Slime Frost Oil"
id = "m_frostoil"
result = "frostoil"
required_reagents = list("phoron" = 5)
result_amount = 20
required = /obj/item/slime_extract/blue
/datum/chemical_reaction/slime/blue_stability
name = "Slime Stability"
id = "m_stability"
required_reagents = list("blood" = 5)
result_amount = 1
required = /obj/item/slime_extract/blue
/datum/chemical_reaction/slime/blue_stability/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/stabilizer(get_turf(holder.my_atom))
..()
// *****************
// * Purple slimes *
// *****************
/obj/item/slime_extract/purple
name = "purple slime extract"
icon_state = "purple slime extract"
description_info = "This extract can create a slime steroid agent when injected with phoron, which increases the amount of slime extracts the processor \
can extract from a slime specimen."
/datum/chemical_reaction/slime/purple_steroid
name = "Slime Steroid"
id = "m_steroid"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/purple
/datum/chemical_reaction/slime/purple_steroid/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/steroid(get_turf(holder.my_atom))
..()
// *****************
// * Orange slimes *
// *****************
/obj/item/slime_extract/orange
name = "orange slime extract"
icon_state = "orange slime extract"
description_info = "This extract creates a fire when injected with phoron, after a five second delay."
/datum/chemical_reaction/slime/orange_fire
name = "Slime Fire"
id = "m_fire"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/orange
/datum/chemical_reaction/slime/orange_fire/on_reaction(var/datum/reagents/holder)
log_and_message_admins("Orange extract reaction (fire) has been activated in [get_area(holder.my_atom)]. Last fingerprints: [holder.my_atom.fingerprintslast]")
holder.my_atom.visible_message("<span class='danger'>\The [src] begins to vibrate violently!</span>")
playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 75, 1)
spawn(5 SECONDS)
if(holder && holder.my_atom)
var/turf/simulated/T = get_turf(holder.my_atom)
if(!istype(T))
return
for(var/turf/simulated/target_turf in view(2, T))
target_turf.assume_gas("volatile_fuel", 33, 1500+T0C)
target_turf.assume_gas("oxygen", 66, 1500+T0C)
spawn(0)
target_turf.hotspot_expose(1500+T0C, 400)
playsound(T, 'sound/effects/phasein.ogg', 75, 1)
..()
// *****************
// * Yellow slimes *
// *****************
/obj/item/slime_extract/yellow
name = "yellow slime extract"
icon_state = "yellow slime extract"
description_info = "This extract will create a special 10k capacity power cell that self recharges slowly over time, when injected with phoron. \
When injected with blood, it will create a glob of slime which glows brightly. If injected with water, it will emit a strong EMP, after a five second delay."
/datum/chemical_reaction/slime/yellow_emp
name = "Slime EMP"
id = "m_emp"
required_reagents = list("water" = 5)
result_amount = 1
required = /obj/item/slime_extract/yellow
/datum/chemical_reaction/slime/yellow_emp/on_reaction(var/datum/reagents/holder)
log_and_message_admins("Yellow extract reaction (emp) has been activated in [get_area(holder.my_atom)]. Last fingerprints: [holder.my_atom.fingerprintslast]")
holder.my_atom.visible_message("<span class='danger'>\The [src] begins to vibrate violently!</span>")
playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 75, 1)
spawn(5 SECONDS)
if(holder && holder.my_atom)
empulse(get_turf(holder.my_atom), 2, 4, 7, 10) // As strong as a normal EMP grenade.
playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 75, 1)
..()
/datum/chemical_reaction/slime/yellow_battery
name = "Slime Cell"
id = "m_cell"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/yellow
/datum/chemical_reaction/slime/yellow_battery/on_reaction(var/datum/reagents/holder)
new /obj/item/weapon/cell/slime(get_turf(holder.my_atom))
..()
/datum/chemical_reaction/slime/yellow_flashlight
name = "Slime Flashlight"
id = "m_flashlight"
required_reagents = list("blood" = 5)
result_amount = 1
required = /obj/item/slime_extract/yellow
/datum/chemical_reaction/slime/yellow_flashlight/on_reaction(var/datum/reagents/holder)
new /obj/item/device/flashlight/slime(get_turf(holder.my_atom))
..()
// ***************
// * Gold slimes *
// ***************
/obj/item/slime_extract/gold
name = "gold slime extract"
icon_state = "gold slime extract"
description_info = "This extract will create 5u liquid gold when injected with phoron."
/datum/chemical_reaction/slime/gold_gold
name = "Slime Gold"
id = "m_gold"
result = "gold"
required_reagents = list("phoron" = 5)
result_amount = 5
required = /obj/item/slime_extract/gold
// *****************
// * Silver slimes *
// *****************
/obj/item/slime_extract/silver
name = "silver slime extract"
icon_state = "silver slime extract"
description_info = "This extract will create 5u liquid silver when injected with phoron."
/datum/chemical_reaction/slime/silver_silver
name = "Slime Silver"
id = "m_silver"
result = "silver"
required_reagents = list("phoron" = 5)
result_amount = 5
required = /obj/item/slime_extract/silver
// **********************
// * Dark Purple slimes *
// **********************
/obj/item/slime_extract/dark_purple
name = "dark purple slime extract"
icon_state = "dark purple slime extract"
description_info = "This extract will create 40u liquid phoron when injected with water."
/datum/chemical_reaction/slime/dark_purple_phoron
name = "Slime Phoron"
id = "m_phoron_harvest"
result = "phoron"
required_reagents = list("water" = 5)
result_amount = REAGENTS_PER_SHEET * 2
required = /obj/item/slime_extract/dark_purple
// ********************
// * Dark Blue slimes *
// ********************
/obj/item/slime_extract/dark_blue
name = "dark blue slime extract"
icon_state = "dark blue slime extract"
description_info = "This extract will massively lower the temperature of the surrounding atmosphere when injected with phoron. \
Slimes will suffer massive harm from the cold snap and most colors will die instantly. Other entities are also chilled, however \
cold-resistant armor like winter coats can protect from this. Note that the user is not immune to the extract's effects."
/datum/chemical_reaction/slime/dark_blue_cold_snap
name = "Slime Cold Snap"
id = "m_cold_snap"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/dark_blue
// This iterates over a ZAS zone's contents, so that things seperated in other zones aren't subjected to the temperature drop.
/datum/chemical_reaction/slime/dark_blue_cold_snap/on_reaction(var/datum/reagents/holder)
var/turf/simulated/T = get_turf(holder.my_atom)
if(!T) // Nullspace lacks zones.
return
if(!istype(T))
return
var/zone/Z = T.zone
if(!Z) // Paranoid.
return
log_and_message_admins("Dark Blue extract reaction (cold snap) has been activated in [get_area(holder.my_atom)]. Last fingerprints: [holder.my_atom.fingerprintslast]")
var/list/nearby_things = view(T)
// Hurt mobs.
for(var/mob/living/L in nearby_things)
var/turf/simulated/their_turf = get_turf(L)
if(!istype(their_turf)) // Not simulated.
continue
if(!(their_turf in Z.contents)) // Not in the same zone.
continue
if(istype(L, /mob/living/simple_animal/slime))
var/mob/living/simple_animal/slime/S = L
if(S.cold_damage_per_tick <= 0) // Immune to cold.
to_chat(S, "<span class='warning'>A chill is felt around you, however it cannot harm you.</span>")
continue
if(S.client) // Don't instantly kill player slimes.
to_chat(S, "<span class='danger'>You feel your body crystalize as an intense chill overwhelms you!</span>")
S.adjustToxLoss(S.cold_damage_per_tick * 2)
else
S.adjustToxLoss(S.cold_damage_per_tick * 5) // Metal slimes can survive this 'slime nuke'.
continue
if(ishuman(L))
var/mob/living/carbon/human/H = L
var/protection = H.get_cold_protection()
if(protection < 1)
var/cold_factor = abs(protection - 1)
H.bodytemperature = between(50, (H.bodytemperature - ((H.bodytemperature - 50) * cold_factor) ), H.bodytemperature)
if(protection < 0.7)
to_chat(L, "<span class='danger'>A chilling wave of cold overwhelms you!</span>")
else
to_chat(L, "<span class='warning'>A chilling wave of cold passes by you, as your armor protects you from it.</span>")
continue
// Now make it very cold.
var/datum/gas_mixture/env = T.return_air()
if(env)
// This is most likely physically impossible but when has that stopped slimes before?
env.add_thermal_energy(-10 * 1000 * 1000) // For a moderately sized room this doesn't actually lower it that much.
playsound(T, 'sound/effects/phasein.ogg', 75, 1)
..()
// **************
// * Red slimes *
// **************
/obj/item/slime_extract/red
name = "red slime extract"
icon_state = "red slime extract"
description_info = "This extract will create a slime mutator agent when injected with phoron, which increases a slime's odds of mutating \
into a different color when reproducing by 12%. Injecting with blood causes all slimes that can see the user to enrage, becoming very violent and \
out of control."
/datum/chemical_reaction/slime/red_enrage
name = "Slime Enrage"
id = "m_enrage"
required_reagents = list("blood" = 5)
result_amount = 1
required = /obj/item/slime_extract/red
/datum/chemical_reaction/slime/red_enrage/on_reaction(var/datum/reagents/holder)
for(var/mob/living/simple_animal/slime/S in view(get_turf(holder.my_atom)))
if(S.stat || S.docile || S.rabid)
continue
if(S.client) // Player slimes always have free will.
to_chat(S, "<span class='warning'>An intense wave of rage almost overcomes you, but you remain in control of yourself.</span>")
continue
S.enrage()
log_and_message_admins("Red extract reaction (enrage) has been activated in [get_area(holder.my_atom)]. Last fingerprints: [holder.my_atom.fingerprintslast]")
playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 75, 1)
..()
/datum/chemical_reaction/slime/red_mutation
name = "Slime Mutation"
id = "m_mutation"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/red
/datum/chemical_reaction/slime/red_mutation/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/mutator(get_turf(holder.my_atom))
..()
// ***************
// * Green slime *
// ***************
/obj/item/slime_extract/green
name = "green slime extract"
icon_state = "green slime extract"
description_info = "This extract will create 5u of liquid uranium when injected with phoron."
/datum/chemical_reaction/slime/green_uranium
name = "Slime Uranium"
id = "m_uranium"
result = "uranium"
required_reagents = list("phoron" = 5)
result_amount = 5
required = /obj/item/slime_extract/green
// ***************
// * Pink slimes *
// ***************
/obj/item/slime_extract/pink
name = "pink slime extract"
icon_state = "pink slime extract"
description_info = "This extract will create 20u of blood clotting agent if injected with blood. It can also create 20u of bone binding agent if injected \
with phoron. When injected with water, it will create an organ-mending agent. The slime medications have a very low threshold for overdosage, however."
/datum/chemical_reaction/slime/pink_clotting
name = "Slime Clotting Med"
id = "m_clotting"
result = "slime_bleed_fixer"
required_reagents = list("blood" = 5)
result_amount = 30
required = /obj/item/slime_extract/pink
/datum/chemical_reaction/slime/pink_bone_fix
name = "Slime Bone Med"
id = "m_bone_fixer"
result = "slime_bone_fixer"
required_reagents = list("phoron" = 5)
result_amount = 30
required = /obj/item/slime_extract/pink
/datum/chemical_reaction/slime/pink_organ_fix
name = "Slime Organ Med"
id = "m_organ_fixer"
result = "slime_organ_fixer"
required_reagents = list("water" = 5)
result_amount = 30
required = /obj/item/slime_extract/pink
/datum/reagent/myelamine/slime
name = "Agent A"
id = "slime_bleed_fixer"
description = "A slimy liquid which appears to rapidly clot internal hemorrhages by increasing the effectiveness of platelets at low quantities. Toxic in high quantities."
taste_description = "slime"
overdose = 5
/datum/reagent/osteodaxon/slime
name = "Agent B"
id = "slime_bone_fixer"
description = "A slimy liquid which can be used to heal bone fractures at low quantities. Toxic in high quantities."
taste_description = "slime"
overdose = 5
/datum/reagent/peridaxon/slime
name = "Agent C"
id = "slime_organ_fixer"
description = "A slimy liquid which is used to encourage recovery of internal organs and nervous systems in low quantities. Toxic in high quantities."
taste_description = "slime"
overdose = 5
// **************
// * Oil slimes *
// **************
/obj/item/slime_extract/oil
name = "oil slime extract"
icon_state = "oil slime extract"
description_info = "This extract cause a moderately sized delayed explosion if injected with phoron. The delay is five seconds. Extract enhancers will \
increase the power of the explosion instead of allowing for multiple explosions."
/datum/chemical_reaction/slime/oil_griff
name = "Slime Explosion"
id = "m_boom"
required_reagents = list("blood" = 5)
result_amount = 1
required = /obj/item/slime_extract/oil
/datum/chemical_reaction/slime/oil_griff/on_reaction(var/datum/reagents/holder)
..()
var/obj/item/slime_extract/E = holder.my_atom
var/power = 1
if(E.enhanced)
power++
E.uses = 0
playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 75, 1)
holder.my_atom.visible_message("<span class='danger'>\The [holder.my_atom] begins to vibrate violently!</span>")
log_and_message_admins("Oil extract reaction (explosion) has been activated in [get_area(holder.my_atom)]. Last fingerprints: [holder.my_atom.fingerprintslast]")
spawn(5 SECONDS)
if(holder && holder.my_atom)
explosion(get_turf(holder.my_atom), 1 * power, 3 * power, 6 * power)
if(holder && holder.my_atom) // Explosion may or may not have deleted the extract.
qdel(holder.my_atom)
// ********************
// * Bluespace slimes *
// ********************
/obj/item/slime_extract/bluespace
name = "bluespace slime extract"
icon_state = "bluespace slime extract"
description_info = "This extract creates slime crystals. When injected with water, it creates five 'lesser' slime crystals, which allow for limited \
short ranged, random teleporting. When injected with phoron, it creates one 'greater' slime crystal, which allows for a one time precise teleport to \
a specific area."
/datum/chemical_reaction/slime/bluespace_lesser
name = "Slime Lesser Tele"
id = "m_tele_lesser"
required_reagents = list("water" = 5)
result_amount = 1
required = /obj/item/slime_extract/bluespace
/datum/chemical_reaction/slime/bluespace_lesser/on_reaction(var/datum/reagents/holder)
for(var/i = 1 to 5)
new /obj/item/slime_crystal(get_turf(holder.my_atom))
..()
/datum/chemical_reaction/slime/bluespace_greater
name = "Slime Greater Tele"
id = "m_tele_lesser"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/bluespace
/datum/chemical_reaction/slime/bluespace_greater/on_reaction(var/datum/reagents/holder)
new /obj/item/weapon/disposable_teleporter/slime(get_turf(holder.my_atom))
..()
// *******************
// * Cerulean slimes *
// *******************
/obj/item/slime_extract/cerulean
name = "cerulean slime extract"
icon_state = "cerulean slime extract"
description_info = "This extract creates a slime extract enhancer agent, when injected with phoron. The agent allows an extract to have more \
'charges' before it goes inert."
/datum/chemical_reaction/slime/cerulean_enhancer
name = "Slime Enhancer"
id = "m_enhancer"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/cerulean
/datum/chemical_reaction/slime/cerulean_enhance/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/enhancer(get_turf(holder.my_atom))
..()
// ****************
// * Amber slimes *
// ****************
/obj/item/slime_extract/amber
name = "amber slime extract"
icon_state = "amber slime extract"
description_info = "This extract creates a slime feeding agent when injected with phoron, which will instantly feed the slime and make it reproduce. When \
injected with water, it will create a very delicious and filling product."
/datum/chemical_reaction/slime/amber_slimefood
name = "Slime Feeding"
id = "m_slime_food"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/amber
/datum/chemical_reaction/slime/amber_slimefood/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/feeding(get_turf(holder.my_atom))
..()
/datum/chemical_reaction/slime/amber_peoplefood
name = "Slime Food"
id = "m_people_food"
required_reagents = list("water" = 5)
result_amount = 1
required = /obj/item/slime_extract/amber
/datum/chemical_reaction/slime/amber_peoplefood/on_reaction(var/datum/reagents/holder)
new /obj/item/weapon/reagent_containers/food/snacks/slime(get_turf(holder.my_atom))
..()
// *******************
// * Sapphire slimes *
// *******************
// Renamed from adamantine.
/obj/item/slime_extract/sapphire
name = "sapphire slime extract"
icon_state = "sapphire slime extract"
description_info = "This extract will create one 'slime cube' when injected with phoron. The slime cube is needed to create a Promethean."
/datum/chemical_reaction/slime/sapphire_promethean
name = "Slime Promethean"
id = "m_promethean"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/sapphire
/datum/chemical_reaction/slime/sapphire_promethean/on_reaction(var/datum/reagents/holder)
new /obj/item/slime_cube(get_turf(holder.my_atom))
..()
// ***************
// * Ruby slimes *
// ***************
/obj/item/slime_extract/ruby
name = "ruby slime extract"
icon_state = "ruby slime extract"
description_info = "This extract will cause all entities close to the extract to become stronger for ten minutes, when injected with phoron. \
When injected with blood, makes a slime loyalty agent which will make the slime fight other dangerous entities but not station crew."
/datum/chemical_reaction/slime/ruby_swole
name = "Slime Strength"
id = "m_strength"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/ruby
/datum/chemical_reaction/slime/ruby_swole/on_reaction(var/datum/reagents/holder)
for(var/mob/living/L in range(1, holder.my_atom))
L.add_modifier(/datum/modifier/slime_strength, 10 MINUTES, src)
..()
/datum/modifier/slime_strength
name = "slime strength"
desc = "You feel much stronger than usual."
mob_overlay_state = "pink_sparkles"
on_created_text = "<span class='warning'>Twinkling spores of goo surround you. It makes you feel stronger and more robust.</span>"
on_expired_text = "<span class='notice'>The spores of goo have faded, and you feel your strength returning to what it was before.</span>"
stacks = MODIFIER_STACK_EXTEND
max_health_flat = 50
outgoing_melee_damage_percent = 2
disable_duration_percent = 0.5
incoming_damage_percent = 0.75
/datum/chemical_reaction/slime/ruby_loyalty
name = "Slime Loyalty"
id = "m_strength"
required_reagents = list("blood" = 5)
result_amount = 1
required = /obj/item/slime_extract/ruby
/datum/chemical_reaction/slime/ruby_loyalty/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/loyalty(get_turf(holder.my_atom))
..()
// *****************
// * Emerald slime *
// *****************
/obj/item/slime_extract/emerald
name = "emerald slime extract"
icon_state = "emerald slime extract"
description_info = "This extract will cause all entities close to the extract to become more agile for ten minutes, when injected with phoron."
/datum/chemical_reaction/slime/emerald_fast
name = "Slime Agility"
id = "m_agility"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/emerald
/datum/chemical_reaction/slime/emerald_fast/on_reaction(var/datum/reagents/holder)
for(var/mob/living/L in range(1, holder.my_atom))
L.add_modifier(/datum/modifier/slime_agility, 10 MINUTES, src)
..()
/datum/modifier/slime_agility
name = "slime agility"
desc = "You feel much faster than usual."
mob_overlay_state = "green_sparkles"
on_created_text = "<span class='warning'>Twinkling spores of goo surround you. It makes you feel fast and more agile.</span>"
on_expired_text = "<span class='notice'>The spores of goo have faded, and you feel your agility returning to what it was before.</span>"
stacks = MODIFIER_STACK_EXTEND
evasion = 2
slowdown = -1
// *********************
// * Light Pink slimes *
// *********************
/obj/item/slime_extract/light_pink
name = "light pink slime extract"
icon_state = "light pink slime extract"
description_info = "This extract creates a slime docility agent when injected with water, which will make the slime be harmless forever. \
When injected with phoron, it instead creates a slime friendship agent, which makes the slime consider the user their ally. The agent \
might be useful on other specimens as well."
/datum/chemical_reaction/slime/light_pink_docility
name = "Slime Docility"
id = "m_docile"
required_reagents = list("water" = 5)
result_amount = 1
required = /obj/item/slime_extract/light_pink
/datum/chemical_reaction/slime/light_pink_docility/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/docility(get_turf(holder.my_atom))
..()
/datum/chemical_reaction/slime/light_pink_friendship
name = "Slime Friendship"
id = "m_friendship"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/light_pink
/datum/chemical_reaction/slime/light_pink_friendship/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/friendship(get_turf(holder.my_atom))
..()
// ******************
// * Rainbow slimes *
// ******************
/obj/item/slime_extract/rainbow
name = "rainbow slime extract"
icon_state = "rainbow slime extract"
description_info = "This extract will create a baby slime of a random color when injected with phoron, or a slime unification agent if injected with water, \
which makes slimes stop attacking other slime colors."
/datum/chemical_reaction/slime/rainbow_random_slime
name = "Slime Random Slime"
id = "m_rng_slime"
required_reagents = list("phoron" = 5)
result_amount = 1
required = /obj/item/slime_extract/rainbow
/datum/chemical_reaction/slime/rainbow_random_slime/on_reaction(var/datum/reagents/holder)
var/list/forbidden_types = list(
/mob/living/simple_animal/slime/rainbow/kendrick
)
var/list/potential_types = typesof(/mob/living/simple_animal/slime) - forbidden_types
var/slime_type = pick(potential_types)
new slime_type(get_turf(holder.my_atom))
..()
/datum/chemical_reaction/slime/rainbow_unity
name = "Slime Unity"
id = "m_unity"
required_reagents = list("water" = 5)
result_amount = 1
required = /obj/item/slime_extract/rainbow
/datum/chemical_reaction/slime/rainbow_unity/on_reaction(var/datum/reagents/holder)
new /obj/item/slimepotion/unity(get_turf(holder.my_atom))
..()
+128
View File
@@ -0,0 +1,128 @@
// Slime cube lives here. Makes Prometheans.
/obj/item/slime_cube
name = "slimy monkey cube"
desc = "Wonder what might come out of this."
icon = 'icons/mob/slime2.dmi'
icon_state = "slime cube"
description_info = "Use in your hand to attempt to create a Promethean. It functions similarly to a positronic brain, in that a ghost is needed to become the Promethean."
var/searching = 0
/obj/item/slime_cube/attack_self(mob/user as mob)
if(!searching)
user << "<span class='warning'>You stare at the slimy cube, watching as some activity occurs.</span>"
icon_state = "slime cube active"
searching = 1
request_player()
spawn(60 SECONDS)
reset_search()
// Sometime down the road it would be great to make all of these 'ask ghosts if they want to be X' procs into a generic datum.
/obj/item/slime_cube/proc/request_player()
for(var/mob/observer/dead/O in player_list)
if(!O.MayRespawn())
continue
if(O.client)
if(O.client.prefs.be_special & BE_ALIEN)
question(O.client)
/obj/item/slime_cube/proc/question(var/client/C)
spawn(0)
if(!C)
return
var/response = alert(C, "Someone is requesting a soul for a promethean. Would you like to play as one?", "Promethean request", "Yes", "No", "Never for this round")
if(response == "Yes")
response = alert(C, "Are you sure you want to play as a promethean?", "Promethean request", "Yes", "No")
if(!C || 2 == searching)
return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located.
if(response == "Yes")
transfer_personality(C.mob)
else if(response == "Never for this round")
C.prefs.be_special ^= BE_ALIEN
/obj/item/slime_cube/proc/reset_search() //We give the players sixty seconds to decide, then reset the timer.
icon_state = "slime cube"
if(searching == 1)
searching = 0
var/turf/T = get_turf_or_move(src.loc)
for (var/mob/M in viewers(T))
M.show_message("<span class='warning'>The activity in the cube dies down. Maybe it will spark another time.</span>")
/obj/item/slime_cube/proc/transfer_personality(var/mob/candidate)
announce_ghost_joinleave(candidate, 0, "They are a promethean now.")
src.searching = 2
var/mob/living/carbon/human/S = new(get_turf(src))
S.client = candidate.client
to_chat(S, "<b>You are a promethean, brought into existence on [station_name()].</b>")
S.mind.assigned_role = "Promethean"
S.set_species("Promethean")
S.shapeshifter_set_colour("#2398FF")
visible_message("<span class='warning'>The monkey cube suddenly takes the shape of a humanoid!</span>")
var/newname = sanitize(input(S, "You are a Promethean. Would you like to change your name to something else?", "Name change") as null|text, MAX_NAME_LEN)
if(newname)
S.real_name = newname
S.name = S.real_name
S.dna.real_name = newname
if(S.mind)
S.mind.name = S.name
qdel(src)
// More or less functionally identical to the telecrystal tele.
/obj/item/slime_crystal
name = "lesser slime cystal"
desc = "A small, gooy crystal."
description_info = "This will teleport you to a mostly 'safe' tile when used in-hand, consuming the slime crystal. \
It can also teleport someone else, by throwing it at them or attacking them with it."
icon = 'icons/obj/objects.dmi'
icon_state = "slime_crystal_small"
w_class = ITEMSIZE_TINY
origin_tech = list(TECH_MAGNETS = 6, TECH_BLUESPACE = 3)
force = 1 //Needs a token force to ensure you can attack because for some reason you can't attack with 0 force things
/obj/item/slime_crystal/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
target.visible_message("<span class='warning'>\The [target] has been teleported with \the [src] by \the [user]!</span>")
safe_blink(target, 14)
qdel(src)
/obj/item/slime_crystal/attack_self(mob/user)
user.visible_message("<span class='warning'>\The [user] teleports themselves with \the [src]!</span>")
safe_blink(user, 14)
qdel(src)
/obj/item/slime_crystal/throw_impact(atom/movable/AM)
if(!istype(AM))
return
if(AM.anchored)
return
AM.visible_message("<span class='warning'>\The [AM] has been teleported with \the [src]!</span>")
safe_blink(AM, 14)
qdel(src)
/obj/item/weapon/disposable_teleporter/slime
name = "greater slime crystal"
desc = "A larger, gooier crystal."
description_info = "This will teleport you to a specific area once, when used in-hand."
icon = 'icons/obj/objects.dmi'
icon_state = "slime_crystal_large"
uses = 1
w_class = ITEMSIZE_SMALL
origin_tech = list(TECH_MAGNETS = 5, TECH_BLUESPACE = 4)
// Very filling food.
/obj/item/weapon/reagent_containers/food/snacks/slime
name = "slimy clump"
desc = "A glob of slime that is thick as honey. For the brave Xenobiologist."
icon_state = "honeycomb"
filling_color = "#FFBB00"
center_of_mass = list("x"=17, "y"=10)
nutriment_amt = 25 // Very filling.
nutriment_desc = list("slime" = 10, "sweetness" = 10, "bliss" = 5)
/obj/item/weapon/reagent_containers/food/snacks/slime/New()
..()
bitesize = 5
+255
View File
@@ -0,0 +1,255 @@
// These things get applied to slimes to do things.
/obj/item/slimepotion
name = "slime agent"
desc = "A flask containing strange, mysterious substances excreted by a slime."
icon = 'icons/obj/chemical.dmi'
w_class = ITEMSIZE_TINY
origin_tech = list(TECH_BIO = 4)
// This is actually applied to an extract, so no attack() overriding needed.
/obj/item/slimepotion/enhancer
name = "extract enhancer agent"
desc = "A potent chemical mix that will give a slime extract an additional two uses."
icon_state = "potpurple"
description_info = "This will even work on inert slime extracts, if it wasn't enhanced before. Extracts enhanced cannot be enhanced again."
// Makes slimes less likely to mutate.
/obj/item/slimepotion/stabilizer
name = "slime stabilizer agent"
desc = "A potent chemical mix that will reduce the chance of a slime mutating."
icon_state = "potcyan"
description_info = "The slime needs to be alive for this to work. It will reduce the chances of mutation by 15%."
/obj/item/slimepotion/stabilizer/attack(mob/living/simple_animal/slime/M, mob/user)
if(!istype(M))
to_chat(user, "<span class='warning'>The stabilizer only works on slimes!</span>")
return ..()
if(M.stat == DEAD)
to_chat(user, "<span class='warning'>The slime is dead!</span>")
return ..()
if(M.mutation_chance == 0)
to_chat(user, "<span class='warning'>The slime already has no chance of mutating!</span>")
return ..()
to_chat(user, "<span class='notice'>You feed the slime the stabilizer. It is now less likely to mutate.</span>")
M.mutation_chance = between(0, M.mutation_chance - 15, 100)
playsound(src, 'sound/effects/bubbles.ogg', 50, 1)
qdel(src)
// The opposite, makes the slime more likely to mutate.
/obj/item/slimepotion/mutator
name = "slime mutator agent"
desc = "A potent chemical mix that will increase the chance of a slime mutating."
description_info = "The slime needs to be alive for this to work. It will increase the chances of mutation by 12%."
icon_state = "potred"
/obj/item/slimepotion/mutator/attack(mob/living/simple_animal/slime/M, mob/user)
if(!istype(M))
to_chat(user, "<span class='warning'>The mutator only works on slimes!</span>")
return ..()
if(M.stat == DEAD)
to_chat(user, "<span class='warning'>The slime is dead!</span>")
return ..()
if(M.mutation_chance == 100)
to_chat(user, "<span class='warning'>The slime is already guaranteed to mutate!</span>")
return ..()
to_chat(user, "<span class='notice'>You feed the slime the mutator. It is now more likely to mutate.</span>")
M.mutation_chance = between(0, M.mutation_chance + 12, 100)
playsound(src, 'sound/effects/bubbles.ogg', 50, 1)
qdel(src)
// Makes the slime friendly forever.
/obj/item/slimepotion/docility
name = "docility agent"
desc = "A potent chemical mix that nullifies a slime's hunger, causing it to become docile and tame. It might also work on other creatures?"
icon_state = "potlightpink"
description_info = "The target needs to be alive, not already passive, and have animal-like intelligence."
/obj/item/slimepotion/docility/attack(mob/living/simple_animal/M, mob/user)
if(!istype(M))
to_chat(user, "<span class='warning'>The agent only works on creatures!</span>")
return ..()
if(M.stat == DEAD)
to_chat(user, "<span class='warning'>\The [M] is dead!</span>")
return ..()
// Slimes.
if(istype(M, /mob/living/simple_animal/slime))
var/mob/living/simple_animal/slime/S = M
if(S.docile)
to_chat(user, "<span class='warning'>The slime is already docile!</span>")
return ..()
S.pacify()
S.nutrition = 700
to_chat(M, "<span class='warning'>You absorb the agent and feel your intense desire to feed melt away.</span>")
to_chat(user, "<span class='notice'>You feed the slime the agent, removing its hunger and calming it.</span>")
// Simple Animals.
else if(istype(M, /mob/living/simple_animal))
var/mob/living/simple_animal/SA = M
if(SA.intelligence_level > SA_ANIMAL) // So you can't use this on Russians/syndies/hivebots/etc.
to_chat(user, "<span class='warning'>\The [SA] is too intellient for this to affect them.</span>")
return ..()
if(!SA.hostile)
to_chat(user, "<span class='warning'>\The [SA] is already passive!</span>")
return ..()
SA.hostile = FALSE
to_chat(M, "<span class='warning'>You consume the agent and feel a serene sense of peace.</span>")
to_chat(user, "<span class='notice'>You feed \the [SA] the agent, calming it.</span>")
playsound(src, 'sound/effects/bubbles.ogg', 50, 1)
M.LoseTarget() // So hostile things stop attacking people even if not hostile anymore.
var/newname = copytext(sanitize(input(user, "Would you like to give \the [M] a name?", "Name your new pet", M.name) as null|text),1,MAX_NAME_LEN)
if(newname)
M.name = newname
M.real_name = newname
qdel(src)
// Makes slimes make more extracts.
/obj/item/slimepotion/steroid
name = "slime steroid agent"
desc = "A potent chemical mix that will increase the amount of extracts obtained from harvesting a slime."
description_info = "The slime needs to be alive and not an adult for this to work. It will increase the amount of extracts gained by one, up to a max of five per slime. \
Extra extracts are not passed down to offspring when reproducing."
icon_state = "potpurple"
/obj/item/slimepotion/steroid/attack(mob/living/simple_animal/slime/M, mob/user)
if(!istype(M))
to_chat(user, "<span class='warning'>The steroid only works on slimes!</span>")
return ..()
if(M.stat == DEAD)
to_chat(user, "<span class='warning'>The slime is dead!</span>")
return ..()
if(M.is_adult) //Can't steroidify adults
to_chat(user, "<span class='warning'>Only baby slimes can use the steroid!</span>")
return ..()
if(M.cores >= 5)
to_chat(user, "<span class='warning'>The slime already has the maximum amount of extract!</span>")
return ..()
to_chat(user, "<span class='notice'>You feed the slime the steroid. It will now produce one more extract.</span>")
M.cores++
playsound(src, 'sound/effects/bubbles.ogg', 50, 1)
qdel(src)
// Makes slimes not try to murder other slime colors.
/obj/item/slimepotion/unity
name = "slime unity agent"
desc = "A potent chemical mix that makes the slime feel and be seen as all the colors at once, and as a result not be considered an enemy to any other color."
description_info = "The slime needs to be alive for this to work. Slimes unified will not attack or be attacked by other colored slimes, and this will \
carry over to offspring when reproducing."
icon_state = "potpink"
/obj/item/slimepotion/unity/attack(mob/living/simple_animal/slime/M, mob/user)
if(!istype(M))
to_chat(user, "<span class='warning'>The agent only works on slimes!</span>")
return ..()
if(M.stat == DEAD)
to_chat(user, "<span class='warning'>The slime is dead!</span>")
return ..()
if(M.unity == TRUE)
to_chat(user, "<span class='warning'>The slime is already unified!</span>")
return ..()
to_chat(user, "<span class='notice'>You feed the slime the agent. It will now be friendly to all other slimes.</span>")
to_chat(M, "<span class='notice'>\The [user] feeds you \the [src], and you suspect that all the other slimes will be \
your friends, at least if you don't attack them first.</span>")
M.unify()
playsound(src, 'sound/effects/bubbles.ogg', 50, 1)
qdel(src)
// Makes slimes not kill (most) humanoids but still fight spiders/carp/bears/etc.
/obj/item/slimepotion/loyalty
name = "slime loyalty agent"
desc = "A potent chemical mix that makes an animal deeply loyal to the species of whoever applies this, and will attack threats to them."
description_info = "The slime or other animal needs to be alive for this to work. The slime this is applied to will have their 'faction' change to \
the user's faction, which means the slime will attack things that are hostile to the user's faction, such as carp, spiders, and other slimes."
icon_state = "potred"
/obj/item/slimepotion/loyalty/attack(mob/living/simple_animal/M, mob/user)
if(!istype(M))
to_chat(user, "<span class='warning'>The agent only works on animals!</span>")
return ..()
if(M.intelligence_level > SA_ANIMAL) // So you can't use this on Russians/syndies/hivebots/etc.
to_chat(user, "<span class='warning'>\The [M] is too intellient for this to affect them.</span>")
return ..()
if(M.stat == DEAD)
to_chat(user, "<span class='warning'>The animal is dead!</span>")
return ..()
if(M.faction == user.faction)
to_chat(user, "<span class='warning'>\The [M] is already loyal to your species!</span>")
return ..()
to_chat(user, "<span class='notice'>You feed \the [M] the agent. It will now try to murder things that want to murder you instead.</span>")
to_chat(M, "<span class='notice'>\The [user] feeds you \the [src], and feel that the others will regard you as an outsider now.</span>")
M.faction = user.faction
M.attack_same = FALSE
M.LoseTarget() // So hostile things stop attacking people even if not hostile anymore.
playsound(src, 'sound/effects/bubbles.ogg', 50, 1)
qdel(src)
// User befriends the slime with this.
/obj/item/slimepotion/friendship
name = "slime friendship agent"
desc = "A potent chemical mix that makes an animal deeply loyal to the the specific entity which feeds them this agent."
description_info = "The slime or other animal needs to be alive for this to work. The slime this is applied to will consider the user \
their 'friend', and will never attack them. This might also work on other things besides slimes."
icon_state = "potlightpink"
/obj/item/slimepotion/friendship/attack(mob/living/simple_animal/M, mob/user)
if(!istype(M))
to_chat(user, "<span class='warning'>The agent only works on animals!</span>")
return ..()
if(M.intelligence_level > SA_ANIMAL) // So you can't use this on Russians/syndies/hivebots/etc.
to_chat(user, "<span class='warning'>\The [M] is too intellient for this to affect them.</span>")
return ..()
if(M.stat == DEAD)
to_chat(user, "<span class='warning'>The animal is dead!</span>")
return ..()
if(user in M.friends)
to_chat(user, "<span class='warning'>\The [M] is already loyal to you!</span>")
return ..()
to_chat(user, "<span class='notice'>You feed \the [M] the agent. It will now be your best friend.</span>")
to_chat(M, "<span class='notice'>\The [user] feeds you \the [src], and feel that \the [user] wants to be best friends with you.</span>")
if(isslime(M))
var/mob/living/simple_animal/slime/S = M
S.befriend(user)
else
M.friends.Add(user)
M.LoseTarget() // So hostile things stop attacking people even if not hostile anymore.
playsound(src, 'sound/effects/bubbles.ogg', 50, 1)
qdel(src)
// Feeds the slime instantly.
/obj/item/slimepotion/feeding
name = "slime feeding agent"
desc = "A potent chemical mix that will instantly sediate the slime."
description_info = "The slime needs to be alive for this to work. It will instantly grow the slime enough to reproduce."
icon_state = "potyellow"
/obj/item/slimepotion/feeding/attack(mob/living/simple_animal/slime/M, mob/user)
if(!istype(M))
to_chat(user, "<span class='warning'>The mutator only works on slimes!</span>")
return ..()
if(M.stat == DEAD)
to_chat(user, "<span class='warning'>The slime is dead!</span>")
return ..()
to_chat(user, "<span class='notice'>You feed the slime the feeding agent. It will now instantly reproduce.</span>")
M.make_adult()
M.amount_grown = 10
M.reproduce()
playsound(src, 'sound/effects/bubbles.ogg', 50, 1)
qdel(src)
+105
View File
@@ -0,0 +1,105 @@
/obj/item/weapon/melee/baton/slime
name = "slimebaton"
desc = "A modified stun baton designed to stun slimes and other lesser xeno lifeforms for handling."
icon_state = "slimebaton"
item_state = "slimebaton"
slot_flags = SLOT_BELT
force = 9
lightcolor = "#33CCFF"
origin_tech = list(TECH_COMBAT = 2, TECH_BIO = 4)
agonyforce = 10 //It's not supposed to be great at stunning human beings.
hitcost = 48 //Less zap for less cost
description_info = "This baton will stun a slime or other lesser lifeform for about five seconds, if hit with it while on."
/obj/item/weapon/melee/baton/slime/attack(mob/M, mob/user, hit_zone)
// Simple Animals.
if(istype(M, /mob/living/simple_animal/slime) && status)
var/mob/living/simple_animal/SA = M
if(SA.intelligence_level <= SA_ANIMAL) // So it doesn't stun hivebots or syndies.
SA.Weaken(5)
if(isslime(SA))
var/mob/living/simple_animal/slime/S = SA
S.adjust_discipline(3)
// Prometheans.
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.species && H.species.name == "Promethean" && status)
var/agony_to_apply = 60 - agonyforce
H.apply_damage(agony_to_apply, HALLOSS)
..()
/obj/item/weapon/melee/baton/slime/loaded/New()
..()
bcell = new/obj/item/weapon/cell/device(src)
update_icon()
return
// Research borg's version
/obj/item/weapon/melee/baton/slime/robot
hitcost = 200
/obj/item/weapon/melee/baton/slime/robot/attack_self(mob/user)
//try to find our power cell
var/mob/living/silicon/robot/R = loc
if (istype(R))
bcell = R.cell
return ..()
/obj/item/weapon/melee/baton/slime/robot/attackby(obj/item/weapon/W, mob/user)
return
// Xeno stun gun + projectile
/obj/item/weapon/gun/energy/taser/xeno
name = "xeno taser gun"
desc = "Straight out of NT's testing laboratories, this small gun is used to subdue non-humanoid xeno life forms. \
While marketed towards handling slimes, it may be useful for other creatures."
desc = "An easy to use weapon designed by NanoTrasen, for NanoTrasen. This weapon is designed to subdue lesser \
xeno lifeforms at a distance. It is ineffective at stunning larger lifeforms such as humanoids."
icon_state = "taserold"
fire_sound = 'sound/weapons/taser2.ogg'
charge_cost = 120 // Twice as many shots.
projectile_type = /obj/item/projectile/beam/stun/xeno
accuracy = 2 // Make it a bit easier to hit the slimes.
description_info = "This gun will stun a slime or other lesser lifeform for about two seconds, if hit with the projectile it fires."
/obj/item/weapon/gun/energy/taser/xeno/robot // Borg version
self_recharge = 1
use_external_power = 1
recharge_time = 3
/obj/item/projectile/beam/stun/xeno
icon_state = "omni"
agony = 4
nodamage = TRUE
// For whatever reason the projectile qdels itself early if this is on, meaning on_hit() won't be called on prometheans.
// Probably for the best so that it doesn't harm the slime.
taser_effect = FALSE
muzzle_type = /obj/effect/projectile/laser_omni/muzzle
tracer_type = /obj/effect/projectile/laser_omni/tracer
impact_type = /obj/effect/projectile/laser_omni/impact
/obj/item/projectile/beam/stun/xeno/on_hit(var/atom/target, var/blocked = 0)
if(istype(target, /mob/living))
var/mob/living/L = target
// Simple Animals.
if(istype(L, /mob/living/simple_animal/slime))
var/mob/living/simple_animal/SA = L
if(SA.intelligence_level <= SA_ANIMAL) // So it doesn't stun hivebots or syndies.
SA.Weaken(2) // Less powerful since its ranged, and therefore safer.
if(isslime(SA))
var/mob/living/simple_animal/slime/S = SA
S.adjust_discipline(2)
// Prometheans.
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.species && H.species.name == "Promethean")
var/agony_to_apply = 60 - agony
H.apply_damage(agony_to_apply, HALLOSS)
..()
+118
View File
@@ -0,0 +1,118 @@
// This is specifically for slimes since we don't have a 'normal' processor now.
// Feel free to rename it if that ever changes.
/obj/machinery/processor
name = "slime processor"
desc = "An industrial grinder used to automate the process of slime core extraction. It can also recycle biomatter."
icon = 'icons/obj/kitchen.dmi'
icon_state = "processor1"
density = TRUE
anchored = TRUE
var/processing = FALSE // So I heard you like processing.
var/list/to_be_processed = list()
var/monkeys_recycled = 0
description_info = "Clickdrag dead slimes or monkeys to it to insert them. It will make a new monkey cube for every four monkeys it processes."
/obj/item/weapon/circuitboard/processor
name = T_BOARD("slime processor")
build_path = /obj/machinery/processor
origin_tech = list(TECH_DATA = 2, TECH_BIO = 2)
/obj/machinery/processor/attack_hand(mob/living/user)
if(processing)
to_chat(user, "<span class='warning'>The processor is in the process of processing!</span>")
return
if(to_be_processed.len)
spawn(1)
begin_processing()
else
to_chat(user, "<span class='warning'>The processor is empty.</span>")
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 1)
return
// Verb to remove everything.
/obj/machinery/processor/verb/eject()
set category = "Object"
set name = "Eject Processor"
set src in oview(1)
if(usr.stat || !usr.canmove || usr.restrained())
return
empty()
add_fingerprint(usr)
return
// Ejects all the things out of the machine.
/obj/machinery/processor/proc/empty()
for(var/atom/movable/AM in to_be_processed)
to_be_processed.Remove(AM)
AM.forceMove(get_turf(src))
// Ejects all the things out of the machine.
/obj/machinery/processor/proc/insert(var/atom/movable/AM, var/mob/living/user)
if(!Adjacent(AM))
return
if(!can_insert(AM))
to_chat(user, "<span class='warning'>\The [src] cannot process \the [AM] at this time.</span>")
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 1)
return
to_be_processed.Add(AM)
AM.forceMove(src)
visible_message("<span class='notice'>\the [user] places [AM] inside \the [src].</span>")
/obj/machinery/processor/proc/begin_processing()
if(processing)
return // Already doing it.
processing = TRUE
playsound(src.loc, 'sound/machines/juicer.ogg', 50, 1)
for(var/atom/movable/AM in to_be_processed)
extract(AM)
sleep(1 SECONDS)
while(monkeys_recycled >= 4)
new /obj/item/weapon/reagent_containers/food/snacks/monkeycube(get_turf(src))
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
monkeys_recycled -= 4
sleep(1 SECOND)
processing = FALSE
playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
/obj/machinery/processor/proc/extract(var/atom/movable/AM)
if(istype(AM, /mob/living/simple_animal/slime))
var/mob/living/simple_animal/slime/S = AM
while(S.cores)
new S.coretype(get_turf(src))
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
S.cores--
sleep(1 SECOND)
to_be_processed.Remove(S)
qdel(S)
if(istype(AM, /mob/living/carbon/human))
var/mob/living/carbon/human/M = AM
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
to_be_processed.Remove(M)
qdel(M)
monkeys_recycled++
sleep(1 SECOND)
/obj/machinery/processor/proc/can_insert(var/atom/movable/AM)
if(istype(AM, /mob/living/simple_animal/slime))
var/mob/living/simple_animal/slime/S = AM
if(S.stat != DEAD)
return FALSE
return TRUE
if(istype(AM, /mob/living/carbon/human))
var/mob/living/carbon/human/H = AM
if(!istype(H.species, /datum/species/monkey))
return FALSE
if(H.stat != DEAD)
return FALSE
return TRUE
return FALSE
/obj/machinery/processor/MouseDrop_T(var/atom/movable/AM, var/mob/living/user)
if(user.stat || user.incapacitated(INCAPACITATION_DISABLED) || !istype(user))
return
insert(AM, user)
@@ -1,70 +0,0 @@
/* What this file contains:
* A specialized stun prod, for handling fiesty slimes
* A specialized stun gun, for handling many fiesty slimes
* A stun projectile for handling xenomorphs.
*/
/obj/item/weapon/melee/baton/slime
name = "slimebaton"
desc = "A modified stun baton designed to stun slimes for handling."
icon_state = "slimebaton"
item_state = "slimebaton"
slot_flags = SLOT_BELT
force = 9
lightcolor = "#33CCFF"
origin_tech = list(TECH_COMBAT = 2, TECH_BIO = 4)
agonyforce = 10 //It's not supposed to be great at stunning human beings.
var/stasisforce = 60 //How much stasis it does to slimes, and 1/3rd to non-slimes.
hitcost = 48 //Less zap for less cost
/obj/item/weapon/melee/baton/slime/attack(mob/M, mob/user)
if(istype(M, /mob/living/simple_animal/xeno))
var/mob/living/simple_animal/xeno/X = M
if(istype(M, /mob/living/simple_animal/xeno/slime))
X.stasis += stasisforce
else
X.stasis += (stasisforce / 6)
..()
/obj/item/weapon/melee/baton/slime/loaded/New()
..()
bcell = new/obj/item/weapon/cell/device(src)
update_icon()
return
// Xeno stun gun + projectile
/obj/item/weapon/gun/energy/taser/xeno
name = "xeno taser gun"
desc = "Straight out of NT's testing laboratories, this small gun is used to subdue non-humanoid xeno life forms. While marketed towards handling slimes, it may be useful for other creatures."
icon_state = "taserold"
fire_sound = 'sound/weapons/taser2.ogg'
projectile_type = /obj/item/projectile/beam/stun/xeno
/obj/item/projectile/beam/stun/xeno
icon_state = "omni"
agony = 4
var/stasisforce = 40
muzzle_type = /obj/effect/projectile/laser_omni/muzzle
tracer_type = /obj/effect/projectile/laser_omni/tracer
impact_type = /obj/effect/projectile/laser_omni/impact
/*
/obj/item/projectile/beam/stun/xeno/on_hit(var/atom/target, var/blocked = 0)
if(istype(target, /mob/living/simple_animal/xeno))
world << "is xeno"
var/mob/living/simple_animal/xeno/X = target
world << "[target.name]"
if(istype(X, /mob/living/simple_animal/xeno/slime))
world << "is slime"
X.stasis += stasisforce
else
world << "is not slime"
X.stasis += (stasisforce / 8)
else
world << "is not xeno"
..()
*/