UTIL_WeaponTimeBase
Always 0.0 on client, even if not predicting weapons ( won't get called
in that case )
=====================
*/
float UTIL_WeaponTimeBase( void )
{
return 0.0;
}
static unsigned int glSeed = 0;
unsigned int seed_table[ 256 ] =
{
28985, 27138, 26457, 9451, 17764, 10909, 28790, 8716, 6361, 4853, 17798, 21977, 19643, 20662, 10834, 20103,
27067, 28634, 18623, 25849, 8576, 26234, 23887, 18228, 32587, 4836, 3306, 1811, 3035, 24559, 18399, 315,
26766, 907, 24102, 12370, 9674, 2972, 10472, 16492, 22683, 11529, 27968, 30406, 13213, 2319, 23620, 16823,
10013, 23772, 21567, 1251, 19579, 20313, 18241, 30130, 8402, 20807, 27354, 7169, 21211, 17293, 5410, 19223,
10255, 22480, 27388, 9946, 15628, 24389, 17308, 2370, 9530, 31683, 25927, 23567, 11694, 26397, 32602, 15031,
18255, 17582, 1422, 28835, 23607, 12597, 20602, 10138, 5212, 1252, 10074, 23166, 19823, 31667, 5902, 24630,
18948, 14330, 14950, 8939, 23540, 21311, 22428, 22391, 3583, 29004, 30498, 18714, 4278, 2437, 22430, 3439,
28313, 23161, 25396, 13471, 19324, 15287, 2563, 18901, 13103, 16867, 9714, 14322, 15197, 26889, 19372, 26241,
31925, 14640, 11497, 8941, 10056, 6451, 28656, 10737, 13874, 17356, 8281, 25937, 1661, 4850, 7448, 12744,
21826, 5477, 10167, 16705, 26897, 8839, 30947, 27978, 27283, 24685, 32298, 3525, 12398, 28726, 9475, 10208,
617, 13467, 22287, 2376, 6097, 26312, 2974, 9114, 21787, 28010, 4725, 15387, 3274, 10762, 31695, 17320,
18324, 12441, 16801, 27376, 22464, 7500, 5666, 18144, 15314, 31914, 31627, 6495, 5226, 31203, 2331, 4668,
12650, 18275, 351, 7268, 31319, 30119, 7600, 2905, 13826, 11343, 13053, 15583, 30055, 31093, 5067, 761,
9685, 11070, 21369, 27155, 3663, 26542, 20169, 12161, 15411, 30401, 7580, 31784, 8985, 29367, 20989, 14203,
29694, 21167, 10337, 1706, 28578, 887, 3373, 19477, 14382, 675, 7033, 15111, 26138, 12252, 30996, 21409,
25678, 18555, 13256, 23316, 22407, 16727, 991, 9236, 5373, 29402, 6117, 15241, 27715, 19291, 19888, 19847
};
unsigned int U_Random( void )
{
glSeed *= 69069;
glSeed += seed_table[ glSeed & 0xff ];
return ( ++glSeed & 0x0fffffff );
}
void U_Srand( unsigned int seed )
{
glSeed = seed_table[ seed & 0xff ];
}
/*
=====================
UTIL_SharedRandomLong
=====================
*/
int UTIL_SharedRandomLong( unsigned int seed, int low, int high )
{
unsigned int range;
U_Srand( (int)seed + low + high );
range = high - low + 1;
if ( !(range - 1) )
{
return low;
}
else
{
int offset;
int rnum;
rnum = U_Random();
offset = rnum % range;
return (low + offset);
}
}
/*
=====================
UTIL_SharedRandomFloat
=====================
*/
float UTIL_SharedRandomFloat( unsigned int seed, float low, float high )
{
//
unsigned int range;
U_Srand( (int)seed + *(int *)&low + *(int *)&high );
U_Random();
U_Random();
range = high - low;
if ( !range )
{
return low;
}
else
{
int tensixrand;
float offset;
tensixrand = U_Random() & 65535;
offset = (float)tensixrand / 65536.0;
return (low + offset * range );
}
}
/*
======================
第二段:
=====================
CBaseEntity::FireBulletsPlayer
Only produces random numbers to match the server ones.
=====================
*/
Vector CBaseEntity::FireBulletsPlayer ( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int shared_rand )
{
float x, y, z;
for ( ULONG iShot = 1; iShot <= cShots; iShot++ )
{
if ( pevAttacker == NULL )
{
// get circular gaussian spread
do {
x = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5);
y = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5);
z = x*x+y*y;
} while (z > 1);
}
else
{
//Use player's random seed.
// get circular gaussian spread
x = UTIL_SharedRandomFloat( shared_rand + iShot, -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 1 + iShot ) , -0.5, 0.5 );
y = UTIL_SharedRandomFloat( shared_rand + ( 2 + iShot ), -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 3 + iShot ), -0.5, 0.5 );
z = x * x + y * y;
}
}
return Vector ( x * vecSpread.x, y * vecSpread.y, 0.0 );
}
/*
=====================
上面两段东西定义了子弹弹道扩散是基于大学概率论的高斯分布定理。
它的数学模型像一条倒过来抛物线,中间有一峰值位,然后往两边慢
慢地流线型伸展下降,即得到峰值位附近数值的概率比较大。这个与
CS木仓械的随机弹道一样,木仓打出去的子弹落在墙上是在一个圆形范围
内服从高斯分布随机理论的(即子弹不是以直线射出总是落在一个点
上而是在以木仓口为锥尖木仓身为锥轴的一个三维圆锥范围内随机摆动的,
数学模型就像打蛋器一样),因此我们连续射出的每一木仓不会总是落
到同一个点上(除了AWP、鸟狙和散弹木仓——这就是为什么暴力作弊器
要用AWP、鸟狙或者散弹木仓冲刺的原因)而其中第一段的:
static unsigned int glSeed = 0;
unsigned int seed_table[ 256 ] =
{
28985, 27138, 26457, 9451, 17764, 10909, 28790, 8716, 6361, 4853, 17798, 21977, 19643, 20662, 10834, 20103,
27067, 28634, 18623, 25849, 8576, 26234, 23887, 18228, 32587, 4836, 3306, 1811, 3035, 24559, 18399, 315,
26766, 907, 24102, 12370, 9674, 2972, 10472, 16492, 22683, 11529, 27968, 30406, 13213, 2319, 23620, 16823,
10013, 23772, 21567, 1251, 19579, 20313, 18241, 30130, 8402, 20807, 27354, 7169, 21211, 17293, 5410, 19223,
10255, 22480, 27388, 9946, 15628, 24389, 17308, 2370, 9530, 31683, 25927, 23567, 11694, 26397, 32602, 15031,
18255, 17582, 1422, 28835, 23607, 12597, 20602, 10138, 5212, 1252, 10074, 23166, 19823, 31667, 5902, 24630,
18948, 14330, 14950, 8939, 23540, 21311, 22428, 22391, 3583, 29004, 30498, 18714, 4278, 2437, 22430, 3439,
28313, 23161, 25396, 13471, 19324, 15287, 2563, 18901, 13103, 16867, 9714, 14322, 15197, 26889, 19372, 26241,
31925, 14640, 11497, 8941, 10056, 6451, 28656, 10737, 13874, 17356, 8281, 25937, 1661, 4850, 7448, 12744,
21826, 5477, 10167, 16705, 26897, 8839, 30947, 27978, 27283, 24685, 32298, 3525, 12398, 28726, 9475, 10208,
617, 13467, 22287, 2376, 6097, 26312, 2974, 9114, 21787, 28010, 4725, 15387, 3274, 10762, 31695, 17320,
18324, 12441, 16801, 27376, 22464, 7500, 5666, 18144, 15314, 31914, 31627, 6495, 5226, 31203, 2331, 4668,
12650, 18275, 351, 7268, 31319, 30119, 7600, 2905, 13826, 11343, 13053, 15583, 30055, 31093, 5067, 761,
9685, 11070, 21369, 27155, 3663, 26542, 20169, 12161, 15411, 30401, 7580, 31784, 8985, 29367, 20989, 14203,
29694, 21167, 10337, 1706, 28578, 887, 3373, 19477, 14382, 675, 7033, 15111, 26138, 12252, 30996, 21409,
25678, 18555, 13256, 23316, 22407, 16727, 991, 9236, 5373, 29402, 6117, 15241, 27715, 19291, 19888, 19847
};
这段定义了一个无符号整型的拥有256个数字成员的16X16的一个结构
体数组。
这部分就是产生高斯分布随机数的源头,数学称{}里面的数值为seed
(种子)——顾名思义即产生随机数的初始值,所有产生的随机数都
是由这些种子通过数学运算(即第一段和第二段代码)而生成的。因
此不难想象如果我们可以人为改变这些种子的话就可以改变最终生成
的随机数的范围、大小等。大家不难发现所有拥有nospread(反弹道
扩散)功能的作弊器源代码里面都有这两段代码(要么在recoil.cpp
要么在nospread.cpp文件里),然后作弊器的源码再对每种武器通过
数学运算把基于以上两段代码所产生的随机数(即随机弹道)作一些
微小的修补,但也不能做到子弹直线射出的,因为这两段代码通过VC
编译以后是存在于hl.dll文件里面的,而hl.dll文件又是存在服务器
上面的,我们网络混战时服务器只是接受玩家的控制键输入,其他的
比如血量、子弹量、各种武器弹道定义等都是由服务器hl.dll文件决
定的,所以妄想通过作弊器锁血、锁子弹、使子弹直线飞等都不可能
成功的,除非你可以黑了服务器然后修改它的hl.dll,到了那个时候
除了你其他人的子弹也是直飞的,每种木仓都可以当作AWP用了。
说了那么多,最后建议大家还是练好AWP吧,散弹木仓虽然没有弹道扩散
但是打不远。看来Valve一开始的时候就预感了有人作弊的,所以一个
随机数就能使大家公平一点可以令大家都可以打一下,如果没有随机
弹道的话像三角洲,那么很快就会打完一盘的。
最后附带一个说明:
Awp瞬间开一级镜并开火(CS默认为鼠标右键和左键差不多是同时按下)
到可以接受输入开二级镜命令(CS默认为按一下鼠标右键)之间的时间
间隔为1400毫秒;接受了开二级镜命令之后到接受输入收镜命令(CS默
认也是再按一下鼠标右键)之间的时间间隔为230毫秒。整个过程简单
化就是
一级镜开火→间隔1400ms→二级镜→间隔230ms→收镜
以上说的1400ms和230ms是指在完成了前一步命令的前提下CS可以接受
再输入下一步控制命令的最短时间,如果快于这个间隔时间而过早按
控制键的话会不产生任何效果的——“效果”比如前面说的开二级镜
或收镜。