设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
楼主: zhufeng233
打印 上一主题 下一主题

[交流讨论] 基于YEP插件的一些技能设计与实现方法

[复制链接]

Lv3.寻梦者

梦石
0
星屑
2608
在线时间
314 小时
注册时间
2022-3-24
帖子
115
21
 楼主| 发表于 2023-4-13 22:03:10 | 只看该作者
今天考了一天的试,没怎么做技能。但翻译了一下Damage Core,Skill Core 和 BuffStatesCore 的一些时点。因为都是用自己刚过六级的英语水平和一些自己的理解翻译的结果,可能会有一些错误,如有发现请及时指出。

Damage Core
<Bypass Damage Cap>伤害破限
<Damage Cap: x>伤害限制
<Heal Cap: x>治疗限制
<damage formula> 伤害公式
</damage formula>

Buffstatescore
<Show Turns>显示回合
<Hide Turns>隐藏回合
<Turn Font Size: x> 回合字体大小

<Turn Alignment: Left>
<Turn Alignment: Center> 回合计数对齐方式
<Turn Alignment: Right>


<Turn Buffer X: +x>
<Turn Buffer X: -x>
<Turn Buffer Y: +x>  回合计数位置
<Turn Buffer Y: -x>

<Turn Color: x> 回合计数颜色

<Reapply Ignore Turns>
<Reapply Reset Turns> 改变回合数
<Reapply Add Turns>

<State x Turns: +y>
<State x Turns: -y>
<State named Turns: +y>  修改回合数
<State named Turns: -y>

<Show State Turns>
<Hide State Turns> 显示回合


<Custom stat Buff Turn>
turn = 10;
turn += user.agi;
</Custom stat Buff Turn>
设置默认的buff


<Custom Apply Effect>
code
code
</Custom Apply Effect>
获得状态时触发

<Custom Remove Effect>
code
code
</Custom Remove Effect>
移除状态时触发

<Custom Leave Effect>
code
code
</Custom Leave Effect>
状态自然消失时触发


<Custom Turn Start Effect>
code
code
</Custom Turn Start Effect>
回合开始时触发

<Custom Action Start Effect>
code
code
</Custom Action Start Effect>
动作开始时触发

<Custom Action End Effect>
code
code
</Custom Action End Effect>
动作结束时触发


<Custom Regenerate Effect>
code
code
</Custom Regenerate Effect>
使用者HP,MP,TP有变化时触发

<Custom Turn End Effect>
code
code
</Custom Turn End Effect>
回合结束时触发

<Custom Battle Effect>
code
code
</Custom Battle Effect>
战斗开始时触发

<Custom Victory Effect>
code
code
</Custom Victory Effect>
战斗胜利时触发


<Custom Escape Effect>
code
code
</Custom Escape Effect>
逃跑时触发

<Custom Defeat Effect>
code
code
</Custom Defeat Effect>
失败时触发

<Custom Initiate Effect>
code
code
</Custom Initiate Effect>
选中目标时触发


<Custom Select Effect>
code
code
</Custom Select Effect>
被选中时触发


<Custom Confirm Effect>
code
code
</Custom Confirm Effect>
确认命中但未造成伤害时触发


<Custom React Effect>
value -= 100;
value -= user.def;
</Custom React Effect>
被确认命中但未造成伤害时触发

<Custom Respond Effect>
code
code
</Custom Respond Effect>
被确认命中并造成伤害时触发

<Custom Establish Effect>
code
code
</Custom Establish Effect>
确认命中且造成伤害时触发


<Custom Deselect Effect>
code
code
</Custom Deselect Effect>
被选中并一切结算之后时触发

<Custom Conclude Effect>
code
code
</Custom Conclude Effect>
选中并一切结算之后时触发





Skill core

<Pre-Damage Eval>
code
code
</Pre-Damage Eval>  造成伤害前生效

<Post-Damage Eval>
code
code
</Post-Damage Eval> 造成伤害后生效
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
2608
在线时间
314 小时
注册时间
2022-3-24
帖子
115
22
 楼主| 发表于 2023-4-14 00:58:52 | 只看该作者
