Merge pull request #1956 from Yoshax/harpiesports

Various Bay Ports
This commit is contained in:
EmperorJon
2016-06-21 17:31:29 +01:00
committed by GitHub
21 changed files with 161 additions and 80 deletions

View File

@@ -122,7 +122,7 @@
var/mob/living/carbon/human/H = target
affecting = H.get_organ(hit_zone)
if(user.a_intent == I_HURT)
if(user.a_intent == I_HURT || user.a_intent == I_DISARM)
. = ..()
//whacking someone causes a much poorer electrical contact than deliberately prodding them.
agony *= 0.5

View File

@@ -114,6 +114,11 @@ var/list/holder_mob_icon_cache = list()
if(!holder_type || buckled || pinned.len)
return
if(self_grab)
if(src.incapacitated()) return
else
if(grabber.incapacitated()) return
var/obj/item/weapon/holder/H = new holder_type(get_turf(src))
H.held_mob = src
src.forceMove(H)

View File

@@ -194,7 +194,7 @@
status += "hurts when touched"
if(org.status & ORGAN_DEAD)
status += "is bruised and necrotic"
if(!org.is_usable())
if(!org.is_usable() || org.is_dislocated())
status += "dangling uselessly"
if(status.len)
src.show_message("My [org.name] is <span class='warning'> [english_list(status)].</span>",1)
@@ -309,14 +309,19 @@
if(!item) return
var/throw_range = item.throw_range
if (istype(item, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = item
item = G.throw_held() //throw the person instead of the grab
if(ismob(item))
var/mob/M = item
//limit throw range by relative mob size
throw_range = round(M.throw_range * min(src.mob_size/M.mob_size, 1))
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
var/turf/end_T = get_turf(target)
if(start_T && end_T)
var/mob/M = item
var/start_T_descriptor = "<font color='#6b5d00'>tile at [start_T.x], [start_T.y], [start_T.z] in area [get_area(start_T)]</font>"
var/end_T_descriptor = "<font color='#6b4400'>tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]</font>"
@@ -324,31 +329,28 @@
usr.attack_log += text("\[[time_stamp()]\] <font color='red'>Has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]</font>")
msg_admin_attack("[usr.name] ([usr.ckey]) has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[usr.x];Y=[usr.y];Z=[usr.z]'>JMP</a>)")
if(!item) return //Grab processing has a chance of returning null
src.remove_from_mob(item)
item.loc = src.loc
src.drop_from_inventory(item)
if(!item || !isturf(item.loc))
return
//actually throw it!
if (item)
src.visible_message("\red [src] has thrown [item].")
src.visible_message("<span class='warning'>[src] has thrown [item].</span>")
if(!src.lastarea)
src.lastarea = get_area(src.loc)
if((istype(src.loc, /turf/space)) || (src.lastarea.has_gravity == 0))
src.inertia_dir = get_dir(target, src)
step(src, inertia_dir)
if(!src.lastarea)
src.lastarea = get_area(src.loc)
if((istype(src.loc, /turf/space)) || (src.lastarea.has_gravity == 0))
src.inertia_dir = get_dir(target, src)
step(src, inertia_dir)
/*
if(istype(src.loc, /turf/space) || (src.flags & NOGRAV)) //they're in space, move em one space in the opposite direction
src.inertia_dir = get_dir(target, src)
step(src, inertia_dir)
if(istype(src.loc, /turf/space) || (src.flags & NOGRAV)) //they're in space, move em one space in the opposite direction
src.inertia_dir = get_dir(target, src)
step(src, inertia_dir)
*/
item.throw_at(target, item.throw_range, item.throw_speed, src)
item.throw_at(target, throw_range, item.throw_speed, src)
/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()

View File

@@ -1324,8 +1324,8 @@
var/list/limbs = list()
for(var/limb in organs_by_name)
var/obj/item/organ/external/current_limb = organs_by_name[limb]
if(current_limb && current_limb.dislocated == 2)
limbs |= limb
if(current_limb && current_limb.dislocated > 0 && !current_limb.is_parent_dislocated()) //if the parent is also dislocated you will have to relocate that first
limbs |= current_limb
var/choice = input(usr,"Which joint do you wish to relocate?") as null|anything in limbs
if(!choice)

View File

@@ -326,7 +326,7 @@
if(!target_zone)
return 0
var/obj/item/organ/external/organ = get_organ(check_zone(target_zone))
if(!organ || organ.is_dislocated() || organ.dislocated == -1)
if(!organ || organ.dislocated > 0 || organ.dislocated == -1) //don't use is_dislocated() here, that checks parent
return 0
user.visible_message("<span class='warning'>[user] begins to dislocate [src]'s [organ.joint]!</span>")

View File

@@ -187,11 +187,13 @@ emp_act
// Handle striking to cripple.
if(user.a_intent == I_DISARM)
effective_force /= 2
if(..(I, user, effective_force, blocked, hit_zone))
attack_joint(affecting, I, blocked)
else
effective_force *= 0.66 //reduced effective force...
if(!..(I, user, effective_force, blocked, hit_zone))
return 0
//set the dislocate mult less than the effective force mult so that
//dislocating limbs on disarm is a bit easier than breaking limbs on harm
attack_joint(affecting, I, effective_force, 0.5, blocked) //...but can dislocate joints
else if(!..())
return 0
@@ -242,10 +244,16 @@ emp_act
return 1
/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/blocked)
/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/effective_force, var/dislocate_mult, var/blocked)
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100)
return 0
if(prob(W.force * (100 - blocked)/100))
if(W.damtype != BRUTE)
return 0
//want the dislocation chance to be such that the limb is expected to dislocate after dealing a fraction of the damage needed to break the limb
var/dislocate_chance = effective_force/(dislocate_mult * organ.min_broken_damage * config.organ_health_multiplier)*100
if(prob(dislocate_chance * (100 - blocked)/100))
visible_message("<span class='danger'>[src]'s [organ.joint] [pick("gives way","caves in","crumbles","collapses")]!</span>")
organ.dislocate(1)
return 1

