Rage(PC) Modding Notes 狂怒 制作模组 指南

( 相对于原来的英语文档,我将我用 翻译工具和我自己翻译的一些粘贴在这里,如有错误,请包

涵,很多英语我确实暂时不会,只能翻译了一部分,相对于原来的英语文章至少看的下去)                   

_________________________________________

              

                                    Rage(PC)

                                 Modding Notes

                                

                   _________________________________________

                   

                                Nov 19, 2014

                                 Draft 1.01

                              Written by:  Dheu

______________________________________Notes____________________________________

This Document looks best in a fixed-width font, such as Courier New.

此文档最好使用 固定宽度的字体,例如 新宋体。(?翻译可能有误)

-------------------------------------------------------------------------------

                              Table of Contents:目录:

-------------------------------------------------------------------------------

  I.       Basics

    I.1       Requirements  需求

    I.2       Recommendations 推荐,建议

    I.3       Game Architecture  游戏体系结构

    I.4       Using the Game Console  使用 游戏控制台

    I.5       Console Variables  控制台变量

    I.6       Standard Tools  标准工具 /标准工具栏

    I.7       Best Practices最佳实践

I.8       Hard verus Easy changes  困难vs简单的变化

  II.      Getting Started  入门指南;准备开始

    II.1      Installation 安装

    II.2      Setting up Software Change Management 设置软件 变更 管理

II.3      Fix Bugs 修复错误

  III.     Hello World Popup Message         Hello World  弹出消息

    III.1     Adding Strings             添加字符串

    III.2     Tutorial Messages       教程 的 消息

III.3     Firing a Job event          触发Job事件

   IV.      Scripting 脚本。   

    IV.1      Basics         基础;基本要素

    Iv.2      Common Commands  常用命令

    Iv.3      Action Script         行为脚本

    IV.4      Map Scripts and Event Handlers  地图脚本和事件处理程序

    IV.5      Global Scripts and Event Handlers 全局脚本和事件处理器

    IV.6        Persisting data          持久化数据                

    IV.7      Global Script Memory Limits  全局脚本内存限制

IV.8      DECL Pathing         //  DECL路径控制

  V.       Editing and Customizing NPCs  编辑和定制npc

    V.1       Mr. Potato Head style  土豆头先生风格

    V.2       Deforming Models with Blender  变形模型与 Blender (应该是Blender3d软件)

V.3       Animations 动画

  VI.      Adding Textures     添加纹理

    VI.1     Simple Textures (ie for Icons)   简单纹理(如图标)

    VI.2     Textures for models  模型的纹理

VI.3     Splash Screens for Maps 地图启动画面

  VII.     Adding Sounds and Audio 添加声音和音频

  VIII.    NPCs   非玩家角色

 VIII.1     Followers   追随者

VIII.2      Setting up Interaction/Activation Handlers 设置交互/激活处理程序

VIII.3     Merchantsn. 商人( merchant的名词复数 );(某活动的)爱好者,热衷于…的人

VIII.4     Animations 动画

  IX.      Building, Dependencies and Deployment  构建、依赖关系和部署

    IX.1       Map Mods             地图模块

    IX.2       Asset/Script Mods  资产/脚本模块

    IX.2       When it fails  开发运维手册

  X.       External Appendix  附录

     A.       Console Commands  控制台命令

     B.       Console Variables  控制台变量

     C.       ID Script Full listing id 脚本 完整清单

     D.       Script operations  脚本 操作

===============================================================================

I. > > > >  Basics   基础;基本要素

===============================================================================

  

  The Rage Tool Kit (ID Studio) comes with several tutorials that focused on

  making new maps from the assets that ship with Rage. These notes therefore

  do not cover the subjects addressed by those tutorials. Rather these notes

  cover subjects outside the scope of the tutorials that come with Rage Tool

  Kit.

狂怒工具包(ID Studio)附带了几个教程,重点是根据《狂怒》发行的资产制作新地图。

因此这些笔记不涵盖 这些 教程 所 涉及的主题。

而是这些 笔记 覆盖的 主题 以外的教程,随附 狂怒工具 的 范围装备。

-------------------------------------------------------------------------------

I.1 > > > >  Requirements 配置要求

-------------------------------------------------------------------------------

  To use the Rage Tool Kit, you must own Rage and have it installed. If you do

  not have Rage installed, the toolkit will not work.

要使用Rage工具包,您必须拥有Rage并已安装。

如果你知道没有安装Rage,工具包 将 无法工作。

  Rage Tool Kit Requires a 64 bit OS and a minimum of 2 Gigs of Ram.

It will  bail immediately if a 32 bit Operating System is detected.

Rage工具包需要64位操作系统和至少2g的Ram。

如果检测到32位操作系统,它将立即停止。

  Rage can be purchased through Steam: http://store.steampowered.com/

-------------------------------------------------------------------------------

I.2 > > > >  Recommendations 建议

-------------------------------------------------------------------------------

  I would recommend no less than 16 GB of RAM and 32GB + if you are

  making/modding maps. A solid state Hard drive is also highly recommend,

  but not required.

我建议内存不少于16gb,如果是32GB以上的话制造/改装地图。

也强烈推荐使用固态硬盘。但不是必需的。

-------------------------------------------------------------------------------

I.3  > > > >  Game Architecture游戏体系结构

-------------------------------------------------------------------------------

  1) The game engine:

       You generally don't touch this part. It handles rendering

       the 3D environment, managing input, output and events. Rage

       uses ID Tech 5.

你一般不会碰这部分。它处理渲染3D环境,管理输入、输出和事件。

狂怒使用 id tech5 引擎技术。

  2) Map files:

2)地图文件:

       Map files  serve 2 purposes. They define WHERE stuff goes and they

       also store off HIGH LEVEL INSTANCE DATA about the objects embedded

       within. The instance data can include customized initialization

       and spawn information.

地图文件有 两个用途。

他们定义物品 的 去向 还 存储 关于 嵌入对象的  HIGH LEVEL INSTANCE DATA 内部。

实例数据可以包括自定义的初始化以及衍生信息。

       "Stuff" includes characters, trigger zones, sound emitters,

       invisible cameras and patrol path nodes. If you have experience modding

       other games such as Skyrim or Never Winter Nights, some of these

       concepts should sound familiar.

“Stuff”包括人物,触发区,声音发射器,隐形摄像头和巡逻路径节点。

如果你有改装经验《天际》或《无冬之夜》等其他游戏概念

应该听起来很熟悉。

       For those that are new to this, I will simply say that there are a lot

       of invisible objects hidden in maps that you can't see that help

       make things easier for game play.

对于那些不熟悉的人,

我只想说有很多隐藏在地图上你看不见的无形物体

让游戏玩法更简单。

       

  3) Models: 模型

       Model files provide the look and feel of objects when rendered

       within the Map.

These are read in and injected into the map at runtime.

Maps contain "pointers" to these models, but not the model data itself.

模型文件在渲染时提供对象的外观和感觉在 地图 内。

它们被读入并在运行时注入到地图中 时间 。

地图  包含指向 这些模型的“指针”,但不包含模型数据本身。

       Model files come in 2 flavors. lwo files (Light Wave Objects) and

       MD6 files. The primary difference is that LWO files are simply

       meshes and textures. MD6 files are more complicated.

模型文件有两种类型。

两个文件(LightWave,3d软件 ) 和 MD6文件。

主要区别在于LWO文件非常简单网格和纹理。

MD6文件更复杂。

They are similar to maps in that they mostly contain pointers to lots of

       other information... like what textures to use, what skeleton

       to use, what mesh to use and what animations to use.

它们类似于 地图,因为它们大多包含指向许多对象的指针其他信息…

比如使用什么材质,什么骨骼
使用,使用什么网格,使用什么动画。

       While MD6 files can be used to describe inanimate objects

       like rocks, they are generally used to describe the more complicated

       objects with moving parts... like cars and NPCs.

而MD6文件可以用来描述无生命的物体像岩石一样,

它们通常被用来描述更复杂的东西带有活动部件的物体……

比如汽车和npc。

       MD6 is discussed in more detail below.

 下面将更详细地讨论MD6。

  4) Textures:

       ID Tech 5 uses TGA files for textures. Raw textures often consist

       of many small files. An NPC's hat for example may have its own

       dedicated texture file.

ID Tech 5使用TGA文件处理纹理。

原始纹理通常包括许多小文件。

例如,NPC的帽子可能有自己的帽子专用纹理文件。

  

     But when you build a map, often those small textures will get

       pulled together and merged into a larger "megatexture" that can

       be paged and streamed into memory as needed.

但当你创建地图时,这些小纹理通常会拉在一起,

合并成一个更大的“巨型结构”,

可以根据需要对其进行 分页 并 流式 传输到内存中。

  5) Sounds:

5)声音:

       Ever watch a movie with the sound turned off? Gets real boring real

       fast.  On the other hand, you can take a crappy looking 16 color sprite

       and give it a human voice and it adds a whole new dimension of

       interaction.  Rage supports wav files for background music and ambient

       sounds. There are also rumors that it supports 192 Khz ogg files,

       but this isn't confirmed. However, the engine will convert whatever

       audio you provide to MS-ADPCM format when it builds your mod.

有没有看过关掉声音的电影?变得很无聊,真的快。

另一方面,你也可以选择一个糟糕的 16色精灵 给 它一个人的声音,

它增加了一个全新的维度交互。

Rage 支持 wav文件 作为 背景音乐  和 环境音乐 的 声音。

也有传言说 它 支持 192khz ogg 文件,但 这还没有得到证实。

然而,引擎会转换任何东西音频你提供MS-ADPCM格式时,

它建立 你 的 mod。

  6) Scripts  脚本

       ID Tech 5 comes with its own comprehensive scripting language. Generally

       scripts are used as event handlers, helping to coordinate complex

       scenes and interactions.

ID Tech 5 自带 全面的 脚本语言。

一般脚本 用作 事件 处理程序,有助于复杂的协调 场景 和 互动。

-------------------------------------------------------------------------------

I.4  > > > > Using the Game Console  使用 游戏 控制台

------------------------------------------------------------------------------

  Anytime you run Rage in 64 bit mode (With mod support), console is enabled.

任何时候你运行 Rage 在64位模式 (与mod支持),控制台 是 启用的。 

  The console comes with hundreds of commands to help developers and players

  alike. Type "listCmds" to see a full list (or go to the bottom of these notes).

控制台命令自带数百个命令,以帮助开发人员和玩家一样的。

输入“listcmd”以查看完整的列表(或转到这些注释的 底部 )。

  My Favorite: 我的最爱

      find <string>

          very useful command. Searches animations, models, commands,

          cvars and images for anything containing the string. So if

          you want to know what map commands are available for example,

          you might try:

非常 有用 的 命令。 搜索动画、模型、命令、任何包含字符串的变量和图像。

因此,如果 您想知道哪些地图命令可用,例如, 你可以试试:

          i.e.: find map  例如:查找地图

  Other Example commands:  其他 示例 命令

      Notarget  隐形 /隐形模式 /敌人不攻击 /对大多数敌人隐身

          Enemies do not see you (invisibility)   敌人看不到你(隐身)

      Noclip  穿墙 /穿墙模式 /模式 /可穿过任何固体

          Walk through walls. More importantly, disables the activation of

          triggers.

   穿墙行走。更重要的是,禁用的 激活 触发器。

      map <map name>     

          Teleport to a map. Be warned that scripts often assume a certain game

          state, so if you teleport somewhere before you would normally have

          access to it, things may break. Even starting a conversation may

          cause the game to crash.

传送到地图上。(应该是加载一个地图)需要注意的是,脚本通常会假设一个特定的游戏状态,

所以如果你传送到某个地方,你通常会接触到它,东西可能会坏掉。

甚至开始一段对话也可能 导致 游戏崩溃

      selectDebugEntity

          Selects whatever entity is below the crosshair as the debug

          entity (for other commands that affect the selected entity)

选择 十字准星 下方 的 任何实体 作为 调试对象实体

(用于影响所选实体的其他命令)

      list items 物品列表

          list is a command, but "items" is actually an incorrect

          parameter. However, this will cause the console to list

          valid entity types, which is far more useful feedback

          than the default feedback.

List是命令,但“items”实际上是错误的参数。

但是,这将导致控制台列出有效的实体类型,这是 远为 有用的反馈  比 默认反馈值 高。

          ie: list inventoryItem    例如:list inventoryItem

      give (item) #

          give the player an item # times      给 玩家 一个道具#次

          ie : give inventory/currency/currency_unit 999

例如:给予库存/货币/currency_unit 999

-------------------------------------------------------------------------------

I.5  > > > > Console Variables  控制台变量

------------------------------------------------------------------------------

  Console variables are very similar to console commands. Console variable

  control parameters about how the current game engine is running. Type

  "listCvars" to see a full list (or see Appendix)

控制台变量 与 控制台命令 非常相似。

控制台变量 控制 当前游戏引擎 如何运行的参数。

类型"listCvars" 查看完整列表 (或参见附录)

  My Favorite Cvar:我 喜欢 的  Cvar:

      g_showEntityInfo      应该是显示 实体信息

          When set to 1, you will see a blue box around game entities

          within the game telling you what their instance ID is. This

          can come in handy for other commands that allow you to

          target entities. Especially when designing scripts for

          maps that we never received the source code for.

当设置为1时,你将在 游戏实体 周围 看到一个 蓝色框 告诉 你 它们的 实例ID 是什么。

这可以派上用场的其他命令,允许您目标的实体。

尤其是在 设计 脚本 的时候 我们 从未 收到 源代码 的地图。

          Very useful, even during normal game play and it brings

          attention to hidden items and doors.

非常有用,即使在正常的游戏过程中,它也会带来 注意 隐藏 的 物品 和 门。

  Other Example Cvars:  其他示例:

      ai_enable     ai 启用

          Similar to the Notarget command. However,

this disables NPC'sbrains all together.

So they don't move, they don't take damage,

          etc...

类似于Notarget命令。但是,这会使NPC的大脑 全部 失效。

所以它们不会移动,不会受到伤害,

等等……

      g_showHud 0      

          Turn off the game hud. Can be handy if you are recording a

          video.

关闭游戏界面。可以方便,如果你正在录制一个 视频。

      g_stopTime 1

          Freeze time (except for you). 冻结时间(除了你)。

-------------------------------------------------------------------------------

I.6  > > > > Standard Tools   标准工具  / 标准工具栏

-------------------------------------------------------------------------------

  If you want to actually deform Rage NPCs , you will need additional software.

  Gimp is the best free image editing program that I know of for updating

  textures. As for model deformation, Blender3D is probably the best free

  option. As working with rage involves dealing with a lot of metadata

  files, I also recommend a good text editing program like Notepad++

      如果你真的想要 改变 Rage 的npc,你将需要额外的软件。


Gimp 是我所知道的最好的免费图像编辑程序纹理。

至于模型变形,Blender3D可能是最好的免费工具选择。

因为处理 狂怒 涉及到处理大量元数据

我还推荐一个不错的文本编辑程序,比如notepad++

      GIMP:  (GNU图像处理程序(Gnu Image Manipulation Program) /)

      

          http://www.gimp.org/

      Blender:

(3D建模软件(Blender)是一款方便使用的3D建模的软件, 写的很精炼。

且使用方便,效果惊人,某些方面比3DS更好。)

      

          http://www.blender.org/

      NotePad++: (一个记事本程序)

      

          http://notepad-plus-plus.org/

-------------------------------------------------------------------------------

I.7  > > > > Best Practices   最佳实践 /最佳实务 /最佳范例

-------------------------------------------------------------------------------

  A general best practice that is universal when it comes to modding games is

  to avoid changing original game resources when possible. Break your changes

  out into new directories and files names and raw resources.

当涉及到 游戏建模 时,一个普遍的 最佳实践 是 尽可能 避免 改变 原始 游戏 资源。

中断 更改 输出 到 新的目录、文件名 和 原始资源 中。

  Most games that support modding provide hooking mechanisms so that you don't

  have to edit the original game resources to make things happen. This is

  true for most of Rage modding (but not all).

大多数支持mod的游戏都提供了吸引机制,

所以你就不会 这么做  必须 编辑 原始 的 游戏资源 才能 让 事情 发生。

这是适用于《狂怒》的大部分 mod  (但不是全部)。

  As you mod rage, you will discover most raw resources have an associated

  metadata file that "points" to the raw resource.

当你 mod rage 时,你会发现 大多数 原始 资源 都有 关联 的 “指向”原始资源 的 元数据 文件。

    .m2      : Textures    材质 /纹理 /贴图 /纹理贴图

    .md6mesh : Model Mesh  网格模型

    .md6anim : Model Animations  模型的动画

    .md6def  : Binds Meshes to Animations  将网格绑定到动画

    .def     : Entity Definitions   实体 定义

    .shdsnd  : Sound (wav)      声音 (wav)

    .vtr     : Vocal Track (lip synched)   声道( 唇同步)

    .tdef    : Type definitions (Jobs, behaviors, etc...)  类型定义(作业、行为等)

     etc....  等等,及其他(et cetera)

  You can create your own metadata files and Rage will simply import them when

  it starts up. In some cases, Rage will reload/refresh directories without

  having to restart the toolkit.

你可以创建你自己的元数据文件,Rage会在你需要的时候导入它们


它启动了。

在某些情况下,Rage会 重载/刷新 目录 必须 重新 启动 工具包。

  Part of the reason I install version control software is so that I can see

  what files are edited by my actions and even what lines are created in those

  files. Then I can create my own files named after my mod and move those

  changes out of the original games files.

我 安装 版本控制软件 的部分 原因是  我可以看到 我的 动作 编辑 了 哪些 文件,

甚至 在 这些 文件中 创建了 哪些 行文件。

然后我可以创建我自己的文件,以我的mod命名,并移动那些 更改了 原始游戏文件。

  This helps in several ways. It makes it easier to identify where my changes

  are. It minimizes the chance of conflicts with other mods and it eases the

  burden of merging two mods if a decision is ever made to go that route.

这在几个方面都有帮助。

这样可以更容易地识别 我的更改 是这样的。

它最大限度地减少了与其他mod冲突的机会,并缓解了 合并两个mod的负担,

如果决定走这条路。

-------------------------------------------------------------------------------

I.8  > > > > Hard versus easy Changes  难易对比

-------------------------------------------------------------------------------

  When you are making your own map, you can do just about anything you

  want. However, changing an original game map is much more difficult,

  especially if your goal is to introduce a change that affect multiple

  maps.

当你在制作自己的地图时,你可以做任何你想做的事情 想要 的 东西。

然而,更改原始游戏地图要困难得多,

特别是如果您的 目标 是 引入 一个影响 多人 的 更改 地图。

  When ID studio compiles a map, it includes pointers to entities such

  as NPCs. However the map also includes high level entity information

  embedded within the map itself. Basically "instance" data.

当ID studio编译地图 时,它包含指向实体的指针,例如npc。

然而,该地图还包括高级实体信息嵌入在地图本身中。

基本上是“实例”数据。

  For example, the type of information defined within :

例如,其中定义的信息类型:

    decls -> entityDefs  ...

  So take this scenario:     以这个场景为例:

  - You make a mod with a custom map 你做一个mod与自定义地图,

where you embed Ghost Bandits that are smart and tough.

你嵌入Ghost Bandits 是聪明 又强硬。

  - Someone else makes a mod with a custom map where they embed Ghost

    Bandits that are dumb and weak.

  其他人制作了一个带有自定义地图的mod,其中嵌入了Ghost又笨又弱的强盗。

  If a user installs both mods, both mods will work fine because the

  ai and damage susceptibility are defined at a high level and included

  with the instance data embedded in the map.

如果用户安装了两个mod,两个mod都可以正常工作,

因为Ai和损伤敏感性在高水平上定义并包括在内 实例数据嵌入到地图中

  That may sound great... until you realize this same protection prevents

  you from (easily) changing the ai or damage susceptibility of any of the

  monsters in the original game maps because you don't have the original maps

  to recompile them with your changes.

听起来不错……直到你意识到同样的保护可以防止你从(容易地) 改变ai

或伤害敏感性的任何原始游戏地图中的怪物,

因为你没有原始地图用您的更改重新编译它们。

  When editing the original game, you are more or less limited to

  global scripting changes which are applied at runtime. For example,

  you could update script_main.script to call a custom method that

  you write (it is called every time a user enters a new map). Your

  method could examine the map name and the active layers and take actions

  based on the two.

  Most rage maps have enemy instances embedded into them and each instance

  has a unique ID. So if you had a list of maps and instances, you could

  use script commands to alter the enemies on a map (or add new enemies

  or simulate nightmare "dynamic spawning" enemies when current enemies

  die, etc....)

  However there is a major drawback to this as well:

  Only 1 mod can edit the script_main.script, which is where global

  changes are defined. So if a user wishes to install 2 mods that edit

  the original game with scripts, one of those mods will break.

  The good news is, that only high level information is embedded. The

  EntityDef points to many lower level support resources and those resources

  are NOT embedded into the maps.  For example, MD6 resources define the

  mesh and animations of the NPC. So you can change the look of all Ghost

  Bandits in the original game,  but you couldn't add additional Ghost

  bandits to a map without scripts.

  Other low level (global) entities that are safe for editing if

  you are targeting the original game:

  - inventory

  - weapons

  - ammo

  - engineering schematics

  - md6 (models)

  - m2  (materials/textures)

  - ** Jobs

  - sounds/voicetracks

  ** Jobs are global, but they are generally started by map scripts/objects

     or other (already existing) jobs. You can add new jobs to the game

     with minimal edits, but you will have to edit an existing job to

     do so, which means the possibility of mod conflicts with other mods.  

  As stated, if you are making your own maps, then these concerns don't really

  apply to you.

===============================================================================

II. > > > > Getting Started

===============================================================================

-------------------------------------------------------------------------------

II.1  > > > >  Installation

-------------------------------------------------------------------------------

  Ensure Rage is installed and then open up Steam.

  Go to the "Library" tab.

  Notice at the top of the page next to the Search box, there is a combo box

  which normally reads "All Games". Click on "All Games" and change it to

  "Tools"

  Scroll down and right click on the Rage Tool Kit and select "Install Game..."

  DO NOT run the Toolkit after install is done if you want an early version

  controlled snapshot.

-------------------------------------------------------------------------------

II.2  > > > >  Setting up Software Change Management

-------------------------------------------------------------------------------

   1) Install a FRESH COPY of The Rage Toolkit (See Part I. above)

   2) Install tortoiseSVN

      - Go to http://tortoisesvn.tigris.org/

      - Download correct version

      - Install, use defaults

      - Restart Computer

   3) Create Repository

      - Open Windows Explorer

      - Create a new folder and name it. For example: C:\svnrepo (Drive should

        have at least 100 Gigs of free space)

      - Right-click on the newly created folder and select:

        TortoiseSVN -> Create repository here...

      - Select "Create folder Structure"

      - [OK] -> [OK]

   

      A repository is then created inside the new folder. DO NOT EDIT THOSE

      FILES YOUSELF!

   4) Import the Rage Toolkit directory into the Repository:

      - Using Explorer, browser to:

         C:\Program Files (x86)\Steam\steamapps\common

      - Right Click "rage tool kit" and select: TortoiseSVN -> Import

      - Use the browse button [...] to select the REPO : (file:///C:/svnrepo)         

      - Take a nap or something. Import takes about 1.5 hours.

   5) Check Out the Code Base:

      - Using Explorer, browser to:

         C:\Program Files (x86)\Steam\steamapps\common

      - Right Click "rage tool kit" and DELETE it.

      - Using Explorer, browser to:

         C:\Program Files (x86)\Steam\steamapps

      - Right Click "common"

      - Select "SVN checkout..."  

      - Update "Checkout Directory" :

          C:\Program Files (x86)\Steam\steamapps\common\rage tool kit

      - It will begin the checkout process. Find something else to do for 1.5

   6) Set up Virtual Mount:

      Many rage resources have the path "W:\Rage" hard coded into them as the

      location of the rage files. It is unclear if this may cause problems,

      however it is trivial to set up a virtual mount and makes accessing

      the tool kit much easier.

      Start -> [Search Programs and Files] <- Enter "cmd"

      cd c:\

      mkdir RageFix

      subst W: C:\RageFix

      cd W:

      mklink /D Rage "C:\Program Files (x86)\Steam\steamapps\common\rage tool kit"

      If you close the window, when you open explorer, you should now see a

      W: drive in your listing.

   7) Finally, it is time to start up rage tool kit and extract all the resources:

      - Steam -> Library -> Change "All Games" to "Tools"

      - Right click Rage ToolKit -> Play Game

      - When the startup window appears hit Enter

      - When you see the ID Studio menu appear, select "ID Studio"

      - If it is your first time, you will get a message about your default

        layout being changed.

      - Exit the game and restart

      - When the startup window appears hit tilde (`\~) and enter the command:

        exec buildAssets.cfg

      - Wait 20 to 60 minutes while it uncompressed resources

   8) Rage will likely close. I believe it is suppose to restart itself, but it

      tends to fail. So... As painful as it is, you need ot start it up and

      type buildAssets.cfg yet again.

      - Steam -> Library -> Change "All Games" to "Tools"

      - Right click Rage ToolKit -> Play Game

      - When the startup window appears hit (`) and enter the command:

        exec buildAssets.cfg

      - When you find that running the script creates a progress bar the

        finishes rather quickly and the toolkit auto closes within 2 or 3

        minutes... it is time to start it up without using the buildAsset.cfg

        command:

      - Steam -> Library -> Change "All Games" to "Tools"

      - Right click Rage ToolKit -> Play Game

      - When the startup window appears hit Enter

      - When you see the ID Studio menu appear, select "ID Studio"

        You should see the splash say something about "finishing up".

   9) Add Dynamic Resources to SVN Ignore:

      - Using Explorer, browse to:

         C:\Program Files (x86)\Steam\steamapps\common\rage tool kit

      - Right Click "virtualtextures" and select:

        TortoiseSVN -> Unversion and Add to Ignore List -> "virtualtextures"

