<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[samp | open.mp 联机社区论坛 - 所有版块]]></title>
		<link>https://open-mp.cn/</link>
		<description><![CDATA[samp | open.mp 联机社区论坛 - https://open-mp.cn]]></description>
		<pubDate>Mon, 04 May 2026 10:17:25 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[[插件] kook-connect]]></title>
			<link>https://open-mp.cn/showthread.php?tid=33</link>
			<pubDate>Fri, 01 May 2026 01:07:22 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=1">siwode</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=33</guid>
			<description><![CDATA[<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">samp-kook-connector 插件 Wiki</span></span><br />
<br />
将 Kook 机器人集成到你的 SA-MP / open.mp 服务器游戏模式中。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">目录</span><br />
<br />
<ol type="1" class="mycode_list"><li><a href="http://#install" target="_blank" rel="noopener" class="mycode_url">安装</a><br />
</li>
<li><a href="http://#notes" target="_blank" rel="noopener" class="mycode_url">重要说明</a><br />
</li>
<li><a href="http://#natives" target="_blank" rel="noopener" class="mycode_url">Natives（原生函数）</a><ul class="mycode_list"><li><a href="http://#ch" target="_blank" rel="noopener" class="mycode_url">频道</a><br />
</li>
<li><a href="http://#msg" target="_blank" rel="noopener" class="mycode_url">消息</a><br />
</li>
<li><a href="http://#usr" target="_blank" rel="noopener" class="mycode_url">用户</a><br />
</li>
<li><a href="http://#role" target="_blank" rel="noopener" class="mycode_url">身份组</a><br />
</li>
<li><a href="http://#guild" target="_blank" rel="noopener" class="mycode_url">服务器</a><br />
</li>
<li><a href="http://#bot" target="_blank" rel="noopener" class="mycode_url">机器人</a><br />
</li>
<li><a href="http://#embed" target="_blank" rel="noopener" class="mycode_url">嵌入消息</a><br />
</li>
<li><a href="http://#emoji" target="_blank" rel="noopener" class="mycode_url">表情</a><br />
</li>
<li><a href="http://#react" target="_blank" rel="noopener" class="mycode_url">反应</a><br />
</li>
<li><a href="http://#misc" target="_blank" rel="noopener" class="mycode_url">其他</a><br />
</li>
</ul>
</li>
<li><a href="http://#callbacks" target="_blank" rel="noopener" class="mycode_url">Callbacks（回调函数）</a><ul class="mycode_list"><li><a href="http://#cb-ch" target="_blank" rel="noopener" class="mycode_url">频道回调</a><br />
</li>
<li><a href="http://#cb-msg" target="_blank" rel="noopener" class="mycode_url">消息回调</a><br />
</li>
<li><a href="http://#cb-usr" target="_blank" rel="noopener" class="mycode_url">用户回调</a><br />
</li>
<li><a href="http://#cb-guild" target="_blank" rel="noopener" class="mycode_url">服务器回调</a><br />
</li>
</ul>
</li>
</ol>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">1. 安装</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">1.1 创建 Kook 机器人</span><br />
<br />
<ol type="1" class="mycode_list"><li>访问 <a href="https://developer.kookapp.cn/" target="_blank" rel="noopener" class="mycode_url">https://developer.kookapp.cn/</a><br />
</li>
<li>创建一个新的应用 / 机器人<br />
</li>
<li>输入机器人名称并完成创建<br />
</li>
<li>从机器人设置页面获取你的 <span style="font-weight: bold;" class="mycode_b">机器人令牌（Bot Token）</span><br />
</li>
<li>通过开发者门户或邀请链接，将机器人邀请到你的服务器<br />
</li>
</ol>
<br />
<span style="text-decoration: underline;" class="mycode_u">1.2 配置令牌</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">SA-MP（server.cfg）：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>kook_bot_token YOUR_BOT_TOKEN_HERE</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">open.mp（config.json）：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>kook.bot_token YOUR_BOT_TOKEN_HERE</code></div></div><br />
也可以使用环境变量代替：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SAMP_KOOK_BOT_TOKEN=YOUR_BOT_TOKEN_HERE</code></div></div><br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">注意事项：</span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">永远不要</span>将机器人令牌分享给任何人<br />
</li>
<li>确保服务器时钟定期同步，否则速率限制器将无法正常工作，机器人可能会被封禁<br />
</li>
<li>此插件专为 open.mp (OMP) 服务器设计<br />
</li>
</ul>
</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">2. 重要说明</span></span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">关于 Kook ID 与内部 ID：</span><br />
Kook ID 是一个很大的数字，无法放入 PAWN 的 32 位整数中。因此插件采用两套 ID 体系：<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Kook ID</span>：Kook 平台使用的真实 ID，必须以字符串形式传递<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">内部 ID</span>：插件内部使用的整数索引，通过 <span style="font-family: courier;" class="mycode_font">KCC_Find*</span> / <span style="font-family: courier;" class="mycode_font">KCC_Get*</span> 系列函数获取<br />
</li>
</ul>
<br />
你的脚本只需持有内部 ID（索引），插件会在内部维护与真实 ID 的映射关系。</blockquote>
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">关于发送私信：</span><br />
向用户发送私信需要两步：<br />
<ol type="1" class="mycode_list"><li>调用 <span style="font-family: courier;" class="mycode_font">KCC_CreatePrivateChannel(user, "回调函数名")</span> 打开私信频道<br />
</li>
<li>在回调函数中调用 <span style="font-family: courier;" class="mycode_font">KCC_GetCreatedPrivateChannel()</span> 获取频道 ID<br />
</li>
<li>使用该频道 ID 调用 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 等频道函数发送消息<br />
</li>
</ol>
</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">3. Natives（原生函数）</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.1 频道</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KOOK_FindChannelById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KOOK_FindChannelById(const channel_id[])</code></div></div>通过 Kook ID 查找频道，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Channel</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelId(KCC_Channel:channel, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取频道的 Kook ID，以文本形式存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelType</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelType(KCC_Channel:channel, &amp;KCC_ChannelType:type)</code></div></div>获取频道类型，存入 <span style="font-family: courier;" class="mycode_font">type</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelGuild</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelGuild(KCC_Channel:channel, &amp;KCC_Guild:guild)</code></div></div>获取频道所属服务器，存入 <span style="font-family: courier;" class="mycode_font">guild</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelName(KCC_Channel:channel, dest[], max_size = sizeof dest)</code></div></div>获取频道名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelTopic</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelTopic(KCC_Channel:channel, dest[], max_size = sizeof dest)</code></div></div>获取频道主题，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelPosition</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelPosition(KCC_Channel:channel, &amp;position)</code></div></div>获取频道排列位置，存入 <span style="font-family: courier;" class="mycode_font">position</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SendChannelMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SendChannelMessage(KCC_Channel:channel, const message[], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>向指定频道发送消息。<span style="font-family: courier;" class="mycode_font">callback</span>（可选）为消息发送确认后调用的公共函数，<span style="font-family: courier;" class="mycode_font">format</span> 及后续参数为回调参数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetChannelName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetChannelName(KCC_Channel:channel, const name[])</code></div></div>修改频道名称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetChannelTopic</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetChannelTopic(KCC_Channel:channel, const topic[])</code></div></div>修改频道主题。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteChannel(KCC_Channel:channel)</code></div></div>删除指定频道。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.2 消息</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageId(KCC_Message:message, dest[KCC_ID_SIZE], max_size = KCC_ID_SIZE)</code></div></div>获取消息的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageChannel(KCC_Message:message, &amp;KCC_Channel:channel)</code></div></div>获取消息所在频道，存入 <span style="font-family: courier;" class="mycode_font">channel</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageAuthor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageAuthor(KCC_Message:message, &amp;KCC_User:author)</code></div></div>获取消息发送者，存入 <span style="font-family: courier;" class="mycode_font">author</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageContent</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageContent(KCC_Message:message, dest[], max_size = sizeof dest)</code></div></div>获取消息文本内容，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsMessageMentioningEveryone</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsMessageMentioningEveryone(KCC_Message:message, &amp;bool:mentions_everyone)</code></div></div>检查消息是否 @全体成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageUserMentionCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageUserMentionCount(KCC_Message:message, &amp;mentioned_user_count)</code></div></div>获取消息中提及的用户数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageUserMention</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageUserMention(KCC_Message:message, offset, &amp;KCC_User:mentioned_user)</code></div></div>按索引获取消息中提及的某个用户。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageRoleMentionCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageRoleMentionCount(KCC_Message:message, &amp;mentioned_role_count)</code></div></div>获取消息中提及的身份组数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageRoleMention</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageRoleMention(KCC_Message:message, offset, &amp;KCC_Role:mentioned_role)</code></div></div>按索引获取消息中提及的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteMessage(KCC_Message:message)</code></div></div>在 Kook 上删除该消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedMessage()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 的回调中使用，返回刚发送的消息的内部 ID（带 <span style="font-family: courier;" class="mycode_font">KCC_Message</span> 标签）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteInternalMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteInternalMessage(KCC_Message:message)</code></div></div>从插件内部存储中移除该消息（<span style="font-weight: bold;" class="mycode_b">不会</span>在 Kook 上删除消息），用于持久化消息的清理。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_EditMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_EditMessage(KCC_Message:message, const content[], KCC_Embed:embed = KCC_Embed:0)</code></div></div>编辑消息内容，可选附带嵌入消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetMessagePersistent</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetMessagePersistent(KCC_Message:message, bool:persistent)</code></div></div>设置消息是否持久保存在插件内部存储中。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CacheChannelMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CacheChannelMessage(const channel_id[DCC_ID_SIZE], const message_id[DCC_ID_SIZE], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>通过 Kook ID 将指定消息缓存到插件中，缓存完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.3 用户</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>用户的 discriminator 是附加在 Kook 用户名后的 4 位数字标识。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindUserByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindUserByName(const user_name[], const user_discriminator[])</code></div></div>通过用户名 + discriminator 查找用户，返回带 <span style="font-family: courier;" class="mycode_font">KCC_User</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindUserById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindUserById(const user_id[])</code></div></div>通过 Kook ID 查找用户，返回带 <span style="font-family: courier;" class="mycode_font">KCC_User</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserId(KCC_User:user, dest[DCC_ID_SIZE], max_size = DCC_ID_SIZE)</code></div></div>获取用户的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserName(KCC_User:user, dest[DCC_USERNAME_SIZE], max_size = sizeof dest)</code></div></div>获取用户名，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserDiscriminator</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserDiscriminator(KCC_User:user, dest[], max_size = DCC_ID_SIZE)</code></div></div>获取用户的 discriminator，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsUserBot</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsUserBot(KCC_User:user, &amp;bool:is_bot)</code></div></div>检查用户是否为机器人。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsUserVerified</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsUserVerified(KCC_User:user, &amp;bool:is_verified)</code></div></div>检查用户是否已完成验证。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.4 身份组</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 DCC_ID_SIZE。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindRoleByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindRoleByName(KCC_Guild:guild, const role_name[])</code></div></div>在指定服务器中按名称查找身份组，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Role</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindRoleById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindRoleById(const role_id[])</code></div></div>通过 Kook ID 查找身份组，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Role</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleId(KCC_Role:role, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取身份组的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleName(KCC_Role:role, dest[], max_size = sizeof dest)</code></div></div>获取身份组名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleColor(KCC_Role:role, &amp;color)</code></div></div>获取身份组颜色值，存入 <span style="font-family: courier;" class="mycode_font">color</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRolePermissions</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRolePermissions(KCC_Role:role, &amp;perm_high, &amp;perm_low)</code></div></div>获取身份组权限（64 位整数分为高低两个 32 位部分）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsRoleHoist</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsRoleHoist(KCC_Role:role, &amp;bool:is_hoist)</code></div></div>检查身份组是否在成员列表中单独显示（提升显示）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRolePosition</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRolePosition(KCC_Role:role, &amp;position)</code></div></div>获取身份组的排列位置，存入 <span style="font-family: courier;" class="mycode_font">position</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsRoleMentionable</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsRoleMentionable(KCC_Role:role, &amp;bool:is_mentionable)</code></div></div>检查身份组是否可被 @ 提及。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.5 服务器</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 DCC_ID_SIZE。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">— 查询 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindGuildByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindGuildByName(const guild_name[])</code></div></div>按名称查找服务器，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Guild</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindGuildById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindGuildById(const guild_id[])</code></div></div>通过 Kook ID 查找服务器，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Guild</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildId(KCC_Guild:guild, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取服务器的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildName(KCC_Guild:guild, dest[], max_size = sizeof dest)</code></div></div>获取服务器名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildOwnerId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildOwnerId(KCC_Guild:guild, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取服务器所有者的 Kook 用户 ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetAllGuilds</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetAllGuilds(KCC_Guild:dest[], max_size = sizeof dest)</code></div></div>获取所有服务器的内部 ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span> 数组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 频道 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildChannel(KCC_Guild:guild, offset, &amp;KCC_Channel:channel)</code></div></div>按索引获取服务器中的某个频道。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildChannelCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildChannelCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器的频道总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildChannel(KCC_Guild:guild, const name[], DCC_ChannelType:type, const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>在服务器中创建新频道，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedGuildChannel()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreateGuildChannel</span> 的回调中使用，返回新创建频道的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 成员 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMember</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMember(KCC_Guild:guild, offset, &amp;KCC_User:user)</code></div></div>按索引获取服务器中的某个成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器成员总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberVoiceChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberVoiceChannel(KCC_Guild:guild, KCC_User:user, &amp;KCC_Channel:channel)</code></div></div>获取成员当前所在的语音频道。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberNickname</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberNickname(KCC_Guild:guild, KCC_User:user, dest[DCC_NICKNAME_SIZE], max_size = sizeof dest)</code></div></div>获取成员在服务器中的昵称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberRole(KCC_Guild:guild, KCC_User:user, offset, &amp;KCC_Role:role)</code></div></div>按索引获取成员拥有的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberRoleCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberRoleCount(KCC_Guild:guild, KCC_User:user, &amp;count)</code></div></div>获取成员拥有的身份组数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_HasGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_HasGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role, &amp;bool:has_role)</code></div></div>检查成员是否拥有指定身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildMemberNickname</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildMemberNickname(KCC_Guild:guild, KCC_User:user, const nickname[])</code></div></div>修改成员昵称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_AddGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_AddGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role)</code></div></div>为成员添加身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role)</code></div></div>移除成员的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMember</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMember(KCC_Guild:guild, KCC_User:user)</code></div></div>踢出服务器成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildMemberBan</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildMemberBan(KCC_Guild:guild, KCC_User:user, const reason[] = "")</code></div></div>封禁成员，可附带原因。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMemberBan</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMemberBan(KCC_Guild:guild, KCC_User:user)</code></div></div>解封成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 身份组管理 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildRole(KCC_Guild:guild, offset, &amp;KCC_Role:role)</code></div></div>按索引获取服务器中的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildRoleCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildRoleCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器的身份组总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildRole(KCC_Guild:guild, const name[], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>在服务器中创建新身份组，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedGuildRole()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreateGuildRole</span> 的回调中使用，返回新创建身份组的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteGuildRole(KCC_Guild:guild, KCC_Role:role)</code></div></div>删除服务器中的身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleName(KCC_Guild:guild, KCC_Role:role, const name[])</code></div></div>修改身份组名称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRolePermissions</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRolePermissions(KCC_Guild:guild, KCC_Role:role, perm_high, perm_low)</code></div></div>修改身份组权限（64 位整数分为高低两个 32 位部分）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleColor(KCC_Guild:guild, KCC_Role:role, color)</code></div></div>修改身份组颜色。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleHoist</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleHoist(KCC_Guild:guild, KCC_Role:role, bool:hoist)</code></div></div>设置身份组是否在成员列表中单独显示。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleMentionable</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleMentionable(KCC_Guild:guild, KCC_Role:role, bool:mentionable)</code></div></div>设置身份组是否可被 @ 提及。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.6 机器人</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreatePrivateChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreatePrivateChannel(KCC_User:user, const callback[], const format[] = "", {Float, _}:...)</code></div></div>向指定用户打开私信频道，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedPrivateChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedPrivateChannel()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreatePrivateChannel</span> 的回调中使用，返回私信频道的内部 ID（可直接用于 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 等函数）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.7 嵌入消息</span><br />
<br />
嵌入消息（Embed）允许向 Kook 频道发送富文本内容消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateEmbed</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateEmbed(const title[] = "", const description[] = "", const url[] = "", const timestamp[] = "", color = 0, const footer_text[] = "", const footer_icon_url[] = "", const thumbnail_url[] = "", const image_url[] = "")</code></div></div>创建一个嵌入消息，所有参数均为可选，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Embed</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteEmbed</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteEmbed(KCC_Embed:embed)</code></div></div>删除嵌入消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SendChannelEmbedMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SendChannelEmbedMessage(KCC_Channel:channel, KCC_Embed:embed, const message[] = "", const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>向频道发送带嵌入消息的内容，可附带普通文字。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_AddEmbedField</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_AddEmbedField(KCC_Embed:embed, const name[], const value[], bool:inline = false)</code></div></div>为嵌入消息添加字段，<span style="font-family: courier;" class="mycode_font">inline</span> 为 <span style="font-family: courier;" class="mycode_font">true</span> 时字段并排显示。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedTitle</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedTitle(KCC_Embed:embed, const title[])</code></div></div>设置嵌入消息标题。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedDescription</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedDescription(KCC_Embed:embed, const description[])</code></div></div>设置嵌入消息描述。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedUrl</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedUrl(KCC_Embed:embed, const url[])</code></div></div>设置嵌入消息链接。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedTimestamp</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedTimestamp(KCC_Embed:embed, const timestamp[])</code></div></div>设置嵌入消息时间戳。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedColor(KCC_Embed:embed, color)</code></div></div>设置嵌入消息左侧色条颜色。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedFooter</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedFooter(KCC_Embed:embed, const footer_text[], const footer_icon_url[] = "")</code></div></div>设置嵌入消息页脚文本，可附带图标 URL。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedThumbnail</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedThumbnail(KCC_Embed:embed, const thumbnail_url[])</code></div></div>设置嵌入消息缩略图。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedImage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedImage(KCC_Embed:embed, const image_url[])</code></div></div>设置嵌入消息主图片。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.8 表情</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 <span style="font-family: courier;" class="mycode_font">DCC_EMOJI_NAME_SIZE</span>。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateEmoji</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateEmoji(const name[DCC_EMOJI_NAME_SIZE], const snowflake[DCC_ID_SIZE] = "")</code></div></div>创建一个表情对象，<span style="font-family: courier;" class="mycode_font">snowflake</span> 为可选的 Kook 雪花 ID，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Emoji</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteEmoji</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteEmoji(KCC_Emoji:emoji)</code></div></div>删除表情对象。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetEmojiName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetEmojiName(KCC_Emoji:emoji, dest[DCC_EMOJI_NAME_SIZE], maxlen = DCC_EMOJI_NAME_SIZE)</code></div></div>获取表情名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.9 反应</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateReaction(KCC_Message:message, KCC_Emoji:reaction_emoji)</code></div></div>对指定消息添加表情反应。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteMessageReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteMessageReaction(KCC_Message:message, KCC_Emoji:reaction_emoji = KCC_Emoji:0)</code></div></div>移除消息上的表情反应。<span style="font-family: courier;" class="mycode_font">reaction_emoji</span> 为 0（默认）时删除该消息上的<span style="font-weight: bold;" class="mycode_b">所有</span>反应。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.10 其他</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_EscapeMarkdown</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_EscapeMarkdown(const src[], dest[], max_size = sizeof dest)</code></div></div>对字符串中的 Markdown 特殊字符进行转义，使文本在 Kook 消息中原样显示，不被格式化。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">4. Callbacks（回调函数）</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.1 频道回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelCreate(KCC_Channel:channel)</code></div></div>触发时机：服务器中有新频道创建时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelUpdate(KCC_Channel:channel)</code></div></div>触发时机：频道信息更新时（名称、权限等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelDelete(KCC_Channel:channel)</code></div></div>触发时机：频道被删除时。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.2 消息回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageCreate(KCC_Message:message)</code></div></div>触发时机：频道中有新消息发送时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageDelete(KCC_Message:message)</code></div></div>触发时机：消息被删除时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageReaction(KCC_Message:message, KCC_User:reaction_user, KCC_Emoji:emoji, DCC_MessageReactionType:reaction_type)</code></div></div>触发时机：消息添加或移除表情反应时。<ul class="mycode_list"><li><span style="font-family: courier;" class="mycode_font">message</span>：消息内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">reaction_user</span>：操作反应的用户内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">emoji</span>：使用的表情内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">reaction_type</span>：反应事件类型（添加 / 移除等）<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.3 用户回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnUserUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnUserUpdate(KCC_User:user)</code></div></div>触发时机：用户资料更新时（用户名、头像等）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.4 服务器回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildCreate(KCC_Guild:guild)</code></div></div>触发时机：服务器创建，或机器人加入新服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildUpdate(KCC_Guild:guild)</code></div></div>触发时机：服务器信息更新时（名称、图标等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildDelete(KCC_Guild:guild)</code></div></div>触发时机：服务器删除，或机器人离开服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberAdd</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberAdd(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：用户加入服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberUpdate(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：成员信息更新时（昵称、身份组等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberVoiceUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberVoiceUpdate(KCC_Guild:guild, KCC_User:user, KCC_Channel:channel)</code></div></div>触发时机：成员语音状态变化时（加入 / 离开语音频道）。<ul class="mycode_list"><li><span style="font-family: courier;" class="mycode_font">channel</span>：语音频道内部 ID，用户离开语音时该值可能无效<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberRemove</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberRemove(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：用户离开或被踢出服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleCreate(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器中创建新身份组时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleUpdate(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器身份组更新时（名称、颜色、权限等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleDelete(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器身份组被删除时。]]></description>
			<content:encoded><![CDATA[<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">samp-kook-connector 插件 Wiki</span></span><br />
<br />
将 Kook 机器人集成到你的 SA-MP / open.mp 服务器游戏模式中。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">目录</span><br />
<br />
<ol type="1" class="mycode_list"><li><a href="http://#install" target="_blank" rel="noopener" class="mycode_url">安装</a><br />
</li>
<li><a href="http://#notes" target="_blank" rel="noopener" class="mycode_url">重要说明</a><br />
</li>
<li><a href="http://#natives" target="_blank" rel="noopener" class="mycode_url">Natives（原生函数）</a><ul class="mycode_list"><li><a href="http://#ch" target="_blank" rel="noopener" class="mycode_url">频道</a><br />
</li>
<li><a href="http://#msg" target="_blank" rel="noopener" class="mycode_url">消息</a><br />
</li>
<li><a href="http://#usr" target="_blank" rel="noopener" class="mycode_url">用户</a><br />
</li>
<li><a href="http://#role" target="_blank" rel="noopener" class="mycode_url">身份组</a><br />
</li>
<li><a href="http://#guild" target="_blank" rel="noopener" class="mycode_url">服务器</a><br />
</li>
<li><a href="http://#bot" target="_blank" rel="noopener" class="mycode_url">机器人</a><br />
</li>
<li><a href="http://#embed" target="_blank" rel="noopener" class="mycode_url">嵌入消息</a><br />
</li>
<li><a href="http://#emoji" target="_blank" rel="noopener" class="mycode_url">表情</a><br />
</li>
<li><a href="http://#react" target="_blank" rel="noopener" class="mycode_url">反应</a><br />
</li>
<li><a href="http://#misc" target="_blank" rel="noopener" class="mycode_url">其他</a><br />
</li>
</ul>
</li>
<li><a href="http://#callbacks" target="_blank" rel="noopener" class="mycode_url">Callbacks（回调函数）</a><ul class="mycode_list"><li><a href="http://#cb-ch" target="_blank" rel="noopener" class="mycode_url">频道回调</a><br />
</li>
<li><a href="http://#cb-msg" target="_blank" rel="noopener" class="mycode_url">消息回调</a><br />
</li>
<li><a href="http://#cb-usr" target="_blank" rel="noopener" class="mycode_url">用户回调</a><br />
</li>
<li><a href="http://#cb-guild" target="_blank" rel="noopener" class="mycode_url">服务器回调</a><br />
</li>
</ul>
</li>
</ol>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">1. 安装</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">1.1 创建 Kook 机器人</span><br />
<br />
<ol type="1" class="mycode_list"><li>访问 <a href="https://developer.kookapp.cn/" target="_blank" rel="noopener" class="mycode_url">https://developer.kookapp.cn/</a><br />
</li>
<li>创建一个新的应用 / 机器人<br />
</li>
<li>输入机器人名称并完成创建<br />
</li>
<li>从机器人设置页面获取你的 <span style="font-weight: bold;" class="mycode_b">机器人令牌（Bot Token）</span><br />
</li>
<li>通过开发者门户或邀请链接，将机器人邀请到你的服务器<br />
</li>
</ol>
<br />
<span style="text-decoration: underline;" class="mycode_u">1.2 配置令牌</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">SA-MP（server.cfg）：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>kook_bot_token YOUR_BOT_TOKEN_HERE</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">open.mp（config.json）：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>kook.bot_token YOUR_BOT_TOKEN_HERE</code></div></div><br />
也可以使用环境变量代替：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SAMP_KOOK_BOT_TOKEN=YOUR_BOT_TOKEN_HERE</code></div></div><br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">注意事项：</span><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">永远不要</span>将机器人令牌分享给任何人<br />
</li>
<li>确保服务器时钟定期同步，否则速率限制器将无法正常工作，机器人可能会被封禁<br />
</li>
<li>此插件专为 open.mp (OMP) 服务器设计<br />
</li>
</ul>
</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">2. 重要说明</span></span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">关于 Kook ID 与内部 ID：</span><br />
Kook ID 是一个很大的数字，无法放入 PAWN 的 32 位整数中。因此插件采用两套 ID 体系：<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">Kook ID</span>：Kook 平台使用的真实 ID，必须以字符串形式传递<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">内部 ID</span>：插件内部使用的整数索引，通过 <span style="font-family: courier;" class="mycode_font">KCC_Find*</span> / <span style="font-family: courier;" class="mycode_font">KCC_Get*</span> 系列函数获取<br />
</li>
</ul>
<br />
你的脚本只需持有内部 ID（索引），插件会在内部维护与真实 ID 的映射关系。</blockquote>
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">关于发送私信：</span><br />
向用户发送私信需要两步：<br />
<ol type="1" class="mycode_list"><li>调用 <span style="font-family: courier;" class="mycode_font">KCC_CreatePrivateChannel(user, "回调函数名")</span> 打开私信频道<br />
</li>
<li>在回调函数中调用 <span style="font-family: courier;" class="mycode_font">KCC_GetCreatedPrivateChannel()</span> 获取频道 ID<br />
</li>
<li>使用该频道 ID 调用 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 等频道函数发送消息<br />
</li>
</ol>
</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">3. Natives（原生函数）</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.1 频道</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KOOK_FindChannelById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KOOK_FindChannelById(const channel_id[])</code></div></div>通过 Kook ID 查找频道，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Channel</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelId(KCC_Channel:channel, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取频道的 Kook ID，以文本形式存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelType</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelType(KCC_Channel:channel, &amp;KCC_ChannelType:type)</code></div></div>获取频道类型，存入 <span style="font-family: courier;" class="mycode_font">type</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelGuild</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelGuild(KCC_Channel:channel, &amp;KCC_Guild:guild)</code></div></div>获取频道所属服务器，存入 <span style="font-family: courier;" class="mycode_font">guild</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelName(KCC_Channel:channel, dest[], max_size = sizeof dest)</code></div></div>获取频道名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelTopic</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelTopic(KCC_Channel:channel, dest[], max_size = sizeof dest)</code></div></div>获取频道主题，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetChannelPosition</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetChannelPosition(KCC_Channel:channel, &amp;position)</code></div></div>获取频道排列位置，存入 <span style="font-family: courier;" class="mycode_font">position</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SendChannelMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SendChannelMessage(KCC_Channel:channel, const message[], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>向指定频道发送消息。<span style="font-family: courier;" class="mycode_font">callback</span>（可选）为消息发送确认后调用的公共函数，<span style="font-family: courier;" class="mycode_font">format</span> 及后续参数为回调参数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetChannelName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetChannelName(KCC_Channel:channel, const name[])</code></div></div>修改频道名称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetChannelTopic</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetChannelTopic(KCC_Channel:channel, const topic[])</code></div></div>修改频道主题。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteChannel(KCC_Channel:channel)</code></div></div>删除指定频道。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.2 消息</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageId(KCC_Message:message, dest[KCC_ID_SIZE], max_size = KCC_ID_SIZE)</code></div></div>获取消息的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageChannel(KCC_Message:message, &amp;KCC_Channel:channel)</code></div></div>获取消息所在频道，存入 <span style="font-family: courier;" class="mycode_font">channel</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageAuthor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageAuthor(KCC_Message:message, &amp;KCC_User:author)</code></div></div>获取消息发送者，存入 <span style="font-family: courier;" class="mycode_font">author</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageContent</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageContent(KCC_Message:message, dest[], max_size = sizeof dest)</code></div></div>获取消息文本内容，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsMessageMentioningEveryone</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsMessageMentioningEveryone(KCC_Message:message, &amp;bool:mentions_everyone)</code></div></div>检查消息是否 @全体成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageUserMentionCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageUserMentionCount(KCC_Message:message, &amp;mentioned_user_count)</code></div></div>获取消息中提及的用户数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageUserMention</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageUserMention(KCC_Message:message, offset, &amp;KCC_User:mentioned_user)</code></div></div>按索引获取消息中提及的某个用户。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageRoleMentionCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageRoleMentionCount(KCC_Message:message, &amp;mentioned_role_count)</code></div></div>获取消息中提及的身份组数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetMessageRoleMention</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetMessageRoleMention(KCC_Message:message, offset, &amp;KCC_Role:mentioned_role)</code></div></div>按索引获取消息中提及的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteMessage(KCC_Message:message)</code></div></div>在 Kook 上删除该消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedMessage()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 的回调中使用，返回刚发送的消息的内部 ID（带 <span style="font-family: courier;" class="mycode_font">KCC_Message</span> 标签）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteInternalMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteInternalMessage(KCC_Message:message)</code></div></div>从插件内部存储中移除该消息（<span style="font-weight: bold;" class="mycode_b">不会</span>在 Kook 上删除消息），用于持久化消息的清理。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_EditMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_EditMessage(KCC_Message:message, const content[], KCC_Embed:embed = KCC_Embed:0)</code></div></div>编辑消息内容，可选附带嵌入消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetMessagePersistent</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetMessagePersistent(KCC_Message:message, bool:persistent)</code></div></div>设置消息是否持久保存在插件内部存储中。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CacheChannelMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CacheChannelMessage(const channel_id[DCC_ID_SIZE], const message_id[DCC_ID_SIZE], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>通过 Kook ID 将指定消息缓存到插件中，缓存完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.3 用户</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>用户的 discriminator 是附加在 Kook 用户名后的 4 位数字标识。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindUserByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindUserByName(const user_name[], const user_discriminator[])</code></div></div>通过用户名 + discriminator 查找用户，返回带 <span style="font-family: courier;" class="mycode_font">KCC_User</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindUserById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindUserById(const user_id[])</code></div></div>通过 Kook ID 查找用户，返回带 <span style="font-family: courier;" class="mycode_font">KCC_User</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserId(KCC_User:user, dest[DCC_ID_SIZE], max_size = DCC_ID_SIZE)</code></div></div>获取用户的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserName(KCC_User:user, dest[DCC_USERNAME_SIZE], max_size = sizeof dest)</code></div></div>获取用户名，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetUserDiscriminator</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetUserDiscriminator(KCC_User:user, dest[], max_size = DCC_ID_SIZE)</code></div></div>获取用户的 discriminator，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsUserBot</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsUserBot(KCC_User:user, &amp;bool:is_bot)</code></div></div>检查用户是否为机器人。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsUserVerified</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsUserVerified(KCC_User:user, &amp;bool:is_verified)</code></div></div>检查用户是否已完成验证。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.4 身份组</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 DCC_ID_SIZE。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindRoleByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindRoleByName(KCC_Guild:guild, const role_name[])</code></div></div>在指定服务器中按名称查找身份组，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Role</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindRoleById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindRoleById(const role_id[])</code></div></div>通过 Kook ID 查找身份组，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Role</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleId(KCC_Role:role, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取身份组的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleName(KCC_Role:role, dest[], max_size = sizeof dest)</code></div></div>获取身份组名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRoleColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRoleColor(KCC_Role:role, &amp;color)</code></div></div>获取身份组颜色值，存入 <span style="font-family: courier;" class="mycode_font">color</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRolePermissions</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRolePermissions(KCC_Role:role, &amp;perm_high, &amp;perm_low)</code></div></div>获取身份组权限（64 位整数分为高低两个 32 位部分）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsRoleHoist</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsRoleHoist(KCC_Role:role, &amp;bool:is_hoist)</code></div></div>检查身份组是否在成员列表中单独显示（提升显示）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetRolePosition</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetRolePosition(KCC_Role:role, &amp;position)</code></div></div>获取身份组的排列位置，存入 <span style="font-family: courier;" class="mycode_font">position</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_IsRoleMentionable</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_IsRoleMentionable(KCC_Role:role, &amp;bool:is_mentionable)</code></div></div>检查身份组是否可被 @ 提及。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.5 服务器</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 DCC_ID_SIZE。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">— 查询 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindGuildByName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindGuildByName(const guild_name[])</code></div></div>按名称查找服务器，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Guild</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_FindGuildById</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_FindGuildById(const guild_id[])</code></div></div>通过 Kook ID 查找服务器，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Guild</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildId(KCC_Guild:guild, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取服务器的 Kook ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildName(KCC_Guild:guild, dest[], max_size = sizeof dest)</code></div></div>获取服务器名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildOwnerId</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildOwnerId(KCC_Guild:guild, dest[DCC_ID_SIZE], max_size = sizeof dest)</code></div></div>获取服务器所有者的 Kook 用户 ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetAllGuilds</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetAllGuilds(KCC_Guild:dest[], max_size = sizeof dest)</code></div></div>获取所有服务器的内部 ID，存入 <span style="font-family: courier;" class="mycode_font">dest</span> 数组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 频道 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildChannel(KCC_Guild:guild, offset, &amp;KCC_Channel:channel)</code></div></div>按索引获取服务器中的某个频道。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildChannelCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildChannelCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器的频道总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildChannel(KCC_Guild:guild, const name[], DCC_ChannelType:type, const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>在服务器中创建新频道，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedGuildChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedGuildChannel()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreateGuildChannel</span> 的回调中使用，返回新创建频道的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 成员 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMember</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMember(KCC_Guild:guild, offset, &amp;KCC_User:user)</code></div></div>按索引获取服务器中的某个成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器成员总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberVoiceChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberVoiceChannel(KCC_Guild:guild, KCC_User:user, &amp;KCC_Channel:channel)</code></div></div>获取成员当前所在的语音频道。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberNickname</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberNickname(KCC_Guild:guild, KCC_User:user, dest[DCC_NICKNAME_SIZE], max_size = sizeof dest)</code></div></div>获取成员在服务器中的昵称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberRole(KCC_Guild:guild, KCC_User:user, offset, &amp;KCC_Role:role)</code></div></div>按索引获取成员拥有的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildMemberRoleCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildMemberRoleCount(KCC_Guild:guild, KCC_User:user, &amp;count)</code></div></div>获取成员拥有的身份组数量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_HasGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_HasGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role, &amp;bool:has_role)</code></div></div>检查成员是否拥有指定身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildMemberNickname</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildMemberNickname(KCC_Guild:guild, KCC_User:user, const nickname[])</code></div></div>修改成员昵称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_AddGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_AddGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role)</code></div></div>为成员添加身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMemberRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMemberRole(KCC_Guild:guild, KCC_User:user, KCC_Role:role)</code></div></div>移除成员的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMember</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMember(KCC_Guild:guild, KCC_User:user)</code></div></div>踢出服务器成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildMemberBan</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildMemberBan(KCC_Guild:guild, KCC_User:user, const reason[] = "")</code></div></div>封禁成员，可附带原因。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_RemoveGuildMemberBan</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_RemoveGuildMemberBan(KCC_Guild:guild, KCC_User:user)</code></div></div>解封成员。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">— 身份组管理 —</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildRole(KCC_Guild:guild, offset, &amp;KCC_Role:role)</code></div></div>按索引获取服务器中的某个身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetGuildRoleCount</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetGuildRoleCount(KCC_Guild:guild, &amp;count)</code></div></div>获取服务器的身份组总数。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateGuildRole(KCC_Guild:guild, const name[], const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>在服务器中创建新身份组，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedGuildRole()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreateGuildRole</span> 的回调中使用，返回新创建身份组的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteGuildRole</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteGuildRole(KCC_Guild:guild, KCC_Role:role)</code></div></div>删除服务器中的身份组。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleName(KCC_Guild:guild, KCC_Role:role, const name[])</code></div></div>修改身份组名称。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRolePermissions</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRolePermissions(KCC_Guild:guild, KCC_Role:role, perm_high, perm_low)</code></div></div>修改身份组权限（64 位整数分为高低两个 32 位部分）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleColor(KCC_Guild:guild, KCC_Role:role, color)</code></div></div>修改身份组颜色。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleHoist</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleHoist(KCC_Guild:guild, KCC_Role:role, bool:hoist)</code></div></div>设置身份组是否在成员列表中单独显示。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetGuildRoleMentionable</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetGuildRoleMentionable(KCC_Guild:guild, KCC_Role:role, bool:mentionable)</code></div></div>设置身份组是否可被 @ 提及。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.6 机器人</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreatePrivateChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreatePrivateChannel(KCC_User:user, const callback[], const format[] = "", {Float, _}:...)</code></div></div>向指定用户打开私信频道，完成后调用 <span style="font-family: courier;" class="mycode_font">callback</span>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetCreatedPrivateChannel</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetCreatedPrivateChannel()</code></div></div>在 <span style="font-family: courier;" class="mycode_font">KCC_CreatePrivateChannel</span> 的回调中使用，返回私信频道的内部 ID（可直接用于 <span style="font-family: courier;" class="mycode_font">KCC_SendChannelMessage</span> 等函数）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.7 嵌入消息</span><br />
<br />
嵌入消息（Embed）允许向 Kook 频道发送富文本内容消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateEmbed</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateEmbed(const title[] = "", const description[] = "", const url[] = "", const timestamp[] = "", color = 0, const footer_text[] = "", const footer_icon_url[] = "", const thumbnail_url[] = "", const image_url[] = "")</code></div></div>创建一个嵌入消息，所有参数均为可选，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Embed</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteEmbed</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteEmbed(KCC_Embed:embed)</code></div></div>删除嵌入消息。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SendChannelEmbedMessage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SendChannelEmbedMessage(KCC_Channel:channel, KCC_Embed:embed, const message[] = "", const callback[] = "", const format[] = "", {Float, _}:...)</code></div></div>向频道发送带嵌入消息的内容，可附带普通文字。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_AddEmbedField</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_AddEmbedField(KCC_Embed:embed, const name[], const value[], bool:inline = false)</code></div></div>为嵌入消息添加字段，<span style="font-family: courier;" class="mycode_font">inline</span> 为 <span style="font-family: courier;" class="mycode_font">true</span> 时字段并排显示。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedTitle</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedTitle(KCC_Embed:embed, const title[])</code></div></div>设置嵌入消息标题。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedDescription</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedDescription(KCC_Embed:embed, const description[])</code></div></div>设置嵌入消息描述。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedUrl</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedUrl(KCC_Embed:embed, const url[])</code></div></div>设置嵌入消息链接。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedTimestamp</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedTimestamp(KCC_Embed:embed, const timestamp[])</code></div></div>设置嵌入消息时间戳。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedColor</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedColor(KCC_Embed:embed, color)</code></div></div>设置嵌入消息左侧色条颜色。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedFooter</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedFooter(KCC_Embed:embed, const footer_text[], const footer_icon_url[] = "")</code></div></div>设置嵌入消息页脚文本，可附带图标 URL。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedThumbnail</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedThumbnail(KCC_Embed:embed, const thumbnail_url[])</code></div></div>设置嵌入消息缩略图。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_SetEmbedImage</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_SetEmbedImage(KCC_Embed:embed, const image_url[])</code></div></div>设置嵌入消息主图片。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.8 表情</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>dest 字符串大小必须为 <span style="font-family: courier;" class="mycode_font">DCC_EMOJI_NAME_SIZE</span>。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateEmoji</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateEmoji(const name[DCC_EMOJI_NAME_SIZE], const snowflake[DCC_ID_SIZE] = "")</code></div></div>创建一个表情对象，<span style="font-family: courier;" class="mycode_font">snowflake</span> 为可选的 Kook 雪花 ID，返回带 <span style="font-family: courier;" class="mycode_font">KCC_Emoji</span> 标签的内部 ID。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteEmoji</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteEmoji(KCC_Emoji:emoji)</code></div></div>删除表情对象。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_GetEmojiName</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_GetEmojiName(KCC_Emoji:emoji, dest[DCC_EMOJI_NAME_SIZE], maxlen = DCC_EMOJI_NAME_SIZE)</code></div></div>获取表情名称，存入 <span style="font-family: courier;" class="mycode_font">dest</span>。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.9 反应</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_CreateReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_CreateReaction(KCC_Message:message, KCC_Emoji:reaction_emoji)</code></div></div>对指定消息添加表情反应。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_DeleteMessageReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_DeleteMessageReaction(KCC_Message:message, KCC_Emoji:reaction_emoji = KCC_Emoji:0)</code></div></div>移除消息上的表情反应。<span style="font-family: courier;" class="mycode_font">reaction_emoji</span> 为 0（默认）时删除该消息上的<span style="font-weight: bold;" class="mycode_b">所有</span>反应。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">3.10 其他</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_EscapeMarkdown</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>KCC_EscapeMarkdown(const src[], dest[], max_size = sizeof dest)</code></div></div>对字符串中的 Markdown 特殊字符进行转义，使文本在 Kook 消息中原样显示，不被格式化。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u"><span style="font-weight: bold;" class="mycode_b">4. Callbacks（回调函数）</span></span><br />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.1 频道回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelCreate(KCC_Channel:channel)</code></div></div>触发时机：服务器中有新频道创建时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelUpdate(KCC_Channel:channel)</code></div></div>触发时机：频道信息更新时（名称、权限等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnChannelDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnChannelDelete(KCC_Channel:channel)</code></div></div>触发时机：频道被删除时。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.2 消息回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageCreate(KCC_Message:message)</code></div></div>触发时机：频道中有新消息发送时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageDelete(KCC_Message:message)</code></div></div>触发时机：消息被删除时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnMessageReaction</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnMessageReaction(KCC_Message:message, KCC_User:reaction_user, KCC_Emoji:emoji, DCC_MessageReactionType:reaction_type)</code></div></div>触发时机：消息添加或移除表情反应时。<ul class="mycode_list"><li><span style="font-family: courier;" class="mycode_font">message</span>：消息内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">reaction_user</span>：操作反应的用户内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">emoji</span>：使用的表情内部 ID<br />
</li>
<li><span style="font-family: courier;" class="mycode_font">reaction_type</span>：反应事件类型（添加 / 移除等）<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.3 用户回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnUserUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnUserUpdate(KCC_User:user)</code></div></div>触发时机：用户资料更新时（用户名、头像等）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="text-decoration: underline;" class="mycode_u">4.4 服务器回调</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildCreate(KCC_Guild:guild)</code></div></div>触发时机：服务器创建，或机器人加入新服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildUpdate(KCC_Guild:guild)</code></div></div>触发时机：服务器信息更新时（名称、图标等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildDelete(KCC_Guild:guild)</code></div></div>触发时机：服务器删除，或机器人离开服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberAdd</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberAdd(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：用户加入服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberUpdate(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：成员信息更新时（昵称、身份组等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberVoiceUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberVoiceUpdate(KCC_Guild:guild, KCC_User:user, KCC_Channel:channel)</code></div></div>触发时机：成员语音状态变化时（加入 / 离开语音频道）。<ul class="mycode_list"><li><span style="font-family: courier;" class="mycode_font">channel</span>：语音频道内部 ID，用户离开语音时该值可能无效<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildMemberRemove</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildMemberRemove(KCC_Guild:guild, KCC_User:user)</code></div></div>触发时机：用户离开或被踢出服务器时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleCreate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleCreate(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器中创建新身份组时。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleUpdate</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleUpdate(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器身份组更新时（名称、颜色、权限等）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">KCC_OnGuildRoleDelete</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public KCC_OnGuildRoleDelete(KCC_Guild:guild, KCC_Role:role)</code></div></div>触发时机：服务器身份组被删除时。]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[圣安地列斯联机二十年：SA:MP 与 open.mp 历史]]></title>
			<link>https://open-mp.cn/showthread.php?tid=30</link>
			<pubDate>Tue, 24 Mar 2026 20:45:15 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=30</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">圣安地列斯联机二十年：SA:MP 与 open.mp 历史</h2><br />
<br />
2026 年。GTA6 即将在今年 11 月发售，新的时代正在敲门。<br />
<br />
也是在这一年，《侠盗猎车手：圣安地列斯》PC 版上市整整二十年，SA:MP 的第一个可玩版本也已走过二十个年头。<br />
<br />
一座从未被设计为联机游戏的城市，有人在这里认识了一辈子的朋友。有人在这里第一次学会了写代码。有人在角色扮演服务器里扮演一个JC或一个黑帮头目。有人在一个无聊的下午打开了游戏，然后就再也没有那个下午了。<br />
<br />
SA:MP 从来不是一个精致的产品。它是一群人强行塞进一款单人游戏里的多人世界。它有数不清的 bug，有争议不断的管理者，有过漫长的停滞与分裂——它也有 open.mp，有一批不肯让它消失的开发者，有如今可以在手机上随时上线的客户端，不管你还记不记得服务器的 IP，不管你当年是服主、脚本开发者，还是只是一个普通的玩家——你在这里的时间是真实的。<br />
<br />
GTA6 会带来它的世界。但圣安地列斯的街道，还在。服务器还在跑，玩家还在上线，有人还在第一次输入 /register。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">前言</h3><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>本文以客观事实为准绳。所有关键事件、人物声明、原始帖文，均完整收录于正文之中，不以外部链接替代实质内容。链接仅作考证索引，供读者溯源查验，不构成叙述本身的一部分。<br />
<br />
凡引用原文处，均以引用块标注，并注明来源与时间。凡转述处，均忠实于原意，不加渲染，不作价值评判。<br />
<br />
这是一部关于热爱、控制、背叛与重建的故事，也是一个游戏社区在二十年间走过的记录。</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">卷首语：一个不该有多人模式的游戏</h3><br />
<br />
2004 年 10 月 26 日，《侠盗猎车手：圣安地列斯》（Grand Theft Auto: San Andreas）在 PlayStation 2 平台正式发售。2005 年 6 月 10 日，PC 版本上市。<br />
<br />
这款游戏从未被设计为多人联机。Rockstar Games 为它设计了一个宏大的单人故事——主角 CJ 在帮派、JC与腐败之间挣扎求生，横跨三座城市、一片乡野。游戏没有联机大厅，没有服务器浏览器，没有任何供多人游玩的接口。<br />
<br />
然而在 GTA 模组社区里，有一批人从不接受"这不可能"这个答案。<br />
<br />
他们是一群来自世界各地的年轻人，大多数有着普通的日间生活——学生、程序员、上班族——他们一点一点地撬开这款游戏的外壳，试图将它改造成一个可以容纳数百人同时在线的多人世界。<br />
<br />
这便是 SA:MP 的起点。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第一卷：诞生（2004–2006）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第一章　从 Vice City 到 San Andreas</h4><br />
<br />
在《圣安地列斯》PC 版尚未发售之前，GTA 模组社区已经有人在为《GTA 罪恶都市》（Vice City）制作多人联机改造，这个项目被命名为 <span style="font-weight: bold;" class="mycode_b">VC:MP（Vice City Multiplayer）</span>。<br />
<br />
领导这支早期团队的，是一个网名叫 <span style="font-weight: bold;" class="mycode_b">kyeman</span> 的开发者，真名 <span style="font-weight: bold;" class="mycode_b">Kye Bitossi</span>。他在 GTA 模组社区中颇有声望，是公认的技术核心人物。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2005 年 4 月初</span>，kyeman 在全球最大的 GTA 社区论坛 <span style="font-weight: bold;" class="mycode_b">GTAForums</span> 上发布了一篇帖子，正式宣布 SA:MP 项目的存在。帖子标题是：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"[WIP] SA-MP: Multiplayer for San Andreas PC"</span><br />
——kyeman，GTAForums，2005年4月3日</blockquote>
<br />
消息一出，社区立刻沸腾。预告视频和截图开始在各大 GTA 论坛流传，项目的小型社区论坛在尚未开放任何测试的情况下，已吸引了约 <span style="font-weight: bold;" class="mycode_b">120 名注册用户</span>。<br />
<br />
公开 beta 测试期间，服务器承载能力远不及涌入的测试者数量，进入测试服务器需要排队等候，等待时间往往很长。这种盛况，是对整个项目最好的背书。<br />
<br />
进入开发团队的成员，来自 GTA 模组社区的各个方向，过去的SA-MP 0.2开发者和测试者包括：kyeman、spookie、Y_Less、mike、jax、Mike、Cam、adamcs、bakasan、Born Acorn、Dalpura、Damian、Delfi、dexx、DrAke&#36;、Drift、ECLiPSE、f3llah1n、him selfe、illspirit、littlewhitey、MrJax、njr1489、Posty、PsYcHoGoD、Shizz、Simon、sockx、squiddy、Static、steve-m、The Azer、Trix、Wacko、XcR、[ULK]Crack，其中许多人既是开发者也是测试员。<br />
<br />
他们大多是业余爱好者，利用业余时间共同推进这个无人出资的项目。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第二章　合作模式的争议与团队第一次动荡</h4><br />
<br />
然而，SA:MP 从一开始便并非一片和谐。<br />
<br />
开发团队内部，关于游戏核心玩法的方向，爆发了一场至今仍被一些老玩家提起的根本性争论：<br />
<br />
一部分人主张将 SA:MP 建设为一款<span style="font-weight: bold;" class="mycode_b">合作模式（Co-op）</span>游戏，设想最多 6 名玩家共同游玩，保留完整的 NPC 行为、警察追捕系统与任务流程，让多人体验尽可能接近单人游戏的质感；<br />
<br />
另一方，以 kyeman 为首，坚持将其建设为一个能够容纳大量玩家同时在线的<span style="font-weight: bold;" class="mycode_b">大规模死亡竞技（Deathmatch）</span>式多人服务器。<br />
<br />
这场分歧并未在内部平息，而是溢出到了 GTANet 社区论坛，引发了玩家的大量公开讨论与批评，负面声音之多，令整个项目团队承受了巨大压力。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2005 年 9 月 18 日</span>，kyeman 在持续的内外压力下，宣布因个人事务无暇继续领导项目，将主导权移交给团队二号核心开发者 <span style="font-weight: bold;" class="mycode_b">spooky</span>。<br />
<br />
spooky 接手后，将项目更名为 <span style="font-weight: bold;" class="mycode_b">GTA:Multiplayer（GTA:M）</span>，以示风格与管理方式的转变。<br />
<br />
然而，约一个月后，kyeman 重新归队。合作模式方案在此期间被彻底搁置，项目名称最终改回 <span style="font-weight: bold;" class="mycode_b">San Andreas Multiplayer（SA:MP）</span>，方向确定为大规模多人在线游戏。<br />
<br />
关于"Grand Theft Auto"字样是否应出现在项目名称中，团队在命名时也有过考量——使用 Rockstar 的商标可能引发法律风险，最终以缩写"SA:MP"作为正式名称，在一定程度上规避了这一问题。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第三章　2006 年：第一个可玩版本</h4><br />
<br />
在经历了那段动荡之后，SA:MP 于 <span style="font-weight: bold;" class="mycode_b">2006 年</span> 发布了第一个向公众开放的可玩版本。<br />
<br />
从技术层面看，这是一项相当可观的成就：开发者们在完全没有官方支持的前提下，用逆向工程的方式强行将联机功能"嵌入"进一款从未被设计为多人联机的作品，使其能够支持最多 <span style="font-weight: bold;" class="mycode_b">1000 名玩家</span>同时在线，在同一片虚拟的圣安地列斯地图中驾车、射击、竞速。<br />
<br />
服务器使用 <span style="font-weight: bold;" class="mycode_b">Pawn</span> 作为脚本语言，服务器主可以自行编写游戏模式（GameMode）与过滤脚本（FilterScript）。这一设计赋予了整个生态极高的开放性——任何人只要学会 Pawn，就可以在圣安地列斯的地图上建造出属于自己的世界。<br />
<br />
0.2.2 版本是这一阶段的代表版本，也是现存有据可查的最早可玩 SA:MP 版本记录之一。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第二卷：黄金时代与暗流（2006–2009）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第四章　版本迭代与社区的兴盛</h4><br />
<br />
2006 年至 2014 年，是 SA:MP 最活跃的开发阶段。Kalcor（此时 kyeman 已开始使用这个网名）陆续发布了一系列重要版本：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">0.2 系列</span>（2006–2008）期间，SA:MP 奠定了基本架构，确立了 Pawn 脚本语言作为游戏模式开发的标准。这段时间并非全然顺利——一次大规模安全漏洞爆发，险些让整个团队就此放弃。而最终让他们坚持下来的，是一份在线请愿：短短时间内，数以千计的玩家签名支持 SA:MP 继续存在。这份来自社区的温度，让开发者重新燃起了动力。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">0.3a</span>（约 2010 年）是 SA:MP 历史上最具里程碑意义的版本之一。单服务器玩家上限从原来的数百人扩展至 <span style="font-weight: bold;" class="mycode_b">500 人</span>（后续版本更高），引入了鼠标驱动的记分板与聊天界面，增加了可编程的 NPC 机器人系统（允许服务器创建可驾驶火车、飞机的脚本机器人），网络同步质量大幅改善。<br />
<br />
此后数年，<span style="font-weight: bold;" class="mycode_b">0.3c、0.3d、0.3e、0.3x、0.3z</span> 相继发布，带来了音频流媒体支持、延迟补偿模式、自定义对象渲染距离、新的安全更新等功能。每一个版本的发布，都在 SA:MP 官方论坛的"新闻与更新"板块留下了一条由 Kalcor 亲自发布的公告。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2015 年 5 月 1 日</span>，Kalcor 发布了 SA:MP <span style="font-weight: bold;" class="mycode_b">0.3.7</span>，这是 SA:MP 有史以来最后一个带有实质性新功能的正式版本。0.3.7 新增了超过 500 个物体 ID（含特技物件与地形物件）、界面字体大小调整选项、若干新版警察皮肤、服务端对车门与车窗的控制权、为未标记警车添加警报灯的能力，以及一个简单的静态 NPC actor 系统。<br />
<br />
这个版本在此后数年间成为整个 SA:MP 生态的事实标准，直至今日仍是服务器主最常使用的版本。<br />
<br />
与此同时，这个社区在技术之外也在野蛮生长。<span style="font-weight: bold;" class="mycode_b">角色扮演（RP）服务器</span>在这段时期走向成熟，玩家们在 SA:MP 的世界中建构起了拥有经济系统、帮派政治、法律体系的虚拟社会。来自世界各地大型服务器先后崛起。SA:MP 不再只是一个小众模组，它已经成为一个真实的、活跃的、跨越语言与国境的国际社区。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第五章　Y_Less 的双重身份与 YSI 的诞生</h4><br />
<br />
在 SA:MP 的所有社区开发者中，有一个人的名字几乎是无可回避的：<span style="font-weight: bold;" class="mycode_b">Y_Less</span>，真名 Alex Cole。<br />
<br />
Y_Less 最初以 beta 测试员的身份加入 SA:MP 团队，随后正式成为开发团队成员，主要负责 Pawn 脚本语言相关的功能开发。然而，他与 Kalcor 之间的分歧，从他正式入队的第一天起便已埋下。<br />
<br />
用 Y_Less 自己后来的话说：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"加入开发团队之后，我开始开发 Pawn，但我发现自己能做的事被 Kye 严重限制。我们之间存在重大的意见分歧：他认为 90% 的开发精力应该投入同步（sync）工作，Pawn 几乎只是顺手提供一点额外功能的附属品。而我认为，虽然同步很重要，但他已经把同步覆盖得很好了，我更想专注于 Pawn 的功能与函数。然而他是老板，说了算，严重限制了我被允许做的事。此外，他有个坏习惯——每次版本迭代之后，只要在某个细枝末节的测试中有任何不稳定，就要来指责我，尽管测试本来就是我们有 beta 测试团队的原因。不用说，这不是一个好的工作环境，但我仍然喜欢 SA:MP 这个产品本身。"</span></blockquote>
<br />
在这种压抑的工作环境中，Y<span style="font-style: italic;" class="mycode_i">Less 于 <span style="font-weight: bold;" class="mycode_b">2007 年</span> 开始独立开发 <span style="font-weight: bold;" class="mycode_b">YSI（Y</span>Less' Server/Script Includes）</span>。<br />
<br />
YSI 最初是他此前若干工具的整合与升级，同时也是他在 Kalcor 的管控边界之外，以纯 Pawn 脚本的方式，实现他认为 SA:MP 脚本系统应当具备的扩展能力。他在这个过程中也加入了一些辅助性的函数，例如 player objects 功能，最初是专门为了支撑他的对象流式传输器 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">e_objects</code> 而写的。<br />
<br />
用 Y_Less 自己的话说：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"2007 年，我开始开发 YSI。这部分是对若干早期工具的更新与整合，部分也是在 Kye 的控制之外，以 Pawn 能力范围内的方式带来我认为 Pawn 所需的扩展功能——尽管以纯 Pawn 来做，能实现的事情自然有其上限。YSI 成为我的主要项目这一事实惹恼了 Kye，因为他认为这说明我没有把时间花在 SA:MP 上，尽管我实际上一直都在。"</span></blockquote>
<br />
YSI 涵盖了命令处理（y<span style="font-style: italic;" class="mycode_i">commands）、玩家迭代器（y</span>iterate）、钩子机制（y<span style="font-style: italic;" class="mycode_i">hooks）、INI 文件读写（y</span>ini）、多语言支持（y_languages）等数十个子模块，是当时 SA:MP 社区功能最全面、使用最广泛的第三方脚本库。<br />
<br />
至于"YSI"到底代表什么，连 Y_Less 本人也说不清：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"最初的想法是'Y[i]Less' Server Includes'，但 Server 和 Script 经常被混用，而且现在参与的开发者不止 Y</span>Less 一人，所以'Y'就变成了一个递归缩写，代表'YSI'本身。"[/i]</blockquote>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第六章　2008 年底：GTANet 风波与团队大出走</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2008 年底</span>，SA:MP 开发团队内部爆发了一场与 GTANet 社区相关的严重矛盾。关于这场风波的具体细节，现有的公开资料已难以完整还原，但其结果是清晰且影响深远的：<span style="font-weight: bold;" class="mycode_b">Mike、aru 和 Peter</span> 等多名核心开发者相继以此为由宣布离队。<br />
<br />
Y_Less 在日后的声明中这样描述这段经历：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"2008 年底，GTANet 风波爆发，Mike、aru 和 Peter 因此离开，我也因为团队氛围实在太差，加之大家都在走，便也一同离开了。"</span></blockquote>
<br />
这一波出走之后，SA:MP 的开发工作几乎完全落回 Kalcor 一人肩上，这进一步强化了整个项目对他个人的高度依赖，也使得社区的任何集体意见都更加难以产生实质影响。<br />
<br />
然而事情并未就此平息。Y_Less 出走后，出于他自己也说不清的原因，重新回归了团队。他在后来的声明中写道：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"不知为何，真的记不清了，我之后又重新加入了团队。那时候 Kye 想要关闭 SA:MP，我提出愿意接手，他拒绝了。然后我再次退出——不是因为我没接手到，这一点需要说明——于是 Kye 决定封禁我的论坛账号，而且不只是封号，而是彻底抹除——删掉了我所有的帖子。这意味着原版《实用函数》帖没了，旧版 FAQ 帖没了，大量迷你教程没了，《Pawn 关键词》帖也没了——我只有在非常必要的时候才发帖，那些帖子都有其存在的价值，它们的消失被大量用户注意到并提出了强烈抗议。"</span></blockquote>
<br />
这便是 2008 年底那次"第一次封号"事件的始末——相对低调，但已经是一个信号。真正震动整个社区的风波，还在后面。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第七章　2009 年 1 月：YSF 封号事件</h4><br />
<br />
从团队再度离开之后，Y<span style="font-style: italic;" class="mycode_i">Less 没有停止为社区创作工具。他开发了 <span style="font-weight: bold;" class="mycode_b">YSF（Y</span>Less' Server Fixes）</span>——一个以服务端插件形式存在的 bug 修复集合。<br />
<br />
YSF 的设计理念很简单：SA:MP 有很多 Kalcor 长期忽略或拒绝修复的 bug，既然拿不到源代码，那就通过内存操作（memory patching）的方式，在运行时强行修正这些行为。这个方法技术上相当复杂，但效果立竿见影。<br />
<br />
Y_Less 事后这样形容 YSF：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"YSF 是我最成功的项目，因为它做到了所有人都想要的事。它本质上是一个更新版的服务端——人们总是渴望新版本带来修复和新功能，功能方面已经有其他插件（包括 YSI 插件）覆盖了，所以我选择了修复这条路（以及一些小功能——显然正是这些小功能引发了麻烦）。"</span></blockquote>
<br />
YSF 在社区中广泛流传，大量服务器安装并使用它。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">2009 年 1 月 19 日</span>，事件的直接导火索被点燃。<br />
<br />
当天，Kalcor 私信给 Y_Less，表达了对 YSF 的不满。他的顾虑有两项：<br />
<br />
第一，他认为 YSF 可能与 SA:MP 未来版本产生脚本兼容性问题；第二，他认为 YSF 代码中存在与 SA:MP 服务端源代码相似的内容，以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">functions.cpp</code> 中的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">IsNickInvalid</code> 函数为例。<br />
<br />
Y_Less 对此逐一作出回应。关于兼容性问题，他指出 YSF 恰恰是在让脚本对未来版本<span style="font-weight: bold;" class="mycode_b">更加</span>兼容，而非相反；关于源代码问题，他坦言：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"这实际上并非盗用，但我承认看起来非常相似，因为它做的事情完全一样，而且也不是什么复杂的函数，我懒得争，就直接把它彻底重写了。"</span></blockquote>
<br />
他还顺带提到，Kalcor 自己曾主导过一些令他反对的修改决策——比如改变服务端的默认运行风格，以及在 0.3 版本中移除对象（最后改为以 IPL 文件形式替代，而非完全移除）——当初他的反对意见被 Kalcor 直接否决。<br />
<br />
双方讨论的最终结果，表面上是达成了共识：Kalcor 表示接受了 Y_Less 的解释，YSF 可以继续存在。<br />
<br />
然而，Y_Less 第二天登录论坛，发现自己已经被封号。<br />
<br />
他在后来的声明中还原了这段过程：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"就在我们讨论同意 YSF 可以继续存在，之后，他发现了 SetServerRule，并意识到它可以用来修改只读控制台变量——比如服务器版本号——从而让人们能够违反 SA:MP 服务条款第（g）条：'你不得人为地增加玩家数量，或向 SA:MP 查询机制提供虚假信息。'"</span></blockquote>
<br />
Kalcor 认为，Y_Less 在 YSF 中提供了这样一个功能，就等同于为违规行为提供了手段，因此必须承担责任。<br />
<br />
封号通知的原文如下（Y_Less 在声明中直接引用）：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>*"抱歉 ssǝן‾ʎ，你已被禁止使用本论坛！  <br />
滥用前开发者身份。入侵服务器，并为他人违反服务条款提供手段。"*</blockquote>
<br />
封号的同时，Kalcor 再次<span style="font-weight: bold;" class="mycode_b">删除了 Y_Less 在 SA:MP 官方论坛上的全部历史帖子</span>。大量教程、工具发布帖、FAQ 就此永久消失，众多用户注意到这些帖子的蒸发，并提出了强烈抗议。<br />
<br />
Y_Less 随即在社区发布了一篇完整声明，以下是他原文的核心段落：<br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"基本上，我因为 YSF 被 SA:MP 官方论坛封号了！</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">历史：</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">200x 年（实在记不清了），在与 Spookie 讨论之后，我以 beta 测试员的身份加入了 SA:MP 团队——那还是第一次公开 beta 之前的事——并开始编写 Pawn 相关的代码。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">没过多久，我正式加入了开发团队，专注于 Pawn 的开发，但我很快发现自己受到 Kye 的诸多限制，做不了想做的事。我们之间存在重大分歧：他认为 90% 的开发精力应该用于同步（sync），Pawn 只是顺手提供一点额外功能的附属品；而我认为，虽然同步很重要，但他已经把同步做得很好了，我更想把时间花在 Pawn 的功能扩展上。然而他是老板，说了算，严重限制了我能做的事。更让人受不了的是，他有个习惯——每次版本迭代后，只要在某个犄角旮旯的测试里出了任何小问题，就要来责怪我，哪怕我们有 beta 测试团队本来就是为了发现这些问题的。说实话那不是一个好的工作环境，但我还是喜欢 SA:MP 这个产品本身。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2007 年，我开始开发 YSI。这一方面是对此前一批旧项目的整合升级，另一方面也是想在 Kye 的管控之外，以纯 Pawn 脚本的方式实现我认为 Pawn 所需要的扩展功能——尽管能做到的事情有限，毕竟纯 Pawn 本身有其局限（我确实额外添加了一些辅助函数，比如 player objects 功能完全是为了写我最初的对象流式传输器 e\_objects 而专门实现的）。YSI 成为我的主要项目这件事惹恼了 Kye，因为他觉得我没有把时间花在 SA:MP 上——尽管我实际上一直都在。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2008 年底，GTANet 社区风波爆发，Mike、aru 和 Peter 因此离队。我也因为团队氛围实在太差，加上大家都在走，便也跟着离开了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不知为何（真的记不清了），我之后又重新回归了团队。那时候 Kye 想要关闭 SA:MP，我主动提出愿意接手，他拒绝了。然后我再次退出——不是因为没接手到，这一点需要说清楚——于是 Kye 决定封禁我的论坛账号，而且不只是封号，而是彻底抹除，删掉了我所有的帖子。这意味着原版《实用函数》帖没了，旧版 FAQ 帖没了，大量迷你教程没了，《Pawn 关键词》帖也没了——我只有在非常必要的时候才会发帖，那些帖子都有其价值，它们的消失被大量用户注意到并提出了抗议。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不管怎样，我还是喜欢 SA:MP 和这个社区本身（至少喜欢其中的一部分），所以我还是留了下来（现在回想起来真不知道当时为什么，深感后悔），并继续努力让 SA:MP 变得更好——尽管 Kye 的存在让这件事很难。我继续开发 YSI、写教程和帮助帖，后来又创作了 YSF。YSF 大概是我最成功的项目了，因为它做到了所有人都想要的事。它本质上就是一个改进版的服务端——人们总是渴望新版本带来修复和新功能，功能方面已经有其他插件（包括 YSI 插件）覆盖了，所以我选择了专注于修复这条路（以及一些小功能——显然正是这些小功能引发了这次麻烦）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">总之，Kye 和我一般都各自行事、互不干扰（至少我是这么以为的），有一段时间相安无事。直到 2009 年 1 月 19 日，我收到了 Kye 的消息，说他不太喜欢我在 YSF 里做的事。经过一番交涉，才明白他的顾虑在于：YSF 可能与未来版本的脚本产生兼容性问题（这话从他嘴里说出来真是讽刺——我当初就反对过他把默认运行方式改掉，以及 0.3 版本里删除对象的决定，但他否决了我；对象最后是改成了 IPL 文件的形式，而非完全删除，但也没有了 per-player objects，至少我最后听到的消息是这样）。此外，他还质疑 YSF 里有 SA:MP 服务端的源代码——他举的例子是 functions.cpp 里的 IsNickInvalid 函数。这个函数其实不是照抄的，但我承认看起来确实很像，毕竟它做的事完全一样，而且也不是什么复杂的函数，我懒得争，就直接把它彻底重写了。在我指出 YSF 并不会造成兼容性问题（恰恰相反，它让脚本对未来版本的兼容性更好），并同意日后不再使用 SA:MP 源代码（尽管我此前一直在刻意避免这样做）之后，他让步了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">第二天我上论坛，发现自己已经被封了……</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">原来在我们达成共识之后，他又发现了 SetServerRule 这个功能，意识到它可以用来修改只读控制台变量（比如服务器版本号），从而让人能够违反 SA:MP 服务条款第（g）条：'你不得人为地增加玩家数量，或向 SA:MP 查询机制提供虚假信息。'</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我解释说，我本人根本没有这样做，这个功能的设计初衷是好的，只是不幸被人滥用了。我甚至想过反问他：他提供论坛和 IRC 频道，同样也给人们提供了违反条款（c）（d）条的方式，按他的逻辑，他也应该被封号——但我懒得说了。封号通知的原文是：</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">'抱歉 ssǝן‾ʎ，你已被禁止使用本论坛！滥用前开发者身份。入侵服务器，并为他人违反服务条款提供手段。'</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">所谓'滥用'，是指我用它改善了所有人的游戏体验；所谓'入侵服务器'，是指我修复了它；所谓'提供手段'，意思是人们可以拿我提供的工具做坏事——但这不代表我支持或认可这种行为，这只是一个有用工具所带来的无奈副作用。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">Kye 说 YSF 的事已经覆水难收，他只能发布新版本来屏蔽它，伤害已经造成，它已经广泛传播，人们正在用它黑自己的服务器，没有人能阻止，所以我必须被封。我回应说，如果我没被封，我本来可以发布最新版本，在修复拾取物 bug 的同时，加入对规则的只读标志检查——虽然这无法彻底解决问题，但能大幅减少滥用，因为几乎没有人会主动把它改回旧方式，大多数人会为了这个重要修复而升级。说到这里，他就不再回复我了（我觉得他是意识到自己断掉了快速、高效解决这件事的唯一合理途径，然后不想认账了——如果不是这样，我欢迎他来回应）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">总之，我决定把当时正在写的那段代码（YSI 的示例脚本）收个尾，毕竟我还是喜欢使用 YSI 的那些人，上传最终版本，然后就此结束。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">所以，截至目前：YSI 1.0、YSF 1.0、YSI2 1.0、YPI 1.0，到此为止，我不干了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言：Kye 正在研究一种过滤"修改版本服务端"并将其列入黑名单的机制——我可能会发布一个不自动修改版本号的 YSF 版本，这样用它的人就不会因为我的失误被连坐；请留意这里的动态（我可能也会顺带加入拾取物修复，但不会保留只读变量相关的功能）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言二：IRC 才是王道，我还活跃在 GTANet 的大量频道里，包括 #YSI 和 #Y_Less，欢迎来找我。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言三：不知道 MTA 的源代码长什么样……</span>"</blockquote>
<br />
——Y_Less，2009年1月，TMS Forums<br />
<br />
<hr class="mycode_hr" />
<br />
这篇声明在社区引发了强烈反响。数日后，经社区压力，Y_Less 得以解封，YSF 在不修改只读变量的前提下被允许继续使用。从表面上看，风波平息了。<br />
<br />
但那句"附言三"——"不知道 MTA 的源代码长什么样"——如今读来，已不再只是一句无心之语。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第三卷：停滞、管控与分歧（2014–2019）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第八章　0.3.7 之后的沉寂（含源码泄漏事件）</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2015 年 5 月 1 日</span>，SA:MP <span style="font-weight: bold;" class="mycode_b">0.3.7</span> 发布。此后，Kalcor 在新功能层面的开发近乎陷入停滞。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年前后</span>，Kalcor 发布了 <span style="font-weight: bold;" class="mycode_b">SA-MP 0.3.DL</span>——一个支持服务端向玩家客户端推送自定义模型（Download Content）的版本。这是社区长期以来最渴望的功能之一，玩家们可以在 SA:MP 服务器上看到服务器自定义的车辆、皮肤、物件模型，而不再局限于原版游戏资产。<br />
<br />
然而 0.3.DL 的推出并不顺利：安全问题（恶意服务器可能推送损坏的模型文件危害客户端）和与旧版 0.3.7 的兼容性问题，使得相当一部分服务器拒绝迁移。SA:MP 社区自此一分为二，0.3.7 阵营与 0.3.DL 阵营长期并存。<br />
<br />
这种分裂令社区感到困惑与沮丧。有人多次在论坛呼吁将两个版本合并，但得不到任何回应。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">源码泄漏事件（2010 年起源，2018 年爆发）</h4><br />
<br />
在 0.3.DL 引发社区分裂的同一时期，另一条隐患也终于浮出水面。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年 11 月 15 日</span>，SA:MP 官方论坛上出现了一篇由用户 Kshishtof 发起的帖子，标题是《SA-MP 源代码泄漏》。帖子指向一个名为 <span style="font-weight: bold;" class="mycode_b">rw-mp.net</span> 的项目，该项目被认为是基于泄漏的 SA:MP 源代码构建的独立多人联机分支。<br />
<br />
帖子引发了社区的激烈讨论。一部分人对 rw-mp 持同情甚至欣赏的态度，认为它至少在做 SA:MP 不再愿意做的事；另一部分人则斥之为对原作的窃取与侮辱。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年 11 月 16 日</span>，Kalcor 亲自在帖子中出现，发表了两段回应。第一段揭示了这批泄漏源码的来历：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"SA:MP 的源代码于 2010 年被一名法国人从我们的服务器上黑掉，目的是为 IV:MP 这个 mod 服务。我记录并上报了这次入侵。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">GitHub 上大约有十个副本。我一直没有把它们下架，是因为提交 DMCA 申诉需要将我的真实姓名录入 GitHub 的公开 DMCA 数据库，否则就得花钱请律师。"</span></blockquote>
<br />
第二段话语气更为强硬，是一封事实上的法律警告：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"0.2.5 的源代码是通过计算机入侵从我们的服务器上盗取的。任何基于该代码发布软件的人，都涉嫌与我们作对的刑事共谋。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">SA:MP 所使用的 RakNet 版本并非开源，而是通过付费许可证使用的。BASS 音频库同样是付费许可证使用的。整个游戏 mod 社区正在被那些删除原始版权信息、将他人成果冒充自己作品重新发布的蠢货所伤害。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我给他们几天时间关闭并停止任何与 SA:MP 相关的活动。"</span></blockquote>
<br />
——Kalcor，SA:MP 官方论坛，2018 年 11 月 16 日 原帖：https://sampforum.blast.hk/showthread.php?tid=660866<br />
<br />
这段声明揭示了几个此前从未公开过的重要事实：<br />
<br />
其一，SA:MP 源码泄漏的根源远早于 2018 年——<span style="font-weight: bold;" class="mycode_b">2010 年</span>就已经发生了一次有据可查的服务器入侵事件，是一名法国黑客为了支持 IV:MP（GTA IV 的多人 mod）而实施的。这与 Kalcor 在 2019 年 pawn.wiki 文章中所说的"R* 给 MTA 的代码被用于攻击 SA:MP"形成了完整的脉络——他所遭受的代码安全威胁，来自不止一个方向。<br />
<br />
其二，Kalcor 之所以始终不对 GitHub 上的泄漏副本提交 DMCA，并非不知情或不在意，而是出于一个极具讽刺意味的现实顾虑：提交 DMCA 需要将他的真实姓名公开录入数据库，而他不愿意这样做。源码在网上流传的同时，他本人却因为隐私顾虑而放任不管。<br />
<br />
这次事件在社区中引发了新一轮关于"Kalcor 应不应该直接将 SA:MP 开源"的讨论。部分社区成员认为，既然源码已经通过非法途径广泛流传，不如主动开源，至少可以让社区以合法的方式参与改进。这个声音 Kalcor 听到了，但他的答案，在两年后的 pawn.wiki 那篇文章里已经说得很清楚。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第九章  Kalcor 眼中的历史：MTA 的旧账、R\* 的源码，与闭源的真实理由</h4><br />
<br />
编年史至此已经写了许多关于 Kalcor 的事——他的决策、他的封号、他的沉默——却始终没有给他一个真正完整的出场。他是从哪里来的？他为什么那样做？他拒绝开源的理由究竟是什么？<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2019 年 10 月 25 日</span>，就在 Kalcor 于 SA:MP 官方论坛发布某条帖子后不久，俄语 Pawn 开发者社区 pawn.wiki 上出现了一篇由用户 <span style="font-weight: bold;" class="mycode_b">m1n1vv</span> 整理、转述并翻译的长文，标题是《SA-MP 0.3.9 与 Kalcor 的新故事》。这篇文章完整记录了 Kalcor 这篇帖子的核心内容——那是迄今为止他对自己技术履历与闭源立场最完整、最直接的一次亲口陈述。<br />
<br />
以下是 Kalcor 在那篇帖子中所说的全部内容，经 m1n1vv 翻译并整理，原文以俄文发布于 pawn.wiki：<br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">那么，请允许我给你们讲一段历史。结论由你们自己得出。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2003 年，在 MTA 的 IRC 频道上待了一周之后，我被邀请加入 MTA:VC（Vice City Multiplayer）的开发。几个月后，我晋升为 MTA 的首席开发者。以下是一张截图，记录了我和 Si|ent 一起尝试让 MTA:VC 中的船只同步正常工作的画面，日期是 2003年12月31日。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我是 MTA:Blue 的少数开发者之一——这是 MTA 针对罪恶都市的新版本。那时候除我之外，大多数人都被现实生活拖住了。我开发了玩家上下文切换同步系统，并引入了 RakNet 库。同样的系统至今仍被 SA-MP 和 MTA:SA 所使用。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">这种处境让我感到沮丧——一周又一周过去，只有我一个人在提交代码，而论坛上却有一堆"开发者"在大谈特谈一切将会如何运作。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">于是我离开了 MTA 的开发。在我离开期间，另一个叫 eAi 的人加入了项目，开始研究我的代码，试图弄清楚它是怎么工作的。至少有人在做事了——他的方式是去主动联系各方，于是他通过 ICQ 找到了我，还找到了 R</span>（Rockstar Games）开发者的电子邮件地址，并与他们取得了联系。*<br />
<br />
<span style="font-style: italic;" class="mycode_i">那时候我对 GTA 多人联机并不感兴趣。我有一个乐队，还参与了 ipodlinux 等项目，但 eAi 似乎非常热衷于推动 MTA:Blue 取得进展。于是我重新加入了项目，持续了几个月。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">以下是 2004年底 MTA:Blue 的公开宣传页面存档。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">正是这件事导致了我和 MTA 其他开发者之间的决裂：我想要构建一个服务端系统——就像 VC-MP 的 ini 脚本系统，以及 SA-MP 中基于 Pawn 脚本的服务端系统；而 MTA 的开发者们则想要客户端扩展，就像那个宣传页面上描述的那样。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2005年初，我再次离开了 MTA。就在那段时间，R</span> North 在 PS2 上发布了 GTA:SA，并正在开发 PC 版本。eAi 与 R<span style="font-style: italic;" class="mycode_i"> 的技术总监有联系，还通过 ICQ 向我炫耀说，他拿到了大量 GTA:SA 源代码的头文件。我注意到，MTA 的开发者们似乎打算放弃罪恶都市版的 MTA:Blue，转战 GTA:SA。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不相信 MTA 及其开发能力，2005年中，我开始独立开发自己的多人联机。我发布了 VC-MP，基于玩家上下文切换和 RakNet。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">随后，我与 jax、spooky 以及其他一些人一起开发了 SA-MP。它远比之前的 mod 庞大得多。我们与 GTANet/GTAForums——最大的 GTA 非官方粉丝站——有着较为密切的联系，这使我们获得了更大的知名度。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">到 2008 年，SA-MP 的玩家数量是 MTA 的 10 到 20 倍。MTA 的开发者们感到在这种竞争环境下已无法与之抗衡，于是他们公开了自己的源代码。MTA 的开发者们从未询问过我或任何前任开发者，是否可以公开这些源代码。他们声称所有东西都已经被重写了，但事实并非完全如此。时至今日，MTA:SA 中仍然有我的代码。我没有费心去追究他们，因为他们看起来太蠢了——但我猜，这里那些呼吁公开 SA-MP 源代码的人，很可能是受到了 MTA 的启发，尽管他们或许不应该这样。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">而这就是现在正在发生的事：我为 MTA 开发的"游戏"代码，以及 R\</span> 给 MTA 的源代码，正在被移植进 mod\<span style="font-style: italic;" class="mycode_i">so\</span>beit——一款流行的 SA-MP 外挂工具。*<br />
<br />
<span style="font-style: italic;" class="mycode_i">你们知道这意味着什么吗？R\</span> 给 MTA 的那部分源代码，有相当大一部分被用来——攻击 SA-MP！*<br />
<br />
<span style="font-style: italic;" class="mycode_i">从一小批相当专业的 MTA 开发者起步，这件事已经演变成了极度肮脏的东西。那些想要摧毁 SA-MP 的人，对于是否违法毫不在意。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">看起来，任何被公开的源代码都可能被用来攻击 SA-MP——尽管它本可以被用于提供有价值的更新。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">公开 SA-MP 源代码这个决定，归根结底取决于：我们是否仍然处于这种充满敌意的环境中——人们在攻击我、想要攻击 SA-MP——还是这一切已经成为过去。我想说，这取决于 mod 的规模以及对外挂工具的需求程度。封闭源代码让我可以在每次发布时重新洗牌所有内部结构，使大量外挂工具失效。SA-MP 的许多"安全"更新，实质上就是我在重新排列数据，以清除现有的外挂工具。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">最终，SA-MP 将会走到这样一个时刻：所有人都彼此友善和尊重，外挂与欺诈变得罕见——但届时玩家数量将极为稀少，我们中的大多数人也已不在了。</span></blockquote>
<br />
——Kalcor，2019年10月，SA:MP 官方论坛<br />
（由 m1n1vv 转述并整理，经 Типичный Скриптер 译为俄文，发布于 pawn.wiki，2019年10月25日）<br />
<br />
<hr class="mycode_hr" />
<br />
这篇陈述，是理解 Kalcor 其人与其决策的关键文献。<br />
<br />
它第一次完整地揭示了他的来历：他不是凭空出现的 SA:MP 创始人，而是一个从 MTA 内部出走的人。<span style="font-weight: bold;" class="mycode_b">2003 年至 2005 年间，他在 MTA 团队中担任首席开发者</span>，亲手构建了玩家同步系统与 RakNet 架构——而他愤而离开，正是因为他坚持的"服务端脚本系统"方向遭到其他成员的反对。SA:MP 的诞生，某种程度上是一次对 MTA 的报复性创业。<br />
<br />
它也第一次给出了 Kalcor 拒绝开源的真实逻辑：他不是在藏私，也不是单纯的控制欲作祟——在他看来，<span style="font-weight: bold;" class="mycode_b">闭源是他对抗外挂工具的核心武器</span>。他承认 SA:MP 的许多所谓"安全更新"，实质只是重新排列内部数据结构，使依赖固定内存地址的外挂工具在新版本中失效。一旦开源，这条防线便彻底坍塌。<br />
<br />
而他与 MTA 之间的积怨，在这篇文章里也首次有了完整呈现：他认为 MTA 在开源自己的代码库时，从未征得他这位最初作者的同意；更令他愤怒的是，他随后发现，R\* 曾向 MTA 提供的部分 GTA:SA 源代码头文件，辗转流入了 SA:MP 外挂工具的制作者手中——成为攻击 SA:MP 的武器。这份偏执与防御，贯穿了他此后对待社区和开源请求的所有态度。<br />
<br />
这篇发布于 2019 年 10 月的文章，距 Kalcor 宣告放弃 SA:MP 仅剩不到一个月。这是他在离开之前，最后一次试图解释自己。<br />
<br />
<hr class="mycode_hr" />]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">圣安地列斯联机二十年：SA:MP 与 open.mp 历史</h2><br />
<br />
2026 年。GTA6 即将在今年 11 月发售，新的时代正在敲门。<br />
<br />
也是在这一年，《侠盗猎车手：圣安地列斯》PC 版上市整整二十年，SA:MP 的第一个可玩版本也已走过二十个年头。<br />
<br />
一座从未被设计为联机游戏的城市，有人在这里认识了一辈子的朋友。有人在这里第一次学会了写代码。有人在角色扮演服务器里扮演一个JC或一个黑帮头目。有人在一个无聊的下午打开了游戏，然后就再也没有那个下午了。<br />
<br />
SA:MP 从来不是一个精致的产品。它是一群人强行塞进一款单人游戏里的多人世界。它有数不清的 bug，有争议不断的管理者，有过漫长的停滞与分裂——它也有 open.mp，有一批不肯让它消失的开发者，有如今可以在手机上随时上线的客户端，不管你还记不记得服务器的 IP，不管你当年是服主、脚本开发者，还是只是一个普通的玩家——你在这里的时间是真实的。<br />
<br />
GTA6 会带来它的世界。但圣安地列斯的街道，还在。服务器还在跑，玩家还在上线，有人还在第一次输入 /register。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">前言</h3><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>本文以客观事实为准绳。所有关键事件、人物声明、原始帖文，均完整收录于正文之中，不以外部链接替代实质内容。链接仅作考证索引，供读者溯源查验，不构成叙述本身的一部分。<br />
<br />
凡引用原文处，均以引用块标注，并注明来源与时间。凡转述处，均忠实于原意，不加渲染，不作价值评判。<br />
<br />
这是一部关于热爱、控制、背叛与重建的故事，也是一个游戏社区在二十年间走过的记录。</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">卷首语：一个不该有多人模式的游戏</h3><br />
<br />
2004 年 10 月 26 日，《侠盗猎车手：圣安地列斯》（Grand Theft Auto: San Andreas）在 PlayStation 2 平台正式发售。2005 年 6 月 10 日，PC 版本上市。<br />
<br />
这款游戏从未被设计为多人联机。Rockstar Games 为它设计了一个宏大的单人故事——主角 CJ 在帮派、JC与腐败之间挣扎求生，横跨三座城市、一片乡野。游戏没有联机大厅，没有服务器浏览器，没有任何供多人游玩的接口。<br />
<br />
然而在 GTA 模组社区里，有一批人从不接受"这不可能"这个答案。<br />
<br />
他们是一群来自世界各地的年轻人，大多数有着普通的日间生活——学生、程序员、上班族——他们一点一点地撬开这款游戏的外壳，试图将它改造成一个可以容纳数百人同时在线的多人世界。<br />
<br />
这便是 SA:MP 的起点。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第一卷：诞生（2004–2006）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第一章　从 Vice City 到 San Andreas</h4><br />
<br />
在《圣安地列斯》PC 版尚未发售之前，GTA 模组社区已经有人在为《GTA 罪恶都市》（Vice City）制作多人联机改造，这个项目被命名为 <span style="font-weight: bold;" class="mycode_b">VC:MP（Vice City Multiplayer）</span>。<br />
<br />
领导这支早期团队的，是一个网名叫 <span style="font-weight: bold;" class="mycode_b">kyeman</span> 的开发者，真名 <span style="font-weight: bold;" class="mycode_b">Kye Bitossi</span>。他在 GTA 模组社区中颇有声望，是公认的技术核心人物。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2005 年 4 月初</span>，kyeman 在全球最大的 GTA 社区论坛 <span style="font-weight: bold;" class="mycode_b">GTAForums</span> 上发布了一篇帖子，正式宣布 SA:MP 项目的存在。帖子标题是：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"[WIP] SA-MP: Multiplayer for San Andreas PC"</span><br />
——kyeman，GTAForums，2005年4月3日</blockquote>
<br />
消息一出，社区立刻沸腾。预告视频和截图开始在各大 GTA 论坛流传，项目的小型社区论坛在尚未开放任何测试的情况下，已吸引了约 <span style="font-weight: bold;" class="mycode_b">120 名注册用户</span>。<br />
<br />
公开 beta 测试期间，服务器承载能力远不及涌入的测试者数量，进入测试服务器需要排队等候，等待时间往往很长。这种盛况，是对整个项目最好的背书。<br />
<br />
进入开发团队的成员，来自 GTA 模组社区的各个方向，过去的SA-MP 0.2开发者和测试者包括：kyeman、spookie、Y_Less、mike、jax、Mike、Cam、adamcs、bakasan、Born Acorn、Dalpura、Damian、Delfi、dexx、DrAke&#36;、Drift、ECLiPSE、f3llah1n、him selfe、illspirit、littlewhitey、MrJax、njr1489、Posty、PsYcHoGoD、Shizz、Simon、sockx、squiddy、Static、steve-m、The Azer、Trix、Wacko、XcR、[ULK]Crack，其中许多人既是开发者也是测试员。<br />
<br />
他们大多是业余爱好者，利用业余时间共同推进这个无人出资的项目。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第二章　合作模式的争议与团队第一次动荡</h4><br />
<br />
然而，SA:MP 从一开始便并非一片和谐。<br />
<br />
开发团队内部，关于游戏核心玩法的方向，爆发了一场至今仍被一些老玩家提起的根本性争论：<br />
<br />
一部分人主张将 SA:MP 建设为一款<span style="font-weight: bold;" class="mycode_b">合作模式（Co-op）</span>游戏，设想最多 6 名玩家共同游玩，保留完整的 NPC 行为、警察追捕系统与任务流程，让多人体验尽可能接近单人游戏的质感；<br />
<br />
另一方，以 kyeman 为首，坚持将其建设为一个能够容纳大量玩家同时在线的<span style="font-weight: bold;" class="mycode_b">大规模死亡竞技（Deathmatch）</span>式多人服务器。<br />
<br />
这场分歧并未在内部平息，而是溢出到了 GTANet 社区论坛，引发了玩家的大量公开讨论与批评，负面声音之多，令整个项目团队承受了巨大压力。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2005 年 9 月 18 日</span>，kyeman 在持续的内外压力下，宣布因个人事务无暇继续领导项目，将主导权移交给团队二号核心开发者 <span style="font-weight: bold;" class="mycode_b">spooky</span>。<br />
<br />
spooky 接手后，将项目更名为 <span style="font-weight: bold;" class="mycode_b">GTA:Multiplayer（GTA:M）</span>，以示风格与管理方式的转变。<br />
<br />
然而，约一个月后，kyeman 重新归队。合作模式方案在此期间被彻底搁置，项目名称最终改回 <span style="font-weight: bold;" class="mycode_b">San Andreas Multiplayer（SA:MP）</span>，方向确定为大规模多人在线游戏。<br />
<br />
关于"Grand Theft Auto"字样是否应出现在项目名称中，团队在命名时也有过考量——使用 Rockstar 的商标可能引发法律风险，最终以缩写"SA:MP"作为正式名称，在一定程度上规避了这一问题。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第三章　2006 年：第一个可玩版本</h4><br />
<br />
在经历了那段动荡之后，SA:MP 于 <span style="font-weight: bold;" class="mycode_b">2006 年</span> 发布了第一个向公众开放的可玩版本。<br />
<br />
从技术层面看，这是一项相当可观的成就：开发者们在完全没有官方支持的前提下，用逆向工程的方式强行将联机功能"嵌入"进一款从未被设计为多人联机的作品，使其能够支持最多 <span style="font-weight: bold;" class="mycode_b">1000 名玩家</span>同时在线，在同一片虚拟的圣安地列斯地图中驾车、射击、竞速。<br />
<br />
服务器使用 <span style="font-weight: bold;" class="mycode_b">Pawn</span> 作为脚本语言，服务器主可以自行编写游戏模式（GameMode）与过滤脚本（FilterScript）。这一设计赋予了整个生态极高的开放性——任何人只要学会 Pawn，就可以在圣安地列斯的地图上建造出属于自己的世界。<br />
<br />
0.2.2 版本是这一阶段的代表版本，也是现存有据可查的最早可玩 SA:MP 版本记录之一。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第二卷：黄金时代与暗流（2006–2009）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第四章　版本迭代与社区的兴盛</h4><br />
<br />
2006 年至 2014 年，是 SA:MP 最活跃的开发阶段。Kalcor（此时 kyeman 已开始使用这个网名）陆续发布了一系列重要版本：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">0.2 系列</span>（2006–2008）期间，SA:MP 奠定了基本架构，确立了 Pawn 脚本语言作为游戏模式开发的标准。这段时间并非全然顺利——一次大规模安全漏洞爆发，险些让整个团队就此放弃。而最终让他们坚持下来的，是一份在线请愿：短短时间内，数以千计的玩家签名支持 SA:MP 继续存在。这份来自社区的温度，让开发者重新燃起了动力。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">0.3a</span>（约 2010 年）是 SA:MP 历史上最具里程碑意义的版本之一。单服务器玩家上限从原来的数百人扩展至 <span style="font-weight: bold;" class="mycode_b">500 人</span>（后续版本更高），引入了鼠标驱动的记分板与聊天界面，增加了可编程的 NPC 机器人系统（允许服务器创建可驾驶火车、飞机的脚本机器人），网络同步质量大幅改善。<br />
<br />
此后数年，<span style="font-weight: bold;" class="mycode_b">0.3c、0.3d、0.3e、0.3x、0.3z</span> 相继发布，带来了音频流媒体支持、延迟补偿模式、自定义对象渲染距离、新的安全更新等功能。每一个版本的发布，都在 SA:MP 官方论坛的"新闻与更新"板块留下了一条由 Kalcor 亲自发布的公告。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2015 年 5 月 1 日</span>，Kalcor 发布了 SA:MP <span style="font-weight: bold;" class="mycode_b">0.3.7</span>，这是 SA:MP 有史以来最后一个带有实质性新功能的正式版本。0.3.7 新增了超过 500 个物体 ID（含特技物件与地形物件）、界面字体大小调整选项、若干新版警察皮肤、服务端对车门与车窗的控制权、为未标记警车添加警报灯的能力，以及一个简单的静态 NPC actor 系统。<br />
<br />
这个版本在此后数年间成为整个 SA:MP 生态的事实标准，直至今日仍是服务器主最常使用的版本。<br />
<br />
与此同时，这个社区在技术之外也在野蛮生长。<span style="font-weight: bold;" class="mycode_b">角色扮演（RP）服务器</span>在这段时期走向成熟，玩家们在 SA:MP 的世界中建构起了拥有经济系统、帮派政治、法律体系的虚拟社会。来自世界各地大型服务器先后崛起。SA:MP 不再只是一个小众模组，它已经成为一个真实的、活跃的、跨越语言与国境的国际社区。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第五章　Y_Less 的双重身份与 YSI 的诞生</h4><br />
<br />
在 SA:MP 的所有社区开发者中，有一个人的名字几乎是无可回避的：<span style="font-weight: bold;" class="mycode_b">Y_Less</span>，真名 Alex Cole。<br />
<br />
Y_Less 最初以 beta 测试员的身份加入 SA:MP 团队，随后正式成为开发团队成员，主要负责 Pawn 脚本语言相关的功能开发。然而，他与 Kalcor 之间的分歧，从他正式入队的第一天起便已埋下。<br />
<br />
用 Y_Less 自己后来的话说：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"加入开发团队之后，我开始开发 Pawn，但我发现自己能做的事被 Kye 严重限制。我们之间存在重大的意见分歧：他认为 90% 的开发精力应该投入同步（sync）工作，Pawn 几乎只是顺手提供一点额外功能的附属品。而我认为，虽然同步很重要，但他已经把同步覆盖得很好了，我更想专注于 Pawn 的功能与函数。然而他是老板，说了算，严重限制了我被允许做的事。此外，他有个坏习惯——每次版本迭代之后，只要在某个细枝末节的测试中有任何不稳定，就要来指责我，尽管测试本来就是我们有 beta 测试团队的原因。不用说，这不是一个好的工作环境，但我仍然喜欢 SA:MP 这个产品本身。"</span></blockquote>
<br />
在这种压抑的工作环境中，Y<span style="font-style: italic;" class="mycode_i">Less 于 <span style="font-weight: bold;" class="mycode_b">2007 年</span> 开始独立开发 <span style="font-weight: bold;" class="mycode_b">YSI（Y</span>Less' Server/Script Includes）</span>。<br />
<br />
YSI 最初是他此前若干工具的整合与升级，同时也是他在 Kalcor 的管控边界之外，以纯 Pawn 脚本的方式，实现他认为 SA:MP 脚本系统应当具备的扩展能力。他在这个过程中也加入了一些辅助性的函数，例如 player objects 功能，最初是专门为了支撑他的对象流式传输器 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">e_objects</code> 而写的。<br />
<br />
用 Y_Less 自己的话说：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"2007 年，我开始开发 YSI。这部分是对若干早期工具的更新与整合，部分也是在 Kye 的控制之外，以 Pawn 能力范围内的方式带来我认为 Pawn 所需的扩展功能——尽管以纯 Pawn 来做，能实现的事情自然有其上限。YSI 成为我的主要项目这一事实惹恼了 Kye，因为他认为这说明我没有把时间花在 SA:MP 上，尽管我实际上一直都在。"</span></blockquote>
<br />
YSI 涵盖了命令处理（y<span style="font-style: italic;" class="mycode_i">commands）、玩家迭代器（y</span>iterate）、钩子机制（y<span style="font-style: italic;" class="mycode_i">hooks）、INI 文件读写（y</span>ini）、多语言支持（y_languages）等数十个子模块，是当时 SA:MP 社区功能最全面、使用最广泛的第三方脚本库。<br />
<br />
至于"YSI"到底代表什么，连 Y_Less 本人也说不清：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"最初的想法是'Y[i]Less' Server Includes'，但 Server 和 Script 经常被混用，而且现在参与的开发者不止 Y</span>Less 一人，所以'Y'就变成了一个递归缩写，代表'YSI'本身。"[/i]</blockquote>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第六章　2008 年底：GTANet 风波与团队大出走</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2008 年底</span>，SA:MP 开发团队内部爆发了一场与 GTANet 社区相关的严重矛盾。关于这场风波的具体细节，现有的公开资料已难以完整还原，但其结果是清晰且影响深远的：<span style="font-weight: bold;" class="mycode_b">Mike、aru 和 Peter</span> 等多名核心开发者相继以此为由宣布离队。<br />
<br />
Y_Less 在日后的声明中这样描述这段经历：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"2008 年底，GTANet 风波爆发，Mike、aru 和 Peter 因此离开，我也因为团队氛围实在太差，加之大家都在走，便也一同离开了。"</span></blockquote>
<br />
这一波出走之后，SA:MP 的开发工作几乎完全落回 Kalcor 一人肩上，这进一步强化了整个项目对他个人的高度依赖，也使得社区的任何集体意见都更加难以产生实质影响。<br />
<br />
然而事情并未就此平息。Y_Less 出走后，出于他自己也说不清的原因，重新回归了团队。他在后来的声明中写道：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"不知为何，真的记不清了，我之后又重新加入了团队。那时候 Kye 想要关闭 SA:MP，我提出愿意接手，他拒绝了。然后我再次退出——不是因为我没接手到，这一点需要说明——于是 Kye 决定封禁我的论坛账号，而且不只是封号，而是彻底抹除——删掉了我所有的帖子。这意味着原版《实用函数》帖没了，旧版 FAQ 帖没了，大量迷你教程没了，《Pawn 关键词》帖也没了——我只有在非常必要的时候才发帖，那些帖子都有其存在的价值，它们的消失被大量用户注意到并提出了强烈抗议。"</span></blockquote>
<br />
这便是 2008 年底那次"第一次封号"事件的始末——相对低调，但已经是一个信号。真正震动整个社区的风波，还在后面。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第七章　2009 年 1 月：YSF 封号事件</h4><br />
<br />
从团队再度离开之后，Y<span style="font-style: italic;" class="mycode_i">Less 没有停止为社区创作工具。他开发了 <span style="font-weight: bold;" class="mycode_b">YSF（Y</span>Less' Server Fixes）</span>——一个以服务端插件形式存在的 bug 修复集合。<br />
<br />
YSF 的设计理念很简单：SA:MP 有很多 Kalcor 长期忽略或拒绝修复的 bug，既然拿不到源代码，那就通过内存操作（memory patching）的方式，在运行时强行修正这些行为。这个方法技术上相当复杂，但效果立竿见影。<br />
<br />
Y_Less 事后这样形容 YSF：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"YSF 是我最成功的项目，因为它做到了所有人都想要的事。它本质上是一个更新版的服务端——人们总是渴望新版本带来修复和新功能，功能方面已经有其他插件（包括 YSI 插件）覆盖了，所以我选择了修复这条路（以及一些小功能——显然正是这些小功能引发了麻烦）。"</span></blockquote>
<br />
YSF 在社区中广泛流传，大量服务器安装并使用它。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">2009 年 1 月 19 日</span>，事件的直接导火索被点燃。<br />
<br />
当天，Kalcor 私信给 Y_Less，表达了对 YSF 的不满。他的顾虑有两项：<br />
<br />
第一，他认为 YSF 可能与 SA:MP 未来版本产生脚本兼容性问题；第二，他认为 YSF 代码中存在与 SA:MP 服务端源代码相似的内容，以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">functions.cpp</code> 中的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">IsNickInvalid</code> 函数为例。<br />
<br />
Y_Less 对此逐一作出回应。关于兼容性问题，他指出 YSF 恰恰是在让脚本对未来版本<span style="font-weight: bold;" class="mycode_b">更加</span>兼容，而非相反；关于源代码问题，他坦言：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"这实际上并非盗用，但我承认看起来非常相似，因为它做的事情完全一样，而且也不是什么复杂的函数，我懒得争，就直接把它彻底重写了。"</span></blockquote>
<br />
他还顺带提到，Kalcor 自己曾主导过一些令他反对的修改决策——比如改变服务端的默认运行风格，以及在 0.3 版本中移除对象（最后改为以 IPL 文件形式替代，而非完全移除）——当初他的反对意见被 Kalcor 直接否决。<br />
<br />
双方讨论的最终结果，表面上是达成了共识：Kalcor 表示接受了 Y_Less 的解释，YSF 可以继续存在。<br />
<br />
然而，Y_Less 第二天登录论坛，发现自己已经被封号。<br />
<br />
他在后来的声明中还原了这段过程：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"就在我们讨论同意 YSF 可以继续存在，之后，他发现了 SetServerRule，并意识到它可以用来修改只读控制台变量——比如服务器版本号——从而让人们能够违反 SA:MP 服务条款第（g）条：'你不得人为地增加玩家数量，或向 SA:MP 查询机制提供虚假信息。'"</span></blockquote>
<br />
Kalcor 认为，Y_Less 在 YSF 中提供了这样一个功能，就等同于为违规行为提供了手段，因此必须承担责任。<br />
<br />
封号通知的原文如下（Y_Less 在声明中直接引用）：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>*"抱歉 ssǝן‾ʎ，你已被禁止使用本论坛！  <br />
滥用前开发者身份。入侵服务器，并为他人违反服务条款提供手段。"*</blockquote>
<br />
封号的同时，Kalcor 再次<span style="font-weight: bold;" class="mycode_b">删除了 Y_Less 在 SA:MP 官方论坛上的全部历史帖子</span>。大量教程、工具发布帖、FAQ 就此永久消失，众多用户注意到这些帖子的蒸发，并提出了强烈抗议。<br />
<br />
Y_Less 随即在社区发布了一篇完整声明，以下是他原文的核心段落：<br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"基本上，我因为 YSF 被 SA:MP 官方论坛封号了！</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">历史：</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">200x 年（实在记不清了），在与 Spookie 讨论之后，我以 beta 测试员的身份加入了 SA:MP 团队——那还是第一次公开 beta 之前的事——并开始编写 Pawn 相关的代码。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">没过多久，我正式加入了开发团队，专注于 Pawn 的开发，但我很快发现自己受到 Kye 的诸多限制，做不了想做的事。我们之间存在重大分歧：他认为 90% 的开发精力应该用于同步（sync），Pawn 只是顺手提供一点额外功能的附属品；而我认为，虽然同步很重要，但他已经把同步做得很好了，我更想把时间花在 Pawn 的功能扩展上。然而他是老板，说了算，严重限制了我能做的事。更让人受不了的是，他有个习惯——每次版本迭代后，只要在某个犄角旮旯的测试里出了任何小问题，就要来责怪我，哪怕我们有 beta 测试团队本来就是为了发现这些问题的。说实话那不是一个好的工作环境，但我还是喜欢 SA:MP 这个产品本身。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2007 年，我开始开发 YSI。这一方面是对此前一批旧项目的整合升级，另一方面也是想在 Kye 的管控之外，以纯 Pawn 脚本的方式实现我认为 Pawn 所需要的扩展功能——尽管能做到的事情有限，毕竟纯 Pawn 本身有其局限（我确实额外添加了一些辅助函数，比如 player objects 功能完全是为了写我最初的对象流式传输器 e\_objects 而专门实现的）。YSI 成为我的主要项目这件事惹恼了 Kye，因为他觉得我没有把时间花在 SA:MP 上——尽管我实际上一直都在。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2008 年底，GTANet 社区风波爆发，Mike、aru 和 Peter 因此离队。我也因为团队氛围实在太差，加上大家都在走，便也跟着离开了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不知为何（真的记不清了），我之后又重新回归了团队。那时候 Kye 想要关闭 SA:MP，我主动提出愿意接手，他拒绝了。然后我再次退出——不是因为没接手到，这一点需要说清楚——于是 Kye 决定封禁我的论坛账号，而且不只是封号，而是彻底抹除，删掉了我所有的帖子。这意味着原版《实用函数》帖没了，旧版 FAQ 帖没了，大量迷你教程没了，《Pawn 关键词》帖也没了——我只有在非常必要的时候才会发帖，那些帖子都有其价值，它们的消失被大量用户注意到并提出了抗议。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不管怎样，我还是喜欢 SA:MP 和这个社区本身（至少喜欢其中的一部分），所以我还是留了下来（现在回想起来真不知道当时为什么，深感后悔），并继续努力让 SA:MP 变得更好——尽管 Kye 的存在让这件事很难。我继续开发 YSI、写教程和帮助帖，后来又创作了 YSF。YSF 大概是我最成功的项目了，因为它做到了所有人都想要的事。它本质上就是一个改进版的服务端——人们总是渴望新版本带来修复和新功能，功能方面已经有其他插件（包括 YSI 插件）覆盖了，所以我选择了专注于修复这条路（以及一些小功能——显然正是这些小功能引发了这次麻烦）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">总之，Kye 和我一般都各自行事、互不干扰（至少我是这么以为的），有一段时间相安无事。直到 2009 年 1 月 19 日，我收到了 Kye 的消息，说他不太喜欢我在 YSF 里做的事。经过一番交涉，才明白他的顾虑在于：YSF 可能与未来版本的脚本产生兼容性问题（这话从他嘴里说出来真是讽刺——我当初就反对过他把默认运行方式改掉，以及 0.3 版本里删除对象的决定，但他否决了我；对象最后是改成了 IPL 文件的形式，而非完全删除，但也没有了 per-player objects，至少我最后听到的消息是这样）。此外，他还质疑 YSF 里有 SA:MP 服务端的源代码——他举的例子是 functions.cpp 里的 IsNickInvalid 函数。这个函数其实不是照抄的，但我承认看起来确实很像，毕竟它做的事完全一样，而且也不是什么复杂的函数，我懒得争，就直接把它彻底重写了。在我指出 YSF 并不会造成兼容性问题（恰恰相反，它让脚本对未来版本的兼容性更好），并同意日后不再使用 SA:MP 源代码（尽管我此前一直在刻意避免这样做）之后，他让步了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">第二天我上论坛，发现自己已经被封了……</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">原来在我们达成共识之后，他又发现了 SetServerRule 这个功能，意识到它可以用来修改只读控制台变量（比如服务器版本号），从而让人能够违反 SA:MP 服务条款第（g）条：'你不得人为地增加玩家数量，或向 SA:MP 查询机制提供虚假信息。'</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我解释说，我本人根本没有这样做，这个功能的设计初衷是好的，只是不幸被人滥用了。我甚至想过反问他：他提供论坛和 IRC 频道，同样也给人们提供了违反条款（c）（d）条的方式，按他的逻辑，他也应该被封号——但我懒得说了。封号通知的原文是：</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">'抱歉 ssǝן‾ʎ，你已被禁止使用本论坛！滥用前开发者身份。入侵服务器，并为他人违反服务条款提供手段。'</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">所谓'滥用'，是指我用它改善了所有人的游戏体验；所谓'入侵服务器'，是指我修复了它；所谓'提供手段'，意思是人们可以拿我提供的工具做坏事——但这不代表我支持或认可这种行为，这只是一个有用工具所带来的无奈副作用。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">Kye 说 YSF 的事已经覆水难收，他只能发布新版本来屏蔽它，伤害已经造成，它已经广泛传播，人们正在用它黑自己的服务器，没有人能阻止，所以我必须被封。我回应说，如果我没被封，我本来可以发布最新版本，在修复拾取物 bug 的同时，加入对规则的只读标志检查——虽然这无法彻底解决问题，但能大幅减少滥用，因为几乎没有人会主动把它改回旧方式，大多数人会为了这个重要修复而升级。说到这里，他就不再回复我了（我觉得他是意识到自己断掉了快速、高效解决这件事的唯一合理途径，然后不想认账了——如果不是这样，我欢迎他来回应）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">总之，我决定把当时正在写的那段代码（YSI 的示例脚本）收个尾，毕竟我还是喜欢使用 YSI 的那些人，上传最终版本，然后就此结束。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">所以，截至目前：YSI 1.0、YSF 1.0、YSI2 1.0、YPI 1.0，到此为止，我不干了。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言：Kye 正在研究一种过滤"修改版本服务端"并将其列入黑名单的机制——我可能会发布一个不自动修改版本号的 YSF 版本，这样用它的人就不会因为我的失误被连坐；请留意这里的动态（我可能也会顺带加入拾取物修复，但不会保留只读变量相关的功能）。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言二：IRC 才是王道，我还活跃在 GTANet 的大量频道里，包括 #YSI 和 #Y_Less，欢迎来找我。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">附言三：不知道 MTA 的源代码长什么样……</span>"</blockquote>
<br />
——Y_Less，2009年1月，TMS Forums<br />
<br />
<hr class="mycode_hr" />
<br />
这篇声明在社区引发了强烈反响。数日后，经社区压力，Y_Less 得以解封，YSF 在不修改只读变量的前提下被允许继续使用。从表面上看，风波平息了。<br />
<br />
但那句"附言三"——"不知道 MTA 的源代码长什么样"——如今读来，已不再只是一句无心之语。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第三卷：停滞、管控与分歧（2014–2019）</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第八章　0.3.7 之后的沉寂（含源码泄漏事件）</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2015 年 5 月 1 日</span>，SA:MP <span style="font-weight: bold;" class="mycode_b">0.3.7</span> 发布。此后，Kalcor 在新功能层面的开发近乎陷入停滞。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年前后</span>，Kalcor 发布了 <span style="font-weight: bold;" class="mycode_b">SA-MP 0.3.DL</span>——一个支持服务端向玩家客户端推送自定义模型（Download Content）的版本。这是社区长期以来最渴望的功能之一，玩家们可以在 SA:MP 服务器上看到服务器自定义的车辆、皮肤、物件模型，而不再局限于原版游戏资产。<br />
<br />
然而 0.3.DL 的推出并不顺利：安全问题（恶意服务器可能推送损坏的模型文件危害客户端）和与旧版 0.3.7 的兼容性问题，使得相当一部分服务器拒绝迁移。SA:MP 社区自此一分为二，0.3.7 阵营与 0.3.DL 阵营长期并存。<br />
<br />
这种分裂令社区感到困惑与沮丧。有人多次在论坛呼吁将两个版本合并，但得不到任何回应。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">源码泄漏事件（2010 年起源，2018 年爆发）</h4><br />
<br />
在 0.3.DL 引发社区分裂的同一时期，另一条隐患也终于浮出水面。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年 11 月 15 日</span>，SA:MP 官方论坛上出现了一篇由用户 Kshishtof 发起的帖子，标题是《SA-MP 源代码泄漏》。帖子指向一个名为 <span style="font-weight: bold;" class="mycode_b">rw-mp.net</span> 的项目，该项目被认为是基于泄漏的 SA:MP 源代码构建的独立多人联机分支。<br />
<br />
帖子引发了社区的激烈讨论。一部分人对 rw-mp 持同情甚至欣赏的态度，认为它至少在做 SA:MP 不再愿意做的事；另一部分人则斥之为对原作的窃取与侮辱。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2018 年 11 月 16 日</span>，Kalcor 亲自在帖子中出现，发表了两段回应。第一段揭示了这批泄漏源码的来历：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"SA:MP 的源代码于 2010 年被一名法国人从我们的服务器上黑掉，目的是为 IV:MP 这个 mod 服务。我记录并上报了这次入侵。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">GitHub 上大约有十个副本。我一直没有把它们下架，是因为提交 DMCA 申诉需要将我的真实姓名录入 GitHub 的公开 DMCA 数据库，否则就得花钱请律师。"</span></blockquote>
<br />
第二段话语气更为强硬，是一封事实上的法律警告：<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">"0.2.5 的源代码是通过计算机入侵从我们的服务器上盗取的。任何基于该代码发布软件的人，都涉嫌与我们作对的刑事共谋。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">SA:MP 所使用的 RakNet 版本并非开源，而是通过付费许可证使用的。BASS 音频库同样是付费许可证使用的。整个游戏 mod 社区正在被那些删除原始版权信息、将他人成果冒充自己作品重新发布的蠢货所伤害。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我给他们几天时间关闭并停止任何与 SA:MP 相关的活动。"</span></blockquote>
<br />
——Kalcor，SA:MP 官方论坛，2018 年 11 月 16 日 原帖：https://sampforum.blast.hk/showthread.php?tid=660866<br />
<br />
这段声明揭示了几个此前从未公开过的重要事实：<br />
<br />
其一，SA:MP 源码泄漏的根源远早于 2018 年——<span style="font-weight: bold;" class="mycode_b">2010 年</span>就已经发生了一次有据可查的服务器入侵事件，是一名法国黑客为了支持 IV:MP（GTA IV 的多人 mod）而实施的。这与 Kalcor 在 2019 年 pawn.wiki 文章中所说的"R* 给 MTA 的代码被用于攻击 SA:MP"形成了完整的脉络——他所遭受的代码安全威胁，来自不止一个方向。<br />
<br />
其二，Kalcor 之所以始终不对 GitHub 上的泄漏副本提交 DMCA，并非不知情或不在意，而是出于一个极具讽刺意味的现实顾虑：提交 DMCA 需要将他的真实姓名公开录入数据库，而他不愿意这样做。源码在网上流传的同时，他本人却因为隐私顾虑而放任不管。<br />
<br />
这次事件在社区中引发了新一轮关于"Kalcor 应不应该直接将 SA:MP 开源"的讨论。部分社区成员认为，既然源码已经通过非法途径广泛流传，不如主动开源，至少可以让社区以合法的方式参与改进。这个声音 Kalcor 听到了，但他的答案，在两年后的 pawn.wiki 那篇文章里已经说得很清楚。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第九章  Kalcor 眼中的历史：MTA 的旧账、R\* 的源码，与闭源的真实理由</h4><br />
<br />
编年史至此已经写了许多关于 Kalcor 的事——他的决策、他的封号、他的沉默——却始终没有给他一个真正完整的出场。他是从哪里来的？他为什么那样做？他拒绝开源的理由究竟是什么？<br />
<br />
<span style="font-weight: bold;" class="mycode_b">2019 年 10 月 25 日</span>，就在 Kalcor 于 SA:MP 官方论坛发布某条帖子后不久，俄语 Pawn 开发者社区 pawn.wiki 上出现了一篇由用户 <span style="font-weight: bold;" class="mycode_b">m1n1vv</span> 整理、转述并翻译的长文，标题是《SA-MP 0.3.9 与 Kalcor 的新故事》。这篇文章完整记录了 Kalcor 这篇帖子的核心内容——那是迄今为止他对自己技术履历与闭源立场最完整、最直接的一次亲口陈述。<br />
<br />
以下是 Kalcor 在那篇帖子中所说的全部内容，经 m1n1vv 翻译并整理，原文以俄文发布于 pawn.wiki：<br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-style: italic;" class="mycode_i">那么，请允许我给你们讲一段历史。结论由你们自己得出。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2003 年，在 MTA 的 IRC 频道上待了一周之后，我被邀请加入 MTA:VC（Vice City Multiplayer）的开发。几个月后，我晋升为 MTA 的首席开发者。以下是一张截图，记录了我和 Si|ent 一起尝试让 MTA:VC 中的船只同步正常工作的画面，日期是 2003年12月31日。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">我是 MTA:Blue 的少数开发者之一——这是 MTA 针对罪恶都市的新版本。那时候除我之外，大多数人都被现实生活拖住了。我开发了玩家上下文切换同步系统，并引入了 RakNet 库。同样的系统至今仍被 SA-MP 和 MTA:SA 所使用。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">这种处境让我感到沮丧——一周又一周过去，只有我一个人在提交代码，而论坛上却有一堆"开发者"在大谈特谈一切将会如何运作。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">于是我离开了 MTA 的开发。在我离开期间，另一个叫 eAi 的人加入了项目，开始研究我的代码，试图弄清楚它是怎么工作的。至少有人在做事了——他的方式是去主动联系各方，于是他通过 ICQ 找到了我，还找到了 R</span>（Rockstar Games）开发者的电子邮件地址，并与他们取得了联系。*<br />
<br />
<span style="font-style: italic;" class="mycode_i">那时候我对 GTA 多人联机并不感兴趣。我有一个乐队，还参与了 ipodlinux 等项目，但 eAi 似乎非常热衷于推动 MTA:Blue 取得进展。于是我重新加入了项目，持续了几个月。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">以下是 2004年底 MTA:Blue 的公开宣传页面存档。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">正是这件事导致了我和 MTA 其他开发者之间的决裂：我想要构建一个服务端系统——就像 VC-MP 的 ini 脚本系统，以及 SA-MP 中基于 Pawn 脚本的服务端系统；而 MTA 的开发者们则想要客户端扩展，就像那个宣传页面上描述的那样。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">2005年初，我再次离开了 MTA。就在那段时间，R</span> North 在 PS2 上发布了 GTA:SA，并正在开发 PC 版本。eAi 与 R<span style="font-style: italic;" class="mycode_i"> 的技术总监有联系，还通过 ICQ 向我炫耀说，他拿到了大量 GTA:SA 源代码的头文件。我注意到，MTA 的开发者们似乎打算放弃罪恶都市版的 MTA:Blue，转战 GTA:SA。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">不相信 MTA 及其开发能力，2005年中，我开始独立开发自己的多人联机。我发布了 VC-MP，基于玩家上下文切换和 RakNet。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">随后，我与 jax、spooky 以及其他一些人一起开发了 SA-MP。它远比之前的 mod 庞大得多。我们与 GTANet/GTAForums——最大的 GTA 非官方粉丝站——有着较为密切的联系，这使我们获得了更大的知名度。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">到 2008 年，SA-MP 的玩家数量是 MTA 的 10 到 20 倍。MTA 的开发者们感到在这种竞争环境下已无法与之抗衡，于是他们公开了自己的源代码。MTA 的开发者们从未询问过我或任何前任开发者，是否可以公开这些源代码。他们声称所有东西都已经被重写了，但事实并非完全如此。时至今日，MTA:SA 中仍然有我的代码。我没有费心去追究他们，因为他们看起来太蠢了——但我猜，这里那些呼吁公开 SA-MP 源代码的人，很可能是受到了 MTA 的启发，尽管他们或许不应该这样。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">而这就是现在正在发生的事：我为 MTA 开发的"游戏"代码，以及 R\</span> 给 MTA 的源代码，正在被移植进 mod\<span style="font-style: italic;" class="mycode_i">so\</span>beit——一款流行的 SA-MP 外挂工具。*<br />
<br />
<span style="font-style: italic;" class="mycode_i">你们知道这意味着什么吗？R\</span> 给 MTA 的那部分源代码，有相当大一部分被用来——攻击 SA-MP！*<br />
<br />
<span style="font-style: italic;" class="mycode_i">从一小批相当专业的 MTA 开发者起步，这件事已经演变成了极度肮脏的东西。那些想要摧毁 SA-MP 的人，对于是否违法毫不在意。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">看起来，任何被公开的源代码都可能被用来攻击 SA-MP——尽管它本可以被用于提供有价值的更新。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">公开 SA-MP 源代码这个决定，归根结底取决于：我们是否仍然处于这种充满敌意的环境中——人们在攻击我、想要攻击 SA-MP——还是这一切已经成为过去。我想说，这取决于 mod 的规模以及对外挂工具的需求程度。封闭源代码让我可以在每次发布时重新洗牌所有内部结构，使大量外挂工具失效。SA-MP 的许多"安全"更新，实质上就是我在重新排列数据，以清除现有的外挂工具。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">最终，SA-MP 将会走到这样一个时刻：所有人都彼此友善和尊重，外挂与欺诈变得罕见——但届时玩家数量将极为稀少，我们中的大多数人也已不在了。</span></blockquote>
<br />
——Kalcor，2019年10月，SA:MP 官方论坛<br />
（由 m1n1vv 转述并整理，经 Типичный Скриптер 译为俄文，发布于 pawn.wiki，2019年10月25日）<br />
<br />
<hr class="mycode_hr" />
<br />
这篇陈述，是理解 Kalcor 其人与其决策的关键文献。<br />
<br />
它第一次完整地揭示了他的来历：他不是凭空出现的 SA:MP 创始人，而是一个从 MTA 内部出走的人。<span style="font-weight: bold;" class="mycode_b">2003 年至 2005 年间，他在 MTA 团队中担任首席开发者</span>，亲手构建了玩家同步系统与 RakNet 架构——而他愤而离开，正是因为他坚持的"服务端脚本系统"方向遭到其他成员的反对。SA:MP 的诞生，某种程度上是一次对 MTA 的报复性创业。<br />
<br />
它也第一次给出了 Kalcor 拒绝开源的真实逻辑：他不是在藏私，也不是单纯的控制欲作祟——在他看来，<span style="font-weight: bold;" class="mycode_b">闭源是他对抗外挂工具的核心武器</span>。他承认 SA:MP 的许多所谓"安全更新"，实质只是重新排列内部数据结构，使依赖固定内存地址的外挂工具在新版本中失效。一旦开源，这条防线便彻底坍塌。<br />
<br />
而他与 MTA 之间的积怨，在这篇文章里也首次有了完整呈现：他认为 MTA 在开源自己的代码库时，从未征得他这位最初作者的同意；更令他愤怒的是，他随后发现，R\* 曾向 MTA 提供的部分 GTA:SA 源代码头文件，辗转流入了 SA:MP 外挂工具的制作者手中——成为攻击 SA:MP 的武器。这份偏执与防御，贯穿了他此后对待社区和开源请求的所有态度。<br />
<br />
这篇发布于 2019 年 10 月的文章，距 Kalcor 宣告放弃 SA:MP 仅剩不到一个月。这是他在离开之前，最后一次试图解释自己。<br />
<br />
<hr class="mycode_hr" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[考古] openmp 常见问题解答 | 2020年4月]]></title>
			<link>https://open-mp.cn/showthread.php?tid=29</link>
			<pubDate>Tue, 24 Mar 2026 16:55:00 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=29</guid>
			<description><![CDATA[<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">GTA SA 和 SA:MP 中的漏洞会被修复吗？</span><br />
<br />
会的！<br />
你也可以向我们反馈我们尚未知晓的 bug：github.com/openmultiplayer/samp-bugs/<br />
或在论坛提交：burgershot.gg/showthread.php?tid=99<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 会支持哪些 SA:MP 版本？包括 0.3DL 吗？</span><br />
<br />
我们不会支持 0.3.7 以下的版本，但你可以自行实现（这正是开源的魅力所在）。<br />
如果大多数服务器都尝试使用 0.3DL，我们会跟进支持。我们也做过调查，多数人支持 0.3DL，所以这件事大概率会做，但不会出现在客户端的前几个版本中。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 客户端会有固定的更新周期吗？</span><br />
<br />
不会。固定周期需要一支流程成熟的大型团队，而我们目前是一支志愿者队伍。<br />
也许情况将来会有所改变，我们不敢打包票。代码开源之后，你们可以随时关注项目进展。我们会尽一切努力在版本更新之间保持与社区的沟通。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">我们可以提交新功能建议吗？</span><br />
<br />
我们非常欢迎社区参与，你可以在这里留下你的建议：burgershot.gg/forumdisplay.php?fid=42&amp;page=6<br />
<br />
当然，我们无法保证每个想法都会被采纳和实现。但由于代码是开源的，你随时可以自己动手实现。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">会有反作弊系统吗？</span><br />
<br />
会有。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 会继续使用 Pawn 吗？可以使用其他语言吗？</span><br />
<br />
所有的开发工作、测试和文档均以 Pawn 为基础完成。不过，我们提供了 C API，允许任何人在此之上实现其他语言的支持。<br />
<br />
我们也讨论过引入一些半官方的语言模块，但 Pawn 依然是主要且受官方支持的脚本语言。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">SA:MP 的插件能在 open.mp 中使用吗？</span><br />
<br />
"插件"这个词目前用来指代旧式插件——即那些为 SA-MP 编写的插件（例如 sscanf、MySQL 等）。open.mp 提供了加载这些现有插件的 API。<br />
<br />
我们对新式插件的称呼是"模块"——无论是外部插件还是内部代码，只要使用 open.mp 更新、更强大的 API，统称为模块。<br />
<br />
旧式插件仍然可以正常运行，并会持续得到支持，除非它们依赖内存黑客手段（例如 YSF），因为那类插件依赖特定的内存地址和数据结构，而这些在 open.mp 服务端上是完全不同的。不过，大多数老式内存黑客当初存在的意义，恰恰是为了补全一些功能——而这些功能将直接内置于 open.mp，所以那些插件本来也就用不着了。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">数据库功能只能用 SQLite，还是也可以用 MySQL？</span><br />
<br />
默认的数据库功能与以前一样，仍然是 SQLite。但如前所述，open.mp 提供了加载现有插件的 API，因此数据库方面无需在内部做任何改动——通过现有插件依然可以实现。<br />
<br />
第三方模块在 open.mp 中是完全受支持的"一等公民"——无论是回调还是原生函数，其可用性与内部代码完全一致，因此将功能放入外部模块不存在任何劣势。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">HUD、体力值、小游戏（台球、健身房等）、车辆选项、路线指示、SA:MP+ 功能等会有更多自定义选项吗？会支持更灵活的图形界面，而不是像 SA:MP 那样只能用有限的文字绘制吗？CEF 呢？这些内容会如何保障安全？</span><br />
<br />
关于这个话题我们收到了太多提问，请先去泡杯茶——这个回答会有点长。<br />
<br />
我们的开发团队里有 Hual（SA:MP+ 的作者），未来会带来什么，谁知道呢？?<br />
<br />
SA:MP 与 MTA 最本质的区别，其实在名字里就说得很清楚了——SA:MP 就是字面意思上的"圣安地列斯多人游戏"，是 GTA 圣安地列斯这款游戏的多人版本；而 MTA 则是一个架设在这个世界观之上、更偏向通用平台的存在。<br />
<br />
SA:MP 在加入新功能时，始终紧扣原版游戏的体验感，尽管走出框架并非不可能，但整体风格一直非常保守。<br />
<br />
我们之所以长期坚守 SA:MP，正是因为认同这种态度。但我们希望拥有更多一点的自由度（这也是我们另起炉灶的原因），同时又不想走得太远。我们会引入一些新功能，其中有些在原版游戏中并不存在，但我们仍然会审慎地权衡每个功能带来的影响。<br />
<br />
让对话框稍微宽一点，算是突破 GTA 正统边界的疯狂改动吗？大概不算。<br />
<br />
加入 CEF 是否走得太远了？是的，这不会发生。?‍♂️<br />
<br />
平衡点就在两者之间。<br />
<br />
话虽如此，玩家们向来能在有限的支持下迸发出令人惊叹的创造力，我们相信这一点不会改变。我们会始终鼓励玩家和开发者尽情发挥创意——这也是我们选择开源的原因之一，我们甚至会在这方面提供帮助，但这不会是我们的核心任务。<br />
<br />
我们最主要的顾虑集中在客户端层面。我们不希望服务器主可以向玩家分发任何具有潜在危害的内容。圣安地列斯本身并非为多人游戏或 mod 而设计，许多文件加载器对损坏或恶意文件缺乏防护——当初根本没有这方面的需求。这正是 SA:MP 在引入自定义模型时遇到的难题，对我们来说同样如此。<br />
<br />
每当我们要对游戏的某个部分进行自定义，都必须先确保对应的文件格式和加载器不存在可利用的漏洞。我们可以确认，模型和脚本已经出现过被攻击的案例，其他部分可能也已经被攻击，而一旦我们开始允许服务器上传任意文件，被攻击几乎是必然的。<br />
<br />
至于资源保护——坦率地说，这在根本上是无法实现的。要让客户端显示一个自定义模型，就必须把这个模型文件传给它。文件一旦传到客户端，它就在对方的电脑上了，对方拿它怎么做，我们管不了。有些方法可以让盗取变得麻烦一些，但没有哪种方法是绝对可靠的。网络上虽然存在 DRM、安全隔离区等手段，但要使用这些技术，就必须牺牲开源原则。可以参考一下 EME 标准以及 Firefox 中内嵌闭源二进制文件所引发的争议。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">NPC 会有更好的支持吗？</span><br />
<br />
这不是我们当前的优先事项，但从客户端角度来看，NPC 本质上与普通玩家没有区别。我们至少希望 open.mp 的 NPC 功能能够对标 FCNPC 插件的水平，这是未来版本中我们可以认真考虑的方向。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">你们说 open.mp 移除了所有限制——这具体是怎么实现的？它像 streamer 插件一样吗？</span><br />
<br />
原理类似，但与 streamer 相比集成度更高，因此我们同样可以对载具和玩家进行流式处理，并能以远超插件能力的方式操作本地 ID。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">玩家可以被附加到物体上吗？</span><br />
<br />
可以，我们已经实现了这个功能。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 完成 SA:MP 功能的复现之后，接下来会新增什么？</span><br />
<br />
我们很喜欢聊未来的计划——持续关注我们就好，你们会看到的。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">可以用 SA:MP 客户端连接 open.mp 服务器吗？</span><br />
<br />
SA:MP 是通过逆向工程对第三方程序进行交互的 mod，open.mp 也是如此，我们的法律立场与 SA:MP 完全相同。我们没有使用任何 SA:MP 的泄露源代码——这一点已经反复强调，代码开源之后，社区自然会看得清清楚楚。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">新版 open.mp 客户端最大的挑战是什么？</span><br />
<br />
把它写出来！<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">五年后，你们认为 open.mp 会是什么样子？</span><br />
<br />
不必担心这个，我们有很多长远的想法。?<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">五年后，你们认为 SA-MP 会是什么样子？</span><br />
<br />
那是 SA-MP 团队的事，不是我们该操心的——在这个问题上我们没有立场去猜测。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">你们有没有想过放弃 open.mp？</span><br />
<br />
有过，因为我们也是普通人。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">最后，也是被问得最多的问题：</span><br />
<span style="font-weight: bold;" class="mycode_b">我们什么时候才能看到 open.mp？</span><br />
<br />
等它准备好了。???<br />
<br />
<hr class="mycode_hr" />
<br />
祝大家接下来的一周愉快！<br />
<br />
带着满满的爱，<br />
open.mp 团队 ?]]></description>
			<content:encoded><![CDATA[<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">GTA SA 和 SA:MP 中的漏洞会被修复吗？</span><br />
<br />
会的！<br />
你也可以向我们反馈我们尚未知晓的 bug：github.com/openmultiplayer/samp-bugs/<br />
或在论坛提交：burgershot.gg/showthread.php?tid=99<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 会支持哪些 SA:MP 版本？包括 0.3DL 吗？</span><br />
<br />
我们不会支持 0.3.7 以下的版本，但你可以自行实现（这正是开源的魅力所在）。<br />
如果大多数服务器都尝试使用 0.3DL，我们会跟进支持。我们也做过调查，多数人支持 0.3DL，所以这件事大概率会做，但不会出现在客户端的前几个版本中。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 客户端会有固定的更新周期吗？</span><br />
<br />
不会。固定周期需要一支流程成熟的大型团队，而我们目前是一支志愿者队伍。<br />
也许情况将来会有所改变，我们不敢打包票。代码开源之后，你们可以随时关注项目进展。我们会尽一切努力在版本更新之间保持与社区的沟通。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">我们可以提交新功能建议吗？</span><br />
<br />
我们非常欢迎社区参与，你可以在这里留下你的建议：burgershot.gg/forumdisplay.php?fid=42&amp;page=6<br />
<br />
当然，我们无法保证每个想法都会被采纳和实现。但由于代码是开源的，你随时可以自己动手实现。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">会有反作弊系统吗？</span><br />
<br />
会有。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 会继续使用 Pawn 吗？可以使用其他语言吗？</span><br />
<br />
所有的开发工作、测试和文档均以 Pawn 为基础完成。不过，我们提供了 C API，允许任何人在此之上实现其他语言的支持。<br />
<br />
我们也讨论过引入一些半官方的语言模块，但 Pawn 依然是主要且受官方支持的脚本语言。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">SA:MP 的插件能在 open.mp 中使用吗？</span><br />
<br />
"插件"这个词目前用来指代旧式插件——即那些为 SA-MP 编写的插件（例如 sscanf、MySQL 等）。open.mp 提供了加载这些现有插件的 API。<br />
<br />
我们对新式插件的称呼是"模块"——无论是外部插件还是内部代码，只要使用 open.mp 更新、更强大的 API，统称为模块。<br />
<br />
旧式插件仍然可以正常运行，并会持续得到支持，除非它们依赖内存黑客手段（例如 YSF），因为那类插件依赖特定的内存地址和数据结构，而这些在 open.mp 服务端上是完全不同的。不过，大多数老式内存黑客当初存在的意义，恰恰是为了补全一些功能——而这些功能将直接内置于 open.mp，所以那些插件本来也就用不着了。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">数据库功能只能用 SQLite，还是也可以用 MySQL？</span><br />
<br />
默认的数据库功能与以前一样，仍然是 SQLite。但如前所述，open.mp 提供了加载现有插件的 API，因此数据库方面无需在内部做任何改动——通过现有插件依然可以实现。<br />
<br />
第三方模块在 open.mp 中是完全受支持的"一等公民"——无论是回调还是原生函数，其可用性与内部代码完全一致，因此将功能放入外部模块不存在任何劣势。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">HUD、体力值、小游戏（台球、健身房等）、车辆选项、路线指示、SA:MP+ 功能等会有更多自定义选项吗？会支持更灵活的图形界面，而不是像 SA:MP 那样只能用有限的文字绘制吗？CEF 呢？这些内容会如何保障安全？</span><br />
<br />
关于这个话题我们收到了太多提问，请先去泡杯茶——这个回答会有点长。<br />
<br />
我们的开发团队里有 Hual（SA:MP+ 的作者），未来会带来什么，谁知道呢？?<br />
<br />
SA:MP 与 MTA 最本质的区别，其实在名字里就说得很清楚了——SA:MP 就是字面意思上的"圣安地列斯多人游戏"，是 GTA 圣安地列斯这款游戏的多人版本；而 MTA 则是一个架设在这个世界观之上、更偏向通用平台的存在。<br />
<br />
SA:MP 在加入新功能时，始终紧扣原版游戏的体验感，尽管走出框架并非不可能，但整体风格一直非常保守。<br />
<br />
我们之所以长期坚守 SA:MP，正是因为认同这种态度。但我们希望拥有更多一点的自由度（这也是我们另起炉灶的原因），同时又不想走得太远。我们会引入一些新功能，其中有些在原版游戏中并不存在，但我们仍然会审慎地权衡每个功能带来的影响。<br />
<br />
让对话框稍微宽一点，算是突破 GTA 正统边界的疯狂改动吗？大概不算。<br />
<br />
加入 CEF 是否走得太远了？是的，这不会发生。?‍♂️<br />
<br />
平衡点就在两者之间。<br />
<br />
话虽如此，玩家们向来能在有限的支持下迸发出令人惊叹的创造力，我们相信这一点不会改变。我们会始终鼓励玩家和开发者尽情发挥创意——这也是我们选择开源的原因之一，我们甚至会在这方面提供帮助，但这不会是我们的核心任务。<br />
<br />
我们最主要的顾虑集中在客户端层面。我们不希望服务器主可以向玩家分发任何具有潜在危害的内容。圣安地列斯本身并非为多人游戏或 mod 而设计，许多文件加载器对损坏或恶意文件缺乏防护——当初根本没有这方面的需求。这正是 SA:MP 在引入自定义模型时遇到的难题，对我们来说同样如此。<br />
<br />
每当我们要对游戏的某个部分进行自定义，都必须先确保对应的文件格式和加载器不存在可利用的漏洞。我们可以确认，模型和脚本已经出现过被攻击的案例，其他部分可能也已经被攻击，而一旦我们开始允许服务器上传任意文件，被攻击几乎是必然的。<br />
<br />
至于资源保护——坦率地说，这在根本上是无法实现的。要让客户端显示一个自定义模型，就必须把这个模型文件传给它。文件一旦传到客户端，它就在对方的电脑上了，对方拿它怎么做，我们管不了。有些方法可以让盗取变得麻烦一些，但没有哪种方法是绝对可靠的。网络上虽然存在 DRM、安全隔离区等手段，但要使用这些技术，就必须牺牲开源原则。可以参考一下 EME 标准以及 Firefox 中内嵌闭源二进制文件所引发的争议。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">NPC 会有更好的支持吗？</span><br />
<br />
这不是我们当前的优先事项，但从客户端角度来看，NPC 本质上与普通玩家没有区别。我们至少希望 open.mp 的 NPC 功能能够对标 FCNPC 插件的水平，这是未来版本中我们可以认真考虑的方向。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">你们说 open.mp 移除了所有限制——这具体是怎么实现的？它像 streamer 插件一样吗？</span><br />
<br />
原理类似，但与 streamer 相比集成度更高，因此我们同样可以对载具和玩家进行流式处理，并能以远超插件能力的方式操作本地 ID。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">玩家可以被附加到物体上吗？</span><br />
<br />
可以，我们已经实现了这个功能。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">open.mp 完成 SA:MP 功能的复现之后，接下来会新增什么？</span><br />
<br />
我们很喜欢聊未来的计划——持续关注我们就好，你们会看到的。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">可以用 SA:MP 客户端连接 open.mp 服务器吗？</span><br />
<br />
SA:MP 是通过逆向工程对第三方程序进行交互的 mod，open.mp 也是如此，我们的法律立场与 SA:MP 完全相同。我们没有使用任何 SA:MP 的泄露源代码——这一点已经反复强调，代码开源之后，社区自然会看得清清楚楚。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">新版 open.mp 客户端最大的挑战是什么？</span><br />
<br />
把它写出来！<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">五年后，你们认为 open.mp 会是什么样子？</span><br />
<br />
不必担心这个，我们有很多长远的想法。?<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">五年后，你们认为 SA-MP 会是什么样子？</span><br />
<br />
那是 SA-MP 团队的事，不是我们该操心的——在这个问题上我们没有立场去猜测。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">你们有没有想过放弃 open.mp？</span><br />
<br />
有过，因为我们也是普通人。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">最后，也是被问得最多的问题：</span><br />
<span style="font-weight: bold;" class="mycode_b">我们什么时候才能看到 open.mp？</span><br />
<br />
等它准备好了。???<br />
<br />
<hr class="mycode_hr" />
<br />
祝大家接下来的一周愉快！<br />
<br />
带着满满的爱，<br />
open.mp 团队 ?]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[考古]MTA 团队与 open.mp 团队早期就潜在合作可能性展开的公开对话 | 2019年5月]]></title>
			<link>https://open-mp.cn/showthread.php?tid=28</link>
			<pubDate>Tue, 24 Mar 2026 16:53:51 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=28</guid>
			<description><![CDATA[<hr class="mycode_hr" />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表：</span><br />
<br />
你好，<br />
<br />
在正式开始之前，先允许我做个自我介绍。我是 MTA 团队的成员，长期深度参与多人游戏模组的开发工作。本帖内容也已获得团队其他成员的认可。<br />
<br />
过去这几天，我们一直在默默关注 SA-MP 的近况，以及你们测试团队的动向。我们刻意等待了一段时间，让局势稍微平息，这也是我们迟迟没有表态的原因。<br />
<br />
在我们看来，眼下的局面对 MTA:SA 和 SA-MP 来说，恰恰是一次难得的相互靠拢的机会。我们理解你们对现状的不满，但我们认为，为《GTA 圣安地列斯》这款已有相当历史的游戏再从零搭建一个多人游戏项目，似乎并不是最明智的选择。我们对圣安地列斯的热爱，与你们一样深厚。尽管近来在线玩家数量基本保持稳定，但不可否认的是，吸引新玩家的难度正在与日俱增——尤其考虑到玩家群体结构的变化。<br />
<br />
因此，我们诚邀你们加入 MTA 社区。从技术层面来看，我们认为最务实的方案是实现从 SA-MP 到 MTA 的兼容层，这样也能帮助你们更快推进前期更新的发布。<br />
<br />
说几个数据：过去三年，我们发布了四个新版本，并持续推出大量迭代更新和反作弊升级；而 SA-MP 的最后一次官方发布，距今已超过四年（依据 sa-mp.com 官方数据）。<br />
<br />
除少数例外情况，MTA 在技术上已基本能够"模拟"SA-MP 的全部功能。我们相信，凭借你们作为资深开发者的经验，双方完全可以共同实现客户端兼容。<br />
<br />
此外，我们已有一个名为 <span style="font-weight: bold;" class="mycode_b">amx</span> 的资源（https://github.com/multitheftauto/mtasa-resources/tree/master/%5Bgamemodes%5D/%5Bamx%5D），可在 MTA 内部运行 Pawn 虚拟机。该资源目前版本较旧，可能需要重构，但核心功能依然可用。<br />
<br />
我们相信这将是一个对双方都有利的合作，也是两个社区难得的机遇——不仅能汇聚各自优秀的开发者和新鲜想法，还能为玩家带来真正丰富的游戏体验，甚至可能吸引新玩家（例如 MTA 的粉丝群体）加入，并催生一批概念全新的脚本功能。<br />
<br />
如果你们对潜在问题有任何顾虑，欢迎随时与我们深入探讨。<br />
<br />
谨致问候，代表 MTA 团队。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">JustMichael，论坛跟进者：</span><br />
<br />
我们需要在团队内部充分讨论之后，才能就该提案给出正式回应。这绝非一个小提案，我们需要时间消化并核实帖子中提及的所有信息。因此，请不要将这条回复理解为拒绝——我们绝对没有在拖延，会尽快给出正式答复。另外，请始终将 J0sh 的名字写作"J0sh……"。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表：</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>BloodMaster 写道：「SA-MP 保留了圣安地列斯原汁原味的氛围和外观，而 MTA 则是一个可以高度自定义的引擎——这正是 SA-MP 吸引更多玩家的根本原因。」</blockquote>
这个观点我之前也看到过几次，确实触及了一个重要方面。MTA 确实拥有某种"可自由改造的自定义引擎"，但我个人并不认为这是一个负面特质。毕竟，没有人强迫任何人把游戏做成与原版圣安地列斯截然不同的样子——这完全是开发者自己的选择。况且，随着功能的不断叠加，你们迟早也会面临类似的情况。<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>iReal Worlds 写道：「Lua……认真的吗？」</blockquote>
依我个人之见，Lua 是一门非常出色的多范式语言，同时支持命令式、面向对象乃至部分函数式编程风格。更重要的是，它在设计之初就以"嵌入其他应用程序"为核心目标，这在客户端脚本的安全执行方面具有显著优势，是其他语言难以比拟的。<br />
<br />
此外，我还想提一个近期由 MTA 社区打造的有趣项目：https://mta-slipe.com/。它本质上是将 C# 引入到 Lua 环境中。<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>michael@belgium 写道：「想象一下所有人都切换到 Lua……」</blockquote>
这并不是我的提议。我们谈论的是兼容性方案——让 SA-MP 的模组和插件（用 Pawn 编写）无需任何修改，即可直接在 MTA 中运行。如果 open.mp 的开发者计划支持更多脚本语言，我们也可以将 Pawn 作为 MTA 的附加语言引入（包括对 SA-MP API 脚本的支持）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">MyU，open.mp 开发者：</span><br />
<br />
首先声明：以下内容纯属个人观点，与 open.mp 项目及团队立场无关。<br />
<br />
事实上，已经有一些人指出，MTA 和 SA-MP 本质上是两种完全不同的东西——确实如此，差异相当显著。MTA 走的是不断创新的路线，而 SA-MP 则始终"守着老传统"；正因为长期没有更新、也不理会社区的功能需求，才会是今天这个局面。<br />
<br />
我个人两款都玩过（MTA 是大约两三年前，当时 OOP Lua 刚加入不久，玩了一两个月）。玩了一段时间后，MTA 对我来说变得有些"吃不消"——那时候我的电脑配置比较低，加上遇到了一些 CEF 相关的问题，虽然我相信这些问题现在应该都已经解决了。<br />
<br />
SA-MP 相当"轻量"：一个压缩包、一个 samp.dll、一个启动器，再加一两个文件，就全了。而 MTA:SA 则捆绑了 CEF 文件、CGUI 文件、本地化文件等一大堆内容。我个人认为，把这两个多人游戏合并在一起是行不通的——它们太不一样了，目标也各不相同。SA-MP 里安装 mod 极其简单，丢进游戏文件夹就能用；MTA:SA 则更像是一个经过精心打磨、功能完整的多人游戏模组，但玩家有自己的偏好，这无可厚非。<br />
<br />
简单总结一下：<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">SA-MP</span> → 轻量、易上手，但在某些方面存在局限；<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">MTA:SA</span> → 体量较重，但功能全面，有时略显复杂，稳定性却强于 SA-MP（玩家们甚至会利用 MTA:SA 的崩溃报告来排查问题——这本身就说明很多问题）。<br />
</li>
</ul>
<br />
不过我认为，玩家并不希望社区就此一分为二、各走各的路。竞争本身，以及由此带来的优胜劣汰，对整体发展是有益的。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表（回复 MyU）：</span><br />
<br />
性能问题在绝大多数情况下都源于脚本编写质量低下（尤其是客户端脚本写得糟糕）。"能力越大，责任越大"这句话在这里再合适不过了，虽然这听起来有点无奈。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Sasino97，open.mp 软件开发者：</span><br />
<br />
我认为加入 MTA 最大的好处，是可以直接接触到庞大的现有玩家群体，以及 MTA 客户端本身极为强大的功能上限。至于缺点嘛……他们的论坛实在是太丑了，抱歉直说。<br />
<br />
不过，我个人很认可 open.mp 这个项目的理念，所以我觉得两边（MTA 和 open.mp）还是应该作为独立项目，各自继续发展下去。<br />
<br />
<hr class="mycode_hr" />]]></description>
			<content:encoded><![CDATA[<hr class="mycode_hr" />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表：</span><br />
<br />
你好，<br />
<br />
在正式开始之前，先允许我做个自我介绍。我是 MTA 团队的成员，长期深度参与多人游戏模组的开发工作。本帖内容也已获得团队其他成员的认可。<br />
<br />
过去这几天，我们一直在默默关注 SA-MP 的近况，以及你们测试团队的动向。我们刻意等待了一段时间，让局势稍微平息，这也是我们迟迟没有表态的原因。<br />
<br />
在我们看来，眼下的局面对 MTA:SA 和 SA-MP 来说，恰恰是一次难得的相互靠拢的机会。我们理解你们对现状的不满，但我们认为，为《GTA 圣安地列斯》这款已有相当历史的游戏再从零搭建一个多人游戏项目，似乎并不是最明智的选择。我们对圣安地列斯的热爱，与你们一样深厚。尽管近来在线玩家数量基本保持稳定，但不可否认的是，吸引新玩家的难度正在与日俱增——尤其考虑到玩家群体结构的变化。<br />
<br />
因此，我们诚邀你们加入 MTA 社区。从技术层面来看，我们认为最务实的方案是实现从 SA-MP 到 MTA 的兼容层，这样也能帮助你们更快推进前期更新的发布。<br />
<br />
说几个数据：过去三年，我们发布了四个新版本，并持续推出大量迭代更新和反作弊升级；而 SA-MP 的最后一次官方发布，距今已超过四年（依据 sa-mp.com 官方数据）。<br />
<br />
除少数例外情况，MTA 在技术上已基本能够"模拟"SA-MP 的全部功能。我们相信，凭借你们作为资深开发者的经验，双方完全可以共同实现客户端兼容。<br />
<br />
此外，我们已有一个名为 <span style="font-weight: bold;" class="mycode_b">amx</span> 的资源（https://github.com/multitheftauto/mtasa-resources/tree/master/%5Bgamemodes%5D/%5Bamx%5D），可在 MTA 内部运行 Pawn 虚拟机。该资源目前版本较旧，可能需要重构，但核心功能依然可用。<br />
<br />
我们相信这将是一个对双方都有利的合作，也是两个社区难得的机遇——不仅能汇聚各自优秀的开发者和新鲜想法，还能为玩家带来真正丰富的游戏体验，甚至可能吸引新玩家（例如 MTA 的粉丝群体）加入，并催生一批概念全新的脚本功能。<br />
<br />
如果你们对潜在问题有任何顾虑，欢迎随时与我们深入探讨。<br />
<br />
谨致问候，代表 MTA 团队。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">JustMichael，论坛跟进者：</span><br />
<br />
我们需要在团队内部充分讨论之后，才能就该提案给出正式回应。这绝非一个小提案，我们需要时间消化并核实帖子中提及的所有信息。因此，请不要将这条回复理解为拒绝——我们绝对没有在拖延，会尽快给出正式答复。另外，请始终将 J0sh 的名字写作"J0sh……"。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表：</span><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>BloodMaster 写道：「SA-MP 保留了圣安地列斯原汁原味的氛围和外观，而 MTA 则是一个可以高度自定义的引擎——这正是 SA-MP 吸引更多玩家的根本原因。」</blockquote>
这个观点我之前也看到过几次，确实触及了一个重要方面。MTA 确实拥有某种"可自由改造的自定义引擎"，但我个人并不认为这是一个负面特质。毕竟，没有人强迫任何人把游戏做成与原版圣安地列斯截然不同的样子——这完全是开发者自己的选择。况且，随着功能的不断叠加，你们迟早也会面临类似的情况。<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>iReal Worlds 写道：「Lua……认真的吗？」</blockquote>
依我个人之见，Lua 是一门非常出色的多范式语言，同时支持命令式、面向对象乃至部分函数式编程风格。更重要的是，它在设计之初就以"嵌入其他应用程序"为核心目标，这在客户端脚本的安全执行方面具有显著优势，是其他语言难以比拟的。<br />
<br />
此外，我还想提一个近期由 MTA 社区打造的有趣项目：https://mta-slipe.com/。它本质上是将 C# 引入到 Lua 环境中。<br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>michael@belgium 写道：「想象一下所有人都切换到 Lua……」</blockquote>
这并不是我的提议。我们谈论的是兼容性方案——让 SA-MP 的模组和插件（用 Pawn 编写）无需任何修改，即可直接在 MTA 中运行。如果 open.mp 的开发者计划支持更多脚本语言，我们也可以将 Pawn 作为 MTA 的附加语言引入（包括对 SA-MP API 脚本的支持）。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">MyU，open.mp 开发者：</span><br />
<br />
首先声明：以下内容纯属个人观点，与 open.mp 项目及团队立场无关。<br />
<br />
事实上，已经有一些人指出，MTA 和 SA-MP 本质上是两种完全不同的东西——确实如此，差异相当显著。MTA 走的是不断创新的路线，而 SA-MP 则始终"守着老传统"；正因为长期没有更新、也不理会社区的功能需求，才会是今天这个局面。<br />
<br />
我个人两款都玩过（MTA 是大约两三年前，当时 OOP Lua 刚加入不久，玩了一两个月）。玩了一段时间后，MTA 对我来说变得有些"吃不消"——那时候我的电脑配置比较低，加上遇到了一些 CEF 相关的问题，虽然我相信这些问题现在应该都已经解决了。<br />
<br />
SA-MP 相当"轻量"：一个压缩包、一个 samp.dll、一个启动器，再加一两个文件，就全了。而 MTA:SA 则捆绑了 CEF 文件、CGUI 文件、本地化文件等一大堆内容。我个人认为，把这两个多人游戏合并在一起是行不通的——它们太不一样了，目标也各不相同。SA-MP 里安装 mod 极其简单，丢进游戏文件夹就能用；MTA:SA 则更像是一个经过精心打磨、功能完整的多人游戏模组，但玩家有自己的偏好，这无可厚非。<br />
<br />
简单总结一下：<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">SA-MP</span> → 轻量、易上手，但在某些方面存在局限；<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">MTA:SA</span> → 体量较重，但功能全面，有时略显复杂，稳定性却强于 SA-MP（玩家们甚至会利用 MTA:SA 的崩溃报告来排查问题——这本身就说明很多问题）。<br />
</li>
</ul>
<br />
不过我认为，玩家并不希望社区就此一分为二、各走各的路。竞争本身，以及由此带来的优胜劣汰，对整体发展是有益的。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Jusonex，MTA 团队代表（回复 MyU）：</span><br />
<br />
性能问题在绝大多数情况下都源于脚本编写质量低下（尤其是客户端脚本写得糟糕）。"能力越大，责任越大"这句话在这里再合适不过了，虽然这听起来有点无奈。<br />
<br />
<hr class="mycode_hr" />
<br />
<span style="font-weight: bold;" class="mycode_b">Sasino97，open.mp 软件开发者：</span><br />
<br />
我认为加入 MTA 最大的好处，是可以直接接触到庞大的现有玩家群体，以及 MTA 客户端本身极为强大的功能上限。至于缺点嘛……他们的论坛实在是太丑了，抱歉直说。<br />
<br />
不过，我个人很认可 open.mp 这个项目的理念，所以我觉得两边（MTA 和 open.mp）还是应该作为独立项目，各自继续发展下去。<br />
<br />
<hr class="mycode_hr" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[服务器开发 精选资源清单]]></title>
			<link>https://open-mp.cn/showthread.php?tid=27</link>
			<pubDate>Sun, 22 Mar 2026 00:24:28 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=27</guid>
			<description><![CDATA[<hr class="mycode_hr" />
为 SA-MP 开发精选的实用工具、库、游戏模式、滤镜脚本和插件列表。<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">工具</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/compiler" target="_blank" rel="noopener" class="mycode_url">Community Compiler</a></span> - 一个大幅更新的编译器版本，包含众多修复和增强功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/sampctl" target="_blank" rel="noopener" class="mycode_url">sampctl</a></span> - 用于安装库和运行服务器的包管理器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Zeex/samp-plugin-runner" target="_blank" rel="noopener" class="mycode_url">Plugin Runner</a></span> - 用于直接从命令行运行轻量级服务器版本（无需 server.cfg）以测试插件的工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-plugin-boilerplate" target="_blank" rel="noopener" class="mycode_url">Plugin Boilerplate</a></span> - 通过样板代码简化插件的创建。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/samp-ptl" target="_blank" rel="noopener" class="mycode_url">SA:MP Plugin Template Library</a></span> - 使用此模板库，可以非常轻松快速地制作自己的插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://fiddle.sa-mp.dev" target="_blank" rel="noopener" class="mycode_url">SA-MP Fiddle</a></span> - 一个测试脚本（代码片段、概念验证、调试等）并分享给其他人的地方。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://packagecontrol.io/packages/Pawn%20syntax" target="_blank" rel="noopener" class="mycode_url">Pawn Syntax - Sublime</a></span> - 为 Sublime Text 提供的 Pawn 自动补全。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://marketplace.visualstudio.com/items?itemName=southclaws.vscode-pawn" target="_blank" rel="noopener" class="mycode_url">Pawn Syntax - Visual Marketplace</a></span> - 为 Visual Studio Code 提供的 Pawn 自动补全。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://bitbucket.org/Grimrandomer/samp-zone-editor/downloads" target="_blank" rel="noopener" class="mycode_url">SA-MP Zone Editor</a></span> - 用于制作区域等的区域编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/tools/Map%20Editor.zip" target="_blank" rel="noopener" class="mycode_url">SA-MP Map Editor</a></span> - 流行的 SA:MP 地图编辑器。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">库</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/samp-stdlib" target="_blank" rel="noopener" class="mycode_url">samp-stdlib</a></span> - 默认包含文件的更新版本。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 正确、文档齐全且完整。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/sa-mp-fixes" target="_blank" rel="noopener" class="mycode_url">fixes.inc</a></span> - 针对大量 SA:MP 服务器错误的高度优化修复。即插即用。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/YSI-Includes" target="_blank" rel="noopener" class="mycode_url">YSI-Includes</a></span> - 为 SA:MP/pawn 开发的最古老、最大、经过最充分测试且支持最完善的库，提供了大量新的游戏和语言特性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Open-GTO/foreach" target="_blank" rel="noopener" class="mycode_url">foreach</a></span> - 独立的 foreach 包含文件（非 y_iterate 版本）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/amx_assembly" target="_blank" rel="noopener" class="mycode_url">amx_assembly</a></span> - 对 pawn 脚本本身的底层访问。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/md-sort" target="_blank" rel="noopener" class="mycode_url">md-sort</a></span> - 在 Pawn 中对多维数组进行排序。修改数组的内部指针，而不是复制数据。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/indirection" target="_blank" rel="noopener" class="mycode_url">indirection</a></span> - 用于传递指针和间接调用函数的系统，并提供了自定义调用的抽象方法。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/code-parse.inc" target="_blank" rel="noopener" class="mycode_url">code-parse.inc</a></span> - 在编译时解析和自定义 pawn 代码。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Vince0789/sa-mp-extended-vehicle-information" target="_blank" rel="noopener" class="mycode_url">Extended Vehicle Information</a></span> - 将单人游戏中的大量车辆标志导入 SQLite 数据库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/sqlitei" target="_blank" rel="noopener" class="mycode_url">sqlitei</a></span> - 为 SA-MP SQLite 函数提供的高级 API。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/samp-weapon-config" target="_blank" rel="noopener" class="mycode_url">weapon-config</a></span> - 更一致、响应更快的伤害系统，并包含许多新特性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/SAMP-geoip" target="_blank" rel="noopener" class="mycode_url">samp-geoip</a></span> - 基于 IP 地址的地理位置信息。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/progress2" target="_blank" rel="noopener" class="mycode_url">progress2</a></span> - 将时间、生命值、车辆燃料等内容显示为进度条。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/itsneufox/GameText-Plus" target="_blank" rel="noopener" class="mycode_url">GameText+</a></span> - 一个为 SA-MP 和 open.mp 改进原生 GameText 的包含文件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-weapon-data" target="_blank" rel="noopener" class="mycode_url">weapon-data</a></span> - 精细调校、可自定义的武器数据。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/MichaelBelgium/MV_Youtube" target="_blank" rel="noopener" class="mycode_url">MV_Youtube</a></span> - 用于音频流的 YouTube 转换器 API。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/MySQL-Prepared-Statements" target="_blank" rel="noopener" class="mycode_url">MySQL Prepared Statements</a></span> - 为 PAWN MySQL 插件模拟预处理语句。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Brunoo16/samp-server-weapons" target="_blank" rel="noopener" class="mycode_url">samp-server-weapons</a></span> - 完全由服务器控制的武器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/actor_robbery" target="_blank" rel="noopener" class="mycode_url">actor_robbery</a></span> - 灵感来自 GTA V 的商店抢劫。actor_robbery.inc 模仿了该功能！<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-aviation" target="_blank" rel="noopener" class="mycode_url">samp-aviation</a></span> - 一个基于俯仰角的高度自动控制和基于横滚角的航向自动控制的基础系统。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-logger" target="_blank" rel="noopener" class="mycode_url">samp-logger</a></span> - 简单的结构化日志记录器，提供了一组简单的日志记录和调试函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/tdworg/samp-include-rscan" target="_blank" rel="noopener" class="mycode_url">TDW Recursion Scanner</a></span> - 一个查找代码中递归的库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Awsomedude/easyDialog" target="_blank" rel="noopener" class="mycode_url">easyDialog</a></span> - 简化对话框的通用使用方法。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Open-GTO/mdialog" target="_blank" rel="noopener" class="mycode_url">mdialog</a></span> - 现代化的对话框系统，类似于 easyDialog。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Crayder/Model-Sizes-Plus" target="_blank" rel="noopener" class="mycode_url">Model Sizes Plus</a></span> - 更新、更高级、更精确的旧版 modelsizes 包含文件版本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/uPeppe/physics.inc" target="_blank" rel="noopener" class="mycode_url">physics.inc</a></span> - 模拟 2D 和 3D 物理效果（真实运动、碰撞等）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AGraber/samp-async-dialogs" target="_blank" rel="noopener" class="mycode_url">samp-async-dialogs</a></span> - 使用 PawnPlus 任务的异步对话框处理。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/blob/master/includes/speedcap.inc" target="_blank" rel="noopener" class="mycode_url">speedcap.inc</a></span> - 一个控制车辆速度的包含文件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Kirima2nd/samp-command-guess" target="_blank" rel="noopener" class="mycode_url">SA:MP Command Guess</a></span> - 使用莱文斯坦距离函数为 SA:MP 实现的命令猜测器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/wuzi/vending" target="_blank" rel="noopener" class="mycode_url">vending</a></span> - SA-MP 的服务器端自动售货机。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/strlib" target="_blank" rel="noopener" class="mycode_url">strlib</a></span> - 一系列实用的字符串函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ScavengeSurvive/mathutil" target="_blank" rel="noopener" class="mycode_url">mathutil</a></span> - 一系列实用的数学函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/sampctl/rotations.inc" target="_blank" rel="noopener" class="mycode_url">rotations.inc</a></span> - 一系列实用的旋转函数，来源于 Nero_3D 的 rotations.inc。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/samp-distance" target="_blank" rel="noopener" class="mycode_url">SA-MP Distance Functions</a></span> - 一系列实用的距离检测函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/emmet-jones/New-SA-MP-callbacks" target="_blank" rel="noopener" class="mycode_url">New SA-MP callbacks</a></span> - 一系列实用的新回调函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/Alternative-Dialogs" target="_blank" rel="noopener" class="mycode_url">Alternative Dialogs</a></span> - 具有全新设计的文本绘图对话框。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/TommyB123/eSelection" target="_blank" rel="noopener" class="mycode_url">eSelection</a></span> - 增加在 SA-MP 游戏模式中创建动态模型选择菜单的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/alextwothousand/mSelection" target="_blank" rel="noopener" class="mycode_url">mSelection</a></span> - 与 eSelection 类似，但风格不同。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/adib-yg/SAMP-RGB-Textdraw" target="_blank" rel="noopener" class="mycode_url">RGB-Textdraw</a></span> - 为文本绘图添加 RGB 颜色支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/mysy00/LangPlus" target="_blank" rel="noopener" class="mycode_url">LangPlus</a></span> - 为 open.mp 服务器提供的多语言库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://beckzy.net/index.php?action=downloads;sa=view;id=41" target="_blank" rel="noopener" class="mycode_url">beckzy's mod shops</a></span> - 一个用于服务器端改装店的包含文件。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">命令处理器</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/YashasSamaga/I-ZCMD" target="_blank" rel="noopener" class="mycode_url">I-ZCMD</a></span> - ZCMD 的改进版本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.CMD" target="_blank" rel="noopener" class="mycode_url">Pawn.CMD</a></span> - 比任何其他命令处理器都快。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/YSI-Includes/blob/5.x/YSI_Visual/y_commands.md" target="_blank" rel="noopener" class="mycode_url">y_commands</a></span> - 来自 YSI Includes 的命令处理器。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/samp-plugin-jit-backup" target="_blank" rel="noopener" class="mycode_url">JIT</a></span> - 代码稳定后，使用此插件可以显著提高速度。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-plugin-crashdetect" target="_blank" rel="noopener" class="mycode_url">CrashDetect</a></span> - 在测试期间用于查找错误的开发工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/samp-plugin-profiler-backup" target="_blank" rel="noopener" class="mycode_url">Profiler</a></span> - SA-MP 服务器的性能分析器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/sscanf" target="_blank" rel="noopener" class="mycode_url">sscanf</a></span> - 将字符串转换为多个值、整数、浮点数、玩家等。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pBlueG/SA-MP-MySQL" target="_blank" rel="noopener" class="mycode_url">MySQL Plugin</a></span> - 将服务器连接到 MySQL 数据库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-streamer-plugin" target="_blank" rel="noopener" class="mycode_url">Streamer Plugin</a></span> - 绕过许多 SA:MP 限制，例如物体和拾取物的数量限制。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/plugins/nativechecker.zip" target="_blank" rel="noopener" class="mycode_url">nativechecker</a></span> - 在服务器启动时检查原生函数。在 open.mp 中不需要，因为 open.mp 自带原生函数检查机制。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ziggi/FCNPC" target="_blank" rel="noopener" class="mycode_url">FCNPC</a></span> - 一个为 SA-MP 服务器添加大量功能给现有标准 NPC 的插件。它在 open.mp 中无法使用，但你可以改用官方的 NPC 组件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/JaTochNietDan/SA-MP-FileManager" target="_blank" rel="noopener" class="mycode_url">FileManager</a></span> - 允许你管理根文件夹中的文件和文件夹（通过此插件，不局限于 scriptfiles 服务器目录）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.RakNet" target="_blank" rel="noopener" class="mycode_url">Pawn.Raknet</a></span> - 允许你分析 RakNet 流量。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/bmisiak/samp-precise-timers" target="_blank" rel="noopener" class="mycode_url">samp-precise-timers</a></span> - 一个用 Rust 编写的 SA-MP 插件，提供精确计时器。在 open.mp 中不需要，因为 open.mp 自带精确计时器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/PawnPlus" target="_blank" rel="noopener" class="mycode_url">PawnPlus</a></span> - 通过新的结构、数据类型和编程技术扩展 Pawn 脚本语言的可能性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/BigETI/pawn-memory" target="_blank" rel="noopener" class="mycode_url">PAWN memory access</a></span> - 允许在 PAWN 中从堆中分配和释放内存。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/NativeFallback" target="_blank" rel="noopener" class="mycode_url">Native Fallback</a></span> - SA-MP 插件，为未注册的原生函数提供回退实现。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/YSF" target="_blank" rel="noopener" class="mycode_url">YSF</a></span> - 一个旨在从服务器中挖掘最大可能性的插件，主要通过内存编辑和钩子实现。它的许多功能现在已经内置在 open.mp 中。请参阅 <a href="https://github.com/openmultiplayer/open.mp/issues/189" target="_blank" rel="noopener" class="mycode_url">这个 github issue</a> 了解功能列表。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/SKY" target="_blank" rel="noopener" class="mycode_url">SKY</a></span> - 该插件提供底层函数，让 Pawn 脚本能够执行强大的操作。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.Regex" target="_blank" rel="noopener" class="mycode_url">Pawn.Regex</a></span> - 为 Pawn 添加正则表达式支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/pawn-scraper" target="_blank" rel="noopener" class="mycode_url">pawn-scraper</a></span> - 一个强大的爬虫插件，提供了在 pawn 中使用 html 解析器和 css 选择器的接口。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/philip1337/samp-plugin-totp" target="_blank" rel="noopener" class="mycode_url">TOTP</a></span> - 允许在 sa-mp 游戏模式中使用 TOTP 身份验证。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-dns-plugin" target="_blank" rel="noopener" class="mycode_url">DNS Plugin</a></span> - 该插件提供 DNS 查找和反向 DNS 查找的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-plugin-mapandreas" target="_blank" rel="noopener" class="mycode_url">MapAndreas</a></span> - 允许你加载不同的高度图并检查 x, y 坐标处的最低高度。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Pottus/ColAndreas" target="_blank" rel="noopener" class="mycode_url">ColAndreas</a></span> - 创建一个圣安地列斯世界的模拟。使用 Bullet Physics 库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://bitbucket.org/Pamdex/pathfinder/src/master" target="_blank" rel="noopener" class="mycode_url">PathFinder</a></span> - 允许你计算圣安地列斯地图上从 A 点到 B 点的路线。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/spmn/samp-custom-query-flood-check" target="_blank" rel="noopener" class="mycode_url">Custom Query Flood Check</a></span> - 编写针对查询洪水攻击的自定义保护措施。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/YashasSamaga/sampml" target="_blank" rel="noopener" class="mycode_url">sampml</a></span> - 简化的机器学习工具包及相关 SAMP 项目（如自瞄检测）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/tgconnector" target="_blank" rel="noopener" class="mycode_url">TgConnector</a></span> - 一个电报连接器插件，帮助通过 SA-MP 与电报机器人交互。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-discord-connector" target="_blank" rel="noopener" class="mycode_url">Discord connector</a></span> - 允许你从 PAWN 脚本中控制 Discord 机器人。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-tsconnector" target="_blank" rel="noopener" class="mycode_url">TSConnector</a></span> - 允许你从 PAWN 脚本中控制 Teamspeak3 服务器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-irc-plugin" target="_blank" rel="noopener" class="mycode_url">IRC Plugin</a></span> - 允许通过 SA-MP 服务器创建和管理 IRC 机器人。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-requests" target="_blank" rel="noopener" class="mycode_url">pawn-requests</a></span> - 提供了一个与 HTTP(S) API 交互的 API，支持文本和 JSON 数据类型。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-redis" target="_blank" rel="noopener" class="mycode_url">pawn-redis</a></span> - 授予对快速内存数据库的访问权限，以及与其他程序之间的异步消息通道。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-chrono" target="_blank" rel="noopener" class="mycode_url">Chrono</a></span> - 一个用于处理日期和时间的现代 Pawn 库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ziggi/rustext" target="_blank" rel="noopener" class="mycode_url">rustext</a></span> - SA-MP 的俄文文本修复插件：修复 GameText、TextDraw 和 Menu。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/KrYpToDeN/Advanced-SA-NickName" target="_blank" rel="noopener" class="mycode_url">Advanced SA NickName</a></span> - 支持昵称中的任何符号。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Hual/SAMPSON" target="_blank" rel="noopener" class="mycode_url">SAMPSON</a></span> - 一个 SA-MP 的 JSON 插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/SimoSbara/samp-chatbot" target="_blank" rel="noopener" class="mycode_url">samp-chatbot</a></span> - 一个用于在游戏内进行 AI 聊天机器人通信的 GTA SAMP 插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-bscrashfix" target="_blank" rel="noopener" class="mycode_url">SAMP BitStream Crash Fix</a></span> - 修复了 BitStream 读取溢出的问题。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-json" target="_blank" rel="noopener" class="mycode_url">pawn-json</a></span> - 为 Pawn 提供的 JSON 支持。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">客户端-服务器插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Hual/SA-MP-Plus" target="_blank" rel="noopener" class="mycode_url">SA-MP+</a></span> - 一个客户端修改，利用 SA-MP 的插件 SDK 与服务器交互并添加新功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/dotSILENT/chandling" target="_blank" rel="noopener" class="mycode_url">CHandling</a></span> - 通过修改游戏的默认行为，为单个车辆分配车辆操控数据的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/CyberMor/sampvoice" target="_blank" rel="noopener" class="mycode_url">SAMPVOICE</a></span> - 在 SA:MP 服务器的 Pawn 语言中实现语音通信系统。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/CyberMor/keylistener" target="_blank" rel="noopener" class="mycode_url">KeyListener</a></span> - 用于跟踪任何按键的客户端-服务器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ZOTTCE/samp-cef" target="_blank" rel="noopener" class="mycode_url">SAMP CEF</a></span> - 为 SA:MP 嵌入 CEF 的客户端和服务器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Whitetigerswt/SAMP_AC_v2" target="_blank" rel="noopener" class="mycode_url">SAMP_AC_v2</a></span> - SA:MP 客户端反作弊。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">加密插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-whirlpool" target="_blank" rel="noopener" class="mycode_url">whirlpool</a></span> - SA:MP 的 Whirlpool 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/samp-bcrypt" target="_blank" rel="noopener" class="mycode_url">SyS' bcrypt Plugin</a></span> - 由 Sreyas Sreelal 为 SA:MP 制作的 Bcrypt 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/lassir/bcrypt-samp" target="_blank" rel="noopener" class="mycode_url">lassir's bcrypt Plugin</a></span> - 由 lassir 为 SA:MP 制作的 Bcrypt 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/alextwothousand/samp-crypto" target="_blank" rel="noopener" class="mycode_url">samp-crypto</a></span> - 为 SA:MP 提供的一系列加密函数，如 Argon2、Scrypt 和 Bcrypt。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/plugins/SHA512.zip" target="_blank" rel="noopener" class="mycode_url">SHA512</a></span> - SA:MP 的 SHA512 加密插件。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">GDK/SDK</h3><br />
<br />
现在，你可以使用 open.mp 在不借助任何插件的情况下，用 Pawn 以外的语言编写脚本。请参阅 <a href="https://www.open.mp/blog/release-candidate-1" target="_blank" rel="noopener" class="mycode_url">这篇博客文章</a>。<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-plugin-sdk" target="_blank" rel="noopener" class="mycode_url">sampsdk</a></span> - 这是开发插件所需的最基本内容。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/sampgdk-backup" target="_blank" rel="noopener" class="mycode_url">sampgdk</a></span> - 为 SA:MP 编写游戏模式的 C/C++ 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ikkentim/SampSharp" target="_blank" rel="noopener" class="mycode_url">SampSharp</a></span> - 为 SA:MP 编写游戏模式的 C# 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Seregamil/.NET-plugin" target="_blank" rel="noopener" class="mycode_url">.NET Plugin</a></span> - 为 SA:MP 编写插件的 C# 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/sampgo/sampgo" target="_blank" rel="noopener" class="mycode_url">sampgo</a></span> - 为 SA:MP 编写游戏模式/插件的 Go 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-node" target="_blank" rel="noopener" class="mycode_url">samp-node</a></span> - 为 SA:MP 编写游戏模式的 Javascript/Typescript 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Shoebill/ShoebillPlugin" target="_blank" rel="noopener" class="mycode_url">Shoebill Project</a></span> - 为 SA:MP 编写游戏模式的 Java 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/habecker/PySAMP" target="_blank" rel="noopener" class="mycode_url">pySAMP</a></span> - 为 SA:MP 编写游戏模式的 Python 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ZOTTCE/samp-rs" target="_blank" rel="noopener" class="mycode_url">samp-rs</a></span> - 为 SA:MP 编写插件的 Rust 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/YALP" target="_blank" rel="noopener" class="mycode_url">Yet Another Lua Plugin</a></span> - 为 SA:MP 编写游戏模式的 Lua 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Lapayo/SAMPHP" target="_blank" rel="noopener" class="mycode_url">SAMPHP</a></span> - 为 SA:MP 编写游戏模式的 PHP 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">[SA-MP S[D]K](<a href="https://github.com/Hual/SA-MP-S-D-K" target="_blank" rel="noopener" class="mycode_url">https://github.com/Hual/SA-MP-S-D-K</a>)</span> - 为 SA:MP 编写游戏模式的 D 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Double-O-Seven/kamp" target="_blank" rel="noopener" class="mycode_url">Kamp</a></span> - 为 SA:MP 编写游戏模式的 Kotlin 语言支持。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">游戏模式</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/midosvt/omp-base-script" target="_blank" rel="noopener" class="mycode_url">Simple base script</a></span> - 一个帮助初学者入门的简单基础脚本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/ScavengeSurvive" target="_blank" rel="noopener" class="mycode_url">ScavengeSurvive</a></span> - 基于 PvP 的生存游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/gta-open" target="_blank" rel="noopener" class="mycode_url">gta-open</a></span> - 一个以洛圣都为背景的警察与匪徒模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/zeelorenc/sf-cnr" target="_blank" rel="noopener" class="mycode_url">SF-CnR</a></span> - 为 SA-MP 开发的圣费耶罗警察与匪徒游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NextGenerationGamingLLC/SA-MP-Development" target="_blank" rel="noopener" class="mycode_url">Next Generation Roleplay</a></span> - Next Generation Gaming, LLC 的 SA:MP 游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/seanny/SC-RP" target="_blank" rel="noopener" class="mycode_url">SC-RP</a></span> - 一个支持 MySQL 的角色扮演游戏模式。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">滤镜脚本</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/MapFix" target="_blank" rel="noopener" class="mycode_url">MapFix</a></span> - 修复 GTA 圣安地列斯地图的纹理错误。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-animbrowse" target="_blank" rel="noopener" class="mycode_url">SA:MP Animbrowse</a></span> - SA:MP 的动画浏览器工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Fairuz-Afdhal/IsPlayerUsingAndroid" target="_blank" rel="noopener" class="mycode_url">IsPlayerUsingAndroid</a></span> - 检查玩家是否为安卓用户。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Nickk888SAMP/TextDraw-Editor" target="_blank" rel="noopener" class="mycode_url">Nickk's TextDraw Editor</a></span> - 一个具有丰富功能的文本绘图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/nexquery/samp-textdraw-editor" target="_blank" rel="noopener" class="mycode_url">Nexor's Textdraw Editor</a></span> - 此编辑器提供许多功能，如分组、恢复删除的文本、撤销更改、从文件导入文本绘图等。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/Ultimate-Creator" target="_blank" rel="noopener" class="mycode_url">Ultimate Creator</a></span> - 具有众多功能的高级地图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/fusez/Map-Editor-V3" target="_blank" rel="noopener" class="mycode_url">Fusez's Map Editor</a></span> - SA:MP 的游戏内地图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Pottus/Texture-Studio" target="_blank" rel="noopener" class="mycode_url">Texture Studio</a></span> - 这是一个游戏内地图编辑器，允许你为物体贴图，最多支持材质索引 15（16 种材质），并可为该材质索引设置颜色。<br />
</li>
</ul>
]]></description>
			<content:encoded><![CDATA[<hr class="mycode_hr" />
为 SA-MP 开发精选的实用工具、库、游戏模式、滤镜脚本和插件列表。<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">工具</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/compiler" target="_blank" rel="noopener" class="mycode_url">Community Compiler</a></span> - 一个大幅更新的编译器版本，包含众多修复和增强功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/sampctl" target="_blank" rel="noopener" class="mycode_url">sampctl</a></span> - 用于安装库和运行服务器的包管理器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Zeex/samp-plugin-runner" target="_blank" rel="noopener" class="mycode_url">Plugin Runner</a></span> - 用于直接从命令行运行轻量级服务器版本（无需 server.cfg）以测试插件的工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-plugin-boilerplate" target="_blank" rel="noopener" class="mycode_url">Plugin Boilerplate</a></span> - 通过样板代码简化插件的创建。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/samp-ptl" target="_blank" rel="noopener" class="mycode_url">SA:MP Plugin Template Library</a></span> - 使用此模板库，可以非常轻松快速地制作自己的插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://fiddle.sa-mp.dev" target="_blank" rel="noopener" class="mycode_url">SA-MP Fiddle</a></span> - 一个测试脚本（代码片段、概念验证、调试等）并分享给其他人的地方。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://packagecontrol.io/packages/Pawn%20syntax" target="_blank" rel="noopener" class="mycode_url">Pawn Syntax - Sublime</a></span> - 为 Sublime Text 提供的 Pawn 自动补全。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://marketplace.visualstudio.com/items?itemName=southclaws.vscode-pawn" target="_blank" rel="noopener" class="mycode_url">Pawn Syntax - Visual Marketplace</a></span> - 为 Visual Studio Code 提供的 Pawn 自动补全。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://bitbucket.org/Grimrandomer/samp-zone-editor/downloads" target="_blank" rel="noopener" class="mycode_url">SA-MP Zone Editor</a></span> - 用于制作区域等的区域编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/tools/Map%20Editor.zip" target="_blank" rel="noopener" class="mycode_url">SA-MP Map Editor</a></span> - 流行的 SA:MP 地图编辑器。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">库</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/samp-stdlib" target="_blank" rel="noopener" class="mycode_url">samp-stdlib</a></span> - 默认包含文件的更新版本。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 正确、文档齐全且完整。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/sa-mp-fixes" target="_blank" rel="noopener" class="mycode_url">fixes.inc</a></span> - 针对大量 SA:MP 服务器错误的高度优化修复。即插即用。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/YSI-Includes" target="_blank" rel="noopener" class="mycode_url">YSI-Includes</a></span> - 为 SA:MP/pawn 开发的最古老、最大、经过最充分测试且支持最完善的库，提供了大量新的游戏和语言特性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Open-GTO/foreach" target="_blank" rel="noopener" class="mycode_url">foreach</a></span> - 独立的 foreach 包含文件（非 y_iterate 版本）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/amx_assembly" target="_blank" rel="noopener" class="mycode_url">amx_assembly</a></span> - 对 pawn 脚本本身的底层访问。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/md-sort" target="_blank" rel="noopener" class="mycode_url">md-sort</a></span> - 在 Pawn 中对多维数组进行排序。修改数组的内部指针，而不是复制数据。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/indirection" target="_blank" rel="noopener" class="mycode_url">indirection</a></span> - 用于传递指针和间接调用函数的系统，并提供了自定义调用的抽象方法。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/code-parse.inc" target="_blank" rel="noopener" class="mycode_url">code-parse.inc</a></span> - 在编译时解析和自定义 pawn 代码。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Vince0789/sa-mp-extended-vehicle-information" target="_blank" rel="noopener" class="mycode_url">Extended Vehicle Information</a></span> - 将单人游戏中的大量车辆标志导入 SQLite 数据库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/sqlitei" target="_blank" rel="noopener" class="mycode_url">sqlitei</a></span> - 为 SA-MP SQLite 函数提供的高级 API。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/samp-weapon-config" target="_blank" rel="noopener" class="mycode_url">weapon-config</a></span> - 更一致、响应更快的伤害系统，并包含许多新特性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/SAMP-geoip" target="_blank" rel="noopener" class="mycode_url">samp-geoip</a></span> - 基于 IP 地址的地理位置信息。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/progress2" target="_blank" rel="noopener" class="mycode_url">progress2</a></span> - 将时间、生命值、车辆燃料等内容显示为进度条。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/itsneufox/GameText-Plus" target="_blank" rel="noopener" class="mycode_url">GameText+</a></span> - 一个为 SA-MP 和 open.mp 改进原生 GameText 的包含文件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-weapon-data" target="_blank" rel="noopener" class="mycode_url">weapon-data</a></span> - 精细调校、可自定义的武器数据。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/MichaelBelgium/MV_Youtube" target="_blank" rel="noopener" class="mycode_url">MV_Youtube</a></span> - 用于音频流的 YouTube 转换器 API。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/MySQL-Prepared-Statements" target="_blank" rel="noopener" class="mycode_url">MySQL Prepared Statements</a></span> - 为 PAWN MySQL 插件模拟预处理语句。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Brunoo16/samp-server-weapons" target="_blank" rel="noopener" class="mycode_url">samp-server-weapons</a></span> - 完全由服务器控制的武器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/actor_robbery" target="_blank" rel="noopener" class="mycode_url">actor_robbery</a></span> - 灵感来自 GTA V 的商店抢劫。actor_robbery.inc 模仿了该功能！<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-aviation" target="_blank" rel="noopener" class="mycode_url">samp-aviation</a></span> - 一个基于俯仰角的高度自动控制和基于横滚角的航向自动控制的基础系统。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-logger" target="_blank" rel="noopener" class="mycode_url">samp-logger</a></span> - 简单的结构化日志记录器，提供了一组简单的日志记录和调试函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/tdworg/samp-include-rscan" target="_blank" rel="noopener" class="mycode_url">TDW Recursion Scanner</a></span> - 一个查找代码中递归的库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Awsomedude/easyDialog" target="_blank" rel="noopener" class="mycode_url">easyDialog</a></span> - 简化对话框的通用使用方法。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Open-GTO/mdialog" target="_blank" rel="noopener" class="mycode_url">mdialog</a></span> - 现代化的对话框系统，类似于 easyDialog。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Crayder/Model-Sizes-Plus" target="_blank" rel="noopener" class="mycode_url">Model Sizes Plus</a></span> - 更新、更高级、更精确的旧版 modelsizes 包含文件版本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/uPeppe/physics.inc" target="_blank" rel="noopener" class="mycode_url">physics.inc</a></span> - 模拟 2D 和 3D 物理效果（真实运动、碰撞等）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AGraber/samp-async-dialogs" target="_blank" rel="noopener" class="mycode_url">samp-async-dialogs</a></span> - 使用 PawnPlus 任务的异步对话框处理。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/blob/master/includes/speedcap.inc" target="_blank" rel="noopener" class="mycode_url">speedcap.inc</a></span> - 一个控制车辆速度的包含文件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Kirima2nd/samp-command-guess" target="_blank" rel="noopener" class="mycode_url">SA:MP Command Guess</a></span> - 使用莱文斯坦距离函数为 SA:MP 实现的命令猜测器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/wuzi/vending" target="_blank" rel="noopener" class="mycode_url">vending</a></span> - SA-MP 的服务器端自动售货机。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/strlib" target="_blank" rel="noopener" class="mycode_url">strlib</a></span> - 一系列实用的字符串函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ScavengeSurvive/mathutil" target="_blank" rel="noopener" class="mycode_url">mathutil</a></span> - 一系列实用的数学函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/sampctl/rotations.inc" target="_blank" rel="noopener" class="mycode_url">rotations.inc</a></span> - 一系列实用的旋转函数，来源于 Nero_3D 的 rotations.inc。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/samp-distance" target="_blank" rel="noopener" class="mycode_url">SA-MP Distance Functions</a></span> - 一系列实用的距离检测函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/emmet-jones/New-SA-MP-callbacks" target="_blank" rel="noopener" class="mycode_url">New SA-MP callbacks</a></span> - 一系列实用的新回调函数。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/Alternative-Dialogs" target="_blank" rel="noopener" class="mycode_url">Alternative Dialogs</a></span> - 具有全新设计的文本绘图对话框。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/TommyB123/eSelection" target="_blank" rel="noopener" class="mycode_url">eSelection</a></span> - 增加在 SA-MP 游戏模式中创建动态模型选择菜单的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/alextwothousand/mSelection" target="_blank" rel="noopener" class="mycode_url">mSelection</a></span> - 与 eSelection 类似，但风格不同。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/adib-yg/SAMP-RGB-Textdraw" target="_blank" rel="noopener" class="mycode_url">RGB-Textdraw</a></span> - 为文本绘图添加 RGB 颜色支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/mysy00/LangPlus" target="_blank" rel="noopener" class="mycode_url">LangPlus</a></span> - 为 open.mp 服务器提供的多语言库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://beckzy.net/index.php?action=downloads;sa=view;id=41" target="_blank" rel="noopener" class="mycode_url">beckzy's mod shops</a></span> - 一个用于服务器端改装店的包含文件。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">命令处理器</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/YashasSamaga/I-ZCMD" target="_blank" rel="noopener" class="mycode_url">I-ZCMD</a></span> - ZCMD 的改进版本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.CMD" target="_blank" rel="noopener" class="mycode_url">Pawn.CMD</a></span> - 比任何其他命令处理器都快。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pawn-lang/YSI-Includes/blob/5.x/YSI_Visual/y_commands.md" target="_blank" rel="noopener" class="mycode_url">y_commands</a></span> - 来自 YSI Includes 的命令处理器。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/samp-plugin-jit-backup" target="_blank" rel="noopener" class="mycode_url">JIT</a></span> - 代码稳定后，使用此插件可以显著提高速度。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-plugin-crashdetect" target="_blank" rel="noopener" class="mycode_url">CrashDetect</a></span> - 在测试期间用于查找错误的开发工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/samp-plugin-profiler-backup" target="_blank" rel="noopener" class="mycode_url">Profiler</a></span> - SA-MP 服务器的性能分析器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Y-Less/sscanf" target="_blank" rel="noopener" class="mycode_url">sscanf</a></span> - 将字符串转换为多个值、整数、浮点数、玩家等。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/pBlueG/SA-MP-MySQL" target="_blank" rel="noopener" class="mycode_url">MySQL Plugin</a></span> - 将服务器连接到 MySQL 数据库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-streamer-plugin" target="_blank" rel="noopener" class="mycode_url">Streamer Plugin</a></span> - 绕过许多 SA:MP 限制，例如物体和拾取物的数量限制。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/plugins/nativechecker.zip" target="_blank" rel="noopener" class="mycode_url">nativechecker</a></span> - 在服务器启动时检查原生函数。在 open.mp 中不需要，因为 open.mp 自带原生函数检查机制。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ziggi/FCNPC" target="_blank" rel="noopener" class="mycode_url">FCNPC</a></span> - 一个为 SA-MP 服务器添加大量功能给现有标准 NPC 的插件。它在 open.mp 中无法使用，但你可以改用官方的 NPC 组件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/JaTochNietDan/SA-MP-FileManager" target="_blank" rel="noopener" class="mycode_url">FileManager</a></span> - 允许你管理根文件夹中的文件和文件夹（通过此插件，不局限于 scriptfiles 服务器目录）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.RakNet" target="_blank" rel="noopener" class="mycode_url">Pawn.Raknet</a></span> - 允许你分析 RakNet 流量。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/bmisiak/samp-precise-timers" target="_blank" rel="noopener" class="mycode_url">samp-precise-timers</a></span> - 一个用 Rust 编写的 SA-MP 插件，提供精确计时器。在 open.mp 中不需要，因为 open.mp 自带精确计时器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/PawnPlus" target="_blank" rel="noopener" class="mycode_url">PawnPlus</a></span> - 通过新的结构、数据类型和编程技术扩展 Pawn 脚本语言的可能性。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/BigETI/pawn-memory" target="_blank" rel="noopener" class="mycode_url">PAWN memory access</a></span> - 允许在 PAWN 中从堆中分配和释放内存。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/NativeFallback" target="_blank" rel="noopener" class="mycode_url">Native Fallback</a></span> - SA-MP 插件，为未注册的原生函数提供回退实现。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/YSF" target="_blank" rel="noopener" class="mycode_url">YSF</a></span> - 一个旨在从服务器中挖掘最大可能性的插件，主要通过内存编辑和钩子实现。它的许多功能现在已经内置在 open.mp 中。请参阅 <a href="https://github.com/openmultiplayer/open.mp/issues/189" target="_blank" rel="noopener" class="mycode_url">这个 github issue</a> 了解功能列表。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/oscar-broman/SKY" target="_blank" rel="noopener" class="mycode_url">SKY</a></span> - 该插件提供底层函数，让 Pawn 脚本能够执行强大的操作。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/katursis/Pawn.Regex" target="_blank" rel="noopener" class="mycode_url">Pawn.Regex</a></span> - 为 Pawn 添加正则表达式支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/pawn-scraper" target="_blank" rel="noopener" class="mycode_url">pawn-scraper</a></span> - 一个强大的爬虫插件，提供了在 pawn 中使用 html 解析器和 css 选择器的接口。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/philip1337/samp-plugin-totp" target="_blank" rel="noopener" class="mycode_url">TOTP</a></span> - 允许在 sa-mp 游戏模式中使用 TOTP 身份验证。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-dns-plugin" target="_blank" rel="noopener" class="mycode_url">DNS Plugin</a></span> - 该插件提供 DNS 查找和反向 DNS 查找的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-plugin-mapandreas" target="_blank" rel="noopener" class="mycode_url">MapAndreas</a></span> - 允许你加载不同的高度图并检查 x, y 坐标处的最低高度。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Pottus/ColAndreas" target="_blank" rel="noopener" class="mycode_url">ColAndreas</a></span> - 创建一个圣安地列斯世界的模拟。使用 Bullet Physics 库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://bitbucket.org/Pamdex/pathfinder/src/master" target="_blank" rel="noopener" class="mycode_url">PathFinder</a></span> - 允许你计算圣安地列斯地图上从 A 点到 B 点的路线。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/spmn/samp-custom-query-flood-check" target="_blank" rel="noopener" class="mycode_url">Custom Query Flood Check</a></span> - 编写针对查询洪水攻击的自定义保护措施。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/YashasSamaga/sampml" target="_blank" rel="noopener" class="mycode_url">sampml</a></span> - 简化的机器学习工具包及相关 SAMP 项目（如自瞄检测）。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/tgconnector" target="_blank" rel="noopener" class="mycode_url">TgConnector</a></span> - 一个电报连接器插件，帮助通过 SA-MP 与电报机器人交互。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-discord-connector" target="_blank" rel="noopener" class="mycode_url">Discord connector</a></span> - 允许你从 PAWN 脚本中控制 Discord 机器人。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-tsconnector" target="_blank" rel="noopener" class="mycode_url">TSConnector</a></span> - 允许你从 PAWN 脚本中控制 Teamspeak3 服务器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/samp-incognito/samp-irc-plugin" target="_blank" rel="noopener" class="mycode_url">IRC Plugin</a></span> - 允许通过 SA-MP 服务器创建和管理 IRC 机器人。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-requests" target="_blank" rel="noopener" class="mycode_url">pawn-requests</a></span> - 提供了一个与 HTTP(S) API 交互的 API，支持文本和 JSON 数据类型。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-redis" target="_blank" rel="noopener" class="mycode_url">pawn-redis</a></span> - 授予对快速内存数据库的访问权限，以及与其他程序之间的异步消息通道。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-chrono" target="_blank" rel="noopener" class="mycode_url">Chrono</a></span> - 一个用于处理日期和时间的现代 Pawn 库。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ziggi/rustext" target="_blank" rel="noopener" class="mycode_url">rustext</a></span> - SA-MP 的俄文文本修复插件：修复 GameText、TextDraw 和 Menu。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/KrYpToDeN/Advanced-SA-NickName" target="_blank" rel="noopener" class="mycode_url">Advanced SA NickName</a></span> - 支持昵称中的任何符号。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Hual/SAMPSON" target="_blank" rel="noopener" class="mycode_url">SAMPSON</a></span> - 一个 SA-MP 的 JSON 插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/SimoSbara/samp-chatbot" target="_blank" rel="noopener" class="mycode_url">samp-chatbot</a></span> - 一个用于在游戏内进行 AI 聊天机器人通信的 GTA SAMP 插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-bscrashfix" target="_blank" rel="noopener" class="mycode_url">SAMP BitStream Crash Fix</a></span> - 修复了 BitStream 读取溢出的问题。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/pawn-json" target="_blank" rel="noopener" class="mycode_url">pawn-json</a></span> - 为 Pawn 提供的 JSON 支持。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">客户端-服务器插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Hual/SA-MP-Plus" target="_blank" rel="noopener" class="mycode_url">SA-MP+</a></span> - 一个客户端修改，利用 SA-MP 的插件 SDK 与服务器交互并添加新功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/dotSILENT/chandling" target="_blank" rel="noopener" class="mycode_url">CHandling</a></span> - 通过修改游戏的默认行为，为单个车辆分配车辆操控数据的功能。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/CyberMor/sampvoice" target="_blank" rel="noopener" class="mycode_url">SAMPVOICE</a></span> - 在 SA:MP 服务器的 Pawn 语言中实现语音通信系统。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/CyberMor/keylistener" target="_blank" rel="noopener" class="mycode_url">KeyListener</a></span> - 用于跟踪任何按键的客户端-服务器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ZOTTCE/samp-cef" target="_blank" rel="noopener" class="mycode_url">SAMP CEF</a></span> - 为 SA:MP 嵌入 CEF 的客户端和服务器插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Whitetigerswt/SAMP_AC_v2" target="_blank" rel="noopener" class="mycode_url">SAMP_AC_v2</a></span> - SA:MP 客户端反作弊。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">加密插件</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-whirlpool" target="_blank" rel="noopener" class="mycode_url">whirlpool</a></span> - SA:MP 的 Whirlpool 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Sreyas-Sreelal/samp-bcrypt" target="_blank" rel="noopener" class="mycode_url">SyS' bcrypt Plugin</a></span> - 由 Sreyas Sreelal 为 SA:MP 制作的 Bcrypt 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/lassir/bcrypt-samp" target="_blank" rel="noopener" class="mycode_url">lassir's bcrypt Plugin</a></span> - 由 lassir 为 SA:MP 制作的 Bcrypt 加密插件。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/alextwothousand/samp-crypto" target="_blank" rel="noopener" class="mycode_url">samp-crypto</a></span> - 为 SA:MP 提供的一系列加密函数，如 Argon2、Scrypt 和 Bcrypt。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/openmultiplayer/archive/raw/master/plugins/SHA512.zip" target="_blank" rel="noopener" class="mycode_url">SHA512</a></span> - SA:MP 的 SHA512 加密插件。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">GDK/SDK</h3><br />
<br />
现在，你可以使用 open.mp 在不借助任何插件的情况下，用 Pawn 以外的语言编写脚本。请参阅 <a href="https://www.open.mp/blog/release-candidate-1" target="_blank" rel="noopener" class="mycode_url">这篇博客文章</a>。<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/maddinat0r/samp-plugin-sdk" target="_blank" rel="noopener" class="mycode_url">sampsdk</a></span> - 这是开发插件所需的最基本内容。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Foundation-PAWN/sampgdk-backup" target="_blank" rel="noopener" class="mycode_url">sampgdk</a></span> - 为 SA:MP 编写游戏模式的 C/C++ 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ikkentim/SampSharp" target="_blank" rel="noopener" class="mycode_url">SampSharp</a></span> - 为 SA:MP 编写游戏模式的 C# 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Seregamil/.NET-plugin" target="_blank" rel="noopener" class="mycode_url">.NET Plugin</a></span> - 为 SA:MP 编写插件的 C# 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/sampgo/sampgo" target="_blank" rel="noopener" class="mycode_url">sampgo</a></span> - 为 SA:MP 编写游戏模式/插件的 Go 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/AmyrAhmady/samp-node" target="_blank" rel="noopener" class="mycode_url">samp-node</a></span> - 为 SA:MP 编写游戏模式的 Javascript/Typescript 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Shoebill/ShoebillPlugin" target="_blank" rel="noopener" class="mycode_url">Shoebill Project</a></span> - 为 SA:MP 编写游戏模式的 Java 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/habecker/PySAMP" target="_blank" rel="noopener" class="mycode_url">pySAMP</a></span> - 为 SA:MP 编写游戏模式的 Python 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/ZOTTCE/samp-rs" target="_blank" rel="noopener" class="mycode_url">samp-rs</a></span> - 为 SA:MP 编写插件的 Rust 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/IllidanS4/YALP" target="_blank" rel="noopener" class="mycode_url">Yet Another Lua Plugin</a></span> - 为 SA:MP 编写游戏模式的 Lua 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Lapayo/SAMPHP" target="_blank" rel="noopener" class="mycode_url">SAMPHP</a></span> - 为 SA:MP 编写游戏模式的 PHP 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">[SA-MP S[D]K](<a href="https://github.com/Hual/SA-MP-S-D-K" target="_blank" rel="noopener" class="mycode_url">https://github.com/Hual/SA-MP-S-D-K</a>)</span> - 为 SA:MP 编写游戏模式的 D 语言支持。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Double-O-Seven/kamp" target="_blank" rel="noopener" class="mycode_url">Kamp</a></span> - 为 SA:MP 编写游戏模式的 Kotlin 语言支持。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">游戏模式</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/midosvt/omp-base-script" target="_blank" rel="noopener" class="mycode_url">Simple base script</a></span> - 一个帮助初学者入门的简单基础脚本。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/ScavengeSurvive" target="_blank" rel="noopener" class="mycode_url">ScavengeSurvive</a></span> - 基于 PvP 的生存游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/PatrickGTR/gta-open" target="_blank" rel="noopener" class="mycode_url">gta-open</a></span> - 一个以洛圣都为背景的警察与匪徒模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/zeelorenc/sf-cnr" target="_blank" rel="noopener" class="mycode_url">SF-CnR</a></span> - 为 SA-MP 开发的圣费耶罗警察与匪徒游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NextGenerationGamingLLC/SA-MP-Development" target="_blank" rel="noopener" class="mycode_url">Next Generation Roleplay</a></span> - Next Generation Gaming, LLC 的 SA:MP 游戏模式。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/seanny/SC-RP" target="_blank" rel="noopener" class="mycode_url">SC-RP</a></span> - 一个支持 MySQL 的角色扮演游戏模式。<br />
</li>
</ul>
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">滤镜脚本</h3><br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/MapFix" target="_blank" rel="noopener" class="mycode_url">MapFix</a></span> - 修复 GTA 圣安地列斯地图的纹理错误。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Southclaws/samp-animbrowse" target="_blank" rel="noopener" class="mycode_url">SA:MP Animbrowse</a></span> - SA:MP 的动画浏览器工具。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Fairuz-Afdhal/IsPlayerUsingAndroid" target="_blank" rel="noopener" class="mycode_url">IsPlayerUsingAndroid</a></span> - 检查玩家是否为安卓用户。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Nickk888SAMP/TextDraw-Editor" target="_blank" rel="noopener" class="mycode_url">Nickk's TextDraw Editor</a></span> - 一个具有丰富功能的文本绘图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/nexquery/samp-textdraw-editor" target="_blank" rel="noopener" class="mycode_url">Nexor's Textdraw Editor</a></span> - 此编辑器提供许多功能，如分组、恢复删除的文本、撤销更改、从文件导入文本绘图等。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/NexiusTailer/Ultimate-Creator" target="_blank" rel="noopener" class="mycode_url">Ultimate Creator</a></span> - 具有众多功能的高级地图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/fusez/Map-Editor-V3" target="_blank" rel="noopener" class="mycode_url">Fusez's Map Editor</a></span> - SA:MP 的游戏内地图编辑器。<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b"><a href="https://github.com/Pottus/Texture-Studio" target="_blank" rel="noopener" class="mycode_url">Texture Studio</a></span> - 这是一个游戏内地图编辑器，允许你为物体贴图，最多支持材质索引 15（16 种材质），并可为该材质索引设置颜色。<br />
</li>
</ul>
]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[教程] 枚举器 enum 详细讲解 原文作者: iPLEOMAX]]></title>
			<link>https://open-mp.cn/showthread.php?tid=26</link>
			<pubDate>Sun, 22 Mar 2026 00:11:14 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=26</guid>
			<description><![CDATA[<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">枚举器</h3><br />
<br />
原文作者: iPLEOMAX<br />
<br />
关于枚举，有些细节很多脚本作者并不清楚。<br />
<br />
很多人都喜欢在脚本里用枚举来存玩家数据、车辆数据、房屋数据之类的，尤其是用户信息这块。<br />
<br />
一个很典型的写法是这样的：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_PLAYER_INFO<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SCORE,<br />
&nbsp;&nbsp;&nbsp;&nbsp;MONEY,<br />
&nbsp;&nbsp;&nbsp;&nbsp;KILLS,<br />
&nbsp;&nbsp;&nbsp;&nbsp;DEATHS<br />
};<br />
<br />
new pInfo[MAX_PLAYERS][E_PLAYER_INFO];</code></div></div><br />
用起来大概是这样：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
public OnPlayerDeath(playerid, killerid, reason)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;pInfo[playerid][DEATHS]++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(IsPlayerConnected(killerid) &amp;&amp; killerid != playerid)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pInfo[killerid][KILLS]++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
这段应该不难理解。<br />
<br />
现在我们看另一个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_PLAYER_INFO<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SCORE,<br />
&nbsp;&nbsp;&nbsp;&nbsp;MONEY = 9,<br />
&nbsp;&nbsp;&nbsp;&nbsp;KILLS = 5,<br />
&nbsp;&nbsp;&nbsp;&nbsp;DEATHS = 56<br />
};<br />
<br />
new pInfo[MAX_PLAYERS][E_PLAYER_INFO];<br />
<br />
printf("%i | %i | %i | %i", pInfo[0][SCORE], pInfo[0][MONEY], pInfo[0][KILLS], pInfo[0][DEATHS]);</code></div></div><br />
你可能会觉得输出是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0 | 9 | 5 | 56</code>，对吧？<br />
<br />
如果你这么想，那就错了。实际上输出是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0 | 0 | 0 | 0</code>。<br />
<br />
你可能会以为枚举是用来存储数据的，但事实并非如此。我在枚举里写了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MONEY = 9</code>，然后在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 里用了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pInfo[0][MONEY]</code>，但编译器其实把它当成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pInfo[0][9]</code> 来处理，而不是什么 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_PLAYER_INFO:MONEY</code>。也就是说，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MONEY</code> 在这里只是作为一个<span style="font-weight: bold;" class="mycode_b">索引</span>来用的。<br />
<br />
所以枚举本质上<span style="font-weight: bold;" class="mycode_b">根本不是变量</span>，它其实就是一组<span style="font-weight: bold;" class="mycode_b">常量</span>，只不过帮你的数组索引起了个好记的名字罢了。<br />
<br />
好，我们再来深入一点，应该能让你理解得更清楚。<br />
<br />
举个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
const e_CAR1 = 0;<br />
const e_CAR2 = 1;<br />
const e_CAR3 = 2;<br />
<br />
new MyCars[3];<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR1] = 520;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR2] = 458;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR3] = 411;<br />
}</code></div></div><br />
现在我们用枚举重写一下：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum e_TEST<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR1,<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR2,<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR3<br />
};<br />
<br />
new MyCars[e_TEST];<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR1] = 520;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR2] = 458;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR3] = 411;<br />
}</code></div></div><br />
这两段代码都能正常编译，做的事情也完全一样。你看出区别了吗？其实就只是代码写法不同而已。<br />
<br />
这个例子告诉我们，枚举干的事情和常量是一样的。不过枚举有些地方比常量或者宏定义（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const e_CAR1 = 0;</code> 或者 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define e_CAR1 0</code>）更好用，具体差异我们后面再说。<br />
<br />
首先你需要明白枚举的结构：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp; Abc,<br />
&nbsp;&nbsp; Def,<br />
&nbsp;&nbsp; Ghi,<br />
};</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Abc</code> 是一个值为 0 的常量（差不多等于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const Abc = 0;</code> 或 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define Abc 0</code>），<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Def</code> 是值为 1 的常量，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Ghi</code> 是值为 2 的常量。<br />
<br />
预编译器会自动给这些常量赋值，从 0 开始一直往上排。而用常量的时候，你得自己手动赋值。枚举则是自动帮你排好的。<br />
<br />
再看个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp; e_ONE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 自动得到 0<br />
&nbsp;&nbsp; e_TWO,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 得到 1<br />
&nbsp;&nbsp; e_THREE,&nbsp;&nbsp;&nbsp;&nbsp;// 得到 2<br />
&nbsp;&nbsp; e_FOUR = 12,// 这里手动赋了 12，所以不再是 3 了<br />
&nbsp;&nbsp; e_FIVE,&nbsp;&nbsp;&nbsp;&nbsp; // 变成 13，因为上一个值是 12<br />
&nbsp;&nbsp; e_SIX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 变成 14，上一个值是 13<br />
}</code></div></div><br />
看到了吧，如果你手动给某个枚举项赋了值，后面的项就会在此基础上依次加 1。<br />
<br />
再来看看更复杂的情况：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum DATA<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;INT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 得到 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;STRING[10],&nbsp;&nbsp;&nbsp;&nbsp; // 得到 1，但因为是数组，一个位置不够，它会占 10 个位置<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 所以实际占用的索引是 1, 2, 3, 4, 5, 6, 7, 8, 9, 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;INT2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 得到 11，因为 STRING 最后一位是 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;STRING2[10]&nbsp;&nbsp;&nbsp;&nbsp; // 从 12 开始，一直到 22，需要 10 个位置<br />
};</code></div></div><br />
运行下面的代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
printf("%i", _:DATA);</code></div></div><br />
结果输出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">22</code>。<br />
<br />
因为整个枚举的总大小是 22：<br />
INT 占 1 个 + STRING 占 10 个 + INT2 占 1 个 + STRING2 占 10 个 = 22。<br />
<br />
你可能会问，为什么我写 INT 是 1 而不是 0？因为这里我数的是<span style="font-weight: bold;" class="mycode_b">占用了多少个位置</span>，不是<span style="font-weight: bold;" class="mycode_b">从哪个位置开始</span>。如果问起始位置，那 INT 确实是 0。<br />
<br />
一个大小为 22 的块，索引范围是 0 到 21，总共 22 个位置。<br />
<br />
再试一下：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
printf("%i", _:STRING);</code></div></div><br />
输出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1</code>。因为第一个位置（索引 0）被 INT 占了，所以 STRING 从索引 1 开始。<br />
<br />
每个枚举项占用的位置是这样的：<ul class="mycode_list"><li>INT：索引 0<br />
</li>
<li>STRING：索引 1 到 10<br />
</li>
<li>INT2：索引 11<br />
</li>
<li>STRING2：索引 12 到 21<br />
</li>
</ul>
<br />
运行这段：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new Array[DATA];<br />
printf("%i", sizeof Array);</code></div></div><br />
结果也是 22，因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">DATA</code> 的大小就是 22。<br />
<br />
所以，这个数组实际上相当于：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
Array[INT + STRING + INT2 + STRING2];</code></div></div>这行代码是编译不了的，只是帮你想明白结构而已。<br />
<br />
也就是说，用枚举的时候，你其实是用这些枚举常量作为数组的索引。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">另一个例子</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SomeInteger = 124,<br />
&nbsp;&nbsp;&nbsp;&nbsp;SomeString[12],<br />
&nbsp;&nbsp;&nbsp;&nbsp;Float:SomeFloat<br />
};<br />
<br />
public OnFilterScriptInit()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new var_TEST[TEST];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;var_TEST[SomeInteger] = 1337;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("1) 储存的值: %i, 常量: %i", var_TEST[SomeInteger], _:SomeInteger);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;format(var_TEST[SomeString], 12, "Hey!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("2) 储存的值: %s, 常量: %i", var_TEST[SomeString], _:SomeString);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;var_TEST[SomeFloat] = 2054.124;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("3) 储存的值: %f, 常量: %i", var_TEST[SomeFloat], _:SomeFloat);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;return true;<br />
}</code></div></div><br />
输出结果：<br />
<ol type="1" class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: 1337, 常量: 124</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: Hey!, 常量: 125</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: 2054.124023, 常量: 137</code><br />
</li>
</ol>
<br />
第一行，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeInteger</code> 的常量值是 124，我把 1337 存到了索引 124 的位置。<br />
<br />
第二行，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString</code> 虽然定义了长度为 12，但输出常量值时显示的是 125。因为 125 是这个字符串的起始索引，它占了 125 到 136 这 12 个位置。<br />
<br />
第三行，浮点数正常显示，但 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeFloat</code> 的常量值是 137。你可能会想，它应该在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString</code>（125）后面，应该是 126 才对？但别忘了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString[12]</code> 是个数组，占了 12 个位置，所以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeFloat</code> 的起始索引是 125 + 12 = 137。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">一些额外的重要信息</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">枚举也可以作为标签使用：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_MY_TAG<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_FIRST = 4,<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_SECOND = 2<br />
}</code></div></div><br />
然后可以这样写：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new E_MY_TAG:SomeVar;</code></div></div>或者：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new E_MY_TAG:MyVariable = E_FIRST; // 不会报错，因为 E_FIRST 本来就是 E_MY_TAG 的一部分</code></div></div><br />
但是：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new data[E_MY_TAG];<br />
data[E_FIRST] = 7; // 编译错误，索引越界</code></div></div>因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_MY_TAG</code> 的大小是 3（枚举里最大索引是 2），而 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_FIRST</code> 的值是 4，已经超出范围了。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">匿名枚举：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum // 没有名字<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_TEST[10] = 32,<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new data[E_TEST]; // E_TEST 的值是 32，不是 10<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">强标签和弱标签：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_STRONG // 名字以大写字母开头，生成的是强标签<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR = 64<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new Test = E_STRONG:E_VAR; <br />
&nbsp;&nbsp;&nbsp;&nbsp;// 会报“标签不匹配”的警告，因为 Test 没有 E_STRONG 标签<br />
}</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum e_WEAK // 名字以小写字母开头，生成的是弱标签<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR = 64<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new Test = e_WEAK:E_VAR; <br />
&nbsp;&nbsp;&nbsp;&nbsp;// 没有警告<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
枚举的大概内容就是这些了，这也是为什么我们更喜欢用枚举而不是直接写常量的原因。<br />
<br />
<span style="font-style: italic;" class="mycode_i">感谢 Y_Less 的讲解。</span>]]></description>
			<content:encoded><![CDATA[<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">枚举器</h3><br />
<br />
原文作者: iPLEOMAX<br />
<br />
关于枚举，有些细节很多脚本作者并不清楚。<br />
<br />
很多人都喜欢在脚本里用枚举来存玩家数据、车辆数据、房屋数据之类的，尤其是用户信息这块。<br />
<br />
一个很典型的写法是这样的：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_PLAYER_INFO<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SCORE,<br />
&nbsp;&nbsp;&nbsp;&nbsp;MONEY,<br />
&nbsp;&nbsp;&nbsp;&nbsp;KILLS,<br />
&nbsp;&nbsp;&nbsp;&nbsp;DEATHS<br />
};<br />
<br />
new pInfo[MAX_PLAYERS][E_PLAYER_INFO];</code></div></div><br />
用起来大概是这样：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
public OnPlayerDeath(playerid, killerid, reason)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;pInfo[playerid][DEATHS]++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(IsPlayerConnected(killerid) &amp;&amp; killerid != playerid)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pInfo[killerid][KILLS]++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
这段应该不难理解。<br />
<br />
现在我们看另一个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_PLAYER_INFO<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SCORE,<br />
&nbsp;&nbsp;&nbsp;&nbsp;MONEY = 9,<br />
&nbsp;&nbsp;&nbsp;&nbsp;KILLS = 5,<br />
&nbsp;&nbsp;&nbsp;&nbsp;DEATHS = 56<br />
};<br />
<br />
new pInfo[MAX_PLAYERS][E_PLAYER_INFO];<br />
<br />
printf("%i | %i | %i | %i", pInfo[0][SCORE], pInfo[0][MONEY], pInfo[0][KILLS], pInfo[0][DEATHS]);</code></div></div><br />
你可能会觉得输出是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0 | 9 | 5 | 56</code>，对吧？<br />
<br />
如果你这么想，那就错了。实际上输出是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0 | 0 | 0 | 0</code>。<br />
<br />
你可能会以为枚举是用来存储数据的，但事实并非如此。我在枚举里写了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MONEY = 9</code>，然后在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 里用了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pInfo[0][MONEY]</code>，但编译器其实把它当成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pInfo[0][9]</code> 来处理，而不是什么 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_PLAYER_INFO:MONEY</code>。也就是说，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MONEY</code> 在这里只是作为一个<span style="font-weight: bold;" class="mycode_b">索引</span>来用的。<br />
<br />
所以枚举本质上<span style="font-weight: bold;" class="mycode_b">根本不是变量</span>，它其实就是一组<span style="font-weight: bold;" class="mycode_b">常量</span>，只不过帮你的数组索引起了个好记的名字罢了。<br />
<br />
好，我们再来深入一点，应该能让你理解得更清楚。<br />
<br />
举个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
const e_CAR1 = 0;<br />
const e_CAR2 = 1;<br />
const e_CAR3 = 2;<br />
<br />
new MyCars[3];<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR1] = 520;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR2] = 458;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR3] = 411;<br />
}</code></div></div><br />
现在我们用枚举重写一下：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum e_TEST<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR1,<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR2,<br />
&nbsp;&nbsp;&nbsp;&nbsp;e_CAR3<br />
};<br />
<br />
new MyCars[e_TEST];<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR1] = 520;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR2] = 458;<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyCars[e_CAR3] = 411;<br />
}</code></div></div><br />
这两段代码都能正常编译，做的事情也完全一样。你看出区别了吗？其实就只是代码写法不同而已。<br />
<br />
这个例子告诉我们，枚举干的事情和常量是一样的。不过枚举有些地方比常量或者宏定义（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const e_CAR1 = 0;</code> 或者 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define e_CAR1 0</code>）更好用，具体差异我们后面再说。<br />
<br />
首先你需要明白枚举的结构：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp; Abc,<br />
&nbsp;&nbsp; Def,<br />
&nbsp;&nbsp; Ghi,<br />
};</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Abc</code> 是一个值为 0 的常量（差不多等于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const Abc = 0;</code> 或 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define Abc 0</code>），<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Def</code> 是值为 1 的常量，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Ghi</code> 是值为 2 的常量。<br />
<br />
预编译器会自动给这些常量赋值，从 0 开始一直往上排。而用常量的时候，你得自己手动赋值。枚举则是自动帮你排好的。<br />
<br />
再看个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp; e_ONE,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 自动得到 0<br />
&nbsp;&nbsp; e_TWO,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 得到 1<br />
&nbsp;&nbsp; e_THREE,&nbsp;&nbsp;&nbsp;&nbsp;// 得到 2<br />
&nbsp;&nbsp; e_FOUR = 12,// 这里手动赋了 12，所以不再是 3 了<br />
&nbsp;&nbsp; e_FIVE,&nbsp;&nbsp;&nbsp;&nbsp; // 变成 13，因为上一个值是 12<br />
&nbsp;&nbsp; e_SIX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 变成 14，上一个值是 13<br />
}</code></div></div><br />
看到了吧，如果你手动给某个枚举项赋了值，后面的项就会在此基础上依次加 1。<br />
<br />
再来看看更复杂的情况：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum DATA<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;INT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 得到 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;STRING[10],&nbsp;&nbsp;&nbsp;&nbsp; // 得到 1，但因为是数组，一个位置不够，它会占 10 个位置<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 所以实际占用的索引是 1, 2, 3, 4, 5, 6, 7, 8, 9, 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;INT2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 得到 11，因为 STRING 最后一位是 10<br />
&nbsp;&nbsp;&nbsp;&nbsp;STRING2[10]&nbsp;&nbsp;&nbsp;&nbsp; // 从 12 开始，一直到 22，需要 10 个位置<br />
};</code></div></div><br />
运行下面的代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
printf("%i", _:DATA);</code></div></div><br />
结果输出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">22</code>。<br />
<br />
因为整个枚举的总大小是 22：<br />
INT 占 1 个 + STRING 占 10 个 + INT2 占 1 个 + STRING2 占 10 个 = 22。<br />
<br />
你可能会问，为什么我写 INT 是 1 而不是 0？因为这里我数的是<span style="font-weight: bold;" class="mycode_b">占用了多少个位置</span>，不是<span style="font-weight: bold;" class="mycode_b">从哪个位置开始</span>。如果问起始位置，那 INT 确实是 0。<br />
<br />
一个大小为 22 的块，索引范围是 0 到 21，总共 22 个位置。<br />
<br />
再试一下：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
printf("%i", _:STRING);</code></div></div><br />
输出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1</code>。因为第一个位置（索引 0）被 INT 占了，所以 STRING 从索引 1 开始。<br />
<br />
每个枚举项占用的位置是这样的：<ul class="mycode_list"><li>INT：索引 0<br />
</li>
<li>STRING：索引 1 到 10<br />
</li>
<li>INT2：索引 11<br />
</li>
<li>STRING2：索引 12 到 21<br />
</li>
</ul>
<br />
运行这段：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new Array[DATA];<br />
printf("%i", sizeof Array);</code></div></div><br />
结果也是 22，因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">DATA</code> 的大小就是 22。<br />
<br />
所以，这个数组实际上相当于：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
Array[INT + STRING + INT2 + STRING2];</code></div></div>这行代码是编译不了的，只是帮你想明白结构而已。<br />
<br />
也就是说，用枚举的时候，你其实是用这些枚举常量作为数组的索引。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">另一个例子</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum TEST<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SomeInteger = 124,<br />
&nbsp;&nbsp;&nbsp;&nbsp;SomeString[12],<br />
&nbsp;&nbsp;&nbsp;&nbsp;Float:SomeFloat<br />
};<br />
<br />
public OnFilterScriptInit()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new var_TEST[TEST];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;var_TEST[SomeInteger] = 1337;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("1) 储存的值: %i, 常量: %i", var_TEST[SomeInteger], _:SomeInteger);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;format(var_TEST[SomeString], 12, "Hey!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("2) 储存的值: %s, 常量: %i", var_TEST[SomeString], _:SomeString);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;var_TEST[SomeFloat] = 2054.124;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("3) 储存的值: %f, 常量: %i", var_TEST[SomeFloat], _:SomeFloat);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;return true;<br />
}</code></div></div><br />
输出结果：<br />
<ol type="1" class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: 1337, 常量: 124</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: Hey!, 常量: 125</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">储存的值: 2054.124023, 常量: 137</code><br />
</li>
</ol>
<br />
第一行，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeInteger</code> 的常量值是 124，我把 1337 存到了索引 124 的位置。<br />
<br />
第二行，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString</code> 虽然定义了长度为 12，但输出常量值时显示的是 125。因为 125 是这个字符串的起始索引，它占了 125 到 136 这 12 个位置。<br />
<br />
第三行，浮点数正常显示，但 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeFloat</code> 的常量值是 137。你可能会想，它应该在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString</code>（125）后面，应该是 126 才对？但别忘了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeString[12]</code> 是个数组，占了 12 个位置，所以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SomeFloat</code> 的起始索引是 125 + 12 = 137。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">一些额外的重要信息</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">枚举也可以作为标签使用：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_MY_TAG<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_FIRST = 4,<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_SECOND = 2<br />
}</code></div></div><br />
然后可以这样写：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new E_MY_TAG:SomeVar;</code></div></div>或者：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new E_MY_TAG:MyVariable = E_FIRST; // 不会报错，因为 E_FIRST 本来就是 E_MY_TAG 的一部分</code></div></div><br />
但是：<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
new data[E_MY_TAG];<br />
data[E_FIRST] = 7; // 编译错误，索引越界</code></div></div>因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_MY_TAG</code> 的大小是 3（枚举里最大索引是 2），而 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_FIRST</code> 的值是 4，已经超出范围了。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">匿名枚举：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum // 没有名字<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_TEST[10] = 32,<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new data[E_TEST]; // E_TEST 的值是 32，不是 10<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">强标签和弱标签：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum E_STRONG // 名字以大写字母开头，生成的是强标签<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR = 64<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new Test = E_STRONG:E_VAR; <br />
&nbsp;&nbsp;&nbsp;&nbsp;// 会报“标签不匹配”的警告，因为 Test 没有 E_STRONG 标签<br />
}</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code class="language-cpp" data-lang="cpp"><br />
enum e_WEAK // 名字以小写字母开头，生成的是弱标签<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;E_VAR = 64<br />
};<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new Test = e_WEAK:E_VAR; <br />
&nbsp;&nbsp;&nbsp;&nbsp;// 没有警告<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
枚举的大概内容就是这些了，这也是为什么我们更喜欢用枚举而不是直接写常量的原因。<br />
<br />
<span style="font-style: italic;" class="mycode_i">感谢 Y_Less 的讲解。</span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[教程] Pawn 中的压缩字符串 原文作者: Emmet_]]></title>
			<link>https://open-mp.cn/showthread.php?tid=25</link>
			<pubDate>Sat, 21 Mar 2026 23:52:50 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=25</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">Pawn 中的压缩字符串</h2><br />
<br />
原文作者: Emmet_ 本篇教程仅为翻译搬运<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">引言</h3><br />
<br />
压缩字符串自 SA-MP 和 Pawn 诞生之初就已存在。然而，很多人并不了解压缩字符串以及它能节省多少内存！本教程将教你压缩字符串的基础知识，以及如何正确操作它们。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">什么是压缩字符串？</h3><br />
<br />
压缩字符串是一种数组，它将数据存储在<span style="font-weight: bold;" class="mycode_b">每个字节</span>中，而不是像普通数组那样存储在<span style="font-weight: bold;" class="mycode_b">每个单元格</span>中。压缩字符串以小端序存储（即低位字节在前），并且只能容纳 0 到 255 的 ASCII 字符，超出这个范围的数值会绕回。<br />
<br />
看这段代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new string[5];<br />
string[0] = 'a';<br />
string[1] = 'b';<br />
string[2] = 'c';<br />
string[3] = 'd';<br />
string[4] = '&#92;0';</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'a'</code> 存储在单元格 0，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'b'</code> 存储在单元格 1，依此类推。一个单元格基本上占用 4 个字节，所以算一下，上面的字符串大约占用 20 个字节，每个字符占用 4 个字节的空间。<br />
<br />
然而，使用下面的代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new string[5 char];<br />
string{0} = 'a';<br />
string{1} = 'b';<br />
string{2} = 'c';<br />
string{3} = 'd';<br />
string{4} = '&#92;0';</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'a'</code> 存储在字节 0，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'b'</code> 存储在字节 1，依此类推。实际上，上面的字符串只占用 8 个字节，仅包含 2 个单元格！<br />
<br />
你可能在想为什么这个字符串不是 5 个字节。使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">char</code> 修饰符会自动将数组大小向上取整到最近的 4 的倍数（例如，1 变成 4，3 变成 4，5 变成 8，23 变成 24，依此类推）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 这个数组占用 5 个单元格，共 20 个字节。<br />
new string[5] = "abcd"; <br />
// 这个数组占用 2 个单元格，共 8 个字节。<br />
new string[5 char] = !"abcd";</code></div></div><br />
因此，使用压缩字符串可以节省 3 到 4 倍的内存！<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">适用场景</h3><br />
<br />
你可能认为压缩数组没什么用。如果这么想，那你就错了。压缩数组有很多用途，不仅仅是节省内存！<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">稀疏数组</h4><br />
<br />
首先，你可以阅读我关于稀疏数组的教程：<br />
<br />
<a href="https://sampforum.blast.hk/showthread.php?tid=480439" target="_blank" rel="noopener" class="mycode_url">https://sampforum.blast.hk/showthread.php?tid=480439</a><br />
<br />
稀疏数组就是那些大部分数据经常为空的数组。使用压缩数组可以轻松节省内存！<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MAX_ITEMS (64)<br />
// 8,192 个单元格 = 32,768 字节！<br />
new gData[MAX_ITEMS][128];<br />
// 2,048 个字节 = 8,192 个单元格！<br />
new gData[MAX_ITEMS][128 char];</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">不常使用的字符串</h4><br />
<br />
很多时候，你会把字符串保存到内存中，但很少使用它们（例如几乎不用）。对于这类数组，压缩数组非常适用。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">大量数据存储</h4><br />
<br />
回到上面的“稀疏数组”部分，如果你需要存储大量数据，最好使用压缩字符串。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">内存节省！</h4><br />
<br />
压缩数组能节省 4 倍的内存，既然可以用压缩数组，为什么还要用那些多占 4 倍内存的方式存储数据呢？<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">SA-MP 中的不支持情况</h3><br />
<br />
压缩字符串在纯 Pawn 中完美支持。但是，大多数 SA-MP 原生函数<span style="font-weight: bold;" class="mycode_b">不支持</span>压缩字符串，比如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">format</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetPlayerName</code> 等。<br />
<br />
如果你打算使用压缩字符串，就必须依赖 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strpack</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strunpack</code> 以及 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string.inc</code> 中的其他字符串函数。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">格式化字符串</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">format</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 函数不支持压缩字符串，因此你必须使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strpack</code>：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    string[128 char];<br />
strpack(string, "Hello world!");</code></div></div><br />
你也可以这样做：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new <br />
    string[128 char],<br />
    temp[128]<br />
;<br />
strpack(string, "Emmet");<br />
strunpack(temp, string);<br />
format(temp, sizeof(temp), "%s likes to eat %s.", temp, "Big Macs");<br />
strpack(string, temp);</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">支持压缩字符串的函数</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string.inc</code> 中的所有字符串函数都同时支持压缩数组和非压缩数组。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">fread</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">valstr</code> 函数也接受一个可选的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pack</code> 参数来支持压缩数组，因此你不用担心它们是否能与压缩数组一起工作。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">访问数据</h3><br />
<br />
在 Pawn 中，非压缩数组将数据存储在<span style="font-weight: bold;" class="mycode_b">每个单元格</span>中。而压缩数组将数据存储在<span style="font-weight: bold;" class="mycode_b">每个字节</span>中，这意味着你不能像访问非压缩数组那样使用方括号 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">[]</code> 来访问和获取压缩数组中的数据。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误。<br />
if (g_PackedString[0] != '&#92;0')<br />
{<br />
    g_PackedString[0] = 'h';<br />
    g_PackedString[1] = 'i';<br />
}<br />
// 正确！<br />
if (g_PackedString{0} != '&#92;0')<br />
{<br />
    g_PackedString{0} = 'h'; <br />
    g_PackedString{1} = 'i';<br />
}</code></div></div><br />
另外，要设置一个压缩字符串，你需要在字符串前加上感叹号，以表示这是压缩输入。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误。这会尝试将字符串按单元格存储，这不是我们想要的！<br />
g_PackedString = "Hello world.";<br />
// 正确！<br />
g_PackedString = !"Hello world.";</code></div></div>]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">Pawn 中的压缩字符串</h2><br />
<br />
原文作者: Emmet_ 本篇教程仅为翻译搬运<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">引言</h3><br />
<br />
压缩字符串自 SA-MP 和 Pawn 诞生之初就已存在。然而，很多人并不了解压缩字符串以及它能节省多少内存！本教程将教你压缩字符串的基础知识，以及如何正确操作它们。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">什么是压缩字符串？</h3><br />
<br />
压缩字符串是一种数组，它将数据存储在<span style="font-weight: bold;" class="mycode_b">每个字节</span>中，而不是像普通数组那样存储在<span style="font-weight: bold;" class="mycode_b">每个单元格</span>中。压缩字符串以小端序存储（即低位字节在前），并且只能容纳 0 到 255 的 ASCII 字符，超出这个范围的数值会绕回。<br />
<br />
看这段代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new string[5];<br />
string[0] = 'a';<br />
string[1] = 'b';<br />
string[2] = 'c';<br />
string[3] = 'd';<br />
string[4] = '&#92;0';</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'a'</code> 存储在单元格 0，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'b'</code> 存储在单元格 1，依此类推。一个单元格基本上占用 4 个字节，所以算一下，上面的字符串大约占用 20 个字节，每个字符占用 4 个字节的空间。<br />
<br />
然而，使用下面的代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new string[5 char];<br />
string{0} = 'a';<br />
string{1} = 'b';<br />
string{2} = 'c';<br />
string{3} = 'd';<br />
string{4} = '&#92;0';</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'a'</code> 存储在字节 0，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'b'</code> 存储在字节 1，依此类推。实际上，上面的字符串只占用 8 个字节，仅包含 2 个单元格！<br />
<br />
你可能在想为什么这个字符串不是 5 个字节。使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">char</code> 修饰符会自动将数组大小向上取整到最近的 4 的倍数（例如，1 变成 4，3 变成 4，5 变成 8，23 变成 24，依此类推）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 这个数组占用 5 个单元格，共 20 个字节。<br />
new string[5] = "abcd"; <br />
// 这个数组占用 2 个单元格，共 8 个字节。<br />
new string[5 char] = !"abcd";</code></div></div><br />
因此，使用压缩字符串可以节省 3 到 4 倍的内存！<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">适用场景</h3><br />
<br />
你可能认为压缩数组没什么用。如果这么想，那你就错了。压缩数组有很多用途，不仅仅是节省内存！<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">稀疏数组</h4><br />
<br />
首先，你可以阅读我关于稀疏数组的教程：<br />
<br />
<a href="https://sampforum.blast.hk/showthread.php?tid=480439" target="_blank" rel="noopener" class="mycode_url">https://sampforum.blast.hk/showthread.php?tid=480439</a><br />
<br />
稀疏数组就是那些大部分数据经常为空的数组。使用压缩数组可以轻松节省内存！<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MAX_ITEMS (64)<br />
// 8,192 个单元格 = 32,768 字节！<br />
new gData[MAX_ITEMS][128];<br />
// 2,048 个字节 = 8,192 个单元格！<br />
new gData[MAX_ITEMS][128 char];</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">不常使用的字符串</h4><br />
<br />
很多时候，你会把字符串保存到内存中，但很少使用它们（例如几乎不用）。对于这类数组，压缩数组非常适用。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">大量数据存储</h4><br />
<br />
回到上面的“稀疏数组”部分，如果你需要存储大量数据，最好使用压缩字符串。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">内存节省！</h4><br />
<br />
压缩数组能节省 4 倍的内存，既然可以用压缩数组，为什么还要用那些多占 4 倍内存的方式存储数据呢？<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">SA-MP 中的不支持情况</h3><br />
<br />
压缩字符串在纯 Pawn 中完美支持。但是，大多数 SA-MP 原生函数<span style="font-weight: bold;" class="mycode_b">不支持</span>压缩字符串，比如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">format</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetPlayerName</code> 等。<br />
<br />
如果你打算使用压缩字符串，就必须依赖 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strpack</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strunpack</code> 以及 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string.inc</code> 中的其他字符串函数。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">格式化字符串</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">format</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 函数不支持压缩字符串，因此你必须使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">strpack</code>：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    string[128 char];<br />
strpack(string, "Hello world!");</code></div></div><br />
你也可以这样做：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new <br />
    string[128 char],<br />
    temp[128]<br />
;<br />
strpack(string, "Emmet");<br />
strunpack(temp, string);<br />
format(temp, sizeof(temp), "%s likes to eat %s.", temp, "Big Macs");<br />
strpack(string, temp);</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">支持压缩字符串的函数</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string.inc</code> 中的所有字符串函数都同时支持压缩数组和非压缩数组。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">fread</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">valstr</code> 函数也接受一个可选的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pack</code> 参数来支持压缩数组，因此你不用担心它们是否能与压缩数组一起工作。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">访问数据</h3><br />
<br />
在 Pawn 中，非压缩数组将数据存储在<span style="font-weight: bold;" class="mycode_b">每个单元格</span>中。而压缩数组将数据存储在<span style="font-weight: bold;" class="mycode_b">每个字节</span>中，这意味着你不能像访问非压缩数组那样使用方括号 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">[]</code> 来访问和获取压缩数组中的数据。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误。<br />
if (g_PackedString[0] != '&#92;0')<br />
{<br />
    g_PackedString[0] = 'h';<br />
    g_PackedString[1] = 'i';<br />
}<br />
// 正确！<br />
if (g_PackedString{0} != '&#92;0')<br />
{<br />
    g_PackedString{0} = 'h'; <br />
    g_PackedString{1} = 'i';<br />
}</code></div></div><br />
另外，要设置一个压缩字符串，你需要在字符串前加上感叹号，以表示这是压缩输入。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误。这会尝试将字符串按单元格存储，这不是我们想要的！<br />
g_PackedString = "Hello world.";<br />
// 正确！<br />
g_PackedString = !"Hello world.";</code></div></div>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[修仙者篇] AMX 汇编文档]]></title>
			<link>https://open-mp.cn/showthread.php?tid=24</link>
			<pubDate>Sat, 21 Mar 2026 23:19:49 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=24</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> AMX 汇编</h2><br />
<br />
AMX 版本: 3.0<br />
<br />
AMX 文件版本: 8<br />
<br />
本文档是关于抽象机执行器（Abstract Machine eXecutor）汇编的<span style="font-style: italic;" class="mycode_i">非官方</span>文档。本文档的内容可能不准确且可能随时更改。<a href="http://#terminology" target="_blank" rel="noopener" class="mycode_url">术语部分</a>中定义的部分术语在官方手册中并未出现。它们是为了帮助读者理解而引入的辅助术语。<br />
<br />
本文档的目标读者是首次接触汇编语言的程序员。他们应根据需要点击超链接以收集背景信息。高级用户可跳过部分章节或将本文档用作快速参考指南。<br />
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 目录</h2><ul class="mycode_list"><li><a href="http://#prerequisites" target="_blank" rel="noopener" class="mycode_url">先决条件</a><br />
</li>
<li><a href="http://#terminology" target="_blank" rel="noopener" class="mycode_url">术语</a><br />
</li>
<li><a href="http://#term-amx" target="_blank" rel="noopener" class="mycode_url">抽象机执行器 (AMX)</a><br />
</li>
<li><a href="http://#term-amx-assembly" target="_blank" rel="noopener" class="mycode_url">AMX 汇编</a><br />
</li>
<li><a href="http://#term-amx-binary" target="_blank" rel="noopener" class="mycode_url">AMX 二进制</a><br />
</li>
<li><a href="http://#term-amx-instance" target="_blank" rel="noopener" class="mycode_url">AMX 实例</a><br />
</li>
<li><a href="http://#term-host-program" target="_blank" rel="noopener" class="mycode_url">宿主程序</a><br />
</li>
<li><a href="http://#term-extension-module" target="_blank" rel="noopener" class="mycode_url">扩展模块</a><br />
</li>
<li><a href="http://#basic-concepts" target="_blank" rel="noopener" class="mycode_url">基本概念</a><br />
</li>
<li><a href="http://#concept-cell" target="_blank" rel="noopener" class="mycode_url">单元格概念</a><br />
</li>
<li><a href="http://#concept-memory-addresses" target="_blank" rel="noopener" class="mycode_url">内存地址</a><br />
</li>
<li><a href="http://#concept-stack-heap" target="_blank" rel="noopener" class="mycode_url">栈与堆</a><br />
</li>
<li><a href="http://#concept-instructions" target="_blank" rel="noopener" class="mycode_url">指令</a><br />
</li>
<li><a href="http://#concept-spc-vna" target="_blank" rel="noopener" class="mycode_url">存储程序概念与冯·诺依曼体系结构</a><br />
</li>
<li><a href="http://#concept-hdc" target="_blank" rel="noopener" class="mycode_url">头、数据段、代码段</a><br />
</li>
<li><a href="http://#concept-registers" target="_blank" rel="noopener" class="mycode_url">寄存器</a><br />
</li>
<li><a href="http://#file-memory-layout" target="_blank" rel="noopener" class="mycode_url">文件与内存布局</a><br />
</li>
<li><a href="http://#instruction-set" target="_blank" rel="noopener" class="mycode_url">指令集</a><br />
</li>
<li><a href="http://#pawn-inline-assembly" target="_blank" rel="noopener" class="mycode_url">Pawn 内联汇编语法</a><br />
</li>
<li><a href="http://#instruction-table" target="_blank" rel="noopener" class="mycode_url">指令表</a><br />
</li>
<li><a href="http://#loadstore-instructions" target="_blank" rel="noopener" class="mycode_url">加载/存储指令</a><br />
</li>
<li><a href="http://#indexing-instructions" target="_blank" rel="noopener" class="mycode_url">索引指令</a><br />
</li>
<li><a href="http://#arithmetic-instructions" target="_blank" rel="noopener" class="mycode_url">算术指令</a><br />
</li>
<li><a href="http://#logical-instructions" target="_blank" rel="noopener" class="mycode_url">逻辑指令</a><br />
</li>
<li><a href="http://#relational-instructions" target="_blank" rel="noopener" class="mycode_url">关系指令</a><br />
</li>
<li><a href="http://#stack-manipulation-instructions" target="_blank" rel="noopener" class="mycode_url">栈操作指令</a><br />
</li>
<li><a href="http://#heap-instructions" target="_blank" rel="noopener" class="mycode_url">堆指令</a><br />
</li>
<li><a href="http://#control-register-manipulation-instructions" target="_blank" rel="noopener" class="mycode_url">控制寄存器操作指令</a><br />
</li>
<li><a href="http://#control-flow-instructions" target="_blank" rel="noopener" class="mycode_url">控制流指令</a><br />
</li>
<li><a href="http://#switch-case-instructions" target="_blank" rel="noopener" class="mycode_url">Switch-case 指令</a><br />
</li>
<li><a href="http://#call-stack-and-call-convention" target="_blank" rel="noopener" class="mycode_url">调用栈与调用约定</a><br />
</li>
<li><a href="http://#local-variables-and-function-frame" target="_blank" rel="noopener" class="mycode_url">局部变量与函数帧</a><br />
</li>
<li><a href="http://#call-convention" target="_blank" rel="noopener" class="mycode_url">调用约定</a><br />
</li>
<li><a href="http://#methods-passing-arguments" target="_blank" rel="noopener" class="mycode_url">参数传递方法</a><br />
</li>
<li><a href="http://#system-requests" target="_blank" rel="noopener" class="mycode_url">系统请求</a><br />
</li>
<li><a href="http://#multi-dimensional-arrays" target="_blank" rel="noopener" class="mycode_url">多维数组</a><br />
</li>
</ul>
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 先决条件</h2><ul class="mycode_list"><li>Pawn 脚本语言<br />
</li>
<li><a href="https://en.wikipedia.org/wiki/Binary_number" target="_blank" rel="noopener" class="mycode_url">二进制数制</a><br />
</li>
<li><a href="https://en.wikipedia.org/wiki/Hexadecimal" target="_blank" rel="noopener" class="mycode_url">十六进制数制</a><br />
</li>
<li>内存地址（理解<a href="https://en.wikipedia.org/wiki/Pointer_(computer_programming)" target="_blank" rel="noopener" class="mycode_url">指针</a>更佳）<br />
</li>
<li><a href="https://en.wikipedia.org/wiki/Stack_(abstract_data_type)" target="_blank" rel="noopener" class="mycode_url">栈（作为抽象数据类型）</a><br />
</li>
</ul>
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 术语</h2><br />
&lt;a name="term-amx"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">抽象机执行器 (AMX)</span>：AMX 是我们感兴趣的<a href="https://en.wikipedia.org/wiki/Abstract_machine" target="_blank" rel="noopener" class="mycode_url">抽象机</a>（或<a href="https://en.wikipedia.org/wiki/Virtual_machine" target="_blank" rel="noopener" class="mycode_url">虚拟机</a>）。<br />
<br />
&lt;a name="term-amx-assembly"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">AMX 汇编</span>：AMX 的<a href="https://en.wikipedia.org/wiki/Assembly_language" target="_blank" rel="noopener" class="mycode_url">汇编语言</a>。<br />
<br />
&lt;a name="term-amx-binary"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">AMX 二进制</span>：AMX <a href="https://en.wikipedia.org/wiki/Executable" target="_blank" rel="noopener" class="mycode_url">二进制文件</a>是编译后生成的可执行文件（通常扩展名为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.amx</code>）。<span style="font-style: italic;" class="mycode_i">术语 AMX 程序在某些上下文中可能指代 AMX 二进制文件。</span><br />
<br />
&lt;a name="term-amx-instance"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">AMX 实例</span>：每个加载的 AMX 二进制文件独立存在。加载后的程序称为 AMX 实例。<span style="font-style: italic;" class="mycode_i">术语 AMX 程序在某些上下文中可能指代 AMX 实例。</span><br />
<br />
&lt;a name="term-host-program"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">宿主程序</span>：嵌入 AMX 的程序称为宿主程序。以 <a href="http://sa-mp.com/" target="_blank" rel="noopener" class="mycode_url">San Andreas Multiplayer (SA-MP)</a> 或 <a href="https://open.mp/" target="_blank" rel="noopener" class="mycode_url">open.mp</a> 为例，服务器就是宿主程序。<br />
<br />
&lt;a name="term-extension-module"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">扩展模块</span>：扩展模块是一个独立的模块，通常动态链接到宿主程序，提供额外的原生函数。扩展模块通常被称为插件。<br />
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 基本概念</h2><br />
<ul class="mycode_list"><li>## &lt;a name="concept-cell"&gt;&lt;/a&gt; 单元格概念<br />
</li>
</ul>
<br />
Pawn 是一种无类型语言：没有数据类型。所有数据都作为原始二进制数据存储在一个单元格或一组单元格中。我们将使用<a href="https://en.wikipedia.org/wiki/Two%27s_complement" target="_blank" rel="noopener" class="mycode_url">有符号二进制补码表示法</a>来传达一个或多个单元格的内容，而不是显式地用二进制写出来。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new a = 5, b = 'A';</code></div></div><br />
上述代码创建了两个独立的单元格，分别由 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b</code> 标识。单元格 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a</code> 将包含值 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">5</code>，单元格 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b</code> 将包含值 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">65</code>（字符 'A' 的 <a href="https://en.wikipedia.org/wiki/ASCII" target="_blank" rel="noopener" class="mycode_url">ASCII</a> 等效值）。<br />
<br />
为了弥补数据类型的缺失，Pawn 提供了为单元格添加标签的能力。这些标签仅仅是编译时的辅助工具，不会直接&lt;sup&gt;<a href="http://#bc-cc-note-1" target="_blank" rel="noopener" class="mycode_url">1</a>&lt;/sup&gt;出现在 AMX 二进制文件中。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new Float:x = 5.0, Float:y = 10.0, Float:z;<br />
&nbsp;&nbsp;z = x + y;</code></div></div><br />
上述代码创建了三个带有标签的单元格，由 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">z</code> 标识。它们分别被初始化为值 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">5.0</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">10.0</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0.0</code>（默认初始化为二进制零，也是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0.0</code>），其二进制表示符合<a href="https://en.wikipedia.org/wiki/Floating-point_arithmetic#Internal_representation" target="_blank" rel="noopener" class="mycode_url">浮点数的正确表示</a>。编译器会记住遇到的变量的标签，并确保在变量被使用时生成正确的代码 &lt;sup&gt;<a href="http://#bc-cc-note-2" target="_blank" rel="noopener" class="mycode_url">2</a>&lt;/sup&gt;。在上述例子中，编译器在处理第二行时，会生成正确的代码来执行两个浮点数 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 的加法。请记住，整数加法和浮点数加法的执行方式不同。编译器使用与单元格关联的标签来确定应对操作数执行哪种加法操作。<br />
<br />
编译完成后，变量的标签信息会丢失。生成的 AMX 二进制文件将包含对 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 中存储的数据执行浮点数加法并将结果存储在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">z</code> 中的指令。<br />
在运行时，浮点数加法会在不考虑脚本中 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 的标签原本是否为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Float</code> 的情况下执行。<br />
<br />
&lt;a name="bc-cc-note-1"&gt;&lt;/a&gt; [[1]](#bc-cc-note-1) <span style="font-style: italic;" class="mycode_i">Pawn 语言提供了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">tagof</code> 运算符，它返回与标签关联的编译时 id，该 id 可以被存储。编译器还会在 AMX 二进制文件的标签表中创建一个公开可访问的标签列表。</span><br />
<br />
&lt;a name="bc-cc-note-2"&gt;&lt;/a&gt; [[2]](#bc-cc-note-2) <span style="font-style: italic;" class="mycode_i">Pawn 语言允许基于标签的运算符重载。编译器知道所有存在的运算符重载，并根据操作数的标签调用正确的重载。如果给定的操作数没有重载存在，编译器将默认使用无标签单元格的运算符（即整数算术）。</span><br />
<ul class="mycode_list"><li>## &lt;a name="concept-memory-addresses"&gt;&lt;/a&gt; 内存地址<br />
</li>
</ul>
AMX 遵循平坦的字节可寻址内存模型，即 AMX 内存可以被认为是一个线性的字节集合<br />
（<a href="https://en.wikipedia.org/wiki/Flat_memory_model" target="_blank" rel="noopener" class="mycode_url">平坦内存</a>），每个字节都有一个唯一的地址（<a href="https://en.wikipedia.org/wiki/Byte_addressing" target="_blank" rel="noopener" class="mycode_url">字节可寻址</a>）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new a[5];</code></div></div><br />
上述代码创建了一个由五个单元格组成的数组，由 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a</code> 标识。这些单元格连续存储，即一个接一个地存储。假设单元格大小为 4 字节，如果存储 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a[0]</code> 的位置地址是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1000</code>，那么存储 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a[1]</code> 的位置地址将是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1004</code>。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>data:&nbsp;&nbsp;&nbsp;&nbsp;a[0] | a[1] | a[2] | a[3] | a[4]<br />
&nbsp;&nbsp;address: 1000&nbsp;&nbsp; 1004&nbsp;&nbsp; 1008&nbsp;&nbsp; 1012&nbsp;&nbsp; 1016</code></div></div><br />
<span style="font-style: italic;" class="mycode_i">所需知识</span>：<a href="https://en.wikipedia.org/wiki/Base_address" target="_blank" rel="noopener" class="mycode_url">基地址</a>，<a href="https://en.wikipedia.org/wiki/Offset_(computer_science)" target="_blank" rel="noopener" class="mycode_url">相对地址</a><br />
<br />
<span style="font-style: italic;" class="mycode_i">所需知识</span>：<a href="https://en.wikipedia.org/wiki/Array_data_structure#Element_identifier_and_addressing_formulas" target="_blank" rel="noopener" class="mycode_url">数组数据结构，元素标识符和寻址公式</a><br />
<br />
<span style="font-style: italic;" class="mycode_i">另请参阅</span>：<a href="https://en.wikipedia.org/wiki/Endianness" target="_blank" rel="noopener" class="mycode_url">字节序</a><br />
<ul class="mycode_list"><li>## &lt;a name="concept-stack-heap"&gt;&lt;/a&gt; 栈和堆<br />
</li>
</ul>
每个 AMX 实例都包含一个<span style="font-style: italic;" class="mycode_i">内部</span> <a href="https://en.wikipedia.org/wiki/Call_stack" target="_blank" rel="noopener" class="mycode_url">程序栈</a>（也称为调用栈）和<a href="https://en.wikipedia.org/wiki/Memory_management#HEAP" target="_blank" rel="noopener" class="mycode_url">程序堆</a>。这些是 AMX 程序中的内存区域，专用于一组任务。<br />
<br />
栈负责：<ul class="mycode_list"><li>存储局部变量<br />
</li>
<li>存储函数参数<br />
</li>
<li>存储函数调用信息（例如参数个数）<br />
</li>
<li>提供临时存储<br />
</li>
</ul>
<br />
堆负责：<ul class="mycode_list"><li>为动态分配提供内存<br />
</li>
<li>存储作为引用/数组传递的默认参数<br />
</li>
<li>存储不是<a href="https://en.wikipedia.org/wiki/Value_(computer_science)#lrvalue" target="_blank" rel="noopener" class="mycode_url">左值</a>且作为可变参数传递的常量和表达式<br />
</li>
</ul>
<br />
###<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>f(argc, ...) { }<br />
&nbsp;&nbsp;main () <br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new a, b, c[100];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f(1, 25);<br />
&nbsp;&nbsp;}</code></div></div><br />
在上面的代码片段中，变量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">c</code> 和常量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1</code> 在栈上分配空间。常量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">25</code> 在堆上分配空间。引用和可变参数作为地址传递给函数。由于字面量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">25</code> 是一个常量且没有地址，因此在堆上分配了一个临时单元格来存储值 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">25</code>。该单元格的地址被传递给函数。<br />
<ul class="mycode_list"><li>## &lt;a name="concept-instructions"&gt;&lt;/a&gt; 指令<br />
</li>
</ul>
<br />
<a href="https://en.wikipedia.org/wiki/Instruction_set_architecture#Instructions" target="_blank" rel="noopener" class="mycode_url">指令</a>是离散的原子执行单元。大多数指令执行简单的任务，如基本算术。高级结构（如循环和条件语句）可以简化为一系列简单的指令。<br />
<br />
例如，将值压入调用栈然后弹出的指令可能是：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>push 100<br />
&nbsp;&nbsp;pop</code></div></div><br />
<a href="https://en.wikipedia.org/wiki/Assembly_language#Assembler" target="_blank" rel="noopener" class="mycode_url">汇编器</a>为上述代码片段生成的二进制代码可能是：<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">push-opcode | 100 | pop-opcode</code><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0x0013 0x0064 0x0014</code> 或者可能是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0000 0000 0000 0000 0000 0000 0001 0011 0000 0000 0000 0000 0000 0000 0110 0100 0000 0000 0000 0000 0000 0000 0001 0100</code><br />
<br />
是的，它只是一系列比特位，CPU（或者在我们这里是抽象机）知道如何解释这些比特位。当为物理硬件上的执行汇编时，这种表示被称为<a href="https://en.wikipedia.org/wiki/Machine_code" target="_blank" rel="noopener" class="mycode_url">机器码（或原生码）</a>。在为假想 CPU（如 AMX）上的执行汇编时，这种表示被称为 <a href="https://en.wikipedia.org/wiki/P-code_machine" target="_blank" rel="noopener" class="mycode_url">p-code</a>。<br />
<br />
<span style="font-style: italic;" class="mycode_i">另请参阅：</span> <a href="https://en.wikipedia.org/wiki/Bytecode" target="_blank" rel="noopener" class="mycode_url">字节码</a><br />
<ul class="mycode_list"><li>## &lt;a name="concept-spc-vna"&gt;&lt;/a&gt; 存储程序概念与冯·诺依曼体系结构<br />
</li>
</ul>
<br />
代码像数据一样驻留在内存中的想法被称为<a href="https://en.wikipedia.org/wiki/Stored-program_computer" target="_blank" rel="noopener" class="mycode_url">存储程序概念</a>。这也意味着内存中的每条指令都有一个地址，就像数据一样。代码和数据都驻留在<span style="font-weight: bold;" class="mycode_b">同一内存</span>中的想法是<a href="https://en.wikipedia.org/wiki/Von_Neumann_architecture" target="_blank" rel="noopener" class="mycode_url">冯·诺依曼体系结构</a>的一个原则。这也意味着所有代码和数据共享一个<a href="https://en.wikipedia.org/wiki/Address_space" target="_blank" rel="noopener" class="mycode_url">地址空间</a>。<br />
<br />
AMX 使用一个公共内存来存储代码和数据。<br />
<ul class="mycode_list"><li>## &lt;a name="concept-hdc"&gt;&lt;/a&gt; 头、数据段、代码段<br />
</li>
</ul>
<br />
可执行二进制文件及程序的内存结构根据其包含的内容被划分为逻辑上不同的区域。一个典型的二进制可执行文件至少包含一个头、一个代码段和一个数据段。头提供了程序本身的信息，例如<a href="https://en.wikipedia.org/wiki/Entry_point" target="_blank" rel="noopener" class="mycode_url">程序入口点</a>。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>HEADER<br />
&nbsp;&nbsp;-------<br />
&nbsp;&nbsp; CODE<br />
&nbsp;&nbsp;-------<br />
&nbsp;&nbsp; DATA</code></div></div><br />
代码段以二进制形式（机器码/p-code）存储代码，而数据段存储数据，如全局变量和静态局部变量。<br />
<br />
程序的内存结构通常不同。除了代码段和数据段外，它通常还包含程序栈和程序堆的区域。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>HEADER<br />
&nbsp;&nbsp;-------<br />
&nbsp;&nbsp; CODE<br />
&nbsp;&nbsp;-------<br />
&nbsp;&nbsp; DATA<br />
&nbsp;&nbsp;-------<br />
&nbsp;&nbsp; HEAP<br />
&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp; STACK</code></div></div><br />
AMX 二进制文件组织为三个部分：前缀、代码和数据（按顺序）。前缀部分包含有关 AMX 二进制文件的信息，例如代码和数据部分在二进制文件中的起始偏移量。代码部分存储 p-code，数据段存储全局变量和静态局部变量。<br />
<br />
堆栈区域是在 AMX 二进制文件加载到内存后，使用前缀部分中的信息创建的。<br />
<br />
<span style="font-style: italic;" class="mycode_i">另请参阅</span>：<a href="https://en.wikipedia.org/wiki/Memory_segmentation" target="_blank" rel="noopener" class="mycode_url">内存分段</a>，<a href="https://en.wikipedia.org/wiki/Data_segment" target="_blank" rel="noopener" class="mycode_url">数据段</a>，<a href="https://en.wikipedia.org/wiki/Code_segment" target="_blank" rel="noopener" class="mycode_url">代码段</a>，<a href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format" target="_blank" rel="noopener" class="mycode_url">ELF 格式</a><br />
<ul class="mycode_list"><li>## &lt;a name="concept-registers"&gt;&lt;/a&gt; 寄存器<br />
</li>
</ul>
了解处理器和内存位于不同的位置至关重要。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>|-------|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|------------------|<br />
&nbsp;&nbsp;|&nbsp;&nbsp;CPU&nbsp;&nbsp;|&nbsp;&nbsp;=============== |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MEMORY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp;|-------|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BUS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |------------------|</code></div></div><br />
内存存储数据，CPU 对数据进行操作。对于每次操作，处理器都必须将操作数从内存中取出并临时存储在 CPU 内部。这些临时存储位置被称为<a href="https://en.wikipedia.org/wiki/Processor_register" target="_blank" rel="noopener" class="mycode_url">寄存器</a>。这些寄存器可以容纳少量数据，范围在几个字节（通常为 2、4 或 8 字节）。<br />
<br />
假设处理器必须将两个变量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 相加，并将结果存储在变量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">z</code> 中。一个典型的处理器会执行以下操作：<br />
<ol type="1" class="mycode_list"><li>从内存中取出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 的值（即从 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 的地址读取）并将其存储在一个寄存器中，比如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R1</code><br />
</li>
<li>从内存中取出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 的值（即从 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 的地址读取）并将其存储在一个寄存器中，比如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R2</code><br />
</li>
<li>将 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R1</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R2</code> 的内容相加，并将结果存储在某寄存器中，比如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R3</code><br />
</li>
<li>将 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R3</code> 的内容存储到 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">z</code> 中（写入 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">z</code> 的地址）<br />
</li>
</ol>
<br />
处理器包含不同<a href="https://en.wikipedia.org/wiki/Processor_register#Categories_of_registers" target="_blank" rel="noopener" class="mycode_url">类型的寄存器</a>，用于不同目的。一些寄存器专用于特定任务，一些寄存器可用于任何目的。上例中使用的那类寄存器属于通用寄存器。<br />
<br />
AMX 的寄存器集包括以下寄存器：<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">主寄存器 (PRI)</span>：通用寄存器（常用作<a href="https://en.wikipedia.org/wiki/Accumulator_(computing)" target="_blank" rel="noopener" class="mycode_url">累加器寄存器</a>）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">辅助寄存器 (ALT)</span>：通用寄存器（常用作地址寄存器）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">代码段寄存器 (COD)</span>：内存中代码段起始的绝对地址<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">数据段寄存器 (DAT)</span>：内存中数据段起始的绝对地址<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">当前指令指针 (CIP)</span>：下一条<span style="font-style: italic;" class="mycode_i">要执行指令</span>的地址（相对于 COD 寄存器）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">栈顶寄存器 (STP)</span>：栈顶的地址（相对于 DAT 寄存器）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">栈指针寄存器 (STK)</span>：栈上当前位置的地址（相对于 DAT 寄存器）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">帧指针寄存器 (FRM)</span>：栈中当前函数帧起始的地址（相对于 DAT 寄存器）（<span style="font-style: italic;" class="mycode_i">稍后解释</span>）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">堆指针 (HEA)</span>：堆顶的地址（相对于 DAT 寄存器）<br />
</li>
</ul>
<br />
在编写汇编代码时，地址通常不是绝对的；它们是相对于某个段或帧指针寄存器的。全局变量和字符串的地址相对于 DAT 寄存器。函数、指令和标签的地址相对于 COD 寄存器。这意味着变量或指令的绝对地址分别是相对地址加上 DAT 或 COD 寄存器的值。局部变量的地址相对于帧指针寄存器。这有点复杂，稍后会解释。<br />
<br />
<span style="font-style: italic;" class="mycode_i">从现在开始，当我们讨论代码地址和数据地址时，除非明确说明，否则暗示这些地址分别相对于 COD 寄存器和 DAT 寄存器。</span><br />
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 文件与内存布局</h2><br />
所有非调试 AMX 二进制文件按如下方式组织：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>START OF BINARY FILE<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PREFIX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CODE<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DATA<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
END OF BINARY FILE</code></div></div><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">前缀</span>：包含程序的基本信息<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">代码</span>：包含代码<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">数据</span>：包含数据<br />
</li>
</ul>
<br />
<span style="font-style: italic;" class="mycode_i">注意：根据编译器的选项，前缀部分可能会被<a href="https://en.wikipedia.org/wiki/Data_structure_alignment" target="_blank" rel="noopener" class="mycode_url">填充</a>以使代码和数据部分对齐。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">注意：启用调试编译的脚本的二进制映像将在末尾附加符号调试信息。更多详情请参阅 Pawn 实现者指南。</span><br />
<br />
内存中的结构采用与二进制文件类似的结构，但额外包含一个栈和一个堆，这是使用前缀中的信息设置的。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>LOW ADDRESS (0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PREFIX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CODE<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DATA<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HEAP<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FREE SPACE<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;STACK<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
HIGH ADDRESS</code></div></div><br />
堆和栈共享一个公共的内存区域。它们从该区域的两端开始，并向相反方向增长。堆向高地址增长，栈向低地址增长。由于它们共享同一内存区域，因此可能会相互覆盖（当堆指针和栈指针碰撞时）。发生这种情况时，AMX 会中止并显示如下错误信息：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>Script[gamemodes/TEST.amx]: Run time error 3: "Stack/heap collision (insufficient stack size)"</code></div></div><br />
根据编译器掌握的信息，它会估算并间接地在 AMX 二进制文件的前缀部分设置堆栈大小。然而，程序员可以使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#pragma dynamic [estimated number of cells]</code> 指令提供自己对所需堆栈区域大小的估计。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">前缀部分的字段</h3><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">类型</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">大小</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">描述</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">size</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">内存映像的大小；不包括栈和堆</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">magic</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">2</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">指示格式和单元格大小</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">file version</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">1</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">格式版本</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">amx version</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">1</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">抽象机所需的最低版本</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">flags</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">2</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">是否存在符号调试信息、紧凑编码等。</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">defsize</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">2</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">表中记录的大小</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">cod</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">代码部分起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">dat</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">数据部分起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">hea</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">HEA 寄存器的初始值（标记数据段结束）</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">stp</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STP 寄存器的初始值（指示总内存需求）</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">cip</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CIP 寄存器的初始值（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main</code> 函数的地址；如果不存在则为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">-1</code>）</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">publics</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">公共函数表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">natives</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">原生函数表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">libraries</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">库表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">pubvars</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">公共变量表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">tags</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">标签表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">name table</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">名称表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">overlays</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">覆盖表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">publics</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">公共函数列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">natives</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">原生函数列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">libraries</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">库列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">pubvars</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">公共变量列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">tags</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">公共标签列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">overlays</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">覆盖列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">name table</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">符号名称列表</td>
 </tr>
</table>
<br />
<span style="font-style: italic;" class="mycode_i">注意：关于 magic、version 和 flags 字段中信息如何编码的详细信息，请参阅 Pawn 实现者指南。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">注意：前缀中的所有多字节字段都以<a href="https://en.wikipedia.org/wiki/Endianness" target="_blank" rel="noopener" class="mycode_url">小端格式</a>存储，无论 AMX 二进制文件是在哪个平台上生成或将在哪个平台上执行。</span><br />
<br />
可以看出，前缀由一个固定部分组成，后面跟着一系列表。除了名称表之外，表中的每条记录都由两个字段组成，如下所示：<br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">字段</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">大小</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">描述</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">变量</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">单元格大小</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">变量</span></td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">名称字符串偏移量</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4 字节</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">从前缀起始到名称表中字符串的偏移量</td>
 </tr>
</table>
<br />
表中每条记录（除了名称表）的大小由前缀中的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">defsize</code> 字段给出：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">defsize</code> = 4 + 单元格大小。<br />
<br />
表中的每条记录都被分配了一个索引号。每个表的第一个记录被分配索引 0，后续记录的索引号是前一个记录索引加 1。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">名称表</span>：<br />
除了名称表本身之外，其他表中的记录包含一个指向字符串的指针。这些字符串作为以空字符结尾的 C 字符串存储在名称表中。此表中记录的大小是其包含的字符串的大小。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">公共函数表</span>：<br />
为脚本中定义的每个公共函数创建一条记录。这些记录包含公共函数的地址（函数第一条指令的地址）和指向相应公共函数名称的偏移量。表中记录的索引就是相应公共函数的索引。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">原生函数表</span>：<br />
为脚本中调用的每个原生函数创建一条记录。记录的第一个字段由编译器在二进制文件中设置为 0，但宿主程序在加载二进制文件时会将该字段初始化为函数的地址（位于宿主程序的地址空间中）。第二个字段包含指向原生函数名称的偏移量。表中记录的索引就是相应原生函数的索引。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">库表</span>：<br />
Pawn 语言提供了一个 pragma 指令 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#pragma directive [library name]</code>，用于告知编译器调用的某些原生函数需要扩展模块。对于在脚本中调用了其原生函数的库，会在库表中创建一条记录。目的是告知宿主程序 AMX 程序依赖于一个扩展模块。记录的第一个字段供内部使用，在 AMX 二进制文件中设置为 0。另一个字段包含从前缀起始到名称表中库名称的偏移量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">公共变量表</span>：<br />
为脚本中声明的每个公共变量创建一条记录。该记录包含公共变量的地址和指向公共变量名称的偏移量。表中记录的索引就是公共变量的索引。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">标签表</span>：<br />
与 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">sleep</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">exit</code> 语句一起使用的标签以及与 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">tagof</code> 运算符一起使用的标签会被导出。为每个这样的标签创建一条记录。第一个字段包含标签 id 号，第二个字段存储指向标签名称的偏移量。<br />
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 指令集</h2><br />
<br />
&lt;a name="pawn-inline-assembly"&gt;&lt;/a&gt; Pawn 编译器接受的大部分 AMX 汇编指令可以用以下格式表示：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>mnemonic[.prefix][.register suffix] operand<br />
<br />
SHL.C.pri 3<br />
ZERO.alt<br />
ADD.C 100<br />
LIDX</code></div></div><br />
助记符给出了指令功能的提示。可选的前缀指示指令操作数的类型。可选的尾缀指示指令主要作用于哪个寄存器。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">前缀列表</span>：<ul class="mycode_list"><li>.C = 常量<br />
</li>
<li>.S = 栈<br />
</li>
<li>.I = 间接寻址<br />
</li>
<li>.B = 无 B 变体的变体&lt;sup&gt;\[需要更好的描述\]&lt;/sup&gt;<br />
</li>
<li>.ADR = 地址<br />
</li>
<li>.R = 重复<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">寄存器尾缀列表</span>：<ul class="mycode_list"><li>.pri = 主寄存器<br />
</li>
<li>.alt = 辅助寄存器<br />
</li>
</ul>
<br />
每条指令的二进制形式需要一个单元格来存储操作码，每个操作数还需要一个额外的单元格。绝大多数指令使用隐含寄存器作为操作数。这减少了所需显式操作数的数量，从而减小了代码段的大小并提高了性能。<br />
<br />
&lt;a name="instruction-table"&gt;&lt;/a&gt; <span style="font-style: italic;" class="mycode_i">阅读表格：</span><br />
<ol type="1" class="mycode_list"><li><span style="font-style: italic;" class="mycode_i">[address] 指的是存储在位置 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">DAT + address</code> 的值</span><br />
</li>
<li><span style="font-style: italic;" class="mycode_i">语义列中使用的运算符执行与 Pawn 中相同的操作</span><br />
</li>
</ol>
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">操作码</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">助记符</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">操作数</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">语义</th>
 </tr>
</table>
 <br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">1</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">LOAD.pri</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">address</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">PRI = [address]</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">2</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LOAD.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = [address]</td>
 </tr>
</table>
   <br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">3</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">LOAD.S.pri</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">offset</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">PRI = [FRM + offset]</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LOAD.S.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = [FRM + offset]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">5</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LREF.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [[address]]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">6</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LREF.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = [[address]]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">7</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LREF.S.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [[FRM + offset]]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">8</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LREF.S.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = [[FRM + offset]]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">9</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LOAD.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [PRI]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">10</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LODB.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = 'number' of bytes from [PRI] (read 1/2/4 bytes)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">11</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CONST.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">12</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CONST.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">13</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ADDR.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = FRM + offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">14</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ADDR.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = FRM + offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">15</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STOR.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[address] = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">16</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STOR.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[address] = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">17</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STOR.S.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[FRM + offset] = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">18</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STOR.S.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[FRM + offset] = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">19</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SREF.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[[address]] = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">20</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SREF.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[[address]] = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">21</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SREF.S.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[[FRM + offset]] = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">22</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SREF.S.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[[FRM + offset]] = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">23</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STOR.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[ALT] = PRI (full cell)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">24</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STRB.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number of bytes at [ALT] = PRI (store 1/2/4 bytes)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">25</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LIDX</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [ALT + (PRI x cell size)]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">26</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LIDX.B</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">shift</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [ALT + (PRI &lt;&lt; shift)]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">27</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">IDXADDR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT + (PRI x cell size) (calculate indexed address)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">28</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">IDXADDR.B</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">shift</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT + (PRI &lt;&lt; shift) (calculate indexed address)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">29</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALIGN.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">Little Endian: PRI ^= cell size - number</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">30</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALIGN.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">Little Endian: ALT ^= cell size - number</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">31</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LCTRL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">index</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = value contained in the selected register; 1=COD, 1=DAT, 2=HEA,3=STP, 4=STK, 5=FRM, 6=CIP</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">32</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SCTRL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">index</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">selected register = PRI; 2=HEA, 4=STK, 5=FRM, 6=CIP</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">33</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">MOVE.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">34</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">MOVE.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">35</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">XCHG</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">Exchange contents of PRI and ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">36</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">37</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">38</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.R</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">repeat (STK = STK - cell size, [STK] = PRI) 'number' times</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">39</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.C</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = value</td>
 </tr>
</table>
  <br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">40</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">PUSH</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">address</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">STK = STK - cell size, [STK] = [address]</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">41</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.S</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = [FRM + offset]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">42</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">POP.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [STK], STK = STK + cell size</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">43</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">POP.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = [STK], STK = STK + cell size</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">44</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STACK</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = STK, STK = STK + value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">45</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">HEAP</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = HEA, HEA = HEA + value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">46</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PROC</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = FRM, FRM = STK</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">47</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">RET</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">FRM = [STK], STK = STK + cell size, CIP = [STK], STK = STK + cell size</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">48</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">RETN</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">FRM = [STK], STK = STK + cell size, CIP = [STK], STK = STK + cell size, STK = STK + [STK] + cell size</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">49</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CALL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK − cell size, [STK] = CIP, CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">50</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CALL.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK − cell size, [STK] = CIP, CIP = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">51</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JUMP</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">53</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JZER</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI == 0 then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">54</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JNZ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI != 0 then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">55</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI == ALT then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">56</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JNEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI != ALT then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">57</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JLESS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &lt; ALT (unsigned) then CIP = offset</td>
 </tr>
</table>
 <br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">58</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">JLEQ</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">offset</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">if PRI &lt;= ALT (unsigned)  then CIP = offset</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">59</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JGRTR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &gt; ALT (unsigned) then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">60</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JGEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &gt;= ALT (unsigned) then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">61</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JSLESS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &lt; ALT (signed) then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">62</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JSLEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &lt;= ALT (signed) then CIP = offset</td>
 </tr>
</table>
 <br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">63</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">JSGRTR</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">offset</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">if PRI &gt; ALT (signed) then CIP = offset</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">64</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JSGEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &gt;= ALT (signed) then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">65</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt;&lt; ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">66</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt;&gt; ALT (without sign extension)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">67</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SSHR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt;&gt; ALT (with sign extension)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">68</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHL.C.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt;&lt; value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">69</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHL.C.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = ALT &lt;&lt; value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">70</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHR.C.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt;&gt; value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">71</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHR.C.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = ALT &gt;&gt; value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">72</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SMUL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI * ALT (signed multiply)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">73</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SDIV</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI / ALT (signed divide), ALT = PRI mod ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">74</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SDIV.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT / PRI (signed divide), ALT = ALT mod PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">75</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">UMUL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI * ALT (unsigned multiply)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">76</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">UDIV</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI / ALT (unsigned divide), ALT = PRI mod ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">77</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">UDIV.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT / PRI (unsigned divide), ALT = ALT mod PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">78</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ADD</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI + ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">79</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SUB</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI - ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">80</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SUB.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT - PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">81</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">AND</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &amp; ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">82</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">OR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &#124; ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">83</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">XOR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI ^ ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">84</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">NOT</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = !PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">85</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">NEG</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = -PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">86</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INVERT</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ~PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">87</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ADD.C</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI + value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">88</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SMUL.C</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI * value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">89</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ZERO.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">90</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ZERO.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">91</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ZERO</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[address] = 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">92</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ZERO.S</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[FRM + offset] = 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">93</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SIGN.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">sign extend the byte in PRI to a cell</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">94</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SIGN.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">sign extend the byte in ALT to a cell</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">95</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">EQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI == ALT ? 1 : 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">96</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">NEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI != ALT ? 1 : 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">97</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LESS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt; ALT ? 1 : 0 (unsigned)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">98</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt;= ALT ? 1 : 0 (unsigned)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">99</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">GRTR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt; ALT ? 1 : 0 (unsigned)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">100</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">GEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt;= ALT ? 1 : 0 (unsigned)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">101</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SLESS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt; ALT ? 1 : 0 (signed)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">102</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SLEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt;= ALT ? 1 : 0 (signed)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">103</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SGRTR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt; ALT ? 1 : 0 (signed)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">104</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SGEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt;= ALT ? 1 : 0 (signed)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">105</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">EQ.C.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI == value ? 1 : 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">106</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">EQ.C.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT == value ? 1 : 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">107</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INC.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI + 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">108</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INC.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = ALT + 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">109</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INC</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[address] = [address] + 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">110</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INC.S</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[FRM + offset] = [FRM + offset] + 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">111</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INC.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[PRI] = [PRI] + 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">112</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">DEC.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI - 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">113</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">DEC.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = ALT - 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">114</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">DEC</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[address] = [address] - 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">115</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">DEC.S</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[FRM + offset] = [FRM + offset] - 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">116</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">DEC.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[PRI] = [PRI] - 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">117</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">MOVS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">copy 'number' bytes of non-overlapping memory from [PRI] to [ALT]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">118</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CMPS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">compare 'number' bytes of non-overlapping memory at [PRI] with [ALT]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">119</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">FILL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">fill 'number' bytes of memory from [ALT] with value in PRI (number must be multiple of cell size)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">120</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">HALT</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">0</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">abort execution (exit value in PRI)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">121</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">BOUNDS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">abort execution if PRI &gt; value or if PRI &lt; 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">122</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SYSREQ.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">call system service, service number in PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">123</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SYSREQ.C</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">call system service</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">128</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JUMP.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CIP = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">129</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SWITCH</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">compare PRI to the values in the case table (whose address is passed in the 'offset' argument) and jump to the associated address in the matching record</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">130</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CASETBL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">...</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">a variable number of case records follows this opcode, where each record takes two cells</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">131</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SWAP.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[STK] = PRI, PRI = [STK]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">132</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SWAP.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[STK] = ALT, ALT = [STK]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">133</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.ADR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = FRM + offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">134</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">NOP</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">no operation</td>
 </tr>
</table>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 加载/存储指令</h4><br />
<br />
当使用全局变量作为操作数时，编译器会替换该变量的地址。下面代码中的第一条加载指令，如果 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">some_global</code> 的地址是 1288，则实际上变成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#emit LOAD.pri 1288</code>。请注意，编译器替换的地址是从数据段起始的偏移量；因此，该地址是相对于 DAT 寄存器的。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new some_global = 10, another_global = 25;<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LOAD.pri some_global // 将 'some_global' 的值加载到主寄存器<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LOAD.alt another_global&nbsp;&nbsp;// 将 'another_global' 的值加载到辅助寄存器<br />
}</code></div></div><br />
当使用局部变量时，编译器会替换从函数帧起始的偏移量。<span style="font-style: italic;" class="mycode_i">(稍后解释)</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;static s_local = 20; // 静态局部变量存储在数据段中<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;new some_local = 10, another_local = 25; // 局部变量存储在栈中<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LOAD.S.pri some_local // 将 'some_local' 的值加载到主寄存器<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LOAD.S.alt another_local&nbsp;&nbsp;// 将 'another_local' 的值加载到辅助寄存器<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LOAD.pri s_local // 注意静态局部变量的行为类似于全局变量<br />
}</code></div></div><br />
由于编译器会为全局变量替换地址，因此可以使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">CONST.pri/CONST.alt</code> 来获取这些变量的地址。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new some_global;<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 10 // 将 10 放入主寄存器<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt 50 // 将 50 放入辅助寄存器<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri some_global // 将 'some_global' 的地址存储在主寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt some_global // 将 'some_global' 的地址存储在辅助寄存器中<br />
}</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new some_global;<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new some_local;<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit ZERO.pri // 将零存储在主寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit STOR.pri some_global // 将主寄存器中存储的值（本例中为零）设置给 'some_global'<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt 125<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit STOR.S.alt some_local // 将辅助寄存器中存储的值（125）设置给 'some_local'<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 索引指令</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new global_arr[10];<br />
main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt global_arr // 将 'global_arr' 的地址（'global_arr' 第一个元素的地址）加载到辅助寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 2 // 设置我们感兴趣的 'global_arr' 元素的索引<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LIDX // 现在主寄存器中存储的是 'global_arr[2]` 处存储的值<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt global_arr // 将 'global_arr' 的地址（第一个元素的地址）加载到辅助寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 2 // 设置我们感兴趣的 'global_arr' 元素的索引<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit IDXADDR // 现在主寄存器中存储的是 'global_arr[2]` 的地址<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 算术指令</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 4<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt 5<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit SMUL // 现在主寄存器中是 20（SMUL 执行有符号乘法；UMUL 执行无符号乘法）<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit ADD // 将 5 加到 20（由于上一条指令，主寄存器中存储的是 20）<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit ADD.C 10 // 将 10 加到主寄存器；现在主寄存器中是 35<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit SUB.alt // 用 5 减去 35；现在主寄存器中是 -30<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit SMUL.C 2 // -30 乘以 2；得到 -60<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 逻辑指令</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 5 // .. 0000 0101<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt 3 // ... 0000 0011<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit AND // 主寄存器现在包含 ... 0000 0001<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit XOR // 主寄存器现在包含 ... 0000 0110<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit INVERT // 对主寄存器中存储的值取反码<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit NEG // 对主寄存器中存储的值取补码（本质上是取负）<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">关系指令</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 5<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt 8<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit EQ // 如果 5 == 8，则将主寄存器设置为 1，否则为 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LESS // 如果 0 &lt; 8，则将主寄存器设置为 1，否则为 0<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 栈操作指令</h4><br />
<br />
局部变量存储在栈上。详细说明将在后续章节中提供，但现在我们假设使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">CONST.pri some_local</code> 会得到某个偏移量，该偏移量加上帧寄存器中存储的基地址即得数据地址。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new some_local = 25;<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit ADDR.alt some_local // 计算 'some_local' 的地址<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 100<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit STOR.I // 将 100 存储到 'some_local'<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 100<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit STOR.S.pri some_local // 实现上述代码功能的更好方法<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri some_local // 神秘地等价于 CONST.pri -4（稍后解释）<br />
}</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit PUSH.C 100 // 将值 100 压入调用栈<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit POP.pri // 从栈中弹出一个值并将结果存储在主寄存器中<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit PUSH.pri // 推送主寄存器的值<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit PUSH.alt // 推送辅助寄存器的值<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit POP.pri<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit POP.alt // 最后 4 条指令有效地交换了主寄存器和辅助寄存器的内容<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit XCHG // 交换主寄存器和辅助寄存器内容的更好方法<br />
}</code></div></div><br />
局部数组位于栈上。因此，在使用索引指令之前，必须使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">ADDR.alt/ADDR.pri</code> 来获取完整的地址。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new local_array[10];<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit ADDR.alt local_array // 加载存储在 'local_array' 中的值，即数组的地址<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 5<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LIDX // 有效地将 'local_array[5]' 的值存储在主寄存器中<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 堆指令</h4><br />
堆指针（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">HEA</code> 寄存器）指向堆的顶部。将堆指针向前移动 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 字节，我们就能有效地<br />
在堆上预留 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 字节。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit HEAP 16 // 为四个单元格预留空间（假设单元格为 4 字节）<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 注意 HEAP 指令也将辅助寄存器设置为我们预留内存的起始地址<br />
&nbsp;&nbsp;&nbsp;&nbsp; // ALT = HEA, HEA += 16<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit CONST.pri 50<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit STOR.I // 有效地将值 50 存储在我们预留的堆区域的第一个单元格中<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit HEAP -16 // 归还预留的内存<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 控制寄存器操作指令</h4><br />
可以使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">LCTRL</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SCTRL</code> 指令直接读取和修改专用寄存器的内容。<br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">助记符</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">操作数</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">描述</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">LCTRL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">index</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = 所选寄存器中包含的值；0=COD, 1=DAT, 2=HEA, 3=STP, 4=STK, 5=FRM, 6=CIP</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">SCTRL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">index</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">所选寄存器 = PRI；2=HEA, 4=STK, 5=FRM, 6=CIP</td>
 </tr>
</table>
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp; new cod, dat;<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit LCTRL 0 // 将 COD 段寄存器的值存储在主寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit STOR.S.pri cod<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit LCTRL 1 // 将 DAT 段寄存器的值存储在主寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit STOR.S.pri dat<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; printf("%d %d", cod, dat);<br />
}</code></div></div><br />
当函数名用作操作数时，编译器会用函数的地址替换它。替换的地址是相对于 COD 寄存器的。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>f()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print("f() was called.");<br />
}<br />
<br />
main ()<br />
{<br />
&nbsp;&nbsp; #emit PUSH.C 0 // 参数占用的字节数（稍后解释）<br />
&nbsp;&nbsp; #emit LCTRL 6 // 获取 CIP 的值，即下一条指令（本例中的 ADD.C）的地址<br />
&nbsp;&nbsp; #emit ADD.C 28 // 计算 'f' 之后要执行的指令的地址（注意每个操作码和操作数都需要一个单元格）<br />
&nbsp;&nbsp; #emit PUSH.pri // 推送返回地址，以便 'f' 知道返回到哪里（稍后解释）<br />
&nbsp;&nbsp; #emit CONST.pri f // 将函数 'f' 的地址存储在 pri 中<br />
&nbsp;&nbsp; #emit SCTRL 6 // 将当前指令指针设置为存储在主寄存器中的值<br />
<br />
&nbsp;&nbsp; // 函数 'f' 执行<br />
&nbsp;&nbsp; // 函数 'f' 返回后，下一条指令（本例中的 NOP）将开始执行<br />
<br />
&nbsp;&nbsp; #emit NOP // 不执行任何操作的指令<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 控制流指令</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main()<br />
{&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit JUMP check // 跳转到 check 标签<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;not_equal:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("1 is not equal to 2");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;equal:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("1 is equal to 2");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;check:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #emit CONST.pri 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #emit CONST.alt 2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #emit JEQ equal // 如果主寄存器的值等于辅助寄存器的值，则跳转到 'equal'<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #emit JUMP not_equal // 如果执行到这里，意味着两个寄存器的值不相等；因此跳转到 'not_equal'<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> Switch case 指令</h4><br />
<br />
switch-case 块使用<a href="https://en.wikipedia.org/wiki/Branch_table" target="_blank" rel="noopener" class="mycode_url">分支表</a>实现。分支表仅仅是由 case 值及其对应的跳转地址组成的元组列表。对于给定的 case 值，AMX 会搜索分支表并跳转到相应的跳转地址。分支表中的记录按 case 值的升序排列。这允许 AMX 对分支表执行二分搜索，但它也可能执行线性搜索。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SWITCH</code> 指令标记 switch-case 块的开始。它接受一个指向分支表（也位于代码段中）的偏移量作为操作数。分支表正式以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">CASETBL</code> 操作码（仅作为标记，功能上未使用）开始，后跟一系列 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">CASE</code> 记录，每条记录占用两个参数。第一条 case 记录的参数具有特殊含义：第一个参数是分支表中的 case 数量，第二个参数是默认 case 的偏移量。如果没有提供默认 case，则第二个参数包含 switch-case 块之后指令的偏移量。其余的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">CASE</code> 记录包含 case 值及其对应的跳转地址。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>switch(expression)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;case 2: {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;case 4: {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;case 3: {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;case 7: {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;case 5: {}<br />
}</code></div></div><br />
编译器会添加指令来计算给定的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">expression</code>，其结果存储在主寄存器中。紧接着是一条 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SWITCH</code> 指令，它使 AMX 搜索分支表，查找与主寄存器中存储的值匹配的 case 值。如果找到匹配项，则执行跳转到匹配记录指向的地址；否则，跳转到默认地址。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>; 编译器通过在汇编输出中使用标签而不是实际的偏移量/地址，使阅读更容易<br />
; 每个标签都以前缀 "l." 开头<br />
<br />
switch 0 ; 注意这里的零是一个标签<br />
<br />
l.2 ; 标签 2<br />
&nbsp;&nbsp; jump 1 ; 跳转到标签 1<br />
l.3<br />
&nbsp;&nbsp; jump 1<br />
l.4<br />
&nbsp;&nbsp; jump 1<br />
l.5<br />
&nbsp;&nbsp; jump 1<br />
l.6<br />
&nbsp;&nbsp; jump 1<br />
<br />
l.0<br />
&nbsp;&nbsp;casetbl <br />
&nbsp;&nbsp;case 5 1 ; 记录数量，默认跳转地址（本例中为标签 1）<br />
&nbsp;&nbsp; case 2 2 ; 真正的第一条记录<br />
&nbsp;&nbsp; case 3 4 ; case 值: 3, 跳转标签: 4<br />
&nbsp;&nbsp; case 4 3 ; 编译器在实际二进制文件中会用正确的地址替换标签<br />
&nbsp;&nbsp; case 5 6 ; <br />
&nbsp;&nbsp; case 7 5 ; 最后一条记录<br />
<br />
 l.1<br />
&nbsp;&nbsp; ; 其余代码</code></div></div>]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> AMX 汇编</h2><br />
<br />
AMX 版本: 3.0<br />
<br />
AMX 文件版本: 8<br />
<br />
本文档是关于抽象机执行器（Abstract Machine eXecutor）汇编的<span style="font-style: italic;" class="mycode_i">非官方</span>文档。本文档的内容可能不准确且可能随时更改。<a href="http://#terminology" target="_blank" rel="noopener" class="mycode_url">术语部分</a>中定义的部分术语在官方手册中并未出现。它们是为了帮助读者理解而引入的辅助术语。<br />
<br />
本文档的目标读者是首次接触汇编语言的程序员。他们应根据需要点击超链接以收集背景信息。高级用户可跳过部分章节或将本文档用作快速参考指南。<br />
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 目录</h2><ul class="mycode_list"><li><a href="http://#prerequisites" target="_blank" rel="noopener" class="mycode_url">先决条件</a><br />
</li>
<li><a href="http://#terminology" target="_blank" rel="noopener" class="mycode_url">术语</a><br />
</li>
<li><a href="http://#term-amx" target="_blank" rel="noopener" class="mycode_url">抽象机执行器 (AMX)</a><br />
</li>
<li><a href="http://#term-amx-assembly" target="_blank" rel="noopener" class="mycode_url">AMX 汇编</a><br />
</li>
<li><a href="http://#term-amx-binary" target="_blank" rel="noopener" class="mycode_url">AMX 二进制</a><br />
</li>
<li><a href="http://#term-amx-instance" target="_blank" rel="noopener" class="mycode_url">AMX 实例</a><br />
</li>
<li><a href="http://#term-host-program" target="_blank" rel="noopener" class="mycode_url">宿主程序</a><br />
</li>
<li><a href="http://#term-extension-module" target="_blank" rel="noopener" class="mycode_url">扩展模块</a><br />
</li>
<li><a href="http://#basic-concepts" target="_blank" rel="noopener" class="mycode_url">基本概念</a><br />
</li>
<li><a href="http://#concept-cell" target="_blank" rel="noopener" class="mycode_url">单元格概念</a><br />
</li>
<li><a href="http://#concept-memory-addresses" target="_blank" rel="noopener" class="mycode_url">内存地址</a><br />
</li>
<li><a href="http://#concept-stack-heap" target="_blank" rel="noopener" class="mycode_url">栈与堆</a><br />
</li>
<li><a href="http://#concept-instructions" target="_blank" rel="noopener" class="mycode_url">指令</a><br />
</li>
<li><a href="http://#concept-spc-vna" target="_blank" rel="noopener" class="mycode_url">存储程序概念与冯·诺依曼体系结构</a><br />
</li>
<li><a href="http://#concept-hdc" target="_blank" rel="noopener" class="mycode_url">头、数据段、代码段</a><br />
</li>
<li><a href="http://#concept-registers" target="_blank" rel="noopener" class="mycode_url">寄存器</a><br />
</li>
<li><a href="http://#file-memory-layout" target="_blank" rel="noopener" class="mycode_url">文件与内存布局</a><br />
</li>
<li><a href="http://#instruction-set" target="_blank" rel="noopener" class="mycode_url">指令集</a><br />
</li>
<li><a href="http://#pawn-inline-assembly" target="_blank" rel="noopener" class="mycode_url">Pawn 内联汇编语法</a><br />
</li>
<li><a href="http://#instruction-table" target="_blank" rel="noopener" class="mycode_url">指令表</a><br />
</li>
<li><a href="http://#loadstore-instructions" target="_blank" rel="noopener" class="mycode_url">加载/存储指令</a><br />
</li>
<li><a href="http://#indexing-instructions" target="_blank" rel="noopener" class="mycode_url">索引指令</a><br />
</li>
<li><a href="http://#arithmetic-instructions" target="_blank" rel="noopener" class="mycode_url">算术指令</a><br />
</li>
<li><a href="http://#logical-instructions" target="_blank" rel="noopener" class="mycode_url">逻辑指令</a><br />
</li>
<li><a href="http://#relational-instructions" target="_blank" rel="noopener" class="mycode_url">关系指令</a><br />
</li>
<li><a href="http://#stack-manipulation-instructions" target="_blank" rel="noopener" class="mycode_url">栈操作指令</a><br />
</li>
<li><a href="http://#heap-instructions" target="_blank" rel="noopener" class="mycode_url">堆指令</a><br />
</li>
<li><a href="http://#control-register-manipulation-instructions" target="_blank" rel="noopener" class="mycode_url">控制寄存器操作指令</a><br />
</li>
<li><a href="http://#control-flow-instructions" target="_blank" rel="noopener" class="mycode_url">控制流指令</a><br />
</li>
<li><a href="http://#switch-case-instructions" target="_blank" rel="noopener" class="mycode_url">Switch-case 指令</a><br />
</li>
<li><a href="http://#call-stack-and-call-convention" target="_blank" rel="noopener" class="mycode_url">调用栈与调用约定</a><br />
</li>
<li><a href="http://#local-variables-and-function-frame" target="_blank" rel="noopener" class="mycode_url">局部变量与函数帧</a><br />
</li>
<li><a href="http://#call-convention" target="_blank" rel="noopener" class="mycode_url">调用约定</a><br />
</li>
<li><a href="http://#methods-passing-arguments" target="_blank" rel="noopener" class="mycode_url">参数传递方法</a><br />
</li>
<li><a href="http://#system-requests" target="_blank" rel="noopener" class="mycode_url">系统请求</a><br />
</li>
<li><a href="http://#multi-dimensional-arrays" target="_blank" rel="noopener" class="mycode_url">多维数组</a><br />
</li>
</ul>
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 先决条件</h2><ul class="mycode_list"><li>Pawn 脚本语言<br />
</li>
<li><a href="https://en.wikipedia.org/wiki/Binary_number" target="_blank" rel="noopener" class="mycode_url">二进制数制</a><br />
</li>
<li><a href="https://en.wikipedia.org/wiki/Hexadecimal" target="_blank" rel="noopener" class="mycode_url">十六进制数制</a><br />
</li>
<li>内存地址（理解<a href="https://en.wikipedia.org/wiki/Pointer_(computer_programming)" target="_blank" rel="noopener" class="mycode_url">指针</a>更佳）<br />
</li>
<li><a href="https://en.wikipedia.org/wiki/Stack_(abstract_data_type)" target="_blank" rel="noopener" class="mycode_url">栈（作为抽象数据类型）</a><br />
</li>
</ul>
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 术语</h2><br />
&lt;a name="term-amx"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">抽象机执行器 (AMX)</span>：AMX 是我们感兴趣的<a href="https://en.wikipedia.org/wiki/Abstract_machine" target="_blank" rel="noopener" class="mycode_url">抽象机</a>（或<a href="https://en.wikipedia.org/wiki/Virtual_machine" target="_blank" rel="noopener" class="mycode_url">虚拟机</a>）。<br />
<br />
&lt;a name="term-amx-assembly"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">AMX 汇编</span>：AMX 的<a href="https://en.wikipedia.org/wiki/Assembly_language" target="_blank" rel="noopener" class="mycode_url">汇编语言</a>。<br />
<br />
&lt;a name="term-amx-binary"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">AMX 二进制</span>：AMX <a href="https://en.wikipedia.org/wiki/Executable" target="_blank" rel="noopener" class="mycode_url">二进制文件</a>是编译后生成的可执行文件（通常扩展名为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.amx</code>）。<span style="font-style: italic;" class="mycode_i">术语 AMX 程序在某些上下文中可能指代 AMX 二进制文件。</span><br />
<br />
&lt;a name="term-amx-instance"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">AMX 实例</span>：每个加载的 AMX 二进制文件独立存在。加载后的程序称为 AMX 实例。<span style="font-style: italic;" class="mycode_i">术语 AMX 程序在某些上下文中可能指代 AMX 实例。</span><br />
<br />
&lt;a name="term-host-program"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">宿主程序</span>：嵌入 AMX 的程序称为宿主程序。以 <a href="http://sa-mp.com/" target="_blank" rel="noopener" class="mycode_url">San Andreas Multiplayer (SA-MP)</a> 或 <a href="https://open.mp/" target="_blank" rel="noopener" class="mycode_url">open.mp</a> 为例，服务器就是宿主程序。<br />
<br />
&lt;a name="term-extension-module"&gt;&lt;/a&gt;<span style="font-weight: bold;" class="mycode_b">扩展模块</span>：扩展模块是一个独立的模块，通常动态链接到宿主程序，提供额外的原生函数。扩展模块通常被称为插件。<br />
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 基本概念</h2><br />
<ul class="mycode_list"><li>## &lt;a name="concept-cell"&gt;&lt;/a&gt; 单元格概念<br />
</li>
</ul>
<br />
Pawn 是一种无类型语言：没有数据类型。所有数据都作为原始二进制数据存储在一个单元格或一组单元格中。我们将使用<a href="https://en.wikipedia.org/wiki/Two%27s_complement" target="_blank" rel="noopener" class="mycode_url">有符号二进制补码表示法</a>来传达一个或多个单元格的内容，而不是显式地用二进制写出来。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new a = 5, b = 'A';</code></div></div><br />
上述代码创建了两个独立的单元格，分别由 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b</code> 标识。单元格 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a</code> 将包含值 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">5</code>，单元格 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b</code> 将包含值 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">65</code>（字符 'A' 的 <a href="https://en.wikipedia.org/wiki/ASCII" target="_blank" rel="noopener" class="mycode_url">ASCII</a> 等效值）。<br />
<br />
为了弥补数据类型的缺失，Pawn 提供了为单元格添加标签的能力。这些标签仅仅是编译时的辅助工具，不会直接&lt;sup&gt;<a href="http://#bc-cc-note-1" target="_blank" rel="noopener" class="mycode_url">1</a>&lt;/sup&gt;出现在 AMX 二进制文件中。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new Float:x = 5.0, Float:y = 10.0, Float:z;<br />
&nbsp;&nbsp;z = x + y;</code></div></div><br />
上述代码创建了三个带有标签的单元格，由 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">z</code> 标识。它们分别被初始化为值 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">5.0</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">10.0</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0.0</code>（默认初始化为二进制零，也是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0.0</code>），其二进制表示符合<a href="https://en.wikipedia.org/wiki/Floating-point_arithmetic#Internal_representation" target="_blank" rel="noopener" class="mycode_url">浮点数的正确表示</a>。编译器会记住遇到的变量的标签，并确保在变量被使用时生成正确的代码 &lt;sup&gt;<a href="http://#bc-cc-note-2" target="_blank" rel="noopener" class="mycode_url">2</a>&lt;/sup&gt;。在上述例子中，编译器在处理第二行时，会生成正确的代码来执行两个浮点数 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 的加法。请记住，整数加法和浮点数加法的执行方式不同。编译器使用与单元格关联的标签来确定应对操作数执行哪种加法操作。<br />
<br />
编译完成后，变量的标签信息会丢失。生成的 AMX 二进制文件将包含对 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 中存储的数据执行浮点数加法并将结果存储在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">z</code> 中的指令。<br />
在运行时，浮点数加法会在不考虑脚本中 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 的标签原本是否为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Float</code> 的情况下执行。<br />
<br />
&lt;a name="bc-cc-note-1"&gt;&lt;/a&gt; [[1]](#bc-cc-note-1) <span style="font-style: italic;" class="mycode_i">Pawn 语言提供了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">tagof</code> 运算符，它返回与标签关联的编译时 id，该 id 可以被存储。编译器还会在 AMX 二进制文件的标签表中创建一个公开可访问的标签列表。</span><br />
<br />
&lt;a name="bc-cc-note-2"&gt;&lt;/a&gt; [[2]](#bc-cc-note-2) <span style="font-style: italic;" class="mycode_i">Pawn 语言允许基于标签的运算符重载。编译器知道所有存在的运算符重载，并根据操作数的标签调用正确的重载。如果给定的操作数没有重载存在，编译器将默认使用无标签单元格的运算符（即整数算术）。</span><br />
<ul class="mycode_list"><li>## &lt;a name="concept-memory-addresses"&gt;&lt;/a&gt; 内存地址<br />
</li>
</ul>
AMX 遵循平坦的字节可寻址内存模型，即 AMX 内存可以被认为是一个线性的字节集合<br />
（<a href="https://en.wikipedia.org/wiki/Flat_memory_model" target="_blank" rel="noopener" class="mycode_url">平坦内存</a>），每个字节都有一个唯一的地址（<a href="https://en.wikipedia.org/wiki/Byte_addressing" target="_blank" rel="noopener" class="mycode_url">字节可寻址</a>）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new a[5];</code></div></div><br />
上述代码创建了一个由五个单元格组成的数组，由 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a</code> 标识。这些单元格连续存储，即一个接一个地存储。假设单元格大小为 4 字节，如果存储 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a[0]</code> 的位置地址是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1000</code>，那么存储 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a[1]</code> 的位置地址将是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1004</code>。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>data:&nbsp;&nbsp;&nbsp;&nbsp;a[0] | a[1] | a[2] | a[3] | a[4]<br />
&nbsp;&nbsp;address: 1000&nbsp;&nbsp; 1004&nbsp;&nbsp; 1008&nbsp;&nbsp; 1012&nbsp;&nbsp; 1016</code></div></div><br />
<span style="font-style: italic;" class="mycode_i">所需知识</span>：<a href="https://en.wikipedia.org/wiki/Base_address" target="_blank" rel="noopener" class="mycode_url">基地址</a>，<a href="https://en.wikipedia.org/wiki/Offset_(computer_science)" target="_blank" rel="noopener" class="mycode_url">相对地址</a><br />
<br />
<span style="font-style: italic;" class="mycode_i">所需知识</span>：<a href="https://en.wikipedia.org/wiki/Array_data_structure#Element_identifier_and_addressing_formulas" target="_blank" rel="noopener" class="mycode_url">数组数据结构，元素标识符和寻址公式</a><br />
<br />
<span style="font-style: italic;" class="mycode_i">另请参阅</span>：<a href="https://en.wikipedia.org/wiki/Endianness" target="_blank" rel="noopener" class="mycode_url">字节序</a><br />
<ul class="mycode_list"><li>## &lt;a name="concept-stack-heap"&gt;&lt;/a&gt; 栈和堆<br />
</li>
</ul>
每个 AMX 实例都包含一个<span style="font-style: italic;" class="mycode_i">内部</span> <a href="https://en.wikipedia.org/wiki/Call_stack" target="_blank" rel="noopener" class="mycode_url">程序栈</a>（也称为调用栈）和<a href="https://en.wikipedia.org/wiki/Memory_management#HEAP" target="_blank" rel="noopener" class="mycode_url">程序堆</a>。这些是 AMX 程序中的内存区域，专用于一组任务。<br />
<br />
栈负责：<ul class="mycode_list"><li>存储局部变量<br />
</li>
<li>存储函数参数<br />
</li>
<li>存储函数调用信息（例如参数个数）<br />
</li>
<li>提供临时存储<br />
</li>
</ul>
<br />
堆负责：<ul class="mycode_list"><li>为动态分配提供内存<br />
</li>
<li>存储作为引用/数组传递的默认参数<br />
</li>
<li>存储不是<a href="https://en.wikipedia.org/wiki/Value_(computer_science)#lrvalue" target="_blank" rel="noopener" class="mycode_url">左值</a>且作为可变参数传递的常量和表达式<br />
</li>
</ul>
<br />
###<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>f(argc, ...) { }<br />
&nbsp;&nbsp;main () <br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new a, b, c[100];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f(1, 25);<br />
&nbsp;&nbsp;}</code></div></div><br />
在上面的代码片段中，变量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">c</code> 和常量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1</code> 在栈上分配空间。常量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">25</code> 在堆上分配空间。引用和可变参数作为地址传递给函数。由于字面量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">25</code> 是一个常量且没有地址，因此在堆上分配了一个临时单元格来存储值 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">25</code>。该单元格的地址被传递给函数。<br />
<ul class="mycode_list"><li>## &lt;a name="concept-instructions"&gt;&lt;/a&gt; 指令<br />
</li>
</ul>
<br />
<a href="https://en.wikipedia.org/wiki/Instruction_set_architecture#Instructions" target="_blank" rel="noopener" class="mycode_url">指令</a>是离散的原子执行单元。大多数指令执行简单的任务，如基本算术。高级结构（如循环和条件语句）可以简化为一系列简单的指令。<br />
<br />
例如，将值压入调用栈然后弹出的指令可能是：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>push 100<br />
&nbsp;&nbsp;pop</code></div></div><br />
<a href="https://en.wikipedia.org/wiki/Assembly_language#Assembler" target="_blank" rel="noopener" class="mycode_url">汇编器</a>为上述代码片段生成的二进制代码可能是：<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">push-opcode | 100 | pop-opcode</code><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0x0013 0x0064 0x0014</code> 或者可能是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0000 0000 0000 0000 0000 0000 0001 0011 0000 0000 0000 0000 0000 0000 0110 0100 0000 0000 0000 0000 0000 0000 0001 0100</code><br />
<br />
是的，它只是一系列比特位，CPU（或者在我们这里是抽象机）知道如何解释这些比特位。当为物理硬件上的执行汇编时，这种表示被称为<a href="https://en.wikipedia.org/wiki/Machine_code" target="_blank" rel="noopener" class="mycode_url">机器码（或原生码）</a>。在为假想 CPU（如 AMX）上的执行汇编时，这种表示被称为 <a href="https://en.wikipedia.org/wiki/P-code_machine" target="_blank" rel="noopener" class="mycode_url">p-code</a>。<br />
<br />
<span style="font-style: italic;" class="mycode_i">另请参阅：</span> <a href="https://en.wikipedia.org/wiki/Bytecode" target="_blank" rel="noopener" class="mycode_url">字节码</a><br />
<ul class="mycode_list"><li>## &lt;a name="concept-spc-vna"&gt;&lt;/a&gt; 存储程序概念与冯·诺依曼体系结构<br />
</li>
</ul>
<br />
代码像数据一样驻留在内存中的想法被称为<a href="https://en.wikipedia.org/wiki/Stored-program_computer" target="_blank" rel="noopener" class="mycode_url">存储程序概念</a>。这也意味着内存中的每条指令都有一个地址，就像数据一样。代码和数据都驻留在<span style="font-weight: bold;" class="mycode_b">同一内存</span>中的想法是<a href="https://en.wikipedia.org/wiki/Von_Neumann_architecture" target="_blank" rel="noopener" class="mycode_url">冯·诺依曼体系结构</a>的一个原则。这也意味着所有代码和数据共享一个<a href="https://en.wikipedia.org/wiki/Address_space" target="_blank" rel="noopener" class="mycode_url">地址空间</a>。<br />
<br />
AMX 使用一个公共内存来存储代码和数据。<br />
<ul class="mycode_list"><li>## &lt;a name="concept-hdc"&gt;&lt;/a&gt; 头、数据段、代码段<br />
</li>
</ul>
<br />
可执行二进制文件及程序的内存结构根据其包含的内容被划分为逻辑上不同的区域。一个典型的二进制可执行文件至少包含一个头、一个代码段和一个数据段。头提供了程序本身的信息，例如<a href="https://en.wikipedia.org/wiki/Entry_point" target="_blank" rel="noopener" class="mycode_url">程序入口点</a>。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>HEADER<br />
&nbsp;&nbsp;-------<br />
&nbsp;&nbsp; CODE<br />
&nbsp;&nbsp;-------<br />
&nbsp;&nbsp; DATA</code></div></div><br />
代码段以二进制形式（机器码/p-code）存储代码，而数据段存储数据，如全局变量和静态局部变量。<br />
<br />
程序的内存结构通常不同。除了代码段和数据段外，它通常还包含程序栈和程序堆的区域。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>HEADER<br />
&nbsp;&nbsp;-------<br />
&nbsp;&nbsp; CODE<br />
&nbsp;&nbsp;-------<br />
&nbsp;&nbsp; DATA<br />
&nbsp;&nbsp;-------<br />
&nbsp;&nbsp; HEAP<br />
&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp; STACK</code></div></div><br />
AMX 二进制文件组织为三个部分：前缀、代码和数据（按顺序）。前缀部分包含有关 AMX 二进制文件的信息，例如代码和数据部分在二进制文件中的起始偏移量。代码部分存储 p-code，数据段存储全局变量和静态局部变量。<br />
<br />
堆栈区域是在 AMX 二进制文件加载到内存后，使用前缀部分中的信息创建的。<br />
<br />
<span style="font-style: italic;" class="mycode_i">另请参阅</span>：<a href="https://en.wikipedia.org/wiki/Memory_segmentation" target="_blank" rel="noopener" class="mycode_url">内存分段</a>，<a href="https://en.wikipedia.org/wiki/Data_segment" target="_blank" rel="noopener" class="mycode_url">数据段</a>，<a href="https://en.wikipedia.org/wiki/Code_segment" target="_blank" rel="noopener" class="mycode_url">代码段</a>，<a href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format" target="_blank" rel="noopener" class="mycode_url">ELF 格式</a><br />
<ul class="mycode_list"><li>## &lt;a name="concept-registers"&gt;&lt;/a&gt; 寄存器<br />
</li>
</ul>
了解处理器和内存位于不同的位置至关重要。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>|-------|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|------------------|<br />
&nbsp;&nbsp;|&nbsp;&nbsp;CPU&nbsp;&nbsp;|&nbsp;&nbsp;=============== |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MEMORY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp;|-------|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BUS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |------------------|</code></div></div><br />
内存存储数据，CPU 对数据进行操作。对于每次操作，处理器都必须将操作数从内存中取出并临时存储在 CPU 内部。这些临时存储位置被称为<a href="https://en.wikipedia.org/wiki/Processor_register" target="_blank" rel="noopener" class="mycode_url">寄存器</a>。这些寄存器可以容纳少量数据，范围在几个字节（通常为 2、4 或 8 字节）。<br />
<br />
假设处理器必须将两个变量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 相加，并将结果存储在变量 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">z</code> 中。一个典型的处理器会执行以下操作：<br />
<ol type="1" class="mycode_list"><li>从内存中取出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 的值（即从 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 的地址读取）并将其存储在一个寄存器中，比如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R1</code><br />
</li>
<li>从内存中取出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 的值（即从 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">y</code> 的地址读取）并将其存储在一个寄存器中，比如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R2</code><br />
</li>
<li>将 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R1</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R2</code> 的内容相加，并将结果存储在某寄存器中，比如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R3</code><br />
</li>
<li>将 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">R3</code> 的内容存储到 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">z</code> 中（写入 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">z</code> 的地址）<br />
</li>
</ol>
<br />
处理器包含不同<a href="https://en.wikipedia.org/wiki/Processor_register#Categories_of_registers" target="_blank" rel="noopener" class="mycode_url">类型的寄存器</a>，用于不同目的。一些寄存器专用于特定任务，一些寄存器可用于任何目的。上例中使用的那类寄存器属于通用寄存器。<br />
<br />
AMX 的寄存器集包括以下寄存器：<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">主寄存器 (PRI)</span>：通用寄存器（常用作<a href="https://en.wikipedia.org/wiki/Accumulator_(computing)" target="_blank" rel="noopener" class="mycode_url">累加器寄存器</a>）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">辅助寄存器 (ALT)</span>：通用寄存器（常用作地址寄存器）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">代码段寄存器 (COD)</span>：内存中代码段起始的绝对地址<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">数据段寄存器 (DAT)</span>：内存中数据段起始的绝对地址<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">当前指令指针 (CIP)</span>：下一条<span style="font-style: italic;" class="mycode_i">要执行指令</span>的地址（相对于 COD 寄存器）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">栈顶寄存器 (STP)</span>：栈顶的地址（相对于 DAT 寄存器）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">栈指针寄存器 (STK)</span>：栈上当前位置的地址（相对于 DAT 寄存器）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">帧指针寄存器 (FRM)</span>：栈中当前函数帧起始的地址（相对于 DAT 寄存器）（<span style="font-style: italic;" class="mycode_i">稍后解释</span>）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">堆指针 (HEA)</span>：堆顶的地址（相对于 DAT 寄存器）<br />
</li>
</ul>
<br />
在编写汇编代码时，地址通常不是绝对的；它们是相对于某个段或帧指针寄存器的。全局变量和字符串的地址相对于 DAT 寄存器。函数、指令和标签的地址相对于 COD 寄存器。这意味着变量或指令的绝对地址分别是相对地址加上 DAT 或 COD 寄存器的值。局部变量的地址相对于帧指针寄存器。这有点复杂，稍后会解释。<br />
<br />
<span style="font-style: italic;" class="mycode_i">从现在开始，当我们讨论代码地址和数据地址时，除非明确说明，否则暗示这些地址分别相对于 COD 寄存器和 DAT 寄存器。</span><br />
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 文件与内存布局</h2><br />
所有非调试 AMX 二进制文件按如下方式组织：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>START OF BINARY FILE<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PREFIX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CODE<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DATA<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
END OF BINARY FILE</code></div></div><ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">前缀</span>：包含程序的基本信息<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">代码</span>：包含代码<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">数据</span>：包含数据<br />
</li>
</ul>
<br />
<span style="font-style: italic;" class="mycode_i">注意：根据编译器的选项，前缀部分可能会被<a href="https://en.wikipedia.org/wiki/Data_structure_alignment" target="_blank" rel="noopener" class="mycode_url">填充</a>以使代码和数据部分对齐。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">注意：启用调试编译的脚本的二进制映像将在末尾附加符号调试信息。更多详情请参阅 Pawn 实现者指南。</span><br />
<br />
内存中的结构采用与二进制文件类似的结构，但额外包含一个栈和一个堆，这是使用前缀中的信息设置的。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>LOW ADDRESS (0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PREFIX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CODE<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DATA<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HEAP<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FREE SPACE<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;STACK<br />
&nbsp;&nbsp;&nbsp;&nbsp;| ---------------------- |<br />
HIGH ADDRESS</code></div></div><br />
堆和栈共享一个公共的内存区域。它们从该区域的两端开始，并向相反方向增长。堆向高地址增长，栈向低地址增长。由于它们共享同一内存区域，因此可能会相互覆盖（当堆指针和栈指针碰撞时）。发生这种情况时，AMX 会中止并显示如下错误信息：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>Script[gamemodes/TEST.amx]: Run time error 3: "Stack/heap collision (insufficient stack size)"</code></div></div><br />
根据编译器掌握的信息，它会估算并间接地在 AMX 二进制文件的前缀部分设置堆栈大小。然而，程序员可以使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#pragma dynamic [estimated number of cells]</code> 指令提供自己对所需堆栈区域大小的估计。<br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">前缀部分的字段</h3><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">类型</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">大小</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">描述</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">size</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">内存映像的大小；不包括栈和堆</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">magic</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">2</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">指示格式和单元格大小</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">file version</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">1</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">格式版本</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">amx version</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">1</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">抽象机所需的最低版本</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">flags</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">2</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">是否存在符号调试信息、紧凑编码等。</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">defsize</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">2</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">表中记录的大小</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">cod</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">代码部分起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">dat</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">数据部分起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">hea</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">HEA 寄存器的初始值（标记数据段结束）</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">stp</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STP 寄存器的初始值（指示总内存需求）</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">cip</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CIP 寄存器的初始值（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main</code> 函数的地址；如果不存在则为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">-1</code>）</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">publics</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">公共函数表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">natives</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">原生函数表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">libraries</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">库表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">pubvars</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">公共变量表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">tags</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">标签表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">name table</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">名称表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">overlays</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">覆盖表起始的偏移量</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">publics</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">公共函数列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">natives</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">原生函数列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">libraries</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">库列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">pubvars</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">公共变量列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">tags</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">公共标签列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">overlays</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">覆盖列表</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">name table</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">可变</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">符号名称列表</td>
 </tr>
</table>
<br />
<span style="font-style: italic;" class="mycode_i">注意：关于 magic、version 和 flags 字段中信息如何编码的详细信息，请参阅 Pawn 实现者指南。</span><br />
<br />
<span style="font-style: italic;" class="mycode_i">注意：前缀中的所有多字节字段都以<a href="https://en.wikipedia.org/wiki/Endianness" target="_blank" rel="noopener" class="mycode_url">小端格式</a>存储，无论 AMX 二进制文件是在哪个平台上生成或将在哪个平台上执行。</span><br />
<br />
可以看出，前缀由一个固定部分组成，后面跟着一系列表。除了名称表之外，表中的每条记录都由两个字段组成，如下所示：<br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">字段</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">大小</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">描述</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">变量</span></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">单元格大小</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-style: italic;" class="mycode_i">变量</span></td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">名称字符串偏移量</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">4 字节</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">从前缀起始到名称表中字符串的偏移量</td>
 </tr>
</table>
<br />
表中每条记录（除了名称表）的大小由前缀中的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">defsize</code> 字段给出：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">defsize</code> = 4 + 单元格大小。<br />
<br />
表中的每条记录都被分配了一个索引号。每个表的第一个记录被分配索引 0，后续记录的索引号是前一个记录索引加 1。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">名称表</span>：<br />
除了名称表本身之外，其他表中的记录包含一个指向字符串的指针。这些字符串作为以空字符结尾的 C 字符串存储在名称表中。此表中记录的大小是其包含的字符串的大小。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">公共函数表</span>：<br />
为脚本中定义的每个公共函数创建一条记录。这些记录包含公共函数的地址（函数第一条指令的地址）和指向相应公共函数名称的偏移量。表中记录的索引就是相应公共函数的索引。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">原生函数表</span>：<br />
为脚本中调用的每个原生函数创建一条记录。记录的第一个字段由编译器在二进制文件中设置为 0，但宿主程序在加载二进制文件时会将该字段初始化为函数的地址（位于宿主程序的地址空间中）。第二个字段包含指向原生函数名称的偏移量。表中记录的索引就是相应原生函数的索引。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">库表</span>：<br />
Pawn 语言提供了一个 pragma 指令 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#pragma directive [library name]</code>，用于告知编译器调用的某些原生函数需要扩展模块。对于在脚本中调用了其原生函数的库，会在库表中创建一条记录。目的是告知宿主程序 AMX 程序依赖于一个扩展模块。记录的第一个字段供内部使用，在 AMX 二进制文件中设置为 0。另一个字段包含从前缀起始到名称表中库名称的偏移量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">公共变量表</span>：<br />
为脚本中声明的每个公共变量创建一条记录。该记录包含公共变量的地址和指向公共变量名称的偏移量。表中记录的索引就是公共变量的索引。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">标签表</span>：<br />
与 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">sleep</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">exit</code> 语句一起使用的标签以及与 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">tagof</code> 运算符一起使用的标签会被导出。为每个这样的标签创建一条记录。第一个字段包含标签 id 号，第二个字段存储指向标签名称的偏移量。<br />
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;"> 指令集</h2><br />
<br />
&lt;a name="pawn-inline-assembly"&gt;&lt;/a&gt; Pawn 编译器接受的大部分 AMX 汇编指令可以用以下格式表示：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>mnemonic[.prefix][.register suffix] operand<br />
<br />
SHL.C.pri 3<br />
ZERO.alt<br />
ADD.C 100<br />
LIDX</code></div></div><br />
助记符给出了指令功能的提示。可选的前缀指示指令操作数的类型。可选的尾缀指示指令主要作用于哪个寄存器。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">前缀列表</span>：<ul class="mycode_list"><li>.C = 常量<br />
</li>
<li>.S = 栈<br />
</li>
<li>.I = 间接寻址<br />
</li>
<li>.B = 无 B 变体的变体&lt;sup&gt;\[需要更好的描述\]&lt;/sup&gt;<br />
</li>
<li>.ADR = 地址<br />
</li>
<li>.R = 重复<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">寄存器尾缀列表</span>：<ul class="mycode_list"><li>.pri = 主寄存器<br />
</li>
<li>.alt = 辅助寄存器<br />
</li>
</ul>
<br />
每条指令的二进制形式需要一个单元格来存储操作码，每个操作数还需要一个额外的单元格。绝大多数指令使用隐含寄存器作为操作数。这减少了所需显式操作数的数量，从而减小了代码段的大小并提高了性能。<br />
<br />
&lt;a name="instruction-table"&gt;&lt;/a&gt; <span style="font-style: italic;" class="mycode_i">阅读表格：</span><br />
<ol type="1" class="mycode_list"><li><span style="font-style: italic;" class="mycode_i">[address] 指的是存储在位置 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">DAT + address</code> 的值</span><br />
</li>
<li><span style="font-style: italic;" class="mycode_i">语义列中使用的运算符执行与 Pawn 中相同的操作</span><br />
</li>
</ol>
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">操作码</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">助记符</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">操作数</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">语义</th>
 </tr>
</table>
 <br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">1</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">LOAD.pri</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">address</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">PRI = [address]</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">2</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LOAD.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = [address]</td>
 </tr>
</table>
   <br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">3</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">LOAD.S.pri</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">offset</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">PRI = [FRM + offset]</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">4</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LOAD.S.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = [FRM + offset]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">5</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LREF.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [[address]]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">6</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LREF.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = [[address]]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">7</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LREF.S.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [[FRM + offset]]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">8</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LREF.S.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = [[FRM + offset]]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">9</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LOAD.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [PRI]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">10</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LODB.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = 'number' of bytes from [PRI] (read 1/2/4 bytes)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">11</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CONST.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">12</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CONST.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">13</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ADDR.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = FRM + offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">14</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ADDR.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = FRM + offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">15</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STOR.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[address] = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">16</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STOR.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[address] = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">17</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STOR.S.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[FRM + offset] = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">18</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STOR.S.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[FRM + offset] = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">19</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SREF.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[[address]] = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">20</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SREF.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[[address]] = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">21</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SREF.S.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[[FRM + offset]] = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">22</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SREF.S.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[[FRM + offset]] = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">23</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STOR.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[ALT] = PRI (full cell)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">24</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STRB.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number of bytes at [ALT] = PRI (store 1/2/4 bytes)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">25</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LIDX</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [ALT + (PRI x cell size)]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">26</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LIDX.B</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">shift</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [ALT + (PRI &lt;&lt; shift)]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">27</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">IDXADDR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT + (PRI x cell size) (calculate indexed address)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">28</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">IDXADDR.B</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">shift</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT + (PRI &lt;&lt; shift) (calculate indexed address)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">29</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALIGN.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">Little Endian: PRI ^= cell size - number</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">30</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALIGN.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">Little Endian: ALT ^= cell size - number</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">31</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LCTRL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">index</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = value contained in the selected register; 1=COD, 1=DAT, 2=HEA,3=STP, 4=STK, 5=FRM, 6=CIP</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">32</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SCTRL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">index</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">selected register = PRI; 2=HEA, 4=STK, 5=FRM, 6=CIP</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">33</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">MOVE.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">34</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">MOVE.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">35</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">XCHG</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">Exchange contents of PRI and ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">36</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">37</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">38</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.R</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">repeat (STK = STK - cell size, [STK] = PRI) 'number' times</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">39</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.C</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = value</td>
 </tr>
</table>
  <br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">40</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">PUSH</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">address</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">STK = STK - cell size, [STK] = [address]</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">41</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.S</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = [FRM + offset]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">42</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">POP.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = [STK], STK = STK + cell size</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">43</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">POP.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = [STK], STK = STK + cell size</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">44</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STACK</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = STK, STK = STK + value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">45</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">HEAP</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = HEA, HEA = HEA + value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">46</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PROC</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = FRM, FRM = STK</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">47</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">RET</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">FRM = [STK], STK = STK + cell size, CIP = [STK], STK = STK + cell size</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">48</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">RETN</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">FRM = [STK], STK = STK + cell size, CIP = [STK], STK = STK + cell size, STK = STK + [STK] + cell size</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">49</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CALL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK − cell size, [STK] = CIP, CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">50</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CALL.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK − cell size, [STK] = CIP, CIP = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">51</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JUMP</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">53</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JZER</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI == 0 then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">54</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JNZ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI != 0 then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">55</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI == ALT then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">56</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JNEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI != ALT then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">57</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JLESS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &lt; ALT (unsigned) then CIP = offset</td>
 </tr>
</table>
 <br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">58</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">JLEQ</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">offset</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">if PRI &lt;= ALT (unsigned)  then CIP = offset</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">59</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JGRTR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &gt; ALT (unsigned) then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">60</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JGEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &gt;= ALT (unsigned) then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">61</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JSLESS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &lt; ALT (signed) then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">62</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JSLEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &lt;= ALT (signed) then CIP = offset</td>
 </tr>
</table>
 <br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">63</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">JSGRTR</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">offset</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">if PRI &gt; ALT (signed) then CIP = offset</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">64</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JSGEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">if PRI &gt;= ALT (signed) then CIP = offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">65</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt;&lt; ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">66</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt;&gt; ALT (without sign extension)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">67</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SSHR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt;&gt; ALT (with sign extension)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">68</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHL.C.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt;&lt; value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">69</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHL.C.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = ALT &lt;&lt; value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">70</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHR.C.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt;&gt; value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">71</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SHR.C.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = ALT &gt;&gt; value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">72</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SMUL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI * ALT (signed multiply)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">73</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SDIV</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI / ALT (signed divide), ALT = PRI mod ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">74</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SDIV.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT / PRI (signed divide), ALT = ALT mod PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">75</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">UMUL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI * ALT (unsigned multiply)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">76</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">UDIV</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI / ALT (unsigned divide), ALT = PRI mod ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">77</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">UDIV.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT / PRI (unsigned divide), ALT = ALT mod PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">78</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ADD</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI + ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">79</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SUB</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI - ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">80</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SUB.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT - PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">81</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">AND</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &amp; ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">82</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">OR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &#124; ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">83</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">XOR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI ^ ALT</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">84</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">NOT</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = !PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">85</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">NEG</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = -PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">86</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INVERT</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ~PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">87</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ADD.C</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI + value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">88</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SMUL.C</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI * value</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">89</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ZERO.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">90</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ZERO.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">91</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ZERO</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[address] = 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">92</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ZERO.S</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[FRM + offset] = 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">93</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SIGN.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">sign extend the byte in PRI to a cell</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">94</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SIGN.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">sign extend the byte in ALT to a cell</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">95</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">EQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI == ALT ? 1 : 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">96</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">NEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI != ALT ? 1 : 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">97</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LESS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt; ALT ? 1 : 0 (unsigned)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">98</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">LEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt;= ALT ? 1 : 0 (unsigned)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">99</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">GRTR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt; ALT ? 1 : 0 (unsigned)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">100</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">GEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt;= ALT ? 1 : 0 (unsigned)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">101</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SLESS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt; ALT ? 1 : 0 (signed)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">102</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SLEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &lt;= ALT ? 1 : 0 (signed)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">103</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SGRTR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt; ALT ? 1 : 0 (signed)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">104</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SGEQ</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI &gt;= ALT ? 1 : 0 (signed)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">105</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">EQ.C.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI == value ? 1 : 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">106</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">EQ.C.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = ALT == value ? 1 : 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">107</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INC.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI + 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">108</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INC.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = ALT + 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">109</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INC</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[address] = [address] + 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">110</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INC.S</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[FRM + offset] = [FRM + offset] + 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">111</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">INC.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[PRI] = [PRI] + 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">112</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">DEC.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = PRI - 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">113</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">DEC.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">ALT = ALT - 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">114</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">DEC</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">address</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[address] = [address] - 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">115</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">DEC.S</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[FRM + offset] = [FRM + offset] - 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">116</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">DEC.I</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[PRI] = [PRI] - 1</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">117</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">MOVS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">copy 'number' bytes of non-overlapping memory from [PRI] to [ALT]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">118</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CMPS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">compare 'number' bytes of non-overlapping memory at [PRI] with [ALT]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">119</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">FILL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">number</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">fill 'number' bytes of memory from [ALT] with value in PRI (number must be multiple of cell size)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">120</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">HALT</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">0</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">abort execution (exit value in PRI)</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">121</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">BOUNDS</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">abort execution if PRI &gt; value or if PRI &lt; 0</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">122</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SYSREQ.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">call system service, service number in PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">123</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SYSREQ.C</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">value</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">call system service</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">128</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">JUMP.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CIP = PRI</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">129</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SWITCH</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">compare PRI to the values in the case table (whose address is passed in the 'offset' argument) and jump to the associated address in the matching record</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">130</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">CASETBL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">...</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">a variable number of case records follows this opcode, where each record takes two cells</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">131</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SWAP.pri</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[STK] = PRI, PRI = [STK]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">132</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">SWAP.alt</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">[STK] = ALT, ALT = [STK]</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">133</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PUSH.ADR</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">offset</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">STK = STK - cell size, [STK] = FRM + offset</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">134</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">NOP</td>
 <td style="border:1px solid #ddd;padding:6px 10px;"></td>
 <td style="border:1px solid #ddd;padding:6px 10px;">no operation</td>
 </tr>
</table>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 加载/存储指令</h4><br />
<br />
当使用全局变量作为操作数时，编译器会替换该变量的地址。下面代码中的第一条加载指令，如果 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">some_global</code> 的地址是 1288，则实际上变成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#emit LOAD.pri 1288</code>。请注意，编译器替换的地址是从数据段起始的偏移量；因此，该地址是相对于 DAT 寄存器的。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new some_global = 10, another_global = 25;<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LOAD.pri some_global // 将 'some_global' 的值加载到主寄存器<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LOAD.alt another_global&nbsp;&nbsp;// 将 'another_global' 的值加载到辅助寄存器<br />
}</code></div></div><br />
当使用局部变量时，编译器会替换从函数帧起始的偏移量。<span style="font-style: italic;" class="mycode_i">(稍后解释)</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;static s_local = 20; // 静态局部变量存储在数据段中<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;new some_local = 10, another_local = 25; // 局部变量存储在栈中<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LOAD.S.pri some_local // 将 'some_local' 的值加载到主寄存器<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LOAD.S.alt another_local&nbsp;&nbsp;// 将 'another_local' 的值加载到辅助寄存器<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LOAD.pri s_local // 注意静态局部变量的行为类似于全局变量<br />
}</code></div></div><br />
由于编译器会为全局变量替换地址，因此可以使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">CONST.pri/CONST.alt</code> 来获取这些变量的地址。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new some_global;<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 10 // 将 10 放入主寄存器<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt 50 // 将 50 放入辅助寄存器<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri some_global // 将 'some_global' 的地址存储在主寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt some_global // 将 'some_global' 的地址存储在辅助寄存器中<br />
}</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new some_global;<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new some_local;<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit ZERO.pri // 将零存储在主寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit STOR.pri some_global // 将主寄存器中存储的值（本例中为零）设置给 'some_global'<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt 125<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit STOR.S.alt some_local // 将辅助寄存器中存储的值（125）设置给 'some_local'<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 索引指令</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new global_arr[10];<br />
main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt global_arr // 将 'global_arr' 的地址（'global_arr' 第一个元素的地址）加载到辅助寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 2 // 设置我们感兴趣的 'global_arr' 元素的索引<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LIDX // 现在主寄存器中存储的是 'global_arr[2]` 处存储的值<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt global_arr // 将 'global_arr' 的地址（第一个元素的地址）加载到辅助寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 2 // 设置我们感兴趣的 'global_arr' 元素的索引<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit IDXADDR // 现在主寄存器中存储的是 'global_arr[2]` 的地址<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 算术指令</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 4<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt 5<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit SMUL // 现在主寄存器中是 20（SMUL 执行有符号乘法；UMUL 执行无符号乘法）<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit ADD // 将 5 加到 20（由于上一条指令，主寄存器中存储的是 20）<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit ADD.C 10 // 将 10 加到主寄存器；现在主寄存器中是 35<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit SUB.alt // 用 5 减去 35；现在主寄存器中是 -30<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit SMUL.C 2 // -30 乘以 2；得到 -60<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 逻辑指令</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 5 // .. 0000 0101<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt 3 // ... 0000 0011<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit AND // 主寄存器现在包含 ... 0000 0001<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit XOR // 主寄存器现在包含 ... 0000 0110<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit INVERT // 对主寄存器中存储的值取反码<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit NEG // 对主寄存器中存储的值取补码（本质上是取负）<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">关系指令</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 5<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.alt 8<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit EQ // 如果 5 == 8，则将主寄存器设置为 1，否则为 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LESS // 如果 0 &lt; 8，则将主寄存器设置为 1，否则为 0<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 栈操作指令</h4><br />
<br />
局部变量存储在栈上。详细说明将在后续章节中提供，但现在我们假设使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">CONST.pri some_local</code> 会得到某个偏移量，该偏移量加上帧寄存器中存储的基地址即得数据地址。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new some_local = 25;<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit ADDR.alt some_local // 计算 'some_local' 的地址<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 100<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit STOR.I // 将 100 存储到 'some_local'<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 100<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit STOR.S.pri some_local // 实现上述代码功能的更好方法<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri some_local // 神秘地等价于 CONST.pri -4（稍后解释）<br />
}</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit PUSH.C 100 // 将值 100 压入调用栈<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit POP.pri // 从栈中弹出一个值并将结果存储在主寄存器中<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit PUSH.pri // 推送主寄存器的值<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit PUSH.alt // 推送辅助寄存器的值<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit POP.pri<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit POP.alt // 最后 4 条指令有效地交换了主寄存器和辅助寄存器的内容<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit XCHG // 交换主寄存器和辅助寄存器内容的更好方法<br />
}</code></div></div><br />
局部数组位于栈上。因此，在使用索引指令之前，必须使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">ADDR.alt/ADDR.pri</code> 来获取完整的地址。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new local_array[10];<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit ADDR.alt local_array // 加载存储在 'local_array' 中的值，即数组的地址<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit CONST.pri 5<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit LIDX // 有效地将 'local_array[5]' 的值存储在主寄存器中<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 堆指令</h4><br />
堆指针（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">HEA</code> 寄存器）指向堆的顶部。将堆指针向前移动 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 字节，我们就能有效地<br />
在堆上预留 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">x</code> 字节。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit HEAP 16 // 为四个单元格预留空间（假设单元格为 4 字节）<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 注意 HEAP 指令也将辅助寄存器设置为我们预留内存的起始地址<br />
&nbsp;&nbsp;&nbsp;&nbsp; // ALT = HEA, HEA += 16<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit CONST.pri 50<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit STOR.I // 有效地将值 50 存储在我们预留的堆区域的第一个单元格中<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit HEAP -16 // 归还预留的内存<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 控制寄存器操作指令</h4><br />
可以使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">LCTRL</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SCTRL</code> 指令直接读取和修改专用寄存器的内容。<br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
 <tr>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">助记符</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">操作数</th>
 <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">描述</th>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">LCTRL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">index</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">PRI = 所选寄存器中包含的值；0=COD, 1=DAT, 2=HEA, 3=STP, 4=STK, 5=FRM, 6=CIP</td>
 </tr>
 <tr>
 <td style="border:1px solid #ddd;padding:6px 10px;">SCTRL</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">index</td>
 <td style="border:1px solid #ddd;padding:6px 10px;">所选寄存器 = PRI；2=HEA, 4=STK, 5=FRM, 6=CIP</td>
 </tr>
</table>
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main ()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp; new cod, dat;<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit LCTRL 0 // 将 COD 段寄存器的值存储在主寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit STOR.S.pri cod<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit LCTRL 1 // 将 DAT 段寄存器的值存储在主寄存器中<br />
&nbsp;&nbsp;&nbsp;&nbsp; #emit STOR.S.pri dat<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; printf("%d %d", cod, dat);<br />
}</code></div></div><br />
当函数名用作操作数时，编译器会用函数的地址替换它。替换的地址是相对于 COD 寄存器的。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>f()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print("f() was called.");<br />
}<br />
<br />
main ()<br />
{<br />
&nbsp;&nbsp; #emit PUSH.C 0 // 参数占用的字节数（稍后解释）<br />
&nbsp;&nbsp; #emit LCTRL 6 // 获取 CIP 的值，即下一条指令（本例中的 ADD.C）的地址<br />
&nbsp;&nbsp; #emit ADD.C 28 // 计算 'f' 之后要执行的指令的地址（注意每个操作码和操作数都需要一个单元格）<br />
&nbsp;&nbsp; #emit PUSH.pri // 推送返回地址，以便 'f' 知道返回到哪里（稍后解释）<br />
&nbsp;&nbsp; #emit CONST.pri f // 将函数 'f' 的地址存储在 pri 中<br />
&nbsp;&nbsp; #emit SCTRL 6 // 将当前指令指针设置为存储在主寄存器中的值<br />
<br />
&nbsp;&nbsp; // 函数 'f' 执行<br />
&nbsp;&nbsp; // 函数 'f' 返回后，下一条指令（本例中的 NOP）将开始执行<br />
<br />
&nbsp;&nbsp; #emit NOP // 不执行任何操作的指令<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> 控制流指令</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main()<br />
{&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;#emit JUMP check // 跳转到 check 标签<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;not_equal:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("1 is not equal to 2");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;equal:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("1 is equal to 2");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;check:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #emit CONST.pri 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #emit CONST.alt 2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #emit JEQ equal // 如果主寄存器的值等于辅助寄存器的值，则跳转到 'equal'<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #emit JUMP not_equal // 如果执行到这里，意味着两个寄存器的值不相等；因此跳转到 'not_equal'<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;"> Switch case 指令</h4><br />
<br />
switch-case 块使用<a href="https://en.wikipedia.org/wiki/Branch_table" target="_blank" rel="noopener" class="mycode_url">分支表</a>实现。分支表仅仅是由 case 值及其对应的跳转地址组成的元组列表。对于给定的 case 值，AMX 会搜索分支表并跳转到相应的跳转地址。分支表中的记录按 case 值的升序排列。这允许 AMX 对分支表执行二分搜索，但它也可能执行线性搜索。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SWITCH</code> 指令标记 switch-case 块的开始。它接受一个指向分支表（也位于代码段中）的偏移量作为操作数。分支表正式以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">CASETBL</code> 操作码（仅作为标记，功能上未使用）开始，后跟一系列 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">CASE</code> 记录，每条记录占用两个参数。第一条 case 记录的参数具有特殊含义：第一个参数是分支表中的 case 数量，第二个参数是默认 case 的偏移量。如果没有提供默认 case，则第二个参数包含 switch-case 块之后指令的偏移量。其余的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">CASE</code> 记录包含 case 值及其对应的跳转地址。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>switch(expression)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;case 2: {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;case 4: {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;case 3: {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;case 7: {}<br />
&nbsp;&nbsp;&nbsp;&nbsp;case 5: {}<br />
}</code></div></div><br />
编译器会添加指令来计算给定的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">expression</code>，其结果存储在主寄存器中。紧接着是一条 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">SWITCH</code> 指令，它使 AMX 搜索分支表，查找与主寄存器中存储的值匹配的 case 值。如果找到匹配项，则执行跳转到匹配记录指向的地址；否则，跳转到默认地址。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>; 编译器通过在汇编输出中使用标签而不是实际的偏移量/地址，使阅读更容易<br />
; 每个标签都以前缀 "l." 开头<br />
<br />
switch 0 ; 注意这里的零是一个标签<br />
<br />
l.2 ; 标签 2<br />
&nbsp;&nbsp; jump 1 ; 跳转到标签 1<br />
l.3<br />
&nbsp;&nbsp; jump 1<br />
l.4<br />
&nbsp;&nbsp; jump 1<br />
l.5<br />
&nbsp;&nbsp; jump 1<br />
l.6<br />
&nbsp;&nbsp; jump 1<br />
<br />
l.0<br />
&nbsp;&nbsp;casetbl <br />
&nbsp;&nbsp;case 5 1 ; 记录数量，默认跳转地址（本例中为标签 1）<br />
&nbsp;&nbsp; case 2 2 ; 真正的第一条记录<br />
&nbsp;&nbsp; case 3 4 ; case 值: 3, 跳转标签: 4<br />
&nbsp;&nbsp; case 4 3 ; 编译器在实际二进制文件中会用正确的地址替换标签<br />
&nbsp;&nbsp; case 5 6 ; <br />
&nbsp;&nbsp; case 7 5 ; 最后一条记录<br />
<br />
 l.1<br />
&nbsp;&nbsp; ; 其余代码</code></div></div>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[wiki系列] openmp/samp 关键字：指令]]></title>
			<link>https://open-mp.cn/showthread.php?tid=23</link>
			<pubDate>Sat, 21 Mar 2026 23:06:33 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=23</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">[wiki系列] openmp/samp 关键字：指令</h2><br />
<br />
<span style="font-weight: bold;" class="mycode_b">来自 SA-MP Wiki</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">目录</h3><br />
<ul class="mycode_list"><li><a href="http://#assert" target="_blank" rel="noopener" class="mycode_url">1 #assert</a><br />
</li>
<li><a href="http://#define" target="_blank" rel="noopener" class="mycode_url">2 #define</a><br />
</li>
<li><a href="http://#else" target="_blank" rel="noopener" class="mycode_url">3 #else</a><br />
</li>
<li><a href="http://#elseif" target="_blank" rel="noopener" class="mycode_url">4 #elseif</a><br />
</li>
<li><a href="http://#emit" target="_blank" rel="noopener" class="mycode_url">5 #emit</a><br />
</li>
<li><a href="http://#endif" target="_blank" rel="noopener" class="mycode_url">6 #endif</a><br />
</li>
<li><a href="http://#endinput-endscript" target="_blank" rel="noopener" class="mycode_url">7 #endinput , #endscript</a><br />
</li>
<li><a href="http://#error" target="_blank" rel="noopener" class="mycode_url">8 #error</a><br />
</li>
<li><a href="http://#if" target="_blank" rel="noopener" class="mycode_url">9 #if</a><br />
</li>
<li><a href="http://#include" target="_blank" rel="noopener" class="mycode_url">10 #include</a><br />
</li>
<li><a href="http://#pragma" target="_blank" rel="noopener" class="mycode_url">11 #pragma</a><br />
</li>
<li><a href="http://#pragma-information" target="_blank" rel="noopener" class="mycode_url">11.1 说明</a><br />
</li>
<li><a href="http://#pragma-list" target="_blank" rel="noopener" class="mycode_url">11.2 列表</a><br />
</li>
<li><a href="http://#pragma-examples" target="_blank" rel="noopener" class="mycode_url">11.3 示例</a><br />
</li>
<li><a href="http://#pragma-deprecated" target="_blank" rel="noopener" class="mycode_url">11.3.1 已弃用（Deprecated）</a><br />
</li>
<li><a href="http://#tryinclude" target="_blank" rel="noopener" class="mycode_url">12 #tryinclude</a><br />
</li>
<li><a href="http://#undef" target="_blank" rel="noopener" class="mycode_url">13 #undef</a><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#assert</h3><br />
<br />
此指令会检查常量表达式是否为真，如果不为真则停止编译。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 10<br />
#assert MOO &gt; 5</code></div></div><br />
以上代码可以正常编译。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 1<br />
#assert MOO &gt; 5</code></div></div><br />
以上代码无法编译，会产生致命错误。<br />
<br />
这类似于：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 1<br />
#if MOO &lt;= 5<br />
    #error Moo check failed<br />
#endif</code></div></div><br />
但是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#assert</code> 会给出以下错误信息：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"Assertation failed: 1 &gt; 5"</code></div></div><br />
而第二种写法会给出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"User error: Moo check failed"</code></div></div><br />
哪种错误信息更实用，则视情况而定。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#define</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code> 是一个文本替换指令。只要在代码中找到被定义的符号（宏名），就会将其替换为定义的内容。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 7<br />
printf("%d", MOO);</code></div></div><br />
会被替换为：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printf("%d", 7);</code></div></div><br />
这也是为什么反编译后的代码中看不到任何 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code>，因为所有指令都在预处理器阶段处理完毕。定义的内容不一定是数字：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define PL new i = 0; i &lt; MAX_PLAYERS; i++) if (IsPlayerConnected(i)<br />
for (PL)<br />
{<br />
    printf("%d connected", i);<br />
}</code></div></div><br />
会编译成大家熟悉（或讨厌）的玩家循环。注意括号的使用：一部分来自 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">for</code> 语句，一部分来自宏本身。<br />
<br />
另一个鲜为人知的特性是：定义可以跨行（通过在行尾加上反斜杠 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\</code> 来转义换行）。一般来说换行会结束定义，但下面这样是有效的：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define PL &#92;<br />
    new i = 0; i &lt; MAX_PLAYERS; i++) &#92;<br />
        if (IsPlayerConnected(i)<br />
for (PL)<br />
{<br />
    printf("%d connected", i);<br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\</code> 字符表示定义继续到下一行。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code> 的第三个重要特性是支持参数（宏参数）。参数用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">%0</code> 到 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">%9</code> 表示，用法与普通函数参数类似：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO(%0) &#92;<br />
    ((%0) * 7)<br />
printf("%d", MOO(6));</code></div></div><br />
输出结果为 42（不是随意选的）。注意宏里多余的括号——这是因为宏是纯文本替换，所以实际编译成：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printf("%d", ((6) * 7));</code></div></div><br />
这样是安全的。但看下面这个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printf("%d", MOO(5 + 6));</code></div></div><br />
你会期望结果是 77（(5 + 6) * 7）。加上括号后确实如此；如果去掉括号：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO(%0) &#92;<br />
    %0 * 7<br />
printf("%d", MOO(5 + 6));</code></div></div><br />
实际会变成：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printf("%d", 5 + 6 * 7);</code></div></div><br />
由于运算优先级（BODMAS），结果变为 47（5 + (6 * 7)），这就完全错误了。<br />
<br />
关于参数还有一个有趣的事实：如果传入的参数数量超过定义的数量，最后一个参数会包含所有多余的部分。例如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define PP(%0,%1) &#92;<br />
    printf(%0, %1)<br />
PP("%s %s %s", "hi", "hello", "hi");</code></div></div><br />
实际会打印：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>hi hello hi</code></div></div><br />
因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">%1</code> 包含了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">"hi", "hello", "hi"</code>。你可能还注意到 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#</code> 可以把字面量转换成字符串，这是 openmp(samp) 特有的功能，这里只是为了区分参数。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#else</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#else</code> 相当于普通 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else</code>，但用于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 条件。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#elseif</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#elseif</code> 相当于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code>，但用于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 条件。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 10<br />
#if MOO == 9<br />
    printf("if");<br />
#elseif MOO == 8<br />
    printf("else if");<br />
#else<br />
    printf("else");<br />
#endif</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#emit</h3><br />
<br />
此指令在 pawn-lang.pdf 的表格中并未列出，但实际存在。它相当于内联汇编器，如果你熟悉 AMX 字节码，可以用它直接插入 AMX 操作码。唯一限制是每次只能带一个参数。<br />
<br />
语法：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#emit &lt;opcode&gt; &lt;argument&gt;</code><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">&lt;argument&gt;</code> 可以是小数、整数或（局部/全局）符号（变量、函数、标签）。<br />
<br />
操作码列表及其含义可在 Pawn Toolkit ver. 3664 中找到。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#endif</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#endif</code> 相当于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 的结束括号。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 不使用大括号，所有条件内容一直持续到对应的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#endif</code>。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#endinput , #endscript</h3><br />
<br />
此指令停止当前文件的包含（不再继续读取该文件）。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#error</h3><br />
<br />
此指令立即停止编译，并输出自定义错误信息。示例见 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#assert</code>。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#if</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 是预处理器版本的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code>。你可以精确控制哪些代码被编译、哪些不被编译。例如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define LIMIT 10<br />
if (LIMIT &lt; 10)<br />
{<br />
    printf("Limit too low");<br />
}</code></div></div><br />
会编译成：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>if (10 &lt; 10)<br />
{<br />
    printf("Limit too low");<br />
}</code></div></div><br />
编译器知道这个条件永远为假，因此会给出“常量表达式”警告。但既然永远不会成立，为什么还要保留这段代码呢？你可以直接删掉，但之后别人修改 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">LIMIT</code> 重新编译时就无法检查了。这就是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 的作用。<br />
<br />
普通 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 在常量表达式时会警告，而 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> <span style="font-weight: bold;" class="mycode_b">必须</span> 是常量表达式：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define LIMIT 10<br />
#if LIMIT &lt; 10<br />
    #error Limit too low<br />
#endif</code></div></div><br />
这样会在编译时就检查限制是否过小，如果是则直接报错，而不用运行脚本测试。同时也不会生成多余的代码。注意 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 不强制使用括号（虽然复杂表达式可能需要）。<br />
<br />
另一个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define LIMIT 10<br />
if (LIMIT &lt; 10)<br />
{<br />
    printf("Limit less than 10");<br />
}<br />
else<br />
{<br />
    printf("Limit equal to or above 10");<br />
}</code></div></div><br />
同样是常量检查，会产生警告，而且两个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 都会被编译（尽管我们知道只会执行一个）。用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 改写后：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define LIMIT 10<br />
#if LIMIT &lt; 10<br />
    printf("Limit less than 10");<br />
#else<br />
    printf("Limit equal to or above 10");<br />
#endif</code></div></div><br />
这样只有需要的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 会被编译，另一个仍保留在源代码中（方便以后改 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">LIMIT</code>），但不会占用最终编译后的代码空间，也不会每次运行都执行无用的判断。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#include</h3><br />
<br />
此指令会把指定文件的所有代码插入到 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#include</code> 所在的位置。有两种包含方式：相对路径（用双引号）和系统路径（用尖括号，我自己起的名称，如果你有更好的叫法请告诉我）。<br />
<br />
相对包含使用双引号，路径相对于当前文件：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include "me.pwn"</code></div></div><br />
会包含与当前文件同目录下的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">me.pwn</code>。<br />
<br />
系统包含使用尖括号，从 Pawn 编译器所在目录下的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">include</code> 文件夹（或其父目录的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">include</code> 文件夹）中查找：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;me&gt;</code></div></div><br />
会包含 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">qawno/include/me.inc</code>（注意没有扩展名；如果文件不是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.p</code> 或 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.inc</code>，可以指定扩展名）。<br />
<br />
两种方式都支持子目录：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include "folder/me.pwn"<br />
#include &lt;folder/me&gt;</code></div></div><br />
如果文件不存在，编译会立即失败。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#pragma</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">说明</h4><br />
<br />
这是最复杂的指令之一。它提供了一系列选项来控制脚本的编译行为。例如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#pragma ctrlchar '&#36;'</code></div></div><br />
会把转义字符从 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\</code> 改成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">&#36;</code>，所以换行符不再是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">"\r\n"</code>，而是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">"&#36;r&#36;n"</code>。<br />
<br />
很多选项原本是为嵌入式系统设计的，用来限制 PC 上几乎无限制的资源。这里只列出与 openmp(samp) 相关的选项（完整列表见 pawn-lang.pdf）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">列表</h4><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">名称</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">值</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">说明</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">codepage</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">名称/值</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">设置字符串使用的 Unicode 码页</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">compress</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">1/0</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">openmp(samp) 不支持，请勿使用</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">deprecated</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">符号名称</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">如果使用该符号会产生警告，用于提示有更好的替代版本</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">dynamic</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">值（通常是 2 的幂）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">设置栈和堆内存大小（单位：cells）。出现“excessive memory usage”警告时需要设置</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">library</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">dll 名称</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">在 openmp(samp) 中经常被误用。它指定本文件中的原生函数来自哪个 DLL，并非把文件定义为库</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">pack</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">1/0</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">交换 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">!""</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">""</code> 的含义（详见 pawn-lang.pdf 中的打包字符串说明）</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">tabsize</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">值</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">经常被误用。用于设置制表符宽度，避免因空格和制表符混用产生的警告。openmp(samp) 默认设为 4（qawno 编辑器中制表符宽度）。设为 0 会关闭所有缩进警告，但强烈不推荐（会导致代码难以阅读）</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">unused</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">符号名称</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">类似 deprecated，用于抑制“symbol is never used”警告。推荐使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">stock</code>，但某些情况（如函数参数）无法使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">stock</code> 时才用此方式</td>
  </tr>
</table>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">示例</h4><br />
<br />
<h5 style="font-size:1.05em;font-weight:bold;margin:10px 0 4px;color:#444;">已弃用（Deprecated）</h5><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    gOldVariable = 5;<br />
#pragma deprecated gOldVariable<br />
main()<br />
{<br />
    printf("%d", gOldVariable);<br />
}</code></div></div><br />
使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gOldVariable</code> 时会产生警告，提示不应再使用它。主要用于函数更新 API 时保留向下兼容性。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#tryinclude</h3><br />
<br />
类似于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#include</code>，但如果文件不存在，编译不会失败。这非常适合根据用户是否安装了特定插件（或插件的 include 文件）来选择性包含功能。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">myinc.inc：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#if defined _MY_INC_INC<br />
    #endinput<br />
#endif<br />
#define _MY_INC_INC<br />
stock MyIncFunc()<br />
{<br />
    printf("Hello");<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">主脚本：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#tryinclude &lt;myinc&gt;<br />
main()<br />
{<br />
    #if defined _MY_INC_INC<br />
        MyIncFunc();<br />
    #endif<br />
}</code></div></div><br />
只有当 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">myinc.inc</code> 存在并被成功包含时，才会调用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MyIncFunc()</code>。这对 IRC 插件等需要检测插件是否安装的情况非常有用。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#undef</h3><br />
<br />
移除之前定义的宏或常量符号。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 10<br />
printf("%d", MOO);<br />
#undef MOO<br />
printf("%d", MOO);</code></div></div><br />
第二个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 会编译失败，因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MOO</code> 已被取消定义。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum<br />
{<br />
    e_example = 300<br />
};<br />
printf("%d", e_example);<br />
#undef e_example<br />
printf("%d", e_example); // 致命错误</code></div></div><hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">[wiki系列] openmp/samp 关键字：指令</h2><br />
<br />
<span style="font-weight: bold;" class="mycode_b">来自 SA-MP Wiki</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">目录</h3><br />
<ul class="mycode_list"><li><a href="http://#assert" target="_blank" rel="noopener" class="mycode_url">1 #assert</a><br />
</li>
<li><a href="http://#define" target="_blank" rel="noopener" class="mycode_url">2 #define</a><br />
</li>
<li><a href="http://#else" target="_blank" rel="noopener" class="mycode_url">3 #else</a><br />
</li>
<li><a href="http://#elseif" target="_blank" rel="noopener" class="mycode_url">4 #elseif</a><br />
</li>
<li><a href="http://#emit" target="_blank" rel="noopener" class="mycode_url">5 #emit</a><br />
</li>
<li><a href="http://#endif" target="_blank" rel="noopener" class="mycode_url">6 #endif</a><br />
</li>
<li><a href="http://#endinput-endscript" target="_blank" rel="noopener" class="mycode_url">7 #endinput , #endscript</a><br />
</li>
<li><a href="http://#error" target="_blank" rel="noopener" class="mycode_url">8 #error</a><br />
</li>
<li><a href="http://#if" target="_blank" rel="noopener" class="mycode_url">9 #if</a><br />
</li>
<li><a href="http://#include" target="_blank" rel="noopener" class="mycode_url">10 #include</a><br />
</li>
<li><a href="http://#pragma" target="_blank" rel="noopener" class="mycode_url">11 #pragma</a><br />
</li>
<li><a href="http://#pragma-information" target="_blank" rel="noopener" class="mycode_url">11.1 说明</a><br />
</li>
<li><a href="http://#pragma-list" target="_blank" rel="noopener" class="mycode_url">11.2 列表</a><br />
</li>
<li><a href="http://#pragma-examples" target="_blank" rel="noopener" class="mycode_url">11.3 示例</a><br />
</li>
<li><a href="http://#pragma-deprecated" target="_blank" rel="noopener" class="mycode_url">11.3.1 已弃用（Deprecated）</a><br />
</li>
<li><a href="http://#tryinclude" target="_blank" rel="noopener" class="mycode_url">12 #tryinclude</a><br />
</li>
<li><a href="http://#undef" target="_blank" rel="noopener" class="mycode_url">13 #undef</a><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#assert</h3><br />
<br />
此指令会检查常量表达式是否为真，如果不为真则停止编译。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 10<br />
#assert MOO &gt; 5</code></div></div><br />
以上代码可以正常编译。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 1<br />
#assert MOO &gt; 5</code></div></div><br />
以上代码无法编译，会产生致命错误。<br />
<br />
这类似于：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 1<br />
#if MOO &lt;= 5<br />
    #error Moo check failed<br />
#endif</code></div></div><br />
但是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#assert</code> 会给出以下错误信息：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"Assertation failed: 1 &gt; 5"</code></div></div><br />
而第二种写法会给出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"User error: Moo check failed"</code></div></div><br />
哪种错误信息更实用，则视情况而定。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#define</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code> 是一个文本替换指令。只要在代码中找到被定义的符号（宏名），就会将其替换为定义的内容。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 7<br />
printf("%d", MOO);</code></div></div><br />
会被替换为：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printf("%d", 7);</code></div></div><br />
这也是为什么反编译后的代码中看不到任何 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code>，因为所有指令都在预处理器阶段处理完毕。定义的内容不一定是数字：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define PL new i = 0; i &lt; MAX_PLAYERS; i++) if (IsPlayerConnected(i)<br />
for (PL)<br />
{<br />
    printf("%d connected", i);<br />
}</code></div></div><br />
会编译成大家熟悉（或讨厌）的玩家循环。注意括号的使用：一部分来自 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">for</code> 语句，一部分来自宏本身。<br />
<br />
另一个鲜为人知的特性是：定义可以跨行（通过在行尾加上反斜杠 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\</code> 来转义换行）。一般来说换行会结束定义，但下面这样是有效的：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define PL &#92;<br />
    new i = 0; i &lt; MAX_PLAYERS; i++) &#92;<br />
        if (IsPlayerConnected(i)<br />
for (PL)<br />
{<br />
    printf("%d connected", i);<br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\</code> 字符表示定义继续到下一行。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code> 的第三个重要特性是支持参数（宏参数）。参数用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">%0</code> 到 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">%9</code> 表示，用法与普通函数参数类似：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO(%0) &#92;<br />
    ((%0) * 7)<br />
printf("%d", MOO(6));</code></div></div><br />
输出结果为 42（不是随意选的）。注意宏里多余的括号——这是因为宏是纯文本替换，所以实际编译成：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printf("%d", ((6) * 7));</code></div></div><br />
这样是安全的。但看下面这个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printf("%d", MOO(5 + 6));</code></div></div><br />
你会期望结果是 77（(5 + 6) * 7）。加上括号后确实如此；如果去掉括号：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO(%0) &#92;<br />
    %0 * 7<br />
printf("%d", MOO(5 + 6));</code></div></div><br />
实际会变成：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printf("%d", 5 + 6 * 7);</code></div></div><br />
由于运算优先级（BODMAS），结果变为 47（5 + (6 * 7)），这就完全错误了。<br />
<br />
关于参数还有一个有趣的事实：如果传入的参数数量超过定义的数量，最后一个参数会包含所有多余的部分。例如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define PP(%0,%1) &#92;<br />
    printf(%0, %1)<br />
PP("%s %s %s", "hi", "hello", "hi");</code></div></div><br />
实际会打印：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>hi hello hi</code></div></div><br />
因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">%1</code> 包含了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">"hi", "hello", "hi"</code>。你可能还注意到 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#</code> 可以把字面量转换成字符串，这是 openmp(samp) 特有的功能，这里只是为了区分参数。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#else</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#else</code> 相当于普通 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else</code>，但用于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 条件。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#elseif</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#elseif</code> 相当于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code>，但用于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 条件。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 10<br />
#if MOO == 9<br />
    printf("if");<br />
#elseif MOO == 8<br />
    printf("else if");<br />
#else<br />
    printf("else");<br />
#endif</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#emit</h3><br />
<br />
此指令在 pawn-lang.pdf 的表格中并未列出，但实际存在。它相当于内联汇编器，如果你熟悉 AMX 字节码，可以用它直接插入 AMX 操作码。唯一限制是每次只能带一个参数。<br />
<br />
语法：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#emit &lt;opcode&gt; &lt;argument&gt;</code><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">&lt;argument&gt;</code> 可以是小数、整数或（局部/全局）符号（变量、函数、标签）。<br />
<br />
操作码列表及其含义可在 Pawn Toolkit ver. 3664 中找到。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#endif</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#endif</code> 相当于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 的结束括号。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 不使用大括号，所有条件内容一直持续到对应的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#endif</code>。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#endinput , #endscript</h3><br />
<br />
此指令停止当前文件的包含（不再继续读取该文件）。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#error</h3><br />
<br />
此指令立即停止编译，并输出自定义错误信息。示例见 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#assert</code>。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#if</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 是预处理器版本的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code>。你可以精确控制哪些代码被编译、哪些不被编译。例如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define LIMIT 10<br />
if (LIMIT &lt; 10)<br />
{<br />
    printf("Limit too low");<br />
}</code></div></div><br />
会编译成：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>if (10 &lt; 10)<br />
{<br />
    printf("Limit too low");<br />
}</code></div></div><br />
编译器知道这个条件永远为假，因此会给出“常量表达式”警告。但既然永远不会成立，为什么还要保留这段代码呢？你可以直接删掉，但之后别人修改 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">LIMIT</code> 重新编译时就无法检查了。这就是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 的作用。<br />
<br />
普通 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 在常量表达式时会警告，而 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> <span style="font-weight: bold;" class="mycode_b">必须</span> 是常量表达式：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define LIMIT 10<br />
#if LIMIT &lt; 10<br />
    #error Limit too low<br />
#endif</code></div></div><br />
这样会在编译时就检查限制是否过小，如果是则直接报错，而不用运行脚本测试。同时也不会生成多余的代码。注意 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 不强制使用括号（虽然复杂表达式可能需要）。<br />
<br />
另一个例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define LIMIT 10<br />
if (LIMIT &lt; 10)<br />
{<br />
    printf("Limit less than 10");<br />
}<br />
else<br />
{<br />
    printf("Limit equal to or above 10");<br />
}</code></div></div><br />
同样是常量检查，会产生警告，而且两个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 都会被编译（尽管我们知道只会执行一个）。用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 改写后：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define LIMIT 10<br />
#if LIMIT &lt; 10<br />
    printf("Limit less than 10");<br />
#else<br />
    printf("Limit equal to or above 10");<br />
#endif</code></div></div><br />
这样只有需要的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 会被编译，另一个仍保留在源代码中（方便以后改 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">LIMIT</code>），但不会占用最终编译后的代码空间，也不会每次运行都执行无用的判断。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#include</h3><br />
<br />
此指令会把指定文件的所有代码插入到 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#include</code> 所在的位置。有两种包含方式：相对路径（用双引号）和系统路径（用尖括号，我自己起的名称，如果你有更好的叫法请告诉我）。<br />
<br />
相对包含使用双引号，路径相对于当前文件：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include "me.pwn"</code></div></div><br />
会包含与当前文件同目录下的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">me.pwn</code>。<br />
<br />
系统包含使用尖括号，从 Pawn 编译器所在目录下的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">include</code> 文件夹（或其父目录的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">include</code> 文件夹）中查找：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;me&gt;</code></div></div><br />
会包含 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">qawno/include/me.inc</code>（注意没有扩展名；如果文件不是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.p</code> 或 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.inc</code>，可以指定扩展名）。<br />
<br />
两种方式都支持子目录：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include "folder/me.pwn"<br />
#include &lt;folder/me&gt;</code></div></div><br />
如果文件不存在，编译会立即失败。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#pragma</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">说明</h4><br />
<br />
这是最复杂的指令之一。它提供了一系列选项来控制脚本的编译行为。例如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#pragma ctrlchar '&#36;'</code></div></div><br />
会把转义字符从 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\</code> 改成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">&#36;</code>，所以换行符不再是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">"\r\n"</code>，而是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">"&#36;r&#36;n"</code>。<br />
<br />
很多选项原本是为嵌入式系统设计的，用来限制 PC 上几乎无限制的资源。这里只列出与 openmp(samp) 相关的选项（完整列表见 pawn-lang.pdf）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">列表</h4><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">名称</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">值</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">说明</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">codepage</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">名称/值</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">设置字符串使用的 Unicode 码页</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">compress</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">1/0</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">openmp(samp) 不支持，请勿使用</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">deprecated</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">符号名称</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">如果使用该符号会产生警告，用于提示有更好的替代版本</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">dynamic</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">值（通常是 2 的幂）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">设置栈和堆内存大小（单位：cells）。出现“excessive memory usage”警告时需要设置</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">library</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">dll 名称</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">在 openmp(samp) 中经常被误用。它指定本文件中的原生函数来自哪个 DLL，并非把文件定义为库</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">pack</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">1/0</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">交换 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">!""</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">""</code> 的含义（详见 pawn-lang.pdf 中的打包字符串说明）</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">tabsize</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">值</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">经常被误用。用于设置制表符宽度，避免因空格和制表符混用产生的警告。openmp(samp) 默认设为 4（qawno 编辑器中制表符宽度）。设为 0 会关闭所有缩进警告，但强烈不推荐（会导致代码难以阅读）</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">unused</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">符号名称</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">类似 deprecated，用于抑制“symbol is never used”警告。推荐使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">stock</code>，但某些情况（如函数参数）无法使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">stock</code> 时才用此方式</td>
  </tr>
</table>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">示例</h4><br />
<br />
<h5 style="font-size:1.05em;font-weight:bold;margin:10px 0 4px;color:#444;">已弃用（Deprecated）</h5><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    gOldVariable = 5;<br />
#pragma deprecated gOldVariable<br />
main()<br />
{<br />
    printf("%d", gOldVariable);<br />
}</code></div></div><br />
使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gOldVariable</code> 时会产生警告，提示不应再使用它。主要用于函数更新 API 时保留向下兼容性。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#tryinclude</h3><br />
<br />
类似于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#include</code>，但如果文件不存在，编译不会失败。这非常适合根据用户是否安装了特定插件（或插件的 include 文件）来选择性包含功能。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">myinc.inc：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#if defined _MY_INC_INC<br />
    #endinput<br />
#endif<br />
#define _MY_INC_INC<br />
stock MyIncFunc()<br />
{<br />
    printf("Hello");<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">主脚本：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#tryinclude &lt;myinc&gt;<br />
main()<br />
{<br />
    #if defined _MY_INC_INC<br />
        MyIncFunc();<br />
    #endif<br />
}</code></div></div><br />
只有当 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">myinc.inc</code> 存在并被成功包含时，才会调用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MyIncFunc()</code>。这对 IRC 插件等需要检测插件是否安装的情况非常有用。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">#undef</h3><br />
<br />
移除之前定义的宏或常量符号。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MOO 10<br />
printf("%d", MOO);<br />
#undef MOO<br />
printf("%d", MOO);</code></div></div><br />
第二个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf</code> 会编译失败，因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MOO</code> 已被取消定义。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum<br />
{<br />
    e_example = 300<br />
};<br />
printf("%d", e_example);<br />
#undef e_example<br />
printf("%d", e_example); // 致命错误</code></div></div><hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[wiki系列] openmp/samp 关键字：运算符]]></title>
			<link>https://open-mp.cn/showthread.php?tid=22</link>
			<pubDate>Sat, 21 Mar 2026 23:06:11 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=22</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">[wiki系列] openmp/samp 关键字：运算符</h2><br />
<br />
<span style="font-weight: bold;" class="mycode_b">来自 SA-MP Wiki</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">目录</h3><br />
<ul class="mycode_list"><li><a href="http://#char" target="_blank" rel="noopener" class="mycode_url">1 char</a><br />
</li>
<li><a href="http://#defined" target="_blank" rel="noopener" class="mycode_url">2 defined</a><br />
</li>
<li><a href="http://#sizeof" target="_blank" rel="noopener" class="mycode_url">3 sizeof</a><br />
</li>
<li><a href="http://#state" target="_blank" rel="noopener" class="mycode_url">4 state</a><br />
</li>
<li><a href="http://#tagof" target="_blank" rel="noopener" class="mycode_url">5 tagof</a><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">char</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">char</code> 返回存放给定数量<span style="font-weight: bold;" class="mycode_b">字符</span>（打包字符串）所需的 <span style="font-weight: bold;" class="mycode_b">cells</span> 数量。  <br />
即：存放给定字节数所需的 4 字节 cells 数量。<br />
<br />
示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>4 char</code></div></div><br />
返回 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1</code>。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>3 char</code></div></div><br />
返回 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1</code>（你不能拥有 3/4 个变量）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>256 char</code></div></div><br />
返回 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">64</code>（256 ÷ 4）。<br />
<br />
此运算符通常用于变量声明：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    someVar[40 char];</code></div></div><br />
会创建一个<span style="font-weight: bold;" class="mycode_b">10 cells</span>大小的数组。<br />
<br />
更多关于打包字符串（packed strings）的细节，请阅读 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pawn-lang.pdf</code>。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">defined</h3><br />
<br />
检查一个符号（symbol）是否存在。通常用于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 语句：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    someVar = 5;<br />
#if defined someVar<br />
    printf("%d", someVar);<br />
#else<br />
    #error The variable 'someVar' isn't defined<br />
#endif</code></div></div><br />
最常见的用法是检查某个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code> 是否存在，并据此生成不同代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define FILTERSCRIPT<br />
#if defined FILTERSCRIPT<br />
public OnFilterScriptInit()<br />
{<br />
    return 1;<br />
}<br />
#else<br />
public OnGameModeInit()<br />
{<br />
    return 1;<br />
}<br />
#endif</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">sizeof</h3><br />
<br />
返回数组<span style="font-weight: bold;" class="mycode_b">元素</span>（ELEMENTS）的数量：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    someVar[10];<br />
printf("%d", sizeof (someVar));</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>10</code></div></div><br />
二维数组示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    someVar[2][10];<br />
printf("%d %d", sizeof (someVar), sizeof (someVar[]));</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>2 10</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">state</h3><br />
<br />
此关键字与 PAWN 自动机（autonoma）代码相关，因此本文不做介绍。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">tagof</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">tagof</code> 返回一个代表变量<span style="font-weight: bold;" class="mycode_b">标签</span>（tag）的数字：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    someVar,<br />
    Float:someFloat;<br />
printf("%d %d", tagof (someVar), tagof (someFloat));</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>-./,)),(-*,( -1073741820</code></div></div><br />
这其实是一个轻微的显示 bug，但本质上代表：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>0x80000000 0xC0000004</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">实际应用：检查变量是否为 Float</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new Float: fValue = 6.9;<br />
new tag = tagof (fValue);<br />
if (tag == tagof (Float:))<br />
    print("float");<br />
else<br />
    print("not a float");</code></div></div><hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">[wiki系列] openmp/samp 关键字：运算符</h2><br />
<br />
<span style="font-weight: bold;" class="mycode_b">来自 SA-MP Wiki</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">目录</h3><br />
<ul class="mycode_list"><li><a href="http://#char" target="_blank" rel="noopener" class="mycode_url">1 char</a><br />
</li>
<li><a href="http://#defined" target="_blank" rel="noopener" class="mycode_url">2 defined</a><br />
</li>
<li><a href="http://#sizeof" target="_blank" rel="noopener" class="mycode_url">3 sizeof</a><br />
</li>
<li><a href="http://#state" target="_blank" rel="noopener" class="mycode_url">4 state</a><br />
</li>
<li><a href="http://#tagof" target="_blank" rel="noopener" class="mycode_url">5 tagof</a><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">char</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">char</code> 返回存放给定数量<span style="font-weight: bold;" class="mycode_b">字符</span>（打包字符串）所需的 <span style="font-weight: bold;" class="mycode_b">cells</span> 数量。  <br />
即：存放给定字节数所需的 4 字节 cells 数量。<br />
<br />
示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>4 char</code></div></div><br />
返回 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1</code>。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>3 char</code></div></div><br />
返回 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1</code>（你不能拥有 3/4 个变量）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>256 char</code></div></div><br />
返回 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">64</code>（256 ÷ 4）。<br />
<br />
此运算符通常用于变量声明：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    someVar[40 char];</code></div></div><br />
会创建一个<span style="font-weight: bold;" class="mycode_b">10 cells</span>大小的数组。<br />
<br />
更多关于打包字符串（packed strings）的细节，请阅读 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">pawn-lang.pdf</code>。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">defined</h3><br />
<br />
检查一个符号（symbol）是否存在。通常用于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#if</code> 语句：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    someVar = 5;<br />
#if defined someVar<br />
    printf("%d", someVar);<br />
#else<br />
    #error The variable 'someVar' isn't defined<br />
#endif</code></div></div><br />
最常见的用法是检查某个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code> 是否存在，并据此生成不同代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define FILTERSCRIPT<br />
#if defined FILTERSCRIPT<br />
public OnFilterScriptInit()<br />
{<br />
    return 1;<br />
}<br />
#else<br />
public OnGameModeInit()<br />
{<br />
    return 1;<br />
}<br />
#endif</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">sizeof</h3><br />
<br />
返回数组<span style="font-weight: bold;" class="mycode_b">元素</span>（ELEMENTS）的数量：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    someVar[10];<br />
printf("%d", sizeof (someVar));</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>10</code></div></div><br />
二维数组示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    someVar[2][10];<br />
printf("%d %d", sizeof (someVar), sizeof (someVar[]));</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>2 10</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">state</h3><br />
<br />
此关键字与 PAWN 自动机（autonoma）代码相关，因此本文不做介绍。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">tagof</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">tagof</code> 返回一个代表变量<span style="font-weight: bold;" class="mycode_b">标签</span>（tag）的数字：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    someVar,<br />
    Float:someFloat;<br />
printf("%d %d", tagof (someVar), tagof (someFloat));</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>-./,)),(-*,( -1073741820</code></div></div><br />
这其实是一个轻微的显示 bug，但本质上代表：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>0x80000000 0xC0000004</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">实际应用：检查变量是否为 Float</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new Float: fValue = 6.9;<br />
new tag = tagof (fValue);<br />
if (tag == tagof (Float:))<br />
    print("float");<br />
else<br />
    print("not a float");</code></div></div><hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[wiki系列] openmp/samp 关键字：初始值设定项]]></title>
			<link>https://open-mp.cn/showthread.php?tid=21</link>
			<pubDate>Sat, 21 Mar 2026 23:05:31 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=21</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">[wiki系列] openmp/samp 关键字：初始值设定项</h2><br />
<br />
<span style="font-weight: bold;" class="mycode_b">来自 SA-MP Wiki</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">目录</h3><br />
<ul class="mycode_list"><li><a href="http://#const" target="_blank" rel="noopener" class="mycode_url">1 const</a><br />
</li>
<li><a href="http://#enum" target="_blank" rel="noopener" class="mycode_url">2 enum</a><br />
</li>
<li><a href="http://#forward" target="_blank" rel="noopener" class="mycode_url">3 forward</a><br />
</li>
<li><a href="http://#native" target="_blank" rel="noopener" class="mycode_url">4 native</a><br />
</li>
<li><a href="http://#new" target="_blank" rel="noopener" class="mycode_url">5 new</a><br />
</li>
<li><a href="http://#operator" target="_blank" rel="noopener" class="mycode_url">6 operator</a><br />
</li>
<li><a href="http://#public" target="_blank" rel="noopener" class="mycode_url">7 public</a><br />
</li>
<li><a href="http://#static" target="_blank" rel="noopener" class="mycode_url">8 static</a><br />
</li>
<li><a href="http://#stock" target="_blank" rel="noopener" class="mycode_url">9 stock</a><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">const</h3><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new const<br />
    MY_CONSTANT[] = {1, 2, 3};</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 并不常用，但它用于声明一个<span style="font-weight: bold;" class="mycode_b">无法被代码修改</span>的变量。它的用途包括：让函数的数组参数编译得更高效，或者创建一个类似 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code> 但却是数组的常量。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 是一个修饰符，必须与 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 或其他变量声明关键字搭配使用。如果你尝试修改 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 变量，编译器会报错。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">enum</h3><br />
<br />
枚举（enum）是一个非常实用的系统，用于表示大量数据并快速修改常量。主要用途有三类：<ul class="mycode_list"><li>替代一大堆 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code> 语句<br />
</li>
<li>用符号名称表示数组下标（其实本质相同，只是写法不同）<br />
</li>
<li>创建新的标签（tag）<br />
</li>
</ul>
<br />
最常见的用法是定义数组结构：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_MY_ARRAY<br />
{<br />
    E_MY_ARRAY_MONEY,<br />
    E_MY_ARRAY_GUN<br />
}<br />
new<br />
    gPlayerData[MAX_PLAYERS][E_MY_ARRAY];<br />
public OnPlayerConnect(playerid)<br />
{<br />
    gPlayerData[playerid][E_MY_ARRAY_MONEY] = 0;<br />
    gPlayerData[playerid][E_MY_ARRAY_GUN] = 5;<br />
}</code></div></div><br />
这会为每个玩家创建一个包含两个槽位的数组。连接时，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_MY_ARRAY_MONEY</code> 槽位设为 0，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_MY_ARRAY_GUN</code> 槽位设为 5。<br />
<br />
如果不用 enum，代码会变成这样：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    gPlayerData[MAX_PLAYERS][2];<br />
public OnPlayerConnect(playerid)<br />
{<br />
    gPlayerData[playerid][0] = 0;<br />
    gPlayerData[playerid][1] = 5;<br />
}</code></div></div><br />
可读性明显变差——下标 0 和 1 分别代表什么？而且扩展性差：如果要在中间插入一个新槽位，就得手动把所有 1 改成 2，非常容易出错。而使用 enum，只需添加一行：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_MY_ARRAY<br />
{<br />
    E_MY_ARRAY_MONEY,<br />
    E_MY_ARRAY_AMMO,<br />
    E_MY_ARRAY_GUN<br />
}<br />
new<br />
    gPlayerData[MAX_PLAYERS][E_MY_ARRAY];<br />
public OnPlayerConnect(playerid)<br />
{<br />
    gPlayerData[playerid][E_MY_ARRAY_MONEY] = 0;<br />
    gPlayerData[playerid][E_MY_ARRAY_AMMO] = 100;<br />
    gPlayerData[playerid][E_MY_ARRAY_GUN] = 5;<br />
}</code></div></div><br />
重新编译后，所有索引自动更新。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">enum 的完整格式与工作原理</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum NAME (modifier)<br />
{<br />
    NAME_ENTRY_1 = value,<br />
    NAME_ENTRY_2 = value,<br />
    ...<br />
    NAME_ENTRY_N = value<br />
}</code></div></div><br />
大部分内容是隐含的。默认 modifier 为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">(+= 1)</code>，表示每个值都是前一个值 + 1：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_EXAMPLE<br />
{<br />
    E_EXAMPLE_0,<br />
    E_EXAMPLE_1,<br />
    E_EXAMPLE_2<br />
}</code></div></div><br />
结果：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_0 = 0</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_1 = 1</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_2 = 2</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE = 3</code>（枚举名本身等于最后一个值）。<br />
<br />
修改 modifier 的例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_EXAMPLE (+= 5)<br />
{<br />
    E_EXAMPLE_0,<br />
    E_EXAMPLE_1,<br />
    E_EXAMPLE_2<br />
}</code></div></div><br />
结果：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0, 5, 10, 15</code>。如果声明 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new gEnumArray[E_EXAMPLE];</code>，数组大小为 15，但只能通过枚举名访问 0、5、10（仍可使用普通数字访问）。<br />
<br />
另一个例子（乘法）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_EXAMPLE (*= 2)<br />
{<br />
    E_EXAMPLE_0,<br />
    E_EXAMPLE_1,<br />
    E_EXAMPLE_2<br />
}</code></div></div><br />
全部变为 0。解决方法是手动指定初始值：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_EXAMPLE (*= 2)<br />
{<br />
    E_EXAMPLE_0 = 1,<br />
    E_EXAMPLE_1,<br />
    E_EXAMPLE_2<br />
}</code></div></div><br />
结果：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1, 2, 4, 8</code>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">提示</span>：数组用途时强烈建议只用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">+= 1</code>，其他 modifier 容易导致混乱。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">enum 中可以包含数组</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_EXAMPLE<br />
{<br />
    E_EXAMPLE_0[10],<br />
    E_EXAMPLE_1,<br />
    E_EXAMPLE_2<br />
}</code></div></div><br />
结果：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_0 = 0</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_1 = 10</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_2 = 11</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE = 12</code>（而不是很多人以为的 0、1、2、3）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">enum 项可以带标签</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_MY_ARRAY<br />
{<br />
    E_MY_ARRAY_MONEY,<br />
    E_MY_ARRAY_AMMO,<br />
    Float:E_MY_ARRAY_HEALTH,<br />
    E_MY_ARRAY_GUN<br />
}<br />
new<br />
    gPlayerData[MAX_PLAYERS][E_MY_ARRAY];<br />
public OnPlayerConnect(playerid)<br />
{<br />
    gPlayerData[playerid][E_MY_ARRAY_MONEY] = 0;<br />
    gPlayerData[playerid][E_MY_ARRAY_AMMO] = 100;<br />
    gPlayerData[playerid][E_MY_ARRAY_GUN] = 5;<br />
    gPlayerData[playerid][E_MY_ARRAY_HEALTH] = 50.0;  // 不会产生标签不匹配警告<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">enum 本身也可以作为标签使用（位标志）</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_MY_TAG (&lt;&lt;= 1)<br />
{<br />
    E_MY_TAG_NONE,<br />
    E_MY_TAG_VAL_1 = 1,<br />
    E_MY_TAG_VAL_2,<br />
    E_MY_TAG_VAL_3,<br />
    E_MY_TAG_VAL_4<br />
}<br />
new<br />
    E_MY_TAG:gMyTagVar = E_MY_TAG_VAL_2 | E_MY_TAG_VAL_3;</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gMyTagVar</code> 值为 6（4 | 2），并带有自定义标签。直接赋值 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gMyTagVar = 7;</code> 会产生标签不匹配警告，但可以用强制转换绕过：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>gMyTagVar = E_MY_TAG:7;</code></div></div><br />
进阶用法（掩码 + 组合）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_MY_TAG (&lt;&lt;= 1)<br />
{<br />
    E_MY_TAG_NONE,<br />
    E_MY_TAG_MASK = 0xFF,<br />
    E_MY_TAG_VAL_1 = 0x100,<br />
    E_MY_TAG_VAL_2,<br />
    E_MY_TAG_VAL_3,<br />
    E_MY_TAG_VAL_4<br />
}<br />
new<br />
    E_MY_TAG:gMyTagVar = E_MY_TAG_VAL_2 | E_MY_TAG_VAL_3 | (E_MY_TAG:7 &amp; E_MY_TAG_MASK);</code></div></div><br />
结果为 1543（0x0607）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">用无名 enum 替代 #define</h4><br />
<br />
传统写法：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define TEAM_NONE  0<br />
#define TEAM_COP    1<br />
#define TEAM_ROBBER 2<br />
#define TEAM_CIV    3<br />
#define TEAM_CLERK  4<br />
#define TEAM_DRIVER 5</code></div></div><br />
改用 enum 自动赋值：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum<br />
{<br />
    TEAM_NONE,<br />
    TEAM_COP,<br />
    TEAM_ROBBER,<br />
    TEAM_CIV,<br />
    TEAM_CLERK,<br />
    TEAM_DRIVER<br />
}</code></div></div><br />
值完全相同，使用方式也一样。<br />
<br />
更强大的位标志写法（推荐）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum (&lt;&lt;= 1)<br />
{<br />
    TEAM_NONE,<br />
    TEAM_COP = 1,<br />
    TEAM_ROBBER,<br />
    TEAM_CIV,<br />
    TEAM_CLERK,<br />
    TEAM_DRIVER,<br />
    TEAM_ADMIN<br />
}</code></div></div><br />
现在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">TEAM_COP = 1</code>（二进制 00000001）、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">TEAM_ROBBER = 2</code>（00000010）等。一个变量就能同时表示多个团队：<br />
<ul class="mycode_list"><li>添加团队：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gPlayerTeam[playerid] |= TEAM_COP;</code><br />
</li>
<li>移除团队：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gPlayerTeam[playerid] &amp;= ~TEAM_COP;</code><br />
</li>
<li>检查是否在团队：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (gPlayerTeam[playerid] &amp; TEAM_COP)</code><br />
</li>
</ul>
<br />
非常简洁且强大。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">forward</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">forward</code> 用于告诉编译器“这个函数稍后会定义”。所有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 函数都<span style="font-weight: bold;" class="mycode_b">必须</span> forward，也可以用于其他地方。<br />
<br />
语法：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward MyPublicFunction(playerid, const string[]);</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward MyPublicFunction(playerid, const string[]);<br />
public MyPublicFunction(playerid, const string[])<br />
{<br />
}</code></div></div><br />
除了 public 函数外，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">forward</code> 还能解决一种罕见的“reparse”警告（当函数返回带标签的值如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Float</code> 时，在声明前被调用）：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">有警告的写法：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main()<br />
{<br />
    new Float:myVar = MyFloatFunction();<br />
}<br />
Float:MyFloatFunction()<br />
{<br />
    return 5.0;<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">解决方法 1（函数前置）：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>Float:MyFloatFunction()<br />
{<br />
    return 5.0;<br />
}<br />
main()<br />
{<br />
    new Float:myVar = MyFloatFunction();<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">解决方法 2（forward）：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward Float:MyFloatFunction();<br />
main()<br />
{<br />
    new Float:myVar = MyFloatFunction();<br />
}<br />
Float:MyFloatFunction()<br />
{<br />
    return 5.0;<br />
}</code></div></div><br />
注意：forward 也要带返回值标签。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">native</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">native</code> 函数是由虚拟机（openmp(samp) 服务器或插件）提供的函数，而不是脚本自己定义的。你只能声明已存在于 openmp(samp) 或插件中的 native。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">用途 1</span>：让自定义函数出现在 qawno 右侧函数列表中（即使是假的）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/*<br />
native MyFunction(playerid);<br />
*/</code></div></div><br />
注释会被 qawno 识别加入列表，但编译器会忽略。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">用途 2</span>：重命名 / 重载函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>native my_print(const string[]) = print;</code></div></div><br />
现在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code> 函数在脚本中已不存在（但服务器内部仍存在）。你可以重新定义它：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>print(const string[])<br />
{<br />
    my_print("Someone called print()");<br />
    my_print(string);<br />
}</code></div></div><br />
以后所有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print()</code> 调用都会先执行你的代码，再调用原函数。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">new</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 是变量声明的核心关键字之一。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    myVar = 5;</code></div></div><br />
创建变量并赋值为 5。未赋值时默认为 0：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new myVar;<br />
printf("%d", myVar);  // 输出 0</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">作用域</span>（scope）由大括号 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">{}</code> 决定，声明在括号内的变量只能在该括号内使用。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>if (a == 1)<br />
{<br />
    new myVar = 5;<br />
    printf("%d", myVar);        // 可以<br />
    if (myVar == 1)<br />
    {<br />
        printf("%d", myVar);    // 可以<br />
    }<br />
}<br />
// 这里无法使用 myVar，会报错<br />
printf("%d", myVar);</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">全局变量</span>（在函数外声明）从声明位置之后可在整个脚本中使用（包括 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#include</code> 的其他文件）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">static</span> 与 <span style="font-weight: bold;" class="mycode_b">new</span> 的区别详见下方 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 部分。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">operator</h3><br />
<br />
允许为自定义标签重载运算符。<br />
<br />
示例（大端序转换）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>stock BigEndian:operator=(b)<br />
{<br />
    return BigEndian:(((b &gt;&gt;&gt; 24) &amp; 0x000000FF) | ((b &gt;&gt;&gt; 8) &amp; 0x0000FF00) | ((b &lt;&lt; 8) &amp; 0x00FF0000) | ((b &lt;&lt; 24) &amp; 0xFF000000));<br />
}<br />
main()<br />
{<br />
    new BigEndian:a = 7;<br />
    printf("%d", _:a);  // 输出 117440512（因为小端序读取大端序数据）<br />
}</code></div></div><br />
可重载的运算符：<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">+, -, *, /, %, ++, --, ==, !=, &lt;, &gt;, &lt;=, &gt;=, !, =</code><br />
<br />
你可以让运算符做任何事（不一定是原本功能）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>stock BigEndian:operator+(BigEndian:a, BigEndian:b)<br />
{<br />
    return BigEndian:42;<br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a + b</code> 永远返回 42。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">public</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 让函数对虚拟机可见，允许 openmp(samp) 服务器从外部直接调用（而非仅在脚本内部调用）。也可用于变量（允许服务器读写），但 openmp(samp) 中极少使用。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 函数的名称会存储在 .amx 文件中（普通函数只存地址），这也是反编译的难点之一。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">通过名称调用 public 函数：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward MyPublicFunc();<br />
main()<br />
{<br />
    CallLocalFunction("MyPublicFunc", "");<br />
}<br />
public MyPublicFunc()<br />
{<br />
    printf("Hello");<br />
}</code></div></div><br />
也可使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">@</code> 前缀：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward MyPublicFunc();<br />
forward @MyOtherPublicFunc(var);<br />
main()<br />
{<br />
    CallLocalFunction("MyPublicFunc", "");<br />
    SetTimerEx("@MyOtherPublicFunc", 5000, 0, "i", 7);<br />
}<br />
public MyPublicFunc()<br />
{<br />
    printf("Hello");<br />
}<br />
@MyOtherPublicFunc(var)<br />
{<br />
    printf("%d", var);<br />
}</code></div></div><br />
所有 openmp(samp) 回调（如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerConnect</code>）都是 public，由服务器自动调用。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 函数也可以像普通函数一样直接调用（速度更快）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward MyPublicFunc();<br />
main()<br />
{<br />
    MyPublicFunc();  // 直接调用，比 CallLocalFunction 快<br />
}<br />
public MyPublicFunc()<br />
{<br />
    printf("Hello");<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">static</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 全局变量类似 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code>，但作用域更小（仅限于声明所在的文件或 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#section</code>）。<br />
<br />
对比 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 的跨文件可见性，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 仅限本文件：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// file2.pwn 中无法访问 file1.pwn 里的 static 变量</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">局部 static</span>：作用域与 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 相同（仅大括号内），但<span style="font-weight: bold;" class="mycode_b">值在函数多次调用间保留</span>（不像 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 每次重置）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>MyFunc()<br />
{<br />
    new i = 0;<br />
    printf("%d", i);<br />
    i++;<br />
    printf("%d", i);<br />
}</code></div></div><br />
调用 4 次输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>0 1<br />
0 1<br />
0 1<br />
0 1</code></div></div><br />
改为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 后：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>0 1<br />
1 2<br />
2 3<br />
3 4</code></div></div><br />
初始化值仅在<span style="font-weight: bold;" class="mycode_b">第一次</span>调用时生效。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 函数只能在声明所在文件中调用，适合“私有”函数。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">stock</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">stock</code> 用于声明可能不会被使用的变量或函数，避免产生“unused”警告。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new stock<br />
    gMayBeUsedVar;<br />
static stock<br />
    g_sMayBeUsedVar;</code></div></div><br />
如果被使用则编译保留；如果未使用则<span style="font-weight: bold;" class="mycode_b">完全剔除</span>（不像 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#pragma unused</code> 只隐藏警告）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">最常见用途</span>：编写库时。库作者无法预知用户会用哪些函数，使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">stock</code> 可避免大量无用警告。<br />
<br />
```pawn<br />
stock Func1()<br />
{<br />
printf("Hello");<br />
}<br />
<br />
stock Func2()<br />
{<br />
printf("Hi");<br />
}<br />
<br />
<hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">[wiki系列] openmp/samp 关键字：初始值设定项</h2><br />
<br />
<span style="font-weight: bold;" class="mycode_b">来自 SA-MP Wiki</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">目录</h3><br />
<ul class="mycode_list"><li><a href="http://#const" target="_blank" rel="noopener" class="mycode_url">1 const</a><br />
</li>
<li><a href="http://#enum" target="_blank" rel="noopener" class="mycode_url">2 enum</a><br />
</li>
<li><a href="http://#forward" target="_blank" rel="noopener" class="mycode_url">3 forward</a><br />
</li>
<li><a href="http://#native" target="_blank" rel="noopener" class="mycode_url">4 native</a><br />
</li>
<li><a href="http://#new" target="_blank" rel="noopener" class="mycode_url">5 new</a><br />
</li>
<li><a href="http://#operator" target="_blank" rel="noopener" class="mycode_url">6 operator</a><br />
</li>
<li><a href="http://#public" target="_blank" rel="noopener" class="mycode_url">7 public</a><br />
</li>
<li><a href="http://#static" target="_blank" rel="noopener" class="mycode_url">8 static</a><br />
</li>
<li><a href="http://#stock" target="_blank" rel="noopener" class="mycode_url">9 stock</a><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">const</h3><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new const<br />
    MY_CONSTANT[] = {1, 2, 3};</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 并不常用，但它用于声明一个<span style="font-weight: bold;" class="mycode_b">无法被代码修改</span>的变量。它的用途包括：让函数的数组参数编译得更高效，或者创建一个类似 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code> 但却是数组的常量。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 是一个修饰符，必须与 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 或其他变量声明关键字搭配使用。如果你尝试修改 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 变量，编译器会报错。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">enum</h3><br />
<br />
枚举（enum）是一个非常实用的系统，用于表示大量数据并快速修改常量。主要用途有三类：<ul class="mycode_list"><li>替代一大堆 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#define</code> 语句<br />
</li>
<li>用符号名称表示数组下标（其实本质相同，只是写法不同）<br />
</li>
<li>创建新的标签（tag）<br />
</li>
</ul>
<br />
最常见的用法是定义数组结构：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_MY_ARRAY<br />
{<br />
    E_MY_ARRAY_MONEY,<br />
    E_MY_ARRAY_GUN<br />
}<br />
new<br />
    gPlayerData[MAX_PLAYERS][E_MY_ARRAY];<br />
public OnPlayerConnect(playerid)<br />
{<br />
    gPlayerData[playerid][E_MY_ARRAY_MONEY] = 0;<br />
    gPlayerData[playerid][E_MY_ARRAY_GUN] = 5;<br />
}</code></div></div><br />
这会为每个玩家创建一个包含两个槽位的数组。连接时，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_MY_ARRAY_MONEY</code> 槽位设为 0，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_MY_ARRAY_GUN</code> 槽位设为 5。<br />
<br />
如果不用 enum，代码会变成这样：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    gPlayerData[MAX_PLAYERS][2];<br />
public OnPlayerConnect(playerid)<br />
{<br />
    gPlayerData[playerid][0] = 0;<br />
    gPlayerData[playerid][1] = 5;<br />
}</code></div></div><br />
可读性明显变差——下标 0 和 1 分别代表什么？而且扩展性差：如果要在中间插入一个新槽位，就得手动把所有 1 改成 2，非常容易出错。而使用 enum，只需添加一行：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_MY_ARRAY<br />
{<br />
    E_MY_ARRAY_MONEY,<br />
    E_MY_ARRAY_AMMO,<br />
    E_MY_ARRAY_GUN<br />
}<br />
new<br />
    gPlayerData[MAX_PLAYERS][E_MY_ARRAY];<br />
public OnPlayerConnect(playerid)<br />
{<br />
    gPlayerData[playerid][E_MY_ARRAY_MONEY] = 0;<br />
    gPlayerData[playerid][E_MY_ARRAY_AMMO] = 100;<br />
    gPlayerData[playerid][E_MY_ARRAY_GUN] = 5;<br />
}</code></div></div><br />
重新编译后，所有索引自动更新。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">enum 的完整格式与工作原理</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum NAME (modifier)<br />
{<br />
    NAME_ENTRY_1 = value,<br />
    NAME_ENTRY_2 = value,<br />
    ...<br />
    NAME_ENTRY_N = value<br />
}</code></div></div><br />
大部分内容是隐含的。默认 modifier 为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">(+= 1)</code>，表示每个值都是前一个值 + 1：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_EXAMPLE<br />
{<br />
    E_EXAMPLE_0,<br />
    E_EXAMPLE_1,<br />
    E_EXAMPLE_2<br />
}</code></div></div><br />
结果：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_0 = 0</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_1 = 1</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_2 = 2</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE = 3</code>（枚举名本身等于最后一个值）。<br />
<br />
修改 modifier 的例子：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_EXAMPLE (+= 5)<br />
{<br />
    E_EXAMPLE_0,<br />
    E_EXAMPLE_1,<br />
    E_EXAMPLE_2<br />
}</code></div></div><br />
结果：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0, 5, 10, 15</code>。如果声明 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new gEnumArray[E_EXAMPLE];</code>，数组大小为 15，但只能通过枚举名访问 0、5、10（仍可使用普通数字访问）。<br />
<br />
另一个例子（乘法）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_EXAMPLE (*= 2)<br />
{<br />
    E_EXAMPLE_0,<br />
    E_EXAMPLE_1,<br />
    E_EXAMPLE_2<br />
}</code></div></div><br />
全部变为 0。解决方法是手动指定初始值：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_EXAMPLE (*= 2)<br />
{<br />
    E_EXAMPLE_0 = 1,<br />
    E_EXAMPLE_1,<br />
    E_EXAMPLE_2<br />
}</code></div></div><br />
结果：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">1, 2, 4, 8</code>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">提示</span>：数组用途时强烈建议只用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">+= 1</code>，其他 modifier 容易导致混乱。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">enum 中可以包含数组</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_EXAMPLE<br />
{<br />
    E_EXAMPLE_0[10],<br />
    E_EXAMPLE_1,<br />
    E_EXAMPLE_2<br />
}</code></div></div><br />
结果：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_0 = 0</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_1 = 10</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE_2 = 11</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">E_EXAMPLE = 12</code>（而不是很多人以为的 0、1、2、3）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">enum 项可以带标签</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_MY_ARRAY<br />
{<br />
    E_MY_ARRAY_MONEY,<br />
    E_MY_ARRAY_AMMO,<br />
    Float:E_MY_ARRAY_HEALTH,<br />
    E_MY_ARRAY_GUN<br />
}<br />
new<br />
    gPlayerData[MAX_PLAYERS][E_MY_ARRAY];<br />
public OnPlayerConnect(playerid)<br />
{<br />
    gPlayerData[playerid][E_MY_ARRAY_MONEY] = 0;<br />
    gPlayerData[playerid][E_MY_ARRAY_AMMO] = 100;<br />
    gPlayerData[playerid][E_MY_ARRAY_GUN] = 5;<br />
    gPlayerData[playerid][E_MY_ARRAY_HEALTH] = 50.0;  // 不会产生标签不匹配警告<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">enum 本身也可以作为标签使用（位标志）</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_MY_TAG (&lt;&lt;= 1)<br />
{<br />
    E_MY_TAG_NONE,<br />
    E_MY_TAG_VAL_1 = 1,<br />
    E_MY_TAG_VAL_2,<br />
    E_MY_TAG_VAL_3,<br />
    E_MY_TAG_VAL_4<br />
}<br />
new<br />
    E_MY_TAG:gMyTagVar = E_MY_TAG_VAL_2 | E_MY_TAG_VAL_3;</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gMyTagVar</code> 值为 6（4 | 2），并带有自定义标签。直接赋值 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gMyTagVar = 7;</code> 会产生标签不匹配警告，但可以用强制转换绕过：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>gMyTagVar = E_MY_TAG:7;</code></div></div><br />
进阶用法（掩码 + 组合）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum E_MY_TAG (&lt;&lt;= 1)<br />
{<br />
    E_MY_TAG_NONE,<br />
    E_MY_TAG_MASK = 0xFF,<br />
    E_MY_TAG_VAL_1 = 0x100,<br />
    E_MY_TAG_VAL_2,<br />
    E_MY_TAG_VAL_3,<br />
    E_MY_TAG_VAL_4<br />
}<br />
new<br />
    E_MY_TAG:gMyTagVar = E_MY_TAG_VAL_2 | E_MY_TAG_VAL_3 | (E_MY_TAG:7 &amp; E_MY_TAG_MASK);</code></div></div><br />
结果为 1543（0x0607）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">用无名 enum 替代 #define</h4><br />
<br />
传统写法：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define TEAM_NONE  0<br />
#define TEAM_COP    1<br />
#define TEAM_ROBBER 2<br />
#define TEAM_CIV    3<br />
#define TEAM_CLERK  4<br />
#define TEAM_DRIVER 5</code></div></div><br />
改用 enum 自动赋值：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum<br />
{<br />
    TEAM_NONE,<br />
    TEAM_COP,<br />
    TEAM_ROBBER,<br />
    TEAM_CIV,<br />
    TEAM_CLERK,<br />
    TEAM_DRIVER<br />
}</code></div></div><br />
值完全相同，使用方式也一样。<br />
<br />
更强大的位标志写法（推荐）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>enum (&lt;&lt;= 1)<br />
{<br />
    TEAM_NONE,<br />
    TEAM_COP = 1,<br />
    TEAM_ROBBER,<br />
    TEAM_CIV,<br />
    TEAM_CLERK,<br />
    TEAM_DRIVER,<br />
    TEAM_ADMIN<br />
}</code></div></div><br />
现在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">TEAM_COP = 1</code>（二进制 00000001）、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">TEAM_ROBBER = 2</code>（00000010）等。一个变量就能同时表示多个团队：<br />
<ul class="mycode_list"><li>添加团队：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gPlayerTeam[playerid] |= TEAM_COP;</code><br />
</li>
<li>移除团队：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gPlayerTeam[playerid] &amp;= ~TEAM_COP;</code><br />
</li>
<li>检查是否在团队：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (gPlayerTeam[playerid] &amp; TEAM_COP)</code><br />
</li>
</ul>
<br />
非常简洁且强大。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">forward</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">forward</code> 用于告诉编译器“这个函数稍后会定义”。所有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 函数都<span style="font-weight: bold;" class="mycode_b">必须</span> forward，也可以用于其他地方。<br />
<br />
语法：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward MyPublicFunction(playerid, const string[]);</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward MyPublicFunction(playerid, const string[]);<br />
public MyPublicFunction(playerid, const string[])<br />
{<br />
}</code></div></div><br />
除了 public 函数外，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">forward</code> 还能解决一种罕见的“reparse”警告（当函数返回带标签的值如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Float</code> 时，在声明前被调用）：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">有警告的写法：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main()<br />
{<br />
    new Float:myVar = MyFloatFunction();<br />
}<br />
Float:MyFloatFunction()<br />
{<br />
    return 5.0;<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">解决方法 1（函数前置）：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>Float:MyFloatFunction()<br />
{<br />
    return 5.0;<br />
}<br />
main()<br />
{<br />
    new Float:myVar = MyFloatFunction();<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">解决方法 2（forward）：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward Float:MyFloatFunction();<br />
main()<br />
{<br />
    new Float:myVar = MyFloatFunction();<br />
}<br />
Float:MyFloatFunction()<br />
{<br />
    return 5.0;<br />
}</code></div></div><br />
注意：forward 也要带返回值标签。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">native</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">native</code> 函数是由虚拟机（openmp(samp) 服务器或插件）提供的函数，而不是脚本自己定义的。你只能声明已存在于 openmp(samp) 或插件中的 native。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">用途 1</span>：让自定义函数出现在 qawno 右侧函数列表中（即使是假的）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>/*<br />
native MyFunction(playerid);<br />
*/</code></div></div><br />
注释会被 qawno 识别加入列表，但编译器会忽略。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">用途 2</span>：重命名 / 重载函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>native my_print(const string[]) = print;</code></div></div><br />
现在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code> 函数在脚本中已不存在（但服务器内部仍存在）。你可以重新定义它：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>print(const string[])<br />
{<br />
    my_print("Someone called print()");<br />
    my_print(string);<br />
}</code></div></div><br />
以后所有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print()</code> 调用都会先执行你的代码，再调用原函数。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">new</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 是变量声明的核心关键字之一。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    myVar = 5;</code></div></div><br />
创建变量并赋值为 5。未赋值时默认为 0：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new myVar;<br />
printf("%d", myVar);  // 输出 0</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">作用域</span>（scope）由大括号 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">{}</code> 决定，声明在括号内的变量只能在该括号内使用。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>if (a == 1)<br />
{<br />
    new myVar = 5;<br />
    printf("%d", myVar);        // 可以<br />
    if (myVar == 1)<br />
    {<br />
        printf("%d", myVar);    // 可以<br />
    }<br />
}<br />
// 这里无法使用 myVar，会报错<br />
printf("%d", myVar);</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">全局变量</span>（在函数外声明）从声明位置之后可在整个脚本中使用（包括 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#include</code> 的其他文件）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">static</span> 与 <span style="font-weight: bold;" class="mycode_b">new</span> 的区别详见下方 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 部分。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">operator</h3><br />
<br />
允许为自定义标签重载运算符。<br />
<br />
示例（大端序转换）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>stock BigEndian:operator=(b)<br />
{<br />
    return BigEndian:(((b &gt;&gt;&gt; 24) &amp; 0x000000FF) | ((b &gt;&gt;&gt; 8) &amp; 0x0000FF00) | ((b &lt;&lt; 8) &amp; 0x00FF0000) | ((b &lt;&lt; 24) &amp; 0xFF000000));<br />
}<br />
main()<br />
{<br />
    new BigEndian:a = 7;<br />
    printf("%d", _:a);  // 输出 117440512（因为小端序读取大端序数据）<br />
}</code></div></div><br />
可重载的运算符：<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">+, -, *, /, %, ++, --, ==, !=, &lt;, &gt;, &lt;=, &gt;=, !, =</code><br />
<br />
你可以让运算符做任何事（不一定是原本功能）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>stock BigEndian:operator+(BigEndian:a, BigEndian:b)<br />
{<br />
    return BigEndian:42;<br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a + b</code> 永远返回 42。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">public</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 让函数对虚拟机可见，允许 openmp(samp) 服务器从外部直接调用（而非仅在脚本内部调用）。也可用于变量（允许服务器读写），但 openmp(samp) 中极少使用。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 函数的名称会存储在 .amx 文件中（普通函数只存地址），这也是反编译的难点之一。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">通过名称调用 public 函数：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward MyPublicFunc();<br />
main()<br />
{<br />
    CallLocalFunction("MyPublicFunc", "");<br />
}<br />
public MyPublicFunc()<br />
{<br />
    printf("Hello");<br />
}</code></div></div><br />
也可使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">@</code> 前缀：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward MyPublicFunc();<br />
forward @MyOtherPublicFunc(var);<br />
main()<br />
{<br />
    CallLocalFunction("MyPublicFunc", "");<br />
    SetTimerEx("@MyOtherPublicFunc", 5000, 0, "i", 7);<br />
}<br />
public MyPublicFunc()<br />
{<br />
    printf("Hello");<br />
}<br />
@MyOtherPublicFunc(var)<br />
{<br />
    printf("%d", var);<br />
}</code></div></div><br />
所有 openmp(samp) 回调（如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerConnect</code>）都是 public，由服务器自动调用。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 函数也可以像普通函数一样直接调用（速度更快）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>forward MyPublicFunc();<br />
main()<br />
{<br />
    MyPublicFunc();  // 直接调用，比 CallLocalFunction 快<br />
}<br />
public MyPublicFunc()<br />
{<br />
    printf("Hello");<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">static</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 全局变量类似 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code>，但作用域更小（仅限于声明所在的文件或 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#section</code>）。<br />
<br />
对比 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 的跨文件可见性，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 仅限本文件：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// file2.pwn 中无法访问 file1.pwn 里的 static 变量</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">局部 static</span>：作用域与 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 相同（仅大括号内），但<span style="font-weight: bold;" class="mycode_b">值在函数多次调用间保留</span>（不像 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 每次重置）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>MyFunc()<br />
{<br />
    new i = 0;<br />
    printf("%d", i);<br />
    i++;<br />
    printf("%d", i);<br />
}</code></div></div><br />
调用 4 次输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>0 1<br />
0 1<br />
0 1<br />
0 1</code></div></div><br />
改为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 后：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>0 1<br />
1 2<br />
2 3<br />
3 4</code></div></div><br />
初始化值仅在<span style="font-weight: bold;" class="mycode_b">第一次</span>调用时生效。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 函数只能在声明所在文件中调用，适合“私有”函数。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">stock</h3><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">stock</code> 用于声明可能不会被使用的变量或函数，避免产生“unused”警告。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new stock<br />
    gMayBeUsedVar;<br />
static stock<br />
    g_sMayBeUsedVar;</code></div></div><br />
如果被使用则编译保留；如果未使用则<span style="font-weight: bold;" class="mycode_b">完全剔除</span>（不像 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#pragma unused</code> 只隐藏警告）。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">最常见用途</span>：编写库时。库作者无法预知用户会用哪些函数，使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">stock</code> 可避免大量无用警告。<br />
<br />
```pawn<br />
stock Func1()<br />
{<br />
printf("Hello");<br />
}<br />
<br />
stock Func2()<br />
{<br />
printf("Hi");<br />
}<br />
<br />
<hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[wiki系列] openmp/samp 控制结构]]></title>
			<link>https://open-mp.cn/showthread.php?tid=20</link>
			<pubDate>Sat, 21 Mar 2026 23:04:54 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=20</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">[wiki系列] openmp/samp 控制结构</h2><br />
<br />
<span style="font-weight: bold;" class="mycode_b">来自 SA-MP Wiki</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">目录</h3><br />
<ul class="mycode_list"><li><a href="http://#conditionals" target="_blank" rel="noopener" class="mycode_url">1 条件语句</a><br />
</li>
<li><a href="http://#if" target="_blank" rel="noopener" class="mycode_url">1.1 if</a><br />
</li>
<li><a href="http://#operators" target="_blank" rel="noopener" class="mycode_url">1.2 运算符</a><br />
</li>
<li><a href="http://#brackets" target="_blank" rel="noopener" class="mycode_url">1.3 括号</a><br />
</li>
<li><a href="http://#else" target="_blank" rel="noopener" class="mycode_url">1.4 else</a><br />
</li>
<li><a href="http://#else-if" target="_blank" rel="noopener" class="mycode_url">1.5 else if</a><br />
</li>
<li><a href="http://#ternary" target="_blank" rel="noopener" class="mycode_url">1.6 ?:（三元运算符）</a><br />
</li>
<li><a href="http://#loops" target="_blank" rel="noopener" class="mycode_url">2 循环</a><br />
</li>
<li><a href="http://#while" target="_blank" rel="noopener" class="mycode_url">2.1 while ()</a><br />
</li>
<li><a href="http://#for" target="_blank" rel="noopener" class="mycode_url">2.2 for ()</a><br />
</li>
<li><a href="http://#do-while" target="_blank" rel="noopener" class="mycode_url">2.3 do-while</a><br />
</li>
<li><a href="http://#if-goto" target="_blank" rel="noopener" class="mycode_url">2.4 if-goto</a><br />
</li>
<li><a href="http://#oboe" target="_blank" rel="noopener" class="mycode_url">2.5 OBOE（Off By One Error）</a><br />
</li>
<li><a href="http://#switch" target="_blank" rel="noopener" class="mycode_url">3 switch</a><br />
</li>
<li><a href="http://#switch-2" target="_blank" rel="noopener" class="mycode_url">3.1 switch</a><br />
</li>
<li><a href="http://#case" target="_blank" rel="noopener" class="mycode_url">3.2 case</a><br />
</li>
<li><a href="http://#default" target="_blank" rel="noopener" class="mycode_url">3.3 default</a><br />
</li>
<li><a href="http://#single-line-statements" target="_blank" rel="noopener" class="mycode_url">4 单行语句</a><br />
</li>
<li><a href="http://#goto" target="_blank" rel="noopener" class="mycode_url">4.1 goto</a><br />
</li>
<li><a href="http://#break" target="_blank" rel="noopener" class="mycode_url">4.2 break</a><br />
</li>
<li><a href="http://#continue" target="_blank" rel="noopener" class="mycode_url">4.3 continue</a><br />
</li>
<li><a href="http://#return" target="_blank" rel="noopener" class="mycode_url">4.4 return</a><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">条件语句</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">if</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 语句会检查某个条件是否成立，如果成立则执行对应代码。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5;<br />
if (a == 5)<br />
{<br />
    print("a is 5");<br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 后面的括号内是<span style="font-weight: bold;" class="mycode_b">条件</span>，你可以进行多种判断（详见运算符部分）。<br />
<br />
条件中不仅可以是变量，也可以是函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>if (SomeFunction() == 5)<br />
{<br />
    print("SomeFunction() is 5");<br />
}</code></div></div><br />
还可以组合多个条件：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5,<br />
    b = 3;<br />
if (a == 5 &amp;&amp; b != 3)<br />
{<br />
    print("Won't be printed");<br />
}</code></div></div><br />
上面检查 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a == 5</code> <span style="font-weight: bold;" class="mycode_b">并且</span> <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b != 3</code>，但 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b</code> 是 3，所以整个条件为假。<br />
<br />
使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">||</code>（或）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5,<br />
    b = 3;<br />
if (a == 5 || b != 3)<br />
{<br />
    print("Will be printed");<br />
}</code></div></div><br />
只要有一个条件为真，整个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 就成立（即使 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b != 3</code> 为假，因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a == 5</code> 为真）。<br />
<br />
还可以链式比较（无需显式写多个 &amp;&amp;）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    idx = 3;<br />
if (0 &lt; idx &lt; 5)<br />
{<br />
    print("idx is greater than 0 and less than 5!");<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">运算符</h4><br />
<br />
条件判断中常用的运算符及其含义：<br />
<br />
<h5 style="font-size:1.05em;font-weight:bold;margin:10px 0 4px;color:#444;">比较运算符</h5><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">运算符</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">含义</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">示例</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">==</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边等于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left == Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">!=</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边不等于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left != Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">&gt;</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边大于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left &gt; Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">&gt;=</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边大于等于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left &gt;= Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">&lt;</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边小于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left &lt; Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">&lt;=</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边小于等于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left &lt;= Right)</code></td>
  </tr>
</table>
<br />
<h5 style="font-size:1.05em;font-weight:bold;margin:10px 0 4px;color:#444;">逻辑运算符</h5><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">运算符</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">含义</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">示例</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">&amp;&amp;</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">并且（AND）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left &amp;&amp; Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">或者（OR）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left || Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">!</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">非（NOT）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (!Variable)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">都不（NOR）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (!(Left || Right))</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">不是都（NAND）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (!(Left &amp;&amp; Right))</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">异或（XOR）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (!(Left &amp;&amp; Right) &amp;&amp; (Left || Right))</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">同或（NXOR）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if ((Left &amp;&amp; Right) || !(Left || Right))</code></td>
  </tr>
</table>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">括号</h4><br />
<br />
括号决定运算顺序：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 3,<br />
    b = 3,<br />
    c = 1;<br />
if (a == 5 &amp;&amp; b == 3 || c == 1)<br />
{<br />
    print("Will this be called?");<br />
}</code></div></div><br />
有两种可能的解释：<br />
<br />
<ol type="1" class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">(a == 5 &amp;&amp; b == 3) || c == 1</code>  <br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a == 5 &amp;&amp; (b == 3 || c == 1)</code><br />
</li>
</ol>
<br />
第一种：先判断 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a==5 &amp;&amp; b==3</code>（为假），再判断 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">c==1</code>（为真），整体为真。  <br />
第二种：先判断 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b==3 || c==1</code>（为真），再判断 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a==5</code>（为假），整体为假。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">强烈建议始终使用括号</span>，既能明确逻辑，也能避免歧义。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">else</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else</code> 在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 条件不成立时执行：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5;<br />
if (a == 3)  // 假<br />
{<br />
    print("Won't be called");<br />
}<br />
else<br />
{<br />
    print("Will be called as the check failed");<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">else if</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code> 用于在第一个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 不成立时继续检查其他条件：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5;<br />
if (a == 1)<br />
{<br />
    print("Will be called if a is 1");<br />
}<br />
else if (a == 5)<br />
{<br />
    print("Will be called if a is 5");<br />
}<br />
else<br />
{<br />
    print("All other numbers");<br />
}</code></div></div><br />
你可以连续写多个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code>，但一个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 组中只能有一个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else</code>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code> 只在最初的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 失败时才检查，且变量值以检查开始时的状态为准。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">?:（三元运算符）</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">?</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">:</code> 组合成三元运算符，可将 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if-else</code> 写在单行内：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a,<br />
    b = 3;<br />
if (b == 3)<br />
{<br />
    a = 5;<br />
}<br />
else<br />
{<br />
    a = 7;<br />
}</code></div></div><br />
可简化为：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a,<br />
    b = 3;<br />
a = (b == 3) ? 5 : 7;</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">(条件) ? 真值 : 假值</code><br />
<br />
也可以嵌套（类似多个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code>）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a,<br />
    b = 3;<br />
a = (b == 1) ? 2 : (b == 2) ? 3 : (b == 3) ? 4 : 5;</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">循环</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">while ()</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">while</code> 循环在条件成立时重复执行代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 9;<br />
while (a &lt; 10)<br />
{<br />
    // 循环内的代码<br />
    a++;<br />
}</code></div></div><br />
每次到达 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">}</code> 时会回到条件重新判断。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">for ()</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">for</code> 是压缩版的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">while</code> 循环，包含三部分：初始化、条件、递增。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new a = 9; a &lt; 10; a++)<br />
{<br />
    // 循环内的代码<br />
}</code></div></div><br />
常用遍历玩家示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new i, a = GetMaxPlayers(); i &lt; a; i++)<br />
{<br />
    if (IsPlayerConnected(i))<br />
    {<br />
        // do something<br />
    }<br />
}</code></div></div><br />
三部分均可省略（留空）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new a = 9;<br />
for ( ; a &lt; 10; )<br />
{<br />
    a++;<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">do-while</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">do-while</code> 先执行代码，再判断条件，因此<span style="font-weight: bold;" class="mycode_b">至少执行一次</span>：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 10;<br />
do<br />
{<br />
    // 循环内的代码<br />
    a++;<br />
}<br />
while (a &lt; 10);  // 注意分号</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">if-goto</h4><br />
<br />
循环本质上就是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> + <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">goto</code> 的结构化形式（不推荐直接使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">goto</code>）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 9;<br />
loop_start:<br />
if (a &lt; 10)<br />
{<br />
    // 循环内的代码<br />
    a++;<br />
    goto loop_start;<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">OBOE（Off By One Error）</h4><br />
<br />
OBOE 是最常见的循环错误之一——循环多跑或少跑一次。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 0,<br />
    b[10];<br />
while (a &lt;= sizeof (b))<br />
{<br />
    b[a] = 0;<br />
}</code></div></div><br />
上面会尝试访问 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b[10]</code>（越界），导致 OOB（Out Of Bounds）错误。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">特别注意</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">do-while</code> 永远至少执行一次，更容易出现 OBOE。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">switch</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">switch</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">switch</code> 是结构化的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if / else if / else</code>，更清晰：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5;<br />
switch (a)<br />
{<br />
    case 1:<br />
    {<br />
        // 不会执行<br />
    }<br />
    case 2:<br />
    {<br />
        // 不会执行<br />
    }<br />
    case 5:<br />
    {<br />
        // 会执行<br />
    }<br />
    default:<br />
    {<br />
        // 不会执行<br />
    }<br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">switch</code> 只调用一次判断表达式（比连续 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code> 更高效）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">case</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">case</code> 支持单个值、列表或范围：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>case 1, 2, 3, 4:    // 列表<br />
case 1 .. 4:        // 范围（推荐连续数字）</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">default</h4><br />
<br />
相当于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else</code>，所有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">case</code> 都不匹配时执行。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">单行语句</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">goto</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">goto</code> 直接跳转到标签（不推荐使用，会破坏程序流程）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">break</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">break</code> 立即跳出当前循环：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new a = 0; a &lt; 10; a++)<br />
{<br />
    if (a == 5) break;<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">continue</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">continue</code> 跳过本次循环剩余代码，直接进入下一次迭代：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new a = 0; a &lt; 3; a++)<br />
{<br />
    if (a == 1) continue;<br />
    printf("a = %d", a);<br />
}</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>a = 0<br />
a = 2</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：在某些循环（尤其是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">while</code>）中使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">continue</code> 时要小心，可能导致无限循环。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">return</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code> 立即结束当前函数，返回到调用处：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main()<br />
{<br />
    print("1");<br />
    MyFunction(1);<br />
    print("3");<br />
}<br />
MyFunction(num)<br />
{<br />
    if (num == 1)<br />
    {<br />
        return;  // 直接返回，不执行下面的 print<br />
    }<br />
    print("2");<br />
}</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>1<br />
3</code></div></div><br />
也可以返回具体值：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>return 27;</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：如果函数有时返回值，有时不返回值，必须在所有路径都显式 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code> 一个值。<br />
<br />
<hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">[wiki系列] openmp/samp 控制结构</h2><br />
<br />
<span style="font-weight: bold;" class="mycode_b">来自 SA-MP Wiki</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">目录</h3><br />
<ul class="mycode_list"><li><a href="http://#conditionals" target="_blank" rel="noopener" class="mycode_url">1 条件语句</a><br />
</li>
<li><a href="http://#if" target="_blank" rel="noopener" class="mycode_url">1.1 if</a><br />
</li>
<li><a href="http://#operators" target="_blank" rel="noopener" class="mycode_url">1.2 运算符</a><br />
</li>
<li><a href="http://#brackets" target="_blank" rel="noopener" class="mycode_url">1.3 括号</a><br />
</li>
<li><a href="http://#else" target="_blank" rel="noopener" class="mycode_url">1.4 else</a><br />
</li>
<li><a href="http://#else-if" target="_blank" rel="noopener" class="mycode_url">1.5 else if</a><br />
</li>
<li><a href="http://#ternary" target="_blank" rel="noopener" class="mycode_url">1.6 ?:（三元运算符）</a><br />
</li>
<li><a href="http://#loops" target="_blank" rel="noopener" class="mycode_url">2 循环</a><br />
</li>
<li><a href="http://#while" target="_blank" rel="noopener" class="mycode_url">2.1 while ()</a><br />
</li>
<li><a href="http://#for" target="_blank" rel="noopener" class="mycode_url">2.2 for ()</a><br />
</li>
<li><a href="http://#do-while" target="_blank" rel="noopener" class="mycode_url">2.3 do-while</a><br />
</li>
<li><a href="http://#if-goto" target="_blank" rel="noopener" class="mycode_url">2.4 if-goto</a><br />
</li>
<li><a href="http://#oboe" target="_blank" rel="noopener" class="mycode_url">2.5 OBOE（Off By One Error）</a><br />
</li>
<li><a href="http://#switch" target="_blank" rel="noopener" class="mycode_url">3 switch</a><br />
</li>
<li><a href="http://#switch-2" target="_blank" rel="noopener" class="mycode_url">3.1 switch</a><br />
</li>
<li><a href="http://#case" target="_blank" rel="noopener" class="mycode_url">3.2 case</a><br />
</li>
<li><a href="http://#default" target="_blank" rel="noopener" class="mycode_url">3.3 default</a><br />
</li>
<li><a href="http://#single-line-statements" target="_blank" rel="noopener" class="mycode_url">4 单行语句</a><br />
</li>
<li><a href="http://#goto" target="_blank" rel="noopener" class="mycode_url">4.1 goto</a><br />
</li>
<li><a href="http://#break" target="_blank" rel="noopener" class="mycode_url">4.2 break</a><br />
</li>
<li><a href="http://#continue" target="_blank" rel="noopener" class="mycode_url">4.3 continue</a><br />
</li>
<li><a href="http://#return" target="_blank" rel="noopener" class="mycode_url">4.4 return</a><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">条件语句</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">if</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 语句会检查某个条件是否成立，如果成立则执行对应代码。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5;<br />
if (a == 5)<br />
{<br />
    print("a is 5");<br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 后面的括号内是<span style="font-weight: bold;" class="mycode_b">条件</span>，你可以进行多种判断（详见运算符部分）。<br />
<br />
条件中不仅可以是变量，也可以是函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>if (SomeFunction() == 5)<br />
{<br />
    print("SomeFunction() is 5");<br />
}</code></div></div><br />
还可以组合多个条件：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5,<br />
    b = 3;<br />
if (a == 5 &amp;&amp; b != 3)<br />
{<br />
    print("Won't be printed");<br />
}</code></div></div><br />
上面检查 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a == 5</code> <span style="font-weight: bold;" class="mycode_b">并且</span> <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b != 3</code>，但 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b</code> 是 3，所以整个条件为假。<br />
<br />
使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">||</code>（或）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5,<br />
    b = 3;<br />
if (a == 5 || b != 3)<br />
{<br />
    print("Will be printed");<br />
}</code></div></div><br />
只要有一个条件为真，整个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 就成立（即使 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b != 3</code> 为假，因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a == 5</code> 为真）。<br />
<br />
还可以链式比较（无需显式写多个 &amp;&amp;）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    idx = 3;<br />
if (0 &lt; idx &lt; 5)<br />
{<br />
    print("idx is greater than 0 and less than 5!");<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">运算符</h4><br />
<br />
条件判断中常用的运算符及其含义：<br />
<br />
<h5 style="font-size:1.05em;font-weight:bold;margin:10px 0 4px;color:#444;">比较运算符</h5><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">运算符</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">含义</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">示例</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">==</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边等于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left == Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">!=</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边不等于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left != Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">&gt;</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边大于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left &gt; Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">&gt;=</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边大于等于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left &gt;= Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">&lt;</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边小于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left &lt; Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">&lt;=</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">左边小于等于右边</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left &lt;= Right)</code></td>
  </tr>
</table>
<br />
<h5 style="font-size:1.05em;font-weight:bold;margin:10px 0 4px;color:#444;">逻辑运算符</h5><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">运算符</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">含义</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">示例</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">&amp;&amp;</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">并且（AND）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left &amp;&amp; Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">或者（OR）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (Left || Right)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">!</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">非（NOT）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (!Variable)</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">都不（NOR）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (!(Left || Right))</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">不是都（NAND）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (!(Left &amp;&amp; Right))</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">异或（XOR）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if (!(Left &amp;&amp; Right) &amp;&amp; (Left || Right))</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">同或（NXOR）</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if ((Left &amp;&amp; Right) || !(Left || Right))</code></td>
  </tr>
</table>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">括号</h4><br />
<br />
括号决定运算顺序：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 3,<br />
    b = 3,<br />
    c = 1;<br />
if (a == 5 &amp;&amp; b == 3 || c == 1)<br />
{<br />
    print("Will this be called?");<br />
}</code></div></div><br />
有两种可能的解释：<br />
<br />
<ol type="1" class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">(a == 5 &amp;&amp; b == 3) || c == 1</code>  <br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a == 5 &amp;&amp; (b == 3 || c == 1)</code><br />
</li>
</ol>
<br />
第一种：先判断 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a==5 &amp;&amp; b==3</code>（为假），再判断 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">c==1</code>（为真），整体为真。  <br />
第二种：先判断 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b==3 || c==1</code>（为真），再判断 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">a==5</code>（为假），整体为假。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">强烈建议始终使用括号</span>，既能明确逻辑，也能避免歧义。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">else</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else</code> 在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 条件不成立时执行：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5;<br />
if (a == 3)  // 假<br />
{<br />
    print("Won't be called");<br />
}<br />
else<br />
{<br />
    print("Will be called as the check failed");<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">else if</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code> 用于在第一个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 不成立时继续检查其他条件：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5;<br />
if (a == 1)<br />
{<br />
    print("Will be called if a is 1");<br />
}<br />
else if (a == 5)<br />
{<br />
    print("Will be called if a is 5");<br />
}<br />
else<br />
{<br />
    print("All other numbers");<br />
}</code></div></div><br />
你可以连续写多个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code>，但一个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 组中只能有一个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else</code>。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code> 只在最初的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 失败时才检查，且变量值以检查开始时的状态为准。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">?:（三元运算符）</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">?</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">:</code> 组合成三元运算符，可将 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if-else</code> 写在单行内：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a,<br />
    b = 3;<br />
if (b == 3)<br />
{<br />
    a = 5;<br />
}<br />
else<br />
{<br />
    a = 7;<br />
}</code></div></div><br />
可简化为：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a,<br />
    b = 3;<br />
a = (b == 3) ? 5 : 7;</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">(条件) ? 真值 : 假值</code><br />
<br />
也可以嵌套（类似多个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code>）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a,<br />
    b = 3;<br />
a = (b == 1) ? 2 : (b == 2) ? 3 : (b == 3) ? 4 : 5;</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">循环</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">while ()</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">while</code> 循环在条件成立时重复执行代码：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 9;<br />
while (a &lt; 10)<br />
{<br />
    // 循环内的代码<br />
    a++;<br />
}</code></div></div><br />
每次到达 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">}</code> 时会回到条件重新判断。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">for ()</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">for</code> 是压缩版的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">while</code> 循环，包含三部分：初始化、条件、递增。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new a = 9; a &lt; 10; a++)<br />
{<br />
    // 循环内的代码<br />
}</code></div></div><br />
常用遍历玩家示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new i, a = GetMaxPlayers(); i &lt; a; i++)<br />
{<br />
    if (IsPlayerConnected(i))<br />
    {<br />
        // do something<br />
    }<br />
}</code></div></div><br />
三部分均可省略（留空）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new a = 9;<br />
for ( ; a &lt; 10; )<br />
{<br />
    a++;<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">do-while</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">do-while</code> 先执行代码，再判断条件，因此<span style="font-weight: bold;" class="mycode_b">至少执行一次</span>：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 10;<br />
do<br />
{<br />
    // 循环内的代码<br />
    a++;<br />
}<br />
while (a &lt; 10);  // 注意分号</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">if-goto</h4><br />
<br />
循环本质上就是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> + <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">goto</code> 的结构化形式（不推荐直接使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">goto</code>）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 9;<br />
loop_start:<br />
if (a &lt; 10)<br />
{<br />
    // 循环内的代码<br />
    a++;<br />
    goto loop_start;<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">OBOE（Off By One Error）</h4><br />
<br />
OBOE 是最常见的循环错误之一——循环多跑或少跑一次。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 0,<br />
    b[10];<br />
while (a &lt;= sizeof (b))<br />
{<br />
    b[a] = 0;<br />
}</code></div></div><br />
上面会尝试访问 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">b[10]</code>（越界），导致 OOB（Out Of Bounds）错误。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">特别注意</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">do-while</code> 永远至少执行一次，更容易出现 OBOE。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">switch</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">switch</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">switch</code> 是结构化的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if / else if / else</code>，更清晰：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
    a = 5;<br />
switch (a)<br />
{<br />
    case 1:<br />
    {<br />
        // 不会执行<br />
    }<br />
    case 2:<br />
    {<br />
        // 不会执行<br />
    }<br />
    case 5:<br />
    {<br />
        // 会执行<br />
    }<br />
    default:<br />
    {<br />
        // 不会执行<br />
    }<br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">switch</code> 只调用一次判断表达式（比连续 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else if</code> 更高效）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">case</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">case</code> 支持单个值、列表或范围：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>case 1, 2, 3, 4:    // 列表<br />
case 1 .. 4:        // 范围（推荐连续数字）</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">default</h4><br />
<br />
相当于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">else</code>，所有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">case</code> 都不匹配时执行。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">单行语句</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">goto</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">goto</code> 直接跳转到标签（不推荐使用，会破坏程序流程）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">break</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">break</code> 立即跳出当前循环：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new a = 0; a &lt; 10; a++)<br />
{<br />
    if (a == 5) break;<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">continue</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">continue</code> 跳过本次循环剩余代码，直接进入下一次迭代：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new a = 0; a &lt; 3; a++)<br />
{<br />
    if (a == 1) continue;<br />
    printf("a = %d", a);<br />
}</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>a = 0<br />
a = 2</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：在某些循环（尤其是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">while</code>）中使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">continue</code> 时要小心，可能导致无限循环。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">return</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code> 立即结束当前函数，返回到调用处：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main()<br />
{<br />
    print("1");<br />
    MyFunction(1);<br />
    print("3");<br />
}<br />
MyFunction(num)<br />
{<br />
    if (num == 1)<br />
    {<br />
        return;  // 直接返回，不执行下面的 print<br />
    }<br />
    print("2");<br />
}</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>1<br />
3</code></div></div><br />
也可以返回具体值：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>return 27;</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：如果函数有时返回值，有时不返回值，必须在所有路径都显式 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code> 一个值。<br />
<br />
<hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[[wiki系列] openmp/samp脚本基础]]></title>
			<link>https://open-mp.cn/showthread.php?tid=19</link>
			<pubDate>Sat, 21 Mar 2026 22:34:25 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=19</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">[wiki系列] openmp/samp 脚本基础</h2><br />
<br />
<span style="font-weight: bold;" class="mycode_b">来自 SAMP Wiki</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">目录</h3><br />
<ul class="mycode_list"><li><a href="http://#starting-out" target="_blank" rel="noopener" class="mycode_url">1 入门！</a><br />
</li>
<li><a href="http://#include" target="_blank" rel="noopener" class="mycode_url">1.1 Include</a><br />
</li>
<li><a href="http://#calls" target="_blank" rel="noopener" class="mycode_url">1.2 调用</a><br />
</li>
<li><a href="http://#statements" target="_blank" rel="noopener" class="mycode_url">1.3 语句</a><br />
</li>
<li><a href="http://#functions" target="_blank" rel="noopener" class="mycode_url">2 函数</a><br />
</li>
<li><a href="http://#calling" target="_blank" rel="noopener" class="mycode_url">2.1 调用</a><br />
</li>
<li><a href="http://#defining" target="_blank" rel="noopener" class="mycode_url">2.2 定义</a><br />
</li>
<li><a href="http://#parameters" target="_blank" rel="noopener" class="mycode_url">2.3 参数</a><br />
</li>
<li><a href="http://#variables" target="_blank" rel="noopener" class="mycode_url">3 变量</a><br />
</li>
<li><a href="http://#declaration" target="_blank" rel="noopener" class="mycode_url">3.1 声明</a><br />
</li>
<li><a href="http://#setting" target="_blank" rel="noopener" class="mycode_url">3.2 赋值</a><br />
</li>
<li><a href="http://#arrays" target="_blank" rel="noopener" class="mycode_url">3.3 数组</a><br />
</li>
<li><a href="http://#declaration-2" target="_blank" rel="noopener" class="mycode_url">3.3.1 声明</a><br />
</li>
<li><a href="http://#accessing" target="_blank" rel="noopener" class="mycode_url">3.3.2 访问</a><br />
</li>
<li><a href="http://#example" target="_blank" rel="noopener" class="mycode_url">3.3.3 示例</a><br />
</li>
<li><a href="http://#strings" target="_blank" rel="noopener" class="mycode_url">3.4 字符串</a><br />
</li>
<li><a href="http://#basic-use" target="_blank" rel="noopener" class="mycode_url">3.4.1 基本用法</a><br />
</li>
<li><a href="http://#escape-character" target="_blank" rel="noopener" class="mycode_url">3.4.2 转义字符</a><br />
</li>
<li><a href="http://#tags" target="_blank" rel="noopener" class="mycode_url">3.5 标签</a><br />
</li>
<li><a href="http://#scope" target="_blank" rel="noopener" class="mycode_url">3.6 作用域</a><br />
</li>
<li><a href="http://#local" target="_blank" rel="noopener" class="mycode_url">3.6.1 局部（local）</a><br />
</li>
<li><a href="http://#static-local" target="_blank" rel="noopener" class="mycode_url">3.6.2 静态局部（static local）</a><br />
</li>
<li><a href="http://#global" target="_blank" rel="noopener" class="mycode_url">3.6.3 全局（global）</a><br />
</li>
<li><a href="http://#global-static" target="_blank" rel="noopener" class="mycode_url">3.6.4 全局静态（global static）</a><br />
</li>
<li><a href="http://#control-structures" target="_blank" rel="noopener" class="mycode_url">4 控制结构</a><br />
</li>
<li><a href="http://#keywords" target="_blank" rel="noopener" class="mycode_url">5 关键字</a><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">入门！</h3><br />
<br />
下面是一个可能最简单的脚本示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
我们将逐一讲解各个部分，先从第一行开始。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">Include</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;</code></div></div><br />
这一行会把 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">qawno/includes/open.mp.inc</code> 文件中的所有代码加载到你的脚本中，这样你就可以使用它提供的一切内容。其中它还包含了：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;args&gt;<br />
#include &lt;console&gt;<br />
#include &lt;core&gt;<br />
#include &lt;file&gt;<br />
#include &lt;float&gt;<br />
#include &lt;string&gt;<br />
#include &lt;time&gt;<br />
#include &lt;omp_core&gt;<br />
#include &lt;omp_player&gt;<br />
#include &lt;omp_actor&gt;<br />
#include &lt;omp_checkpoint&gt;<br />
#include &lt;omp_class&gt;<br />
#include &lt;omp_database&gt;<br />
#include &lt;omp_dialog&gt;<br />
#include &lt;omp_gangzone&gt;<br />
#include &lt;omp_http&gt;<br />
#include &lt;omp_menu&gt;<br />
#include &lt;omp_network&gt;<br />
#include &lt;omp_object&gt;<br />
#include &lt;omp_pickup&gt;<br />
#include &lt;omp_textdraw&gt;<br />
#include &lt;omp_variable&gt;<br />
#include &lt;omp_vehicle&gt;<br />
#include &lt;omp_textlabel&gt;<br />
#include &lt;omp_npc&gt;</code></div></div><br />
这些文件包含了 open.mp(samp) 的所有核心功能，因此只需这一行，你就拥有了 open.mp(samp) 的全部函数（函数后面会详细说明）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">调用</h4><br />
<br />
接下来是函数调用的两部分。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main()</code> 是你自己编写代码的函数，由外部调用；<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print(string[])</code> 是代码在别处定义、由你调用的函数。目前这个脚本只会加载、打印一行字符串（即在服务器控制台输出 “Hello World!”，不带引号——这是所有脚本语言的传统），然后结束。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>return 1;</code></div></div><br />
这条语句将值 1 返回给调用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main</code> 的地方，告诉它执行结果（具体返回值在这里不重要，但在其他地方很重要）。<br />
<br />
你现在已经写出了第一个（非常基础）的脚本。如果你在 qawno 中选择“文件 → 新建”，它会给你一个更大的模板，包含所有回调（见下文），包括 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main</code>（严格来说它不是回调，但行为类似）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">语句</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code> 行都以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">;</code>（分号）结尾，分号表示一条<span style="font-weight: bold;" class="mycode_b">语句</span>的结束（语句是一组函数和运算符的组合，用于完成某项操作，类似自然语言中的句子）。大多数人把每条语句写在单独一行，但这不是必须的，只是为了更清晰。下面这种写法同样有效：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!"); <br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1; <br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">{}</code>（大括号）用于将一组语句组合在一起执行（类似自然语言中的段落）。如果你写成：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main() <br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!"); <br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;</code></div></div><br />
编译器会报错，因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return 1;</code> 没有被括起来，不属于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main</code> 函数。大括号将多条语句组合成一条<span style="font-weight: bold;" class="mycode_b">复合语句</span>，而函数体只能包含一条语句。没有大括号时，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code> 是两条独立的语句，函数只能有一条，所以第二条语句就游离在函数之外，这是非法的。<br />
<br />
不过，你也可以用逗号运算符 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">,</code> 来扩展复合语句，但不推荐这样做（不是最佳编码习惯）。示例如下：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main() <br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!"), return 1;</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">函数</h3><br />
<br />
函数是一段完成特定任务的代码，可以从其他地方调用。它还可以将执行结果返回给调用它的地方。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">调用</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>print("Hello World!");</code></div></div><br />
如“入门”部分所述，这会调用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code> 函数（定义在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">open.mp.inc</code> 中，所以需要 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#include</code>），并让它在服务器控制台显示 “Hello World!”。<br />
<br />
函数由<span style="font-weight: bold;" class="mycode_b">函数名</span>（如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code>）和<span style="font-weight: bold;" class="mycode_b">参数列表</span>（用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">()</code> 括起来）组成。参数列表向函数传递额外数据。如果没有参数，你就需要成千上万个函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printa();<br />
printaa();<br />
printab();<br />
...</code></div></div><br />
函数可以有任意数量的参数（从 0 开始，至少支持 128 个）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printf("Hello World!", 1, 2, 3, 4, 5, 6);</code></div></div><br />
现在不用关心这个函数具体做什么，只需知道它有 7 个参数，用逗号分隔。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">定义</h4><br />
<br />
除了调用已有函数，你也可以自己编写并调用函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return MyFunction();<br />
}<br />
<br />
MyFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
这段代码功能与最初的示例完全相同，只是结构不同。当模式启动时 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main()</code> 被自动调用，它再调用自定义函数 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MyFunction()</code>。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MyFunction()</code> 在控制台打印消息，然后返回 1 给 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main()</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main()</code> 再把这个值返回给服务器。<br />
<br />
因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return MyFunction();</code> 是一条完整语句，你也可以写成：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
<br />
main() return MyFunction();<br />
<br />
MyFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
但大多数人为了清晰起见还是分开写。你也可以完全不使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MyFunction</code> 的返回值：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyFunction();<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}<br />
<br />
MyFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">参数</h4><br />
<br />
参数是一种特殊的<span style="font-weight: bold;" class="mycode_b">变量</span>，你不需要自己声明，它来自调用函数的地方：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return MyFunction("Hello World!");<br />
}<br />
<br />
MyFunction(const string[])<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print(string);<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
这段代码功能相同，但现在我们把要显示的内容传给了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MyFunction()</code>。调用时把字符串 “Hello World!” 传递给函数，存储在名为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string</code> 的变量中（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">[]</code> 表示这是一个数组，后面会解释）。然后调用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code>，把 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string</code> 的内容传给它（没有引号，所以它是一个变量）。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">变量</h3><br />
<br />
变量本质上是内存中的一块空间，用于存储数据，可以随时读取和修改。变量由一个或多个 <span style="font-weight: bold;" class="mycode_b">cell</span> 组成，一个 cell 是 32 位（4 字节），默认有符号，可存储 -2147483648 到 2147483647（注意 -2147483648 在 PAWN 中定义不完善，显示时可能异常）。由多个 cell 组成的变量叫<span style="font-weight: bold;" class="mycode_b">数组</span>，字符串是一种特殊的数组，每个 cell 存放一个字符（打包字符串每个 cell 可存 4 个字符，但这里不讨论）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">声明</h4><br />
<br />
要创建一个新变量，必须先声明它：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myVariable;</code></div></div><br />
这会创建一个名为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">myVariable</code> 的变量，初始值为 0。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">赋值</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myVariable = 7;</code></div></div><br />
声明变量并设置初始值为 7。现在打印它会显示 7。要打印非字符串变量，需要使用前面提到的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf()</code>：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myVariable = 7;<br />
<br />
printf("%d", myVariable);</code></div></div><br />
现在只需知道这会在服务器控制台输出变量的值（当前是 7）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myVariable = 7;<br />
<br />
printf("%d", myVariable);<br />
<br />
myVariable = 8;<br />
<br />
printf("%d", myVariable);</code></div></div><br />
这段代码会先打印 7，然后把变量改为 8，再打印新的值。<br />
<br />
变量操作示例（更多运算符请参考其他章节）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>myVariable = myVariable + 4;&nbsp;&nbsp; // 等价于<br />
myVariable += 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 增加 4<br />
<br />
myVariable -= 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 减少 4<br />
myVariable *= 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 乘以 4<br />
myVariable /= 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 除以 4</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">数组</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">声明</h4><br />
<br />
数组是一种可以同时存储多个数据、动态访问的变量。数组大小在编译时就固定了，必须提前知道需要多少个槽位。最常见的例子是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_PLAYERS</code> 数组，每个玩家一个槽位，确保数据不会互相干扰。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myArray[5];</code></div></div><br />
这会创建一个有 5 个槽位的数组。<span style="font-weight: bold;" class="mycode_b">不能</span>这样做：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myVariable = 5,<br />
&nbsp;&nbsp;&nbsp;&nbsp;myArray[myVariable];&nbsp;&nbsp;// 错误！</code></div></div><br />
因为 PAWN 在编译时就分配内存，数组大小必须是常量。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">访问</h4><br />
<br />
要给数组某个位置赋值，必须指定下标（index），下标可以是变量：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myArray[5];<br />
<br />
myArray[2] = 7;</code></div></div><br />
数组现在的内容是：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0, 0, 7, 0, 0</code><br />
<br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：下标从 0 开始计数，而不是 1。<br />
<br />
如果你尝试访问 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">myArray[5]</code>（超出范围），可能会导致服务器崩溃。<br />
<br />
下标可以是数字、变量，甚至是返回值的函数。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myArray[5],<br />
&nbsp;&nbsp;&nbsp;&nbsp;myIndex = 2;<br />
<br />
myArray[myIndex] = 7;</code></div></div><br />
数组中的元素可以像普通变量一样使用：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>myArray[2] = myArray[2] + 1;<br />
myArray[2] += 1;<br />
myArray[2]++;</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">示例</h4><br />
<br />
最常见的数组是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_PLAYERS</code> 数组（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_PLAYERS</code> 是一个常量，默认 1000）。下面对比用普通变量和数组处理 4 个玩家数据（假设 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_PLAYERS</code> 为 4）：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">传统写法（4 个变量）：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;gPlayer0, gPlayer1, gPlayer2, gPlayer3;<br />
<br />
SetPlayerValue(playerid, value)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;switch (playerid)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 0: gPlayer0 = value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 1: gPlayer1 = value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 2: gPlayer2 = value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 3: gPlayer3 = value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">数组写法（推荐）：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;gPlayers[MAX_PLAYERS];<br />
<br />
SetPlayerValue(playerid, value)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;gPlayers[playerid] = value;<br />
}</code></div></div><br />
数组写法无论玩家数量多少，都只需要一行代码，清晰且高效。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">字符串</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">基本用法</h4><br />
<br />
字符串是一种特殊的数组，用于存放多个字符组成文本。每个字符默认占用一个 cell。字符串以 <span style="font-weight: bold;" class="mycode_b">NULL 终止</span>（遇到 0 就结束，不是字符 '0'）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myString[16] = "Hello World!";</code></div></div><br />
这会创建一个可容纳 15 个字符的字符串，初始值为 “Hello World!”。内部实际存储为：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>104 101 108 108 111 0 x x x x x x x x x x</code></div></div><br />
（0 是终止符，后面的 x 无关紧要）<br />
<br />
你可以像操作数组一样修改字符串：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myString[16] = "Hello World!";<br />
<br />
myString[1] = 97;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 97 是 'a'</code></div></div><br />
结果变为 “hallo”。<br />
<br />
更易读的写法：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>myString[1] = 'a';</code></div></div><br />
单引号表示单个字符。<br />
<br />
把某个位置设为终止符：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>myString[1] = '&#92;0';&nbsp;&nbsp; // 或 = 0;</code></div></div><br />
字符串会变成 “h”。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">转义字符</h4><br />
<br />
反斜杠 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\</code> 是特殊字符，用于创建无法直接输入的字符：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myString[4] = "&#92;"";&nbsp;&nbsp; // 字符串内容就是一个双引号 "</code></div></div><br />
常用转义序列：<br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">转义符</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">含义</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">说明</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\0</code> / <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">EOS</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">NULL 字符</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">字符串结束</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\n</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">换行</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">Linux 新行（Windows 也可用）</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\r</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">回车</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">Windows 新行用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\r\n</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\\</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">反斜杠</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">实际输出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\'</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">单引号</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">在单引号中用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'\' '</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\"</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">双引号</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">在字符串中用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\"</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\xNNN;</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">十六进制字符</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">用十六进制值设置字符</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\NNN;</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">十进制字符</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">用十进制值设置字符</td>
  </tr>
</table>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">标签</h3><br />
<br />
标签是变量的额外信息，用于定义其用途和可使用范围。标签分为强标签（首字母大写）和弱标签。<br />
<br />
示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;Float:a = 6.0;</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Float</code> 就是标签，表示这是一个浮点数（小数）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>native SetGravity(Float:gravity);</code></div></div><br />
这要求参数必须是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Float</code> 类型：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SetGravity(6.0);<br />
<br />
new Float:fGrav = 5.0;<br />
<br />
SetGravity(fGrav);</code></div></div><br />
使用错误标签会产生 <span style="font-weight: bold;" class="mycode_b">tag mismatch</span> 警告：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SetGravity(MyTag:7);&nbsp;&nbsp;// 错误</code></div></div><br />
标签区分大小写。<br />
<br />
你可以自定义标签：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new myTag: variable = 0,<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;AppleTag: another = 1;</code></div></div><br />
直接相加时需要用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">_: </code> 去除标签，否则会报标签不匹配。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">作用域</h3><br />
<br />
作用域决定变量在哪里可用。主要有四种：局部、静态局部、全局、全局静态。变量必须先声明后使用。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">局部（local）</h4><br />
<br />
在函数内用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 声明：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>MyFunc()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new var1 = 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", var1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new var2 = 8;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%d %d", var1, var2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;// var2 已失效<br />
}<br />
// var1 已失效</code></div></div><br />
局部变量每次进入函数都会重置：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new i = 0; i &lt; 3; i++)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new j = 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;j++;<br />
}</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>1<br />
1<br />
1</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">静态局部（static local）</h4><br />
<br />
与局部变量作用域相同，但值会在函数多次调用间保留：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new i = 0; i &lt; 3; i++)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;static j = 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;j++;<br />
}</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>1<br />
2<br />
3</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">全局（global）</h4><br />
<br />
在函数外声明，可在任何函数中使用，且永不重置：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;gMyVar = 4;<br />
<br />
MyFunc()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", gMyVar);<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">全局静态（global static）</h4><br />
<br />
与全局类似，但<span style="font-weight: bold;" class="mycode_b">仅限声明所在文件</span>使用：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">File1.pwn</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>static<br />
&nbsp;&nbsp;&nbsp;&nbsp;gs_MyVar = 4;<br />
<br />
MyFunc()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", gs_MyVar);<br />
}<br />
<br />
#include "File2"</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">File2.pwn</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>MyFunc2()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// gs_MyVar 在这里不存在<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", gs_MyVar);&nbsp;&nbsp;// 错误<br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 也可用于函数，实现类似“私有”函数的效果。<br />
<br />
<hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">[wiki系列] openmp/samp 脚本基础</h2><br />
<br />
<span style="font-weight: bold;" class="mycode_b">来自 SAMP Wiki</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">目录</h3><br />
<ul class="mycode_list"><li><a href="http://#starting-out" target="_blank" rel="noopener" class="mycode_url">1 入门！</a><br />
</li>
<li><a href="http://#include" target="_blank" rel="noopener" class="mycode_url">1.1 Include</a><br />
</li>
<li><a href="http://#calls" target="_blank" rel="noopener" class="mycode_url">1.2 调用</a><br />
</li>
<li><a href="http://#statements" target="_blank" rel="noopener" class="mycode_url">1.3 语句</a><br />
</li>
<li><a href="http://#functions" target="_blank" rel="noopener" class="mycode_url">2 函数</a><br />
</li>
<li><a href="http://#calling" target="_blank" rel="noopener" class="mycode_url">2.1 调用</a><br />
</li>
<li><a href="http://#defining" target="_blank" rel="noopener" class="mycode_url">2.2 定义</a><br />
</li>
<li><a href="http://#parameters" target="_blank" rel="noopener" class="mycode_url">2.3 参数</a><br />
</li>
<li><a href="http://#variables" target="_blank" rel="noopener" class="mycode_url">3 变量</a><br />
</li>
<li><a href="http://#declaration" target="_blank" rel="noopener" class="mycode_url">3.1 声明</a><br />
</li>
<li><a href="http://#setting" target="_blank" rel="noopener" class="mycode_url">3.2 赋值</a><br />
</li>
<li><a href="http://#arrays" target="_blank" rel="noopener" class="mycode_url">3.3 数组</a><br />
</li>
<li><a href="http://#declaration-2" target="_blank" rel="noopener" class="mycode_url">3.3.1 声明</a><br />
</li>
<li><a href="http://#accessing" target="_blank" rel="noopener" class="mycode_url">3.3.2 访问</a><br />
</li>
<li><a href="http://#example" target="_blank" rel="noopener" class="mycode_url">3.3.3 示例</a><br />
</li>
<li><a href="http://#strings" target="_blank" rel="noopener" class="mycode_url">3.4 字符串</a><br />
</li>
<li><a href="http://#basic-use" target="_blank" rel="noopener" class="mycode_url">3.4.1 基本用法</a><br />
</li>
<li><a href="http://#escape-character" target="_blank" rel="noopener" class="mycode_url">3.4.2 转义字符</a><br />
</li>
<li><a href="http://#tags" target="_blank" rel="noopener" class="mycode_url">3.5 标签</a><br />
</li>
<li><a href="http://#scope" target="_blank" rel="noopener" class="mycode_url">3.6 作用域</a><br />
</li>
<li><a href="http://#local" target="_blank" rel="noopener" class="mycode_url">3.6.1 局部（local）</a><br />
</li>
<li><a href="http://#static-local" target="_blank" rel="noopener" class="mycode_url">3.6.2 静态局部（static local）</a><br />
</li>
<li><a href="http://#global" target="_blank" rel="noopener" class="mycode_url">3.6.3 全局（global）</a><br />
</li>
<li><a href="http://#global-static" target="_blank" rel="noopener" class="mycode_url">3.6.4 全局静态（global static）</a><br />
</li>
<li><a href="http://#control-structures" target="_blank" rel="noopener" class="mycode_url">4 控制结构</a><br />
</li>
<li><a href="http://#keywords" target="_blank" rel="noopener" class="mycode_url">5 关键字</a><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">入门！</h3><br />
<br />
下面是一个可能最简单的脚本示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
我们将逐一讲解各个部分，先从第一行开始。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">Include</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;</code></div></div><br />
这一行会把 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">qawno/includes/open.mp.inc</code> 文件中的所有代码加载到你的脚本中，这样你就可以使用它提供的一切内容。其中它还包含了：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;args&gt;<br />
#include &lt;console&gt;<br />
#include &lt;core&gt;<br />
#include &lt;file&gt;<br />
#include &lt;float&gt;<br />
#include &lt;string&gt;<br />
#include &lt;time&gt;<br />
#include &lt;omp_core&gt;<br />
#include &lt;omp_player&gt;<br />
#include &lt;omp_actor&gt;<br />
#include &lt;omp_checkpoint&gt;<br />
#include &lt;omp_class&gt;<br />
#include &lt;omp_database&gt;<br />
#include &lt;omp_dialog&gt;<br />
#include &lt;omp_gangzone&gt;<br />
#include &lt;omp_http&gt;<br />
#include &lt;omp_menu&gt;<br />
#include &lt;omp_network&gt;<br />
#include &lt;omp_object&gt;<br />
#include &lt;omp_pickup&gt;<br />
#include &lt;omp_textdraw&gt;<br />
#include &lt;omp_variable&gt;<br />
#include &lt;omp_vehicle&gt;<br />
#include &lt;omp_textlabel&gt;<br />
#include &lt;omp_npc&gt;</code></div></div><br />
这些文件包含了 open.mp(samp) 的所有核心功能，因此只需这一行，你就拥有了 open.mp(samp) 的全部函数（函数后面会详细说明）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">调用</h4><br />
<br />
接下来是函数调用的两部分。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main()</code> 是你自己编写代码的函数，由外部调用；<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print(string[])</code> 是代码在别处定义、由你调用的函数。目前这个脚本只会加载、打印一行字符串（即在服务器控制台输出 “Hello World!”，不带引号——这是所有脚本语言的传统），然后结束。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>return 1;</code></div></div><br />
这条语句将值 1 返回给调用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main</code> 的地方，告诉它执行结果（具体返回值在这里不重要，但在其他地方很重要）。<br />
<br />
你现在已经写出了第一个（非常基础）的脚本。如果你在 qawno 中选择“文件 → 新建”，它会给你一个更大的模板，包含所有回调（见下文），包括 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main</code>（严格来说它不是回调，但行为类似）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">语句</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code> 行都以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">;</code>（分号）结尾，分号表示一条<span style="font-weight: bold;" class="mycode_b">语句</span>的结束（语句是一组函数和运算符的组合，用于完成某项操作，类似自然语言中的句子）。大多数人把每条语句写在单独一行，但这不是必须的，只是为了更清晰。下面这种写法同样有效：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!"); <br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1; <br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">{}</code>（大括号）用于将一组语句组合在一起执行（类似自然语言中的段落）。如果你写成：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main() <br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!"); <br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;</code></div></div><br />
编译器会报错，因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return 1;</code> 没有被括起来，不属于 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main</code> 函数。大括号将多条语句组合成一条<span style="font-weight: bold;" class="mycode_b">复合语句</span>，而函数体只能包含一条语句。没有大括号时，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code> 和 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code> 是两条独立的语句，函数只能有一条，所以第二条语句就游离在函数之外，这是非法的。<br />
<br />
不过，你也可以用逗号运算符 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">,</code> 来扩展复合语句，但不推荐这样做（不是最佳编码习惯）。示例如下：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>main() <br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!"), return 1;</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">函数</h3><br />
<br />
函数是一段完成特定任务的代码，可以从其他地方调用。它还可以将执行结果返回给调用它的地方。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">调用</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>print("Hello World!");</code></div></div><br />
如“入门”部分所述，这会调用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code> 函数（定义在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">open.mp.inc</code> 中，所以需要 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#include</code>），并让它在服务器控制台显示 “Hello World!”。<br />
<br />
函数由<span style="font-weight: bold;" class="mycode_b">函数名</span>（如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code>）和<span style="font-weight: bold;" class="mycode_b">参数列表</span>（用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">()</code> 括起来）组成。参数列表向函数传递额外数据。如果没有参数，你就需要成千上万个函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printa();<br />
printaa();<br />
printab();<br />
...</code></div></div><br />
函数可以有任意数量的参数（从 0 开始，至少支持 128 个）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>printf("Hello World!", 1, 2, 3, 4, 5, 6);</code></div></div><br />
现在不用关心这个函数具体做什么，只需知道它有 7 个参数，用逗号分隔。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">定义</h4><br />
<br />
除了调用已有函数，你也可以自己编写并调用函数：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return MyFunction();<br />
}<br />
<br />
MyFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
这段代码功能与最初的示例完全相同，只是结构不同。当模式启动时 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main()</code> 被自动调用，它再调用自定义函数 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MyFunction()</code>。<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MyFunction()</code> 在控制台打印消息，然后返回 1 给 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main()</code>，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">main()</code> 再把这个值返回给服务器。<br />
<br />
因为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return MyFunction();</code> 是一条完整语句，你也可以写成：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
<br />
main() return MyFunction();<br />
<br />
MyFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
但大多数人为了清晰起见还是分开写。你也可以完全不使用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MyFunction</code> 的返回值：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyFunction();<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}<br />
<br />
MyFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print("Hello World!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">参数</h4><br />
<br />
参数是一种特殊的<span style="font-weight: bold;" class="mycode_b">变量</span>，你不需要自己声明，它来自调用函数的地方：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;<br />
<br />
main()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return MyFunction("Hello World!");<br />
}<br />
<br />
MyFunction(const string[])<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;print(string);<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
这段代码功能相同，但现在我们把要显示的内容传给了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MyFunction()</code>。调用时把字符串 “Hello World!” 传递给函数，存储在名为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string</code> 的变量中（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">[]</code> 表示这是一个数组，后面会解释）。然后调用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">print</code>，把 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">string</code> 的内容传给它（没有引号，所以它是一个变量）。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">变量</h3><br />
<br />
变量本质上是内存中的一块空间，用于存储数据，可以随时读取和修改。变量由一个或多个 <span style="font-weight: bold;" class="mycode_b">cell</span> 组成，一个 cell 是 32 位（4 字节），默认有符号，可存储 -2147483648 到 2147483647（注意 -2147483648 在 PAWN 中定义不完善，显示时可能异常）。由多个 cell 组成的变量叫<span style="font-weight: bold;" class="mycode_b">数组</span>，字符串是一种特殊的数组，每个 cell 存放一个字符（打包字符串每个 cell 可存 4 个字符，但这里不讨论）。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">声明</h4><br />
<br />
要创建一个新变量，必须先声明它：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myVariable;</code></div></div><br />
这会创建一个名为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">myVariable</code> 的变量，初始值为 0。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">赋值</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myVariable = 7;</code></div></div><br />
声明变量并设置初始值为 7。现在打印它会显示 7。要打印非字符串变量，需要使用前面提到的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">printf()</code>：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myVariable = 7;<br />
<br />
printf("%d", myVariable);</code></div></div><br />
现在只需知道这会在服务器控制台输出变量的值（当前是 7）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myVariable = 7;<br />
<br />
printf("%d", myVariable);<br />
<br />
myVariable = 8;<br />
<br />
printf("%d", myVariable);</code></div></div><br />
这段代码会先打印 7，然后把变量改为 8，再打印新的值。<br />
<br />
变量操作示例（更多运算符请参考其他章节）：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>myVariable = myVariable + 4;&nbsp;&nbsp; // 等价于<br />
myVariable += 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 增加 4<br />
<br />
myVariable -= 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 减少 4<br />
myVariable *= 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 乘以 4<br />
myVariable /= 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 除以 4</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">数组</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">声明</h4><br />
<br />
数组是一种可以同时存储多个数据、动态访问的变量。数组大小在编译时就固定了，必须提前知道需要多少个槽位。最常见的例子是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_PLAYERS</code> 数组，每个玩家一个槽位，确保数据不会互相干扰。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myArray[5];</code></div></div><br />
这会创建一个有 5 个槽位的数组。<span style="font-weight: bold;" class="mycode_b">不能</span>这样做：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myVariable = 5,<br />
&nbsp;&nbsp;&nbsp;&nbsp;myArray[myVariable];&nbsp;&nbsp;// 错误！</code></div></div><br />
因为 PAWN 在编译时就分配内存，数组大小必须是常量。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">访问</h4><br />
<br />
要给数组某个位置赋值，必须指定下标（index），下标可以是变量：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myArray[5];<br />
<br />
myArray[2] = 7;</code></div></div><br />
数组现在的内容是：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">0, 0, 7, 0, 0</code><br />
<br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：下标从 0 开始计数，而不是 1。<br />
<br />
如果你尝试访问 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">myArray[5]</code>（超出范围），可能会导致服务器崩溃。<br />
<br />
下标可以是数字、变量，甚至是返回值的函数。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myArray[5],<br />
&nbsp;&nbsp;&nbsp;&nbsp;myIndex = 2;<br />
<br />
myArray[myIndex] = 7;</code></div></div><br />
数组中的元素可以像普通变量一样使用：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>myArray[2] = myArray[2] + 1;<br />
myArray[2] += 1;<br />
myArray[2]++;</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">示例</h4><br />
<br />
最常见的数组是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_PLAYERS</code> 数组（<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_PLAYERS</code> 是一个常量，默认 1000）。下面对比用普通变量和数组处理 4 个玩家数据（假设 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_PLAYERS</code> 为 4）：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">传统写法（4 个变量）：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;gPlayer0, gPlayer1, gPlayer2, gPlayer3;<br />
<br />
SetPlayerValue(playerid, value)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;switch (playerid)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 0: gPlayer0 = value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 1: gPlayer1 = value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 2: gPlayer2 = value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 3: gPlayer3 = value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">数组写法（推荐）：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;gPlayers[MAX_PLAYERS];<br />
<br />
SetPlayerValue(playerid, value)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;gPlayers[playerid] = value;<br />
}</code></div></div><br />
数组写法无论玩家数量多少，都只需要一行代码，清晰且高效。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">字符串</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">基本用法</h4><br />
<br />
字符串是一种特殊的数组，用于存放多个字符组成文本。每个字符默认占用一个 cell。字符串以 <span style="font-weight: bold;" class="mycode_b">NULL 终止</span>（遇到 0 就结束，不是字符 '0'）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myString[16] = "Hello World!";</code></div></div><br />
这会创建一个可容纳 15 个字符的字符串，初始值为 “Hello World!”。内部实际存储为：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>104 101 108 108 111 0 x x x x x x x x x x</code></div></div><br />
（0 是终止符，后面的 x 无关紧要）<br />
<br />
你可以像操作数组一样修改字符串：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myString[16] = "Hello World!";<br />
<br />
myString[1] = 97;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 97 是 'a'</code></div></div><br />
结果变为 “hallo”。<br />
<br />
更易读的写法：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>myString[1] = 'a';</code></div></div><br />
单引号表示单个字符。<br />
<br />
把某个位置设为终止符：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>myString[1] = '&#92;0';&nbsp;&nbsp; // 或 = 0;</code></div></div><br />
字符串会变成 “h”。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">转义字符</h4><br />
<br />
反斜杠 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\</code> 是特殊字符，用于创建无法直接输入的字符：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;myString[4] = "&#92;"";&nbsp;&nbsp; // 字符串内容就是一个双引号 "</code></div></div><br />
常用转义序列：<br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">转义符</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">含义</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">说明</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\0</code> / <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">EOS</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">NULL 字符</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">字符串结束</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\n</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">换行</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">Linux 新行（Windows 也可用）</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\r</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">回车</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">Windows 新行用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\r\n</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\\</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">反斜杠</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">实际输出 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\'</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">单引号</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">在单引号中用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">'\' '</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\"</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">双引号</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">在字符串中用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\"</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\xNNN;</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">十六进制字符</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">用十六进制值设置字符</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">\NNN;</code></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">十进制字符</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">用十进制值设置字符</td>
  </tr>
</table>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">标签</h3><br />
<br />
标签是变量的额外信息，用于定义其用途和可使用范围。标签分为强标签（首字母大写）和弱标签。<br />
<br />
示例：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;Float:a = 6.0;</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Float</code> 就是标签，表示这是一个浮点数（小数）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>native SetGravity(Float:gravity);</code></div></div><br />
这要求参数必须是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Float</code> 类型：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SetGravity(6.0);<br />
<br />
new Float:fGrav = 5.0;<br />
<br />
SetGravity(fGrav);</code></div></div><br />
使用错误标签会产生 <span style="font-weight: bold;" class="mycode_b">tag mismatch</span> 警告：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SetGravity(MyTag:7);&nbsp;&nbsp;// 错误</code></div></div><br />
标签区分大小写。<br />
<br />
你可以自定义标签：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new myTag: variable = 0,<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;AppleTag: another = 1;</code></div></div><br />
直接相加时需要用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">_: </code> 去除标签，否则会报标签不匹配。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">作用域</h3><br />
<br />
作用域决定变量在哪里可用。主要有四种：局部、静态局部、全局、全局静态。变量必须先声明后使用。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">局部（local）</h4><br />
<br />
在函数内用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">new</code> 声明：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>MyFunc()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new var1 = 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", var1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new var2 = 8;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%d %d", var1, var2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;// var2 已失效<br />
}<br />
// var1 已失效</code></div></div><br />
局部变量每次进入函数都会重置：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new i = 0; i &lt; 3; i++)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new j = 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;j++;<br />
}</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>1<br />
1<br />
1</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">静态局部（static local）</h4><br />
<br />
与局部变量作用域相同，但值会在函数多次调用间保留：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>for (new i = 0; i &lt; 3; i++)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;static j = 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;j++;<br />
}</code></div></div><br />
输出：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>1<br />
2<br />
3</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">全局（global）</h4><br />
<br />
在函数外声明，可在任何函数中使用，且永不重置：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new<br />
&nbsp;&nbsp;&nbsp;&nbsp;gMyVar = 4;<br />
<br />
MyFunc()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", gMyVar);<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">全局静态（global static）</h4><br />
<br />
与全局类似，但<span style="font-weight: bold;" class="mycode_b">仅限声明所在文件</span>使用：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">File1.pwn</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>static<br />
&nbsp;&nbsp;&nbsp;&nbsp;gs_MyVar = 4;<br />
<br />
MyFunc()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", gs_MyVar);<br />
}<br />
<br />
#include "File2"</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">File2.pwn</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>MyFunc2()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// gs_MyVar 在这里不存在<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", gs_MyVar);&nbsp;&nbsp;// 错误<br />
}</code></div></div><br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">static</code> 也可用于函数，实现类似“私有”函数的效果。<br />
<br />
<hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[SAMP 迁移到 openmp 完整指南 + pawn 编译报错全解析]]></title>
			<link>https://open-mp.cn/showthread.php?tid=18</link>
			<pubDate>Fri, 20 Mar 2026 22:36:25 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=18</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">SAMP 迁移到 openmp 完整指南 + pawn 编译报错全解析</h2><br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>本篇适合：<ul class="mycode_list"><li>已有 SA-MP 服务器，想迁移到 open.mp 的开发者<br />
</li>
<li>在编译时遇到错误不知道怎么处理的新手</blockquote>
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第一部分：迁移步骤</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第一步：下载 open.mp 服务端</h4><br />
<br />
前往 <a href="https://github.com/openmultiplayer/open.mp/releases" target="_blank" rel="noopener" class="mycode_url">https://github.com/openmultiplayer/open.mp/releases</a> 下载最新版本。<br />
<ul class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">open.mp-win-x86.zip</code> — Windows 服务器<br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">open.mp-linux-x86.tar.gz</code> — Linux 服务器<br />
</li>
</ul>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第二步：解压</h4><br />
<br />
目录结构<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>omp-server/<br />
├── components/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← open.mp 原生组件（某些插件放这里而不是 plugins）<br />
├── filterscripts/&nbsp;&nbsp; ← 过滤脚本（辅助脚本）<br />
├── gamemodes/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← 游戏模式（主脚本 .amx 放这里）<br />
├── models/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← 自定义模型文件（.txd .dff）<br />
├── plugins/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← 旧版插件（.dll 或 .so）<br />
├── qawno/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← Pawn 编辑器 + include 头文件<br />
│&nbsp;&nbsp; └── include/&nbsp;&nbsp;&nbsp;&nbsp; ← 把 .inc 头文件放这里<br />
├── scriptfiles/&nbsp;&nbsp;&nbsp;&nbsp; ← INI 文件等资料<br />
├── bans.json&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← 封禁列表<br />
├── config.json&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← 服务器配置（替代 SA-MP 的 server.cfg）<br />
└── omp-server.exe&nbsp;&nbsp; ← 服务器主程序</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第三步：放置脚本插件文件</h4><br />
<ul class="mycode_list"><li>把你的游戏模式 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code> 源文件放入 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gamemodes/</code> 文件夹<br />
</li>
<li>把所需的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.inc</code> 头文件（如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">sscanf2.inc</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">streamer.inc</code>）放入 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">qawno/include/</code><br />
</li>
<li>把插件文件（如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">streamer.dll</code>）放入 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code><br />
</li>
</ul>
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">YSI 用户</span>：需要升级到 <a href="https://github.com/pawn-lang/YSI-Includes/releases" target="_blank" rel="noopener" class="mycode_url">YSI-5.x</a>，YSI-4 与 open.mp 不兼容。</blockquote>
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">FCNPC 用户</span>：FCNPC 插件已被官方 open.mp NPC 组件取代，转换代码即可使用。</blockquote>
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">YSF 用户</span>：open.mp 已内置了大多数 YSF 的原生函数，不再需要 YSF。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：有些插件需要放进 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">components/</code> 而不是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code>，具体查阅以下清单：<br />
<br />
<h5 style="font-size:1.05em;font-weight:bold;margin:10px 0 4px;color:#444;">常见插件</h5><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">插件</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">状态</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">备注</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">Streamer</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code>，正常加载</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">MySQL R41-4</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code>，正常加载</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">CrashDetect</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">开发调试，放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">Whirlpool</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code> 但不建议使用</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">PawnPlus</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code>，open.mp 对其有专项优化</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">pawn-memory</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">JIT</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">代码稳定后可用来提升性能，放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">Profiler</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">性能分析工具，放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">FileManager</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">sscanf</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 放 components/</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/Y-Less/sscanf/releases/tag/v2.13.8" target="_blank" rel="noopener" class="mycode_url">sscanf 2.13.8</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">Pawn.CMD</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 放 components/</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/katursis/Pawn.CMD/releases/tag/3.4.0-omp" target="_blank" rel="noopener" class="mycode_url">3.4.0-omp</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">Pawn.RakNet</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 放 components/</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/katursis/Pawn.RakNet/releases/tag/1.6.0-omp" target="_blank" rel="noopener" class="mycode_url">1.6.0-omp</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">sampvoice</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 放 components/</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/AmyrAhmady/sampvoice/releases/tag/v3.1.5-omp" target="_blank" rel="noopener" class="mycode_url">v3.1.5-omp</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">discord-connector</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 放 components/</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/maddinat0r/samp-discord-connector/releases/tag/v0.3.6-pre" target="_blank" rel="noopener" class="mycode_url">v0.3.6-pre</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">rustext</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">⚠️ 需升级</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/ziggi/rustext/releases/tag/v2.0.11" target="_blank" rel="noopener" class="mycode_url">v2.0.11-nomemhack</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">keylistener</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">⚠️ 需升级</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/edgyaf/keylistener/releases/tag/1.1.2-pr" target="_blank" rel="noopener" class="mycode_url">1.1.2-pr</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">BCrypt</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/Sreyas-Sreelal/samp-bcrypt" target="_blank" rel="noopener" class="mycode_url">samp-bcrypt</a>，密码哈希推荐方案</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">SHA256_PassHash</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 有替代</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 中已标记为废弃，改用 BCrypt</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">nativechecker</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 有替代</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 已内置 native 检查机制，不再需要</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">YSF</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 有替代</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 已内置大多数 YSF 原生函数，不再需要</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">SKY</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 有替代</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">改用 <span style="font-weight: bold;" class="mycode_b">Pawn.RakNet</span></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">中文名插件</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 有替代</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 有内置函数可实现兼容中文昵称</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">FCNPC</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">❌ 不兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 官方内置 NPC 组件，性能更好，不再需要它</td>
  </tr>
</table>
<br />
<hr class="mycode_hr" />
<ul class="mycode_list"><li>plugins/    ← 旧版（legacy）插件放这里，在 config.json 的 legacy_plugins 里加载<br />
</li>
<li>components/ ← open.mp 原生组件放这里，服务器启动时自动加载，无需配置<br />
</li>
</ul>
<br />
以上资料来源个人经验和 open.mp/docs/server/Installation<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第四步：修改 #include</h4><br />
<br />
打开你的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code> 文件，把第一行：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;a_samp&gt;</code></div></div><br />
改为：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;</code></div></div><br />
然后按 <span style="font-weight: bold;" class="mycode_b">F5</span> 编译。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第五步：配置 config.json</h4><br />
<br />
用记事本打开 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">config.json</code>，按需修改：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">加载主图：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"main_scripts": [<br />
&nbsp;&nbsp;&nbsp;&nbsp;"你的脚本文件名 1"<br />
]</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">加载插件：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"legacy_plugins": [<br />
&nbsp;&nbsp;&nbsp;&nbsp;"mysql",<br />
&nbsp;&nbsp;&nbsp;&nbsp;"sscanf",<br />
&nbsp;&nbsp;&nbsp;&nbsp;"streamer"<br />
]</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">加载过滤脚本：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"side_scripts": [<br />
&nbsp;&nbsp;&nbsp;&nbsp;"filterscripts/你的过滤脚本名"<br />
]</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">设置 RCON 密码：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"rcon": {<br />
&nbsp;&nbsp;&nbsp;&nbsp;"allow_teleport": false,<br />
&nbsp;&nbsp;&nbsp;&nbsp;"enable": false,<br />
&nbsp;&nbsp;&nbsp;&nbsp;"password": "你的强密码"<br />
}</code></div></div><br />
<blockquote class="mycode_quote"><cite>引用:</cite>如何把旧的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">server.cfg</code> 转换为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">config.json</code>，参考官方文档：https://www.open.mp/docs/server/config.json</blockquote>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第六步：启动服务器</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Windows：</span> 双击 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">omp-server.exe</code><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Linux：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>chmod +x omp-server<br />
./omp-server</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第二部分：SA-MP 到 open.mp 的变化</h3><br />
<br />
有以下几个变化<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更一：拼写统一为英式英语</h4><br />
<br />
open.mp 将所有函数名统一为英式拼写，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Color</code> 改为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Colour</code>，例如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// SA-MP 写法（会报 warning）<br />
TextDrawBoxColor(textid, 0xFF0000FF);<br />
TextDrawColor(textid, 0xFFFFFFFF);<br />
<br />
// open.mp 正确写法<br />
TextDrawBoxColour(textid, 0xFF0000FF);<br />
TextDrawColour(textid, 0xFFFFFFFF);</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">批量替换方法</span>：在你的编辑器里按 <span style="font-weight: bold;" class="mycode_b">Ctrl+H</span>，把所有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.....Color</code> 替换为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.....Colour</code>。<br />
<br />
如果不想逐个修改，可以在 include 顶部加上：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MIXED_SPELLINGS<br />
#include &lt;open.mp&gt;</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更二：GetPlayerPoolSize 等函数已移除</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetPlayerPoolSize()</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetVehiclePoolSize()</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetActorPoolSize()</code> 这三个函数在 open.mp 中已被移除，因为它们本身就存在 bug（返回的是最高 ID 而不是数量，而且没有玩家时会返回错误数据）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：这些函数不存在了<br />
for(new i = 0; i &lt;= GetPlayerPoolSize(); i++) { }<br />
<br />
// 正确：直接用 MAX_PLAYERS<br />
for(new i = 0; i &lt; MAX_PLAYERS; i++)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(IsPlayerConnected(i)) { }<br />
}<br />
<br />
// 或者用 foreach（需要 YSI）<br />
foreach(new i : Player) { }</code></div></div><br />
同理：<ul class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetPlayerPoolSize()</code> → 换成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_PLAYERS</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetVehiclePoolSize()</code> → 换成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_VEHICLES</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetActorPoolSize()</code> → 换成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_ACTORS</code><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更三：死亡不再自动扣 100 元</h4><br />
<br />
SA-MP 中玩家死亡后会自动扣除 100 元（住院费）。open.mp 移除了这个机制，让脚本自己管理金钱。<br />
<br />
如果你的脚本之前为了「修复」这个扣钱机制，在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerDeath</code> 或 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerSpawn</code> 里手动加了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GivePlayerMoney(playerid, 100)</code>，现在<span style="font-weight: bold;" class="mycode_b">应该删掉这行</span>，否则玩家死亡后反而会多 100 元。<br />
<br />
如果你的脚本确实依赖这个「死亡扣钱」功能，在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerDeath</code> 里手动加上：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public OnPlayerDeath(playerid, killerid, WEAPON:reason)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;GivePlayerMoney(playerid, -100); // 手动模拟死亡扣款<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更四：HideMenuForPlayer 行为修正</h4><br />
<br />
SA-MP 中 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">HideMenuForPlayer</code> 会忽略你传入的菜单 ID，直接关掉玩家当前打开的任意菜单。<br />
<br />
open.mp 修正了这个行为，现在它只会关闭你指定的那个菜单。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// SA-MP 的老写法（在 open.mp 里可能不按预期工作）<br />
HideMenuForPlayer(gShopMenu, playerid);<br />
<br />
// open.mp 正确写法：先获取玩家当前菜单再关闭<br />
HideMenuForPlayer(GetPlayerMenu(playerid), playerid);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更五：SetPlayerAttachedObject 不再跨模式保留</h4><br />
<br />
SA-MP 中玩家身上的附加物件（attached objects）在游戏模式重启后仍然保留。open.mp 修正了这个行为，重启后附加物件会消失。<br />
<br />
如果你需要在模式重启后保留玩家的附加物件，需要在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerConnect</code> 里重新为他设置。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更六：GameText 样式统一（不再渐变）</h4><br />
<br />
SA-MP 中有些 GameText 样式会闪烁、有些会忽略时间参数。open.mp 统一用 TextDraw 重新实现了这些样式，外观相同但不再渐变。如果你的玩家反馈 GameText 显示效果有变化，这是正常现象。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">自动升级工具</h4><br />
<br />
open.mp 提供了一个自动升级工具，可以批量修复旧代码中的 tag 问题、const 问题和拼写问题：<br />
<ul class="mycode_list"><li>工具已包含在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">qawno/upgrader/</code> 文件夹中<br />
</li>
<li>在线版本：https://github.com/openmultiplayer/upgrade<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">建议先用工具跑一遍，再手动处理剩余的报错。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第三部分：编译错误与警告完全手册</h3><br />
<br />
编译器报的信息分两种：<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">error（错误）</span>：必须修复，否则无法生成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.amx</code> 文件<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">warning（警告）</span>：可以运行，但代码存在潜在问题，建议修复<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">常见 Error（错误）</h3><br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 001: expected token</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：期望某个符号但没找到，通常是缺少分号、括号不匹配。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：缺少分号<br />
new gold = 100<br />
SetPlayerHealth(playerid, 100.0)<br />
<br />
// 正确<br />
new gold = 100;<br />
SetPlayerHealth(playerid, 100.0);</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：括号不匹配<br />
if(gold &gt; 0<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// ...<br />
}<br />
<br />
// 正确<br />
if(gold &gt; 0)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// ...<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 017: undefined symbol "xxx"</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：用了一个没有定义过的变量、函数或常量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">最常见的三种原因：</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. 名字拼写错误</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误<br />
SenClientMessage(playerid, -1, "hello"); // 少了 d<br />
new scroe = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 字母顺序错了<br />
<br />
// 正确<br />
SendClientMessage(playerid, -1, "hello");<br />
new score = 0;</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">2. SetTimerEx 的目标函数忘记 forward</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：没有 forward，运行时找不到函数<br />
SetTimerEx("MyFunc", 1000, false, "i", playerid);<br />
<br />
public MyFunc(playerid) { return 1; }<br />
<br />
<br />
// 正确：使用前先 forward<br />
forward MyFunc(playerid);<br />
<br />
SetTimerEx("MyFunc", 1000, false, "i", playerid);<br />
<br />
public MyFunc(playerid) { return 1; }</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">3. 变量在使用之前没有声明</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：先用再声明<br />
gold += 100;<br />
new gold = 0;<br />
<br />
// 正确：先声明再用<br />
new gold = 0;<br />
gold += 100;</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 021: symbol already defined "xxx"</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：同一个名字被定义了两次。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：同名变量重复声明<br />
new gold = 0;<br />
new gold = 100; // 重复了<br />
<br />
// 错误：同名函数重复定义<br />
MyFunction() { return 1; }<br />
MyFunction() { return 0; } // 重复了</code></div></div><br />
也可能是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.inc</code> 文件被 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#include</code> 了两次，导致里面的函数被重复引入。<br />
<br />
解决方法：在每个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.inc</code> 文件顶部加防重复引入守卫：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#if defined _MY_INC<br />
&nbsp;&nbsp;&nbsp;&nbsp;#endinput<br />
#endif<br />
#define _MY_INC</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 025: function heading differs from prototype</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">forward</code> 声明的参数和实际 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 函数的参数不一致，或者参数类型不匹配。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：forward 和 public 参数不一致<br />
forward MyFunc(playerid);<br />
public MyFunc(playerid, value) { return 1; } // 多了一个参数</code></div></div><br />
open.mp 特别常见的情况是回调参数的 tag 不匹配：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误（SA-MP 写法）<br />
public OnPlayerDeath(playerid, killerid, reason)<br />
<br />
// 正确（open.mp 要求 WEAPON: tag）<br />
public OnPlayerDeath(playerid, killerid, WEAPON:reason)</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误<br />
public OnPlayerEditAttachedObject(playerid, response, index, modelid, boneid, ...)<br />
<br />
// 正确（open.mp 要求 EDIT_RESPONSE: tag）<br />
public OnPlayerEditAttachedObject(playerid, EDIT_RESPONSE:response, index, modelid, boneid, ...)</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 010: invalid function or declaration</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：函数定义或声明的语法写错了。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：函数名后面缺括号<br />
MyFunction<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}<br />
<br />
// 正确<br />
MyFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 029: invalid expression, assumed zero</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：表达式写法不合法，通常是运算符用错或者判断写法有问题。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：判断用了单等号（赋值）而不是双等号（比较）<br />
if(gold = 100) { }&nbsp;&nbsp;// 这是赋值，不是比较<br />
<br />
// 正确<br />
if(gold == 100) { }</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 035: argument type mismatch (argument N)</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：函数调用时，第 N 个参数的类型与函数期望的类型不符。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：SetPlayerHealth 需要 Float，传了整数<br />
SetPlayerHealth(playerid, 100);<br />
<br />
// 正确：加小数点<br />
SetPlayerHealth(playerid, 100.0);</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：传了字符串给需要整数的参数<br />
SetPlayerSkin(playerid, "86");<br />
<br />
// 正确<br />
SetPlayerSkin(playerid, 86);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 047: array sizes do not match</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：把一个数组赋值给另一个数组，但两者大小不一样。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new a[10];<br />
new b[20];<br />
a = b; // 错误：大小不同，不能直接赋值<br />
<br />
// 正确：用 for 循环逐元素复制，或者用 memcpy<br />
for(new i = 0; i &lt; 10; i++) a[i] = b[i];</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 004: function not implemented</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：只有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">forward</code> 声明，没有对应的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 函数体。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：只 forward 了，没有写函数体<br />
forward MyFunc(playerid);<br />
// 下面没有 public MyFunc ...<br />
<br />
// 正确：forward 之后要有对应的实现<br />
forward MyFunc(playerid);<br />
public MyFunc(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">常见 Warning（警告）</h3><br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 213: tag mismatch</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：变量或参数的 tag（类型标签）不匹配。这是迁移到 open.mp 最常见的警告。<br />
<br />
open.mp 为很多函数参数增加了 tag，让编译器能检查你传的值是否合理：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：传了普通整数而不是 bool<br />
TogglePlayerControllable(playerid, 1);<br />
<br />
// 正确：用 true/false<br />
TogglePlayerControllable(playerid, true);</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：传了数字而不是枚举值<br />
TextDrawFont(textid, 1);<br />
GivePlayerWeapon(playerid, 4, 1);<br />
<br />
// 正确：用枚举常量<br />
TextDrawFont(textid, TEXT_DRAW_FONT_1);<br />
GivePlayerWeapon(playerid, WEAPON_KNIFE, 1);</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">如果暂时不想处理这些警告</span>，可以在顶部加：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define NO_TAGS<br />
#include &lt;open.mp&gt;<br />
<br />
// 或者只关闭 213 号警告<br />
#pragma warning disable 213</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 234: function is deprecated</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：你用的函数已经过时，open.mp 建议换用新的写法。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">TextDrawColor → TextDrawColour</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>TextDrawColor(textid, 0xFFFFFFFF);&nbsp;&nbsp; // 警告<br />
TextDrawColour(textid, 0xFFFFFFFF);&nbsp;&nbsp;// 正确</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">GetPlayerPoolSize / GetVehiclePoolSize / GetActorPoolSize</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>GetPlayerPoolSize()&nbsp;&nbsp;// 警告：已移除<br />
MAX_PLAYERS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 正确</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">SHA256_PassHash（不安全的密码哈希）</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SHA256_PassHash(...); // 警告：SHA-256 不安全<br />
// 改用 BCrypt：https://github.com/Sreyas-Sreelal/samp-bcrypt</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 214 / 239: const 相关警告</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：把字符串或数组传给没有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 修饰的参数，或者反过来。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：参数应该是 const<br />
public MyFunction(string[])<br />
// 正确：加上 const<br />
public MyFunction(const string[])</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 203: symbol is never used</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：你声明了一个变量或函数，但从来没有使用过。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：声明了但没用<br />
new iUnusedVar = 0;<br />
<br />
MyUnusedFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
解决方法：删掉没用的变量/函数，或者用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">stock</code> 修饰函数告诉编译器「不用也不要警告」：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>stock MyMaybeUnusedFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 204: symbol is assigned a value that is never used</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：给变量赋值了，但这个值从来没被读取。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new iResult = SomeFunction(); // 警告：iResult 赋了值但后面没用到</code></div></div><br />
通常意味着这行代码没有实际效果，检查是否逻辑有误。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 211: possibly unintended assignment</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 条件里用了单等号 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">=</code>，可能是误把赋值写成了比较。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：这是赋值，不是比较，结果永远为 true<br />
if(gold = 100) { }<br />
<br />
// 正确：比较用双等号<br />
if(gold == 100) { }</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 219: local variable shadows a variable at a higher level</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：在内层作用域声明了一个和外层同名的变量，内层的「遮住」了外层的，容易引发逻辑混乱。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new gold = 100; // 外层<br />
<br />
public OnPlayerConnect(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new gold = 50; // 警告：这个 gold 遮住了外层的 gold<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 在这个函数里，gold 指的是 50 那个<br />
}</code></div></div><br />
解决方法：给内层变量换个名字，或者直接用外层变量。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 225: unreachable code</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：有一段代码永远不会被执行到，通常是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code> 后面还有代码。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>MyFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;SendClientMessage(playerid, -1, "这行永远不会执行"); // 警告<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 209: function should return a value</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：函数应该有返回值，但某个分支没有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code>。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：else 分支没有 return<br />
MyFunction(iValue)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(iValue &gt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 如果 iValue &lt;= 0，函数执行完没有 return<br />
}<br />
<br />
// 正确：所有分支都要有 return<br />
MyFunction(iValue)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(iValue &gt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 202: number of arguments does not match definition</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：调用函数时传入的参数数量和函数定义不一致。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 函数定义需要 2 个参数<br />
MyFunction(playerid, value)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}<br />
<br />
// 警告：只传了 1 个参数<br />
MyFunction(playerid);<br />
<br />
// 正确：传够参数<br />
MyFunction(playerid, 100);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">运行时报错（服务器控制台）</h3><br />
<br />
这些不是编译错误，而是服务器运行时打印在控制台的提示。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">Couldn't announce legacy network to open.mp list</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>[Info] Couldn't announce legacy network to open.mp list.<br />
[Info] [Server Error] Status: 406</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：服务器无法被 open.mp 的服务器列表访问到。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">原因</span>：<ul class="mycode_list"><li>你在本地运行，没有公网 IP<br />
</li>
<li>防火墙阻止了对应端口<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">影响</span>：<span style="font-weight: bold;" class="mycode_b">不影响服务器正常运行</span>，玩家仍然可以通过 IP 直连，只是不会显示在公开服务器列表里。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">Insufficient specifiers given to format</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>[Warning] Insufficient specifiers given to `format`: "?" &lt; 1</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">format</code> 函数里，格式字符串中的占位符数量少于你传入的参数数量。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new str[32];<br />
new name[32] = "Tom";<br />
<br />
format(str, sizeof(str), "Hello", name); // 警告：格式字符串里没有 %s，但传了 name<br />
<br />
// 正确<br />
format(str, sizeof(str), "Hello %s", name);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">有用的资源</h3><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">资源</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">地址</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 官方文档</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://open.mp/docs" target="_blank" rel="noopener" class="mycode_url">https://open.mp/docs</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 新增函数列表</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://open.mp/docs/server/omp-functions" target="_blank" rel="noopener" class="mycode_url">https://open.mp/docs/server/omp-functions</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">config.json 配置说明</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://www.open.mp/docs/server/config.json" target="_blank" rel="noopener" class="mycode_url">https://www.open.mp/docs/server/config.json</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">自动升级工具</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/openmultiplayer/upgrade" target="_blank" rel="noopener" class="mycode_url">https://github.com/openmultiplayer/upgrade</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">官方 Discord</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://discord.gg/samp" target="_blank" rel="noopener" class="mycode_url">https://discord.gg/samp</a></td>
  </tr>
</table>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">延伸阅读</h3><br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">地址</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">描述</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/pawn-lang/samp-stdlib/tree/consistency-overhaul" target="_blank" rel="noopener" class="mycode_url">https://github.com/pawn-lang/samp-stdlib...y-overhaul</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">更新后的 SA:MP 包含文件，增加了常量正确性及更多标签。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/samp-incognito/samp-streamer-plugin/pull/435" target="_blank" rel="noopener" class="mycode_url">https://github.com/samp-incognito/samp-s...n/pull/435</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">一个流加载器插件的拉取请求，提供了关于此标签系统的更多信息。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/pawn-lang/compiler/wiki/What's-new#const-correctness" target="_blank" rel="noopener" class="mycode_url">https://github.com/pawn-lang/compiler/wi...orrectness</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">编译器的变更，错误地将常量正确性列为“破坏性”变更。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/pawn-lang/compiler/wiki/Const-Correctness" target="_blank" rel="noopener" class="mycode_url">https://github.com/pawn-lang/compiler/wi...orrectness</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">关于常量正确性及代码更新的更多信息。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/pawn-lang/sa-mp-fixes/" target="_blank" rel="noopener" class="mycode_url">https://github.com/pawn-lang/sa-mp-fixes/</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">许多修复的起源，包括若干已集成至 open.mp 但未在此列出的细微修复。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/pawn-lang/compiler/raw/master/doc/pawn-lang.pdf" target="_blank" rel="noopener" class="mycode_url">https://github.com/pawn-lang/compiler/ra...n-lang.pdf</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">获取有关强标签与弱标签的更多信息。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/openmultiplayer/upgrade" target="_blank" rel="noopener" class="mycode_url">https://github.com/openmultiplayer/upgrade</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">一个可自动完成大量标签与常量正确性升级的工具。</td>
  </tr>
</table>
<br />
如果您在运行服务器时仍有问题，请加入官方的 open.mp Discord 服务器：https://discord.gg/samp<br />
<br />
在 <a href="https://discord.com/channels/231799104731217931/966398440051445790" target="_blank" rel="noopener" class="mycode_url">#openmp-support</a> 频道提问。<br />
<br />
或者在我们的社区群求助: 673335567<br />
<br />
<hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">SAMP 迁移到 openmp 完整指南 + pawn 编译报错全解析</h2><br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>本篇适合：<ul class="mycode_list"><li>已有 SA-MP 服务器，想迁移到 open.mp 的开发者<br />
</li>
<li>在编译时遇到错误不知道怎么处理的新手</blockquote>
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第一部分：迁移步骤</h3><br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第一步：下载 open.mp 服务端</h4><br />
<br />
前往 <a href="https://github.com/openmultiplayer/open.mp/releases" target="_blank" rel="noopener" class="mycode_url">https://github.com/openmultiplayer/open.mp/releases</a> 下载最新版本。<br />
<ul class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">open.mp-win-x86.zip</code> — Windows 服务器<br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">open.mp-linux-x86.tar.gz</code> — Linux 服务器<br />
</li>
</ul>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第二步：解压</h4><br />
<br />
目录结构<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>omp-server/<br />
├── components/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← open.mp 原生组件（某些插件放这里而不是 plugins）<br />
├── filterscripts/&nbsp;&nbsp; ← 过滤脚本（辅助脚本）<br />
├── gamemodes/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← 游戏模式（主脚本 .amx 放这里）<br />
├── models/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← 自定义模型文件（.txd .dff）<br />
├── plugins/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← 旧版插件（.dll 或 .so）<br />
├── qawno/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← Pawn 编辑器 + include 头文件<br />
│&nbsp;&nbsp; └── include/&nbsp;&nbsp;&nbsp;&nbsp; ← 把 .inc 头文件放这里<br />
├── scriptfiles/&nbsp;&nbsp;&nbsp;&nbsp; ← INI 文件等资料<br />
├── bans.json&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← 封禁列表<br />
├── config.json&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;← 服务器配置（替代 SA-MP 的 server.cfg）<br />
└── omp-server.exe&nbsp;&nbsp; ← 服务器主程序</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第三步：放置脚本插件文件</h4><br />
<ul class="mycode_list"><li>把你的游戏模式 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code> 源文件放入 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">gamemodes/</code> 文件夹<br />
</li>
<li>把所需的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.inc</code> 头文件（如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">sscanf2.inc</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">streamer.inc</code>）放入 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">qawno/include/</code><br />
</li>
<li>把插件文件（如 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">streamer.dll</code>）放入 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code><br />
</li>
</ul>
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">YSI 用户</span>：需要升级到 <a href="https://github.com/pawn-lang/YSI-Includes/releases" target="_blank" rel="noopener" class="mycode_url">YSI-5.x</a>，YSI-4 与 open.mp 不兼容。</blockquote>
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">FCNPC 用户</span>：FCNPC 插件已被官方 open.mp NPC 组件取代，转换代码即可使用。</blockquote>
<br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">YSF 用户</span>：open.mp 已内置了大多数 YSF 的原生函数，不再需要 YSF。</blockquote>
<br />
<span style="font-weight: bold;" class="mycode_b">注意</span>：有些插件需要放进 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">components/</code> 而不是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code>，具体查阅以下清单：<br />
<br />
<h5 style="font-size:1.05em;font-weight:bold;margin:10px 0 4px;color:#444;">常见插件</h5><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">插件</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">状态</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">备注</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">Streamer</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code>，正常加载</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">MySQL R41-4</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code>，正常加载</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">CrashDetect</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">开发调试，放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">Whirlpool</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code> 但不建议使用</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">PawnPlus</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code>，open.mp 对其有专项优化</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">pawn-memory</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">JIT</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">代码稳定后可用来提升性能，放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">Profiler</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">性能分析工具，放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">FileManager</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">放 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">plugins/</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">sscanf</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 放 components/</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/Y-Less/sscanf/releases/tag/v2.13.8" target="_blank" rel="noopener" class="mycode_url">sscanf 2.13.8</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">Pawn.CMD</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 放 components/</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/katursis/Pawn.CMD/releases/tag/3.4.0-omp" target="_blank" rel="noopener" class="mycode_url">3.4.0-omp</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">Pawn.RakNet</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 放 components/</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/katursis/Pawn.RakNet/releases/tag/1.6.0-omp" target="_blank" rel="noopener" class="mycode_url">1.6.0-omp</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">sampvoice</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 放 components/</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/AmyrAhmady/sampvoice/releases/tag/v3.1.5-omp" target="_blank" rel="noopener" class="mycode_url">v3.1.5-omp</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">discord-connector</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 放 components/</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/maddinat0r/samp-discord-connector/releases/tag/v0.3.6-pre" target="_blank" rel="noopener" class="mycode_url">v0.3.6-pre</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">rustext</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">⚠️ 需升级</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/ziggi/rustext/releases/tag/v2.0.11" target="_blank" rel="noopener" class="mycode_url">v2.0.11-nomemhack</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">keylistener</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">⚠️ 需升级</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">使用 <a href="https://github.com/edgyaf/keylistener/releases/tag/1.1.2-pr" target="_blank" rel="noopener" class="mycode_url">1.1.2-pr</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">BCrypt</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">✅ 兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/Sreyas-Sreelal/samp-bcrypt" target="_blank" rel="noopener" class="mycode_url">samp-bcrypt</a>，密码哈希推荐方案</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">SHA256_PassHash</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 有替代</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 中已标记为废弃，改用 BCrypt</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">nativechecker</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 有替代</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 已内置 native 检查机制，不再需要</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">YSF</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 有替代</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 已内置大多数 YSF 原生函数，不再需要</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">SKY</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 有替代</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">改用 <span style="font-weight: bold;" class="mycode_b">Pawn.RakNet</span></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">中文名插件</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">? 有替代</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 有内置函数可实现兼容中文昵称</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><span style="font-weight: bold;" class="mycode_b">FCNPC</span></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">❌ 不兼容</td>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 官方内置 NPC 组件，性能更好，不再需要它</td>
  </tr>
</table>
<br />
<hr class="mycode_hr" />
<ul class="mycode_list"><li>plugins/    ← 旧版（legacy）插件放这里，在 config.json 的 legacy_plugins 里加载<br />
</li>
<li>components/ ← open.mp 原生组件放这里，服务器启动时自动加载，无需配置<br />
</li>
</ul>
<br />
以上资料来源个人经验和 open.mp/docs/server/Installation<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第四步：修改 #include</h4><br />
<br />
打开你的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code> 文件，把第一行：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;a_samp&gt;</code></div></div><br />
改为：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#include &lt;open.mp&gt;</code></div></div><br />
然后按 <span style="font-weight: bold;" class="mycode_b">F5</span> 编译。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第五步：配置 config.json</h4><br />
<br />
用记事本打开 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">config.json</code>，按需修改：<br />
<br />
<span style="font-weight: bold;" class="mycode_b">加载主图：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"main_scripts": [<br />
&nbsp;&nbsp;&nbsp;&nbsp;"你的脚本文件名 1"<br />
]</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">加载插件：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"legacy_plugins": [<br />
&nbsp;&nbsp;&nbsp;&nbsp;"mysql",<br />
&nbsp;&nbsp;&nbsp;&nbsp;"sscanf",<br />
&nbsp;&nbsp;&nbsp;&nbsp;"streamer"<br />
]</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">加载过滤脚本：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"side_scripts": [<br />
&nbsp;&nbsp;&nbsp;&nbsp;"filterscripts/你的过滤脚本名"<br />
]</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">设置 RCON 密码：</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>"rcon": {<br />
&nbsp;&nbsp;&nbsp;&nbsp;"allow_teleport": false,<br />
&nbsp;&nbsp;&nbsp;&nbsp;"enable": false,<br />
&nbsp;&nbsp;&nbsp;&nbsp;"password": "你的强密码"<br />
}</code></div></div><br />
<blockquote class="mycode_quote"><cite>引用:</cite>如何把旧的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">server.cfg</code> 转换为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">config.json</code>，参考官方文档：https://www.open.mp/docs/server/config.json</blockquote>
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">第六步：启动服务器</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Windows：</span> 双击 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">omp-server.exe</code><br />
<br />
<span style="font-weight: bold;" class="mycode_b">Linux：</span><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>chmod +x omp-server<br />
./omp-server</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第二部分：SA-MP 到 open.mp 的变化</h3><br />
<br />
有以下几个变化<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更一：拼写统一为英式英语</h4><br />
<br />
open.mp 将所有函数名统一为英式拼写，<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Color</code> 改为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">Colour</code>，例如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// SA-MP 写法（会报 warning）<br />
TextDrawBoxColor(textid, 0xFF0000FF);<br />
TextDrawColor(textid, 0xFFFFFFFF);<br />
<br />
// open.mp 正确写法<br />
TextDrawBoxColour(textid, 0xFF0000FF);<br />
TextDrawColour(textid, 0xFFFFFFFF);</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">批量替换方法</span>：在你的编辑器里按 <span style="font-weight: bold;" class="mycode_b">Ctrl+H</span>，把所有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.....Color</code> 替换为 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.....Colour</code>。<br />
<br />
如果不想逐个修改，可以在 include 顶部加上：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define MIXED_SPELLINGS<br />
#include &lt;open.mp&gt;</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更二：GetPlayerPoolSize 等函数已移除</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetPlayerPoolSize()</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetVehiclePoolSize()</code>、<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetActorPoolSize()</code> 这三个函数在 open.mp 中已被移除，因为它们本身就存在 bug（返回的是最高 ID 而不是数量，而且没有玩家时会返回错误数据）。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：这些函数不存在了<br />
for(new i = 0; i &lt;= GetPlayerPoolSize(); i++) { }<br />
<br />
// 正确：直接用 MAX_PLAYERS<br />
for(new i = 0; i &lt; MAX_PLAYERS; i++)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(IsPlayerConnected(i)) { }<br />
}<br />
<br />
// 或者用 foreach（需要 YSI）<br />
foreach(new i : Player) { }</code></div></div><br />
同理：<ul class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetPlayerPoolSize()</code> → 换成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_PLAYERS</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetVehiclePoolSize()</code> → 换成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_VEHICLES</code><br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetActorPoolSize()</code> → 换成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">MAX_ACTORS</code><br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更三：死亡不再自动扣 100 元</h4><br />
<br />
SA-MP 中玩家死亡后会自动扣除 100 元（住院费）。open.mp 移除了这个机制，让脚本自己管理金钱。<br />
<br />
如果你的脚本之前为了「修复」这个扣钱机制，在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerDeath</code> 或 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerSpawn</code> 里手动加了 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GivePlayerMoney(playerid, 100)</code>，现在<span style="font-weight: bold;" class="mycode_b">应该删掉这行</span>，否则玩家死亡后反而会多 100 元。<br />
<br />
如果你的脚本确实依赖这个「死亡扣钱」功能，在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerDeath</code> 里手动加上：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public OnPlayerDeath(playerid, killerid, WEAPON:reason)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;GivePlayerMoney(playerid, -100); // 手动模拟死亡扣款<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更四：HideMenuForPlayer 行为修正</h4><br />
<br />
SA-MP 中 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">HideMenuForPlayer</code> 会忽略你传入的菜单 ID，直接关掉玩家当前打开的任意菜单。<br />
<br />
open.mp 修正了这个行为，现在它只会关闭你指定的那个菜单。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// SA-MP 的老写法（在 open.mp 里可能不按预期工作）<br />
HideMenuForPlayer(gShopMenu, playerid);<br />
<br />
// open.mp 正确写法：先获取玩家当前菜单再关闭<br />
HideMenuForPlayer(GetPlayerMenu(playerid), playerid);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更五：SetPlayerAttachedObject 不再跨模式保留</h4><br />
<br />
SA-MP 中玩家身上的附加物件（attached objects）在游戏模式重启后仍然保留。open.mp 修正了这个行为，重启后附加物件会消失。<br />
<br />
如果你需要在模式重启后保留玩家的附加物件，需要在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerConnect</code> 里重新为他设置。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">变更六：GameText 样式统一（不再渐变）</h4><br />
<br />
SA-MP 中有些 GameText 样式会闪烁、有些会忽略时间参数。open.mp 统一用 TextDraw 重新实现了这些样式，外观相同但不再渐变。如果你的玩家反馈 GameText 显示效果有变化，这是正常现象。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">自动升级工具</h4><br />
<br />
open.mp 提供了一个自动升级工具，可以批量修复旧代码中的 tag 问题、const 问题和拼写问题：<br />
<ul class="mycode_list"><li>工具已包含在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">qawno/upgrader/</code> 文件夹中<br />
</li>
<li>在线版本：https://github.com/openmultiplayer/upgrade<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">建议先用工具跑一遍，再手动处理剩余的报错。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">第三部分：编译错误与警告完全手册</h3><br />
<br />
编译器报的信息分两种：<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">error（错误）</span>：必须修复，否则无法生成 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.amx</code> 文件<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">warning（警告）</span>：可以运行，但代码存在潜在问题，建议修复<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">常见 Error（错误）</h3><br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 001: expected token</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：期望某个符号但没找到，通常是缺少分号、括号不匹配。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：缺少分号<br />
new gold = 100<br />
SetPlayerHealth(playerid, 100.0)<br />
<br />
// 正确<br />
new gold = 100;<br />
SetPlayerHealth(playerid, 100.0);</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：括号不匹配<br />
if(gold &gt; 0<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// ...<br />
}<br />
<br />
// 正确<br />
if(gold &gt; 0)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// ...<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 017: undefined symbol "xxx"</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：用了一个没有定义过的变量、函数或常量。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">最常见的三种原因：</span><br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. 名字拼写错误</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误<br />
SenClientMessage(playerid, -1, "hello"); // 少了 d<br />
new scroe = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 字母顺序错了<br />
<br />
// 正确<br />
SendClientMessage(playerid, -1, "hello");<br />
new score = 0;</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">2. SetTimerEx 的目标函数忘记 forward</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：没有 forward，运行时找不到函数<br />
SetTimerEx("MyFunc", 1000, false, "i", playerid);<br />
<br />
public MyFunc(playerid) { return 1; }<br />
<br />
<br />
// 正确：使用前先 forward<br />
forward MyFunc(playerid);<br />
<br />
SetTimerEx("MyFunc", 1000, false, "i", playerid);<br />
<br />
public MyFunc(playerid) { return 1; }</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">3. 变量在使用之前没有声明</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：先用再声明<br />
gold += 100;<br />
new gold = 0;<br />
<br />
// 正确：先声明再用<br />
new gold = 0;<br />
gold += 100;</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 021: symbol already defined "xxx"</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：同一个名字被定义了两次。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：同名变量重复声明<br />
new gold = 0;<br />
new gold = 100; // 重复了<br />
<br />
// 错误：同名函数重复定义<br />
MyFunction() { return 1; }<br />
MyFunction() { return 0; } // 重复了</code></div></div><br />
也可能是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.inc</code> 文件被 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">#include</code> 了两次，导致里面的函数被重复引入。<br />
<br />
解决方法：在每个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.inc</code> 文件顶部加防重复引入守卫：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#if defined _MY_INC<br />
&nbsp;&nbsp;&nbsp;&nbsp;#endinput<br />
#endif<br />
#define _MY_INC</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 025: function heading differs from prototype</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">forward</code> 声明的参数和实际 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 函数的参数不一致，或者参数类型不匹配。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：forward 和 public 参数不一致<br />
forward MyFunc(playerid);<br />
public MyFunc(playerid, value) { return 1; } // 多了一个参数</code></div></div><br />
open.mp 特别常见的情况是回调参数的 tag 不匹配：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误（SA-MP 写法）<br />
public OnPlayerDeath(playerid, killerid, reason)<br />
<br />
// 正确（open.mp 要求 WEAPON: tag）<br />
public OnPlayerDeath(playerid, killerid, WEAPON:reason)</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误<br />
public OnPlayerEditAttachedObject(playerid, response, index, modelid, boneid, ...)<br />
<br />
// 正确（open.mp 要求 EDIT_RESPONSE: tag）<br />
public OnPlayerEditAttachedObject(playerid, EDIT_RESPONSE:response, index, modelid, boneid, ...)</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 010: invalid function or declaration</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：函数定义或声明的语法写错了。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：函数名后面缺括号<br />
MyFunction<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}<br />
<br />
// 正确<br />
MyFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 029: invalid expression, assumed zero</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：表达式写法不合法，通常是运算符用错或者判断写法有问题。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：判断用了单等号（赋值）而不是双等号（比较）<br />
if(gold = 100) { }&nbsp;&nbsp;// 这是赋值，不是比较<br />
<br />
// 正确<br />
if(gold == 100) { }</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 035: argument type mismatch (argument N)</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：函数调用时，第 N 个参数的类型与函数期望的类型不符。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：SetPlayerHealth 需要 Float，传了整数<br />
SetPlayerHealth(playerid, 100);<br />
<br />
// 正确：加小数点<br />
SetPlayerHealth(playerid, 100.0);</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：传了字符串给需要整数的参数<br />
SetPlayerSkin(playerid, "86");<br />
<br />
// 正确<br />
SetPlayerSkin(playerid, 86);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 047: array sizes do not match</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：把一个数组赋值给另一个数组，但两者大小不一样。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new a[10];<br />
new b[20];<br />
a = b; // 错误：大小不同，不能直接赋值<br />
<br />
// 正确：用 for 循环逐元素复制，或者用 memcpy<br />
for(new i = 0; i &lt; 10; i++) a[i] = b[i];</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">error 004: function not implemented</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：只有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">forward</code> 声明，没有对应的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 函数体。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 错误：只 forward 了，没有写函数体<br />
forward MyFunc(playerid);<br />
// 下面没有 public MyFunc ...<br />
<br />
// 正确：forward 之后要有对应的实现<br />
forward MyFunc(playerid);<br />
public MyFunc(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">常见 Warning（警告）</h3><br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 213: tag mismatch</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：变量或参数的 tag（类型标签）不匹配。这是迁移到 open.mp 最常见的警告。<br />
<br />
open.mp 为很多函数参数增加了 tag，让编译器能检查你传的值是否合理：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：传了普通整数而不是 bool<br />
TogglePlayerControllable(playerid, 1);<br />
<br />
// 正确：用 true/false<br />
TogglePlayerControllable(playerid, true);</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：传了数字而不是枚举值<br />
TextDrawFont(textid, 1);<br />
GivePlayerWeapon(playerid, 4, 1);<br />
<br />
// 正确：用枚举常量<br />
TextDrawFont(textid, TEXT_DRAW_FONT_1);<br />
GivePlayerWeapon(playerid, WEAPON_KNIFE, 1);</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">如果暂时不想处理这些警告</span>，可以在顶部加：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>#define NO_TAGS<br />
#include &lt;open.mp&gt;<br />
<br />
// 或者只关闭 213 号警告<br />
#pragma warning disable 213</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 234: function is deprecated</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：你用的函数已经过时，open.mp 建议换用新的写法。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">TextDrawColor → TextDrawColour</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>TextDrawColor(textid, 0xFFFFFFFF);&nbsp;&nbsp; // 警告<br />
TextDrawColour(textid, 0xFFFFFFFF);&nbsp;&nbsp;// 正确</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">GetPlayerPoolSize / GetVehiclePoolSize / GetActorPoolSize</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>GetPlayerPoolSize()&nbsp;&nbsp;// 警告：已移除<br />
MAX_PLAYERS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 正确</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">SHA256_PassHash（不安全的密码哈希）</span><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SHA256_PassHash(...); // 警告：SHA-256 不安全<br />
// 改用 BCrypt：https://github.com/Sreyas-Sreelal/samp-bcrypt</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 214 / 239: const 相关警告</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：把字符串或数组传给没有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">const</code> 修饰的参数，或者反过来。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：参数应该是 const<br />
public MyFunction(string[])<br />
// 正确：加上 const<br />
public MyFunction(const string[])</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 203: symbol is never used</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：你声明了一个变量或函数，但从来没有使用过。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：声明了但没用<br />
new iUnusedVar = 0;<br />
<br />
MyUnusedFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
解决方法：删掉没用的变量/函数，或者用 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">stock</code> 修饰函数告诉编译器「不用也不要警告」：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>stock MyMaybeUnusedFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 204: symbol is assigned a value that is never used</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：给变量赋值了，但这个值从来没被读取。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new iResult = SomeFunction(); // 警告：iResult 赋了值但后面没用到</code></div></div><br />
通常意味着这行代码没有实际效果，检查是否逻辑有误。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 211: possibly unintended assignment</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：在 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">if</code> 条件里用了单等号 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">=</code>，可能是误把赋值写成了比较。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：这是赋值，不是比较，结果永远为 true<br />
if(gold = 100) { }<br />
<br />
// 正确：比较用双等号<br />
if(gold == 100) { }</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 219: local variable shadows a variable at a higher level</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：在内层作用域声明了一个和外层同名的变量，内层的「遮住」了外层的，容易引发逻辑混乱。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new gold = 100; // 外层<br />
<br />
public OnPlayerConnect(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;new gold = 50; // 警告：这个 gold 遮住了外层的 gold<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 在这个函数里，gold 指的是 50 那个<br />
}</code></div></div><br />
解决方法：给内层变量换个名字，或者直接用外层变量。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 225: unreachable code</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：有一段代码永远不会被执行到，通常是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code> 后面还有代码。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>MyFunction()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;SendClientMessage(playerid, -1, "这行永远不会执行"); // 警告<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 209: function should return a value</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：函数应该有返回值，但某个分支没有 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return</code>。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 警告：else 分支没有 return<br />
MyFunction(iValue)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(iValue &gt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 如果 iValue &lt;= 0，函数执行完没有 return<br />
}<br />
<br />
// 正确：所有分支都要有 return<br />
MyFunction(iValue)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(iValue &gt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br />
}</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">warning 202: number of arguments does not match definition</h4><br />
<br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：调用函数时传入的参数数量和函数定义不一致。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 函数定义需要 2 个参数<br />
MyFunction(playerid, value)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}<br />
<br />
// 警告：只传了 1 个参数<br />
MyFunction(playerid);<br />
<br />
// 正确：传够参数<br />
MyFunction(playerid, 100);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">运行时报错（服务器控制台）</h3><br />
<br />
这些不是编译错误，而是服务器运行时打印在控制台的提示。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">Couldn't announce legacy network to open.mp list</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>[Info] Couldn't announce legacy network to open.mp list.<br />
[Info] [Server Error] Status: 406</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：服务器无法被 open.mp 的服务器列表访问到。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">原因</span>：<ul class="mycode_list"><li>你在本地运行，没有公网 IP<br />
</li>
<li>防火墙阻止了对应端口<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">影响</span>：<span style="font-weight: bold;" class="mycode_b">不影响服务器正常运行</span>，玩家仍然可以通过 IP 直连，只是不会显示在公开服务器列表里。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">Insufficient specifiers given to format</h4><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>[Warning] Insufficient specifiers given to `format`: "?" &lt; 1</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">含义</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">format</code> 函数里，格式字符串中的占位符数量少于你传入的参数数量。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>new str[32];<br />
new name[32] = "Tom";<br />
<br />
format(str, sizeof(str), "Hello", name); // 警告：格式字符串里没有 %s，但传了 name<br />
<br />
// 正确<br />
format(str, sizeof(str), "Hello %s", name);</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">有用的资源</h3><br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">资源</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">地址</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 官方文档</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://open.mp/docs" target="_blank" rel="noopener" class="mycode_url">https://open.mp/docs</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">open.mp 新增函数列表</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://open.mp/docs/server/omp-functions" target="_blank" rel="noopener" class="mycode_url">https://open.mp/docs/server/omp-functions</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">config.json 配置说明</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://www.open.mp/docs/server/config.json" target="_blank" rel="noopener" class="mycode_url">https://www.open.mp/docs/server/config.json</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">自动升级工具</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/openmultiplayer/upgrade" target="_blank" rel="noopener" class="mycode_url">https://github.com/openmultiplayer/upgrade</a></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">官方 Discord</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://discord.gg/samp" target="_blank" rel="noopener" class="mycode_url">https://discord.gg/samp</a></td>
  </tr>
</table>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">延伸阅读</h3><br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">地址</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">描述</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/pawn-lang/samp-stdlib/tree/consistency-overhaul" target="_blank" rel="noopener" class="mycode_url">https://github.com/pawn-lang/samp-stdlib...y-overhaul</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">更新后的 SA:MP 包含文件，增加了常量正确性及更多标签。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/samp-incognito/samp-streamer-plugin/pull/435" target="_blank" rel="noopener" class="mycode_url">https://github.com/samp-incognito/samp-s...n/pull/435</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">一个流加载器插件的拉取请求，提供了关于此标签系统的更多信息。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/pawn-lang/compiler/wiki/What's-new#const-correctness" target="_blank" rel="noopener" class="mycode_url">https://github.com/pawn-lang/compiler/wi...orrectness</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">编译器的变更，错误地将常量正确性列为“破坏性”变更。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/pawn-lang/compiler/wiki/Const-Correctness" target="_blank" rel="noopener" class="mycode_url">https://github.com/pawn-lang/compiler/wi...orrectness</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">关于常量正确性及代码更新的更多信息。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/pawn-lang/sa-mp-fixes/" target="_blank" rel="noopener" class="mycode_url">https://github.com/pawn-lang/sa-mp-fixes/</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">许多修复的起源，包括若干已集成至 open.mp 但未在此列出的细微修复。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/pawn-lang/compiler/raw/master/doc/pawn-lang.pdf" target="_blank" rel="noopener" class="mycode_url">https://github.com/pawn-lang/compiler/ra...n-lang.pdf</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">获取有关强标签与弱标签的更多信息。</td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;"><a href="https://github.com/openmultiplayer/upgrade" target="_blank" rel="noopener" class="mycode_url">https://github.com/openmultiplayer/upgrade</a></td>
    <td style="border:1px solid #ddd;padding:6px 10px;">一个可自动完成大量标签与常量正确性升级的工具。</td>
  </tr>
</table>
<br />
如果您在运行服务器时仍有问题，请加入官方的 open.mp Discord 服务器：https://discord.gg/samp<br />
<br />
在 <a href="https://discord.com/channels/231799104731217931/966398440051445790" target="_blank" rel="noopener" class="mycode_url">#openmp-support</a> 频道提问。<br />
<br />
或者在我们的社区群求助: 673335567<br />
<br />
<hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[零基础开发openmp/SAMP服务器基础教程 - 第一章]]></title>
			<link>https://open-mp.cn/showthread.php?tid=17</link>
			<pubDate>Fri, 20 Mar 2026 21:38:31 +0800</pubDate>
			<dc:creator><![CDATA[<a href="https://open-mp.cn/member.php?action=profile&uid=3">小鸟unsigned</a>]]></dc:creator>
			<guid isPermaLink="false">https://open-mp.cn/showthread.php?tid=17</guid>
			<description><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">零基础开发openmp/SAMP服务器基础教程 - 第一章</h2><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">写给完全没接触过编程的你</h4><br />
<br />
零基础开发openmp/SAMP服务器基础教程一共有三个篇章，此为第一篇，按顺序学习阅读即可<br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>这篇文章不会让你马上写出任何代码。<br />
它只做一件事：<span style="font-weight: bold;" class="mycode_b">让你在打开编辑器之前，脑子里先有一张地图。</span><br />
有了这张地图，后面学什么都会快很多。</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">你可能正处于这样的处境</h4><br />
<br />
你玩过 SAMP 联机，看到别的服务器有各种有趣的玩法，心里想：这个我也想做。<br />
<br />
然后你搜了一下教程，打开了一个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code> 文件，看到满屏的英文字母和括号符号，看不懂。<br />
<br />
然后关掉了。<br />
<br />
这不是你的问题。是大多数教程默认你已经有一些基础，直接跳过了最重要的第一步——<span style="font-weight: bold;" class="mycode_b">建立认知</span>。<br />
<br />
这篇文章就是来补这一步的。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">理解底层逻辑</h4><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>理解这些尤为重要，是一切的起点。本篇将优先使用新手能理解的大白话进行讲解。</blockquote>
<br />
计算机是一个非常听话但非常死板的工具，先忘掉代码，我们来聊聊计算机到底是什么。<br />
<br />
比方说地图导航软件<br />
<br />
你输入目的地，导航会告诉你：前方 200 米左转，然后直行 500 米，到达目的地。<br />
<br />
导航给出的是一步一步的<span style="font-weight: bold;" class="mycode_b">指令</span>，你只需要跟着做。如果你在它说左转的时候右转了，它不会生气，也不会猜你的意思，它只会重新计算，继续给你下一条指令。<br />
<br />
计算机就是这样的。<br />
<br />
它只会严格地、一条接一条地执行你给它的指令。<br />
<br />
它不会猜，不会发挥，不会应该是这个意思吧帮你圆场。你说什么，它做什么。你没说的，它绝对不做。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">而编程，就是把你的想法翻译成计算机能看懂的指令。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">这件事没有你想的那么神秘</h4><br />
<br />
很多人会觉得这是某种神秘的技术，像外星文字一样难以理解。<br />
<br />
但你其实每天都在做类似的事情。<br />
<br />
假设你要告诉一个<span style="font-weight: bold;" class="mycode_b">什么都不懂</span>的人，怎么帮你冲一杯咖啡，你会怎么说？<br />
<br />
你不能说帮我冲杯咖啡，因为他不知道冲咖啡是什么意思。<br />
<br />
你需要说：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>1. 走到茶水间<br />
2. 从柜子里取出咖啡粉<br />
3. 打开水壶，确认里面有水<br />
4. 按下水壶开关，等待水烧开<br />
5. 取出一个杯子<br />
6. 在杯子里放入一勺咖啡粉<br />
7. 把烧开的水倒进杯子里<br />
8. 搅拌均匀</code></div></div><br />
你写的这份说明书，其实就是一段程序。<br />
<br />
你是在把帮我冲咖啡这个模糊的想法，拆分成一步一步清晰的指令。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">编程做的事情，和这个完全一样。</span><br />
<br />
唯一的区别是：你的指令不是写给人看的，是写给计算机看的，所以要用计算机能懂的语法来写。<br />
<br />
学编程，本质上是在学把事情说清楚，编程里真正难的不是记住语法，而是<span style="font-weight: bold;" class="mycode_b">把你的想法说得足够清楚、足够准确</span>，清楚到计算机能执行。想法是模糊的。你需要把它变得更具体，这就是代码背后的思维过程。语法是最后才出现的东西，在这之前，你要先把逻辑想清楚。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">为什么代码要用奇怪的语法写？</h4><br />
<br />
为什么不能直接用中文写？直接告诉电脑给玩家 100 块钱不行吗？<br />
<br />
因为计算机本身只认识 0 和 1，它不理解任何人类语言。<br />
<br />
所以人们发明了编程语言——它是人和计算机之间的翻译官。<br />
<br />
编程语言的语法比中文严格得多，但也简单得多。<br />
<br />
中文有几万个汉字，有各种语气、歧义、修辞。编程语言通常只有几十个固定的关键词，每一个词只有一个意思，没有歧义。<br />
<br />
比如在 Pawn 里：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>if&nbsp;&nbsp; → 如果<br />
else → 否则<br />
new&nbsp;&nbsp;→ 新建一个变量（容器）<br />
return → 返回一个结果，并结束</code></div></div><br />
就这些，你能用的词总共就这么多。其他所有千变万化的功能，都是用这些基础词拼出来的。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">所以，代码并不是在用一门你不认识的语言说话，它只是在用一套更严格的格式，表达你本来就会表达的逻辑。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">不会就查，查了才会</h4><br />
<br />
open.mp 有完整的官方文档，里面列出了所有可用的函数和回调，以及每个函数怎么用、参数是什么意思。<br />
<br />
地址：https://open.mp/docs<br />
<br />
养成看文档的习惯，这是最重要的自学能力。当你查了文档、搜了搜索引擎，还是搞不定，这时候可以去问人<br />
<br />
<span style="font-weight: bold;" class="mycode_b">不好的问法：</span>为什么我的代码不行？<br />
<br />
<span style="font-weight: bold;" class="mycode_b">好的问法：</span>我想实现玩家加入时显示欢迎消息，我写了这段代码（贴上代码），编译没有报错，但玩家加入时没有收到消息，请问可能是什么原因？<br />
<br />
把你的代码、你的预期、你观察到的现象都说清楚，别人才能帮你快速定位问题。你描述问题的清晰程度，决定了你能得到帮助的速度。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">报错，是编译器在帮你</h4><br />
<br />
报错信息是编译器（帮你把代码翻译成计算机能运行的文件的工具）在帮你找问题。<br />
<br />
报错信息通常会告诉你两件事：<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">哪一行出了问题</span>（行号）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">出了什么问题</span>（错误描述）<br />
</li>
</ul>
<br />
就算是工作了十年的程序员，每天也在面对 bug（程序里的错误）。<br />
<br />
但是pawn相对简单很多，熟悉了之后，有时都不需要实际测试都可以直接通过看代码预判出运行的效果。<br />
<br />
<hr class="mycode_hr" />
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">进入正题</h2><br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">Pawn 是什么</h3><br />
<br />
Pawn 是一种为游戏服务器设计的轻量脚本语言，不是通用高级语言。<br />
<br />
对于想学习编程的人来说，它是一个很好的起点——因为你写的代码可以立刻在游戏里看到效果，这种即时反馈会让你进步很快。<br />
<br />
本质上，这是在用C 语言的思维写游戏逻辑。学会 Pawn 的人，以后转 C/C++、Rust 都很快。在国外有不少人通过 SA-MP 开发找到了工作，后来接触到了 C++、PHP、JavaScript 等更复杂的方向。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">脚本文件是什么</h3><br />
<br />
你写的 Pawn 代码保存在一个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code> 文件里，这就是你的脚本源码。<br />
<br />
写完后需要经过<span style="font-weight: bold;" class="mycode_b">编译</span>，把 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code> 变成服务器能运行的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.amx</code> 文件，服务器加载的是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.amx</code>，不是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code>。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>你写的代码&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编译&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;服务器运行<br />
myscript.pwn&nbsp;&nbsp;→&nbsp;&nbsp;myscript.amx&nbsp;&nbsp;→&nbsp;&nbsp;open.mp 加载执行</code></div></div><br />
这个过程就像你写了一份中文食谱，翻译成机器能理解的语言，机器才能按步骤操作。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">单线程</h3><br />
<br />
目前你只需要知道一件事：<span style="font-weight: bold;" class="mycode_b">Pawn 服务器是单线程的</span>。<br />
<br />
单线程意味着：整个服务器只有一条流水线，所有逻辑、计算只能排着队一个一个处理，同一时间只能执行一条指令。<br />
<br />
举个例子：假设你写了一段代码需要执行 1 秒钟，那在这 1 秒内，服务器上其他所有事情都会停下来等它跑完，包括玩家的移动同步、其他玩家的操作响应。<br />
<br />
早期玩过 RPG 服的应该有印象——每到发薪日，服务器会卡顿一下。就是因为给所有玩家结算工资的代码在单线程里跑完之前，所有事件都被暂停了。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">结论：写代码要注重性能，避免一段逻辑执行时间过长。单条简单的加减、判断代码几乎是瞬间完成的（微秒级别），这类代码完全不用担心。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">理解 Tick（帧）</h3><br />
<br />
open.mp 默认每秒运行 <span style="font-weight: bold;" class="mycode_b">30 个 tick（帧）</span>，也就是每秒打包、更新、同步 30 次数据。<br />
<br />
如果网络不好（玩家或服务器任意一方），就可能出现某次 tick 的数据包没有成功传输，也就是俗称的<span style="font-weight: bold;" class="mycode_b">丢包</span>。<br />
<br />
比如连续两秒没收到玩家的位置数据，第三秒突然收到了，就会出现我们常见的<span style="font-weight: bold;" class="mycode_b">瞬移</span>现象。网络好的情况下，每帧数据几乎全部到达，玩家动作就很平滑。<br />
<br />
即使你什么逻辑都没写，open.mp 每个 tick 也会自动同步这些基础数据：<br />
<ul class="mycode_list"><li>玩家位置、朝向<br />
</li>
<li>玩家动作状态<br />
</li>
<li>武器信息<br />
</li>
<li>血量和护甲<br />
</li>
<li>车辆位置、朝向<br />
</li>
<li>玩家按键状态<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">从玩家操作到游戏表现，完整流程</h3><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>玩家操作<br />
&nbsp;&nbsp;↓<br />
客户端生成数据包，通过 UDP 发送到服务端<br />
&nbsp;&nbsp;↓<br />
服务端接收数据包，自动触发对应的回调函数<br />
&nbsp;&nbsp;↓<br />
回调内的 Pawn 代码执行，修改服务器内存里的数据<br />
&nbsp;&nbsp;↓<br />
Tick 结束，服务器把最新数据同步给所有客户端<br />
&nbsp;&nbsp;↓<br />
玩家在游戏里看到最终表现</code></div></div><br />
不同的玩家操作，会触发不同的回调：<br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">玩家操作</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">触发的回调</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">移动位置</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerUpdate</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">开枪</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerWeaponShot</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">按下按键</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerKeyStateChange</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">操作对话框</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnDialogResponse</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">死亡</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerDeath</code></td>
  </tr>
</table>
<br />
<span style="font-weight: bold;" class="mycode_b">举个例子：友伤保护</span><br />
<br />
当玩家开枪，触发 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerWeaponShot</code>。在这个回调里，你可以判断被击中的是不是队友，如果是队友就让伤害为 0：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(IsTeamMate(playerid, hitid))<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0; // 返回 0 = 取消这次子弹伤害<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1; // 返回 1 = 允许子弹正常造成伤害<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">再举个例子：对话框治疗</span><br />
<br />
当玩家操作对话框，触发 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnDialogResponse</code>。判断玩家选了哪个选项，然后执行对应逻辑：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(listitem == 2) // 第三个选项（listitem 从 0 开始，0=第一个，1=第二个，2=第三个）<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetPlayerHealth(playerid, 100.0); // 设置血量为 100<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">注意</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">listitem</code> 从 <span style="font-weight: bold;" class="mycode_b">0</span> 开始计数，第一个选项是 0，第二个是 1，第三个是 2，以此类推。这是新手非常容易犯错的地方。</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">关于作弊</h3><br />
<br />
服务器收到的数据，默认是信任客户端发来的。作弊工具就是利用这一点，篡改客户端发出的数据包（比如把血量改成 10000、位置瞬移到某处），服务器收到后会直接把这些数据同步给其他玩家，其他人就会看到无敌血条、飞天瞬移。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetPlayerMoney</code> 获取的就是客户端发来的金钱数据。如果你没有用服务端自己的变量记录玩家金钱，就相当于完全信任了客户端，没有任何验证。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">解决方法：重要的数据（血量、金钱、等级等）永远在服务端自己维护，不信任客户端发来的数值。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">什么是回调（Callback）</h3><br />
<br />
回调是服务端<span style="font-weight: bold;" class="mycode_b">自动触发</span>的函数，触发时机是服务端提前定好的，你不需要手动调用它。<br />
<br />
你能做的是：在这个函数里写你自己的逻辑。<br />
<br />
所有服务端自带的回调都以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public On</code> 开头，比如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public OnPlayerConnect(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 当有玩家连入服务器时，这里的代码会自动执行<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}<br />
<br />
public OnPlayerDeath(playerid, killerid, reason)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 当有玩家死亡时，这里的代码会自动执行<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">public 是什么意思</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 表示这个函数是公开的，可以被服务端直接调用。服务端自带的回调必须加 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code>，否则服务端找不到它，触发时就不会执行你写的代码。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">return 1 是什么意思</h4><br />
<br />
函数执行完毕后，需要返回一个结果告诉服务端处理完了。<br />
<ul class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return 1</code> = 正常处理，允许默认行为继续<br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return 0</code> = 在某些回调里代表拦截/取消这次事件（比如上面的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerWeaponShot</code> 返回 0 取消伤害）<br />
</li>
</ul>
<br />
具体每个回调返回 0 和 1 各代表什么，查文档就知道。新手阶段统一写 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return 1</code> 不会出大问题。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">每个回调都是一个独立的房间</h4><br />
<br />
回调的范围 = 花括号 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">{}</code> 包着的所有内容。从 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">{</code> 到 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">}</code> 之间的所有代码都属于这个回调。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public OnPlayerConnect(playerid)<br />
{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← 房间开始<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 这里的代码属于 OnPlayerConnect<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 玩家连入时执行<br />
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← 房间结束</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">什么是函数</h3><br />
<br />
函数是一个<span style="font-weight: bold;" class="mycode_b">工具</span>，你不需要知道它内部怎么实现的，只需要知道怎么用、给它传什么参数、它会做什么事。<br />
<br />
就像微波炉：你不需要知道微波炉的电路原理，只需要把食物放进去、设好时间、按启动，它就帮你加热。<br />
<br />
服务端自带大约 1000 个左右的函数，每个函数从名字上就能大致猜到它的作用：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SetPlayerHealth(playerid, Float:health)&nbsp;&nbsp;// 设置玩家血量<br />
SetPlayerSkin(playerid, skinid)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 修改玩家皮肤<br />
SendClientMessage(playerid, color, msg) // 给玩家发送聊天消息<br />
GivePlayerMoney(playerid, money)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 给玩家钱（负数是扣钱）<br />
GetPlayerPos(playerid, Float:x, Float:y, Float:z) // 获取玩家坐标</code></div></div><br />
括号里是参数，告诉函数对谁做做什么。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">能不能自己创建函数</h3><br />
<br />
可以。当你发现一段代码要重复写很多次，就该把它打包成函数。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 没有函数：每次都要重复写<br />
GivePlayerMoney(playerid, 500);<br />
SetPlayerHealth(playerid, 100.0);<br />
SendClientMessage(playerid, -1, "欢迎奖励已发放");<br />
<br />
// 下一个地方又要写一遍...<br />
GivePlayerMoney(playerid, 500);<br />
SetPlayerHealth(playerid, 100.0);<br />
SendClientMessage(playerid, -1, "欢迎奖励已发放");</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 有了函数：打包一次，随时调用<br />
GiveWelcomeReward(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;GivePlayerMoney(playerid, 500);<br />
&nbsp;&nbsp;&nbsp;&nbsp;SetPlayerHealth(playerid, 100.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;SendClientMessage(playerid, -1, "欢迎奖励已发放");<br />
}<br />
<br />
// 需要用的地方只需要一行<br />
GiveWelcomeReward(playerid);</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">什么时候该建函数？</span> 一段逻辑在两个以上的地方用到，或者逻辑比较复杂、需要给它起个名字方便理解，就建函数。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">能不能用别人写好的函数</h3><br />
<br />
可以，这就是<span style="font-weight: bold;" class="mycode_b">安装插件和依赖库</span>。<br />
<br />
你不需要为了拧一颗螺丝自己炼钢做螺丝刀，直接去五金店买一把就好了。<br />
<br />
别人做好的功能，打包成插件，你直接引入使用，不需要知道内部原理。<br />
<br />
不过在用之前可以留意几点：<ul class="mycode_list"><li>它会不会消耗大量服务器性能？<br />
</li>
<li>作者是否持续维护？<br />
</li>
<li>社区是否有人在用、有没有已知的 bug？<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">去哪里找？</span> Github 搜索，或者 open.mp 官方推荐列表：https://open.mp/docs/awesome<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">回调的执行顺序</h3><br />
<br />
回调不是按固定顺序排好的，而是<span style="font-weight: bold;" class="mycode_b">由 tick 中收到了什么数据来决定</span>。<br />
<br />
玩家没有做某个操作，对应的回调就不会触发。<br />
<br />
如果一个玩家在同一个 tick 内同时触发了多个操作（极罕见），服务器会把这些事件排成队列，在单线程里一个接一个处理。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">但回调内部的代码，是严格从上到下一行一行执行的。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">代码写在哪里</h3><br />
<br />
所有实际运行的代码，都必须写在某个回调的花括号里面。<br />
<br />
写在外面的只能是：变量声明、函数定义、常量定义。<br />
<br />
你自己写的函数，不会自动运行，必须在某个回调里主动调用它，才会被执行：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 这个函数不会自动运行<br />
MyFunction(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SendClientMessage(playerid, -1, "你好");<br />
}<br />
<br />
// 必须在某个回调里调用它，才会执行<br />
public OnPlayerConnect(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyFunction(playerid); // ← 在这里调用，玩家连入时才会执行<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
可以把服务器想象成一台自动售货机：投币（玩家操作）会触发里面固定的机械流程（服务端回调）。你想加功能，只能在原有流程的某个环节里接线（在回调里调用你自己写的函数），你的代码不会凭空自己运行。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">决定你高度的关键因素</h3><br />
<br />
掌握了上面这些，你已经理解了 open.mp 服务端运行的核心原理。剩下的，本质上都是数学和逻辑问题。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">但有一件事只能靠你自己做：查文档。</span><br />
<br />
你能实现什么功能，取决于你知道多少回调和函数的存在。不需要把所有函数都背下来，但你需要通过不断查阅，建立起自己的工具库认知——知道有什么工具可以用，需要的时候去查怎么用。<br />
<br />
官方文档：https://open.mp/docs<br />
<br />
交流群：673335567<br />
<br />
新手最常犯的错误是：遇到不会的功能，直接问别人这个怎么做，但别人告诉你思路了，你又不知道用哪个函数实现。<br />
<br />
根本原因是对现有工具了解太少。<span style="font-weight: bold;" class="mycode_b">多看文档，多看别人的开源脚本</span>，这是没有捷径的积累过程。<br />
<br />
你知道的越多，能做的就越多。<br />
<br />
<hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></description>
			<content:encoded><![CDATA[<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">零基础开发openmp/SAMP服务器基础教程 - 第一章</h2><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">写给完全没接触过编程的你</h4><br />
<br />
零基础开发openmp/SAMP服务器基础教程一共有三个篇章，此为第一篇，按顺序学习阅读即可<br />
<br />
<hr class="mycode_hr" />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>这篇文章不会让你马上写出任何代码。<br />
它只做一件事：<span style="font-weight: bold;" class="mycode_b">让你在打开编辑器之前，脑子里先有一张地图。</span><br />
有了这张地图，后面学什么都会快很多。</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">你可能正处于这样的处境</h4><br />
<br />
你玩过 SAMP 联机，看到别的服务器有各种有趣的玩法，心里想：这个我也想做。<br />
<br />
然后你搜了一下教程，打开了一个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code> 文件，看到满屏的英文字母和括号符号，看不懂。<br />
<br />
然后关掉了。<br />
<br />
这不是你的问题。是大多数教程默认你已经有一些基础，直接跳过了最重要的第一步——<span style="font-weight: bold;" class="mycode_b">建立认知</span>。<br />
<br />
这篇文章就是来补这一步的。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">理解底层逻辑</h4><br />
<br />
<blockquote class="mycode_quote"><cite>引用:</cite>理解这些尤为重要，是一切的起点。本篇将优先使用新手能理解的大白话进行讲解。</blockquote>
<br />
计算机是一个非常听话但非常死板的工具，先忘掉代码，我们来聊聊计算机到底是什么。<br />
<br />
比方说地图导航软件<br />
<br />
你输入目的地，导航会告诉你：前方 200 米左转，然后直行 500 米，到达目的地。<br />
<br />
导航给出的是一步一步的<span style="font-weight: bold;" class="mycode_b">指令</span>，你只需要跟着做。如果你在它说左转的时候右转了，它不会生气，也不会猜你的意思，它只会重新计算，继续给你下一条指令。<br />
<br />
计算机就是这样的。<br />
<br />
它只会严格地、一条接一条地执行你给它的指令。<br />
<br />
它不会猜，不会发挥，不会应该是这个意思吧帮你圆场。你说什么，它做什么。你没说的，它绝对不做。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">而编程，就是把你的想法翻译成计算机能看懂的指令。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">这件事没有你想的那么神秘</h4><br />
<br />
很多人会觉得这是某种神秘的技术，像外星文字一样难以理解。<br />
<br />
但你其实每天都在做类似的事情。<br />
<br />
假设你要告诉一个<span style="font-weight: bold;" class="mycode_b">什么都不懂</span>的人，怎么帮你冲一杯咖啡，你会怎么说？<br />
<br />
你不能说帮我冲杯咖啡，因为他不知道冲咖啡是什么意思。<br />
<br />
你需要说：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>1. 走到茶水间<br />
2. 从柜子里取出咖啡粉<br />
3. 打开水壶，确认里面有水<br />
4. 按下水壶开关，等待水烧开<br />
5. 取出一个杯子<br />
6. 在杯子里放入一勺咖啡粉<br />
7. 把烧开的水倒进杯子里<br />
8. 搅拌均匀</code></div></div><br />
你写的这份说明书，其实就是一段程序。<br />
<br />
你是在把帮我冲咖啡这个模糊的想法，拆分成一步一步清晰的指令。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">编程做的事情，和这个完全一样。</span><br />
<br />
唯一的区别是：你的指令不是写给人看的，是写给计算机看的，所以要用计算机能懂的语法来写。<br />
<br />
学编程，本质上是在学把事情说清楚，编程里真正难的不是记住语法，而是<span style="font-weight: bold;" class="mycode_b">把你的想法说得足够清楚、足够准确</span>，清楚到计算机能执行。想法是模糊的。你需要把它变得更具体，这就是代码背后的思维过程。语法是最后才出现的东西，在这之前，你要先把逻辑想清楚。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">为什么代码要用奇怪的语法写？</h4><br />
<br />
为什么不能直接用中文写？直接告诉电脑给玩家 100 块钱不行吗？<br />
<br />
因为计算机本身只认识 0 和 1，它不理解任何人类语言。<br />
<br />
所以人们发明了编程语言——它是人和计算机之间的翻译官。<br />
<br />
编程语言的语法比中文严格得多，但也简单得多。<br />
<br />
中文有几万个汉字，有各种语气、歧义、修辞。编程语言通常只有几十个固定的关键词，每一个词只有一个意思，没有歧义。<br />
<br />
比如在 Pawn 里：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>if&nbsp;&nbsp; → 如果<br />
else → 否则<br />
new&nbsp;&nbsp;→ 新建一个变量（容器）<br />
return → 返回一个结果，并结束</code></div></div><br />
就这些，你能用的词总共就这么多。其他所有千变万化的功能，都是用这些基础词拼出来的。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">所以，代码并不是在用一门你不认识的语言说话，它只是在用一套更严格的格式，表达你本来就会表达的逻辑。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">不会就查，查了才会</h4><br />
<br />
open.mp 有完整的官方文档，里面列出了所有可用的函数和回调，以及每个函数怎么用、参数是什么意思。<br />
<br />
地址：https://open.mp/docs<br />
<br />
养成看文档的习惯，这是最重要的自学能力。当你查了文档、搜了搜索引擎，还是搞不定，这时候可以去问人<br />
<br />
<span style="font-weight: bold;" class="mycode_b">不好的问法：</span>为什么我的代码不行？<br />
<br />
<span style="font-weight: bold;" class="mycode_b">好的问法：</span>我想实现玩家加入时显示欢迎消息，我写了这段代码（贴上代码），编译没有报错，但玩家加入时没有收到消息，请问可能是什么原因？<br />
<br />
把你的代码、你的预期、你观察到的现象都说清楚，别人才能帮你快速定位问题。你描述问题的清晰程度，决定了你能得到帮助的速度。<br />
<br />
<hr class="mycode_hr" />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">报错，是编译器在帮你</h4><br />
<br />
报错信息是编译器（帮你把代码翻译成计算机能运行的文件的工具）在帮你找问题。<br />
<br />
报错信息通常会告诉你两件事：<br />
<ul class="mycode_list"><li><span style="font-weight: bold;" class="mycode_b">哪一行出了问题</span>（行号）<br />
</li>
<li><span style="font-weight: bold;" class="mycode_b">出了什么问题</span>（错误描述）<br />
</li>
</ul>
<br />
就算是工作了十年的程序员，每天也在面对 bug（程序里的错误）。<br />
<br />
但是pawn相对简单很多，熟悉了之后，有时都不需要实际测试都可以直接通过看代码预判出运行的效果。<br />
<br />
<hr class="mycode_hr" />
<br />
<h2 style="font-size:1.8em;font-weight:bold;border-bottom:2px solid #aaa;padding-bottom:5px;margin:20px 0 10px;">进入正题</h2><br />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">Pawn 是什么</h3><br />
<br />
Pawn 是一种为游戏服务器设计的轻量脚本语言，不是通用高级语言。<br />
<br />
对于想学习编程的人来说，它是一个很好的起点——因为你写的代码可以立刻在游戏里看到效果，这种即时反馈会让你进步很快。<br />
<br />
本质上，这是在用C 语言的思维写游戏逻辑。学会 Pawn 的人，以后转 C/C++、Rust 都很快。在国外有不少人通过 SA-MP 开发找到了工作，后来接触到了 C++、PHP、JavaScript 等更复杂的方向。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">脚本文件是什么</h3><br />
<br />
你写的 Pawn 代码保存在一个 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code> 文件里，这就是你的脚本源码。<br />
<br />
写完后需要经过<span style="font-weight: bold;" class="mycode_b">编译</span>，把 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code> 变成服务器能运行的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.amx</code> 文件，服务器加载的是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.amx</code>，不是 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">.pwn</code>。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>你写的代码&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编译&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;服务器运行<br />
myscript.pwn&nbsp;&nbsp;→&nbsp;&nbsp;myscript.amx&nbsp;&nbsp;→&nbsp;&nbsp;open.mp 加载执行</code></div></div><br />
这个过程就像你写了一份中文食谱，翻译成机器能理解的语言，机器才能按步骤操作。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">单线程</h3><br />
<br />
目前你只需要知道一件事：<span style="font-weight: bold;" class="mycode_b">Pawn 服务器是单线程的</span>。<br />
<br />
单线程意味着：整个服务器只有一条流水线，所有逻辑、计算只能排着队一个一个处理，同一时间只能执行一条指令。<br />
<br />
举个例子：假设你写了一段代码需要执行 1 秒钟，那在这 1 秒内，服务器上其他所有事情都会停下来等它跑完，包括玩家的移动同步、其他玩家的操作响应。<br />
<br />
早期玩过 RPG 服的应该有印象——每到发薪日，服务器会卡顿一下。就是因为给所有玩家结算工资的代码在单线程里跑完之前，所有事件都被暂停了。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">结论：写代码要注重性能，避免一段逻辑执行时间过长。单条简单的加减、判断代码几乎是瞬间完成的（微秒级别），这类代码完全不用担心。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">理解 Tick（帧）</h3><br />
<br />
open.mp 默认每秒运行 <span style="font-weight: bold;" class="mycode_b">30 个 tick（帧）</span>，也就是每秒打包、更新、同步 30 次数据。<br />
<br />
如果网络不好（玩家或服务器任意一方），就可能出现某次 tick 的数据包没有成功传输，也就是俗称的<span style="font-weight: bold;" class="mycode_b">丢包</span>。<br />
<br />
比如连续两秒没收到玩家的位置数据，第三秒突然收到了，就会出现我们常见的<span style="font-weight: bold;" class="mycode_b">瞬移</span>现象。网络好的情况下，每帧数据几乎全部到达，玩家动作就很平滑。<br />
<br />
即使你什么逻辑都没写，open.mp 每个 tick 也会自动同步这些基础数据：<br />
<ul class="mycode_list"><li>玩家位置、朝向<br />
</li>
<li>玩家动作状态<br />
</li>
<li>武器信息<br />
</li>
<li>血量和护甲<br />
</li>
<li>车辆位置、朝向<br />
</li>
<li>玩家按键状态<br />
</li>
</ul>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">从玩家操作到游戏表现，完整流程</h3><br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>玩家操作<br />
&nbsp;&nbsp;↓<br />
客户端生成数据包，通过 UDP 发送到服务端<br />
&nbsp;&nbsp;↓<br />
服务端接收数据包，自动触发对应的回调函数<br />
&nbsp;&nbsp;↓<br />
回调内的 Pawn 代码执行，修改服务器内存里的数据<br />
&nbsp;&nbsp;↓<br />
Tick 结束，服务器把最新数据同步给所有客户端<br />
&nbsp;&nbsp;↓<br />
玩家在游戏里看到最终表现</code></div></div><br />
不同的玩家操作，会触发不同的回调：<br />
<br />
<table style="border-collapse:collapse;width:100%;margin:10px 0;">
  <tr>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">玩家操作</th>
    <th style="background:#e8e8e8;border:1px solid #ccc;padding:7px 10px;text-align:left;font-weight:bold;">触发的回调</th>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">移动位置</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerUpdate</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">开枪</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerWeaponShot</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">按下按键</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerKeyStateChange</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">操作对话框</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnDialogResponse</code></td>
  </tr>
  <tr>
    <td style="border:1px solid #ddd;padding:6px 10px;">死亡</td>
    <td style="border:1px solid #ddd;padding:6px 10px;"><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerDeath</code></td>
  </tr>
</table>
<br />
<span style="font-weight: bold;" class="mycode_b">举个例子：友伤保护</span><br />
<br />
当玩家开枪，触发 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerWeaponShot</code>。在这个回调里，你可以判断被击中的是不是队友，如果是队友就让伤害为 0：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(IsTeamMate(playerid, hitid))<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0; // 返回 0 = 取消这次子弹伤害<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1; // 返回 1 = 允许子弹正常造成伤害<br />
}</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">再举个例子：对话框治疗</span><br />
<br />
当玩家操作对话框，触发 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnDialogResponse</code>。判断玩家选了哪个选项，然后执行对应逻辑：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(listitem == 2) // 第三个选项（listitem 从 0 开始，0=第一个，1=第二个，2=第三个）<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetPlayerHealth(playerid, 100.0); // 设置血量为 100<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<blockquote class="mycode_quote"><cite>引用:</cite><span style="font-weight: bold;" class="mycode_b">注意</span>：<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">listitem</code> 从 <span style="font-weight: bold;" class="mycode_b">0</span> 开始计数，第一个选项是 0，第二个是 1，第三个是 2，以此类推。这是新手非常容易犯错的地方。</blockquote>
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">关于作弊</h3><br />
<br />
服务器收到的数据，默认是信任客户端发来的。作弊工具就是利用这一点，篡改客户端发出的数据包（比如把血量改成 10000、位置瞬移到某处），服务器收到后会直接把这些数据同步给其他玩家，其他人就会看到无敌血条、飞天瞬移。<br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">GetPlayerMoney</code> 获取的就是客户端发来的金钱数据。如果你没有用服务端自己的变量记录玩家金钱，就相当于完全信任了客户端，没有任何验证。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">解决方法：重要的数据（血量、金钱、等级等）永远在服务端自己维护，不信任客户端发来的数值。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">什么是回调（Callback）</h3><br />
<br />
回调是服务端<span style="font-weight: bold;" class="mycode_b">自动触发</span>的函数，触发时机是服务端提前定好的，你不需要手动调用它。<br />
<br />
你能做的是：在这个函数里写你自己的逻辑。<br />
<br />
所有服务端自带的回调都以 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public On</code> 开头，比如：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public OnPlayerConnect(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 当有玩家连入服务器时，这里的代码会自动执行<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}<br />
<br />
public OnPlayerDeath(playerid, killerid, reason)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 当有玩家死亡时，这里的代码会自动执行<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">public 是什么意思</h4><br />
<br />
<code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code> 表示这个函数是公开的，可以被服务端直接调用。服务端自带的回调必须加 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">public</code>，否则服务端找不到它，触发时就不会执行你写的代码。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">return 1 是什么意思</h4><br />
<br />
函数执行完毕后，需要返回一个结果告诉服务端处理完了。<br />
<ul class="mycode_list"><li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return 1</code> = 正常处理，允许默认行为继续<br />
</li>
<li><code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return 0</code> = 在某些回调里代表拦截/取消这次事件（比如上面的 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">OnPlayerWeaponShot</code> 返回 0 取消伤害）<br />
</li>
</ul>
<br />
具体每个回调返回 0 和 1 各代表什么，查文档就知道。新手阶段统一写 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">return 1</code> 不会出大问题。<br />
<br />
<h4 style="font-size:1.15em;font-weight:bold;margin:12px 0 6px;">每个回调都是一个独立的房间</h4><br />
<br />
回调的范围 = 花括号 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">{}</code> 包着的所有内容。从 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">{</code> 到 <code style="background:#f0f0f0;border:1px solid #ddd;padding:1px 5px;border-radius:3px;font-family:Consolas,monospace;font-size:0.9em;">}</code> 之间的所有代码都属于这个回调。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>public OnPlayerConnect(playerid)<br />
{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← 房间开始<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 这里的代码属于 OnPlayerConnect<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 玩家连入时执行<br />
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ← 房间结束</code></div></div><br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">什么是函数</h3><br />
<br />
函数是一个<span style="font-weight: bold;" class="mycode_b">工具</span>，你不需要知道它内部怎么实现的，只需要知道怎么用、给它传什么参数、它会做什么事。<br />
<br />
就像微波炉：你不需要知道微波炉的电路原理，只需要把食物放进去、设好时间、按启动，它就帮你加热。<br />
<br />
服务端自带大约 1000 个左右的函数，每个函数从名字上就能大致猜到它的作用：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>SetPlayerHealth(playerid, Float:health)&nbsp;&nbsp;// 设置玩家血量<br />
SetPlayerSkin(playerid, skinid)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 修改玩家皮肤<br />
SendClientMessage(playerid, color, msg) // 给玩家发送聊天消息<br />
GivePlayerMoney(playerid, money)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 给玩家钱（负数是扣钱）<br />
GetPlayerPos(playerid, Float:x, Float:y, Float:z) // 获取玩家坐标</code></div></div><br />
括号里是参数，告诉函数对谁做做什么。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">能不能自己创建函数</h3><br />
<br />
可以。当你发现一段代码要重复写很多次，就该把它打包成函数。<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 没有函数：每次都要重复写<br />
GivePlayerMoney(playerid, 500);<br />
SetPlayerHealth(playerid, 100.0);<br />
SendClientMessage(playerid, -1, "欢迎奖励已发放");<br />
<br />
// 下一个地方又要写一遍...<br />
GivePlayerMoney(playerid, 500);<br />
SetPlayerHealth(playerid, 100.0);<br />
SendClientMessage(playerid, -1, "欢迎奖励已发放");</code></div></div><br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 有了函数：打包一次，随时调用<br />
GiveWelcomeReward(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;GivePlayerMoney(playerid, 500);<br />
&nbsp;&nbsp;&nbsp;&nbsp;SetPlayerHealth(playerid, 100.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;SendClientMessage(playerid, -1, "欢迎奖励已发放");<br />
}<br />
<br />
// 需要用的地方只需要一行<br />
GiveWelcomeReward(playerid);</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">什么时候该建函数？</span> 一段逻辑在两个以上的地方用到，或者逻辑比较复杂、需要给它起个名字方便理解，就建函数。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">能不能用别人写好的函数</h3><br />
<br />
可以，这就是<span style="font-weight: bold;" class="mycode_b">安装插件和依赖库</span>。<br />
<br />
你不需要为了拧一颗螺丝自己炼钢做螺丝刀，直接去五金店买一把就好了。<br />
<br />
别人做好的功能，打包成插件，你直接引入使用，不需要知道内部原理。<br />
<br />
不过在用之前可以留意几点：<ul class="mycode_list"><li>它会不会消耗大量服务器性能？<br />
</li>
<li>作者是否持续维护？<br />
</li>
<li>社区是否有人在用、有没有已知的 bug？<br />
</li>
</ul>
<br />
<span style="font-weight: bold;" class="mycode_b">去哪里找？</span> Github 搜索，或者 open.mp 官方推荐列表：https://open.mp/docs/awesome<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">回调的执行顺序</h3><br />
<br />
回调不是按固定顺序排好的，而是<span style="font-weight: bold;" class="mycode_b">由 tick 中收到了什么数据来决定</span>。<br />
<br />
玩家没有做某个操作，对应的回调就不会触发。<br />
<br />
如果一个玩家在同一个 tick 内同时触发了多个操作（极罕见），服务器会把这些事件排成队列，在单线程里一个接一个处理。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">但回调内部的代码，是严格从上到下一行一行执行的。</span><br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">代码写在哪里</h3><br />
<br />
所有实际运行的代码，都必须写在某个回调的花括号里面。<br />
<br />
写在外面的只能是：变量声明、函数定义、常量定义。<br />
<br />
你自己写的函数，不会自动运行，必须在某个回调里主动调用它，才会被执行：<br />
<br />
<div class="codeblock"><div class="title">代码:</div><div class="body" dir="ltr"><code>// 这个函数不会自动运行<br />
MyFunction(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;SendClientMessage(playerid, -1, "你好");<br />
}<br />
<br />
// 必须在某个回调里调用它，才会执行<br />
public OnPlayerConnect(playerid)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;MyFunction(playerid); // ← 在这里调用，玩家连入时才会执行<br />
&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br />
}</code></div></div><br />
可以把服务器想象成一台自动售货机：投币（玩家操作）会触发里面固定的机械流程（服务端回调）。你想加功能，只能在原有流程的某个环节里接线（在回调里调用你自己写的函数），你的代码不会凭空自己运行。<br />
<br />
<hr class="mycode_hr" />
<br />
<h3 style="font-size:1.4em;font-weight:bold;border-bottom:1px solid #ddd;padding-bottom:4px;margin:16px 0 8px;">决定你高度的关键因素</h3><br />
<br />
掌握了上面这些，你已经理解了 open.mp 服务端运行的核心原理。剩下的，本质上都是数学和逻辑问题。<br />
<br />
<span style="font-weight: bold;" class="mycode_b">但有一件事只能靠你自己做：查文档。</span><br />
<br />
你能实现什么功能，取决于你知道多少回调和函数的存在。不需要把所有函数都背下来，但你需要通过不断查阅，建立起自己的工具库认知——知道有什么工具可以用，需要的时候去查怎么用。<br />
<br />
官方文档：https://open.mp/docs<br />
<br />
交流群：673335567<br />
<br />
新手最常犯的错误是：遇到不会的功能，直接问别人这个怎么做，但别人告诉你思路了，你又不知道用哪个函数实现。<br />
<br />
根本原因是对现有工具了解太少。<span style="font-weight: bold;" class="mycode_b">多看文档，多看别人的开源脚本</span>，这是没有捷径的积累过程。<br />
<br />
你知道的越多，能做的就越多。<br />
<br />
<hr class="mycode_hr" />
<br />
#GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa#<br />
<br />
社区交流群: 673335567<br />
<br />
论坛: <a href="https://open-mp.cn/" target="_blank" rel="noopener" class="mycode_url">https://open-mp.cn/</a>]]></content:encoded>
		</item>
	</channel>
</rss>