View File

@@ -68,7 +68,7 @@
/mob/living/carbon/human/proc/handle_stance()
// Don't need to process any of this if they aren't standing anyways
// unless their stance is damaged, and we want to check if they should stay down
if (!stance_damage && (lying || resting) && (life_tick % 4) == 0)
if (!stance_damage && (lying || resting) && (life_tick % 4) != 0)
return
stance_damage = 0
@@ -80,7 +80,7 @@
var/limb_pain
for(var/limb_tag in list("l_leg","r_leg","l_foot","r_foot"))
var/obj/item/organ/external/E = organs_by_name[limb_tag]
if(!E || (E.status & (ORGAN_MUTATED|ORGAN_DEAD)) || E.is_stump()) //should just be !E.is_usable() here but dislocation screws that up.
if(!E || !E.is_usable())
stance_damage += 2 // let it fail even if just foot&leg
else if (E.is_malfunctioning())
//malfunctioning only happens intermittently so treat it as a missing limb when it procs
@@ -93,7 +93,7 @@
spark_system.start()
spawn(10)
qdel(spark_system)
else if (E.is_broken() || !E.is_usable())
else if (E.is_broken())
stance_damage += 1
else if (E.is_dislocated())
stance_damage += 0.5

View File

@@ -847,7 +847,10 @@
if(!isSynthetic() && (species.flags & IS_PLANT) && (!light_organ || light_organ.is_broken()))
if(nutrition < 200)
take_overall_damage(2,0)
traumatic_shock++
//traumatic_shock is updated every tick, incrementing that is pointless - shock_stage is the counter.
//Not that it matters much for diona, who have NO_PAIN.
shock_stage++
// TODO: stomach and bloodstream organ.
if(!isSynthetic())

