[MIRROR] Glamour mob pack (#9225)
Co-authored-by: Heroman3003 <31296024+Heroman3003@users.noreply.github.com> Co-authored-by: Kashargul <KashL@t-online.de>
@@ -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'
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
359
code/modules/mob/living/simple_mob/subtypes/glamour/blaidd.dm
Normal 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
|
||||||
590
code/modules/mob/living/simple_mob/subtypes/glamour/ddraig.dm
Normal 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."))
|
||||||
219
code/modules/mob/living/simple_mob/subtypes/glamour/fluffball.dm
Normal 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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
//
|
//
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 435 KiB After Width: | Height: | Size: 438 KiB |
|
Before Width: | Height: | Size: 708 KiB After Width: | Height: | Size: 733 KiB |
|
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 247 KiB |
BIN
icons/mob/vore96x96.dmi
Normal file
|
After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.3 KiB |
@@ -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"
|
||||||
|
|||||||