|
2006/3/30カスタムAIVer4:アミストル専用 |
|---|
AI_2はこちら
-- ※"require"のある行からコピペで、AI.luaへ上書き貼り付けして使用してください※
-- ※使用は自己責任で※
-- ・コードが長くなったので 2ファイル に分けてます
-- ・これはVer3をアミストル専用にまとめたものです
-- ・他のホムンクルスでこのAIを使用するとエラー落ちします
-- ・デフォルトで先行型になっているので、非先行型が好みの方は
-- function GetMyEnemy (myid)内の GetMyEnemyB (myid) を GetMyEnemyA (myid)に変えて使用してください
----------------------------------------
-------------------------------------------------
-- 参考AI
-- The Winter's Tale
-- http://www.sgv417.jp/~winter/index.html
-- 0-MATERIAL (ぜろ・まてりある)
-- http://www.kogarashi.jp/0-material/
-- 工体研究所rev10
-- http://blog.livedoor.jp/aidev/archives/50119284.html
-- くま○〜@ガルムのAIファイル配布
-- http://www.kmzw.jp/nb/ai.html
-- ホムンクルスのAIを語るスレ その3
-- http://enif.mmobbs.com/test/read.cgi/livero/1142535070/l50
-- ホムンクルスのAIを語るスレ その4
-- http://enif.mmobbs.com/test/read.cgi/livero/1143193717/l50
-- ホムンクルスAIについての雑談・要望スレ
-- http://enif.mmobbs.com/test/read.cgi/livero/1142513331/l50
-------------------------------------------------
require "./AI/Const.lua"
require "./AI/Util.lua"
require "./AI/USER_AI/AI_2.lua"
-----------------------------
-- state(ホムの状態関数)
-----------------------------
IDLE_ST = 0 -- 待機状態
FOLLOW_ST = 1 -- 所持者追従状態
CHASE_ST = 2 -- ターゲット追跡状態
ATTACK_ST = 3 -- 攻撃状態
--
MOVE_CMD_ST = 4
STOP_CMD_ST = 5
ATTACK_OBJECT_CMD_ST = 6
ATTACK_AREA_CMD_ST = 7
PATROL_CMD_ST = 8
HOLD_CMD_ST = 9
SKILL_OBJECT_CMD_ST = 10
SKILL_AREA_CMD_ST = 11
FOLLOW_CMD_ST = 12
--
RUNAWAY_ST = 13 -- 追加関数(逃亡処理)
AUTOSKILL_ST = 14 -- 追加関数(オートスキル処理)
AMISTR_ST = 15 -- 追加関数(アミストル専用)
----------------------------
------------------------------------------
-- global variable(処理内部で使うグローバル変数)
------------------------------------------
MyState = IDLE_ST -- ホムの現在状態(初期値は待機状態)
MyEnemy = 0 -- ホムがターゲットしている敵のキャラクターID
MyDestX = 0 -- ホムの目標座標X(移動先 / スキル使用座標)
MyDestY = 0 -- ホムの目標座標Y(移動先 / スキル使用座標)
MyPatrolX = 0 -- ホムの偵察目的地 x座標
MyPatrolY = 0 -- ホムの偵察目的地 y座標
ResCmdList = List.new() -- 予約コマンドリスト
MyID = 0 -- ホムンクルス自身のid
MySkill = 0 -- ホムンクルスの使用スキル
MySkillLevel = 0 -- ホムンクルスの使用スキルレベル
------------------------------------------
------------------------------------------
-- 追加分global variable(ここの初期値をいじることでホムの設定をカスタマイズできる)
------------------------------------------
AttackArea = 6 -- アクティブ状態の時、主人からこの距離のMobを殴りに行く
AwayRange = 4 -- 主人からどのくらい離れたところまで逃げるか
AwayHP = 40 -- 何%でホムが逃げるか
Move_Distance = 15 -- ALT+右クリックでホムを移動させた時、どの範囲までなら帰ってこないようにするか(5〜15推奨)
AttackOrder = 1 -- 攻撃の優先度(主人のタゲ優先(デフォルトAIと同じ)=1、自分のタゲ優先=0)
SafeMyOwner = 1 -- 主人がタゲられたら攻撃を中止して主人のタゲを奪う「ご主人はぼくが守る!」モード(yes=1、no=0)
-- オートスキル設定
AutoSkill = 20 -- ホムの自動スキルの最高確率(%)(SPが減ると確率減少、フィーリルとバニルミストのみ)
AutoSkill_SP = 40 -- ホムのSPがこの%を下回った場合には自動スキル発動なし
-- アミストルのオートスキル設定
CastlingLv = 5 -- キャスリングの使用Lv(アミストルのみ)
CastOwner = 10 -- 主人のHPが何%で自動キャスリング(アミストルのみ)
CastWay = 6 -- 主人から何セル離れた場所でキャスリングするか(アミストルのみ)
CastSwitch = 1 -- 自動でキャスリングするかどうかスイッチ(yes=1 no=0)
-- その他
Timer1 = GetTick() -- タイマー1、現在時刻格納
MoveTime = 500 -- 移動時の座標更新間隔
MoveTime2 = 0 -- 移動時の座標更新用タイマー1
Castling = 1 -- キャスリングしたかどうかの印、変更しないほうが無難
NoAttackSwitch = 0 -- 設定Mobを殴らないスイッチ、いじってはダメ※先行時のみ効果有り※
AwayEnwmySwitch = 0 -- 逃亡時設定Mobからは逃げないスイッチ、いじってはダメ
ActionSwitch = 1 -- テレポ、マップ移動後即座にホムが敵を攻撃しにいかない(yes=1 no=0)(先行時のみ)
-- (ActionSwitchはホム生成2秒後に主人と重なったセルから飛び出すという処理にも使っているのでいじらないほうが無難)
------------------------------------------
----------------------------------------------------
-- 手動(予約)処理
------------- command process ---------------------
----------------------------------------------------
-- 移動命令(地面をALT+右クリック)
----------------------------------------------------
----------------------------------------------------
function OnMOVE_CMD (x,y)
TraceAI ("OnMOVE_CMD")
if ( x == MyDestX and y == MyDestY and MOTION_MOVE == GetV(V_MOTION,MyID)) then
return -- 目的地と現在地が同一の場合は、処理しない
end
local curX, curY = GetV (V_POSITION,MyID) -- ホム自身の座標を代入
-- ホムの自動戻り処理
if (math.abs(x-curX)+math.abs(y-curY) > 15) then -- 目的地が一定距離(15セル)以上なら (サーバーで遠距離は処理しないため)
List.pushleft (ResCmdList,{MOVE_CMD,x,y}) -- 元の目的地への移動を予約する
x = math.floor((x+curX)/2) -- 予約した地点と現在位置の中間地点へ移動する
y = math.floor((y+curY)/2) -- 同上
end
-- 移動処理
Move (MyID,x,y)
MyState = MOVE_CMD_ST -- 移動状態へ、以下初期化
MyDestX = x
MyDestY = y
MyEnemy = 0
MySkill = 0
end
----------------------------------------------------
-- 停止命令(未実装)
----------------------------------------------------
----------------------------------------------------
function OnSTOP_CMD ()
TraceAI ("OnSTOP_CMD")
if (GetV(V_MOTION,MyID) ~= MOTION_STAND) then -- 現在の命令がSTANDでない場合
Move (MyID,GetV(V_POSITION,MyID)) -- ホム自身の座標へ移動(その場で停止)
end
MyState = IDLE_ST -- 待機状態へ、以下初期化
MyDestX = 0
MyDestY = 0
MyEnemy = 0
MySkill = 0
end
----------------------------------------------------
-- 指定目標への攻撃命令(対象を ALT+右ダブルクリック or ALT+右クリック2回目)
----------------------------------------------------
----------------------------------------------------
function OnATTACK_OBJECT_CMD (id)
TraceAI ("OnATTACK_OBJECT_CMD")
MySkill = 0
MyEnemy = id -- 指定目標のidをホムのターゲットに指定
MyState = CHASE_ST -- 指定目標を追跡
end
----------------------------------------------------
-- 指定座標への攻撃命令(未実装)
----------------------------------------------------
----------------------------------------------------
function OnATTACK_AREA_CMD (x,y)
TraceAI ("OnATTACK_AREA_CMD")
if (x ~= MyDestX or y ~= MyDestY or MOTION_MOVE ~= GetV(V_MOTION,MyID)) then
Move (MyID,x,y) -- 座標目標と指定座標が違う、または現在の状態が移動状態ではない場合、指定座標まで移動
end
MyDestX = x
MyDestY = y
MyEnemy = 0 -- ターゲットリセット
MyState = ATTACK_AREA_CMD_ST -- 範囲攻撃開始
end
----------------------------------------------------
-- 偵察(移動)命令(未実装)
----------------------------------------------------
----------------------------------------------------
function OnPATROL_CMD (x,y)
TraceAI ("OnPATROL_CMD")
MyPatrolX , MyPatrolY = GetV (V_POSITION,MyID) -- 偵察目的地に現在のホムの座標を代入
MyDestX = x -- 指定座標を目標座標に設定
MyDestY = y
Move (MyID,x,y)
MyState = PATROL_CMD_ST -- 偵察開始
end
----------------------------------------------------
-- (未実装)
----------------------------------------------------
----------------------------------------------------
function OnHOLD_CMD ()
TraceAI ("OnHOLD_CMD")
MyDestX = 0
MyDestY = 0
MyEnemy = 0
MyState = HOLD_CMD_ST
end
----------------------------------------------------
-- 指定目標へスキルを使う命令
----------------------------------------------------
----------------------------------------------------
function OnSKILL_OBJECT_CMD (level,skill,id)
TraceAI ("OnSKILL_OBJECT_CMD")
MySkillLevel = level
MySkill = skill
MyEnemy = id
MyState = CHASE_ST
end
----------------------------------------------------
-- 指定座標へスキルを使う命令(未実装)
----------------------------------------------------
----------------------------------------------------
function OnSKILL_AREA_CMD (level,skill,x,y)
TraceAI ("OnSKILL_AREA_CMD")
Move (MyID,x,y)
MyDestX = x
MyDestY = y
MySkillLevel = level
MySkill = skill
MyState = SKILL_AREA_CMD_ST
end
----------------------------------------------------
-- 主人追尾命令(ALT+T)、追尾状態と待機状態を互いに転換させる
----------------------------------------------------
----------------------------------------------------
function OnFOLLOW_CMD ()
if (MyState ~= FOLLOW_CMD_ST) then -- 現在状態が追尾コマンド実行中でない場合
MoveToOwner (MyID) -- ホム所持者(ケミ)の元まで移動
MyState = FOLLOW_CMD_ST -- 追尾状態に
MyDestX, MyDestY = GetV (V_POSITION,GetV(V_OWNER,MyID)) -- 所持者の座標を目標に指定
MyEnemy = 0
MySkill = 0
TraceAI ("OnFOLLOW_CMD")
else
MyState = IDLE_ST -- 待機コマンド実行中だった場合、待機状態に
MyEnemy = 0
MySkill = 0
TraceAI ("FOLLOW_CMD_ST --> IDLE_ST")
end
end
----------------------------------------------------
-- 手動(予約)処理、本体
-- クライアントからのコマンドを解釈し対応する関数へ渡す
----------------------------------------------------
----------------------------------------------------
function ProcessCommand (msg)
if (msg[1] == MOVE_CMD) then -- msg[1]が移動コマンドだった場合
OnMOVE_CMD (msg[2],msg[3]) -- msg[2]とmsg[3]の値をそれぞれOnMOVE_CMDのxとyへ
TraceAI ("MOVE_CMD")
elseif (msg[1] == STOP_CMD) then -- msg[1]が停止コマンドだった場合(未実装)
OnSTOP_CMD ()
TraceAI ("STOP_CMD")
elseif (msg[1] == ATTACK_OBJECT_CMD) then -- msg[1]が指定目標への攻撃コマンドだった場合
OnATTACK_OBJECT_CMD (msg[2]) -- msg[2]をOnATTACK_OBJECT_CMDのidへ
TraceAI ("ATTACK_OBJECT_CMD")
elseif (msg[1] == ATTACK_AREA_CMD) then -- msg[1]が指定座標への攻撃コマンドだった場合(未実装)
OnATTACK_AREA_CMD (msg[2],msg[3])
TraceAI ("ATTACK_AREA_CMD")
elseif (msg[1] == PATROL_CMD) then -- msg[1]が偵察(移動)コマンドだった場合(未実装)
OnPATROL_CMD (msg[2],msg[3])
TraceAI ("PATROL_CMD")
elseif (msg[1] == HOLD_CMD) then -- msg[1]がホールドコマンドだった場合(未実装)
OnHOLD_CMD ()
TraceAI ("HOLD_CMD")
elseif (msg[1] == SKILL_OBJECT_CMD) then -- msg[1]が指定対象へのスキルコマンドだった場合
OnSKILL_OBJECT_CMD (msg[2],msg[3],msg[4],msg[5]) -- それぞれ、OnSKILL_OBJECT_CMD (level,skill,id)へ代入
TraceAI ("SKILL_OBJECT_CMD")
elseif (msg[1] == SKILL_AREA_CMD) then -- msg[1]が指定座標へのスキルコマンドだった場合(未実装)
OnSKILL_AREA_CMD (msg[2],msg[3],msg[4],msg[5]) -- それぞれ、OnSKILL_AREA_CMD (level,skill,x,y)へ代入
TraceAI ("SKILL_AREA_CMD")
elseif (msg[1] == FOLLOW_CMD) then -- msg[1]が追尾コマンドだった場合
OnFOLLOW_CMD ()
TraceAI ("FOLLOW_CMD")
end
end
-----------------------------------------------------
-- 基本処理(ホムの状態関数)
-------------- state process -----------------------
----------------------------------------------------
-- 待機処理
----------------------------------------------------
----------------------------------------------------
function OnIDLE_ST ()
TraceAI ("OnIDLE_ST")
local cmd = List.popleft(ResCmdList)
if (cmd ~= nil) then
ProcessCommand (cmd) -- 予約コマンド処理
return
end
----------------------------------------------------
local motion = GetV(V_MOTION, GetV(V_OWNER,MyID))
if (motion == MOTION_MOVE or motion == MOTION_ATTACK or motion == MOTION_ATTACK2) then -- 主人が移動状態or攻撃状態だったら
ActionSwitch = 0 -- テレポ、マップ移動後、主人が動き出したらスイッチOFF
elseif(2000 <= GetTick()-Timer1 and ActionSwitch == 1) then -- ホム生成後2秒過ぎたら
local x,y = GetV (V_POSITION,GetV(V_OWNER,MyID))
Move (MyID,x+1,y) -- 主人と重ならないためにx+1(主人と重なったセルから飛び出す)
end
----------------------------------------------------
if (ActionSwitch == 0) then -- スイッチOFFだったら行動開始
-- AttackOrderが1なら主人優先
if(AttackOrder == 1)then
local object = GetOwnerEnemy (MyID) -- 所持者(ケミ)のidをobjectへ
if (object ~= 0) then -- MYOWNER_ATTACKED_IN
MyState = CHASE_ST
MyEnemy = object
TraceAI ("IDLE_ST -> CHASE_ST : MYOWNER_ATTACKED_IN")
return
end
object = GetMyEnemy (MyID) -- ホムの敵のidをobjectへ
if (object ~= 0) then -- ATTACKED_IN
MyState = CHASE_ST
MyEnemy = object
TraceAI ("IDLE_ST -> CHASE_ST : ATTACKED_IN")
return
end
end
-- AttackOrderが0ならホム自身優先
if(AttackOrder == 0) then
local object = GetMyEnemy (MyID) -- ホムの敵のidをobjectへ
if (object ~= 0) then -- ATTACKED_IN
MyState = CHASE_ST
MyEnemy = object
TraceAI ("IDLE_ST -> CHASE_ST : ATTACKED_IN")
return
end
object = GetOwnerEnemy (MyID) -- 所持者(ケミ)のidをobjectへ
if (object ~= 0) then -- MYOWNER_ATTACKED_IN
MyState = CHASE_ST
MyEnemy = object
TraceAI ("IDLE_ST -> CHASE_ST : MYOWNER_ATTACKED_IN")
return
end
end
local distance = GetDistanceFromOwner(MyID)
if ( distance > 2 or distance == -1) then -- MYOWNER_OUTSIGNT_IN
MyState = FOLLOW_ST
TraceAI ("IDLE_ST -> FOLLOW_ST")
return;
end
--------------------------オートスキル2-------------
MyState = AMISTR_ST -- オートスキル処理2、支援スキルの自動かけなおし
----------------------------------------------------
TraceAI ("OnIDLE_ST -> AMISTR_ST")
end
end
----------------------------------------------------
-- 追尾処理
----------------------------------------------------
----------------------------------------------------
function OnFOLLOW_ST ()
TraceAI ("OnFOLLOW_ST")
if (GetDistanceFromOwner(MyID) <= 2) then -- 主人とホムの距離が2以下の場合
MyState = IDLE_ST -- 待機状態に
TraceAI ("FOLLOW_ST -> IDLW_ST")
return;
elseif (GetV(V_MOTION,MyID) == MOTION_STAND or GetV(V_MOTION,MyID) == MOTION_MOVE) then -- ホムの状態が立ち、または移動状態だった場合
if (GetV(V_MOTION, GetV(V_OWNER,MyID)) == MOTION_MOVE) then -- 主人が移動状態だったら
MoveTime2 = GetTick() -- 現在時刻を移動時の座標更新用タイマー1へ
if (MoveTime < MoveTime2 - Timer1) then -- MoveTimeに格納されてるm秒数を過ぎたら移動
Timer1 = GetTick() -- 移動した時点での時刻を格納しなおす
local x,y = GetV(V_POSITION,GetV(V_OWNER,MyID))
Move (MyID,x,y)
TraceAI ("FOLLOW_ST -> FOLLOW_ST")
end
return;
else
local x,y = GetV(V_POSITION,GetV(V_OWNER,MyID)) -- 主人が立ち状態だったら主人のそばに待機
MoveToOwner (MyID)
TraceAI ("FOLLOW_ST -> FOLLOW_ST")
return;
end
end
end
----------------------------------------------------
-- 追跡処理
----------------------------------------------------
----------------------------------------------------
function OnCHASE_ST ()
TraceAI ("OnCHASE_ST")
---------------------------逃亡判定-----------------
local MyHP = GetV (V_HP,MyID)
local MyMaxHP = GetV (V_MAXHP,MyID)
local HPper = (MyHP / MyMaxHP) * 100
if (AwayHP >= HPper) then -- AwayHP以下だと追跡(攻撃)しない
MyState = RUNAWAY_ST
TraceAI ("CHASE_ST -> RUNAWAY_ST")
return
end
----------------------------------------------------
if (true == IsOutOfSight(MyID,MyEnemy)) then -- Mobが視界から消えたら待機
MyState = IDLE_ST
MyEnemy = 0
MyDestX, MyDestY = 0,0
TraceAI ("CHASE_ST -> IDLE_ST : ENEMY_OUTSIGHT_IN")
return
end
if (true == IsInAttackSight(MyID,MyEnemy)) then -- 攻撃範囲に入ったら攻撃
MyState = ATTACK_ST
TraceAI ("CHASE_ST -> ATTACK_ST : ENEMY_INATTACKSIGHT_IN")
return
end
local x, y = GetV (V_POSITION,MyEnemy) -- 敵の座標を代入
if (MyDestX ~= x or MyDestY ~= y) then -- 敵の座標がホムの目的座標でない場合
MyDestX, MyDestY = GetV (V_POSITION,MyEnemy);
Move (MyID,MyDestX,MyDestY) -- 敵の方へ接近
TraceAI ("CHASE_ST -> CHASE_ST : DESTCHANGED_IN")
return
end
end
----------------------------------------------------
-- 攻撃処理
----------------------------------------------------
----------------------------------------------------
function OnATTACK_ST ()
TraceAI ("OnATTACK_ST")
if (true == IsOutOfSight(MyID,MyEnemy)) then -- Mobが視界から消えたら待機
MyEnemy = 0
MySkill = 0
MyState = IDLE_ST
TraceAI ("ATTACK_ST -> IDLE_ST")
return
end
if (MOTION_DEAD == GetV(V_MOTION,MyEnemy)) then -- Mobが死んだら待機
MyEnemy = 0
MySkill = 0
MyState = IDLE_ST
TraceAI ("ATTACK_ST -> IDLE_ST")
return
end
---------------------------逃亡判定---------------------------------------------
local MyHP = GetV (V_HP,MyID)
local MyMaxHP = GetV (V_MAXHP,MyID)
local HPper = (MyHP / MyMaxHP) * 100
if (AwayHP >= HPper) then -- AwayHP以下だと追跡(攻撃)しない
MyState = RUNAWAY_ST
TraceAI ("ATTACK_ST -> RUNAWAY_ST")
return
end
--------------------------------------------------------------------------------
if (false == IsInAttackSight(MyID,MyEnemy)) then -- Mobが視界に入ったら追いかける
MyState = CHASE_ST
MyDestX, MyDestY = GetV (V_POSITION,MyEnemy);
Move (MyID,MyDestX,MyDestY)
TraceAI ("ATTACK_ST -> CHASE_ST : ENEMY_OUTATTACKSIGHT_IN")
return
end
if (MySkill == 0) then -- 使用スキルが指定されていなければ
Attack (MyID,MyEnemy)
MyState = AUTOSKILL_ST -- オートスキル使用
TraceAI ("ATTACK_ST -> AUTOSKILL_ST")
else -- スキルが指定されていたらスキル使用
SkillObject (MyID,MySkillLevel,MySkill,MyEnemy)
MySkill = 0
end
--------------------------------------------------------------------------------
if(SafeMyOwner == 1) then -- 「ご主人はぼくが守る!」発動
local object = GetOwnerEnemy (MyID) -- 所持者(ケミ)のidをobjectへ
if (object ~= 0) then -- MYOWNER_ATTACKED_IN
MyState = CHASE_ST
MyEnemy = object
TraceAI ("ATTACK_ST -> CHASE_ST : SafeMyOwner")
end
end
--------------------------------------------------------------------------------
return
end
----------------------------------------------------
-- 移動処理
----------------------------------------------------
----------------------------------------------------
function OnMOVE_CMD_ST ()
TraceAI ("OnMOVE_CMD_ST")
local x, y = GetV (V_POSITION,MyID)
if (x == MyDestX and y == MyDestY) then -- ホムの位置が目的地である場合
MyState = STOP_CMD_ST -- 停止状態へ(IDLE_ST=>STOP_CMD_STと変更)
end
end
-------------------------------------------------
-- 停止処理
-- ケミ待機時に限り、ホムを手動で移動させても戻ってこない(移動先で待機)
-------------------------------------------------
-------------------------------------------------
function OnSTOP_CMD_ST ()
TraceAI ("OnSTOP_CMD_ST")
local ownerX, ownerY
ownerX, ownerY = GetV (V_POSITION,GetV(V_OWNER,MyID))
if (ownerX ~= MyOwnerX or ownerY ~= MyOwnerY) then -- 主人が動いていたら
MyOwnerX = ownerX
MyOwnerY = ownerY
MyState = IDLE_ST -- 待機状態に
else -- 主人の位置が動いていなければそのまま留まる
if (GetDistanceFromOwner(MyID) >= Move_Distance) then -- 主人とホムの距離が20セル以上の場合
MyState = IDLE_ST -- 戻ってくる
end
MyOwnerX = ownerX
MyOwnerY = ownerY
end
return
end
-------------------------------------------------
-- 指定対象を攻撃する時のコマンド(使用されていない)
-------------------------------------------------
-------------------------------------------------
function OnATTACK_OBJECT_CMD_ST ()
end
-------------------------------------------------
-- 指定座標を攻撃する時のコマンド(使用されていない)
-------------------------------------------------
-------------------------------------------------
function OnATTACK_AREA_CMD_ST ()
TraceAI ("OnATTACK_AREA_CMD_ST")
local object = GetOwnerEnemy (MyID)
if (object == 0) then
object = GetMyEnemy (MyID)
end
if (object ~= 0) then -- MYOWNER_ATTACKED_IN or ATTACKED_IN
MyState = CHASE_ST
MyEnemy = object
return
end
local x , y = GetV (V_POSITION,MyID)
if (x == MyDestX and y == MyDestY) then -- DESTARRIVED_IN
MyState = IDLE_ST
end
end
-------------------------------------------------
-- 偵察処理(未実装)使えるのか使えないのかよくわからんコマンド
-------------------------------------------------
-------------------------------------------------
function OnPATROL_CMD_ST ()
TraceAI ("OnPATROL_CMD_ST")
local object = GetOwnerEnemy (MyID) -- 主人の敵IDを代入
if (object == 0) then -- 敵が居ない場合
object = GetMyEnemy (MyID) -- ホムの敵を代入
end
if (object ~= 0) then -- 敵が居る場合
MyState = CHASE_ST -- その敵を追跡→攻撃
MyEnemy = object
TraceAI ("PATROL_CMD_ST -> CHASE_ST : ATTACKED_IN")
return
end
local x , y = GetV (V_POSITION,MyID)
if (x == MyDestX and y == MyDestY) then -- ホムが目的地に来たら
MyDestX = MyPatrolX -- ホムの目的地座標に偵察座標を設定
MyDestY = MyPatrolY -- 同上(どっかで偵察座標の数値をいれないと使えないな…)
MyPatrolX = x -- 現在位置を偵察座標へ
MyPatrolY = y -- 同上(偵察座標と現在位置の二点をウロウロするってことか…微妙)
Move (MyID,MyDestX,MyDestY)
end
end
-------------------------------------------------
-- (未実装)よー分からんコマンド
-------------------------------------------------
-------------------------------------------------
function OnHOLD_CMD_ST ()
TraceAI ("OnHOLD_CMD_ST")
if (MyEnemy ~= 0) then -- 敵がいる場合
local d = GetDistance2(MyEnemy,MyID) -- ホムのターゲットの距離をdへ代入
if (d ~= -1 and d <= GetV(V_ATTACKRANGE,MyID)) then -- 敵が攻撃範囲内なら
Attack (MyID,MyEnemy) -- 攻撃する
else -- 敵がいない場合
MyEnemy = 0; -- 敵をリセット
end
return
end
local object = GetOwnerEnemy (MyID) -- 主人の敵のIDを代入
if (object == 0) then -- 敵が居ない場合
object = GetMyEnemy (MyID) -- ホムの敵のIDを代入
if (object == 0) then -- 敵が居なければ
return
end
end
MyEnemy = object -- 敵IDをセット
end
-------------------------------------------------
-- 指定対象へのスキル使用コマンド(未実装)
-------------------------------------------------
-------------------------------------------------
function OnSKILL_OBJECT_CMD_ST ()
end
-------------------------------------------------
-- 指定座標へのスキル使用コマンド(未実装)
-------------------------------------------------
-------------------------------------------------
function OnSKILL_AREA_CMD_ST ()
TraceAI ("OnSKILL_AREA_CMD_ST")
local x , y = GetV (V_POSITION,MyID) -- ホムンクルスの位置を取得
if (GetDistance(x,y,MyDestX,MyDestY) <= GetV(V_SKILLATTACKRANGE,MyID,MySkill)) then -- スキル範囲内にホムの目的座標がある場合
SkillGround (MyID,MySkillLevel,MySkill,MyDestX,MyDestY) -- -- 設置型スキルを目的座標に使用
MyState = IDLE_ST
MySkill = 0
end
end
-------------------------------------------------
-- 主人追尾
-------------------------------------------------
-------------------------------------------------
function OnFOLLOW_CMD_ST ()
TraceAI ("OnFOLLOW_CMD_ST")
local ownerX, ownerY, myX, myY
ownerX, ownerY = GetV (V_POSITION,GetV(V_OWNER,MyID)) -- 主人の位置を代入
myX, myY = GetV (V_POSITION,MyID) -- 自分の位置を代入
local d = GetDistance (ownerX,ownerY,myX,myY) -- 主人とホムの位置を計算してdへ
if ( d <= 3) then -- 3セル以下の距離なら
return
end
local motion = GetV (V_MOTION,MyID)
if (motion == MOTION_MOVE) then -- ホムが移動中の場合
d = GetDistance (ownerX, ownerY, MyDestX, MyDestY)
if ( d > 3) then -- 4セル以上の距離なら
MoveTime2 = GetTick() -- 現在時刻を移動時の座標更新用タイマー1へ
if (MoveTime < MoveTime2 - Timer1) then -- MoveTimeに格納されてるm秒数を過ぎたら移動
Timer1 = GetTick() -- 移動した時点での時刻を格納しなおす
local x,y = GetV(V_POSITION,GetV(V_OWNER,MyID))
Move (MyID,x,y)
TraceAI ("FOLLOW_CMD_ST -> FOLLOW_CMD_ST")
MyDestX = ownerX -- ホムの目的地を主人の位置にする
MyDestY = ownerY -- 同上
end
return
end
else -- ホムが移動以外の動作の時
MoveToOwner (MyID) -- 主人のそばへ移動させる
MyDestX = ownerX -- ホムの目的地を主人の位置にする
MyDestY = ownerY -- 同上
return
end
-- やってることは同じのはずなのに、なんでOnFOLLOW_STと違う記述なんだ…?謎です
end
-------------------------------------------------
-- 主人の敵のIDを得る関数
-------------------------------------------------
-------------------------------------------------
function GetOwnerEnemy (myid)
local result = 0 -- 返す敵ID(敵がいない場合0)
local owner = GetV (V_OWNER,myid)
local actors = GetActors () -- 視野内のオブジェクト
local enemys = {}
local index = 1
local target
for i,v in ipairs(actors) do -- すべての視野内のオブジェクトに対して
-----------------------------主人が殴ってるモンスターも敵とみなす
if (v == owner) then -- オブジェクトが主人だった場合
target = GetV (V_TARGET,v) -- 主人のターゲットのIDを代入
if (IsMonster(target) == 1) then --それがモンスターだったら
enemys[index] = target -- そのターゲットを敵とみなす
index = index+1
end
end
----------------------------------------------------
if (v ~= owner and v ~= myid) then -- オブジェクトが主人とホム自身でない場合
target = GetV (V_TARGET,v) -- ターゲットIDを代入
if (target == owner) then -- 主人をタゲっていたら
if (IsMonster(v) == 1) then -- それがモンスターだったら
enemys[index] = v -- そのオブジェクトを敵とみなす
index = index+1
else -- モンスターで無い場合
local motion = GetV(V_MOTION,v) -- vの行動を取得
if (motion == MOTION_ATTACK or motion == MOTION_ATTACK2) then -- 攻撃行動を取っているなら
enemys[index] = v -- 敵とみなす
index = index+1
end
end
end
end
end
local min_dis = 100 -- ホムンクルスと敵との最小距離を保存しておく
local dis
for i,v in ipairs(enemys) do -- すべての敵に対して
dis = GetDistance2 (myid,v) -- ホムンクルスと敵との距離を代入
if (dis < min_dis) then -- 敵とホムンクルスの距離が今までの最小距離より小さい場合
result = v -- 敵として返すIDの候補に入れる
min_dis = dis -- 最小距離を更新
end
end
return result -- ホムから最も近い距離にいる召還者の敵IDを返す
end
-------------------------------------------------
-- ホム敵の敵のIDを得る関数(Aタイプ(非先行)とBタイプ(先行)に分かれている)
-------------------------------------------------
-------------------------------------------------
function GetMyEnemy (myid)
local result = 0
result = GetMyEnemyB (myid) -- Bタイプで敵IDを得る
return result
end
-------------------------------------------
-- 非先攻型 GetMyEnemy
-------------------------------------------
function GetMyEnemyA (myid)
local result = 0 -- 返す敵ID(敵がいない場合0)
local owner = GetV (V_OWNER,myid)
local actors = GetActors ()
local enemys = {}
local index = 1
local target
local type
local MyHP = GetV (V_HP,MyID)
local MyMaxHP = GetV (V_MAXHP,MyID)
local HPper = (MyHP / MyMaxHP) * 100
-------------------------------------------------
if (AwayHP >= HPper) then -- AwayHP以下だとアクティブに敵認識(逃亡用の敵認識)
for i,v in ipairs(actors) do -- すべての視野内のオブジェクトに対して
if (v ~= owner and v ~= myid ) then -- オブジェクトが主人のidでもホム自身のidでもない場合
if (1 == IsMonster(v) and IsNotNoManner( myid, v ) and IsAWAYENEMY(v)) then -- vがモンスターでタゲが無い、自分か主人をタゲってる、指定Mobでない
if (3 >= GetDistance2 (myid, v)) then -- 自分との距離が3の敵を認識(逃亡用)
enemys[index] = v -- 敵リストにvのidを追加
index = index+1
end
end
end
end
else
-- AwayHPより高い場合、ホムはノンアクティブ
for i,v in ipairs(actors) do
if (v ~= owner and v ~= myid) then -- オブジェクトが主人とホム自身でない場合
target = GetV (V_TARGET,v) -- オブジェクトのターゲット対象を抽出
if (target == myid) then -- ターゲットが自分だったら
enemys[index] = v -- 敵リストにvのidを追加
index = index+1
end
end
end
end
local min_dis = 100 -- ホムンクルスと敵との最小距離を保存しておく
local dis
for i,v in ipairs(enemys) do -- すべての敵に対して
dis = GetDistance2 (myid,v) -- ホムンクルスと敵との距離を代入
if (dis < min_dis) then -- 敵とホムンクルスの距離が今までの最小距離より小さい場合
result = v -- 敵として返すIDの候補に入れる
min_dis = dis -- 最小距離を更新
end
end
return result -- ホムから最も近い距離にいる召還者の敵IDを返す
end
-------------------------------------------
-- 先攻型 GetMyEnemy
-------------------------------------------
function GetMyEnemyB (myid)
local result = 0 -- 返す敵ID(敵がいない場合0)
local owner = GetV (V_OWNER,myid)
local actors = GetActors ()
local enemys = {}
local index = 1
local type
local MyHP = GetV (V_HP,MyID)
local MyMaxHP = GetV (V_MAXHP,MyID)
local HPper = (MyHP / MyMaxHP) * 100
---------------------------------------------------------
if (AwayHP >= HPper) then -- AwayHP以下だとアクティブに敵認識(逃亡用の敵認識)
for i,v in ipairs(actors) do -- すべての視野内のオブジェクトに対して
if (v ~= owner and v ~= myid ) then -- オブジェクトが主人のidでもホム自身のidでもない場合
if (1 == IsMonster(v) and IsNotNoManner( myid, v ) and IsAWAYENEMY(v)) then -- vがモンスターでタゲが無い、自分か主人をタゲってる、指定Mobでない
if (3 >= GetDistance2 (myid, v)) then -- 自分との距離が3の敵を認識(逃亡用)
enemys[index] = v -- 敵リストにvのidを追加
index = index+1
end
end
end
end
else -- AwayHPより高い場合、ホムはアクティブ
for i,v in ipairs(actors) do
if (v ~= owner and v ~= myid) then -- オブジェクトが主人のidでもホム自身のidでもない場合
if (1 == IsMonster(v) and IsNotNoManner( myid, v) and IsNoAttack(v)) then -- vがモンスターでタゲが無い、自分か主人をタゲってる、指定Mobでない
if (AttackArea >= GetDistance2 (GetV(V_OWNER,MyID), v)) then -- 主人との距離がAttackArea以下の場合
enemys[index] = v -- 敵リストにvのidを追加
index = index+1
end
end
end
end
end
local min_dis = 100 -- ホムンクルスと敵との最小距離を保存しておく
local dis
for i,v in ipairs(enemys) do -- すべての敵に対して
dis = GetDistance2 (myid,v) -- ホムンクルスと敵との距離を代入
if (dis < min_dis) then -- 敵とホムンクルスの距離が今までの最小距離より小さい場合
result = v -- 敵として返すIDの候補に入れる
min_dis = dis -- 最小距離を更新
end
end
return result -- ホムから最も近い距離にいる召還者の敵IDを返す
end
-------------------------------------------------
-- メイン関数
-------------------------------------------------
-------------------------------------------------
function AI(myid)
MyID = myid
local msg = GetMsg (myid) -- クライアントからのコマンドを得る
local rmsg = GetResMsg (myid) -- クライアントからの予約コマンドを得る
if msg[1] == NONE_CMD then -- コマンドが無い場合で
if rmsg[1] ~= NONE_CMD then -- さらに予約コマンドがある場合
if List.size(ResCmdList) < 10 then -- 予約コマンドのリストの数が10個以下なら
List.pushright (ResCmdList,rmsg) -- 予約コマンドのリストに追加
end
end
else -- コマンドがある場合は
List.clear (ResCmdList) -- 新しいコマンドが入力されたら、予約コマンドは削除する
ProcessCommand (msg) -- コマンド処理
end
-- 状態処理
if (MyState == IDLE_ST) then
OnIDLE_ST ()
elseif (MyState == CHASE_ST) then
OnCHASE_ST ()
elseif (MyState == ATTACK_ST) then
OnATTACK_ST ()
elseif (MyState == FOLLOW_ST) then
OnFOLLOW_ST ()
elseif (MyState == MOVE_CMD_ST) then
OnMOVE_CMD_ST ()
elseif (MyState == STOP_CMD_ST) then
OnSTOP_CMD_ST ()
elseif (MyState == ATTACK_OBJECT_CMD_ST) then
OnATTACK_OBJECT_CMD_ST ()
elseif (MyState == ATTACK_AREA_CMD_ST) then
OnATTACK_AREA_CMD_ST ()
elseif (MyState == PATROL_CMD_ST) then
OnPATROL_CMD_ST ()
elseif (MyState == HOLD_CMD_ST) then
OnHOLD_CMD_ST ()
elseif (MyState == SKILL_OBJECT_CMD_ST) then
OnSKILL_OBJECT_CMD_ST ()
elseif (MyState == SKILL_AREA_CMD_ST) then
OnSKILL_AREA_CMD_ST ()
elseif (MyState == FOLLOW_CMD_ST) then
OnFOLLOW_CMD_ST ()
elseif (MyState == RUNAWAY_ST) then
OnRUNAWAY_ST () -- 追加関数(逃亡処理)
elseif (MyState == AUTOSKILL_ST) then
OnAUTOSKILL_ST () -- 追加関数(オートスキル処理)
elseif (MyState == AMISTR_ST) then
OnAMISTR_ST () -- 追加関数(アミストル専用)
end
end
|