View File

@@ -190,6 +190,7 @@
/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs.
H.mob_size = mob_size
for(var/obj/item/organ/organ in H.contents)
if((organ in H.organs) || (organ in H.internal_organs))
qdel(organ)
@@ -249,7 +250,6 @@
H.mob_swap_flags = swap_flags
H.mob_push_flags = push_flags
H.pass_flags = pass_flags
H.mob_size = mob_size
/datum/species/proc/handle_death(var/mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns).
return

View File

@@ -23,8 +23,10 @@
if(istype(src,/mob/living/carbon/human))
var/mob/living/carbon/human/M = src
for(var/obj/item/organ/external/organ in M.organs)
if(organ && (organ.is_broken() || organ.open))
if(organ.is_broken() || organ.open)
src.traumatic_shock += 30
else if(organ.is_dislocated())
src.traumatic_shock += 15
if(src.traumatic_shock < 0)
src.traumatic_shock = 0

View File

@@ -623,26 +623,9 @@ default behaviour is:
/mob/living/proc/resist_grab()
var/resisting = 0
for(var/obj/O in requests)
requests.Remove(O)
qdel(O)
resisting++
for(var/obj/item/weapon/grab/G in grabbed_by)
resisting++
switch(G.state)
if(GRAB_PASSIVE)
qdel(G)
if(GRAB_AGGRESSIVE)
//Not standing up makes it much harder to break, so it is easier to cuff someone who is down without forcing them into unconsciousness.
//Otherwise, it's the same chance of breaking the grab as disarm.
if(incapacitated(INCAPACITATION_KNOCKDOWN)? prob(15) : prob(60))
visible_message("<span class='warning'>[src] has broken free of [G.assailant]'s grip!</span>")
qdel(G)
if(GRAB_NECK)
//If the you move when grabbing someone then it's easier for them to break free. Same if the affected mob is immune to stun.
if (((world.time - G.assailant.l_move_time < 30 || !stunned) && prob(15)) || prob(3))
visible_message("<span class='warning'>[src] has broken free of [G.assailant]'s headlock!</span>")
qdel(G)
G.handle_resist()
if(resisting)
visible_message("<span class='danger'>[src] resists!</span>")

View File

@@ -121,7 +121,6 @@
var/datum/hud/hud_used = null
var/list/grabbed_by = list( )
var/list/requests = list( )
var/list/mapobjs = list()

View File

