Shifts vore mobs to proper locations, cleans loose folder

also attempts a Travis complaint fix The command "awk -f tools/indentation.awk **/*.dm" exited with 1.
This commit is contained in:
Poojawa
2019-02-02 08:07:20 -06:00
parent 0eb6288ce1
commit a9d025b1f0
34 changed files with 1878 additions and 88 deletions

View File

@@ -1,53 +1,53 @@
/mob/living/simple_mob/vore/cookiegirl /mob/living/simple_mob/vore/cookiegirl
name = "cookiegirl" name = "cookiegirl"
desc = "A woman made with a combination of, well... Whatever you put in a cookie. What were the chefs thinking?" desc = "A woman made with a combination of, well... Whatever you put in a cookie. What were the chefs thinking?"
icon_state = "cookiegirl" icon_state = "cookiegirl"
icon_living = "cookiegirl" icon_living = "cookiegirl"
icon_rest = "cookiegirl_rest" icon_rest = "cookiegirl_rest"
icon_dead = "cookiegirl-dead" icon_dead = "cookiegirl-dead"
icon = 'icons/mob/vore.dmi' icon = 'icons/mob/vore.dmi'
maxHealth = 10 maxHealth = 10
health = 10 health = 10
harm_intent_damage = 2 harm_intent_damage = 2
melee_damage_lower = 5 melee_damage_lower = 5
melee_damage_upper = 10 melee_damage_upper = 10
say_list_type = /datum/say_list/cookiegirl say_list_type = /datum/say_list/cookiegirl
ai_holder_type = /datum/ai_holder/simple_mob/passive/cookiegirl ai_holder_type = /datum/ai_holder/simple_mob/passive/cookiegirl
// Activate Noms! // Activate Noms!
/mob/living/simple_mob/vore/cookiegirl /mob/living/simple_mob/vore/cookiegirl
vore_active = 1 vore_active = 1
vore_bump_chance = 2 vore_bump_chance = 2
vore_pounce_chance = 25 vore_pounce_chance = 25
vore_standing_too = 1 vore_standing_too = 1
vore_ignores_undigestable = 0 // Do they look like they care? vore_ignores_undigestable = 0 // Do they look like they care?
vore_default_mode = DM_HOLD // They're cookiepeople, what do you expect? vore_default_mode = DM_HOLD // They're cookiepeople, what do you expect?
vore_digest_chance = 10 // Gonna become as sweet as sugar, soon. vore_digest_chance = 10 // Gonna become as sweet as sugar, soon.
vore_icons = SA_ICON_LIVING | SA_ICON_REST vore_icons = SA_ICON_LIVING | SA_ICON_REST
/datum/ai_holder/simple_mob/passive/cookiegirl/on_hear_say(mob/living/speaker, message) /datum/ai_holder/simple_mob/passive/cookiegirl/on_hear_say(mob/living/speaker, message)
if(!speaker.client) if(!speaker.client)
return return
if(findtext(message, "Can I eat you?")) if(findtext(message, "Can I eat you?"))
delayed_say(pick("Do you really wanna eat someone as sweet as me~?"), speaker) delayed_say(pick("Do you really wanna eat someone as sweet as me~?"), speaker)
if(findtext(message, "You look tasty.")) if(findtext(message, "You look tasty."))
delayed_say(pick("Awww, thank you~!"), speaker) delayed_say(pick("Awww, thank you~!"), speaker)
if(findtext(message, "Can I serve you to the crew?")) if(findtext(message, "Can I serve you to the crew?"))
delayed_say(pick("If I have a backup, sure!"), speaker) delayed_say(pick("If I have a backup, sure!"), speaker)
/datum/say_list/cookiegirl /datum/say_list/cookiegirl
speak = list("Hi!","Are you hungry?","Got milk~?","What to do, what to do...") speak = list("Hi!","Are you hungry?","Got milk~?","What to do, what to do...")
emote_hear = list("hums","whistles") emote_hear = list("hums","whistles")
emote_see = list("shakes her head","shivers", "picks a bit of crumb off of her body and sticks it in her mouth.") emote_see = list("shakes her head","shivers", "picks a bit of crumb off of her body and sticks it in her mouth.")
/datum/ai_holder/simple_mob/passive/cookiegirl /datum/ai_holder/simple_mob/passive/cookiegirl
base_wander_delay = 8 base_wander_delay = 8
intelligence_level = AI_NORMAL //not sure why we have this, but I'm just porting. intelligence_level = AI_NORMAL //not sure why we have this, but I'm just porting.

View File

@@ -1,30 +1,30 @@
/mob/living/simple_mob/vore/fennix /mob/living/simple_mob/vore/fennix
name = "Fennix" name = "Fennix"
desc = "A feral fennix, Warm to the touch" desc = "A feral fennix, Warm to the touch"
tt_desc = "Incaendium Faeles Vulpes" tt_desc = "Incaendium Faeles Vulpes"
icon_state = "fennix" icon_state = "fennix"
icon_living = "fennix" icon_living = "fennix"
icon_dead = "fennix_dead" icon_dead = "fennix_dead"
icon = 'icons/mob/vore.dmi' icon = 'icons/mob/vore.dmi'
faction = "fennec" // Will protec other fenfens faction = "fennec" // Will protec other fenfens
maxHealth = 60 maxHealth = 60
health = 60 health = 60
response_help = "pats the" response_help = "pats the"
response_disarm = "gently pushes aside the" response_disarm = "gently pushes aside the"
response_harm = "hits the" response_harm = "hits the"
harm_intent_damage = 20 harm_intent_damage = 20
melee_damage_lower = 1 melee_damage_lower = 1
melee_damage_upper = 5 melee_damage_upper = 5
attacktext = list("Bites") attacktext = list("Bites")
say_list_type = /datum/say_list/fennix say_list_type = /datum/say_list/fennix
ai_holder_type = /datum/ai_holder/simple_mob/retaliate/cooperative ai_holder_type = /datum/ai_holder/simple_mob/retaliate/cooperative
/datum/say_list/fennix /datum/say_list/fennix
speak = list("SQUEL!","SQEL?","Skree.") speak = list("SQUEL!","SQEL?","Skree.")
emote_hear = list("Screeeeecheeeeessss!","Chirrup.") emote_hear = list("Screeeeecheeeeessss!","Chirrup.")
emote_see = list("earflicks","pats at the ground") emote_see = list("earflicks","pats at the ground")

View File

