From ed1a18b66b3ab0c69e8efad6dd8c36e03fb74477 Mon Sep 17 00:00:00 2001 From: ms622 <ms622@hdm-stuttgart.de> Date: Mon, 11 Dec 2023 11:20:44 +0100 Subject: [PATCH] update: player textures, fix: hit detection #36 #18 --- .../Controller/GameSceneController.java | 10 +- .../Model/Entity/EnemyHandler.java | 9 ++ .../battlearena/Model/Entity/EntityClass.java | 8 ++ .../Model/Entity/EntityFactory.java | 4 +- .../battlearena/Model/Entity/IEntity.java | 2 + .../battlearena/Model/Entity/Player.java | 100 +++++++++++++++--- .../resources/textures/player/HumanDown01.png | Bin 0 -> 1862 bytes .../resources/textures/player/HumanDown02.png | Bin 0 -> 1917 bytes 8 files changed, 111 insertions(+), 22 deletions(-) create mode 100644 src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityClass.java create mode 100644 src/main/resources/textures/player/HumanDown01.png create mode 100644 src/main/resources/textures/player/HumanDown02.png diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Controller/GameSceneController.java b/src/main/java/de/hdm_stuttgart/battlearena/Controller/GameSceneController.java index 3882c1e0..9594f016 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Controller/GameSceneController.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Controller/GameSceneController.java @@ -1,5 +1,6 @@ package de.hdm_stuttgart.battlearena.Controller; +import de.hdm_stuttgart.battlearena.Model.Entity.EntityClass; import de.hdm_stuttgart.battlearena.Model.Entity.EntityFactory; import de.hdm_stuttgart.battlearena.Model.Entity.EntityType; import de.hdm_stuttgart.battlearena.Model.Entity.IEntity; @@ -32,6 +33,9 @@ public class GameSceneController implements Initializable { IEntity player; IEntity enemy; + EntityClass playerClass = EntityClass.HUMAN; + EntityClass enemyClass = EntityClass.HUMAN; + TileManager tileManager; //map data @@ -63,8 +67,8 @@ public class GameSceneController implements Initializable { graphicsContext2D = canvas2D.getGraphicsContext2D(); graphicsContext2D.setImageSmoothing(false); - player = EntityFactory.createEntity(EntityType.PLAYER, graphicsContext2D, inputHandler); - enemy = EntityFactory.createEntity(EntityType.ENEMY_PLAYER, graphicsContext2D, inputHandler); + player = EntityFactory.createEntity(EntityType.PLAYER, graphicsContext2D, inputHandler, playerClass); + enemy = EntityFactory.createEntity(EntityType.ENEMY_PLAYER, graphicsContext2D, inputHandler, enemyClass); tileManager = new TileManager(graphicsContext2D, diffTileCount, horizontalTileCount, verticalTileCount, mapString); @@ -72,8 +76,8 @@ public class GameSceneController implements Initializable { @Override public void handle(long l) { graphicsContext2D.clearRect(0, 0, canvas2D.getWidth(), canvas2D.getHeight()); - updateContent(); renderContent(graphicsContext2D); + updateContent(); } }; gameLoop.start(); diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EnemyHandler.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EnemyHandler.java index a34f2234..75ae76e9 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EnemyHandler.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EnemyHandler.java @@ -19,6 +19,8 @@ class EnemyHandler implements IEntity{ private int entitySpeed = 3; + private int health = 10; + @Override public void initializeEntity() { @@ -65,4 +67,11 @@ class EnemyHandler implements IEntity{ return 3; } + @Override + public int gotHit(int damageDone) { + log.debug(health); + return health -= damageDone; + } + + } \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityClass.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityClass.java new file mode 100644 index 00000000..03b800ac --- /dev/null +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityClass.java @@ -0,0 +1,8 @@ +package de.hdm_stuttgart.battlearena.Model.Entity; + +public enum EntityClass { + HUMAN, + HIGH_BORN, + LOW_BORN, + SENTINELS +} \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityFactory.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityFactory.java index 189243ff..fdc56cc2 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityFactory.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/EntityFactory.java @@ -11,10 +11,10 @@ public class EntityFactory { private static final Logger log = LogManager.getLogger(EntityFactory.class); - public static IEntity createEntity(EntityType entityType, GraphicsContext gameScene, InputHandler inputHandler) { + public static IEntity createEntity(EntityType entityType, GraphicsContext gameScene, InputHandler inputHandler, EntityClass entityClass) { if (entityType == EntityType.PLAYER) { log.debug("Entity " + entityType + " created"); - return new Player(gameScene, inputHandler); + return new Player(gameScene, inputHandler, entityClass); } else if (entityType == EntityType.ENEMY_PLAYER) { log.debug("Entity " + entityType + " created"); return new EnemyHandler(); diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/IEntity.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/IEntity.java index 9f0d3412..8914040b 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/IEntity.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/IEntity.java @@ -24,4 +24,6 @@ public interface IEntity { int getEntitySpeed(); + int gotHit(int damageDone); + } \ No newline at end of file diff --git a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/Player.java b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/Player.java index f3242a2d..8472c377 100644 --- a/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/Player.java +++ b/src/main/java/de/hdm_stuttgart/battlearena/Model/Entity/Player.java @@ -37,6 +37,8 @@ class Player implements IEntity { swordLeft, swordRight; + private final EntityClass entityClass; + private int spriteCounter = 0; private int spriteNumber = 1; @@ -48,9 +50,13 @@ class Player implements IEntity { private int playerSpeed; private EntityDirection playerDirection; - public Player(GraphicsContext gameScene, InputHandler inputHandler) { + private int health = 10; + private int damage = 1; + + public Player(GraphicsContext gameScene, InputHandler inputHandler, EntityClass entityClass) { this.gameScene = gameScene; this.inputHandler = inputHandler; + this.entityClass = entityClass; initializeEntity(); loadEntitySprites(); @@ -68,23 +74,75 @@ class Player implements IEntity { @Override public void loadEntitySprites() { try { - directionDownOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/downOne.png"))); - directionDownTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/downTwo.png"))); - directionUpOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upOne.png"))); - directionUpTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upTwo.png"))); - directionLeftOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftOne.png"))); - directionLeftTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftTwo.png"))); - directionRightOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightOne.png"))); - directionRightTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightTwo.png"))); - swordUp = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordUp.png"))); - swordDown = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordDown.png"))); - swordLeft = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordLeft.png"))); - swordRight = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordRight.png"))); + if (entityClass == EntityClass.HUMAN) { + loadHumanSprites(); + loadWeaponSprites(); + } else if (entityClass == EntityClass.HIGH_BORN) { + loadHighBornSprites(); + loadWeaponSprites(); + } else if (entityClass == EntityClass.LOW_BORN) { + loadLowBornSprites(); + loadWeaponSprites(); + } else { + loadSentinelsSprites(); + loadWeaponSprites(); + } } catch (Exception e) { log.error(e); } } + private void loadHumanSprites() { + directionDownOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown01.png"))); + directionDownTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown02.png"))); + directionUpOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upOne.png"))); + directionUpTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upTwo.png"))); + directionLeftOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftOne.png"))); + directionLeftTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftTwo.png"))); + directionRightOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightOne.png"))); + directionRightTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightTwo.png"))); + } + + private void loadHighBornSprites() { + directionDownOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown01.png"))); + directionDownTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown02.png"))); + directionUpOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upOne.png"))); + directionUpTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upTwo.png"))); + directionLeftOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftOne.png"))); + directionLeftTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftTwo.png"))); + directionRightOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightOne.png"))); + directionRightTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightTwo.png"))); + } + + private void loadLowBornSprites() { + directionDownOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown01.png"))); + directionDownTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown02.png"))); + directionUpOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upOne.png"))); + directionUpTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upTwo.png"))); + directionLeftOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftOne.png"))); + directionLeftTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftTwo.png"))); + directionRightOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightOne.png"))); + directionRightTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightTwo.png"))); + } + + private void loadSentinelsSprites() { + directionDownOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown01.png"))); + directionDownTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/HumanDown02.png"))); + directionUpOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upOne.png"))); + directionUpTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/upTwo.png"))); + directionLeftOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftOne.png"))); + directionLeftTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/leftTwo.png"))); + directionRightOne = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightOne.png"))); + directionRightTwo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/player/rightTwo.png"))); + } + + private void loadWeaponSprites() { + swordUp = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordUp.png"))); + swordDown = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordDown.png"))); + swordLeft = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordLeft.png"))); + swordRight = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/textures/weapons/SwordRight.png"))); + } + @Override public void updateEntityMovement(GameSceneController gameScene) { if (inputHandler.isMoveUp() || inputHandler.isMoveDown() || inputHandler.isMoveLeft() || inputHandler.isMoveRight()) { @@ -144,6 +202,9 @@ class Player implements IEntity { @Override public void attack(IEntity entity, GraphicsContext graphicsContext) { BoundingBox hitBox; + + //Added and subtracted numbers from variables are the pixel insets of the player sprite + int attackRange = 30; int attackWidth = 10; @@ -153,7 +214,7 @@ class Player implements IEntity { graphicsContext.strokeRect(mapPosX+playerWidth, mapPosY-10, attackWidth, attackRange); graphicsContext.drawImage(swordUp, mapPosX+8, mapPosY-10, 32, 32); if (hitBox.intersects(entity.getBoxCollider())) { - //todo: implement health + entity.gotHit(damage); graphicsContext.strokeText("Hit", 10, 10); } } else if (playerDirection == EntityDirection.DOWN) { @@ -161,7 +222,7 @@ class Player implements IEntity { graphicsContext.strokeRect(mapPosX+playerWidth, mapPosY+playerHeight, attackWidth, attackRange); graphicsContext.drawImage(swordDown, mapPosX+8, mapPosY+playerHeight, 32, 32); if (hitBox.intersects(entity.getBoxCollider())) { - //todo: implement health + entity.gotHit(damage); graphicsContext.strokeText("Hit", 10, 10); } } else if (playerDirection == EntityDirection.LEFT) { @@ -171,7 +232,7 @@ class Player implements IEntity { attackRange, attackWidth); graphicsContext.drawImage(swordLeft, mapPosX-8, mapPosY+8, 32, 32); if (hitBox.intersects(entity.getBoxCollider())) { - //todo: implement health + entity.gotHit(damage); graphicsContext.strokeText("Hit", 10, 10); } } else { @@ -181,7 +242,7 @@ class Player implements IEntity { attackRange, attackWidth); graphicsContext.drawImage(swordRight, mapPosX+playerWidth+8, mapPosY+8, 32, 32); if (hitBox.intersects(entity.getBoxCollider())) { - //todo: implement health + entity.gotHit(damage); graphicsContext.strokeText("Hit", 10, 10); } } @@ -262,6 +323,11 @@ class Player implements IEntity { return playerSpeed; } + @Override + public int gotHit(int damageDone) { + return health -= damageDone; + } + public int getMapPosX() { return mapPosX; } diff --git a/src/main/resources/textures/player/HumanDown01.png b/src/main/resources/textures/player/HumanDown01.png new file mode 100644 index 0000000000000000000000000000000000000000..ee8c9024a240bfec9f28cdecffff3060d3eb769e GIT binary patch literal 1862 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4(FKU@Xmab`HpPc6ZLt$u9~nNK8(3 z$t*6&NvsSoW?;~mSUO>^_u&AMqyDRdE?9N&$;udYI$ycORaTgxE#hhr!n!(mRvl+< zjf!Sap>Vk75BZ3Lkp&w%LJA5C1YFn!@6NH(+>udnZ+gfrrF+Mp{<WA>yffy2bbzGx zHztjj(<b^HS+e!Yt|!&a?el_HrEOZVNQdj+-`%f2U;KK{za!FjcbULV|Cs6L^rn~1 zV+yYS8+&#B$yri=?_Y83l@xn0v2$u}H|IT7Il~OiN2?y}Ieon8vfg~_c~ev7{FoMT zi7TsZho{bR>n}Cz)4NjFZf(ACZ~oQr=|^Q=1)fP1R+H!o2yA3weOUkJa-V&lZc%tb zfL=e7&M6m9LE%kDK3`avC}dQ~;rMF8j^fvK{A+)o%*}l-IwQB>oc^s_PRtf_7f!x< z`&I>ugcL*GD<9Jk_g4$QJu5o!o6}$hQ`>uu&56$rDVA5)^Sr2j_$Qg?gDg|o)X(dc z&%Kpuo!_Yamt9;lYfmtn<7r?#RHR0Druq6ZXaU(A46KZ749q|lBLfqVkYZp3vl$q? z7^UItAVv*@n)XZv7O0viAPoX7K+FiInHDg?RR}C#MzBFj4W%+?0x8Y{kH}&M1`%Hn zW}I@WSD%4_xg;|rq9nrC$0|8LS1&OoKPgqOBDVmfi@~PC3dqb&ElE_U$j!+swyLmI z0;{kBvO&W7N(x{lCE2!05xxNm&iO^D3TAo+dIm~%TnY*bHbp6ERzWUqQ0+jTtx`rw zNr9EVetCJhUb(Seeo?x<p{1pzzJZaxk&!M?g>G?WUP)qwZeFo6#1NP{E~&-IMVSR9 znfZANAafIw@=Hr>m6Sjh!2!gbDamkq3QCJ|z_z3$>!;?V=BDPA6zd!68R}!xSCW~A zaA96CG&q0(qYsh+YBRv9&9k5+*#sC;t`$J{K>Y`FXfoK|;*u17BnA3L1_l<o21dF@ zmilo20iAD?l5ACyS(1|q4mh}fz#-_EQ-UfAQV$A(oJ>&2TID3>rQ0f1=%%EmC6?xt zDA{?G0{!WdU!G@RXrm8Nh-v^t6xCcCeJoC}0eRdiGAOk;Kc^HF^mc~EMmFH!KoLbm z0z^jyRvpNq=sE&2@=Nl8iK-|w*)y*swWy#7n83g`!tBGX0^KZx<)L|*C3Y|a(1ek6 zAw`gtV^K+Yeo=M^I5JQ|5~nJtNsv%QN~e%a0FD7*F0kXW(TC?KJFfn>Y%0JUT<q!M z7-AvV8?@1j*->EbWtr)R+_<$_JvVGH-Z~?QmHAb;%SMrw1l_vk{RzU%;vHd0KB<W- zIoSR(K3$b_AZ4!kbj$wTyeWs%($eqEt~IWf+Zle~p~hsbv~xvYWDXwqUMp;tuabK5 z@%*KCZ(W?gyi=*Tk4f;v`=?z??s?5ldVfeQWTwu&PzQtK+T2P0;mNaAU){XQRP=0j z^;(IlzG=;wx*|eX_A{?^x+HMo+4I(}ZqY3hW-}Ks-}6Xn*d~1Mkbl|oyHW*>C37x+ zbmH#3v-EA%fs|La(=u28Qsnp{-W&f>zAAph;k~yM*Jxand|;Ne=|uZ_mkDw1*(E_+ zkL;VoIFacW*DdjTvuv!}7M@=1<kZ$b+wjiGhNnTH3M~JO0~(q9@0MmVZ_htdpH;Vt ziS@)=!=3tB4sO<ym+G!c`sel8d&%AH(Fboti3DEih(2H<Y_#I$`vWHD&bMsXT(7_- wu~_WK%xU}TrFssD&2C;~Fn7+?a?xe>Lhq-%{WoptEl?rn>FVdQ&MBb@0Lqh*&Hw-a literal 0 HcmV?d00001 diff --git a/src/main/resources/textures/player/HumanDown02.png b/src/main/resources/textures/player/HumanDown02.png new file mode 100644 index 0000000000000000000000000000000000000000..3a96754826bed31e6baad1d519a71c2e97680821 GIT binary patch literal 1917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4(FKU@Xmab`HpPc6ZLt$u9~nNK8(3 z$t*6&NvsSoW?;~mSUO>^_u&AMqyDRdE?9N&$;udYI$ycORaTgxE#hhr!n!(mRvl+< zjf!Sap>Vk75BZ3Lkp&w%LJA5C1YFn!@6NH(+>udnZ+gfrrF+Mp{<WA>yffy2bbzGx zHztjj(<b^HS+e!Yt|!&a?el_HrEOZVNQdj+-`%f2U;KK{za!FjcbULV|Cs6L^rn~1 zV+yYS8+&#B$yri=?_Y83l@xn0v2$u}H|IT7Il~OiN2?y}Ieon8vfg~_c~ev7{FoMT zi7TsZho{bR>n}Cz)4NjFZf(ACZ~oQr=|^Q=1)fP1R+H!o2yA3weOUkJa-V&lZc%tb zfL=e7&M6m9LE%kDK3`avC}dQ~;rMF8j^fvK{A+)o%*}l-IwQB>oc^s_PRtf_7f!x< z`&I>ugcL*GD<9Jk_g4$QJu5o!o6}$hQ`>uu&56$rDVA5)^Sr2j_$Qg?gDg|o)X(dc z&%Kpuo!_Yamt9;lYfmtn<7r?#RHR0Druq6ZXaU(A46KZ749q|lBLfqVkYZp3vl$q? z7^UItAVv*@n)XZv7O0viAPoX7K+FiInHDg?RR}C#MzBFj4W%+?0x8Y{kH}&M1`%Hn zW}I@WSD%4_xg;|rq9nrC$0|8LS1&OoKPgqOBDVmfi@~PC3dqb&ElE_U$j!+swyLmI z0;{kBvO&W7N(x{lCE2!05xxNm&iO^D3TAo+dIm~%TnY*bHbp6ERzWUqQ0+jTtx`rw zNr9EVetCJhUb(Seeo?x<p{1pzzJZaxk&!M?g>G?WUP)qwZeFo6#1NP{E~&-IMVSR9 znfZANAafIw@=Hr>m6Sjh!2!gbDamkq3QCJ|z_z3$>!;?V=BDPA6zd!68R}!xSCW~A zaA96CG&q0(qYsh+YBRv9&9k5+*#sC;t`$J{K>Y`FXfoK|;*u17BnA3L1_l<o21dF@ zmilo20iAD?l5ACyS(1|q4mh}fz#-_EQ-UfAQV$A(oJ>&2TID3>rQ0f1=%%EmC6?xt zDA{?G0{!WdU!G@RWTOvJh-v^t6xCcCeJoC}0eRdiGAOk;Kc^HF^mc~EKr=B!5s?7V z5rI_)vM9QafQ<Z-d|;v~%1rjmD@iRXC;}!hu#GVLaH~K!3t@R^US^3M%m6fDBwa`m zWaU^?Ql4Lw9RiLFl#s-!3ThH0RFTptBolyR0GJExxNP*{Im(V}F5l!rU=Cj8>Eak- zAy^u`-<zpWq`qA9xqvILFY6?WEveBQ>slqAT)1;7fW=9q)udfu%NCd9WZsztZKkcy zL@q|Sxcy~5>U%e_YVY~e>+R2d?yS52d(ZjjcdOs;%X*T}c6ge)=%*t>S#}EqdDwD| z>lHPpoBZ3cWrCMA&lk~)wOkPb``wZzRn43?_4Bbai?wf`{;sVs=j+KtOY`Ob{MQE@ zty5M=uMhPTZI@fanS6nx(QNhO1)+kP97(@_cRD2-_FUM`ezaMDyTtpMXvf?9l@UK4 zGTq&A=|fZGlQ{Xy($*JKjwNjj)OFXGw}O-NU){IxKf7P4`=uLh)iM0vV$if$)%erB zpD!=j9g$7!^*fb#%VURtrT0tG!<9D5bz73pti6@hY1ZsE*;4s)c1qm5%eAUpjJ?OD zmF!NihJ@S7u3&m_%K8|`tlLwVUOd?;xNPP^{wIlEHeB)!-)$$nEj#kwsX^lL79Y2i z_@V>5tQ~Uhi*Z{d+DzhJ)KO8k>iX*g)h4!%-EaO1JGxX`N4KqeJ;mC_>0)E~!L&uQ y@7_IjDpg%z^Fr<;2d+xI`89i&!#$mr+DG;o6|?-7YN*Wzm5rXRelF{r5}E)@XsTua literal 0 HcmV?d00001 -- GitLab