9)添加动态资源到SVN中,请忽略:

-使用资源管理器,浏览到:

C:\程序文件(x86)蒸汽通用工具包

-右键单击“虚拟纹理”,并选择:

乌龟SVN->反转和添加到忽略列表->“虚拟纹理”

     

 - Right Click "mods" and select:

        TortoiseSVN -> Unversion and Add to Ignore List -> "generated"

      - Using Explorer, browse to:

         C:\Program Files (x86)\Steam\steamapps\common\rage tool kit\base

      -右键单击“mods”并选择:

乌龟SVN->反转和添加到忽略列表->“生成”

-使用资源管理器,浏览到:

C:\程序文件(x86)蒸汽蒸汽程序通用工具包

- Right Click "generated" and select:

        TortoiseSVN -> Unversion and Add to Ignore List -> "generated"

    

  -右键单击“已生成”,并选择:

TortoiseSVN->反转和添加到忽略列表->“生成”

- Right Click "SAVES" and select:

        TortoiseSVN -> Unversion and Add to Ignore List -> "SAVES"

      - Right Click "cache" and select:

        TortoiseSVN -> Unversion and Add to Ignore List -> "cache"

-右键单击“保存”,并选择:

乌龟->反转和添加到忽略列表->“保存”

-右键单击“高速缓存”,然后选择:

乌龟SVN->反转和添加到忽略列表->“缓存”

  10) Take a snapshot of the rage tool kit Before you start making changes:

      - IMPORTANT: Shut the toolkit down before proceeding

      - Using Explorer, browse to:

         C:\Program Files (x86)\Steam\steamapps\common

  1. 采取一个狂怒的工具包的快照,在你开始进行更改之前:

-重要提示:在继续操作之前,先关闭工具包

-使用资源管理器,浏览到:

C:\程序文件(x86)Steam\steamapps程序

      - Right Click "rage tool kit" and select:

           SVN Commit ...

        You will see a giant list of changed files (mostly new files).

        Check all by clicking on the bold "All"

        In the message, put "After buildAssets"

        Hit [OK]

      - Now wait another 10 mins...

-右键点击“rage工具包”,并选择:

SVN提交..。

您将看到一个巨大的更改文件列表(大部分是新文件)。

通过点击粗体的“所有”来检查全部

在消息中,放置“建成后的资产”

点击“确定”

-现在再等10分钟。

      

  11) [Option] Copy your backed-up Rage folder contents into the rage tool kit

      directory.

-------------------------------------------------------------------------------

II.3  > > > >  Fix Bugs

-------------------------------------------------------------------------------

  There are several bugs that come for free with the Rage Toolkit.

  1) When ID Studio compiles your mod, it will write the scorcher dlc

     weapon textures to the wrong offset, causing the nail gun that

     comes with the scorcher DLC to look odd when your mod is enabled.

     Fix: (This should be done now...)

     open up :

       W:\Rage\base\decls\skins\vehicle_buggy.skin

       Search the file for: "#ifdef DVD3"   // 在文件中搜索:"#ifdef DVD3"

       You will see 10 segments throughout the file that look like:

         // 你将在整个文件中看到10个片段,如下所示:

         #ifdef DVD3

            robocola

            {

               "models/vehicles/class2/buggy01bodypanels"

               "models/vehicles/class2/buggy01bodypanels4"

            }

         #endif

       You need to comment these sections out by placing "//"

       in at the front of each line within the ifdef. IE:

您需要通过添加"//" 来 注释 这些 部分。 在ifdef内每行的前面。即:

         // #ifdef DVD3

         //    robocola

         //    {

         //       "models/vehicles/class2/buggy01bodypanels"

         //       "models/vehicles/class2/buggy01bodypanels4"

         //    }

         // #endif

  2) When you create textures, those textures will be written to

 //当你创建纹理时,这些纹理将被写入

 either 


要么

         game.resources       <- non-animated textures

         or 或

         _vmtr_dlc.pages      <- animated textures

     Depending mostly on if the texture is mapped to an animated

entity such as an NPC or a buggy.

主要取决于 纹理 是否 映射 到 动画 实体,如 NPC 或 bug。

     As of this writing (Rage.1700.354669), rage does not load

     the animated textures that ship with mods.

在撰写本文时(rage .1700.354669), rage无法加载 带有 mods的 动画纹理。

     Fix/Hack: (To be done later when you build/deploy your mod)

 修复/Hack:(当您构建/部署您的mod 时 稍后完成)

     After you build your mod, you must make a zip/7-zip installer

     that places your _vmtr_dlc.pages file in a non standard location

在你构建你的mod之后,你必须制作一个zip/7-zip的安装程序放置_vmtr_dlc。

Pages 文件 位于 非 标准 位置

     This is discussed in more detail below in the Textures

     section. Hopefully the need for this hack will not be needed

     in the future.

这在下面的纹理中有 更详细 的 讨论 部分。 希望不需要这个hack 在未来。

===============================================================================

III. > > > > Hello World Popup Message 

Hello World 弹出消息

===============================================================================

  For our fist mod, we will simply make a message pop up that says hello

  world when you get out of the buggy at the beginning of the game. This

  will introduce you to a couple of simple concepts:

对于我们的第一个mod, 我们将简单 地使一个消息弹出,说你好世界,

当你在游戏开始的时候从bug中出来。这 将向你介绍几个简单的概念:

  1) Adding Strings        添加字符串

  2) Tutorial Messages  读出指导信息

  3) Job Creation        Job 创建

-------------------------------------------------------------------------------

III.1  > > > >  Adding Strings  添加 字符串

-------------------------------------------------------------------------------

  Adding new strings to the game for use in message boxes and other gui

  components is pretty simple, however the button to add strings is not

  obvious.

添加新的字符串到游戏中 使用的 消息框  和  其他gui  组件非常简单,

但是用于添加 字符串 的 按钮 却不是 显而易见的。

      Start up rage tool kit      启动 《狂怒》 工具包

      World Edit -> Tools -> String Browser

世界编辑->工具->字符串浏览器

  Next to the Find box, there is a little [abc] button. Click it to add

  new text:

在查找框的旁边,有一个小的[abc]按钮。点击 它 来添加 新 文本:

      "#str_mod1_popup_title" "Hello"

      "#str_mod1_popup_body" "World!"

  After you finish editing a field, make sure to hit [ENTER] for the change to take effect.

编辑 完一个字段后,请确保按 [ENTER] 使 更改 生效

  If you have version control installed, you will notice that your edit

  just caused a file to get updated:

如果您安装了版本控制,您会注意到您的编辑 刚刚 导致 一个文件 被 更新:

      <Rage Tool Kit>/base/strings/english.lang

  If you right click the file and do a diff, you will notice that it added

  the new lines to the bottom of the file.

如果右键单击该文件并执行diff操作,您将注意到它已添加将 新行 移到 文件 的 底部。

  IMPORTANT: You can edit the english.lang file directly to save time.

  However, you must add all new strings to the END of the file.

  Do not insert your new strings into the middle or the head of the

  file.

      重要提示:您可以编辑英文。 直接使用Lang文件来节省时间。


但是,您必须将所有新字符串添加到文件的END。


不要将新字符串插入到字符串的中间或头部文件。

-------------------------------------------------------------------------------

III.2  > > > >  Tutorial Messages  读出指导信息

-------------------------------------------------------------------------------

  One of the easiest ways to pop up a message is to create a job that quickly

  starts and stops which has an associated tutorial message. The tutorial

  message will pop up and freeze the game until the user hits the Accept

  button.

 弹出消息 最简单的方法之一 就是快速创建一个job具有相关 教程消息 的 开始 和 停止。

本教程消息 将 弹出 并 冻结游戏,直到 用户 点击“接受” 按钮。

  TutorialEvents are defined in the Media Browser. The easiest way to create

  one is to copy an existing one:

TutorialEvents在媒体浏览器中定义。最简单的创建方法  一种是复制一个已有的文件:

      Start up rage tool kit  启动《狂怒》工具包

      In the bottom left corner, you will find the "Media Browser" tab

      decls -> tutorialEvent -> new -> dlc1 -> intro

/******************************************************************

在左下角,你会发现“Media Browser (媒体浏览器)”选项卡

dlc -> tutorialEvent -> new -> dlc -> intro

***************************************************************/

      Right click "intro" and select "duplicate"

      place it under a folder that represents your mod name. ie:

      "awesomemod/intro"

右键点击"intro",选择"duplicate" , 把 它 放在一个代表你的mod名的文件夹下。

即:“awesomemod /intro ”

      Now double click the new "intro" tutorial Event you created

      and change the headingText and bodyText to point at your

      new Strings. Also change the type to: "TUTORIAL_TEXT"

现在双击新创建的“intro”教程事件  并 更改 headingText和bodyText以 指向 您的 新字符串。

同时 将 类型 更改为:"TUTORIAL_TEXT"

  And there you have it. You have made a tutorial message.

结果出来了。您已经 制作 了 教程 信息。

  NOTES: 备注 /注释 /注意事项 /说明

  if you go to the file system and you have version control software

  installed, you will notice that your change updated the file:

如果你去文件系统,你有版本控制软件 ,安装后,你会注意到你的修改更新了文件:

      <Rage Tool Kit>/base/decls/typeinfo/dlc_1_tutorialEvents.tdef  

  If you right click and do a diff, you will see your change at

  the bottom of the file:

如果您右键单击并执行更改,您将看到您的更改 文件的底部:

      tutorialEvent awesomemod/intro {

          edit = {

              headingText = "#str_mod1_popup_title";

              bodyText = "#str_mod1_popup_body";

              retryInMS = 1000;

          }

      }

  In section I.6 above, I mentioned that a best practice is to

  break out changes into our own files. So at this time, I open

  up explorer and go to:

在上面的第1 .6节中,我提到了最佳实践是  将更改拆分到我们自己的文件中。

于是在这个时候,我打开了 打开资源管理器,转到:

      <Rage Tool Kit>/base/decls/typeinfo/

  I create the file "awesomemod.tdef" and then I copy the contents

  from the bottom of dlc_1_tutorialEvents.tdef to my new file.

  Then I save my new file and finally I right click:

我创建了文件“awesomemod”。tdef”,然后  复制 内容 从 dlc_1_tutorialEvents底部。

转到我的新文件。


然后保存我的新文件,最后右键点击:

  dlc_1_tutorialEvents.tdef and select TortoiseSvn -> Revert

  This restores the file to its unedited version. If you shut

  down ID Studio and restart it, you will find your new tutorial

  event is still there. Furthermore, if you make any further

  changes to it, ID Studio will update your new file.

这将文件恢复到 未编辑 的 版本。

如果你闭嘴关闭ID Studio并重新启动它,你会发现你的新教程 事件仍然在那里。

此外,如果你再往前走更改它,id Studio将更新您的新文件。

-------------------------------------------------------------------------------

III.3  > > > >  Firing a Job event  启动 job事件

-------------------------------------------------------------------------------

  Jobs and scripts are the glue that holds the game together. There are a

  couple of different types of jobs. As far as I can tell, the type controls

  things like:

jobs和脚本本是维系游戏联系的粘合剂。有一个

两种不同类型的工作。据我所知,类型控制

比如:

  - Can the job repeat

  - Does the job show up in the players list of jobs when in progress

or completed.

-该作业是否可以重复执行

-工作是否出现在玩家列表中

或完成。

  I am not going to claim that I possess a comprehensive knowledge of

  all the types. What I can tell you is that after several days of

  experimenting, I was unable to get a job to start without some

  "help" from either a script or an existing job.

我不会说我拥有一个全面的知识所有类型。

我能告诉你的是,在这几天之后经过实验,我无法找到一个 job,

没有一些 从脚本或现有job 中获得的“帮助”。

  Luckily, he game does offer the ability for an existing job to for multiple additional jobs. This is typically done as a "reward".  

幸运的是,这款游戏确实提供了一份现有 job 到 多个 额外 job 的 能力。

这通常是作为一种“奖励”。

  So to add a job to the (original) game, we will update an existing job

  definition so that it starts our new job when the existing job  completes.

因此,要向(原始)游戏添加 job,我们将更新现有的 job

定义,以便现有 job在完成时启动 新 job

      Start up rage tool kit  启动《狂怒》的工具包

      In the bottom left corner, you will find the "Media Browser" tab

      decls -> job -> jobs -> dlc1

在左下角,你会找到“媒体浏览器”标签

decls ->作业->作业-> dlc1

      Right click "rumbles_in_the_dark" and select "duplicate"

      place it under a folder that represents your mod name. ie:

      "jobs/awesomemod/intro"

右键点击“rumbles_in_the_dark(隆隆黑暗)”,选择“重复”

将它放在一个表示mod名称的文件夹下。

即: "jobs/awesomemod/intro"

      Now double click the new "intro" job you created

      and change the jobNameId to point to "#str_mod1_popup_title"

      and the jobSummaryId to point to "#str_mod1_popup_body"

现在双击您创建的新“介绍”job 并改变 jobNameId,

以指向“#str_mod1_popup_title”

和    jobSummaryId  指向“#str_mod1_popup_body”

      Finally, change: 最后 ,改变 

        jobType -> Optional

        requiredDLC -> "GAME_DLC_STATE_DEFAULT"

        acceptTutorial -> "awesomemod/intro"

        saveAsJob      <- clear value so that it has nothing.

        msDelayForTutorial -> 3000

最后,更改:

jobType ->可选

要求DLC->“GAME_DLC_STATE_DEFAULT”

acceptTutorial -> "awesomemod/intro"

saveAsJob <-明确的值,所以它什么都没有。

msDelayForTutorial -> 3000

  Now... we want the job to stop itself as soon as it begins. So

  we expand "acceptRewards". Right click "acceptRewards" and

  select "appendItem". This will incease the num count to 1.

现在……我们希望工作一开始就停止 job。如此 我们扩大了“可接受的奖励”。

右键点击“接受奖励”和 选择“appendItem (附件项)”。这将使数数为1。

  Expand the new item and declare the reward type as:

展开新项目,并将奖励类型声明为:

     reward  "JOBREWARD_JOBCOMPLETION"

     jobDecl "jobs/awesomemod/intro"

奖励“JOBREWARD_JOBCOMPLETION”

jobDecl "jobs/awesomemod/intro"

  Make sure to hit the save icon at the top. 确保点击顶部的保存图标。

  So our job immediately completes itself, but triggers our tutorial message

  during its brief existence. Perfect.

因此,我们的 Job 立即完成,但 触发 了我们的教程消息

在它 短暂 存在的时候。完美。

  All that is left is hooking the job up to an existing job. Before we

  do that, this would be the best time to use SVN to see what changed

  and extract out the changes into a new file.

 I am not going to walkyou through it. I am just telling you now would be the time to do it

  if you want to keep your changes externalized.

所剩下的就是将job 与 现有的job 连接起来。

在我们之前这样做,  这将是使用SVN查看有什么变化的最佳时间

并将这些更改提取到一个新文件中。

我不打算给你讲解。 我只是告诉你,现在是时候这么做了

如果您想保持您的更改外部化。

  Finally, 最终

      Start up rage tool kit

      In the bottom left corner, you will find the "Media Browser" tab

      decls -> job -> jobs -> support

启动《狂怒》的工具包

在左下角,你会找到“媒体浏览器”标签

decls -> job ->工作->支持

      Double click the support_game_start

      Right click "rewards" and select "Add Item".

      Change the reward to:

双击支持游戏并启动

右键点击“奖励”,然后选择“添加项目”。

将奖励更改为:

        reward "JOBREWARD_JOBACCEPT"

        jobDecl "jobs/awesomemod/intro"

奖励“JOBREWARD_JOBACCEPT”

jobDecl "jobs/awesomemod/intro"

  Make sure to hit the save icon at the top. 确保点击顶部的保存图标。

  At this point you can build your mod and test it out.

(See the deployment section below for help).

在这一点上,你可以构建你的mod并测试它。

(请参见:下面的部署部分以寻求帮助)。

===============================================================================

IV. > > > > Scripting  脚本 / 脚本撰写  / 脚本处理 / 脚本设计

===============================================================================

  Where are scripts used?

脚本在哪里使用?

  1) Maps  1)地图

     Every map can have a script associated with it that is loaded when the

     player enters the map. By default, these scripts have a "main" function

     which receives a thread of execution when the map loads.

每个地图 都可以有一个 与之关联 的 脚本,当加载时玩家进入地图。

默认情况下,这些 脚本 有一个“主”函数   当 地图 加载时,它接收一个 执行线程。

     The most common use of map scripts is:  地图脚本最常见的用法是:

     - Dynamic handlers for things that are not embedded in the map

动态处理程序的东西,没有嵌入在地图中

       (ie: respawning enemies).  (例如:重生敌人)。

     - The development of global scripts 全局 脚本的开发

  2) Spawn Settings           2)生成设置

     AI based entities can call a sequence of script commands when the spawn.

基于AI的实体 可以在 生成 时 调用 一系列脚本命令

For example, to have an old man begin walking across town or have an enemy jump on a nearby zip line.

例如,让一个老人开始穿过城镇或 让敌人跳到附近的 滑索 上。

  1. Animations
  2. 动画

     If you click on an MD6 file and then click on an animation alias, you

     will see a little timeline graph appear under the model. If you right

     click in the timeline, you can add an event.

如果 单击 MD6文件,然后 单击 动画别名,则可以 将看到一个小的时间轴图出现在模型下。

如果你是对的单击时间轴中,您可以添加一个事件。

     These events can do lots of things from having the NPC drop their

     attached weapon to restoring health. One of the options is:

这些事件可以做很多事情,从让全国人大放弃他们的

附加武器,以恢复健康。其中一个选项是:

     ae_ScriptFunction

     Which allows you to call a global function or a function attached to

     the entities assigned Script Object handler. So for example, you

     could setup a custom animweb for an NPC and have the various

     animations alert your script as to what is happening with

     callbacks.

它允许您调用一个全局函数或一个附加到的函数 分配的脚本 对象处理程序的实体。

例如,

你是否可以为一个NPC设置一个自定义的动画网络,

并有各种动画提醒你的脚本关于发生了什么回调。

  1. Global Event Handlers 全局事件处理程序

     Global scripts are tricky to write because

全局脚本很难编写,因为

     - you can't compile them  while ID Studio is running

     - you can crash the game if you attempt to access or spawn something

       that is not in memory (typically defined/enforced by the map).

     -在ID Studio运行时无法编译它们

-  如果你试图访问或衍生一些东西,你可以破坏游戏

它不在内存中 

(通常由地图定义 /强制执行)。

     However, let there be no mistake... You CAN edit and create global

     scripts. It is discussed below.

但是,不要弄错。。您可以 编辑 和 创建全局剧本 下面将讨论。

-------------------------------------------------------------------------------

IV.1 > > > > Basics:  基础;基本要素

-------------------------------------------------------------------------------

  A) Environment VariablesA)环境变量

  

    When a map is loaded within ID Tech 5, several globals are setup and made

available:

当在ID Tech 5中加载一个地图时,将设置并制作几个 全局元素 可用的

      sys <- The main thread of the game.

           ie:  sys.print( "^2" + sys.getTime());

      $<entity_name>  <- You can reference any embedded map entities using

                       $<entity_name> (no less then/greater than signs). Use of

                       references means that your script is obviously tightly

                       bound to the map.

$<实体_name><-您可以引用任何嵌入式映射实体使用

$<实体_name>(不小于/大于符号)。的使用:

引用意味着您的脚本明显很紧密

绑定到地图。

      $player1        <- While Rage does not expose the functionality, ID Tech

      $player2           supports up to 4 co-op players. However you should

      $player3           use $player1 when playing single player.

     

$播放器1<-虽然Rage没有暴露的功能,ID技术

$播放器2最多支持4个合作对战。但是你应该

$播放器3在玩单人播放器时使用单人战役。

 $player4

            

      $null           <- place holder for unassigned/initialized objects.

      $self           <- entity that the script is attached to. You can also use

                         the object "self" without the $.

$player4

$空-未分配/初始化对象的<留位符。

该脚本附加到的$自<-实体。你也可以使用

没有$的对象“self”。

    $self_target0   <- Not sure. The assumption is that these refer to  

$self_target1      combat targets. I've never used them

$self_target0 <-不确定。假设这些指的是

$self_target1战斗目标。我从来没有用过

    $self_target2

    $self_target3

    $self_target4

    $self_target5

    $self_target6

    $self_target7

    $self_target8

    $self_target9

    $executor       <- No idea... Could be the object running the code or

                       it could be the dude that just killed the NPC.

    $activator      <- If you activate an NPC by talking to them, this would

                       be you...

$执行人<-不知道。可以是运行该代码的对象或

可能是那个家伙刚停掉了NPC

$激活器<-如果你通过与他们交谈来激活一个NPC,这将会

做你..。

 B) Vectors:

    vector v        <- A vector is basically an array of 3 floats. In

    v_x                ID tech 5, vectors use the property accessors

    v_y                "_x", "_y" and "_z" to access the various

    v_z                float values.

 C) Type Casting:

    ID Tech 5 supports type casting, but only through variable assignment:

    MyCustomClass mcc = $someCompatibleEntity;

mcc.MyCustomClassMethod...

ID Tech 5支持类型转换,但只能通过变量分配:

MyCustomClass mcc = $someCompatibleEntity;

mcc.MyCustomClassMethod ...

    If you are calling a method that takes no parameters and doesn't

    return a value, you can also use the callFunction method:

$someEntity.callFunction("NoParamNoReturnMethod")

如果你调用的方法不需要参数

返回一个值,您也可以使用调用函数方法:

$someEntity.callFunction("NoParamNoReturnMethod")

  1. Decls Loading:
  2. D)判定加载:

    Some methods require a decl parameter. They seem to be initialized

like so:

有些方法需要一个decl参数。它们似乎已经被初始化了

像这样

    @sound(<file path>)  <- instantiate a decl and cast to sound.

    @job(<file path>)    <- instantiate a decl and cast to sound.

ie: @sound( "music/maps/well/level_three" )

 E) Includes:

    The line below is how you would include code from one file in

    another file:

#include "filename.script"   

  1. 包括:

下面这一行是如何从一个文件中包含代码

另一个文件:

#包括“文件名。脚本”

-------------------------------------------------------------------------------

IV.2 > > > > Common Commands常用命令

-------------------------------------------------------------------------------

  This is by no means a comprehensive listing. It is simply an overview of

  the most common commands and objects. For a full listing of commands,

  parameters, return types, constants and the Object Inheritance heiarchy,

  

这绝不是一个全面的清单。它只是一个概述

最常见的命令和对象。对于完整的命令列表,

参数、返回类型、常量和对象继承属性,

  see

  

  <Rage Tool Kit>/base/script/script_events.script

    

  A) idEntity :

     Pretty much everything in the game is an Entity. (Entity is the base

     object), however there are lots of children of entity that add additional

     methods. For a full hierarchy and all methods, return values, parameters

     and descriptions,  see the Appendix below.   

游戏中几乎所有的东西都是一个实体。(实体为基础

对象),但是有许多实体的子元素添加了额外的

方法对于一个完整的层次结构和所有方法,请返回值、参数

和描述,见下面的附录。

     activate             getNextTeamEntity            setCanBecomeDormant                  

     activateTargets      getOrigin                    setClipMask

     addClipMaskFlag      getScriptObject              setClipModel

     addContentsFlag      getScriptObjectBool          setColor

     addTarget            getScriptObjectFloat         setColorAndAlpha

     angleTo              getScriptObjectString        setContents

     bind                 getSize                      setHudWatchTarget

     bindPosition         getTarget                    setHighlight

     bindToJoint          getTeamChain                 setLinearVelocity

     bindToTag            getTeamMaster                setModel

     cacheSoundShader     getWorldOrigin               setName

     callFunction         hasFunction                  setOwner

     clampAngles          hide                         setOrigin

     distanceFromBounds   hideRenderModel              setProgressionOwner

     distanceTo           isHidden                     setScriptObject

     distanceToPoint      joinTeam                     setShaderParms

     fadeSound            makeActivatable              setSkin

     findEntity           notifyProgressionOwner       setTakesDamage

     findTeamEntity       numTargets                   setWorldOrigin

     getAngles            playVoiceOver                show

     getAngularVelocity   quitTeam                     showRenderModel

     getClipMask          randomTarget                 signalEvent

     getColor             remove                       startSoundShader

     getContents          removeBinds                  stopSound

     getLinearVelocity    removeClipMaskFlag           targetsReady

     getMaxs              removeContentsFlag           teleport

     getMins              removeTarget                 testFunctionality

     getModel             restorePosition              touches

     getModelForward      setAngles                    unbind

     getName              setAngularVelocity           wait

                                                       waitFrame

  B) idAnimatedEntity < idEntity

     getJointHandle

     getJointPos          setJointPos                  startFX

     getJointAngle        setJointAngle                stopFX

  C) idActor : < idAnimatedEntity

     

     Probably the second most common object you will work with.

     currentNPC           getWalkState                 leftFoot

     decreaseHealth       getWeaponReadyState          needsHealth

     disableLegIK         hideAttachment               numOfItemTypeInInventory

     disableWalkIK        increaseHealth               removeAllInventoryItems

     enableLegIK          isDead                       removeInventoryItem

     enableWalkIK         isDying                      rightFoot

     giveInventoryItem    itemInInventory              showAttachment

                                                       weaponBurstMode

  D) idThread : (sys methods)

     angToForward         getThreadHandle              setThreadName

     angToRight           getTicsPerSecond             sin

     angToUp              getTime                      spawn

     arcCos               getTraceBody                 spawnDecal

     arcSin               getTraceEndPos               sqrt

     arcTan               getTraceEntity               strLeft

     arcTan2              getTraceFraction             strLength

     assert               getTraceJoint                strMid

     cacheSoundShader     getTraceNormal               strRight

     clearSignalThread    halt                         strSkip

     cos                  isEntityValid                strToFloat

     createArray          isLayerActive                strToInt

     debugArrow           isValidDecl                  tan

     debugBounds          killByType                   terminate

     debugCircle          killThread                   threadCall

     debugLine            killThreadId                 trace

     destroyArray         music                        tracePoint

     disableSaves         onSignal                     trigger

     drawText             pause                        vecCrossProduct

     enableSaves          playerIsIncapacitated        vecDotProduct

     endThread            print                        vecLength

     error                println                      vecNormalize

     executeCommandText   radiusDamage                 vecToAngles

     fadeSoundGroup       random                       wait

     getcvar              randomInt                    waitFor

     getDeclName          randomSetSeed                waitForEvent

     getEntity            remove                       waitForFlags

     getFrameTime         say                          waitForThread

     getMapPath           setcvar                      waitFrame

     getThreadName        setThreadEntity              warning

