内置的基本对象类型
基本对象类型
-
EUDVariable
它就是由 var 声明的变量,也是一个对象;只是它在语法上被定义为值类型,和其他对象类型有一些区别,例如可以用等号赋值。
一个 EUDVariable 会使用一个只有一条 SetDeathsX 动作的虚拟触发器模拟,占用 72 字节。以下是它的类型结构,其中包含许多条件和动作函数。object EUDVariable {// 常规方法function ineg(){} // euddraft 0.9.9.8 版新增,将自身值转换为相反数,相当于 x = -x; 支持转换成动作这样用 DoActions(v.ineg(action = true));function iabs(){} // euddraft 0.9.9.8 版新增,将自身值转换为绝对值,相当于 x = (x & (1 << 31) == 0) ? x : -x; 支持转换成动作这样用 DoActions(v.iabs(action = true));// 常规条件function AtLeast(v){} // 变量值 >= vfunction AtMost(v){} // 变量值 <= vfunction Exactly(v){} // 变量值 == vfunction AtLeastX(v,mask){} // (变量值 & mask) >= vfunction AtMostX(v,mask){} // (变量值 & mask) <= vfunction ExactlyX(v,mask){} // (变量值 & mask) == vfunction MaskAtLeast(v){} // 变量的虚拟触发器 SetDeathsX 的动作的 Mask >= vfunction MaskAtMost(v){} // 变量的虚拟触发器 SetDeathsX 的动作的 Mask <= vfunction MaskExactly(v){} // 变量的虚拟触发器 SetDeathsX 的动作的 Mask == vfunction MaskAtLeastX(v,msk){} // 变量的虚拟触发器 SetDeathsX 的动作的 (Mask & msk) >= vfunction MaskAtMostX(v,msk){} // 变量的虚拟触发器 SetDeathsX 的动作的 (Mask & msk) <= vfunction MaskExactlyX(v,msk){} // 变量的虚拟触发器 SetDeathsX 的动作的 (Mask & msk) == v// 常规动作function SetNumber(v){} // 变量值 = vfunction AddNumber(v){} // 变量值 = 变量值 + vfunction SubtractNumber(v){} // 变量值 = 变量值 - v if 变量值 <= v else 变量值 = 0function SetNumberX(v,mask){} // 变量值 = 变量值 - (变量值 & mask) + (v & mask)function AddNumberX(v,mask){} // 变量值 = 变量值 - (变量值 & mask) + ( ((变量值 & mask) + (v & mask)) & mask )function SubtractNumberX(v,mask){} // 变量值 = 变量值 - (变量值 & mask) + ( ((变量值 & mask) - (v & mask)) & mask )// 编译期常量函数function GetVTable(){} // 编译期获取变量虚拟触发器的运行时地址function getMaskAddr(){} // 编译期获取变量虚拟触发器的 SetDeathsX 动作中的掩码参数的运行时地址function getValueAddr(){} // 编译期获取变量虚拟触发器的 SetDeathsX 动作中的数值参数的运行时地址function getDestAddr(){} // 编译期获取变量虚拟触发器的 SetDeathsX 动作中的玩家编号参数的运行时地址// 下列动作实际只能配合 VProc 使用function SetMask(v){} // 将变量的虚拟触发器 SetDeathsX 的动作的 Mask = vfunction AddMask(v){} // 将变量的虚拟触发器 SetDeathsX 的动作的 Mask = Mask + vfunction SubtractMask(v){} // 将变量的虚拟触发器 SetDeathsX 的动作的 Mask = Mask - v if Mask >= v else Mask = 0function SetMaskX(v,msk){} // 将变量的虚拟触发器 SetDeathsX 的动作的 Mask = Mask - (Mask & msk) + (v & msk)function AddMaskX(v,msk){} // 将变量的虚拟触发器 SetDeathsX 的动作的 Mask = Mask - (Mask & msk) + ( ((Mask & msk) + (v & msk)) & msk )function SubtractMaskX(v,msk){} // 将变量的虚拟触发器 SetDeathsX 的动作的 Mask = Mask - (Mask & msk) + ( ((Mask & msk) - (v & msk)) & msk )function SetDest(dest){} // 将变量的虚拟触发器 SetDeathsX 的动作的 玩家编号 = destfunction AddDest(dest){} // 将变量的虚拟触发器 SetDeathsX 的动作的 玩家编号 = 玩家编号 + destfunction SubtractDest(dest){} // 将变量的虚拟触发器 SetDeathsX 的动作的 玩家编号 = 玩家编号 - dest if 玩家编号 >= dest else 玩家编号 = 0function SetDestX(dest,mask){} // 将变量的虚拟触发器 SetDeathsX 的动作的 玩家编号 = 玩家编号 - (玩家编号 & mask) + (dest & mask)function AddDestX(dest,mask){} // 将变量的虚拟触发器 SetDeathsX 的动作的 玩家编号 = 玩家编号 - (玩家编号 & mask) + ( ((玩家编号 & mask) + (dest & mask)) & mask )function SubtractDestX(dest,mask){} // 将变量的虚拟触发器 SetDeathsX 的动作的 玩家编号 = 玩家编号 - (玩家编号 & mask) + ( ((玩家编号 & mask) - (dest & mask)) & mask )function SetModifier(modifier){} // 将变量的虚拟触发器 SetDeathsX 的动作的 数值修改方法 设置为 modifierfunction QueueAssignTo(dest){} // 将变量的虚拟触发器 SetDeathsX 的动作的 玩家编号 设置为 dest 并将 数值修改方法 设置为 SetTofunction QueueAddTo(dest){} // 将变量的虚拟触发器 SetDeathsX 的动作的 玩家编号 设置为 dest 并将 数值修改方法 设置为 Addfunction QueueSubtractTo(dest){} // 将变量的虚拟触发器 SetDeathsX 的动作的 玩家编号 设置为 dest 并将 数值修改方法 设置为 Subtract,Subtract 方法无法将数值从正数减到负数};
-
EUDLightVariable
轻变量和 var 声明的变量不同,它只开辟 4 字节内存空间。它的传值操作比普通变量更消耗资源,但判断值或写入值与普通变量一样,只需要执行一条触发器。(普通变量实质是一个虚拟触发器,占用 72 字节)
要将它的值当作参数传递到其他函数中,需要使用 dwread 函数读取它。
若一个普通变量(EUDVariable)的值不需要当作其他函数的参数(例如用于计数判断、自增、自减、赋值、开关等不与其他函数/条件/动作关联的场景),则可使用 EUDLightVariable 替代该普通变量。object EUDLightVariable {// 编译期常量函数function getValueAddr(){}// 能够通过以下函数、条件、动作搭配达成的目标,都可选用 EUDLightVariable 实现,否则就应该用普通变量(EUDVariable)// 常规方法function ineg(){} // 将自身值转换为相反数,相当于 x = -x; 在 euddraft 0.9.9.8 及之后的版本中支持转换成动作这样用 DoActions(v.ineg(action = true));function iabs(){} // euddraft 0.9.9.8 新增,将自身值转换为绝对值,相当于 x = (x & (1 << 31) == 0) ? x : -x; 支持转换成动作这样用 DoActions(v.iabs(action = true));// 常规条件function AtLeast(v){} // 轻变量值 >= vfunction AtMost(v){} // 轻变量值 <= vfunction Exactly(v){} // 轻变量值 == vfunction AtLeastX(v,mask){} // (轻变量值 & mask) >= vfunction AtMostX(v,mask){} // (轻变量值 & mask) <= vfunction ExactlyX(v,mask){} // (轻变量值 & mask) == v// 常规动作function SetNumber(v){} // 轻变量值 = vfunction AddNumber(v){} // 轻变量值 = 轻变量值 + vfunction SubtractNumber(v){} // 轻变量值 = 轻变量值 - v if 轻变量值 <= v else 轻变量值 = 0function SetNumberX(v,mask){} // 轻变量值 = 轻变量值 - (轻变量值 & mask) + (v & mask)function AddNumberX(v,mask){} // 轻变量值 = 轻变量值 - (轻变量值 & mask) + ( ((轻变量值 & mask) + (v & mask)) & mask )function SubtractNumberX(v,mask){} // 轻变量值 = 轻变量值 - (轻变量值 & mask) + ( ((轻变量值 & mask) - (v & mask)) & mask )};示例
const lv = EUDLightVariable(100);DoActions(lv.AddNumber(564)); // lv += 564;if (lv != 150) {println("{}", dwread(lv.getValueAddr())); // 这个读取值的过程比普通变量要消耗更多的触发器资源,大概在 32 倍以上}lv.ineg(); // lv = -lv;if (lv > 0x80000000 && lv < -663) {println("小于 -663 的负数");}
-
EUDLightBool
轻布尔型(开关)变量,它最少只使用 1 位(八分之一字节)存储。布尔型变量应尽量使用这个,而不是 var。
在 eudplib 内部实现中,每 32 个 EUDLightBool 共用一个 EUDLightVariable。
布尔型(开关)只能表示两个状态,1 表示 Set,0 表示 Cleared,默认初始值为 Cleared。object EUDLightBool {// 编译期常量函数function getValueAddr() {}// 常规条件function IsSet(){} // 当前开关为已设置状态function IsCleared(){} // 当前开关为已清除状态// 常规动作function Set(){} // 设置为开状态function Clear(){} // 设置为关状态function Toggle(){} // 转换开关状态};示例
const b = EUDLightBool(); // 默认初始值为 ClearedDoActions(b.Set(),b.Clear(),b.Toggle(),);if ( b.IsSet() ) {simpleprint("b is set");}if ( b.IsCleared() ) {simpleprint("b is cleared");}
-
EUDArray
轻静态数组容器,它可以使用
[...]语法初始化声明,不能动态更改尺寸object EUDArray {function constructor(size : py_int) {}const length;};示例
const a = EUDArray(10); // 声明一个尺寸为 10 的数组(下标 0~9)a[0] = 29; // 将 a 数组中的下标为 0 的元素赋值为 29println("数组尺寸:{} [0]位置的值:{}", a.length, a[0]); // 数组尺寸:10 [0]位置的值:29const b = [3, 2, 1]; // 声明一个尺寸为 3 的数组(下标 0~2)并初始化为 b[0] = 3; b[1] = 2; b[2] = 1;const c = [list(3, 2, 1), 4, list(5, 6)]; // 声明一个尺寸为 6 的数组(下标 0~5)并初始化为 b[0] = 3; b[1] = 2; b[2] = 1; b[3] = 4; b[4] = 5; b[5] = 6;
-
EUDVArray
使用虚拟触发器实现的静态数组容器,它还可以使用
VArray(...)语法初始化声明,不能动态更改尺寸EUDVArray 容器支持静态设定它包含的值的引用类型
它在数组下标为变量时有更快的访问速度
object EUDVArray {function constructor(size : py_int, basetype : type) : _EUDVArrayClass {}};object _EUDVArray {function constructor(vars : list) {}const length;}示例
const a = EUDVArray(4)(list(1, 2, 3, 4)); // 声明一个尺寸为 4 的数组并初始化为 a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4;const b = VArray(1, 2, 3, 4); // 和上面那个一样const c = VArray(list(1, 2, 3, 4)); // 和上面那个一样const d = VArray(list(1, 2), list(3, 4)); // 和上面那个一样const d = EUDVArray(4)(); // 声明一个尺寸为 4 的数组,等同 VArray(0, 0, 0, 0);foreach (i : py_range(4)) {d[i] = i + 1;}// 声明一个尺寸为 4 x 2 的二维数组const e = EUDVArray(4, EUDVArray(2))(list(VArray(5, 6), VArray(7, 8), VArray(9, 10), VArray(11, 12)));var a = e[2][1]; // euddraft 0.9.9.8 开始支持该语法println("e[2][1] == {}", a); // e[2][1] == 10
-
PVariable
玩家变量实际上是
EUDVArray(8)()的另一种表示方式,也就是一个为每个玩家分别存储不同值的数组。星际最多 8 个玩家。object PVariable {const length;};示例
// 以下两个用法等价const pv1 = PVariable();const pv2 = EUDVArray(8)();
-
EUDVArrayReader
用于遍历 EUDVArray 的类
object EUDVArrayReader {function seek(varr_ptr, varr_epd, eudv, acts) {}function read(acts) {}}
-
EUDDeque
使用虚拟触发器实现的静态双向队列容器,EUDDeque 是运行时迭代器类型
object EUDDeque {function constructor(size : py_int, basetype : type) : _EUDDequeClass {}};object _EUDDeque {function constructor() {}function append(arg) {}function appendleft(arg) {}function pop() {}function popleft() {}function clear() {}function empty() {}const length;};示例
const dq = EUDDeque(10)();// `.length` : 获取当前双向队列长度println("双向队列中元素个数 {}", dq.length);// `.append(x)` : 将 x 添加到双向队列的最右侧dq.append(10);// `.pop()` : 将双向队列最右侧的元素弹出来(移除并返回),你需要先判断双向队列中是否还有元素,如果里面没有元素,直接使用这个方法的行为是未定义的println("双向队列最右边的值弹出 {}", dq.pop());// `.appendleft(x)` : 将 x 添加到双向队列的最左侧dq.appendleft(13);// `.popleft()` : 将双向队列最左侧的元素弹出来(移除并返回),你需要先判断双向队列中是否还有元素,如果里面没有元素,直接使用这个方法的行为是未定义的println("双向队列最左边的值弹出 {}", dq.popleft());// `.clear()` : 清空双向队列dq.clear();// `.empty()` : 判断当前双向队列中元素个数是否为 0if (dq.empty()) {println("双向队列为空");}
-
StringBuffer
内存静态字符串缓冲操作类型
object StringBuffer {function constructor(content : py_str | py_bytes) {}function constructor(len : py_int) {}function append(*args) {}function appendf(format_string, *args) {}function insert(index, *args) {}function insertf(index, format_string, *args) {}function delete(start, length=1) {}function Display() {}function DisplayAt(line) {}function print(*args) {}function printf(format_string, *args) {}function printfAt(line, format_string, *args) {}function Play() {}function fadeIn(*args, line=-1, color=None, wait=1, reset=True, tag=None) {}function fadeOut(*args, line=-1, color=None, wait=1, reset=True, tag=None) {}function fadeInf(format_string, *args, line=-1, color=None, wait=1, reset=True, tag=None) {}function fadeOutf(format_string, *args, line=-1, color=None, wait=1, reset=True, tag=None) {}function length();const StringIndex;const epd;};除初始化方法外,StringBuffer 对象的所有方法都是非同步方法,都只在
当前玩家 == 本机玩家的机器上生效。const buf = StringBuffer(64); // 初始化缓冲区尺寸setcurpl(P1); // 设置 当前玩家 为 P1buf.insert(0, "给玩家 1 显示的信息"); // 这一行只会修改 P1 机器上的 buf,因为当前玩家是 P1if (getuserplayerid() == $P2) { // 本机玩家是 P2 才会执行buf.insert(0, "这行代码不会生效"); // 本机玩家是 P2,但当前玩家是 P1,所以这行代码不生效}setcurpl(P2); // 设置 当前玩家 为 P2buf.insert(0, "给玩家 2 显示的信息"); // 这一行只会修改 P2 机器上的 buf,因为当前玩家是 P2setcurpl(P1);buf.Display(); // 给玩家 1 显示 “给玩家 1 显示的信息”setcurpl(P2);buf.Display(); // 给玩家 2 显示 “给玩家 2 显示的信息” -
StringBuffer
StringBuffer(content)
若 [content] 是字符串或字节串,则以该字符串或字节串初始化一个 StringBuffer 对象。
若 [content] 是一个整数,则以 [content] 作为尺寸初始化一个 StringBuffer 对象。
[content] 是可选参数,默认为整数 218
const s1 = StringBuffer(); // 尺寸为 218 的 StringBuffer 对象,初始内容为 218 个回车符const s2 = StringBuffer(64); // 尺寸为 64 的 StringBuffer 对象,初始内容为 64 个回车符const s3 = StringBuffer("havonz"); // 尺寸为 6 的 StringBuffer 对象,初始内容为 “havonz” -
.insert
-
.insert(index, *args)
将可变参数 [*args] 转换成字符串,并按顺序插入到当前玩家机器上的 StringBuffer 对象缓冲区的[index] * 4位置(索引不是 4 的倍数时不能使用这个方法)。 -
.insertf(index, format_string, *args)
将可变参数 [*args] 使用格式 [format_string] 格式化后,插入到当前玩家机器上的 StringBuffer 对象缓冲区的[index] * 4位置(索引不是 4 的倍数时不能使用这个方法)。
const s1 = StringBuffer();s1.insert(0, "havonz");s1.insert(1, "0");s1.Display(); // havo0 -
-
.append
-
.append(*args)
将可变参数 [*args] 转换成字符串,并按顺序插入到当前玩家机器上的 StringBuffer 对象缓冲区中字符串的末尾。 -
.appendf(format_string, *args)
将可变参数 [*args] 使用格式 [format_string] 格式化后,插入到当前玩家机器上的 StringBuffer 对象缓冲区中字符串的末尾。
const s1 = StringBuffer();setcurpl(getuserplayerid());s1.insert(0);s1.append("你好!");s1.appendf("{}{}", PColor(getuserplayerid()), PName(getuserplayerid()) );s1.Display(); -
-
.delete
.delete(start, length=1)
从当前玩家机器上的 StringBuffer 对象的[start] * 4索引位置删除[length] * 4个字节(索引不是 4 的倍数时不能使用这个方法)。
-
.Display
.Display()
将 StringBuffer 缓冲区的字符串打印到当前玩家屏幕滚动信息的最底下一行。.DisplayAt(line)
将 StringBuffer 缓冲区的字符串打印到当前玩家屏幕滚动信息从上到下第 [line] 行
const s1 = StringBuffer();setcurpl(getuserplayerid());s1.insert(0, "你好!星际争霸");s1.DisplayAt(0); // 输出到最上一行s1.Display(); // 输出到最下一行 -
.print
-
.print(*args)
使用当前 StringBuffer 将多个参数 [*args] 按顺序打印到当前玩家屏幕滚动信息的下一行,并将最底下的信息向上滚动。 -
.printf(formatstring, *args)
使用当前 StringBuffer 以格式 [format_string] 格式化多个参数 [*args],并打印到当前玩家屏幕滚动信息的下一行,同时将最底下的信息向上滚动。 -
.printfAt(line, formatstring, *args)
使用当前 StringBuffer 以格式 [format_string] 格式化多个参数 [*args],并打印到当前玩家屏幕滚动信息从上往下的第 [line] 行(取值范围 0~10)。
const s1 = StringBuffer();setcurpl(getuserplayerid());s1.print("你好!星际争霸"); // 在最底下滚出一条信息s1.printf("你好!{}{}", PColor(getuserplayerid()), PName(getuserplayerid()) ); // 将上一条信息往上滚动,并将这条消息滚出来s1.printfAt(0, "你好!{}{}", PColor(getuserplayerid()), PName(getuserplayerid()) ); // 将这条信息从最上一行打印出来 -
-
.Play
.Play()
将当前玩家机器上的 StringBuffer 对象的内容作为声音文件名,播放该声音文件
当目标声音文件包含本地化声音时,使用 StringBuffer 动态拼接的文件名可能无法播放。
setcurpl(P1);buf.insert(0, "sound\\Zerg\\Devourer\\");buf.append("ZDvPss00.WAV\0");buf.Display(); // 在玩家 1 的屏幕上的下一行输出 “sound\Zerg\Devourer\ZDvPss00.WAV”buf.DisplayAt(9); // 在玩家 1 的屏幕上的第十行输出 “sound\Zerg\Devourer\ZDvPss00.WAV”buf.Play(); // 找到文字指向的 wav 并在玩家 1 的电脑上播放它StringBuffer("sound\\terran\\advisor\\tadupd04.wav").Play(); // nuclear launch detected. -
.fade
-
.fadeIn(*args, line=0, color=None, wait=1, reset=true, tag=None)
使 [*args] 组合成的文本从 [line] 行以 [color] 颜色渐显出现,步间隔帧数为 [wait],是否重置由 [reset] 决定,特效文本标签为 [tag]。循环调用时,返回非 0 表示特效尚未完成、还需继续调用,返回 0 表示特效已完成。 -
.fadeOut(*args, line=0, color=None, wait=1, reset=true, tag=None)
使 [*args] 组合成的文本从 [line] 行以 [color] 颜色渐隐消失,步间隔帧数为 [wait],是否重置由 [reset] 决定,特效文本标签为 [tag]。循环调用时,返回非 0 表示特效尚未完成、还需继续调用,返回 0 表示特效已完成。 -
.fadeInf(format_string, *args, line=0, color=None, wait=1, reset=true, tag=None)
使 [*args] 使用 [format_string] 格式化成的文本从 [line] 行以 [color] 颜色渐显出现,步间隔帧数为 [wait],是否重置由 [reset] 决定,特效文本标签为 [tag]。返回非 0 表示特效尚未完成、还需继续调用,返回 0 表示特效已完成。 -
.fadeOutf(format_string, *args, line=0, color=None, wait=1, reset=true, tag=None)
使 [*args] 使用 [format_string] 格式化成的文本从 [line] 行以 [color] 颜色渐隐消失,步间隔帧数为 [wait],是否重置由 [reset] 决定,特效文本标签为 [tag]。返回非 0 表示特效尚未完成、还需继续调用,返回 0 表示特效已完成。
function 单次渐显然后渐隐文字() {const buf = StringBuffer(128);const onceWait = EUDLightVariable(0);if (getcurpl() != getuserplayerid()) {return;}if (onceWait >= 10000) {return;}const text = py_str("\x13\x04失去\x19人\x04性\n\x13\x04失去\x19很多\x04\n\x13\x04失去\x19兽\x04性\n\x13\x04失去\x19一切\x04");const tecolor = 4, 2, 0x1E, 5, 0;if (onceWait <= 0) {if ( 0 != buf.fadeIn(text, line = 3, color = tecolor, wait = 2, tag = py_str("渐显特效")) ) {return;}}if (onceWait <= 100) {DoActions(onceWait.AddNumber(1));return;}TextFX_SetTimer("渐显特效", SetTo, 0);TextFX_Remove("渐显特效");if ( 0 != buf.fadeOut(text, line = 3, color = tecolor, wait = 2, tag = py_str("渐隐特效")) ) {return;}TextFX_SetTimer("渐隐特效", SetTo, 0);TextFX_Remove("渐隐特效");DoActions(onceWait.SetNumber(10000)); /* 执行完了 */}function beforeTriggerExec() {const cp = getcurpl();setcurpl(getuserplayerid());单次渐显然后渐隐文字();setcurpl(cp);} -
-
Db
静态内存字节数据类型。
object Db {function constructor(content) {}function GetDataSize() {}};支持使用整数、字符串、字节串初始化一段内存字节数据。
使用
Db("string")等同于Db(b"string\0")(UTF-8)。const buf1 = Db(b"string\0"); // Db(b"string\0")const buf2 = Db("string"); // Db(b"string\0")const buf3 = Db(5); // Db(b"\0\0\0\0\0")
-
EUDByteStream
内存字节流操作类。
object EUDByteStream {function seekepd(epd) {}function seekoffset(ptr) {}function copyto(stream : EUDByteStream) {}function readbyte() {}function writebyte(byte) {}}const buf = Db(b"\0uck fu\0k fuck");sprintf(buf, "908 + 8 = {}", 908 + 8);StringBuffer().printAt(6, ptr2s(buf));const stream = EUDByteStream();stream.seekoffset(buf);StringBuffer().printAt(7, stream.readbyte());stream.seekoffset(buf);stream.writebyte(97);stream.writebyte(98);stream.writebyte(99);StringBuffer().printAt(8, ptr2s(buf));
-
CPString已废弃 CPTrick 优化的字符串缓冲操作类
object CPString {function constructor(content) {}function Display() {}function GetVTable() {}};const s1 = CPString("一个字符串");const s2 = CPString(b"stringstringstring");const s3 = CPString(64);
-
DBString已废弃 静态内存字符串
object DBString {function constructor(content) {}function GetStringMemoryAddr() {}function Display() {}function Play() {}};const s = DBString("一个很长的字符串\0一个很长的字符串");const buf = s.GetStringMemoryAddr();s.Display();sprintf(buf, "908 + 8 = {}", 908 + 8);s.Display();