--[[--------------------------------------------- シンプルAIシリーズ Sage Owl Ver0.9 初回限定 (http://pretty.pc3merchanet.net/) Alt+右クリックで対象の隣へ移動させると、対象を追尾するようになります。 対象のID Motion Target 等をshowstate_HTAアプリへ出力します。 ------------------------------------------------- based 標準AI 説明付版 by くま○〜 ※タブ幅4に最適化してあります。 ------------------------------------------------- --]] -- const.lua ------------------------------------------------- -- ROクライアントの内部関数一覧 ------------------------------------------------- --[[ function TraceAI (string) end -- [string]をTraceAIに出力する。 -- 「/traceai」コマンドでTraceAI.txtに出力可能になる。 function MoveToOwner (id) end -- [id]のホムをケミの近くに移動させる function Move (id,x,y) end -- [id]のホムを座標([x],[y])に移動させる function Attack (id,id) end -- [id1]のホムに[id2]の敵を攻撃させる function GetV (V_,id) end -- [id]の[V_]に応じた情報を得る function GetActors () end -- 視界内のオブジェクト(キャラ,NPC,モンスタ,スキル)のidをtable形式で得る function GetTick () end -- コンピューター起動時からの時間を得る(1/1000秒単位) function GetMsg (id) end -- [id]のホムへのROクライアントからの命令をtable形式で得る function GetResMsg (id) end -- [id]のホムへのROクライアントからの予約命令をtable形式で得る function SkillObject (id,level,skill,target) end -- [id]のホムに[skill]のスキルを[level]レベルで -- [target]のオブジェクトに使用させる function SkillGround (id,level,skill,x,y) end -- [id]のホムに[skill]のスキルを[level]レベルで -- 座標([x],[y])に使用させる function IsMonster (id) end -- [id]のオブジェクトがモンスターなら[1]、そうでなければ [0]を得る --]] ------------------------------------------------- -- GetV関数の第一引数と戻り値の説明 ------------------------------------------------- ------------------------------------------------- V_OWNER = 0 -- 召喚者のID V_POSITION = 1 -- 座標 (x、y) V_TYPE = 2 -- (未実装) タイプ V_MOTION = 3 -- 現在の命令 V_ATTACKRANGE = 4 -- (未実装) 物理攻撃範囲 (現在は1セルに固定) V_TARGET = 5 -- 攻撃、スキル使用対象の ID V_SKILLATTACKRANGE = 6 -- (未実装) スキル攻撃範囲 V_HOMUNTYPE = 7 -- ホムの種類 V_HP = 8 -- HP (ホムとケミ) V_SP = 9 -- SP (ホムとケミ) V_MAXHP = 10 -- 最大 HP (ホムとケミ) V_MAXSP = 11 -- 最大 SP (ホムとケミ) ------------------------------------------------- ------------------------------------------------- -- GetV(V_HOMUNTYPE, id)の戻り値(オブジェクトの種類) ------------------------------------------------- ------------------------------------------------- LIF = 1 -- リーフ AMISTR = 2 -- アミストル FILIR = 3 -- フィーリル VANILMIRTH = 4 -- バニルミルト LIF2 = 5 -- (未実装) AMISTR2 = 6 -- (未実装) FILIR2 = 7 -- (未実装) VANILMIRTH2 = 8 -- (未実装) LIF_H = 9 -- (未実装)リーフ進化形? AMISTR_H = 10 -- (未実装)アミストル進化形? FILIR_H = 11 -- (未実装)フィーリル進化形? VANILMIRTH_H = 12 -- (未実装)バニルミルト進化形? LIF_H2 = 13 -- (未実装) AMISTR_H2 = 14 -- (未実装) FILIR_H2 = 15 -- (未実装) VANILMIRTH_H2 = 16 -- (未実装) ------------------------------------------------- ------------------------------------------------- -- GetV(V_MOTION, id)の戻り値(オブジェクトの行動状態) ------------------------------------------------- ------------------------------------------------- MOTION_STAND = 0 -- 立っている MOTION_MOVE = 1 -- 移動中 MOTION_ATTACK = 2 -- 攻撃中 MOTION_DEAD = 3 -- 死亡 MOTION_SIT = 6 -- 座っている MOTION_ATTACK2 = 9 -- 攻撃する(予約?) ------------------------------------------------- ------------------------------------------------- -- GetMsg(id),GetResMsg(id)によって得られる命令番号 ------------------------------------------------- ------------------------------------------------- NONE_CMD = 0 -- 命令無し MOVE_CMD = 1 -- 移動 STOP_CMD = 2 -- 停止 ATTACK_OBJECT_CMD = 3 -- 攻撃 ATTACK_AREA_CMD = 4 -- 設置型攻撃 PATROL_CMD = 5 -- パトロール HOLD_CMD = 6 -- 待機 SKILL_OBJECT_CMD = 7 -- スキル使用 SKILL_AREA_CMD = 8 -- 設置型スキル使用 FOLLOW_CMD = 9 -- 状態切替 ------------------------------------------------- ------------------------------------------------- -- SkillObject(),SkillGround()のスキルID ------------------------------------------------- ------------------------------------------------- -- リーフ SKILL_TOUCH_OF_HEAL = 8001 --   癒しの手 SKILL_EMERGENCY_AVOID = 8002 --   緊急回避 -- アミストル SKILL_CASTLING = 8005 --   キャスリング SKILL_DEFFENCE = 8006 --   ディフェンス -- フィーリル SKILL_MOONLIGHT = 8009 --   ムーンライト SKILL_FLEET_MOVE = 8010 --   フリットムーブ SKILL_OVERED_SPEED = 8011 --   オーバードスピード -- バニルミルト SKILL_CAPRICE = 8013 --   カプリス SKILL_CHAOTIC_VENEDICTION = 8014 --   カオティックベネットディクション ------------------------------------------------- -- util.lua ------------------------------------------------- -- リスト構造の操作クラスの定義(List utility) ------------------------------------------------- ------------------------------------------------- List = {} function List.new () --新しいリストを返す return { first = 0, last = -1} end function List.pushleft (list, value) --listの左側に要素追加 local first = list.first-1 list.first = first list[first] = value; end function List.pushright (list, value) --listの右側に要素追加 local last = list.last + 1 list.last = last list[last] = value end function List.popleft (list) --listの一番左側の値を取り出す local first = list.first if first > list.last then return nil end local value = list[first] list[first] = nil -- to allow garbage collection list.first = first+1 return value end function List.popright (list) --listの一番右側の値を取り出す local last = list.last if list.first > last then return nil end local value = list[last] list[last] = nil list.last = last-1 return value end function List.clear (list) --listを空にする for i,v in ipairs(list) do list[i] = nil end --[[ if List.size(list) == 0 then return end local first = list.first local last = list.last for i=first, last do list[i] = nil end --]] list.first = 0 list.last = -1 end function List.size (list) --listに入っている要素の個数を返す local size = list.last - list.first + 1 return size end ------------------------------------------------- ------------------------------------------------- -- 座標([x1],[y1])と座標([x2],[y2])の距離を返す ------------------------------------------------- ------------------------------------------------- function GetDistance (x1,y1,x2,y2) return math.floor(math.sqrt((x1-x2)^2+(y1-y2)^2)) end ------------------------------------------------- ------------------------------------------------- -- [id1]と[id2]のオブジェクトの距離を返す ------------------------------------------------- ------------------------------------------------- function GetDistance2 (id1, id2) local x1, y1 = GetV (V_POSITION,id1) local x2, y2 = GetV (V_POSITION,id2) if (x1 == -1 or x2 == -1) then return -1 end return GetDistance (x1,y1,x2,y2) end ------------------------------------------------- ------------------------------------------------- -- [id]のホムのケミの座標を返す ------------------------------------------------- ------------------------------------------------- function GetOwnerPosition (id) return GetV (V_POSITION,GetV(V_OWNER,id)) end ------------------------------------------------- ------------------------------------------------- -- [id]のホムとそのケミの距離を返す ------------------------------------------------- ------------------------------------------------- function GetDistanceFromOwner (id) local x1, y1 = GetOwnerPosition (id) local x2, y2 = GetV (V_POSITION,id) if (x1 == -1 or x2 == -1) then return -1 end return GetDistance (x1,y1,x2,y2) end ------------------------------------------------- ------------------------------------------------- -- [id1]と[id2]のオブジェクト同士が -- 見える距離ならtrue、見えない距離ならfalseを返す ------------------------------------------------- ------------------------------------------------- function IsOutOfSight (id1,id2) local x1,y1 = GetV (V_POSITION,id1) local x2,y2 = GetV (V_POSITION,id2) if (x1 == -1 or x2 == -1) then return true end local d = GetDistance (x1,y1,x2,y2) if d > 20 then return true else return false end end ------------------------------------------------- ------------------------------------------------- -- [id1]の攻撃使用範囲に[id2]がいればtrue、 -- そうでなければfalseを返す。 ------------------------------------------------- ------------------------------------------------- function IsInAttackSight (id1,id2) local x1,y1 = GetV (V_POSITION,id1) local x2,y2 = GetV (V_POSITION,id2) if (x1 == -1 or x2 == -1) then return false end local d = GetDistance (x1,y1,x2,y2) local a = 0 if (MySkill == 0) then a = GetV (V_ATTACKRANGE,id1) else a = GetV (V_SKILLATTACKRANGE,id1,MySkill) end if a >= d then return true; else return false; end end ------------------------------------------------- -- ホムの状態 ------------------------------------------------- ------------------------------------------------- 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 -- 状態切替命令 ------------------------------------------------- ------------------------------------------------- -- ホムの属性を保存するグローバル変数 ------------------------------------------------- ------------------------------------------------- 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 -- ホムの使用スキルレベル ------------------------------------------------- MyBoss = GetV(V_OWNER,MyID) MyOwner = GetV(V_OWNER,MyID) ---------- ●以下、命令処理関数● ----------- ------------------------------------------------- function OnMOVE_CMD (x,y) ------------------------------------------------- -- 移動命令 (地面をALT+右クリック) ------------------------------------------------- --TraceAI ("OnMOVE_CMD") local t local actors = GetActors () MyBoss = MyOwner --移動命令があったときは、対象をリセット。 TraceAI ("Target Reset") for i,v in ipairs(actors) do if ( v~=MyID and v~=MyOwner) then -- 自身とオーナーは除外する。 chkX,chkY = GetV (V_POSITION,v) if (GetDistance(chkX,chkY, x,y)<=1) then -- 移動先と距離1以上のものを除外する。 t = GetV(V_HOMUNTYPE,v) TraceAI(string.format("NewTarget ID:%d type:%s",v,t)) MyBoss = v -- 新たなマスターを設定し、ループを抜ける。 break end end end 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 -- 目的地が一定距離以上なら -- (サーバーで遠距離は処理しないため) List.pushleft (ResCmdList,{MOVE_CMD,x,y}) -- 目的位置まで移動を予約した上で、 x = math.floor((x+curX)/2) -- ひとまず中間位置までを目的位置に変更する-x y = math.floor((y+curY)/2) -- ひとまず中間位置までを目的位置に変更する-y end Move (MyID,x,y) -- 目的地へ移動する MyState = MOVE_CMD_ST -- ホムを移動命令状態に変更 MyDestX = x -- 目的位置の x座標を設定 MyDestY = y -- 目的位置の y座標を設定 MyEnemy = 0 -- ホムの敵設定をクリア MySkill = 0 -- ホムの使用スキルをクリア end ------------------------------------------------- ------------------------------------------------- function OnATTACK_OBJECT_CMD (id) ------------------------------------------------- -- 攻撃命令 (対象を ALT+右クリ2回目) ------------------------------------------------- --TraceAI ("OnATTACK_OBJECT_CMD") MyState = CHASE_ST -- ホムをターゲット追跡状態に変更 MyEnemy = id -- ホムの敵を設定 MySkill = 0 -- ホムの使用スキルをクリア end ------------------------------------------------- ------------------------------------------------- function OnSKILL_OBJECT_CMD (level,skill,id) ------------------------------------------------- -- スキル使用命令 (ホムの対象指定スキル使用) ------------------------------------------------- --TraceAI ("OnSKILL_OBJECT_CMD") SkillObject (MyID,level,skill,id) -- 敵に指定されたスキルを指定されたレベルで使用する end ------------------------------------------------- ------------------------------------------------- function OnFOLLOW_CMD () ------------------------------------------------- -- 状態切替命令 (ALT+T) -- 索敵状態(先攻型or非先攻型)と非索敵状態(無抵抗状態)を切り替える ------------------------------------------------- end ------------------------------------------------- ------------------------------------------------- function ProcessCommand (msg) ------------------------------------------------- -- クライアントからの命令を解釈し、 -- 対応する関数へ渡す関数 -- 予約命令の場合も呼ばれる。 ------------------------------------------------- if (msg[1] == MOVE_CMD) then OnMOVE_CMD (msg[2],msg[3]) -- 移動命令 --TraceAI ("MOVE_CMD") elseif (msg[1] == ATTACK_OBJECT_CMD) then OnATTACK_OBJECT_CMD (msg[2]) -- 攻撃命令 --TraceAI ("ATTACK_OBJECT_CMD") elseif (msg[1] == SKILL_OBJECT_CMD) then OnSKILL_OBJECT_CMD (msg[2],msg[3],msg[4],msg[5]) -- スキル使用命令 --TraceAI ("SKILL_OBJECT_CMD") elseif (msg[1] == FOLLOW_CMD) then OnFOLLOW_CMD () -- 状態切替命令 --TraceAI ("FOLLOW_CMD") end end ------------------------------------------------- ------- ●以下、ホムンクルスの状態関数● -------- ------------------------------------------------- function OnIDLE_ST () ------------------------------------------------- -- 待機状態 ------------------------------------------------- --TraceAI ("OnIDLE_ST") local cmd = List.popleft(ResCmdList) -- 予約命令を得る if (cmd ~= nil) then -- 予約命令が存在したら ProcessCommand (cmd) -- 予約命令を処理して return -- 抜ける end local distance = GetDistance2 (MyID,MyBoss) -- ホムとケミの距離を得る if ( distance > 2 or distance == -1) then -- ホムとケミの距離が3以上か、視野外の場合は MyState = FOLLOW_ST -- ホムをケミ追従状態にして --TraceAI ("IDLE_ST -> FOLLOW_ST") return; -- 抜ける end end ------------------------------------------------- ------------------------------------------------- function OnFOLLOW_ST () ------------------------------------------------- -- ケミ追従状態 ------------------------------------------------- --TraceAI ("OnFOLLOW_ST") if (GetDistance2 (MyID,MyBoss) <= 2) then -- ケミとホムの距離が3以下の場合 MyState = IDLE_ST -- ホムを待機状態にする --TraceAI ("FOLLOW_ST -> IDLW_ST") return; -- 抜ける elseif (GetV(V_MOTION,MyID) == MOTION_STAND) then -- ホムのモーションが立っている状態の場合 MoveToBoss (MyID) -- ホムをケミの近くに移動させる --TraceAI ("FOLLOW_ST -> FOLLOW_ST") return; -- 抜ける end end ------------------------------------------------- ------------------------------------------------- function OnCHASE_ST () ------------------------------------------------- -- ターゲット追跡状態 ------------------------------------------------- --TraceAI ("OnCHASE_ST") if (true == IsOutOfSight(MyID,MyEnemy)) then -- 敵がホムの視野外にいる場合 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 -- 敵がホムの視野外にいる場合 MyState = IDLE_ST -- ホムを待機状態にする --TraceAI ("ATTACK_ST -> IDLE_ST") return -- 抜ける end if (MOTION_DEAD == GetV(V_MOTION,MyEnemy)) then -- 敵のモーションが死亡状態の場合 MyState = IDLE_ST -- ホムを待機状態にする --TraceAI ("ATTACK_ST -> IDLE_ST") return -- 抜ける end if (false == IsInAttackSight(MyID,MyEnemy)) then -- 敵がホムの攻撃範囲外にいる場合 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) -- ホムは敵を物理攻撃する else -- 使用スキルの指定があれば SkillObject (MyID,MySkillLevel,MySkill,MyEnemy) -- 敵に指定されたスキルを指定されたレベルで使用する MySkill = 0 -- 使用スキルの指定をクリアする end --TraceAI ("ATTACK_ST -> ATTACK_ST : ENERGY_RECHARGED_IN") 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 OnFOLLOW_CMD_ST () ------------------------------------------------- -- 非索敵状態 ------------------------------------------------- --TraceAI ("OnFOLLOW_CMD_ST") local ownerX, ownerY, myX, myY ownerX, ownerY = GetV (V_POSITION, MyBos) -- ケミの位置を取得する myX, myY = GetV (V_POSITION,MyID) -- ホムの位置を取得する local d = GetDistance (ownerX,ownerY,myX,myY) -- ケミとホムの距離を計算する 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セル以上の場合 MoveToOwner (MyID) -- ホムをケミの近くに移動させて MyDestX = ownerX -- ホムの目的位置をケミの位置に変更 x MyDestY = ownerY -- ホムの目的位置をケミの位置に変更 y return -- 抜ける end else -- ホムが移動中以外の場合 MoveToOwner (MyID) -- ホムをケミの近くに移動させて MyDestX = ownerX -- ホムの目的位置をケミの位置に変更 x MyDestY = ownerY -- ホムの目的位置をケミの位置に変更 y return -- 抜ける end end ------------------------------------------------- -- ●サブ関数● 戦闘系--------------- ------------------------------------------------- -- ケミの敵のIDを得る関数 ------------------------------------------------- ------------------------------------------------- function GetOwnerEnemy (myid) local result = 0 -- 結果として返す敵ID(いない場合0) local owner = GetV (V_OWNER,myid) -- ホムのケミのID local actors = GetActors () -- 視野内のオブジェクト local enemys = {} local index = 1 local target for i,v in ipairs(actors) do -- すべての視野内のオブジェクトに対して if (v ~= owner and v ~= myid) then -- オブジェクトがケミとホム自身じゃない場合 target = GetV (V_TARGET,v) -- オブジェクトの攻撃、スキル使用の対象を取得し、 if (target == owner) then -- オブジェクトの攻撃、スキル使用の対象がケミで if (IsMonster(v) == 1) then -- オブジェクトがモンスターであるならば、 enemys[index] = v -- 敵の配列にオブジェクトを追加し index = index+1 -- 敵の配列をインクリメント else -- オブジェクトの攻撃、スキル使用の対象がケミであっても -- オブジェクトがモンスターでないならば、(人ならば) local motion = GetV(V_MOTION,v) -- オブジェクトのモーションを取得し、 -- (■GetV関数の第2引数を i から 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を返す -- 敵がいない場合は 0を返す end ------------------------------------------------- ------------------------------------------------- -- ホムの敵のIDを得る関数 -- (■条件文をホムごとに分けました) ------------------------------------------------- ------------------------------------------------- function GetMyEnemy (myid) local result = 0 -- 敵のID。いない場合として初期値0 local type = GetV (V_HOMUNTYPE,myid) -- ホムのIDを得る if (type == LIF or type == LIF_H or type == LIF2 or type == LIF_H2 ) then result = GetMyEnemyA (myid) -- リーフは 非先行型の敵探索で敵IDを得る elseif (type == AMISTR or type == AMISTR_H or type == AMISTR2 or type == AMISTR_H2) then result = GetMyEnemyA (myid) -- アミストルは 非先行型の敵探索で敵IDを得る elseif (type == FILIR or type == FILIR_H or type == FILIR2 or type == FILIR_H2 ) then result = GetMyEnemyA (myid) -- フィーリルは 先行型の敵探索で敵IDを得る elseif (type == VANILMIRTH or type == VANILMIRTH_H or type == VANILMIRTH2 or type == VANILMIRTH_H2) then result = GetMyEnemyA (myid) -- バニルミルトは 先行型の敵探索で敵IDを得る end return result -- 敵IDを返す。いない場合は0を返す end ------------------------------------------------- ------------------------------------------------- -- ホムの敵のIDを得る関数 (非先攻型) ------------------------------------------------- ------------------------------------------------- function GetMyEnemyA (myid) local result = 0 -- 結果として返す敵ID(いない場合0) local owner = GetV (V_OWNER,myid) -- ホムの召還者のID local actors = GetActors () -- 視野内のオブジェクト local enemys = {} local index = 1 local target 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 -- 敵の配列にオブジェクトを追加し index = index+1 -- 敵の配列をインクリメント 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を返す -- 敵がいない場合は 0を返す end ------------------------------------------------- ------------------------------------------------- -- ホムの敵のIDを得る関数(先攻型) ------------------------------------------------- ------------------------------------------------- function GetMyEnemyB (myid) local result = 0 -- 結果として返す敵ID(いない場合0) local owner = GetV (V_OWNER,myid) -- ホムのケミのID local actors = GetActors () -- 視野内のオブジェクト local enemys = {} local index = 1 local type for i,v in ipairs(actors) do -- すべての視野内のオブジェクトに対して if (v ~= owner and v ~= myid) then -- オブジェクトがケミとホム自身じゃない場合 if (1 == IsMonster(v)) then -- オブジェクトがモンスターであるならば、 enemys[index] = v -- 敵の配列にオブジェクトを追加し index = index+1 -- 敵の配列をインクリメント 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を返す -- 敵がいない場合は 0を返す end ------------------------------------------------- -- ●サブ関数 移動系とか● --------------- function MoveToBoss (myid) ------------------------------------------ -- ボスの近くに移動(最寄の位置) ------------------------------------------ local x,y = GetV(V_POSITION,MyBoss) -- マスターの現在地を得る Move2(MyID,x,y) -- マスターのそばへ移動。 end function Move2(id,x1,y1) ------------------------------------------------- --指定座標から1マスずれた場所へ移動するMove -- ※問題点:移動先が移動不可セルの場合、移動できずに元の位置で止まります。 ------------------------------------------------- local MyX , MyY = GetV (V_POSITION, id) --ホムの現在座標を取得。 local x2,y2 = x1,y1 if (x1 < MyX) then -- x座標の1マスずれた場所を計算。 x2 = x2 + 1 elseif (x1 > MyX) then x2 = x2 - 1 end if (y1 < MyY) then -- y座標の1マスずれた場所を計算。 y2 = y2 + 1 elseif (x1 > MyX) then y2 = y2 - 1 end Move(id,x2,y2) end -- ●サブ関数 その他● --------------- local stateCount = 0 -- 状態出力 local USE_BUFF = true; local showstate_buff={} local buffsize = 0; function CreateStatus( state , mode ,writemode) -- ステータス表示実体。 -- 指定された文字列のステータスをユーザーに見せる。 if state~=nil then -- ステータスが mode = mode or 0 -- mode が指定されて無いときは0を代入。 buffsize = buffsize +1 ; showstate_buff[buffsize]={mode,state} TraceAI("set buf[".. mode .."]="..state ,5) if not USE_BUFF then -- バッファモードでないときはそのまま書き込み TraceAI("not USE_BUFF",5) writemode = true end end if writemode and buffsize > 0 then -- 書き込みバッファがある場合で書き込みモードならばファイル作成 local name = "./AI/temp/ShowState/"..string.format("%010d", stateCount + 1 ) local fp = io.open( name, "w") if not fp then return end for k, v in pairs(showstate_buff) do fp:write(string.format( "%s=%s\n",v[1],v[2])) end fp:close() stateCount = stateCount + 1 showstate_buff = {} buffsize = 0; end end ------------------------------------------------- -- id の情報を表示する ------------------------------------------------- b_motion = -1 b_homtype =-1 b_target = -1 b_isMob = -1 b_id = -1 function TraceMotion(id) ------------------------------------------------- -- id のモーションを記録する。 ------------------------------------------------- homuntype = GetV(V_HOMUNTYPE,id) motion = GetV(V_MOTION,id) target = GetV(V_TARGET,id) isMob = IsMonster (id) if b_id ~= id then CreateStatus(string.format("ID:%s Type:%s", id, homuntype),0) b_id = id b_homtype= homuntype end if motion ~= b_motion or target ~= b_target or isMob ~= b_isMob then CreateStatus(string.format("Motion:%s Target:%s IsMonster:%s", motion ,target, isMob),20000) b_motion=motion b_target=target b_isMob=isMob end 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 () -- 待機状態の処理 end if (MyState == CHASE_ST) then OnCHASE_ST () -- ケミ追従状態の処理 end if (MyState == ATTACK_ST) then OnATTACK_ST () -- ターゲット追跡状態の処理 end if (MyState == FOLLOW_ST) then OnFOLLOW_ST () -- ターゲット攻撃状態の処理 end if (MyState == MOVE_CMD_ST) then OnMOVE_CMD_ST () -- 移動命令状態の処理 end if (MyState == ATTACK_OBJECT_CMD_ST) then OnATTACK_OBJECT_CMD_ST () -- 攻撃命令状態の処理 end if (MyState == SKILL_OBJECT_CMD_ST) then OnSKILL_OBJECT_CMD_ST () -- スキル使用命令状態の処理 end if (MyState == FOLLOW_CMD_ST) then OnFOLLOW_CMD_ST () -- 非索敵状態の処理 end TraceMotion (MyBoss) -- Bossの行動をチェック CreateStatus(nil,nil,true) -- 出力バッファの内容を書き出す。 end CreateStatus( "" , -3 ) -- メッセージビュアーの掃除 CreateStatus( "" , 0 ) -------------------------------------------------