半夜更新一个新技能,琢磨了很久总算做出来了。
我将其命名为:电力爆发  相应的状态命名为:电气引擎  是给游戏里使用雷魔法战斗的角色使用的技能
该技能效果为:当角色处于该状态时,初始会获得20层充能。每进行一次普攻获得30层充能,每释放一次技能获得20层充能。充能层数越高,电力爆发的威力越大,在使用电力爆发后所有层数清零。
灵感取自于LOL的电刀,具体效果如下:
需要用到的插件为:战斗核心,状态核心,技能核心。一个技能,一个状态。
首先是状态:电气引擎
<Custom Apply Effect>
target._motordrive = target._motordrive || 0;   //定义电气引擎层数变量并赋值
target._motordrive += 20;   //初始层数为20
user.setStateCounter(185, 20);  //层数计数,185为本状态ID
user.clampStateCounter(185, 0, 100);  //限制层数在0~100内
</Custom Apply Effect>


<Custom Confirm Effect>
var skills = [];  //定义数组skills
skills.push(313); //将电力爆发的技能ID(此处为313)放入skills数组
if (this.isAttack() && target.isActor() !== user.isActor()) {  //判断角色是否进行普攻且对象为敌人
  user.addStateCounter(185, 30);  //计数+30
  user.clampStateCounter(185, 0, 100);
  target._motordrive += 30; //电气引擎变量+30
}else if (this.isSkill() && (skills.contains(this.item().id)) && target.isActor() !== user.isActor()){  //如果角色不是普攻,那么判断角色是否使用了技能,且该技能是313号电力爆发,且目标为敌人
user.setStateCounter(185, 0);  //计数清零
user.clampStateCounter(185, 0, 100);
target._motordrive = 0; //变量清零
}else if (this.isSkill() && target.isActor() !== user.isActor()) {  //如果角色不是普攻,且没有使用电力爆发,但使用了技能且对象为敌人
  user.addStateCounter(185, 20);  //计数+20
  user.clampStateCounter(185, 0, 100);  
  target._motordrive += 20; //变量+20
}
</Custom Confirm Effect>

技能电力爆发的设置如下:
<Damage Formula>
target._motordrive = target._motordrive || 0;  //获取电气引擎中电气引擎的变量
value = Math.floor(user.mat * (target._motordrive * 0.2 + 1));  //定义伤害公式,此处的伤害为角色魔力*(1+电气引擎层数*0.2)并向下取整。
</Damage Formula>

此技能可以设置的更加灵活,例如让角色进行防御,受到伤害,受到治疗等等情况都叠加电气引擎层数,应该可以做的更加有深度。
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
2608
在线时间
314 小时
注册时间
2022-3-24
帖子
115
23
 楼主| 发表于 2023-4-14 09:44:22 | 只看该作者
本帖最后由 zhufeng233 于 2023-4-14 09:52 编辑

翻译一下YEP范例中的电刀,昨天设计的技能是根据YEP电刀的范例修改而来的。
LOL中电刀的效果为:角色的移动会增加6点充能,每次攻击也会增加充能(应该会吧,很久没玩LOL了),当充能达到100时下一次平A会附带一个雷电魔法伤害,并且该伤害会有类似闪电链的链接伤害效果。
因为RM的回合制中并不存在“移动”这一概念,所以YEP将移动获取的充能改成了角色HP,MP,TP发生变化时充能+6,以下是YEP的范例,我对注释进行了翻译并添加了一些额外的注释,如有错误请指出。
该技能需要:状态核心,战斗核心

<Custom Regenerate Effect>
// 提升6点充能.
user.addStateCounter(stateId, 6);
// 将充能范围限制在0~100,stateID是用作记录充能的状态
user.clampStateCounter(stateId, 0, 100);
</Custom Regenerate Effect>

