MENU

【GerSwap】Mote-libsで遊ぶナイト:サンプルコードあり

アンバスなどのコンテンツで、何かと出番が増えてきているナイト。

詠唱中断処理など、そこそこ拘ってMote-libsのコードを組んでいます。是非とも参考にしてください。

目次

コード

Mote-libsでは、ジョブロジック部分(ジョブ名.lua)と装備セット部分(ジョブ名_gear.lua)を切り分けていますので、次のような階層構造になっています。

GearSwap/
  └ data/
    ├ PLD.lua
    └ キャラクター名/
       └ PLD_gear.lua

ジョブロジック部分

function get_sets()
    mote_include_version = 2
    include('Mote-Include.lua')
	set_language('japanese')
end

function job_setup()
	state.Buff["センチネル"] = buffactive["センチネル"] or false
	state.Buff["かばう"] = buffactive["かばう"] or false
	state.Buff["死の宣告"] = buffactive["死の宣告"] or false

    state.OffenseMode:options('Normal')
    state.DefenseMode:options('Physical', 'Magical')
    state.IdleMode:options('Normal','Refresh','Physical')
    state.Weapons = M{['description']='Use Weapon','Burtgang'}
end


function user_setup()
    send_command('bind f1 gs c cycle IdleMode')
    send_command('bind f2 gs c cycle DefenseMode')
    send_command('wait 2; gs c set IdleMode Normal;')
end

function user_unload()
    send_command('unbind f1')
    send_command('unbind f2')
    send_command('input /si blank;')
end

function job_buff_change(buff, gain)
    if buff == "ファランクス" and not gain then
        windower.add_to_chat(167,'!!!!!! ファランクス切れ !!!!!!')
    end
end

function customize_idle_set(idleSet) 
    local weapon = sets.weapons[state.Weapons.value]
    idleSet = set_combine(idleSet, weapon)
    return idleSet
end

function customize_melee_set(meleeSet)    
    local weapon = sets.weapons[state.Weapons.value]
    if player.equipment.sub == weapon.main.name then
        weapon.sub.priority = 1
        weapon.main.priority = 0
    end
    meleeSet = set_combine(meleeSet, weapon)
    return meleeSet
end

function job_midcast(spell, action, spellMap, eventArgs) 
    local fc=68/100
    if string.find(spell.type, 'Magic') then
        equip(sets.midcast.interruption)
        local adjust=0.95
        local cast_time = (spell.cast_time*(1-fc))*adjust        
        if spellMap == 'Phalanx' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.Phalanx')

        elseif spellMap == 'Cure' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.Cure')

        elseif spellMap == 'Flash' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.Flash')

        elseif spellMap == 'Banish' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.Banish')

        elseif spellMap == 'BlueMagical' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.BlueMagical')

        elseif spellMap == 'BlueBuff' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.BlueBuff')
        end
    end
end

