版本1.1

这个插件比较简单,主要是如何利用gmod事件编写。

首先是Gmod wiki连接:https://wiki.facepunch.com/gmod/

搜索hook就能找到这些事件。

第二,可以用vscode编辑gmod lua文件,vscode 有gmod lua插件,比较方便

vscode中的gmod插件

二段跳:在地面上按住空格键0.3s触发二段跳

玩家按键按下和弹起事件

boolean Player:KeyPressed( number key )
boolean Player:KeyReleased( number key )

利用hook.add(事件名,功能名,函数)添加事件的功能,函数可以像是下面这样的匿名函数

hook.Add("KeyPress", "DoubleJump_KeyValue",function( p, k)if ( k == IN_JUMP )  thenKeyJump_Value = 1//空格键值        end
end)hook.Add("KeyRelease", "Dishonored_DoubleJump_KeyValue",function( p, k)if ( k == IN_JUMP ) thenKeyJump_Value=0end
end)

hook.Remove(事件名,功能名)可以移除添加的功能。

以上代码就能获取玩家的跳跃键状态,如果说起跳时在地上,那么创建一个0.3s的定时器,定时器到期后判断跳跃键是否按下,如果满足条件就给玩家加个向上的速度。

timer. Create(名字,时长 , 执行次数, 函数)

hook.Add("KeyPress", "DoubleJump_KeyValue",function( p, k)if ( k == IN_JUMP )  thenKeyJump_Value = 1//空格键值        if p:OnGround() thentimer. Create("DoubleJump_Timer",0.3 , 1 , function ()if KeyJump_Value==1 and !p:OnGround() thenp:DoCustomAnimEvent(PLAYERANIMEVENT_JUMP , -1)//播放动作                     p:SetVelocity(Vector(0,0,500))//二段跳                    p:EmitSound(Sound("dishonoreddoublejump"..math.random(1, 3)..".mp3"), 100, 100)//播放音效endend)        endend
end)hook.Add("KeyRelease", "Dishonored_DoubleJump_KeyValue",function( p, k)if ( k == IN_JUMP ) thenKeyJump_Value=0end
end)

这样就实现了二段跳。

有些需要注意的:

1、某些函数只能在服务器端实现(也就是在lua/autorun/server/下或者用lua_openscript打开),比如设置速度。

2、对玩家来说,SetVelocity貌似是起到加速的作用,SetLocalVelocity才是设置速度

视角晃动功能:落地时视角晃动

在耻辱中,玩家掉到地上的话,视角会像果冻或者说弹簧那样晃动。这里用带阻尼的弹簧去模拟,视角的晃动量可以用数值法或符号法解

撞击地面事件和设置视角偏移函数:

boolean GM:OnPlayerHitGround( Entity player, boolean inWater, boolean onFloater, number speed )
Player:SetViewOffset( Vector viewOffset )
Player:SetCurrentViewOffset( Vector viewOffset )

这两个比较奇怪,站立时,第一个似乎只对Z方向偏移启作用,第二个只对XY方向启作用,

蹲下时,第二个对XYZ都起作用,第一个可能对XY方向其作用,两个可能需要结合着用。

再对晃动程度做个限制,直接限制初始条件的速度就行。

hook.Add("OnPlayerHitGround", "Dishonored_ShakeView", function( p,iW,oF,speed)//下坠视角震荡:弹簧加阻尼,数值求解if !sv_dj_a_sv:GetBool() then return endlocal damping=10//阻尼系数local k=100//弹性//PrintMessage(HUD_PRINTTALK,tostring(p:GetVelocity()) )local Origin=Vector(0,0,0)//原点local Vel=p:GetVelocity()*sv_dj_svg:GetFloat()//下坠速度local Acc=Vector(0,0,0)//加速度(弹簧)local ViewOffset=Originlocal Dt=0.015local SpeedLimit = sv_dj_svms:GetFloat()Vel[1]=math.Clamp(Vel[1], -SpeedLimit, SpeedLimit)Vel[2]=math.Clamp(Vel[2], -SpeedLimit, SpeedLimit)Vel[3]=math.Clamp(Vel[3], -SpeedLimit, SpeedLimit)timer.Create('Dishonored_view'..tostring(p['UserID']), Dt, 50, function()           ViewOffset=ViewOffset+(Vel + Acc*0.5*Dt)*Dt//二阶泰勒Acc=(Origin-ViewOffset)*k -damping*VelVel=Vel+Acc*Dt         p:SetViewOffset(ViewOffset+Vector(0,0,StandZOffset))//站立时,Z轴偏移立马生效,XY?  p:SetCurrentViewOffset(ViewOffset+Vector(0,0,DuckZOffset))//站立时,XY轴偏移立马生效,Z不生效。下蹲时对XYZ轴偏移立马生效//PrintMessage(HUD_PRINTTALK,tostring(ViewOffset) )end)
end)

