From c56329206df8c48f8a1b9c1f4dbaa1b0ece471cf Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 1 Dec 2022 15:06:36 +0800 Subject: [PATCH] update Adventure Matchscreen --- forge-gui-mobile/src/forge/Forge.java | 3 + forge-gui-mobile/src/forge/Graphics.java | 311 +++++++++++++----- forge-gui-mobile/src/forge/Shaders.java | 36 +- .../src/forge/adventure/scene/ArenaScene.java | 278 +++++++--------- .../src/forge/adventure/scene/DuelScene.java | 11 +- .../src/forge/adventure/scene/GameScene.java | 19 +- .../src/forge/adventure/stage/MapStage.java | 152 ++++----- .../src/forge/adventure/stage/WorldStage.java | 189 +++++------ .../src/forge/adventure/util/Controls.java | 10 +- .../src/forge/screens/TransitionScreen.java | 114 ++++--- forge-gui/res/adventure/Shandalar/ui/vs.png | Bin 6037 -> 68503 bytes 11 files changed, 611 insertions(+), 512 deletions(-) diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index 7cf13bfaf16..a8113190e3b 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -350,6 +350,9 @@ public class Forge implements ApplicationListener { try { FileHandle transitionFile = Config.instance().getFile("ui/transition.png"); FileHandle titleBGFile = Forge.isLandscapeMode() ? Config.instance().getFile("ui/title_bg.png") : Config.instance().getFile("ui/title_bg_portrait.png"); + FileHandle vsIcon = Config.instance().getFile("ui/vs.png"); + if (vsIcon.exists()) + Forge.getAssets().fallback_skins().put(2, new Texture(vsIcon)); if (transitionFile.exists()) Forge.getAssets().fallback_skins().put(1, new Texture(transitionFile)); if (titleBGFile.exists()) diff --git a/forge-gui-mobile/src/forge/Graphics.java b/forge-gui-mobile/src/forge/Graphics.java index 4d7d51241bb..44a1508ee60 100644 --- a/forge-gui-mobile/src/forge/Graphics.java +++ b/forge-gui-mobile/src/forge/Graphics.java @@ -5,6 +5,7 @@ import java.util.Deque; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.*; +import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.glutils.ShaderProgram; @@ -46,6 +47,7 @@ public class Graphics { private final ShaderProgram shaderRipple = new ShaderProgram(Shaders.vertPixelateShader, Shaders.fragRipple); private final ShaderProgram shaderPixelateWarp = new ShaderProgram(Shaders.vertPixelateShader, Shaders.fragPixelateShaderWarp); private final ShaderProgram shaderChromaticAbberation = new ShaderProgram(Shaders.vertPixelateShader, Shaders.fragChromaticAbberation); + private final ShaderProgram shaderHueShift = new ShaderProgram(Shaders.vertPixelateShader, Shaders.fragHueShift); private Texture dummyTexture = null; @@ -92,7 +94,7 @@ public class Graphics { shaderGrayscale.dispose(); shaderUnderwater.dispose(); shaderWarp.dispose(); - if(dummyTexture != null) dummyTexture.dispose(); + if (dummyTexture != null) dummyTexture.dispose(); } public SpriteBatch getBatch() { @@ -102,6 +104,7 @@ public class Graphics { public boolean startClip() { return startClip(0, 0, bounds.width, bounds.height); } + public boolean startClip(float x, float y, float w, float h) { batch.flush(); //must flush batch to prevent other things not rendering @@ -115,22 +118,40 @@ public class Graphics { float maxY = minY; tmp.set(clip.x + clip.width, clip.y, 0); tmp.mul(batch.getTransformMatrix()); - if (tmp.x < minX) { minX = tmp.x; } - else if (tmp.x > maxX) { maxX = tmp.x; } - if (tmp.y < minY) { minY = tmp.y; } - else if (tmp.y > maxY) { maxY = tmp.y; } + if (tmp.x < minX) { + minX = tmp.x; + } else if (tmp.x > maxX) { + maxX = tmp.x; + } + if (tmp.y < minY) { + minY = tmp.y; + } else if (tmp.y > maxY) { + maxY = tmp.y; + } tmp.set(clip.x + clip.width, clip.y + clip.height, 0); tmp.mul(batch.getTransformMatrix()); - if (tmp.x < minX) { minX = tmp.x; } - else if (tmp.x > maxX) { maxX = tmp.x; } - if (tmp.y < minY) { minY = tmp.y; } - else if (tmp.y > maxY) { maxY = tmp.y; } + if (tmp.x < minX) { + minX = tmp.x; + } else if (tmp.x > maxX) { + maxX = tmp.x; + } + if (tmp.y < minY) { + minY = tmp.y; + } else if (tmp.y > maxY) { + maxY = tmp.y; + } tmp.set(clip.x, clip.y + clip.height, 0); tmp.mul(batch.getTransformMatrix()); - if (tmp.x < minX) { minX = tmp.x; } - else if (tmp.x > maxX) { maxX = tmp.x; } - if (tmp.y < minY) { minY = tmp.y; } - else if (tmp.y > maxY) { maxY = tmp.y; } + if (tmp.x < minX) { + minX = tmp.x; + } else if (tmp.x > maxX) { + maxX = tmp.x; + } + if (tmp.y < minY) { + minY = tmp.y; + } else if (tmp.y > maxY) { + maxY = tmp.y; + } clip.set(minX, minY, maxX - minX, maxY - minY); } @@ -140,12 +161,12 @@ public class Graphics { } return true; } + public void endClip() { if (failedClipCount == 0) { batch.flush(); //must flush batch to ensure stuffed rendered during clip respects that clip ScissorStack.popScissors(); - } - else { + } else { failedClipCount--; } } @@ -159,8 +180,7 @@ public class Graphics { bounds = new Rectangle(parentBounds.x + displayObj.getLeft(), parentBounds.y + displayObj.getTop(), displayObj.getWidth(), displayObj.getHeight()); if (!Dtransforms.isEmpty()) { //transform screen position if needed by applying transform matrix to rectangle updateScreenPosForRotation(displayObj); - } - else { + } else { displayObj.screenPos.set(bounds); } @@ -172,8 +192,7 @@ public class Graphics { if (displayObj.getRotate90()) { //use top-right corner of bounds as pivot point startRotateTransform(displayObj.getWidth(), 0, -90); updateScreenPosForRotation(displayObj); - } - else if (displayObj.getRotate180()) { //use center of bounds as pivot point + } else if (displayObj.getRotate180()) { //use center of bounds as pivot point startRotateTransform(displayObj.getWidth() / 2, displayObj.getHeight() / 2, 180); //screen position won't change for this object from a 180 degree rotation } @@ -181,7 +200,7 @@ public class Graphics { displayObj.draw(this); if (displayObj.getRotate90() || displayObj.getRotate180()) { - endTransform(); + endTransform(); } visibleBounds = backup; @@ -201,24 +220,42 @@ public class Graphics { tmp.set(bounds.x + bounds.width, regionHeight - bounds.y, 0); tmp.mul(batch.getTransformMatrix()); tmp.y = regionHeight - tmp.y; - if (tmp.x < minX) { minX = tmp.x; } - else if (tmp.x > maxX) { maxX = tmp.x; } - if (tmp.y < minY) { minY = tmp.y; } - else if (tmp.y > maxY) { maxY = tmp.y; } + if (tmp.x < minX) { + minX = tmp.x; + } else if (tmp.x > maxX) { + maxX = tmp.x; + } + if (tmp.y < minY) { + minY = tmp.y; + } else if (tmp.y > maxY) { + maxY = tmp.y; + } tmp.set(bounds.x + bounds.width, regionHeight - bounds.y - bounds.height, 0); tmp.mul(batch.getTransformMatrix()); tmp.y = regionHeight - tmp.y; - if (tmp.x < minX) { minX = tmp.x; } - else if (tmp.x > maxX) { maxX = tmp.x; } - if (tmp.y < minY) { minY = tmp.y; } - else if (tmp.y > maxY) { maxY = tmp.y; } + if (tmp.x < minX) { + minX = tmp.x; + } else if (tmp.x > maxX) { + maxX = tmp.x; + } + if (tmp.y < minY) { + minY = tmp.y; + } else if (tmp.y > maxY) { + maxY = tmp.y; + } tmp.set(bounds.x, regionHeight - bounds.y - bounds.height, 0); tmp.mul(batch.getTransformMatrix()); tmp.y = regionHeight - tmp.y; - if (tmp.x < minX) { minX = tmp.x; } - else if (tmp.x > maxX) { maxX = tmp.x; } - if (tmp.y < minY) { minY = tmp.y; } - else if (tmp.y > maxY) { maxY = tmp.y; } + if (tmp.x < minX) { + minX = tmp.x; + } else if (tmp.x > maxX) { + maxX = tmp.x; + } + if (tmp.y < minY) { + minY = tmp.y; + } else if (tmp.y > maxY) { + maxY = tmp.y; + } displayObj.screenPos.set(minX, minY, maxX - minX, maxY - minY); } @@ -226,6 +263,7 @@ public class Graphics { public void drawLine(float thickness, FSkinColor skinColor, float x1, float y1, float x2, float y2) { drawLine(thickness, skinColor.getColor(), x1, y1, x2, y2); } + public void drawLine(float thickness, Color color, float x1, float y1, float x2, float y2) { batch.end(); //must pause batch while rendering shapes @@ -264,16 +302,17 @@ public class Graphics { public void drawLineArrow(float arrowThickness, FSkinColor skinColor, float x1, float y1, float x2, float y2) { fillCircle(skinColor.getColor(), x2, y2, arrowThickness); drawLineArrow(arrowThickness, skinColor.getColor(), x1, y1, x2, y2); - fillCircle(Color.WHITE, x2, y2, arrowThickness/2); - drawLine(arrowThickness/3, Color.WHITE, x1, y1, x2, y2); + fillCircle(Color.WHITE, x2, y2, arrowThickness / 2); + drawLine(arrowThickness / 3, Color.WHITE, x1, y1, x2, y2); } + public void drawLineArrow(float thickness, Color color, float x1, float y1, float x2, float y2) { batch.end(); //must pause batch while rendering shapes float angle = new Vector2(x1 - x2, y1 - y2).angleRad(); - float arrowHeadRotation = (float)(Math.PI * 0.8f); - Vector2 arrowCorner3 = new Vector2(x2 + (thickness/3) * (float)Math.cos(angle + arrowHeadRotation), y2 + (thickness/3) * (float)Math.sin(angle + arrowHeadRotation)); - Vector2 arrowCorner4 = new Vector2(x2 + (thickness/3) * (float)Math.cos(angle - arrowHeadRotation), y2 + (thickness/3) * (float)Math.sin(angle - arrowHeadRotation)); + float arrowHeadRotation = (float) (Math.PI * 0.8f); + Vector2 arrowCorner3 = new Vector2(x2 + (thickness / 3) * (float) Math.cos(angle + arrowHeadRotation), y2 + (thickness / 3) * (float) Math.sin(angle + arrowHeadRotation)); + Vector2 arrowCorner4 = new Vector2(x2 + (thickness / 3) * (float) Math.cos(angle - arrowHeadRotation), y2 + (thickness / 3) * (float) Math.sin(angle - arrowHeadRotation)); if (thickness > 1) { Gdx.gl.glLineWidth(thickness); @@ -306,9 +345,11 @@ public class Graphics { batch.begin(); } + public void drawArrow(float borderThickness, float arrowThickness, float arrowSize, FSkinColor skinColor, float x1, float y1, float x2, float y2) { drawArrow(borderThickness, arrowThickness, arrowSize, skinColor.getColor(), x1, y1, x2, y2); } + public void drawArrow(float borderThickness, float arrowThickness, float arrowSize, Color color, float x1, float y1, float x2, float y2) { batch.end(); //must pause batch while rendering shapes @@ -319,31 +360,31 @@ public class Graphics { Gdx.gl.glEnable(GL_LINE_SMOOTH); float angle = new Vector2(x2 - x1, y2 - y1).angleRad(); - float perpRotation = (float)(Math.PI * 0.5f); - float arrowHeadRotation = (float)(Math.PI * 0.8f); - float arrowTipAngle = (float)(Math.PI - arrowHeadRotation); + float perpRotation = (float) (Math.PI * 0.5f); + float arrowHeadRotation = (float) (Math.PI * 0.8f); + float arrowTipAngle = (float) (Math.PI - arrowHeadRotation); float halfThickness = arrowThickness / 2; int index = 0; float[] vertices = new float[14]; - Vector2 arrowCorner1 = new Vector2(x2 + arrowSize * (float)Math.cos(angle + arrowHeadRotation), y2 + arrowSize * (float)Math.sin(angle + arrowHeadRotation)); - Vector2 arrowCorner2 = new Vector2(x2 + arrowSize * (float)Math.cos(angle - arrowHeadRotation), y2 + arrowSize * (float)Math.sin(angle - arrowHeadRotation)); + Vector2 arrowCorner1 = new Vector2(x2 + arrowSize * (float) Math.cos(angle + arrowHeadRotation), y2 + arrowSize * (float) Math.sin(angle + arrowHeadRotation)); + Vector2 arrowCorner2 = new Vector2(x2 + arrowSize * (float) Math.cos(angle - arrowHeadRotation), y2 + arrowSize * (float) Math.sin(angle - arrowHeadRotation)); float arrowCornerLen = (arrowCorner1.dst(arrowCorner2) - arrowThickness) / 2; - float arrowHeadLen = arrowSize * (float)Math.cos(arrowTipAngle); + float arrowHeadLen = arrowSize * (float) Math.cos(arrowTipAngle); index = addVertex(arrowCorner1.x, arrowCorner1.y, vertices, index); index = addVertex(x2, y2, vertices, index); index = addVertex(arrowCorner2.x, arrowCorner2.y, vertices, index); - index = addVertex(arrowCorner2.x + arrowCornerLen * (float)Math.cos(angle + perpRotation), arrowCorner2.y + arrowCornerLen * (float)Math.sin(angle + perpRotation), vertices, index); - index = addVertex(x1 + halfThickness * (float)Math.cos(angle - perpRotation), y1 + halfThickness * (float)Math.sin(angle - perpRotation), vertices, index); - index = addVertex(x1 + halfThickness * (float)Math.cos(angle + perpRotation), y1 + halfThickness * (float)Math.sin(angle + perpRotation), vertices, index); - index = addVertex(arrowCorner1.x + arrowCornerLen * (float)Math.cos(angle - perpRotation), arrowCorner1.y + arrowCornerLen * (float)Math.sin(angle - perpRotation), vertices, index); + index = addVertex(arrowCorner2.x + arrowCornerLen * (float) Math.cos(angle + perpRotation), arrowCorner2.y + arrowCornerLen * (float) Math.sin(angle + perpRotation), vertices, index); + index = addVertex(x1 + halfThickness * (float) Math.cos(angle - perpRotation), y1 + halfThickness * (float) Math.sin(angle - perpRotation), vertices, index); + index = addVertex(x1 + halfThickness * (float) Math.cos(angle + perpRotation), y1 + halfThickness * (float) Math.sin(angle + perpRotation), vertices, index); + index = addVertex(arrowCorner1.x + arrowCornerLen * (float) Math.cos(angle - perpRotation), arrowCorner1.y + arrowCornerLen * (float) Math.sin(angle - perpRotation), vertices, index); //draw arrow tail startShape(ShapeType.Filled); shapeRenderer.setColor(color); shapeRenderer.rectLine(adjustX(x1), adjustY(y1, 0), - adjustX(x2 - arrowHeadLen * (float)Math.cos(angle)), //shorten tail to make room for arrow head - adjustY(y2 - arrowHeadLen * (float)Math.sin(angle), 0), arrowThickness); + adjustX(x2 - arrowHeadLen * (float) Math.cos(angle)), //shorten tail to make room for arrow head + adjustY(y2 - arrowHeadLen * (float) Math.sin(angle), 0), arrowThickness); //draw arrow head shapeRenderer.triangle(vertices[0], vertices[1], vertices[2], vertices[3], vertices[4], vertices[5]); @@ -381,6 +422,7 @@ public class Graphics { public void drawRoundRect(float thickness, FSkinColor skinColor, float x, float y, float w, float h, float cornerRadius) { drawRoundRect(thickness, skinColor.getColor(), x, y, w, h, cornerRadius); } + public void drawRoundRect(float thickness, Color color, float x, float y, float w, float h, float cornerRadius) { batch.end(); //must pause batch while rendering shapes @@ -408,8 +450,8 @@ public class Graphics { shapeRenderer.arc(adjustX(x) + w - cornerRadius, adjustY(y + cornerRadius, 0), cornerRadius, 0f, 90f); shapeRenderer.arc(adjustX(x) + w - cornerRadius, adjustY(y + h - cornerRadius, 0), cornerRadius, 270, 90f); shapeRenderer.arc(adjustX(x) + cornerRadius, adjustY(y + h - cornerRadius, 0), cornerRadius, 180, 90f); - shapeRenderer.rect(adjustX(x), adjustY(y+cornerRadius, h-cornerRadius*2), w, h-cornerRadius*2); - shapeRenderer.rect(adjustX(x+cornerRadius), adjustY(y, h), w-cornerRadius*2, h); + shapeRenderer.rect(adjustX(x), adjustY(y + cornerRadius, h - cornerRadius * 2), w, h - cornerRadius * 2); + shapeRenderer.rect(adjustX(x + cornerRadius), adjustY(y, h), w - cornerRadius * 2, h); endShape(); @@ -429,6 +471,7 @@ public class Graphics { public void fillRoundRect(FSkinColor skinColor, float x, float y, float w, float h, float cornerRadius) { fillRoundRect(skinColor.getColor(), x, y, w, h, cornerRadius); } + public void fillRoundRect(Color color, float x, float y, float w, float h, float cornerRadius) { batch.end(); //must pause batch while rendering shapes if (alphaComposite < 1) { @@ -443,8 +486,8 @@ public class Graphics { shapeRenderer.arc(adjustX(x) + w - cornerRadius, adjustY(y + cornerRadius, 0), cornerRadius, 0f, 90f); shapeRenderer.arc(adjustX(x) + w - cornerRadius, adjustY(y + h - cornerRadius, 0), cornerRadius, 270, 90f); shapeRenderer.arc(adjustX(x) + cornerRadius, adjustY(y + h - cornerRadius, 0), cornerRadius, 180, 90f); - shapeRenderer.rect(adjustX(x), adjustY(y+cornerRadius, h-cornerRadius*2), w, h-cornerRadius*2); - shapeRenderer.rect(adjustX(x+cornerRadius), adjustY(y, h), w-cornerRadius*2, h); + shapeRenderer.rect(adjustX(x), adjustY(y + cornerRadius, h - cornerRadius * 2), w, h - cornerRadius * 2); + shapeRenderer.rect(adjustX(x + cornerRadius), adjustY(y, h), w - cornerRadius * 2, h); endShape(); if (color.a < 1) { Gdx.gl.glDisable(GL_BLEND); @@ -455,6 +498,7 @@ public class Graphics { public void drawRect(float thickness, FSkinColor skinColor, float x, float y, float w, float h) { drawRect(thickness, skinColor.getColor(), x, y, w, h); } + public void drawRect(float thickness, Color color, float x, float y, float w, float h) { batch.end(); //must pause batch while rendering shapes @@ -480,16 +524,18 @@ public class Graphics { batch.begin(); } + public void drawRectLines(float thickness, Color color, float x, float y, float w, float h) { - drawLine(thickness, color, x, y, x+w, y); - drawLine(thickness, color, x+thickness/2f, y+thickness/2f, x+thickness/2f, y+h-thickness/2f); - drawLine(thickness, color, x, y+h, x+w, y+h); - drawLine(thickness, color, x+w-thickness/2f, y+thickness/2f, x+w-thickness/2f, y+h-thickness/2f); + drawLine(thickness, color, x, y, x + w, y); + drawLine(thickness, color, x + thickness / 2f, y + thickness / 2f, x + thickness / 2f, y + h - thickness / 2f); + drawLine(thickness, color, x, y + h, x + w, y + h); + drawLine(thickness, color, x + w - thickness / 2f, y + thickness / 2f, x + w - thickness / 2f, y + h - thickness / 2f); } public void fillRect(FSkinColor skinColor, float x, float y, float w, float h) { fillRect(skinColor.getColor(), x, y, w, h); } + public void fillRect(Color color, float x, float y, float w, float h) { batch.end(); //must pause batch while rendering shapes @@ -515,6 +561,7 @@ public class Graphics { public void drawCircle(float thickness, FSkinColor skinColor, float x, float y, float radius) { drawCircle(thickness, skinColor.getColor(), x, y, radius); } + public void drawCircle(float thickness, Color color, float x, float y, float radius) { batch.end(); //must pause batch while rendering shapes @@ -544,6 +591,7 @@ public class Graphics { public void fillCircle(FSkinColor skinColor, float x, float y, float radius) { fillCircle(skinColor.getColor(), x, y, radius); } + public void fillCircle(Color color, float x, float y, float radius) { batch.end(); //must pause batch while rendering shapes @@ -569,6 +617,7 @@ public class Graphics { public void fillTriangle(FSkinColor skinColor, float x1, float y1, float x2, float y2, float x3, float y3) { fillTriangle(skinColor.getColor(), x1, y1, x2, y2, x3, y3); } + public void fillTriangle(Color color, float x1, float y1, float x2, float y2, float x3, float y3) { batch.end(); //must pause batch while rendering shapes @@ -594,12 +643,15 @@ public class Graphics { public void fillGradientRect(FSkinColor skinColor1, FSkinColor skinColor2, boolean vertical, float x, float y, float w, float h) { fillGradientRect(skinColor1.getColor(), skinColor2.getColor(), vertical, x, y, w, h); } + public void fillGradientRect(FSkinColor skinColor1, Color color2, boolean vertical, float x, float y, float w, float h) { fillGradientRect(skinColor1.getColor(), color2, vertical, x, y, w, h); } + public void fillGradientRect(Color color1, FSkinColor skinColor2, boolean vertical, float x, float y, float w, float h) { fillGradientRect(color1, skinColor2.getColor(), vertical, x, y, w, h); } + public void fillGradientRect(Color color1, Color color2, boolean vertical, float x, float y, float w, float h) { batch.end(); //must pause batch while rendering shapes @@ -654,17 +706,21 @@ public class Graphics { alphaComposite = alphaComposite0; batch.setColor(new Color(1, 1, 1, alphaComposite)); } + public void resetAlphaComposite() { alphaComposite = 1; batch.setColor(Color.WHITE); } - public float getfloatAlphaComposite() { return alphaComposite; } + + public float getfloatAlphaComposite() { + return alphaComposite; + } public void drawBorderImage(FImage image, Color borderColor, Color tintColor, float x, float y, float w, float h, boolean tint) { float oldalpha = alphaComposite; - if(tint && !tintColor.equals(borderColor)){ - drawRoundRect(2f, borderLining(borderColor.toString()), x, y, w, h, (h-w)/12); - fillRoundRect(tintColor, x, y, w, h, (h-w)/12); + if (tint && !tintColor.equals(borderColor)) { + drawRoundRect(2f, borderLining(borderColor.toString()), x, y, w, h, (h - w) / 12); + fillRoundRect(tintColor, x, y, w, h, (h - w) / 12); } else { if (image != null) { image.draw(this, x, y, w, h); @@ -673,17 +729,20 @@ public class Graphics { } setAlphaComposite(oldalpha); } + public void drawborderImage(Color borderColor, float x, float y, float w, float h) { float oldalpha = alphaComposite; - fillRoundRect(borderColor, x, y, w, h, (h-w)/12); + fillRoundRect(borderColor, x, y, w, h, (h - w) / 12); setAlphaComposite(oldalpha); } + public void drawImage(FImage image, Color borderColor, float x, float y, float w, float h) { if (image == null) return; image.draw(this, x, y, w, h); - fillRoundRect(borderColor, x+1, y+1, w-1.5f, h-1.5f, (h-w)/10);//used by zoom let some edges show... + fillRoundRect(borderColor, x + 1, y + 1, w - 1.5f, h - 1.5f, (h - w) / 10);//used by zoom let some edges show... } + public void drawAvatarImage(FImage image, float x, float y, float w, float h, boolean drawGrayscale) { if (image == null) return; @@ -704,6 +763,7 @@ public class Graphics { batch.begin(); } } + public void drawCardImage(FImage image, TextureRegion damage_overlay, float x, float y, float w, float h, boolean drawGrayscale, boolean damaged) { if (image == null) return; @@ -726,6 +786,7 @@ public class Graphics { batch.begin(); } } + public void drawCardImage(Texture image, TextureRegion damage_overlay, float x, float y, float w, float h, boolean drawGrayscale, boolean damaged) { if (!drawGrayscale) { batch.draw(image, adjustX(x), adjustY(y, h), w, h); @@ -746,6 +807,7 @@ public class Graphics { batch.begin(); } } + public void drawCardImage(TextureRegion image, TextureRegion damage_overlay, float x, float y, float w, float h, boolean drawGrayscale, boolean damaged) { if (image != null) { if (!drawGrayscale) { @@ -768,6 +830,7 @@ public class Graphics { } } } + public void drawGrayTransitionImage(FImage image, float x, float y, float w, float h, float percentage) { if (image == null) return; @@ -784,6 +847,7 @@ public class Graphics { batch.setShader(null); batch.begin(); } + public void drawGrayTransitionImage(Texture image, float x, float y, float w, float h, boolean withDarkOverlay, float percentage) { batch.end(); shaderGrayscale.bind(); @@ -798,6 +862,7 @@ public class Graphics { batch.setShader(null); batch.begin(); } + public void drawGrayTransitionImage(TextureRegion image, float x, float y, float w, float h, boolean withDarkOverlay, float percentage) { batch.end(); shaderGrayscale.bind(); @@ -812,6 +877,47 @@ public class Graphics { batch.setShader(null); batch.begin(); } + + public void drawHueShift(Texture image, float x, float y, float w, float h, Float time) { + if (image == null) + return; + if (time != null) { + batch.end(); + shaderHueShift.bind(); + shaderHueShift.setUniformf("u_time", time); + batch.setShader(shaderHueShift); + batch.begin(); + //draw + batch.draw(image, x, y, w, h); + //reset + batch.end(); + batch.setShader(null); + batch.begin(); + } else { + drawImage(image, x, y, w, h); + } + } + + public void drawHueShift(TextureRegion image, float x, float y, float w, float h, Float time) { + if (image == null) + return; + if (time != null) { + batch.end(); + shaderHueShift.bind(); + shaderHueShift.setUniformf("u_time", time); + batch.setShader(shaderHueShift); + batch.begin(); + //draw + batch.draw(image, x, y, w, h); + //reset + batch.end(); + batch.setShader(null); + batch.begin(); + } else { + drawImage(image, x, y, w, h); + } + } + public void drawChromatic(TextureRegion image, float x, float y, float w, float h, Float time) { if (image == null) return; @@ -831,6 +937,7 @@ public class Graphics { drawImage(image, x, y, w, h); } } + public void drawRipple(FImage image, float x, float y, float w, float h, Float amount, boolean flipY) { if (image == null) return; @@ -852,13 +959,14 @@ public class Graphics { drawImage(image, x, y, w, h); } } + public void drawPixelated(FImage image, float x, float y, float w, float h, Float amount, boolean flipY) { if (image == null) return; if (amount != null) { batch.end(); shaderPixelate.bind(); - shaderPixelate.setUniformf("u_resolution", Forge.isLandscapeMode() ? w : h , Forge.isLandscapeMode() ? h : w); + shaderPixelate.setUniformf("u_resolution", Forge.isLandscapeMode() ? w : h, Forge.isLandscapeMode() ? h : w); shaderPixelate.setUniformf("u_cellSize", amount); shaderPixelate.setUniformf("u_yflip", flipY ? 1f : 0f); shaderPixelate.setUniformf("u_bias", 0.7f); @@ -874,13 +982,14 @@ public class Graphics { drawImage(image, x, y, w, h); } } + public void drawPixelated(TextureRegion image, float x, float y, float w, float h, Float amount, boolean flipY) { if (image == null) return; if (amount != null) { batch.end(); shaderPixelate.bind(); - shaderPixelate.setUniformf("u_resolution", Forge.isLandscapeMode() ? w : h , Forge.isLandscapeMode() ? h : w); + shaderPixelate.setUniformf("u_resolution", Forge.isLandscapeMode() ? w : h, Forge.isLandscapeMode() ? h : w); shaderPixelate.setUniformf("u_cellSize", amount); shaderPixelate.setUniformf("u_yflip", flipY ? 1 : 0); shaderPixelate.setUniformf("u_bias", 0.6f); @@ -896,6 +1005,7 @@ public class Graphics { drawImage(image, x, y, w, h); } } + public void drawPixelatedWarp(TextureRegion image, float x, float y, float w, float h, float amount) { if (image == null) return; @@ -904,7 +1014,7 @@ public class Graphics { shaderPixelateWarp.bind(); shaderPixelateWarp.setUniformf("u_resolution", image.getRegionWidth(), image.getRegionHeight()); shaderPixelateWarp.setUniformf("u_cellSize", amount); - shaderPixelateWarp.setUniformf("u_amount", 0.2f*amount); + shaderPixelateWarp.setUniformf("u_amount", 0.2f * amount); shaderPixelateWarp.setUniformf("u_speed", 0.5f); shaderPixelateWarp.setUniformf("u_time", 0.8f); batch.setShader(shaderPixelateWarp); @@ -919,6 +1029,7 @@ public class Graphics { drawImage(image, x, y, w, h); } } + public void drawWarpImage(Texture image, float x, float y, float w, float h, float time) { batch.end(); shaderWarp.bind(); @@ -934,6 +1045,7 @@ public class Graphics { batch.setShader(null); batch.begin(); } + public void drawWarpImage(TextureRegion image, float x, float y, float w, float h, float time) { batch.end(); shaderWarp.bind(); @@ -949,6 +1061,7 @@ public class Graphics { batch.setShader(null); batch.begin(); } + public void drawWarpImage(FImage image, float x, float y, float w, float h, float time) { if (image == null) return; @@ -966,13 +1079,14 @@ public class Graphics { batch.setShader(null); batch.begin(); } + public void drawUnderWaterImage(FImage image, float x, float y, float w, float h, float time) { if (image == null) return; batch.end(); shaderUnderwater.bind(); - shaderUnderwater.setUniformf("u_amount", 10f*time); - shaderUnderwater.setUniformf("u_speed", 0.5f*time); + shaderUnderwater.setUniformf("u_amount", 10f * time); + shaderUnderwater.setUniformf("u_speed", 0.5f * time); shaderUnderwater.setUniformf("u_time", time); shaderUnderwater.setUniformf("u_bias", 0.7f); batch.setShader(shaderUnderwater); @@ -984,6 +1098,7 @@ public class Graphics { batch.setShader(null); batch.begin(); } + public void drawNightDay(FImage image, float x, float y, float w, float h, Float time) { if (image == null) return; @@ -1003,6 +1118,7 @@ public class Graphics { drawImage(image, x, y, w, h); } } + public void drawUnderWaterImage(TextureRegion image, float x, float y, float w, float h, float time) { batch.end(); shaderUnderwater.bind(); @@ -1018,32 +1134,37 @@ public class Graphics { batch.setShader(null); batch.begin(); } + public void drawImage(FImage image, float x, float y, float w, float h) { drawImage(image, x, y, w, h, false); } + public void drawImage(FImage image, float x, float y, float w, float h, boolean withDarkOverlay) { if (image == null) return; image.draw(this, x, y, w, h); - if(withDarkOverlay){ + if (withDarkOverlay) { float oldalpha = alphaComposite; setAlphaComposite(0.4f); fillRect(Color.BLACK, x, y, w, h); setAlphaComposite(oldalpha); } } + public void drawImage(Texture image, float x, float y, float w, float h) { if (image != null) batch.draw(image, adjustX(x), adjustY(y, h), w, h); } + public void drawImage(TextureRegion image, float x, float y, float w, float h) { if (image != null) batch.draw(image, adjustX(x), adjustY(y, h), w, h); } + public void drawImage(TextureRegion image, TextureRegion glowImageReference, float x, float y, float w, float h, Color glowColor, boolean selected) { if (image == null || glowImageReference == null) return; - //1st image is the image on top of the shader, 2nd image is for the outline reference for the shader glow... + //1st image is the image on top of the shader, 2nd image is for the outline reference for the shader glow... // if the 1st image don't have transparency in the middle (only on the sides, top and bottom, use the 1st image as outline reference... if (!selected) { batch.draw(image, adjustX(x), adjustY(y, h), w, h); @@ -1065,12 +1186,13 @@ public class Graphics { batch.draw(image, adjustX(x), adjustY(y, h), w, h); } } + public void drawDeckBox(FImage cardArt, float scale, TextureRegion image, TextureRegion glowImageReference, float x, float y, float w, float h, Color glowColor, boolean selected) { if (image == null || glowImageReference == null) return; - float yBox = y-(h*0.25f); + float yBox = y - (h * 0.25f); if (!selected) { - cardArt.draw(this,x+((w-w*scale)/2), y+((h-h*scale)/3f), w*scale, h*scale/1.85f); + cardArt.draw(this, x + ((w - w * scale) / 2), y + ((h - h * scale) / 3f), w * scale, h * scale / 1.85f); batch.draw(image, adjustX(x), adjustY(yBox, h), w, h); } else { batch.end(); @@ -1087,7 +1209,7 @@ public class Graphics { batch.setShader(null); batch.begin(); //cardart - cardArt.draw(this,x+((w-w*scale)/2), y+((h-h*scale)/3f), w*scale, h*scale/1.85f); + cardArt.draw(this, x + ((w - w * scale) / 2), y + ((h - h * scale) / 3f), w * scale, h * scale / 1.85f); //deckbox batch.draw(image, adjustX(x), adjustY(yBox, h), w, h); } @@ -1097,8 +1219,8 @@ public class Graphics { if (image == null) return; if (startClip(x, y, w, h)) { //only render if clip successful, otherwise it will escape bounds - int tilesW = (int)(w / image.getWidth()) + 1; - int tilesH = (int)(h / image.getHeight()) + 1; + int tilesW = (int) (w / image.getWidth()) + 1; + int tilesH = (int) (h / image.getHeight()) + 1; batch.draw(image, adjustX(x), adjustY(y, h), image.getWidth() * tilesW, image.getHeight() * tilesH, @@ -1136,7 +1258,7 @@ public class Graphics { shapeRenderer.setTransformMatrix(batch.getTransformMatrix().idt()); Dtransforms.removeFirst(); transformCount--; - if(transformCount != Dtransforms.size()) { + if (transformCount != Dtransforms.size()) { System.err.println(String.format("Stack count: %d, transformCount: %d", Dtransforms.size(), transformCount)); transformCount = 0; Dtransforms.clear(); @@ -1149,16 +1271,26 @@ public class Graphics { public void drawRotatedImage(Texture image, float x, float y, float w, float h, float originX, float originY, float rotation) { drawRotatedImage(image, x, y, w, h, originX, originY, 0, 0, image.getWidth(), image.getHeight(), rotation); } + public void drawRotatedImage(TextureRegion image, float x, float y, float w, float h, float originX, float originY, float rotation) { drawRotatedImage(image.getTexture(), x, y, w, h, originX, originY, image.getRegionX(), image.getRegionY(), image.getRegionWidth(), image.getRegionHeight(), rotation); } + public void drawRotatedImage(Texture image, float x, float y, float w, float h, float originX, float originY, int srcX, int srcY, int srcWidth, int srcHeight, float rotation) { batch.draw(image, adjustX(x), adjustY(y, h), originX - x, h - (originY - y), w, h, 1, 1, rotation, srcX, srcY, srcWidth, srcHeight, false, false); } + public void drawText(String text, BitmapFont bitmapFont, float x, float y, Color color, float alpha) { + if (text == null || bitmapFont == null || text.isEmpty()) + return; + bitmapFont.setColor(color.r, color.g, color.b, alpha); + bitmapFont.draw(batch, text, x, y); + } + public void drawText(String text, FSkinFont font, FSkinColor skinColor, float x, float y, float w, float h, boolean wrap, int horzAlignment, boolean centerVertically) { drawText(text, font, skinColor.getColor(), x, y, w, h, wrap, horzAlignment, centerVertically); } + public void drawText(String text, FSkinFont font, Color color, float x, float y, float w, float h, boolean wrap, int horzAlignment, boolean centerVertically) { try { if (text == null) @@ -1173,8 +1305,7 @@ public class Graphics { TextBounds textBounds; if (wrap) { textBounds = font.getWrappedBounds(text, w); - } - else { + } else { textBounds = font.getMultiLineBounds(text); } @@ -1185,12 +1316,10 @@ public class Graphics { font = font.shrink(); if (wrap) { textBounds = font.getWrappedBounds(text, w); - } - else { + } else { textBounds = font.getMultiLineBounds(text); } - } - else { + } else { needClip = true; break; } @@ -1224,6 +1353,7 @@ public class Graphics { public void drawOutlinedText(String text, FSkinFont skinFont, Color textColor, Color outlineColor, float x, float y, float w, float h, boolean wrap, int horzAlignment, boolean centerVertically) { drawOutlinedText(text, skinFont, textColor, outlineColor, x, y, w, h, wrap, horzAlignment, centerVertically, false); } + public void drawOutlinedText(String text, FSkinFont skinFont, Color textColor, Color outlineColor, float x, float y, float w, float h, boolean wrap, int horzAlignment, boolean centerVertically, boolean shadow) { if (shadow) { float oldAlpha = alphaComposite; @@ -1250,20 +1380,21 @@ public class Graphics { public float adjustY(float y, float height) { return regionHeight - y - bounds.y - height; //flip y-axis } - public Color borderLining(String c){ + + public Color borderLining(String c) { if (c == null || c == "") return Color.valueOf("#fffffd"); - int c_r = Integer.parseInt(c.substring(0,2),16); - int c_g = Integer.parseInt(c.substring(2,4),16); - int c_b = Integer.parseInt(c.substring(4,6),16); + int c_r = Integer.parseInt(c.substring(0, 2), 16); + int c_g = Integer.parseInt(c.substring(2, 4), 16); + int c_b = Integer.parseInt(c.substring(4, 6), 16); int brightness = ((c_r * 299) + (c_g * 587) + (c_b * 114)) / 1000; - return brightness > 155 ? Color.valueOf("#171717") : Color.valueOf("#fffffd"); + return brightness > 155 ? Color.valueOf("#171717") : Color.valueOf("#fffffd"); } - public Texture getDummyTexture(){ - if (dummyTexture == null){ + public Texture getDummyTexture() { + if (dummyTexture == null) { Pixmap P = new Pixmap(1, 1, Pixmap.Format.RGBA8888); - P.setColor(1f,1f,1f,1f); + P.setColor(1f, 1f, 1f, 1f); P.drawPixel(0, 0); dummyTexture = new Texture(P); P.dispose(); diff --git a/forge-gui-mobile/src/forge/Shaders.java b/forge-gui-mobile/src/forge/Shaders.java index 18d75c22913..f86f94fedda 100644 --- a/forge-gui-mobile/src/forge/Shaders.java +++ b/forge-gui-mobile/src/forge/Shaders.java @@ -25,9 +25,9 @@ public class Shaders { + " gl_Position = u_projTrans * " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" + "}\n"; /* - * Test Pixelate shader - * - **/ + * Test Pixelate shader + * + **/ public static final String vertPixelateShader = "attribute vec4 a_position;\n" + "attribute vec4 a_color;\n" + "attribute vec2 a_texCoord0;\n" + @@ -42,7 +42,31 @@ public class Shaders { " v_texCoords = a_texCoord0;\n" + " gl_Position = u_projTrans * a_position;\n" + "}"; - public static final String fragRipple="#ifdef GL_ES\n" + + public static final String fragHueShift = "#ifdef GL_ES\n" + + "#define LOWP lowp\n" + + "precision mediump float;\n" + + "#else\n" + + "#define LOWP \n" + + "#endif\n" + + "varying vec2 v_texCoords;\n" + + "uniform sampler2D u_texture;\n" + + "uniform float u_time;\n" + + "\n" + + "vec3 hs(vec3 c, float s) {\n" + + " vec3 m=vec3(cos(s),s=sin(s)*.5774,-s);\n" + + " return c*mat3(m+=(1.-m.x)/3.,m.zxy,m.yzx);\n" + + "}\n" + + "\n" + + "void main() {\n" + + "\tvec2 uv = v_texCoords;\n" + + " vec4 orig = texture2D(u_texture, uv);\n" + + " vec3 col = texture2D(u_texture, uv).rgb;\n" + + " vec4 col2 = vec4(hs(col, u_time), 1.);\n" + + " //multiply the original texture alpha to render only opaque shifted colors \n" + + " col2.a *= orig.a;\n" + + " gl_FragColor = col2;\n" + + "}"; + public static final String fragRipple = "#ifdef GL_ES\n" + "#define LOWP lowp\n" + "precision mediump float;\n" + "#else\n" + @@ -74,7 +98,7 @@ public class Shaders { "\t\tcolor = texture2D(u_texture, coord);\n" + "\tgl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), vec4(color.rgba * dist), u_bias);\n" + "}"; - public static final String fragChromaticAbberation="#ifdef GL_ES\n" + + public static final String fragChromaticAbberation = "#ifdef GL_ES\n" + "#define LOWP lowp\n" + "precision mediump float;\n" + "#else\n" + @@ -1135,6 +1159,7 @@ public class Shaders { * {@link com.github.tommyettinger.colorful.rgb.ColorTools#rgb(float, float, float, float)}. *
* Meant for use with {@link #vertexShader}. + * * @see #fragmentShaderConfigurableContrast a per-sprite-configurable version of this */ public static String fragmentShaderFlatLightness = @@ -1176,6 +1201,7 @@ public class Shaders { * the specific way this uses them. *
* Meant for use with {@link #vertexShader}. + * * @see #fragmentShaderFlatLightness if you only need one contrast setting and still want to set color tints */ public static String fragmentShaderConfigurableContrast = diff --git a/forge-gui-mobile/src/forge/adventure/scene/ArenaScene.java b/forge-gui-mobile/src/forge/adventure/scene/ArenaScene.java index 7eb9a0c8d29..6169a11137f 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/ArenaScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/ArenaScene.java @@ -1,10 +1,7 @@ package forge.adventure.scene; -import com.badlogic.gdx.files.FileHandle; -import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Group; import com.badlogic.gdx.scenes.scene2d.ui.*; @@ -15,7 +12,6 @@ import forge.Forge; import forge.adventure.character.EnemySprite; import forge.adventure.data.ArenaData; import forge.adventure.data.WorldData; -import forge.adventure.player.AdventurePlayer; import forge.adventure.stage.GameHUD; import forge.adventure.stage.IAfterMatch; import forge.adventure.stage.WorldStage; @@ -29,16 +25,14 @@ import java.util.Random; * Displays the rewards of a fight or a treasure */ public class ArenaScene extends UIScene implements IAfterMatch { - private FileHandle vsIcon = Config.instance().getFile("ui/vs.png"); - private TextureRegion vsTextureRegion = vsIcon.exists() ? new TextureRegion(new Texture(vsIcon)) : null; private static ArenaScene object; private final float gridSize; private ArenaData arenaData; private final TextraButton startButton; public static ArenaScene instance() { - if(object==null) - object=new ArenaScene(); + if (object == null) + object = new ArenaScene(); return object; } @@ -46,7 +40,7 @@ public class ArenaScene extends UIScene implements IAfterMatch { private final TextraLabel goldLabel; private final Group arenaPlane; - private final Random rand=new Random(); + private final Random rand = new Random(); final Sprite fighterSpot; final Sprite lostOverlay; @@ -58,49 +52,45 @@ public class ArenaScene extends UIScene implements IAfterMatch { final Sprite edgeM; final Sprite edgeWin; final Sprite edgeWinM; - boolean arenaStarted=false; + boolean arenaStarted = false; + private ArenaScene() { super(Forge.isLandscapeMode() ? "ui/arena.json" : "ui/arena_portrait.json"); + TextureAtlas atlas = Config.instance().getAtlas(Paths.ARENA_ATLAS); + fighterSpot = atlas.createSprite("Spot"); + lostOverlay = atlas.createSprite("Lost"); + up = atlas.createSprite("Up"); + upWin = atlas.createSprite("UpWin"); + side = atlas.createSprite("Side"); + sideWin = atlas.createSprite("SideWin"); + edge = atlas.createSprite("Edge"); + edgeM = atlas.createSprite("Edge"); + edgeM.setFlip(true, false); + edgeWin = atlas.createSprite("EdgeWin"); + edgeWinM = atlas.createSprite("EdgeWin"); + edgeWinM.setFlip(true, false); + gridSize = fighterSpot.getRegionWidth(); - - - TextureAtlas atlas=Config.instance().getAtlas(Paths.ARENA_ATLAS); - fighterSpot=atlas.createSprite("Spot"); - lostOverlay=atlas.createSprite("Lost"); - up=atlas.createSprite("Up"); - upWin=atlas.createSprite("UpWin"); - side=atlas.createSprite("Side"); - sideWin=atlas.createSprite("SideWin"); - edge=atlas.createSprite("Edge"); - edgeM=atlas.createSprite("Edge"); - edgeM.setFlip(true,false); - edgeWin=atlas.createSprite("EdgeWin"); - edgeWinM=atlas.createSprite("EdgeWin"); - edgeWinM.setFlip(true,false); - gridSize=fighterSpot.getRegionWidth(); - - goldLabel=ui.findActor("gold"); + goldLabel = ui.findActor("gold"); ui.onButtonPress("done", () -> { - if(!arenaStarted) + if (!arenaStarted) ArenaScene.this.done(); else showAreYouSure(); }); ui.onButtonPress("start", () -> startButton()); doneButton = ui.findActor("done"); - ScrollPane pane= ui.findActor("arena"); - arenaPlane=new Table(); + ScrollPane pane = ui.findActor("arena"); + arenaPlane = new Table(); pane.setActor(arenaPlane); - startButton=ui.findActor("start"); - + startButton = ui.findActor("start"); } private void showAreYouSure() { - - Dialog areYouSureDialog= prepareDialog(Forge.getLocalizer().getMessage("lblConcedeTitle"),ButtonYes|ButtonNo,()->loose()); + Dialog areYouSureDialog = prepareDialog(Forge.getLocalizer().getMessage("lblConcedeTitle"), ButtonYes | ButtonNo, () -> loose()); areYouSureDialog.text(Forge.getLocalizer().getMessage("lblConcedeCurrentGame")); showDialog(areYouSureDialog); } @@ -109,26 +99,24 @@ public class ArenaScene extends UIScene implements IAfterMatch { doneButton.setText(Forge.getLocalizer().getMessage("lblLeave")); doneButton.layout(); startButton.setDisabled(true); - arenaStarted=false; + arenaStarted = false; } private void startButton() { - if(roundsWon ==0) - { - Dialog startDialog = prepareDialog(Forge.getLocalizer().getMessage("lblStart"), ButtonYes|ButtonNo,()->startArena()); + if (roundsWon == 0) { + Dialog startDialog = prepareDialog(Forge.getLocalizer().getMessage("lblStart"), ButtonYes | ButtonNo, () -> startArena()); startDialog.text("Do you want to go into the Arena?"); showDialog(startDialog); - } - else - { + } else { startRound(); } } - int roundsWon =0; + int roundsWon = 0; + private void startArena() { goldLabel.setVisible(false); - arenaStarted=true; + arenaStarted = true; startButton.setText(Forge.getLocalizer().getMessage("lblContinue")); startButton.layout(); doneButton.setText(Forge.getLocalizer().getMessage("lblConcede")); @@ -137,48 +125,41 @@ public class ArenaScene extends UIScene implements IAfterMatch { Current.player().takeGold(arenaData.entryFee); startRound(); } + @Override public void setWinner(boolean winner) { - Array winners=new Array<>(); - Array winnersEnemies=new Array<>(); - for(int i=0;i winners = new Array<>(); + Array winnersEnemies = new Array<>(); + for (int i = 0; i < fighters.size - 2; i += 2) { + boolean leftWon = rand.nextBoolean(); + if (leftWon) { + winners.add(fighters.get(i)); + winnersEnemies.add(enemies.get(i)); + moveFighter(fighters.get(i), true); + markLostFighter(fighters.get(i + 1)); + } else { + markLostFighter(fighters.get(i)); + moveFighter(fighters.get(i + 1), false); + winners.add(fighters.get(i + 1)); + winnersEnemies.add(enemies.get(i + 1)); + } } - else - { - markLostFighter(fighters.get(fighters.size-1)); - moveFighter(fighters.get(fighters.size-2),true); - winners.add(fighters.get(fighters.size-2)); + if (winner) { + markLostFighter(fighters.get(fighters.size - 2)); + moveFighter(fighters.get(fighters.size - 1), false); + winners.add(fighters.get(fighters.size - 1)); + roundsWon++; + } else { + markLostFighter(fighters.get(fighters.size - 1)); + moveFighter(fighters.get(fighters.size - 2), true); + winners.add(fighters.get(fighters.size - 2)); loose(); } - fighters=winners; - enemies=winnersEnemies; - if(roundsWon >=arenaData.rounds ) - { - arenaStarted=false; + fighters = winners; + enemies = winnersEnemies; + if (roundsWon >= arenaData.rounds) { + arenaStarted = false; startButton.setDisabled(true); doneButton.setText(Forge.getLocalizer().getMessage("lblDone")); doneButton.layout(); @@ -186,49 +167,44 @@ public class ArenaScene extends UIScene implements IAfterMatch { } private void moveFighter(Actor actor, boolean leftPlayer) { - - Image spotImg=new Image(upWin); - double stepsToTheSide=Math.pow(2, roundsWon); - float widthDiff=actor.getWidth()-spotImg.getWidth(); - spotImg.setPosition(actor.getX()+widthDiff/2,actor.getY()+gridSize+widthDiff/2); + Image spotImg = new Image(upWin); + double stepsToTheSide = Math.pow(2, roundsWon); + float widthDiff = actor.getWidth() - spotImg.getWidth(); + spotImg.setPosition(actor.getX() + widthDiff / 2, actor.getY() + gridSize + widthDiff / 2); arenaPlane.addActor(spotImg); - for(int i=0;i { Forge.setTransitionScreen(new TransitionScreen(() -> { duelScene.initDuels(WorldStage.getInstance().getPlayerSprite(), enemy); Forge.switchScene(duelScene); - }, Forge.takeScreenshot(), true, false, false, false, "", vsTextureRegion, AdventurePlayer.current().avatar(), enemy.getAtlasPath())); + }, Forge.takeScreenshot(), true, false, false, false, "", Current.player().avatar(), enemy.getAtlasPath(), Current.player().getName(), enemy.nameOverride.isEmpty() ? enemy.getData().name : enemy.nameOverride)); }); } public boolean start() { - - return true; } @@ -236,14 +212,11 @@ public class ArenaScene extends UIScene implements IAfterMatch { public boolean done() { GameHUD.getInstance().getTouchpad().setVisible(false); Forge.switchToLast(); - if(roundsWon !=0) - { - Array data=new Array<>(); - for(int i = 0; i< roundsWon; i++) - { - for(int j=0;j data = new Array<>(); + for (int i = 0; i < roundsWon; i++) { + for (int j = 0; j < arenaData.rewards[i].length; j++) { + data.addAll(arenaData.rewards[i][j].generate(false, null)); } } RewardScene.instance().loadRewards(data, RewardScene.Type.Loot, null); @@ -251,96 +224,84 @@ public class ArenaScene extends UIScene implements IAfterMatch { } return true; } + @Override public void act(float delta) { stage.act(delta); } - Array enemies = new Array<>(); Array fighters = new Array<>(); Actor player; - public void loadArenaData(ArenaData data,long seed) { + public void loadArenaData(ArenaData data, long seed) { startButton.setText(Forge.getLocalizer().getMessage("lblStart")); startButton.layout(); doneButton.setText(Forge.getLocalizer().getMessage("lblDone")); doneButton.layout(); - arenaData=data; + arenaData = data; //rand.setSeed(seed); allow to reshuffle arena enemies for now enemies.clear(); fighters.clear(); arenaPlane.clear(); - roundsWon =0; - int numberOfEnemies= (int) (Math.pow(2f, data.rounds)-1); + roundsWon = 0; + int numberOfEnemies = (int) (Math.pow(2f, data.rounds) - 1); - for(int i=0;iCurrent.player().getGold()); - int currentSpots=numberOfEnemies+1; - int gridWidth=currentSpots*2; - int gridHeight=data.rounds+1; - arenaPlane.setSize(gridWidth*gridSize,gridHeight*gridSize*2); - int fighterIndex=0; - for(int x=0;x Current.player().getGold()); + int currentSpots = numberOfEnemies + 1; + int gridWidth = currentSpots * 2; + int gridHeight = data.rounds + 1; + arenaPlane.setSize(gridWidth * gridSize, gridHeight * gridSize * 2); + int fighterIndex = 0; + for (int x = 0; x < gridWidth; x++) { + for (int y = 0; y < gridHeight; y++) { + if (x % Math.pow(2, y + 1) == Math.pow(2, y)) { + if (y == 0) { + if (fighterIndex < fighters.size) { + float widthDiff = gridSize - fighters.get(fighterIndex).getWidth(); + fighters.get(fighterIndex).setPosition(x * gridSize + widthDiff / 2, y * gridSize * 2 + widthDiff / 2); arenaPlane.addActor(fighters.get(fighterIndex)); fighterIndex++; } } - Image spotImg=new Image(fighterSpot); - spotImg.setPosition(x*gridSize,y*gridSize*2); + Image spotImg = new Image(fighterSpot); + spotImg.setPosition(x * gridSize, y * gridSize * 2); arenaPlane.addActor(spotImg); - if(y!=gridHeight-1) - { - Image upImg=new Image(up); - upImg.setPosition(x*gridSize,y*gridSize*2+gridSize); + if (y != gridHeight - 1) { + Image upImg = new Image(up); + upImg.setPosition(x * gridSize, y * gridSize * 2 + gridSize); arenaPlane.addActor(upImg); } - if(y!=0) - { - for(int i=0;i insult = Lists.newArrayList("I'm sorry...", "... ....", "Learn from your defeat.", "I haven't begun to use my full power.", "No matter how much you try, you still won't beat me.", @@ -244,7 +245,7 @@ public class DuelScene extends ForgeScene { this.AIExtras = aiCards; deck = deckProxy.getDeck(); } else { - deck = currentEnemy.copyPlayerDeck ? this.playerDeck : currentEnemy.generateDeck(Current.player().isFantasyMode(), Current.player().isUsingCustomDeck()||Current.player().getDifficulty().name.equalsIgnoreCase("Hard")); + deck = currentEnemy.copyPlayerDeck ? this.playerDeck : currentEnemy.generateDeck(Current.player().isFantasyMode(), Current.player().isUsingCustomDeck() || Current.player().getDifficulty().name.equalsIgnoreCase("Hard")); } RegisteredPlayer aiPlayer = RegisteredPlayer.forVariants(playerCount, appliedVariants, deck, null, false, null, null); @@ -300,7 +301,7 @@ public class DuelScene extends ForgeScene { hostedMatch.startMatch(rules, appliedVariants, players, guiMap); MatchController.instance.setGameView(hostedMatch.getGameView()); boolean showMessages = enemy.getData().copyPlayerDeck && Current.player().isUsingCustomDeck(); - if (chaosBattle||showMessages) { + if (chaosBattle || showMessages) { List list = Lists.newArrayList("It all depends on your skill!", "It's showtime!", "Let's party!", "You've proved yourself!", "Are you ready? Go!", "Prepare to strike, now!", "Let's go!", "What's next?", "Yeah, I've been waitin' for this!", "The stage of battle is set!", "And the battle begins!", "Let's get started!", diff --git a/forge-gui-mobile/src/forge/adventure/scene/GameScene.java b/forge-gui-mobile/src/forge/adventure/scene/GameScene.java index 45f4d1086e6..447c2ee1fab 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/GameScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/GameScene.java @@ -3,7 +3,6 @@ package forge.adventure.scene; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL20; import forge.Forge; -import forge.adventure.character.PlayerSprite; import forge.adventure.data.BiomeData; import forge.adventure.stage.MapStage; import forge.adventure.stage.WorldStage; @@ -27,8 +26,8 @@ public class GameScene extends HudScene { private static GameScene object; public static GameScene instance() { - if(object==null) - object=new GameScene(); + if (object == null) + object = new GameScene(); return object; } @@ -58,18 +57,18 @@ public class GameScene extends HudScene { super.enter(); WorldStage.getInstance().handlePointsOfInterestCollision(); } + public String getAdventurePlayerLocation(boolean forHeader) { String location = ""; - if(MapStage.getInstance().isInMap()) { - location = forHeader? TileMapScene.instance().rootPoint.getData().name : TileMapScene.instance().rootPoint.getData().type; + if (MapStage.getInstance().isInMap()) { + location = forHeader ? TileMapScene.instance().rootPoint.getData().name : TileMapScene.instance().rootPoint.getData().type; } else { - World world= Current.world(); - PlayerSprite player = WorldStage.getInstance().getPlayerSprite(); - int currentBiome = World.highestBiome(world.getBiome((int) player.getX() / world.getTileSize(), (int) player.getY() / world.getTileSize())); - List biomeData = Current.world().getData().GetBiomes(); + World world = Current.world(); + int currentBiome = World.highestBiome(world.getBiome((int) Current.player().getWorldPosX() / world.getTileSize(), (int) Current.player().getWorldPosY() / world.getTileSize())); + List biomeData = world.getData().GetBiomes(); try { BiomeData data = biomeData.get(currentBiome); - location = forHeader? TextUtil.capitalize(data.name)+" Map" : data.name; + location = forHeader ? TextUtil.capitalize(data.name) + " Map" : data.name; } catch (Exception e) { e.printStackTrace(); location = forHeader ? "Waste Map" : "waste"; diff --git a/forge-gui-mobile/src/forge/adventure/stage/MapStage.java b/forge-gui-mobile/src/forge/adventure/stage/MapStage.java index d03b2db8740..a56a3d0c8a6 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/MapStage.java +++ b/forge-gui-mobile/src/forge/adventure/stage/MapStage.java @@ -56,7 +56,7 @@ public class MapStage extends GameStage { final Array actors = new Array<>(); TiledMap map; - Array collisionRect=new Array<>(); + Array collisionRect = new Array<>(); private boolean isInMap = false; MapLayer spriteLayer; private PointOfInterestChanges changes; @@ -76,9 +76,9 @@ public class MapStage extends GameStage { //These maps are defined as embedded properties within the Tiled maps. private EffectData effect; //"Dungeon Effect": Character Effect applied to all adversaries within the map. private boolean preventEscape = false; //Prevents player from escaping the dungeon by any means that aren't an exit. - private final Array< TextraButton> dialogButtonMap=new Array<>(); + private final Array dialogButtonMap = new Array<>(); - public InputEvent eventTouchDown, eventTouchUp; + public InputEvent eventTouchDown, eventTouchUp; TextraButton selectedKey; private boolean respawnEnemies; @@ -118,8 +118,7 @@ public class MapStage extends GameStage { return changes; } - private MapStage() - { + private MapStage() { dialog = Controls.newDialog(""); eventTouchDown = new InputEvent(); eventTouchDown.setPointer(-1); @@ -128,6 +127,7 @@ public class MapStage extends GameStage { eventTouchUp.setPointer(-1); eventTouchUp.setType(InputEvent.Type.touchUp); } + public static MapStage getInstance() { return instance == null ? instance = new MapStage() : instance; } @@ -246,9 +246,10 @@ public class MapStage extends GameStage { setDialogStage(GameHUD.getInstance()); showDialog(); } - Array otherEntries=new Array<>(); - Array spawnClassified=new Array<>(); - Array sourceMapMatch=new Array<>(); + + Array otherEntries = new Array<>(); + Array spawnClassified = new Array<>(); + Array sourceMapMatch = new Array<>(); public void loadMap(TiledMap map, String sourceMap) { isLoadingMatch = false; @@ -263,9 +264,9 @@ public class MapStage extends GameStage { actors.clear(); collisionRect.clear(); - if(collisionGroup!=null) + if (collisionGroup != null) collisionGroup.remove(); - collisionGroup=null; + collisionGroup = null; float width = Float.parseFloat(map.getProperties().get("width").toString()); float height = Float.parseFloat(map.getProperties().get("height").toString()); @@ -281,13 +282,10 @@ public class MapStage extends GameStage { effect = JSONStringLoader.parse(EffectData.class, map.getProperties().get("dungeonEffect").toString(), ""); effectDialog(effect); } - if(MP.get("respawnEnemies")!=null&&MP.get("respawnEnemies") instanceof Boolean&&(Boolean)MP.get("respawnEnemies")) - { - respawnEnemies=true; - } - else - { - respawnEnemies=false; + if (MP.get("respawnEnemies") != null && MP.get("respawnEnemies") instanceof Boolean && (Boolean) MP.get("respawnEnemies")) { + respawnEnemies = true; + } else { + respawnEnemies = false; } if (MP.get("preventEscape") != null) preventEscape = (boolean) MP.get("preventEscape"); @@ -310,34 +308,31 @@ public class MapStage extends GameStage { loadObjects(layer, sourceMap); } } - if(!spawnClassified.isEmpty()) + if (!spawnClassified.isEmpty()) spawnClassified.first().spawn(); - else if(!sourceMapMatch.isEmpty()) + else if (!sourceMapMatch.isEmpty()) sourceMapMatch.first().spawn(); - else if(!otherEntries.isEmpty()) + else if (!otherEntries.isEmpty()) otherEntries.first().spawn(); //reduce geometry in collision rectangles int oldSize; do { - oldSize=collisionRect.size; - for(int i=0;i= r1.x && xmi <= r1.x + r1.width && xma >= r1.x && xma <= r1.x + r1.width && ymi >= r1.y && ymi <= r1.y + r1.height && yma >= r1.y && yma <= r1.y + r1.height; } + private void loadCollision(TiledMapTileLayer layer) { for (int x = 0; x < layer.getWidth(); x++) { for (int y = 0; y < layer.getHeight(); y++) { @@ -390,7 +386,7 @@ public class MapStage extends GameStage { for (MapObject obj : layer.getObjects()) { MapProperties prop = obj.getProperties(); String type = prop.get("type", String.class); - if (type!=null) { + if (type != null) { int id = prop.get("id", int.class); if (changes.isObjectDeleted(id)) continue; @@ -403,20 +399,16 @@ public class MapStage extends GameStage { float w = Float.parseFloat(prop.get("width").toString()); float h = Float.parseFloat(prop.get("height").toString()); - String targetMap=prop.get("teleport").toString(); - boolean spawnPlayerThere=(targetMap==null||targetMap.isEmpty()&&sourceMap.isEmpty())||//if target is null and "from world" - !sourceMap.isEmpty()&&targetMap.equals(sourceMap); + String targetMap = prop.get("teleport").toString(); + boolean spawnPlayerThere = (targetMap == null || targetMap.isEmpty() && sourceMap.isEmpty()) ||//if target is null and "from world" + !sourceMap.isEmpty() && targetMap.equals(sourceMap); - EntryActor entry=new EntryActor(this, id, prop.get("teleport").toString(), x, y, w, h, prop.get("direction").toString()); - if((prop.containsKey("spawn")&& prop.get("spawn").toString().equals("true"))&&spawnPlayerThere) - { + EntryActor entry = new EntryActor(this, id, prop.get("teleport").toString(), x, y, w, h, prop.get("direction").toString()); + if ((prop.containsKey("spawn") && prop.get("spawn").toString().equals("true")) && spawnPlayerThere) { spawnClassified.add(entry); - }else if(spawnPlayerThere) - { + } else if (spawnPlayerThere) { sourceMapMatch.add(entry); - } - else - { + } else { otherEntries.add(entry); } addMapActor(obj, entry); @@ -484,11 +476,10 @@ public class MapStage extends GameStage { addMapActor(obj, new OnCollide(() -> Forge.switchScene(SpellSmithScene.instance()))); break; case "arena": - addMapActor(obj, new OnCollide(() -> { ArenaData arenaData = JSONStringLoader.parse(ArenaData.class, prop.get("arena").toString(), ""); - ArenaScene.instance().loadArenaData(arenaData,WorldSave.getCurrentSave().getWorld().getRandom().nextLong()); - Forge.switchScene(ArenaScene.instance()); + ArenaScene.instance().loadArenaData(arenaData, WorldSave.getCurrentSave().getWorld().getRandom().nextLong()); + Forge.switchScene(ArenaScene.instance()); })); break; case "exit": @@ -498,10 +489,10 @@ public class MapStage extends GameStage { if (obj instanceof TiledMapTileMapObject) { TiledMapTileMapObject tiledObj = (TiledMapTileMapObject) obj; DialogActor dialog; - if(prop.containsKey("sprite")) - dialog= new DialogActor(this, id, prop.get("dialog").toString(), prop.get("sprite").toString()); + if (prop.containsKey("sprite")) + dialog = new DialogActor(this, id, prop.get("dialog").toString(), prop.get("sprite").toString()); else - dialog= new DialogActor(this, id, prop.get("dialog").toString(), tiledObj.getTextureRegion()); + dialog = new DialogActor(this, id, prop.get("dialog").toString(), tiledObj.getTextureRegion()); addMapActor(obj, dialog); } break; @@ -611,12 +602,12 @@ public class MapStage extends GameStage { protected void getReward() { isLoadingMatch = false; - RewardScene.instance().loadRewards(currentMob.getRewards(), RewardScene.Type.Loot, null); + RewardScene.instance().loadRewards(currentMob.getRewards(), RewardScene.Type.Loot, null); Forge.switchScene(RewardScene.instance()); if (currentMob.defeatDialog == null) { currentMob.remove(); actors.removeValue(currentMob, true); - if(!respawnEnemies||currentMob.getData().boss) + if (!respawnEnemies || currentMob.getData().boss) changes.deleteObject(currentMob.getId()); } else { currentMob.defeatDialog.activate(); @@ -638,8 +629,8 @@ public class MapStage extends GameStage { @Override protected void onActing(float delta) { - float sprintingMod=currentModifications.containsKey(PlayerModification.Sprint)?2:1; - player.setMoveModifier(2*sprintingMod); + float sprintingMod = currentModifications.containsKey(PlayerModification.Sprint) ? 2 : 1; + player.setMoveModifier(2 * sprintingMod); oldPosition4.set(oldPosition3); oldPosition3.set(oldPosition2); oldPosition2.set(oldPosition); @@ -659,10 +650,10 @@ public class MapStage extends GameStage { } else if (actor instanceof RewardSprite) { Gdx.input.vibrate(50); if (Controllers.getCurrent() != null && Controllers.getCurrent().canVibrate()) - Controllers.getCurrent().startVibration(100,1); + Controllers.getCurrent().startVibration(100, 1); startPause(0.1f, () -> { //Switch to item pickup scene. RewardSprite RS = (RewardSprite) actor; - RewardScene.instance().loadRewards(RS.getRewards(), RewardScene.Type.Loot, null); + RewardScene.instance().loadRewards(RS.getRewards(), RewardScene.Type.Loot, null); RS.remove(); actors.removeValue(RS, true); changes.deleteObject(RS.getId()); @@ -683,11 +674,11 @@ public class MapStage extends GameStage { Gdx.input.vibrate(50); int duration = mob.getData().boss ? 400 : 200; if (Controllers.getCurrent() != null && Controllers.getCurrent().canVibrate()) - Controllers.getCurrent().startVibration(duration,1); + Controllers.getCurrent().startVibration(duration, 1); startPause(0.8f, () -> { Forge.setCursor(null, Forge.magnifyToggle ? "1" : "2"); SoundSystem.instance.play(SoundEffectType.ManaBurn, false); - DuelScene duelScene = DuelScene.instance(); + DuelScene duelScene = DuelScene.instance(); FThreads.invokeInEdtNowOrLater(() -> { if (!isLoadingMatch) { isLoadingMatch = true; @@ -696,7 +687,7 @@ public class MapStage extends GameStage { if (isInMap && effect != null) duelScene.setDungeonEffect(effect); Forge.switchScene(duelScene); - }, Forge.takeScreenshot(), true, false)); + }, Forge.takeScreenshot(), true, false, false, false, "", Current.player().avatar(), mob.getAtlasPath(), Current.player().getName(), mob.nameOverride.isEmpty() ? mob.getData().name : mob.nameOverride)); } }); }); @@ -709,6 +700,7 @@ public class MapStage extends GameStage { public boolean isInMap() { return isInMap; } + public boolean isDialogOnlyInput() { return dialogOnlyInput; } @@ -717,12 +709,12 @@ public class MapStage extends GameStage { dialogButtonMap.clear(); for (int i = 0; i < dialog.getButtonTable().getCells().size; i++) { - dialogButtonMap.add( (TextraButton) dialog.getButtonTable().getCells().get(i).getActor()); + dialogButtonMap.add((TextraButton) dialog.getButtonTable().getCells().get(i).getActor()); } dialog.show(dialogStage, Actions.show()); dialog.setPosition((dialogStage.getWidth() - dialog.getWidth()) / 2, (dialogStage.getHeight() - dialog.getHeight()) / 2); dialogOnlyInput = true; - if (Forge.hasGamepad()&&!dialogButtonMap.isEmpty()) + if (Forge.hasGamepad() && !dialogButtonMap.isEmpty()) dialogStage.setKeyboardFocus(dialogButtonMap.first()); } @@ -792,40 +784,36 @@ public class MapStage extends GameStage { } }, 0.10f); } + private void selectNextDialogButton() { if (dialogButtonMap.size < 2) return; - if(!(dialogStage.getKeyboardFocus() instanceof Button)) - { + if (!(dialogStage.getKeyboardFocus() instanceof Button)) { dialogStage.setKeyboardFocus(dialogButtonMap.first()); return; } - for(int i=0;i> enemies = new ArrayList<>(); - private final static Float dieTimer=20f;//todo config - private Float globalTimer=0f; + private final static Float dieTimer = 20f;//todo config + private Float globalTimer = 0f; public WorldStage() { super(); @@ -63,57 +62,50 @@ public class WorldStage extends GameStage implements SaveFileContent { return instance == null ? instance = new WorldStage() : instance; } + final Rectangle tempBoundingRect = new Rectangle(); + final Vector2 enemyMoveVector = new Vector2(); - final Rectangle tempBoundingRect=new Rectangle(); - final Vector2 enemyMoveVector =new Vector2(); @Override protected void onActing(float delta) { if (player.isMoving()) { handleMonsterSpawn(delta); handlePointsOfInterestCollision(); - globalTimer+=delta; + globalTimer += delta; Iterator> it = enemies.iterator(); while (it.hasNext()) { - Pair pair= it.next(); - if(globalTimer>=pair.getKey()+dieTimer) - { + Pair pair = it.next(); + if (globalTimer >= pair.getKey() + dieTimer) { foregroundSprites.removeActor(pair.getValue()); it.remove(); continue; } - EnemySprite mob=pair.getValue(); + EnemySprite mob = pair.getValue(); - if(!currentModifications.containsKey(PlayerModification.Hide)) - { + if (!currentModifications.containsKey(PlayerModification.Hide)) { enemyMoveVector.set(player.getX(), player.getY()).sub(mob.pos()); - enemyMoveVector.setLength(mob.speed()*delta); - tempBoundingRect.set(mob.getX()+ enemyMoveVector.x,mob.getY()+ enemyMoveVector.y,mob.getWidth(),mob.getHeight()*mob.getCollisionHeight()); + enemyMoveVector.setLength(mob.speed() * delta); + tempBoundingRect.set(mob.getX() + enemyMoveVector.x, mob.getY() + enemyMoveVector.y, mob.getWidth(), mob.getHeight() * mob.getCollisionHeight()); - if(!mob.getData().flying && WorldSave.getCurrentSave().getWorld().collidingTile(tempBoundingRect))//if direct path is not possible + if (!mob.getData().flying && WorldSave.getCurrentSave().getWorld().collidingTile(tempBoundingRect))//if direct path is not possible { - tempBoundingRect.set(mob.getX()+ enemyMoveVector.x,mob.getY(),mob.getWidth(),mob.getHeight()); - if(WorldSave.getCurrentSave().getWorld().collidingTile(tempBoundingRect))//if only x path is not possible + tempBoundingRect.set(mob.getX() + enemyMoveVector.x, mob.getY(), mob.getWidth(), mob.getHeight()); + if (WorldSave.getCurrentSave().getWorld().collidingTile(tempBoundingRect))//if only x path is not possible { - tempBoundingRect.set(mob.getX(),mob.getY()+ enemyMoveVector.y,mob.getWidth(),mob.getHeight()); - if(!WorldSave.getCurrentSave().getWorld().collidingTile(tempBoundingRect))//if y path is possible + tempBoundingRect.set(mob.getX(), mob.getY() + enemyMoveVector.y, mob.getWidth(), mob.getHeight()); + if (!WorldSave.getCurrentSave().getWorld().collidingTile(tempBoundingRect))//if y path is possible { mob.moveBy(0, enemyMoveVector.y); } - } - else - { + } else { mob.moveBy(enemyMoveVector.x, 0); } - } - else - { + } else { mob.moveBy(enemyMoveVector.x, enemyMoveVector.y); } } - if (player.collideWith(mob)) { player.setAnimation(CharacterSprite.AnimationTypes.Attack); mob.setAnimation(CharacterSprite.AnimationTypes.Attack); @@ -121,16 +113,16 @@ public class WorldStage extends GameStage implements SaveFileContent { Gdx.input.vibrate(50); int duration = mob.getData().boss ? 400 : 200; if (Controllers.getCurrent() != null && Controllers.getCurrent().canVibrate()) - Controllers.getCurrent().startVibration(duration,1); + Controllers.getCurrent().startVibration(duration, 1); startPause(0.8f, () -> { Forge.setCursor(null, Forge.magnifyToggle ? "1" : "2"); SoundSystem.instance.play(SoundEffectType.ManaBurn, false); - DuelScene duelScene = DuelScene.instance(); + DuelScene duelScene = DuelScene.instance(); FThreads.invokeInEdtNowOrLater(() -> { Forge.setTransitionScreen(new TransitionScreen(() -> { duelScene.initDuels(player, mob); Forge.switchScene(duelScene); - }, Forge.takeScreenshot(), true, false)); + }, Forge.takeScreenshot(), true, false, false, false, "", Current.player().avatar(), mob.getAtlasPath(), Current.player().getName(), mob.nameOverride.isEmpty() ? mob.getData().name : mob.nameOverride)); currentMob = mob; WorldSave.getCurrentSave().autoSave(); }); @@ -138,29 +130,27 @@ public class WorldStage extends GameStage implements SaveFileContent { break; } } - - } else { for (Pair pair : enemies) { pair.getValue().setAnimation(CharacterSprite.AnimationTypes.Idle); } } } - private void removeEnemy(EnemySprite currentMob) { + private void removeEnemy(EnemySprite currentMob) { currentMob.removeAfterEffects(); Iterator> it = enemies.iterator(); while (it.hasNext()) { Pair pair = it.next(); - if (pair.getValue()==currentMob) { + if (pair.getValue() == currentMob) { it.remove(); return; } } } + @Override public void setWinner(boolean playerIsWinner) { - if (playerIsWinner) { Current.player().win(); player.setAnimation(CharacterSprite.AnimationTypes.Attack); @@ -179,12 +169,10 @@ public class WorldStage extends GameStage implements SaveFileContent { WorldStage.this.removeEnemy(currentMob); currentMob = null; }); - } - } - public void handlePointsOfInterestCollision() { + public void handlePointsOfInterestCollision() { for (Actor actor : foregroundSprites.getChildren()) { if (actor.getClass() == PointOfInterestMapSprite.class) { PointOfInterestMapSprite point = (PointOfInterestMapSprite) actor; @@ -200,18 +188,17 @@ public class WorldStage extends GameStage implements SaveFileContent { } } } - } } + @Override - public boolean isColliding(Rectangle boundingRect) - { - if(currentModifications.containsKey(PlayerModification.Fly)) + public boolean isColliding(Rectangle boundingRect) { + if (currentModifications.containsKey(PlayerModification.Fly)) return false; return WorldSave.getCurrentSave().getWorld().collidingTile(boundingRect); } - public boolean spawn(String enemy) - { + + public boolean spawn(String enemy) { return spawn(WorldData.getEnemy(enemy)); } @@ -219,23 +206,23 @@ public class WorldStage extends GameStage implements SaveFileContent { World world = WorldSave.getCurrentSave().getWorld(); int currentBiome = World.highestBiome(world.getBiome((int) player.getX() / world.getTileSize(), (int) player.getY() / world.getTileSize())); List biomeData = WorldSave.getCurrentSave().getWorld().getData().GetBiomes(); - float sprintingMod=currentModifications.containsKey(PlayerModification.Sprint)?2:1; + float sprintingMod = currentModifications.containsKey(PlayerModification.Sprint) ? 2 : 1; if (biomeData.size() <= currentBiome) {// "if isOnRoad - player.setMoveModifier(1.5f*sprintingMod); + player.setMoveModifier(1.5f * sprintingMod); return; } - player.setMoveModifier(1.0f*sprintingMod); + player.setMoveModifier(1.0f * sprintingMod); BiomeData data = biomeData.get(currentBiome); if (data == null) return; spawnDelay -= delta; - if(spawnDelay>=0) return; - spawnDelay=spawnInterval + ( rand.nextFloat() * 4.0f ); + if (spawnDelay >= 0) return; + spawnDelay = spawnInterval + (rand.nextFloat() * 4.0f); ArrayList list = data.getEnemyList(); if (list == null) return; - EnemyData enemyData = data.getEnemy( 1.0f ); + EnemyData enemyData = data.getEnemy(1.0f); spawn(enemyData); } @@ -245,23 +232,20 @@ public class WorldStage extends GameStage implements SaveFileContent { EnemySprite sprite = new EnemySprite(enemyData); float unit = Scene.getIntendedHeight() / 6f; Vector2 spawnPos = new Vector2(1, 1); - for(int j=0;j<10;j++) - { + for (int j = 0; j < 10; j++) { spawnPos.setLength(unit + (unit * 3) * rand.nextFloat()); spawnPos.setAngleDeg(360 * rand.nextFloat()); - for(int i=0;i<10;i++) - { - boolean enemyXIsBigger=sprite.getX()>player.getX(); - boolean enemyYIsBigger=sprite.getY()>player.getY(); - sprite.setX(player.getX() + spawnPos.x+(i*sprite.getWidth()*(enemyXIsBigger?1:-1)));//maybe find a better way to get spawn points - sprite.setY(player.getY() + spawnPos.y+(i*sprite.getHeight()*(enemyYIsBigger?1:-1))); - if(sprite.getData().flying || !WorldSave.getCurrentSave().getWorld().collidingTile(sprite.boundingRect())) - { - enemies.add(Pair.of(globalTimer,sprite)); + for (int i = 0; i < 10; i++) { + boolean enemyXIsBigger = sprite.getX() > player.getX(); + boolean enemyYIsBigger = sprite.getY() > player.getY(); + sprite.setX(player.getX() + spawnPos.x + (i * sprite.getWidth() * (enemyXIsBigger ? 1 : -1)));//maybe find a better way to get spawn points + sprite.setY(player.getY() + spawnPos.y + (i * sprite.getHeight() * (enemyYIsBigger ? 1 : -1))); + if (sprite.getData().flying || !WorldSave.getCurrentSave().getWorld().collidingTile(sprite.boundingRect())) { + enemies.add(Pair.of(globalTimer, sprite)); foregroundSprites.addActor(sprite); return true; } - int g=0; + int g = 0; } } return false; @@ -273,13 +257,13 @@ public class WorldStage extends GameStage implements SaveFileContent { //spriteGroup.setCullingArea(new Rectangle(player.getX()-getViewport().getWorldHeight()/2,player.getY()-getViewport().getWorldHeight()/2,getViewport().getWorldHeight(),getViewport().getWorldHeight())); super.draw(); if (WorldSave.getCurrentSave().getPlayer().hasAnnounceFantasy()) { - MapStage.getInstance().showDeckAwardDialog("{BLINK=WHITE;RED}Chaos Mode!{ENDBLINK}\n"+ WorldSave.getCurrentSave().getPlayer().getName()+ "'s Deck: "+ - WorldSave.getCurrentSave().getPlayer().getSelectedDeck().getName()+ + MapStage.getInstance().showDeckAwardDialog("{BLINK=WHITE;RED}Chaos Mode!{ENDBLINK}\n" + WorldSave.getCurrentSave().getPlayer().getName() + "'s Deck: " + + WorldSave.getCurrentSave().getPlayer().getSelectedDeck().getName() + "\nEnemy will use Preconstructed or Random Generated Decks. Genetic AI Decks will be available to some enemies on Hard difficulty.", WorldSave.getCurrentSave().getPlayer().getSelectedDeck()); WorldSave.getCurrentSave().getPlayer().clearAnnounceFantasy(); } else if (WorldSave.getCurrentSave().getPlayer().hasAnnounceCustom()) { - MapStage.getInstance().showDeckAwardDialog("{GRADIENT}Custom Deck Mode!{ENDGRADIENT}\n"+ WorldSave.getCurrentSave().getPlayer().getName()+ "'s Deck: "+ - WorldSave.getCurrentSave().getPlayer().getSelectedDeck().getName()+ + MapStage.getInstance().showDeckAwardDialog("{GRADIENT}Custom Deck Mode!{ENDGRADIENT}\n" + WorldSave.getCurrentSave().getPlayer().getName() + "'s Deck: " + + WorldSave.getCurrentSave().getPlayer().getSelectedDeck().getName() + "\nSome enemies will use Genetic AI Decks randomly.", WorldSave.getCurrentSave().getPlayer().getSelectedDeck()); WorldSave.getCurrentSave().getPlayer().clearAnnounceCustom(); } @@ -287,7 +271,6 @@ public class WorldStage extends GameStage implements SaveFileContent { @Override public void enter() { - getPlayerSprite().LoadPos(); getPlayerSprite().setMovementDirection(Vector2.Zero); for (Actor actor : foregroundSprites.getChildren()) { @@ -297,12 +280,10 @@ public class WorldStage extends GameStage implements SaveFileContent { collidingPoint = point; } } - } setBounds(WorldSave.getCurrentSave().getWorld().getWidthInPixels(), WorldSave.getCurrentSave().getWorld().getHeightInPixels()); - GridPoint2 pos = background.translateFromWorldToChunk(player.getX(), player.getY()); - background.loadChunk(pos.x,pos.y); + background.loadChunk(pos.x, pos.y); handlePointsOfInterestCollision(); } @@ -315,57 +296,49 @@ public class WorldStage extends GameStage implements SaveFileContent { public void load(SaveFileData data) { try { clearCache(); - - - - List timeouts= (List) data.readObject("timeouts"); - List names = (List) data.readObject("names"); - List x = (List) data.readObject("x"); - List y = (List) data.readObject("y"); - for(int i=0;i timeouts = (List) data.readObject("timeouts"); + List names = (List) data.readObject("names"); + List x = (List) data.readObject("x"); + List y = (List) data.readObject("y"); + for (int i = 0; i < timeouts.size(); i++) { EnemySprite sprite = new EnemySprite(WorldData.getEnemy(names.get(i))); sprite.setX(x.get(i)); sprite.setY(y.get(i)); - enemies.add(Pair.of(timeouts.get(i),sprite)); + enemies.add(Pair.of(timeouts.get(i), sprite)); foregroundSprites.addActor(sprite); } - globalTimer=data.readFloat("globalTimer"); - } - catch (Exception e) - { + globalTimer = data.readFloat("globalTimer"); + } catch (Exception e) { } } public void clearCache() { - - for(Pair enemy:enemies) + for (Pair enemy : enemies) foregroundSprites.removeActor(enemy.getValue()); enemies.clear(); background.clear(); - player=null; + player = null; } @Override public SaveFileData save() { - SaveFileData data=new SaveFileData(); - List timeouts=new ArrayList<>(); - List names=new ArrayList<>(); - List x=new ArrayList<>(); - List y=new ArrayList<>(); - for(Pair enemy:enemies) - { + SaveFileData data = new SaveFileData(); + List timeouts = new ArrayList<>(); + List names = new ArrayList<>(); + List x = new ArrayList<>(); + List y = new ArrayList<>(); + for (Pair enemy : enemies) { timeouts.add(enemy.getKey()); names.add(enemy.getValue().getData().name); x.add(enemy.getValue().getX()); y.add(enemy.getValue().getY()); } - data.storeObject("timeouts",timeouts); - data.storeObject("names",names); - data.storeObject("x",x); - data.storeObject("y",y); - data.store("globalTimer",globalTimer); + data.storeObject("timeouts", timeouts); + data.storeObject("names", names); + data.storeObject("x", x); + data.storeObject("y", y); + data.store("globalTimer", globalTimer); return data; } @@ -376,23 +349,19 @@ public class WorldStage extends GameStage implements SaveFileContent { public void removeNearestEnemy() { - - float shortestDist=Float.MAX_VALUE; - EnemySprite enemy=null; + float shortestDist = Float.MAX_VALUE; + EnemySprite enemy = null; for (Pair pair : enemies) { - float dist= pair.getValue().pos().sub(player.pos()).len(); - if(dist8@RMQrObcVB-0q;JWJtBcV_@S=c!~v-1gZ^9u5CCe1*R{y+abLs3!-aGF>M z7@P32aPu3Ru<&zogMZjfO<2s0c{w=D__#T^j7^iop@-&dJHb@qde+4QsSRIvrlt8Jc*W4?f?%sdgP?8Y2;%{}I;a$d7Hs&+BQV{O+k$D5hIG%$Zj zwfa^_A4n|+0X?yH9_Ipr5TZ}Qq?vpc#vJKO7J|O$zW;GgU&BKo5dsfjP!38NpPfO5 zz++HKMfhPQbcqC@gP$yurjEWYYx{{o}GXx^)YyW#{2!2Y%o|iy( zktSH78-T<=viBF74PqF2JV4!G=P`VTwB|M=$#+U#+A0uyv`L&K!>vz#gwmK_FRl?v zorbO7v_tm!vlu|+v~3pa!nWJu;{&lvK^+f%_vt74k~frA-{^Y)`V^`?0q3o;7fI*D zGVJsob&KAJ!f7fQ#q)g2L+7OS^h`WDd?pkJEV>9HPL&TjpUa#B@e?Q?`Ur#yXCP1k zo%Nwr*VgZDgH(zKp5?#OIp|Be;ZIS$dhs>K{edtN@QZ&@{tyEzqh1#LRiYO|T_Um8 zv3@_F0_sqyr6SOMAQUP*FcM{XJWU+Yj40s|{`(V33wd)7VpP66nrrlMwW!rcaLG41 zB>vwy93`p>>!T50)IiXa(NdI=pS);zrhX9y2w>r_D@qPtXnY-MwNW2%CjnIeeq(Mp z%LIrwbDoqq6nNT(2OSF*ehUS}+2&Qr^*3JdpYj69(|%c?WfWDbi|AXoXKJ zKXJDtQ7EeuW#1w4?_HTj-2S>us@)jBW`fiSm~x&<{+rkS=_82*6av`7$wsaFpP&~g z_DO;wpru=&wGpe$H!$kFZdHLR?XU&>*l-72GBlJ)r+v5a%j_@JfLV!`BV?U*kjIuP zt%%2j2$~Op-iv#9h9&7}>{O2MZEquXGt7DH$Vh}8Zqu}2u3LT@G+lfB;(5H$;6_=(WLoIR2gk>Pjwu&`PC<*K zQ1Nd1Sw5lR_7g2yq?g`>G5=E`vMg~^L{6Ne(U82n!{etgyhUV|DEwo@VABnVB|kIN zjU8&-4{_^{_(Tdp0R4KgT+E*rLZU$F1>~FL?|v7U>CcF*J9&qyRzH>(z6`v!v|K;r zkk@Bcet+PrxozqY`Oy{qKQmjaD)So3yZ2TupjLbYa@}w@U zkAbhZAdQVOab;)`MELmZxYTety(4k*r}D`g$P5WQ;|YPm1pE8w;Lz@QqLk*L^#NNr z@X9~Y<0+uqT@$v72G~K8S{mnu8EI-k**kIrj?egzg``BsrA{^WtsIo3&$Wei; z5eOS24#3ubbGkj8ZdY?p(EP`IGyXv~WLc*JLt~th=@&oOmzuEWH%sWa7)HP4AUPit zm%y3@o%dn0XjjMo#i|lwvf8GJQbr;s2TOoREQqUnPNr)(P^xE!8HpR#B`SvTa_Nw8mdN2Qnvjb%3+>+=@Ig!T_YB4Ff3 zLY!siyv1Sbo-EA1#H?z&J~2{K%?Xbf;rwZX(t>qU%n|CzeX77z1I5GFj$~Sx`v$+w z!4K;OwI>w9!>WeOGctJfqppM35LC zKZDcw@ItB4Bh&VA9Eq&*JYc#PP>A;1ib;foA@^0C#tVWQ-MO8yp}-xKL+ppj?29s( zYHw-@^RmI){2_6x;GHB!*aiasi0HQe{uFHwlHy->-Jua4&#o}a+ObfU0hGt4y>&{eEda4vQG)K6DzH!uD#M~iSb|Xxg+gM^wE;5 z*dy*V&8(xU>63~RqG7 zDvF;J@A2Rk$^*W7J$bOM@}i1>lI13AT3f}*B{}D$fQJgFqhC%t(u(PR7lKb%s;7qi z^DXCFeQX}lMqZyOMOKKI0`+xHh<*xs8%oHLgG*96dl()f?_AzgJQ=({TiHe`5)`D? zF*zl;0U2Vj*?c z>$EfmXDJbyO3ZmeXrpHo`o9V!mBPNqQC?%$wjvax)RGb(UA*!+Gs*x759qqJJ56<8 z6m1Xe=vkQ*5#{P2peZ+<3RN^fxt`XQ8(51ug|M)$(>rPrm!+`gt3S35mvuCt!t#!U z&rJB!*(+xuKAVEQHRs9XE^utudO;$ODpCTe-+_xwPg8cha_sajOU4rCR_%iN(?7|Y z2lsykF#=qmVXC1HAc0{B%NRc?b|%oDPSz%dwD}Dvt?onkLZ0b*Hw~5+|L!OdfK>8( zGc>6-sA>Ze>7!nNxnnV2Ip~EF8C#q$0L^YyF#Nfv{ad)d=w2c=zKV~{k(4MPF!6z8 z%5NV^CyrI(4EM_7v(=G2oAEEUr5HKVK0gaCD#qK5qNWcn6F}c7-Twf^Kz{NQU-ll6 z^Kj)!K*GGoemX&o)8onZ6`&uIq^E2F{j#-t@nD!g7w)Ch&@O46e6d*&4QC&LNl3u-ZiI3(729wrr zp5vi++6jbKrTt*4zhm=lwq{6>qKcq?^qa?+QQsQMi!(^#ON<`bF6$o`O*C7KT$kD< zK{hk;M>%aEPt=p~cM<7%o|6=Q_BmSVho6MWfR(a3(PpW7hYo)+vN^8z7T^sL{yVGFV@^5k z0Eqo3Ed0oBbR;p?IlSj8z+&$0YAw)njdZ=H z=-&B%ZYen?8mpzl@*!v50FtiT=ELt(^$BOAXNcuU+MVAHq-`uiuRZ$X`Yrtg=fN#& zz!tktx1ys1%OK4u7<;lrq`Mz>(`9J#d@y_JRbV#%HEH|!9OJa;=JYcQx53Om=>2t~ zsQOhNeG|XrlR7Q5vV5mW7?q>8*zrZpo=xA9kuJN?oVZ1P%0>;S{>tOT>yp>=>22NH zp=VB~$D}28P31r248l)VI~S|``w@US;FOzZ>~&Hs?nXfU0y#bvnAU@8Qgc%OE&i8k zQb7Bg!{2V4x05q#?~d*Exc*;c_C4m4R~P*h5)jI*4_GDNiD1{*}J(%JXQ;(h;%+mJq;!kMheM zR+X}d0s%{7zRPnfAp$wqQDcB|f<@oW zkdO>eYahx?wP)H>COzDofqM`9Ics(i-{^4~<(4<()}tWY;~F>Qz226&f zgM7#fy@(<4{rn#K`fpX=18CBCu~dY|V(q?RTf+&LS3%ODH3zu@s3x;lJj{lSle=9P zM>(nSh4gSN6`L`OxU@0zGh>No zZlyWXL;}0EP^=qJnKNpXmeXdRLHqJc!lg3FALQKxQ$wY27b%^;2`hw{3JXhiF@#y~ z+h$Ne_7z%Hs4ON>LZ~K`*Z(5a-T&d7{2QY=R&j%>(<6@4<8zwx8iFmoU>#NK;fILf z-YALEo=_iPcJwKW1F;wDXI#@_?RpK>y?O{PxP1emvgQIKQ;i3G0$P2KwIUI}T}Vro z5-{88#bms{?j@s3m2QazM}6~XAQ`Pwzz!w8LS)w6A#+!1hCR_VH}GSy8mRpK zBII72A^O^#mm&)1%wtdc3o4uhGHP01p;@%gu=^ejT(DR@9f@Sg8pHezr}V4H4}-BF zrvp79N!tOgsmj^`m$)n|!IOA3<+q>lmPwP3io^=U2@ zJv{D5!cb~tn^8k~b#`k&GF%NcZJ}L+xtM?iy7YCop)-v=T6aT9zV=8R%lzPZ_x#Xi zH_?&4dFvJ@|8>fY>lCH8&%xER%Er_wtkX}B5%5;=K?GWLx9>Y~IscLHa&GYaSpyir zuYPFHV6hEmDk0DL-g=cDc>QXS>gVwvzI+w{_t;zot+HV&*b@S92W*OU>LvB)Cq=j; zc)d{w4B7!uzOqoegb`Mwo@%7nBoqj2{7tE^;c=e~Ts}p#+rPXFoUPqbB`AvS?>hl| z<_x$wYa=_79-oY$yQaH)V_BSbPPQ+w@De@vFry+K3eDwpochB}{6DB{w&jZYi>Ql} zs`82)P<(7-{TZO~+9*`_UrKrANLCXymDo#wnj`i{)bpo&a8K2tftf**@>7+jfJ1WD zs0h-=9io3w*dZ8m)nTMYHpYkh1a!wEt7fL+m^67JTKHT{KueH<%NNrogd&^bCvE=V zh^`a|J)1yJ%-AmU@4hHz--sfiX4Am{H69Nd>C5{eUfZq3ax+3~8#1a*i2kdxu)h!A zZ>4-{;m_QhU)tocykV{io_lv&V2{{4G7Y{JHn?`7~wq}leB2TQ4Wy`=r5 zcSCbzy;MjYu}U?L{SJxe%$As;=E{Z)r4bI^_04Vs-P4iZ>@FQySIi4U z(H$BAr17aK@qe|%AFgCUzxRvz6~t&@;$s~%AW2F!lc?iMtoPjgWzh6&4`ATL>kg+A|H{QWr)U0QsBftTAm^n-mHJs&jI$pUa+NZ~ZE-N=1 zm@)1A$4`dD@QJ4+Y#mjc}!@3Sw&bB{7k|B7L7qEaDlkxBft2AZELzGP`x&=4KH~9 zN0hc7-7=?5*4Hk%0JUujF}=!dF4#0+(zb*Cr}1Coc(;PStZ6?{uLzJoXCNffPo;50 zivL)RJ1qK=SSi=<_#GtnZ3o*dWP#(GKSDAZOB(a`6?JtKw;p$`xMN$hce+n?ewgJ%7v|#EB zC>7vGqDH)IgpWLWFZ<3zsC11iupXedZYQ^!YpV~~_+r;`oRHTFnsSY<`T`^Wi)P^B z?${mc%JUuQqj3}oYG1H16nD`V3eSN6<)L1u-Ny6Wk}bkt#u{IU z4^tR&|LOiRvWgxPwJ-`)(@SOYx*Vm%E4%JM3b5>Lk8bnJ$)xcPMRe0J^n4;3k)%d+ zM$6V|ROXxQW*v>|?#iHZtUmBUW}@t@X+OlLTO(UkYQjCuD?V-< zE?&*FhcDX zZINzatQ;rM4Ybck_IfyY5?4%+L)rVLYCFK%mEQ5bsk8XP+4>X$zxOv@m^KV-r+);Y zA!r4i4LaGh4&vm;BH1Pr^y)M?6N_%$?w$kI(0&sJ5M>6<$b8LktBExZA8Bp&#VHZJ zKtG_{kRM*>c-V7;vlR+Dx!c{%1QKWC*_$Z;#yWIA^JqU;p=L{ghF^(@d#Y3196;BE z`CN1iZH#QVvKyRzF1jO8%{8^h15>N6Fo{NVrG%QS29$g|H2nS;U%jB!WdT_) zGvkfb9Mqcdg$-A#uX%bTdXIAkJ6Q7Yn_FU(c;|AcR>_|N2;az<1%8&7S3o>Xw;M#) zL&)kspTMlMB2T#_?W083FQCx1qHJ`A1Rn1sx$~fE{SGe|rZyDf=H+KOzI92b zdBSo?CkSE~ihrQ^^;d>Lx*8pc65(ibxnHEGV!zqYj=1oLE{@j=K(L(OO z%k*batFtOC%~B(<=Z#UTqzVzrFQpe@E?vxF8A9l?@?$8b<>J9K=j8z?=NprJwRQ_>D3R5Y&#ITWT7RXMFWsRlmpY2l5wF(wPEvY+A`M@C}t)m z6wArL{GKnGo&LwT8h;~X#8Qwn01ayuF%U*l=lg-!M}|xDhaB~aa-PO_R!|aSb%~n3 zj|B0Dt-Za&K$t<{8EDnC(4fPMwdM>v-yb=ajwIHqyZ)l0WELQTZq(gD5wP6?jxj;LxL1VPgczSs zAqfLWSvIM!l7ooEe`;)C;iaF9aNrv4_l~pfrt#GpuPQ7z;5PTDW>Bl*e5h@D8wmko z;W=m}kf;ac_+8Ad@DY?Flnl_QuoUqc7^|fO>TE9(P*pGbch$@Gc=0huPyPI@reIw~8uNjYLtEStaZ}0fl(9S~sDyYOKRudM58yiMW zU8wZ!GYq|s>P7xfT!SMw3R0YtLZdk#3~QvN*dQ|9#7Sh+Oz+W4Zpf&E%`AkVHg?K% zfC_i|1!hr%bK@xN3&lM|&yvo&ikk;sp$-^JnV^FwKgJXCw)FA~01_E#q$Z z*bTE9F0S}e95Bd&n5!r0wIvlQ>`Oza@tyAQqHAtn4kA~+>M8|UX7#Fa;*ybZR{;WH zeel}$xb69%4B0FCu#`}VROf_i*ykICJ6b`uPXs2o83Daj9788U=sHCUs$~ePT>(hG zce}EQHU!>V5htlgDQb?nGeE#S6@7_=WzZhSAvwAtD~gz3Qt@&3zNFKf_1TR{CIaYC3LXZoM#bRAfpjlY+Ol0fw)sJU=2_L#bmpMS4Jh-Sm%Kx5*xIc+B{4fm)(a zQeC?hK{8As<5v-$m#2A^ODB2!`l(LTXOozax^`bg3>|U`2rzJl0`&CG-tc;mr$j`C z&U2L-k7r|A*Hhr6kOP(s5Xhbv2wtxG=;S>#Npr}~enipo9=}3|2~X9!zehkTehl#F z_Mw;-?o1$igGr2WIzy5F*lokga%+2mWv(bm^;>g{ZAl#_sksuJr5g8xIbOO}$WKB! zG%?4I)v+eXf6~5($N|C-wG*Gj<)nY_gPo)ve=}8{fe!-Z?Q8daQQ6hX=3B#@eH~K3 zbsTJiiqqe=i$VQ;53JD}`tPhO?&qj?%3#j`Y5#;7fu`mG?#K8B2x{r;cFeD}{g*9x zZwFEw?TSksP`VHu(dZs0GS6E@{jgz$8F2`GVpg3s&l01q4wGHrZc2&W52wRU>YPgjPTQa9u1 zCvyS{^u}jcOL3q!DhUeCo8KQ+_$jV3tSSAK|H2wOdYB@vfO-S&N23+2@6J3@Ma`z% z6sJuSDK)dRxR-*SR*9&MZZm`aluuRlA9x#)>Ti@18VO@npELLsCW{!E@oFeY@hC5$ z0Qbn`TC&z5Y?F0t2vJQ|%IZjk=QTO;Ol=W&!!VG)pD5ZpMtd`iR>caE8`*_N&8-g@ zjtwfx%8`TUlhr&pP1+s2N6uLy9Bo*d7+Rn3BbXZFpor7`tdN)vJg$Y4-!`;9K&*F# z&uF*ciso%U(4@d{mcBp5ueav-Ay~!%oox-g7DvSlOcx$Khwy4KRihM1ood1QpV)B3 zmHMxg?=*iX2{*%4k^9Znk5j8FlQg(1`RJg0;W8jv{v+7{XCt`P!Z)xk8rp=Wkk|`@ z;f}GU2yaUMkKlbT{k%@U$AS3-kszo%8N@WDBQ}^o$u3Ne8pFeZJ4NFAc{UVC>Csno z2hp!jZkMr?yPGUKa@EVw*~8ligqi%2zle?NC3}Ns`Z!uYdHRLmJAKK~M<{OE{l!Gv z;X6tRq&`Qqr%|6oiRuJy5L+N{G96Ns+Ml>b`#Hy&eUGvoJL9a=?rp2_SLs%4jFUd8 z3765EZ_7$#f$@$9-zym6d@xOP_g+o~PapmAw0}yM+4V-XniUa6m{!A#Ee=b~JIP8q z5h6uAVA|cId%5k8H6$1BBN7%j!A%nf(miuqm0gVdhOTW(TGl4(mJYR(GR3I_3v zn71YJKw$l+$GQ~Io)so2N8S59G}uC`tGZK<;ntz%R*TL%Zyvm(LI$~{yqDg_v^D<@ zHU4pQ&hUH=ZNZcoMx+(MHRaqkW=0+$4m>iE8n`pC7SzZppBWq+Mj`F3rxv4%F0%dDsu0PvuEmEkDB}n2Cm|9p8^oo=4B#XND_btOvVd=D@sc z%SH*>IN@}JAqB?bVnqXdEPHW+orodvb& z%Q+tn)BPE>G&|nG%+{HP(=T%dR1pqkEnloxv3{)4`1D|SG*pBTl@-qfSKa;8Ci4aX zCp*tAFLKDkg}}2^xO>EuNM$Piqb*4VZ9QHUj|(wK-1`^3}8*m7dl9QaU=} zh0Tu-5$Nhc>=E5$5)5v19~;KVAB}ADd0{u-&9E$|zaZ7e^t17d82WC#^KKH7h+8z$ z5AMDad$>LdgQ?=r0}!qGQS6omNL)JNFRQy_eR*akywBX=c}s}`gL}OHwpN$DK@*IFANXgKoE=_8rW-n5YeM*nLPP@Pwp=)1^MENPPGWY?;GA0O@0Ve=bmso8! zdqDD@digtnyzd{bF zp+?vU!uboqyC*e8tu}ho$`^n9iA=gff%iQs=TpETAdxR{d@Q8P`18f zx|L6(7QV0oiY9ni;xGvef2POIE12yJd|+DqyMhlHeV}7sQ(l7>pS){sh3MRG(bd5; z&K*GY`Mep?=*>hq`ihDysKsC&k>^bNHUKTu9^UyzvYF%sGJ1kh8{-dQINCzLaa6%y zase&iUWS>d8gk?gnrnOIM8)XsPmz2#+CcX4xv6&_HH)t^WCHPm=T<9v zWU$Z=ziR!i6RX0A-x8FB^mlFzPq51w0g?bA$(1Gy*Zb~g4%^SMpBR>ZLkk%u6Gv|x zW^3z!rU^MhkmNN6C#8qsIVaRHg?@WfHFdtIs$wS)4n) ztF?jezIfbIF7i(#gXqCrai116_AkqWUZ4fSiQst%A&1(Uoa9U>rbRlFb-R~_8UcK3 z7-<=6q@>)zRb-Ax_~4^w1f`rlh5=wRf%vI!GM6~$rXsEj_dDQ1#4>pn?`&@2)WMxgQL|z9No(JD&Wzc=a zK{Q|1%9{LteO`BoNDG^R`VGu*Us+_tgF0eX0v(RCwv@G4OG}0$e({huhO;DvknnWG z-LN3MF!p^w$j3`%p+7en1`?tTKv#ZWqeUAth8JVqkp`|_(TMD)t-tM7t}0V2er!YR zek!5Sdu*otOg#6U+x(k0XNGLq%nCk=bPx035w3K;Grcei2a2fble82z3(}RBlkjY_ zTIxa!c2~*TT{!psi|FzV`b})rU~WM_CP9jW#Hk-RVBg8r?6sDk0NM&ZRot15?zOE+ z32$-O4@vdtM|#W2%-ES*KX$3fg>7@A;fXpwhy`nbRx(DRr#1XkWHq`D4StR&7liqf z%0uNk+5}^L3@eIlIVvDRD|Z`{-cUe@Je6M_qemvE#%Lm_7mc_YnyYga7?#L5msFOj zP9P2llM)rauN&4E1wwp*61g4E3~W|@We=MgQ67SOToW7g_PRT0`jU^3tTi%iH~sV5 zo%7^N@CiC{lhUbCDP~4bGRf6ZvqtKs)#oq~*IDiM_6)VrH^X%f+7$c_Ct<1THUsp1m)=Hel5JzlB?V=VX zG$s2-!aXCHtT}(V4@(x%J5;T-w$94f;#VnsvYx>nD_i?BqrvGPg}buEcQsyHyOUt3 zMVeDsEhxzh{H!rH((r5*y zK~UzlGG4%;L*ke0nr9$VN7!*|O?QQ)l_%6^jQ z=$1SyT)RfNpZowr_)0{c^sBgwA4^QROt9wu8yT;JE9`jr^Rrk%#;xti!{7JsJEM6h zB7%U(6nXaQkE!sz`Z)6Fz*90S0syaq({KjS)giT2mc^WjiXI)wH5J=@{ldoYvaf{! z(OpfCv*e6dE&Zrhew>8WPdVjqPyoD^acy(I5!{-L5D)6DNb4KLE3I(c=w+pbKO3Z_ zb`UCwSTXTiRtWmjE&6paEwmV4NNg~)7!#;Sk|>U>AWxIa>-_9Hcs=PVkNIdkAu}+MZ^4UhtDjjJ;a?h+0-O>4RMmOzh zdBFB}vvVg_JNd2UJY3k!PxSI?F&oHYzRL!etsF=Df`aZ~1L{s}9uD`kicgC<^vOV_ z9L}NzBzutWH#BOJ5udMQq0ED4*easi7vZ(8;Ldeml}Ia6)HbJQuVh_1LL?HLW<=46 zUTkfaQNe?2p2Ml__+a82B`Kz&fa3AioFO6}F&tPQW0WBLsKkE%0T_F#Nk^ zlIIYzrZbY2ItMX9gKl!)7cFr;vmh+p0u`zE!dQVkP^dw~LckaWDk9nrV0Z9qDSImT zesg@2G;QqAnegM;uk*@Cuk3!9;@^<0PnHi$L`IJZ(=)aD$&80g0ZMbJkHkNb_|6z$ z{N@!W^Pwm!tW0gQ4%Be#3LH6lo~LX`pP)x}NY$z)S|UXx9UfRxlA(LFMy3B-Ex4@jqkaBah<>7#2LOV`X1OTF9S_s+Sa zhLwf7+Z%7+4MrmN5(u3SBcN-av3)Ola9th}W}=v|xJq})XmuG(B$Ry$teoiW#{3pV zXfiZ-CBFJ0*7Y(4C8fCkFd)0RC!Q4Ht3Bw>gR^9yWN6RP(3@=&0;uEsh!{s8iO1&;Z|FRF&B54^$cz^?w!8q z6G%!kg6`epI58vj9%UZJ=n5#>av@bbJK~96_;JG2%Oc5owXRgury$0O+_L!hZ+3{| z|Acz`aihKTXsq420VAh~Q;EiP)qkyqYAV3`n$8Vcg|7!;V2*r1E?JP5+Q0x}e5U2hZqDFd@U z#w~)gN-IbcfeT8BH(n$2K9_ycZ}LvpOb?eaRSyFy1wC}004-I5^hF(9SBu(-e!+e{ znUSCp6@@#QtY)J+c!cZnhMDMJ7P3krRVX6GgTEw$nNv?2q!%{*rii3GsWNMMQ~fo! z`e+x|Gfcdc$x$c0P>f3~G`a^a;u+Jf3RZJH?I1NPzk>vP5n$GBKt)?3(oM^zM)GP| zg{ zt#{t^gY6d(!)8tUGR6_)FWmb1JW@QZIPy5DXp!k_!Imwvv$GS1;J48Itr2b@popUl zqjQ2N_*K72NgeM;)I{az9{+iaWzc48e5p5RATz&Im$S|WBd&kL)rb%QMefA=HGD@EXUtPp{}4leQm8J5NGPw6(Nf(N5bl`W zW_s`VcIZf;L%(clAp6Vu{p52r-{1zAk9g+Il-_tt54JS=ZoG7O^hZ@C@>6IDg zhqbp3ny6aA&i176-N|v$Zs<3WHRifJ+8PFIRY32baq5^QopOuyZOyTRp7Q}8toQr8 zEYH8FM+Bvz{1&Kp9!-mRIh7pY%N_7#;Lj^!hOi5Y4TkQjJILT3yBc#y&Sw-JR20hu zcet-)p=^G}6tdZC;SGFP!UrPj{Xj$3kYjLgY$DR1V7KxE4uDg!j7*>1@D0ySypWpBy(~ zv?ae_G4n&p{x1o4V zZ%Nuwp*$+9JRvEmJbME?K~=*%2xYbHmny$J;a$8GVRi4ZH7)+C!UF9XaUK*y1Td;DhMji!rd%^4b&$KcX@A%PQ zWc&B=Cb8P2u~_PZa*27=d7BXmzCSrD{f_kiU5w_K8x+;1Ht@5FLSc=w^C&mZG zsT`w(q~E2Zp3DH~Si|^(=jhctwL*lb$_}`Zw0LrI19Tmk28TZI6&VbbrzEp*!d$7@^YE+qYXKe(t^MYZ1$OV@+il3i^c7POnd2 z#CtkH+-J(v@%YL@^u^=;;(D(!@BlCR((Bcn@h`>TjkFv9{&rNNR~Cx62xz*zPV5vN zCgW}IVln2p>iz4YJma{&AWur(H~*m0(e6&QW1`*^)6c4D>^_isSB$N9?V;Rdxn**M zLIwxm&bZ3jbj1gg-XjJz&2n_9Z&pT~3pDGQIA!^D?V&BkPM`0}dMqfCYKPY-YVj#n zp42bGIu-!CvGQl0jDz+i6X|#rf%I+W3w^4?Za#~)G20dNnBgzY$cxnk_apMZ&@>hN zkUUqHeI_BBA)Gdtwnfg z7Fh$39?)^NHJf~GRH*f};BlcJvObj1L&7FR(0>9qVjZU&p6 z&5~tUZF7E`^i{s3JEnD@@~DVX|Mnxm0y1}{#)t~(wR#4lAq`CMC zE+pLR7F(NiZ$bFY{~j*)i@>7140W6;IfoS3!^nRk+#zDRIqj>>eB!EwU57L^?<(qg z1OC{0+WpGBT%&@NVaTi|{g12D07Aww@cQXKcv3g&x^*KP$wuT{fONC+}|>x z?Kjg6GmC@XG&tE-)R-!|4%PM+ncd`7vbZXF1z*3klutn$izN$G>4j)5LGg9I5juN5 z%iXqx|HwwM5x?W)c3Mr6Y>CZ0zP^@8t@jg#4Jk5IMuDRuUVB4xy< z7#jReV@73JEkp7pSL5EjQLaG*uYIv@j&Zd}v}fWT1U*Y!!DIYWD7-?2dceHQ=73qd z;MQTj<0{;bxCwIU!I*vW)M4(2Jq^f@1f}DAl}a+V>+`Zd@uzDr8N|GOUVvfQ?FFu< zNSW139;qLn3hvELQxotSk%M8fg;7XZj2LGXdq()(9<^+2GCfZ>o{v^APq}sMZP33e z_Wh8DK;s}`*Y7@|s2oUd|6P(=$jUt#E(ip}%!;ddnZifHC>}9{80IfrLn~Xm-$sp8 zmj>`>yIo17lIr|oP~k|~!2-bKrRG-u@!d!0ivo`UFRdT(Eu1%$x0wFs#0(dvC|#O= zGCR2Dj`Mx7@cCv^oizx&FyqPFu9%RO$?6NEM@(6^ELI<8wSsFuV}3C&mT5IH`dxYs zsi}NC83N8KU)D~fa z9RkzNvQ4N01LZ9O#>4Ry?6u#7Gba#Vj!(8(9J6I7{xFyL?<)ybhh~)9TVGeEtQ9Ih zCOqL_J$@Dgr9>r1jty%QDG+K~_q?Eq4drh|(lx?G>?I06jMI6&Rcuuggne^LorQD) z-=tNlxz#P*$(1P<)FWq5u#WR0kT$DZ-7?3m&_v&wW)tU=R$cXAPqw2BpPn8Uo9!`uOt zW=z3b^+7OWEZ5OZG;!@#xq!%=y4~UT;D_JSK}G7j`d3I4&Oiu0!u*~JrBq7!)Ag~7 zX?gFynp9zFu7D)EcAi~wYF~cz5M;i-*&m|T2FAgnrzhjHI>BxXmUs=F6UWa&*d+^+ z7?#{u_>uW$=$n2-#GHrnbFoeaEQJlaGh510oqF}&!t)~RP8wfu^2$P6f2c~3c0o9o zJCi2`6N<$706RoX^= zZArK3z)#Ha&Y1Avm7#kslS-Em@&P8nqZaD*wGRzSa&SshpU{K7Sk}5Z= z$BMeh%1@69GDKjR%|3F1HFc)=+gt4=xj!JA+(qc|MoP>*O_gLuHV~7B9eb9GDkHLp>(?su@MmHT4c&;u*l+kcoJO0ILdGRUrqu(}8lBno>-b6u{L^xel64 zcK@J;8_(742`UFw;k|vuS*X^Z76VuoCLpTdQ<@AM^nOUy59z0*z{& zV4Cm|-OHdPpq(O)uNyCx-hW&iW?pP&e~OZ?i;P4r|{ zB~qm%D9tHmK8}f-FE&`f8?X^ltRUu{*<;->Ok(mbi4Xmo&!`aLSHf@`T`xk^!RV(z zW;<1Sb`6G3$R~477m>km%$KTAzE_wlcP>rR7jH31X2=R-=gd#%*R2@MUEe-|_vbO? zA12DScHieha+aARtyzt{&6f{;V`JaYkvryg){H0qAC}I+Ewio*;Bz~+K)JIyb_Aku>rtLYe$ZL6kML= z9k@-C_j2x(I3}4ae2Vr?3EBm?RUT6Suj@B6@hrnJPH8?ozsI%4BxEfr{>fU#C?B=) z!EZ>38VHj-Sg8FQlk?tZb~z>$bAZvYEdXgnX`Am$}XhE zmjtLM?tUO(vO4FDvq~vWfFz%w7WRM7=MGq(%HnA;MOH%mZvCWQ_ccF`Wk63c zojL}?M?x0(Tytue+EUQ9Hzurb-`FlT10nN@GKw#P!$+bFxZAuI8m&4h@IjH8?>0>l zMY(InWQMX1HkD3?Xl2lLqU0q2# z$A+&N9F`G@#qkzpS%|38P=f8~k|Wizp@pX2&{-Wv>ffH*@6XgBrrj$3n!ECbo$Rhp zjsm9eZPh6Xu&`is`AZS;Sj@bgQMFaUpDV?>V%x)5b5<*uQ!R7Ba+a_**yg8N7IRfx zzA*VP-~=7`xGir%qk>9kG=39JDh5zSD~=+gKBpvy^{&^D6I3MJEy`_&EEoTqGl(-a zj(B=s7lit6NdTwKYFzbL169gUO7m_sPsJM5y_KFCun*hoY+;5F(cp-jNOX9RpgC_c z_}1#yaW)7~14UvhB>4uF%uy{xA1En?PbcXRXPA;A zJgIC62s70t*)eK3dX4m79Hy+7QCfAMPaXJfIT;cCxu@2rV5#zo%>udXy`1Zk%_Q42% zMjovswi-3qGg!RBEKr`LUQVpp{SyIKDDCFxMwA&eS1%2!)WZVGAT}F z7=N7wKpVJ<#)uhqEswSbjd0%`Kc6KTKx1&UqkS}xwP{p}sEgQXEQ**T3-~+pe|>b4 z=?Gz+-7-IO13`MmIi;a_aUwv_f6pgUv_YKCp=Rf8aS})Gl+yGE&3`}Uuk|c&%|s1x z);b18KHQV$bz-UDu7F4anhSo}kq&kf*2H?y%o6t}2~aU>uxt!(P36voc6G92S{K0? zV2Fu`dMh^?44LA?x-YIFJ9)Jubu^~h!~>GIWZrh_g&gWq)!W^#0HFQv0o?d^Hj;U( zI8`IWdgq8VwlCx;Dhl$5LL*muN4Nu{V{^&)-*2uoYAob4OgOuoA5vjnRYI;JNHAnv zXsOpXP;|g2pk_+^EsVHlN@AQ~8wVQj(mb-wAaZnFQE(^rlQ8@5j$EF?YrSvXZQ(YM zz>yn^ECeOXlHtwJ02YnZSPzy*=zJo~u=I$;#8a;$(pVXfZo(YFG=i$L!8sz-g~vw?6tUUezg5EE`90E;bvqb&Fc{OCrFHK&M) z7*&vPk(nqZXa{^Ld&FbhQt1HK*e}N8StHM~mR4Cq$50{bo`?sNs$hu8`y)f)=c4W=5km5+;QJTn$-; zb&A)ab3@Suux{j%G5oc&-$+WpiB8hJ2i9H(&G|dQGqH22OOS}JaJOP*7?Gy6lssOZ zQ7+ZZ07S)Ur$Y2#ef=v}uD9Vc|C#=~I46Ah4Hy!UMQwB#Lca3YXB~m=z<620+7XL_ zL;{@$2=V@g5umr%u19T0db>jGc9vZ{z-DfJJ8e=048rXnr$ZceiC%{2lWYyG8_(R# z6P)fst)oo3YlHou!NEv2zYkD31#fa$tx^=P<4~G`ztJB=M@r9dmUO_(2iR47_0k!nC$tw62^el~kKYq5Wro69DN}wSJbNEAt^uW`Xx2iI5_EMn-54L8aCt6tcdO zT+}`?4gJr7^Fa_gPIVq~@nc^5djy~dPCta_CySn9N5Nu4pE(NP)!rq1;DaNJkOuBo zd_-VDv<`AkpcMnVomL{U)1Sx;WJsk^O4et9kf9i98cZsttmp1{I#fKLnb2_82G{2g zKW^g><%|Ws2c+Oqt}2U(0KId!auZND!zD~t=N%?(f@+g(Kl@Q}G0%MgT{=`x6D5aV zCQXCY?Mlh5ajBruQ{ob7Wyu?q4THlvzo}@h2+JV{w*!H&FsK#b?60Gl>7ERS z-Jlshi;c&`jQWqr&g=j)9TSq5MigVKq8`_@#KsinhA%F_5E*zkln7lDJ>jx1|+ zXN?@cA)5x(LVO5eWEi#WZ+J4Rt)M#S=nIIxufp4LbG*-z);@=S+aMq8I23(X)Z7VT5`)&$lrkos1_GS=W@$g!~sRfI&rkdQB4K0YNWDNC)pDrvAa$2-m z@FqD`>Ge%u6}dcrWn?DbSj-Ut0{5qQb7w!#a5pcqlP0072}r_aoFBaF9|%9AShl{% zF{*MmUq-G$#k?ZT@h!h16&HXJ{apI8@a42$W(=WJ6~mBX5J1`HfrM`M9aQ{V!UOs1 zlvo6mME0Dk(SbU$)D1Ri!fV{@x{5svM`jE)Xj7%jm0QdpUW?4pI~@z_^OS{o_XU2- z{eIA($DiM$6`!J#_pn)i9ChIG`74c(*}k|9{B4O-1ktmpnF8G225@}^2TZVYt;_~L z$%AwbxP{1ND=c23WP>m$%GrnwmAa07wAz?CQ^>W(2xb;EYoSa>^ zFGrp1(ADCC+DJ;-B2vaZi~mtem0EH)QJpO#(FKDUWp$VHffM@JLhoh<>F7RovBWSM z=?P)SX~7O^xjB?10C-Y*Q2SB`s<6pNNxz7VXs1VKf=9&oB0KD)(&%qvZ)%@8Zb!8T zqa&R{4y|&e)PwuWA&H6y2+Y7yj#?*$`ygaOg1@D{v$TBk87?>da~(2W1#elgjr`Ai zt5+<{I~tVUvc%{fJ%KL^JIb05Gf_M)iwka}o0uGlV41*g0CQpjg|J`;#{x0D<#4DS zns~K8opwPI>^WYdF=bris6k5|$=(P*ayO&1+&pW;odX;h1Mi%nq6oi5Ck zltK9WLWC76^|>hIXr ze243w*UPVM1$-`AY)eO>{pS{P7Rx^7%dRL)SNwFFg&6cXHud9DJ-pBmo=&iT0I?Nr2r-QGE6z7T*x%F^92XQH&L~h9! z4hHWW-x@%QE2=m)@2yb4t-CPWlX4H#1+Fzz>;H8C5Z%AZC50(t-!YTU>-F1VM37QQ zXo5c4+Yr@b{Bai^ndAQ7dcJn#zfa>CFqCLIP?@c9+48mpJ3ZPOjJj}49|hg84KM>< zhN{`b5dvZql(jAD$C_%Ib3C@-;VW1lGQOe`;)TXf89`u^DZ|>Ky;0!18*md?Ze>$s zcfntPTa;4+*v3PFEm0p#!{gnGx*FjyE$Jx1xCD_ha!~0TdX~VCMR&;9gFMIcM==(X z!ecqFhC0K|sK(?t0RvSw_#0Smu|4i`xk*7ax6%mmDuEwcYrUEzjMQ}u`tcczZ^^X2u!a!%# z;fQkX_@p-ezjAxQ6U5%2+(0=!l$B>w<2m-)OpdQB=)ub^YB(WN*(2(ym6zmAL9ith z#c-27;Jb(aZ{20oRE6|1jKJ3K9J|o%9A@WpPW$`U18m3HeX68OD#N7}L^b6$e7XSu z^12(2q7j+eD2yp3)o8|4<&QPxqR^b!5xUWH^$XoLtod%DE*PcxJMd-kP(2daO2 zWDLbr)eQ(u!liM3AQ#gB>G{gO&9Z#)c&7JtzYkWKUL5E56)?gCtG6Phg#QpO^oo^P1$h=g*m8JdKO(ciu!Xo?;!+nFBG5+?nCRn zNMyUn$wxnKibv1hgygf1uth5Y!A=G{p+}`+T9YE?fWKcAlHJ#rSB5{&POm&kc&`-v z_0CAN01*x)QGBN~lIX6xOMh=o2F|taR5LIhYbDB`;HGe6Bwj>zaASAKsT~#u$?rv@ z+shT&M4d?X2WitSA$IoQvm3zw@+58GiK12^%dUo5+a$9e6=92crT|4AtiTR} z6Tp6vd@6+$Vot?y@!Y3Sn!MWyATMlVH|N4h#Wq82o)5y0~=-D$Jxjc29I8BLKfM!FOcYHSnuCAOTPROYW=JW(=tFJA-T(5p11; zWnjyX|F>#~;A3Ne^!2W4qYJhj5VzI%;~wp9&G8~ySx5qeABCPSp%y;~lji9!TLx?1 zn81uMWb*P zWnng3@oeU*2XYivg-E(@BPJX_dwgDqT))%@ezhK5l%J^tUy}DEga;cnEZqz#y#VL9 zV|ueg%>WJeGKeQw;EhB8690o-m%&n%C=Zj(B*!DVD6G*tIKcP1rx7HAj?tLJCVmEp z2WxTyNXK-0y6oV(olO7JgCn`O=f3K2nc?p{Z;eVqccN<#hb72Ne4osq1rid&U3nO$ z?G=WBRc7HO+u=J~L#HKLzV?TggV*d(OD zm<%S~l*Tgy0T0mGF4m#R&=e{^FAYl#NnIkBJ-y)*tDX@Te@SBN>-5&8U4J=<%UZt7 zd@WDnuQDD0g!_}EAswsLvhG;%pX_eAf#9`|%3jY<I`*2O`DQWPlBA(=irC{u6QEiIFU<*0Q79R`9tdYV|Vywfb^(i zsXmxH@WLkWe%NE{Eq0QfPlmk)e$Ui|a*^tb2F$kP0NKX{`ydE;|&SLs%&sV zJD7w{E*>RC#k4=(aCYA)32G>GxDFlnBnb!d$KrN(rn&p|uNIm>RKT&kb@N+ds{hSf zAzQv(OTU~qSckOzM`OA_C1~w1K;;|Qy%7L;ggiwQCv5YXdqqJtZl;$ZY-cV?e&1-R z(y%cOWG#@BsbqWC#`BkoUNATKw#y1gs=B8|0-z5zFiP#V0PHj%&) zcJML$-{CjH*Jl>(s*^7N*KY&yXo8fWzyJJ*!9rRJ`y54$oBy953O%l-a7A=qTQ8c2{{^-Q=;366VRSsb_xv$)Py?={J%?_;g( z!$9Lmn)_G`#)dXcm8iZVu*Av8o!lv2qi_n~Is2)-?~ym1i=yqWsPX9H8V5hPYz#~p zqdNO6O}&gNfBnV;kX-+j1yB(>$~Wwx)ILJ9?0G)<(Uu-l&^fqDeDyL}<)Yl}$@EPT4uBY9f^}cxoo1l1YeAU#9%`}wT- zf^NSN?51h$IACKrOLMWyozCJT7_avQfBl=j*U^)vAIY_8)2-|i%0tRnh)9<1CBvjp zJNi@lc-I_2^?eYsu^YK!`@ad}HqA`kuPbXM=VcdC3||G2p_ZnEE8NvaA#X>O)Q_PV zo`ur3(;-6r%ua*?+=k*ct6NiVsRylI{(f;17fKOW)E7eAhfkA(mayN0u6?xr=KJ{p z@}y8;0X43v;Ayhbi5C#MAX^kpS2S?YV47Rt`D}1g%*P=osU42zvcrTo@iW~k4z7i7A=*@1{2Qf!_<`=it(JsVy5g!QKK^fBNEqgad#H^-IwUT{J*P>oN|KPzfF%$cxlxJPc6a|A9IbTbm{Wz zz=7WRv%((0yNpQ;B9jK>h6;GEs`vG|-dWGa$qjz)a<$S` zZ)tMAf`egK`^16gPly(^zq5r@MJasfjlZ(de%MIVgh~My1^L#_BA0^x$<`y6Q-a->N&q#^N9*^c=25C^*Z!IFL= zAUyy?mqc$4cRvR+%PH08E=mPDoE*=V6&-Jm&yU%LzhGAs5_wR~NWo~Mxr2H()Fmj; zNn_ev3Q7-!DD|AGMKTSD23!Z*$nB?CnF{(ELsz8MpVyfb{a^So6OdgSgpou|6kl2YC@ZlGf=i6rUs^!z(i!_a>XRkjoUpee(3K4fnygXKjK8v>+n zDwXSxCpJx}UO&(qeiShmM}w%3%9S@|?EWvpeII=o1HPDoBO{uha+$%~b@}W1JX2^l zn6M$77@&_WI=AMGYpahWj|#qut5~V_rlNxQ9h)`Ni24qW#sl$n^NHG{-JWpk(VZK$ zo{n^533}9lTeW!FZ`YiwIxj*310eL#h%+nPnOw0$wGtgC)AFoNK|3{K^sf>pn&TO3 zY4N4fgpUv=+R4?#?;T>LW@lv4+@y@j;o8Jk{#C`_6@@#{j5URg9 zssDAL3cC483qyUqZA6Xm5Xn(-Vg;hq3{Yf>VV1c2I1-qtK24Se?W4TxDRVV01!K-) zF2Z5e{0(B7<8oa}Z@+m25K8mBo`NizKQ<=1A`2^i+OuAH*&9dlA9|e5Ve*cZ>>GgI z2SmS@?H?|IFBLv9LQNCDUt)ocwTdh$NL$r{`TfO2y0Z#B_ql7Hl)t{-=)&J}acF3+ z`LtpQD!DBZzPEtA#~H8|Lb~oks@d?=-9UBSI*VE9nM{a4v3dZ|gOXsHvS?>byTPtB>m?6kR(}}@>crl_3d5I_JX}* zO(*1?8l-RaH3`FMOO=6iQNbAZ8Xw^|+4+7}=ZBPv+4o)a1W)IR>lbfZ+&bdsdfS4f z6vK#J;bVgj(5Va{IsEJtw1U%MofB;ew3B|jT8b&^-@=fTh$NKOYZ`rDDJRu5h$ zWk*#dH)^H0BI@eIodO)BP%8$!k+Y^0bH_Q7^Lbc*HMxu) z9MKtC$}>ble8=U4+zi$l3WEuqr(Mn%fb;BGXRh5*9z)`DG~TCLFH5;MKNIO>zsDnq zhFfG!cI5)dU+(2SY(YdYv?`PLkv#95yZDhso{U%%`o3(VguS|nbcw5W56+#3*jp|! z@IkKHf}bLq@Rg4Y<`$2NSmyU(H>VfMsRgE|BBkW+x9v@7*MitSq=zTb64V-_@kjAp zCECM5hLDwgxj$VF*swP-^B-pOQ&tKF6)A6%pIQKx|9;~E9-JsLv(UQfj;fsb@+Net zAUWrwr>pCWEKpt}ZYVoeGS9#{jl=}lUor|oD1mZX-Yz@R2>aZVuBNO|avSwN^-=Jra zeER!vids=NJS%POhAJN$?96%C5I1iZM&Z_HJw2@oZ6hFC6?M{-spva_lQ5R=-l|c0 zK6V!zs@>UQ9Pv*D6^1_oF^xpGO1kg{Cjm!vSPqNCD&xL~Zng+g`@f|Oa#aWZ$YLef z8qfYU_P9F@)zpm3U!1{;6V2}tE* z$lOH^mJD7s{xcFI-u=2F?lSX=#^edaE-@#CZnzT>Jfa31`4kFNZ{CgR$qi%`SOTyu z@L($r^T}Hi#WZjvn$V&}gt~$V`&+X@VCy>r*{Dd#5d~HoGwK8U1ns}L9_;vo+@XDb z#!#>p(y07a^gvPj)4Lk`WT!sQ+N=NPly);=i@TN4iM=MH^bhh?c8tQ?$!7gkZ6T$s)^lzN2ZneHxT z2uB^>iAd1|r2IRP=GHC_(fFDOGNK8$$02_i6TKyS>2da%>Hj2WU28Y)`@s|t-vs#V zPR8>6V54s{c4V@E5jk00%j+n(W1e;hyMj=mY>7u^W00M7Cd-#EfB^tU9r@Q9*`x!( zS~kN^g0DqQ!F;`j(r^oJ7#}=Bv;9)8{=S6-DA<3HYF>7t{uhGrs=fuNzZ2z;7dV7AsbkfvrhF?F8LFo0v7sS!tRd|$YVSmx zb^)S#J>4D6$tNDT0?N7exZN=)#CHs*i=S)Ct)Dm2zclOvE(=`g|G@MR+ZJDuVUVw; zJiDM74pOi%33A?W{&F{XwMrv}R~Dpu=WHEZUmYs6CLa9h!`w{h#m4_feA@F?pg{vy zu#veZW;P+XNKr%>Uwj#w2{B5JE(<8_Na<_6kt3Zd{4GI<6##yLZqU*fA_f%`PSqL+ z;=E5{_!Azfuh8S={AUPl{KXvYM5$osF4>caS7Jkf8+PGq<+r6vQE z%@QV=i>x&<0AVdtAm@P{Ww7ltpDn*Jt2XBd!d)20nQeDVQ%{sDzmem10D)(wU4sYI z-3$0lL?fyjz5$kYsK7W}Fx-&|lxfRVjJe)S-;cawURHY&s^fv%$e}WD*G(qj=G5?e z>$_%S;c(($2BnaQbS7#cb6mC!IkjlP3j{(LzfW5A{p)wxm_R(c z;rh{ljOu7}aBpllb+3H6q9O+{m#fSU77tEWyucElu%JTvv-@MvBAgh&mg95#14R#S zG`iL8rf_C?8Mon-Dp`JMV^LJf>!z?&%DJX38c@`lMwE1e8?JUT3N8=D8KAvb<0!#4 z@O-G-MR2Fb7?BfEgsQY$L+(J1KIi|fNVW0%zZfu06AKL|LgYkq_2+OnkEND2tHZG`5NLO&SM;l;Y77H;j4#5K<21| z2ycV!LH4fh7{d-^zR$CO+2~9M@y+U=o4NcjYf`_7;mnzi!$b=U*2hnz9`{slM==oW#9UK({4oQ2&k0(8jtR9$333!x21Xhym0jt zXh{2ZML;x#mn{Hckx|hi0{!GSMG4Xn_<^vYYc)&j*3k5U#r1uzg76=(fD#k4JUh|R z0DQ^$#3l|uB=YzU7#3tLQxfB^E33eFq^-ANODrAn8n9|orvpw>Cl=0dIX=4YPQD1R zd}>4v%Vr}Opz<#E2}rq5lj(P8;NV9XSP01v>7*bt&_)%&1(%w-CDE4o5|B8ximmIM z7rkqrj8Ljb;80>BL%y~PV9#_M^qOl3Djp@)(g5-$aN~%%)J=d;gB*x@AljcHv_y*K zYq`5>fL~7kCl(bK2f5D&!i84mTVSRmCjls#`st|7D1nUrzMfg6oBVgcZckyBNKoNn zvM*B4&;(e>WhU0A=nq@F(uF@ZHc`&E2<8a(%lqtm=4B96l}i#3H&-pI|6K;$6I2Z(oc$t;Yme&CX1&84?7_MvPj|K&Myv&Kaij;ocEv%abC)(U z8>|hKqul-3$1Cq5)4hoyHGT+3vh{_!QN>5B9S{CGo`By!2&}E5s~!^)1eq+l7{L|@ zqB>|&*LA8zX==WoP1D;D60w{$xjh zu&3gwtwL)hLiH5AlQmmt30p@hl+ZIL@~3ObgWFcN(zzFj$l^QA)k6Wz?Fd{=F)}3p zfl|GZ3jnNIIUNC5CE-5onz$st12OLK1HDJHNxVK~D)#YYO-*Ra zwjLr^%X`n`eYN+U^mn%W4>_Amy0PtlOC0$x-eec;v4S1G#1NHZ8Jwuc#E9SOf-I%m zSp5c(?EdoK)RxoYl%Nci8|dqq|9awBtX&MRs02(twYmyJXWGi)kZz>m^y(yizaqbu z{x?W!j&{@L-ypD1bmu^RT3{`|L%+J~ZI!)fNq!LVWA7qo3kVy#JZ$(-EhBson*ZID`9N@u@`tNUP0Koz9zfz;RZ@6s?C@n!K z0R9~?E>Wc}_}4~G2ZO9bB$zoH5E~^J8|>*l^OSJL=LJ6L7Mlo=Q@24JK;;B|d+FYV8-NB&3JN!1KPfy^v%0wW)s=*Dk_=%j_9qunS2iWu@VZq70ifyw4uqN%3QM@a-3lJ?HI#NXI^HfOxkH{G z(GCV#gtf<#CtV21+2-i24Mku5(~L!re?wbkPBSqkCt_PTRQ^aZosJj}(vc;hA*Zm4 zl8~)|WRlP||0`I;)3L!MTVwg5^cN)%KUUf9Xir$+K`j>I8jJ*ti`+P!qbcRS6|gcq z;)nujTQqsGDjN}5T=KYwBx*X#BhWtKS#usSRu{6x7czXFg@`s!Yp&9JYAUt*?n|*UTN7Nb&!4_u~-3PaNHRwiAsN727u! z+eiKJR83IhF(4!D*qL4rl4<{njeVFJRx4Ze=6obE09mRH&5KSB zp4t;(ksTCUf?5_GFmrjii|F62c6P_R*WJ!Xyx`<3OJoGCz{il;&RxFw<40v53E94g zVlLM75v){x2dL6vDLrT!yLX6a@>Dp(@kdy8$CaGCP2L1cVp_OgjnaWdRJX|WSapS0 zJ#bw!$_KfxGp$mNg(7SZppTR+sr~yJyETl=Ut)sHr8_kRD&aX6q3ycG`=a{%ED${g zdaV(=DL_pXMa8{cVe*4nugP5uA_Mln4$6H7=gaC)LObyQ#eP)CnML$15iOowFq9J` z;%Ot!?MEc{{5+C}V*?Y)+@;;%zKhV?Xt$2viHvoQcl|{XzwZEmD=|!hc-jyK*AV{1 zU`OnHD-a96AeI?3n-$@;G@2Wt$;|rt+ZLU%frVT;Q+iTg>bliC8XFt0qk5igO%tc8 zPtK9-WJ9>l&pwP;IZ9!Dt@V(YH?zI9u83g#ggdhAAfL#AWYnRjnPk8I$48HY-wdc4 zplCZ`bH1q;*F*!n2Xm;x{>@?=B_;QS6=lT*N$|sG2ze~fdoKN0>(SMa3kcF~ck{ca zmXUsjHRb_81`n1p8ClIg)JqCjRet67g4K1vp%|@<^hj>EFozv;MXk6m#)q~3;601m zqnwI~NnJwy)D<;K+I*lbcUy@tG=TuK5sL_ZoApiWmy_6Lg8o492UhKj|HcUjchIE@M#K)H-TJAvJ_RQXsXW}*CqqJ zj^zi5?(t1tz4IQ+F1~Ms$dDNohOOkM#aji|CPSCFV4N6ZEK5YYL8`^5kK=T9^DiU$ z-vCt+wT93?UG-En3HJ(5DaLhV+Ib1aSnT-cF&nYHVIrEVPotNIC*cj|I6Pd3{w|a< zEys_R1Cm_t{1;SIcqGs&%KrKVXV$&tC4H$w@KS~@%+0P>TI zV)R*qnVNo(IKZb6T-m(}4lSanv{*dI=Tv5y9x+HQ2pEGzjcAB7Myi}9i1?;aGgkqb zW$~#!6Jm&FLet~@QlLBVWFR_}6EZCa;jvuIoN3x7OvVuNHA@PC4R&k-!!5gD&U7h2 z*XhG23zsCJB;wP3V@q=2C7}BqfH%wb1*$(+wf5O~DYvkQpG{zt!Lu=^s7(cxkFl4= z8-TY1E~%`fzqD}V!v-I*#h1Jp0Hl0_P$zg(AJ`fM@$UXdoRN9MB&M75*gsST1=IrI z#M?AK9Z+}Y>euS;vd>Z1wV;Y1_nppSr=BvI1^gNQ0n2Z4^Vy@(VoUn~@O6Rg20rMF zyoK<@*EIIg?A5D3*=&f;{Ent6h0PYVq&rBbM&N1?@>6l~nHBfX2Is6w@FrwzdrbaH zMqC&Z?Y)R7t}dyNh7;?ev;LH##z^5vZ)MxP0f#TSR#Qn2Gt`x#Z4?oK8`UnpFQBNEp*1c zPysrIJ%)-=n{#egA>@N*V_0~h?xcfSxqdi^N0uopcAyC;9_IQg%ew21HfhdLRcO!} zV)QkR78tupO1F8&rM4`ozSE**`|0%BNqcMdzzzB29Dh^F8TK|nLDBZ1+y2ruCuT|L z?Z-Rzx;zc7kh>sQgfMdBIavogvdQ{>yLE7l!t6SsXkqo z76;4VRh{E#c~VflCRQ{rTck>ZT(A75z5GW;{?F4tv(L9f-&uWE=J@R|0TsvSnQ?w5 z9<`{0Ep^jR)fuXDuGB+;5Ld|%*##Rp$wDlh-z0$jU+k@@so1Nb^phUz&F!ngR;WoR zr(#*Wu;Q0z1JNd(W^;d5#kP@L{wDK0dhkS}2ry9r`CTUW#4viJ_?cg>q#(7ke5Cm7 zYLY7)+KETHXtPQnP%&CGtB5rsNVAg=+l@ zP89~6XdssGSNmc-+tvyT$tru~gJ4}h95)Pk3`Tv8-*0 z@9X#-^B;tcWV8=9ql#P!=HuN9$k=_rO0Nl)COH$FI}OK;Afx*RN&*Ns$mh&!dWbE%5bc=4!~3+A2v_u|6jCsfZqOK* z8=m|fC5VfgjG<&+R1V~N<-e6lo#4$hXcrkmj8|mvaRf}%zbE3%D2HU2!ho#J>xT}v z(2M(~rM=1Y2`V#i<+@NWf08`E`J9pw)KIrCN+sZIl_>{AW-l7EFSfyR7c`LofRNXj zl21sd8bMiWAb9ffGiO(aqb$O4pJyRM0jLFxXp&^Zvo|Z1_arHjRDJOv9+#Z*V4?P~ zr0Sl!JKB)ce?nFZiEY_a1<1RSMXVOfdb!WPn~@rB68pAUo%*2vjj{KB@>y$a%{9zT zl`KHk5G4WQ|K_6q4iXEjyRni)Q4Qy!TRxBf)OuO&oX?OT>RlRjZcH~F8*oCqi+UD~ z?9NaQbjR-h2hTx@BK)!IL-eC&bgPW{j-TDaFYPArx{m#0Iy;!L10d>Z!ktQ`_A9(3 z($Gtaq36t(=Y5|_9>=;tEqk0_3~kU9p%}bWv8tN$iQW$&vfNP`v!Mg^TR45y5|PpD zDO2VygETm2VfIduZGZm4nKdmE5h*ApC|zb@TV47DCf|^d?EQlIhkloL9idq-#`)T3 zh`uNmcmz(IrzRt<6hN|K)*f`aB9V^R)0`FMCrh_i4sKR*4A&V0!mN;wkC2@WhT3O$ zewv^A%tnz0UiSlYmbjMklP0R_*(c(J^+6~m98Cxh1(8~`K!O>qtqdjIx{w#X|7mh; z2T&}#?9Jl=Ot4S&rzA}akP@NmT{o>m`N=DVk+J?l3IY=jz%6_N(KuQlyG#pLvK4?F zs34R{<`);zG30;P2@}@<}RIdNLt6k3gfc{`A^pV zqjcf=_&*y7Ka|?y{#0lK6eEcGE&?LH$v6TrnFBJyBq4_m;feFl(%87_!`kZlU##+3A-WqG2P3G$zX{PF~N8H4Pd-f~eD!2%-sNZ8J{TY(!_q^@3hL z?`J44XsFJ3-tf6JKt7DQ#naXa4Y^!R_L_r^WOGvmjM>45c^J{&VslU)DE}4sz3z)l z6&U`D>#DCa7x1w>Uo5S!RyJdgWD{xu@tshHYHx%AILVM5{id9@(TcL~roMze!0j4u z_Ie3`L>PYa)4+e9ml~dI3s*5qJJq8@WgIJ%<_?ZQW1<B>1$+*;4QII<{*v z;e(eQfcn#pH25f3JE%B5*cpJ`_B=o*T@J9Z^G@&<(<uOvbdT{!Ej1Y)MN|-F%0#@6)#nj3RM#$;<{r* zl&nOoY!o>mTipz6t&V1juRo6d(@;$q^KmD515+?NX(Da1%C**7n-ifgW%ul4;sW?? zBtv2jQUwcwl`eY>g#WpCcQ_(7HVFu0SErNYXeHX|!L!8^CD<<-*2oTTj_1wWC4Hqm z&m&?Y*7o&6l5|8UYV=eR!Zv#R!E@`5-g2>u=2ifV(WjPP_kccn*e=ri6%HkJ@JS*; z8b-dWtemR9@hh@OHsBYn3sDp<*(xBJVhP=R=7ad(r82RDE+UK5T5fQu*Ga)-{p@6d zz;7u~R720mOlWqQW&hjaQ7>u8B}&rN)7|hdC|LB+cD)X8op4w|2gAk9oVQ<^Z-ic{ zxhkxd-yy`OeC-3-E-|n6K?>cGI!@O)my@2}4z!oPt-Fm(q;i`t1mBd9^Z+*MT2!9s zG@$x4N7op()x@vqXp{WuO!*AMBBE}TxnS1?9E=1bk-gmSPCsnh9BVF^ZTLJDE53b< zkilb>8h`!AvP?3!<^T5yLl1$*-FPLv<~Y-_S_4zcMnS_g>sFKQ??e@dZ&_Mht#W`z zb?zHF$%e4_%vHt?TNeTVxi)1ySwFm4Y#4^ax@1eKK-5VI#>Wo-9-(l!@jq9=*2+R$ zSvFr_3-V27a|`G)V^>_)m+KkUo@#j9$TNQ;AK8OZkDvZW#Y-_Elhcq@reJmYNz`Rm zy)1w+h2ba_s=+ZCOJ)5<)=zD|GWL$K1*cJNF73DWM$$9`;nEL)mgoZR`H)uGIu=d$ zWTZk_X03hq+N&8uHy5__yj*%zI^Hsi1lx7V=Ks)H@(d1g>co^bcI=qV|Ijadwnx@PQCTCqLU?`d6-*PHwGDJ1ZPCBpD=7EOCDck~4s5B73L#fxi4ESILJvZ=~C zXsF10fIvTPPJrnn`vf_8z@c`BAO{aI*d>84DmItUtx2bXpIUVvW?nU{*e-#cSYJ~9 z)Bh(gs?mDXFG@przwe5NZv>}-jS-tpx{7nf4L%-YP;Y=H1^B?o5<^GGyal~4v-)3F zr2lQCFvS%&D4wl3J{M}^HQ~M`bBe@hp~aL)%=$JK{csI_k}iHDni$T|*r76lFS@sp z=HmV|Yr61FPtKul;ueeN8{pS3V*KqN6?Z==6QzBp+5Uqv{gJ2Z=Jp7S8@|sLJ^*Fi z34V-Z0B$tHvnRff{-XK#(~O2L22;N8TlOV0xNNXIqKIgO{0P6Er->afpU9~K!8`FY zq=Ufg0>kIYza^FF3`+mAF>#Fa(hAt=)K-U2vWmy(#ADe(xQ6f#dZB63uJ)Vs+6UNw z=Si42^S%IrujHa7Ss9gE-y6JiLXieZ*D|OofC4$>i8l z)aqfC2%Y<%4Pjyl_($I6;bfueYD_Q~$fgcHs4Il1M9DIG4%l=%f2WRXuA!I&?^--f zh#iQQLp)<9NYjDwG5bV?O;qoKT?hIB7^ZMM65`s-`4G~uKZ~pqZ%6K(j0TiqlsPrUtGy4{5E%KBkZh3k zbeci8Fok6imG}VxeI8#0Zn9wRB#X!aEu}R&3}Z%M&c1H!(oAP2WZ=Bi)mH=x-V+tm zO4*-;Ea0OtcLcw--aK*kmQwTo3_I-L6FP%p;2AQQY;4 z4N>7)iVycq$FaT!Yqg#+3MO_#SY%3CRT{cmo;8UM#p6Q@%7|g`lWJhPR z9LNpn4n4=pTbfZhh7JrrqDou$Fh#~w_BT3el$MP$!2G;1SHXw%^yJ(Iag3P zNq!4yZK4WO$umTa$u4kQf|?`DFj_}1y4{j}N)YYUMf-itp3a>#NEvR>G>8B|FF^xP z+Ejm)s+QVMutPKbz|8VHf<3|*iL>}mGo%DGB9GPkhv*7%gvhwL8~2P0@&!xN{YIV- zw-HW(w{~8)wzY1Q0EufqNuH`~CjPnObKyAVEnvvE zU=bUQn)PZ&RKTcG)~Ius2@Tl{C9 z+5wqG)N|CH+j+955Kn=T)r)vHT>od&`zwqJi8(sBni)eiPV7K8*Y_3Ri1m0;)E+PL zbVcvKuAlt{nLW0aLyppH=6Z(m_kupqxMTN-?G&qvq?BWrIf)4tq*CC+3 zj!$6MI~x=9dX8qs_Du=0lBd!@C6#0stsa~yfv#ThPp30t<`A7iUh=D)@&C41GhJY@ z$oeeM2a`&fWs-60xcG>gJxh)*R6bMB1!1f1SeY7h4CH$DR!?T@wRms}Hgib)EUEk4 zSUOw`fFPY)ptk4qw>eko(b>7dTmZW|n*~p%fA7ieGZ+cG9?^D?c)JSYU?a?-_Kg8Uyl|=!r|HM@1){SF`NDkM#x0@cM;E@tq3fvWr{&g zDh~L|QJOfjBahlvZMV_0l9{`L8Q}{>RtugRu51^(N)#WRkDH&0i7xv@Ho;pRQiG4BERi}Dv`_KsztG<1kqH47^$Yb(O-#X+xsINu!F37FA*oRd6wkDjN*mHY&y5 z3Q>|Qh(bfulJs{B>)y6#M|jo*h*W3bCahKnZfk0?wW}Z*<6DvC*n&go*Ox<}uC2ip z%xG@N0sZ*7lbL}__*ptroKJoTv&eKi8FyactU^zo5%*-sxf)sY?XSN^f>a0Yo5p+=M^Ol#}LSBTgtJVx# zs19@M%B}#3h-jy#Cq#H%@!s98kJQFCb;)vp;tXw1j6ytW2ik1tVKyXDj1H_j0-&Y{ zZ1Y##Rx*@B;9d5bPXNVDR3z+QL_zzsOJ;(}Zz1&U3T{CaOIHUqqJ5~_sYcWMWV_s0 zM@z7_8>!9(%VD~z$)%o?yZ#@Yait#|3sEw>JG7^RtL<64HQNG7|kDuWSmLy|QTA^0#NazT%gS^^ z74(lxbw^zx4EcX>XFQ7x-EP|VefA-L&>kjrw-~kHU?qs5b-LEZg~nh9 zO+7+g1UOb$8nFM?B>7pzpXn(;;(Nwb#6S9MTgIXTIs}x%8}Y2xMiFu!=&1cn!5#p7 z#7MayoF7+AC*IQ|_TDFjcx3)W9Bkqf9;0`yw0G>16D2y@@Yl)EG6UkIq~_yb9tR>g z{gU{s<$a*U5s^f+6mER7MZoEOHS*bE%F;}^q@+GX${kyb+0Aq5w#tC$>Fio#!HvT=0&9y0Y~3Jsi)8HAbmNSqZvo-p?}v5AeMn`?wT!B#V>;{+1La zPD|9V2~Wej-dl#xX>?t#iV+T)7x+*d^J=)Wun1KDh^da6Z=WbhJTBnZnS7Sb_P&x? znTNpolAz|7UInj62H^x5;5PF!G}9H_>CK(Tfl;>7Kp_m_W}j7&3vPBT5~53oEn(Egq9 z0ONRP3RZ3?T=FzdAPbbi5{VE}mca$E zfBYU;U~)0+bmRUfh$NkoS_`nVM>^V)dJ=&p}qmtb9N7nlEGwWpU!SojKfwOWf5Bg9O8(#Z!}isjV>) zRY8)#I-+BQWXktCvy3@@|A!V27@$q4gf`R|j(S=<9%hO5X)O=r%(H@awzsE$_6R1X z*N147O+!wpE0979l{CE{hO};Cq=1d2V?~K%J1n%!5d~gom?BzTSY`-qYeSVy#COc3 zO$lMOZa$k^XW}L)ILY=k+E#5mkuP>`s82u%Feq{r7R}6~TBQXtpKAyLRYR{gHS4k6 zxc|P!&*HV=(${VI&pi6U`V#rdd5F793vRMws-0Z~+9sJ(YboM8RTabt4?;`Ma6l%% z23AK!VCS{rO>o8Bd_K2p5&{(Ew_PVJ2ZsXXVBKT}1)@~9r+nWj#}eYForknalS@L{ zy(d=c%x(z~i{Z+`@KZ~HXIncXC_}Ki3_6Lm4IFY(5z>B*k%FdaxyfCUNO~SG`rc!r z(A1`Aaz=d^vMg-2%+rl3J%-9cNFp3XCoP2T*p&1Dc<~;ljxa!5+8g9fYSqHXF(8u;Qi>anRTU<;inNSlt z{ftnxt#U{bdPa4H#Io#BXT0+*StuRx>Y$`!2kUZP+3hs8jw!WeVs{lxLP#xcY#d;& zvoz|4gVN<}&**^P>@#A5$!s8TuA@c**fh>_dxM>!43Hu(Z^HvE0+GYrNKoDQ8a}9< z@WpGBsr7~3>&`Gz+Nv>Q4y?V6n8y#&u@A+bwCmpfMx?>`jmNzewI4cc=`CtxUgDp= zDl%GIyWIk@$J>EzgxGn1>OgYDkY=PubgZq#@Ui8)~ zUKo%i`kq$0fAxMbtS`mu=5>9Hc|`;|?R`Mo2Vq3u|5xWS2khIKa7adcu!C_MVWWXk zgzml1iTy=AO^`!`qp~PrB#B{@Mzy@?s%L>Fjxg)+qK+G)-J^|8ewf{UPHG!)Ax1hB z))PS%Z*R5tNu^#xdN+o`^IS}JeU)vs0B=`DLV!>lc^M%NNlU6OnYd9Y8iFg5c%12{ zwm^&QHB6I@Uzp@n{ET}p>|2XMM@rNqEZ=HEKDInGUeoJ3-hD?s#5$=>? zyt|&gATf6ZPh+n~ey5wgvuw4kQm(wA907cgKm1k zCYgOXC9H=%U3sehP4V{K2=qDdfQ~=c*n0PO9%eR(6}UzY|K>pztT9loV#0xIPi1QR zlj$Y@VBvseW>GvB%63>S`XZIh*OC3~4Mz6B3znO2==xW^``!^aZ?3wy9E7&`B=}_8 zXdm7!7*bi`((Uib{H${tQ0jj{Zr>TIf?O;eCt1VL=}UE+?F2t(Jj~2<(&Sh;!*2f;m=Wz z_Guaqr2C{1d{UV#^Ycle0H$vs!kUc}WM`hpqLCodF)Iyq1^j%58&)CL+b9Ph(-$Ql zv-m=^v!-cD>`fhS(=w;8|8)uVxGQm$6s55zM;%{o>vZ>h-TN??7yq%P&d}8x$-^Nu z!QUGD{sKVEbNWdTIhCD+*0L>}n2JtE(x41k4poHP zi{iE3=KNOzJ2oB(2>S9TSQ9VP!Z52~Ay!lGLE`gcfX?p+yG{4HrDslbp(`}FqCW|=WzeKArg~qpk}aTq0S@CY%+1%Qv#vejFW3az0=4m-{$f6gx2F?pXeNI`V(^SXU0BVZPt?9l|h{K^mVwBF~tD&H9? zW5-{W@E3yRQ4Ztyf1gWcJxnq3RKUv81LxAX_HtaFd5tDZC}w=*5~>geX>X_tcP;d zX0pNnzz;w*=_*Sj4tPh{ehb{V&2S7|W#@ZoB(i3;8B)pIhy1o-0DWp6ixbTu5uSqE zoxHHG;lbKe%|#d0tDBpSMdmvBW+pzR%g`NuLGnkTU!*HOi+O01H_ivC+`g0bsX?I( zoH=JQY~PEq7b4FgP0F4r{LdO*ekvOBD&aB{P@&q^b@Pxm^CrppXPxE1?LWvtxJ8Lu zOqWF^+oOX7*%W4IZ|I}p1?x>ZKQMR_>bFKh9CqQ5KC5jusNzLftkDkT zJZc4cf0--haE;OzU(}JL3T?eC2Q5PuIb*Kfie^ zeiJ*4V`gT<`_Wu50$p^E5TQ z?J2>n#vFT5m?WVuhdk_8;9ec`gQ{j?@Y;+tOr`;Rns8VrgK*oJc z%LNs3yx#_G^0>?7DgJGgf%Z+=I@@2=e9_$TAVxatE({k_9ETgNk_A$W?lKJQ@R=~~ z0A2Qff5lywrOFwmdR=H#W+Z`piO{iGY~h)HBpU5l`+;V0*yU2pmTaC2))YN!Z|fH> z3OdNOn`4XTQLVUtMN7}DB?|%|pt$fsPF+8uwuVsTF=0k?sejSQu#f+%(7hPQ&^ z9OS4hExHu8>9KXPx-A)xk$9~1pALxTZRmhPAltmm0lk~KM9REdP&%s-m`K$C7QvPk zg}j93U(}xE-iyg47)nIo{mi&tPO20OzsC5@8^%&#zl~9;09HL3F#TcBEosrj=~R)W zv6fD76XS*P=ysY=P{+S?O$l_>^OTU%(^b4xNM1d>%8-+}KQ|zavh7cjuT8N5?EUUI z*9A+@uW#qYsqJW9oLA#OU(FA_Qu2t2W>28<2m0%#teu)pGb5N&WUO56tm&C&jYuZuS{O2 zUf&MIHrH*~**bVeQwM!p0JR8W7;>|i?--1R#08~7v$~y!03Y03zoy~r5!ucfWx+#$ zpC?JBP48(-&qx61S6>a0cWS_Q4fxO5A5V6~+fNzmWhzsD$Fd8n+Az=i;(8(;dT_Vy z$h;ozuC5>YF9D=nVdR(K32zI3M#-GDlt910ZiS1nt9NCLU_Q07E6W8xZK3G)ED9KP z(jlEQsn(_?1c@$M(Xu0JSm5X*nUV#i;s8^KXvQvA5zKF|`6m6tdDitt zMNn$6XSP7ZK9|>?7GrbEucyI72lT8^sM4AqETl#Eil*ZoduhbQ9 z)SJx@pCpUL-8;}#jA0nkHXqmvF_Oq=#ak@a6*Mt@qvxk9tse|1o=Cpnn{FD_etofN zrxK6@)jDTIMLEpr18%z)T!YTw(MwK2(|eJ|2^R4DT-bra&41yzg?cyIB99gNOf&T| zN+nmAqm&+Lax<+L(RTkOadRC{A~yuwDQIiJlF-u zhz!_X82qGlu&2TpZSjV{YA!O!w539wRvB;6>#;3t-|G@X-6u_$|=6vyd%IJ53&m#_mb}m zd*a+FA`7kN`fN&2Jl^Bk0O(7vXHCha@5kVj{?^qqp7GjNk7sBBQB*a$LDah**p5%O zb#2E^S~EjkEjx+|XSwqmrRP?A?xi38E+Fsx zSNy#0Dh(+ADiillAH5yxh5zV0^af^sBCg^PAvVZn!cBzBm2Eb7Fr2E-J^PeJcX-iC zMDtoDNoMQ^mEJ+nHmp?o{M{g3_e*~5@$}!&cxuQdGdv4P5G9DN>dsT9;d^9=ECDp3 ziBL}u>5^mkNWM)9n{R8x->B!C!Pw=4{&1(i!bqS zN*-a^n#$hF-`~r}I8JwfZWM)H&$FjV$yF{ih?PgLb@-iW9eg6oz+$qY1&AjHR?##W z$j02UrzXmF>e$(*!ckFeri?61tYI)hudfc)&x6K!`^%XrwUAp`Z}9-5IN+*>bhsANlm5zg*h+no%A}K(e@!0Qwl& zB(1pF?&vUnBOi7*P5T3W1g?hE8X1OWz1no5u1oux8XL9@9;#jjaN|758a71AK{1Wt zLLy?~a>Jq6i%fBG^5O9{c3!ywp*3$otA1ErxyNFC6gIstK$4T1f8h&WmXAPvsS@vg zA+zx_%6XnMK7wS4#(U{&>L(CZhyf{J8fJgm4WXIbKIj!Wl9Ol&pFg1>4)G#dTP%CM zQdLEzNKoHSXL0r9lz)tVm*Vv(?J zpnfZi;SsokJAQo&@&-6rygNjDMMGBiHiv%T@U`iLM$*11{d$Pb zmH#q#Z+7VmeAXDX1Z`BfUk+LDIWMRwY)Xn^5eolh4b!u#t$?Odw>{PGA;4Sg+a0R4 z#{IG=F3IfHJn(&er`4jc9O`e0h7@yeLUD--lzclgLETs+(>)Pnt#9v5@{wV9J<*D+ zyb1e!;>2=+MF`@)ngK<(R&u`qm`E|C^pA4-l9=NQfMxn1+}3Bx!pye*UHz%`eC5Y( zw@Go^DRU5Wy*3LYvBA;=mCDIu9shXjkF`w z)omhkAh(!{9<{%$Ig*3oJ$ij!u-obwsDI95_M8VN=*6b0xFs7{KEvL32ePqGsb zC||uQtrB{qUU`)}-jbJ@#ex8NXforN=U~DCv-EI+vJLZ|z_q2zu1ZKgY)y>$uaq*! zJPepnO``9N=c4A?;S`J+h&oa@wz#Xez>`aOPgP1D;TM*@L*5I}i)dcXK4d{tH^$f; zA$|_P=y&yYnvRIB!$k46fmqyq07Yq14zdVn zXOO_ySAUG`?970zkQIQ2qm?Wvij!se^R_yy&-k0?>_=6OyAkST8)SMQ5 z#!1DVcNQg#8H%NOEt%K+yT@~X{tl^=NQBfo<*e!n3t|qO_CO&64N85*DvYPl8!W8;}#ciV>aen$+<@Rt*Kiwb!$e18DjkTaFMLm9f(S`3-184F`G zZ%Jk>k8=@wv=PSZHAkTX<$3q%3~Vi2GoAQ3gB)bW9a-oBm|K2mEIH`6CnYQOoapSt z3=2tDKWedNDrg1AZioB{I!Ph4@xJ)E4vNu1i9b~t&@Dxk#D3-88tXYUzEc4rdlR} zpFAEtpXn+dc&hHwer^d427s^FFlJoRVUX4S)EmyEB%=7U+EA&-|CWK$P=n}eibRcF zgm*MMq2K^Oe6dYFY3wVdzRpO`s{wX?k2o4w#MMkk5F$zhDjcZ#LE|=~6h)u=?@?1I#9@T$vKi)w3X)MK zsZMs2xMj>zGmGS&01IT*IAcs^nnV{F0_ZHh4c;|U;Kly&-XzF2rWd})pxpg9w>1WO zFpQ+w1Ww+<$lBNR4QA0zZ`43cllMD5OIk=ypb*J0C?Vj=IR$_ZTzWPKZ9xmR%cc4f zfm*h~*`jY~BF|IqoevGHt32LRUFsBcLK`KfGVVkNyqvxl{Cvt+F_#jz9x-{<#>Nfp zKQ`Av$mAR2I^ApIya8}l!V*FOQcOL<+1+s3vP_NWYhgArmZ}cLLyk)FlO!TX(TbU4gT*pJeY^!<-oAIsbLIzEQ>v(SH@Ruw;yZ`WKJLXJ1D4zLxx0MRpaT zKZ9b_r$wwa9AzlLx+b@ryd*qYg=K3L(<8e-SG+yVZW$%;*BjT0+*$}=XNtO)gq5Uf zi5=1P_3Y(*=#|_KHwb_ZQ-RM_RWFGyH~H2<`o1T+1DJ@s+7pq5eZ2?=-n2Q7g}qq= zHYG%^+NA&JBTR3hh2b4dEf!i7V5`X?U`pS}demTwCPt#a1|{v%SeYRVhX)5+x^m*u zdmBFWJ^jfMJ<;qOAKeTk0IR1s>TC#nzH41CbBVDD^7MP_yhVlop}HnXQ@u)KEZCHD zJPSVL1m@NSh;isLm!rh?kgwj>`&5m_<3vL`K2XA+Q2b;ld9Pc>q{tu}mzFt-ab6** zv?lOB$fiW64mh1uZr8Wzp8n{<98Zul>Hn$dO%^P0;6Uau#Gw-Xx)O}`VQ84LUfsUb~1MH)wu!mQ&KCBDB zOGPBz!qtzsSX;~kd(3r?`8!sT6pG)==7DMJ72Uqg&zoDcwX~`Rp|!pp_`8Tu6!!1~ zSbQ%I(>Ph~WvBpsrBTOAU*+to%~G9bRpR9OR7Jl!+gYWg4i$QcH*i1 z(o3JvZ__9uPNIB^pk~Ndb$kE2fP1t$fE@fs^?~ibAY1KPm$Ao^m-6U%UVeUrdR9wB z!v#BOQhd{(V&kX;?e?DB%|+3&nOJVab>P2ya-N-st5$}ydb0NfI1o3*>@3C<|E@4I z_@v|C9EP8F0z^kbtCs=>8hr&(ZgVNJfwL)csJnZ_Ubl=gly$QaQdnE}@3;%VQ z5w$&?jpHiG8j&sL5GwX%NtbN=A1MO5d*=WKH&d^=2agUzD#F(nMGYpyh zKf2LjDruH86^{%e5U@IN34<=*wPi3FDJBs!`oZDW^!yEBw_DArvQFy~z%ATtrUGk3 z16xRZt2guQFGx$n##)w7>5``IHnhd+GZJtFL6TKg+m-o)4d$t{OAlzU=bqF!9n54L zZ%t+xw+Gb3eU@hYfjpr$gdC8yacebCoW@(dRy8VhUOqvx`D2LzM8<2Mb!omsu);|| z@gsom3zWS_8ZxH{&kV}>0P4prq}Ks69%c*Ck^Oi0NS(;2r zQ|G~n;7wmM83}>YuDiplS;dSxyCv)2fubVyi4`^EVB?%1O=!o{RH_7x%wf~pprKx> zeR*_yX|#l$4gDe|!yc5WR;;bZc-%kyj?`&lQ#Av}HdF$ihVuM=0CJ6d@_3C$U!^fo z854>W>c8SDdW;9=q)SLmv+^XxT3Q*1utG%y!4-wr)CB3`^|it6s_9Y$6}do6lUNuG zZ9_}Nalg5;$p4v0bPIZQxT&5_hxc=QHDvB+f%PpV7#2Wjsz-w=gmtx<+4`6+w4-Z( zFWp5r&X% z84|uXnv@BCj+0+uY9C8Yf&JK2RD0 zbZk+$CBsdo@{C4{AS&=qd1kXZy8Ka*m-mGlwjyfF7K2_HD5fBNM{=1RMw-+0rxwK? z`uF$h$iBf|w&Y$)52GoDiQ7etRzdqgPBpE;Qy9r+W>awVPe+=TMCbK;c0hJ=KQP~u!X!M2$UX@D zZd2kMdazvuDK3_0HjQJ>SPC{}qm*Y->$n|j!sF=DyIf1@A{JBO{GH-$$ z>&#VD7n9EX%~2-Nbm&s}RAvhjq@kSa@Ms8^$T_K{kWM@*CFt2`TfW61f9ipbzx`{8 zA!0T`Bvdw4`7n836d=ESaNTUl2lsb=Qf<81q6dxBFS!nz^ZDYE@J@@jv=xsRwxH?@ zt;`|=_>;U5KU$+;hs1m-ejrFMX9VZvUR_-XydO-TK3!!)yf}0}l}0=b#lgE}i?WkK zCct%a-Ae}RRdV?%R?cPv5G~s~smiYyJ%?~#TAiu~%{+bUtV#t>d9FO4qt~H?CGk*aMOD9Z7j>5pcOD&Pb zaSB0vf~ojMjhRqcw)U{w>0VIsHB?u7>ARK7XR#E)ok<)pYZRwZwv61M#->jW~sq67LKH zCb?3L<-HLfW)@MGUJH+fOV3>vB6diULrfQald=722Ndtag$s0~#jG~Y+B)vJqs6ap z9j5OJM=Gg}@z>(`6efv}5%F0!xk9PFMHpA34YduB9*$6K&|i%a?5C=Km3O0xYQ1_% zxq@(&erX#{3FDem@R<9%XPFN~!iPZt`&7)Ut`*Y>Tb(YzpnCL6ocZ@icJTUm08HDV z4`Rb@kyCRQy6SBKGo-qbbuTsfFlli4)b2UW@Ys+auZr}?n=Uu{!|&?ff^Q4?;ipA; z{?3!RgD*s>&u~{C_dQ>^>y1?s%om74-;9EF$D+UQ+}Q8LR-9yVw?xU+C^Z6l$d#>L zwEpPkd0(8F4W8qD#bghui1LnUyUL;>$b!b(uC@|NuYOH5NhO|m91xY^SkNfLLIs(} zjzk6Lhcw^gsJ?wto&bk7Il*1_kZ+VX1>9vO2tzctpL>3P*v`K< zKH3Z1^#yq8i_{IFdU_hop;Z8?L7OM@#w*4Ka0_COCSXNvB9B+NK`2P|f#92d^(Mx$ zdnD$-&x_8)hfnO|CSW!}b?U@Z5r)RPwO7+lCm|f`o>Q}if#lka2JcXaT{`;Wr%G=R zNJL+ake9pq3$3da3yX9M2qusbmARp2(+yjy0)@^dv~K$aV(8zy(g1gOyb_;^rDuG2 zw|(`)BF=KmRNXg2dg5}%)Gl;Zst%_>2dD@5MwjL&yXO-%GM=W4@;=J2Xb#eBKsXFE<%?~S#s%^7{*PDFc@N3 z_yghFip+(uz4%nk*FCl!V0(@4k?KBy+@@;epE2nq0^@DvO_*-*<3C?!zjzBNVh zh?q1&>Jm;)N}GtSzt+qb=Qz821v@$3hqTW8MEdFJi3$r3xY(DxG#A?yK6|y^`0>4; z`TVVl)=0Ax%kDBK!ty>Em$c$PbEiBIb0T9Zn)w#|cMWFBNYkXK6eH*{vIt6_g+W!4 zjxGu=S2g#~p^hT#S(uZ7lz|2Gbi4|=@AwiMDH=GgDuPh|v?5I-ACfh6ANJ->m8#+4 zh&oUj#X7765;JQ^18a~~g_*trLZMC&e#VTSyZC6)MsOZ$?Rcn?xeH>P7DO9~ zZbTcFKg*2F7TMrQG)}>vbU#edjKXp_B=1aLJ3@M(+YEPltHpzBU@EUyQDpZ&kOXB@ z)x$tYk(ED|jsh=3wih<{9X&c|qo^t1l(I9E8V;OM7btsB^Dj_`(|R5B;BQJd+uQTt z7@F^g+Wk!UxPe-`qvD)>`ukrocQrbW-!Z#|`+%xba48wYc9o>X&8s0|%E70oTqzl~ z*Ia<5DZCju%JJ!#($btUvQ5qQiKbLOS9xzMu2R5-vD8q633H1xRfC!CemsE$j9qBJ z+tl;_{Qbz$9-2@>eB)ldBcVgVnZ_jxJx~*vz@GODzvaTp4NT)%;IEOwi+ws{_ha+F z)p;sUvG`^3&9i8Oxj5@4O1H}&;nV&5o&fhPVS6Il-XHvqb>4m{fmj)~|;4r17YH%iTUfSuRGDRvoQK1EU2;+O_ zPxIGe1{0+~NaI_-aqtDuRvJPxtA?yeGrsB}ue2#&v+2}W4I4hrIcZz)t0s>DlI0qe zm|+V9sIeCRhCU~L*%=^(9+U0m912laT`0M=3P%9zwPygw12z*f1$LhvK5_dlmp`(k zVc;bOk{IJ1Er{m60!z>g!B<}ObE-zZOeV;3I43JZ!nL+N(Nqw{ElF#+uYRH+0M*cE zvCK_qX;4RG_D{z_R`jjd>O<+wvwo|-L z&`%%#dV(%{a?MxEVN@Ckx6|c~2yMN-{hR+%$XDm9-?)Uv8)S+^-vkYmQ$TU{XDZc zxS!&g0kggK7oQSFGqRVOy}$j~eF6kM)w8c8?su5r3*W{iUZvNxa6Vn|mNvAt*}B1` z0_@lm>@e2+KD%Gx6!;JjK)dSE`tl2nXQLs67a)z#M}P4t7T1IP`C1VqA%E%Cv7-3q z%#*4CJNiWdIG62@0OwKr6&QYr8C$sBU9){XxIOj0*xAWjqzGlL{O=#fp!`JZ z$K8xnUrz#NCZm93728dw^bt(j0q(ooe5t#IoBn$|yoK!UJsukD8Am&LIIKtw8Nch# zSdl3q^<*|Rfrf@ih}c~m)*^^T>EIhMCv)4m?gnFo9yZ?pEB1r*r_wY9WRq454^rcn z`slBqY|l(;*^5BH2$(*lGcJ0{%N=1W9+*hEO-^UwCrp7`0pD5CB6R= zo>VNP!h+42H^=R~wj)j=7rE4%P~wd=#rszk1mK&jX0jq8g$NhVnJ#|9wW|Kms=-3`#nFaL~u+^90f9 zfUyB_x)ICmbPKjn`|Y~W{j+bDq(|y=?b_b;o@^Q}7o?82(Aa!zW!#9?zjLA#aD=Gu zf0x`A#C-X4_$g9%j+h1rb9msEy5U^uz-Dd7s~r6PM}UzpMHcKHjKYyxETkG-%Kn7; z-#eQ^{`1R`G8Lj8Sx~~S0K(V37qj=Gi*AQx2daNbG|UNk$sB_TR2r1 z5#KJx8}X0KPLK8;tdFL8IPwgt`Fd4q!dq8E_@zZPqa`%H+I0N;v5KNE$PDAeEDnk? z2wdN7*YUIGcznQ5eR-N8)bIV?&KFwlYO|q-Vl?np-nHLvhIGHcE)wq1sdQQ~qi4#s3BS7DFB`-hV%QM;Tk-qJ{?=4|do;fE` z|KF=14^^@tn5u#QCzHF>kns)=Oyh}VG-ds6yp=}P2QVAM$KdHCJxE_r>#&M{cLn{6 zJXK(J{wZeZTAr5LUtchT+~w_JA^eU~+2aq-c6wYu3WkO9{oMq*0z=^u1yzU?W0E~V zBaUlR-6Qbv0;!0*y#$Th3D#iT2QFB$PO{d@s*)!NGZvfK25rpwS2Hql(&2MZEOnrT*RJ^jQPv z+V8AS45|ETD@nhuyG@G;5_j@GR!tE~aJ0nW-)?;-AUw|>w>Oi(k$4iJnJ@&|O-VGP zcu4#5)}MkG@q5RS!9G_*^da>oH2L^dA2j~}D^@EKnlyYD@yr#jcNzw&1^spuCM!C6 z#Zau-#Fmor4Uc`F402@R{Gb!R(45>Lq`JQHK%?mrul)zx{i&f$n+>4_LW78v^lnXi z|4W#SEzJKtn(q&Il{i45cb{acp`1%ppQR06DYp1I6}CHa8cP^2Z&pcJ07aGd zl(toPZ&Cd>io4_~6lfaGgX7MIb+L``n5s|EY_k;JeC5rq@K?0eJvt^b7S80si` zujcMk6}T2jR8)-_knoZCp}0T*?G!!hf%qY|MD?GV&K%Ev3G&9(GZ=cYAC>d47;x1! z8YvH0R5`R&@L9V#z}zH)!RMZjrtD`4C`8O%4DgM^Sc>D-E4)!C`Z~5yJ?`B&V-Qwb-w4$CJX)l&jMpT9;psHRtr}h)G*fKsR65lmz}rE z^5LenNQzI!?l5PWgJ@KrOPGjK>22G)Tr^!SB#ZGmNSlPN+Tw(+ELNRX31>82prTQw zxLe6q;zOGI65=KS6RqHm#wDGE>0A=h|CI~k@QMY=OUOiJnDfO8Xph|0IhW^#Ov;y{ zqE{vI8^`LrYlOsLNS@H|))iAk)W?|Bt4jkE?=R3~+2qRek07{oQsl0@y2c{bZsF|q zEVNpS%F=E{d;jCstv~94wP@hp95sUQCIIz?nn~ql1YpnTM->$aLhlhoM9e@@BTGX1 z#!Lk#n|L9xs5>~J*j~3M*&kA!=ac7K9AeNN<}D;X?df%c=T(M?R4zlaWmK?E308kv z)GjSXdIh{*>>h#TN#MGp0Mptas@Fd9FfGlMI5gH5^^kWaOiU(!%=2O>S{+?c6c)^f zNszb!jjc7Xn(<;>YTAJ|^uJN01T=(RjZ)OpR3Jsl^bwsGz>$L1l-@1S6A=pdK0NDZ z0WuzJ!y@u1yGKQ`E~GX2aB9P65( z)0*EFv&r;hQYA5_l*seUg~HaB(@FYB>w|#sKb(nvSFG9=Y-?Rp14f?ho*-E#RAXgm z4J*+-6u!O1n5bWVuV@+3uA@CD>-kGuPQ-jCk?cvnlFN%hVA?YVV0(LsP(C^E?FXgP^}|;HrH2Si*CxqnKO8%4-Vj|FH=Vh-5#Dib2>!fyz!Wgr0O%_40o__A*dmiVrF z%fu_)#>RryxH)e-`cv)YVXKTQ>#K5w#ByRANpu>@zVnS$$TG+q+K4g~iE7pR6#qLb z;lZ<`9;)tN0{4n!kS?+N3Ya�eFVa+=c;^O4&_ete?2i@?c>(_hcpkXK!+I?b#a$ z+he2xWgLGFXSqg-{ltW5>3!;U?KOOFkE%jY2);W5X!l{^_TNME_mPJfi`M}lzb_WM zC5br%tW9KhHfPLHBI+RFcscR9*`hP{LQ*I(hT;WbJpNpI{)z3iE(`l#4V%Y;dm@UV z;4}5TNrsvxdZ{s*697Cg#q)Q^1b4-$NLfn}CJo39%GF4kaMD<5-{ir?3UzdTey+&2 zX&ok*`SlSQ_K&RvS&bp`O9ys@@pQ>tIDFp!adcJzZFE}{#)G@NySux)yK8YN4kfs| zJCx#5+#P~bthg5`?ob?V{`;If%*jm7?6db;-}-WZ_NgZv^uR>XR~={U$Mnn$!jjCd z=2Iyp_V2d1QfkD!0ln*@Zj&ts#H0QHGLXSxV;Q2i@XT?VC%_b_*LL36%BraKGPgsW z)_f0dlBzX(VZvxZ%HHkzY^x-!gw+A}iWZ~uv5AWTh zQdwz(V#{RS#=@Vy47?w({}NPTKfUW7PBoQ!l{BfLB zZv<8E&((8Tr&LwgomA;i2A(Bch$k7;jlmI%0mz77b}6b}vZ1{@Zxr2R&rB0^Y>Q4;tSHeeZ~NtMx(@UB08_{PQdk~e5h2e--*^IRG@;!eZAr;Ii)mLkQu38{|anfEIR!?Y+E938b%Va zjQg~&;`YYSoE@M{(pm1!yS1z+$0X1584a`@cQ$JODNg3xP24nYX@s|5UWfnKfjt{d@V2VV@OILlk z@JBROmL#)T$LI~$PFbi}VCZ-$*s?iVJ)dkH^l&c;tOBHe%>8BEuYcsZTg_TH=Lgyn zIqJGtso^efW93g+is{OaNbj7@!b7K0zKMsS_+X(H?8oH#kD>c7cbo*_lc6kD)4;d#beKVIi4GJE?1xI|*VA|4;v zeKxzldgegf1e^9OmF2=$*(C9FqkkYOR<%Q9K{qFV5CcNQFI$g)8r})&gVobPq{Quk zTqdH@DlBqv*9iykgm3w^z@e$VxjHx>wEK*z0(e?qE=aXj*E*YVkd~xypH7RcCu&Js z%-!lP9yw`5ex7vI+UBd6vr~XAp!KW8Qa`ix#EpjGqm1uKeO__ndj5Ck0fHz`t1Z!# zN8c99*l*ZU;rJrynkx`@!ThO_-Qn&i=}7L>sp>wE%mz?o0iPb#z>15}m_fXTU4RZ)ykXtlbjN^O0*jTr|O2xcx8jjoTJi`IiWH<@nMpF_x659 zeQSK=P*zo|(V#$XHe9_Vs%33bDZ)Zwzz(Jf+eRt}3z=;fK^LN5*I&hkcbw0b&|3op zL*9eucfOVRCw6!ZAb+XDMgw!&=$X0U`#-AWS1|8^;7ATTbS?sC4?fHuF91Q3a9A;3 z`sHDQRORJp4!l#w?ZAUmJQWs~?4kuW8q(%!Y)azkpG7P~4+r1Y^=AI$#MeM3;6V9k znK|h0V%`>`=iuXInk1hwfCgDQx8+GG4NJ8`&pbWm@*voNh&S;Rk(|dc<*&C+I@squ z*dG}g3R>x*P*bqC43vlV3-XuR-AL;S7!(O82g=O!8DWKOhW{f&CTGXh{oM{a$vkG zlU3C;^C!_d`j%@x#_GjGfCqUsEg z?zaJB1>$bJkE-1AVwUvgFzttD>;9Ah^8EJD5{LsB@_{tx%@i^`CnzSHk9Juo8|L86 zRb;v@xUKj4`pVqLtSE`_0C6GAwMp!9#n7yyzd(|h|Nl1uOeEkMATB)`r4QYC#aSeR zY=uE7q}0%Vr}e#Rb^F_iUVuuvQ5L`mBmmF6)k(Pi$lmP<-LdTdE|Q$fY$RpI>KCuY zME79EC%`~YjX$C|m8h*&NrgyWjX#a(FdPcwb2+RsLwYv8MO$JPV;Cyv|MIu*iceDn zu>JIy++eqVb=$fB7x&{j!O}KE!<{aL`GOf<-F0SRaKJwg(wCk(DMk*w+tbnj6*o1< zC?-h(IUKEG>8i3UJ$s1R?Z|&g0eU9q>O%dwF8!UenKvPo&pG0R{C=eAObDoWh`S?n z|6<2TXd`fy8@2&sY5gWzu&y50o4f*Y%W zK)n9vc%?yDAt;}B(0B7^C*K}m#1Sd!ODedvhpBLlQafqEG8F~Rh9o_ZqeEVUg`;nNs_`BkY-jTcA2E-U{Fr1A#FB`?rGPz`vw#Aej;b@NEny^h!Fy#E|Xp>DI#UQgoI~vv&VKQ;oHzIt*SG27s8pJ5H=hQ zIONOSe*(-W2=%XNJ6=K^a93JWRELzd*n21cc#155< z@!(fw`WF{SYcj{34~Ez6+8Lg;lO0?{;!}aEO?Un8>Hc`B8ajg=qXMCYt1c62&%Hqe zJJXvKIJtvzvglqzY~lBT z2+&=K7hdy^&pW2!yvK#=S0 zQtdj5$l3@Ll5_W`gl~zXw^2G; zuf*`3ivAL`(XYN~^BT+Z0}NY36(H(=o6IIS@c=a+t`_1iW!doi9?`x6X)~?_Cv0=( z@FCss*>*?j`r2&T*vN1h6Wi^cAY+<6v6Y4SUu~UqCA3mu=2#a-=YI&g2ZgMo@S*!* zPZB$A3Zc<#g2pg8MiL{P?i$Y;;Kp)u{fq*l2U@ZJfq_8^GAp{m@b*P3@VMnyt&Fqh zxtG9)q3^@%DTV#brWMQE?Nq}b34zDMs|cm-p4h7kqp4-OFeb&MG3PB2(y(xTU+`t` z6@xE3A$bJz?v5PWHBH`rTV4}q@3yi!q~_Cw0`I58VW|uOqgHZkD2|Dm9^#}E#6C_9X{Z4m`u@$2E9f2fWsViYjJ4* zH&D}@9~Va+GK~#NbVfQU9|9u6dvWNdrvS5b+ye_L`a}+Eh(-hPYEF?FtaHaaGATRB z@o9LENmTa_ge|7aA%f;&Iw+G%%)ZZ$y3NP9y{faU39j|dm>cQJY9WOG=18(AWs7Gi z;=U||KHLAo8_DGS?IRE9Id%cI88cK?1w zRRi>|05LWOjvta6z=_bp@*i`;kK$nKGi1saeBt@P9e3M;zbmuKeW#)gsNI#+l+Z)N zrbJEgXuoDH8SPlJlNWrg5i-kIB-?_pr z!w=#Wo1VQnf5q0dU+!h?cmS+TN!Tv|>%i9KdXlVp$#|jv%0_Z<7cCb1Ie|(O84tUt z8=JKgX4{P>KhQQ+-w!Si*&z1LHq$a#D3k&vO`(*sT#3xKDY9?LCwSqxb8(4l;e{bI zIV&$Jnx(2o$7YZ64kKolSdv^YI^;m*rRG=ZleZ05GGmwvz)*xX%tFK(`1QfF zWv1AsW^c4!N)%B44AJvyf+;-f6Gjq-qf{(_*6lt0x8ieKxx6Y(dFaho7Nv5yg?njm4<^w zYA(%<6ACFdP6ngssqxbg`Oc>+pmS*fqX2@ooz-sU(?dqd>c-4!6HrXQ9+Gs+>!RH-qOXF|15-Hi&<_6J|0c9+SxQ>VC_?7Ghb z-tGQeTt&wE`&DcXS*APxUh0GuYsz*7+7Yn{!#b-p+;w_+5|;Qv$y5L42O_vzkWiCC z{TFs~P%MYY@dvCVqL0#a;7$GaX}fD_ecA00D65uRB(t`3(rodfaQ*X+gte}G*7-Gumo8joK0awhsr zvyUy@=)s6}?Fqg4gf!j)9KPTGGvylY3wr>r`1A?g08}xe(haZbKg^|mPJ_aNOS4LT zSW!G~_he@Aj*Egva)AszC%sd1OL>h=4UdOdzL(##?0vuI=tGtNIxoACh!4GV65Qy5 z-y_Ocnp^Xpvy6U(HUZ0z&>Ygyqrgc%#3NvV7PjvOD1N&iD5U}v={a(~j{R*uQnf^l z=?tpQ9j9_Bj*o2mg5YjWyU%|=Y9py9P?b9)&~%E1S?MG#*jqpAtMF^o?Hcgrf`djC z-QMk287pZAr|F*kmC)FK64Q3{5mTvb%?M%)M%;;7g9+!1Q|P7Q(cxP z0R@9sgy^V3%uETmf7fuXSqc8~&(OG8Xd#Y-jSsxbet_o&+;lO_a}c)$UbZM8Q89+H?W4sI`l}`Fcm=_ zIw~zXGF=wR%D82T<5lIP%!Z0Z&4v~DP7&Q+ zt5tr|FoK7;W5W$`!JEXK+d`tQzUkU7kR@A8oC)e} z7T%E;2FKf_qA**HK>D>uUQRo;)j1z^MiD(vUCiCXOdBA7-Y*&Al9|bl5RcROH!v4P zj-5TjI>JiHDZNC1>1oobb{7)$Q(bx&mcTlW3)9+OlaK-cby_|XTAF_PwZ<9 zE~0*C4H+#D$kYpk(I73PKj$$pg^~VFl*)RERSex4EL~&s@`iw05=-y1-PG`-DaEQh zH7rb)gsk!rm#7zT%S0g&X$4{J*5Gy}P{))d0Doq%@+LH;$N#vXXeuwBUB{P(+gB#f zM1wWE9J$DRlAXzV`DPY#R@)8j^3EX~lvKLZC2;&pa!cU4FR6C-;Hy!?x$Z4%$7170 z6~5Sq1GJF~$zC5V9QZ|9&u?vq#6j`jTEI$3s9mM_rUqAGSd^>+$ogJlQ+L{YuNfzx z(-h@CABH;|h$L{1VBBs%Aw-W?7K-4>C;8H_sjh{bUEKc0_&dP=j^{ui^H-AC&~G+L zD^k&aJ`CE-Dx0i|f$5_fl;uIvMp$a(U@|smuy{Jf7&E5D5*oBQ|+#v$T-PpU`483VvT^%k)M8Aq0(%8X^K1XS4 znR9A>1k}oP7xKn?g+u@@H2O^`?r=K|7bE>YB?uE%>ZZAl?#%AbYxw@R4DAk}*}eC8 zs(Eg~Xc-VaC^>L~A~-3(gN>f-&C)nPBA@nhB5Tz-s)CRC&-O;!!V|IQIZNV$51Ck6 zS=M1rPGBl)Gt2klv9M}v?G@S_(Ewx4O4;DAVjV_9qiS-vU`F&1`_F2n+Nh+DuRIm`MoL55(#f!!YNM0-&{4m2(O%M+VDE!T zqFj_X2P_R%docQ5PwHAOBAK=!j!c?D%op&w%!4c?$}T?o8CR(%qfF7B~)FV zlJDuv!z)5K8TKXM-Yw zU4}Pyo)B4kz5x8fg^ht|jLhQ?iZ-21pwvc68AoeM^<34>b`>R>&I%fKvN(AMckQ^1 z>Z#2%n_*EjTQW3PKcf5qFA|+*UQM6_k4RTS>zR>&&un1f7Gzy-LmSGBF~rAI>$&e2 zCcbxTV2(B*d?UnIUnaNv%olMECNrPz_SqyX^wVgMhW*K2TE@u#gKhTKkR?GcKH{%YO{qNE}s{)UETxB zs83^`faU5DPi~Uo$L$xq!T^4LM-D8=e-IJDs751i@TGyQ-DmeyKVxthPo#;sF;$J{1tfMA*0Sgc=apAs6VmpXGYIf>Ax z;HKBB4LIQ1k4D5BDuPwc7Mx^~Lv3oJwm-$;@^UFi+GB6N32qe-LEk9tGSoc)6CMW8 zwaCD0qXd(glI{`JAn-^|@APzsm$HUzjs^tq#NT_UL7Yv5J|hLci6XwV)GL>eF(al*XvB0%=v|pesflKrO6-+Jk?q-kd<>SV=22_0h>;&s6+;{ zbOBBpi`p1PM(~HkVAg6ZR>pZFeiLWXXsk*x6wJYomLA-mOQMI(4vvH_;RY)78r6j} zo9MYCle3i#;U|LyS?eK-=LPJVjWBBZo2RiMA=4Ng?1q`31AEP&yr{s z)(lO38Zjjk=^r7m+R}ge>fEkypMZFh27Zl*f#iWjmPUp~mvrhg7qZdJE^#=i3AWMn z6ZmoDOrIT9@_O>jGDZMZQmO|c0)#?6{55}H6ICcdKIgJNLs&Aje zy3PmJjg*>=K+u_YWNzVzflC@vBTSI}p({se_vNd_gT34G8qZ>8JEj^G0$z!2Spgnj zEQ&gucanU-kKjsWmrM>3?G}9Gm2xxzY#Ddwm+p{S@fWKBkOSAMBoLuEWAkP+$L%`{ zRIuNUJ`waZJ`?;;rmv_b#A2%=yKSUu<1;L4xLhxclkr6QoT4L7;XQMoT_$Et<&=s) ze>KIXGMRo#H9-BI28A$#XpX+nV9~gS z9EsD>23bj&l1bTk2m%kQP&_LDxw!V>tV(=(kYR`tANa9Ek@yH;^dVL}&pe!P0<(8L zlrE>`@}gUkn8@@$aRCSVTX~cKV?RVzVUkP|=xRh&6XYy24K=?OjJM^Ib^nw1Rr9Po zF+`dyhw8>3h;E=;dUa1L9CLLx)aEL*uMuX1`=f2T82pptCF@g7sZHTN-qVbH?SFLK+OmZ6IA+fE39H&X_%{*yw-1~6)E>D4 z6@C{)et*}5ZU;sjU|61mYb0`tl5pcOe8zz|`6TyGNVD4@q$%#H%+l2!ozdFbNG;V! znXl##2yQntcU3jp5`luWbZr{8zwn3T*o*yDca1cmHD36z=?+66ZyLMG2Wl4*mKwxd z)o_mm;{C|B(ebh&nhd+}99SMTZIyn-*yQX@3WIJfb$}g-F*fw>NepQI&VG>sWE_k#Y-Mlaeho5bhqnxp&eWAb{E z@Q(*6@YvRaX7s4fw&UWj*ZF&H#{+5;9RLXLXY3E=G4nH`m*0>=C@(KY4Ah`9`-sW_ z&!{4vioa3M(}-hcM_4PzGC7PI%cl>vd5uOi!vE|>-1dJ!%w)S5V08tdYI<=N*Ff4V zs3n-~Tx4+TpPu))8+CT=2blGerXadCXV7)cq*Ez|yba7@AY!YE~C;@bV#~8}w z@284j#Z$Cq@|2_jGNHGW9;)|cnAVYm0jx4xmW@QXWhDcew#M*ZyYjocD`$>+@@V z3lFrEQhx^01;e6%@ma#XXmNS+*AUIq?(y}HTm&Hn#EEK8EtsEmI6%CC&u_;ti3Pn9 z@Rou@EVj6}0pu&FDKPxM8QLNl3p8E@{t^fqp;9L=wq8D*G$1;`?=*??8O4OPj?dIJ~&IR z(wP#rFuqFsf6}JXa>|+7>TZx>?@Ex73jl`q-WFqFOU?%2Vm;2-=(u==naB<{$%rx! zvNC={c$l<>^TVJ8^pMdsg>cx$)`Y)26lMo(K8&cYx3=fEIe^MUTwC>o0(5&`nU z(roB7Qv0#*=!PT|qp%bq`1nf0k_&~b{MttsZVM>$Gdyo zKOiTuH8Mr{B93)N_A!lO4Q`itF1$MKRHImk+HU5WuWx0QHFosb|C&Fs55xO?sbdp< z8k7vD-;1V2FI!AXIaz>WB!75;HXTWT#{C(o*5`mhR~y~zW}9em181(KF<8Glq-@yUQf=Z^)RhE|9?)6k8g zFz`PSyIl>$c3p`A3cEpenHLUKB0ymc(1h^>~ENfC}4MY!+7Hl+(DEBd2 zlzQdtEEqP59>2I8{}tM?x4jSvGf9s^ZwFGr$`DBNJSIimSxOS;WT&z+mn{n1 ztBIqegIErb?t;uA_gQ010iNtVa5|sZQ@Q@Whm8D3_x|8y5DCVnjFF{i$4TDqEJh@_ zzKn&kZ@Zz4Te!+EWj4Fe(0>Pm*7NC9IkY-3-}v=IF8%usvc;z+q4^L4ge+Xx)KLrF z&47NopTEUFOY7cY=K;F)YT-yVExQe_dAu+KyK)E6DZ%L(l?Yj)9y@HK0hB-CW&h!7 z-gjtpZSkWJ5j}5UT_2m7-%$-4zk&8xsVmzMd`%s{ZCG^1qRZiwr^A+{zX&X3xITc2 z>fj9YF6r0){w@-BIA&wpOO+pDnhl%E90caj4G-lcS30DZISK47kTS-VtJT$8Z>ZlS zn(t`pDJJ`$&5QN7m9o#ZC-9~LT&VbU%yky(D~I`(<1?~icuxm6;gh*fyYJbU^IOz! z@k7yk#NnhSlJ(*1M!jI{*S3xVFpCofFCJV0JLO?~X zQq)R;-}=`~p#1F^n2}H36gngfOL}DlFdpLpVBIEaZ>JBBGh3HV3^3kcS|(A{@|AmDN^`KsAgVN5*>8{1ZSGh6R!W$b=w(*^T6oXlg=i!PW9iFE1qLoIM5~dCNiiLS(FZbphx!LH&rq_A9u;% zC18@+lX`S|{jdNr;K>pV5O=lk8v`?L<5?MZ()Px{>{TSmV@6>k+(ezIFGe-yW~@GL z!hm7jL+`$TZ#4RTgn|;eV$~~u_(@9{zG}M5GNtcIUX4Mvlhx8BH5U`tB8@msGGe2- ztTH8+7FufR@5GLuP+M0E*oFZEYR78Ks9|>N!Q{$!wCp262qz6IKt5S*KNtl z${^HpYMT`CJV;PUE?CiOqn2^ypXU~keS}eGx5uRSk_PSuejA?cC?DrYhU3#ID}rx` z$Ut^&B6fLtz-GM-(1N6A54o}kwk9!bN;QLY(RX~WImy%GBv>L9f_K8 zw>s`mnBMHDPu_@3ImS?<%5=D;ck1CI9a?rN45qc|b1F#&@R7n{enqA%9W4Xb-ghH3 z91ZQgwXlNB>EIC}DAW8&DePH9RwmKO3izB!*HJgdz~~8~9>F zJ{p_r|Fo)eU3jKiGHFWJtO`3~z=_t8ybbtOusde%LZYoh-fV@LlibY^X|w+83Oo!A z(b*Di^Rz9d(@QY=vS03eT@I_h3UGbLx<3#7CvsggyOMI| zT;@mvEr zQuh3QrC0+}B9pb3luh2>j0=n$b-LM3>ZrN|XK4A8KjKh=tcOaQ#KHQ1I8(oCDjcr} zC~aLSy9vwN>Z#qu3@=|170@21N@)Q3Y3xr8;8(&Kv2U;n0aOw6`9Z?d3;@RB;iw~{ zKZo95f()#C)at@Unu`N71wtZ{<+`7C0-E;}Z=Bph1(VJD`vB%aaE;OAUr0klb*_jH z7WOg?+mXC4pxXhL0i=Z;fJ8IcJ8+^I)-Ks>O8gILsJEPl<2G51fFw#rGYPhJ{;)%J zprRPA6iCcG)sQ?oC~FHvnt}}Dta>WKQ|P`lt)~UUrJHW}2ink7LYYeyc{A(8oWzYG z2<8{3hlsk^rmOdMW$VZJ7gTr*%WCrlaE*Ej#*F$+}%3)e(l!0Ow7%ecrwDq*y`JX#ini_z=YcVSpK??tj*GEkRZ;yJTx5O#kHFs zho@n~XTBoEjr75-UO;)Q2WJ_*mdqAanKV5>+qTzv|3J{5pE}La?A(MEjrsx98X3!( zVzu5+t9$#WM$py=A>=(!sIp)FMTnSGx~bATycFCH8MUTN?uR;xZ&S5es%i*~RA}cW zkfNWc)WDF>7(@n~+75<3yPXd`E7!+jvFOir6JRckSJV*kwo0n8SuaYOuC7g@kxn$c z5AG`OQHIhwoc@_L%lmb@_Uj4wwQR?WNgeBphQ0OB6>pUP+!rZkNG|A41&EDvJT`&l z6lapHhIWEl=JYJ73|K*mqxI~_NN(nAR64dCmCn4fo|>q@nKCC{nS@%!7h#Tdz(Z4& zDBvyKsr{vODNS;??~%%o8l8kd8J#^_JakbXIB?d+ihG0d)&lDX`PUtYqV1Y;0R1(& zDfX7)@50N%SLdngwn*cd?{z<7mopIyfn9N~TdR|QW7NWXkrcYW89KiAB8VA*4S^78 zG2*f~pI|}iS-rt{9&6oEb~Uq2br=-lVZdslTuW^*4y28NI=$WFUEc9=i0W@SDqTpD zf@@8#^KIxPzM=iu!6{i_Tjl3uOJ<0rw^Ds*h3HXo?Nr{*Ru6$Cl1a ze9qsf=++=;6PHsBMUKkTMA4cb>FjW$&q{SsnouW4Ib1NDsWyLrjtqNu8H9^S)pdR?(6n(0ynY7rgut>Nat> z`VT+}nCbBRM=$%Zbxs74=bTG-Xma10r@I?T5NEN}Tmx2HzoC{iQK&Joi(pHcO$`Y{ zS2McdBT}lZyro|gs_%s9Zn$KnBvY!w1A zG9-i6LZtxRC(~a@5aNZw(@Mu*LWZMH3kmcO2JS1}*wkzFly%U7>*g!0zCR@_35EDBKEIIy-r&C=yhcXBQ-ELNsgjEAdB=EY0$;v$ z?LlOjBI}u{k1^1xRp>g~*)m41%**;f-V$Q!u(QA}PsvNK`5ay&T5Gz7{#-ZYt#$m< z0n9;)v1`MM8$UZ~qDFI>y1s9A`%Ej|ph2oEA?74(6Qe5inFmWm1)2?dF>$9I%e`4; z4vpz`YsZpvxGjP*b1o#jGu`w2L{|&`&fD+Wj0^64tj|MVz2FcFp?vIPR_4f>#TlCW zf^mkAG&HzMx}RkSkmVneIA{o=8)XhRK#AlHR&tf<)LWP1)NhIcOjog@dKG+m1#F@C+)_PgxLSBgqXRm~}e zqqghGrR&p`qJc)FE(b%Qc9V4KIPA2K(T?X z_F>qH;ny9=m~oE}w>#QP6F^?u1UuNna+`Lxy09)C0BJ}FBKep2o8;%WE%!zJvj}oU z<|z7mp7e!R^0de%{`)TVzv6w!B?z%qvSpZbqF=N;pQc&$by#pEj7UG0Au4`h?N2Di z;w(g^FegKOsZ$g{De&S>FWSh)-05&SZns>mKrUz}tONGC#(Z#10W-zpnERu(m@SH~y(~dV z5w<1>MF0;|!imOm5046-@f6+@n|eeaK$$38(B2Mlqxd4%CHH6O_G0hgYNG7kZ^1uM z-k~v+88#=>^JFUP{ESKgh?rp;Z_HNOD=64iz1Ce3@1^E+6f$P?MRj-~XUSTq%hxk) z>e892Y>O77?IET5=8psazqkO54c8iiFGQF}s~C(sk?;^noT z{d#(AQQt^=I&7XWGTEXg2^!cS>kXg|2~D@5`~5XHXV!5JogrlK!-Xu(pPhEJ-wB!3}bmJj*6pse}<>|OJaibml>p4fQWIx3FSE7 zc&V#aJQoZI^1x_dN}*v@RX(~*O#tuZ)z{d1f)tGJ9~WGc&$)Nx$4M4X#<0zJ6NZOE zK!guNt`5mfGK>SomX)1$%Mqw3@F^&{kUnlV$B=D8(&-KY+p^5hcvsuI`#A^1rSk`M z$N1w2L{V#@Nf!-29X4fAF!tz&s40_Isdf{aEEat&D!0kV4^m0JQvxmtEDO$m1~aLJ zD`gGm9MLrja_-3>)y67<5HOQt7_b+6IZxn3W?JVv7VvARXiH)y(WA}SU*TY|N^jr} z(Dg~@`b+A8EnOn)WZDz_W%v_N-}TWn1wA1rDktq^R7aN4)h0eJUU#GVBg}RX&rpk_ z>%~G!@w)_8v)%DLkbp?PUBMfHuX2eXdixoBe%kjf@{_$O`5Q|w5n~{yaZh=sjnb6F z)yN~4a!s|YSG$BLRrtKj{Q4KZVc3vA--6+4Hj~4E?raRD{)M&H^pMs8#dOeHIWnFd z96cur|4NDUS5`;8Du(hIqjj@6LSwt3WX`CvPn7C%7K)^FU{L`q41?08gqxh!)(q|v zod)#UEZ?gvn7YZLE{_?5{HF|qUi&3sq^L&ZPbc2%lENsH0#bbT?7@Rn;$yHyHyl4+ z!72m@0hYW$8FMz;G34TK9Vva2=BAZ#?L*U1&_@ru_2<9wt^D2K;m(3|wy*6g6f3L5 z&XE~Q3D;kNK1CI&e0d>GaO`3*u_3XnlPT)8ZMH(lO_|WJK@z9 zZn`d#tcTS0zmRlobsx*$V)7cX3va6sR4hOe#fh>5eG`ZbKtEp7#qKPBPJ+?;^K((V z*8ac+n$qvGLCC9{OSHlgdJ5sv%0JG3BfKn5oukpQq7o@m~Tua$+;P!S-;g${0yUWaeU1bHS#UprR;IKqU6)FPaTNIpXY#E z2s8JD-d7GbWL3@wJQ(>WNd|Mz4Nvxd*s1^%_LnGBn<*LLp@5_MjBzM>3T;bSTeU9>ix+SAQe&xd!Kb!2CjK zsQ7;Hw(o2nkBSD>9c%`TVt6K{6-P=b9WAQNh^Gs-0Fw*^$-|gaa0WQrF>~qL@MzbE z?id4V5;>}xB$V`$6%AyB5?x}~Gz_kpidnQ&+LlUIW;J#7oTUTK-h&73%Qttbet*P|^`k{<4Q&kE2l-`pl4Wl`Vi|+DfP@$T4wlPhhL9 zD88XZlQAc8A+5fO2hC$ekh7I{;u7VFYxr+y+xyGp5E9$aGRoYpqPGq;;*~Gebas1a zpbuU*-66viK5}?dVdQIx#}B)@MT_&0Cuaf~G$0fB zW3X<(zwY6P?iA*~e>)Lv29l$7I!87&oZe$b#cnp(2>{6qtPQcMwy^C4p;hlSG>}qB zerYO?f1TjPl~KcOD4rf~KH|JqrV2cq|HaRG@Ncj%>(2;YliFa2shI(~0{-o_^ufGTn}IrV?jw$6b`kABoszN6 zWLl&q#8yxvFrT`h?$26l-P?=3{F8G>4lk)6Ms6XYqE+?G+ooCBjzr4Xg}hjTcPXN9 z@w}k)z%?F#3*3mK7$r+vgX+ZX=YwW-bzdMOwJ?E@Z<-7?UfW#x*+={ai7CS5R51_g*K!2_vM3N1?4o*l_OAE_+YhmSm1Q#3~=*=y~y9J8t9t`jk z-wo);R|SaKu$~7`{=1T6PI#62Rt2V4iPF-92;Yrc0nv=vpE9VM?i2suah7(Q|0w|q zc6C3_wRjN;AtnEk4B+$hQh4wVAT$(`5J+gb3QHt)M{3=eTZV4i7-*At7Lpn3JU9D@50|1&5&MNv&9$b`J{fi>BR5&GPn{j!6{!}T&`KFn97mO+n?Lv@B`QcRSiX9 zk=#eLK6n**>D}m%D`?@!CH%%rlezF+HaP@#&uqhWb6+nS?cA^KVV3rK=)X&e<}g4w zfL4FMfY#$vrs%9U5m!IpaG$!ZCiFcjbNgF`bmFu%^EWw2nWBApg0&1V8p8k z9KTfs(2j!>#{8tiYNZJrUGGt=YAsUltXGRdA3LU45Zj zY~c9b&Vft_ej6|(Dkzhms)48ak6z*Um_Cq1V41DRCLSjEv*9QpxSy_Wm?C;&%p-?E zJn)U!U8y%(JLGf4qPG+bL{dgn{$Bux0eJq(EUXgT3tSeG$6>+!z@6a!Olv({PH%`1 zA&z29Y6}EFDfKFa*Gb*Y13CEpCaOgI~s&If#t@V?K^?#~Dga~oeV9F6l zDU?#L0+t}8(WbS&?GT;!)4(afYeupAt%yai71)Ci*@+Zo660n+AJGCSqfhawZ@Yz% zU=MPy4O;8pjl->k2oWO00b@!N$l-=k>KtGNVi83Uiy(qnIvbJps_PHm6@~~ABE-ZY zB#;mxLWBr$K(O||ODKpCAwq-*F&H6%ga{ELM2G{z{|6%lSo_`c!)5>g002ovPDHLk FV1kzee#ig- literal 6037 zcmeHLc~n!^x(^NvqCm9{6od#7yoJmVLLh*mV3dGfEvN_>k`M!AAPJBV8LV@QqTs+7 z>WEepg-VoJsUTAjX&Gde2qHt6Ljr+!P_*rPw|!l2t^5AES?jFq;oHA&`t5J;bI$B? zcU`gUt7RY%Xa!;W)_;OPYUk%4O?6--rWjKV{Asbb@8^O*+NDwbX)IAaId&v<&WLt`fqXXEUj{^W0R2~V;X9P33I6mIw11=6|&kw^*z#l|-L3oqR z^9sTHh`YefEDjZnfgzw|1Of%Nv4tTqR%i^u5{yEi5O4$vjzmKdNF2fjheClDekOo6 z4kZBh&#f*Cx_}uN#=+s?;o-1wG>pZe!I8GMw(}S$6cmtvas^Bti4SFRO+O)Q zrE!%5hW6F z1SXe9Vv?zZt#}i_C>Whi!C6^hkQB5{0F;EpVxdT^6%uM|MMgr&Rupsq7HjQ~_Q!s( z3s}FEMGl=0-~9TIw571f0LJGC;cO8B))*83ge4)cP>PL}71ZArjf7&+7;77AK$U+0 z@)Mc|hYsu~O}XOL)AIGaf`0sm%=Gb@I4h>V-GcCp%qLA ze;^%>M4sn5-h@1#WGcmEVVM3eqWAag{0JL1 z3Uoe~XDSnb<^aXF(!0kE1p0zY*t&TyKXtH;7z>g6ly|X0YX|OzCp00$Vz<13Y)6JH zTB!!xY#W1ps;1>`3;se!(_M4JhI0oux9Wi*obQ~L9eg|-=6uiz%Sqj;Rr!6$mN!ev z4Z7PVh6=t3c_$hesva7zX8o9dH$UC=tHJ8=;ECv4`S0t$Y4e%8)t?6{*?;yj9t84C zhym>~0fR1TYJxT{TI6)*Kiz*%G%6YhYcWJFwBjbDrJnVOFl5%85{2J^a_1llEeVrx zmUFXNjdf?DOCjQ3cACs%RAmblw(H2u5Ad ztC_gjMq>58S(JM2Ei>ML0CUfp_OER$_4koT!`dW;gB@voRPTCO`cJA9>iK?lV`#?Q zQ`bm{;z+!t{E0)dv1f{%yPf=B{C^_!a>>YF#hHStaT3Auh&qo ztv?tc^sB9!4y&zd*_$;{P_PpZkE?kppCnxkSSp=35$j(VNo!u*d37>i?nP2H?xMPG z&a0MF`_<^QgOWGvErlS^nHbA09R^3#^lxcb8G$V5HyeBRtBs&K#)M6GPf5t)-nVse zq0x^vjMdGfE?E?_^3(&+riU88k&?f9%>qd?MVF%5roI~cZW~6D>D21;ViQ)I1zDm_ z@^mW5pPX?=n}hDw8fmV!D2z;8tw&pjFW&6F&ROQEOm(rW*}*anSbAgsi%kvQ9dQVl zyukjDpdmu{cvqj$1fuNHTVvqr)FT5Nlsyz(adl)ug`mtEMPglT>mWJdkVJL@k_8cb zolq?A(q8qtuQ5X)jhNz2Iw;59LS&W4#`v+EN&K065co#H{fv-@`;|=&2VWF2Cek5_ zHc|Q1c4A{_T+su1(RrzJq;FSyyKippNnukK9V4TsZ|E>f;R_9M^ft-}v!f`j+{j=? zEhcNDqC~Kk^Lko@UmmkZZ@hcSl9-ihYS^VhaJklpeal`p>2z+D9%#psC7oXm95plt zgZjx=Gk*Ev!_d6&4_lo;oBr5!Cv9tYJ=pei`0w+!(yEhIe3~&Tgzfed^Hc`+7g$p~N+VWvqlg_xa_ zG7wq|$%;lbPw#+}g$jeYD{@u!&O*zeOS}%n)G_&;940GSyMD0LQ}miS`o_^paW&kG zm=IfD!FP#H>1mJb9PYS9aJgPl-XfAk7Wb@;AE2N-BAO%j5at+-p~cGE>E3*&Jn!hV z*pvC_snM#^^(_TIiD%8aN8+7})J0MDeKMzVae{aHd;0#031ZvRg6XV6Xke=kAvO zOTErMQ*W+ja7~ak)>NB-|0{X`Y-s{r4`?<$wEiQ>3`(@{i5efMbZAx6Qj*R`8ZI!a z33RX5DRHsd(G{JM$E%OUl&Ci~i+`+l7=b)rY0z@dTLsnD(b623o{8fLhF7fZ6~4JTEt}P`R}I%Qd?QH~jaj++ zae1-jgjYBEb;_Fz9jkwp7F8J|%dDfBRI9d-{`e#PznaxXW%|75pLB6L7c(xcdF3>vZ;Bd&c zKv(+sgogAPzphcU#2$NmDSO#jZqmYHiF8HAgCTDE-VcW!}?nC zygtL13=fYTkBGTtn4`|w(Ni2(51goKw#$5|oo1s-VF*s!d({xQMmEH;6A(h07S6PO z5}9EqFQd}nikESiCr9oShhSuno|D%pQ@v&>6Bkk_TFBPSdx>wE&75q0UdQKEkw~Zw#hEZaOL#yKgvP_9pzQT-1}le z%MC_CY~Bq@0($clY7%m2ReEk>N}8`X)r}~G-PhJ5?ir( zvSl|cw&f=uRA6#adDT#E#bK+;+w=sOzRx?xVKx)4^0~rnSQAJ{w&rW?sjumai5MI1 zw)9G9O|Du!`R=*nfl19Zy~ciSQFHZGM$aRrT8(Xz8kIcXj{Ih6?;JakoRV=htIBai zSY`Co&2J!YNa5=9_?`L?Y)YBfrK;s`xe0eZ>-uIwSzUfj=B2}4UOlPqaO$TsIyxr} zY&;vUEk;dwg))-EO5&3HYVW5c**>6Y|JhB>5(oa)8euBd+(j9C*!B9T=&;T@huEOunTxkA%I+Fpe3`s{a+X$erd@or7UMATtm?Y`$i6E!OltzVKlFaR zq7f}11Ya?&Kh3gHyo(#R(Ju|MNvMsCyeRhT&&G@J+U=^N{CyU){n0{$*JZ*H10w8P zzTtqm2Ax9_SKZV{cN+dw@%)}y%XOGdc*5ZB1UsRRuMn-cnLfY@?l=;O>cxk$1|iXN z&o&t!xm86W7K?`*D-Y+rT0grNt@1?&-saA*1IkYIFlO9h|_w%nf>Vb7vz_Z0nPt0*X?+c1y*t zM!im|+N_PmBfTmpYg;PTTzO6Igpr(0QNdVNBGv6v6A!{)$}X15qGpD3m}h&`2hSaG zC=Ts@fAa}6f_m@i?#HD3hOsoJ{lI!ygw=tO!egP_tL2GV+G$I-F#v&O1voFXencP9A6&?tZFNalCN{=AAS?! z{+tUg&3-$HEo(U39#K>er0eqa)#u57sK)a*f!~h(^S1rdGeKSrJ(fQ{I8Y{W4vz&? zc-FG~+M4@ALzX9sV|A+9k9tct0g6;2k2?|cmNfnztZ?c9_EB}nA{0&b_?2uFhCBWU z>9P#9i7YNh20&7CcCL-jpC$-jQi=y(-KdDNN&1#+pBz~^WL$lxb>sCqif;g>G@Nyg zquP=JOL(%`tUk9rf974|cvg_PIil?=v10ZfH7f_nC|yRkHAsgXC))wYZzfpVpcS!k#v+7|WgH zUh5bl>7PQw3ob~#@s@E>KJW9G@CsiuvHWbQcHaH`G|O?ds?t_TMCMMmnP{=Ca(w7zleCdyFSDNCIlJgVmNDPWzS)Wgvij{xJi3AfvZGyL^7hGNf&})3yIZ&dB{| z>zbG6+!}HCekX7p(BWRIElnV_SNFMJ4KbHvjN}@MVPV!r0WI3uTPuCXs76w?M|%Lu zOMrTUX7)ZU?hntHV-n%{(NSZCeT@vW`W3p(-AVRSd{g<52E%OZak`XE?Wj8Tg|Y?` z-OxSNwA{~a^nzPMN*ctAHZxP#)LP6u7vGxZZm!xTL5{Pth;wbW-E+dG>n|H~1ZoN~ zq(ksR&JqnrOO#@xWP`Y=SyQhfec#(U$Iph@B@DilMEa#acaKjED}S~jQy~m)UcB$y z{c(9oHHQ6r3mEfP%Q5kp@-lqflB&AiF=Mor=GgE#AW(^pYDvX|&5qe&?FS}74Kan- zuY1ORyzQ!YUSXH0GG$jkr|QOBvg-fFt8k@WPgiBO#shUv)i-p@Q@u{0KNhUt^IXyL zbNH9SF{#3K4`y}#_XQ}mBu9fqU$0S~MBLWX>v@`gySCQX@R&JxEd0&I^Fft&+$6Hs z*%~D~4!pzoIQ6hr+1%2`>*U{ZtK9Z{KMicZmU|6e_Q*}-R-90A@@iUCQD8=d;}Hki z#R?g^vhYb|dD4u?W255LGuK>^$Yb;pRoA~$$2{2JtuL>|9@{umm);_Ziah_Tw?!?HFr&*64v6Qk?hw=iU4N>(j%G<0XY%3Pb2Ao&Ru7*yg_V{+2`E F{uld+v=IOR