@@ -0,0 +1,400 @@
// ToDo: Make this code not a fucking snowflaky horrible broken mess. Do not use until it's actually fixed. It's miserably bad right now.
// Also ToDo: Dev-to-dev communication to ensure responsible parties (if available. In this case, yes.) are aware of what's going on and what's broken.
// Probably easier to troubleshoot when we ain't breaking the server by spawning a buttload of heavily extra feature coded snowflake mobs to the wilderness as mass cannonfodder.
// Also ToDo: An actual "simple" mob for that purpose if necessary :v
/mob/living/simple_mob/otie //Spawn this one only if you're looking for a bad time. Not friendly.
name = "otie"
desc = "The classic bioengineered longdog."
tt_desc = "Otus robustus"
icon = 'icons/mob/vore64x32.dmi'
icon_state = "otie"
icon_living = "otie"
icon_dead = "otie-dead"
icon_rest = "otie_rest"
faction = "otie"
recruitable = 1
maxHealth = 150
health = 150
minbodytemp = 200
move_to_delay = 4
hostile = 1
investigates = 1
reacts = 1
animal = 1
specific_targets = 1
run_at_them = 0
attack_same = 0
speak_chance = 4
speak = list("Boof.","Waaf!","Prurr.","Bork!","Rurrr..","Arf.")
speak_emote = list("growls", "roars", "yaps", "Awoos")
emote_hear = list("rurrs", "rumbles", "rowls", "groans softly", "murrs", "sounds hungry", "yawns")
emote_see = list("stares ferociously", "snarls", "licks their chops", "stretches", "yawns")
say_maybe_target = list("Ruh?", "Waf?")
say_got_target = list("Rurrr!", "ROAR!", "MARR!", "RERR!", "RAHH!", "RAH!", "WARF!")
melee_damage_lower = 5
melee_damage_upper = 15 //Don't break my bones bro
response_help = "pets the"
response_disarm = "bops the"
response_harm = "hits the"
attacktext = list("mauled")
friendly = list("nuzzles", "slobberlicks", "noses softly at", "noseboops", "headbumps against", "leans on", "nibbles affectionately on")
meat_amount = 6
old_x = -16
old_y = 0
default_pixel_x = -16
pixel_x = -16
pixel_y = 0
max_buckled_mobs = 1 //Yeehaw
can_buckle = TRUE
buckle_movable = TRUE
buckle_lying = FALSE
mount_offset_y = 10
var/glowyeyes = FALSE
var/image/eye_layer = null
var/eyetype
var/mob/living/carbon/human/friend
var/tamed = 0
var/tame_chance = 50 //It's a fiddy-fiddy default you may get a buddy pal or you may get mauled and ate. Win-win!
// Activate Noms!
/mob/living/simple_mob/otie
vore_active = 1
vore_capacity = 1
vore_pounce_chance = 20
vore_icons = SA_ICON_LIVING | SA_ICON_REST
/mob/living/simple_mob/otie/feral //gets the pet2tame feature. starts out hostile tho so get gamblin'
name = "mutated feral otie"
desc = "The classic bioengineered longdog. No pets. Only bite. This one has mutated from too much time out on the surface of Virgo-3B."
tt_desc = "Otus phoronis"
icon_state = "siftusian"
icon_living = "siftusian"
icon_dead = "siftusian-dead"
icon_rest = "siftusian_rest"
faction = "virgo3b"
tame_chance = 5 // Only a 1 in 20 chance of success. It's feral. What do you expect?
melee_damage_lower = 10
melee_damage_upper = 25
// Lazy way of making sure this otie survives outside.
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
glowyeyes = TRUE
eyetype = "photie"
/mob/living/simple_mob/otie/red
name = "feral red otie"
desc = "Seems this ominous looking longdog has been infused with wicked infernal forces."
tt_desc = "Otus infernalis"
icon_state = "hotie"
icon_living = "hotie"
icon_dead = "hotie-dead"
icon_rest = "hotie_rest"
faction = "cult"
tame_chance = 20
melee_damage_lower = 10
melee_damage_upper = 25
// Lazy way of making sure this otie survives outside.
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
glowyeyes = TRUE
eyetype = "hotie"
/mob/living/simple_mob/otie/red/friendly //gets the pet2tame feature and doesn't kill you right away
name = "red otie"
desc = "Seems this ominous looking longdog has been infused with wicked infernal forces. This one seems rather peaceful though."
faction = "neutral"
tamed = 1
/mob/living/simple_mob/otie/friendly //gets the pet2tame feature and doesn't kill you right away
name = "otie"
desc = "The classic bioengineered longdog. This one might even tolerate you!"
faction = "neutral"
tamed = 1
/mob/living/simple_mob/otie/cotie //same as above but has a little collar :v
name = "tamed otie"
desc = "The classic bioengineered longdog. This one has a nice little collar on its neck. However a proper domesticated otie is an oxymoron and the collar is likely just a decoration."
icon_state = "cotie"
icon_living = "cotie"
icon_rest = "cotie_rest"
faction = "neutral"
tamed = 1
/mob/living/simple_mob/otie/cotie/phoron //friendly phoron pup with collar
name = "mutated otie"
desc = "Looks like someone did manage to domesticate one of those wild phoron mutants. What a badass."
tt_desc = "Otus phoronis"
icon_state = "pcotie"
icon_living = "pcotie"
icon_rest = "pcotie_rest"
icon_dead = "siftusian-dead"
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
glowyeyes = TRUE
eyetype = "photie"
/mob/living/simple_mob/otie/security //tame by default unless you're a marked crimester. can be befriended to follow with pets tho.
name = "guard otie"
desc = "The VARMAcorp bioengineering division flagship product on trained optimal snowflake guard dogs."
icon_state = "sotie"
icon_living = "sotie"
icon_rest = "sotie_rest"
icon_dead = "sotie-dead"
faction = "neutral"
maxHealth = 200 //armored or something
health = 200
tamed = 1
glowyeyes = TRUE
eyetype = "sotie"
loot_list = list(/obj/item/clothing/glasses/sunglasses/sechud,/obj/item/clothing/suit/armor/vest/alt)
vore_pounce_chance = 60 // Good boys don't do too much police brutality.
var/check_records = 0 // If true, arrests people without a record.
var/check_arrest = 1 // If true, arrests people who are set to arrest.
/mob/living/simple_mob/otie/security/phoron
name = "mutated guard otie"
desc = "An extra rare phoron resistant version of the VARMAcorp trained snowflake guard dogs."
tt_desc = "Otus phoronis"
icon_state = "sifguard"
icon_living = "sifguard"
icon_rest = "sifguard_rest"
icon_dead = "sifguard-dead"
melee_damage_lower = 10
melee_damage_upper = 25
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
glowyeyes = TRUE
eyetype = "sotie"
/mob/living/simple_mob/otie/PunchTarget()
if(istype(target_mob,/mob/living/simple_mob/mouse))
return EatTarget()
else ..()
/mob/living/simple_mob/otie/Found(var/atom/found_atom)
if(!SA_attackable(found_atom))
return null
if(istype(found_atom,/mob/living/simple_mob/mouse))
return found_atom
else if(ismob(found_atom))
var/mob/found_mob = found_atom
if(found_mob.faction == faction)
return null
else if(friend == found_atom)
return null
else if(tamed == 1 && ishuman(found_atom))
return null
else if(tamed == 1 && isrobot(found_atom))
return null
else
if(resting)
lay_down()
return found_atom
else
return null
/mob/living/simple_mob/otie/security/Found(var/atom/found_atom)
if(check_threat(found_atom) >= 4)
if(resting)
lay_down()
return found_atom
..()
/mob/living/simple_mob/otie/attackby(var/obj/item/O, var/mob/user) // Trade donuts for bellybrig victims.
if(istype(O, /obj/item/weapon/reagent_containers/food))
qdel(O)
playsound(src.loc,'sound/items/eatfood.ogg', rand(10,50), 1)
if(ai_inactive)//No autobarf on player control.
return
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/donut) && istype(src, /mob/living/simple_mob/otie/security))
to_chat(user,"<span class='notice'>The guard pup accepts your offer for their catch.</span>")
release_vore_contents()
else if(prob(2)) //Small chance to get prey out from non-sec oties.
to_chat(user,"<span class='notice'>The pup accepts your offer for their catch.</span>")
release_vore_contents()
return
. = ..()
/mob/living/simple_mob/otie/security/feed_grabbed_to_self(var/mob/living/user, var/mob/living/prey) // Make the gut start out safe for bellybrigging.
if(ishuman(prey))
vore_selected.digest_mode = DM_HOLD
if(check_threat(prey) >= 4)
global_announcer.autosay("[src] has detained suspect <b>[target_name(prey)]</b> in <b>[get_area(src)]</b>.", "SmartCollar oversight", "Security")
if(istype(prey,/mob/living/simple_mob/mouse))
vore_selected.digest_mode = DM_DIGEST
. = ..()
/mob/living/simple_mob/otie/security/proc/check_threat(var/mob/living/M)
if(!M || !ishuman(M) || M.stat == DEAD || src == M)
return 0
return M.assess_perp(0, 0, 0, check_records, check_arrest)
/mob/living/simple_mob/otie/security/set_target(var/mob/M)
ai_log("SetTarget([M])",2)
if(!M || (world.time - last_target_time < 5 SECONDS) && target_mob)
ai_log("SetTarget() can't set it again so soon",3)
return 0
var/turf/seen = get_turf(M)
if(investigates && (annoyed < 10))
try_say_list(say_maybe_target)
face_atom(seen)
annoyed += 14
sleep(1 SECOND) //For realism
if(M in ListTargets(view_range))
try_say_list(say_got_target)
target_mob = M
last_target_time = world.time
if(check_threat(M) >= 4)
global_announcer.autosay("[src] is attempting to detain suspect <b>[target_name(M)]</b> in <b>[get_area(src)]</b>.", "SmartCollar oversight", "Security")
return M
else if(investigates)
spawn(1)
WanderTowards(seen)
return 0
/mob/living/simple_mob/otie/security/proc/target_name(mob/living/T)
if(ishuman(T))
var/mob/living/carbon/human/H = T
return H.get_id_name("unidentified person")
return "unidentified lifeform"
//Basic friend AI
/mob/living/simple_mob/otie/Life()
. = ..()
if(!. || ai_inactive) return
if(prob(5) && (stance == STANCE_IDLE))
lay_down()
if(!friend) return
var/friend_dist = get_dist(src,friend)
if (friend_dist <= 4)
if(stance == STANCE_IDLE)
if(set_follow(friend))
handle_stance(STANCE_FOLLOW)
if(resting)
lay_down()
if (friend_dist <= 1)
if (friend.stat >= DEAD || friend.health <= config.health_threshold_softcrit)
if (prob((friend.stat < DEAD)? 50 : 15))
var/verb = pick("whines", "yelps", "whimpers")
audible_emote(pick("[verb] in distress.", "[verb] anxiously."))
else
if (prob(5))
visible_emote(pick("nuzzles [friend].",
"brushes against [friend].",
"rubs against [friend].",
"noses at [friend].",
"slobberlicks [friend].",
"murrs contently.",
"leans on [friend].",
"nibbles affectionately on [friend]."))
else if (friend.health <= 50)
if (prob(10))
var/verb = pick("whines", "yelps", "whimpers")
audible_emote("[verb] anxiously.")
//Pet 4 friendly
/mob/living/simple_mob/otie/attack_hand(mob/living/carbon/human/M as mob)
switch(M.a_intent)
if(I_HELP)
if(health > 0)
M.visible_message("<span class='notice'>[M] [response_help] \the [src].</span>")
if(ai_inactive)
return
LoseTarget()
handle_stance(STANCE_IDLE)
if(prob(tame_chance))
friend = M
if(tamed != 1)
tamed = 1
faction = M.faction
sleep(1 SECOND)
if(I_GRAB)
if(health > 0)
if(ai_inactive)
return
audible_emote("growls disapprovingly at [M].")
if(M == friend)
friend = null
return
else
..()
else
..()
/mob/living/simple_mob/otie/proc/add_eyes()
if(!eye_layer)
eye_layer = image(icon, "[eyetype]-eyes")
eye_layer.plane = PLANE_LIGHTING_ABOVE
add_overlay(eye_layer)
/mob/living/simple_mob/otie/proc/remove_eyes()
cut_overlay(eye_layer)
/mob/living/simple_mob/otie/New()
if(glowyeyes)
add_eyes()
..()
/mob/living/simple_mob/otie/update_icon()
. = ..()
remove_eyes()
if(glowyeyes && stat == CONSCIOUS && !resting)
add_eyes()
/mob/living/simple_mob/otie/death(gibbed, deathmessage = "dies!")
.=..()
resting = 0
icon_state = icon_dead
/mob/living/simple_animal/otie/Login()
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_animal(src)
verbs |= /mob/living/simple_animal/proc/animal_mount
/mob/living/simple_animal/otie/MouseDrop_T(mob/living/M, mob/living/user)
return

