My First Mod:zh-cn

From Valve Developer Community
Jump to: navigation, search
English Deutsch Español Polski Português Português-Brasileiro Русский 

此教程会教您如何建立一个简单的mod。这个mod中我们会修改Half-Life 2的火箭速度。本教程使用Source SDK 2007但是同样应用于Source SDK 2013

创建项目

我们将本教程mod叫做「Mymod」。您自己的mod可以随意叫任何名字(如「Quickmod」「TreasureTroll」「Old Man With Melons Mod」等。)

注意我们要求最新版本的源码,请通过refresh the SDK content来获取。

创建mod项目:

  1. 打开Source SDK,它位于Steam的Tools菜单里面。
  2. 请选择Source Engine 2007的版本。
  3. 打开Create A ModUtilities组。
  4. 请选择modify Half-Life 2 Single Playermodify Half-Life 2 Multiplayer
  5. 选择mod的路径安装(即C:\Mymod)。
  6. 输入您的mod名字,本教程使用「Mymod」。
  7. 完成剩下的步骤。

然后Steam将把源代码复制到您选择的目录,现在可以开始修改之旅了。

准备解决方案

  1. 请参阅Compiling under VS2008 / 2005 / 2010 / 2012 / 2015,并以适当者为准。
  2. 参阅Launching from Visual Studio

改变火箭的速度

如果您修改的是Half-Life 2: Singleplayer在解决方案浏览器,打开文件Server Episodic > Source Files > HL2 DLL > weapon_rpg.cpp。 否则打开hl2mp_dll/weapon_rpg.cpp

在开头您可以找到以下定义:

#define RPG_SPEED 1500

改变它:

#define RPG_SPEED 400

通过修改这个数字,我们便告诉了火箭的速度是400单位(或者33英尺或10米)。先前则是1500单位(125 ft/s, 38 m/s)。当您启动mod的时候您会直观的感受到速度的变化。

编译项目

现在我们准备编译项目了。选择 Build->Build Solution 开始。请求的编译完成后会出现一个server.dllclient.dll文件,位于Mymod/bin 目录。(即C:\Mymod\Mymod\Bin)。这是我们的mod客户端和服务器的自定义DLL,也是未来游戏发布的一部分。

启动mod

在启动之前,我们需要确保一些重要的东西启用。默认的,新mod会使用 AppId 215(半条命2第一章)或218(橙盒)。这会加载目前版本的Source SDK Base,您可以在mod目录的这个地方GameInfo.txt file修改它。

SDK Base provides only Half-Life 2's shared content, however. If you want to use content from a specific game, or HL2's maps, you will need to change the AppId to that of the game you want to load from. If you want to 'mount' more than one game you can do so, but you should avoid that method unless you really need it for reasons explained on its page.

In the directory that you created your mod, there will be a batch file called run_mod.bat. Don't use the bat file to launch your mod, as it has not been updated for the SDK Base. The best way to launch your mod is from within Visual Studio by pressing F5, or restart Steam and launch it from your Games list (where it should hopefully have appeared - if not, check your AppId).

No maps are provided with your single player mod, so copy a map from the HL2 maps with GCFScape to your mod's /maps/ directory inside of SteamApps/Sourcemods. Load a map by typing "map " (including the space) into the console and select from the list (e.g. map d1_canals_01) then type "impulse 101" to give yourself a load of weapons.

Now that there's content to load, start the game up. When the engine has loaded, you'll be taken to the title screen. If you are warned about missing content, such as maplist.txt, ignore it.

In "Options", "Keyboard", and "Advanced", enable the Developer Console. Hit the tilde key (~) to bring up the Developer Console. This console will provide you with numerous tools to help you create content for the Source engine.
Note:The console will always appear if -allowdebug is specified as a command line argument/advanced option
Note:A map that you can always use and is guaranteed to work is sdk_shader_samples.bsp, found in steamapps\[USER ID]\half-life 2\hl2\maps
Note:Enable cheats in the game by typing "sv_cheats 1" in the console (~) for the "impulse 101" command to work

Select and fire the RPG to view the changes you've made.

Debugging Techniques

You may have some difficulties following these steps using Release configuration. Change to Debug if you run into problems. Before moving on, I must point out that Source modding is a VERY difficult way to learn C++. You will be better served trying out lots of tutorials designed for learning C++, and applying what you've learned to modding.

Navigating Code: What is RPG_SPEED

