[MIRROR] Glamour mob pack (#9225)

Co-authored-by: Heroman3003 <31296024+Heroman3003@users.noreply.github.com>
Co-authored-by: Kashargul <KashL@t-online.de>
This commit is contained in:
CHOMPStation2
2024-10-13 13:31:24 -07:00
committed by GitHub
parent 032b0be496
commit 464ebe7360
18 changed files with 1288 additions and 3 deletions

View File

@@ -103,6 +103,13 @@
//VOREStation edit ends //VOREStation edit ends
/obj/effect/projectile/impact/pointdefense /obj/effect/projectile/impact/pointdefense
icon_state = "impact_pointdef" icon_state = "impact_pointdef"
/obj/effect/projectile/impact/rainbow
icon_state = "impact_rainbow"
light_range = 3
light_power = 1
light_color = "#ffffff"
//CHOMPStation add coilgun pointdefense //CHOMPStation add coilgun pointdefense
/obj/effect/projectile/impact/coildefense /obj/effect/projectile/impact/coildefense
icon = 'icons/obj/projectiles_impact_ch.dmi' icon = 'icons/obj/projectiles_impact_ch.dmi'

View File

@@ -115,6 +115,13 @@
//VOREStation edit ends //VOREStation edit ends
/obj/effect/projectile/muzzle/pointdefense /obj/effect/projectile/muzzle/pointdefense
icon_state = "muzzle_pointdef" icon_state = "muzzle_pointdef"
/obj/effect/projectile/muzzle/rainbow
icon_state = "muzzle_rainbow"
light_range = 3
light_power = 1
light_color = "#ffffff"
//CHOMPStation add coilgun pointdefense //CHOMPStation add coilgun pointdefense
/obj/effect/projectile/muzzle/coildefense /obj/effect/projectile/muzzle/coildefense
icon = 'icons/obj/projectiles_muzzle_ch.dmi' icon = 'icons/obj/projectiles_muzzle_ch.dmi'

View File

@@ -142,6 +142,13 @@
//VOREStation edit ends //VOREStation edit ends
/obj/effect/projectile/tracer/pointdefense /obj/effect/projectile/tracer/pointdefense
icon_state = "beam_pointdef" icon_state = "beam_pointdef"
/obj/effect/projectile/tracer/rainbow
icon_state = "rainbow"
light_range = 3
light_power = 1
light_color = "#ffffff"
//CHOMPStation add coilgun pointdefense //CHOMPStation add coilgun pointdefense
/obj/effect/projectile/tracer/coildefense /obj/effect/projectile/tracer/coildefense
icon = 'icons/obj/projectiles_tracer_ch.dmi' icon = 'icons/obj/projectiles_tracer_ch.dmi'

View File

@@ -70,9 +70,11 @@
vore_default_item_mode = IM_DIGEST vore_default_item_mode = IM_DIGEST
/mob/living/simple_mob/vore/squirrel/init_vore() /mob/living/simple_mob/vore/squirrel/init_vore()
if(!voremob_loaded) //CHOMPAdd //CHONOEdit Start
return //CHOMPAdd if(!voremob_loaded)
.=..() //CHOMPEdit return
.=..()
//CHONOEdit End
var/obj/belly/B = vore_selected var/obj/belly/B = vore_selected
B.name = "stomach" B.name = "stomach"
B.digest_mode = DM_SELECT B.digest_mode = DM_SELECT

View File

@@ -0,0 +1,359 @@
/mob/living/simple_mob/vore/blaidd
name = "blaidd"
desc = "A wolf like creature with a large, spikey mane."
tt_desc = "Canis glamoris"
icon = 'icons/mob/vore64x32.dmi'
icon_dead = "blaidd-dead"
icon_living = "blaidd"
icon_state = "blaidd"
icon_rest = "blaidd_rest"
old_x = -16
old_y = 0
default_pixel_x = -16
pixel_x = -16
pixel_y = 0
faction = FACTION_GLAMOUR
catalogue_data = list(/datum/category_item/catalogue/fauna/blaidd)
ai_holder_type = /datum/ai_holder/simple_mob/vore/blaidd
harm_intent_damage = 10
melee_damage_lower = 10
melee_damage_upper = 20
maxHealth = 300
minbodytemp = 0
max_buckled_mobs = 1
mount_offset_y = 14
mount_offset_x = 2
can_buckle = TRUE
buckle_movable = TRUE
buckle_lying = FALSE
var/blaidd_invisibility
vore_bump_chance = 25
vore_digest_chance = 50
vore_escape_chance = 5
vore_pounce_chance = 100
vore_active = 1
vore_icons = 1
vore_icons = SA_ICON_LIVING | SA_ICON_REST
vore_capacity = 1
swallowTime = 50
vore_ignores_undigestable = TRUE
vore_default_mode = DM_SELECT
vore_pounce_maxhealth = 125
vore_bump_emote = "tries to devour"
/mob/living/simple_mob/vore/blaidd/Login()
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
verbs |= /mob/living/simple_mob/proc/animal_mount
verbs |= /mob/living/proc/toggle_rider_reins
verbs |= /mob/living/simple_mob/vore/blaidd/proc/blaidd_invis
movement_cooldown = -1
/mob/living/simple_mob/vore/blaidd/init_vore()
//CHONOEdit Start
if(!voremob_loaded)
return
.=..()
//CHONOEdit End
var/obj/belly/B = vore_selected
B.name = "stomach"
B.desc = "The canine pounces atop you and wastes now time in wrapping its jaws around your entire head. The beast is strong and determined, there is no wriggling out of it's iron grip. Within its maw, the tongue slathers canine drool across you, hot doglike breaths wash across your face, triangular teeth hold you firmly in place. It doesn't take long before the blaidd is gulping you down aggressively, like a big chunk of meat. The creature's stomach distends and hangs beneath it with your weight, swaying heavily not just with your movements, but every step from the wolf. Bound up uncomfortably tight in this sweltering, dark gut, movement is almost impossible and it's hard to tell which way is up."
B.vore_sound = "Tauric Swallow"
B.release_sound = "Pred Escape"
B.mode_flags = DM_FLAG_THICKBELLY
B.fancy_vore = 1
B.selective_preference = DM_DIGEST
B.vore_verb = "devour"
B.digest_brute = 1
B.digest_burn = 1
B.digest_oxy = 0
B.selectchance = 50
B.absorbchance = 0
B.escapechance = 10
B.escape_stun = 5
B.contamination_color = "grey"
B.contamination_flavor = "Wet"
B.emote_lists[DM_DIGEST] = list(
"The blaidd growls as the gut squeeze over your body, smearing caustic oozes into your form!",
"You are turned over and walls clench around you as the beast moves about, tossing more digestive juices over your body.",
"You can't make out any sound from the outside as the gut grumbled and reverberates over your body.",
"As the thinning air begins to make you feel dizzy, menacing bworps and grumbles fill that dark, constantly shifting organ!",
"The constant, rhythmic kneading and massaging starts to take its toll along with the muggy heat, making you feel weaker and weaker!",
"The blaidd presses its gut against the floor, giving you a full body crush deep within its gut. The strain on your body aids digestion, making you all the easier to work down.")
/datum/category_item/catalogue/fauna/blaidd
name = "Extra-Realspace Fauna - Blaidd"
desc = "Classification: Canis glamoris\
<br><br>\
A large canine found in whitespace or the Glamour, distinguished easily by a large spikey mane and lightly striped pattern. The Blaidd, named from the glamourspeak word for wolf, is known to be a ferocious hunter and predator. It is a carnivore that stalks prey from a distance silently, whilst its otherwise quite striking fur blends it well into the environment through some sort of active camouflage, a less powerful version of that seen in the local Lleill. It generally avoids attacking its prey when it feels it is being watched, but once it is able to finally pounce on a target, it will not retreat until forced."
value = CATALOGUER_REWARD_HARD
/mob/living/simple_mob/vore/blaidd/update_icon()
. = ..()
if(vore_active)
var/voremob_awake = FALSE
if(icon_state == icon_living)
voremob_awake = TRUE
if(blaidd_invisibility)
icon_state = "[icon_living]_cloaked"
update_fullness()
if(!vore_fullness)
update_transform()
return 0
else if((stat == CONSCIOUS) && (!icon_rest || !resting || !incapacitated(INCAPACITATION_DISABLED)) && (vore_icons & SA_ICON_LIVING))
if(blaidd_invisibility)
icon_state = "[icon_living]_cloaked-[vore_fullness]"
else
icon_state = "[icon_living]-[vore_fullness]"
else if(stat >= DEAD && (vore_icons & SA_ICON_DEAD))
icon_state = "[icon_dead]-[vore_fullness]"
else if(((stat == UNCONSCIOUS) || resting || incapacitated(INCAPACITATION_DISABLED) ) && icon_rest && (vore_icons & SA_ICON_REST))
icon_state = "[icon_rest]-[vore_fullness]"
if(vore_eyes && voremob_awake) //Update eye layer if applicable.
remove_eyes()
add_eyes()
update_transform()
/mob/living/simple_mob/vore/blaidd/proc/blaidd_invis()
set name = "Invisibility"
set desc = "Change your appearance to match your surroundings, becoming somewhat invisible to the naked eye."
set category = "Abilities"
if(blaidd_invisibility)
blaidd_invisibility = 0
else
blaidd_invisibility = 1
update_icon()
/datum/ai_holder/simple_mob/vore/blaidd
can_flee = TRUE
vision_range = 12 //They rush you from off-screen, but easily countered if you are aware
var/watched = 0
var/hiding = 0
/datum/ai_holder/simple_mob/vore/blaidd/hostile
hostile = TRUE
/datum/ai_holder/simple_mob/vore/blaidd/proc/check_witness(list/possible_targets, has_targets_list)
if(!has_targets_list)
possible_targets = list_targets()
for(var/mob/living/L in possible_targets)
var/distance = get_dist(holder, L)
if(!check_attacker(L) && !L.stat && distance <= 9) //Stop approaching just off screen if they're looking in your direction
if((L.dir == 1 && holder.y >= L.y) || (L.dir == 2 && holder.y <= L.y) || (L.dir == 4 && holder.x >= L.x) || (L.dir == 8 && holder.x <= L.x)) //stop attacking if they look at you
set_stance(STANCE_IDLE)
if(!watched)
watched = 1
spawn(5) //run away if they keep staring
watched = 0
if((L.dir == 1 && holder.y >= L.y) || (L.dir == 2 && holder.y <= L.y) || (L.dir == 4 && holder.x >= L.x) || (L.dir == 8 && holder.x <= L.x) && distance <= 8)
if(!L.stat) //If the prey is weakened in any way, don't run
step_away(holder, L, 8) //Flee if they stare at you within normal view range
holder.face_atom(L)
return TRUE
return FALSE
/datum/ai_holder/simple_mob/vore/blaidd/find_target(list/possible_targets, has_targets_list)
if(!vore_hostile)
return ..()
if(!isanimal(holder)) //Only simplemobs have the vars we need
return ..()
var/mob/living/simple_mob/H = holder
if(H.vore_fullness >= H.vore_capacity) //Don't beat people up if we're full
return ..()
ai_log("find_target() : Entered.", AI_LOG_TRACE)
. = list()
if(!has_targets_list)
possible_targets = list_targets()
var/list/valid_mobs = list()
for(var/mob/living/possible_target in possible_targets)
if(!can_attack(possible_target))
continue
. |= possible_target
if(!isliving(possible_target))
continue
if(vore_check(possible_target))
valid_mobs |= possible_target
var/new_target
if(valid_mobs.len)
new_target = pick(valid_mobs)
else if(hostile)
new_target = pick(.)
if(!new_target)
return null
give_target(new_target)
return new_target
/datum/ai_holder/simple_mob/vore/blaidd/can_attack(atom/movable/the_target, var/vision_required = TRUE)
ai_log("can_attack() : Entering.", AI_LOG_TRACE)
if(!can_see_target(the_target) && vision_required)
return FALSE
if(!belly_attack)
if(isbelly(holder.loc))
return FALSE
var/distance = get_dist(holder, target)
if(distance > 2)
if(check_witness())
return FALSE
if(isliving(the_target))
var/mob/living/L = the_target
if(ishuman(L) || issilicon(L))
if(L.key && !L.client) // SSD players get a pass
return FALSE
if(L.stat)
if(L.stat == DEAD && !handle_corpse) // Leave dead things alone
return FALSE
if(L.stat == UNCONSCIOUS) // Do we have mauling? Yes? Then maul people who are sleeping but not SSD
if(mauling)
return TRUE
//VOREStation Add Start
else if(unconscious_vore && L.allowmobvore)
var/mob/living/simple_mob/vore/eater = holder
if(eater.will_eat(L))
return TRUE
else
return FALSE
//VOREStation Add End
else
return FALSE
// if(!check_attacker(L))
// if((L.dir == 1 && holder.y >= L.y) || (L.dir == 2 && holder.y <= L.y) || (L.dir == 4 && holder.x >= L.x) || (L.dir == 8 && holder.x <= L.x)) //stop attacking if they look at you
// set_stance(STANCE_IDLE)
// spawn(40) //run away if they keep staring
// if((L.dir == 1 && holder.y >= L.y) || (L.dir == 2 && holder.y <= L.y) || (L.dir == 4 && holder.x >= L.x) || (L.dir == 8 && holder.x <= L.x))
// if(!L.stat) //If the prey is weakened in any way, don't run
// step_away(holder, L, 8)
// holder.face_atom(L)
// return FALSE
//VOREStation add start
else if(forgive_resting && !isbelly(holder.loc)) //Doing it this way so we only think about the other conditions if the var is actually set
if((holder.health == holder.maxHealth) && !hostile && (L.resting || L.weakened || L.stunned)) //If our health is full, no one is fighting us, we can forgive
var/mob/living/simple_mob/vore/eater = holder
if(!eater.will_eat(L)) //We forgive people we can eat by eating them
set_stance(STANCE_IDLE)
return FALSE //Forgiven
//VOREStation add end
if(holder.IIsAlly(L))
return FALSE
return TRUE
if(istype(the_target, /obj/mecha))
var/obj/mecha/M = the_target
if(M.occupant)
return can_attack(M.occupant)
return destructive // Empty mechs are 'neutral'.
if(istype(the_target, /obj/machinery/porta_turret))
var/obj/machinery/porta_turret/P = the_target
if(P.stat & BROKEN)
return FALSE // Already dead.
if(P.faction == holder.faction)
return FALSE // Don't shoot allied turrets.
if(!P.raised && !P.raising)
return FALSE // Turrets won't get hurt if they're still in their cover.
return TRUE
if(istype(the_target, /obj/structure/blob)) // Blob mobs are always blob faction, but the blob can anger other things.
var/obj/structure/blob/Blob = the_target
if(holder.faction == Blob.faction)
return FALSE
return TRUE
/datum/ai_holder/simple_mob/vore/blaidd/engage_target()
ai_log("engage_target() : Entering.", AI_LOG_DEBUG)
// Can we still see them?
if(!target || !can_attack(target))
ai_log("engage_target() : Lost sight of target.", AI_LOG_TRACE)
if(lose_target()) // We lost them (returns TRUE if we found something else to do)
ai_log("engage_target() : Pursuing other options (last seen, or a new target).", AI_LOG_TRACE)
return
var/distance = get_dist(holder, target)
ai_log("engage_target() : Distance to target ([target]) is [distance].", AI_LOG_TRACE)
holder.face_atom(target)
last_conflict_time = world.time
// Do a 'special' attack, if one is allowed.
// if(prob(special_attack_prob) && (distance >= special_attack_min_range) && (distance <= special_attack_max_range))
if(holder.ICheckSpecialAttack(target))
ai_log("engage_target() : Attempting a special attack.", AI_LOG_TRACE)
on_engagement(target)
if(special_attack(target)) // If this fails, then we try a regular melee/ranged attack.
ai_log("engage_target() : Successful special attack. Exiting.", AI_LOG_DEBUG)
return
// Stab them.
else if(distance <= 1 && !pointblank)
ai_log("engage_target() : Attempting a melee attack.", AI_LOG_TRACE)
on_engagement(target)
melee_attack(target)
else if(distance <= 1 && !holder.ICheckRangedAttack(target)) // Doesn't have projectile, but is pointblank
ai_log("engage_target() : Attempting a melee attack.", AI_LOG_TRACE)
on_engagement(target)
melee_attack(target)
// Shoot them.
else if(holder.ICheckRangedAttack(target) && (distance <= max_range(target)) )
on_engagement(target)
if(firing_lanes && !test_projectile_safety(target))
// Nudge them a bit, maybe they can shoot next time.
var/turf/T = get_step(holder, pick(cardinal))
if(T)
holder.IMove(T) // IMove() will respect movement cooldown.
holder.face_atom(target)
ai_log("engage_target() : Could not safely fire at target. Exiting.", AI_LOG_DEBUG)
return
ai_log("engage_target() : Attempting a ranged attack.", AI_LOG_TRACE)
ranged_attack(target)
// Run after them.
else if(!stand_ground)
ai_log("engage_target() : Target ([target]) too far away. Exiting.", AI_LOG_DEBUG)
set_stance(STANCE_APPROACH)
/datum/ai_holder/simple_mob/vore/blaidd/proc/set_invis()
var/mob/living/simple_mob/vore/blaidd/B = holder
if(!istype(B))
return
var/list/possible_targets = list_targets()
if(!possible_targets.len)
if(B.blaidd_invisibility)
B.blaidd_invisibility = 0
B.update_icon()
return
if(!target)
return
var/distance = get_dist(holder, target)
if(distance <= 1)
if(B.blaidd_invisibility)
B.blaidd_invisibility = 0
B.update_icon()
return
else
if(!B.blaidd_invisibility)
B.blaidd_invisibility = 1
B.update_icon()
return
/datum/ai_holder/simple_mob/vore/blaidd/handle_stance_strategical()
set_invis()
return ..()
/mob/living/simple_mob/vore/blaidd/hostile
ai_holder_type = /datum/ai_holder/simple_mob/vore/blaidd/hostile
/datum/ai_holder/simple_mob/vore/blaidd/hostile
hostile = TRUE

View File

@@ -0,0 +1,590 @@
/mob/living/simple_mob/vore/ddraig
name = "ddraig"
desc = "A massive drake-like creature with dark purple scales and a seemingly exposed skull."
tt_desc = "Draconis glamoris"
icon = 'icons/mob/vore96x96.dmi'
icon_dead = "ddraig-dead"
icon_living = "ddraig"
icon_state = "ddraig"
icon_rest = "ddraig_rest"
faction = FACTION_GLAMOUR
catalogue_data = list(/datum/category_item/catalogue/fauna/ddraig)
old_x = -32
old_y = 0
vis_height = 92
melee_damage_lower = 20
melee_damage_upper = 15
friendly = list("nudges", "sniffs on", "rumbles softly at", "nuzzles")
default_pixel_x = -32
pixel_x = -32
pixel_y = 0
response_help = "bumps"
response_disarm = "shoves"
response_harm = "bites"
movement_cooldown = 1
harm_intent_damage = 10
melee_damage_lower = 15
melee_damage_upper = 25
maxHealth = 1000
attacktext = list("mauled")
see_in_dark = 8
minbodytemp = 0
ai_holder_type = /datum/ai_holder/simple_mob/vore/ddraig
max_buckled_mobs = 1
mount_offset_y = 32
can_buckle = TRUE
buckle_movable = TRUE
buckle_lying = FALSE
minbodytemp = 0
var/flames
var/firebreathtimer
var/charge_warmup = 3 SECOND
var/tf_warmup = 2 SECOND
special_attack_min_range = 2
special_attack_max_range = 6
special_attack_cooldown = 15 SECONDS
var/leap_warmup = 2 SECOND // How long the leap telegraphing is.
var/leap_sound = 'sound/weapons/spiderlunge.ogg'
/mob/living/simple_mob/vore/ddraig
vore_bump_chance = 25
vore_digest_chance = 50
vore_escape_chance = 5
vore_pounce_chance = 100
vore_active = 1
vore_icons = 3
vore_icons = SA_ICON_LIVING | SA_ICON_REST
vore_capacity = 3
swallowTime = 50
vore_ignores_undigestable = TRUE
vore_default_mode = DM_DIGEST
vore_pounce_maxhealth = 125
vore_bump_emote = "tries to devour"
/mob/living/simple_mob/vore/ddraig/Login()
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
verbs |= /mob/living/simple_mob/proc/animal_mount
verbs |= /mob/living/proc/toggle_rider_reins
verbs |= /mob/living/proc/set_size
verbs |= /mob/living/proc/polymorph
verbs |= /mob/living/proc/glamour_invisibility
movement_cooldown = -1
/mob/living/simple_mob/vore/ddraig/init_vore()
//CHONOEdit Start
if(!voremob_loaded)
return
.=..()
//CHONOEdit End
var/obj/belly/B = vore_selected
B.name = "stomach"
B.desc = "Despite the jaws of the dragon not being particular visible, once they begin to part it reveals a rather vast maw. More than wide enough to engulf your head and upper body, the ddraig lifts you effortlessly from the ground, standing up to full height with only your legs dangling from the beast's mouth. Inside you are engulfed in the wet, slimy and hot slobber of the creature. A massive tongue beneath your body curls over you to taste and lather every inch on offer. Soon enough, the dragon tosses its head backwards, sending your body beyond the throat, wrapped in the rippled lining of the creatures gullet for a slow, dark descent into the abyss below. It is a long journey through that seemingly endless neck, but eventually you are deposited in the creature's stomach. Little sound from the outside makes it inside, all drowned out by the cacophony of bodily functions groaning, burbling and beating around you. Despite the size of the beast, the gut is not massive, the walls clench down tight around your helplessly trapped body. The stomach lining grinds roughly over your body, smearing you in a slurry of slimy fluids."
B.vore_sound = "Tauric Swallow"
B.release_sound = "Pred Escape"
B.mode_flags = DM_FLAG_THICKBELLY
B.fancy_vore = 1
B.selective_preference = DM_DIGEST
B.vore_verb = "devour"
B.digest_brute = 3
B.digest_burn = 2
B.digest_oxy = 0
B.selectchance = 50
B.absorbchance = 0
B.escapechance = 3
B.escape_stun = 5
B.contamination_color = "grey"
B.contamination_flavor = "Wet"
B.emote_lists[DM_DIGEST] = list(
"The ddraig coos contentedly as the walls crush and squeeze over your body!",
"As the ddraig moves about, it becomes more difficult to keep yourself upright, being forced to turn and slip of the slime slickened stomach lining.",
"You can't make out any sound from the outside as the gut grumbled and reverberates over your body.",
"As the thinning air begins to make you feel dizzy, menacing bworps and grumbles fill that dark, constantly shifting organ!",
"The constant, rhythmic kneading and massaging starts to take its toll along with the muggy heat, making you feel weaker and weaker!",
"The slender creature has no issue showing off the weak movements of you inside, even the churning of the gut itself tosses you about, all bumps so very visible on its flesh.")
/datum/category_item/catalogue/fauna/ddraig
name = "Extra-Realspace Fauna - Ddraig"
desc = "Classification: Draconis glamoris\
<br><br>\
A massive dragon-like creature found to reside in the glamour, also known as whitespace. The ddraig is considered a rarity, even amongst this alien world, and often revered by other inhabitants. \
It is rarely considered outright aggressive, but has been known to attack if it feels threatened. It is a sapiant creature and considered to be particularly intelligent. \
It is a carnivorous creature and quite capable of hunting. Aside from the deadly claws and teeth, it is also able to breathe fire like realspace dragons, turn itself invisible at will, and transform other creatures temporarily."
value = CATALOGUER_REWARD_HARD
/mob/living/simple_mob/vore/ddraig/do_special_attack(atom/A)
. = TRUE
if(ckey)
return
var/specialattack = rand(1,3)
if(specialattack == 1)
lunge(A)
if(specialattack == 2)
firebreathstart(A)
if(specialattack == 3)
tfbeam(A)
/mob/living/simple_mob/vore/ddraig/proc/lunge(atom/A) //Mostly copied from hunter.dm
set waitfor = FALSE
if(!isliving(A))
return FALSE
var/mob/living/L = A
if(!L.devourable || !L.allowmobvore || !L.can_be_drop_prey || !L.throw_vore || L.unacidable)
return FALSE
set_AI_busy(TRUE)
visible_message(span_warning("\The [src] rears back, ready to lunge!"))
to_chat(L, span_danger("\The [src] focuses on you!"))
// Telegraph, since getting stunned suddenly feels bad.
do_windup_animation(A, leap_warmup)
sleep(leap_warmup) // For the telegraphing.
if(L.z != z) //Make sure you haven't disappeared to somewhere we can't go
set_AI_busy(FALSE)
return FALSE
// Do the actual leap.
status_flags |= LEAPING // Lets us pass over everything.
visible_message(span_critical("\The [src] leaps at \the [L]!"))
throw_at(get_step(L, get_turf(src)), special_attack_max_range+1, 1, src)
playsound(src, leap_sound, 75, 1)
sleep(5) // For the throw to complete. It won't hold up the AI ticker due to waitfor being false.
if(status_flags & LEAPING)
status_flags &= ~LEAPING // Revert special passage ability.
set_AI_busy(FALSE)
if(Adjacent(L)) //We leapt at them but we didn't manage to hit them, let's see if we're next to them
L.Weaken(2) //get knocked down, idiot
/mob/living/simple_mob/vore/ddraig/proc/firebreathstart(var/atom/A) //Borrowed from le big dragon
glow_toggle = 1
set_light(glow_range, glow_intensity, glow_color) //Setting it here so the light starts immediately
flames = 1
set_AI_busy(TRUE)
visible_message(span_warning("\The [src] opens its maw, emitting flames!"))
do_windup_animation(A, charge_warmup)
firebreathtimer = addtimer(CALLBACK(src, PROC_REF(firebreathend), A), charge_warmup, TIMER_STOPPABLE)
playsound(src, "sound/magic/Fireball.ogg", 50, 1)
/mob/living/simple_mob/vore/ddraig/proc/firebreathend(var/atom/A)
//make sure our target still exists and is on a turf
if(QDELETED(A) || !isturf(get_turf(A)))
set_AI_busy(FALSE)
return
var/obj/item/projectile/P = new /obj/item/projectile/bullet/dragon(get_turf(src))
src.visible_message(span_danger("\The [src] spews fire at \the [A]!"))
playsound(src, "sound/weapons/Flamer.ogg", 50, 1)
P.launch_projectile(A, BP_TORSO, src)
set_AI_busy(FALSE)
glow_toggle = 0
flames = 0
/mob/living/simple_mob/vore/ddraig/proc/tfbeam(var/atom/A)
if(!isturf(get_turf(A)))
return
set_AI_busy(TRUE)
visible_message(span_warning("\The [src] begins to shimmer with a rainbow hue!"))
do_windup_animation(A, tf_warmup)
sleep(tf_warmup)
set_AI_busy(FALSE)
var/obj/item/projectile/P = new /obj/item/projectile/beam/mouselaser/ddraig(get_turf(src))
src.visible_message(span_danger("\The [src] breathes a beam at \the [A]!"))
playsound(src, "sound/weapons/sparkle.ogg", 50, 1)
P.launch_projectile(A, BP_TORSO, src)
/obj/item/projectile/beam/mouselaser/ddraig
tf_admin_pref_override = TRUE //It will TF them regardless of their prefs because it is only very temporary
icon_state = "rainbow"
muzzle_type = /obj/effect/projectile/muzzle/rainbow
tracer_type = /obj/effect/projectile/tracer/rainbow
impact_type = /obj/effect/projectile/impact/rainbow
/obj/item/projectile/beam/mouselaser/ddraig/on_hit(var/atom/target)
var/mob/living/M = target
if(!istype(M))
return
if(target != firer) //If you shot yourself, you probably want to be TFed so don't bother with prefs.
if(!M.allow_spontaneous_tf && !tf_admin_pref_override)
return
if(M.tf_mob_holder)
var/mob/living/ourmob = M.tf_mob_holder
if(ourmob.ai_holder)
var/datum/ai_holder/our_AI = ourmob.ai_holder
our_AI.set_stance(STANCE_IDLE)
M.tf_mob_holder = null
ourmob.ckey = M.ckey
var/turf/get_dat_turf = get_turf(target)
ourmob.loc = get_dat_turf
ourmob.forceMove(get_dat_turf)
ourmob.vore_selected = M.vore_selected
M.vore_selected = null
for(var/obj/belly/B as anything in M.vore_organs)
B.loc = ourmob
B.forceMove(ourmob)
B.owner = ourmob
M.vore_organs -= B
ourmob.vore_organs += B
ourmob.Life(1)
if(ishuman(M))
for(var/obj/item/W in M)
if(istype(W, /obj/item/implant/backup) || istype(W, /obj/item/nif))
continue
M.drop_from_inventory(W)
qdel(target)
return
else
if(M.stat == DEAD) //We can let it undo the TF, because the person will be dead, but otherwise things get weird.
return
var/mob/living/new_mob = spawn_mob(M)
new_mob.faction = M.faction
if(new_mob && isliving(new_mob))
for(var/obj/belly/B as anything in new_mob.vore_organs)
new_mob.vore_organs -= B
qdel(B)
new_mob.vore_organs = list()
new_mob.name = M.name
new_mob.real_name = M.real_name
for(var/lang in M.languages)
new_mob.languages |= lang
M.copy_vore_prefs_to_mob(new_mob)
new_mob.vore_selected = M.vore_selected
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(ishuman(new_mob))
var/mob/living/carbon/human/N = new_mob
N.gender = H.gender
N.identifying_gender = H.identifying_gender
else
new_mob.gender = H.gender
else
new_mob.gender = M.gender
if(ishuman(new_mob))
var/mob/living/carbon/human/N = new_mob
N.identifying_gender = M.gender
for(var/obj/belly/B as anything in M.vore_organs)
B.loc = new_mob
B.forceMove(new_mob)
B.owner = new_mob
M.vore_organs -= B
new_mob.vore_organs += B
new_mob.ckey = M.ckey
if(M.ai_holder && new_mob.ai_holder)
var/datum/ai_holder/old_AI = M.ai_holder
old_AI.set_stance(STANCE_SLEEP)
var/datum/ai_holder/new_AI = new_mob.ai_holder
new_AI.hostile = old_AI.hostile
new_AI.retaliate = old_AI.retaliate
M.loc = new_mob
M.forceMove(new_mob)
new_mob.tf_mob_holder = M
spawn(30 SECONDS)
new_mob.revert_mob_tf() //TF them back after 30 seconds, basically takes them out of the fight for a short time.
/obj/item/projectile/beam/mouselaser/ddraig/spawn_mob(var/mob/living/target)
var/list/tf_list = list(/mob/living/simple_mob/animal/passive/mouse,
/mob/living/simple_mob/animal/passive/mouse/rat,
/mob/living/simple_mob/vore/alienanimals/dustjumper,
/mob/living/simple_mob/vore/woof,
/mob/living/simple_mob/animal/passive/dog/corgi,
/mob/living/simple_mob/animal/passive/cat,
/mob/living/simple_mob/animal/passive/chicken,
/mob/living/simple_mob/animal/passive/cow,
/mob/living/simple_mob/animal/passive/lizard,
/mob/living/simple_mob/vore/rabbit,
/mob/living/simple_mob/animal/passive/fox,
/mob/living/simple_mob/vore/fennec,
/mob/living/simple_mob/animal/passive/fennec,
/mob/living/simple_mob/vore/fennix,
/mob/living/simple_mob/vore/redpanda,
/mob/living/simple_mob/animal/passive/opossum,
/mob/living/simple_mob/vore/horse,
/mob/living/simple_mob/animal/space/goose,
/mob/living/simple_mob/vore/sheep)
tf_type = pick(tf_list)
if(!ispath(tf_type))
return
var/new_mob = new tf_type(get_turf(target))
return new_mob
/datum/ai_holder/simple_mob/vore/ddraig
var/used_invis = 0
can_flee = TRUE
flee_when_dying = FALSE
/datum/ai_holder/simple_mob/vore/find_target(list/possible_targets, has_targets_list)
if(!vore_hostile)
return ..()
if(!isanimal(holder)) //Only simplemobs have the vars we need
return ..()
var/mob/living/simple_mob/H = holder
if(H.vore_fullness >= H.vore_capacity) //Don't beat people up if we're full
return ..()
ai_log("find_target() : Entered.", AI_LOG_TRACE)
. = list()
if(!has_targets_list)
possible_targets = list_targets()
var/list/valid_mobs = list()
for(var/mob/living/possible_target in possible_targets)
if(!can_attack(possible_target))
continue
if(istype(target,/mob/living/simple_mob) && !check_attacker(target)) //Do not target simple mobs who didn't attack you (disengage with TF'd mobs)
continue
. |= possible_target
if(!isliving(possible_target))
continue
if(vore_check(possible_target))
valid_mobs |= possible_target
var/new_target
if(valid_mobs.len)
new_target = pick(valid_mobs)
else if(hostile)
new_target = pick(.)
if(!new_target)
return null
give_target(new_target)
return new_target
/datum/ai_holder/simple_mob/vore/ddraig/engage_target()
ai_log("engage_target() : Entering.", AI_LOG_DEBUG)
if(holder.cloaked)
set_stance(STANCE_FLEE)
return
if((holder.health < (holder.maxHealth / 4)) && !used_invis)
holder.cloak()
used_invis = 1
step_away(holder, target, 8)
step_away(holder, target, 8)
step_away(holder, target, 8)
step_away(holder, target, 8)
step_away(holder, target, 8)
spawn(60 SECONDS)
holder.uncloak()
if(istype(target,/mob/living/simple_mob) && !check_attacker(target)) //Immediately disengage with TF'd mobs so you don't one shot the poor guy you turned into a mouse.
lose_target()
// Can we still see them?
if(!target || !can_attack(target))
ai_log("engage_target() : Lost sight of target.", AI_LOG_TRACE)
if(lose_target()) // We lost them (returns TRUE if we found something else to do)
ai_log("engage_target() : Pursuing other options (last seen, or a new target).", AI_LOG_TRACE)
return
var/distance = get_dist(holder, target)
ai_log("engage_target() : Distance to target ([target]) is [distance].", AI_LOG_TRACE)
holder.face_atom(target)
last_conflict_time = world.time
// Do a 'special' attack, if one is allowed.
// if(prob(special_attack_prob) && (distance >= special_attack_min_range) && (distance <= special_attack_max_range))
if(holder.ICheckSpecialAttack(target))
ai_log("engage_target() : Attempting a special attack.", AI_LOG_TRACE)
on_engagement(target)
if(special_attack(target)) // If this fails, then we try a regular melee/ranged attack.
ai_log("engage_target() : Successful special attack. Exiting.", AI_LOG_DEBUG)
return
// Stab them.
else if(distance <= 1 && !pointblank)
ai_log("engage_target() : Attempting a melee attack.", AI_LOG_TRACE)
on_engagement(target)
melee_attack(target)
else if(distance <= 1 && !holder.ICheckRangedAttack(target)) // Doesn't have projectile, but is pointblank
ai_log("engage_target() : Attempting a melee attack.", AI_LOG_TRACE)
on_engagement(target)
melee_attack(target)
// Shoot them.
else if(holder.ICheckRangedAttack(target) && (distance <= max_range(target)) )
on_engagement(target)
if(firing_lanes && !test_projectile_safety(target))
// Nudge them a bit, maybe they can shoot next time.
var/turf/T = get_step(holder, pick(cardinal))
if(T)
holder.IMove(T) // IMove() will respect movement cooldown.
holder.face_atom(target)
ai_log("engage_target() : Could not safely fire at target. Exiting.", AI_LOG_DEBUG)
return
ai_log("engage_target() : Attempting a ranged attack.", AI_LOG_TRACE)
ranged_attack(target)
// Run after them.
else if(!stand_ground)
ai_log("engage_target() : Target ([target]) too far away. Exiting.", AI_LOG_DEBUG)
set_stance(STANCE_APPROACH)
////////////////////////////Player controlled verbs///////////////////////////////
/mob/living/proc/polymorph()
set name = "Polymorph"
set desc = "Take the form of a non-humanoid creature."
set category = "Abilities"
var/list/beast_options = list("Rabbit" = /mob/living/simple_mob/vore/rabbit,
"Red Panda" = /mob/living/simple_mob/vore/redpanda,
"Fennec" = /mob/living/simple_mob/vore/fennec,
"Giant Frog" = /mob/living/simple_mob/vore/aggressive/frog,
"Giant Rat" = /mob/living/simple_mob/vore/aggressive/rat,
"Wolf" = /mob/living/simple_mob/vore/wolf,
"Dire Wolf" = /mob/living/simple_mob/vore/wolf/direwolf,
"Fox" = /mob/living/simple_mob/animal/passive/fox/beastmode,
"Panther" = /mob/living/simple_mob/vore/aggressive/panther,
"Giant Snake" = /mob/living/simple_mob/vore/aggressive/giant_snake,
"Otie" = /mob/living/simple_mob/vore/otie,
"Squirrel" = /mob/living/simple_mob/vore/squirrel,
"Raptor" = /mob/living/simple_mob/vore/raptor,
"Giant Bat" = /mob/living/simple_mob/vore/bat,
"Horse" = /mob/living/simple_mob/vore/horse,
"Horse (Big)" = /mob/living/simple_mob/vore/horse/big,
"Kelpie" = /mob/living/simple_mob/vore/horse/kelpie,
"Bear" = /mob/living/simple_mob/animal/space/bear/brown/beastmode,
"Seagull" = /mob/living/simple_mob/vore/seagull,
"Sheep" = /mob/living/simple_mob/vore/sheep,
"Azure Tit" = /mob/living/simple_mob/animal/passive/bird/azure_tit/beastmode,
"Robin" = /mob/living/simple_mob/animal/passive/bird/european_robin/beastmode,
"Cat" = /mob/living/simple_mob/animal/passive/cat/black/beastmode,
"Tamaskan Dog" = /mob/living/simple_mob/animal/passive/dog/tamaskan,
"Corgi" = /mob/living/simple_mob/animal/passive/dog/corgi,
"Bull Terrier" = /mob/living/simple_mob/animal/passive/dog/bullterrier,
"Duck" = /mob/living/simple_mob/animal/sif/duck,
"Cow" = /mob/living/simple_mob/animal/passive/cow,
"Chicken" = /mob/living/simple_mob/animal/passive/chicken,
"Goat" = /mob/living/simple_mob/animal/goat,
"Penguin" = /mob/living/simple_mob/animal/passive/penguin,
"Goose" = /mob/living/simple_mob/animal/space/goose
)
var/chosen_beast = tgui_input_list(src, "Which form would you like to take?", "Choose Beast Form", beast_options)
if(!chosen_beast)
return
var/mob/living/M = src
log_debug("polymorph start")
if(!istype(M))
log_debug("polymorph istype")
return
if(M.stat) //We can let it undo the TF, because the person will be dead, but otherwise things get weird.
log_debug("polymorph stat")
to_chat(src, span_warning("You can't do that in your condition."))
return
if(M.health <= 10) //We can let it undo the TF, because the person will be dead, but otherwise things get weird.
log_debug("polymorph injured")
to_chat(src, span_warning("You are too injured to transform into a beast."))
return
visible_message("<b>\The [src]</b> begins significantly shifting their form.")
if(!do_after(src, 10 SECONDS, src, exclusive = TASK_USER_EXCLUSIVE))
visible_message("<b>\The [src]</b> ceases shifting their form.")
return 0
var/image/coolanimation = image('icons/obj/glamour.dmi', null, "animation")
coolanimation.plane = PLANE_LIGHTING_ABOVE
src.overlays += coolanimation
spawn(10)
src.overlays -= coolanimation
log_debug("polymorph not dead")
var/mob/living/new_mob = spawn_polymorph_mob(beast_options[chosen_beast])
new_mob.faction = M.faction
if(new_mob && isliving(new_mob))
log_debug("polymorph new_mob")
for(var/obj/belly/B as anything in new_mob.vore_organs)
log_debug("polymorph new_mob belly")
new_mob.vore_organs -= B
qdel(B)
new_mob.vore_organs = list()
new_mob.name = M.name
new_mob.real_name = M.real_name
new_mob.verbs |= /mob/living/proc/revert_beast_form
new_mob.verbs |= /mob/living/proc/set_size
for(var/lang in M.languages)
new_mob.languages |= lang
M.copy_vore_prefs_to_mob(new_mob)
new_mob.vore_selected = M.vore_selected
if(ishuman(M))
log_debug("polymorph ishuman part2")
var/mob/living/carbon/human/H = M
if(ishuman(new_mob))
log_debug("polymorph ishuman(newmob)")
var/mob/living/carbon/human/N = new_mob
N.gender = H.gender
N.identifying_gender = H.identifying_gender
else
log_debug("polymorph gender else")
new_mob.gender = H.gender
else
log_debug("polymorph gender else 2")
new_mob.gender = M.gender
if(ishuman(new_mob))
var/mob/living/carbon/human/N = new_mob
N.identifying_gender = M.gender
for(var/obj/belly/B as anything in M.vore_organs)
B.loc = new_mob
B.forceMove(new_mob)
B.owner = new_mob
M.vore_organs -= B
new_mob.vore_organs += B
new_mob.ckey = M.ckey
if(M.ai_holder && new_mob.ai_holder)
var/datum/ai_holder/old_AI = M.ai_holder
old_AI.set_stance(STANCE_SLEEP)
var/datum/ai_holder/new_AI = new_mob.ai_holder
new_AI.hostile = old_AI.hostile
new_AI.retaliate = old_AI.retaliate
M.loc = new_mob
M.forceMove(new_mob)
new_mob.tf_mob_holder = M
new_mob.visible_message("<b>\The [src]</b> has transformed into \the [chosen_beast]!")
/mob/living/proc/spawn_polymorph_mob(var/chosen_beast)
log_debug("polymorph proc spawn mob")
var/tf_type = chosen_beast
log_debug("polymorph [tf_type]")
if(!ispath(tf_type))
log_debug("polymorph tf_type fail")
return
log_debug("polymorph tf_type pass")
var/new_mob = new tf_type(get_turf(src))
return new_mob
/mob/living/proc/glamour_invisibility()
set name = "Invisibility"
set desc = "Change your appearance to match your surroundings, becoming completely invisible to the naked eye."
set category = "Abilities"
if(stat)
to_chat(src, span_warning("You can't go invisible when weakened like this."))
return
if(!cloaked)
cloak()
to_chat(src, span_warning("Your skin shimmers and shifts around you, hiding you from the naked eye."))
else
uncloak()
to_chat(src, span_warning("The shifting of your skin settles down and you become visible once again."))

View File

@@ -0,0 +1,219 @@
/mob/living/simple_mob/vore/fluffball
name = "fluffball"
desc = "A small, rotund humanoid creature. It is difficult to make out physical features of it as it covers most of its face behind big floppy, fluffy ears with only beady yellow eyes looking out. Most of its body is covered by a thick, soft tail that it wraps around itself and holds onto with small stumpy arms."
catalogue_data = list(/datum/category_item/catalogue/fauna/fluffball)
tt_desc = "glamoris fluffalia"
icon = 'icons/mob/vore.dmi'
icon_dead = "fluffball-dead"
icon_living = "fluffball"
icon_state = "fluffball"
faction = FACTION_SCRUBBLE
friendly = list("nudges", "sniffs on", "rumbles softly at", "nuzzles")
response_help = "bumps"
response_disarm = "shoves"
response_harm = "attacks"
movement_cooldown = 0
harm_intent_damage = 2
melee_damage_lower = 1
melee_damage_upper = 4
maxHealth = 50
attacktext = list("tail whips")
see_in_dark = 8
minbodytemp = 0
ai_holder_type = /datum/ai_holder/simple_mob/hostile/fluffball
say_list_type = /datum/say_list/fluffball
faction = FACTION_GLAMOUR
vore_bump_chance = 25
vore_digest_chance = 50
vore_escape_chance = 5
vore_pounce_chance = 1000
vore_active = 1
vore_icons = 1
vore_icons = SA_ICON_LIVING
vore_capacity = 1
swallowTime = 50
vore_ignores_undigestable = FALSE
vore_default_mode = DM_SELECT
vore_pounce_maxhealth = 1000
vore_bump_emote = "pounces on"
vore_pounce_falloff = 0 //Always eat someone at full health
vore_standing_too = 1
/mob/living/simple_mob/vore/fluffball/init_vore()
//CHONOEdit Start
if(!voremob_loaded)
return
.=..()
//CHONOEdit End
var/obj/belly/B = vore_selected
B.name = "tail"
B.desc = "The small critter seems to suddenly panic, lunging at you with its massive fluffy tail, using it like a weapon. Despite the appearance of the tail, it seems to be much larger on the inside, suddenly engulfing you completely in a world of endless softness. Inside, you are bound up nice and tight in an oddly comfortable prison of hair, it ripples over your body tickling every bit of exposed body on offer."
B.mode_flags = DM_FLAG_THICKBELLY
B.belly_fullscreen = "yet_another_tumby"
B.digest_brute = 1
B.digest_burn = 1
B.digest_oxy = 0
B.digestchance = 10
B.absorbchance = 60
B.escapechance = 10
B.selective_preference = DM_ABSORB
B.escape_stun = 5
B.transferlocation_absorb = "fluff"
var/obj/belly/fluff = new /obj/belly(src)
fluff.immutable = TRUE
fluff.name = "fluff"
fluff.desc = "You find yourself sinking deeper and deeper into the fluff around you, steadily it wraps around your entire body, binding you up. It seems to grow tighter and tigher forever, although never to the point of discomfort. Before long, the tightness goes beyond a physical sensation, it starts to feel like it buries into you, becoming part of you. It is becoming hard to discern yourself from the fluff, you feel floaty, wavy and soft yourself. Eventually, you can't feel yourself at all, there's nothing but fur. Every movement you make feels pointless, simply causing the slightest rustling of fluff as though the hair was moving on its own."
fluff.digest_mode = DM_HOLD // like, shes got you already, doesn't need to get you more
fluff.mode_flags = DM_FLAG_FORCEPSAY
fluff.escapable = TRUE // good luck
fluff.escapechance = 40 // high chance of STARTING a successful escape attempt
fluff.escapechance_absorbed = 5 // m i n e
fluff.vore_verb = "soak"
fluff.count_absorbed_prey_for_sprite = FALSE
fluff.absorbed_struggle_messages_inside = list(
"You try and push free from %pred's %belly, but can't seem to will yourself to move.",
"Your fruitless mental struggles only cause %pred to giggle lightly.",
"You can't make any progress freeing yourself from %pred's %belly.")
fluff.escape_attempt_absorbed_messages_owner = list(
"%prey is attempting to free themselves from your %belly!")
fluff.escape_attempt_absorbed_messages_prey = list(
"You try to force yourself out of %pred's %belly.",
"You strain and push, attempting to reach out of %pred's %belly.",
"You work up the will to try and force yourself free of %pred's clutches.")
fluff.escape_absorbed_messages_owner = list(
"%prey forces themselves free of your %belly!")
fluff.escape_absorbed_messages_prey = list(
"You finally manage to wrest yourself free from %pred's %belly, re-asserting your more usual form.",
"You heave and push, eventually spilling out from %pred's %belly, eliciting a happy chirp from your former captor.")
fluff.escape_absorbed_messages_outside = list(
"%prey suddenly forces themselves free of %pred's %belly!")
fluff.escape_fail_absorbed_messages_owner = list(
"%prey's attempt to escape form your %belly has failed!")
fluff.escape_fail_absorbed_messages_prey = list(
"Before you manage to reach freedom, you feel yourself getting dragged back into %pred's %belly!",
"%pred laughs lightly, simply pressing your wrigging form back into her %belly before you get anywhere.",
"Try as you might, you barely make an impression before %pred simply clenches with the most minimal effort, binding you back into her %belly.",
"Unfortunately, %pred seems to have absolutely no intention of letting you go, and your futile effort goes nowhere.",
"Strain as you might, you can't keep up the effort long enough before you sink back into %pred's %belly.")
/datum/say_list/fluffball
emote_hear = list("makes a shy squeal","whimpers","lets out a little squeak")
emote_see = list("hides its face","cuddles up to its own tail","stands there awkwardly","avoids eye contact")
/datum/category_item/catalogue/fauna/fluffball
name = "Extra-Realspace Fauna - Fluffball"
desc = "Classification: Glamoris Fluffalia\
<br><br>\
A stout creature with an apparently quite round figure, known to habit the location known as the Glamour. It is generally difficult to identify any physical features on the creature \
due to its anxiety around other creatures, it hides itself beneath its heavily furred ears and tail. Most creatures that approach it will find the fluffball fleeing quickly, \
though it is known to act more calm around those carrying food, which it is quick to steal from people's hands if offered. However, they have been observed to use their tails as weapons when panicked and unable to flee."
value = CATALOGUER_REWARD_HARD
/mob/living/simple_mob/vore/fluffball/PounceTarget(var/mob/living/M, var/successrate = 100)
vore_pounce_cooldown = world.time + 20 SECONDS // don't attempt another pounce for a while
if(prob(successrate)) // pounce success!
M.Weaken(5)
M.visible_message("<span class='danger'>\The [src] pounces on \the [M]!</span>!")
else // pounce misses!
M.visible_message("<span class='danger'>\The [src] attempts to pounce \the [M] but misses!</span>!")
playsound(src, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
if(will_eat(M) && (!M.canmove || vore_standing_too)) //if they're edible then eat them too
return EatTarget(M)
else
return //just leave them
/mob/living/simple_mob/vore/fluffball/attackby(obj/item/W as obj, mob/user as mob)
..()
if(istype(W,/obj/item/reagent_containers/food))
user.drop_item(W)
qdel(W)
visible_message("<span class='notice'>\The [src] quickly steals \the [W] into its fluff, it seems to have become a little less shy!</span>!")
var/datum/ai_holder/simple_mob/hostile/fluffball/A = ai_holder
if(istype(A))
A.friend_list |= user
//AI
/datum/ai_holder/simple_mob/hostile/fluffball
can_flee = TRUE
vision_range = 3 //Only react if you get close
can_flee = TRUE // If they're even allowed to flee.
flee_when_dying = TRUE // If they should flee when low on health.
dying_threshold = 1.1 // Flee at max health
var/list/friend_list = list()
/datum/ai_holder/simple_mob/hostile/fluffball/flee_from_target()
ai_log("flee_from_target() : Entering.", AI_LOG_DEBUG)
if(!target || !should_flee() || !can_attack(target)) // can_attack() is used since it checks the same things we would need to anyways.
ai_log("flee_from_target() : Lost target to flee from.", AI_LOG_INFO)
lose_target()
set_stance(STANCE_IDLE)
ai_log("flee_from_target() : Exiting.", AI_LOG_DEBUG)
return
var/mob/living/simple_mob/vore/H = holder
var/mob/living/L = target
var/distance = get_dist(holder, target)
if(distance <= 1)
if(H.will_eat(L) && H.CanPounceTarget(L))
H.face_atom(L)
H.PounceTarget(L)
return
ai_log("flee_from_target() : Stepping away.", AI_LOG_TRACE)
step_away(holder, target, 5)
ai_log("flee_from_target() : Exiting.", AI_LOG_DEBUG)
/datum/ai_holder/simple_mob/hostile/fluffball/find_target(list/possible_targets, has_targets_list)
if(!isanimal(holder)) //Only simplemobs have the vars we need
return ..()
var/list/L = list()
if(!has_targets_list)
possible_targets = list_targets()
var/list/valid_mobs = list()
for(var/mob/living/possible_target in possible_targets)
var/mob/living/carbon/human/H = possible_target
if(istype(H))
var/obj/item/reagent_containers/food/B = H.get_active_hand()
var/obj/item/reagent_containers/food/R = H.get_inactive_hand()
if(istype(R) || istype(B))
continue
if(!can_attack(possible_target))
continue
if((possible_target in friend_list) && !check_attacker(possible_target))
continue
L |= possible_target
if(!isliving(possible_target))
continue
if(vore_check(possible_target))
valid_mobs |= possible_target
var/new_target
if(valid_mobs.len)
new_target = pick(valid_mobs)
else if(hostile && L.len)
new_target = pick(L)
if(!new_target)
return null
give_target(new_target)
return new_target
/datum/ai_holder/simple_mob/vore/fluffball
vision_range = 4
hostile = FALSE
retaliate = TRUE
vore_hostile = FALSE
forgive_resting = TRUE
cooperative = FALSE

View File

@@ -0,0 +1,79 @@
/mob/living/simple_mob/vore/horse/unicorn
name = "unicorn"
icon_state = "unicorn"
icon_living = "unicorn"
icon_dead = "unicorn-dead"
icon = 'icons/mob/vore64x64.dmi'
desc = "A bright white horse-like creature with a golden horn protruding from its forehead. It's mane and hooves is a similarly golden."
tt_desc = "Equus unicornis"
vore_capacity = 2
maxHealth = 250
health = 250
meat_amount = 10
old_x = -16
old_y = 0
default_pixel_x = -16
pixel_x = -16
pixel_y = 0
mount_offset_y = 22
say_list_type = /datum/say_list/horse/unicorn
ai_holder_type = /datum/ai_holder/simple_mob/vore
minbodytemp = 0
movement_cooldown = 1
vore_bump_chance = 75
vore_pounce_chance = 75
vore_pounce_maxhealth = 200
vore_bump_emote = "chomps down on"
faction = FACTION_GLAMOUR
projectiletype = /obj/item/projectile/beam/rainbow
projectilesound = 'sound/weapons/sparkle.ogg'
projectile_dispersion = 7
projectile_accuracy = -20
/mob/living/simple_mob/vore/horse/unicorn/init_vore()
//CHONOEdit Start
if(!voremob_loaded)
return
.=..()
//CHONOEdit End
var/obj/belly/B = vore_selected
B.name = "stomach"
B.desc = "With a final few gulps, the unicorn finishes swallowing you down into its hot, humid gut... and with a slosh, your weight makes the equine's belly hang down slightly like some sort of organic hammock. The thick, damp air is tinged with the smell of... candyfloss(?), and the surrounding flesh wastes no time in clenching and massaging down over its newfound fodder."
B.digest_brute = 3
B.digest_burn = 3
B.digestchance = 40
B.absorbchance = 1
B.escapechance = 7
B.escape_stun = 5
B.emote_lists[DM_HOLD] = list(
"The unicorn's idle trotting helps its stomach gently churn around you, slimily squelching against your figure.",
"The equine predator takes a moment to intentionally clench its gut around you, encapsulating you in a strange, fleshy hug.",
"Some hot, viscous slime oozes down over your form, helping slicken you up during your stay.",
"During a moment of relative silence, you can hear the beast's soft, relaxed breathing as it casually goes about its day.",
"The thick, humid atmosphere within the unicorn's hanging belly works in tandem with its steady, metronome-like heartbeat to soothe you.",
"Your surroundings sway from side to side as the unicorn trots about, as if it is showing off its newest catch.")
B.emote_lists[DM_DIGEST] = list(
"The unicorn huffs in annoyance before clenching those wrinkled walls tight against your form, grinding away at you!",
"As the beast trots about, you're forced to slip and slide around amidst a pool of thick digestive goop!",
"You can barely hear the unicorn let out a pleased nicker as its stomach eagerly gurgles around its newfound meal!",
"As the thinning air begins to make you feel dizzy, menacing bworps and grumbles fill that dark, constantly shifting organ!",
"The constant, rhythmic kneading and massaging starts to take its toll along with the muggy heat, making you feel weaker and weaker!",
"The unicorn happily trots around while digesting its meal, almost like it is trying to show off the hanging gut you've given it.")
/datum/say_list/horse/unicorn
speak = list("...","?")
emote_hear = list("makes some sort of sparkling sound","whinnies with the most beautiful sounds")
emote_see = list("twinkles prettily", "shakes its mane", "looks so very regal")
/mob/living/simple_mob/vore/horse/unicorn/hostile
ai_holder_type = /datum/ai_holder/simple_mob/ranged/aggressive/unicorn
/datum/ai_holder/simple_mob/ranged/aggressive/unicorn
pointblank = FALSE

View File

@@ -489,6 +489,17 @@
tracer_type = /obj/effect/projectile/tracer/darkmatter tracer_type = /obj/effect/projectile/tracer/darkmatter
impact_type = /obj/effect/projectile/impact/darkmatter impact_type = /obj/effect/projectile/impact/darkmatter
hud_state = "plasma_rifle_blast" hud_state = "plasma_rifle_blast"
/obj/item/projectile/beam/rainbow
name = "rainbow"
fire_sound = 'sound/weapons/sparkle.ogg'
icon_state = "rainbow"
light_color = "#ffffff"
muzzle_type = /obj/effect/projectile/muzzle/rainbow
tracer_type = /obj/effect/projectile/tracer/rainbow
impact_type = /obj/effect/projectile/impact/rainbow
hud_state = "laser"
damage = 20
// //
// Projectile Beam Definitions // Projectile Beam Definitions
// //

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 KiB

After

Width:  |  Height:  |  Size: 438 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 KiB

After

Width:  |  Height:  |  Size: 733 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 KiB

After

Width:  |  Height:  |  Size: 247 KiB

BIN
icons/mob/vore96x96.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -3460,7 +3460,11 @@
#include "code\modules\mob\living\simple_mob\subtypes\animal\space\worm.dm" #include "code\modules\mob\living\simple_mob\subtypes\animal\space\worm.dm"
#include "code\modules\mob\living\simple_mob\subtypes\blob\blob.dm" #include "code\modules\mob\living\simple_mob\subtypes\blob\blob.dm"
#include "code\modules\mob\living\simple_mob\subtypes\blob\spore.dm" #include "code\modules\mob\living\simple_mob\subtypes\blob\spore.dm"
#include "code\modules\mob\living\simple_mob\subtypes\glamour\blaidd.dm"
#include "code\modules\mob\living\simple_mob\subtypes\glamour\ddraig.dm"
#include "code\modules\mob\living\simple_mob\subtypes\glamour\fluffball.dm"
#include "code\modules\mob\living\simple_mob\subtypes\glamour\homunculus.dm" #include "code\modules\mob\living\simple_mob\subtypes\glamour\homunculus.dm"
#include "code\modules\mob\living\simple_mob\subtypes\glamour\unicorn.dm"
#include "code\modules\mob\living\simple_mob\subtypes\horror\bradley.dm" #include "code\modules\mob\living\simple_mob\subtypes\horror\bradley.dm"
#include "code\modules\mob\living\simple_mob\subtypes\horror\Eddy.dm" #include "code\modules\mob\living\simple_mob\subtypes\horror\Eddy.dm"
#include "code\modules\mob\living\simple_mob\subtypes\horror\horror .dm" #include "code\modules\mob\living\simple_mob\subtypes\horror\horror .dm"