function job_self_command(cmdParams, eventArgs)
    if cmdParams[1] == 'lockstyleset' then
        send_command('input /lockstyleset 121;')
    elseif cmdParams[1] == 'Enmity' then
        local spell_recasts = windower.ffxi.get_spell_recasts()
        local recast_time_Flash = spell_recasts[112]/60
        local recast_time_BlankGaze = spell_recasts[592]/60
        local recast_time_Jettatura = spell_recasts[575]/60
        
        local ability_recasts = windower.ffxi.get_ability_recasts()
        local recast_time_Provoke = spell_recasts[5]/60

        if recast_time_Flash == 0 then
            send_command('input /ja '..windower.to_shift_jis('神聖の印')..' <me>;wait 0.5;input /ma '..windower.to_shift_jis('フラッシュ')..' <stnpc>')
        elseif recast_time_Jettatura == 0 then
            send_command('input /ma '..windower.to_shift_jis('ジェタチュラ')..' <stnpc>')--0.5
        elseif recast_time_BlankGaze == 0 then
            send_command('input /ma '..windower.to_shift_jis('ブランクゲイズ')..' <stnpc>')--3
        elseif recast_time_Provoke == 0 then
            send_command('input /ja '..windower.to_shift_jis('挑発')..' <stnpc>')
        end
    elseif cmdParams[1] == 'EnmityRange' then
        local spell_recasts = windower.ffxi.get_spell_recasts()
        local recast_time_FrightfulRoar = spell_recasts[561]/60
        local recast_time_Soporific = spell_recasts[598]/60
        local recast_time_SheepSong = spell_recasts[584]/60
        local recast_time_GeistWall = spell_recasts[605]/60
        local recast_time_Stinking = spell_recasts[537]/60
        
        if recast_time_FrightfulRoar == 0 then
            send_command('input /ma '..windower.to_shift_jis('フライトフルロア')..' <stnpc>')--2
        elseif recast_time_GeistWall == 0 then
            send_command('input /ma '..windower.to_shift_jis('ガイストウォール')..' <stnpc>')--3
        elseif recast_time_Stinking == 0 then
            send_command('input /ma '..windower.to_shift_jis('スティンキングガス')..' <stnpc>')--4
        elseif recast_time_Soporific == 0 then
            send_command('input /ma '..windower.to_shift_jis('サペリフィック')..' <stnpc>')--3
        elseif recast_time_SheepSong == 0 then
            send_command('input /ma '..windower.to_shift_jis('シープソ\\ング')..' <stnpc>')--3
        end
    end
end

装備セット部分

