中国虚拟军事网(VME)- 专注于武装突袭系列虚拟军事游戏

 找回密码
 加入VME

QQ登录

只需一步,快速开始

搜索
楼主: FFUR2007SLX2_5

[教程] 《武装突袭3》脚本编写高级教程【255楼,武装突袭3——疯狂的戴夫和他的重量】

    [复制链接]
发表于 2014-3-17 21:59:29 | 显示全部楼层
新一期的教程简直酷炫
 楼主| 发表于 2014-3-21 19:02:28 | 显示全部楼层
本帖最后由 FFUR2007SLX2_5 于 2014-6-8 22:04 编辑

245楼,《武装突袭3——HandleDamage与cfg函数》



今天我们将来讨论A3中EH的2号人物”handledamage”,作为一个异常强大的EH,它可以帮助我们轻松实现许多人所希望出现的效果:譬如设定单位不同部位的防护,设定装甲车辆不同部位的防护模拟,更简单点,如果你觉得想让A3里的人耐打一点,就请开始今天的教程:
https://community.bistudio.com/w ... ndlers#HandleDamage 于2009年引入A2,作为EL+AL EH其MP表现形式则需要在每台客户端上判断local找到实体的主人并且PV EH中的变量才能达到各客户端同步的目的,如果BI的程序员能够加入MPHandleDamage或许会更方便些。


从handleDamage的五个参数中我们看到,HD并不是我们想象中的返还被击中部位的伤害值那么简单,而是返还值之后再对该部位的伤害值进行重设并将重设值累加至总伤害值中,有别于celery的解释!这点尤为关键,我们通过这样一个例子就可对其一目了然:

  1. private ["_unit"];
  2. _unit = [_this,0,objnull,[objnull]] call bis_fnc_param;
  3. _unit addEventHandler
  4. [
  5.         "HandleDamage",
  6.         {
  7.                 _part = _this select 1;
  8.                 _hit = _this select 2;
  9.                 switch (_part) do {
  10.                   case "head_hit": {_hit*0.9};
  11.                   case "body": {_hit*0.7};
  12.                   case "hands": {_hit*0.5};
  13.                   case "legs": {_hit*0.8};
  14.                   default {_hit*0.85};
  15.                 };
  16.         }
  17. ];
复制代码


通过上述例子我们就能够简单模拟OPREP装甲对士兵各个不同部位的保护,handledamage会将被击中部位的伤害值化作整体伤害值作用于士兵身上,与其说修改固定的config值,何不进行动态的调用来得更为方便?

接下来我想讲一下cfg fnc,采取cfg是脚本员们的基本功,许多人只会使用别人现成的cfg来采取武器设备,想要更灵活的运用则变得一问三不知,显然没有了解cfg采取的实质,Karel为我们写了一套函数可以帮助我们更加方便的采取cfg内容。



一、
  1. ["1000Rnd_65x39_Belt_Tracer_Green"] call BIS_fnc_classMagazine
复制代码
//用以返回弹药字符串的cfg项,相当于isclass (configFile >> "cfgMagazines" >> "1000Rnd_65x39_Belt_Tracer_Green"),其作用相当于检查所述弹药是否存在于游戏,否则返还false。

二、
  1. ["arifle_MX_SW_Black_Hamr_pointer_F"] call BIS_fnc_classWeapon
复制代码
//用于直接检查武器名字符串的函数,对应解释同上。

三、
  1. [configfile >> "CfgWeapons" >> "arifle_MX_SW_Black_Hamr_pointer_F"] call BIS_fnc_configPath
复制代码
//相当于将cfg路径转换成字符串的数组["configfile","CfgWeapons","arifle_MX_SW_Black_Hamr_pointer_F"]

四、BIS_fnc_getCfgData是一个非常强大的函数,秒杀一切isArray,isNumber,isText,getArray,getText和getNumber。如果以后在cfg采集项源时若再出现上述代码绝对是脚本菜鸟,BIS_fnc_getCfgData 已经完全将上述6个代码剔除了,它们没有存在的必要了。
  1. [configfile >> "CfgWeapons" >> "arifle_MX_SW_Black_Hamr_pointer_F" >> "artilleryDispersion"] call BIS_fnc_getCfgData
复制代码
返回1.你可以通过这个函数直接返回任何值。

五、BIS_fnc_getCfgDataArray则是将值加入至一个新的数组中,
  1. [configfile >> "CfgWeapons" >> "arifle_MX_SW_Black_Hamr_pointer_F" >> "artilleryDispersion"] call BIS_fnc_getCfgData
复制代码
返回[1]。