View File

@@ -0,0 +1,13 @@
#define NOT_WHILE_SHIFTED 1
#define ONLY_WHILE_SHIFTED 2
#define SHIFTED_OR_NOT 3
#define BLUE_EYES 1
#define RED_EYES 2
#define PURPLE_EYES 3
#define YELLOW_EYES 4
#define GREEN_EYES 5
#define ORANGE_EYES 6
#define AB_PHASE_SHIFTED 0x1
#define AB_SHADE_REGEN 0x2

View File

@@ -0,0 +1,165 @@
/obj/effect/shadekin_ability
name = ""
desc = ""
icon = 'icons/mob/screen_spells.dmi'
var/ability_name = "FIX ME"
var/cost = 50
var/mob/living/simple_mob/shadekin/my_kin
var/shift_mode = NOT_WHILE_SHIFTED
var/ab_sound
/obj/effect/shadekin_ability/New(var/new_kin)
..()
my_kin = new_kin
loc = null
/obj/effect/shadekin_ability/Destroy()
my_kin = null
return ..()
/obj/effect/shadekin_ability/proc/atom_button_text()
var/shift_denial
if(shift_mode == NOT_WHILE_SHIFTED && (my_kin.ability_flags & AB_PHASE_SHIFTED))
shift_denial = "Physical Only"
else if(shift_mode == ONLY_WHILE_SHIFTED && !(my_kin.ability_flags & AB_PHASE_SHIFTED))
shift_denial = "Shifted Only"
if(shift_denial)
name = shift_denial
else
name = my_kin.energy >= cost ? "Activate" : "No Energy"
return src
/obj/effect/shadekin_ability/Click(var/location, var/control, var/params)
if(my_kin.stat) return
var/list/clickprops = params2list(params)
var/opts = clickprops["shift"]
if(opts)
to_chat(my_kin,"<span class='notice'><b>[name]</b> (Cost: [cost]%) - [desc]</span>")
else
do_ability(my_kin)
/obj/effect/shadekin_ability/proc/do_ability()
if(my_kin.stat)
to_chat(my_kin,"<span class='warning'>Can't use that ability in your state!</span>")
return FALSE
if(shift_mode == NOT_WHILE_SHIFTED && (my_kin.ability_flags & AB_PHASE_SHIFTED))
to_chat(my_kin,"<span class='warning'>Can't use that ability while phase shifted!</span>")
return FALSE
else if(shift_mode == ONLY_WHILE_SHIFTED && !(my_kin.ability_flags & AB_PHASE_SHIFTED))
to_chat(my_kin,"<span class='warning'>Can only use that ability while phase shifted!</span>")
return FALSE
else if(my_kin.energy < cost)
to_chat(my_kin,"<span class='warning'>Not enough energy for that ability!</span>")
return FALSE
my_kin.energy -= cost
if(ab_sound)
playsound(src,ab_sound,75,1)
return TRUE
/////////////////////////////////////////////////////////////////
/obj/effect/shadekin_ability/phase_shift
ability_name = "Phase Shift"
desc = "Shift yourself out of alignment with realspace to travel quickly between dark areas (or light areas, with a price)."
icon_state = "tech_passwall"
cost = 100
shift_mode = SHIFTED_OR_NOT
ab_sound = 'sound/effects/stealthoff.ogg'
/obj/effect/shadekin_ability/phase_shift/do_ability()
if(!..())
return
my_kin.phase_shift()
if(my_kin.ability_flags & AB_PHASE_SHIFTED)
cost = 0 //Shifting back is free (but harmful in light)
else
cost = initial(cost)
/////////////////////////////////////////////////////////////////
/obj/effect/shadekin_ability/heal_boop
ability_name = "Regenerate Other"
desc = "Spend energy to heal physical wounds in another creature."
icon_state = "tech_biomedaura"
cost = 50
shift_mode = NOT_WHILE_SHIFTED
ab_sound = 'sound/effects/EMPulse.ogg'
/obj/effect/shadekin_ability/heal_boop/do_ability()
if(!..())
return
if(!my_kin.mend_other())
my_kin.energy += cost //Refund due to abort
/datum/modifier/shadekin/heal_boop
name = "Shadekin Regen"
desc = "You feel serene and well rested."
mob_overlay_state = "green_sparkles"
on_created_text = "<span class='notice'>Sparkles begin to appear around you, and all your ills seem to fade away.</span>"
on_expired_text = "<span class='notice'>The sparkles have faded, although you feel much healthier than before.</span>"
stacks = MODIFIER_STACK_EXTEND
/datum/modifier/shadekin/heal_boop/tick()
if(!holder.getBruteLoss() && !holder.getFireLoss() && !holder.getToxLoss() && !holder.getOxyLoss() && !holder.getCloneLoss()) // No point existing if the spell can't heal.
expire()
return
holder.adjustBruteLoss(-2)
holder.adjustFireLoss(-2)
holder.adjustToxLoss(-2)
holder.adjustOxyLoss(-2)
holder.adjustCloneLoss(-2)
/////////////////////////////////////////////////////////////////
/obj/effect/shadekin_ability/create_shade
ability_name = "Create Shade"
desc = "Create a field of darkness that follows you."
icon_state = "tech_dispelold"
cost = 25
shift_mode = NOT_WHILE_SHIFTED
ab_sound = 'sound/effects/bamf.ogg'
/obj/effect/shadekin_ability/create_shade/do_ability()
if(!..())
return
my_kin.add_modifier(/datum/modifier/shadekin/create_shade,20 SECONDS)
/datum/modifier/shadekin/create_shade
name = "Shadekin Shadegen"
desc = "Darkness envelops you."
mob_overlay_state = ""
on_created_text = "<span class='notice'>You drag part of The Dark into realspace, enveloping yourself.</span>"
on_expired_text = "<span class='warning'>You lose your grasp on The Dark and realspace reasserts itself.</span>"
stacks = MODIFIER_STACK_EXTEND
var/mob/living/simple_mob/shadekin/my_kin
/datum/modifier/shadekin/create_shade/tick()
if(my_kin.ability_flags & AB_PHASE_SHIFTED)
expire()
/datum/modifier/shadekin/create_shade/on_applied()
my_kin = holder
holder.glow_toggle = TRUE
holder.glow_range = 8
holder.glow_intensity = -10
holder.glow_color = "#FFFFFF"
holder.set_light(8, -10, "#FFFFFF")
/datum/modifier/shadekin/create_shade/on_expire()
holder.glow_toggle = initial(holder.glow_toggle)
holder.glow_range = initial(holder.glow_range)
holder.glow_intensity = initial(holder.glow_intensity)
holder.glow_color = initial(holder.glow_color)
holder.set_light(0)
my_kin = null
/*
/////////////////////////////////////////////////////////////////
/obj/effect/shadekin_ability/energy_feast
ability_name = "Devour Energy"
desc = "Devour the energy from another creature (potentially fatal)."
icon_state = "gen_eat"
cost = 25
shift_mode = NOT_WHILE_SHIFTED
/obj/effect/shadekin_ability/energy_feast/do_ability()
if(!..())
return
*/

View File

