mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-27 22:18:27 +01:00
'Appendage Vore' AKA - Tongue Vore/Long Vore
- Credit to VerySoft for the tongue sprites! - Adds in 'Long Vore' a selectable neutral trait that allows you to throw out your 'appendage' at a target. (5 tiles). Respects prefs. - Gives frogs the special attack to do this as well. - Adds in an admin-spawn gun that allows you to shoot the 'appendage' projectile as if you had the trait. Doesn't respect prefs, obviously. Will detail this out more in the PR.
This commit is contained in:
+183
-1
@@ -1152,4 +1152,186 @@
|
||||
target.visible_message("<span class='warning'>\The [target] suddenly disappears, being dragged into the water!</span>",\
|
||||
"<span class='danger'>You are dragged below the water and feel yourself slipping directly into \the [src]'s [vore_selected]!</span>")
|
||||
to_chat(src, "<span class='notice'>You successfully drag \the [target] into the water, slipping them into your [vore_selected].</span>")
|
||||
target.forceMove(src.vore_selected)
|
||||
target.forceMove(src.vore_selected)
|
||||
|
||||
|
||||
//This is the 'long vore' ability. Also known as "Grab Prey with appendage" or "Long Predatorial Reach". Or simply "Tongue Vore"
|
||||
//It involves projectiles (which means it can be VV'd onto a gun for shenanigans)
|
||||
//It can also be recolored via the proc, which persists between rounds.
|
||||
|
||||
/mob/living/proc/long_vore() // Allows the user to tongue grab a creature in range. Made a /living proc so frogs can frog you.
|
||||
set name = "Grab Prey with appendage"
|
||||
set category = "Abilities"
|
||||
set desc = "Grab a target with any of your appendages!"
|
||||
|
||||
if(stat || paralysis || weakened || stunned || world.time < last_special) //No tongue flicking while stunned.
|
||||
to_chat(src, "<span class='warning'>You can't do that in your current state.</span>")
|
||||
return
|
||||
|
||||
last_special = world.time + 10 //Anti-spam.
|
||||
|
||||
if (!istype(src, /mob/living))
|
||||
to_chat(src, "<span class='warning'>It doesn't work that way.</span>")
|
||||
return
|
||||
|
||||
var/choice = tgui_alert(src, "Do you wish to change the color of your appendage or use it?", "Selection List", list("Use it", "Color"))
|
||||
|
||||
if(choice == "Color") //Easy way to set color so we don't bloat up the menu with even more buttons.
|
||||
var/new_color = input(usr, "Choose a color to set your appendage to!", "", appendage_color) as color|null
|
||||
if(new_color)
|
||||
appendage_color = new_color
|
||||
else
|
||||
var/list/targets = list() //IF IT IS NOT BROKEN. DO NOT FIX IT.
|
||||
|
||||
for(var/mob/living/L in range(5, src))
|
||||
if(!istype(L, /mob/living)) //Don't eat anything that isn't mob/living. Failsafe.
|
||||
continue
|
||||
if(L == src) //no eating yourself. 1984.
|
||||
continue
|
||||
if(L.devourable && L.throw_vore && (L.can_be_drop_pred || L.can_be_drop_prey))
|
||||
targets += L
|
||||
|
||||
if(!(targets.len))
|
||||
to_chat(src, "<span class='notice'>No eligible targets found.</span>")
|
||||
return
|
||||
|
||||
var/mob/living/target = tgui_input_list(src, "Please select a target.", "Victim", targets)
|
||||
|
||||
if(!target)
|
||||
return
|
||||
|
||||
if(!istype(target, /mob/living)) //Safety.
|
||||
to_chat(src, "<span class='warning'>You need to select a living tarrget!</span>")
|
||||
return
|
||||
|
||||
if (get_dist(src,target) >= 6)
|
||||
to_chat(src, "<span class='warning'>You need to be closer to do that.</span>")
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>\The [src] attempts to snatch up [target]!</span>", \
|
||||
"<span class='notice'>You attempt to snatch up [target]!</span>" )
|
||||
playsound(src, 'sound/vore/sunesound/pred/schlorp.ogg', 25)
|
||||
|
||||
//Code to shoot the beam here.
|
||||
var/obj/item/projectile/beam/appendage/appendage_attack = new /obj/item/projectile/beam/appendage(get_turf(loc))
|
||||
appendage_attack.launch_projectile(target, BP_TORSO, src) //Send it.
|
||||
last_special = world.time + 100 //Cooldown for successful strike.
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/item/projectile/beam/appendage //The tongue projecitle.
|
||||
name = "appendage"
|
||||
icon_state = "laser"
|
||||
nodamage = 1
|
||||
damage = 0
|
||||
eyeblur = 0
|
||||
check_armour = "bullet" //Not really needed, but whatever.
|
||||
can_miss = FALSE //Let's not miss our tongue!
|
||||
hitsound = 'sound/vore/sunesound/pred/schlorp.ogg'
|
||||
hitsound_wall = 'sound/vore/sunesound/pred/schlorp.ogg'
|
||||
excavation_amount = 0
|
||||
hitscan_light_intensity = 0
|
||||
hitscan_light_range = 0
|
||||
muzzle_flash_intensity = 0
|
||||
muzzle_flash_range = 0
|
||||
impact_light_intensity = 0
|
||||
impact_light_range = 0
|
||||
light_range = 0 //No your tongue can not glow...For now.
|
||||
light_power = 0
|
||||
light_on = 0 //NO LIGHT
|
||||
combustion = FALSE //No, your tongue can't set the room on fire.
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
muzzle_type = /obj/effect/projectile/muzzle/appendage
|
||||
tracer_type = /obj/effect/projectile/tracer/appendage
|
||||
impact_type = /obj/effect/projectile/impact/appendage
|
||||
|
||||
/obj/item/projectile/beam/appendage/generate_hitscan_tracers()
|
||||
if(firer) //This neat little code block allows for C O L O R A B L E tongues! Correction: 'Appendages'
|
||||
if(istype(firer,/mob/living))
|
||||
var/mob/living/originator = firer
|
||||
color = originator.appendage_color
|
||||
..()
|
||||
|
||||
/obj/item/projectile/beam/appendage/on_hit(var/atom/target)
|
||||
if(target == firer) //NO EATING YOURSELF
|
||||
return
|
||||
if(istype(target, /mob/living))
|
||||
var/mob/living/M = target
|
||||
var/throw_range = get_dist(firer,M)
|
||||
if(istype(M))
|
||||
M.throw_at(firer, throw_range, M.throw_speed, firer) //Fun fact: living things have a throw_speed of 2.
|
||||
M.updateicon()
|
||||
else //Anything that isn't a /living
|
||||
return
|
||||
if(istype(target, /obj/item/)) //We hit an object? Pull it. This can only happen via admin shenanigans such as a gun being VV'd with this projectile.
|
||||
var/obj/item/hit_object = target
|
||||
if(hit_object.density || hit_object.anchored)
|
||||
if(istype(firer, /mob/living))
|
||||
var/mob/living/originator = firer
|
||||
originator.Weaken(2) //If you hit something dense or anchored, fall flat on your face.
|
||||
originator.visible_message("<span class='warning'>\The [originator] trips over their self and falls flat on their face!</span>", \
|
||||
"<span class='warning'>You trip over yourself and fall flat on your face!</span>" )
|
||||
playsound(originator, "punch", 25, 1, -1)
|
||||
return
|
||||
else
|
||||
hit_object.throw_at(firer, throw_range, hit_object.throw_speed, firer)
|
||||
if(istype(target, /turf/simulated/wall) || istype(target, /obj/machinery/door) || istype(target, /obj/structure/window)) //This can happen normally due to odd terrain. For some reason, it seems to not actually interact with walls.
|
||||
if(istype(firer, /mob/living))
|
||||
var/mob/living/originator = firer
|
||||
originator.Weaken(2) //Hit a wall? Whoops!
|
||||
originator.visible_message("<span class='warning'>\The [originator] trips over their self and falls flat on their face!</span>", \
|
||||
"<span class='warning'>You trip over yourself and fall flat on your face!</span>" )
|
||||
playsound(originator, "punch", 25, 1, -1)
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
|
||||
|
||||
/obj/effect/projectile/muzzle/appendage
|
||||
icon = 'icons/obj/projectiles_vr.dmi'
|
||||
icon_state = "muzzle_appendage"
|
||||
light_range = 0
|
||||
light_power = 0
|
||||
light_color = "#FF0D00"
|
||||
|
||||
/obj/effect/projectile/tracer/appendage
|
||||
icon = 'icons/obj/projectiles_vr.dmi'
|
||||
icon_state = "appendage_beam"
|
||||
light_range = 0
|
||||
light_power = 0
|
||||
light_color = "#FF0D00" //Doesn't matter. Not used.
|
||||
|
||||
/obj/effect/projectile/impact/appendage
|
||||
icon = 'icons/obj/projectiles_vr.dmi'
|
||||
icon_state = "impact_appendage_combined"
|
||||
light_range = 0
|
||||
light_power = 0
|
||||
light_color = "#FF0D00"
|
||||
//LONG VORE ABILITY END
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/tongue //This is the 'tongue' gun for admin memery.
|
||||
name = "tongue"
|
||||
desc = "A tongue that can be used to grab things."
|
||||
icon = 'icons/mob/dogborg_vr.dmi'
|
||||
icon_state = "synthtongue"
|
||||
item_state = "gun"
|
||||
fire_delay = null
|
||||
force = 0
|
||||
fire_delay = 1 //Adminspawn. No delay.
|
||||
charge_cost = 0 //This is an adminspawn gun...No reason to force it to have a charge state.
|
||||
|
||||
projectile_type = /obj/item/projectile/beam/appendage
|
||||
cell_type = /obj/item/weapon/cell/device/weapon/recharge
|
||||
battery_lock = 1
|
||||
modifystate = null
|
||||
|
||||
|
||||
firemodes = list(
|
||||
list(mode_name="vore", projectile_type=/obj/item/projectile/beam/appendage, modifystate=null, fire_sound='sound/vore/sunesound/pred/schlorp.ogg', charge_cost = 0),)
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/tongue/update_icon() //No updating the icon.
|
||||
icon_state = "synthtongue"
|
||||
return
|
||||
@@ -118,6 +118,16 @@
|
||||
H.verbs |= /mob/living/carbon/human/proc/succubus_drain_finalize
|
||||
H.verbs |= /mob/living/carbon/human/proc/succubus_drain_lethal
|
||||
|
||||
/datum/trait/neutral/long_vore
|
||||
name = "Long Predatorial Reach"
|
||||
desc = "Makes you able to use your tongue to grab creatures."
|
||||
cost = 0
|
||||
custom_only = FALSE
|
||||
|
||||
/datum/trait/neutral/long_vore/apply(var/datum/species/S,var/mob/living/carbon/human/H)
|
||||
..(S,H)
|
||||
H.verbs |= /mob/living/proc/long_vore
|
||||
|
||||
/datum/trait/neutral/feeder
|
||||
name = "Feeder"
|
||||
desc = "Allows you to feed your prey using your own body."
|
||||
|
||||
@@ -324,6 +324,26 @@
|
||||
src.anchored = TRUE
|
||||
src.pinned += O
|
||||
|
||||
//VORESTATION EDIT START - Allows for thrown vore!
|
||||
//Throwing a prey into a pred takes priority. After that it checks to see if the person being thrown is a pred.
|
||||
if(istype(AM, /mob/living))
|
||||
var/mob/living/thrown_mob = AM
|
||||
if((can_be_drop_pred && throw_vore) && (thrown_mob.devourable && thrown_mob.throw_vore && thrown_mob.can_be_drop_prey)) //Prey thrown into pred.
|
||||
vore_selected.nom_mob(thrown_mob) //Eat them!!!
|
||||
visible_message("<span class='warning'>[thrown_mob] is thrown right into [src]'s [lowertext(vore_selected.name)]!</span>")
|
||||
if(thrown_mob.loc != vore_selected)
|
||||
thrown_mob.forceMove(vore_selected) //Double check. Should never happen but...Weirder things have happened!
|
||||
add_attack_logs(thrown_mob.thrower,src,"Devoured [thrown_mob.name] via throw vore.")
|
||||
return //We can stop here. We don't need to calculate damage or anything else. They're eaten.
|
||||
else if((can_be_drop_prey && throw_vore && devourable) && (thrown_mob.can_be_drop_pred && thrown_mob.throw_vore)) //Pred thrown into prey.
|
||||
visible_message("<span class='warning'>[src] suddenly slips inside of [thrown_mob]'s [lowertext(thrown_mob.vore_selected.name)] as [thrown_mob] flies into them!</span>")
|
||||
thrown_mob.vore_selected.nom_mob(src) //Eat them!!!
|
||||
if(src.loc != thrown_mob.vore_selected)
|
||||
src.forceMove(thrown_mob.vore_selected) //Double check. Should never happen but...Weirder things have happened!
|
||||
add_attack_logs(thrown_mob.LAssailant,src,"Was Devoured by [thrown_mob.name] via throw vore.")
|
||||
return
|
||||
//VORESTATION EDIT END - Allows for thrown vore!
|
||||
|
||||
/mob/living/proc/embed(var/obj/O, var/def_zone=null)
|
||||
O.loc = src
|
||||
src.embedded += O
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
icon = 'icons/mob/vore.dmi'
|
||||
|
||||
movement_cooldown = 4 //fast as fucc boie.
|
||||
can_be_drop_pred = 1 //They can tongue vore.
|
||||
|
||||
meat_amount = 4
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
@@ -39,6 +40,10 @@
|
||||
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/melee
|
||||
|
||||
special_attack_min_range = 1
|
||||
special_attack_max_range = 5
|
||||
special_attack_cooldown = 100
|
||||
|
||||
// Pepe is love, not hate.
|
||||
/mob/living/simple_mob/vore/aggressive/frog/New()
|
||||
if(rand(1,1000000) == 1)
|
||||
@@ -46,6 +51,21 @@
|
||||
desc = "You found a rare Pepe. Screenshot for good luck."
|
||||
..()
|
||||
|
||||
/mob/living/simple_mob/vore/aggressive/frog/do_special_attack(atom/A)
|
||||
set_AI_busy(TRUE)
|
||||
do_windup_animation(A, 20)
|
||||
addtimer(CALLBACK(src, .proc/chargeend, A), 20)
|
||||
|
||||
/mob/living/simple_mob/vore/aggressive/frog/proc/chargeend(atom/A)
|
||||
if(stat) //you are dead
|
||||
set_AI_busy(FALSE)
|
||||
return
|
||||
playsound(src, 'sound/vore/sunesound/pred/schlorp.ogg', 25)
|
||||
var/obj/item/projectile/beam/appendage/appendage_attack = new /obj/item/projectile/beam/appendage(get_turf(loc))
|
||||
appendage_attack.old_style_target(A, src)
|
||||
appendage_attack.launch_projectile(A, BP_TORSO, src)
|
||||
set_AI_busy(FALSE)
|
||||
|
||||
// Activate Noms!
|
||||
/mob/living/simple_mob/vore/aggressive/frog
|
||||
vore_active = 1
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
permit_healbelly = client.prefs_vr.permit_healbelly
|
||||
noisy = client.prefs_vr.noisy
|
||||
selective_preference = client.prefs_vr.selective_preference
|
||||
appendage_color = client.prefs_vr.appendage_color
|
||||
|
||||
drop_vore = client.prefs_vr.drop_vore
|
||||
stumble_vore = client.prefs_vr.stumble_vore
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
var/vis_height = 32 // Sprite height used for resize features.
|
||||
var/show_vore_fx = TRUE // Show belly fullscreens
|
||||
var/selective_preference = DM_DEFAULT // Preference for selective bellymode
|
||||
var/appendage_color = "#e03997" //Default pink. Used for the 'long_vore' trait.
|
||||
var/regen_sounds = list(
|
||||
'sound/effects/mob_effects/xenochimera/regen_1.ogg',
|
||||
'sound/effects/mob_effects/xenochimera/regen_2.ogg',
|
||||
@@ -271,6 +272,7 @@
|
||||
P.can_be_drop_pred = src.can_be_drop_pred
|
||||
P.allow_inbelly_spawning = src.allow_inbelly_spawning
|
||||
P.allow_spontaneous_tf = src.allow_spontaneous_tf
|
||||
P.appendage_color = src.appendage_color
|
||||
P.step_mechanics_pref = src.step_mechanics_pref
|
||||
P.pickup_pref = src.pickup_pref
|
||||
P.drop_vore = src.drop_vore
|
||||
@@ -318,6 +320,7 @@
|
||||
can_be_drop_pred = P.can_be_drop_pred
|
||||
allow_inbelly_spawning = P.allow_inbelly_spawning
|
||||
allow_spontaneous_tf = P.allow_spontaneous_tf
|
||||
appendage_color = P.appendage_color
|
||||
step_mechanics_pref = P.step_mechanics_pref
|
||||
pickup_pref = P.pickup_pref
|
||||
drop_vore = P.drop_vore
|
||||
|
||||
@@ -70,6 +70,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
|
||||
var/list/belly_prefs = list()
|
||||
var/vore_taste = "nothing in particular"
|
||||
var/vore_smell = "nothing in particular"
|
||||
var/appendage_color = "#e03997" //Default pink. Used for the 'long_vore' trait.
|
||||
|
||||
var/selective_preference = DM_DEFAULT
|
||||
|
||||
@@ -171,6 +172,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
|
||||
vore_smell = json_from_file["vore_smell"]
|
||||
permit_healbelly = json_from_file["permit_healbelly"]
|
||||
noisy = json_from_file["noisy"]
|
||||
appendage_color = json_from_file["appendage_color"]
|
||||
selective_preference = json_from_file["selective_preference"]
|
||||
show_vore_fx = json_from_file["show_vore_fx"]
|
||||
can_be_drop_prey = json_from_file["can_be_drop_prey"]
|
||||
@@ -210,6 +212,8 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
|
||||
selective_preference = DM_DEFAULT
|
||||
if (isnull(noisy))
|
||||
noisy = FALSE
|
||||
if (isnull(appendage_color))
|
||||
appendage_color = "#e03997"
|
||||
if(isnull(show_vore_fx))
|
||||
show_vore_fx = TRUE
|
||||
if(isnull(can_be_drop_prey))
|
||||
@@ -283,6 +287,7 @@ V::::::V V::::::VO:::::::OOO:::::::ORR:::::R R:::::REE::::::EEEEEE
|
||||
"vore_smell" = vore_smell,
|
||||
"permit_healbelly" = permit_healbelly,
|
||||
"noisy" = noisy,
|
||||
"appendage_color" = appendage_color,
|
||||
"selective_preference" = selective_preference,
|
||||
"show_vore_fx" = show_vore_fx,
|
||||
"can_be_drop_prey" = can_be_drop_prey,
|
||||
|
||||
@@ -272,6 +272,7 @@
|
||||
"can_be_drop_pred" = host.can_be_drop_pred,
|
||||
"allow_inbelly_spawning" = host.allow_inbelly_spawning,
|
||||
"allow_spontaneous_tf" = host.allow_spontaneous_tf,
|
||||
"appendage_color" = host.appendage_color,
|
||||
"step_mechanics_active" = host.step_mechanics_pref,
|
||||
"pickup_mechanics_active" = host.pickup_pref,
|
||||
"noisy" = host.noisy,
|
||||
|
||||
@@ -231,6 +231,7 @@
|
||||
new_mob.permit_healbelly = permit_healbelly
|
||||
new_mob.noisy = noisy
|
||||
new_mob.selective_preference = selective_preference
|
||||
new_mob.appendage_color = appendage_color
|
||||
new_mob.drop_vore = drop_vore
|
||||
new_mob.stumble_vore = stumble_vore
|
||||
new_mob.slip_vore = slip_vore
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Reference in New Issue
Block a user