六、BIS_fnc_getCfgDataBool是将采取的任意cfg parseNumber至一个数字,只要大于1便返还true.
  1. [configfile >> "CfgWeapons" >> "arifle_MX_SW_Black_Hamr_pointer_F" >> "cartridgePos"] call BIS_fnc_getCfgDatabool
复制代码
//返还false,因为不是大于1的数字。

七、BIS_fnc_getCfgDataObject一个比较奇怪的函数,它的作用是查看被采取cfg对象的项源字符串是否在任务中是否有与其命名相同的变量,如果有同时判断该变量是否指代实体,如果是的话则直接返还该实体,比较晦涩。
  1. [configfile >> "CfgWeapons" >> "arifle_MX_SW_Black_Hamr_pointer_F" >> "cursor"] call BIS_fnc_getCfgDataObject
复制代码
//查找missionnamespace变量mg,这里player为mg,那么返还player

八、BIS_fnc_getCfgDataPool和BIS_fnc_getCfgDataPool已经过时,C++写的代码已经代替他们了,在此不用了,跳过看BIS_fnc_getCfgSubClasses,这又是一个异常强大的函数,由BI DEV Warka操刀,倘若下次再看到使用循环来采取cfg不得不说菜鸟了,唯一一点要注意的是在这个函数中warka直接使用了_this所以不要将你的cfg放入数组,直接
  1. (configfile >> "CfgFaces" >> "Man_A3") call BIS_fnc_getCfgSubClasses
复制代码
//返回你所需要的全部面容字串符数组,突然发现原来这是那么简单的一件事!

九、BIS_fnc_loadClass和BIS_fnc_loadEntry在此跳过,因为我们不需要自定义cfg路径,暂时没有使用价值,来看BIS_fnc_returnChildren,它是有karel操刀的一个函数,功能和BIS_fnc_getCfgSubClasses完全相同,但其返还值不是字符串数组,而是cfg路径数组。
  1. hint str ([configfile >> "CfgFaces" >> "Man_A3"] call bis_fnc_returnchildren)
复制代码
可以看看其返回什么。

十、BIS_fnc_returnConfigEntry也是一个十分实用的函数,由Joris-Jan van 't Land(DNA)和Karel联合操刀的一个函数,它可以用来翻找cfg路径子项的内容并返回其值,如果没有找到则可以自定义返回默认值,
  1. hint str ([(configfile >> "CfgCloth" >> "Flag"),"stepSize",nil] call BIS_fnc_returnConfigEntry)
复制代码
//返回0.005

十一、BIS_fnc_returnParents用来返回父类cfg路径,当然前提是你的源cfg路径是一个变量,否则用这个函数无意义:
  1. hint str ([configfile >> "CfgCloth" >> "Flag"] call BIS_fnc_returnParents)
复制代码


十二、BIS_fnc_uniqueClasses是Karel操刀的高端产品,凌驾于bis_fnc_returnchildren和BIS_fnc_getCfgSubClasses之上,该函数在取出所有所有子项cfg路径的同时,脚本员还需要将代码作用于每一个子项cfg路径,这里的cfg路径传递使用内部变量_this,我们还可以从中选择子项entry项,也是相当晦涩的一个函数,属于程序员入门级。
举例:
  1. my_array = []; [(configfile >> "BombCrater"),{my_array set [count my_array,_this]}] call BIS_fnc_uniqueClasses
复制代码
这里你可以看到代码是如何作用于每一个class子项及其value的。
甚至是这样:
  1. my_array = []; [(configfile >> "BombCrater"),{my_array set [count my_array,(_this select 2) call bis_fnc_getcfgdata]}] call BIS_fnc_uniqueClasses
复制代码

返还[[0,0,0],[0,0,0],[0,0,0]]

十三、BIS_fnc_unitAddon 用以返还该物体是否属于加载的MOD,举个例子在MP中你想要检查有没有客户端生成了一个作弊MOD的单位,通过检查黑名单来达到你所要的目的:
  1. hint str ([player] call BIS_fnc_unitAddon)
复制代码


十四、BIS_fnc_weaponAddon 和上面相同的作用,只不过这次检查武器字符串的MOD名:
  1. hint str ([WeaponName_String] call BIS_fnc_weaponAddon)
复制代码


头晕了?休息一下,看到各种莫名其妙的调用你是不是觉得SQF更本就不好用?BI的目的是想让SQF成为非编程专业的人员也能迅速掌握的一门语言而结果却是恰恰相反,由于SQF的各种反向参数反而使得其晦涩,好比中国人学英文,语法都是反的,最终的结果就是SQF逆向于了其他计算机语言,这就是为什么越来越多的专业玩家开始呼吁JAVA,LUA。只不过我想说的是,BI不会改变,SQF的语法是ARMA的生命,既然无法改变,何不适应?

