---
title: "零基础入门"
image: "https://wiki.wrightkit.dev/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://wiki.wrightkit.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 零基础入门

> 本文的目的是从0开始到入门。如果你已经理解了地图工坊是怎么回事了，那么本文可能对你帮助并不大

我们先用几个问题来“揭开”​地图工坊神秘的“面纱”:

* 地图工坊是什么？它是一个功能更多的自定义模式。
* 地图工坊能做什么？现阶段，它可以做一些很有意思的玩法，相信你已经体验过地图工坊的作品了。
* 地图工坊不能做什么？它不能脱离游戏的基本框架，例如OW限制了只能有12个玩家，地图工坊并不能让你的房间能塞更多人。现阶段它也不能替换模型，不能改变地形。
* 地图工坊在哪里？它不难找，新建一个自定义房间，打开设置，你就会发现一个大大的“地图工坊”按钮。地图工坊所有的设置就在这里面了。

## 什么是规则

地图工坊是由很多条“规则”组成的。规则是什么？你可以把它看做是一条一条的“条例”。当“规则”该被运行的时候，它就会被运行。

举个例子：在生活中，如果你上班迟到了，那么老板就会扣你工资。当你早上闹铃响了，那么你就应该起床了。这些都是生活中的“规则”。

规则由三个部分组成：事件，条件和动作。还是上面的例子，当你上班迟到，并且今天不是休息日的话，那么老板就会扣你工资。这条“规则”中，“上班迟到”是事件，“今天不是休息日”是条件，“扣工资”则是动作。

那在游戏里怎么体现呢？例如，我们知道，DVA的核爆会对一定范围内的敌人造成伤害，那么，“机甲爆炸”是事件，“玩家在爆炸范围内，且玩家和DVA是敌对关系”是条件，“造成伤害”则是动作。（PS：这里只是用“机甲爆炸”举例子，让你明白事件、条件、动作之间的关系）

总而言之，规则即是：**当某件事（事件）发生，且条件满足时，就做一些动作。**

## 编写规则

相信你已经知道“规则”是什么了，那么，接下来，我们就通过“规则”做一件简单的事：让玩家每次受伤时，回复10生命值。

过程其实很简单：玩家受伤→回血。那么相应的规则应该是什么样？

通过翻阅事件列表，我们发现有一个事件刚好合适：玩家受到伤害。那么我们就用它作为事件了。

我们并没有什么特别的要求，所以不需要“条件”。

动作是给玩家回血。我们应该用什么动作？通过翻阅手册，我们发现了一个“治疗”的动作。它需要选择几个东西：

* 玩家
* 治疗者
* 治疗量

“玩家”就是这个动作的目标，即给谁治疗。我们怎么让游戏知道，治疗的目标是受伤的玩家呢？我们可以使用“事件玩家”。顾名思义，“事件玩家”指的是触发事件的玩家。我们在上面使用了“玩家受到伤害”事件，那么，在这里“事件玩家”指的就是受到伤害的那个玩家。类似的，如果我们使用“玩家阵亡”作为事件，那么就可以用“事件玩家”来代指阵亡的那个玩家。

在本例中，治疗者是谁并不重要，所以我们选择“无”就行了。

最后，我们设定的治疗量是10点，所以我们选择“数字”，然后输入10。

## 变量和值

在OW中，变量和常量统称叫“值”。没接触过编程的朋友可能会觉得这个东西有一些难以理解。但它并没有想象中那么难。我们可以用数学来理解它。

例如我们有一个等式：`y=x+1`。在数学上，我们把x叫做自变量：当我们放入不同的x时，y就不一样。我们的“方程”只是定义了一个从x到y的过程。

在我们上面的例子中，我们有一条动作：给事件玩家治疗10点生命值。这里面，“事件玩家”是一个变量——因为触发事件的玩家可以有很多个。过程是给玩家治疗。而10我们一般把它叫做“常量”——因为它不会变，无论是哪个玩家受伤了，治疗量都是10。

看完上面是不是觉得有点绕，还是不太明白“变量”是什么？没关系，变量就像一个“盒子”，我们可以把东西放进去，也可以把里面的东西拿出来。在下面的内容里，我会举一些实际的例子，让你知道什么时候用到“变量”。

## 实现“冰冻弹”

现在我们来写一点更复杂的规则。我们希望让麦克雷的子弹变成“冰冻弹”——被麦克雷打中的玩家，就会被冰冻住1秒。

同样的，我们先想一想过程：玩家被麦克雷打中→把玩家冻住。

我们发现“事件”并没有“被麦克雷打中”的事件。怎么办？这时候就该让“条件”出马了。被麦克雷打是受到伤害的一种，所以“事件”我们可以继续用“玩家受到伤害”。但是我们有一个附加条件：伤害的来源应该是一名麦克雷玩家。

