翔鹰帝国网|帝国时代论坛|帝国时代系列|神话时代
 找回密码
 注册翔鹰会员(昵称)
搜索
查看: 1952|回复: 0

[教程分享] 获取地编玩家 ID 对应的世界玩家 ID

[复制链接]

19

主题

1

精华

1301

积分

侯爵

耕战
116
鹰币
780
天龙币
0
回帖
98
附庸关系0
 楼主| 发表于 2023-7-31 15:12:29 | 显示全部楼层 |阅读模式
本帖最后由 Syser 于 2023-7-31 15:27 编辑

为方便描述,现定义如下概念:

  • 地编玩家 ID,在场景编辑器中使用的玩家索引,例如某个触发器中效果的目标(地编)玩家是“玩家1”。
  • 世界玩家 ID,除了场景编辑器的任何地方使用,例如 AI 脚本、XS 脚本。

在大厅中,玩家的座位号是定义 2,世界玩家 ID。这意味着房主永远是 1,第一个进入游戏的那个人可能是 2,在已满 8 人的游戏大厅中,这八个人的 世界玩家 ID 从上到下依次是 1~8。

而这八个人在开始游戏前,可以选择他们在场景中扮演的玩家,通过点击带颜色的按钮选择自己的玩家颜色编号,即定义 1,地编玩家 ID。例如房主选择了编号 2,颜色可能是红色。在进入游戏后,他将扮演场景中的玩家 2,颜色是红色。

在这种情况下,房主的 世界玩家 ID 是 1,但 地编玩家 ID 是 2。

在观战时按 Ctrl + Shift + F1,是切换到 世界玩家 ID 为 1 的玩家,而不是 地编玩家 ID 为 1 的玩家。这也是单机中无论自己是何种颜色编号,Ctrl + Shift + F1 始终能切换到自己的原因——自己始终是座位 1。

在地编中,地编玩家 ID 对应的颜色是可以修改的。例如,将玩家 3 颜色改成红色,那么红色就是编号 3,进入游戏后,就会看到他的颜色是红色,且玩家名称前有一个红色的 3。此时对他生效的触发,是玩家 3 的触发。在自定义场景中,如果只用 XS 脚本,或者只用场景触发器,是不会有任何问题的。但如果同时使用两者,甚者再加上 AI 脚本,世界玩家 ID(座位号)和地编玩家 ID(颜色编号)的不同会影响到场景逻辑。

解决思路:
地编中的资源(贡品)可以被 XS 函数读取,可以选取一个无用资源,通过触发器赋予八个玩家的值分别为 1~8。由于地编使用的是 地编玩家 ID,当我们在 XS 函数中顺序读取时使用的却是 世界玩家 ID,我们就可以依次记录当前 世界玩家 ID 对应的 地编玩家 ID。不过这种记录没有什么作用,因为记录是为了能在 XS 中索引到地编玩家,应该反过来记录“当前数字下标所代表的 地编玩家 ID 对应的 世界玩家 ID”。这样,每当我们想索引地编中的玩家时,就通过它获取在 XS 函数中可用的 世界玩家 ID

思路已经明确,解决起来也不困难。在上文所述的触发器新建后,我们可以建立八个全局变量 p1, p2,..., p8,分别代指 地编玩家 ID 为 1~8 的玩家对应的 世界玩家 ID。在某个函数中初始化,另外要注意,由于场景触发器启动时间比 main() 更晚,故不可在 main 中使用这些变量,即不能在 main() 中索引地编玩家。这些变量的初始化,要在场景触发器为这八名玩家的资源(贡品)赋值后才能成功。

以下例程是可能的实现,其原理同上,只是在一些细则上有所不同:
  • 考虑到有遍历的需求,例程并不按八个全局变量的方式来实现,而是使用函数 p() 中的参数代表需要索引的地编玩家
  • 考虑到场景玩家不一定是 8 名,例程并没有固定玩家数量
/// @brief 获取地编玩家 ID 对应的世界玩家 ID。
/// 在调用本函数前,请在场景触发器中新建一个不循环触发,
/// 添加 8 个效果,分别设置玩家 1~8 的无用资源(例如 200 号资源)分别为 1~8,
/// 本函数会在被首次调用时初始化。
/// 此后,使用 p(1), p(2),而不是 1, 2。
/// 例如,设置地编中的玩家 3 的黄金为 999,应该调用:
/// xsSetPlayerAttribute(p(3), cAttributeGold, 999);
/// @param scenarioPlayerId 玩家在地编中的 ID,即他们在大厅中选择的颜色数字
/// @return 如果 scenarioPlayerId 有效,则返回对应玩家的世界 ID,否则返回 0。
/// 玩家的世界 ID 是他在大厅中的座位号,在 xs 内部,始终使用这个 ID 索引玩家。
int p(int scenarioPlayerId = 0) {
  const int ResColor = 200;
  static int stacked = 0;
  int length = xsGetNumPlayers();
  if (0 == stacked)
    for (i = 1; <= length)
      stacked = stacked + i * pow(10, xsPlayerAttribute(i, ResColor) - 1);

  if (0 >= scenarioPlayerId || scenarioPlayerId > length)
    return (0);

  scenarioPlayerId = pow(10, scenarioPlayerId - 1);
  return ((stacked / scenarioPlayerId) % 10);
}

/// @brief 以场景玩家 ID 为序,打印他们对应的世界 ID。
void printPlayerWorldID() {
  for (i = 1; <= xsGetNumPlayers())
    xsChatData("Scenario Player " + i + " World ID: " + p(i));
}

/// @brief 以世界玩家 ID 为序,打印他们对应的场景 ID。
/// 按照预期,打印的输出顺序应该和玩家们在大厅中选择的颜色数字相同
void printPlayerScenarioId() {
  static int stacked = 0;
  int length = xsGetNumPlayers();
  if (0 == stacked)
    for (i = 1; <= length)
      stacked = stacked + i * pow(10, p(i) - 1);
  int id = stacked;
  for (i = 1; <= length) {
    xsChatData("World Player " + i + " Scenario ID:" + id % 10);
    id = id / 10;
  }
}
有关 AI 脚本中的两者互换,可以参考:
[1]newtonerdai, "[UP1.5] [玩家编号-颜色校正模块] 在联机场景里终于可以正常使用数字AI啦!,"   Hawkaoe, Mar. 21, 2020. https://www.hawkaoe.net/bbs/thread-146068-1-1.html(访问时间 Jan. 1, 1970).

评分

参与人数 2耕战 +50 鹰币 +110 收起 理由
cly806 + 50 + 100 原创精华
熊教授 + 10 原创精华

查看全部评分

回复

使用道具 举报

本版积分规则

排行榜|小黑屋|翔鹰帝国

GMT+8, 2024-11-15 12:39 , Processed in 0.169688 second(s), 25 queries , File On.

Powered by Hawk Studio  QS Security Corp.® Licensed

Copyright © 2001-2023, Hawkaoe.net All Rights Reserved

快速回复 返回顶部 返回列表