In the game code, right click the RPG_SPEED and select Find all references.... This will display the Find Symbol Results pane. Click the plus to expand the results. The first is obviously the definition, the part we were playing with before. The other two are locations where RPG_SPEED is actually being used. Double click the last one.

This brings us to a function called void CMissile::IgniteThink(). When the rocket is first launched, it's not ignited. This code is used, or “called”, to ignite the rocket. The line of code we are at:

SetAbsVelocity( vecForward * RPG_SPEED );

sets the velocity (direction and speed) of the rocket. Use the Find all references..., Go to Definition, and Go to Declaration tools liberally. If ever you don't know what something is, where it came from, or what it is doing, these tools can help you wrap your mind around the code.

By default, the RPG_SPEED is set to 1500.

Using break points

In the gray margin to the left of this line of code, click the left mouse button. If this doesn't do anything or you are just confused, you can alternatively press F9 or use Debug Menu > Toggle Breakpoint. This will put a red dot in the margin known as a break point. A break point is used to pause execution of a program. This may seem like a strange concept, so some explanation is in order.

It's often useful to see what's going on in a program at a specific moment. When the program tries to run this line of code, it will be stopped. EVERYTHING in the program will be stopped. 3D graphics, mouse input, even clicking the close button have been paused. This allows you to scrutinize the state/data of the program, frozen in a moment in time.

If the mod isn't already running, press F5 and fire it up. Load up your map and some weapons, and shoot the RPG.

Examining and modifying state

Right when the rocket tried to kick on, Visual Studio should have popped up and should say Paused in the title bar. The cursor will be on the line of code, a yellow arrow is in the margin. Hover the mouse over vecForward and you'll see a box pop showing you the values inside of vecForward, X Y and Z. These values are currently rather small (This is a normalized vector, but that's another tutorial). If you click the plus to expand the values, you can actually modify the values, changing the internal state of the program.

Go to Debug Menu > Windows > Autos. This will automatically show you any variables that are being used by the current code, and show them in red if they've changed their value.

Stepping through execution

This line of code we have “paused execution” at is an instruction to use the SetAbsVelocity function, and it also passes some data to the function: vecForward * RPG_SPEED.

Press F11. Alternatively, you can use Debug Menu > Step Into, or find the button in the toolbar with the same icon. Notice again the yellow arrow in the gray margin. This arrow indicates the next instruction the program will execute.

We are now inside the SetAbsVelocity function. Examine the value of vecAbsVelocity. You'll notice that it's much bigger than vecForward before, because it's been multiplied by RPG_SPEED. Now examine, m_vecAbsVelocity. This is the actual saved velocity of the rocket. Right now it's still rather small, because the rocket just got ignited and hasn't sped up at all. Press F10. F10 is similar to F11, except that it wont go inside of functions.

If we had pressed F10 before, the yellow arrow wouldn't have moved into the SetAbsVelocity function. Instead it would have moved to the line after SetAbsVelocity(vecForward*RPG_SPEED). The call to SetAbsVelocity still occurs, but it happens very quickly without us watching. Press F10 a few times till you get to the line:

m_vecAbsVelocity = vecAbsVelocity;

If you examine the two variables again, you will see they haven't changed yet. Press F11 (or F10. Since this isn't a function to step into, it has the same effect) once more. Now examine m_vecAbsVelocity. You will see that the values from vecAbsVelocity have been assigned, or copied over. This is a very powerful debugging technique. It allows us to see how the programs state changes from one line to the next. If something isn't working how we expect, we can watch things as they happen and trace to where things are going wrong. You can also trace backwards. Start from where the unexpected result is observed, and examine the state there. If part of the state (like a variable) is not right, go back to where the wrong state might have become present (the last place the variable got assigned a value). Use the Go to Definition, or Find all References to help you hunt down the possible places. Repeat the process until you hone in on the source of the error.

More debugging techniques

There are many features in Visual Studio to help you debug more efficiently. You can make break points only break on a certain condition, see the call stack - the chain of functions that have been called to get where you are now, and many others. If you want to get great at mod programming, you have to get great at programming C++, debugging C++, and how to get make full use of your IDE (in this case VS).

You've built your first mod. Now what?

You’ve now set up, built, and debugged your first mod. Now experiment and tinker. Getting your hands dirty is the best way. If you have coding questions, there is a formal news group called HLCODERS. If you are serious about mod programming, track it down. There are also many communities centered around HL2 and modding, and most have a programming forum, tutorials, etc.

For a stepping stone to different aspects of mapping see What makes a good level?