标题:
孔明传恢复性策略、道具,及每回合初始状态自动恢复的分析
[打印本页]
作者:
阿尔法孝直
时间:
2010-8-5 05:47
标题:
孔明传恢复性策略、道具,及每回合初始状态自动恢复的分析
int __thiscall sub_4089F2(int this, char a2, char a3, char a4)
//函数入口在0x4089F2
{
int result; // eax@1
char v5; // al@7
int v6; // eax@28
int v7; // [sp+14h] [bp-1Ch]@1
int v8; // [sp+20h] [bp-10h]@1
int v9; // [sp+24h] [bp-Ch]@1
int v10; // [sp+2Ch] [bp-4h]@5
char v11; // [sp+28h] [bp-8h]@7
unsigned int v12; // [sp+10h] [bp-20h]@11
unsigned int v13; // [sp+Ch] [bp-24h]@19
unsigned __int8 v14; // [sp+1Ch] [bp-14h]@29
int v15; // [sp+18h] [bp-18h]@33
v7 = this;
v8 = (int)((char *)&dword_4556E8 + 54 * *(_DWORD *)this);
//接受方人物代码
v9 = 0;
result = sub_409830();
if ( (unsigned __int8)result == 2 )
{
result = sub_409790(v8);
if ( result != *(_DWORD *)(v7 + 15) )
{
if ( (unsigned __int8)a3 != 255 )
v10 = (int)((char *)&dword_4556E8 + 54 * sub_409130((int)((char *)&dword_46C098 + 23 * (unsigned __int8)a3)));
//使用方人物代码
if ( (unsigned __int8)a4 == 3 )
{
v13 = (unsigned __int8)a2;
if ( v13 <= 3 )
{
switch ( v13 )
{
case 0u:
v9 = (unsigned __int8)sub_409110(v10) / 10 + 100;
//恢复豆的效果为使用者智力/10+100
break;
case 1u:
v9 = (unsigned __int8)sub_409110(v10) / 5 + 300;
//恢复麦的效果为使用者智力/5+300
break;
case 2u:
v9 = 2 * (unsigned __int8)sub_409110(v10) / 5 + 500;
//恢复米的效果为2*使用者智力/5+500
break;
case 3u:
v9 = sub_409790(v8);
//至于恢复肉,效果直接取被恢复者的最大耐久力
break;
}
}
}
else
{
sub_409130((int)((char *)&dword_46C098 + 23 * (unsigned __int8)a3));
v5 = sub_40C2BC();
v11 = v5;
if ( (unsigned __int8)v5 == 6 || (unsigned __int8)v11 == 10 || (unsigned __int8)v11 == 11 )
v9 = (unsigned __int8)sub_40CA5E(0, 0);
v12 = (unsigned __int8)a2;
if ( v12 <= 3 )
{
switch ( v12 )
{
case 0u:
v9 = ((signed int)(unsigned __int8)sub_409110(v10) >> 1) + 20;
//小补给的效果为使用者智力/2+20
break;
case 1u:
v9 = 4 * (unsigned __int8)sub_409110(v10) / 5 + 40;
//中补给的效果为4*使用者智力/5+40
break;
case 2u:
v9 = 11 * (unsigned __int8)sub_409110(v10) / 10 + 60;
//大补给的效果为11*使用者智力/10+60
break;
case 3u:
v9 = sub_409790(v8);
//至于全补给,效果直接取被恢复者的最大耐久力
break;
}
}
}
if ( sub_409790(v8) < (unsigned int)(v9 + *(_DWORD *)(v7 + 15)) )
//回复后不能超过被恢复者最大耐久力
v9 = sub_409790(v8) - *(_DWORD *)(v7 + 15);
sub_43EA40(3 * *(_BYTE *)(v7 + 5), 3 * *(_BYTE *)(v7 + 6), 6, 0);
v6 = sub_409180();
if ( BYTE1(v6) & 1 )
{
sub_439DC1(&v15, *(_BYTE *)(v7 + 4));
if ( sub_409220((int)((char *)&dword_46C098 + 23 * *(_BYTE *)(v7 + 4))) )
LOBYTE(v15) = 14;
else
LOBYTE(v15) = 42;
sub_4091B0(2 * (unsigned __int8)byte_46FCBD + 6);
sub_439E26(v15, *(_BYTE *)(v7 + 4));
sub_4373C8();
sub_4375BB(1);
sub_4091B0(2 * (unsigned __int8)byte_46FCBD + 6);
sub_43A16E(v15, *(_BYTE *)(v7 + 4), v9, -128);
sub_4373C8();
sub_4375BB(1);
sub_43AB2D(6, *(int *)((char *)&v15 + 1), 33, 9);
}
else
{
v14 = 0;
while ( (signed int)v14 < 3 )
{
sub_439B63(*(_BYTE *)(v7 + 4), v9, 13);
++v14;
}
}
*(_DWORD *)(v7 + 15) += v9;
result = sub_4053B8((unsigned __int8)a3, *(_BYTE *)(v7 + 4), 1);
}
}
return result;
}
[
本帖最后由 阿尔法孝直 于 2010-8-8 00:13 编辑
]
作者:
lewulezo
时间:
2010-8-6 08:13
我比较关心的是传入的参数a2是什么?
对于伤害类技能,范围和威力绑在同一个值上,对于补给类技能,也是这样吗?
作者:
阿尔法孝直
时间:
2010-8-6 13:27
往回倒,调用上面这个函数的前一个函数为:
char __cdecl sub_406847(int a1, int a2, int a3)
{
int v3; // eax@11
int v4; // [sp+14h] [bp-10h]@1
char v5; // [sp+20h] [bp-4h]@1
unsigned __int8 v6; // [sp+1Ch] [bp-8h]@2
bool v7; // [sp+10h] [bp-14h]@6
int v8; // [sp+18h] [bp-Ch]@8
int v9; // [sp+Ch] [bp-18h]@13
LOBYTE(v4) = -1;
v5 = byte_44D2B0[a1];
v6 = (unsigned int)a1 > 0x1C;
v7 = (unsigned __int8)sub_4093D0() == 7 || byte_4535A4 & 4;
LOBYTE(v8) = a1 - ((-(v6 < 1u) & 0xFFFFFFFC) + 29);
if ( v6 )
{
v3 = sub_408DF5((int)((char *)&dword_46C098 + 23 * a2), v8, a3);
dword_44DA98 = v3;
}
else
{
if ( v7 )
sub_438F35(0, (char)"使%s的耐久力恢复。");
LOBYTE(v3) = sub_43CEB5((int)dword_46FB00, a2, (unsigned __int8)v5 | 0x80, 1);
LOBYTE(v4) = v3;
if ( (unsigned __int8)v3 != 255 )
{
v3 = sub_4069E4(v4, 0);
if ( v3 )
{
LOWORD(v9) = *(_WORD *)sub_409200();
sub_43B1E8(v9, SBYTE1(v9));
LOBYTE(v3) =
sub_4089F2((int)((char *)&dword_46C098 + 23 * (unsigned __int8)v4), v8, a2, a3)
;
dword_44DA98 = 1;
}
}
}
return v3;
}
sub_4089F2的参数a2就是这里的v8,再看:
LOBYTE(v8) = a1 - ((-(v6 < 1u) & 0xFFFFFFFC) + 29);
(v6<1u)的值不是0就是1:
当(v6<1u)==0时(使用群体恢复道具),LOBYTE(v8) = a1 -29; //29是援队书的道具代码
当(v6<1u)==1时(使用单体恢复道具),LOBYTE(v8) = a1 -25; //25是恢复豆的道具代码
a1显然是所使用的道具代码。
25~28分别是豆、麦、米、肉
29~32分别是援队书、援部书、援军书、援国书
最终v8的取值可以是0~3
后面不解释了。
[
本帖最后由 阿尔法孝直 于 2010-8-6 13:32 编辑
]
作者:
阿尔法孝直
时间:
2010-8-7 02:21
每回合初始时状态自动恢复与否,在0x42AF30,判断在0x42ADE7
void __fastcall sub_42AF30(int a1)
{
char v1; // al@4
char v2; // al@10
int v3; // [sp+Ch] [bp-4h]@1
v3 = a1;
if ( (unsigned __int8)sub_409830(a1) == 2 )
{
if ( sub_42DF80() & 0x40 )
{
v1 = sub_4096D0(v3);
sub_4096A0(v1 & 0xBF);
}
else
{
if ( (signed int)*(_BYTE *)(v3 + 20) <= 2 )
{
if ( (signed int)*(_BYTE *)(v3 + 20) < 2 )
// 攻击力上升
sub_42ADE7(v3, 0, *(_BYTE *)(v3 + 20) + 1, *(_BYTE *)(v3 + 20));
}
else
// 攻击力下降
{
sub_42ADE7(v3, 0, *(_BYTE *)(v3 + 20) - 1, *(_BYTE *)(v3 + 20));
}
}
if ( sub_42DFA0() & 0x40 )
{
v2 = sub_409730(v3);
sub_409700(v2 & 0xBF);
}
else
{
if ( (signed int)*(_BYTE *)(v3 + 21) <= 2 )
{
if ( (signed int)*(_BYTE *)(v3 + 21) < 2 )
// 防御力上升
sub_42ADE7(v3, 1, *(_BYTE *)(v3 + 21) + 1, *(_BYTE *)(v3 + 21));
}
else
// 防御力下降
{
sub_42ADE7(v3, 1, *(_BYTE *)(v3 + 21) - 1, *(_BYTE *)(v3 + 21));
}
}
if ( sub_42DFC0(v3) & 0x40 )
{
sub_4097D0(v3, 64);
}
else
{
if ( sub_409150(v3, 1) )
// 移动力下降
sub_42ADE7(v3, 3, 129, 2);
if ( sub_409150(v3, 2) )
// 攻击速度下降
sub_42ADE7(v3, 3, 130, 2);
if ( sub_409150(v3, 4) )
// 封策
sub_42ADE7(v3, 3, 132, 2);
if ( sub_409150(v3, 8) )
// 减轻策略损伤
sub_42ADE7(v3, 3, 136, 2);
if ( sub_409150(v3, 16) )
// 混乱
{
sub_42ADE7(v3, 3, 144, 2);
sub_42BEBF(v3);
}
if ( sub_409150(v3, 32) )
// 耐久力每回合减少
sub_42ADE7(v3, 3, 160, 2);
}
}
}
----------------------------------------------
void __thiscall sub_42ADE7(int this, int a2, int a3, char a4)
{
int v4; // ebx@4
int v5; // eax@4
unsigned int v6; // ebx@4
int v7; // ebx@9
int v8; // eax@9
unsigned int v9; // ebx@9
int v10; // [sp+10h] [bp-Ch]@1
int v11; // [sp+18h] [bp-4h]@1
int v12; // [sp+14h] [bp-8h]@1
signed int v13; // [sp+Ch] [bp-10h]@4
v10 = this;
v11 = 0;
v12 = (int)((char *)&dword_4556E8 + 54 * *(_DWORD *)this);
if ( ((unsigned __int8)a2 != 3 || a3 & 8) && (signed int)(unsigned __int8)a4 <= 2 )
// 从良好状态复原(攻防上升、减轻策略损伤)
{
if ( a3 & 8 || (signed int)(unsigned __int8)a4 < 2 )
{
v7 = (unsigned __int8)sub_409110(v12);
// 取智力
v8 = sub_42A227(v10);
// 取防御力
v9 = sub_447328((v7 + v8) / 0x64u + 20);
// 随机数
if ( v9 <= (unsigned __int8)
sub_42AC4E(*(_BYTE *)(v10 + 4), 0)
)
sub_428A0B((int)dword_46C088, *(_DWORD *)v10, a2, a3, 1);
}
}
else
// 从不良状态复原
{
v13 = 20;
v4 = (unsigned __int8)sub_409110(v12);
// 取智力
v5 = sub_42A227(v10);
// 取防御力
v6 = sub_447328(v13 - (v4 + v5) / 0x64u);
// 随机数
if ( v6 <= (unsigned __int8)
sub_42AC4E(*(_BYTE *)(v10 + 4), 1)
)
sub_428A0B((int)dword_46C088, *(_DWORD *)v10, a2, a3, 1);
}
}
------------------------------------------------
char __cdecl sub_42AC4E(char a1, char a2)
{
int v3; // [sp+10h] [bp-Ch]@1
char v4; // [sp+14h] [bp-8h]@1
unsigned int v5; // [sp+Ch] [bp-10h]@1
char v6; // [sp+18h] [bp-4h]@3
v3 = sub_409130((int)((char *)&dword_46C098 + 23 * (unsigned __int8)a1));
v4 = sub_4092A0((int)((char *)&dword_46C098 + 23 * (unsigned __int8)a1));// 取兵种
v5 = (unsigned __int8)
sub_40C2BC(v3);
// 和兵种相关的一个值
if ( v5 > 0xB ) // 兵种代码>=30
{
LABEL_18:
if ( (unsigned __int8)v4 != 32 && (unsigned __int8)v4 != 33 && (unsigned __int8)v4 != 38 )// 南蛮兵、南蛮骑兵等少数民族持有兵种
{
if ( a2 ) // 良好状态复原
v6 = 1;
else // 不良状态复原
v6 = 4;
}
else // 皇帝、都督、幻术师
{
if ( a2 )
v6 = 4;
else
v6 = 1;
}
}
else // 0<=v5<=11
{
switch ( *((_BYTE *)
byte_42ADCE
+ v5) ) //
0x0042ADCE: 00 00 01 02 02 03 04 05 05 07 06 06 8A 45
{
case 0: // 步兵系、弓兵系
case 2: // 战车系、炮车系
if ( a2 )
v6 = 3;
else
v6 = 2;
break;
case 1: // 骑兵系
case 3: // 弓骑兵系
case 5: // 贼兵系、武术家系
if ( a2 )
v6 = 2;
else
v6 = 3;
break;
case 4: // 军师系
if ( a2 )
v6 = 10;
else
v6 = 1;
break;
case 6: // 运粮队、物资队、军乐队
if ( a2 )
v6 = 4;
else
v6 = 1;
break;
case 7: // 虎兵系
goto LABEL_18;
}
}
return v6;
}
----------------------------------------------
char __cdecl sub_40C2BC(int a1)
{
__int16 v1; // ax@2
char v2; // al@1
char v3; // [sp+10h] [bp-4h]@1
signed int v4; // [sp+Ch] [bp-8h]@5
v2 = sub_4092D0((int)((char *)&dword_4556E8 + 54 * a1)); // 取兵种
v3 = v2;
if ( (signed int)(unsigned __int8)v2 > 20 ) // 20大军师 21山贼
{
if ( (signed int)(unsigned __int8)v3 > 28 ) // 28物资队 29军乐队
{
v4 = (unsigned __int8)v3;
if ( v4 == 29 ) // 29军乐队
{
LOBYTE(v1) = 11;
}
else
{
if ( v4 >= 30 && v4 <= 31 ) // 30南蛮兵 31南蛮骑兵
LOBYTE(v1) = 12;
else // >32
LOBYTE(v1) = 14;
}
}
else // 兵种代码21~28
{
LOBYTE(v1) = (unsigned __int8)(((unsigned __int8)v3 - 21) / 2) + 7;// 取值可能有7,8,9,10
}
}
else // 兵种代码0~20
{
v1 = (unsigned __int8)v3 / 3; // 取值可能有0,1,2,3,4,5,6
}
return v1;
}
[
本帖最后由 阿尔法孝直 于 2010-8-8 00:44 编辑
]
作者:
阿尔法孝直
时间:
2010-8-7 23:59
从楼上的代码可以看出:
1、如果是好的状态(攻防上升、策略损伤减轻)
恢复某一个状态(去掉策略损伤减轻,去掉一阶攻防上升,二阶攻防上升降为一阶)要求
随机数%[(智力+防御力)/100+20]<=A
其中A的取值与兵种类型有关:
军师系、运粮队、物资队、军乐队、皇帝、都督、幻术师:1
步兵系、弓兵系、战车系、炮车系:2
骑兵系、弓骑兵系、贼兵系、武术家系:3
少数民族兵种、动物兵团:4
2、如果是坏的状态(攻防下降、混乱、耐久力每回合减少等)
恢复某一个状态(去掉不良状态,去掉一阶攻防下降,二阶攻防下降降为一阶)要求
随机数%[20-(智力+防御力)/100]<=B
其中B的取值与兵种类型有关:
军师系:10
运粮队、物资队、军乐队、皇帝、都督、幻术师:4
步兵系、弓兵系、战车系、炮车系:3
骑兵系、弓骑兵系、贼兵系、武术家系:2
少数民族兵种、动物兵团:1
[
本帖最后由 阿尔法孝直 于 2010-8-8 00:43 编辑
]
作者:
阿尔法孝直
时间:
2010-8-8 01:06
天气变化的算法:
unsigned __int8 __fastcall sub_443C7E(int a1)
{
unsigned __int8 result; // al@6
unsigned __int8 v2; // al@1
int v3; // [sp+Ch] [bp-Ch]@1
unsigned __int8 v4; // [sp+14h] [bp-4h]@1
unsigned __int8 v5; // [sp+10h] [bp-8h]@1
v3 = a1;
v2 = sub_447328(6); //随机数%6
v4 = v2;
v5 = *(_BYTE *)(v3 + 4); //天气代码地址
if ( v5 <= (signed int)v2 )
{
if ( v5 < (signed int)v4 )
++v5;
}
else
{
--v5;
}
if ( v5 )
{
if ( v5 == 5 )
{
result = v3;
*(_BYTE *)(v3 + 4) = 0;
}
else
{
result = v5;
*(_BYTE *)(v3 + 4) = v5;
}
}
else
{
result = v3;
*(_BYTE *)(v3 + 4) = 5;
}
return result;
}
---------------------------------------------
释义:
A=0~5的随机数
B=上一回合天气
如果A>B,则B加1;如果A<B,则B减1。
如果B=5,则本回合天气=0;如果B=0,则本回合天气=5。
天气代码:00、01、02晴,03云,04、05雨
注:孔明传的天气算法与英杰传完全一致。
[
本帖最后由 阿尔法孝直 于 2010-8-8 01:39 编辑
]
作者:
阿尔法孝直
时间:
2010-8-8 01:10
每回合开始,在恢复地形部队恢复耐久力的算法。
int __cdecl sub_42AB99(unsigned __int8 a1)
{
int result; // eax@2
unsigned int v2; // [sp+Ch] [bp-4h]@1
v2 = a1;
v2 -= 7;
if ( v2 > 6 )
{
LABEL_7:
result = 0;
}
else
{
switch ( v2 )
{
case 0u: //村庄
result = sub_447328(5) + 10; //恢复耐久力为最大耐久力的百分之(随机数%5+10),下面类似
break;
case 1u: //鹿砦
result = sub_447328(5) + 15;
break;
case 2u: //兵营
result = sub_447328(5) + 5;
break;
case 3u:
case 4u:
goto LABEL_7;
case 5u: //城池
result = sub_447328(5) + 25;
break;
case 6u: //关隘
result = sub_447328(5) + 20;
break;
}
}
return result;
}
注意:
1、最后的结果值不是恢复耐久力的值,而是恢复最大耐久力的百分比!!
2、如果同时处在恢复地形且持有自动回复的道具,则两种回复可以叠加;但是如果持有多个自动回复道具,则只取威力最大的一个。
具体是:剩余耐久力=剩余耐久力+地形恢复效果(也就是上面的result)*最大耐久力/100+道具恢复效果*最大耐久力/100
自动回复道具效果值:
三略10,六韬15,孟德新书20,孙子兵法25,不加随机数
[
本帖最后由 阿尔法孝直 于 2010-8-9 00:10 编辑
]
作者:
lewulezo
时间:
2010-8-8 14:00
C语言的代码看起来果然直白不少。
我还想知道的一些准确的内存地址位置(exe位置)
比如说,基本回复量,村庄10% 鹿砦15% 兵营5%等等,这个10,15,5的准确地址在哪,这样我可以方便修改。
作者:
阿尔法孝直
时间:
2010-8-11 13:57
标题:
回复 #8 lewulezo 的帖子
0042AB99 $ 55 PUSH EBP
0042AB9A . 8BEC MOV EBP,ESP
0042AB9C . 83EC 04 SUB ESP,4
0042AB9F . 53 PUSH EBX
0042ABA0 . 56 PUSH ESI
0042ABA1 . 57 PUSH EDI
0042ABA2 . 33C0 XOR EAX,EAX
0042ABA4 . 8A45 08 MOV AL,BYTE PTR SS:[EBP+8]
0042ABA7 . 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
0042ABAA . E9 66000000 JMP EKD2Win.0042AC15
0042ABAF > 6A 05 PUSH 5 ; /Arg1 = 00000005
0042ABB1 . E8 72C70100 CALL EKD2Win.00447328 ; \EKD2Win.00447328
0042ABB6 . 83C4 04 ADD ESP,4
0042ABB9 . 83C0
0A
ADD EAX,
0A
;村庄恢复耐久力为最大耐久力的百分之(随机数%5+10),下面类似
0042ABBC . E9 88000000 JMP EKD2Win.0042AC49
0042ABC1 > 6A 05 PUSH 5 ; /Arg1 = 00000005
0042ABC3 . E8 60C70100 CALL EKD2Win.00447328 ; \EKD2Win.00447328
0042ABC8 . 83C4 04 ADD ESP,4
0042ABCB . 83C0
0F
ADD EAX,
0F
0042ABCE . E9 76000000 JMP EKD2Win.0042AC49
0042ABD3 > 6A 05 PUSH 5 ; /Arg1 = 00000005
0042ABD5 . E8 4EC70100 CALL EKD2Win.00447328 ; \EKD2Win.00447328
0042ABDA . 83C4 04 ADD ESP,4
0042ABDD . 83C0
05
ADD EAX,
5
0042ABE0 . E9 64000000 JMP EKD2Win.0042AC49
0042ABE5 > 6A 05 PUSH 5 ; /Arg1 = 00000005
0042ABE7 . E8 3CC70100 CALL EKD2Win.00447328 ; \EKD2Win.00447328
0042ABEC . 83C4 04 ADD ESP,4
0042ABEF . 83C0
14
ADD EAX,
14
0042ABF2 . E9 52000000 JMP EKD2Win.0042AC49
0042ABF7 > 6A 05 PUSH 5 ; /Arg1 = 00000005
0042ABF9 . E8 2AC70100 CALL EKD2Win.00447328 ; \EKD2Win.00447328
0042ABFE . 83C4 04 ADD ESP,4
0042AC01 . 83C0
19
ADD EAX,
19
0042AC04 . E9 40000000 JMP EKD2Win.0042AC49
0042AC09 > 33C0 XOR EAX,EAX
0042AC0B . E9 39000000 JMP EKD2Win.0042AC49
0042AC10 . E9 34000000 JMP EKD2Win.0042AC49
0042AC15 > 836D FC 07 SUB DWORD PTR SS:[EBP-4],7
0042AC19 . 837D FC 06 CMP DWORD PTR SS:[EBP-4],6
0042AC1D .^ 0F87 E6FFFFFF JA EKD2Win.0042AC09
0042AC23 . 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
0042AC26 . FF2485 2DAC42>JMP DWORD PTR DS:[EAX*4+42AC2D]
0042AC2D . AFAB4200 DD EKD2Win.0042ABAF ; 分支表 被用于 0042AC26
0042AC31 . C1AB4200 DD EKD2Win.0042ABC1
0042AC35 . D3AB4200 DD EKD2Win.0042ABD3
0042AC39 . 09AC4200 DD EKD2Win.0042AC09
0042AC3D . 09AC4200 DD EKD2Win.0042AC09
0042AC41 . F7AB4200 DD EKD2Win.0042ABF7
0042AC45 . E5AB4200 DD EKD2Win.0042ABE5
0042AC49 > 5F POP EDI
0042AC4A . 5E POP ESI
0042AC4B . 5B POP EBX
0042AC4C . C9 LEAVE
0042AC4D . C3 RETN
欢迎光临 轩辕春秋文化论坛 (http://xycq.org.cn/forum/)
Powered by Discuz! 5.0.0