石器时代论坛

 找回密码
 立即注册

QQ登录

查看: 10673|回复: 12
打印 上一主题 下一主题

从石器源码解析宠物转生篇之要相信科学和随机数

[复制链接]

6

主题

43

帖子

179

石币

石器高手

Rank: 3Rank: 3

积分
227

攻略达人

跳转到指定楼层
楼主
发表于 2021-4-10 00:58:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
_npc_transmigration.rar (11.75 KB, 下载次数: 6)

第一个函数:

int PETTRANS_PetTransManStatus( int toindex, int petindex1, int petindex2)

{

       int petrank=0,i;

       int total1,total2,total,petLV,ans;

       int petID,enemynum,ret=-1;

       int work[4]=;

       int base[4]=;

#define RAND(x,y)   ((x-1)+1+ (int)( (double)(y-(x-1))*rand()/(RAND_MAX+1.0)) )

       total1 = PETTRANS_getPetBase( petindex1, work, &petrank);

       total2 = PETTRANS_getPetBase( petindex2, base, &petrank);

       petLV        = CHAR_getInt( petindex2, CHAR_LV);

//======================第一部分===================================

#ifdef _PET_2TRANS

       ans = NPC_PetTransManGetAns( total1, total2, petLV, petrank, CHAR_getInt( petindex2, CHAR_TRANSMIGRATION ) );

#else

       ans = NPC_PetTransManGetAns( total1, total2, petLV, petrank );

#endif

//=========================================================

       total = total1 + (total2*4);

       total2 = 0;

       for( i=0; i

               work = work*4;

               total2 += work;

       }

       total = total1 + total2;

       for( i=0; i

               base = (ans * (base+work)) /total;

       }

       enemynum = ENEMY_getEnemyNum();

       petID = CHAR_getInt( petindex2, CHAR_PETID);

       for( i=0; i

               if( ENEMY_getInt(i, ENEMY_TEMPNO) == petID )

                       break;

       }

       if( i == enemynum )

               return -1;

       ret = GetNewPet( toindex, petindex2, i, base);        if( ret < 0 )

               return -1;

       return ret;

}

这个函数大致上应该是宠物转生的入口函数,从第一部分红色代码就可以判断,这段代码判断是一转还是二转,我们现在只研究一转的情况.

ans = NPC_PetTransManGetAns( total1, total2, petLV, petrank );

从这个ans不用说,是一个影响转身的系数,从它后面的用法可以看得出,而toital1和total2代表的大致是MM和转宠的一个什么合值,后面有分析.petLv不用说代表宠的等级,petRank代表的大致是宠物的成长方面的东西,rank代表的是成长方面的数值,这个后面有分析.

接下来我们再看后面这段:

total = total1 + (total2*4);

       total2 = 0;

       for( i=0; i

               work = work*4;

               total2 += work;

       }

       total = total1 + total2;

       for( i=0; i

               base = (ans * (base+work)) /total;

       }

这里有两个关键变量,一个是total1,一个是total2,从这段代码推测:

total1 = PETTRANS_getPetBase( petindex1, work, &petrank);

total2 = PETTRANS_getPetBase( petindex2, base, &petrank);

total1和total2分别传入了petindex1,和petindex2.petindex不用说,都代表一个宠物的指针,也就是可以这个宠物的代号,那么至少可以说明,这两个total,一个代表人宠,一个代表转生宠.

再看这句:

for( i=0; i

               work = work*4;

               total2 += work;

       }

       total = total1 + total2;

for( i=0; i

               base = (ans * (base+work)) /total;

       }

base是一个int数组,经我研究,这个数组是4位长,从0-3的下标,分别代表:血,攻,防,敏.看这段代码就知道:

//最终启动的转身函数

ret = GetNewPet( toindex, petindex2, i, base);

//=============

(这个base最终被当作一个参数传给了GetNewPet,GetNewPet不用说,就代表了获取新的宠物的函数)再看GetNewPet的定义中

int GetNewPet( int toindex , int petindex, int array, int *work)

{

    ......前面的先省略

    work[0] += ( RAND(0,4) - 2 );

    work[1] += ( RAND(0,4) - 2 );

    work[2] += ( RAND(0,4) - 2 );

    work[3] += ( RAND(0,4) - 2 );

///而参数work,刚好就是前面传入的base数组

    CHAR_setInt( petindex, CHAR_VITAL, ( PARAM_CAL(E_T_BASEVITAL) * work[0] ));

   CHAR_setInt( petindex, CHAR_STR , ( PARAM_CAL(E_T_BASESTR) * work[1] ));

   CHAR_setInt( petindex, CHAR_TOUGH , ( PARAM_CAL(E_T_BASETGH) * work[2] ));

   CHAR_setInt( petindex, CHAR_DEX , ( PARAM_CAL(E_T_BASEDEX) * work[3] ));

  //看到没,char_serInt,字面上的意思,就是character_setInital,也就是特征初始化,work[0]对应BASEVITAL,work[1]对应BASESTR,work[2]对应BASETGH,work[3]对应BASEDEX,很显然,BASEVITAL就是基本血量,BASESTR就是基本攻击力,BASEDEX就是基本敏捷,BASETGH虽然我不太理解TGH的意思,但不用说就是指防御了.

}

