本帖最后由 Hueihuea 于 2021-2-15 20:01 编辑
前言:
老问题了 NPC脚本到底发编程开发呢 还是MOD教程呢 考虑之前一直发MOD教程 那么方便查阅 这次也发MOD教程好了
正文:
传统艺能 放点DEMO By @不二语



根据传统 我们马上放代码记得先设置成木偶职业哦
复制代码
主要特色:
示例附在代码尾部注释
来自群组: CNPC Script Studio
前言:
老问题了 NPC脚本到底发编程开发呢 还是MOD教程呢 考虑之前一直发MOD教程 那么方便查阅 这次也发MOD教程好了
正文:
传统艺能 放点DEMO By @不二语
根据传统 我们马上放代码记得先设置成木偶职业哦
- /**
- * @author Hueihuea(mchhui)
- * @description 请把本代码段至于引用之前。
- * 2020.10.16
- */
- /**
- * @description 动画列表
- * @description 警告 线程不安全 请勿在运行后修改
- */
- function MovementList() {
- var LinkedList = Java.type("java.util.LinkedList");
- this.lastFrame = 0;
- this.movements = new LinkedList();
- /**
- * @description 添加一帧动画
- * @param {"int"} frame 动画在第几帧
- * @param {"int"} part 运动那一部分 0:头 1:左手 2:右手 3:身体 4:左腿 5:右腿
- * @param {"int"} yaw X轴旋转
- * @param {"int"} pitch Y轴旋转
- * @param {"int"} rool Z轴旋转
- * @param {boolean} update 是否更新 默认false
- * @return {"MovementList"} this 返回自己
- */
- this.add = function (frame, part, yaw, pitch, rool, update) {
- if (update == null) {
- update = false;
- }
- if (frame < this.lastFrame) {
- throw "动画必须是有序的";
- }
- if (yaw != 0 && yaw % 360 == 0) {
- yaw = 360;
- } else {
- yaw %= 360;
- if (yaw < 0) {
- yaw += 360;
- }
- }
- if (pitch != 0 && pitch % 360 == 0) {
- pitch = 360;
- } else {
- pitch %= 360;
- if (pitch < 0) {
- pitch += 360;
- }
- }
- if (rool != 0 && rool % 360 == 0) {
- rool = 360;
- } else {
- rool %= 360;
- if (rool < 0) {
- rool += 360;
- }
- }
- this.lastFrame = frame;
- this.movements.add(new Movement(frame, part, yaw, pitch, rool, update));
- return this;
- }
- /**
- * @description 添加一系列动画
- * @param {"ChainMovement"} chainMovement
- * @return {"MovementList"} this 返回自己
- */
- this.addChainMovement = function (chainMovement) {
- var frameLine = chainMovement.endFrame - chainMovement.startFrame;
- var yawLine = chainMovement.endYaw - chainMovement.startYaw;
- var pitchLine = chainMovement.endPitch - chainMovement.startPitch;
- var roolLine = chainMovement.endRool - chainMovement.startRool;
- var yawVelocityCurveFunction = chainMovement.yawVelocityCurveFunction;
- var pitchVelocityCurveFunction = chainMovement.pitchVelocityCurveFunction;
- var roolVelocityCurveFunction = chainMovement.roolVelocityCurveFunction;
- for (var frame = chainMovement.startFrame; frame <= chainMovement.endFrame; frame += chainMovement.spacing) {
- this.add(frame, chainMovement.part,
- chainMovement.startYaw + yawLine * yawVelocityCurveFunction((frame - chainMovement.startFrame) / frameLine),
- chainMovement.startPitch + pitchLine * pitchVelocityCurveFunction((frame - chainMovement.startFrame) / frameLine),
- chainMovement.startRool + roolLine * roolVelocityCurveFunction((frame - chainMovement.startFrame) / frameLine), true);
- }
- return this;
- }
- }
- /**
- * @description 一帧动画 你不应该调用本函数
- */
- function Movement(frame, part, yaw, pitch, rool, update) {
- this.frame = frame;
- this.part = part;
- this.yaw = yaw;
- this.pitch = pitch;
- this.rool = rool;
- this.update = update;
- }
- Movement.HEAD = 0;
- Movement.LEFTARM = 1;
- Movement.RIGHTARM = 2;
- Movement.BODY = 3;
- Movement.LEFTLEG = 4;
- Movement.RIGHTLEG = 5;
- /**
- *@description 一系列动画
- */
- function ChainMovement() {
- this.startFrame;
- this.endFrame;
- this.spacing = 1;
- this.part;
- this.startYaw;
- this.startPitch;
- this.startRool;
- this.endYaw;
- this.endPitch;
- this.endRool;
- this.yawVelocityCurveFunction = function (x) { return x };
- this.pitchVelocityCurveFunction = function (x) { return x };
- this.roolVelocityCurveFunction = function (x) { return x };
- /**
- * @description 设置开始帧和结束帧
- * @param {"int"} startFrame 开始帧
- * @param {"int"} endFrame 结束帧
- * @return {"ChainMovement"} this 返回自己
- */
- this.setFrames = function (startFrame, endFrame) {
- this.startFrame = startFrame;
- this.endFrame = endFrame;
- return this;
- }
- /**
- * @description 设置每帧间距 默认是1
- * @param {*} spacing 间距
- * @return {"ChainMovement"} this 返回自己
- */
- this.setSpacing = function (spacing) {
- this.spacing = spacing;
- return this;
- }
- /**
- * @description 设置动画
- * @param {"int"} part 运动那一部分 0:头 1:左手 2:右手 3:身体 4:左腿 5:右腿
- * @param {"int"} startYaw 开始yaw
- * @param {"int"} startPitch 开始pitch
- * @param {"int"} startRool 开始rool
- * @param {"int"} endYaw 结束yaw
- * @param {"int"} endPitch 结束pitch
- * @param {"int"} endRool 结束rool
- * @return {"ChainMovement"} this 返回自己
- */
- this.setMovements = function (part, startYaw, startPitch, startRool, endYaw, endPitch, endRool) {
- this.part = part;
- this.startYaw = startYaw;
- this.startPitch = startPitch;
- this.startRool = startRool;
- this.endYaw = endYaw;
- this.endPitch = endPitch;
- this.endRool = endRool;
- return this;
- }
- /**
- * @description 设置yaw速度曲线 应该接受x 返回y
- * @description y=f(x)
- * @description x是0-1的数 表示时间 0是开始 1是结束
- * @description y是0-1的数 表示动画完成进度 0是开始 1是结束
- * @param {"Function"} func 速度曲线函数
- * @return {"ChainMovement"} 返回自己
- */
- this.setYawVelocityCurveFunction = function (func) {
- this.yawVelocityCurveFunction = func;
- return this;
- }
- /**
- * @description 设置pitch速度曲线 应该接受x 返回y
- * @description y=f(x)
- * @description x是0-1的数 表示时间 0是开始 1是结束
- * @description y是0-1的数 表示动画完成进度 0是开始 1是结束
- * @param {"Function"} func 速度曲线函数
- * @return {"ChainMovement"} 返回自己
- */
- this.setPitchVelocityCurveFunction = function (func) {
- this.pitchVelocityCurveFunction = func;
- return this;
- }
- /**
- * @description 设置rool速度曲线 应该接受x 返回y
- * @description y=f(x)
- * @description x是0-1的数 表示时间 0是开始 1是结束
- * @description y是0-1的数 表示动画完成进度 0是开始 1是结束
- * @param {"Function"} func 速度曲线函数
- * @return {"ChainMovement"} 返回自己
- */
- this.setRoolVelocityCurveFunction = function (func) {
- this.roolVelocityCurveFunction = func;
- return this;
- }
- }
- /**
- * @description 动画播放器
- * @param {"NpcEvent"} event npc的事件(1.7.10直接写npc对象)
- * @param {"MovementList"} movementList 动画列表
- * @param {"int"} fps FPS
- * @param {"boolean"} oldVersion 1.7.10模式
- */
- function MovementPlayer(event, movementList, fps, oldVersion) {
- var isStop = false;
- var running = false;
- var instance = this;
- if (oldVersion == null) {
- oldVersion = false;
- }
- /**
- * @description 开始播放动画
- */
- if (oldVersion) {
- var temp = event;
- event = new Object();
- event.npc = temp;
- }
- this.start = function (dontUpdate) {
- dontUpdate = (dontUpdate == null) ? true : dontUpdate;
- if (event.npc != null) {
- var typePuppet = 9;
- if (oldVersion) {
- typePuppet = 8;
- }
- if (event.npc.job.getType() != typePuppet) {
- return;
- }
- } else {
- return;
- }
- if (running && !isStop) {
- throw "有一个动画正在运行";
- }
- var Thread = Java.type("java.lang.Thread");
- var MyRun = Java.extend(Java.type("java.lang.Runnable"), {
- run: function () {
- var frames = movementList.movements;
- var npc = event.npc;
- var FPS = (fps != null) ? fps : 50;
- var callbackFunction = instance.callback;
- var iterator = frames.iterator();
- var frame;
- var amplifier = 1;
- var lastFrame;
- var flag = true;
- var Server;
- var EnumPacketClient;
- var FMLCommonHandler;
- var Minecraft;
- if (!npc.world.getMCWorld().field_72995_K) {
- Minecraft = Java.type("net.minecraft.client.Minecraft");
- }
- if (oldVersion) {
- Server = Java.type("noppes.npcs.Server");
- EnumPacketClient = Java.type("noppes.npcs.constants.EnumPacketClient");
- FMLCommonHandler = Java.type("cpw.mods.fml.common.FMLCommonHandler");
- } else {
- FMLCommonHandler = Java.type("net.minecraftforge.fml.common.FMLCommonHandler");
- }
- running = true;
- while (iterator.hasNext() && !isStop) {
- while (FMLCommonHandler.instance().getSide().isClient()) {
- if (!Minecraft.func_71410_x().func_147113_T()) {
- break;
- }
- }
- if (frame != null) {
- lastFrame = frame.frame;
- }
- frame = iterator.next();
- if (flag) {
- flag = false;
- } else {
- amplifier = frame.frame - lastFrame;
- if (amplifier < 0) {
- amplifier = 0;
- }
- }
- if (oldVersion) {
- var tempPart = frame.part;
- if (frame.part == 1) {
- tempPart = 2;
- } else if (frame.part == 2) {
- tempPart = 3;
- } else if (frame.part == 3) {
- tempPart = 1;
- }
- npc.job.setRotationX(tempPart, frame.yaw);
- npc.job.setRotationY(tempPart, frame.pitch);
- npc.job.setRotationZ(tempPart, frame.rool);
- } else {
- npc.job.getPart(frame.part).setRotation(
- frame.yaw,
- frame.pitch,
- frame.rool);
- if (!npc.world.getMCWorld().field_72995_K) {
- Minecraft.func_71410_x().field_71441_e.func_73045_a(npc.getMCEntity().func_145782_y()).jobInterface.getPart(frame.part).setRotation(
- frame.yaw,
- frame.pitch,
- frame.rool);
- }
- }
- if (frame.update && !dontUpdate) {
- if (oldVersion) {
- var compound = npc.getMCEntity().writeSpawnData();
- compound.func_74768_a("EntityId", npc.getMCEntity().func_145782_y());
- Server.sendAssociatedData(npc.getMCEntity(), EnumPacketClient.UPDATE_NPC, [compound]);
- } else {
- if (npc.world.getMCWorld().field_72995_K) {
- npc.updateClient();
- }
- }
- }
- if (iterator.hasNext()) {
- Thread.sleep(1000 / FPS * amplifier);
- }
- }
- callbackFunction(isStop, npc);
- isStop = false;
- running = false;
- }
- });
- new Thread(new MyRun()).start()
- }
- /**
- * @description 回调函数
- * @param {boolean} isStop 动画是否被强制终止
- * @param {"ICustomNpc"} npc 执行动画的npc
- * @return {void}
- */
- this.callback = function (isStop, npc) {
- }
- /**
- * @description 返回是否正在运行
- */
- this.isRunning = function () {
- return running && !isStop;
- }
- /**
- * @description 强制终止动画
- * @return {void}
- */
- this.stop = function () {
- if (!this.isRunning()) {
- throw "没有动画在运行";
- }
- isStop = true;
- }
- }
- /**
- *@description 执行木偶动画
- *@param CustomNPCsEvent event:事件对象
- *@param String[] movements:动画配置
- *@param int fps:一秒播放多少帧
- *@description 动画配置示例:"0.head,0,0,0,true" "帧.部位,yaw,pitch,roll,是否更新(可选)"
- */
- function playMovements_old(event, movements, fps) {
- var isStop = false;
- this.start = function () {
- if (event.npc != null) {
- var typePuppet = 9;
- if (event.npc.job.getType() != typePuppet) {
- return;
- }
- } else {
- return;
- }
- var str;
- for (var x in movements) {
- str = movements[x];
- str = str.replace("head", 0);
- str = str.replace("leftarm", 1);
- str = str.replace("rightarm", 2);
- str = str.replace("body", 3);
- str = str.replace("leftleg", 4);
- str = str.replace("rightleg", 5);
- if (str.search(/[A-Za-z]+/) >= 0) {
- throw "An error in line " + x + "."
- }
- movements[x] = str;
- }
- var Thread = Java.type("java.lang.Thread");
- var MyRun = Java.extend(Java.type("java.lang.Runnable"), {
- run: function () {
- var frames = movements;
- var npc = event.npc;
- var parameterFrame = 0;
- var parameterValue = 1;
- var parameterValuePart = 0;
- var parameterValuePitch = 1;
- var parameterValueYaw = 2;
- var parameterValueRoll = 3;
- var parameterValueRefresh = 4;
- var FPS = (fps != null) ? fps : 50;
- this.getParameters = (
- function (str) {
- var parameters = str.split(".");
- parameters[parameterValue] = parameters[parameterValue].split(",");
- parameters[parameterFrame] = parseInt(parameters[parameterFrame]);
- parameters[parameterValueRefresh] = (parameters[parameterValueRefresh] != null) ? parameters[parameterValueRefresh] : true;
- for (var x in parameters[parameterValue]) {
- parameters[parameterValue][x] = parseInt(parameters[parameterValue][x]);
- }
- return parameters;
- }
- );
- for (var frame = 0; frames.length > 0; frame++) {
- if (isStop) {
- return;
- }
- var parameters = this.getParameters(frames[0])
- if (parameters[parameterFrame] == frame) {
- frames.shift();
- npc.job.getPart(parameters[parameterValue][parameterValuePart]).setRotation(
- parameters[parameterValue][parameterValueYaw],
- parameters[parameterValue][parameterValuePitch],
- parameters[parameterValue][parameterValueRoll]);
- if (parameters[parameterValueRefresh] != 0) {
- npc.updateClient();
- }
- }
- Thread.sleep(1000 / FPS);//50fps(0.02*1000)
- }
- }
- });
- new Thread(new MyRun()).start()
- }
- this.stop = function () {
- isStop = true;
- }
- /*
- *执行木偶动画
- *CustomNPCsEvent event:事件对象
- *String[] movements:动画配置
- *int fps:一秒播放多少帧
- *动画配置示例:"0.head,0,0,0,true" "帧.部位,yaw,pitch,roll,是否更新(可选)"
- */
- }
- function setTimeout(fn, millis) {
- var Thread = Java.type("java.lang.Thread");
- var MyRun = Java.extend(Java.type("java.lang.Runnable"), {
- run: function () {
- Thread.sleep(millis)
- try {
- fn.apply();
- } catch (err) { throw err; }
- }
- });
- new Thread(new MyRun()).start()
- //延迟millis毫秒执行fn
- /*
- *function fn:要运行的function对象
- *int millis:延迟的毫秒
- */
- }
- /*
- 附示例:
- //示例一
- var wave = new MovementList();
- for (var i = 0; i < 40; i++) {
- wave.add(i, Movement.RIGHTARM, 0, 0, 170 - i, true);
- }
- for (var i = 0; i < 40; i++) {
- wave.add(40 + i, Movement.RIGHTARM, 0, 0, 130 + i, true);
- }
- wave.add(80, Movement.RIGHTARM, 0, 0, 0, true);
- function interact(event) {
- var mmPlayer = new MovementPlayer(event, wave, 60);
- //自定义回调函数 isStop表示动画是否被强制终止
- mmPlayer.callback = function (isStop, npc) {
- npc.say("hello world");
- }
- mmPlayer.start();
- }
- //示例二
- var waveRight = new MovementList();
- var waveLeft = new MovementList();
- //自动补充动画
- waveRight.addChainMovement(new ChainMovement().setFrames(0, 10).setMovements(Movement.RIGHTARM, 0, 0, 170, 0, 0, 140));
- waveRight.addChainMovement(new ChainMovement().setFrames(10, 20).setMovements(Movement.RIGHTARM, 0, 0, 140, 0, 0, 170));
- waveRight.addChainMovement(new ChainMovement().setFrames(20, 30).setMovements(Movement.RIGHTARM, 0, 0, 170, 0, 0, 140));
- waveRight.addChainMovement(new ChainMovement().setFrames(30, 40).setMovements(Movement.RIGHTARM, 0, 0, 140, 0, 0, 170));
- //waveRight.addChainMovement(new ChainMovement().setFrames(40, 50).setMovements(Movement.RIGHTARM, 0, 0, 170, 0, 0, 140));
- waveRight.addChainMovement(new ChainMovement().setFrames(50, 60).setMovements(Movement.RIGHTARM, 0, 0, 140, 0, 0, 170));
- waveRight.addChainMovement(new ChainMovement().setFrames(60, 80).setMovements(Movement.RIGHTARM, 0, 0, 170, 0, 0, 0)
- .setRoolVelocityCurveFunction(function (x) {
- return Math.sqrt(x);
- }));
- waveLeft.addChainMovement(new ChainMovement().setFrames(0, 10).setMovements(Movement.LEFTARM, 0, 0, 360 - 170, 0, 0, 360 - 140));
- waveLeft.addChainMovement(new ChainMovement().setFrames(10, 20).setMovements(Movement.LEFTARM, 0, 0, 360 - 140, 0, 0, 360 - 170));
- waveLeft.addChainMovement(new ChainMovement().setFrames(20, 30).setMovements(Movement.LEFTARM, 0, 0, 360 - 170, 0, 0, 360 - 140));
- waveLeft.addChainMovement(new ChainMovement().setFrames(30, 40).setMovements(Movement.LEFTARM, 0, 0, 360 - 140, 0, 0, 360 - 170));
- waveLeft.addChainMovement(new ChainMovement().setFrames(40, 50).setMovements(Movement.LEFTARM, 0, 0, 360 - 170, 0, 0, 360 - 140));
- waveLeft.addChainMovement(new ChainMovement().setFrames(50, 60).setMovements(Movement.LEFTARM, 0, 0, 360 - 140, 0, 0, 360 - 170));
- waveLeft.addChainMovement(new ChainMovement().setFrames(60, 80).setMovements(Movement.LEFTARM, 0, 0, 360 - 170, 0, 0, 360 - 0)
- .setRoolVelocityCurveFunction(function (x) {
- return Math.sqrt(x);
- }));
- function interact(event) {
- var mmPlayer = new MovementPlayer(event, waveRight, 10);
- mmPlayer.callback=function(isStop,npc){
- npc.say("右手完事了");
- }
- mmPlayer.start();
- mmPlayer = new MovementPlayer(event, waveLeft, 10);
- mmPlayer.callback=function(isStop,npc){
- npc.say("左手完事了");
- }
- mmPlayer.start();
- }
- //示例三(1.7.10)
- var waveRight = new MovementList();
- var waveLeft = new MovementList();
- //自动补充动画
- waveRight.addChainMovement(new ChainMovement().setFrames(0, 10).setMovements(Movement.RIGHTARM, 0, 360, 350, 0, 360, 320));
- waveRight.addChainMovement(new ChainMovement().setFrames(10, 20).setMovements(Movement.RIGHTARM, 0, 360, 320, 0, 360, 350));
- waveRight.addChainMovement(new ChainMovement().setFrames(20, 30).setMovements(Movement.RIGHTARM, 0, 360, 350, 0, 360, 320));
- waveRight.addChainMovement(new ChainMovement().setFrames(30, 40).setMovements(Movement.RIGHTARM, 0, 360, 320, 0, 360, 350));
- waveRight.addChainMovement(new ChainMovement().setFrames(40, 50).setMovements(Movement.RIGHTARM, 0, 360, 350, 0, 360, 320));
- waveRight.addChainMovement(new ChainMovement().setFrames(50, 60).setMovements(Movement.RIGHTARM, 0, 360, 320, 0, 360, 350));
- waveRight.addChainMovement(new ChainMovement().setFrames(60, 80).setMovements(Movement.RIGHTARM, 0, 360, 350, 180, 180, 180));
- waveLeft.addChainMovement(new ChainMovement().setFrames(0, 60).setMovements(Movement.LEFTARM, 0, 0, 360 - 350, 0, 0, 360 - 320).setRoolVelocityCurveFunction(function (x) {
- if (parseInt(60 * x / 10) % 2 == 0) {
- return 60 * x % 10 / 10;
- }
- return 1 - 60 * x % 10 / 10;
- }));
- waveLeft.addChainMovement(new ChainMovement().setFrames(60, 80).setMovements(Movement.LEFTARM, 0, 0, 10, 180, 180, 180));
- var mmPlayer = new MovementPlayer(npc, waveRight, 30, true);
- mmPlayer.callback = function (isStop, npc) {
- npc.say("右手完事了");
- }
- mmPlayer.start();
- mmPlayer = new MovementPlayer(npc, waveLeft, 30, true);
- mmPlayer.callback = function (isStop, npc) {
- npc.say("左手完事了");
- }
- mmPlayer.start();
- */
主要特色:
- 支持自动渐变填充空白帧
- 支持渐变函数
- 支持回调函数
示例附在代码尾部注释
来自群组: CNPC Script Studio
来抢个灰佬贴的沙发
太强了吧我去
灰佬牛逼
灰佬牛逼
搶沙發,技術革新前排
属实牛逼,就是我们这种编程小白玩不了了啊啊啊啊
本帖最后由 诺言T 于 2020-12-16 12:23 编辑
灰灰yyds!
灰灰yyds!
灰灰yyds!
谢谢大佬写这么个脚本为了让我们运用方便,由衷的感谢!QWQ
好家伙~可以用这个做动画了
很详细的教程,感谢分享
很不错的教程,感谢分享
很不错的教程,感谢分享
真不错,还能这样啊
这个有意思啊,可以在副本里面做一些丰富剧情,🐮
很不错的教程,感谢分享
太强了太强了捏
说起来将示例丢进去npc脚本上,职业也设置好了,前置也放了,但是启用一点反应都没有,这会是版本问题么(脚本没有报错)