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:
Tigercat2000
2015-04-25 10:37:01 -07:00
parent 7bb0108a60
commit ccfde28c4e
6 changed files with 174 additions and 58 deletions
@@ -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
+13 -2
View File
@@ -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
View File
@@ -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)
..()
..()
+5
View File
@@ -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 .