我们翻阅手册，找到“攻击方”可以代指伤害来源。但我们应该直接拿它来做比较吗？仔细想想，“玩家使用的是麦克雷”比较的应该是英雄，而不是玩家。因此，我们继续找找怎么知道玩家用的什么英雄。最后，我们找到了“英雄”这个选项。条件便是：`英雄(攻击方) == 英雄(麦克雷)`

注意：等号的左右两边一定要是相同类型的，即类似`事件玩家 == 英雄(麦克雷)`是不正确的，因为左边是玩家，右边是英雄。正确的写法是`英雄(事件玩家) == 英雄(麦克雷)`

动作应该是什么？“冰冻”是官方提供的状态之一，我们可以直接使用“设置状态”。

* 玩家
* 助攻者
* 状态
* 持续时间

“玩家”和上面一样，使用“事件玩家”即可。助攻者即为“攻击方”。状态是“冻结”。“持续时间”输入“1”。

## 两个“特殊”​的事件

通过上面的内容，我们已经知道了规则是什么，以及基本都规则编写。但你发现，“事件”只有非常少的几项。如果我们要做一些其他功能，例如，我们想让玩家重生后马上将他移到某个位置，无论是受到、造成伤害事件，还是阵亡事件，都不能满足要求。这时候，就需要用到持续事件+条件了。

持续事件和其他的事件都不太一样。其他事件都是“当这件事发生时”，而持续事件则是“我会一直等着，直到条件满足”。

例如，我们可以用“存活”来判断玩家阵亡与否。而结合我们上面所说的持续事件，我们可以写出这样的规则：

* 事件：持续 - 每名玩家
* 条件：存活(事件玩家) == 真

这是什么意思呢？根据上面的介绍，我们把它“翻译”过来，就是：一直等，直到玩家活着的时候，就做下面的动作。

官方文档中有这样的解释：“当首次检查就满足条件时，则会执行行动。当未满足条件列表，但之后又满足时，则会尝试再次执行行动”。

因此，我们上面的规则，实际上就是：当玩家阵亡的时候，游戏就会等——等到玩家复活，然后做相应的动作。之后玩家又阵亡了，游戏又会继续等。不断重复上述的过程。

类似的，我们现在要编写一个规则，能响应不在地板上的玩家按互动键（F），那么我们就可以这样写

事件：
* 持续 - 每名玩家

条件：
* 在地面上(事件玩家) == 假
* 按钮被按下(事件玩家, 互动) == 真

## 动手做一个模式

