2006/3/17カスタムAIモルティシアVer(先行公開) | |
---|---|
※AI.luaにコピペで上書き貼り付けして使用してください※ ※使用は自己責任で※ ・Mobから逃げ回る処理に移る際、攻撃行動をキャンセルできなかった仕様を修正、 攻撃行動をキャンセルして逃げるようになりました ---------------------------------------- ・先行型の時の横殴り防止 ・主人とホムの近くに居るMobしか殴らない ・HPが40%未満になったら非先行型に切り替わり、Mobから逃げ回る ・移動の時遅れ気味なホムがまっすぐついてくるように調整 ・ホムが主人から離れすぎないよう調整 ・草など、反撃しないMobを主人と一緒に殴ってくれる といったカスタマイズがされています デフォルトで先行型になっているので、非先行型が好みの方は function GetMyEnemy (myid)内の GetMyEnemyB (myid) を GetMyEnemyA (myid)に変えて使用してください ---------------------------------------- require "./AI/Const.lua" require "./AI/Util.lua" 〜省略〜 ------------------------------------------ -- 追加分global variable ------------------------------------------ AwayHP = 40 -- 何%でホムが逃げるか ------------------------------------------ 〜省略〜 -------------------------------------------------- -- 基本処理 -------------- state process -------------------- -- 待機処理 function OnIDLE_ST () TraceAI ("OnIDLE_ST") local cmd = List.popleft(ResCmdList) if (cmd ~= nil) then ProcessCommand (cmd) -- 予約コマンド処理 return end 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 local distance = GetDistanceFromOwner(MyID) if ( distance > 2 or distance == -1) then -- MYOWNER_OUTSIGNT_IN MyState = FOLLOW_ST TraceAI ("IDLE_ST -> FOLLOW_ST") return; end end -- 主人のところへ戻る function OnFOLLOW_ST () TraceAI ("OnFOLLOW_ST") if (GetDistanceFromOwner(MyID) <= 2) then -- DESTINATION_ARRIVED_IN MyState = IDLE_ST TraceAI ("FOLLOW_ST -> IDLW_ST") return; elseif (GetV(V_MOTION,MyID) == MOTION_STAND or GetV(V_MOTION,MyID) == MOTION_MOVE) then local x,y = GetV(V_POSITION,GetV(V_OWNER,MyID)) Move (MyID,x,y) TraceAI ("FOLLOW_ST -> FOLLOW_ST") return; 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 -- ENEMY_OUTSIGHT_IN 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 -- ENEMY_INATTACKSIGHT_IN 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 -- DESTCHANGED_IN 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が視界から消えたら待機 MyState = IDLE_ST TraceAI ("ATTACK_ST -> IDLE_ST") return end if (MOTION_DEAD == GetV(V_MOTION,MyEnemy)) then -- Mobが死んだら待機 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) 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 -- DESTINATION_ARRIVED_IN MyState = IDLE_ST end end function OnSTOP_CMD_ST () 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) if (object == 0) then object = GetMyEnemy (MyID) end if (object ~= 0) then -- MYOWNER_ATTACKED_IN or ATTACKED_IN 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 -- DESTARRIVED_IN 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 = GetDistance(MyEnemy,MyID) -- ホムのターゲットの距離 if (d ~= -1 and d <= GetV(V_ATTACKRANGE,MyID)) then Attack (MyID,MyEnemy) else MyEnemy = 0; end return end local object = GetOwnerEnemy (MyID) if (object == 0) then object = GetMyEnemy (MyID) if (object == 0) then return end end MyEnemy = object 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 -- DESTARRIVED_IN SkillGround (MyID,MySkillLevel,MySkill,MyDestX,MyDestY) MyState = IDLE_ST MySkill = 0 end end -- 主人追尾ALT+T 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) 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 MyDestY = ownerY return end else -- 他の動作 MoveToOwner (MyID) MyDestX = ownerX MyDestY = ownerY return end end -- ホム逃亡処理 function OnRUNAWAY_ST () TraceAI ("OnRUNAWAY_ST") local MyHP = GetV (V_HP,MyID) local MyMaxHP = GetV (V_MAXHP,MyID) local HPper = (MyHP / MyMaxHP) * 100 if (AwayHP >= HPper) then -- AwayHP以下だと追跡(攻撃)しない local distance = GetDistanceFromOwner(MyID) if ( distance > 5 or distance == -1) then -- MYOWNER_OUTSIGNT_IN MyState = FOLLOW_ST TraceAI ("RUNAWAY -> FOLLOW_ST") return; end local AwayX,AwayY,OwnerX, OwnerY = 0 AwayX,AwayY = GetV (V_POSITION,MyEnemy); OwnerX, OwnerY = GetV (V_POSITION,GetV(V_OWNER,MyID)) MyX,MyY = GetV(V_POSITION,MyID) local distance = GetDistanceFromOwner(MyID) if (OwnerX > AwayX and OwnerY > AwayY) then -- 北東へ MyDestX = AwayX + 4 MyDestY = AwayY + 4 if (MyX > OwnerX + 4) then MyDestX = MyDestX - 2 if (MyY > OwnerY + 4) then MyDestY = MyDestY - 2 end end elseif (OwnerX > AwayX and OwnerY <= AwayY) then --南東へ MyDestX = AwayX + 4 MyDestY = AwayY - 4 if (MyX > OwnerX + 4) then MyDestX = MyDestX - 2 if (MyY < OwnerY - 4) then MyDestY = MyDestY + 2 end end elseif (OwnerX <= AwayX and OwnerY <= AwayY) then --南西へ MyDestX = AwayX - 4 MyDestY = AwayY - 4 if (MyX < OwnerX - 2) then MyDestX = MyDestX + 2 if (MyY < OwnerY - 4) then MyDestY = MyDestY + 2 end end elseif (OwnerX <= AwayX and OwnerY > AwayY) then --北西へ MyDestX = AwayX - 4 MyDestY = AwayY + 4 if (MyX < OwnerX - 4) then MyDestX = MyDestX + 2 if (MyY > OwnerY + 4) then MyDestY = MyDestY - 2 end end else MoveToOwner (MyID) TraceAI ("RUNAWAY -> RUNAWAY : END") return end Move (MyID,MyDestX,MyDestY) return else MyState = IDLE_ST TraceAI ("RUNAWAY -> IDLE_ST") return end end -- function GetOwnerEnemy (myid) local result = 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) 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) 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 min_dis = dis end end return result end function GetMyEnemy (myid) local result = 0 local MyHP = GetV (V_HP,MyID) local MyMaxHP = GetV (V_MAXHP,MyID) local HPper = (MyHP / MyMaxHP) * 100 if (AwayHP <= HPper) then -- HPが50%以下になったら非アクティブ化 result = GetMyEnemyB (myid) else result = GetMyEnemyA (myid) end return result end ------------------------------------------- -- 非先攻型 GetMyEnemy ------------------------------------------- function GetMyEnemyA (myid) local result = 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 -- AwayHP以下だとアクティブに敵認識 if (AwayHP >= HPper) then for i,v in ipairs(actors) do -- iとvへ、テーブルactorsの値が順番に初期値として入り、iがnilになったらループ脱出 if (v ~= owner and v ~= myid ) then -- vの値が主人のidでもホム自身のidでもない場合 if (1 == IsMonster(v) and IsNotNoManner( myid, v )) then -- vがモンスターでIsNotNoManner( myid, v )に値が入っている場合 if (3 >= GetDistance2 (myid, v)) then -- 自分との距離が3の敵 enemys[index] = v -- 敵リストにvのidを追加 index = index+1 end end end end else for i,v in ipairs(actors) do -- iとvへ、テーブルactorsの値が順番に初期値として入り、iがnilになったらループ脱出 if (v ~= owner and v ~= myid) then -- vの値が主人のidでもホム自身のidでもない場合 target = GetV (V_TARGET,v) -- 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 -- iとvへ、テーブルenemysの値が順番に初期値として入り、iがnilになったらループ脱出 dis = GetDistance2 (myid,v) -- 自分をタゲってる敵(v)との距離をdisに代入 if (dis < min_dis) then -- 距離が100未満だったら result = v -- resultへvを代入 min_dis = dis end end return result -- resultを返す end ------------------------------------------- -- 先攻型 GetMyEnemy ------------------------------------------- -- -- 横殴り防止 function IsNotNoManner( myid, id ) -- 攻撃行動中止 local target = GetV( V_TARGET, id ) -- idのターゲット相手を抽出 return target == 0 or ( target == myid or target == GetV( V_OWNER, myid ) ) -- タゲが居ない、またはタゲの対象がホム、持ち主(ケミだった場合)、値を返す end -- -- function GetMyEnemyB (myid) local result = 0 local owner = GetV (V_OWNER,myid) local actors = GetActors () local enemys = {} local index = 1 local type for i,v in ipairs(actors) do -- iとvへ、テーブルactorsの値が順番に初期値として入り、iがnilになったらループ脱出 if (v ~= owner and v ~= myid) then -- vの値が主人のidでもホム自身のidでもない場合 if (1 == IsMonster(v) and IsNotNoManner( myid, v ) ) then -- vがモンスターでIsNotNoManner( myid, v )に値が入っている場合 if (6 >= GetDistance2 (GetV(V_OWNER,MyID), v)) then -- 主人との距離が6以下の場合 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 -- iとvへ、テーブルenemysの値が順番に初期値として入り、iがnilになったらループ脱出 dis = GetDistance2 (myid,v) -- 自分をタゲってる敵(v)との距離をdisに代入 if (dis < min_dis) then -- 距離が100未満だったら result = v -- resultへvを代入 min_dis = dis end end return result end function AI(myid) MyID = myid local msg = GetMsg (myid) -- command local rmsg = GetResMsg (myid) -- reserved command if msg[1] == NONE_CMD then if rmsg[1] ~= NONE_CMD then if List.size(ResCmdList) < 10 then 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 () end end |