-------------------------------------------------------------------------------

IV.3 > > > > Action Script

-------------------------------------------------------------------------------

  Action script is a small subset of ID Tech 5's scripting language. It

  consists of 95 commands that can be used to coordinate quick and

  dirty cut scenes without having to get your hands dirty writing actual

  code or creating/editing map.scripts.

动作脚本是IDTech5的脚本语言的一小部分。

它由95个命令组成,可以用来协调快速和肮脏的过场动画,

而不必让你的手肮脏的写作实际代码或创建/编辑  地图.脚本。

  Examples:示例:

  - Have enemies stand around talking to each other, unaware of the player,

    but then have them stop talking and fight if the player reveals himself.

让敌人站在周围互相交谈,却不知道玩家,

但如果玩家暴露了自己,就让他们停止说话并战斗。

  - Have an enemy perform a spectacular entrance animation before attacking,

like riding in on a zipline or jumping down from a balcony.

-让一个敌人在攻击前表演一个壮观的入口动画,

比如坐在拉链上或者从阳台上跳下来。

  - Have members of wellspring starts doing things to make the town feel alive.

    Like walking from point a to point b, or enter a looping idle

    animation that makes them sit or play a game...

-让wellspring (清泉镇)开始 做事 让小镇感觉有活力。

比如从a点走到b点,或者进入一个空闲的循环

让他们坐着或玩游戏的动画。

  To create action script: 要创建操作脚本,请执行以下操作:

    - go to Media Brwoser -> decls -> entityDef -> ai

    - select an entity

    - In the Properties window, open up: aiEditable -> spawnSettings

    - change the number of action script events from 0 to 1

    - When you click on the action script, a gui will come up that

      lists all action scripts.

- When you select an action, parameter combos will appear.

-去媒体Brwoser -> decls ->完整的Def->ai

-选择一个实体

-在属性窗口中,打开:ai可编辑的->生成设置

-将动作脚本事件的数量从0更改为1

-当你点击动作脚本时,就会出现一个gui

列出所有操作脚本。

-当您选择一个操作时,将会出现参数组合。

    While you can add action scripts to entity templates in the media browser,

    normally you first make the map and inject your instance and then add the

    action script to the instance. Thus you don't change ALL instances of

Ghost. Only a specific instance of Ghost.

虽然您可以在媒体浏览器中的实体模板中添加操作脚本,

通常,首先创建映射并注入实例,然后添加

对实例的动作脚本。因此,您不会更改的所有实例,Ghost只有一个特定的 Ghost实例。

  Notes:

    Action script sequences are meant to fire once and do not support

    looping or conditional branching.

动作脚本序列意味着要触发一次,而不支持

正在循环的或有条件的分支。

    Technically, "action_" precedes all the function names. They are defined

in the object hierarchy under the idAI2 Entity.

从技术上讲,“action_”出现在所有函数名之前。它们被定义

在idAI2实体下的对象层次结构中。

    Action Scripts do not reside in compiled .script files. Instead they

    become part of the entitydef or instance. Thus they provide a way of

    creating scripts that don't rely on global or map specific support

objects/functions.

操作脚本不驻留在已编译的。脚本文件中。相反,他们

成为整体结构或实例的一部分。因此,它们提供了一种方法

创建不依赖于全局或映射特定支持的脚本

objects/functions.

  List:

     ChangeAnimState      MoveToEntity                 SetPlayerFocus

     ChangeAnimStateVia   MoveToEntityNoFail           SetPosture

     ClearAimFocus        MoveToPathPoint              SetScriptAbort

     ClearLookFocus       MoveToPathPointNoFail        SetScriptFlag

     ClearScriptFlag      MoveToPoint                  SetSitState

     ClearWorldState      MoveToPointNoFail            SetStandState

     CrouchToStand        ForceAwarenessByDistance     SetSubWeb

     Dive                 ForcePlayerInteraction       SetWalkState

     Dodge                PlayInteractionVoiceOver     ShowAttachment

     DrawWeapon           PlayOverrideAnim             SpringAngles

     DropAttachment       PlayOverrideAnimInterrupt    SpringAnglesDisable

     EnableAutoFocus      PlayVoiceOver                SpringOrigin

     EnableBodyRotation   PullTriggerLeft              SpringOriginDisable

     EnableDamage         PullTriggerRight             SpringOriginAtRest

     EnableHeadTracking   ReleaseTriggerRight          StandToCrouch

     EnablePain           ReloadWeapon                 StartAnim

     EnterVehicle         ReloadWeaponTorso            StopVoiceOver

     EnableWalkIK         SetPlayerEnemy               TakeItem

     ForceAnimState       SearchToTarget               Trigger

     Pain                 SetAccuracy                  TurnToPoint

     ForceOpenCombat      SetActionNodeGroup           TurnToEntity

     PerformCoverAction   SetAimFocusOffset            TurnToEntityWithOffset

     GiveItem             SetAimPoint                  UseZipline

     HideAttachment       SetAIVar                     Wait

     HolsterWeapon        SetAlertCycle                WaitForAIVar

     Idle                 SetEnemy                     WaitForAnim

     IgnorePlayerApproach SetFireMode                  WaitForAnimVia

     LeapAttack           SetFocus                     WaitForEntity

     LoopAnim             SetLookFocusOffset           WaitForPlayerInteraction

     LoopAnimExitAtEnd    SetMoveMode                  ReleaseTriggerLeft

     Melee                SetMovePushStatus            WaitForTraversalAnim

     MoveToCover          WaitForPlayerInteractionDist

         

  For a full listing that includes parameters and descriptions (descriptions

  are with the constants), see:

  对于包含参数和描述的完整清单(描述

具有常量),请参见:

    <Rage Tool Kit>/base/script/script_events.script

  Thread Notes and Bugs  线程注释 和bug

    Action Script commands are meant to be used from the spawn settings of

    NPC entities. While you can technically call action_<SCRIPT> commands

from regular script, you have to be very careful about threading.

操作脚本命令旨在从的衍生设置中使用NPC实体。

虽然技术上可以调用action_<脚本>命令  从常规脚本来看,您必须非常小心线程。

    All action script commands are syncronis... that is, they lock the

    thread until they have completed. Typically, they use the object they are

affecting as their lock.

所有的动作脚本命令都是同步的……也就是说,它们会锁定的

线程,直到它们完成。通常,它们使用它们所在的对象

影响他们的锁。

    So if you use action_MoveToPoint, that thread will continue to override

    and control the entity until they reach the point. Any other threads

    will stop executing. For example, threads that might make the NPC

    follow the player. Or threads that might cause an interaction icon

to appear when you approach the NPC.

所以如果你使用action_MoveToPoint,该线程将继续覆盖并控制这个实体,直到他们到达这个点。

任何其他线程 将 停止 执行。

例如,可能生成NPC的线程跟随玩家。

或可能导致交互图标的线程 将在您接近NPC时出现。

    In particular, the "action_Set" commands can cause havoc. Unlike

    other commands that have a begin and an end, the Set commands take

    ownership of the entity for the lifetime of the thread they are called

    from. The Set commands are really only safe to use from the spawn

settings of the NPC.  

特别是,“action_Set”命令可能会造成严重破坏。不像

其他有开始和结束的命令,设置命令采取

它们被调用的线程生命周期内实体的所有权

从…Set命令确实只能从衍生程序中安全使用

NPC的设置。

    Finally, if you use an event (such as hitting the quick-use command)

    to fire action scripts on an NPC, secondary threads attempting to

    call action_<Script>s on an NPC already performing an action script

will actually crash the game.

最后,如果您使用一个事件(例如点击快速使用命令)

在NPC上触发动作脚本,辅助线程试图

在已经在执行操作脚本的NPC上调用动作_<脚本>

真的会让游戏崩溃。

    So general advice :

    1) Stick to commands that can finish/end

    2) Only use Set commands from spawn settings.     

    So how do you use an Action Script command and cancel it? There are

    two options:

    1) You remove/respawn the entity associated with the command... (thus

       releasing the lock).

1)移除/重生与命令相关的实体…(因此 释放锁)。

    2) YOu run your action script commands in a managed thread which

       you can terminate/kill at any time. I will note that this

       last approach is not bullet proof. Killing the thread doesn't

       really kill it. It suspends it and marks it for termination

       when you change maps. So if you use terminate(threadID) followed

       by "waitForThread(threadID)", waitForThread, will never return.

在托管线程中运行操作脚本命令 您可以随时终止/终结。

 我会注意到这一点 最后一种方法 并非 无懈可击。

终结线程则不然,真的停止了它。它将它挂起并标记为 终止

当你改变地图的时候。所以如果你使用 terminate (threadID)


通过"waitForThread(threadID)", waitForThread将永远不会返回。

       However, suspending the thread does allow you to start another action script without crashing the game.

然而,暂停线程 确实 允许 你在 不崩溃游戏的情况下  启动 另一个 动作 脚本。

But there is a limit of  around 8 or so threads,

suspended or not, that can simultaneousl   hold a lock on an entity.

但是有大约8个线程的限制, 无论是否挂起,它都可以同时持有一个实体的锁。

Once you hit the max locks, action scripts

       will stop working for that entity until you remove\respawn the entity.

一旦你达到了 最大 的 锁,动作脚本 将停止对该实体工作,直到 您 删除 该 实体。

       (You know the actions scrtips aren't working because they return

        immediatly when the lock attempt fails... so you can time the

        commands to detect when you have saturated the locks).

(你知道动作提示提示不起作用,因为它们返回了当锁定尝试失败时…

这样你就可以计时 用于检测锁是否饱和的命令)。

       Here is the framework for a global function solution. Note that you

       would have to create an gameStateInt and make sure it made it into the

       map/game.  This is only pseudo code. It hasn't been tested:

下面是一个全局函数解决方案的框架。请注意,您

将不得不创建一个游戏状态,并确保它进入

map/game.这只是一个伪代码。尚未进行测试:

       The method would be called like: thread actionWrapper(...);

该方法可以这样调用:

       void actionWrapper(entity someEntity, int actionType, int actionParam, int attempts) {

         if (attempts > 3) {

           sys.setGameStateInt("yourmod_actionThread",0);

           return;

         }

         if (0 != sys.getGameStateInt("yourmod_actionThread")) {

           sys.killThread(sys.getGameStateInt("yourmod_actionThread"));

           sys.wait(2.5);

         }

         sys.setGameStateInt("yourmod_actionThread",sys.getThreadID());

         float start = sys.getTime();

         // action commands...  使用记录命令

         if (1 == actionType) {

            someEntity.action_SomeAction();

         } else if (2 == actionType) {

            someEntity.action_SomeAction(actionParam);

         }

         if ((sys.getTime() - start) < 1.0) {

           // Depending on the action, it probably didn't work... Time

           // to remove the target entity, spawn a duplicate in its place and

           // retry...

//这取决于动作,它可能没有工作…时间
//删除目标实体,在其位置生成一个副本和
/ /重试…

           // Remove/Respawn entity...  移除/重生实体…

           someEntity.hide();

           entity newEntity = sys.spawn("some/replacement");

           newEntity.teleport(someEntity.getOrigin(),someEntity.getAngles());

           someEntity.remove();

           // Retry  重试 /睿创 /屡败屡战 /重新连接服务器

           thread actionWrapper(newEntitty, type, someParam, attempts + 1);

         } else {

           sys.setGameStateInt("yourmod_actionThread",0);

         }

       }

    Again, these are only issues if you use action_ script commands from

    within normal scripts and those scripts have multiple thread sources.

    As long as you avoid action_ scripts from normal scripts or you use a

    singleton pattern to ensure only 1 thread runs the actions, you

    shouldn't have an issue.              

同样,只有 在 使用 来自的 action_脚本命令时才会出现这些问题


在 普通 脚本 中,这些脚本有多个线程 源。


只要避免使用普通脚本中的动作脚本,或者使用 单例模式  确保 只有一个 线程 运行 操作

应该 没 什么 问题。

-------------------------------------------------------------------------------

IV.4 > > > > Map Scripts and Event Handlers  地图脚本和事件处理程序

-------------------------------------------------------------------------------

  As mentioned above, When you make a map, that map can be given a script

  which will load with the map. By default, the map will call the function

  "main()" within the script. However if you select the "World" Object within

  the World Editor when a map is loaded, over in the Entity Inspector (bottom

  left corner, left most tab) you will see a "call list" which is a list of

  functions you want called when the map loads. You can add additional methods

  to be called there.

如上所述,当您制作地图时,可以为该地图提供脚本 它将加载地图。

默认情况下,map将调用该函数 "main()"在脚本中。

但是如果你选择“World”对象  世界编辑器,当地图被加载,在实体检查器(底部)左上角,

最左边的选项卡),你会看到一个“呼叫列表”,这是一个列表  你想在地图加载时调用的函数。

您 可以 添加 其他 方法 被 召唤 到那里。

  If you define objects and functions within a map script (and compile it),

  they will be exposed the next time you load the map. They don't actually

  have to be in the script itself. They can be in a script that your map

  script "#includes"

如果在map脚本中定义对象和函数(并对其进行编译),下次加载地图时,它们就会暴露出来。

实际上并不是这样 必须是剧本本身。

他们可以在一个脚本,你的地图


script "#includes" ( 脚本“#包括“)

  If you then embed an INSTANCE of an entity into the map, you can shift

  click the INSTANCE and when you go to the entities script object type

  the combo box will list any Objects you have defined on the map script.

如果你将实体的实例嵌入到地图中,你就可以移动了


单击INSTANCE,然后转到  实体脚本对象类型


组合框 将列出 您在地图脚本 中 定义 的 所有 对象。

  In this section I will walk you through a simple example:

在本节中,我将向您介绍一个简单的示例:

  A) Duplicate an existing (small) map:

复制现有的(小)地图:

     ID Studio -> World Editor -> Open -> Map -> tutorial...

               -> basic_env -> basic_env.map

  

                      Then

     File -> Save As -> game/awesomemod.map

     It will ask you if you want to copy over the land textures, click [Copy]

它会问你是否要复制地面纹理,点击[复制] 

  B) Create a Script:

     1) File -> New -> Map Script

        Note that a map can only have 1 script.

       

        In the future, after you open the map, you will go to

        File -> Open -> Map Script

在未来,你打开地图后,你会去
文件->打开->地图脚本

  C) Define an Event Handler:

     // -----------------------------------------------------------------------

     // <Rage Tool Kit>/base/maps/game/awesomemod.script

     // -----------------------------------------------------------------------

     object AwesomeNPC {

       void   init();

       void   start();

       string msg;

     };

     void AwesomeNPC::init() {

       sys.println( "^2[Awesome]: init");

       // properties are set BEFORE init is called,

       if (msg == "") { msg = "Stop touching me!"; }

       int myThread = thread start();

     }

     void AwesomeNPC::start() {

       vector origin = self.getOrigin();

       string s_origin = "" + origin_x + "," + origin_y + "," + origin_z;

       sys.println( "^2[Awesome]: name   : [" + self.getName() + "]");

       sys.println( "^2[Awesome]: model  : [" + self.getModel() + "]");

       sys.println( "^2[Awesome]: origin : [" + s_origin + "]");

       self.setHudWatchTarget( true );

       self.setOwner($player1);              // prevent collision

       sys.wait(3); // wait 3 seconds

       sys.println( "^2[Awesome]: Starting monitor loop...");

       while (1) {

         if ( self.isDead() ) { break; }

         if ( self.touches( $player1 ) ) {

           sys.println( "^2[Awesome]: " + msg);

         }

         if ( self.needsHealth() ) {

           self.increaseHealth(10.0);

         }

         sys.wait( 1.5 );

       }

       sys.println( "^2[Awesome]: [" + self.getName() + "] has died");

     }

     void main() {

     }

     ---------------------------------------------------------------------------

  D) Compile Script:

     File -> Compile Script

  E) Re-Open Map

     World Edit -> Open -> Map -> game/awesomemod.map

  F) Create Entity INSTANCE:

     1) Right Click somewhere within the map boundaries (center?) and select:

        New Entity -> ai -> settlers -> wellspring -> Olive

        hit [ESC] to unselect all and then SHIFT + Click Olive within the map.

  G) Assign to your Event Handler :  分配给你的事件处理程序:

     - Open the  Entity Inspector (bottom left window, left most tab)

打开实体检查器(左下角窗口,最左边选项卡)

     - Expand [+] Script Object and click on the "type" combo box.

       You should see the AwesomeNPC type appear. Assign it to Olive.

展开[+]Script Object并单击“type”组合框。


您应该会看到AwesomeNPC类型出现。   分配给Olive。

     - Click the World Edit window, Hit ESC to deselect everything and then select

       Olive again with SHIFT + click.

-点击世界编辑窗口,按ESC取消所有选择,然后选择


用SHIFT + click再次使用Olive。

       When the Entity Inspector re-draws, it should expand and show the

       AwesomeNPC's AI "msg" variables. This lets you customize what she

       says when you run into her.

当实体检查器重新绘制时,它应该展开并显示 AwesomeNPC的AI“msg”变量。

这可以让你自定义她  当你遇到她的时候。

     - File -> Save

  H) Build the map/script:  构建地图 / 脚本:

     World Edit: Tab -> Build -> Full Map Build + MegaBake [default]

     [Done] (When finished)

  I) Test the map/script:  测试 地图/脚本:

     - Click on the Engine Tab

     - Hit the tilda key (~/`) to open console

     - type : devmap game/awesomemod`

  L) Walk over to Olive... maybe through her. Then open console and look

     at the output.

走到奥利弗身边……也许是通过她。然后打开控制台并查看 在输出端。

  In this particular example, I used a re-firing thread to periodically

  check the state of the NPC. There are often multiple ways of achieving the

  same goal. Many events such as job interactions and trigger events

  will automatically call "callbacks" on your Event Handler if you have

  methods set up to receive them.

在这个特殊的示例中,我使用了一个重新触发线程来周期性地 检查NPC的状态。

通常有多种方法来实现相同的目标。

许多事件,如工作交互和触发事件 将自动调用“回调”事件处理程序,如果你有


方法设置以接收它们。

  See: <Rage Tool Kit>/base/script/rage_npc.script for an example.

参见:<Rage Tool Kit>/base/script/rage_npc。示例脚本

  Finally, it should be noted that the scope of map scripts are limited to

  the map. When you leave the map, any threads spawned by your script will

  be ungracefully killed along with the parent thread. So for example, if

  the script above was attached to a sentry bot, the sentry bot would be

  destroyed and the script thread would be killed when you transitioned

  between maps. So if you relied on the died handler above to update

  a game variable or job state, you might miss the event.

最后,应该指出的是,地图脚本的范围是有限的地图。

当您离开地图时,脚本生成的任何线程都将离开

与父线程一起被不优雅地终止。

例如,如果 上面的脚本附加到一个哨兵机器人,哨兵机器人将是

销毁,脚本线程将在转换时被终结

-------------------------------------------------------------------------------

IV.5 > > > > Global Scripts and Event Handlers  全局脚本和事件处理程序

-------------------------------------------------------------------------------

  A) Mod Compatibility   模组的兼容性

     Before you embrace global scripts and event handlers, be aware that

     only 1 mod can edit the games main script: script_main.script.

在使用全局脚本和事件处理程序之前,

请注意 只有一个mod可以编辑游戏的主脚本:script_main.script。

     If a user tries to install 2 mods that edit that script, then one of them

     will not work.

The Scorchers DLC does not edit script_main.script, but

     that does not mean that a future DLC will not.

如果用户试图安装2个mod来编辑该脚本,那么其中一个不会起作用。

Scorchers DLC不编辑script_main.script ,但是 但这并不意味着未来的DLC不会如此。

     Avoid Global Script Edits if you can. Sadly, I realize that most mods

     that wish to edit/update the vanilla game will not be able to avoid

     making global edits.

尽量避免全局脚本编辑。 

可悲的是,我意识到大多数mod希望编辑/更新香草游戏将无法避免 进行全局编辑。

  

B) Compiling  编译 /编写 /编译阶段 /阶段

     So, if you start up ID Studio and open:  所以,如果你启动ID Studio并打开:

        <Rage Tool Kit>/base/script/script_main.script

     And attempt to compile it without making ANY edits, you will get a

     redefinition error. This is because the script is already loaded in memory

     because it is needed by ID Studio.

 并且尝试编译它而不做任何编辑,您将得到一个重新定义错误。

这是因为脚本已经加载到内存中 因为是ID Studio需要的。

     So... to edit the script, you must do it without using ID Studio.

     That is to say, if you shut down ID Studio, make edits to

所以…要编辑脚本,必须不使用ID Studio。
也就是说,如果你关闭了ID Studio, 请编辑

        <Rage Tool Kit>/base/script/script_main.script

     using your favorite text editing program, when you restart ID

     Studio, it will compile script_main.script and startup and make your

     changes available.

使用您最喜欢的文本编辑程序,当您重新启动IDStudio,它将编译script_main。脚本和启动,

并使您的 变化可用。

     Of coarse this basically sucks as you can't easily hit a compile button to

     see if your script has errors before you add it to the game.

这很糟糕,因为你不能轻易点击编译按钮

在将你的脚本 添加到游戏中之前,看看它是否有错误。

     So the typical way of writing global scripts is to start by creating

     the script as if it is going to be part of a stand alone map.

因此,编写 全局脚本 的典型方法是从创建开始  脚本就好像它将成为 独立地图的一部分

     Basically, follow the directions for IV.3 above.  基本上,遵循上面IV.3的指示。

     Once you have your script(s) working... then you move your code

     to a new file and use a #include to add it in script_main.script.

一旦你有你的脚本工作…然后移动代码 到一个新文件,

并使用#include将其添加到script_main.script中。

     Building on to the IV.3 example above, I would move the AwesomeNPC

     Event handler I created for the map to a stand alone file in the

     same directory as script_main.script:

在上面的IV.3示例的基础上,我将移动AwesomeNPC中的独立文件的映射所创建的事件

处理程序 与script_main.script目录相同:

     // -----------------------------------------------------------------------

     // <Rage Tool Kit>/base/script/awesome_npc.script

     // -----------------------------------------------------------------------

     object AwesomeNPC {

       void   init();

       void   start();

       string msg;

     };

     void AwesomeNPC::init() {

       sys.println( "^2[Awesome]: init");

       // properties are set BEFORE init is called,

       if (msg == "") { msg = "Stop touching me!"; }

       int myThread = thread start();

     }

     void AwesomeNPC::start() {

       vector origin = self.getOrigin();

       string s_origin = "" + origin_x + "," + origin_y + "," + origin_z;

       sys.println( "^2[Awesome]: name   : [" + self.getName() + "]");

       sys.println( "^2[Awesome]: model  : [" + self.getModel() + "]");

       sys.println( "^2[Awesome]: origin : [" + s_origin + "]");

       self.setHudWatchTarget( true );

       self.setOwner($player1);              // prevent collision

       sys.wait(3); // wait 3 seconds

       sys.println( "^2[Awesome]: Starting monitor loop...");

       while (1) {

         if ( self.isDead() ) { break; }

         if ( self.touches( $player1 ) ) {

           sys.println( "^2[Awesome]: " + msg);

         }

         if ( self.needsHealth() ) {

           self.increaseHealth(10.0);

         }

         sys.wait( 1.5 );

       }

       sys.println( "^2[Awesome]: [" + self.getName() + "] has died");

     }

     ---------------------------------------------------------------------------

     Notice that I left out the "main" block at the bottom.

请注意,我在底部遗漏了“主”块。

     I also need to update my map script and remove the definition as it will

     cause conflicts once the AwesomeNPC definition becomes global:

我还需要更新我的地图脚本,并删除该定义

一旦AwesomeNPC定义变成全局,会导致冲突:

     // -----------------------------------------------------------------------

     // <Rage Tool Kit>/base/maps/game/awesomemod.script

     // -----------------------------------------------------------------------

     void main() {

     }

     --------------------------------------------------------------------------

     Finally, I add a #include to  script_main.script when ID Studio is not

     running:

最后,当ID Studio不存在时,我向script_main.script添加一个#包含

跑步

     // -----------------------------------------------------------------------

     // <Rage Tool Kit>/base/maps/game/script_main.script

     // -----------------------------------------------------------------------

     /***********************************************************************

     script_main.script

     This is the main script that is loaded before any level scripts load.

     这是在任何级别的脚本加载之前都要加载的主要脚本。***********************************************************************/

     // these are automatically included by every script file

