From ecfb03d62d13c7e05030db450fe3be324f6e97b0 Mon Sep 17 00:00:00 2001 From: josua Date: Mon, 22 Jun 2020 23:35:29 +1000 Subject: [PATCH] Fixed issues with smooth lighting and added dynamic lighting. Fixed issues with spawning and fixed issues with expensive pathfinding. --- .classpath | 2 +- src/projectzombie/display/DisplayRender.java | 5 +- .../display/DisplayRenderUI.java | 3 - src/projectzombie/display/DisplayWindow.java | 54 +----- .../display/lighting/TileLighting.java | 170 ++++++++++++++---- src/projectzombie/entity/EntityFlare.java | 20 ++- src/projectzombie/entity/EntityTnt.java | 6 - src/projectzombie/entity/EntityZombie.java | 91 +++++----- .../entity/player/EntityPlayer.java | 4 - src/projectzombie/menu/MenuDeath.java | 1 - src/projectzombie/menu/MenuGamePause.java | 2 +- src/projectzombie/model/Model.java | 17 +- src/projectzombie/model/ModelChunk.java | 14 +- src/projectzombie/model/ModelEmpty.java | 10 ++ src/projectzombie/model/ModelGui.java | 20 ++- src/projectzombie/model/ModelTile.java | 20 ++- src/projectzombie/model/ModelVertical.java | 18 +- src/projectzombie/world/World.java | 1 + src/projectzombie/world/chunk/Chunk.java | 100 +++++------ .../world/layer/layergen/LayerGenCaves.java | 20 ++- .../world/layer/layergen/LayerGenEarth.java | 12 +- .../layer/layergen/LayerGenLavaCaves.java | 33 ++-- src/resources/shader/environmentRenderer.fsh | 34 +++- src/resources/shader/environmentRenderer.vsh | 41 ++--- src/resources/shader/lightmapRenderer.vsh | 3 +- worker.jar | Bin 64420 -> 66838 bytes 26 files changed, 433 insertions(+), 268 deletions(-) diff --git a/.classpath b/.classpath index 9b934e1..344bafb 100755 --- a/.classpath +++ b/.classpath @@ -3,7 +3,6 @@ - @@ -42,5 +41,6 @@ + diff --git a/src/projectzombie/display/DisplayRender.java b/src/projectzombie/display/DisplayRender.java index 2a0a8ee..8c9d649 100755 --- a/src/projectzombie/display/DisplayRender.java +++ b/src/projectzombie/display/DisplayRender.java @@ -31,8 +31,6 @@ public class DisplayRender GL33.glUniform3f(Main.window.glsl_day_low, (float)range.min.x, (float)range.min.y, (float)range.min.z); GL33.glUniform3f(Main.window.glsl_day_high, (float)range.max.x, (float)range.max.y, (float)range.max.z); - GL33.glUniform3f(Main.window.glsl_src_low, 0, 0, 0); - GL33.glUniform3f(Main.window.glsl_src_high, 1, 1, 1); if(Main.menu.doGameRender) { @@ -44,13 +42,14 @@ public class DisplayRender // Create the projection matrix Matrix4 projection = Matrix4.projection((double)w / (double)h, 45, 0.1, 1000); + projection = Matrix4.multiply(camera.getMatrix(), projection); + Matrix4 rotated = Matrix4.rotate(-camera.angle, 0, 1, 0); // Process all the light sources //DynamicLighting.update(); Main.window.environmentRenderer.use(); - GL33.glUniformMatrix4fv(Main.window.glsl_camera, true, camera.getMatrix().getArray()); GL33.glUniformMatrix4fv(Main.window.glsl_projection, true, projection.getArray()); GL33.glUniformMatrix4fv(Main.window.glsl_rotated, true, rotated.getArray()); GL33.glUniform1i(Main.window.glsl_time, (int)((System.currentTimeMillis() / 10) % 1000)); diff --git a/src/projectzombie/display/DisplayRenderUI.java b/src/projectzombie/display/DisplayRenderUI.java index df35041..0ade87b 100755 --- a/src/projectzombie/display/DisplayRenderUI.java +++ b/src/projectzombie/display/DisplayRenderUI.java @@ -92,11 +92,8 @@ public class DisplayRenderUI GL33.glUniform3f(Main.window.glsl_day_low, 1, 1, 1); GL33.glUniform3f(Main.window.glsl_day_high, 1, 1, 1); - GL33.glUniform3f(Main.window.glsl_src_low, 1, 1, 1); - GL33.glUniform3f(Main.window.glsl_src_high, 1, 1, 1); GL33.glUniformMatrix4fv(Main.window.glsl_projection, true, projection.getArray()); - GL33.glUniformMatrix4fv(Main.window.glsl_camera, true, camera.getArray()); GL33.glDisable(GL33.GL_DEPTH_TEST); diff --git a/src/projectzombie/display/DisplayWindow.java b/src/projectzombie/display/DisplayWindow.java index 2ff9ac9..39dc5df 100755 --- a/src/projectzombie/display/DisplayWindow.java +++ b/src/projectzombie/display/DisplayWindow.java @@ -36,21 +36,16 @@ public class DisplayWindow implements IMainloopTask public static int fps = 0; public GraphicsShader environmentRenderer; - private GraphicsShader lightmapRenderer; - private int lightmapVao; public int glsl_color; public int glsl_tex_cut; public int glsl_model; public int glsl_projection; public int glsl_rotated; - public int glsl_camera; public int glsl_time; public int glsl_day_low; public int glsl_day_high; - public int glsl_src_low; - public int glsl_src_high; public int glsl_lightmap_offset; public int glsl_lightmap_size; @@ -106,6 +101,8 @@ public class DisplayWindow implements IMainloopTask // Make the cursor invisible GLFW.glfwSetInputMode(this.window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_HIDDEN); + GLFW.glfwSwapInterval(0); + // Show the window //GLFW.glfwShowWindow(this.window); @@ -113,7 +110,6 @@ public class DisplayWindow implements IMainloopTask environmentRenderer.use(); glsl_model = GL33.glGetUniformLocation(environmentRenderer.program, "model"); - glsl_camera = GL33.glGetUniformLocation(environmentRenderer.program, "camera"); glsl_rotated = GL33.glGetUniformLocation(environmentRenderer.program, "rotated"); glsl_projection = GL33.glGetUniformLocation(environmentRenderer.program, "projection"); glsl_time = GL33.glGetUniformLocation(environmentRenderer.program, "time"); @@ -122,8 +118,6 @@ public class DisplayWindow implements IMainloopTask glsl_day_low = GL33.glGetUniformLocation(environmentRenderer.program, "lighting_day_low"); glsl_day_high = GL33.glGetUniformLocation(environmentRenderer.program, "lighting_day_high"); - glsl_src_low = GL33.glGetUniformLocation(environmentRenderer.program, "lighting_src_low"); - glsl_src_high = GL33.glGetUniformLocation(environmentRenderer.program, "lighting_src_high"); glsl_lightmap_offset = GL33.glGetUniformLocation(environmentRenderer.program, "lightmap_offset"); glsl_lightmap_size = GL33.glGetUniformLocation(environmentRenderer.program, "lightmap_size"); @@ -131,31 +125,8 @@ public class DisplayWindow implements IMainloopTask int glsl_atlas = GL33.glGetUniformLocation(environmentRenderer.program, "atlas"); int glsl_lightmap = GL33.glGetUniformLocation(environmentRenderer.program, "lightmap"); - GL33.glUniform1ui(glsl_atlas, 1); - GL33.glUniform1ui(glsl_lightmap, 0); - - lightmapRenderer = new GraphicsShader("/resources/shader/lightmapRenderer"); - lightmapRenderer.use(); - - lightmapVao = GL33.glGenVertexArrays(); - GL33.glBindVertexArray(lightmapVao); - - int vbo = GL33.glGenBuffers(); - GL33.glBindBuffer(GL33.GL_ARRAY_BUFFER, vbo); - GL33.glBufferData(GL33.GL_ARRAY_BUFFER, new float[] { - - -0.95f, -0.95f, - -0.65f, -0.95f, - -0.65f, -0.65f, - - -0.95f, -0.95f, - -0.95f, -0.65f, - -0.65f, -0.65f, - - }, GL33.GL_STATIC_DRAW); - - glVertexAttribPointer(0, 2, GL_FLOAT, false, Float.BYTES * 2, 0); - glEnableVertexAttribArray(0); + GL33.glUniform1i(glsl_atlas, 0); + GL33.glUniform1i(glsl_lightmap, 1); } public void render() @@ -168,30 +139,19 @@ public class DisplayWindow implements IMainloopTask height = h[0]; environmentRenderer.use(); + TileLighting.updateLighting(); // Bind the texture atlas - GL33.glActiveTexture(GL33.GL_TEXTURE1); + GL33.glActiveTexture(GL33.GL_TEXTURE0); Resources.ATLAS.bind(); // Bind the lightmap - GL33.glActiveTexture(GL33.GL_TEXTURE0); + GL33.glActiveTexture(GL33.GL_TEXTURE1); GL33.glBindTexture(GL33.GL_TEXTURE_2D, TileLighting.lightmap); // Render everything DisplayRender.render(w[0], h[0]); - // Check if the matrix count is ok - //GlHelpers.checkMatrixCount(); - - lightmapRenderer.use(); - - GL33.glActiveTexture(GL33.GL_TEXTURE0); - - //GL33.glDisable(GL33.GL_DEPTH_TEST); - - GL33.glBindVertexArray(lightmapVao); - GL33.glDrawArrays(GL33.GL_TRIANGLES, 0, 6); - // Swap the framebuffers and poll events GLFW.glfwSwapBuffers(window); GLFW.glfwPollEvents(); diff --git a/src/projectzombie/display/lighting/TileLighting.java b/src/projectzombie/display/lighting/TileLighting.java index 323a856..393519c 100755 --- a/src/projectzombie/display/lighting/TileLighting.java +++ b/src/projectzombie/display/lighting/TileLighting.java @@ -8,9 +8,11 @@ import org.lwjgl.opengl.GL33; import bdf.types.BdfNamedList; import bdf.types.BdfObject; import gl_engine.MathHelpers; +import gl_engine.range.Range2i; import gl_engine.vec.Vec2i; import projectzombie.Main; import projectzombie.display.Camera; +import projectzombie.entity.Entity; import projectzombie.entity.player.EntityPlayer; import projectzombie.util.math.TileState; import projectzombie.world.chunk.Chunk; @@ -19,29 +21,31 @@ import projectzombie.world.layer.Layer; public class TileLighting { - private static class LightingTask { - float[] b; + private static class Lighting { + float[] p; int w, h; int x, y; + + private int getID(int x, int y) { + return (x + y * w) * 3 + 1; + } } private static boolean lighting_dirty = false; public static int lightmap; - private static LightingTask task; + private static Lighting lighting; public static void setDirty() { lighting_dirty = true; } - public synchronized static LightingTask getTask() { - LightingTask t = task; - task = null; - return t; + private synchronized static Lighting getLighting() { + return lighting; } - public synchronized static void setTask(LightingTask task) { - TileLighting.task = task; + private synchronized static void setLighting(Lighting lighting) { + TileLighting.lighting = lighting; } public TileLighting() { @@ -50,21 +54,6 @@ public class TileLighting public static void update() { - { - LightingTask task = getTask(); - - if(task != null) - { - GL33.glBindTexture(GL33.GL_TEXTURE_2D, lightmap); - GL33.glTexImage2D(GL33.GL_TEXTURE_2D, 0, GL33.GL_RGB, task.w, task.h, 0, GL33.GL_RGB, GL33.GL_FLOAT, task.b); - GL33.glGenerateMipmap(GL33.GL_TEXTURE_2D); - - Main.window.environmentRenderer.use(); - GL33.glUniform2f(Main.window.glsl_lightmap_offset, task.x * 16 - 1, task.y * 16 - 1); - GL33.glUniform2f(Main.window.glsl_lightmap_size, task.w, task.h); - } - } - if(Camera.camera == null) return; if(!ChunkEventHandler.loaded) return; Layer layer = Main.world.getLayer(); @@ -140,6 +129,125 @@ public class TileLighting MathHelpers.floor(player.pos.y / 16) - Chunk.RENDER_DISTANCE); } + private static void calculateLight(Layer layer, Lighting lighting, float[] pixels, int x, int y, float level, boolean ignore) + { + if(x < 0 || y < 0 || x >= lighting.w || y >= lighting.h) { + return; + } + + int id = lighting.getID(x, y); + float level_current = pixels[id]; + + Vec2i tpos = new Vec2i(x + lighting.x * 16, y + lighting.y * 16); + int tid = tpos.getId(Chunk.CHUNK_SIZE); + + if(level_current >= level && !ignore) { + return; + } + + pixels[id] = level; + + Chunk chunk = layer.getChunk(tpos); + TileState ft = chunk.getFrontTile(tid); + TileState bt = chunk.getBackTile(tid); + + float dissipation = (float)Math.max(ft.tile.getLightDissipation(ft), bt.tile.getLightDissipation(bt)); + float level_next = level - dissipation; + + int[] adjacent = new int[] { + x+1, y+0, + x+0, y+1, + x-1, y-0, + x-0, y-1, + }; + + for(int i=0;i<8;i+=2) { + calculateLight(layer, lighting, pixels, adjacent[i], adjacent[i+1], level_next, false); + } + } + + public static void updateLighting() + { + Lighting lighting = getLighting(); + + // Copy the pixels + float[] pixels = new float[lighting.p.length]; + for(int i=0;i 1) { + level = 1; + } + + Vec2i lpos = Main.player.pos.toInt().subtract(new Vec2i(lighting.x * 16, lighting.y * 16)); + + calculateLight(layer, lighting, pixels, lpos.x, lpos.y, (float)level, true); + } + + for(int cx=-Chunk.RENDER_DISTANCE;cx<=Chunk.RENDER_DISTANCE;cx++) { + for(int cy=-Chunk.RENDER_DISTANCE;cy<=Chunk.RENDER_DISTANCE;cy++) + { + Vec2i cpos = new Vec2i( + cx + MathHelpers.floor(Main.player.pos.x / 16), + cy + MathHelpers.floor(Main.player.pos.y / 16)); + + Chunk chunk = layer.chunks.get(cpos); + + for(Entity entity : chunk.entities) + { + if(!entity.emitsLight) { + continue; + } + + double level = entity.getLightLevel(); + + if(level <= 0) { + continue; + } + + if(level > 1) { + level = 1; + } + + Vec2i lpos = entity.pos.toInt().subtract(new Vec2i(lighting.x * 16, lighting.y * 16)); + + calculateLight(layer, lighting, pixels, lpos.x, lpos.y, (float)level, true); + } + } + } + + // Update the texture + GL33.glBindTexture(GL33.GL_TEXTURE_2D, lightmap); + GL33.glTexImage2D(GL33.GL_TEXTURE_2D, 0, GL33.GL_RGB, lighting.w, lighting.h, 0, GL33.GL_RGB, GL33.GL_FLOAT, pixels); + GL33.glGenerateMipmap(GL33.GL_TEXTURE_2D); + + // Set the texture location data + GL33.glUniform2f(Main.window.glsl_lightmap_offset, lighting.x * 16 - 0.5f, lighting.y * 16 - 0.5f); + GL33.glUniform2f(Main.window.glsl_lightmap_size, lighting.w, lighting.h); + } + + public static void clearLighting() + { + Lighting lighting = new Lighting(); + lighting.p = new float[3]; + lighting.w = 1; + lighting.h = 1; + lighting.x = 0; + lighting.y = 0; + + setLighting(lighting); + } + public static void updateLighting(BdfObject bdf) { BdfNamedList nl = bdf.getNamedList(); @@ -156,13 +264,13 @@ public class TileLighting pixels[i*3+1] = light[i*2+1]; } - LightingTask task = new LightingTask(); - task.w = width; - task.h = height; - task.b = pixels; - task.x = x; - task.y = y; + Lighting lighting = new Lighting(); + lighting.p = pixels; + lighting.w = width; + lighting.h = height; + lighting.x = x; + lighting.y = y; - setTask(task); + setLighting(lighting); } } diff --git a/src/projectzombie/entity/EntityFlare.java b/src/projectzombie/entity/EntityFlare.java index 3dd3249..801259f 100755 --- a/src/projectzombie/entity/EntityFlare.java +++ b/src/projectzombie/entity/EntityFlare.java @@ -19,12 +19,26 @@ public class EntityFlare extends EntityTnt public EntityFlare(Vec2d pos, double angle) { super(pos, angle, 0, 0); - this.explode_time = 1000; + this.explode_time = 2000; + this.emitsLight = true; } @Override - public double getLightLevel() { - return getLightWithHeight(1 - (this.pos.y * (1/12.0))) * ( rand.nextDouble() / 10.0 + 0.9 ); + public double getLightLevel() + { + if(this.explode_time > 1950) { + return 0; + } + + if(this.explode_time > 1900) { + return (1950 - this.explode_time) / 50.0; + } + + if(this.explode_time < 200) { + return this.explode_time / 200.0; + } + + return 1; } @Override diff --git a/src/projectzombie/entity/EntityTnt.java b/src/projectzombie/entity/EntityTnt.java index 31014d1..6043c1f 100755 --- a/src/projectzombie/entity/EntityTnt.java +++ b/src/projectzombie/entity/EntityTnt.java @@ -80,7 +80,6 @@ public class EntityTnt extends Entity implements EntityHeight, EntityHoldsEntiti this.goThroughSolid = false; this.explode_damage = explode_damage; this.smoke_particles = new ParticleSpark[100]; - this.emitsLight = true; // Set to 2.5 seconds this.explode_time = 250; @@ -154,11 +153,6 @@ public class EntityTnt extends Entity implements EntityHeight, EntityHoldsEntiti smoke_particles[dead_particle] = new ParticleSpark(new Vec3d(pos, height + 1)); } - @Override - public double getLightLevel() { - return getLightWithHeight(1 - (this.height * (1/12.0))) * ( rand.nextDouble() / 10.0 + 0.9 ); - } - @Override protected void moveAwayFromSolidEntities(Layer layer) { } diff --git a/src/projectzombie/entity/EntityZombie.java b/src/projectzombie/entity/EntityZombie.java index 85abd09..741c77e 100755 --- a/src/projectzombie/entity/EntityZombie.java +++ b/src/projectzombie/entity/EntityZombie.java @@ -111,54 +111,59 @@ public class EntityZombie extends Entity implements EntityAlive, EntityKillWithP walk_scan_cooldown -= 1; } - if( - (walk_direction != null && pos.toInt().equal(walk_direction) && - pos.squareDistance(Main.player.pos) > 2) || - walk_scan_cooldown < 1 || walking_for > 200) + double player_distance = pos.squareDistance(Main.player.pos); + + // Only pathfind if in range of the player + if(player_distance < 16) { - AStar astar = new AStar(pos.toInt(), 16, new AStarSearcher(layer, crossUnWalkable)); - Vec2i path[] = astar.getPath(Main.player.pos.toInt()); - - walk_scan_cooldown = 100; - walking_for = 0; - - if(path != null && path.length > 1) { - walk_direction = path[1]; - } else { - walk_direction = Main.player.pos.toInt(); + if( + (walk_direction != null && pos.toInt().equal(walk_direction) && + player_distance > 2) || walk_scan_cooldown < 1 || walking_for > 200) + { + AStar astar = new AStar(pos.toInt(), 16, new AStarSearcher(layer, crossUnWalkable)); + Vec2i path[] = astar.getPath(Main.player.pos.toInt()); + + walk_scan_cooldown = 100; + walking_for = 0; + + if(path != null && path.length > 1) { + walk_direction = path[1]; + } else { + walk_direction = Main.player.pos.toInt(); + } + + can_see_player = (path != null); } - can_see_player = (path != null); - } - - // Walk towards the player - if(walk_direction != null) - { - double angle = Math.toDegrees(Math.atan2( - walk_direction.x - (this.pos.x - 0.5) + noise_target_x.eval(time, pos.x/10, pos.y/10), - walk_direction.y - (this.pos.y - 0.5) + noise_target_y.eval(time, pos.x/10, pos.y/10))); - this.moveTowards(angle); - - walking_for += 1; - } - - if(can_see_player && noise_gun_fire.eval(time, 0) > 0 && !Main.player.dead && !Main.player.in_animation) - { - // Get the angle between the player and the zombie - double angle_fire = Math.atan2(pos.x - Main.player.pos.x, pos.y - Main.player.pos.y); - - gun_interval += 1; - gun_interval %= 10; - - if(gun_interval == 0) + // Walk towards the player + if(walk_direction != null) { - // Aim the gun at the player - double angle_gun = Math.toDegrees(angle_fire) + 180; - angle_gun += noise_gun_angle.eval(time, 0)*20; + double angle = Math.toDegrees(Math.atan2( + walk_direction.x - (this.pos.x - 0.5) + noise_target_x.eval(time, pos.x/10, pos.y/10), + walk_direction.y - (this.pos.y - 0.5) + noise_target_y.eval(time, pos.x/10, pos.y/10))); + this.moveTowards(angle); - // Fire the gun - int d = (int)(1 + gun_level / 5.0); - layer.spawnEntity(new EntityBullet(pos.copy(), this, angle_gun, 20*d*d, 60)); + walking_for += 1; + } + + if(can_see_player && noise_gun_fire.eval(time, 0) > 0 && !Main.player.dead && !Main.player.in_animation) + { + // Get the angle between the player and the zombie + double angle_fire = Math.atan2(pos.x - Main.player.pos.x, pos.y - Main.player.pos.y); + + gun_interval += 1; + gun_interval %= 10; + + if(gun_interval == 0) + { + // Aim the gun at the player + double angle_gun = Math.toDegrees(angle_fire) + 180; + angle_gun += noise_gun_angle.eval(time, 0)*20; + + // Fire the gun + int d = (int)(1 + gun_level / 5.0); + layer.spawnEntity(new EntityBullet(pos.copy(), this, angle_gun, 20*d*d, 60)); + } } } diff --git a/src/projectzombie/entity/player/EntityPlayer.java b/src/projectzombie/entity/player/EntityPlayer.java index 21348b3..b8ad4c7 100755 --- a/src/projectzombie/entity/player/EntityPlayer.java +++ b/src/projectzombie/entity/player/EntityPlayer.java @@ -107,10 +107,6 @@ public class EntityPlayer extends Entity implements EntityAlive, EntityInventory // Create the inventory inventory = new Inventory(10); - - inventory.addItem(new ItemStack(Items.SPAWN_ZOMBIE, 99, (short)0)); - inventory.addItem(new ItemStack(Items.AMMO, 99, (short)0)); - inventory.addItem(new ItemStack(Items.LANTERN, 99, (short)0)); } @Override diff --git a/src/projectzombie/menu/MenuDeath.java b/src/projectzombie/menu/MenuDeath.java index fbe6dbb..456de90 100755 --- a/src/projectzombie/menu/MenuDeath.java +++ b/src/projectzombie/menu/MenuDeath.java @@ -22,7 +22,6 @@ public class MenuDeath extends Menu this.input = new InputGUI(this.gui); gui.add(new OverlayBackground()); - gui.add(new LabelPause("You were slain")); ButtonGroup group = new ButtonGroupPause(); diff --git a/src/projectzombie/menu/MenuGamePause.java b/src/projectzombie/menu/MenuGamePause.java index cbfc318..5654634 100755 --- a/src/projectzombie/menu/MenuGamePause.java +++ b/src/projectzombie/menu/MenuGamePause.java @@ -56,7 +56,7 @@ public class MenuGamePause extends Menu System.out.println("Time for BdfClassSave: " + (cur - now)); now = cur; - System.out.println("Size on file: " + bdf.serialize().length()); + System.out.println("Size on file: " + bdf.serialize().size()); //System.out.println(bdf.serializeHumanReadable()); try { diff --git a/src/projectzombie/model/Model.java b/src/projectzombie/model/Model.java index b82c931..d198a87 100644 --- a/src/projectzombie/model/Model.java +++ b/src/projectzombie/model/Model.java @@ -20,14 +20,16 @@ import projectzombie.Main; public abstract class Model { - int vao, vbo; + int vao, vbo, ibo; boolean loaded = false; public static final int SIZE = 14; // px, py, pz, tx, ty + public abstract int[] getIndicies(); public abstract float[] getVerticies(); public abstract TextureRef3D[] getTextures(); public abstract double getHeight(); + public abstract int getIndexSize(); public abstract int getSize(); private static Model bound = null; @@ -38,11 +40,12 @@ public abstract class Model return; } + int[] indicies = this.getIndicies(); float[] verticies = this.getVerticies(); TextureRef3D[] refs = this.getTextures(); - if(verticies.length % SIZE != 0 || refs.length * 3 != verticies.length / SIZE) { - System.err.println("Invalid model"); + if(verticies.length % SIZE != 0 || refs.length * SIZE != verticies.length) { + System.err.println("Invalid model: " + verticies.length + ", " + refs.length + ", " + indicies.length); System.exit(1); return; } @@ -51,7 +54,7 @@ public abstract class Model double k = 0.001; for(int i=0;i 0.95) + if(rand.nextDouble() > 0.9) { Entity zombie = new EntityZombie(new Vec2d( RandomHelpers.randrange(rand, (int)Main.player.pos.x - 128, (int)Main.player.pos.x + 128), RandomHelpers.randrange(rand, (int)Main.player.pos.y - 128, (int)Main.player.pos.y + 128))); - if(layer.getBackTile(new Vec2i((int)zombie.pos.x, - (int)zombie.pos.y)).tile == getTileDestroyed().tile && - zombie.pos.squareDistance(Main.player.pos) > 32) + boolean exists = false; + + for(Entity e : layer.getChunk(zombie.pos).entities) { + if(e.getClass() == zombie.getClass()) { + exists = true; + break; + } + } + + if( + !exists && layer.getBackTile(new Vec2i((int)zombie.pos.x, + (int)zombie.pos.y)).tile == getTileDestroyed().tile && + zombie.pos.squareDistance(Main.player.pos) > 32 + ) { layer.spawnEntity(zombie); + } } } diff --git a/src/projectzombie/world/layer/layergen/LayerGenEarth.java b/src/projectzombie/world/layer/layergen/LayerGenEarth.java index 38e2318..da27763 100755 --- a/src/projectzombie/world/layer/layergen/LayerGenEarth.java +++ b/src/projectzombie/world/layer/layergen/LayerGenEarth.java @@ -83,8 +83,18 @@ public class LayerGenEarth extends LayerGen RandomHelpers.randrange(rand, (int)Main.player.pos.x - 128, (int)Main.player.pos.x + 128), RandomHelpers.randrange(rand, (int)Main.player.pos.y - 128, (int)Main.player.pos.y + 128))); - if(zombie.pos.squareDistance(Main.player.pos) > 64) + boolean exists = false; + + for(Entity e : layer.getChunk(zombie.pos).entities) { + if(e.getClass() == zombie.getClass()) { + exists = true; + break; + } + } + + if(!exists && zombie.pos.squareDistance(Main.player.pos) > 64) { layer.spawnEntity(zombie); + } } } diff --git a/src/projectzombie/world/layer/layergen/LayerGenLavaCaves.java b/src/projectzombie/world/layer/layergen/LayerGenLavaCaves.java index 48f1b9d..29fecaf 100755 --- a/src/projectzombie/world/layer/layergen/LayerGenLavaCaves.java +++ b/src/projectzombie/world/layer/layergen/LayerGenLavaCaves.java @@ -119,21 +119,34 @@ public class LayerGenLavaCaves extends LayerGen @Override public void spawnEntities(Layer layer, Random rand) { - if(rand.nextDouble() > 0.98) + if(rand.nextDouble() > 0.9) { Entity zombie = new EntityZombieArmored(new Vec2d( RandomHelpers.randrange(rand, (int)Main.player.pos.x - 128, (int)Main.player.pos.x + 128), RandomHelpers.randrange(rand, (int)Main.player.pos.y - 128, (int)Main.player.pos.y + 128))); - TileState tsb = layer.getBackTile(new Vec2i((int)zombie.pos.x, - (int)zombie.pos.y)); - TileState tsf = layer.getFrontTile(new Vec2i((int)zombie.pos.x, - (int)zombie.pos.y)); - if( - tsb.tile == getTileDestroyed().tile && - tsf.tile == Tiles.VOID && - zombie.pos.squareDistance(Main.player.pos) > 32) { - layer.spawnEntity(zombie); + boolean exists = false; + + for(Entity e : layer.getChunk(zombie.pos).entities) { + if(e.getClass() == zombie.getClass()) { + exists = true; + break; + } + } + + if(!exists) + { + TileState tsb = layer.getBackTile(new Vec2i((int)zombie.pos.x, + (int)zombie.pos.y)); + TileState tsf = layer.getFrontTile(new Vec2i((int)zombie.pos.x, + (int)zombie.pos.y)); + + if( + tsb.tile == getTileDestroyed().tile && + tsf.tile == Tiles.VOID && + zombie.pos.squareDistance(Main.player.pos) > 32) { + layer.spawnEntity(zombie); + } } } } diff --git a/src/resources/shader/environmentRenderer.fsh b/src/resources/shader/environmentRenderer.fsh index 707981f..6064cbc 100644 --- a/src/resources/shader/environmentRenderer.fsh +++ b/src/resources/shader/environmentRenderer.fsh @@ -2,16 +2,46 @@ in vec3 pPos; in vec3 pTexture; -in vec3 pLighting; +in vec3 pLightMapPos; + out vec4 FragColor; uniform sampler3D atlas; +uniform sampler2D lightmap; + +uniform vec3 lighting_day_low; +uniform vec3 lighting_day_high; + +uniform vec2 lightmap_offset; +uniform vec2 lightmap_size; + uniform vec2 tex_cut; uniform vec4 color; +float map(float x, float in_min, float in_max, float out_min, float out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +vec3 mapVec(float x, float in_min, float in_max, vec3 out_min, vec3 out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +vec3 biggest(vec3 a, vec3 b) { + return vec3(a.x > b.x ? a.x : b.x, + a.y > b.y ? a.y : b.y, + a.z > b.z ? a.z : b.z); +} + void main() { - FragColor = texture(atlas, pTexture) * color * vec4(pLighting, 1); + vec4 light = texture(lightmap, vec2( + map(pLightMapPos.x, lightmap_offset.x, lightmap_offset.x + lightmap_size.x, 0, 1), + map(pLightMapPos.z, lightmap_offset.y, lightmap_offset.y + lightmap_size.y, 0, 1))); + + vec3 light_day = mapVec(light.r, 0, 1, lighting_day_low, lighting_day_high); + vec3 light_src = vec3(1, 1, 1) * (light.g - abs(pLightMapPos.y) * 0.1); + + FragColor = texture(atlas, pTexture) * color * vec4(biggest(light_day, light_src), 1); discard(FragColor.a == 0 || (pPos.x > tex_cut.y && tex_cut.x > 0.5)); } \ No newline at end of file diff --git a/src/resources/shader/environmentRenderer.vsh b/src/resources/shader/environmentRenderer.vsh index 936b80e..0809d02 100644 --- a/src/resources/shader/environmentRenderer.vsh +++ b/src/resources/shader/environmentRenderer.vsh @@ -6,37 +6,20 @@ layout (location = 2) in vec2 aTexY; layout (location = 3) in vec3 aChunkOffset; layout (location = 4) in vec3 aFlags; +out vec3 pLightMapPos; out vec3 pLighting; out vec3 pTexture; out vec3 pPos; -uniform sampler2D lightmap; uniform mat4 projection; uniform mat4 model; -uniform mat4 camera; uniform mat4 rotated; uniform int time; -uniform vec3 lighting_day_low; -uniform vec3 lighting_day_high; - -uniform vec2 lightmap_offset; -uniform vec2 lightmap_size; - float map(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } -vec3 mapVec(float x, float in_min, float in_max, vec3 out_min, vec3 out_max) { - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; -} - -vec3 biggest(vec3 a, vec3 b) { - return vec3(a.x > b.x ? a.x : b.x, - a.y > b.y ? a.y : b.y, - a.z > b.z ? a.z : b.z); -} - mat4 translate(vec3 vec) { mat4 result = mat4(1); @@ -48,6 +31,16 @@ mat4 translate(vec3 vec) return result; } +vec3 mapVec(float x, float in_min, float in_max, vec3 out_min, vec3 out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +vec3 biggest(vec3 a, vec3 b) { + return vec3(a.x > b.x ? a.x : b.x, + a.y > b.y ? a.y : b.y, + a.z > b.z ? a.z : b.z); +} + float getTexY() { float animate_count = aFlags.x; @@ -74,17 +67,9 @@ void main() vec4 pos = vec4(aPos, 1) * (mod(type, 2) == 1 ? do_rotation : no_rotation) * translate(aChunkOffset) * model; - gl_Position = pos * camera * projection; + gl_Position = pos * projection; + pLightMapPos = pos.xyz; pTexture = vec3(aTex.x, getTexY(), aTex.z); pPos = aPos; - - vec4 light = texture(lightmap, vec2( - map(floor(pos.x), lightmap_offset.x, lightmap_offset.x + lightmap_size.x, 0, 1), - map(floor(pos.z), lightmap_offset.y, lightmap_offset.y + lightmap_size.y, 0, 1))); - - vec3 light_day = mapVec(light.r, 0, 1, lighting_day_low, lighting_day_high); - vec3 light_src = vec3(1, 1, 1) * light.g; - - pLighting = biggest(light_day, light_src); } \ No newline at end of file diff --git a/src/resources/shader/lightmapRenderer.vsh b/src/resources/shader/lightmapRenderer.vsh index 2337d53..226a281 100644 --- a/src/resources/shader/lightmapRenderer.vsh +++ b/src/resources/shader/lightmapRenderer.vsh @@ -1,11 +1,12 @@ #version 330 layout (location = 0) in vec2 aPos; +layout (location = 1) in vec2 aTex; out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 0, 1); - TexCoord = aPos; + TexCoord = aTex; } \ No newline at end of file diff --git a/worker.jar b/worker.jar index 74efdd46cc4fa9fbcf7842b20c350d2598dcb215..fbd14901355c6ac5b4d446cec515db3445171f71 100644 GIT binary patch delta 24831 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 delta 22303 zcmbQ%#j@l(GjD)5Gm8iV2L}g3%hszCd7GJ;mtLJXS(Ukb>(z<7wd*7Eg~LVut+V~+ zGv{Pe^X3T~R3;?M&PnBMS?W+|Xu&AOrIL8^h+LBTG0tty4Pw6zC2N0e75_BFE3_*l z)TyZ<>WX~8*M;^A{r?JvviyBFH_@pp(4_dh<@b5N=RUQ5{O9Ad>-QPo95uJ9VS2dp zx4Bqaw{h7<{i(B0O)GBIl%3^J|94C2@mHs#TUYKYo_x7%*BWJwfZb)k7KP3d`A|Kq7r#of1Z0=KQY~!j^i`w9MV9ut~hp*{cPd+uZW3Oht zR5bsix4cppoNx53wc5sE5@wf@Bz>#%oHuLI#Vb*sZl_$uvJAouStVbV30q~;{h zQg=;DUSCXi*?QOH$DLXnZ%h^*HV{aT6kBp!Px$T&L5_>cks7yy%K}yBOs0)v zF3Xj>-PX=IJC((3ncb6v3Lj_AcUY1%E2m2Fyj|UzLrkHnvm<`qsg0ht%Q3C;lnc}R z&4EixdtY_ey_t4O)oj9)g_D~;UD~V`v?*|5YmDXVEpAMFvn|>``z%uVUB1WZzn1Zb z;~M~_Q(q&zZO#}VRfzJB-Fiz%t%WtQ&mdZw)Xa%O_* z@+jAB91<$-r)I8pFqzq-sdd*N@l>C*YQFJ_vn?{Jh3)+AoBR62yTcZmq>H|Fn#Fj1 z68FoWdqTIx%E$idIq4{TV%CnX?4Vg@hK$}`mBNz8!weE1FO#XS``zcu#ZnyHdUKJ? zCquWjJ?57_yE1*eHDR&%o82Ki+Qzv{r`|Q6cg67hiEGCl^|B_l3q9Z0$!ht}XUzo5 zgHbCQ72GmX%J$9JCTw}~!L0I{w^RSRTFd^eVd6NXp57yGJ%5he*09~HU#>HK7qvPp z@~qXB&wCqh_3t@;{%g)3)kF2W!vrL|%G;yEFKlb-6MwNtDAel@Yt_mx`-97ZZ~peX z>HhS9b?SqeOx8!r+qu?=Nj+R8pyn>ML00-=KSy7Hb+a1Jrz2+SEHcYPy{x*Dc{XsV zf6(mvZ02~9H*!wGEyj6OzogCj_Z>O8F!rwYk2ghsER}2e?%s6xR$6dle|)rCeYw92 zcgkO3lXBNB3QPZSpITC>*1ODoR!7FX-@Zz@Y?kSX{^rEBYWqC?|9G=SounH zU&)rb%6pf;1>Jt0$-aVj$1I(Wc+n>U-Hcl{>de;6U3%r5QfY$x>7rSmG3ON4R`tR1DIs$P!w_A#eEdU5CWGLI~cNqG(nBv;?? zSjG3d>+PuqA@vvkqsUmt~8rU&Y-UUM?)N6Y2D z?e+FTPNf+y-^OQ`z6{zK^Q<+z!|vGY^`D|kcxQXu=DSt3!~8(R^^A%OXK%Ov&AVrn zU-;?X0ekiLhNeshLs^b!{XZPzI`@72i<%{eWA!I19@Si+_^!V3^`9^Iy0h2$Z!qKQ z&APF<=DEaMo{gVWp6H5Bez{|}A!kkN`n#)l?>uEY|J&#PC+dFN`pVO_#)C!Yr?zaL&}4%@K0>CLJyHQa@b7iE8LK4Z4@{)u(rWg(&5JS!9g zW|SSEm_@|K(^?#ERy%L^X*z+J;>}qCqsP&@aww?8|ZRL9dwBuRLmKi2Z+st=v zW|z>yX^m!+B-zD3Y-_k0Q03gVdyD_l{*Z)}oh()Iw~wjr$xi$xaYFj`k&VwD7zG_G z4qj>I?RVE}x|>0JPwUU*S|d4Gof#&N+)@-zcWG~}3VXjjbjI21ul8=c8F8ee@MB{$ zf1zuFMF`8Dm$oW5>eGYrty<3p+@V0V`l~WD7^pCz({7mOnW_wKi%(mD1hKc_D*|WGWTAWzm$a3s=!St(U z{2Fd5cmE5WFNk+vBUL*&*k{&-*$dxXcfU1r8OM=Rm6t2N)vR_hiR1q$ExY4ck zY6TxT?^S;J^!`ln64rT%6RqB_O%=&yv>t{*G9{ii>=CcH*Rby8*n>x zuh*Y+5nmm9$Lx4TzWmnR8n#tGwHNcc+DEwG2 zS#FY4VbyF`QB$QQN@tSvA4JTkYc%XGWO*gHs<)m|7L-Fjx#>TxW@cbG&5E2u&n&$< zakuPbnJ+x`rJ>Q~!l5Gn{AQR#c9C;T@KIe&O3&TQwk1mw)^7>3zRFoRn#1TH}`?e(+ot#%hOuWtCE(zNb?B*vf@Rn)c-?q#f?5tYO5A)vH%{l*q zF=SDct0+^bK*YjB-15(tB)*!v^iD(G(k+cT-><8F&eXlVHnOdzyjQOJh6dLa_31%s z?5Q5xgZU2b3aHR@O}xCc-s1Hptt~g4gVt>ET9&dS&Q+k1!R$dDtF-u&McGr>pM}^o zs5MS~IZ5^LG{bUq59#U+_h5^qC;B*(qw+QHs{zZblG9u5Vl3L zqGQS&XCGzx&i-3fdrT}=L~CtRRC;iIQ{=P5X?)j;f{P^2M~L#@SeL|J##J98vFyOB zP11XX(iWza-_%LcQ#*fqZ4&=Ct_suBm)uk*7UbJBxC;ae%vIe~Fu&`sg~Rzx0(%zT ztFTa9C>Q!sf^XwBpSnXO&0ZQ7J~JB6Bpi{`eR0&o#<(Ks!J2v7L}gO{K5=r}Y?^6* zsM0|@NW%TY4v}Mp;`3&9E{=_wC&1BGKk0OC*VMgMAtjGm8oY$&M){rh2<2F_m`AK& zMs)YjhrAC&g1C0ENKGpb`Y5tQjYCU-PxX1`fo(j+8rwMb$|U*-RYke-pW_HA%)dD^ zu>Fv?B2xw1d94@G8iwhiXxGOE_E4|1dnWB&~O0qS%8si?scf{kab~gsEApt8U9lc$jDZ$wvD*M{HZAU#sf+ z#yyoM_gFsZioG|-Yfg9}qj+VW;p*3{nmuKax{cmi*Aj9WrWd*%^N67Jm#m$u8mk(FX%Jq6t>>{q#(RbA^&T323Wm(af&<`u$9O1qt^>NoH zRqeI%#wqM;=e@0;ep^LtRz#nd*qSDLv!qC?n_DcZcN|hX`_XRS+vmF`tkw+!WOmdyH`%blJSW?*-5$s1Zhmp`lWo={zL3}3yEkN=OkKJ; zI>~g(-&h^}pQaO5I&2P^*j;tO_3PFxdJn`3*6`lhnkF~x{LxANaqRWpC(7cFt$ML| zZC7@^@wL*+8GrcB%H%JITz~vocKo4u%U)gKQzlW9%s&*oRw?sMy5D&0^#`9VVSbMu zCF83311jZ9`VIZisw(icQEi=>hBrZ z^2KkH*GxFGrt_=J_06xOU+kPYwPM1*=pWY(o%%5O*!{A)J!K!nkNTN)$9g2`|JuMW zd89rd;q1PHig%uz%9S~K-l8pj;(_-W$K_ufm>+UhcFvL5vX}d3a7XTSoOfi`j;qL#$fe^`60X0n`oL0HAK z^R>IY@AH2Y{Aj24E7NS_uKIxW3qsF0I8S9#oG%&^EMOmA;Fb7$>i>YNuSAXa82?MP z5vgH1;TqK{qgVXvjOLr?{~1BW_~VsHuG3i=7}`0Ji}A}#Kn*SF$wGoBnOnAAojh@} zJeb}*Srts*o~%{BHkz{{By^hH@@XMUKXG^}C`zy9S~zLKhE`P%=bnoS-4ZN}f!sk3 z1}ZaLkJd6CP7uxgRpV8DivG2qs59@u;&Wf<^ z6yFi0yFSe;J5<48#!HrC!SU@(kEAr#b(Edyi#uepAmxdV_;Z)vQ?4D$=$NsI_te5V z3FDcF!nBUR zNml9bPw2a|O_O-GDnem=~Pe@gU zMJe~>qjB3(GE;-CgY#Bx;b2{6$16KARs3Annv02k`Ta_7&iYP&SY7AIwTbbUXVA%+ z`?~MGe5CYBY5Nj&(~}{pSEWo^{lwg}Qx9YsJ*Y2f*^yG%tHHBOl5MV|@x&I7WaZ%8 zt}V+o+Co@mog8&n=V$h8Q|Ns->B)>4pI%i>FJXDCaz(-O!?VsUdv+`%x?|ZT zo91(BSBf4y@+eL(Iajpop{i|qA9r2HvrAt}qCC2px16xt@4KJJYWlPV7PGf}w|uAZ zT)Ko&abf1fdeiJhx*ah)qq(X&OgLFLo>}0gc`3m?dyiXjtn$$(nN8|3{r{ibYH8Z? z>e-ibS0_%}ylA4ErpCbdFe!NsjhzI@5}JS!u5w`2B8BOUqrX%BatKiuD4v2{mT z>zNzcQ_W{A3%|UTaaWtB@j~s(5sQlEPATclZj@l!a&LijMziJq>}cz&Axs)xf82Ii zI+&~aiU&I;FP9naHgl-Bt$xl_ zv!3DlPNsaeg1HR$(=Ytp^rqf3?p3taBJCy9>iwdbzbJ^kKH~A$Ct*A1n%_2&iWB-J zw#=0?4L>k*?IfNZR?05@7lj$CY&180icpv@azb+5gxwEb`ZV6ny&zY0i^uWsscUA& zEWCnZORP6WBA5G;{zJdon*xy>ZKsZ}X8UXWH|pA@b4%au()fJk z+QUbu^B)}XF#NmAasSf$Gnaie**No9%1_&6b0ZRenK$2CvV8{6-itTBWHo&;yR*_z z^#9!j z=Q%D2ZitJKUy%P~mxjarlUvms?w=Mtzx(MefrM$UNXe~Hnv+)0(7a4p zX#K2nPfst-t@TYx>e~#JLlQIzK(M_J{e?JG-%FHWHK?T-f=<1q+`L22aQId&8L;Jl}^vHy4F=- z;L|l>`YEfo&kV0!>By2>P`l`$`pTtze2?bIP3*t>X=9vSp8KKt9akP0>4p0?TwU5z z66<@nnrr5KtK*gD>HqcItcWsn!&zH!)gV&5%15!V*FdE#N?ACf~ zt)=!}@4dUH3w38TFaL1zgTkddJz<-bSA7jm{j1LA|M;cHyIFq5J6St#z6o*PIX9_5 zcmAmK8NNj|J>xf#A)w=2OU0oA46X=Z&M6?w7h8X!NADr&Gl7t z9e>A0Ju>4BTDpAyY@=XT&s8rcaB0|o{j+jO&P@-oq@X>`8Eij=1N+keZ}@g%|_07dsZ{;nO<2n^UUtaXFKz5?=x62J!*$n*2An= zgLnJBWcuHG%5cM5GDbgjgWvTo>jf9*Z4nedQJ<*hnr3uc_P5%U>Y454CvEmb`d_<} z^X9fTL-ovt?I&6G#GVf-KhWbn%PK5NR`GKzoBtC}jqHit%Q)(@K4jMH3cDt%{OK%P zAFJ_(f{vJ-s+WHA&O2@4((00RN&I6o+x&yZrkheCTKFaRG@QT4q2;S|H}8Xx9e?eX zvzE0+X?68y9(ex*|8ypB4x7ouyCV18nGfxm{^{vrgE^wNypJw5lzLL# zvgl#ZdVM$bs^k!+%pF(M`4t4-K3`#>y{w(-IE`E z`m)x9Y5eYlHHSSInt?n~Mp7=*FDLBk@;j25v*Xds^i7L8O*~zns?F+=FbbXBaaZC6rvSS_51WXWv30B8 zwTU$m?m3xrV%8P$m$&L)zEW$Vdrn$r^WkMXjNFzVIr@_G;|__rTpM}5%W~+|e>wHJ z^7jhA6Xk(_<+@jIP|;edq_x;E#P4g!!U~CH>a*G_`nxnv30GNM%xHhl-XVXz;M|;> z_q6WwY2EWL7N1rgc-Sr~;Fru?;l-bmwv>Fcl7IfIOaA4*9X5#;{=G8Yy9+r!RUAo{ z@ycv6vODLpwMk-GvF0inuFFMHjPiR-n(D(Y3B_E_kT7+87VOt{;D6*PJioRVY3bFWBkzh$!Nl91N+(u=WCPt(mrpG~=7-MuA%4bp^^6O% z>nlIxx8L~DzoR~L&g^N@KmPxiesgyH|Cc@Yf5`XTH%@xISYE#_a_`UYoyK*G)xSQA zxBGKj!|dPdd$m?E-rVTXm+|e3#8TW}SNyHS2Wu3!Qx(Qa>1D z$}imfqjUCoc?RQt@9rPTQD^2~+F8>xt-|f{&Usl@_lu=sA4K{J`fHn3>D4b?kuI$J zJ!iS-JoAFu>9cI+U((8#-*w^k^r$^Que_3V&EB*8lIy+hg1s`*2iabIc(=&!ecrAs zw_UUMuD_gm&;LbHyjkos?M2$P$}hC;>+HH^-oEbhT<7b*qcY~^+phg?+xxoi)`Q=o zxnF7>&42A%6kX%~GOS)L_tSir?LVJC+EqW}-G}uHtp9Gm6#MV?i@2@Y?_5GQG#@Q@ zt+~8gY2V6NLBSo<{<)XA9$9$ij_ARv#nWUD=iPQ`Kf%5%ioeG7yn_6VOi7EbHwG!| zqc{0aS<_vUurT$3(k9<0&CjFQ{=06wd8c>hOutj#cqA_5zqpX-+|GA)W?${hU6~@R zq3l~GJguMi@u%sQvvdNAK;{#V<`~ ze|0Jea*3AleP8?H^trJpBRqq%C36veouZ-T)y;u(SiMJ-{X(}eP2~x&u{ydZT_3u zy7MpgbN<*~@W1T+2YtmFwLgrdEXNAX@BQez{KMEgIYuPIPGHv4xx1QwP2oLK|964q z>peCXYBsF>y?VnO_tW1h_*;b3=RGW9T4?|1bM2Iy>@y1G6U%COe!54@v~Sg(pXgM- z?hg0tXw)_Ro(R-f_auK5lxgpO z^rM1BuAW`&?%qu&mM12B4quR9 z`-D~=srts(73Y?4&Ph&=&fO@x?xt9v;f*@}ZOjMnOxb@IMyde9{K3+=NGZQk`u z?P&A^E^F5M&y6M0&4QmF^ZW^_byB$NsUXk7<+z}Ot5SjYnPWkLLT_vLvBWGELjh33}pvuIo}*+G+IO7j5?ffX!` z7Zn0HnI1bNJSr6UvCf?7{xQy)uE-Z*E|Ge!A{z`fELW!svd$4%)^x}uUAB@4*v0J-ufLcoYlG;AY}g zFyObG(J!OZ(ENE~eY2}V;XVH647Sy;WHzYJYYtqsT!4wUs`L8$-*QU=EYkgY4s(B5 zJ-wwqYvOZ_Khb`XdoFD|@myX1Q-oBd$Z=kkw~CPm*)=8l3YWI6FFCZHt%f`G)2u7i z9%>Jks@;8X+4sjssk%AB`-DG;Gyl7E@1go972f+S6W`>zCd&WXXh$%o=* zXx!onINjqv`{u&<30e!U=iUC6S3fzw>Fw-Hf%{HVYgV8ACvp0p#0~o;_b)DDmu@lh zud}@{Z_TCC4uuvw!o64==f%F06?`1YedwuXQw@90Jx|FR@uwf|&d~aPqbVlmrf%C^ z-wl%%Hurov)h{_M)_D8ThikUD6!~`)I=_07x6I@o)9&vF-~HY2+rex1?A$Wdo!md> z)XUZUHQU#myvM-we(rk5J z_GcC{szH50GvtXwYmEL~&zeAcVa zb5y7Lly+*pG>qu?@&0;2aIM|LH4A=ODofs)qZ!*!Une)Q<{;bc<4tc5m+o;o=yyQq zIKn%c`&e#F4?biz^Inww>yVeiOBUAo+&sQIsb=Bh<+A@;bLSeZnf#C?yr=L$ zgzRH6^<%5oNo4;}5^lb{P_|)>+MKD1_PnxF4r#<%SiVh|8vplMK*)q?ucfWG<~&Hd zyW^hV<87?3)Z1g~|8INOKY7*h7zs8`rT=V(mAyQ5vcGTSXNs&7{>eM**#7NrlTE{V zvL;;2e=ylGbXON!aQvEU?O*J~Cd!v{X)HMR*nQ)C)q6%Mx0YPf=H~O%zx}w;eP7w( z{qr1l#5Juw$n%!lO6TfB9p_fn4VNTm$Z(#~U{O1kE&TC^QmV~8C!6|z4R@dCN}YPY zz_4<*+vnXTo%f3~eLnDhv|vg%S{ZXZS>srI&fC|lPbN;cQ0ra)*ks?drj(z$m&;B} zI(%eGL74neWo-%dq`lM5OuRlx)HKyOx#lU;>)PZjrT2#?@=utmA+f+}-v$fJrB}f3u8~@9IguEINH+V})DaOq*-T`R@)cUjOJ}@pHql zj~Ui-a_tX}Cw}-LWz*Mi{Q85BycIRGCmk=>v*9t9yML^*Ci~Nk1Jc!DVPWg1)|*zj z-8><2zrto}DNkQXaQvEihi!aRcl3R%$lP>%`l?McVzsg-d#4&6)$Tr-QpCM$s+{D> zce(4ruT7mR^4RzIL_z-vmuy~6dC7S(fZuP^j=pbS7JAM*6C#vAUo8*k-?; zOg^44iR!g`FS05>JF=p*;AdQ7N#yQH+{Zrq^<0*fxXYEi|EkjNgqFDyn`I=tMUFA9 z{#kmkVB6$*JNqhT6#sW!eHp^tEGyx=Og_xp%1zdu@4|`fo+)S7rZ4f(CRqe_R{O z$arJ2|9UCO(_WrC?HL&un3>RZG_5zN4+yy~S$FQ;-Muw2%!@d*y$9D zHCD>jH?BK%V`80hRHXQetZUW14#@^m!3#N3U0l1Pq^=d@FsmFw9nH%KL9igkEz_3a;bIV0ofxdY!4tXS%oa&o>tq zyKP->%FL<}^6=@xlR74M`dFFP?9}3zC|_JS=7`rl@>J_O)W7WTIHmrwr~6h5u3#%Ja6_OWAmZrbbD; zHNUz}wsBGaYKFARa-a7$SC)Lg&E(rJC6aTZWJ>(3AP3eHlT_YcyU=BOM5sqn(Ds`9 z%rn|wRYj7UZR6*5nr&HqJ6F{|G``{fEb%epqIuR26%8YdF8(%sb3|`tT&y#@ z73&s@s9?8wm#$3GZ%{P8q`JYdbwcn->!pX~G*#0Mhu(^No;{U^Ka*qObj=qR7oSy= z)S5lV_>sj*){DnAj;e3t`||2xY@6JMNAKsWoo*{|P+O&FsIohGV#1EyQEClGr6#`$ zOsRi$xnRa8>oOZ&{tr``cJx2)HY$mq6(;^|*P8wMj{`;HXU2UFGccKR zM04J4LBlW3n~a~T*gsw^wXbdc=1pJz)hWvuSl>8vxIWG2<`G}<{_F~-`%CsE*Is*6 zQhF;+<-ujCc~f@WaTHFqI`_a@YoG20gL@3t)n7cWbQDgP<9jjDVei*-Dt5i^gWSuv z=iEDg&18S!F}~ZIqLw|Dl-#|UiCbg$m1&>$MRcT_&N<9qVSDte*}=t6{&TsNO0}(6 zxk@RrUO(f-@!HHE^@8cAx-S(pYFXPYHoVof)OW%p;VWA>xPMHNo4#hTSC^>J?^Ir8 ziPY{_6U+~`b!>dOkJ0wXk;&%VdFxw_=&2Nh9+s%{ndrXsgt>~P=1a$YSEd*2db9S~ z##K3Q-gR8OT|UF-l>NM;OQa*~?Js_qwPydROa5F3Pl|G_->fflx%pv6eOFLoeqiLS za!Gd|?)cw6(q`?>&pypj>DJ2IVEy);bVrHQ?B-33XZ?rv~`@Ah=+ znp@Y|i(TgYDgNj`@xEitvd_sE8hN}zPUvg=JNL+EZYF!mZ}-C4^*lFo7oXVKW2ry$ z+Ri_Fd&LgO{F>RTbLObczRYWKPZaCt`@cM&{8Ko$;IqktCnojhW+}Ry+7tKn0LQa< z$BP_ZS^gFx=R{7;6r2*SDRa%oH1hGHvl7#`7g}9ceeS+-(J9-u(A+QkmwA0%A@@CX z&12`CJyQQw&wN~=d}D)q)b)zfZW~^{`Qdr;XlBvPHkp6tHt($X@mh5;tA?APm&Deo ze-710b*t|A;hnL2%J%v4u^P_$r*59p{-_YPVSCj_4ST&5nX<^3w-zTZhM5=$ZN7PD z`$Ijq4HE1ZPE4G+2uMHD2GiYULlHYrPNdX)Wzp zJnMCM!2>R)-qfQ0ITEhhf4&QpSl;Q{uO$DaFyO(NA09UgY${ZjwXE{k*_QDB$#1qv zs~+Et^}is!vHdf<1cRi6{YSyMvNKHHsMbl&aC-M%*_XZiej=Na|q2-FhTt$y|Q!K*71cXV00Q61X>M^Ujo_mNTnkk}d9q6|(a8 zKH^TD{^10Nob*BSjF)mv<*#mSf3sCMZ{q83^Q8X=ANnN0cH2g;?NzFcY1jMMgWq!> zv&^3JJnh^`+t;V|aEbojvp1{xT<8?$=M$#y_}?zfATn|FjkNUR;meX1)GtX>kgYiH zmpGyLUep|)$9i1cSEAT18+7O2%t-tZz4A}>j5&LKa;)!vOR|5r^xF5wCX=gXuB;Je z+~a?{|3dTZkap&F7rXh~GjCPsc3c(Sdf?*Z9U8w`-1TQ|ouE6-;OX*?WWIaGubm&R zT%Rz*BSz%B(w-xh=EvSnRPC)e=Uh7muu}Kgw6`JvE!-sN8iI*APv))|)9gdbX`TmT}iZ>~yaCZmm~{KC7`VM6+(Q zM%>-Ufojap(@z{QdvM_Im4|`bdLQTTHedO8cun(Sl@AzCQ&I08_(?roBz0fF!^YkUlfx%SL%60c5zAK+><`_MKQU{Zh6kOnY}n=8s~G} zlnH$rWivwVZCPn^&iB)?NX_*?s#- z-)M;!{9rxh`tCJ%z6&kcuJ4yWf3BG2rX|mlwnksl?(xnSUaKyg;+0>f_402I$C{eh zElaoGnsU#@;>J=gn^P_pv$P+5D%O1dbdO}4y~TO|(>K^lzAEb9xc@onk8=IWx)W#q zSUz;?+%DdyHf7tLuvya!RBD!U+MjQFKdT`>`TXN)+dpti|K_#{*|m0~YYA_2Z&2A$ z&P~~RpHF2kP^#m8GjGwZ`%`_x@5ayAuz%Cqe{(zjHFEW>{&=2+&(y5lr_Se(khzb> z>71*ToRyQD*<`j)SogM^o_?bX$&dD41=+^uC3kQnW zu9uaFVq2lB+tsnc^|qs?MxEFNFB3D#g2saQV5TXpCuAsJmTGVE_Z&wOLR z?d#P&I|~(VP3vMS`uTWM^yCRF$x`bcNiklrOkGy|bWdSXlB+1|C4nY~&qXc23<_pV zK7DDA&AD}hF(FfI?3BbP2dzv#GJTFSNhgjS$i%R9T;9R9t(_*K5VkPEthQq*zQ zziLj78_OPTPsvwyuJ>Ow!^@!Ia*6Srg9!}ZTUNQ~tbMZh2@6mxQzta6LfN62omst21*TaJ{$4X3q&uMCe#pZEXvRCwzbm}zT78m!16)Y;2kaG$kJ@~H7j^M;*FpVVw~Ei#zAHXg`OfzD^Z$RoeP{UgaC*Jf zEf%GjZ|}Si)EYh8CyZD*T4W1?HcjxF&dfBg8eXYbN)9#>Q^0YN6 zHCjE4ca}en)BF0_V1w{??k(q|&l$Qum=~cX`n{d&F{90jh-D$a6!{AQWjM;DY#7gXaea`lg#|w!&9> z#ZKFEF(!Vtcilf}?;$N#ZZ2Q0bN=RM&M!$m7iX2LSDpG+BT}cn*iZLe_g0_347*Y! zT9gj+j~!<${f~8u31z7A#Bc6-uE~74BFZ7&z+1S> zO7y_$mnzpMK_#<>@oKH067)URRrX{?jCnWm%gIUW&Z^Qxo*; zj!A*UVZ}2--wz!X=upr*(OJpNo$!gf%K0uU-R_zqkpckdVY4c>C8O`M2~Q@*|nb!KJ9mKZcfOeb|udJ zDG#_OgADv5(CF&M+Q%XFKP>hqJ}_N5vrO`YXy#5e-A`$cxGGsq z)~&rK(>Q6$%>bRR|36RvVQ=!mY#sNThll>JT=2?m*LAbhz`yUNh3N(!_uq3bz(4uB za^jr>t3sZhPbvE|;}oCNJe?`so3D9B%UwFxyHe28;X#h^WvMy6<&7!3e%dZ5Wj7D{ zxhK?Sp0Rhm>gtx?HzzY^I9r$0T}~-}wxe^sR<6Mh?Ud-}&&8sSz0kDClihRlzp2Zz z{Dsf2zxX@#)4g-&&wgPD&v3bMXt|x8rHJFU$W@_k)H4@y5h$IvmbI*zqfM9)f%nhKU053rcX`lMt$wyT2GAy z9K1#{J9m1okdD34CKpu65V&p6Z;4BKJ(s_+lxc7J9pfYy`Sa~z3y)o~7F{ZQhCciF zKBU>W{5jrH%_6V(EwHL=VeZ@ujLQO#GdSNnotmQ(w`PB^Wg6dgg98Tr%T>Q~`T49# zI{zWxK<@*4&m6f`36B=kPn%%)c7LyW-s75C{6!1SPiDG)?fGOXVG@N($TFG zPedQ@b@}6($-3jQn?W(}L62u?D%OHG)~|gOn)z1szvZ#w4Yj=8mk)2BxVyDJ>5=Ue z?H?tq=Pw)Y=*swer~BR=Z^w($J@+F1yPqwouU1;M@m2hnnmu!?O>>{IZM$ya7I)9# zqRaYcJ7eR|Z(p=<>oP^gMb}?vxa@o5cW>GaX|*B=wvnR2z$qC3BlU` z$0BaevrBq^__}ScoO+$~abKfC&dN1x`CUT{25hi>`Y3h{KJ5{Y#Z9kIzqfdUdtmvM5XR>B;&(A&h%2&-%<3L#AzNyM;eEO|LUVF~o zIQ171hkG;c-Luc-`7Szt5!;92r(e1GU&-!S%_Q_@@~h|jLAC0c2ffE+*clj9_%Ul$ z>B$q0^VR1Dp7uNBAYyxX^_2F6#;)^gMTB=3w(kl^R>?FGbb3_e#V!-nweYCR{!?=U zh3yaY8{HFYVV!$)ud(^_sn+)U=ig`WD_Ed#aKX)U2YBMiVXI_YBrdc=@4W_L1F-@`~fP)JuF(eUoPP?B3o7eA{Cm znMhwd)nk!+UNG)Lmh`n#tA%}*nyZK^%gJ>6#`?)jWOrW3z#7>$N!7N{TKaa?A;cXBlO5L>5|3@!;mD7$Q(n3cCBsPHxBAa z&hheRd(P9|TRQh^=f(Qu6QydKGvi}U8`OQYe^c0T)*#A3=%MGu|4S!2{^;MrKdU8n z>8!=SB^L@^x%w>d6Z21%doLzBOw4LiaFCM@`D)3bIz>59boPYcgofq~%>10+dtF)(m2fOaZRRywHy?uJ}ErCnbe>zWr8s0=^5}4ttZqwL@misJ#g$ame{SMyZj?B#Hk;^mg#W?% z5RbpiQ|A3n%kp_tW?c7vU-dcL=l5QR*Z==0W@~ryY<(q?dU#@wvm8o@!w5rCDcWX6O*8P&Tj|esJdYa4n`PaPHOA{Zo z@N%CN5%Ig#p}cTH<`3ET-yXl86<2;bbDO8ZwHw)%Z*!NwK5ff2>)^Wk!6(eyRz?M$ zm@4%?B$q9A|K`m>_xzHXD!F%lH)&sQ=J$}9>;A{4t@2F$chXksT&h3bC#-qI`}?&c z9&=t^e^I__%f2|db*jF_@?B>&mwjhie!67qIll_oaHalR`&??aB^Vb(-M?2Pm)Sq9 zMET-3E9-;n-bovVE%7_DcDknCQ3s7KX056H-oA-)rrgg()4oI>zrT8G+1$MI+%q1P z#4LXu$N%0|TD)N5qk)Ba~2JS)XQZ|*$}-uLG} zy!dZYeDc`wA1;3LZ)q$%BU-F~D!uVmrkZ5Kc=HtFCDE_eZ@LO+JUOq=bIjn-dx?ci#+=@Yy@7Ka+61jx z>Oal9%Bqvrwj^FqQuvAWrB`;x+BeMWiEuwL@#31F0+Jg~Y4&-3`lnGX`tg3}4`b#( z&L=ht{**|5%=~1gU8URi7VA!?Wy+uCmn?61RdUeQ=bm1S+5E&ByL7QTr}8%xKYMgd zIQZ$Am&^0x_c!dau5Wl$yi9smL7cPy#F9yWXFe*g7fKJja`d%g?*0nV<%MqFH=Ht@ zyKoCj+RV8M;axlWC5#LE-e(@UcVL^rYNIpHy)9UMy--XGpp-8zT=KEIiF z<$T{e(}C+^s@$`C)z9YCezSXi=j8nN|8KAsFuKaxHJ;1aH(}L|ZIfpi#(v)Rbjq4f zZG659YR}eWE|b~3V^-9Ob&;0g3!Zk>$8Ncs&Gawg&%y??z4Nvo`k+^httWQN zGj07%VLuyZmg+Qmq}irh@t@tKdwyPE@%)?8OtCZ5cB-@Xt&7V0H8p#wc573pm_(oE zd7HUGFKZmF($Df{8_f$8>Hb!gb-&iAhfn6R;KwbpJw_KgS2$ca?I;(evu_UHVrg5e zzItw%Y^JOSELAUmCg0TI{BmU4<+H`yKR(^uwaK}Lwa*~??}`#r=1%keX*}m8UQB<( zoVGJ(-y|>gl$Yl(Dp_t+*Nt4CagkrZ#7xKR@W%R0Y2E9t82z4Dy;RDyR~oHbr< zs9jy&zBcQS{lEHvsuZ3xiSxdic&o0SabJFB|Lad2t5m-8)b#$&S-3lHeR%pC=A{)0 z52On^oTR6|X?uQ0boSibM}B^#{T`dQM;)A2!)m>IBz%kJ;O6H_qG6y>04s z!+U!sUY>u$gYohK(U{b8nVj+SKka&P(0|pP6oEGj-+S(7sZnDLZ>o<_PTTKL!9V%X zq3+jHi_YyzJv}ie|3}^2=@Tpt7uY}1KOt-1SM$nd=?<=SjYrIy_7^{Po^f6*^-5uj z|Keu{zG_?-h`RWUwZH1%!6Ra~R==n!SFpPyAnzjYx2ocvo&G-|&6DNF_^hUN6jn*6 z^CxXFOOTK_@|;V#ZAbgWh1>hH>vzYwDowW8*!sDDQfSYc$6K@>9$&FwaztS3_0aBv z693DWY*Xf%+1%Eh66*YKW}#7$!p7Nm{)#gGkN$tvw?yUFu}QVbum0Rp|0T3L|KDHl zYH$1fr>?o0EC_#@lX|my$G69GPF3w{Yu7hi7iHLR`p!q~Gx}FqX8tf(c_njU{f~C> z`fr7&89%-FvvwETnhgQhpOqVI-O?*9JnMf@g0S)4!xsZCO3?d{tN z%DK6PZ>gO#xg~tj!DNB$-9t%tAC@|}Fdr7#bb0aK+rdUBzBo+EY+s>r^i}Vsc5%Z) zT(Jt5e{ZopSi1C0RIilW!|0_stlkxCsWg03iEDQ`UI55jF(a8sHxq^zU%^bH^Kt@70->m@&Og6fw zRPXP3$=l2GF%#IF*Lzhi3NSD*@IhNI@Uk#~0SRz0Ffiy96y;~7CYO{>aO69rAmDoa zo5-@?Vt02gC|&rG=@p}!g!C+?vkuaG_g+X^toH8T{GZ184e#Z5MfZF7MFu~;T{L<9 zMGoz$nXBsmR9TAdu8B|IqkenQ2ltYukoV3z&V}7+IQDB9&xOqs9xU7ued&SaY$-*B zHPmPUe(w(F*t)}f&c%m)uAMpJ{=akof%TiFv1w<2W&dJcTKaWP zqQ;J%__TMn>-V0wOMmvh{{DZ~1jhZ6FN7^3^Yf-}kM*CfefF(sRru8PQC21s1SL|_ z|14Uo{4MXA{A)Lz37Pe)e@r~k@j1daG}Zs-+D~CJyXvw#Yu3FF>d38qqhl4bc4gAh zqj{HhuTwf}Y2LKV?8D3kpGkKXoN@7)al-S7p^CwdGo|afdcJGLJic&V)y+UF!DLE( z`08a2`$PZSJ+R|Ignojsx?yI5QfYb8b?=1y%=K#zdpzQvqr~c@we?Zu>v~;#j;~n~ zY>6rXFOEJ+JbFaJ&-k%EE8CiOQ8lx+^*4>?URcS=W4Ug8wq)b9r9UD&8F_@9 z{+w7ErZ(4KhoSMLhwWAOs+lvU?`WuJ&04hd@zg4jin$T%RbATGK57rK{IlqYQu}j_ zKYd(V<>k+PopdBs?%IQMlb1=mu}x!D>wBJG_NYu+A4A8_OFm2A8B4_99ox!!O5MP{Ma0gX_NgnEg|GY)0eI8Qs|xK>27JGkUu z--L6QdIkO;oWl6bKR&CgezuW?dj9l#4}aT=yuB2C=FOy~`i`g6-z?Ys%~RA;*fQz3 z<&?%JM=F*`c2BzYck-thk8Qq(F50)sICjqaN9}rbd-nIMZi~G+W9#l6w_KNYZ@sBk zSJ&G3>YZLFL)waOZuPg`-dwWC_k857DVDFkGU>!Dnc>>C%VpYWi~grAx0wnRul(P6 zcKMx6Pf~S%X;gERf8f44Px*Ij&cxoY3+rX*TGpi3od$j8*Z8QA!#M&m1WCO#7!v`dS%X{hMjemVVa?{mB7HqULI-}(Lg{{H=p8ye(!zHs_nm#Y40dpz`KQgZ&)`}wR| zJfX?WI;k&DF5}`+VbL?tsk#_culRUd_W2N7A&)I7UqTX=eDRSxu}6Dv+CCxHzUw*{ zW(IsC}+1x&1*02S93mUx4O<*vcmtsCBMG;&s}_Gctm<6dn6Rhe0)z( z;ARw(oiVD^&tN95oE?Y0tmAs58)~@SQvtPfA($oJSgVNvF5?tLNyj6F`hZb z7x`y*7BPt%?=?LiHo0Z~c7q1Tq>g!3A*Xy^&aHQL+!Ch2e`RHx+Pdf;GTb44!LHg{ zFO=V&ch>*^TUxPD+a3WzJY^jeiWzJQti`+V~`3MLzL3S57`zPG0& z>Zj?}=chbaZ@*n}wa+6@^*ir{2%kAmEvvI0nFXnFMI?H5MNJZZ6FEmtsnL}C^$h`! zwys$Ztn^pb_jI0#R+}DOb^egrJMKA)i@NlcT&>iMsu;X(7zHeQ`N}mtF}nX)f1|MG zvAX1kiv7nN?tXRN#nb=d(_D+Zy!HP>!q=YoXgf=Gzwh_#J>`N-O+s?oUq9#+RQl`G zoVtE;&5ySW(T*!G{3-hIS7GZuWf4}1#T>#C$5eeD8Ks>ts*}-9^SX3W z$4+h8>MhF0_8Vk2XfF&`e74_T?#<+F#p^$Mibq<1mwv`~^3w8|m#ltEewydnl{9zL zl0x1}hxIf1uOwGK+EG8Dx4t;$(XOJ9@XB?~=dE^JJh=9_yT%)thi13;zj^fT+Mc@y zv)JQHKYXoW=dU~H@bkk2rp9;2d_x{BTL0=m@t3ogU&JhL$-D4MEO8n~=z{KzKD({0 zj1u=Nctf?x`rkP=N9hGXRK^>sZN9AE3Fd5$H=G7$ zO#We{3s(NtQ+IQyu{Bt5^JEi0Fk`ZVy!7V(rp=HB!e3wg&08$Y1VQRIzxB+8E1CS? zRAh6HcOF>T=D)s|g}_QKCseb57?T52HNo_SQl-uFQ-4DO0mRv#$Hxwm*?gh&IxC1V z86 zN@i*nBRH_89%Phe^7EK_k5Lh3Fw+u`>GF(>;voKXOGZX%rqdpicVCp5eC{g`*oDY_ z98|Nf_)MS2$fyC3sTXCPrzS z%rHoZf+z5?B=tp~y!nNg7#K=f7#I{0<}xraOb(mQ#LTD<4xY2F%dSmfU|=}Lz`&q{ zqUuY;^gw1t15ofx{`p^;=|<%Ah0M@sM{Z2XqUib`Ia%(J{B$1{Mo91@7u@P7Dp$u& zzW7uVtP*6$^k^1FX{H&8(<@k@Q80&vQQGcfA_GH^tD}prt6pvjC>)S88Mn-%YEYk( zhXK;}M3`Tn1rD6a_y2=a#$?0K(y}MB7#PxX;#2d|GxJi>)8OQdU!<8nW=%f#1zg%s z{`*Cm=~&@psjr&gU_zM8z#xpwVfa-(*Ltnpr!!?;FIOd%sCD zy=zf?d)ZgEvnZ(;C=NXDm*8eU7HZ}C6iC;P+1A`tD0|RPY&FBCttokkj);saL zG?Q1?LcRFcb(dFrZd09mm0n_vdj;F8B=zrTX8}OuNrbF8m`hdBbmEu-mKo_VoI(F)-Ni zqwAk~1+4!}HOJ(CQ2o4rq?xpCgN1GXKw|nx!4u~eCYZc9#1a(BP+tn2J)p7 PgA>DTK?a7+FF`y2(W&;Q