@@ -0,0 +1,133 @@
// Phase shifting procs (and related procs)
/mob/living/simple_mob/shadekin/proc/phase_shift()
var/turf/T = get_turf(src)
if(!T.CanPass(null,T) || loc != T)
to_chat(src,"<span class='warning'>You can't use that here!</span>")
return FALSE
forceMove(T)
var/original_canmove = canmove
SetStunned(0)
SetWeakened(0)
if(buckled)
buckled.unbuckle_mob()
if(pulledby)
pulledby.stop_pulling()
stop_pulling()
canmove = FALSE
//Shifting in
if(ability_flags & AB_PHASE_SHIFTED)
ability_flags &= ~AB_PHASE_SHIFTED
name = real_name
for(var/belly in vore_organs)
var/obj/belly/B = belly
B.escapable = initial(B.escapable)
overlays.Cut()
alpha = initial(alpha)
invisibility = initial(invisibility)
see_invisible = initial(see_invisible)
incorporeal_move = initial(incorporeal_move)
density = initial(density)
force_max_speed = initial(force_max_speed)
//Cosmetics mostly
flick("tp_in",src)
custom_emote(1,"phases in!")
sleep(5) //The duration of the TP animation
canmove = original_canmove
//Potential phase-in vore
if(can_be_drop_pred) //Toggleable in vore panel
var/list/potentials = living_mobs(0)
if(potentials.len)
var/mob/living/target = pick(potentials)
if(istype(target) && vore_selected)
target.forceMove(vore_selected)
to_chat(target,"<span class='warning'>\The [src] phases in around you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!</span>")
// Do this after the potential vore, so we get the belly
update_icon()
//Affect nearby lights
var/destroy_lights = 0
if(eye_state == RED_EYES)
destroy_lights = 80
if(eye_state == PURPLE_EYES)
destroy_lights = 25
for(var/obj/machinery/light/L in machines)
if(L.z != z || get_dist(src,L) > 10)
continue
if(prob(destroy_lights))
spawn(rand(5,25))
L.broken()
else
L.flicker(10)
//Shifting out
else
ability_flags |= AB_PHASE_SHIFTED
custom_emote(1,"phases out!")
real_name = name
name = "Something"
for(var/belly in vore_organs)
var/obj/belly/B = belly
B.escapable = FALSE
overlays.Cut()
flick("tp_out",src)
sleep(5)
invisibility = INVISIBILITY_LEVEL_TWO
see_invisible = INVISIBILITY_LEVEL_TWO
update_icon()
alpha = 127
canmove = original_canmove
incorporeal_move = TRUE
density = FALSE
force_max_speed = TRUE
/mob/living/simple_mob/shadekin/UnarmedAttack()
if(ability_flags & AB_PHASE_SHIFTED)
return FALSE //Nope.
. = ..()
/mob/living/simple_mob/shadekin/can_fall()
if(ability_flags & AB_PHASE_SHIFTED)
return FALSE //Nope!
return ..()
/mob/living/simple_mob/shadekin/zMove(direction)
if(ability_flags & AB_PHASE_SHIFTED)
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
if(destination)
forceMove(destination)
return TRUE
return ..()
// Healing others
/mob/living/simple_mob/shadekin/proc/mend_other()
//I hate to crunch a view() but I only want ones I can see
var/list/viewed = oview(1)
var/list/targets = list()
for(var/mob/living/L in viewed)
targets += L
if(!targets.len)
to_chat(src,"<span class='warning'>Nobody nearby to mend!</span>")
return FALSE
var/mob/living/target = input(src,"Pick someone to mend:","Mend Other") as null|anything in targets
if(!target)
return FALSE
target.add_modifier(/datum/modifier/shadekin/heal_boop,1 MINUTE)
visible_message("<span class='notice'>\The [src] gently places a hand on \the [target]...</span>")
face_atom(target)
return TRUE

View File

