diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index ca293307099..a05575f575d 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -54,6 +54,13 @@
#define AI_IDLE 2
#define AI_OFF 3
+//Attack types for checking shields/hit reactions
+
+#define MELEE_ATTACK 1
+#define UNARMED_ATTACK 2
+#define PROJECTILE_ATTACK 3
+#define THROWN_PROJECTILE_ATTACK 4
+
//Gun Stuff
#define SAWN_INTACT 0
#define SAWN_OFF 1
diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index e79d40f7176..0562d7086ab 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -4,10 +4,9 @@
#define NOBLUDGEON 4 // when an item has this it produces no "X has been hit by Y with Z" message with the default handler
#define AIRTIGHT 8 // mask allows internals
#define HANDSLOW 16 // If an item has this flag, it will slow you to carry it
-#define NOSHIELD 32 // weapon not affected by shield
-#define CONDUCT 64 // conducts electricity (metal etc.)
-#define ABSTRACT 128 // for all things that are technically items but used for various different stuff, made it 128 because it could conflict with other flags other way
-#define ON_BORDER 256 // item has priority to check when entering or leaving
+#define CONDUCT 32 // conducts electricity (metal etc.)
+#define ABSTRACT 64 // for all things that are technically items but used for various different stuff, made it 128 because it could conflict with other flags other way
+#define ON_BORDER 128 // item has priority to check when entering or leaving
#define GLASSESCOVERSEYES 1024
#define MASKCOVERSEYES 1024 // get rid of some of the other retardation in these flags
diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm
index f4d628deebd..765fbd0a5e1 100644
--- a/code/game/gamemodes/changeling/powers/mutations.dm
+++ b/code/game/gamemodes/changeling/powers/mutations.dm
@@ -206,6 +206,7 @@
flags = NODROP
icon = 'icons/obj/weapons.dmi'
icon_state = "ling_shield"
+ block_chance = 50
var/remaining_uses //Set by the changeling ability.
@@ -217,17 +218,17 @@
/obj/item/weapon/shield/changeling/dropped()
qdel(src)
-/obj/item/weapon/shield/changeling/IsShield()
+/obj/item/weapon/shield/changeling/hit_reaction()
if(remaining_uses < 1)
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
- H.visible_message("With a sickening crunch, [H] reforms his shield into an arm!", "We assimilate our shield into our body", "With a sickening crunch, [H] reforms his shield into an arm!", "We assimilate our shield into our body", "[owner] blocks [attack_text] with [src]!")
+ return 1
+ return 0
+
/obj/item/proc/talk_into(mob/M as mob, var/text, var/channel=null)
return
@@ -374,9 +383,6 @@
/obj/item/proc/ui_action_click()
attack_self(usr)
-/obj/item/proc/IsShield()
- return 0
-
/obj/item/proc/IsReflect(var/def_zone) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit
return 0
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 6c0cf78de6e..52fa28f58eb 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -141,7 +141,6 @@
item_state = "sword0"
var/active = 0.0
w_class = 2.0
- flags = NOSHIELD
attack_verb = list("attacked", "struck", "hit")
/obj/item/toy/sword/attack_self(mob/user as mob)
@@ -199,7 +198,7 @@
origin_tech = null
attack_verb = list("attacked", "struck", "hit")
-/obj/item/weapon/twohanded/dualsaber/toy/IsShield()
+/obj/item/weapon/twohanded/dualsaber/toy/hit_reaction()
return 0
/obj/item/weapon/twohanded/dualsaber/toy/IsReflect()//Stops Toy Dualsabers from reflecting energy projectiles
diff --git a/code/game/objects/items/weapons/alien_specific.dm b/code/game/objects/items/weapons/alien_specific.dm
index e4f6bcd7a75..c487af03cd6 100644
--- a/code/game/objects/items/weapons/alien_specific.dm
+++ b/code/game/objects/items/weapons/alien_specific.dm
@@ -14,7 +14,6 @@
throw_range = 5
w_class = 2
w_class_on = 2
- flags = NOSHIELD
attack_verb = list("attacked", "slashed", "gored", "sliced", "torn", "ripped", "butchered", "cut")
attack_verb_on = list()
diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm
index 75c1b030ed4..10394b2e236 100644
--- a/code/game/objects/items/weapons/flamethrower.dm
+++ b/code/game/objects/items/weapons/flamethrower.dm
@@ -191,10 +191,10 @@
return
-/obj/item/weapon/flamethrower/proc/ignite_turf(turf/target)
+/obj/item/weapon/flamethrower/proc/ignite_turf(turf/target, release_amount = 0.05)
//TODO: DEFERRED Consider checking to make sure tank pressure is high enough before doing this...
//Transfer 5% of current tank air contents to turf
- var/datum/gas_mixture/air_transfer = ptank.air_contents.remove_ratio(0.05)
+ var/datum/gas_mixture/air_transfer = ptank.air_contents.remove_ratio(release_amount)
air_transfer.toxins = air_transfer.toxins * 5 // This is me not comprehending the air system. I realize this is retarded and I could probably make it work without fucking it up like this, but there you have it. -- TLE
target.assume_air(air_transfer)
//Burn it based on transfered gas
@@ -218,4 +218,12 @@
/obj/item/weapon/flamethrower/full/tank/New(var/loc)
..()
ptank = new /obj/item/weapon/tank/plasma/full(src)
- update_icon()
\ No newline at end of file
+ update_icon()
+
+/obj/item/weapon/flamethrower/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance, damage, attack_type)
+ if(ptank && damage && attack_type == PROJECTILE_ATTACK && prob(15))
+ owner.visible_message("[attack_text] hits the fueltank on [owner]'s [src], rupturing it! What a shot!")
+ var/target_turf = get_turf(owner)
+ ignite_turf(target_turf, 100)
+ qdel(ptank)
+ return 1 //It hit the flamethrower, not them
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index a951f1ade8f..f130f61b7a8 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -102,6 +102,11 @@
spawn(det_time)
prime()
+/obj/item/weapon/grenade/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance, damage, attack_type)
+ if(damage && attack_type == PROJECTILE_ATTACK && prob(15))
+ owner.visible_message("[attack_text] hits [owner]'s [src], setting it off! What a shot!")
+ prime()
+ return 1 //It hit the grenade, not them
/obj/item/weapon/grenade/chem_grenade/attackby(obj/item/I, mob/user, params)
if(istype(I,/obj/item/weapon/hand_labeler))
diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm
index b56e103233e..ada15a3b108 100644
--- a/code/game/objects/items/weapons/holy_weapons.dm
+++ b/code/game/objects/items/weapons/holy_weapons.dm
@@ -76,9 +76,7 @@
w_class = 5
force = 5
slot_flags = SLOT_BACK
-
-/obj/item/weapon/nullrod/staff/IsShield()
- return 1
+ block_chance = 50
/obj/item/weapon/nullrod/staff/blue
name = "blue holy staff"
@@ -92,16 +90,16 @@
desc = "A weapon fit for a crusade!"
w_class = 4
slot_flags = SLOT_BACK|SLOT_BELT
+ block_chance = 30
sharp = 1
edge = 1
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
-/obj/item/weapon/nullrod/claymore/IsShield()
- if(prob(30))
- return 1
- else
- return 0
+/obj/item/weapon/nullrod/claymore/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance, damage, attack_type)
+ if(attack_type == PROJECTILE_ATTACK)
+ final_block_chance = 0 //Don't bring a sword to a gunfight
+ return ..()
/obj/item/weapon/nullrod/claymore/darkblade
icon_state = "cultblade"
@@ -333,6 +331,7 @@
desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts, now used to harass the clown."
w_class = 4
force = 15
+ block_chance = 40
slot_flags = SLOT_BACK
sharp = 0
edge = 0
@@ -342,12 +341,6 @@
icon_state = "bostaff0"
item_state = "bostaff0"
-/obj/item/weapon/nullrod/claymore/bostaff/IsShield()
- if(prob(40))
- return 1
- else
- return 0
-
/obj/item/weapon/nullrod/tribal_knife
icon_state = "crysknife"
item_state = "crysknife"
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 45b2f1f7452..79cad015653 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -62,7 +62,7 @@
w_class = 3
w_class_on = 5
hitsound = "swing_hit"
- flags = CONDUCT | NOSHIELD
+ flags = CONDUCT
armour_penetration = 100
origin_tech = "combat=3"
attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut")
@@ -83,9 +83,9 @@
throw_speed = 3
throw_range = 5
hitsound = "swing_hit"
- flags = NOSHIELD
armour_penetration = 35
origin_tech = "magnets=3;syndicate=4"
+ block_chance = 50
sharp = 1
edge = 1
var/hacked = 0
@@ -95,9 +95,9 @@
if(item_color == null)
item_color = pick("red", "blue", "green", "purple")
-/obj/item/weapon/melee/energy/sword/IsShield()
+/obj/item/weapon/melee/energy/sword/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance)
if(active)
- return 1
+ return ..()
return 0
/obj/item/weapon/melee/energy/sword/cyborg
@@ -133,7 +133,7 @@
..()
item_color = null
-/obj/item/weapon/melee/energy/sword/cyborg/saw/IsShield()
+/obj/item/weapon/melee/energy/sword/cyborg/saw/hit_reaction()
return 0
/obj/item/weapon/melee/energy/sword/saber
@@ -206,7 +206,6 @@
throw_speed = 3
throw_range = 1
w_class = 4//So you can't hide it in your pocket or some such.
- flags = NOSHIELD
armour_penetration = 50
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
var/datum/effect/system/spark_spread/spark_system
diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm
index a161755c285..809bf0d298d 100644
--- a/code/game/objects/items/weapons/shields.dm
+++ b/code/game/objects/items/weapons/shields.dm
@@ -1,5 +1,6 @@
/obj/item/weapon/shield
name = "shield"
+ block_chance = 50
/obj/item/weapon/shield/riot
name = "riot shield"
@@ -17,8 +18,10 @@
attack_verb = list("shoved", "bashed")
var/cooldown = 0 //shield bash cooldown. based on world.time
-/obj/item/weapon/shield/riot/IsShield()
- return 1
+/obj/item/weapon/shield/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance, damage, attack_type)
+ if(attack_type == THROWN_PROJECTILE_ATTACK)
+ final_block_chance += 30
+ return ..()
/obj/item/weapon/shield/riot/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/weapon/melee/baton))
@@ -41,12 +44,7 @@
icon_state = "buckler"
item_state = "buckler"
materials = list()
-
-/obj/item/weapon/shield/riot/buckler/IsShield()
- if(prob(60))
- return 1
- else
- return 0
+ block_chance = 30
/obj/item/weapon/shield/energy
name = "energy combat shield"
@@ -62,8 +60,8 @@
attack_verb = list("shoved", "bashed")
var/active = 0
-/obj/item/weapon/shield/energy/IsShield()
- return (active)
+/obj/item/weapon/shield/energy/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance)
+ return 0
/obj/item/weapon/shield/energy/IsReflect()
return (active)
@@ -109,8 +107,10 @@
w_class = 3
var/active = 0
-/obj/item/weapon/shield/riot/tele/IsShield()
- return (active)
+/obj/item/weapon/shield/riot/tele/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance)
+ if(active)
+ return ..()
+ return 0
/obj/item/weapon/shield/riot/tele/attack_self(mob/living/user)
active = !active
diff --git a/code/game/objects/items/weapons/staff.dm b/code/game/objects/items/weapons/staff.dm
index 049339a1b01..793f384126e 100644
--- a/code/game/objects/items/weapons/staff.dm
+++ b/code/game/objects/items/weapons/staff.dm
@@ -8,7 +8,6 @@
throw_speed = 1
throw_range = 5
w_class = 2.0
- flags = NOSHIELD
armour_penetration = 100
attack_verb = list("bludgeoned", "whacked", "disciplined")
@@ -73,5 +72,4 @@
throwforce = 5.0
throw_speed = 1
throw_range = 5
- w_class = 2.0
- flags = NOSHIELD
\ No newline at end of file
+ w_class = 2.0
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index 0f2fd65475e..6ab787e519f 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -134,7 +134,7 @@
/obj/item/weapon/melee/baton/proc/baton_stun(mob/living/L, mob/user)
if(ishuman(L))
var/mob/living/carbon/human/H = L
- if(H.check_shields(0, "[user]'s [name]")) //No message; check_shields() handles that
+ if(H.check_shields(0, "[user]'s [name]", src, MELEE_ATTACK)) //No message; check_shields() handles that
playsound(L, 'sound/weapons/Genhit.ogg', 50, 1)
return
user.lastattacked = L
diff --git a/code/game/objects/items/weapons/swords_axes_etc.dm b/code/game/objects/items/weapons/swords_axes_etc.dm
index 6af34367d75..844a6f68d54 100644
--- a/code/game/objects/items/weapons/swords_axes_etc.dm
+++ b/code/game/objects/items/weapons/swords_axes_etc.dm
@@ -53,7 +53,7 @@
if(cooldown <= 0)
if(ishuman(target))
var/mob/living/carbon/human/H = target
- if(H.check_shields(0, "[user]'s [name]"))
+ if(H.check_shields(0, "[user]'s [name]", src, MELEE_ATTACK))
return 0
playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1)
target.Weaken(3)
diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm
index 1f808939f17..cf43a0b7bf4 100644
--- a/code/game/objects/items/weapons/twohanded.dm
+++ b/code/game/objects/items/weapons/twohanded.dm
@@ -120,14 +120,6 @@
/obj/item/weapon/twohanded/offhand/wield()
qdel(src)
-/obj/item/weapon/twohanded/offhand/IsShield()//if the actual twohanded weapon is a shield, we count as a shield too!
- var/mob/user = loc
- if(!istype(user)) return 0
- var/obj/item/I = user.get_active_hand()
- if(I == src) I = user.get_inactive_hand()
- if(!I) return 0
- return I.IsShield()
-
///////////Two hand required objects///////////////
//This is for objects that require two hands to even pick up
/obj/item/weapon/twohanded/required/
@@ -205,10 +197,10 @@
force_wielded = 34
wieldsound = 'sound/weapons/saberon.ogg'
unwieldsound = 'sound/weapons/saberoff.ogg'
- flags = NOSHIELD
armour_penetration = 35
origin_tech = "magnets=3;syndicate=4"
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+ block_chance = 75
sharp = 1
edge = 1
no_embed = 1 // Like with the single-handed esword, this shouldn't be embedding in people.
@@ -238,11 +230,10 @@
user.dir = i
sleep(1)
-/obj/item/weapon/twohanded/dualsaber/IsShield()
+/obj/item/weapon/twohanded/dualsaber/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance)
if(wielded)
- return 1
- else
- return 0
+ return ..()
+ return 0
/obj/item/weapon/twohanded/dualsaber/green/New()
blade_color = "green"
@@ -296,7 +287,6 @@
throw_speed = 3
armour_penetration = 10
no_spin_thrown = 1 // Thrown spears that spin look dumb. -Fox
- flags = NOSHIELD
attack_verb = list("attacked", "poked", "jabbed", "torn", "gored")
/obj/item/weapon/twohanded/spear/update_icon()
@@ -371,7 +361,6 @@
force_wielded = 40 //you'll gouge their eye out! Or a limb...maybe even their entire body!
wieldsound = 'sound/weapons/chainsawstart.ogg'
hitsound = null
- flags = NOSHIELD
armour_penetration = 35
origin_tech = "materials=6;syndicate=4"
attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered")
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index 8ff2f931159..908cc1e2d80 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -50,13 +50,11 @@
edge = 1
w_class = 3
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+ block_chance = 50
- IsShield()
- return 1
-
- suicide_act(mob/user)
- to_chat(viewers(user), "[user] is falling on the [src.name]! It looks like \he's trying to commit suicide.")
- return(BRUTELOSS)
+/obj/item/weapon/claymore/suicide_act(mob/user)
+ user.visible_message("[user] is falling on the [src.name]! It looks like \he's trying to commit suicide.")
+ return(BRUTELOSS)
/obj/item/weapon/claymore/ceremonial
name = "ceremonial claymore"
@@ -77,6 +75,7 @@
w_class = 3
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+ block_chance = 50
/obj/item/weapon/katana/cursed
slot_flags = null
@@ -85,9 +84,6 @@
user.visible_message("[user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.")
return(BRUTELOSS)
-/obj/item/weapon/katana/IsShield()
- return 1
-
/obj/item/weapon/harpoon
name = "harpoon"
sharp = 1
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index ea811f68be6..f99837df127 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -222,30 +222,27 @@
//Reactive armor
-//When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!)
/obj/item/clothing/suit/armor/reactive
- name = "Reactive Teleport Armor"
- desc = "Someone seperated our Research Director from his own head!"
- var/active = 0.0
+ name = "reactive armor"
+ desc = "Doesn't seem to do much for some reason."
+ var/active = 0
icon_state = "reactiveoff"
item_state = "reactiveoff"
blood_overlay_type = "armor"
- action_button_name = "Toggle Reactive Armor"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
+ action_button_name = "Toggle Reactive Armor"
+ unacidable = 1
+ hit_reaction_chance = 50
-/obj/item/clothing/suit/armor/reactive/IsShield()
- if(active)
- return 1
- return 0
-/obj/item/clothing/suit/armor/reactive/attack_self(mob/user as mob)
+/obj/item/clothing/suit/armor/reactive/attack_self(mob/user)
active = !(active)
if(active)
- to_chat(user, "The reactive armor is now active.")
+ to_chat(user, "[src] is now active.")
icon_state = "reactive"
item_state = "reactive"
else
- to_chat(user, "The reactive armor is now inactive.")
+ to_chat(user, "[src] is now inactive.")
icon_state = "reactiveoff"
item_state = "reactiveoff"
add_fingerprint(user)
@@ -255,11 +252,91 @@
active = 0
icon_state = "reactiveoff"
item_state = "reactiveoff"
-
- var/mob/living/carbon/human/user = usr
- user.update_inv_wear_suit()
..()
+//When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!)
+/obj/item/clothing/suit/armor/reactive/teleport
+ name = "reactive teleport armor"
+ desc = "Someone seperated our Research Director from his own head!"
+ var/tele_range = 6
+
+/obj/item/clothing/suit/armor/reactive/teleport/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance)
+ if(!active)
+ return 0
+ if(prob(hit_reaction_chance))
+ var/mob/living/carbon/human/H = owner
+ owner.visible_message("The reactive teleport system flings [H] clear of [attack_text], shutting itself off in the process!")
+ var/list/turfs = new/list()
+ for(var/turf/T in orange(tele_range, H))
+ if(istype(T, /turf/space))
+ continue
+ if(T.density)
+ continue
+ if(T.x>world.maxx-tele_range || T.xworld.maxy-tele_range || T.yThe [src] blocks the [attack_text], sending out jets of flame!")
+ for(var/mob/living/carbon/C in range(6, owner))
+ if(C != owner)
+ C.fire_stacks += 8
+ C.IgniteMob()
+ owner.fire_stacks = -20
+ return 1
+ return 0
+
+
+/obj/item/clothing/suit/armor/reactive/stealth
+ name = "reactive stealth armor"
+
+/obj/item/clothing/suit/armor/reactive/stealth/hit_reaction(mob/living/carbon/human/owner, attack_text)
+ if(!active)
+ return 0
+ if(prob(hit_reaction_chance))
+ var/mob/living/simple_animal/hostile/illusion/escape/E = new(owner.loc)
+ E.Copy_Parent(owner, 50)
+ E.GiveTarget(owner) //so it starts running right away
+ E.Goto(owner, E.move_to_delay, E.minimum_distance)
+ owner.alpha = 0
+ owner.visible_message("[owner] is hit by [attack_text] in the chest!") //We pretend to be hit, since blocking it would stop the message otherwise
+ spawn(40)
+ owner.alpha = initial(owner.alpha)
+ return 1
+
+/obj/item/clothing/suit/armor/reactive/tesla
+ name = "reactive tesla armor"
+
+/obj/item/clothing/suit/armor/reactive/tesla/hit_reaction(mob/living/carbon/human/owner, attack_text)
+ if(!active)
+ return 0
+ if(prob(hit_reaction_chance))
+ owner.visible_message("The [src] blocks the [attack_text], sending out arcs of lightning!")
+ for(var/mob/living/M in view(6, owner))
+ if(M == owner)
+ continue
+ owner.Beam(M,icon_state="lightning[rand(1, 12)]",icon='icons/effects/effects.dmi',time=5)
+ M.adjustFireLoss(25)
+ playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1)
+ return 1
//All of the armor below is mostly unused
diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm
index 5a7017b353a..68307875b1b 100644
--- a/code/modules/clothing/under/jobs/civilian.dm
+++ b/code/modules/clothing/under/jobs/civilian.dm
@@ -70,6 +70,9 @@
item_color = "clown"
flags_size = ONESIZEFITSALL
+/obj/item/clothing/under/rank/clown/hit_reaction()
+ playsound(loc, 'sound/items/bikehorn.ogg', 50, 1, -1)
+ return 0
/obj/item/clothing/under/rank/head_of_personnel
desc = "It's a jumpsuit worn by someone who works in the position of \"Head of Personnel\"."
diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm
index fd4864b7900..86b3728be3c 100644
--- a/code/modules/customitems/item_defines.dm
+++ b/code/modules/customitems/item_defines.dm
@@ -92,7 +92,7 @@
sharp = 0
edge = 0
-/obj/item/weapon/claymore/fluff/IsShield()
+/obj/item/weapon/claymore/fluff/hit_reaction()
return 0
/obj/item/weapon/crowbar/fluff/zelda_creedy_1 // Zomgponies: Griffin Rowley
diff --git a/code/modules/hydroponics/trays/tray_tools.dm b/code/modules/hydroponics/trays/tray_tools.dm
index 9cb59b4f296..3fae45bea2e 100644
--- a/code/modules/hydroponics/trays/tray_tools.dm
+++ b/code/modules/hydroponics/trays/tray_tools.dm
@@ -313,7 +313,7 @@
throw_range = 3
w_class = 4
var/extend = 1
- flags = NOSHIELD | CONDUCT
+ flags = CONDUCT
armour_penetration = 20
slot_flags = SLOT_BACK
origin_tech = "materials=2;combat=2"
@@ -339,7 +339,6 @@
throw_range = 3
w_class = 2.0
extend = 0
- flags = NOSHIELD
armour_penetration = 20
slot_flags = SLOT_BELT
origin_tech = "materials=3;combat=3"
diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm
index d128e22c0f6..0ca98c921d8 100644
--- a/code/modules/martial_arts/martial.dm
+++ b/code/modules/martial_arts/martial.dm
@@ -181,7 +181,7 @@
attack_verb = list("smashed", "slammed", "whacked", "thwacked")
icon = 'icons/obj/weapons.dmi'
icon_state = "bostaff0"
-
+ block_chance = 50
/obj/item/weapon/twohanded/bostaff/update_icon()
icon_state = "bostaff[wielded]"
@@ -239,8 +239,7 @@
return ..()
return ..()
-/obj/item/weapon/twohanded/bostaff/IsShield()
+/obj/item/weapon/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance)
if(wielded)
- return 1
- else
- return 0
\ No newline at end of file
+ return ..()
+ return 0
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
index a5e72059ab8..aff7b82bd03 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
@@ -85,7 +85,7 @@
leaping = 0
update_icons()
-/mob/living/carbon/alien/humanoid/hunter/throw_impact(A)
+/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/A)
if(!leaping)
return ..()
@@ -93,20 +93,26 @@
if(A)
if(istype(A, /mob/living))
var/mob/living/L = A
- L.visible_message("[src] pounces on [L]!", "[src] pounces on you!")
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- H.apply_effect(5, WEAKEN, H.run_armor_check(null, "melee"))
- else
- L.Weaken(5)
- sleep(2)//Runtime prevention (infinite bump() calls on hulks)
- step_towards(src,L)
+ var/blocked = 0
+ if(ishuman(A))
+ var/mob/living/carbon/human/H = A
+ if(H.check_shields(90, "the [name]", src, attack_type = THROWN_PROJECTILE_ATTACK))
+ blocked = 1
+ if(!blocked)
+ L.visible_message("[src] pounces on [L]!", "[src] pounces on you!")
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ H.apply_effect(5, WEAKEN, H.run_armor_check(null, "melee"))
+ else
+ L.Weaken(5)
+ sleep(2)//Runtime prevention (infinite bump() calls on hulks)
+ step_towards(src,L)
toggle_leap(0)
pounce_cooldown = !pounce_cooldown
spawn(pounce_cooldown_time) //3s by default
pounce_cooldown = !pounce_cooldown
- else
+ else if(A.density && !A.CanPass(src))
visible_message("[src] smashes into [A]!", "[src] smashes into [A]!")
weakened = 2
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 1bc79c16242..bbaa9e40da0 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -203,15 +203,14 @@
now_pushing = 0
return
- if(tmob.r_hand && istype(tmob.r_hand, /obj/item/weapon/shield/riot))
- if(prob(99))
- now_pushing = 0
- return
- if(tmob.l_hand && istype(tmob.l_hand, /obj/item/weapon/shield/riot))
- if(prob(99))
- now_pushing = 0
- return
+ //anti-riot equipment is also anti-push
+ if(tmob.r_hand && (prob(tmob.r_hand.block_chance * 2)) && !istype(tmob.r_hand, /obj/item/clothing))
+ now_pushing = 0
+ return
+ if(tmob.l_hand && (prob(tmob.l_hand.block_chance * 2)) && !istype(tmob.l_hand, /obj/item/clothing))
+ now_pushing = 0
+ return
if(!(tmob.status_flags & CANPUSH))
now_pushing = 0
@@ -414,16 +413,16 @@
M.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])")
src.attack_log += text("\[[time_stamp()]\] was attacked by [M.name] ([M.ckey])")
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
- if(check_shields(damage, "the [M.name]"))
+ if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration))
return 0
var/dam_zone = pick("head", "chest", "groin", "l_arm", "l_hand", "r_arm", "r_hand", "l_leg", "l_foot", "r_leg", "r_foot")
var/obj/item/organ/external/affecting = get_organ(ran_zone(dam_zone))
- var/armor = run_armor_check(affecting, "melee")
+ var/armor = run_armor_check(affecting, "melee", armour_penetration = M.armour_penetration)
var/obj/item/organ/external/affected = src.get_organ(dam_zone)
if(affected)
affected.add_autopsy_data(M.name, damage) // Add the mob's name to the autopsy data
- apply_damage(damage,M.melee_damage_type, affecting, armor, M.name)
+ apply_damage(damage, M.melee_damage_type, affecting, armor)
updatehealth()
/mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L as mob)
@@ -461,7 +460,7 @@
else
damage = rand(5, 25)
- if(check_shields(damage, "the [M.name]"))
+ if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK))
return 0
var/dam_zone = pick("head", "chest", "groin", "l_arm", "l_hand", "r_arm", "r_hand", "l_leg", "l_foot", "r_leg", "r_foot")
diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm
index 33cb567ba4a..f7839568a03 100644
--- a/code/modules/mob/living/carbon/human/human_attackhand.dm
+++ b/code/modules/mob/living/carbon/human/human_attackhand.dm
@@ -18,10 +18,9 @@
..()
- if((M != src) && check_shields(0, M.name))
+ if((M != src) && M.a_intent != "help" && check_shields(0, M.name, attack_type = UNARMED_ATTACK))
add_logs(src, M, "attempted to touch")
- M.do_attack_animation(src)
- visible_message("\red [M] attempted to touch [src]!")
+ visible_message("[M] attempted to touch [src]!")
return 0
if(istype(M.gloves , /obj/item/clothing/gloves/boxing/hologlove))
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 3a935e5e449..c8bc136103c 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -32,7 +32,7 @@ emp_act
return -1 // complete projectile permutation
//Shields
- if(check_shields(P.damage, "the [P.name]", P))
+ if(check_shields(P.damage, "the [P.name]", P, PROJECTILE_ATTACK, P.armour_penetration))
P.on_hit(src, 100, def_zone)
return 2
@@ -132,40 +132,24 @@ emp_act
//End Here
-/mob/living/carbon/human/proc/check_shields(var/damage = 0, var/attack_text = "the attack", var/obj/item/O)
- if(O)
- if(O.flags & NOSHIELD) //weapon ignores shields altogether
- return 0
- if(l_hand && istype(l_hand, /obj/item/weapon))//Current base is the prob(50-d/3)
- var/obj/item/weapon/I = l_hand
- if(I.IsShield() && (prob(50 - round(damage / 3))))
- visible_message("[src] blocks [attack_text] with [l_hand]!", \
- "[src] blocks [attack_text] with [l_hand]!")
+/mob/living/carbon/human/proc/check_shields(damage = 0, attack_text = "the attack", atom/movable/AM, attack_type = MELEE_ATTACK, armour_penetration = 0)
+ var/block_chance_modifier = round(damage / -3)
+
+ if(l_hand && !istype(l_hand, /obj/item/clothing))
+ var/final_block_chance = l_hand.block_chance - (Clamp((armour_penetration-l_hand.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
+ if(l_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
return 1
- if(r_hand && istype(r_hand, /obj/item/weapon))
- var/obj/item/weapon/I = r_hand
- if(I.IsShield() && (prob(50 - round(damage / 3))))
- visible_message("[src] blocks [attack_text] with [r_hand]!", \
- "[src] blocks [attack_text] with [r_hand]!")
+ if(r_hand && !istype(r_hand, /obj/item/clothing))
+ var/final_block_chance = r_hand.block_chance - (Clamp((armour_penetration-r_hand.armour_penetration)/2,0,100)) + block_chance_modifier //Need to reset the var so it doesn't carry over modifications between attempts
+ if(r_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
return 1
- if(wear_suit && istype(wear_suit, /obj/item/))
- var/obj/item/I = wear_suit
- if(I.IsShield() && (prob(50)))
- visible_message("The reactive teleport system flings [src] clear of [attack_text]!", \
- "The reactive teleport system flings [src] clear of [attack_text]!")
- var/list/turfs = new/list()
- for(var/turf/T in orange(6, src))
- if(istype(T,/turf/space)) continue
- if(T.density) continue
- if(T.x>world.maxx-6 || T.x<6) continue
- if(T.y>world.maxy-6 || T.y<6) continue
- turfs += T
- if(!turfs.len) turfs += pick(/turf in orange(6, src))
- var/turf/picked = pick(turfs)
- if(!isturf(picked)) return
- if(buckled)
- buckled.unbuckle_mob()
- src.loc = picked
+ if(wear_suit)
+ var/final_block_chance = wear_suit.block_chance - (Clamp((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
+ if(wear_suit.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
+ return 1
+ if(w_uniform)
+ var/final_block_chance = w_uniform.block_chance - (Clamp((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier
+ if(w_uniform.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
return 1
return 0
@@ -221,7 +205,7 @@ emp_act
if(user != src)
user.do_attack_animation(src)
- if(check_shields(I.force, "the [I.name]", I))
+ if(check_shields(I.force, "the [I.name]", I, MELEE_ATTACK, I.armour_penetration))
return 0
if(istype(I,/obj/item/weapon/card/emag))
@@ -315,59 +299,52 @@ emp_act
//this proc handles being hit by a thrown atom
/mob/living/carbon/human/hitby(atom/movable/AM as mob|obj,var/speed = 5)
- if(istype(AM,/obj/))
- var/obj/O = AM
+ if(istype(AM, /obj/item))
+ var/obj/item/I = AM
if(in_throw_mode && !get_active_hand() && speed <= 5) //empty active hand and we're in throw mode
if(canmove && !restrained())
- if(isturf(O.loc))
- put_in_active_hand(O)
- visible_message("[src] catches [O]!")
+ if(isturf(I.loc))
+ put_in_active_hand(I)
+ visible_message("[src] catches [I]!")
throw_mode_off()
return
var/zone = ran_zone("chest", 65)
var/dtype = BRUTE
- if(istype(O,/obj/item/weapon))
- var/obj/item/weapon/W = O
+ if(istype(I, /obj/item/weapon))
+ var/obj/item/weapon/W = I
dtype = W.damtype
- var/throw_damage = O.throwforce*(speed/5)
+ var/throw_damage = I.throwforce*(speed/5)
- /*
- if(!zone)
- visible_message("\blue \The [O] misses [src] narrowly!")
- return
- */
- O.throwing = 0 //it hit, so stop moving
+ I.throwing = 0 //it hit, so stop moving
- if ((O.thrower != src) && check_shields(throw_damage, "[O]"))
+ if((I.thrower != src) && check_shields(throw_damage, "\the [I.name]", I, THROWN_PROJECTILE_ATTACK))
return
var/obj/item/organ/external/affecting = get_organ(zone)
if(!affecting)
- var/missverb = (O.gender == PLURAL) ? "whizz" : "whizzes"
- visible_message("\The [O] [missverb] past [src]'s missing [parse_zone(zone)]!",
- "\The [O] [missverb] past your missing [parse_zone(zone)]!")
+ var/missverb = (I.gender == PLURAL) ? "whizz" : "whizzes"
+ visible_message("\The [I] [missverb] past [src]'s missing [parse_zone(zone)]!",
+ "\The [I] [missverb] past your missing [parse_zone(zone)]!")
return
var/hit_area = affecting.name
- src.visible_message("\red [src] has been hit in the [hit_area] by [O].")
- var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") //I guess "melee" is the best fit here
+ src.visible_message("\red [src] has been hit in the [hit_area] by [I].")
+ var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].", I.armour_penetration) //I guess "melee" is the best fit here
+ apply_damage(throw_damage, dtype, zone, armor, is_sharp(I), has_edge(I), I)
- apply_damage(throw_damage, dtype, zone, armor, is_sharp(O), has_edge(O), O)
-
- if(ismob(O.thrower))
- var/mob/M = O.thrower
+ if(ismob(I.thrower))
+ var/mob/M = I.thrower
if(M)
- src.attack_log += text("\[[time_stamp()]\] Has been hit with a [O], thrown by [key_name(M)]")
- M.attack_log += text("\[[time_stamp()]\] Hit [key_name(src)] with a thrown [O]")
+ src.attack_log += text("\[[time_stamp()]\] Has been hit with a [I], thrown by [key_name(M)]")
+ M.attack_log += text("\[[time_stamp()]\] Hit [key_name(src)] with a thrown [I]")
if(!istype(src,/mob/living/simple_animal/mouse))
- msg_admin_attack("[key_name_admin(src)] was hit by a [O], thrown by [key_name_admin(M)]")
+ msg_admin_attack("[key_name_admin(src)] was hit by a [I], thrown by [key_name_admin(M)]")
//thrown weapon embedded object code.
- if(dtype == BRUTE && istype(O,/obj/item))
- var/obj/item/I = O
+ if(dtype == BRUTE && istype(I))
if (!I.is_robot_module())
var/sharp = is_sharp(I)
var/damage = throw_damage
@@ -384,10 +361,10 @@ emp_act
affecting.embed(I)
// Begin BS12 momentum-transfer code.
- if(O.throw_source && speed >= 15)
- var/obj/item/weapon/W = O
+ if(I.throw_source && speed >= 15)
+ var/obj/item/weapon/W = I
var/momentum = speed/2
- var/dir = get_dir(O.throw_source, src)
+ var/dir = get_dir(I.throw_source, src)
visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!")
src.throw_at(get_edge_target_turf(src,dir),1,momentum)
@@ -399,9 +376,9 @@ emp_act
if(T)
src.loc = T
- visible_message("[src] is pinned to the wall by [O]!","You are pinned to the wall by [O]!")
+ visible_message("[src] is pinned to the wall by [I]!","You are pinned to the wall by [I]!")
src.anchored = 1
- src.pinned += O
+ src.pinned += I
/mob/living/carbon/human/proc/bloody_hands(var/mob/living/source, var/amount = 2)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index cc50408148e..2df5b32409b 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -62,49 +62,40 @@
//this proc handles being hit by a thrown atom
/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = 5)//Standardization and logging -Sieve
- if(istype(AM,/obj/))
- var/obj/O = AM
+ if(istype(AM, /obj/item))
+ var/obj/item/I = AM
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE
- if(istype(O,/obj/item/weapon))
- var/obj/item/weapon/W = O
+ if(istype(I, /obj/item/weapon))
+ var/obj/item/weapon/W = I
dtype = W.damtype
if (W.hitsound && W.throwforce > 0)
playsound(loc, W.hitsound, 30, 1, -1)
//run to-hit check here
- var/throw_damage = O.throwforce*(speed/5)
+ var/throw_damage = I.throwforce*(speed/5)
- //var/miss_chance = 15
- //if (O.throw_source)
- //var/distance = get_dist(O.throw_source, loc)
- //miss_chance = min(15*(distance-2), 0)
- /*
- if (prob(miss_chance))
- visible_message("\blue \The [O] misses [src] narrowly!")
- return
- */
- src.visible_message("\red [src] has been hit by [O].")
- var/armor = run_armor_check(zone, "melee")
+ src.visible_message("\red [src] has been hit by [I].")
+ var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].", I.armour_penetration)
- apply_damage(throw_damage, dtype, zone, armor, is_sharp(O), has_edge(O), O)
+ apply_damage(throw_damage, dtype, zone, armor, is_sharp(I), has_edge(I), I)
- O.throwing = 0 //it hit, so stop moving
+ I.throwing = 0 //it hit, so stop moving
- if(ismob(O.thrower))
- var/mob/M = O.thrower
+ if(ismob(I.thrower))
+ var/mob/M = I.thrower
if(M)
- src.attack_log += text("\[[time_stamp()]\] Has been hit with a [O], thrown by [key_name(M)]")
- M.attack_log += text("\[[time_stamp()]\] Hit [key_name(src)] with a thrown [O]")
+ attack_log += text("\[[time_stamp()]\] Has been hit with a [I], thrown by [key_name(M)]")
+ M.attack_log += text("\[[time_stamp()]\] Hit [key_name(src)] with a thrown [I]")
if(!istype(src,/mob/living/simple_animal/mouse))
- msg_admin_attack("[key_name_admin(src)] was hit by a [O], thrown by [key_name_admin(M)]")
+ msg_admin_attack("[key_name_admin(src)] was hit by a [I], thrown by [key_name_admin(M)]")
// Begin BS12 momentum-transfer code.
- if(O.throw_source && speed >= 15)
- var/obj/item/weapon/W = O
+ if(I.throw_source && speed >= 15)
+ var/obj/item/weapon/W = I
var/momentum = speed/2
- var/dir = get_dir(O.throw_source, src)
+ var/dir = get_dir(I.throw_source, src)
visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!")
src.throw_at(get_edge_target_turf(src,dir),1,momentum)
@@ -113,16 +104,16 @@
if(W.sharp) //Projectile is suitable for pinning.
//Handles embedding for non-humans and simple_animals.
- O.loc = src
- src.embedded += O
+ I.loc = src
+ embedded += I
var/turf/T = near_wall(dir,2)
if(T)
src.loc = T
- visible_message("[src] is pinned to the wall by [O]!","You are pinned to the wall by [O]!")
+ visible_message("[src] is pinned to the wall by [I]!","You are pinned to the wall by [I]!")
src.anchored = 1
- src.pinned += O
+ src.pinned += I
/mob/living/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == I_HARM)
diff --git a/code/modules/mob/living/simple_animal/hostile/illusion.dm b/code/modules/mob/living/simple_animal/hostile/illusion.dm
new file mode 100644
index 00000000000..c4a71cca618
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/illusion.dm
@@ -0,0 +1,75 @@
+/mob/living/simple_animal/hostile/illusion
+ name = "illusion"
+ desc = "It's a fake!"
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "static"
+ icon_living = "static"
+ icon_dead = "null"
+ melee_damage_lower = 5
+ melee_damage_upper = 5
+ a_intent = "harm"
+ attacktext = "gores"
+ maxHealth = 100
+ health = 100
+ speed = 0
+ faction = list("illusion")
+ var/life_span = INFINITY //how long until they despawn
+ var/mob/living/parent_mob
+ var/multiply_chance = 0 //if we multiply on hit
+
+
+/mob/living/simple_animal/hostile/illusion/Life()
+ ..()
+ if(world.time > life_span)
+ death()
+
+/mob/living/simple_animal/hostile/illusion/death(gibbed)
+ ..()
+ visible_message("\The [src] vanishes into thin air! It was a fake!")
+ ghostize()
+ qdel(src)
+
+/mob/living/simple_animal/hostile/illusion/proc/Copy_Parent(mob/living/original, life = 50, health = 100, damage = 0, replicate = 0 )
+ appearance = original.appearance
+ parent_mob = original
+ dir = original.dir
+ life_span = world.time+life
+ melee_damage_lower = damage
+ melee_damage_upper = damage
+ multiply_chance = replicate
+ faction -= "neutral"
+ transform = initial(transform)
+ pixel_y = initial(pixel_y)
+ pixel_x = initial(pixel_x)
+
+/mob/living/simple_animal/hostile/illusion/examine(mob/user)
+ if(parent_mob)
+ parent_mob.examine(user)
+ else
+ return ..()
+
+
+/mob/living/simple_animal/hostile/illusion/AttackingTarget()
+ ..()
+ if(istype(target, /mob/living) && prob(multiply_chance))
+ var/mob/living/L = target
+ if(L.stat == DEAD)
+ return
+ var/mob/living/simple_animal/hostile/illusion/M = new(loc)
+ M.faction = faction.Copy()
+ M.Copy_Parent(parent_mob, 80, health/2, melee_damage_upper, multiply_chance/2)
+ M.GiveTarget(L)
+
+///////Actual Types/////////
+
+/mob/living/simple_animal/hostile/illusion/escape
+ retreat_distance = 10
+ minimum_distance = 10
+ melee_damage_lower = 0
+ melee_damage_upper = 0
+ speed = -1
+ environment_smash = 0
+
+
+/mob/living/simple_animal/hostile/illusion/escape/AttackingTarget()
+ return
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index 32bdf5fc772..fe04470c60c 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -39,6 +39,7 @@
icon_living = "syndicatemelee"
attacktext = "slashes"
attack_sound = 'sound/weapons/bladeslice.ogg'
+ armour_penetration = 28
status_flags = 0
loot = list(/obj/effect/landmark/mobcorpse/syndicatesoldier, /obj/item/weapon/melee/energy/sword/saber/red, /obj/item/weapon/shield/energy)
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 93e72a96707..f1818153974 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -49,6 +49,7 @@
//LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly
var/melee_damage_lower = 0
var/melee_damage_upper = 0
+ var/armour_penetration = 0 //How much armour they ignore, as a flat reduction from the targets armour value
var/melee_damage_type = BRUTE //Damage type of a simple mob's melee attack, should it do damage.
var/list/damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) // 1 for full damage , 0 for none , -1 for 1:1 heal from that source
var/attacktext = "attacks"
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index 695d701dba3..725d97ce21b 100644
Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 3f06e7152d2..9817e7c4db0 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -1628,6 +1628,7 @@
#include "code\modules\mob\living\simple_animal\hostile\headcrab.dm"
#include "code\modules\mob\living\simple_animal\hostile\hivebot.dm"
#include "code\modules\mob\living\simple_animal\hostile\hostile.dm"
+#include "code\modules\mob\living\simple_animal\hostile\illusion.dm"
#include "code\modules\mob\living\simple_animal\hostile\jungle_animals.dm"
#include "code\modules\mob\living\simple_animal\hostile\killertomato.dm"
#include "code\modules\mob\living\simple_animal\hostile\mimic.dm"