1+ #include < jni.h>
2+ #include < string>
3+ #include < thread>
4+
5+ #include " logger.h"
6+ #include < BNM/Image.hpp>
7+ #include < BNM/Class.hpp>
8+ #include < BNM/Field.hpp>
9+ #include < BNM/Method.hpp>
10+ #include < BNM/Loading.hpp>
11+ #include " utils.h"
12+
13+
14+ void OnLoaded ();
15+
16+ extern " C" JNIEXPORT jint JNICALL
17+ JNI_OnLoad (JavaVM *vm, void *reserved) {
18+ JNIEnv *env;
19+ vm->GetEnv ((void **) &env, JNI_VERSION_1_6 );
20+ BNM::Loading::AddOnLoadedEvent (OnLoaded);
21+ BNM::Loading::TryLoadByJNI (env);
22+ return JNI_VERSION_1_6 ;
23+ }
24+
25+ // FeatureTypes: Toggle, Seekbar, Category
26+ // Examples:
27+ // Toggle:ToggleName:true
28+ // Seekbar:SeekbarName:1_20_10
29+ // Category:CategoryName
30+ extern " C" JNIEXPORT jobjectArray JNICALL
31+ Java_com_android_support_Menu_getFeatureList (JNIEnv *env, jobject thiz) {
32+ std::string featList[] = {
33+ " Seekbar:Attack:1_20" ,
34+ " Seekbar:Defence:1_20" ,
35+ };
36+ return toJobjectArray (env, featList, std::size (featList));
37+ }
38+
39+ int attack = 1 ;
40+ int defence = 1 ;
41+ extern " C" JNIEXPORT void JNICALL
42+ Java_com_android_support_Menu_valueChange (
43+ JNIEnv *env,
44+ jobject thiz,
45+ jint featIdx,
46+ jstring featName,
47+ jobject value
48+ ) {
49+ // featIdx: index in feature list
50+ switch (featIdx) {
51+ case 0 : {
52+ attack = toJint (env, value);
53+ break ;
54+ }
55+ case 1 : {
56+ defence = toJint (env, value);
57+ break ;
58+ }
59+ default :
60+ break ;
61+ }
62+ }
63+
64+ BNM ::Field<int > Camp{};
65+
66+ float (*old_GetSkillConditionAttack)(void *instance, void *inSource,
67+ void *inSkillProcessContext,
68+ void *inSourceSkillFunctionInfos);
69+
70+ float new_GetSkillConditionAttack (void *instance, void *inSource,
71+ void *inSkillProcessContext,
72+ void *inSourceSkillFunctionInfos) {
73+ auto ret = old_GetSkillConditionAttack (instance, inSource, inSkillProcessContext,
74+ inSourceSkillFunctionInfos);
75+ auto camp = Camp[inSource]();
76+ if (camp == 1 ) {
77+ ret = ret * attack;
78+ }
79+ return ret;
80+ }
81+
82+ float (*old_GetDefenceRate)(void *instance, void *inSource,
83+ void *inSkillProcessContext,
84+ void *inSourceSkillFunctionInfos);
85+
86+ float new_GetDefenceRate (void *instance, void *inSource,
87+ void *inSkillProcessContext,
88+ void *inSourceSkillFunctionInfos) {
89+ auto ret = old_GetDefenceRate (instance, inSource, inSkillProcessContext,
90+ inSourceSkillFunctionInfos);
91+ auto camp = Camp[inSource]();
92+ if (camp == 2 ) {
93+ ret = ret * defence;
94+ }
95+ return ret;
96+ }
97+
98+
99+ // Example Game: [Ark Re:Code](https://www.nutaku.net/games/ark-recode/)
100+ void OnLoaded () {
101+ LOGI (" OnLoaded" );
102+ auto AssemblyCSharp = BNM::Image (" Assembly-CSharp" );
103+ auto BattleRoleData = BNM::Class (" Game" , " BattleRoleData" , AssemblyCSharp);
104+ Camp = BattleRoleData.GetField (" Camp" );
105+ auto BattleCalculator = BNM::Class (" Game" , " BattleCalculator" , AssemblyCSharp);
106+ auto GetSkillConditionAttack = BattleCalculator.GetMethod (" GetSkillConditionAttack" );
107+ auto GetDefenceRate = BattleCalculator.GetMethod (" GetDefenceRate" );
108+ BNM::BasicHook (GetSkillConditionAttack, new_GetSkillConditionAttack,
109+ old_GetSkillConditionAttack);
110+ BNM::BasicHook (GetDefenceRate, new_GetDefenceRate, old_GetDefenceRate);
111+ }
0 commit comments