EmptyEpsilon

它是什么?

EmptyEpsilon 是一款飞船舰桥模拟游戏。它是完全开源的,因此人们可以根据自己的意愿进行修改。

这意味着什么?

EmptyEpsilon 让您扮演飞船舰桥指挥官的角色,就像在 Star Trek 中看到的那样。虽然您可以单独或与朋友一起玩 EmptyEpsilon,但最好的体验是 6 名玩家在每艘船上协同工作。

每位指挥官都扮演着独特的角色:舰长、舵手、武器官、通讯官、科学官和工程师。除了舰长之外,每位指挥官都通过专门的屏幕操作飞船的一部分。舰长依靠他们值得信赖的船员来报告信息并服从命令。

像 Artemis Spaceship Bridge Simulator 吗?

Artemis Spaceship Bridge Simulator 是 EmptyEpsilon 的灵感来源。作为一个舰桥模拟器,它相当不错,但我们在使用它时遇到了一些问题,我们想解决这些问题。由于 Artemis 不是开源的,我们唯一的解决方案就是自己重新开始。

例如,Artemis 的“通讯”站非常有限,对玩家来说可能很无聊。游戏可能会失去同步,让玩家感到困惑。此外,它的 Game Master 屏幕并没有完成我们想要的所有功能。

总而言之,Artemis 是一款不错的游戏。我们编写了自己的游戏,以便能够实现新的功能和可扩展性。

联系方式

讨论舰桥模拟和 EmptyEpsilon 的最佳场所是 Starship Bridge Simulation Network。我们定期查看这个论坛,并发布我们的太空冒险的更新和战斗记录。

EmptyEpsilon 的主要开发者是 DaidNallath

捐赠

EmptyEpsilon 是一款 100% 免费的游戏。我们制作这款游戏是因为我们想玩自己设想的游戏,但我们不是艺术家,所以我们购买了游戏的 3D 模型。

目前,我们还没有为任何特定的目标筹集资金。但是,如果您想表达您的支持,可以进行捐赠。

之前的贡献

感谢 Daniel Ginat 的贡献,我们成功购买了:更多的护卫舰模型

感谢 Serge Wroclawski 的慷慨贡献,我们成功购买了:更多的战列舰模型

感谢 MadKat 和 Daid 的贡献,我们成功购买了:更大的 3D 空间站模型

大型战斗期间,巡洋舰的主屏幕视图。

控制飞船移动的舵手屏幕视图。

控制飞船武器和护盾的武器官屏幕视图。

可以向飞船子系统分配电力和进行维修的工程师屏幕视图。

具有远程扫描仪和大型信息数据库的科学官屏幕视图。

可以看到并呼叫盟友、分享其短程雷达以及发射远程探测器的通讯官屏幕视图。

可以实时调整和修改游戏场景的 Game Master 屏幕视图。

要运行 EmptyEpsilon 的标准舰桥,您需要以下设备:

除了 1 名指挥官之外,所有指挥官都操作“工作站”,这些工作站控制着飞船的不同部分。最后一台电脑用于主屏幕,主屏幕不需要任何输入,并且应该对所有玩家可见。

指定 1 名玩家为舰长,其计算机可以充当飞船的主屏幕。舰长的唯一职责是与其他指挥官沟通,并告诉他们应该做什么。

其他指挥官各自操作一个飞船工作站,这些工作站的描述在 工作站选项卡 中。

运行游戏

在充当主屏幕的计算机上启动游戏后,您还可以将其配置为游戏服务器。然后,其他工作站可以作为客户端连接到游戏服务器。

启动服务器后,选择一个场景(对于第一次游戏,我们建议使用“Waves”或“Basic”场景),然后生成一艘玩家飞船,供所有人加入。

每个人都应该选择同一艘飞船并选择其指定的工作站。就是这样!您现在指挥着一艘功能齐全的飞船。

互联网游戏

船员可以通过互联网连接玩 EmptyEpsilon。这意味着游戏服务器需要可以从互联网访问。服务器在端口 35666 上运行,该端口需要在您的防火墙中打开,并且如果您位于路由器后面,则需要转发到您的服务器。

如果您没有足够的玩家(或工作站),您可以通过在飞船选择菜单中选择多个角色,在一台机器上运行多个工作站。然后,您可以通过按游戏屏幕右上角的按钮在工作站之间切换。

还有 3 个专为 3-4 名指挥官设计的特殊屏幕:TacticalEngineering+Operations

这 3 个工作站也可以与 5 个标准工作站结合使用。

Game Master 可以通过添加和移除 AI 控制的飞船和工作站、更改其配置、放置空间危险以及与玩家飞船通信来动态修改场景,所有这些都为玩家带来了更有趣和定制化的体验。