所以,base = (ans * (base+work)) /total;就是关键,按这个公式,ans越大越好,而total却并不一定越小越好,为什么,再看ans的获取代码:

int NPC_PetTransManGetAns( int total1, int total2, int LV, int rank )

#endif

{

       int ans=0 , TransLV = 100;

       float total = 0.00;

       int Fx=1;

       if( LV > 130 ) LV = 130;

       total = ( (float)total1/100 ); // 嚎立程蔼 total1=200

       total = total*total*total*total*total;

       if( total < 1 ) total = 0;

       else total= total*1.3; // ┮?total程?=41.6 程?=0

       Fx = (int)((5-rank)*1.2)+5; // rank=0~6 ┮? Fx程?=11(rank=0)程?=4(rank=6)

       ans = (int)total + total2 + ((LV-TransLV)/Fx); //42+150+30/11=194

#ifdef _PET_2TRANS

       if( tran == 0 ){

               if( ans > 150 )     

                       ans = 150;

       }

       else{

               if( ans > 200 )     

                       ans = 200;

       }

#else

       if( ans > 150 )        {

               ans = 150;

       }

#endif

       print("\n ans = %d", ans);

       return ans;

}

没错,等级大于130,按130计算,同时:

total = ( (float)total1/100 ); // 嚎立程蔼 total1=200

       total = total*total*total*total*total;

       if( total < 1 ) total = 0;

       else total= total*1.3;

这个total=total1/100,然后再=自己的4次方,还会被判断是否<1,由此可见,如果total1>100,则total=total*1.3,否则total=0,从这里可以判断,total1是关于人宠的,因为只有人宠的基数才会有一个如此明确的标准来决定转生的成功与失败.(结合73级喂满灵石的MM转宠无差别,这个total绝对不是指4围的合,而应该是4围成长的一个系数的合).

ans = (int)total + total2 + ((LV-TransLV)/Fx);

所以base = (ans * (base+work)) /total这个公式的total不是那么单纯,因为它同时影响分子和分母,这个我们先不研究了,太多假设.