<Custom Confirm Effect>
// 如果是一次普通攻击且目标为敌人
if (this.isAttack() && target.isActor() !== user.isActor()) {
  // 提升12点充能
  user.addStateCounter(stateId, 12);
  // 限制充能范围为0~100
  user.clampStateCounter(stateId, 0, 100);
  // 如果充能达到或超过了100(即充能完毕)
  if (user.getStateCounter(stateId) >= 100) {
    // 清除所有充能
    user.removeStateCounter(stateId);
    // 定义电刀伤害的元素类型,你可以根据自己数据库里的属性类型自由定义,可以做成火刀水刀土刀都行。
    var elementId = 5;
    // 定义额外伤害的数值
    var damage = user.mat * 2;
    // 如果造成了暴击
    if (target.result().critical) {
      // 则这个额外伤害也造成暴击
      damage = this.applyCritical(damage);
    }
    // 获取所有还活着的敌人
    var members = this.opponentsUnit().aliveMembers();
    // 移除掉被选中的那个目标
    members.splice(members.indexOf(target), 1);
    // 播放电刀效果动画
    target.startAnimation(77);
    // 提升电刀伤害
    value += Math.ceil(damage * target.elementRate(elementId));
    // 额外命中四个目标(也就是电刀链接伤害会链接到另外四个敌人身上)
    var extraTargets = 4;
    // 对这四个目标进行循环
    while (extraTargets--) {
      // 随机从四个目标中选一个
      var member = members[Math.floor(Math.random() * members.length)];
      // 确定该目标存在
      if (member) {
        // 播放动画
        member.startAnimation(77);
        // 让这个目标受到链接伤害
        member.gainHp(-Math.ceil(damage * member.elementRate(elementId)));
        // 跳出伤害数字
        member.startDamagePopup();
        // 清除结果
        member.clearResult();
        // 将这个目标从候选目标中排除
        members.splice(members.indexOf(member), 1);
        // 如果这个目标死了
        if (member.isDead()) {
          // If the member is dead, have it collapse.(这一段没有理解,这段指令是让角色倒下显示消失动画,但角色已经死亡为何还要再写一段这个指令呢?)
          member.performCollapse();
        }
      }
    }
  }
}
</Custom Confirm Effect>
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
2608
在线时间
314 小时
注册时间
2022-3-24
帖子
115
24
 楼主| 发表于 2023-4-14 23:51:08 | 只看该作者
彻底晕厥,想要用YEP范例中的Dualcast,也就是双重吟唱。但别说自己改了,哪怕直接套用YEP的范例也没用,一开始怀疑是插件版本落后了,换上了最新的版本,然后怀疑是工程环境的问题重新新建了一个原版环境依然不行,真不知道是哪里出了毛病
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
2608
在线时间
314 小时
注册时间
2022-3-24
帖子
115
25
 楼主| 发表于 2023-4-14 23:54:05 | 只看该作者
<Custom Action Start Effect>
// If a chained action is stored...
if ($gameTemp._chainAction === undefined) {
  // ...then set the action to the user's current action.
  $gameTemp._chainAction = user.currentAction();
} else {
  // ...then clear the stored action.
  $gameTemp._chainAction = undefined;
}
</Custom Action Start Effect>

<Custom Action End Effect>
// If a chained action is stored...
if ($gameTemp._chainAction) {
  // Set the 'action' variable to the chained action.
  var action = $gameTemp._chainAction;
  // Check if the action exists, is a skill, and is a magical attack.
  if (action && action.isSkill() && action.isMagical()) {
    // Get the skill used for that action.
    var skill = action.item();
    // Check if the user can pay the skill cost.
    if (user.canPaySkillCost(skill)) {
      // Check if the battle system is DTB.
      if (BattleManager.isDTB()) {
        // If it is, add the action to queue.
        user.setAction(0, action);
      // If the battle system isn't DTB...
      } else {
        // ...make it a forced forced.
        BattleManager.queueForceAction(user, skill.id, -2);
      }
    }
  }
}
</Custom Action End Effect>

<Custom Remove Effect>
// Clear the chained action effect.
$gameTemp._chainAction = undefined;
</Custom Remove Effect>

