From 991c60944f5bf9209880d12a287ab85ff38b8f74 Mon Sep 17 00:00:00 2001 From: Jonathan Hager Date: Sun, 26 Apr 2020 23:38:03 +0200 Subject: [PATCH 1/3] Leider keine 5dimensionalen Arrays :( --- .../dungeoncrawler/control/Controller.java | 2 +- .../com/dungeoncrawler/view/GameScreen.java | 5 +- core/src/com/dungeoncrawler/view/Map.java | 28 +------ .../com/dungeoncrawler/view/MapContainer.java | 78 +++++++++++++++++++ .../com/dungeoncrawler/view/MapGenerator.java | 37 +++++---- 5 files changed, 108 insertions(+), 42 deletions(-) create mode 100644 core/src/com/dungeoncrawler/view/MapContainer.java diff --git a/core/src/com/dungeoncrawler/control/Controller.java b/core/src/com/dungeoncrawler/control/Controller.java index 2e7af6f..bef9b95 100644 --- a/core/src/com/dungeoncrawler/control/Controller.java +++ b/core/src/com/dungeoncrawler/control/Controller.java @@ -159,7 +159,7 @@ public class Controller extends ApplicationAdapter implements InputProcessor{ public void updateObjects(int level, int roomPosX, int roomPosY){ - MapLayers layers = m.getM().getMaps()[level][roomPosX][roomPosY].getLayers(); + MapLayers layers = m.getM().getMaps()[level][roomPosX][roomPosY].getMap().getLayers(); MapObjects objects = layers.get(0).getObjects(); //System.out.println(objects.getCount()); diff --git a/core/src/com/dungeoncrawler/view/GameScreen.java b/core/src/com/dungeoncrawler/view/GameScreen.java index 0feab51..f432b15 100644 --- a/core/src/com/dungeoncrawler/view/GameScreen.java +++ b/core/src/com/dungeoncrawler/view/GameScreen.java @@ -85,8 +85,7 @@ public class GameScreen { MapGenerator mg = new MapGenerator(new Texture(Gdx.files.internal("tilesets/tileset_floor_1.png"))); - TiledMap[][][] maps = mg.generateMap(d); - m.setMaps(maps); + m = mg.generateMap(d); mg.ichWillSpielen(m.getMaps()); tm = new TiledMap(); @@ -107,7 +106,7 @@ public class GameScreen { player.setX(p.getxPos()); player.setY(p.getyPos()); - tm = getM().getMaps()[level][roomPosX][roomPosY]; + tm = getM().getMaps()[level][roomPosX][roomPosY].getMap(); if(tm == null){ System.out.println("Dein scheiß geht net"); diff --git a/core/src/com/dungeoncrawler/view/Map.java b/core/src/com/dungeoncrawler/view/Map.java index 2bc0cd0..fd87c75 100644 --- a/core/src/com/dungeoncrawler/view/Map.java +++ b/core/src/com/dungeoncrawler/view/Map.java @@ -6,16 +6,12 @@ package com.dungeoncrawler.view; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.maps.tiled.TiledMap; - /** * * @author jonathan */ public class Map { - private TiledMap[][][] maps; - private Sprite[] animatedObjects; + private MapContainer[][][] maps; public Map(){ @@ -24,33 +20,15 @@ public class Map { /** * @return the maps */ - public TiledMap[][][] getMaps() { + public MapContainer[][][] getMaps() { return maps; } /** * @param maps the maps to set */ - public void setMaps(TiledMap[][][] maps) { + public void setMaps(MapContainer[][][] maps) { this.maps = maps; } - - /** - * @return the animatedObjects - */ - public Sprite[] getAnimatedObjects() { - return animatedObjects; - } - - /** - * @param animatedObjects the animatedObjects to set - */ - public void setAnimatedObjects(Sprite[] animatedObjects) { - this.animatedObjects = animatedObjects; - } - - public void setAnimatedObjects(Sprite animatedObjects, int i) { - this.animatedObjects[i] = animatedObjects; - } } diff --git a/core/src/com/dungeoncrawler/view/MapContainer.java b/core/src/com/dungeoncrawler/view/MapContainer.java new file mode 100644 index 0000000..9372548 --- /dev/null +++ b/core/src/com/dungeoncrawler/view/MapContainer.java @@ -0,0 +1,78 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.dungeoncrawler.view; + +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.maps.tiled.TiledMap; + +/** + * + * @author jonathan + */ +public class MapContainer { + private TiledMap map; + private Sprite[] animatedObjects; + private TextureRegion[][][] textures; + + public MapContainer(TiledMap map, int objectAmount){ + this.map = map; + this.animatedObjects = new Sprite[objectAmount]; + this.textures = new TextureRegion[objectAmount][][]; + } + + /** + * @return the map + */ + public TiledMap getMap() { + return map; + } + + /** + * @param map the map to set + */ + public void setMap(TiledMap map) { + this.map = map; + } + + /** + * @return the animatedObjects + */ + public Sprite[] getAnimatedObjects() { + return animatedObjects; + } + + /** + * @param animatedObjects the animatedObjects to set + */ + public void setAnimatedObjects(Sprite[] animatedObjects) { + this.animatedObjects = animatedObjects; + } + + public void setAnimatedObjects(Sprite animatedObject, int i) { + this.animatedObjects[i] = animatedObject; + } + + /** + * @return the textures + */ + public TextureRegion[][][] getTextures() { + return textures; + } + + /** + * @param textures the textures to set + */ + public void setTextures(TextureRegion[][][] textures) { + this.textures = textures; + } + + public void setTextures(TextureRegion[][] textures, int i) { + this.textures[i] = textures; + } + + +} diff --git a/core/src/com/dungeoncrawler/view/MapGenerator.java b/core/src/com/dungeoncrawler/view/MapGenerator.java index 5142b50..cdfe994 100644 --- a/core/src/com/dungeoncrawler/view/MapGenerator.java +++ b/core/src/com/dungeoncrawler/view/MapGenerator.java @@ -25,32 +25,39 @@ public class MapGenerator { Texture tiles; TextureRegion[][] splitTiles; + Texture torchT; + TextureRegion[][] torch; public MapGenerator(Texture tiles){ this.tiles = tiles; splitTiles = TextureRegion.split(this.tiles, 48, 48); + torchT = new Texture("sprites/torch.png"); + torch = TextureRegion.split(torchT, 48, 48); } - public TiledMap[][][] generateMap(Dungeon d){ + public Map generateMap(Dungeon d){ + Map temp = new Map(); + int levelAmount = d.getLevel().length; - TiledMap[][][] tempMap = new TiledMap[levelAmount][][]; + MapContainer[][][] tempMap = new MapContainer[levelAmount][][]; // Jedes Level wird generiert for(int i = 0; i < levelAmount; i++){ - TiledMap[][] tempLevel = generateLevel(i, d.getLevel()[i]); + MapContainer[][] tempLevel = generateLevel(i, d.getLevel()[i]); tempMap[i] = tempLevel; } - return tempMap; + temp.setMaps(tempMap); + return temp; } - private TiledMap[][] generateLevel(int i, Level l){ + private MapContainer[][] generateLevel(int i, Level l){ int sizeX = l.getRooms().length; int sizeY = l.getRooms()[0].length; - TiledMap[][] tempLevel = new TiledMap[sizeX][sizeY]; + MapContainer[][] tempLevel = new MapContainer[sizeX][sizeY]; for(int x = 0; x < sizeX; x++){ for(int y = 0; y < sizeY; y++){ @@ -63,8 +70,9 @@ public class MapGenerator { int mapDimensionX = tempX + 2; int mapDimensionY = tempY + 2; - // Raum wird generiertf - TiledMap tempRoom = generateRoom(room, tempX, tempY, i); + // Raum wird generiert + MapContainer temp = generateRoom(room, tempX, tempY, i); + TiledMap tempRoom = temp.getMap(); // Wenn es Fehler gibt, dann wohl hier: Viel Spaß beim Suchen! Danke! MapLayer collisionLayer = tempRoom.getLayers().get(0); @@ -173,7 +181,8 @@ public class MapGenerator { collisionLayer.getObjects().add(tempBottom); } - tempLevel[x][y] = tempRoom; + temp.setMap(tempRoom); + tempLevel[x][y] = temp; } } @@ -182,7 +191,7 @@ public class MapGenerator { return tempLevel; } - private TiledMap generateRoom(Room r, int roomDimensionX, int roomDimensionY, int lvl){ + private MapContainer generateRoom(Room r, int roomDimensionX, int roomDimensionY, int lvl){ int bodenX; int bodenY; @@ -196,6 +205,7 @@ public class MapGenerator { bodenY = lvl - 4; } + MapContainer temp; TiledMap tempRoom = new TiledMap(); // roomDimension bezieht sich auf die Größe des Raumes, da aber noch die Wände fehlen, @@ -298,13 +308,14 @@ public class MapGenerator { layers.add(dynamicLayer); layers.add(staticLayer); - return tempRoom; + temp = new MapContainer(tempRoom, 0); + return temp; } - public void ichWillSpielen(TiledMap[][][] map){ + public void ichWillSpielen(MapContainer[][][] map){ for(int i=0;i Date: Mon, 27 Apr 2020 12:56:12 +0200 Subject: [PATCH 2/3] Raytracing funktioniert --- .../dungeoncrawler/control/Controller.java | 1 + .../dungeoncrawler/view/AnimatedObject.java | 70 +++++++++++++++++++ .../com/dungeoncrawler/view/GameScreen.java | 23 ++++++ .../com/dungeoncrawler/view/MapContainer.java | 46 +++--------- .../com/dungeoncrawler/view/MapGenerator.java | 42 +++++------ 5 files changed, 126 insertions(+), 56 deletions(-) create mode 100644 core/src/com/dungeoncrawler/view/AnimatedObject.java diff --git a/core/src/com/dungeoncrawler/control/Controller.java b/core/src/com/dungeoncrawler/control/Controller.java index bef9b95..5c3748e 100644 --- a/core/src/com/dungeoncrawler/control/Controller.java +++ b/core/src/com/dungeoncrawler/control/Controller.java @@ -143,6 +143,7 @@ public class Controller extends ApplicationAdapter implements InputProcessor{ if(tileX == 0 || tileX == roomX || tileY == 0 || tileY == roomY){ updateRoom(); } + // Render methode zum rendern der einzelnen Sprites wird aufgerufen diff --git a/core/src/com/dungeoncrawler/view/AnimatedObject.java b/core/src/com/dungeoncrawler/view/AnimatedObject.java new file mode 100644 index 0000000..6ae8fe9 --- /dev/null +++ b/core/src/com/dungeoncrawler/view/AnimatedObject.java @@ -0,0 +1,70 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.dungeoncrawler.view; + +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.TextureRegion; + +/** + * + * @author jonathan + */ +public class AnimatedObject { + private Sprite sprite; + private TextureRegion[][] texture; + private int frame; + private int row; + + public AnimatedObject(Texture tx, int tileWidth, int tileHeight){ + texture = TextureRegion.split(tx, tileWidth, tileHeight); + + frame = (int) (Math.random()*texture[0].length); + row = (int) (Math.random()*texture.length); + + sprite = new Sprite(texture[row][frame]); + } + + public void updateTexture(){ + if(frame >= texture[0].length - 1){ + frame = 0; + } + else{ + frame++; + } + + sprite.setRegion(texture[row][frame]); + + } + + /** + * @return the sprite + */ + public Sprite getSprite() { + return sprite; + } + + /** + * @param sprite the sprite to set + */ + public void setSprite(Sprite sprite) { + this.sprite = sprite; + } + + /** + * @return the texture + */ + public TextureRegion[][] getTexture() { + return texture; + } + + /** + * @param texture the texture to set + */ + public void setTexture(TextureRegion[][] texture) { + this.texture = texture; + } +} diff --git a/core/src/com/dungeoncrawler/view/GameScreen.java b/core/src/com/dungeoncrawler/view/GameScreen.java index f432b15..893a124 100644 --- a/core/src/com/dungeoncrawler/view/GameScreen.java +++ b/core/src/com/dungeoncrawler/view/GameScreen.java @@ -12,9 +12,11 @@ import com.badlogic.gdx.maps.tiled.TiledMap; import com.badlogic.gdx.maps.tiled.TiledMapRenderer; import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer; import com.badlogic.gdx.math.Intersector; +import com.badlogic.gdx.utils.Timer; import com.dungeoncrawler.model.Dungeon; import com.dungeoncrawler.model.Entity; import com.dungeoncrawler.model.entities.*; +import java.util.ArrayList; public class GameScreen { //CONTROLS @@ -44,6 +46,9 @@ public class GameScreen { TiledMapRenderer tmr; TiledMap tm; OrthographicCamera camera; + ArrayList objects; + + Timer animations; // Sound public Music music; @@ -94,6 +99,18 @@ public class GameScreen { music = Gdx.audio.newMusic(Gdx.files.internal("music/gamemusic.mp3")); music.setVolume(volume); music.play(); + + animations = new Timer(); + animations.scheduleTask(new Timer.Task() { + @Override + public void run() { + if(objects != null){ + for(AnimatedObject object : objects){ + object.updateTexture(); + } + } + } + },0, 0.1f); } @@ -107,6 +124,7 @@ public class GameScreen { player.setY(p.getyPos()); tm = getM().getMaps()[level][roomPosX][roomPosY].getMap(); + objects = getM().getMaps()[level][roomPosX][roomPosY].getObjects(); if(tm == null){ System.out.println("Dein scheiß geht net"); @@ -161,6 +179,10 @@ public class GameScreen { //BATCH batch.begin(); + for(AnimatedObject object : objects){ + object.getSprite().draw(batch); + } + player.draw(batch); //controls.draw(batch); //DRAW'T JEDES ENTITY - prueft vorher ob vorhanden @@ -227,6 +249,7 @@ public class GameScreen { arrowSprites[i].draw(batch); } } + batch.end(); } diff --git a/core/src/com/dungeoncrawler/view/MapContainer.java b/core/src/com/dungeoncrawler/view/MapContainer.java index 9372548..bc5bf81 100644 --- a/core/src/com/dungeoncrawler/view/MapContainer.java +++ b/core/src/com/dungeoncrawler/view/MapContainer.java @@ -5,9 +5,8 @@ */ package com.dungeoncrawler.view; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.maps.tiled.TiledMap; +import java.util.ArrayList; /** * @@ -15,13 +14,11 @@ import com.badlogic.gdx.maps.tiled.TiledMap; */ public class MapContainer { private TiledMap map; - private Sprite[] animatedObjects; - private TextureRegion[][][] textures; + private ArrayList objects; - public MapContainer(TiledMap map, int objectAmount){ + public MapContainer(TiledMap map){ this.map = map; - this.animatedObjects = new Sprite[objectAmount]; - this.textures = new TextureRegion[objectAmount][][]; + this.objects = new ArrayList<>(); } /** @@ -39,40 +36,17 @@ public class MapContainer { } /** - * @return the animatedObjects + * @return the objects */ - public Sprite[] getAnimatedObjects() { - return animatedObjects; + public ArrayList getObjects() { + return objects; } /** - * @param animatedObjects the animatedObjects to set + * @param objects the objects to set */ - public void setAnimatedObjects(Sprite[] animatedObjects) { - this.animatedObjects = animatedObjects; + public void setObjects(ArrayList objects) { + this.objects = objects; } - public void setAnimatedObjects(Sprite animatedObject, int i) { - this.animatedObjects[i] = animatedObject; - } - - /** - * @return the textures - */ - public TextureRegion[][][] getTextures() { - return textures; - } - - /** - * @param textures the textures to set - */ - public void setTextures(TextureRegion[][][] textures) { - this.textures = textures; - } - - public void setTextures(TextureRegion[][] textures, int i) { - this.textures[i] = textures; - } - - } diff --git a/core/src/com/dungeoncrawler/view/MapGenerator.java b/core/src/com/dungeoncrawler/view/MapGenerator.java index cdfe994..1a2a2c9 100644 --- a/core/src/com/dungeoncrawler/view/MapGenerator.java +++ b/core/src/com/dungeoncrawler/view/MapGenerator.java @@ -26,13 +26,12 @@ public class MapGenerator { Texture tiles; TextureRegion[][] splitTiles; Texture torchT; - TextureRegion[][] torch; public MapGenerator(Texture tiles){ this.tiles = tiles; splitTiles = TextureRegion.split(this.tiles, 48, 48); torchT = new Texture("sprites/torch.png"); - torch = TextureRegion.split(torchT, 48, 48); + //torch = TextureRegion.split(torchT, 48, 48); } public Map generateMap(Dungeon d){ @@ -121,9 +120,13 @@ public class MapGenerator { // X: Gesamtlänge, Y: Exakte Mitte der Gesamtlänge staticLayer.getCell(tempX + 1, (tempY / 2) + 0).setTile(new StaticTiledMapTile(splitTiles[4][4])); //rechts-1 staticLayer.getCell(tempX + 1, (tempY / 2) + 1).setTile(new StaticTiledMapTile(splitTiles[0][0])); //rechts1 - staticLayer.getCell(tempX + 1, (tempY / 2) + 2).setTile(new StaticTiledMapTile(splitTiles[3][1])); //rechts2 - staticLayer.getCell(tempX + 1, (tempY / 2) + 3).setTile(new StaticTiledMapTile(splitTiles[2][1])); //rechts3 + staticLayer.getCell(tempX + 1, (tempY / 2) + 2).setTile(new StaticTiledMapTile(splitTiles[1][1])); //rechts2 + staticLayer.getCell(tempX + 1, (tempY / 2) + 3).setTile(new StaticTiledMapTile(splitTiles[0][1])); //rechts3 staticLayer.getCell(tempX + 1, (tempY / 2) + 4).setTile(new StaticTiledMapTile(splitTiles[2][5])); //rechts4 + + AnimatedObject tempObject = new AnimatedObject(torchT, 48, 48); + tempObject.getSprite().setPosition((tempX + 1) * 48, ((tempY / 2) + 2) * 48); + temp.getObjects().add(tempObject); } collisionLayer.getObjects().remove(right); @@ -167,9 +170,13 @@ public class MapGenerator { // X: 0, Y: Exakte Mitte der Gesamtlänge staticLayer.getCell(0, (tempY / 2) + 0).setTile(new StaticTiledMapTile(splitTiles[4][5])); //links-1 staticLayer.getCell(0, (tempY / 2) + 1).setTile(new StaticTiledMapTile(splitTiles[0][0])); //links1 - staticLayer.getCell(0, (tempY / 2) + 2).setTile(new StaticTiledMapTile(splitTiles[3][1])); //links2 - staticLayer.getCell(0, (tempY / 2) + 3).setTile(new StaticTiledMapTile(splitTiles[2][1])); //links3 + staticLayer.getCell(0, (tempY / 2) + 2).setTile(new StaticTiledMapTile(splitTiles[1][1])); //links2 + staticLayer.getCell(0, (tempY / 2) + 3).setTile(new StaticTiledMapTile(splitTiles[0][1])); //links3 staticLayer.getCell(0, (tempY / 2) + 4).setTile(new StaticTiledMapTile(splitTiles[3][5])); //links4 + + AnimatedObject tempObject = new AnimatedObject(torchT, 48, 48); + tempObject.getSprite().setPosition(0, ((tempY / 2) + 2) * 48); + temp.getObjects().add(tempObject); } collisionLayer.getObjects().remove(left); @@ -192,6 +199,8 @@ public class MapGenerator { } private MapContainer generateRoom(Room r, int roomDimensionX, int roomDimensionY, int lvl){ + TiledMap tempRoom = new TiledMap(); + MapContainer temp = new MapContainer(tempRoom); int bodenX; int bodenY; @@ -205,9 +214,6 @@ public class MapGenerator { bodenY = lvl - 4; } - MapContainer temp; - TiledMap tempRoom = new TiledMap(); - // roomDimension bezieht sich auf die Größe des Raumes, da aber noch die Wände fehlen, // muss auf die Größe jeweils 2 addiert werden. int mapDimensionX = roomDimensionX + 2; @@ -258,20 +264,17 @@ public class MapGenerator { // oben1 else if(y == mapDimensionY - 1){ if(x == roomDimensionX / 2 - 1 || x == roomDimensionX / 2 + 3){ - cell.setTile(new StaticTiledMapTile(splitTiles[3][1])); - } - else{ - cell.setTile(new StaticTiledMapTile(splitTiles[1][1])); + + AnimatedObject tempObject = new AnimatedObject(torchT, 48, 48); + tempObject.getSprite().setPosition(x * 48, y * 48); + temp.getObjects().add(tempObject); } + + cell.setTile(new StaticTiledMapTile(splitTiles[1][1])); } // oben2 else if(y == mapDimensionY){ - if(x == roomDimensionX / 2 - 1 || x == roomDimensionX / 2 + 3){ - cell.setTile(new StaticTiledMapTile(splitTiles[2][1])); - } - else{ - cell.setTile(new StaticTiledMapTile(splitTiles[0][1])); - } + cell.setTile(new StaticTiledMapTile(splitTiles[0][1])); } // oben3 else if(y == mapDimensionY + 1){ @@ -308,7 +311,6 @@ public class MapGenerator { layers.add(dynamicLayer); layers.add(staticLayer); - temp = new MapContainer(tempRoom, 0); return temp; } From b100268a965a38b0f4a5fd118d0a53db024fe353 Mon Sep 17 00:00:00 2001 From: Jonathan Hager Date: Mon, 27 Apr 2020 12:56:50 +0200 Subject: [PATCH 3/3] Raytracing funktioniert besser --- core/assets/sprites/torch.png | Bin 987 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 core/assets/sprites/torch.png diff --git a/core/assets/sprites/torch.png b/core/assets/sprites/torch.png deleted file mode 100644 index 4601909e5cae90e9e6a94b7f6037f957dc37944e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 987 zcmeAS@N?(olHy`uVBq!ia0y~yV0-{%8*s1z$&+(e@&N@}GM$|RJe{2t3X1a6GILTH z7&Io>zVA-hPRaD66qY;fa8`IvrgWUZULz3%7_yl^X2)!ad7GMN_Y@Df{5T z{-dj!yEm`nTi2xUgYnUm7fW6!ss7W~+|u#!!4CQN?`+@QWBivkb!A!sQ-JAd5A{b$ zdi%B7;sjk-n3yD{%vh;z+#Olbx4!zvk1FxUk@ueellkj)Fr~p?WnS{GM8SN4^Epvg z&ufz!r>eI8m{W0Q0k@ESQEb`I-r|#q_UA=XaL5OKW{JDGUiTJ@x&0 zOqfM}Vc6=@Yx~se6L&0Fo3g{Nn1xeEu~Wq5#EQjDS~^EEu6h_wT=sWIyZxgd!A~Zg z3}sY4&Xg6PXj%8c{>R<5k#lC1Og>b&;Q7&Q_HKe?w#LgGaj-pR7Lcl+WPL67RMr9*nd8B?(s8FU~*3?7ZFK{;b>4)$+^v z9j5Jy+Q-Pp*SJwAb$#`o-P?C>uRp)#_iskC&qe(@v+8C8qlGQW+ua371Hn({-St3< zv%n*=n1O-s2naJy)#j513bL1Y`ns||VUZGL5(;pi5C@FO8=fwXAr-gYUO$-E6d>Yy zk@?gA_%(Lyd?x2u9@_57R`r!)*AD?vndA05Dr`KaH{k|LhEN1c@ zJ3F^3vs=IS*k>0Xui0i7UA4d3`o(tJBFESFt54PLShCME{pBCO%WF&QZqHYpS)8SN z!PZ`qN&C$6|6(zYe{?(c|2H_WPNCtn`(DOrN|&7LBoZ`(zH@mA{0uB^;5Gcj%(Fqe zLy+xdV1C2Wjz1IR*eV)CR5^FlNF)@n9;`pY7SX0)|D>I9n&KzspOO#$p9|>Q(c~e( ztmC?b{gd&5AeNVk_BS&v06>?37>KjvBUzE(Se$AbG{hAIde=pU<7q&}*ZivuFPmYX>x6FzAZn-xd5nB@+&ax&WQZyU1a}e8y`EG7$@e3R!qJ z2y-N~7#^@%5?0G~$mP{HFo!)pPNjxRh0RxYg@ zg3EwT^;6(t0h-I(#58d}qg(S8?SRgNhPe(5$Iml7wokeO@{JYCS4Defo*hjJ_RN2l z^IElP2sr07TvX&@c`2D7%Vbf