/这些都会自动包含在每个脚本文件中

     //#include "script_defs.script"

     //#include "script_events.script"

     // base defines and util functions

     #include "script_util.script"

     #include "debug_drawtext.script"

     #include "rage_npc.script"

     #include "awesome_npc.script"

     void script_main() {

          sys.print( "^3 --== Entering script_main() ==--\n");

//

// Do any script setup here

//

sys.print( "Exiting script_main()\n" );

     }

     ---------------------------------------------------------------------------

     If you do all of this, when you restart ID Studio, it will load the

     new AwesomeNPC as an available Script Object type which you can assign

     to whoever.

如果您执行所有这些,当您重新启动ID Studio时,它将加载

作为一个可分配的可用的脚本对象类型

给任何人。

     A more common example would be creating a new usable inventory item

     that can activate your script from anywhere in the game.  

     一个更常见的例子是创建一个新的可用的库存项

它可以在游戏中的任何地方激活你的脚本。

  C) Be careful with your names

     I advise adding your mods name to most of your globally exposed functions

     and Event Handler Objects to avoid conflicts with methods and event

     handler objects that may exist in vanilla or mod maps.

我建议将您的插件名称添加到大多数全局公开的函数中

和事件处理程序对象,以避免与方法和事件的冲突

可能存在于普通映射或mod映射中的处理程序对象。

  D) Threading

     Like Map Scripts, Global scripts and event handlers are ungracefully

     shutdown when the player transitions between maps. Like map scripts,

     you can not create a thread and expect it to still be running when you

     transition areas.

与映射脚本一样,全局脚本和事件处理程序也是不正常的

当玩家在地图之间转换时,会关闭。比如地图脚本,

你不能创建一个线程,并期望它仍然在运行时,当你

过渡区域。

  E) Persistence  /cleanup / initialization

     Trying to intercept exit map events or entity/prop destruction events is

     generally a bad idea. Even if you had the source code for the map, there

     are lots of ways one can leave a map and you would have to make sure you

     had code in place to handle them all.

试图拦截退出映射事件或实体/道具破坏事件是

一般来说,这是个坏主意。即使你有地图的源代码,你也可以在那里找到它

有很多方法可以留下一张地图,你必须确保你的位置

有了处理所有问题的代码。

     A better strategy is to focus on the map ENTER event. Perform your cleanup

     and re-initialization then.

一个更好的策略是专注于地图进入事件。执行清理

然后重新初始化。

     script_main.script: script_main() gets called every time a player enters a

     new map. So a simple strategy is to create a master "JustEnteredMap"

     event/routine that examines hidden inventory items and determines

     what was happening before you changed areas and takes appropriate

     actions to create the illusion of persistence.

script_main.script:每次玩家进入一个

新地图。所以一个简单的策略是创建一个大师“正义的地图”

检查隐藏的库存项目并确定的事件/例行程序

在你改变区域和采取适当的措施之前发生了什么

采取行动来创造一种坚持不懈的错觉。

-------------------------------------------------------------------------------

IV.6 > > > > Persisting data

-------------------------------------------------------------------------------

  I have actually found that persisting (script) data is one of the hardest

  things to do in this game and also very expensive.

我实际上发现,持久化(脚本)数据是最困难的方法之一

在这个游戏中要做的事情也非常昂贵。

  The main way of persisting data is by creating jobs and maintaining job

  state, but dealing with jobs is not easy from script.

持久化数据的主要方法是创建作业和维护作业

但是从脚本中,处理工作并不容易。

  The other way I have been able to persist data is through the presence of

  hidden inventory items.

  ** When you define an inventoryItem, you can mark it as not visible in the

     players inventory.

  You can think of a hidden inventory item like a global variable. It has an

  initial value of 0 (because there are 0 instances in the players inventory).

  Scripts can then add and remove instances, thereby incrementing and

  decrementing the value.

你可以想到一个隐藏的库存项目,比如一个全局变量。它有一个

初始值为0(因为在玩家库存中有0个实例)。

然后,脚本可以添加和删除实例,从而增加和

递减值。

  The only thing you have to be careful with is when you first enter a map,

  it takes the game some time to load everything and repopulate the players

  inventory. script_main.script runs well before the inventory is updated,

  so if you use inventory items for persistence, you will need to delay

  examination of the player inventory by 2 or 3 seconds using a thread.

你唯一要注意的是,当你第一次输入地图时,

游戏需要一些时间来加载所有内容并重新填充玩家

存货清单script_main.script在库存更新之前运行良好,

因此,如果您使用库存项目进行持久性,您将需要延迟

使用一个线程检查2或3秒的玩家库存。

  void do_checks() {

    sys.wait(2.5);

    ...

  }

  void script_main() {

    thread do_checks();

  }

    

  The game also supports something called a GameStateInt.

  GameStateInts are short lived global variables handy for communicating

  with in game objects like jobs and vo interaction and also between

  script objects/threads. IE: They are technically a property on the player

  and have to be declared in IDStudio (and used/referenced by a job or a VO

  so that they are compiled into the mod).

  However like all script variables, the life of a GameStateInt is limited

  to the game map unless it is part of a running Job.

这个游戏还支持一个叫做游戏的状态。

游戏状态变量是一种短期的全局变量,便于通信

在游戏对象如工作和vo交互之间也有

脚本对象/线程。从技术上讲,它们是玩家的财产

并且必须在IDStudio中声明(并由作业或VO使用/引用

这样它们就会被编译成mod中)。

然而,就像所有的脚本变量一样,游戏状态的使用寿命也是有限的

除非它是正在运行作业的一部分。

  INCLUDING HIDDEN INVENTOYITEM

    To get hidden inventory items included in the build, I normally

    create a welcome message job (see tutorial above) and as one of the

    rewards, remove all the hidden items from the players inventory. This

    will hint to the engine that it needs to include the items, even if

the reward is to remove them.

为了获得隐藏的库存项目包括在构建中,我通常

创建一个欢迎消息作业(请参见上面的教程),并作为其中一个

奖励,从玩家的库存中删除所有隐藏的物品。这个

会提示引擎它需要包括这些项目,即使

奖励是移除它们。

  GAMESTATEINT SETUP

  A) Declare your Game State Int variable

     Media Browser -> decls -> gameStateInt

  B) High-light an existing variable and select duplicate

     Use whatever path you want. IE:

     "awesomemod/awesomestate"

  C) Browser to your new GameStateInt and double click 浏览器到你的新GameStateInt并双击

     THere is one propery, this is the default value. Typically it is 0.

 有一个属性,这是默认值。通常是0。

  D) To access from script: 从脚本访问:

     float awesomestate = $player1.getGameStateInt("awesomemod/awesomestate");

  E) To set from Script:  // 从脚本设置:

     $player1.setGameStateInt("awesomemod/awesomestate",(awesomestate +

1));

  If you are unsure what path to use, Dble click on the variable within

  ID Studio and note the "Name" Field above the properties.

如果您不确定要使用什么路径,请直接单击其中的变量

ID Studio,并注意属性上方的“名称”字段。

  NOTE: To get  GameStateInts included in the build, you will likely need to

  associate them with a job.

For example, you could make them a failure  condition,

but use values that are so crazy that the job would never fail.

注意:要想在构建中包含游戏状态,您可能需要把他们和 job 联系起来。

例如,您可能会使它们成为一个失败者 条件,但是使用的值是如此疯狂,以至于job永远不会失败。

-------------------------------------------------------------------------------

IV.7 > > > > Global Script Memory Limits 全局 脚本内存 限制

-------------------------------------------------------------------------------

  A) What is a global script? 什么是全局脚本?

     As far as I can tell, pretty much all scripts are global except those

     used by spawn settings (action scripts).

据我所知,除了那些脚本之外,几乎所有的脚本都是全局的

用于衍生设置(操作脚本)。

  B) What is the memory limit?  //内存限制是多少?

     ID has a 65K limit. This can be exceeded by either having 65K of compiled statements or 65K of variables.

ID有一个65K 的限制。这可以超过有65K的编译语句或65K的变量。

  C) What happens if I break the limit?

     The game crashes to the main menu without saving when you try to load or start a game.

当你试图加载或开始一个游戏时,游戏会崩溃到主菜单而没有保存。

  D) How can I see how much memory I am using?

     When Rage loads a map, it tells you how much statment memory is being

     used in the console and the log. The output looks something like:

当《狂怒》 加载一张地图时,它会告诉你有多少statment memory (状态内存?)

在 控制台 和 日志 中使用。输出看起来类似于:

     Memory usage:      内存使用 /内存利用 /内存使用率 /内存使用情况

          Strings: 5, 568 bytes    字符串:5,568字节

       Statements: 918, 29376 bytes    <-- Maxes out at 65536

        Functions: 695, 85736 bytes    函数 : 695, 85736 bytes 

        Variables: 16548 bytes          变量:16548字节

         Mem used: 417232 bytes      内存使用:417232字节

      Static data: 803352 bytes     静态数据:803352字节

        Allocated: 1133568 bytes   已分配:1133568字节

      Thread size: 7888 bytes    线程大小:7888字节

    The first number (918) is the number of statements.

The second is how muchmemory they are using.

第一个数字(918)是语句的数量。

第二个是它们 使用 了多少 内存。

      Unfortunately, Variable memory usage is not as easy to discover.

      I see it when running mods in Rage, but not in ID Studio.

So you just  have to get into the habit of building daily so you know

when you have broken the limit.  

不幸的是,可变内存的使用情况并不那么容易 发现。

我在Rage中运行mod时看到了它,但在id  Studio中没有。

所以你要养成每天都做的习惯


当你突破了极限。

  E) That tells me overall how much is used. How can I tell how much I am using.

它告诉我 总的使用量。我怎么知道 我 用了多少?

    The easiest way is to have your script load with a small custom map.

    Alternatively, if you have included your script as part of

    script_main.script, your script will be loaded any time you load any

    devmap within the engine tab of ID Studio. So for example, open console and

type:

最简单的方法是用一个小的自定义映射来加载脚本。

或者,如果您已经将您的脚本作为其中的一部分

script_main.script,你的脚本将在你加载的任何时候加载任何

在ID Studio的引擎选项卡中开发的devmap。例如,打开控制台和

类型

      devmap tutorial/basic_env/basic_env

    Then re-open console and scroll up to see the memory usage summary.

然后 重新 打开 控制台,向上滚动以查看内存使用情况摘要。

    To figure out how much you are using, take a before and after

    snapshot. IE: load up the map with your scripts commented out and then

load it up with your scripts included.

要弄清楚你用了多少,在之前和之后做一个  快照。

用注释出来的脚本加载地图,然后  加载 它与 您的 脚本 包括在内。

    On my machine, a clean build with no extra scripts is already using:

在我的机器上,一个 没有 额外脚本 的 干净构建 已经在使用:

     Statements: 916, 29312 bytes  // 语句:916,29312字节

    Thus you dont really have 65K to play with. You also want to leave some

    breathing room for the original games scripts. IE: The game may start and

    play fine and then half way through the game, it crashes when you enter

    a map because that map has enough scripted material to push the game over the max.

这样你就没有65K可以玩了。你还想留下一些为 原始的游戏脚本 提供了喘息的空间。

游戏可能会开始和开始玩得很好,然后在游戏进行到一半,

当你进入时它就会崩溃,

因为这张地图拥有足够的 脚本花材质?(翻译可能有误)   去推动游戏 超越 极限。

    Surprisingly, Rage doesn't actually use many per-map scripts, but they do exist.

You will want to leave about 3K of breathing space to be on the safe  side.

令人惊讶的是,《狂怒》并没有使用很多地图脚本,但它们 确实 存在。

为了安全起见,你需要留出大约3K的安全 空间吧?。

    So that leaves you with about 32K to play with.  

这样你就剩下32K来玩了。

  F) Any Guidlines? 指导吗?

    The memory limit has nothing to do with the actual size of your script or

    variable names. At runtime, scripts get compiled. Things like Documentation

    are discarded. Variables names are replaced with memory addresses, so the

size of your variable and method names has no impact.

内存限制与脚本的实际大小无关,或变量名称。

在运行时,脚本会被编译。类似文档的东西被丢弃。

变量名称被替换为内存地址,因此 变量和方法名 的大小没有影响。

    So what uses up statement memory?  那么是什么耗尽了语句内存呢?

    - Every class object/type definition

    - Every method definition

    - Every method parameter uses

- Every API method call.

-每个类对象/类型定义

-每种方法定义

-每个方法参数都在使用

-每个API方法调用。

    Variables do NOT use up statement memory, but they do use up variable

    memory, which is not as easy to see from ID Studio. In general, variables

    use less memory than API methods. So if using some variables can

    avoid calling a api method more than twice, generally you should use a

variable.

变量并不会使用完语句内存,但它们确实会使用完变量

内存,从ID Studio中不那么容易看到。一般来说,变量

比API方法使用更少的内存。所以,如果使用一些变量,就可以

避免调用api方法超过两次,通常应该使用 变化的

    statements include:  陈述式

       if (condition)

       somevar = value;

       sys.getTime();

       self.localMethod();

    So lets take this example:

       void debugPrint(string msg) {

         if (debug) { sys.println(msg); }

       }

    Now assume that you use debugPrint() throughout all of your code. The

question is : Does such a strategy save any memory? The answer is yes.

现在假设您在所有代码中都使用调试gprint()。

这个 问题是: 这样的策略能节省任何内存吗?答案是肯定的。

    The reason here is because you are taking 2 statements that always happen

    together (if and println) and combining them into one. Calling debugPrint

    one time may be more expensive, but after 2 or 3 calls, it starts to save

memory.

这是因为你做了两个经常发生的陈述结合在一起(如果和打印出来的n),

并将它们组合成一个。调用调试打印一次可能更贵,但2到3次后,就开始节省 内存 了

    Even Better:  甚至更好

    // #define debugPrint(msg)  (msg)

    #define debugPrint(msg)  sys.println( msg );

    Now, when you compile for production, you can remove the sys.println()

    methods from you code altogether by swapping comments.  In my case, this

    shaves off about 3K of memory, which is ironically how much you want to

    leave for safety reason. So this particular strategy us highly recommended.

现在,当您为生产环境编译时,您可以删除sys.println()方法通过 交换注释 从 代码 中删除。

对我来说,就是这个 会减少大约3K的内存,

讽刺的是,这正是你想要的 为安全起见请离开。所以我们强烈推荐这种特殊的策略。

    As far as I can tell, every API method results in a larger block of inlined code at compile time.

Some methods are more expensive than others.

据我所知,每个API方法在编译时都会 导致 更大的 内联 代码 块。

有些方法比其他方法更昂贵。

    Take this example:   举个例子来说

      $player1.removeInventoryItem( "some/item1",2);

      $player1.removeInventoryItem( "some/item2",2);

      $player1.removeInventoryItem( "some/item3",2);

      $player1.removeInventoryItem( "some/item4",2);

      $player1.removeInventoryItem( "some/item5",2);

      $player1.removeInventoryItem( "some/item6",2);

    You can save about 2K of statement memory by doing this instead:

      int c = 1;

      while (c != 7) {

        $player1.removeInventoryItem( "some/item" + c,2);

        c += 1;

      }

    Each usage of removeInventoryItem will be expanded inline. By placing it in

    a loop and doing variable manipulation, we cause the code block to be

    inlined once instead of 6 times.

removeInventoryItem的每次使用 都将 内联扩展。

把它放在 一个循环和做变量操作,我们使代码块为 内联一次 而 不是 6次。

  G) What Else?  还有什么?

     When writing scripts, you need to make a habit of compiling your mod and

     keeping an eye on the Statement Memory usage. This is especially true when

     introducing new ID script commands that you are not familiar with. Do

     before and after snapshots and see how much memory using that ID Script

     function you have your eye on really costs you.

在编写脚本时,您需要养成编译mod和的习惯  密切关注语句内存的使用情况。

尤其是当  介绍您不熟悉的新 id 脚本 命令。

做并查看使用该ID脚本的内存大小 ,你所关注的功能 确实 会让 你 付出代价。

     By doing daily checks, you will have some idea of when/if you have

     done something that is pushing your script over the memory limit.

     Personally, I tend to code however I want and then retroactively free  

     up memory by applying some of these concepts if/when the limit is

     actually hit:

     - Instead of using polymorphism, you can collapse several object classes

       into one class with a class variable that marks the type.

  H) Uninvestigated workarounds:

     The console allows you to compile and load a script using console

     commands. For example there are commnads like:

     convertToSuperScript    converts a .script file to a .ss file

转变 a .脚本文件发送到 a .ss文件

     ReloadSuperScriptDLL    Reload super script重新加载超级脚本

     script                  executes a line of script执行一行脚本

     Furthermore, a script can execute console commands:

此外,脚本还可以执行控制台命令:

     sys.executeCommandText("console command");

     It MIGHT be possible to make larger scripts dynamically load

     after the map loads using console commands relayed from a

     very small global bootstrap script, allowing you to bypass the

     typical global memory script size checks. However I haven't spent

     much time on this because even if one was successful, I am not

     sure how stable the solution would be. Basically this assume that the

     script limit is a bug and not by design.

也许有可能动态加载更大的脚本

地图加载后使用控制台命令从非常小的全局引导脚本,

允许您绕过典型的全局内存脚本大小检查。

不过我还没花我在这方面花了很多时间,因为即使有一个人成功了,

我也没有确定这个解决方案会有多稳定。

基本上,这是假设的脚本限制是一个错误,而不是通过设计。

     If someone looks into this and is able to compile and load

     scripts from console at runtime that bypass memory limits, let

     me know and I will add a blurb here to the notes.

如果有人调查了这个问题,并能够编译和加载

运行时控制台的脚本绕过内存限制,

让我知道,我将在笔记上添加一个简介。

-------------------------------------------------------------------------------

IV.8 > > > > DECL Pathing

-------------------------------------------------------------------------------

  There is a console command called "give", which has a script counterpart:

有一个叫做“give”的控制台命令,它有一个对应的脚本:

  $entity.giveInventoryItem("decl/path",#);

  What I noticed as I created various objects is that there is a degree of

  refactoring that goes on by the compiler when you compile the mod.

当我创建各种对象时,我注意到的是有一定程度的

编译器在编译mod时继续由编译器进行的重构。

  For example, DECLS has the following paths:

例如,DECLS有以下路径:

    decls -> throwable     -> throwable -> ....

    decls -> weapon        -> weapon    -> ....

    decls -> inventoryItem -> inventory -> ....

    decls -> health        -> inventory -> ....

    decls -> ammo          -> ammo      -> ....

  However, if I make a new throwable, instead of using the path:

但是,如果我做了一个新的可投掷的东西,而不是使用路径:

    give "throwable/throwable/customthrowable"

  instead I have to use the path: 相反,我必须使用这个路径:

    give "throwable/customthrowable"

  Same thing for ammo, health and weapons. What this tells me is that at

  compile time, ID Studio collapses most of the directories into a single

  resources directory.

弹药、健康和武器也是如此。

这告诉我,在编译时,ID Studio将 大部分 目录 折叠成

一个目录资源目录。

  This is why you often times see parent directories with a child that has

  the same name as the parent.

这就是为什么您经常看到  父目录的子目录       与 父级 同名。

  At the end of the day, this just makes everything scattered and confusing.

  You might think that all inventoryItem definitions that you can use with

  the give command would be found under inventoryItem, but in fact they are

  spread out amongst various parent category directories.

在一天结束的时候,这只是让一切变得分散和混乱。

您可能认为您可以使用的所有库存项目定义

给予命令将在 库存项目 下找到,但实际上它们是分布在各种父类别目录中。

  Keep this in mind if you make use of the giveInventoryItem() command.

  Under almost all conditions, you ignore the root directory name and start

  from the child directory in describing the path to the object.

如果您使用了提供的 giveInventoryItem()  ( 得到 存货 物品)命令,请记住这一点。

在几乎所有条件下,您都可以忽略根目录名称并启动 从 子目录中 描述到 对象 的 路径。

===============================================================================

V. > > > > Editing and Customizing NPCs  编辑和自定义npc

===============================================================================

-------------------------------------------------------------------------------

V.1 > > > >  Mr. Potato Head style  土豆头先生造型

-------------------------------------------------------------------------------

  Md6Mesh files use a pretty strait forward, human readable format. Internally,

  most of the files describe separate objects referred to as sub-meshes.

For   example, one submesh may be called "hat".

Another may be called "belt". And

  then there is the face, the torso, the backpack, ect....

Md6网格文件使用了一个相当狭窄的向前,人类可读的格式。

内部,大多数文件都描述了被称为 子网格 的单独对象。

为了例如,一个子网格可以被称为“hat”。

另一种可以被称为“belt”。(belt 皮带)

和 然后 是 脸,躯干,背包,等等。

  So, the raw md6mesh files do not describe a single hull, but rather many

  parts that are combined together when the model is built using ID Studio.

  Thus 12 different torsos/boots/jackets and various accessories could result

  in hundreds of unique looking combinations.

因此,原始的md6网格文件并没有描述单个船体,而是描述了很多船体

在使用ID Studio构建模型时组合在一起的部件。

因此,可能会产生12种不同的躯干/靴子/夹克和各种配件

在数百种独特的外观组合中。

  Well, as it turns out, each submesh is more or less independent of the file

  it is sitting in.  

So using nothing but a text editor like Notepad (or NotePad++),

you can literally copy and paste parts from one NPC

  to another, so long as the body types are similar.

事实证明,每个子网格或多或少都独立于文件

它坐在里面。

所以除了使用像记事本这样的文本编辑器(或者

NotePad++),你可以从一个NPC中复制和粘贴部件,只要体型相似。

  All that matters is that the skeletons of the models you are swapping

  between are the same. Most humanoid NPCs and monsters all use the same

  skeleton.

最重要的是你要交换的 模型的骨架 两者是相同的。

大多数人形 npc 和 怪物 都使用 相同 的 功能骨架

  A) Example: 例子 /榜样 /实例 /范例

     1) Create the directory:  1)创建目录:

         <Rage Tool Kit>\base\md6\awesomemod\mesh

       And copy

         <Rage Tool Kit>\base\md6\characters\settlers\mesh\ginny.md6mesh

       to

         <Rage Tool Kit>\base\md6\awesomemod\mesh\ginny.md6mesh

1)创建目录:1)创建目录:
<Rage Tool Kit>\base\md6\awesomemod\mesh
和复制
<Rage Tool Kit>\base\md6\characters\settlers\mesh\ginny.md6mesh


到<Rage Tool Kit>\base\md6\awesomemod\mesh\ginny.md6mesh

  1. Start up rage tool kit (restart it if it is already running)
  2. 2)启动狂怒工具包(如果它已经在运行,则重新启动它)

        MEDIA_B -> decls -> md6def -> settlers -> wellspring -> ginny.md6

        Right click "ginny.md6" -> duplicate -> "awesomemod/newginny.md6"

MEDIA_B -> decls -> md6def ->移民->井泉-> ginny.md6

右键单击“ginny.md6”->复制->“awesomemod/newginny.md6”

        Browse to the duplicate: 浏览副本:

          MEDIA_B -> decls -> md6def -> awesomemod -> /newginny.md6

          (Double click to open)

        Over on the right hand side under "Model Def Properties", you will

        see: MD6 Mesh Name. Click on the field, then the [...] and browse

        to the new md6mesh you just duplicated. (md6/awesomemod/mesh/ginny)

在右边的“模型定义属性”下,你会

请参阅:MD6网格名称。

点击字段,然后…然后浏览到新的,你刚刚复制的md6网格。

(md6/awesomemod/mesh/ginny)

     3) Grab Elizabeth 4:           3) Grab伊丽莎白4:

         Using Notepad or Notepad++, Open up

   使用 记事本 或 notepad++,打开

         <Rage Tool Kit>\base\md6\characters\settlers\mesh\Elizabeth.md6mesh

         Search for: name "elizabeth4"

         (with double quotes0>

搜索:名称“elizabeth”  (带双引号)

         Grab the Elizabeth 4 mesh (place cursor before "mesh", scroll down

         to the end of the mesh definition and SHIFT + CLICK after it to

         highlight all, then hit CTRL + C to copy).

抓取伊丽莎白4网格(将光标放在“网格”之前,向下滚动

到网格定义的末尾,并将+在其后面单击移到 突出显示所有内容,

然后点击CTRL + C进行复制)。

     4) Paste into newginny.md6mesh:   4)粘贴到newginny.md6mesh:

         Using Notepad or Notepad++, Open up

         <Rage Tool Kit>\base\md6\awesomemod\ginny.md6mesh

         search for "fem_bikini_low03" until you find the mesh definition.

         Highlight the mesh definition, hit delete and then paste in

         the elizabeth4 mesh in its place.

搜索“fem_bikini_low03”,直到您找到网格定义。

突出显示网格定义,点击删除,然后粘贴到其中

伊丽莎白4号网格就在它的位置上。

     5) Grab Elizabeth 6

        Same as step 3, only this time you are grabbing the "Elizabeth4"

        Mesh

和第三步一样,只是这次你抓住了“伊丽莎白4号”

网状

     6) Paste into newginny.md6mesh    6)粘贴到newginny.md6mesh

         search for "fem_shortsleeve_low01" until you find the mesh definition

         Highlight the mesh definition, hit delete and then paste in

         the elizabeth6 mesh in its place.

搜索“fem_shortsleeve_low01”,直到您找到网格定义

突出显示网格定义,点击删除,然后粘贴到其中

伊丽莎白6号网格就在它的位置上。

  1. Scrap Ginny's shoulder pad: 
  2. 7)废料金妮的肩垫:

         search ginny.md6mesh for shoulder_low01 until you find the mesh. hi-

         light and delete it.

在ginny.md6mesh中搜索shoulder_low01,直到找到网格。

hi-点亮并删除它。

     8) Update numMeshes:

        You replace 2 meshes and removed 1. So numMeshes should be changed to

        15.

     9) Save ginny.md6mesh.   保存ginny.md6mesh。

        If you open up an MD6 NPC file in ID Studio

        如果你在ID Studio中打开一个MD6 NPC文件

        (decls -> md6 -> awesomemod -> newginny)

