Hueihuea
本帖最后由 Hueihuea 于 2021-2-15 20:01 编辑

前言:
老问题了 NPC脚本到底发编程开发呢 还是MOD教程呢 考虑之前一直发MOD教程 那么方便查阅 这次也发MOD教程好了

正文:


传统艺能 放点DEMO By @不二语





根据传统 我们马上放代码记得先设置成木偶职业哦


  1. /**
  2. * @author Hueihuea(mchhui)
  3. * @description 请把本代码段至于引用之前。
  4. * 2020.10.16
  5. */

  6. /**
  7. * @description 动画列表
  8. * @description 警告 线程不安全 请勿在运行后修改
  9. */
  10. function MovementList() {
  11.   var LinkedList = Java.type("java.util.LinkedList");
  12.   this.lastFrame = 0;
  13.   this.movements = new LinkedList();
  14.   /**
  15.    * @description 添加一帧动画
  16.    * @param {"int"} frame 动画在第几帧
  17.    * @param {"int"} part 运动那一部分 0:头 1:左手 2:右手 3:身体 4:左腿 5:右腿
  18.    * @param {"int"} yaw X轴旋转
  19.    * @param {"int"} pitch Y轴旋转
  20.    * @param {"int"} rool Z轴旋转
  21.    * @param {boolean} update 是否更新 默认false
  22.    * @return {"MovementList"} this 返回自己
  23.    */
  24.   this.add = function (frame, part, yaw, pitch, rool, update) {
  25.     if (update == null) {
  26.       update = false;
  27.     }
  28.     if (frame < this.lastFrame) {
  29.       throw "动画必须是有序的";
  30.     }
  31.     if (yaw != 0 && yaw % 360 == 0) {
  32.       yaw = 360;
  33.     } else {
  34.       yaw %= 360;
  35.       if (yaw < 0) {
  36.         yaw += 360;
  37.       }
  38.     }
  39.     if (pitch != 0 && pitch % 360 == 0) {
  40.       pitch = 360;
  41.     } else {
  42.       pitch %= 360;
  43.       if (pitch < 0) {
  44.         pitch += 360;
  45.       }
  46.     }
  47.     if (rool != 0 && rool % 360 == 0) {
  48.       rool = 360;
  49.     } else {
  50.       rool %= 360;
  51.       if (rool < 0) {
  52.         rool += 360;
  53.       }
  54.     }
  55.     this.lastFrame = frame;
  56.     this.movements.add(new Movement(frame, part, yaw, pitch, rool, update));
  57.     return this;
  58.   }

  59.   /**
  60.    * @description 添加一系列动画
  61.    * @param {"ChainMovement"} chainMovement
  62.    * @return {"MovementList"} this 返回自己
  63.    */
  64.   this.addChainMovement = function (chainMovement) {
  65.     var frameLine = chainMovement.endFrame - chainMovement.startFrame;
  66.     var yawLine = chainMovement.endYaw - chainMovement.startYaw;
  67.     var pitchLine = chainMovement.endPitch - chainMovement.startPitch;
  68.     var roolLine = chainMovement.endRool - chainMovement.startRool;
  69.     var yawVelocityCurveFunction = chainMovement.yawVelocityCurveFunction;
  70.     var pitchVelocityCurveFunction = chainMovement.pitchVelocityCurveFunction;
  71.     var roolVelocityCurveFunction = chainMovement.roolVelocityCurveFunction;
  72.     for (var frame = chainMovement.startFrame; frame <= chainMovement.endFrame; frame += chainMovement.spacing) {
  73.       this.add(frame, chainMovement.part,
  74.         chainMovement.startYaw + yawLine * yawVelocityCurveFunction((frame - chainMovement.startFrame) / frameLine),
  75.         chainMovement.startPitch + pitchLine * pitchVelocityCurveFunction((frame - chainMovement.startFrame) / frameLine),
  76.         chainMovement.startRool + roolLine * roolVelocityCurveFunction((frame - chainMovement.startFrame) / frameLine), true);
  77.     }
  78.     return this;
  79.   }
  80. }

  81. /**
  82. * @description 一帧动画 你不应该调用本函数
  83. */
  84. function Movement(frame, part, yaw, pitch, rool, update) {
  85.   this.frame = frame;
  86.   this.part = part;
  87.   this.yaw = yaw;
  88.   this.pitch = pitch;
  89.   this.rool = rool;
  90.   this.update = update;
  91. }
  92. Movement.HEAD = 0;
  93. Movement.LEFTARM = 1;
  94. Movement.RIGHTARM = 2;
  95. Movement.BODY = 3;
  96. Movement.LEFTLEG = 4;
  97. Movement.RIGHTLEG = 5;

  98. /**
  99. *@description 一系列动画
  100. */
  101. function ChainMovement() {
  102.   this.startFrame;
  103.   this.endFrame;
  104.   this.spacing = 1;
  105.   this.part;
  106.   this.startYaw;
  107.   this.startPitch;
  108.   this.startRool;
  109.   this.endYaw;
  110.   this.endPitch;
  111.   this.endRool;
  112.   this.yawVelocityCurveFunction = function (x) { return x };
  113.   this.pitchVelocityCurveFunction = function (x) { return x };
  114.   this.roolVelocityCurveFunction = function (x) { return x };
  115.   /**
  116.    * @description 设置开始帧和结束帧
  117.    * @param {"int"} startFrame 开始帧
  118.    * @param {"int"} endFrame 结束帧
  119.    * @return {"ChainMovement"} this 返回自己
  120.    */
  121.   this.setFrames = function (startFrame, endFrame) {
  122.     this.startFrame = startFrame;
  123.     this.endFrame = endFrame;
  124.     return this;
  125.   }

  126.   /**
  127.    * @description 设置每帧间距 默认是1
  128.    * @param {*} spacing 间距
  129.    * @return {"ChainMovement"} this 返回自己
  130.    */
  131.   this.setSpacing = function (spacing) {
  132.     this.spacing = spacing;
  133.     return this;
  134.   }
  135.   /**
  136.    * @description 设置动画
  137.    * @param {"int"} part 运动那一部分 0:头 1:左手 2:右手 3:身体 4:左腿 5:右腿
  138.    * @param {"int"} startYaw 开始yaw
  139.    * @param {"int"} startPitch 开始pitch
  140.    * @param {"int"} startRool 开始rool
  141.    * @param {"int"} endYaw 结束yaw
  142.    * @param {"int"} endPitch 结束pitch
  143.    * @param {"int"} endRool 结束rool
  144.    * @return {"ChainMovement"} this 返回自己
  145.    */
  146.   this.setMovements = function (part, startYaw, startPitch, startRool, endYaw, endPitch, endRool) {
  147.     this.part = part;
  148.     this.startYaw = startYaw;
  149.     this.startPitch = startPitch;
  150.     this.startRool = startRool;
  151.     this.endYaw = endYaw;
  152.     this.endPitch = endPitch;
  153.     this.endRool = endRool;
  154.     return this;
  155.   }
  156.   /**
  157.    * @description 设置yaw速度曲线 应该接受x 返回y
  158.    * @description y=f(x)
  159.    * @description x是0-1的数 表示时间 0是开始 1是结束
  160.    * @description y是0-1的数 表示动画完成进度 0是开始 1是结束
  161.    * @param {"Function"} func 速度曲线函数
  162.    * @return {"ChainMovement"} 返回自己
  163.    */
  164.   this.setYawVelocityCurveFunction = function (func) {
  165.     this.yawVelocityCurveFunction = func;
  166.     return this;
  167.   }

  168.   /**
  169.    * @description 设置pitch速度曲线 应该接受x 返回y
  170.    * @description y=f(x)
  171.    * @description x是0-1的数 表示时间 0是开始 1是结束
  172.    * @description y是0-1的数 表示动画完成进度 0是开始 1是结束
  173.    * @param {"Function"} func 速度曲线函数
  174.    * @return {"ChainMovement"} 返回自己
  175.    */
  176.   this.setPitchVelocityCurveFunction = function (func) {
  177.     this.pitchVelocityCurveFunction = func;
  178.     return this;
  179.   }

  180.   /**
  181.    * @description 设置rool速度曲线 应该接受x 返回y
  182.    * @description y=f(x)
  183.    * @description x是0-1的数 表示时间 0是开始 1是结束
  184.    * @description y是0-1的数 表示动画完成进度 0是开始 1是结束
  185.    * @param {"Function"} func 速度曲线函数
  186.    * @return {"ChainMovement"} 返回自己
  187.    */
  188.   this.setRoolVelocityCurveFunction = function (func) {
  189.     this.roolVelocityCurveFunction = func;
  190.     return this;
  191.   }
  192. }

  193. /**
  194. * @description 动画播放器
  195. * @param {"NpcEvent"} event npc的事件(1.7.10直接写npc对象)
  196. * @param {"MovementList"} movementList 动画列表
  197. * @param {"int"} fps FPS
  198. * @param {"boolean"} oldVersion 1.7.10模式
  199. */
  200. function MovementPlayer(event, movementList, fps, oldVersion) {
  201.   var isStop = false;
  202.   var running = false;
  203.   var instance = this;

  204.   if (oldVersion == null) {
  205.     oldVersion = false;
  206.   }

  207.   /**
  208.    * @description 开始播放动画
  209.    */
  210.   if (oldVersion) {
  211.     var temp = event;
  212.     event = new Object();
  213.     event.npc = temp;
  214.   }
  215.   this.start = function (dontUpdate) {
  216.     dontUpdate = (dontUpdate == null) ? true : dontUpdate;
  217.     if (event.npc != null) {
  218.       var typePuppet = 9;
  219.       if (oldVersion) {
  220.         typePuppet = 8;
  221.       }
  222.       if (event.npc.job.getType() != typePuppet) {
  223.         return;
  224.       }
  225.     } else {
  226.       return;
  227.     }

  228.     if (running && !isStop) {
  229.       throw "有一个动画正在运行";
  230.     }
  231.     var Thread = Java.type("java.lang.Thread");
  232.     var MyRun = Java.extend(Java.type("java.lang.Runnable"), {
  233.       run: function () {
  234.         var frames = movementList.movements;
  235.         var npc = event.npc;
  236.         var FPS = (fps != null) ? fps : 50;
  237.         var callbackFunction = instance.callback;
  238.         var iterator = frames.iterator();
  239.         var frame;
  240.         var amplifier = 1;
  241.         var lastFrame;
  242.         var flag = true;
  243.         var Server;
  244.         var EnumPacketClient;
  245.         var FMLCommonHandler;
  246.         var Minecraft;
  247.         if (!npc.world.getMCWorld().field_72995_K) {
  248.           Minecraft = Java.type("net.minecraft.client.Minecraft");
  249.         }


  250.         if (oldVersion) {
  251.           Server = Java.type("noppes.npcs.Server");
  252.           EnumPacketClient = Java.type("noppes.npcs.constants.EnumPacketClient");
  253.           FMLCommonHandler = Java.type("cpw.mods.fml.common.FMLCommonHandler");
  254.         } else {
  255.           FMLCommonHandler = Java.type("net.minecraftforge.fml.common.FMLCommonHandler");
  256.         }

  257.         running = true;
  258.         while (iterator.hasNext() && !isStop) {
  259.           while (FMLCommonHandler.instance().getSide().isClient()) {
  260.             if (!Minecraft.func_71410_x().func_147113_T()) {
  261.               break;
  262.             }
  263.           }
  264.           if (frame != null) {
  265.             lastFrame = frame.frame;
  266.           }
  267.           frame = iterator.next();
  268.           if (flag) {
  269.             flag = false;
  270.           } else {
  271.             amplifier = frame.frame - lastFrame;
  272.             if (amplifier < 0) {
  273.               amplifier = 0;
  274.             }
  275.           }

  276.           if (oldVersion) {
  277.             var tempPart = frame.part;
  278.             if (frame.part == 1) {
  279.               tempPart = 2;
  280.             } else if (frame.part == 2) {
  281.               tempPart = 3;
  282.             } else if (frame.part == 3) {
  283.               tempPart = 1;
  284.             }
  285.             npc.job.setRotationX(tempPart, frame.yaw);
  286.             npc.job.setRotationY(tempPart, frame.pitch);
  287.             npc.job.setRotationZ(tempPart, frame.rool);
  288.           } else {
  289.             npc.job.getPart(frame.part).setRotation(
  290.               frame.yaw,
  291.               frame.pitch,
  292.               frame.rool);
  293.             if (!npc.world.getMCWorld().field_72995_K) {
  294.               Minecraft.func_71410_x().field_71441_e.func_73045_a(npc.getMCEntity().func_145782_y()).jobInterface.getPart(frame.part).setRotation(
  295.                 frame.yaw,
  296.                 frame.pitch,
  297.                 frame.rool);
  298.             }
  299.           }

  300.           if (frame.update && !dontUpdate) {
  301.             if (oldVersion) {
  302.               var compound = npc.getMCEntity().writeSpawnData();
  303.               compound.func_74768_a("EntityId", npc.getMCEntity().func_145782_y());
  304.               Server.sendAssociatedData(npc.getMCEntity(), EnumPacketClient.UPDATE_NPC, [compound]);
  305.             } else {
  306.               if (npc.world.getMCWorld().field_72995_K) {
  307.                 npc.updateClient();
  308.               }
  309.             }
  310.           }
  311.           if (iterator.hasNext()) {
  312.             Thread.sleep(1000 / FPS * amplifier);
  313.           }
  314.         }
  315.         callbackFunction(isStop, npc);
  316.         isStop = false;
  317.         running = false;
  318.       }
  319.     });
  320.     new Thread(new MyRun()).start()
  321.   }
  322.   /**
  323.    * @description 回调函数
  324.    * @param {boolean} isStop 动画是否被强制终止
  325.    * @param {"ICustomNpc"} npc 执行动画的npc
  326.    * @return {void}
  327.    */
  328.   this.callback = function (isStop, npc) {

  329.   }

  330.   /**
  331.   * @description 返回是否正在运行
  332.   */
  333.   this.isRunning = function () {
  334.     return running && !isStop;
  335.   }

  336.   /**
  337.    * @description 强制终止动画
  338.    * @return {void}
  339.    */
  340.   this.stop = function () {
  341.     if (!this.isRunning()) {
  342.       throw "没有动画在运行";
  343.     }
  344.     isStop = true;
  345.   }
  346. }


  347. /**
  348. *@description 执行木偶动画
  349. *@param CustomNPCsEvent event:事件对象
  350. *@param String[] movements:动画配置
  351. *@param int fps:一秒播放多少帧
  352. *@description 动画配置示例:"0.head,0,0,0,true" "帧.部位,yaw,pitch,roll,是否更新(可选)"
  353. */
  354. function playMovements_old(event, movements, fps) {
  355.   var isStop = false;
  356.   this.start = function () {
  357.     if (event.npc != null) {
  358.       var typePuppet = 9;
  359.       if (event.npc.job.getType() != typePuppet) {
  360.         return;
  361.       }
  362.     } else {
  363.       return;
  364.     }
  365.     var str;
  366.     for (var x in movements) {
  367.       str = movements[x];
  368.       str = str.replace("head", 0);
  369.       str = str.replace("leftarm", 1);
  370.       str = str.replace("rightarm", 2);
  371.       str = str.replace("body", 3);
  372.       str = str.replace("leftleg", 4);
  373.       str = str.replace("rightleg", 5);
  374.       if (str.search(/[A-Za-z]+/) >= 0) {
  375.         throw "An error in line " + x + "."
  376.       }
  377.       movements[x] = str;
  378.     }

  379.     var Thread = Java.type("java.lang.Thread");
  380.     var MyRun = Java.extend(Java.type("java.lang.Runnable"), {
  381.       run: function () {
  382.         var frames = movements;
  383.         var npc = event.npc;
  384.         var parameterFrame = 0;
  385.         var parameterValue = 1;
  386.         var parameterValuePart = 0;
  387.         var parameterValuePitch = 1;
  388.         var parameterValueYaw = 2;
  389.         var parameterValueRoll = 3;
  390.         var parameterValueRefresh = 4;
  391.         var FPS = (fps != null) ? fps : 50;
  392.         this.getParameters = (
  393.           function (str) {
  394.             var parameters = str.split(".");
  395.             parameters[parameterValue] = parameters[parameterValue].split(",");
  396.             parameters[parameterFrame] = parseInt(parameters[parameterFrame]);
  397.             parameters[parameterValueRefresh] = (parameters[parameterValueRefresh] != null) ? parameters[parameterValueRefresh] : true;

  398.             for (var x in parameters[parameterValue]) {
  399.               parameters[parameterValue][x] = parseInt(parameters[parameterValue][x]);
  400.             }
  401.             return parameters;
  402.           }
  403.         );
  404.         for (var frame = 0; frames.length > 0; frame++) {
  405.           if (isStop) {
  406.             return;
  407.           }
  408.           var parameters = this.getParameters(frames[0])
  409.           if (parameters[parameterFrame] == frame) {
  410.             frames.shift();
  411.             npc.job.getPart(parameters[parameterValue][parameterValuePart]).setRotation(
  412.               parameters[parameterValue][parameterValueYaw],
  413.               parameters[parameterValue][parameterValuePitch],
  414.               parameters[parameterValue][parameterValueRoll]);
  415.             if (parameters[parameterValueRefresh] != 0) {
  416.               npc.updateClient();
  417.             }
  418.           }
  419.           Thread.sleep(1000 / FPS);//50fps(0.02*1000)
  420.         }
  421.       }
  422.     });
  423.     new Thread(new MyRun()).start()
  424.   }

  425.   this.stop = function () {
  426.     isStop = true;
  427.   }
  428.   /*
  429.   *执行木偶动画
  430.   *CustomNPCsEvent event:事件对象
  431.   *String[] movements:动画配置
  432.   *int fps:一秒播放多少帧
  433.   *动画配置示例:"0.head,0,0,0,true" "帧.部位,yaw,pitch,roll,是否更新(可选)"
  434.   */
  435. }

  436. function setTimeout(fn, millis) {
  437.   var Thread = Java.type("java.lang.Thread");
  438.   var MyRun = Java.extend(Java.type("java.lang.Runnable"), {
  439.     run: function () {
  440.       Thread.sleep(millis)
  441.       try {
  442.         fn.apply();
  443.       } catch (err) { throw err; }
  444.     }
  445.   });
  446.   new Thread(new MyRun()).start()
  447.   //延迟millis毫秒执行fn
  448.   /*
  449.   *function fn:要运行的function对象
  450.   *int millis:延迟的毫秒
  451.   */
  452. }

  453. /*
  454. 附示例:

  455. //示例一

  456. var wave = new MovementList();
  457. for (var i = 0; i < 40; i++) {
  458.   wave.add(i, Movement.RIGHTARM, 0, 0, 170 - i, true);
  459. }
  460. for (var i = 0; i < 40; i++) {
  461.   wave.add(40 + i, Movement.RIGHTARM, 0, 0, 130 + i, true);
  462. }
  463. wave.add(80, Movement.RIGHTARM, 0, 0, 0, true);
  464. function interact(event) {
  465.   var mmPlayer = new MovementPlayer(event, wave, 60);
  466.   //自定义回调函数 isStop表示动画是否被强制终止
  467.   mmPlayer.callback = function (isStop, npc) {
  468.     npc.say("hello world");
  469.   }
  470.   mmPlayer.start();
  471. }


  472. //示例二

  473. var waveRight = new MovementList();
  474. var waveLeft = new MovementList();
  475. //自动补充动画
  476. waveRight.addChainMovement(new ChainMovement().setFrames(0, 10).setMovements(Movement.RIGHTARM, 0, 0, 170, 0, 0, 140));
  477. waveRight.addChainMovement(new ChainMovement().setFrames(10, 20).setMovements(Movement.RIGHTARM, 0, 0, 140, 0, 0, 170));
  478. waveRight.addChainMovement(new ChainMovement().setFrames(20, 30).setMovements(Movement.RIGHTARM, 0, 0, 170, 0, 0, 140));
  479. waveRight.addChainMovement(new ChainMovement().setFrames(30, 40).setMovements(Movement.RIGHTARM, 0, 0, 140, 0, 0, 170));
  480. //waveRight.addChainMovement(new ChainMovement().setFrames(40, 50).setMovements(Movement.RIGHTARM, 0, 0, 170, 0, 0, 140));
  481. waveRight.addChainMovement(new ChainMovement().setFrames(50, 60).setMovements(Movement.RIGHTARM, 0, 0, 140, 0, 0, 170));
  482. waveRight.addChainMovement(new ChainMovement().setFrames(60, 80).setMovements(Movement.RIGHTARM, 0, 0, 170, 0, 0, 0)
  483.   .setRoolVelocityCurveFunction(function (x) {
  484.     return Math.sqrt(x);
  485.   }));
  486. waveLeft.addChainMovement(new ChainMovement().setFrames(0, 10).setMovements(Movement.LEFTARM, 0, 0, 360 - 170, 0, 0, 360 - 140));
  487. waveLeft.addChainMovement(new ChainMovement().setFrames(10, 20).setMovements(Movement.LEFTARM, 0, 0, 360 - 140, 0, 0, 360 - 170));
  488. waveLeft.addChainMovement(new ChainMovement().setFrames(20, 30).setMovements(Movement.LEFTARM, 0, 0, 360 - 170, 0, 0, 360 - 140));
  489. waveLeft.addChainMovement(new ChainMovement().setFrames(30, 40).setMovements(Movement.LEFTARM, 0, 0, 360 - 140, 0, 0, 360 - 170));
  490. waveLeft.addChainMovement(new ChainMovement().setFrames(40, 50).setMovements(Movement.LEFTARM, 0, 0, 360 - 170, 0, 0, 360 - 140));
  491. waveLeft.addChainMovement(new ChainMovement().setFrames(50, 60).setMovements(Movement.LEFTARM, 0, 0, 360 - 140, 0, 0, 360 - 170));
  492. waveLeft.addChainMovement(new ChainMovement().setFrames(60, 80).setMovements(Movement.LEFTARM, 0, 0, 360 - 170, 0, 0, 360 - 0)
  493.   .setRoolVelocityCurveFunction(function (x) {
  494.     return Math.sqrt(x);
  495.   }));
  496. function interact(event) {
  497.   var mmPlayer = new MovementPlayer(event, waveRight, 10);
  498.   mmPlayer.callback=function(isStop,npc){
  499.     npc.say("右手完事了");
  500.   }
  501.   mmPlayer.start();
  502.   mmPlayer = new MovementPlayer(event, waveLeft, 10);
  503.   mmPlayer.callback=function(isStop,npc){
  504.     npc.say("左手完事了");
  505.   }
  506.   mmPlayer.start();
  507. }


  508. //示例三(1.7.10)
  509. var waveRight = new MovementList();
  510. var waveLeft = new MovementList();
  511. //自动补充动画
  512. waveRight.addChainMovement(new ChainMovement().setFrames(0, 10).setMovements(Movement.RIGHTARM, 0, 360, 350, 0, 360, 320));
  513. waveRight.addChainMovement(new ChainMovement().setFrames(10, 20).setMovements(Movement.RIGHTARM, 0, 360, 320, 0, 360, 350));
  514. waveRight.addChainMovement(new ChainMovement().setFrames(20, 30).setMovements(Movement.RIGHTARM, 0, 360, 350, 0, 360, 320));
  515. waveRight.addChainMovement(new ChainMovement().setFrames(30, 40).setMovements(Movement.RIGHTARM, 0, 360, 320, 0, 360, 350));
  516. waveRight.addChainMovement(new ChainMovement().setFrames(40, 50).setMovements(Movement.RIGHTARM, 0, 360, 350, 0, 360, 320));
  517. waveRight.addChainMovement(new ChainMovement().setFrames(50, 60).setMovements(Movement.RIGHTARM, 0, 360, 320, 0, 360, 350));
  518. waveRight.addChainMovement(new ChainMovement().setFrames(60, 80).setMovements(Movement.RIGHTARM, 0, 360, 350, 180, 180, 180));
  519. waveLeft.addChainMovement(new ChainMovement().setFrames(0, 60).setMovements(Movement.LEFTARM, 0, 0, 360 - 350, 0, 0, 360 - 320).setRoolVelocityCurveFunction(function (x) {
  520.   if (parseInt(60 * x / 10) % 2 == 0) {
  521.     return 60 * x % 10 / 10;
  522.   }
  523.   return 1 - 60 * x % 10 / 10;
  524. }));
  525. waveLeft.addChainMovement(new ChainMovement().setFrames(60, 80).setMovements(Movement.LEFTARM, 0, 0, 10, 180, 180, 180));
  526. var mmPlayer = new MovementPlayer(npc, waveRight, 30, true);
  527. mmPlayer.callback = function (isStop, npc) {
  528.   npc.say("右手完事了");
  529. }
  530. mmPlayer.start();
  531. mmPlayer = new MovementPlayer(npc, waveLeft, 30, true);
  532. mmPlayer.callback = function (isStop, npc) {
  533.   npc.say("左手完事了");
  534. }
  535. mmPlayer.start();
  536. */



