一些JAPI的技巧(1)
我想分享一下一些我所了解的对于JAPI的应用。
但仅限于YDWE的EX和网易的DZ函数,由于网络问题和语言问题我并不在M16活跃,所以不了解JN相关函数的应用。
1:设置技能属性
大部分人都知道,EX函数只能设置一个技能类别的数据,更改后所有同类型技能数据会一起更改。
但一些技能有例外,他们不会立即刷新数据,而是在添加删除或更改技能等级时更新数据。
看一个例子:
function UnitSetDamageBonus takes unit whichUnit, real newValue returns nothing
if GetUnitAbilityLevel(whichUnit, 'AIat') <= 0 then
call UnitAddAbility(whichUnit, 'AIat')
endif
call EXSetAbilityDataReal(EXGetUnitAbility(whichUnit, 'AIat'), 1, ABILITY_DATA_DATA_A, newValue)
call IncUnitAbilityLevel(whichUnit, 'AIat')
call DecUnitAbilityLevel(whichUnit, 'AIat')
endfunction
这是一个设置单位额外攻击奖励的函数,'AIat'是一个攻击之爪技能。(使用"Ctrl+D"来查看物体编辑器中的ID,使用"Ctrl+F"来查找ID)
这样就可以完成对一个单位设置额外攻击力,而不影响其他拥有攻击之爪的单位。
但你无法得知直接通过获取技能数据来得知此单位的额外攻击,你需要自己储存他的额外攻击数值。
同理可以这样修改的技能还有:
'AIsx', 'AId1', 'AIms', 'Aamk'....甚至更多
还有一些例外的情况,生命恢复和法力恢复。('Arel', 'AIrn')
生命恢复和法力恢复技能无法通过直接更改等级来达到刷新效果。
他们需要与('AIlf', 'AIbm')这种能够增加生命值或法力值上限的物品技能来搭配使用。
看一个例子:
function UnitSetLifeRegenBonus takes unit whichUnit, real newValue returns nothing
if GetUnitAbilityLevel(whichUnit, 'Arel') <= 0 then
call UnitAddAbility(whichUnit, 'Arel')
endif
call EXSetAbilityDataReal(EXGetUnitAbility(whichUnit, 'Arel'), 1, ABILITY_DATA_DATA_A, newValue)
call IncUnitAbilityLevel(whichUnit, 'Arel')
call DecUnitAbilityLevel(whichUnit, 'Arel')
call UnitAddAbility(whichUnit, 'AIlf')
call UnitRemoveAbility(whichUnit, 'AIlf')
endfunction
这个设置生命值恢复奖励的函数在改变等级后,多了一个添加删除'AIlf'技能的操作来让数据刷新。
法力恢复同理,在更改技能等级后添加删除'Albm'技能即可,同样需要你自行储存此单位的恢复奖励数值。
还有一个比较特殊的情况,'AIsi'
通过以下操作,可以永久性的增加或减少一个单位的视野。
function UnitAddVisualRange takes unit whichUnit, integer value returns nothing
call UnitAddAbility(whichUnit, 'AIsi' )
call EXSetAbilityDataReal(EXGetUnitAbility(whichUnit, 'AIsi'), 2, ABILITY_DATA_DATA_A, - value )
call IncUnitAbilityLevel(whichUnit, 'AIsi')
call UnitRemoveAbility(whichUnit, 'AIsi' )
endfunction
这些技巧可以用来取代二进制属性系统。
需要注意的是:这些技能最好自己添加,而不是在物体编辑器中直接给予单位,这样可能会导致镜像单位拥有错误的数据。
对于镜像单位,应该在镜像单位产出时重新同步主体的额外属性。

