Board logo

标题: [教程] 世上之最——独霸武林《结合篇》 [打印本页]

作者: 但偏偏雨渐渐    时间: 2006-2-28 09:34     标题: 世上之最——独霸武林《结合篇》

<;P>====这里是一些很初级的问题收集,比如“地图编辑器是什么、在哪里”=====——U9
<;P>Q什么是地图编辑器?如何打开?

地图编辑器是Blizzard(暴雪:魔兽争霸的制作组织)提供给所有玩家的创建和编辑属于自己的地图的工具。在WAR3(魔兽3)的游戏目录下找到World Editor(世界编辑器),双击打开,这个就是地图编辑器。
<;P>Q什么是Object Editor?

Object Editor就是对象编辑器,其中包含了单位编辑器,技能编辑器,装饰物编辑器,科技编辑器等,可以允许地图制作者修改已有的上述对象或者建立新的对象。
打开对象编辑器的方法是在地图编辑窗口按F6或者点击快截工具栏中的头盔样按钮。
Q什么是Trigger?

Trigger就是触发器,在地图编辑窗口按F4或者点击快截工具栏中的带有a字的按钮即可打开Trigger Editor(触发器编辑器)。
触发器是地图编辑器中用于控制地图中所发生的事件的工具,一个基本的触发器由Event(事件),Condition(环境/条件),Action(动作)三部分组成。下面用一个简单的例子来说明这三部分之间的关系:
“你在此论坛提出的有价值的问题都会得到解答”
如果将上面这句话看做一个触发器,那么“你提出问题”就是整个触发器的Event(事件),接下来要发生的一切,不管是“我们为你解答问题”或者“我们不理会你”,都是在“你提出问题”之后发生的。
而限制你所提出的问题是否会得到解答的条件则是“你提出的问题有价值”,也就是整个触发器的条件,这个条件直接影响你“是否得到我们的解答”。
最后,当你提出的问题满足“有价值”这个条件的时候,就会发生“我们为你解答问题”这个动作,也就是整个触发器的动作。

Q什么是JASS?

JASS是用于编辑地图的一种简单的语言,可以说是文本化以后的触发器(地图脚本:MAP SCRIPTS),但是由于触发器并没有提供JASS所具备的所有功能,所以可以说JASS在某种意义上是触发器功能的扩展。
编辑JASS可以通过以下三种途径:
1, 在触发编辑器(TRIGGER EDITOR)中,通过 MENU -> EDIT -> CONVERT TO CUSTOM TEXT 可以将当前选定的触发转换成脚本模式,也就是以JASS编辑的模式。
2,在触发编辑器中点击触发树(TRIGGER TREE,就是最左边列出所有触发的地方)的最顶端地图名,可以进入自定义脚本功能块,在这里可以用 JASS 写需要的函数,并且在其他的触发器中通过命令来调用。


3,使用 ACTIONS 中的 CUSTOM SCRIPT 动作可以在触发中插入一行 JASS 脚本代码。

Q什么是“高级-游戏平衡常数”(英文名称Advanced - Gameplay Constants)

最上方菜单左起第7个菜单上数第4个选择,这个选项里面包括了很多不能用T修改但是很有用的设置。比如买卖东西的距离,各种攻击类型对防御类型的伤害,英雄的等级经验复活数据等等。

Q地图扩展名中的w3m,w3x,w3n,w3g分别是什么意思?

w3m:混乱之制(roc)版本的地图。
w3x:冰封王座(tft)版本的地图。
w3n:战役地图,这类地图必须放在War3(魔兽)目录下的Campaigns(战役)文件夹中才能使用。
w3g:游戏录象,位于War3(魔兽)目录下的Replay文件夹下。

E:地图类型解释

Melee - 对战地图,即 War3 默认的游戏方式,BN Ladder 指定游戏类型。
Non-Melee - 除了 melee 以外的所有类型统称。
Custom - 非官方地图,但是通常表示 非官方的 non-melee 地图。
RPG - Role Play Games(角色扮演)~~但是现在很多人把所有 Non-Melee 地图都叫成 RPG。
Mini - 迷你游戏,通常指没有突出剧情、快节奏、游戏周期短的地图,没有固定的游戏方式,不含 rpg 。
Offence - 通常是对抗性地图统称,有时也表示一些进攻npc为主题的地图。
3C - Offence 的一种,本来只是一个地图的名称,通常是指 有 3条进攻路线的 Offence 。
Arena - Offence 一种,竞技场,通常是指选定英雄后在固定区域内进行决斗的地图。
Defence - 通常是指防守性地图统称,有时候也表示一些在非平衡的 NPC进攻前提下的防守与反攻。
TD - Defence 的一种,建造 Tower(炮台) 防守 NPC 有规律的进攻。
Cutscene - 通常是指剪辑影片,内容比较简单。(非 CG )
Cinematic - 通常是指完整影片,内容比较丰富。(非 CG )


在掌握了以上基础知识以后,您可以试着看看其他内容

[ 本帖最后由 龙小天 于 2006-12-28 20:35 编辑 ]
作者: 但偏偏雨渐渐    时间: 2006-2-28 09:34

JASS研究-关于JASS函数调用中模拟传递数组参数

作者:白银の游戏王 文章来源:GA 点击数:

  1. &lt;SCRIPT language=javascript src="/war3rpg/GetHits.asp?ArticleID=8224"&gt;<br><br>&lt;/script&gt;
复制代码
2298 更新时间:2005-12-13

突然想到的一个系统...

需要该系统的地方:有些时候调用函数时觉得不传数组麻烦,但又不想用全局数组
系统需求:Handle System
首先是代码:
//==============================================
function H2Q takes handle h returns quest
return h
return null
endfunction

function CreateArrayInt takes integer size returns handle
local handle harray=CreateQuest()
local integer i=0
loop
exitwhen (i>=size)
call SetHandleInt(harray,I2S(i),0)
set i=i+1
endloop
call SetHandleInt(harray,"SIZE",size)
return harray
endfunction

function DestroyArrayInt takes handle h returns nothing
call FlushHandleLocals(h)
call DestroyQuest(H2Q(h))
endfunction

function GetArrayInt takes handle h,integer p returns integer
local integer s=GetHandleInt(h,"SIZE")
if (p<s) then
return GetHandleInt(h,I2S(p))
else
return 0
endif
endfunction

function SetArrayInt takes handle h,integer p,integer value returns nothing
local integer s=GetHandleInt(h,"SIZE")
if (p<s) then
call SetHandleInt(h,I2S(p),value)
endif
endfunction
//==============================================

系统解说:
暂时包含4个主函数,1个辅助函数,模拟Integer数组的传递
1====function CreateArrayInt takes integer size returns handle
功能:创建一个模拟Integer数组,并初始化为0
参数:
integer size -> 指定创建的数组的容量
返回值:模拟数组句柄

2===function DestroyArrayInt takes handle harray returns nothing
功能:销毁一个模拟数组
参数:
handle harray -> 指定欲销毁的模拟数组句柄
返回值:无

3===function GetArrayInt takes handle h,integer p returns integer
功能:得到数组中指定位置的值
参数:
handle h -> 数组句柄
integer p -> 下标
返回值:数组中指定下标位置的值
PS:如果下标超过了数组最大容量,则返回0

4===function SetArrayInt takes handle h,integer p,integer value returns nothing
功能:为数组中指定位置的赋值
参数:
handle h -> 数组句柄
integer p -> 下标
integer value -> 欲设定的值
返回值:无
PS:如果下标超过了数组最大容量,则无操作

Sample:
function B takes handle harray returns nothing
local integer i=0
loop
exitwhen i>=10
call DisplayTextToForce(bj_FORCE_ALL_PLAYERS,I2S(GetArrayInt(harray,i)))
set i=i+1
endloop
endfunction

function A takes nothing returns nothing
local handle harray=CreateArrayInt(10)
local integer i=0
loop
exitwhen i>=10
call SetArrayInt(harray,i,9-i)
set i=i+1
endloop
call B(harray)
call DestroyArrayInt(harray)
endfunction

缺点:
1.比直接控制数组慢(如果觉得慢的无法忍受就表用了)
2.输入/输出比直接用数组稍麻烦(仅仅是“稍微”)

本系统经本人测试通过...


作者: 但偏偏雨渐渐    时间: 2006-2-28 09:36

[WE] 3C的英雄选取系统制作教程

说到魔兽争霸3大家肯定不会陌生,那么各位在玩过特色各异的地图以后有没有想过自己动手做一张地图?摇头拒绝的家伙们听我把话说完,其实做一张地图并不是各位想象的那么困难。下面我将会简单介绍一下集合了几种常见功能的地图的制作方法,有兴趣的朋友不妨跟着做做。
这次要做的是一个3C中的人物选择功能,也就是当小精灵进入能量圆的时候选择对应的英雄,这是一个3C最普通的选人功能。那么动手了。
首先找到地图编辑器,编辑器位于魔兽目录下,名为WorldEditor.exe(世界编辑器),双击打开。第一次使用地图编辑器,系统会自动为我们创建一张64*64大小,环境为罗丹仑的夏天的新地图。如果想要手动创建新地图,可以通过点击菜单栏的文件 - 新地图/File - New Map来创建。如果想要关闭在打开编辑器的同时创建新地图的功能,可以同过选择文件 - 参数设置 - 常规 - 打开时创建新地图/File - Preferences - General - Create a new map on start_up,将前面的勾去掉来实现。
地图创建完毕以后看见的就是这个地图编辑器的组成了,按2下G关闭坐标格的显示。在制作上面提到的功能以前,让我们先做点准备工作。首先既然是选择英雄,那么英雄自然是必不可少的,按U打开单位编辑面板,在这里可以选择我们所希望的单位放置到地图上,我选择了恶魔猎人(Demon Hunter),血巫师(Blood Mage)和巫妖王(Lich King),当然各位如果看上其他英雄请随意,这并不会影响后面的制作。顺便说说在单位面板中切换种族的方法是在第三行左边的那个扩展菜单里面选择希望的种族,由于选择英雄的时候所看见的英雄是不被我们控制的,必须选择了以后才能控制,因此一般的做法是将英雄更改为中立单位,更改的方法是双击放置在地图上的英雄,选择常规 - 玩家 - 中立无敌意/General - Player - Neutral Passive。注意各英雄之间不要间隔太远,否则让小精灵跑来跑去的很麻烦。放好英雄以后当然还要在英雄面前放个能量圆作为小精灵进入选择用,能量圆可以在单位面板的中立敌对分支中找到。最后再放上选英雄用的小精灵,由于多个玩家的选择英雄的原理是相同的,所以这里我们只做3个玩家的选择,因此只放属于3个势力玩家的小精灵。如图:]至此,准备工作就算是完毕了,接着开始做功能部分,要用到触发器。
由于是初次介绍,为了不扰乱大家的思维,所以我对触发器的原理不做太多的介绍,大家只需要知道触发器的作用就是可以以事件的方式来实现一些功能就可以了。按F4打开触发器编辑器/Trigger Editor,删除默认的那个触发器,那是为MEELE准备的。可以看见在魔兽地图编辑器中,一个触发器是由事件(Events),环境(Conditions),动作(Actions)三部分左右,这三个部分之间的关系可以用一个简单的例子说明:“火药接触火以后爆炸”。在这里,火药与火接触就是事件,只有二者接触才会发生以后的动作;而火药接触的对象必须是火才会爆炸,所以火在这里作为环境,限制火药爆炸需要的条件;火药爆炸就是动作,是在与火接触以后引发的动作。在触发器里面我们可以根据需要自己修改事件,环境,动作这三部分的内容,比如可以将火药与火接触爆炸改为与水接触爆炸。那么有了以上概念,来看看选择英雄的制作方法,首先英雄必须在发生了一个事件以后才会被选择,而这个事件在这里就是:小精灵进入能量圆;但是在这里必须限制只有小精灵进入能量圆的时候英雄才会被选择,其他种类的单位进入则什么都不会发生,于是整个触发的环境 - 也就是限制条件也有了,就是:进入能量圆的单位类型是“小精灵”;最后就是动作了,英雄被选择,其实选择英雄的动作就是把英雄的从中立单位更改为玩家势力控制的单位。把上面所说的步骤以触发的方式写出来就是这样的:
事件(Events)
一个单位进入能量圆范围内

环境(Conditions)
进入的单位的类别是“小精灵”

动作(Actions)
把能量圆对应的英雄的控制者改为选择英雄的玩家

现在再按照写出来的触发在地图编辑器中寻找对应的选项。
创建一个新的触发/New Trigger,方法是在触发编辑器右方的窗口中按鼠标右键选择新<触发器/New Trigger>,新触器发会被自动命名为“为命名触发00X”,触发器的名字可以通过在选择触发以后按F2来修改。然后点击新建的那个触发,在右下方的触发编辑窗口中鼠标右键,选择<新事件/New Event>,在出现的选单中选择<单位 - 单位进入区域/Unit - Unit Enters Region>,接着<点击红色字体部分 - 选择区域/- Select Region>,这时候窗口会自动切换到大地图,要求我们选择一个区域,这里要解释一下在魔兽中,我们平时所看见的例如进入能量圆,或者进入花园,进入洞穴诸如此类“进入某个地点”的情况,其实并不是进入了我们看见的地方,而是进入了事先放置在能量圆,花园,洞穴等位置上的一个区域(Region)。而现在我们要做的正是放置这么一个区域并且在事件中选择他作为小精灵进入的区域,在大地图上可以看见面板已经自动切换到区域面板(直接打开区域面板的快截键是R),点击面板上坐标样的按钮使之处于按下的状态,按住右键拖动鼠标在能量圆上画一个和能量圆大小差不多的区域出来,再次点击面板上的按钮使之处于弹起的状态,然后点选刚才放置的区域,会自动切换回触发编辑窗,红色字体部分也会被刚才所选的区域的名字取代,连续确定2次,事件便做好了。如图:

接着是环境/Condition,选择<新环境 - 单位类型判断/New Conditions - Unit Type Comparison>,将进入区域的单位类型限制为“小精灵”,操作结果如图:

其中Entering Unit的意思是“进入单位”这里指进入区域的单位,Equal to的意思是“等同于”。
最后是动作/Actions, 在这里先整理一下有哪些动作需要执行:

1,由于选择好英雄以后小精灵会消失,所以在动作的开头要从游戏中移除小精灵。
2,更改被选英雄所属的势力为玩家操纵的势力。
3,将选好的英雄移动到指定位置,也就是3C中的基地。
4,由于英雄只能被选择一次,所以在动作的最后要关闭整个触发使之不再执行。
对应以上4条的动作分别是:
1,<新动作 - 单位 - 移除 - 从游戏中移除进入单位/New Action - Unit - Remove - Unit - Remove (Entering unit) from the game>;
2,<新动作 - 单位 - 改变拥有者 - 改变恶魔猎人的拥有者为进入单位的拥有者并且改变颜色/New Action - Unit - Change owner - Unit - Change ownership of Demon Hunter 0002 <gen> to (Owner of (Entering unit)) and Change color>;
3,<新动作 - 单位 - 移动 - 移动恶魔猎人到区域001的中心/New Action - Unit - Move Demon Hunter 0002 <gen> instantly to (Center of Region 001 <gen>)>当然区域001也是自己创建的区域;
4,<新动作 - 触发 - 关闭此触发/New Action - Trigger - Turn off (This trigger)>
全部完毕以后的动作如图:


这样整个触发就完成了,对照这个触发再将选择另外2个英雄的也完成。最后保存地图,保存的时候会提醒你为每个势力放置开始点,如果没有放置,会自动为你在地图任意区域放置,手动放置的方法是在单位面板中选择开始点的图标然后进行放置。保存地图以后按Ctrl + F9测试一下吧~。另外别忘记在菜单栏<设定 - 玩家/Scenario - Player>中将势力2和3的控制者设置为玩家/User,否则在游戏里就不能选择势力2,3了。


作者: 但偏偏雨渐渐    时间: 2006-2-28 09:37

[WE] 3C系统制作之2-刷兵-关于周期事件的实现

上一期我介绍了关于3C地图中最常见的使用小精灵选择英雄的触发器制作方法(关于触发器的概念上一期已经讲过了,我就不再重复了),而这次要讲的仍然是3C触发器的重要组成部分:刷兵(有的地方把这个叫做孵蛋,我完全不能理解…………)。简单解释就是每隔一定时间产生一些单位在基地附近,那么废话不多说,下面开始介绍怎样制作。

大家都知道在3C中兵是每隔一定时间就会自动产生的,在触发器中,我们将这种每隔固定时间就会自动发生一次的事件叫做“周期性事件”,一般来说经常通过以下两种途径来实现事件的周期发生:
==========================方法1=========================================
第一种是通过触发器中的循环事件来实现的(也有将这个叫做回圈的),在触发器中新建一个Action(动作),在下拉菜单中找到这样的句子——For Each Integer A,Do Multiple Actions(对于所有的整数数值A,执行若干动作),点击确定以后会看见在Actions(动作)这个类下面已经增加了这样的一个Action(动作):

For each (Integer A) from 1 to 10, do (Actions)
Loop - Actions
(对于所有的整数值A,从1到10,执行动作
循环 - 动作)

[图:loop1.gif]

我详细解释一下这个Action的作用,For each (Integer A) from 1 to 10(对于所有的整数值A,从1到10)的意思是重复执行10次Loop - Actions(循环 - 动作)中指定的Actions(动作),同样的道理如果将后面的from 1 to 10(从1到10)改成from 1 to 20(从1到20)那么就会重复执行20次动作,假设是from 5 to 10则只会执行5次动作,至于为什么不直接用from 1 to 5来代替from 5 to 10,这是在某些时候必须用到的功能,至于具体使用的时机,为了不使大家头脑混乱,现在暂时不做解释,等到实际使用中遇到类似情况再做说明。
--------------------------范例-------------------------------------
现在为了更形象的说明这个功能,我们来做个简单的范例,按F4打开触发器编辑器,新键一个Event(事件):Player - Player 1 (Red) skips a cinematic sequence“玩家 - 玩家 1(红色)跳过一段电影序列”,这个事件的建立方法是鼠标右键 - New Event(新事件) - Player(玩家) - Cinematic Skipped(电影被跳过),这个事件的作用是当玩家1按下ESC键的时候就会触发动作。接着增加一个动作

For each (Integer A) from 1 to 10, do (Actions)
Loop - Actions

这样就将需要重复执行动作的次数定为10次,然后在Loop - Actions下面依次添加这些动作:
Game - Display to (All players) the text: (String((Integer A)))
(游戏 - 向所有玩家显示信息 : 将作为循环序列的整数A的值转换为字符串类型[关于数据类型,这里不多做解释,大家只需要知道只有字符串类型的数据才能被作为信息显示出来就可以了]。在这里“作为循环序列的整数A”其实就是用来记录已经重复执行了多少次动作的一个数值。)添加这个动作的顺序为New Action(新动作) - Game(游戏) - TextMessage(Auto-Timed)(显示信息,自动调整信息显示时间)
Wait 1.00 seconds
(等待1.00秒,这样在每次执行动作以后都会间隔1秒才执行下一次动作)添加这个动作的顺序为New Action(新动作) - All(所有) - Wait(等待)。

