===============
---(入門篇)---
===============
《4》函數構造
函數(function)是JASS運作的基本單位,其構造是:
function 函數名 takes 引數類型1 引數名1, 引數類型2 引數名2, ... returns 傳回值類型
//*****************************
//*** 函數主體 ***
//*****************************
return 回傳值
endfunction
引數可以用來在各個function之間傳遞資料
GUI未開放這個功能,所以剛從GUI轉JASS的函數引數都是nothing(無)
但是在JASS你可以透過引數輕鬆的在各個觸發間傳遞資料
假設你A觸發裡面抓到一個部隊,而你要把這部隊的資料傳給觸發B
在GUI的做法是將部隊設為一個全域變數,並執行處發B
在JASS則是使用指令 call 函數B(部隊) 直接將部隊資料從函數A傳給函數B
呼叫函數:(自成一行時)
call 函數名(引數1,引數2,引數3...)
設定變數等於函數回傳值:(變數A的類型與函數回傳值類型必須相同)
(A是整數,函數的回傳值就要是整數,A是部隊,函數的回傳值就要是部隊)
set A = 函數名(引數1,引數2,引數3...)
多重呼叫:(作為函數A引數的函數B,回傳值類型必須等於函數A需要的引數)
call 函數名(函數名B(B引數1,B引數2),A引數2,A引數3...)
《5》向前參照
JASS都有所謂的向前參照特性,雖然所有的function都可以直接被呼叫出來運作,但只有後面的function可以呼叫前面的function,而前面的function如果要呼叫後面的function就會相對的困難許多,除了使用WE自學手冊提到的ExecuteFunc之外,也可以跟GUI一樣先做一個觸發器(包包)把要用的function裝起來,等需要的時候再拿來使用。
JASS的排列方式,是照著觸發器的順序排列的,你把JASS寫在比較前面的觸發,儲存的時候這段JASS就會被排在前面,但這排列順序只針對WE剛讀取的檔案,之後新增的觸發JASS都會被排在最後方!
共用區(永久置頂) → 共用區(永久置頂)
觸發A → 觸發A
觸發B → 觸發B
觸發C → 觸發C
觸發D → 觸發D
在A與B之間新增一條觸發:
共用區(永久置頂) → 共用區(永久置頂)
觸發A → 觸發A
觸發E → 觸發B
觸發B → 觸發C
觸發C → 觸發D
觸發D → 觸發E
關閉WE再重新載入地圖存檔:
共用區(永久置頂) → 共用區(永久置頂)
觸發A → 觸發A
觸發E → 觸發E
觸發B → 觸發B
觸發C → 觸發C
觸發D → 觸發D
《6》觸發的簡化
這是一個非常基礎的GUI英雄技能觸發
直接判定英雄施展的技能類型,並啟動相對應的觸發
以GUI來說,已經是非常節省資源的做法
不過以JASS的角度來看,仍相當累贅呢!
function Trig_Skill_GO_Func001Func001Func001C takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'AEfk' ) ) then
return false
endif
return true
endfunction
function Trig_Skill_GO_Func001Func001C takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'AOws' ) ) then
return false
endif
return true
endfunction
function Trig_Skill_GO_Func001C takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'AHbz' ) ) then
return false
endif
return true
endfunction
function Trig_Skill_GO_Actions takes nothing returns nothing
if ( Trig_Skill_GO_Func001C() ) then
call TriggerExecute( gg_trg_Skill_A )
else
if ( Trig_Skill_GO_Func001Func001C() ) then
call TriggerExecute( gg_trg_Skill_B )
else
if ( Trig_Skill_GO_Func001Func001Func001C() ) then
call TriggerExecute( gg_trg_Skill_C )
else
call TriggerExecute( gg_trg_Skill_D )
endif
endif
endif
endfunction
//=================================
function InitTrig_Skill_GO takes nothing returns nothing
set gg_trg_Skill_GO = CreateTrigger( )
call TriggerRegisterUnitEvent( gg_trg_Skill_GO, gg_unit_hpea_0000, EVENT_UNIT_SPELL_EFFECT )
call TriggerAddAction( gg_trg_Skill_GO, function Trig_Skill_GO_Actions )
endfunction
這是剛從GUI轉成JASS的樣子,還真夠複雜的對吧!
初步的減化是把所有判定直接移回主要的 function 裡面
減少不必要的呼叫,也讓整個觸發變得更簡單明瞭
function Trig_Skill_GO_Actions takes nothing returns nothing
if GetSpellAbilityId() == 'AEfk' then
call TriggerExecute( gg_trg_Skill_A )
else
if GetSpellAbilityId() == 'AOws' then
call TriggerExecute( gg_trg_Skill_B )
else
if GetSpellAbilityId() == 'AHbz' then
call TriggerExecute( gg_trg_Skill_C )
else
call TriggerExecute( gg_trg_Skill_D )
endif
endif
endif
endfunction
//=================================
function InitTrig_Skill_GO takes nothing returns nothing
set gg_trg_Skill_GO = CreateTrigger( )
call TriggerRegisterUnitEvent( gg_trg_Skill_GO, gg_unit_hpea_0000, EVENT_UNIT_SPELL_EFFECT )
call TriggerAddAction( gg_trg_Skill_GO, function Trig_Skill_GO_Actions )
endfunction
接下來是把英雄施展的技能紀錄下來,以整數直接判定類型
並且把多層的if判定改寫為elseif
function Trig_Skill_GO_Actions takes nothing returns nothing
local integer ID = GetSpellAbilityId()
if ID == 'AEfk' then
call TriggerExecute( gg_trg_Skill_A )
elseif ID == 'AOws' then
call TriggerExecute( gg_trg_Skill_B )
elseif ID == 'AHbz' then
call TriggerExecute( gg_trg_Skill_C )
else
call TriggerExecute( gg_trg_Skill_D )
endif
endfunction
//=================================
function InitTrig_Skill_GO takes nothing returns nothing
set gg_trg_Skill_GO = CreateTrigger( )
call TriggerRegisterUnitEvent( gg_trg_Skill_GO, gg_unit_hpea_0000, EVENT_UNIT_SPELL_EFFECT )
call TriggerAddAction( gg_trg_Skill_GO, function Trig_Skill_GO_Actions )
endfunction
至此,觸發的簡化已經告一段落
如果這四個技能的觸發也已經純JASS化
你可以直接把這四個技能的初始化觸發清空
不加入事件、條件、動作,連觸發器都不用創造
function InitTrig_Skill_D takes nothing returns nothing
(清空,刪光光!)
endfunction
直接從主要的function去啟動技能的function
為了方便整理,也可以在裡面使用一些引數,直接傳送必要的數值過去
例如英雄技能等級、可造成傷害
function Trig_Skill_GO takes nothing returns boolean
local integer ID = GetSpellAbilityId()
if ID == 'AEfk' then
call Trig_Skill_A_Actions(引數1,引數2,引數3...)
elseif ID == 'AOws' then
call Trig_Skill_B_Actions(引數1,引數2,引數3...)
elseif ID == 'AHbz' then
call Trig_Skill_C_Actions(引數1,引數2,引數3...)
else
call Trig_Skill_D_Actions(引數1,引數2,引數3...)
endif
return false
endfunction
//=================================
function InitTrig_Skill_GO takes nothing returns nothing
set gg_trg_Skill_GO = CreateTrigger( )
call TriggerRegisterUnitEvent( gg_trg_Skill_GO, gg_unit_hpea_0000, EVENT_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Skill_GO, Condition(function Trig_Skill_GO) )
endfunction
因為不使用等待指令,所以能騙WE說這條function是Condition而不是Action
還記得第3篇提到的處理流程吧?
Condition會在Action之前被處理,而且效率比Action更快
所以針對不需等待的觸發
純JASS化之後可以把Action的東西全部移到Condition
當然在Condition裡面也可以用TimerStart做到更精準且節省資源的等待動作
不過這比較複雜,後面再做詳細介紹