如果您在ID Studio中打开一个MD6 NPC文件

(decls -> md6 -> awesomemod -> newginny)

        You will notice a little button in the preview toolbar which reads

        "Reload Everything"  when you hover over it. This will reload the mesh

        and textures, allowing you to see your changes to the text file as you

        go. Often times I have to hit the reload twice on my machine for the

        change to get recognized, but this saves me a lot of time.  

您会注意到预览工具栏中的一个小按钮,它可以读取当你悬停时,“重新放在它上面。

这将重新加载网格和纹理,允许您看到您对文本文件的更改去,

很多时候,我必须在我的机器上重新加载两次

改变是为了得到认可,但这节省了我很多时间。

     ** To be comprehensive, we should have also grabbed Elizabeth's neck

        (elizabeth5) and replaced Ginny's neck. However as this is just an

        example, I didn't feel the extra steps necessary.

**要更全面,我们也应该抓住伊丽莎白(狂怒游戏中角色 ,应该是模型的操作)的脖子

(《伊丽莎白5号》),并取代了金妮(游戏中角色,模型)的脖子。

然而,因为这只是一个例如,我觉得没有必要采取额外的步骤。

  B) Notes: 注释,说明,笔记

     1)  NumMeshes

         At the top of md6mesh files you probably noticed the "init" block

         where the sub-meshes are defined with names. The init block can be a

         good guide for the layout of the file,  but it is ultimately ignored

         by the loader.

在md6网格文件的顶部,您可能注意到了“init”块

其中,子网格是用名称定义的。

init块可以是a这是指导文件布局的 良好指南,但它最终被忽略了由加载器。

         When these files are loaded, the only thing ID Tech actually cares

         about are the numMeshes and numJoints values, and then the actual

         definition blocks themselves. You shouldn't be messing with

         numJoints.

当这些文件被加载时,id Tech引擎唯一真正关心的是

关于是数字网格和数字关节的值,然后是实际的值 定义块本身。你不应该搞乱了

numJoints.

         So for example, if you change numMeshes to "1" and load it up in ID

         studio, the engine will show the very first mesh and ignore the

         others.

例如,如果你将数字网格更改为“1”,并以ID的形式加载它

工作室,引擎将显示第一个网格,并忽略别的

         It also doesn't matter if the name of the mesh actually matches the

         name in the init block. (As you probably noticed during the example).

         There  is no validation.

网格的名称是否 实际匹配 也无关紧要

在init块中的名称。(正如您可能在本示例中注意到的那样)。

没有验证。

        ** I still try to keep the order and names consistent for my own

           sanity.

**,我仍然努力保持我自己的顺序和名字一致 理智 。

     2) Seeing what you are doing:   2)看到你在做什么:

        As mentioned in the last step of the example, at any time you can

        hit the "reload everything" button and it will show you the current

        state of the model.

    正如示例的最后一步中提到的,在 任何时候 都可以

点击 “重新加载一切” 按钮,它会 显示 你 当前的情况 模型 的 状态。

     3) identifying what a sub-mesh represents visually

        It isn't always easy identifying what a sub-mesh translates to

        visually.   Often times they have generic names like "Elizabeth1",  

        "Elizabeth2".

识别一个子网格翻译成什么并不总是容易的

视觉上通常 他们 都有 一些 通用的名字,比如“伊丽莎白1号”,“伊丽莎白2”。

        I normally use the texture mapping as a hint. Sometimes the texture

        name alone is all I need. IE "common/eyes_blue"... probably maps

        to the eyes.

我通常使用纹理映射作为提示。有时纹理我只需要一个名字。

我是“普通的/eyes_blue”……可能是地图的眼睛。

        However, when editing models, I also normally keep another program  

        running (like Adobe Photoshop) that can show me all the TGA's in a

        directory. I also leave ID Studio running so I can see the textures

        on the model.

Between the two, I can normally figure out what part a sub-mesh maps to.  

但是,在编辑模型时,我通常也会保留另一个程序运行(像Adobe ps),

可以显示我所有的TGA在一个 通讯录 我 还让 ID Studio开始运行,

这样我就可以看到纹理了在模型上。

在这两者之间,我通常可以弄清楚子网格 映射 到 哪个部分。(翻译可能有误 )

     4) Editing Textures:  组织和编辑纹理

        If you plan on editing textures, you will want to grab the texture

        information from the md6mesh file and write it down somewhere.

如果您计划编辑纹理,则需要获取纹理

信息从md6网格文件,并写在 某个地方。

        md6mesh files do not point directly at raw tga's. Rather they

        point at texture definitions, typically found under

md6网格文件不直接指向原始tga的。

而是他们指向纹理定义,通常发现在

           decls -> material -> models -> ...

        These definitions are normally contained within .m2 files.

        Most of these definitions include several tga files for the

        bump map, specular and diffuse settings.

这些定义通常包含在.m2文件中。

这些定义大多数包含几个tga文件凹凸贴图、镜面设置 和 漫反射设置。

        If you want to edit model textures, you will want to duplicate

        the texture definition that your cloned md6 file points at

        (maybe place the new definitions under your own directory)

        and then edit the definitions so that they points to your

        own raw tga files.

如果要编辑模型纹理,则需要复制您所克隆的md6文件 所指向的 纹理定义

(可能会将新的定义放在您自己的目录下)

然后编辑定义,使它们指向你的自己的原始tga文件。

-------------------------------------------------------------------------------

V.2 > > > >  Deforming Models with Blender

用Blender变形模型

  Before we begin, lets clarify something:

在我们开始之前,让我们澄清一些事情:

  ID Tech 5 lets you export models to LZO from the preview pane. These lzo

  files include mesh/hull information, but do not include bones, skeleton or

  armature information.

ID Tech 5允许您从预览窗格导出 模型 到 LZO。

这些 lzo文件包含 网格/船体信息,但不包括骨骼、骨架或(盔甲,甲胄,电枢?)信息。

  However bones, skeleton and armature information don't really matter if

  we are talking about static objects in the game that don't move... like

  rocks... or even many of the weapons.

然而,骨骼、骨骼 和( 盔甲,甲胄 电枢 )的信息并不重要

我们 谈论的 是游戏中不移动的静态对象……比如 岩石……甚至是许多武器。

  When editing a non-animated PROP, you can assign the render model to an

  lzo file that you have made without the need to convert to md6.

在 编辑 非动画 的PROP时,可以将渲染模型分配给lzo文件,你已经做了,

而不需要转换为md6。

  These directions only apply to people who wish to edit ANIMATED entities

  such as NPCs, where the edits must be made to md6mesh files.

这些说明仅适用于希望编辑动画实体的人

例如 npc(非玩家角色),其中必须对md6网格文件进行编辑。

  1. Breaking things out:A)突破:

     So, the first step to editing an MD6mesh is to export each of the

     md6mesh subparts as separate lzo files. This actually isn't as

     complicated as it sounds thanks to the numMeshes property.

因此,编辑MD6网格的第一步是导出每个md6网格子部分

作为单独的lzo文件。

实际上 不是 这样的 由于 数字网格属性,这 听起来 很 复杂。

     As mentioned earlier, when numMeshes is set to 1, then ID Studio

     will only load the first mesh defined in the file. This fact will save

     us a lot of time.

因此,编辑MD6网格的第一步是导出 每个md6网格 子部分作为单独的lzo文件。

实际上不是这样的由于数字网格属性,这听起来 很 复杂。

如前所述,当numMeshes设置为1时,则为ID Studio将只 加载 在 文件中 定义 的第一个网格。

这一事实 将 节省 我们  很多时间。

     Example:例子

     1) Backup the md6mesh file: 备份md6mesh文件

        Copy

          <Rage Tool Kit>\base\md6\characters\settlers\mesh\ginny.md6mesh

        to

          <Rage Tool Kit>\base\md6\characters\settlers\mesh\ginny2.md6mesh

1)备份md6网格文件:

复制 <狂怒工具包>\base\md6\characters\settlers\mesh\ginny.md6mesh

向  <狂怒工具包 >\base\md6\characters\settlers\mesh\ginny2.md6mesh

    

 2) Fix NumMeshes:      2)修复数字网格:

        Using Notepad or Notepad++, Open up   使用记事本或记事本++,打开

          <Rage Tool Kit>\base\md6\characters\settlers\mesh\ginny.md6mesh

        One line 5, Change "numMeshes 16" to "numMeshes 1"

        Save the file.

在第5行、将“numMeshes 16”改为“numMeshes 1”


保存文件。

        Scroll down to the first mesh definition: 向下滚动到第一个网格定义:

          name "Object43"

          shader "models/characters/settlers/wellspring/females/bracer2_ginny"

        Note the name of the sub-mesh is "Object43"

请注意,子网格的名称是“对象43”

     3) Start up rage tool kit (restart it if it is already running)

        MEDIA_B -> decls -> md6def -> settlers -> wellspring -> ginny.md6

        If all is going well, you should see Ginny's left arm bracelet.

        If you still see the full ginny.md6 model, hit the "Reload everything"

        button.

3)启动狂怒工具包(如果它已经在运行,则重新启动它)

MEDIA_B -> decls -> md6def ->移民->井泉-> ginny.md6

如果一切顺利,你应该看看金妮(模型)的左臂手镯。

如果你仍然看到完整的ginny.md6模型,点击“重新加载一切”

纽扣

     4) Within the Preview Pane, find the toolbar button that says

        "Export Model" when you hover over it and click it. Place the

        file anywhere you want, but make sure you name it "Object43".

4)在预览窗格中,找到工具栏按钮上说

“导出模型”时,当你悬停在它上面,并单击它。放置

文件在任何你想要的地方,但确保你命名它为“对象43”。

     5) Back to the text editor, SHIFT + CLICK to highlight the Object43

        mesh definition and delete it. Then hit save. Note the name of

        the next mesh:

  1. 返回到文本编辑器,SHIFT +单击以突出显示对象43

网格定义并删除它。

然后点击保存。 注意的名称下一个网格:

          eye_shadow02

     6) Back to ID Studio, Within the Preview Pane, find the leftmost

        toolbar button that says "Reload All". Hit it once or twice.

6)返回到ID Studio,在预览窗格中,找到最左边的

工具栏按钮,说“重新加载所有”。点击一两次。

        The second object (eye_shadow) is small and black, so you may

        not see it. Still, export the lzo model with the name

        "eye_shadow02"

第二个物体(eye_soad)是小而黑色的,所以你可以没有看到它。

不过,请导出具有该名称的lzo模型

" eye_shadow02 "

     7) Repeat step 5 and 6 until there are no more sub-meshes left.

        That is, deleting the top most mesh, reload the file in ID Studio

        and then save the mesh as its sub-mesh name over and over until

        there are no sub-meshes left.

  1. 重复步骤5和步骤6,直到不再剩下子网格为止。

也就是说,删除最上面的网格,在ID Studio中重新加载文件

然后 将 网格 反复 保存为 其 子网格 名称,直到 没有 留下 任何子网格。

        I found sometimes ID Studio would crash. When that happens, it is

        not a big deal. Just restart it and continue where you left off.

 我发现有时ID Studio会崩溃。

当这种情况发生时,它就是这样的,

没什么大不了 只要 重新 启动 它,并继续在 你离开的地方。

        When you are done you should have 16 lzo files. One for each of the

        md6mesh's original sub-meshes. At this time, you can delete

        ginny.md6mesh and restore ginny2.md6mesh back to the original file.

当你完成任务时,你应该有16个lzo文件。

给每一个的md6网格的原始子网格。

此时,您可以删除ginny.md6mesh,并将ginny2.md6mesh还原到原始文件。

  1. Import into blender: (I used a fresh install of version 2.68)

  1. 导入到Blender:(我使用了一个新安装的版本2.68)

  1. Activate the Lightwave import script:  激活Lightwave导入脚本:

        Start Blender (if it is not already running)

启动Blender(如果它尚未运行)

        Within Blender: From top to bottom, you will see 3 menu bars

        The top menu bar will have an "i" icon at the far left.

        The middle menu bar will have a 3d box icon at the far left.

        The bottom Menu Bar will have clock icon at the far left.

在Blender :从上到下,你会看到3个菜单栏,顶部的菜单栏在最左边有一个“i”图标。

中间的菜单栏在最左边有一个3d框图标。

底部的菜单栏在最左边会有时钟图标。

        You want to click on the top menu bar's "File" and select

        "User Preferences". Go to the "Addons" Tab, category

        "Import/Export" and check

你想要点击顶部菜单栏的“文件“,”并选择“用户首选项”。

进入“插件”选项卡,类别“导入/导出”并检查

        [X] Import Lightwave Objects  导入LightWave (应该是lightwave软件制作的模型)对象

        Click the "Save as Default" button.

点击“另存为默认值”按钮。

  1. Clear the default Scene: 清除默认的场景:

        The Default Scene contains 3 items. A light source, a cube and a

        camera. Right click each of the 3 items and hit the "Delete" key.

        Confirm you want to delete.

默认场景包含3个项目。

一个光源,一个立方体和一个a照相机右键单击这3个项目,

然后点击“删除”键。

确认您要删除。

        ** You can also press "a", which will select all and hit delete.

        ** You don't want any extra stuff in the scene or it will complicate

           the export.

**你也可以按“a”,这将选择所有并点击删除。

**你不希望在场景中出现任何额外的东西,否则它会复杂化

导出。

     3) File -> Import -> LightWave Object (lwo)

        Browse to the location you exported and import.

        (RAGE)\base\Object43.lwo

     4) Repeat as necessary. Each time you import a new lwo, it will

        create a new layer dedicated to that lwo.  

  1. 根据需要重复。
  2. 每次你导入一个新的lwo时,它都会输入的

创建一个专用于这个的新层。

  C) Maneuvering:

     Middle MOUSE = ROTATE CAMERA (z axis)

     SHIFT + Middle Mouse = MOVE CAMERA (x,y)

     MOUSE WHEEL UP/DOWN = ZOOM IN OUT

     'a': toggle selecting everything/nothing (only affects

          currently selected layer).

“a”:切换选择一切/无(仅影响

当前选定的图层)。

     IMPORTANT: You can not do anything that would add or delete

     a vertice. If you do something unexpected, I would recommend

     backtracking to "B.2" above and re-performing the previous

     steps.

重要的是:你不能做任何可以添加或删除的事情一个晶格。

如果你做了一些意想不到的事,

我推荐你回溯到上面的“B.2”,

并重新执行前一个步骤

  D) Exporting:

     File -> Export -> "Object (.obj)"

     OBJ format is also human readable and follows the same basic

     principles as md6. However, OBJ lists the vertices in a  

     different order (left to right) and with the polarity

     switched of the second parameter switched (negative when

     original was positive).

OBJ格式也是人类可读的,

并遵循相同的基本原理原则如md6。

然而,OBJ在a不同的顺序(从左到右)和

与极性切换的第二个参数切换(负值时原始是积极的)。

     Still, it is pretty easy to merge the various points by

     eye and make the necessary adjustments. Assuming the changes

     were minor (clothing seem shifting, etc)... you can generally

     assume the original MD6's polarity is still accurate.

尽管如此,还是很容易合并不同的点眼睛,

并做出必要的调整。

假设更改是次要的(衣服似乎在移动,等等)…

你可以假设原始的md6的极性仍然是准确的。

     Still, this can be very tedious if you are dealing with 1000+

     points. So I wrote a merge script in python that you can

     download here:

不过,如果你要处理1000个+,这可能是非常乏味的

道岔所以我在python中写了一个合并脚本

在此处下载:

     https://docs.google.com/file/d/0B0VAFIuYmSp5N1dZR21saUxmcG8/edit?pli=1

     The way I run it: I installed python 2.6. I place:

我运行它的方式是:我安装了python 2.6。我放置:

     obj_md6_merge.py

     original_copy.md6mesh

     exported_mesh.obj

     in the same directory.

     ** original_copy.md6mesn should be a copy as it will get clobbered by the

        script.

     Then I right click obj_md6_merge.py from explorer and choose

     "Edit with IDLE" (IDLE editor is installed when you install python).

     This will bring up 2 python windows. One window will show you the source

     code of the file, the other window is an interactive shell prompt.

然后我右键单击obj_md6_merge.py并选择

“使用IDLE编辑”(在安装python时安装了IDLE编辑器)。

这将打开2个python窗口。其中一个窗口将显示源代码

该文件的代码,另一个窗口是一个交互式的shell提示符。

     Within the interactive shell, I type:

在交互式shell中,我输入:

     >>> import obj_md6_merge

     >>> obj_md6_merge.merge("exported_mesh.obj", "original_copy.md6mesh")

     If you named your layers properly, it will match up the sub-meshes

     in the obj file and merge any changed lines with the corresponding

     md6mesh, automatically sapping y/z coordinates and flipping polarity.

     However, it can fail if the sub-mesh names don't match up or if new

     vertices are encountered.

如果您正确地命名了您的图层,那么它将匹配子网格

在obj文件中,并合并任何更改的行与相应的md6网格,

自动缩小y/z坐标和翻转极性。

但是,如果子网格名称不匹配或为新名称,

它可能会失败遇到顶点。

-------------------------------------------------------------------------------

V.3 > > > >  Animationsn. 生气( animation的名词复数 );兴奋;动画片;(指电影、录像、电脑游戏的)动画制作

-------------------------------------------------------------------------------

  1. AnimWebs
  1. 动画网络

  1. What the hell are these things?
  2. 1)这些东西到底是什么东西?

       An animWeb is an object that defines all the "states" that an NPC

       supports as well as the animations associated with those states. An

       animWeb is how the game engine translates the AI state of the NPC with

       how they look within the game.

animWeb是一个定义NPC的所有“状态”的对象

支持以及与这些状态相关联的动画。

一animWeb是游戏引擎如何转换NPC的AI状态

它们在游戏中的样子。

       A typical use case scenario:

       NPC is relaxed and interacting with a device in their hand when an

       enemy shows up. The game engine will go to the animWeb and say:

       I need to go from the current state to state "attack"

一个典型的用例场景:NPC是放松的,

并与他们手中的设备互动时敌人出现了。

游戏引擎会在动画网络上说:

我需要从当前的状态转到状态中的“攻击”

       The animWeb will compute a PATH of states that the NPC can follow

       to go from their current state to the desired state. Furthermore,

       the animWeb knows what animations should play with each state and

       how long the animations should play.

animWeb将计算NPC可以遵循的状态路径

从它们当前的状态转到它们所期望的状态。

此外动画网络知道什么动画应该玩与每个状态和

动画应该播放多久。

       Finally, the engine begins rolling through the states and animations

       by applying them to the NPC.

       In order to go from idle_interact_device to "attack", the

       NPC has to go through states : put_device_away, draw_weapon,

       aim, approach and attack.

最后,引擎开始滚动通过状态和动画

通过将它们应用于NPc。

为了从空闲的交互设备到“攻击”,这个系统

NPC必须通过以下状态:放下设备,提取武器,

目标,接近和攻击。

  1. Structure
  2. 2)结构

       The top of the animWeb has a declaration of all states defined within

       the animWeb. Some of the states are standard/hard coded. However you

       are also free to make your own states. You will then see a declaration

       of subwebs (again, some are hard coded, but you are also free to make

       your own).

动画网络的顶部有一个包含在内部定义的所有状态的声明

动画Web。有些州是标准的/硬编码的。但是你

你也可以自由地建立你自己的州。然后,您将看到一个声明

的子网(同样,有些是硬编码的,但你也可以自由制作

你自己的

       A subweb is a parent state. For example, you may have a subweb for

       pistol animations and a subweb for rifle animations. Most the time

       subwebs will encompass both the weapon and combat aspects of the NPC. So

一个子网是一个父状态。例如,您可能有一个子网

手枪动画设计和一个为步枪动画设计的子网。大部分时间

子网将包括NPC的武器和战斗方面。

       example subweb names:

         hands_relaxed

         hands_searching

         hands_combat

         hands_interacting

         pistol_relaxed

         pistol_searching

         pistol_combat

         pistol_interacting

放松的手

手搜索

手战

手交互作用

放松的手枪

手枪搜索

手枪战斗

手枪相互作用

       Every singe one of these subwebs could have an "idle" state. Thus lower

       in file, your idle state may in fact be defined many times and

       associated with many different animations, 1 for each subweb.

这些子网中的每一个都可能有一个“空闲”状态。从而降低

在文件中,您的空闲状态实际上可以被多次定义和定义

与许多不同的动画相关联,每个子网对应1个。

       The state definition itself includes the animation as well as other

       states that the state can lead into. These are called edges.

状态定义本身也包括动画和其他动画

国家可以导致的状态。这些被称为边。

         subWeb "hands_relaxed" {

           node "idle" {

             ...

             blendTrees {

               tree {

                 anims {

                   alias {

                     name "md6/../idle.md6anim"

                   }

                 }

               }

             }

             edges {

               edge {

                 toState "car_lean_on_hood"

                 toSubWeb "hands_actionScript"

                 ...

               }

             }

           }

         }

       Edges (target states) can be in different subwebs. So for example:

       hands_relaxed could have a state called "to_combat" which targets

       the "idle" state of pistol_relaxed. So if someone was in a hands_relaxed

       subweb state and an external force requested that the NPC be in a state

       that was only defined in pistol_combat, the NPC would automatically

       transition to the other subweb through the to_combat state.

边(目标状态)可以位于不同的子网中。例如:

手放松可以有一个叫做“战斗”的状态

手枪的“闲置”状态放松了。所以如果有人在放松

子网状态和一个外力要求全国人大处于一个状态

这只在手枪战斗中定义,全国人大会自动定义

通过到战斗状态过渡到另一个子网。

       On the other hand, if an external force requested a state that was not

       in the current subweb and there was no way of transitioning to the

       subweb with the state, then the game would simply ignore the request.

另一方面,如果一个外力要求的状态不是

在当前的子网上,没有办法过渡到

那么游戏就会简单地忽略这个请求。

       In ID Studio, when you open up an animWeb, you will see several

       different visualizations of this web. I prefer the Tree View. If you

       click on one of the states, you will see a "Going To" and "Coming From"

       tab in the right most pane which summarizes what leads to the state and

       what the state can lead to.

在ID Studio中,当您打开一个动画Web时,您会看到几个

这个网络的不同可视化。我更喜欢树视图。如果你

点击其中一个州,你会看到一个“去”和“来自”

最右边窗格中的选项卡,它总结了什么导致状态和

国家能导致什么。

       However, most the time I don't use ID Studio's viewer since you can't

       edit animWebs from ID Studio. I normally only bring it up in ID Studio

       to verify that there aren't any mistakes. (When it doesn't render, it is

       normally because I forgot to define the state).  

然而,大多数时候我不使用IDStudio的查看器,

因为你不能从ID Studio中编辑动画web。

我通常只在ID Studio中提到它来验证没有任何错误。

(当它不渲染时,它确实是通常是因为我忘记了定义状态)。

       ** The "Coming From" information is deduced at runtime and is not part

          of the file format.

**“来自”的信息是在运行时推导出来的,而不是一部分的文件格式。

     3) Control

        Animation states are "driven" by one of three sources: Behaviors,

        pcInteractions and scripts.

        I talk about this in more detail below.

动画状态是由三个来源之一“驱动”的:行为,

pc交互和脚本。

我将在下面更详细地讨论这个问题。

  B) Behaviors

     NPCs are defined in:   npc的定义如下:

       decls -> entityDef -> ai

     There are two key properties: 有两个关键属性:

       aiEditable -> behaviors -> decl

       aiConstants -> animation -> animWebs -> animWebs[0]

     The first property points to an aiBehavior, which determines how the

     NPC behaves. For example, what weapons do they prefer (if any)? Do

     they throw grenades? Do they take cover? (It doesnt make sense to take

     cover if your are enraged with no weapon). You describe how the NPC

     fights by answering a lot questions and that in turn causes the

     behavior to generate a bunch of desired states for the NPC at runtime.

第一个属性指向一个ai行为,它决定了如何

NPC行为。例如,他们更喜欢什么武器(如果有的话)?做

他们扔手榴弹?他们有掩护吗?(这并没有意义

如果你没有武器被激怒,就掩护)。你描述了NPC是如何做到的

通过回答很多问题,这反过来导致

在运行时为NPC生成一堆期望状态的行为。

     The states are fed to the animWeb. 这些状态被输入到动画网络中。

     As mentioned above, the animWeb is basically state to animation

     translator. Only it is more advanced than that. It doesn't simply

     translate a state to an animtion, it also includes a sequence of

     animations that should be played before the target state/animation

     to ensure a smooth transition.

如上所述,动画网络基本上是动画的状态

翻译。只是它比这更先进。

这不仅仅是将一个状态转换为一个动画,它还包括一个序列

应该在目标状态/动画之前播放的动画

以确保平稳过渡。

     However, the main point here is that you have no control over what

     states the BehaviorAI requests. Your AnimWeb either has the target

     state or it doesn't. So while there is some freedom in making

     animWebs, most of that freedom is localized to scripted animations.

然而,这里的主要观点是,你无法控制什么

陈述行为人工智能请求。你的AnimWeb要么就有了目标

状态或它没有。所以虽然有一些自由

大部分的自由都是局限于脚本动画。

     BehaviorAI driven states are more or less hard coded.

行为ai驱动的状态或多或少是硬编码的。

     It is not always easy figuring out what the "raw" state requests are

     that come from an AI. One way is to make a custom AnimWeb with no

     subwebs or animations. When you spawn a map with an NPC that is hooked

     up to that animWeb, the console will begin filling with error messages

     revealing the states that the behavior AI is attempting to goto

     unsuccessfully. However, this is limited. For example, the AI

     wont attempt many states unless conditions are right. So you may

     not account for fcover states (for example) because during your

     testing/data gathering, you never fought near cover.