function init_gear_sets()
    sets.weapons = {}
    sets.weapons.Burtgang	= { main={name="ブルトガング"}}
	sets.defense.PDT		= {sub="ドゥバン",}
    sets.defense.MDT 		= {sub="イージス",}

	sets.idle = {
		ammo="ストンチタスラム+1",
		head={name="CVアーメット+3",priority=4},
		body={name="アダマンアーマー",priority=5},
		hands="CVガントレ+3",
		legs={name="CVクウィス+3",priority=7},
		feet="RVレギンス+3",
		neck={ name="アンムーヴカラー+1", augments={'Path: A',},priority=9},
		waist={name="プラチナモグベルト",priority=10},
		left_ear="ズワゾピアス+1",
		right_ear={ name="シバリエピアス+1", augments={'System: 1 ID: 1676 Val: 0','Accuracy+15','Mag. Acc.+15','Damage taken-5%',}},
		left_ring="フォテファイリング",
		right_ring="シュネデックリング",
		back={ name="ルディアノスマント", augments={'HP+60','Eva.+20 /Mag. Eva.+20','HP+20','Enmity+10','Chance of successful block +5',}},
    }

	sets.idle.Refresh = set_combine(sets.idle, {
		body="SVキュイラス+1",
		left_ring="スティキニリング+1",
	})

	sets.idle.Physical = set_combine(sets.idle, {
		right_ring="ワーデンリング"
	})

    sets.engaged = {
		ammo="ストンチタスラム+1",
		head="サクパタヘルム",
		body="デーゴンブレスト",
		hands="サクパタガントレ",
		legs="サクパタクウィス",
		feet="サクパタレギンス",
		neck={ name="アンムーヴカラー+1", augments={'Path: A',},priority=9},
		waist={name="プラチナモグベルト",priority=10},
		left_ear="テロスピアス",
		right_ear={ name="シバリエピアス+1", augments={'System: 1 ID: 1676 Val: 0','Accuracy+15','Mag. Acc.+15','Damage taken-5%',}},
		left_ring={ name="ゼラチナスリング+1", augments={'Path: A',},priority=13},
		right_ring={name="月明の指輪",priority=14},
		back={ name="ルディアノスマント", augments={'HP+60','Eva.+20 /Mag. Eva.+20','Enmity+10','Chance of successful block +5',}},
    }

    sets.engaged.DT = set_combine(sets.engaged ,{
		body="サクロブレスト",
		left_ear="ハーティーピアス",
		left_ring="スティキニリング+1",
    })

	sets.Enmity = {
		ammo="サピエンスオーブ",
		head={ name="ロースバルブータ+1", augments={'Path: A',}},
		body="CVキュイラス+3",
		hands={ name="SVハントシュ+1", augments={'HP+105','Enmity+9','Potency of "Cure" effect received +15%',}},
		legs={ name="CBブリーチズ+3", augments={'Enhances "Invincible" effect',}},
		feet="CVサバトン+3",
		neck="月光の首飾り",
		waist={name="プラチナモグベルト",priority=10},
		left_ear="クリプティクピアス",
		right_ear={ name="シバリエピアス+1", augments={'System: 1 ID: 1676 Val: 0','Accuracy+15','Mag. Acc.+15','Damage taken-5%',}},
		left_ring="パニシャスリング",
		right_ring="アイワツリング",
		back={ name="ルディアノスマント", augments={'HP+60','Eva.+20 /Mag. Eva.+20','HP+20','Enmity+10','Chance of successful block +5',}},
	}

	sets.buff['かばう']={body="CBサーコート+3"}

	sets.precast.JA['ランパート'] = set_combine(sets.Enmity,{head="	CBコロネット+3"})
	sets.precast.JA['フィールティ'] = set_combine(sets.Enmity,{body="CBサーコート+3"})
	sets.precast.JA['シールドバッシュ'] = set_combine(sets.Enmity,{hands="CBガントレ+3"})
	sets.precast.JA['シバルリー'] = {
		ammo="クォーツタスラム+1",
		head="ニャメヘルム",
		body="ニャメメイル",
		hands={ name="CBガントレ+3", augments={'Enhances "Chivalry" effect',}},
		legs="ニャメフランチャ",
		feet="ニャメソルレット",
		neck={ name="騎士の数珠+2", augments={'Path: A',}},
		waist={name="プラチナモグベルト",priority=10},
		left_ear={ name="オノワイヤリング+1", augments={'Path: A',}},
		right_ear="エアバニピアス",
		left_ring="スティキニリング+1",
		right_ring="スティキニリング+1",
		back={name="月明の羽衣",priority=15}
	}
	sets.precast.JA['インビンシブル'] = set_combine(sets.Enmity,{legs="CBブリーチズ+3"})
	sets.precast.JA['センチネル'] = set_combine(sets.Enmity,{feer="CBレギンス+3"})

	sets.precast.JA['ホーリーサークル'] = set_combine(sets.Enmity,{feet="RVレギンス+3"})
	sets.precast.JA['神聖の印'] = set_combine(sets.Enmity,{feet="CVサバトン+3"})
	sets.precast.JA['かばう'] = set_combine(sets.Enmity,{head="RVコロネット+1"})

	sets.precast.JA['挑発'] = sets.Enmity
	sets.precast.JA['ヴァレション'] = sets.Enmity
	sets.precast.JA['フルーグ'] = sets.Enmity
	sets.precast.JA['ソードプレイ'] = sets.Enmity
	sets.precast.JA['イグニス'] = sets.Enmity
	sets.precast.JA['ゲールス'] = sets.Enmity
	sets.precast.JA['フラブラ'] = sets.Enmity
	sets.precast.JA['テッルス'] = sets.Enmity
	sets.precast.JA['スルポール'] = sets.Enmity
	sets.precast.JA['ウンダ'] = sets.Enmity
	sets.precast.JA['ルックス'] = sets.Enmity
	sets.precast.JA['テネブレイ'] = sets.Enmity

	sets.precast.FC = {--68
		ammo="サピエンスオーブ",
		head={ name="カマインマスク+1", augments={'Accuracy+20','Mag. Acc.+12','"Fast Cast"+4',}},
		body="RVサーコート+3",
		hands={ name="レイライングローブ", augments={'Accuracy+6','Mag. Acc.+2','"Mag.Atk.Bns."+6',}},
		legs={ name="カマインクウィス+1", augments={'HP+80','STR+12','INT+12',}},
		feet={ name="オディシアグリーヴ", augments={'Mag. Acc.+1 "Mag.Atk.Bns."+1','"Fast Cast"+6','VIT+2','Mag. Acc.+2','"Mag.Atk.Bns."+13',}},
		neck={ name="アンムーヴカラー+1", augments={'Path: A',},priority=9},
		waist={name="プラチナモグベルト",priority=10},
		left_ear="エンチャンピアス+1",
		right_ear={ name="シバリエピアス+1", augments={'System: 1 ID: 1676 Val: 0','Accuracy+15','Mag. Acc.+15','Damage taken-5%',}},
		left_ring="キシャールリング",
		right_ring="メダダリング",
		back={ name="ルディアノスマント", augments={'HP+60','Eva.+20 /Mag. Eva.+20','HP+20','"Fast Cast"+10','Spell interruption rate down-10%',}},

    }

	sets.precast.WS = {
		ammo="昏黄の礫",
		head="サクパタヘルム",
		body="サクパタブレスト",
		hands="サクパタガントレ",
		legs="サクパタクウィス",
		feet="サクパタレギンス",
		neck="フォシャゴルゲット",
		waist="フォシャベルト",
		left_ear="テロスピアス",
		right_ear={ name="シバリエピアス+1", augments={'System: 1 ID: 1676 Val: 0','Accuracy+15','Mag. Acc.+15','Damage taken-5%',}},
		left_ring="エパミノダスリング",
		right_ring="月明の指輪",
		back="月明の羽衣",
    }
	
	sets.precast.WS['ロイエ'] = sets.Enmity
	
	sets.midcast.interruption = {
		ammo="ストンチタスラム+1",
		head={ name="SVシャレル+1", augments={'HP+105','VIT+12','Phys. dmg. taken -4',},priority=4},
		body={name="CVキュイラス+3",priority=5},
		hands={ name="SVハントシュ+1", augments={'HP+105','Enmity+9','Potency of "Cure" effect received +15%',},priority=6},
		legs={ name="CBブリーチズ+3", augments={'Enhances "Invincible" effect',}},
		feet="CVサバトン+3",
		neck="月光の首飾り",
		waist={name="プラチナモグベルト",priority=10},
		left_ear="磁界の耳",
		right_ear={ name="シバリエピアス+1", augments={'System: 1 ID: 1676 Val: 0','Accuracy+15','Mag. Acc.+15','Damage taken-5%',}},
		left_ring={name="ゼラチナスリング+1",priority=13},
		right_ring="アイワツリング",
		back={ name="ルディアノスマント", augments={'HP+60','Eva.+20 /Mag. Eva.+20','HP+20','Enmity+10','Chance of successful block +5',}},
	}
	sets.midcast.Flash = sets.Enmity
	sets.midcast.Banish = sets.Enmity
	sets.midcast.BlueMagical = sets.Enmity
	sets.midcast.BlueBuff = sets.Enmity

	
	sets.midcast.Phalanx = {
		main="サクパタソード",
		sub="プリュウェン",
		ammo="ストンチタスラム+1",
		head={ name="オディシアヘルム", augments={'"Dbl.Atk."+3','"Mag.Atk.Bns."+3','Phalanx +5',}},
		body={ name="オディシアプレート", augments={'VIT+8','Attack+1','Phalanx +5',}},
		hands={ name="SVハントシュ+1", augments={'HP+105','Enmity+9','Potency of "Cure" effect received +15%',},priority=6},
		legs={name="サクパタクウィス",priority=7},
		feet={ name="SVシュー+1", augments={'HP+105','Enmity+9','Potency of "Cure" effect received +15%',},priority=8},
		neck="月光の首飾り",
		waist={name="プラチナモグベルト",priority=10},
		left_ear="磁界の耳",
		right_ear="ミミルピアス",
		left_ring={ name="ゼラチナスリング+1", augments={'Path: A',},priority=13},
		right_ring="エバネセンスリング",
		back={ name="ウェルドマント", augments={'VIT+1','DEX+2','Enmity+1','Phalanx +5',}},
	}

	sets.midcast.Cure = {
		ammo="ストンチタスラム+1",
		head={ name="SVシャレル+1", augments={'HP+105','VIT+12','Phys. dmg. taken -4',},priority=4},
		body={name="CVキュイラス+3",priority=5},
		hands={ name="SVハントシュ+1", augments={'HP+105','Enmity+9','Potency of "Cure" effect received +15%',},priority=6},
		legs={name="CVクウィス+3",priority=7},
		feet={ name="オディシアグリーヴ", augments={'Mag. Acc.+1 "Mag.Atk.Bns."+1','"Fast Cast"+6','VIT+2','Mag. Acc.+2','"Mag.Atk.Bns."+13',}},
		neck="月光の首飾り",
		waist="スローダベルト",
		left_ear="磁界の耳",
		right_ear={ name="シバリエピアス+1", augments={'System: 1 ID: 1676 Val: 0','Accuracy+15','Mag. Acc.+15','Damage taken-5%',}},
		left_ring={ name="ゼラチナスリング+1", augments={'Path: A',},priority=14},
		right_ring={name="月明の指輪",priority=14},
		back={ name="ルディアノスマント", augments={'HP+60','Eva.+20 /Mag. Eva.+20','HP+20','Enmity+10','Chance of successful block +5',}},
	}
