mirror of
https://github.com/CHOMPstation/CHOMPstation.git
synced 2026-07-12 07:32:33 +01:00
Merge pull request #3767 from Neerti/8/10/2017_make_xenobio_old_again
Make Xenobiology Old(ish) Again
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"),
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)]°C) ([round(temperature*1.8-459.67)]°F)</FONT>"
|
||||
else
|
||||
temp_text = "<FONT color=blue>[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°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),
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>")
|
||||
@@ -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
|
||||
. = ..()
|
||||
|
||||
@@ -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))
|
||||
..()
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
..()
|
||||
@@ -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"
|
||||
..()
|
||||
*/
|
||||
Reference in New Issue
Block a user