弄清楚“原始”状态请求是什么并不总是容易的

这就来自于一个人工智能。

一种方法是制作一个定制的AnimWeb

子网站或动画。

当你生成一个具有已连接的NPC的映射时

直到那个animWeb,控制台将开始填充错误信息

揭示了人工智能试图采取的行为

不成功地然而,这是有限的。

例如,人工智能

除非条件正确,否则不会尝试很多州。

所以你可以不考虑fcover状态(例如),

因为在您的测试/数据收集,你从来没有在掩护附近战斗过。

     Or you can simply use an existing animWeb/behavior combo and assume

     everything that is needed is there. Unfortunately, it is generally

     not clear what is required for the Behavior AI and what has been

     created to help the animWeb transition between state requests.

      或者你可以简单地使用一个现有的动画web/行为组合,并假设

我们所需要的一切都在那里。不幸的是,它通常是

不清楚行为人工智能需要什么,也不清楚已经需要了什么

创建以帮助animWeb在状态请求之间转换。

     In one file, I found about 460 declared states. Below I listed some

     of them. Chances are, states starting with "to_..." are not actually

     needed by the behaviorAI, but they are setup to help the animWeb make

     smooth transitions between states and subwebs:

在一个文件中,我发现了大约460个已声明的状态。下面我列出了一些

他们的。很有可能,以“to_……”开头的州实际上不是

行为人工智能需要的,但它们是为了帮助动画网络制作

状态和子网之间的平滑过渡:

          idle         to_hands_relaxed

          walk         to_pipe_relaxed

          run          to_pistol_relaxed

          sprint       to_rifle_relaxed

          kick         to_pipe_combat

          throw        to_pistol_combat

          punch        to_rifle_combat

          fall         to_rifle_search

          back         to_pistol_search

          forward      to_pipe_search

          left         hide_into

          right        hide

          aiming       hide_out

          blocked      turn_left

          collapse     turn_right

          to_crouch    pain_head

          to_stand     pain_chest

          to_relaxed   pain_gut

          to_search    pain_left_leg

          to_combat    pain_right_leg

          to_run       pain_right_arm

     ID Studio does not support editing AnimWebs from within

     ID Studio. You can  duplicate webs and change specific animations,

     but you can't add new subwebs, states or fix an animation that is

     pointing to NULL. The last three things require you to edit the

     ".aweb" file directly.

ID Studio不支持从内部编辑animweb

ID工作室。

你可以复制网页和改变特定的动画,

但是你不能添加新的子网,状态或修复一个动画

指向空值。

最后三件事需要你编辑“.aweb”文件直接。

     You might notice that the animweb is defined on the entity under

     "aiConstants".. meaning the animweb can't be changed once the entity is

     spawned. However, the behavior is defined under aiEditable... which means

     it CAN change after the NPC is spawned.

您可能会注意到,动画网络是在下面的实体上定义的

“一个常数”..这意味着一旦实体成立,电子网络就不能改变

大量产然而,该行为是在可编辑的状态下定义的……这意味着

它可以在NPC产生后进行改变。

     However, when you change an NPC's behavior, that will cause the state

     machine to start spitting out different states. If the animweb doesn't

     support the states, the NPC is likely to stand there doing nothing...

然而,当你改变一个NPC的行为时,这将会导致这个状态

机器开始输出不同的状态。如果动画网站没有

支持各州,全国人大很可能会站在那里什么都不做。

     So if I had a ranged enemy that was suppose to change to melee when the

     player got close enough (maybe I flip the behavior using a script), if

     I was pointing to a ranged animweb, chances are the enemy would just

     stand there because his animweb wouldn't support a state/animation

     transition from ranged-weapon to melee-weapon. If you want complex

     enemies capable of adapting/changing their fighting behaviors, you will

     need to make sure you are using a composite animweb that can support

     multiple behaviors. An excellent example is: "ai_bandits_body.aweb"

所以如果我有一个远程敌人,它应该变成近战时

玩家走得足够近(也许我用脚本翻转行为),如果

我指着一个远程动画网络,很有可能敌人会只是

站在那里,因为他的动画网络不支持一个状态/动画

从远程武器到近战武器的过渡。

如果你想要复杂的

能够适应/改变他们的战斗行为的敌人,

你一定会改变的

需要确保你使用的是一个复合动画网络,可以支持

多种行为。

一个很好的例子是:“ai_bandits_body.aweb”

     Death Animations: aiBehaviors have a property that marks the NPC

     as supporting Death Animations or not. If the NPC does not support

     death animations, they will go strait to ragdoll. This may be preferred

     for custom NPC models. Odd that they put the property on the aiBehavior

     and not the entityDef.

死亡动画:ai行为者有一个标记NPC的属性

作为死亡动画的支持。如果NPC不支持

死亡动画,他们会变成布娃娃。这可能是首选

用于自定义NPC模型。奇怪的是,他们把财产放在行为

而不是entyDef。

  C) Scripts

     So you have an AI driven NPC and you want them to strike a pose.

所以你有一个人工智能驱动的NPC,你想让他们摆个姿势。

     You can use scripts to tell the NPC to go to any subweb/state you

     want. Granted, you will need to define a custom state that is

     associated with the animation. And you probably also want to

     define at least 1 transition edge state so that your custom state

     can return to the idle of one of the existing subwebs. Otherwise,

     your NPC will not be able to stop the assigned animation.

您可以使用脚本告诉NPC转到任何子网/状态您

需要当然,您将需要定义一个自定义状态,即为

与动画相关联。你可能也想做

定义至少1个过渡边缘状态,以便实现自定义状态

可以返回到现有子网之一的空闲状态。否则,

您的NPC将无法停止指定的动画。

     That is assuming you want the NPC to continue working. You might

     also create a state/animation that doesn't link to any other

     states so that when you put them into that state, they essentially

     become stuck until a script moves them out.

前提是你希望NPC继续工作。你可能会

也可以创建一个不链接到任何其他状态的状态/动画

所以当你把它们放到那个状态时,它们本质上是

陷入困境,直到一个剧本把他们移出去。

     So while we are here, lets talk about some of the script commands

     and the differences between them:

当我们在这里,让我们谈谈一些脚本命令

以及它们之间的区别:

     

npc.action_ChangeAnimState(AIANIMWEB_BODY,"ai/some/animweb/hands_relaxed/idle", AIANIMWAIT_DONT_WAIT);

     The ChangeAnimState command is the graceful state change command.

     It will do what the game always does: politely request a new

     desired state and transition to it. However, this command can fail

     if there is no way to path from the current state to the desired

     state. If the behavior AI requests a desired state during the

     transition, your request may also be interrupted.

更改动画状态命令是一个优雅的状态更改命令。

它会做游戏总是做的事情:礼貌地请求一个新的

期望的状态并转换到它。但是,此命令可能会失败

如果没有办法从当前状态路径到所需的路径

状态如果行为AI请求一个所需的状态在

过渡时,您的请求也可能会被中断。

       npc.action_ForceAnimState( AIANIMWEB_BODY, "ai/some/animweb/subweb/state", 0, AIANIMWAIT_WAIT_FOR_DEST_TO_START_BLEND );

     This version is the not-so-graceful version. It causes the NPC to

     immediatly blend to the target state from their current state.

     The animWeb is not consulted for a graceful set of transition

     animations, however the target state and subweb must still exist

     on the animweb assigned to the NPC.

这个版本已经是不那么优雅的版本了。它导致NPC

立即从其当前状态混合到目标状态。

动画网络不会被咨询为一组优雅的过渡

然而,目标状态和子网必须仍然存在

在分配给NPC的动画网络上。

     The third parameter to ForceAnimState is the amount of time in ms

     you want the NPC's current animation to "blend" into the target

     animation.

A value of 0 means there will be no blend.

The transition   will happen immediatly is a "snap" like fashion. A value of 3000,

     would cause a more graceful blend from the NPC's current animation

     to the target animation over the coard of 3 seconds.

第三个参数是毫秒的时间  您希望NPC的当前动画能够“混合”到目标动画中

动画片值为0表示将没有混合。

过渡会立即发生的是一种“瞬间”的时尚。

值为3000,会导致NPC当前动画更优雅的混合到目标动画超过3秒的时间。

     The last parameter on these action_ commands indicates when the

     action_ command should return:

这些操作_命令上的最后一个参数 指示 何时 action_ command  应返回:

        AIANIMWAIT_DONT_WAIT

     This causes the call to be asynchronous. The action fires and whatever

     line is after the action takes place immediatly.

这将导致调用是异步的。动作着火之类的 线是动作发生后立即发生的。

        AIANIMWAIT_WAIT_FOR_DEST_TO_START_BLEND

     This will wait until the blend has completed and the target

     state/animation is running before it returns.

        AIANIMWAIT_WAIT_FOR_DEST_TO_FINISH_BLEND

     This will wait until the target state/animation has completed before

     returning. Note that some states are marked as repeating, so using this

     with repeating state is a bad idea as it means it will never return.

这将等到目标状态/动画完成之前完成

返回请注意,一些状态被标记为重复,因此使用这个

重复状态是一个坏主意,因为它意味着它永远不会回来。

        action_LoopAnim(string animWebNode, int milliseconds);

     action_LoopAnim - If milliseconds is 0, it starts a looping/repeating

     animation and returns immediately. If milliseconds is non-zero, it plays

     the repeating animation for a period of time and then returns.

action_LoopAnim -如果毫秒为0,则开始循环/重复

动画并立即返回。如果毫秒非零,则会播放

重复的动画将持续一段时间,然后返回。

        action_LoopAnimExitAtEnd(string animWebNode, int milliseconds, int framesFromEnd)

     Same as LoopAnim, but stops the animation after a certain number of

     seconds or frames. I am actually not cerain if this one returns immediatly

     or waits until the animation is done.  

与LoopAnim相同,但在一定数量后停止动画秒或帧。

如果这个立即回来,我真的不肯定或者一直等待,直到动画完成为止。

     In most of these commands we have the animWebNode parameter. This is

     where your state and subweb naming freedom comes into play. In fact, there

     may be states that you ONLY want accessible from scripts. You may place

     them in a subweb like:

在大多数这些命令中,我们都有 animWebNode 参数。

这是在哪里,你的状态和子网命名自由开始发挥作用。

事实上,那里可能是您只希望从脚本中获得可访问的状态。

你可以放置他们在一个子网上,比如:

        pistol_awesomeStuff

     IMPORTANT NOTE: AI and scripts dont mix very well. If the AI is sending a

     state change request at the same time a script command arrives to change

     the animation,  generally the AI breaks and the NPC ends up just stuck in

     the animation. Punching or damaging the NPC will normally wake the AI up,

     but that is a bad solution.

重要的注意:人工智能和脚本不能很好地混合。

如果人工智能正在发送一个状态更改请求的同时,

脚本命令到达进行更改动画,通常AI中断,NPC最终就 卡住了 动画。

击打或 破坏 NPC 通常会 唤醒 人工智能, 但这是一个不好的解决方案。

     The robust solution checks that the NPC is working and if they break,

     respawn a clone of the NPC (in the original NPC's position) which would

     not have been affected by the action scripts. (Thus fixing the stuck AI  issue).

这个健壮的解决方案会检查NPC是否在工作,以及它们是否失效,

重生一个克隆的NPC(在最初的NPC的位置),这将会未受到操作脚本的影响。

(从而修复了被卡住的人工智能问题

  D) Interactions   交互作用 /交流

     "Interactions" are defined under:

  

        decls -> aiInteraction

        decls -> aiPlayerInteraction

D)交互

“交互作用”的定义如下:

decls -> aiInteraction

decls -> aiPlayerInteraction

     Interactions are normally invoked through job declarations:  交互通常通过 job 声明 来 调用:

        decls -> jobs

     But can also be defined on the entityDef   但是也可以在entityDef上定义

        decls -> entityDef -> ai -> npc -> aiEditable -> interactions

交互通常通过作业声明来调用:

decls ->工作

但也可以在整个def上进行定义

decls ->完整的Def->>->npc->可编辑->交互

     Interactions affect the NPC model and can point directly to an

     animation alias defined on the MD6 without needing an AnimWeb or

     state translation.

交互作用会影响NPC模型,并可以直接指向一个动画别名定义的,

不需要AnimWeb或状态翻译。

  E) MD6Def Animation Aliases      MD6Def 动画别名

     

     Lets take a look at some of the animation aliases. Open up:

让我们来看看一些动画别名,打开:

       decls -> md6Def -> bandits -> Ghost -> pipe.md6

     FYI: "MD6" is in fact defined by the file:

       <Rage Tool Kit>/base/decls/md6def/bandits_ghosts_pipe.md6def

E) MD6Def动画别名

让我们来看看一些动画的别名。

打开:

decls -> md6Def ->强盗-> Ghost -> pipe.md6

供您参考:“MD6”实际上是由以下文件定义的:

<《狂怒》工具包 >/base/decls/md6def/bandits_ghosts_pipe.md6def

     The format is a bit confusing. Personally, I think it is done backwards.

这个格式有点令人困惑。我个人认为这是反向做的。

     At the bottom of the .md6def is a block called "aliases".

在.md6def的底部是一个被称为“别名”的块。

     The aliases define the name that you see in IDStudio and associate it

     with a .md6anim file. This is pretty strait forward.

这些别名定义了您在IDStudio中看到的名称,并将其关联起来

使用.md6anim文件。这是相当狭窄的前进。

     Then there is a block called "events" above aliases. Events allows you

     to associate a timeline of events to fire when a specfic .md6anim file

     plays. Why would you do this?

然后在别名上面有一个被称为“事件”的块。

事件允许您当一个指定的.md6anim文件时,将事件的时间轴关联到触发演奏

你为什么要这样做?

     This is an override system for NPCs that use the same animations. For

     example, crossbows and shotguns both use the RIFLE_ animation subwebs

     and they both rely on the "Shoot" event animation to fire the weapon.

这是一个针对使用 相同动画的npc的覆盖系统。

例如,弩 和 散弹枪 都使用RIFLE_动画子网,他们都依靠“射击”事件动画来发射武器。

     But it looks very different when someone shoots a shotgun and a crossbow.

     So the NPCs likely both have their own .md6 with local overrides so that

     the shoot aliases maps to different animations when they fire.

但当有人射击猎枪和弩时,情况看起来就完全不同了。

所以npc可能都有自己的.md6和本地覆盖,当它们射击时,射击的别名会映射到不同的动画。

     The MD6 is also where you hook up AI hints to the game engine.

MD6也是 你将AI 提示 连接到 游戏引擎 的地方。

Thegame engine has no idea what is going on in an animation.

     If someoneis throwing a punch,

这个游戏引擎 并不知道在 动画中发生了什么。

the game engine doesn't know when the punch should

     land and do damage.

如果有人是 投拳,游戏引擎不知道什么时候应该投拳

So the timeline on the animation Aliases is where you

     can define AI hints to the game engine to say "Here is where the foot

     hits the ground, so play the footstep noise" or "Here is where the

     bullet should leave the gun, so activate the attachment" or "Here

     is where the NPC is dead, so activate rag-doll".

土地和破坏。所以动画中别名上的时间轴就是你的位置

可以定义A智能提示游戏引擎说“这是脚击中地面,所以播放脚步声噪音”或“这里是哪里

子弹应该离开枪,所以激活附件”或“在这里”是NPC 终结 的地方,所以激活布娃娃”。

     what else can you do? Change where the head turns (What the NPC is looking  at)

or disable animations regarding certain body parts at specific frames

     in the animation (like facial expressions, or an entire leg). You can even

     fire global and object specific script functions.

     你还能做什么呢?改变头部转动的地方(NPC在看什么)

或在特定的帧中禁用关于特定的身体部位的动画在动画中(如面部表情,或一整条腿)。

你甚至可以触发全局特定的和对象特定的脚本函数。

     Within ID Studio, you should see a list of animations for our Pipe ghost

     bandit in the right pane.

在ID Studio中,你应该会看到我们的管道 ghost 的动画列表  右窗格中的 ghost。

       - Grey animations are inherited from a parent class.

-灰色的 动画 是 继承 自一个 父类 的。

       - Black animations are locally defined OR override a parent animation.

-黑色动画是本地定义的,或覆盖一个父动画。

       - Red animations are aliases that point to a missing file.

-红色的动画是指向一个缺失的文件的别名。

     Clicking on an animation brings up the animation viewer. At the bottom

     of the screen is a timeline (width is number of frames) and within you

     can see any events defined to fire at certain frames. You can also right

     click within the timeline to add new events.

单击一个动画,将弹出动画查看器。在底部屏幕的一部分是一个时间轴(宽度是帧数)

和在你的内部可以看到任何定义为在特定帧上触发的事件。

你也可以正确 在 时间轴内 单击 以添加 新的 事件。

     Facial animations such as blinking and viseme_A (What the face looks like

     when a spoken word contains an "a")

get used by the lipsynch system if the NPC is involved in VO tracks or spoken interactions.

Otherwise, most  the animations are not used unless explicitly hooked up to an interaction.

面部动画,如眨眼和viseme_A(脸是什么样子的,当一个口语包含一个“a”)

如果NPC参与到VO音轨或语音交互中,可以使用lipsynch系统。

否则,大多数 除非显式地连接到交互中,否则不会使用这些动画。

  F) Props and Weapons 道具和武器

     On an Enities MD6 file (decls -> MD6 -> ...) you will find a list of

     attachments. The reason  you define an attachment on the MD6 is so that

     the engine knows where and how to connect the attachment to the NPC. This

     is important because, without that information, the default location is

     the NPC's origin (center). So small props like pistols may not show up

     on an npc in game if you do not define how to attach the MD6 model that

     the pistol uses to the NPC.

在一个Enities MD6文件(decls->MD6->…)上,你会发现一个列表

附件。您在MD6上定义一个附件的原因是这样的

发动机知道在哪里以及如何将附件连接到NPC。这个

很重要,因为如果没有这些信息,默认位置是

全国人大的起源(中心)。所以像手枪这样的小道具可能不会出现

如果你没有定义如何附加MD6模型

手枪用于全国人大。

     I ran into this issue when I tried to make my custom NPC use new

     weapons. At firwst I thought it wasnt' working... until I attached a

     large weapon and saw that it was being connected incorrectly.

当我试图让我的自定义NPC使用新的功能时,我遇到了这个问题

武器首先,我以为它行不通……直到我附加了一个

大武器,看到它的连接不正确。

     So in essence, to get an NPC to use a prop or weapon you MUST define

     an attachment on the MD6 for the NPC that tells the game engine

     what joint and offset to connect the attachment to. Luckily, ID

     studio supports this in game and include a list of joints when you

     right click the Attachment list on the MD6 viewer in game and select

     "Add New Attachement".

所以从本质上说,要让NPC使用道具或武器,你必须定义

NPCMD6上的附件,告诉游戏引擎连接到的接头和偏移量。

幸运的是,ID工作室支持这在游戏中,并包括一个关节列表时,

当你右键单击游戏中的MD6查看器上的附件列表并选择

“添加新的附件”。

===============================================================================

VI. > > > > Adding Textures 添加纹理

===============================================================================

-------------------------------------------------------------------------------

VI.1 > > > >  Simple Textures简单的纹理

  Lets suppose you are making a new inventory item and you want to add your

  own icon for how it appears in the players inventory.

让我们假设您正在制作一个新的库存项目,并且您想要添加您的

自己的图标,它如何出现在玩家库存。

  A) Notes:

     1)  Most textures are 24 bit, however textures which support translucent

         zones and invisibility (such as icons), are 32 bit. Icons are

         typically 64 pixels x 64 pixels.

     2)  Avoid the use of spaces and underscores in your file name.

  1. 注意事项:

1)大多数纹理都是24位的,但是这些纹理都是支持半透明的

区域和不可见性(如图标),是32位。

图标为

通常是64像素x 64像素。

  1. 避免在文件名中使用空格和下划线。

  B) Example:

     1) After you create your icon, place it under:

        <Rage Tool Kit>\base\textures\yourmod

B)示例:

1)创建图标后,将其放于:

<愤怒的工具包>\base\纹理\你的mod

     2) Start up rage tool kit

        Go to the Media browser -> textures -> yourmod

        you should see your file.

2)启动愤怒工具包

进入媒体浏览器->纹理->你的mod

你应该看到你的文件。

  1. Right click the files and select "Generate Material" 右键单击这些文件并选择“生成材质”

        ** Note, this will create the file name:

           <Rage Tool Kit>\base\decls\m2\generated.m2

**注意,这将创建文件名:

<《狂怒》工具包>\base\decls\m2\generated.m2

           you can rename this file to reflect your mod name once you

           are finished importing the textures.

您可以重命名此文件,以反映您的mod名称,一旦您已 完成 了 导入 纹理。

     4) Fix the declarations: 修复声明:

        ID Tech 5 uses a default texture declaration that is normally

        not quite right. What you need to do is take a look at other

        texture meta-data wrappers that are used in the same manner as

        your texture and copy their settings.

ID Tech 5使用了一个正常的默认纹理声明 ,不完全正确,

你需要做的是看看其他的纹理元数据包装器,其使用方式与你的纹理 和 复制 他们的设置。

        In this case, since we are making a gui icon for the hud, I note

        that there is already some hud textures. For example:

在这种情况下,由于我们正在为hud制作一个gui图标,

我注意到已经有一些hud纹理了。例如:

        Media Browser -> decls -> material -> hud -> info_window

媒体浏览器-> decls ->材料->hud->info_窗口

        So, we click on info_window, Right click -> Edit Text

        Then we browse to

        Media Browser -> decls -> material -> textures -> yourmod

        Right click your texture and click EDIT

所以,我们点击info_窗口,右键点击->编辑文本

然后我们浏览到

媒体浏览器-> decls ->材料->纹理->你的mod

右键单击纹理并单击“编辑”

        ** Important: If you plan on saving changes, you EDIT and

           not EDIT TEXT. The FIle menu in EDIT TEXT tends to lock

           up and crash the game if you ever attemtp to save from

           that window.

**重要提示:如果您计划保存更改,那么请编辑和而不是经过编辑的文本。

编辑文本中的文件菜单 倾向 于锁定 如果 你曾经试图 从 那个窗口。

        Re-declare your texture in the same manner as the hud:

以与hud相同的方式重新声明你的纹理:

        {

            stageProgram  guiBlend

            transMap      textures/yourmod/somefilename.tga

        }

     5) Hook it up.  介绍一下

        For this simple example, we will duplicate an existing item and

        add the icon to it.

对于 这个 简单 的 示例,我们将复制一个 现有的 项 和 添加图标

        Media Browser -> decls -> inventoryItem -> deployable

        Right click "sentrybot" and select "duplicate".

        place it under "yourmod/awesome_sentry"

媒体浏览器-> decls ->库存项目->可部署

右键点击“哨兵蜘蛛”,然后选择“复制”。

把它放在“你的超级哨兵”下面

        Open up your new awesome_sentry. Click on the icon Property

        field and browse to your new icon.

        To test in game: open console and type "give yourmod/awesome_sentry".

        You should see your icon.   

打开你 awesome_sentry. 。单击图标属性

进入字段,并浏览到您的新图标。

在游戏中进行测试:打开控制台,输入give yourmod/awesome_sentry

(“give yourmod/ 可怕的哨兵”。)

你应该看到你的图标。

-------------------------------------------------------------------------------

VI.2 > > > >  Textures for models模型的纹理

-------------------------------------------------------------------------------

  A) Notes:  备注 /注释 /注意事项 /说明

     1) Most model support textures have multiple components. The tool kit

        recognizes/expects specular maps to end with _s.tga, height maps

        to end with _h.tga, normal maps to end with _local.tga and diffuse

        maps to not have any underscores.

  1. 注意事项:
  2. 大多数模型支持纹理都有多个组件。
  3. 工具包识别/期望镜面地图以_s.tga结尾,
  4. 以高度地图结束以_h.tga结束,
  5. 法线映射以_local.tga和漫反射结束地图上没有任何下划线。

     2) If you use proper naming conventions:

        base.tga, base_h.tga, base_s.tga, base_local.tga

        When you import base.tga, Rage will automatically import all relevant

        files. This saves a lot of time and energy.

2)如果您使用正确的命名约定:

base. tga,base_h.tga,base_s.tga,base_local.tga

当您导入base.tga时,Rage将自动导入所有相关的 文件夹 这节省了大量的时间和精力。

  B) Example:B)示例:

     1) Placed/save your textures under:

        <Rage Tool Kit>\base\models\yourmod

1)放置/保存您的纹理下:

<愤怒的工具包>\base\模型\你的mod

     2) Start up Rage tool kit, open the media browser and browse to your new

        files(s).

2)启动愤怒工具包,打开媒体浏览器,浏览到您的新产品

文件(s)。

     3) Right click the BASE files (ie the ones without underscores) and select

        "Generate Material". If you have proper underscores in place, Rage

        will import all relevant files at the same time.

3)右键单击BASE文件(即没有下划线的文件)并选择

“生成材料”。如果你有适当的下划线,愤怒

将同时导入所有相关的文件。

        ** Note, this will create the file name:  // **注意,这将创建文件名:

           <Rage Tool Kit>\base\decls\m2\generated.m2

           you can rename this file to reflect your mod name once you

           are finished importing the textures.

您可以重命名此文件,以反映您的mod名称,一旦您

已完成了导入纹理。

     4) Fix the declarations:

        Browse to:  decls -> materials -> models -> yourmod

4)修复声明:

浏览到: decls ->材料->模型->你的mod

        And use EDIT TEXT to look at other textures for an idea of how your

        texture should be setup. For example, if you edited the skins of an

        NPC, then looking at the original skin definition is probably the best

        example you are going to find.

 并使用编辑文本来查看其他纹理来了解你的

