mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-27 22:17:32 +01:00
First commit of context-based grab from Bay12
This is the first commit to the context based grab system ported from baystation 12. It includes the first 4 baystation commits. More commits will be added as their system is developed.
This commit is contained in:
@@ -226,4 +226,32 @@
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, inrange, params)
|
||||
return
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/grab_joint(var/mob/living/user, var/def_zone)
|
||||
var/has_grab = 0
|
||||
for(var/obj/item/weapon/grab/G in list(user.l_hand, user.r_hand))
|
||||
if(G.affecting == src && G.state == GRAB_NECK)
|
||||
has_grab = 1
|
||||
break
|
||||
|
||||
if(!has_grab)
|
||||
return 0
|
||||
|
||||
if(!def_zone) def_zone = user.zone_sel.selecting
|
||||
var/target_zone = check_zone(def_zone)
|
||||
if(!target_zone)
|
||||
return 0
|
||||
var/obj/item/organ/external/organ = get_organ(check_zone(target_zone))
|
||||
if(!organ || organ.is_broken())
|
||||
return 0
|
||||
|
||||
if(organ.limb_name == "chest" || organ.limb_name == "groin")
|
||||
return 0 //what how do you dislocate a chest with your hands or a groin really
|
||||
|
||||
user.visible_message("<span class='warning'>[user] begins to dislocate [src]'s [organ.name]!</span>")
|
||||
if(do_after(user, 100))
|
||||
organ.fracture()
|
||||
src.visible_message("<span class='danger'>[src]'s [organ.name] [pick("cracks","gives way","snaps","collapses")]!</span>")
|
||||
return 1
|
||||
return 0
|
||||
@@ -264,6 +264,11 @@
|
||||
if(!(status_flags & CANPUSH))
|
||||
return 0
|
||||
|
||||
for(var/obj/item/weapon/grab/G in src.grabbed_by)
|
||||
if(G.assailant == user)
|
||||
user << "<span class='notice'>You already grabbed [src].</span>"
|
||||
return
|
||||
|
||||
add_logs(user, src, "grabbed", addition="passively")
|
||||
|
||||
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(user, src)
|
||||
@@ -276,5 +281,11 @@
|
||||
LAssailant = user
|
||||
|
||||
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
if(!supress_message)
|
||||
visible_message("<span class='warning'>[user] has grabbed [src] passively!</span>")
|
||||
if(user.dir == src.dir)
|
||||
G.state = GRAB_AGGRESSIVE
|
||||
G.adjust_position()
|
||||
if(!supress_message)
|
||||
visible_message("<span class='warning'>[user] has grabbed [src] from behind!</span>")
|
||||
else
|
||||
if(!supress_message)
|
||||
visible_message("<span class='warning'>[user] has grabbed [src] passively!</span>")
|
||||
|
||||
+122
-55
@@ -5,11 +5,13 @@
|
||||
name = "grab"
|
||||
flags = NOBLUDGEON | ABSTRACT
|
||||
var/obj/screen/grab/hud = null
|
||||
var/mob/affecting = null
|
||||
var/mob/living/affecting = null
|
||||
var/mob/assailant = null
|
||||
var/state = GRAB_PASSIVE
|
||||
|
||||
var/allow_upgrade = 1
|
||||
var/last_upgrade = 0
|
||||
var/last_hit_zone = 0
|
||||
|
||||
layer = 21
|
||||
item_state = "nothing"
|
||||
@@ -28,8 +30,12 @@
|
||||
|
||||
hud = new /obj/screen/grab(src)
|
||||
hud.icon_state = "reinforce"
|
||||
icon_state = "grabbed"
|
||||
hud.name = "reinforce grab"
|
||||
hud.master = src
|
||||
|
||||
last_upgrade = world.time //makes it so you can't insta-agressive-grab.
|
||||
|
||||
//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)
|
||||
@@ -64,10 +70,12 @@
|
||||
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
|
||||
@@ -75,17 +83,38 @@
|
||||
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)
|
||||
if(G.state >= GRAB_AGGRESSIVE)
|
||||
allow_upgrade = 0
|
||||
|
||||
if(allow_upgrade)
|
||||
hud.icon_state = "reinforce"
|
||||
if(state < GRAB_AGGRESSIVE)
|
||||
hud.icon_state = "reinforce"
|
||||
else
|
||||
hud.icon_state = "reinforce1"
|
||||
else
|
||||
hud.icon_state = "!reinforce"
|
||||
else
|
||||
if(!affecting.buckled)
|
||||
affecting.loc = assailant.loc
|
||||
|
||||
if(state >= GRAB_AGGRESSIVE)
|
||||
var/hit_zone = assailant.zone_sel.selecting
|
||||
var/announce = 0
|
||||
if(hit_zone != last_hit_zone)
|
||||
announce = 1
|
||||
last_hit_zone = hit_zone
|
||||
switch(hit_zone)
|
||||
if("mouth")
|
||||
if(announce)
|
||||
assailant.visible_message("<span class='warning'>[assailant] covers [affecting]'s mouth!</span>")
|
||||
if(affecting.silent < 3)
|
||||
affecting.silent = 3
|
||||
if("eyes")
|
||||
if(announce)
|
||||
assailant.visible_message("<span class='warning'>[assailant] covers [affecting]'s eyes!</span>")
|
||||
if(affecting.eye_blind < 3)
|
||||
affecting.eye_blind = 3
|
||||
|
||||
if(state >= GRAB_NECK)
|
||||
affecting.Stun(5) //It will hamper your voice, being choked and all.
|
||||
if(isliving(affecting))
|
||||
@@ -95,10 +124,46 @@
|
||||
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)
|
||||
|
||||
//Updating pixelshift, position and direction
|
||||
//Gets called on process, when the grab gets upgraded or the assailant moves
|
||||
/obj/item/weapon/grab/proc/adjust_position()
|
||||
if(affecting.buckled)
|
||||
return
|
||||
var/shift = 0
|
||||
var/adir = get_dir(assailant, affecting)
|
||||
affecting.layer = 4
|
||||
switch(state)
|
||||
if(GRAB_PASSIVE)
|
||||
shift = 6
|
||||
if(GRAB_AGGRESSIVE)
|
||||
shift = 12
|
||||
if(GRAB_NECK, GRAB_UPGRADING)
|
||||
shift = -10
|
||||
adir = assailant.dir
|
||||
affecting.set_dir(assailant.dir)
|
||||
affecting.loc = assailant.loc
|
||||
if(GRAB_KILL)
|
||||
shift = 0
|
||||
adir = 1
|
||||
affecting.set_dir(reverse_dir[assailant.dir])
|
||||
affecting.loc = assailant.loc
|
||||
affecting.lying = 1
|
||||
|
||||
switch(adir)
|
||||
if(NORTH)
|
||||
animate(affecting, pixel_x = 0, pixel_y =-shift, 5, 1, LINEAR_EASING)
|
||||
affecting.layer = 3.9
|
||||
if(SOUTH)
|
||||
animate(affecting, pixel_x = 0, pixel_y = shift, 5, 1, LINEAR_EASING)
|
||||
if(WEST)
|
||||
animate(affecting, pixel_x = shift, pixel_y = 0, 5, 1, LINEAR_EASING)
|
||||
if(EAST)
|
||||
animate(affecting, pixel_x =-shift, pixel_y = 0, 5, 1, LINEAR_EASING)
|
||||
|
||||
/obj/item/weapon/grab/proc/s_click(obj/screen/S)
|
||||
if(!affecting)
|
||||
return
|
||||
@@ -111,6 +176,7 @@
|
||||
if(!assailant.canmove || assailant.lying)
|
||||
del(src)
|
||||
return
|
||||
|
||||
last_upgrade = world.time
|
||||
|
||||
if(state < GRAB_AGGRESSIVE)
|
||||
@@ -119,56 +185,38 @@
|
||||
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
|
||||
hud.icon_state = "reinforce1"
|
||||
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"
|
||||
assailant.visible_message("<span class='warning'>[assailant] has reinforced \his grip on [affecting] (now neck)!</span>")
|
||||
state = GRAB_NECK
|
||||
icon_state = "grabbed+1"
|
||||
assailant.set_dir(get_dir(assailant, affecting))
|
||||
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
|
||||
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
|
||||
affecting.LAssailant = assailant
|
||||
hud.icon_state = "kill"
|
||||
hud.name = "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 = "kill1"
|
||||
|
||||
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>"
|
||||
msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]")
|
||||
|
||||
assailant.next_move = world.time + 10
|
||||
affecting.losebreath += 1
|
||||
adjust_position()
|
||||
|
||||
//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()
|
||||
@@ -187,9 +235,20 @@
|
||||
if(!affecting)
|
||||
return
|
||||
|
||||
if(ishuman(M) && assailant.a_intent == "harm" && M == affecting)
|
||||
var/mob/living/carbon/human/victim = M
|
||||
if(state < GRAB_NECK)
|
||||
assailant << "<span class='warning'>You require a better grab to do this.</span>"
|
||||
return
|
||||
|
||||
if(victim.grab_joint(assailant))
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
return
|
||||
|
||||
if(M == affecting)
|
||||
s_click(hud)
|
||||
return
|
||||
|
||||
if(M == assailant && state >= GRAB_AGGRESSIVE)
|
||||
if( (ishuman(user) && (FAT in user.mutations) && iscarbon(affecting) ) || ( isalien(user) && iscarbon(affecting) ) || ( istype(user,/mob/living/carbon/human/kidan) && istype(affecting,/mob/living/carbon/monkey/diona) ) || ( ishuman(user) && user.get_species() == "Tajaran" && istype(affecting,/mob/living/simple_animal/mouse) ) )
|
||||
var/mob/living/carbon/attacker = user
|
||||
@@ -207,7 +266,15 @@
|
||||
/obj/item/weapon/grab/dropped()
|
||||
del(src)
|
||||
|
||||
/obj/item/weapon/grab/Del()
|
||||
//make sure the grabbed_by list doesn't fill up with nulls
|
||||
if(affecting) affecting.grabbed_by -= src
|
||||
..()
|
||||
|
||||
/obj/item/weapon/grab/Destroy()
|
||||
affecting.pixel_x = 0
|
||||
affecting.pixel_y = 0 //used to be an animate, not quick enough for del'ing
|
||||
affecting.layer = initial(affecting.layer)
|
||||
if(affecting) affecting.grabbed_by -= src
|
||||
del(hud)
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -322,6 +322,11 @@
|
||||
. = ..()
|
||||
mob.last_movement=world.time
|
||||
|
||||
for (var/obj/item/weapon/grab/G in mob)
|
||||
if (G.state == GRAB_NECK)
|
||||
mob.set_dir(reverse_dir[direct])
|
||||
G.adjust_position()
|
||||
|
||||
moving = 0
|
||||
|
||||
return .
|
||||
|
||||
Reference in New Issue
Block a user