@@ -3,10 +3,15 @@
///Process_Grab()
///Called by client/Move()
///Checks to see if you are grabbing anything and if moving will affect your grab.
///Checks to see if you are grabbing or being grabbed by anything and if moving will affect your grab.
/client/proc/Process_Grab()
if(istype(mob, /mob/living))
//if we are being grabbed
if(isliving(mob))
var/mob/living/L = mob
if(!L.canmove && L.grabbed_by.len)
L.resist() //shortcut for resisting grabs
//if we are grabbing someone
for(var/obj/item/weapon/grab/G in list(L.l_hand, L.r_hand))
G.reset_kill_state() //no wandering across the station/asteroid while choking someone
@@ -131,7 +136,7 @@
handle_eye_mouth_covering(affecting, assailant, assailant.zone_sel.selecting)
if(force_down)
if(affecting.loc != assailant.loc)
if(affecting.loc != assailant.loc || size_difference(affecting, assailant) > 0)
force_down = 0
else
affecting.Weaken(2)
@@ -232,7 +237,7 @@
if(state < GRAB_AGGRESSIVE)
if(!allow_upgrade)
return
if(!affecting.lying)
if(!affecting.lying || size_difference(affecting, assailant) > 0)
assailant.visible_message("<span class='warning'>[assailant] has grabbed [affecting] aggressively (now hands)!</span>")
else
assailant.visible_message("<span class='warning'>[assailant] pins [affecting] down to the ground (now hands)!</span>")
@@ -335,6 +340,40 @@
hud.icon_state = "kill"
state = GRAB_NECK
/obj/item/weapon/grab/proc/handle_resist()
var/grab_name
var/break_strength = 1
var/list/break_chance_table = list(100)
switch(state)
//if(GRAB_PASSIVE)
if(GRAB_AGGRESSIVE)
grab_name = "grip"
//Being knocked down makes it harder to break a grab, so it is easier to cuff someone who is down without forcing them into unconsciousness.
if(!affecting.incapacitated(INCAPACITATION_KNOCKDOWN))
break_strength++
break_chance_table = list(15, 60, 100)
if(GRAB_NECK)
grab_name = "headlock"
//If the you move when grabbing someone then it's easier for them to break free. Same if the affected mob is immune to stun.
if(world.time - assailant.l_move_time < 30 || !affecting.stunned)
break_strength++
break_chance_table = list(3, 18, 45, 100)
//It's easier to break out of a grab by a smaller mob
break_strength += max(size_difference(affecting, assailant), 0)
var/break_chance = break_chance_table[Clamp(break_strength, 1, break_chance_table.len)]
if(prob(break_chance))
if(grab_name)
affecting.visible_message("<span class='warning'>[affecting] has broken free of [assailant]'s [grab_name]!</span>")
qdel(src)
//returns the number of size categories between affecting and assailant, rounded. Positive means A is larger than B
/obj/item/weapon/grab/proc/size_difference(mob/A, mob/B)
return mob_size_difference(A.mob_size, B.mob_size)
/obj/item/weapon/grab
var/destroying = 0

View File

@@ -51,10 +51,16 @@
return
attacker.visible_message("<span class='danger'>[attacker] [pick("bent", "twisted")] [target]'s [organ.name] into a jointlock!</span>")
if(target.species.flags & NO_PAIN)
return
var/armor = target.run_armor_check(target, "melee")
if(armor < 60)
target << "<span class='danger'>You feel extreme pain!</span>"
affecting.adjustHalLoss(Clamp(0, 60-affecting.halloss, 30)) //up to 60 halloss
var/max_halloss = round(target.species.total_health * 0.8) //up to 80% of passing out
affecting.adjustHalLoss(Clamp(0, max_halloss - affecting.halloss, 30))
/obj/item/weapon/grab/proc/attack_eye(mob/living/carbon/human/target, mob/living/carbon/human/attacker)
if(!istype(attacker))
@@ -125,6 +131,10 @@
return
if(force_down)
attacker << "<span class='warning'>You are already pinning [target] to the ground.</span>"
return
if(size_difference(affecting, assailant) > 0)
attacker << "<span class='warning'>You are too small to do that!</span>"
return
attacker.visible_message("<span class='danger'>[attacker] starts forcing [target] to the ground!</span>")
if(do_after(attacker, 20) && target)

View File

@@ -5,6 +5,9 @@
return L.mob_size <= MOB_SMALL
return 0
//returns the number of size categories between two mob_sizes, rounded. Positive means A is larger than B
/proc/mob_size_difference(var/mob_size_A, var/mob_size_B)
return round(log(2, mob_size_A/mob_size_B), 1)
/proc/istiny(A)
if(A && istype(A, /mob/living))

View File

@@ -50,6 +50,7 @@ var/list/organ_cache = list()
max_damage = min_broken_damage * 2
if(istype(holder))
src.owner = holder
src.w_class = max(src.w_class + mob_size_difference(holder.mob_size, MOB_MEDIUM), 1) //smaller mobs have smaller organs.
species = all_species["Human"]
if(holder.dna)
dna = holder.dna.Clone()

View File

