#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("[assailant] has grabbed [affecting] aggressively (now hands)!") state = GRAB_AGGRESSIVE icon_state = "grabbed1" else if(state < GRAB_NECK) if(isslime(affecting)) assailant << "You squeeze [affecting], but nothing interesting happens." return assailant.visible_message("[assailant] has reinforced \his grip on [affecting] (now neck)!") state = GRAB_NECK icon_state = "grabbed+1" if(!affecting.buckled) affecting.loc = assailant.loc affecting.attack_log += "\[[time_stamp()]\] Has had their neck grabbed by [assailant.name] ([assailant.ckey])" assailant.attack_log += "\[[time_stamp()]\] Grabbed the neck of [affecting.name] ([affecting.ckey])" log_attack("[assailant.name] ([assailant.ckey]) grabbed the neck of [affecting.name] ([affecting.ckey])") 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("[assailant] starts to tighten \his grip on [affecting]'s neck!") 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("[assailant] has tightened \his grip on [affecting]'s neck!") affecting.attack_log += "\[[time_stamp()]\] Has been strangled (kill intent) by [assailant.name] ([assailant.ckey])" assailant.attack_log += "\[[time_stamp()]\] Strangled (kill intent) [affecting.name] ([affecting.ckey])" log_attack("[assailant.name] ([assailant.ckey]) Strangled (kill intent) [affecting.name] ([affecting.ckey])") if(!iscarbon(assailant)) affecting.LAssailant = null else affecting.LAssailant = assailant assailant.changeNext_move(CLICK_CD_TKSTRANGLE) affecting.losebreath += 1 else assailant.visible_message("[assailant] was unable to tighten \his grip on [affecting]'s neck!") 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("[user] is attempting to devour \the [affecting]!") if(!do_mob(user, affecting) || !do_after(user, checktime(user, affecting))) return user.visible_message("[user] devours \the [affecting]!") 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) && !isalien(prey)) //Fat people eating carbon mobs but not xenos 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