From 25d1af748de2b9138a16cf1ad66c6bf9c20d3cdb Mon Sep 17 00:00:00 2001 From: Andrei Abrudan Date: Wed, 13 Jul 2022 09:26:52 +0100 Subject: [PATCH 01/30] Fixed compilation issues with C++20 --- cheat-library/cheat-library.vcxproj | 2 +- cheat-library/src/user/cheat/misc/Debug.cpp | 6 ++++-- injector/injector.vcxproj | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cheat-library/cheat-library.vcxproj b/cheat-library/cheat-library.vcxproj index efbd795..1776f5f 100644 --- a/cheat-library/cheat-library.vcxproj +++ b/cheat-library/cheat-library.vcxproj @@ -895,7 +895,7 @@ true Use pch-il2cpp.h - stdcpp17 + stdcpp20 $(ProjectDir)src/appdata;$(ProjectDir)src/framework;$(ProjectDir)res/;$(ProjectDir)vendor/protobuf/src/;$(ProjectDir)src/user;$(SolutionDir)cheat-base/src/;$(SolutionDir)cheat-base/vendor/imgui/;$(SolutionDir)cheat-base/vendor/json/single_include/;$(SolutionDir)cheat-base/vendor/magic_enum/include/;$(SolutionDir)cheat-base/vendor/fmt/include/;$(SolutionDir)cheat-base/vendor/imgui-notify-v2/;$(SolutionDir)cheat-base/vendor/simpleIni/;$(SolutionDir)cheat-base/vendor/imgui-notify-v2/;$(SolutionDir)cheat-base/vendor/detours/ MaxSpeed true diff --git a/cheat-library/src/user/cheat/misc/Debug.cpp b/cheat-library/src/user/cheat/misc/Debug.cpp index 0699dc3..e30396c 100644 --- a/cheat-library/src/user/cheat/misc/Debug.cpp +++ b/cheat-library/src/user/cheat/misc/Debug.cpp @@ -203,7 +203,8 @@ namespace cheat::feature for (auto entity : entities) { auto entityPos = entity->absolutePosition(); std::string baseString = csvFriendly ? "{},{},{},{},{},{}" : "{} {} {} x={} y={} z={}"; - auto entityDetails = fmt::format(baseString, + auto entityDetails = fmt::format( + fmt::runtime(baseString), fmt::ptr(entity), entity->runtimeID(), entity->name().c_str(), @@ -222,7 +223,8 @@ namespace cheat::feature std::string baseString = csvFriendly ? "{},{},{},{},{},{}" : "{} {} {} x={} y={} z={}"; if (csvFriendly && includeHeaders) baseString = headerString.append(baseString); - auto entityDetails = fmt::format(baseString, + auto entityDetails = fmt::format( + fmt::runtime(baseString), fmt::ptr(entity), entity->runtimeID(), entity->name().c_str(), diff --git a/injector/injector.vcxproj b/injector/injector.vcxproj index 836096f..7bf85d8 100644 --- a/injector/injector.vcxproj +++ b/injector/injector.vcxproj @@ -127,7 +127,7 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true - stdcpp17 + stdcpp20 $(ProjectDir)include/;$(SolutionDir)cheat-base/src;$(SolutionDir)cheat-base/vendor/simpleIni/ stdc17 From 37931b89a40920df29ad0df8111e7dc8ea12e226 Mon Sep 17 00:00:00 2001 From: Miya Date: Thu, 21 Jul 2022 02:00:48 +0800 Subject: [PATCH 02/30] fix interactive map revert latest point completion It looks like "unordered_set" is in forward order in memory instead of reverse order --- cheat-library/src/user/cheat/imap/InteractiveMap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheat-library/src/user/cheat/imap/InteractiveMap.cpp b/cheat-library/src/user/cheat/imap/InteractiveMap.cpp index 5cf9b3c..bf5c164 100644 --- a/cheat-library/src/user/cheat/imap/InteractiveMap.cpp +++ b/cheat-library/src/user/cheat/imap/InteractiveMap.cpp @@ -595,7 +595,7 @@ namespace cheat::feature if (m_CompletedPoints.empty()) return; - PointData* pointData = *m_CompletedPoints.begin(); + PointData* pointData = *--m_CompletedPoints.end(); pointData->completed = false; pointData->completeTimestamp = 0; m_ScenesData[pointData->sceneID].labels[pointData->labelID].completedCount--; From 30ed789e1225aaf9a9436ebe1e8181b2187f529f Mon Sep 17 00:00:00 2001 From: Miya Date: Thu, 21 Jul 2022 22:31:11 +0800 Subject: [PATCH 03/30] fixed revert last point completion the elements in unordered_set are not sorted in any particular order. so when insert point data , it will insert at begin or end or somewhere. so i changed it to list to make sure the last inserted element must be at the end of the list --- .../src/user/cheat/imap/InteractiveMap.cpp | 24 ++++++++++++------- .../src/user/cheat/imap/InteractiveMap.h | 3 ++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/cheat-library/src/user/cheat/imap/InteractiveMap.cpp b/cheat-library/src/user/cheat/imap/InteractiveMap.cpp index bf5c164..83c1ba8 100644 --- a/cheat-library/src/user/cheat/imap/InteractiveMap.cpp +++ b/cheat-library/src/user/cheat/imap/InteractiveMap.cpp @@ -563,13 +563,13 @@ namespace cheat::feature std::lock_guard _userDataLock(m_UserDataMutex); LOG_WARNING("Complete point at %.0f.", game::EntityManager::instance().avatar()->distance(pointData->levelPosition)); - if (m_CompletedPoints.count(pointData) > 0) + if (std::find_if(m_CompletedPoints.begin(), m_CompletedPoints.end(), [=](PointData* data) { return pointData->id == data->id; }) != std::end(m_CompletedPoints)) return; pointData->completed = true; pointData->completeTimestamp = util::GetCurrentTimeMillisec(); m_ScenesData[pointData->sceneID].labels[pointData->labelID].completedCount++; - m_CompletedPoints.insert(pointData); + m_CompletedPoints.push_back(pointData); SaveCompletedPoints(); } @@ -578,13 +578,14 @@ namespace cheat::feature { std::lock_guard _userDataLock(m_UserDataMutex); - if (m_CompletedPoints.count(pointData) == 0) + auto pointDataIterator = std::find_if(m_CompletedPoints.begin(), m_CompletedPoints.end(), [=](PointData* data) { return pointData->id == data->id; }); + if (pointDataIterator == m_CompletedPoints.end()) return; pointData->completed = false; pointData->completeTimestamp = 0; m_ScenesData[pointData->sceneID].labels[pointData->labelID].completedCount--; - m_CompletedPoints.erase(pointData); + m_CompletedPoints.erase(pointDataIterator); SaveCompletedPoints(); } @@ -595,11 +596,12 @@ namespace cheat::feature if (m_CompletedPoints.empty()) return; - PointData* pointData = *--m_CompletedPoints.end(); + auto pointDataIterator = --m_CompletedPoints.end(); + PointData* pointData = *pointDataIterator; pointData->completed = false; pointData->completeTimestamp = 0; m_ScenesData[pointData->sceneID].labels[pointData->labelID].completedCount--; - m_CompletedPoints.erase(pointData); + m_CompletedPoints.erase(pointDataIterator); SaveCompletedPoints(); } @@ -916,7 +918,7 @@ namespace cheat::feature } auto& point = points[pointID]; - if (m_CompletedPoints.count(&point) > 0) + if (std::find_if(m_CompletedPoints.begin(), m_CompletedPoints.end(), [=](PointData* data) { return point.id == data->id; }) != std::end(m_CompletedPoints)) { LOG_WARNING("Completed point %u duplicate.", pointID); return; @@ -926,7 +928,7 @@ namespace cheat::feature point.completeTimestamp = data["complete_timestamp"]; labelData->completedCount++; - m_CompletedPoints.insert(&point); + m_CompletedPoints.push_back(&point); } void InteractiveMap::LoadFixedPointData(LabelData* labelData, const nlohmann::json& data) @@ -1026,6 +1028,7 @@ namespace cheat::feature void InteractiveMap::LoadCompletedPoints() { LoadUserData(f_CompletedPointsJson, &InteractiveMap::LoadCompletedPointData); + ReorderCompletedPointDataByTimestamp(); } void InteractiveMap::SaveCompletedPoints() @@ -1040,6 +1043,11 @@ namespace cheat::feature m_CompletedPoints.clear(); } + void InteractiveMap::ReorderCompletedPointDataByTimestamp() + { + m_CompletedPoints.sort([](PointData* a, PointData* b) { return a->completeTimestamp < b->completeTimestamp; }); + } + void InteractiveMap::LoadCustomPoints() { LoadUserData(f_CustomPointsJson, &InteractiveMap::LoadCustomPointData); diff --git a/cheat-library/src/user/cheat/imap/InteractiveMap.h b/cheat-library/src/user/cheat/imap/InteractiveMap.h index 51b2f44..47b7cfa 100644 --- a/cheat-library/src/user/cheat/imap/InteractiveMap.h +++ b/cheat-library/src/user/cheat/imap/InteractiveMap.h @@ -146,7 +146,7 @@ namespace cheat::feature std::unordered_set m_CustomPoints; std::unordered_set m_FixedPoints; - std::unordered_set m_CompletedPoints; + std::list m_CompletedPoints; std::mutex m_PointMutex; // PointData* m_SelectedPoint; @@ -182,6 +182,7 @@ namespace cheat::feature void LoadCompletedPointData(LabelData* labelData, const nlohmann::json& data); void SaveCompletedPointData(nlohmann::json& jObject, PointData* point); bool ResetCompletedPointData(LabelData* label, PointData* point); + void ReorderCompletedPointDataByTimestamp(); void LoadCustomPointData(LabelData* labelData, const nlohmann::json& data); void SaveCustomPointData(nlohmann::json& jObject, PointData* point); From 578e260599dbd05746cbb427987196421c71c99d Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Fri, 29 Jul 2022 22:47:12 -0600 Subject: [PATCH 04/30] Added Buried Chest(Dig spots) to ESP --- cheat-library/res/icons/BookPage.png | Bin 0 -> 1659 bytes cheat-library/res/iconsHD/BookPage.png | Bin 0 -> 49501 bytes cheat-library/res/res.rc | 26 +++-- cheat-library/src/user/cheat/esp/ESP.cpp | 96 +++++++++--------- cheat-library/src/user/cheat/game/filters.cpp | 29 +++--- cheat-library/src/user/cheat/game/filters.h | 4 +- 6 files changed, 85 insertions(+), 70 deletions(-) create mode 100644 cheat-library/res/icons/BookPage.png create mode 100644 cheat-library/res/iconsHD/BookPage.png diff --git a/cheat-library/res/icons/BookPage.png b/cheat-library/res/icons/BookPage.png new file mode 100644 index 0000000000000000000000000000000000000000..c504ebe96a71f5a0d68cd22d6202294d7f7472e9 GIT binary patch literal 1659 zcmV->288*EP)J9p;Jj6Jq7xbm~ac1^HDlH$b3O>p^08%Xj~b=;_lOPVUJqDDmY0a7db z&Q<6aRdOkt}E|tN;eS2qfukXaZF}jQ%+_U zSA(!pLE2!f3vyOS3?Xjr#*+_J)xY-rzCP!`*AJ~XcO$We*>NCZu{aU+s_Vy_188_+ zZ}-F7wzoYNEU)@Pz#rOCU9&l?q=(t5sdvgNBX(kLUc55!%Vz-OR*P{fRjb*phq7O} z2cBzb-@e=OnQcN)Tcn~gR1t}QK`2QNQfftD1Z}@jDi)w+5pTT}Kls`&jvtN3<3?}q z+T_HN;7O%)BZGgIo~*vB%H z$?EiSnw6&v0H$gA4bx|mVVNiv^YHltMj@Z~c}jC@>(<)ChhBV%hi=mLuWe};@jLYK}vE?&$T0qg*xv{C2 zzIo{WdFJfxRIhGX0>Ha=)!Va|Cu$}qC(+d0EKq?b@p zQ3KEOP*dB0<>j={EOcX2UHySqpYOYq>Q!O}0MDD0_dn3Fvn*^20x3Hf!1Uw;cyt++uOef0I}G6dOg)^t|ixX^^oJ3e?B!j`pMYE zSTUa#g?wHm=4Pe7YtAYnjC58<*(L@KvHNd;yg zToys8kVARZCM>0rU?#4vuEawR@BATy5syc2)8lL4J$qcm%;NCt$6g)&Xk@6A&l#!3 zq+|uy!4QZDi^*9mUs<@iEeQ*W87L`1AP~bSdQ!Kx-naLO9j#qLd`(58QR7a;0Ki1V z%uKHzJ^q!k(T_*Mp@5l~pHZgIgi;b^<&}_9qU4pJHN&>USWYb<9H~SuvjnZdb#+_B zW4j-HgP9SJ$9W^f0Klmj} z2{1z#CWtJfq?GFH+_8J#=No@OMEZKww{;+{>uP6UxB0tMqeGLEb8n^>=FN*2&MQL* zD6a_1=L4&iJ_{ibE~^3nSOFW-DN*k%5i$k zQ-6CuHatA~r?aQtGYh$l7Q#R zzhzreDxJ?|P|D}T+{_FX7E>SOGU=1!pZx3ei4%W4GnT<90KK{veR>Y=0`X|n=p7tX z&+h5?$v5`*{Wz6Qmr{#KE1%6^e0<{l^TQ)=ygR(`4z7EVgb+~2j~mq6%Qqx&S0Dz^ zd0%DuBOTk`eyFp3pHe(=>C*JTPmlfa*ecP9{(dttGQz`ygY2#(aa$X-Ve+eA>qp;y z+Ue@pS_1&gOgCN<{|(UfHaGr1AY6lZJZkXWx9k5D{|5c@`*D2epzZ(w002ovPDHLk FV1k^GI(Gm7 literal 0 HcmV?d00001 diff --git a/cheat-library/res/iconsHD/BookPage.png b/cheat-library/res/iconsHD/BookPage.png new file mode 100644 index 0000000000000000000000000000000000000000..d13b14f8f66c03d9f47879c0ba828396564e7b26 GIT binary patch literal 49501 zcmb??Wm8;T6Yby@T!Xv2yE_RU+#$GIa2+7HhhRhS@W9~i65QPx+})i!??1S=>ehVd zkuz2MoZj8Ld#%;c>Z%IpsKlrM003P{QC1TGfPub+0U#qnjgk9bYp8*@k@_kH0MsO+ zy_zFHKT}#NYJLR({OAFI5Fh~X4E-wP5CHJv1OSfB0080N005zDPOF9}^an%>6$M$q z$Nye`I!aTaR|1q|rL=ukPTy>jzAOELAib}>ZM@X~Bs8#+EzZ_x1jT>inV1PLx~ z8w;S6G@wrt4-Yl#m=5xFe3js8z6vlnnYULmAyf|lAF7el^Y$o*lncUWWZndxg+THQRw4FB22AD(d^-o9UjpRU0$(1 z3Bb6b82gvcfPjUNCD=8XI3IL}5Huny{zm0(rQp4r$}ECv z2DMtO|F?Fdt}{d}?DXIBk6oK@-mD>H%gJgrr;PuPb`#*e%fO6?!c{4aDnk^ZcoKvS z;G%%*ZB}dJQ3%Ybooy4jKK-X$wCszJSA2T=o^U!;s^^W@{r}5O#wki#An4W1Lnu^1 z-XCO7N568d{*d`HE1?DkH3#P1&0h>9AYAfrq?G!PWj_S3?3@j$rJm{mdb=k#zuf*= zW`~ifWp({XXzLcA;M$E06kZiAMlk!AAng0Awh$0 zOD`PjI)B7gL7aS90}%aFZDSLniX&$Rjz_AFxlpFA=to7+X>!JRT9I{^@wj-Amknem!rx{BUd!oI#dsAzmRL-VK>U;H(0lFp;Lab zK@^y3U{rnzMM$c-t2VEWvAP^#OYd7CY`O=hkZo;y8h9qX+|T{woV`~ zQ;rXdOa*+&^U5)dNkFYetUjM@?B&O~6ovRHQ(=WfFTxf$AO?@Yv|Da}Xb&gAJ`P#+ zeR{4Lwmtx*C#jaobu8d5J8mpwIW*qDAzRWoMD!C=^-$CH5?AY0bBZ^z@S2B*AWPii z8s(WNwVAVFg{k|3bfhh&&Co#%$TBkg8TcpV&!z1g*|)0+beE}VWKfq;uY_Ir>XB$U z8TkIMp?Je?s@0*jrfVyNlT zO4DH{wR$l{fl1E#)iimw(1)(ZG$Y>bSB<}Ja+5eH%?S&1AFQmbL_Qhv!hHoPsSUe=KEDSWE&-S|#xiEg4tVcixHS*7B6iFU; zYx#g=6=0n{DW8umj3OLdAO3_1)8kzg?-^-c_iegA9T^nG{7|$*`G;aI(Y7`AL8d5Eo!Ewdrcdn z{BGB|vrR#(8H`SnmNfM`#O860wq#UAACH0AuXQi}HO}`8>opr3r<{l%@Ky>i01_lI z!vJxkeM0_$t<;CbZ4+zLVe|v_D+67$#k=q~Iw01$i=_s?w35=Qa#9Q&5{9R=6Xf~+ zM|u^oexcwfNAYOrjT~Udu>e3Umn2<-+@uHazqB~=KX?>NpL?LG#Qv<7>(nb*TkYEg z1;)k2Yq1h26>F|_d1OFdav{Z~+RqnJ{#rH{tc@E9E~ASC3-%f!sl(jD{MKpOR@|Q} z@D-2D!Tq*s_!BwPeyb?_s;0TTHpk7o-3kzNl&ppdtfo**j^tO7{Md(m(+8NhsbznJOiXPFF|OJuo&%5=*C_j;Z<>K zkedb)-MS_`f&rkaxT_9DqR!0>}dv^CaUZJ9^0o=C)ltc)5$IHu>7fMM*180N!?zi(~i#hrJovBMCo1_{R4#4&ulD9>!5lvX zV)$9Rm5)>XHmJQBXB@bx|3h^BuK+p`75VI~fHjibBkwhjB}@Pj#fySD4C_CF5Nr&u zjInijPxAPJ2I%RCPNYyS~Arkk>8-LYRoHItPh3Q9GFawct_ zHJ{el$>gHa4m8;DFgZ9l9*{>VB~3rN1-h4r>m8m1VWF0RC#_5UwoGO&5{= z3m;^VD)a=_Vh$-TrW25(sUD!VDga0tq;V0Yj_s>TAVSXFEv&294*w!&F`Ii>--cgF%rd6A-JSVqTO+Qej1(OtQF%un>Lz7zgob72H8TLBH2*8I#FMF!2iftxJ!{~+DHb~ny(4R4Sl2nqw z#uO#4|4^1XgkutL*k=y>CLv_C&IO6-*C#@ zR=djqpe7^y3XllbcYrAE8l?}J5{LYBqr;GKZ^!@hykXhYB1BD14W*nf9fTUIa`U{)43#T26k$5z$yxyw1S&=%W)2T6G7dy+qIcMswU$^BCp5$l7o2D z&0nq&6c?2fnMUR9)r<;<+twJ${rTsQ z7XcfWSGZ^dLZ%SGFT`+J6z`(N+jg?SBZ0_ydT3_GHw+thKKHAh3SwenB=5h7pa<5p z{j6hS|0o9q56LOw2^EksW`&iFZP>44*uo11EW#sqS*ouTCuUR0(Kx_aEtQ(+dW^`_G2#6gh5j&pR@m}qw8?U zNL`EgIeU8et%+o!jG?$-`Y&!Iwt+(Zs#DfD{aLkA8`+E_zipF@C!U52uWf@th@lM{ zmGMY5mLijq&5Tu@5cd&p(5A)+A>%{Z@czxNyZ$RBWx8_94QePC`_7bsij_=-+bi6? zdDc=h-roEk-FxuI%?FS#43pjXV_Xc$^zp6hb)zkF=n0p`G}NYg*dzWXkzde2MXapU zFLAe&boi0S97d4^o7SZ4YnPMs0v)E2GNx_n5z~;_m1zn?rg?I{o#e(0x_7yF@3pNY6BEpE}!{!G#AXU#Ia zGVK^6{@8;TGHT2+Jik~zPaN@7&23+k3Q;_RDiQcxx?O6NY@}K)dhy6Oo8a~30iszq z)|Ibr&v%F6Cv*KTTCe57PaJkl)a+}`H`%(@3-1*uf1=Y4Hxc7%NyOfV$-XfkB_4`B zdyX*Np9?Spa9KiV=k~1amx=%tR&I7uuuDF0=3ZfqT34(tso#nbcLwD{LbSPL@~d)I zXSGH;W(-F<79fVc#mkQ3rD@Vka(F_sZR(6klY~rZ%08KR#H*S4y5;4v8o(4(C*Dk> zg!lJ%AN2!9Jk+$&?@*r}IYt_>ABU<~65etkI(W>kE z=t(bw{AV~dzy=4DeK8ZQYk)mG8y6j2yu{^@;6vT)+aGC>VnGg&Q&UScGSN@H^M*5D zt4ZswTW~6bVftnp2Uq^Ad^v+QSpV-25V2e+_*ql});-PWFZ42|rg_=mx=f#` z1CelblJNRJ4JBlQmxWVO;SF55FwA3qcz0Hs*Knk&djms2CEbxFxnU+`Pi-}$UH5a{F1WAUK#GYT?H zVVMeLA?Hj5PvRM4NTR&>6>7IGbEYqj;(w>&C7x6dswNd~iiX{pw_@MPail4X6)4!!DdWXVyJ%@F9clh7w|5xoM__fvT}FafM#$iU z*sC_8L^^%Ca(+YfSL^ksAAe~Cs=Zdnv#$Oes?r~yeJ=3hO;TcPJ-n(?3_LJfX;Kdb9pHStNAh{=tHRN zT22?%P~rd9=88SxHmk8?)2RVRE|VVs$;>PTqQg%t4629bYUrg-gdQVae@V{1r) z8ahoNHn-S!-8+M5S<(dUPeAgZGT0 z>Y&C}=-$LluQN1A_c%9|&4nH*0yI z7jWCd{(I3%k+USpPj05-z%5RS=(tblVq0%#icPPcn}C1&z7pQUgAgXQsf3jrF@IGu zk^3<5z~?j<8l-wIZ!vj}(CN;(*eY_7YYFC6`r1g2fGxCJ^mtBwE+rRJiu8AwurI_A zG~`15c)wivww@XAs-6Q1jm?ONQSeyEDwjjyMC@DhR$(4rksXe>Hn%ll{~n>w<)(YT zo&lIY*}1UBM_I^GI!VeQ{=gS#{xf|7mYE=?{r)-oHCy7@asUx2*y;FvEf4u2!9Ij@ zZbXGCR}gOxqyJKCl&21ma+Rxu5OP$}(7+Eb6{4v*M~q%Dq(~woo6J=?xQT$1<|V`_ zu0FygxRfo?=;D4_E;}7;Rs9OZPh758f-fX)tFb=Er-k`-gkHSNE$Zm$=>clUd&BNR zb3^QKZoFkv8pm1m;Wi`7K5m>C@+K4dAIUf&7N zn=IOO=npvm3VASfSRhHp2{XpUeVu>k8qN4vsFK?3rcU-&*Gv0uZifPvNoz`&IeF)` zrlH)o!ROrGY$(}rIHWw6b$kOX-365`k~p7j*w13D@)Gk^@E`t-kLEq|UPWcPOp|1e zsKQ&;M%`k$TZ{GE}av3ufus<{KAh8KQ6`tzedgR zakb$=;`e08^quyCwtRN`Ywp&x$s7n6k8+bEO^1<`&qNnwlC@ za*CBZmKk8zY4nss<3f`16a+F^Luh&r3V!#U2_2MpD*cFyC7irDKFP}`i(qA)n1Nn! zdWyFK{M-G5RYcmUm7Dx>=A&pgRPd$bM&kIvS>=0q^T+;ML@n~sRGPG2fj5aIb%vH1 zbpc}$HUrWTBlQgXT4@8Cu`=D2Se~bF?3k~%Ces#@cu6goe_-keAv6t&pm@JT(k`Fx@^!t~tjcW{yitpg)QdHBsPAxT&!1`Bk)K@ny4y_u+GMjewiuiv zS|X6>&f_aG2}g@y5Eb{>W`UPv7qK;p%D~`$KoPPf^~%>lhRvC%^`1ZoL-u%KKwdy6 za>xO~BZxxec^9$YvLfD?r{+O|{plO^VPMEpo6JP^~sF=#b57st9wLDmQ(U=L+S!#s|#xC&Kk^t9WG5Pi{d2{ zA4M0K5>g11K*cFjY2m+}|DN1vv7W-Lm6ItxkF^VlYd<}0y^myM-K~^oekob8=Nsu) zj^Oxs<)}WG!j2pm1T?932=I;PiZnHQoRl;No*<&l@&Lac9P-p?VNF|~NF#e}ZK1mF$h{6_4?)AcVYHKvP{e$zG#&&7v zKfnPt31Gdf0Zo9MaQ05D=_~ceNqq1CXgE5UldtXiEc1I{9lA1dexEvv1eqh8Wm+OB zG6`B!MesxOwGxCP2p08Esb()x-^ev_2qVELJspB_Q+g@54R;LVR@ zmEzjF27LPlVN1)lF&3BhZyQZ65|)KKf4gbs77R^{EWUq_&?)SpcWP+Tp zG{g#+1gnq=dk$eFqTd_@zkAix)*>#&UhEPH1`G^%?GF?W zMt0)DvV4t;NOCiUf&%2fG6?ic4D$7ClSiz#ujO#0;+|nJ$b1tBO?|jTJ&wnAJ8QP` zf_LVPKl&&FPtMwZEeNd0=DoD!?VJujL=a|UYT!*{WE%_63|rTcf|>3P6+?iSWZH5M-{6Z zIRkUq!uf*6_AzKrXHFEx�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 literal 0 HcmV?d00001 diff --git a/cheat-library/res/res.rc b/cheat-library/res/res.rc index 3b9e066..923ed0e 100644 --- a/cheat-library/res/res.rc +++ b/cheat-library/res/res.rc @@ -25,21 +25,21 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // TEXTINCLUDE // -1 TEXTINCLUDE +1 TEXTINCLUDE BEGIN - "resource.h\0" +"resource.h\0" END -2 TEXTINCLUDE +2 TEXTINCLUDE BEGIN - "#include ""winres.h""\r\n" - "\0" +"#include ""winres.h""\r\n" +"\0" END -3 TEXTINCLUDE +3 TEXTINCLUDE BEGIN - "\r\n" - "\0" +"\r\n" +"\0" END #endif // APSTUDIO_INVOKED @@ -140,6 +140,8 @@ HDBOAR PNG "iconsHD\\Boar.png" HDBOOK PNG "iconsHD\\Book.png" +HDBOOKPAGE PNG "iconsHD\\BookPage.png" + HDBOOTWEASEL PNG "iconsHD\\BootWeasel.png" HDBRIGHTCROWNPIGEON PNG "iconsHD\\BrightcrownPigeon.png" @@ -316,6 +318,8 @@ HDGEOGRANUM PNG "iconsHD\\Geogranum.png" HDGEOHYPOSTASIS PNG "iconsHD\\GeoHypostasis.png" +HDGEOPUZZLE PNG "iconsHD\\MiniPuzzle.png" + HDGEOSIGIL PNG "iconsHD\\GeoSigil.png" HDGEOVISHAP PNG "iconsHD\\Geovishap.png" @@ -626,7 +630,7 @@ HDSHOGUN PNG "iconsHD\\Shogun.png" HDSHOGUNATEINFANTRY PNG "iconsHD\\ShogunateInfantry.png" -HDSHRINEOFDEPTH PNG "iconsHD\\ShrineOfDepth.png" +HDSHRINEOFDEPTH PNG "iconsHD\\Mondstadt.png" HDSIGNORA PNG "iconsHD\\Signora.png" @@ -850,6 +854,8 @@ BOAR PNG "icons\\Boar.png" BOOK PNG "icons\\Book.png" +BOOKPAGE PNG "icons\\BookPage.png" + BOOTWEASEL PNG "icons\\BootWeasel.png" BRIGHTCROWNPIGEON PNG "icons\\BrightcrownPigeon.png" @@ -1026,6 +1032,8 @@ GEOGRANUM PNG "icons\\Geogranum.png" GEOHYPOSTASIS PNG "icons\\GeoHypostasis.png" +GEOPUZZLE PNG "icons\\MiniPuzzle.png" + GEOSIGIL PNG "icons\\GeoSigil.png" GEOVISHAP PNG "icons\\Geovishap.png" diff --git a/cheat-library/src/user/cheat/esp/ESP.cpp b/cheat-library/src/user/cheat/esp/ESP.cpp index 98a8d30..43d5d0b 100644 --- a/cheat-library/src/user/cheat/esp/ESP.cpp +++ b/cheat-library/src/user/cheat/esp/ESP.cpp @@ -21,17 +21,17 @@ namespace cheat::feature ESP::ESP() : Feature(), NF(f_Enabled, "ESP", "ESP", false), - NF(f_DrawBoxMode, "Draw Mode", "ESP", DrawMode::Box), + NF(f_DrawBoxMode, "Draw Mode", "ESP", DrawMode::Box), NF(f_DrawTracerMode, "Tracer Mode", "ESP", DrawTracerMode::Line), - NF(f_Fill, "Fill Box/Rectangle/Arrows", "ESP", false), - NF(f_FillTransparency, "Fill Transparency", "ESP", 0.5f), + NF(f_Fill, "Fill Box/Rectangle/Arrows", "ESP", false), + NF(f_FillTransparency, "Fill Transparency", "ESP", 0.5f), NF(f_ArrowRadius, "Arrow Radius", "ESP", 100.0f), NF(f_OutlineThickness, "Outline Thickness", "ESP", 1.0f), NF(f_TracerSize, "Tracer Size", "ESP", 1.0f), NF(f_MiddleScreenTracer, "Middle Screen Tracer", "ESP", false), - NF(f_DrawDistance, "Draw Distance", "ESP", false), - NF(f_DrawName, "Draw Name", "ESP", false), + NF(f_DrawDistance, "Draw Distance", "ESP", false), + NF(f_DrawName, "Draw Name", "ESP", false), NF(f_FontSize, "Font Size", "ESP", 12.0f), NF(f_FontOutline, "Font outline", "ESP", true), @@ -69,7 +69,7 @@ namespace cheat::feature ConfigWidget(f_DrawBoxMode, "Select the mode of box drawing."); ConfigWidget(f_DrawTracerMode, "Select the mode of tracer drawing."); - + ConfigWidget(f_Fill); ConfigWidget(f_FillTransparency, 0.01f, 0.0f, 1.0f, "Transparency of filled part."); ConfigWidget(f_MiddleScreenTracer, "Draw tracer from middle part of the screen."); @@ -84,7 +84,7 @@ namespace cheat::feature } ImGui::EndGroupPanel(); } - + ImGui::Spacing(); ConfigWidget(f_DrawName, "Draw name of object."); ConfigWidget(f_DrawDistance, "Draw distance of object."); @@ -189,55 +189,55 @@ namespace cheat::feature //switch statement to determine how we will get name switch (count) { - case 3: + case 3: + { + j = 0; // j is the number of spaces before the name starts + pos1 = 0; + pos2 = 0; + for (int i = 0; i < name.length(); i++) { - j = 0; // j is the number of spaces before the name starts - pos1 = 0; - pos2 = 0; - for (int i = 0; i < name.length(); i++) + if (name[i] == '_') { - if (name[i] == '_') + j++; + if (j == 3) { - j++; - if (j == 3) - { - pos1 = i; - } - + pos1 = i; } - if (name[i] == '(') + + } + if (name[i] == '(') + { + pos2 = i; + break; + } + } + name = name.substr(pos1, pos2 - pos1); + } + case 4: + { + j = 0; // j is the number of spaces before the name starts + pos1 = 0; + pos2 = 0; + for (int i = 0; i < name.length(); i++) + { + if (name[i] == '_') + { + j++; + if (j == 3) + { + pos1 = i; + } + if (j == 4) { pos2 = i; break; } } - name = name.substr(pos1, pos2 - pos1); } - case 4: - { - j = 0; // j is the number of spaces before the name starts - pos1 = 0; - pos2 = 0; - for (int i = 0; i < name.length(); i++) - { - if (name[i] == '_') - { - j++; - if (j == 3) - { - pos1 = i; - } - if (j == 4) - { - pos2 = i; - break; - } - } - } - name = name.substr(pos1 + 1, pos2 - pos1 - 1); - } - default: - break; + name = name.substr(pos1 + 1, pos2 - pos1 - 1); + } + default: + break; } return; } @@ -574,12 +574,16 @@ namespace cheat::feature ADD_FILTER_FIELD(collection, WoodenCrate); ADD_FILTER_FIELD(collection, GeoSigil); + // Regular Chests ADD_FILTER_FIELD(chest, CommonChest); ADD_FILTER_FIELD(chest, ExquisiteChest); ADD_FILTER_FIELD(chest, PreciousChest); ADD_FILTER_FIELD(chest, LuxuriousChest); ADD_FILTER_FIELD(chest, RemarkableChest); + // Other Chests + ADD_FILTER_FIELD(chest, BuriedChest); ADD_FILTER_FIELD(chest, SearchPoint); + ADD_FILTER_FIELD(featured, Anemoculus); ADD_FILTER_FIELD(featured, CrimsonAgate); diff --git a/cheat-library/src/user/cheat/game/filters.cpp b/cheat-library/src/user/cheat/game/filters.cpp index 0827961..781c30e 100644 --- a/cheat-library/src/user/cheat/game/filters.cpp +++ b/cheat-library/src/user/cheat/game/filters.cpp @@ -32,6 +32,7 @@ namespace cheat::game::filters ChestFilter SFrozen = ChestFilter(Chest::ChestState::Frozen); ChestFilter SBramble = ChestFilter(Chest::ChestState::Bramble); ChestFilter STrap = ChestFilter(Chest::ChestState::Trap); + SimpleFilter BuriedChest = { EntityType__Enum_1::Field, "_WorldArea_Operator" }; } namespace equipment @@ -111,7 +112,7 @@ namespace cheat::game::filters SimpleFilter WeaselThief = { EntityType__Enum_1::Monster, "Thoarder_Weasel" }; SimpleFilter Kitsune = { EntityType__Enum_1::EnvAnimal, "Vulpes" }; SimpleFilter BakeDanuki = { EntityType__Enum_1::Monster, "Inu_Tanuki" }; - SimpleFilter Meat = { EntityType__Enum_1::GatherObject , { "_Food_BirdMeat", "_Food_Meat", "_Fishmeat" }}; + SimpleFilter Meat = { EntityType__Enum_1::GatherObject , { "_Food_BirdMeat", "_Food_Meat", "_Fishmeat" } }; } namespace mineral @@ -131,7 +132,7 @@ namespace cheat::game::filters SimpleFilter DunlinsTooth = { EntityType__Enum_1::GatherObject, "_DunlinsTooth" }; SimpleFilter AmethystLumpDrop = { EntityType__Enum_1::GatherObject, "_Thundercrystaldrop" }; - SimpleFilter CrystalChunkDrop = { EntityType__Enum_1::GatherObject,"_Drop_Crystal"}; + SimpleFilter CrystalChunkDrop = { EntityType__Enum_1::GatherObject,"_Drop_Crystal" }; SimpleFilter ElectroCrystalDrop = { EntityType__Enum_1::GatherObject, "_Drop_Ore_ElectricRock" }; SimpleFilter IronChunkDrop = { EntityType__Enum_1::GatherObject, "_Drop_Stone" }; SimpleFilter NoctilucousJadeDrop = { EntityType__Enum_1::GatherObject,"_NightBerth" }; @@ -161,7 +162,7 @@ namespace cheat::game::filters SimpleFilter RuinGrader = { EntityType__Enum_1::Monster, "_Konungmathr" }; SimpleFilter RuinSentinel = { EntityType__Enum_1::Monster, "_Apparatus_Enigma" }; SimpleFilter Samachurl = { EntityType__Enum_1::Monster, "_Shaman" }; - SimpleFilter ShadowyHusk = { EntityType__Enum_1::Monster, "ForlornVessel_Strong" }; + SimpleFilter ShadowyHusk = { EntityType__Enum_1::Monster, "ForlornVessel_Strong" }; SimpleFilter Slime = { EntityType__Enum_1::Monster, "_Slime" }; SimpleFilter FloatingFungus = { EntityType__Enum_1::Monster, "Fungus_Un_" }; SimpleFilter StretchyFungus = { EntityType__Enum_1::Monster, "Fungus_Deux_" }; @@ -221,7 +222,7 @@ namespace cheat::game::filters SimpleFilter JadeplumeTerrorshroom = { EntityType__Enum_1::Monster, "Fungus_Raptor" }; SimpleFilter RishbolandTiger = { EntityType__Enum_1::Monster, "_Megamoth_" }; SimpleFilter ShaggySumpterBeast = { EntityType__Enum_1::Monster, "_Panther" }; - SimpleFilter Spincrocodile = { EntityType__Enum_1::Monster, "_Gator" }; + SimpleFilter Spincrocodile = { EntityType__Enum_1::Monster, "_Gator" }; SimpleFilter SentryTurrets = { EntityType__Enum_1::Field, "SentryTurrets_" }; } @@ -285,7 +286,7 @@ namespace cheat::game::filters SimpleFilter AncientRime = { EntityType__Enum_1::Gadget, "_IceSolidBulk" }; SimpleFilter BakeDanuki = { EntityType__Enum_1::Monster, "Animal_Inu_Tanuki_" }; SimpleFilter BloattyFloatty = { EntityType__Enum_1::Field, "_Flower_PongPongTree_" }; - WhitelistFilter CubeDevices = { {EntityType__Enum_1::Gadget, EntityType__Enum_1::Platform }, {"_ElecStone", "_ElecSwitch" }}; + WhitelistFilter CubeDevices = { {EntityType__Enum_1::Gadget, EntityType__Enum_1::Platform }, {"_ElecStone", "_ElecSwitch" } }; SimpleFilter EightStoneTablets = { EntityType__Enum_1::Gadget, "_HistoryBoard" }; SimpleFilter ElectricConduction = { EntityType__Enum_1::Gear, "_ElectricPowerSource" }; SimpleFilter RelayStone = { EntityType__Enum_1::Worktop, "_ElectricTransfer_" }; @@ -518,15 +519,15 @@ namespace cheat::game::filters monster::Whopperflower }; SimpleFilter MonsterEquips = { EntityType__Enum_1::MonsterEquip }; - BlacklistFilter Living = { - {EntityType__Enum_1::EnvAnimal, EntityType__Enum_1::Monster}, - { - // Environmental mobs - "Cat", "DogPrick", "Vulpues", "Inu_Tanuki", - // Overworld bosses - "Ningyo", "Regisvine", "Hypostasis", "Planelurker", "Nithhoggr" - } - }; + BlacklistFilter Living = { + {EntityType__Enum_1::EnvAnimal, EntityType__Enum_1::Monster}, + { + // Environmental mobs + "Cat", "DogPrick", "Vulpues", "Inu_Tanuki", + // Overworld bosses + "Ningyo", "Regisvine", "Hypostasis", "Planelurker", "Nithhoggr" + } + }; SimpleFilter OrganicTargets = { Monsters, Animals }; // Solael: Please don't mess around with this filter. //m0nkrel: We can choose the entities we need ourselves so as not to magnetize cats, dogs, etc. //AdvancedFilter Animals = { {EntityType__Enum_1::EnvAnimal, EntityType__Enum_1::Monster }, {"Crane", "Tit", "Boar", "Squirrel", "Fox", "Pigeon", "Wigeon", "Falcon" ,"Marten" } }; diff --git a/cheat-library/src/user/cheat/game/filters.h b/cheat-library/src/user/cheat/game/filters.h index 8a9f2a2..f5fa633 100644 --- a/cheat-library/src/user/cheat/game/filters.h +++ b/cheat-library/src/user/cheat/game/filters.h @@ -32,6 +32,8 @@ namespace cheat::game::filters extern ChestFilter SFrozen; extern ChestFilter SBramble; extern ChestFilter STrap; + + extern SimpleFilter BuriedChest; } namespace equipment @@ -220,7 +222,7 @@ namespace cheat::game::filters extern SimpleFilter Beisht; extern SimpleFilter RishbolandTiger; extern SimpleFilter ShaggySumpterBeast; - extern SimpleFilter Spincrocodile; + extern SimpleFilter Spincrocodile; extern SimpleFilter SentryTurrets; } From 9eb7e87b832d20e458306e93579923dc90596c27 Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Fri, 29 Jul 2022 23:40:39 -0600 Subject: [PATCH 05/30] Added AutoDestroy:Plants --- cheat-library/src/user/cheat/game/filters.cpp | 7 +++++++ cheat-library/src/user/cheat/game/filters.h | 1 + cheat-library/src/user/cheat/world/AutoDestroy.cpp | 14 +++++++++----- cheat-library/src/user/cheat/world/AutoDestroy.h | 1 + 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/cheat-library/src/user/cheat/game/filters.cpp b/cheat-library/src/user/cheat/game/filters.cpp index 781c30e..3c23e4f 100644 --- a/cheat-library/src/user/cheat/game/filters.cpp +++ b/cheat-library/src/user/cheat/game/filters.cpp @@ -347,6 +347,13 @@ namespace cheat::game::filters mineral::Starsilver, mineral::WhiteIronChunk }; + SimpleFilter PlantDestroy = { + //plant::SakuraBloom, + plant::DandelionSeed, + plant::MistFlowerCorolla, + plant::FlamingFlowerStamen + }; + WhitelistFilter Doodads = { EntityType__Enum_1::Gadget, { diff --git a/cheat-library/src/user/cheat/game/filters.h b/cheat-library/src/user/cheat/game/filters.h index f5fa633..2edd84f 100644 --- a/cheat-library/src/user/cheat/game/filters.h +++ b/cheat-library/src/user/cheat/game/filters.h @@ -327,6 +327,7 @@ namespace cheat::game::filters extern SimpleFilter Oculies; extern SimpleFilter Chests; extern SimpleFilter Ores; + extern SimpleFilter PlantDestroy; extern WhitelistFilter Doodads; extern SimpleFilter Animals; extern SimpleFilter AnimalDrop; diff --git a/cheat-library/src/user/cheat/world/AutoDestroy.cpp b/cheat-library/src/user/cheat/world/AutoDestroy.cpp index 65d26a3..4ee4168 100644 --- a/cheat-library/src/user/cheat/world/AutoDestroy.cpp +++ b/cheat-library/src/user/cheat/world/AutoDestroy.cpp @@ -18,6 +18,7 @@ namespace cheat::feature NF(f_DestroyOres, "Destroy Ores", "AutoDestroy", false), NF(f_DestroyShields, "Destroy Shields", "AutoDestroy", false), NF(f_DestroyDoodads, "Destroy Doodads", "AutoDestroy", false), + NF(f_DestroyPlants, "Destroy Plants", "AutoDestroy", false), NF(f_Range, "Range", "AutoDestroy", 10.0f) { HookManager::install(app::MoleMole_LCAbilityElement_ReduceModifierDurability, LCAbilityElement_ReduceModifierDurability_Hook); @@ -43,6 +44,7 @@ namespace cheat::feature ConfigWidget("Doodads", f_DestroyDoodads, "Barrels, boxes, vases, etc."); ImGui::SameLine(); ImGui::TextColored(ImColor(255, 165, 0, 255), "Extremely risky!"); + ConfigWidget("Plants", f_DestroyPlants, "Dandelion Seeds, Sakura Bloom, etc."); ImGui::Unindent(); ConfigWidget("Range (m)", f_Range, 0.1f, 1.0f, 15.0f); } @@ -54,12 +56,13 @@ namespace cheat::feature void AutoDestroy::DrawStatus() { - ImGui::Text("Destroy [%.01fm%s%s%s%s]", + ImGui::Text("Destroy [%.01fm%s%s%s%s%s]", f_Range.value(), - f_DestroyOres || f_DestroyShields || f_DestroyDoodads ? "|" : "", + f_DestroyOres || f_DestroyShields || f_DestroyDoodads || f_DestroyPlants ? "|" : "", f_DestroyOres ? "O" : "", f_DestroyShields ? "S" : "", - f_DestroyDoodads ? "D" : ""); + f_DestroyDoodads ? "D" : "", + f_DestroyPlants ? "P" : ""); } AutoDestroy& AutoDestroy::GetInstance() @@ -86,8 +89,9 @@ namespace cheat::feature (autoDestroy.f_DestroyDoodads && game::filters::combined::Doodads.IsValid(manager.entity(entity))) || (autoDestroy.f_DestroyShields && !game::filters::combined::MonsterBosses.IsValid(manager.entity(entity)) && ( game::filters::combined::MonsterShielded.IsValid(manager.entity(entity)) || // For shields attached to monsters, e.g. abyss mage shields. - game::filters::combined::MonsterEquips.IsValid(manager.entity(entity)) // For shields/weapons equipped by monsters, e.g. rock shield. - )) + game::filters::combined::MonsterEquips.IsValid(manager.entity(entity)) || // For shields/weapons equipped by monsters, e.g. rock shield. + (autoDestroy.f_DestroyPlants && game::filters::combined::PlantDestroy.IsValid(manager.entity(entity))) // For plants e.g dandelion seeds. + )) ) ) { diff --git a/cheat-library/src/user/cheat/world/AutoDestroy.h b/cheat-library/src/user/cheat/world/AutoDestroy.h index 14e0985..d4c47a0 100644 --- a/cheat-library/src/user/cheat/world/AutoDestroy.h +++ b/cheat-library/src/user/cheat/world/AutoDestroy.h @@ -12,6 +12,7 @@ namespace cheat::feature config::Field> f_DestroyOres; config::Field> f_DestroyShields; config::Field> f_DestroyDoodads; + config::Field> f_DestroyPlants; config::Field f_Range; static AutoDestroy& GetInstance(); From a82fcaba479c203c7e35383163e4a6a077f5774b Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Sat, 30 Jul 2022 00:21:02 -0600 Subject: [PATCH 06/30] [WIP] Animation Changer --- cheat-library/cheat-library.vcxproj | 4 + cheat-library/cheat-library.vcxproj.filters | 12 + cheat-library/src/user/cheat/cheat.cpp | 4 +- .../user/cheat/visuals/AnimationChanger.cpp | 292 ++++++++++++++++++ .../src/user/cheat/visuals/AnimationChanger.h | 26 ++ 5 files changed, 337 insertions(+), 1 deletion(-) create mode 100644 cheat-library/src/user/cheat/visuals/AnimationChanger.cpp create mode 100644 cheat-library/src/user/cheat/visuals/AnimationChanger.h diff --git a/cheat-library/cheat-library.vcxproj b/cheat-library/cheat-library.vcxproj index af6ba65..04f14df 100644 --- a/cheat-library/cheat-library.vcxproj +++ b/cheat-library/cheat-library.vcxproj @@ -21,6 +21,7 @@ + @@ -113,6 +114,7 @@ + @@ -219,6 +221,7 @@ + @@ -557,6 +560,7 @@ + diff --git a/cheat-library/cheat-library.vcxproj.filters b/cheat-library/cheat-library.vcxproj.filters index 7392f94..c949b36 100644 --- a/cheat-library/cheat-library.vcxproj.filters +++ b/cheat-library/cheat-library.vcxproj.filters @@ -252,6 +252,9 @@ Header Files + + Header Files + @@ -462,6 +465,9 @@ Source Files + + Source Files + @@ -2508,5 +2514,11 @@ Resource Files + + Resource Files + + + Resource Files + \ No newline at end of file diff --git a/cheat-library/src/user/cheat/cheat.cpp b/cheat-library/src/user/cheat/cheat.cpp index 5093d7f..1dbdcae 100644 --- a/cheat-library/src/user/cheat/cheat.cpp +++ b/cheat-library/src/user/cheat/cheat.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include "GenshinCM.h" @@ -122,7 +123,8 @@ namespace cheat FEAT_INST(Browser), FEAT_INST(EnablePeeking), FEAT_INST(TextureChanger), - FEAT_INST(FreeCamera) + FEAT_INST(FreeCamera), + FEAT_INST(AnimationChanger) }); #undef FEAT_INST diff --git a/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp b/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp new file mode 100644 index 0000000..bca2fd5 --- /dev/null +++ b/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp @@ -0,0 +1,292 @@ +#include "pch-il2cpp.h" +#include "AnimationChanger.h" + +#include +#include +#include +#include + +namespace cheat::feature +{ + static std::string f_Animation; + + AnimationChanger::AnimationChanger() : Feature(), + NFEX(f_Enabled, "Animation Changer", "AnimationChanger", "Visuals", false, false) + { + events::GameUpdateEvent += MY_METHOD_HANDLER(AnimationChanger::OnGameUpdate); + } + + const FeatureGUIInfo& AnimationChanger::GetGUIInfo() const + { + static const FeatureGUIInfo info{ "AnimationChanger", "Visuals", false }; + return info; + } + + void AnimationChanger::DrawMain() + { + ConfigWidget(f_Enabled, "Changes active character's animation."); + ImGui::InputText("Animation", &f_Animation); + } + + bool AnimationChanger::NeedStatusDraw() const + { + return f_Enabled; + } + + void AnimationChanger::DrawStatus() + { + ImGui::Text("AnimationChanger"); + } + + AnimationChanger& AnimationChanger::GetInstance() + { + static AnimationChanger instance; + return instance; + } + + void AnimationChanger::OnGameUpdate() + { + auto& manager = game::EntityManager::instance(); + auto avatar = manager.avatar(); + if (avatar->animator() == nullptr) + return; + + static bool changed = false; + + if (f_Enabled) + { + auto avatarObj = avatar->gameObject(); + auto rootObj = app::MoleMole_BaseEntity_get_rootGameObject(avatar->raw(), nullptr); // (Clone) + auto path = app::Object_1_get_name(reinterpret_cast(avatarObj), nullptr); + auto pathavatarObj = app::Object_1_get_name(reinterpret_cast(rootObj), nullptr); // (Clone) + + if (!changed) + { + app::Animator_Play(avatar->animator(), string_to_il2cppi(f_Animation.c_str()), 0, 0, nullptr); + changed = true; + } + + } + else + { + if (changed) + { + app::Animator_Rebind(avatar->animator(), nullptr); + changed = false; + } + } + } +} + +/* +//------Animations------\\ +SlipFaceWall +SlipBackWall +DropDown +JumpOffWall +Jump +JumpForRun +JumpForWalk +Fly +FlyStart +JumpForSprint +SwimIdle +SwimMove +SwimDash +ClimbMove1 +ClimbIdle +ClimbJump +ClimbMove0 +FallToGroundRun +FallOnGroundLit +FallOnGround +FallToGroundRunHard +FallToGroundSprint +Walk +Run +Standby +RunToIdle +RunToWalk +WalkToIdle +WalkToRun +Sprint +SprintToIdle +SprintToRun +ClimbDownToGround +SprintBS +ShowUp +CrouchToStandby +CrouchIdle +CrouchRoll +CrouchMove +SkiffNormal +Upstairs +JumpUpWallForStandby +JumpUpWallReady +Standby2ClimbA +SwimJump +SwimJumpDrop +SwimJumpToWater +Standby2ClimbB +CrouchDrop +TurnDir +StandbyWeapon +StandbyPutaway +StandbyPutawayOver +Icespine_Out +Icespine +LiquidStrike_MoveStandby +LiquidStrike_AS +LiquidStrike_BS +LiquidStrike_BS1 +LiquidStrike_Move +LiquidStrike_Strike +LiquidStrike_FatalStandby +LiquidStrike_FatalMove +LiquidStrike_AS_OnWater +LiquidStrike_BS_0 +FrozenWindmill +FrozenWindmill_AS +Attack03 +Attack04 +Attack05 +Attack01 +Attack02 +ExtraAttack +ExtraAttack_AS +FallingAnthem_Loop +FallingAnthem_AS_2 +FallingAnthem_BS_1 +FallingAnthem_BS_2 +FallingAnthem_AS_1 +FallingAnthem_Loop_Low +SitBDown +SitBLoop +SitBUp +SitDown +SitLoop +SitUp +StandbyShow_01 +StandbyShow_02 +StandbyVoice +Think01BS +Think01Loop +Think01AS +Akimbo02BS +Akimbo02Loop +Akimbo02AS +ChannelBS +ChannelLoop +ChannelAS +PlayMusic_Lyre_AS +PlayMusic_Lyre_BS +PlayMusic_Lyre_Loop +PlayMusic_Qin_BS +PlayMusic_Qin_AS +PlayMusic_Qin_Loop +ActivitySkill_ElectricCoreFly +Hit_H +Hit_L +Hit_Throw +Hit_Throw_Ground +Hit_ThrowAir +Struggle +NormalDie +SwimDie +HitGroundDie +FallDie_AS +FallDie + +//------Main Character------\\ +UziExplode_AS +UziExplode_BS +UziExplode_Charge_01 +UziExplode_Strike_02 +UziExplode_Charge_02 +UziExplode_Strike_01 +UziExplode_BS_1 +WindBreathe_AS +WindBreathe +Hogyoku_AS +Hogyoku_BS +Hogyoku +Hogyoku_Charge +Hogyoku_Charge_AS +Hogyoku_Charge_2 +RockTide_AS +RockTide +CrouchThrowBS +CrouchThrowLoop +CrouchThrowAS +FindCatThrowBS +FindCatThrowLoop +FindCatThrowAS +Player_Electric_ElementalArt +Player_Electric_ElementalArt_AS +Player_Electric_ElementalBurst +Player_Electric_ElementalBurst_AS +PutHand01BS +PutHand01Loop +PutHand01AS +Akimbo01BS +Backrake01BS +Forerake01BS +StrikeChest01BS +Akimbo01Loop +Akimbo01AS +Backrake01Loop +Backrake01AS +Forerake01Loop +Forerake01AS +StrikeChest01Loop +StrikeChest01AS +HoldHead01BS +HoldHead01Loop +HoldHead01AS +Clap01 +Turn01_90LBS +Turn01_90RBS +Turn01_90LAS +Turn01_90RAS +Alert01BS +Alert01Loop +Alert01AS +Fishing01_BS +Fishing01Loop +Fishing01AS +Think01_BS +Think01_Loop +Think01_AS +Channel01BS +Channel01Loop +Channel01AS +Fishing_Battle_BS +Fishing_Cast_AS +Fishing_Cast_BS +Fishing_Cast_Loop +Fishing_Choose +Fishing_Choose_Loop +Fishing_End +Fishing_Pull_01 +Fishing_Pull_02 +Fishing_Wait +Fishing_Pull_Fail +Bartender_MixingStandby +Bartender_MixingStart +Bartender_MixingToPour +Bartender_Pour +Bartender_PourFinish +Bartender_PourStandby +Bartender_AddLoop +Bartender_PrepareStart +Bartender_Standby +Bartender_AddStandby +Bartender_PrepareToStandby +Bartender_StandbyFinish +Blocking_BS +Blocking_Loop +Blocking_Back +Blocking_Bounce +Blocking_Hit +Blocking_AS +*/ \ No newline at end of file diff --git a/cheat-library/src/user/cheat/visuals/AnimationChanger.h b/cheat-library/src/user/cheat/visuals/AnimationChanger.h new file mode 100644 index 0000000..309bdf9 --- /dev/null +++ b/cheat-library/src/user/cheat/visuals/AnimationChanger.h @@ -0,0 +1,26 @@ +#pragma once +#include +#include + +namespace cheat::feature +{ + + class AnimationChanger : public Feature + { + public: + config::Field> f_Enabled; + + static AnimationChanger& GetInstance(); + + const FeatureGUIInfo& GetGUIInfo() const override; + void DrawMain() override; + + virtual bool NeedStatusDraw() const override; + void DrawStatus() override; + void OnGameUpdate(); + + private: + AnimationChanger(); + }; +} + From 69fdabafc5f7e908f534bc6fa03c06de30f7fc70 Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Sat, 30 Jul 2022 18:06:43 -0600 Subject: [PATCH 07/30] Refactored Animation Changer, Added Sealed Chest to AutoDestroy --- .../user/cheat/visuals/AnimationChanger.cpp | 487 +++++++++--------- .../src/user/cheat/visuals/AnimationChanger.h | 2 + .../src/user/cheat/world/AutoDestroy.cpp | 4 +- 3 files changed, 253 insertions(+), 240 deletions(-) diff --git a/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp b/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp index bca2fd5..83daebd 100644 --- a/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp +++ b/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp @@ -8,10 +8,222 @@ namespace cheat::feature { - static std::string f_Animation; - + static std::string animations[] = { + // All characters + "SlipFaceWall", + "SlipBackWall", + "DropDown", + "JumpOffWall", + "Jump", + "JumpForRun", + "JumpForWalk", + "Fly", + "FlyStart", + "JumpForSprint", + "SwimIdle", + "SwimMove", + "SwimDash", + "ClimbMove1", + "ClimbIdle", + "ClimbJump", + "ClimbMove0", + "FallToGroundRun", + "FallOnGroundLit", + "FallOnGround", + "FallToGroundRunHard", + "FallToGroundSprint", + "Walk", + "Run", + "Standby", + "RunToIdle", + "RunToWalk", + "WalkToIdle", + "WalkToRun", + "Sprint", + "SprintToIdle", + "SprintToRun", + "ClimbDownToGround", + "SprintBS", + "ShowUp", + "CrouchToStandby", + "CrouchIdle", + "CrouchRoll", + "CrouchMove", + "SkiffNormal", + "Upstairs", + "JumpUpWallForStandby", + "JumpUpWallReady", + "Standby2ClimbA", + "SwimJump", + "SwimJumpDrop", + "SwimJumpToWater", + "Standby2ClimbB", + "CrouchDrop", + "TurnDir", + "StandbyWeapon", + "StandbyPutaway", + "StandbyPutawayOver", + "Icespine_Out", + "Icespine", + "LiquidStrike_MoveStandby", + "LiquidStrike_AS", + "LiquidStrike_BS", + "LiquidStrike_BS1", + "LiquidStrike_Move", + "LiquidStrike_Strike", + "LiquidStrike_FatalStandby", + "LiquidStrike_FatalMove", + "LiquidStrike_AS_OnWater", + "LiquidStrike_BS_0", + "FrozenWindmill", + "FrozenWindmill_AS", + "Attack03", + "Attack04", + "Attack05", + "Attack01", + "Attack02", + "ExtraAttack", + "ExtraAttack_AS", + "FallingAnthem_Loop", + "FallingAnthem_AS_2", + "FallingAnthem_BS_1", + "FallingAnthem_BS_2", + "FallingAnthem_AS_1", + "FallingAnthem_Loop_Low", + "SitBDown", + "SitBLoop", + "SitBUp", + "SitDown", + "SitLoop", + "SitUp", + "StandbyShow_01", + "StandbyShow_02", + "StandbyVoice", + "Think01BS", + "Think01Loop", + "Think01AS", + "Akimbo02BS", + "Akimbo02Loop", + "Akimbo02AS", + "ChannelBS", + "ChannelLoop", + "ChannelAS", + "PlayMusic_Lyre_AS", + "PlayMusic_Lyre_BS", + "PlayMusic_Lyre_Loop", + "PlayMusic_Qin_BS", + "PlayMusic_Qin_AS", + "PlayMusic_Qin_Loop", + "ActivitySkill_ElectricCoreFly", + "Hit_H", + "Hit_L", + "Hit_Throw", + "Hit_Throw_Ground", + "Hit_ThrowAir", + "Struggle", + "NormalDie", + "SwimDie", + "HitGroundDie", + "FallDie_AS", + "FallDie", + // Main Character only + "UziExplode_AS", + "UziExplode_BS", + "UziExplode_Charge_01", + "UziExplode_Strike_02", + "UziExplode_Charge_02", + "UziExplode_Strike_01", + "UziExplode_BS_1", + "WindBreathe_AS", + "WindBreathe", + "Hogyoku_AS", + "Hogyoku_BS", + "Hogyoku", + "Hogyoku_Charge", + "Hogyoku_Charge_AS", + "Hogyoku_Charge_2", + "RockTide_AS", + "RockTide", + "CrouchThrowBS", + "CrouchThrowLoop", + "CrouchThrowAS", + "FindCatThrowBS", + "FindCatThrowLoop", + "FindCatThrowAS", + "Player_Electric_ElementalArt", + "Player_Electric_ElementalArt_AS", + "Player_Electric_ElementalBurst", + "Player_Electric_ElementalBurst_AS", + "PutHand01BS", + "PutHand01Loop", + "PutHand01AS", + "Akimbo01BS", + "Backrake01BS", + "Forerake01BS", + "StrikeChest01BS", + "Akimbo01Loop", + "Akimbo01AS", + "Backrake01Loop", + "Backrake01AS", + "Forerake01Loop", + "Forerake01AS", + "StrikeChest01Loop", + "StrikeChest01AS", + "HoldHead01BS", + "HoldHead01Loop", + "HoldHead01AS", + "Clap01", + "Turn01_90LBS", + "Turn01_90RBS", + "Turn01_90LAS", + "Turn01_90RAS", + "Alert01BS", + "Alert01Loop", + "Alert01AS", + "Fishing01_BS", + "Fishing01Loop", + "Fishing01AS", + "Think01_BS", + "Think01_Loop", + "Think01_AS", + "Channel01BS", + "Channel01Loop", + "Channel01AS", + "Fishing_Battle_BS", + "Fishing_Cast_AS", + "Fishing_Cast_BS", + "Fishing_Cast_Loop", + "Fishing_Choose", + "Fishing_Choose_Loop", + "Fishing_End", + "Fishing_Pull_01", + "Fishing_Pull_02", + "Fishing_Wait", + "Fishing_Pull_Fail", + "Bartender_MixingStandby", + "Bartender_MixingStart", + "Bartender_MixingToPour", + "Bartender_Pour", + "Bartender_PourFinish", + "Bartender_PourStandby", + "Bartender_AddLoop", + "Bartender_PrepareStart", + "Bartender_Standby", + "Bartender_AddStandby", + "Bartender_PrepareToStandby", + "Bartender_StandbyFinish", + "Blocking_BS", + "Blocking_Loop", + "Blocking_Back", + "Blocking_Bounce", + "Blocking_Hit", + "Blocking_AS" + }; + static std::string currentAnimation{}; AnimationChanger::AnimationChanger() : Feature(), - NFEX(f_Enabled, "Animation Changer", "AnimationChanger", "Visuals", false, false) + NF(f_Enabled, "Animation Changer", "Visuals::AnimationChanger", false), + NF(f_ApplyAnimation, "Apply Animation", "Visuals::AnimationChanger", false), + NF(f_ResetAnimation, "Reset Animation", "Visuals::AnimationChanger", false) { events::GameUpdateEvent += MY_METHOD_HANDLER(AnimationChanger::OnGameUpdate); } @@ -24,8 +236,30 @@ namespace cheat::feature void AnimationChanger::DrawMain() { - ConfigWidget(f_Enabled, "Changes active character's animation."); - ImGui::InputText("Animation", &f_Animation); + ConfigWidget(f_Enabled, "Changes active character's animation.\nNot all animations work for every character except Main Character."); + if (f_Enabled) + { + if (ImGui::BeginCombo("Animations", currentAnimation.c_str())) + { + for (int n = 0; n < IM_ARRAYSIZE(animations); n++) + { + bool is_selected = (currentAnimation.c_str() == animations[n]); + if (ImGui::Selectable(animations[n].c_str(), is_selected)) + currentAnimation = animations[n]; + + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + if (ImGui::Button("Apply")) + f_ApplyAnimation = true; + ImGui::SameLine(); + if (ImGui::Button("Reset")) + f_ResetAnimation = true; + } + } bool AnimationChanger::NeedStatusDraw() const @@ -46,247 +280,24 @@ namespace cheat::feature void AnimationChanger::OnGameUpdate() { + if (!f_Enabled) + return; + auto& manager = game::EntityManager::instance(); auto avatar = manager.avatar(); if (avatar->animator() == nullptr) return; - static bool changed = false; - - if (f_Enabled) + if (f_Enabled && f_ApplyAnimation) { - auto avatarObj = avatar->gameObject(); - auto rootObj = app::MoleMole_BaseEntity_get_rootGameObject(avatar->raw(), nullptr); // (Clone) - auto path = app::Object_1_get_name(reinterpret_cast(avatarObj), nullptr); - auto pathavatarObj = app::Object_1_get_name(reinterpret_cast(rootObj), nullptr); // (Clone) - - if (!changed) - { - app::Animator_Play(avatar->animator(), string_to_il2cppi(f_Animation.c_str()), 0, 0, nullptr); - changed = true; - } - + app::Animator_Play(avatar->animator(), string_to_il2cppi(currentAnimation.c_str()), 0, 0, nullptr); + f_ApplyAnimation = false; } - else + + if (f_Enabled && f_ResetAnimation) { - if (changed) - { - app::Animator_Rebind(avatar->animator(), nullptr); - changed = false; - } + app::Animator_Rebind(avatar->animator(), nullptr); + f_ResetAnimation = false; } } } - -/* -//------Animations------\\ -SlipFaceWall -SlipBackWall -DropDown -JumpOffWall -Jump -JumpForRun -JumpForWalk -Fly -FlyStart -JumpForSprint -SwimIdle -SwimMove -SwimDash -ClimbMove1 -ClimbIdle -ClimbJump -ClimbMove0 -FallToGroundRun -FallOnGroundLit -FallOnGround -FallToGroundRunHard -FallToGroundSprint -Walk -Run -Standby -RunToIdle -RunToWalk -WalkToIdle -WalkToRun -Sprint -SprintToIdle -SprintToRun -ClimbDownToGround -SprintBS -ShowUp -CrouchToStandby -CrouchIdle -CrouchRoll -CrouchMove -SkiffNormal -Upstairs -JumpUpWallForStandby -JumpUpWallReady -Standby2ClimbA -SwimJump -SwimJumpDrop -SwimJumpToWater -Standby2ClimbB -CrouchDrop -TurnDir -StandbyWeapon -StandbyPutaway -StandbyPutawayOver -Icespine_Out -Icespine -LiquidStrike_MoveStandby -LiquidStrike_AS -LiquidStrike_BS -LiquidStrike_BS1 -LiquidStrike_Move -LiquidStrike_Strike -LiquidStrike_FatalStandby -LiquidStrike_FatalMove -LiquidStrike_AS_OnWater -LiquidStrike_BS_0 -FrozenWindmill -FrozenWindmill_AS -Attack03 -Attack04 -Attack05 -Attack01 -Attack02 -ExtraAttack -ExtraAttack_AS -FallingAnthem_Loop -FallingAnthem_AS_2 -FallingAnthem_BS_1 -FallingAnthem_BS_2 -FallingAnthem_AS_1 -FallingAnthem_Loop_Low -SitBDown -SitBLoop -SitBUp -SitDown -SitLoop -SitUp -StandbyShow_01 -StandbyShow_02 -StandbyVoice -Think01BS -Think01Loop -Think01AS -Akimbo02BS -Akimbo02Loop -Akimbo02AS -ChannelBS -ChannelLoop -ChannelAS -PlayMusic_Lyre_AS -PlayMusic_Lyre_BS -PlayMusic_Lyre_Loop -PlayMusic_Qin_BS -PlayMusic_Qin_AS -PlayMusic_Qin_Loop -ActivitySkill_ElectricCoreFly -Hit_H -Hit_L -Hit_Throw -Hit_Throw_Ground -Hit_ThrowAir -Struggle -NormalDie -SwimDie -HitGroundDie -FallDie_AS -FallDie - -//------Main Character------\\ -UziExplode_AS -UziExplode_BS -UziExplode_Charge_01 -UziExplode_Strike_02 -UziExplode_Charge_02 -UziExplode_Strike_01 -UziExplode_BS_1 -WindBreathe_AS -WindBreathe -Hogyoku_AS -Hogyoku_BS -Hogyoku -Hogyoku_Charge -Hogyoku_Charge_AS -Hogyoku_Charge_2 -RockTide_AS -RockTide -CrouchThrowBS -CrouchThrowLoop -CrouchThrowAS -FindCatThrowBS -FindCatThrowLoop -FindCatThrowAS -Player_Electric_ElementalArt -Player_Electric_ElementalArt_AS -Player_Electric_ElementalBurst -Player_Electric_ElementalBurst_AS -PutHand01BS -PutHand01Loop -PutHand01AS -Akimbo01BS -Backrake01BS -Forerake01BS -StrikeChest01BS -Akimbo01Loop -Akimbo01AS -Backrake01Loop -Backrake01AS -Forerake01Loop -Forerake01AS -StrikeChest01Loop -StrikeChest01AS -HoldHead01BS -HoldHead01Loop -HoldHead01AS -Clap01 -Turn01_90LBS -Turn01_90RBS -Turn01_90LAS -Turn01_90RAS -Alert01BS -Alert01Loop -Alert01AS -Fishing01_BS -Fishing01Loop -Fishing01AS -Think01_BS -Think01_Loop -Think01_AS -Channel01BS -Channel01Loop -Channel01AS -Fishing_Battle_BS -Fishing_Cast_AS -Fishing_Cast_BS -Fishing_Cast_Loop -Fishing_Choose -Fishing_Choose_Loop -Fishing_End -Fishing_Pull_01 -Fishing_Pull_02 -Fishing_Wait -Fishing_Pull_Fail -Bartender_MixingStandby -Bartender_MixingStart -Bartender_MixingToPour -Bartender_Pour -Bartender_PourFinish -Bartender_PourStandby -Bartender_AddLoop -Bartender_PrepareStart -Bartender_Standby -Bartender_AddStandby -Bartender_PrepareToStandby -Bartender_StandbyFinish -Blocking_BS -Blocking_Loop -Blocking_Back -Blocking_Bounce -Blocking_Hit -Blocking_AS -*/ \ No newline at end of file diff --git a/cheat-library/src/user/cheat/visuals/AnimationChanger.h b/cheat-library/src/user/cheat/visuals/AnimationChanger.h index 309bdf9..1cf2f7f 100644 --- a/cheat-library/src/user/cheat/visuals/AnimationChanger.h +++ b/cheat-library/src/user/cheat/visuals/AnimationChanger.h @@ -9,6 +9,8 @@ namespace cheat::feature { public: config::Field> f_Enabled; + config::Field> f_ApplyAnimation; + config::Field> f_ResetAnimation; static AnimationChanger& GetInstance(); diff --git a/cheat-library/src/user/cheat/world/AutoDestroy.cpp b/cheat-library/src/user/cheat/world/AutoDestroy.cpp index 4ee4168..757d7d1 100644 --- a/cheat-library/src/user/cheat/world/AutoDestroy.cpp +++ b/cheat-library/src/user/cheat/world/AutoDestroy.cpp @@ -85,8 +85,8 @@ namespace cheat::feature if (autoDestroy.f_Enabled && autoDestroy.f_Range > manager.avatar()->distance(entity) && ( - (autoDestroy.f_DestroyOres && game::filters::combined::Ores.IsValid(manager.entity(entity))) || - (autoDestroy.f_DestroyDoodads && game::filters::combined::Doodads.IsValid(manager.entity(entity))) || + (autoDestroy.f_DestroyOres && game::filters::combined::Ores.IsValid(manager.entity(entity))) || + (autoDestroy.f_DestroyDoodads && (game::filters::combined::Doodads.IsValid(manager.entity(entity)) || game::filters::chest::SBramble.IsValid(manager.entity(entity)))) || (autoDestroy.f_DestroyShields && !game::filters::combined::MonsterBosses.IsValid(manager.entity(entity)) && ( game::filters::combined::MonsterShielded.IsValid(manager.entity(entity)) || // For shields attached to monsters, e.g. abyss mage shields. game::filters::combined::MonsterEquips.IsValid(manager.entity(entity)) || // For shields/weapons equipped by monsters, e.g. rock shield. From be2546903a6b15bbb9c6ad928154d8a54c6e945a Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Mon, 1 Aug 2022 00:29:35 -0600 Subject: [PATCH 08/30] Fixed enemies not freezing(elemental reaction) --- cheat-library/src/user/cheat/world/FreezeEnemies.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cheat-library/src/user/cheat/world/FreezeEnemies.cpp b/cheat-library/src/user/cheat/world/FreezeEnemies.cpp index a9d8bed..5b6ca72 100644 --- a/cheat-library/src/user/cheat/world/FreezeEnemies.cpp +++ b/cheat-library/src/user/cheat/world/FreezeEnemies.cpp @@ -9,6 +9,7 @@ namespace cheat::feature { + static bool change = false; FreezeEnemies::FreezeEnemies() : Feature(), NF(f_Enabled, "Freeze Enemies", "FreezeEnemies", false) @@ -61,11 +62,16 @@ namespace cheat::feature //LOG_DEBUG("%s", magic_enum::enum_name(constraints).data()); app::Rigidbody_set_constraints(rigidBody, app::RigidbodyConstraints__Enum::FreezeAll, nullptr); app::Animator_set_speed(animator, 0.f, nullptr); + change = false; } else { app::Rigidbody_set_constraints(rigidBody, app::RigidbodyConstraints__Enum::FreezeRotation, nullptr); - app::Animator_set_speed(animator, 1.f, nullptr); + if (!change) + { + app::Animator_set_speed(animator, 1.f, nullptr); + change = true; + } } } } From 42f260ab9539286d5589838ce4ae390d86621cc1 Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Mon, 1 Aug 2022 05:14:29 -0600 Subject: [PATCH 09/30] Changed from Button to Hotkey(Animation Changer) --- .../user/cheat/visuals/AnimationChanger.cpp | 60 ++++++++++--------- .../src/user/cheat/visuals/AnimationChanger.h | 13 ++-- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp b/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp index 83daebd..2b61f77 100644 --- a/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp +++ b/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp @@ -219,11 +219,13 @@ namespace cheat::feature "Blocking_Hit", "Blocking_AS" }; - static std::string currentAnimation{}; + AnimationChanger::AnimationChanger() : Feature(), NF(f_Enabled, "Animation Changer", "Visuals::AnimationChanger", false), - NF(f_ApplyAnimation, "Apply Animation", "Visuals::AnimationChanger", false), - NF(f_ResetAnimation, "Reset Animation", "Visuals::AnimationChanger", false) + NF(f_Animation, "Animation", "Visuals::AnimationChanger", "ExtraAttack"), + NF(f_ApplyKey, "Apply Animation", "Visuals::AnimationChanger", Hotkey('Y')), + NF(f_ResetKey, "Reset Animation", "Visuals::AnimationChanger", Hotkey('R')), + toBeUpdate(), nextUpdate(0) { events::GameUpdateEvent += MY_METHOD_HANDLER(AnimationChanger::OnGameUpdate); } @@ -236,30 +238,30 @@ namespace cheat::feature void AnimationChanger::DrawMain() { - ConfigWidget(f_Enabled, "Changes active character's animation.\nNot all animations work for every character except Main Character."); - if (f_Enabled) + ImGui::BeginGroupPanel("Animation Changer"); { - if (ImGui::BeginCombo("Animations", currentAnimation.c_str())) + ConfigWidget(f_Enabled, "Changes active character's animation.\nNot all animations work for every character except Main Character."); + if (f_Enabled) { - for (int n = 0; n < IM_ARRAYSIZE(animations); n++) + if (ImGui::BeginCombo("Animations", f_Animation.value().c_str())) { - bool is_selected = (currentAnimation.c_str() == animations[n]); - if (ImGui::Selectable(animations[n].c_str(), is_selected)) - currentAnimation = animations[n]; + for (int n = 0; n < IM_ARRAYSIZE(animations); n++) + { + bool is_selected = (f_Animation.value().c_str() == animations[n]); + if (ImGui::Selectable(animations[n].c_str(), is_selected)) + f_Animation.value() = animations[n]; - if (is_selected) - ImGui::SetItemDefaultFocus(); + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); } - ImGui::EndCombo(); + + ConfigWidget("Apply Key", f_ApplyKey, true); + ConfigWidget("Reset Key", f_ResetKey, true); } - - if (ImGui::Button("Apply")) - f_ApplyAnimation = true; - ImGui::SameLine(); - if (ImGui::Button("Reset")) - f_ResetAnimation = true; } - + ImGui::EndGroupPanel(); } bool AnimationChanger::NeedStatusDraw() const @@ -283,21 +285,21 @@ namespace cheat::feature if (!f_Enabled) return; + auto currentTime = util::GetCurrentTimeMillisec(); + if (currentTime < nextUpdate) + return; + auto& manager = game::EntityManager::instance(); auto avatar = manager.avatar(); if (avatar->animator() == nullptr) return; - if (f_Enabled && f_ApplyAnimation) - { - app::Animator_Play(avatar->animator(), string_to_il2cppi(currentAnimation.c_str()), 0, 0, nullptr); - f_ApplyAnimation = false; - } + if (f_ApplyKey.value().IsPressed()) + app::Animator_Play(avatar->animator(), string_to_il2cppi(f_Animation.value().c_str()), 0, 0, nullptr); - if (f_Enabled && f_ResetAnimation) - { + if (f_ResetKey.value().IsPressed()) app::Animator_Rebind(avatar->animator(), nullptr); - f_ResetAnimation = false; - } + + nextUpdate = currentTime + (int)f_DelayUpdate; } } diff --git a/cheat-library/src/user/cheat/visuals/AnimationChanger.h b/cheat-library/src/user/cheat/visuals/AnimationChanger.h index 1cf2f7f..c0e9d29 100644 --- a/cheat-library/src/user/cheat/visuals/AnimationChanger.h +++ b/cheat-library/src/user/cheat/visuals/AnimationChanger.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include namespace cheat::feature { @@ -9,19 +10,21 @@ namespace cheat::feature { public: config::Field> f_Enabled; - config::Field> f_ApplyAnimation; - config::Field> f_ResetAnimation; - - static AnimationChanger& GetInstance(); + config::Field f_Animation; + config::Field f_ApplyKey; + config::Field f_ResetKey; const FeatureGUIInfo& GetGUIInfo() const override; void DrawMain() override; - virtual bool NeedStatusDraw() const override; void DrawStatus() override; + static AnimationChanger& GetInstance(); void OnGameUpdate(); private: + SafeQueue toBeUpdate; + SafeValue nextUpdate; + int f_DelayUpdate = 500; AnimationChanger(); }; } From b621f8bc3af77063cf90bf069cf8985db83391b1 Mon Sep 17 00:00:00 2001 From: Nanako <00sh.chiha+github@gmail.com> Date: Wed, 3 Aug 2022 17:35:34 +0900 Subject: [PATCH 10/30] Update AnimationChanger.cpp --- .../src/user/cheat/visuals/AnimationChanger.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp b/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp index 2b61f77..2b77708 100644 --- a/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp +++ b/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp @@ -245,12 +245,11 @@ namespace cheat::feature { if (ImGui::BeginCombo("Animations", f_Animation.value().c_str())) { - for (int n = 0; n < IM_ARRAYSIZE(animations); n++) + for (auto &animation : animations) { - bool is_selected = (f_Animation.value().c_str() == animations[n]); - if (ImGui::Selectable(animations[n].c_str(), is_selected)) - f_Animation.value() = animations[n]; - + bool is_selected = (f_Animation.value().c_str() == animation); + if (ImGui::Selectable(animation.c_str(), is_selected)) + f_Animation.value() = animation; if (is_selected) ImGui::SetItemDefaultFocus(); } From cdc4f4b9e2d6e95be3387a71294501be2420d8f8 Mon Sep 17 00:00:00 2001 From: Nanako <00sh.chiha+github@gmail.com> Date: Wed, 3 Aug 2022 18:46:41 +0900 Subject: [PATCH 11/30] interpolata --- .../user/cheat/teleport/CustomTeleports.cpp | 26 ++++++++++++++++++- .../src/user/cheat/teleport/CustomTeleports.h | 1 - 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp index 8e6738f..5c10866 100644 --- a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp +++ b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp @@ -17,7 +17,6 @@ namespace cheat::feature { CustomTeleports::CustomTeleports() : Feature(), - NF(f_DebugMode, "Debug Mode", "CustomTeleports", false), // Soon to be added NF(f_Enabled, "Custom Teleport", "CustomTeleports", false), NF(f_Next, "Teleport Next", "CustomTeleports", Hotkey(VK_OEM_6)), NF(f_Previous, "Teleport Previous", "CustomTeleports", Hotkey(VK_OEM_4)), @@ -194,6 +193,8 @@ namespace cheat::feature selectedIndexName = name; } + app::Vector3 Lerp(const app::Vector3 &a, const app::Vector3 &b, float t) { return a + (b - a) * t; } + void CustomTeleports::DrawMain() { // Buffers @@ -368,6 +369,29 @@ namespace cheat::feature } ImGui::SameLine(); + if (ImGui::Button("Interpolate to")) + { + auto &manager = game::EntityManager::instance(); + auto avatarPos = manager.avatar()->absolutePosition(); + LOG_DEBUG("Defined avatar pos: %s", il2cppi_to_string(avatarPos).c_str()); + auto endPos = position; + LOG_DEBUG("Defined end pos: %s", il2cppi_to_string(endPos).c_str()); + std::thread interpolate([avatarPos, endPos, &manager](){ + float t = 0.0f; + app::Vector3 zero = {0,0,0}; + auto newPos = zero, speed = zero; + while (t <= 1.0f) { + newPos = Lerp(avatarPos, endPos, t); + manager.avatar()->setAbsolutePosition(newPos); + t += 0.01f; + LOG_DEBUG("newpos: %s, completion rate: %.02f%%", il2cppi_to_string(newPos).c_str(), t * 100.0f); + Sleep(10); + if (t >= 1.0f) break; // this *might* be redundant, but i'm paranoid + } }); + interpolate.detach(); + } + ImGui::SameLine(); + if (ImGui::Button(("Select##Button" + std::to_string(index)).c_str())) { selectedIndex = index; diff --git a/cheat-library/src/user/cheat/teleport/CustomTeleports.h b/cheat-library/src/user/cheat/teleport/CustomTeleports.h index e1fd414..3800dc2 100644 --- a/cheat-library/src/user/cheat/teleport/CustomTeleports.h +++ b/cheat-library/src/user/cheat/teleport/CustomTeleports.h @@ -25,7 +25,6 @@ namespace cheat::feature class CustomTeleports : public Feature { public: - config::Field> f_DebugMode; config::Field> f_Enabled; config::Field f_Next; config::Field f_Previous; From bb8a1f79667cfec13afdfe5d073b4b1225a836a8 Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Wed, 3 Aug 2022 05:01:52 -0600 Subject: [PATCH 12/30] Lerp function --- cheat-library/src/user/cheat/teleport/CustomTeleports.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp index 5c10866..633be4c 100644 --- a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp +++ b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp @@ -193,8 +193,6 @@ namespace cheat::feature selectedIndexName = name; } - app::Vector3 Lerp(const app::Vector3 &a, const app::Vector3 &b, float t) { return a + (b - a) * t; } - void CustomTeleports::DrawMain() { // Buffers @@ -381,7 +379,7 @@ namespace cheat::feature app::Vector3 zero = {0,0,0}; auto newPos = zero, speed = zero; while (t <= 1.0f) { - newPos = Lerp(avatarPos, endPos, t); + newPos = app::Vector3_Lerp(avatarPos, endPos, t, nullptr); manager.avatar()->setAbsolutePosition(newPos); t += 0.01f; LOG_DEBUG("newpos: %s, completion rate: %.02f%%", il2cppi_to_string(newPos).c_str(), t * 100.0f); From 7db1b4eff28c25c79a410cc85069d042dfda0b56 Mon Sep 17 00:00:00 2001 From: Nanako <00sh.chiha+github@gmail.com> Date: Wed, 3 Aug 2022 20:56:45 +0900 Subject: [PATCH 13/30] Make speed option - and some fixes --- .../user/cheat/teleport/CustomTeleports.cpp | 30 +++++++++---------- .../src/user/cheat/teleport/CustomTeleports.h | 1 + 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp index 633be4c..6f9a71a 100644 --- a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp +++ b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp @@ -20,6 +20,7 @@ namespace cheat::feature NF(f_Enabled, "Custom Teleport", "CustomTeleports", false), NF(f_Next, "Teleport Next", "CustomTeleports", Hotkey(VK_OEM_6)), NF(f_Previous, "Teleport Previous", "CustomTeleports", Hotkey(VK_OEM_4)), + NF(f_Speed, "Interpolation Speed", "CustomTeleports", 10.0f), dir(util::GetCurrentPath() / "teleports") { f_Next.value().PressedEvent += MY_METHOD_HANDLER(CustomTeleports::OnNext); @@ -172,9 +173,7 @@ namespace cheat::feature while (wordItr != std::sregex_iterator()) { for (unsigned i = 0; i < wordItr->size(); i++) - { shortened.append((*wordItr)[i]); - } wordItr++; } @@ -248,6 +247,9 @@ namespace cheat::feature "3. You can now press Next or Previous Hotkey to Teleport through the Checklist\n" "Initially it will teleport the player to the selection made\n" "Note: Double click or click the arrow to open teleport details"); + ConfigWidget("Interpolation Speed", f_Speed, 0.1f, 0.1f, 99.0f, + "Interpolation speed.\n" \ + "recommended setting below or equal to 0.1."); ImGui::SameLine(); if (ImGui::Button("Delete Checked")) @@ -315,7 +317,7 @@ namespace cheat::feature maxNameLength = Teleport.name.length(); ImGui::BeginTable("Teleports", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_NoSavedSettings); ImGui::TableSetupColumn("#", ImGuiTableColumnFlags_WidthFixed, 20); - ImGui::TableSetupColumn("Commands", ImGuiTableColumnFlags_WidthFixed, 100); + ImGui::TableSetupColumn("Commands", ImGuiTableColumnFlags_WidthFixed, 130); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, maxNameLength * 8 + 10); ImGui::TableSetupColumn("Position"); ImGui::TableHeadersRow(); @@ -331,12 +333,13 @@ namespace cheat::feature bool checked = std::any_of(checkedIndices.begin(), checkedIndices.end(), [&index](const auto &i) { return i == index; }); bool selected = index == selectedIndex; + std::string stringIndex = std::to_string(index); ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text("%d", index); ImGui::TableNextColumn(); - ImGui::Checkbox(("##Index" + std::to_string(index)).c_str(), &checked); + ImGui::Checkbox(("##Index" + stringIndex).c_str(), &checked); if (ImGui::IsItemClicked(0)) { if (checked) @@ -351,7 +354,7 @@ namespace cheat::feature } ImGui::SameLine(); - if (ImGui::Button(("TP##Button" + std::to_string(index)).c_str())) + if (ImGui::Button(("TP##Button" + stringIndex).c_str())) { auto &manager = game::EntityManager::instance(); auto avatar = manager.avatar(); @@ -367,30 +370,27 @@ namespace cheat::feature } ImGui::SameLine(); - if (ImGui::Button("Interpolate to")) + if (ImGui::Button(("Lerp##Button" + stringIndex).c_str())) { + float speed = this->f_Speed; auto &manager = game::EntityManager::instance(); auto avatarPos = manager.avatar()->absolutePosition(); - LOG_DEBUG("Defined avatar pos: %s", il2cppi_to_string(avatarPos).c_str()); auto endPos = position; - LOG_DEBUG("Defined end pos: %s", il2cppi_to_string(endPos).c_str()); - std::thread interpolate([avatarPos, endPos, &manager](){ + std::thread interpolate([avatarPos, endPos, &manager, speed](){ float t = 0.0f; app::Vector3 zero = {0,0,0}; - auto newPos = zero, speed = zero; - while (t <= 1.0f) { + auto newPos = zero; + while (t < 1.0f) { newPos = app::Vector3_Lerp(avatarPos, endPos, t, nullptr); manager.avatar()->setAbsolutePosition(newPos); - t += 0.01f; - LOG_DEBUG("newpos: %s, completion rate: %.02f%%", il2cppi_to_string(newPos).c_str(), t * 100.0f); + t += speed / 100.0f; Sleep(10); - if (t >= 1.0f) break; // this *might* be redundant, but i'm paranoid } }); interpolate.detach(); } ImGui::SameLine(); - if (ImGui::Button(("Select##Button" + std::to_string(index)).c_str())) + if (ImGui::Button(("Select##Button" + stringIndex).c_str())) { selectedIndex = index; selectedByClick = true; diff --git a/cheat-library/src/user/cheat/teleport/CustomTeleports.h b/cheat-library/src/user/cheat/teleport/CustomTeleports.h index 3800dc2..3150659 100644 --- a/cheat-library/src/user/cheat/teleport/CustomTeleports.h +++ b/cheat-library/src/user/cheat/teleport/CustomTeleports.h @@ -26,6 +26,7 @@ namespace cheat::feature { public: config::Field> f_Enabled; + config::Field f_Speed; config::Field f_Next; config::Field f_Previous; static CustomTeleports& GetInstance(); From cac25b8a96596ed5fe4f06e3af6f0d80846bd149 Mon Sep 17 00:00:00 2001 From: Nanako <00sh.chiha+github@gmail.com> Date: Thu, 4 Aug 2022 16:24:28 +0900 Subject: [PATCH 14/30] Little Refactor --- .../user/cheat/teleport/CustomTeleports.cpp | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp index 6f9a71a..91776a9 100644 --- a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp +++ b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp @@ -157,36 +157,28 @@ namespace cheat::feature OnTeleportKeyPressed(true); } + void itr(std::regex exp, std::string name, std::string s) + { + std::sregex_iterator itr(name.begin(), name.end(), exp); + while (itr != std::sregex_iterator()) + { + for (unsigned i = 0; i < itr->size(); i++) + s.append((*itr)[i]); + itr++; + } + } void CustomTeleports::UpdateIndexName() { - std::string name(selectedIndex == -1 || checkedIndices.empty() ? "" : Teleports.at(selectedIndex).name); - // abbreviate teleport names that are too long + std::string name(selectedIndex == -1 || checkedIndices.empty() ? "" : Teleports.at(selectedIndex).name); if (name.length() > 15) { std::string shortened; std::regex numsExp("[\\d]+"); std::regex firstCharsExp("\\b[A-Za-z]"); - - std::sregex_iterator wordItr(name.begin(), name.end(), firstCharsExp); - while (wordItr != std::sregex_iterator()) - { - for (unsigned i = 0; i < wordItr->size(); i++) - shortened.append((*wordItr)[i]); - wordItr++; - } - - std::sregex_iterator numItr(name.begin(), name.end(), numsExp); - while (numItr != std::sregex_iterator()) - { - for (unsigned i = 0; i < numItr->size(); i++) - { - shortened.append(" "); - shortened.append((*numItr)[i]); - } - numItr++; - } + itr(firstCharsExp, name, shortened); + itr(numsExp, name, shortened); name = shortened; } selectedIndexName = name; @@ -250,7 +242,6 @@ namespace cheat::feature ConfigWidget("Interpolation Speed", f_Speed, 0.1f, 0.1f, 99.0f, "Interpolation speed.\n" \ "recommended setting below or equal to 0.1."); - ImGui::SameLine(); if (ImGui::Button("Delete Checked")) { From 4a49e139f7c8850329a7c6216e39754f774784c2 Mon Sep 17 00:00:00 2001 From: Nanako <00sh.chiha+github@gmail.com> Date: Thu, 4 Aug 2022 17:32:13 +0900 Subject: [PATCH 15/30] Refactor and Interpolate Hotkey --- .../user/cheat/teleport/CustomTeleports.cpp | 71 +++++++++++-------- .../src/user/cheat/teleport/CustomTeleports.h | 2 + 2 files changed, 44 insertions(+), 29 deletions(-) diff --git a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp index 91776a9..7444093 100644 --- a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp +++ b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp @@ -20,6 +20,7 @@ namespace cheat::feature NF(f_Enabled, "Custom Teleport", "CustomTeleports", false), NF(f_Next, "Teleport Next", "CustomTeleports", Hotkey(VK_OEM_6)), NF(f_Previous, "Teleport Previous", "CustomTeleports", Hotkey(VK_OEM_4)), + NF(f_Interpolate, "Custom Teleport", "CustomTeleports", false), NF(f_Speed, "Interpolation Speed", "CustomTeleports", 10.0f), dir(util::GetCurrentPath() / "teleports") { @@ -122,6 +123,42 @@ namespace cheat::feature return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2) + pow(a.z - b.z, 2)); } + void CustomTeleports::TeleportTo(app::Vector3 position, bool interpolate) + { + auto &manager = game::EntityManager::instance(); + auto avatar = manager.avatar(); + if (avatar->moveComponent() == nullptr) + { + LOG_ERROR("Avatar has no move component, Is scene loaded?"); + return; + } + if (interpolate) + { + float speed = this->f_Speed; + auto avatarPos = manager.avatar()->absolutePosition(); + auto endPos = position; + std::thread interpolate([avatarPos, endPos, &manager, speed]() + { + float t = 0.0f; + app::Vector3 zero = {0,0,0}; + auto newPos = zero; + while (t < 1.0f) { + newPos = app::Vector3_Lerp(avatarPos, endPos, t, nullptr); + manager.avatar()->setAbsolutePosition(newPos); + t += speed / 100.0f; + Sleep(10); + } }); + interpolate.detach(); + } + else + { + if (PositionDistance(position, app::ActorUtils_GetAvatarPos(nullptr)) > 60.0f) + MapTeleport::GetInstance().TeleportTo(position); + else + manager.avatar()->setAbsolutePosition(position); + } + } + void CustomTeleports::OnTeleportKeyPressed(bool next) { if (!f_Enabled || selectedIndex < 0) @@ -144,7 +181,7 @@ namespace cheat::feature position = Teleports.at(list.at(index + (next ? 1 : -1))).position; selectedIndex = list.at(index + (next ? 1 : -1)); } - mapTeleport.TeleportTo(position); + TeleportTo(position, this->f_Interpolate); UpdateIndexName(); } @@ -239,9 +276,9 @@ namespace cheat::feature "3. You can now press Next or Previous Hotkey to Teleport through the Checklist\n" "Initially it will teleport the player to the selection made\n" "Note: Double click or click the arrow to open teleport details"); + ConfigWidget("Enable Interpolation", f_Interpolate, "Enable interpolation between teleports when using keybinds"); ConfigWidget("Interpolation Speed", f_Speed, 0.1f, 0.1f, 99.0f, - "Interpolation speed.\n" \ - "recommended setting below or equal to 0.1."); + "Interpolation speed.\n recommended setting below or equal to 0.1."); if (ImGui::Button("Delete Checked")) { @@ -347,37 +384,13 @@ namespace cheat::feature ImGui::SameLine(); if (ImGui::Button(("TP##Button" + stringIndex).c_str())) { - auto &manager = game::EntityManager::instance(); - auto avatar = manager.avatar(); - if (avatar->moveComponent() == nullptr) - { - LOG_ERROR("Avatar has no move component, Is scene loaded?"); - return; - } - if (PositionDistance(position, app::ActorUtils_GetAvatarPos(nullptr)) > 60.0f) - MapTeleport::GetInstance().TeleportTo(position); - else - manager.avatar()->setAbsolutePosition(position); + TeleportTo(position, false); } ImGui::SameLine(); if (ImGui::Button(("Lerp##Button" + stringIndex).c_str())) { - float speed = this->f_Speed; - auto &manager = game::EntityManager::instance(); - auto avatarPos = manager.avatar()->absolutePosition(); - auto endPos = position; - std::thread interpolate([avatarPos, endPos, &manager, speed](){ - float t = 0.0f; - app::Vector3 zero = {0,0,0}; - auto newPos = zero; - while (t < 1.0f) { - newPos = app::Vector3_Lerp(avatarPos, endPos, t, nullptr); - manager.avatar()->setAbsolutePosition(newPos); - t += speed / 100.0f; - Sleep(10); - } }); - interpolate.detach(); + TeleportTo(position, true); } ImGui::SameLine(); diff --git a/cheat-library/src/user/cheat/teleport/CustomTeleports.h b/cheat-library/src/user/cheat/teleport/CustomTeleports.h index 3150659..6b2de3c 100644 --- a/cheat-library/src/user/cheat/teleport/CustomTeleports.h +++ b/cheat-library/src/user/cheat/teleport/CustomTeleports.h @@ -26,6 +26,7 @@ namespace cheat::feature { public: config::Field> f_Enabled; + config::Field> f_Interpolate; config::Field f_Speed; config::Field f_Next; config::Field f_Previous; @@ -55,6 +56,7 @@ namespace cheat::feature std::string selectedName; std::string selectedIndexName; CustomTeleports(); + void TeleportTo(app::Vector3 position, bool interpolate); void OnTeleportKeyPressed(bool next); void OnPrevious(); void OnNext(); From c2df15a5dc53eac52e666d48bcc1e2ec719e6211 Mon Sep 17 00:00:00 2001 From: Nanako <00sh.chiha+github@gmail.com> Date: Thu, 4 Aug 2022 21:09:00 +0900 Subject: [PATCH 16/30] add theme functionality not full implementation --- .../src/cheat-base/cheat/misc/Settings.cpp | 59 +++++++++++++++++-- .../src/cheat-base/cheat/misc/Settings.h | 4 ++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/cheat-base/src/cheat-base/cheat/misc/Settings.cpp b/cheat-base/src/cheat-base/cheat/misc/Settings.cpp index 371650d..0e9d407 100644 --- a/cheat-base/src/cheat-base/cheat/misc/Settings.cpp +++ b/cheat-base/src/cheat-base/cheat/misc/Settings.cpp @@ -1,9 +1,14 @@ #include #include "Settings.h" -#include -#include #include +#include +#include +#include +#include + +#include "shlwapi.h" +#pragma comment(lib, "shlwapi.lib") namespace cheat::feature { @@ -29,11 +34,14 @@ namespace cheat::feature NF(f_ConsoleLogging, "Console Logging", "General::Logging", true), NF(f_FastExitEnable, "Fast Exit", "General::FastExit", false), - NF(f_HotkeyExit, "Hotkeys", "General::FastExit", Hotkey(VK_F12)) - + NF(f_HotkeyExit, "Hotkeys", "General::FastExit", Hotkey(VK_F12)), + themesDir(util::GetCurrentPath() / "themes") + { renderer::SetGlobalFontSize(static_cast(f_FontSize)); f_HotkeyExit.value().PressedEvent += MY_METHOD_HANDLER(Settings::OnExitKeyPressed); + if (!std::filesystem::exists(themesDir)) + std::filesystem::create_directory(themesDir); } const FeatureGUIInfo& Settings::GetGUIInfo() const @@ -42,6 +50,35 @@ namespace cheat::feature return info; } + void Settings::Colors_Export(std::string name) + { + ImGuiStyle &style = ImGui::GetStyle(); + auto colors = style.Colors; + + nlohmann::json json; + for (int i = 0; i < ImGuiCol_COUNT; i++) + json[ImGui::GetStyleColorName((ImGuiCol)i)] = {colors[i].x, colors[i].y, colors[i].z, colors[i].w}; + std::ofstream file(themesDir / (name + ".json")); + file << std::setw(4) << json << std::endl; + } + + void Settings::Colors_Import(std::string name) + { + ImGuiStyle &style = ImGui::GetStyle(); + auto colors = style.Colors; + nlohmann::json json; + std::ifstream file(themesDir / (name + ".json")); + file >> json; + for (int i = 0; i < ImGuiCol_COUNT; i++) + { + auto color = json[ImGui::GetStyleColorName((ImGuiCol)i)]; + colors[i].x = color[0]; + colors[i].y = color[1]; + colors[i].z = color[2]; + colors[i].w = color[3]; + } + } + void Settings::DrawMain() { @@ -123,6 +160,20 @@ namespace cheat::feature ImGui::EndDisabled(); } ImGui::EndGroupPanel(); + + ImGui::BeginGroupPanel("Colors"); + { + static std::string nameBuffer_; + ImGui::InputText("Name", &nameBuffer_); + if (ImGui::Button("Export")) + Colors_Export(nameBuffer_); + if (ImGui::Button("Import")) + Colors_Import(nameBuffer_); + if (ImGui::Button("Open themes folder")) + ShellExecute(nullptr, "open", themesDir.c_str(), nullptr, nullptr, SW_SHOW); + + } + ImGui::EndGroupPanel(); } Settings& Settings::GetInstance() diff --git a/cheat-base/src/cheat-base/cheat/misc/Settings.h b/cheat-base/src/cheat-base/cheat/misc/Settings.h index 710866b..51eadca 100644 --- a/cheat-base/src/cheat-base/cheat/misc/Settings.h +++ b/cheat-base/src/cheat-base/cheat/misc/Settings.h @@ -31,10 +31,14 @@ namespace cheat::feature config::Field f_FastExitEnable; config::Field f_HotkeyExit; + std::filesystem::path themesDir; + static Settings& GetInstance(); const FeatureGUIInfo& GetGUIInfo() const override; void DrawMain() override; + void Colors_Export(std::string name); + void Colors_Import(std::string name); private: From 87877bc18fd43b928ecb04a54d8ef12b8cc85400 Mon Sep 17 00:00:00 2001 From: HarrySilan Date: Thu, 4 Aug 2022 20:36:43 +0800 Subject: [PATCH 17/30] fix #413 --- .../user/cheat/teleport/CustomTeleports.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp index 8e6738f..39b000c 100644 --- a/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp +++ b/cheat-library/src/user/cheat/teleport/CustomTeleports.cpp @@ -138,11 +138,12 @@ namespace cheat::feature else { std::vector list(checkedIndices.begin(), checkedIndices.end()); - if (selectedIndex == list.back() ? next : selectedIndex == list.front()) + if (next ? selectedIndex == list.back() : selectedIndex == list.front()) return; + auto index = std::distance(list.begin(), std::find(list.begin(), list.end(), selectedIndex)); - position = Teleports.at(list.at(index + (next ? 1 : -1))).position; selectedIndex = list.at(index + (next ? 1 : -1)); + position = Teleports.at(selectedIndex).position; } mapTeleport.TeleportTo(position); UpdateIndexName(); @@ -281,8 +282,8 @@ namespace cheat::feature { std::sort(Teleports.begin(), Teleports.end(), [](const auto &a, const auto &b) { return StrCmpLogicalW(std::wstring(a.name.begin(), a.name.end()).c_str(), std::wstring(b.name.begin(), b.name.end()).c_str()) < 0; }); - bool allChecked = checkedIndices.size() == Teleports.size() && !Teleports.empty(); - bool allSearchChecked = checkedIndices.size() == searchIndices.size() && !searchIndices.empty(); + bool allSearchChecked = std::includes(checkedIndices.begin(), checkedIndices.end(), searchIndices.begin(), searchIndices.end()) && !searchIndices.empty(); + bool allChecked = (checkedIndices.size() == Teleports.size() && !Teleports.empty()) || allSearchChecked; ImGui::Checkbox("All", &allChecked); if (ImGui::IsItemClicked()) { @@ -320,7 +321,6 @@ namespace cheat::feature ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, maxNameLength * 8 + 10); ImGui::TableSetupColumn("Position"); ImGui::TableHeadersRow(); - ImGuiTreeNodeFlags nodeFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth; for (const auto &[name, position, description] : Teleports) { @@ -374,15 +374,11 @@ namespace cheat::feature selectedByClick = true; UpdateIndexName(); } - ImGui::SameLine(); - ImGui::PushStyleColor(ImGuiCol_Text, selected ? IM_COL32(40, 90, 175, 255) : IM_COL32(255, 255, 255, 255)); - - if (selected) - nodeFlags |= ImGuiTreeNodeFlags_Selected; - ImGui::PopStyleColor(); ImGui::TableNextColumn(); + ImGui::PushStyleColor(ImGuiCol_Text, selected ? IM_COL32(40, 90, 175, 255) : ImGui::ColorConvertFloat4ToU32(ImGui::GetStyle().Colors[ImGuiCol_Text])); ImGui::Text("%s", name.c_str()); + ImGui::PopStyleColor(); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); From 504679196c154eee1912d7a8e7a2e623822c967c Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Thu, 4 Aug 2022 22:01:17 -0600 Subject: [PATCH 18/30] Changes from review --- .../src/user/cheat/visuals/AnimationChanger.cpp | 11 ++++------- .../src/user/cheat/visuals/AnimationChanger.h | 4 ---- cheat-library/src/user/cheat/world/FreezeEnemies.cpp | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp b/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp index 2b77708..37f36e0 100644 --- a/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp +++ b/cheat-library/src/user/cheat/visuals/AnimationChanger.cpp @@ -224,8 +224,7 @@ namespace cheat::feature NF(f_Enabled, "Animation Changer", "Visuals::AnimationChanger", false), NF(f_Animation, "Animation", "Visuals::AnimationChanger", "ExtraAttack"), NF(f_ApplyKey, "Apply Animation", "Visuals::AnimationChanger", Hotkey('Y')), - NF(f_ResetKey, "Reset Animation", "Visuals::AnimationChanger", Hotkey('R')), - toBeUpdate(), nextUpdate(0) + NF(f_ResetKey, "Reset Animation", "Visuals::AnimationChanger", Hotkey('R')) { events::GameUpdateEvent += MY_METHOD_HANDLER(AnimationChanger::OnGameUpdate); } @@ -250,6 +249,7 @@ namespace cheat::feature bool is_selected = (f_Animation.value().c_str() == animation); if (ImGui::Selectable(animation.c_str(), is_selected)) f_Animation.value() = animation; + if (is_selected) ImGui::SetItemDefaultFocus(); } @@ -284,9 +284,8 @@ namespace cheat::feature if (!f_Enabled) return; - auto currentTime = util::GetCurrentTimeMillisec(); - if (currentTime < nextUpdate) - return; + // Taiga#5555: Maybe need to add separate option to change delay value if user feels like it's too fast or slow. + UPDATE_DELAY(400); auto& manager = game::EntityManager::instance(); auto avatar = manager.avatar(); @@ -298,7 +297,5 @@ namespace cheat::feature if (f_ResetKey.value().IsPressed()) app::Animator_Rebind(avatar->animator(), nullptr); - - nextUpdate = currentTime + (int)f_DelayUpdate; } } diff --git a/cheat-library/src/user/cheat/visuals/AnimationChanger.h b/cheat-library/src/user/cheat/visuals/AnimationChanger.h index c0e9d29..b8f9d0c 100644 --- a/cheat-library/src/user/cheat/visuals/AnimationChanger.h +++ b/cheat-library/src/user/cheat/visuals/AnimationChanger.h @@ -1,7 +1,6 @@ #pragma once #include #include -#include namespace cheat::feature { @@ -22,9 +21,6 @@ namespace cheat::feature void OnGameUpdate(); private: - SafeQueue toBeUpdate; - SafeValue nextUpdate; - int f_DelayUpdate = 500; AnimationChanger(); }; } diff --git a/cheat-library/src/user/cheat/world/FreezeEnemies.cpp b/cheat-library/src/user/cheat/world/FreezeEnemies.cpp index 5b6ca72..183b4d1 100644 --- a/cheat-library/src/user/cheat/world/FreezeEnemies.cpp +++ b/cheat-library/src/user/cheat/world/FreezeEnemies.cpp @@ -9,7 +9,6 @@ namespace cheat::feature { - static bool change = false; FreezeEnemies::FreezeEnemies() : Feature(), NF(f_Enabled, "Freeze Enemies", "FreezeEnemies", false) @@ -48,6 +47,7 @@ namespace cheat::feature void FreezeEnemies::OnGameUpdate() { auto& manager = game::EntityManager::instance(); + static bool change = false; for (const auto& monster : manager.entities(game::filters::combined::Monsters)) { From 3b2d95ea63d3b526b6a48f56e80dd5dd210ddbab Mon Sep 17 00:00:00 2001 From: Nanako <00sh.chiha+github@gmail.com> Date: Thu, 4 Aug 2022 21:51:39 +0900 Subject: [PATCH 19/30] Update Settings.cpp --- .../src/cheat-base/cheat/misc/Settings.cpp | 27 ++++++++++++++----- .../src/cheat-base/cheat/misc/Settings.h | 1 + 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/cheat-base/src/cheat-base/cheat/misc/Settings.cpp b/cheat-base/src/cheat-base/cheat/misc/Settings.cpp index 0e9d407..036bdfe 100644 --- a/cheat-base/src/cheat-base/cheat/misc/Settings.cpp +++ b/cheat-base/src/cheat-base/cheat/misc/Settings.cpp @@ -35,6 +35,7 @@ namespace cheat::feature NF(f_FastExitEnable, "Fast Exit", "General::FastExit", false), NF(f_HotkeyExit, "Hotkeys", "General::FastExit", Hotkey(VK_F12)), + NFS(f_DefaultTheme, "Theme", "General::Colors", "Default"), themesDir(util::GetCurrentPath() / "themes") { @@ -43,6 +44,7 @@ namespace cheat::feature if (!std::filesystem::exists(themesDir)) std::filesystem::create_directory(themesDir); } + bool themeLoaded = false; const FeatureGUIInfo& Settings::GetGUIInfo() const { @@ -164,14 +166,27 @@ namespace cheat::feature ImGui::BeginGroupPanel("Colors"); { static std::string nameBuffer_; + if (this->f_DefaultTheme.value() != "Default" && !themeLoaded) + { + Colors_Import(f_DefaultTheme.value()); + themeLoaded = true; + } + ImGui::InputText("Name", &nameBuffer_); - if (ImGui::Button("Export")) + if (std::filesystem::exists(themesDir / (nameBuffer_ + ".json"))) + { + if (ImGui::Button("Set as default")) + f_DefaultTheme = nameBuffer_; + if (ImGui::Button("Load")) + { + Colors_Import(nameBuffer_); + themeLoaded = true; + } + else { + ImGui::Text("Theme does not exist.");} + } + if (ImGui::Button("Save")) Colors_Export(nameBuffer_); - if (ImGui::Button("Import")) - Colors_Import(nameBuffer_); - if (ImGui::Button("Open themes folder")) - ShellExecute(nullptr, "open", themesDir.c_str(), nullptr, nullptr, SW_SHOW); - } ImGui::EndGroupPanel(); } diff --git a/cheat-base/src/cheat-base/cheat/misc/Settings.h b/cheat-base/src/cheat-base/cheat/misc/Settings.h index 51eadca..69a8fe6 100644 --- a/cheat-base/src/cheat-base/cheat/misc/Settings.h +++ b/cheat-base/src/cheat-base/cheat/misc/Settings.h @@ -32,6 +32,7 @@ namespace cheat::feature config::Field f_HotkeyExit; std::filesystem::path themesDir; + config::Field f_DefaultTheme; static Settings& GetInstance(); From 92cc932852e6fad6ff13d389f4ec42329677afea Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Fri, 5 Aug 2022 05:20:13 -0600 Subject: [PATCH 20/30] Fix AutoDestroy:Plants not working if enabled alone --- .../src/user/cheat/world/AutoDestroy.cpp | 69 +++++++++---------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/cheat-library/src/user/cheat/world/AutoDestroy.cpp b/cheat-library/src/user/cheat/world/AutoDestroy.cpp index 757d7d1..3f873e2 100644 --- a/cheat-library/src/user/cheat/world/AutoDestroy.cpp +++ b/cheat-library/src/user/cheat/world/AutoDestroy.cpp @@ -9,32 +9,32 @@ #include #include -namespace cheat::feature +namespace cheat::feature { static void LCAbilityElement_ReduceModifierDurability_Hook(app::LCAbilityElement* __this, int32_t modifierDurabilityIndex, float reduceDurability, app::Nullable_1_Single_ deltaTime, MethodInfo* method); - AutoDestroy::AutoDestroy() : Feature(), - NF(f_Enabled, "Auto Destroy", "AutoDestroy", false), - NF(f_DestroyOres, "Destroy Ores", "AutoDestroy", false), - NF(f_DestroyShields, "Destroy Shields", "AutoDestroy", false), - NF(f_DestroyDoodads, "Destroy Doodads", "AutoDestroy", false), - NF(f_DestroyPlants, "Destroy Plants", "AutoDestroy", false), - NF(f_Range, "Range", "AutoDestroy", 10.0f) - { + AutoDestroy::AutoDestroy() : Feature(), + NF(f_Enabled, "Auto Destroy", "AutoDestroy", false), + NF(f_DestroyOres, "Destroy Ores", "AutoDestroy", false), + NF(f_DestroyShields, "Destroy Shields", "AutoDestroy", false), + NF(f_DestroyDoodads, "Destroy Doodads", "AutoDestroy", false), + NF(f_DestroyPlants, "Destroy Plants", "AutoDestroy", false), + NF(f_Range, "Range", "AutoDestroy", 10.0f) + { HookManager::install(app::MoleMole_LCAbilityElement_ReduceModifierDurability, LCAbilityElement_ReduceModifierDurability_Hook); } - const FeatureGUIInfo& AutoDestroy::GetGUIInfo() const - { - static const FeatureGUIInfo info { "Auto Destroy Objects", "World", true }; - return info; - } + const FeatureGUIInfo& AutoDestroy::GetGUIInfo() const + { + static const FeatureGUIInfo info{ "Auto Destroy Objects", "World", true }; + return info; + } - void AutoDestroy::DrawMain() - { + void AutoDestroy::DrawMain() + { ImGui::TextColored(ImColor(255, 165, 0, 255), "Note. This feature is not fully tested detection-wise.\n" "Not recommended for main accounts or used with high values."); - + ConfigWidget("Enabled", f_Enabled, "Instantly destroys non-living objects within range."); ImGui::Indent(); ConfigWidget("Ores", f_DestroyOres, "Ores and variants, e.g. electro crystals, marrows, etc."); @@ -47,15 +47,15 @@ namespace cheat::feature ConfigWidget("Plants", f_DestroyPlants, "Dandelion Seeds, Sakura Bloom, etc."); ImGui::Unindent(); ConfigWidget("Range (m)", f_Range, 0.1f, 1.0f, 15.0f); - } + } - bool AutoDestroy::NeedStatusDraw() const + bool AutoDestroy::NeedStatusDraw() const { - return f_Enabled; - } + return f_Enabled; + } - void AutoDestroy::DrawStatus() - { + void AutoDestroy::DrawStatus() + { ImGui::Text("Destroy [%.01fm%s%s%s%s%s]", f_Range.value(), f_DestroyOres || f_DestroyShields || f_DestroyDoodads || f_DestroyPlants ? "|" : "", @@ -63,13 +63,13 @@ namespace cheat::feature f_DestroyShields ? "S" : "", f_DestroyDoodads ? "D" : "", f_DestroyPlants ? "P" : ""); - } + } - AutoDestroy& AutoDestroy::GetInstance() - { - static AutoDestroy instance; - return instance; - } + AutoDestroy& AutoDestroy::GetInstance() + { + static AutoDestroy instance; + return instance; + } // Thanks to @RyujinZX // Every ore has ability element component @@ -82,18 +82,17 @@ namespace cheat::feature auto& manager = game::EntityManager::instance(); auto& autoDestroy = AutoDestroy::GetInstance(); auto entity = __this->fields._._._entity; - if (autoDestroy.f_Enabled && + if (autoDestroy.f_Enabled && autoDestroy.f_Range > manager.avatar()->distance(entity) && ( (autoDestroy.f_DestroyOres && game::filters::combined::Ores.IsValid(manager.entity(entity))) || (autoDestroy.f_DestroyDoodads && (game::filters::combined::Doodads.IsValid(manager.entity(entity)) || game::filters::chest::SBramble.IsValid(manager.entity(entity)))) || (autoDestroy.f_DestroyShields && !game::filters::combined::MonsterBosses.IsValid(manager.entity(entity)) && ( - game::filters::combined::MonsterShielded.IsValid(manager.entity(entity)) || // For shields attached to monsters, e.g. abyss mage shields. - game::filters::combined::MonsterEquips.IsValid(manager.entity(entity)) || // For shields/weapons equipped by monsters, e.g. rock shield. - (autoDestroy.f_DestroyPlants && game::filters::combined::PlantDestroy.IsValid(manager.entity(entity))) // For plants e.g dandelion seeds. - )) + game::filters::combined::MonsterShielded.IsValid(manager.entity(entity)) || // For shields attached to monsters, e.g. abyss mage shields. + game::filters::combined::MonsterEquips.IsValid(manager.entity(entity)))) || // For shields/weapons equipped by monsters, e.g. rock shield. + (autoDestroy.f_DestroyPlants && game::filters::combined::PlantDestroy.IsValid(manager.entity(entity))) // For plants e.g dandelion seeds. + ) ) - ) { // This value always above any ore durability reduceDurability = 1000; From 41a53fde4808ac23c261dd2277abff8e4290d42d Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Fri, 5 Aug 2022 19:53:20 -0600 Subject: [PATCH 21/30] configID checks for Rapid Fire --- .../src/user/cheat/player/RapidFire.cpp | 103 ++++++++++-------- 1 file changed, 59 insertions(+), 44 deletions(-) diff --git a/cheat-library/src/user/cheat/player/RapidFire.cpp b/cheat-library/src/user/cheat/player/RapidFire.cpp index bcad5ee..d49b3e2 100644 --- a/cheat-library/src/user/cheat/player/RapidFire.cpp +++ b/cheat-library/src/user/cheat/player/RapidFire.cpp @@ -6,41 +6,41 @@ #include #include -namespace cheat::feature +namespace cheat::feature { static void LCBaseCombat_DoHitEntity_Hook(app::LCBaseCombat* __this, uint32_t targetID, app::AttackResult* attackResult, bool ignoreCheckCanBeHitInMP, MethodInfo* method); - RapidFire::RapidFire() : Feature(), - NF(f_Enabled, "Attack Multiplier", "RapidFire", false), - NF(f_MultiHit, "Multi-hit", "RapidFire", false), - NF(f_Multiplier, "Hit Multiplier", "RapidFire", 2), - NF(f_OnePunch, "One Punch Mode", "RapidFire", false), - NF(f_Randomize, "Randomize", "RapidFire", false), - NF(f_minMultiplier, "Min Multiplier", "RapidFire", 1), - NF(f_maxMultiplier, "Max Multiplier", "RapidFire", 3), - NF(f_MultiTarget, "Multi-target", "RapidFire", false), - NF(f_MultiTargetRadius, "Multi-target Radius", "RapidFire", 20.0f) - { + RapidFire::RapidFire() : Feature(), + NF(f_Enabled, "Attack Multiplier", "RapidFire", false), + NF(f_MultiHit, "Multi-hit", "RapidFire", false), + NF(f_Multiplier, "Hit Multiplier", "RapidFire", 2), + NF(f_OnePunch, "One Punch Mode", "RapidFire", false), + NF(f_Randomize, "Randomize", "RapidFire", false), + NF(f_minMultiplier, "Min Multiplier", "RapidFire", 1), + NF(f_maxMultiplier, "Max Multiplier", "RapidFire", 3), + NF(f_MultiTarget, "Multi-target", "RapidFire", false), + NF(f_MultiTargetRadius, "Multi-target Radius", "RapidFire", 20.0f) + { HookManager::install(app::MoleMole_LCBaseCombat_DoHitEntity, LCBaseCombat_DoHitEntity_Hook); - } + } - const FeatureGUIInfo& RapidFire::GetGUIInfo() const - { - static const FeatureGUIInfo info{ "Attack Effects", "Player", true }; - return info; - } + const FeatureGUIInfo& RapidFire::GetGUIInfo() const + { + static const FeatureGUIInfo info{ "Attack Effects", "Player", true }; + return info; + } - void RapidFire::DrawMain() - { + void RapidFire::DrawMain() + { ConfigWidget("Enabled", f_Enabled, "Enables attack multipliers. Need to choose a mode to work."); ImGui::SameLine(); ImGui::TextColored(ImColor(255, 165, 0, 255), "Choose any or both modes below."); ConfigWidget("Multi-hit Mode", f_MultiHit, "Enables multi-hit.\n" \ - "Multiplies your attack count.\n" \ - "This is not well tested, and can be detected by anticheat.\n" \ - "Not recommended to be used with main accounts or used with high values.\n" \ + "Multiplies your attack count.\n" \ + "This is not well tested, and can be detected by anticheat.\n" \ + "Not recommended to be used with main accounts or used with high values.\n" \ "Known issues with certain multi-hit attacks, e.g. Xiao E, Ayaka CA, etc."); ImGui::Indent(); @@ -73,20 +73,20 @@ namespace cheat::feature "If multi-hit is off and there are still multiple numbers on a single target, check the Entity Manager in the Debug section to see if there are invisible entities.\n" \ "This can cause EXTREME lag and quick bans if used with multi-hit. You are warned." ); - + ImGui::Indent(); ConfigWidget("Radius (m)", f_MultiTargetRadius, 0.1f, 5.0f, 50.0f, "Radius to check for valid targets."); ImGui::Unindent(); - } + } - bool RapidFire::NeedStatusDraw() const -{ - return f_Enabled && (f_MultiHit || f_MultiTarget); - } + bool RapidFire::NeedStatusDraw() const + { + return f_Enabled && (f_MultiHit || f_MultiTarget); + } - void RapidFire::DrawStatus() - { - if (f_MultiHit) + void RapidFire::DrawStatus() + { + if (f_MultiHit) { if (f_Randomize) ImGui::Text("Multi-Hit Random[%d|%d]", f_minMultiplier.value(), f_maxMultiplier.value()); @@ -97,20 +97,20 @@ namespace cheat::feature } if (f_MultiTarget) ImGui::Text("Multi-Target [%.01fm]", f_MultiTargetRadius.value()); - } + } - RapidFire& RapidFire::GetInstance() - { - static RapidFire instance; - return instance; - } + RapidFire& RapidFire::GetInstance() + { + static RapidFire instance; + return instance; + } int RapidFire::CalcCountToKill(float attackDamage, uint32_t targetID) { if (attackDamage == 0) return f_Multiplier; - + auto& manager = game::EntityManager::instance(); auto targetEntity = manager.entity(targetID); if (targetEntity == nullptr) @@ -165,10 +165,10 @@ namespace cheat::feature entity = game::Entity(app::MoleMole_GadgetEntity_GetOwnerEntity(reinterpret_cast(entity.raw()), nullptr)); if (entity.runtimeID() == avatarID) return true; - } + } return false; - + } bool IsAttackByAvatar(game::Entity& attacker) @@ -183,6 +183,20 @@ namespace cheat::feature return attackerID == avatarID || IsAvatarOwner(attacker); } + bool IsConfigByAvatar(game::Entity& attacker) + { + if (attacker.raw() == nullptr) + return false; + + auto& manager = game::EntityManager::instance(); + auto avatarID = manager.avatar()->raw()->fields._configID_k__BackingField; + auto attackerID = attacker.raw()->fields._configID_k__BackingField; + // Taiga#5555: IDs can be found in ConfigAbility_Avatar_*.json or GadgetExcelConfigData.json + bool bulletID = attackerID >= 40000160 && attackerID <= 41069999; + + return avatarID == attackerID || bulletID; + } + bool IsValidByFilter(game::Entity* entity) { if (game::filters::combined::OrganicTargets.IsValid(entity) || @@ -192,7 +206,7 @@ namespace cheat::feature game::filters::puzzle::LargeRockPile.IsValid(entity) || game::filters::puzzle::SmallRockPile.IsValid(entity)) return true; - return false; + return false; } // Raises when any entity do hit event. @@ -203,7 +217,7 @@ namespace cheat::feature { auto attacker = game::Entity(__this->fields._._._entity); RapidFire& rapidFire = RapidFire::GetInstance(); - if (!IsAttackByAvatar(attacker) || !rapidFire.f_Enabled) + if (!IsConfigByAvatar(attacker) || !IsAttackByAvatar(attacker) || !rapidFire.f_Enabled) return CALL_ORIGIN(LCBaseCombat_DoHitEntity_Hook, __this, targetID, attackResult, ignoreCheckCanBeHitInMP, method); auto& manager = game::EntityManager::instance(); @@ -243,7 +257,8 @@ namespace cheat::feature int attackCount = rapidFire.GetAttackCount(__this, entity->runtimeID(), attackResult); for (int i = 0; i < attackCount; i++) CALL_ORIGIN(LCBaseCombat_DoHitEntity_Hook, __this, entity->runtimeID(), attackResult, ignoreCheckCanBeHitInMP, method); - } else CALL_ORIGIN(LCBaseCombat_DoHitEntity_Hook, __this, entity->runtimeID(), attackResult, ignoreCheckCanBeHitInMP, method); + } + else CALL_ORIGIN(LCBaseCombat_DoHitEntity_Hook, __this, entity->runtimeID(), attackResult, ignoreCheckCanBeHitInMP, method); } } } From e42914712239647537026c8e68741b55c11ae985 Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Fri, 5 Aug 2022 23:47:10 -0600 Subject: [PATCH 22/30] Added animation rapid fire --- .../src/user/cheat/player/RapidFire.cpp | 28 +++++++++++++++++-- .../src/user/cheat/player/RapidFire.h | 1 + 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/cheat-library/src/user/cheat/player/RapidFire.cpp b/cheat-library/src/user/cheat/player/RapidFire.cpp index d49b3e2..b8292a1 100644 --- a/cheat-library/src/user/cheat/player/RapidFire.cpp +++ b/cheat-library/src/user/cheat/player/RapidFire.cpp @@ -10,6 +10,9 @@ namespace cheat::feature { static void LCBaseCombat_DoHitEntity_Hook(app::LCBaseCombat* __this, uint32_t targetID, app::AttackResult* attackResult, bool ignoreCheckCanBeHitInMP, MethodInfo* method); + static void VCAnimatorEvent_HandleProcessItem_Hook(app::MoleMole_VCAnimatorEvent* __this, + app::MoleMole_VCAnimatorEvent_MoleMole_VCAnimatorEvent_AnimatorEventPatternProcessItem* processItem, + app::AnimatorStateInfo processStateInfo, app::MoleMole_VCAnimatorEvent_MoleMole_VCAnimatorEvent_TriggerMode__Enum mode, MethodInfo* method); RapidFire::RapidFire() : Feature(), NF(f_Enabled, "Attack Multiplier", "RapidFire", false), @@ -20,9 +23,11 @@ namespace cheat::feature NF(f_minMultiplier, "Min Multiplier", "RapidFire", 1), NF(f_maxMultiplier, "Max Multiplier", "RapidFire", 3), NF(f_MultiTarget, "Multi-target", "RapidFire", false), - NF(f_MultiTargetRadius, "Multi-target Radius", "RapidFire", 20.0f) + NF(f_MultiTargetRadius, "Multi-target Radius", "RapidFire", 20.0f), + NF(f_MultiAnimation, "Multi-animation", "RapidFire", false) { HookManager::install(app::MoleMole_LCBaseCombat_DoHitEntity, LCBaseCombat_DoHitEntity_Hook); + HookManager::install(app::MoleMole_VCAnimatorEvent_HandleProcessItem, VCAnimatorEvent_HandleProcessItem_Hook); } const FeatureGUIInfo& RapidFire::GetGUIInfo() const @@ -77,11 +82,14 @@ namespace cheat::feature ImGui::Indent(); ConfigWidget("Radius (m)", f_MultiTargetRadius, 0.1f, 5.0f, 50.0f, "Radius to check for valid targets."); ImGui::Unindent(); + + ConfigWidget("Multi-animation", f_MultiAnimation, "Enables multi-animation attacks.\n" \ + "Do keep in mind that the character's audio will also be spammed."); } bool RapidFire::NeedStatusDraw() const { - return f_Enabled && (f_MultiHit || f_MultiTarget); + return f_Enabled && (f_MultiHit || f_MultiTarget || f_MultiAnimation); } void RapidFire::DrawStatus() @@ -97,6 +105,9 @@ namespace cheat::feature } if (f_MultiTarget) ImGui::Text("Multi-Target [%.01fm]", f_MultiTargetRadius.value()); + + if (f_MultiAnimation) + ImGui::Text("Multi-Animation"); } RapidFire& RapidFire::GetInstance() @@ -261,5 +272,18 @@ namespace cheat::feature else CALL_ORIGIN(LCBaseCombat_DoHitEntity_Hook, __this, entity->runtimeID(), attackResult, ignoreCheckCanBeHitInMP, method); } } + + static void VCAnimatorEvent_HandleProcessItem_Hook(app::MoleMole_VCAnimatorEvent* __this, + app::MoleMole_VCAnimatorEvent_MoleMole_VCAnimatorEvent_AnimatorEventPatternProcessItem* processItem, + app::AnimatorStateInfo processStateInfo, app::MoleMole_VCAnimatorEvent_MoleMole_VCAnimatorEvent_TriggerMode__Enum mode, MethodInfo* method) + { + auto attacker = game::Entity(__this->fields._._._entity); + RapidFire& rapidFire = RapidFire::GetInstance(); + + if (rapidFire.f_MultiAnimation && IsAttackByAvatar(attacker)) + processItem->fields.lastTime = -1; + + CALL_ORIGIN(VCAnimatorEvent_HandleProcessItem_Hook, __this, processItem, processStateInfo, mode, method); + } } diff --git a/cheat-library/src/user/cheat/player/RapidFire.h b/cheat-library/src/user/cheat/player/RapidFire.h index 940741c..7d9d26f 100644 --- a/cheat-library/src/user/cheat/player/RapidFire.h +++ b/cheat-library/src/user/cheat/player/RapidFire.h @@ -19,6 +19,7 @@ namespace cheat::feature config::Field f_maxMultiplier; config::Field> f_MultiTarget; config::Field f_MultiTargetRadius; + config::Field> f_MultiAnimation; static RapidFire& GetInstance(); From bfb7b0f3a631150e9a999f53ae9da548b4e5582f Mon Sep 17 00:00:00 2001 From: Nanako <00sh.chiha+github@gmail.com> Date: Fri, 5 Aug 2022 18:08:29 +0900 Subject: [PATCH 23/30] Update Settings.cpp --- .../src/cheat-base/cheat/misc/Settings.cpp | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/cheat-base/src/cheat-base/cheat/misc/Settings.cpp b/cheat-base/src/cheat-base/cheat/misc/Settings.cpp index 036bdfe..f710b29 100644 --- a/cheat-base/src/cheat-base/cheat/misc/Settings.cpp +++ b/cheat-base/src/cheat-base/cheat/misc/Settings.cpp @@ -166,24 +166,39 @@ namespace cheat::feature ImGui::BeginGroupPanel("Colors"); { static std::string nameBuffer_; + if (this->f_DefaultTheme.value() != "Default" && !themeLoaded) { - Colors_Import(f_DefaultTheme.value()); - themeLoaded = true; + LOG_INFO("Loading theme: %s", themesDir / (f_DefaultTheme.value() + ".json").c_str()); + if (!std::filesystem::exists(themesDir / (f_DefaultTheme.value() + ".json"))) + { + LOG_ERROR("Theme file not found: %s", themesDir / (f_DefaultTheme.value() + ".json").c_str()); + f_DefaultTheme = "Default"; + themeLoaded = true; + } + else + { + Colors_Import(f_DefaultTheme.value()); + themeLoaded = true; + LOG_INFO("Loaded theme \"%s\"", f_DefaultTheme.value().c_str()); + } } ImGui::InputText("Name", &nameBuffer_); if (std::filesystem::exists(themesDir / (nameBuffer_ + ".json"))) { - if (ImGui::Button("Set as default")) - f_DefaultTheme = nameBuffer_; + if (this->f_DefaultTheme.value() != nameBuffer_) + if (ImGui::Button("Set as default")) + f_DefaultTheme = nameBuffer_; if (ImGui::Button("Load")) { Colors_Import(nameBuffer_); themeLoaded = true; } - else { - ImGui::Text("Theme does not exist.");} + } + else + { + ImGui::Text("Theme does not exist."); } if (ImGui::Button("Save")) Colors_Export(nameBuffer_); @@ -205,4 +220,3 @@ namespace cheat::feature ExitProcess(0); } } - From 04b79610d8a500120d3845e7e1752a70edf3767a Mon Sep 17 00:00:00 2001 From: Nanako <00sh.chiha+github@gmail.com> Date: Sat, 6 Aug 2022 15:48:03 +0900 Subject: [PATCH 24/30] Fix Init Co-Authored-By: Taiga <67109235+Taiga74164@users.noreply.github.com> --- .../src/cheat-base/cheat/misc/Settings.cpp | 87 +++++++++---------- .../src/cheat-base/cheat/misc/Settings.h | 11 +-- cheat-base/src/cheat-base/render/renderer.cpp | 16 ++-- 3 files changed, 56 insertions(+), 58 deletions(-) diff --git a/cheat-base/src/cheat-base/cheat/misc/Settings.cpp b/cheat-base/src/cheat-base/cheat/misc/Settings.cpp index f710b29..cdf4fdb 100644 --- a/cheat-base/src/cheat-base/cheat/misc/Settings.cpp +++ b/cheat-base/src/cheat-base/cheat/misc/Settings.cpp @@ -10,9 +10,9 @@ #include "shlwapi.h" #pragma comment(lib, "shlwapi.lib") -namespace cheat::feature +namespace cheat::feature { - Settings::Settings() : Feature(), + Settings::Settings() : Feature(), NF(f_MenuKey, "Show Cheat Menu Key", "General", Hotkey(VK_F1)), NF(f_HotkeysEnabled, "Hotkeys Enabled", "General", true), NF(f_FontSize, "Font size", "General", 16.0f), @@ -20,17 +20,17 @@ namespace cheat::feature NF(f_StatusMove, "Move Status Window", "General::StatusWindow", true), NF(f_StatusShow, "Show Status Window", "General::StatusWindow", true), - - NF(f_InfoMove, "Move Info Window", "General::InfoWindow", true), - NF(f_InfoShow, "Show Info Window", "General::InfoWindow", true), - + + NF(f_InfoMove, "Move Info Window", "General::InfoWindow", true), + NF(f_InfoShow, "Show Info Window", "General::InfoWindow", true), + NF(f_FpsMove, "Move FPS Indicator", "General::FPS", false), NF(f_FpsShow, "Show FPS Indicator", "General::FPS", true), - NF(f_NotificationsShow, "Show Notifications", "General::Notify", true), + NF(f_NotificationsShow, "Show Notifications", "General::Notify", true), NF(f_NotificationsDelay, "Notifications Delay", "General::Notify", 500), - - NF(f_FileLogging, "File Logging", "General::Logging", false), + + NF(f_FileLogging, "File Logging", "General::Logging", false), NF(f_ConsoleLogging, "Console Logging", "General::Logging", true), NF(f_FastExitEnable, "Fast Exit", "General::FastExit", false), @@ -38,35 +38,47 @@ namespace cheat::feature NFS(f_DefaultTheme, "Theme", "General::Colors", "Default"), themesDir(util::GetCurrentPath() / "themes") - { + { renderer::SetGlobalFontSize(static_cast(f_FontSize)); f_HotkeyExit.value().PressedEvent += MY_METHOD_HANDLER(Settings::OnExitKeyPressed); if (!std::filesystem::exists(themesDir)) std::filesystem::create_directory(themesDir); - } - bool themeLoaded = false; - const FeatureGUIInfo& Settings::GetGUIInfo() const - { - static const FeatureGUIInfo info{ "", "Settings", false }; - return info; - } + } + + bool inited = false; + void Settings::Init() { + if (this->f_DefaultTheme.value() != "Default" && !inited) + { + LOG_INFO("Loading theme: %s", themesDir / (f_DefaultTheme.value() + ".json").c_str()); + if (!std::filesystem::exists(themesDir / (f_DefaultTheme.value() + ".json"))) + f_DefaultTheme = "Default"; + else Colors_Import(f_DefaultTheme.value()); + inited = true; + } + } + + const FeatureGUIInfo& Settings::GetGUIInfo() const + { + static const FeatureGUIInfo info{ "", "Settings", false }; + return info; + } void Settings::Colors_Export(std::string name) { - ImGuiStyle &style = ImGui::GetStyle(); + ImGuiStyle& style = ImGui::GetStyle(); auto colors = style.Colors; nlohmann::json json; for (int i = 0; i < ImGuiCol_COUNT; i++) - json[ImGui::GetStyleColorName((ImGuiCol)i)] = {colors[i].x, colors[i].y, colors[i].z, colors[i].w}; + json[ImGui::GetStyleColorName((ImGuiCol)i)] = { colors[i].x, colors[i].y, colors[i].z, colors[i].w }; std::ofstream file(themesDir / (name + ".json")); file << std::setw(4) << json << std::endl; } - + void Settings::Colors_Import(std::string name) { - ImGuiStyle &style = ImGui::GetStyle(); + ImGuiStyle& style = ImGui::GetStyle(); auto colors = style.Colors; nlohmann::json json; std::ifstream file(themesDir / (name + ".json")); @@ -142,7 +154,7 @@ namespace cheat::feature ImGui::BeginGroupPanel("Show Notifications"); { ConfigWidget(f_NotificationsShow, "Notifications on the bottom-right corner of the window will be displayed."); - ConfigWidget(f_NotificationsDelay, 1,1,10000, "Delay in milliseconds between notifications."); + ConfigWidget(f_NotificationsDelay, 1, 1, 10000, "Delay in milliseconds between notifications."); } ImGui::EndGroupPanel(); @@ -150,7 +162,7 @@ namespace cheat::feature { ConfigWidget("Enabled", f_FastExitEnable, - "Enable Fast Exit.\n" + "Enable Fast Exit.\n" ); if (!f_FastExitEnable) ImGui::BeginDisabled(); @@ -166,24 +178,6 @@ namespace cheat::feature ImGui::BeginGroupPanel("Colors"); { static std::string nameBuffer_; - - if (this->f_DefaultTheme.value() != "Default" && !themeLoaded) - { - LOG_INFO("Loading theme: %s", themesDir / (f_DefaultTheme.value() + ".json").c_str()); - if (!std::filesystem::exists(themesDir / (f_DefaultTheme.value() + ".json"))) - { - LOG_ERROR("Theme file not found: %s", themesDir / (f_DefaultTheme.value() + ".json").c_str()); - f_DefaultTheme = "Default"; - themeLoaded = true; - } - else - { - Colors_Import(f_DefaultTheme.value()); - themeLoaded = true; - LOG_INFO("Loaded theme \"%s\"", f_DefaultTheme.value().c_str()); - } - } - ImGui::InputText("Name", &nameBuffer_); if (std::filesystem::exists(themesDir / (nameBuffer_ + ".json"))) { @@ -193,7 +187,6 @@ namespace cheat::feature if (ImGui::Button("Load")) { Colors_Import(nameBuffer_); - themeLoaded = true; } } else @@ -206,11 +199,11 @@ namespace cheat::feature ImGui::EndGroupPanel(); } - Settings& Settings::GetInstance() - { - static Settings instance; - return instance; - } + Settings& Settings::GetInstance() + { + static Settings instance; + return instance; + } void Settings::OnExitKeyPressed() { diff --git a/cheat-base/src/cheat-base/cheat/misc/Settings.h b/cheat-base/src/cheat-base/cheat/misc/Settings.h index 69a8fe6..2a38205 100644 --- a/cheat-base/src/cheat-base/cheat/misc/Settings.h +++ b/cheat-base/src/cheat-base/cheat/misc/Settings.h @@ -2,11 +2,11 @@ #include #include -namespace cheat::feature +namespace cheat::feature { class Settings : public Feature - { + { public: config::Field f_MenuKey; config::Field f_HotkeysEnabled; @@ -18,10 +18,10 @@ namespace cheat::feature config::Field f_InfoMove; config::Field f_InfoShow; - + config::Field f_FpsShow; config::Field f_FpsMove; - + config::Field f_NotificationsShow; config::Field f_NotificationsDelay; @@ -38,9 +38,10 @@ namespace cheat::feature const FeatureGUIInfo& GetGUIInfo() const override; void DrawMain() override; + void Init(); void Colors_Export(std::string name); void Colors_Import(std::string name); - + private: void OnExitKeyPressed(); diff --git a/cheat-base/src/cheat-base/render/renderer.cpp b/cheat-base/src/cheat-base/render/renderer.cpp index f9ba79b..17a633e 100644 --- a/cheat-base/src/cheat-base/render/renderer.cpp +++ b/cheat-base/src/cheat-base/render/renderer.cpp @@ -12,6 +12,7 @@ #include #include +#include extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); @@ -33,14 +34,14 @@ namespace renderer static constexpr int _fontsCount = _fontSizeMax / _fontSizeStep; static std::array _fonts; - static Data _customFontData {}; + static Data _customFontData{}; static WNDPROC OriginalWndProcHandler; static ID3D11RenderTargetView* mainRenderTargetView; static void OnRenderDX11(ID3D11DeviceContext* pContext); static void OnInitializeDX11(HWND window, ID3D11Device* pDevice, ID3D11DeviceContext* pContext, IDXGISwapChain* pChain); - + static void OnPreRenderDX12(); static void OnPostRenderDX12(ID3D12GraphicsCommandList* commandList); static void OnInitializeDX12(HWND window, ID3D12Device* pDevice, UINT buffersCounts, ID3D12DescriptorHeap* pDescriptorHeapImGuiRender); @@ -106,7 +107,7 @@ namespace renderer return io.FontDefault; } int fontSizeInt = static_cast(fontSize); - int fontIndex = fontSizeInt / _fontSizeStep + + int fontIndex = fontSizeInt / _fontSizeStep + (fontSizeInt % _fontSizeStep > (_fontSizeStep / 2) ? 1 : 0) - 1; fontIndex = std::clamp(fontIndex, 0, _fontsCount - 1); return _fonts[fontIndex]; @@ -122,7 +123,7 @@ namespace renderer int fontSizeInt = static_cast(fontSize); int fontIndex = fontSizeInt / _fontSizeStep; - int fontAligned = fontIndex * _fontSizeStep + + int fontAligned = fontIndex * _fontSizeStep + ((fontSizeInt % _fontSizeStep) > _fontSizeStep / 2 ? _fontSizeStep : 0); fontAligned = std::clamp(fontAligned, _fontSizeStep, _fontSizeMax); @@ -138,7 +139,7 @@ namespace renderer { return _globalFontSize; } - + static void LoadCustomFont() { if (_customFontData.data == nullptr) @@ -195,7 +196,7 @@ namespace renderer reinterpret_cast(hWndProc))); ImGui_ImplWin32_Init(window); - ImGui_ImplDX12_Init(pDevice, buffersCounts, DXGI_FORMAT_R8G8B8A8_UNORM, + ImGui_ImplDX12_Init(pDevice, buffersCounts, DXGI_FORMAT_R8G8B8A8_UNORM, pDescriptorHeapImGuiRender, pDescriptorHeapImGuiRender->GetCPUDescriptorHandleForHeapStart(), pDescriptorHeapImGuiRender->GetGPUDescriptorHandleForHeapStart()); @@ -253,6 +254,9 @@ namespace renderer pContext->OMSetRenderTargets(1, &mainRenderTargetView, nullptr); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + + auto& themes = cheat::feature::Settings::GetInstance(); + themes.Init(); } static LRESULT CALLBACK hWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) From 97318b646ce1360494b030c96f75ed57101aa2e8 Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Sat, 6 Aug 2022 07:46:39 -0600 Subject: [PATCH 25/30] Fix issue with Kazuha E --- cheat-library/src/user/cheat/player/RapidFire.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheat-library/src/user/cheat/player/RapidFire.cpp b/cheat-library/src/user/cheat/player/RapidFire.cpp index b8292a1..db2e4d5 100644 --- a/cheat-library/src/user/cheat/player/RapidFire.cpp +++ b/cheat-library/src/user/cheat/player/RapidFire.cpp @@ -281,7 +281,7 @@ namespace cheat::feature RapidFire& rapidFire = RapidFire::GetInstance(); if (rapidFire.f_MultiAnimation && IsAttackByAvatar(attacker)) - processItem->fields.lastTime = -1; + processItem->fields.lastTime = 0; CALL_ORIGIN(VCAnimatorEvent_HandleProcessItem_Hook, __this, processItem, processStateInfo, mode, method); } From 10ebe7a99d890acdc07c61c78f7f3d5cc11bc120 Mon Sep 17 00:00:00 2001 From: lunatic <56441863+lunaticwhat@users.noreply.github.com> Date: Sat, 6 Aug 2022 23:44:36 +0700 Subject: [PATCH 26/30] re-arrange codes and color settings --- .../src/cheat-base/cheat/misc/Settings.cpp | 51 ++++++++++++------- .../src/cheat-base/cheat/misc/Settings.h | 5 +- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/cheat-base/src/cheat-base/cheat/misc/Settings.cpp b/cheat-base/src/cheat-base/cheat/misc/Settings.cpp index cdf4fdb..fff9213 100644 --- a/cheat-base/src/cheat-base/cheat/misc/Settings.cpp +++ b/cheat-base/src/cheat-base/cheat/misc/Settings.cpp @@ -15,9 +15,7 @@ namespace cheat::feature Settings::Settings() : Feature(), NF(f_MenuKey, "Show Cheat Menu Key", "General", Hotkey(VK_F1)), NF(f_HotkeysEnabled, "Hotkeys Enabled", "General", true), - NF(f_FontSize, "Font size", "General", 16.0f), - NF(f_ShowStyleEditor, "Show Style Editor", "General", false), - + NF(f_StatusMove, "Move Status Window", "General::StatusWindow", true), NF(f_StatusShow, "Show Status Window", "General::StatusWindow", true), @@ -35,6 +33,9 @@ namespace cheat::feature NF(f_FastExitEnable, "Fast Exit", "General::FastExit", false), NF(f_HotkeyExit, "Hotkeys", "General::FastExit", Hotkey(VK_F12)), + + NF(f_FontSize, "Font Size", "General", 16.0f), + NF(f_ShowStyleEditor, "Show Colors Customization", "General", false), NFS(f_DefaultTheme, "Theme", "General::Colors", "Default"), themesDir(util::GetCurrentPath() / "themes") @@ -102,13 +103,7 @@ namespace cheat::feature "Key to toggle main menu visibility. Cannot be empty.\n"\ "If you forget this key, you can see or set it in your config file."); ConfigWidget(f_HotkeysEnabled, "Enable hotkeys."); - if (ConfigWidget(f_FontSize, 1, 8, 64, "Font size for cheat interface.")) - { - f_FontSize = std::clamp(f_FontSize.value(), 8, 64); - renderer::SetGlobalFontSize(static_cast(f_FontSize)); - } - ConfigWidget(f_ShowStyleEditor, "Show interface style editor window."); - } + } ImGui::EndGroupPanel(); ImGui::BeginGroupPanel("Logging"); @@ -175,26 +170,44 @@ namespace cheat::feature } ImGui::EndGroupPanel(); - ImGui::BeginGroupPanel("Colors"); + ImGui::BeginGroupPanel("Interface Customization"); { + if (ConfigWidget(f_FontSize, 1, 8, 64, "Adjust interface font size.")) + { + f_FontSize = std::clamp(f_FontSize.value(), 8, 64); + renderer::SetGlobalFontSize(static_cast(f_FontSize)); + } + ImGui::Spacing(); + + ConfigWidget(f_ShowStyleEditor, "Show colors customization window."); + ImGui::Spacing(); + + ImGui::Text("Save Customized Color"); static std::string nameBuffer_; - ImGui::InputText("Name", &nameBuffer_); + ImGui::InputText("Color Name", &nameBuffer_); + if (ImGui::Button("Save")) + Colors_Export(nameBuffer_); + ImGui::SameLine(); + if (std::filesystem::exists(themesDir / (nameBuffer_ + ".json"))) { if (this->f_DefaultTheme.value() != nameBuffer_) - if (ImGui::Button("Set as default")) - f_DefaultTheme = nameBuffer_; - if (ImGui::Button("Load")) { - Colors_Import(nameBuffer_); + if (ImGui::Button("Set as default")) + { + f_DefaultTheme = nameBuffer_; + } + ImGui::SameLine(); + if (ImGui::Button("Load")) + { + Colors_Import(nameBuffer_); + } } } else { - ImGui::Text("Theme does not exist."); + ImGui::Text("Color does not exist."); } - if (ImGui::Button("Save")) - Colors_Export(nameBuffer_); } ImGui::EndGroupPanel(); } diff --git a/cheat-base/src/cheat-base/cheat/misc/Settings.h b/cheat-base/src/cheat-base/cheat/misc/Settings.h index 2a38205..7605b43 100644 --- a/cheat-base/src/cheat-base/cheat/misc/Settings.h +++ b/cheat-base/src/cheat-base/cheat/misc/Settings.h @@ -10,8 +10,6 @@ namespace cheat::feature public: config::Field f_MenuKey; config::Field f_HotkeysEnabled; - config::Field f_FontSize; - config::Field f_ShowStyleEditor; config::Field f_StatusMove; config::Field f_StatusShow; @@ -31,9 +29,12 @@ namespace cheat::feature config::Field f_FastExitEnable; config::Field f_HotkeyExit; + config::Field f_FontSize; + config::Field f_ShowStyleEditor; std::filesystem::path themesDir; config::Field f_DefaultTheme; + static Settings& GetInstance(); const FeatureGUIInfo& GetGUIInfo() const override; From 21fd6d5f24e7317e333530f84cb06269733c3c8f Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Sun, 7 Aug 2022 01:45:55 -0600 Subject: [PATCH 27/30] Fixed RapidFire for all polearm characters --- cheat-library/src/user/cheat/player/RapidFire.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cheat-library/src/user/cheat/player/RapidFire.cpp b/cheat-library/src/user/cheat/player/RapidFire.cpp index db2e4d5..8adf898 100644 --- a/cheat-library/src/user/cheat/player/RapidFire.cpp +++ b/cheat-library/src/user/cheat/player/RapidFire.cpp @@ -267,9 +267,9 @@ namespace cheat::feature if (rapidFire.f_MultiHit) { int attackCount = rapidFire.GetAttackCount(__this, entity->runtimeID(), attackResult); for (int i = 0; i < attackCount; i++) - CALL_ORIGIN(LCBaseCombat_DoHitEntity_Hook, __this, entity->runtimeID(), attackResult, ignoreCheckCanBeHitInMP, method); + app::MoleMole_LCBaseCombat_FireBeingHitEvent(__this, entity->runtimeID(), attackResult, method); } - else CALL_ORIGIN(LCBaseCombat_DoHitEntity_Hook, __this, entity->runtimeID(), attackResult, ignoreCheckCanBeHitInMP, method); + else app::MoleMole_LCBaseCombat_FireBeingHitEvent(__this, entity->runtimeID(), attackResult, method); } } From 0826a790058661450f91a5dfc95b3c2e438b5732 Mon Sep 17 00:00:00 2001 From: TerraFaster Date: Sun, 7 Aug 2022 17:04:50 +0300 Subject: [PATCH 28/30] Improve AutoCook feature UX --- .../src/user/cheat/world/AutoCook.cpp | 46 +++++++++++++++---- cheat-library/src/user/cheat/world/AutoCook.h | 6 +-- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/cheat-library/src/user/cheat/world/AutoCook.cpp b/cheat-library/src/user/cheat/world/AutoCook.cpp index 12cab44..712de5d 100644 --- a/cheat-library/src/user/cheat/world/AutoCook.cpp +++ b/cheat-library/src/user/cheat/world/AutoCook.cpp @@ -14,7 +14,9 @@ namespace cheat::feature app::Component_1* Profirency = nullptr; } - static void PlayerModule_RequestPlayerCook(app::MoleMole_PlayerModule* __this, uint32_t recipeId, uint32_t avatarId, uint32_t qteQuality, uint32_t count, MethodInfo* method); + static std::map qualities{ {"Strange", 1}, {"Normal", 2}, {"Delicious", 3} }; + + static void PlayerModule_RequestPlayerCook(app::MoleMole_PlayerModule* __this, uint32_t recipeId, uint32_t avatarId, uint32_t qteQuality, uint32_t count, MethodInfo* method); static void PlayerModule_OnPlayerCookRsp(app::MoleMole_PlayerModule* __this, app::PlayerCookRsp* rsp, MethodInfo* method); static void CookingQtePageContext_UpdateProficiency(app::CookingQtePageContext* __this, MethodInfo* method); @@ -22,7 +24,7 @@ namespace cheat::feature NF(f_Enabled, "Standart Cooking", "AutoCook", false), NF(f_FastProficiency, "Fast Proficiency", "AutoCook", false), NF(f_CountField, "Count Item", "AutoCook", 1), - NF(f_QualityField, "Quality", "AutoCook", 1) + NF(f_QualityField, "Quality", "AutoCook", "Normal") { HookManager::install(app::MoleMole_PlayerModule_RequestPlayerCook, PlayerModule_RequestPlayerCook); HookManager::install(app::MoleMole_PlayerModule_OnPlayerCookRsp, PlayerModule_OnPlayerCookRsp); @@ -38,12 +40,24 @@ namespace cheat::feature void AutoCook::DrawMain() { ConfigWidget(f_Enabled, "Fast Cooking if the recipe has fast cooking open. \n" \ - "If fast cooking is closed, you in addition need to turn on Fast Proficiency."); + "If fast cooking is closed, you in addition need to turn on Fast Proficiency."); ConfigWidget(f_FastProficiency, "Quickly prepare an unstudied recipe to the maximum possible."); ConfigWidget("Count Item", f_CountField, 1, 1, 100, "How much to cook at a time.\n" \ "(For standard mode only.)"); - ConfigWidget("Quality Cooking", f_QualityField, 1, 1, 3, "Quality of the cook."); + if (ImGui::BeginCombo("Cooking Quality", f_QualityField.value().c_str())) + { + for (auto& [qualityName, quality] : qualities) + { + bool is_selected = (f_QualityField.value().c_str() == qualityName); + if (ImGui::Selectable(qualityName.c_str(), is_selected)) + f_QualityField.value() = qualityName; + + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } } bool AutoCook::NeedStatusDraw() const @@ -53,7 +67,10 @@ namespace cheat::feature void AutoCook::DrawStatus() { - ImGui::Text("Auto Cooking [%s]", f_FastProficiency ? "Proficiency" : "Standart"); + if (f_FastProficiency) + ImGui::Text("Auto Cooking [Proficiency]"); + else + ImGui::Text("Auto Cooking [Standart, %s]", f_QualityField.value().c_str()); } AutoCook& AutoCook::GetInstance() @@ -82,9 +99,14 @@ namespace cheat::feature if (autoCook.f_Enabled || autoCook.f_FastProficiency) { autoCook.CookFoodMaxNum = app::MoleMole_Config_CookRecipeExcelConfig_CheckCookFoodMaxNum(recipeId, nullptr); - qteQuality = autoCook.f_QualityField; - if (!autoCook.f_FastProficiency && autoCook.f_Enabled){ + // To prevent possible crashes + if (!qualities.count(autoCook.f_QualityField.value())) + autoCook.f_QualityField.value() = "Normal"; + + qteQuality = qualities.find(autoCook.f_QualityField.value())->second; + + if (!autoCook.f_FastProficiency && autoCook.f_Enabled) { count = autoCook.f_CountField; if (autoCook.f_CountField > autoCook.CookFoodMaxNum) count = autoCook.CookFoodMaxNum; @@ -99,7 +121,7 @@ namespace cheat::feature auto RectTransform = app::GameObject_GetComponentByName(GameObject::Profirency, string_to_il2cppi("RectTransform"), nullptr); auto TransformChild = app::Transform_GetChild(reinterpret_cast(RectTransform), 0, nullptr); auto TextComponent = app::Component_1_GetComponent_1(reinterpret_cast(TransformChild), string_to_il2cppi("Text"), nullptr); - + if (TextComponent != nullptr) { auto Text_str = app::Text_get_text(reinterpret_cast(TextComponent), nullptr); auto ProficiencyStr = il2cppi_to_string(Text_str).erase(0, il2cppi_to_string(Text_str).find_first_of(" .")); @@ -127,7 +149,11 @@ namespace cheat::feature AutoCook& autoCook = AutoCook::GetInstance(); if (autoCook.f_Enabled || autoCook.f_FastProficiency) { - rsp->fields.qteQuality_ = autoCook.f_QualityField; + // To prevent possible crashes + if (!qualities.count(autoCook.f_QualityField.value())) + autoCook.f_QualityField.value() = "Normal"; + + rsp->fields.qteQuality_ = qualities.find(autoCook.f_QualityField.value())->second; rsp->fields.cookCount_ = autoCook.f_CountField; if (autoCook.f_FastProficiency) rsp->fields.cookCount_ = 1; @@ -137,7 +163,7 @@ namespace cheat::feature return CALL_ORIGIN(PlayerModule_OnPlayerCookRsp, __this, rsp, method); } - + static void CookingQtePageContext_UpdateProficiency(app::CookingQtePageContext* __this, MethodInfo* method) { AutoCook& autoCook = AutoCook::GetInstance(); if (autoCook.f_Enabled || autoCook.f_FastProficiency) diff --git a/cheat-library/src/user/cheat/world/AutoCook.h b/cheat-library/src/user/cheat/world/AutoCook.h index 1efaa6c..de11afb 100644 --- a/cheat-library/src/user/cheat/world/AutoCook.h +++ b/cheat-library/src/user/cheat/world/AutoCook.h @@ -12,10 +12,10 @@ namespace cheat::feature config::Field> f_FastProficiency; config::Field f_CountField; - config::Field f_QualityField; + config::Field f_QualityField; int CookFoodMaxNum; // Maximum quantity at a time - int CookCount; + int CookCount; static AutoCook& GetInstance(); @@ -26,7 +26,7 @@ namespace cheat::feature void DrawStatus() override; private: - + AutoCook(); }; } From 5847f17361bf31f5bd6710461e109ac61117c965 Mon Sep 17 00:00:00 2001 From: TerraFaster Date: Sun, 7 Aug 2022 17:19:19 +0300 Subject: [PATCH 29/30] Fixed typo in cooking quality list --- cheat-library/src/user/cheat/world/AutoCook.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheat-library/src/user/cheat/world/AutoCook.cpp b/cheat-library/src/user/cheat/world/AutoCook.cpp index 712de5d..653fd39 100644 --- a/cheat-library/src/user/cheat/world/AutoCook.cpp +++ b/cheat-library/src/user/cheat/world/AutoCook.cpp @@ -14,7 +14,7 @@ namespace cheat::feature app::Component_1* Profirency = nullptr; } - static std::map qualities{ {"Strange", 1}, {"Normal", 2}, {"Delicious", 3} }; + static std::map qualities{ {"Suspicious", 1}, {"Normal", 2}, {"Delicious", 3} }; static void PlayerModule_RequestPlayerCook(app::MoleMole_PlayerModule* __this, uint32_t recipeId, uint32_t avatarId, uint32_t qteQuality, uint32_t count, MethodInfo* method); static void PlayerModule_OnPlayerCookRsp(app::MoleMole_PlayerModule* __this, app::PlayerCookRsp* rsp, MethodInfo* method); From 3db5883a453f15277c060369d7eb939bc49b909f Mon Sep 17 00:00:00 2001 From: Joaquin <67109235+Taiga74164@users.noreply.github.com> Date: Sun, 7 Aug 2022 14:37:02 -0600 Subject: [PATCH 30/30] Forgot Call Origin oops --- cheat-library/src/user/cheat/player/RapidFire.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cheat-library/src/user/cheat/player/RapidFire.cpp b/cheat-library/src/user/cheat/player/RapidFire.cpp index 8adf898..f4bf3a2 100644 --- a/cheat-library/src/user/cheat/player/RapidFire.cpp +++ b/cheat-library/src/user/cheat/player/RapidFire.cpp @@ -10,8 +10,8 @@ namespace cheat::feature { static void LCBaseCombat_DoHitEntity_Hook(app::LCBaseCombat* __this, uint32_t targetID, app::AttackResult* attackResult, bool ignoreCheckCanBeHitInMP, MethodInfo* method); - static void VCAnimatorEvent_HandleProcessItem_Hook(app::MoleMole_VCAnimatorEvent* __this, - app::MoleMole_VCAnimatorEvent_MoleMole_VCAnimatorEvent_AnimatorEventPatternProcessItem* processItem, + static void VCAnimatorEvent_HandleProcessItem_Hook(app::MoleMole_VCAnimatorEvent* __this, + app::MoleMole_VCAnimatorEvent_MoleMole_VCAnimatorEvent_AnimatorEventPatternProcessItem* processItem, app::AnimatorStateInfo processStateInfo, app::MoleMole_VCAnimatorEvent_MoleMole_VCAnimatorEvent_TriggerMode__Enum mode, MethodInfo* method); RapidFire::RapidFire() : Feature(), @@ -84,7 +84,7 @@ namespace cheat::feature ImGui::Unindent(); ConfigWidget("Multi-animation", f_MultiAnimation, "Enables multi-animation attacks.\n" \ - "Do keep in mind that the character's audio will also be spammed."); + "Do keep in mind that the character's audio will also be spammed."); } bool RapidFire::NeedStatusDraw() const @@ -271,6 +271,8 @@ namespace cheat::feature } else app::MoleMole_LCBaseCombat_FireBeingHitEvent(__this, entity->runtimeID(), attackResult, method); } + + CALL_ORIGIN(LCBaseCombat_DoHitEntity_Hook, __this, targetID, attackResult, ignoreCheckCanBeHitInMP, method); } static void VCAnimatorEvent_HandleProcessItem_Hook(app::MoleMole_VCAnimatorEvent* __this,