YEP的范例,我盯着看了好久也没看出哪里有问题,但实际用起来就是不行,跪求有大佬指点迷津
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
811
在线时间
117 小时
注册时间
2018-8-25
帖子
95
26
发表于 2023-4-15 04:51:56 | 只看该作者
zhufeng233 发表于 2023-4-12 22:19
目前只做出了前半部分的效果

敌人是否死亡会有个死亡状态,编辑器里默认是1号,可以在动作序列里用if target.isStateAffected(X)判断目标是否处于设定的死亡状态,如果有就是死亡了随机攻击其他目标一次,没有就再攻击一次
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
2608
在线时间
314 小时
注册时间
2022-3-24
帖子
115
27
 楼主| 发表于 2023-4-15 15:49:15 | 只看该作者
之前更新的一些技能和状态虽然逻辑上不复杂难度也不高,但对于一些完全没有接触过编程的小伙伴来说可能还是有些抽象,其实自己有做一些功能很简单的技能和状态,原本觉得没什么发出来的价值,但可能对完全没有基础的小伙伴来说能起一些帮助。
有考虑过逐句解析一下各个语句的具体作用,但其实我对js完全没有了解,对其它语言的编程水平也不高,如果讲起来肯定会有相当多的错误,就不误人子弟,仅单纯的分享一些范例好了。
这种非常简单的范例我就说的更详细一些,还会附上一些插件的使用方法,针对完全一点都不懂YEP插件和编程的小伙伴。但因为我也是初学者,可能会有错误,请大家指出

先分享两个:
第一个是YEP范例里有的,仿制了LOL中安妮的Q技能。
当该技能击杀目标后,会返还该技能消耗的蓝量。
需要用到的插件有:技能核心,立即释放(可选)

初学者可能会疑惑,在这些代码中类似于<Post-Damage Eval>或者其他的类似这种的标识到底起何作用。
按照我个人的理解,这些通常是起一个“时点”的作用,玩过游戏王的朋友应该清楚这个概念,说白了就是控制效果具体在哪个阶段生效的。
以<Post-Damage Eval>为例,在<Post-Damage Eval>和</Post-Damage Eval>之间的所有代码,只会在技能对敌人造成伤害后才生效。
也就是说,如果这个技能没有造成伤害(例如miss了,被敌人防反了),那么这段代码就不会生效。具体这些东西对应哪些时点,我上面都有翻译,其实YEP的插件说明里也写的非常详细,是很好理解的一个东西。

<Post-Damage Eval>  //在造成伤害之后生效。为何用这个时点很好理解,我要确定我这个技能杀死了敌人,那当然是要在造成伤害后。
if (target.hp <= 0) {  //如果敌人生命值小于等于0则执行下面的指令。if else语句是非常基础且常用的编程语句,如果连这个都不清楚的话可以把它想象成RM里的“分支条件”,效果上几乎差不多。要是连分支条件是什么都不知道……那还是别急着用插件了。
  user.gainMp(item.mpCost);  //给予使用者该技能消耗的MP值。 user就是使用者,上面语句中target就是目标,target.hp就是目标生命值的意思,user.gainMp就是使用者获得MP的意思,其实这种语句直接把单词翻译一下都能知道大概起什么作用,不要因为看见                  
                                          // 编程语句就感觉很困难很复杂,只要肯自己花点心思,这些都是小儿科。
}
</Post-Damage Eval>  

<Instant Cast>  // 立即释放标志。有立即释放插件的话,这个技能就会变成不消耗行动数可以直接释放的技能。

第二个:用MP来顶伤害。就是受到攻击时角色可以用MP来顶替掉一部分HP的损失。称为魔力护盾
需要的插件有:状态核心