@@ -0,0 +1,447 @@
/mob/living/simple_mob/shadekin //Spawning the prototype spawns a random one, see initialize()
name = "shadekin"
desc = "Some sort of fluffer. Big ears, long tail."
icon = 'icons/mob/vore_shadekin.dmi'
icon_state = "map_example"
icon_living = "map_example"
faction = "shadekin"
ui_icons = 'icons/mob/shadekin_hud.dmi'
intelligence_level = SA_HUMANOID
maxHealth = 200
health = 200
move_to_delay = 2
speed = -1
see_in_dark = 10 //SHADEkin
has_hands = TRUE //Pawbs
seedarkness = FALSE //SHAAAADEkin
attack_sound = 'sound/weapons/bladeslice.ogg'
has_langs = list(LANGUAGE_GALCOM,LANGUAGE_SHADEKIN)
investigates = TRUE
reacts = TRUE
run_at_them = FALSE
cooperative = FALSE
melee_damage_lower = 10
melee_damage_upper = 20
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
minbodytemp = 0
maxbodytemp = 900
speak_chance = 2
speak = list("Marrr.", "Marrr?", "Marrr!")
emote_hear = list("chrrrrrs", "wurbles", "wrrrrbles")
emote_see = list("tailtwitches", "earflicks")
say_maybe_target = list("...mar?")
say_got_target = list("MAR!!!")
response_help = "pets the"
response_disarm = "bops the"
response_harm = "hits the"
attacktext = list("mauled","slashed","clawed")
friendly = list("boops", "pawbs", "mars softly at", "sniffs on")
reactions = list("Mar?" = "Marrr!", "Mar!" = "Marrr???", "Mar." = "Marrr.")
vore_active = TRUE
vore_pounce_chance = 10
vore_icons = SA_ICON_LIVING
swallowTime = 2 SECONDS
vore_escape_chance = 25
//None, they stay as their defaults.
vore_digest_chance = 0
vore_absorb_chance = 0
vore_bump_chance = 0 //They follow people, this would be DENGEROUS
var/eye_state = RED_EYES //Eye color/energy gain/loss mode
var/eye_icon_state = null //Default, changed in init
var/eye_desc //Eye color description added to examine
var/mob/living/carbon/human/henlo_human //Human we're stalking currently
//Behavior
var/stalker = TRUE //Do we creep up on humans
var/shy_approach = FALSE //Do we creep up slowly on humans to boop them
//Icon handling
var/image/tailimage //Cached tail image
//Darknesssss
var/energy = 100 //For abilities
var/energy_adminbuse = FALSE //For adminbuse infinite energy
var/dark_gains = 0 //Last tick's change in energy
var/ability_flags = 0 //Flags for active abilities
var/obj/screen/darkhud //Holder to update this icon
var/obj/screen/energyhud //Holder to update this icon
var/list/shadekin_abilities
/mob/living/simple_mob/shadekin/initialize()
//You spawned the prototype, and want a totally random one.
if(type == /mob/living/simple_mob/shadekin)
//I'm told by VerySoft these are the liklihood values
var/list/sk_types = list(
/mob/living/simple_mob/shadekin/red = 20, //Actively seek people out to nom, so fairly common to see (relatively speaking),
/mob/living/simple_mob/shadekin/blue = 15, //Explorers that like to interact with people, so still fairly common,
/mob/living/simple_mob/shadekin/purple = 15, //Also explorers that may or may not homf people,
/mob/living/simple_mob/shadekin/yellow = 1 //Very rare, usually never leaves their home
)
var/new_type = pickweight(sk_types)
new new_type(loc)
initialized = TRUE
return INITIALIZE_HINT_QDEL
if(icon_state == "map_example")
icon_state = pick("white","dark","brown")
icon_living = icon_state
switch(eye_state)
if(BLUE_EYES)
eye_icon_state = "e_blue"
if(RED_EYES)
eye_icon_state = "e_red"
if(PURPLE_EYES)
eye_icon_state = "e_purple"
if(YELLOW_EYES)
eye_icon_state = "e_yellow"
if(GREEN_EYES)
eye_icon_state = "e_green"
if(ORANGE_EYES)
eye_icon_state = "e_orange"
else
eye_icon_state = "e_red"
tailimage = image('icons/mob/vore_shadekin64.dmi',null,icon_state)
tailimage.pixel_x = -16
if(eye_desc)
desc += " This one has [eye_desc]!"
var/list/ability_types = subtypesof(/obj/effect/shadekin_ability)
shadekin_abilities = list()
for(var/type in ability_types)
shadekin_abilities += new type(src)
update_icon()
return ..()
/mob/living/simple_mob/shadekin/Destroy()
QDEL_NULL_LIST(shadekin_abilities)
. = ..()
/mob/living/simple_mob/shadekin/init_vore()
if(LAZYLEN(vore_organs))
return
var/obj/belly/B = new /obj/belly(src)
vore_selected = B
B.immutable = 1
B.name = vore_stomach_name ? vore_stomach_name : "stomach"
B.desc = vore_stomach_flavor ? vore_stomach_flavor : "Your surroundings are warm, soft, and slimy. Makes sense, considering you're inside \the [name]."
B.digest_mode = vore_default_mode
B.escapable = vore_escape_chance > 0
B.escapechance = vore_escape_chance
B.digestchance = vore_digest_chance
B.absorbchance = vore_absorb_chance
B.human_prey_swallow_time = swallowTime
B.nonhuman_prey_swallow_time = swallowTime
B.vore_verb = "swallow"
// TODO - Customizable per mob
B.emote_lists[DM_HOLD] = list(
"The walls gently squeeze against you. The wet sounds of shifting flesh against your form fill the air.",
"The hot, humid air rushes around you for a moment as the creature urps. The walls clench in around you for a moment, before relaxing again.",
"Your body is soaked in the fluids that cling to the churning walls. They squeeze across your form gently, conforming to your shape.",
"You can feel the world around you shift and sway as the creature moves! The flesh is stretchy, doughy. You can sink into it a little ways before it bounces back, curling you into a small shape."
)
B.emote_lists[DM_DIGEST] = list(
"The walls slop thick slime across your body! It tingles briefly before the sting and ache sets in!",
"The sound of your body slipping and sliding against the powerfully churning stomach fills the air!",
"The grip of that stomach is harsh. Eagerly mushing and rubbing that slime into your body in attempts to break you down!",
"The intense churning and grinding jostles your around within the thick slime as you're slowly broken down!"
)
B.emote_lists[DM_ABSORB] = list(
"The walls cling to you awfully close... It's almost like you're sinking into them.",
"You can feel the walls press in tightly against you, clinging to you posessively!",
"It almost feels like you're sinking into the soft, doughy flesh!",
"You can feel the walls press in around you. Almost molten, so squishy!!"
)
B.emote_lists[DM_DRAIN] = list(
"The walls churn down on you heavily!! It's hard to move!",
"You can feel yourself getting weaker with every moment! The doughy walls sap your strength!",
"You're practically smothered in the oppressive heat of the creature's stomach!",
"It's hot, wet and tight!"
)
B.emote_lists[DM_HEAL] = list(
"The walls pulse against you almost rhythmically. It feels nice, almost like a massage.",
"You're gently squeezed in pleasant warmth, softly churned.",
"The doughy feel of the heavy flesh clinging to you makes you feel a little stronger with every passing moment.",
"The flesh caresses across your body gently as you're held."
)
B.digest_messages_prey = list(
"Your body is steadily softened more and more over time! Eventually you pass out. The creature's stomach rumbles powerfully as you are reduced to paste, processed for energy!",
"The creature's slimy gut lets out a heavy groan as you're slowly melted away. Gushing deeper through the creature.",
"The stinging and aching gives way to numbness as you're slowly smothered out. Your body is steadily reduced to nutrients and energy for the creature to continue on its way.",
"The chaos of being digested fades as you're snuffed out by a harsh clench! You're steadily broken down into a thick paste, processed and absorbed by the predator!"
)
/mob/living/simple_mob/shadekin/Life()
. = ..()
if(ability_flags & AB_PHASE_SHIFTED)
density = FALSE
//Convert spare nutrition into energy at a certain ratio
if(. && nutrition > initial(nutrition) && energy < 100)
nutrition = max(0, nutrition-5)
energy = min(100,energy+1)
/mob/living/simple_mob/shadekin/update_icon()
. = ..()
cut_overlay(tailimage)
tailimage.icon_state = icon_state
add_overlay(tailimage)
add_overlay(eye_icon_state)
/mob/living/simple_mob/shadekin/Stat()
. = ..()
if(statpanel("Shadekin"))
abilities_stat()
/mob/living/simple_mob/shadekin/proc/abilities_stat()
for(var/A in shadekin_abilities)
var/obj/effect/shadekin_ability/ability = A
stat("[ability.ability_name]",ability.atom_button_text())
//They phase back to the dark when killed
/mob/living/simple_mob/shadekin/death(gibbed, deathmessage = "phases to somewhere far away!")
overlays = list()
icon_state = ""
flick("tp_out",src)
spawn(1 SECOND)
qdel(src) //Back from whence you came!
. = ..(FALSE, deathmessage)
//Blue-eyes want to nom people to heal them
/mob/living/simple_mob/shadekin/Found(var/atom/A)
if(specific_targets && isliving(A)) //Healing!
var/mob/living/L = A
var/health_percent = (L.health/L.maxHealth)*100
if(health_percent <= 50 && will_eat(A))
return A
. = ..()
//They reach nutritional equilibrium (important for blue-eyes healbelly)
/mob/living/simple_mob/shadekin/Life()
if((. = ..()))
handle_shade()
/mob/living/simple_mob/shadekin/proc/handle_shade()
//Shifted kin don't gain/lose energy (and save time if we're at the cap)
var/darkness = 1
var/turf/T = get_turf(src)
if(!T)
dark_gains = 0
return
var/brightness = T.get_lumcount() //Brightness in 0.0 to 1.0
darkness = 1-brightness //Invert
if(ability_flags & AB_PHASE_SHIFTED)
dark_gains = 0
else
//Heal (very) slowly in good darkness
if(darkness >= 0.75)
adjustFireLoss(-0.05)
adjustBruteLoss(-0.05)
adjustToxLoss(-0.05)
switch(eye_state)
//Blue has constant, steady (slow) regen and ignores darkness.
if(BLUE_EYES)
dark_gains = 0.5
//Red has extremely tiny energy buildup in dark, none in light, and hunts for energy.
if(RED_EYES)
if(darkness >= 0.75)
dark_gains = 0.25
//Purple eyes have moderate gains in darkness and loss in light.
if(PURPLE_EYES)
dark_gains = round((darkness - 0.5) * 2, 0.1)
//Yellow has extreme gains in darkness and loss in light.
if(YELLOW_EYES)
dark_gains = round((darkness - 0.5) * 4, 0.1)
//Similar to blues, but passive is less, and affected by dark
if(GREEN_EYES)
dark_gains = 0.25
dark_gains += round((darkness - 0.5), 0.1)
//More able to get energy out of the dark, worse attack gains tho
if(ORANGE_EYES)
if(darkness >= 0.65)
dark_gains = 0.30
energy = max(0,min(initial(energy),energy + dark_gains))
if(energy_adminbuse)
energy = 100
//Update turf darkness hud
if(darkhud)
switch(darkness)
if(0.80 to 1.00)
darkhud.icon_state = "dark2"
if(0.60 to 0.80)
darkhud.icon_state = "dark1"
if(0.40 to 0.60)
darkhud.icon_state = "dark"
if(0.20 to 0.40)
darkhud.icon_state = "dark-1"
if(0.00 to 0.20)
darkhud.icon_state = "dark-2"
//Update energy storage hud
if(energyhud)
switch(energy)
if(80 to INFINITY)
energyhud.icon_state = "energy0"
if(60 to 80)
energyhud.icon_state = "energy1"
if(40 to 60)
energyhud.icon_state = "energy2"
if(20 to 40)
energyhud.icon_state = "energy3"
if(0 to 20)
energyhud.icon_state = "energy4"
//Friendly ones wander towards people, maybe shy-ly if they are set to shy
/mob/living/simple_mob/shadekin/handle_wander_movement()
if(isturf(src.loc) && !resting && !buckled && canmove)
lifes_since_move++
if(lifes_since_move >= turns_per_move)
if(!(stop_when_pulled && pulledby))
var/moving_to
if(stalker)
//Sniff sniff.
var/list/humans = human_mobs(world.view)
//Can we see the last person we were following?
if(henlo_human && !(henlo_human in humans))
henlo_human = null
//Can we find a new person to follow?
if(!henlo_human)
while(!henlo_human && humans.len)
henlo_human = pick(humans)
if(!isturf(henlo_human.loc))
humans -= henlo_human
henlo_human = null
//Boopable hunam?
if(henlo_human)
moving_to = get_dir(src,henlo_human)
if((get_dist(src,henlo_human) <= 1))
dir = moving_to
if(prob(speak_chance))
visible_message("<span class='notice'>\The [src] [pick(friendly)] \the [henlo_human].</span>")
shy_approach = FALSE //ACCLIMATED
lifes_since_move = 0
return //No need to move
if(shy_approach)
var/them_to_us = turn(moving_to,180)
if(abs(dir2angle(henlo_human.dir) - dir2angle(them_to_us)) <= 90)
dir = them_to_us
return //AAA!
dir = moving_to
//Random walk
if(!moving_to)
moving_to = pick(cardinal)
dir = moving_to
var/turf/T = get_step(src,moving_to)
if(avoid_turf(T))
return
Move(T)
lifes_since_move = 0
/mob/living/simple_mob/shadekin/speech_bubble_appearance()
return "ghost"
/mob/living/simple_mob/shadekin/DoPunch(var/atom/A)
. = ..(A)
if(isliving(A)) //We punched something!
var/mob/living/L = A
if(L.stat != DEAD)
var/gains = 0
switch(eye_state)
if(RED_EYES)
gains = 8
if(BLUE_EYES)
gains = 1
if(PURPLE_EYES)
gains = 4
if(YELLOW_EYES)
gains = 3
if(GREEN_EYES)
gains = 1
if(ORANGE_EYES)
gains = 5
energy += gains
//Special hud elements for darkness and energy gains
/mob/living/simple_mob/shadekin/extra_huds(var/datum/hud/hud,var/icon/ui_style,var/list/hud_elements)
//Darkness hud
darkhud = new /obj/screen()
darkhud.icon = ui_style
darkhud.icon_state = "dark"
darkhud.name = "darkness"
darkhud.screen_loc = "CENTER-2:16,SOUTH:5" //Left of the left hand
darkhud.alpha = 150
hud_elements |= darkhud
//Energy hud
energyhud = new /obj/screen()
energyhud.icon = ui_style
energyhud.icon_state = "energy0"
energyhud.name = "energy"
energyhud.screen_loc = "CENTER+1:16,SOUTH:5" //Right of the right hand
energyhud.alpha = 150
hud_elements |= energyhud
// When someone clicks us with an empty hand
/mob/living/simple_mob/shadekin/attack_hand(mob/living/carbon/human/M as mob)
. = ..()
if(M.a_intent == I_HELP)
shy_approach = FALSE //ACCLIMATED
/datum/language/shadekin
name = "Shadekin Empathy"
desc = "Shadekin seem to always know what the others are thinking. This is probably why."
colour = "changeling"
speech_verb = "mars"
ask_verb = "mars"
exclaim_verb = "mars"
key = "m"
machine_understands = 0
flags = WHITELISTED | HIVEMIND

