-
坐标系定义
游戏中实际使用的坐标系 X 正方向朝东➡️、Y 正方向朝南⬇️、Z 正方向朝上(高度),均为
float
浮点数。此坐标系的具体数据在游戏内不可见,但你可以通过日志、FFLogs、实体解析等各种方式获取到坐标数据。
此坐标系与小地图的坐标轴方向一致,但坐标不同。比例尺一般为小地图 1 : 实际坐标 50,原点位置也并不一致。
补充说明:
如果你只是刚接触 FF14 的坐标系,你可以先忽略这段内容,记住图中的坐标系即可。
这个定义和内存及网络包中的真实顺序不一样,真实的顺序是 X Z Y,即 Y 是高度轴、Z 是正南方向。
FFXIV 解析插件将内存和网络包中的 YZ 定义颠倒并输出为日志,以匹配数学上的正常习惯,即 XOY 为水平面。
后续 ACT 中的 OverlayPlugin、触发器等插件基本也都仿照此定义修改了顺序。
这也带来了一些问题,无论平面还是三维坐标系都变成了左手系,且部分涉及到角度的数学函数可能与正常定义下有所出入。
你可能在一些插件(如鲶鱼精邮差、卫月)中看见 Y Z 与之相反的定义,届时需留意。
-
实际场地
4.0 时期,大多数形状规则的八人本场地的中心坐标是
0, 0, 0
。5.0 以后,大多数新场地的中心坐标变为了
100, 100, 0
,如下图所示。也有少数例外(如 P5s 被原型宝石兽踹到了
100, 100, -300
)。场地的半径/半宽一般是 20,也有少数 15 (如高贝扎,M3s,一些矩形场地的短边)。
你可以用触发器查询
${_me.Pos}
获取自身的三维坐标,
或使用${_entity[${_me.TargetID}].Pos}
获取自己选中的实体(Boss)的坐标,
很容易判断出场地中心和半径/半宽。
下图以万魔殿 P6s 的场地为例,详细画出了坐标系(浅黄色)和面向(红色)的示意。
三个维度的坐标和一个水平旋转角(面向)构成了 FF14 中实体位姿的全部四个自由度,
即你只使用这四个参数即可精确描述一个实体的位姿信息。
无论在日志中还是在游戏底层,旋转角均为弧度表示的 float
浮点数,
范围从 -π (-3.14)
至 π (3.14)
。
如上图,在俯视视角下,旋转角定义为从 z
正半轴方向(正南)开始旋转的角度,沿逆时针方向增加。
如正西为 -π/2
,正南为 0
,正东为 π/2
,正北为 ±π
。
方向角的变化周期为 2π
,在原本的数值上增减 2π
不会影响实际面向,
你一般也无需将角度标准化至 -π
至 π
。
补充说明:
这不涉及三维旋转。
FF14 中的三维旋转通过四元数或矩阵定义和计算,仅和显示模型有关,实体并没有另外两个旋转自由度。
触发器中定义了很多数学常数/函数,以方便处理与坐标和方向角有关的数学计算。
注:目前触发器只识别小写函数名,但即将更新为大小写不敏感。
注意全部方向角均为弧度制。
表达式 | 解释 |
---|---|
pi / π |
圆周率,3.1415... |
pi2 |
等价于 2π |
pi05 |
等价于 π / 2 |
pi025 |
等价于 π / 4 |
pi0125 |
等价于 π / 8 |
pitorad |
1 弧度等价的角度值,57.295... |
piofrad |
1° 等价的弧度,0.017453... |
后两个常数为早期引入的,不建议用于角度 / 弧度转换。
弧度 → 角度可以使用后文的 rad2deg(rad)
函数;
角度 → 弧度可以直接用 °
,如 30°
会计算为对应的弧度值 30° = 30 * 0.017453 = 0.5236
。
函数 | 解释 |
---|---|
sin(θ) |
θ (弧度)的正弦 |
cos(θ) |
θ (弧度)的余弦 |
tan(θ) |
θ (弧度)的正切 |
cot(θ) |
θ (弧度)的余切 |
sec(θ) |
θ (弧度)的正割 |
csc(θ) |
θ (弧度)的余割 |
sec(θ) |
θ (弧度)的正割 |
arcsin(x) |
x 的反正弦(弧度) |
arccos(x) |
x 的反余弦(弧度) |
arctan(x) |
x 的反正切(弧度) |
arctan2(x, y) atan2(x, y) |
优化的反正切函数,大致等价于 atan2(x / y) , 但可以正确处理分母 y 接近 0 时的情况。你可能会想问为什么这里是 x, y 而不是此函数一般定义下的 y, x :因为此坐标系的方向角 0 为 y 轴而非 x 轴,向量 (x, y) 的方向角就是 θ = atan2(x / y) 。 |
函数 | 解释 |
---|---|
d(x0, y0, x1, y1) distance(x0, y0, x1, y1) |
(x0, y0) 到 (x1, y1) 的平面欧式距离。 |
d(x0, y0, z0, ..., x1, y1, z1, ...) |
你也可以传入 2n 个参数,计算两个 n 维坐标的欧氏距离。n = 1 时等价于 abs(x0 - x1) 。也可写为全称 distance(...) 。 |
L1d(x0, y0, z0, ..., x1, y1, z1, ...) |
类似 d(...) ,计算两个点的 L1 距离(曼哈顿距离)。等于每个维度的坐标差的绝对值之和。 也可以写为全称: ManhattanDistance(...) |
L∞d(x0, y0, z0, ..., x1, y1, z1, ...) |
类似 d(...) ,计算两个点的 L∞ 距离(切比雪夫距离)。等于每个维度的坐标差的最大值。 也可以写为全称: ChebyshevDistance(...) |
radtodeg(rad) |
将弧度转化为角度。 |
degtorad(deg) |
将角度转化为弧度。不推荐,建议直接使用 ° 。 |
θ(x0, y0, x1, y1) angle(x0, y0, x1, y1) |
从 (x0, y0) 面向 (x1, y1) 时的方向角。等价于 atan2(x1 - x0, y1 - y0) 。 |
relθ(θ0, θ1) relangle(θ0, θ1) |
θ1 相对于 θ0 偏转的角度,可以用于判断 θ1 在 θ0 的顺/逆时针方向。相当于将 θ1 - θ0 的结果规范至 -π 到 π 。 |
isθbetween(θ, minθ, maxθ) isanglebetween(θ, minθ, maxθ) |
θ 是否处于从 minθ 开始逆时针旋转到 maxθ 的区间范围内。返回 0 (false)或 1 (true)。角度无需规范化, minθ 可以数值上大于 maxθ ,如判断方向角 -2.75 是否指向北半场,即判断是否位于正东 π/2 到正西 -π/2 的范围:isθbetween(-2.75, π/2, -π/2) |
-
射影距离:
ProjectDistance(srcX, srcY, θ, tgtX, tgtY)
-
射影高度:
ProjectHeight(srcX, srcY, θ, tgtX, tgtY)
定义如下图所示,注意 A 点处于反方向时,射影距离为负值。
主要用于涉及直线/射线型 AoE 的计算,如 Boss 处于 O 点,面朝 θ 释放射线 AoE,玩家处于 A 点。
-
衍生:
IsPointInRay(srcX, srcY, θ, width, tgtX, tgtY)
直接判断一个点是否处于一个射线 AoE 中。
例:阿罗阿罗岛的风元精当前处于 (19, 28),面向正东(π/2),准备释放半宽 5、长度 40 的射线 AoE,
你可以使用
IsPointInRay(19, 28, π/2, 5, ${_me.x}, ${_me.y})
判断自己当前位置是否会被击中。
-
概念
副本中经常需要判断一个实体处于哪个方位。
此时计算出方向角(如塔在
-2.45
方向)并不能输出结果,还需转换为枚举值,如塔在正西北 / 10 点钟方向。这通常需要复杂的
arctan2
和mod
计算,所以设计了这个角度取整用于简化计算。下面展示的角度取整函数可以直接将方向角近似到圆周的
n
等分方向,返回0
至n - 1
, -
roundir(θ, n)
(n > 0
)首先将圆周从正北开始
n
等分,从正北开始编号为0
,1
, ...,n - 1
。如:n
= 4,代表 正北 = 0,正西 = 1, 正南 = 2, 正东 = 3;
n
= 3,代表正三角形等分,正北 = 0,左下顶点方向 = 1,右下顶点方向 = 2;
n
= 12,与表盘类似,n
点钟方向 =12 - n
。然后判断给定的方向
θ
更接近哪个方向,返回这个方向的编号。例 1:四等分场地,
θ = 1.4
(接近正东),则roundir(1.4, 4)
会得到 3(取整至正东);
例 2:八等分场地,θ = 0.8
(接近东南),则roundir(0.8, 8)
会得到 5(东南); -
roundir(θ, -n)
(-n < 0
)除了上述情况以外,也会遇到另一种圆周等分方式,正北不是一个等分点,而位于两个等分点的正中心。
如四个斜方向、绝巴哈 / P7s 倒三角、第二次大地摇动的倒五边形。
在此函数中,用负值 -n 代表这种等分方式,如下图所示:
上述八等分的八方例子如果改成这种四个斜方向的写法,则为:
θ = 0.8
(接近东南),roundir(0.8, -4)
会得到 2(东南)。 -
roundir(θ, ±n, digits)
和小数取整的 round 函数一样,可以在最后指定
digits
参数,代表保留的小数位数。默认情况下取整,
digits = 0
可省略。如果给定负数,代表不舍入。
-
roundvec(dx, dy, ±n, digits = 0)
roundir
函数中的 θ 有时不是可以直接从日志或实体数据获取的面向,而是某个实体相对于某个坐标的方向。这时如果正常计算,就要先算出 θ,如
atan2(x - x0, y - y0)
,或θ(x0, y0, x, y)
。而用这个函数可以直接接受
dx
,dy
(即x - x0
,y - y0
)的方向向量,省去一步角度计算。实际上完全等价于:
roundir(atan2(dx, dy), ±n, digits = 0)
-
应用:输出文本
-
结合字符串函数输出结果
这些函数可以与字符串函数
f:pick(index): 文本1, 文本2, 文本3
结合使用,从弧度或坐标输出任何方向为字符串。如上述的八方表达式
roundir(${θ}, 8)
,结合字符串输出结果则为:${f:pick(${n:roundir(${θ}, 8)}): 上北, 左上, 左西, 左下, 下南, 右下, 右东, 右上}
这个表达式接收不同
${θ}
输入时,即可直接返回对应的八方方向文本,而在传统的写法中需要写八个条件判断。如传入
${θ}
为 0.8 时,即返回前文所述的结果右下
。 -
结合临时列表输出结果
上述表达式亦可以写为:
${?l: 上北, 左上, 左西, 左下, 下南, 右下, 右东, 右上 [${n:roundir(${θ}, 8) + 1}]}
这个表达式利用了临时变量新特性,意为:
用
上北, 左上, 左西, 左下, 下南, 右下, 右东, 右上
字符串构建一个临时列表, 然后取roundir(${θ}, 8) + 1
索引。由于触发器定义的列表从 1 开始,所以索引号 + 1。
-
-
反函数:
dir2rad(dir, ±n)
有时也需要将取整过后的索引号重新转回方向角,即可使用这个函数。
如:
dir2rad(3, 4)
意为四等分圆周的第三个等分点对应的方向,得到正东对应的1.57...
。注意这个函数不包含取整过程的反函数,如果传入的
dir
为小数,则会返回对应的非等分方向的方向角。