<Custom React Effect> // 被确定命中,但未造成伤害时生效。选这个时点也很好理解,我要用MP来代替HP的损失,所以要先判断敌人这一招真的命中我了,然后在造成伤害之前判定我的MP去代替HP伤害
if (value > 0 && this.isHpEffect()) {  // 如果这次攻击的伤害值大于0且是对生命值的一次攻击
  var mpDmg = Math.floor(value * 0.85); // 定义变量mpDmg。var就是定义变量的指令,后面的mpDmg是变量名称,名称随便叫什么都好,只要你自己看得懂且不与其他变量冲突想叫什么叫什么。Math.floor()函数的作用是向下取整,以免伤害出现小数
                                                           // 这里定义,让MP去承担本次伤害的85%,如果你改成1,那就是完全用MP去承受伤害。
  mpDmg = Math.min(mpDmg, target.mp);  // Math.min()函数是判断两个函数的大小,取里面最小的那个。也就是考虑到角色MP不足以承担85%的伤害时,那就有多少承担多少。
  target.gainMp(-mpDmg);  // 给予角色MP伤害
  value -= mpDmg;  // 再让原本应该造成的伤害减去角色损失的MP
  if (target.mp === 0) {  // 当角色MP归零时
    target.removeState(71);  // 移除魔力护盾的buff
  }
}
</Custom React Effect>
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
285
在线时间
74 小时
注册时间
2022-12-4
帖子
194
28
发表于 2023-4-15 17:12:32 | 只看该作者
2669483303 发表于 2023-4-15 04:51
敌人是否死亡会有个死亡状态,编辑器里默认是1号,可以在动作序列里用if target.isStateAffected(X)判断 ...

我发现其实我设想的这个技能的之前逻辑有问题。应该是技能攻击结算效果后,然后判定敌人的血量,是 >0还是 <=0 ,然后再判断行动是否再攻击一次。我还没试出来,准备今天再试试
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
285
在线时间
74 小时
注册时间
2022-12-4
帖子
194
29
发表于 2023-4-15 18:40:19 | 只看该作者
zhufeng233 发表于 2023-4-15 15:49
之前更新的一些技能和状态虽然逻辑上不复杂难度也不高,但对于一些完全没有接触过编程的小伙伴来 ...

我看了你这段解释,然后试着写那个技能,就是给敌人造成伤害,杀死它后,再普通攻击一次
<Post-Damage Eval>
if(target.hp <= 0){
            user.startAnimation(1)
            var 1: existing enemies;
            target.startDamagePopup();
            }else{user.removeState(13)}
</Post-Damage Eval>
现在的结果是不通过。。。。。显示bug准备再学习下
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
2608
在线时间
314 小时
注册时间
2022-3-24
帖子
115
30
 楼主| 发表于 2023-4-15 23:48:33 | 只看该作者
woliebe 发表于 2023-4-15 18:40
我看了你这段解释,然后试着写那个技能,就是给敌人造成伤害,杀死它后,再普通攻击一次

if(target.hp  ...

老哥,我又尝试了几个小时,实在是有点黔驴技穷了,目前做出来的效果是角色攻击后如果目标没有死亡就会追击一次同等伤害的攻击,但不论目标有没有死亡都会再追加一次普通攻击的伤害。
我目前的能力实在是做不到灵活的判断技能的生效范围,其实理论上最简单的方式是用强制攻击:BattleManager.queueForceAction(user, skillid, -2);
但是强制攻击这个东西bug非常非常多,我在多次测试后发现,如果用if判断角色生命值和是否死亡,里面再写强制攻击,那被第一次攻击的目标会强行不死,剩0血就是没死,真的非常之离谱。
走到这一步我也真是想不出别的法子了,可能还要等进一步学习吧,我把目前做出的效果放出来
要用到技能核心,伤害核心和范围核心:

<Damage Formula>
this._commondamage = this._commondamage || 0;
this._skilldamage = user.mat * 2 + 1000;
value = this._commondamage || this._skilldamage;
var successRate = 0.3;
if(!target.isDead() && target.hp > 0 && this._commondamage == 0){
  if(Math.random() < successRate){
    target.gainHp(-value);
    target.startDamagePopup();
  }
}
this._commondamage = user.atk * 2;
</Damage Formula>

<Custom Target Eval>
targets.push(target);
var members = foes.aliveMembers();
members.splice(members.indexOf(target), 1);
var member = members[Math.floor(Math.random() * members.length)];
if (member) {
  targets.push(member);
  members.splice(members.indexOf(member), 1);
}
}
</Custom Target Eval>
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-17 11:40

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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