SQF曾被一些程序员,如s0beit狂吐:http://s0beit.me/scripting/quick ... scripting-language/



随后就是kk,x39和s0beit的一场猛烈的“对轰”。

SQF到底适不适合作为一门语言,你说的算!

刚才这些为题外话,本片教程中的最后实例部分将是如何配合Karel的cfg函数和EH HD来发挥自己的想象力。我们知道在BI没有正式放出步兵不同部位背心防护特性之前目前尚没有人来做这块内容,虽然cfg中目前我们也没有办法找到有关vest防护的任何参数:



不过我们依然能够做出我们想要的效果。我们知道BI DEV对OPREP步兵细节化防护的设计主旨在三点上,即北约制防弹背心厚重耗体能、东方制式背心轻量重机动和通用制式背心综合性强的三个特点,我们就能够开始自己开始配置步兵防御能力的参数!

  1. /*
  2. fn_SoliderProtectionSample
  3. author: ffur
  4. description: scripted customizable soldier protection simulation
  5. param:
  6. 0 - unit
  7. 1 - blufor vest protection level (number)
  8. 2 - common vest protection level (number)
  9. 3 - opfor vest protection level (number)
  10. */
  11. private ["_unit"];
  12. _unit = [_this,0,objnull,[objnull]] call bis_fnc_param;
  13. BLUFOR_LEVEL = [_this,1,0.1,[0]] call bis_fnc_param;
  14. COMMON_LEVEL = [_this,2,0.4,[0]] call bis_fnc_param;
  15. OPFOR_LEVEL = [_this,3,0.8,[0]] call bis_fnc_param;
  16. if (_unit == vehicle _unit) exitwith {
  17.   _unit addeventhandler [
  18.     "handledamage",{
  19.           private ["_part","_damage","_unit"];
  20.           _unit = _this select 0;
  21.           _part = _this select 1;
  22.           _damage = _this select 2;
  23.           if (_part == "body") then {
  24.             private ["_vest","_vestStr"];
  25.                 _vest = vest _unit;
  26.             if (_vest != "") then {
  27.           _vestStr = [configfile >> "CfgWeapons" >> _vest >> "model"] call bis_fnc_getcfgdata;
  28.                   {
  29.                     if ([_x select 0,_vestStr] call bis_fnc_instring) then {
  30.                         _damage = _damage*(_x select 1);
  31.                         };
  32.                   } foreach [["BLUFOR",BLUFOR_LEVEL],["Common",COMMON_LEVEL],["OPFOR",OPFOR_LEVEL]];         
  33.                 };
  34.           };
  35.           _damage;
  36.         }
  37.   ];
  38. };
复制代码


在这里的bis_fnc_getcfgdata和bis_fnc_inString为我们的脚本节约了许多内容,如果你还是第一次碰到bis_fnc_inString,那这里就介绍一下,该函数是由BI DEV Mika Hannola操刀,为脚本编写者提供了引擎内的一个字符串检查解决方案,函数库的比较详细大家可以试下,对于非编程专业起家的朋友这是一个不错的函数,功能还是相当强大的。(不过毕竟无法和C++的优化效率相比,当然后者需要是编程专业的朋友)



在这个例子中我仅仅示范了HD在防弹背心身体保护部分的效果,默认效果中北约可以减免90%的伤害效果,通用型可以减免60%的伤害效果,东方型可以减免20的伤害效果,这样我们就可以通过不同的防弹衣类型达到不同的防弹效果:[unit,0.1,0.4,0.8] call fnc_soldierprotectionsample,当然你也可以根据自己的需要进行修改。这里我只是提供了一个开头,接下来我们还可以对各种防弹衣的防弹效果继续进行细分,甚至扩展至头部防护的细分和腿部防护的细分,喜欢真实模拟的朋友们可以试试了!



PS,如果你对ARMA装甲车辆不同防护部位不满意的话,也可以通过HD来进行修改。

247楼继续教程,《武装突袭3——方位角与倾转角》

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入VME

x
发表于 2014-5-29 20:34:21 | 显示全部楼层
不是程序员,简直如看天书啊!
 楼主| 发表于 2014-6-8 21:58:24 | 显示全部楼层
247楼,《武装突袭3——方位角与倾转角》



