mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 16:47:13 +01:00
# Conflicts: # _maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm # _maps/RandomRuins/SpaceRuins/garbagetruck2.dmm # _maps/map_files/CatwalkStation/CatwalkStation_2023.dmm # _maps/map_files/tramstation/tramstation.dmm # code/_onclick/hud/new_player.dm # code/datums/components/squashable.dm # code/datums/diseases/advance/symptoms/heal.dm # code/datums/diseases/chronic_illness.dm # code/datums/status_effects/buffs.dm # code/datums/status_effects/debuffs/drunk.dm # code/datums/status_effects/debuffs/stamcrit.dm # code/game/machinery/computer/crew.dm # code/game/objects/items/devices/scanners/health_analyzer.dm # code/game/objects/items/wall_mounted.dm # code/game/turfs/closed/indestructible.dm # code/modules/admin/view_variables/filterrific.dm # code/modules/antagonists/heretic/influences.dm # code/modules/cargo/orderconsole.dm # code/modules/client/preferences.dm # code/modules/events/space_vines/vine_mutations.dm # code/modules/mob/dead/new_player/new_player.dm # code/modules/mob/living/carbon/human/death.dm # code/modules/mob/living/carbon/human/species_types/jellypeople.dm # code/modules/mob/living/damage_procs.dm # code/modules/mob/living/living.dm # code/modules/mob_spawn/ghost_roles/mining_roles.dm # code/modules/mob_spawn/mob_spawn.dm # code/modules/projectiles/ammunition/energy/laser.dm # code/modules/projectiles/guns/ballistic/launchers.dm # code/modules/projectiles/guns/energy/laser.dm # code/modules/reagents/chemistry/machinery/chem_dispenser.dm # code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm # code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm # code/modules/reagents/chemistry/reagents/medicine_reagents.dm # code/modules/surgery/healing.dm # code/modules/unit_tests/designs.dm # icons/mob/inhands/items_lefthand.dmi # icons/mob/inhands/items_righthand.dmi # tgui/packages/tgui/interfaces/ChemDispenser.tsx
198 lines
6.5 KiB
Plaintext
198 lines
6.5 KiB
Plaintext
GLOBAL_LIST_INIT(digest_modes, init_digest_modes())
|
|
|
|
/proc/init_digest_modes()
|
|
var/list/digest_modes = list()
|
|
for(var/datum/digest_mode/digest_mode as anything in subtypesof(/datum/digest_mode))
|
|
var/datum/digest_mode/DM = new digest_mode()
|
|
digest_modes[DM.name] = DM
|
|
return digest_modes
|
|
|
|
/datum/digest_mode
|
|
var/name = ""
|
|
var/gurgle_noises = FALSE
|
|
|
|
/datum/digest_mode/proc/handle_belly(obj/vore_belly/vore_belly, seconds_per_tick)
|
|
if(gurgle_noises)
|
|
vore_belly.try_play_gurgle_sound()
|
|
|
|
/datum/digest_mode/safe
|
|
name = DIGEST_MODE_SAFE
|
|
gurgle_noises = FALSE
|
|
|
|
/datum/digest_mode/digest
|
|
name = DIGEST_MODE_DIGEST
|
|
gurgle_noises = TRUE
|
|
|
|
/mob/living/proc/vore_can_negatively_affect()
|
|
if(REQUIRES_PLAYER)
|
|
return FALSE
|
|
if(mind)
|
|
// they were at some point a player, we don't digest them until they get back
|
|
return FALSE
|
|
// Animal, melt em
|
|
return TRUE
|
|
|
|
/mob/living/proc/vore_can_digest()
|
|
if(client)
|
|
var/datum/vore_preferences/vore_prefs = client.get_vore_prefs()
|
|
return vore_prefs?.read_preference(/datum/vore_pref/toggle/digestion)
|
|
|
|
return vore_can_negatively_affect()
|
|
|
|
/mob/living/proc/vore_can_qdel()
|
|
if(client)
|
|
var/datum/vore_preferences/vore_prefs = client.get_vore_prefs()
|
|
return vore_prefs?.read_preference(/datum/vore_pref/toggle/digestion_qdel)
|
|
|
|
return vore_can_negatively_affect()
|
|
|
|
/obj/machinery/cryopod/quiet/vore
|
|
name = "vore cryopod"
|
|
|
|
/obj/machinery/cryopod/quiet/vore/process()
|
|
return
|
|
|
|
/obj/machinery/cryopod/quiet/vore/find_control_computer(urgent)
|
|
return
|
|
|
|
GLOBAL_DATUM_INIT(vore_cryopod, /obj/machinery/cryopod/quiet/vore, new /obj/machinery/cryopod/quiet/vore(null))
|
|
|
|
// This is hilariously cursed
|
|
/proc/remove_player_from_round_safely(mob/living/L)
|
|
// Immediately kick them out of their body so they don't get ghosted in nullspace
|
|
L.ghostize(FALSE)
|
|
|
|
// Have to do this before we let the cryopod have them, or it'll throw all their items into nullspace without qdeling them
|
|
for(var/obj/item/item_content as anything in L)
|
|
if(!istype(item_content) || HAS_TRAIT(item_content, TRAIT_NODROP))
|
|
continue
|
|
if(issilicon(L) && istype(item_content, /obj/item/mmi))
|
|
continue
|
|
qdel(item_content)
|
|
|
|
GLOB.vore_cryopod.close_machine(L)
|
|
L = null // make sure we're not keeping a ref
|
|
GLOB.vore_cryopod.despawn_occupant()
|
|
|
|
/obj/vore_belly/proc/digestion_death(mob/living/L)
|
|
if(!L.vore_can_qdel())
|
|
return FALSE
|
|
var/mob/living/living_parent = owner.parent
|
|
|
|
if(fancy_sounds)
|
|
play_vore_sound_preypred("vore_sounds_death_fancy_prey", "vore_sounds_death_fancy", pref = /datum/vore_pref/toggle/digestion_noises)
|
|
else
|
|
play_vore_sound_preypred("vore_sounds_death_classic", "vore_sounds_death_classic", pref = /datum/vore_pref/toggle/digestion_noises)
|
|
living_parent.adjust_nutrition(NUTRITION_PER_KILL)
|
|
|
|
to_chat(living_parent, span_notice(get_digest_messages_pred(L)))
|
|
to_chat(L, span_notice(get_digest_messages_prey(L)))
|
|
|
|
living_parent.log_message("digested and qdel'd [key_name(L)].", LOG_ATTACK)
|
|
L.log_message("was digested and qdel'd by [key_name(living_parent)].", LOG_VICTIM)
|
|
|
|
remove_player_from_round_safely(L)
|
|
return TRUE
|
|
|
|
/datum/digest_mode/digest/handle_belly(obj/vore_belly/vore_belly, seconds_per_tick)
|
|
var/mob/living/living_parent = vore_belly.owner.parent
|
|
|
|
for(var/mob/living/L in vore_belly)
|
|
if(!L.vore_can_digest())
|
|
continue
|
|
if(L.stat == DEAD)
|
|
if(L.vore_can_qdel())
|
|
vore_belly.digestion_death(L)
|
|
continue
|
|
if(vore_belly.brute_damage > 0)
|
|
L.adjust_brute_loss(vore_belly.brute_damage * seconds_per_tick)
|
|
living_parent.adjust_nutrition(NUTRITION_PER_DAMAGE * vore_belly.brute_damage * seconds_per_tick)
|
|
if(vore_belly.burn_damage > 0)
|
|
L.adjust_fire_loss(vore_belly.burn_damage * seconds_per_tick)
|
|
living_parent.adjust_nutrition(NUTRITION_PER_DAMAGE * vore_belly.burn_damage * seconds_per_tick)
|
|
|
|
/datum/digest_mode/absorb
|
|
name = DIGEST_MODE_ABSORB
|
|
gurgle_noises = TRUE
|
|
|
|
/mob/living/proc/vore_can_absorb()
|
|
if(client)
|
|
var/datum/vore_preferences/vore_prefs = client.get_vore_prefs()
|
|
return vore_prefs?.read_preference(/datum/vore_pref/toggle/absorb)
|
|
|
|
// Arguably, absorption is completely reversable and therefore harmless
|
|
// and this could just return TRUE
|
|
// But in case there's a player that logs out and really really doesn't like absorption...
|
|
return vore_can_negatively_affect()
|
|
|
|
/obj/vore_belly/proc/absorb(mob/living/L)
|
|
if(!L.vore_can_absorb())
|
|
return FALSE
|
|
// Already absorbed
|
|
if(HAS_TRAIT_FROM(L, TRAIT_RESTRAINED, TRAIT_SOURCE_VORE))
|
|
return FALSE
|
|
|
|
var/mob/living/living_parent = owner.parent
|
|
|
|
// Add full restraints
|
|
ADD_TRAIT(L, TRAIT_RESTRAINED, TRAIT_SOURCE_VORE)
|
|
ADD_TRAIT(L, TRAIT_STASIS, TRAIT_SOURCE_VORE)
|
|
|
|
to_chat(living_parent, span_notice(get_absorb_messages_owner(L)))
|
|
to_chat(L, span_notice(get_absorb_messages_prey(L)))
|
|
|
|
return TRUE
|
|
|
|
/datum/digest_mode/absorb/handle_belly(obj/vore_belly/vore_belly, seconds_per_tick)
|
|
var/mob/living/living_parent = vore_belly.owner.parent
|
|
|
|
for(var/mob/living/L in vore_belly)
|
|
if(!L.vore_can_absorb())
|
|
continue
|
|
if(HAS_TRAIT_FROM(L, TRAIT_RESTRAINED, TRAIT_SOURCE_VORE))
|
|
continue
|
|
if(L.nutrition < ABSORB_NUTRITION_BARRIER)
|
|
vore_belly.absorb(L)
|
|
continue
|
|
// Times 2 because we assume a baseline of 2 "damage" in absorb mode
|
|
var/nutrition_transfer = NUTRITION_PER_DAMAGE * 2 * seconds_per_tick
|
|
L.adjust_nutrition(-nutrition_transfer)
|
|
living_parent.adjust_nutrition(nutrition_transfer)
|
|
|
|
/datum/digest_mode/unabsorb
|
|
name = DIGEST_MODE_UNABSORB
|
|
gurgle_noises = TRUE
|
|
|
|
/obj/vore_belly/proc/unabsorb(mob/living/L)
|
|
// Not absorbed
|
|
if(!HAS_TRAIT_FROM(L, TRAIT_RESTRAINED, TRAIT_SOURCE_VORE))
|
|
return FALSE
|
|
|
|
var/mob/living/living_parent = owner.parent
|
|
|
|
// Remove full restraints
|
|
REMOVE_TRAIT(L, TRAIT_RESTRAINED, TRAIT_SOURCE_VORE)
|
|
REMOVE_TRAIT(L, TRAIT_STASIS, TRAIT_SOURCE_VORE)
|
|
|
|
to_chat(living_parent, span_notice(get_unabsorb_messages_owner(L)))
|
|
to_chat(L, span_notice(get_unabsorb_messages_prey(L)))
|
|
|
|
// Unabsorbs kick them back out
|
|
var/datum/component/absorb_control/AC = living_parent.GetComponent(/datum/component/absorb_control)
|
|
if(AC && AC.controller == L)
|
|
AC.revert()
|
|
|
|
return TRUE
|
|
|
|
/datum/digest_mode/unabsorb/handle_belly(obj/vore_belly/vore_belly, seconds_per_tick)
|
|
var/mob/living/living_parent = vore_belly.owner.parent
|
|
|
|
for(var/mob/living/L in vore_belly)
|
|
if(!HAS_TRAIT_FROM(L, TRAIT_RESTRAINED, TRAIT_SOURCE_VORE))
|
|
continue
|
|
// Parent can only reform if they have ABSORB_NUTRITION_BARRIER worth of nutrition
|
|
// Note that this nutrition is deliberately lost and not given back to the prey
|
|
if(living_parent.nutrition > ABSORB_NUTRITION_BARRIER)
|
|
living_parent.adjust_nutrition(-ABSORB_NUTRITION_BARRIER)
|
|
vore_belly.unabsorb(L)
|