View File

@@ -0,0 +1,256 @@
/////////////////////////////////////////////////////////////////
/mob/living/simple_mob/shadekin/red
name = "red-eyed shadekin"
eye_state = RED_EYES
hostile = TRUE
animal = TRUE
stop_when_pulled = FALSE
destroy_surroundings = TRUE
armor = list(
"melee" = 30,
"bullet" = 20,
"laser" = 20,
"energy" = 50,
"bomb" = 10,
"bio" = 100,
"rad" = 100)
eye_desc = "red eyes"
vore_stomach_flavor = "You slip past pointy triangle teeth and down the slick, \
slippery gullet of the creature. It's warm, and the air is thick. You can hear \
its body squelch and shift around you as you settle into its stomach! Thick digestive \
enzymes cling to you within that dark space, tingling and stinging immediately! The weight of \
the doughy walls press in around you instantly, churning you up as you begin to digest!"
player_msg = "You hunt for energy to fuel yourself, not minding in the least \
if you strip it off unsuspecting prey. You're stronger than other shadekin, faster, and more capable in \
a brawl, but you barely generate any of your own energy. You can stand in a dark spot to gather scraps \
of energy in a pinch, but otherwise need to take it, by force if necessary."
/mob/living/simple_mob/shadekin/red/white
icon_state = "white"
/mob/living/simple_mob/shadekin/red/dark
icon_state = "dark"
/mob/living/simple_mob/shadekin/red/brown
icon_state = "brown"
/////////////////////////////////////////////////////////////////
/mob/living/simple_mob/shadekin/blue
name = "blue-eyed shadekin"
eye_state = BLUE_EYES
health = 100
hostile = FALSE
animal = FALSE
stop_when_pulled = TRUE
specific_targets = TRUE //For finding injured people
destroy_surroundings = FALSE
vore_default_mode = DM_HEAL
vore_escape_chance = 75
vore_standing_too = 1
vore_pounce_chance = 100
swallowTime = 4 SECONDS //A little longer to compensate for the above
vore_ignores_undigestable = FALSE
attacktext = list("shoved")
armor = list(
"melee" = 5,
"bullet" = 5,
"laser" = 5,
"energy" = 5,
"bomb" = 0,
"bio" = 100,
"rad" = 100)
eye_desc = "blue eyes"
shy_approach = TRUE
stalker = TRUE
vore_stomach_flavor = "You slip past pointy triangle teeth and down the slick, \
slippery gullet of the creature. It's warm, and the air is thick. You can hear its body \
squelch and shift around you as you settle into its stomach! It's oddly calm, and very dark. \
The doughy flesh rolls across your form in gentle waves. The aches and pains across your form slowly begin to \
diminish, your body is healing much faster than normal! You're also soon soaked in harmless slime."
player_msg = "You've chosen to generate your own energy rather than taking \
it from others. Most of the time, anyway. You don't have a need to steal energy from others, and gather it up \
without doing so, albeit slowly. Dark and light are irrelevant to you, they are just different places to explore and \
discover new things and new people."
/mob/living/simple_mob/shadekin/blue/white
icon_state = "white"
/mob/living/simple_mob/shadekin/blue/dark
icon_state = "dark"
/mob/living/simple_mob/shadekin/blue/brown
icon_state = "brown"
/////////////////////////////////////////////////////////////////
/mob/living/simple_mob/shadekin/purple
name = "purple-eyed shadekin"
eye_state = PURPLE_EYES
health = 150
hostile = FALSE
animal = TRUE
stop_when_pulled = FALSE
destroy_surroundings = TRUE
vore_default_mode = DM_HOLD
vore_digest_chance = 25
vore_absorb_chance = 25
armor = list(
"melee" = 15,
"bullet" = 15,
"laser" = 15,
"energy" = 15,
"bomb" = 15,
"bio" = 100,
"rad" = 100)
eye_desc = "purple eyes"
shy_approach = TRUE
stalker = TRUE
vore_stomach_flavor = "You slip past pointy triangle teeth and down the slick, slippery gullet of the creature. \
It's warm, and the air is thick. You can hear its body squelch and shift around you as you settle into its stomach! \
It's relatively calm inside the dark organ. Wet and almost molten for how gooey your surroundings feel. \
You can feel the doughy walls cling to you posessively... It's almost like you could sink into them. \
There is also an ominous gurgling from somewhere nearby..."
player_msg = "You're familiar with generating your own energy, but occasionally \
steal it from others when it suits you. You generate energy at a moderate pace in dark areas, and staying in well-lit \
areas is taxing on your energy. You can harvest energy from others in a fight, but since you don't need to, you may \
just choose to simply not fight."
/mob/living/simple_mob/shadekin/purple/white
icon_state = "white"
/mob/living/simple_mob/shadekin/purple/dark
icon_state = "dark"
/mob/living/simple_mob/shadekin/purple/brown
icon_state = "brown"
/////////////////////////////////////////////////////////////////
/mob/living/simple_mob/shadekin/yellow
name = "yellow-eyed shadekin"
eye_state = YELLOW_EYES
health = 100
hostile = FALSE
animal = TRUE
stop_when_pulled = FALSE
destroy_surroundings = TRUE
vore_default_mode = DM_DRAIN
vore_digest_chance = 5
vore_ignores_undigestable = FALSE
armor = list(
"melee" = 5,
"bullet" = 5,
"laser" = 5,
"energy" = 5,
"bomb" = 0,
"bio" = 100,
"rad" = 100)
eye_desc = "yellow eyes"
stalker = FALSE
vore_stomach_flavor = "You slip past pointy triangle teeth and down the slick, slippery gullet \
of the creature. It's warm, and the air is thick. You can hear its body squelch and shift around you \
as you settle into its stomach! The doughy walls within cling to you heavily, churning down on you, wearing \
you out!! There doesn't appear to be any actual danger here, harmless slime clings to you, but it's getting \
harder and harder to move as those walls press in on you insistently!"
player_msg = "Your kind rarely ventures into realspace. Being in any well-lit \
area is very taxing on you, but you gain energy extremely fast in any very dark area. You're weaker than other \
shadekin, but your fast energy generation in the dark allows you to phase shift more often."
/mob/living/simple_mob/shadekin/yellow/white
icon_state = "white"
/mob/living/simple_mob/shadekin/yellow/dark
icon_state = "dark"
/mob/living/simple_mob/shadekin/yellow/brown
icon_state = "brown"
/////////////////////////////////////////////////////////////////
/mob/living/simple_mob/shadekin/green
name = "green-eyed shadekin"
eye_state = GREEN_EYES
health = 125
hostile = FALSE
animal = TRUE
stop_when_pulled = FALSE
destroy_surroundings = TRUE
vore_default_mode = DM_DRAIN
vore_digest_chance = 0
vore_ignores_undigestable = FALSE
armor = list(
"melee" = 5,
"bullet" = 5,
"laser" = 5,
"energy" = 5,
"bomb" = 0,
"bio" = 100,
"rad" = 100)
eye_desc = "green eyes"
stalker = TRUE
vore_stomach_flavor = "You slip past pointy triangle teeth and down the slick, slippery gullet \
of the creature. It's warm, and the air is thick. You can hear its body squelch and shift around you \
as you settle into its stomach! The doughy walls within cling to you heavily, churning down on you, wearing \
you out!! There doesn't appear to be any actual danger here, harmless slime clings to you, but it's getting \
harder and harder to move as those walls press in on you insistently!"
player_msg = "Your kind rarely ventures into realspace. Being in any well-lit area is very taxing on you, but you \
have more experience than your yellow-eyed cousins. You gain energy decently fast in any very dark area. You're weaker than other \
shadekin, but your slight energy generation constnatly, and especially in the dark allows for a good mix of uses."
/mob/living/simple_mob/shadekin/green/white
icon_state = "white"
/mob/living/simple_mob/shadekin/green/dark
icon_state = "dark"
/mob/living/simple_mob/shadekin/green/brown
icon_state = "brown"
/////////////////////////////////////////////////////////////////
/mob/living/simple_mob/shadekin/orange
name = "orange-eyed shadekin"
eye_state = ORANGE_EYES
health = 175
hostile = TRUE
animal = TRUE
stop_when_pulled = FALSE
destroy_surroundings = TRUE
armor = list(
"melee" = 20,
"bullet" = 15,
"laser" = 15,
"energy" = 25,
"bomb" = 10,
"bio" = 100,
"rad" = 100)
eye_desc = "orange eyes"
vore_stomach_flavor = "You slip past pointy triangle teeth and down the slick, \
slippery gullet of the creature. It's warm, and the air is thick. You can hear \
its body squelch and shift around you as you settle into its stomach! Thick digestive \
enzymes cling to you within that dark space, tingling and stinging immediately! The weight of \
the doughy walls press in around you instantly, churning you up as you begin to digest!"
player_msg = "You usually hunt for energy to fuel yourself, though not as often as your red-eyed cousins. \
You're stronger than most shadekin, faster, and more capable in a brawl, but you don't generate much of your own energy. \
You can stand in a dark spot to gather some energy, but otherwise need to take it, by force if necessary."
/mob/living/simple_mob/shadekin/orange/white
icon_state = "white"
/mob/living/simple_mob/shadekin/orange/dark
icon_state = "dark"
/mob/living/simple_mob/shadekin/orange/brown
icon_state = "brown"
/////////////////////////////////////////////////////////////////
//Fluffy specific fluffer
/mob/living/simple_mob/shadekin/blue/rivyr
name = "Rivyr"
desc = "She appears to be a fluffer of some sort. Deep blue eyes and curious attitude."
icon_state = "rivyr"
eye_desc = ""
vore_stomach_flavor = "Blue flesh gleams in the fading light as you slip down the little mar's gullet! \
Gooey flesh and heat surrounds your form as you're tucked away into the darkness of her stomach! Thick slimes cling \
to you, but they seem to be harmless. The organ gently churns around you, clinging to your shape and forcing \
you to curl up a bit. You can feel her rub at you some through the layers of flesh and fluff, while aches \
and pains begin to fade away across your body."
player_msg = "Mar? Mar mar. Mar mar mar. Mar. Mar mar? Mar! Mar. Marrrr."