场景还可以添加特殊的 GM 功能,这些功能会触发脚本事件。这使得 Game Master 能够构建复杂的故事和错综复杂、动态的情境,他们可以在游戏过程中随意操纵这些情境。脚本命令在 任务脚本选项卡 中进行了深入介绍。

在无法直接控制飞船的情况下,舰长会让船员专注于他们的目标,并在战斗中做出战术决策。飞船的主屏幕应该设置在大型显示器或投影仪上,以便所有玩家都可以跟踪其飞船的状态。

舰长的任务包括:

控制

有很多方法可以配置主屏幕并定义舰长的角色。您可以授予任何指挥官的工作站对主屏幕的控制权,但您也可以使用以下键盘控制让舰长直接控制它:

请注意,这些控件是可选的,对于玩游戏来说不是必需的,但可以在自定义硬件设置中使用。这些控件仅适用于主屏幕。

舰长的“自定义”硬件设置可以像用胶带将 3 键鼠标贴在扶手椅上一样简单。

舵手

数据: 在左上角,舵手屏幕显示飞船的能量(最大值为 1,000)、当前航向(以度为单位)和当前速度(以单位/分钟为单位)。在此数据下方是两个滑块。 引擎: 左侧滑块控制脉冲引擎,从 -100%(全速倒车)到 0%(完全停止)到 100%(全速前进)。如果飞船配备了高速曲速引擎或瞬时传送跳跃引擎,则右侧滑块控制飞船的高速曲速或瞬时传送跳跃引擎。 设置航向: 舵手有一个短程雷达。在雷达内部按下即可设置飞船在该方向上的航向。如果飞船有光束武器,则雷达视图包括这些武器的射击弧,以帮助舵手将目标保持在武器官的视线范围内。 跳跃: 跳跃引擎将飞船沿其当前航向传送指定距离。飞船的脉冲引擎关闭,并且在倒计时结束后,飞船从其位置消失并立即重新出现在其目的地。每次跳跃都会消耗能量,更长的跳跃会消耗更多能量。标准跳跃需要 10 秒才能启动,但根据分配给驱动器的功率(以及损坏程度),驱动跳跃的时间可能会有所不同。 曲速: 曲速引擎以比脉冲引擎快几倍的速度直线推进飞船,但会以更快的速度消耗能量。翘曲的飞船仍然可能与小行星和地雷等危险物相撞,但飞船可以非常快速地进入曲速状态,以进行快速逃生和高级战术动作。 战斗机动: 对于能够执行战斗机动的飞船,舵手屏幕包括右下角最多两个特殊的滑块。垂直滑块可快速将飞船的前进速度提高到最大巡航速度以上,但会在脉冲引擎中产生大量热量并快速消耗能量。水平滑块可以横向移动飞船,但会很快使机动系统过热。战斗机动可能会耗尽,但会随着时间的推移而重新充电。 对接: 当友方或中立的空间站(或者在某些情况下,更大的飞船)在 1U 范围内时,舵手可以与之对接。对接后,飞船无法启动引擎或发射武器,但其能量会更快地充电,维修所需的时间更少,飞船的探测器供应得到补充,并且通讯官可以请求导弹武器重新武装。舵手还负责解除飞船的对接。 检索物体: 舵手还负责驾驶飞船进入补给掉落和其他可检索物品以检索它们。

武器

数据: 在左上角,武器官的屏幕显示飞船的能量(最大值为 1,000)以及其前部和后部护盾的强度。 瞄准: 为了发射光束武器和瞄准制导导弹武器,武器官可以在屏幕的短程雷达上选择飞船。 导弹: 导弹是飞船最具破坏力的武器之一。在发射导弹之前,武器官会选择它,然后选择其中一个武器发射管来装载它。装载和卸载武器发射管需要时间。(地雷也可以装载到特殊类型的武器发射管中。)武器发射管面向特定方向,并且有些飞船只有在飞船的某些侧面才有发射管,这使得与舵手机动的合作尤为重要。

要发射导弹,武器官按下已装载的导弹发射管。除了 HVLI 之外,导弹会追踪武器官选择的任何目标。否则,导弹会以哑弹方式发射,并从其发射管中直线飞行。武器官可以选择将发射管的瞄准锁定到目标上,或者单击雷达右上角的“锁定”按钮来手动调整射击角度。

有几种类型的导弹武器:

