首页 » 技术分享 » 红色警戒2修改器原理百科(七)

红色警戒2修改器原理百科(七)

 
文章目录

(十五)科技全开——前方高能,BOOM

    其实这一小节,最晚应该在第四篇的十小节来讲述的,这样是按照一条线索来讲的,容易理解和把握笔者修改时的思路,以一点逐渐扩大。由于笔者的一些原因(一是牵涉到的数据结构比较多——3个,笔者当时没有完全理解;二是当时笔者发现一个关键位置——代码很复杂,并且红警全能王也进行了复杂的修改。因于此,笔者当时没深入就转而去搞其他的了),当笔者想写科技全开的时候,却发现讲不通,又不想只给出一个这么改就行的模糊回答,因为这是百科!结果就是,第十小节生硬地变成了打开小地图雷达——————

    有些东西终究是逃不掉的,Let’s face it.对第八节——添加任意建造项,是否还有印象?可以回过去再看看第三篇,传送门。其中,我提到是这样确定类型编号的:当你展开基地车的时候,会获得建造发电站的选项;建造完发电站,获得矿场和兵营的选项………如果读者亲自实验过,就会知道每次刷新建造项都会频繁调用那个函数添加建造选项。那么谁调用了这里,调用者将会判断决定添加什么选项。于是在函数头下断点,返回上一层,我们来到:

kj1

    分析这里能得到一些东西:循环次数——所有建筑物种类数目(A35CE8,即game.exe+635CE8),(建筑物)建造描述对象数组(A35CDC)。还有轻易就知道CALL<添加建造选项>前面的CALL就是得到某种建筑是不是应该被添加的的判断函数。

    并且004E3660被很多地方调用,然而这个函数有很多判断和很多出口,修改并不是很容易。一旦做了努力,修改成功,科技全开将是显而易见的。例如红警全能王就是修改了这里:

kj2

    这个函数被重新跳转到2931F96的一个自定义函数。注意:这个地址是临时申请的,每次都会变的。同样也是一个挺复杂的自定义函数,其中还调用了其他自定义函数。此处只是为了给出直接修改这个函数实现科技全开的思路并举例证明可行,并无意侵犯原作者权利。由于红警全能王版本及修改版繁多,历史久远(最初貌似是联网获取核心DLL的,后来被大神做出本地验证的单机版,最近我下载的是红警全能王谷子猫绿色珍藏版),我也搞不清谁是原作者,在未获得许可的情况下,还是不公开具体实现。有兴趣的可以自行下载分析,我也好偷懒大声笑

    由上面,已经给出科技全开的一种实现原理和思路了。本可以由此打发读者,弃坑的,但是我骗不了自己,还有自己同样在讲的优雅。好复杂的原函数,好复杂的自定义函数,能不能简单点……我很懒的,不想自己搞。于是找到了红色警戒2修改大师,附近的Case 7(建筑物)被简单的修改成如下(已由作者林毛口头授权公开):

    kj3

    其他的Case28,Case10,Case3也是类似的。+55C偏移是什么鬼?为什么要和-1比较?为什么要这么改?为了给读者有个解释,我终于下决心去看原函数了。最初我大体一看也是被这么长的函数吓坏了,还那么多判断,就果断绕道去看别人怎么实现的了……结果现在才发现开头不远就有:

kj4

    红警修改大师的作者看来是认真分析过的微笑,我站在他人的肩膀上~~之所以上面+55C偏移我确定是科技需求等级,是有原因的。记不清在哪里看到的,修改红警ini配置文件来启用隐藏兵种,修改的就是科技需求值-1,再通过对比其他兵种就基本确定了。破解、修改、入侵都一样,要思路开阔,方法灵活~

    最初,我以为这样就可以优雅的科技全开了。然而今天我想整理这篇文章时才发现我错了,直接调用添加建造选项的CALL能添加成功,我修改成这样为什么不能成功,红警修改大师为什么修改有效?原因,下节分析……这里先重新完善一个内存结构/游戏对象,提出与此相关的几个新对象。昨天不想写博文,为了拖延去看了看我当时由于找到另一个建造CD指针就没仔细分析的,结果解决了今天我遇到的问题眨眼——努力就有收获,不死方能最强王者(但是我对LOL心已经死了,反射弧太长)。

