From c2d4620b0b971413f429266be14f99d881d07aee Mon Sep 17 00:00:00 2001 From: Atsuihsio <842960157@qq.com> Date: Sat, 21 Dec 2024 00:22:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BA=A2=E4=B8=89=E8=A7=92?= =?UTF-8?q?=E5=92=8C=E9=94=81=E5=AE=9A=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/screens/JavelinHudOverlay.java | 45 ++++++++- .../client/screens/RedTriangleOverlay.java | 67 ++++++++++++++ .../item/gun/launcher/JavelinItem.java | 7 +- .../superbwarfare/tools/HudUtil.java | 87 ++++++++++++++++++ .../superbwarfare/tools/SeekTool.java | 3 +- .../textures/screens/javelin/frame.png | Bin 0 -> 245 bytes .../textures/screens/javelin/frame_lock.png | Bin 0 -> 460 bytes .../textures/screens/javelin/red_triangle.png | Bin 0 -> 732 bytes .../textures/screens/red_triangle.png | Bin 0 -> 732 bytes 9 files changed, 200 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/screens/RedTriangleOverlay.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/tools/HudUtil.java create mode 100644 src/main/resources/assets/superbwarfare/textures/screens/javelin/frame.png create mode 100644 src/main/resources/assets/superbwarfare/textures/screens/javelin/frame_lock.png create mode 100644 src/main/resources/assets/superbwarfare/textures/screens/javelin/red_triangle.png create mode 100644 src/main/resources/assets/superbwarfare/textures/screens/red_triangle.png diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/JavelinHudOverlay.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/JavelinHudOverlay.java index aa8fe58b8..680bac601 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/screens/JavelinHudOverlay.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/JavelinHudOverlay.java @@ -1,17 +1,26 @@ package com.atsuishio.superbwarfare.client.screens; -import com.atsuishio.superbwarfare.network.ModVariables; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.client.RenderHelper; import com.atsuishio.superbwarfare.event.ClientEventHandler; import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.network.ModVariables; +import com.atsuishio.superbwarfare.tools.EntityFindUtil; +import com.atsuishio.superbwarfare.tools.HudUtil; +import com.atsuishio.superbwarfare.tools.SeekTool; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.RenderType; +import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.RenderGuiEvent; import net.minecraftforge.eventbus.api.EventPriority; @@ -22,14 +31,21 @@ import static com.atsuishio.superbwarfare.client.RenderHelper.preciseBlit; @Mod.EventBusSubscriber(value = Dist.CLIENT) public class JavelinHudOverlay { - + private static final ResourceLocation FRAME = ModUtils.loc("textures/screens/javelin/frame.png"); + private static final ResourceLocation FRAME_LOCK = ModUtils.loc("textures/screens/javelin/frame_lock.png"); private static float scopeScale = 1; + @SubscribeEvent(priority = EventPriority.LOWEST) public static void eventHandler(RenderGuiEvent.Pre event) { int w = event.getWindow().getGuiScaledWidth(); int h = event.getWindow().getGuiScaledHeight(); Player player = Minecraft.getInstance().player; + Minecraft mc = Minecraft.getInstance(); + Camera camera = mc.gameRenderer.getMainCamera(); + Vec3 cameraPos = camera.getPosition(); + PoseStack poseStack = event.getGuiGraphics().pose(); + if (player != null) { ItemStack stack = player.getMainHandItem(); @@ -60,6 +76,7 @@ public class JavelinHudOverlay { if (stack.getOrCreateTag().getInt("SeekTime") > 1 && stack.getOrCreateTag().getInt("SeekTime") < 20) { preciseBlit(event.getGuiGraphics(), ModUtils.loc("textures/screens/javelin/seek.png"), k, l, 0, 0.0F, i, j, i, j); } + event.getGuiGraphics().fill(RenderType.guiOverlay(), 0, (int) l, (int) k + 3, (int) j1, -90, -16777216); event.getGuiGraphics().fill(RenderType.guiOverlay(), (int) i1, (int) l, w, (int) j1, -90, -16777216); RenderSystem.depthMask(true); @@ -67,6 +84,26 @@ public class JavelinHudOverlay { RenderSystem.enableDepthTest(); RenderSystem.disableBlend(); RenderSystem.setShaderColor(1, 1, 1, 1); + + Entity targetEntity = EntityFindUtil.findEntity(player.level(), stack.getOrCreateTag().getString("TargetEntity")); + Entity seekingEntity = SeekTool.seekEntity(player, player.level(), 512, 8); + + if (seekingEntity == null) return; + + Vec3 p = RenderHelper.worldToScreen(new Vec3(seekingEntity.getX(), seekingEntity.getEyeY(),seekingEntity.getZ()), cameraPos); + + if (p == null) return; + + boolean lockOn = stack.getOrCreateTag().getInt("SeekTime") > 20 && seekingEntity == targetEntity; + + poseStack.pushPose(); + + int x = (int) p.x; + int y = (int) p.y; + + HudUtil.blit(poseStack, lockOn ? FRAME_LOCK : FRAME, x-8, y-8, 0, 0, 16, 16, 16, 16, 1f); + + poseStack.popPose(); } else { scopeScale = 1; } diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/RedTriangleOverlay.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/RedTriangleOverlay.java new file mode 100644 index 000000000..32ec5feee --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/RedTriangleOverlay.java @@ -0,0 +1,67 @@ +package com.atsuishio.superbwarfare.client.screens; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.client.RenderHelper; +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.tools.HudUtil; +import com.atsuishio.superbwarfare.tools.SeekTool; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.RenderGuiEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(value = Dist.CLIENT) +public class RedTriangleOverlay { + private static final ResourceLocation TRIANGLE = ModUtils.loc("textures/screens/red_triangle.png"); + + @SubscribeEvent(priority = EventPriority.NORMAL) + public static void eventHandler(RenderGuiEvent.Pre event) { + int w = event.getWindow().getGuiScaledWidth(); + int h = event.getWindow().getGuiScaledHeight(); + Minecraft mc = Minecraft.getInstance(); + Camera camera = mc.gameRenderer.getMainCamera(); + Vec3 cameraPos = camera.getPosition(); + PoseStack poseStack = event.getGuiGraphics().pose(); + + Player player = Minecraft.getInstance().player; + if (player == null) return; + + ItemStack stack = player.getMainHandItem(); + + if (stack.is(ModItems.RPG.get())) { + Entity idf = SeekTool.seekLivingEntity(player, player.level(),128,6); + + if (idf == null) return; + + Vec3 p = RenderHelper.worldToScreen(new Vec3(idf.getX(), idf.getEyeY() + 2,idf.getZ()), cameraPos); + + if (p == null) return; + + poseStack.pushPose(); + + int x = (int) p.x; + int y = (int) p.y; + + HudUtil.blit(poseStack, TRIANGLE, x-4, y-4, 0, 0, 8, 8, 8, 8, -65536); + + poseStack.popPose(); + + } + + RenderSystem.depthMask(true); + RenderSystem.defaultBlendFunc(); + RenderSystem.enableDepthTest(); + RenderSystem.disableBlend(); + RenderSystem.setShaderColor(1, 1, 1, 1); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/launcher/JavelinItem.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/launcher/JavelinItem.java index f59de3a66..cc5e961f0 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/gun/launcher/JavelinItem.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/launcher/JavelinItem.java @@ -21,7 +21,6 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.world.InteractionHand; -import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; @@ -155,9 +154,9 @@ public class JavelinItem extends GunItem implements GeoItem, AnimatedItem { } if (seekingEntity != null && tag.getInt("SeekTime") > 20) { - if (seekingEntity instanceof LivingEntity living) { - living.addEffect(new MobEffectInstance(MobEffects.GLOWING, 40, 0)); - } +// if (seekingEntity instanceof LivingEntity living) { +// living.addEffect(new MobEffectInstance(MobEffects.GLOWING, 40, 0)); +// } if (player instanceof ServerPlayer serverPlayer) { SoundTool.playLocalSound(serverPlayer, ModSounds.JAVELIN_LOCKON.get(), 2, 1); diff --git a/src/main/java/com/atsuishio/superbwarfare/tools/HudUtil.java b/src/main/java/com/atsuishio/superbwarfare/tools/HudUtil.java new file mode 100644 index 000000000..e807c4b71 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/tools/HudUtil.java @@ -0,0 +1,87 @@ +package com.atsuishio.superbwarfare.tools; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.*; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.resources.ResourceLocation; +import org.joml.Matrix4f; + +public class HudUtil { + public static void blit(PoseStack pose, ResourceLocation pAtlasLocation, int pX, int pY, float pUOffset, float pVOffset, int pWidth, int pHeight, int pTextureWidth, int pTextureHeight, int color) { + blit(pose, pAtlasLocation, pX, pY, pWidth, pHeight, pUOffset, pVOffset, pWidth, pHeight, pTextureWidth, pTextureHeight, color); + } + + public static void blit(PoseStack pose, ResourceLocation pAtlasLocation, int pX, int pY, int pWidth, int pHeight, float pUOffset, float pVOffset, int pUWidth, int pVHeight, int pTextureWidth, int pTextureHeight, int color) { + blit(pose, pAtlasLocation, pX, pX + pWidth, pY, pY + pHeight, 0, pUWidth, pVHeight, pUOffset, pVOffset, pTextureWidth, pTextureHeight, color); + } + + public static void blit(PoseStack pose, ResourceLocation pAtlasLocation, int pX1, int pX2, int pY1, int pY2, int pBlitOffset, int pUWidth, int pVHeight, float pUOffset, float pVOffset, int pTextureWidth, int pTextureHeight, int color) { + innerBlit(pose, pAtlasLocation, pX1, pX2, pY1, pY2, pBlitOffset, (pUOffset + 0.0F) / (float)pTextureWidth, (pUOffset + (float)pUWidth) / (float)pTextureWidth, (pVOffset + 0.0F) / (float)pTextureHeight, (pVOffset + (float)pVHeight) / (float)pTextureHeight, color); + } + + public static void blit(PoseStack pose, ResourceLocation pAtlasLocation, int pX, int pY, float pUOffset, float pVOffset, int pWidth, int pHeight, int pTextureWidth, int pTextureHeight, float alpha, boolean opposite) { + blit(pose, pAtlasLocation, pX, pY, pWidth, pHeight, pUOffset, pVOffset, pWidth, pHeight, pTextureWidth, pTextureHeight, alpha, opposite); + } + public static void blit(PoseStack pose, ResourceLocation pAtlasLocation, int pX, int pY, float pUOffset, float pVOffset, int pWidth, int pHeight, int pTextureWidth, int pTextureHeight, float alpha) { + blit(pose, pAtlasLocation, pX, pY, pUOffset, pVOffset, pWidth, pHeight, pTextureWidth, pTextureHeight, alpha, false); + } + + public static void blit(PoseStack pose, ResourceLocation pAtlasLocation, int pX, int pY, int pWidth, int pHeight, float pUOffset, float pVOffset, int pUWidth, int pVHeight, int pTextureWidth, int pTextureHeight, float alpha, boolean opposite) { + blit(pose, pAtlasLocation, pX, pX + pWidth, pY, pY + pHeight, 0, pUWidth, pVHeight, pUOffset, pVOffset, pTextureWidth, pTextureHeight, alpha, opposite); + } + + public static void blit(PoseStack pose, ResourceLocation pAtlasLocation, int pX1, int pX2, int pY1, int pY2, int pBlitOffset, int pUWidth, int pVHeight, float pUOffset, float pVOffset, int pTextureWidth, int pTextureHeight, float alpha, boolean opposite) { + innerBlit(pose, pAtlasLocation, pX1, pX2, pY1, pY2, pBlitOffset, (pUOffset + 0.0F) / (float)pTextureWidth, (pUOffset + (float)pUWidth) / (float)pTextureWidth, (pVOffset + 0.0F) / (float)pTextureHeight, (pVOffset + (float)pVHeight) / (float)pTextureHeight, alpha, opposite); + } + + private static void innerBlit(PoseStack pose, ResourceLocation pAtlasLocation, int pX1, int pX2, int pY1, int pY2, int pBlitOffset, float pMinU, float pMaxU, float pMinV, float pMaxV, int color) { + RenderSystem.setShaderTexture(0, pAtlasLocation); + RenderSystem.setShader(GameRenderer::getPositionColorTexShader); + + Matrix4f matrix4f = pose.last().pose(); + BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); + bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX); + + vertexC(pX1, pX2, pY1, pY2, pBlitOffset, pMinU, pMaxU, pMinV, pMaxV, color, matrix4f, bufferbuilder); + + BufferUploader.drawWithShader(bufferbuilder.end()); + } + + private static void innerBlit(PoseStack pose, ResourceLocation pAtlasLocation, int pX1, int pX2, int pY1, int pY2, int pBlitOffset, float pMinU, float pMaxU, float pMinV, float pMaxV, float alpha, boolean opposite) { + RenderSystem.setShaderTexture(0, pAtlasLocation); + RenderSystem.setShader(GameRenderer::getPositionColorTexShader); + RenderSystem.enableBlend(); + Matrix4f matrix4f = pose.last().pose(); + BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); + bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX); + + if(opposite){ + vertex(pX1, pX2, pY1, pY2, pBlitOffset, pMaxU, pMinU, pMinV, pMaxV, alpha, matrix4f, bufferbuilder); + }else { + vertex(pX1, pX2, pY1, pY2, pBlitOffset, pMinU, pMaxU, pMinV, pMaxV, alpha, matrix4f, bufferbuilder); + } + + BufferUploader.drawWithShader(bufferbuilder.end()); + RenderSystem.disableBlend(); + } + + private static void vertex(float pX1, float pX2, float pY1, float pY2, float pBlitOffset, float pMinU, float pMaxU, float pMinV, float pMaxV, float alpha, Matrix4f matrix4f, BufferBuilder bufferbuilder) { + bufferbuilder.vertex(matrix4f, pX1, pY1, pBlitOffset).color(1f, 1f, 1f, alpha).uv(pMinU, pMinV).endVertex(); + bufferbuilder.vertex(matrix4f, pX1, pY2, pBlitOffset).color(1f, 1f, 1f, alpha).uv(pMinU, pMaxV).endVertex(); + bufferbuilder.vertex(matrix4f, pX2, pY2, pBlitOffset).color(1f, 1f, 1f, alpha).uv(pMaxU, pMaxV).endVertex(); + bufferbuilder.vertex(matrix4f, pX2, pY1, pBlitOffset).color(1f, 1f, 1f, alpha).uv(pMaxU, pMinV).endVertex(); + } + + private static void vertexC(float pX1, float pX2, float pY1, float pY2, float pBlitOffset, float pMinU, float pMaxU, float pMinV, float pMaxV, int color, Matrix4f matrix4f, BufferBuilder bufferbuilder) { + float r = (float)(color >> 16 & 255) / 255.0F; + float g = (float)(color >> 8 & 255) / 255.0F; + float b = (float)(color & 255) / 255.0F; + + bufferbuilder.vertex(matrix4f, pX1, pY1, pBlitOffset).color(r, g, b, 1f).uv(pMinU, pMinV).endVertex(); + bufferbuilder.vertex(matrix4f, pX1, pY2, pBlitOffset).color(r, g, b, 1f).uv(pMinU, pMaxV).endVertex(); + bufferbuilder.vertex(matrix4f, pX2, pY2, pBlitOffset).color(r, g, b, 1f).uv(pMaxU, pMaxV).endVertex(); + bufferbuilder.vertex(matrix4f, pX2, pY1, pBlitOffset).color(r, g, b, 1f).uv(pMaxU, pMinV).endVertex(); + } + + +} diff --git a/src/main/java/com/atsuishio/superbwarfare/tools/SeekTool.java b/src/main/java/com/atsuishio/superbwarfare/tools/SeekTool.java index 9e6fa29cc..5b303f991 100644 --- a/src/main/java/com/atsuishio/superbwarfare/tools/SeekTool.java +++ b/src/main/java/com/atsuishio/superbwarfare/tools/SeekTool.java @@ -1,5 +1,6 @@ package com.atsuishio.superbwarfare.tools; +import com.atsuishio.superbwarfare.entity.IVehicleEntity; import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; @@ -38,7 +39,7 @@ public class SeekTool { if (e.distanceTo(entity) <= seekRange && calculateAngle(e, entity) < seekAngle && e != entity && e.isAlive() - && e instanceof LivingEntity + && (e instanceof LivingEntity || e instanceof IVehicleEntity) && !(e instanceof Player player && (player.isCreative() || player.isSpectator())) && (!e.isAlliedTo(entity) || e.getTeam() == null || e.getTeam().getName().equals("TDM"))) { return level.clip(new ClipContext(entity.getEyePosition(), e.getEyePosition(), diff --git a/src/main/resources/assets/superbwarfare/textures/screens/javelin/frame.png b/src/main/resources/assets/superbwarfare/textures/screens/javelin/frame.png new file mode 100644 index 0000000000000000000000000000000000000000..29c93af169e88b298014d03d9992eba320e19eea GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;j}Y zi(^Q|oVPa*@-`a?um$u1oj;Tr{obD6kon|$wU5n{`H~HC4#o_&4QUKj3}+d> zFwA0n!DzyKfjNV10s93W2mS@v6l^)U`{3%BssB?{7;0VTbub5nKL*+hLQC58&oc8Z UikaQ84d`SBPgg&ebxsLQ0RBo`R{#J2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/superbwarfare/textures/screens/javelin/frame_lock.png b/src/main/resources/assets/superbwarfare/textures/screens/javelin/frame_lock.png new file mode 100644 index 0000000000000000000000000000000000000000..ffc05897b16b33e732ed0f02de5daf52e18975d3 GIT binary patch literal 460 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|R57 zr;B4q#hkaZqVt*!L|lBY&P`=M*AyV;Qg-0h3;u~0*2aII$j4i}hZat4!H4ZE8Gl&qn@yaYI@8esl9E}f% zP2^svv`Mu}ZR@W|exI-2y3KrJ<=2br>XsNyJ;lG4_n#Jn_FbIT#`F?`Zb>d85Lc{3Z@BbFYn6O&T3ob&#^3W!4;*gFTHkK zY_yA>k=Orw^_y+yxNB5z7zJ1@yUIPUdDs2tVHxguE3dUJU3&G^VKe8J3E7{S|GsNC U+-o}#7%dD8p00i_>zopr05BiH-v9sr literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/superbwarfare/textures/screens/javelin/red_triangle.png b/src/main/resources/assets/superbwarfare/textures/screens/javelin/red_triangle.png new file mode 100644 index 0000000000000000000000000000000000000000..8ea63052e3e9814f16d676e1b0f6a174e98ba0b4 GIT binary patch literal 732 zcmV<20wev2P)otIj zun>W4)+~6JcL7=j#}NpZ&#@~1z4sDfG6L!HnG7ah7GWm>aS3*U%ew$Wf_r26d%=)N z02g7^IKZlzybI7RxG<8x5OkXca1rK=0?b*v10ZM-90ry@RE--tK@p4#o&(803&yRT z-yqlu6kyBRH50*r;MTMJtzf{~wIYIL&jFUL9jhYf5S)3EKNECVJJv)n<0-(5wOcOq z@>FTRVEKL3c#snnf>FU!LGn+6QER8V5o{C`V8hy_Aq0Jb>n7!|1%1{o4I@}=GQgs> zLsJOa1Sbv3pXfcjsw0?cFu;`c?u8-Pty6y2dgnqB3=1A|%0CE(t#>XQ!CKA$Yu3AZ zLC_<(tRa6X=&|0_8-n>70p_iD^om}dDjijjKhppGLRLNm6MB35>{&2jy<0E@+phv_ zTkjMU!Jy#I$=?YEt#=BJV8sPkvEIc5L6_j0pv!s}Gd{F@B9TZWjQIn_@g{fCux>5@ O0000otIj zun>W4)+~6JcL7=j#}NpZ&#@~1z4sDfG6L!HnG7ah7GWm>aS3*U%ew$Wf_r26d%=)N z02g7^IKZlzybI7RxG<8x5OkXca1rK=0?b*v10ZM-90ry@RE--tK@p4#o&(803&yRT z-yqlu6kyBRH50*r;MTMJtzf{~wIYIL&jFUL9jhYf5S)3EKNECVJJv)n<0-(5wOcOq z@>FTRVEKL3c#snnf>FU!LGn+6QER8V5o{C`V8hy_Aq0Jb>n7!|1%1{o4I@}=GQgs> zLsJOa1Sbv3pXfcjsw0?cFu;`c?u8-Pty6y2dgnqB3=1A|%0CE(t#>XQ!CKA$Yu3AZ zLC_<(tRa6X=&|0_8-n>70p_iD^om}dDjijjKhppGLRLNm6MB35>{&2jy<0E@+phv_ zTkjMU!Jy#I$=?YEt#=BJV8sPkvEIc5L6_j0pv!s}Gd{F@B9TZWjQIn_@g{fCux>5@ O0000