2:被动技能的冷却时间
https://cafe.naver.com/w3umf/133585
有描述设置被动技能冷却时间的方法。
但这种方法会使图标可以点击,并且对于幻象单位不显示图标和冷却时间,我自认为有更好的方法。
魔兽争霸3种有3个被动技能模板可以拥有冷却时间,'AIll', 'Aexh', 'AOre'。
'AIll'始终使用暗图标,这是一个巨大的缺陷。https://tieba.baidu.com/p/6634712745
'Aexh'在hive有详细介绍,https://www.hiveworkshop.com/threads/passive-ability-with-cooldown-best-method.275068/。
'AOre'对幻象也显示图标和冷却时间,唯一的问题就是,如何让重生失去作用。
native TriggerRegisterDeathEvent takes trigger whichTrigger, widget whichWidget returns event
为拥有重生技能的单位注册此事件,单位在有重生时死亡也会触发此事件。
触发事件时禁用重生技能,0秒计时器后开启。
一个例子:
function EnableReincarnationActions takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h = GetHandleId(t)
local player p = LoadPlayerHandle(HY, h, 1)
if not SPCDB[GetPlayerId(p)] then
call SetPlayerAbilityAvailable(p, 'QP1G', true)
call SetPlayerAbilityAvailable(p, 'A522', true)
call SetPlayerAbilityAvailable(p, 'QP17', true)
call SetPlayerAbilityAvailable(p, 'QP1O', true)
call SetPlayerAbilityAvailable(p, 'A3UF', true)
call SetPlayerAbilityAvailable(p, 'A0CG', true)
endif
call FlushChildHashtable(HY, h)
call DestroyTimer(t)
set t = null
set p = null
endfunction
function DisableReincarnationActions takes nothing returns boolean
local trigger tri = GetTriggeringTrigger()
local timer t = CreateTimer()
local integer tri_h = GetHandleId(tri)
local integer h = GetHandleId(t)
local player p = LoadPlayerHandle(HY, tri_h, 1)
call SetPlayerAbilityAvailable(p, 'QP1G', false)
call SetPlayerAbilityAvailable(p, 'A522', false)
call SetPlayerAbilityAvailable(p, 'QP17', false)
call SetPlayerAbilityAvailable(p, 'QP1O', false)
call SetPlayerAbilityAvailable(p, 'A3UF', false)
call SetPlayerAbilityAvailable(p, 'A0CG', false)
call SavePlayerHandle(HY, h, 1, p)
call TimerStart(t, 0.00, false, function EnableReincarnationActions)
set p = null
set t = null
set tri = null
return false
endfunction
function CreateCheckReincarnationTrig takes unit u returns nothing
local trigger t = CreateTrigger()
local integer h = GetHandleId(t)
call SavePlayerHandle(HY, h, 1, GetOwningPlayer(u))
call TriggerRegisterDeathEvent(t, u)
call TriggerAddCondition(t, Condition(function DisableReincarnationActions))
call SaveTriggerHandle(W, GetHandleId(u),'PACD', t)
set t = null
endfunction

3:单位类型数据
globals
constant integer UNIT_STRING_MODEL_PATH = 13
constant integer UNIT_STRING_MODEL_PORTRAIT_PATH = 14
constant integer UNIT_STRING_SHADOW_PATH = 0x13
constant integer UNIT_REAL_MODEL_SCALE = 0x2c
constant integer UNIT_REAL_SHADOW_X = 0x20
constant integer UNIT_REAL_SHADOW_Y = 0x21
constant integer UNIT_REAL_SHADOW_W = 0x22
constant integer UNIT_REAL_SHADOW_H = 0x23
endglobals
native EXGetUnitString takes integer unitcode, integer Type returns string
native EXSetUnitString takes integer unitcode,integer Type,string value returns boolean
native EXGetUnitReal takes integer unitcode, integer Type returns real
native EXSetUnitReal takes integer unitcode,integer Type,real value returns boolean
native EXGetUnitInteger takes integer unitcode, integer Type returns integer
native EXSetUnitInteger takes integer unitcode,integer Type,integer value returns boolean
native EXGetUnitArrayString takes integer unitcode, integer Type,integer index returns string
一些数据需要在设置后使用变身刷新数据,或者在创建单位之前来修改这些值。
4:lua引擎
https://github.com/actboy168/jass2lua/blob/master/lua-engine.md
我并不怎么了解LUA,我只能分享一些简单的与JASS的应用。
LUA引擎中有很多独特的功能,通过hook库的功能让JASS可以调用它们。
native EXExecuteScript takes string script returns string
EXExecuteScript此函数也可以在JASS与LUA引擎交互。
示例:
local message = require 'jass.message'
local globals = require 'jass.globals'
local hook = require "jass.hook"
function hook.GetStartLocPrioSlot(x,y)
local ability, order= message.button(x, y)
globals.MessageAbilityOrder = order
return ability
end
function hook.GetDetectedUnit()
local u = message.selection()
if not u then
return nil
end
return u
end
GetStartLocPrioSlot 只在config中使用,在正常游戏时没有作用。
GetDetectedUnit 什么也不干,我不知道他有什么作用。
这2个函数都是我用不到的,所以hook来与LUA交互。
GetStartLocPrioSlot 现在会返回当前玩家控制台指定坐标的技能Id和命令。
GetDetectedUnit 现在会返回玩家当前所选择的第一个单位。
必须要注意的是:这些值全都是异步的,如果需要在同步环境下使用,请使用DzSyncData。
链接:https://pan.baidu.com/s/1kqwznNIcu7TT5pc0uymdmA?pwd=5vfy
提取码:5vfy
我之前的DoubleClickSpell系统就是通过LUA引擎来实现的。
https://cafe.naver.com/w3umf/133875
japi库:require 'jass.japi'
包含了所有EX和DZ的JAPI函数,由于JNLoader没有向LUA引擎注入JN函数,所以LUA无法使用JN函数。
进入此地图可以查看当前环境下JAPI库中的所有函数。
链接:https://pan.baidu.com/s/1hWOblnVf3HUNjYPuhlWanw?pwd=mqq2
提取码:mqq2