@@ -60,7 +60,7 @@
var/cannot_gib // Impossible to gib, distinct from amputation.
var/joint = "joint" // Descriptive string used in dislocation.
var/amputation_point // Descriptive string used in amputation.
var/dislocated = 0 // If you target a joint, you can dislocate the limb, causing temporary damage to the organ.
var/dislocated = 0 // If you target a joint, you can dislocate the limb, impairing it's usefulness and causing pain
var/encased // Needs to be opened with a saw to access the organs.
// Surgery vars.
@@ -156,32 +156,38 @@
/obj/item/organ/external/proc/is_dislocated()
if(dislocated > 0)
return 1
if(parent)
return parent.is_dislocated()
if(is_parent_dislocated())
return 1//if any parent is dislocated, we are considered dislocated as well
return 0
/obj/item/organ/external/proc/dislocate(var/primary)
if(dislocated != -1)
if(primary)
dislocated = 2
else
dislocated = 1
owner.verbs |= /mob/living/carbon/human/proc/undislocate
if(children && children.len)
for(var/obj/item/organ/external/child in children)
child.dislocate()
/obj/item/organ/external/proc/is_parent_dislocated()
var/obj/item/organ/external/O = parent
while(O && O.dislocated != -1)
if(O.dislocated == 1)
return 1
O = O.parent
return 0
/obj/item/organ/external/proc/dislocate()
if(dislocated == -1)
return
dislocated = 1
if(owner)
owner.verbs |= /mob/living/carbon/human/proc/undislocate
/obj/item/organ/external/proc/undislocate()
if(dislocated != -1)
dislocated = 0
if(children && children.len)
for(var/obj/item/organ/external/child in children)
if(child.dislocated == 1)
child.undislocate()
if(dislocated == -1)
return
dislocated = 0
if(owner)
owner.shock_stage += 20
//check to see if we still need the verb
for(var/obj/item/organ/external/limb in owner.organs)
if(limb.dislocated == 2)
if(limb.dislocated == 1)
return
owner.verbs -= /mob/living/carbon/human/proc/undislocate
@@ -1085,7 +1091,7 @@ Note that amputating the affected organ does in fact remove the infection from t
return 0
/obj/item/organ/external/proc/is_usable()
return !is_dislocated() && !(status & (ORGAN_MUTATED|ORGAN_DEAD))
return !(status & (ORGAN_MUTATED|ORGAN_DEAD))
/obj/item/organ/external/proc/is_malfunctioning()
return ((robotic >= ORGAN_ROBOT) && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam))

View File

@@ -206,4 +206,5 @@
amputation_point = "branch"
joint = "structural ligament"
dislocated = -1
vital = 0
vital = 0
slot_flags = SLOT_BELT

View File

@@ -2,6 +2,8 @@
ORGAN DEFINES
****************************************************/
//Make sure that w_class is set as if the parent mob was medium sized! This is because w_class is adjusted automatically for mob_size in New()
/obj/item/organ/external/chest
name = "upper body"
organ_tag = BP_TORSO
@@ -148,6 +150,7 @@
organ_tag = BP_HEAD
icon_name = "head"
name = "head"
slot_flags = SLOT_BELT
max_damage = 75
min_broken_damage = 35
w_class = 3

View File

@@ -0,0 +1,7 @@
author: HarpyEagle
delete-after: True
changes:
- bugfix: "Fixes disarm-attack dislocation chances being so low that you were very likely to break the targeted limb before it would dislocate."
- bugfix: "It is now possible to disarm-attack with stunbatons like with other melee weapons. Note that this means that using a stunbaton on disarm intent will hurt people."

View File

@@ -0,0 +1,9 @@
author: HarpyEagle
delete-after: True
changes:
- rscadd: "Trying to move while being grabbed will now automatically resist."
- tweak: "Small mobs are no longer able to pin larger mobs."
- tweak: "Resisting a smaller mob's grab is more likely to be successful."
- bugfix: "Fixed being able to climb onto a larger mob while restrained, weakened, unconscious, or dead."