View File

@@ -0,0 +1,11 @@
#undef NOT_WHILE_SHIFTED
#undef ONLY_WHILE_SHIFTED
#undef SHIFTED_OR_NOT
#undef BLUE_EYES
#undef RED_EYES
#undef PURPLE_EYES
#undef YELLOW_EYES
#undef AB_PHASE_SHIFTED
#undef AB_SHADE_REGEN

View File

@@ -0,0 +1,108 @@
/*
A work in progress, lore will go here later.
List of things solar grubs should be able to do:
2. have three stages of growth depending on time. (Or energy drained altho that seems like a hard one to code)
3. be capable of eating people that get knocked out. (also be able to shock attackers that dont wear insulated gloves.)
5. ((potentially use digested people to reproduce))
6. add glow?
*/
#define SINK_POWER 1
/mob/living/simple_mob/animal/space/solargrub
name = "juvenile solargrub"
desc = "A young sparkling solargrub"
icon = 'icons/mob/vore.dmi' //all of these are placeholders
icon_state = "solargrub"
icon_living = "solargrub"
icon_dead = "solargrub-dead"
faction = "grubs"
maxHealth = 50 //grubs can take a lot of harm
health = 50
melee_damage_lower = 1
melee_damage_upper = 5
speed = 2
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/grubmeat
response_help = "pokes"
response_disarm = "pushes"
response_harm = "roughly pushes"
var/poison_per_bite = 5 //grubs cause a shock when they bite someone
var/poison_type = "shockchem"
var/poison_chance = 50
var/datum/powernet/PN // Our powernet
var/obj/structure/cable/attached // the attached cable
var/emp_chance = 20 // Beware synths
/datum/say_list/solargrub
emote_see = list("squelches", "squishes")
/* //Commented out pending reworks - 2/2/19
/mob/living/simple_mob/animal/solargrub/PunchTarget()
if(target_mob&& prob(emp_chance))
target_mob.emp_act(4) //The weakest strength of EMP
visible_message("<span class='danger'>The grub releases a powerful shock!</span>")
..()
/mob/living/simple_mob/animal/solargrub/Life()
. = ..()
if(!. || ai_inactive) return
if(stance == STANCE_IDLE)
//first, check for potential cables nearby to powersink
var/turf/S = loc
attached = locate() in S
if(attached)
if(prob(2))
src.visible_message("<span class='notice'>\The [src] begins to sink power from the net.</span>")
if(prob(5))
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(5, 0, get_turf(src))
sparks.start()
anchored = 1
PN = attached.powernet
PN.draw_power(100000) // previous value 150000
var/apc_drain_rate = 750 //Going to see if grubs are better as a minimal bother. previous value : 4000
for(var/obj/machinery/power/terminal/T in PN.nodes)
if(istype(T.master, /obj/machinery/power/apc))
var/obj/machinery/power/apc/A = T.master
if(A.operating && A.cell)
var/cur_charge = A.cell.charge / CELLRATE
var/drain_val = min(apc_drain_rate, cur_charge)
A.cell.use(drain_val * CELLRATE)
else if(!attached && anchored)
anchored = 0
PN = null
*/
/mob/living/simple_mob/animal/solargrub //active noms
vore_bump_chance = 50
vore_bump_emote = "applies minimal effort to try and slurp up"
vore_active = 1
vore_capacity = 1
vore_pounce_chance = 0 //grubs only eat incapacitated targets
vore_default_mode = DM_DIGEST
/*
/mob/living/simple_mob/animal/solargrub/PunchTarget()
. = ..()
if(isliving(.))
var/mob/living/L = .
if(L.reagents)
if(prob(poison_chance))
L << "<span class='warning'>You feel a shock rushing through your veins.</span>"
L.reagents.add_reagent(poison_type, poison_per_bite) */
/mob/living/simple_mob/animal/solargrub/death()
src.anchored = 0
set_light(0)
..()
/mob/living/simple_mob/animal/solargrub/handle_light()
. = ..()
if(. == 0 && !is_dead())
set_light(2.5, 1, COLOR_YELLOW)
return 1

View File

