From 2b615b7b10e4e204b9ee6face1ee188569bedb16 Mon Sep 17 00:00:00 2001 From: Fox McCloud Date: Sat, 31 Aug 2019 18:23:59 -0400 Subject: [PATCH] blood drunk update --- code/__DEFINES/mobs.dm | 2 + .../temporary_visuals/miscellaneous.dm | 9 + .../hostile/megafauna/blood_drunk_miner.dm | 132 ++++++---- .../hostile/megafauna/megafauna.dm | 23 ++ .../simple_animal/hostile/mining_mobs.dm | 225 ------------------ .../living/simple_animal/hostile/russian.dm | 1 + .../living/simple_animal/hostile/syndicate.dm | 1 + icons/mob/actions/actions_animal.dmi | Bin 0 -> 5618 bytes 8 files changed, 116 insertions(+), 277 deletions(-) delete mode 100644 code/modules/mob/living/simple_animal/hostile/mining_mobs.dm create mode 100644 icons/mob/actions/actions_animal.dmi diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 608fcfcce20..11b03d7102a 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -218,3 +218,5 @@ #define hasorgans(A) (ishuman(A)) #define is_admin(user) (check_rights(R_ADMIN, 0, (user)) != 0) + +#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return; \ No newline at end of file diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index 7f1683ba415..d6dbf1dddbb 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -140,6 +140,15 @@ ..() animate(src, alpha = 0, time = duration) +/obj/effect/temp_visual/decoy/fading/threesecond + duration = 40 + +/obj/effect/temp_visual/decoy/fading/fivesecond + duration = 50 + +/obj/effect/temp_visual/decoy/fading/halfsecond + duration = 5 + /obj/effect/temp_visual/fire icon = 'icons/goonstation/effects/fire.dmi' icon_state = "3" diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm index d45e6f6ead8..db96f9fce96 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm @@ -34,7 +34,7 @@ Difficulty: Medium move_to_delay = 3 projectiletype = /obj/item/projectile/kinetic/miner projectilesound = 'sound/weapons/kenetic_accel.ogg' - ranged = 1 + ranged = TRUE ranged_cooldown_time = 16 pixel_x = -16 crusher_loot = list(/obj/item/melee/energy/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye) @@ -47,8 +47,12 @@ Difficulty: Medium var/dashing = FALSE var/dash_cooldown = 15 var/guidance = FALSE + var/transform_stop_attack = FALSE // stops the blood drunk miner from attacking after transforming his weapon until the next attack chain deathmessage = "falls to the ground, decaying into glowing particles." death_sound = "bodyfall" + attack_action_types = list(/datum/action/innate/megafauna_attack/dash, + /datum/action/innate/megafauna_attack/kinetic_accelerator, + /datum/action/innate/megafauna_attack/transform_weapon) /obj/item/gps/internal/miner icon_state = null @@ -56,13 +60,52 @@ Difficulty: Medium desc = "The sweet blood, oh, it sings to me." invisibility = 100 -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/guidance - guidance = TRUE - -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/hunter/AttackingTarget() +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/Initialize(mapload) . = ..() - if(. && prob(12)) - INVOKE_ASYNC(src, .proc/dash) + miner_saw = new(src) + internal_gps = new/obj/item/gps/internal/miner(src) + + // Add a zone selection UI; otherwise the mob can't melee attack properly. + zone_sel = new /obj/screen/zone_sel() + +/datum/action/innate/megafauna_attack/dash + name = "Dash To Target" + icon_icon = 'icons/mob/actions/actions.dmi' + button_icon_state = "sniper_zoom" + chosen_message = "You are now dashing to your target." + chosen_attack_num = 1 + +/datum/action/innate/megafauna_attack/kinetic_accelerator + name = "Fire Kinetic Accelerator" + icon_icon = 'icons/obj/guns/energy.dmi' + button_icon_state = "kineticgun" + chosen_message = "You are now shooting your kinetic accelerator." + chosen_attack_num = 2 + +/datum/action/innate/megafauna_attack/transform_weapon + name = "Transform Weapon" + icon_icon = 'icons/obj/lavaland/artefacts.dmi' + button_icon_state = "cleaving_saw" + chosen_message = "You are now transforming your weapon." + chosen_attack_num = 3 + +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/OpenFire() + if(client) + switch(chosen_attack) + if(1) + dash(target) + if(2) + shoot_ka() + if(3) + transform_weapon() + return + + Goto(target, move_to_delay, minimum_distance) + if(get_dist(src, target) > MINER_DASH_RANGE && dash_cooldown <= world.time) + dash_attack() + else + shoot_ka() + transform_weapon() /obj/item/melee/energy/cleaving_saw/miner //nerfed saw because it is very murdery force = 6 @@ -79,14 +122,6 @@ Difficulty: Medium icon_state = "ka_tracer" range = MINER_DASH_RANGE -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/Initialize() - . = ..() - miner_saw = new(src) - internal_gps = new/obj/item/gps/internal/miner(src) - - // Add a zone selection UI; otherwise the mob can't melee attack properly. - zone_sel = new /obj/screen/zone_sel() - /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/adjustHealth(amount, updating_health = TRUE, forced = FALSE) var/adjustment_amount = amount * 0.1 if(world.time + adjustment_amount > next_move) @@ -104,16 +139,19 @@ Difficulty: Medium return FALSE return ..() -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/ex_act(severity, target) +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/ex_act(severity) if(dash()) return return ..() +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/MeleeAction(patience = TRUE) + transform_stop_attack = FALSE + return ..() + /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/AttackingTarget() - if(QDELETED(target)) - return - if(next_move > world.time || !Adjacent(target)) //some cheating - INVOKE_ASYNC(src, .proc/quick_attack_loop) + if(client) + transform_stop_attack = FALSE + if(QDELETED(target) || transform_stop_attack) return face_atom(target) if(isliving(target)) @@ -132,8 +170,6 @@ Difficulty: Medium miner_saw.melee_attack_chain(src, target) if(guidance) adjustHealth(-2) - transform_weapon() - INVOKE_ASYNC(src, .proc/quick_attack_loop) return TRUE /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) @@ -146,16 +182,10 @@ Difficulty: Medium . = ..() if(. && target && !targets_the_same) wander = TRUE - transform_weapon() - INVOKE_ASYNC(src, .proc/quick_attack_loop) -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/OpenFire() - Goto(target, move_to_delay, minimum_distance) - if(get_dist(src, target) > MINER_DASH_RANGE && dash_cooldown <= world.time) - INVOKE_ASYNC(src, .proc/dash, target) - else - shoot_ka() - transform_weapon() +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/dash_attack() + INVOKE_ASYNC(src, .proc/dash, target) + shoot_ka() /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/shoot_ka() if(ranged_cooldown <= world.time && get_dist(src, target) <= MINER_DASH_RANGE && !Adjacent(target)) @@ -166,21 +196,6 @@ Difficulty: Medium Shoot(target) changeNext_move(CLICK_CD_RANGE) -//I'm still of the belief that this entire proc needs to be wiped from existence. -// do not take my touching of it to be endorsement of it. ~mso -/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/quick_attack_loop() - while(!QDELETED(target) && next_move <= world.time) //this is done this way because next_move can change to be sooner while we sleep. - stoplag(1) - sleep((next_move - world.time) * 1.5) //but don't ask me what the fuck this is about - if(QDELETED(target)) - return - if(dashing || next_move > world.time || !Adjacent(target)) - if(dashing && next_move <= world.time) - next_move = world.time + 1 - INVOKE_ASYNC(src, .proc/quick_attack_loop) //lets try that again. - return - AttackingTarget() - /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/dash(atom/dash_target) if(world.time < dash_cooldown) return @@ -189,7 +204,9 @@ Difficulty: Medium var/turf/own_turf = get_turf(src) if(!QDELETED(dash_target)) self_dist_to_target += get_dist(dash_target, own_turf) - for(var/turf/simulated/O in RANGE_TURFS(MINER_DASH_RANGE, own_turf)) + for(var/turf/O in RANGE_TURFS(MINER_DASH_RANGE, own_turf)) + if(O.density) + continue var/turf_dist_to_target = 0 if(!QDELETED(dash_target)) turf_dist_to_target += get_dist(dash_target, O) @@ -218,26 +235,29 @@ Difficulty: Medium var/turf/step_forward_turf = get_step(own_turf, get_cardinal_dir(own_turf, target_turf)) new /obj/effect/temp_visual/small_smoke/halfsecond(step_back_turf) new /obj/effect/temp_visual/small_smoke/halfsecond(step_forward_turf) - var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc, src) - animate(D, alpha = 0, time = 5) + var/obj/effect/temp_visual/decoy/fading/halfsecond/D = new (own_turf, src) forceMove(step_back_turf) playsound(own_turf, 'sound/weapons/punchmiss.ogg', 40, 1, -1) dashing = TRUE alpha = 0 animate(src, alpha = 255, time = 5) - sleep(2) + SLEEP_CHECK_DEATH(2) D.forceMove(step_forward_turf) forceMove(target_turf) playsound(target_turf, 'sound/weapons/punchmiss.ogg', 40, 1, -1) - sleep(1) + SLEEP_CHECK_DEATH(1) dashing = FALSE - shoot_ka() return TRUE /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/transform_weapon() if(time_until_next_transform <= world.time) miner_saw.transform_cooldown = 0 miner_saw.transform_weapon(src, TRUE) + if(!miner_saw.active) + rapid_melee = 5 // 4 deci cooldown before changes, npcpool subsystem wait is 20, 20/4 = 5 + else + rapid_melee = 3 // same thing but halved (slightly rounded up) + transform_stop_attack = TRUE icon_state = "miner[miner_saw.active ? "_transformed":""]" icon_living = "miner[miner_saw.active ? "_transformed":""]" time_until_next_transform = world.time + rand(50, 100) @@ -263,4 +283,12 @@ Difficulty: Medium sleep(4) animate(src, alpha = 0, time = 6, easing = EASE_OUT, flags = ANIMATION_PARALLEL) +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/guidance + guidance = TRUE + +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/hunter/AttackingTarget() + . = ..() + if(. && prob(12)) + INVOKE_ASYNC(src, .proc/dash) + #undef MINER_DASH_RANGE \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index b618ff9e650..20df360a51a 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -32,10 +32,15 @@ mob_size = MOB_SIZE_LARGE layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway + var/chosen_attack = 1 // chosen attack num + var/list/attack_action_types = list() /mob/living/simple_animal/hostile/megafauna/New() ..() apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING) + for(var/action_type in attack_action_types) + var/datum/action/innate/megafauna_attack/attack_action = new action_type() + attack_action.Grant(src) /mob/living/simple_animal/hostile/megafauna/Destroy() QDEL_NULL(internal_gps) @@ -113,3 +118,21 @@ SSmedals.SetScore(BOSS_SCORE, C, 1) SSmedals.SetScore(score_type, C, 1) return TRUE + +/datum/action/innate/megafauna_attack + name = "Megafauna Attack" + icon_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon_state = "" + var/mob/living/simple_animal/hostile/megafauna/M + var/chosen_message + var/chosen_attack_num = 0 + +/datum/action/innate/megafauna_attack/Grant(mob/living/L) + if(istype(L, /mob/living/simple_animal/hostile/megafauna)) + M = L + return ..() + return FALSE + +/datum/action/innate/megafauna_attack/Activate() + M.chosen_attack = chosen_attack_num + to_chat(M, chosen_message) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm deleted file mode 100644 index efc18895141..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm +++ /dev/null @@ -1,225 +0,0 @@ -/mob/living/simple_animal/hostile/asteroid/ - vision_range = 2 - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - unsuitable_atmos_damage = 15 - faction = list("mining") - weather_immunities = list("lava","ash") - obj_damage = 30 - environment_smash = 2 - minbodytemp = 0 - heat_damage_per_tick = 20 - response_help = "pokes" - response_disarm = "shoves" - response_harm = "strikes" - status_flags = 0 - a_intent = INTENT_HARM - var/throw_message = "bounces off of" - var/icon_aggro = null // for swapping to when we get aggressive - see_in_dark = 8 - lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE - mob_size = MOB_SIZE_LARGE - -/mob/living/simple_animal/hostile/asteroid/Aggro() - ..() - icon_state = icon_aggro - -/mob/living/simple_animal/hostile/asteroid/LoseAggro() - ..() - if(stat == CONSCIOUS) - icon_state = icon_living - -/mob/living/simple_animal/hostile/asteroid/bullet_act(var/obj/item/projectile/P)//Reduces damage from most projectiles to curb off-screen kills - if(!stat) - Aggro() - if(P.damage < 30 && P.damage_type != BRUTE) - P.damage = (P.damage / 3) - visible_message("The [P] has a reduced effect on [src]!") - ..() - -/mob/living/simple_animal/hostile/asteroid/hitby(atom/movable/AM)//No floor tiling them to death, wiseguy - if(istype(AM, /obj/item)) - var/obj/item/T = AM - if(!stat) - Aggro() - if(T.throwforce <= 20) - visible_message("The [T.name] [src.throw_message] [src.name]!") - return - ..() - -/mob/living/simple_animal/hostile/asteroid/basilisk - name = "basilisk" - desc = "A territorial beast, covered in a thick shell that absorbs energy. Its stare causes victims to freeze from the inside." - icon = 'icons/mob/animal.dmi' - icon_state = "Basilisk" - icon_living = "Basilisk" - icon_aggro = "Basilisk_alert" - icon_dead = "Basilisk_dead" - icon_gib = "syndicate_gib" - move_to_delay = 20 - projectiletype = /obj/item/projectile/temp/basilisk - projectilesound = 'sound/weapons/pierce.ogg' - ranged = 1 - ranged_message = "stares" - ranged_cooldown_time = 30 - throw_message = "does nothing against the hard shell of" - vision_range = 2 - speed = 3 - maxHealth = 200 - health = 200 - harm_intent_damage = 5 - obj_damage = 60 - melee_damage_lower = 12 - melee_damage_upper = 12 - attacktext = "bites into" - a_intent = INTENT_HARM - speak_emote = list("chitters") - attack_sound = 'sound/weapons/bladeslice.ogg' - aggro_vision_range = 9 - idle_vision_range = 2 - turns_per_move = 5 - loot = list(/obj/item/stack/ore/diamond{layer = 4.1}, - /obj/item/stack/ore/diamond{layer = 4.1}) - -/obj/item/projectile/temp/basilisk - name = "freezing blast" - icon_state = "ice_2" - damage = 0 - damage_type = BURN - nodamage = 1 - flag = "energy" - temperature = 50 - -/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(var/new_target) - if(..()) //we have a target - if(isliving(target)) - var/mob/living/L = target - if(L.bodytemperature > 261) - L.bodytemperature = 261 - visible_message("The [src.name]'s stare chills [L.name] to the bone!") - -/mob/living/simple_animal/hostile/asteroid/basilisk/ex_act(severity) - switch(severity) - if(1.0) - gib() - if(2.0) - adjustBruteLoss(140) - if(3.0) - adjustBruteLoss(110) - -/mob/living/simple_animal/hostile/asteroid/goliath - name = "goliath" - desc = "A massive beast that uses long tentacles to ensare its prey, threatening them is not advised under any conditions." - icon = 'icons/mob/animal.dmi' - icon_state = "Goliath" - icon_living = "Goliath" - icon_aggro = "Goliath_alert" - icon_dead = "Goliath_dead" - icon_gib = "syndicate_gib" - attack_sound = 'sound/weapons/punch4.ogg' - mouse_opacity = MOUSE_OPACITY_OPAQUE - move_to_delay = 40 - ranged = 1 - ranged_cooldown = 2 //By default, start the Goliath with his cooldown off so that people can run away quickly on first sight - ranged_cooldown_time = 120 - friendly = "wails at" - speak_emote = list("bellows") - vision_range = 4 - speed = 3 - maxHealth = 300 - health = 300 - harm_intent_damage = 1 //Only the manliest of men can kill a Goliath with only their fists. - obj_damage = 100 - melee_damage_lower = 25 - melee_damage_upper = 25 - attacktext = "pulverizes" - attack_sound = 'sound/weapons/punch1.ogg' - throw_message = "does nothing to the rocky hide of the" - aggro_vision_range = 9 - idle_vision_range = 5 - move_force = MOVE_FORCE_VERY_STRONG - move_resist = MOVE_FORCE_VERY_STRONG - pull_force = MOVE_FORCE_VERY_STRONG - var/pre_attack = 0 - loot = list(/obj/item/stack/sheet/animalhide/goliath_hide{layer = ABOVE_MOB_LAYER}) - -/mob/living/simple_animal/hostile/asteroid/goliath/Life() - ..() - handle_preattack() - -/mob/living/simple_animal/hostile/asteroid/goliath/proc/handle_preattack() - if(ranged_cooldown <= world.time + ranged_cooldown_time * 0.25 && !pre_attack) - pre_attack++ - if(!pre_attack || stat || AIStatus == AI_IDLE) - return - icon_state = "Goliath_preattack" - -/mob/living/simple_animal/hostile/asteroid/goliath/revive() - move_force = MOVE_FORCE_VERY_STRONG - move_resist = MOVE_FORCE_VERY_STRONG - pull_force = MOVE_FORCE_VERY_STRONG - ..() - -/mob/living/simple_animal/hostile/asteroid/goliath/OpenFire() - var/tturf = get_turf(target) - if(get_dist(src, target) <= 7)//Screen range check, so you can't get tentacle'd offscreen - visible_message("The [src.name] digs its tentacles under [target.name]!") - new /obj/effect/goliath_tentacle/original(tturf) - ranged_cooldown = world.time + ranged_cooldown_time - icon_state = icon_aggro - pre_attack = 0 - return - -/mob/living/simple_animal/hostile/asteroid/goliath/adjustHealth(damage) - ranged_cooldown-- - handle_preattack() - ..() - -/mob/living/simple_animal/hostile/asteroid/goliath/Aggro() - vision_range = aggro_vision_range - handle_preattack() - if(icon_state != icon_aggro) - icon_state = icon_aggro - return - -/obj/effect/goliath_tentacle/ - name = "Goliath tentacle" - icon = 'icons/mob/animal.dmi' - icon_state = "Goliath_tentacle" - var/latched = 0 - -/obj/effect/goliath_tentacle/New() - var/turftype = get_turf(src) - if(istype(turftype, /turf/simulated/mineral)) - var/turf/simulated/mineral/M = turftype - M.gets_drilled() - spawn(20) - Trip() - -/obj/effect/goliath_tentacle/original - -/obj/effect/goliath_tentacle/original/New() - for(var/obj/effect/goliath_tentacle/original/O in loc)//No more GG NO RE from 2+ goliaths simultaneously tentacling you - if(O != src) - qdel(src) - var/list/directions = cardinal.Copy() - var/counter - for(counter = 1, counter <= 3, counter++) - var/spawndir = pick(directions) - directions -= spawndir - var/turf/T = get_step(src,spawndir) - new /obj/effect/goliath_tentacle(T) - ..() - - -/obj/effect/goliath_tentacle/proc/Trip() - for(var/mob/living/M in src.loc) - M.Stun(5) - M.adjustBruteLoss(rand(10,15)) - latched = 1 - if(src && M) - visible_message("The [src.name] grabs hold of [M.name]!") - if(!latched) - qdel(src) - else - spawn(50) - qdel(src) diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm index a4f7cce2f51..0c5f2647ae8 100644 --- a/code/modules/mob/living/simple_animal/hostile/russian.dm +++ b/code/modules/mob/living/simple_animal/hostile/russian.dm @@ -33,6 +33,7 @@ ranged = 1 retreat_distance = 5 minimum_distance = 5 + projectilesound = 'sound/weapons/gunshots/gunshot.ogg' casingtype = /obj/item/ammo_casing/a357 loot = list(/obj/effect/mob_spawn/human/corpse/russian/ranged, /obj/item/gun/projectile/revolver/mateba) diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 546fa3ad50d..d95c18dd831 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -262,6 +262,7 @@ minimum_distance = 5 icon_state = "syndicateranged" icon_living = "syndicateranged" + projectilesound = 'sound/weapons/gunshots/gunshot.ogg' casingtype = /obj/item/ammo_casing/c45 loot = list(/obj/effect/mob_spawn/human/corpse/syndicatesoldier, /obj/item/gun/projectile/automatic/c20r) diff --git a/icons/mob/actions/actions_animal.dmi b/icons/mob/actions/actions_animal.dmi new file mode 100644 index 0000000000000000000000000000000000000000..e8f2d4ada8346079e62a06c1b84d9c3bc5b852fa GIT binary patch literal 5618 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 literal 0 HcmV?d00001