[MIRROR] Spontaneous Vore Element (#11785)

Co-authored-by: Cameron Lennox <killer65311@gmail.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-10-06 14:17:26 -07:00
committed by GitHub
parent 9b1fb8d624
commit 11a4471110
14 changed files with 310 additions and 265 deletions

View File

@@ -968,6 +968,21 @@
// Hose Connector Component // Hose Connector Component
#define COMSIG_HOSE_FORCEPUMP "hose_force_pump" #define COMSIG_HOSE_FORCEPUMP "hose_force_pump"
// Spontaneous vore stuff.
///from /mob/living/stumble_into(mob/living/M)
#define COMSIG_LIVING_STUMBLED_INTO "living_stumbled_into"
///Something has special handling. Don't continue.
#define CANCEL_STUMBLED_INTO (1<<0)
///from /mob/living/handle_fall(var/turf/landing) args: landing, drop_mob)
#define COMSIG_LIVING_FALLING_DOWN "living_falling_down"
//Special handling. Cancel the fall chain.
#define COMSIG_CANCEL_FALL (1<<0)
///from /mob/living/hitby(atom/movable/source, var/speed = THROWFORCE_SPEED_DIVISOR)
#define COMSIG_LIVING_HIT_BY_THROWN_ENTITY "hit_by_thrown_entity"
//Special handling. Cancel the hitby proc.
#define COMSIG_CANCEL_HITBY (1<<0)
//Unittest data update //Unittest data update
#ifdef UNIT_TESTS #ifdef UNIT_TESTS
#define COMSIG_UNITTEST_DATA "unittest_send_data" #define COMSIG_UNITTEST_DATA "unittest_send_data"

View File

@@ -165,7 +165,7 @@
continue //Don't do anything to ourselves. continue //Don't do anything to ourselves.
if(living_mob.stat) if(living_mob.stat)
continue continue
if(!living_mob.CanStumbleVore(living_guy) && !living_guy.CanStumbleVore(living_mob)) //Works both ways! Either way, someone's getting eaten! if(!CanStumbleVore(living_guy, living_mob) && !CanStumbleVore(living_mob, living_guy)) //Works both ways! Either way, someone's getting eaten!
continue continue
living_mob.stumble_into(living_guy) //logic reversed here because the game is DUMB. This means that living_guy is stumbling into the target! living_mob.stumble_into(living_guy) //logic reversed here because the game is DUMB. This means that living_guy is stumbling into the target!
living_guy.visible_message(span_danger("[living_guy] loses their balance and slips into [living_mob]!"), span_boldwarning("You lose your balance, slipping into [living_mob]!")) living_guy.visible_message(span_danger("[living_guy] loses their balance and slips into [living_mob]!"), span_boldwarning("You lose your balance, slipping into [living_mob]!"))

View File

@@ -59,6 +59,7 @@
/datum/component/turfslip/proc/next_slip() /datum/component/turfslip/proc/next_slip()
// check tile for next slip // check tile for next slip
owner.is_slipping = TRUE
if(!step(owner, owner.dir) || dirtslip) // done sliding, failed to move, dirt also only slips once if(!step(owner, owner.dir) || dirtslip) // done sliding, failed to move, dirt also only slips once
qdel(src) qdel(src)
return return
@@ -70,6 +71,7 @@
/datum/component/turfslip/Destroy(force = FALSE) /datum/component/turfslip/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_MOVABLE_MOVED) UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
owner.inertia_dir = 0 owner.inertia_dir = 0
owner.is_slipping = FALSE
owner = null owner = null
slip_dist = 0 slip_dist = 0
. = ..() . = ..()

View File