RV4中的方位角与倾转角其实是相当便于理解的,只是如果我们不认真学习我们将始终无法究其要领,最后的结果往往便会是无法将这些强大的功能运用到我们的脚本中去,无疑是一种遗憾。
对于空间想象力不是很好的朋友来说,SetVectorDirAndUp的两组矢量的理解上确实有些困难,如何将抽象的数字化为脑海中清晰的图形方位?将在这篇教程中为大家解惑。

相信大家已经看过SetVectorDirAndUp的文献了:
http://forums.bistudio.com/showt ... randUp-Usage-Solved
https://community.bistudio.com/wiki/setVectorDirAndUp

SetVectorDirAndUp最为困难的地方就是它不等于SetVectorDir + SetVectorUp。(正如http://feedback.arma3.com/view.php?id=19005 标注中所提到的,KillZone_Kid将我在wiki中的标注反应到feedback后,即使得到解决我们也依旧没有办法分步对其测试,因为任何一个矢量都会被之后的代码篡改导致不正确的转向,所以我们只能直接分析SetVectorDirAndUp)
再来看这张图:



在方向角与倾斜度中最为痛苦的事就是两组矢量中的任何一个数字并没有独立存在的意义,两组矢量的每一组数字都必须相互配合起来才有可能达到我们所需要的旋转角度,但这需要我们超强的空间想象力,没有经过训练几乎不可知起源。killZone_Kid正尝试努力为我们简化SetVectorDirAndUp的思考方式,如果说想让物体平放于水平面并且让其延顺时针方向旋转90度:
_obj setVectorDirAndUp [[1,0,0],[0,0,1]];

这样的解释其实是出于无奈,因为这会误导我们1便代表90度,0.5便代表45度这种概念。现在我想说的是,请彻底颠覆这种假设,这本身就是不正确的,试试:
_obj setVectorDirAndUp [[0.01,0,0],[0,0,1]];
是不是大脑中想象物体沿顺时针方向稍微偏转0.9度?抱歉,结果同样是偏转90度,这就会令我们百思不得其解,那么更加复杂的翻转我们岂不是彻底完蛋?

来分析一下,我们先要回到世界最混沌的阶段,物体面朝北,垂直站立的初始值永远都是:
_obj setVectorDirAndUp [[0,1,0],[0,0,1]];



当然也可以是:
_obj setVectorDirAndUp [[0,0.001,0],[0,0,0.001]];这同样也是面朝北,水平直立的初始值,到这里应该能清楚的明白当XY均为0时Z在UP轴上的略微正值即可让物体笔直向上,那么让他彻底倒立呢?



对了,就是_obj setVectorDirAndUp [[0,0.001,0],[0,0,-0.001]];我们延UP黑线相反的方向略微一点的负值就可以让物体彻底反转
现在来点高级的,在刚才的基础上我需要让物体往右面倾斜,该怎么办?



充分发挥我们的空间想象力,DIR起的是方向作用,UP起的是倾斜作用,如果要倾斜我们要修改UP中的数值,那么究竟是改X轴还是Y轴?想象一下X轴正值无限延伸至右侧导致物体右倾但永远无法与法线(UP线)垂直因为我有一个Z轴的值还存在,反之亦然,向右无限负值延伸致使物体向左侧倾斜同样永远不会垂直于法线。
_obj setVectorDirAndUp [[0,0.001,0],[10000,0,-0.001]]; 向右倾但不垂直于UP轴(法线轴)
_obj setVectorDirAndUp [[0,0.001,0],[-10000,0,-0.001]]; 向左倾但不垂直于UP轴(法线轴)

这里的UP数组Y轴又扮演什么作用?很高兴的告诉大家没有任何作用,无论我们怎么改
_obj setVectorDirAndUp [[0,0.001,0],[10000,100000,-0.001]];
_obj setVectorDirAndUp [[0,0.001,0],[10000,-100000,-0.001]];
都不会造成任何变化。为什么?想象一下Y轴在这里扮演的作用是在DIR平面扮演倾斜作用,一旦UP的Y轴起了作用是不是对DIR的Z轴抢了饭碗?怎么办?如果我们要在刚才的基础上再对物体作出前后的倾仰,该是DIR轴出场的时候了:



这时的脑子千万不能乱,让物体向上倾仰,起作用的是DIR轴的Z轴
_obj setVectorDirAndUp [[0,0.001,10000],[10000,0,-0.001]]; 无限向前倾但不平行于DIR轴
_obj setVectorDirAndUp [[0,0.001,-10000],[-10000,0,-0.001]]; 无限向左后倾但不平行于DIR轴

是不是开始有点混乱了?但当我们能够紧跟步伐来到这一步时已近很不错了,这些已经完全可以将物体转到我们所需要的几乎所有3D方向。
如果我要在物体水平向上面朝北的情况下向右转向该怎么办?修改DIR的X轴。



_obj setVectorDirAndUp [[1,1,0],[0,0,1]];

那么我再在上面的基础上让物体向左侧倾斜该调节哪个值?UP轴的Y值,向右则是Z值:



_obj setVectorDirAndUp [[1,1,0],[0,1,1]];

搞清楚了,那么我们使用这个命令的思路是什么?
1、        设定初始值_obj setVectorDirAndUp [[0,1,0],[0,0,1]];在大脑中绘制出面朝北水平垂直于地表的物体。(永远记住UP和DIR是常量,它们是永远不随物体翻滚的,翻转点位于物体正中央: https://community.bistudio.com/wiki/boundingCenter



2、        随后开始一步一步翻转,最后形成好的翻转对象后一气呵成将数字逐个填入。

说老实话setVectorDirAndUp是最贴近于底层的一个命令,如果从实用性考虑出发普通玩家根本就不可能使用如此贴近于引擎的代码,因此我们需要新的命令setPitchBank,在正式命令没有出来之前BI程序员Andrew Barron为我们提供了BIS_fnc_setPitchBank,但十分可惜的是,这个函数在与attachTo一起使用时存在BUG。(当然,在正常情况下官方函数还是相当方便的,用法我已经在wiki中更新)所以我于4号又更新了一个更佳的函数以替代BIS_fnc_setPitchBank,几乎解决了所有困惑,所以作为这篇教程的结束篇,我将提供一个让车辆疯狂翻滚的函数(函数来源于wiki note fnc_setPitchBankYaw – bapedibupa修改版 https://community.bistudio.com/wiki/setVectorDirAndUp 最后)不过在此之前,我不得不在下一篇教程中谈谈ARMA3中的重量,新玩法需要新解释,至少我们都需要:)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入VME

x

点评

这个需要数学基础啊 呵呵 好多年没复习过了  发表于 2014-6-8 23:12
发表于 2014-6-9 09:06:05 | 显示全部楼层
版主老师~~~我有个问题啊
(configfile >> "CfgFaces" >> "Man_A3") call BIS_fnc_getCfgSubClasses
你说这个函数可以快速地返还出一个类别里的字符串数组,但是用于返还载具和人员貌似不行呢CfgVehicles里面~有载具有人员甚至有背包~~全混一起~~~那么要如何使用BIS_fnc_getCfgSubClasses这个函数才能
把阵营,人员,载具,背包,物品,武器,这些东西精确区分开来呢?
 楼主| 发表于 2014-6-14 15:26:41 | 显示全部楼层
本帖最后由 FFUR2007SLX2_5 于 2014-6-14 15:49 编辑
下网上载 发表于 2014-6-9 09:06
版主老师~~~我有个问题啊
(configfile >> "CfgFaces" >> "Man_A3") call BIS_fnc_getCfgSubClasses
你说 ...


不是BIS_fnc_getCfgSubClasses,而是BIS_fnc_UniqueClasses

如果我要所有蓝方阵营的士兵(或者平民,红方,绿方什么的):
  1. BLUFOR_UNITS = [];
  2. [(configfile >> "CfgVehicles"),{
  3.   if (((_this >> "faction") call bis_fnc_getcfgdata) == "BLU_F") then {
  4.     if (((_this >> "faceType") call bis_fnc_getcfgdata) == "Man_A3") then {
  5.           BLUFOR_UNITS set [count BLUFOR_UNITS, configname _this];
  6.         };
  7.   };
  8. }
  9. ] call bis_fnc_uniqueclasses;
复制代码


如果我要所有帽子(装备,服装各种各样的东西进行分类,以此类推):
  1. ALL_HATS = [];
  2. [(configfile >> "CfgWeapons"),{
  3.   if (((_this >> "ItemInfo" >> "type") call bis_fnc_getcfgdata) == 605) then {   
  4.           ALL_HATS set [count ALL_HATS, configname _this];
  5.   };
  6. }
  7. ] call bis_fnc_uniqueclasses;
复制代码


如果我要所有红方的装甲车辆(各种车子)
  1. ALL_REDFOR_TANKS = [];
  2. [(configfile >> "CfgVehicles"),{
  3.   if (((_this >> "faction") call bis_fnc_getcfgdata) == "IND_F") then {
  4.     if ((configname _this) iskindof "Tank_F") then {
  5.           ALL_REDFOR_TANKS set [count ALL_REDFOR_TANKS, configname _this];
  6.     };       
  7.   };
  8. }
  9. ] call bis_fnc_uniqueclasses;
复制代码



发表于 2014-6-14 18:24:42 | 显示全部楼层
FFUR2007SLX2_5 发表于 2014-6-14 15:26
不是BIS_fnc_getCfgSubClasses,而是BIS_fnc_UniqueClasses

如果我要所有蓝方阵营的士兵(或者平民 ...

原来如此~收藏学习了
发表于 2014-6-18 15:12:26 | 显示全部楼层
很好的帖子认真学习了。
发表于 2014-6-18 15:12:40 | 显示全部楼层
很好的帖子认真学习了。
发表于 2014-6-18 15:12:46 | 显示全部楼层
很好的帖子认真学习了。
发表于 2014-6-18 15:12:53 | 显示全部楼层
很好的帖子认真学习了。
 楼主| 发表于 2014-6-26 16:18:01 | 显示全部楼层
本帖最后由 FFUR2007SLX2_5 于 2014-8-13 22:16 编辑

255楼,《武装突袭3——疯狂的戴夫和他的重量》



在我们“疯狂的道夫”开始旋转之前,他又给我们带来了几个新朋友:

https://community.bistudio.com/wiki/setMass
https://community.bistudio.com/wiki/getMass
https://community.bistudio.com/wiki/getCenterOfMass
https://community.bistudio.com/wiki/setCenterOfMass

当我们还在各种吐槽RV4的Physix时,波米则落落大方毫不掩饰的敞开衣襟让我们看了个遍。用过O2的朋友都知道我们的第一个盒子肯定不乏Mass这个词眼。她其实就是负责我们盒子在引擎中的重量,一个盒子250KG重,同时四个角也有各自的重量:



A3的“科尼赛格”只有1090KG!好轻啊,难怪可以跑出那么快的速度。(Agrea one-one也要1340kg耶)不过从现在开始我们可以用setMass和setCenterOfMass让我们的神级超跑更加逆天。setMass支持在时间的控制下逐渐控制重量,那么请试想在你逐渐轰油门的那一瞬间破天荒的减小车重将会是何等光景?“小黄车”可以拥有更快的加速度直到彻底失重四轮离地漂浮于空中,简直就是飞车中的极品。
接下来有请我们的Top Gear的Jeremy前来试车:



  1. /*
  2. Mass test, author: ffur2007slx2_5
  3. 0 = [vehicle player] spawn fn_MassTest;
  4. */
  5. private ["_car","_topSpeed","_code","_OldMass"];
  6. _car = [_this,0,objnull,[objnull]] call bis_fnc_param;
  7. if (_car iskindof "Car") then {
  8.   if (canmove _car) then {
  9.       _topSpeed = (configfile >> "CfgVehicles" >> typeof _car >> "maxSpeed") call bis_fnc_getcfgdata;
  10.           _OldMass = getmass _car;
  11.           _code = {
  12.             private ["_car","_topSpeed","_ratio","_Oldmass","_NewMass"];
  13.                 _car = _this select 0;
  14.                 _topSpeed = _this select 1;
  15.                 _Oldmass = _this select 2;
  16.                 _ratio = (speed _car) / _topSpeed;
  17.                 _NewMass = _OldMass - (_OldMass * _ratio);
  18.                 _car setmass _NewMass;
  19.           };
  20.           ["ffur_00","OnEachFrame",_code,[_car,_topSpeed,_OldMass]] call bis_fnc_addStackedEventHandler;
  21.   };
  22. };
复制代码


在使用该脚本前请即好安全带(我无法保证开快了你会不会飞出去),当然如果大家喜欢我们也可以用setMass来建立一个无重力的世界。getCenterOfMass可以让你看到重量集中在哪一个点上,setCenterOfMass则可以自由规划物体的重量集中在哪里。举个例子,波米的下一个Heli DLC吊装负重的模拟得用上setCenterofMass,直升机不同部位挂载的重物模拟就全靠上她们啦。等不及的朋友可以自己先开始体验一番啦!

接着上次的教程,体验了重力后疯狂的戴夫该出场了,今天他的任务是将翻斗车转出翔来。他将使用mass, setpitchbankyaw和attachto来克服setvelocity无法兼顾同时360度三轴旋转物体的软肋,将我们翻个底朝天。(FFUR_fnc_rotate测试版,暂时提供的方案仅供教程参考,函数FFUR_fnc_setPitchBankYaw位于https://community.bistudio.com/wiki/setVectorDirAndUp)

  1. /*
  2. FFUR_fnc_rotate
  3. author: ffur2007slx2_5
  4. description: Overcome the limitation brought by setvectordirandup and setvelocity, simulate physix simulation with on-the-fly rotation
  5. example: [power(scalar),angle(scalar),obj(obj),id(string)] spawn FFUR_fnc_rotate
  6. */
  7. private ["_power","_angle","_mass","_veh","_vector","_velocity","_distance","_a","_b","_duration","_temp_logic","_code","_halfDuration","_expotent","_random","_signed","_idString"];
  8. _power = [_this,0,0,[0]] call bis_fnc_param;
  9. _power = abs _power;
  10. _angle = [_this,1,0,[0]] call bis_fnc_param;
  11. _veh = [_this,2,objnull,[objnull]] call bis_fnc_param;
  12. if (_veh iskindof "man") exitwith {
  13.   private "_msg";
  14.   _msg = format ["%1 is kind of man, %2 instead.",_veh,typename objnull];
  15.   [_msg] call BIS_fnc_error;
  16. };
  17. _idString = [_this,3,"",[""]] call bis_fnc_param;
  18. _mass = getmass _veh;
  19. _expotent = ((log _mass) / 2);
  20. _vector = [];
  21. _random = [0,1,2] call bis_fnc_selectrandom;
  22. _signed = [-1,1] call bis_fnc_selectrandom;
  23. {
  24.   _veh setVariable [format ["FFUR_temp_var_%1",_x],0];
  25. } foreach ["a","b","c"];
  26. _veh setVariable ["FFUR_temp_down",false];
  27. for "_i" from 0 to 2 do {
  28.   _vector set [_i,_power];
  29. };
  30. _velocity = [_vector,_angle] call BIS_fnc_rotateVector2D;
  31. _veh setvariable ["FFUR_temp_vector",_velocity];
  32. if ((!isnull _veh) && isServer) then {
  33.   _a = _velocity select 0;
  34.   _b = _velocity select 1;
  35.   _distance = (sqrt ((_a ^ 2) + (_b ^ 2)));
  36.   _duration = (_distance / 6);
  37.   _halfDuration = (_duration / 2);
  38.   _temp_logic = "logic" createvehiclelocal (position _veh);
  39.   _code = {
  40.     private ["_veh","_a","_b","_c","_logic","_halfDuration","_expotent","_duration","_EachRoundFrame","_random","_signed"];
  41.         _veh = _this select 0;
  42.         _a = _this select 1;
  43.         _b = _this select 2;
  44.         _c = _this select 3;
  45.         _logic = _this select 4;
  46.         _halfDuration = _this select 5;
  47.         _expotent = _this select 6;
  48.         _random = _this select 7;
  49.         _signed = _this select 8;
  50.         _EachRoundFrame = (360 * _expotent) / diag_fpsmin;
  51.         private ["_constant_a","_constant_b","_constant_c"];
  52.         _constant_a = (((_a / 2) / diag_fpsmin) / _halfDuration);
  53.         _constant_b = (((_b / 2) / diag_fpsmin) / _halfDuration);
  54.         _constant_c = ((_c / diag_fpsmin) / _halfDuration);
  55.         _veh setvariable ["FFUR_temp_var_a",((_veh getvariable "FFUR_temp_var_a") + _constant_a)];
  56.     _veh setvariable ["FFUR_temp_var_b",((_veh getvariable "FFUR_temp_var_b") + _constant_b)];
  57.     _veh setvariable ["FFUR_temp_var_c",
  58.           call {
  59.             if (_veh getvariable "FFUR_temp_down") then [
  60.                 {(_veh getvariable "FFUR_temp_var_c") - _constant_c},
  61.                 {(_veh getvariable "FFUR_temp_var_c") + _constant_c}];
  62.           }
  63.         ];
  64.     if (_a >= 0) then [
  65.         {
  66.           if (_b >=0) then [
  67.           {
  68.             _veh attachto [_logic,[
  69.                   (_veh getvariable "FFUR_temp_var_a"),
  70.                   (_veh getvariable "FFUR_temp_var_b"),
  71.                   (_veh getvariable "FFUR_temp_var_c")]];
  72.           },
  73.           {
  74.             _veh attachto [_logic,[
  75.                   (_veh getvariable "FFUR_temp_var_a"),
  76.                   - (_veh getvariable "FFUR_temp_var_b"),
  77.                   (_veh getvariable "FFUR_temp_var_c")]];
  78.           }
  79.           ];
  80.         },
  81.         {
  82.           if (_b >= 0) then [
  83.           {
  84.             _veh attachto [_logic,[
  85.                   - (_veh getvariable "FFUR_temp_var_a"),
  86.                   (_veh getvariable "FFUR_temp_var_b"),
  87.                   (_veh getvariable "FFUR_temp_var_c")]];
  88.           },
  89.           {
  90.             _veh attachto [_logic,[
  91.                   - (_veh getvariable "FFUR_temp_var_a"),
  92.                   - (_veh getvariable "FFUR_temp_var_b"),
  93.                   (_veh getvariable "FFUR_temp_var_c")]];
  94.           }
  95.           ];
  96.         }
  97.         ];
  98.         _veh setvariable ["FFUR_temp_vector",
  99.           [_random,_signed,_EachRoundFrame] call {
  100.             private ["_arr","_random","_signed","_EachRoundFrame"];
  101.                 _random = _this select 0;
  102.                 _signed = _this select 1;
  103.                 _EachRoundFrame = _this select 2;
  104.                 _arr = (_veh getvariable "FFUR_temp_vector");
  105.                 _arr set [_random,(_arr select _random) + (_signed * _EachRoundFrame)];
  106.                 _arr
  107.           }
  108.         ];
  109.         [_veh,(_veh getvariable "FFUR_temp_vector")] call FFUR_fnc_setPitchBankYaw;
  110.   };
  111.   [_idString,"OnEachFrame",_code,[_veh,_a,_b,_power,_temp_logic,_halfDuration,_expotent,_random,_signed]] call bis_fnc_addstackedeventhandler;
  112.   sleep _halfDuration;
  113.   _veh setvariable ["FFUR_temp_down",true];
  114.   sleep _halfDuration;
  115.   [_idString,"OnEachFrame"] call bis_fnc_removestackedeventhandler;
  116.   detach _veh;
  117.   deletevehicle _temp_logic;  
  118. };
复制代码


关于脚本中用到的bis_fnc_rotateVector2D我得画张图来解释这个函数:



我们将角a旋转一定角度后到黄色的角a,就这么简单。(如果说有一些新玩意比如log,wiki中我也做了相应的解释,理解应该不成问题)
好了,接下来就来看一下戴夫是如何将我们转出翔来的。



往我们的MP一扔,我们可以随时随地的将世界转个天翻地覆。比如说这样:

  1. {[random 360,random 360,_x select 0,_x select 1] spawn vbs3_fnc_rotate;} foreach [[car,"id0"],[car1,"id1"]…[car100,"id100"]];
复制代码


明天27日变形金刚4首映,想象一下在“爆点”中心放一个“机甲”什么玩意,一个大招100多辆车旋转着飞起,疯狂的戴夫应该会比较高兴。

作为本篇的结语,或许我们还能往船上不停的堆箱子把船堆沉了,把车子堆斜了,等等:)

(P.S. 当然对https://community.bistudio.com/w ... StackedEventHandler 感到非常抱歉,因为我至少还没有办法将所有的代码叠加到一个PFH中来最大化FPS)

#260 ArmA3 15 Years' Anniversary to continue the tutorial

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入VME

x
发表于 2014-6-26 18:51:17 | 显示全部楼层
本帖最后由 qevhytpl 于 2014-6-26 18:54 编辑

版主,我有一个问题,比如让AI驾驶的武装直升机,对地面的目标进行火箭弹轰击,依靠脚本控制,我该如何漂亮地完成这个动作?提供我个思路就行了,谢谢!目前我无法完成的是让其在飞行中瞄准目标,如果能告知战斗机准确投弹的思路,我一并表示感谢!另外我知道自己的要求有点过分,但是我还是厚着脸皮希望版主能够写一个关于人机交互的教程。
 楼主| 发表于 2014-6-28 22:25:12 | 显示全部楼层
qevhytpl 发表于 2014-6-26 18:51
版主,我有一个问题,比如让AI驾驶的武装直升机,对地面的目标进行火箭弹轰击,依靠脚本控制,我该如何漂亮 ...

你可以使用BIS_fnc_dirTo + setDir设置方位角。

VectorDistance + getPosASL得到向量直线距离,以及高度差。

atan2得出仰角,90 - 仰角得到俯角。

使用BIS_fnc_setPitchBank设置俯角。

使用forceWeaponFire开火。
发表于 2014-6-28 22:43:32 | 显示全部楼层
很好的教程 收下了 非常重要
您需要登录后才可以回帖 登录 | 加入VME

本版积分规则

小黑屋|中国虚拟军事网

GMT+8, 2024-5-3 14:14

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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