From 8f3114e377a8da9e577714de7052ee16fa539cb7 Mon Sep 17 00:00:00 2001 From: Michael Fabian Dirks Date: Mon, 24 Nov 2014 18:18:24 +0100 Subject: [PATCH] Add projects including README.md(s), .gitignore(s) and the actual project files. Signed-off-by: Michael Fabian Dirks --- .gitignore | 0 BlitzBasic/.gitignore | 8 + .../All/Advanced Text/01 Colored Text.bb | 23 + BlitzBasic/All/Advanced Text/AdvText.bb | 193 ++ BlitzBasic/All/Advanced Text/README.md | 8 + .../LinkedListEmulation.bb | 258 +++ BlitzBasic/All/LinkedList Emulation/README.md | 9 + BlitzBasic/All/Random Stuff/LinkedList.bb | 258 +++ BlitzBasic/All/Random Stuff/Logger.bb | 27 + BlitzBasic/All/Random Stuff/NetCode.bb | 665 ++++++ BlitzBasic/All/Random Stuff/README.md | 8 + BlitzBasic/All/Random Stuff/Test.bb | 44 + BlitzBasic/All/Random Stuff/Tradelane.bb | 207 ++ BlitzBasic/All/Random Stuff/TrueMotion.bb | 51 + BlitzBasic/All/Random Stuff/VectorMath.bb | 161 ++ .../All/Sirius Online Inventory/README.md | 8 + .../Sirius Online Inventory/SOInventory.bb | 407 ++++ .../HelpersAndFixes/HelpersAndFixes.bb | 227 ++ BlitzBasic/Blitz3D/HelpersAndFixes/README.md | 9 + .../Impostor/CreateImpostorTextures.bb | 282 +++ BlitzBasic/Blitz3D/Impostor/Cube.imp | Bin 0 -> 22 bytes BlitzBasic/Blitz3D/Impostor/Cube.png | Bin 0 -> 96015 bytes BlitzBasic/Blitz3D/Impostor/Example01_Cube.bb | 47 + BlitzBasic/Blitz3D/Impostor/FastExt.bb | 496 ++++ BlitzBasic/Blitz3D/Impostor/FreeImage.bb | 1297 +++++++++++ BlitzBasic/Blitz3D/Impostor/Impostor.bb | 122 + BlitzBasic/Blitz3D/Impostor/Impostor.ipf | 18 + BlitzBasic/Blitz3D/Impostor/Preview.imp | Bin 0 -> 22 bytes BlitzBasic/Blitz3D/Impostor/Preview.png | Bin 0 -> 1494525 bytes BlitzBasic/Blitz3D/Impostor/PreviewNormal.imp | Bin 0 -> 22 bytes BlitzBasic/Blitz3D/Impostor/PreviewNormal.png | Bin 0 -> 1296421 bytes BlitzBasic/Blitz3D/Impostor/README.md | 9 + .../Blitz3D/Level of Detail/01 Small Test.bb | 41 + .../Blitz3D/Level of Detail/LevelOfDetail.bb | 163 ++ BlitzBasic/Blitz3D/Level of Detail/README.md | 8 + BlitzBasic/Blitz3D/Motion Blur/README.md | 8 + .../01 Moving and Rotating Cube.bb | 42 + .../TrueMotion.bb | 51 + .../01 Moving and Rotating Cube.bb | 42 + .../TrueMotion.bb | 82 + BlitzBasic/Blitz3D/TiledSprite/Example01.bb | 267 +++ BlitzBasic/Blitz3D/TiledSprite/README.md | 9 + BlitzBasic/Blitz3D/TiledSprite/TiledSprite.bb | 537 +++++ .../TiledSprite/TiledSprite_Test01.fw.png | Bin 0 -> 344180 bytes .../Userlib/BlitzUtility/BlitzUtility.bb | 85 + .../Userlib/BlitzUtility/BlitzUtility.cpp | 137 ++ .../Userlib/BlitzUtility/BlitzUtility.decls | 20 + BlitzBasic/Userlib/BlitzUtility/README.md | 9 + BlitzBasic/Userlib/InputEx/InputEx.bb | 322 +++ BlitzBasic/Userlib/InputEx/InputEx.decls | 32 + BlitzBasic/Userlib/InputEx/README.md | 9 + BlitzMax/.gitignore | 6 + .../Sirius Online Launcher/#Old/FileHash.bmx | 124 + .../#Old/Patcher.old.bmx | 197 ++ .../#Old/ThreadPool.bmx | 242 ++ BlitzMax/Sirius Online Launcher/Clock.c | 14 + .../GFX/FNT/TranscendsGames.otf | Bin 0 -> 22780 bytes .../GFX/LNC/BARxPROGRESS.png | Bin 0 -> 817 bytes .../GFX/LNC/BTNxACCOUNT.png | Bin 0 -> 1448 bytes .../GFX/LNC/BTNxCHECK.png | Bin 0 -> 1096 bytes .../GFX/LNC/BTNxCLOSE.png | Bin 0 -> 1229 bytes .../GFX/LNC/BTNxEULATOS.png | Bin 0 -> 1488 bytes .../GFX/LNC/BTNxPATCH.png | Bin 0 -> 1371 bytes .../GFX/LNC/BTNxPLAY.png | Bin 0 -> 1353 bytes .../GFX/LNC/BTNxRESTART.png | Bin 0 -> 1353 bytes .../GFX/LNC/BTNxSUPPORT.png | Bin 0 -> 56925 bytes .../GFX/LNC/BTNxWEBSITE.png | Bin 0 -> 56903 bytes .../GFX/LNC/GUIxSTYLE.png | Bin 0 -> 86643 bytes .../GFX/LNC/LAUxPATxA.fw.png | Bin 0 -> 163404 bytes .../GFX/LNC/LAUxPATxA.png | Bin 0 -> 30166 bytes .../GFX/LNC/LAUxPATxB.png | Bin 0 -> 693579 bytes BlitzMax/Sirius Online Launcher/Launcher.bmx | 488 ++++ .../Sirius Online Launcher/Max2DExtended.bmx | 300 +++ BlitzMax/Sirius Online Launcher/README.md | 9 + .../Sirius Online Launcher/SFX/M/launcher.ogg | Bin 0 -> 3442554 bytes .../Sirius Online Launcher/SFX/UI/MxCL.wav | Bin 0 -> 29038 bytes .../Sirius Online Launcher/SFX/UI/MxOV.ogg | Bin 0 -> 16860 bytes .../Sirius Online Launcher/SFX/UI/MxRE.wav | Bin 0 -> 67714 bytes BlitzMax/Sirius Online Launcher/TDigest.bmx | 285 +++ BlitzMax/Sirius Online Launcher/TGUI.bmx | 184 ++ BlitzMax/Sirius Online Launcher/TPatcher.bmx | 435 ++++ BlitzMax/Sirius Online Server/BlitzNet.bmx | 1139 +++++++++ BlitzMax/Sirius Online Server/README.md | 8 + BlitzMax/Sirius Online Server/Server.bmx | 639 ++++++ BlitzMax/xaymar.config/README.md | 9 + BlitzMax/xaymar.config/config.bmx | 366 +++ BlitzMax/xaymar.datapak/README.md | 11 + BlitzMax/xaymar.datapak/datapak.bmx | 1089 +++++++++ BlitzMax/xaymar.datapak/example1.bmx | 35 + BlitzMax/xaymar.datapak/example2.bmx | 27 + BlitzMax/xaymar.desktop/README.md | 8 + BlitzMax/xaymar.desktop/Test01.bmx | 104 + BlitzMax/xaymar.resource/README.md | 11 + BlitzMax/xaymar.resource/brl-support.bmx | 166 ++ BlitzMax/xaymar.resource/datapak-support.bmx | 37 + .../xaymar.resource/example-NoThreading.bmx | 106 + BlitzMax/xaymar.resource/resource.bmx | 299 +++ .../Flowing Water (GLSL)/DiffuseMap_01.png | Bin 0 -> 960046 bytes .../Flowing Water (GLSL)/Flowmap_01.fw.png | Bin 0 -> 49785 bytes .../Flowing Water (GLSL)/Flowmap_02.fw.png | Bin 0 -> 50394 bytes .../Flowing Water (GLSL)/NormalMap_01.jpg | Bin 0 -> 53365 bytes .../Flowing Water (GLSL)/Plane.blend | Bin 0 -> 635448 bytes .../Flowing Water (GLSL)/Plane.blend1 | Bin 0 -> 635448 bytes .../Flowing Water (GLSL)/Plane.mtl | 10 + .../Flowing Water (GLSL)/README.md | 8 + .../Flowing Water (GLSL)/Shader.txt | 259 +++ .../Flowing Water (GLSL)/WaterShaders.rfx | 2028 +++++++++++++++++ .../Smart Filter (GLSL)/Error.txt | 7 + .../Smart Filter (GLSL)/README.md | 8 + .../Smart Filter (GLSL)/SmartFilter.fp.glsl | 260 +++ .../Smart Filter (GLSL)/SmartFilter.rfx | 1345 +++++++++++ .../Smart Filter (GLSL)/SmartFilter.vp.glsl | 15 + .../Smart Filter (GLSL)/maxstools-s.png | Bin 0 -> 5437 bytes .../Smart Filter (GLSL)/maxstools.png | Bin 0 -> 27867 bytes .../Smart Filter (GLSL)/sfltproc.bmx | 257 +++ .../Smart Filter (GLSL)/test-s.png | Bin 0 -> 138 bytes .../Smart Filter (GLSL)/test.png | Bin 0 -> 154 bytes .../Smart Filter (GLSL)/test01-s.png | Bin 0 -> 1544 bytes .../Smart Filter (GLSL)/test01.png | Bin 0 -> 949 bytes .../Smart Filter (GLSL)/test02-s.png | Bin 0 -> 294 bytes .../Smart Filter (GLSL)/test02.png | Bin 0 -> 1321 bytes .../Smart Filter (GLSL)/test03-s.png | Bin 0 -> 1750 bytes .../Smart Filter (GLSL)/test03.png | Bin 0 -> 999 bytes .../Smart Filter (GLSL)/usage.txt | 20 + Java/.gitignore | 3 + Java/ExtraGenerators (CraftBukkit)/.gitignore | 4 + Java/ExtraGenerators (CraftBukkit)/LICENSE | 354 +++ Java/ExtraGenerators (CraftBukkit)/README.md | 8 + .../images/Generator_Empty.fw.png | Bin 0 -> 154339 bytes .../images/Generator_Empty.png | Bin 0 -> 8876 bytes .../images/Template.fw.png | Bin 0 -> 154851 bytes .../images/Text_Generators.fw.png | Bin 0 -> 67115 bytes .../images/Text_Generators.png | Bin 0 -> 3816 bytes .../images/Text_Overview.fw.png | Bin 0 -> 63592 bytes .../images/Text_Overview.png | Bin 0 -> 3370 bytes .../images/Text_Populators.fw.png | Bin 0 -> 69541 bytes .../images/Text_Populators.png | Bin 0 -> 3747 bytes .../images/Title.fw.png | Bin 0 -> 294917 bytes .../images/Title.png | Bin 0 -> 19443 bytes Java/ExtraGenerators (CraftBukkit)/pom.xml | 129 ++ .../ExtraGenerators/Generators/Empty.java | 41 + .../ExtraGenerators/Generators/Generator.java | 69 + .../RealityBends/ExtraGenerators/Plugin.java | 151 ++ .../ExtraGenerators/Populators/Populator.java | 15 + .../Populators/SkyIslands.java | 73 + .../ExtraGenerators/World/Configuration.java | 86 + .../ExtraGenerators/World/Handler.java | 63 + .../src/main/resources/plugin.yml | 19 + Java/Inception (CraftBukkit)/.gitignore | 4 + Java/Inception (CraftBukkit)/README.md | 8 + .../dependency-reduced-pom.xml | 99 + .../nb-configuration.xml | 60 + Java/Inception (CraftBukkit)/pom.xml | 129 ++ .../de/RealityBends/Inception/Plugin.java | 784 +++++++ .../RealityBends/Inception/PluginMetrics.java | 132 ++ .../de/RealityBends/Inception/Utility.java | 181 ++ .../RealityBends/Inception/World/Cache.java | 53 + .../Inception/World/CacheQueries.java | 38 + .../RealityBends/Inception/World/Handler.java | 1413 ++++++++++++ .../Inception/World/OverlapDelayBlocks.java | 65 + .../Inception/World/OverlapEventExecutor.java | 76 + .../Inception/World/OverlapEvents.java | 57 + .../src/main/resources/plugin.yml | 27 + README.md | 56 +- Web-based/Stream2VLC/README.md | 8 + Web-based/Stream2VLC/getTwitchData.php | 144 ++ Web-based/Stream2VLC/index.html | 405 ++++ Web-based/myGravatar.php | 4 + Web-based/relink.php | 8 + desktop.ini | 4 + 170 files changed, 22028 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 BlitzBasic/.gitignore create mode 100644 BlitzBasic/All/Advanced Text/01 Colored Text.bb create mode 100644 BlitzBasic/All/Advanced Text/AdvText.bb create mode 100644 BlitzBasic/All/Advanced Text/README.md create mode 100644 BlitzBasic/All/LinkedList Emulation/LinkedListEmulation.bb create mode 100644 BlitzBasic/All/LinkedList Emulation/README.md create mode 100644 BlitzBasic/All/Random Stuff/LinkedList.bb create mode 100644 BlitzBasic/All/Random Stuff/Logger.bb create mode 100644 BlitzBasic/All/Random Stuff/NetCode.bb create mode 100644 BlitzBasic/All/Random Stuff/README.md create mode 100644 BlitzBasic/All/Random Stuff/Test.bb create mode 100644 BlitzBasic/All/Random Stuff/Tradelane.bb create mode 100644 BlitzBasic/All/Random Stuff/TrueMotion.bb create mode 100644 BlitzBasic/All/Random Stuff/VectorMath.bb create mode 100644 BlitzBasic/All/Sirius Online Inventory/README.md create mode 100644 BlitzBasic/All/Sirius Online Inventory/SOInventory.bb create mode 100644 BlitzBasic/Blitz3D/HelpersAndFixes/HelpersAndFixes.bb create mode 100644 BlitzBasic/Blitz3D/HelpersAndFixes/README.md create mode 100644 BlitzBasic/Blitz3D/Impostor/CreateImpostorTextures.bb create mode 100644 BlitzBasic/Blitz3D/Impostor/Cube.imp create mode 100644 BlitzBasic/Blitz3D/Impostor/Cube.png create mode 100644 BlitzBasic/Blitz3D/Impostor/Example01_Cube.bb create mode 100644 BlitzBasic/Blitz3D/Impostor/FastExt.bb create mode 100644 BlitzBasic/Blitz3D/Impostor/FreeImage.bb create mode 100644 BlitzBasic/Blitz3D/Impostor/Impostor.bb create mode 100644 BlitzBasic/Blitz3D/Impostor/Impostor.ipf create mode 100644 BlitzBasic/Blitz3D/Impostor/Preview.imp create mode 100644 BlitzBasic/Blitz3D/Impostor/Preview.png create mode 100644 BlitzBasic/Blitz3D/Impostor/PreviewNormal.imp create mode 100644 BlitzBasic/Blitz3D/Impostor/PreviewNormal.png create mode 100644 BlitzBasic/Blitz3D/Impostor/README.md create mode 100644 BlitzBasic/Blitz3D/Level of Detail/01 Small Test.bb create mode 100644 BlitzBasic/Blitz3D/Level of Detail/LevelOfDetail.bb create mode 100644 BlitzBasic/Blitz3D/Level of Detail/README.md create mode 100644 BlitzBasic/Blitz3D/Motion Blur/README.md create mode 100644 BlitzBasic/Blitz3D/Motion Blur/Version 1 - Render to Screen/01 Moving and Rotating Cube.bb create mode 100644 BlitzBasic/Blitz3D/Motion Blur/Version 1 - Render to Screen/TrueMotion.bb create mode 100644 BlitzBasic/Blitz3D/Motion Blur/Version 2 - Render to Texture (TODO)/01 Moving and Rotating Cube.bb create mode 100644 BlitzBasic/Blitz3D/Motion Blur/Version 2 - Render to Texture (TODO)/TrueMotion.bb create mode 100644 BlitzBasic/Blitz3D/TiledSprite/Example01.bb create mode 100644 BlitzBasic/Blitz3D/TiledSprite/README.md create mode 100644 BlitzBasic/Blitz3D/TiledSprite/TiledSprite.bb create mode 100644 BlitzBasic/Blitz3D/TiledSprite/TiledSprite_Test01.fw.png create mode 100644 BlitzBasic/Userlib/BlitzUtility/BlitzUtility.bb create mode 100644 BlitzBasic/Userlib/BlitzUtility/BlitzUtility.cpp create mode 100644 BlitzBasic/Userlib/BlitzUtility/BlitzUtility.decls create mode 100644 BlitzBasic/Userlib/BlitzUtility/README.md create mode 100644 BlitzBasic/Userlib/InputEx/InputEx.bb create mode 100644 BlitzBasic/Userlib/InputEx/InputEx.decls create mode 100644 BlitzBasic/Userlib/InputEx/README.md create mode 100644 BlitzMax/.gitignore create mode 100644 BlitzMax/Sirius Online Launcher/#Old/FileHash.bmx create mode 100644 BlitzMax/Sirius Online Launcher/#Old/Patcher.old.bmx create mode 100644 BlitzMax/Sirius Online Launcher/#Old/ThreadPool.bmx create mode 100644 BlitzMax/Sirius Online Launcher/Clock.c create mode 100644 BlitzMax/Sirius Online Launcher/GFX/FNT/TranscendsGames.otf create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/BARxPROGRESS.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/BTNxACCOUNT.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/BTNxCHECK.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/BTNxCLOSE.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/BTNxEULATOS.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/BTNxPATCH.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/BTNxPLAY.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/BTNxRESTART.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/BTNxSUPPORT.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/BTNxWEBSITE.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/GUIxSTYLE.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/LAUxPATxA.fw.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/LAUxPATxA.png create mode 100644 BlitzMax/Sirius Online Launcher/GFX/LNC/LAUxPATxB.png create mode 100644 BlitzMax/Sirius Online Launcher/Launcher.bmx create mode 100644 BlitzMax/Sirius Online Launcher/Max2DExtended.bmx create mode 100644 BlitzMax/Sirius Online Launcher/README.md create mode 100644 BlitzMax/Sirius Online Launcher/SFX/M/launcher.ogg create mode 100644 BlitzMax/Sirius Online Launcher/SFX/UI/MxCL.wav create mode 100644 BlitzMax/Sirius Online Launcher/SFX/UI/MxOV.ogg create mode 100644 BlitzMax/Sirius Online Launcher/SFX/UI/MxRE.wav create mode 100644 BlitzMax/Sirius Online Launcher/TDigest.bmx create mode 100644 BlitzMax/Sirius Online Launcher/TGUI.bmx create mode 100644 BlitzMax/Sirius Online Launcher/TPatcher.bmx create mode 100644 BlitzMax/Sirius Online Server/BlitzNet.bmx create mode 100644 BlitzMax/Sirius Online Server/README.md create mode 100644 BlitzMax/Sirius Online Server/Server.bmx create mode 100644 BlitzMax/xaymar.config/README.md create mode 100644 BlitzMax/xaymar.config/config.bmx create mode 100644 BlitzMax/xaymar.datapak/README.md create mode 100644 BlitzMax/xaymar.datapak/datapak.bmx create mode 100644 BlitzMax/xaymar.datapak/example1.bmx create mode 100644 BlitzMax/xaymar.datapak/example2.bmx create mode 100644 BlitzMax/xaymar.desktop/README.md create mode 100644 BlitzMax/xaymar.desktop/Test01.bmx create mode 100644 BlitzMax/xaymar.resource/README.md create mode 100644 BlitzMax/xaymar.resource/brl-support.bmx create mode 100644 BlitzMax/xaymar.resource/datapak-support.bmx create mode 100644 BlitzMax/xaymar.resource/example-NoThreading.bmx create mode 100644 BlitzMax/xaymar.resource/resource.bmx create mode 100644 HLSL & GLSL Shaders/Flowing Water (GLSL)/DiffuseMap_01.png create mode 100644 HLSL & GLSL Shaders/Flowing Water (GLSL)/Flowmap_01.fw.png create mode 100644 HLSL & GLSL Shaders/Flowing Water (GLSL)/Flowmap_02.fw.png create mode 100644 HLSL & GLSL Shaders/Flowing Water (GLSL)/NormalMap_01.jpg create mode 100644 HLSL & GLSL Shaders/Flowing Water (GLSL)/Plane.blend create mode 100644 HLSL & GLSL Shaders/Flowing Water (GLSL)/Plane.blend1 create mode 100644 HLSL & GLSL Shaders/Flowing Water (GLSL)/Plane.mtl create mode 100644 HLSL & GLSL Shaders/Flowing Water (GLSL)/README.md create mode 100644 HLSL & GLSL Shaders/Flowing Water (GLSL)/Shader.txt create mode 100644 HLSL & GLSL Shaders/Flowing Water (GLSL)/WaterShaders.rfx create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/Error.txt create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/README.md create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/SmartFilter.fp.glsl create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/SmartFilter.rfx create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/SmartFilter.vp.glsl create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/maxstools-s.png create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/maxstools.png create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/sfltproc.bmx create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/test-s.png create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/test.png create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/test01-s.png create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/test01.png create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/test02-s.png create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/test02.png create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/test03-s.png create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/test03.png create mode 100644 HLSL & GLSL Shaders/Smart Filter (GLSL)/usage.txt create mode 100644 Java/.gitignore create mode 100644 Java/ExtraGenerators (CraftBukkit)/.gitignore create mode 100644 Java/ExtraGenerators (CraftBukkit)/LICENSE create mode 100644 Java/ExtraGenerators (CraftBukkit)/README.md create mode 100644 Java/ExtraGenerators (CraftBukkit)/images/Generator_Empty.fw.png create mode 100644 Java/ExtraGenerators (CraftBukkit)/images/Generator_Empty.png create mode 100644 Java/ExtraGenerators (CraftBukkit)/images/Template.fw.png create mode 100644 Java/ExtraGenerators (CraftBukkit)/images/Text_Generators.fw.png create mode 100644 Java/ExtraGenerators (CraftBukkit)/images/Text_Generators.png create mode 100644 Java/ExtraGenerators (CraftBukkit)/images/Text_Overview.fw.png create mode 100644 Java/ExtraGenerators (CraftBukkit)/images/Text_Overview.png create mode 100644 Java/ExtraGenerators (CraftBukkit)/images/Text_Populators.fw.png create mode 100644 Java/ExtraGenerators (CraftBukkit)/images/Text_Populators.png create mode 100644 Java/ExtraGenerators (CraftBukkit)/images/Title.fw.png create mode 100644 Java/ExtraGenerators (CraftBukkit)/images/Title.png create mode 100644 Java/ExtraGenerators (CraftBukkit)/pom.xml create mode 100644 Java/ExtraGenerators (CraftBukkit)/src/main/java/de/RealityBends/ExtraGenerators/Generators/Empty.java create mode 100644 Java/ExtraGenerators (CraftBukkit)/src/main/java/de/RealityBends/ExtraGenerators/Generators/Generator.java create mode 100644 Java/ExtraGenerators (CraftBukkit)/src/main/java/de/RealityBends/ExtraGenerators/Plugin.java create mode 100644 Java/ExtraGenerators (CraftBukkit)/src/main/java/de/RealityBends/ExtraGenerators/Populators/Populator.java create mode 100644 Java/ExtraGenerators (CraftBukkit)/src/main/java/de/RealityBends/ExtraGenerators/Populators/SkyIslands.java create mode 100644 Java/ExtraGenerators (CraftBukkit)/src/main/java/de/RealityBends/ExtraGenerators/World/Configuration.java create mode 100644 Java/ExtraGenerators (CraftBukkit)/src/main/java/de/RealityBends/ExtraGenerators/World/Handler.java create mode 100644 Java/ExtraGenerators (CraftBukkit)/src/main/resources/plugin.yml create mode 100644 Java/Inception (CraftBukkit)/.gitignore create mode 100644 Java/Inception (CraftBukkit)/README.md create mode 100644 Java/Inception (CraftBukkit)/dependency-reduced-pom.xml create mode 100644 Java/Inception (CraftBukkit)/nb-configuration.xml create mode 100644 Java/Inception (CraftBukkit)/pom.xml create mode 100644 Java/Inception (CraftBukkit)/src/main/java/de/RealityBends/Inception/Plugin.java create mode 100644 Java/Inception (CraftBukkit)/src/main/java/de/RealityBends/Inception/PluginMetrics.java create mode 100644 Java/Inception (CraftBukkit)/src/main/java/de/RealityBends/Inception/Utility.java create mode 100644 Java/Inception (CraftBukkit)/src/main/java/de/RealityBends/Inception/World/Cache.java create mode 100644 Java/Inception (CraftBukkit)/src/main/java/de/RealityBends/Inception/World/CacheQueries.java create mode 100644 Java/Inception (CraftBukkit)/src/main/java/de/RealityBends/Inception/World/Handler.java create mode 100644 Java/Inception (CraftBukkit)/src/main/java/de/RealityBends/Inception/World/OverlapDelayBlocks.java create mode 100644 Java/Inception (CraftBukkit)/src/main/java/de/RealityBends/Inception/World/OverlapEventExecutor.java create mode 100644 Java/Inception (CraftBukkit)/src/main/java/de/RealityBends/Inception/World/OverlapEvents.java create mode 100644 Java/Inception (CraftBukkit)/src/main/resources/plugin.yml create mode 100644 Web-based/Stream2VLC/README.md create mode 100644 Web-based/Stream2VLC/getTwitchData.php create mode 100644 Web-based/Stream2VLC/index.html create mode 100644 Web-based/myGravatar.php create mode 100644 Web-based/relink.php create mode 100644 desktop.ini diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/BlitzBasic/.gitignore b/BlitzBasic/.gitignore new file mode 100644 index 0000000..f18a99c --- /dev/null +++ b/BlitzBasic/.gitignore @@ -0,0 +1,8 @@ +# Source Backup Files +*.bb_bak2 +*.bb_bak1 + +# Binary Files +*.exe +*.o +*.a \ No newline at end of file diff --git a/BlitzBasic/All/Advanced Text/01 Colored Text.bb b/BlitzBasic/All/Advanced Text/01 Colored Text.bb new file mode 100644 index 0000000..b3de75a --- /dev/null +++ b/BlitzBasic/All/Advanced Text/01 Colored Text.bb @@ -0,0 +1,23 @@ +Global sTestTxt$ +sTestTxt$ = sTestTxt$ + "|fFF0000H|fFF7E00a|fFFFF00l|f7EFF00l|f00FF00o |f00FF7EW|f00FFFFe|f007EFFl|f0000FFt|f7E00FF!|fFF00FF!|fFF007E!"+Chr(10) +sTestTxt$ = sTestTxt$ + Chr(10) +sTestTxt$ = sTestTxt$ + "|fFFFFFFDies ist ein Text der |fFF0000Rot |f00FF00Grün |fFFFFFFund |f0000FFBlau |fFFFFFFist." + Chr(10) +sTestTxt$ = sTestTxt$ + "|f33FF33Man kann alle mögli|f0000FFchen Farben machen!" + Chr(10) +sTestTxt$ = sTestTxt$ + "|f000000|bFF0000Sogar|b-1-1-1 |bFF7E00der|b-1-1-1 |bFFFF00Hinter|b7EFF00grund|b-1-1-1 |b00FF00kann|b-1-1-1 |b00FF7Egesetzt|b-1-1-1 |b00FFFFwerden|b-1-1-1!" + Chr(10) +sTestTxt$ = sTestTxt$ + "|fAAAAFF|b-1-1-1Dies kann für mehr|f444400|bAAAAFFzeilige Selektion|fAAAAFF|b-1-1-1 verwendet werden!" + Chr(10) +sTestTxt$ = sTestTxt$ + "|fFFFFFFD|fFF7E00amit wäre der |b7E7E7E|fFFFFFFB|fFF7E00eispieltext|b-1-1-1 beendet|fFFFFFF!" + +Graphics 400,300,32,2 +SetBuffer BackBuffer() + +Global timer = CreateTimer(30) + +While Not KeyHit(1) + Cls + AdvText(200,150, sTestTxt, MouseX()/200.0, MouseY()/150.0, 1) + + Flip 0 + WaitTimer timer +Wend + +Include "AdvText.bb" \ No newline at end of file diff --git a/BlitzBasic/All/Advanced Text/AdvText.bb b/BlitzBasic/All/Advanced Text/AdvText.bb new file mode 100644 index 0000000..946b775 --- /dev/null +++ b/BlitzBasic/All/Advanced Text/AdvText.bb @@ -0,0 +1,193 @@ +;AdvText Function +Dim SplittedString$(0) +Dim sTextLines$(0,1) +Global SplitCount, AdvText_X, AdvText_Y, AdvText_Width, AdvText_Height +Function AdvText(iX, iY, sText$, iCenterX#=0, iCenterY#=0, fLineSpace#=1) + Local iTextLines = 1, iLine = 0 + + AdvText_X = 0:AdvText_Y = 0:AdvText_Width = 0:AdvText_Height = 0 + + SplitString(sText, Chr(10)) + iTextLines = SplitCount-1 + + Dim sTextLines$(iTextLines,1) + For iLine = 0 To iTextLines + sTextLines(iLine, 0) = SplittedString$(iLine) + Next + + ;Parse the Text so that we get only the visible text into the second slot. + Local iLastClr = 1, tabLength = 0 + For iLine = 0 To iTextLines + iLastClr = 1 + For iPos = 1 To Len(sTextLines(iLine,0)) + sChar$ = Mid(sTextLines(iLine,0), iPos, 1) + If sChar = "|" And (Mid(sTextLines(iLine,0), iPos+1, 1) = "f" Or Mid(sTextLines(iLine,0), iPos+1, 1) = "b") + sTextLines(iLine,1) = sTextLines(iLine,1) + Mid(sTextLines(iLine,0),iLastClr,iPos-iLastClr) + iLastClr = iPos+8 + ElseIf sChar = Chr(9) + sTextLines(iLine,1) = sTextLines(iLine,1) + Mid(sTextLines(iLine,0),iLastClr,iPos-iLastClr) + iLastClr = iPos + + ;Remove Tab Character + sTextLines(iLine,0) = Left(sTextLines(iLine,0), iPos-1) + Right(sTextLines(iLine,0), Len(sTextLines(iLine,0))-iPos) + + tabLength = (4-(Len(sTextLines(iLine,1)) Mod 4)) + For iTabSpace = 1 To tabLength + sTextLines(iLine,0) = Left(sTextLines(iLine,0), iPos-1) + " " + Right(sTextLines(iLine,0), Len(sTextLines(iLine,0))-iPos+1) + Next + ElseIf sChar = Chr(11) + sTextLines(iLine,1) = sTextLines(iLine,1) + Mid(sTextLines(iLine,0),iLastClr,iPos-iLastClr) + iLastClr = iPos + + ;Remove Tab Character + sTextLines(iLine,0) = Left(sTextLines(iLine,0), iPos-1) + Right(sTextLines(iLine,0), Len(sTextLines(iLine,0))-iPos) + + tabLength = (8-(Len(sTextLines(iLine,1)) Mod 8)) + For iTabSpace = 1 To tabLength + sTextLines(iLine,0) = Left(sTextLines(iLine,0), iPos-1) + " " + Right(sTextLines(iLine,0), Len(sTextLines(iLine,0))-iPos+1) + Next + ElseIf iPos = Len(sTextLines(iLine,0)) + sTextLines(iLine,1) = sTextLines(iLine,1) + Mid(sTextLines(iLine,0),iLastClr,iPos-iLastClr+1) + EndIf + Next + ; Return width. + If (AdvText_Width < StringWidth(sTextLines(iLine,1))) Then AdvText_Width = StringWidth(sTextLines(iLine,1)) + Next + + ; Return Height + If (AdvText_Height < (FontHeight()*(iTextLines+1)*fLineSpace)) Then AdvText_Height = (FontHeight()*(iTextLines+1)*fLineSpace) + + ;Real Text Processing + Local iRedO = ColorRed(), iGreenO = ColorGreen(), iBlueO = ColorBlue() ; Original Foreground Color + Local iRed = ColorRed(), iGreen = ColorGreen(), iBlue = ColorBlue() ;Foreground + Local iBGRed = -1, iBGGreen = -1, iBGBlue = -1 ;Background + Local icX, icY, icsX, scText$, iRealPos + For iLine = 0 To iTextLines + sText$ = sTextLines(iLine,0) + icsX = -(StringWidth(sTextLines(iLine,1))*0.5)*iCenterX + icX = icsX + icY = ( -(FontHeight()*(iTextLines+1)*0.5*fLineSpace*iCenterY) + (iLine * FontHeight() * fLineSpace) ) + + ; Return X and Y starting point. + If (AdvText_X > iX + icX) Then AdvText_X = iX + icX + If (AdvText_Y > iY + icY) Then AdvText_Y = iY + icY + + iRealPos = 1 + For iPos = 1 To Len(sText) + sChar$ = Mid(sText, iPos, 1) + If sChar = "|" And Mid(sText, iPos+1, 1) = "f" ;Foreground Change + If iBGRed > -1 And iBGGreen > -1 And iBGBlue > -1 + Color iBGRed, iBGGreen, iBGBlue + Rect iX+icX, iY+icY, StringWidth(scText), FontHeight()*fLineSpace + EndIf + Color iRed, iGreen, iBlue + Text iX+icX, iY+icY, scText$ + + icX = icX + StringWidth(scText$) + scText = "" + + If Mid(sText, iPos+2, 2) = "-1" + iRed = iRedO + iGreen = iGreenO + iBlue = iBlueO + Else + iRed = HexB(Mid(sText, iPos+2, 2)) + iGreen = HexB(Mid(sText, iPos+4, 2)) + iBlue = HexB(Mid(sText, iPos+6, 2)) + EndIf + + sText = Left(sText, iPos)+Mid(sText, iPos+8) + ElseIf sChar = "|" And Mid(sText, iPos+1, 1) = "b" ;Background Change + If iBGRed > -1 And iBGGreen > -1 And iBGBlue > -1 + Color iBGRed, iBGGreen, iBGBlue + Rect iX+icX, iY+icY, StringWidth(scText), FontHeight()*fLineSpace + EndIf + Color iRed, iGreen, iBlue + Text iX+icX, iY+icY, scText$ + + icX = icX + StringWidth(scText$) + scText = "" + + If Mid(sText, iPos+2, 2) = "-1" + iBGRed = -1 + iBGGreen = -1 + iBGBlue = -1 + Else + iBGRed = HexB(Mid(sText, iPos+2, 2)) + iBGGreen = HexB(Mid(sText, iPos+4, 2)) + iBGBlue = HexB(Mid(sText, iPos+6, 2)) + EndIf + sText = Left(sText, iPos)+Mid(sText, iPos+8) + Else + scText$ = scText$ + sChar$ + iRealPos = iRealPos + 1 + EndIf + + If iPos = Len(sText) + If iBGRed > -1 And iBGGreen > -1 And iBGBlue > -1 + Color iBGRed, iBGGreen, iBGBlue + Rect iX+icX, iY+icY, StringWidth(scText), FontHeight()*fLineSpace + EndIf + Color iRed, iGreen, iBlue + Text iX+icX, iY+icY, scText + scText = "" + EndIf + Next + scText$ = "" + Next +End Function + +Function HexB#(Hexzahl$) + Local Integer_Result# + If Left$(Hexzahl$,1)="$" Then Hexzahl$=Mid$(Hexzahl$,2) + For i=1 To Len(Hexzahl$) + tmp1$=Upper$(Mid$(Hexzahl$,i,1)):tmp2=tmp1$ + If tmp2=0 And tmp1$<>"0" Then tmp2=Asc(tmp1$)-55 + Integer_Result=Integer_Result*16:Integer_Result=Integer_Result+tmp2 + Next + Return Integer_Result +End Function + +Function SplitString(In$, StringSplitter$ = "|") + Local InLength% = Len(In) + Local SplitLength% = Len(StringSplitter) + Local CountPos%, InPos%, SplitIndex% + Local SplitTest$, LineText$ + + ; Count how many Lines there are and resize Dim. + SplitCount = 0 + For CountPos = 1 To InLength-(SplitLength-1) + SplitTest = Mid(In,CountPos,1) + If SplitTest = StringSplitter Then SplitCount = SplitCount + 1 + Next + Dim SplittedString(SplitCount) + + ; Split the Text onto multiple lines. + While Not InPos = Len(In) + ; Increment Position + InPos = InPos + 1 + + ; Grab a piece of the text. + SplitTest = Mid(In, InPos, SplitLength) + Local Char$ = Left(SplitTest, 1) + + ; Check if the current Text matches the splitter or if we are near the end. + If SplitTest = StringSplitter Or InPos = InLength + ; Append the current character if it doesn't match the Splitter. + If InPos = InLength And SplitTest <> StringSplitter Then LineText = LineText + Char + + ; Store the Line. + SplittedString(SplitIndex) = LineText + + ; Increment split index. + SplitIndex = SplitIndex + 1 + + ; Reset LineText + LineText = "" + Else + LineText = LineText + Char + EndIf + Wend +End Function +;~IDEal Editor Parameters: +;~C#Blitz3D \ No newline at end of file diff --git a/BlitzBasic/All/Advanced Text/README.md b/BlitzBasic/All/Advanced Text/README.md new file mode 100644 index 0000000..e15e545 --- /dev/null +++ b/BlitzBasic/All/Advanced Text/README.md @@ -0,0 +1,8 @@ +Advanced Text +======================= + +This project adds an advanced text function to BlitzBasic. While somewhat slower, it supports many features and if you cache the result you can get quite good results. It was written for a project that needed such features in the chat, but has been abandoned. + +License +======= +Advanced Text by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/. \ No newline at end of file diff --git a/BlitzBasic/All/LinkedList Emulation/LinkedListEmulation.bb b/BlitzBasic/All/LinkedList Emulation/LinkedListEmulation.bb new file mode 100644 index 0000000..f1a69a3 --- /dev/null +++ b/BlitzBasic/All/LinkedList Emulation/LinkedListEmulation.bb @@ -0,0 +1,258 @@ +;---------------------------------------------------------------- +;-- Types +;---------------------------------------------------------------- +Type TList + Field FirstEntry.TListEntry + Field LastEntry.TListEntry + + Field Iterator.TListEntry +End Type + +Type TListEntry + Field Value% + + Field PreviousEntry.TListEntry + Field NextEntry.TListEntry +End Type + +;---------------------------------------------------------------- +;-- Functions +;---------------------------------------------------------------- +Function TList_Create.TList() + Local lList.TList = New TList + + lList\FirstEntry = Null + lList\LastEntry = Null + lList\Iterator = Null + + Return lList +End Function + +Function TList_Destroy(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to destroy non-existing list." + + ; Delete all entries + pList\Iterator = pList\FirstEntry + While pList\Iterator <> Null + Local lNextEntry.TListEntry = pList\Iterator\NextEntry + Delete pList\Iterator + pList\Iterator = lNextEntry + Wend +End Function + +Function TList_Reset(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to reset non-existing list." + + pList\Iterator = Null +End Function + +Function TList_First%(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + pList\Iterator = pList\FirstEntry + If pList\Iterator <> Null Then Return pList\Iterator\Value +End Function + +Function TList_Last%(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + pList\Iterator = pList\LastEntry + If pList\Iterator <> Null Then Return pList\Iterator\Value +End Function + +Function TList_Next%(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + If pList\Iterator <> Null Then + pList\Iterator = pList\Iterator\NextEntry + Else + pList\Iterator = pList\FirstEntry + EndIf + If pList\Iterator <> Null Then Return pList\Iterator\Value +End Function + +Function TList_Previous%(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + If pList\Iterator <> Null Then + pList\Iterator = pList\Iterator\PreviousEntry + Else + pList\Iterator = pList\LastEntry + EndIf + If pList\Iterator <> Null Then Return pList\Iterator\Value +End Function + +Function TList_HasFirst(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + Return (pList\FirstEntry <> Null) +End Function + +Function TList_HasLast(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + Return (pList\LastEntry <> Null) +End Function + +Function TList_HasNext(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + If pList\Iterator <> Null Then + Return (pList\Iterator\NextEntry <> Null) + Else + Return (pList\FirstEntry <> Null) + EndIf +End Function + +Function TList_HasPrevious(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + If pList\Iterator <> Null Then + Return (pList\Iterator\PreviousEntry <> Null) + Else + Return (pList\LastEntry <> Null) + EndIf +End Function + +Function TList_AddFirst(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + + Local lEntry.TListEntry = New TListEntry + lEntry\Value = Value + + If pList\FirstEntry <> Null Then + lEntry\NextEntry = pList\FirstEntry + lEntry\NextEntry\PreviousEntry = lEntry + EndIf + + pList\FirstEntry = lEntry + If pList\LastEntry = Null Then pList\LastEntry = lEntry +End Function + +Function TList_AddLast(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + + Local lEntry.TListEntry = New TListEntry + lEntry\Value = Value + + If pList\LastEntry <> Null Then + lEntry\PreviousEntry = pList\LastEntry + lEntry\PreviousEntry\NextEntry = lEntry + EndIf + + If pList\FirstEntry = Null pList\FirstEntry = lEntry + pList\LastEntry = lEntry +End Function + +Function TList_InsertBefore(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + Local lEntry.TListEntry = New TListEntry + lEntry\Value = Value + + If pList\Iterator\PreviousEntry <> Null Then + lEntry\PreviousEntry = pList\Iterator\PreviousEntry + pList\Iterator\PreviousEntry\NextEntry = lEntry + Else + pList\FirstEntry = lEntry + EndIf + pList\Iterator\PreviousEntry = lEntry + + If pList\Iterator\NextEntry = Null Then + pList\LastEntry = lEntry + EndIf + lEntry\NextEntry = pList\Iterator +End Function + +Function TList_InsertAfter(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + Local lEntry.TListEntry = New TListEntry + lEntry\Value = Value + + If pList\Iterator\NextEntry <> Null Then + lEntry\NextEntry = pList\Iterator\NextEntry + pList\Iterator\NextEntry\PreviousEntry = lEntry + Else + pList\LastEntry = lEntry + EndIf + pList\Iterator\NextEntry = lEntry + + If pList\Iterator\PreviousEntry = Null Then + pList\FirstEntry = lEntry + EndIf + lEntry\PreviousEntry = pList\Iterator +End Function + +Function TList_Replace(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + pList\Iterator\Value = Value +End Function + +Function TList_DeleteFirst(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\FirstEntry = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + Local lEntry.TListEntry = pList\FirstEntry + pList\FirstEntry\NextEntry\PreviousEntry = Null + pList\FirstEntry = pList\FirstEntry\NextEntry + Delete lEntry + + If pList\FirstEntry <> Null Then Return pList\FirstEntry\Value +End Function + +Function TList_DeleteLast(pList.Tlist) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\LastEntry = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + Local lEntry.TListEntry = pList\LastEntry + pList\LastEntry\PreviousEntry\NextEntry = Null + pList\LastEntry = pList\LastEntry\PreviousEntry + Delete lEntry + + If pList\LastEntry <> Null Then Return pList\LastEntry\Value +End Function + +Function TList_Delete(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + If pList\FirstEntry = pList\Iterator Then pList\FirstEntry = pList\Iterator\NextEntry + If pList\LastEntry = pList\Iterator Then pList\LastEntry = pList\Iterator\PreviousEntry + + If pList\Iterator\NextEntry <> Null Then pList\Iterator\NextEntry\PreviousEntry = pList\Iterator\PreviousEntry + If pList\Iterator\PreviousEntry <> Null Then pList\Iterator\PreviousEntry\NextEntry = pList\Iterator\NextEntry + + Local lEntry.TListEntry = pList\Iterator + pList\Iterator = pList\Iterator\NextEntry + Delete lEntry + + If pList\Iterator <> Null Then Return pList\Iterator\Value +End Function + +Function TList_DeleteValue(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + + If pList\FirstEntry <> Null Then + Local lEntry.TListEntry = pList\FirstEntry + While lEntry <> Null + If lEntry\Value = Value Then + If lEntry\PreviousEntry <> Null Then lEntry\PreviousEntry\NextEntry = lEntry\NextEntry + If lEntry\NextEntry <> Null Then lEntry\NextEntry\PreviousEntry = lEntry\PreviousEntry + + If pList\FirstEntry = lEntry Then pList\FirstEntry = lEntry\NextEntry + If pList\LastEntry = lEntry Then pList\LastEntry = lEntry\PreviousEntry + + Local lDelEntry.TListEntry = lEntry + lEntry = lEntry\NextEntry + Delete lDelEntry + Else + lEntry = lEntry\NextEntry + EndIf + Wend + EndIf +End Function \ No newline at end of file diff --git a/BlitzBasic/All/LinkedList Emulation/README.md b/BlitzBasic/All/LinkedList Emulation/README.md new file mode 100644 index 0000000..f89c229 --- /dev/null +++ b/BlitzBasic/All/LinkedList Emulation/README.md @@ -0,0 +1,9 @@ +LinkedList Emulation +======================= + +Since the early BlitzBasic languages didn't have any kind of lists aside from the global ones, I had to make something out of nothing. This library adds the ability to have linked lists inside of those languages. +It was initially ment to use FastPointer or a similar library, but that failed horrifically, as I wasn't able to cast back into the original type and memory leaks happened. It's somewhat fast, but solutions tailored to a single type still work faster 90% of the time. + +License +======= +LinkedList Emulation by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/. \ No newline at end of file diff --git a/BlitzBasic/All/Random Stuff/LinkedList.bb b/BlitzBasic/All/Random Stuff/LinkedList.bb new file mode 100644 index 0000000..f1a69a3 --- /dev/null +++ b/BlitzBasic/All/Random Stuff/LinkedList.bb @@ -0,0 +1,258 @@ +;---------------------------------------------------------------- +;-- Types +;---------------------------------------------------------------- +Type TList + Field FirstEntry.TListEntry + Field LastEntry.TListEntry + + Field Iterator.TListEntry +End Type + +Type TListEntry + Field Value% + + Field PreviousEntry.TListEntry + Field NextEntry.TListEntry +End Type + +;---------------------------------------------------------------- +;-- Functions +;---------------------------------------------------------------- +Function TList_Create.TList() + Local lList.TList = New TList + + lList\FirstEntry = Null + lList\LastEntry = Null + lList\Iterator = Null + + Return lList +End Function + +Function TList_Destroy(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to destroy non-existing list." + + ; Delete all entries + pList\Iterator = pList\FirstEntry + While pList\Iterator <> Null + Local lNextEntry.TListEntry = pList\Iterator\NextEntry + Delete pList\Iterator + pList\Iterator = lNextEntry + Wend +End Function + +Function TList_Reset(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to reset non-existing list." + + pList\Iterator = Null +End Function + +Function TList_First%(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + pList\Iterator = pList\FirstEntry + If pList\Iterator <> Null Then Return pList\Iterator\Value +End Function + +Function TList_Last%(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + pList\Iterator = pList\LastEntry + If pList\Iterator <> Null Then Return pList\Iterator\Value +End Function + +Function TList_Next%(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + If pList\Iterator <> Null Then + pList\Iterator = pList\Iterator\NextEntry + Else + pList\Iterator = pList\FirstEntry + EndIf + If pList\Iterator <> Null Then Return pList\Iterator\Value +End Function + +Function TList_Previous%(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + If pList\Iterator <> Null Then + pList\Iterator = pList\Iterator\PreviousEntry + Else + pList\Iterator = pList\LastEntry + EndIf + If pList\Iterator <> Null Then Return pList\Iterator\Value +End Function + +Function TList_HasFirst(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + Return (pList\FirstEntry <> Null) +End Function + +Function TList_HasLast(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + Return (pList\LastEntry <> Null) +End Function + +Function TList_HasNext(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + If pList\Iterator <> Null Then + Return (pList\Iterator\NextEntry <> Null) + Else + Return (pList\FirstEntry <> Null) + EndIf +End Function + +Function TList_HasPrevious(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to iterate non-existing list." + + If pList\Iterator <> Null Then + Return (pList\Iterator\PreviousEntry <> Null) + Else + Return (pList\LastEntry <> Null) + EndIf +End Function + +Function TList_AddFirst(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + + Local lEntry.TListEntry = New TListEntry + lEntry\Value = Value + + If pList\FirstEntry <> Null Then + lEntry\NextEntry = pList\FirstEntry + lEntry\NextEntry\PreviousEntry = lEntry + EndIf + + pList\FirstEntry = lEntry + If pList\LastEntry = Null Then pList\LastEntry = lEntry +End Function + +Function TList_AddLast(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + + Local lEntry.TListEntry = New TListEntry + lEntry\Value = Value + + If pList\LastEntry <> Null Then + lEntry\PreviousEntry = pList\LastEntry + lEntry\PreviousEntry\NextEntry = lEntry + EndIf + + If pList\FirstEntry = Null pList\FirstEntry = lEntry + pList\LastEntry = lEntry +End Function + +Function TList_InsertBefore(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + Local lEntry.TListEntry = New TListEntry + lEntry\Value = Value + + If pList\Iterator\PreviousEntry <> Null Then + lEntry\PreviousEntry = pList\Iterator\PreviousEntry + pList\Iterator\PreviousEntry\NextEntry = lEntry + Else + pList\FirstEntry = lEntry + EndIf + pList\Iterator\PreviousEntry = lEntry + + If pList\Iterator\NextEntry = Null Then + pList\LastEntry = lEntry + EndIf + lEntry\NextEntry = pList\Iterator +End Function + +Function TList_InsertAfter(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + Local lEntry.TListEntry = New TListEntry + lEntry\Value = Value + + If pList\Iterator\NextEntry <> Null Then + lEntry\NextEntry = pList\Iterator\NextEntry + pList\Iterator\NextEntry\PreviousEntry = lEntry + Else + pList\LastEntry = lEntry + EndIf + pList\Iterator\NextEntry = lEntry + + If pList\Iterator\PreviousEntry = Null Then + pList\FirstEntry = lEntry + EndIf + lEntry\PreviousEntry = pList\Iterator +End Function + +Function TList_Replace(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + pList\Iterator\Value = Value +End Function + +Function TList_DeleteFirst(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\FirstEntry = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + Local lEntry.TListEntry = pList\FirstEntry + pList\FirstEntry\NextEntry\PreviousEntry = Null + pList\FirstEntry = pList\FirstEntry\NextEntry + Delete lEntry + + If pList\FirstEntry <> Null Then Return pList\FirstEntry\Value +End Function + +Function TList_DeleteLast(pList.Tlist) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\LastEntry = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + Local lEntry.TListEntry = pList\LastEntry + pList\LastEntry\PreviousEntry\NextEntry = Null + pList\LastEntry = pList\LastEntry\PreviousEntry + Delete lEntry + + If pList\LastEntry <> Null Then Return pList\LastEntry\Value +End Function + +Function TList_Delete(pList.TList) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + If pList\Iterator = Null Then RuntimeError "TList: TList: Tried to change non-existing list entry." + + If pList\FirstEntry = pList\Iterator Then pList\FirstEntry = pList\Iterator\NextEntry + If pList\LastEntry = pList\Iterator Then pList\LastEntry = pList\Iterator\PreviousEntry + + If pList\Iterator\NextEntry <> Null Then pList\Iterator\NextEntry\PreviousEntry = pList\Iterator\PreviousEntry + If pList\Iterator\PreviousEntry <> Null Then pList\Iterator\PreviousEntry\NextEntry = pList\Iterator\NextEntry + + Local lEntry.TListEntry = pList\Iterator + pList\Iterator = pList\Iterator\NextEntry + Delete lEntry + + If pList\Iterator <> Null Then Return pList\Iterator\Value +End Function + +Function TList_DeleteValue(pList.TList, Value%) + If pList = Null Then RuntimeError "TList: Tried to insert into non-existing list." + + If pList\FirstEntry <> Null Then + Local lEntry.TListEntry = pList\FirstEntry + While lEntry <> Null + If lEntry\Value = Value Then + If lEntry\PreviousEntry <> Null Then lEntry\PreviousEntry\NextEntry = lEntry\NextEntry + If lEntry\NextEntry <> Null Then lEntry\NextEntry\PreviousEntry = lEntry\PreviousEntry + + If pList\FirstEntry = lEntry Then pList\FirstEntry = lEntry\NextEntry + If pList\LastEntry = lEntry Then pList\LastEntry = lEntry\PreviousEntry + + Local lDelEntry.TListEntry = lEntry + lEntry = lEntry\NextEntry + Delete lDelEntry + Else + lEntry = lEntry\NextEntry + EndIf + Wend + EndIf +End Function \ No newline at end of file diff --git a/BlitzBasic/All/Random Stuff/Logger.bb b/BlitzBasic/All/Random Stuff/Logger.bb new file mode 100644 index 0000000..0ee5736 --- /dev/null +++ b/BlitzBasic/All/Random Stuff/Logger.bb @@ -0,0 +1,27 @@ +Global Logger_Stream + +Function Logger_Initialize(File$) + File = "Logs/" + File + CreateDir("./Logs/") + If FileType("./Logs/") <> 2 Then RuntimeError("Unable To create Log File."+Chr(10)+" If the program is running in a protected directory,"+Chr(10)+" consider running it as an administrator.") + + Logger_Stream = OpenFile(File) + If Logger_Stream = 0 + Logger_Stream = WriteFile(File) + If Logger_Stream = 0 Then RuntimeError("Unable to create log file."+Chr(10)+" If the program is running in a protected directory,"+Chr(10)+" consider running it as an administrator.") + EndIf +End Function + +Function Logger_Info(Module$, Message$) + WriteLine Logger_Stream, "[" + CurrentTime() + "] [Info] " + Module + ": " + Message +End Function + +Function Logger_Warning(Module$, Message$) + WriteLine Logger_Stream, "[" + CurrentTime() + "] [Warn] " + Module + ": " + Message +End Function + +Function Logger_Error(Module$, Message$) + WriteLine Logger_Stream, "[" + CurrentTime() + "] [Errr] " + Module + ": " + Message +End Function +;~IDEal Editor Parameters: +;~C#Blitz3D \ No newline at end of file diff --git a/BlitzBasic/All/Random Stuff/NetCode.bb b/BlitzBasic/All/Random Stuff/NetCode.bb new file mode 100644 index 0000000..2550642 --- /dev/null +++ b/BlitzBasic/All/Random Stuff/NetCode.bb @@ -0,0 +1,665 @@ +;---------------------------------------------------------------- +;-- Packet Descriptors +;---------------------------------------------------------------- + +;-- Any Packet +;Off Size Desc +; 0 1 Packet Id + +;-- Login +;Off Size Desc +; 1 2 Unique Id (Server) / UDP Port (Client) +; 3 2 Version +; 5 16 Name (Always 16B, Only allows bytes above 32) +; 21 4F Initial Position X +; 25 4F Initial Position Y +; 29 4F Initial Position Z +; 33 4F Initial Rotation X +; 37 4F Initial Rotation Y +; 41 4F Initial Rotation Z + +;-- Logout +;Off Size Desc +; 1 2 Unique Id + +;-- Kick +;Off Size Desc +; 1 2 Reason Length +; 3 ^ Reason + +;-- Data +; 1 2 Unique Id +; 3 1 Data Flags (See BNET_DATAFLAG_*) +;... 4F Position X +;... 4F Position Y +;... 4F Position Z +;... 2 Rotation X +;... 2 Rotation Y +;... 2 Rotation Z +;... 2 Velocity X +;... 2 Velocity Y +;... 2 Velocity Z +;... 2 Aim X +;... 2 Aim Y + +;-- Action (Yet Unsupported) + +;---------------------------------------------------------------- +;-- Constants +;---------------------------------------------------------------- + ; BlitzNet Version +Const BNET_VERSION_MAJOR% = 0 +Const BNET_VERSION_MINOR% = 1 + ; Size of Buffer for Network Packets, 64KB should be enough for now. +Const BNET_BUFFER_SIZE% = (64 * 1024) + ; Flags for data changes. Only when the bit is set this data is available. +Const BNET_DATAFLAG_POSX = $00000001 +Const BNET_DATAFLAG_POSY = $00000010 +Const BNET_DATAFLAG_POSZ = $00000100 +Const BNET_DATAFLAG_ROTX = $00001000 +Const BNET_DATAFLAG_ROTY = $00010000 +Const BNET_DATAFLAG_ROTZ = $00100000 +Const BNET_DATAFLAG_VELOCITY = $01000000 +Const BNET_DATAFLAG_AIM = $10000000 + ; Packet Ids, for identification of each one. +Const BNET_PACKET_LOGIN = 0 +Const BNET_PACKET_LOGOUT = 1 +Const BNET_PACKET_KICK = 2 +Const BNET_PACKET_DATA = 3 +Const BNET_PACKET_ACTION = 4 + ; How many updates should we send out each minute? +Const BNET_DATA_COUNT = 150 + ; How many keyframes should we send out each minute? +Const BNET_DATA_COUNT_KEYFRAME = 3 + ; How much has the value to change to be considered different? +Const BNET_DATA_THRESHOLD_POS# = 1.0 +Const BNET_DATA_THRESHOLD_ROT# = 1.0 +Const BNET_DATA_THRESHOLD_VEL# = 1.0 +Const BNET_DATA_THRESHOLD_AIM# = 1.0 + +;---------------------------------------------------------------- +;-- Globals +;---------------------------------------------------------------- + ; Connections to Sector Servers. +Global BNet_Sector_TCP% = 0 +Global BNet_Sector_UDP% = 0 + ; Our UniqueId and Player instance so we know which Player is us. +Global BNet_UniqueId% = -1 +Global BNet_Player.BNetPlayer = Null + ; Buffer for Network Packets. +Global BNet_Buffer% = CreateBank(BNET_BUFFER_SIZE) + ; Set to true when Kicked from the server, or similar. +Global BNet_Kick% = False +Global BNet_Kick_Reason$ = "Not Kicked" + ; Update Times +Global BNet_Data_Time = 60000 / BNET_DATA_COUNT +Global BNet_Data_Time_KeyFrame = 60000 / BNET_DATA_COUNT_KEYFRAME +Global BNet_Data_LastUpdate = 0 +Global BNet_Data_LastKeyFrame = 0 + ; Array for all known players. Makes access a bit faster. +Dim BNet_Players.BNetPlayer(65535) + +;---------------------------------------------------------------- +;-- Types +;---------------------------------------------------------------- +Type BNetPlayer + Field Name$ = "Invalid Player" + + ; Position, Rotation, Velocity and Aim + Field PositionX#, PositionY#, PositionZ# + Field RotationX#, RotationY#, RotationZ# + Field VelocityX#, VelocityY#, VelocityZ# + Field AimX#, AimY# + + ; Internal Data + Field m_UniqueId% +End Type + +;---------------------------------------------------------------- +;-- Functions +;---------------------------------------------------------------- +Function BNet_Initialize() + TCPTimeouts 100, 100 +End Function + +Function BNet_Connect(Ip$ = "127.0.0.1", IPort% = 27000, DPort = 27001) + BNet_Kick% = False + BNet_Kick_Reason$ = "Not Kicked" + + BNet_Sector_TCP = OpenTCPStream(Ip, IPort) + If BNet_Sector_TCP Then + BNet_Sector_UDP = CreateUDPStream() + If BNet_Sector_UDP Then + Return True + Else + CloseTCPStream BNet_Sector_TCP + BNet_Sector_UDP = 0 + BNet_Sector_TCP = 0 + EndIf + Else + BNet_Sector_UDP = 0 + BNet_Sector_TCP = 0 + EndIf + Return False +End Function + +Function BNet_Disconnect() + If BNet_UniqueId > -1 Then + ; Remove all existing players + For Player.BNetPlayer = Each BNetPlayer + Local UniqueId = Player\m_UniqueId + + CB_BNet_DeletePlayer(UniqueId, Player) + + Delete BNet_Players(UniqueId):BNet_Players(UniqueId) = Null + Next + + ; Logout + BNet_Logout() + BNet_UniqueId = -1 + EndIf + If BNet_Sector_UDP Then CloseUDPStream(BNet_Sector_UDP):BNet_Sector_UDP = 0 + If BNet_Sector_TCP Then CloseTCPStream(BNet_Sector_TCP):BNet_Sector_TCP = 0 +End Function + +Function BNet_Connected() + If BNet_Sector_TCP = 0 Then Return False + If BNet_Sector_UDP = 0 Then Return False + If Eof(BNet_Sector_TCP) <> 0 Then Return False + + Return True +End Function + +Function BNet_Login(Name$, PosX# = 0, PosY# = 0, PosZ# = 0, RotX# = 0, RotY# = 0, RotZ# = 0) + If BNet_Connected() And BNet_UniqueId = -1 Then + ; Packet Id: Login + PokeByte BNet_Buffer, 0, BNET_PACKET_LOGIN + ; Write UDP Port + PokeShort BNet_Buffer, 1, UDPStreamPort(BNet_Sector_UDP) + ; Write Client Version + PokeShort BNet_Buffer, 3, BNET_VERSION_MAJOR Shl 8 + BNET_VERSION_MINOR + ; Write Name + Local NameLength% = Len(Name) + For NamePos = 1 To NameLength:PokeByte BNet_Buffer, (5 + NamePos - 1), Asc(Mid(Name, NamePos, 1)):Next + For NamePos = NameLength To 16:PokeByte BNet_Buffer, (5 + NamePos - 1), 0:Next + ; Write Initial Position + PokeFloat BNet_Buffer, 21, PosX + PokeFloat BNet_Buffer, 25, PosY + PokeFloat BNet_Buffer, 29, PosZ + ; Write Initial Rotation + PokeFloat BNet_Buffer, 33, RotX + PokeFloat BNet_Buffer, 37, RotX + PokeFloat BNet_Buffer, 41, RotX + + ; Write to Stream + WriteBytes BNet_Buffer, BNet_Sector_TCP, 0, 47 + + Return True + Else + Return False + EndIf +End Function + +Function BNet_Logout() + If BNet_Connected() And BNet_UniqueId > -1 Then + ; Packet Id: Logout + PokeByte BNet_Buffer, 0, BNET_PACKET_LOGOUT + ; Write our own UniqueId + PokeShort BNet_Buffer, 1, BNet_UniqueId + + ; Write to Stream + WriteBytes BNet_Buffer, BNet_Sector_TCP, 0, 3 + + Return True + Else + Return False + EndIf +End Function + +Function BNet_Update() + Local UniqueId, PacketSize, PacketId, DataFlags, Offset, TempPlayer.BNetPlayer + If BNet_Connected() Then + ; TCP + While Not Eof(BNet_Sector_TCP) And ReadAvail(BNet_Sector_TCP) > 0 + PacketSize = ReadAvail(BNet_Sector_TCP) + If PacketSize > BNET_BUFFER_SIZE Then PacketSize = BNET_BUFFER_SIZE + ReadBytes(BNet_Buffer, BNet_Sector_TCP, 0, PacketSize) + + PacketId = PeekByte(BNet_Buffer, 0) + Select PacketId + Case BNET_PACKET_LOGIN + UniqueId = PeekShort(BNet_Buffer, 1) + + BNet_Players(UniqueId) = New BNetPlayer + ; Read Name + For NamePos = 1 To 16 + Local NameChar = PeekByte(BNet_Buffer, (5 + NamePos - 1)) + If NameChar < 32 Then Exit + BNet_Players(UniqueId)\Name$ = BNet_Players(UniqueId)\Name$ + Chr(NameChar) + Next + ; Read initital Position + BNet_Players(UniqueId)\PositionX = PeekFloat(BNet_Buffer, 21) + BNet_Players(UniqueId)\PositionY = PeekFloat(BNet_Buffer, 25) + BNet_Players(UniqueId)\PositionZ = PeekFloat(BNet_Buffer, 29) + ; Read initial Rotation + BNet_Players(UniqueId)\RotationX = PeekFloat(BNet_Buffer, 33) + BNet_Players(UniqueId)\RotationY = PeekFloat(BNet_Buffer, 37) + BNet_Players(UniqueId)\RotationZ = PeekFloat(BNet_Buffer, 41) + ; Assign Unique Id + BNet_Players(UniqueId)\m_UniqueId = UniqueId + + ; Assign local UniqueId if we don't have one. + If BNet_UniqueId > -1 Then + BNet_UniqueId = UniqueId + Else + CB_BNet_CreatePlayer(UniqueId, BNet_Players(BNet_UniqueId)) + EndIf + Case BNET_PACKET_LOGOUT + UniqueId = PeekShort(BNet_Buffer, 1) + + ; A logout packet for ourselves will make us logout. + If BNet_UniqueId = UniqueId Then + BNet_Disconnect():Return True + ElseIf BNet_Players(UniqueId) <> Null Then + ; Otherwise, it is another player removed from visible space. + CB_BNet_DeletePlayer(Unique, BNet_Players(UniqueId)) + + Delete BNet_Players(UniqueId):BNet_Players(UniqueId) = Null + Else + DebugLog "BNet: Logout for non-existing player." + EndIf + Case BNET_PACKET_KICK + BNet_Kick = True + + ; Read reason for Kick + Local ReasonLength% = PeekShort(BNet_Buffer, 1) + For ReasonPos = 1 To ReasonLength + Local ReasonChar = PeekByte(BNet_Buffer, (3 + ReasonPos - 1)) + If ReasonChar < 32 Then Exit + BNet_Kick_Reason = BNet_Kick_Reason + Chr(NameChar) + Next + + BNet_Disconnect():Return True + End Select + Wend + + ; UDP + While Not Eof(BNet_Sector_UDP) And ReadAvail(BNet_Sector_UDP) > 0 + PacketSize = ReadAvail(BNet_Sector_UDP) + If PacketSize > BNET_BUFFER_SIZE Then PacketSize = BNET_BUFFER_SIZE + ReadBytes(BNet_Buffer, BNet_Sector_UDP, 0, PacketSize) + + PacketId = PeekByte(BNet_Buffer, 0) + Select PacketId + Case BNET_PACKET_DATA + If BNet_UniqueId > -1 Then + UniqueId = PeekShort(BNet_Buffer, 1) + If BNet_Players(UniqueId) <> Null Then + DataFlags = PeekShort(BNet_Buffer, 3) + Offset% = 5 + + If DataFlags And BNET_DATAFLAGS_POSX Then BNet_Players(UniqueId)\PositionX = PeekInt(BNet_Buffer, Offset):Offset = Offset + 4 + If DataFlags And BNET_DATAFLAGS_POSY Then BNet_Players(UniqueId)\PositionY = PeekInt(BNet_Buffer, Offset):Offset = Offset + 4 + If DataFlags And BNET_DATAFLAGS_POSZ Then BNet_Players(UniqueId)\PositionZ = PeekInt(BNet_Buffer, Offset):Offset = Offset + 4 + If DataFlags And BNET_DATAFLAGS_ROTX Then BNet_Players(UniqueId)\RotationX = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 360.0:Offset = Offset + 2 + If DataFlags And BNET_DATAFLAGS_ROTY Then BNet_Players(UniqueId)\RotationY = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 360.0:Offset = Offset + 2 + If DataFlags And BNET_DATAFLAGS_ROTZ Then BNet_Players(UniqueId)\RotationZ = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 360.0:Offset = Offset + 2 + If DataFlags And BNET_DATAFLAGS_VELOCITY Then + BNet_Players(UniqueId)\VelocityX = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 255.0 + BNet_Players(UniqueId)\VelocityY = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 255.0 + BNet_Players(UniqueId)\VelocityZ = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 255.0 + + Offset = Offset + 6 + EndIf + If DataFlags And BNET_DATAFLAGS_AIM Then + BNet_Players(UniqueId)\AimX = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 360.0 + BNet_Players(UniqueId)\AimY = BNet_FloatFromShort(PeekShort(BNet_Buffer, Offset)) * 360.0 + + Offset = Offset + 4 + EndIf + + ; Tell Client to update visual stuff + CB_BNet_UpdatePlayer(UniqueId, BNet_Players(UniqueId)) + EndIf + EndIf +; Case BNET_PACKET_ACTION +; If BNet_UniqueId > -1 Then +; +; EndIf + End Select + Wend + + ; If we are logged in, tell the server our current data. + If BNet_UniqueId > -1 Then + Local Time = MilliSecs() + + ; Send out whatever is needed. + If Time - BNet_Data_LastKeyFrame > BNet_Data_Time_KeyFrame Then + ; Force Client to update Player object + CB_BNet_SendUpdate(BNet_UniqueId, BNet_Player) + + ; Packet Id + PokeByte BNet_Buffer, 0, BNET_PACKET_DATA + ; Unique Id + PokeShort BNet_Buffer, 1, BNet_UniqueId + ; Data Flags (KeyFrame always has this at 255, since it contains all data) + PokeByte BNet_Buffer, 3, $11111111 + ; Position + PokeFloat BNet_Buffer, 4, BNet_Player\PositionX + PokeFloat BNet_Buffer, 8, BNet_Player\PositionY + PokeFloat BNet_Buffer,12, BNet_Player\PositionZ + ; Rotation + PokeShort BNet_Buffer,16, BNet_ShortFromFloat(BNet_Player\RotationX / 360.0) + PokeShort BNet_Buffer,18, BNet_ShortFromFloat(BNet_Player\RotationY / 360.0) + PokeShort BNet_Buffer,20, BNet_ShortFromFloat(BNet_Player\RotationZ / 360.0) + ; Velocity + PokeShort BNet_Buffer,22, BNet_ShortFromFloat(BNet_Player\VelocityX / 256.0) + PokeShort BNet_Buffer,24, BNet_ShortFromFloat(BNet_Player\VelocityY / 256.0) + PokeShort BNet_Buffer,26, BNet_ShortFromFloat(BNet_Player\VelocityZ / 256.0) + ; Aim + PokeShort BNet_Buffer,28, BNet_ShortFromFloat(BNet_Player\AimX / 360.0) + PokeShort BNet_Buffer,30, BNet_ShortFromFloat(BNet_Player\AimY / 360.0) + + ; Send Packet + WriteBytes BNet_Buffer, BNet_Sector_UDP, 0, 32 + + ; Swap Player objects. + TempPlayer = BNet_Player + BNet_Player = BNet_Players(BNet_UniqueId) + BNet_Players(BNet_UnqiueId) = TempPlayer + + ; Set last keyframe and update time to now. + BNet_Data_LastKeyFrame = Time + BNet_Data_LastUpdate = Time + ElseIf Time - BNet_Data_LastUpdate > BNet_Data_Time Then + DataFlags = 0 + Offset = 4 + + ; Force Client to update Player object + CB_BNet_SendUpdate(BNet_UniqueId, BNet_Player) + + ; Packet Id + PokeByte BNet_Buffer, 0, BNET_PACKET_DATA + ; Unique Id + PokeShort BNet_Buffer, 1, BNet_UniqueId + + ; Position + If Abs(BNet_Player\PositionX - BNet_Players(BNet_UniqueId)\PositionX) > BNET_DATA_THRESHOLD_POS Then + DataFlags = DataFlags Or BNET_DATAFLAG_POSX + PokeFloat BNet_Buffer, Offset, BNet_Player\PositionX:Offset = Offset + 4 + EndIf + If Abs(BNet_Player\PositionY - BNet_Players(BNet_UniqueId)\PositionY) > BNET_DATA_THRESHOLD_POS Then + DataFlags = DataFlags Or BNET_DATAFLAG_POSY + PokeFloat BNet_Buffer, Offset, BNet_Player\PositionY:Offset = Offset + 4 + EndIf + If Abs(BNet_Player\PositionZ - BNet_Players(BNet_UniqueId)\PositionZ) > BNET_DATA_THRESHOLD_POS Then + DataFlags = DataFlags Or BNET_DATAFLAG_POSZ + PokeFloat BNet_Buffer, Offset, BNet_Player\PositionZ:Offset = Offset + 4 + EndIf + ; Rotation + If Abs(BNet_Player\RotationX - BNet_Players(BNet_UniqueId)\RotationX) > BNET_DATA_THRESHOLD_POS Then + DataFlags = DataFlags Or BNET_DATAFLAG_ROTX + PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\RotationX / 360.0):Offset = Offset + 2 + EndIf + If Abs(BNet_Player\RotationY - BNet_Players(BNet_UniqueId)\RotationY) > BNET_DATA_THRESHOLD_POS Then + DataFlags = DataFlags Or BNET_DATAFLAG_ROTY + PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\RotationY / 360.0):Offset = Offset + 2 + EndIf + If Abs(BNet_Player\RotationZ - BNet_Players(BNet_UniqueId)\RotationZ) > BNET_DATA_THRESHOLD_POS Then + DataFlags = DataFlags Or BNET_DATAFLAG_ROTZ + PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\RotationZ / 360.0):Offset = Offset + 2 + EndIf + ; Velocity + If Abs(BNet_Player\VelocityX - BNet_Players(BNet_UniqueId)\VelocityX) + Abs(BNet_Player\VelocityY - BNet_Players(BNet_UniqueId)\VelocityY) + Abs(BNet_Player\VelocityZ - BNet_Players(BNet_UniqueId)\VelocityZ) > BNET_DATA_THRESHOLD_VEL Then + DataFlags = DataFlags Or BNET_DATAFLAG_VELOCITY + PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\VelocityX / 256.0):Offset = Offset + 2 + PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\VelocityY / 256.0):Offset = Offset + 2 + PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\VelocityZ / 256.0):Offset = Offset + 2 + EndIf + ; Aim + If Abs(BNet_Player\AimX - BNet_Players(BNet_UniqueId)\AimX) + Abs(BNet_Player\AimY - BNet_Players(BNet_UniqueId)\AimY) > BNET_DATA_THRESHOLD_AIM Then + DataFlags = DataFlags Or BNET_DATAFLAG_AIM + PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\AimX / 360.0):Offset = Offset + 2 + PokeFloat BNet_Buffer, Offset, BNet_ShortFromFloat(BNet_Player\AimY / 360.0):Offset = Offset + 2 + EndIf + + ; Data Flags + PokeByte BNet_Buffer, 3, DataFlags + + ; Send Packet + WriteBytes BNet_Buffer, BNet_Sector_UDP, 0, Offset + + ; Swap Player objects. + TempPlayer = BNet_Player + BNet_Player = BNet_Players(BNet_UniqueId) + BNet_Players(BNet_UnqiueId) = TempPlayer + + ; Set last update time to now. + BNet_Data_LastUpdate = Time + EndIf + EndIf + Else + Return False + EndIf +End Function + +Function BNet_FloatFromShort#(Value%) + Return BNet_Math_ClipF((Value / 65536.0), 0.0, 1.0) +End Function + +Function BNet_ShortFromFloat%(Value#) + Return BNet_Math_ClipF((Value * 65536.0), 0.0, 1.0) +End Function + +Function BNet_Math_MinimumF#(Value#, Min#) + If Value < Min Then Return Min + Return Value +End Function + +Function BNet_Math_MaximumF#(Value#, Max#) + If Value > Max Then Return Max + Return Value +End Function + +Function BNet_Math_ClampF#(Value#, Min#, Max#) + If Value < Min Then Return Min + If Value > Max Then Return Max + Return Value +End Function + +Function BNet_Math_ClipF#(Value#, Min#, Max#) + Local Out#, Diff# + Diff = Max - Min:Out = Value - Min + If (Out >= Diff) Or (Out < 0) Then Out = Out - (Floor(Out/Diff) * Diff) + Return Min + Out +End Function + +;---------------------------------------------------------------- +;-- Callbacks +;---------------------------------------------------------------- +;Function CB_BNet_CreatePlayer(UniqueId, Player.BNetPlayer) +;End Function + +;Function CB_BNet_UpdatePlayer(UniqueId, Player.BNetPlayer) +;End Function + +;Function CB_BNet_DeletePlayer(UniqueId, Player.BNetPlayer) +;End Function + +;Function CB_BNet_SendUpdate(UniqueId, Player.BNetPlayer) +;End Function + +;---------------------------------------------------------------- +;-- Example +;---------------------------------------------------------------- +Graphics3D 800, 600, 32, 2 +SetBuffer BackBuffer() +SeedRnd MilliSecs() + +Local FrameTimer = CreateTimer(60) +Local TimeToLogin = MilliSecs() + +Dim Players.TPlayer(65535) +Local Player.TPlayer = Null + +Global TestX#, TestY#, TestZ# +Global TestRX#, TestRY#, TestRZ# +Global TestVX#, TestVY#, TestVZ# +Global TestAX#, TestAY# +Local ShipVeloLR#, ShipVeloUD#, ShipVeloFB# +Const ShipMaxVeloLR# = 5.0, ShipMaxVeloUD# = 5.0, ShipMaxVeloFB = 30.0 + +; Init +TestX = Rnd(-2048, 2048) +TestY = Rnd(-2048, 2048) +TestZ = Rnd(-2048, 2048) +TestRX = Rnd(0, 360) +TestRY = Rnd(0, 360) +TestRZ = Rnd(0, 360) +TestVX = 0 +TestVY = 0 +TestVZ = 0 +TestAX = 0 +TestAY = 0 + + +Local Cam = CreateCamera() +Local Conv = CreatePivot() + +Print "[INF] Connecting..." +BNet_Initialize() +BNet_Connect() +If BNet_Connected() Then + Print "[INF] Logging in..." + BNet_Login("Test " + Rand(0, 65535), TestX, TestY, TestZ, TestRX, TestRY, TestRZ) + + Local LoopExit = False + Local Load = False + Repeat + If Load = False And BNet_UniqueId = -1 And (MilliSecs() - TimeToLogin > 30000) Then + Print "[ERR] Failed to login." + LoopExit = True + ElseIf Load = False And BNet_UniqueId > -1 Then + Print "[INF] Logged in." + + Player = New TPlayer + Player\Mesh = CreateCone() + Player\Player = BNet_Player + Players(BNet_UniqueId) = Player + EntityParent Cam, Player\Mesh + + Load = True + ElseIf Load = True And BNet_UniqueId > -1 + ; Player Input + ; Velocity + ShipVeloFB = BNet_Math_ClampF(ShipVeloFB + (KeyDown(17) - KeyDown(31)) * 2.5, -ShipMaxVeloFB, ShipMaxVeloFB) + ShipVeloLR = BNet_Math_ClampF(ShipVeloLR + (KeyDown(32) - KeyDown(30)) * 1.5, -ShipMaxVeloLR, ShipMaxVeloLR) + ShipVeloUD = BNet_Math_ClampF(ShipVeloUD + (KeyDown(19) - KeyDown(33)) * 1.5, -ShipMaxVeloUD, ShipMaxVeloUD) + ; Rotation + If KeyDown(57) Then + If KeyHit(57) Then MoveMouse 512, 384 + TestRX = TestRX + ((MouseX() / 512) - 1.0) + TestRY = TestRY + ((MouseY() / 384) - 1.0) + EndIf + TestRZ = TestRZ + (KeyDown(18) - KeyDown(16)) * 1.0 + + ; Update Game + ; Slowly scale down Velocity. + ShipVeloFB = ShipVeloFB * 0.9 + ShipVeloLR = ShipVeloLR * 0.8 + ShipVeloUD = ShipVeloUD * 0.8 + ; Convert Local Velocity to Global Velocity + TFormPoint ShipVeloLR, ShipVeloUD, ShipVeloFB, Player\Mesh, Conv + TestVX = TFormedX() + TestVY = TFormedY() + TestVZ = TFormedZ() + ; Move player by Velocity. + TestX = TestX + TestVX + TestY = TestY + TestVY + TestZ = TestZ + TestVZ + + ; Draw Game + ; Update Local Mesh + PositionEntity Player\Mesh, TestX, TestY, TestZ + RotateEntity Player\Mesh, TestRX, TestRY, TestRZ + ; Update conversion point + PositionEntity Conv, TestX, TestY, TestZ + + RenderWorld + Flip 0 + EndIf + + If BNet_Update() Then + LoopExit = True + EndIf + WaitTimer FrameTimer + Until (LoopExit = True) + If BNet_Kick = True Then Print "[INF] Kicked: " + BNet_Kick_Reason Else Print "Logging out." + + BNet_Disconnect() +Else + Print "[ERR] Failed to connect." +EndIf +End + +Function CB_BNet_CreatePlayer(UniqueId, Player.BNetPlayer) + DebugLog "[INF] New Player: " + Player\Name + "[" + UniqueId + "]" + DebugLog " Pos: " + Player\PositionX + ", " + Player\PositionY + ", " + Player\PositionZ + DebugLog " Rot: " + Player\RotationX + ", " + Player\RotationY + ", " + Player\RotationZ + + If Players(UniqueId) = Null Then Players(UniqueId) = New TPlayer + If Players(UniqueId)\Mesh <> 0 Then Players(UniqueId)\Mesh = CreateCone() + Players(UniqueId)\Player = Player + + PositionEntity Players(UniqueId)\Mesh, Player\PositionX, Player\PositionY, Player\PositionZ + RotateEntity Players(UniqueId)\Mesh, Player\RotationX, Player\RotationY, Player\RotationZ +End Function + +Function CB_BNet_UpdatePlayer(UniqueId, Player.BNetPlayer) + If Players(UniqueId) <> Null Then + DebugLog "[INF] Update Player: " + Player\Name + "[" + UniqueId + "]" + DebugLog " Pos: " + Player\PositionX + ", " + Player\PositionY + ", " + Player\PositionZ + DebugLog " Rot: " + Player\RotationX + ", " + Player\RotationY + ", " + Player\RotationZ + + PositionEntity Players(UniqueId)\Mesh, Player\PositionX, Player\PositionY, Player\PositionZ + RotateEntity Players(UniqueId)\Mesh, Player\RotationX, Player\RotationY, Player\RotationZ + Else + DebugLog "[ERR] Player does not exist: " + Player\Name + "[" + UniqueId + "]" + EndIf +End Function + +Function CB_BNet_DeletePlayer(UniqueId, Player.BNetPlayer) + If Players(UniqueId) <> Null Then + DebugLog "[INF] Delete Player: " + UniqueId + "," + Player\Name + + FreeEntity Players(UniqueId)\Mesh + Delete Players(UniqueId) + Else + DebugLog "[ERR] Player does not exist: " + Player\Name + "[" + UniqueId + "]" + EndIf +End Function + +Function CB_BNet_SendUpdate(UniqueId, Player.BNetPlayer) + DebugLog "[INF] Update Self" + + Player\PositionX = TestX + Player\PositionY = TestY + Player\PositionZ = TestZ + + Player\VelocityX = TestVX + Player\VelocityY = TestVY + Player\VelocityZ = TestVZ + + Player\RotationX = TestRX + Player\RotationY = TestRY + Player\RotationZ = TestRZ + + Player\AimX = TestAX + Player\AimY = TestAY +End Function + +Type TPlayer + Field Mesh + + Field Player.BNetPlayer +End Type \ No newline at end of file diff --git a/BlitzBasic/All/Random Stuff/README.md b/BlitzBasic/All/Random Stuff/README.md new file mode 100644 index 0000000..874584b --- /dev/null +++ b/BlitzBasic/All/Random Stuff/README.md @@ -0,0 +1,8 @@ +Random Stuff +======================= + +Contains remaining projects that don't require their own folder or were modified to fit a specific project. Most of this is from Sirius Online and BlitzHit, so expect nothing to work. + +License +======= +Random Stuff by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/. \ No newline at end of file diff --git a/BlitzBasic/All/Random Stuff/Test.bb b/BlitzBasic/All/Random Stuff/Test.bb new file mode 100644 index 0000000..7a6e705 --- /dev/null +++ b/BlitzBasic/All/Random Stuff/Test.bb @@ -0,0 +1,44 @@ +AppTitle "TrueMotion" +Include "TrueMotion.bb" + +Graphics3D 1024,768,0,2 +SetBuffer BackBuffer() +SeedRnd MilliSecs() + +Local eCamera = CreateCamera() + +Local tCube = CreateTexture(128,128) +SetBuffer TextureBuffer(tCube) +Color 255, 255, 0 +Rect 0, 0, 64, 64 +Rect 64, 64, 64, 64 +Color 0, 127, 255 +Rect 64, 0, 64, 64 +Rect 0, 64, 64, 64 + +SetBuffer BackBuffer() + +Local eCube = CreateCube() +PositionEntity eCube, 0, 0, 3 +EntityTexture eCube, tCube + +Local tInstance.TrueMotion = TrueMotion_Create(eCamera) + +Timer = CreateTimer(60) + +Global Msec +While Not KeyHit(1) + Cls + + Msec = Msec + 10 + RotateEntity eCube, Cos(Msec/4.0)*30, 0, EntityRoll(eCube) + 16 + PositionEntity eCube, 0, Sin(Msec/4.0)*2, 4 + + TrueMotion_RenderWorld(tInstance) + Flip + WaitTimer(Timer) +Wend + +End +;~IDEal Editor Parameters: +;~C#Blitz3D \ No newline at end of file diff --git a/BlitzBasic/All/Random Stuff/Tradelane.bb b/BlitzBasic/All/Random Stuff/Tradelane.bb new file mode 100644 index 0000000..414c61c --- /dev/null +++ b/BlitzBasic/All/Random Stuff/Tradelane.bb @@ -0,0 +1,207 @@ +Type Tradelane + Field P1.TVector, P2.TVector, Dir.TVector + Field From$, Target$ + Field FromSpot.Spotmark, TargetSpot.Spotmark + + Field Gates.TList, Lasers.TList + Field RingsTop.TList, RingsBot.TList + Field RingsInnerTop.TList, RingsInnerBot.TList + Field TubesTop.TList, TubesBot.TList + + Field PivotTubes + Field PivotRings + + Field MeshA, MeshB, OBBa, OBBb + Field XTubeA, XTubeB + Field Range +End Type + +Const Tradelane_Speed# = 50.0 +Const Tradelane_SpeedForce# = 0.125 +Const Tradelane_Force# = 0.1 + +Const Tradelane_GateDistance# = 5000.0 +Const Tradelane_Offset# = 144 +Const Tradelane_Size# = 115 + +Function CreateTradelane(StartX,StartY,StartZ, EndX,EndY,EndZ, From$, Target$) + Local T.Tradelane = New Tradelane + Local TempVec.TVector + + ; Information + T\From = From:T\Target = Target + + ; Start, End and Direction Vector + T\P1 = TVector_Create(StartX, StartY, StartZ) + T\P2 = TVector_Create(EndX, EndY, EndZ) + TempVec = TVector_Subtract(T\P2, T\P1) + T\Dir = TVector_Normalize(TempVec):Delete TempVec + Local Range# = TVector_Distance(T\P1, T\P2) + + ; Initialize LinkedLists + T\Gates = TList_Create() + T\Lasers = TList_Create() + T\RingsTop = TList_Create() + T\RingsBot = TList_Create() + T\RingsInnerTop = TList_Create() + T\RingsInnerBot = TList_Create() + T\TubesTop = TList_Create() + T\TubesBot = TList_Create() + + T\PivotRings = CreatePivot(PVTxEFFECT) + T\PivotTubes = CreatePivot(PVTxEFFECT) + + ; Create Spots + T\FromSpot.Spotmark = CreateSpot(T\P1\X, T\P1\Y, T\P1\Z, 21, (From + ">>>" + Target)) + T\FromSpot.Spotmark = CreateSpot(T\P2\X, T\P2\Y, T\P2\Z, 21, (Target + ">>>" + From)) + + ; Create OBB Collisions + TVector_Angle(T\Dir) + Local TX#, TY#, TZ# + TX = (T\P1\X + T\P2\X) / 2.0 + TY = (T\P1\Y + T\P2\Y) / 2.0 + TZ = (T\P1\Z + T\P2\Z) / 2.0 + + Local TVecUp.TVector = TVector_Rotate(T\Dir, -90, 0, 0) + T\OBBa=CreateOBB(TX, TY, TZ, TVector_Pitch-90, TVector_Yaw, 0, 115, 115, Range/2) + T\OBBb=CreateOBB(TX, TY, TZ, TVector_Pitch-90, TVector_Yaw, 0, 115, 115, Range/2) MoveEntity T\OBBa, 0, Tradelane_Offset, 0 + MoveEntity T\OBBb, 0, -Tradelane_Offset, 0 + Delete TVecUp + + ; Create Gates, Sprites and Rings + Local Count = Ceil(Range / Tradelane_GateDistance) + Local Stp# = Range / Count + For n = 0 To Count + ; Calculate Position + TempVec = TVector_MultiplyScalar(T\Dir, n*Stp) + Local Pos.TVector = TVector_Add(T\P1, TempVec) + + ; Create Mesh + Local Mesh = CopyEntity(TLxMSH, PVTxNORMAL) + PositionEntity Mesh, Pos\X, Pos\Y, Pos\Z + AlignToVector Mesh, T\Dir\X, T\Dir\Y, T\Dir\Z, 0, 1 + RotateEntity Mesh, EntityPitch(Mesh, 1), EntityYaw(Mesh, 1), 0, 1 + EntityAutoFade Mesh,14500,15000 + TList_AddLast(T\Gates, Mesh) + + ; Create Laser + Local Laser = CopyEntity(TLxMSX, Mesh) + EntityAutoFade Laser,9500,10000 + TList_AddLast(T\Lasers, Laser) + + ; Create Rings + Local RingTop = CopyEntity(TLxENT, Mesh) + Local RingBot = CopyEntity(TLxENT, Mesh) + MoveEntity RingTop, 0, Tradelane_Offset, 0 + MoveEntity RingBot, 0, -Tradelane_Offset, 0 + ScaleSprite RingTop, 125, 125:SpriteViewMode RingTop, 2:EntityColor RingTop, 64, 198, 255:EntityAlpha RingTop, 0.5:EntityAutoFade RingTop, 4500, 5000:EntityBlend RingTop, 3:EntityFX RingTop, 1+16 + ScaleSprite RingBot, 125, 125:SpriteViewMode RingBot, 2:EntityColor RingBot, 255, 0, 0:EntityAlpha RingBot, 0.5:EntityAutoFade RingBot, 4500, 5000:EntityBlend RingBot, 3:EntityFX RingBot, 1+16 + TList_AddLast(T\RingsTop, RingTop) + TList_AddLast(T\RingsBot, RingBot) + + Local RingInTop = CopyEntity(TLxENT2, Mesh) + Local RingInBot = CopyEntity(TLxENT2, Mesh) + MoveEntity RingInTop, 0, Tradelane_Offset, 0 + MoveEntity RingInBot, 0, -Tradelane_Offset, 0 + ScaleSprite RingInTop, 125, 125:SpriteViewMode RingInTop, 2:EntityAlpha RingInTop, 0.5:EntityAutoFade RingInTop, 4500, 5000:EntityBlend RingInTop, 3:EntityFX RingInTop, 1+16 + ScaleSprite RingInBot, 125, 125:SpriteViewMode RingInBot, 2:EntityAlpha RingInBot, 0.5:EntityAutoFade RingInBot, 4500, 5000:EntityBlend RingInBot, 3:EntityFX RingInBot, 1+16 + TList_AddLast(T\RingsInnerTop, RingInTop) + TList_AddLast(T\RingsInnerBot, RingInBot) + + ; Create Refraction Tubes + If n < Count + Local Tube + Tube = CreateCylinder(24, 0, RingInTop) + ScaleEntity Tube, Tradelane_Size, Stp/2, Tradelane_Size + TurnEntity Tube, -90, 0, 0 + MoveEntity Tube, 0, -Stp/2, 0 + EntityParent Tube, T\PivotTubes + EntityAutoFade Tube, 5000, 10000 + EntityFX Tube, 1+8+16 + EntityTexture Tube,StarBTex,0,0 + EntityTexture Tube,ProjectTex,0,1 + EntityAlpha Tube, 0.35 + TList_AddLast(T\TubesTop, Tube) + + Tube = CreateCylinder(24, 0, RingInBot) + ScaleEntity Tube, Tradelane_Size, Stp/2, Tradelane_Size + TurnEntity Tube, 90, 0, 0 + MoveEntity Tube, 0, Stp/2, 0 + EntityParent Tube, T\PivotTubes + EntityAutoFade Tube, 5000, 10000 + EntityFX Tube, 1+8+16 + EntityTexture Tube,StarBTex,0,0 + EntityTexture Tube,ProjectTex,0,1 + EntityAlpha Tube, 0.35 + TList_AddLast(T\TubesBot, Tube) + EndIf + + ; Delete remaining temporary data + Delete Pos:Delete TempVec + Next +End Function + +Function UpdateTradelane() + ;set test on + TLxTST=0 + + ; Create Camera Vector + Local vCam.TVector = New TVector + Local vGate.TVector = New TVector + Local vTmp.TVector = Null + Local vTmp2.TVector = Null + vCam\X = EntityX(cCamera, 1) + vCam\Y = EntityY(cCamera, 1) + vCam\Z = EntityZ(cCamera, 1) + + For TL.Tradelane = Each Tradelane + ; Rings + TList_Reset(TL\RingsTop):TList_Reset(TL\RingsInnerTop) + TList_Reset(TL\RingsBot):TList_Reset(TL\RingsInnerBot) + TList_Reset(TL\Gates) + While TList_HasNext(TL\Gates) + Local RT = TList_Next(TL\RingsTop) + Local RTI = TList_Next(TL\RingsInnerTop) + Local RB = TList_Next(TL\RingsBot) + Local RBI = TList_Next(TL\RingsInnerBot) + Local Gate = TList_Next(TL\Gates) + + TurnEntity RT, 0, 0, -.1 + TurnEntity RB, 0, 0, .1 + + vGate\X = EntityX(Gate, 1) + vGate\Y = EntityY(Gate, 1) + vGate\Z = EntityZ(Gate, 1) + + vTmp = TVector_Subtract(vGate, vCam) + vTmp2 = TVector_Normalize(vTmp):Delete vTmp + + Local Dot# = TVector_Dot(TL\Dir, vTmp2):Delete vTmp2 + If Dot >= 0 Then + EntityColor RT, 64, 198, 255 + EntityColor RB, 255, 0, 0 + Else + EntityColor RB, 64, 198, 255 + EntityColor RT, 255, 0, 0 + EndIf + Wend + + ; Traveling + If EntityInOBB(TL\OBBa,pvShip) + AlignToVector pvShip, TL\Dir\X, TL\Dir\Y, TL\Dir\Z, 0, Tradelane_Force + ShipSpeedZ = (ShipSpeedZ * (1-Tradelane_SpeedForce)) + (Tradelane_Speed * Tradelane_SpeedForce) + TLxTST=1 + EndIf + If EntityInOBB(TL\OBBB,pvShip) + AlignToVector pvShip, -TL\Dir\X, -TL\Dir\Y, -TL\Dir\Z, 0, Tradelane_Force + ShipSpeedZ = (ShipSpeedZ * (1-Tradelane_SpeedForce)) + (Tradelane_Speed * Tradelane_SpeedForce) + TLxTST=1 + EndIf + Next + Delete vCam:Delete vGate + + PositionTexture StarBTex, Sin(MilliSecs() / 10000.0), (MilliSecs() / 10000.0) Mod 1 + +End Function +;~IDEal Editor Parameters: +;~C#Blitz3D \ No newline at end of file diff --git a/BlitzBasic/All/Random Stuff/TrueMotion.bb b/BlitzBasic/All/Random Stuff/TrueMotion.bb new file mode 100644 index 0000000..0e5887d --- /dev/null +++ b/BlitzBasic/All/Random Stuff/TrueMotion.bb @@ -0,0 +1,51 @@ +Type TrueMotion + Field Camera% = 0 + Field Mesh% = 0 +End Type + +Function TrueMotion_Create.TrueMotion(Camera%) + ;Create TrueMotion Instance + tInstance.TrueMotion = New TrueMotion + + ; Camera can't be Null or invalid + If Camera = 0 Then + RuntimeError "TrueMotion: Camera is Null." + Else + If EntityClass(Camera) <> "Camera" Then + RuntimeError "TrueMotion: Camera is not of type ." + Else + tInstance\Camera = Camera + EndIf + EndIf + + ; Create Mesh + tInstance\Mesh = CreateMesh(tInstance\Camera) + sSurface = CreateSurface(tInstance\Mesh) + AddVertex(sSurface, -1, 1, 0, 0, 0) + AddVertex(sSurface, 1, 1, 0, 1, 0) + AddVertex(sSurface, 1, -1, 0, 1, 1) + AddVertex(sSurface, -1, -1, 0, 0, 1) + AddTriangle(sSurface, 0, 1, 2) + AddTriangle(sSurface, 0, 2, 3) + + EntityOrder(tInstance\Mesh, -1) + EntityColor(tInstance\Mesh, 0, 0, 0) + PositionEntity(tInstance\Mesh, 0, 0, 1) + HideEntity(tInstance\Mesh) + + Return tInstance +End Function + +; Call this before after you have done your changes. It is a good practice to only let this effect affect nearby entities. +Function TrueMotion_RenderWorld(tInstance.TrueMotion, Steps%=12) + ShowEntity(tInstance\Mesh) + EntityAlpha(tInstance\Mesh, 1.0/Steps) + CameraClsMode(tInstance\Camera, 0, 1) + For curStep = 0 To Steps - 1 + RenderWorld curStep/Float(Steps) + Next + HideEntity(tInstance\Mesh) + RenderWorld 1 + CameraClsMode(tInstance\Camera, 1, 1) + CaptureWorld +End Function \ No newline at end of file diff --git a/BlitzBasic/All/Random Stuff/VectorMath.bb b/BlitzBasic/All/Random Stuff/VectorMath.bb new file mode 100644 index 0000000..d71e372 --- /dev/null +++ b/BlitzBasic/All/Random Stuff/VectorMath.bb @@ -0,0 +1,161 @@ +;VectorMath.bb + +Type TVector + Field X#,Y#,Z# +End Type + +Global VectorForward.TVector = TVector_Create( 0, 0, 1) +Global VectorBackward.TVector = TVector_Create( 0, 0, -1) +Global VectorLeft.TVector = TVector_Create(-1, 0, 0) +Global VectorRight.TVector = TVector_Create( 1, 0, 0) +Global VectorUp.TVector = TVector_Create( 0, 1, 0) +Global VectorDown.TVector = TVector_Create( 0, -1, 0) + +Function TVector_Create.TVector(X#,Y#,Z#) + Local R.TVector = New TVector + R\X = X + R\Y = Y + R\Z = Z + Return R +End Function +Function TVector_Copy.TVector(A.TVector) + Return TVector_Create(A\X,A\Y,A\Z) +End Function + +Function TVector_Add.TVector(A.TVector, B.TVector) + Local R.TVector = New TVector + R\X = A\X + B\X + R\Y = A\Y + B\Y + R\Z = A\Z + B\Z + Return R +End Function +Function TVector_AddScalar.TVector(A.TVector, B#) + Local R.TVector = New TVector + R\X = A\X + B + R\Y = A\Y + B + R\Z = A\Z + B + Return R +End Function + +Function TVector_Subtract.TVector(A.TVector, B.TVector) + Local R.TVector = New TVector + R\X = A\X - B\X + R\Y = A\Y - B\Y + R\Z = A\Z - B\Z + Return R +End Function +Function TVector_SubtractScalar.TVector(A.TVector, B#) + Local R.TVector = New TVector + R\X = A\X - B + R\Y = A\Y - B + R\Z = A\Z - B + Return R +End Function + +Function TVector_Multiply.TVector(A.TVector, B.TVector) + Local R.TVector = New TVector + R\X = A\X * B\X + R\Y = A\Y * B\Y + R\Z = A\Z * B\Z + Return R +End Function +Function TVector_MultiplyScalar.TVector(A.TVector, B#) + Local R.TVector = New TVector + R\X = A\X * B + R\Y = A\Y * B + R\Z = A\Z * B + Return R +End Function + +Function TVector_Divide.TVector(A.TVector, B.TVector) + Local R.TVector = New TVector + R\X = A\X / B\X + R\Y = A\Y / B\Y + R\Z = A\Z / B\Z + Return R +End Function +Function TVector_DivideScalar.TVector(A.TVector, B#) + Local R.TVector = New TVector + R\X = A\X / B + R\Y = A\Y / B + R\Z = A\Z / B + Return R +End Function + +Function TVector_Normalize.TVector(A.TVector, MultiPass%=True) + Local R1.TVector, R.TVector + R = TVector_DivideScalar(A, TVector_Length(A)) + If MultiPass Then + R1 = R + R = TVector_DivideScalar(R1, TVector_Length(R1)) + Delete R1 + EndIf + Return R +End Function +Function TVector_Rotate.TVector(A.TVector, Pitch#, Yaw#, Roll#) + Local M1.TVector = TVector_Create(Cos(Roll) * Cos(Yaw), -Sin(Roll), Sin(Yaw)) + Local M2.TVector = TVector_Create(Sin(Roll), Cos(Roll) * Cos(Pitch), -Sin(Pitch)) + Local M3.TVector = TVector_Create(-Sin(Yaw), Sin(Pitch), Cos(Yaw) * Cos(Pitch)) + + Local R.TVector = New TVector + R\X = (A\X * M1\X) + (A\Y * M1\Y) + (A\Z * M1\Z) + R\Y = (A\X * M2\X) + (A\Y * M2\Y) + (A\Z * M2\Z) + R\Z = (A\X * M3\X) + (A\Y * M3\Y) + (A\Z * M3\Z) + Delete M1:Delete M2:Delete M3:Return R +End Function +Function TVector_RotateAround.TVector(A.TVector, B.TVector, Pitch#, Yaw#, Roll#) + Local R1.TVector = TVector_Subtract(A, B) + Local R2.TVector = TVector_Rotate(R1, Pitch, Yaw, Roll) + Local R3.TVector = TVector_Add(R2, B) + Delete R1:Delete R2:Return R3 +End Function +Function TVector_RotateAroundScalar.TVector(A.TVector, X#, Y#, Z#, Pitch#, Yaw#, Roll#) + Local B.TVector = TVector_Create(X,Y,Z) + Local R.TVector = TVector_RotateAround(A, B, Pitch, Yaw, Roll) + Delete B:Return R +End Function + +Function TVector_Dot#(A.TVector, B.TVector) + Return ((A\X*B\X)+(A\Y*B\Y)+(A\Z*B\Z)) +End Function +Function TVector_Cross.TVector(A.TVector, B.TVector) + Local R.TVector = New TVector + R\X = (A\Y*B\Z) - (A\Z*B\Y) + R\Y = (A\Z*B\X) - (A\X*B\Z) + R\Z = (A\X*B\Y) - (A\Y*B\X) + Return R +End Function + +Global TVector_Pitch#, TVector_Yaw# +Function TVector_Angle(A.TVector) ; X + TVector_Pitch = VectorPitch(A\X, A\Y, A\Z);-ATan2(A\Y, Sqr((A\X*A\X) + (A\Z*A\Z))) + 90 + TVector_Yaw# = VectorYaw(A\X, A\Y, A\Z);ATan2(A\Z, A\X) - 90 +End Function + +Function TVector_PitchFrom#(A.TVector, B.TVector) ; X + ;Return ATan2(A\Y-B\Y, A\Z-B\Z) + Return VectorPitch(A\X-B\X, A\Y-B\Y, A\Z-B\Z) +End Function +Function TVector_YawFrom#(A.TVector, B.TVector) ; Y + ;Return ATan2(A\Z-B\Z, A\X-B\X) + Return VectorYaw(A\X-B\X, A\Y-B\Y, A\Z-B\Z) +End Function +;Function TVector_RollFrom#(A.TVector, B.TVector) ; Z +; Return ATan2(A\Y-B\Y, A\X-B\X) +;End Function + +Function TVector_Length#(A.TVector) + Return Sqr((A\X*A\X)+(A\Y*A\Y)+(A\Z*A\Z)) +End Function +Function TVector_Distance#(A.TVector, B.TVector) + Local X# = (A\X-B\X) + Local Y# = (A\Y-B\Y) + Local Z# = (A\Z-B\Z) + Return Sqr(X*X+Y*Y+Z*Z) +End Function + +Function TVector_ToString$(A.TVector) + Return "{X:"+A\X+";Y:"+A\Y+";Z:"+A\Z+"}" +End Function +;~IDEal Editor Parameters: +;~C#Blitz3D \ No newline at end of file diff --git a/BlitzBasic/All/Sirius Online Inventory/README.md b/BlitzBasic/All/Sirius Online Inventory/README.md new file mode 100644 index 0000000..83a0f34 --- /dev/null +++ b/BlitzBasic/All/Sirius Online Inventory/README.md @@ -0,0 +1,8 @@ +Sirius Online Inventory +======================= + +This was ment to be in the Sirius Online project, but the lead devloper never got further than complaining. So it has the side-effect of not working.I planned to optimize it to use as little memory and network bandwidth as possible, but the project was abandoned before I could go that far. Right now, it probably doesn't even work. + +License +======= +Sirius Online Inventory by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/. \ No newline at end of file diff --git a/BlitzBasic/All/Sirius Online Inventory/SOInventory.bb b/BlitzBasic/All/Sirius Online Inventory/SOInventory.bb new file mode 100644 index 0000000..da457cb --- /dev/null +++ b/BlitzBasic/All/Sirius Online Inventory/SOInventory.bb @@ -0,0 +1,407 @@ +;---------------------------------------------------------------- +;-- Constants +;---------------------------------------------------------------- +Const ITEM_MAXIMUMID = 65535 + ; Item Classes +Const ITEM_CLASS_WEAPON = 1 +Const ITEM_CLASS_SHIELD = 2 +Const ITEM_CLASS_ARMOR = 3 +Const ITEM_CLASS_ENGINE = 4 +Const ITEM_CLASS_POWERCORE = 5 +Const ITEM_CLASS_RESOURCE = 6 +Const ITEM_CLASS_UPGRADE = 7 +Const ITEM_CLASS_MININGMODULE = 8 +Const ITEM_CLASS_ELITIUM = 255 + ; Return Codes +Const INVENTORY_RC_OK = 0 +Const INVENTORY_RC_INVALIDID = -1 +Const INVENTORY_RC_INVALIDAMOUNT = -2 +Const INVENTORY_RC_UNKNOWNITEM = -3 +Const INVENTORY_RC_ITEMTOOBIG = -4 +Const INVENTORY_RC_ITEMNOTFOUND = -5 + +;---------------------------------------------------------------- +;-- Types +;---------------------------------------------------------------- + ; Item Definition +Type TItem + Field ID% + + Field Name$ ; Name of the Item + Field Description$ ; Description of the Item + Field Image ; Handle of the Image for the Item + + Field Size% ; Size in cubic decimeters. Divide by 1000 to get the size in cube meters, which is displayed. + Field Rarity% ; Rarity + + Field Class% ; Class of the Item. + Field AttributeID0% + Field AttributeID1% + Field AttributeID2% + Field AttributeID3% + + ; Attributes for Class: Weapon + ; - Short/255 Electric Damage (Attribute 0 High) + ; - Short/255 Physical Damage (Attribute 0 Low) + ; - Short/255 Rate of Fire (Attribute 1 High) + ; - Short Energy (Attribute 3 High) + ; - Short/255 CPU (Attribute 3 Low) + ; Attributes for Class: Shield + ; - Int Shield Maximum (Attribute 0) + ; - Short/255 Electric Resist (Attribute 1 High) + ; - Short/255 Physical Resist (Attribute 1 Low) + ; - Short Recharge Amount (Attribute 2 High) + ; - Short Recharge Rate (Attribute 2 Low) + ; - Short/255 CPU (Attribute 3 Low) + ; Attributes for Class: Armor + ; - Int Armor Maximum (Attribute 0) + ; - Short/255 Speed Modifier (Attribute 1 High) + ; - Short/255 Turn Modifier (Attribute 1 Low) + ; - Short/255 Signature Mod. (Attribute 2 High) + ; Attributes for Class: Engine + ; - Short/255 Maximum Speed (Attribute 0 High) + ; - Short/255 Maximum Boost (Attribute 0 Low) + ; - Short Trace Type (Attribute 2 High) + ; - Short/255 Trace Threshold (Attribute 2 Low) + ; - Short Energy (Attribute 3 High) + ; - Short/255 CPU (Attribute 3 Low) + ; Attributes for Class: PowerCore + ; - Int Energy Maximum (Attribute 0) + ; - Short Energy Amount (Attribute 1 High) + ; - Short Energy Rate (Attribute 1 Low) + ; - Byte Elec. Signature (Attribute 2 High 1) + ; - Byte Scramble Str. (Attribute 2 High 0) + ; - Short/255 CPU (Attribute 3 Low) + ; Attributes for Class: Resource + ; - Byte Processing Tier (Attribute 0 Low 1) + ; - Byte Load Type (Attribute 0 Low 0) + ; - Int Half-life Time (Attribute 3) + ; Attributes for Class: Upgrade + ; - Byte/127 Armor Bonus (Attribute 0 High 1) + ; - Byte/127 Shield Bonus (Attribute 0 High 0) + ; - Byte/127 Speed Bonus (Attribute 0 Low 1) + ; - Byte/127 Cargo Bonus (Attribute 0 Low 0) + ; - Byte/127 Elec. Sig. Mod. (Attribute 1 High 1) + ; - Byte/127 Grav. Sig. Mod. (Attribute 1 High 0) + ; - Byte/127 Elec. Dmg. Mod. (Attribute 1 Low 1) + ; - Byte/127 Phys. Dmg. Mod. (Attribute 1 Low 0) + ; - Byte/127 El. ShRes Mod. (Attribute 2 High 1) + ; - Byte/127 Ph. ShRes Mod. (Attribute 2 High 0) + ; - Byte/127 El. ArRes Mod. (Attribute 2 Low 1) + ; - Byte/127 Ph. ArRes Mod. (Attribute 2 Low 0) + ; - Byte Scramble Str. (Attribute 3 High 1) + ; - Byte/127 Yield Bonus (Attribute 3 High 0) + ; - Byte Energy Max (Attribute 3 Low 1) + ; - Byte/127 CPU Modifier (Attribute 3 Low 0) + ; Attributes for Class: Mining Module + ; - + ; Attributes for Class: Elitium + ; - +End Type +Dim Items.TItem(ITEM_MAXIMUMID) + + ; Inventory +Type TInventory + Field Size% ; Size in cubic meters. Divide by 1000 to get the size in cube meters, which is displayed. + Field Used% ; Used space in cubic decimeters. Divide by 1000 to get the size in cube meters, which is displayed. + + ; Array containing all Items using their ItemID as index. + Field Items.TInventoryItem[ITEM_MAXIMUMID] +End Type + +Type TInventoryItem + Field Amount% ; How many of this Item are stored? +End Type + +;---------------------------------------------------------------- +;-- Functions +;---------------------------------------------------------------- + ; Create a new inventory. +Function TInventory_Create.TInventory(Size%) + If Size <= 0 Then RuntimeError "TInventory: Size is equal to or less than 0." + + Local lInventory.TInventory = New TInventory + lInventory\Size = Size + lInventory\Used = 0 + + Return lInventory +End Function + + ; Safely destroy an existing inventory. +Function TInventory_Destroy(pInventory.TInventory) + If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist." + + For lIndex = 0 To (ITEM_MAXIMUMID - 1) + If pInventory\Items[lIndex] <> Null Then + Delete pInventory\Items[lIndex] + pInventory\Items[lIndex] = Null + EndIf + Next + + Delete pInventory +End Function + + ; Retrieve the amount of items in the inventory with the given ItemID. +Function TInventory_GetItemAmount(pInventory.TInventory, ItemID%) + If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist." + + If ItemID >= 0 And ItemID < ITEM_MAXIMUMID Then + If Items(ItemID) <> Null Then + If pInventory\Items[ItemID] <> Null + Return pInventory\Items[ItemID]\Amount + Else + Return INVENTORY_RC_ITEMNOTFOUND + EndIf + Else + Return INVENTORY_RC_UNKNOWNITEM + EndIf + Else + Return INVENTORY_RC_INVALIDID + EndIf +End Function + + ; Set the amount of items in the inventory with the given ItemID. +Function TInventory_SetItemAmount(pInventory.TInventory, ItemID%, Amount%) + If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist." + If Amount < 0 Then Return INVENTORY_RC_INVALIDAMOUNT + + If ItemID >= 0 And ItemID < ITEM_MAXIMUMID Then + If Items(ItemID) <> Null Then + ; Remove current Amount and Size from Inventory + If pInventory\Items[ItemID] <> Null Then + pInventory\Used = pInventory\Used - (Items(ItemID)\Size * pInventory\Items[ItemID]\Amount) + If Amount = 0 Then + Delete pInventory\Items[ItemID] + pInventory\Items[ItemID] = Null + EndIf + EndIf + + If Amount > 0 + If pInventory\Items[ItemID] = Null pInventory\Items[ItemID] = New TInventoryItem + + Local lAmount = Amount + If pInventory\Used + (Items(ItemID)\Size * lAmount) > PInventory\Size Then lAmount = (pInventory\Size - pInventory\Used) / Items(ItemID)\Size + + pInventory\Items[ItemID]\Amount = lAmount + pInventory\Used = pInventory\Used + (Items(ItemID)\Size * lAmount) + + Return lAmount + Else + Return INVENTORY_RC_OK + EndIf + If pInventory\Items[ItemID] <> Null Then lSize = lSize - (Items(ItemID)\Size * pInventory\Items[ItemID]\Amount) + Else + Return INVENTORY_RC_UNKNOWNITEM + EndIf + Else + Return INVENTORY_RC_INVALIDID + EndIf +End Function + + ; Add an item to the inventory. + ; Returns the amount of items added or a negative value (error code) +Function TInventory_AddItem(pInventory.TInventory, ItemID%, Amount%=1) + If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist." + If Amount <= 0 Then Return INVENTORY_RC_INVALIDAMOUNT + + If ItemID >= 0 And ItemID < ITEM_MAXIMUMID Then + If Items(ItemID ) <> Null Then + Local lAmount = Amount + + If pInventory\Used + (lAmount * Items(ItemID)\Size) > pInventory\Size Then lAmount = (pInventory\Size - pInventory\Used) / Items(ItemID)\Size + + If lAmount > 0 Then + If pInventory\Items[ItemID] = Null Then pInventory\Items[ItemID] = New TInventoryItem + pInventory\Items[ItemID]\Amount = pInventory\Items[ItemID]\Amount + lAmount + pInventory\Used = pInventory\Used + (lAmount * Items(ItemID)\Size) + EndIf + + Return lAmount + Else + Return INVENTORY_RC_UNKNOWNITEM + EndIf + Else + Return INVENTORY_RC_INVALIDID + EndIf +End Function + + ; Remove an item from the inventory. + ; Returns the amount of items removed or a negative value (error code). +Function TInventory_RemoveItem(pInventory.TInventory, ItemID%, Amount%=1) + If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist." + If Amount <= 0 Then Return INVENTORY_RC_INVALIDAMOUNT + + If ItemID >= 0 And ItemID < ITEM_MAXIMUMID Then + If Items(ItemID) <> Null Then + If pInventory\Items[ItemID] <> Null Then + Local lAmount = pInventory\Items[ItemID]\Amount + pInventory\Items[ItemID]\Amount = pInventory\Items[ItemID]\Amount - Amount + + If pInventory\Items[ItemID]\Amount <= 0 Then + pInventory\Used = pInventory\Used - (lAmount * Items(ItemID)\Size) + ; Delete Item Entry (Reduces Memory Usage) + Delete pInventory\Items[ItemID]:pInventory\Items[ItemID] = Null + + Return lAmount + Else + pInventory\Used = pInventory\Used - (Amount * Items(ItemID)\Size) + + Return Amount + EndIf + Else + Return INVENTORY_RC_ITEMNOTFOUND + EndIf + Else + Return INVENTORY_RC_UNKNOWNITEM + EndIf + Else + Return INVENTORY_RC_INVALIDID + EndIf +End Function + + ; For when you edit the inventory without using the above functions. +Function TInventory_RecalculateUsedSpace(pInventory.TInventory) + If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist." + + pInventory\Used = 0 + For lIndex = 0 To (ITEM_MAXIMUMID - 1) + If Items(lIndex) <> Null And pInventory\Items[lIndex] <> Null Then + pInventory\Used = pInventory\Used + (pInventory\Items[lIndex]\Amount * Items(lIndex)\Size) + EndIf + Next +End Function + +;---------------------------------------------------------------- +;-- Extras - Require 'LinkedListEmulation.bb'! +;---------------------------------------------------------------- +;Type TInventoryItemLink +; Field ItemID% +; Field Amount% +;End Type +; +; ; Retrieve a LinkedList containing all items in this inventory. +; ; The returned list must be deleted using TInventory_DeleteItemList(...). +; ; Modifications on this list can only be applied to the inventory using TInventory_SetItemList(...). +;Function TInventory_GetItemList.TList(pInventory.TInventory) +; If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist." +; +; Local lList.TList = TList_Create() +; For lIndex = 0 To (ITEM_MAXIMUMID - 1) +; If Items(lIndex) <> Null And pInventory\Items[lIndex] <> Null Then +; Local lInvItemLink.TInventoryItemLink = New TInventoryItemLink +; lInvItemLink\ItemID = lIndex +; lInvItemLink\Amount = pInventory\Items[lIndex]\Amount +; TList_AddLast(lInvItemLink) +; EndIf +; Next +; +; Return lList +;End Function +; +;Function TInventory_SetItemList(pInventory.TInventory, pList.TList) +; If pInventory = Null Then RuntimeError "TInventory: Inventory does not exist." +; If pList = Null Then RuntimeError "TInventory: List does not exist." +; +; pInventory\Used = 0 +; For lIndex = 0 To (ITEM_MAXIMUMID - 1) +; If Items(lIndex) <> Null And pInventory\Items[lIndex] <> Null Then +; Delete pInventory\Items[lIndex] +; pInventory\Items[lIndex] = Null +; EndIf +; Next +; +; Local lInvItemLink.TInventoryItemLink = Object.TInventoryItemLink(TList_First(pList)) +; While lInvItemLink <> Null +; If lInvItemLink\ItemID >= 0 And lInvItemLink\ItemID < ITEM_MAXIMUMID Then +; If Items(lInvItemLink\ItemID) <> Null And lInvItemLink\Amount > 0 Then +; pInventory\Items[lInvItemLink\ItemID] = New TInventoryItem +; pInventory\Items[lInvItemLink\ItemID]\Amount = lInvItemLink\Amount +; +; pInventory\Used = pInventory\Used + (lInvItemLink\Amount * Items(lInvItemLink\ItemID)\Size) +; EndIf +; EndIf +; lInvItemLink = Object.TInventoryItemLink(TList_Next(pList)) +; Wend +;End Function +; +;Function TInventory_DeleteItemList(pList.TList) +; If pList = Null Then RuntimeError "TInventory: List does not exist." +; +; Local lInvItemLink.TInventoryItemLink = Object.TInventoryItemLink(TList_First(pList)) +; While lInvItemLink <> Null +; Delete lInvItemLink +; lInvItemLink = Object.TInventoryItemLink(TList_Delete(pList)) +; Wend +; +; TList_Destroy(pList) +;End Function + +;---------------------------------------------------------------- +;-- Example +;---------------------------------------------------------------- +SeedRnd(MilliSecs()) + + ; Test Item +Items(0) = New TItem +Items(0)\Name = "1dm³ Item" +Items(0)\Description = "" +Items(0)\Size = 1 + + ; Test Item +Items(1) = New TItem +Items(1)\Name = "10dm3 Item" +Items(1)\Description = "" +Items(1)\Size = 10 + + ; Test Item +Items(2) = New TItem +Items(2)\Name = "100dm3 Item" +Items(2)\Description = "" +Items(2)\Size = 100 + + ; Test Item +Items(3) = New TItem +Items(3)\Name = "1000dm3 Item" +Items(3)\Description = "" +Items(3)\Size = 1000 + +Local MyInv.TInventory = TInventory_Create(10000) +While Not KeyHit(1) + Cls + Locate 0,0 + PrintInv(MyInv) + + If Rand(0,1000) Mod 4 < 2 + TInventory_AddItem(MyInv, Rand(0,3), Rand(0,100)) + TInventory_RemoveItem(MyInv, Rand(0,3), Rand(0,100)) + Else + TInventory_SetItemAmount(MyInv, Rand(0,3), Rand(0,100)) + TInventory_SetItemAmount(MyInv, Rand(0,3), Rand(0,100)) + EndIf + + WaitKey() + Flip 0 +Wend +TInventory_Destroy(MyInv) +End + +Function PrintInv(Inv.TInventory) + Print "Inventory " + Handle(Inv) + Print " Size: " + (Inv\Size/1000) + "." + (Inv\Size Mod 1000) + " m³" + Print " Used: " + (Inv\Used/1000) + "." + (Inv\Used Mod 1000) + " m³ / " + Int((Inv\Used/Float(Inv\Size))*100) + "%" + Print " Remaining: " + ((Inv\Size - Inv\Used)/1000) + "." + ((Inv\Size - Inv\Used) Mod 1000) + " m³ / " + Int(((Inv\Size - Inv\Used)/Float(Inv\Size))*100) + "%" + Print " Items:" + For lIndex = 0 To (ITEM_MAXIMUMID - 1) + If Items(lIndex) <> Null And TInventory_GetItemAmount(Inv, lIndex) > 0 Then + Print " - " + Items(lIndex)\Name + " x" + TInventory_GetItemAmount(Inv, lIndex) + EndIf + Next + ; Alternatively, using Extras + ;Local lList.TList = TInventory_GetItemList(Inv) + ;Local lEntry.TInventoryItemLink = Object.TInventoryItemLink(TList_First(lList)) + ;While lEntry <> Null + ; Print " - " + Items(lEntry\ItemID)\Name + " x" + lEntry\Amount + ; lEntry = Object.TInventoryItemLink(TList_Next(lList)) + ;Wend + ;TInventory_DestroyItemList(lList) +End Function \ No newline at end of file diff --git a/BlitzBasic/Blitz3D/HelpersAndFixes/HelpersAndFixes.bb b/BlitzBasic/Blitz3D/HelpersAndFixes/HelpersAndFixes.bb new file mode 100644 index 0000000..e5ea55c --- /dev/null +++ b/BlitzBasic/Blitz3D/HelpersAndFixes/HelpersAndFixes.bb @@ -0,0 +1,227 @@ +;[Block] Rendering Functions +Global ERTPos#[2], ERTRot#[2] +Const ES_AxisX = 0, ES_AxisY = 1, ES_AxisZ = 2 +;[End Block] +Function EntityRenderToImage(iCam, iEnt, iImg) + Local CP#[2], EP#[2], CR#[2], Buffer = GraphicsBuffer(), SX#, SY#, SZ#, Dist#, IW = ImageWidth(iImg), IH = ImageHeight(iImg), IB = ImageBuffer(iImg) + + CP[0] = EntityX(iCam):CP[1] = EntityY(iCam):CP[2] = EntityZ(iCam) + CR[0] = EntityPitch(iCam):CR[1] = EntityYaw(iCam):CR[2] = EntityRoll(iCam) + EP[0] = EntityX(iEnt):EP[1] = EntityY(iEnt):EP[2] = EntityZ(iEnt) + + SX = EntityScale(iEnt,ES_AxisX):SY = EntityScale(iEnt,ES_AxisY):SZ = EntityScale(iEnt,ES_AxisZ) + Dist# = Sqr((SX*SX)+(SY*SY)+(SZ*SZ)) + + PositionEntity iCam, ERTPos[0], ERTPos[1], ERTPos[2] + PositionEntity iEnt, ERTPos[0], ERTPos[1], ERTPos[2]+Dist + RotateEntity iCam, 0, 0, 0 + EntityParent iEnt, iCam + RotateEntity iCam, ERTRot[0], ERTRot[1], ERTRot[2] + + CameraViewport iCam, 0, 0, IW, IH + RenderWorld + CopyRect 0,0,IW,IH,0,0,Buffer,IB + CameraViewport iCam, 0, 0, GraphicsWidth(), GraphicsHeight() + + RotateEntity iCam, 0, 0, 0 + EntityParent iEnt, 0 + + PositionEntity iCam, CP[0],CP[1],CP[2] + PositionEntity iEnt, EP[0],EP[1],EP[2] + RotateEntity iCam, CR[0],CR[1],CR[2] +End Function +Function EntityRenderToTexture(iCam, iEnt, iTex) + Local CP#[2], EP#[2], CR#[2], Buffer = GraphicsBuffer(), SX#, SY#, SZ#, Dist#, IW = TextureWidth(iTex), IH = TextureHeight(iTex), IB = TextureBuffer(iTex) + + CP[0] = EntityX(iCam):CP[1] = EntityY(iCam):CP[2] = EntityZ(iCam) + CR[0] = EntityPitch(iCam):CR[1] = EntityYaw(iCam):CR[2] = EntityRoll(iCam) + EP[0] = EntityX(iEnt):EP[1] = EntityY(iEnt):EP[2] = EntityZ(iEnt) + + SX = EntityScale(iEnt,ES_AxisX):SY = EntityScale(iEnt,ES_AxisY):SZ = EntityScale(iEnt,ES_AxisZ) + Dist# = Sqr((SX*SX)+(SY*SY)+(SZ*SZ))*0.25 + Sqr(Sqr((SX*SX)+(SY*SY)+(SZ*SZ)))*0.75 + + PositionEntity iCam, ERTPos[0], ERTPos[1], ERTPos[2] + PositionEntity iEnt, ERTPos[0], ERTPos[1], ERTPos[2]+Dist + RotateEntity iCam, 0, 0, 0 + EntityParent iEnt, iCam + RotateEntity iCam, ERTRot[0], ERTRot[1], ERTRot[2] + + CameraViewport iCam, 0, 0, IW, IH + ;SetBuffer IB ;FastEXT only + RenderWorld + CopyRect 0,0,IW,IH,0,0,Buffer,IB + CameraViewport iCam, 0, 0, GraphicsWidth(), GraphicsHeight() + ;SetBuffer Buffer ;FastEXT only + + RotateEntity iCam, 0, 0, 0 + EntityParent iEnt, 0 + + PositionEntity iCam, CP[0],CP[1],CP[2] + PositionEntity iEnt, EP[0],EP[1],EP[2] + RotateEntity iCam, CR[0],CR[1],CR[2] +End Function +Function EntityScale#( Entity, Axis ) + VX# = GetMatElement( Entity, Axis, 0 ) + VY# = GetMatElement( Entity, Axis, 1 ) + VZ# = GetMatElement( Entity, Axis, 2 ) + Return Sqr( VX#*VX# + VY#*VY# + VZ#*VZ# ) +End Function + +;[Block] Math Functions +Global HSV#[2], RGB#[2] +;[End Block] +Function Math_MaxMin#(Value#, Max#, Min#) + If Value> Max Then Return Max + If Value < Min Then Return Min + Return Value +End Function +Function Math_Max#(Value#, Max#) + If Value> Max Then Return Max + Return Value +End Function +Function Math_Min#(Value#, Min#) + If Value < Min Then Return Min + Return Value +End Function +Function Math_Clip#(Value#, Low#, High#) + Local Out#, Diff# + Diff = High-Low:Out = Value-Low + If (Out >= Diff) Then Out = Out - Floor(Out/Diff)*Diff + If (Out < 0) Then Out = Out - Floor(Out/Diff)*Diff + Return Low+Out +End Function +Function Math_RGBHSV(R,G,B) + Local maxC#, minC#, delta#, dr#, dg#, db# + + R = R/255.0:G = G/255.0:B = B/255.0 + maxC = Math_Min(Math_Min(R,G),B) + minC = Math_Max(Math_Max(R,G),B) + delta = maxC - minC + HSV[0] = 0:HSV[1] = 0:HSV[2] = maxC + + If delta = 0 + HSV[0] = 0:HSV[1] = 0 + Else + HSV[1] = delta / maxC + dr = 60*(maxC - R)/delta + 180 + dg = 60*(maxC - G)/delta + 180 + db = 60*(maxC - B)/delta + 180 + If R = maxC + HSV[0] = db - dg + ElseIf G = maxC + HSV[0] = 120 + dr - db + Else + HSV[0] = 240 + dg - dr + EndIf + EndIf + HSV[0] = Math_Clp(HSV[0],0,360) +End Function +Function Math_HSVRGB(H#,S#,V#) + Local m#, n#, f#, i + + H = Math_Clp(H,0,360)/60.0 + If H = S And S = 0 + RGB[0] = V + RGB[1] = V + RGB[2] = V + EndIf + i = Floor(H) + f = H - i + If Not (i Mod 2) Then f = 1 - f + m = V * (1-S) + n = V * (1-S*f) + Select i + Case 6,0 + RGB[0] = V*255 + RGB[1] = n*255 + RGB[2] = m*255 + Case 1 + RGB[0] = n*255 + RGB[1] = V*255 + RGB[2] = m*255 + Case 2 + RGB[0] = m*255 + RGB[1] = V*255 + RGB[2] = n*255 + Case 3 + RGB[0] = m*255 + RGB[1] = n*255 + RGB[2] = V*255 + Case 4 + RGB[0] = n*255 + RGB[1] = m*255 + RGB[2] = V*255 + Case 5 + RGB[0] = V*255 + RGB[1] = m*255 + RGB[2] = n*255 + End Select +End Function + +;[Block] String Functions +Dim SplittedString$(1) +Global SplitCount +;[End Block] +Function SplitString(In$, StringSplitter$ = "|") + Local InLength% = Len(In) + Local SplitLength% = Len(StringSplitter) + Local CountPos%, InPos%, SplitIndex% + Local SplitTest$, LineText$ + + ; Count how many Lines there are and resize Dim. + SplitCount = 0 + For CountPos = 1 To InLength-(SplitLength-1) + SplitTest = Mid(In,CountPos,1) + If SplitTest = StringSplitter Then SplitCount = SplitCount + 1 + Next + Dim SplittedString(SplitCount) + + ; Split the Text onto multiple lines. + While Not InPos = Len(In) + ; Increment Position + InPos = InPos + 1 + + ; Grab a piece of the text. + SplitTest = Mid(In, InPos, SplitLength) + Local Char$ = Left(SplitTest, 1) + + ; Check if the current Text matches the splitter or if we are near the end. + If SplitTest = StringSplitter Or InPos = InLength + ; Append the current character if it doesn't match the Splitter. + If InPos = InLength And SplitTest <> StringSplitter Then LineText = LineText + Char + + ; Store the Line. + SplittedString(SplitIndex) = LineText + + ; Increment split index. + SplitIndex = SplitIndex + 1 + + ; Reset LineText + LineText = "" + Else + LineText = LineText + Char + EndIf + Wend +End Function + +Function SafeText$(sText$) + Local sSafeText$ = sText + For i = 0 To 31 + sSafeText = Replace(sSafeText,Chr(i),"["+i+"]") + Next + Return sSafeText +End Function + +Function Replace$(S$,F$,T$,CaseSensitive=0) + Local LF = Len(F), Pos + Pos = 1 + While Not Pos > Len(S)-LF+1 + Local Check$ = Mid(S,Pos,LF) + If Lower(F) = Lower(Check) And (F = Check Or CaseSensitive=0) + S = Left(S,Pos-1)+T+Mid(S,Pos+LF,-1) + Pos = Pos + Len(T) + EndIf + Pos = Pos + 1 + Wend + Return S +End Function \ No newline at end of file diff --git a/BlitzBasic/Blitz3D/HelpersAndFixes/README.md b/BlitzBasic/Blitz3D/HelpersAndFixes/README.md new file mode 100644 index 0000000..e12781b --- /dev/null +++ b/BlitzBasic/Blitz3D/HelpersAndFixes/README.md @@ -0,0 +1,9 @@ +HelpersAndFixes +======================= + +A try at adding features to BlitzBasic that didn't exist, without touching C++ or manipulating the DLL file using reverse engineering. Worked quite well, though obviously slower than native code. +Documentation at: http://www.blitzforum.de/forum/viewtopic.php?p=374655#374655 + +License +======= +HelpersAndFixes by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/. \ No newline at end of file diff --git a/BlitzBasic/Blitz3D/Impostor/CreateImpostorTextures.bb b/BlitzBasic/Blitz3D/Impostor/CreateImpostorTextures.bb new file mode 100644 index 0000000..6e5bc7b --- /dev/null +++ b/BlitzBasic/Blitz3D/Impostor/CreateImpostorTextures.bb @@ -0,0 +1,282 @@ +Const CfgMeshToRender$ = "D:\Projekte\Blitz3D\Sirius\GFX\ENV\VINxROIDx001.3ds" +Const CfgDiffuseMap$ = "D:\Projekte\Blitz3D\Sirius\GFX\ENV\VINxROIDx001DIFF.png" +Const CfgDiffuseFlags% = (1+256+512) +Const CfgNormalMap$ = "D:\Projekte\Blitz3D\Sirius\GFX\ENV\VINxROIDx001NORM.png" +Const CfgNormalFlags = (1+256+512) + +Const CfgFrameSizeX = 128 +Const CfgFrameSizeY = 128 +Const CfgPitchMin# = -90 +Const CfgPitchMax# = 90 +Const CfgPitchFrames = 5 +Const CfgYawMin# = 0 +Const CfgYawMax# = 360 +Const CfgYawFrames = 16 +Const CfgDistance# = 120 + +; Includes +Include "FreeImage.bb" +Include "FastExt.bb" +Include "../Advanced Text (Library)/AdvText.bb" +Include "Impostor.bb" + +; Set up 3D Scene +Graphics3D 1024, 1024, 32, 2:InitExt() +SetBuffer_ BackBuffer() + +; Set up Camera +Global CameraPivot = CreatePivot() +Global Camera = CreateCamera(CameraPivot) +MoveEntity Camera, 0, 0, -CfgDistance + +AmbientLight 255, 255, 255 + +; Set up Impostor data +Local ImpostorMesh% = LoadMesh(CfgMeshToRender) +Local ImpostorDiffuse% = LoadTexture(CfgDiffuseMap, CfgDiffuseFlags) +Local ImpostorNormal% = LoadTexture(CfgNormalMap, CfgNormalFlags) + +; Set up final image +Local DiffuseSheet% = CreateImage(CfgFrameSizeX, CfgFrameSizeY, CfgYawFrames * CfgPitchFrames) +Local NormalSheet% = CreateImage(CfgFrameSizeX, CfgFrameSizeY, CfgYawFrames * CfgPitchFrames) + +; Set up render target +;Const RTSize% = 2048 +Local RenderTarget% = CreateTexture(CfgFrameSizeX, CfgFrameSizeY, 1+256+FE_RENDER+FE_ZRENDER) +CameraViewport Camera, 0, 0, CfgFrameSizeX, CfgFrameSizeY + +; Render +SetBuffer TextureBuffer(RenderTarget) +Local YawStep# = (CfgYawMax - CfgYawMin) / CfgYawFrames +Local PitchStep# = (CfgPitchMax - CfgPitchMin) / CfgPitchFrames +Local Yaw, Pitch +For Yaw = 0 To CfgYawFrames - 1 + Local RealYaw# = CfgYawMin + (YawStep * Yaw) + For Pitch = 0 To CfgPitchFrames - 1 + Local RealPitch# = CfgPitchMin + (PitchStep * Pitch) + Local Frame = Pitch * CfgYawFrames + Yaw + + RotateEntity CameraPivot, RealPitch, RealYaw, 0, 1 + + ; Render Diffuse + Cls:EntityTexture ImpostorMesh, ImpostorDiffuse:RenderWorld:CopyRectStretch(0, 0, CfgFrameSizeX, CfgFrameSizeY, 0, 0, CfgFrameSizeX, CfgFrameSizeY, TextureBuffer(RenderTarget), ImageBuffer(DiffuseSheet, Frame)) + ; Render Normal + Cls:EntityTexture ImpostorMesh, ImpostorNormal:RenderWorld:CopyRectStretch(0, 0, CfgFrameSizeX, CfgFrameSizeY, 0, 0, CfgFrameSizeX, CfgFrameSizeY, TextureBuffer(RenderTarget), ImageBuffer(NormalSheet, Frame)) + Next +Next +SetBuffer BackBuffer() +FreeTexture RenderTarget + +Local Stream = WriteFile("Preview.imp") +WriteShort Stream, CfgFrameSizeX +WriteShort Stream, CfgFrameSizeY +WriteByte Stream, CfgPitchFrames +WriteFloat Stream, CfgPitchMin +WriteFloat Stream, CfgPitchMax +WriteByte Stream, CfgYawFrames +WriteFloat Stream, CfgYawMin +WriteFloat Stream, CfgYawMax +CloseFile(Stream) +Stream = WriteFile("PreviewNormal.imp") +WriteShort Stream, CfgFrameSizeX +WriteShort Stream, CfgFrameSizeY +WriteByte Stream, CfgPitchFrames +WriteFloat Stream, CfgPitchMin +WriteFloat Stream, CfgPitchMax +WriteByte Stream, CfgYawFrames +WriteFloat Stream, CfgYawMin +WriteFloat Stream, CfgYawMax +CloseFile(Stream) + + +Function SaveAnimImageSheet(Image%, File$, FramesX%, FramesY%) + Local x, y, img = CreateImage(ImageWidth(Image) * FramesX, ImageHeight(Image) * FramesY) + For x = 0 To FramesX - 1 + For y = 0 To FramesY - 1 + Local frame = y * FramesX + x + CopyRect 0, 0, ImageWidth(Image), ImageHeight(Image), x * ImageWidth(Image), y * ImageHeight(Image), ImageBuffer(Image, frame), ImageBuffer(img) + Next + Next + FiSaveImage(img, File) +End Function + +SaveAnimImageSheet(DiffuseSheet, "Preview.png", CfgYawFrames, CfgPitchFrames) +SaveAnimImageSheet(NormalSheet, "PreviewNormal.png", CfgYawFrames, CfgPitchFrames) + +Global ControlHelp1$ +ControlHelp1$ = ControlHelp1$ + "Controls:" + Chr(10) +ControlHelp1$ = ControlHelp1$ + Chr(9) + "1 - Mode: Draw Sheet" + Chr(10) +ControlHelp1$ = ControlHelp1$ + Chr(9) + "2 - Mode: Draw Frame" + Chr(10) +ControlHelp1$ = ControlHelp1$ + Chr(9) + "3 - Mode: 3D Preview" + Chr(10) +Global ControlHelp2$ +ControlHelp2$ = ControlHelp2$ + "Sheet Mode Controls:" + Chr(10) +ControlHelp2$ = ControlHelp2$ + Chr(9) + "Q - Sheet: Diffuse" + Chr(10) +ControlHelp2$ = ControlHelp2$ + Chr(9) + "W - Sheet: Normal" + Chr(10) +Global ControlHelp3$ +ControlHelp3$ = ControlHelp3$ + "Frame Mode Controls:" + Chr(10) +ControlHelp3$ = ControlHelp3$ + Chr(9) + "Q - Sheet: Diffuse" + Chr(10) +ControlHelp3$ = ControlHelp3$ + Chr(9) + "W - Sheet: Normal" + Chr(10) +ControlHelp3$ = ControlHelp3$ + Chr(9) + "A - Previous Frame" + Chr(10) +ControlHelp3$ = ControlHelp3$ + Chr(9) + "D - Next Frame" + Chr(10) +Global ControlHelp4$ +ControlHelp4$ = ControlHelp4$ + "3D Mode Controls:" + Chr(10) +ControlHelp4$ = ControlHelp4$ + Chr(9) + "Q - Sheet: Diffuse" + Chr(10) +ControlHelp4$ = ControlHelp4$ + Chr(9) + "W - Sheet: Normal" + Chr(10) +ControlHelp4$ = ControlHelp4$ + Chr(9) + "Mouse - Rotate Camera" + Chr(10) + +Local Timer = CreateTimer(30) + +Const DrawModeSheet% = 0 +Const DrawModeFrame% = 1 +Const DrawMode3D% = 2 +Local DrawMode% = DrawModeSheet + +Local ModeSheet_Image% = DiffuseSheet +Local ModeSheet_XOff% = 0 +Local ModeSheet_YOff% = 0 + +Local ModeFrame_Image% = DiffuseSheet +Local ModeFrame_Frame% = 0 + + +Local Mode3D_DiffImp.Impostor = Impostor_Load("Preview.imp") +Local Mode3D_NormImp.Impostor = Impostor_Load("PreviewNormal.imp") +Local Mode3D_Pitch# = 0 +Local Mode3D_Yaw# = 0 +Local Mode3D_Pivot = CreatePivot() +Local Mode3D_Camera = CreateCamera(Mode3D_Pivot) +MoveEntity Mode3D_Camera, 0, 0, -100 +EntityTexture ImpostorMesh, ImpostorDiffuse:HideEntity Mode3D_NormImp\Pivot + +CameraViewport Camera, 0, 256, 512, 512 +CameraViewport Mode3D_Camera, 512, 256, 512, 512 +MoveEntity Mode3D_DiffImp\Mesh, 1000, 0, 0 +MoveEntity Mode3D_NormImp\Mesh, 1000, 0, 0 +ScaleEntity Mode3D_DiffImp\Mesh, CfgDistance, CfgDistance, 1 +ScaleEntity Mode3D_NormImp\Mesh, CfgDistance, CfgDistance, 1 +MoveEntity Mode3D_Pivot, 1000, 0, 0 +CameraRange Camera, 0.1, 500 +CameraRange Mode3D_Camera, 0.1, 500 + +;Local tc = CreateCube(Mode3D_Pivot) +EntityTexture Mode3D_DiffImp\Mesh, Mode3D_DiffImp\Sheet, 0, 0 + +While Not KeyHit(1) + Cls + + ; 3D - Render + If DrawMode = DrawMode3D + Impostor_Update(Mode3D_Camera) + ;EntityTexture Mode3D_DiffImp\Mesh, Mode3D_DiffImp\Sheet, 0, 0 + WireFrame KeyDown(57) + RenderWorld + EndIf + + ; 2D - Rener + AdvText 0, 0, ControlHelp1, 0, 0, 1 + + ; Show Mode specific data. + Select DrawMode + Case DrawModeSheet + ; Control + If MouseDown(1) And MouseHit(1) Then + MoveMouse MouseX(), MouseY() + ElseIf MouseDown(1) + ModeSheet_XOff = ModeSheet_XOff + MouseXSpeed() + ModeSheet_YOff = ModeSheet_YOff + MouseYSpeed() + EndIf + + If KeyHit(16) Then ModeSheet_Image = DiffuseSheet + If KeyHit(17) Then ModeSheet_Image = NormalSheet + + ; Render + Local rw = ImageWidth(ModeSheet_Image) * CfgYawFrames + Local rh = ImageHeight(ModeSheet_Image) * CfgPitchFrames + For p = 0 To CfgPitchFrames - 1 + For y = 0 To CfgYawFrames - 1 + DrawImage ModeSheet_Image, GraphicsWidth() / 2 - rw / 2 + ModeSheet_XOff + ImageWidth(ModeSheet_Image) * y, GraphicsHeight() / 2 - rh / 2 + ModeSheet_YOff + ImageHeight(ModeSheet_Image) * p, y + p * CfgYawFrames + Next + Next + + ; Show Help + AdvText 0, 50, ControlHelp2, 0, 0, 1 + Case DrawModeFrame + ; Control + If KeyHit(16) Then ModeFrame_Image = DiffuseSheet + If KeyHit(17) Then ModeFrame_Image = NormalSheet + If KeyHit(30) Then ModeFrame_Frame = ModeFrame_Frame - 1 + If KeyHit(32) Then ModeFrame_Frame = ModeFrame_Frame + 1 + + If ModeFrame_Frame < 0 Then ModeFrame_Frame = CfgPitchFrames * CfgYawFrames - 1 + If ModeFrame_Frame = (CfgPitchFrames * CfgYawFrames) Then ModeFrame_Frame = 0 + + ; Render + DrawImage ModeFrame_Image, GraphicsWidth() / 2 - ImageWidth(ModeFrame_Image) / 2, GraphicsHeight() / 2 - ImageHeight(ModeFrame_Image) / 2, ModeFrame_Frame + + ; Show Help + AdvText 0, 50, ControlHelp3, 0, 0, 1 + Case DrawMode3D + ; Control + If KeyHit(16) Then + HideEntity Mode3D_NormImp\Pivot + ShowEntity Mode3D_DiffImp\Pivot + EntityTexture ImpostorMesh, ImpostorDiffuse + EndIf + If KeyHit(17) Then + ShowEntity Mode3D_NormImp\Pivot + HideEntity Mode3D_DiffImp\Pivot + EntityTexture ImpostorMesh, ImpostorNormal + EndIf + + If MouseDown(1) And MouseHit(1) + MoveMouse 512, 384 + ElseIf MouseDown(1) + Mode3D_Pitch = Math_MaxMin(Mode3D_Pitch + MouseYSpeed() / 15.0, 90, -90) + Mode3D_Yaw = Mode3D_Yaw + MouseXSpeed() / 15.0 + RotateEntity Mode3D_Pivot, Mode3D_Pitch, Mode3D_Yaw, 0, 1 + RotateEntity CameraPivot, Mode3D_Pitch, Mode3D_Yaw, 0, 1 + MoveMouse 512, 384 + EndIf + + If MouseDown(2) And MouseHit(2) + MoveMouse 512, 384 + ElseIf MouseDown(2) + MoveEntity Mode3D_Camera, 0, 0, (MouseXSpeed() - MouseYSpeed()) / 15.0 + MoveMouse 512, 384 + EndIf + + ; Show Help + AdvText 0, 50, ControlHelp4, 0, 0, 1 + End Select + + ; Switch Mode Hotkeys + If KeyHit(2) Then DrawMode = DrawModeSheet + If KeyHit(3) Then DrawMode = DrawModeFrame + If KeyHit(4) Then DrawMode = DrawMode3D + + Flip 0 + WaitTimer Timer +Wend + +Function Math_MaxMin#(Value#, Max#, Min#) + If Value> Max Then Return Max + If Value < Min Then Return Min + Return Value +End Function +Function Math_Max#(Value#, Max#) + If Value> Max Then Return Max + Return Value +End Function +Function Math_Min#(Value#, Min#) + If Value < Min Then Return Min + Return Value +End Function +Function Math_Clip#(Value#, Low#, High#) + Local Out#, Diff# + Diff = High-Low:Out = Value-Low + If (Out >= Diff) Then Out = Out - Floor(Out/Diff)*Diff + If (Out < 0) Then Out = Out - Floor(Out/Diff)*Diff + Return Low+Out +End Function +;~IDEal Editor Parameters: +;~C#Blitz3D \ No newline at end of file diff --git a/BlitzBasic/Blitz3D/Impostor/Cube.imp b/BlitzBasic/Blitz3D/Impostor/Cube.imp new file mode 100644 index 0000000000000000000000000000000000000000..b653ac973cc7b74321e98f84d408bef4a81abf43 GIT binary patch literal 22 acmZo*XkcJvVAyg9h@Au&7)%ZWu`>WWDg^KV literal 0 HcmV?d00001 diff --git a/BlitzBasic/Blitz3D/Impostor/Cube.png b/BlitzBasic/Blitz3D/Impostor/Cube.png new file mode 100644 index 0000000000000000000000000000000000000000..8916813234ac495d2df55c1b707582d5b9421541 GIT binary patch literal 96015 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 Then + RuntimeError "ERROR! FastExstension library - Incorrect versions for FastExt.dll (v"+ExtVersion()+") And FastExt.bb (v"+FE_VERSION+")" + Else + DebugLog "Init FastExtension library v"+FE_VERSION+"successful" + EndIf + If FE_InitExtFlag=0 Then + FE_InitExtFlag = 1 + FE_PivotSys = CreatePivot() + DeInitPostprocess() + InitExt_ ( SystemProperty("Direct3DDevice7"), BackBuffer(), GfxDriverCapsEx ) + EndIf +End Function + + + +; ôóíêöèÿ äëÿ ðåíäåðèíãà îäíîãî åíòèòè (âñå åãî ÷èëäû òîæå áóäóò îòðåíäåðåíû, åñëè íå ñêðûòû) +; Function for render single entity or entity with childrens +Function RenderEntity% (entity%, camera%, clearViewport%=0, tween#=1.0) + Return RenderEntity_ (entity, camera, tween, clearViewport, FE_PivotSys) +End Function + + + +; ôóíêöèÿ äëÿ ðåíäåðèíãà ãðóïïû åíòèòåé (âñå åãî ÷èëäû òîæå áóäóò îòðåíäåðåíû, åñëè íå ñêðûòû) +; Function for render group of entities (with childrens, if not hidden) +Function RenderGroup% (group%, camera%, clearViewport%=0, tween#=1.0) + Return RenderGroup_ (group, camera, tween, clearViewport, FE_PivotSys) +End Function + + + +Function TextureAnisotropy% (level%=0, index%=-1) + Return TextureAnisotropy_ (level, index) +End Function + + + +Function TextureLodBias% (bias#=-0.2, index%=-1) + Return TextureLodBias_ (bias, index) +End Function + + + +; Äîïîëüíèòåëüíûå ôóíêöèè äëÿ ÊëèïÏëåéíîâ +; Additional functions for ClipPlanes + +Function CreateClipplane% (entity%=0, x1#=0, y1#=0, z1#=0, x2#=0, y2#=0, z2#=1, x3#=1, y3#=0, z3#=0) + If entity<>0 Then + TFormPoint 0, 0, 0,entity,0 : x1 = TFormedX() : y1 = TFormedY() : z1 = TFormedZ() + TFormPoint 0, 0, 1,entity,0 : x2 = TFormedX() : y2 = TFormedY() : z2 = TFormedZ() + TFormPoint 1, 0, 0,entity,0 : x3 = TFormedX() : y3 = TFormedY() : z3 = TFormedZ() + EndIf + Return CreateClipplane_ ( x1, y1, z1, x2, y2, z2, x3, y3, z3 ) +End Function + +Function AlignClipplane% (plane%, entity%=0, x1#=0, y1#=0, z1#=0, x2#=0, y2#=0, z2#=1, x3#=1, y3#=0, z3#=0) + If entity<>0 Then + TFormPoint 0, 0, 0,entity,0 : x1 = TFormedX() : y1 = TFormedY() : z1 = TFormedZ() + TFormPoint 0, 0, 1,entity,0 : x2 = TFormedX() : y2 = TFormedY() : z2 = TFormedZ() + TFormPoint 1, 0, 0,entity,0 : x3 = TFormedX() : y3 = TFormedY() : z3 = TFormedZ() + EndIf + Return AlignClipplane_ ( plane, x1, y1, z1, x2, y2, z2, x3, y3, z3 ) +End Function + + + + +; Äîïîëüíèòåëüíûå ôóíêöèè äëÿ Êàìåðû +; Additional functions for Camera + +Global MirrorCameraLast% = 0 +Global MirrorCameraX# = 0 +Global MirrorCameraY# = 0 +Global MirrorCameraZ# = 0 +Global MirrorCameraAX# = 0 +Global MirrorCameraAY# = 0 +Global MirrorCameraAZ# = 0 +Global MirrorCameraParent% = 0 + +Function MirrorCamera% (camera%=0, entity%=0) + If camera<>0 Then + MirrorCameraLast = camera + MirrorCameraX# = EntityX(camera,1) + MirrorCameraY# = EntityY(camera,1) + MirrorCameraZ# = EntityZ(camera,1) + MirrorCameraAX# = EntityPitch(camera,1) + MirrorCameraAY# = EntityYaw(camera,1) + MirrorCameraAZ# = EntityRoll(camera,1) + If entity<>0 Then + MirrorCameraParent = ParentEntity(camera) + EntityParent camera, entity, 1 + PositionEntity camera, EntityX(camera), -EntityY(camera), EntityZ(camera) + RotateEntity camera, -EntityPitch(camera), EntityYaw(camera), -EntityRoll(camera) + EntityParent camera,0,1 + Else + PositionEntity camera, MirrorCameraX, -MirrorCameraY, MirrorCameraZ, 1 + RotateEntity camera, -MirrorCameraAX, MirrorCameraAY, -MirrorCameraAZ, 1 + EndIf + EndIf +End Function + +Function RestoreCamera% (camera%=0) + If camera=0 Then camera=MirrorCameraLast + If camera<>0 Then + PositionEntity camera, MirrorCameraX, MirrorCameraY, MirrorCameraZ, 1 + RotateEntity camera, MirrorCameraAX, MirrorCameraAY, MirrorCameraAZ, 1 + If MirrorCameraParent<>0 Then EntityParent camera, MirrorCameraParent, 1 + EndIf +End Function + + + + +; ñòàðûå ôóíêöèè òåïåðü ñ íîâûìè âîçìîæíîñòÿìè +; Old functions with NEW capabilities + +Function SetBuffer% (buffer%) + Return SetBuffer_ (buffer) +End Function + +Function GetBuffer% () + Return SetBuffer_ (-1) +End Function + +Function ClsColor% (red%, green%, blue%, alpha%=$FF, zValue#=1.0) + Return ClsColor_ (red, green, blue, alpha, zValue) +End Function + +Function Cls% (clearColor%=1, clearZBuffer%=1) + Return Cls_ (clearColor, clearZBuffer) +End Function + +Function WireFrame% (enable%=0) + Return Wireframe_ (enable) +End Function + +Function Bump% (enable%=-1) + Return Bump_ (enable) +End Function + +Function FreeTexture% (texture%) + If texture<>0 Then + Return FreeTexture_ (texture, TextureBuffer(texture)) + Else + Return 0 + EndIf +End Function + +Function ColorFilter% (red%=1, green%=1, blue%=1, alpha%=1) + Return ColorFilter_ (red, green, blue, alpha) +End Function + + + + +Function TextureBlend% (texture%, blend%) + TextureBlend_ texture, blend +End Function + + + +; íîâûå ôóíêöèÿ äëÿ çàäàíèÿ ÑÂÎÈÕ òåêñòóðíûõ ñìåøèâàíèé (èñïîëüçóéòå òîëüêî D3DTOP_* êîíñòàíòû, ñì. èõ íèæå) +; New function for custom texture blending (use D3DTOP_* constans only, see below) + +Function TextureBlendCustom% (texture%, color_operation%, alpha_operation%=0, projection_flag%=0) + If color_operation>24 Then color_operation=24 + If color_operation<1 Then color_operation=1 + If alpha_operation>24 Then alpha_operation=24 + If alpha_operation<0 Then alpha_operation=0 + projection_flag = projection_flag And $7 + TextureBlend texture, (projection_flag Shl 16) Or (color_operation Shl 8) Or alpha_operation +End Function + + + +; íîâûå ôóíêöèè äëÿ ñîçäàíèÿ ÑÂÎÈÕ ñìåøèâàíèé ïðè ðåíäåðå îáúåêòîâ (èñïîëüçóéòå òîëüêî D3DBLEND_* êîíñòàíòû, ñì. èõ íèæå) +; New functions for custom entity (brush) blending (use D3DBLEND_* constans only, see below) + +Function EntityBlendCustom% (entity%, source_blend%=1, destination_blend%=1, alphablending_enable%=0) + If source_blend>13 Then source_blend=13 + If source_blend<1 Then source_blend=1 + If destination_blend>13 Then destination_blend=13 + If destination_blend<1 Then destination_blend=1 + If alphablending_enable<>0 Then alphablending_enable=1 + EntityBlend entity, (alphablending_enable Shl 16) Or (source_blend Shl 8) Or destination_blend +End Function + +Function BrushBlendCustom% (brush%, source_blend%=1, destination_blend%=1, alphablending_enable%=0) + If source_blend>13 Then source_blend=13 + If source_blend<1 Then source_blend=1 + If destination_blend>13 Then destination_blend=13 + If destination_blend<1 Then destination_blend=1 + If alphablending_enable<>0 Then alphablending_enable=1 + BrushBlend brush, (alphablending_enable Shl 16) Or (source_blend Shl 8) Or destination_blend +End Function + + + + + +Function ExecAndExit% (file$="", command$="", workingDir$="") + ExecAndExit_ file, command, workingDir +End Function + + + + +Function InitPostprocess% () + Local CurrentBuffer%, smallWidth%, smallHeight% + If FE_InitPostprocessFlag=0 + smallWidth = GraphicsWidth()/3 : smallHeight = GraphicsHeight()/3 + FE_PostprocessTexture1 = CreateTexture ( GraphicsWidth(), GraphicsHeight(), 1 + 256 + FE_ExSIZE + FE_RENDER + FE_ZRENDER ) + FE_PostprocessTexture2 = CreateTexture ( smallWidth, smallHeight, 1 + 256 + FE_ExSIZE + FE_RENDER ) + FE_PostprocessTexture3 = CreateTexture ( 16, 16, 1 ) + FE_PostprocessTexture4 = CreateTexture ( smallWidth, smallHeight, 1 + 256 + FE_ExSIZE + FE_RENDER ) + FE_PostprocessTexture5 = CreateTexture ( GraphicsWidth(), GraphicsHeight(), 1 + 256 + FE_ExSIZE ) ; comment this string if MotionBlur not needed (not used) + + CurrentBuffer = SetBuffer (TextureBuffer(FE_PostprocessTexture3)) + ClsColor 255,255,255 : Cls : SetBuffer BackBuffer() + If InitPostprocess_ (BackBuffer(), TextureBuffer(FE_PostprocessTexture1), TextureBuffer(FE_PostprocessTexture2), TextureBuffer(FE_PostprocessTexture3), TextureBuffer(FE_PostprocessTexture4), TextureBuffer(FE_PostprocessTexture5))<>0 Then + FE_InitPostprocessFlag = 1 + Else + If FE_PostprocessTexture1<>0 Then FreeTexture FE_PostprocessTexture1 + If FE_PostprocessTexture2<>0 Then FreeTexture FE_PostprocessTexture2 + If FE_PostprocessTexture3<>0 Then FreeTexture FE_PostprocessTexture3 + If FE_PostprocessTexture4<>0 Then FreeTexture FE_PostprocessTexture4 + If FE_PostprocessTexture5<>0 Then FreeTexture FE_PostprocessTexture5 + EndIf + SetBuffer CurrentBuffer + EndIf + Return FE_InitPostprocessFlag +End Function + +Function DeInitPostprocess% () + If FE_InitPostprocessFlag<>0 Then + If FE_PostprocessTexture1<>0 Then FreeTexture FE_PostprocessTexture1 + If FE_PostprocessTexture2<>0 Then FreeTexture FE_PostprocessTexture2 + If FE_PostprocessTexture3<>0 Then FreeTexture FE_PostprocessTexture3 + If FE_PostprocessTexture4<>0 Then FreeTexture FE_PostprocessTexture4 + If FE_PostprocessTexture5<>0 Then FreeTexture FE_PostprocessTexture5 + FE_InitPostprocessFlag = 0 + EndIf +End Function + +Function RenderPostprocess% (flags%=0, x%=0, y%=0, width%=0, height%=0) + If InitPostprocess()<>0 Then RenderPostprocess_ flags, x, y, width, height +End Function + +Function CustomPostprocessDOF% (near#=10.0, far#=100.0, direction%=1, level%=3, blurRadius#=0.35, quality%=1) + CustomPostprocessDOF_ near, far, direction, level, blurRadius, quality +End Function + +Function CustomPostprocessGlow% (alpha#=1.0, darkPasses%=2, blurPasses%=4, blurRadius#=0.35, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0) + CustomPostprocessGlow_ alpha, darkPasses, blurPasses, blurRadius, quality, red, green, blue, alphaTexture +End Function + +Function CustomPostprocessBlur% (alpha#=1.0, blurPasses%=4, blurRadius#=0.35, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0) + CustomPostprocessBlur_ alpha, blurPasses, blurRadius, quality, red, green, blue, alphaTexture +End Function + +Function CustomPostprocessInverse% (alpha#=1.0, red%=255, green%=255, blue%=255, alphaTexture%=0) + CustomPostprocessInverse_ alpha, red, green, blue, alphaTexture +End Function + +Function CustomPostprocessGrayscale% (alpha#=1.0, brightness#=1.0, inverse%=0, alphaTexture%=0) + CustomPostprocessGrayscale_ alpha, brightness, inverse, alphaTexture +End Function + +Function CustomPostprocessContrast% (alpha#=1.0, method%=0, red%=255, green%=255, blue%=255, alphaTexture%=0) + CustomPostprocessContrast_ alpha#, method, red, green, blue, alphaTexture +End Function + +Function CustomPostprocessBlurDirectional% (angle#=0, alpha#=1, blurPasses%=4, blurRadius#=0.35, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0) + CustomPostprocessBlurDirectional_ angle, alpha, blurPasses, blurRadius, quality, red, green, blue, alphaTexture +End Function + +Function CustomPostprocessBlurZoom% (x#=0.5, y#=0.5, zoomFactor#=105, alpha#=1, blurPasses%=4, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0) + CustomPostprocessBlurZoom_ x, y, zoomFactor, alpha, blurPasses, quality, red, green, blue, alphaTexture +End Function + +Function CustomPostprocessBlurSpin% (x#=0.5, y#=0.5, spinAngle#=4, alpha#=1, blurPasses%=4, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0) + CustomPostprocessBlurSpin_ x, y, spinAngle, alpha, blurPasses, quality, red, green, blue, alphaTexture +End Function + +Function CustomPostprocessBlurMotion% (alpha#=0.9, originX#=0, originY#=0, handleX#=0.5, handleY#=0.5, scaleX#=100, scaleY#=100, angle#=0, blend%=0, red%=255, green%=255, blue%=255, alphaTexture%=0) + CustomPostprocessBlurMotion_ alpha, originX, originY, handleX, handleY, scaleX, scaleY, angle, blend, red, green, blue, alphaTexture +End Function + +Function CustomPostprocessOverlay% (alpha#=0.5, blend%=0, red%=255, green%=255, blue%=255, alphaTexture%=0) + CustomPostprocessOverlay_ alpha, blend, red, green, blue, alphaTexture +End Function + +Function CustomPostprocessRays% (centerX#=0.5, centerY#=0.5, zoomFactor#=105, alpha#=1, darkPasses%=2, blurPasses%=4, quality%=1, red%=255, green%=255, blue%=255, alphaTexture%=0) + CustomPostprocessRays_% (centerX, centerY, zoomFactor, alpha, darkPasses, blurPasses, quality, red, green, blue, alphaTexture) +End Function + + +Function DeInitExt% () + If FE_InitExtFlag<>0 Then + FE_InitExtFlag = 0 + SetBuffer BackBuffer() + FreeEntity FE_PivotSys + DeInitPostprocess + DeInitExt_ + EndIf +End Function \ No newline at end of file diff --git a/BlitzBasic/Blitz3D/Impostor/FreeImage.bb b/BlitzBasic/Blitz3D/Impostor/FreeImage.bb new file mode 100644 index 0000000..09f912e --- /dev/null +++ b/BlitzBasic/Blitz3D/Impostor/FreeImage.bb @@ -0,0 +1,1297 @@ +;FreeImage Module for B3D/B+ +;Author: markcw, edited 29 Nov 08 +;Site: freeimage.sourceforge.net/ + +;Load and save image functions + +Function FiLoadImage(filename$) + ;Loads an image from filename$ + ;Returns an image or False if fails + ;Uses FiLoad and FiRead + + Local dib, image + dib = FiLoad(filename$) + image = FiRead(dib) + FreeImage_Unload(dib) + Return image + +End Function + +Function FiSaveImage(image, filename$) + ;Saves an image as filename$ + ;Returns True if succeeds or False if fails + ;Uses FiWrite and FiSave + + Local dib, bool + dib = FiWrite(image) + bool = FiSave(dib, filename$) + FreeImage_Unload(dib) + Return bool + +End Function + +Function FiLoad(filename$) + ;Loads a FreeImage bitmap from filename$ + ;Returns a FreeImage bitmap or False if fails + + Local fif, dib + fif = FreeImage_GetFIFFromFilename(filename$) ;Format from extension + If fif >= 0 ;Format is valid + dib = FreeImage_Load(fif, filename$, 0) + EndIf + Return dib + +End Function + +Function FiRead(dib) + ;Reads a FreeImage bitmap and writes an image + ;Returns an image or False if fails + + Local dib24, pixel, width, height, image, buffer, ix, iy + + dib24 = FreeImage_ConvertTo24Bits(dib) ;Copy to 24 bit, no palette + If dib24 = 0 Then Return 0 ;Unknown format + pixel = CreateBank(4) ;Temp bank + width = FreeImage_GetWidth(dib) + height = FreeImage_GetHeight(dib) + image = CreateImage(width, height) + buffer = GraphicsBuffer() + + LockBuffer(ImageBuffer(image)) + For iy = 0 To height - 1 + For ix = 0 To width - 1 + FreeImage_GetPixelColor(dib24, ix, height - 1 - iy, pixel) ;Invert + WritePixelFast ix, iy, PeekInt(pixel, 0), ImageBuffer(image) + Next + Next + UnlockBuffer(ImageBuffer(image)) + + SetBuffer buffer + FreeImage_Unload(dib24) + FreeBank pixel + Return image + +End Function + +Function FiSave(dib, filename$) + ;Saves a FreeImage bitmap as filename$ + ;Returns True if succeeds or False if fails + + Local fif, bpp, dib8, dib24, bool + + If dib = 0 Then Return 0 ;No image + fif = FreeImage_GetFIFFromFilename(filename$) ;Format from extension + bpp = FreeImage_GetBPP(dib) ;bpp will be one of 1/4/8/16/24/32 + dib8 = dib ;8 bit or other, variable passed to FreeImage_Save + dib24 = dib ;24 bit + + If fif >= 0 ;Format is valid + If fif = 11 ;Check pgm format, pgm=11/pgmraw=12 + dib8 = FreeImage_ConvertToGreyscale(dib) ;8 bit greyscale + ElseIf fif = 25 ;Gif format, gif=25 + If bpp <> 24 ;Dib not 24 bits + dib24 = FreeImage_ConvertTo24Bits(dib) + EndIf + dib8 = FreeImage_ColorQuantize(dib24, 0) ;8 bit paletted + If dib24 <> dib ;24 bit conversion was required + FreeImage_Unload(dib24) + EndIf + EndIf + bool = FreeImage_Save(fif, dib8, filename$, 0) + If dib8 <> dib ;8 bit conversion was required + FreeImage_Unload(dib8) + EndIf + EndIf + + Return bool + +End Function + +Function FiWrite(image) + ;Reads an image and writes a FreeImage bitmap + ;Returns a FreeImage bitmap or False if fails + + Local pixel, width, height, dib, buffer, ix, iy + + If image = 0 Then Return 0 ;No image + pixel = CreateBank(4) ;Temp bank + width = ImageWidth(image) + height = ImageHeight(image) + dib = FreeImage_Allocate(width, height, 24, $ff0000, $00ff00, $0000ff) + buffer = GraphicsBuffer() + + LockBuffer(ImageBuffer(image)) + For iy = 0 To height - 1 + For ix = 0 To width - 1 + PokeInt pixel, 0, ReadPixelFast(ix, iy, ImageBuffer(image)) + FreeImage_SetPixelColor(dib, ix, height - 1 - iy, pixel) ;Invert + Next + Next + UnlockBuffer(ImageBuffer(image)) + + SetBuffer buffer + FreeBank pixel + Return dib + +End Function + +Function FiUnload(dib) + ;Frees a FreeImage bitmap, a wrapper function + ;Returns nothing + + FreeImage_Unload(dib) + +End Function + +;Load and save anim image functions + +Function FiLoadAnimImage(filename$, index = 0, frames = 0) + ;Loads an anim image from a FreeImage multipage bitmap + ;index -> first frame, 0=first, frames -> number of frames, 0=all + ;Returns an image or False if fails + ;Uses FiOpenAnim + + Local dib, count, pixel, page, width, height + Local image, graphic, buffer, dib24, ix, iy, dst + + dib = FiOpenAnim(filename$, 1) ;Load read-only + If dib = 0 Then Return 0 ;No dib + count = FreeImage_GetPageCount(dib) ;Number of frames + If index < 0 Or index > count - 1 Then index = count - 1 + If frames < 1 Or frames > count Then frames = count + If frames + index > count Then frames = count - index + + pixel = CreateBank(4) + page = FreeImage_LockPage(dib, 0) ;Lock first page + width = FreeImage_GetWidth(page) ;Get the width/height + height = FreeImage_GetHeight(page) + FreeImage_UnlockPage(dib, page, 0) ;Unlock + image = CreateImage(width, height, frames) + graphic = CreateImage(width, height) + buffer = GraphicsBuffer() + + For count = 0 To index + frames - 1 + page = FreeImage_LockPage(dib, count) ;Lock next page + dib24 = FreeImage_ConvertTo24Bits(page) ;Copy to 24 bits, no palette + FreeImage_UnlockPage(dib, page, 0) ;Unlock + + LockBuffer(ImageBuffer(graphic)) + For iy = 0 To height - 1 + For ix = 0 To width - 1 + FreeImage_GetPixelColor(dib24, ix, height - 1 - iy, pixel) ;Invert + WritePixelFast ix, iy, PeekInt(pixel, 0), ImageBuffer(graphic) + Next + Next + UnlockBuffer(ImageBuffer(graphic)) + + If count - index >= 0 ;Frame is valid + dst = ImageBuffer(image, count - index) ;Copy graphic to frame + CopyRect 0, 0, width, height, 0, 0, ImageBuffer(graphic), dst + EndIf + FreeImage_Unload(dib24) ;Free dib + Next + + SetBuffer buffer + FreeImage graphic + FreeBank pixel + FreeImage_CloseMultiBitmap(dib, 0) + Return image + +End Function + +Function FiSaveAnimImage(image, filename$, frames, index = 0) + ;Saves an anim image as filename$ + ;frames -> number of frames, index -> first frame, 0=first + ;Returns True if succeeds or False if fails + ;Uses FiOpenAnim + + Local dib, fif, pixel, width, height, dib24 + Local buffer, count, ix, iy, page + + If image = 0 Then Return 0 ;No image + dib = FiOpenAnim(filename$, 2, 0) ;2=create new + fif = FreeImage_GetFIFFromFilename(filename$) ;format from extension + frames = frames + index + If frames < 1 Then frames = 1 ;Limit + If index < 0 Or index > frames - 1 Then index = frames - 1 + + pixel = CreateBank(4) ;Temp bank + width = ImageWidth(image) + height = ImageHeight(image) + dib24 = FreeImage_Allocate(width, height, 24, $ff0000, $00ff00, $0000ff) + buffer = GraphicsBuffer() + + For count = index To frames - 1 + LockBuffer(ImageBuffer(image, count)) + For iy = 0 To height - 1 + For ix = 0 To width - 1 + PokeInt pixel, 0, ReadPixelFast(ix, iy, ImageBuffer(image, count)) + FreeImage_SetPixelColor(dib24, ix, height - 1 - iy, pixel) ;Invert + Next + Next + UnlockBuffer(ImageBuffer(image, count)) + + If fif = 25 ;Gif format + page = FreeImage_ColorQuantize(dib24, 0) ;8 bit palette + Else ;Other format, ico=1/tif=18 + page = FreeImage_ConvertTo24Bits(dib24) ;24 bits + EndIf + FreeImage_AppendPage(dib, page) ;Add next page + FreeImage_Unload(page) + Next + + SetBuffer buffer + FreeBank pixel + FreeImage_Unload(dib24) + FreeImage_CloseMultiBitmap(dib, 0) + Return 1 + +End Function + +Function FiAnimFrames(filename$, index = 0, frames = 0) + ;Returns the number of frames in a FreeImage multipage bitmap + ;index -> first frame, 0=first, frames -> number of frames, 0=all + ;Uses FiOpenAnim + + Local dib, count + dib = FiOpenAnim(filename$, 1) ;Load as read-only + count = FreeImage_GetPageCount(dib) + If index < 0 Or index > count - 1 Then index = count - 1 + If frames < 1 Or frames > count Then frames = count + If frames + index > count Then frames = count - index + FreeImage_CloseMultiBitmap(dib, 0) + Return frames + +End Function + +Function FiOpenAnim(filename$, opentype = 0, flags = 0) + ;Opens a FreeImage multipage bitmap from filename$ + ;opentype -> 0=open read/write, 1=open read-only, 2=create new + ;Returns a FreeImage multipage bitmap or False if fails + + Local fif, dib, isnew, isread + If opentype = 1 Then isread = 1 + If opentype = 2 Then isnew = 1 + fif = FreeImage_GetFIFFromFilename(filename$) ;Format from extension + If fif >= 0 ;Format is valid + dib = FreeImage_OpenMultiBitmap(fif, filename$, isnew, isread, 0, flags) + EndIf + Return dib + +End Function + +Function FiCloseAnim(dib, flags = 0) + ;Closes a FreeImage multipage bitmap, a wrapper function + ;Returns nothing + + FreeImage_CloseMultiBitmap(dib, flags) + +End Function + +;Image manipulation functions + +Function FiRescale(dib, scale, filter = 0) + ;Rescales a FreeImage bitmap + ;scale -> scale as percentage, filter -> scale algorithm 0..5 + ;Returns a rescaled FreeImage bitmap or False if fails + + Local width, height + width = (scale * FreeImage_GetWidth(dib)) / 100 + height = (scale * FreeImage_GetHeight(dib)) / 100 + Return FreeImage_Rescale(dib, width, height, filter) + +End Function + +Function FiRotateClassic(dib, angle#) + ;Rotates a FreeImage bitmap by a degree, 0..360 + ;Returns a rotated FreeImage bitmap + + Local dlo, dhi + angle# = -angle# ;Invert angle + dlo = FiFloatToDouble(angle#, 0) + dhi = FiFloatToDouble(angle#, 1) + Return FreeImage_RotateClassic(dib, dlo, dhi) + +End Function + +Function FiRotateClassicEx(dib, angle#, bgcolor = 0) + ;Rotates a FreeImage bitmap by a degree, 0..360 + ;bgcolor -> RGB background color + ;Returns a rotated FreeImage bitmap + ;From FreeImage source by Hervé Drolon + ;NB: sub-functions need 16/24/32 bits per pixel + + Local bpp, hsrc, hdst + bpp = FreeImage_GetBPP(dib) + hsrc = dib ;Init source + If bpp < 16 ;Image is 1/4/8 bits per pixel + hsrc = FreeImage_ConvertTo24Bits(dib) ;Copy to 24 bits + EndIf + hdst = FiRotateAny(hsrc, angle#, bgcolor) + If hsrc <> dib ;Conversion required + FreeImage_Unload(hsrc) ;Free from memory + EndIf + Return hdst + +End Function + +Function FiAdjustGamma(dib, gamma#) + ;Adjust gamma correction on a 8/24/32-bit FreeImage bitmap, 0.1..10.0 + ;A value of 1.0 leaves the image alone + ;less than one darkens it, and greater than one lightens it + ;Returns True if succeeds or False if fails + + Local dlo, dhi + dlo = FiFloatToDouble(gamma#, 0) + dhi = FiFloatToDouble(gamma#, 1) + Return FreeImage_AdjustGamma(dib, dlo, dhi) + +End Function + +Function FiAdjustBrightness(dib, brightness#) + ;Adjusts the brightness of a 8/24/32-bit FreeImage bitmap, -100..100 + ;A value 0 means no change, less than 0 will make the image darker + ;and greater than 0 will make the image brighter + ;Note: FreeImage_AdjustBrightness is actually an intensity algorithm + ;Adapted from FreeImage source by Hervé Drolon + + Local plut, i, value#, bool + plut = CreateBank(256) ;Lookup table + If brightness# > 100 Then brightness# = 100 ;-100..100 + If brightness# < -100 Then brightness# = -100 + For i = 0 To 255 ;Build the lut + value# = i + (255 * brightness# / 100) ;Calc brightness + If value# > 255 Then value# = 255 ;value 0..255 + If value# < 0 Then value# = 0 + PokeByte plut, i, Floor(value# + 0.5) + Next + bool = FreeImage_AdjustCurve(dib, plut, 0) ;Apply lut + FreeBank plut ;Free from memory + Return bool + +End Function + +Function FiAdjustIntensity(dib, intensity#) + ;Adjusts the intensity of a 8/24/32-bit FreeImage bitmap, -100..100 + ;A value 0 means no change, less than 0 will decrease the contrast + ;and greater than 0 will increase the contrast + ;Note: FreeImage_AdjustBrightness is actually an intensity algorithm + ;From FreeImage source by Hervé Drolon + + Local plut, i, value#, bool + plut = CreateBank(256) ;Lookup table + If intensity# > 100 Then intensity# = 100 ;-100..100 + If intensity# < -100 Then intensity# = -100 + For i = 0 To 255 ;Build the lut + value# = i * (100 + intensity#) / 100 ;Calc intensity + If value# > 255 Then value# = 255 ;value 0..255 + If value# < 0 Then value# = 0 + PokeByte plut, i, Floor(value# + 0.5) + Next + bool = FreeImage_AdjustCurve(dib, plut, 0) ;Apply lut + FreeBank plut ;Free from memory + Return bool + +End Function + +Function FiAdjustContrast(dib, contrast#) + ;Adjusts the contrast of a 8/24/32-bit FreeImage bitmap, -100..100 + ;A value 0 means no change, less than 0 will decrease the contrast + ;and greater than 0 will increase the contrast + ;Returns True if succeeds or False if fails + + Local dlo, dhi + dlo = FiFloatToDouble(contrast#, 0) + + dhi = FiFloatToDouble(contrast#, 1) + Return FreeImage_AdjustContrast(dib, dlo, dhi) + +End Function + +;Information functions + +Function FiGetWidth(dib) + ;Returns the width of a FreeImage bitmap, a wrapper function + + Return FreeImage_GetWidth(dib) ;Get bitmap info + +End Function + +Function FiGetHeight(dib) + ;Returns the height of a FreeImage bitmap, a wrapper function + + Return FreeImage_GetHeight(dib) + +End Function + +Function FiGetBPP(dib) + ;Returns the bits per pixel of a FreeImage bitmap, a wrapper function + + Return FreeImage_GetBPP(dib) + +End Function + +;Clipboard functions + +Function FiCopyToClipboard(dib) + ;Copies a FreeImage bitmap to the clipboard + ;Returns True is succeeds or False if fails + ;Uses User32.dll And Kernel32.dll + ;From: Copying a DIB to the clipboard, by John Simmons + ;Site: www.codeproject.com + + Local phdr, ppal, pbits, sdib, sbits, bank, shdr, spal, hmem + + phdr = FreeImage_GetInfoHeader(dib) ;Pointer to info header + ppal = FreeImage_GetPalette(dib) ;Pointer to palette + pbits = FreeImage_GetBits(dib) ;Pointer to bits + + ;Calc bits, DWORD-aligned scanline (Pitch) * Height + sbits = FreeImage_GetPitch(dib) * FreeImage_GetHeight(dib) + sdib = FreeImage_GetDIBSize(dib) ;total size + bank = CreateBank(sdib) ;Bank to store dib + FiApiMemoryToBank(bank, phdr, 40) ;Move info header to bank + shdr = PeekInt(bank, 0) ;biSize + + ;Calc palette, FreeImage bitmaps use the BITMAPINFO struct + spal = PeekInt(bank, 32) ;biClrUsed + If Not spal + If PeekShort(bank, 14) <> 24 ;No color table for 24-bit + spal = 1 Shl PeekShort(bank, 14) ;biBitCount, colors=2/16/256 + EndIf + EndIf + spal = spal * 4 ;sizeof(RGBQUAD) + + ;Move bits, palette and header separately for proper alignment + FiApiMemoryToBank(bank, pbits, sbits) ;Move bits to bank + CopyBank bank, 0, bank, shdr + spal, sbits ;Move bits up + FiApiMemoryToBank(bank, ppal, spal) ;Move palette to bank + CopyBank bank, 0, bank, shdr, spal ;Move palette up + FiApiMemoryToBank(bank, phdr, shdr) ;Move info header to bank + + + ;Alloc memory block to store our dib + hmem = FiApiGlobalAlloc(66, sdib) ;GHND=66, MOVEABLE=2|ZEROINIT=64 + If Not hmem ;Major bummer if we couldn't get memory block + FreeBank bank + Return False ;Fail + EndIf + + phdr = FiApiGlobalLock(hmem) ;Lock memory and get pointer to it + FiApiBankToMemory(phdr, bank, sdib) ;Move dib to memory + FiApiGlobalUnlock(hmem) ;Unlock the dib + + ;Send the dib to the clipboard + If FiApiOpenClipboard(0) ;hwnd + FiApiEmptyClipboard() ;Free last data + FiApiSetClipboardData(8, hmem) ;CF_DIB=8, hdata[bitmap] + FiApiCloseClipboard() + EndIf + + FreeBank bank + Return True ;Success + +End Function + +Function FiPasteFromClipboard() + ;Pastes the clipboard to a new FreeImage bitmap + ;Returns a FreeImage bitmap or dummy bitmap if fails + ;Uses User32.dll And Kernel32.dll + ;From: Copying a DIB to the clipboard, by John Simmons + ;Site: www.codeproject.com + + Local hmem, dib, phdr, bank, shdr, spal, bw, bh + Local bpp, sbits, sdib, ppal, pbits + + ;Receive the bitmap from the clipboard as a dib + If FiApiOpenClipboard(0) ;hwnd + hmem = FiApiGetClipboardData(8) ;CF_DIB=8 + FiApiCloseClipboard() + EndIf + If Not hmem ;If we didn't get a dib, return a dummy bitmap + dib = FreeImage_Allocate(1, 1, 24, $ff0000, $00ff00, $0000ff) + Return dib ;Fail + EndIf + + phdr = FiApiGlobalLock(hmem) ;Lock memory and get pointer to it + bank = CreateBank(40) ;Init bank, we will resize it later + FiApiMemoryToBank(bank, phdr, 40) ;Move info header to bank + shdr = PeekInt(bank, 0) ;biSize + + ;Calc palette, Clipboard dibs use the BITMAPINFO struct + spal = PeekInt(bank, 32) ;biClrUsed + If Not spal + If PeekShort(bank, 14) <> 24 ;No color table for 24-bit + spal=1 Shl PeekShort(bank, 14) ;biBitCount, colors=2/16/256 + EndIf + EndIf + spal = spal * 4 ;sizeof(RGBQUAD) + bw = PeekInt(bank, 4) ;biWidth + bh = PeekInt(bank, 8) ;biHeight + bpp = PeekShort(bank, 14) ;biBitCount + + ;Calc bits, DWORD-aligned scanline (Width * BitCount) * Height + sbits = ((bw * bpp + 31) / 32 * 4) * bh + sdib = shdr + spal + sbits ;Total size + ResizeBank bank, sdib ;Resize bank to store dib + FiApiMemoryToBank(bank, phdr, sdib) ;Move dib to bank + FiApiGlobalUnlock(hmem) ;Unlock the dib + + ;Alloc FreeImage bitmap, this has its own info header + dib = FreeImage_Allocate(bw, bh, bpp, $ff0000, $00ff00, $0000ff) + ppal = FreeImage_GetPalette(dib) ;Pointer to palette + pbits = FreeImage_GetBits(dib) ;Pointer to bits + + ;Move palette and bits (not header) separately for proper alignment + CopyBank bank, shdr, bank, 0, spal ;Move palette down + FiApiBankToMemory(ppal, bank, spal) ;Move palette to memory + CopyBank bank, shdr + spal, bank, 0, sbits ;Move bits down + FiApiBankToMemory(pbits, bank, sbits) ;Move bits to memory + + FreeBank bank + Return dib ;Success + +End Function + +;Bank functions + +Function FiBankFromFile(filename$, size = 0, pos = 0) + ;Creates and reads a bank from filename$ + ;size -> file size, pos -> file position + ;Returns a bank + + Local bank, file + If size = 0 Then size = FileSize(filename$) + bank = CreateBank(size) + file = ReadFile(filename$) + If file + SeekFile(file, pos) + ReadBytes(bank, file, 0, size) + CloseFile(file) + EndIf + Return bank + +End Function + +Function FiBankToFile(bank, filename$, size = 0, pos = 0) + ;Appends a bank to filename$ + ;size -> file size, pos -> file position + ;Returns True if succeeds or False if fails + + Local file + If bank = 0 Then Return 0 ;No bank + If size = 0 Then size = FileSize(filename$) + file = OpenFile(filename$) ;Existing file + If file = 0 Then file = WriteFile(filename$) ;New file + If file + SeekFile(file, pos) + WriteBytes(bank, file, 0, size) + CloseFile(file) + file = 1 + EndIf + Return file + +End Function + +Function FiLoadFromBank(bank) + ;Loads a FreeImage bitmap from a bank + ;Returns a FreeImage bitmap or False if fails + + Local stream, fif, dib + If bank = 0 Then Return 0 ;No bank + stream = FreeImage_OpenMemory(bank, BankSize(bank)) ;Attach to memory + fif = FreeImage_GetFileTypeFromMemory(stream, 0) ;Format from filetype + If fif >= 0 ;Format is valid + dib = FreeImage_LoadFromMemory(fif, stream, 0) ;Load from memory + EndIf + FreeImage_CloseMemory(stream) ;Close memory + Return dib + +End Function + +;Zlib functions + +Function FiZlibLoadImage(filename$, datafile$) + ;Loads an image from a zlib compressed file stored in datafile$ + ;Returns an image + ;Uses FiZlibUnpack, FiLoadFromBank and FiRead + + Local bank, dib, image + bank = FiZlibUnpack(filename$, datafile$) + dib = FiLoadFromBank(bank) + image = FiRead(dib) + FreeBank bank + FreeImage_Unload(dib) + Return image + +End Function + +Function FiZlibPack(filename$, datafile$) + ;Compresses a file with zlib and appends it to datafile$ + ;Returns True if succeeds or False if fails + ;Uses FiBankFromFile and FiBankToFile + + Local file, hdrsize, pos, dstsize, srcsize + Local dataname$, count, srcbank, dstbank + + file = ReadFile(datafile$) + If file ;Check if file exists + hdrsize = ReadInt(file) ;"zlib" file type header + While Not Eof(file) + pos = FilePos(file) + dstsize = ReadInt(file) + srcsize = ReadInt(file) + dataname$ = "" + For count = 1 To Len(filename$) + dataname$ = dataname$ + Chr(ReadByte(file)) + Next + If filename$ = dataname$ Then count = -1 : Exit ;Found file + SeekFile(file, pos + dstsize) ;Next file block + Wend + CloseFile(file) + If count < 0 Then Return 1 ;File exists, don't save + EndIf + + srcsize = FileSize(filename$) ;Load uncompressed file + hdrsize = Len(filename$) + 9 + dstsize = srcsize + Int(srcsize * 0.1) + 12 + srcbank = FiBankFromFile(filename$, dstsize + hdrsize) + + dstbank = CreateBank(dstsize + hdrsize) ;Compress file + dstsize = FreeImage_ZLibCompress(dstbank, dstsize, srcbank, srcsize) + CopyBank dstbank, 0, srcbank, hdrsize, dstsize ;Room for header + PokeInt srcbank, 0, dstsize + hdrsize ;Compressed + header size + PokeInt srcbank, 4, srcsize ;Uncompressed size + For count = 1 To Len(filename$) ;Filename + PokeByte srcbank, count + 7, Asc(Mid(filename$, count, 1)) + Next + PokeByte srcbank, hdrsize - 1, 0 ;Null terminator + + If FileType(datafile$) = 0 ;File doesn't exist + file = WriteFile(datafile$) + WriteInt file, $62696c7a ;"zlib" file type header + CloseFile(file) + EndIf + + srcsize = FileSize(datafile$) ;Save compressed file + FiBankToFile(srcbank, datafile$, dstsize + hdrsize, srcsize) + FreeBank dstbank + FreeBank srcbank + Return file + +End Function + +Function FiZlibUnpack(filename$, datafile$) + ;Uncompresses a zlib compressed file stored in datafile$ + ;Returns a bank or False if fails + ;Uses FiBankFromFile + + Local file, hdrsize, pos, dstsize, srcsize + Local dataname$, count, srcbank, dstbank + + file = ReadFile(datafile$) + If file ;Check if file exists + hdrsize = ReadInt(file) ;"zlib" file type header + While Not Eof(file) + pos = FilePos(file) + dstsize = ReadInt(file) + srcsize = ReadInt(file) + dataname$ = "" + For count = 1 To Len(filename$) + dataname$ = dataname$ + Chr(ReadByte(file)) + Next + If filename$ = dataname$ Then count = -1 : Exit ;Found file + SeekFile(file, pos + dstsize) ;Next file block + Wend + CloseFile(file) + If count >= 0 Then Return 0 ;File doesn't exist, don't load + EndIf + + hdrsize = Len(filename$) + 9 ;Load compressed file + dstsize = dstsize - hdrsize + srcbank = FiBankFromFile(datafile$, srcsize, pos + hdrsize) + + dstbank = CreateBank(srcsize) ;Uncompress file + dstsize = FreeImage_ZLibUncompress(dstbank, srcsize, srcbank, dstsize) + FreeBank srcbank + Return dstbank + +End Function + +Function FiGZipLoadImage(filename$, datafile$) + ;Loads an image from a gzip compressed file stored in datafile$ + ;Returns an image + ;Uses FiGUnzip, FiLoadFromBank and FiRead + + Local bank, dib, image + bank = FiGUnzip(filename$, datafile$) + dib = FiLoadFromBank(bank) + image = FiRead(dib) + FreeBank bank + FreeImage_Unload(dib) + Return image + +End Function + +Function FiGZip(filename$, datafile$) + ;Compresses a file with gzip and appends it to datafile$ + ;Returns True if succeeds or False if fails + ;Uses FiBankFromFile and FiBankToFile + + Local file, hdrsize, pos, dstsize, srcsize + Local dataname$, count, srcbank, dstbank + + file = ReadFile(datafile$) + If file ;Check if file exists + hdrsize = ReadInt(file) ;"gzip" file type header + While Not Eof(file) + pos = FilePos(file) + dstsize = ReadInt(file) + srcsize = ReadInt(file) + dataname$ = "" + For count = 1 To Len(filename$) + dataname$ = dataname$ + Chr(ReadByte(file)) + Next + If filename$ = dataname$ Then count = -1 : Exit ;Found file + SeekFile(file, pos + dstsize) ;Next file block + Wend + CloseFile(file) + If count < 0 Then Return 1 ;File exists, don't save + EndIf + + srcsize = FileSize(filename$) ;Load uncompressed file + hdrsize = Len(filename$) + 9 + dstsize = srcsize + Int(srcsize * 0.1) + 24 + srcbank = FiBankFromFile(filename$, dstsize + hdrsize) + + dstbank = CreateBank(dstsize + hdrsize) ;Compress file + dstsize = FreeImage_ZLibGZip(dstbank, dstsize, srcbank, srcsize) + CopyBank dstbank, 0, srcbank, hdrsize, dstsize ;Room for header + PokeInt srcbank, 0, dstsize + hdrsize ;Compressed + header size + PokeInt srcbank, 4, srcsize ;Uncompressed size + For count = 1 To Len(filename$) ;Filename + PokeByte srcbank, count + 7, Asc(Mid(filename$, count, 1)) + Next + PokeByte srcbank, hdrsize - 1, 0 ;Null terminator + + If FileType(datafile$) = 0 ;File doesn't exist + file = WriteFile(datafile$) + WriteInt file, $70697a67 ;"gzip" file type header + CloseFile(file) + EndIf + + srcsize = FileSize(datafile$) ;Save compressed file + FiBankToFile(srcbank, datafile$, dstsize + hdrsize, srcsize) + FreeBank dstbank + FreeBank srcbank + Return file + +End Function + +Function FiGUnzip(filename$, datafile$) + ;Uncompresses a gzip compressed file stored in datafile$ + ;Returns a bank or False if fails + ;Uses FiBankFromFile + + Local file, hdrsize, pos, dstsize, srcsize + Local dataname$, count, srcbank, dstbank + + file = ReadFile(datafile$) + If file ;Check if file exists + hdrsize = ReadInt(file) ;"gzip" file type header + While Not Eof(file) + pos = FilePos(file) + + dstsize = ReadInt(file) + srcsize = ReadInt(file) + dataname$ = "" + For count = 1 To Len(filename$) + dataname$ = dataname$ + Chr(ReadByte(file)) + Next + If filename$ = dataname$ Then count = -1 : Exit ;Found file + SeekFile(file, pos + dstsize) ;Next file block + Wend + CloseFile(file) + If count >= 0 Then Return 0 ;File doesn't exist, don't load + EndIf + + hdrsize = Len(filename$) + 9 ;Load compressed file + dstsize = dstsize - hdrsize + srcbank = FiBankFromFile(datafile$, srcsize, pos + hdrsize) + + dstbank = CreateBank(srcsize) ;Uncompress file + dstsize = FreeImage_ZLibGUnzip(dstbank, srcsize, srcbank, dstsize) + FreeBank srcbank + Return dstbank + +End Function + +;Memory stream functions + +Function FiSaveToMemory(filename$) + ;Loads a FreeImage bitmap and saves it to a memory stream + ;Returns a FreeImage memory stream or False if fails + + Local fif, dib, stream + fif = FreeImage_GetFileType(filename$, 0) ;Format from filetype + If fif >= 0 ;Format is valid + dib = FreeImage_Load(fif, filename$, 0) + stream = FreeImage_OpenMemory(dib, 0) ;Attach to memory + FreeImage_SaveToMemory(fif, dib, stream, 0) ;Save to memory + FreeImage_Unload(dib) + EndIf + Return stream + +End Function + +Function FiLoadFromMemory(stream) + ;Loads a FreeImage bitmap from a memory stream + ;Returns a FreeImage bitmap or False if fails + + Local fif, dib + FreeImage_SeekMemory(stream, 0, 0) ;Seek to memory start + fif = FreeImage_GetFileTypeFromMemory(stream, 0) ;Format from memory + If fif >= 0 ;Format is valid + dib = FreeImage_LoadFromMemory(fif, stream, 0) + EndIf + Return dib + +End Function + +Function FiMemoryToFile(stream, filename$) + ;Saves a memory stream as filename$ + ;Assumes the file extension is known + ;Returns True if succeeds or False if fails + ;Uses Kernel32.dll + + Local buf, size, bank, file + buf = CreateBank(4) ;Memory buffer + size = CreateBank(4) ;Size of buffer + FreeImage_AcquireMemory(stream, buf, size) ;Get buffer from stream + bank = CreateBank(PeekInt(size, 0)) ;Bank for bitmap + FiApiMemoryToBank(bank, PeekInt(buf, 0), PeekInt(size, 0)) ;Move to bank + file = WriteFile(filename$) + If file ;Check if file opened + WriteBytes bank, file, 0, PeekInt(size, 0) + CloseFile(file) + EndIf + FreeBank buf ;Free banks + FreeBank size + FreeBank bank + If file Then file = 1 + Return file + +End Function + +Function FiMemorySize(stream) + ;Returns the size of a FreeImage bitmap in a memory stream + + Local size + FreeImage_SeekMemory(stream, 0, 2) ;Seek to memory end + size = FreeImage_TellMemory(stream) ;Memory position is file size + Return size + +End Function + +Function FiCloseMemory(stream) + ;Frees a FreeImage bitmap in a memory stream, a wrapper function + ;Returns nothing + + FreeImage_CloseMemory(stream) + +End Function + +;FiRotateClassicEx functions + +Function FiRotateAny(hsrc, angle#, bgcolor) + ;Rotates an image by a degree. Angle is unlimited + ;Used by FiRotateClassicEx + ;From FreeImage source by Hervé Drolon + + Local hmid, hdst + + hmid = hsrc ;Init middle + While angle# < 0 : angle# = angle# + 360 : Wend ;Wrap angle to 0..360 + While angle# >= 360 : angle# = angle# - 360 : Wend + + If angle# > 45 And angle# <= 135 ;Angle in range 45..135 + hmid = FiRotate90(hsrc) + angle# = angle# - 90 + ElseIf angle# > 135 And angle# <= 225 ;Angle in range 135..225 + hmid = FiRotate180(hsrc) + angle# = angle# - 180 + ElseIf angle# > 225 And angle# <= 315 ;Angle in range 225..315 + hmid = FiRotate270(hsrc) + angle# = angle# - 270 + EndIf + + If angle# = 0 ;Angle is 0 + If hmid = hsrc ;Nothing to do + Return FreeImage_Clone(hsrc) ;Clone handle + Else ;No more rotation needed + Return hmid ;Rotated handle, multiple of 90 + EndIf + Else ;Last rotation, angle in range -45..45 + hdst = FiRotate45(hmid, angle#, bgcolor) + If hmid <> hsrc ;Middle conversion required + FreeImage_Unload(hmid) ;Free from memory + EndIf + Return hdst ;Rotated handle, sheared + EndIf + +End Function + +Function FiRotate45(hsrc, angle#, bgcolor) + ;Rotates an image by a degree in range -45..45 (counter clockwise) + ;Using the 3-shear technique + ;Used by FiRotateClassicEx + ;From FreeImage source by Hervé Drolon + + Local bpp, sinv#, tanv#, srcw, srch, i, shear#, offset, weight + Local w1, h1, hdst1, w2, h2, hdst2, w3, h3, hdst3 + + bpp = FreeImage_GetBPP(hsrc) ;Init values + sinv# = Sin(angle#) + tanv# = Tan(angle# / 2) + srcw = FreeImage_GetWidth(hsrc) + srch = FreeImage_GetHeight(hsrc) + + h1 = srch ;Calc 1st shear destination image dimensions + w1 = srcw + Int(Float(srch) * Abs(tanv#) + 0.5) + hdst1 = FreeImage_Allocate(w1, h1, bpp, 0, 0, 0) + For i = 0 To h1 - 1 ;Perform 1st shear (horizontal) + If tanv# >= 0 ;Positive angle + shear# = (Float(i) + 0.5) * tanv# + Else ;Negative angle + shear# = (Float(Int(i) - h1) + 0.5) * tanv# + EndIf + offset = Int(Floor(shear#)) + weight = 255 * (shear# - Float(offset)) ;Was weight+1 + While weight < 0 : weight = weight + 256 : Wend ;Wrap byte to 0..255 + While weight > 255 : weight = weight - 256 : Wend + FiHorizontalSkew(hsrc, hdst1, i, offset, weight, bgcolor) + Next + + w2 = w1 ;Calc 2nd shear destination image dimensions + h2 = Float(srcw) * Abs(sinv#) + Float(srch) * Cos(angle#) + 0.5 + hdst2 = FreeImage_Allocate(w2, h2, bpp, 0, 0, 0) + If sinv# >= 0 ;Positive angle + shear# = Float(srcw - 1) * sinv# + Else ;Negative angle + shear# = -sinv# * Float(srcw - w2) + EndIf + For i = 0 To w2 - 1 ;Perform 2nd shear (vertical) + shear# = shear# - sinv# + offset = Int(Floor(shear#)) + weight = 255 * (shear# - Float(offset)) ;Was weight+1 + While weight < 0 : weight = weight + 256 : Wend ;Wrap byte to 0..255 + While weight > 255 : weight = weight - 256 : Wend + offset = offset + 1 ;Was offset + FiVerticalSkew(hdst1, hdst2, i, offset, weight, bgcolor) + Next + FreeImage_Unload(hdst1) ;Free 1st shear + + h3 = h2 ;Calc 3rd shear destination image dimensions + w3 = Float(srch) * Abs(sinv#) + Float(srcw) * Cos(angle#) + 0.5 + hdst3 = FreeImage_Allocate(w3, h3, bpp, 0, 0, 0) + If sinv# >= 0 ;Positive angle + shear# = Float(srcw - 1) * sinv#* - tanv# + Else ;Negative angle + shear# = tanv#*(Float(srcw - 1) * -sinv# + Float(1 - h3)) + EndIf + For i = 0 To h3 - 1 ;Perform 3rd shear (horizontal) + shear# = shear# + tanv# + offset = Int(Floor(shear#)) + weight = 255 * (shear# - Float(offset)) ;Was weight+1 + While weight < 0 : weight = weight + 256 : Wend ;Wrap byte to 0..255 + While weight > 255 : weight = weight - 256 : Wend + FiHorizontalSkew(hdst2, hdst3, i, offset, weight, bgcolor) + Next + FreeImage_Unload(hdst2) ;Free 2nd shear + + Return hdst3 ;3rd shear handle + +End Function + +Function FiHorizontalSkew(hsrc, hdst, row, offset, weight, bgcolor) + ;Skews a row horizontally (with filtered weights) + ;Limited to 45 degree skewing only. Filters two adjacent pixels + ;Used by FiRotateClassicEx + ;From FreeImage source by Hervé Drolon + + Local pxlsrc, pxlleft, pxloldleft, srcw, dstw, bytespp, i, j, ix, byte + + pxlsrc = CreateBank(12) ;4 byte arrays, for 32bit max + pxlleft = 4 ;2nd array offset + pxloldleft = 8 ;3rd array offset + srcw = FreeImage_GetWidth(hsrc) + 2 ;Was srcw + dstw = FreeImage_GetWidth(hdst) + bytespp = FreeImage_GetLine(hsrc) / FreeImage_GetWidth(hsrc) + + For i = 0 To srcw - 1 ;Loop through row pixels + PokeInt pxlsrc, 0, bgcolor ;Get background color + If i > 0 And i < srcw - 1 ;Source in bounds + FreeImage_GetPixelColor(hsrc, i - 1, row, pxlsrc) ;Was i + EndIf + For j = 0 To bytespp - 1 ;Calc weights + PokeByte pxlsrc, j + pxlleft, PeekByte(pxlsrc, j) * weight / 256 + Next + ix = i + offset - 1 ;Was offset + If ix >= 0 And ix < dstw ;Check boundaries + For j = 0 To bytespp - 1 ;Update left over on source + byte=PeekByte(pxlsrc, j + pxlleft) - PeekByte(pxlsrc, j + pxloldleft) + PokeByte pxlsrc, j, PeekByte(pxlsrc, j) - byte + Next + FreeImage_SetPixelColor(hdst, ix, row, pxlsrc) + EndIf + For j = 0 To bytespp - 1 ;Save leftover for next pixel in scan + PokeByte pxlsrc, j + pxloldleft, PeekByte(pxlsrc, j + pxlleft) + Next + Next + + PokeInt pxlsrc, 0, bgcolor ;Get background color + + ix = srcw + offset - 1 ;Go to rightmost point of skew, nb: offset + While ix < dstw ;Fill gap right of skew with background + FreeImage_SetPixelColor(hdst, ix, row, pxlsrc) + ix = ix + 1 ;Was ix + Wend + + If offset > 0 + For j = 0 To offset - 1 ;Fill gap left of skew with background + FreeImage_SetPixelColor(hdst, j, row, pxlsrc) + Next + EndIf + + FreeBank pxlsrc ;Free from memory + +End Function + +Function FiVerticalSkew(hsrc, hdst, col, offset, weight, bgcolor) + ;Skews a column vertically (with filtered weights) + ;Limited to 45 degree skewing only. Filters two adjacent pixels + ;Used by FiRotateClassicEx + ;From FreeImage source by Hervé Drolon + + Local pxlsrc, pxlleft, pxloldleft, srch, dsth, bytespp, i, j, iy, byte + + pxlsrc = CreateBank(12) ;4 byte arrays, for 32bit max + pxlleft = 4 ;2nd array offset + pxloldleft = 8 ;3rd array offset + srch = FreeImage_GetHeight(hsrc) + 2 ;Was srch + dsth = FreeImage_GetHeight(hdst) + bytespp = FreeImage_GetLine(hsrc) / FreeImage_GetWidth(hsrc) + + For i = 0 To srch - 1 ;Loop through column pixels + PokeInt pxlsrc, 0, bgcolor ;Get background color + If i > 0 And i < srch - 1 ;Source in bounds + FreeImage_GetPixelColor(hsrc, col, i - 1, pxlsrc) ;Was i + EndIf + For j = 0 To bytespp - 1 ;Calc weights + PokeByte pxlsrc, j + pxlleft, PeekByte(pxlsrc, j) * weight / 256 + Next + iy = i + offset - 1 ;Was offset + If iy >= 0 And iy < dsth ;Check boundaries + For j = 0 To bytespp - 1 ;Update left over on source + byte = PeekByte(pxlsrc, j + pxlleft) - PeekByte(pxlsrc, j + pxloldleft) + PokeByte pxlsrc, j, PeekByte(pxlsrc, j) - byte + Next + FreeImage_SetPixelColor(hdst, col, iy, pxlsrc) + EndIf + For j = 0 To bytespp - 1 ;Save leftover for next pixel in scan + PokeByte pxlsrc, j + pxloldleft, PeekByte(pxlsrc, j + pxlleft) + Next + Next + + PokeInt pxlsrc, 0, bgcolor ;Get background color + + iy = srch + offset - 1 ;Go to bottom point of skew, nb: offset + While iy < dsth ;Fill gap below skew with background + FreeImage_SetPixelColor(hdst, col, iy, pxlsrc) + iy = iy + 1 ;Was iy + Wend + + If offset > 0 + For i = 0 To offset - 1 ;Fill gap above skew with background + FreeImage_SetPixelColor(hdst, col, i, pxlsrc) + Next + EndIf + + FreeBank pxlsrc ;Free from memory + +End Function + +Function FiRotate90(hsrc) + ;Rotates an image by 90 degrees (counter clockwise) + ;Used by FiRotateClassicEx + ;From FreeImage source by Hervé Drolon + ;Code adapted from CxImage: www.xdp.it/cximage.htm + + Local pcolor, bpp, width, height, hdst, xs, ys, minw, minh, x, y, y2 + + pcolor = CreateBank(4) ;Bank structure, for 32 bit max + bpp = FreeImage_GetBPP(hsrc) + width = FreeImage_GetHeight(hsrc) + height = FreeImage_GetWidth(hsrc) + hdst = FreeImage_Allocate(width, height, bpp, 0, 0, 0) + + For ys = 0 To height - 1 Step 64 ;Loop for x-segment and y-segment + For xs = 0 To width - 1 Step 64 ;64=rblock, size of image blocks + minh = height : If ys + 64 < height Then minh = ys + 64 + For y = ys To minh - 1 ;Do rotation + y2 = height - y - 1 + minw = width : If xs + 64 < width Then minw = xs + 64 + For x = xs To minw - 1 + FreeImage_GetPixelColor(hsrc, y2, x, pcolor) + FreeImage_SetPixelColor(hdst, x, y, pcolor) + Next + Next + Next + Next + + FreeBank pcolor ;Free from memory + + Return hdst ;Rotated handle + +End Function + +Function FiRotate180(hsrc) + ;Rotates an image by 180 degrees (counter clockwise) + ;Used by FiRotateClassicEx + ;From FreeImage source by Hervé Drolon + + Local pcolor, bpp, width, height, hdst, x, y + + pcolor = CreateBank(4) ;Bank structure, for 32 bit max + bpp = FreeImage_GetBPP(hsrc) + width = FreeImage_GetWidth(hsrc) + height = FreeImage_GetHeight(hsrc) + hdst = FreeImage_Allocate(width, height, bpp, 0, 0, 0) + + For y = 0 To height - 1 + For x = 0 To width - 1 + FreeImage_GetPixelColor(hsrc, x, y, pcolor) + FreeImage_SetPixelColor(hdst, width - x - 1, height - y - 1, pcolor) + Next + Next + + FreeBank pcolor ;Free from memory + + Return hdst ;Rotated handle + +End Function + +Function FiRotate270(hsrc) + ;Rotates an image by 270 degrees (counter clockwise) + ;Used by FiRotateClassicEx + ;From FreeImage source by Hervé Drolon + ;Code adapted from CxImage: www.xdp.it/cximage.htm + + Local pcolor, bpp, width, height, hdst, xs, ys, minw, minh, x, y, x2 + + pcolor = CreateBank(4) ;Bank structure, for 32 bit max + bpp = FreeImage_GetBPP(hsrc) + width = FreeImage_GetHeight(hsrc) + height = FreeImage_GetWidth(hsrc) + hdst = FreeImage_Allocate(width, height, bpp, 0, 0, 0) + + For ys = 0 To height - 1 Step 64 ;Loop for x-segment and y-segment + For xs = 0 To width - 1 Step 64 ;rblock=64, size of image blocks + minw = width : If xs + 64 < width Then minw = xs + 64 + For x = xs To minw - 1 ;Do rotation + x2 = width - x - 1 + minh = height : If ys + 64 < height Then minh = ys + 64 + For y = ys To minh - 1 + FreeImage_GetPixelColor(hsrc, y, x2, pcolor) + FreeImage_SetPixelColor(hdst, x, y, pcolor) + Next + Next + Next + Next + + FreeBank pcolor ;Free from memory + + Return hdst ;Rotated handle + +End Function + +;FloatToDouble functions + +Function FiFloatToDouble(value#, dpart = 0) + ;Converts a float into a double as 2 integers + ;dpart -> Double flag indicating which part to return, 0=dlo, 1=dhi + ;Returns a low or high double integer - decimal equivalent of the float + ;Site: techsupt.winbatch.com/TS/T000001034F21.html + + Local integer, sign, exponent, fraction, dexp, dlo, dhi + integer = FiFloatToInt(value#) + sign = integer And $80000000 ;Sign bit + exponent = integer And $7F800000 ;8-bit exponent + fraction = integer And $007FFFFF ;23-bit mantissa + dexp = ((exponent Shr 23) - 127 + 1023) Shl 20 ;Double exponent + dlo = (fraction And 7) Shl 29 + dhi = sign Or dexp Or (fraction Shr 3) + If dpart = 0 Then Return dlo + Return dhi + +End Function + +Function FiDoubleToFloat#(dlo, dhi) + ;Converts a double as 2 integers into a float + ;dlo -> Low double integer, dhi -> High double integer + ;Returns a float - decimal equivalent of the double as 2 integers + ;Site: techsupt.winbatch.com/TS/T000001034F21.html + + + Local dsgn, sign, dexp, exponent, fraction + dsgn = Abs(dhi Shr 31) ;Double sign + sign = dsgn Shl 31 ;Sign bit + dexp = Abs((dhi Shr 20) - (dsgn Shl 11)) ;Double exponent + exponent = (dexp + 127 - 1023) Shl 23 ;8-bit exponent + fraction = ((dhi And $000FFFFF) Shl 3) + (dlo Shr 29) ;23-bit mantissa + Return FiIntToFloat(sign Or exponent Or fraction) + +End Function + +Function FiFloatToInt(value#) + ;Converts a float into a float as an integer + ;Returns an integer that is the binary equivalent of the float + ;Site: wiki.tcl.tk/756 + + Local sign, exponent, fraction# + Local f1f#, f2f#, f3f#, se1, e2f1, f1, f2, f3 + If value# > 0 Then sign = 0 Else sign = 1 + value# = Abs(value#) + exponent = Int(Floor(Log(value#) / 0.69314718055994529)) + 127 + fraction# = (value# / (2 ^ (exponent - 127))) - 1 + If exponent < 0 Then exponent = 0 : fraction# = 0.0 ;Round off to zero + If exponent > 255 Then exponent = 255 ;Outside legal range for a float + fraction# = fraction# * 128.0 + f1f# = Floor(fraction#) + fraction# = (fraction# - f1f#) * 256.0 + f2f# = Floor(fraction#) + fraction# = (fraction# - f2f#) * 256.0 + f3f# = Floor(fraction#) + f1 = Int(f1f#) : f2 = Int(f2f#) : f3 = Int(f3f#) + se1 = (sign Shl 7) Or (exponent Shr 1) ;Sign and Exponent1 + e2f1 = ((exponent And 1) Shl 7) Or f1 ;Exponent2 and Fraction1 + Return (se1 Shl 24) Or (e2f1 Shl 16) Or (f2 Shl 8) Or f3 + +End Function + +Function FiIntToFloat#(value) + ;Converts a float as an integer into a float + ;Returns a float that is the binary equivalent of the integer + ;Site: www.cs.princeton.edu/introcs/91float/ + + Local sign, exponent, fraction + sign = (value And $80000000) Shr 31 + exponent = (value And $7F800000) Shr 23 + fraction = value And $007FFFFF + Return (-1 ^ sign) * (2 ^ (exponent - 127)) * (1 + (fraction / (2 ^ 23))) + +End Function + +;End of FreeImage Module +;~IDEal Editor Parameters: +;~C#Blitz3D \ No newline at end of file diff --git a/BlitzBasic/Blitz3D/Impostor/Impostor.bb b/BlitzBasic/Blitz3D/Impostor/Impostor.bb new file mode 100644 index 0000000..5ad3ef8 --- /dev/null +++ b/BlitzBasic/Blitz3D/Impostor/Impostor.bb @@ -0,0 +1,122 @@ +Const ImpostorVariant = 0 + +Type Impostor + Field Frames% + Field FrameWidth%, FrameHeight% + Field PitchFrames%, PitchMin#, PitchMax# + Field YawFrames%, YawMin#, YawMax# + Field Sheet% + + Field Pivot%, Parent% + Field Mesh%, Surface% + + Field YawStep#, PitchStep# +End Type + +Function Impostor_Init.Impostor(Parent%=0) + Local Instance.Impostor = New Impostor + Instance\Pivot = CreatePivot(Parent) + Instance\Mesh = CreateMesh(Instance\Pivot) + Instance\Surface = CreateSurface(Instance\Mesh) + Local V0,V1,V2,V3 + V0 = AddVertex(Instance\Surface, -1, 1, 0, 1, 0, 0) + V1 = AddVertex(Instance\Surface, 1, 1, 0, 0, 0, 0) + V2 = AddVertex(Instance\Surface, -1, -1, 0, 1, 1, 0) + V3 = AddVertex(Instance\Surface, 1, -1, 0, 0, 1, 0) + AddTriangle Instance\Surface, V0, V2, V1 + AddTriangle Instance\Surface, V1, V2, V3 + Return Instance +End Function + +Function Impostor_Load.Impostor(Path$, Flags%=1+4+16+32+256+512, Parent%=0) + If FileType(Path) <> 1 Then + RuntimeError "Impostor: Given is not a file." + Else + Local Stream = ReadFile(Path) + If Stream = 0 Then + RuntimeError "Impostor: Unable to open given ." + Else + Local Instance.Impostor = Impostor_Init(Parent) + + Instance\FrameWidth = ReadShort(Stream) + Instance\FrameHeight = ReadShort(Stream) + Instance\PitchFrames = ReadByte(Stream) + Instance\PitchMin = ReadFloat(Stream) + Instance\PitchMax = ReadFloat(Stream) + Instance\YawFrames = ReadByte(Stream) + Instance\YawMin = ReadFloat(Stream) + Instance\YawMax = ReadFloat(Stream) + + Local BaseName$ = Impostor_StripExtension(Path) + Instance\Sheet = LoadAnimTexture(BaseName + "png", Flags, Instance\FrameWidth, Instance\FrameHeight, 0, Instance\PitchFrames * Instance\YawFrames) + If Instance\Sheet = 0 Then RuntimeError "Impostor: Unable to open texture for given ." + + Instance\YawStep = (Instance\YawMax - Instance\YawMin) / Instance\YawFrames + Instance\PitchStep = (Instance\PitchMax - Instance\PitchMin) / Instance\PitchFrames + + Return Instance + EndIf + EndIf +End Function + +Function Impostor_Create.Impostor(Mesh%, Diffuse%) + + + +End Function + +Function Impostor_Update(Camera%) + Local Instance.Impostor = Null + For Instance = Each Impostor + Impostor_UpdateSingle(Camera, Instance) + Next +End Function + +Function Impostor_UpdateSingle(Camera%, Impostor.Impostor) + ; Calculate current Yaw frame and Pitch frame. + PointEntity Impostor\Mesh, Camera, 0 + + Local Yaw# = Impostor_Math_MaxMin(EntityYaw(Impostor\Mesh), Impostor\YawMax, Impostor\YawMin) - Impostor\YawMin + Local Pitch# = Impostor_Math_MaxMin(EntityPitch(Impostor\Mesh), Impostor\PitchMax, Impostor\PitchMin) - Impostor\PitchMin + + Local YawFrame = Int(Yaw / Impostor\YawStep) + Local PitchFrame = Floor(Pitch / Impostor\PitchStep) + DebugLog YawFrame + EntityTexture Impostor\Mesh, Impostor\Sheet, PitchFrame * Impostor\YawFrames + YawFrame, 0 + EntityFX Impostor\Mesh, 16 + RotateEntity Impostor\Mesh, Impostor\PitchMin - PitchFrame * Impostor\PitchStep, 180 + Impostor\YawMin + YawFrame * Impostor\YawStep, 0 +End Function + +Function Impostor_StripExtension$(Path$) + Local RPath$ = Path$ + For temp_Pos = Len(Path)-1 To 1 Step -1 + If Mid(Path, temp_Pos, 1) = "." + RPath = Left(Path, temp_Pos) + Exit + EndIf + Next + Return RPath +End Function + +Function Impostor_Math_MaxMin#(Value#, Max#, Min#) + If Value> Max Then Return Max + If Value < Min Then Return Min + Return Value +End Function +Function Impostor_Math_Max#(Value#, Max#) + If Value> Max Then Return Max + Return Value +End Function +Function Impostor_Math_Min#(Value#, Min#) + If Value < Min Then Return Min + Return Value +End Function +Function Impostor_Math_Clip#(Value#, Low#, High#) + Local Out#, Diff# + Diff = High-Low:Out = Value-Low + If (Out >= Diff) Then Out = Out - Floor(Out/Diff)*Diff + If (Out < 0) Then Out = Out - Floor(Out/Diff)*Diff + Return Low+Out +End Function +;~IDEal Editor Parameters: +;~C#Blitz3D \ No newline at end of file diff --git a/BlitzBasic/Blitz3D/Impostor/Impostor.ipf b/BlitzBasic/Blitz3D/Impostor/Impostor.ipf new file mode 100644 index 0000000..ff95dee --- /dev/null +++ b/BlitzBasic/Blitz3D/Impostor/Impostor.ipf @@ -0,0 +1,18 @@ +[IDEal Project file] + + Version="1" + Expanded="True" + Icon="" + MainFile="CreateImpostorTextures.bb" + Compiler="Blitz3D" + CommandLine="" + + + + + AbsPath="\CreateImpostorTextures.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False" + AbsPath="\Example01_Cube.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False" + AbsPath="\FastExt.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False" + AbsPath="\FreeImage.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False" + AbsPath="\Impostor.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False" + diff --git a/BlitzBasic/Blitz3D/Impostor/Preview.imp b/BlitzBasic/Blitz3D/Impostor/Preview.imp new file mode 100644 index 0000000000000000000000000000000000000000..fecac8dfe0082cb705912f9ad684f1a9dc5c0b1d GIT binary patch literal 22 YcmZo*XkcJvVAyg9h@Au&z+j6r05>B9c>n+a literal 0 HcmV?d00001 diff --git a/BlitzBasic/Blitz3D/Impostor/Preview.png b/BlitzBasic/Blitz3D/Impostor/Preview.png new file mode 100644 index 0000000000000000000000000000000000000000..d32916fe2d12fd603d8877d800e264d04d652592 GIT binary patch literal 1494525 zcmb@tRa6|&^EEmUWUw&72A2d4?gWS6?(RPL1lJ*G@SuUgWgvKPhXBEX>ktSKAh-p0 zxcvTd*SFUF9`8f1(+|D6}6x@zxT(Hd&rXS-pWxv{(OMX1#T+_zvLvux}=a6;^J|&e?oO$&uDBsxySG_lfo2>QfLQPlN z{_>}DnytJ++f9896kWwxpQI&yfBzA`1GdsH{w{F8IdEShaEoTkRQA6u3(GM!yHv_8 zrPv>|mooTAiDCoa3V>~!o>f=;pC6)ChogKyY+fyJDsG%SYH-TCIrzeFg<5FP!;O(0 z%Z#lu<2%r(uUu`s@899rSi{@}Xeg?J14V0t;r14bTkBnHJS8gKdNu{(F|F4v0~|i(4HVlC|szxh21`$8pr&XueXldU0ZW# zZL+r3jhHA)A?ZJ)zG{{mG6F1w$mbn((do3xk;j(h%|?e3{;O_d?R!iO$H6Bqk%*H} zCwOaHQ(b#ICM~79T$?MAiZnVr{w-swE$(YcFJX$rBB2XbV#mpxhdxo3t_$PbC{RmB z^NSV(GqcvGM_#{NWpw9>uA}mb;7u^hb>&r_joCw_ptI?seYPp|R_EBl-o@+Teyd6C zWc6ORRqTH^(RuhKMfan5m-hq`XW*6eXR8VClBvp}Of`UR2sd5vx*xg6O|*LO9<=%p zOAK(GM02OEAqO1*oiY<#Nqm^%#skV$8EJ#4k9ej&KMc(0hk3R^1vWo#`4B; z?XrXbObwn-@ytKj2QtOTH>QvzIzUC^?JjG=F%6~NNu?mJXE{qxhmkID;gDJqAU4=fDzB-+_oMZk)s>VX z^sM`CX!-2rN%-0Nmt|;wbPAZmIrsS>j%M=0OHhCyY0`48Q93p+4)}jQ#C{rL}hA@0*KT+@4>(C>8KaS z`W-k@74N-$y16VAot{n-wmVuE&j!|At=h#=R z2!d`Nac~ahh@ya>`IJrMwY3}cFL`}L zof+l>+Oe{->b!Ya^AyOeq!B9weRFPahgt0FWi!Dp2RD_@CE9nlj6wWr=6?P@+dTGG z!dV*SyYSk&hFPkY$wF^{V9|;C@V(T{Q7@|ZGpZvdriSF0C-YmjN?rpqeC+TGqx9`~ zqqEbaCOI!9&o~*_LeZ>f&<7W%<|iMT$H|TjajBrQv#yJsffHJ|Zl_~^jai4MBCiUv zAu=r3zP7%;ogLA!VawTm)x&!i6`(s3bh8PAta1tK>J{;%xRBG*>cq|<@6NbiydKd~NO!!gD(@8Urw8(yp zPqNHc#Gve(>|DHCxeGX}z8YS;TrwBPQSoBtBGM{SQi}5&BIDFry1?p1n!yhH$8gXI zu~9?#BJ$14O8w?t*;WEpU!;{oFLw7YFMX)}|MYMMu6dlPoe`b9s0s35tdF?t&5WXE z#tuGMINkY^Uq9;4Q7>g!3P9U{n{UvSM*n$mdhXWHyd zsOC_AKM6Rw^j&_#a{1FrK<<$bdiNg@a|Ko7Frd_|(E)Dc2H!~WpRVJYnkqTP>HUj7 zdOP$hXXV$H`$M%s8~}T^Pbsw6MMAI@K?xsGO6G9@#`4i;M`3`K^~1u}=AlueFrHoK zN{>hGgKEk!-^4Xd*OlNl)ot|VQultkP=Z^>$-r7ZY~heB(vG6ql`O)Bk$Zz)251Fv zZCQ()2wsbw=vZ5wg3sOhl7OULW~2>X6?^;mqvppP2mR?h&h;tzpX6v-`{x*E zXPU+`w6lC05959LzF%%YZr1j@5Ss;wS)l4EA1C&(ZsYpf5YHJPBd=;{*Ri&A3jNX5 zUA6r#9EVIMtJtp|V9uvabJ1XPh{Q(>K#ku<7RzjQ%)1;$rEe=1A@qZhM*)rW z*kN4nH5^k((<6y!KZ9lIK32kodmRG0Yl@4BRGA37S3bf~lH@=QR8^)m9-7X_)THS- zh+#I1r^5}JT%UQr+o|U6SA-p%yrUVoVV^4$s_zg+*)p`(<2 znhp5#r#HW0y`9CH8~{=Xr^Ar3V8NEkuk$L(FCO|3MoKUwm1@_!RrwXUh?C=8FfC6L zJn2zU;UcD+3xRiECpnKVgI@y)^w~6|FTV1GkZa(9I_}?gPGsp`35^I z%gl4eUi_hzZ30(&8{0q!TsO&g_;7r;>?fbsEz*6A_l~f1>Cd#n#b7;~az)zDUM)-( z@&T#FbwhG`9Zb^x6tkJqyzcGO-cz1%cfN!D5?L=Cg#;FbWVUGS7=>&GU@!eR$rs@! zJo}B7DWl&joue7|=YtZ$$1P_kP0byyMAn0RS1(_(zkeZ#A|r|=@>D*?yq_AG@%R}Z3U9DEZ?4fQ7?T?(TpzYD*uVK z4?VB!TjW6J_se^s=;!34KoDLP*4Njez+EB<)N}vDz41CDKJV`L_H$uluAgk&l(}8W zJgro6maq?# zIl2|DS-m`bT2mLlwlr-9FIJ6+h@{2v;|(wtXAlg|%hHvm zun6GIoS|VVv5bE}ORJ^;0dgiC=Z2FeH2;a=Y&4zcdC0kf32mm28joj@B;kI;SF7Ml$yGKs|BWCO{-#sg(0C;R)-p z4||L}bfn|!Zh`Y2jYUk&=cYu^V8OG7d}x9Z`K+i3HLw7fi@7t|7~m!^XIM613V@nB9dI0-=7Vqe%=RFMZw*X-Nn z`UleR>^ekKVekdO$6t>v#C=PWE3m>Axz33fwQ#4-}WU4JhTn}{6cFRwyf`*pQA zIBE_KXCGH&>`gh^?9*lr2e?s4PI9T_uKOtJ<1^hn&*1w~m@CX)B+kIY(sGh! zHqfaxxmp0%_NHixe!HhRdph`9u=%)qyZ)@Y;lIk~>F!0=Bj2=LBVuHu*Ta{`Gm$OR z@st7f<`qq%XiM_CKXc`IJaT1I|CaTZ{r@B>V^6`&Gu28+rGOT>#ki;pmYP5Wnv4Qd zDhT+BGQNaZKQTF+;PYmyQ(Ii^zFSMMlT(U^VFiEiwomZ>i6Y+<%6BTCpzdnT!NwNA z!-~b`P|~m^@>}JwrwwUj^4qc4!apOiIj-FmWO7N{Xj;|9B{QOmUrSW&XHo`{F>F8U z*fJwP1(2TxD8K@8hDZb}-O|`wG@iGqwmUP!Hr7=htF2?*PdhVC8%s;DYx&Z8$oPT< zsa{2{i*Xj1Q@ClMW!AY=6WTZ2vbwKXh&v`}umKn#6I4}3K~VVT5@QgDZ3&-1@Q}a~J-*=-^0TtuRM>wEpavFt zZYOE>*BpDoLh}7L$ykoM$M?XRXF^j!nhFub+R{u-^~3rD96m*Xsu# zSM<_Wwvd2i;RBjKgSwOH-(iNl9(t#b7A^f+K~)*a9160BSQ_~gF$9lsp5jU>&=N~7 z2y?40U1XbGea}zTAcz};yR@ZK$-GKRRusq$hdoT4ww`m|k8<8C2_29C#v zI_HY`-Dl`m5l0NQd^WLTu@}VzU=OGu$<(9=1+ZBdH%^8d@thrHleQt=br87M6;0O% zGbZnLX-;Pjl^!4-yHz3Wc9;W&;{0u*qY3_^s zn*Tz*kXK#vC#Fh`79_ZXZ_xkYu>$Ayjz#LNt?DdFb0T7Flc!XIP9DWx4o$DW{?o6E z%oX6f{TGDKG5e0kvGqgS!x0-$6&1&9!49D(c-Q&BmlW!V(c1*!!6E^}OAaq0iwcK= zkQC|zP$HyAPE~B8aNDw(L-)36H}`R{Xw#AZ9RA-*g|p%*lfP_S{Gs{W*|NfPT2NeQ zGNQ>Pqm5(~mEo0CX0=lv1SH#P+m;hCFuxflS9CE-p{72tQ6uWx?Q*9>M;B489io^7 z2EJBu&$Vx|N3SQ6{u6L?d;2p8KgZZn;H;2zLJoG*Ba!37M6EBl9N6yk?$c|!Oo+xS zRWvUWeZ2{ZwlcE$y$?)Ej9{AOiy-+Kmn8uny@j?{{k24`mJ4%wOsc)XZXgv#rx8_c zUK;W4C6lk}Ofzbwo$c-MbdW}paGj{4p0dVBj#z}SI!eo~<7IaHqt(i8o}}4RNwcb5 zJ>lT|(%}}k`Q$s6A5hwIQLkuj;rH*|hH}P_J;nN0IZicvw&{B8{MPfG_5;WM zt9cV5QvU;>!8p4%BT(Tc-y$xj>9g4zjiJfR0J@O$eM!xZJHe;@4yVBNwoOFyU3|o^ z>(3z7Fwrlc9sDaa?fptLrw{Q#0)4y1iw<0LAv&4_OC_&H3HoFE=MWthlF@70PKk%~;QKcOSB82;OUic9x zj(NF=0N;H5!Jsim9<`SIMlS*Bc${Q{qr3-Z3+lGLRlg@4kt z#ZvS_ytr1G{-W?Xcv@!|hpc0*ZcaiWWqC$e%r@p4uCxq46^nPn7NcT0b231w01ydH z1+Z|HNGew9P(~ik#rMCVz|R$960&CNx;*C{Hw_d5o~gqMO`v!7tN-FBKKw2R-ITGa zZ`Z$)lw=`7w`BV;SP3e$g-Qd}apbtt0YuQ(uYP>8VY#B5X*yIS$}BNE69Y~TBq5lw zKiTDpz{Z={CcHf3E32t9F;4W4JHbFmrd+))?C)Cr{ytORF9#B|IU{1}St^xx+Mu^N zj@k9vgZirvOPfq*0KmUddx`GG18y;$| z$FsTutgBLNWmD0@6pbq8-c6ikql6<;OG*$BIB~0`h{ju0Bt_$5zJvpxqh+$HJ#V~L zyhFMz0Qd9j$OI4_BzdU`QLGWlO{dbQBMFir1#g_>>pdTh&IS()g7cozU*x}^{)`{D z_I;~_*64fiuhx*J?YZ;yz^Ml_ZG}Ifrn44=92-dSr4bB5N7EJ;gvRSc?IWDppKFkt zG|r&8Zz>G4k4N+VVdJDq-_&EihW4%TwXOfvqB}uSlgTSiInV2XjkQ9HmCpfsA0LK(#~@*{oWC9 zmf<_)Qe&{^c}lOUB~F=G&cE%jWVk&2uod@d2y%n3*7HqV%G}%=O}@Txg(L*jwVk?Tu|;B1Wo&ZH zvFa!KHY!2cbha)GKHPeNpBDz0 z&pJ%mm-irs9kO0&TLFhfS2^oOXI0CKrX2pZcp;&F)K>v_pjX(jk8G^rCeEDfRct1r zKAI?O7PUWw-rGwq6gJ=->H?VDc3e9)3dx!vto z{jztL2R$SCGv!61_rH9)U@L3?4eUSQ2zFj0Rs#=D`@k4-UXZKPqFnvWN{}=}xR#1D zdfmGng_iOhGr_o)%1K~h=HNB}*8V%=TEc&DqU$0_Ic3eWNds9*=P>J}@9rUNNL<5e-5J7((kq?VD_8_r~allZ8&%3t2LG z)v&zws^-^|{38O7oa~DrA)k3%HjePc`@!U9S8amWBxca{g+U2e-u41f%Igt6Jdc4o zwg#&DU8H{s*&H62@yCa|KCDpkUP+ef-N+K-`dyWOy(M1_y*ia5aEK$dL-Prwv0gEf zfzbzMz1djMNF4QmC}qnAk;%tL2RR0A694`crMtooHeeFRcB6yFE2mp47Chu}iIk?a zI_(LRlUgV$L5}ofRy;VXk#>s1~U%fWX~$$LUiX4tv6xZWb4{5Js(@5Z+9T1oLJ#Ji^0oNO@9w!#(|SC?z-Uj=*<+bDL%2j2GAkEWTb88P?sqa>;?yp!I5J&2 zQ*f-eQ8`qf`Z^SEY!+9QDXw000$B3tvt#3BMfdgjEmrWOeXzIFnI=lh@j^EE(^nNz zkfU^YB{SC?cet!35dFC*uwLScb``%PLvoKlvwoGnk6T-|1HJ?pGt42MeAATb*Wm_7 z>e6~dRdU+(Vu;B~pQCbqpVqQvpR$&x^#;8PYLUex6Dw8ak{98Bk3PT9+==|iP5yEa zlJ2!g#d5mlt5d~){FowFN7a>ybXs0XBTp4g+t zHF>d=OK7VoI)c*MWNQ@pE>{&H-DXL-B*YlA{?7tTXS3if8q3|2^2<{=#}RILQu)l; zXuGVQ$GQa|Ed1;(hs)-pFqf2LV*vmajog^GyYFTDLR+iic@ssA6i6pRS!;gpBu36m zg@X&K+ogL8K_F?sNBs(*9#OW`C%}(nkA8H*UZ`mdqHOAfZTe8DLX*>%&KKGe5Q0^9 zt;_ObSDUr3ikGDt8y!^GeI=s)i?`;;e{BEufqUTVj3bGOC%!lBe0hRt4YG(i3ELYp z$W$;7+NWD>7r46;K=(bAcd!Y&8h1wLwYCXv31rL%MS8Bh8MYwib-(ka>sq&aYMRf= z(Z5lTBEcRLGoY!Uy-C|er#L+7A()&AnYY82Q+(KOzSLyyoAX#GDB4+V<~xG_G}LE5 z!O6jCjPYynH@C`u+kW-Crr^K(=G_zA!w=g6`e3lw>Wq&6Y9@Q-ZgMS~dNTb9>k2>8 zB;aJ41YABu7E-?3yI*Z|baYV7?hj_Vymj0@>V6!Y2rBtKul*moeOff=>8g8ceUoZr zGRewp46O8qR2ItNYp3BM|5*FKT7X$c9h~v{4h>Xz(-^vb_I`;7Tt#dZp;M~!rSLoO zq{aNO@^KONxao%p?{@Ql^kHjw8{7z8$P?QrzX&*jeOordwX>v@kB!Xy5%3~iN#kdCyZ zG}-sagqpU!^P5;Oc7jY&@XiGFS!eVaCE)jYp)rb9Y)---70H&#udavAPVoJfaU0P} zWXGe0qv6)n8+rVIzP`TqDxl9G0$TJhaUKKw+HQhQ=!CN4-2HK2MN)7F7w%pLxgIS$ zDVUP@mtzHWG2~~2h68l-(|YpGV#JusU`dIksPEQPP4I5s)K--6(XZU%B@1}qKUL=wI z`0DYRDR-R-x_Vjng|`5xMfxw4HLd{SAKttCK*#WP9hnwK5s!}ik+6y(+vW33aMy={ zv-oqm6ri9afs)0cQ+#CI)n`k$JcE{lfym0uJ`X;pRK}i< z^lL@j+cU@EQtFsXnRgY+Hn{QZhKi-bxB1NBMO*{nTIKedT4j1BgKHh10U!WfWOW4? zGGBfhu-vB<5HG0%&GxzPofvD!ORUgex#=X1az~(RvW15L<{ghNFU5P%G$}C)w(lV1 zOc2+MlH?&i)$!Kk7%eV}#Qk_Xf_~{!xOtk=OQw(J6|a~n2eCGO zU0hwF*^n;s(k$9)s;a!6=xOFn-U*Xd6d9h<_qxYX|433+%d<~E5!=<$)XWW)8HAKkSo=qbn z^s2U&Qgq@5r8?~_tuFn;E~TAd+jVX|O=Cj#OE2D8UnZr=BKcD_LZXnBcRsMaO6@WQ zI&3{qTwr%OKw*YHK`UBwxhD8eka}a|RJ++lIeY_cCP_NK^_y_c04PO~Z$p|KVCr+Y zi#d^PTxHyz*KuQJkMKr-`iyuFF0S#u8;8nv19y|28RFWVAq73gBK6+by^3-Sw- zsyi3iTCBB3M0zFJPRwV%`~ zr_zVVZcp`|5VdySMtUQJEpP^qGt+2lP% zmF_m>{gz?7pSiTA-;lQo9A+&VWo@v3 zU4xfzMq2Rzu0g}94-m5o0aoHSDs>lga~32#4EtsbDl=>o0hnSn>$K=I(z@lekFI+P>#( zmX>t+h@(&Eugg5TC}1nhR*etRx{a6D_}l;qPlOHzFCe;}EK2FkL}HWB-KYD+0kTo zqOsX2K{{h;O{*R;6y@LA${HIkEnTE-o=~t>)N92T3UTzfU*!za6(VpjoZlny%6A9m zZ_aw0D>WSqn+PK0qAfMhL6~q_Ie0%LRkyqmLgb&0K#NlF4tNM1_V@T`5&!zPLz_%9 zhq!>yr;_*}(e9APD9VDc>p0;VddY--Cb-jt%5!2o3=eMx`Izkwy zN?YF?`gp(jTJ3FDXG2E@w@_vrTdYNheZ3S2Cnl}La>g?Qu;yH@nWLDrDGLY7rX!8n zd$33N7>kCdr`OrA3x$pvjN9aV$35en&4gBs%-jUvaJjC3trNi~vCoWzGBth;Y}x5$ z`<+=;8WR>BIU}E%HbaZ82sB%W7$!_@P~sxuO*&|pjDT2W2!v+Ti*nZ4RZ%n4f|UN@ zN>3X(LdOkz!~e_*7&ZFC?PYqt4sCE%>6AM;#TtvW^Vby8ALGj__IMWlYKowR2t43? z5%5~J$VM7b5lsXiKS$oMZ^8G2!RHqC_KOmHrlm)F2E1h45z;fe#d;77L-KI$4U^JY zw^^Hl@S%D(0WUo5J}zcCKI}f`I3l#R-8#`37H(6VH&n0V46#|Zu(hQDXgG(r^P6HN zAqZnX>P3O1I6|@;;ox&F)eP@3-BR!uI8W@R&Gx|~nz8Qq_1ap`0I`1L2DH;`by*@? zwG{Y5wFrHi=5D`qNc>#H{9=!7tZbA#{wJSZh9frNurH~7I>OZFf?p~*JLoz|t}#Yd z+X@)qb-T-hJ=aBS32EUi>&Mv#<3j9bTJn>;IGT^6SxviOtYPxM{yE!pJ5ZnK_ygSBZNB6g9zN-j2%KKky^9espL6C5DB@1# z8PR&r3mBMz+rNIC zSL3u+DI%8wNQp;hz9?GZGBFW*382^EG$;v|A;m^;g=E{$Ii^Hg31n)Ts;4+?>_iX$ z>y2k}jFRowp2_naOzG--igoSW7(bHgUJr=(kF`R>qQ<|ScxD|$VULt^&j8;Hy)>w* zrlGmHJ%!#!Z2O$JlsfR*ge%Jmt&U5~>oz8?G!!M*7Rx#({aE8LbC7>fW6c3m>n>58 z7s5$H=5_USROB-u;`(1WvO4q`Cwk@zr6{9JhMG!=O%S2SM~M{|w?5)e@9f9jyxKci z)m*a0x-&O_H^uvs{7TUN+dusQ6CjCI>nVy;+BZdHHC8j5k7`K?hMe7*2$<@0D3HQe-kA&?;@-(?+cG7nT_+EW=Z15kME)<6F?RRe1 z!P$sxoRAR3#$Rk2AouFPZliB1ib-}Xj6|qkLmFII$EN9r-{vx907J`4HsC1J?vb?u zSSgF^NvYr-_jyROFuPCsPs^GsL7Inu)^JbP7a_>5$M}t@h1%#)e>ic1%gejv?ZC6M z0L*~CsTREo+$dgjNloDLq}>de+@v=fhb5Y%JhWPKv?WywkPiqU?+4^t2)qY5 zw!I9Q=KFDKq7dm>bdQ9eGCZ0_>Vg`g#;3%L`FhyuKU0hqoyW`a7=BlpYK8i0KoMjdnWJO}fy@1I7P9%? z;C%Jdsb)sEsl8ip?~nmqk~Hwlqic;Rcuz49ZIIO!2Cbh;1n^Dqw38h(w1!Z?DX z+}M`KaN^7}LUh5l_>T%`<3{wCESAwUid-Jeey!pf|gmpRqRC9qhb3)UyOP8wv&0)T`(vv&4TQG$B_P)y;3!5d~N<* zHN2dc81LiK%ugssC=v$=96?{XvNMSYM%Gkb12-yxVbR;d&kTlN0pOcTmevm;dlOVz zVnD77VT?f!8=;d1Mzn*V$itMSfOW;-m#6(23ELV>-y7EB5G{v{g+}tof9}Wb)BW1&!kSh8hAd1BZA4_jh+7!`yI{zJK=BN zG%MfV^`Uro?}woLAnAQWo$wd-8NC>4;uKD|o_@0Tjd%lBNSnIk8#y ze>vgX-;CKAJTBF)r)!`!gZM;bC=)IIvZMsk+9c&=1brKuv(@Uc&2fx3FI;7qJ`1lB zRekxgO<6fUtTVX2UW2H=_Ts{!)|0Z^C%I>|I(fK3+-eN}yhEKAjCxFHl~|X(xe0!Ls6F zO~EcTtDB+kRaE+h&O(VH{Wbf-X2#A^m7!d7WmdmzM57C3EW=$Uz9^wd(V_@=F7xmK z+=(JHq)qE-BdhGr{^Vyd);bwv5;biC(k#o>Lk-^VO51PtB7&?)fvl)y=JjQ)8S>{%)3D&|hyR!{!BYcs4&)K&(ylTZgbqfpi zCp}NhG#}WHT6@e?tnU8b8!&6GHncLFo1>+g%ujDYSR86|vo7T$8f~J=37GWyX#n4L zEYdT{-O&&v5s9}Tm(#>0;=(mWj-5FF&A>qOgqA@UvNXcf>rwsjXHIchY5mvfsTF*4%sWUlF70nvj{?ds z2R<}H;#Dg3Qb@9Xpbrloi=1pa3j!bmPYBoY%U(>E1+oa?Z!F|{1_k+v?ish0B>Rd+ zqf80$0}Gn0-vbx%j!!RL)62SVhODo*MDkF+<3CO&I=h+wHZXoUBaLlKZU>t+H!?AF zKz85G-L+T*_a~;rY3$vsJX#{Ta6^;i+-s0NY$D29&Fjz}KzJNf>02r`;cI%%Q&c*7 zA;Qr2GF~G;6kap4`~ae?dSMT^jFt^)Vf50cVDHEzg5vwgB!%q{wDSV@OmG5`POxu= z6&RY+BELmGoGC-XOrs8@B#8cKWpO;b4&*t0Dw6-6T{FcuGA2kzBF`zt4E3p z0f!h0NGrI1#8OKBrda`H!7j1sdG%T54QOAJ;6wUS$#D3mjpB7*NUp$s7juS2|Ity; z`Y8tZ0|e@2>$SUnBVXO&xRFBhq|>fRqv8=d`5Y4!TW8LivbvXQG70ugv_={d+$dYG zR_^RmhIyYQr_-BN%xbX>TelnR@zC89gp}VSd#Y)_5_$8{+6U2(&^Jv(G}Y z((MT((Icue!+M4$Ra9y}C!hW1QyJu2Y;@G5$IolmIC%>Jy}OWW)cYcB0(;=~6JGA{ zRjXl>fifGIxixzG_(UkAFOF${2MP1C!P{uZQC(1kvkHS@1@$n+|(FKmZ zEB;X*&(?gg%P^viYxvO=D2M}mwz*WK-y@f*N(kzPGEFaJ=~QOM&)8V82Rz=QjGTqr z!!51Qm{KzLg_V?4>+3?_B{chd)32FBfS&t0s$Zm%;>%@NgtCNxg4&U{*^+j$C<&jlV#{MgM_vYzezdY%8`9vBd?XR{Dh_P_NZPepA{`PVcELOkkfWZ)? z6R7{U)wIHkiFZ70%|I~~8tJn70neU`T(8q8n*pGm$rNgTVf2hyy&kr+L?hDEc$Yxf zZ`gS>i_1RdtHTwNWc!PMb)TA22~jN`v{?k^%v7`GAqTQxg=b{w$j9P51D3gsY*Zfu ztv9>teYVY;U2KE?*mvJHdOuwr`>DfR!Q>Q@w1pu5kM6IqHFYo+vJ8w^tfh1-pUL$o zs18C)x0cm21cXAz@RnR94ueRlEnvcBTwfA8ABHzUSQ^Y^n(^k$F$J%#vV;^Qfg(}hga{o=Br+9tK+!AzgoxG_{KkzlW~A)z6gmxOv^fUaL8t7yY7fs0s+ z3k?*h^$|EP-y$C$r7r?fcNyOug16Hrg`B=nS7Q>b{-Jdm>N?A{t4=a zmV!Tk0}d%xMe{}jYEuT(-%qM8Xni*;6*N^??ZcGEgr?G=6%AEHd|UK4`_?&C5m7=q zYBw^8Q_nXu?(BMgdQ<7B3u3JQHA;&183%P$Nt5jhGcemLm{jNHr=&xpOV<3=uX$#& zb74U3FRLcFTAk}v=kZ-Re%TZGU5`(o&zoys(WA<|fRzX1?uTgg<$y<(U!U5xa`+-a zv=v0p{ZX5q<;8oKcNxANRm^A1mR(W$vMlsprfoYH95*Q|ei#

_=NvQ}0Z`laaGI)P7C$+unU72p(E#{vR+w*tq$lI$ zULby3nf-{Sksp4zT7LRhgfFOj$Yu4ie#iquN7u3vF{<5>2J?#Kr{e>XVrc#a^MBDY zco8RHxueWZC6kN;D46)lov!8BP?D;F_F~mdrYP=}^!d!U4Z@J;B+wdWKH6x)t^hIRQ0hUFEN6Ng>vCZ0ulV z4)g&Bp&fm^=5Ye)IL+@LPkfW@$N(W)1I91OPyjZTCUfX$lPCbnzb-|MFMAcp-pCR% zMQbTR$|A7t0R)mPKVEtZpEwJ%P_))|MzM)|?49=yay*ONZ_2ADj$d}&FCfy5IU3|o zFeTgtgPeQ^m%4F;21QT*R_T_eq|POyhHy15qABVTqtk!l!hd5z{LVVJiG+afR7ypG zG{B6Mg1v+ojJ>5hr>Jcm_qo>ylNREK6UPlwq$9P|Om%QVjYO40DOO@0_--W81$Ea! zvU`7$%XKzV31e2H7+=!6ybZFi(sMkXwIdoBFa;AKkswb*q=sD-IA@jU z&Ko)qqekAYO*WsIh#vQ^UZzM~r1%JLl#a5Ro&2O%9nTfHyP1IP_H#a_b4qw}=TQ+7 z$U?D!#nkmbja(cJ4{@UmeHx6|u^22#si>&uyy8KZfv_~r&hJipuV3;4Us-*!s&Ra~ zjoXl~`&w1Y8u#OnBjNR9hXJsR)HYSqDVyN8lq8q&s!`PU_h{*UQevW`s8K8pb#EOj zba)KxgReP*AM;jrM{||jf|rc9qf&6dYNoBwqB7$cG3kZ*ON>ayeY{v6^DX{<8463<@~YVK=l%-r4~y@B#ok4h>ezPK3X^UiI0J}(aA5^jP!z<0F;cl$7?1;3)@Af>a0y45*Gy6?`tz5}*}yMR0h6~5 zL-!WCjVA7)SaRQ%4sYVLkku|ZE!RKh*7CuF+)~#&J3{%Bs9dIey2gY%ZH6T_6#Wk! zL);9ut&2wHU$kyx_Y*h{?Jr@-CP7U`0zD2 z34fjI>)yas=Sx}4L2WF>5nWPQNGUAfNs?mQj~ex>%TH#t)+xp8S+7IxMS<5bMU&R` zfnJZJyZgv$)}s6G0W%bjk2JxjDa$>d1rKW;_uCukcB@vesu!->TdoffkVUfG<7lI@ z6yx2u=9&^hKXYcrR>lSTzn94tiOJP|urZwN{alz@l$%K3?I%RxdPJ2t7{GK{ZQebA zz+FH1ovE$wM$J|_LVG%0Y5cdIPpw5OhcAaCJ@^k^%0J&O8zYpZN@oo2pUH9P!MU6) zaxQ)R?s{ePcoVtr&N92N12YiDwFzGr#ap2h-vbBnS8S<#Ibj$3K9_2w9A||J)1!{d z4RiBHu7>lf{cmU}s`mZ89uLZvqU2TkvgC|n0pB`Zn=75B^rUJyW9w!VBbsuLU$B?X zK;6DoH~f?)_utv^buB1b`?KTzVe4R}Y9F~SWI%J7T5D@~2OULW!2Dk=0BW3KN`r1; zm7{c!oCRE#Y3Pk%&5OOr;v)Q@@^jQDAMw+VB02N=BUvlAVutCa?H{aNf?7t;nBx#% z)pJC(XXDdDW3`-G>I3SA^nqFBEjc{ihduJ#%e@Q@?6)ljiD zaP80Od#Xnk($Kqx6Te z`6GPl_BJq3_1*C!VUiBVVb0h82h2b-zoof${np;j_SKvFTDHBx&}sdw`_3FM7QB@Z zQ{IX!^`$`+d(-)G79|F_)na*KcXu+IAW8smi61V@x^B7AGGLx_&RD07ql^G$sE38% zQPL?_6~&N(=H3gZHg->b?lYfV;3CDZfYT{ zF;WUHWD-Z7?*jlZC4t9)byZyjVd9)MRw^!oAmGhveQWc}4_yv}!1KxWT7PZWzk2%s zAY^&_n;-mYZNt3-1%Lvpr%DhJRtbxSEB%**0rd_1wvve?&3#X;~_ zyW{`@b+w{6h$7!(1S4o<3q_d*zR)n;ICJ&-ZD2&&>%aH^`qi&}GEbrZ{=fODmiY(! z$AmIo*I^tuZG<#Ja*Qy#V$rmXA29437rN8U0zWLO(nz6=1qeFl900uKeh{iw zHoVO`sqay1%_=W3LdvLC8cMKM8e)X4+t^&6FXn_GLNJ5?BTpL(pvDM=9!W#*%MV@b z4>l3;@4xrHo5x2K*ju*_+oo6>_SZK%FZiZ!`s^1Tc7R^Haq#c|-N)~Aihm;ye#fi+ z-m6}5@sY>&k5_e7Kmd#oYwJDEwGhf!-5ZUXRZ-TBG5}!^#Q|~-IW-z|ja3E^|VzLtPcR28dUmdzLQFpSEo zga!d1%cfNd_WC33Y+2;z&Yik>>+r=ddeIY)U2NMXug&RG>&v|KJx?kynU13{ltLp6 zphJx)vn-B$)`4=C%X^>wocH|fT|A)aue|lUzq^<(AtgoKyzM*R_~8%#*6F>I6|V@! zd7g72C)1h7yd+2*K)`AQoZm?(BVtwfVbt&jBjPb1LVzHIgoIJ-QPMQ^Y&i|Qq+Bcr zqty3+b4fR|(iUai?W9V{Wm!i_YL(Q^06+*~O|?qW?%v+c=Rg0@`sUiHlY38Ixk?C2 zLL!7tlTgcMF`HvVE9rjs;~%@z;XO6p@SSg!Z9VKKt31b;_6BR1VkMiKH?I!YPV8=M z=8H)yQGd9;%5&?~;n7jRnAW=6>sZO_T6qEPbUKU0JV`r3s!9k42?QWZ!|8ZV35|Tu z0S5_7A`b$`Fi4W_&7%oGFiw(Tr`ylMOP6mL>|t3D=4DB6ZGRH_SOK=NzA>LIJ$^e3 zJBvnNzIL>G=H#>Py?3#kUwr(DjnN=qRYnURs1JSgF1RDF{f-A0dEV_rj1p%>%|Vz% zR+v?pXPpig$~owHOlxaY9T49j0~|%vIVG}AKQCKj0rGI>GtZA0hJnYFwZp;sW0x+s zZ5;#wVFV$Z#$ix0rAo%fh@+scc#<2VC%@$<+7!F!Bez#L3DTsSQ}eRh z^w33s;QN2=?(4vK=a2qGv0BNdeg1`H0Wv;4;2>_5Zt^l6gb>mQiD5UW6>cR!z#-RS z;!UPg%m_hVBTXDI=m5i@x3+yWSxUv7(EyO6$t;XhOxSFE%qSbgjAetOto$%QRypH< zX~TdX9OtpGW+ke*J9p11M#%MRHwXQ`wQ!No0u~yp5Wpu+Z(qH7ODprd=Ugz&^+6Y{ z_x(?QZvM;f|LV>FeG0wub#D|x4zo_ND*Ed~Yn_w|SlhI9x8L`DuPK*Gfn`xbs~7>y z%Pe%x0jUgz24T@F^xIwRzb-Q-{1>}KqeLmXQ`?>e;udlCTAigelBR=ni zFL~7~Uis&r`4nMs9I<7dGwR22LKvCN7rR^AT9)H^lf;n)wpz{+qoHdg>JY}ffX*kg zEbUmM9ng$Y08zpul5tGS$*3zx@^+iLGk=$T|gCfs= z`?tQj=hxj8-tmL~u&7$f;N~Ekl}$+LV!32Ap=Nyl{r6lS^Yu)gU+;+GdK{43hji#U}OUuF8^l$GU^m^U3{*Z;y(e3N^-FxQA8wb2Bx3@<(4rWQ#EsBCS+!?dJ zv05FGdFrSr|rypmTehO?`S zV;=Jv^E{>Z&Up|;f$vicTP}e!Nfan+wKmph2oypT z6UIE!Rz=Kc0s)QvX(4iM`$^PF@sSVRt;0`#{3n09EGz4DuhYAB`O0wAuiF+tEJQ0B z9)zJ6_`Ky>8-$(F8ZnPT*z(qAv~GpRn6-{l(u&5TzSIUl*jA;32v{qmw8nJObX8Z@ zLB?p{ds0b^Y2*b_MQsMpoH{>*2;c>3fy4(vTA*T+jP z+xq5>0|4Oz&$&R2lTK%0ysYYOCz;L5_rLGy{uc3$cYN>8sB`78EXx%HuqqaTN5iDw zje;vrJ}G3K#;FBZB6#NXUMC4=%c`kMDW&ImO8Ra*_Z-MTKFwNgsY$895kwQbt~Ybe27I_CM5MKy2Q zrokkLljPj_vy160FXqsw;l|eC(U><)D;i9wl!g(+f=KW>VqTC0L@d*&w{iN+fA{Wx za;KC23jOd8zYAh&M0+?{zV_9x{M4WRN21G8p`_bwxwOi79z_^X2p~dQ>B($C2vJIT zm?4S-KPrnQArJx>gr1P5ZA2OeEpMBe2Z8VT)B=PM_Wf8$1pr_STW7Q~VH7E)=8L5t z#!6|UO%VH%bD`w0J2cPuFNpKiic%aiqyc0YMUi)OxX-!%&`0iqFV6pY zuXxRar%nuu#n|%`qgz7gh4bePz-41v(FQ&dEhjX(b!&gMnp*=2Ls96}WlkXkzy(nR z00`5>XY}wm55mYfTb7mQMbyI-p+&Kxm|+B4$uV#QlkDf!|4 zek<)LOBY3+bh^vg5@F~^VJC@#Ag)>gw5Z0HPwx!?rJw%7>fC+jS4DN-h0~M60}brW zo7XotH?Lj30x0{#r*UEC+h6ty2T_*LDDWoJl^;c1Xao_4pyk3^=Y;{UTS7@E&8oUG zTC8uZP3Oxr2{FX|{-`XARwzI4MOkU*Akdv&uW6c%_1*bmrnH*Q7Fm`IMs>IJbZMdbujKawG_ybMs~HQ5pp}%Z7PAivmoc%px3y{!#?{2a_yKq9}gsiOW7^ zNhiJh#FgiN!vpzZGGA7X`B~tHQCJjpCym>-Jf4)DLFXeMxI0=g9(?oL&!0VWFy2py zaX11HV2UTx{J!&NimE!A&y+C0IBitm(-S+pqv7B$KKGa1PPVtV_vMS1wU*spkGHkq zm4zOHjs<}^UYOV6Xje#(NZtru1jZfv)kd3K4stHfF_BNWaT3!l)zX!C#h zh5z|Zhx)hh#<#p3Lzfrju-ChH!w1>gleZRe6jW{7REsQ*DGdk|1mmKpr4rh?VXsqH z74^cpT!ub9obbV*&yX7R(}Uxg)Y>Nq05B_fmSoFSNtlO`ONkj*%JV~vr~%d}PJvqQ zXC=2%>iMdSlI}9kx3)JJCbw_i@`E@{10jvJ=Jbh^d7d|lhtxZoO%Nn6eeN)!%P^21 z{P^+j{m~!a=@kE_Uiqrm`eDi#v(91+7@Gyio;xOrNDs7xIO|?iU^3#4*i@aQ|4MI^?l|-2ONfMW3 z<5PkV@;vX>(b4+)uv+C&m_!lv5H-~2i|c2%ld~HL2Hi()!AEZtXHM??{6GEKJDu56 z?C-tib%X@p_?-K%-M+P$%uem?J^AGIFiAOYvTjFnZXpZ_EQRT$u@v0%=>9ZM)uckB z;YL4TUcmg>bb_&^gwB_R9|S@wk5WHiqG>Pzqd}ibD}jXlony%V$9dGn0 ztmjGMa&Y?gabdLTcavZHm0!BksoWXwe)oGGyL2P%B$#-Zpt^1k4h|S4ahyeQuv|<- z-w*uko*mp}c{hWmT}VYmd_qgPKQSEk_s5e#h(qdHWopfC-nbe?84D;ugdixS{Md)T zZo62X@r-BOEx!Ggug{WjGMz;pbHEBI(!qXj{_0)U2l>=`&4X_pX7PMF zRTd0lSJ&FFS8`5 z8}o_Zed-5SeoYGiuYAp`eG2cn@7cHaj}OO3+dI3!7ywgkB_9}o7*SHysvB;MqLf+fEYNjT`(9WS zD)k}7j=mtp@bleecywCQ!9-1dYgM~xiSF!>M!4YeE{$J zp&t`U$+i{RhCX%<1yNAeEk(4hszJ9KWy#U;M7DL?h_svLt5p((1S25?#Kb|Tgu;k8 zXtPd_x2?0*8eKOnV}9G#LP(4;3q0T~1ONc&j0Mm_M3N*nMq8t`ag_R2Nk52;sK5C< zyfO=wfY!M|C%CbH+iKS~;@$@y;KE*f_zTXljrGB)dr#HN#cVo}#ulqG2*S;ck(SO2 zqhJ1|r|I6qH@)_ir!L%g{mNzNC6n0_K@Fe|SscfKRXSfSV~Qvy3V}H5PiGTEa5u}e zf&fFKmBmO2>CvF!O(#o*HbNLJWm(l0K#X7-MM3D*O>GZtUemVNsG@1BvY{9y-BHulqA`GCq133?_k&2w){8tYv}{_!*ztJ6 zJkqp+G712u7>$N$Kp>W7A;J4TaQBVPedC*6Z(8Z4y)vJ06KrH8wA>%`W~)*vNSHrg z=EH7Uw=JO_!#MI|2uvJN=gefjio!r?1DusgrAdM?HbSs4v`RBZ0dfvnfGDrH)Ng3wG-=Q-qb5@jS9jbPJ_uf zPm*LjK0ttC0)j9gl&q%5(86x7<0!+-V-_cA#C5wYa%&Mn*g!0~V3bLt3C6(LH0c&) z&V^zK^m}P5#oF45wr#4isH%GR#1=x-YK4*8J8|-h4_^%81Uef8zBQ^?m0Y_dijJm} zt;juaCQ^?6$rqPG>GiG6axp=~hlmdPVG?&AfBe#_Dk#Q#yW6)94*uYGpLVzA<*#~u zzZa^eGT4U@I7fQjbUvS30P}o-5yO;V2n|%Dgm*;;eIgG;zR%EcD|DLb;eN2=NetQPL@k0uhv^ z3AREj&L|dA`HVtWK|~Eom2n>8QIs4VP8tcCrtW2lC2%&KBY?RS1i-EBUG0qILK@Y{ zdIv{`fAsrL_x`Z=yys{C@}Y;IsP<0pm5u0yV4MR=+3wEfrN=J~27MuA+tv=TIG~XE zKJ(VshV%KdT;x^jRm2H%ch}} zNFmn~G+7pY7+Yg70?I<6fYfSpYy05f$QS?s2%^|oH5d$ve95&ItuWR|&LLvMwKb2T zFimehd1YgB^IM+(jUWD<-;F4E$>06fANk?CX2ACk{OFH!p+|$xbYAB9{DF;l^S*C> z^x=yZv%29J!ZeG^vLwhg4c|GjRTu4aJ|A`?gydq`LZAZAuWAc1i((Rk@?csV)syui80ynx^E&*^5L4=vJ zRvL`~91I82N>NKjgGI4?&WY&krrYd;pZr&kKl;#T?sSlUBX4=|js5N2Ea_c(@)CeJ ziPNU#A)}bU@nnAP?B0#r$GomRMgs;h(p)GDLjbLFPAfsE=XrhJq7C7cqv*P zN1@g-Onb}uB#quY_tIg_d0%$aqIY`Q~-uZRL{L{cw>K-te<=I(y>sY-|N5s*MH?s zXY;l8t{?tyoz2I`E9&`_QmxgglRI2#$;D(mDT-=yXKS`toIACNA>E=ktfd;aqZl}V zZjCiJtP*Z8=sD$Nev?Mbp)4A#U%lB(#!~|Ufe2v?o$93i{^3k(;T-vsKmK|cU3<6q z{&#%;ufO-#@AN93@r*m;<*$B2l0}_taP{gnk0K>Rr{CjkE4YZ`NNSmQ80yN=c%$Rz zQUa8$t*u+_9)9$q$Fex4M)BnKx{(n>tc=hYvta&YrC6o*Y8F3n8B%Qy?^U-jye>55OGE8tM%?^%kBSNAe zl3LeAZLOgcj@C8?gSEZA?Z+OyB$Y50x2@ouE5%Qq+8a-%v&nog>{$bZR8brwU|JzK zZ?!g2tFZQItuN)peb9dSS>;Yz(<}|Kb;Z;Z8^OmHU>z`|Vv1 z`H{D~p0e(##~;6>wCN;iE7~OM5(3MrvQlfU&YnFX{!f4QXGt8@ zRYfUz;R|2z$i<5dm&?4Q81L?F6=msDzit{Sc@Tz5YppZ{&{}7mjRFQBYMK^6Af)Jo zLEw|3=1R1kII8NV-|r(92`%fgJ{r$I^XaF4Gtk$x0Punrerp(IC$>A?!P@b0o-b$p zUZ<#)+N3VfFl^!jZ8w;%EqVEN0fv?S(l^HXmWHg>_$&s-v?ZiBssZv zMmbo_C#|T@UU=Z`_=Jrm&&}cN;zj_S?>2JROY1a+#z2E=#wQhF# z+GH^5U%PQDjTz^Hc)|Lxe|)g-4BzOm76#Z)wY1~O@nG1UPV+E{(l9)nOanh;m_Upu z#!4$GRnu~99fS@55C%~kLlUgx`DTc(4o#3ADDJ4ChVTg=11VJf; z7kExoF9z_ zgSCySSWQ=}wyY-O14^)S&>GoEG6=L%+yaCl$@;^Vx4sup0+e%#Yo(3Q219}fW}$DT zA{f<8+wdm!l2(*KlwfSrBrR&u>kXERd0kg^-Ntc9eJ@~)029XDv*5bf7kRFZ49yLWJC}P0qWY8-Yxk2`$AAEW> z=KsJC{a{sA1gi1048m}>obPV$u+Tp~I95t*Y;05wH&RAP$135pk+y-rgBS*Zzp86W z!oT{sCXLSGPTiJGD*_J<`@L4UFpeb`X}2>!8kfxqW2Cf`N)HDk1e{PhOM>xa9{Pa; zS}B`$viV}UySXtvzS-}^o9k1hN&mlk$2;C($_Y!l4tsee*4H-1N5`kn z?oG#&s;N7ju2L3S2N(dnRTi?#!-|Aqpw}Pp7`G0dRPfiH+*f7<#oNtn|zz_g-kq)yZD)*~>R~cecx_)eazphyC8+{-IDU#ViT~03CED^nk}m zQS!9AUKJA|5u$K>ygaq;6B-=n)xftw5G}Zy%<|Q;==UN=B4E|3C^t8^8{Qh@c(H&8 z5c{O9z_8`7FZv^JVfmz8X7 znk5k0IF2XNS;O_t=2|IiTUBk-p5I7rE;&G$&_IgDM@Whac?qUCj*|Ie?uXG3T{|jl$b$PWoc*yM zdFP!D?*_YWtq2tO{*}8uvq11_p<5uX#3=STvj)abY9ujDwk6Cdg-8(EDLUpDaw)& zQb~oh$T}VC_$Pkv5ASpsUq4>|#s@LPr6--};JPq&4!+Y^{-~v%f#ho7(pSD}_%nrZ@<~ zR`8~3_x84Z53jB5T)uk1us%9E#?&)fAq0{juF6FaXRE3O7DTb1rJcI2xR7bqshUy= zW1Z2)P=W>L&RNf+O6#Vsvn(@8LyR#63}Iu0740yJgyKpAGxNnV4rAni zken+`sPBMw&b3WT34sVosR$tu0;^>dMb7B;jrGNHA)011T*Dr+vbFUp9PUXe4i1k0 z!ynx>8!KM*x;O3ZYznDGTgIJk8o=8}d8gac+Dyk|k5M61l4h%-2m*!)Sm*45 zv_>03nby!~l_aULsu4md8OJe%pe`$qF)h_HpU;FR@tE^GoMpY$D(`i&#bU+?UFLHmje*u#d*bAU^QX`6-}vIrnP-3MQ=i@4 z?6N4jborWApxf&}WCd^f-R$a>Yuno!5VK$TrKeE^_@DgDPuxD5kLO}-)SFD_oEMZ) z?9kb*+N->XF;6g84t#TFw1e3CDvpAMgv{e)M{=8UWgu@`v zf@9x9lrlmiMwQfDNr+IEq*5sWfzcWQySYBFMq|vXx>ZVNoy1w=GjCBWDT0ikEb9r; zRMl#7JOkFoNthRHTi4ySjiwQZ&~B$6MSfk@)A`r|*tRn3_kpo-99pA|H9mz1!$C-H zPsi(~N2vzJ zXhSdze6Ojw(1!Cih{C2-7yv>&&%+Lw#XOIq#9_n*#})=*u)aB(92{F`048-=zw{;F zdTW1wa&)AW4ARWUkShh9`1SX`?@kB&xAXFszuao`+-G07HEnKPy=IM}ly!R1g}t@B zbT^MC7^97~buBrbi8fiQ~A{cSWMb(ZcM@gCuMk7Yxd_F@cGFnP0AVNtHEX#s=Y;ApG zIbRHi{kB;IND#R^SiosT?!R|0WK3Cb>4`@-)(6vEVgRdUzP`1ooy7=o-hAi-Pow+t zu6KQZvC5@(z@em*9Uo7kFtQF9Ba<-32pa$y#*UC;Hcetr30`tO7>u~o!WaT+;Cq#5 zlu!&I3`vyGC}he~Onu)EmW#QA&SP{jUm|C{FxJKTmdsH-Xx+;xTlwv{x zg4_f5--{7_M%SE@-$&#onDk(W6p~tWvc+2G~&sS22 z-L19ma4kuwXhBh|pe{GN^!kk3w%+Kl;{sAjkLN|%h%}4KRe>N(8MF{!FCdIgC(|Gs z@TN(km|z5;Rzh}%BVI1|k7k6@y%T#<>9mv7RYS1%YybKe?{vWb1>gUUw_89x#tgs- zi?(*xKK;4RpB{F{wPp;T*jf9`pMRk{7<9YcvaA6FZPNmP(lm}kx_{$I&rb+Ji26ws zEsF*K%ema_(N5wY&RPZ~cCNd={>0VWS_485=SCX^p@S3ygGIeW2ulr;ZkJJ7ltmmx zM)RuTX_g70AVh<1xXA0B-R;SAmW3ho{3r;f$1~w90(NI}m+;H?oZG%~ZT8Rp<oWsKn}pL1oSBpD2b2e)op!;P{I(}s&AiJH2hjGZ}idbM04 zM5R_?;6tDR4pyt2V8WYnYi&S+XueojLeBYqSmdjd8@*1y`^Cqu zQ2<-1<18K}Y*jX*EozCaF?jA#T?;w%c}*^Ui#>gqVZ@tIPb4K6%%?Nqq(W>wok!XHT8@ z!j~U04kTbX<#E$CgMRn;@VIG25Yl>8pFDk%P-+eL!(=*H5(?AMb5u_unQUKc^TS~ZkW-}m$75@2FgYpkQh zk76&5;~)qS#P9vJr_oE(UEw7!`8J_+ztdmUH6j>TC4?Fd`kOl&H?G|l!tCsB)bqm^ zJ^vdgrBKS;Jem?Kq>xO20L;vf)`enn5FMa7D0u6KxMid6ga+MPlYG}2z z#PcvA3;-4eljB(=VaqVgA6|a76;3d?w0~RQ4q9}yMRdtOS z@+d_ZJEN4~fk!p;DP`KIq9_L4{&+fJo+q74!T=eQ^?FrV7DWXJOyW>*4tMp+;OeF)|z?Fk^6(bVS(FfS?6Bc&mXX=*7IS` zF~|G9zn638oifH69fzS-k~3nQ1J+Ka^V73smgQm0tE$Vg{5?POG-yNlvU%03U-J!L z_li$^>{ESLdWgT}RWJYO$3BxsbnoK5nD9Hdt^;Th!OOFHn$fc9U+~=LZmME;G5z=_ z9%B^k?M}wyJWDfe(LL3!Y`sP=C^kbjgU(DX~bMLv^&b}O8 z{te#}#t8=Uxd(CA>zjq+lp{=mw@DmJ)m!7TEE*I#xUeUOI!S`ZuH9CHI@sTR;`()j zS->elD9_@mt^uLY`!ERPFn9z3KzW`^r69!4ny!^aSrUdl09p z?@u3^1?5tgBaepabq^$JGyhHZc74TBm$)d9;ZrnX_|WoR?Fq? z{%*0U2qtaY^uqulO0q~wGYmRS6Jxd0w(ELrOy5@hFoZ#pq!}ibF<#dlaMl3_3FQbU zX)-7^44rkx8kd9-0N#3+C1E7+lQ&N9yYI?mGJp7?kA37LzyDPe_5X)AeE(YoWvZ7D z!@ZrwwpbAwMWLvg)+rUm$>H&77)4Fr22{wtgBT(N1mh6EFinSELtq4_QV#2?CX~lv zsFm{GmSuw>*48#vVXaQ$I876+O)?r)bsGmU^co_dtqFn%LfEyv;M_Xvffo#88W045 z)z)gxXw%d}@Ukq2rbUG99$Yp?3Yv7P!4U87jc*^XZe72XO=j3>=WUoxHs_~FKrju@ zH;vK5AN>B^|Cadc|M`D$-~CrU^x;1qjmJv%UE5&{y;UK{vz^`RcTOqA`@8dDP#*fK zY7xK=_@V7ELyQXV;UE*mq&^yVP-Y_ju$7rt0)dHv?iVzWtNp@vrL0YM;y z2%|v6Q4~f>y55+s={OIiwbt1zj-7|vdTVUoc8C&$2>}jxFf`@CEOgFlKuV3A!%-3i zoR>xEp%;{&Esq4_vz^7s=?TKrTer8nCylMn&$Lz3$$l%l=REsa4}I!WEQs?E>TaWq zNho~iW_#uGrQOA(YinQzXVrFKvaboDZQJue3|)6{VgK*{+*9RN^lfkdf%W+rB$RQ1 zF_m4-g9t%5osP725aYJ)X47d^73*RHrD6e_Oea;{0K^eSgH&4EI1~_&wyzKX7iJN~ z=)AMq5FYThY2z@Wj9}uMwg(>d&EO!Ik4Ms)UbbGTrj?W+9_C3L7_F-`*yo2yo3Au3&e1}ZHlt?-XTl` z=XoA8$^di-Gl~`Li?(+jLGBGr^V9S8^yD-UVI+w2h9ayn3!<#5it#8%-k&U2kaFlW zqtqG~CSg^zd7g|Twp=bR?C&2Qoj&u~&tBd60?seBwfRT?;D5c_n*UPX{jQ&S;>OYg z4-qY!=Kc$N%7IN;U7qpdt-g5a^5?(sNE}AiVWTwwE{fvgvt_`!ltY>%UDs-@X0t`# zR#}>+que{xGzFsu3^f9{(=tj&0#(c9us)0Jf#kFtYVezvWz%ybf`MGxQguBXa_<*(qu zH@`hklTn%-o}BIN?GogTky`tMz1_oGH?u^y9l%U%>cKc4F^GMKoj+M^pY^<#W?BBJ z&wMJPpy@O~Y`v`k@EJ!M;$awog@9w^ydGMQnbF2LhaqSOHC-$yWz?&3bG~!oo~Dxs zp>ayr+wOc_00-uavDF$;R@L=vGV;z}ns^R|QkzcmozY}lG(CuRc6R^X-~Dgyw!$x; zAN=8;P)-2{VnI5kjdrWeMu_O^UiRYClRIB{>}C=L$~pwx)eDQk*gMB7Df=WF8DqvV zg;qkA9Iv)v07Iv@gTqwRRU@Uo|Gs-M^>UC*L?@@GP2F+Irn8ZA5;&NoS>3dQHc1db zXpPZB-{*O-S#5S_*|yb-Nzitka`ElMQ>Dz+OFQeL{P6Gmd)Z}o*LnMo{shpSR4U2F zB8+xM=|i7;3}YC^V(5G?Wmj!?=DQGjrQ~EXv(OqjSZxskaTs=8&4c*HtwTm=HcG~U zqu6hI0Dvvay6aRJigC>9RvsKIPEJk-4Il!eEIB&aAVe_bCue7z351UOi)931St_r1S*w>>>|dFwlV*jhUbGN4ddU6nn;=!P?j>5|ai-*5(XS*rVgzisc$Me;BJ6TNq;8&ZavnGnd zFbq!5mW!Rm6W5=l7$$Lg@$x+ZMGt@WQQ+-|f9vTK?QmE4wr~G#?c{tmqnI{>g1}>h zt@9TyUbuGc@hnOJ0GP14uDZSrgAgD%&QsaRd^RNrF%g`dEw}4U5(xn9YPmf)Sgh7t z1hL?h@?f0jh+yQjvgUNT@eUdXl9;W}%P%gW3&#d;&Xdjh{F%?Wzuv6(FCP5MKYr*LR~FW)UOC3& z)1zY=3d%6DAWlTnwBzw~Q*8QS@Yddc-virnd%ilSlpsWcFaQ8@&H@6x(}?jI$icIY4e?4y%O^4@>^mFzYA zDir|U{?<1R+95GppDzVM(wVP+$@7iTQrq)&p|#FOb3*XZ@$u!0`-jJ8S}DP367#e5 z+5;$uVSjI*GKvVz($U%3iPWmDTdB1iB!mbU7li^qk0@3~LjdctY045~7>02e#t=E+ z0i{9%BZnd6Q4|DCS9V=1gfPx%X$WQzyDSc&_geSo%QDDk(74f<){XwH-+UTW_22lG zw`n;X>|a=}*I67YW#d?QhqlE=OQ{TS9_D%4b{(dKU{n=bAvne)AB|V5Vm=>JidL&l z+jR&Lh%u!i5By|4E{g&Hqz518NhqlImQe~JN|Hn?Z_X4fA7ET#OOd#-%)lMk^V z$g^qNmC)%VWZL7?Wf6(6@4J8b`yaZCwtwP3`)gHmet6oXi5Qfh8rP1{p>iKp%yPlD6qv0$~(~%k?_VbFZ~jCePwQ zY6pEBM(b_C7=-{i0IH%&gTN6AfdRlH4+mwMwhDqUl9CY7nGc2H6~iV;l0xRDYetCZnENDxI<*1ds{DmyfF zHA?s*j36;Z(>5AI7CB=XXJ2e#zyv8Zl-trdW4#wV9Ha~=U+nL3PR@=GyIw_6+7E+= z5F($10l{__*|Mw;cBdcy=0sNKs zJ|zlc-~T;t81L>DjrP_n*&3zB<6Hz$-Bf`P4gf||DckjC#S!YeF3rOr3hJiU4iLg2 zLYOiNK~-%DjdufrNiQua6{JDhRAoLMd*`GYytTkNhj3HWoN?=o2$Ozj2=v|~91Em3>xY}%Xr-+MivnfTAr2+li6GvS= zgi!zh8l=?LLWCF(lO*f5kHFeu|i{0JDV!;{i`@vWv7~h;;zqmhbTWyBYVS=ssZ7@hE@xd|LB=Fk71kNxWV-+#Bg{#$tU>)!|g{-$sI#!vkDM=u>* zV3a`07#CeHtGesjx-LshFhpQBPKT~fB0#lSZnw{W(ThLv(B~MVAtzO<;vhO(Z>zEy zPxHDS00Mi9+40FyKxv$$kn-chBW=te6%#=agu4fOXNRX3FYIpC8|fS-9BIWPS{9Wx zFw0|WRT#v*GHp{OX?|gZwDom;Rt?cOXyy^|(f+M-+qcyR-}kia68(C`lLd(P~w+ZPWJ6NB`ts-EDJUG2ZxnZyS#%gOr1;I_Y<3b19YS zij!3{n$33SQxC!6t=r8YCzH|8cX^%=?|BfmU55~o!?3@Ytj@Pp(=o=h)^VB*gA4@C zBYL_nt=85I&Kb@*p$sEJv0*_HhHSMw-E4XYse^kqH{5geYO&cA#fBgT5blRQ5W!APW;>I?lBRCzrr{!F1T?LdQiTDVW*mS3nC+(b zga+^XN(VUn2gZ;7=sORO?+i_oPm+7D-cKlh^!g13NnO`c%F$$Ud~)`z`!B{x0svcY zwu9Eg>FukR7Z&4M!5~OGjqV)XiUJNCV4UA`<;tDgca)OZI17c4eZSe1s_zHjA{uyL z7CZB!Rok}}!ypRC2S4ysf7O0k?!EWc?VA7rYy8Da zm$sWCAZ|9F-MDik!o(Tt5ul8AP3t@wWl339f#6@f$CE~@wk}$oq|tmn<-U3M|MYWr zTh&*XzxlU*>c;I`mo8mAJw4m5OH5oGg>}=v@CDCbtv3M^lga4M{`_M?Ag2&SUIb!3 z-#K3|4|b=AC!3~i^`PeS9MiC_TBVHAy>*7rKrr6*m6nP!zB8YTfOl=%_sT#7z3rOD zI%lkf5D7-Dvj|{}q4i)opZ85&))fQV0~B&T%16ufS}6mdgN(|qPqX~}zy51?Ti(AL zuY2R01w-pib$Ksigw~o>b(QDI@@yp-3k1FA@;&Qvn`ZDM zh5>|_QnuZcyNfYl#s!=t`-@Grl~#!`YKqzcpJjQm zUCySHei%5%-W!Y%L?lhpwr#D|f)gv-$$YX|Z<93l0Prv>%7Rcvxi!*_k`O`fD7k(8 zdXmP2QoH+C%i?ssTm^v`PiAe~U`(C0XRA61NtV#%st7~=mN&irpWVIXsN1%jh4DJH zoOAD_){;`{Jr*K3K3z?w^KDsf`b>kY92;rS|MzSnT`~WgR&A!+pwLDo-A)=6Uy)3synCIS+wk%l~ zZmM2M2>>XHCgOr6qmO_3({KFVcf9}Co+_CqulepbjAMH9cvaS9XFh($GY^hdb=y>g zpxNGh%rPLL^sFD0H5L(S2g8`K&O!i05CIFd>H$K7h8%gRB^XpFmP*8yKOe;Ugjv!oY)*@h90tYS7 zuC={1z&iz{&C|WJ<;mW3Ql4$|G_=m19IuirH^4_x#DfTIwq?_dvuwTIL}BpY_r2o- zzxq`1|0VhMZ~vAgrWf}2`qri1zvSCq_Zz?Se`9ZV_OG6t-Wi$#8XpVB80BFYcrf4D zg8-FPxh;mOZXqHfNEn1tsYZ5`5l$lAZWS2Hw&Wo*#$ap-gkd0NSxT`s0C^S(&g*6n zoO$nfz##;{J1Gb2tiaS$rmf4;9D3jNebXuD0U;CuFd2_~t-7{x4p@i{3PcDfu?(og z)6@Nndk1^F!k#xL>yVMQX#j!FMt55|006x6$A2Qr!aGN&vg@UFv&pQ| zWz{ssX=CKjSr7Tq>2)gyj-iBlG@Ye!tc-yWdF!0_j1%MmLKJvnhQ3EIz_jX>_SE!} z3(+=Z9B1AEr7ZyV!eaj%!sYQ{9EDn0Y&{cHTW^8)0L>=jCvV*G&LRLkr2G4O-dRd{ z)$4M*=0Xr($K$Cnh6VW`wGgC}_VDP8QWl5dXgXW2SD6T&c;XrlI0X0=U;n~?{fUoX zxqNxGK2MX-S^J`wzBC@?ANZBKe6R7Yzy05zJb5i;poO_J##%@?S5n4lc5-sGx0v6! zd6NJTC!^!j)7fkk(qOyZ6q|F(Sr8_p@uX=RF$%3rj!#Yn3k2t7H&_CJ)7D`RX&eJ> zEJ8pe>Cj1tP?(BsSp`vuuor-JN)bZy5rqghRT(lw8Pa`65TP6~9vmN?Oy(0=R{Q%G zs;1kP8%khNv;l>jlFe2HlxDPTrMZ13%RhVgMK6BY`DVR3Kg~vCj7-;e=jZ3ZgY|iL zcWr-3zVA&B?(8nw!4KBAU3Fn+&V%TaAOF~BzNe*BTE*GOd03sVWIu!)YoqF>bl!DU zsf~%#gc8>GgSH4jx?XJ|f(#>T9A&KUIuY^Jrb0#y4unn>y@`Va0N-`C(+WAOw3*1T(FiyF@_a)u7L-Havyd6!qd4ihzV8}FLjY8sr#BCekn5S?i^;6YTh4_V`mPxk z^ZCsuo}5mzO<7V-&W@Lp@r-b4v`x~i*cMu!nK!`xhhhA2Ox7B$VW<-@uYrf{0 z7fzPvLhM+B@3zG+hu6H}d+xjM-fNFvlgdm-Nt#BtZrsui?(Zy?+v;NveLA3wLg<_m zf@teJLhJL5?23FeB^Xbp^V5^w^|EW~UOFMTlv-<>?(HR!xO3wcLViAXHYPAY!}+-sxU5!H*A*vN-Y%2C0A$iGX%(eO?O<8_L3_>oG*w18aQW_Ro0WG8Z%n z)3R7UaTD~zaQ{8o>mGcNCwa3ef9E&<(?#=NRV^G z_jfMy@#?ATegwuiuEm*g0(m-}l9MoPGMUkL>U6OHd$h%d z`&2)s{+k4xOW8o^jYVbGLky~_ndBiQcruPx>so|Sb^CS}bE&%RMv5>vU#$^B$Roic zN(BXmML`s&K^zxlxp!f|ugkh^W{XAJ4vf$wjntsFMG=aSP$D(Mgech!+A#_l6I!?1 z?OI#MLQ(czfQi6Cz)0V9B8iQclRP^w>+);~0eHoWp7ZDvPd@lPulvCJzGBVjUyTWX zx4z|j^AO%T>leGb%gv@O%6qQfn`G&FvuTPFLO+=#_uv1lkNn=B+<))o+jkDbI6~el zEjbrW*NGrVvP?Ej)yloaZa-8;`Jybwvm61awZ@b{;GOXvAT6yjJwbp8addhT#Zg9gDDI-xBiRSKM(!~s*^`ey@v@h{?9Sm)l8u0~7cXDDb?c}u zw;~Ln_l)7yc`?fKo%v*2me#1c=>R}lNn;(R1R`9QO&kRx5F!Y)l*UN!owIJWT0=q! zM2t}dEFol^kMtLNLXCwUjnWJu(;I876O3@d2?BN5j7FoPtoAPK_H9EDbXM1GZMt?{ z)M1!vhZsi)@%;-kPWYhJ!=L%=C>eQgwNc~gv??lyQOH42NrnmNi%ZXV!O#BOU3dZf z^-|N!u;d zmSw{jXB0ck%Blj+9xN7d79QQcF&*bSvFr`}*yq;wKJW~pnk*bnmxUE`txex{4mhn1 zLKpxCApDK@-~IXeAAH9<0QLZjW?PhX6$GO0x;PGvMzhJ764v%jQEoYbrs<{!2iRg3 zP=Ggf*3VT%Q(7paFKFWZmP$xJvolZVkC~&TMwuK{{H*! zef-hKJfX${DGh>HNf{-vbw+z{dKIQ&SGQ>zHAUxO`T+p;oB<$2l- zecLvB8ATLYLl|_`&;dP6^7s=^o>MHMDA}&hFJHNQ{pJluLkNHfLTLJk!E`iflnpt% zbNJ*iI0eEmiULlOG;`iIRkhgJZH9s%aeU__jKU-dF=4;-e?5iTufFTM9~@`IL7v2; z_4?cx4-ko>2q6O_R84WSEV|d3@o* z{%`;GM=&DJse7+pJ~~`Qc>=V*@0s^K{)I=T)A60d!!V37v;h~bvL0Y9RhotXI$)%g zrT2D!!i^)r3EcB=b#7GcAJf+O?|$1aOL*x+gZfZY^*J4x(eCBNeOA-2_+bvpPxHp(#ez( z42_zMr)}G=iYgA%Af&QylPrb~N-6VLwB5j%0MOS}9gRnF&oVd7nI_r?I{97FDW4yTSAC7U>Js8N)ZMaplQOj*3tt?DF6T=+IF2XHVSyv zG}t2{Skn()%TYddNVd(;HO=ns{N}B*I8HE9gdl66i1_k&HNOihu5pReBjdVPygK0CQ0(k$(Qc2cvN!D52OW z$CxY2jtM%7gomi_wR2bl@ak8+eC>PI9PADK_FJEHL#%ThkP6Iaygm zkhjKLt-R_Q>z#m5dkuM-Wup)L+J8h7GvD?NFQ@So5K@=TGcM#@AOIbp0br5VuIkk@ z@4x@iN1qU3ba8+8Gmm^O6hS`9tuzLLve@cD#Yx(!)=D&<=FSd9*&3;=)j=Sdu7Bk> zzTyjC`21`>6Pz6$ZvX&IxzSoPM$GG_q>S{Djt?`7QqUf@5y1%z`da?=y zYr94W4j{x3dw@6FrfXUeVCQ|BMpk=cBw|5V*J&C-Ob|j%u@O;-F)p^%#fuB%r7q4k zg<5WlD4RmW#tA;OSSYP9Y;dFAS*x@zyedg=3zUb6r!rW5Pj0}tHy z>CZeuSwJ!By9#2`)}01UDXF!}lGu5#4Nha;_Z`AiE2Wi$ko0{!o{XUP5D~2hYg815 zZP#)}Cjnw!Z5lNw2a~Y?eO31V;-znu{n10|H?fQbMrSnqX?JLxdQm5%SLC zaUkP}Zd%;-^5SCjiBCP8PIj|=G968iR;PO-_Sj=LDZ?N7@Kdw~@Ye5pgQ0oMoHU^C z^>j9I+V1b~KX&aJgsATZ5eOcLV!dXRaKRvgcW$2@94r_^=bM5t3ILA7ux^@GX`>v3 zAdCYFJ;78PTNEW`6nWP*b<;H3`83ZN!_K-;i1B2iv@}BtEYKd0$D^{Y;xq%+X=`>S zBPC_i4Zu3*9bqI47;vts>(MB!x97dqebdFsq>-|%>u>(nSKq$=*dV*}vKCCFaa`1G zUDsXT&S$f_EaNzKsvAYzLHdt>`qf1a@VO z2yt4@=DStb>b`dXAcUprF=iqN5JXB#YaMi6DS3K&LMREtfH68KtCgSa?DSm~Mge79 zD@mY-&U=hG7fs!aM`Ma$r;G+bw$*GlbH+14t<`-mnFxUQnBb-^X49D*x?!+M8hHQ( zq>Ub$x{d>Gy`qSEU@(MrBb6GAN8UT{tn*kYtA^S`yt}(!H|=Pgbe){$qStVoO~OdL z`|th_Uw!jme668N>hq}@o3d3#zj@t(8GWSMbq|D zhMbSbqq?ma7o764sxd-IlE!hkTrMeNoDs@7(8ePihY_W8Q*3~@gfXMR>Cw?WSFd^q zJ#Y|u2!YaCE1yJ3-Ijz98VEfY47^ejA=1g-XdMTb8WRPWU{5HodPT!{Q#8(kD9r*M z8gGy89A3Tm9`Au*^y1$9lb?B%ady5gt77xa2kzV3-8noxFUsop=x{V1VM6}dFaM*v z<^M0^!8g7kPEtnco#S<$B+^OQ^}4Ao0C^S-a)`qy$x>r9B{UGB)LL4D0IAA)I-gcm z={-nBV@{A%y%3318X*h-Y}-1H(@qV2Ck3Fbsu%P9%Oh-Epy)d=ff~0VQ8Ey)};_Zo~6cHf&j!21GL$e1fj0)MUok*JOG@!o%w}Zw;su|*#mo| zsH-pBl*wpvFgEqJ3MZF7{e>Hxk)iLdKJb8UyG{4etz-L_E;krfHHiOrKGG{ z&Vpf3&N*v!%Eh)D5Oo~EG~Mw)mv!f?3B#aQb{M+FEJu_l$w*1*jPu@N4EkQOFzVaR zsV+;SC=3T>0Ca?feK+(&hcUC(1MG*s1I9pvxCkgA-pKne&ri=w&S=0~K=H$m9&L*r zb3UJ@lu_%z^6Zo#+O@3*KI9w_hA?7O6isKWNwe|k@zJxM{VW81QFhk5kh3IB*XwOl zm8wRhtHQXzObyT{jqrTt;!*HBp*&8YVH@Z0dA&xofxI^bIfn=kNbO6vqHT zit#ufb$u%>G{#-nNpIXai^8~Rt9hP?fOF2fws)9;{^Y*>;QoD?#raSF`f9wm@ZMki z`MWLnuj1Rk^FhXVoF$vHA`A)eT422x1^aswN^IQ>Tts!-cbZ8HH``4dkh1o1oDNoV zr)HzDFwf;^}z&3;*ZezuP+hKk=rw{$MvqZ&VzmMX`;9(5Cf-J1L#Tli5gVTb1>t z%a?B6xDiE>wr)1fPEU)S#Y7foJYQ60)hiitI#la^Ff@#;vra1q(8bI5K!WVhJLiYK zGY%NzcIQ*)Eag-wRcuR+B*ft`$kBA%wXFj#O7ipNxwSqB1tHAZK`VuTOS7yUS|^p1 zUOKO&6hgFZlc!K=BVHlh(H_quWjHT)s zfrJq6ob{kddkGm7SFW z0yrRtAY&`oigPV zg)yM8xmXGjP*NBW0wh+gv-I?I_q~0$?|Sy-+4F;|QvQJuz|zd%*Prk@Rp&hC`7G~u zOQCmnXPa$-k?T4&ogZvgR|MK1W|Rd(*F`>b)>-W3ML&r4=wSZD8;<*Y*sQkqUw+W-}ip%jIG` z8d;;VB!H?11T&~BjjmR`Q(`>Mxqhf@Z|6O;fo{) znu~{{o$21;A!s+kfTp)z6mB=w{bYPznicMp%I(@9fp*UR-!|KwlRa@ybiJKu^S z^a9TTly6qRxxItKu4&r78zphq^xHDu+uf_%wykPmT|j`4!Xm~QiK0+;J-~3iDJY?G z5MdZ7C8g9+5t~FV?X~b=B5`O!p3pqN0r4K0ZV|K6&|5Kl`s=vsD~_0p9-h zcNhSkdiu#a&ymxu29G~}=k(-3U00k^qb>72-(y*ttTq=$%3%zB zhK{e_FjmN3oV=TW{r~_V07*naRBh@w3^2iU(;;XP@Y=36Rwrp%*IiLIn1F!ML8!@O zqRdbfB_-5aC#7%}48ssd0c8{+I7&j}Y+aXeoV87LG>Yn~7>w>)!{QO3Y?1{(^h2MS zo1f2a0pP2?_8V5~6{q+O*XM@CFWx;3%2 zUpv3J@F^S=LKr@FeDw0^`8W;{rK{C;GMg^0)_q%A>yjuYoN8@*(HaBtZRG`C9LHA6 zt}5%M#*|XRfN{+Cy}(DnAP5k~07Bmnw9;MI#bF?%!&oH*VG1GRRVk15W+xX9){Byb z*;l^zYv2E~KlWGN`kZXmXII-z-hS{`UXN$iFMIFTIMv62rvYkP5hW3_jxw^iS~5

1OSNffO|e=6eH+|ewM~io2D*WB|Yv9y_jTU1e~&VI>|QM0x|9p z)YO&d^Pz7?*|=(JhSBbPdU1YU7ZoIc23cEogV4`?&Rfn-9;~+cd=^Jxwp^{WHonjM zL2EN$Cx>3nd|XKTOaJFJDT%3j< z|HD7}-H-hCt1tg=ebv`!Ii!=>bQBq7(#Wfu_TK#~r|WS*{J_gb)4XjQU>EBx00tro z9m%&_sU4&^i;^(%jkN?qB^BXJYm+5$nxsX(t%cx>K>$3?+ODOTVnQIqK^QDH8>n;` zg~=#un?@=r24NvW4o^m@QljrW%D9DKP>LEf$X;mUGZHayFdYG4r09!Q075&BtpQ%( zQOX%5bzMm*+PaUT;OVEI+~&o_qf@0_oK3cy4FDoZCq-4xN2BF-8*;zvy4ifDtozab z{dII_@h#u>EjRWi_b;|D-@WIQ>_jK!5QpKlqXUX*6nRS7u9t){&-1Nw1QUcXLdZE+ zR271FoQ*7oRb5TTQvgt}WZl$8+Bk@W>;Z&~bBM80Zd5 z7-z(X(8X!2q&7xrtNKn@qvLqIJbM5UF~B9+M5z{8tF#Tg&;Zx>Z5YLUKkV%60H^Ds zVvInn_Y>eV@bbf|knH+S=y9r1qMUi@rI$wIDdj%0b~+xNoL>xmH%Rq=ec-kHPx#*N z{jQhpzEU^sXtdW<+u3|X8M(H9ROH*y{MsM=(H|V_?QXYgq=n}*FHEI%7&-??5c<|3 z<4_Xu?P@z{8wFw2lmQUWJ$2;%c!opI3FxnFkS3N~x~QCZnPf zK^S<93Mu-oMTihY<8e~uWm7j%>;Z?IHDTxz#-S4t5?6&B`ko@-hyHfk8*3oJahwcN z5yDsNoKfa;JSZ)sjN`~ife`;8TTfmNmEx*L^+1F#N6{B zLe>FFU{RF7S;m;}MGgq$wAR4$6UL~udKmh)Z7@PYDh=WFgZ(-$wb5A`20?WG=-!=M zH!jYX*(gYSSP$;*S*4`v>LyCk&3YC3)M!DO@2pW4)>V_u=0=G&;IZa{@5YJ2>gQ2d+UdP=c93w1`Kb?T3KL~!I)*^RBMG0SX?cXG}B3z zX0daqtb4+c)uyeR(D#gygEq72q}W_NdGlJ^^jh{BxwBQ@b$t}_x|T`AAk+YQ<8f9r zQdxBW?%ln^eTtygX1iG(UEf#AQjGF?@H{W#Hm{{r#%g)%Xm3!uuG+(E2bZf&?1MMV zhMf$@`*(ig1NR^yKl2l>-_G=J{N`_EJb7^Xu*u86@mG%%pE*&SEt*35Ap>3zcMA6s z0H~lfLg}Fu<4FW9X_eV-3dX#n-7pPs*DB#Ou)-QhfIcgLb#NH8vYOi=%0`%aLCCt^ z)tzXY=H~JByx5*ReCT^VBKYR58%dlkE-yFRZQ#=+iOX`pp!U6pP>(abE;moIE755K6tZ;hV6w2Z(zsvi+`s**R)@c$W2yWiK`RMf2 zIzu2v)Z01O%Qp)rdc=b}H;+F2yB`apa6C?ZFYLQ^v%Uz!3^-HQE#_pLjfFJJ^%^)} zlnz2}go+aC49G^~Vd$lhgb=`p(XMN1B`u|_YMb4isWDw!ON?2yjd|Jk4V%X(|}@A6Ck;@b+TG3Y10 zw^0 z8jW{2Bb#~aBCmGlQ|v&PaV=Hb^g^4i@2!K#IS1^m z8`u31H+fyxeeC;w7+}U=cU4;d`psvGVtammWf6u>0f2ttXZ}NY3V&X{@SR@_9jL1E z*3IkNyzG0)8Apg5T-&>Q_a)!+tExZPkBhP!kFq;=p85UX`+cP)_pq^al=#=K?LK($ zfGKT^_LJCJczCpD28F`3={gJ9X1VOTHceATsdCn7o#(|Ujf`f2;+0gY-5IE?@S+X-3DI*`8t$fCOk06Zp_V+zTXY-?vef$$~5*ews#kQ$y zZ9(6)Njk!WF0al;qm20hV_s9W7FlF1_q|~dZBx(Z2cuB{MP4-Mhky8oUTd9yKEC)% z-!t3Ut=b-2ZM1ssbKdfy5C7KNKKFA!{;5y++#k9oO~=+*-{YIIsPbYmo39sFjAG9V zF-7z7_*5S9@7*sY_p^K;5Pt&Na!7zQZ>fbN;6o?0xI zL*IM8Zwv^7q?5JPPKuUL+O)kKM4YBZYXlwVJ|=c(Ixh^G^<~!?9)y;1)%ORxlij_& zPd)$qFaE+`f{@gI%R9dK-9y*KN%)rMp83=ZFNHx8B;l8T$-92!NB@5o|nCWw{P99diCJ`{qbmIG2CqOz5U&MQ{|ft z^=TaXT`PovukU*E{y$Ft@ z93LOtyMGn?q#wFC4wZ&wnM;Fi-@0B`)z0otS=7^!hamaHi}&Y~iNmOh%oS) zrqxPMCnL&9)zo#}DrJpzR%iUBXBX?8{Uaso!&^^oFBi(0&wKXvpy|K)t&e{2mtS|^gRlJh zZ|m_igEQ|T>v}rnLtpm302aH)&)D8khnK4o+=>WnAItLI!jQIp3XH^`BL$55bUf^|Y z#|Vw%h(n|tsQWev{5Ve9z8kvU_jnRV5V)#tC_zTIv)SHez1*%=VU!7_2L*a5o_q7> zoS&X((-7i^VQ_J|9!*p1(CPUFur~1V-YD9Z_3_QefAAl_s)_L5_h0>eYtW<9ljUML zn$C}*9N(cZga?X#Ee7m8PL4+uwRaLch8ALIJpzS+tG=tb04WYFTCZo}f zcZXi?j)6tlgZnQ&_v{;=f9dqeXCC_>{`((z)y#kSd%hex>!zaH^NiG$nkIhNmL8{ss%2Uo#d4vnf&fKf=m&u|#^b&+wkS4nlyDZbgW!xI2wEYAzME!Q*_1&T z0}F(*5J4gPA}=7qN-NIT$mb~$x9{A#%JpKCuQoL$JP1QAg&%r@5MkiAZJVU&FbJ(R zqZV5`7?bC17+$pZ=5o`8ARMj(5KMaDQ}i^3Yf}o$aM*T;{92 zgIk=r+3fH`zxg4L^DyL1v0&Vb!q^WJp|!G38aK(}UMNPrw(1N}7(!)%vEZ4*34*yo z!Go(hFS}7Zallz42xE-%rmf;2D9chQ<@p|?WDr_gfB~SC7$ZF9LrkR>&^d;1lqP-G zDya$gfRTDAj^^2>R!X$sflQO-C@IRX-x z!2vv*&kVp19-Jm|y4r4U9A96qml(pa4_k@+B)ht}dg6)47t0ldC<}2KATQvzy9HmaL&u^>Y1mW zq?~JG%A(R*TBir0o2K8HOoi5dz_k+jHs?GvPS57^>2&hqC!Y_Z(2v5dt%s%w;&eV6 ztD$qwh71bPGYr;ci@ogR>~fT3eOnQ12{O`P1W7WQKYVl^#qsWZ_QxOpBcF4l;PLVP zdQ%Wayt9f>!_&8TaVrPpZ?Kn zHfi^#^N;?=?|<-U{oB!e8dT@HFjY{Ha;KSKCIXzp3 z*<22N+4Q3{1ptN-Zni}dXr;84$~d^cGkUb@ms`;d?JVG(8m5!%a#ii^OuOEsliho- zyrN{kx4-w|^Up_dN-#b;I$(^6p;yLsbzuOsQgLiL2`C|P78k44?C_eBS_oYfRp>KD z#C#kt)^!@fYG9kZwE)g0*-!r;uj`xW_kH!(DQ!GP07MR81g+F+Z#wS#wH8)m+P8xg zE{K9nUQq-gMx!)A7z(NLys}1Ln*>{7odt0emsL$n$HI7!%4$uy?|Zy1>&w+T3S(g1 z{{HTCXT-hu(f#|>_q6CR!Ab)wdx#w6Aw-xnQq@(lEighiuOF=Q!UB{f(YDxjwJ-n= zQh5x2>$VZ`7d8y)^*)@GCID#d-v`m z4B=#VPxMVu)tvFg<>K&Yx;LFP_0SG&(+(bEm|)_0MruTOQ`VpV`ETlr_6L6Ob#Z|F z3-g0N@SRYVqkv+Eo<9Kqwm}jnXcpIpw2FOZF`NPZD)r8KsN{-AndGh zK@?hmh13+dw(rw4edYc+VXW($d6qJdG`&c($!t2gxIFKw#yWCzkX3aH5!A*sd8eSx zMpMysoU=E-`OP2sy+3&R&P}8Gs%TYT23{D`Isny>jYk1xMb|;C93(})O_EVJ zv^TEbsLNcczN#eS^vNe~h@q`EIb|FIL$NWC8XQXFX49F^$=z4(I}1ZU@*_{SgOE~K z2>_leDLrj%O>|;xr=}^#*M}?f~+p8$u#8@t+$JO(;C}HQM6uc6l5R%jlZlb z%l<^Z?A`Avnl|t`04NIB(|2x%VW_Nm>Fz^a=Lp)oZuWQg`@T=oIPuA5n?vfi5_!J2 z$v0s-(?TEwg&3f}hoDK~s8`N9 zr!|HM1p!6SK6U5umtMN3EtXpMO%p`{f}p7jKM3o#pHD`ew8m&gP~Xd){oNN{cpd@w z=4YQY!D~&5j#0OKiEI`XaDSVJ*)a}dDoYJML#Gr)Yq>cv_b*v;w07D#&LY_ z{{7JR%3_mdUZiXvQ<&EerL08VLC)P)~} zl<=mi>bfA5`kv1?@jQ=E+*F;?20~|yF~EvWSz|=kV9J;uA!O^S@;&Ap41mo~&x4ik; z-}sGRa{vUPXN>84NWwa$8kZSyo!M`?Il9lKb(&-n?#`p*DzOZFCg)gOI=h zLI`lMsr$C+w9*i81avPo!kG90#FzmDErOU6YlFb|J--`z=U`suArE3dpp01ygcJZl z&Yi^oIB1+!R*hmWOT)#Z2ebJ|w$1YDVcn<)FTM2kx4rr1_1Syg_tn4fvp@M+wfEj1huC6hZ{K7aDa*P(+ZqbLXj#fAZs$U@a|jju3FQDj=|*e&Gd7h&2{N zU@U|XEmj*~UEl|V@GwNyxG3?ACPpi*fgi+i63Af?eJ2J<{Qv;#oDqWn2t$W_&aJje z8Zk%-t%cb4qJC&c*;q*#cpf68>4ddL8EGuG8f~`4wZlV%?a3==)9Dz8!FV$I^d~+x zo9;lzJkL|g8Y8dHuRP8XL|*JuV6XCW8U`1qr?0Z={OWY)_^HLZxbfIyRas&LJue)( zfe^%)*R?J65JuSJ+!;M65Ji69OQ|%)gc4eIt?zrBaR6WtIctsVMHYn!k|ZTqU)hJK7FF-liuX{@1?BkV%%wf!(yYb>0MlBTKpq4)j3Y1Ot(6epX_ zDvV-lMBNX-f+&jmR>*bkfTP^kTGyRmgjz4Q&NWSE#1N0hL)UwLIR-3&M~Q3!T1N*3|c}mU-JX zT00AE(X<0a5kcjku_yyCs=6jiVxv^s^}Uc;9E+~Uj6zI+cFq~&EW(H*HuR$Fpmt8y zP3U=q;J&LJVch2)^C-gvAgM%I*JL0{xu)qb#@aaKFtAQkwUP>9nvLh{?V@QK-w&8G zq&~+eAfvGCVJCH7DHbKxX>ByZSSj0goe+KEr5HL&5chb~)*IVJF)yX@*=!>?ii)~kb^u^}^SneO}fAQb^>R587D@=A`+*Ud>_GBK?E?p zT&x_V`?E}Hg)vFvjC%giH)+6jB5-_sr_}hWIPa9fjEF%32#wN+0E~%4fD)*rG!|GX z0ff-=V_=hjZ?*;JOdB`JGJ{a)M^#Z%&aE?|Q*j{ocIWp_8e!nYs*I8hBCxH8+qZ9> zUFAdFgn{4HdFUm1o?GWQ#~u%($lK(b*UJCRNFQtqy{?A51Gcig0Vp@t9L9v9>~5&yOuI5Mke^LUC&hu)y=VHdgAP?R%po zL@Y@Y?7(JQyLJFp%WmB(8FAuquQ1(olnz1y$T2}hRcRPdYyfr4Kn#pkorEY(C(HFB ziIYv<5(LY#2m^k0e&+LlGg1yxDw#5B5!$RT7-0Yst?XnnVu+lbKDu?|#-Q~1`8oBD zo;&d4aq?>U{*yU<`Rw)^pBdzR!UAUu^4a0x(J%kXulinKwcOjEm3<#UG@p*QMb!$C zrK!|a6!;e7t}Hp{%`o_ZkDx=2o}WBCJ9#jf>{@I4z6TiZ?(HvEtEPle7+~Tv%7iqC z*uV?(PWhZVYaqq|AOj#mL|Pl~&L_RttXF5Un~cUqo@b*m_q^j92QS|{9j958Ms=A} z$~b31z_b?mX500B-!z>1z^Z1j+q@4G)OaH%=-%P=*H-fX7vJ(t-wL-U4_>~QPR8Sa zyz+2)5vHpOPIkB#B&${$D-Vut081BF=YfYWua?fa?PkL%-y4sk$+*~TrLaN+p^es% zkRZ)sj{<00ZPec0&iZNrAXaklh*?~%9HY!+zK=%9_})t|`+h(u1wcDzm6XfHf>0Jl zK0@^3gg`_b0;Ff3-|%D*`WCuDJBS^@ z&`_S2b%dl8no-<$J#wIGyBA+MeeO+9RdrtEm6k3}Wxn;q3Wi3`0xY)bfF~o*kiYEA*)YM&aGAkk{d_Io#;+awsDq* z9^dA9=z9T0Mb*zHNwukCFH+7(X(+}HI}f|EEC__g_Qu)Y|AS9x*}wBYe%l8>^coEE zen$9j|H0oodvM=<)lj_0hPh+WVcJNTVn;))D51*m@rFu*cfo)}7E@ zH%K=qH|W7xFdD~A(^U0f4al-YI}irGbA~dii=oSlOJyly7!#xPdfO39`li&-hFK(p zCJ-1#!Z`TIM}OBN=#^I(9X+`%t2jyq(S~8zG|h5(`NW+!yzu;| z(j@t7fBnmT?f?Fz*IMUioiF^tcSI;TLF9XB6w<`@ z5dZ)n07*naR61*SrjvZTs_KFIK`&(-dsSOKcIWZUdh>>-$4cnm_|R{>`RS(yA*FTW zByNY=XIhHR^An>76we-i{IR?DUID}@A%&7!>x2D+<>GQ@I&JIbi@)d{KlM{T$)HmP zan2r|oCTaur{j~erB!mh-9G#D6WeWpyfn$wCLccUZEsJr@K=BNFMWXdmwx%X2;rQv zrtS9TiJ>00>ZBRxG?Wn00^$0vvJ(V+3`tr3k|S zPymrXrNkH~jkxo~@uSl#1d$hcyQA#h$)hxleBU1ifep%G8 zPrUQ(&%JbV@x9;k_x{QM`l>dA{>Av>cmK^OWRTJ0gTs&h(I4-OCI~v&4RMwkrK)@x zCn-F_Br#eqE;a@MMm?pJ zb!Heu9LHVXVt|$E7RxJ!?d@APUU=bQQx&^AJ8?iE@q9m7tn$}d>Ys@lH*aj0>mb}M z>P88DbhvwVwc6X=X_{(2+u1BHrjx85G-EW2gR7y##sX#3AcOfR@WZpkrW5LLceKAZ z9tJH$hpZI6+}3TtJW2XAsBJ$appM(98_0V3xZi$l}ZU! z*V8eD)N#*ix*j6rAaYXd&gTFTrId9R0!DPVwqd1J|i|hyAuGP|MqucD4x2# zyR1bvI=s3(pU-xhw)H4DzJ8;qE02-8_a0J;x=sb5R~A(m_z=TsozJ`|3bQQj`mU^-uIr*G^n*b6t;cCqm!U__FBeXl$DV$!@5Re^KP3iZ zti67;&#B296Q$wLy#IAn1Ni1|`SwSbtD8r=SKG>G7!xv|WQ%oi^5FE&6Sp6K>}EHZ z-~OH7;hfI0F~;`M)s^Rk+L$;B`(7R$9T&wa46}>#^Rg}iKZwFGO;d>6cAIzoKoC#T z(Q>o&gMbjIrL6K?2}LQ!6ha6fVuW%8k+oVV9Yryx!~p{k0+v`SqacXlxUKVk5PleQ z#?&x4WQdmItN*791MJ)QOJW^*s>b^V1WhB*z3XJ`BU|-hSKnV(5*wjM1_x1D`8t#^Xe3r8Tt5 z1u-9nwiAGHX0-7=Pl<*w&KYl-$~vcoY}=-8TFwK)I3a{GN-=g;a?f)PDP<`FP1DWh z)2^=(#EkodaIIC81V#!Wdw@yTiX@7>(Ch2gAS9(7#SzBXHuhBEd!Z+ZK#f9T)5 z|HnSN-COVdiudjA&6iipvT1HyKR!CT_WX-4o4~8#*`2WfwdS0JWxtQ zfPJ4SCA93@rcn;eru$myP6*09&!e1@rl|-fo2uL&?=UQP$GqAUlX19r?fS(!e{jBO zTE(c(fKeS4vS*)bEIKOnxjIxXcq39cDoP!(@5JZVnVt;@C{(}cmz^yWk zf~i|R*fIn~-K#80L|6XuFTG~_Xa4#--kHW>@4z%bLTMH!%VnN~Ufp#7!by^bA+LK0 z9HfXuaiZjq#PK$-x}gIAAV>(oy&MRoMmdUcn8X0Wx-1cdm@#7{gjfv1^ZlZ20`6T4 zEVBL0C*OEh+LMb-Tdy&o)|u^gv%5RD%0P?&!m~-1=LLYkNHG~_b+4eq;}OlbRWBW7 zWSpiBxaHLvbFVClz~|24B(M;|s%k067>L00u|KXmk;VSKlM4#T!T#=Iu?YMih@zt0 zmR0Ahoz7>YarVmH`@iz4hjxC=*Z%D|@|2c!S?tcIoJB<=Fag`V22M$3;y5J6EEku1 z$A>$k@zu6emU52~Oe`=!nn4(cT#zPp)dbAzhF*$x-_v)Vdg8^?ZZQ3}XpOR6*Nny^ zEe7DQah5QG2uk7tQNy?cywr#xmqk|5kwFe0Q69C zN?DRIsPCQ@7w0SAkAv7pgl#ulpR?)C?&+hmy`A}FI#zu%8O0AzFUxkIj8DgtzH5u3 z=tZA|5yU`gkVM}5f9ywJ1>t|~3qCiEBahM+IEZ~~EpSw-VNf~*a0%jpXm@^)7Y)PKT0k*r`#Mh2Dqr=TLNxF=rHrPdF()9;D{Bp+ z*rx-MX3!uEJPyUhwy8VR$u+8C?kcS$kt7_-fpL(gb<{aGr)1qvm|Q!wl1n{ zl;zu+c|Kzpn?X4ym3Zv-@yB0yIYc_mrp7Agh&S5btX2epo!R)&`J?4x83a)_N_OT` zXF)%7P1^$t9IzDAvZ}(+=M1$?PZ%|-N01kF9YqlWMu@>UjG!y)MjN*?8*_p-MP;1B z&RGZ}Kd9RtItK{?&K+Dk)NSD)`i0l`CV}_9_p5H*dE(^3DW+J6VK$jcWuh?Hl)3Di zs#e#J_R2Ds!YE_stUb#`INsk}UZ#oP2^oaZX1xibFbo2Sse=Fk$S~AeLFgzW)}p@5 z8HJa5b^Y2gF!v!MTk3um>qjWcj!@X(Sw92}j z$s~+uUX=5l+45=$5si}s1E+yqTrAtRed5mTBn?MNv|3lXS+9HduYdYyUTeXBK7R0j z`KPG-#0#g@&i?IB+&wi$Q)C(Uj}Lb&KoMApdb{o*;7PAJu!>>38xu!x(WrW`&fh~U7Fq&9v)yDE2%bi=S-ub+JKaYA_8cTL?DRU3OajiZaJg_Pp)CvHA<=MA6y z#3$RXtp?Tg{oW)yzIMpNxGan1>WY&fO+4moQI!zDC!T&{yD1R!cK2^?w;Rs+amterEZ)ult&+7R(Rova|qbrL~k&squJPHF*?<24W?(8v5xt zlS7|o(Q1yzaHd zK^W!h6`?dqQa|9!^(G3V)p9+~MhH70gw{5S0^h@BEt;~}+dEjUR$dYVr8et4P6JND zye{7LSKm}C`6yi9adm!m?b=~gmPYhVFDFStsV{VgjPQJJEH;=HO)G?P)&U0~LDT81 zuIgg5iqmwIcrQP=m`!H{!A^8M4DwB7jdRwFCnF^cg0N~^=6e`IEeGS!d^TOKRy*^V z(Iy*Dy1v)SKmfMeEr5<7BZ#*^S!>4J|_+WfUwi58N?e7XRQHJ4)1^e>pHsm zUGI6H&u|#VquE&2-PQVn`@x&v^wzs~?{VLQz$H<1et8kc>1w^vMuonom1^sHGM`jM z10dX)jtF&Uj}~c&tksCcx+!;$kMq(L>yuXD-FXHvtD4qGNonvOz4a|0`Mr-4M$;s2 zx_+EZl~h%gCrRA2O200ffuNWt?TenX>2(j<5CQ5<)ziB>mvFRmT`<>ozaz>2!uL!h|B^ z2xi7PF-U9lY&y2Ut+p!%5ON43+_fF&$m6tb#CE&2R%b~9F~`_3PTOw42)BJ_q)Cz} z3PSCK)rt~K8J++mrFiQXz5ADb`B#(>AN=6Iukg=q0pLr&FHZ1kIuCs>&=Q{LMYikoOw`39(!fcP|sr!i>}m$Zp$)GV{1VW z_|BQW@1b?m$vlW-M1a*U&&y4o8*7tnL@6Hn#ww9-x0oWY$#$ysaT&+De^#3%{&rojuZTt5E98wDTVpAxN-aOm+#(-LQf1*3Y8`iVQiCc5JdzNEo|NP^SvFXRaxXk zQ9-LbpJIZIb^tJpD0Bt@hbfEV&^hff9}#S=@jOrVgCECz-$3A~$A_jLXQ|ezDD#8E zYs<@3;G-<^E-$Xyp*PA(V--M%dN;1!%<~m;77%dy=nNxjjPe36N&GnA&1y5A?*EG) zd6kC0zWLk#Gl-z)`zJ5oV?hvbw#sv#GGpCnJYKCAR=FrkwwpD@I7~99hagI&(4$eL zrMOz>VHg;r|Qhj!X~ z-t)F^ed_LI_56V3D9KPFICCb~pKz`H%e_8(-5-Du;|xLXtPO)00Oy?QhcOH?;334& zdlv{~tgotWHed8zKbvNlA%>|}YO~u!`IOQ?DH#R=0)P<+qi~d3_Pud-x>z)I3%t`> zVk8J*qpAZgoVRMwogT6$Szn zPyOUuI5Yp?5B?y-;MIp`9Q$#UVGub0w)-kb0$@O07S_YtHy4x%Gxo|tYg9E#fra%x zisG(oobhE-aUmv2WRw}COtYDh(s|7oLzFsekyRLz!8!<#925_NFc1u5W2^@VA7 zjB_oOaVCsHtxVfDlPIX_8aSZjpo~r?nX?WdY_%JdjKUyI;<~AxfA-GfCs#ojBTRI= zOF=V|{14tZ|D1Qf^ABEmRWSD9pL!ee$glXyuUgJ$Qh81^CvsD}G|9`lG0qSca_moM zWK@`lnZrOE=cHUL;_KDkdCY?lA>gdl_iYIA*))M=QFJa zg2`^XisE!SoezV&yt<+U)lF~BczAFOpqqjA|)Q%#+sbCm5XOtX+I1)i_fvK7=E-wz1Y69v)s@T@eg00Tfg3{jH;;q1|Hy%0_w0 z*PAtGaog1qhY%P8gQJ7xYF&(uCXj!_kN(ixV)#$y8@}zka-yGm=J>i8>VbuEsFh???2D~4+9L=&Xxc6clleTa z%gT9cv@VK$6vjamByptVfFRM@Ot^~E$#Qvc_UMV=sFup(a98#Scn?e#L}j_Jnj*=U zeK+ij24c{*?F-L8*R{QpQUoEUTyQFcSZ}u!lVKQG5O4;^LFSW5*EfCN&t|h>kj8l? zq9}B2HL9UIK0PY-TZjnfF{5O&*)?_hOTYB-a4us%+B7){pK*Pr(3cVB+x z0r8Rtp|K!NA_J4EE{#_6=@enOTCEVK&T2|=z?q!xvwCrjuhJ(0X0&%hD(_4m~CWLa2?K=95vH(_6Qj?J8nQ z1C%DyfB4^i>TY5Bs=xBJM@Oe^)mg6yWk%^JO*flemZc21)vma6_xWQHk0nUwC8dPO9j7~&h9EMLX&aA=+BSK(Z_dKAdN5{MUdQ=)&q=B(Y z2k9hDGNtr>xBaZo{>-~a$)k&=Dpu=lb92UPOMl`+pNi?%C*=L#{nwI^3x@8Wt#vo@ zkmYeMb?*S8oCX9X2^o6l0c^Uit{P662t((rcaAgM^@DScGma@4RSzBV9w=iciSTB; zT9u5zgM(vd-KuDum1YzOIXbaLg%>lQ0NE?;Yb&Rn>YN zw3eqw3)OYn>f_@Bt@OUP)pVn{9zOcWhdk-Vk6 z@7q5x3}coCjPd(#Je=k;E`)`utGccm7=>*+00<5b4;_Gn;D7=E;A*vvlJM5)(I340 zz#~i%I6PUdE-sh|gJ=?p;I-FZ2iDB;FbR^wqvcpt(kL1RF~^oAyQ0z7YU>dIebZq^ ztu@ej4`7~W))-GPbcRu}*%m?&iam$s@;Z133A?HYaKXQOb(82tX7+< zuDW*kxu5w|EQ9TPt&Xd@#rkN;^86&kxJG4n#m1Zo39}eEa6f`Q_Dm zSLGqUUTrXA&N-!RAQO5hwKkAoIGaw4@lT#UT`m?$k^-a{ z6IPFH(_qHaFwqVk%;Vj@88z#Z>$5bT{V+%DSg z<=39xxw-rYfB#c`iQfl4`2AUuv{iS#+7N=AQY+jaiRc`OxeP(lY5l_j zR#(?qmO%sN-m&dh7&`jWfyg(E5QH#B2m(ytB#8(n z1cOO{%0@q3?U&Q+pZw%c{yBxbg)4x*;TylnIm=+|Y0xyiv~W3JSm(4Hvow3~=A(my zB?Odl)b|6X6hYvz5g6N1y}H@oxpl)BS5}qOt{<8tjf4>;B;Af%Ea5ZairEhlOInVswTL)L`t1z4p1Q5a3>teZ>a>6_W&Z8%9zP>G62;t!}bJC4cW%*PorJWayGEVv+ zx;Q)MoD)PO(3lW}F%Nx#8B{X>>EOy zR;|{~TYw2M7Q{)6JR66;8zhCKEH=x-gHB5CEfG;w6+swyFkJ7eY8bYzDnW z(C=2ezHJe4gpwdg9K@L7$z-C(mN8mYEka~$YXX7NmJ?LeyJ;MyS#GqA15#?euev0T zu+y@vnBct{vq@ezjn*bh)2_9~N@tw4&{?zITqp5_LR@z}$BeZ`1}cl9ug5x(!L(P^8+9FM?dx#Kem0Ctlb@*loD z45LSM5{8&iJ=B!acf5Fazg;)=035a$K}e%00M@ocA3CFzHrgg>s+3Yv6N-}{-S2jB z9D4vD#sC09U=&W;ZiE1&le9zasGRqptP6|?CakWS*(~!23|)H=$JWYTJLw!o*a2^c zF;DZ^5sht&iZ_qKczSZL?c^&D*VjeYbfYuMSRAsz8b8`T$xwf8{O}|s?M&i-}5zJ z`M><^&%fuJ-uIDD?j!o||Gp1Cxx6fz{v9toC##Fy2%PQKn-$}cx5!)2Yuk1n0@Uh; zb1yXl-mJG;L@{(gJHRPV@?=*QjImu=L4pZmuD4Co1K(Tc0Ym_RU0EVT=JPypWy%4Y z%-%fPDC4py1Q2%RPYJvbBEiTs`x-j^{Ij3-;KA$OW9xL7 zCT$BwJ%n-mHShiApZV!e-thLdU-!*|li&EA-*K4b`83JJjicpjuRM6;%{Lh(6uGw9 zamuHQ#mUj>YE|`v3&Mb6)Q%?LTw8}A$&#e1_a1`ndLxad2t9L{h76Ru3S$4CW z*lnjInm7uT9GDPx z9HNjXX>6c(Yzn#?CITAOeIb zf(ZcxU`s79$`EQXLC(QPkDqw!;y8o=A`%3YUF|nYscDozPIpC>O>);QsulnMAOJ~3 zK~&%@$CKTDl}}UMs`In+e0gHqaeaCH=`TH#l%)t_>l`7XZ%PDl7)R4=YQ1TiPB5ko z2!tTs$Fqf$Ex~MG?~hJTpvT8EgZhJ1FAE6+s`l*Nv7ilHBsW?T?V+HQ2#w$<+W=kN6G*bX+GWK~tkQF%+0 zf(Sux9R|P?q^%uPhZMEO8L%;<30WH z9r`{?Ge%LGrx1g#t@A9eyYXa^@Ao@O!n&!gBT_p`ohNv(Y~MRXJclFpX4K|wG5ja< zUElltQp)w9Z`5Tf0vhEQf~UnEqCTHZZ=Rfd?4SQ`6h}=zLI75)74V*N-VYKJF^oE& z&C8;gWD^9TbgI&Pf3?BD@Bm|qnYGGV&LANaI1HE=w1t>;O|h;tP~Ibbd~|$uxth+W z+PG1U5htStO6x37_uG9Sn9-8(z-n2yT~oEj7zFmWPEVd*t_JU&4ePq$1R84&52j^N zUtOL_rXdU8}0omBnd^1wq(2`Gy4!K<%`AOyf7B&@Qg?baBy7XK9wt9-m)t_FbGH&aifd5acnX zl=fW-AauTGLg;ZYMjy=6%j-rdciru>bm{;aM;S+xlT*67K07^KL~+;-WnHO$9D^_& z`}VSa90b8jpMF=ZufyPUN^Rik;-YKocfaeM#=FhcwjVVio^j@_w_1;WD2n3n^t9<} z=sa}VC^={ioYNLq)rR2&v%os!fYa^prC<7&Uw!k9i&tMeIXZ5uZoS>6Q8bMD%fI^T z{@0)V|JnWWC*-ew|KDiZVYAr);G1r^alGIRI;+Z}@B22-v%{l<&2Eb@5rG(##K1L; z-x-UL|I1(UMVD8rHy=N3+a`)b3vszEAfl8CvOdR;e@&s`WKv+)2K?z(X}oXwr}`FwtMetmv<9q`a2^! z$f#f#V+gP{j&gcceHGrCnsx^>zz@KU^N|_5~yaLellUw0ayy#^BZU zng>E@^XC0GiJ;Hkx&8FB02GMwqtKYL>g)YF5|DGeUR_6V$hg>U3WTBT`e*Ll@c=N6ondj96cqvp zPqL|$g9ySuynlIcFnjp={Va_Rj*iD+Se3P0)nUNA)q)3Q*#QI@Gvj`TF}`*CRHT04a zL@0Z^?fxlz*;jn+*bk5QO`fGu6xK}@M=Tc6cD15$03lqj*Q3@k@_C#JijGf@w6QT7 zE#!AT?b*lIeX-jk;N!`(8+t<6bg}FP83Y^?rmgc{dk;374HvvB>S?}+;>1Ej2847(n!7U2{%=>C1h$+10o1+-&NGGODx-yi^xvk1eoZ2Ddw&1XebCzH%-prl$Z<^Z!DnMlAz^?7!}T=}!rgvj&4gjxDupSb z7>`n8;+)1o7Gt7!o2$R`LqGf@Kl<;#)t>+QzwvJ(D!P7f)+SMeC~Uhi3PhuZ%k%SY zFl{@|=DGJCBLom6go`K)SP})g?>hjIQPMc8dxXw+?%RvDUKddrq?`%B=(4&~S`r`C=HFZeK@}xRMPc?C@k( z?VI_0R=2J5)B@YpV;m(RV+aRth3$x-s@g^%yIQR*u-9i#Lmmy|5Qk`WeZeS9f_M_q z>x;`>SsffMxBDg(QQy^E1X^3psE4p=dqN0u$ZKdZ6r6NTCkGuT$U4w$(X-rnTf;?DzY=lVK!MCKwN*AR47U zI9w_%oouaD)`j_eju6HGw(Z`v!#h4bb&x4p3i9mzH=Z6Iogjj~^8?@akACcvRLl7V zU-&QIzH#Hp`J$_2bah(&(du(?tpvXxm%z+kbdgRPE35@PXP6M$#ZjV$o?tQ>HJ#?guBH@3VGt*bQ8Fl%W=Y?+$0tYQ z*iG^&((-D*C&-qqIWlhcz= zj{iTxI2Q6#Ble(kzLBXf|J-U9Ocw%cDhA6?W8^IKsJ- zW81ZkJ4A`pDhlHXrPw1dmR5xK-+bCMDoXOcDWw6>YR)lXj1Z#qn8xwllN*2V;Pr0o zqksX9$Dwh+Dq|Sqb>GQR#!+5So z5b)kR01>RKS_EMfg~gt;loVA#c_8KZv5$S6bMe6+__zMv z-~BJ&QsIQqap+Huv$AY@sRAAb0UaS|+y3z2NNGEX(_Z#QsoI;9qr?NZt=qnpfk=Qw zgBh)bUEf9r3lB7~b{q!fJaU#2*7Z6R4g%<{#}HfR+OnC?7g9>=OvuRCwuK%kMjoIz zCq2m$E(t#ScFuJ60q;&dq1VGwx-JZ6id6TzcbUj5Bmx9`6B;HlLH z062Dyl7_{CGYnA}hODdx%t=65-3_5&JV-3GB1~-E9^W|G?=}Z197b{XkZK*jrMCY# zsUGRg&<#v}$<^)p4c$}sL6X@-}D6+-e;XMNA z#;pUXy0$7I;n&wI>-{uK`fiYFG}a1Aq9`e&c$s|sawjb=!Z+9a`lu&=llPuG6pfrHMAxeOU&RVPOGtb@~hYl0uq?EG97!l_Y6r<;+b3}>$D!IcLWnTt$hkZTd#Oc0jkO3tf_xZa;KjBm zPHy-pqSoUmf^FqF=eu3A!%p{oAmS)uO;x4S{5@au^&k0}PoZ5joQJ*MXGt2x;kGEO zMU1k=e7@Q3k|Z9ah0cyzy>NWXoIU1Gq7vhfp-ffIR}Wzn|ioHyH@ffx%enx>sDr`Y4wY8wPWEP|pe7{$ng zs%@kBoyB7DSHAu||MQ1G@^&l#1l)gkpJJRQldp7h zgbBrHdOVAQ%mG)|LpF)tc>O`$wJ`<()SzD9y?yKH`Sz>7?i+vhpT2GTB>#+j-8X() zHVGEfJKOE9((|(mK#9j#YnP^JT{o1`s%jRC z9AXeM&RLF}6%2cfo%OrT#lbvFu;QAS-PCfo;-OtFQ-`utg#OA zFznin36UgGQC82~dnQlQkACzQDT^QmN~y(iA*K4PcRcsng{H}B_J*0n&5qeUps z9arnL8`#l$rAN|}fe)R2j|9>$L;KS8uFP{WZr?ctu#yzi8Ab8U?cTNu1 z>#J&894w}j2&W;kYIy$EysgK1mTtDYJfB=VJzJdKn;+c#*zf(qVxC`JuMUkLD- z*zNN98~}fLy}=j}!qO;8qVVkT({8BaIAxSs?067hh@U*U9J>}kpJd4-O{6w;t0GFR z)r>O;Y~6N~bmF~hn?{83ICP;9RaGt)Q)i7*3VFQ@aN(RBHDh>^%^o~>^x2>H`Txgn z{pQ>4_!IN>-}pW**dKKxU0hur&lY%^&GNkI`uSomwdxu7Mh|V9-a9zkRVO!&ce}M$ z9h&4KN>_yrlW@D<@+4}yR%It{TEbD;>1@`t4dlcV7exWZ@uPzo5T3J?Gg071#nw3ra*@xG{~k_XFKtrR7+R~@FP z?dyk+9}5gvT{){?c>bmPk1p4*y&QxQ!{md1^rcG3(l1TV=+Pgkf1$1P6H<#e!FL#YGY(Q8x?- zfH01w9597SYG>;_ORma_AS%MJ8e|%9?+tK9Yum|D1PoE=49>H-?wZ-bk$1+KigRHA z2*YT<-+PauFh;;rPR4GSB%!g^XcNYXHja2;q>`iRok5gHrGemsRz{6s9Pg!v5HiL_ zV*rHv?G9t%u*Nua-dZ`_I9OmOecvzA)Grphy=DAR)o+RVYL|N{Y#1!U9 zm?lwU5DQ{d_eI%p#=W%w0)&wnq#8%r4?+lIwHn&pes_FuFiO>r(mB0dUBzhx5p3($ zW9D>^5hDaEsgXwxnr`SY<$^mk)Cd7LwuB;z!PpOjcNiH6n9({8g6D6}Zl)Fzu!h0I z?XZ3G<%pui;o)L=P!>%Rr{!+%04&Pg>B$L#5F#>;L)X+%oHEL^u?Qe%t+gN)Y`@=! zQIt(54<5dWz0ukt!i?5=o`+#*jKSDg0jsjQaXh_u_nqs_iUl;zXT|DLYV~FR%Gdtl z&%NbkVxRk$zTl-7?)~y_{92Msp1%I-VMg~7j-zw{O!H|sjFghHE+@$pL1!&<-a!Y$ zFjU$Qg15U;P@=t8Qmdw&W;v!f2%^LoHFkPb!~$v5uBjMfLr@{?M+CEOa((@V z@-`AdS+&|2CnXITBY14aFpjmCA{2LS-dS%p5c#^OLV=VXF`{bhodcYOO7@ze0Xg!p&9kjf6 zas#J4P7>?Q(>EW#)$;!Z|IvT&!>_#Z#%F%o3qSUI{|tC=b-lfF=k)aUyQba25m@kvO1-pMKX`@XBj%BynPatDC`ilc$Hxc5RG{Cox61 zDz}6X2XS3ifO_Ce({|Z(8VBThvupdeyv9>%B?5v0h?1=D`sp;c(CzkD0S}E*Q5cCp zG(*b+(zU&D7C?{$sick(I`m@@XUdFG7;d)P=}8=gU_Rwf&I{uRg3@^_9pHkEqvBB@ zyKb>qrb+UoJ@d+iBFM9(XnR5!MYxll>_^}MCX^BAtN~tnsGQ>%5&)$2etq?(wa~~B zkqBD%+RLvU-#E%Ac`Rt#=(er22AqSVqf?48r>Lj~0DY3Ag7dEH2Pqc^^RDkHB}Jp1 z8wYJ;AzpgvZnJvob@wCx;MKQU_$S18w?2P(bn_HAqUG@Hv-e(q?Nt_qO+6|lF@wg) zgXPindd-74Nz%R_`nHod4SjJO&W)sQKX>-eqU96 zH$d;RJnh?dmL^T5tk*`FzVGIXW9^h2drncbJk~|)f%i}$h&{q>KL#SGt9m+{8Vl1{ zG_|PPj&U+{-E0!BcV!TSlo^abT{n|S)b)dh0yzc!I5yo2pL0)|@lk;c%qDw(ZgB>1K5ig+jwXJCM!h#pa509yy}{aKQJSLLMQ^rbi2f3TurVIz}kw zkq3~6(J0l?Nyd4&+iX=Y0kr$7j-v=c8i{a_qu^2B^^}muPp_W2b68ewQ`KYFLr9Ba zfBV_nei%k&vOMkO0G%<`e(6_z^)LPWr^>a?$A9-@v-v??6#M;Fa4J1Q7!yi@AUs+e zJUu_3%xAZv)2`cwf+e{KFoeEWLrDO{ln-5hIt?o|K6f+QtgFZC3VCFmG0J99rM+>GhLG;~)to{iv?4uBFoXBsn-<$Uy-B!Z6IUY2Q`zMb>t*E9>K<<#w~t)&_BW zz1il|2|}W;n(lm4l2iXk68gNhs#?bT*%!o!hD$G{8tCAOHQ| zV-yj>-)`TZm|;-a;T$sQl+o5eIiT7SGIDR9OdAXbA@K<);EsULb>mIZ}Wxju{%Kmhbn z(GqoQ^ZzvM5Fb5P{plM^S?5_@4K^?;}6`saweWeShr-R;y~a*>`O_s$S|r zcKYz>&;xsQxee1Gh{L9+tn=1b$z+m7@gysD`=J{#v=|w$T^fOm<+ zsI@*26!5UqZWd<*cgnab8zad4cp%5nrpJ$%}WFFt+xWR&(ZKI5fVUb|m66=!@got8~| z>(= z@ou$t!1m*Cd9|HQXLVCwtuIfGZ?)2GcMXP+COPlhWd^S2$lRo}OPR?G7gNx#Q(v(D|-Ggh9;aS-jqC z8DnSH*N4jkW57p$`B#}>jNxw7gy6Pqcs@xcaj~m-0E_*eU<3dZLNH2d(}++w4WcMa zqIkRCy!z_vFTHU0_}%Zy^ZY~q5+HcVzIOyzuk`iSTMm=T~D)| zQF3_l!qvs)XT0>{qlZuXz76vEeznB}CSi~y$#yklvx)awt1iwCh=|8gc6~25&Fo+a z5lB3|xVR{GrPh*jDjSt0X+QP^GRkRP*N7q(aAl+%b&^eH(|K8zHZ;znZs?tdkWwiJ zXMuIz0|z0PEoZA(1;^Pm>)MXeNJ%yHoioZb(u zdTE&8#uRPJmQU+y4*}}h9wTyecy#}b*W*wyPNkBJ;?cNq?E794 zN_1}+2?*l|AU!HB=x(#O5JW-btgD-v@j!b+A>@eiAnclw5~i&qm=Hn`MpjATT)E#% zV_=*FVPFBq6jRJ0NuufW;_-v`f5&%y=*R!Nw@x{g;?4j7AOJ~3K~(0SjyFYJMk#Ho z9&&n^XPfn=9hFl0@zW;(r-azmdS|`Q;^6q?WP1e=VYhCa9?auyrMteZ%2q2wDUk?! z?*kz)rlXOn+6zJZwpTp?-a!ww>L_Oc52P}EuYk3aNn)(F-kMfYjH7^4ij`Erc_rI) zk|`srrp%($o0^_e&^R|iWRfRUSq+22n8s0vAabn*1P}r#re(38q~Rn_ z!ho0iVzpW`5$JAUF$4tdHdg^bjB~_74<#m8N!9lqAc%{IIoyw>RY*(aJZQS{V0o%k z;~dPBWK|UhlbJS+ZMVdlMQD!>mu2N3HV}v`nD?@y&dnyc9O310G> zBLG9wAr^k@cVGUV?|T3Bhd$l(c{p`=oJhNc~0h5YIB&C3%fWZ)gO$be^CQ)f3`l3x$N>f#;NLBSk ztF);Sp|(j#LRB>>345s%;;?$b9?#gGnP-3Q^|xL7a_)UWl?V$*4R{!T{)Er>&8g!! zkK@1yB8FIO#@<Zt&?J#%J)A7(q3=+_>!EKg1%Q~~E-x-IA_NhhMLq!Fp_C9| z!6;*l6lJN5Pb7x{P)G)EMI^1WFp#2Y5yDI)f*NCV(KOZvYn|ZiXf3b*TO z$_PV@auz}ez-N=VDmzagldNu=aqO?3T+1XsFkDp)0L}*=%h&-p_6k$t0O4r@F!CN& z)nSrEm=FMiRzp!>F(?2aV}g6F%Cpt+$!amHJO8nd{brJ-+Ia}E2VV6$$ue)CjKzbe zPfw1oA%b03AO!!Nzwj6S*5CLW@0|aC!AF1Xfn;Gr*E) zX&P1dHOj6_jdkMshv^8Dgn!9Xrxr%o0FZ#uxIAaV6QP4-loH87ZEDjfr0^57uC**F zAjmM#>fzVV+BQNt!tGfjrNO1)!jW2VM@b_E zNKQq8T=B4?)yMW)lnB@o&@D#aFOa@FGofu}kiDnjsPrCYKFa6!lzkizMEMB*9-H%! zk;t`jwrVRImZkMPoZjS7n*qGAbc|Os5!XGPTphMN-)?b*KjD|fTkYpz`pA;2-gr#{ zCLuV%7jb$u0f9`}|ku#a2=~8r2!bbY0VV zbkOa9?eK875Mn)Z%#{c_$(&FoOQ#k%i8v>G@MFPk1Kn2sU!-GJ2@q4}qF7$(8Sw^Q ztCH^LT3x?n&}*BLtxXqBi3}DS**qQ%>7^T+RQ`4GV}XQjZ&>b0G173yI|WpXq{xn*yBiPONt><oL>|$(y13(ij`; z!^IYXQUY&rI&3m3W!mRs?~}>y%emuvgG3hHUWZQ%^DW}+iV-2+fRndEWFOSfE=^Jq z$za*a<4Q_&|w9DS9DlP*uto|z-J%39a1 zsnpbzL7#yp`kfX}2r`b2=K3e_naYH6*k=r>9#-;%IA9BJcRcsjiYfxai7}LHAjooh zH2iuqNr&TP&)F#L1s^XT0XPvD*6oshJ_MF!hVK2724t7fZmAJ5!&+K3&InF(eQYG& zk57v}j(iDW&gXisSzSc}_&Ycld!GO8Bi9Eb$*paqXrZy3*7!`Br)}f|+DP#4KudL2 z8%1D}2W?m#x!lo(^+Rw%o0O<|()O1$ZoK?G!p)mQFJDjJ&kCMY#11bqZmf0fV_}`Y zt1{}aH(h@Bn9!5Z_Jx^H+WVQN5azgoIq#VqGse6>zcL1uLf2<$(FzMq0;{u|+<01G z>w<5UzBo{M%}jc*8Eqg|oa1By!|B=g;bjt&IAU}I7kclSwiDSNoANpBY2QSP3(p8> zKy4Rp6Rkn*%a7ReNm~J*u$8L_mN0(H>syql#2}|>Op9wyKY18TBj>-*zIx47+?qhsQmT3@#54dSnvQBO-B^Zd{WiAzpeH7C>{>mVGIE104#BA-dT}+s-$`{eR*J$OrCaZNT z4M{>5xm7bt1c~NpBy4}4+-z+xVtaqoU~!u}+R<{q601{bc@rpgvx(AVy1l}+-HS8# zxQol%|D^6N25ne==VT8@M&F**@AZrmNw0aQdlx<+mk7D$&zKC5=2rl%#RqlreQX@X z6v?IIs};A+*ORY^Yi?KNu2Z96g~<;m{4k|bcd^rh^KTmv8r4FyCgmSImp;Ug+A~bK z)I6!@w^w8Pgma8pLT7vx)>~T|W;W}%fCo3nO=DHQ+F1kP8Yw65KZ_8JRmFAC+X1Ls2-AG!Xni0(<3a$+(PnY6>V@tsTj8aKD@FMvO5o5L=&yh1)9+AdoM3Ve)&BaY`k)V^>> z*e=a=xB^%qU2Lk6U}P2>rHZ2O!ek&H2FL!E2?M_^tmp5A8Dc195xU&0N!rV=!uwJq zn|#wA_k|C${e*RTXtcMcbV8PIOG7*$tr-@VB(J=2iK`^ZbKDc>(z&|5D&dS7k&{Ex zeJsCEF@4y8S!vgKivR0_3xlbV`)v98M1VenhGRWUN^CjfRgZi*C9X%DnR#n-N*~5+o5cW+1_(2KIwYTmekP*1-$a?tg@Wn_A}q zpmDa-U^-|NFA&V^p}y=y3t=ntQ`13a*4Z;8Si0!(sT`YEqWn9rsx0!Z_@BFZC!Ui*R z0Q~SDOjn+etC06&1|j+;!s_UBbv%!^^FpyYC?hsI{aKa^u6V>5xQ8d*JfYjh;gy{s zY!#uN^2-?QBhmfgxYPKedFVV-ti+AAgSmLMGEX;(a z0My-?a~_Azj}-!BdA~a7PlhS1_ySpJL)O>v+e;(j9HPyrSjf)#H7yLoC~3}Z_##2w0!Wd3QPp}M(BImsk*@%06j98Vb7ZTk2cgx!R%C!Y9nq4? zV;#_H!SzaWR_DF#4<3!|KxIos2l@x zywdo>q7W{vkleyWK=w;C(91PPHARuL^K@|5eeq}T&ir;argZt}E)>U6INa=5i@hP2 z6BfY7{t*p0`6omUWC2R! zO2vlUf#iD|gr7Fgd=*Y3{t2OGYvkuN_4u!)={rz>LP_1L*u%NGe6)IE>HK-xDvlm^ z*d%qibsDfI2kV559nanU7&}%=D#Kn0Qg*eLG^veqshmek$iRTYIsK&4>%j}SV2c9q znR1&SILdG}Td9V*+41AzFOLKe%7cxG(KxWeaPHA7K5lvsw^Fi5u}B>|t2m^zLOrKA2$|JVgLa44c`_8Q&~1YMBV8XBMwA-&PG9=- zx8D-w$leAY%$G_XP9FO;O-s{7;RVq1j#b;2|DluO>c?@b=U=AuMtVS(vkN zd&d((XAh@ll9u9v^UE~5pQmhqwYV=gw!MV1&w`bjSKtr3%X%fVtER>u2^khD^m#8R zr2sH21!?FGG%|eOqiY=W#dnk$y7~#uK5eXdT!g(^7LnFZTO8-+#?0|7n(skv482HY zq__sxa8@QW-3@#p5*LaG>}gc;V1Y!n(zbHZavzM~$NK#;_uE8@o1U>Cql&*v*mziO zOpG4}jD9OBgY{n?jyCgaS*Bb){l{Nf-ttBB<@A@KI>&Uvm4!yw7fs5){b5{+Z)WE& z8sGW3GgUsl>&wQ0QjK1L<+C&@OZ}(Qo{{S72a+au&66F^rH%h409NF&ZNbP%<(O_@ z^I^Zda~aP1ZK=-f*x&ZClCVevbx~pGpeU|bk%X(pV2^w6;QIaR5R1n?3)*n#-(*&d z*}^&CV$VJgsXhC_5tk+*qVEw7K{o}hWrS`mKECJ6r+L&m>YeV>-UENSUcPQ!1t-9J z?wV`*S!kRm@6G5B(-#tv3JZbqVtXH^?TmOf;?(tQP^z4 z>90TN#DWM}EM?2&s8!6T7bga57)2#A1xJ0aQz#Afr>*(j7o1)teM!!lxpWEGn{S~n zxi))%aB!3?>tNDjW5!n_!7KW0;aW+bq~T^E_Or?SsYLM2?%Vbj@lJ?7Q#}U=EaQV- z?(n@m#5fF}PPA6uoR|F8XCT1nWoeWM;Ewttx&adJkA8g^cf?2oT&oqyxF&~AAdq0@ zNF_?9z!%nkbKaOYv~#496;dNe9-qFI{{8N;MXtG3+?7>Y3K0fz{C&i&VzV@xLxZ!< zD1Ge6iXl%jz`mZKuSg&qM3a+C(6T6`nHMC>@hR=oIZGTTJh|+!Caell_Gh&pts^z2(q*BI>mw8iC7 zi{{;fo21ZNPL%LU#P%X~OPG)(9IQCqQKwh>$J_iW>r<2#?9OxGb2@faATV+ah< z3wB#-Q~A;dne}O1V63O(KWp9NNa5eKZqK{|FiHlQru$3_A_Nkx^nJ`M-mYISA+=Lf zQ#9+)rAaKLX-A74ZNV7ZcRyV}j~)r4SR+@gEUME}0hhM2kQ`Tv>oKzG+I- zSlLy1$9B1}!9vR)E&S}3A7AtbSi^3bLTN`|DEr$>31e!&D#C9uSuF)> zWT#@P$6kDKaiRQcN@nKNCN0Kb>3Zl^2{&9C>sT$`(fac>A)U~ zJEWL6^MBCSf6WcAU5cv04us%l55E_blT%Nv1r-%j!2b}dG!K~Ch`{_18jyy(iiext zGwEb$+xkzQX^Ov|^cunWWw`|9>Jaw0BXJLZ&l*wDITztjFdx>EVC4u`>8EoH@&ezt z!w^ye3e7n9Aehj;d-DU#0M; z70EEJSUTEyc<=a2Rm8hUE#&1}Z+!!BFQ)L>%je-Z1u=vQMB1y|$G;Bm>3ZOR=qJVr zQBkP4f%E+WnsU?TktSqxPts zIor8%r16UazedOe_X8OK%eQ<=>&DE@`TTtMwwh~uK1@(eme?K&#VhSmV>|TK69S3C zQ+BP#{qppxQEA!>Czx-b0stU925ueZnY-@9P}ld41kV!nQ&}Kyvvm&_32z|8tt~Cp z$Vs4*bU8>Uh-G8AumINAZN~#z<ZFd=bQo!-F1!6dx}vCS{Zyf7pTGEjw0n4ED^tMndiRTQV<6S!pyB(Ywj42r^h|osX>cRIipE&Adk;`W}OqQ%yTlbjP zf2giE&T#>{-@YX-J^(x!=-^BBBDc>E)2WO;Piv=igNeZ4?xo*caqw4)JGB)6fEn6* z=^YCmE6NZRH9^Si1*1_<;6OXlD9A}Qs?#gLFXy9^6&ECQNhT{J|SjrQ7^G>Pfkd(khIzn!@ zxAAr13Zz?xDA!<`4H$4N`~ckYRhi`|`bzi1tft--XPVT|G}6qKv6F%LL# zvB^|H_DCwVGT*NVrXf|N=aa(%uA?n)7otcNbb{$o<1(iJ$|iRmCx4>>AKGFaE@tqpJcQ|}+*_5+kVa5-iw)-M`$u{trdw|RFl>k2{*^^V-6q(tB;-WP=k2Fe zdpsm=zIz+}mxQ7T(3%;#hlO0v%Xzcaf_HKH+>B_p*H@l~)iX{m4GjhcV!Y3=qoN6! zUysG7=l`2lPhBUGgnu!tz;-kcl{-&_UKC2*X*|5g54qsG1-%u@E+`V%B3$(G$>p@T zZm{t8_2f-m(`rhiE+@7BWsFCexjtA0VZr4n?T|cqRVn^vO=c!Ud|XzMKLm#vswP|8e=K;B=n^{pmuamV)g+FDA6D;7OmUJm}( z;ZiI_(*yvz^03o@Be^QG@g}$c%VoKfuhVK6~$#y-((Z0>3uF=>#{;)#-lZMb;ddb@bCJMZ2 zszRQ?y_a8SLjIQpu<}2ic^BYJqZZfkKIm-iGEms3)w86SEpX?M_Y;2s@Y|uSdXm>i zy!x=TewIN_M(b(e88XAy)SzcxqIQ|uL}2+aR*H%ojZ(8^0L6S+OiG$1@rTh#kaV@g zi*h9Ckmzd>VR8`f$9%sfXIxS4-r00}N?)kV?<@BZOvTUVD@HF!x?8?Y^;dItQL#3vLzXnW>na-VVYlj$xVlw2^+k8G_9@VM^|ko*~pnIDk4 zyb5TTnh~WSv?*V7v)C6wQIx@Lb@bu{=7jaL*nM=h!_$wa+0^SUce`&(w}AAo1gyZ_ z1_ngDz#}cM`SZQ;ax1n}9(zRDgr34vC06x=kWgl@pZX3$jD{VU@1_)f$rj~D z5~!Vr*hQ^ns?L(84%S2i0yZm;V-&Ru5-uG&uO?Q+fp@6AbNrp5#+2}LG^R>eA^7em zrzXsrH8%8M`Sw`qvh!}#Z{ZfZirY63r076#r>6v*rJmqM;q9HY#b~h3asI{ z!(eaSp+=FjPdM#+8{!ARQ`C8@1}heJ&xLK)H@NDTa?8kjA*s31)3r?Wl>>#RL$ZHl z1iO~Vo^Sj+J3UPuuH|inzh3DIYVnxaCGWRxmrQF#54%c!G298;huP0PfA-sASB!Lu zr_th`Y#Elvd4ItaVkF4X8P<759eSQHYwlcb&C0XuJ0P6YQfkn;WU^dATNhnwFfYr2 zDRYC<4^&xH%q++qZnx9oHge%Lo{a2+C#zm2)6ep0WPqO%1Jdf>hzLF6mGU7a*$0}JCW^UN_qgR@F;-W5jqRv;SLqU@l z9{PfeWwm5Z^>AxN_TrA`uelvvF4}3a`;8fObKASS)-~cS^Sh;J9^AB*YmiO9FhzDh zZt_9uKpL|eh#hnj7~1dQCbphK24;+lv!W?ldhO-u z`+%DYxZLd9{s(&k{U!d%bGrhS@(p`38?@LIbY#<+uFe^5+j?a!q0Xu(VFwu+h&7^O_`teWm8j)JAUh}`97zv>FYBw<&veG2ugwd*QpraTVEwh`Q~ zXl+18@jIj`d(@t$`!$vsP~CBJlzqNzPdes+#%=b)q>1~ux8@~Bt%+F98bxRn7DhH6 z+IWx4A(UDC7rfWIKIkRV6W<-I1?Vi^fhiJNCyH6LXcDdFNpv`|r*x z(T+Tdm916BfKl2(v=V(O8B3Q)9bzoHgGuSpyEzIoDL6W4VlGY#33|Rm5YCqP48?`< z7PMI)tDz0|M6ScmkYAL46;uG%XGA~~R;^+pB9GyOSV#)QAGc8@vEeAPHI<*^*%;Gn z2&H8Y<(ItZrtnwhYs$u9%zpCt1tNYmR+;->+VxzdI&2z~p;buRMkfDl@8Yxk=(zlI zIY(FOA(Ur9JF)H->f`AK>Q&!TSBi}QoyfhW`(mpC_+VuXcidLpp#=VEXiu{iu{a5y zee#%$Uz(n7clSo`^!JFx z5a&l))0iHB!^Ow&|5Ce2e9d`;Vyx9W3PLh}JBtD%Ea^D4K_B?TWqz=bnvKC+chbF7 zp@d*tTzAqB)+~89=(v0e##1Cdzyq)4k8b{awe(FJ>WKK>nn>wXUkqmj76xrU{hbj- zrz8t44u6^NlLYXbsi-nLH`rXS`VmkBEOmVTz^KaI>fhtki+7tD<^2_It%9S8kI{2^ zm-(HzgZncvhtu;lZ{hig&YRVT(Y2C`E-8W%X?6=!Dy(<_ru#K#KR4c;6851BaO79G zrCJ-?-Ne^wv(Amr_?fD)P&o|D5>)>Nt|aVU6>p8*9dE2m4kwmOdEl$o?pN0E+Oeh~*r)aFJE);w93CzG3ZrZkRBOysCTd;#ogBc-tsp@T2g^_WUCp_DZ}Li= zK>^pHuqbOc4h#n!$VfBAKI#F&n$2HSSNY0KdukNIgzPBUYo455UBD6xOTO2+%=_92 zeSv513FcX=O?@NgH_FvKBF0aq+)b#p2ZElw^x|g2pj~vL#<`gkD5+ToC(F@fB>Lhx z2Qhwo;|xOYP^^R0GU0xQG<2@j>-<0@*FiJnjgntpuK6R^+nbydo6bWKPTKcrRpn1?{F|aFwc-rok=f;=-dR7vMaRGiX3R<#&Jm5Sd(BNP z+haMA@us;JPz%Y&y#QQ=7TBofpGbJ;Xy7p$e~+fnOy%hZlVQ5Pyj@7t7Jy60km7{H zHsPmo!e4A3&*$$Q@h~+Ig8Kz@kXj!_6pXWF=;VVqN(1Wgt_0(ni}XEXAVF7aG{->e zG&XJ)2%aFuQ1$A{NQoG3EmY>x|8dwMDgv5_1}i$hAU9VPQAzFC8u`k6;F%_}`;{Vi zna*`pP&Ku!ibU;~Eo;1DLqxBw8Vm~XVmvo1Jy~If&Lpa;pb~sM*=9J0N9X8-By==P`?{inXvK_ImYyh#!e8F%y}vzoF; z)%nw}(f(<#8nt7UH*J>9z44brthhgR(=X{#Xjj8z_fKUiu!l!g zmHv}w#bQLycEaCv`9HH2+D@4HsOZUDPyd2Z`8s!Y-C7m;2427#Q(5=^oCnTO(3n4sc#um@Gj$ENg8nHZ#fCh&g#?q$94 z_w|XgitXB}*;!g2XR}tZpPmvNu=uDtMj2@?Ve-jLncdb7vKg(R7Po&b_Cnd(xcP%w zdE%^yqA`7C{YE5vN~`6y3^ra8wMvU!Y=gB<<;(;?72VGh$O!QPKSn1R0MI;5%94mT zJB43pJP~ToCdgdh1-bg)kK#*16x5uvH8_!(WjhZx)0m&XY!4kCTl2=(zx@XbJw7?LYWo9&?bj|fD*vAJ05g} z&NJadmrO_U^Ku{sY48U*x5O!8^z=u${RCQC{y5Zpi}wos4sn1)^jkBw(N)l0drsYc zQ*>}KnbosY)eeKI0-@Xgt`cUKg935rK?_A{z}TX=BjI#IVeQp^JYUH6XkL8bZ;pIA zdXBYkp$=>0|JhO6&X^F1vnxBQLtoB2&GtLWgWhh(m8wjfK%&CN*Qb$28SC{GCppgL zuEmspDf=Q*Ix6`G(3d2s5kiTci7Uzgw|ODp%h!-!=&GmM0K{s`7IP$6ddD1on=aYG#_G}P&prjN*&?e()YPqk7kNQFF$)?SF5LW-T69 zW)##&-PcJ;eW|Wz89O^Wt6U%FX0wj^hZ)P$pbin2)0H%x`KS{a_WA)z;OBp5X6_kU zPngOU?He+|pL`Y}gKrr|-_2$q(N>XWot&9Tj8sp+){s?Ni;%myx`%OHP{Hs4co$DR zVeych=jP9a($Y;d8y$!Yg-;3wsboE=j06V@!$>KC!BSJVP)J_i&xsZ$F_r?zvDmpe zuw*M*GVa3qXNa$FoHz*t#GTja-{cfm06QUj0GP|apJ2M?3%%*Qt6p+F2LL=8=5$vO z=R5s3LFwP!c*=P{S*LK|(g3b(7&-S?Wwvza$;08qQ4>on^9GkW1EFIM{sW`TgA--`vh2#jntNsoOF4ppCl6-Ohd;t5$~`_HE)P zXvDCxy!Hr$fx&A@JTPF0s}2SFL{YeZm9C8_)rEgg{$mo@_~MVH!Ew-(JtP1L`mDF5 z4K;6kYEwb~3J8`P0%~&2xd{WKV%{klNx_k=D+J_46~kO9v>6#)g|!v+uRK#6E7P>q zg&E=&51pLgk~CzIl8;x<-kpPwfD z%QNKi0F#8LXsDJ|)(~AH?7e%PN*^C4Pt{veHe6;83O#$5N3bMMNyJ-!s|+TGNW<$H zX@{feMl4U*?9n{y_-5u$Y#vea$>ur&r$ED(?Q+OEQNvP>4d z-F$;;JLmU&PY(~Ns2Nr06x!&Y^ibN_?p|}L6ILEO9!(_O2o#U+TvQH66U!y>k>Rhr zN3lLWjWH}Yi02xcO=8NUDAcf4HyMB}@bv(IjS}MzaB5V6}d|tz$u7n5gL=O~BN%GY|=zYd7(6e9i z2;TI*@59G0;;HBTo;a#0FTB!GY;s>-+$G0a1D7v3JI5fO)h6?Kmv3%@DFzMN0-CCb zTtBw_>)1{T>hHH#0{I{RMQ>seE)=a?gJ9dtsL^Q|4?iOg1c}CFgV=y4k8id$q$Rb` zzlP~tVT*+&8I};;U6o{@uHR6p2<$gXVF~9x;st$Si7ac0O--ZnY?H)~;pa|!Qr4mf z)>hlGKOiP~6B}dDn&O!VoiNspyAC;Fd}G%SOoCyfeLsysi5Glny5;!;Pi9Q2anc+D zYQUxY1@-dL*xgpf#GfUi&U+&6e#M^v*%UTa?&oaOqy!f$hjPj4eWr?Dxp(OPSZmn2tJhf9=dQ(uV{(^fq7GIb(r zCY`28qQjs>-S4==870DOq{t)imtGIjIoR(~+NJT^d~V2ps?YY!xxRt?nc!ebtz$bq zmdC2pU*dfvagU{*sK%Qn9On3XBG~;DyD%m;4Y-)WURXMORO@q{#VM+X&i@2n9~uS2 z()Pk+KwNcn8OJ*vc>V~ zE!z)Jexw$Xzem*(sSLvV@FP5{IVx@bQoXMw3PAN{==+}#a&37;Wy zG5gB!-#S#rKQb5L&iVzF`fp-?+_x9^1&F)-sLTP;ZHZ%zh4Rm6lQge@Wo;JOM$>dq z^D0!>GZWXF`{6&?x7&@ye*T3_HfQfbMz7w~UDxdh`k=VWhIn;>Xb5eTS!0cgTDWzz zrRgtE)*l7Rg9#e;>$p6vg|LXr+@nL#!<;C zOVuM~y8m^2=k6B=LD*F_eRT06ckJDBK7hO!b%q*hP+yBOv3|}mc+Y}rU~jLwZM@&t zKOgqe9$_!KuI+;;5!=a+P@U4=*LB|H-Q$9DL~H&o(PeIvYzj-@kA#ku?=AK2 z%<0$jOTly)W+WkCE$qPKXC|JzscZ4n{PkaZGXBKWKf^5sHjj^3$@vf3YcoDm0U1z6 zi)z*FL6b>N(yMpkm;Dx(363d*U1b&INpGxZKA%E|I(Ec%^Zg=a!ntEpfGls}1!>Ze zX=%pUD5IShAG_Y_)6`Y%B+|xjI+V&S3#y+_tgb_C?F={(!ew`VLwA%yH$rc)o!UKg zrAymR%i_4ZE0d1XCHMOoT8HCtZU2y9Bc3E~vhBviwx`jLWvnY?!7AS=gm!}h|P zkxfN!|2&C&1DLtF6QZR7SfeRx%KpCF^DDuaq4JHkyyjT-`ShKoaaJX+pXq2*(j$g}k{ z+6Mg*rYHV}1inxTy!SXm8WH7_KB${)yPC*Y4m^(qby_WwF5g9W z9#iv41qAq>5=q?-a$+rQ_#6S!Jrl#x0) zul6|LF^F`cssfe-=}tggnR}8}G~r(DH_*f|N|N0|qhCM1i1Rp)w{*m)v;7k6&W`_2 z`KgRDxeedIPP}s@L*K>Pdmmq45f*5oE`*SLzIXj_ud!#bE5eXYMAa<)v)`464?qSE zreVoKE|m%8@=Xgm5+w`I6X45G9W6E6YXQOn&-W$7S`lMWnqmAMd)Lefbue+!5e(PU z)9uTxQP@!Y@J=cwLNj<<7kCwVP|h?J{|kF%lcxauBk}WHi0{v3_xX~?ptC}`JvnG`C>I+t~162mri6}>h;O}l4wX`733pwDkae7F(Bs?ewE3l5MgnJ-KH|AJ zJI5R}nk?lEo8x$HOb!U#0d)G}dynMME$1GNmLE_ih=*w-1M8|@bNnpzb&+^VbiSu;Cva?e_@tfWSLLZ7vG=?xe|#Z;dP5{@syu>ixOCX z=X+njNgDE&mI$R*aX(Ib%9q};iwwz1^9FfiXgp+CHuMY&<-xZ8ymr_R4)8zb79>cJ z!d%Pu#Ez4NMyCsn|o)bpVNRZIHNLW%* zl3(_#XWdnku&+`lrT4qbSJ_gx>W#OW$DDT;n^)$#il@IL;T^}QK*zo$atb0x`;oSb zqj=4{yuG2b?JE+3z9{9@-zIxt5?1_5Yc=46stMZ93~WC`1$v51CYID7k^NTm0g$)& z2Po*3D2+1-C69WM<{$#>)H3@rXlLtqdPpB8o?Y{*JkIRFD=2e93#zl0Ry+Wx?0mG+ zim8Pv_xuWEm*9v@_wlL!6`qV8F4_Hv!Qh%7@g65g&MWzBan+$ka;vrlgXp@O=+L#X z+YyWVWMQ$SNg4&osT`&K{YC0>n!bZ=uj7;3O@Aty8p&LRMW{c7qBh~n@R9U)?Z~-7 zPjg}QEG7B1_8QW#ey^Vv*p!$+ORyrL{|<2&xLJjp=>gk_y@rN{ri$^enjJYSr*{P_raT6|W=sklHH-kVt>v#6#AWudX#wbW13Z*O0WNWMqW zb_z&kva5Ld`d1OrZK@cMd#0TEoSp@a;e9lZuqsPRBxf$kzU>sGjxu&Amsj`L&0ZXp zR4+Uo70r8~!myvMXc-QT`UMXbwit1(qrWyDv=SN?4rWsP8Pc;4bUZXBiJ5w!WXZuz6AI?=WvTt-pSc+6 z(ly)4G1q%ve*)-kpXcpK~jY(>!)~o+)!bOW5~)A^+Q?>4h@@+V{s;jX(0&rY8eQ$y&3ydybqH z+hczLa$Wws<*Mq^5Cpr`kY~u|5B>c!djfGpRW*pRj%Pakmv1#?2D;gBM5ts5`?|8| zd?|pz2gmqWzW#~5nzpzOPwQ}Nc~h6velvs?4!J!X+}`%RWsdi?yMCH?Il_0}9?Jb3 zuj5|xF8RUDVBIl{N{Kr>pykEFErfc~2GHULi2Sb?a>5M04J+FIIv{&cTk#GrX`ktA ze$De{ceU~R0!$;i<6%^D=skJQ?$zq^xbQvu%G1og8h%NQLMZ5)<%sp>qRU4-c5b;H z9DTk7;5sYZ&tuH^qQHCowu{bSh>?*|9SvludCZh6zEoYkDo+HSZN2g}Q}m2smd=d) z1PP$~$Wpv|=6gG1qG=v{YZGZ1^EaLXdw;Zi-@p}@DwrU9h?5dXNCjW*-uiJPmEu=d zXDDqG9?Y~#U1RQ-H18Yk&w3Ld1Z^aRpaKkE5frX%p&h!iLKxc4M}6yzM|K)Jo0ptl zRgrJ@!q`+~Jd5i8!Ufdi`;aoFUos!n#qYdusNW@`RIE#jhqlZM>Ce3|h%Z5^U-N)^ zVr;qx$CCik6knBM=)Y^ByUrJc9paA5l}dD7^9tQ5u- zO^+oOIHP#L32MRJs4#ta^~zoDs>dp z*zlYpbJ|_-V!(+<>wdnRG!phD=;s=nlu6QkS*&eXRIoIyzG!M{_NS_viIJ)OWEB(o zofk046-hG?|BarI{d&&jZuhoSMp@JuXeH>4%DRsBU+{sCRLx$u4h+}rsOJ-5ZVNLQ zKl>yNECqmp`2wi7F)H8m2S7w!*t5ND%b8ONoVU9&trq#D{Fs$9?Tr}*cR2rk@|jSs zj;Okh^K0mK*7MP4&c)N?fuOJr7s7in08IXn995)hOn_Q`BMUB3@7-MP1NL z_Fk{c>0O{^=k0mO754Tv?|zr*8f9@I6?&N0J4SSd53t5F?fWhdlmEASLj?%@A)0Tc zTQ!?^k*?WxilYC2`ol(vEI5*~gw>+@HLqdHBNnjmVi>f5=7~)&RBO^e|0z(`5!2oa z3J3#tD;g15={G1mu`(fo+59gH5XV=IYCl)~GFnC6tE@5{!ORKr|BtItam@a8<*Xuo zBHoAhO$(#;4&#psPG;gZ!hlQ*CZ(Phm7Yf^Q9yJMPU+xyArtWfv|K*xy zn=Y>wZ*FVh_jOW@;s*iGyR1jtoXv`QH@5YhXxX{D`V7C7cB=`&@m=j^jZ}#NRrA3??lwz75xcwqRiy*D`BERlY(x&cG!sAp za*&(tizKv~`7?!hm&Ee{^d7RYW$5En8y`{s{67+LMN-NbXjTyk{=~EynhZD@{F9C3>OZ&NOxMU`)B({jL0(#*5rhxL^SN*+gO%UA+&1I7+-9b0X1eiE z55^%CMNb~thXB>p7=B5(K#ZJo!;CR~>5F=#(c+lFaAQ?`@{l7${I?&@=t=I1P8($% zVLJyqKI$fjk%eUWXz(RlPtIV;opx6diJ5S;?fEx_5* ztWS2{mfGl7yBF4$4u{D7p84S@9P{tq}NUbQ!7CGRC;7DVCkQy7S{4ZD{T$@N+87jSY zTiM;mva#d(viJ5@;VYZCh-$0nyxUiS07%J;=MDA8>p1Qo7peX$q>&n^ga+FxBO(oQ zi~guh;+sY56cr&^OqV3{XFBLL`ev&@B-*PaobtelEz|v^gfS zUMLi)U8tXqY<+_Y^Z${xygL-Ki%%)hb|22)64?5pNi2rtA-=@-aPJ;;s@b|^P`La{k5KwEg zCD9HqEZ{ypOap&?TN4T*-#uxmNyGF;CoMRFAVeq?$009lgUaOlEH?X_E#DR;;rqX# zH+grs;|2l*{pci)xbwBaXJL9hm#BN<@BabmKo-BEE34UZ@!qp1%X#5sWS#fcBZjAb zS`=At#<6QWrVyC@W)nv7X17HIQIbH?lQ2|D!@jp3j!JXJC5XQvm7)xs!ycL9{9 z``dA|nUXaA;5`2`srJ_g0UZF*gNdVP9QDom8hQ}MnKfe=aHaKZo_h=0zPHXEE*3_Q zz_=)k92OK)f>B#FzcsoG93thFMHg+YuHFO?elYM68!16AoDD( z$|lbXfB?2~-SzDB+0Zr4Nr=%nNfrdV?KaIbN~5kR@1M*FW8GkY16l(q2TYNi27(b* z(pVb=qVIc5iT7k2n>b>YfPO2x?#ei`T;$#vE&Ij1Xq!F=Bkc^LLD%~j!YC4c?Z#;c zMC8ViGr~kLcD=F2jMk|U0FMa{g&^2IySQaEU;_4o-tEdX3}*52=JI0byEuyWbCJ$W|X@BKe1XKRDJXK(F>dP6+!?J)b56htLMO~PknTSOjq`{ zlVH-8ajK<@(glQL%!6!}0$`1j05haIhoCd&=xEUlT}Y!rsv@L_&APe*z|9v6XSKGv ztV+R1TW)6=#{nLuURq_XEM^(SBr6i<-FmaTclXZSla-o=P~iDIU2pbQnkWu#*ZbLG zWg#F0^<9lH3W8vxqM4%^$3G2olBZ4UrLHydwkIybI$Li*@ zf8h81!aw-JhiD!E@TY$GN0d>0@28=^0w54{mgP^MKc`n{KA$B?w!S=%X958RfWE%G z6r3-(^3GkJodN_9#7?QrdUJkx5r>IjFpi^>Z~OFmb9Luv^{c<~i*-|1O(VD%m0lhl zJFWVv6&%M|QgwYKgq&m)2x+Wyjv#w-vMj5%@3gZjEplhHRFYugyjmR`YNNZhqYzb9 zr=^ofLhpCm_0`37oWvh{{k5mhp0AFNLczzO&$0{xCq%GbU&nEl&JNyv_enrlmZpbC zcP_855%x;C57+aS-jx4sdF;veu|cW?|S&6N{6ChE>;CV}Nr- zmQLf)4dY^QAUO6G3}bh*Q4m5QL=;9!Tfte|^%!H$=<48bzpqdz-agyD{E-LaSOqbe zrvZS>L$RyszHjDP6i~LF#@)V7(bqkn>OEXS#?yFd7?kBYF{?e-V9ySzwKF=CNP z36NEN-vI;=@qyrK>VejnfjrB*wo^*)I+dr{^|p$mka4P{;X%ka-|d>dZIxD0oDfEV z^S8Ha#sUD`1pEDFeedC;M~@zT`73WgulLH;yAHx}aWLb8r`dt?aCf^21KznRT^>LO z@*;Tu>C+b;KH8T}I$K3#TA!bGy?XrUWYoItJAz1EHS>8<*QHcWF!AE!2S&E*&AzO5 z$op4bdGX1Ur*#E-hJWXc-+AeU`$xxr_}%y3d3JXCu~!~HJ-b}rZWw2Qh(7FOz`ybb z{-8D{Nh3^=Q?}mkz4e?EZHz_4LYsta?CoIPVtx<`aCuv0Mb?j9-y2G$@pL(#jg#C~ z!)(4#Ru!|kv1U|e+xe#Hmy5J2cS*d6gP?3G&S`VozVy-y&(AJtkT{3aIK92OG;*8< z$#@8zFU!50CQdQI9y3B5K>#bIr$N>2b&_Oq>}4pS_tpc34gtVzH)ONf!NIKSMnai1 z7GffZ4@Afp*f?8ObsPrHTgvFg)lD2Fam4qN3Pq9@34reM{3iRRf2RH}@0?yI=?udT zGct{Sb$rnEW;>1uAR0yx^2@99yLV33SGS9U`R-TQZnBHFCi%UPz{)ZqC?;XyO>e~7IV3Lzk%IK|}rujUF z0C?bxmCis0M4sl>o3WXkK~WfuV;@GbRRhA?lDAY8au70FiLj*ySP z{_@-JJn04(MeO|l0uuzcg~w~rQ-QRE!{!5{pSKl`)aq~`G?yu~y455`rN&N#!N5W-=4uloHCU^CBzu!#8*f%|F5Q?Ik6GhKN%J09YLz z6NoW@m)F;U;90R82Dw?^B23iSFPAIpZ4$>V7%1njzw*kn)8~Yc^UG`NZQC{kBZN^t zn+;0owh^2GfOrt5-go0L$q8ecE<&XSj9He?+fm2FM*<6hAP)|Uw5*3oJIJY&3IG^} zQByab3R&&1jJsY>Z9k22^4JOyFe*fx+^+Xc)dKI0mdINzE%2~w`!J-&O3GNC$K$A# zp1d~2EVFVPrxs&ODBkSrXq0ci`4&dlcn%>AqM#WD0Z>0oU;Ldn?j9Zd_+R+<|Jq;u zufHL-o4)(_>SH{3r>d$nn|bH8wE_p@BoB{{&Mz+VC<1W;5F{7@f<5qD2de0~W${1xEGtT&sM&WFgfA#&fGsas(IZcwBGgP;&lnO$yST4${ zBoN$gHv$I;84Rq0#2S5Ykhe|WBJY6qz%Lf_W?yP)cf)!dCno4H^v(X_&dFgEMgRuL zwu9kK+h_TFUL;qi?;aQ8D{o%&DAU>iL^j(!g#K$^`&uA^Z%7uO`K})b1j>tIHhW=x z^?bYAgbXJUuQcYIOWAXtSm&t_*g51p7lL96Auz@|Yau28LP9{C=H>Yf^3W*586PI; zA)uH7UizjrobKvoCG z=V#B?>$T2eOv%toK&B`T5*8E6nris^+1d{p0u_dwae*Baktbp=?G)^%-+7A$n$U*GOAAtA#ABEW!_G72K=4aC|x zPmv!1oSi(F+O95l{V<&z7lGgyGY60}N==iuS|h()F3Wl^C$-4(i?j1Ichn~Rd5=>{5X#fQ8kfzB zt4&3?n7jraItYV^QyACvzN*VS&L(3j+0Te<>*|F^cYf=OZv;UbBw5?lMUs5xGv9G_ zeU+q{>YFghL>Ra$fB%JtTI*p~)wQ;hd-*tF1^LRe8)pb(ycrbmZW>3yF+`9H(f5im z0JTY3=$WtpVMg=Wvbw$Hg2icKq-LA|fRQt^dD?fq^N3=`6Xcx)kN^O@M_Ow}sI#sJ zwFgMXcfau4yJC5Gd-?nWRsB!!<3IW%(u^&Ls;a~+$l}!K5>Y0BGe&VC_WQ~slx2zW zDvr{&>Bb2J80Hc0y)T=_)4(z6J({Ft3=vAS)=Ehs*t*(4gvzQ!ly&=xb3P4P>n@GM zIOHM>10GM)IE2N8h~bAhkUuLz~iJ2hG%0%)c* zjhXk8vsEWKA)H0yI59#!#%U7u$^vNZG=z+vUu_o4mGjy=;GmnP4}Y=1XFvN{is)>X zb<>1Af{0AAg&HcQKK{`czx=hgtb+#N`FwGGb1OLSr!fr!0&!E_%;$;sXkY3miPqaq zF;CSrOoN)w=A#W5Q8%4Rvm_3MlAEd=wRS5J zP)-k%!(M4MO=*@mi-tkfO?9*?F0Rf$T=Qo)7ipZ|ef02Vy*;~HI|s_TONIH?kFN+0 zE=#xXY#=CS{^8xji>u9kdkuj|5znLj<42FGevG1s z2gOGpJ@}PU{<$Cf(f{rzzhRF`|2c?w=)AeQym{#(_pCNrt6>^vv)p-OEf5F=VIr_c z1Yiev5ISqLvlL?5` z5sRXTF@iz}()E}!gfS+RV;clC4tP5ZNg6Ayhu&D@A;zoKTuySk)3=)~AvlYp)AP$P zN&`-=Z??eu#cbXVeVS+I7Z-Q$-yzW6?DxxJp{0~k2149y%WT27&rVmzcUx=9+wHsW zKbz%Q7$$cf9e(oTAN#NV@?ZK8Blt6)|MSDt9~`Xi+&OvY-RE^xj@>?sXg^KUFk0;% zKDzI$->ui@*PA2^rm-hP&>$$whB7`3qg56|G)=v>F3(c}(IBVGX2U3R&H#Ygww=$H zB8_<*bp2S54RlU$N-zQlAdKg;8HNBjL$RL~v$`FPbxPU!d=9Y(-seR@5a9tgz+3Aa zGf=Ftm}w&U4xp`9~7_Gf?iCx7~9KCDpwi@*3|!TdhPVKjdE-f^_+ z{j;;39rc4%=smH?YFl@hM_Dd};MP+@U|qMIk(1+%MMJP7bwkr)P1KI}ZusCv~(X{^l!^cS$m%GjR)fFbJ$WC5c(QR2CB*{UMPu6bN z)q1_BT!>hB@6XOJoHeh$`caSA>#u&~mwxG&kMBGj$JRMNbp3Ds=9li@zcWuWquiIi z`mUhS%o7*@G{>!*W*xi&5i!nSLVj_%Y=2`N}E=Y7|3 z9xAJ5^TSDd=tj=z`NhRJswB$*=GDIKhH-f?_nXZmRi0&i-vj78L0p8++1YHiuNq2; zBRC8a@BG8ZFLrg?)(wDuTW;ep+)H(Hvp!fZATY*2=e38vA0?tKaE>vW=d-aJ=Ccs= z`yToA?d|c=aTtZ&G~phu*EhvtIm+QfiQv1w`+L(QyScnRzO(B4AqzPHsA((CL_by> zbHTv*`SUPYFd@#)uRiwrYv&gica9ECk}jff-A%-IM+f=oRpYs}%FbsCt*5ST1tm?_ zXosP6^{Jtn;Ft9g-^)mF(Vj8jZlwQq!=&Kbt=?ad}j697E`E(k)SwVWoWKp2J0 z__8VybW_(r?70f_9HS}=wwGZ?CAD)Q7ph`b8JNGava*jxGK zfAp0PMfE?Ec$VdnsN43mUY{J!oySg1vk+TVulLQpB-riB zXV1>=f8<43P1886mRW5qW2CB^d66k-`cY)yWe^C$1n@451m?8shH;RDGHbN= zPB4)~32=@fq>Sym$y!_0HSnGihH)^NNlG1r+*s?K^}wZZtexryEv2lx&I5ok!I)D{ z%CbH=JZj3l(IyEJr`^0*WcmCPufOnj{^!5@6F>16{>oqZtN(u$eNYzwqjs}dR@H5_ z?~7tq*4?sL00@dAy}r7!N*%0Lbu&3TN{MF6dlxrvB|doJ(W9pA2?WjNHqVOL{P1?Y z_Rf24XIVCkHN?btKnMoFduI@`kMG}^hK3-5G5h*x=Qv4*yn$Aas@_9_7<3v?!Gu7- zA;zo&EW|{JK!~nulPFeGudRy&GfE*1!yxFT3%qbWk};74C;FK z;)@^E*XOH)rQngW?)3DMQ8Js&$FbrJjYf|B^xfb6JwN~RKlcF{{#}0PPyd-GPcNbX zZmaVkxtHa|&{gw!@!pds=a(1X@-3hEhrj-hUVrgno^!3~Fu`$B1c8goo8|I|BHK&5 z+qc?G&ck6G1SOm>!I@PP$5>NljKLgXgyp2Cp;^sx;PpHS5TcvS7C?&wK6E+@BPOCa zB*bg&&@dQ^d+mXD2syh5^}SV)NAdgDbs7gR9OX(OPawu{=tcuwLSt#P(l%tmDvcqW zjH5KrULisOWJ510rht%s9OIaKEdfCD*&GsL5mtRSdB5G2Z4Z9%PyHJ|`+==sBA8+f z1!qc|%XN8hw5pqW)Dy&b7>2`RKFg!|toX{;eur{qfJYvbWgRD}QTnZS-<47(K_r;4 z%6i}sW2PT~N0U?q#SkFi;mz%Bnx+uKIEcEolWDTsRsAFZfH47th^B9-h|?&2`|Qd( z0HMzUXQlDjsc}%&aAgZ&fOQChfJNW(?Vot(y*IRW2*S3jBN0g{oddvX&cA*m_Vt8u z+q5UgC%bw#jZ#WEOQW(ZyS8`EW=WJUmeV-2^;G1U_i*a_W*9{rz4gYM-}cFmzyJKw zLDbaE*nh*0Td(b}f8n=*wMqiYm@ytRfe7(dja?sx!Wc7k{V2Ge2F@5JNNek@O=DWO z6+(m(k2oDhndb@c);g=D48w?EB7|t#4niMrjG&_wuZ|A-Zt~g;dW?c_(q^|UwNai> z0`fmIw3en~hRKnq>Fx-~AU4;uGKcsVt?pw^f$sqG`L` z8bhDw3+EIAm|{%g40t%nsq2P7aDXrcWE{q%)Hv7g|H=E72n;QZ>!L+PL4dUADj zIrPnZIdA&D+ztpM5d_nylPpDEmb?9=3|7b~8-=0N5&~=uNTR5zcgTZ03+vsMa}1rw zQ0AP9Rk6Ogy}H>~1FEamXv@M7Q#N*8Q#NUq9xRgU%XMDl#(R=dgn_f*w|?Wxai_<~{hfbt|NjJ^`>yYP@bG@u>GjRJu5XJXedUGM35m8j0?vUf=!bqX8e90nos~s~MaeN3 z`ZlNoud_`7(vi= z`<3s$bSzQk*D3DFE6i>G%44&K^g&I#?A(zkN`?)o%3l-CJweu zHxn>Pk|IyJFxTr%J9L}`TC4SDcmKgXDJKRQM7XKj{ia+j7u~MPX2pKH&5N{`()1Ij zY#9J6t2}`vnDj)n?6gI@%`FcDA;KUopwqIcEF|p+l*4VOFlWX(?KB2(QWgdPW9Y4E z#-4D&C^bs;-E??o)jq#;*7E=p&H%!fXPr+(FOWNgPvXKm0jd=deL2AlOby zNx3Jm?HbBN$ndTnj_=%=COs;}OmK8~bas9g1aUJ?WYQQwfw2L|LsgbLjPQP6VhFk5 z(=>3#G?*CS?a&ZL#$n_HdxQyu7!txT0C-n5gb+-iQYuMj5O|0{Teo2lct)mvz)oNY zlQam!u*l;)EAwj4- zxPSMk?F^%&-S4KZ`*6+YS#h{Hc>lfkg`m%_t{{ZDP%j?kZ9f@LjmJiJy+;A_S2wqH zs}PO4zRmLF^!zLiBj_C^h}&RwZ~$E1jZSNGxX2J9SG!GsY06pIbYYqkfC9q#BAljS zl2ahki?h?CqqM3!%IRdZvFh3BC8uOQ&%3Vv$P15$ak#o#D_1XP#r4e|0z@eqyC$G) zloJFvN>kt*LfBfXowdqF5!K2CQPR})GEc*Zr|As3#(8jcb^ZA9i`rS>&_Dd`w*etS zHy@(;@A>{e*~{VTY8^#^Hsd%NN^w7ockdqET<`m4m!+`-4q?bexLAgpT`i{(IW0Ke zu6JGC-hX)9k2*<$wr|5IxxQT^0Jhhc%PfQdboGER+39Uj6msej6u=8iao06GAZe16 zWz&yCAcDhXK`6Pn*=T2x_Yr4pqswMYl31$HAxfBt;&{8+D5>Kp(MFLdEOKl;sk&~M zB*oL6qr-meZ^}N5Q$2QhRxFFGlXA73c@`>QA@Ejf1mN%g^rzo?>rIBqdbhV${iz@N zk-z=7{`!X#!4LfFT##@3wr{_@ID7i^e3GLzrW({o9^J(RKR>;JgwkN&1S_{pPvCgYz5B)bk`M18wiTvD8e*WECzR|H6{mZk{@^-z35YffSB9U^$ zENDkaF^tm1G|7F{Axx5pSm)C;LJ*u@T<+_R5>hNvX^m7`YweZmlnH}5W3)&D=gBx( z#^5ye?ND`N-}OTvf`^YDjniP1YxY&sRD_~(Un#9W{_&6f#;^Z+nk0}62>G_Ei=v2Q z9&jordFRg2Zo4JW>ahwlzfrwYQ?)BM*RIF}^k#eO?;oUsA&BA0ouf2O2_?7dTW5LK z^%qySz=JppRtI;!^3|^_4i1$ZEpW!_?QS0>Nu0#{YR{sqyuM)puc`rK{7nw!ALqM1 z_c_7iag0REM*Lucx{>DAj-nDCLyYUFdK|(gfHnJcnP9hA(5CX_b zIDjBU91ul{lqiZKAt5CPQ6dpSkPrt%7~}x4V-v#Aw7cEzsjBv_J$~~$KI58)9CQ>} z*bxGEm2>?G*Zt@@SiiOIALo?N)pD{~?=gggk&Blv2p4y^yQAfl^KA6Z%cmdnA{T-> zX%Xc`UCw6Je%F;%<$N55A#?owci;c`*|XJR-ge#RKKS7O`X^tAwm&*QU#}0wTL67s zWRv-V>?HwMTAfn3e}0ZI?&;{f5xLOD7-tcHP+;es?#EH8GS4Xl1R@vWv!|aV?^B8? zMM62jz*!SP+-&w$A=+l3ELW=Mj0I~T#@c8h^2vm6ce|5$eRhPUl+B^3=Bsz!zISnX z86dv9x&4J-_$}C!^+$jDr{>E=F6P^P6A}$R3@K3nRo9l&Mc+FB6w8+c3$4vKng@^0 zU%h-)&nMS6nYfTGayB!ZA!@n7ee&WT5TwSP2&@S z5k$slQDhM$1UZ6gl)=a3twoq{hC>KI2*gn8Z46Kjs>~)`^Z$#^q;FyR2G^@afzzl$ zqZSW7KsX*Y9^e@-(ynt^miLF9g*Zm!y@m<34UnVCCsoG4&8|r?wq3VBw5!z=Apjv& zV+$aV($r7?Y8_d~zCx=GFhfCwgPkg&>N zM3hw!Bx@X{sG8JW+YQ4&2qRV5OGz1{1o{vm&9qb}tJP+Ax2W=GFRl_m(T9KYhkoRL z{9pcuo2%oo@4xc3ul{Q&`m_RoH?LlvoF2b_bo%t!3u(sLY|07&4N}qs>yD0A&7pbs zgZE%^+s*pH!$%)}_@NNOn8-1N5SLjt3KIgjG^iK zU>w9GX%!L}#(`j*(&S{cmakOpI_~2N8yTjIKPcUIzcyFZgRaJR!F$||? z=bw_^U(4Oy*0^wXyn6Nga(>F@vqiJJySV75)2WvIKm0%c@dxj}cegvlgoWUTVRZ*3Gk}8dUY{foDeQB!k8g} z@WaJhpPp@;6rl@7h>MAFrsd#6I9i>Bc+>ABM&W}G-uvc9FQ=1Pipe?yJgCcxGKL|V z72>iV0yWm^;37a^vp-Do!aF+-eUXbS18vts1g&$7G6W$6V87c9Qn~;q8PhO8EDA29 z3C-(QQX3z@WXdToSO|kuo;rp(0|5ppD7`<=2aCtCSuKyBzkCHDoXw{x#()veh#M2e z1R+Qelv*dPR!7Hoch`s#O0m&VDT4_uM5b*@AZn!uhSr+5-g+eoMd{LbTx%bV?fx17$tUAAM4&iloD9uSb-U}BtA)u3HoWNkOr(_+8b9-p7eQ33#S z!6Qg1rlKq-1=}4crzob_TSv33tn;z&BaG8&86&^|ARMiCf>IJa&xD|uiEL6%`>w+h zff%}eY!3UQSzVGSvRUuJcFJ*Z@;95JsE?0M zE?&Q0H^cq&qr1EPp!#yU+}y3pqNwY9Qm|1<;JzEI zF*dnJkDjPu+x1$zkQc>zb5rIgGNOm)N7|2BNs8IMbn#UTF@kBo-^bu7WdMSUi_72q zAin#%K5u_+!qbNo(#7q$9{d7?|rz7y&-7SI?1JZYG z@Xi=vtPM_cE|eN6Ev428BuZ)Yy4i26flLS=6CseH^DEL5$ z$foe=Cod5~m8d4u8G!INFaOsg&3N(ZcC)=*P0RcD&qS7Y(uCkL#@FjLqnt9KwVf|! zN;?F}D0T0Q(mEtKpUn^@S{t4hyZzQ%$3;H$sw^r_!aRd@85$k7mwnqDW&$ko4Crmr z#iCCC(NF!rFMi?m$1nB?vT-zAU=MAK7`Vh3DvBaFu;ATT$5%H2bFLkN5EF{jFvLk2 z0Un#d7&DvBiu;c~{_rC}xV}5AR@3$M_3h2wiXt-eY4pftyYjAN^n((?G}yw zFq==uK|X%#ku!rgiBUf4(G13c00GikE~cyH(NddFaWVaJd31JMK70O}vB~D{8;qsA zoR4z&(wDvxyv<6X1_cm$^zi)lrpZLfDLEXv>3re?(B6g+ii{r`8Dr2!??QaP5_uYC zCEINiO3+!208-kxu=fD$x=u`r=mJb&?1#zGqArS2N{(nd9JHnwLJHBcfEI`sSE_9f zyvU)2f{}5Mv)K${c5;4ldwY9!@3b9EaG^W&gyZSy@%nBtX`te1^l&NZBJky<7+5^!I$<_x|kv`q_0I{a63xfANKX_D{!bH;jSm=F;rt?cp9i3<_{41>uTEDLJ)Mk+}eUd$JL z(-Ok0wgoC7z?q52ALXim{m9aV#^z!1WC^ABz z(zeXSWHRB5G=~j>EaRZa@}@m}W~%?cxPR}YE;Hr5iyjO9=)wK3HzOsKFuZ9FC#xeV zrPF4s*AznxA#@f-ti1x!2ZVrDRVD&Qhh`9jSf?>yQahz3VZu0@X9XfeOA}*s-Z=*t zOM(OYt@{c9NTouE&IO3lq^#690+8x53q~FtRoAzUAb9`$^h;m)+F|2FJtd4f<6N|u zLMGUu9S*$;5g9cg3}Z}OREPEs#iYg|B09^l)2hrwa{B4hj~OkNB{)A_CiGjJzF+{X zwHT9T*OfVY=e$T}+n7*g#dN-EuA6$cA~+AO-|aTq!3?@#=$}1(QBSAa;chaYW_cyY z5mW4>hltd5vECm>DKX{FTOR^vz#HXank}a>0x2EF7()HlTMzH<)&s*;J>i@Y2T}5Q z#;tX2?>>3?hEn8>bg;U3^~MB<3FdqESbtWP=rAM=Eq zoS&^Xw=tz&8Xp0p)cY`w#u`gG?M4-X11WFXL*MPSa@vNBV#eUv`DskhS+`iOw6P+| z<9Ts=dqc}CMc@N^b8&+Ng#bYS)Hni!F^G)8Ny!UV@f&giSx z7uF?frME8QJb7|nLGab8oNr4SH7(YYeWZL@3oZgq4tbP~~o zP}tnw0!AsvZL^slpVVdf`o&XT)W7=muReV6*7e0z0QT|YN5A}~ul(@u`|)4=dq4LX z`~Sm#>`yEvMLC^*cs>k{2>4z_}LOi~IZ#23aC4lkl z^i;{wx-?%Nw?pr(f9J`Atf;NAjH2m$UYBCGm)4qAYRdU!Qh4Vv6A*$?s*Kaqqob58 zVeHThQpsfDp*c(@b?if)<;!_(t!npD8DCA}5D@{$2ZwMJjOA6aX|^|a`{*O4d@`ME z_gf~iyY&td{P^)>KywhC?DxiKo|B7L+gxOaq05-)b(l=&-k9Jc1mI{n+3km_s)lh8 zB6C`<*LRN}KT^uQc=naew)p9P|4;w5|LL1bG-n`UP~=Z{ z38#3u_Xk@;kYI`-#uTKnW-_hipeQ3Ky5#73b1O%?oXukJAYi4H^`V|jb56Rp?WOF8 z$QV}EK?n%KI05Sd&$82#b420A<(0Les)RS%8JCyYXcUJ0t6%?!Q7)xi%ooeWB0{>m zy9qHaX0xX2?zVfU^`KO}I=&si?D)PTO_ugBcx!FW5$Eu_l^@)nFUxS(b`St*bO?!K zoN?x?)mHuLSAR7)|K9uWwoOm-OpjVjrn7n74$7!zF`H+F03Pi2&2)|c1b^nw{`vpz zFaM>_Y%c#VKk}nLwwO-xvbwmu2|;rNK^PIHtL0QnL%85V+-(m8C8hfL^4Lge1J+uX zMP*W;82954k{fy*69h0K3?Dyv{PM+f2*aT{I3GTG`eIU*WqIU$fXESOt8zjp*=_fe zYO-7J00xY)q3=g&d@z$b!!RxuGi@vYsU2DbFr&QSoKZq3iQZ?7Qvxq9FUz_*UM;oq zhrSCT=8TR~G6JfqHeO*wVoWKejPn>gL~zvBYQNqdh;f1mz=gK9Y4@M|+$8!M%C;YC4@Fh)A8U7WXb+ zTmh7NX|{V8Vyb7$yC#4X7AFg@bjAhAvYV?Lk;7o35T&tpzuf_dLk#248$t!o9Kcmw zLjY3pm;$3C!IV-egkY48a_pLBR#$`|PH|o5-KdUMr@OlwDyq%RZ9fc{kX)2%)G5X+ z3kfA}9H$~>KwI4pNX|NCd}`#0d<{X;*wsF_?} zltmTu6TL=otQ z;q2bIlCGXi#y_6!$DI&>PXZ_d@M%kjs3LyxDkueNY3^o@$8J%U>IF8YWlma2dL^;~w zpM3Eb7Sm}xnLc^)B*F9#!7u%*TKcpCfPUy|J?Xm(fWcxmO9-ez1CqL~&#M9eXRLYt z$y3g`lfxIk_@zlzwTHG|9cif_+&jJ7?gL2>BhFYqbX7U2Ces*#F-{N~nQ+!*jANer z$apnt4ttDnh)($cy=R=suD^G-EFtO-*F%h`m{ZPSOz(a0`J2nvQYpf)m%7R`=d2IO zYr|PyRRw^MGP-0_%&6890wgk~bx#Q{Gcj5>Y;H+0jmZ^RZnS#m$vdwuZu-6{i(5L6_cD098(w^D)Pns)5?xL4Cdpz z-Q%|&joa6VlhcCbQjcz!p48iRYptEm7o*bM(2mMfWz{r$0DZ=%gBgfH#%fBsrdP+y zxs}>@5P}hiK?uiDr-ZlrPqFj;Z~yGi{pgSXesAc}$@%T|+Gz6d(YXtzuIr)g8Rft9 zOaDmZ)%Sk)cm3mk_Jv7ZP>h?V&5Hc$Zu9Wo`@i$S4}AR_UjZ>$XL-(N(qT5C-x{Z^$dps38UT!^OWdMO8ODJ3Yuq9~L$vuPcn@d3G%0A@Bs2vfo0 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