转自3DM-作者jewelswey-从零开始学破甲(小白向)
此教程全是作者的功劳,我只负责转,如果你对这篇教程比较感兴趣,对作者想表达感谢,请去3DM为他顶帖。送上原帖地址。传送门
这里假设我们要修改一件上衣为三段破甲,手头分别有{a.nif(上衣原始模型) b.nif(准备好的二段模型) femaleupperbody.nif(无甲模型——即身形,当然要是有专用的模型就最好,但是一般自改都是利用现成资源,第三段通常都会用果体)} 三个模型文件用于破甲各阶段替换模型。然后将三个文件丢到data\meshes\a\下
然后我们要让名为**.esp中id为**的上衣破甲化,勾上breakundies.esm和**.esp
新建脚本(在脚本中符号“;”为注释符,包括分号在内本行后面的文字只起描述作用,即便写进脚本也不会产生影响)
script type 为 object
[*]scn aaBU**
[*]
[*]ref who
[*]short break
[*]short check
[*]short wait
[*]short flag
复制代码
这时我们创建了一个名为aaBU**的脚本,当脚本写完后打开**选择此脚本即完成破甲化,脚本名命名请随意,这里只是举个例子,同时建议在首段写上诸如aa的字符使之排列靠前方便找到
此外我们在这个脚本关联了一个内部参变量who,四个自定参变量。
所有未被赋值的参数在初始状态下都 == 0
我们让break代表破甲的三阶段,即当耐久度为100%时break==0 ,耐久小于等于50%break==1,耐久度为0时break==2。
在这里check是可有可无的,因为它的作用是实现多件装备在同一脚本中完成破甲化,它的好处有很多,既便于统一管理,也方便装备跟脚本的关联以及esp的精简。我在最后会提一下它的用法,所以还是保留check。
flag代表装备的穿着状态,于是它应该是当装备时flag== 0 ,反之为1
wait要解释起来比较麻烦,因为它即作为因变量又作为自变量,在意义上也是表示穿着状态,但起到了动态地调用各部分函数的作用,我的知识有限表述能力也欠佳所以也不赘述以免误导人,只要理解这个破甲脚本的运作过程就不难理解它。
下面开始脚本的主体。
首先要设定脚本的触发方式,我们将脚本关联在上衣上,在游戏中耐久的变化是实时的,所以整个脚本要在实时中执行。 因此接下来应该录入的是
[*]Begin Gamemode;它表示除菜单状态下进入游戏后执行
复制代码
接着设置一个if的条件,第一段破甲应该是耐久度小于等于装备总耐久的1/2,录入以下代码
[*]if GetCurrentHealth <= GetObjectHealth / 2&&break == 0
[*]endif
复制代码
现在让我们来理一下思路,第一段破甲首先该角色的上衣是尚未破甲的而且他必须活着,然后输出一行屏幕提示破甲,接着将此上衣的材质替换成第二阶段的模型,然后卸下此装备旋即再穿上,在此之间需要播放一段破甲的特效。
为什么要卸了再穿,作者给出的解释是为了避免出错和无用的信息。当这一切完成后,该角色应该是穿着上衣,并且上衣为第二阶段。此时break理应为1,flag为0。完整代码如下
[*]if GetCurrentHealth <= GetObjectHealth / 2&&break == 0
[*] set who to container ; 这是定义who这个变量为满足条件并携带此装备的角色,这就解释了为什么我们要定义who而不是player,因为随着破甲的广泛应用,它不再成为玩家的专利。
[*] if wait == 2
[*] who.pms effectBreakArmor 0.5 ; 播放破甲特效,此特效在magicshadereffect中,你完全可以用自设的材质自设一个比它更好的散甲效果。
[*] if check == 1&&flag == 1
[*] who.equipItemNS **
[*] endif
[*] set flag to 0
[*] set break to 1
[*] set wait to 0
[*] elseif Break == 0&&who.getdead == 0
[*] if who.isincombat&&who.isActor
[*] message "上半身の鎧が破損した…!"
[*] endif
[*] set wait to wait + 1
[*] if who.GetEquipped **
[*] set flag to 1
[*] set check to 1
[*] SetFemaleBipedPath "a\b.nif" **
[*] who.UnequipItemNS **
[*] endif
[*] endif
[*]endif
复制代码
因为wait初始数值为0,所以这一段是从elseif部分开始进行的,输出上身破损的提示后,wait被赋值为1卸下装备后继续从elseif开始,输出提示后wait被赋值为2而此时角色装备已卸下于是跳过下面的if段回到整段代码的最上端运算,最后3个参数被重新赋值,不再进入elseif。整个过程只有一瞬间,所以这个复杂的循环过程是无缝的。
以上是第一阶段的破甲。
第二阶段依样画葫芦。
[*]if GetCurrentHealth == 0&&break == 1
[*] set who to getcontainer
[*] if wait == 2
[*] who.pms effectBreakArmor 1.0
[*] if check == 1&&flag == 1
[*] who.equipItemNS **
[*] endif
[*] set flag to 0
[*] set break to 2
[*] set wait to 0
[*] endif
[*]elseif Break == 1
[*] if who.isincombat&&who.isActor
[*] message "上半身の鎧が完全に壊れた!"
[*] endif
[*] set wait to wait + 1
[*] if who.GetEquipped **
[*] set flag to 1
[*] set check to 1
[*] SetFemaleBipedPath "a\femaleupperbody.nif" **
[*] who.UnequipItemNS ###
[*] endif
[*]endif
复制代码
以上就是简单的三段破甲的全过程,但是到这里还不能结束。因为我们耐久是可以修复的,所以接着要逆向补甲。
依旧一样画葫芦。
[*]if GetCurrentHealth > GetObjectHealth / 2&&break == 1
[*] set who to getcontainer
[*] if wait == 1
[*] if check == 1&&flag == 1
[*] who.equipItemNS **
[*] endif
[*] set flag to 0
[*] set break to 0
[*] set wait to 0
[*] set check to 0
[*] elseif wait == 0&&Break == 1
[*] set wait to 1
[*] if check == 1
[*] SetFemaleBipedPath "a\a.nif" **
[*] if who.getequipped **
[*] set flag to 1
[*] who.UnequipItemNS **
[*] endif
[*] endif
[*] endif
[*]endif
[*]
[*]if GetCurrentHealth != 0&&break == 2
[*] set who to getcontainer
[*] if wait == 1
[*] if check == 1&&flag == 1
[*] who.equipItemNS ###
[*] endif
[*] set flag to 0
[*] set break to 1
[*] set wait to 0
[*] elseif wait == 0&&Break == 2
[*] set wait to 1
[*] if check == 1
[*] SetFemaleBipedPath "...\b.nif" **
[*] if who.getequipped **
[*] set flag to 1
[*] who.UnequipItemNS **
[*] endif
[*] endif
[*] endif
[*]endif
复制代码
通常情况下到这里是可以写end结束脚本了,但是我们是前人栽树后人乘凉,一个好的脚本都是经过不断地发现问题不断修改才能经世致用的。
接下来还要处理两个细节。
首先为了防止角色死亡后脚本停止导致装备的模型路径没有改回原始模型而发生不必要的错误。我们应当让它在穿戴着死亡后初始化。
[*]if who.GetDead&&break != 0
[*] set break to 0
[*] set wait to 0
[*] set flag to 0
[*] if check == 1
[*] SetFemaleBipedPath "a\a.nif" **
[*] endif
[*]endif
[*]end;到这里关于gamemode的触发脚本已经全部完结,录入end结束。
复制代码
当玩家或者其他NPC将初始化的装备捡起来穿上,因为耐久度是不会变的,所以又会重新运算一遍这样又能自动回到正常的破损状态。
同理,依葫芦画瓢。让它在从包裹丢弃后初始化。
[*]begin ondrop;区别于begin gamemode,ondrop表示离开道具栏时触发
[*]set break to 0
[*]set wait to 0
[*]set flag to 0
[*]if check == 1
[*] SetFemaleBipedPath "Armor\apachii\gatecloser\###.nif" ###
[*]endif
[*]end
复制代码
整个脚本结束,接下来要做的就是关联editid为**的上衣了。
接下来简要介绍变量check的用法,如你所见check是用来实现多件破甲在同一脚本中运作。
回到最初的第一段破甲的循环中
[*]elseif Break == 0&&who.getdead == 0
[*] if who.isincombat&&who.isActor
[*] message "上半身の鎧が破損した…!"endif
[*] set wait to wait + 1
[*] if who.GetEquipped **; <<
[*] set flag to 1
[*] set check to 1; <<
[*] SetFemaleBipedPath "a\b.nif" **
[*] who.UnequipItemNS **
[*] endif
[*] endif
[*]endif
复制代码
假设我们添加第二件上衣为**2,这段代码便应该做如下变动。
[*]elseif Break == 0&&who.getdead == 0
[*] if who.isincombat&&who.isActor
[*] message "上半身の鎧が破損した…!"
[*] set wait to wait + 1
[*] if who.GetEquipped **;
[*] set flag to 1
[*] set check to 1;
[*] SetFemaleBipedPath "a\b.nif" **
[*] who.UnequipItemNS **
[*] endif
[*] if who.GetEquipped **2 ; <<
[*] set flag to 1
[*] set check to 2 ; <<
[*] SetFemaleBipedPath "a\b2.nif" ** ; <<
[*] who.UnequipItemNS **2 ; <<
[*] endif
[*] endif
[*]endif
复制代码
然后各阶段就应该在存在check==1的地方各添加一条check==2的if循环。
如下
[*]set who to getcontainer
[*]if wait == 2
[*] who.pms effectBreakArmor 1.0
[*] if check == 1&&flag == 1
[*] who.equipItemNS **
[*] endif
[*] if check == 2&&flag == 1; <<
[*] who.equipitemNS **2; <<
[*] endif;<<
[*] set flag to 0
[*] set break to 2
[*] set wait to 0
[*]endif
复制代码
{:KB57:}莫非是 沙发 忘记自沙。太悲剧了 本帖最后由 mjxy 于 2011-5-23 20:47 编辑
{:KB72:}三大妈收藏了,鲁国支持+1 太技術了,看不懂 酱油党路过了……
支持工作~
{:KB72:} 教學~收藏了~ {:H5_11:}学习中。。。。不太懂 好高难度的样子
页:
[1]