这样就实现了视角晃动。

一些常数:

1、默认站立视角偏移(0,0,64)

2、默认蹲下视角偏移(0,0,28)

攀爬功能:

这里用TraceLine来判断,相当于射出一条线,然后返回线碰到的位置和法向量。

   Ck_L[i]=util.TraceLine({start = Vector(0,0,0),//起始位置endpos = Vector(0,0,100),//终止位置filter = LocalPlayer() //忽略实体:玩家})

那这任务相当于做一个避障判断,我不擅长这个,所以这插件BUG比较多。

这个事件每tick一次:

GM:Think()

这里8个tick检测一次。

检测

首先是水平扫描,在玩家位置创建一组间隔均匀、长度50左右的探测器

蹲着能通过的最大高度为36,为了不错过这个窗口,所以间隔为36的一半,当有探测器碰到了并且法向量Z值小于cos(45°),45°是能站稳的平面最小角度,这说明可能碰到障碍物,延长其他探测器以获得更多信息。

根据探测器的结果来判断哪个高度可能有可通行的路径,这里这样判断,上个与下个水平距离至少拉开10且不能再同一平面,防止以下情况。

通过点积与水平距离差来大致判断

通过后,再检测一下上面,由于没有准确的障碍物高度,所以大概判断一下,缝隙别太小就行

通过后利用二分法来搜索落脚点,实际上游戏环境比较复杂,而寥寥几次的Traceline信息量有限,所以必须做一些假设。

比较常见的障碍物形状差不多这样:

假设在障碍物上能找到个点将梯度符号给分割开来,然后类似找极值,对落脚点要求是能站住,并且高度也有一定要求,这样就比较简单了。

                         if Ck_div.HitPos[3] >= Z and Ck_div.HitNormal[3]>Cos_BanAngle thenclimb_Data['Pos'] = Ck_div.HitPosclimb_Data['Norm'] = Ck_div.HitNormalclimb_over = true//print('收敛')break end

收敛条件:对高度有点要求,大致判断一下能否站稳

nxor(eyeDir:Dot(Ck_div.HitNormal)>0 , Ck_div.HitNormal[3]>0)

变化率符号:这两非异或一下可以得到

再列举一些情况,减少BUG

找到落脚点后再大致判断一下这个点会不会卡住。

 //是否会卡住for i=0,1,1 dofor j=0,3,1 doCk = util.TraceLine({start = climb_Data['Pos'] + Vector(0,0,18)*i,endpos = climb_Data['Pos'] + Vector(0,0,18)*i + Temp[j],filter = p})if Ck.Hit and (Ck.HitNormal[3] < climb_Data['Cos_BanAngle'] or Ck.Normal:Dot(Ck.HitPos-Ck.StartPos)<12) thenif Debug then PrintMessage(HUD_PRINTTALK, '无效落脚点,距离:'..tostring(Ck.Normal:Dot(Ck.HitPos-Ck.StartPos))) endreturnendendend

落脚点判断完成了,做个抛物线插值到落脚点就可以了。

改变实体位置,只能在服务器端运行

Entity:SetPos( Vector position )

晃动玩家视角角度

Player:ViewPunch( Angle PunchAngle )

如果说检测是在客户端跑的,那就需要与服务器通信,比如说客户端发个定位,让服务器将玩家移动到那:

客户端:

net.Start("climb_over")net.WriteTable(climb_Data)
net.SendToServer()

服务器端:

util.AddNetworkString("climb_over")
net.Receive("climb_over", function(len,p)local climb_Data = net.ReadTable()//读取数据p:SetPos(climb_Data.Pos)
end)

类似用hook.add添加事件

创建菜单和控制台变量:

CreateConVar:创建控制台变量,如果已有就返回那个变量

第一个参数是名字,第二是默认值

FCVAR那些是变量的特性,wiki中可以查到

//添加控制台变量
CreateConVar( "sv_dj_a_dj", "1", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//允许二段跳
CreateConVar( "sv_dj_a_a1", "1", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//允许初级加速
CreateConVar( "sv_dj_a1", "100", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//初级弹速
CreateConVar( "sv_dj_a2", "300", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//二级弹速
CreateConVar( "sv_dj_g", "0.1", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//增益
CreateConVar( "sv_dj_dt", "0.3", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//延时CreateConVar( "sv_dj_a_sv", "1", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//允许摇晃视角
CreateConVar( "sv_dj_svg", "1", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//摇晃速度增益
CreateConVar( "sv_dj_svms", "1000", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//摇晃限制CreateConVar( "sv_dj_a_cl", "1", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//允许攀爬
CreateConVar( "sv_dj_sd", "50", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//水平扫描距离
CreateConVar( "sv_dj_sh", "72", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//不可跨越的高度
CreateConVar( "sv_dj_sg", "0.25", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//跨越距离增益
CreateConVar( "sv_dj_lt", "200", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//跨越判断-水平速度阈值
CreateConVar( "sv_dj_vt", "-200", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//跨越判断-垂直速度阈值
CreateConVar( "sv_dj_chs", "1", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//启动高攀音效
CreateConVar( "sv_dj_cls", "1", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//启动低攀音效
CreateConVar( "sv_dj_chvp", "30", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//高攀镜头晃动
CreateConVar( "sv_dj_clvp", "0", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//低攀镜头晃动CreateConVar( "sv_dj_a_rb", "1", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//允许反弹
CreateConVar( "sv_dj_rbg", "2", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//反弹增益
CreateConVar( "sv_dj_rbl", "84", { FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_SERVER_CAN_EXECUTE } )//头顶距离

添加控制台变量

Utilities是指添加到“设置”里

hook.Add("PopulateToolMenu", "djmenu", function()//添加菜单spawnmenu.AddToolMenuOption("Utilities", "耻辱跑跳(Dishonored_Jump)", "Dishonored_Jump", "配置(Config)", "", "", function(panel)panel:ClearControls()panel:Help("------------------二段跳(Double Jump)------------------")panel:CheckBox( "启用二段跳(Activate)", 'sv_dj_a_dj' )//复选框panel:CheckBox( "允许初级加速(Allow First Jump Gain)", 'sv_dj_a_a1' )panel:NumSlider( "初级弹速(Acc1)", "sv_dj_a1", -1000, 1000,0)//进度条panel:NumSlider( "二级弹速(Acc2)", "sv_dj_a2", -1000, 1000,0)panel:NumSlider( "延时(Delay)", "sv_dj_dt", 0.1, 1)panel:NumSlider( "增益(Gain)", "sv_dj_g", 0, 1)panel:Help("跳跃速度 = 自身速度 x 增益 + (0 ,0 , 弹速)\nJumpVel = Vel * Gain + ( 0, 0, Acc)")end)
end)

添加菜单

进度条、复选框之类得指定调节刚才创建的控制台变量

效果

补充:SetViewOffset只能在服务器跑,所以在多人模式下,上述方法实现的摇晃视角存在延迟,可以用客户端的CalcView事件来做,但这种方法只会晃动视角,手臂位置没变,可能需要重写当前武器的GetViewModelPosition方法,但这样的话可能会使一些武器的机瞄失效。

//本地
local svUpdate_not = true
local damping = 10 //阻尼系数
local k = 100 //弹性
local Vel = Vector(0,0,0)//速度
local Acc = Vector(0,0,0)//加速度(弹簧)
local ViewOffset = Vector(0,0,0)//偏移
local Dt = 0.015
net.Receive('shakeview', function(len,p)if First then return endAcc = Vector(0,0,0)ViewOffset = Vector(0,0,0)Vel = net.ReadVector()WEP = ply:GetActiveWeapon()function WEP:GetViewModelPosition(EyePos, EyeAng)if svUpdate_not then return endEyePos = EyePos + ViewOffsetreturn EyePos, EyeAngendsvUpdate_not = falsetimer.Create('Dishonored_view', 0.75, 1, function()svUpdate_not = trueend)
end)
hook.Add('CalcView', 'Dishonored_ShakeView', function(ply, pos, angles, fov)if svUpdate_not then return endDt = FrameTime()ViewOffset = ViewOffset + (Vel + Acc*0.5*Dt)*Dt//二阶泰勒Acc = (-ViewOffset)*k - damping*VelVel = Vel + Acc*Dt    local view = GAMEMODE:CalcView(ply, pos, angles, fov) view.origin  = view.origin  + ViewOffsetreturn view
end)//服务器
hook.Add("OnPlayerHitGround", "Dishonored_ShakeView", function( p,iW,oF,speed)if !sv_dj_a_sv:GetBool() then return endlocal Vel = p:GetVelocity()*sv_dj_svg:GetFloat()local SpeedLimit = sv_dj_svms:GetFloat()Vel[1]=math.Clamp(Vel[1], -SpeedLimit, SpeedLimit)Vel[2]=math.Clamp(Vel[2], -SpeedLimit, SpeedLimit)Vel[3]=math.Clamp(Vel[3], -SpeedLimit, SpeedLimit)net.Start('shakeview')net.WriteVector(Vel)net.Send(p)end)

后续版本的攀爬过程不再使用设置位置而是使用设置速度,抛物线的数值微分作为速度,不再需要判断是否会卡住,彻底解决了穿模问题。

补充:在第二个版本中使用了TraceHull来检测,就像探测线那样,只不过这个是盒子,

输入和Traceline一样,返回的结构体也是一样的,这可比Traceline好用多了,如果早用这个就不用搞那么多花里胡哨的。

第二就是,可以在SetupMove这个钩子中使用SetOrigin函数来改变位置相比SetPos,这个更平滑一些。

Gmod lua插件(Dishonored_Jump)解析相关推荐

  1. lua语言学习之自定义wireshark插件来解析自定义协议

    lua语言学习之自定义wireshark插件来解析自定义协议 关于wireshark这个抓包工具 关于lua 使用lua写wireshark插件 wireshark接口文档 如何在wireshark使 ...

  2. Wireshark lua插件

    源地址:https://www.zybuluo.com/natsumi/note/77991 参考:  http://yoursunny.com/t/2008/Wireshark-Lua-dissec ...

  3. 解决wireshark安装mavlink协议插件后解析报错的问题

    在wireshark上安装mavlink的解析脚本后,在解析mavlink的udp报文时出现如下错误: Lua Error: D:\Program Files\Wireshark\mavlink_v1 ...

  4. Wireshark lua 插件简介

    在我的专栏<wireshark从入门到精通>前面的章节中,学习了wireshark UI界面的使用技巧,学习了命令行工具的使用方法.除此之外为了方便使用者的灵活定制,比如说按需批量修改报文 ...

  5. idea安装lua插件_IntelliJ EmmyLua 1.1.9发布,IDEA的Lua插件

    IntelliJ EmmyLua 1.1.9发布,IDEA的Lua插件 发布时间:2017-09-19 22:07:23来源:红联作者:lovsher EmmyLua 1.1.9 发布,此次更新主要内 ...

  6. VSCode lua插件LuaHelper

    LuaHelper是腾讯开源的一款VSCode下的Lua代码插件,它后端是采用采用go语言编写,具有较高的性能. GitHub:https://github.com/Tencent/LuaHelper ...

  7. LuaHelper高性能Lua插件

    LuaHelper是腾讯开源的一款VSCode下的Lua代码插件,它后端是采用采用go语言编写,具有较高的性能. GitHub:https://github.com/Tencent/LuaHelper ...

  8. Logstash数据处理服务的过滤插件GeoIP解析IP地址的地理位置

    Logstash数据处理服务的过滤插件GeoIP解析IP地址的地理位置 文章目录 Logstash数据处理服务的过滤插件GeoIP解析IP地址的地理位置 1.GeoIP解析IP地址的地理位置 2.安装 ...

  9. MyBatis插件原理解析及自定义插件实践

    一.插件原理解析 首先,要搞清楚插件的作用.不管是我们自定义插件,还是用其他人开发好的第三方插件,插件都是对MyBatis的四大核心组件:Executor,StatementHandler,Param ...

最新文章

  1. ASCII码对应表,ASCII码值的大小顺序
  2. 在FL2440上使用kei MDK 调试程序(J-link)
  3. cygwin nginx php mysql_Windows 下 Nginx + PHP5 的安装与配置
  4. 2016年,这50家创业公司将真正改变世界
  5. smokeping部署安装
  6. hibernate-Maven
  7. python怎么打印出文件的内容_Python---进阶---文件操作---按需求打印文件的内容
  8. android项目中values中几个文件的作用
  9. Spring MVC 3模板和Apache Tiles
  10. oracle数据库,增加序列,自增序列,规定位数,不足用0补足
  11. Java生成指定范围随机数的方法
  12. [HAOI2007] 修筑绿化带
  13. 前端项目,css样式获取到了,没能渲染页面
  14. Java程序的开发步骤
  15. PCIe协议在具体实现时的大体框图
  16. #常见电池型号介绍 常见电池尺寸是多少【详解】
  17. 排列组合常见公式集合
  18. python调用gpu amd_TensorFlow通过AMD GPU加速(ROCm/Ubuntu 18.04)
  19. android sim卡状态改变广播,android监听SIM状态
  20. 小飞升值记——(4)

热门文章

  1. 物联网模组行业市场空间发展前景
  2. 基于JAVA+SpringMVC+Mybatis+MYSQL的驾校考试预约系统
  3. 一篇通俗易懂的ADT介绍
  4. 第1节:英语中的名词,冠词和数词,代词
  5. 网络安全-域服务器(二)
  6. 判断一个经纬度是不是在一个范围内
  7. CSS position中 绝对定位和相对定位的区别以及占位问题
  8. 安卓数学公式 FlexibleRichTextView 的使用
  9. 大数据和云计算技术周报(第59期) - 云+社区 - 腾讯云
  10. 利用正则表达式匹配标点问题