本帖最后由 815208129 于 2022-9-26 14:40 编辑
在ms系统里, 数值计算是一门非常重要的基础,决定了mod的优秀程度.
在ms里,存储数值的变量有一下类
1.寄存器类 reg0-reg64
2.局部变量 “:var_6” 格式为两端用双引号夹住,并且以冒号 : 开头,里面标识符以a-z或者下划线_开头,之后的字符还可以带有数字0-9,不推荐使用含有大写字母的局部变量
3.全局变量 “$var_8” 格式为两端用双引号夹住,并且以美元符号$ 开头, 里面标识符以a-z或者下划线_开头,之后的字符还可以带有数字0-9,不推荐使用含有大写字母的局部变量
4.slot: 只能存储,不能运算.
slot的使用要比 上面提到的要复杂一点, 相关介绍比较优秀的有 [rubik前辈] 撰写的帖子,这里就不放出链接了.有兴趣可以自行查找
这里要说的是slot关于游戏内存的联系
slot的存取都是通过编号来的,比如slot_item_is_checked = 0 需要注意的是, slot它是使用预申请的机制的, 比如开发者取1000号的troop_slot, 那么将会发生这样一件事情,Warband先判定,1000号slot存不存在,不存在则申请空间.但是申请空间不可能一个一个来,要申请就得申请多个,目前这个数值暂不知晓为多少. 据我所知的所有mod内,用过slot编号最大的mod是9999 [永恒世界PW]. 不过它是联机mod.
联机mod和单机mod的是有区别的, 联机mod因为运算分流的关系[简而言之就是,运算均匀分摊在玩家的电脑和服务器上,服务器只需要加载模型的名称和引用,不需要加载完整的模型外观,计算各类数值并且发送给玩家端,玩家端只需要根据服务器发来的数据绘制游戏.],能够容纳比单机mod更多的 代码和模型.而且流畅度更高. 所以它使用9999号slot, 看不出来有明显的卡顿. 但是回过头来看单机mod.我们会发现, 游玩时间一长,某个存档的体积就很大了,存档期间会有明显的卡顿. 特别是 在大地图上 添加了很多城堡, 和野怪的单机mod,非常卡顿, 每一个party就要有n个slot, m个party就要有m*n个slot.所以存档就大起来,运行则卡顿.
为了应对这种情况.可以参考以下原则 ①不使用超过 编号为1000的slot ②临时数据 只存放在固定的几个troop或者item里面
5. pos : 定点数运算,结构如下,每一个结构都分有xyz轴分量
小数运算:MS没有提供浮点数类型,只提供了定点数(定点数已经被整个计算机行业淘汰,现在计算机行业使用的是IEEE 754标准的浮点数).不过,如果你真的想有浮点数,可以用slot来模拟.工具是加减乘除配合取余mod运算.这样精度可以自己调节.
下面介绍一下定点数的使用
相关的OP有以下这些
- set_fixed_point_multiplier = 2124 #(set_fixed_point_multiplier, <value>),
- convert_to_fixed_point = 2130 # (convert_to_fixed_point,<destination_fixed_point>),
- convert_from_fixed_point = 2131 # (convert_from_fixed_point,<destination>),
复制代码
set_fixed_point_multiplier : 设置乘数λ
convert_to_fixed_point :将传入的数值val转换为 p=λ*val并且 val赋值为p,
也就是val=λ*val
如果不太好理解的话,我们用代码来测试一下
结果如下
当乘数为100时,5*100=500,符合上式,然后当取根号时,结果时224,看起来好像有问题,因为
224*224>500.但是我们从原数出发, 2.24*2.24~5.因此,计算没有问题,而是计算结果的状态还是定点数状态,只要用convert_from_fixed_point,把数值转换回我们能看懂的十进制数形式,
果然,结果为2.符合预期.
但是,直到这里,我们依然没有发现小数点. 别着急.获取小数可以使用取余,整数除法 这两种操作符.到了这里,差不多你能知道我在说什么了.
代码3
这样就能知道输出小数了, 结果为2.24,这样可以知道一件事. 计算小数的精度可以由乘数的位数决定, 因此,如果你想要高精度的小数. 可以这样写 10**n,那么可以得到n位小数.
那么接下来有一个新的问题, 如果乘数λ不是10的整数次方,那又要怎么办?
同样的,我们使用代码来测试
代码4
结果为
代码5
整体变成了两倍.但是转换为原来的数发现结果不变,那么刚刚的获取小数的代码就有问题了.发现刚好为之前的两倍, 因此可以先除以2,然后再取余.
这样做是为了配合一些需要使用定点数的op.如果制作者想要自己的浮点数.那么需要使用slot来模拟.
下面介绍一种算法:
计算5/3
5/3 =1
5%3=2
2/3=0 #当除法为0,数乘以10,直到除法结果大于零 (等价为 (lt,“:num”, “:divide_number”),
20/3=6
20%3=2
继续上一步,乘10再余数
20/3=6
其实大家都知道这个数是无理数,因此一定要设计精度数.比如7位,算到7次就停下,把除法产生的结果依次填入slot中
结果为 1.666666
|
POS运算 有了上面底子,这里开始介绍pos的运算, pos在mt和 prsnt当中有非常大的作用,熟练掌握并且深度理解有助于mod开发.
在mt中, 场景scene是一个方形的盒子, agent在其中运动.那么自然而然,需要有一个量来描述agent的位置. Pos变量就是这个应运而生的工具.
position_get_x= 726 #(position_get_x, <destination_fixed_point>, <position>), position_get_y= 727 #(position_get_y, <destination_fixed_point>, <position>), position_get_z= 728 # (position_get_y,<destination_fixed_point>, <position>), position_set_x= 729 #(position_set_x, <position>, <value_fixed_point>), position_set_y= 730 #(position_set_y, <position>, <value_fixed_point>), position_set_z= 731 #(position_set_z, <position>, <value_fixed_point>), 因此,你一眼就看到了fixed_point,顿时明白了, 坐标是支持定点数的,但是请不要忘记,定点数的范围比整数广大,因此你仍然可以大方地使用整数.
position_rotate_x = 723 #(position_rotate_x, <position>, <angle>), position_rotate_x_floating = 738 #(position_rotate_x_floating, <position>, <angle_fixed_point>), rotate为旋转,这里你可能有疑惑,坐标怎么能旋转.别急. 如果我们把坐标当作从原点(0,0,0)到(x,y,z)的向量,那么自然而然就能明白,角度那就是向量和坐标轴xyz轴的夹角( )
而且旋转有两种方式,一种为整数旋转,一种为浮点旋转.(t社真心有毒,明明参数写着定点数,结果这个op还挂上浮点,真是挂羊头卖狗肉),而且pos里存储了xyz三个角度,有相应的op可以获取旋转的角度.
position_get_rotation_around_x = 742 #(position_get_rotation_around_x, <destination>, <position>), position_get_rotation_around_y = 743 # (position_get_rotation_around_y,<destination>, <position>), position_get_rotation_around_z = 740 # (position_get_rotation_around_z,<destination>, <position>), 这三个op可以获取存放在pos里的角度
这里有个很奇特的OP,获取屏幕投影.
position_get_screen_projection = 750 # (position_get_screen_projection,<position_screen>, <position_world>), 首先,这个OP通过一个pos1 <position_world>这个pos1的坐标是mt里的实体坐标,然后返回屏幕pos2这个pos2的坐标是prsnt里的平面坐标. |
2022年7月28日
在pos的xyz轴坐标中有local 和 parent(global)
local 即为以某一个 agent或者 scene_prop_instance(spr)为中心, agent/spr正面朝向为y轴正方向, 垂直y轴, 左边为负,右边为正为x轴正方向
这个概念可以用于区分 前面的敌人和后面的敌人.
position_transform_position_to_local = 717 # (position_transform_position_to_local, <position_dest>, <position_anchor>, <position_source>),
例如我们获取玩家的pos然后 判定一下
- (get_player_agent_no, ":player_agent_id"),
- (agent_get_position, pos1, ":player_agent_id"),
- ## 假设队友的id为 agent_a
- (agent_get_position, pos9, ":agent_a"),
- (position_transform_position_to_local, pos13, pos1, pos9),
- (position_is_behind_position, pos1, pos9),
复制代码传送类,比如向前传送,只需要使用一些op - <div>position_move_x = 720 # (position_move_x, <position>, <movement>, [value]),
复制代码
这个第三参数就是local 和parent的参数 local (value=0) or global (value=1)
因此向前传送 只需要
- (position_move_y, pos1, 200, 0),
复制代码为何要z轴也拉高? 如果前面是山坡,只向前传送则会有问题.拉高一点z轴就能解决一些问题.
|