光束武器: 光束武器的位置和范围由源自玩家飞船的红色射击弧表示。在武器官选择目标后,飞船的光束武器将在目标位于光束的射击弧内时自动向该目标射击。指挥官可以使用右下角的频率选择器,以及 科学官 提供的有关目标护盾频率的数据,将光束重新调制到造成更大伤害的频率。请注意,您可以立即更改光束频率。

光束武器默认情况下会向目标的船体射击,但武器官也可以瞄准特定的子系统以禁用敌人。但是,如果您只是想摧毁敌人,最好将其留在船体上。 护盾: 武器官负责激活飞船的护盾并调节其频率。一直保持护盾处于开启状态可能很诱人,但它们在激活时会消耗更多的能量。某些护盾频率对某些光束频率具有特别的抵抗力,科学官也可以在目标中检测到这些频率。但是,与光束武器不同,重新调节护盾的频率会使它们离线几秒钟,并使飞船暂时失去防御能力。

工程

电源管理: 工程师可以通过选择系统并移动其电源滑块来将电源路由到系统。为系统提供更多电力会增加其输出。例如,超载的反应堆会产生更多能量,超载的护盾会减少更多伤害并更快地再生,超载的脉冲引擎会增加其最大速度。超载系统(高于 100%)也会增加其热量产生,并且除了反应堆之外,还会增加其能量消耗。同样,降低系统的功率(低于 100%)会减少热量输出和能量消耗。 冷却剂管理: 通过向系统添加冷却剂,工程师可以降低其温度并防止系统损坏飞船。飞船拥有无限的冷却剂储备,但在任何给定时间可以应用的冷却剂数量有限,因此工程师必须预算每个系统可以接收多少冷却剂。系统中温度的变化用温度列中的白色箭头表示。箭头越亮,趋势越大。 维修: 当系统因被击中、与太空危险物相撞或过热而损坏时,工程师可以派遣维修人员到系统进行维修。每个系统都有一个介于 -100% 到 100% 之间的损坏状态。低于 100% 的系统功能不佳,这与它们功率不足的方式大致相同。一旦系统处于或低于 0%,它就会完全停止运行,直到它被修复。可以通过派遣维修人员到包含该系统的房间来修复系统。船体损坏会影响整个飞船,维修人员始终可以修复它,但船体维修的进展非常缓慢。

科学

远程雷达: 科学站有一个远程雷达,可以定位最远 25U 范围内的飞船和物体。科学官最重要的任务是报告扇区的状态以及其中的任何变化。在雷达的边缘是彩色信号干扰带,这些干扰带可以模糊地暗示物体或空间危险物的存在,即使它们距离飞船更远,但由科学官来解释它们。 扫描: 您可以扫描飞船以获取有关它们的更多信息。科学官必须将飞船的两个扫描频率与目标对齐才能完成扫描。大多数飞船在场景开始时对您的船员来说是未知的(灰色),并且必须在将它们识别为朋友(绿色)、敌人(红色)或中立(蓝色)之前进行扫描。扫描还可以识别飞船的类型,科学官可以使用该类型来识别其在工作站数据库中的功能。 深度扫描: 第二次,更困难的扫描会产生有关飞船的更多信息,包括其护盾和光束频率。科学官必须对齐每种扫描类型的频率和调制才能完成深度扫描。舵手和武器屏幕也可以看到深度扫描的飞船的射击弧,这有助于他们引导您的飞船免受光束的射击。 星云: 星云会阻挡飞船的远程扫描仪。科学官无法看到其中或后面的东西,并且在星云中时,飞船的雷达无法检测到它外面的东西。这些特性使星云成为修理或进行伏击的理想场所。为了避免星云周围出现意外,请将您可以看到和无法看到物体的位置信息传递给舰长和通讯官。 探测器视图: 通讯官可以发射探测器并将其中一个连接到科学站。科学官可以查看探测器的短程传感器数据以扫描其范围内的飞船,即使探测器远离飞船的远程扫描仪或位于星云中。 数据库: 科学官可以访问飞船的所有已知飞船数据库,以及有关武器和空间危险物的数据。这在评估飞船在没有深度扫描的情况下的能力,或在帮助导航黑洞、虫洞或其他异常时至关重要。

通讯