//对应游戏界面中的建筑选项
//游戏中有4个ConstrctionOptions数组,对应4个建造选项卡
//是struct,不是class。结构数组在内存上是连续的,而对象数组存储的是对象指针
//所以上一个数组元素地址加上元素大小得到下一个数组元素地址
struct ConstructionOption
{
    int                   nCount;         //+0,建造选项数目,仅在第一个建造选项中有意义
    int                   nID;            //+4,建造编号
    int                   nType;          //+8,建造类型,07标识建筑(基础建筑、防御建筑)
    int                   nUnkonwn;       //+C,未知标识数,基础建筑和防御建筑此值不同
    ConstructionProgress* pConProgress;   //+10,指针指向建造进度对象
    //...其他未知数据
    //size=0x30,这也是为什么第一篇中各CD基址相差0x30的原因 
    //很明确的告诉你,该结构没有指针指向ConstructionDescriptor
    //对应的图像、名称等等在ConstructionDescriptor中,因此我起的名字还是相当合理的
    //那游戏怎么将Option和Descriptor联系起来的?请继续阅读下一篇
}

//对应建造的过程
class ConstructionProgress
{
    //...
    int nCD;           //+24,当前单位建造CD
    int nTotalTime;    //+28,全局建造时间,联网对战中可能根据此同步建造
    int nNum;          //+4C,此次建造的剩余队列数量,单独修改此值会崩溃
                       //     猜想与总建造队列数值不一致引起
    int nNeededMoney;  //+5C,还需求多少金钱此单位建造完成
    //...
}

//对应游戏中的单位定义
class ConstructionDescriptor : public BaseA, ...
{
    //以下成员继承于基类BaseA,游戏内建筑对象、作战单位都继承了BaseA
    //包括我发现的游戏内触发器对象,标签对象等
    //BaseA或许叫做CommonObj更合适,游戏内大部分对象均继承此类
    //上面的ConstructionProgress不继承BaseA
    int     nGobalID;                //+10,全局对象ID
    Char    szName[16];              //+3D,单位定义名称,修改过ini文件的应该熟悉
    //...
    int     nCost;                   //+550,造价
    int     nSold;                   //+554,出售价(复制中心回收)
    int     nRequiredTechnology;     //+55C,需求科技等级
    //...
}

    我现在在想这一篇的长度是不是够了呢?停下吧,去修改之前的错误,我发现第一篇描述有错误(那些CD基址不是对应建筑或者兵种的,是相对所在格子的),也归功于今天的遇到的问题带来的一些重新思考。其实笔者,一直在修修改改之前的文章……哭泣的脸从来没写过这么大型的百科,之前也没写过博文。

==========

。。。错误改完了,在最后补充一下第一篇承诺的详细解释:

    以第一格CD为例。第一格CD地址:[game.exe+433A80]+24,当时在第一篇被错误的称作盟军电厂CD地址。第一篇中为了不一上来引入复杂的数据结构,简单的让读者认为,game.exe+433A80存放的指针指向一个SomethingAboutConstuction结构。现在相关类/结构已经在上述完整的描述了,是时候纠正了。

    game.exe+433A80存放的指针指向的是ConstructionProgress对象,game.exe+433A80这个地址是ConstructionOption结构的成员变量pConProgress,减去偏移0x10=game.exe+433A70,即第一格的ConstructionOption对象的起始地址。上面提到nCount仅在第一个建造选项中有意义,即数组ConstructionOptions[0].nCount记录了游戏中该建造选项卡下有几个建造选项,ConstructionOptions[1,2,3,…].nCount=0。

To be continued…

署名许可转载请注明来源,http://www.cnblogs.com/viewll/p/4775482.html

转载自原文链接, 如需删除请联系管理员。

原文链接:红色警戒2修改器原理百科(七),转载请注明来源!

0