~☆【教程】【jass技能入门教程~Part I】【由浅入深】☆~

查看: 240|回复: 3
[复制链接]

WOW8 发表于 2018-7-18 15:08:20 | 显示全部楼层

欢迎访问本论坛,注册你的账号并登录,来与我们交流吧!

欢迎 登录 与我们交流!没有帐号?立即注册

x
夜の星 发表于 2011-6-12 22:41:08


☆笨蛋的笨蛋前言~

唔...熟悉了T的中文化表达与图形界面,不少WEER对于jass这种“天人语言”望而生畏;
其实不然~星相信每一个人通过努力,再加上一点恰当的引导,都能够学会jass,步入一个新的层次~

在接下来的教程中,星会从最基本的东西开始讲起,演示jass技能制作的方法
所以为了便于理解,技能都十分简单~(不许吐槽哦~)

除了本篇外,预计还有2~3次的教程~之后会不断深入
,直至RB/Hash,以及动态创建触发器等等较为高级的运用为止~

打起精神,上课了哦~

☆补习!语法什么的我才不想讲呢~

磨刀不误砍柴工的说~
如果是初入门,或者是完完全全的新人,就先了解一下jass的书写规则吧~
jass入门到提高教程 By Alex
这是学习jass最好的教科书~星最欣赏的jass教程, 由浅入深;讲述形象化,将抽象物体联系生活实际,便于理解~
建议新人仔细阅读~


jass语法简要介绍:(←这个不能代替jass教程,学习jass,请仔细参照上方链接帖子~)
jass
//★ 注释符
//   "//"就是传说中的注释符咯~用途就是在代码中,加入一些辅助说明的语句,这些语句不会被程序执行,仅能起到帮助说明,使代码便于理解的功效~
local real dam=70//一行中,双斜杠之后的内容,就是注释符作用的范围~


jass
//★ 变量
//变量就是计算机编程中,存储数据的最基本最常用的单元~如同字面意思,变量的值是可以改变的~
//语法格式:

//变量类型+变量名(=变量的初始值)
real PI=3.14149
real PI//也可以不给予初始值,直接声明~

//数组的声明
integer array Number
//必须变量类型+array+变量名;不可以直接赋予初始值~

//全局变量——任何地方都能访问
globals//全局变量的声明,需要在一个globals~endglobals之间~
    real PI=3.14159//这样任何触发中,都能够使用PI这个变量,并且能够对其值进行修改的说~
    constant real E=2.71828//constant,表示为常量,即将E变为一个全局常数,能够访问,但你不能修改E的值~
endglobals

//局部变量——仅能在函数体内访问,并且互不冲突
function A takes nothing returns nothing//一个无参数无返回值的函数A
    local real r=3//声明一个局部实数变量r,初始值为3
//格式:local+变量类型+变量名=初始值~
endfunction

//~~~!注意!~~~局部变量的声明,必须在一个函数体的最前面
function  B takes nothing returns nothing
    local integer i=0
    call BJDebugMsg("我在学习jass的说~")//显示一行信息:“我在学习jass的说~”
    local real r=3//错误!local real r=3不可以在 call BJDebugMsg后面
endfunction

function  B takes nothing returns nothing
    local integer i=0
    local real r=3//正确~
    call BJDebugMsg("我在学习jass的说~")
endfunction

//变量的赋值与访问:
function A takes nothing returns nothing
    local real PI=3.14159//声明的时候,也可以直接赋值~
    local real array R
    set PI=3.14
//格式:set + 变量名 = 新的值;对已经声明的变量进行操作~
    set R[0]=5
//数组的赋值,set + 变量名[下标] = 新的值
//数组下标从0开始,8191结束,一共可以有8192个元是;超出范围的,会发生错误~


//通过变量名访问数据
    set R[1]=R[0]+PI
endfunction

//变量的同名冲突~
globals
    real A=3
    integer A=5
    real array A
    real A=7//不允许有任何2个全局变量重名,哪怕类型不同,是否数组,都不可以,否则无法通过语法检测