复制代码

主要特色:


示例附在代码尾部注释




来自群组: CNPC Script Studio

玫兰蒂斯
来抢个灰佬贴的沙发

荒-漠
太强了吧我去

灰佬牛逼

Xue_Se_
搶沙發,技術革新前排

j531065605
属实牛逼,就是我们这种编程小白玩不了了啊啊啊啊

诺言T
本帖最后由 诺言T 于 2020-12-16 12:23 编辑

灰灰yyds!

无尽の咸羊
灰灰yyds!

淑芳
谢谢大佬写这么个脚本为了让我们运用方便,由衷的感谢!QWQ

啦啦德古拉
好家伙~可以用这个做动画了

454564啊
很详细的教程,感谢分享

Zinllen
很不错的教程,感谢分享

popsugar
很不错的教程,感谢分享

ddggh55
真不错,还能这样啊

芜湖氵人
这个有意思啊,可以在副本里面做一些丰富剧情,🐮

Y南栀向寒Y
很不错的教程,感谢分享

jeirse
太强了太强了捏

Colin_Sakuya
说起来将示例丢进去npc脚本上,职业也设置好了,前置也放了,但是启用一点反应都没有,这会是版本问题么(脚本没有报错)

Hueihuea
Colin_Sakuya 发表于 2022-5-29 11:19
说起来将示例丢进去npc脚本上,职业也设置好了,前置也放了,但是启用一点反应都没有,这会是版本问题么( ...

你啥版本 怎么写的

国威国威
我看不懂,但我大受震撼

15465532
不错的教程,感谢分享,看懂了,不会做qwq

雪妖谜
不错不错有意思

Colin_Sakuya
Hueihuea 发表于 2022-5-30 00:00
你啥版本 怎么写的

1.12.2 05jul20版本,把示例前面的内容丢进去,然后放入示例1,没效果也没报错

Hueihuea
Colin_Sakuya 发表于 2022-6-10 15:25
1.12.2 05jul20版本,把示例前面的内容丢进去,然后放入示例1,没效果也没报错 ...

复制你的代码给我看

Colin_Sakuya
Hueihuea 发表于 2022-6-10 23:24
复制你的代码给我看

  1. /**
  2. * [url=home.php?mod=space&uid=1231151]@author[/url] Hueihuea(mchhui)
  3. * @description 请把本代码段至于引用之前。
  4. * 2020.10.16
  5. */

  6. /**
  7. * @description 动画列表
  8. * @description 警告 线程不安全 请勿在运行后修改
  9. */
  10. function MovementList() {
  11.   var LinkedList = Java.type("java.util.LinkedList");
  12.   this.lastFrame = 0;
  13.   this.movements = new LinkedList();
  14.   /**
  15.    * @description 添加一帧动画
  16.    * @param {"int"} frame 动画在第几帧
  17.    * @param {"int"} part 运动那一部分 0:头 1:左手 2:右手 3:身体 4:左腿 5:右腿
  18.    * @param {"int"} yaw X轴旋转
  19.    * @param {"int"} pitch Y轴旋转
  20.    * @param {"int"} rool Z轴旋转
  21.    * @param {boolean} update 是否更新 默认false
  22.    * [url=home.php?mod=space&uid=491268]@Return[/url] {"MovementList"} this 返回自己
  23.    */
  24.   this.add = function (frame, part, yaw, pitch, rool, update) {
  25.     if (update == null) {
  26.       update = false;
  27.     }
  28.     if (frame < this.lastFrame) {
  29.       throw "动画必须是有序的";
  30.     }
  31.     if (yaw != 0 && yaw % 360 == 0) {
  32.       yaw = 360;
  33.     } else {
  34.       yaw %= 360;
  35.       if (yaw < 0) {
  36.         yaw += 360;
  37.       }
  38.     }
  39.     if (pitch != 0 && pitch % 360 == 0) {
  40.       pitch = 360;
  41.     } else {
  42.       pitch %= 360;
  43.       if (pitch < 0) {
  44.         pitch += 360;
  45.       }
  46.     }
  47.     if (rool != 0 && rool % 360 == 0) {
  48.       rool = 360;
  49.     } else {
  50.       rool %= 360;
  51.       if (rool < 0) {
  52.         rool += 360;
  53.       }
  54.     }
  55.     this.lastFrame = frame;
  56.     this.movements.add(new Movement(frame, part, yaw, pitch, rool, update));
  57.     return this;
  58.   }

  59.   /**
  60.    * @description 添加一系列动画
  61.    * @param {"ChainMovement"} chainMovement
  62.    * @return {"MovementList"} this 返回自己
  63.    */
  64.   this.addChainMovement = function (chainMovement) {
  65.     var frameLine = chainMovement.endFrame - chainMovement.startFrame;
  66.     var yawLine = chainMovement.endYaw - chainMovement.startYaw;
  67.     var pitchLine = chainMovement.endPitch - chainMovement.startPitch;
  68.     var roolLine = chainMovement.endRool - chainMovement.startRool;
  69.     var yawVelocityCurveFunction = chainMovement.yawVelocityCurveFunction;
  70.     var pitchVelocityCurveFunction = chainMovement.pitchVelocityCurveFunction;
  71.     var roolVelocityCurveFunction = chainMovement.roolVelocityCurveFunction;
  72.     for (var frame = chainMovement.startFrame; frame <= chainMovement.endFrame; frame += chainMovement.spacing) {
  73.       this.add(frame, chainMovement.part,
  74.         chainMovement.startYaw + yawLine * yawVelocityCurveFunction((frame - chainMovement.startFrame) / frameLine),
  75.         chainMovement.startPitch + pitchLine * pitchVelocityCurveFunction((frame - chainMovement.startFrame) / frameLine),
  76.         chainMovement.startRool + roolLine * roolVelocityCurveFunction((frame - chainMovement.startFrame) / frameLine), true);
  77.     }
  78.     return this;
  79.   }
  80. }

  81. /**
  82. * @description 一帧动画 你不应该调用本函数
  83. */
  84. function Movement(frame, part, yaw, pitch, rool, update) {
  85.   this.frame = frame;
  86.   this.part = part;
  87.   this.yaw = yaw;
  88.   this.pitch = pitch;
  89.   this.rool = rool;
  90.   this.update = update;
  91. }
  92. Movement.HEAD = 0;
  93. Movement.LEFTARM = 1;
  94. Movement.RIGHTARM = 2;
  95. Movement.BODY = 3;
  96. Movement.LEFTLEG = 4;
  97. Movement.RIGHTLEG = 5;

  98. /**
  99. *@description 一系列动画
  100. */
  101. function ChainMovement() {
  102.   this.startFrame;
  103.   this.endFrame;
  104.   this.spacing = 1;
  105.   this.part;
  106.   this.startYaw;
  107.   this.startPitch;
  108.   this.startRool;
  109.   this.endYaw;
  110.   this.endPitch;
  111.   this.endRool;
  112.   this.yawVelocityCurveFunction = function (x) { return x };
  113.   this.pitchVelocityCurveFunction = function (x) { return x };
  114.   this.roolVelocityCurveFunction = function (x) { return x };
  115.   /**
  116.    * @description 设置开始帧和结束帧
  117.    * @param {"int"} startFrame 开始帧
  118.    * @param {"int"} endFrame 结束帧
  119.    * @return {"ChainMovement"} this 返回自己
  120.    */
  121.   this.setFrames = function (startFrame, endFrame) {
  122.     this.startFrame = startFrame;
  123.     this.endFrame = endFrame;
  124.     return this;
  125.   }

  126.   /**
  127.    * @description 设置每帧间距 默认是1
  128.    * @param {*} spacing 间距
  129.    * @return {"ChainMovement"} this 返回自己
  130.    */
  131.   this.setSpacing = function (spacing) {
  132.     this.spacing = spacing;
  133.     return this;
  134.   }
  135.   /**
  136.    * @description 设置动画
  137.    * @param {"int"} part 运动那一部分 0:头 1:左手 2:右手 3:身体 4:左腿 5:右腿
  138.    * @param {"int"} startYaw 开始yaw
  139.    * @param {"int"} startPitch 开始pitch
  140.    * @param {"int"} startRool 开始rool
  141.    * @param {"int"} endYaw 结束yaw
  142.    * @param {"int"} endPitch 结束pitch
  143.    * @param {"int"} endRool 结束rool
  144.    * @return {"ChainMovement"} this 返回自己
  145.    */
  146.   this.setMovements = function (part, startYaw, startPitch, startRool, endYaw, endPitch, endRool) {
  147.     this.part = part;
  148.     this.startYaw = startYaw;
  149.     this.startPitch = startPitch;
  150.     this.startRool = startRool;
  151.     this.endYaw = endYaw;
  152.     this.endPitch = endPitch;
  153.     this.endRool = endRool;
  154.     return this;
  155.   }
  156.   /**
  157.    * @description 设置yaw速度曲线 应该接受x 返回y
  158.    * @description y=f(x)
  159.    * @description x是0-1的数 表示时间 0是开始 1是结束
  160.    * @description y是0-1的数 表示动画完成进度 0是开始 1是结束
  161.    * @param {"Function"} func 速度曲线函数
  162.    * @return {"ChainMovement"} 返回自己
  163.    */
  164.   this.setYawVelocityCurveFunction = function (func) {
  165.     this.yawVelocityCurveFunction = func;
  166.     return this;
  167.   }

  168.   /**
  169.    * @description 设置pitch速度曲线 应该接受x 返回y
  170.    * @description y=f(x)
  171.    * @description x是0-1的数 表示时间 0是开始 1是结束
  172.    * @description y是0-1的数 表示动画完成进度 0是开始 1是结束
  173.    * @param {"Function"} func 速度曲线函数
  174.    * @return {"ChainMovement"} 返回自己
  175.    */
  176.   this.setPitchVelocityCurveFunction = function (func) {
  177.     this.pitchVelocityCurveFunction = func;
  178.     return this;
  179.   }

  180.   /**
  181.    * @description 设置rool速度曲线 应该接受x 返回y
  182.    * @description y=f(x)
  183.    * @description x是0-1的数 表示时间 0是开始 1是结束
  184.    * @description y是0-1的数 表示动画完成进度 0是开始 1是结束
  185.    * @param {"Function"} func 速度曲线函数
  186.    * @return {"ChainMovement"} 返回自己
  187.    */
  188.   this.setRoolVelocityCurveFunction = function (func) {
  189.     this.roolVelocityCurveFunction = func;
  190.     return this;
  191.   }
  192. }

  193. /**
  194. * @description 动画播放器
  195. * @param {"NpcEvent"} event npc的事件(1.7.10直接写npc对象)
  196. * @param {"MovementList"} movementList 动画列表
  197. * @param {"int"} fps FPS
  198. * @param {"boolean"} oldVersion 1.7.10模式
  199. */
  200. function MovementPlayer(event, movementList, fps, oldVersion) {
  201.   var isStop = false;
  202.   var running = false;
  203.   var instance = this;

  204.   if (oldVersion == null) {
  205.     oldVersion = false;
  206.   }

  207.   /**
  208.    * @description 开始播放动画
  209.    */
  210.   if (oldVersion) {
  211.     var temp = event;
  212.     event = new Object();
  213.     event.npc = temp;
  214.   }
  215.   this.start = function (dontUpdate) {
  216.     dontUpdate = (dontUpdate == null) ? true : dontUpdate;
  217.     if (event.npc != null) {
  218.       var typePuppet = 9;
  219.       if (oldVersion) {
  220.         typePuppet = 8;
  221.       }
  222.       if (event.npc.job.getType() != typePuppet) {
  223.         return;
  224.       }
  225.     } else {
  226.       return;
  227.     }

  228.     if (running && !isStop) {
  229.       throw "有一个动画正在运行";
  230.     }
  231.     var Thread = Java.type("java.lang.Thread");
  232.     var MyRun = Java.extend(Java.type("java.lang.Runnable"), {
  233.       run: function () {
  234.         var frames = movementList.movements;
  235.         var npc = event.npc;
  236.         var FPS = (fps != null) ? fps : 50;
  237.         var callbackFunction = instance.callback;
  238.         var iterator = frames.iterator();
  239.         var frame;
  240.         var amplifier = 1;
  241.         var lastFrame;
  242.         var flag = true;
  243.         var Server;
  244.         var EnumPacketClient;
  245.         var FMLCommonHandler;
  246.         var Minecraft;
  247.         if (!npc.world.getMCWorld().field_72995_K) {
  248.           Minecraft = Java.type("net.minecraft.client.Minecraft");
  249.         }


  250.         if (oldVersion) {
  251.           Server = Java.type("noppes.npcs.Server");
  252.           EnumPacketClient = Java.type("noppes.npcs.constants.EnumPacketClient");
  253.           FMLCommonHandler = Java.type("cpw.mods.fml.common.FMLCommonHandler");
  254.         } else {
  255.           FMLCommonHandler = Java.type("net.minecraftforge.fml.common.FMLCommonHandler");
  256.         }

  257.         running = true;
  258.         while (iterator.hasNext() && !isStop) {
  259.           while (FMLCommonHandler.instance().getSide().isClient()) {
  260.             if (!Minecraft.func_71410_x().func_147113_T()) {
  261.               break;
  262.             }
  263.           }
  264.           if (frame != null) {
  265.             lastFrame = frame.frame;
  266.           }
  267.           frame = iterator.next();
  268.           if (flag) {
  269.             flag = false;
  270.           } else {
  271.             amplifier = frame.frame - lastFrame;
  272.             if (amplifier < 0) {
  273.               amplifier = 0;
  274.             }
  275.           }

  276.           if (oldVersion) {
  277.             var tempPart = frame.part;
  278.             if (frame.part == 1) {
  279.               tempPart = 2;
  280.             } else if (frame.part == 2) {
  281.               tempPart = 3;
  282.             } else if (frame.part == 3) {
  283.               tempPart = 1;
  284.             }
  285.             npc.job.setRotationX(tempPart, frame.yaw);
  286.             npc.job.setRotationY(tempPart, frame.pitch);
  287.             npc.job.setRotationZ(tempPart, frame.rool);
  288.           } else {
  289.             npc.job.getPart(frame.part).setRotation(
  290.               frame.yaw,
  291.               frame.pitch,
  292.               frame.rool);
  293.             if (!npc.world.getMCWorld().field_72995_K) {
  294.               Minecraft.func_71410_x().field_71441_e.func_73045_a(npc.getMCEntity().func_145782_y()).jobInterface.getPart(frame.part).setRotation(
  295.                 frame.yaw,
  296.                 frame.pitch,
  297.                 frame.rool);
  298.             }
  299.           }

  300.           if (frame.update && !dontUpdate) {
  301.             if (oldVersion) {
  302.               var compound = npc.getMCEntity().writeSpawnData();
  303.               compound.func_74768_a("EntityId", npc.getMCEntity().func_145782_y());
  304.               Server.sendAssociatedData(npc.getMCEntity(), EnumPacketClient.UPDATE_NPC, [compound]);
  305.             } else {
  306.               if (npc.world.getMCWorld().field_72995_K) {
  307.                 npc.updateClient();
  308.               }
  309.             }
  310.           }
  311.           if (iterator.hasNext()) {
  312.             Thread.sleep(1000 / FPS * amplifier);
  313.           }
  314.         }
  315.         callbackFunction(isStop, npc);
  316.         isStop = false;
  317.         running = false;
  318.       }
  319.     });
  320.     new Thread(new MyRun()).start()
  321.   }
  322.   /**
  323.    * @description 回调函数
  324.    * @param {boolean} isStop 动画是否被强制终止
  325.    * @param {"ICustomNpc"} npc 执行动画的npc
  326.    * @return {void}
  327.    */
  328.   this.callback = function (isStop, npc) {

  329.   }

  330.   /**
  331.   * @description 返回是否正在运行
  332.   */
  333.   this.isRunning = function () {
  334.     return running && !isStop;
  335.   }

  336.   /**
  337.    * @description 强制终止动画
  338.    * @return {void}
  339.    */
  340.   this.stop = function () {
  341.     if (!this.isRunning()) {
  342.       throw "没有动画在运行";
  343.     }
  344.     isStop = true;
  345.   }
  346. }


  347. /**
  348. *@description 执行木偶动画
  349. *@param CustomNPCsEvent event:事件对象
  350. *@param String[] movements:动画配置
  351. *@param int fps:一秒播放多少帧
  352. *@description 动画配置示例:"0.head,0,0,0,true" "帧.部位,yaw,pitch,roll,是否更新(可选)"
  353. */
  354. function playMovements_old(event, movements, fps) {
  355.   var isStop = false;
  356.   this.start = function () {
  357.     if (event.npc != null) {
  358.       var typePuppet = 9;
  359.       if (event.npc.job.getType() != typePuppet) {
  360.         return;
  361.       }
  362.     } else {
  363.       return;
  364.     }
  365.     var str;
  366.     for (var x in movements) {
  367.       str = movements[x];
  368.       str = str.replace("head", 0);
  369.       str = str.replace("leftarm", 1);
  370.       str = str.replace("rightarm", 2);
  371.       str = str.replace("body", 3);
  372.       str = str.replace("leftleg", 4);
  373.       str = str.replace("rightleg", 5);
  374.       if (str.search(/[A-Za-z]+/) >= 0) {
  375.         throw "An error in line " + x + "."
  376.       }
  377.       movements[x] = str;
  378.     }

  379.     var Thread = Java.type("java.lang.Thread");
  380.     var MyRun = Java.extend(Java.type("java.lang.Runnable"), {
  381.       run: function () {
  382.         var frames = movements;
  383.         var npc = event.npc;
  384.         var parameterFrame = 0;
  385.         var parameterValue = 1;
  386.         var parameterValuePart = 0;
  387.         var parameterValuePitch = 1;
  388.         var parameterValueYaw = 2;
  389.         var parameterValueRoll = 3;
  390.         var parameterValueRefresh = 4;
  391.         var FPS = (fps != null) ? fps : 50;
  392.         this.getParameters = (
  393.           function (str) {
  394.             var parameters = str.split(".");
  395.             parameters[parameterValue] = parameters[parameterValue].split(",");
  396.             parameters[parameterFrame] = parseInt(parameters[parameterFrame]);
  397.             parameters[parameterValueRefresh] = (parameters[parameterValueRefresh] != null) ? parameters[parameterValueRefresh] : true;

  398.             for (var x in parameters[parameterValue]) {
  399.               parameters[parameterValue][x] = parseInt(parameters[parameterValue][x]);
  400.             }
  401.             return parameters;
  402.           }
  403.         );
  404.         for (var frame = 0; frames.length > 0; frame++) {
  405.           if (isStop) {
  406.             return;
  407.           }
  408.           var parameters = this.getParameters(frames[0])
  409.           if (parameters[parameterFrame] == frame) {
  410.             frames.shift();
  411.             npc.job.getPart(parameters[parameterValue][parameterValuePart]).setRotation(
  412.               parameters[parameterValue][parameterValueYaw],
  413.               parameters[parameterValue][parameterValuePitch],
  414.               parameters[parameterValue][parameterValueRoll]);
  415.             if (parameters[parameterValueRefresh] != 0) {
  416.               npc.updateClient();
  417.             }
  418.           }
  419.           Thread.sleep(1000 / FPS);//50fps(0.02*1000)
  420.         }
  421.       }
  422.     });
  423.     new Thread(new MyRun()).start()
  424.   }

  425.   this.stop = function () {
  426.     isStop = true;
  427.   }
  428.   /*
  429.   *执行木偶动画
  430.   *CustomNPCsEvent event:事件对象
  431.   *String[] movements:动画配置
  432.   *int fps:一秒播放多少帧
  433.   *动画配置示例:"0.head,0,0,0,true" "帧.部位,yaw,pitch,roll,是否更新(可选)"
  434.   */
  435. }

  436. function setTimeout(fn, millis) {
  437.   var Thread = Java.type("java.lang.Thread");
  438.   var MyRun = Java.extend(Java.type("java.lang.Runnable"), {
  439.     run: function () {
  440.       Thread.sleep(millis)
  441.       try {
  442.         fn.apply();
  443.       } catch (err) { throw err; }
  444.     }
  445.   });
  446.   new Thread(new MyRun()).start()
  447.   //延迟millis毫秒执行fn
  448.   /*
  449.   *function fn:要运行的function对象
  450.   *int millis:延迟的毫秒
  451.   */
  452. }  







  453. //示例一

  454. var wave = new MovementList();
  455. for (var i = 0; i < 40; i++) {
  456.   wave.add(i, Movement.RIGHTARM, 0, 0, 170 - i, true);
  457. }
  458. for (var i = 0; i < 40; i++) {
  459.   wave.add(40 + i, Movement.RIGHTARM, 0, 0, 130 + i, true);
  460. }
  461. wave.add(80, Movement.RIGHTARM, 0, 0, 0, true);
  462. function interact(event) {
  463.   var mmPlayer = new MovementPlayer(event, wave, 60);
  464.   //自定义回调函数 isStop表示动画是否被强制终止
  465.   mmPlayer.callback = function (isStop, npc) {
  466.     npc.say("hello world");
  467.   }
  468.   mmPlayer.start();
  469. }





复制代码

Hueihuea

你其他脚本可以用吗?能否用qq交流?

Colin_Sakuya
Hueihuea 发表于 2022-6-11 15:58
你其他脚本可以用吗?能否用qq交流?

其他脚本正常,我qq上呼你了,麻烦看下谢谢

绘图仪
哇还能这样玩

StGeorges
烦人的村民就是用的这个吗?

FubukiE
哈哈哈哈rpg服可以做剧情杀了

三重圆的黑暗
看来得好好研究一下了awa

GGYYZZ
这个可以做视频很好看了

xw51684
牛哇,太强了,我这种编程小白表示不会

ai你yong不老
Hueihuea 发表于 2022-6-10 23:24
复制你的代码给我看

同遇一样的问题 1.7.10的,设置成木偶,就丢了你的代码和实例3在“对话”脚本中测试    没作用

y天夏王魔大粉
辛苦作者大大