扇区地图: 通讯站可以查看扇区的地图,包括短程扫描仪范围内的空间危险物和飞船 (5U)。它还可以看到其他友方飞船和空间站周围的短程传感器数据,这可能会在科学站之前发现遥远的飞船。但是,通讯官无法扫描飞船。 探测器: 通讯官可以将最多 8 个高速探测器发射到扇区中的任何点。这些探测器飞向一个位置并将短程传感器数据传输到飞船 10 分钟。探测器在星云内部工作,因此是在面对被星云阻挡的区域时强大的工具。通讯官还可以将探测器的传感器连接到科学站,这使科学官可以扫描探测器传感器范围内的飞船,即使探测器超出飞船的远程扫描仪范围。探测器无法检索,并且可能会被敌人摧毁;您的飞船的探测器库存只能通过停靠在空间站来补充。 航点: 通讯官可以在扇区周围设置航点。这些航点出现在舵手的短程扫描仪上,可以引导飞船朝向目的地或在太空中沿着特定路线行驶。在请求友方空间站的援助时,航点也是必要的。 通信: 通讯官可以与空间站和其他飞船打开通信。通讯官呼叫的友方飞船可以接受命令,并且友方空间站可以派遣后援和补给飞船。当您的飞船停靠在空间站时,通讯官可以请求重新武装飞船的导弹和地雷。其中一些请求可能会花费您船员的一些声誉,通讯站也会跟踪这些声誉。

关于本系列

本系列记录了 EmptyEpsilon 场景 Beacon of Light 的开发,该场景包含在游戏中。

EmptyEpsilon 使用以 Lua 脚本语言 编写的脚本场景,该语言允许许多类型的场景:基本沙盒、故事驱动的战役、随机敌人,甚至动态分支对话。这些场景位于安装 EmptyEpsilon 的“scripts”文件夹中。

Beacon of Light 场景首先向玩家提供要遵循的说明,然后是一系列要克服的挑战。

场景脚本系统可用于创建更复杂的场景,但本指南不会涵盖此类功能。但是,所有场景都是可查看和可编辑的,您可以查看 scripts 文件夹中的“Waves”场景,以查看复杂随机事件的示例。如果您下载了官方 EmptyEpsilon 构建或自己编译了它,它还会附带一个脚本指南,其中列出了可用的函数。

即使您几乎没有或根本没有编程知识,也可以遵循本指南的前几个部分。后面的部分涵盖更高级的主题。

工具

对于场景开发,您需要一个基本的文本编辑器。虽然 Windows Notepad 可以工作,但我强烈建议使用更高级的东西。

有很多选择,包括以下免费编辑器:

我使用 Programmer's Notepad,但任何这些编辑器都可以。

1. 设置场景文件

我们将从一个空场景作为模板开始。

打开您的文本编辑器并输入以下代码:

-- Name: Beacon of light series
-- Description: The beacon of light scenario, build from the scripting tutorial at https://daid.github.io/EmptyEpsilon/#tabs=4.
--- Near the far outpost of Orion-5, Exuari attacks are increasing.
--- A diplomat went missing, and your mission will start with recovering him.
-- Type: Mission

-- Init is run when the scenario is started. Create your initial world
function init()
  -- Create the main ship for the players.
  player = PlayerSpaceship():setFaction("Human Navy"):setTemplate("Atlantis")
end

function update(delta)
end

将此文件另存为 scenario_99_tutorial.lua 在文件夹 EmptyEpsilon/scripts 中。

打开 EmptyEpsilon 并启动一个新的服务器。您的场景应该位于列表底部 “Mission” 类别下。选择该场景并启动它,并注意到已经存在一艘供玩家使用的飞船。

提示和技巧

构建宇宙

现在您已经设置了一个基本脚本并且知道如何保存和运行它,让我们填充更多宇宙。

首先,让我们用一些空间站填充它,然后添加一些星云和小行星。

添加空间站

我们宇宙中唯一的东西就是玩家飞船。这并没有构成一个非常有趣的宇宙,所以让我们添加一些他们可以停靠和交互的空间站。

从 Game Master 屏幕查看您的场景时,起点位于扇区 F5 的左上角。这些坐标是 “0, 0”,X 坐标在前,Y 坐标在后。如果您单击 Game Master 屏幕上的玩家飞船,您可以在左上角看到其坐标。

请注意,当您向上/向北/以航向 0 移动时,您的 Y 坐标减小;起点以北的位置的 Y 坐标为负数。向右/向东/以航向 90 移动增加您的 X 坐标。另请注意,游戏中的距离以单位 (U) 测量,而脚本以毫单位测量距离 -- 游戏中 1U 等于脚本中的 1000。请参见 此图像 以获取示例。

在创建玩家飞船后添加以下代码:

SpaceStation():setTemplate("Small Station"):setFaction("Human Navy"):setPosition(23500, 16100)

此行将一个小型的 Human Navy 空间站放置在 F5 扇区起点右侧 23.5U (23500) 处,以及起点下方 16.1U (16100) 处。由于每个扇区是一个 20U 的正方形,因此这会将空间站放置在 F6 扇区中。玩家飞船也属于 Human Navy 阵营,因此该空间站将对玩家友好。

