diff --git a/vore/bee.dm b/code/modules/mob/living/simple_mob/subtypes/vore/bee.dm similarity index 100% rename from vore/bee.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/bee.dm diff --git a/vore/catgirl.dm b/code/modules/mob/living/simple_mob/subtypes/vore/catgirl.dm similarity index 100% rename from vore/catgirl.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/catgirl.dm diff --git a/vore/cookiegirl.dm b/code/modules/mob/living/simple_mob/subtypes/vore/cookiegirl.dm similarity index 96% rename from vore/cookiegirl.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/cookiegirl.dm index 2e4fa8b378..af4636ef96 100644 --- a/vore/cookiegirl.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/cookiegirl.dm @@ -1,53 +1,53 @@ -/mob/living/simple_mob/vore/cookiegirl - name = "cookiegirl" - desc = "A woman made with a combination of, well... Whatever you put in a cookie. What were the chefs thinking?" - - icon_state = "cookiegirl" - icon_living = "cookiegirl" - icon_rest = "cookiegirl_rest" - icon_dead = "cookiegirl-dead" - icon = 'icons/mob/vore.dmi' - - maxHealth = 10 - health = 10 - - harm_intent_damage = 2 - melee_damage_lower = 5 - melee_damage_upper = 10 - - say_list_type = /datum/say_list/cookiegirl - ai_holder_type = /datum/ai_holder/simple_mob/passive/cookiegirl - - // Activate Noms! -/mob/living/simple_mob/vore/cookiegirl - vore_active = 1 - vore_bump_chance = 2 - vore_pounce_chance = 25 - vore_standing_too = 1 - vore_ignores_undigestable = 0 // Do they look like they care? - vore_default_mode = DM_HOLD // They're cookiepeople, what do you expect? - vore_digest_chance = 10 // Gonna become as sweet as sugar, soon. - vore_icons = SA_ICON_LIVING | SA_ICON_REST - -/datum/ai_holder/simple_mob/passive/cookiegirl/on_hear_say(mob/living/speaker, message) - - if(!speaker.client) - return - - if(findtext(message, "Can I eat you?")) - delayed_say(pick("Do you really wanna eat someone as sweet as me~?"), speaker) - - if(findtext(message, "You look tasty.")) - delayed_say(pick("Awww, thank you~!"), speaker) - - if(findtext(message, "Can I serve you to the crew?")) - delayed_say(pick("If I have a backup, sure!"), speaker) - -/datum/say_list/cookiegirl - speak = list("Hi!","Are you hungry?","Got milk~?","What to do, what to do...") - 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.") - -/datum/ai_holder/simple_mob/passive/cookiegirl - base_wander_delay = 8 +/mob/living/simple_mob/vore/cookiegirl + name = "cookiegirl" + desc = "A woman made with a combination of, well... Whatever you put in a cookie. What were the chefs thinking?" + + icon_state = "cookiegirl" + icon_living = "cookiegirl" + icon_rest = "cookiegirl_rest" + icon_dead = "cookiegirl-dead" + icon = 'icons/mob/vore.dmi' + + maxHealth = 10 + health = 10 + + harm_intent_damage = 2 + melee_damage_lower = 5 + melee_damage_upper = 10 + + say_list_type = /datum/say_list/cookiegirl + ai_holder_type = /datum/ai_holder/simple_mob/passive/cookiegirl + + // Activate Noms! +/mob/living/simple_mob/vore/cookiegirl + vore_active = 1 + vore_bump_chance = 2 + vore_pounce_chance = 25 + vore_standing_too = 1 + vore_ignores_undigestable = 0 // Do they look like they care? + vore_default_mode = DM_HOLD // They're cookiepeople, what do you expect? + vore_digest_chance = 10 // Gonna become as sweet as sugar, soon. + vore_icons = SA_ICON_LIVING | SA_ICON_REST + +/datum/ai_holder/simple_mob/passive/cookiegirl/on_hear_say(mob/living/speaker, message) + + if(!speaker.client) + return + + if(findtext(message, "Can I eat you?")) + delayed_say(pick("Do you really wanna eat someone as sweet as me~?"), speaker) + + if(findtext(message, "You look tasty.")) + delayed_say(pick("Awww, thank you~!"), speaker) + + if(findtext(message, "Can I serve you to the crew?")) + delayed_say(pick("If I have a backup, sure!"), speaker) + +/datum/say_list/cookiegirl + speak = list("Hi!","Are you hungry?","Got milk~?","What to do, what to do...") + 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.") + +/datum/ai_holder/simple_mob/passive/cookiegirl + base_wander_delay = 8 intelligence_level = AI_NORMAL //not sure why we have this, but I'm just porting. \ No newline at end of file diff --git a/vore/corrupt_hounds.dm b/code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm similarity index 100% rename from vore/corrupt_hounds.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/corrupt_hounds.dm diff --git a/vore/deathclaw.dm b/code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm similarity index 100% rename from vore/deathclaw.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/deathclaw.dm diff --git a/vore/dino.dm b/code/modules/mob/living/simple_mob/subtypes/vore/dino.dm similarity index 100% rename from vore/dino.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/dino.dm diff --git a/vore/dragon.dm b/code/modules/mob/living/simple_mob/subtypes/vore/dragon.dm similarity index 100% rename from vore/dragon.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/dragon.dm diff --git a/vore/fennec.dm b/code/modules/mob/living/simple_mob/subtypes/vore/fennec.dm similarity index 100% rename from vore/fennec.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/fennec.dm diff --git a/vore/fennix.dm b/code/modules/mob/living/simple_mob/subtypes/vore/fennix.dm similarity index 96% rename from vore/fennix.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/fennix.dm index cbc2eb4af2..bcbb2d831f 100644 --- a/vore/fennix.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/fennix.dm @@ -1,30 +1,30 @@ -/mob/living/simple_mob/vore/fennix - name = "Fennix" - desc = "A feral fennix, Warm to the touch" - tt_desc = "Incaendium Faeles Vulpes" - - icon_state = "fennix" - icon_living = "fennix" - icon_dead = "fennix_dead" - icon = 'icons/mob/vore.dmi' - - faction = "fennec" // Will protec other fenfens - maxHealth = 60 - health = 60 - - response_help = "pats the" - response_disarm = "gently pushes aside the" - response_harm = "hits the" - - harm_intent_damage = 20 - melee_damage_lower = 1 - melee_damage_upper = 5 - attacktext = list("Bites") - - say_list_type = /datum/say_list/fennix - ai_holder_type = /datum/ai_holder/simple_mob/retaliate/cooperative - -/datum/say_list/fennix - speak = list("SQUEL!","SQEL?","Skree.") - emote_hear = list("Screeeeecheeeeessss!","Chirrup.") - emote_see = list("earflicks","pats at the ground") +/mob/living/simple_mob/vore/fennix + name = "Fennix" + desc = "A feral fennix, Warm to the touch" + tt_desc = "Incaendium Faeles Vulpes" + + icon_state = "fennix" + icon_living = "fennix" + icon_dead = "fennix_dead" + icon = 'icons/mob/vore.dmi' + + faction = "fennec" // Will protec other fenfens + maxHealth = 60 + health = 60 + + response_help = "pats the" + response_disarm = "gently pushes aside the" + response_harm = "hits the" + + harm_intent_damage = 20 + melee_damage_lower = 1 + melee_damage_upper = 5 + attacktext = list("Bites") + + say_list_type = /datum/say_list/fennix + ai_holder_type = /datum/ai_holder/simple_mob/retaliate/cooperative + +/datum/say_list/fennix + speak = list("SQUEL!","SQEL?","Skree.") + emote_hear = list("Screeeeecheeeeessss!","Chirrup.") + emote_see = list("earflicks","pats at the ground") diff --git a/vore/frog.dm b/code/modules/mob/living/simple_mob/subtypes/vore/frog.dm similarity index 100% rename from vore/frog.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/frog.dm diff --git a/vore/hippo.dm b/code/modules/mob/living/simple_mob/subtypes/vore/hippo.dm similarity index 100% rename from vore/hippo.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/hippo.dm diff --git a/vore/horse.dm b/code/modules/mob/living/simple_mob/subtypes/vore/horse.dm similarity index 100% rename from vore/horse.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/horse.dm diff --git a/vore/jelly.dm b/code/modules/mob/living/simple_mob/subtypes/vore/jelly.dm similarity index 100% rename from vore/jelly.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/jelly.dm diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/otie.dm b/code/modules/mob/living/simple_mob/subtypes/vore/otie.dm new file mode 100644 index 0000000000..5de33d56b7 --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/otie.dm @@ -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,"The guard pup accepts your offer for their catch.") + release_vore_contents() + else if(prob(2)) //Small chance to get prey out from non-sec oties. + to_chat(user,"The pup accepts your offer for their catch.") + 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 [target_name(prey)] in [get_area(src)].", "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 [target_name(M)] in [get_area(src)].", "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("[M] [response_help] \the [src].") + 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 \ No newline at end of file diff --git a/vore/panther.dm b/code/modules/mob/living/simple_mob/subtypes/vore/panther.dm similarity index 100% rename from vore/panther.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/panther.dm diff --git a/vore/rat.dm b/code/modules/mob/living/simple_mob/subtypes/vore/rat.dm similarity index 100% rename from vore/rat.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/rat.dm diff --git a/vore/redpanda.dm b/code/modules/mob/living/simple_mob/subtypes/vore/redpanda.dm similarity index 100% rename from vore/redpanda.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/redpanda.dm diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/_defines.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/_defines.dm new file mode 100644 index 0000000000..1567134c4d --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/_defines.dm @@ -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 \ No newline at end of file diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_objects.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_objects.dm new file mode 100644 index 0000000000..6990623043 --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_objects.dm @@ -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,"[name] (Cost: [cost]%) - [desc]") + else + do_ability(my_kin) + +/obj/effect/shadekin_ability/proc/do_ability() + if(my_kin.stat) + to_chat(my_kin,"Can't use that ability in your state!") + return FALSE + if(shift_mode == NOT_WHILE_SHIFTED && (my_kin.ability_flags & AB_PHASE_SHIFTED)) + to_chat(my_kin,"Can't use that ability while phase shifted!") + return FALSE + else if(shift_mode == ONLY_WHILE_SHIFTED && !(my_kin.ability_flags & AB_PHASE_SHIFTED)) + to_chat(my_kin,"Can only use that ability while phase shifted!") + return FALSE + else if(my_kin.energy < cost) + to_chat(my_kin,"Not enough energy for that ability!") + 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 = "Sparkles begin to appear around you, and all your ills seem to fade away." + on_expired_text = "The sparkles have faded, although you feel much healthier than before." + 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 = "You drag part of The Dark into realspace, enveloping yourself." + on_expired_text = "You lose your grasp on The Dark and realspace reasserts itself." + 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 +*/ \ No newline at end of file diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_procs.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_procs.dm new file mode 100644 index 0000000000..0be707f852 --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_procs.dm @@ -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,"You can't use that here!") + 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,"\The [src] phases in around you, [vore_selected.vore_verb]ing you into their [vore_selected.name]!") + + // 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,"Nobody nearby to mend!") + 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("\The [src] gently places a hand on \the [target]...") + face_atom(target) + return TRUE diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm new file mode 100644 index 0000000000..7b151161be --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm @@ -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("\The [src] [pick(friendly)] \the [henlo_human].") + 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 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/types.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/types.dm new file mode 100644 index 0000000000..ea7a9b0f2c --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/types.dm @@ -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." diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/~defines.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/~defines.dm new file mode 100644 index 0000000000..28ce75c50b --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/~defines.dm @@ -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 \ No newline at end of file diff --git a/vore/snake.dm b/code/modules/mob/living/simple_mob/subtypes/vore/snake.dm similarity index 100% rename from vore/snake.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/snake.dm diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/solargrub.dm b/code/modules/mob/living/simple_mob/subtypes/vore/solargrub.dm new file mode 100644 index 0000000000..8444d55538 --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/solargrub.dm @@ -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 don’t 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("The grub releases a powerful shock!") + ..() + +/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("\The [src] begins to sink power from the net.") + 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 << "You feel a shock rushing through your veins." + 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 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/solargrub_larva.dm b/code/modules/mob/living/simple_mob/subtypes/vore/solargrub_larva.dm new file mode 100644 index 0000000000..898a3d2757 --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/solargrub_larva.dm @@ -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("\The [src] finds an opening and crawls inside \the [M].") + 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("\The [src] suddenly balloons in size!") + 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, "You disturb a grub nesting in \the [O]!") + return + return ..() diff --git a/vore/wolf.dm b/code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm similarity index 100% rename from vore/wolf.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/wolf.dm diff --git a/vore/wolfgirl.dm b/code/modules/mob/living/simple_mob/subtypes/vore/wolfgirl.dm similarity index 100% rename from vore/wolfgirl.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/wolfgirl.dm diff --git a/vore/zz_vore_overrides.dm b/code/modules/mob/living/simple_mob/subtypes/vore/zz_vore_overrides.dm similarity index 100% rename from vore/zz_vore_overrides.dm rename to code/modules/mob/living/simple_mob/subtypes/vore/zz_vore_overrides.dm diff --git a/code/modules/ventcrawl/ventcrawl.dm b/code/modules/ventcrawl/ventcrawl.dm index 5cef7f694a..87459904e1 100644 --- a/code/modules/ventcrawl/ventcrawl.dm +++ b/code/modules/ventcrawl/ventcrawl.dm @@ -9,10 +9,10 @@ var/list/ventcrawl_machinery = list( /obj/item/device/radio/borg, /obj/item/weapon/holder, /obj/machinery/camera, - ///mob/living/simple_mob/borer, //VORESTATION AI TEMPORARY REMOVAL //VOREStation Edit - /obj/belly, //VOREStation Edit, + /obj/belly, //VOREStation Edit /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/last_played_vent diff --git a/code/modules/xenoarcheaology/artifacts/autocloner.dm b/code/modules/xenoarcheaology/artifacts/autocloner.dm index c5e89a7b51..5d70e62752 100644 --- a/code/modules/xenoarcheaology/artifacts/autocloner.dm +++ b/code/modules/xenoarcheaology/artifacts/autocloner.dm @@ -25,9 +25,9 @@ /mob/living/simple_mob/animal/giant_spider/nurse, /mob/living/simple_mob/animal/space/alien, /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/slime/xenobio) + // /mob/living/simple_mob/carp, // Vorestation edit //VORESTATION AI TEMPORARY REMOVAL, REPLACE BACK IN LIST WHEN FIXED else spawn_type = pick(\ /mob/living/simple_mob/animal/passive/cat, diff --git a/code/modules/xenoarcheaology/artifacts/replicator.dm b/code/modules/xenoarcheaology/artifacts/replicator.dm index 3dd5fca3d0..af78f320e5 100644 --- a/code/modules/xenoarcheaology/artifacts/replicator.dm +++ b/code/modules/xenoarcheaology/artifacts/replicator.dm @@ -26,7 +26,6 @@ /obj/item/roller, /obj/structure/closet/crate, /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/hivebot, /obj/item/device/analyzer, @@ -65,6 +64,7 @@ /obj/item/weapon/grenade/chem_grenade/cleaner, /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) for(var/i=0, i