end

私のナイトの説明

ナイトでコンテンツに出す機会もそれなりにありますので、少しでも便利にするため、小細工を仕込んでいます。

小細工その①詠唱中断処理

function job_midcast(spell, action, spellMap, eventArgs) 
    local fc=68/100
    if string.find(spell.type, 'Magic') then
        equip(sets.midcast.interruption)
        local adjust=0.95
        local cast_time = (spell.cast_time*(1-fc))*adjust        
        if spellMap == 'Phalanx' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.Phalanx')

        elseif spellMap == 'Cure' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.Cure')

        elseif spellMap == 'Flash' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.Flash')

        elseif spellMap == 'Banish' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.Banish')

        elseif spellMap == 'BlueMagical' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.BlueMagical')

        elseif spellMap == 'BlueBuff' then
            eventArgs.handled = true
            send_command('wait '..cast_time..'; gs equip sets.midcast.BlueBuff')
        end
    end
end

【GerSwap】Mote-libsで遊ぶ青魔道で紹介している詠唱中断処理を使っています。

  • ファランクス
  • ケアル
  • フラッシュ
  • バニシュ
  • 青魔法

これらの魔法は詠唱中断装備で詠唱して、詠唱完了直前に効果アップ装備に着替えています。

上記にない魔法に関しては、とりあえず詠唱中断装備で詠唱しています。

