GScript.loader("L", [==[474852437279707400010000002d0000002d000000f03c00001d3d0000100000002d3d000008000000560500002d74bfa643172452c844daf8281e4b1da7b8c9d97f8ed329fe5c3d66c75279a14bec14e61fbe6fd6a356d680fe2b2b71e1cd30140fb5efba34d149eb709a664381394132f5b4664e8c262e22c1d0b7fea0708bffa2f91895e3241a1f49375fad50741b7d5c18f3a079119cc60b8e81ccf2575caab8f6e81b1301967c9c633d79e9c8bf125edf9d4404e007606f54ec475e4fba03557299194a731b8e1e9e28f497d374ee597379b785b40a9a9b865afe79c716582dcce9344e76e0f90175d3fd953258da90de8ff3e8dce03f79e72dcaf783ec0f916fab49068a27480638f6a8c328eb619699cf4a7abc42d2f912759b4c51b90153e81f278f42ea1d759d032abc1e4c1c78e4f0d7fc061cbcdb5667ced36c0fca4c505248846e636b83eb1936d43d72d8cba90cd61c61ef2dd72bfdb6c30393a4e7f21bcee31d24d23437d25c731500ec80979b4bec3f14670a431131febec35fa6956a8d9a412889427053c75705bfd0da26c3dbbbd5ccb478ebd6e75beddabad8df1248a95e0f4bf2633b85da04e0db2314073bd9867b11cb49aee1e277d32a2b6555c2069f09b4eec40dc86079b874090c056a533fadfe5b846f227dad560325aa7ca068b88546a7d271272a4574f305c2bbba53380a17f8ce420c5ebc7ed993a620c43d6602af1b2e9cf64619d731cb8e890460d903e156f3bff4164dab521cea7a98f34eea5ee4433c3b133be968e333c4141dac14515fd78656b3882e3a7ce575ca67803581052454897d5799fc6ed4716929d822a264a4360ed21f2fe2a5772785a7b9f7a0f0fd5c8f84f380c741b56bc9655e7b3a93494886881f4a27daad01a9d0218a3301216636181b4dfe1f326f1183e7d8760bb7cdbf1c720ca567d195528fa5d1ab90264f104a741b5fe589de1f08977fa3451651501bceff5d8f663715b5907fd7be69bd7aa75df35a34c5557e55a75d56de95a54e78c3fb5742b0a682df9ab123fb5c4fd97a92ae0876d6d943cd5a584f1dc5ec6732e920c9b8fa56e214c5e7ff456dbaebcbe39cf6551d03ce39d6ecd0b740f5a5b9b23e0405f48ebdc94c525069ec21a67101a92fe5c522af19eacfe0f901be346c2309c7ed78f26215f87760ff97b2b3bcc38c6560afe036d7be031ff24a3d8e97bbc909d9c9097693a36b4611bf490ac4db594d4d7bbbd73675c4d57e424d2d3ac799593c54e1b3ef0d20fb32c670bbb864c5db68552c299bdfc5dbbd67db990ff33f4bb14c9df0a34072ee25439853b68bb1be149dc862722e6826093ba45dc5e3be461873db8ddbb44a599448d9895a5486513080920ce2d152c0028a9ab000eafefe247b10018474c6af22955854506a8cf08d4053b07e9ca7b17793d8e9f151fa54dbc44192dda47705e5994d286a286195f19f02f090be3134291193e63a1aaa7e7bfe8e368d0f026132a94dfba36c85aea1ee3cd0ed3ec2b41b4b4df468f93b5657b25e1f435284ed646e5e499ab2fbe1640b363b9718fd0f28fa02e9c531ea195feb3f5f1e7efbf04ac0fc198ae744dfb5a90dbf7f7f8e866329b19e698efdeb6d169820c3054e22fe00ad4dfab309c5ff3cb63c95d0d0b5fe36db7af1ecbc3f7d9ee2d13cfb4720e963728861a6973f5724d5e17cd5d01bcb00ca4d6d6ffb56d2f7fabd032cda0808855829b22a2782e0490247cb19a1c0a18b3280b46c72e90760894cb148adb6952cd0395654bd31b8cbb3fdf1c6606f1cd280b4fe5dfcbda3f9eea067fa640c92c13dac8c930fb3ebb868eed23d2fe85cd530142e9e00be57007bf390ee6c8af104fc2ce7afd46a74d67a0c59a4994e8c4a3f1748d1f7d52252b1f28946f865cd354f392b6ec2fd543bac18ff2b356d8298926365c9eee72da13a90f03377d23b150513e864ba939e5302adde4861e1116d81dbdf442178f5741f1089feac64cc222fcc07735da7650df159744eb20ada432dd04a9c93397e2ec99b718a6e4acdc371f3451418dd202f66cb99de319cd565e5fb5c4e151f91d156078e76922f1c7494ead9322d11e17bc417390156afc011f32575d194653e057b2df5b51c6e18f5ca8a18f5bb48713ac2be47833def39751acc0ba69527b68384bb4fdf7862c0904535908900389268d8b17d64092a2899a46213f6b8c9f045bcdb0a21d7820973bc72851679862e8df621f330d075c10fee38fb91a3aa9a1fcbd73e2ba2ddaa71fc3d801c71fe3f892005144cc00c015ada80fc69edae382b7bf80bae961603e3a7e41ea2fe41f748fcc71de3852a4c82790ad1632b87efb593fc796c1c7db9f7f110e505f4e46fbf7e109e8600bb772931fa9e1319064040549d0a8393064a52b74dbedb42dab73b023dadb84d4794ce222a940b5fb6c3996bd42e50f6ae3f74ec9b5c4a96535cc67149c6d613cecb36fb4a408cf671e23bc8cf308156481d36168b1854e00ccf698236485f6546f3a10d35c15f8546a11e6ca4353de4407521e0b03a483ee32e9df7fcdcc0196af7b29f8663328a9fb1884475e15f3d979274cda32838e3a329f10dad09230daecff564bd71471aa377a1be1e3d6b14cd30affd07298b0190bd694e9245d6fd7fd3bc767c83fb34b8f1c2a1de99bba28acd19f3a9218d7ef609ad3401db2f81ee9d00a3932797549d1026c0314b803aa94e00dee627c3dc18a8c88dfc5d4280b696839272b6980cc955c114b04379a7e672d8a41ac1911ede503d1f568be9a96333680b83a91d5b8bbbdf975899694526ca323b0f98e6ad4784f70e1c6d21767bf38afc33c2d5b9ed16a3350a1d7a1bb85fdd8a22751c41fc855c0f0e1540d0bad9e23cb1d87519a5bd5dc29df26ea19a1446a808981da456b8c8c5e5287838c7d4e0fbcd7c1d59bbddb5d90af32717b5743453f75e4c55ac45a93e1255687320c3253eb9423ebb2b47d779a988a301ff95e54d621e3951ab4c87cc1c0c97ef494dfafa86b944467ac84205248eab136ca458cddd29e557a839a6c9bf6eed2166385759ac28e729b88c8617d419bbf4126bf68950aaceff04cc1f15699e4621ea9ec91079812018304dc95f03e7642480486387b0351b60e674f2d849c312021b3b1ba800fdf9ffd6607ac91ce3375f58515407e5ba6a7461488440f7ff4918336c2229c9399f6f5a148af22bf32356471de7c5e98bdd74a82f7f96175ee39c1469fadaa2cb116188ffa0a1a391f9c6bd75798bedcd61b5e404cf5438a5c58a83ec3678ac55959ce533134f56a1b8d9ab6bda1b643be13649dc8e5d4fb0dec10b3d481825753d8a2269d7e14a22091c424892773c5dd6d991d386491d1aa13910283fdf2eb0fea74ff41879f654151818b1e6835194b8aa65146312ea18f71efb1e26965d4ef843dd1af5bc1ad198976311c9b72b5522e193c98483e320d40985b0c4f1edb2268883e284e259c4349e2d5a6b71e7913bb052211099185b2ce703e542bce3607f34f73fc01caeebe03c4f1ca327ef6b23b6a5517e84fa71dab56b276db735da2a4829a12b598f0eb421cb3bc3f999b986daa7c2f912bb3b6f79f7bb5ec68fded8a453ef26f870b3890c5ef8bcfc2d419744fedaea0b1994ab6780bc8cff8f479f0e776c2784dfb15ec499cc2881fc5e15ecff5aa5d868a70102177a20442e19e3b1055bcd76b43d222ee181467bb35fda4c36910ee893d826fa87b65901886a63d83e4c10fa3fee4bf86eacdbbc0bc74a15b93a8f8ad60c6c836b997dcec37b276eba6e34f450bdc5d9d9ee4f819d38a445e843350d8703e21b61c6205734f93f41a3d8b6d8af0133ce8e50c4d55941bcd761cf46a18e5319b0d2b3317017a7c064a7b06726f57e26ada1927a78db9b6f78d303af4e1c11baed9a7b49d3a8ce7bfa4d6df6a6265474fd321dbf603622106e4f4162d4896df8081999aa1dadfa132b61d9dd07dc455d77fb543103143b39f2e71e8dbce8978232728bbd9c82e52c71bfc3ec649a1ba18dd9db105f4703cf38c7c9e00bbc6a817768e6d33916d00ddea10ff0e62838e447592b93bc8da445c3748050332129a5c0eedf19d696742c4c21a87ca863b033e01586717ac871acec87ec31e7077a140874dd9a94f38189431f1c2ffb23fdf1ad6540cbec6c6adb9f521d21bf3e81dd7c7ef5b6331ba91a5a91a80a933e8541b3acf1cd66b2afc0d34923f9d0c380306c738f151361e31cbc3334e2d4519f37f1865a207cb00ade032a456a6ec8b5663d055efb5de98064b07a16874f4040cf76f3de3ea1b72573d46a03ca03c11b54e4f5a27e60785ecc0acc7f5216817f8276c48f8b0b843257c9cdafc0c6ae2a5673d5c3e45180f69e05fe0a808a5bf9ef11ca780a9e11bba12267d019ef1bcc3a16268137f43766be94b16e37d74718ffd675c597ddc44cbb4137d23a2a237f1b7de63954be199d484882dfe73e9fe62b574db47251947e8cdc6580de6ce3fac0e6cfcae8515242fb10bc97bcff82eacc43527998622e83d7a71098f48892cdab34310884221a01a0d5da787352b57e5cb6899cf910bcc8385c8d06f3a066513e1c160d620139ddc35cd939d321da8d090b01caaec0e049aaa0a113c6e58b41d7801068b44f4841a54adaecf3eff8dbffab6f9b62314bd1774e041bdeabbf4bb36373e64e5f33affae4dff55781786aff75c73aba83ac9a1fc31452cc64966e7acba931444ac7bb3a47226ddac09037c8e78797976f49863845f715cc43fc97818c819bb65164f903c0c4f09f0c5e674fc4b4150468c07996e577ec04ec520d4aa26a8b2d360b6afbfd8472f7bfe366321b3d5cf88a8de13290d04854de56ce79dd8b09d1131e67efcdcb9a13d0b9bd0f694cddd661555145a1b5af80ecc9d0173665e95decd33ff17241dce341c46ea9f603703c04516875376747af90c0d61ab078937a9d0bb3e05a673f22a08715c5733f9baacdcf42ff6cf85132b94a426723d1141f22609ca9daaef142dc9ebd99a967ad12626cb6db07438aa5f6ab49b31e4f4d40a51c31996b0be953283127cf989279f118a1c3e5bf8e1b4e6be64a2e52cb0cafd5d879cd82f451b22e1fc5392d3c8081a8b919e048d71149688a711ab13a491034568e3eebe7cccf01e874110d9a43de22371350770033f75ff5e2199d52431b47df70efeb87ef48dacba019d0ba0c23071260293fef125bbabf9f9de1a01c4877100502c20397fae556f09b04156e2f4a11300455025e4f878a38805b053f5c3db0dfd9d91fd1a81967105a9c1f9e33ac66a0233fd6c711cce47dc1ae60deaf054fe5a7f24ae3f1f694d3da21f8e2d3508280a16c897a94c62daf8dd2a0314e260227c5cfae6d1b85fd67d19d8cfd2abad7e52d4a2ffa2629b0c80535b161c3a3d7d862f35d2cce5c1fbcb3ddf8183e25eadeade7b2ea8b8b47154405d943f38548e44ea106f6552f683045030bc07205d25e89fa03212626745cbd8d8fd261d3a5bad6213d2dfe21719c81ef4899790984ce9c628c6689e38d75f2e074678eff46aaa64cc814873d5b8b84106c66899c936eb86ae05630e95c1899d322f7fd05a01911c5ff7db2b3bacc6a938d8e447a191ecc5ce09add8b008e54327a6a780c86e5373ea83ca28bc45561674a7f82ad74dfad1b7b36f432198ed2b1b43ff5c5edd96fb323cb709a2093d6a2055263944b5272d3e4072b462f660fc1a3d52da1879b2ca968c89b18af99d1259753cc7dbf059860382b3b194227620a0f8d40b00b42f7e59186d4cc6cc2af07a26a6c7f8b1e4fa345d136c6b25413d51a31fb3392a2c5c8e7a10a4ae49828dbb511728d86a1540564001dff853b639a2c3eb4bcb77c202e99d0fb2735d9bb9973b2ebe312c793855e91ee31cbe29ed6ffe874c472b0281470b43d4c40a9317f7039388edaf73032112fe7ed0ce22170d7eed85742128ee8872ff82943e6eb71df52a9524c939401e5de409cbec14e6566cd07499cce7010be5917594184de6e6ddaf7e39f8454ea8232687e6dadb797091dba4208ca3f29c917b938bfde2e5f1805fd1c2e253e4f25d72734f82f69d4c38fb4a759c87c3be5524bf7f37e830286eb47cd403275b465ef80cc587367e5de9c46f23741e10b8be41545dc8bf5178086d92c2f94c1da7864990bb26db74b2cbb4b79a28f28ab40ea7da450e2e9b5d9a599c2df44b270a854f82dbb5134ab7a6684fe04b7e84219d8c4afcad5884a84c43ae23a6918a549a9aa5f6b73c7b8076cf32197a1f2e7385e10d68c0ff933307cb7be2975c5fdacf5780cb6ab688278c12a4b8039c8796c2c7b044d310fdf74bd38080829dbc4c44d9a996eb17778eae8e7c8cfc9a3998fb68f8f092d52bdaac9426c79c2c3b1a3cd912325451f9dbbd5c9099680f188a0c5e01d51b78952310df29c71ee12a590b6c6da62f3aadf8e0c60f73deb0c82a2f14af7f4abfe456f81966427d34bcfa14b4a2490e8a9b63e6ed550353dde30da7ac3f3e3b285602d02ccf5b699219a301a06188ee0a0f1be67b03dcccf537e748404a3da749dc874278859405b1715443d0c310a1ac846ff0e7be43bf29d114b785a604b5dc329399b4c702882d928adf2aa4f42ffd54b765c57376d059539a720733f8d2aff0c25b658e730064071752f6a474431315f43a7121abd7f759274c7d9e98481e9c20ed32228f5869808754447b83e03a667d9387e7877ba020691c967cd7996219ad7e56b8d53aa3b2756172a3dbd65f9c8bd4a03d1c2b0f7749b22fcea4b53ca97fdfbf1cebc22f18fbabee6d7d7dfe1d4bcc43cef71d61fe86ed05e106b4ea8a44482275e34cf0518d57378a0ba75fe93d6656992c66aaab036b95f4f2f748bc95b496b8e1a892fa1dd711200f0718cce201bd43509d7d6a6ca988a6fe84e6dceed2f78fb7e227160309f25c224145e68fa6e94ef1ad46520928674f7f56f93435c91515230a9522a7bcfd41f87a53d47ebfd322e2bd5ad8f4bc5ff703aae1b5729fad10c81e3317cd1d8564ce3dd77107c4d74835d7a740a817e841295b7d84ea2ae170ab6a76b598cce350d3f7882586ea6e9892f16a1647b6056d72faa5c6a467d47775e51366527e753e2da612f5d0767fb863f01562300eefe337f1663600ce99df0ae045727e476e459aee7194cd570970435b9b5f45843f13e502af8e20f420d9613d36bcbcad91bcacfc419b16ec76c3e7872d2b16bf28bc70e2b3edc72cdb7d3dbc4dc50409c092d77abe96f289d0469d89e15d05e7b94598eeffb828accb4c6ed466ba67062a85fd9b0b35ab84224cc099e8d38ac569d84fb1029c7c5824d663f9ac72e3424d0bc72157f6ea6c82fb6cb8ce848a0ef6be9bc5c1846a9275f730e6c8867a66566ea0cae914df34aa4e4d572094c943b1572316640873aab73dbc2a209c83df9f3861ae4cd996b40777ab9a034faaacb1bf12a62366a656eef12bf2dbd455198651e28c5794b840762568388cee40e64c44203ce03bf79759971d796877487898ee9fcbeda4d4d2c840e2f8b41e972afcfeb4e884c1f573f9d71d08ed122845e0fa5c6bc0662b16da937338d12762d1ce306b1f3156bec90186d4fa3bdd514c35f1ede73b7ba2d1d6cb5274fefcd88192c685418688f4c628a2eae5629391fbd92af6189078cb5b70095e911c00ba73ca397fe7a6a0df3f763e5e06d77ab712d7d12c3495ea8d35dcd5c69dcea439f3d4f1faf65bdc7641659524548c16e96cddff269ad5293b1c351c883ed816eeb5aadd4e02f8b1d20fead134d36b4e46ba502a0c6a759617d93297f799a67dab934943d68ae5c409f4d8a51ae2a08a5de9e42e61e4ac209b35cb18a4bfccd3186aa117bdfb4f53bbf31f8665b85084015e0623119503d3d9d0870350e16771f936e5e905d807435105c7cc648710b8fe0e12761b016c813c09b2761e8a1fb222ab04f45824ee9e56323a76787f9192c1a3fb17bbc9c5fdbb3028b37c228162cb5e900eb98e78da8a588c8dce142ff163609e480a7db4cfaec88b807c7acb08548ad8084c8563f0ac852759da7ab512442837f4f67a2835b12ee31aaae178588cd3437afbebeb9beaec2413787328a7bc7f2ffe2f97b24f4ee181a0456ded96a39f2bbb6ee3cccabb109a55a412ffcbd099af82a05a35a26904ab6b061fed74027b52b00e27306fc51b6b8d5a993716f6fbf17ee33fa5b173676ae12a9d00d7c15ba89603366a5831f3ab1bf28b05bf6b2e30902b523933f1d9184a19041f002ce3423f7ecc71c0f77c1e9cb466f9155a6e6868d8f8bfb4458da18fcf95b50c8ba39184781a55228b1e30bd3eaadea338679140b00f7f41ed6036788f68813bc4295fc64abbd7714c606ab8bb166f93207d0fad00b1073a77aed242d5bec97dfca06048f92cd5452df4924cbab0ebd5d385569f018d167bb6a5d67bdd84628613e97b698b815fea202e035ed6e77525e516f9a9359133515114a001860b639d2617c49bc68e2fe0e7375184b4ceb0fff214c9ecd7c11d457a56e9025bb88e16ad5d3598fcd6f85b3b43bc1e89c68bd822623e2e11d67f3cbc07359b319a203fee61a6da2979fa4bc60f34f7003c5748a1ab81917d85a2d08299b76ca16c6ab7843bc1a2f099d34aff7ee3dfca6764bd174abcd05b3dd1e0291d2d26d4554096a303487b65be247421f7d636ca6bd4d1d7dba85f1d721666a3a793e2af82d4410128b06814eee544bf914dcfa60a8ce56ddac222cab2ee01303e7cf7a1ab90b6e89a34dfc25e666b0a6b302582b2b709bfb11f60741afac336c47e8930609d4f81b1e49cf5af226119d40ac815b3ff9706acce95fedbbaa99b026725ba77ab90b0fcd9f36d7c614142966730a532f6d7c45bac13c8337e5fcae4ca1385087234932360950a2e5b0b5cc75576581c41ee3eadf71cf7e4a419f537fec3ae6f10553f9e02c60667eb712fbf2b58978dc7f69c7b0d940e2b09aae664ad4c7f62e79fed85e1583d248b01a08a24c74b3c2a3ac443cea0abb6cec9ab224c8f4429276809608daa6bd02d2c42dca02f384a042bf0f5dd3f356e714b41d34314627a1174cab57df6871352a1e93cd2b129c84571cbc3d5e27a48b54fa563a118703dbbd42b8105833aeaecf56c8748ed46409ebc60aa5d39fa40157db0c18a5cc34eb87276ea6d9590d6ceaa9727e4fff5b4953629e5d8b09a51f7735a978dcbc03bd34c40325bd550b489fa1d2ba08909a4a5c06ff042339e2b0eab8f8656166fb6913dfb2023b59b9104dc584c156a3df583f3bbfb4e914f60d7fbc74241a4178ebde21832fb4dcec506d01b920184e473ef3cf8ac4bedd1ec866132c7982139260c53a88d8fd76ae5fc98553992c5aecb424699986815c377888e2cbf161bb9d6be5b1073108a53432335f42bad4bd73454b59d71df0cac0838fdb763458213b6dd6ee8abe73b210e7b04ce0a2d63894c16cc237ae0c2491ab198096e9abae9be53ccd4541e654fa352ffdd2e16d9666500c0e01ec38beed2b9f923d39931740ed76be4e4163db3b0865cb2e77dd8fc1c78442ca77551852568a7ac59501ddac99a54ad3f507af372aebda6e56ab9184ae04b15f487884078b84ec7cf2589b0441e05cc820d8c61dddffee0c10171824bda4917d915eb095739d8c574bea0393091179d7c436c49719605029658a93a2951b1927912db31d745b40b1c1524082a85b4fb85e64dddd3c4c81b0cafd50287cca3fc91df3f8299bfb3d02353febf02d93753d6aff546ed10fa22f5a22cc3e2751868355cf9eb8f0143fa50de71d91dab7ffe6342b77f04647f581471387f05122794834cbbe1c5ca097a155dd96a926f2d2191704f2d17d8271c44a660fd2ff589844d68329cfd535740c5464c15cccbf9f381b301ac57ca56976d7e07e633017a66d2566c3ee6d25357aaa9a19c339a116c781c441107f7230e81925cec0d9d9aa25bce646a6b0e83434a142a000f4eff7060c644355c887b0d26459ce6d74df09ce252538716001150082c5c503f338d650934aad741dde4993b40a0ff0187b73d5433501a8bcb41ff9f5769646873ce7656b741d6f9d688d394acd53333f1fb9a1c75d84e85ee08b2b02a0810baa012fc12351cff888e88c003aa74b377dcd88974297360206443c48a1b91fb2a2a6c4f8dc2a51d3d8d70d35bdfda027d9bb67dc2968bed858c9b9ba677d3d16508569659b59f93628b620aeda67ffb1ee19ba4de286bb601cfa4c380e617ca0017b59a696d47a47faf61beb29af9fda0a54fd8a13551c590eb9593679644228f78af41f66a5574892b7c66e4d21cb6b6c9e641933a02dcec9dc9d69dbbea01a0d03f1afc6925d52f0f0c803ad03e4f75b52418728bf9789a8a8e53d2ec914063f6ee034366eb4bded7f2f35807285ee70d37a639dfa2a1e6a310851f80306a1851fc7de9fbc0aef432d5d7cfbe9e5c6cf311e26c6d4050bc6ddb67f94de6ccd52de6b24f76758575f6f7b580ad05b966bcd8e9221938f7f40529ae4e29b6b539ebe74fc6d834f9bcd6fbfe1f277ffdfd1ab8bbaec8f69467700b732d82d7087946fc829c6a16fd6a9543231d7a76b4a18be3d209236556e51a8390c10bcc20849d91924465901f8ef73fbe0ac462f249cfb4d0a8b47b71db1d94b885337edf46da8be09b3526a96e51ee7f4ffd7b8fd294313a0b509b4e4b14433b4ec2cec11251ee9ff85b60876f26886c214b1ddb762a8af3a1f03fd4ed749aed65fd4b473240d986325e094d81f34c5ceef11b2b2dae0e4ca8de37dd0d5464d2b1f56296a300f68350d481032beb31f7a91ed13200c9b5b4ce7c009dc4230cd29713bac0603cbdd8f0ec353f33d82b80b6b3601ca444c8aa11a3abc04cbf338edeefc00e8d25e566f11331c1fbee569473c5cdab9906b5162068e7cc872b2a5f7ec8da63541ef26f82b92b0c99d7005b96360284dc69c159231590bfc58535666ef0fe4e24a4cfb6b66ba5e40e7cb51bf38e3a8427e01e159330787624513f7e465e743d22c552967e4177671bc495331c08a28167b4fdecffe720dcdff988e1854df62206e5001098b9f0e6e55ffe996888c2e9c00b1b50cea59454f641230b8bdf16b669855dc6e4e93f417630bf52bdefec6d5c5b7a0605c528288eb16f8877dcc798a64a279ba9595795b980423078ad5ba9df85f63d928a294de9cc94693b3e1b0b9b328861a07e3f6f9a6937dad984dbed63e314c0bd6a3904b883e3a516bad46eff8efc300b6c6d98e0df69e13fedf5321dd547281e21a679b85f7323720a517e503d5d55c2625a581451525ea3c4022daa866ac3965d0feeae836ea42865ce36656f1ab4fedc34da956eb4fc90240962d79ba8e1e6e35e3ad978122beab4e87b0342a23ac90b621c2a7ce14bfe374f21c7d0c4ffff3efd04d0ff28fcb4a177148110f3b409ca527b9d8298a5630ed676b6a58377ce0c6d2d0d7bb6f13a4d96d22244209e2d0c716d57a8b1692ad73e3cbc5ab1df2d17fd1b9eea8b47cbcd944f04a0a3362e74df9804334187d34eebe375417f0d04907708c95f692b0b3fcea84e73b5641b5ec06a0fa3203f6154c9b2c0a867a5b6a94ccf9cd33d7616b79dbaa083d8a1662cdf5ff31b830d8c564f3ec891c7dfc1e2cad47acfcb983c6a88e56227d9d761413b3fc6bf26d7db3dad1b22b900da7758f81e62374f1a5009f270d521b9e22564352589557bc2984c56d509be8b3477bc71eb0005781bb467dbc77448f4d8cc3b58b3d5ae4c10c2ee37604db151c9c1e17327c94fa875e4eb5dedd2e5785fc03b8365fa69b9b0a6488f5708ca8b839a74d72cd2821ea2aa0b0b87ca125f6103f126522acdc3a629210de5c4e4cd98291076fe720dc98a08f46b8b03e2c20bf25259d640f39cd14e7be0dcfbde854d6b07f3b2b9a5c45db204853b965c8eeb2cd4138c52ba30d39ec576f43db95392fb7fdeddc1db0646b948838c3a771ead8a1a00e8c1d97ba42158b68fea51707798f8668f810ab4ff38775177c82e0b6a672fbe36df785e842bc7622dfdaa948de62f201a7a0834f39ef2c439b239d2977b754fbc70620a913940c4af70217b1cc5e399cc79366cc5067074f4e94e10923feb798fc0917e0cbb122a4022986ddfc9c2214a9958d86090e21968bd91b06f1bcdb0c495532f72c9a61731af004274af97a8269cc04fd3d493fa80c8c8ae6976b4865c9a9cbb34a30e010c0c21dfc435924b6508d3a6efee0b00a0e1c52c4e59ace2387d8e714f8390570f4b6413abd5240e22e2c81a80b8b2f043bef93ca97f4e5130edacaceb0ba0206c6ae2013d4ecdc9e3f67e5c49c2cc70fa201d92a97a6a8f79130e799886b1fdad24bd2c1fdbd63c580b230d661ba6846384d7260fd3c0c20bc0bf27085cfba8c6617f2ff7a40459ff60218e11fcefeca9041bef7e311a2479f0818e129ec264e548cdb3c5a2113c0be56356072e1f3833168cca5513fa088cad12ff9dbcb788b05d508a979fde75a0c8a24878136bd55f2df097c5eb718e8d597488add0cca610eb051c9568dc351c757c45d8bdb348ecbcc20b30720899c0e8c5b1c153e33981ec5121afd70ba01ed9d186855dedac47135558692563b5068eacde978d87ac61920cff454ddbc011ba79c8846b5520942ae5a0e9db30f2795d341d7ace14f8acf102ec6b9a6a38101471870b3f0d6425f3f1157b72bb2251d51f57948eacd51debf7fcdfcf8d8b5c0477f080cc18c5b52e051aaa94643c3e458095b00b25977a9603110159212e5f07b8827d295e4cc73ab6056950fba1feb51562d3bac74f9d66a9eee702760173dbc35e59aef958b5460d7a464f79c174d6e4d59ebf16d5454108c6d467194fb9830e00e2e34bc09e7810a5b2d04cc05e4acb9a509537fcf79ed2cc3e50b01f4a96dc7e66a19a644e2f691b89238ba79f1f0def3f921fc38db19862c52aa06129746f7ac21aeecba27bd0c9fe8d5820d191dd68b9e6023f4fa84cd063770bf536bc07d3125e3604e3b8ab44ae2b6117609bf06cf12c7460ee02b29eb690634e3e6056d04d730d6a08bf3d9e66fd23c07465d7f782880728c91cb3c82c5ffb4373c91b274e5646f089065cacaf3cf568826cdf4b8a677c21450538a0119a905e09a9f3847804031dccfd01875a13d43759e2293887e5d274f3c909b84fc0eda387811742b6efc7bcf738b767574177703d51e1d7ff79ba91bc476f4357f0275f2d4cd99db7b68d945d1d35e0e50ebfb9c3e8395fb7af25cd64102d69bac880ab2645958d3ea7e144b7d9bfef5bbe9c78fd52380eb391b341646888687ffd171cd30f55ae35685b2e7d4d2ec8dcc19f6a427418828d9cb63ecbf281dd546ca8bfc7c84298ebdf4932aa6e1b9289d688f322dae6124afa42178562b91a6cf4e140ffc915e2dda5a5afb12843607182b12518c5ec488f29bf4c514b0ed672850ed4f0f7e876746e9482e8f23b4898ab67c5129f5ee467b5fea593a934bb3e6b639bc59e85ef74f3eec7ba67033f43cb8b20bfb39a575ac4d0085b23d3eb66fba3dadc672db712d3a3b95e56bcb1a5fad9eb8c51709482271f48bb78d34d701a82242ed3c4fda33d5140e331e7f98a1fc94a4ee024e1bf4db2e375003b92aa8c80c8047ccc997e531a4107b33388ee6b904db2b3c7ae00786bf38cc9cdd88aec9b22f138a2d1b8054455d3afa73bbe9ab3779a1b21228d20d73ec20e97388ca5a7cdade9abec6268aa65c664bf8191bc61c5266d4e263423cc8c3aa81d6bcd769e1d5da47b2beddbfcc5caed77dcc26eb701d9512f581b13dd79a1918006da68d4525edd98a267d05ed454ffd4defbf89294c81de4da55afc6041e6d321fbf70b28911a7dc0f40c6b970ff01ee2208a7b03b806e41f7acdf341375a6e3b5a8c10164c9f20df31644bb4c9354e610ed5ac897fd4b702c5b55996d75588764b4cfa868b5af19fe775794d31889e81235a765a1bf2b914c304664fbe4b0d00107fccfb57bc2d06c45c1a241e1fbf00a911a1934fa4ff83c6d9271cc67f2a3aac80b4868dab16d6038ec0e423e469af30a46b8386cbb1921926ba231e0c28738c8f27a91b22cbefc79695ce9903073478ea90951e1bd5e1a6aab7eb1d4562272efab9e16a3d9665145643257a969327b1d8f83aff5ae4bb83dfdf4186f2bb483ec76d5bc1a7a08019175499bae603c71fe29185f3b163bf84ffbbe6bb5c4fac19cb273f021e5d1b736af5b5d83e486b6b7c043e42a0073b907903500d6f1adefe1968d1ec7928ee357f7fa4b107495a7b4971af9d74c8ce26e2380342ab1e21e6c78e975ae204e5555f3d6e65f6cb5422655745120187355ff295f8764b6fe2deaa863fc82fb137d756d5b7e9825a129b6bf2db0da8404225531cef1a0fcdaa61d26cd190deeb8a18aed597109f885d527b6d7aa50bff659f1d07add21942b6457111dfa1dc2f928d22e323e1aee527c8bbb9721ec0bfc64a8e4b7cbad27958641798c3963575bbd91496031d76b12eccf571d78d48b3faebdf50e5ac99cf2824d1d9f15da4cb3a381734ff2fa4ac7860df5b655ab2d44f0a4dbb53356735bc41b5f942171150975e39ddfc0f3f16eec7e49182cda785d9abb90b2b93cf887cdec4e92f1202de01b4d11866abdc4795ecbc7202138eb04f7c2fbdd3838250f883f7add2f0847b02f98b64d4d368fb9814839a22940addadb2a44b2ed6babba13d0ee0095212f7631ac447a824ccd66be0075db2b84e3844cdbe4c40baf1f1ba5215c2fddfe0ff06aa05df08d6e77036bd82809153bb9fc7e3916272bc2d2c98ef37bac69ef76712e814afb50bcf79a983f8a8e66531e961fd1c1942e105f5e01780427988e12423c8ef2a0d3a9087cb9a75ebf33d58bf3346df7c1314f92443b645afb310628ce3c14a7e57891c681e359b6debbd7ef6b968d9ebc7ec0ab91f8ff7f354e81ab8a59dc1bbd6521eca69ffdd7d186d59c56fe04343534c85b18c12c6b99a8f8b150ee837c80dc133bd54795d177dbcad9066231e31def22ab47aef8b3d4980718b82a10a2e37ff85a9aaa84547646e4edaaba0e82dafa95adb827a4fa2e4c73b5dec9cfd56a22da28266d5e7e26ca81ec4160df74dd976882b2463c7f9c3f68b3f50321d8bb10fd6c9e3c08c7b5ff6453053327ab8ec498b3ed47bf1ad1abf9460209c53a033a1f159f29ee6db110bda34b77d711fb88c6b4fdae09b9eb0ceacee0f201f7e9f4a4c7f925b72a9fd583114632645942d6342a824871aeddb4761492b276e9f89530a8523c21afebd8249a501fa31307022b7d13d0169c7e1ef649e47c18a9c7ba72d285b9ebff6e836fd0b39ab9db60d64ba5516abf46743faa277082e6a6288f9dd43b6638d69d495c45de71f740b5d1f0f81173433a7e405668f0de187f315fa0912447b768bc99ed61f01ade2961bd5d8b90c1f5f6aa2f62df8f1f79dde9f7d8cf29759324783e7236983343b0b1dd53acbe31f493b7e2992f6fbf9478489b37c454f5fa8ca2971ba6423ed4bfff9915df28ac2161e995a204c6a19afe80ac489e48f64102df1bf4dd74b4e2ac6a421f4793dd7400d43ca32ca5171ab1f942c64345d701b3f442b5050a798814013f16e748a4a044662efedce4e66b49a71c5c858b81e23746f068ceccb729d3f2504e4c0c06c646bf6914ecf254fcb45e02836ce1b5a061778a7820be7f6b5ea1683b3e9c4e54112e19f0a54f18472d5b1c5c29119b97d658ff289835d98370cb25c859f3ec54632daa93559394376eb113f1c3bc19de3ef42b5f3326aba8a05c57e5db355a1f2ba5109e988428f81e9f3b4bef95608bdc9fa9ae8f997a225ce37885c8fb3bd7254f3de2d6b350eb8f59937409d711e4bcc1a93e937fb848a8bc617454347dcf4a8aca8c5039122b5bb13f6e7cd82dbd4ad9c3b1720abdc7ce2ca1483ae5aac42147833eb1311bb5289fed155e43b978c7445b916743f43378a72e69d4baf91ec10943324af927679539ed45a2495a8373ee5291b6270a245a7001588521fdc59f499a548bb5a9296d7d8f0960ff36537746a58fbe5a97b9ca6afe26eba8270ae15f9ec0b00d792dce590633b46e3606ae762a862b8d7ac48d90ddd1223bba2f605925fa27cdb1b5f9c23a0ac58cd4bf39bfd5f420a7aa6f9407719f6e0904d31811353f48e1eb7c6eb576fb6a84eabd6a75533252ef77c94e3dc524c1a80ac45e1906aca3f3cd5b19bea73f57ffdcf4a5cb5990076262bd1bc309fc7b05be7c196c4455730ad39fdaa80ff16ac41a53cec22789517f8581fd867d6fbf4839f6203db26e607e8c085225acba4f320e9a433f10ae1778426f477dcd9b8f0285d05532f2d53107b573daa14bdb184686220c188f225ff841c52ddf3bfd64944f12a9527eedba28ed955a992889c17af7a94325b90f908932ce50f8a4b5499823877ea9e3139907e200704971b10818c9ddf82f56595f7080aac5857d3e3d93bff585d839d409d86ceeb5945ff903c860ba23de485230bd5fa402a4d42cb01236fa9a168fb7ff3cec56966ada1221bceeb7d43ba1a515d577d84e6a5fb486bfa4eede860474649757740adc74fb7e12b919a2b15305b3aa17b341304113da150e161dc761c0fa54e6418f804daa3fb7117254d93962764e9afd3efeb1c9c710e0ea713dfd998bf6b440cb9b7996e379a36e13e86460d002d528362b2ba2fc4886a7b695b11528820343d7d599ad054060f48d86cb1b8249b892d82088160845b9ee632a9584505167e00bdd4072e73441b275f9e1fc4ece57328328d67fbfc16cdb268970dd5e67562e6c984381ea339b23a68ad1235e9fed5e8e10bbee28e1c702dd6fe7fb3cc9edbff5436564dad4647e00831d313fd79d0748ce56f16102a7db127afd68570ccdf66e443bb5b3885143b9c48dd07e5e412494d719a198f81178c1eced74ff1b1c2804a96925de5d4ccc4a7b036e30e903401f1697b2de7731ce1ea1ebaae56026f05b6561df743be103e89d70f29dfc308952b0e8a4bd6236e5a704daef0fabb8a7cd18b07494c0586e19b5d51d0b7077f3e5577ec3e5faddd3b86f00f4dce610131ff01507415a2d07f0d3723511d99e9bb5d1e99704dc4f210423b6f989a98a212227940da30ffccb1331d57f5cfc853457422c98e2b4954c0e719a5555fa87e8e75e0786a0473de7235fe9acedadb73b902c88bcb1c15adcd3148e0b180fa5fee3c0bd952a0ddddf83f216804a176dbfd45b83a1f548654557ec2c21abaa6ffecc811f29795a24c26085a195e46aeede78b57d026e0c179d576016778e9773c6001e096382da4bbb8617b9dfef6adfd864b77b51933adcce87ea8d2b24c18717a35d6d684dbb06c02bce3855e6920e60bf0cce2c445ff47113b9d741626b89aa210a6b990be10c19b23603b3b02b72e1ece2a879df689c11c5dda92a255f8132913c8a68b6e2f3bb983787b629c8b5a52a2bd5df766a1a26b05c00dfeac58a209be5160460817bdcae8ee9722b4c482abba476930e908d9b30b96660a293792689ed82e4c1c4b8e7947688e3dc607ef3936c6c6d3e11d6238bf9f5765b2cbab795a77c97cb769d29955e526b56e23a1d485d5dabe3d7c9f2a525d5084b7f1738a751bcad46f445331a89ade2c988d6cd5179362590cc569d83701076e556e15c2602c1777ece9cf072e8073a10a1462c52e1bedf5187fd2baa441b0f1062fa08116d192d4fadac872acd7baf67922bb0a83966b77271d6ce357d76ebae283a247f08c142db693a26a42791afa017958a5264bbb70eda657a2d2c3018fa71f5e52611340298587cb4d1c6b1ad3a85a99bd1ffce8fbe5fd40acdcdacf3e71a2e1659fc049fa9e66d1b2f04abc2a4fc4254606e205ce94b8d4d5eac6cd1a727417eabfd4c3fbe4c7f021fdc5cabce2f296cf72bce57aae715d5b31fad9737e9f1430c3b1af8f57a5c3aaea3ff4031f57b5e8d30db876396c0b47a0ea806c905f2a1a51d0154e448c0d0588a0ac97324bace09113c9f0ab71c6dc9d43ee6199988aabe2ec333203549291889d0dfc29b1fa2934e6f81b999e8f81cd27e6a4570a730427f1a61620d57007741cb8cef1dc58e9be6dc5f58faafd321b3b4d17349fc78e5f1c825be4dbf2ce1ece126eb327a37914062522cb3ca9a9ca671b640856a2b763f66f0ee6235bc124e31e7dcb3f6697df5ef43b1a4fa2b6b5ca6a8008835e64d6ce9cc25ed129988613e489a842b795c588cb9dd85144f58fe82f065209638088280638f71fede391517824796ac310d823e7e15bc005d3aa4c45f9a26a7ccec192413b8168c236a8199798e681f53f5f6756d4f9dd97bf211aa2be32642293cc1ceacd5c7d7e8cd16c2bdeccee732eb2c87e8dbde894e79a65a7319ca3f9c6f3c1a6b9e1378088d6d2aaebb66359f199385ffd211d0f9d236803e2636a6f0b0a6fc324a066ec86a2b271562051d9a2f6326ff511563f1b6388fc70c49902995f14c99f6d965bb6286f9918836a2fead446c8536f7cdd879aa0afd0c90b47083f1462a1007c4c0fab4198b43c77e82ac8bfec54e6f7249910df3ab06c9854c19f9e15aa533c07b097baf84cb698108e879f640be8a94adddb56729bc69c5c1b67336d5bb9a84e28d6640301263f594cffc893584749485d7af1d9b484315259f6fec380ba0356fb1c35a04205f0552cff59a3f5e9fa293479c9f8b79ebbbbf3dbd150e0b687699731ab2179aaf394e42b172784f587b971bbfd3d1bc6c074a272f84dfda0090a4a1936cd2d8b9f651dc57ee78f7aac11d04908c5667baafe8db25c8df5850be05f20d7403d17846e92b2c4a06c135887a5d98a54b53a0c82d6b1f8abfef2cff4dfeb6cada9a2155ca99ffed639e8ea789513feb953fcdc02456c82db1f3a76e01acacf7e53633d283c317f49f02d968f8b8ef38a651f4c4d5eacfa0a1e42093e1324ddebba2fdc14d995e08aa1b3feba1d317654f35953fda1768db507a614d18ed4be74b6ab3e0ef9013e9dca4e5bdd7619231426b41daf5b6949d2a14112a7f076a8929a9b97d896049e45e6e51bf48b7948bf281c057fe8b3bdda231a73862d282f589b4301735465d2b83aec4c14beaaa39cb69cd60409e7e406d77a1f56fd11998b4feefad0cead511b677100fd1aa82337ff3f380f885b0e0c77a1c8cfd9b09b80455716b85605b43f86dae43a4c96629fdf163c7c710b7ae26fd6a5bb27c786feeab83b125585c75e1da484df863bf7c9c8a906c214d6ce6f53688a64b0867fe1ac936e11cad05c59ea77d22f2efd477d1f381f87615f84021101a018bef914fd7d9a0e9b84f30ee38d9b5c173209e91799291f9bd33dddf850aae37876a56237ae2064cd506d33d68ff1266e8f98c3b91cc76e4fcea36ac5a64c631b6d7ed68a738f66a3bd2f770be5caadab1dbbfa6346374c993d99d82d7558330df69053caea06614c471c9913029233e13861da3dba3cf9cd4d9144511c80cb22a89d734fe5c16e656284d12520b077204f4de71c558ecb98ce413afd017c2fff5e6d0410b9b57d70484abfd36620041331e8450419293f143b49fffbb11411fdcee5507dfba4cd9a2d5904b058f0a0af9151ed67def3e1836ed8e20c58130407c6082b49a7ceba02794c7242f6dff018d5d7e1b8bfc9ff6d16876d954dea2bee81a5b320dae8754a812ed68d318ee6835018b75f93914fb88f076fe105a3acd6ae6fbc75ccf04b2a9924e2545622299ce698c65ff54af4f3bc731cffd4331c3fea17b7bb0dd6f208d27997c545cd3a6035090337c9c06593701e4c07191c7f0d62a562a90478889042d19b42259cb3b971a06b27481e613b804db0dd03a9238e23ad6142ee12616cb5700d3091485ac4e8b353e21c0bf552e15fff739e4aa098a8527708b9eaabaad7da7b9dbf9e43e2df79dc31366971ed57beee2faf55c12e5065645044841707a2f40d6ffddbab5a70f8c6fa75a5d373ee58be0594d5364bf7c6d7f79e5bd72b5cab5c8c36923ae775ef73ac9c8956abf65a7216822b1d04a313595eee9e0d32a316c1bc7d47d00059633ee776f6ed50a7c673b60ae1f72c98be720fb943786e0e42bb0f39b4d0574e516775e26d7eee486a171db1b4b557d31c523b3bf1720ccde1262fd11195744ac34314fe7bbf00aedcfbfd5697afbd703f6e3979e4fa40cb21218dc69283986ab3d3527398f65e51886421cfc98ef614e27069be6886673442a9836ea3da2d0f5297d7e6012f8a2d293ded146222d5658f01bf11783435bba1cc3f3e5d4c84da2ea664558f95bbe37929f501500a37d5566db61248181435b8a477c46305acc716a5af7bc432712264284582daf7c77b76a894fe77206b9b629bb15a99e81267eeb2302431c8a085f9013f4f29b8000ee826704535bec8962c3424821f0a7681ec6afdd76d1a2b9fff3ad5726fb10a3914a9a7e0d023564ca854b1e3385b6673f2f3c2b923c95ee296bbf89563eba2c47912ceab446789e5d6b3c773fc162a82d904fa3d65fa9004d7c6b6444d9cf62f795e956c1eb875c09f1fc888bc67844351969ebec8a541cf88695b9887bdc9622082d691f697f4eb50566a841e1fe28aef6ccef8febae41e8972d2c1256de79e18c2ab67bdbe014f761d4871b37ae5a15c75d7425044e759bb9a7148a1277c6276be5e7efd8b231dbcb62a7ba6025b86757e762d361c91227b16f4eddac505c68c2dcac251be7efa378fc4c1fa3d08bad342a60817d06aa03eb731e86e44b5a66c73d34d22d62cf67c4b2169193d44ee937bc73648089edc13005965bc599d5ab6fa515c9594981fba67eed7d1b83b6977102eb4e222f3c943c107dfa346cea9ea7285d865688dd9cfd370fcb234477ba55369eda59b66f37585321cd75ff461d78a01dfd40c70d00232c5e1d4c87240d69bd83f65c9dfcc313531a6e414f55cf16cfe5a23f0f9b69487f384d017b7a3330835a99f013bfdee80cb39236caaebff7036f4c92db8c19f0405e3e92f77be8bfff9ab66fedd4e0c7a6f71b8758860383fe0dd3ad0dc0a9cd3acda0ccb54fa3b92416f31620a9f3b7fc664721954e8dff8f17131044595041ca945e51a60ab029628015da6327c88f5b3ca5ff38f90d1828f0df947286f9c499ee22ceca1f5bdcd67b913891fcfee6da0dfbacc91c753d308b7270a7d0bc04b32e4156f5b97989641be25992aa0ab8b58a144d087abe716fc61f064c77d04c6ef69412b00af71b2c47d03eebf27beded2cc1ac4197b37db3ce5cdae101defb7eeeedea71f000cd535a3c3b962d364ec2803b5b59fc8e631c69abf427eac29aa70b232c6a915521a2fb121bd508347508b22e01f11e7b44f608f735ff331ab0792bee3892b79fe871ff0a0627b7277ea5ad061395bffc6353a498819ad96a01efbcfeea1829e84bc80db508fcf855f003ba4090e463713dab25d46e4bd895a21f97035dc060880b164d1317eee22a9a92b88a533cb164d6fd51dc785fc1fc644116261224a573384bdba2049b8dfa99c5bcf0bc0b3bc2c1566863dd9ecac9d41a7ed0c0e17f11871001fe71334361e47372ca4db2ed23006ae7ef292174e2dfb79d2063ba1d8f686793199809cb47e4975770508bfdda312abb6b235188844e6ec99096c67258f2fe33b6f798b1e54852662b9e1815a99e426468f434b2f832f3a5c2fc82cfb334809ebc39e615faabfa4881f7791b066eb810a6877bdae12407eb415ccab432abc244fea5a91dcc3aebd82bec8ecd7837e046a5519b0f8c74a8bca2b6a40e8a04098a7224a8929144bab657d0a0d4451577955f5f9e076162603f65fb390fff8ee947dcecc2914db9fb12940ef28c195a052c46241387929486928adaf67703902d01db778d251c6b9af837187f088d8eb5c152f6c21ee1296cd60845f96c049f6d7d077b7b851cefc3e133ee3f14d80decce0c2c8983e4b2f2f68a10ce4e45c58ec616f4f35e63eecca462940f00a0283c1a17350cbd082aedc6bd3f828a4c12c50e09e5be7b02c64634e21417c8474f9da26d41f0b75bcd4b44dbbb3198888a93dc4a57897f1e6f1ec14b376b5d078629235bb7fb5cd75115ebde445dae4f69d6c8c2265fb2246548ce4dd037a424d4e61c11224cd3be15efe03fc09673d086454bc]==], true) local json = require("json") class Bridge function call(m, ...) local args = {...} local ok, r = pcall(function() return GScript.call(m, json.encode(args)) end) if ok and r then return json.decode(r) end return nil end end local bridge = new Bridge() local function execute(bridge, a, p) bridge:call("execute", a, p) end local function getNested(t, path) if not t or not path then return nil end for part in string.gmatch(path, "[^%.]+") do if type(t) ~= "table" then return nil end t = t[part] end return t end local function setNested(t, path, v) if not t or not path then return end local parts = {} for part in string.gmatch(path, "[^%.]+") do table.insert(parts, part) end for i = 1, #parts - 1 do if not t[parts[i]] then t[parts[i]] = {} end t = t[parts[i]] end t[parts[#parts]] = v end class Renderers static function checkbox(c, state, bridge) local v = getNested(state, c.bind) if v == nil then v = c.default or false end local label = c.description and (c.label .. "##" .. c.id) or c.label local nv, pressed = ImGui.Checkbox(label, v) if pressed then setNested(state, c.bind, nv) execute(bridge, "toggle", {key = c.bind, value = nv, id = c.id}) end if c.description and ImGui.IsItemHovered() then ImGui.BeginTooltip() ImGui.Text(c.description) ImGui.EndTooltip() end return nv, pressed end static function slider(c, state, bridge) local v = getNested(state, c.bind) if type(v) ~= "number" then v = c.default or 0 end local label = c.description and (c.label .. "##" .. c.id) or c.label local nv, used = ImGui.SliderFloat(label, v, c.min or 0, c.max or 100, c.format or "%.2f") if used then setNested(state, c.bind, nv) execute(bridge, "slider", {key = c.bind, value = nv, id = c.id}) end if c.description and ImGui.IsItemHovered() then ImGui.BeginTooltip() ImGui.Text(c.description) ImGui.EndTooltip() end return nv, used end static function slider_int(c, state, bridge) local v = getNested(state, c.bind) if type(v) ~= "number" then v = c.default or 0 end local label = c.description and (c.label .. "##" .. c.id) or c.label local nv, used = ImGui.SliderInt(label, v, c.min or 0, c.max or 100) if used then setNested(state, c.bind, nv) execute(bridge, "slider_int", {key = c.bind, value = nv, id = c.id}) end if c.description and ImGui.IsItemHovered() then ImGui.BeginTooltip() ImGui.Text(c.description) ImGui.EndTooltip() end return nv, used end static function combo(c, state, bridge) local v = getNested(state, c.bind) if v == nil then v = c.default or c.options[1] end local items = c.options or {} local idx = 1 for i, opt in ipairs(items) do if opt == v then idx = i break end end local label = c.description and (c.label .. "##" .. c.id) or c.label local nidx, clicked = ImGui.Combo(label, idx - 1, items, #items) if clicked then local nv = items[nidx + 1] setNested(state, c.bind, nv) execute(bridge, "select", {key = c.bind, value = nv, index = nidx, id = c.id}) end if c.description and ImGui.IsItemHovered() then ImGui.BeginTooltip() ImGui.Text(c.description) ImGui.EndTooltip() end return items[nidx + 1], clicked end static function button(c, state, bridge) local label = c.description and (c.label .. "##" .. c.id) or c.label local clicked = ImGui.Button(label, c.width or -1, c.height or 0) if clicked then execute(bridge, "click", {id = c.id, payload = c.payload or {}}) end if c.description and ImGui.IsItemHovered() then ImGui.BeginTooltip() ImGui.Text(c.description) ImGui.EndTooltip() end return clicked, clicked end static function input_text(c, state, bridge) local v = getNested(state, c.bind) if v == nil then v = c.default or "" end local label = c.description and (c.label .. "##" .. c.id) or c.label local nv, selected = ImGui.InputText(label, v, c.maxLength or 256) if selected then setNested(state, c.bind, nv) execute(bridge, "input", {key = c.bind, value = nv, id = c.id}) end if c.description and ImGui.IsItemHovered() then ImGui.BeginTooltip() ImGui.Text(c.description) ImGui.EndTooltip() end return nv, selected end static function input_int(c, state, bridge) local v = getNested(state, c.bind) if type(v) ~= "number" then v = c.default or 0 end local label = c.description and (c.label .. "##" .. c.id) or c.label local nv, used = ImGui.InputInt(label, v, c.step or 1) if used then if c.min and nv < c.min then nv = c.min end if c.max and nv > c.max then nv = c.max end setNested(state, c.bind, nv) execute(bridge, "input_int", {key = c.bind, value = nv, id = c.id}) end if c.description and ImGui.IsItemHovered() then ImGui.BeginTooltip() ImGui.Text(c.description) ImGui.EndTooltip() end return nv, used end static function input_float(c, state, bridge) local v = getNested(state, c.bind) if type(v) ~= "number" then v = c.default or 0 end local label = c.description and (c.label .. "##" .. c.id) or c.label local nv, used = ImGui.InputFloat(label, v, c.step or 0.1, c.stepFast or 1.0) if used then if c.min and nv < c.min then nv = c.min end if c.max and nv > c.max then nv = c.max end setNested(state, c.bind, nv) execute(bridge, "input_float", {key = c.bind, value = nv, id = c.id}) end if c.description and ImGui.IsItemHovered() then ImGui.BeginTooltip() ImGui.Text(c.description) ImGui.EndTooltip() end return nv, used end static function label(c, state) ImGui.Text(c.label .. ": " .. (c.value or "")) return nil, false end static function text(c, state) local color = c.color if color and type(color) == "table" then ImGui.TextColored(color[1] or 1, color[2] or 1, color[3] or 1, color[4] or 1, c.label .. ": " .. (c.value or "")) else ImGui.Text(c.label .. ": " .. (c.value or "")) end return nil, false end static function separator(c, state) ImGui.Separator() return nil, false end static function color_picker(c, state, bridge) local v = getNested(state, c.bind) if type(v) ~= "table" then v = c.default or {r = 1, g = 1, b = 1, a = 1} end local label = c.description and (c.label .. "##" .. c.id) or c.label local col, used = ImGui.ColorEdit4(label, v, ImGuiColorEditFlags.AlphaBar) if used then setNested(state, c.bind, col) execute(bridge, "color", {key = c.bind, value = col, id = c.id}) end if c.description and ImGui.IsItemHovered() then ImGui.BeginTooltip() ImGui.Text(c.description) ImGui.EndTooltip() end return col, used end static function listbox(c, state, bridge) local v = getNested(state, c.bind) if type(v) ~= "number" then v = c.default or 0 end local items = c.items or {} local strings = {} for _, item in ipairs(items) do table.insert(strings, tostring(item)) end if #strings == 0 then table.insert(strings, "无选项") end local label = c.description and (c.label .. "##" .. c.id) or c.label local nidx, clicked = ImGui.ListBox(label, v, strings, #strings) if clicked then setNested(state, c.bind, nidx) execute(bridge, "list_select", {key = c.bind, index = nidx, value = items[nidx + 1], id = c.id}) end if c.description and ImGui.IsItemHovered() then ImGui.BeginTooltip() ImGui.Text(c.description) ImGui.EndTooltip() end return nidx, clicked end end class App config = nil state = nil currentPage = nil open = true configLoaded = false function __construct(bridge) self.bridge = bridge end function getConfig() return self.config end function getState() return self.state end function update() if not self.open then 强制退出中断() end if not self.configLoaded then self.config = self.bridge:call("getConfig") self.configLoaded = true if self.config and self.config.pages and #self.config.pages > 0 then self.currentPage = self.config.pages[1].id end end self.state = self.bridge:call("getState") end function run() ImGui.Attach(function() self:update() self:renderMainWindow() end) end function centeredText(text) local avail = ImGui.GetContentRegionAvail() local tw, th = ImGui.CalcTextSize(text) ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (avail - tw) * 0.5) ImGui.Text(text) end function renderMainWindow() local sw, sh = ImGui.GetDisplaySize() ImGui.SetNextWindowSize(700, 750, ImGuiCond.FirstUseEver) ImGui.SetNextWindowPos(sw * 0.5, sh * 0.3, ImGuiCond.FirstUseEver, 0.5, 0) ImGui.PushStyleVar(ImGuiStyleVar.WindowRounding, 12) ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 8) ImGui.PushStyleVar(ImGuiStyleVar.ChildRounding, 8) ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, 12, 12) local config = self:getConfig() if not config then ImGui.Text("加载配置中...") ImGui.PopStyleVar(4) return end self.open, shouldDraw = ImGui.Begin(config.app and config.app.title or "脚本", self.open) if shouldDraw then local state = self:getState() if not state then state = {} end ImGui.Dummy(0, 5) if config.app then ImGui.TextColored(0.9, 0.9, 1, 1, "By: " .. (config.app.author or "")) end local fps = ImGui.GetFramerate() local winW = ImGui.GetWindowWidth() ImGui.SameLine(winW - 120) ImGui.TextColored(0.7, 0.7, 0.7, 1, string.format("FPS: %.1f", fps)) ImGui.Separator() ImGui.Dummy(0, 8) if config.pages and #config.pages > 0 then self:renderSidebar(config) ImGui.SameLine() ImGui.BeginChild("##content", 0, 0, false) for _, p in ipairs(config.pages) do if p.id == self.currentPage then self:renderPage(p, state) break end end ImGui.EndChild() else ImGui.Text("暂无页面") end ImGui.End() end ImGui.PopStyleVar(4) end function renderSidebar(config) if not config or not config.pages then return 0 end ImGui.BeginChild("##sidebar", 110, 0, true) ImGui.Dummy(0, 10) self:centeredText("导航") ImGui.Separator() ImGui.Dummy(0, 5) for _, p in ipairs(config.pages) do local active = self.currentPage == p.id if active then ImGui.PushStyleColor(ImGuiCol.Button, 0.32, 0.43, 0.56, 0.74) ImGui.PushStyleColor(ImGuiCol.ButtonHovered, 0.36, 0.48, 0.63, 0.82) ImGui.PushStyleColor(ImGuiCol.ButtonActive, 0.38, 0.52, 0.68, 0.92) else ImGui.PushStyleColor(ImGuiCol.Button, 0.20, 0.22, 0.28, 0.85) ImGui.PushStyleColor(ImGuiCol.ButtonHovered, 0.28, 0.31, 0.38, 0.92) ImGui.PushStyleColor(ImGuiCol.ButtonActive, 0.35, 0.38, 0.45, 1.0) end if ImGui.Button(p.label, -1, 42) then self.currentPage = p.id end ImGui.PopStyleColor(3) if active then local dl = ImGui.GetWindowDrawList() local minX, minY = ImGui.GetItemRectMin() local maxX, maxY = ImGui.GetItemRectMax() ImGui.AddRectFilled(dl, maxX - 3, minY, maxX, maxY, 0xFF6699FF, 2, 0) end ImGui.Dummy(0, 2) end ImGui.EndChild() return 110 end function renderPage(p, state) if not p then return end for _, g in ipairs(p.groups or {}) do self:renderGroup(g, state) end end function renderGroup(g, state) if not g or #(g.controls or {}) == 0 then return end if ImGui.CollapsingHeader(g.label or g.id, ImGuiTreeNodeFlags.DefaultOpen) then ImGui.Indent(10) local checkboxes, others = {}, {} for _, c in ipairs(g.controls) do if c.type == "checkbox" then table.insert(checkboxes, c) else table.insert(others, c) end end if #checkboxes > 0 and g.columns > 1 then local cols = math.min(g.columns, #checkboxes) ImGui.Columns(cols, "##cols", false) for i, c in ipairs(checkboxes) do self:renderControl(c, state) if i < #checkboxes then ImGui.NextColumn() end end ImGui.Columns(1, "##cols_reset", false) else for _, c in ipairs(checkboxes) do self:renderControl(c, state) end end for _, c in ipairs(others) do self:renderControl(c, state) end ImGui.Unindent(10) end end function renderControl(c, state) local fn = Renderers[c.type] if not fn then ImGui.TextColored(1, 0.3, 0.3, 1, "未知: " .. (c.type or "?")) return nil, false end return fn(c, state, self.bridge) end end local app = new App(bridge) app:run()