From 14cfc90ff9e507cb70eaeec9c279388987871c68 Mon Sep 17 00:00:00 2001 From: Fox-McCloud Date: Thu, 7 Jul 2016 21:17:03 -0400 Subject: [PATCH] TG Hit Reaction Port+Armor Fixes --- code/__DEFINES/combat.dm | 7 ++ code/__DEFINES/flags.dm | 7 +- .../gamemodes/changeling/powers/mutations.dm | 7 +- .../miniantags/abduction/abduction_gear.dm | 4 +- .../machinery/computer/HolodeckControl.dm | 10 +- code/game/objects/items.dm | 12 +- code/game/objects/items/toys.dm | 3 +- .../objects/items/weapons/alien_specific.dm | 1 - .../objects/items/weapons/flamethrower.dm | 14 ++- .../items/weapons/grenades/chem_grenade.dm | 5 + .../objects/items/weapons/holy_weapons.dm | 21 ++-- .../objects/items/weapons/melee/energy.dm | 11 +- code/game/objects/items/weapons/shields.dm | 24 ++-- code/game/objects/items/weapons/staff.dm | 4 +- code/game/objects/items/weapons/stunbaton.dm | 2 +- .../objects/items/weapons/swords_axes_etc.dm | 2 +- code/game/objects/items/weapons/twohanded.dm | 19 +-- code/game/objects/items/weapons/weaponry.dm | 14 +-- code/modules/clothing/suits/armor.dm | 107 ++++++++++++++--- code/modules/clothing/under/jobs/civilian.dm | 3 + code/modules/customitems/item_defines.dm | 2 +- code/modules/hydroponics/trays/tray_tools.dm | 3 +- code/modules/martial_arts/martial.dm | 9 +- .../carbon/alien/humanoid/caste/hunter.dm | 26 ++-- code/modules/mob/living/carbon/human/human.dm | 23 ++-- .../living/carbon/human/human_attackhand.dm | 5 +- .../mob/living/carbon/human/human_defense.dm | 113 +++++++----------- code/modules/mob/living/living_defense.dm | 51 ++++---- .../living/simple_animal/hostile/illusion.dm | 75 ++++++++++++ .../living/simple_animal/hostile/syndicate.dm | 1 + .../mob/living/simple_animal/simple_animal.dm | 1 + icons/effects/effects.dmi | Bin 322480 -> 332388 bytes paradise.dme | 1 + 33 files changed, 356 insertions(+), 231 deletions(-) create mode 100644 code/modules/mob/living/simple_animal/hostile/illusion.dm 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 695d701dba35bd337c733c0e37fd10d5c365122f..725d97ce21bc24dca242f19132fdcc63aadebf09 100644 GIT binary patch delta 24084 zcmaI71y~i`_cly}AR!Xhb>$gd<%_N;fDS2RLxv z!RPt?<9)yDyDrD;%$Ys2*Q|A~`(A7BL+uRFMiFs5J<$J7OV8t_mAi$T-CGYk7iT0S zpR7JT6_<4Zf)@r|(z6|IxB)LCFISWj^03AibKa5I+OZRs$iFZ8tpWt#y9qXYdz9Y# zwTIw0&EX3?n{Zy4fY*TE)$O_8HT)01aEO56fJd&l<7Z3v)her9agJ!q-XQPc*8r&! zN72oh<{iK?*I=0Gk-IgpRc41jb(s5s?gMkkhX|SiY&zRs1Bo5(xdxgYgH}~{jrjd_ zu7w<>mtAjLga_ExZrmD*_HH%W(kE}AW()INcm=Y*?izkD6QI+xn}wljq69CAb1@+4 z7iNk6=>n{A=+e(>^~P2sA3ZFb4#rEw(TEQw9(V;X^ABI#JP-LjUwE3d$W>J&;zl4J zmHL^Io*ehd^96%vWS-4mkwp_zEF`rTVRg-cY3_&0QF;`VeeHv_r1=OM@z*IW6@rQb zZzI#+u1fQ+_H0`B{0!d1GuO=>uM<$-sb%1hC&zH5M4n6@dUN#5&1>lQi%)X`OkFF! zf+Ve@0Gc-%3R#73@1F&PRu-i!dpvdO?}$|LcW;%pWGwB114&<*#RpZL;iv|nJZSYx z3Sv<7s?aeWlKN7+i&D$|1kB903GmNF+@ah|-Sd91&oJVw99%MtAQwxI( z1E{!TXC%KOch>J3A9{>A!LUqrp0>qT{;bA%VIi2b82qZ;V*?T#ejfg@y;Gk*y$@zV zdQP*_`Ha^t)czu)DoMJ~&K(;Moq^?hJHOI%QF_S1%MK3t#zo&|dE3Hfc|-8fD{R*J ze$&c)uul1_RJ6HGwAtivWoz!m#)sh(8_Sn(7759{kQ}4jm#=OMW^jgP9#U%dYaq{) zQE^M?+xrr+^UPgD`s8f5U!U9x2i#p`z)=at6^7?!ZB;_HP$RZbk--B6JW!jqP|+~H z0CRq)u;z+)2!yZr0=vF-qP4>mV==iCOYurEGo2<0xq8B&#uK#Ys&l%)Rcz)NHh-m- z0=h0^t>?ylI*%U7t_-pgH(_9#%-1W}m3zG}vP-hgR&hCB`BWGRSicebdC0PSh8nrMf99>D8ajGZN9iR} zt1@*pV@c>(_Mvb5HjsF#KpJc7?BWQsH^?&BojB~EzP_+c^9-*u?ZY!)&7KOp-+(8* zRbvtBHGbe1Iw5V5tjKQ(0$sYq7nB^pTlI>kmEYll2`l1C`QI`x>nonJVC-PTvdS}K zBg=9zB+$4#n9;37QjvkdVdP}A=^IMYCnV#Ee3A4-vo{xOI1#*laQe^@tt~u<=Zpa% z{(akphL z6VjcM5x2|r;)h8`)z)cA>CH$n=Y1uXC1_F(T%pd=C}YLVcx4n2aBy&he*%P=TU21z zb#p6gq9qZ_8!%=*4wI*gRn>f2W1l=Tv(0(y$4pG9AxRfz>nnPyFRxbooxKGkl-M>= znRYF;iFYi8PVgM_Gu)DlAzNBLlBQSl;#5j1Pa#silwg2Qu^QHEweX=KY)dHpHt6<| z8c%NL^jvzb6H_ltasJg~0$qUko!ZW$V4*xOugB9tEf_nqf|7mHWq7mw;qi=cSi3l6 zNKt?D{5L{VNRRs(_xrPrn-|9Y`(*1{DTK1L$R6lyT&LYG&d#Y(Q5Fkl3`vFr4}+`n zW(5?j2$X`+%NPO!*G@yKpS5qcd=8O;8O4rx$(he%L!6$4eN9Z?WXu2{YE=*)Ps&{u za>`{QDMbZC5%$?HsEVk+POlvtA=Smx+r^EalT?b459Yq07WJaAMEcRS?7OGBy!ox1 zNzW0HUR9N)ZzR((rqtmfH0AawT|gm&MAUtRx>}97NK4nk$Ae7MuJesLG6Mq*`k!)Q zUO0oHgMpe+?~FG7g5nTR=ax=PPmCS8XRj6a`inJ}lAxrzom~F2>=If6(^$x((`#ED z+>6xIxN52eHGVKoa#-c>{>^A1A+Ub@KYXK?@{l@~y7$0A-m1~^`%uhrG zP#M{&Nw&F)lAaVuXjBY##Z~t52$BpqioXd2Q|O_NDY6+- z4d&pzx79h|Ffwv!xsH#1Mg9OwNy%ifEj{RP6{{==S7!wdV8Jfo?;@-*^GIAG8Fuv` zPqCIYM6WT%oQ=7ghCa#Abm5G}{vehcN%g75OadfISGx>@??EF0IHcjRmYlhWz=Bg| zwc#nU7!?rew4Q`l5fC_zJE)x^GDY`xQUSpn7&xg=Rw65@T|R|77!VkbSK&mS3w1wB zn!NQ_h=Jtoib%;8FV&ZkjyAEg5~sW~Vk%>`)zENnfP=|W+CZUnUR%`~Ub8@Ai!oE8 zG5mqamXjka3R}MT3L;lp*D9j<;m-EPm!OlK1AwaIUc3w7t03csn!RRKk>PtKN2k!{ z9AwQkRH$iWl->1HU}R)u@(`MsSUoTD9Em`Ug)&&907|qoNz0r^nAaGKQ&co`I5q-j z8uF&ND95h(pd2tnwyVY+YJ&XZ!*JrEE=5E@%bLw&?67a4*YU^EepqNj52j-xe6n0@ zMS$h9Y7C=i%vvZ!dor)YJEPeVOC|*DoP|2t57>@Eu~o}h&5R0ln9)xABti{QJwB4> z75+30XwczN5L~mOj7b>C=G2^?AVpr2WP9+&Jtx$nOmXPwp>@G^p7Y!6W&Dg$4I>K| zZ>I8z_R9}fT-sB5dG^Cv+LMq`YokIA6F8v8Oi%onAw4)b5-S3kRM3@ zz1RsXQSTz0j~r>fFSK0gV}j#yQ)|M&*e2!2$xMI@{wxd-!WfTpZUPbJ@RVs9f=m|WACKnt!SNa zrs|#&1Sb;=>kyAldAy!Pdwc_21!Jph)61@k(SG7UV}V+KZRCne?Q(E&7bDnkT3peG zuHxlO-Wco1V=^Udysmk&x8J=j^QH0^{W594Aga_mk8BRe;C^h;bb~N%WFf>6jQ0>1 z7v`0(LTAFyAx^;sW6s;~?uAGpn7`QCIhXsPv3+mAk2iMK*ZyLOA3^}LqsAE}#1Q9p z30k*WXUVA`Efy-%yN=<7wzO9HPa+GJRBsCiLiw}1HZ!QP!(J+}LDmUiKg_LhA0Ekz z;6nO`G*0U6Kv+CluuNSiu(cbhq8&XcriYdHWo5~~&48G*vhEjKz95`(6&k4%(pL;_ z*`j_`jm(5rAoPM_ zYXJ%M_E+#mamJfg>#>1l$`7>g$P?u&)RoNNEkjUmK*0A9uZn{++K17K{dKs!Pkw%^vD*U+ITX-EWeYwk}LFp z&{e+Jcc|X3yowg!M3n@u$26Br#?Y+EUpr!&u)p#Yi_I3W`%Ka5;NXVP50$2!$o=L; z(YlrOUCulteVZ>vm@4LyX${_3VqGhqA+4v)#q@E^NX+_bvgC7XMvPa+>!BizDc{`u zdPz;aJiBCO>=)Acehu(B_jvv<9<;u8dASBiJ!YL8s~$j}^L0af(`R0Q>Hcz5p5}~? z)K|9H5Y?}98U1tC8Id+Q=>~UEkH;rsol1Alu7n*foogvjP{@AsSxt}@Pi`F_6XkWq z$?=8Fdti68i3%!phaW9CMca(<`8g>R2bF`KjV;nrC#`{KF$WWANy&(WC9nnR91E4$ zO&IF{g9_!uPx=bdhnr$YOtkPl-y^-UV+r5OAFaC@f;}LJmS*jfwJOfCeA573m!k&m zZ<{<2f-fb&`w|}7iu|OCxq@^TNg}B#JfQk%nkZ+{S)%zz9)n`Qgd$=&b883oh5s8z zW~x?36XEg4)yao&ArHAi(+s%u%r4u&6a(;Ko=kZtU({)GOK3JK?+x$K>NpcIU4~*) z^`o&TKpEqYBpu=lU$LxgWhrk#hbfX$5rI<1#7dQtuj{LhvS!Pn*UyxE_@o1+)#nPa z1Qa40y*X_RNNhw%Y)UvrQwdcbIcjKKD3@(Bd$m#NL?JDzrH{A7N$6-<55{BdC>H}e zzyG|CQr!6krN&Kpfa2j++hN6Q@`yBCv9O>PsZ6DKM;FacgXKa`;8wD#p!Tbpofg`w z*sH^MhoB{L4BO<^alizuJ?)dBFpixNT)CZa2Ya8U=6(U0p7yuFT_d?b`8G1ndhLiT_0 zx@weMr0u?~4vJM&bza~OU7q?mvOj5E5rnP1*$d`K#(P>c(V~?x=~^(w!1@Qe-}gH6 zw?eT`RSl=6m!viB@e04tYeiObZq{}T=+79;1+&N!_Y4l-iG<(a*j%2?or_}J)k|SK;4=e2 zfQ=6!10xnBXA_>R)wizY>tSt+fvj!uSCt%Dne6H=L*26 zNAebP)MjEgyD5xwQ&3=`FAyV*IWbjWDbg^cGi!qoStmb@!|$8%xGu8X=N&r=hvsQ$ z3P&r~rzj3>;Ihm?cF#65x@u67ll=meMFMq7U|#wx+c1BRGFD2EOp;#PB)a(oD5DHw z0wzhkoyllo#wAZN&Z88&f}Z$`&ugU!AagRa-iAwcK!^BP9)M*K$tD>M4JL*y9~m4k z)yF%f^5THi?z}Or;hlHN{ZUD!fXgK$joN7Y$X-klJ#pPB8o%I(Z3snWh`qO7#j66_ z^@JDc&$iOQgT}tOSec~cAEJrP7N5uSDMX(_={zm$5tOVLZ(E`q^%KSwv0jgfzpL!VN;_60bC~{%8^_Ou*zC~!hNd*?Zy5MB7hZvR@`?`jb%4G7i6)L6 zX%~CCxfhR=6_3=WWb&M}MygAo4v3i7>>mqR&)$$MKSrT5s~+b|rC;N+B14$zJG%b< zW%7V>V@Qv*ob}tI->y8mzm`f_hZ`KP#i)!M9KA%njQ8umM^N>olCb0#_;jcl;Zkve zy-7Yz0XB_(oBKcu?y! zr;vgpTRN#2f*;J-aq|K~0&T=8l;G8vB!yRWBZc!f!lBfsK08{(jY4<}^zzVE*vnwD zyna`qz@s{+s2&m^E@HHQ;M=Pq%(sq{seP$~tar~IVJ=t?lRDUhpTRNm+AMDO8+s_r|o3H({cumF-h|oI`|N^FXS`X^M^5So3j?rq)B+ z2XUsEN3yl-}wG>A^=(Vww=>s5x4lfdZoz7I@L`U-??hm4pj<433p0xbDR(BVO+3`mMaw0y_XdxlHP-ZQWSn2{Zk6>xDA~E(R@@U|u#9f31nKF>aIB zSs&8nA1RdBrX||aV1W(`3oCzETT#Kw3y|o{NFtB`HT2I#DsPva-CPBonSq*h0!q?6 z)@*CHLHft4Mf{m_&9MM{^xSU zetbn(I-XIwq433LsP+u+Y0%5WGK+-pUrZswSOAiOhBg+2RceSaU7jcYZy6JanlBIE zTPdc5=J#@8;k?&2h_)gPr351Iz7t#P&1DXU4jECf!by~(F-5vvx7FN;2B&(GY_K0Lq>z`t;2_@b=MC04??+6@6EC))>C+UMBl4FkngiR^U{KC=2 zxyHoL2awULR2qoRq(F6s@G&tCp{qE*6>AaYU6I|7eFmTBot7R$LE$H&7X=Z$AC-z( z%BxFix^e+z-jU}+tK4!&@dZcipo7KQO+aU-t$+*AdIl6K-3<)c+F!D$<3gN~P}W?_ zAe;UMljSU*u9}gAzpKvS`8f^t(}cJYpyzihApZzXQx{1Bb(4(=FnblA8IpdNkhT7CzPyj zw>6vC8ryNRpS#%1xK)lU?BFrkFuX9toyi_GN+c z`pIE8`cz2mXrmqzWu;Nur!P%05dY(d1{rq>czv44(3;lnTZnM;$cyw905~HCI#w~R zwLAM<^}!yrt7*%sR$tvOVII+3G_3x* zA@y3{7+&8cHY%qVES>_=>(qy)P`;Z)PH$#6K?^SCo1ULp_J5}+l)a(S zQqnj-QG!1wK%+31CL~uzw9ACeBq}tXU7QqON9L6)b8Bj0ak<4)y!7}j`cr3iS zObdeMLAM#+Xs2|ocS5j-_KTOtcNH0HCs`gYbgQAI=1*;&Pv+v^xhAqyp89xcG^}zbXvSr7r*&C1yj>y^m z`2 zSEGQIRk4tPe5X0iYc2Z45*0V0JAKW_$Y^di_rFr8# zDJO#LLY~p1HsXR?!FXpfd>H)vZ;!)B8$%>07$YAlygaBu5i!M4c!@<LX?i8qDJgT)o%YB13oJzvS8?$V|HM$+4 zd57*8Jqf(Dz8ovN2(Y@c%hZn=yh+gd#NuBkq&~!$vw1ilxon|U$c*OCAjF)^q*1tz zpGGh~8C*NbMKD5a!sl^OZoh?H>(tv|H(rNNi&kln#&#kKlg2K37P*h%M~q9{eXLnZ zH#A6abMh_X<5grI*SmM0ejmTBPWJybE-a_cGdBi!gs2$2u@fz%l}M@u*P_k2e;hbN z+Ksp5h2%uC7?Cj>ZACJdXQf~=zC3^o{Ui%tZ{GCw0R69V4-t>-Y=~kmfo}~m^Dtj) zKJQXv`4`I2P#vRf7l@*ZF^s1uw6|=t7{=MjrRmccz$rgK*-bNRC&@)KFlB?l4{Rw| zaRnS(Rft9s(A1By!(PPF)46vcbXdvI;K?~Boava8Ed9lkFwLrOWaM>?&QcKU$h*Km z^BvPSV#$i`)g_5p-aHp)cKH+j)EZ@KTcy9Y3zgMDsM&k{`F40rko_Zm)q!<_P(pmQ z7{v#ex6Umg96<)kLjTZc^C#^#06~%A0CFsD6h>nRz54{42{bUghK7(OxSSrh6%X=C zZH5;ZdbWJB(;z$L$TMYF&P)*J{(eTrZm^`fJxikB{5N)(^wm867Ae`PUdBjluLs3l zpBL7HBM}mSm2*2r?<2Sem3(?@3KG}vr5MP5vK^}@R*4^OCpDHOPX`8ye^)6G(G&=` z_z{aIqMYf}xDo;^8{c@eU@Xvyr0l2mF9LDq_ zYN|CfFgLd`1IF3lg4)@`^*Bt%ir@hGoKx8BnmipZwa~jec|Kba9n^}n zrPd!N%0z2qd26;@Q=2yLZ{p5GNsk{Ff)%OVzMiyI?iQ^jX}SV;uiF@H8C%lhM`Sc%8^+j zr9{AqM_^fgkvzS|q;RiWSytE+^_I~bqajjfTBlid_lsT16AI)MU_eK==`qLX@3gCp<_=|f5?8p?+NMugRdWp6=xSc*UEdQY#Ah^e6s1=6&-$voG=0pJ;yF zgE+mC6cm#C+59Yht4RLSWR<~bPg>B~m4ZHF8@(8?{?(e^m?hn1!Cxrd+MNEQ&Hgmp zvWtyFme->{lhMF4MGo^?YO49AdNVy?_#igbpFPWpeBRE6v+vIxC_iLp#P-QSaZr0h-4%O1UV z7YGRf9uKRbP3`Z|q;L2yuHXU>I&foV*S4~bL~%pX_`*~&f=jSod(gXcM7Q1r?x9F+ zu?7?IqpN7nT9USJaOQ(Mp3hPof}#qGo1UL@c6jdAn-{^U+2!7LiwlM<4J?G=e^J#TIeiqm`HyF)pD_o2mecOxtHWbh?;O2H)c0--QZ*6#m@EK zv~=GU>B^JyQ))+KXozFKB}zWS=8R-*mJozM1iNA6XNtyM@6{ zSDH6!DjQH;X4>Px?a!%&idWz!&U(ml_uLf>FKXm|dU1qQU|n2SLI3idfF+cg8aE`J z7Ki7KqLKqT-@@`l*Z$zLF^&CWH9!rYJZ(RI+dS>>uHwI2rIZFPt`R%Aacu~k`RQ1E zN8&Jiw?8ROo)?Dr6x3@JPOEPe9G{?-<*a z7|=8uJkoU@j51U1+O13no%^`l9*}zb#Gs=#fPv@}kVG27fR_2Ieia8qzf*}IJAJ6G zVH6hE`M_;YE4lmB=wW)$lw1FuvIh>h?W;w*G|*0wryHhByJX>}Aw-B98(kIBC6MgN z$CI9hdcO&5Tv!!vH=8CqqdVpH${@=)WvR!8*6^nfQp_g6L`vrDF07|fX0j&A;ytD#pp zQ;m*dC*YkL{di<~`Q;>Ol%DQ!YQ4B>;B{nb9Gp*XCrGFbUAXC}2f0$0ehW%(?)M@t zZSvS^k?Fd5=LCp{kgRZ?<5`oiHb2rojSG&pxS-dp1o&!0SZo0txGxxcpshiY#qJXS z4onm639wH(CbH;XwH_m*3w5j+MRqM8TY$)Va3VI;D5`ob_ zfr|m7_&3(wkb8F)Dwg+XOLpRrM&+#@qbtdnq%SbEcWKHaQ~?ehQl|%ud!jAbAPA& zpVMpq9srI0`x++|mk?w!WYHS^759wL-v4JP@IS|bUg!`UGX0w#;8g#h7BpmBqWoVo zTQHd89Klg?L#8Z+zQ=dnfTE+mn_{Kech!7|IX=H6E=Z48N@F|rNMzVrk8l2ek%A7A z6;J?@FcEc@V-w18eQf{tjnOogecO*nVSJJx$xfL!^!fSylvi5CRbv|`Gcs8O56Zae z8fSFu#Bz@#QN6WA?fUt)ilU$3Hr(E#_WeRXI5$?f(KR*Rshf}4&%4ELBMkFpA? zw=m7`Zx8vBuV-PLueCvHBEa6C_BcKu2w5>Uj(^3%3|S%q_2KxP0I^*bOK|w zbk08e5x9;1Up@p0<*xi+T!6mywfu_(Uw~Wku%!EVGu@HgEgL_BUs71c>duFg>86@x~|k`+t0e`62$>OQh8UWVcJC zP2Im=swFf4{sU(nM;Nx{2AD!F7KX1s(~xNV!(IRxjc#8K1;}||RG%q?Y|j(yv_#vQ3GoI*MGIsPS^s$`ZesZpW2fU56sB_cNXBkrvY=j2xG@K zr2-6G6{;7Q>sl0#TV8!Iz{G08i#Nbz?qYTO*yb7ZOGMI{GEeLWvPiJN$1Cn?z0j>;2}ZK0iZC~6=={0Hx?U`_mc^1o>CpRGEP%k%%SOGh$k z(Ge6~dhm;1>~EhXW}<_q-j!DGMRoXvo;Tv%&8tmMe77{l1GWCuyO>64vOFs=DI2mT zNJ@2!n~pHPSD}hUu^*W)wt8aT_6DQl(0@&ij6wQs@6cW2hx{Q^!9#0sXy`(st5o8n z$>rLq@9r)>^^r)B=l*o$v%PdSU7*^q#cgvig-y45$^A{OsZ?F2nii$kgMtle40}W0 z_~!I)+ouNzKULsU&K=kLlds5eF>LrfD-KpvWPkqN_MiKq1$b>}$4ViHSJ%&OsP}jA z3y~NFhTiA?`hw#6QxV>p)|`$;lOW%@{=%)Q?Xc6&=mIg6#tE3jGYxZhbG{%k8|5Z9x5Da! z_j15x>jiLep>}b3ybcw7;)X=#0GDnu1HI97d2x{=bXGSwI5-l9-P4e9_vAl6CRl|_ z*F)*L#+{f2fXY6Tx~ni}nYu1S9m&0wt+;(#abI9;0{7Q1E+wY#t(0z}P4oADutu9K zZ#k?rt!FjzLq0j6)8vw;T1+0GA@I3;5~DWPEvHVL%4ssH8hAo9zpxO z+m$}9#GPBIfI#f8F9F152`06F?QZ+&sKef$KQCNi+6n$AX&eUAXTLv>31s`MMWS28 zX$NwVvhQu1$Om4)y0$VLU>8kYBcs`((S(3SWS7-YYA_T51}`%Z4y;oPo}Zude`#uZ z0*7UadOJ@w*iB^wo>!PWX1MDoL>#moKL7Vg!1B!!G~jX(s&A96oeU#af>Yn_$f3s} z@Bvt_N*ChxF!OoqPC>~sd`l2r;!dZ=cyUAM_0;dV&wuAd%yiv-Da!?DuMYXkl~UP- zSKg!J03`CLF-1xJ9_-4{f|r+OW!Hg3)}`!@6ib*{_?2jbN`vx6NrygxbSXtO64H?e z>!lI~0jG%!N;*_d7N0{@=?PbZah}r^RIR3_w_< zAikpF=P_fiz7?u*`i_wcfvEIeF)%PpwYIim00Pdxd?vxfxrH z7#MV~xl|t841ek_QOP{=5krqe=&?`pWg+^>U6hHWi8o*d^_B`#Kgu=r>n$JHF85P9jWr|E_q%}R zcNo{Cx;n_Uh$~Gd$|eMpH6wUhC(*W+z$ywe1a8m2t-IbM=C}ukQ_a9&2t+9`H9wy* zQz6;6h5xe~w$S7s?n{nOFTJDY-FS%eM#K{zoCymeZB`S-xB8zq}Tl*xxjKAbKs7PjhU-ey2wH5iy_| z$g@0KaPs-M$$7E0Bq|C!@OmoOZNaID+h&x4gwt5Lv!>_C-$x_%bh`%sS^_unSq;eXXzml%X|_a8Yng zkYgg?W`y+X=%Ned(Ty#iSr6K%_zmFrybJD@mm#&~jY}{Y=jYE{?2DX-ey458PqZIWzN{I6hg;E1qy2id? zDwzU+>vp#Ho#qi}I_i7LrFEb$>aj{6C^!l?xOx|($&z#!Nl+a67pMW>hS36RBKGQ6 zkiEOY+nRFTiz|9^g5Q82ybb~#5PmH3tikV5_2ddRL0uu02=qS%t&g7B-&6&ziE{7G zN{@ZSJUl#1^>vH|3rPOLfzt%&%sMzYX#Zjc&TCRpS^2BoavvD} z=%MBH*{=UO`SQw;$sJFopo{hC)`-Jt%cC!|@O%+cgu(JPNt#KZ@6!B{^DSb!sWZi4 z19`CD#L0;xnuKGmyfkNR-vl8dxa9LpRs4$H$jIow05b&st;whUopostJ#g|YvGNMFWBJND?wt>5d7;?e2^LIFeh`zP^B#wT<$w(Nv z@!}5uC!#O<$u`-QYJSKo73|EtdKz`!fv&`I%xQiCMuLYtPLmrlo%-bmecR`g`~*vg zR?4-nMq58P0>#o6C9u)T_!0y{EXT-+?cZIDIm_!|-WQ+Pk?UrNn+A)32`>M_Vt z+8%!_J$NNO4Jr=}I#p z1c>eLH#YGv?#5nR8fIirT+q5rlhdQ4Yczl)PoF-XhzZ?RjP))|7>NKz$Xzf%?2E&AfUhUab-_#djbLYXI1=GQuc$vzil1N1@#T-LZee*eSM;b$bFT0)dbuKiin8REAgI^+>?h3^hp=2&-)0cY8CDwl6?t7 zbmIq(Zyft%C<9X)^+V4swnwv(ez^^C7=og#f{Kdj3xef1qRHZ9V*o7H!lt{g4@(Lp z+*oi(*yB69$<4%x3+CRLgm{0BPn67~2-+ngpY3cz4=PJ9Qa`~60 zMY22yM@QL2_)weP9FPq1jon?6MLrn96LH@fUQLh#s8+W!T}nWWa{+D^c3NYd7G@hq zBE-*V17W??^`IDJ;RS<5jEkIu!@ks&uA!^!(q}F!%%Iaz(VAV;+j~WJrwY~Ix&-Ur zk{YlI5t4^{`(1Zz zU{OLeVavz)Pgp^2+RlTUz}KFjM_J^6Gqw} zU{Rhf>it|0099$m$eR+x7YijNrSIQTrfD72aC;F_6ZPcaK7g6no@})1pmm=>dV}N6 zW;APHGtFcaREyyl!KLpPe-_e3JXwp2iyi0c!*UVuZ8%tdZ-W3FRDwT=mT0FOusq3w z|0Tz0#QXQ}OG3^8Fs#1O2)3H`dSEw-ty)rX0R4%fq_?-A;IFr+_~I}cn=DrhRf$`^ zFJHchUCdhiYgRAU$C8la+d!au4UyqcZ6~6Kz?lfY%t*d(XVFHH@n7f8O4{(DNYcRK z=mx=>`W$(TyjH`}#o@(D-EVh)W78K6&3C5UTYsFY4qJ%=F}=IY;yHFSIG)B zaJ45)1*CPbv*O4CDc*6RF=oG}D<|o-NF?}{i51nYQBBK%nG$!$aqY0RXz)iN0!*k< z;6s4_e#*KFSZ9dc!PdW-bEmTF_soBBNawb|7!$u?#}_+7N@7yA{?+VypUNv>FYpYM zVm?sQB|hOnIg{~b5QePefTyRY%Kmg!Ap{b2bI=xdUq#$wXdM)w{=-Z6X?+`RzY9k& zWKi(oyL)?sb^sV7fQvHLgqgA$(V``A2i7}c)t%S&qhhDZ&aJzQbO~75+1Y%2d|Xz8 z#26SDdSC1xgJ0b11?Zg@!uN@aU($PwQ`~zlkp`AMGBPqr)%*TnJFp2(yMe{bOO~&Ex^nvNa+!g=JSX5n|K8wxmt_gN@9ghefPQ2*YE7P=)~N=i z8*JgeR_cG&Yjk{CuC@1J38*}c*n10?-hF#J76H=PwggdhUo+zFW)7?pYT8e*cRey* z_+8ZcU%43rx1L~oKvCUs@n&l@dkC!gmo&iwjG{|T#1L_s&l#|*n zI=d-GdwY95u(bo=>(njRdliwd3i&$vFr~+ZDm&9OK@lUw??Z9Bdw*bK|vp@4+ zlrsflWTQ!rQ)>LfW=w!=u!KD=q`v(yW9%0rxa`l%`Lrc!WbD7Jrt8Xs7t$4SzBk8RXh;=qx+ z*qi#*;x4=zN_2GP{~K6rO9OT77`7hw*>hh9luEqULaS)6#jh-Le7BzF0C&F5?Z>aE z0?yRIAk3>9g|P}C)c&={z4-Uf($g`CuHAbL@?P|unNR1naXT4catFH#x2w%GUe7(P z=N)GnBqeVoCz^F2ra?-!igVlrJi)4SlCobcZ^5JFTO8KP#?=ZNz27sJ27E{YRR6p`EEV?jVD@y4@Gs z)QS=7PZT5efoia(j|)62Gz`4jyl+5E=jyF0jXN?xV3U!P`)(x2>4CPLZjWs@Oub&u zavwDV`R6|2pQS5r-52~4$^Rh-7IFZ%-8abuMZOno5!2ps4}v|DW+T{5Uz~t{nm6xIGxERQusT+GP#;`oa~n}=*|t-&|oW(KGp4Tp+D8e#D6Vc;gat>60>{WWuN897zCMKsSk={1-OYaKQI@(k^*(qhC58OWyzcCB8JJnvu#~ykZP>QKF}hprjo4q**3>#r`@=2$_wIt*EGohL4ZfyiV`k z(TddB&P1US>|bNPf0yrQdv|$&tEs6ODNoP3c6yaqX91-Hhj({(!;X6KkHNyIDA z)z#Hpf`Vxu{!b6r9ZzNdhL4dIGPB9ZdhJn(9N8ixDcP&+5iRo}TXt4ORzfLz_S!N+ zRz@g032}@Z9M11Py`Rs|#~+S!p7T84@4c?;y6@*v&&xxU0}r(M`1l&avi1FgY6h1i zB_+o{=*qV{>g&^TU-Bb;rbp)K>ACdp>RH{i*|B%#6TpmME98`vI6-T$O5YrD9vC>? zfD;!N_j~B;@4o07m%At$Tk6SebV8-COXa4Lcx_5Eak-_p9D8$OQ+lZZA-XFY>!ONVoGCEN7+QTRrTjsnrXIn{_ zn3#%E50Ca{KEU2M9_i)v4s>WN|LA`)dW_7r5E0e|Dq_ZYPi~NdBDxZI@^f=9zsqd$ zAY+|0D69+;99nXmmk2x!KmzXOYxrKiEb4y4-;O94u z4U?%dTatjlKqE^_8Uq7^x`u|f*4E1l8)#|ia`23MV*>&WI5*nR-=bb2%W>i%M&=Q! z_Nm0g{KnVMeaX8~fUvj?#o$MVN&W;(yMkhIMbzV;nNz4tcYoKTT7Fv23psil$H#{o z_P|fPyuI7%eU@jJmcoOBQFV27IZaL6xw*NCy-P1a{+uYYRVze?jej*LlnoLT#3xJa z19piWUb1cuYHX^WsP_@V1}GO83QxPayBG7SMa+WtA{TtO1jNL|3@t6=ZdKk%qTEbT z&GlN?-cM=rJ43x*IKqa0S{z*KIip{_FkX8aKv0B*1i4PcHW+AaqMXD+f(2M$TgB~O zDc>yzfwN~XpP>tO5X-#e{{UQbB{sVUi|qWQFX-jr;VJbLhxn8Vz0-d9|pdME%jD3l$X=v&+koi;E5^DJeEk+X>sl&CTt1cqCs1 zj)c?eL@X>g3woRVc3lDy*YXGJX59`le=kWuz%YRatqGzb&?xc{mEfkpLq2I~dXRh6 zOift{d&kGmU%WbA`jFr>*k`eLou`6E4LD|I=7X^ZzI6etmz_jNXZomj#jnn`Q{4IX z$f?bk;sd7Tylm)`ERr|uE=D)4Ptl^>7s$+q#uz*25HG_~!?*XXSro~qOX}WP*!O+> zoZC)CMoOAfP;i2hk}^Zinc;J$LMTYkwmr#bS*7hr?dKFN@>C58># z8RK$sLTAO}^xA7?dV5a_>1VdUW{DsO0!kGzAn11BCrMdZG>}dLj&{c{566&LprlrMTl#!zwdnw;utW}oHH8dtB#si_8mAq`RUWA zH+OczqN6Dx#}~DRk|P9)`Ts-rc6T+*%-E;DeY?9hA#G}AW(RKH-QRC=Pyjb5p@U+B zjt=H}o(g&0yQgkrV?*$;?g6=oO7%fPDx$oc8f-)rml|2UX zaNEGZDVb-nZ;FZrS81fw4o&_Ziu`#fUq^gWH>a98b$1jMtXY-wzMei!^R<(^d-&k+ zH3g;eil*mjWmZ{*hHP!!3nF{>Yu4jF9k`?@aXc`+X7##8+0Wv1-Mx8WW5t4?v;N@Vvgiv% zeSLkC|HNC*B-RUR#d9W=SkyBBT`MXoYI!d2Y6u3OoHVDkR7!(vl_vB-DZ?Bq*i)d_I+})ppywGYW`deSK zzgR=FEajJ98feWDyqcHOtI*=I1R{~P%y28$g_)Qfu^Wg$e^x(}}wDBQNUp@f$3b$6W~s4*~oT zsaWe@eC28mY4QHX_pCe~1QHo7kFpp6u0XaymMltMO>v;q`HYevJ^T3h=Gd@1fFCr2>gvIYKXBSUTTZBbK@S)K>=@OQzUS3jw>tahv#5xzUuQt~- z{M_1G8HpUlLiJSEKp(?$AY-HqVXZ-7>qGkb0O}CwXV)=%Di_y^vV=w zwGyKdfbb<1MP-@>*J!AeT7HPgQheC<=@V7tDIU$4ra<2G-qgdSK&xu*h(E4xb&ZUY z)L;Dlg2`VhFI^#`&NZRdF%ORp?o)GJWCAdRn)D+z$hugNb|R(+>o`*SPD1g)+TgF7 z;)RkzT%!P1{yXUo7XHl&fokK7I7b&6WIrBQwg>P9rR1?UTJS%!;nqEor%u~%(?-&b z&AGaL+`CE#I$3fq9oKly#AC6KAQj~_G_WTnC6(3GbY@7~ryNSN;oT0ZM{ke6w=_F? zv$V7HD*vF-ZIE;WVN8noP0iNP4~NQw>(k8K%`26 zquB9bD3>@T+3Y@74zOC=z6@z?0|PBTzl-2DQQ)T+6iE%n6j3N@U&4b46c^@^k5Bv> zS9dP%uk2D#QK_n^pspDkC#9x-th>qVeO^#j_UVBP4F<&}?Ebmu+lvF3;mD z2bA*xKM_6&(;{UIc+mX5_-`~uS|dlyKzfo11oQgcyV4P~Trmmg;|vV;d`h-e0`y~l zK^1p$acP4-J2eCT@XvZaG-eDfEMg^*W?XVAmW3+3thQDQ+P7Z&TetNxq=@3;;)Eq7 zwcy(pFrLEbM($AZQxU1D%#W0~D=I5#81Os+n?xTMFoP2lQIKLoQn5U8PISBLwKIGY z60{)2r9SfaH-7f)*+i8y<2m=qjz>6-PX?u3keQ1?XyN7KBL*c?S{osRvM9WQk4nkP z`WIjP7jwxb&dJq_?UH|n_tg{{LDZ+t@$qtV6ULEHUH>8v{KW@vC!5~HN#?2q*OrtR zn%s(J*w12lzZpzKBIUiP{i?8#kWwovD(IM)I?UMh)eb2y`R%Ca=}`j``1Ix`^ZY3) zD!YC*Zf;t8d&J(<)Kr_0S0f`M;SMvPXH^SXAA+-O?Cgk(uYdY=z;iFkI@hr52j_VY z&e+&kIu4GLzz}JusXG#R)x3TV=ALge!2ZlnuyJ+mbvbap*nxKFrW?zI)DQYa83@}1 zng=s6+I{`~w_YGNPUtykRATPhk>lH zvayxd&{gLik-}hu+_`gh_~WAzKNH>{et!P3%x@nacERjJaHId;6}bK(P+kP!?>lFS zzOK#+LFJ@iV`IAzcp&%I$|S1!;l}6Na`=;1>wcj6h~$*~H?aXI_e(Y^h`Hoxl$Zqu z`NS>tyK-H^&VMOXuI;7rKf1`NVXSD{%;n=zYXUZ}i(0p?YdgiQ)B<`~eog=QczU@` zLg|a_vY;bBy=O8f_V@SyUYxbH^;qW3QY(!I4{9dQMXR?>E_*tmZCiqgqN1ZO`}oKb zt|vQsXS<>95rz)|Y@1(0m}CN~h~tUQfv?nXyu7?63Q)Q`H5@fH$?WXxzEhxi0r){?g{P9P59Hrwm>=lw zw&`E_`7^4lOsd))B(4hq*iG0$;LSMz$%lr92=+LB{rYwM$<=5G$z1bV50|M$Zw32X zk=EzYw(}j)6bSe+wEav8Zs>M=eAC3ld8f{OqAa93*Dc}?V_se!L5YD|O>Z>5p+g(H zes84o8dzNP(&mp6c!`3q5_fWP@)xA$9SC~WSlOy< zudPKLRt}EJL^_OyT@zP0k>g84Ml zTS)Tk++4^28gJoluBJxf?d=W5vh9eXXFcbZ(di_1j`uhsA|n1IKKw=<3YHzY&5F99 z^6)QpcI|!4TDKly5YCK>Dq|6HDSwQ`Uv*_(4ql03i?kHWM;aH1sKu@Y%lX z)D_9!CnU(d{HEwn+(g1BEKm~U!gU9$y7En^GibE6{j|@OD^y{sbN>WTBiv|P5aP9U zb&Y$QI?i=uCnvW(--ZojXW?2N$nJt9G(&+#T6=mZL9z}G4?jVO4?O(4M4?dc88K*I z)$Sf19+0U%gI7T*C7}v`e7{t*W8jD71Pn>pLo?N7N=8=p)(4bKRrcnXxhF5=erOT? zHJIa_I~6~a?){{*u(0@2Lx7mgAf>@KIo!T&3)qq@i{uKf7fBPhAJz3l9q#Xoj2HMZ z;#8)tQ-rIwc2B;@3diEjg7=q<`m>3YvroY<(KzeJtq-59vM~9Y`M*~fH;HgWEtCI> zKbd=HUYl|l&m+$c@6YDH!z}UrKB1+hML>j$lJ#ZhJUJq;GM6+2whaL0(6g}>V@MwD z{kC-bhBPpbj*b!}0^r&Tl48DbN0Wr{h!iy*;3$31(;Zq?W}49&xQ83xZ+}z(Z}^49 zEC8su>3>N^hGB1GrVEOyaJcH6=GfbxqCxJ7CpU|Y3-h1@BrmxS!it#id_ruj!xx?T zQV7bIFJIO@+;};;>i=gAZujfxMB+Hu;t;j{YUw+DtO48o=O1k?QmU${-Acd{N;qH8 z>qu+*!mKQ=YX3bCki7KPcNKho%z~A`4ISlFLdGY$QO7vz!}$tvCga z^CV6r%zg13>}@3EYbCsC{JpjoD`NaQxP4BF9UrmfY7ez55$SQ5^{&rABg(57wAZXk z3>KP8x9*O8`C@30tvu?qW>M!w1lpn3g9ms1o~;vBw+T_l7#$sb!EZ-+6@x5)=8C~e zTGX{v)%51M1!sNknVWVk3N<`~%I=B`wvT<m#VTBSw0voYc#yldPJzo1NcB9o0f%Tj2av-czuN60&zoUyN73B-K}DlRULN=VRx*%)9ayM8h< zRn{z*FJESraiD-?26&C0p1!p%oz&XZ^&gEr+4TTuJ_th@T3lLc?d{clM;+PT3i{?? zt*7-PU*DBo2Y}-e!^6X6KFj(@)JHp@4%!9RIvW=&36>Xb$QIGYLBk;=PZ%oj9OP-2 z+iUCV^jutVM){h&0s>)40IaN8U?4*k#0o%zww|5|FoIZq8V@oY)3<>tAE?w{MhXpv z0387-sFne9x3X9VgoK}D;Zsm}_TLwP1`v+GEDdxfpFqRwjHqZ#H5NHsuNC=w33o4W z5>$+;s_XoepP)TN(0smDI=1)s$NhIaWcZA8?(DQ&7sFswsO{UgtZHmFG?fW^U;zUJ zORK9-ii(8ecs&7YvR=F=tQp514r90J{~ZqSU=xF2T7gNV#ENK8~HzIxSteOoi*NnQGuZ#hnal+%7mP1wyfpz)KE z2sFepGFSs(fPuZZ7HW6&;ogQlNN^Wm{kn=)j_52rlm!IH#^J4H^gMetLC;trcY@F0uc<@?Te z&Uya(-@CiByU%n_b=6x{Z%VxXhj2E0e#Ffj8cQH?M3eQ;3jg#){gIc5@zTyly!5QsnSWnoY!kb@dcuN?CI zQa*`91r~S>`!#ZQ`R8QG-3`sLDfyRVTgMV>4z@F=+NEt08x`7jORrlq&icf|8SjNw zz+%S5aXK)YC8y*wP3+nO{V9Dh2IFC9B!6U~p!02EgvCs7A99JPjYH<6AAFAM$817uC4M8W9hnfn|2 z2Kr=`%b0WOeDY3SJFcJfqHLl=D)|l{fwy-K9bo>!N(nJwUT{XWj0ye2CmX&cnVKn= zjhZY<4Nwm%-h2`#4f3$t=D_XsyV17i9PeE{NNU|;`Y`T7uS9m{jM{Wm!_`J3vB|Ot z$+(4?Dv7ij30kisV(iG)fzaMgf_R044U|KP+~jU10gSv z5bI~Z?_TTx9OLnfq=Uk0UV%Nh5=|^;k~IP{kjqeB&wSaBeBulyXC2ekf1=8Ur)h@|sV9+wZq%zkF%C{S_7mjQ_ zr}vxX%sA-8#V#us$S!$b;!jR`|BB$3c0q{a;JTMZ6xxKqMION`_>X596l9NC{48D<$m#+~>>x*YZM z;JyLJW5DqW!{jGLYhw9qCANgQaLP)E;&+ejvXF33Sw-5l^6b&~w^R5nWG+id6oRsX z{$q0*MRRqMs1YF{+ZL962^LxRyJAu=~$CNf_s|Lxd%^nx>6GZpz=c`TMPvvQe{}YoMg68rh2k1k zC2*RuF7j1AdHaXJkNp6{cR>iFvw^DTlpCcn%+Y;w)Kb_A9aEHM2MS-nd0=8pv}J%C z(_T*}-8z_zSVeWNPm%B&J2R=wEQgMN)*1t?Qpri`E@H4@e8T&u`f7j3Ol-Ma`Ch!R zf7pB`-*BF#Il6Pj9y~1`+#fRlzJK13N2iNbO5$1}`o#f+F%H^BAFlZ<2u-y+2xSct zgoVkL^72h}oF2i2yhE)=vpX!EGdJtfn-$xke513Wr;klI(e`6;u57hj zYJLbTJT-HYr8J&A@E z6#Z_;Sx3*co~FEw25bj5B=QFcq6aE=zJbOH^787NWsnLn2ohvi$ADP2K@fA)uW#Mj z1^sO^w-%IZeC0L~*?gaQPbt;#(CFKI{-wG4T&T-^9h zA>0FIgW*DL{&9%C{Cbc+O1Wj5(_nK3t!R3j>Y{#mQYkE7KoaNOFHcEn&TuR_BB9M9 zc_PCEM04^p#Gxsb36jp(l2dV7R9p6d_wwh^J2SeIhX3!6_J6o)^&q-5Lz+tnHqyi*2Ve_`4LZ zpKmq)+4&qvn3x*emO9>xC``>ubD5kMOz_$=-l%JGjg`mha)eX{h=?;#4TcIggscjL0WY<8f;%=!dAysyvR{A8fa&tXJ&KB`!T2F7GuVgvmi0jtCyJEkSY=k9*$;1^QgCR4Ovzz_;B?{EpwG#AWLb**{6;6R6)MEfp~a zyP2O3_!m4-bsz=>pUZK?kQsad=E4!P{7}DWb?4+Vqf)bz8aSG^Auj%|T<=YT$tZ6} zIKU8Rd3)g)?><ozHI(Y(_$tGSAzYAlr~yTtw1nHwLV^8Xmfkgf79N zWd?TeDqt^ET|sXJiW4h%J3AI{-N~#$3)DQ#v}=)!lBEKi#@i`EjAgU1i4&2RFQpkj zV1}%ctTi#NP3-Eq8;z6qq$FAXz;8xZv%pFCJX7vN8}y=sr%zZ+{9@jLJfZfN?{_Vb zEMr&3CZAKYPtw#TS_vSNVnBr1t_2E#p1c(w-!)G-x55lL3>esXSIUlb6gkj*wyDss zs?aZ6@Zy6vyTX*KZv*6UDjOR!FOK}JbOil5M`~gx)FmQr#gzb)yn5A6a!nn_SmS=y z_GDANy?$HLPfF@7$TflQYSCp;U)}tqB+|b)n65hA5PSw;0F2T%@?aF33~{74l6ltS z245?|In%j~5)bw_7j*sFnDeJ@GAjX^40y5cd~~Y^oe>=zPjmFzU+@nPS2UhGqZB^_ zrrW<$`Y~d`Xwy3=C@h;zU?5PY6*6Qh*2(F(^d!_&?!MfRfktSEJrj$u209_fIP^N~ zReA;~roSr|@LspwnnY9o#LJxgNA}5JvJm><(^3gsNP!R&^->J)^7<9)+FAbU zF8mg&s!o|)=$$$bk`g-@%-OF=5Yr)~J?O~vL7Voa8Rw*Y0p*SAjE?QydA z!@cAqRwvW8;>6~hSTN8@=$ofi+OlN$D#ZgL@pS)K_hT?j0ZIC_OG9 zqw5luyI+&EH=|2X!gM9mYd2%f5RFmKc;v$zIsYa**<8<)rtEI`Xm=guRYfyNjH`1S zA_#N~w(2y}7&NLEdjPEl>&5!l?@o6`3F{o&M8E_cn+l&K=*PI9FkYe|9z`Lo&fqjb z^r5=}-5fmDo!mi%i(Pr`# zj89~|hJtoxV7{j9fp<`oBfQngm_I+hg@^^nbuD|6Md`(2mNX66+^cazuKNM-)OytC zi7=nsD!P4M&(ov!91G6=x^SfQEz+8?V6|5TM^}hvcY{16SbGgoA&_#uPwSCnTNgdT z_3aciVx2eLV%7B9E(9kYj9mrR=uIQx;#)o>N8c+phR+ZX=n+)pWwhKcOZf5vI{Fb& z8~ynXy~O*eBf{-7-Ephq=v)BiAIoMqnC4gZ@a4o-b@kHi!os^3{QUOLnGBIEPiOZG z*)w1nl>=WYHfP3IAEuiOCuvIu+L!cEY9X^3EvFDW&t0SfD*_j10ymyX0X+9b^9nkc z?pt;ek8Y-EtTj(q#5WQY#OGL6Z-31VTDSGTZ=1V8En0$cY?#&e>#hT)u1E!#RIcn4 zY|5<7^Ixm=!RJQ;%Oy%t@!#V%Pq8L+ghdGz-c+0@RgPG*;n&aIpE3pMcTK-3ZycCP z>u9JMP7&HJ50Npyq8QjP9_Z1GCM)0ES9J|)e7qCZ5Lci7(>!T&+}p2czkpZ*<56^d z&Dq~;Wl*= zHgfqxcrLndjL`{SqccSGh*cLMf1glvxnezjzg)SlT-!hCC?SUWHLt@=E}uWVLnvJS zYqR+lI<+e6dUKr;6a+G>5mq+mm*}+``6sBEU|@`nvauBqt6wu(IiZDG~7<9}9DC zrE<$AeM^yDx89RM%7`ziyD>#OAdTMI9V{x{oHfbtuf`?%;OZuy>Uy+7^Gq4O6!p;k zQ~dhw*FJ!JTmIIfFV3Fetzz74C$tz!Ac7ZBXI8A=rBdor*Z=6Y|Ag%_)S`M&JkT(;m^Fy8H;AVfs+qnBvm=VG%H5u&&KEnrySwT?m%)Gof4h6=Nclb#6ZExRjoW{iW4A^Ol1Q2(SqU1((uL8u2 zQ)Z`)Oaq$|g(n)~{N4?CS97AL|v&B`Xz1f?-bQs>yvsJn)(B>UYYJzv zZyi1|P}$^T%H4BImvj|~;`LN6wGw{yy3ed3sq1>4-Jz4smik@-=bdggTkI~lzDqMb zWQ%uh1;Ym$;|))IQJduQ-H)crZ8r7Q2gSLVrIWwrqhSk|Iy1n-Gwi6Dw&0nw z3?nAg7^MPs1Ippl=D4G}du;Fd*l?R$|DCM{r{uWWfxL&yiZvEBlxYfW6qz*`-<+wnBo1N^|8CFUOG=?mi*+Z9Y4(tzOY?Bfy!>yu+&9 zj2=r_8zeHz5x+*SykN)04%cC5TlwMoBzNrb6xJNCYIp#y*G2fKzu zG37f|{f!oGrhW#M-ggsQDy91N{O3%qGtCk~xq6)Adg4PL0aw!?yapi|+wqT*6aCae zr@q;sXKi$Ghui*q{pPNp1$@k;nXukzWh==QJm-rzH{O9SuN2d;HuhN6^v^CQ+UD(U zh7H#J0-WGD+VlsNBA~(-WReG*A*C9N#yAqY0ntzbKC;O z`u!@CdfI2Tyaiu9mQOR&L=bX1Rj5A|l@=6S?0~h?EQXLhRY)P) zDTSB!bRmxC$abE?8q&mmCOEs=r;SxV;#jS5n(03ogKB3JZsBYHWLi~&Lk_M zz9c{zBRLJrv3RsbFHs$-)m*y8bZd*k5uhg-El;9>FSl!Sxf1{>B@Z7}BJ?DQf|EZU zqco%m;rv=}^{3>E!}6fh6jPGLvq9=?Bzp#0=dn9Cqd|Yp_A{s9W|@$n@5f89N@((P zywC$d*>NO$#ah1KH7=J%seXA68wrKWBmm!lSuw>)MuhW6{j>xfDr%`jsL=CX*+O=z zj7uX%n?mHpv{M zqE#M*jqqT0a44k7sBAZOkX%X^5_`1P?V$ZIc}@wQ=SHpfvwy0dKVik@q}27 zR)f=xh#h}hB+%2ReIX%ngEirs4j@&@&MSo zO~vSl`rVv(HQ525FI&7@pCgZi9-_^osN?AL(<798fqJY;boQ@0Wy9!D< zKNnQ~BGa52J-Zrds(W9ilZ(lej}bsxQgto{uQkRM1Br_3wd9K8MNh0#N9@3-Cg||8 zuOYnbEBwPo42_y>)2?UgA`1&8yj2RxEuf_QORvL1v6Hq?^uPFPJSU5 z_;!E!kg&dq+HJhc!$X#eG~vwqlN|5$%kFD2Ixs}kd>s?Afojgqp%xaYDukX8nDIcN z7f!|ln3{Ui1Xtdgm5A<9uofrwDTW@|jx-uZ98pDVay3?IbH0sdn~PUU!IMu3&ZHh$jHkeH)m$^L->K=p{z`Cx>;h@A03R)|;U*KzkxtJnuPJ+9k0wVQ^x=O%V zNYC~M%zMlVWwkOa-C&*{ zPXV%Vvv^toM_7R&Cf}^vCjJ^12=`Cz7(3>bVN@60txi{!tBt1$ZyF-$6`vz=9q#G5 z^IyToC+^*H@Z)}VPAOCSflSdypU{W<*@;Nb-C&1VxQ)mJYxYCMIzExgS4fw$O9tPv zHV6Mj_Zc&G*ga>IOApRPC$F}EyXwiOwv$kXzt;Q!enEF!&WM8?!b>krD24`xz?vPpVq;101opo#x%+te zQV{V;F5`S9RpW8i<&=3|m>qetv155mo$om3dpW4QAjv`5O9!Ie2R)$KC5ZfpsI z7H!fj*6c<60FPeE?Jd>-lpL!?oDbqQE=NCY%zT7l;0TP#X9`4?gxb`q`9katFwBD7E;?4x?Z zOFjCK=kX(&uREkqRsxedxV36OZ288rzOM+OiXTbdKP~2SV4uAdL`YlfJvZ#{Nu1)9 zeV6HNlrI>5-oCvQ!cEGDY@1AX?_UvSO~w;aAHb0jT7}6DG;jv`{Wck=o6OcDsoA>` zNn(j$s1zV$R2#Yoy04hUvq<>_{24IN6`-QF5l|7@{r2)TajrzDVD{oJEAX><9bFv0 zsWB5@6a-BmSPjrL6P}3BM&nmOBf{j@PdTTG&Gk>R;8cW7YCT)yOVv~%;uxnt9=94~ z8F+Ij6C}(5#8&m!apXBU@%{282rHz)VB)OcX}dmObl$Pos*tJFupaj864^Fv^faJ5 z3(XvnZ5}EKN&$)mwLk&%v`i})6jbEv_Gws9tT5S*-B5*mx$5cdZ|s{^j6veD?Cg=S&*bvoP5r=vfzhauow;w^}Tyd&r}6wrGKljIjoeHmlm()kR9Ft5IuSH8oC{ zq(PW0!|$D+H?TAE3G+@HR*mJ)rg~5FtAllL?0fPGU^wHYYMcT&4)Ee+JP$E^qi9S% zxmKe$aOSyqP0eUe6tk4N{I8!}s3~+GW}g@el$>+mzn+jT9Sw|Pw*D|yVnUxS(GI$O z%h?4`lt$Y3wN_ZN9`dXAE&%(Tbg{M{NhG zMq*6fPgZ)susfk^Ki#XgoMWx5tsQ?7vG=gBDR!Od=e;MPGc?*^a*9>DO)Sw+K0JS5t47TYw0?-K#Uk^feBEJsv8G=fsJ+WIG$lPhMp`}>>L z*zLwxNhhfkJleWGl(Mw{%+&F$^GJ6SYHejWRu3XbjL%-S;}W&+(jTW%D1Ff}Wl{Ib zU0z0^m$IHH66mF*p3H1eKZLRPrnk$x*v7ifGAd?>RD1ft|~HO(m~GvpbOlK z9oNm2N&EPV_a9V-np7PBxklT+8%7uLC#6Y9QUBc3!xx}xyV|-e_VC~w*8}d|68HK| zZuxWK)1O*vjVP4rQG^tsO>2kV6}?SD@lt^VW};mG%T`-yfVC99spEO&(q+^xzj|_2 z6~ZHD&n;h~&J}x{wr8@DpngBhq6ox}NMXp`QzXVRhA4)rl56ZM1;Hn{2xoaE22rW) zuT)z}v)Ym&o1v=p_W+xs3UCpShUDNL;wKl)s(t)574CG z{v!r>dCghX%KzfrF|70??VTnvDHj&0(vU}PS?HxyaCC^hsdpNS13|7RfDV;1#*|bQ$SJo+o{i+f*=FXK@I~JR-kA}^Y?zN)H@bvU zCvJm>y2qr~yxa;+M1OU=X`eSued~fz^G@vLD`Hm7@>bf{kp1rf;DA%NxjX2_j4|l! zlstj!CjZQdmMYXQ?-JgDO|$&#^;Pl%X#@5a_UzfBNgTaSQquKkv48D8kG0i!*1(IYO-N=gpXJur|u;z&<|1Qbg<* z=2CQ9#Q6C>!6=uWZT++hAc)W9{)<2d%d!A5sg4ZrS>@&B4-a>@fN=voPIw*oX!hpz zRbmG?0k|Q*I5>xR;!O9q;oY3z`asUy=qd!Gc5Pn)_eVEpKkim-OlF6yc~+V78W1z> zc!F|J#1sgwR~2)8j(f@WA`A|?J>2=51%)!kIA3{V@r}Z(T)VG>Hn;Brht-qU_Yb_D ziVBcenNY&`tkUVs16NXqznslpxVtz@<%iylJJa>FOWYsa-UZzq?B6)wkc%C>4*BL~ zIVfQZ0LBM;mGu*!jRQ2#;3e$6_S0V%DXY+^2wk^RVm1&Pt@ugxRr8N_PrR1!qP3du zQ7Av#;ULW0Beopv;EB{Fn1N{{OnzFt7G@iO#&f-q#65uA7+ecNtXczY?~Y&+S?kM1 zEA8TL@2DU|g%bYwxsM>Li~DSzP50lq0IN7i9-CdnH(b&P_;pKPgS7=jcv5aV3cHpI-Bu~R7pMVX&uhXrg`>Uuj(><2TK|k<@q)v9LNyHSGFGoGMfTmRAu$9 zWtvt}`12NRGAPO@HU$KTM2L%ojM9&9|4_cU6q4uzaxB zM~p=HdvcW?2_+IC3IVg#Ewnu~?g0Jq%A3c=$@oWM@cvZt!3c!(g!E<|D}}9SeN^|O zOVzWmTNSY^LHDz=%NlKZ?)R6$4GBf(A+5Am0Reo1CX#stYn9TC14#05 zN@4?5CP+Wtxl|jyvzbuX-X6i`Znu@PxBx&n4y`B$WWnHq$52!Mt)a4b(Es4F^Wl19 zSPQaKraEnmx`HH-CfShulFlFt>7p#ITcv+idp?qo^e&ql(f_G*>T77$8EM)6{%6e(hc!z#gV3b{K;aC& zRRTNx6;KaPBK+S&)<0CfVrG)&N2(JZg!}06AM+r_B)4L)pMqNODY(^$ZeIJzRbFlgJKTTFNOj1MxXK4# zpb^qbKZ5<}nHIn*qpO89+U3!G2N;hY`YQ}D{&L%6_sVyOd$W8lX%jGYl$VblQhMwP z?~KbR9sKD2$LL^2`onre)jZdLf3YfnsAF zi2(dRWF4gk1|?iNQk2t7Ahwd`Tl^2rE?V80ksbr=4d4sHn#8NQ(MN6nq9F1=Oq@R& zPr@L0jITQdl%EyNICGV#k4F4$DBRS2faEX9@V}B)F$ir68C}z@3%;!u zTmWfTx1!o`1Uj%}NjC7KzC4&Jo6o?UoP3j+=cLZM#NQC;FXh99xJa2ZGEFK&^zxv~ zy^7~C$?aNeCGfQ#lQC;&V36}wMsOPmJ)DlhEf5dEbV0Yxp*<%RU!90R! z=TlTm51{MjC+^=OHlc6NPWpZXJl6K%HGTrYi%(2Ge^HW@>uFI+frzh^;GqO8D&?~A zVHF%7Sv3GBOZn5@P&V56goetS=Pn77XO$KP!52TDA8FfSPPQLEZqc;|h&>$K5f!Ra zHR(F8f&iMHpn6~bKFN*&x~5Hu`%YRb6ISW-lVK9f!=;{q4SvK$$?!ls>x&QSH~dmi zF3yVzmWlbG+&o17gDUxVlmS^gD^Rcm=ng!J;ktI>I(!hi7!oP{P0^n(3{ zX8%Zm^*jH~LNAmUr6Unkpg>{AU!ngu32o{dqS-ex!GoAlT9-DaYT)l!Z)<*m-m35z z{Qu%cNHM~Jn19BI>46ShBs@v{{|>y><-E`p#>ZrXTl`l-71}$~tQ%owVoZYmS9!oA z7>{HN$wxRy9x3Z|jvIR<@KKs2N$lfx$jF)}As!+9BQYzZ{2W^mo#*-sxc`u=UkQ>& z{huh(Ky7C-ivS;vh72YJ3NVsqyRinvW zf>-Mm>N>FhIKzdt*|D|WNS^nkeXATXJ`Zd8uYmupO~ta0aFm>nHGdxcnD7{rIj!zh z29FkBV8VT0NW<_K1=I=GE%o{83-Xj@mHwI@JvFz0(_d#isI!CRFXs4P^#}f*9sF3N zTek^=Pk)KKugZGD=kMKB(Wr5v@#2Cz zk?T>%>!?SSB_DOHWBS`oj}%ylj#Nk0as#x(bL}xN;5jDvpm^QgS{V|l^&y4B1tJ~x zX@yaH{S(%*B*R}n@rfKRZ&45RK}g;e(@td2B|zOW{d3kvwS$#yOWh&Y?@|Pb|DJHM z6U&jm$8a3){rIK{_Uk#>8sO^O7_vne=Ne7&*h0{{6XOmCK71IxxUkPrNOsDVXB=O& zI;pusP|p)9HD-dwQG@9*LjL-63y$DRpiZ6ENYjuHYMk#g6P+9^L4;z;9Z84qEO=TE zJEid!Zx$t~>;8R3{UH96s)R-$T}W*SQsGEC75sWo3hDO|;O6g9z6U}4I=i=Y697=l z5TN}1K{S@@jHi=w!pGUZ0v~kP*NfHb2i}nMc3ohQAw2vR=3Z*7eN{1+T>YSG|EJtt zwdCJJoe$fSZu}&z93Rwy9zja{Z{!)(g>oz%YnztLpZrU@Ow(uIK8$%d2o(`>vtVbF zw@x9cIr9K1sABB&*&#dOYlQFbZ|cVwq2m)tZp8dptpAwqIcAA8mjq@-q#eH~-GqF- z5=0PdG#Of)Lqq2eMOa!|^Z6Nmpw0y z=nXa6%sC^jGeudD@3nPQY=jB5HQLLoM`33?uE0zYg-*jKjEH~0ga|JodF}mpin=a( zP)k(7QZRl>A&n^fN_m_aap_T<6|kB5+WY|R=^$`x8gm8 zCu2zGfV()64Uvt`FpE%3j_DJuJEFy9*W+;U?8*DhubXnNV*0v^ep zw_NhNIBGvST)Mb2 z-rryTo&NA|{|I%{L8}_(WR-?)G)x>7Huca*xJ5}X-7MZ`r>RDbRdA7jonEES-SU)@ zJWHDf9s0u?$hgN#Qe~g^B}M&eyL0}J(u9KPa5Rn)vAVf@7WVQVYT4jQK+AD3@wnmt+ICQ|^{sr?^kKd6A#@fD@L%o^ zt6et0&jl`BF@V5L4<}k)H$j(2QvZRrgc1c6NMNM$$XJ``qV`h`&&sbH<#SEDP$An-{6Unm|841BgzW$fzd5*0- zc~f-;{rJFw_ljRD4L=_RBJsbB+h~!sTqM%6HQ~!1ehZ#OFm^|I+1R+xU30R$2^(>W z7*U!+s6j>+Z}g!JX4;BC@KIFk{5LM@Zzvtg?jmMLKf{~Y9i5OIMj%Nia!aQ_7TTE{ zX|ndxLE}d&#TRfrI{|Ge{ zwt+8g#7gZDu-q1R!b(x=LJYlvFYkK!geqREw+g_YOVPt6e~s$`rD=4BA7||aA`NX5 z*lO6H7MGU!C8Km)uEHtW-7i%7HIZ#l*Fd17s-@wC;o9R*6c#=<)&PbPzzwo*n%M|qz=?_mP`f$XUt2n!!R z9Ndun8^hI~xf+8I^}M%IfwxT({E`bCBO0Mf_ZNRI!j<~je4SiBAnv$*o6e@2%Nm(& zGpev(f=fmqe}!k*Z~(FRqxP?;`?ybVXQyjbi_A=fshEPilo9{ZQNI9j2k8xmqtlVQ sMS$DQWjx1MPwoW=wf6tMEbD=e;g!|8#ghtJ1o%ruL0!I5)->e*07WoH9{>OV 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"