Ashdrake noms (#2868)

* Initial commit

* probably a better way to check this

* It compiled boys. Let's see if it works.

* IT WAS ALL NULLS, BOYS

* Hooray, it's not broken anymore boys!

* Well it works, but we need transfer IDs to work

locating them post-initialize would help, probably. Then assigning their
links soon after.

* Bellies linked, autotransfer, LoseTarget

* half-thought sanity check needs to go away

* A few last minute tweaks.
This commit is contained in:
Poojawa
2017-09-21 06:29:08 -05:00
committed by GitHub
parent 5b38d23bfd
commit aec48daa0a
11 changed files with 239 additions and 39 deletions
+54 -31
View File
@@ -15,7 +15,7 @@
var/vore_verb = "ingest" // Verb for eating with this in messages
var/human_prey_swallow_time = 10 SECONDS // Time in deciseconds to swallow /mob/living/carbon/human
var/nonhuman_prey_swallow_time = 5 SECONDS // Time in deciseconds to swallow anything else
var/emoteTime = 300 // How long between stomach emotes at prey
var/emoteTime = 30 SECONDS // How long between stomach emotes at prey
var/digest_brute = 0 // Brute damage per tick in digestion mode
var/digest_burn = 1 // Burn damage per tick in digestion mode
var/digest_tickrate = 9 // Modulus this of air controller tick number to iterate gurgles on
@@ -25,15 +25,21 @@
var/digestchance = 0 // % Chance of stomach beginning to digest if prey struggles
// var/silenced = FALSE // Will the heartbeat/fleshy internal loop play?
var/escapechance = 0 // % Chance of prey beginning to escape if prey struggles.
var/transferchance = 0 // % Chance of prey being
var/can_taste = FALSE // If this belly prints the flavor of prey when it eats someone.
var/datum/belly/transferlocation = null // Location that the prey is released if they struggle and get dropped off.
var/tmp/digest_mode = DM_HOLD // Whether or not to digest. Default to not digest.
var/transferchance = 0 // % Chance of prey being transferred to transfer location when resisting
var/autotransferchance = 0 // % Chance of prey being autotransferred to transfer location
var/autotransferwait = 10 // Time between trying to transfer.
var/can_taste = FALSE // If this belly prints the flavor of prey when it eats someone.
var/tmp/digest_mode = DM_HOLD // Whether or not to digest. Default to not digest.
var/tmp/list/digest_modes = list(DM_HOLD,DM_DIGEST,DM_HEAL,DM_NOISY) // Possible digest modes
var/tmp/mob/living/owner // The mob whose belly this is.
var/tmp/list/internal_contents = list() // People/Things you've eaten into this belly!
var/tmp/is_full // Flag for if digested remeans are present. (for disposal messages)
var/tmp/emotePend = FALSE // If there's already a spawned thing counting for the next emote
var/tmp/mob/living/owner // The mob whose belly this is.
var/tmp/list/internal_contents = list() // People/Things you've eaten into this belly!
var/tmp/is_full // Flag for if digested remeans are present. (for disposal messages)
var/tmp/emotePend = FALSE // If there's already a spawned thing counting for the next emote
var/swallow_time = 10 SECONDS // for mob transfering automation
var/vore_capacity = 1 // The capacity (in people) this person can hold
// Don't forget to watch your commas at the end of each line if you change these.
var/list/struggle_messages_outside = list(
@@ -153,8 +159,41 @@
// if(B.silenced == FALSE) //this needs more testing later
prey << sound('sound/vore/prey/loop.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_PREYLOOP)
// Handle prey messages
if(inside_flavor)
to_chat(prey, "<span class='warning'><B>[src.inside_flavor]</B></span>")
if(isliving(prey))
var/mob/living/M = prey
if(can_taste && M.get_taste_message(0))
to_chat(owner, "<span class='notice'>[M] tastes of [M.get_taste_message(0)].</span>")
// Setup the autotransfer checks if needed
if(transferlocation && autotransferchance > 0)
addtimer(CALLBACK(src, /datum/belly/.proc/check_autotransfer, prey), autotransferwait)
/datum/belly/proc/check_autotransfer(var/mob/prey)
// Some sanity checks
if(transferlocation && (autotransferchance > 0) && (prey in internal_contents))
if(prob(autotransferchance))
// Double check transferlocation isn't insane
if(verify_transferlocation())
transfer_contents(prey, transferlocation)
else
// Didn't transfer, so wait before retrying
addtimer(CALLBACK(src, /datum/belly/.proc/check_autotransfer, prey), autotransferwait)
/datum/belly/proc/verify_transferlocation()
for(var/I in owner.vore_organs)
var/datum/belly/B = owner.vore_organs[I]
if(B == transferlocation)
return TRUE
for(var/I in owner.vore_organs)
var/datum/belly/B = owner.vore_organs[I]
if(B.name == transferlocation.name)
transferlocation = B
return TRUE
return FALSE
// Get the line that should show up in Examine message if the owner of this belly
// is examined. By making this a proc, we not only take advantage of polymorphism,
@@ -323,23 +362,9 @@
return
else if(prob(transferchance) && istype(transferlocation)) //Next, let's have it see if they end up getting into an even bigger mess then when they started.
var/location_found = FALSE
var/name_found = FALSE
for(var/I in owner.vore_organs)
var/datum/belly/B = owner.vore_organs[I]
if(B == transferlocation)
location_found = TRUE
break
var/location_ok = verify_transferlocation()
if(!location_found)
for(var/I in owner.vore_organs)
var/datum/belly/B = owner.vore_organs[I]
if(B.name == transferlocation.name)
name_found = TRUE
transferlocation = B
break
if(!location_found && !name_found)
if(!location_ok)
to_chat(owner, "<span class='warning'>Something went wrong with your belly transfer settings.</span>")
transferlocation = null
return
@@ -358,18 +383,14 @@
to_chat(R, "<span class='warning'>But make no progress in escaping [owner]'s [name].</span>")
to_chat(owner, "<span class='warning'>But appears to be unable to make any progress in escaping your [name].</span>")
return
//Transfers contents from one belly to another
/datum/belly/proc/transfer_contents(var/atom/movable/content, var/datum/belly/target, silent = 0)
if(!(content in internal_contents))
return
internal_contents.Remove(content)
target.internal_contents.Add(content)
if(isliving(content))
var/mob/living/M = content
if(target.inside_flavor)
to_chat(M, "<span class='notice'><B>[target.inside_flavor]</B></span>")
if(target.can_taste && M.get_taste_message(0))
to_chat(owner, "<span class='notice'>[M] tastes of [M.get_taste_message(0)].</span>")
// Re-use nom_mob
target.nom_mob(content, target.owner)
if(!silent)
for(var/mob/hearer in range(1,owner))
hearer << sound(target.vore_sound,volume=80)
@@ -398,6 +419,8 @@
dupe.escapechance = escapechance
dupe.transferchance = transferchance
dupe.transferlocation = transferlocation
dupe.autotransferchance = autotransferchance
dupe.autotransferwait = autotransferwait
//// Object-holding variables
//struggle_messages_outside - strings
+50
View File
@@ -91,3 +91,53 @@
playsound(get_turf(owner),"digest_pred",35,0,-6,0,channel=CHANNEL_PRED)
M.stop_sound_channel(CHANNEL_PRED)
M.playsound_local(get_turf(M), null, 45, S = prey_gurgle)
//////////////////////////DM_DRAGON /////////////////////////////////////
//because dragons need snowflake guts
if(digest_mode == DM_DRAGON)
for (var/mob/living/M in internal_contents)
if(prob(25))
M.stop_sound_channel(CHANNEL_PRED)
playsound(get_turf(owner),"digest_pred",50,0,-6,0,channel=CHANNEL_PRED)
M.stop_sound_channel(CHANNEL_PRED)
M.playsound_local(get_turf(M), null, 45, S = prey_gurgle)
//No digestion protection for megafauna.
//Person just died in guts!
if(M.stat == DEAD)
var/digest_alert_owner = pick(digest_messages_owner)
var/digest_alert_prey = pick(digest_messages_prey)
//Replace placeholder vars
digest_alert_owner = replacetext(digest_alert_owner,"%pred",owner)
digest_alert_owner = replacetext(digest_alert_owner,"%prey",M)
digest_alert_owner = replacetext(digest_alert_owner,"%belly",lowertext(name))
digest_alert_prey = replacetext(digest_alert_prey,"%pred",owner)
digest_alert_prey = replacetext(digest_alert_prey,"%prey",M)
digest_alert_prey = replacetext(digest_alert_prey,"%belly",lowertext(name))
//Send messages
to_chat(owner, "<span class='warning'>[digest_alert_owner]</span>")
to_chat(M, "<span class='warning'>[digest_alert_prey]</span>")
M.visible_message("<span class='notice'>You watch as [owner]'s guts loudly rumble as it finishes off a meal.</span>")
M.stop_sound_channel(CHANNEL_PRED)
playsound(get_turf(owner),"death_pred",45,0,-6,0,channel=CHANNEL_PRED)
M.stop_sound_channel(CHANNEL_PRED)
M.playsound_local(get_turf(M), null, 45, S = prey_digest)
M.spill_organs(FALSE,TRUE,TRUE)
M << sound(null, repeat = 0, wait = 0, volume = 80, channel = CHANNEL_PREYLOOP)
digestion_death(M)
owner.update_icons()
continue
// Deal digestion damage (and feed the pred)
if(!(M.status_flags & GODMODE))
M.adjustFireLoss(digest_burn)
M.adjustToxLoss(4) // something something plasma based acids
M.adjustCloneLoss(3) // eventually this'll kill you if you're healing everything else, you nerds.
return
+37
View File
@@ -121,6 +121,42 @@
var/belly = input("Choose Belly") in pred.vore_organs
return perform_the_nom(user, prey, pred, belly)
//Dragon noms need to be faster
/mob/living/proc/dragon_feeding(var/mob/living/user, var/mob/living/prey)
var/belly = user.vore_selected
return perform_dragon(user, prey, user, belly)
/mob/living/proc/perform_dragon(var/mob/living/user, var/mob/living/prey, var/mob/living/pred, var/belly, swallow_time = 20)
//Sanity
if(!user || !prey || !pred || !belly || !(belly in pred.vore_organs))
return
// The belly selected at the time of noms
var/datum/belly/belly_target = pred.vore_organs[belly]
var/attempt_msg = "ERROR: Vore message couldn't be created. Notify a dev. (at)"
var/success_msg = "ERROR: Vore message couldn't be created. Notify a dev. (sc)"
// Prepare messages
if(user == pred) //Feeding someone to yourself
attempt_msg = text("<span class='warning'>[] starts to [] [] into their []!</span>",pred,lowertext(belly_target.vore_verb),prey,lowertext(belly_target.name))
success_msg = text("<span class='warning'>[] manages to [] [] into their []!</span>",pred,lowertext(belly_target.vore_verb),prey,lowertext(belly_target.name))
// Announce that we start the attempt!
user.visible_message(attempt_msg)
if(!do_mob(src, user, swallow_time)) // one second should be good enough, right?
return FALSE // Prey escaped (or user disabled) before timer expired.
// If we got this far, nom successful! Announce it!
user.visible_message(success_msg)
playsound(user, belly_target.vore_sound, 100, 1)
// Actually shove prey into the belly.
belly_target.nom_mob(prey, user)
if (pred == user)
message_admins("[key_name(pred)] ate [key_name(prey)].")
log_attack("[key_name(pred)] ate [key_name(prey)]")
return TRUE
//
// Master vore proc that actually does vore procedures
//
@@ -250,6 +286,7 @@
if(M.loc != src)
B.internal_contents.Remove(M)
// OOC Escape code for pref-breaking or AFK preds
//
/mob/living/proc/escapeOOC()
+1 -1
View File
@@ -27,7 +27,7 @@
//
/datum/vore_look
var/datum/belly/selected
var/show_interacts = FALSE
var/show_interacts = TRUE
var/datum/browser/popup
var/loop = null; // Magic self-reference to stop the handler from being GC'd before user takes action.