小細工その②マクロの節約

elseif cmdParams[1] == 'Enmity' then
	local spell_recasts = windower.ffxi.get_spell_recasts()
	local recast_time_Flash = spell_recasts[112]/60
	local recast_time_BlankGaze = spell_recasts[592]/60
	local recast_time_Jettatura = spell_recasts[575]/60
	
	local ability_recasts = windower.ffxi.get_ability_recasts()
	local recast_time_Provoke = spell_recasts[5]/60

	if recast_time_Flash == 0 then
		send_command('input /ja '..windower.to_shift_jis('神聖の印')..' <me>;wait 0.5;input /ma '..windower.to_shift_jis('フラッシュ')..' <stnpc>')
	elseif recast_time_Jettatura == 0 then
		send_command('input /ma '..windower.to_shift_jis('ジェタチュラ')..' <stnpc>')--0.5
	elseif recast_time_BlankGaze == 0 then
		send_command('input /ma '..windower.to_shift_jis('ブランクゲイズ')..' <stnpc>')--3
	elseif recast_time_Provoke == 0 then
		send_command('input /ja '..windower.to_shift_jis('挑発')..' <stnpc>')
	end
elseif cmdParams[1] == 'EnmityRange' then
	local spell_recasts = windower.ffxi.get_spell_recasts()
	local recast_time_FrightfulRoar = spell_recasts[561]/60
	local recast_time_Soporific = spell_recasts[598]/60
	local recast_time_SheepSong = spell_recasts[584]/60
	local recast_time_GeistWall = spell_recasts[605]/60
	local recast_time_Stinking = spell_recasts[537]/60
	
	if recast_time_FrightfulRoar == 0 then
		send_command('input /ma '..windower.to_shift_jis('フライトフルロア')..' <stnpc>')--2
	elseif recast_time_GeistWall == 0 then
		send_command('input /ma '..windower.to_shift_jis('ガイストウォール')..' <stnpc>')--3
	elseif recast_time_Stinking == 0 then
		send_command('input /ma '..windower.to_shift_jis('スティンキングガス')..' <stnpc>')--4
	elseif recast_time_Soporific == 0 then
		send_command('input /ma '..windower.to_shift_jis('サペリフィック')..' <stnpc>')--3
	elseif recast_time_SheepSong == 0 then
		send_command('input /ma '..windower.to_shift_jis('シープソ\\ング')..' <stnpc>')--3
	end