endglobals

function A takes nothing returns nothing
    local real j
    local string k//任何两个局部变量也不可以重名的说~
endfunction
//~~~~~~~分割线的说~~~~~~~
//虽然局部变量和全局变量都不允许重名出现~
//但是如下代码却是正确,可执行的~
globals
    real A=6
endglobals

function MyFunc takes nothing returns nothing
    local real A=10//局部变量与全局变量重名
    call BJDebugMsg(R2S(A))//BJDebugMsg为显示文字;R2S为转换实数成字符;
//执行代码,此时的话,会发现显示出的数字是10;
//当全局变量与局部变量重名时,全局变量被隐藏,访问到的,是局部变量的说~
endfunction


jass
//★函数体

//一个函数体的声明:
//格式:
//function 函数名 takes 参数列表 returns 返回值类型
//    函数的具体实现代码~
//endfunction

//函数名不可以重复,参数类型不同也不允许,jass不支持重载函数~
function A takes nothing returns nothing
endfunction
//无参数的函数,参数列表写 nothing 即可~

function B takes real Value1 returns nothing
endfunction
//函数B是一个参数个数为1的函数示例,参数列表格式为
//takes + 数据类型 + 变量名
//参数就相当于一个局部变量

function C takes nothing returns real//返回值,只需写数据类型即可,且返回值唯一
    return 5//将数据作为返回值返回,可以是变量、常数、或者式子亦或者是函数调用~
//返回值为nothing(即没有返回值)的函数,无需特别return语句~
//但是其他类型,必须拥有return语句~
endfunction

function D takes real a1,real a2,real a3 returns real
//函数D有多个参数,每个参数之间,用逗号隔开的说~
    return a1+a2-a3
endfunction


jass
//★语句

//变量赋值
set A = 9//请参考上边


//函数调用
call BJDebugMsg("jass")
call ShowUnit( UnitA , true )
//对于无返回值的函数,我们可以用call 关键字来调用~
//call + 函数名(参数列表,多个参数用逗号隔开)


local real a=Sin(0.7)
//有返回值的函数,可以作为运算过程使用,上行代码中,sin0.7的值,就被赋值给了变量a
set a=RAbsBJ((Sin(0.5)-5))
return Sin(2)+Cos(3)*6.7
//无返回值的函数,也可以call + 函数名调用,但此时返回值就没有了用处;
//所以仅在不需要返回值的时候,这样写的说~

local trigger trg=CreateTrigger()
//无参数的函数,调用的时候,括号内不写东西,但是括号不可省略的说~



//if 语句
//格式:
//if + 布尔表达式 +then
//    满足条件执行的代码段
//else
//    不满足条件执行的代码段
//endif
//逻辑关系可以参考T中的IF语句,二者是很类似的说~
if ( 1>2 ) then
    call BJDebugMsg("a")
else
    call BJDebugMsg("b")
endif

if (true) then
    call BJDebugMsg("aaa")//当一个If语句,如果不满足条件时不需执行任何代码,可省略else段
endif

if ( 3>2 ) and ( 2>3 ) then//false
if ( 3>2 ) or   ( 2>3) then//true
//if的条件可以用 and 和 or 来联系起来;
//and:两个相连条件都符合,才是true;否则false;
//or   : 两个相连条件,只要一个符合,就是true;否则false;
if (not true) then//not关键字,表示为不符合XXX
    语句A
else
    语句B//执行的,是语句B~
endif


//loop语句(循环语句)
loop
    ......代码段~
endloop
//系统会不断执行loop~endloop中的内容
local integer i=0
loop
    exitwhen i>5//exitwhen语句,用于判断是否退出当前循环,后接一个布尔表达式
//注:没有exitwhen的loop语句,就是死循环,永远不会退出,请谨慎小心的说~
    set i=i+1
endloop


回复

使用道具 举报

 楼主| WOW8 发表于 2018-7-18 15:10:50 | 显示全部楼层
