谁会修改模型的武器数量?给个教程或提示:lol 比如一个单位有2种武器,其中一种武器有2个发射点,想把着2个发射点分开,增加第3种武器。高手赐教:lol :victory:
怎样写一辆坦克的脚本的不完全翻译
How To Script a Basic Tank(怎样写一辆坦克的脚本)
你需要什么工具? 下面每一个都是你需要的, and they’re available from the MAD TA Download Page!
- Scriptor V1.00 (不使用任何其他的编译器).
- Marcosoft 的 Lazy Scripter.
- 3DO Builder.
- HPI View/Hpi Pack 或者 HPI Manager
The next thing I want to say is that I won’t answer any queries by email. If you have a problem, post it at the forum, that way other people with the same problem can find a solution ![]()
I have included a unit with this tutorial that I’d like to release at MAD TA some day. Everything is finished except the script. So… I challenge you to do it for me. For a bit of fun, the first person who sends me this unit with the script working flawlessly can have the pleasure of naming this weapon of war, and they will of course get the credit for scripting it (10 mins of fame - Gotta be worth it
). You’ll find the unit in the Tutorial Challenge folder, and a pic along with side this file. Before I forget, you will need the MAD Stuff file from the top of our units section to see all of the textures correctly.
The first thing to cover before you start scripting is 目标的起源. 这是几点关于一个目标旋转。 在 3DO Builder, 你通过选择对象可以看到一个物体的起源, and looking for a 蓝色点. See it? 现在,如果你写一辆坦克车的脚本,你要确保在一些物体的起源是在正确的地方. 来看看你的炮台。 那里是目标的起源? 应该是炮台的中心, 应该与barrel(s)有同样的高度. 如果不是在这里, 就要移动炮台, 然后使用"设置当前位置为对象的起源"的功能,直到你重新得到它的正确位置 (it won’t take you long to see how this works). 一旦你使你的起源在正确的地方, move 你的炮台回到它原来的地方. 。重要的是,你不要再点击“用现在的位置为研究对象的起源” , 否则你要重新开始。 现在 barrels(炮管)怎样呢? 如果你想它们能够上下活动, 目标的起源 应该在 barrel 连接炮台位置。 想象你的 barrel 绕这点上下活动。 会出问题吗? Or will it be fine. To help you decide, take a look at some of Cavedog’s tank models (always refer to the old trusty when unsure)
Now you’re happy with your 目标的起源 (if you’re not, don’t worry, you’ll soon find out if they’re ok once the thing’s scripted), we’ll cover a few basic unwritten rules for scripting (say these every night aloud before going to sleep):
规则1 : Lazyness is happiness. If you can find an easy way around a problem that you know will work, take it!
规则# 2: Don’t trust anyone elses scripting! It doesn’t matter who wrote it, there’s no guarantee it’s right.
Rule #3: Never add or take away pieces of a model after scripting it without changing your “piece” line
to match, or you’ll find disfunctional pieces in TA, or crashes!
Rule #4: If it doesn’t compile, it doesn’t work! Scriptor will give you an error message that may or may
not be on the line where your mistake is. The mistake will ALWAYS be on or before the line
in question.
Rule #5: The script 是从上到下读取. When starting or calling scripts, the script being called must always be placed before the script calling it, or you will get an “unexpected identifier” error.
Rule #6: 不管一个武器发射什么, 它的基本 scripting 是跟其他一样的。 武器的主要分别是 turreted 和 非turreted 武器 。
Rule #7: Script 名字始终遵循以" ( ) " ,,在这些里可能会有额外的信息,例如关于作者,但在大部分存在的只是空洞的空间之间的括号。
Most of these rules you won’t need for this tutorial, but they will be very useful to you in the future when you venture into some more complex stuff.
Ok, familiar with the rules? No? Well, never mind, just don’t forget they’re there for future use! 开始 scripting the beast! We’ll follow through in a step by step fashion to make this task easy. Don’t worry about how your tank is put together, it’ll work!
-
启动Lazy Scripter. 这是一个符合规则 1的程序 )。 它将为你的脚本建设一个骨架,节省您大量的时间和精力,做了很多枯燥的工作。 Where it says “3DO Filename”, clock on “Load”, and direct the program to your Tank model. 下一步要做的是为这个单位整理出所有的小细节, Over on the right, you can see a number of “check” boxes. “Can move” is enabled, and so it “Compatible With Unit Viewer”. Disable “Compatible With Unit Viewer”. 除非你的script 是非常复杂的, unit viewer 将能够处理好它, so this line is unnecessary, and a waste of space. 在左边你会发现 2 more “check boxes”, 一个标记 can fire (which should be enabled), 另一个标记 “Hide flares when not firing”. 如果你的模型没有可见的 flares (simply a point from which the weapon fires), disable “Hide Flares when not firing”.
下一步, 选择你的武器从那里瞄准。 This is done by selecting the piece beside where it says “Select a piece to aim from” This should be prettty obvious since the program already gives a hint, but just incase - the “turret” should be the piece that turns around to face the heading of the enemy target. The aim from piece must be either your turret piece or a child object, and should have it’s object origin as close to being in平面线形alignment with the barrels as possible. 如果你的模型有多于一个炮台, then you will need to enable the “Secondary turret” as well.。 三个炮台就需要 “Tertiary Turret” enabled.
最后你要在这个软件做的就是选择一个开火的位置。 有件小事你要明白的是 Lazy Scripter 不允许炮台有多于一个 barrel. But don’t fret, 我们可以在后面修正的. Just choose one of the firing pieces for the moment.
现在点击 “Create Script”. 用你的鼠标, 高亮 所有 script, 右击, and 选择 “Copy” (copy and paste?). So we 移动到真正的 scripting 程序… -
你有些东西要修正 in Scripter 在你 go into 这个程序前. Copy all of the files from the “include” subfolder into the main Scripter directory (you do this in Windows by the way, just incase you’re thinking we’ve started the program up
). -
启动 Scriptor V1.00. 在 File 单击 “New”. 粘贴所有你从 Lazy Scripter复制的 script 到新的 script, 然后保存文件为 你的单位的 codename 。 现在你准备好开始了。
-
看看你的 script的头部, 这是开头的几行, 包含 the “piece”, “static-var”, “#include” and “#define” lines. 可以从头部了解到几件事:
A) The piece line 应该包含每一个 object that you have in 3DO Builder. It does at the moment, but if you change pieces in your model after scripting it, you’ll need to make the changes in this line. The order of the objects is not important
B) 当你需要 一个 static var,你要放他的名字 into the static-var line so that Scriptor will 认识他。 先不要担心什么是 Static-var , 我们后面还会用到他们, 我待会会解析的。
C) The Include lines 告诉 scriptor which of the .h files to place in the script, 他们包含smokeunit, exptye, sfxtype, rockunit, hitweap, 和 stdtank. 我们要花一点注意在 Rockunit 和 Hitweap scripts 因为知道什么时候用他们什么时候不用是很重要的。 Hitweap script 使单位在受到武器打击时震动, So, since we’re building a tank we want this script to 增加额外效果。 如果我们 scripting 一个 机器人 或者飞机, though, we wouldn’t want them because it would 不好看 in TA 。 Rockunit script 使单位在发射武器时震动。如果你的坦克是载弹 (carries shells), 我们期待他是有后坐力的, 但如果你的坦克是载激光的, 它就不要后坐力了, 于是我们就可以删除这行! 同样,对于机器人和飞机,这行很少用。
D) The Define line instructs scriptor as to the value of certain variables. It can also be used to call piecenums (that’s the scripting word for an object of your model, like “turret”). 这时,你会看见一行写着 “#define SMOKEPIECE1 base” This line is telling scriptor that a variable talked about in the Smokeunit.h file is actually the base object. Easy, huh? You can have up to 4 smokepieces, 如果你想加多,简单地输入 #define SMOKEPIECE2 turrret" 在下面一条线。 Your first piece of scripting, and an 绝对轻而易举。 Just记住 that define和include lines 必须先 “#” so that Scriptor 知道你在说什么。 -
Ok, 现在你 得到你的 head around the header, we’ll move on to scripting the unit itself. 你非常高兴这个教程最难的部分已经结束了。)
We’ll start off by visiting the all-important Create() script. 所以从上到下找到它, 或者使用Scriptor的搜索工具 .
The script开始于 an opening bracket { 结束于 a closing bracket }. A script 可能有其他 opening and closing brackets with the use of “If” and “While” commands, and we will see where this can occur later on.
The create script is the first script called when a unit starts to build. You will see that it starts another script called “Smokeunit” (你的 #include section的一部分). 你在这里需要设置所有的 static vars’ initial values ,隐藏所有 flares 你不想被看到的东西。 要隐藏 a piece, 所有你要做的就是输入一行: hide “piecename” (不包括引号) followed by a semicolon.
例如 hide flare1;
hide flare2;
是的,这很容易, 现在隐藏你所有的flares 吧。 这是你这时要做的所有事 in create for this script )
现在, 我们转移到 aim script上来. 下翻直到你找到
AimPrimary(heading, pitch) script. The heading and pitch 信息告诉 TA这是 script incorporates a direction to a target in both x and y axes. 不要担心, though. All you have to know is that it’s there.
下一件事 你 see is “Signal SIG_AIM1” 接着 “set-signal-mask SIG_AIM1”. 这行保证在敌人目标移动时没有转到正对敌人武器不开火 , 所以是非常重要的。你不需要明白signals and masks yet, 但他们 提供一个办法 of killing 一个非预期的 script (by “masking”). If the heading or pitch of a target changes, the Aim script is re-called, and the signal cancels out the old running script.
删除 the line where it says “// Place aiming animation code here” 因为这是你现在要开始做的!
What we have to do is get our turret piece to转向面对 the heading, and the “barrel” to 转向面对 the pitch, without the unit firing before the pieces have turned into their position. The 速度 at which our turret and barrel(s) should turn would depend on the type of weapon we’re making, 例如, 某高射炮炮塔会要转弯速率约400,导弹塔200,中型坦克110 ,而伟大的重型坦克(如metron )少于60 。 What we do is turn the turret to face the heading and the barrel(s) to face the pitch:. The spikey括号 () 是用来 around any figures given in all 转向和自旋 命令。 移动命令是不同的, 使用方括号 [ ]. 这只是一项公约, but Scriptor will hate you if you do it wrong.
所有 statement lines are 用分号结束; 你问什么是statement? Well:
“你正在去商店” 是一个 statement, 因为我正在告诉你“你正在去一家商店。
“你在去商店吗?” 不是一个 statement, 是一个问题!
另一件要记的事是 “turn to” 实际意思是 “Turn Around”.我知道这是不正确的, 但 这是可行的方法
我假设你知道你的 x, y, and z axes (在 3DO Builder检查他们 如果你不肯定)
turn turret to y-axis heading speed <120>;
turn barrel1 to x-axis (0-pitch) speed <70>;
turn barrel2 to x-axis (0-pitch) speed <70>;
现在我们的炮台就转向 heading了 ,同时 炮管(barrels )(我的模型力有两个) 就转向 pitch. It is perfecly reasonablt to have your turret turning to the pitch. Simply because barrels are used by convention doesn’t mean that’s all you can use. 一件我忘记解析的是我们使用 (0-pitch). 不用管他, 那只是一个方法而已。
现在我们就要阻止了我们的炮台在面向目标前开火了。 为了这个我们使用 “wait” 命令, 如下:
wait-for-turn turret around y-axis;
wait-for-turn barrel2 around x-axis;
We have only waited for the second barrel to turn around the x-axis because if both barrels started from the same position at the same time, and at the same speed, it is reasonable to assume that both will arrive at the same time.
下一行已经为你做好了, it says “start-script RestoreAfterDelay();” If you have a look around, 你会返现这 script, and see that it is again requesting for animations. We will tackle that next.
The Return 1 line 在尾部 of the AimPrimary is unusual, telling the script to re-start. Most scripts 使用 return 0 (and it is the default line at the end of any script, even if you can’t see it, unless otherwse specified).
现在你的 AimPrimary 应该看起来是这样的
AimPrimary(heading, pitch)
{
signal SIG_AIM1; 瞄准1
set-signal-mask SIG_AIM1; 设置瞄准1标记
turn turret to y-axis heading speed <120>; 以120的速度将炮台转到目标Y坐标
turn barrel1 to x-axis (0-pitch) speed <70>; 以70的速度将炮管1转到目标X坐标
turn barreel2 to x-axis (0-pitch) speed <70>; 以70的速度将炮管2转到目标X坐标
wait-for-turn turret around y-axis; 等待炮台转到目标Y坐标
wait-for-turn barrel2 around x-axis; 等待炮管2转到目标Y坐标
start-script RestoreAfterDelay(); 启动script在延时后
return(TRUE); 返回
}
Rightio! 完成了. The FirePrimry() script is next, so take a look for it. This script tells the unit what to do when the weapon is fired. There is already a default setup in there. But we can add to that. Again, don’t worry if your turret has more than 1 barrel, just follow through, and we’ll come to that. Currently the fire script has show/hide flare with a sleep command in between. If you don’t have a visible flare (just a fire point), delete the 2 flare lines.
首先,你可能想炮管有后坐力吧,是吗? This is pretty simple to do, and 我们使用 MOVE 命令做到它. 我们希望炮管快速后移, 等待一下, 然后慢慢的回去,是吗? So, here’s how we do it, 沿着 z-axis移动炮管. Please note that if the barrel is aiming upward, and you move it along the z-axis, it will still move correctly, because the definition of the z-axis is built into the object itself. So, the barrel won’t move through the top of the turret just because it’s aiming upward. If you don’t understand, don’t worry. It will occur to you later. :
FirePrimary()
{
Show flare1; 显示开炮火光1
move barrel1 to z-axis [-1.5] speed [200]; 以速度200沿着Z轴将炮管移动1.5
sleep 150; 静止150
move barrel to z-axis [0.00] speed [2]; 以速度2沿着Z轴将炮管移到0.00
hide flare1; 隐藏开炮火光1
return 0; 返回0
}
The flare is shown, and the barrel starts moving at the SAME TIME because there are no sleep or wait-for commands in between. Similarly, the flare disappears, and the barrel starts to return at the same time. Sleep commands are calculated in milliseconds. So the script waits for 150 milliseconds before restoring the pieces. The Return 0 is particuarly important in the AimPrimary script, as the script can become troublesome if it is not present. It is good practice to include return 0 at the end of any scripting function, with the exception of the aim script.
移动炮管的距离根据你的模型大小而定. I have just typed in [1.5] there, because it’s a reasonable average figure. When you test your script, you might find it too bit or too small, but it’s easy changed, right?
如果你只有 一个炮管 script, well done! 你的 aim script 已经完成了!
如果你有多于一个炮管, 你就要知道多一些关于 Static Vars (即使你完成了你的 fire script, 我仍建议你看看这个). 他们是很重要的一部分of TA scripting,有一天你将会大量的使用在各种任务).
那什么是 Static Var?
A Static var 是一个命名变量, 它可以被赋予你给予的何时何地的值。 这就是它! 那它在那里有用呢? Well, you can assign IF and while commands, 像这样s
IF (MyStaticVar = = 1)
{
blah blah blah…
}
See the use?
现在我会解析上面的statement in detail when we get to it, but for now, we need to create a static var for our function because we need to use an “if” command in order to get our barrels working…
static-vars最棒之处是你几乎可以叫它任何名字 (except ones that conflict with other functions like ARMORED, HEALTH etc. You will know if you’ve accidently bumped into one.) 到你的 Static-var line, 加入你的名字. 可以是任何你选择的名字, 只要你能记住它。 传统上, 我们称 枪类为 “gun1” for the primary, “gun2” for the secondary etc. 但你可以不用
现在你的 static-var line 应该是这样的 (不要忘记之间的逗号!):
static-var Restore_Delay, Gun1;
Next, it’s always good practice to give your static var a starting value. It doesn’t matter what it’s for. So, go to your create script, because this is the first script called when a unit starts building, and give it a value. You can put this anywhere in the script, but maybe best to keep the static vars together, so add the line below Restore_Delay = 2000;
Gun1 = 1;
这不是很难吧? The next bit isn’t either. So, 现在把它应用到我们的 FirePrimary script. This is where the “If” command comes in. There are a few conventions with If commands:
-
你的 static var 是放在 IF 命令间的括号里, showing Scriptor what you’re talking about. Some commands can also be used within the IF statement, including AND, + - * / , OR. These won’t be of any help to you yet, but in a later tutorial, you might see them cropping up.
-
When typing the IF command, and you have an equal to in the query, always put 2 equals like this = = (无空格)
-
Whatever you open, you close! Every IF command requires you to open a bracket, signifying the start of the command, put your closing bracket at the point where you wish the influence of the If command to stop. It’s as simple as that!
Now, since our Static Var starts as equal to 1, our IF command has to be able to handle that. What to do is include all of your original Fire script within the IF Statement. We can change the value of our Static Var command within the IF statement. The statement will still run through to the end, even if the variable is no longer equal to 1 after it starts. We will also see here an instance of where return 0 is used before the end of the script.
FirePrimary
{
IF (Gun1 == 1) // there’s 2" = " there! The value is kept within standard brackets.
{ // Here’s your opening statement
Show flare1; // notice how I have moved all of the info in the lines to be in vertical alignment
Gun1 = 2; // with the opening/closing brackets? Makes the script much easier for the writer
move barrel1 to z-axis [-1.5] speed [200]; // to read (unlike this statement which is messy)! ![]()
sleep 150;
move barrel to z-axis [0.00] speed [2];
hide flare1;
return 0; // We want the script to finish here, because it has done all the work we want it to.
} //And here’s your closing statement!
}
Now, within the IF statement, we hanve changed the value of our static Var. Now… how can we use this? Well, if we call the script again, we know that Gun1 is going to be equal to 2, therefore the script will ignore all of the info within our IF query. So, we can either add our info for the second barrelbelow our IF query, or create another IF statement, and put the info in there. I am going to take the second option, because it makes the script more clear. Obviously our IF command will be IF the static Var is equal to 2. And in here, we will give all the info of the first IF command, except we will change it to apply to the second barrel:
IF (Gun1 == 2)
{
Show flare2;
Gun1 = 1;
move barrel2 to z-axis [-1.5] speed [200];
sleep 150;
move barre2 to z-axis [0.00] speed [2];
hide flare2;
return 0;
}
See? Exactly the same except all the move commands and show flare are applied to barrel 2, and Gun2 becomes equal to 1 again ![]()
So, now your Fire script looks like this:
FirePrimary()
{
IF (Gun1 == 1)
{
Show flare1;
Gun1 = 2;
move barrel1 to z-axis [-1.5] speed [200];
sleep 150;
move barre1 to z-axis [0.00] speed [2];
hide flare1;
return 0;
}
IF (Gun1 == 2)
{
Show flare2;
Gun1 = 1;
move barrel2 to z-axis [-1.5] speed [200];
sleep 150;
move barre2 to z-axis [0.00] speed [2];
hide flare2;
return 0;
}
}
A nice piece of scripting, eh? If your turret has 3 barrels, you would obviously make Gun1 equal to 3 in the last statement, and create a third IF command, that would bring it back to 1.
The next script to tackle is the mysterious QueryPrimary script. This script tells the unit where to fire from. If you have only 1 barrel, you don’t need to do anything here, because you already set the value with Lazy Scripter. If you’ve got more than 1 barrel, then you will need another IF command, but you can use your old static var, since it already covers which barrel is firing.
Currently your QueryPrimary() looks like this:
QueryPrimary(piecenum)
{
piecenum = flare1;
}
But if you have more than one barrel, then obviously the weapon shouldn’t be leaving from the same place every time. You’ve probably already figured how to do this (I hope I’m not turning you into a vegetable here). Just remember that you don’t want to change the value of your static-var in this script:
QueryPrimary(piecenum)
{
IF (Gun1 == 1)
{
piecenum = flare1;
return 0; // because the script has now done all the work we want it to do - good practice!
}
IF (Gun1 == 2)
{
piecenum = flare2;
return 0;
}
}
Not hard, eh? It only gets easier from here! QueryPrimary is finished!
Now, we want our turret and barrels to restore to their starting positions if the unit hasn’t fired in a while. So, head over to the RestoreAfterDelay script. This is baby’s stuff to you now. So far all you’ve got is :
RestoreAfterDelay()
{
Sleep Restore_Delay;
// add some stuff here!!
return 0;
}
Now, all we have to do is tell our turret and barrels to turn back to “0” after sleeping for the Restore_Delay time. So, it’s as simple as this:
RestoreAfterDelay()
{
Sleep Restore_Delay;
turn turret to y-axis <0.00> speed <80>; // Remember you can set speeds to whatever you like!
turn barrel1 to x-axis <0.00> speed <50>;
turn barrel2 to x-axis <0.00> speed <50>;
return 0; // there are no wait-for commands here, because we don’t want to wait for anything to
} // happen! (It is a common mistake by newbies to add it, so don’t!)
Done ![]()
Your script is basically finished! All you have to do now is sort out a few cosmetic things… Go to your Killed script. You will see loads of lines of pieces exploding. There are 4 sections to the script, depending on “Severity” (= Health Percent lost, or would have been lost in fatal blow I think). For the largest part of your tank - the bit with all of the hull (which you’ve probably named base or body), we don’t want it to fly around in the air if the tank is hit hard by an enemy weapon, right? Now at the moment, it will for the last 2 sections of this script (Explode piecenum type FALL | SMOKE | FIRE | EXPLODE_ON_HIT | BITMAP2; sends the piece flying around the screen emitting fire and smoke. But we don’t want that. The biggest thing that could happen to our tank is for it to shatter, so… Delete the line exploding your body/base piece in the last 2 sections of the Killed Script, and add the following line instead:
explode base type SHATTER | BITMAP4;
The info pieces are separated by | It’s on your keyboard at the bottom left - broken line above back-slash \ Got it?
Right. That’s it. Your script is done! Try compiling. If it compiles, you’re in business, put it into your scripts folder for your unit, pack, and fire up TA. If not, then have a look to see where your error is. The chances are that you are missing a semicolon, or an end bracket. It’s usually something silly like that ![]()
Hope you found this tutorial useful ![]()
M. Kenyon
[ 本帖最后由 Defiler 于 2008-4-27 20:22 编辑 ]
留意我汉化的部分就基本可以完成了:victory: :victory:
你的意思是将其中一个炮台的武器换成其他武器吧,具体要在那里指定我还不知道,
大致是你先用3dobuilder打开模型,先了解每个组成结构,例如你要改那个炮台,就要知道这个炮台整个结构的名字,然后用Scripter在script文件中找到那个名字,改变其武器类型应该就可以了。
有Primary的就是第一武器
有Secondary的就是第二武器
有Tertiary的就是第三武器
估计只要你将你要改的那一部分的Primary换成Tertiary就可以了,不过我没试过。
我模型导入失败,已经基本放弃了。
[ 本帖最后由 Defiler 于 2008-4-27 20:43 编辑 ]
谢谢 Defiler 改好了 告诉你:lol