mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-01-11 10:02:24 +00:00
This refactors the mob-eat-mob code and fixes a few bugs along the way. - Bursting out of a stomach now has a 0.4 second delay between attacks, so the message cannot be spammed. - The list of mobs that can eat other mobs has been refactored to be a subproc instead of a 255char~ list on one line. - Mob grab uses #defines for the time it takes to eat something else, now. - Fixed xenomorphs bugging out the grab system, and made sure that fat people can't actually eat them because of this.
250 lines
8.1 KiB
Plaintext
250 lines
8.1 KiB
Plaintext
#define UPGRADE_COOLDOWN 40
|
|
#define UPGRADE_KILL_TIMER 100
|
|
|
|
//times it takes for a mob to eat
|
|
#define EAT_TIME_XENO 30
|
|
#define EAT_TIME_FAT 100
|
|
|
|
//time it takes for a mob to be eaten (in deciseconds) (overrides mob eat time)
|
|
#define EAT_TIME_MOUSE 30
|
|
|
|
/obj/item/weapon/grab
|
|
name = "grab"
|
|
flags = NOBLUDGEON | ABSTRACT
|
|
var/obj/screen/grab/hud = null
|
|
var/mob/affecting = null
|
|
var/mob/assailant = null
|
|
var/state = GRAB_PASSIVE
|
|
var/allow_upgrade = 1
|
|
var/last_upgrade = 0
|
|
|
|
layer = 21
|
|
item_state = "nothing"
|
|
w_class = 5.0
|
|
|
|
|
|
/obj/item/weapon/grab/New(mob/user, mob/victim)
|
|
..()
|
|
loc = user
|
|
assailant = user
|
|
affecting = victim
|
|
|
|
if(affecting.anchored)
|
|
del(src)
|
|
return
|
|
|
|
hud = new /obj/screen/grab(src)
|
|
hud.icon_state = "reinforce"
|
|
hud.name = "reinforce grab"
|
|
hud.master = src
|
|
//Used by throw code to hand over the mob, instead of throwing the grab. The grab is then deleted by the throw code.
|
|
/obj/item/weapon/grab/proc/throw()
|
|
if(affecting)
|
|
if(affecting.buckled)
|
|
return null
|
|
if(state >= GRAB_AGGRESSIVE)
|
|
return affecting
|
|
return null
|
|
|
|
//This makes sure that the grab screen object is displayed in the correct hand.
|
|
/obj/item/weapon/grab/proc/synch()
|
|
if(affecting)
|
|
if(assailant.r_hand == src)
|
|
hud.screen_loc = ui_rhand
|
|
else
|
|
hud.screen_loc = ui_lhand
|
|
|
|
|
|
/obj/item/weapon/grab/process()
|
|
confirm()
|
|
|
|
if(assailant.client)
|
|
assailant.client.screen -= hud
|
|
assailant.client.screen += hud
|
|
|
|
if(assailant.pulling == affecting)
|
|
assailant.stop_pulling()
|
|
|
|
if(state <= GRAB_AGGRESSIVE)
|
|
allow_upgrade = 1
|
|
if((assailant.l_hand && assailant.l_hand != src && istype(assailant.l_hand, /obj/item/weapon/grab)))
|
|
var/obj/item/weapon/grab/G = assailant.l_hand
|
|
if(G.affecting != affecting)
|
|
allow_upgrade = 0
|
|
if((assailant.r_hand && assailant.r_hand != src && istype(assailant.r_hand, /obj/item/weapon/grab)))
|
|
var/obj/item/weapon/grab/G = assailant.r_hand
|
|
if(G.affecting != affecting)
|
|
allow_upgrade = 0
|
|
if(state == GRAB_AGGRESSIVE)
|
|
var/h = affecting.hand
|
|
affecting.hand = 0
|
|
affecting.drop_item()
|
|
affecting.hand = 1
|
|
affecting.drop_item()
|
|
affecting.hand = h
|
|
for(var/obj/item/weapon/grab/G in affecting.grabbed_by)
|
|
if(G == src) continue
|
|
if(G.state == GRAB_AGGRESSIVE)
|
|
allow_upgrade = 0
|
|
if(allow_upgrade)
|
|
hud.icon_state = "reinforce"
|
|
else
|
|
hud.icon_state = "!reinforce"
|
|
else
|
|
if(!affecting.buckled)
|
|
affecting.loc = assailant.loc
|
|
if(state >= GRAB_NECK)
|
|
affecting.Stun(5) //It will hamper your voice, being choked and all.
|
|
if(isliving(affecting))
|
|
var/mob/living/L = affecting
|
|
L.adjustOxyLoss(1)
|
|
|
|
if(state >= GRAB_KILL)
|
|
affecting.Weaken(5) //Should keep you down unless you get help.
|
|
affecting.losebreath = min(affecting.losebreath + 2, 3)
|
|
|
|
/obj/item/weapon/grab/attack_self(mob/user)
|
|
s_click(hud)
|
|
|
|
/obj/item/weapon/grab/proc/s_click(obj/screen/S)
|
|
if(!affecting)
|
|
return
|
|
if(state == GRAB_UPGRADING)
|
|
return
|
|
if(assailant.next_move > world.time)
|
|
return
|
|
if(world.time < (last_upgrade + UPGRADE_COOLDOWN))
|
|
return
|
|
if(!assailant.canmove || assailant.lying)
|
|
del(src)
|
|
return
|
|
last_upgrade = world.time
|
|
|
|
if(state < GRAB_AGGRESSIVE)
|
|
if(!allow_upgrade)
|
|
return
|
|
assailant.visible_message("<span class='warning'>[assailant] has grabbed [affecting] aggressively (now hands)!</span>")
|
|
state = GRAB_AGGRESSIVE
|
|
icon_state = "grabbed1"
|
|
else
|
|
if(state < GRAB_NECK)
|
|
if(isslime(affecting))
|
|
assailant << "<span class='notice'>You squeeze [affecting], but nothing interesting happens.</span>"
|
|
return
|
|
|
|
assailant.visible_message("<span class='warning'>[assailant] has reinforced \his grip on [affecting] (now neck)!</span>")
|
|
state = GRAB_NECK
|
|
icon_state = "grabbed+1"
|
|
if(!affecting.buckled)
|
|
affecting.loc = assailant.loc
|
|
affecting.attack_log += "\[[time_stamp()]\] <font color='orange'>Has had their neck grabbed by [assailant.name] ([assailant.ckey])</font>"
|
|
assailant.attack_log += "\[[time_stamp()]\] <font color='red'>Grabbed the neck of [affecting.name] ([affecting.ckey])</font>"
|
|
log_attack("<font color='red'>[assailant.name] ([assailant.ckey]) grabbed the neck of [affecting.name] ([affecting.ckey])</font>")
|
|
if(!iscarbon(assailant))
|
|
affecting.LAssailant = null
|
|
else
|
|
affecting.LAssailant = assailant
|
|
hud.icon_state = "disarm/kill"
|
|
hud.name = "disarm/kill"
|
|
else
|
|
if(state < GRAB_UPGRADING)
|
|
assailant.visible_message("<span class='danger'>[assailant] starts to tighten \his grip on [affecting]'s neck!</span>")
|
|
hud.icon_state = "disarm/kill1"
|
|
state = GRAB_UPGRADING
|
|
if(do_after(assailant, UPGRADE_KILL_TIMER))
|
|
if(state == GRAB_KILL)
|
|
return
|
|
if(!affecting)
|
|
del(src)
|
|
return
|
|
if(!assailant.canmove || assailant.lying)
|
|
del(src)
|
|
return
|
|
state = GRAB_KILL
|
|
assailant.visible_message("<span class='danger'>[assailant] has tightened \his grip on [affecting]'s neck!</span>")
|
|
affecting.attack_log += "\[[time_stamp()]\] <font color='orange'>Has been strangled (kill intent) by [assailant.name] ([assailant.ckey])</font>"
|
|
assailant.attack_log += "\[[time_stamp()]\] <font color='red'>Strangled (kill intent) [affecting.name] ([affecting.ckey])</font>"
|
|
log_attack("<font color='red'>[assailant.name] ([assailant.ckey]) Strangled (kill intent) [affecting.name] ([affecting.ckey])</font>")
|
|
if(!iscarbon(assailant))
|
|
affecting.LAssailant = null
|
|
else
|
|
affecting.LAssailant = assailant
|
|
assailant.changeNext_move(CLICK_CD_TKSTRANGLE)
|
|
affecting.losebreath += 1
|
|
else
|
|
assailant.visible_message("<span class='warning'>[assailant] was unable to tighten \his grip on [affecting]'s neck!</span>")
|
|
hud.icon_state = "disarm/kill"
|
|
state = GRAB_NECK
|
|
|
|
|
|
//This is used to make sure the victim hasn't managed to yackety sax away before using the grab.
|
|
/obj/item/weapon/grab/proc/confirm()
|
|
if(!assailant || !affecting)
|
|
del(src)
|
|
return 0
|
|
|
|
if(affecting)
|
|
if(!isturf(assailant.loc) || ( !isturf(affecting.loc) || assailant.loc != affecting.loc && get_dist(assailant, affecting) > 1) )
|
|
del(src)
|
|
return 0
|
|
return 1
|
|
|
|
|
|
/obj/item/weapon/grab/attack(mob/M, mob/user)
|
|
if(!affecting)
|
|
return
|
|
|
|
if(M == affecting) //what the actual fuck is this
|
|
s_click(hud)
|
|
return
|
|
|
|
if(M == assailant && state >= GRAB_AGGRESSIVE) //no eatin unless you have an agressive grab
|
|
if(checkvalid(user, affecting)) //wut
|
|
var/mob/living/carbon/attacker = user
|
|
user.visible_message("<span class='danger'>[user] is attempting to devour \the [affecting]!</span>")
|
|
|
|
if(!do_mob(user, affecting) || !do_after(user, checktime(user, affecting))) return
|
|
|
|
user.visible_message("<span class='danger'>[user] devours \the [affecting]!</span>")
|
|
|
|
affecting.loc = user //add the mob to the user
|
|
attacker.stomach_contents.Add(affecting) //list keeping
|
|
|
|
del(src)
|
|
|
|
/obj/item/weapon/grab/proc/checkvalid(var/mob/attacker, var/mob/prey) //does all the checking for the attack proc to see if a mob can eat another with the grab
|
|
if(ishuman(attacker) && (FAT in attacker.mutations) && iscarbon(prey)) //Fat people eating carbon mobs
|
|
return 1
|
|
|
|
if(isalien(attacker) && iscarbon(prey)) //Xenomorphs eating carbon mobs
|
|
return 1
|
|
|
|
if(ishuman(attacker) && attacker.get_species() == "Kidan" && istype(prey,/mob/living/carbon/monkey/diona)) //Kidan eating nymphs
|
|
return 1
|
|
|
|
if(ishuman(attacker) && attacker.get_species() == "Tajaran" && istype(prey,/mob/living/simple_animal/mouse)) //Tajaran eating mice. Meow!
|
|
return 1
|
|
|
|
return 0
|
|
|
|
/obj/item/weapon/grab/proc/checktime(var/mob/attacker, var/mob/prey) //Returns the time the attacker has to wait before they eat the prey
|
|
if(isalien(attacker))
|
|
return EAT_TIME_XENO //xenos get a speed boost
|
|
|
|
if(istype(prey,/mob/living/simple_animal/mouse)) //mice get eaten at xeno-eating-speed regardless
|
|
return EAT_TIME_MOUSE
|
|
|
|
return EAT_TIME_FAT //if it doesn't fit into the above, it's probably a fat guy, take EAT_TIME_FAT to do it
|
|
|
|
/obj/item/weapon/grab/dropped()
|
|
del(src)
|
|
|
|
|
|
/obj/item/weapon/grab/Destroy()
|
|
del(hud)
|
|
..()
|
|
|
|
#undef EAT_TIME_XENO
|
|
#undef EAT_TIME_FAT
|
|
|
|
#undef EAT_TIME_MOUSE |