啊咧?这楼没有标题的说~
初学者的第一个问题:
jass写在哪里?!用什么写?
同T一样,jass代码要想发挥功效,还是离不开触发编辑器~新建一张地图试试吧~
8KI]K6F2_6$IQMD7U[C16W0.jpg 新建触发器A;
`T{KKFQU7{Z14@9XO_%O_5W.jpg 选中并点击编辑-转化为自定义文本
(XRRR{]_)LR%]T645O5H4.jpg
↓嘛~你看~原本的触发器界面,就变成了代码格式了的说~
jass代码就书写在其中(其实T的每一条指令,最后都会被编辑器转换为jass代码)

QJ2%4(F5LWGQASCFZ1}0FED.jpg

=~=~=~=~=~=~=~=~=~=~=~=~=~=~=

除了单个的触发器,还有一个地方可以写jass代码的说~

↓每张地图的触发编辑器中,都有一个【图标+地图名字】的物件~(图中未命名的)
340DQ{JD_G$B$DDGOGNH8XO.jpg ↓点击一下~
5W]0D)W39VMIJ(5IQE$OW)2.jpg 也是一样的界面哦~
说明:该处为全局脚本区,声明在这里的函数,能够被任何触发器所使用;
所以一般用来做一些系统化的东西~
(jass中,一个函数只能够调用它前面的函数,它无法访问自己身后的函数~)
jass编写的环境与工具~
①记事本等等文本工具
    啊拉~jass只是一段代码,一段文字的说~
   用这些当然可以咯~甚至手机什么的,也不是不行哦~
    不过,星才不喜欢这样的说~
②jassCraft以及jassShop
    这两款软件,是用于jass编写的环境,拥有代码颜色、字体高亮、语法检测及函数查询等功能~
    是一个不错的编写环境~
    但是随着时代的发展,它们多少还是有点捉襟见肘,各种问题也不少~

嗯~时代在发展~好孩子们都去用notepad++吧~
③直接WE内编写
    这是星个人比较喜欢的方式~YDWE或者newgen可以考虑此项~
    其整合了TESH插件,这个插件使得WE的书写环境,能够变得轻松、明了,和jassCraft/Shop相比毫不逊色~
    同样拥有一样的代码高亮等等功能,同时还有输入三个及以上字符,自动完成代码建议~(即输入"Cre",会跳出一个所有开头为Cre的函数列表,你可以双击一个,自动写入字符的说~)
    直接在WE内编写也便于测试、修改的说~

        注:没有该插件(TESH)的编辑器,jass书写界面是和记事本一样的,黑字白底~无任何功能的说~
回复 支持 反对

使用道具 举报

 楼主| WOW8 发表于 2018-7-18 15:13:25 | 显示全部楼层

创建第一个jass触发器~

为了能够便于理解,我们先创建一个T的触发A
JRJ0_VSG9)1]I6}6FR1JDVH.jpg (只是演示而已,请勿吐槽单位死亡后再次杀死的说~)
然后转换成自定义文本格式;

可以看到,我们的这个简易触发器,实际是由3个jass函数构成的~
jass
function Trig_A_Conditions takes nothing returns boolean//条件函数,无参数,布尔返回值~
    if ( not ( GetUnitTypeId(GetTriggerUnit()) == 'hfoo' ) ) then//“触发单位的类型 是否等于 步兵”~
        return false//返回false即终止触发
    endif
    return true//true即执行触发~
endfunction

function Trig_A_Actions takes nothing returns nothing//动作函数,无参数无返回值~
    call KillUnit( GetTriggerUnit() )//杀死触发单位~
endfunction
//===================================================
function InitTrig_A takes nothing returns nothing
//这个是触发器的初始化函数,每个触发器的初始化函数名称有一定要求~
//必须是   <InitTrig_触发器名> ,系统会自动运行这个函数来进行初始化~

    set gg_trg_A = CreateTrigger(  ) //gg_trg_A为系统为触发器A生成的全局变量名~函数CreateTrigger()的作用就是创建触发器~

    call TriggerRegisterAnyUnitEventBJ( gg_trg_A, EVENT_PLAYER_UNIT_DEATH )//为触发器A注册任意单位死亡事件~

    call TriggerAddCondition( gg_trg_A, Condition( function Trig_A_Conditions ) )//为触发器A添加一个条件函数,事件被触发的时候,会先执行一遍条件函数(即上方的Trig_A_Conditions),判断是否符合条件,不符合就终止触发,符合则运行动作函数~

    call TriggerAddAction( gg_trg_A, function Trig_A_Actions )//为触发器A添加动作函数;如果经过条件函数的判断,符合条件,动作函数就会被执行~

endfunction

这里的三个函数,分别相当于T中,事件、条件与动作三个部分~
这样,我们已经大致了解了触发器的jass构成,
如果要添加事件、条件、动作,就只需在三个函数中分别加入相应语句即可的说~



写在正式动工之前:
    新人学习,难免会有不认识的函数~不要过于担忧,这是很正常的~请好好利用T的触发界面,记不住的函数,先用T写好,然后转换成jass~久而久之自己也自然记住了的说~

本次教程附件下载~
Jass技能入门教程 Part① by wow8 夜の星.w3x (31.77 KB, 下载次数: 4)

jass技能演示—位置互换~
这种程度,相信各位在T里面,实现它都是非常非常容易~
不过我们是在学习如何用jass的模式来进行技能制作~
所以从头开始吧~O(∩_∩)O~
a.gif


建立触发器,转换为自定义文本~(事件和条件,新人不会的话,也可以尝试着在T里面写好,然后变成jass再优化的说~)

jass
function Trig_A_Conditions takes nothing returns boolean
    return (GetSpellAbilityId()=='A000')//判断释放技能是否为A000
endfunction

function Trig_A_Actions takes nothing returns nothing
    local unit u0=GetTriggerUnit()
    local unit u1=GetSpellTargetUnit()//获取施法者以及目标单位
    local real array x
    local real array y
    set x[0]=GetUnitX(u0)
    set y[0]=GetUnitY(u0)
    set x[1]=GetUnitX(u1)
    set y[1]=GetUnitY(u1)//记录下施法者和目标的坐标
    call SetUnitX(u0,x[1])
    call SetUnitY(u0,y[1])
    call SetUnitX(u1,x[0])
    call SetUnitY(u1,y[0])//设置坐标,就是移动单位的说~
    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl",x[0],y[0]))
    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl",x[1],y[1]))
    //↑创建两个特效~否则实在是过于平淡无奇了~
    //注意,作为路径的字符串,其中的\必须改为\\,否则会发生错误,无法通过语法检测的说~(\为转义字符,如需详细原因,请自行百度百科的说~)
    set u0=null
    set u1=null
    //所有handle类型的局部变量(除了integer、real、string、boolean、code以外)都必须set null
    //否则会造成内存泄露的说~
    //这也是jass和T不同的地方,需要额外注意~
endfunction

//===========================================================================
function InitTrig_A takes nothing returns nothing
    set gg_trg_A = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_A, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_A, Condition( function Trig_A_Conditions ) )
    call TriggerAddAction( gg_trg_A, function Trig_A_Actions )
endfunction



jass技能演示—多人无冲突的属性汲取~


汲取目标英雄10点智力,附加到自己身上,持续15秒.到期后智力将返还对方


和上个技能比起来,这个技能有了一点不同,它需要延时~
或许大家曾经有过,在T中制作类似Dota小鱼人技能时,由于不支持多人而头疼的经历~
而在这里,我们通过使用局部变量+等待,能够轻松解决这个问题~

局部变量是互不冲突的,哪怕是同一个触发器同时运行2遍,这2次生成的局部变量也是独立运作,等待过后,仍然保持各自原来的值,互不干扰~


那个...这种技能截不了图的说~


jass
function Trig_B_Conditions takes nothing returns boolean
    return (GetSpellAbilityId()=='A001')
endfunction

function Trig_B_Actions takes nothing returns nothing
    local unit u0=GetTriggerUnit()
    local unit u1=GetSpellTargetUnit()//获取施法者以及目标单位
    local integer TargetInt=GetHeroInt(u1,false)//获取目标的智力
    local integer DeltaInt
    local effect e1
    local effect e2
    if (TargetInt>1) then//智力最少保留1点,所以必须判断一下
        set DeltaInt=TargetInt-1
        if (DeltaInt>10) then//最多汲取10点智力,加以判断,获得最终的智力转移数值
            set DeltaInt=10
        endif
        call SetHeroInt(u1,TargetInt-DeltaInt,true)
        call SetHeroInt(u0,GetHeroInt(u0,false)+DeltaInt,true)//双方增减智力
        set e1=AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Possession\\PossessionCaster.mdl",u0,"overhead")
        set e2=AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Possession\\PossessionTarget.mdl",u1,"overhead")
        //创建一点特效,美化下技能
        call PolledWait(15)//等待(游戏时间)15秒
        call SetHeroInt(u1,GetHeroInt(u1,false)+DeltaInt,true)
        call SetHeroInt(u0,GetHeroInt(u0,false)-DeltaInt,true)//智力还原
        call DestroyEffect(e1)
        call DestroyEffect(e2)
    endif
    set u0=null
    set u1=null
    set e1=null
    set e2=null
    //局部变量set null排泄,必须的说~
endfunction

//===========================================================================
function InitTrig_B takes nothing returns nothing
    set gg_trg_B = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_B, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_B, Condition( function Trig_B_Conditions ) )
    call TriggerAddAction( gg_trg_B, function Trig_B_Actions )
endfunction



jass技能演示—支持多人的单位返回~
b.gif


嘛~看过星上一篇T技能教程的童鞋们一定对这个很熟悉呢~

记录单位当前位置,令其五秒后返回~

想想看~当时我们可是得创建一个马甲,利用它的生命周期计时,自定义值指向单位......
这次用jass来写,只是短短几行,轻松不少呢~主要还是给大家演示一下jass局部变量不冲突的特性~
jass
function Trig_C_Actions takes nothing returns nothing
    local unit u=gg_unit_Hamg_0014//局部变量保存单位
    local location loc=GetUnitLoc(u)//记录下单位当前位置
    local unit effectUnit=CreateUnitAtLoc(GetOwningPlayer(u),'h000',loc,270)//创建一个马甲单位,当做特效
    call SetUnitAnimation(effectUnit,"birth")//播放马甲birth动画
    call PolledWait(5)//等待5秒~
    call SetUnitPositionLoc(u,loc)//把单位拽回来的说~
    call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl",loc))
    //特效而已
    call RemoveLocation(loc)//点必须删除否则泄露的说~
    call KillUnit(effectUnit)//特效单位也要杀掉~
    set u=null
    set loc=null
    set effectUnit=null
endfunction
//===========================================================================
function InitTrig_C takes nothing returns nothing
    set gg_trg_C = CreateTrigger(  )
    call TriggerRegisterPlayerEventEndCinematic( gg_trg_C, Player(0) )
    //玩家按下ESC事件~
    call TriggerAddAction( gg_trg_C, function Trig_C_Actions )
endfunction


回复 支持 反对

使用道具 举报

 楼主| WOW8 发表于 2018-7-18 15:15:12 | 显示全部楼层

嘛~上面的三个技能,可以说是使用jass做技能最简单的运用了哦~

主要是熟悉一下jass中局部变量~很方便的东西哦~

接下来的话,要加大难度了的说~没错~会会老朋友——计时器与单位组~
不过...可是在新的环境哦~

jass技能演示—计时器控制的冲锋~
碰到这种需要流畅运行的效果,等待是彻底挂了的说~
等待的精度只有0.125秒左右~
所以必须得使用计时器~

↓效果图~
c.gif




本段主要演示TimerStart函数以及单位组函数的运用~
并不支持多人~

TimerStart,作用是开启一个计时器,计时器到期后,会执行指定的目标函数(必须无参数无返回值);有点像T当中,注册计时器到期事件;不同的是,TimerStart直接执行一个函数,脱离了触发器,不需要额外注册~
ForGroup函数,就是我们在T中,常常用到的“选取某某单位组做动作”,它的参数中,要求有一个函数(无参数无返回值),来对组内每一个单位做动作~在这个函数中,通过GetEnumUnit可以获取选取单位~从而进行相应操作的说~

jass
globals
    unit Assult_Caster
    real Assult_Direction
    integer Assult_Count
    group Assult_Damaged
    timer Assult_Timer=CreateTimer()
    effect Assult_WeaponEffect
    //用globals~endglobals块声明的各种全局变量~
    //也可以选择在T中变量管理器里面声明~
    //但是要注意在jass中使用那些变量,需要在变量名前加上udg_前缀~
endglobals


function Trig_D_Conditions takes nothing returns boolean
    return GetSpellAbilityId()=='A002'//判断技能是冲锋~
endfunction


function Assult_GroupActions takes nothing returns nothing
    local unit u=GetEnumUnit()//GetEnumUnit-----选取单位~
   
    if (IsUnitInGroup(u,Assult_Damaged)==false) then//判断单位是否在单位组~
    if (GetUnitState(u,UNIT_STATE_LIFE)>.405) then//判断单位存活~
    if (IsUnitEnemy(u,GetOwningPlayer(Assult_Caster))) then//判断单位是否为敌对~
    if (IsUnitType(u,UNIT_TYPE_FLYING)==false) then//判断单位不是飞行~
        call UnitDamageTarget(Assult_Caster,u,50,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_FIRE,WEAPON_TYPE_WHOKNOWS)
        //命令施法者对敌人造成伤害
        call GroupAddUnit(Assult_Damaged,u)
        //伤害过的敌人加入单位组防止重复伤害~
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl",u,"origin"))
        //创建一个特效~
    endif
    endif
    endif
    endif
   
    set u=null
endfunction


function Assult_Move takes nothing returns nothing
    local location array loc
    local group g
   
    set Assult_Count=Assult_Count+1
   
    set loc[0]=GetUnitLoc(Assult_Caster)
    set loc[1]=PolarProjectionBJ(loc[0],20,Assult_Direction)
    //极坐标位移,从单位位置开始,指定方向位移20
    call SetUnitX(Assult_Caster,GetLocationX(loc[1]))
    call SetUnitY(Assult_Caster,GetLocationY(loc[1]))
    //设置坐标移动单位~
   
    if (Assult_Count-5*(Assult_Count/5)==0) then//相当于Assult_Count Mod 5 =0
        call DestroyEffect(AddSpecialEffectLoc("Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl",loc[1]))
        //每隔0.1秒,创建尘土特效~
    endif
   
    set g=CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(g,loc[1],135,null)
    //创建一个新的单位组,并选取周围135内所有单位~
    call ForGroup(g,function Assult_GroupActions)
    //ForGroup就是T中,选取[单位组]做动作,实际上,是执行另一个函数,见上方↑
    call DestroyGroup(g)
    //删除单位组,排泄的说~
   
    if (Assult_Count>=50) then
    //计数达到上限,冲锋完毕的说~
        call PauseTimer(Assult_Timer)
        call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl",loc[1]))
        call DestroyGroup(Assult_Damaged)
        call SetUnitTimeScale(Assult_Caster,1.0)
        call DestroyEffect(Assult_WeaponEffect)
    endif
   
    call RemoveLocation(loc[0])
    call RemoveLocation(loc[1])
   
    set g=null
    set loc[0]=null
    set loc[1]=null
endfunction


function Trig_D_Actions takes nothing returns nothing
    local unit u=GetTriggerUnit()//施法单位
    local location loc1=GetUnitLoc(u)//施法单位的位置
    local location loc2=GetSpellTargetLoc()//技能释放点
   
    if (GetLocationX(loc1)==GetLocationX(loc2) and GetLocationY(loc1)==GetLocationY(loc2)) then
    //如果目标点和单位重合,即技能点在自己头像上面~此时方向取单位面向角度
        set Assult_Direction=GetUnitFacing(u)
    else
        set Assult_Direction=AngleBetweenPoints(loc1,loc2)
        //两点间方向: 单位位置 --> 技能释放点
    endif
   
    set Assult_Caster=u
    set Assult_Count =0
    set Assult_Damaged=CreateGroup()//全局变量保存数据~
    call SetUnitTimeScale(u,0.45)//减慢单位动画播放速度~
    set Assult_WeaponEffect=AddSpecialEffectTarget("Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl",u,"hand left")
    //在单位武器上面绑定特效~
    call TimerStart(Assult_Timer,0.02,true,function Assult_Move)
    //TimerStart函数,作用是开启一个计时器,并且计时器到期之后,会执行某一个函数~
    //无需特别弄一个触发器,仅需一个函数即可~
    call RemoveLocation(loc1)
    call RemoveLocation(loc2)
    //删除点,排泄
   
    set u=null
    set loc1=null
    set loc2=null
endfunction

//===========================================================================
function InitTrig_D takes nothing returns nothing
    set gg_trg_D = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_D, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    //任意单位发动技能效果事件
    call TriggerAddCondition( gg_trg_D, Condition( function Trig_D_Conditions ) )
    call TriggerAddAction( gg_trg_D, function Trig_D_Actions )
endfunction



jass技能演示—火焰漩涡~
d.gif
嘛~这个的话,实际上是演示了jass中,遍历单位组的另一种方式~通过循环,来取代forgroup,从而不用创建一个新的函数~(也不必通过全局变量,传递数据)

当然并不是没有代价呢...理论上来说,这种方法要比forgroup慢一些,当然在一般的情况下都可以接受

jass
globals
    timer FV_Timer=CreateTimer()
    unit FV_Caster
    location FV_Loc
    integer FV_Count
    unit FV_Vortex
    //用globals~endglobals块声明的各种全局变量~需要Vjass
    //也可以选择在T中变量管理器里面声明~
    //但是要注意在jass中使用那些变量,需要在变量名前加上udg_前缀~
endglobals  

function Trig_E_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A003'//判断施放技能~
endfunction  

function FlameVortexAct takes nothing returns nothing
    local group g
    local unit target
    local player p
    local location array loc
    local real d
    local unit u
    set FV_Count=FV_Count+1
    //计数每次执行的时候,都自增~
   
    set p=GetOwningPlayer(FV_Caster)//获取施法者的拥有玩家~
    set g=CreateGroup()//创建单位组~
    call GroupEnumUnitsInRangeOfLoc(g,FV_Loc,500.0,null)//单位组不分黑白抓住范围内一切单位~
    loop
        set target=FirstOfGroup(g)//设置target为g中第一个单位~
        exitwhen target==null//如果target为null(即单位组g空了),退出循环的说~
        if (GetUnitState(target,UNIT_STATE_LIFE)>.405) then//target是否存活~
        if (IsUnitEnemy(target,p)) then//target是否是玩家的敌人~
            set loc[0]=GetUnitLoc(target)
            set d=DistanceBetweenPoints(FV_Loc,loc[0])-1.0//获取单位到中心的距离,并减小~
            if (d<0) then
                set d=0.0
            endif
            set loc[1]=PolarProjectionBJ(FV_Loc,d,AngleBetweenPoints(FV_Loc,loc[0])-2.1)
            //极坐标位移~
            call SetUnitX(target,GetLocationX(loc[1]))
            call SetUnitY(target,GetLocationY(loc[1]))//移动单位~
            call RemoveLocation(loc[0])
            call RemoveLocation(loc[1])//删除点~
        endif
        endif
        call GroupRemoveUnit(g,target)//将target移除出组~
    endloop
    call DestroyGroup(g)//删除单位组防止泄露~
   
    if (FV_Count>=250) then//计数达到上限,即漩涡存在5秒,结束技能~
        call KillUnit(FV_Vortex)//干掉漩涡单位~
        
        //↓再次选取范围内单位,造成伤害~
        set g=CreateGroup()
        call GroupEnumUnitsInRangeOfLoc(g,FV_Loc,500.0,null)
        loop
            set target=FirstOfGroup(g)
            exitwhen target==null
            //
            if (GetUnitState(target,UNIT_STATE_LIFE)>.405) then
            if (IsUnitEnemy(target,p)) then
                set loc[0]=GetUnitLoc(target)
                call UnitDamageTarget(FV_Caster,target,50.+75.*((500.-DistanceBetweenPoints(loc[0],FV_Loc))/500.),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_FIRE,WEAPON_TYPE_WHOKNOWS)
                //伤害与单位到中心距离有关,距离约小,伤害越大的说~
                call RemoveLocation(loc[0])
            endif
            endif
            //
            call GroupRemoveUnit(g,target)
        endloop
        call DestroyGroup(g)
        
        set u=CreateUnitAtLoc(p,'h002',FV_Loc,270.0)
        call SetUnitTimeScale(u,0.66)
        call UnitAddAbility(u,'Amrf')
        call UnitRemoveAbility(u,'Amrf')
        call SetUnitFlyHeight(u,400.0,.0)
        call UnitApplyTimedLife(u,'BTLF',3.0)
        set u=CreateUnitAtLoc(p,'h004',FV_Loc,270.0)
        call SetUnitTimeScale(u,0.66)
        call UnitAddAbility(u,'Amrf')
        call UnitRemoveAbility(u,'Amrf')
        call SetUnitFlyHeight(u,400.0,.0)
        call UnitApplyTimedLife(u,'BTLF',3.0)
        set u=CreateUnitAtLoc(p,'h003',FV_Loc,270.0)
        call SetUnitTimeScale(u,0.66)
        call UnitAddAbility(u,'Amrf')
        call UnitRemoveAbility(u,'Amrf')
        call SetUnitFlyHeight(u,400.0,.0)
        call UnitApplyTimedLife(u,'BTLF',3.0)
        set u=CreateUnitAtLoc(p,'h003',FV_Loc,90.0)
        call SetUnitTimeScale(u,0.66)
        call UnitAddAbility(u,'Amrf')
        call UnitRemoveAbility(u,'Amrf')
        call SetUnitFlyHeight(u,400.0,.0)
        call UnitApplyTimedLife(u,'BTLF',3.0)
        //以上都是创建十字架爆炸的语句~
        //创建单位→设置动画速度→添加/删除风暴之鸦技能→调整高度→生命周期
        
        call RemoveLocation(FV_Loc)//技能结束,删除目标点,暂停计时器~
        call PauseTimer(FV_Timer)
        set u=null
    endif
   
    set g=null
    set target=null
    set p=null
    set loc[0]=null
    set loc[1]=null
    //局部变量排泄~
endfunction  

function
Trig_E_Actions takes nothing returns nothing
    set FV_Loc=GetSpellTargetLoc()//捕捉技能释放点~
    set FV_Caster=GetTriggerUnit()//技能施放单位~
    set FV_Count=0//用于计数的整数变量~
    set FV_Vortex=CreateUnitAtLoc(GetOwningPlayer(FV_Caster),'h001',FV_Loc,270.0)
    //创建漩涡的单位~
    call TimerStart(FV_Timer,0.02,true,function FlameVortexAct)
    //TimerStart函数启动计时器,计时器到期后,执行函数FlameVortexAct~
endfunction

//===========================================================================
function InitTrig_E takes nothing returns nothing
    set gg_trg_E = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_E, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    //任意单位发动技能效果事件~
    call TriggerAddCondition( gg_trg_E, Condition( function Trig_E_Conditions ) )
    call TriggerAddAction( gg_trg_E, function Trig_E_Actions )
endfunction


回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表