|
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
|
|