然后在整个循环Action(动作)的后面(注意,是在整个For Each Integer的后面,不要添加到Loop - Actions下面去了)添加这个Action(动作):
Game - Display to (All players) the text: (finish)
作用是在整个循环结束以后显示一句话以标明循环结束了。当然其中的finish大家可以随自己爱好随意更改。现在这个触发应该是这样[图:loopexm.gif]


最后将Melee Initialization(地图初始化)这个触发删除掉,在地图上放置玩家开始点,按Ctrl + F9进游戏测试,可以看见在游戏中当按下ESC键以后会分10次每秒一次依次显示数字1~10,最后则会显示finish。通过这个例子可以很清楚的看出。For each (Integer A) from 1 to 10, do (Actions)这个动作可以让位于Loop - Actions下面的动作重复执行from 1 to 10中后面数字+1减去前面数字的次数,而当所有的重复次数被执行完毕以后,则会继续执行整个循环后面的动作。这样就很简单方便的实现了周期性事件的执行,但是用这个Action(动作)实现的周期性事件有两个弊端,第一是循环执行的次数有限,大家也看见了,在这个Action中无论如何也要求输入2个数字以确定执行次数;第二是每次执行动作之间的时间间隔有最小限制,在上面的例子中,大家将Wait 1.00 seconds(等待1秒)改为Wait 0.00 seconds(等待0秒)以后进入游戏测试,会发现即使是0秒,也会有微小的等待时间(大概0.1~0.4秒左右,视电脑配置而定),这样在执行某些重复时间间隔很小的周期性事件的时候,就完全无法实现了,对于必须排除以上两种限制的周期事件,就必须用到另外一种方法,periodic event(周期循环事件),和For each Integer不同的是,这是一个Event(事件)而不是一个Action(动作)。
========================================================================
==========================方法2=========================================
添加这个事件的方法:New Event(新事件) - Time(时间) - Periodic Event(周期事件),添加完成以后可以看见在Event这一类下面出现了这样的Event(事件):

Time - Every 1.00 seconds of game time
(时间-每1.00秒游戏时间)作用很明显,就是每1秒都会执行一次Actions(动作)中包含的所有动作,Every 1.00 seconds中的数字用于指定每多少秒执行动作。对于这个事件的功能,我们仍然可以用1个简单的范例来说明。
--------------------------范例-------------------------------------
新建一个触发器,Event(事件)就用上面那个事件,将1.00调整为0.50,也就是每0.5秒执行1次,然后按下Ctrl+B打开变量编辑面板,(由于变量是第一次接触,所以我暂时不详细说明,大家按照我说的做就是了,以后会对变量和数据类型做详细介绍。)点击面板上方的绿叉按钮,在出现的窗口中下方的下拉菜单选择Integer(整数)然后在上面的输入栏中为这个变量随便起一个名字,[图:var.gif]这里我用的名字是i1便于下面统一介绍,这样就建立好了一个类型为“整数”型的变量。暂时将这个变量放在这里备用,回到刚才建的触发,在Actions(动作)类中添加如下动作:
Set i1 = (i1 + 1)
添加顺序:New Action(新动作) - All(所有) - Set Varible(设置变量)
这个Action(动作)的作用是每次循环执行动作的时候让i1这个整数的值等于它当前的值+1,比方i1当前的值是5那么执行动作以后i1的值就是5+1,也就是6。
接着添加:
Game - Display to (All players) the text: (String(i1))
现在的触发是这样的[图:loopexm2.gif]


添加方法同上,作用是显示i1的值。
然后进入游戏测试,会看见在游戏中将自动以每0.5秒的速度显示数字,数值为上一次显示的数字+1。由此总结出Periodic Event(周期循环事件)的特点是会在激活触发以后以Event(事件)中规定的时间间隔来重复执行Actions(动作)中包含的所有动作,并且只要该触发没有被关闭,就会一直执行下去。
========================================================================
以上就是两种最常见的周期性事件的实现方法,那么在此理论基础上我简单叙述一下刷兵触发的原理。
刷兵触发就是一个周期事件,其动作的内容就是在指定位置创建单位,下面我简单的将这个触发写一下,并且加上少许说明。相信大家在对上面所讲的内容理解了的情况下应该立刻明白其中的道理。
Untitled Trigger 003
Events
Time - Every 3.00 seconds of game time [这个就是前面讲到的周期事件,在这里将周期的时间间隔设置为3秒]
Conditions
(Farm 0009 <gen> is alive) Equal to True [这里Farm 0009 <gen>是一个农场,整个Condition(条件)的意思是,如果农场0009仍然生存,则继续执行Actions(动作)中的指令]添加这个Condition的方法是New Conditions(新条件) - Boolean Comparison(布尔判断,也就是逻辑判断) - 选择图示位置[图:boolean.gif] - Unit-Unit is Alive(单位 - 单位仍然生存)
Actions
Unit - Create 1 Giant Wolf for Player 1 (Red) at (Position of Farm 0009 <gen>) facing Default building facing degrees
[单位 - 为玩家1(红色)创建一只狼在农场0009所在的位置面向系统默认的方向]
如图所示,现在整个触发应该是这样[图:create.gif]


整个触发如果用语言表达的意思就是,每隔3秒钟只要农场0009依然存活,就创建一只狼在农场所在的位置。
进入游戏进行测试以后,大家应该不难发现这个触发有这样一个弊端:创建的单位没有数量限制,哪怕地图上已经有了几百,几千只狼,只要农场0009仍然存活,就会不断有新的狼产生,对于这种情况,我们可以通过加入如下的一个简单条件来给予限制:
(Number of units in (Units in (Playable map area) matching (((Unit-type of (Matching unit)) Equal to Giant Wolf) and (((Matching unit) is alive) Equal to True)))) Less than 5
整句条件的意思是,如果地图上所有存活的狼的数量小于5只,则继续执行Actions(动作)类中指定的动作。其中units in Units in (Playable map area) 就是指整个地图上的单位,而(Unit-type of (Matching unit)) Equal to Giant Wolf是指符合“单位类型为狼”这个条件的所有单位,(Matching unit) is alive) Equal to True是指所有“仍然存活”的单位。由于这个条件比较复杂,下面列出详细的添加方法:
New Conditions(新条件) - Integer Comparison(整数判断)

- 点击图示位置[图:count1.gif]

- 点击图示位置[图:count2.gif]

- 在下拉菜单中选择“Unit in Region Matching Condition(区域内匹配条件的单位)”

- 点击图示位置[图:count3.gif]

- 在下拉菜单中选择“And” - 点击“Condition1(条件1)” - 在下拉菜单中选择“Unit-Type Comparison(单位-类型判断)”

- 点击图示位置[图:typec.gif]

- 点击“Triggering Unit(触发单位)”将之改为“Matching Unit(匹配单位)” - 连续确定2次,点击“FootMan(步兵)”将之改为你在Action(动作)中所指定的生产单位种类,在这里我选择的是“狼”,这时候的Condition1(条件1)应该是这样[图:con1.gif];


接下来点击“Condition2(条件2)” - 点击图示位置[图bolc.gif] - 在下拉菜单中选择“Unit is Alive(单位仍然存活)” - 点击“Triggering Unit(触发单位)”将之改为“Matching Unit(匹配单位)”,连续确定2次,这时候的Condition2(条件2)应该是这样[图:con2.gif];


最后一直点击确定回到第一层菜单将中间的“Equal to(等同于)”改为“Less Than(小于)”,再点击最后那个0将其改为你所希望的最大出兵数量,到此整个Condition(条件)就完成了[图:LimitCondition.gif]。


此时的触发如图[图:Fin.gif]。


以上就是一个限制了出兵最大数量的刷兵触发的基本原理,但是在实际制作中并不是这么简单,对应很多情况需要做出调整,有兴趣的可以自己去研究研究。这里给出范例地图,不明白的地方可以对照修改[文件:CreateUnit.w3x]


作者: 但偏偏雨渐渐    时间: 2006-2-28 09:39

[WE] 线状特效代码列表

  • 线状特效代码列表:

1. AFOD 死亡之指(Finger of Death)

2. CHIM 双头龙闪电攻击(Lightning Attack)

3. CLPB 连锁闪电主光束(Chain Lightning Primary Bolt)

4. CLSB 连锁闪电次光束(Chain Lightning Secondary Bolt)

5. DRAB 吸取生命与魔法

6. DRAL 吸取生命(Drain Life)

7. DRAM 吸取魔法(Drain Mana)

8. FORK 叉状闪电 (Fork Lightning)

9. HWPB 治疗之风主光束(Healing Wave Primary Bolt)

10. HWSB 治疗之风次光束(Healing Wave Secondary Bolt)

11. LEAS 空中桎梏(Lightning Effect of Aerial Shackles)

12. MBUR 法力燃烧(Mana Burn)

13. MFPB 法力曳光弹(Mana Flare)

SPLK 灵魂连结(Spirit Link)


作者: 但偏偏雨渐渐    时间: 2006-2-28 09:40

