2006/3/28カスタムAIVer3:フィーリル専用 | |
---|---|
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を語るスレ2 -- http://enif.mmobbs.com/test/read.cgi/livero/1140506800/l50 -- ホムンクルスのAIを語るスレ その3 -- http://enif.mmobbs.com/test/read.cgi/livero/1142535070/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 -- 追加関数(オートスキル処理) FILIR_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 -- 何%でホムが逃げるか SkillIdle = 1 -- ALT+Tの時、攻撃スキル使用後その場に待機する自走砲台モード(yes=1 no=0)(フィーリルとバニルミストのみ) ActionSwitch = 1 -- テレポ、マップ移動後即座にホムが敵を攻撃しにいかない(yes=1 no=0)(先行時のみ) -- オートスキル設定 AutoSkill = 20 -- ホムの自動スキルの最高確率(%)(SPが減ると確率減少、フィーリルとバニルミストのみ) AutoSkill_SP = 40 -- ホムのSPがこの%を下回った場合には自動スキル発動なし FastAttack = 0 -- 戦闘時、初撃にスキルを使うかどうか(yes=1 no=0)(フィーリルとバニルミストのみ) -- フィーリルのオートスキル設定 MoonlightLv = 5 -- ムーンライトの使用Lv FleetMoveLv = 5 -- フリートムーブの使用Lv FleetSwitch = 1 -- フリットムーブを自動で使用するかどうか(yes=1 no=0) -- その他 Timer1 = GetTick() -- タイマー1、現在時刻格納 MoveTime = 500 -- 移動時の座標更新間隔 MoveTime2 = 0 -- 移動時の座標更新用タイマー1 FleetMoveDelay = 0 -- フリートムーブ用タイマー、いじってはダメ(フィーリルのみ) NoAttackSwitch = 0 -- 設定Mobを殴らないスイッチ、いじってはダメ※先行時のみ効果有り※ AwayEnwmySwitch = 0 -- 逃亡時設定Mobからは逃げないスイッチ、いじってはダメ FastAttackSwitch = 0 -- 初撃にスキルを使うかどうか内部処理用スイッチ、いじってはダメ SkillIdleSwitch = 0 -- ALT+Tの時、スキル使用後そのまま待機するためのスイッチ、いじってはダメ ------------------------------------------ ---------------------------------------------------- -- 手動(予約)処理 ------------- 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 ------------------------固定砲台モード-------------- if(SkillIdleSwitch == 1 and SkillIdle == 1) then -- 固定砲台スイッチがON(ALT+T状態)で固定砲台モードONの場合 SkillObject (MyID,MySkillLevel,MySkill,MyEnemy) -- スキル使用後初期値、ALT+Tの追尾状態に戻る MySkillLevel = 0 MySkill = 0 MyEnemy = 0 MyState = FOLLOW_CMD_ST else -- それ以外だとこっち MyState = CHASE_ST -- デフォルトAIと同じようにスキル対象を敵とみなして殴りに行く end ---------------------------------------------------- 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) -- ホム所持者(ケミ)の元まで移動 -----------------------固定砲台モード--------------- SkillIdleSwitch = 1 -- 固定砲台スイッチON(ALT+Tでの切り替え用) ---------------------------------------------------- MyState = FOLLOW_CMD_ST -- 追尾状態に MyDestX, MyDestY = GetV (V_POSITION,GetV(V_OWNER,MyID)) -- 所持者の座標を目標に指定 MyEnemy = 0 MySkill = 0 TraceAI ("OnFOLLOW_CMD") else -----------------------固定砲台モード--------------- SkillIdleSwitch = 0 -- 固定砲台スイッチOFF(ALT+Tでの切り替え用) ---------------------------------------------------- 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 ---------------------------------------------------- if (GetV(V_MOTION, GetV(V_OWNER,MyID)) == MOTION_MOVE) then -- 主人が移動状態だったら ActionSwitch = 0 -- テレポ、マップ移動後、主人が動き出したらスイッチOFF end ---------------------------------------------------- if (ActionSwitch == 0) then -- スイッチOFFだったら行動開始 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 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 = FILIR_ST -- オートスキル処理2、支援スキルの自動かけなおし ---------------------------------------------------- TraceAI ("OnIDLE_ST -> FILIR_ST : NoATTACK") 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 ----------------------------初撃スキル-------------- FastAttackSwitch = 0 -- 初撃にスキル使用した目印のリセット ---------------------------------------------------- MyState = IDLE_ST TraceAI ("ATTACK_ST -> IDLE_ST") return end if (MOTION_DEAD == GetV(V_MOTION,MyEnemy)) then -- Mobが死んだら待機 MyEnemy = 0 MySkill = 0 -----------------------------初撃スキル--------------- FastAttackSwitch = 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 -- 使用スキルが指定されていなければ MyState = AUTOSKILL_ST -- オートスキル使用 TraceAI ("ATTACK_ST -> AUTOSKILL_ST") Attack (MyID,MyEnemy) else -- スキルが指定されていたらスキル使用 SkillObject (MyID,MySkillLevel,MySkill,MyEnemy) MySkill = 0 end ---------------------------------------------------- TraceAI ("ATTACK_ST -> ATTACK_ST : ENERGY_RECHARGED_IN") 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 = IDLE_ST -- 待機状態へ end end ------------------------------------------------- -- ホムをその場で停止させる(現在未実装) -- 将来これに手を加えて機能追加させたいなぁ… -- ケミ待機時に限り、ホムを手動で移動させても戻ってこない(移動先で待機)ような機能を考え中 -- なかなかコードがまとまらないので当分未実装 ------------------------------------------------- ------------------------------------------------- function 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 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 == FILIR_ST) then OnFILIR_ST () -- 追加関数(フィーリル専用) end end |