Гайд по написанию скриптов для гомункулусов
-
ой, сорри забыла написать Mir Ai v1.2.2
-
Florencia, сменить аи, ну или для мобов поставить в тактиках WITH_FULL_POWER или как-то так.
-
Florencia, сменить аи, ну или для мобов поставить в тактиках WITH_FULL_POWER или как-то так.
-
Florencia, чтобы ванилька сначала бросала болт в нового врага нужно в файле AI.lua исправить вот этоти куски
[code:k2jhniqc]
function OnIDLE_ST()...
-- Is there a new target? -> chase_st
if CurrTime - StartupTime > 600 then
local NextTarget = GetMyNextTarget(HomunHPPerc)
if NextTarget ~=0 then
isCircling = false
MyEnemy = NextTarget
local Ex, Ey = GetV(V_POSITION, MyEnemy)
if (math.abs(Ex - MyX) <= 1) and (math.abs(Ey - MyY) <= 1) then
MyState = ATTACK_ST
Attack(MyID, MyEnemy)
AtkStartTime = 0
Log(string.format("[IDLE_ST -> ATTACK_ST] Target(%d) already near, switch directly to combat", MyEnemy))
else
MyState = CHASE_ST
Log(string.format("[IDLE_ST -> CHASE_ST] Intercepting new target(%d)", MyEnemy))
end
vOwnerX, vOwnerY = OwnerX, OwnerY
return
else
if MyState == EVADE_ST then
isCircling = false
return
end
end
end
...end
...
function OnATTACK_ST()
...
-- Change target when the enemy is dead or lost local Ex, Ey = GetV(V_POSITION, MyEnemy) if (Ex == -1) or (MOTION_DEAD == GetV(V_MOTION, MyEnemy)) then Log(string.format("MyEnemy(%d) lost or dead. Searching for next target", MyEnemy)) local NextTarget = GetMyNextTarget(HomunHPPerc) if NextTarget ~=0 then MyEnemy = NextTarget AtkSkillDoneCount = 0 AtkStartTime = GetTick() -- a new attack starts (usually this reset is in ON_IDLE_ST) else if MyState ~= EVADE_ST then StopHere("[ATTACK_ST -> IDLE_ST] No more immediate targets") end return end end
...
end
[/code:k2jhniqc]
на то что ограничено стрелочками
[code:k2jhniqc]
function OnIDLE_ST()...
-- Is there a new target? -> chase_st if CurrTime - StartupTime > 600 then local NextTarget = GetMyNextTarget(HomunHPPerc) if NextTarget ~=0 then isCircling = false MyEnemy = NextTarget local Ex, Ey = GetV(V_POSITION, MyEnemy)
--> if((HomunType == VANILMIRTH or HomunType == VANILMIRTH_H
or HomunType == VANILMIRTH2 or HomunType == VANILMIRTH_H2)
and (HomunSP >= AS_VAN_CAPR.MinSP)
and ( GetDistance(Ex, Ey, MyX, MyY) <= GetV( V_SKILLATTACKRANGE, AS_VAN_CAPR.SkillID))
and (DoSkill(AS_VAN_CAPR,MyEnemy) != false)) then
MyState = ATTACK_ST
AtkStartTime = 0
Log(string.format("[IDLE_ST -> ATTACK_ST] Target(%d) already near, switch directly to combat", MyEnemy))
else<--
if (math.abs(Ex - MyX) <= 1) and (math.abs(Ey - MyY) <= 1) then
MyState = ATTACK_ST
Attack(MyID, MyEnemy)
AtkStartTime = 0
Log(string.format("[IDLE_ST -> ATTACK_ST] Target(%d) already near, switch directly to combat", MyEnemy))
else
MyState = CHASE_ST
Log(string.format("[IDLE_ST -> CHASE_ST] Intercepting new target(%d)", MyEnemy))
end
--> end<--
vOwnerX, vOwnerY = OwnerX, OwnerY
return
else
if MyState == EVADE_ST then
isCircling = false
return
end
end
end...
end
function OnATTACK_ST()
...
-- Change target when the enemy is dead or lost local Ex, Ey = GetV(V_POSITION, MyEnemy) if (Ex == -1) or (MOTION_DEAD == GetV(V_MOTION, MyEnemy)) then Log(string.format("MyEnemy(%d) lost or dead. Searching for next target", MyEnemy)) local NextTarget = GetMyNextTarget(HomunHPPerc) if NextTarget ~=0 then MyEnemy = NextTarget
--> local Ex, Ey = GetV(V_POSITION, MyEnemy)
if((HomunType == VANILMIRTH or HomunType == VANILMIRTH_H
or HomunType == VANILMIRTH2 or HomunType == VANILMIRTH_H2)
and (HomunSP >= AS_VAN_CAPR.MinSP)
and ( GetDistance(Ex, Ey, MyX, MyY) <= GetV( V_SKILLATTACKRANGE, AS_VAN_CAPR.SkillID))
and (DoSkill(AS_VAN_CAPR,MyEnemy) != false)) then
AtkStartTime = GetTick() -- a new attack starts (usually this reset is in ON_IDLE_ST)
AtkSkillDoneCount = 1
else<--
AtkSkillDoneCount = 0
AtkStartTime = GetTick() -- a new attack starts (usually this reset is in ON_IDLE_ST)
--> end<--
else
if MyState ~= EVADE_ST then
StopHere("[ATTACK_ST -> IDLE_ST] No more immediate targets")
end
return
end
end...
end
[/code:k2jhniqc]
Данные куски кода не отлажены по этому советую сохранить резервную копию исходного файла, перед внесением изменений. -
Florencia, чтобы ванилька сначала бросала болт в нового врага нужно в файле AI.lua исправить вот этоти куски
[code:k2jhniqc]
function OnIDLE_ST()...
-- Is there a new target? -> chase_st
if CurrTime - StartupTime > 600 then
local NextTarget = GetMyNextTarget(HomunHPPerc)
if NextTarget ~=0 then
isCircling = false
MyEnemy = NextTarget
local Ex, Ey = GetV(V_POSITION, MyEnemy)
if (math.abs(Ex - MyX) <= 1) and (math.abs(Ey - MyY) <= 1) then
MyState = ATTACK_ST
Attack(MyID, MyEnemy)
AtkStartTime = 0
Log(string.format("[IDLE_ST -> ATTACK_ST] Target(%d) already near, switch directly to combat", MyEnemy))
else
MyState = CHASE_ST
Log(string.format("[IDLE_ST -> CHASE_ST] Intercepting new target(%d)", MyEnemy))
end
vOwnerX, vOwnerY = OwnerX, OwnerY
return
else
if MyState == EVADE_ST then
isCircling = false
return
end
end
end
...end
...
function OnATTACK_ST()
...
-- Change target when the enemy is dead or lost local Ex, Ey = GetV(V_POSITION, MyEnemy) if (Ex == -1) or (MOTION_DEAD == GetV(V_MOTION, MyEnemy)) then Log(string.format("MyEnemy(%d) lost or dead. Searching for next target", MyEnemy)) local NextTarget = GetMyNextTarget(HomunHPPerc) if NextTarget ~=0 then MyEnemy = NextTarget AtkSkillDoneCount = 0 AtkStartTime = GetTick() -- a new attack starts (usually this reset is in ON_IDLE_ST) else if MyState ~= EVADE_ST then StopHere("[ATTACK_ST -> IDLE_ST] No more immediate targets") end return end end
...
end
[/code:k2jhniqc]
на то что ограничено стрелочками
[code:k2jhniqc]
function OnIDLE_ST()...
-- Is there a new target? -> chase_st if CurrTime - StartupTime > 600 then local NextTarget = GetMyNextTarget(HomunHPPerc) if NextTarget ~=0 then isCircling = false MyEnemy = NextTarget local Ex, Ey = GetV(V_POSITION, MyEnemy)
--> if((HomunType == VANILMIRTH or HomunType == VANILMIRTH_H
or HomunType == VANILMIRTH2 or HomunType == VANILMIRTH_H2)
and (HomunSP >= AS_VAN_CAPR.MinSP)
and ( GetDistance(Ex, Ey, MyX, MyY) <= GetV( V_SKILLATTACKRANGE, AS_VAN_CAPR.SkillID))
and (DoSkill(AS_VAN_CAPR,MyEnemy) != false)) then
MyState = ATTACK_ST
AtkStartTime = 0
Log(string.format("[IDLE_ST -> ATTACK_ST] Target(%d) already near, switch directly to combat", MyEnemy))
else<--
if (math.abs(Ex - MyX) <= 1) and (math.abs(Ey - MyY) <= 1) then
MyState = ATTACK_ST
Attack(MyID, MyEnemy)
AtkStartTime = 0
Log(string.format("[IDLE_ST -> ATTACK_ST] Target(%d) already near, switch directly to combat", MyEnemy))
else
MyState = CHASE_ST
Log(string.format("[IDLE_ST -> CHASE_ST] Intercepting new target(%d)", MyEnemy))
end
--> end<--
vOwnerX, vOwnerY = OwnerX, OwnerY
return
else
if MyState == EVADE_ST then
isCircling = false
return
end
end
end...
end
function OnATTACK_ST()
...
-- Change target when the enemy is dead or lost local Ex, Ey = GetV(V_POSITION, MyEnemy) if (Ex == -1) or (MOTION_DEAD == GetV(V_MOTION, MyEnemy)) then Log(string.format("MyEnemy(%d) lost or dead. Searching for next target", MyEnemy)) local NextTarget = GetMyNextTarget(HomunHPPerc) if NextTarget ~=0 then MyEnemy = NextTarget
--> local Ex, Ey = GetV(V_POSITION, MyEnemy)
if((HomunType == VANILMIRTH or HomunType == VANILMIRTH_H
or HomunType == VANILMIRTH2 or HomunType == VANILMIRTH_H2)
and (HomunSP >= AS_VAN_CAPR.MinSP)
and ( GetDistance(Ex, Ey, MyX, MyY) <= GetV( V_SKILLATTACKRANGE, AS_VAN_CAPR.SkillID))
and (DoSkill(AS_VAN_CAPR,MyEnemy) != false)) then
AtkStartTime = GetTick() -- a new attack starts (usually this reset is in ON_IDLE_ST)
AtkSkillDoneCount = 1
else<--
AtkSkillDoneCount = 0
AtkStartTime = GetTick() -- a new attack starts (usually this reset is in ON_IDLE_ST)
--> end<--
else
if MyState ~= EVADE_ST then
StopHere("[ATTACK_ST -> IDLE_ST] No more immediate targets")
end
return
end
end...
end
[/code:k2jhniqc]
Данные куски кода не отлажены по этому советую сохранить резервную копию исходного файла, перед внесением изменений. -
спасибо попробую
-
спасибо попробую
-
вообще-то надо править функцию чейзинга, т.к. аттак возникает когда уже началась атака, т.е. хомяк бьет его физ атаками.
сейчас сделаю дифф и попробую найти, что именно для этого я правила.Это конечно смешно, но у меня в мирке из значимых для автокаста болта всего пара изменений, знаком --> показы изменения.
[code:3umzdkg1]--------------------------------------------------
function DoSkill(Skill, Target)if Skill.Level == 0 then return false; end local CurrTime = GetTick() if CastDelayEnd > CurrTime then return false; end local HomunSP = GetV(V_SP, MyID) local result = false if Skill.Engaged then -- if the skill is already active (or in delay time), wait until it goes OFF if CurrTime > Skill.TimeOut then Skill.Engaged = false end else -- if the skill is OFF, activate it if HomunSP >= Skill.MinSP then -- if there are enough SP left MySkill = Skill.SkillID if ( (MySkill == AS_FIL_MOON.SkillID) or (MySkill == AS_VAN_CAPR.SkillID) ) and (HTact.Level ~=-1) then MySkillLevel = HTact.Level elseif (MySkill == AS_VAN_BLES.SkillID) then if Target == OwnerID then MySkillLevel = 3 -- lvl 3 heal rate: enemy=25%, self=25%, owner=50% elseif Target == MyID then MySkillLevel = 4 -- lvl 4 heal rate: enemy=36%, self=60%, owner=4% else MySkillLevel = Skill.Level end else MySkillLevel = Skill.Level end Skill.TimeOut = CurrTime + Skill.HowLast Skill.Engaged = true SkillObject(MyID, MySkillLevel, MySkill, Target) Log(string.format("Done skill %d lvl %d on target %d", MySkill, MySkillLevel, Target))
--> CastDelayEnd = CurrTime + 0
result = true
MySkill = 0
end
end
return result
end[/code:3umzdkg1]
[code:3umzdkg1]
function CanDoAtkSkillsNow()
-- is it the right time for an aggressive skill?local result = true local CurrTime = GetTick() local TimeOutElapsed = CurrTime - AtkStartTime > SKILL_TIME_OUT if (HTact.Skill == WITH_no_skill) then result = false elseif HTact.Skill == WITH_one_skill then -- Log(string.format("AtkSkillDoneCount = %d, CurrTime - AtkStartTime = %d", AtkSkillDoneCount, CurrTime - AtkStartTime)) if (AtkSkillDoneCount > 1) or TimeOutElapsed then result = false end elseif HTact.Skill == WITH_two_skills then if (AtkSkillDoneCount > 2) then result = false end elseif HTact.Skill == WITH_max_skills then if TimeOutElapsed then result = false end elseif HTact.Skill == WITH_slow_power then if (LONG_RANGE_SHOOTER ~= true) and (CurrTime - AtkStartTime < DELAY_SLOW_POWER) then
--> if AtkSkillDoneCount ~= 0 then
--> result = false
end
end
end
return result
end[/code:3umzdkg1]насколько я помню главная проблема мирки была с ненужными задержками там где не надо. если кому интересно, можете скачать и попробовать, а также посмотреть мой вариант с небольшими правками <!-- m --><a class="postlink" href="http://forum.sepulka.org.ua/viewtopic.php?id=399">http://forum.sepulka.org.ua/viewtopic.php?id=399</a><!-- m --> к сожалению из-за изменения файла настроек мой вариант не будет работать с утилитой настроек от оригинальной мирки, а свою я все никак не напишу.
-
вообще-то надо править функцию чейзинга, т.к. аттак возникает когда уже началась атака, т.е. хомяк бьет его физ атаками.
сейчас сделаю дифф и попробую найти, что именно для этого я правила.Это конечно смешно, но у меня в мирке из значимых для автокаста болта всего пара изменений, знаком --> показы изменения.
[code:3umzdkg1]--------------------------------------------------
function DoSkill(Skill, Target)if Skill.Level == 0 then return false; end local CurrTime = GetTick() if CastDelayEnd > CurrTime then return false; end local HomunSP = GetV(V_SP, MyID) local result = false if Skill.Engaged then -- if the skill is already active (or in delay time), wait until it goes OFF if CurrTime > Skill.TimeOut then Skill.Engaged = false end else -- if the skill is OFF, activate it if HomunSP >= Skill.MinSP then -- if there are enough SP left MySkill = Skill.SkillID if ( (MySkill == AS_FIL_MOON.SkillID) or (MySkill == AS_VAN_CAPR.SkillID) ) and (HTact.Level ~=-1) then MySkillLevel = HTact.Level elseif (MySkill == AS_VAN_BLES.SkillID) then if Target == OwnerID then MySkillLevel = 3 -- lvl 3 heal rate: enemy=25%, self=25%, owner=50% elseif Target == MyID then MySkillLevel = 4 -- lvl 4 heal rate: enemy=36%, self=60%, owner=4% else MySkillLevel = Skill.Level end else MySkillLevel = Skill.Level end Skill.TimeOut = CurrTime + Skill.HowLast Skill.Engaged = true SkillObject(MyID, MySkillLevel, MySkill, Target) Log(string.format("Done skill %d lvl %d on target %d", MySkill, MySkillLevel, Target))
--> CastDelayEnd = CurrTime + 0
result = true
MySkill = 0
end
end
return result
end[/code:3umzdkg1]
[code:3umzdkg1]
function CanDoAtkSkillsNow()
-- is it the right time for an aggressive skill?local result = true local CurrTime = GetTick() local TimeOutElapsed = CurrTime - AtkStartTime > SKILL_TIME_OUT if (HTact.Skill == WITH_no_skill) then result = false elseif HTact.Skill == WITH_one_skill then -- Log(string.format("AtkSkillDoneCount = %d, CurrTime - AtkStartTime = %d", AtkSkillDoneCount, CurrTime - AtkStartTime)) if (AtkSkillDoneCount > 1) or TimeOutElapsed then result = false end elseif HTact.Skill == WITH_two_skills then if (AtkSkillDoneCount > 2) then result = false end elseif HTact.Skill == WITH_max_skills then if TimeOutElapsed then result = false end elseif HTact.Skill == WITH_slow_power then if (LONG_RANGE_SHOOTER ~= true) and (CurrTime - AtkStartTime < DELAY_SLOW_POWER) then
--> if AtkSkillDoneCount ~= 0 then
--> result = false
end
end
end
return result
end[/code:3umzdkg1]насколько я помню главная проблема мирки была с ненужными задержками там где не надо. если кому интересно, можете скачать и попробовать, а также посмотреть мой вариант с небольшими правками <!-- m --><a class="postlink" href="http://forum.sepulka.org.ua/viewtopic.php?id=399">http://forum.sepulka.org.ua/viewtopic.php?id=399</a><!-- m --> к сожалению из-за изменения файла настроек мой вариант не будет работать с утилитой настроек от оригинальной мирки, а свою я все никак не напишу.
-
@sepulka:
вообще-то надо править функцию чейзинга, т.к. аттак возникает когда уже началась атака, т.е. хомяк бьет его физ атаками...
я не разбирался как именно работает мира и по этому не трогал функцию чейзинга, в функции аттака я поправил место выбора следующей жертвы, если ту что били умерла или убежала.
[code:s652e4pc]
-- Change target when the enemy is dead or lost (Смена цели когда противник умер или потерен из виду)
local Ex, Ey = GetV(V_POSITION, MyEnemy)
if (Ex == -1) or (MOTION_DEAD == GetV(V_MOTION, MyEnemy)) then
[/code:s652e4pc] -
@"sepulka":
вообще-то надо править функцию чейзинга, т.к. аттак возникает когда уже началась атака, т.е. хомяк бьет его физ атаками...
я не разбирался как именно работает мира и по этому не трогал функцию чейзинга, в функции аттака я поправил место выбора следующей жертвы, если ту что били умерла или убежала.
[code:s652e4pc]
-- Change target when the enemy is dead or lost (Смена цели когда противник умер или потерен из виду)
local Ex, Ey = GetV(V_POSITION, MyEnemy)
if (Ex == -1) or (MOTION_DEAD == GetV(V_MOTION, MyEnemy)) then
[/code:s652e4pc] -
ну я выложила,ч то у меня исправлено. Действительно функцию чейзинга трогать не надо.
-
ну я выложила,ч то у меня исправлено. Действительно функцию чейзинга трогать не надо.
-
Поскажите пожалуйста есть ли возможность и если есть то где прописать что бы Ванилька скилом атаковала несколько раз?
-
Поскажите пожалуйста есть ли возможность и если есть то где прописать что бы Ванилька скилом атаковала несколько раз?
-
SamBut, в мир аи выставляется в тактиках, 1, 2 и много
-
SamBut, в мир аи выставляется в тактиках, 1, 2 и много
-
вы вроде про болты мне написали, чтобы она сначала их кидала. А как сделать, чтобы она не крутилась возле моба, которого бьет другой гом. Получается, что из-за этого она пропускает респ следующего , пока тупо крутится возле чужого. И еще чат зафлуживается надписями вы пытаетесь атаковать чужого моба, хоть она его и не атакует а тока бегает вокруг.
-
вы вроде про болты мне написали, чтобы она сначала их кидала. А как сделать, чтобы она не крутилась возле моба, которого бьет другой гом. Получается, что из-за этого она пропускает респ следующего , пока тупо крутится возле чужого. И еще чат зафлуживается надписями вы пытаетесь атаковать чужого моба, хоть она его и не атакует а тока бегает вокруг.
-
Не бьет потому, что включен антикс. А так бы пинала (отсюда и надписи). Чтобы такого не было, надо включать анти-кс в AI. В MirAI он встроенный, а это значит, что либо у вас старая версия, либо скрипт плохо определяет чужих мобов и стоит перейти на другой (это будет проще, чем докручивать проверки вручную).