@@ -0,0 +1,193 @@
/datum/element/spontaneous_vore
/datum/element/spontaneous_vore/Attach(datum/target)
. = ..()
if(!isliving(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_LIVING_STUMBLED_INTO, PROC_REF(handle_stumble))
RegisterSignal(target, COMSIG_LIVING_FALLING_DOWN, PROC_REF(handle_fall))
RegisterSignal(target, COMSIG_LIVING_HIT_BY_THROWN_ENTITY, PROC_REF(handle_hitby))
RegisterSignal(target, COMSIG_MOVABLE_CROSS, PROC_REF(handle_crossed))
/datum/element/spontaneous_vore/Detach(datum/target)
. = ..()
UnregisterSignal(target, list(COMSIG_LIVING_STUMBLED_INTO, COMSIG_LIVING_FALLING_DOWN, COMSIG_LIVING_HIT_BY_THROWN_ENTITY, COMSIG_MOVABLE_CROSS))
///Source is the one being bumped into (Owner of this component)
///Target is the one bumping into us.
/datum/element/spontaneous_vore/proc/handle_stumble(mob/living/source, mob/living/target)
SIGNAL_HANDLER
//snowflake protean code to prevent protean blobform from eating their human form and humanform from eating their protean blob...gross.
//We are trying to eat our blobform
if(istype(target, /mob/living/simple_mob/protean_blob))
var/mob/living/simple_mob/protean_blob/PB = target
if(PB.humanform == source)
return
//Our blobform is trying to eat us
if(istype(source, /mob/living/simple_mob/protean_blob))
var/mob/living/simple_mob/protean_blob/PB = source
if(PB.humanform == target)
return
//We are able to eat the person stumbling into us.
if(CanStumbleVore(prey = target, pred = source)) //This is if the person stumbling into us is able to eat us!
source.visible_message(span_vwarning("[target] flops carelessly into [source]!"))
source.begin_instant_nom(source, prey = target, pred = source, belly = source.vore_selected)
target.stop_flying()
return CANCEL_STUMBLED_INTO
//The person stumbling into us is able to eat us.
if(CanStumbleVore(prey = source, pred = target)) //This is if the person stumbling into us is able to be eaten by us! BROKEN!
source.visible_message(span_vwarning("[target] flops carelessly into [source]!"))
target.forceMove(get_turf(source))
source.begin_instant_nom(target, prey = source, pred = target, belly = target.vore_selected)
source.stop_flying()
return CANCEL_STUMBLED_INTO
//Source is the one dropping (us)
//Landing is the tile we're falling onto
//drop_mob is whatever mob is found in the turf we're dropping onto.
/datum/element/spontaneous_vore/proc/handle_fall(mob/living/source, turf/landing, mob/living/drop_mob)
SIGNAL_HANDLER
if(!drop_mob || drop_mob == source)
return
//pred = drop_mob
//prey = source
//result: source is eaten by drop_mob
if(CanDropVore(prey = source, pred = drop_mob))
drop_mob.feed_grabbed_to_self_falling_nom(drop_mob, prey = source)
drop_mob.visible_message(span_vdanger("\The [drop_mob] falls right onto \the [source]!"))
return COMSIG_CANCEL_FALL
//pred = source
//prey = drop_mob
//result: drop_mob is eaten by source
if(CanDropVore(prey = drop_mob, pred = source))
source.feed_grabbed_to_self_falling_nom(source, prey = drop_mob)
source.Weaken(4)
source.visible_message(span_vdanger("\The [drop_mob] falls right into \the [source]!"))
return COMSIG_CANCEL_FALL
/datum/element/spontaneous_vore/proc/handle_hitby(mob/living/source, atom/movable/hitby, speed)
SIGNAL_HANDLER
//Handle object throw vore
if(isitem(hitby))
var/obj/item/O = hitby
if(source.stat != DEAD && source.trash_catching && source.vore_selected)
if(source.adminbus_trash || is_type_in_list(O, GLOB.edible_trash) && O.trash_eatable && !is_type_in_list(O, GLOB.item_vore_blacklist))
source.visible_message(span_vwarning("[O] is thrown directly into [source]'s [lowertext(source.vore_selected.name)]!"))
O.throwing = 0
O.forceMove(source.vore_selected)
return COMSIG_CANCEL_HITBY
//Throwing a prey into a pred takes priority. After that it checks to see if the person being thrown is a pred.
if(isliving(hitby))
var/mob/living/thrown_mob = hitby
//If we don't allow mobvore and the thrown mob is an NPC animal, stop here.
if(!source.allowmobvore && isanimal(thrown_mob) && !thrown_mob.ckey)
return
//If we're an NPC animal and the person thrown into us doesn't allow mobvore, stop here.
if(!thrown_mob.allowmobvore && isanimal(source) && !source.ckey)
return
// PERSON BEING HIT: CAN BE DROP PRED, ALLOWS THROW VORE.
// PERSON BEING THROWN: DEVOURABLE, ALLOWS THROW VORE, CAN BE DROP PREY.
if(CanThrowVore(prey = thrown_mob, pred = source))
if(!source.vore_selected)
return
source.vore_selected.nom_mob(thrown_mob) //Eat them!!!
source.visible_message(span_vwarning("[thrown_mob] is thrown right into [source]'s [lowertext(source.vore_selected.name)]!"))
if(thrown_mob.loc != source.vore_selected)
thrown_mob.forceMove(source.vore_selected) //Double check. Should never happen but...Weirder things have happened!
source.on_throw_vore_special(TRUE, thrown_mob)
add_attack_logs(thrown_mob.thrower,source,"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.
// PERSON BEING HIT: CAN BE DROP PREY, ALLOWS THROW VORE, AND IS DEVOURABLE.
// PERSON BEING THROWN: CAN BE DROP PRED, ALLOWS THROW VORE.
else if(CanThrowVore(prey = source, pred = thrown_mob))//Pred thrown into prey.
if(!thrown_mob.vore_selected)
return
source.visible_message(span_vwarning("[source] suddenly slips inside of [thrown_mob]'s [lowertext(thrown_mob.vore_selected.name)] as [thrown_mob] flies into them!"))
thrown_mob.vore_selected.nom_mob(source) //Eat them!!!
if(source.loc != thrown_mob.vore_selected)
source.forceMove(thrown_mob.vore_selected) //Double check. Should never happen but...Weirder things have happened!
add_attack_logs(thrown_mob.LAssailant,source,"Was Devoured by [thrown_mob.name] via throw vore.")
return
//source = person standing up
//crossed = person sliding
/datum/element/spontaneous_vore/proc/handle_crossed(mob/living/source, mob/living/crossed)
SIGNAL_HANDLER
if(source == crossed || !istype(crossed))
return
//Person being slipped into eats the person slipping
if(can_slip_vore(pred = source, prey = crossed)) //If we can vore them go for it
source.begin_instant_nom(source, prey = crossed, pred = source, belly = source.vore_selected)
return COMPONENT_BLOCK_CROSS
//The person slipping eats the person being slipped into
else if(can_slip_vore(pred = crossed, prey = source))
source.begin_instant_nom(crossed, prey = source, pred = crossed, belly = crossed.vore_selected) //Must be
return //We DON'T block it here. Pred can slip onto the prey's tile, no problem.
///Helper Procs
/proc/CanStumbleVore(mob/living/prey, mob/living/pred)
if(!can_spontaneous_vore(pred, prey))
return FALSE
if(!prey.stumble_vore || !pred.stumble_vore)
return FALSE
return TRUE
/proc/CanDropVore(mob/living/prey, mob/living/pred)
if(!can_spontaneous_vore(pred, prey))
return FALSE
if(!pred.drop_vore || !prey.drop_vore)
return FALSE
return TRUE
/proc/CanThrowVore(mob/living/prey, mob/living/pred)
if(!can_spontaneous_vore(pred, prey))
return FALSE
if(!pred.throw_vore || !prey.throw_vore)
return FALSE
return TRUE
/proc/can_slip_vore(mob/living/pred, mob/living/prey)
if(!can_spontaneous_vore(pred, prey))
return FALSE
if(!prey.is_slipping && !pred.is_slipping) //Obviously they have to be slipping to get slip vored
return FALSE
if(world.time <= prey.slip_protect)
return FALSE
if(!pred.slip_vore || !prey.slip_vore)
return FALSE
return TRUE
///This is a general 'do we have the mechanical ability to do any type of spontaneous vore' without specialties.
/proc/can_spontaneous_vore(mob/living/pred, mob/living/prey)
if(!istype(pred) || !istype(prey))
return FALSE
//Unfortunately, can_be_drop_prey is 'spontanous prey' var and can_be_drop_pred is 'spontaneous pred' var...horribly named imo.
if(!prey.can_be_drop_prey || !pred.can_be_drop_pred)
return FALSE
if(prey.is_incorporeal() || pred.is_incorporeal())
return FALSE
if(!prey.devourable)
return FALSE
if(!is_vore_predator(pred)) //Check their bellies and stuff
return FALSE
if(!pred.vore_selected) //Gotta have one selected as well.
return FALSE
if(!prey.allowmobvore && isanimal(pred) && !pred.ckey || (!pred.allowmobvore && isanimal(prey) && !prey.ckey))
return FALSE
return TRUE

View File

@@ -129,7 +129,7 @@
if(has_buckled_mobs() && buckled_mobs.len >= max_buckled_mobs) if(has_buckled_mobs() && buckled_mobs.len >= max_buckled_mobs)
for(var/mob/living/L in buckled_mobs) for(var/mob/living/L in buckled_mobs)
if(istype(L) && M.CanStumbleVore(L)) if(istype(L) && CanStumbleVore(prey = L, pred = M))
unbuckle_mob(L, TRUE) unbuckle_mob(L, TRUE)
if(M == user) if(M == user)
M.visible_message(span_warning("[M.name] sits down on [L.name]!")) M.visible_message(span_warning("[M.name] sits down on [L.name]!"))
@@ -218,7 +218,7 @@
if(has_buckled_mobs() && buckled_mobs.len >= max_buckled_mobs) //Handles trying to buckle yourself to the chair when someone is on it if(has_buckled_mobs() && buckled_mobs.len >= max_buckled_mobs) //Handles trying to buckle yourself to the chair when someone is on it
if(can_do_spont_vore && is_vore_predator(M) && M.vore_selected) if(can_do_spont_vore && is_vore_predator(M) && M.vore_selected)
for(var/mob/living/buckled in buckled_mobs) for(var/mob/living/buckled in buckled_mobs)
if(M.CanStumbleVore(buckled)) if(CanStumbleVore(prey = buckled, pred = M))
return TRUE return TRUE
to_chat(M, span_notice("\The [src] can't buckle any more people.")) to_chat(M, span_notice("\The [src] can't buckle any more people."))
return FALSE return FALSE

View File

@@ -659,19 +659,6 @@
return 1 return 1
return 0 return 0
//Don't eat yourself, idiot
/mob/living/simple_mob/protean_blob/CanStumbleVore(mob/living/target)
if(target == humanform)
return FALSE
return ..()
/mob/living/carbon/human/CanStumbleVore(mob/living/target)
if(istype(target, /mob/living/simple_mob/protean_blob))
var/mob/living/simple_mob/protean_blob/PB = target
if(PB.humanform == src)
return FALSE
return ..()
/mob/living/simple_mob/protean_blob/handle_mutations_and_radiation() /mob/living/simple_mob/protean_blob/handle_mutations_and_radiation()
if(!humanform) if(!humanform)
to_chat(src, span_giant(span_boldwarning("You are currently a blob without a humanform and should be deleted shortly Please report what you were doing when this error occurred to the admins."))) to_chat(src, span_giant(span_boldwarning("You are currently a blob without a humanform and should be deleted shortly Please report what you were doing when this error occurred to the admins.")))

View File

@@ -18,6 +18,8 @@
selected_image = image(icon = GLOB.buildmode_hud, loc = src, icon_state = "ai_sel") selected_image = image(icon = GLOB.buildmode_hud, loc = src, icon_state = "ai_sel")
AddElement(/datum/element/spontaneous_vore)
/mob/living/proc/get_visible_name() /mob/living/proc/get_visible_name()
var/datum/component/shadekin/SK = get_shadekin_component() var/datum/component/shadekin/SK = get_shadekin_component()
if(SK && SK.in_phase) if(SK && SK.in_phase)

View File

@@ -272,14 +272,10 @@
/mob/living/hitby(atom/movable/source, var/speed = THROWFORCE_SPEED_DIVISOR)//Standardization and logging -Sieve /mob/living/hitby(atom/movable/source, var/speed = THROWFORCE_SPEED_DIVISOR)//Standardization and logging -Sieve
if(is_incorporeal()) if(is_incorporeal())
return return
if(SEND_SIGNAL(src, COMSIG_LIVING_HIT_BY_THROWN_ENTITY, source, speed) & COMSIG_CANCEL_HITBY)
return
if(isitem(source)) if(isitem(source))
var/obj/item/O = source var/obj/item/O = source
if(stat != DEAD && trash_catching && vore_selected)
if(adminbus_trash || is_type_in_list(O, GLOB.edible_trash) && O.trash_eatable && !is_type_in_list(O, GLOB.item_vore_blacklist))
visible_message(span_vwarning("[O] is thrown directly into [src]'s [lowertext(vore_selected.name)]!"))
O.throwing = 0
O.forceMove(vore_selected)
return
var/dtype = O.damtype var/dtype = O.damtype
var/throw_damage = O.throwforce*(speed/THROWFORCE_SPEED_DIVISOR) var/throw_damage = O.throwforce*(speed/THROWFORCE_SPEED_DIVISOR)
@@ -336,37 +332,6 @@
src.anchored = TRUE src.anchored = TRUE
src.pinned += O src.pinned += O
//VORESTATION EDIT START - Allows for thrown vore! //CHOMPEdit Start
//Throwing a prey into a pred takes priority. After that it checks to see if the person being thrown is a pred.
if(isliving(source))
var/mob/living/thrown_mob = source
// PERSON BEING HIT: CAN BE DROP PRED, ALLOWS THROW VORE.
// PERSON BEING THROWN: DEVOURABLE, ALLOWS THROW VORE, CAN BE DROP PREY.
if((can_be_drop_pred && throw_vore) && (thrown_mob.devourable && thrown_mob.throw_vore && thrown_mob.can_be_drop_prey)) //Prey thrown into pred.
if(!thrown_mob.allowmobvore && isanimal(src) && !ckey || !vore_selected) //Does the person being thrown not allow mob vore and is the person being hit (us) a simple_mob?
return
vore_selected.nom_mob(thrown_mob) //Eat them!!!
visible_message(span_vwarning("[thrown_mob] is thrown right into [src]'s [lowertext(vore_selected.name)]!"))
if(thrown_mob.loc != vore_selected)
thrown_mob.forceMove(vore_selected) //Double check. Should never happen but...Weirder things have happened!
on_throw_vore_special(TRUE, thrown_mob)
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.
// PERSON BEING HIT: CAN BE DROP PREY, ALLOWS THROW VORE, AND IS DEVOURABLE.
// PERSON BEING THROWN: CAN BE DROP PRED, ALLOWS THROW VORE.
else if((can_be_drop_prey && throw_vore && devourable) && (thrown_mob.can_be_drop_pred && thrown_mob.throw_vore)) //Pred thrown into prey.
if(!allowmobvore && isanimal(thrown_mob) && !thrown_mob.ckey || !thrown_mob.vore_selected) //Does the person being hit not allow mob vore and the perrson being thrown a simple_mob?
return
visible_message(span_vwarning("[src] suddenly slips inside of [thrown_mob]'s [lowertext(thrown_mob.vore_selected.name)] as [thrown_mob] flies into them!"))
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! //CHOMPEdit End
/mob/living/proc/on_throw_vore_special(var/pred = TRUE, var/mob/living/target) /mob/living/proc/on_throw_vore_special(var/pred = TRUE, var/mob/living/target)
return return

View File

@@ -24,33 +24,33 @@
return ..() // Parent call should make the mob move. return ..() // Parent call should make the mob move.
/*one proc, four uses /*one proc, four uses
swapping: if it's 1, the mobs are trying to switch, if 0, non-passive is pushing passive swapping: if it's TRUE, the mobs are trying to switch, if FALSE, non-passive is pushing passive
default behaviour is: default behaviour is:
- non-passive mob passes the passive version - non-passive mob passes the passive version
- passive mob checks to see if its mob_bump_flag is in the non-passive's mob_bump_flags - passive mob checks to see if its mob_bump_flag is in the non-passive's mob_bump_flags
- if si, the proc returns - if si, the proc returns
*/ */
/mob/living/proc/can_move_mob(var/mob/living/swapped, swapping = 0, passive = 0) /mob/living/proc/can_move_mob(var/mob/living/swapped, swapping = FALSE, passive = FALSE)
if(!swapped) if(!swapped)
return 1 return TRUE
if(!passive) if(!passive)
return swapped.can_move_mob(src, swapping, 1) return swapped.can_move_mob(src, swapping, TRUE)
else else
var/context_flags = 0 var/context_flags = FALSE
if(swapping) if(swapping)
context_flags = swapped.mob_swap_flags context_flags = swapped.mob_swap_flags
else else
context_flags = swapped.mob_push_flags context_flags = swapped.mob_push_flags
if(!mob_bump_flag) //nothing defined, go wild if(!mob_bump_flag) //nothing defined, go wild
return 1 return TRUE
if(mob_bump_flag & context_flags) if(mob_bump_flag & context_flags)
return 1 return TRUE
return 0 return FALSE
/mob/living/Bump(atom/movable/AM) /mob/living/Bump(atom/movable/AM)
if(now_pushing || !loc || buckled == AM || AM.is_incorporeal()) if(now_pushing || !loc || buckled == AM || AM.is_incorporeal())
return return
now_pushing = 1 now_pushing = TRUE
if (isliving(AM)) if (isliving(AM))
var/mob/living/tmob = AM var/mob/living/tmob = AM
@@ -58,94 +58,92 @@ default behaviour is:
spreadFire(tmob) spreadFire(tmob)
for(var/mob/living/M in range(tmob, 1)) for(var/mob/living/M in range(tmob, 1))
if(tmob.pinned.len || ((M.pulling == tmob && ( tmob.restrained() && !( M.restrained() ) && M.stat == 0)) || locate(/obj/item/grab, tmob.grabbed_by.len)) ) if(tmob.pinned.len || ((M.pulling == tmob && ( tmob.restrained() && !( M.restrained() ) && M.stat == CONSCIOUS)) || locate(/obj/item/grab, tmob.grabbed_by.len)) )
if ( !(world.time % 5) ) if ( !(world.time % 5) )
to_chat(src, span_warning("[tmob] is restrained, you cannot push past")) to_chat(src, span_warning("[tmob] is restrained, you cannot push past"))
now_pushing = 0 now_pushing = FALSE
return return
if( tmob.pulling == M && ( M.restrained() && !( tmob.restrained() ) && tmob.stat == 0) ) if( tmob.pulling == M && ( M.restrained() && !( tmob.restrained() ) && tmob.stat == CONSCIOUS) )
if ( !(world.time % 5) ) if ( !(world.time % 5) )
to_chat(src, span_warning("[tmob] is restraining [M], you cannot push past")) to_chat(src, span_warning("[tmob] is restraining [M], you cannot push past"))
now_pushing = 0 now_pushing = FALSE
return return
//BubbleWrap: people in handcuffs are always switched around as if they were on 'help' intent to prevent a person being pulled from being seperated from their puller //BubbleWrap: people in handcuffs are always switched around as if they were on 'help' intent to prevent a person being pulled from being seperated from their puller
var/can_swap = 1 var/can_swap = TRUE
if(loc.density || tmob.loc.density) if(loc.density || tmob.loc.density)
can_swap = 0 can_swap = FALSE
if(can_swap) if(can_swap)
for(var/atom/movable/A in loc) for(var/atom/movable/A in loc)
if(A == src) if(A == src)
continue continue
if(!A.CanPass(tmob, loc)) if(!A.CanPass(tmob, loc))
can_swap = 0 can_swap = FALSE
if(!can_swap) break if(!can_swap) break
if(can_swap) if(can_swap)
for(var/atom/movable/A in tmob.loc) for(var/atom/movable/A in tmob.loc)
if(A == tmob) if(A == tmob)
continue continue
if(!A.CanPass(src, tmob.loc)) if(!A.CanPass(src, tmob.loc))
can_swap = 0 can_swap = FALSE
if(!can_swap) break if(!can_swap) break
//Leaping mobs just land on the tile, no pushing, no anything. //Leaping mobs just land on the tile, no pushing, no anything.
if(status_flags & LEAPING) if(status_flags & LEAPING)
loc = tmob.loc loc = tmob.loc
status_flags &= ~LEAPING status_flags &= ~LEAPING
now_pushing = 0 now_pushing = FALSE
return return
if((tmob.mob_always_swap || (tmob.a_intent == I_HELP || tmob.restrained()) && (a_intent == I_HELP || src.restrained())) && tmob.canmove && canmove && !tmob.buckled && !buckled && can_swap && can_move_mob(tmob, 1, 0)) // mutual brohugs all around! if((tmob.mob_always_swap || (tmob.a_intent == I_HELP || tmob.restrained()) && (a_intent == I_HELP || src.restrained())) && tmob.canmove && canmove && !tmob.buckled && !buckled && can_swap && can_move_mob(tmob, 1, 0)) // mutual brohugs all around!
var/turf/oldloc = loc var/turf/oldloc = loc
//VOREstation Edit - Begin
//check bumpnom chance, if it's a simplemob that's doing the bumping //check bumpnom chance, if it's a simplemob that's doing the bumping
var/mob/living/simple_mob/srcsimp = src var/mob/living/simple_mob/srcsimp = src
if(istype(srcsimp)) if(istype(srcsimp))
if(srcsimp.tryBumpNom(tmob)) if(srcsimp.tryBumpNom(tmob))
now_pushing = 0 now_pushing = FALSE
return return
//if it's a simplemob being bumped, and the above didn't make them start getting bumpnommed, they get a chance to bumpnom //if it's a simplemob being bumped, and the above didn't make them start getting bumpnommed, they get a chance to bumpnom
var/mob/living/simple_mob/tmobsimp = tmob var/mob/living/simple_mob/tmobsimp = tmob
if(istype(tmobsimp)) if(istype(tmobsimp))
if(tmobsimp.tryBumpNom(src)) if(tmobsimp.tryBumpNom(src))
now_pushing = 0 now_pushing = FALSE
return return
//VOREstation Edit - End
forceMove(tmob.loc) forceMove(tmob.loc)
//CHOMPSTATION Edit - Making macro/micro step mechanics mandatory again for balance, but removing the fetish aspects if pref denied. //CHOMPSTATION Edit - Making macro/micro step mechanics mandatory again for balance, but removing the fetish aspects if pref denied.
//There's nothing fetishistic about politely stepping past someone. //There's nothing fetishistic about politely stepping past someone.
// In case of micros, we don't swap positions; instead occupying the same square! // In case of micros, we don't swap positions; instead occupying the same square!
if(handle_micro_bump_helping(tmob)) if(handle_micro_bump_helping(tmob))
now_pushing = 0 now_pushing = FALSE
return return
// TODO - Check if we need to do something about the slime.UpdateFeed() we are skipping below. // TODO - Check if we need to do something about the slime.UpdateFeed() we are skipping below.
// CHOMPSTATION Edit - End // CHOMPSTATION Edit - End
tmob.forceMove(oldloc) tmob.forceMove(oldloc)
now_pushing = 0 now_pushing = FALSE
return return
else if((tmob.mob_always_swap || (tmob.a_intent == I_HELP || tmob.restrained()) && (a_intent == I_HELP || src.restrained())) && canmove && can_swap && handle_micro_bump_helping(tmob)) else if((tmob.mob_always_swap || (tmob.a_intent == I_HELP || tmob.restrained()) && (a_intent == I_HELP || src.restrained())) && canmove && can_swap && handle_micro_bump_helping(tmob))
forceMove(tmob.loc) forceMove(tmob.loc)
now_pushing = 0 now_pushing = FALSE
return return
if(!can_move_mob(tmob, 0, 0)) if(!can_move_mob(tmob, FALSE, FALSE))
now_pushing = 0 now_pushing = FALSE
return return
if(a_intent == I_HELP || src.restrained()) if(a_intent == I_HELP || src.restrained())
now_pushing = 0 now_pushing = FALSE
return return
// Plow that nerd. // Plow that nerd.
if(ishuman(tmob)) if(ishuman(tmob))
var/mob/living/carbon/human/H = tmob var/mob/living/carbon/human/H = tmob
if(H.species.lightweight == 1 && prob(50)) if(H.species.lightweight == TRUE && prob(50))
if(HULK in H.mutations) //No knocking over the hulk if(HULK in H.mutations) //No knocking over the hulk
return return
H.visible_message(span_warning("[src] bumps into [H], knocking them off balance!")) H.visible_message(span_warning("[src] bumps into [H], knocking them off balance!"))
H.Weaken(5) H.Weaken(5)
now_pushing = 0 now_pushing = FALSE
return return
//CHOMPSTATION edit Adding alternative to lightweight //CHOMPSTATION edit Adding alternative to lightweight
if(H.species.lightweight_light == 1 && H.a_intent == I_HELP) if(H.species.lightweight_light == 1 && H.a_intent == I_HELP)
@@ -163,55 +161,45 @@ default behaviour is:
if(ishuman(tmob) && (FAT in tmob.mutations)) if(ishuman(tmob) && (FAT in tmob.mutations))
if(prob(40) && !(FAT in src.mutations)) if(prob(40) && !(FAT in src.mutations))
to_chat(src, span_danger("You fail to push [tmob]'s fat ass out of the way.")) to_chat(src, span_danger("You fail to push [tmob]'s fat ass out of the way."))
now_pushing = 0 now_pushing = FALSE
return return
if(tmob.r_hand && istype(tmob.r_hand, /obj/item/shield/riot)) if(tmob.r_hand && istype(tmob.r_hand, /obj/item/shield/riot))
if(prob(99)) if(prob(99))
now_pushing = 0 now_pushing = FALSE
return return
if(tmob.l_hand && istype(tmob.l_hand, /obj/item/shield/riot)) if(tmob.l_hand && istype(tmob.l_hand, /obj/item/shield/riot))
if(prob(99)) if(prob(99))
now_pushing = 0 now_pushing = FALSE
return return
if(!(tmob.status_flags & CANPUSH)) if(!(tmob.status_flags & CANPUSH))
now_pushing = 0 now_pushing = FALSE
return return
tmob.LAssailant = src tmob.LAssailant = src
now_pushing = 0 now_pushing = FALSE
. = ..() . = ..()
if (!istype(AM, /atom/movable) || AM.anchored) if (!istype(AM, /atom/movable) || AM.anchored)
//VOREStation Edit - object-specific proc for running into things
if(((confused || is_blind()) && stat == CONSCIOUS && prob(50) && m_intent==I_RUN) || flying) if(((confused || is_blind()) && stat == CONSCIOUS && prob(50) && m_intent==I_RUN) || flying)
AM.stumble_into(src) AM.stumble_into(src)
//VOREStation Edit End
/* VOREStation Removal - See above
if(confused && prob(50) && m_intent==I_RUN)
Weaken(2)
playsound(src, "punch", 25, 1, -1)
visible_message(span_warning("[src] [pick("ran", "slammed")] into \the [AM]!"))
src.apply_damage(5, BRUTE)
to_chat(src, span_warning("You just [pick("ran", "slammed")] into \the [AM]!"))
*/ // VOREStation Removal End
return return
if (!now_pushing) if (!now_pushing)
if(isobj(AM)) if(isobj(AM))
var/obj/I = AM var/obj/I = AM
if(!can_pull_size || can_pull_size < I.w_class) if(!can_pull_size || can_pull_size < I.w_class)
return return
now_pushing = 1 now_pushing = TRUE
var/t = get_dir(src, AM) var/t = get_dir(src, AM)
if (istype(AM, /obj/structure/window)) if (istype(AM, /obj/structure/window))
for(var/obj/structure/window/win in get_step(AM,t)) for(var/obj/structure/window/win in get_step(AM,t))
now_pushing = 0 now_pushing = FALSE
return return
var/turf/T = AM.loc var/turf/T = AM.loc
var/turf/T2 = get_step(AM,t) var/turf/T2 = get_step(AM,t)
if(!T2) // Map edge if(!T2) // Map edge
now_pushing = 0 now_pushing = FALSE
return return
var/move_time = movement_delay(loc, t) var/move_time = movement_delay(loc, t)
move_time = DS2NEARESTTICK(move_time) move_time = DS2NEARESTTICK(move_time)
@@ -220,9 +208,9 @@ default behaviour is:
if(ishuman(AM) && AM:grabbed_by) if(ishuman(AM) && AM:grabbed_by)
for(var/obj/item/grab/G in AM:grabbed_by) for(var/obj/item/grab/G in AM:grabbed_by)
step(G:assailant, get_dir(G:assailant, AM)) step(G.assailant, get_dir(G.assailant, AM))
G.adjust_position() G.adjust_position()
now_pushing = 0 now_pushing = FALSE
/mob/living/CanPass(atom/movable/mover, turf/target) /mob/living/CanPass(atom/movable/mover, turf/target)
if(istype(mover, /obj/structure/blob) && faction == "blob") //Blobs should ignore things on their faction. if(istype(mover, /obj/structure/blob) && faction == "blob") //Blobs should ignore things on their faction.

View File

@@ -1,78 +1,57 @@
/mob/living/handle_fall(var/turf/landing) /mob/living/handle_fall(var/turf/landing)
var/mob/drop_mob = locate(/mob/living, landing) var/mob/living/drop_mob = locate(/mob/living, landing)
if(locate(/obj/structure/stairs) in landing) if(locate(/obj/structure/stairs) in landing)
for(var/atom/A in landing) for(var/atom/A in landing)
if(!A.CanPass(src, src.loc, 1, 0)) if(!A.CanPass(src, src.loc))
return FALSE return FALSE
Move(landing) Move(landing)
if(isliving(src)) if(isliving(src))
var/mob/living/L = src var/mob/living/L = src
if(L.pulling) if(L.pulling)
L.pulling.forceMove(landing) L.pulling.forceMove(landing)
return 1 return TRUE
for(var/obj/O in loc) for(var/obj/O in loc)
if(!O.CanFallThru(src, landing)) if(!O.CanFallThru(src, landing))
return 1 return TRUE
if(drop_mob && !(drop_mob == src)) //Shitload of checks. This is because the game finds various ways to screw me over. if(SEND_SIGNAL(src, COMSIG_LIVING_FALLING_DOWN, landing, drop_mob) & COMSIG_CANCEL_FALL)
var/mob/living/drop_living = drop_mob return
if(drop_living.dropped_onto(src))
return if(drop_mob && drop_mob != src)
///Varible to tell if we take damage or not for falling.
var/safe_fall = FALSE
if(drop_mob.softfall || (isanimal(drop_mob) && drop_mob.mob_size <= MOB_SMALL))
safe_fall = TRUE
if(ishuman(drop_mob))
var/mob/living/carbon/human/H = drop_mob
if(H.species.soft_landing)
safe_fall = TRUE
forceMove(get_turf(drop_mob))
if(!safe_fall)
drop_mob.Weaken(8)
Weaken(8)
playsound(src, "punch", 25, 1, -1)
var/tdamage
for(var/i = 1 to 5) //Twice as less damage because cushioned fall, but both get damaged.
tdamage = rand(0, 5)
drop_mob.adjustBruteLoss(tdamage)
adjustBruteLoss(tdamage)
drop_mob.updatehealth()
updatehealth()
drop_mob.visible_message(span_danger("\The [drop_mob] falls onto \the [src]!"))
else
drop_mob.visible_message(span_notice("\The [drop_mob] safely brushes past \the [src] as they land."))
// Then call parent to have us actually fall // Then call parent to have us actually fall
return ..() return ..()
/mob/CheckFall(var/atom/movable/falling_atom) /mob/CheckFall(var/atom/movable/falling_atom)
return falling_atom.fall_impact(src) return falling_atom.fall_impact(src)
/mob/living/proc/dropped_onto(var/atom/hit_atom)
if(!isliving(hit_atom))
return 0
var/mob/living/pred = hit_atom
if(pred.is_incorporeal())
return
var/safe_fall = FALSE
if(pred.softfall || (isanimal(pred) && pred.mob_size <= MOB_SMALL)) // TODO: add ability for mob below to be 'soft' and cushion fall
safe_fall = TRUE
if(ishuman(pred))
var/mob/living/carbon/human/H = pred
if(H.species.soft_landing)
safe_fall = TRUE
var/mob/living/prey = src
var/fallloc = prey.loc
if(pred.vore_selected && pred.can_be_drop_pred && prey.can_be_drop_prey && pred.drop_vore && prey.drop_vore)
pred.feed_grabbed_to_self_falling_nom(pred,prey)
pred.loc = fallloc
if(!safe_fall)
pred.Weaken(8)
pred.visible_message(span_vdanger("\The [pred] falls right onto \the [prey]!"))
else if(prey.vore_selected && prey.can_be_drop_pred && pred.can_be_drop_prey && pred.drop_vore && prey.drop_vore)
prey.feed_grabbed_to_self_falling_nom(prey,pred)
prey.Weaken(4)
prey.visible_message(span_vdanger("\The [pred] falls right into \the [prey]!"))
else
pred.loc = prey.loc
if(!safe_fall)
pred.Weaken(8)
prey.Weaken(8)
playsound(src, "punch", 25, 1, -1)
var/tdamage
for(var/i = 1 to 5) //Twice as less damage because cushioned fall, but both get damaged.
tdamage = rand(0, 5)
pred.adjustBruteLoss(tdamage)
prey.adjustBruteLoss(tdamage)
pred.updatehealth()
prey.updatehealth()
pred.visible_message(span_danger("\The [pred] falls onto \the [prey]!"))
else
pred.visible_message(span_notice("\The [pred] safely brushes past \the [prey] as they land."))
return 1
/mob/observer/dead/CheckFall() /mob/observer/dead/CheckFall()
return return

View File

@@ -14,11 +14,11 @@
var/vore_smell = null // What the character smells like var/vore_smell = null // What the character smells like
var/noisy = FALSE // Toggle audible hunger. var/noisy = FALSE // Toggle audible hunger.
var/permit_healbelly = TRUE var/permit_healbelly = TRUE
var/stumble_vore = TRUE //Enabled by default since you have to enable drop pred/prey to do this anyway var/stumble_vore = TRUE
var/slip_vore = TRUE //Enabled by default since you have to enable drop pred/prey to do this anyway var/slip_vore = TRUE
var/drop_vore = TRUE //Enabled by default since you have to enable drop pred/prey to do this anyway var/drop_vore = TRUE
var/throw_vore = TRUE //Enabled by default since you have to enable drop pred/prey to do this anyway var/throw_vore = TRUE
var/food_vore = TRUE //Enabled by default since you have to enable drop pred/prey to do this anyway var/food_vore = TRUE
var/consume_liquid_belly = FALSE //starting off because if someone is into that, they'll toggle it first time they get the error. Otherway around would be more pref breaky. var/consume_liquid_belly = FALSE //starting off because if someone is into that, they'll toggle it first time they get the error. Otherway around would be more pref breaky.
var/digest_pain = TRUE var/digest_pain = TRUE
var/can_be_drop_prey = FALSE var/can_be_drop_prey = FALSE

View File

@@ -2,71 +2,4 @@
/mob/living /mob/living
var/is_slipping = FALSE var/is_slipping = FALSE
var/slip_vore_in_progress = FALSE
var/slip_protect = 1 var/slip_protect = 1
/mob/living/proc/can_slip_vore(var/mob/living/target)
if(!target.is_slipping) //Obviously they have to be slipping to get slip vored
return FALSE
if(is_incorporeal())
return FALSE
if(!target.allowmobvore && isanimal(src) && !ckey)
return FALSE
if(world.time <= target.slip_protect)
return FALSE
if(!(src.can_be_drop_pred && target.devourable && target.can_be_drop_prey)) //Make sure both of their prefs align with what we're gonna do.
return FALSE
if(!is_vore_predator(src)) //Check their bellies and stuff
return FALSE
if(!src.vore_selected) //Gotta have one selected as well.
return FALSE
if(!slip_vore || !target.slip_vore)
return FALSE
return TRUE
/mob/living/proc/can_be_slip_vored_by(var/mob/living/target)
if(!target.is_slipping) //Obviously they have to be slipping to get slip vored
return FALSE
if(is_incorporeal())
return FALSE
if(!allowmobvore && isanimal(target) && !target.ckey)
return FALSE
if(world.time <= target.slip_protect)
return FALSE
if(!(target.can_be_drop_pred && src.devourable && src.can_be_drop_prey)) //Make sure both of their prefs align with what we're gonna do.
return FALSE
if(!is_vore_predator(target)) //Check their bellies and stuff
return FALSE
if(!target.vore_selected) //Gotta have one selected as well.
return FALSE
if(!slip_vore || !target.slip_vore)
return FALSE
return TRUE
/mob/living/Crossed(var/atom/movable/AM)
..()
var/mob/living/target = AM
if(istype(target) && !target.is_incorporeal() && !src.is_incorporeal()) //The slip vore begins
if(can_slip_vore(target) && !src.slip_vore_in_progress && !target.slip_vore_in_progress) //If we can vore them go for it
begin_instant_nom(src,target,src,src.vore_selected)
target.slip_vore_in_progress = FALSE
target.is_slipping = FALSE
return
else if(can_be_slip_vored_by(target) && !src.slip_vore_in_progress && !target.slip_vore_in_progress) //Otherwise, if they can vore us, make it happen.
begin_instant_nom(target,src,target,target.vore_selected)
slip_vore_in_progress = FALSE
is_slipping = FALSE
return
/mob/living/carbon/slip(var/slipped_on,stun_duration=8)
. = ..()
if(.)
is_slipping = TRUE
return .
/mob/living/update_canmove()
. = ..()
if(is_slipping && !lying)
is_slipping = FALSE
return .

View File

@@ -1,18 +1,3 @@
/mob/living/proc/CanStumbleVore(mob/living/target)
if(!can_be_drop_pred)
return FALSE
if(is_incorporeal() || target.is_incorporeal())
return FALSE
if(!is_vore_predator(src))
return FALSE
if(!target.devourable)
return FALSE
if(!target.can_be_drop_prey)
return FALSE
if(!target.stumble_vore || !stumble_vore)
return FALSE
return TRUE
/mob/living/Bump(atom/movable/AM) /mob/living/Bump(atom/movable/AM)
//. = ..() //. = ..()
if(isliving(AM)) if(isliving(AM))
@@ -30,32 +15,27 @@
..() ..()
/mob/living/stumble_into(mob/living/M) /mob/living/stumble_into(mob/living/M)
var/mob/living/carbon/human/S = src if(buckled || M.buckled)
if(S.buckled || M.buckled)
return return
//Stumblevore occurs here. Look at the 'stumblevore' element for more information.
if(SEND_SIGNAL(src, COMSIG_LIVING_STUMBLED_INTO, M) & CANCEL_STUMBLED_INTO)
return
playsound(src, "punch", 25, 1, -1) playsound(src, "punch", 25, 1, -1)
M.Weaken(4) M.Weaken(4)
M.stop_flying() M.stop_flying()
if(CanStumbleVore(M)) //This is if the person stumbling into us is able to eat us!
visible_message(span_vwarning("[M] flops carelessly into [src]!"))
M.forceMove(get_turf(src))
begin_instant_nom(src,M,src,src.vore_selected)
return
if(M.CanStumbleVore(src)) //This is if the person stumbling into us is able to be eaten by us! BROKEN! if(ishuman(src))
visible_message(span_vwarning("[M] flops carelessly into [src]!")) var/mob/living/carbon/human/S = src
M.forceMove(get_turf(src)) if(S.species.lightweight == 1)
begin_instant_nom(M,src,M,M.vore_selected) visible_message(span_vwarning("[M] carelessly bowls [src] over!"))
return M.forceMove(get_turf(src))
M.apply_damage(0.5, BRUTE)
if(istype(S) && S.species.lightweight == 1) Weaken(4)
visible_message(span_vwarning("[M] carelessly bowls [src] over!")) stop_flying()
M.forceMove(get_turf(src)) apply_damage(0.5, BRUTE)
M.apply_damage(0.5, BRUTE) return
Weaken(4)
stop_flying()
apply_damage(0.5, BRUTE)
return
if(round(weight) > 474) if(round(weight) > 474)
var/throwtarget = get_edge_target_turf(M, reverse_direction(M.dir)) var/throwtarget = get_edge_target_turf(M, reverse_direction(M.dir))

View File

@@ -763,6 +763,7 @@
#include "code\datums\elements\lootable\misc.dm" #include "code\datums\elements\lootable\misc.dm"
#include "code\datums\elements\lootable\surface.dm" #include "code\datums\elements\lootable\surface.dm"
#include "code\datums\elements\lootable\trash.dm" #include "code\datums\elements\lootable\trash.dm"
#include "code\datums\elements\vore\spontaneous_vore.dm"
#include "code\datums\game_masters\_common.dm" #include "code\datums\game_masters\_common.dm"
#include "code\datums\helper_datums\construction_datum.dm" #include "code\datums\helper_datums\construction_datum.dm"
#include "code\datums\helper_datums\events.dm" #include "code\datums\helper_datums\events.dm"