[WE] Art代表的意思

  • Art代表的意思:

  • 作者: 但偏偏雨渐渐    时间: 2006-2-28 09:42

    [WE] 魔兽的媒体数据文件

    魔兽争霸III中,有各式各样的图示和动画,它们的格式是什么呢?很不幸地,它们不是TGA、BMP、JPG、GIF这类常见易改的档案,而是特殊压缩的BLP格式。如果你嫌内建的图不够多、不够美,为了要能够在地图中放入自己画的图,或者修改b社画的缺乏美感的图--你必须要有转档工具。


    一般而言,BLP可和32 bit的TGA格式互转,有些程序也支持 BLP <=> BMP 与 BLP <=> JPG,不过建议还是用TGA编辑较好。至于转好的图档要用什么编辑呢?一般来说,可编辑屏蔽及图层的Photoshop是比较好的选择,不过,如果你用别的程序也可以做出同样精美的32 bit TGA图片的话,用小画家也没人管你=_=。


    此外,魔兽的模块(动画)档案是MDX格式,可用3DS Max编辑,详细情况笔者不清楚。


    作者: 但偏偏雨渐渐    时间: 2006-2-28 09:43

    [WE] MPQ 是什么?

    MPQ 是 Blizzard 公司将游戏数据包装在一起的一种档案格式,内容放置采取 Joliet 档案格式 (MS-DOS 路径型态+长文件名),与 Unix/Linux 路径型态不同。内部采取可压缩设计,但对于不同档案型态,其压缩方式也不同。

    后来据说某位国外的天才,将 MPQ 档案格式解碼后, 利用星海争霸任务编辑器staredit.exe 搭配 storm.dll 档案,配合他自行制作的几个 MPQ 功能,成为 MPQ2000 软件。之后又陆续出现了很多新的MPQ软件,例如MPQ View、WinMPQ、MPQ Editor、MPQ Workshop、......,软件的使用范围也从DOS模式延伸到Windows。

    这些软件最主要的功能是可以解出MPQ档案下的东西(就像使用WinZip解开.zip档案一样),甚至可以压入档案到.mpq中。它可以用来解出魔兽争霸III中的图档、动画、战役地图、原始数据等。此外,也可以用在星海争霸(Strcraft)及暗黑破坏神(Diablo)中,以及制作特别版(但是制作出来的版本原则上无法与正常的版本在b.net上联机游戏,只能自high)。本文只讨论基本的解文件功能,其它进阶的功能请大家自行研究。

    此外,对于某些MPQ程序,为了要开启MPQ档案,你必须提供该MPQ文件内部的路径表(listfile),才打的开这个档案。有些比较高级的程序如WinMPQ,可使用该档案内部的listfile开启,但是如果该档案没有附listfile,则无法顺利开启。listfile为.txt文件,如果需要的话,可以把附录 War3 All Listfile 的内容复制起来,贴到记事本并存成.txt檔即可使用

     

    MPQ程序也可以加入档案,但是处理MPQ的档案和处理一般档案的情形有些不同。当你删除档案(或者用同名称的档案覆盖)时,它的空间不会被释放,换句话说,删除档案后,档案不会变小,只是不会被读到而已。就笔者所知,目前只有最难操作的MPQ2K可以释放空间,所以大家最好不要随便用MPQ程序删文件和加文件,不然该档案会越变越大。


    作者: 但偏偏雨渐渐    时间: 2006-2-28 09:44

    JASS教学

    0、JASS简介

    1. JASS是什么?
      JASS
      (正确地说是JASS 2)是魔兽3的程序语言, 用于控制游戏和地图的进行,也是魔兽游戏和地图的基础。 地图编辑器中摆放的单位(Unit),区域(Region) ,触发(Trigger)……等,最终都会被翻译成JASS语言存在地图文件里,在游戏时被使用。
    2. 为什么要学习JASS语言?
      1. 少量功能只用GUI Trigger不能完成, 必须用JASS来实现,例如:
        1. 内存泄漏问题(Leak,指创建的临时游戏对象于使用过后没有被删除,增加计算机负担及游戏lag度的情形)。只有使用JASS提供的相关DestroyRemove函数可以解决。
        2. 对指定玩家播放音效
      2. 在实现一些功能时使用JASS可以比触发(Trigger)写得更简洁、高效、快速,例如:
        1. JASS可以使用区域变量,让多个触发彼此不互相混淆。GUI Trigger则必须使用数组及复杂的判断来达成。
        2. JASS可以大幅简化if判断和loop循环的语法。GUI Trigger可能要很大串的if或者很多个触发串联起来。
    3. 一定要学JASS吗?
      不一定。一般来说,单纯使用GUI Trigger,就可以达到大多数的功能。笔者建议建议对Trigger有一定程度了解的人稍微学些基本JASS写法,可以省下很多力气,且能让你的地图更不lag!!

     

    一、JASS预备知识


    在开始学习JASS之前,大家还是有作业要做的。回去自己写一句Trigger,再翻成JASS(Convert to Custom Text)看。看完了按复原(Ctrl+Z),再改再看。一般时间你就能弄熟语法了。这是入门,如果你没做的话,将来别人写JASS,你会很难看懂。

    此外,也建议大家看一下blizzard.j和common.j档案里的子程序。基本上懂得越多,你写JASS就越有发挥的空间(记住,重要的不是背起来,而是会灵活运用。反正忘了怎么写,可以查那二个档案)。

    好了,以下是正式的JASS教学。前半部在说明JASS的整个语法和结构,这些东西不但无聊(笔者也不是很懂程序的人,里面的数据大多是从别的地方偷来的),而且只要懂程序的人应该就能轻松上手,更重要的是,这对实际写JASS的帮助不大。因此,就像大家学Windows大都不看说明书一样,笔者建议大家先从第八章开始看,看完再回头看第二~七章。


    二、JASS语言的源代码

    JASS语言的扩展类型定义,基本函数和常数取值都是直接调用游戏的函数,他们被存放在war3x.mpq和war3patch.mpq内的Scripts\common.j和Scripts\common.ai中。JASS还有一些扩展函数, 放在war3x.mpq和war3patch.mpq内的Scripts\blizzard.j中。 common.ai则包含了用于设计AI的大量内部函数和扩展函数,但对于我们只用Jass进行普通脚本编写的人来说可以忽略这个档内的代码。 其中war3patch.mpq里的档案是最新版本的资料,可以使用mpq工具解出来。如果不会解也没有关系,这里提供解出来的1.15版的blizzard.j和common.j(请见附档)。


    三、注释

    任何写在//后面的都是注释内容,这也是JASS唯一的注释语法。后面的例子会多处用到这个注释符号,这个符号和后面的注释只是用于解释程序代码的功能,并不会被执行到。


    四、数据类型

    基本数据类型有:
    boolean : 布尔, 只有true和false二个值

    integer:整数。取值范围为 -2147483648到2147483647(2的31次方)
    有4种形式的方法来写整数型的值:
    1)全部为数字, 第一个数位不为0。即是10进制表示方法,如:23
    2)全部为数字, 第一个数位为0。 这是8进制表示方法,如:023(相当于十位位的19)
    3)0x(x可以是大写)开头。 后面全部为数字(16进制的数字包含A,B,C,D,E,F, 分别表示10,11,12,13, 14,15, 可以为小写),这是16进制表示方法。 如:0x23(相当于十位位的35)
    4)用单引号括起4个字母,表示单位/技能编号对应的整数。 如:'Hpea'、'A001'

    real :实数,取值范围为 1.5 x 10^(-45)到3.4 x 10^38

    string :字符串,用双引号括起的若干个字母; 空字符串表示为""。字符串中遇到"可以用\"来表示这是一个字符串中的引号。如:"abc\"def\"", 就表示字符串abc"def"

    code :代码,用于表示一个函数地址。 通常用于传值时传递一个函数。其值的形式为function <函数名>。

    handle : 句柄,它指向内存的一个地址,用于表示一个较大的结构, 是很多数据类型的基类型。

    除了基本数据类型,JASS还提供了大量扩展数据类型,都是以handle为基类型。例如:unit、trigger、timer、rect(Region)、location(Point)、……


    五、表达式(expression)

    表达式可以是直观可见的值,也可以是函数,计算式等。 如:

    布尔: true, false
    数值: 1, 3, 5565.33
    字符串: "Xasfsfs", "Greedwind"
    函数:GetTriggeringUnit()、GetUnitLoc(GetTriggeringUnit())
    计算式:(a + b) * c + d

    计算式中可用的运算有:

    数学计算:+, -, *, / (注意整数除法的结果仍然为整数,小数点无条件舍去)
    比较符号(传回boolean布尔值):>, <, >=, <=, ==, != 分别是大于、小于、大于等于、小于等于、等于(注意不是=)、不等于
    布尔运算:and, or, not
    字符串运算:+ 字符串相加,如"abc" + "def"的结果是"abcdef"


    六、前缀

    B社为了让程序运作顺畅,而且不让制作者自制的变量名称和War3内部的变量名称混淆。因此WE会自动为玩家自订的变量名称加上前缀。例如:
    Variable:udg_
    Region:gg_rct_
    Trigger:gg_trg_
    Unit:gg_unit_

    等等...所以像:
    set A = 1
    翻成Jass以后会变成:
    set udg_A = 1

    假设你在一个名为Choose Hero的Trigger下加入这一条Event:
    Unit - A unit enters HeroChoosePlace 8 <gen>
    翻成JASS以后会变成:
     call TriggerRegisterEnterRectSimple( gg_trg_Hero_Choose, gg_rct_HeroChoosePlace_8 )

    所以如果要在JASS中用到变量,请务必加上”udg_”之类的前缀


    七、函数语法

    Jass中定义一个函数的语法为:

    function <函数名> takes <参数类型> <参数名> returns <传回类型>
     //函数主体
    endfunction

    其中<参数>可以有很多个,用逗号隔开,用于传递参数给函数。传递过去的参数一律被视为区域变量,<参数>和<传回类型>可以写nothing 表示不传入或传回任何值。

    然后介绍函数基本语法return, 它必须写在函数里, 格式为:
    return <表达式>

    当函数返回类型为nothing时,后面不需要表达式,否则必须写表达式。它可以出现在函数的任何地方,可以出现不止一次,但是一旦碰到这一行,函数立即返回值并跳出该函数的运行。注意,return的值的类型必须和函数的返回类型相同。例如blizzard.j中:

    //传回传入二实数中较小者
    function RMinBJ takes real a, real b returns real
     if (a < b) then
       return a
     else
       return b
     endif
    endfunction

    //计算整数余数的程序(如18 mod 5 = 3)
    function ModuloInteger takes integer dividend, integer divisor returns integer
     local integer modulus = dividend - (dividend / divisor) * divisor

     // If the dividend was negative, the above modulus calculation will
     // be negative, but within (-divisor..0). We can add (divisor) to
     // shift this result into the desired range of (0..divisor).
     if (modulus < 0) then
       set modulus = modulus + divisor
     endif

     return modulus
    endfunction

    注:现在的Jass有编译问题,它只会判断最后一个return返回的类型。而且官方明确表示永远不会修正这个bug(这可以做为War3资料转换工具),但是出于安全考虑,最好保证所有return的值的类型都符合。

    函数(function)的调用:

    Call Function(自变量1,自变量2,……)
    →呼叫Function,传递自变量1,自变量2,……

    例如:
     call RMinBJ ( 3.1, 5.4 )
     call ModuloInteger( 18, 5 )
     call RemoveUnit( GetTriggerUnit() )

    *如果该函数不需要传递自变量(takes nothing),则后面可直接用(),如上面的GetTriggerUnit()


    八、区域变量

    local 变数形态 变量名称 (= 值)
    →宣告一个区域变量名称(并设定初始值)

    例:
     local real Duration
     local integer i = 1

    ※变数区分大小写!,例如Ability和ability视为不同的两个变数。


    九、判断语句(if)

    判断语句的基本语法为:
    if <表达式> then
    //代码段,可以为多行
    endif

    <表达式>结果必须为布尔型,因此通常用比较符号和布尔型运算进行复合运算,当表达式结果为真时。 执行中间的代码段。

    此外,我们还可以判断语句在其中加入否则(else)和否则如果(elseif)的语句:

    例如:
     if [条件A] then
      [动作A]
     else
      if [条件B] then
       [动作B]
      else
       if [条件C] then
        [动作C]
       else
        [动作D]
       endif
      endif
     endif

    相当于:
     if [条件A] then
      [动作A]
     elseif [条件B] then
      [动作B]
     elseif [条件C] then
      [动作C]
     else
      [动作D]
     endif

    例子还是blizzard.j的二个函数:

    //传回传入二实数中较小者
    function RMinBJ takes real a, real b returns real
     if (a < b) then
       return a
     else
       return b
     endif
    endfunction


    这个函数也可以改成:
    function RMinBJ takes real a, real b returns real
     if (a < b) then
       return a
     endif
     return b
    endfunction


    //计算整数余数的程序(如18 mod 5 = 3)
    function ModuloInteger takes integer dividend, integer divisor returns integer
     local integer modulus = dividend - (dividend / divisor) * divisor

     // If the dividend was negative, the above modulus calculation will
     // be negative, but within (-divisor..0). We can add (divisor) to
     // shift this result into the desired range of (0..divisor).
     if (modulus < 0) then
       set modulus = modulus + divisor
     endif

     return modulus
    endfunction


    十、循环(Loop)

    循环是用来让计算机做相同或相似的动作多次,而不占用太多程序代码的写法。

    循环语句的语法为:
    loop
     //代码段,可以为多行,也可以不写
     exitwhen <表达式>
      //代码段,可以为多行,也可以不写
    endloop

    *<表达式>表示跳出循环的条件,结果必须为布尔值,当它为真时,程序会直接跳出循环执行endloop后面一行的语句。

    *如果想要强执跳出循环,可以用exitwhen true

    *exitwhen语句可以有多个,表示多个跳出条件;也可以不写,那就会成为无穷循环(直接用无穷循环的话会当机,平常使用时会加上Wait延迟以避免)


    例如blizzard.j中:

    //计算指定单位身上拥有的物品数
    function UnitInventoryCount takes unit whichUnit returns integer
     local integer index = 0
     local integer count = 0

     loop
       if (UnitItemInSlot(whichUnit, index) != null) then
         set count = count + 1
       endif

       set index = index + 1
       exitwhen index >= bj_MAX_INVENTORY
       // bj_MAX_INVENTORY是blizzard.j中的整数常数,值为6
     endloop

     return count
    endfunction


    作者: 但偏偏雨渐渐    时间: 2006-2-28 09:45

    电影制作

    想做一部电影,想当然尔要有一个剧本(废话...)
    有了一个剧本,接下来就是要思考剧本的长短
    剧本的长短关系到舞台,也就是场景的多少
    场景多,则地图大小就大;反之则否,当然「超华丽」的短剧例外,不过现在只讨论一般的
    接下就是最麻烦的场景制作,也是此文的重点
    -----------------------------------------------------------------------------------------------------------
    场景制作包括地形、饰物、角色的安插以及音效跟音乐

    地形:举个例,若今天你想要做个桃源仙境,那么青山绿水是一定要的,此景最忌讳的就是黑色跟红色;再举个例,若今天你想做个混乱世界,那么红色就是最佳的背景,充满力量;最后一个例子,若是悬疑恐怖的气氛,那么颜色就越乱越好,但一切以深色为主。其实地形严格说起来就是地面颜色的配置,也是决定是否能把观众带入气氛的关键,不过除了地刑外,也要考虑到天空。

    饰物:用上面三个例子来说明。桃源仙境若只有青山绿水,却没有「会动」的东西,那看起来就像是人工制品,感觉去了一大半。若今天我在上面放了几只飞鸟,或是一道瀑布,那就会有充满活力,但又不失宁静的感觉,若再加上一层淡淡的蓝光,就更具灵性;再来就是充满力量的混乱世界。混乱,就是无序,杀人放火,红光绿光到处乱闪。会动的东西这场面最多,而且动的速度不能太慢,越狂暴越好。就像说一条街上,有三只乳牛在散步,跟三只斗牛到处冲撞,我想应该是后者最符合这场景〈若你认为是乳牛,那表示你眼光独到,此篇你不用看了,我拜你为师...〉,但就是有一点要注意的,会有乱,表示有静,通常这场景代表静的就是死亡,像是尸体,尸体上面较贴切的动态物可以是虫或苍蝇;接下来是恐怖悬疑。配合地形,这场景的东西就是要暗,而且要静。静,不一定是死亡,「畸形」也是其中的一个代表。但就我前面所说的,有静,表示有动,只不过不同的是,这次的「动」很慢,若太快,则会变调。比如说,一个人在晚上慢跑跟一个人在晚上散步,感觉就不一样

    角色的安插:角色要在最适当的时机出现,我想这是最简单的道理,但怎样才叫最适当的时机呢?其实这没有一定的标准,或许多根本没有标准,因为这要看你的剧本而定。比如说当一个女孩子被坏人欺负时,下一个出现的人是谁?若你的剧本是「从此过着幸福快乐的日子」那型的,那下一位角色通常都是身负正义感的男生,略有变化的,是一位女生;若你的剧本是「女人命真苦」,那下一位登场的八九不离十是一个坏人。所以这部份要视剧本而定。

    音效跟音乐:这部份其实没什么好讲的,若硬是要说的话就是音乐的部份。作电影,除非自己观赏用,否则音乐绝不要放些自己「喜欢」听的,一定要放适合目前场景的音乐。若没有,则干脆不要。比如说战争片,你放妹妹背着洋娃娃,除非你是恶搞电影,不然绝对让人翻桌。
    ===============================================

    电影制作理论讲完了,再来就是实作的部份

    ===============================================
    电影制作的触发,通常都会用到Camera跟Cinematic这两项

    Camera:Camera最简单的制做方式就是你在WE里调整好你要的视角后,在Tool Palette那个小窗口选Camera Palette,然后点Create Camera,这时你就会看到画面出现一个半透明的摄影机,这就是你新做的Camera。至于Camera里的内容我就不多做说明,自己一个一个调来试会更清楚。Camera制作成功了,那要怎么使用呢?
    Camera - Apply Camera Object (Timed)
    这个触发能让某玩家跳到上面所指定的Camera视角,而最后面的时间则是让你从目前的视角移到指定视角所需的时间。还是不明白的,可以在WE上随便移动你目前的视角,时间设10,然后按上面Preview Camera Motoin钮。当你在WE的视角到达指定视角后,把时间设4,随便移动你目前的视角,按同样的钮,这样就会很清楚了。
    会使用Camera之后,接下来就是基本的Camera特效
    Camera - Sway Camera Source
    Camera - Sway Camera Target
    以上两个就是对某一玩家使用晃动的Camera效果,第二个数值是晃动强度,最后一个则是晃动的速度。若你今天想做船在码头上摇晃的感觉,那么晃动速度就不能太高;若今天是船在大浪中行驶,晃动强度就要高,速度也要稍微提高。至于Source跟Target有什么差别呢?想象你盯着某一点看,接着你往前后移动,左右平移或是上下跳跃,仍是盯着那点,则以那点为中心,你视线内的变化就是Source;Target则是你站着一动也不动,眼珠子跟着你眼前的苍蝇转动,以苍蝇为中心视线内的变化。
    Camera - Shake Camera 比较容易理解,就是某玩家做强度多少的前后震动的特效
    当你想结束特效时,就要使用Camera - Stop Swaying/Shaking Camera,不然特效是会一直下去的

    Cinematic:角色说话的画面、屏幕淡入淡出的制作就在这里。
    Cinematic - Cinematic Mode 就是对某一玩家使用或不使用电影模式。何谓电影模式?当你进入电影模式之后,原本下面的控制面版会变成对话窗口,你无法控制任何单位或下达指令,而且游戏中的音效跟音乐会降低声音。

    Cinematic - Letterbox Mode On或Off 与 Cinematic Mode 不同的是,Letterbox Mode 改变的是控制面版变成对话窗口,无法控制任何单位或下达指令,但游戏中的音效跟音乐没影响。

    Cinematic - Transmission From Unit 分两种,一种是抓取地图上的某一单位来对话,当单位开始讲话的时候,他的脚下会有白色光圈一闪一闪的;另一种是选取某一种单位来对话,并且可设定此单位的背景色。后面"Play声音and display讯息"其中的讯息就是角色台词,声音当然就是说话声啰。这里有一个地方要注意,当你没有拨放任何声音而且最后面选择 Wait 的时候,这个对话讯息预设为 5秒,也就是 5 秒后才会消失并执行下一个Trigger 。若选择Don't Wait,则他会忽略所有的条件,马上执行下一个Trigger。假若今天有拨放声音,是为3秒的音效,则在Wait的情况下,此对话会维持3 + 所Add的秒数(秒数负以0计)。所以今天我写一个Trigger:
    Cinematic - Send transmission to (All players) from 单位1 named John: Play 3秒音效 and display Hi. Modify duration: Add 1.00 seconds and Wait
    Cinematic - Send transmission to (All players) from 单位2 named Mary: Play 6秒音效 and display I hate you. Modify duration: Add 0.00 seconds and Don't wait
    Wait 3.00 seconds
    Cinematic - Send transmission to (All players) from 单位2 named Mary: Play 没音效 and display DIE. Modify duration: Add 0.00 seconds and wait
    Units - Mary kills John
    一开始John会先说"Hi",此对话会维持 3+1 秒,接者换Mary说"I hate you",此对话维持 3 秒后Mary又跟着说"DIE",说了5秒的"DIE"后,Mary把John杀了
    由以上的例子应该就很清楚Transmission From Unit 的用法了

    Cinematic - Fade Filter 是专门用来制作电影淡入(Back in)淡出(Fade out)的效果。举些例子:
    Cinematic - Fade out and back in over 2.00 seconds using texture White Mask and color (0.00%, 0.00%, 0.00%) with 0.00% transparency
    画面会在1秒内淡出,渐渐变白,然后又在1秒内渐渐回复
    -----------------------------------------------------------------------------------------------------------
    Cinematic - Fade out over 3.00 seconds using texture White Mask and color (0.00%, 0.00%, 0.00%) with 0.00% transparency
    画面会在3秒内淡出,变成永远的白色
    -----------------------------------------------------------------------------------------------------------
    Cinematic - Back in over 2.00 seconds using texture White Mask and color (0.00%, 0.00%, 0.00%) with 0.00% transparency
    画面会在2秒内由全白淡入,回复原来的样子
    -----------------------------------------------------------------------------------------------------------
    Cinematic - Fade out over 4.00 seconds using texture White Mask and color (100.00%, 0.00%, 0.00%) with 0.00% transparency
    画面会在4秒内渐渐变红,变成永远的红色
    -----------------------------------------------------------------------------------------------------------
    Cinematic - Back in over 2.00 seconds using texture White Mask and color (0.00%, 100.00%, 0.00%) with 0.00% transparency
    画面会在2秒内由全绿淡入,回复原来的样子
    -----------------------------------------------------------------------------------------------------------
    Cinematic - Fade out over 4.00 seconds using texture White Mask and color (100.00%, 0.00%, 0.00%) with 50.00% transparency
    画面会在4秒内渐渐变半透明的红,变成血红的世界
    -----------------------------------------------------------------------------------------------------------
    另外一个Advanced Filter比较复杂,举个例:
    Cinematic - Apply a filter over 2.00 seconds using Normal blending on texture White Mask, starting with color (100.00%, 0.00%, 0.00%) and 0.00% transparency and ending with color (0.00%, 100.00%, 0.00%) and 0.00% transparency
    则画面会在2秒内由全红渐转为全绿,其中有一个Blending选项,是让你选择遮照(Mask)跟画面的混合方式,至于混合的效果,自己开WE试最清楚,所以就不多说了。不过遮照有一个地方要注意,Black Mask是黑色,它在色彩三原色中是0,0,0,所以0不管乘几都是0,想要让Black Mask变色是不可能的,只可调整它的透明度。
    ===============================================

    电影的触发大致上就是这样,接着要讲的是声音的制作

    ===============================================
    声音基本上分单声道(Mono)与双声道(Stereo)两种,一般我们在听的音乐绝大部份都是双声道,魔三的音效则几乎都是单声道,也就是3D音效。何谓3D音效?当一个大法师在下冰雨的时候,把画面中心移往下冰雨的地点,你会发现声音比较大声,离下冰雨地点越远则越小到听不到,那这下冰雨的声音就是3D音效。魔三可汇入的声音为wav檔跟mp3檔,其中mp3可被用为声音或是音乐。至于声音的制作,随便找个好点的录音程序就行了,通常都会有Mono跟Stereo这选项。在声音编辑选单里,若你要用为声音,则选Use As Sound,若是音乐则用Use As Music。通常直接使用魔三内建音效的时候,它都会自动勾选3D sound,表示这是个3D音效。再来就是声音的使用:

    先来讲一般非3D音效的使用方法:
    Sound - Play Sound 是最基本的使用方式(3D音效也是)。不过当你在拨放音效1且未结束时,是没办法拨放音效2的,一定要等音效1拨完才行,也就是说音效无法重迭。至于拨放音效的特殊方式有下面几种(若没加注则3D音效也可用):
    Sound - Play Sound From Offset 从音效的开始往前跳数秒以设定的音量拨放(3D音效不能用)
    Sound - Stop Sound 立即停止或淡出目前的音效
    Sound - Destroy Sound 从游戏中移除某音效,从此此音效再也不能用,若正在拨放则会等它拨完再移
    Sound - Set Sound Volume 设定音效大小(最高到100%)
    Sound - Skip To Sound Offset 可以让你声音拨放到一半时往前跳到几后秒拨放(3D音效不能用)
    Sound - Set Sound Pitch 设定音效的拨放速度,加快速度可以变成卡通小老鼠那种可爱的声音

    再来是3D音效的使用方法:
    要使用3D音效必须先设定此音效的原点,就像之前举的例子,下冰雨的中心点就是冰雨音效的原点。所用的触发Sound - Set 3D Sound Position,其中Z值是高度。这是只某一定点的3D音效,但若想要「可移动」的3D音效呢?那可以用Sound - Attach 3D Sound To Unit ,这时此3D音效就会跟着某单位跑了。而3D音效比较不同的是它可重迭。至于拨放3D音效的特殊方式有下面几种:
    Sound - Play Sound At Point 设定3D音效的原点后开始拨放
    Sound - Play Sound On Unit 把3D音效的原点贴着某单位后开始拨放
    Sound - Set Sound Cutoff Distance 设定3D音效可听到的范围

    最后是Music的部份,一次只能拨一首,可跟音效重迭,顺便翻译触发好了
    Sound - Set Music List 制作音乐清单,第一种是照顺序拨放,第二种是随机。游戏开始时拨放的音乐清单就是这一个。
    Sound -Clear Music List 移除音乐清单
    Sound - Play Music 拨放音乐
    Sound - Play Music From Offset 从某一秒开始拨放音乐,并且是以几秒之内淡入的方式

    补充一点:Sound - Set All Volume Channels For Cinematics 是指把游戏内的音效跟音乐变成Cinematic系统的音量,所以
    Letterbox Mode + Set All Volume Channels For Cinematics = Cinematic Mode


    作者: 但偏偏雨渐渐    时间: 2006-2-28 09:49

    [WE JASS] jASS心得

    变量类型格式:
    String=""
    Integer=''
    ------------------------------------
    基本语法:
    set 变量 = 值(设置变量)
    local 变量类型 变量名称(设置变量类型)
    local 变量类型 变量名称=值(设置变量类型和值)
    ------------------------------------
    变量类型和空值:
    boolean 布尔型(用于真/假判断) false
    destructable 可破坏物 null
    dialog 对话 null
    button 按钮 null
    texttag 漂浮文字 null
    integer 数值 0
    item 物品 null
    leaderboard 排行榜 null
    player 玩家 null
    force 玩家组 null
    location 位置(点) null
    real 真值型数字 null
    rect 地区 0
    effect 特效 null
    string 字符串 null
    terraindeformation 地形 null
    timer 计时器 null
    timerdialog 计时器窗口 null
    unit 单位 null
    group 单位组 null
    playerscore 积分 null
    ------------------------------------
    命令单位执行指令(call):
    call IssueTargetOrderBJ( 单位 , 指令 , 单位 )((单位目标)
    call IssuePointOrderLocBJ( 单位 , 指令 , 点目标 )((点目标)
    call IssueTargetDestructableOrder( 单位 , 指令 , 可破坏物目标 )(可破坏物物标)
    call IssueImmediateOrderBJ( 单位 , 指令 )(没有目标)

    ------------------------------------
    单位(Unit):
    GetLastCreatedUnit()(最后创建的单位)
    GetTriggerUnit()(触发单位)
    GroupPickRandomUnit(单位组)(单位组内随机单位)
    GetEnteringUnit()(正在进入区域的单位)
    GetLeavingUnit()(正在离开区域的单位)
    GetEventTargetUnit()(命令目标单位)
    GetEnumUnit()(Pickup单位)
    GetFilterUnit()(匹配单位)
    GetDyingUnit()(死亡单位)
    GetAttacker()(攻击单位)
    GetAttackedUnitBJ()(被攻击单位)
    GetOrderedUnit()(收到命令单位)
    udg_X()(变量X单位)

    ------------------------------------
    点目标(Loc):
    GetRectCenter()(区域中心)
    GetRandomLocInRect()(区域内随机坐标)
    OffsetLocation((点, x.xx, y.yy) )(区域内坐标点)
    PolarProjectionBJ(点, x.xx, y.yy) )(点方向位移x.xx角度y.yy)
    GetCameraTargetPositionLoc()(当前摄像机视角)
    GetDestructableLoc(可破坏物)(可破坏物的目标点)
    GetOrderPointLoc()(命令目标点)
    GetSpellTargetLoc()(对其实用技能的目标点)
    GetItemLoc(物品)(物品位置)
    GetUnitLoc(单位)(单位位置)
    WaygateGetDestinationLocBJ(单位)(中立建筑-传送门目标点)
    GetPlayerStartLocationLoc(玩家)(玩家的初始位置)
    udg_X()(变量X点)

    ------------------------------------
    地图区域(MapRect):
    GetPlayableMapRect()(可玩区域)
    GetEntireMapRect()(整个地图)
    udg_X()(变量X区域)

    ------------------------------------
    可破坏物目标(Destructable):
    GetLastCreatedDestructable()(最后创建的可破坏物)
    GetOrderTargetDestructable()(命令目标的可破坏物)
    GetSpellTargetDestructable()(对其使用技能的目标点内可破坏物)
    GetEnumDestructable()(pickup可破坏物)
    GetFilterDestructable()(匹配可破坏物)
    RandomDestructableInRectSimpleBJ(区域)(区域内随机可破坏物)
    RandomDestructableInRectBJ(区域, Condition(条件))(区域内随机可破坏物并匹配条件)
    udg_X()(变量X可破坏物)

    ------------------------------------
    物品(Item):
    GetLastCreatedItem()(最后创建的物品)
    GetLastRemovedItem()(最后掉落的物品)
    UnitItemInSlotBJ(单位, X)(单位物品栏X格的物品)
    GetItemOfTypeFromUnitBJ(单位, 'X')(单位物品栏中类型为X的物品)
    GetEnumTargetItem()(Pickup物品)
    GetFilterItem()(匹配物品)
    GetOrderTargetItem()(命令目标物品)
    GetSpellTargetItem()(对其使用技能的目标物品)
    RandomItemInRectSimpleBJ(区域)(区域内随机物品)
    RandomItemInRectBJ(区域, Condition(条件))(区域内随机物品并匹配条件)
    udg_X()(变量X物品)


    作者: 但偏偏雨渐渐    时间: 2006-2-28 09:50

    [WE] 自定义技能(Custom Ability)教程

    自定义技能(Custom Ability)就是使用触发器创建一些效果,来实现无法通过直接在技能编辑器里面修改已有属性的效果~看了比较混乱?举个例子:比方说全体睡眠,无论怎么修改已有的技能也是无法实现的。遇到这种情况只有通过使用触发器来自主的为技能添加一些附带效果,比方创建一些视觉特效,对一定范围内的单位造成伤害,或者将单体技能范围化等等。现在简单的介绍一下制作的流程。
    制作自定义的技能首先需要的是一个作为启动触发器的原始技能,因为前面说了自定义技能几乎所有的效果都是通过触发器实现的,而触发器必须有一个事件作为触发的开端,一般来说,在自定义技能中,这个事件的开端就是“一个单位开始使用一个技能”或者“一个单位开始了一种技能效果”,作为触发效果的这个技能需要根据实际需要自己选用制作(包括确定技能的目标类型“点,单位,无目标”去掉技能本身的效果,自己定义技能释放间隔,消耗等),有了这样一个“干净”的技能,在触发的事件中即可直接使用“单位-单位事件-单位开始一种技能的效果(图:)来启动技能对应的触发。
    原始技能制作好了以后即进入技能效果的制作阶段,前面已经讲过技能效果是通过触发器实现,每个效果都需要一个动作来执行,因此在制作以前务必要在脑中形成一个比较完整的技能效果过程:什么时候创建什么效果,什么时候造成伤害,什么时候取消效果等。都属于需要事前考虑好的范围,当一切都有了一个比较明确的步骤分类以后,就可以着手开始触发的实际制作了。
    这里讲讲自定义技能的触发构成,一般来说触发的“事件”是“一个单位开始了一种技能效果”,因为如果以“一个单位开始使用一个技能”作为触发事件,会造成触发时机判断上的错误(使用的瞬间移动单位,不消耗MANA却出现技能效果等)。
    而为了是使触发产生的效果和启动触发的技能对应起来,则必须在“环境 - 技能比较 - 被释放的技能”中限制启动技能的类型为自己制作的那个原始技能(图:),如果是某个单位或某种类型的单位专署技能那么还应该加上单位的判断“单位比较 - (触发单位) 等于 (指定的单位)”(图:)或者单位类型的判断“单位 - 类型比较 - (单位的类型为(触发单位)) 等于 (指定的单位类型)”(图:),如果不做这种限制,那么当任一单位或者任一类型的单位使用了任何种类的技能的时候,都会启动触发器进而产生一连串效果,这是我们不愿意看到的。
    启动触发的事件和环境设置完成以后,最后需要的就是在“动作”中编入一些和技能的特效有关的东西来完成整个技能的制作了,一般来说一个技能的效果是由视觉效果部分,伤害效果部分和状态变化部分三部分组成的,一个经典的技能也只是将这三部分有机的结合在一起的产物而已。
    最后必须说明的是为技能做效果的时候切忌一味的追求华丽,创新和实用才是好技能必备的特征,同时应该适当的考虑玩家的机器配置,因为如果你的技能使用的时候会很卡或者干脆死机,纵然做的再经典,也只能归入失败的作品范围。


    作者: 但偏偏雨渐渐    时间: 2006-2-28 09:54

    [WE] 非触发器 & JASS问题解答

    ======这里收集有关触发器和 Jass 的问题=======


    Q什么是触发?(Trigger),触发是如何工作的?

    触发(Trigger) - 根据字面意思可以理解为: 事件A 发生后会直接或者间接的导致 事件B 发生的过程~~
    关于触发的工作原理,举例如下:
    动物踩上地雷,地雷就BOOMMMMMMM!:)~~
    以上这就是一个触发,踩地雷事件A ,我们称它为 事件(EVENT)~~而 地雷爆炸 则对应 事件B ,我们称他为 行为(ACTION)~~大家还可能考虑到,如果踩上地雷的不是人,而是质量很小的昆虫,则不可能发生爆炸,于是我们引入一个概念,就是 条件(CONDITON)~~它决定了 事件 发生后是不是会导致连带的结果,即 行为 的实施~~
    一个触发分为三个状态就绪状态工作状态屏蔽状态。其基本状态是 就绪状态
    就绪状态:处于就绪状态的触发可以接收其相应的 事件,只要 事件 发生,则此触发建立一个单独的进程进入工作状态,这个接收事件转入工作状态的过程称为 响应(RESPONSE)~~
    工作状态:从就绪到工作,首先进行 条件(CONDITON)检测 ,如果通过就开始 行为的实施 ,从检测到实施完毕的整个过程为工作状态(无论是否通过检测)。需要注意的是,一个处于工作状态的触发是一个单独的进程~~一个触发可以同时或者异步响应 N次 。
    屏蔽状态:处于屏蔽状态的触发不能 响应 任何事件,但是可以通过 调用行为 进行调用,调用后直接进入 工作状态。在调用的时候可以选择是否跳过 条件检测。
    ]:同一个触发中的多个 事件 之间是 OR 关系,满足其中之一则触发响应;多个 条件 之间为 AND 关系,全部满足才通过检测;而多个 行为 的执行是按照顺序进行从上到下的处理。


    Q触发器的里各语句的位置有影响么/能换么?

    不能换。Trigger 的执行顺序是从上到下依次执行的。
    不过 Category 的先后顺序则无关紧要。


    Q玩家的初始金钱和木材在那里改?

    在地图初始化的触发里选择 Set Property .就可以更改金钱和木材了。


    Q如何更改英雄取得经验的比例?

    ACTION - HERO - HERO EXPERIENCE RATE,设成多少百分比看自己的情况决定咯。


    Q怎么去掉单位身上的那些默认按钮啊?~~比如攻击~~集结点什么什么的~~

    通常用 UNIT - REMOVE ABILITY 可以用来去掉一些按钮~~
    直接删除相应技能即可

    但是可能造成单位无法移动和攻击,慎用
    …………


    QLetterbox 和 Cinematic 有什么区别啊?似乎都是打开影片模式哦

    Letterbox 不会改变可视度~~没有被探索的地方也同样不会显现~~Cinematic 反之~~


    Q怎么可以实现物品栏里每一个格子只能放一类物品,且同类道具只能放有一个呢?

    >>>点击·演示<<<

    这个问题会涉及到变量的使用还有 TRIGGER 。
    首先你需要创建一个变量数组(VAR ARRAY),命名为 IF,类型为 布尔(BOOLEAN),容量为 7(因为下标是从0开始的,所以要对应6个道具栏一般就设置为7比较好操作)。
    然后在 ITEM EDITOR 里面为不同类型的道具设定相同的等级,比如武器就是 L1,头盔就是 L2,等等。
    最后就是写 TEIGGER 了:

    E - 单位拣到道具
    C -
    A -
    +暂时关闭此触发
    +如果以道具等级为下标的变量 IF 值为假,则
    - 把物品栏的第 N 格道具丢弃,N 的值为拣到的道具等级
    - 把刚拣到的道具放到第 N 格
    - 把刚才丢弃的道具放置到第 M 格,M 的的值为此道具等级
    - 设置以道具等级为下标的变量 IF 值为真,则
    +否则如果以道具等级为下标的变量 IF 值为真,则
    - 丢弃这个被捡道具
    +打开此触发

    这个是捡道具的步骤,同样的你需要写一个丢弃道具的 TRIGGER ,内容就是将 以丢弃的道具等级为下标的 IF 设置为假。


    Q怎么做一个自动刷兵的效果呢?

    一般是要定时刷新的~~所以EVENT用PERIODIC TIME EVENT(周期性时间事件)~~间隔时间自己决定~~
    刷兵总得有个限制~~否则一直刷下去你打的完吗?所以在CONDITION中~~用INTEGER COMPRAISON - UNIT - COUNT UNIT IN UNIT GROUP(计算组内单位的数量,具体组的设定自己解决……)来比较你希望的一个数量~~如果小于这个数量~~则执行下面的 ACTIONS ~
    出兵最简单~~ ACTION - UNIT - CREATE UNIT~~种类、所属自己选~~位置就放在你要刷的地方~~一般是你要求刷出兵的建筑附近~~
    PS:以上就是最基本的刷兵了,至于其他的,例如什么时候开始刷,什么时候停止刷,EVENT自己决定吧,用ACTION - TRIGGER - TURN ON/OFF TRIGGER来开关触发器。


    Q在对战地图中,杀死对方的兵是不会获得金钱的,如何在战役中,可以获得金钱?

    在 TRIGGER EDITOR 里面用 Player - Turn Player Flag ON/OFF 开启金钱奖励~~
    在 UNIT EDITOR 里面用 Stats - Bounty Awarded - 来修改某杀死某单位后的金钱数量~~


    Q怎么才能设计一个简单的对话为主的动画呢?

    首先打开剧场模式 ACTION - CINEMATIC - CINEMATIC MODE ON
    然后用 ACTION - CINEMATIC - TRANSMISSION FROM UNIT 选择说话的单位、对话及时间等
    完了别忘了关闭剧场模式 TURN CINEMATIC MODE OFF
    PS:不开剧场模式一样可以使用TRANSMISSION FROM UNIT显示对话,要记得在初始化地图时打开普通场景下的字幕显示,ACTION - CINAMATIC - SUBTITLE DISPLAY OVERRIDE ON


    Q怎么才能设计出用 ESC 跳过的电影?

    建议打开官方的地图学习咯~~
    首先建立一个 BOOLEAN 变量 CIN_FLAG = FALSE ~~这个的作用是表示你是不是按下了 ESC 期望跳过~~
    然后在你写的影片 TRIGGER 中~~每一句后面都增加一句 "如果 CIN_FALSE == TRUE 则 略过后面的 ACTIONS 且 调用 中断处理 TRIGGER" ~~也就是说~~如果记录是否跳过的变量表示为真~~则可以略过后面所有的 ACTIONS ~~
    接着创建一个 TRIGGER ~~
    EVENT - 按下 ESC 键
    ACTIONS - SET CIN_FLAG = TRUE ~~这个就是让你在按下 ESC 后把变量表示为真~~这样就可以在上面的步骤中略过了~~
    最后建立一个 TRIGGER 作为中断处理部分~~提供上面说道的那个调用~~内容就是影片结束后的状态~~比如什么单位最后在什么位置~~


    Q如何做选英雄的TRIGGER?

    以下是最基本的英雄选择方法。
    先做些准备工作,在地图上放一个选人用的小精灵,再在适当位置放上一个力量之环(CIRCLE OF POWER)作为标识,在上面放上待选英雄,然 后在力量之环所在位置画上一个区域(REGION)。
    -建立TRIGGER-
    EVENT - UNIT ENTER REGION REGION就选你建立的那个REGION
    CONDITION - UNIT(TYPE) COMPARISON - ENTERING UNIT EQUAL TO 小精灵 条件判断,判断进入该区域的单位是不是小精灵(或者也可以用 UNIT TYPE COMPARISON来判断进入区域的单位类型是不是小精灵 UNIT TYPE OF ENTERING UNIT)
    POSITION就用你希望出现在的地方(一般你应该建立一个REGION表示游戏的起始点,就是这个啦)
    然后KILL ENTERING UNIT(杀死进入的单位,你要的是英雄而不是小精灵,杀死前你可以HIDE UNIT以隐藏死亡动作,或者干脆REMOVE掉)
    以上完成的就是最基本的选英雄的TRIGGER了,当然每多一个英雄你就得多做一个TRIGGER,并修改相应的CREATE UNIT的类型。对于那些只能选 一次英雄的方法嘛,只要在ACTION中加上TURN OFF THIS TRIGGER(关闭该触发)就可以了~~


    Q如何制作随机掉落物品?

    很多人问刷出来的怪怎么掉宝,以下是一种简单的基本的方法。


    EVENT 为 UNIT DIE 当然是要怪死了才掉宝的嘛
    CONDITION 怎么说呢,一般来说RPG地图里只要是敌人都有机会掉宝,那就用PLAYER COMPARISON - OWNER OF DYING UNIT 来判断。
    同时可以利用INTEGER COMPARISON - MATH - RANDOM NUMBER BETWEEN A TO B(A和B之间的随机数)是否等于(大于/小于)某值来做掉宝的几率。
    ACTION 用 CREATE ITEM ,ITEM TYPE可以选RANDOM ITEM-TYPE,然后选择等级(0-10级,可以根据某些规则来决定掉的是几级的宝,具体自己考虑吧,-1表示所有等级的宝物) POSITION就是POSITION OF DYING UNIT(死亡单位的位置)
    以上可以完成最简单的随机掉宝,具体大家可以慢慢考虑呵呵。


    QSUBSTRING函数 有什么用啊?

    SUBSTRING是截取字符用的~~如在下面一个赋值过程中:

    Set StoreEquitDate[StoreEquitDateLOG] = (Substring(‘XXXXXXXX’), 1, 5)
    (Substring(), 1, 5) 表示取字符串‘XXXXXXXX’中第1到第5位之间的字符串~~

    Q如何让游戏开起后,起始位置不会出现主城和工人?

    进入Trigger Editor,找到Melee Initialization,如果没改过的话应该如下:  
    Melee Initialization


    Events


    ......Map initialization


    Actions


    ......Melee Game - Use melee time of day (for all players)


    使一开始的游戏时间是早上6:00(如果删掉就会从00:00开始)


    ......Melee Game - Limit Heroes to 1 per Hero-type (for all players) 让所有玩家不能生產重覆的英雄


    ......Melee Game - Give trained Heroes a Scroll of Town Portal (for all players) 让第一个生產出来的英雄有传送卷轴


    ......Melee Game - Set starting resources (for all players) 让所有玩家一开始有一定的Gold和Lumber


    ......Melee Game - Remove creeps and critters from used start locations (for all players) 如果某起始位置有玩家,就删除附近的Creep


    ......Melee Game - Create starting units (for all players) 產生主城和工人于玩家的起始位置
    ......Melee Game - Run melee AI s (for computer players) 让电脑玩家有AI


    ......Melee Game - Enforce victory/defeat conditions (for all players) 使用一般的胜利/失败设定(毁掉对方所有建筑者胜) 


    将蓝色的那一条删掉即可  



    作者: 但偏偏雨渐渐    时间: 2006-2-28 09:55

    Q如何製作一个群体Sleep技能?

    Sleep在製作时就被销定為单体技能,因此想这麼做不是AE或者MOD可以解决的,必须使用Trigger来帮忙。以下為可行方法的其中之一:  


    1、将Sleep复製贴上,改名為Group Sleep - Sleep(举例,请自己决定一个适当的名字)。 把mana cost改為0、range改為99999(全地图)、改成单位技能(Is a hero ability = false)  


    2、製作一单位Sleep Caster,model改成none、技能加入刚才做的Group Sleep - Sleep及Invulnerable (Netural)。  


    3、将Sleep技能改名為Group Sleep  


    4、写Trigger:  


    Group Sleep Order


    ......Events


    ............Unit - A unit Is issued an order targeting an object


    //当一个单位接收到一个指定物件的指令


    ......Conditions


    ............(Issued order) Equal to (Order(sleep))

    //指令為sleep


    ......Actions


    ............Set GroupSleep_MajorTarget = (Target unit of issued order)


    //将指令指定的单位存在GroupSleep_MajorTarget这个变数中 


    Group Sleep


    ....Events


    ........Unit - A unit Starts the effect of an ability


    //当一个单位使得一项技能开始生效


    ....Conditions


    ........(Ability being cast) Equal to Group Sleep


    //使用的技能為Group Sleep


    ....Actions


    ........Unit Group - Pick every unit in (Units within 300.00 of (Position of GroupSleep_MajorTarget)) and do (Actions)


    //选取GroupSleep_MajorTarget这个单位附近300范围的所有单位并执行Loop Action内的所有动作


    ............Loop - Actions


    ................Unit - Create 1 Sleep Caster for (Owner of (Triggering unit)) at (Position of (Triggering unit)) facing 0.00 degrees     


    //產生一个单位于施法者(触发的单位)旁边,设定所有者為拥有施法者的玩家


    ................Unit - Add a 2.00 second Generic expiration timer to (Last created unit)


    //设定刚刚產生的单位生命时间為2.00(长度自己决定,足够施放AMS即可) ................Unit - Order (Last created unit) to Undead Dreadlord - Sleep (Picked unit)


    //命令刚刚產生的单位对选到的单位使用自身技能中Order為sleep的技能   这样就能做出一个范围300的群体催眠术咯!


    Q假设在一张 RPG 地图中, 给每一位玩家一个工人, 让玩家选英雄


    Event


    ......Unit - A unit enters


    Action


    ......Unit - Create 1 for Trigging Player at center of


    facing ......  


    为什麼单位进入该Region时没有反应?  

    设定错误。由于引发事件的是单位,而不是玩家,所以 Trigging Player 无法表明到底是哪一个玩家。正确的设定方式如下:  


    Event


    ......Unit - A unit enters


    Action


    ......Unit - Create 1 for (Owner of (Trigging Unit)) at center of facing ......    


    Q请问如何加入随机效果?  

    在设定Trigger时,用If/Then/Else做设定,例如:  


    PaladinSkill:


    Events


    ......Unit - A unit Is attacked


    //一个单位遭受攻击


    Conditions


    ......(Unit-type of (Attacking unit)) Equal to Paladin


    //攻击者為Paladin Actions


    ......If (All Conditions are True) then do (Then Actions) else do (Else Actions)


    ............If - Conditions


    ..................(Random integer number between 1 and 10) Equal to 1


    //如果1-10中随机选到的数字為1


    ............Then - Actions


    ..................Unit - Kill (Triggering unit)



    ------1/10


    //杀死引起触发的单位(遭受攻击的单位,用Attacked Unit也可以)
    ............Else - Actions


    ..................If (All Conditions are True) then do (Then Actions) else do


    (Else Actions) ------9/10


    ........................If - Conditions


    ..............................(Random integer number between 1 and 9) Equal to 1


    //如果1-9中随机选到的数字為1


    ........................Then - Actions


    ..............................Unit - Set life of (Triggering unit) to ((Life of (Triggering unit)) / 2.00) -----1/9*9/10= 1/10


    //将引起触发的单位生命值设為(触发单位生命值 / 2.00)
    ........................Else - Actions    
     
    这么一来,当Paladin攻击敌人时,就会有1/10的机会瞬间杀死对方,1/10的机会使目标的生命值减半。其他的依此类推。这是目前最简单有效的方法,更好的方法大概只能用JASS写了。


    Q如何获得一个技能的目标点?  

    用 TARGET POINT OF ABILITY BEING CAST 就能取到。


    E简单地说一下 GAME CACHE 的使用

    GAME CACHE ~~字面意思就是 游戏缓存 ~~用于开辟一个内存空间来保存用户希望 保留 的数据(最后需要将 CACHE 保存到 硬盘上)~~
    主要作用是将 地图A 的一些数据保留到 地图B 中~~比如战役中英雄的等级或者道具技能什么什么的~~


    GAME CACHE 是用 TRIGGER EDITOR 来操作的~~下面说说相关 ACTIONS 的含义~


    1]创建一个缓存~~想要使用缓存~~当然要先创建啦~~
    Game Cache - Create a game cache from MapName.w3v
    这就是一个创建 CACHE 语句~~后面的 MapName.w3v 是你创建的 CACHE 的名字~~:)~~


    2]创建以后~~就可以用他来保存资料了~~
    Game Cache - Store Unit as Lable of Category in (Last created game cache)
    这是一个 保存单位 的语句~~在 Unit 处选好需要保存的单位~~填写好 标识(Lable) 和 分类(Category) ~~最后 选择将 单位保存到 哪个 CACHE 里面~~其中 标识 和 分类是可以随意填写的~~:)~~


    类似的~~还有下面一些类型的数据可以保存到 CACHE 里面~~使用方法同上!
    Game Cache - Store Real as Lable of Category in (Last created game cache)
    Game Cache - Store Integer as Lable of Category in (Last created game cache)
    Game Cache - Store Boolean as Lable of Category in (Last created game cache)
    Game Cache - Store String as Lable of Category in (Last created game cache)


    (UNIT:单位 / REAL:实数 / INTEGER:整数 / BOOLEAN:布尔 / STRING:字符串)


    保存玩需要的数据后不要忘记保存 CACHE 本身~~
    Game Cache - Save (Last created game cache)


    上面说的是保存数据~~但是怎么取出数据呢?~~
    首先在任何可以使用 你想取出的数据类型 的地方都可以通过 GAME CACHE - LOAD XXXXXX CALUE 来取出数据~~


    另外~~
    Game Cache - Restore lable of Category from (Last created game cache) for Player 1 (Red) at (Center of (Playable map area)) facing 0.00
    Game Cache - Restore lable of Category from (Last created game cache) for Player 1 (Red) at (Center of (Playable map area)) facing (Position of (Triggering unit))

    这个语句是专门用于 取出一个被保存的单位且放置在地图上的~~


    最后~~如果想清除 CACHE 中的数据可以使用下面两个语句~~
    Game Cache - Clear (Last created game cache)
    清除所有数据~~
    Game Cache - Clear all labels of Category in (Last created game cache)
    清除某一类的数据~~


    Q嗯,如何动态改变中立商店/酒馆里卖的东西呢?

    Neutral Building - Add 物品/单位 to (商店/酒馆) with 初始存货数 in stock and a max stock of 最大存货数


    把贩售物存入一个数组,用trigger随机生成数组索引,可以做到真正的”人流不息“的酒馆。又如根据玩家游戏进行的状态,如获得的物品,在商店生成同等级的物品(TM中间的市场一样)等~
    记得商店/酒馆必须有相关的贩售技能(废话-_-)


    Q如何让一个召唤生物不能被选中但能被攻击呢?

    给一个单位添加 "Aloc" 技能, 就可以使它不能被选取, 就好象不死小强的终极技能Locust swarm召唤出的小小小飞强一样~~
    但是, 这个单位也同时失去了碰撞大小, 就是任何人都摸不到他拉, (像鬼魂般穿身而过). 这时配合"Chaos"就可完美解决!
    做两个相同的单位, 一个为真身, 一个为替身. 再自定一个Chaos技能, Data New Unit Type填单位的真身
    把"Aloc", 自定的"Chaos"添加给她, 这时候Chaos立即起作用, 替身单位变为真身, Aloc的"不被选取"作用保留, 而该单位也可同时承受攻击了!
    比如你想做召唤单位, Actions就是把这个自定义的"Chaos"添加给该单位

    就这么简单!
    这个"Aloc" + "Chaos"的组合是wc3c的一位mapper发现的, 用在雇佣兵上真是妙! 不用单心混战中错点到他们了~~

    Q:如何让自定义英雄和普通英雄一样有建造限制呢?

    首先,在游戏平衡常数中将您的自定义英雄添加到“科技 - 等价物 - 英雄”列表里面去,这样的话就能保证每升一级主基地只能造一个了。
    然后还要添加一条 Trigger :

    Player - Limit training of xxx to 1 for Player n (其中“ xxx ”为该自定义英雄的单位类型)

    这样您的英雄就只能造一个了

    Q:如何让死掉的树复活呢?

    很简单的,用 Destructible - Resurrect 即可。


    作者: 但偏偏雨渐渐    时间: 2006-2-28 09:56

    [WE] WE 中比较有趣/有用的技能

    -=Unkown Ability (一些暴雪没有注解的技能特性)=-

    Unkown (AHer) - Is Hero
    作为英雄:似乎只用于作为英雄的判断~~添加给普通单位没有效果(至少我没看到效果)~~如果从英雄身上移除则会发生程序错误~~


    Unkown (AEbu) - Build (Night Elf)
    Unkown (AGbu) - Build (Naga)
    Unkown (AHbu) - Build (Human)
    Unkown (ANbu) - Build (Neutral)
    Unkown (AObu) - Build (Orc)
    Unkown (AUbu) - Build (Undead)
    建造指令:可从农民等可以建造建筑的单位身上移除~~

    Unkown (Aatk) - Attack
    攻击指令:从 可攻击 的单位身上移除后则不可攻击~~本来尝试以 Aatk 作为摸版创造不同攻击特性的 新ATTACK~~比如范围/目标类型等~~但是似乎没有效果(有兴趣的可以去尝试尝试:)

    Unkown (Amov) - Move
    移动指令:基本上也是被移除后则不可移动~~其中有一个已知的作用是“不可移动的物体不能修改 FACE ANGEL,但是被移除了 Amov 的单位则可以,前提是希望单位不能移动,比如希望一个单位自转时”

    Unkown (ARal) - Rally Point
    集结点:拥有训练单位的能力的时候~~通常都附带了这个能力~~删除后则不能设定集结点~~作用显而易见~~通常是为了美观删除之~~

    Unkown (Afih) - On fire (Human)
    Unkown (Afin) - On fire (Night Elf)
    Unkown (Afio) - On fire (Orc)
    Unkown (Afir) - On fire (Neutral)
    Unkown (Afiu) - On fire (Undead)
    准备:未知~~

    Unkown (Aloc) - Locust's Unselectable ability
    不可选中:拥有这个能力的单位拥有 不可选中/不可控制/无敌 的特性(没有尝试过添加此能力后再移除一个无敌能力是否可以使单位仅仅不可被选中)~~拥有此能力之前为此单位编队后~~即使不可选中却依然可以通过编队选择~~但是不能控制~~

    Unkown (Aalr) - Alarm Ability
    警报:未知

    Unkown (Atdp) - Drop Pilot
    卸载驾驶:未知
    Unkown (Atlp) - Load Pilot
    装载驾驶:未知 (使用后出现程序错误)

    Unkown (Attu) - Tank Turret
    坦克炮塔转台:未知

    Unkown (AEpa) - ????
    一个英雄技能~~
    Stats - Durations 有效~~
    拥有 Slow Poison 类似的 DATA 项:
    Data - Attack Speed Factor (攻击速度系数)
    Data - Damage per Second (每秒伤害)
    Data - Extra Damage (额外伤害)
    Data - Movement Speed Factor (移动速度系数)
    Data - Stacking type - Attack Rate (叠加类型 - 攻击速度)
    - Damage (叠加类型 - 伤害)
    - Kill unit (叠加类型 - 致死)
    - Movement (叠加类型 - 移动)
    但是根本不能学习~~晕~~

    -=Another Abilitys (其他一些有趣的技能特性)=-

    Way Gete Ability
    传送门能力:在地图初始化的时候会在拥有此能力的单位位置创建一个区域~~进入此区域的单位会被传送到可变的目标位置~~
    在可移动单位身上添加此技能后~~如果此单位没有离开初始区域则可以被当作传送门使用~~且如果命令此单位向传送的目标位置移动则自己会被传送过去~~如果离开初始区域~~则点击此单位的其他单位会在接触此单位后向传送的目标位置移动~~

    Wander
    徘徊:拥有这个能力的单位会不断的做随机移动~~

    Spell Book
    魔法书:这玩意儿放在身上做多层菜单最好不过了~~

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


    作者: 但偏偏雨渐渐    时间: 2006-2-28 09:57

    [WE JASS] AI脚本初级教程

    JASS与C语言很类似,所以在阅读以下内容之前,首先应该对TRIGGER JASS有着一定的了解。
    了解JASS之后,你将很快的了解AI JASS。
    AI JASS的概念
    最主要的是理解AI线程(Threads)的概念。
    线程是什么?
    线程就象TRIGGER的一个循环判断语句,线程会不停的判断在线程程序列表内所缺少的元素,并去按照线程的指令排放顺序去完成它。
    就象碗中的饭,有即吃,有即吃,有即吃,Loop......
    为什么不用TRIGGER去完成电脑的人工智能呢?
    由于使用TRIGGER相比之下可能会消耗大量的内存,所以,最好用AI线程来完成电脑的人工智能。
    注意: 线程只针对单个玩家运作。

    AI的类型(Melee AI 和 Campaign AI )
    Melee AI 对战AI基本上完全可以利用WORLDEDITOR自带的AI编辑器(AI Edior)完成
    Campaign AI 战役AI(即“非对战AI”),可以详细了解以下内容即可制作一般常用的战役AI
    注:战役AI的用途十分广泛,完全可以利用其制作生存,3C,TD等类型的地图,并且免除了不停使用TRIGGER创造单位所带来的内存泄露。



    线程(Threads)和触发器(Trigger)的区别AI脚本只能使用JASS函数库common.j和common.ai中的函数和量Trigger脚本只能使用common.j和Blizzard.j中的函数和量线程只应用于AI脚本(AI JASS), 不能用于触发器脚本(Trigger Jass)触发器只应用用于触发器脚本(Trigger Jass),不能用于AI脚本(AI JASS)
    通常, 当AI脚本开始运行时只创建一个线程, 创建更多的线程可以用comman.j的本地函数:
    native StartThread takes code func returns nothing
    运行方式的区别在于线程一旦开启即可自动运转,触发器必须调用或者借助事件的发生才可以运行。 调用 call StartThread(function myfunc) 将创建一个从函数myfunc开始执行的线程.
    调用 call SleepForever() 使线程永久性的关闭 *每个玩家最多可以拥有6个线程(包括一开始执行的主线程在内,当一个玩家有6个线程数时, 调用StartThread()的语句将被忽略. ) *线程不能回收, 当你为某玩家创建了5个自定义线程, 将无法为该玩家创建更多的线程. *局域性的全局状态,在同一玩家中的所有线程都共享全局状态(包括变量). 即是修改某个全局变量, 修改后的值在此玩家的所有线程中都是可见的. *当新线程创建时, 线程立即生效. *当线程让步执行时, 创建此线程的父线程将继续执行.

    线程在以下的情况让步执行, 返回父线程
    a) 当线程中的操作码(opcode)超出限制, 线程会自动休眠 1 秒
    当线程中用使用 Sleep(n), 线程将休眠 n 秒, 然后继续执行.

    线程在以下情况会中止, 返回父线程
    a) 如果 call StartThread(null)中, 线程中止
    当线程的主函数返回, 线程中止.
    (StartThread()中之间调用的函数就是主函数.)
    c) 当线程中使用没有声明的变量, 线程中止. 在使用之前, 变量必须声明.
    d) 当线程中出现零为被除数时, 线程中止
    e) 线程主函数出现语法错误.
    注意: 虽然AI脚本可以使用大部分common.j的库函数, 但有些类型的函数在AI不能正常工作, 如:
    a) 返回字符串类型(string)的本地函数, 如I2S(), SubString()等
    需要以code, trigger, boolexpr 等类型数据为参数的本地函数, 如触发器函数, 队列函数(ForGroup, 等)

    注意: AI中不可以使用Blizzard.j的函数, 触发器中也不可以使用common.ai的函数, AI和触发器都可以使用common.j的函数(当然, 对于AI, 还受上面所说的限制)

    common.ai和common.j是写AI时可以调用和参考库文件, 要研究AI, 先去读这2个文件.******************************************************************

    3) 跨脚本通讯(Inter-Script Communication)
    在游戏中, 可能会有多个独立的Jass脚本文件同时运行. 比如在对战地图中的游戏, 运行触发器脚本文件的同时, 也可能运行了每个电脑玩家的AI脚本文件. 每个脚本文件之间的全局变量不是共享的. 所以, 一个电脑玩家的AI脚本中设置的全局变量不会影响另一个电脑玩家的AI脚本的执行.

    触发器脚本也不可以和AI脚本共享全局变量. 但可以用传递命令的方法进行脚本之间的数据交换. 命令由一对数值型数据(integer)组成: 命令值(command value)和数据值(data value).

    从触发器脚本向AI脚本发出通讯命令, 可以使用common.j中定义的以下本地函数:
    native CommandAI takes player num,
    integer command, integer data returns nothing

    参数:
    player num //玩家
    integer command //命令
    integer data //命令数据




    常数
    //--------------------------------------------------------------------
    constant integer M1 = 60 实际上是时间!
    constant integer M2 = 2*60
    constant integer M3 = 3*60
    constant integer M4 = 4*60
    constant integer M5 = 5*60
    constant integer M6 = 6*60
    constant integer M7 = 7*60
    constant integer M8 = 8*60
    constant integer M9 = 9*60
    constant integer M10 = 10*60
    constant integer M11 = 11*60
    constant integer M12 = 12*60
    constant integer M13 = 13*60
    constant integer M14 = 14*60
    constant integer M15 = 15*60

    constant integer EASY = 1
    constant integer NORMAL = 2
    constant integer HARD = 3
    constant integer INSANE = 4 // not used

    constant integer MELEE_NEWBIE = 1
    constant integer MELEE_NORMAL = 2
    constant integer MELEE_INSANE = 3

    constant integer ATTACK_CAPTAIN = 1
    constant integer DEFENSE_CAPTAIN = 2
    constant integer BOTH_CAPTAINS = 3

    constant integer BUILD_UNIT = 1
    constant integer BUILD_UPGRADE = 2
    constant integer BUILD_EXPAND = 3

    constant integer UPKEEP_TIER1 = 50
    constant integer UPKEEP_TIER2 = 80




    JASS函数库common.ai的全局变量(可以更改,也可以自行增加,以下内容会经常在AI脚本中使用):
    player ai_player //AI玩家 integer sleep_seconds
    //等待时间
    integer total_gold = 0 //总计的金钱 integer total_wood = 0
    //总计的木材
    integer gold_buffer = 0
    // usually for potion money
    integer difficulty = NORMAL
    //难度,默认为中等难度
    integer exp_seen = 0
    integer racial_farm = 'hhou'
    integer hero_id = 'Hamg'
    //第一个英雄的ID,默认为圣骑士
    integer hero_id2 = 'Hmkg'
    //第二个英雄的ID,默认为山丘之王
    integer hero_id3 = 'Hpal'
    //第三个英雄的ID,默认为大法
    integer array skill
    integer array skills1
    integer array skills2
    integer array skills3
    integer max_hero_level = 0
    integer array harass_qty
    integer array harass_max
    integer array harass_units
    integer harass_length = 0
    防守单位的全局变量
    例子:防守单位defense_units[defense_length]的数量为defense_qty[defense_length]
    integer array defense_qty //设置防守单位的数量
    integer array defense_units //设置防守的单位
    integer defense_length = 0 //单位Index
    建造的全局变量
    为了区分建造的种类,BLZ为建造的全局变量设置了4类例子:建造单位build_type[build_length]的数量为build_qty[build_length]
    integer array build_qty //建造的数量 设置建造单位的数量
    integer array build_type //建造的种类 普通单位类(包括单位和建筑)
    integer array build_item //购买物品的种类 物品类
    integer array build_town //建造基地的种类 基地类
    integer build_length = 0
    设置采集工人的数量
    integer campaign_gold_peons = 5 //主基地采集金子的人数
    integer campaign_wood_peons = 3 //住基地采集木材的人数
    integer campaign_basics_speed = 5
    integer min_creeps = -1 integer max_creeps = -1
    游戏初试设置的全局变量
    boolean harvest_town1 = true
    boolean harvest_town2 = true
    boolean harvest_town3 = true
    boolean do_campaign_farms = true
    //自动制造战役AI 提供人口的建筑
    boolean two_heroes = false
    //双英雄
    boolean allow_air_creeps = false
    //空中的中立单位(假如有,AI会针对性的发展)
    boolean take_exp = false //<





    一般战役AI常用函数


    CampaignAI takes integer farms, code heroes returns nothing
    是BLZ在COMMON.AI中设置的一个简便函数,直接初始化战役AI
    farms - 提供AI玩家人口的建筑类型
    heroes - 指向设置英雄的ID的CODE

    SetReplacements takes integer easy, integer med, integer hard returns nothing
    尚未研究的函数,一般用法为:
    call SetReplacement( 2, 2, 4 )
    easy - 游戏难度为简单所赋的值
    med - 游戏难度为普通所赋的值
    hard - 游戏难度为困难所赋的值

    native SetCaptainHome takes integer which, real x, real y returns nothing
    设置攻击组队长在家的点?
    which - 什么的聚集点,参数有:
    constant integer ATTACK_CAPTAIN = 1 进攻的点
    constant integer DEFENSE_CAPTAIN = 2 防御的点
    constant integer BOTH_CAPTAINS = 3 进攻和防御的点
    x - X坐标
    Y - Y坐标

    SetBuildUnit takes integer qty, integer unitid returns nothing
    指令AI玩家制造(所有类型的建造,包括升级)
    qty - 数量
    unitid - 单位类型

    SetBuildUnitEx takes integer easy, integer med, integer hard, integer unitid returns nothing
    指令AI玩家制造单位按照游戏难度
    easy - 简单时候的数量
    med - 普通时候的数量
    hard - 困难时候的数量
    unitid - 单位类型

    CampaignDefender takes integer level, integer qty, integer unitid returns nothing
    设置防守单位的数量

    CampaignDefenderEx takes integer easy, integer med, integer hard, integer unitid returns nothing
    设置防守单位的数量,
    按难度 call WaitForSignal() 等待TRIGGER发出AI指令,当堆积的指令数量不等于0时,继续进行AI线程


    进攻组的指令
    function InitAssaultGroup takes nothing returns nothing
    初始化进攻组,设置全局变量harass_length = 0


    CampaignAttacker takes integer level, integer qty, integer unitid returns nothing
    增加进攻组的进攻单位
    qty - 数量
    unitid - 单位类型

    CampaignAttackerEx takes integer easy, integer med, integer hard, integer unitid returns nothing
    增加进攻组的进攻单位,按游戏难度
    easy - 简单时候的数量
    med - 普通时候的数量
    hard - 困难时候的数量
    unitid - 单位类型

    SuicideOnPoint takes integer seconds, player p, integer x, integer y returns nothing
    设置进攻的玩家的点seconds 发起进攻等待的时间,
    常量参数有
    constant integer M1 = 60
    constant integer M2 = 260
    constant integer M3 = 360
    constant integer M4 = 460
    constant integer M5 = 560
    constant integer M6 = 660
    constant integer M7 = 760
    constant integer M8 = 860
    constant integer M9 = 960
    constant integer M10 = 1060
    constant integer M11 = 1160
    constant integer M12 = 1260
    constant integer M13 = 1360
    constant integer M14 = 1460
    constant integer M15 = 1560
    p - 目标玩家

    SuicideOnUnits takes integer seconds, player p returns nothing
    设置进攻的目标玩家seconds





    一般战役AI的制作方案
    参看BLZ在战役中所制作的AI脚本“n08_green.ai”来了解怎么制作AI
    //变量 进攻的目标玩家
    globals
    player user = Player(1)
    endglobals function main takes nothing returns nothing //AI初试设置
    call CampaignAI(ZIGGURAT_1,null)
    call SetReplacements(2,2,4)
    call SetCaptainHome(ATTACK_CAPTAIN,4161,-4668 )
    call SetCaptainHome(DEFENSE_CAPTAIN,5218,-6441 )
    set campaign_wood_peons = 2 //需要建造的建筑以及单位
    call SetBuildUnit( 1, NECROPOLIS_1 )
    call SetBuildUnit( 1, ACOLYTE )
    call SetBuildUnit( 1, UNDEAD_MINE )
    call SetBuildUnit( 1, GRAVEYARD )
    call SetBuildUnit( 8, ZIGGURAT_1 )
    call SetBuildUnit( 2, CRYPT )
    call SetBuildUnit( 1, UNDEAD_ALTAR )
    call SetBuildUnit( 1, NECROPOLIS_2 )
    call SetBuildUnit( 2, SLAUGHTERHOUSE )
    call SetBuildUnit( 1, DAMNED_TEMPLE )
    call SetBuildUnit( 1, NECROPOLIS_3 )
    call SetBuildUnit( 2, BONEYARD )
    call SetBuildUnit( 5, ACOLYTE )
    call SetBuildUnit( 8, ZIGGURAT_2 ) //防守单位
    call CampaignDefenderEx( 1,1,2, ABOMINATION )
    call CampaignDefenderEx( 1,1,1, GARGOYLE )
    call CampaignDefenderEx( 1,1,1, FROST_WYRM )
    call CampaignDefenderEx( 1,1,1, CRYPT_FIEND )
    call CampaignDefenderEx( 1,1,1, DREAD_LORD ) //TRIGGER发出指令就开始进行下面的AI进程
    call WaitForSignal() //进攻,制造
    //WAVE 1
    call InitAssaultGroup()
    call CampaignAttackerEx( 6,6,8, GARGOYLE )
    call SuicideOnPlayerEx(M5,M5,M3,user)
    call SetBuildUpgrEx( 1,1,1, UPG_FIEND_WEB )
    call SetBuildUpgrEx( 1,1,1, UPG_CANNIBALIZE )
    call SetBuildUpgrEx( 1,1,1, UPG_UNHOLY_STR )
    call SetBuildUpgrEx( 1,1,1, UPG_CR_ATTACK )
    //WAVE 2
    call InitAssaultGroup()
    call CampaignAttackerEx( 6,6,8, GARGOYLE )
    call CampaignAttackerEx( 2,2,4, CRYPT_FIEND )
    call CampaignAttackerEx( 1,1,2, FROST_WYRM )
    call SuicideOnPlayerEx(M6,M6,M4,user)
    //WAVE 3
    call InitAssaultGroup()
    call CampaignAttackerEx( 6,6,8, GARGOYLE )
    call CampaignAttackerEx( 2,2,4, CRYPT_FIEND )
    call CampaignAttackerEx( 1,1,2, FROST_WYRM )
    call CampaignAttackerEx( 1,1,1, DREAD_LORD )
    call SuicideOnPlayerEx(M6,M6,M4,user)
    call SetBuildUpgrEx( 2,2,2, UPG_UNHOLY_STR )
    call SetBuildUpgrEx( 2,2,2, UPG_CR_ATTACK )
    call SetBuildUpgrEx( 1,1,1, UPG_SKEL_LIFE )
    call SetBuildUpgrEx( 1,1,1, UPG_WYRM_BREATH )
    //WAVE 4
    call InitAssaultGroup()
    call CampaignAttackerEx( 2,2,3, GARGOYLE )
    call CampaignAttackerEx( 5,5,6, CRYPT_FIEND )
    call CampaignAttackerEx( 1,1,2,

    作者: 但偏偏雨渐渐    时间: 2006-2-28 09:58

    [WE] 最大程度降低你的图的lag

    经验.总结.探讨 欢迎收看IZ's WE小技巧集(TM)!!


    最大程度降低你的图的lag


    1, 一定记得RemoveLocation


    前不久Blizzard发布了一张自己内部做的TD~~各方面之严谨~~真可为又一WE模范教材!! 而里边的Trigger也继承了Blizz(TM)地图的一贯风格: 要么让人"看不懂"~~ 要么让人觉得"太繁琐了,没必要吧?!". 比如,


    Unit - Order (Last created unit) to Move To (Random point in Region 050 <gen>)


    这么简单的触发他也要写成


    Set TempLoc = (Random point in Region 050 <gen>)
    Unit - Order (Last created unit) to Move To TempLoc
    Custom script: call RemoveLocation(udg_TempLoc)



    实际上这是相当严谨的写法~~~ 大家有没有一种感觉, 一些大的地图玩起来会越来越慢, 退出的时候也要很长时间. 这是因为游戏中的点(point),区域(region),单位(unit),物品(item)等等外部定义类型在游戏执行中实际是类似指向某一内存地址的指针, 游戏中每创建一个变量, war3都会分配一段内存给它, 当用过后不把内存释放, 内存就会越积越多, 这个时候就感觉到要~~爆(拉长音)~~了~~


    (当然win2k或xp可以写pagefile, 不过直接导致退出的时候war3要清理大量数据)


    所以像竞技地图经常用到的"某一单位移动到某一点", 如果不用call RemoveLocation把这个点释放, 就等着lag吧~~


    Trigger技能更是如此! 这样写对减低lag的效果很明显! 还有Special Effects创建了以后不移除, 那这个技能用得越多, lag的机会越大


    推荐大家用这两个函数创建特效


    AddSpecialEffectLocWithTimer
    http://kattana.users.whitehat.dk/viewfunc.php?id=31


    AddSpecialEffectTargetUnitWithTimer
    http://kattana.users.whitehat.dk/viewfunc.php?id=32



    2, DestroyTrigger
    在地图初始化trigger的行为末尾加上一句


    call DestroyTrigger(GetTriggeringTrigger())


    可以有效减低游戏刚开始的lag, 但也只对某些地图有效, 具体还是取决于你初始化的行为有哪些. 实在lag的时候再试试吧



    3, Periodic Event
    每xxx秒执行一次的事件, 也是lag的主因之一, 如果你在地图里用多的话, 建议对其进行一些优化. 比如满足特定条件时再用


    Trigger - Add to (trigger) the event (Time - Every 2.00 seconds of game time)


    把Event加上, 总比游戏一开始就不停的动好吧~~


    4, Map initialization
    在编辑器里预放置单位和在地图初始化里创建的单位越多, 地图读取时间越长, 开始时lag的机会越大; 而全部放到游戏中创建的话, 也容易导致lag. 总之, 不在某一时刻同时创建过多单位, 或者让建筑单位生产代替用trigger创建都是不错的解决办法~



    5, bj_wantDestroyGroup
    大家都喜欢用


    Unit Group - Pick every unit in (xxxxx)


    等类似行为来选取满足特定条件的单位, 实际上这个时候就等于创建了一个新的Unit Group, 占用一定的内存空间, 所以用过后也应该把它移除. 方法是在前面加上


    Custom script: set bj_wantDestroyGroup = true



    比如:


    Custom script: set bj_wantDestroyGroup = true
    Unit Group - Pick every unit in (Units owned by Player 1 (Red)) and do (Unit - Order (Picked unit) to Move To (Center of (Playable map area)))



    当Blizzard.j里的Unit Group相关函数执行时会检查bj_wantDestroyGroup, 再决定是否移除Unit Group.


    做到以上几点, 你的图一定比其它人的环保/流畅多了~~

    作者: 但偏偏雨渐渐    时间: 2006-2-28 09:59

    [WE] 面向初级的Trigger技能教程

    此教程适合对WE有一些了解的人,所以不会对所有的命令全部加以解释,自学为主!


    先介绍一下TRIGGER
    TRIGGER在这里的中文意思就是触发器,每个TRIGGER包括3个部分:EVENT、CONDITION、ACTION,也就是常用的ECA机制:事件、条件、动作
    EVENT:事件,说明该TRIGGER在什么情况下会被触发,例如Unit - A unit Dies(单位死亡), Unit - A unit Acquires an item(单位获得道具),等等,都是触发事件
    CONDITION:条件,也可以说是环境,用来判断TRIGGER在触发后是否满足一定的情况,例如 (Triggering unit) Equal to Hero(触发单位等于Hero,这里的Hero是Unit类的变量,当触发单位等于Hero时,将返回True,触发器将被触发,反之则不被触发),条件可以是复数的,用And或Or来决定条件之间的关系
    ACTION:动作,就是在触发器触发后该执行的动作,例如 Unit - Move (Triggering unit) instantly to (Center of (Playable map area)) (将触发单位移动到地图中央),Unit - Add Bloodlust to (Triggering unit) (将嗜血技能添加给触发单位)等等,这个是触发器中可变性最强的地方,所有你想到的东西都将能在这里实现


    以上就是最基本的TRIGGER的介绍了,聪明的朋友应该已经知道TRIGGER技能应该怎么做了吧?下面就把我制作各种TRIGGER技能的心得给大家详细介绍一番,虽然不一定是最好的最有效率的方法,但确实可以给各位初学者们指一条明路……



    在正文开始之前,请各问先考虑下面这个问题:
    复合技能过程的口头描述:当一个单位开始施放一个技能,并且该技能等于XX时,创建一个辅助施法单位对目标单位再施放一个技能,以此完成复合技能的全部过程


    各位可以根据以上的描述,考虑一下单体技能群体化的描述


    第一讲 复合技能的制作


    凡事从简单的做起,其实最简单的就是复合技能了,对于即时生效的复合技能非常简单,但是对于有攻击延时的技能就有点麻烦,例如要做出被死亡缠绕击中同时减防的技能,你并不能完全精确的做到被死亡缠绕击中那一刻给目标单位加上减防技能……虽然其中可以用WAIT命令来模拟效果,但是说实在的效果并不是很好,所以这里暂时只针对即时生效的复合技能,做个介绍


    技能:电能激发
    效果:激发目标单位身上附带的电能,加快其行动速度,身上的电能会对接近他的单位造成伤害
    解释:其实这个技能就是嗜血+闪电盾的效果啦,所以很简单,先要做一个用于施放的技能,如果你用嗜血,那么闪电盾就作为辅助技能;同样如果你用了闪电盾,那么嗜血就是辅助技能了;本例中以闪电盾作为施放技能
    准备工作:把闪电盾技能做成英雄技能,去掉科技要求;做一个3级的嗜血技能,同样去掉科技要求(这点很重要,如果到时候放不出来可别怪我没提醒你),最好可以把COOLDOWN和MANA COST改到0,方便施放嘛;新建一个单位(我起名辅助施法,这个随便你的),把做好的嗜血术加给他,记得调整该单位的MANA让他可以够放这个技能,以及其他需要修改的地方,具体可以看我的演示内容


    触发器内容


    这里开始详细介绍一下


    EVENT:一个单位施放的技能开始生效


    CONDITION:施放的技能是“电能激发”


    (Ability being cast) 这个函数是在EVENT - CAST ABILITY一类里用于响应施放的技能的,返回值就是当前被施放的技能类型


    ACTION:


    1. 在目标单位的位置为触发单位的玩家创建一个辅助施法的单位,面向默认角度


    2. 将最后创建的单位(即辅助施法单位)的嗜血技能等级设置为 触发单位施放技能的等级


    3. 为最后创建的单位创建1秒的生命时间钟


    4. 隐藏最后创建的单位


    5. 命令最后创建的单位对目标单位施放嗜血技能


    看懂了吧?这些中文解释各位读者还满意吧?下面详细介绍一下其中用到的函数……


    (Triggering unit) 响应UNIT类的事件,返回值为触发该触发器的单位,本例中就是施放技能的单位


    (Target unit of ability being cast)响应技能施放事件,返回值为施放技能的目标单位(用于目标为单位的技能,如果技能是对点施放的,则用Target point of ability being cast来取得技能的目标点)


    (Last created unit)返回值为最后创建的那个单位,一般都跟在CREATE UNIT的语句后使用


    (Owner of (Triggering unit))这是2个函数的嵌套,不要以为很麻烦,能理解了就很容易,(Owner of unit)是外层那个函数,返回值是unit所属的玩家,那么各位应该知道(Owner of (Triggering unit))是什么意思了吧?没错,触发单位的所属玩家


    (Position of (Target unit of ability being cast))同上,(Position of unit)返回值是unit的位置,(Position of (Target unit of ability being cast))则表示目标单位的位置


    (Level of (Ability being cast) for (Triggering unit))什么意思呢?触发单位的施放技能等级


    以上那些函数啊,能够熟练使用就好啦


    对ACTION的一些解释:


    设置辅助施法单位的技能等级,理所当然吧?除非你每级的效果都一样,可以省略这步


    创建生命时间钟,为了1秒钟后让该单位自动销毁,释放内存,否则地图上单位会越来越……


    隐藏单位,做什么都要做得像一点,总不能让人看见所谓的复合技能是旁边那丫帮你的吧?


    OK,以上就完成了最简单的复合技能的制作,有了这一招,同学们已经可以做很多很多东西了吧?不过要记住,好好把施放技能和辅助效果技能联系起来,比如持续时间一般都应该是相同的等等……不要给玩家看出破绽就行啦……


    下节课,群体技能

    第二讲 群体技能




    一样,暂时介绍即时生效的群体技能


    技能:经典中的经典:群体睡眠
    效果:范围内的敌人有一定几率会进入睡眠状态,成功的几率会随等级提升
    解释:最最基本的单体技能群体化的演示,还记得我让大家考虑的描述吗?呵呵其实就是,选取范围内的所有敌人,并对每一个敌人创建一个辅助施法单位,对其使用睡眠
    准备工作:首先一样,需要一个用于施放的技能,现在的Channel(通魔)技能已经可以做到有范围的施放技能的模式了,但唯一的缺点在于电脑不知道如何使用……所以,如果大家觉得方便的话,就拿Silence(沉默术)来做施放技能吧,只要把技能的效果改成无效、持续时间改到0,并把作用对象改成AIR+WARD(一般不会有那么变态的单位存在的呵呵,所以沉默的效果不会影响到其他的单位,因为我们只要用到他施放技能的那个圈圈就行了);同时制作一个Sleep技能,添加给辅助释放单位;具体设置可以参照演示里的内容


    触发器内容


    看上去和上一次讲的差不多哦,所以这里我只解释新的东西


    重点在ACTION里的第一句,也就是Pick up unit


    这里整句的意思(句子太长请看演示):选取所有在以施放技能的目标点为中心,100+100*技能等级为半径内,所有活着、并且是触发单位的敌对玩家的单位


    以上就把规定范围内(200,300,400)的敌人挑出来了


    接着是IF语句,用来判断条件:在1-100取一个随机数,是否小于等于20+20*技能等级(40,60,80)


    后面的都一样了,不懂的请看上一课


    接着解释一下新用到的函数


    首先是在Pick un unit命令里,用的是Unit In Range Matching Condition的函数,这条函数表示的是在范围内满足条件的单位,接着选取中心点(Target point of ability being cast技能目标点)以及范围(100+100*技能等级)然后就点开Condition选择选取的条件


    因为要选取的单位是活的并且要是敌人的,所以需要用到And关系来将2条判断联系起来


    (Unit is alive)用判断Unit是否存活用的


    (Unit belongs to an enemy of Player)是用来判断Unit是否是Player玩家的敌对单位


    注意一点,在Match Condition语句里,所有表示在比较的单位,全部用Matching Unit这个函数来表示,Match Unit唯一用在这里也只能用在这里,具体可以看演示,需要自己理解,说不清楚


    然后是在IF语句里的Random Number函数,该函数会返回在上下限之间随机的一个数,通过和固定数比较可以实现一定几率触发的效果


    其他的命令和上一次的都一样就不多做解释了


    大家可以看懂吧?看不懂?看不懂就去做,不做怎么可能懂


    演示,是给你看效果的


    教程,是对演示的详细介绍


    当然对TRIGGER熟悉之后,光看演示就已经可以学到很多自己想不到的东西了


    这次就说到这里


    第三讲 制作全新的技能(一)

    的确的确,总是搞复合啊、群体啊也是非常有限制的,但是只要各位能够很清楚的了解各个ACTION的作用的话,是完全可以做出全新的技能的,例如非常经典的时间静止就是利用PAUSE UNIT命令来实现的,当然本教程并不是给你们解释各种命令什么用的,而是给你们介绍如何利用TRIGGER来做一些自己的原创技能

    技能:附魔武器-冰
    效果:使目标的攻击附带冰冻属性并增加一定伤害,持续45秒
    解释:大家都知道那个FROST ORB的效果,没错!这个技能其实就是把FROST ORB的效果直接添加到单位身上,用的是UNIT-ADD ABILITY来实现这个效果,很简单吧?想必我不说下去大家都知道该怎么做了……不过我认为呢,可能重点更在于那个持续45秒吧,因为有很多人不知道用什么好办法来解决这个WAIT的问题……下面开始具体的制作

    准备工作:首先要做一个施放技能,因为这次的效果是完全用TRIGGER产生的,也就是说施放技能是没有任何效果的,只是用来触发的,所以,这里推荐一个技能:CHANNEL(通魔),CHANNEL可以做出各种施放条件的技能,以单位、点、范围、立即生效为目标的等等都可以很方便的做出来,唯一的缺点就是,电脑的AI并不会自动的使用它(这个真是大麻烦啊~得自己写TRIGGER让电脑用哎)。当然你也可以找一些无效果的技能(例如INNER FIRE效果改0啊等等)作为施放技能,不过本例中就用CHANNEL来做啦,别忘了做一个3级的FROST ORB的技能哦


    插入内容:CHANNEL技能中一些重要的东西
    ART DURATION:技能动作的时间,就是指在你的单位开始做施放技能的动作后多少时间,才开始这个技能的效果

    BASE ORDER ID:基本命令ID,这个ID随便选啦,如果用了不同的ID,就可以把多个CHANNEL技能放在一个单位身上了,在用ORDER命令施放技能时用到的也是这个ID

    DISABLE OTHER ABILITIES:取消其他技能,就是说使用该技能时你的单位就不能移动和使用其他技能一直到该技能效果结束后才能移动



    OPTION: VISIBLE:可见的,不打勾就看不到这个技能了
    TARGETING IMAGE:目标图象,就是施放范围技能时那个大圈圈
    PHYSICAL SPELL:物理技能,可以对魔免的用,就像蜘蛛的网那样
    其他几个根本用不到嘛……就不说了
    TARGET TYPE:施放类型: INSTANT:立即,像山丘的震地那样
    UNIT TARGET:单位目标,像山丘的锤子那样
    POINT TARGET:点目标,像大法的暴风雪那样
    UNIT OR POINT TARGET:单位或点目标,牛头人的震荡波那样
    基本上要做各种施放方式的技能改改以上几个就够了,自己多用用就知道了

    插入完毕



    触发器内容



    怎么样,有了前2次的讲解,函数已经没什么大问题了吧?



    现在先给大家介绍一下新出现的命令

    ACTION第3和最后一句就是ADD ABILITY和REMOVE ABILITY命令了,作用非常简单,从指定单位身上添加和移除技能,没啥好说的



    CONDITION里第2句,是一个判断语句,用来判断目标单位身上的“附魔武器-冰”的效果是否存在,当该技能等级为0时,即没有这个技能



    整个TRIGGER的意思就是,当使用“附魔武器-冰”技能时,如果目标单位身上没有被用过该技能,则技能生效,并在15秒后,移除效果(这个WAIT的时间大家自己改吧)



    最后是ACTION里的第一句,用来解决WAIT问题的关键:局部变量



    局部变量的定义我不多做解释,懂得编程的人肯定知道,不懂就去网上找找介绍什么的,反正用局部变量真的是很方便啊~每次调用这个TRIGGER时,都会帮你开辟一个局部变量的空间,所以完全不需要担心会产生冲突。写局部变量需要用到CUSTOM SCRIPT,对局部变量进行声明的格式如下:



    local (变量类型) (变量名)



    由于JASS是严格区分大小写的,所以一定记得要用小写的local,变量类型在本例中是unit类型的,变量名则是udg_target_unit



    其实各位在TRIGGER EDITOR里定义的全局变量,会被系统自动在最前面加上“udg_”,而这里对局部变量的声明,又正好重复了已经创建的全局变量target_unit的名字,这是问题的关键,在函数内部定义的局部变量将代替同名的全局变量产生效果!所以说,在全局变量里定义的target_unit变量,其实只是为了可以在TRIGGER里直接调用局部变量而不用把整个TRIGGER都写成SCRIPT形式而用。



    第一句声明了局部变量的类型和名称,所以之后TRIGGER中所有的target_unit都将成为局部变量



    第二句将施放技能的目标单位赋值给局部变量target_unit



    第三句将附魔武器-冰的效果添加给target_unit(也就是施放技能的目标单位)



    第四句设置效果技能等级



    第五句等待延时



    第六句第三句将附魔武器-冰的效果从target_unit身上移除



    可能同志们会问为什么不能在WAIT后直接调用(Target unit of ability being cast)这个函数呢?因为在等待后这些函数取到的单位可能产生偏差,并不指向原来的单位,从而造成错误



    解释,到此为止。



    关于这个技能有几个问题存在,首先,效果不能被驱散,其次,不能重复作用在同一人身上,当然以上2个缺点可以通过一定方法解决,不过要考虑到的因素实在太多了~也就不在这里详细介绍,说到底,这个教程只是给大家指点一下制作技能的大致方法,关于技能的严密性,不同情况不同的对策,就要靠各位自己考虑啦!



    我知道这一讲比较抽象,尤其是对首次接触到什么全局变量局部变量的人而言,不过这也没办法,局部变量可以解决太多原本非常复杂的问题,不管你有没有看懂这次说的内容,你只要掌握了声明局部变量和直接在TRIGGER中调用的方法,你已经成功了~具体情况可以打开我的演示仔细的研究一番,呵呵,下课吧~


    下节课,制作全新的技能(二)









    作者: 但偏偏雨渐渐    时间: 2006-2-28 10:00

    [WE] 魔兽争霸1.18版本的新技能系统

    1.18的技能系统和之前版本有很大不同,以下是麦德已经发现的。

    在之前,一般来说,将一个普通技能的等级需求改到6以上,就能让其伤害魔免的单位。
    而原有的终极技能无论等级需求改为多少,都能伤害魔免的单位。

    但是现在完全不同了。
    能否伤害魔免和虚无状态的单位现在取决于技能的伤害类型。

    拥有以下伤害类型技能可以伤害魔免

    Quote:
    UNKNOWN 未知 对应技能:无
    NORMAL 普通(计算护甲值)对应技能:如蝗虫群
    ENHANCED 加强的 对应技能:如剑刃风暴
    POISON 毒 对应技能:如浸毒武器
    DISEASE 疾病 对应技能:如疾病云雾
    ACID 酸 对应技能:如酸性炸弹
    DEMOLITION 粉碎者 对应技能:如兽人战车的燃烧油
    SLOW POISON 缓慢毒药 对应技能:如缓慢毒药
    UNIVERSAL 终极伤害 对应技能:如星落

    在1.18 ,拥有以上伤害类型的各技能中,被动技能总是能伤害魔免单位,而主动技能需要将其等级需求改到6以上,才能伤害魔免单位,即便是终极伤害的技能也不例外。

    而拥有其他伤害类型的技能,如电系伤害的连锁闪电、火系伤害的烈炎风暴、死亡系的死亡之指、冰系的冰冻,无论在任何情况下都不能再伤害魔免的单位了。即时是将等级需求改到6以上,也只能产生技能效果,而不能造成任何伤害。

    拥有以下伤害类型技能可以伤害虚无(被放逐)状态的单位

    Quote:
    UNKNOWN 未知 对应技能:无
    FIRE 火 对应技能:如烈炎风暴、火球的溅射
    DAMAGE_TYPE_COLD 冰 对应技能:如冰冻、霜冻新星
    LIGHTNING 电 对应技能:如连锁闪电、电球的召唤生物伤害
    DIVINE 神圣的 对应技能:不详
    MAGIC 魔法 对应技能:不详
    SONIC 音速的 对应技能:不详
    FORCE 力 对应技能:不详
    DEATH 死亡 对应技能:如死亡之指
    MIND 精神 对应技能:不详
    PLANT 植物 对应技能:如根须残绕
    DEFENSIVE 防御 对应技能:如尖刺护甲
    SPIRIT LINK 精神链接 对应技能:如精神链接
    SHADOW STRIKE 暗影突袭 对应技能:如暗影突袭
    UNIVERSAL 终极伤害 对应技能:如星落

    在1.18 ,只有拥有以上伤害类型的各技能才能伤害虚无状态的单位,如普通伤害(俗称物理伤害)的蝗虫群,加强伤害的剑刃风暴,都不能再伤害虚无状态的单位了。


    结合起来,既能伤害魔免单位有能伤害虚无单位的伤害类型只有未知和终极伤害的技能,而拥有未知伤害的技能是不存在的,因此只有终极伤害的技能才能2者兼顾了。


    作者: 但偏偏雨渐渐    时间: 2006-2-28 10:00

    [WE JASS] 设置一个单位掉宝得函数

    在设置一个单位掉东西时,一般只能在WE编辑时设置好了才可以,而且之后用TRIGGER来做也很麻烦。在这里偶提供一个简单得掉宝函数:
    首先声明全局变量:
    //=======================================================
    //设置一个单位死亡时掉落一个物品类型的函数所用到的全局变量
    unit array wj_DeadUnit_Unit
    integer array wj_DeadUnit_Drop_Item
    integer wj_DeadUnit_Index = 0
    integer wj_DeadUnit_LoopIndex = 0
    integer wj_DeadUnit_LoopIndexEnd = 0
    trigger wj_trg_DeadUnit_DropItem = null
    然后:
    /////////////////////////////////////////////////////////////////////////////
    //
    // 设置一个单位死亡时掉落一个物品类型
    //
    // - 限制最大使用单位量为255个
    //
    // DropItemForDeadUnit takes unit WhichUnit, integer ItemA returns nothing
    //
    /////////////////////////////////////////////////////////////////////////////
    //===========================================================================
    function DropItem_Actions takes nothing returns nothing
    set wj_DeadUnit_LoopIndex = 0
    set wj_DeadUnit_LoopIndexEnd = 255
    loop
    exitwhen wj_DeadUnit_LoopIndex == wj_DeadUnit_LoopIndexEnd
    if wj_DeadUnit_Unit[wj_DeadUnit_LoopIndex] == GetTriggerUnit() then
    call CreateItemLoc( wj_DeadUnit_Drop_Item[wj_DeadUnit_LoopIndex], GetUnitLoc(wj_DeadUnit_Unit[wj_DeadUnit_LoopIndex]) )
    else
    endif
    set wj_DeadUnit_LoopIndex = wj_DeadUnit_LoopIndex + 1
    endloop
    endfunction
    //===========================================================================
    function DropItemForDeadUnit takes unit WhichUnit, integer ItemA returns nothing
    if wj_DeadUnit_Index > 254 then
    return
    endif
    set wj_DeadUnit_Unit[wj_DeadUnit_Index] = WhichUnit
    set wj_DeadUnit_Drop_Item[wj_DeadUnit_Index] = ItemA
    set wj_DeadUnit_Index = wj_DeadUnit_Index + 1
    endfunction
    创建触发器:
    function InitializeDropItemForDeadUnit takes nothing returns nothing
    local integer index
    set wj_trg_DeadUnit_DropItem = CreateTrigger()
    set index = 0
    loop
    call TriggerRegisterPlayerUnitEvent(wj_trg_DeadUnit_DropItem, Player(index), EVENT_PLAYER_UNIT_DEATH, null)
    set index = index + 1
    exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddAction( wj_trg_DeadUnit_DropItem, function DropItem_Actions )
    endfunction
    注意创建触发器要写在最后,将这些脚本写入地图中后,在TRIGGER的最开始调用:
    call InitializeDropItemForDeadUnit()
    随后在编写TRIGGER时,如果想让一个单位掉落物品,则直接用:
    DropItemForDeadUnit takes unit WhichUnit, integer ItemA returns nothing
    参数WhichUnit指的是某一个单位
    参数ItemA指的是物品的原始ID
    例子:
    call DropItemForDeadUnit( udg_xxx, 'Item' )

    不过缺点是最多限制了255个单位掉落物品,这些可以调整,限制255个是为了不影响游戏得速度。

    作者: 但偏偏雨渐渐    时间: 2006-2-28 10:02

    新手做图入门指导教程〔第一章〕(非新手勿进)

    前言:
    现在有很多玩家都对WE有着浓厚的兴趣,而且都想能创作出自己的魔兽地图,虽然在论坛里也有很多相关的讨论贴,但是大部份都是针对一些对WE有一定了解的玩家所做的,而对于刚刚起步并才开始弄WE的玩家则没有一些基本的教程或讨论贴,所以,在此,本人决定以自己学习WE及做图的经验与心得写一个面向初识WE玩家的地图制作指导教程,希望对各位新手们有所帮助!当然要完成一张RPG地图或是对战地图还要有作者的很大的决心及恒心,对魔兽这个游戏,包括战役地图,对战地图及RPG地图要有一定的了解,至少要会玩魔兽。如果你有以上两点条件的话,呵呵,那么请继续往下看吧,你一定会有所收获的!
                     第一章:  认识WE
                 第一节 相关的名词及概念
      相信有些新手们还不知道什么是WE吧!呵呵,WE就是World Editor的简写啦,译做中文应该是叫做世界编辑器,这个东西就是大多数地图制作者们的工具了,你只需要在魔兽的安装目录下就能找到了。如果是第一次运行的话,会出现个用户协议之类的,不用管了,有对话框就只管按确定吧!
      关于什么是T?-我们在一些讨论贴中经常会看到一些诸如“用T吧,T不对吧”的语句,其实这个T也是一个简写,它是触发事件编辑器(Trigger),它的功能是很强大的,知道为什么对战地图时一来每个玩家都有一定的资源和单位吗?就是它弄的了,还有像一些RPG地图里的剧情啊,对话啊,包括开始时选择英雄也是用它来实现的,可以说,只要是一张RPG地图的话,T就是整个地图的精髓与灵魂所在。没有T,那么你的地图就只是一张好看的摆设罢了!!!(由于这是新手教学贴,所以在以下的课程里面会专门提出来进行讲解,现在暂不讨论)
      关于JASS,我想还是有很多人听说过JASS吧,这个的确是个好东东,功能比T还要强大,但是需要一定的程序设计能力的人才会用了吧,这对于新手来说更是不沾边的了,所以在本教程中不涉及讨论!如果各位有兴趣的话可以自己去找点相关的教程!
      另外的几个相关东东:物品管理器,声音管理器及输入管理器将在具体的制图过程教学中提到!

                    第二节 熟悉WE
      不知怎么说呢,大多数地图作者都必须经历的一个过程吧:修改地图。呵呵,没错,修改地图是了解并熟悉WE的一个捷径。虽然现在都不提倡修改地图,不过做为学习WE的一个手段,我还是建议大家先从改图学起,而最简单的就是先修改官方的对战地图了!下面将以Lost Temple这张人气较高的对战图来入手,让我们一起揭开WE的神秘面纱!
      运行WE,进入后先将菜单栏里的窗口选项打开,将里面的刷子表那里的勾去掉,这样WE的速度会有所提高。选择菜单栏里的文件-打开地图,在目录里找到要打开的地图,如:Lost Temple.打开之后,就是这个地图的地形了!
    认识工具面板:在地图中有一个工具面板,如果没显示的话可以在菜单栏的层面里面打开。它包括:地形面板,地形装饰物品面板,单位面板,地区面板和镜头面板。以下将会分别说明!
    1.地形面板,最好理解的一个了,你现在所能看到的整个地图的地形。包括平地,坡地,水,草地和悬崖等都是用它弄出来的,自己试着改改看吧!
    2.地形装饰物面板,呵呵,和上面那个差不多,不过内容就多了,看到地图上的树啊,花啊鸟啊什么的了吗?就是用它弄了,同理,自己试着改去吧!
    3.单位面板:也是事先放东西的工具了,地图上的中立怪,商店,生命泉和金矿就是用这个放的了,还有一个就是玩家开始地点也是由这个来完成。
    4.地区面板:基本上是用在T里面的,现在唯一能做的就是弄传送门。暂时先不管!
    5.镜头面板:用在交待剧情时用,同样要用T来弄,也先不管了!
    说到这里,基本上WE里要用到的几个工具大家都知道一点点了,具体怎么用就在下面以修改地图的实例来说明了。(示范图为Lost Temple)
    一.修改金矿的数量,是不是觉得对战时金矿不够采,才12500的金子,改多一点吧。先将工具面板打开至单位面板,此时在地图上选中一个金矿,双击,会出现一个对话框,里面很明显有个“金钱含量”的框框,默认的是12500,这个就是该金矿的含金量了,想改多少自己弄吧。
    二.如何让中立怪死后掉落物品。是不是看到金矿旁边的怪有两个有白色圈圈在动啊?那个就说明杀了此单位后它会掉东东,怎么弄呢?同上面一样,选中它,双击,出现对话框了,此时你可以修改它的一些属性,如生命值比例,所属玩家等。看到掉落物品的选项没?就是那个,点了它后,打开下拉列表,里面有两个选项,两个都可以设置其死后掉落的物品,自己试试看怎么设置吧,这里就不再说明了!
    三.在原有地图上加一些单位:如商店,酒馆或是金矿放几个怪!打开单位面板,在中立无敌意里面可以找到如金矿,泉水,商店酒馆等中立建筑,也有一些单位,如小鸡野狗等。想在哪里放就放吧。要加入怪的话就打开中立敌对里面,慢慢找吧。放了之后就自己设置其掉落物品了,当然也可以改更其所属玩家,如果将怪改为中立无敌意,那么它就不会主动攻击你,根本就不会攻击你了,但是你杀了他也得不到经验和金钱!
    四.如何加个传送门。以地图的左上和右下的两个小岛为例,先在两边各放一个传送门(单位面板-中立无敌意-建筑),之后将工具面板打开为地区面板,点击后在左上的传送门所以位置(门下)弄出一个区域来,之后命名为DOOR A,同理在右下传送门处也弄一个,名为DOOR B,下面则是激活传送门了,切换回单位面板,双击左上传送门,出现对话框后有个激活选项,打勾,出现下拉列表,选择DOOR B,此时这个传送门就好了,接下来同样的方法弄右下的,选择DOOR A。
    至此,简单的修改就已经完成了,当然了,我们并不满足这点点的修改,接下来当然要来点实在的,比如改改英雄啊,技能啊什么的!

    第三节 物体编辑器初识
    物体编辑器来了,这个相当于一个数据库了,魔兽地图中的所有数据都差不多在这个里面了。打开物体编辑器后会有一排的各种选项,先看单位的吧!
    单位列表:里面有所有你在正常地图里面所能见到的一切单位!而要弄懂这个也并不太难,只不过是里面的内容很多,弄起来费时间吧了,我就找几个常用的来介绍说明。
    先来个变态的,比如,将农民改的比英雄还强大,首先打开人族,对战,单位,选中农民,右边就会出现该单位的相关数据了。要变态当然是攻击超高,护甲超强,技能超变态,血超多,跑得超快,打人也快,好的,慢慢来,一项一项改吧!
    首先是护甲,里面有个基础防御,这个就是初始护甲了,改吧,改为100。之后是战斗-攻击-基础伤害。这个就是攻击力,也改为100吧。然后是战斗-攻击-攻击类型,可以改为混乱,这样就暴强了。战斗-攻击-魔法施放时间间隔时间,就是攻击的间隔,改为1试试,每秒打一下,哈哈,其他的几个较为好理解,故不再说明,自己一试就明白了!有些比较奇怪的就可以不用去管了!接下来是战斗-防御类型,改为神圣吧,这样就只有混乱攻击才打得动了。下面是技能-普通,这个就是该单位的技能了,可以自己加了,想加什么就双击看吧~!后面的什么生命值啊魔法值这些就不用我再多说了吧。这样一来,你的这个农民已经暴强了,哪个英雄见了都吓跑!
    其它的一些单位也同样的改,至于建筑嘛,会多出几个东西来,如升级的科技,训练的单位,都是一看就知道是什么了,所以不再多说,如果是商店的话,看一下它技能及售出的商品及可雇佣的单位等就行了。关于英雄则有些初始属性等,这些也是自己试试就行了!
    物品:很简单,就是物品,或是称宝物等,就是游戏中的那些!
    可破坏物:就是树啊,箱子,门等
    地形装饰物:各种雕像,柱子。。。。。。。
    技能:又是一个重要的东西,和单位及物品关联大呢。在这里就是让玩家自己修改单位或物品技能的地方了,举例说明一下,想让大法师的水元素一次召唤出10个水元素来吗?先找到该技能,然后修改里面的数据-召唤单位计数。改为10吧。其实在技能这个地方最多的就是修改各种数据了,比如等级,伤害值,魔法消耗,施放间隔等,自己试着改一改,因为要每个东西都说明的话估计要一年吧~!汗!
    而后面的效果及科技呢就是在自己做图时再考虑了,不过自己也可以先看看,不难!
    第四节 具体问题解答
    现在说一下几个常见的问题吧!
    1.物品技能怎么修改?比如想把一个血瓶改成加血10000!
    先在物体编辑器里的物品里找到你要改的物品(血瓶),在右边的数据里找到技能-技能:具有医疗效果的物品(较小的),这个就是加血多少的技能了,然后再切换到技能里,找到特殊的-物品,在里面找到相应的技能(具有医疗效果的物品(较小的)),将生命值取得那里改成10000就行了!
    是不是只觉得只有一个血瓶不过瘾,改多点吧,好的,切换回物品,还是先中血瓶,在右边找到状态-负荷数量 改吧,改成100,哈哈,一买血瓶就有100个了,爽!
    2.想让英雄的技能多一点,可以,单位里面找到英雄,比如大法师,找到技能-英雄。在这里加吧,加个先知的召唤狼也行,不过最多此处技能不能超过5个。想加点一般技能么?如重生。在技能-普通里面加吧!
    其它的一些如英雄升级可超过10级等将会在以后的分类主题里面给大家说的,不过目前此类问题都有置顶贴解答了,大家不妨可以去看看!


    作者: 但偏偏雨渐渐    时间: 2006-2-28 10:03

    新手做图入门指导教程〔第二章〕(完结)

    绪言:相信大家在看过第一章之后对WE的一些基本功能都有一定的了解了吧(如果你在看过后有照着上面的说明去修改过图),那么接下来当然是一步步接近我们感兴趣的话题了,制作属于自己的地图!一起来看吧!通过对本章的学习,你将会学会如何在游戏中创建单位,如何制作打怪掉宝,失败及胜利条件以及自定义单位及技能的制作!


    第二章 创建属于自己的RPG地图
    第一节 创建一张新地图
    修改地图我们会了,那么我们怎么样来创建一张自己的地图呢?在菜单栏的文件下有个创建新地图选项,用它就行了!点击后会出现一个窗口:


    此主题相关图片如下:


    此主题相关图片如下:

    这个就是对你的地图的基本大小和地形的设置了,比如弄成宽64,高128,初始海拔为7,地形设置为城邦,之后点确定就会生成新地形了!好了,现在在你眼前的就是你刚才创建的新的地图的地形了,是不是很难看,呵呵,那就让它变漂亮一点吧,用第一章学到的知识,打开工具面板,用地形面板及地形装饰物面板来弄吧!
    那么一张新地图要有自己的名字,这个怎么弄呢?在菜单栏的情节选项里面可以弄相关的信息!点击后出现下拉列表,选择第一项地图描述!之后便会出现以下:


    此主题相关图片如下:


    此主题相关图片如下:

    名字:就是在游戏中的显示出的地图的名字了,如Lost Temple等等!
    建议玩家数:就是推荐的玩家人数,一些对战图上都有的如1V1,2V2等等!
    作者:当然是写上自己的名字啦,不过这个好像在游戏中都看不到!
    修改地图读取中的画面:同样在地图属性的窗口中选择场景读取中就可以修改了,点击使用战役场景。其它的相关信息自己弄吧!

    怎么样弄玩家数:创建了一张新地图后,在默认情况下是只能有一个玩家的,要多玩家的话就得我们自己弄了!同样是在情节选项下,不过这次要选择玩家属性!之后会出现设置玩家的窗口!你在这里可以设置玩家为用户,或是电脑,一般来说,RPG地图里都要有一或两家电脑玩家来作为敌对方的,而且大多数都是用玩家11和玩家12来弄!之后是弄玩家的势力了,一般来说有两个势力:正义和邪恶。具体代表图有3C,多数TD图等,而像FOOTMAN这种图则是有四个势力,那么也可以自己设置!在情节属性窗口中选择势力,然后在重新定义里打勾,添加势力即可,然后就拖动相应玩家到各个势力中了,最后别忘了在固定玩家设置里打上勾!其它的几个选项就暂时不用!


    此主题相关图片如下:


    此主题相关图片如下:

    这几部份弄完了,我们当然是得做开形了!用第一章中学过的知识自己弄吧!
    第二节 自制一张简单的RPG地图
    在现有的地图上我们得先设置玩家开始点!如果是在对战地图中,这个开始点将会是给你创建基地和初始农民的地点,在RPG地图里面就是游戏开始后玩家的初始视野地点了,比如我们就先把玩家开始点都弄到地图左上吧!(提示:给电脑玩家设置开始点的话,可以放在任意位置)


    此主题相关图片如下:

    一张RPG地图不像对战地图那样各位玩家有自己的单位和部队,大部份的RPG地图都是以英雄作为自己的控制对像的,那么我们下面就说一下给玩家创建英雄单位!
    首先将工具面板切换到区域面板,并在玩家开始点的地方画一个区域,命名为Heros!之后打开菜单栏的触发事件编辑器,打开后会有一个初始化的对战初始化的T,将它删除!然后自己新建一个类,之后在该类下新建触发器,命名为Create heros for players!选中你新建的T之后就会在右边出现相关信息窗口了,右上空白窗口可以自己写点提示说明之类的,下面的就是具体的T语句了!关于此处的T,请参考附带的演示地图!


    此主题相关图片如下:

    创建好英雄单位后我们的冒险就开始了,此处我们先在地图上放一些供我们攻击的单位,让其所属玩家为玩家12,我们知道,一般打死中立怪后会掉宝而且会得金钱,怎么让打死非中立单位也掉宝和得金钱呢,同样会T来弄!关于此处的T,请参考附带的演示地图!
    一个游戏自然还得有胜利条件及失败条件,这些也是T的功劳!关于此处的T,请参考附带的演示地图!
    以上所提及到的这些内容在地图均有演示,各位请自己在地图里参看!
    第三节 初识触发器 T
    一个完整的触发器由三个部份组成:事件、环境、和动作!


    此主题相关图片如下:

    事件-即一个事件或是任务、剧情的开始,也可以这样理解,举个例子,上课铃响了就是一个事件,或是早上8.00到了也是一个事件,这意味着接下来我们该上课了,也可以把事件理解成为导火索吧!
    环境-相当于是条件,接着上面的例子来说,早上8.00到了,环境:如果是周一至周五。那么我们就得上学(班),如果是周末,我们就休息,也就是说不做出相应的动作!这里上学及上班就是动作!
    动作-具体的各项命令,如上学,上班,吃饭等,当然这里是用现实生活中的例子来打比方!那么下面我们就来看一个例子以帮助大家理解这三个部份!
    引用某位圣人的一个经典例子:
    有一个花园,花园里面有一条狗!
    事件-一个人进入花园
    环境-此人是狗的主人
    动作-狗摇尾巴
    或者是
    事件-一个人进入花园
    环境-此人不是狗的主人
    动作-狗就叫
    这个就是一个简单的触发器了,下面就用WE中的具体事件来举个例子!就以3C的某个人的英雄被杀了而出现字幕来说明!
    事件-a unit dies 一个单位死亡
    环境-triggering unit is a hero = ture 死亡的单位为英雄单位
    事件-游戏-Display to all players the text:name of owner of triggering unit + 的英雄被 + name of owner of killing unit + 打死了! 出现提示字幕
    当然,在3C中还得有打死了一个英雄后对各位玩家的奖励和对打死英雄的玩家的特别奖励以及判断死亡英雄是否属于玩家控制等,这里就不讨论了,其实这些就是多个动作的运用了,基于新手对WE和知识的情况来考虑,本人只提供简单基本的触发器语句的教学,如果是自己想要更进一步了解更多的话则可以找一些其他的教程或是演示!
    事件里面可以分为时间,单位,初始化等多个类型,各位可以打开WE里的触发器自己研究,环境和动作的内容则就更多了,在这里不可能都作介绍,这些都还得大家自己去研究学习了!
    第四节 自定义单位、物品及技能的制作
    一张RPG地图要有自己的风格及创意当然少不了自定义单位和技能了,那么这些东西是怎么来的呢?其实都是在原有的单位及技能上创建的!而要做到这些,我们又得回到物品编辑器了!
    创建自定义单位:在物体编辑器的单位列表里找一个原始单位作为你要自定义的单位,如用大魔法师来做,选中大魔法师,右键自定义单位,之后会出现对话框,输入该单位的名字,之后会在自定义的类下面多出一个人族-英雄-XXXX(你刚才输入的名字)选中他后,同样右边就会出现其相关数据了,这里的数和标准单位里面的相比除了名字不同外,其他都相同,所以,既然是自定义单位,那么就改吧,模型,声音,攻击,护甲,图标……………………这样就完成了一个自定义单位了!同理,自定义技能的方法也是一样的,只不过你可以修改它们的等级及效果,对召唤技能而言还可以修改召唤出来的单位的数量及种类!这些都是属于基本问题了,自己一看都知道,所以就靠各位自己研究了!
    第五节 制作RPG地图的一些建议
    说了那么多,大家应该对一张RPG地图的产生方法有一定的了解了,不过总体来说,制作一张RPG地图是一个相当辛苦的过程,所以如果各位真下定决心要制作的话,那么我在这里给大家几点建议:
    1.明确自己要做哪种RPG地图?如战役类、角色扮演类、对抗类、TD或是生存防守…………只有明确了自己做图的目标后才能在拟定出一个相关的地图制作计划(即头脑里面有个想,不要到实际做图时还在考虑做成什么才好)
    2.创建地图时大小要适中。不要想着地图弄得大就好,还得想想自己是否有能力将全部地形都用完,有没有合适的剧情来填充庞大的地形,其实有很多很经典的地图有的都是极小型的地形的,如小猪保卫战。而大地图当然也有,比如本人的最终幻想的两个作品用的都是最大的地形设置,当然,在这之前也是要充分考虑好每一块地形的使用的!
    3.创建适合自己RPG地图的单位、技能和物品等!一张RPG地图都是有自己的个性的,这就在自定义单位、技能和物品上得到了充分体现。如果是一张角色扮演图,你得设计自定义单位的职业,名字及称谓等,甚至还得弄出相应的技能及物品。而对于生存一类的,你要考虑的则是单位的技能是否真正有威力,物品是否能够满足游戏的需要!
    4.游戏系统。这个就很多了,比如物品合成,升级,打宝,挑战等,这些主要是为了丰富一张地图的而发展出来的,当然也可以吸引更多的玩家以及体现作者的制图水平,不过在做一些游戏系统时也得注意是否和游戏相适合,有些系统如果做得很抢眼的话,反倒会把你一张地图的主旨给遮蔽了!

    总结
    通过这两章的学习,各位可以说对WE都有一定的知识基础了,而在今后的学习中,各位其实就是要专门去学习T了,毕竟T是有着很强大功能的东东,也是很多高手们一直在研究的话题!而由于本人水平有限,能教给各位的也就只能是最基本的东西了,对于WE而言,大家要想有提高还得靠自己钻研!本人的新手制图指导教程到此也就结束了,因为下一步各位就算得上是进入了WE的进阶提高阶段,而此时各位可以去找其他相关的教程学习了,因为大家有了一定的知识作为基础,剩下的就是针对专门的问题而进行学习了!在此谢谢各位的支持,也希望各位能打造出属于自己的地图!另外,如果有需要的话,本人还会继续做一些基础T的演示供大家参考学习,不过注意喔,只是弄基础的演示,而像单体技能群体化或是多重物品栏等就已经超出了我的能力范围了!

    最后一句,学习WE大部份要靠自己自学为主!


    作者: 但偏偏雨渐渐    时间: 2006-2-28 10:04

    创造新的光环!(很简单的)

    图片看不完整请点击或缩小!
    我下载了山丘全套技能,发现里面的光环是将吸血光环的blp改变而做成的
    这是我自己的理解:
    先准备一张用photoshop编的256×256的图片,用Warcraft 3 Viewer转换成blp,检查:非0KB,用Warcraft 3 Viewer打开有画面。
    然后:



    注意:1、导入更改完路径最好保存再重开WE。
    2、一般图片是256×256的。除非那光环是旋转对称图形,例如:强击。
    3、最好用photoshop来作图,用图画转换后非0KB的。
    4、底色要是黑色,除非你想它连白色也加进光环。

    根据上文,下面是创建光环:
    用Warcraft 3 Viewer导出一个光环的mdx,再转换成mdl,编辑连接的blp(最快是查找“blp”,有多个时,按位置在编辑器查看一下)再转换成mdx,将刚才的mdx和自制的blp导入编辑器



    要查找其他blp的路径:



    war3x.mpq是Frozen Throne,只是资料片里新加的blp和mdx
    war3.mpq是魔兽3
    原理:mdx是3D文件,没有纹理的,再加上blp,就产生了纹理。
    看~都是这幅图~



    在不同光环改有不同,下面是用吸血光环,辉煌,邪恶改的



    文件下载,这个是改光环的,创建的没有做演示。
    打开附件


    作者: 但偏偏雨渐渐    时间: 2006-2-28 10:53     标题: 请谅解

    怎么这样子 这个改完的论坛有问题 我花半宿时间在一个回复上 点发表的时候 但偏偏 出错了 我明明登陆了 论坛怎么还让我登陆一下 我倒 白忙呼了 后退一下 内容全无 |||谢谢各位!!

    我决定了 我没混出头的时候不会在论坛上出现 请大家谅解 谢谢!!!

    最后提醒大家一下如果要发表的时候先把所有内容复制一下!否!后果不堪设想!!谢谢!!!

    正如我轻轻的来...然而我轻轻的走.......


    作者: 誓言如风    时间: 2006-2-28 14:11

    支持一下~~~~~~~
    作者: artharsdada    时间: 2006-3-13 05:11

     

    ddddddd


    作者: 上山下海    时间: 2006-3-13 05:31

    又是一大堆[em01]
    作者: 休_休    时间: 2006-3-13 06:07

    - -加个精华...
    作者: 傻づ瓜    时间: 2006-3-13 20:48

    呵呵,偏偏的精华蛮多了啊……
    作者: h305155695    时间: 2006-12-28 20:25

    good :L :D
    作者: jkboy111    时间: 2007-2-8 14:45     标题: 讲的真是好~

    :D 给了我不少帮助~谢谢,怎么提高力量呢???
    作者: jkboy111    时间: 2007-2-8 14:46     标题: 灌水

    好象回复就可以......
    作者: asd7586    时间: 2007-2-12 21:39

    这么多看到什么时候我眼睛都看花了
    作者: LXJ    时间: 2007-2-12 21:58

    顶DDDD

    [ 本帖最后由 LXJ 于 2007-2-12 22:08 编辑 ]




    欢迎光临 魔兽地图吧 (http://www.wow8.org/bbs/) Powered by Discuz! 7.2