通过上面的文章，我们已经知道了如何编写规则。但相信你还不知道如何编写一个简单的玩法。不知道大家是否玩过有“守望传火”​之称的“烫手山芋”模式？这里，我们就以此模式为例子。（如果没玩过的朋友可以在[这里](https://owmod.net/2)体验）

注意：因为本文是一篇教程文章，所以不会完整覆盖整个游戏模式。

### 传火

我们想想这个模式是怎么玩的？带着“火”的玩家通过攻击别的玩家（不论是何种方式），就可以把“火”传给别人。

那么，这个过程用规则怎么描述？我们可以这样说：当一名玩家受到伤害，并且他自己没有火，但是攻击他的玩家有火的时候，就把火传给这名玩家。

从上面的描述不难看出，我们应该选择“玩家受到伤害”事件。但是，我们如何知道玩家有没有“火”呢？不知道大家是否记得艾什的“延时雷管”——我们可以用点燃状态来表示火。通过翻阅手册，我们可以找到“具有状态”和“设置状态”、“清除状态”几个东西。这样，我们就可以把条件组合出来。

条件是受伤的玩家没有火，而攻击方有火。因为我们使用了“玩家受到伤害”事件，因此，我们使用“事件玩家”表示前者，“攻击方”表示后者。条件便是：

* 具有状态(事件玩家, 点燃) == 假
* 具有状态(攻击方, 点燃) == 真

动作是把火“传给”另一名玩家。“传”的过程，又分为一名玩家“失去”火，和一名玩家“得到”火。因此，规则有两条：
* 设置状态(事件玩家, 无, 点燃, 9999)
* 清除状态(攻击方, 点燃)

另外，“点燃”只是效果——能看不能用，所以，我们还得再加上一个“伤害”的动作：
* 开始持续伤害(事件玩家, 无, 9999, 50)
* 设置玩家变量(事件玩家, A, 上一个持续伤害效果ID)
* 停止持续伤害(玩家变量(攻击方, A))

这里我们用到了变量。大家可以结合上面的变量小节，想一想为什么要这样做。（PS：你可以把变量想象成一个“盒子”，设置就是往“盒子”里放东西）。如果你想不通，文末会有更详细的解释。

最终的规则如图所示：

![1](https://p.pstatp.com/origin/pgc-image/54e937dadac34ac399e973595b58bd09)

### 加分

俗话说“万事开头难”。既然我们已经把最基本的东西做出来了，那么我们就可以做下一个东西了：胜利判断。我们的逻辑是：剩下一名玩家的时候，就给这名玩家加一分。

我们不知道什么时候会剩下一名玩家——可能是某位玩家死亡后，但也可能是某位玩家退出游戏后。我们没办法确定到底是什么时候，但我们条件非常清楚：只剩下一名活着的玩家。因此，我们使用`持续事件+条件`来做这件事。我们翻阅手册，可以找到一个叫做“存活玩家数量”的值。我们直接使用它：

* 事件：持续 - 全局
* 条件：存活玩家数量(所有队伍) == 1

而我们要做的，就是给他加一分。我们在手册中找到一个叫“所有存活玩家”的内容，但注意：它是一个数组。因为游戏中可能有很多玩家存活，也可能一个都没有。游戏没有那么智能，它并不知道我们的规则一定只有一个玩家。因此，我们需要使用“数组中的值”：

* 修改玩家分数(数组中的值(所有存活玩家(所有队伍), 0), 1)

接下来，我们要复活所有玩家，开始一局新的比赛：

* 重生(所有玩家(所有队伍))

最终的规则如图所示：

![2](https://p.pstatp.com/origin/pgc-image/3d566048a2b54623b2c77965be65e074)

### 随机传火

现在大体框架已经有了，但是，我们还没处理一些特别的情况：例如，当玩家死亡时，或者玩家退出游戏，导致“火”不见了的时候，我们需要将“火”随机给一名玩家。和上面一样，我们使用持续事件+条件。

我们的条件应该是，当所有玩家都没有火的时候。换句话说，就是有火的玩家数量=0的时候。游戏并不能直接获取到有火的玩家，但我们可以利用“已过滤的数组”来做到这一点：我们从所有存活玩家里，筛选出有火的玩家，不就可以了？

换成条件，就应该这样写：`数量(已过滤的数组(所有存活玩家, 具有状态(当前数组元素, 被点燃))) == 0`。（如果这条规则你不太看得懂，请尝试把括号拆开，从里到外，结合手册，一点一点看）

动作则是从存活玩家里面，随机选择一个玩家，让他有“火”。同样的，我们又要用到“数组”了：

* 设置全局变量(A, 数组随机取值(所有存活玩家(所有队伍)))
* 设置状态(全局变量(A), 点燃)
* 开始持续伤害(全局变量(A), 无, 9999, 50)
* 设置玩家变量(全局变量(A), A, 上一个持续伤害效果ID)

最终规则如下：

![3](https://p.pstatp.com/origin/pgc-image/e8424aedc6a24f14bfe54f9668b0a4e2)

### 修复问题：死亡掉火

现在邀请几个好友，或者多开账号进入游戏。开始一局游戏。你们愉快的传火中，有一名玩家阵亡了。但是，你们发现，“火”并没有传给下一个人。房主打开“地图工坊查看器”一看，哎？随机传火的规则怎么没有运行呢？

原来，死亡是不会自动掉火的，我们还需要手动处理它：
* 事件：玩家阵亡
* 具有状态(事件玩家, 点燃) == 真

“掉火”其实就是把状态去掉，所以动作也很简单，基本上就是上面的规则复制粘贴：
* 清除状态(事件玩家, 点燃)
* 停止持续伤害(玩家变量(事件玩家, A))

最终规则如下：

![4](https://p.pstatp.com/origin/pgc-image/166fea58782b41bfa2e95dbe3d469dee)

### 为什么要使用变量

前面有一个地方我们编写了这样的规则：

* 开始持续伤害(事件玩家, 无, 9999, 50)
* 设置玩家变量(事件玩家, A, 上一个持续伤害效果ID)
* 停止持续伤害(玩家变量(攻击方, A))

为什么我们需要这样写呢？让我们想一想，如果我们直接使用`停止持续伤害(上一个持续伤害效果ID)`，会有什么样的结果？其实并不难想象，当你增加别的规则或动作，里面同样有“开始持续伤害”时，“上一个持续伤害效果ID”就不一定是我们想要的那个伤害了。我们就可能停止不了正确的持续伤害。

那我们用变量达到了什么目的呢？因为规则是不会被“等待”之外的动作打断，因此我们在“开始持续伤害”之后，紧接着使用“上一个持续伤害效果ID”，就一定是我们刚才设置的持续伤害。我们将它放到一个“盒子”里，等我们需要把它消除的时候，再取出来。

类似的，例如我们想让玩家在某些条件下创建一个特效（比如圆球、小星星什么的），过一会儿再消除掉。我们一般会：

* 创建效果(所有玩家(所有队伍), 火花, 蓝色, 事件玩家, 1.500, 可见，位置和半径)
* 设置玩家变量(事件玩家, A, 最后创建的实体)
* 等待(5, 无视条件)
* 消除效果(玩家变量(事件玩家, A))

### 总结

通过几条规则，我们就写出了一个简单的“烫手山芋”模式。相信你也发现了，这并不是什么难事。你需要的，只是把一件事变成一件件小事，然后用规则来完成它。

Source: https://wiki.wrightkit.dev/zh/tutorial/zero-based/index.mdx