而可以确定的,就是work[]和base[]越大越好,base数组已经清楚了,work数组也是4位,而且是影响total2的,从下面的代码可以看出:

   total2 = 0;

   for( i=0; i

  {

       work = work*4;

       total2 += work;

  }

所以大胆推测,work代表的也是关于转宠4围方面的东西,结合起来可以确定基础宠的4围方面的条件,越高越好,

最后我们回过头来来看下GetNewPet( toindex, petindex2, i, base)这个函数的整体.

int GetNewPet( int toindex , int petindex, int array, int *work)

{

   int     *p;

   int                tp[E_T_DATAINTNUM];

   int                tarray, i;

       int                level, workrank, petrank=0;

       int                LevelUpPoint;

       struct         {

           int                num;

           float        rank;

   }ranktbl[] = {

           { 130, 2.5},

           { 100, 2.0},

           { 95, 1.5},

           { 85, 1.0},

           { 80, 0.5},

           { 0, 0.0},

   };

这里有个ranktbl的数组,这个数组一看就知道是什么意思,它表示每个等级段转身,所获得的rank系数,rank也就是评级系数,或者是能力系数,证明了前面:

total1 = PETTRANS_getPetBase( petindex1, work, &petrank);

total2 = PETTRANS_getPetBase( petindex2, base, &petrank);

中,petRank参数的意思,就是0转时的成长系数,充分证明了0转宠的成长率,和MM的成长率,对转身的影响,虽然大家都知道这点了.

同时再次证明了130+的宠物转身可以得到最高的2.5.接下来:     

level = 1;

#define RAND(x,y)   ((x-1)+1+ (int)( (double)(y-(x-1))*rand()/(RAND_MAX+1.0)) )

#define                E_PAR( a)                (*(p + (a)))

#define                ET_PAR( a)                (*(tp + (a)))

#define                PARAM_CAL( l)         ( ( level -1) * ET_PAR( E_T_LVUPPOINT) + ET_PAR( E_T_INITNUM) )

       work[0] += ( RAND(0,4) - 2 );

       work[1] += ( RAND(0,4) - 2 );

       work[2] += ( RAND(0,4) - 2 );

       work[3] += ( RAND(0,4) - 2 );

这段代码的前半部分注释掉了,搞不懂什么意思,后半部分,说的是一个人品问题,前面我们说了,work数组,也就是base数组,代表了宠物的4围,而这里,就是把初始的4围,随机增加(0-4的随机数)-2,对,有可能会加负数,不然怎么说是人品问题,这里也说明了大家平时所谓的暴成长问题,其实真的不是因为太高而暴掉了,而是人品太差了,呵呵.再接着看:

LevelUpPoint = ( work[0]

               + (work[1]

               + (work[2]

               + (work[3]

CHAR_setInt( petindex, CHAR_ALLOCPOINT, LevelUpPoint);

levelUpPoint这个变量,字面上的意思,是成长关键,我个人理解为成长,这个地方我的理解就是得到内定成长系数.我为什么这么猜,因为接下来第一件事就是把这个POINT给setInt了,之后才setInt的四维,下面会说.在这里至少说明一个问题,成长率是内定的,并且是先于4围初始的,当然也是由4围决定的,这个基本上是废话了,大家都知道.

这个系数怎么算的,呵呵,按照这个公式我给大家解释一下:

内定成长系数=(血*2的24次方)+(攻*2的16次方)+(防*2的8次方)+敏,(当然这里面的血攻防敏不是指纯粹的血攻防敏,不然那数字大得不得了拉)

所以,从这里大胆地得出一个结论,血是关键中的关键,攻是关键,防和敏次要.这个结论其实相信大家已经发现了,比如人龙,普遍情况下,蓝龙成长最好,红龙次之,就是这个道理啊.再接下来:

for( i = 0; i < 10; i ++ ){

               int rnt = RAND( 0, 3 );

               if( rnt == 0 ) work[0]++;

               if( rnt == 1 ) work[1]++;

               if( rnt == 2 ) work[2]++;

               if( rnt == 3 ) work[3]++;

       }

这不用看又是一个人品问题,这段代码重复10次随即把4围中的一项+1,给我的感觉就是在做4围分布的微调,但是一没搞好这段代码,就容易造出那种某项很NB的畸形宠.

CHAR_setInt( petindex, CHAR_VITAL, ( PARAM_CAL(E_T_BASEVITAL) * work[0] ));

   CHAR_setInt( petindex, CHAR_STR , ( PARAM_CAL(E_T_BASESTR) * work[1] ));

   CHAR_setInt( petindex, CHAR_TOUGH , ( PARAM_CAL(E_T_BASETGH) * work[2] ));

   CHAR_setInt( petindex, CHAR_DEX , ( PARAM_CAL(E_T_BASEDEX) * work[3] ));

这段代码就是收尾了,前面说了,是初始化4围的4个函数,因为petindex是不变的,所以是针对同一只宠物,加上是在getNewPet函数的最后面,所以,不解释了.

整个转宠的代码最关键的部分基本上就是这些了,总结一下:

第一关键点,等级上130,这个很明显代码里交代得是清楚的.

第二关键点,MM和宠0转的成长率,这个决定了total值,虽然不是很清楚之间怎么起作用的.

第三关键点,人品,getNewPoint函数里的那两段随机数人品代码,就说明了一切.当然,这个人品并不是算命决定的,算命和转宠无关.

第四关键点,血和攻成长很关键.

4505

主题

1万

帖子

6万

石币

管理员

Rank: 9Rank: 9Rank: 9

积分
82333
推荐
发表于 2021-4-10 08:29:32 | 只看该作者
这不是我们的代码,因此不具参考价值
本服等级必须141级以上,否则无法达到最佳状态。
SOSE我们的家,大家一起来爱护她。
(客服不解答任务,任务不会做论坛发帖提问)
《石器so》无职业2.5PK模式客服QQ号1520218270客服QQ号756111
《石器se》8.5PK职业客服QQ号2311416291

6

主题

43

帖子

179

石币

石器高手

Rank: 3Rank: 3

积分
227

攻略达人

板凳
 楼主| 发表于 2021-4-10 20:07:51 | 只看该作者
石器时代so 发表于 2021-4-10 08:29
这不是我们的代码,因此不具参考价值
本服等级必须141级以上,否则无法达到最佳状态。 ...

这应该是当时台湾最早泄露出来的代码...都这么久了...肯定改得面目全非...但是基础算法应该不会改,但参数必须调...

1

主题

352

帖子

209

石币

石器骨灰

Rank: 4

积分
562
地板
发表于 2021-4-11 00:59:25 | 只看该作者
嗯嗯好了我懂了(

11

主题

582

帖子

181

石币

石器骨灰

Rank: 4

积分
763
5#
发表于 2021-4-11 13:50:47 | 只看该作者
我了个去,写了一大堆,看懂了,结果结论就是人品决定一切,人才啊

2

主题

647

帖子

1248

石币

石器精英

Rank: 6Rank: 6

积分
1895
6#
发表于 2021-4-11 23:14:24 | 只看该作者
小手一抖,石壁带走

3

主题

511

帖子

245

石币

石器骨灰

Rank: 4

积分
756
7#
发表于 2021-4-12 00:24:44 | 只看该作者
11111111111111111111111111111111

8

主题

2169

帖子

1117

石币

石器元老

Rank: 8Rank: 8

积分
3286
8#
发表于 2021-4-12 12:20:38 | 只看该作者
我草,楼主真是有心了!要是放在赚钱上... ...

0

主题

33

帖子

25

石币

石器入门

Rank: 2

积分
58
9#
发表于 2021-5-26 18:19:36 | 只看该作者
666666666666666666666

1

主题

320

帖子

380

石币

石器骨灰

Rank: 4

积分
700
10#
发表于 2021-10-22 10:31:39 | 只看该作者
11111111111111111111111
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|石器时代论坛

GMT+8, 2024-5-15 14:33 , Processed in 0.101850 second(s), 41 queries .

快速回复 返回顶部 返回列表