纹理应该设置。例如,如果您编辑了一个

NPC,那么看看最初的皮肤定义可能是最好的

你将会找到的例子。

        When you find something similar, browse to your texture and select

        EDIT

当你找到类似的东西时,浏览到你的纹理并进行选择

剪辑

        ** This is important. Do NOT use Edit Text when actually updating a

           texture or it tends to corrupt things. Always always always use

           "Edit" when you are actually going to change text and save it.

**这很重要。在实际更新编辑文本时,不要使用编辑文本

纹理,或者它往往会破坏东西。总是总是使用

“编辑”,当你实际上要改变文本并保存它。

        For example, I wanted to import a new shirt for ginny, so I looked at

        the original shirt definition located under:

例如,我想为金妮进口一件新衬衫,所以我看了看

原始衬衫定义位于:

        decls -> material -> models -> characters -> settlers

              -> wellspring -> females -> shortsleeve_ginny

decls ->材料->模型->字符->定居者

->泉->女性-> shortsleeve_ginny

        Selected "Edit Text" on the original so I could see it in the

        background.

      选择了“编辑文本”上的原始,

这样我就可以看到它在背景

        Then i went to my new texture and selected "EDIT". Copied the

        original content to my new texture decl:

  然后我去看了我的新纹理,并选择了“编辑”。

已复制的原始内容到我的新纹理decl:

        {

            renderbump      "-size 2048 2048 - trace .02 models/char...."

            specularmap     models/characters/settlers/wellspring/fem...

            bumpmap         addnormals( models/characters/settlers... )

            diffusemap      models/characters/settlers/wellspring/fem...

            ambientProgram  characterVmtr

        }

        Then replaced the important bits. Personally I even left tabs in place

        in case the compiler is picky.

然后替换掉重要的部分。就我个人而言,我甚至把标签留在原地 以防编译器挑剔。

   5) You can now safely use the textures within your mod and they will be

      deployed when you build it.

你现在可以安全地在你的mod中使用纹理,它们将是在构建时部署。

  C) SPECIAL DEPLOYMENT NOTES:  特别部署注意事项:

     You might find that your imported textures work fine when you are play

     testing in ID Studio's engine tab using devmap mode, however when you

     export your mod to Rage, your texture dont seem to make it.

当你在玩的时候,你可能会发现你导入的纹理工作得很好


在ID Studio的引擎选项卡中使用devmap模式进行测试导出你的mod到Rage,

你的纹理似乎不使它。

     As of Sept 2013 (Rage.1700.354669), Rage (the game) has a bug where

     it does not load the "_vmtr_dlc.pages" file that is placed in mods

     virtual textures directory.

截至2013年9月(Rage.1700.354669), Rage(游戏)有一个bug它不加载“_vmtr_dlc”。

Pages”文件放置在mods中 虚拟纹理目录。

     A temporary fix/hack is to create a 7-zip installer that places

     the _vmtr_dlc.pages file into the virtual textures directory

     of either dlc1 or dlc2, 2 DLCs that pretty much every user has

     that dont use virtual textures.

一个临时修复/hack是创建一个7-zip的安装程序


_vmtr_dlc。

将Pages文件放入虚拟纹理目录不管是dlc1还是dlc2,几乎每个用户都拥有两个dlc

不使用虚拟纹理。

     IE, 7-zip would be extracted to the RAGE directory and it would

         include the paths:

         在IE中,7-zip将被提取到RAGE目录,它将包括路径:

         mods/yourmod/info.txt

         mods/yourmod/base/english.streamed

         mods/yourmod/base/streamed.resources

         mods/yourmod/base/gameresources.resources

         mods/yourmod/virtual textures/somemap.pages   <- if you have a map

         dlc/dlc1/virtual textures/_vmtr_dlc.pages     <- hack

     One problem with this hack is that it limits how many mods a user can

     have installed. At least mods that require virtual textures.

     So I would also recommend creating a separate installer that places your  _vmtr_dlc.pages under dlc2 instead of dlc1.

因此,我还建议创建一个单独的安装程序来放置您的_vmtr_dlc.pages ,dlc2而不是dlc1下的页面。

Then on your download page 然后在你的下载页面

     offer 2 downloads with instructions that tell users to try the other one

     if the first one doesn't work when trying to install multiple mods.


提供两种下载,并告诉用户尝试另一种

如果第一个不工作时,试图 安装 多个 mod。

     Hopefully Rage will eventually release a patch that fixes this problem.

-------------------------------------------------------------------------------

VI.3 > > > >  Splash screens for Maps

-------------------------------------------------------------------------------

  So you make a map and you want to know how to make a splash screen for it

  that appears while the user is waiting for it to load.

你制作了一张地图,你想知道如何为 它 制作 启动画面   在用户等待它加载时出现。

  Locate: //  定位 /查找 /位于 / 找出

    base\swf\loading

  swf is a shockwave flash format.  You will notice several swf and fla files

  exist that support existing maps. As it turns out, the compiler is smart

  enough to look in the directory above for a swf/fla file named after your map.

SWF是一种 shockwave flash 格式。您将注意到几个swf和fla 文件 存在,支持现有的地图。

编译器 很聪明 在上面的目录 中 查找 以您的地图 命名的swf/fla文件 就足够了。

  So to make a splash, copy a pair of existing swf/fla files and then

  rename the copies so that they match your own maps name.

因 此,为了 引起 轰动,复制一对 现有 的 swf/fla 文件,然后 重命名 副本,

使其 与 您 自己 的 地图名称 匹配。

===============================================================================

VII. > > > > Adding Sounds and Audio 添加声音和音频

===============================================================================

  A) Create the sound directory:

A) 创建声音目录:

     Sounds should be placed in the directory:

声音应该放在目录中:

       <rage tool kit>/base/sound/...

     Go ahead and create that directory now.  现在继续创建该目录。

     Next, you need to follow the games original conventions. These

     conventions are derived by looking at some of the existing sound

     definitions defined in:

接下来,你需要遵循 游戏 的 原始约定。

这些 惯例是通过观察一些现有的声音衍生出来的 定义定义于:

       <rage tool kit>\base\decls\sound\vo.sndshd

     So for example, if we are creating new Voice Tracks (VO), then we would

     need to use the directory structure:

举个例子,如果 我们 正在 创建 新的 声音轨迹(VO),那么我们会 需要使用目录结构:

       <rage tool kit>\base\sound\vo\english\ai\yourmod\npc\yourfile.wav

     While Rage does support Ogg Vorbis, the encoding that you use doesn't

     really matter as the file will be converted to a Rage format for

     distribution anyway.

虽然《Rage》确实支持Ogg Vorbis,但你所使用的编码却不支持真的很重要,

因为文件将被转换为Rage格式  无论如何分布。

     Speaking of which, in order for ID studio to play a sound, it has to be

     compressed by ID Studio into .msadpcm format.

说到这里,为了让id studio播放声音,它必须是 由id Studio压缩成 .msadpcm 格式。

     ID Studio will automatically convert your wav files to that format under

     the base/compressed/... directory, but not until it builds your mod for

     distribution and even then, not unless the audio file appears within

     your compile requirements dependency tree. (Discussed in the build

     section below).

ID Studio会自动将你的wav文件转换为下面的格式 base/compressed/...  目录,

但直到它构建您的mod分发和甚至然后,除非音频文件出现在里面

您的编译需求依赖树。(在构建中讨论章节)。

     So this presents a little bit of a dilemma. Either you blindly trust that

     the audio will be compressed when you are done, or... you compress it yourself.

这就出现了一个两难的问题。要么你盲目地相信 完成后音频将被压缩,或者…你自己压缩它

  B) Once the wav files are in place, you need to define a sound shader for  the various sounds.

 一旦wav文件就位,你需要为各种声音定义一个声音着色器。

     The master voice sound shader definition file is:

 主声音着色器 定义文件 是:

       <rage tool kit>\base\decls\sound\vo.sndshd

     This single (enormous) file declares the vast majority of raw voice

     resources in the game. If you open the file up, the main thing you will

     notice is that each "sound" declaration maps to exactly 1 wav file.

这个单一的(巨大的)文件 声明了   绝大多数  原始 声音  游戏中的资源。

如果你打开文件,最主要的是 请注意,每个“声音”声明都映射到1个wav文件。

     We could edit this file, but we want to avoid that to help minimize mod

     conflicts with other mods or DLC.

我们可以编辑这个文件,但我们希望避免这样做,以帮助最小化mod


与其他模组或DLC冲突。

So the second step is making our own master vo file for our mod.

所以第二步是为我们的mod制作我们自己的主vo文件。 

       <rage tool kit>\base\decls\sound\vo_yourmod.sndshd

       sound vo/english/yourmod/somenpc/line1 {

           edit = {

               parms = {

                   minDistance = 256;

                   maxDistance = 512;

                   groups = "SSG_VO";

                   falloff = "sound/falloffs/vo";

               }

               soundFiles = {

                   num = 1;

                   item[0] = "sound/vo/english/yourmod/line1.wav";

               }

           }

       }

     If you are also creating a combat ai set (grunts, hits, etc..), you want

     to make a separate file for that:

       <rage tool kit>\base\decls\sound\vo_ai_npc.sndshd

     Open up ID Studio. You should now see your VO tracks under:

       MEDIA_B -> decls -> sound -> vo -> english -> yourmod

  C) Creating a Voice Over and Voice Track definition

     Creating a sound wrapper is only the first step if you are creating NPC

     voice acting. You also need a voice-track wrapper which associates the

     audio with lip sync information and body animation and a voice over group,

     which acts as a vocal category.  

     1) Right click on: MEDIA_B -> decls -> voiceover -> ai

        ** or select your mod name if you have done this before

        Select: create new VO from sndshd

        Click on [snd] button and browse to one of your audio files.

     2) After you select import, open up: MEDIA_B -> decls -> voiceover -> ai

        You should see your file. You likely want to move it to a folder

        based on your mod. Right click the file and select rename:

          yourmod\filename        

        A new folder will appear under voiceovers for your mod.

     3) When you imported the sound, it also created a .vtr file under:

          <rage tool kit>\base\voicetrack\english\ai\thefilename.vtr

        You will likely want to move this to a mod specific location:

          <rage tool kit>\base\voicetrack\english\yourmod\thefilename.vtr

     4) VoiceOvers are groups of Voice Tracks. For exampe, we might create a  

        voice over for "pain", which maps to 1 of 5 different voice tracks. You

        generally need a voice over group for each voice track, even if the

        group only has 1 track. Voice Overs are tracked by the file:

          <rage tool kit>\base\decls\voiceover\english.vo

        If you diff the file, you will see the change at the bottom, which is

        surprisingly incorrect:

          voiceover compmod/line1 {

              edit = {

                  tracks = {

                      num = 1;

                      item[0] = "theFilename";

                  }

              }

          }

        Notice how all the other entriesin the english.vo file have the full

        path to the VTR, yet the import function did not include the path or

        the .vtr extension. We need to fix this. But first... this is a good

        time to break out changes to our own mod-specific vo file. So create

        the file:

          <rage tool kit>\base\decls\voiceover\english_yourmod.vo

        Copy the incorrect line from the bottom of the english.vo to the top

        of your new file and correct the path:

          voiceover compmod/line1 {

              edit = {

                  tracks = {

                      num = 1;

                      item[0] = "voicetrack/english/ai/theFileName.vtr";

                  }

              }

          }

     

        Revert english.vo back to it's non-changed state. Finally, you probably

        want to move the .vtr to a location that reflects your mod. So you

        will want to create the directory:

          <rage tool kit>\base\voicetrack\english\yourmod\

        then move the vtr to it:

          <rage tool kit>\base\voicetrack\english\yourmod\thefilename.vtr

        and finally update your english_yourmod.vo file:

          voiceover compmod/line1 {

              edit = {

                  tracks = {

                      num = 1;

                      item[0] = "voicetrack/english/yourmod/theFileName.vtr";

                  }

              }

          }

  D) Compressing yourself

     Right now if you try to play your sounds within ID Studio, you will hear a

     beep noise, which is irritating.

     The truth is, I am not certain why or when ID Studio decides to compress

     your raw audio files into ms adpcm. However, you can do it yourself if you

     have no patience.

     I udrf Magic Audio Converter from:

        http://www.magic-video-software.com/magic_audio_converter/index.html

     With the full feature set enabled, you can convert wav files to ms adpcm.

     The output will also be named ".wav", but you can rename it to ID Studios

     convention.

     Place your compressed files into:

       <rage tool kit>\base\compressed\sound\vo\english\yourmod

     (Same path convention you used when defining the sounds).

     Restart ID Studio, and now when you click on the files you will hear them

     play.

  E) Close Captioning

     1) Add strings that encompass what is said. (See the section on strings)

     2)  Go to:

          decls => voiceover => yourmod => yourfile

        When you dble click a line to open it, it will ask you if you want to

        open the voice over browser. Select "Yes"

        Look for the pane "Voice tracks for Selected Voice Over". Double click

        the vtr for the voice track and a Voice Track Editor will appear.

        use slowal for the viseme set and select your string. Also make sure it

        points to the correct line. (sometimes it doesn't).

        Save.

   F) Lip Sync

      Go to:

          decls => voiceover => yourmod => yourfile

      When you dble click a line to open it, it will ask you if you want to

      open the voice over browser. Select "Yes"

      Look for the pane "Voice tracks for Selected Voice Over". There is a

      button in the pane that when you hover over it says "click to generate

      the lip sync data for the voice track"

     At the moment, clicking this button results in an error as ID Studio does

     not include the VO generation utilities.

     Lip Sync Kludging:

       Sometimes, something is better than nothing. If you open up an

       existing VTR file, you will notice lip-sync data with timing

       info. One option is to drag lip animation from another

       file that is as long or longer than your file and trim it so

       that the events stop within your audio files length.

有时候,有总比没有好。如果你打开了一个

现有的VTR文件,您会注意到对口型数据与时间

信息。一种选择是从另一个选项中拖动唇形动画

比你的文件一样长或更长的文件,并修剪它这样

这些事件停止在你的音频文件长度范围内。

       Personally, I would rather have the mouth moving, even if it is

       not saying the right words, then to have no mouth movement.

       This requires editing the VTR file using a text editor. This also

       allows you to steam body and facial animation examples from other

       existing VTR files, even if ID Studio hasn't implemented the

       feature.

就我个人而言,我宁愿动嘴,即使它是

不说正确的话,然后就没有嘴动了。

这就需要使用文本编辑器来编辑VTR文件。这也

允许您从蒸汽的身体和面部动画的例子从其他

现有的VTR文件,即使ID Studio还没有实现

特征

    ** I will likely create a python script that can auto-generate the VTR

     lip data in the near future. Keep an eye on the resources section

     of the Rage Companion Mod website.

**我可能会创建一个可以自动生成VTR的python脚本

嘴唇数据将在不久的将来公布。请密切关注资源部分

愤怒的同伴国防部的网站。

===============================================================================

VIII. > > > > NPCs

===============================================================================

-------------------------------------------------------------------------------

VIII.1 > > > >  Followers

-------------------------------------------------------------------------------

  So why does the sentry bot follow the player, but not other NPCs?

  As far as I can tell, it has to do with relationships.

  Relationships can be defined directly on an NPC's entityDef, or the NPC

  can be assigned to a faction which indicates how the NPC feels about

  several other groups.

  Lets take a look an an NPC that is already configured to follow you:

    decls -> entityDef -> ai -> sentybot -> sentrybot_buddy.

  You may notice there is also a non-buddy version of the sentry bot. If you

  compare the enemy and ally version, you will notice the main difference is

  the faction:

    Properties -> faction -> myFaction -> "faction/player_sentrybot"

  The player_sentrybot faction has the entity "like" the player. But that

  isn't everything. NPCs move and follow the player as a result of states

  fed to the NPC's animation system from the Behavior AI. Notice the

  sentrybot_buddy behavior property:

    aiEditable -> behaviors -> decl

  If you open the behavior that it points at:

    decls -> aiBehavior -> behaviors -> sentrybot -> sentrybot

   

  You will notice a properly on it called followFriendlyThreshold.

  In the case of a sentry bot, the followFriendlyThreshold is set to

    ATTITUDE_LIKE

  And at the same time, the sentry_bot's faction makes the sentry bot like

  the player.

  This leads one to assume that if the followThreashold is equal to or less

  than the relationship, that the NPC will follow the player. However I have

  found this is not necessarily true.

  The bandit/default_pistol has a followThreshold of ATTITUDE_LOVE. But when

  I tried to make a companion with a faction that was set to LOVE the player,

  the NPC stopped following the player as soon as the first mission of the

  game was finished.

  At present, I assume the game prevents relationships from being stronger

  than like. Specifically, I think it looks at relationships and fixes

  them when jobs complete. Especially jobs that affect the players

  faction status.

  So really, it appears the key to getting an NPC to follow the player is

  to choose or create a behavior AI that has the followThreshold set to

  like and then ensure that the NPC likes or loves the player.

  The other thing to notice is on the EntityDef:

    walkIK -> enabled -> true.

  If walk is disabled, then they can't move, even if they wanted to follow you.

-------------------------------------------------------------------------------

VIII.2 > > > >  Setting up Interaction/Activation Handlers

-------------------------------------------------------------------------------

  There are two ways of setting up an NPC so that you will see the Interaction

  Activation icon hovering over them when they come into focus. You can do

  it declaratively or using scripts.

  A) Declaratively (No scripts)

  Declarative interactions are pretty strait forward. You start by making

  the interaction itself:

  Media Browser -> decls -> ai -> PlayerInteraction -> pcinteractions

  You will notice things like an interaction activation radius (how far you

  need to be for the icon to appear). And an interaction list.

  Each item in the interaction list needs a game-wide unique interactName.

  Use your mod name and some identifier:

  ie: interactName "awesomemod_first"

  Technically, for an Interaction Icon to appear, you need 1 of two things:

  - The Interaction must have a messageVO on the interaction definition

  - The NPC must have a merchant inventory defined.

  You will notice that the interaction has several VO files:

  - approachVO          : Opening Voice track/text that is played only once.

                          If it was a merchant, you might get an "welcome to

                          my shop" introduction.

  - secondaryApproachVO : For interactions that have only 1 interaction

                          list item, this is what will get played when you

                          approach the NPC after the approachVO has played

                          once. If it was a merchant, it may be "Welcome

                          back!".

  - messageVO           : What gets played after the approach. If it was

                          our merchant, he might say "I have the best

                          selection!"

  - Finish/Abort VO     : The final line. If it is a merchant, this will

                          play when the inventory window is closed. He

                          might say "Excellent selection. Please come

                          back"

  If the Interaction only has an approachVO and SecondaryVO and the NPC

  is not a merchant, you will not see the activate icon appear on them

  when you approach.

  In the example above, I used a merchant. A merchant may be fine with a

  single interaction list item. But you can create more complex interactions

  by making multiple interaction list items.

  Each interaction list item has an activation and expiration condition. If

  you want the interaction to always be available, then you want to force

  the expiration condition to always false/never expires. Typically

  interactions are linked to job conditions, which in turn may be invisible and

  linked to game state. Thus as the game progresses, commentary can change. A

  non-merchant NPC may even become a merchant.

  One issue with declarative PCInteractions is that these interactions are

  driven by a dedicated Interaction AI Brain. Put a different way, every NPC in

  the game can have only 1 "brain". That brain is typically setup when the NPC

  spawns, and there is really no way of changing it once it is set.

  So, if you setup an NPC with the brain that scans the area around them

  and enables/progresses declared interactions, then that NPC can not also

  use the brain that allows them to follow the Player and vice versa.

  You can however use scripts to get around this. For example, you can use

  scripts to detect when an NPC is within range of the player and manually

  activate an Interaction. Conversely, you could create an interactive NPC and

  use scripts to monitor how far the player is and force them to catch up.

  Dealing with detecting map environments is complicated stuff. (Where is the

  wall/enemies/water/obstacles). I think it is far easier to write custom

  scripts to activate interactions on NPCs than re-invent the follower system.

  B) Scripted 脚本化

  Take the following example:  举个例子:

  if ( self == $player1.getFocusEntity() && self.distanceTo( $player1 ) < 105 )    

  {

    self.beginWaitForPlayerInteraction();

    while( 1 ) {

      if ( self.playerTriggeredInteraction( $player1 ) ) {

        sys.print("Player Triggered Interaction!");

        // Do something....

        break;

      }

      if ( self != $player1.getFocusEntity() ) {

        break;

      }

      if ( self.distanceTo( $player1 ) > 105 ) {

        break;

      }

      sys.waitFrame();

    }

    self.endWaitForPlayerInteraction();

  }

  The assumption here is that you have an NPC assigned to a custom script

  object that monitors the NPC when the NPC spawns using a while loop.

  This code block would be part of the while loop.

这里假设您为一个自定义脚本分配了一个NPC

当NPC使用一个while循环生成时 监视NPC的对象。

这个代码块将是while循环的一部分。

  What this code block will do is cause the Activation icon to appear when you approach the NPC. And if the player hits "E", then the "Do

  Something" will execute. For example, "Do Something" could be th  startVO().

这个代码块的作用是,当你接近NPC时,激活图标会出现。

如果玩家点击了“E”,那么“去做” 某件事将会执行。

“某种东西”会执行 。例如,“Do Something” 可以是 startVO()。

  If the player looks or walks away, the tight loop will break.

如果 玩家 看着 或 走开, 这个 紧密的循环 就会被 打破。 

  One advantage of this method is that it also allows you to execute script

  code when the interaction begins,

which is actually, surprisingly hard to do with declarative Interaction Handlers.

该方法的一个优点是,它还允许您执行脚本

当交互开始时,这在 声明性 交互 处理程序中 是 很难做到的。

  There is one caveat: Normally, when an NPC's interaction is activated,

if  the NPC has a merchant inventory, the inventory will open after the interaction.

This not true when the interaction is forced via sript.

有一个警告:通常,当一个NPC的交互被激活时,

如果NPC有一个商人库存,库存将打开后 互相影响 当交互通过sript强制进行时,

情况并非如此。

  The only way I have been able to get merchants to work is with declarative

  interactions, which basically means you can't have a merchant follower

  without some tricks.  

我能够让商家工作的唯一方法是声明性互动,这基本上意味着你不能有一个商人的追随者

  没有一些技巧。

Travelling Merchant Work around

旅行商人的工作:

  --------------------------------

  One work around is to spawn an invisible merchant NPC on top of your follower

  when you approach them or swap in a follower clone (hide/unhide) that is set up as a merchant.

一种解决办法是在你的追随者上面产生一个看不见的商人NPC

当你接近他们或交换追随者克隆(隐藏/取消隐藏),设置为一个商人。

  if ( self == $player1.getFocusEntity() && self.distanceTo( $player1 ) < 105 )

  {

    clone.setOrigin(self.getOrigin());

    clone.setAngles(self.getAngles());

    clone.show()

    self.hide()

    clone.beginWaitForPlayerInteraction();

    while( 1 ) {

      if ( clone.playerTriggeredInteraction( $player1 ) ) {

        sys.print("Player Triggered Interaction!");

        break;

      }

      if ( self != $player1.getFocusEntity() ) {

        break;

      }

      if ( self.distanceTo( $player1 ) > 105 ) {

        break;

      }

      sys.waitFrame();

    }

    self.endWaitForPlayerInteraction();

  }

  Bugs:

  If you use any "action_<someaction>" command from within a script,

  the action command will work, but it will prevent the interaciton icon from

  appearing on the NPC. You can still use action script commands from

  the spawn settings of NPCs with no issues. But dont use action script

  commands from an Object Script handler if you need interaction/activation

  icons to work properly.  

如果您在脚本中使用任何“action_<某些操作>”命令,

操作命令将工作,但它将阻止交互图标

出现在全国人大大会上。您仍然可以使用动作脚本命令

npc的生成设置没有问题。但是不要使用动作脚本

如果需要交互/激活程序,则使用来自对象脚本处理程序的命令

图标可以正常工作。

-------------------------------------------------------------------------------

VIII.3 > > > >  Merchants

-------------------------------------------------------------------------------

  So how do you create a merchant?

那么,你该如何创建一个商人呢?

  In reality, every NPC is a merchant... or capable of being a merchant. To

  flag an NPC as a mechant, all you have to do is add merchant items to the

  NPCs definition:

事实上,每个NPC都是一个商人……或者有能力成为一个商人。向

标记一个NPC为一个机械师,你所要做的就是添加商业商品到

NPC定义:

  Media Browser -> Decls -> entityDef -> ai -> SomeNPC

  Under Properties, go to aiEditable -> interactions

媒体浏览器-> Decls ->完整的def->ai->SomeNPC

在“属性”下,转到可编辑的->交互

  This is where you will find the merchant definitions.

  

  Most of the lists are self explanatory:

在这里你可以找到商家的定义。

大多数的列表都是不言自明的:

  - Conditional Merchant Inventory : A lists of inventory items that will

    become available throughout the game based on conditions. FOr example,

    Ammo for a plasma rifle might have a condition on the player possessing

a plasma rifle.

 -有条件的商户库存:一个库存项目的清单

根据条件在整个游戏中都可用。FOr示例,

等离子步枪的弹药可能对玩家拥有有一个条件

等离子步枪。

  - Dynamic Merchant Inventory : Stuff that will appear randomly throughout

the game.

-动态商人库存:将随机出现的东西

游戏。

  - Special Dynamic Merchant Inventory : Like Dynamic, only with a discount.

You can think of this as the "On Sale" items.

-特殊动态商户库存:像动态,只有折扣。

你可以把这看作是“待售”的物品。

  Getting Merchants to work:

让商家工作:

  If you edit an NPC, and place items in the merchant invenoty, you may

  notice when you test the map/game that you can not activate the NPC to

  see/buy your inventory.

 如果您编辑一个NPC,并放置项目在商家的发明,您可以

