AI игрок сам выберет рабочего (одного) для починки какого-либо здания
Если конечно я понял, что задача необходима для игрока под управлением искуственного интелекта
Vitamin, ну ок, пример кода - когда нужно юзать нестандартные предметы, прыг во врага и активация предмета стан по аое, ну или что аватар нужно врубать перед замесом а не лоу хп как это делает мили ИИ.
Ну как то так (телепортация во врага и активация предмета я не сделал, но я не думаю, что это проблема будет для человека, который знает JASS)
AI Script
globals
integer g_iCaptainTimer = 0
player g_hPlayerAI = Player(GetAiPlayer())
unit g_hHero
endglobals
function Event_OnHeroLevelGain takes nothing returns integer
// NOTE: All hero levels and skills in this callback
return 0
endfunction
function InitAssaultGroup takes nothing returns nothing
local integer iHeroID = GetUnitTypeId(g_hHero)
local integer iUnitInCaptain = GetUnitCountDone(iHeroID) - IgnoredUnits(iHeroID)
if iUnitInCaptain == 0 then
return
endif
call InitAssault()
call AddAssault(iUnitInCaptain, iHeroID)
endfunction
function FindHeroHandle takes nothing returns nothing
local group hGroup = CreateGroup()
local unit hUnit
call GroupEnumUnitsOfPlayer(hGroup, g_hPlayerAI, null)
loop
set hUnit = FirstOfGroup(hGroup)
exitwhen hUnit == null
if IsUnitType(hUnit, UNIT_TYPE_HERO) then // NOTE: Only one hero available
set g_hHero = hUnit
exitwhen true
endif
call GroupRemoveUnit(hGroup, hUnit)
endloop
call DestroyGroup(hGroup)
set hGroup = null
set hUnit = null
endfunction
function ApplyHeroItems takes nothing returns nothing
local integer ITEM = 'CODE'
local integer iItemIndex = 0
local item hItem
loop
exitwhen iItemIndex == 5
set hItem = UnitItemInSlot(g_hHero, iItemIndex)
if GetItemTypeId(hItem) == ITEM then
exitwhen true
endif
set iItemIndex = iItemIndex + 1
endloop
if hItem == null then
return
endif
// NOTE: Your conditions for applying item
call UnitUseItem(g_hHero, hItem)
// call UnitUseItemPoint
// call UnitUseItemTarget
endfunction
function MonitoringHeroSkills takes nothing returns nothing
// NOTE: Add check via Command or into AI Script if AI Hero using Avatar early and add global var for cooldown
local integer AVATAR_ID = 852086
local integer MAX_CAPTAIN_ATTEMPTS = 5
if not CaptainInCombat(true) then
if g_iCaptainTimer != 0 then
set g_iCaptainTimer = g_iCaptainTimer - 1
endif
else
if g_iCaptainTimer == MAX_CAPTAIN_ATTEMPTS then
call IssueImmediateOrderById(g_hHero, AVATAR_ID)
set g_iCaptainTimer = 0
else
set g_iCaptainTimer = g_iCaptainTimer + 1
endif
endif
endfunction
function DevelopmentSequence takes nothing returns nothing
loop
call ApplyHeroItems()
call MonitoringHeroSkills()
call Sleep(1.0)
endloop
endfunction
function main takes nothing returns nothing
call SetHeroLevels(function Event_OnHeroLevelGain)
call PrintToChat("AI Script started")
call CreateCaptains()
call GroupTimedLife(true)
call SetCampaignAI()
call SetHeroesFlee(true)
call SetHeroesTakeItems(true)
call SetWatchMegaTargets(true)
call Sleep(0.1)
call FindHeroHandle()
call StartThread(function DevelopmentSequence)
loop
call InitAssaultGroup()
call Sleep(1.0)
endloop
endfunction
Если нужна полная кастомизация способности, то на основе способности канала делаем аватар и полностью пишем ИИ для способности соответсвенно
Плюс в AI скриптах тот, что они предоставляют функции управления капитанами, чего нету вне виртуальной машины AI скриптов (по крайней мере я знаю только это), соответсвенно функции SetProduce, GetCreepCamp и иные вне AI скриптов невозможны
А если что то надо связать из карты с AI скриптом, то тут благо есть функция CommandAI
Vitamin, ну такие ИИ же больше для мили, там микро не сделаешь... Лишь макро и тактика.
Не согласен с вами, если посмотреть тот же Advanced Melee AI это вполне реально, к тому же виртуальная машина под AI скрипты предоставляет достаточно много функций для написания того же микроконтроля
Помоему для вашей цели лучше всего пойдет создание AI скрипта и подключение его через функцию SetMeleeAI
Пример AI скрипта ниже (если понимаете JASS, проблем в дальнешем в написании/изменении текущего не составит проблем)
AI Script
globals
constant integer HOLY_BOLT = 1095264354
constant integer FOOTMAN = 1751543663
constant integer KNIGHT = 1751871081
constant integer PRIEST = 1752002674
constant integer UTHER = 1215657064
group g_hHurtUnitGroup = CreateGroup()
integer g_iCaptainHomeX
integer g_iCaptainHomeY
integer g_iFountainOfLifeX
integer g_iFountainOfLifeY
unit g_hHero
endglobals
function B2S takes boolean b returns string
if b then
return "true"
else
return "false"
endif
endfunction
function Dig2Str takes integer i returns string
if i == 1 then
return "1"
elseif i == 2 then
return "2"
elseif i == 3 then
return "3"
elseif i == 4 then
return "4"
elseif i == 5 then
return "5"
elseif i == 6 then
return "6"
elseif i == 7 then
return "7"
elseif i == 8 then
return "8"
elseif i == 9 then
return "9"
else
return "0"
endif
endfunction
// Courtesy of AIAndy and Tommi. See source:
// http://www.hiveworkshop.com/threads/two-custom-campaign-ais-examples.8939/
function Int2Str takes integer ic returns string
local string s = ""
local integer i = ic
local integer ialt = 0
local boolean neg = false
if i == 0 then
return "0"
endif
if i < 0 then
set neg = true
set i = (-1)*i
endif
loop
exitwhen i == 0
set ialt = i
set i = i / 10
set s = Dig2Str( ialt - 10*i ) + s
endloop
if neg then
set s = "-"+s
endif
return s
endfunction
function Event_OnHeroLevelGain takes nothing returns integer
local integer DEVOTION_AURA = 1095262564
local integer DIVINE_SHIELD = 1095263347
local integer RESURRECTION = 1095266917
local integer iLevel = GetHeroLevelAI()
if iLevel == 1 then
return HOLY_BOLT
elseif iLevel == 2 then
return DEVOTION_AURA
elseif iLevel == 3 then
return HOLY_BOLT
elseif iLevel == 4 then
return DIVINE_SHIELD
elseif iLevel == 5 then
return HOLY_BOLT
elseif iLevel == 6 then
return RESURRECTION
elseif iLevel == 7 then
return DIVINE_SHIELD
elseif iLevel == 8 then
return DEVOTION_AURA
elseif iLevel == 9 then
return DEVOTION_AURA
elseif iLevel == 10 then
return DIVINE_SHIELD
endif
return STAT_UP
endfunction
function InitAssaultGroup takes nothing returns nothing
call InitAssault()
call AddAssault(GetUnitCountDone(FOOTMAN) - IgnoredUnits(FOOTMAN) , FOOTMAN )
call AddAssault(GetUnitCountDone(KNIGHT) - IgnoredUnits(KNIGHT) , KNIGHT )
call AddAssault(GetUnitCountDone(PRIEST) - IgnoredUnits(PRIEST) , PRIEST )
call AddAssault(GetUnitCountDone(UTHER) - IgnoredUnits(UTHER) , UTHER )
endfunction
function FindFountainOfLive takes nothing returns nothing
local integer FOUNTAIN_OF_LIFE = 1852206952
local integer PLAYER_NEUTRAL_PASSIVE = 15
local group hGroup = CreateGroup()
local unit hUnit
call GroupEnumUnitsOfPlayer(hGroup, Player(PLAYER_NEUTRAL_PASSIVE), null)
loop
set hUnit = FirstOfGroup(hGroup)
exitwhen hUnit == null
if UnitAlive(hUnit) then
if IsUnitType(hUnit, UNIT_TYPE_STRUCTURE) then
if GetUnitTypeId(hUnit) == FOUNTAIN_OF_LIFE then
set g_iFountainOfLifeX = R2I(GetWidgetX(hUnit)) + 200
set g_iFountainOfLifeY = R2I(GetWidgetY(hUnit)) - 200
exitwhen true
endif
endif
endif
call GroupRemoveUnit(hGroup, hUnit)
endloop
call DestroyGroup(hGroup)
set hGroup = null
set hUnit = null
endfunction
function ChangeCaptainHome takes nothing returns nothing
local integer BOTH_CAPTAINS = 3
set g_iCaptainHomeX = -3700
set g_iCaptainHomeY = 0
call SetCaptainHome(BOTH_CAPTAINS, g_iCaptainHomeX, g_iCaptainHomeY)
endfunction
function CreateUnits takes nothing returns nothing
local integer MASK_OF_DEATH = 1836016756
local integer POTION_OF_HEALTH = 1885825125
set g_hHero = CreateUnit(g_hPlayerAI, UTHER , -1095 , -54 , 0)
call CreateUnit(g_hPlayerAI, FOOTMAN , -1302 , -722 , 0)
call CreateUnit(g_hPlayerAI, FOOTMAN , -1231 , -728 , 0)
call CreateUnit(g_hPlayerAI, FOOTMAN , -1154 , -730 , 0)
call CreateUnit(g_hPlayerAI, FOOTMAN , -1091 , -730 , 0)
call CreateUnit(g_hPlayerAI, FOOTMAN , -1014 , -730 , 0)
call CreateUnit(g_hPlayerAI, FOOTMAN , -951 , -728 , 0)
call CreateUnit(g_hPlayerAI, FOOTMAN , -858 , -722 , 0)
call CreateUnit(g_hPlayerAI, FOOTMAN , -918 , 257 , 0)
call CreateUnit(g_hPlayerAI, FOOTMAN , -1049 , 329 , 0)
call CreateUnit(g_hPlayerAI, FOOTMAN , -1118 , 374 , 0)
call CreateUnit(g_hPlayerAI, FOOTMAN , -982 , 295 , 0)
call CreateUnit(g_hPlayerAI, KNIGHT , -1099 , 106 , 0)
call CreateUnit(g_hPlayerAI, KNIGHT , -1234 , 5 , 0)
call CreateUnit(g_hPlayerAI, PRIEST , -1001 , -809 , 0)
call CreateUnit(g_hPlayerAI, PRIEST , -991 , -112 , 0)
call CreateUnit(g_hPlayerAI, PRIEST , -1152 , -818 , 0)
call CreateUnit(g_hPlayerAI, PRIEST , -1103 , -232 , 0)
call UnitAddItemToSlotById(g_hHero, MASK_OF_DEATH , 0)
call UnitAddItemToSlotById(g_hHero, POTION_OF_HEALTH, 1)
endfunction
function IsEnemyInRangeXY takes integer iX, integer iY, integer iRadius returns boolean
local boolean bIsFindEnemy = false
local group hGroup = CreateGroup()
local unit hUnit
call GroupEnumUnitsInRange(hGroup,iX, iY, I2R(iRadius), null)
loop
set hUnit = FirstOfGroup(hGroup)
exitwhen hUnit == null
if UnitAlive(hUnit) then
if IsUnitEnemy(hUnit, g_hPlayerAI) then
set bIsFindEnemy = true
exitwhen true
endif
endif
endloop
call DestroyGroup(hGroup)
set hGroup = null
set hUnit = null
return bIsFindEnemy
endfunction
function CheckUnitHealth takes nothing returns nothing
local integer ORDER_SMART = 851971
local integer ORDER_MOVE = 851986
local integer MIN_SAFE_RANGE = 200
local integer MIN_UNIT_HEALTH = 150
local boolean bIsUnitInHurtGroup
local group hGroup = CreateGroup()
local integer iOffsetX
local integer iOffsetY
local real flUnitHealth
local unit hUnit
call GroupEnumUnitsOfPlayer(hGroup, g_hPlayerAI, null)
loop
set hUnit = FirstOfGroup(hGroup)
exitwhen hUnit == null
set bIsUnitInHurtGroup = IsUnitInGroup(hUnit, g_hHurtUnitGroup)
if UnitAlive(hUnit) then
if not (IsUnitType(hUnit, UNIT_TYPE_SUMMONED) or hUnit == g_hHero) then
set flUnitHealth = GetWidgetLife(hUnit)
if R2I(flUnitHealth) < MIN_UNIT_HEALTH then
set iOffsetX = GetRandomInt(-50, 50)
set iOffsetY = GetRandomInt(-50, 50)
call RemoveGuardPosition(hUnit)
if not bIsUnitInHurtGroup then
call GroupAddUnit(g_hHurtUnitGroup, hUnit)
endif
if IsEnemyInRangeXY(g_iFountainOfLifeX, g_iFountainOfLifeY, 1000) then
if not IsUnitInRangeXY(hUnit, g_iCaptainHomeX, g_iCaptainHomeY, MIN_SAFE_RANGE) then
call PrintToChat("Unit go home")
call IssuePointOrderById(hUnit, ORDER_MOVE, g_iCaptainHomeX + iOffsetX, g_iCaptainHomeY + iOffsetY)
endif
else
if not IsUnitInRangeXY(hUnit, g_iFountainOfLifeX, g_iFountainOfLifeX, MIN_SAFE_RANGE) then
call IssuePointOrderById(hUnit, ORDER_SMART , g_iFountainOfLifeX + iOffsetX , g_iFountainOfLifeY + iOffsetY)
endif
endif
elseif flUnitHealth * 1.5 > GetUnitState(hUnit, UNIT_STATE_MAX_LIFE) then
if bIsUnitInHurtGroup then
call PrintToChat("Unit back to captain control")
call RecycleGuardPosition(hUnit)
call GroupRemoveUnit(g_hHurtUnitGroup, hUnit)
endif
endif
endif
else
if bIsUnitInHurtGroup then
call GroupRemoveUnit(g_hHurtUnitGroup, hUnit)
endif
endif
call GroupRemoveUnit(hGroup, hUnit)
endloop
if FirstOfGroup(g_hHurtUnitGroup) != null then //NOTE: Some hurt units under attack at home
if not CaptainIsHome() then
if IsEnemyInRangeXY(g_iCaptainHomeX, g_iCaptainHomeY, MIN_SAFE_RANGE) then
if not CaptainRetreating() then
call ClearCaptainTargets()
call CaptainGoHome()
call SetGroupsFlee(true) // NOTE: Tested
call SetUnitsFlee(true)
endif
endif
endif
endif
call DestroyGroup(hGroup)
set hGroup = null
set hUnit = null
endfunction
function DevelopmentSequence takes nothing returns nothing
loop
call InitAssaultGroup()
call CheckUnitHealth()
call Sleep(DEFAULT_SLEEP)
endloop
endfunction
function main takes nothing returns nothing
set g_hPlayerAI = Player(GetAiPlayer())
call SetHeroLevels(function Event_OnHeroLevelGain)
call CreateUnits()
call PrintToChat("AI Script started")
call CreateCaptains()
call GroupTimedLife(true)
call SetCampaignAI()
call SetHeroesFlee(true)
call SetHeroesTakeItems(true)
call SetWatchMegaTargets(true)
call Sleep(0.1)
call ChangeCaptainHome()
call FindFountainOfLive()
call StartThread(function DevelopmentSequence)
loop
call Sleep(1)
endloop
endfunction
Возможно такое сотворить помоему канеш трудно чуток но попытаюсь объяснить
Через MPQ находишь текстуру слабого лагеря и среднего и сильного потом имортируешь текстуру > слабого лагеря в свою карту и прописываешь путь среднего лагеря таком случае и слабый и > средний будет показывать зеленым кругом не совсем идеально но все же можно использовать > главный минус потом у тебя остается только сильный лагерь и слабый
Это всё костыли, если програмно нельзя ничего сделать, тогда будет как есть
Все понял, а как насчет метода, который я привел (по ссылке) ?
Но метод с массивами это конечно просто убого .... Если мне надо к примеру получить значение из функции мне вместо "0" использовать к примеру так ?
variable[1] = GetLastCommand()
Я правильно понял ?
P.S. Ни I2S, ни R2S не работают в AI скрипте
Вообще нашелся один способ решения моей проблемы:
Не реклама
Но вопрос: Неужели ничего проще нету ...
Данный код работает:
local string test = "Hello"
call DisplayTextToPlayer(Player(0), 0.0, 0.0, "Hello " + test)
Я так понимаю функцию I2S отказывается конвертировать (неправильно работает в AI скрипте)
попробуй добавить в карту кастом common.ai куда засунь нативки из common.j
а именно
native DisplayTextToPlayer takes player toPlayer, real x, real y, string message returns nothing
Можно пожалуйста ссылку на статью как правильно импортировать данную вещь в карту ?
Не знаю просто как сделать правильный запрос в поисковике, чтобы выдал мне это.
Ред. Vitamin
» WarCraft 3 / Рабочие и здания
Если конечно я понял, что задача необходима для игрока под управлением искуственного интелекта
Ред. Vitamin
» WarCraft 3 / Создание ИИ
Плюс в AI скриптах тот, что они предоставляют функции управления капитанами, чего нету вне виртуальной машины AI скриптов (по крайней мере я знаю только это), соответсвенно функции SetProduce, GetCreepCamp и иные вне AI скриптов невозможны
А если что то надо связать из карты с AI скриптом, то тут благо есть функция CommandAI
» WarCraft 3 / Создание ИИ
Ред. Vitamin
» WarCraft 3 / Создание ИИ
Пример AI скрипта ниже (если понимаете JASS, проблем в дальнешем в написании/изменении текущего не составит проблем)
» WarCraft 3 / Нейтрально-враждёбные лагеря на мини-карте
Ред. Vitamin
» WarCraft 3 / Как отловить простой юнитов?
» WarCraft 3 / Создание Debug сообщения в AI скрипте
» WarCraft 3 / Создание Debug сообщения в AI скрипте
Но метод с массивами это конечно просто убого .... Если мне надо к примеру получить значение из функции мне вместо "0" использовать к примеру так ?
variable[1] = GetLastCommand()
Ред. Vitamin
» WarCraft 3 / Создание Debug сообщения в AI скрипте
variable[0] = "Test #1"
variable[1] = "Test #2"
P.S. Ни I2S, ни R2S не работают в AI скрипте
Вообще нашелся один способ решения моей проблемы:
Не реклама
Но вопрос: Неужели ничего проще нету ...
» WarCraft 3 / Создание Debug сообщения в AI скрипте
local string test = "Hello"
call DisplayTextToPlayer(Player(0), 0.0, 0.0, "Hello " + test)
Я так понимаю функцию I2S отказывается конвертировать (неправильно работает в AI скрипте)
Ред. Vitamin
» WarCraft 3 / Создание Debug сообщения в AI скрипте
Не знаю просто как сделать правильный запрос в поисковике, чтобы выдал мне это.
» WarCraft 3 / Создание Debug сообщения в AI скрипте
Все что есть:
native DebugS takes string str returns nothing
native DebugFI takes string str, integer val returns nothing
native DebugUnitID takes string str, integer val returns nothing
native DisplayText takes integer p, string str returns nothing
native DisplayTextI takes integer p, string str, integer val returns nothing
native DisplayTextII takes integer p, string str, integer v1, integer v2 returns nothing
native DisplayTextIII takes integer p, string str, integer v1, integer v2, integer v3 returns nothing
native DoAiScriptDebug takes nothing returns boolean
Они ничего не выводят (поэтому они работают только в Developer version game.dll)
» WarCraft 3 / Создание Debug сообщения в AI скрипте