@@ -0,0 +1,256 @@
var/global/list/grub_machine_overlays = list()
/mob/living/simple_mob/solargrub_larva
name = "solargrub larva"
desc = "A tiny wormy thing that can grow to massive sizes under the right conditions."
icon = 'icons/mob/vore.dmi'
icon_state = "grublarva"
icon_living = "grublarva"
icon_dead = "grublarva-dead"
health = 5
maxHealth = 5
meat_amount = 2
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/grubmeat
faction = "grubs"
response_help = "pats"
response_disarm = "nudges"
response_harm = "stomps on"
mob_size = MOB_MINISCULE
pass_flags = PASSTABLE
can_pull_size = ITEMSIZE_TINY
can_pull_mobs = MOB_PULL_NONE
density = 0
stop_when_pulled = 0
var/static/list/ignored_machine_types = list(
/obj/machinery/atmospherics/unary/vent_pump,
/obj/machinery/atmospherics/unary/vent_scrubber,
/obj/machinery/door/firedoor
)
var/obj/machinery/atmospherics/unary/vent_pump/target_vent
var/datum/effect/effect/system/spark_spread/sparks
var/image/machine_effect
var/obj/machinery/abstract_grub_machine/powermachine
var/power_drained = 0
var/forced_out = 0
/mob/living/simple_mob/solargrub_larva/New()
..()
powermachine = new(src)
sparks = new(src)
sparks.set_up()
sparks.attach(src)
verbs += /mob/living/proc/ventcrawl
/mob/living/simple_mob/solargrub_larva/death()
powermachine.draining = 0
set_light(0)
return ..()
/mob/living/simple_mob/solargrub_larva/Destroy()
QDEL_NULL(powermachine)
QDEL_NULL(sparks)
QDEL_NULL(machine_effect)
target_vent = null
return ..()
/mob/living/simple_mob/solargrub_larva/Life()
. = ..()
if(machine_effect && !istype(loc, /obj/machinery))
QDEL_NULL(machine_effect)
if(!. || ai_inactive)
return
if(power_drained >= 7 MEGAWATTS && prob(5))
expand_grub()
return
if(istype(loc, /obj/machinery))
if(machine_effect && air_master.current_cycle%30)
for(var/mob/M in player_list)
M << machine_effect
if(prob(10))
sparks.start()
return
if(stance == STANCE_IDLE)
if(forced_out)
forced_out = Clamp(0, forced_out--, forced_out)
return
if(target_vent)
if(Adjacent(target_vent))
spawn()
do_ventcrawl(target_vent)
target_vent = null
else
target_vent = null
stop_automated_movement = 0
walk(src, 0)
return
if(prob(20))
var/list/possible_machines = list()
for(var/obj/machinery/M in orange(1,src))
if(!Adjacent(M))
continue
if(istype(M, /obj/machinery/power/apc) || istype(M, /obj/machinery/power/smes)) //APCs and SMES units don't actually use power, but it's too thematic to ignore them
possible_machines += M
continue
if(is_type_in_list(M, ignored_machine_types))
continue
if(!M.idle_power_usage && !M.active_power_usage) //If it can't use power at all, ignore it
continue
possible_machines += M
if(possible_machines.len)
enter_machine(pick(possible_machines))
return
if(prob(10))
var/list/vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/vent in view(7,src))
if(vent.welded)
continue
vents += vent
if(vents.len)
var/picked = pick(vents)
target_vent = picked
WanderTowards(get_turf(picked))
return
/mob/living/simple_mob/solargrub_larva/proc/enter_machine(var/obj/machinery/M)
if(!istype(M))
return
forceMove(M)
powermachine.draining = 2
visible_message("<span class='warning'>\The [src] finds an opening and crawls inside \the [M].</span>")
if(!(M.type in grub_machine_overlays))
generate_machine_effect(M)
machine_effect = image(grub_machine_overlays[M.type], M) //Can't do this the reasonable way with an overlay,
for(var/mob/L in player_list) //because nearly every machine updates its icon by removing all overlays first
L << machine_effect
/mob/living/simple_mob/solargrub_larva/proc/generate_machine_effect(var/obj/machinery/M)
var/icon/I = new /icon(M.icon, M.icon_state)
I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD)
I.Blend(new /icon('icons/effects/alert.dmi', "_red"),ICON_MULTIPLY)
grub_machine_overlays[M.type] = I
/mob/living/simple_mob/solargrub_larva/proc/eject_from_machine(var/obj/machinery/M)
if(!M)
if(istype(loc, /obj/machinery))
M = loc
else
return
forceMove(get_turf(M))
sparks.start()
if(machine_effect)
QDEL_NULL(machine_effect)
forced_out += rand(5,15)
powermachine.draining = 1
/mob/living/simple_mob/solargrub_larva/proc/do_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent)
if(!vent)
return
var/obj/machinery/atmospherics/unary/vent_pump/end_vent = get_safe_ventcrawl_target(vent)
if(!end_vent)
return
forceMove(vent)
playsound(vent, 'sound/machines/ventcrawl.ogg', 50, 1, -3)
vent.visible_message("\The [src] wiggles into \the [vent]!")
var/redirect_attempts = 3
while(redirect_attempts)
var/travel_time = round(get_dist(get_turf(src), get_turf(end_vent)) / 2)
sleep(travel_time)
if(end_vent.welded)
end_vent = get_safe_ventcrawl_target(vent)
if(!end_vent)
forceMove(get_turf(vent))
return
redirect_attempts--
continue
break
playsound(end_vent, 'sound/machines/ventcrawl.ogg', 50, 1, -3)
forceMove(get_turf(end_vent))
/mob/living/simple_mob/solargrub_larva/proc/expand_grub()
eject_from_machine()
visible_message("<span class='warning'>\The [src] suddenly balloons in size!</span>")
new /mob/living/simple_mob/animal/solargrub(get_turf(src))
// var/mob/living/simple_mob/animal/solargrub/grub = new(get_turf(src))
// grub.power_drained = power_drained //TODO
qdel(src)
/mob/living/simple_mob/solargrub_larva/handle_light()
. = ..()
if(. == 0 && !is_dead())
set_light(1.5, 1, COLOR_YELLOW)
return 1
/obj/machinery/abstract_grub_machine
var/total_active_power_usage = 45 KILOWATTS
var/list/active_power_usages = list(15 KILOWATTS, 15 KILOWATTS, 15 KILOWATTS)
var/total_idle_power_usage = 3 KILOWATTS
var/list/idle_power_usages = list(1 KILOWATTS, 1 KILOWATTS, 1 KILOWATTS)
var/draining = 1
var/mob/living/simple_mob/solargrub_larva/grub
/obj/machinery/abstract_grub_machine/New()
..()
shuffle_power_usages()
grub = loc
if(!istype(grub))
grub = null
qdel(src)
/obj/machinery/abstract_grub_machine/Destroy()
grub = null
return ..()
/obj/machinery/abstract_grub_machine/process()
if(!draining)
return
var/area/A = get_area(src)
if(!A)
return
var/list/power_list
switch(draining)
if(1)
power_list = idle_power_usages
if(2)
power_list = active_power_usages
for(var/i = 1 to power_list.len)
if(A.powered(i))
use_power(power_list[i], i)
grub.power_drained += power_list[i]
if(prob(5))
shuffle_power_usages()
/obj/machinery/abstract_grub_machine/proc/shuffle_power_usages()
total_active_power_usage = rand(30 KILOWATTS, 60 KILOWATTS)
total_idle_power_usage = rand(1 KILOWATTS, 5 KILOWATTS)
active_power_usages = split_into_3(total_active_power_usage)
idle_power_usages = split_into_3(total_idle_power_usage)
/obj/item/device/multitool/afterattack(obj/O, mob/user, proximity)
if(proximity)
if(istype(O, /obj/machinery))
var/mob/living/simple_mob/solargrub_larva/grub = locate() in O
if(grub)
grub.eject_from_machine(O)
to_chat(user, "<span class='warning'>You disturb a grub nesting in \the [O]!</span>")
return
return ..()

View File

@@ -9,10 +9,10 @@ var/list/ventcrawl_machinery = list(
/obj/item/device/radio/borg, /obj/item/device/radio/borg,
/obj/item/weapon/holder, /obj/item/weapon/holder,
/obj/machinery/camera, /obj/machinery/camera,
///mob/living/simple_mob/borer, //VORESTATION AI TEMPORARY REMOVAL //VOREStation Edit /obj/belly, //VOREStation Edit
/obj/belly, //VOREStation Edit,
/obj/screen /obj/screen
) )
//mob/living/simple_mob/borer, //VORESTATION AI TEMPORARY REMOVAL REPLACE BACK IN LIST WHEN RESOLVED //VOREStation Edit
/mob/living/var/list/icon/pipes_shown = list() /mob/living/var/list/icon/pipes_shown = list()
/mob/living/var/last_played_vent /mob/living/var/last_played_vent

View File

@@ -25,9 +25,9 @@
/mob/living/simple_mob/animal/giant_spider/nurse, /mob/living/simple_mob/animal/giant_spider/nurse,
/mob/living/simple_mob/animal/space/alien, /mob/living/simple_mob/animal/space/alien,
/mob/living/simple_mob/animal/space/bear, /mob/living/simple_mob/animal/space/bear,
// /mob/living/simple_mob/carp, // Vorestation edit //VORESTATION AI TEMPORARY REMOVAL
/mob/living/simple_mob/creature, /mob/living/simple_mob/creature,
/mob/living/simple_mob/slime/xenobio) /mob/living/simple_mob/slime/xenobio)
// /mob/living/simple_mob/carp, // Vorestation edit //VORESTATION AI TEMPORARY REMOVAL, REPLACE BACK IN LIST WHEN FIXED
else else
spawn_type = pick(\ spawn_type = pick(\
/mob/living/simple_mob/animal/passive/cat, /mob/living/simple_mob/animal/passive/cat,

View File

@@ -26,7 +26,6 @@
/obj/item/roller, /obj/item/roller,
/obj/structure/closet/crate, /obj/structure/closet/crate,
/obj/structure/closet/acloset, /obj/structure/closet/acloset,
// /mob/living/simple_mob/mimic/crate, // Vorestation edit //VORESTATION AI TEMPORARY REMOVAL
/mob/living/simple_mob/mechanical/viscerator, /mob/living/simple_mob/mechanical/viscerator,
/mob/living/simple_mob/mechanical/hivebot, /mob/living/simple_mob/mechanical/hivebot,
/obj/item/device/analyzer, /obj/item/device/analyzer,
@@ -65,6 +64,7 @@
/obj/item/weapon/grenade/chem_grenade/cleaner, /obj/item/weapon/grenade/chem_grenade/cleaner,
/obj/item/weapon/grenade/chem_grenade/metalfoam) /obj/item/weapon/grenade/chem_grenade/metalfoam)
// /mob/living/simple_mob/mimic/crate, // Vorestation edit //VORESTATION AI TEMPORARY REMOVAL, REPLACE BACK IN LIST WHEN FIXED
var/quantity = rand(5, 15) var/quantity = rand(5, 15)
for(var/i=0, i<quantity, i++) for(var/i=0, i<quantity, i++)
var/button_desc = "a [pick("yellow","purple","green","blue","red","orange","white")], " var/button_desc = "a [pick("yellow","purple","green","blue","red","orange","white")], "

View File

@@ -55,7 +55,7 @@
/turf/simulated/floor/water, /turf/simulated/floor/water,
/area/submap/spa) /area/submap/spa)
"ak" = ( "ak" = (
/mob/living/simple_mob/fox, /mob/living/simple_mob/animal/fox,
/turf/simulated/floor/grass, /turf/simulated/floor/grass,
/area/submap/spa) /area/submap/spa)
"al" = ( "al" = (
@@ -623,7 +623,7 @@
}, },
/area/space) /area/space)
"bW" = ( "bW" = (
/mob/living/simple_mob/redpanda, /mob/living/simple_mob/animal/redpanda,
/turf/simulated/floor/grass, /turf/simulated/floor/grass,
/area/submap/spa) /area/submap/spa)
"bX" = ( "bX" = (

View File

@@ -2344,6 +2344,7 @@
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\discipline.dm" #include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\discipline.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\subtypes.dm" #include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\subtypes.dm"
#include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\xenobio.dm" #include "code\modules\mob\living\simple_mob\subtypes\slime\xenobio\xenobio.dm"
#include "code\modules\mob\living\simple_mob\subtypes\vore\redpanda.dm"
#include "code\modules\mob\living\voice\voice.dm" #include "code\modules\mob\living\voice\voice.dm"
#include "code\modules\mob\new_player\login.dm" #include "code\modules\mob\new_player\login.dm"
#include "code\modules\mob\new_player\logout.dm" #include "code\modules\mob\new_player\logout.dm"