接下来,添加以下行以添加另外三个空间站:

SpaceStation():setTemplate("Medium Station"):setFaction("Human Navy"):setPosition(-25200, 32200)
SpaceStation():setTemplate("Large Station"):setFaction("Exuari"):setPosition(-45600, -15800)
SpaceStation():setTemplate("Small Station"):setFaction("Independent"):setPosition(9100,-35400)

这会在 G3 扇区(从起点向左 25.2U,向下 32.2U)添加另一个友方空间站,在 E2 扇区(从起点向左 45.6U,向上 15.8U)添加一个大型敌方 Exuari 空间站,并在 D5 扇区(从起点向右 9.1U,向上 35.4U)添加一个小型的中立空间站。

现在,我们希望玩家从更靠近友方小型空间站的地方开始。所以我们将玩家位置设置在小型空间站附近。

PlayerSpaceship():setFaction("Human Navy"):setShipTemplate("Atlantis"):setPosition(22400, 16200)

创建星云

星云是对宇宙的有趣补充。它们在远程雷达上以及后面的空间阻挡了一个 5U 的圆圈,这为玩家和敌人提供了隐藏空间并为游戏提供了有趣的战术选择。

让我们用一些星云围绕敌方空间站,以便它免受传感器的影响。

--Nebula that hide the enemy station.
Nebula():setPosition(-43300, 2200)
Nebula():setPosition(-34000, -700)
Nebula():setPosition(-32000,-10000)
Nebula():setPosition(-24000,-14300)
Nebula():setPosition(-28600,-21900)

这样的星云云显然隐藏着一些东西,所以让我们添加一些随机星云。

--Random nebulae in the system
Nebula():setPosition( -8000,-38300)
Nebula():setPosition( 24000,-30700)
Nebula():setPosition( 42300, 3100)
Nebula():setPosition( 49200, 10700)
Nebula():setPosition( 3750, 31250)
Nebula():setPosition(-39500, 18700)

创建小行星

您可以以与星云和空间站类似的方式添加小行星:

Asteroid():setPosition(-1000, -1000)

但是,由于您通常想要 50 甚至 100 颗小行星带,因此手动放置所有这些小行星将花费大量时间!

幸运的是,我们可以使用 Lua 函数来帮助快速添加许多小行星。首先,让我们使用 random() 函数在 E5 扇区的随机位置放置一颗小行星。由于 E5 扇区是 F5 扇区左侧的一个扇区,因此 X 轴上的范围是 0 到 -20000,Y 轴上的范围是 0 到 2000。

Asteroid():setPosition(random(0, 20000), random(-20000, 0))

现在让我们使用一个循环重复此操作 100 次。

--Create 100 asteroids
for asteroid_counter=1,100 do
  Asteroid():setPosition(random(0, 20000), random(-20000, 0))
end

这是一个 for 循环。它从 1 计数到 100,并为每个计数执行内部操作一次。在这种情况下,它将一颗小行星添加到 E5 扇区中的随机位置。

这会导致一个非常方形的小行星带。不太漂亮。

所以现在,让我们调整参数以在一条直线上从 E4 扇区创建到 G4 扇区。

--Create 50 asteroids
for asteroid_counter=1,50 do
  Asteroid():setPosition(random(-10000, -5000), random(-10000, 30000))
end

这已经好多了。但是从 3D 视图来看,这个小行星带看起来非常平坦。要解决这个问题,还可以添加一些 VisualAsteroids。这些小行星位于飞船的平面上方或下方,无法被击中。它们仅用于视觉效果。

--Create 100 asteroids
for asteroid_counter=1,50 do
  Asteroid():setPosition(random(-10000, -5000), random(-10000, 30000))
  VisualAsteroid():setPosition(random(-10000, -5000), random(-10000, 30000))
end

添加一些色彩

空间站已自动分配了呼号,例如 DS-7 和其他 DS-? 数字。我们可以通过场景脚本更改这些呼号。

通过在空间站上调用 setCallSign() 函数,我们可以为每个空间站设置不同的名称。保持呼号简短。

SpaceStation():setTemplate("Small Station"):setFaction("Human Navy"):setPosition(23500, 16100):setCallSign("Research-1")
SpaceStation():setTemplate("Medium Station"):setFaction("Human Navy"):setPosition(-25200, 32200):setCallSign("Orion-5")
SpaceStation():setTemplate("Large Station"):setFaction("Exuari"):setPosition(-45600, -15800):setCallSign("Omega")
SpaceStation():setTemplate("Small Station"):setFaction("Independent"):setPosition(9100,-35400):