end

挑発やフラッシュなど目的が同じで違う処理が複数ある場合、マクロパレットが煩雑になってしまいます。加えてガイストウォールなど範囲敵対心用のマクロボタンも用意しなければいけなく、敵対心を集めるためのマクロボタンがたくさんできてしまいます。

同じ目的の処理は一つのボタンにまとめたい。そのためのコードです。

こんなコードを使わなくても、6行のマクロに書けばいいじゃないかと思うかもしれませんが、GearSwapで6行マクロに複数の魔法を記述すると、正しく着替えが行われません。なので、一つのボタンで複数の処理をまとめるためこんなコードを書きました。

目的該当箇所マクロからの呼び出し方法
単体敵対心用cmdParams[1] == ‘Enmity’/console gs c Enmity
範囲敵対心用cmdParams[1] == ‘EnmityRange’/console gs c EnmityRange

これらのコマンドが呼び出されると、実行可能なアクションが上から順番に実行されます。リキャストが間に合わない場合は実行されません。

	if recast_time_Flash == 0 then
		send_command('input /ja '..windower.to_shift_jis('神聖の印')..' <me>;wait 0.5;input /ma '..windower.to_shift_jis('フラッシュ')..' <stnpc>')
	elseif recast_time_Jettatura == 0 then
		send_command('input /ma '..windower.to_shift_jis('ジェタチュラ')..' <stnpc>')--0.5
	elseif recast_time_BlankGaze == 0 then
		send_command('input /ma '..windower.to_shift_jis('ブランクゲイズ')..' <stnpc>')--3
	elseif recast_time_Provoke == 0 then
		send_command('input /ja '..windower.to_shift_jis('挑発')..' <stnpc>')

魔法のリキャスト情報はffxi.get_spell_recasts()から、アビリティのリキャスト情報はffxi.get_ability_recasts()から取得します。Windower\resを参照して該当アクションのコードで認識させています。

小細工その③ファランクス切れの通知

function job_buff_change(buff, gain)
    if buff == "ファランクス" and not gain then
        windower.add_to_chat(167,'!!!!!! ファランクス切れ !!!!!!')
    end
end

ナイトにとってファランクスは生命線です。

たくさん強化されているような状況で小さなアイコンからファランクスの経過時間を確認するのは困難です。

Timersである程度認識できるとしても、切れている場合はなかなか気付かないことも多いので、私はファランクスが切れたタイミングで目立つメッセージを自分に表示させるようにしています。

コメント

コメントする

目次