请注意,当你测试地图/游戏时,你不能激活NPC到

查看/购买您的库存。

  This is because Rage has a system. First it plays the playerInteraction,

  then it opens up the inventory only after the playerInteraction associated

  with the merchant has finished playing. So under interactions, if you

  leave the  "playerInteraction" value set to NULL, the merchant wont work.

这是因为愤怒症有一个系统。首先,它播放了玩家的互动,

然后,它只在玩家交互相关后才打开库存

和商人一起玩完了。所以在互动下,如果你

将“玩家交互”值设置为NULL,商家将无法工作。

  You MUST define a playerInteraction for the merchant to work.

  Player Interactions are defined under:

你必须定义一个玩家交互为商人的工作。

玩家交互作用的定义如下:

  Media Browser -> decls -> ai -> PlayerInteraction -> pcinteractions

  For the interaction to work, you need at least 1 item in the

  interactions "interactList" Property and it needs to have a

  unique interactName. (Use your mod name and some identifier)

媒体浏览器-> decls -> ai ->播放器交互->pc交互

要进行交互,您至少需要在

交互“交互列表”属性,它需要有一个

唯一的交互程序名称。(使用您的国防部名称和一些标识符)

  ie: interactName "awesomemod_first"

  The other values dont really matter and in fact you can set

  almost all the VO's to NULL if you don't actually want any

  spoken audio.

即:交互名“awesomemod_first”

其他的值并不重要,事实上你可以设置

如果你真的不想要的话,几乎所有的VO都是空的

口语音频。

  Merchants and Movement

商人和运动

  As mentioned above in VIII.2, Rage does not support merchants that are

  capable of following the player.  Conversely, moving NPCs can't be merchants.

如上八所述。2、愤怒不支持的商家是谁的

能够跟随玩家的。相反,移动的npc不可能成为商人。

  If you attempt to make an NPC that can move (like a sentry bot) a merchant,

  there will be a race condition when they spawn. If they see you and activate

  the merchant inventory quickly, then they wont follow you. If they don't see

  you immediately and the follower AI kicks in, then you wont be able to

  activate the merchant interaction.

如果你试图让一个可以移动的NPC(就像一个哨兵机器人)成为一个商人,

当它们诞生时,将会有一个比赛条件。

如果他们看到了你并激活了你

商人的库存很快,然后他们就不会跟踪你了。

如果他们看不到你马上和追随者AI开始作用,

然后你就不能激活商家的交互作用。

  I talk about a work around in VIII.2 above.    

 我在上面的VIII.2中谈到了一种解决方法。

===============================================================================

IX. > > > > Building, Dependencies and Deployment 构建、依赖关系和部署

===============================================================================

  A) Raw versus compiled resources:  原始资源与编译资源的对比:

    By default, most of Rages resources are raw, uncompressed files, but the

    game engine needs them to be in a streamlined binary (compressed) format

to use.

默认情况下,大多数Rages资源都是原始的、未压缩的文件,

但是游戏引擎需要它们是在一个简化的二进制(压缩)格式使用。

    For example, if you look in the folder:

 例如,如果你查看文件夹:

      <RAGETOOLKIT>\base\md6\

    You will notice there is a default.md6 file.

 您将注意到有一个 default.md6 文件。

    If you ran buildAssets.cfg when you installed Rage, you will likely have

    a "generated" directory where binary (usable) versions of files are stored.

如果您在安装Rage时运行buildAssets.cfg,您可能会有

一个“生成”的目录,其中存储二进制(可用的)文件版本。

     

 <RAGETOOLKIT>\base\generated\md6\default.md6\_default.bmd6anim

    Not only is the generate directory needed to view/listen to resources

in ID Studio, it also acts as a cache for objects.

不仅需要生成目录来查看/侦听资源

在ID Studio中,它还充当对象的缓存。

    It is unclear how and when ID Studio decides to reload/re-generate

    raw resources, but sometimes this caching can lead to issues. Especially

    when you use external version management software where you can revert

    and roll back changes. If ID Studio uses simple timestamps to track when

    cached objects need to be refreshed, then reverting a file using SVN

can lead to a corrupted cache.

目前还不清楚ID Studio如何以及 何时 决定 重新加载 / 重新生成

原始资源,但有时这种缓存可能会导致问题。

特别是当您使用外部版本管理软件时,您可以恢复并回滚更改。

如果ID Studio使用 简单的时间戳 来 跟踪什么时间需要刷新缓存的对象,

然后使用SVN 恢 复文件 可能 会 导致 损坏 的缓存。

     So while it is painful, before building a release, especially one I plan

     on publishing to the web, I clear all cache oriented files and force

     ID studio to rebuild everything. I also do this when I run into awkward

     unexplainable issues to rule out cache problems.

所以,虽然这很痛苦,但在构建发布之前,尤其是我计划的版本在发布到web时,

我清除了所有面向缓存的文件和强制

id工作室来重建一切。

当我遇到尴尬时,我也会这样做无法解释的问题,以排除缓存问题。

     THese are the files that I delete:

这些都是我删除的文件:

       <Rage TOol Kit>/base/pages.xml

       <Rage TOol Kit>/base/vmtr.xml

       <Rage TOol Kit>/pagefiles/build.pages

       <Rage TOol Kit>/pagefiles/build_processed.pages

       <Rage TOol Kit>/virtualtextures/_vmtr_v23_256_C.pages

       <Rage TOol Kit>/virtualtextures/_vmtr_v23_256_C.vmtr

     If you have made a custom map, then any files within the

     <Rage TOol Kit>/virtualtextures directory that have your

     map's name(s) in them...

如果您已经创建了一个自定义地图,那么任何文件在

<Rage工具包>/虚拟纹理目录

地图的名称(s)。

     Finally, I blow away the entire "generated" directory:  最后,我删除了整个“生成”目录:

       <Rage TOol Kit>/base/generated

     This will force ID Studio to rebuild all objects for your mod. Note that

     it will only build objects that it thinks your mod needs. This is

     discussed more below.

这将迫使 ID Studio为 你的 mod 重建 所有对象 它只会构建它认为你的mod需要的对象。

这是 下面将详细讨论。

  B) Fighting the not-so-optimizing compiler:

 B)对抗不太优化的编译器:

     When ID Studio builds your mod, it tries to optimize the size by doing a

     dependency trace and only include things that your mod needs.

     If you click on almost any entity in ID studio's decl section, you will

     see a graph with lots of lines pointing to various objects. That graph

     is the dependency graph. It points to all the things the entity needs

     to ensure the entity can function properly.

当 id Studio构建您的mod时,它试图通过做一个依赖项跟踪,并且只包含mod需要的东西。

如果你点击几乎任何实体在ID工作室的decl部分,

你会可以看到一个有许多线指向不同对象的图形。

那张图是依赖关系图。

它指向了这个实体所需要的所有东西以确保该实体能够正常运行。

     If ID Studio was working correctly, then it would look for any entities

     that you edited, and then follow those entities dependency graphs to

     determine what needs to be included in the mod.

如果ID Studio工作正常,那么它就会查找任何实体,然后遵循这些实体依赖图

确定需要在 模组  中包含什么。

     I wouldn't mind this so much, except that ID Studio fails horribly. If you

     install Rage Tool Kit and immediately build a mod with no maps that does

     absolutely nothing, the final mod size will be around 200 MB.

我不会那么介意,除非 id Studio 失败了。

如果你 安装《狂怒 》的工具包,并立即构建一个模组,没有地图,这样做

绝对没有,最终的mod(模组)大小将在200 MB左右。

     So it is not really clear to me what the optimizing compiler is doing

     other than creating a dependency headache for mod developers... but I

     digress.

所以我并不很清楚优化编译器在做什么,除了给mod开发者制造依赖头痛…但是我跑题了

    

 What this means to you is that just because you import a resource like a

     sound or model into ID Studio does not mean it will get deployed with your

     mod. It will only get included if ID Studio detects that the mod needs it

     because you have it attached to something that you are building.

这对您来说意味着,仅仅因为您导入了像声音或模型导入ID Studio

并不意味着它将被部署到你的 mod.

只有当ID Studio检测到mod需要它时,它才会被包含在内

因为你把它 附着 在 你正在 建造的东西上。

     This dependency "hint" is normally a vanilla job that is edited so that it

     starts your own custom job, which rewards items (or removes items.. still

     identifies the item). Thus the resources get marked for inclusion. If you

     add a resource to the game... be it a texture, model, sound, etc... that

     is not connected to in some what via a "hint" job,

it will not be deployed with your mod.

这个依赖项“提示”通常是一个普通的工作,被编辑它启动您自己的自定义job,以奖励项目

(或删除项目..仍然标识该项目)。

因此,资源被标记为包含。

如果你在游戏中添加资源…比如纹理,模型,声音,等等

没有连接到某些什么通过“提示”作业,它不会 与 您的 mod 一起部署。

     Additionally, Rage itself is very map centric. When it loads a map, it

     only loads resources that MIGHT be accessed from the map because the map

     points to them directly or points to them indirectly. So even if a

     resource is deployed with your mod, it may not be available from all

     maps or at the right time. This is mostly an issue with Asset Mods that

     rely heavily on global scripts and is discussed further below.

此外,《狂怒》本身是非常以地图为中心的。

当它加载一张地图时,它就会加载 只加载可能从地图中访问的资源,

因为地图直接地指向他们或间接地指向他们。

所以即使a资源是与您的mod一起部署的,

它可能不是从所有资源中 都可用的 地图 或在正确的时间。

这主要是资产模块的一个问题

严重依赖于全局脚本,并将在下面进一步讨论。

-------------------------------------------------------------------------------

IX.1 > > > >  Map Mods  地图 插件

  A "Map Mod" is a mod where all the new quests/features, etc... take place in

  a new map that you create as part of the mod. Bottom line is that a "Map Mod"

  makes almost no changes to the original game.

All of your changes are  localized to new maps that you create.

一个“地图mod”是一个mod,其中所有的新任务/功能,等等…

发生在一个您作为mod 的一部分 而 创建 的 新 地图。

底线 是一个“地图Mod”几乎没有改变原来的游戏。

你所有的改变 都是本地化到您 创建 的 新地图 。

  Some "map mods" may include 1 very simple edit to the original game to link

  to the new mod, but edits are very limited.

一些“地图模组”可能包括一个非常简单的编辑 到 原始游戏的链接

到新的 mod,但编辑是非常有限。

  A map mod could technically be a mod that starts/takes place when the game

  ends, as long as the mod takes place in new maps ... or clones of existing

  maps that you have renamed and edited.

从技术上讲,一个地图mod可以是一个在游戏中开始/发生的 mod

结束,只要mod发生在新的地图上…或现有的克隆 已重命名 和 编辑的地图。

  A) Dependencies 依赖关系 /依赖 /相关性 /服务

    Dependencies with new custom maps that YOU create are not that difficult.

You simply have to follow 1 rule:

与您创建的新自定义映射的依赖关系并不困难。你只需要遵循1条规则:

      Make sure you embed instances of everything the map needs into the map,

      even if that means placing them in a non-accessible area.

确保您将 地图 需要 的 所有 实例 嵌入 到 地图中,

即使这 意味着 要把 它们放在一个 不可接近的 区域。

    If you want to write a map script that dynamically spawns enemies,

all you  have to do is make sure at least 1 valid instance of your enemy is embedded

    in the map. This will ensure the sounds, models, textures and animations

are  all in memory when your script spawns the AI decl.

如果你想写一个动态地 产生 敌人 的 地图脚本,所有的你

必须做的是确保至少有一个有效的敌人实例被嵌入在地图上。

这将确保声音,模型,纹理和动画

当你的脚本生成AI decl时,它们都在内存中。

  1. Scope 范围

B)范围

    As mentioned earlier, most settings involving an entity are baked into the

    map. Instance data is that stuff that you see when you SHIFT click the

    entity that you have placed in your map and look at its properties over in

the entity inspector.

如前所述,涉及实体的大多数设置都被烘焙到

地图实例数据是指您在移动时看到的东西,请单击

您放置在地图中 并查看它的属性 在实体检视器 。

    Basically, if you see it in the entity inspector, then the setting is baked

    into the map. So if you make a weak ghost bandit instance in your map, it

    doesn't matter if someone installs another mod that has maps where all

ghosts are invulnerable.

基本上,如果您在实体检查器中看到它,那么该设置将被烘焙

进入地图。所以如果你在地图上做了一个很弱的幽灵强盗实例,它就会出现

不管是否有人安装了另一个有地图的 mod

ghosts 是无创的。

    Your ghost will still be weak because all settings you see in the entity

inspector are baked into the map.

你的幽灵仍然会很弱,因为你在实体中看到的所有设置

检视器 被烘焙 在 地图上。

    THings that are not baked into the mod: Anything you dont see in the entity

    inspector can be changed by other mods.

那些没有嵌入mod的东西:任何你在实体中看不到的东西检查器可以由其他插件更改。

For example, another mod could make

    ghost bandits look like amazon females with a different voice set and

    different animations by redefining what the bandit md6 looks like internally.

例如,另一个mod可以使 幽灵强盗 看起来像 亚马逊 的 女性,

有着不同的声音设置和通过重新定义强盗md6的不同动画 在内部

    If you dynamically spawn ghosts at runtime, you will be spawning whatever

    the entityDef/ai/bandit definition describes.

So if another mod changes that definition, you may not be spawning what you think.

如果你在运行时动态地生成 ghosts,你将会生成任何东西

整个 实体定义 Def/ai/bandit 的定义 描述。

所以如果另一个mod改变了这个定义,你可能不会产生你想要的东西。

    If you dynamically spawn enemies, you may want to make a duplicate copy of

    their entityDef and dynamically spawn your own custom copy to ensure no

    unexpected changes by other mods.

(Or maybe you want to leave that possibility open. It is totally up to you).

如果你 动态地 生成 敌人,你可能想要复制一个副本

它们的完整的def 和 动态生成您自己的自定义副本,以确保没有其他插件的意外变化。

(或者你想保留这种可能性。这完全取决于你)。

  1. Testing 测试 

    The easiest way to test your map is open the map up in ID Studio

测试 地图 的 最简单方法 是在id  Studio 中 打开地图

      File -> Open -> Map

文件-> Open ->地图

    Once it is loaded, go to the Build Menu and select:

加载 完成 后,转到 Build 菜单 并 选择:

      Full Map Build + Mega Bake

      全地图建立 + 超级烘焙

    This will build what is called a combo map. 这将构建所谓的组合地图。

    THen go to the engine tab, hit "tilda" to open console and type:

      devmap game/<yourmap>

然后转到引擎选项卡,点击“tilda”打开控制台并键入:

devmap game/<yourmap>

    One thing you might notice is that the textures are a little fuzzy. THat

    is because fast building maps doesn't normally include the level of

detail that producion building does.

你可能会注意到的一件事是,纹理有点模糊。THat

是因为快速构建地图通常不包括地图的水平吗

生产建筑的细节。

  D) Build Production: 

      Open the Map (FIle -> Open -> Map)

      In the World Edit tab, go to Build -> Build Wizard

      Goto the Advanced Tab

      Change the preset to " Full Map Build + Mega Bake [Default]"

      Uncheck "Build Unique"

      Check "Build Detail"

      In "Build Selected MegaTextures", select your map

      Check any other build optoins that apply

      When you are done, hit build

      Repeat for any all custom maps.

打开地图(FIle -> Open ->地图)

在“世界编辑”选项卡中,转到构建->构建向导

转到“高级”选项卡

将预设更改为“全地图构建+超级烘焙[默认]”

取消选中“构建唯一”

检查“构建详细信息”

在“构建选定的元纹理”中,选择您的地图

检查任何其他适用的 构建视图

当完成后,点击 build(构建)

对任何所有自定义映射都执行重复操作。

  

-------------------------------------------------------------------------------

IX.2 > > > >  Asset/Script Mods 资产/脚本模式

-------------------------------------------------------------------------------

  When you make a map, the map clearly defines what it needs. So when you

  compile your mod, the game knows exactly what models, sounds and even ai

  declarations to add to the game, but when you write scripts, the game doesn't know...

and as a result, often times the thing your script needs

  is not present in memory when you try to access it.

当你制作一个地图时,地图清楚地定义了它需要什么。

所以当你编译你的mod,游戏确切地知道什么模型,声音,甚至 ai声明要添加到游戏中,

但当你编写脚本时,游戏将会出现 不知道…

因此,你的脚本需要的东西

当您试图访问内存时,它不存在于内存中。

  Take this example:

    You make an asset mod (No Map) where you edit one of the original

    games jobs so that it rewards a new item you created. Your item has

    a script attached to it that plays a new sound and spawns a new 3d  

prop in the world using script commands...

您创建一个资产模型(没有地图),在那里您编辑一个原始

游戏工作,使它奖励你创建的新项目。

您的项目有一个附加的脚本,播放一个新的声音,

并产生一个新的3d使用脚本命令。

  Result:

    The inventoryItem and its icon will be included in the mod such that

    when the job activates, they will definitely be present in memory. The

    script will also be present, but running it will either not work or

may crash the game.

库存项目及其图标将被包括在 模组 中,这样

当job 被激活时,它们肯定会出现在 内存 中。

这个脚本也将出现,但运行它将要么不工作,要么

可能会让游戏崩溃。

  WHY:

    ID Studio knows the script compiled, but it doesn't know what the script

    actually does or needs... So when it did its dependency trace, it didn't

    realize it needed to include the new sound and prop because they are

only referenced by the script.

ID Studio知道编译的脚本,但它不知道脚本是什么

实际上做或需要..。所以当它进行依赖性跟踪时,它并没有

意识到它需要包括新的声音和道具,因为他们是

仅被脚本引用。

    Even if you pointed to existing sounds and props, the script would only

    work if you were standing in a  map that HAPPENED to already contain the

model and sound in pre-cache.

即使你指出了现有的声音和道具,剧本也只会这么说

如果你正站在一张地图上,但碰巧已经包含了一个问题

预缓存中的模型和声音。

    So whether you use items/sounds/resources that came with the game

    or new resources you create your own, the problem is the same... The

    optimizing compiler doesn't know you need those things, so they will

not be in memory when your script tries to use them.

所以你是否使用游戏附带的物品/声音/资源呢

或者是你自己创建的新资源,问题也是一样的。。这个

优化编译器并不知道你需要这些东西,所以他们会需要的

当您的脚本尝试使用它们时,它们不在内存中。

    To make things even more confusing... When you test you scripts in ID

    STUDIO, (maybe within a temporary testing map), all game resources are

    in memory. So you likely will not realize you have a script dependency

issue until you try to deploy your mod and run it from the actual game.

让事情更令人困惑。。

当您在ID中测试您的脚本时工作室,

(也许是在一个临时的测试地图内),

所有的游戏资源都是在记忆中。

所以您可能不会意识到您有一个脚本依赖性直到你尝试部署你的 mod

并从实际的游戏中运行它。

  This is probably one of the most frustrating things about modding rage.

  Scripts assume the programmer will only spawn/use entities and items that

  are already in memory when the script runs because ID Studio assumes all

  mods are map mods. (If it was a map script and you made the map, then you

  would know what was safe to reference).

这可能是制造愤怒症最令人沮丧的事情之一。

脚本假设程序员只会生成/使用这些实体和项目

当脚本运行时已经在内存中,因为ID Studio假定所有

模块是地图模块。(如果它是一个地图脚本,而你制作了地图,那么你就可以完成了

我知道什么是安全的参考)。

  So it is up to you to keep track of what your script spawns/plays and

  make sure that those objects are in memory when the script runs.

所以它应该由你来跟踪你的脚本产生/播放什么

请确保在脚本运行时,这些对象都在内存中。

  1. Props, sounds, textures:
  2. 道具、声音、纹理:

    With the exception of AIs (I will get to that in a moment), you can

    get around most issues by creating a welcome message (see tutorial above)

    and "rewarding" the player by removing items and deployables that link to

the items that your script needs.

除了AIs(我马上会讲到),你可以

通过创建一个欢迎消息来解决大多数问题(参见上面的教程)

通过删除项目和可部署来“奖励”玩家

脚本所需的项目。

    So if your script needs to play a sound (existing or not), you need

    a new hidden inventoryItem with that sound associated with it (maybe a

dropSound for example).

  因此,如果你的脚本需要播放一个声音(存在或不存在),你就需要

一个新的隐藏库存项目与之相关的声音(可能是a

例如DropSound)。

    The main two settings you want to "flip" for hidden items are:

你想要“翻转”隐藏项目的两个主要设置是:

      noPickupMessage         : true               

      playerCanSeeInInventory : false

  

    You will also want to mark hidden items as "singular". This setting

    will not prevent items from stacking, however it will eliminate all

    but 1 instance of the item when the player changes maps.

您还需要将隐藏的项目标记为“单数”。此项设置:

不会阻止物品的堆叠,但它将消除所有的东西吗

但当玩家改变地图时,该项目的一个实例。

    Any sounds, props, textures, etc... that the item points to will be

loaded into memory when the engine loads the players inventory.

任何声音,道具,纹理等等…项目将的  加载到内存时,引擎 加载 玩家库存。

    If you have a truely global script with no entity attachment, then

    you can make the resources globably available by adding the

hidden items to the players inventory definition:

如果您有一个真正的全局脚本,但没有实体附件,那么

您可以通过添加  隐藏到 玩家库存定义的物品:

      decls/entityDef/player -> startingInventory

    However I haven't really tested this method. The welcome message jon is the

only method I have proven experience with.

然而,我还没有真正测试过这个方法。乔恩收到的欢迎信息是

我唯一证明经验的方法。

  B) AIs

     AIs (Animated entities such as NPCS) are more complicated because they

     are not simply a model. They include behaviors, voice tracks, animations,

     textures, weapon props for their inventory items, etc...

AIs(动画实体,如NPCS)更加复杂,因为它们

并不仅仅是一个模型。它们包括行为,声音轨道,动画,

纹理,为他们的库存物品准备的武器道具,等等。

     A simple item prop can help you get the model mesh in memory, but that is

     just the tip of the iceburg.

一个简单的项目道具可以帮助你在内存中获得模型网格,但那是 就在冰堡的顶端。

     I did find 1 work around, but it is limited in scope and comes with its

     own bugs.

我确实找到了一个工作,但它的范围有限,并附带它

自己的错误。

     Rage includes a mind control dart weapon as well as remote control cars.

     When you use these items, you see the player model from the remotely

     controlled entity. To support this, every map in rage already includes MD6

     links to the various player armors. However, the MD6 itself is dynamically

     loaded at runtime.

《狂怒》包括一个精神控制飞镖武器 以及 遥控汽车。

当你使用这些项目时,你可以从 远程 看到 玩家模型 受控 实体。

为了支持这一点,每张狂怒的地图都已经包含了MD6

链接到各种玩家的盔甲。

然而,MD6本身是动态的在运行时加载。

     So.. you can edit one of the player outfits so that it points at a

     different md6mesh and different animations. Then your AI can point to the

     corresponding player MD6 outfit.

所以..你可以编辑其中一个玩家服装,使它指向a

不同的md6网格和不同的动画。然后你的人工智能就可以指向

相应的玩家MD6装备。

     THis will cause the game to load the model and any associated animations

     when it loads the maps and your script will be able to spawn AI's that

     use the model/animations since they will be in memory.

这些功能将导致游戏加载模型和任何相关的动画

当它加载地图和你的脚本将能够产生AI的那个

使用模型/动画,因为它们将在内存中。

     By the time Rage gives you access to remove control cars, you already have

     to buy a non-ark suit. Thus the first 2 arksuit outfits are safe for use.

     You could technically use the other outfits as well, though you risk a

     user seeing something unusual when they use the remove control car.

当“狂怒 ”让你可以删除控制车时,你已经有了去买一套非方舟式的西装。

因此,前两套宇航服使用起来是安全的。

从技术上讲,你也可以使用其他服装,

尽管你冒着a用户看到一些不寻常的东西时,他们使用的拆卸控制车。

-------------------------------------------------------------------------------

IX.3 > > > >  When it fails:  开发运维手册

  Sometimes a build fails and when this happens you may find that when you

  try to start up the tool kit that the menu that appears does not have the

  "ID Studio" Link.

有时一个 构建 失败,当这种情况发生时,你可能会发现,

当你尝试启动工具包,因为出现的菜单中没有“ID工作室”链接。

  This is because during the build process, the menu is replaced with a version

  that does not have the IDSTUDIO link, as the menu flash program is part of

  build. When the build fails because of a crash, the menu does not get

  restored.

这是因为在构建过程中,菜单会被替换为一个版本

没有IDSTUDIO链接,因为菜单flash程序的一部分

建造当生成因为崩溃而失败时,菜单将不会得到

归还

  Luckily, ID Studio baks up the original menu .swf file. You should find it

  under:

幸运的是,ID Studio备份了原始菜单.swf文件。你应该找到它

在…下面

  <Rage Tool Kit>/base/swf/

  Look for any ".bak" files and manually restore them. If you have version

  control software installed, it should be obvious.

查找任何“.bak”文件,并手动恢复它们。如果你有版本

控制软件安装后,应该很明显。

===============================================================================

X. > > > > External Appendix>外部附录

===============================================================================

  A) Console Commands:

     http://docs.google.com/file/d/0B0VAFIuYmSp5WE10cDUtS1A2WVE

  B) Console Variables  控制台变量

     http://docs.google.com/file/d/0B0VAFIuYmSp5VkpjRTE0TGdIR0k

  C) Script Commands and Constants 脚本命令 和 常量

     http://docs.google.com/file/d/0B0VAFIuYmSp5Ri1SYlNuaGhYb1E

  D) Script operations

     http://docs.google.com/file/d/0B0VAFIuYmSp5SjlsdFFydVkzaWs

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值