4
22
5 лет назад
Отредактирован Zahanc
4

» WarCraft 3 / Заклинания на заказ

// globals
//    integer array udg_cocoonSpawnUnitTypeId
//    integer array udg_cocoonSpawnsQuantity
//    integer array udg_cocoonUnitTypeId
//    integer cocoonsQuantity = 0
//    player array udg_cocoonOwner
//    real array udg_cocoonHatchDelay
//    real array udg_cocoonOriginX
//    real array udg_cocoonOriginY
//    real array udg_cocoonTargetY
//    real array udg_cocoonTragetX
//    real array udg_cocoonVectorX
//    real array udg_cocoonVectorY
//    unit array udg_cocoon
//    unit array udg_cocoonMissile
//    timer udg_cocoonsTimer
// endglobals

function CocoonTimerCallback takes nothing returns nothing
    local integer i = 0
    local integer j = 0
    local player owner = null
    local real distanceCovered = 0.0
    local real distanceTotal = 0.0
    local real distanceRemaining = 0.0
    local timer t = GetExpiredTimer()
    local real timeout = TimerGetTimeout(t)
    local real x = 0.0
    local real x0 = 0.0
    local real x1 = 0.0
    local real y = 0.0
    local real y0 = 0.0
    local real y1 = 0.0
    local unit missile = null
    local unit spawn = null
    local unit u = null
    local real z = 0.0

    if udg_cocoonsQuantity <= 0 then
        set t = null
	call DestroyTimer(t)
    endif

    loop
        exitwhen i >= udg_cocoonsQuantity
	if IsUnitDeadBJ(udg_cocoon[i]) and null == udg_cocoonMissile[i] then
	    set udg_cocoonsQuantity = udg_cocoonsQuantity - 1

            set udg_cocoonSpawnUnitTypeId[i] = udg_cocoonSpawnUnitTypeId[udg_cocoonsQuantity] 
	    set udg_cocoonSpawnsQuantity[i] = udg_cocoonSpawnsQuantity[i]
            set udg_cocoonUnitTypeId[i] = udg_cocoonUnitTypeId[udg_cocoonsQuantity] 
            set udg_cocoonOwner[i] = udg_cocoonOwner[udg_cocoonsQuantity] 
            set udg_cocoonHatchDelay[i] = udg_cocoonHatchDelay[udg_cocoonsQuantity] 
            set udg_cocoonOriginX[i] = udg_cocoonOriginX[udg_cocoonsQuantity] 
            set udg_cocoonOriginY[i] = udg_cocoonOriginY[udg_cocoonsQuantity] 
            set udg_cocoonTargetX[i] = udg_cocoonTargetX[udg_cocoonsQuantity] 
            set udg_cocoonTargetY[i] = udg_cocoonTargetY[udg_cocoonsQuantity] 
            set udg_cocoonVectorX[i] = udg_cocoonVectorX[udg_cocoonsQuantity] 
            set udg_cocoonVectorY[i] = udg_cocoonVectorY[udg_cocoonsQuantity] 
	    set udg_cocoon[i] = udg_cocoon[udg_cocoonsQuantity] 
            set udg_cocoonMissile[i] = udg_cocoonMissile[udg_cocoonsQuantity] 
 
            set udg_cocoonSpawnUnitTypeId[udg_cocoonsQuantity] = 0 
	    set udg_cocoonSpawnsQuantity[udg_cocoonsQuantity] = 0
            set udg_cocoonUnitTypeId[udg_cocoonsQuantity] = 0 
            set udg_cocoonOwner[udg_cocoonsQuantity] = null 
            set udg_cocoonHatchDelay[udg_cocoonsQuantity] = 0.0 
            set udg_cocoonOriginX[udg_cocoonsQuantity] = 0.0 
            set udg_cocoonOriginY[udg_cocoonsQuantity] = 0.0 
            set udg_cocoonTargetX[udg_cocoonsQuantity] = 0.0 
            set udg_cocoonTargetY[udg_cocoonsQuantity] = 0.0 
            set udg_cocoonVectorX[udg_cocoonsQuantity] = 0.0 
            set udg_cocoonVectorY[udg_cocoonsQuantity] = 0.0 
	    set udg_cocoon[udg_cocoonsQuantity] = null 
            set udg_cocoonMissile[udg_cocoonsQuantity] = null 
	endif 

        set u = udg_cocoon[i]
	set missile = udg_cocoonMissile[i]
	if missile != null then
	    set x0 = udg_cocoonOriginX[i]
	    set y0 = udg_cocoonOriginY[i]
	    set x1 = udg_cocoonTargetX[i]
	    set y1 = udg_cocoonTargetY[i]

	    call SetUnitPosition(missile, GetUnitX(missile) + udg_cocoonVectorX[i]*timeout, GetUnitY(missile) + udg_cocoonVectorY[i]*timeout)
	    set x = GetUnitX(missile)
	    set y = GetUnitY(missile)
	    set distanceTotal = SquareRoot((x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0))
	    set distanceRemaining = SquareRoot((x1 - x)*(x1 - x) + (y1 - y)*(y1 - y)) 
            set distanceCovered = SquareRoot((x - x0)*(x - x0) + (y - y0)*(y - y0))
	    set z = 4*128.0/distanceTotal*distanceRemaining*(distanceCovered/distanceTotal)
	    call SetUnitFlyHeight(missile, z, 0.0)
	    if distanceRemaining <= 64.0 then
	        call RemoveUnit(missile)
		set udg_cocoon[i] = CreateUnit(udg_cocoonOwner[i], udg_cocoonUnitTypeId[i], x1, y1, 225.0)
		set u = udg_cocoon[i]
		call SetUnitUseFood(u, false)
                call UnitAddType(u, UNIT_TYPE_SUMMONED)
                call SetUnitExploded(u, true)
		call PauseUnit(u, true)
	    endif
	endif
       
	if u != null then
            set udg_cocoonHatchDelay[i] = udg_cocoonHatchDelay[i] - timeout
	endif
	if udg_cocoonHatchDelay[i] <= 0.0 and IsUnitAliveBJ(u) then
            set x1 = udg_cocoonTargetX[i]
	    set y1 = udg_cocoonTargetY[i] 
	    call KillUnit(u)
	    set j = 0
	    loop
	        exitwhen j >= udg_cocoonSpawnsQuantity[i]
		set spawn = CreateUnit(udg_cocoonOwner[i], udg_cocoonSpawnUnitTypeId[i], x1, y1, 225.0)
		call SetUnitUseFood(spawn, false)
                call UnitAddType(spawn, UNIT_TYPE_SUMMONED)
                call SetUnitExploded(spawn, true)
		set j = j + 1
            endloop
	endif
	set i = i + 1
    endloop

    set owner = null
    set t = null
    set missile = null
    set spawn = null
    set u = null
endfunction

function CreateSpellEffectCocoon takes unit c, integer cocoon, integer cq, integer spiderling, integer sq, real delay, real x1, real y1, real r returns nothing
    local integer cocoonsQuantity = IMinBJ(IMaxBJ(cq, 1), IMinBJ(128, JASS_MAX_ARRAY_SIZE - udg_cocoonsQuantity - 1))
    local integer i = 0
    local integer j = 0
    local integer spiderlingsQuantity = IMinBJ(IMaxBJ(sq, 1), 64)
    local player p = GetOwningPlayer(c)
    local real hatchDelay = RMaxBJ(1.0, delay)
    local real radius = RMaxBJ(r, 32.0)
    local real x0 = GetUnitX(c)
    local real y0 = GetUnitY(c)
    local unit u = null

    loop
        exitwhen j >= cocoonsQuantity 
	set u = CreateUnit(p, cocoon, x0, y0, bj_UNIT_FACING)
	call SetUnitUseFood(u, false)
	call UnitAddAbility(u, 'Aloc')
	call UnitAddAbility(u, 'Amrf')
	call SetUnitInvulnerable(u, true)
	call SetUnitX(u, x0)
	call SetUnitY(u, y0)
	call PauseUnit(u, true)

	set i = udg_cocoonsQuantity
	set udg_cocoonSpawnUnitTypeId[i] = spiderling
	set udg_cocoonSpawnsQuantity[i] = spiderlingsQuantity
        set udg_cocoonUnitTypeId[i] = cocoon
        set udg_cocoonOwner[i] = p
        set udg_cocoonHatchDelay[i] = hatchDelay
        set udg_cocoonOriginX[i] = x0
        set udg_cocoonOriginY[i] = y0
        set udg_cocoonTargetX[i] = x1 + radius*Cos(I2R(i)*(360.0/I2R(cocoonsQuantity)*bj_DEGTORAD))
        set udg_cocoonTargetY[i] = y1 + radius*Sin(I2R(i)*(360.0/I2R(cocoonsQuantity)*bj_DEGTORAD)) 
        set udg_cocoonVectorX[i] = (udg_cocoonTargetX[i] - x0)/radius*1100.0
        set udg_cocoonVectorY[i] = (udg_cocoonTargetY[i] - y0)/radius*1100.0
        set udg_cocoon[i] = null
        set udg_cocoonMissile[i] = u
	set udg_cocoonsQuantity = udg_cocoonsQuantity + 1
	set j = j + 1
    endloop
   
    if null == udg_cocoonsTimer or 0 == TimerGetTimeout(udg_cocoonsTimer) then
        set udg_cocoonsTimer = CreateTimer() 
        call TimerStart(udg_cocoonsTimer, 0.05, true, function CocoonTimerCallback)
    endif

    set p = null
    set u = null
endfunction

function CreateSpellEffectCocoonDefault takes unit caster returns nothing
    call CreateSpellEffectCocoon(caster, udg_COCOON_UNITTYPEID, udg_COCOON_QUANTITY, udg_COCOON_SPAWN_UNITTYPEID, udg_COCOON_SPAWN_QUANTITY, udg_COCOON_DELAY, GetUnitX(caster), GetUnitY(caster), udg_COCOON_OFFSET)
endfunction
Настраивается с помощью аргументов к функции, а не глобалок. В карте которую прикрепляю есть пример. Это позволяет иметь разные конфигурации заклинания в одной карте. Например, разные цвета коконов или разные по силе паучки, в зависимости от паучихи.
Как импортировать. Включите копирование глобальных переменных в редакторе. Скопируйте триггер. Удостоверьтесь что все глобальные переменные последовали. Скопируйте скрипт JASS в скрипт карты (корень дерева триггеров). Настройка производится либо передачей аргументов "вручную", либо изменением глобальных переменных, которые начинаются с "COCOON_...". Все что начинаются с малых литер должны оставаться неприкасаемыми.
COCOON_DELAY - задержка перед появлением паучков, секунд.
COCOON_OFFSET - растояние от паучихи до кокона.
COCOON_QUANTITY - количество коконов за применение способности.
COCOON_SPAWN_QUANTITY - количество паучков.
COCOON_SPAWN_UNITTYPEID - тип юнита паучка.
COCOON_UNITTYPEID - тип юнита кокона.
Если у кого проблемы с этой версией заклинания, вот ещё одна для русской 1.26а.
Загруженные файлы
4
22
5 лет назад
Отредактирован Zahanc
4

» Освободители / Главная страница

Сыграл. В целом, нормально. Посмеялся над иконками из Казаков и Героев.
Мне кажется нужно больше особенностей. К примеру я считаю что нужно пойти дальше с улучшениями. Если один игрок улучшает войска, то это улучшение распространяется на оба лагеря.
Понравились переменные режимы стрельбы мортир.
FPS rate был низок.
Игра довольно простая. Я предлагаю убрать жёлтых сторожей с дорог вовсе. Или оставить, скажем, двух пехотинцев. Вместо этого, дать игрокам вызвать подкрепление, скажем один раз на этом этапе. Возможно дать предмет, боевой рожок с одним зарядом, как способ это представить.
0
22
5 лет назад
0

» Осквернитель / Главная страница

Сегодня-завтра размещу первую главу для открытого тестирования.
0
22
5 лет назад
0

» WarCraft 3 / Странное поведение AI script

У меня были такие проблемы с 1.27 тоже.
0
22
5 лет назад
0

» WarCraft 3 / Получение точки применения способности ?

Да, он остался в памяти потому что он нужен в другой функции: SCOnDeathCallback
И затем удаляется когда он больше не нужен.
Попрошу модератора удалить оффтопик.
0
22
5 лет назад
0

» WarCraft 3 / Получение точки применения способности ?

Нет, не забыл. SCTimerExpirationCallback
0
22
5 лет назад
0

» WarCraft 3 / Получение точки применения способности ?

Каков контекст у этого всего? Буквально вчера написал заклинание AoE на точке.
/* SpellContaminate.j 1.0 */
globals
  constant integer CONTAMINATE = 'A601'
  constant integer CONTAMINATE_SUMMON = 'nvdl'
  constant real CONTAMINATE_AOE = 200.0
  constant real CONTAMINATE_DURATION = 16.0
  constant real CONTAMINATE_SUMMON_DURATION = 60.0
  constant real CONTAMINATE_UPDATE_TIMER_TIMEOUT = 2.0
  constant string CONTAMINATE_EFFECT = "Abilities\\Spells\\Undead\\UnholyAura\\UnholyAura.mdl"

  integer SCQuantity = 0
  effect array SCEffect
  integer array SCLevel
  location array SCLoc
  player array SCOwner 
  timer array SCTimerExpiration
endglobals

function SCOnDeathFilter takes nothing returns boolean
  local boolean isConvertable = false
  local unit u = GetDyingUnit()
  set isConvertable = not IsUnitType(u, UNIT_TYPE_UNDEAD) and not IsUnitType(u, UNIT_TYPE_MECHANICAL)
  return isConvertable and (SCQuantity > 0)
endfunction

function SCOnDeathCallback takes nothing returns nothing
  local integer i = 0
  local unit f = null
  local unit u = GetTriggerUnit()
  local location loc = GetUnitLoc(u)

  /* In case there are overlaping Contamination zones,
  make sure only one summon is created.
  Moreover, make sure only the oldest zone takes effect.*/
  loop
    exitwhen i >= SCQuantity or (f != null) 
    if DistanceBetweenPoints(loc, SCLoc[i]) <= (CONTAMINATE_AOE / 2 + CONTAMINATE_AOE / 2 * I2R(SCLevel[i])) then
      set f = CreateUnitAtLoc(SCOwner[i], CONTAMINATE_SUMMON, loc, GetUnitFacing(u))
      call SetUnitUseFood(f, false)
      call UnitAddType(f, UNIT_TYPE_SUMMONED)
      call UnitAddType(f, UNIT_TYPE_UNDEAD)
      call UnitApplyTimedLife(f, 'BTLF', CONTAMINATE_SUMMON_DURATION)
      call SetUnitExploded(f, true)

      call DestroyEffect(AddSpecialEffectLoc(CONTAMINATE_EFFECT, loc))
    endif
    set i = i + 1
  endloop

  call RemoveLocation(loc)
  set f = null
  set loc = null
  set u = null
endfunction

function SCOnCastFilter takes nothing returns boolean
  return CONTAMINATE == GetSpellAbilityId() 
endfunction

function SCTimerExpirationCallback takes nothing returns nothing
  local integer i = 0
  local timer t = GetExpiredTimer()
  local integer j = 0
  loop
    exitwhen i >= SCQuantity
    if t == SCTimerExpiration[i] then
      call RemoveLocation(SCLoc[i])
      call DestroyTimer(SCTimerExpiration[i])
      call DestroyEffect(SCEffect[i])

      /* Pull other instances down the stack,
      to preserve the creation order,
      that is relevant in resolving application conflicts. */
      set j = i + 1
      loop
        exitwhen j >= SCQuantity
	set SCEffect[j - 1] = SCEffect[j]
	set SCLevel[j - 1] = SCLevel[j]
	set SCLoc[j - 1] = SCLoc[j]
	set SCOwner[j - 1] = SCOwner[j]
	set j = j + 1
      endloop
      /* Accessing out of array size elements terminates the game,
      instead of returning null,
      hence the ugly patch that follows. */
      set SCQuantity = SCQuantity - 1
      set SCEffect[SCQuantity] = null
      set SCLevel[SCQuantity] = 0
      set SCLoc[SCQuantity] = null
      set SCOwner[SCQuantity] = null

      set t = null
      /* Assume each timer in the array is unique. */
      return
    endif
    set i = i + 1
  endloop
endfunction

function SCOnCastCallback takes nothing returns nothing
  local unit c = GetSpellAbilityUnit()
  local integer i = SCQuantity
  local location loc = null

  if i >= JASS_MAX_ARRAY_SIZE then
    return
  endif

  set loc = GetSpellTargetLoc()
  set SCEffect[i] = AddSpecialEffectLoc(CONTAMINATE_EFFECT, loc)
  set SCLoc[i] = loc
  set SCOwner[i] = GetOwningPlayer(c)
  set SCLevel[i] = GetUnitAbilityLevel(c, CONTAMINATE)
  set SCTimerExpiration[i] = CreateTimer()
  call TimerStart(SCTimerExpiration[i], CONTAMINATE_DURATION, false, function SCTimerExpirationCallback)

  set SCQuantity = SCQuantity + 1

  set c = null
  set loc = null
endfunction

function initSpellContaminate takes nothing returns nothing
  local trigger t = CreateTrigger()
  local trigger t2 = CreateTrigger()

  call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_CAST)
  call TriggerAddCondition(t, Condition(function SCOnCastFilter))
  call TriggerAddAction(t, function SCOnCastCallback)

  call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_DEATH)
  call TriggerAddCondition(t2, Condition(function SCOnDeathFilter))
  call TriggerAddAction(t2, function SCOnDeathCallback)

  set t = null
  set t2 = null
endfunction
/* end SpellContaminate.j */
  call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_CAST)
  call TriggerAddCondition(t, Condition(function SCOnCastFilter))
  call TriggerAddAction(t, function SCOnCastCallback)
...
  set loc = GetSpellTargetLoc()
Хотя мне казалось что заклинания которые юнит поддерживает (channeling) тоже запускают "EVENT_PLAYER_UNIT_SPELL_CAST".
3
22
5 лет назад
Отредактирован Zahanc
3

» WarCraft 3 / Получение точки применения способности ?

constant native GetSpellTargetLoc           takes nothing returns location
native GetLocationX             takes location whichLocation returns real
native GetLocationY             takes location whichLocation returns real
0
22
5 лет назад
Отредактирован Zahanc
0

» WarCraft 3 / Странное поведение AI script

Значит они в атакующей группе. Я думал что может они остаются потому что количество юнитов в атакующей группе превышает 12, но перечитав скрипт не вижу такой проблемы.
+
О, они точно производятся ИИ? Или они создаются при инициализации карты?
+
Попробуйте ещё поменять количество начальных ресурсов, может быть. Я уже просто угадываю к этому моменту.
0
22
5 лет назад
0

» WarCraft 3 / Странное поведение AI script

Но они есть среди атакующих и "стражников". Может они просто стоят там и ждут своей очереди или что-то в этом роде? Хотя мне все ещё кажется что это скорее ошибка обновления.
По главному вопросу, я сам так и не нашел решения. Вероятно это ошибка в коде по ту сторону API. У меня были куда более странные проблемы.
Могу разве что посоветовать разделить базу на несколько владельцев.
0
22
5 лет назад
0

» WarCraft 3 / Странное поведение AI script

Да я тоже сталкивался с тем что ИИ посылает защитников в атаку. Насколько я смог понять это из-за того что ему кажется что его база под угрозой.
Никогда не сталкивался с лишними юнитами в защите, впрочем. Может просто не обновили скрипт в карте как полагается?
0
22
5 лет назад
0

» WarCraft 3 / Проблема с изменением архива кампании с Ladik's MPQ Editor.

Да действительно. Ladik's не создаёт необходимых записей в war3campaign.imp.
Может кто помочь с написанием Batch скрипта, который бы заполнял war3campaign.imp основываясь на дереве папок и файлов?
+ Впрочем, чем утруждаться со скриптами проще добавить записи в WE "вручную".
0
22
5 лет назад
0

» WarCraft 3 / Проблема с изменением архива кампании с Ladik's MPQ Editor.

listfile, да. На вид он тоже в порядке. Поэтому я спрашиваю есть ли какая-то ловушка с форматом listfile. Вроде порядка перечисления файлов.
2
22
5 лет назад
2

» WarCraft 3 / Проблема с изменением архива кампании с Ladik's MPQ Editor.

PT153,
Я думал это распространяется только на архивы игры, а не карты и кампании.
Я имею ввиду, об CASC говорят как о другом формате. Однако я мог открыть *.w3n как обычно.
0
22
5 лет назад
0

» WarCraft 3 / Ошибка при выборе рандомного игрока (Jass)

Это пример а не готовая наработка.
0
22
5 лет назад
0

» WarCraft 3 / Ошибка при выборе рандомного игрока (Jass)

Кстати есть функция ForcePickRandomPlayer. Например
function forceUsersFilter takes nothing returns boolean
  return PLAYER_SLOT_STATE_PLAYING == GetPlayerSlotState(GetFilterPlayer()) and MAP_CONTROL_USER == GetPlayerController(GetFilterPlayer())
endfunction

function getRandomPlayer takes nothing returns player
  local force f = CreateForce()
  call ForceEnumPlayers(f, Condition(forceUsersFilter))
  return ForcePickRandomPlayer(f)
endfunction
Не проверял.
0
22
5 лет назад
0

» WarCraft 3 / Ошибка при выборе рандомного игрока (Jass)

Были ли проверки в многопользовательском режиме? Может компьютер просто находит лишь одного играющего человека в однопользовательском режиме.
И что такое udg_AccEmpPlayer?
0
22
5 лет назад
0

» WarCraft 3 / Подскажите как проще всего написать рандом >покупку< героя

Я не знал про приём с умножением. Как это называется и как это работает?
И наверное это N*X - 1 а не N*X - N.
1
22
5 лет назад
1

» WarCraft 3 / Дамми спелл по типу "Буран"

Data - Options: Visible, Targeting Image
Data - Target Type: Point Target
Stats - Area of Effect: 200.0
Прикрепляю пример. Могу сделать периодический урон тоже если нужно.
Загруженные файлы
0
22
5 лет назад
0

» WarCraft 3 / Модель - странная штука. Вроде работает, а вроде и нет...

Используется ли модель как декорация? Если да, установлены ли вариации декорации в РО? В таком случае уберите вариации. Как основу используйте декорацию без вариаций, как указательный знак или факел.
5
22
5 лет назад
Отредактирован Zahanc
5

» XGM Конкурсы / Warcraft 3 Custom Campaign Contest 2019

На создание Pit Lord, кампанию из двух карт, у меня ушел ровно месяц. Я занимался кампанией приблизительно 4 часа в день. Сообщаю чтобы участники могли соотнести себя.
Мне интересно посмотреть что получится. Поигрываю иногда в пользовательские кампании. Меня удручает что у девяти из десяти очень низкий уровень производства. Казалось бы, за пятнадцать лет можно было научиться, ан нет.
0
22
5 лет назад
0

» WarCraft 3 / ИИ использование способностей

Можно попробовать написать *.ai скрипт пустышку, как для кампаний. В конце концов должен же был компьютер уметь использовать Рёв в кампании.
2
22
5 лет назад
2

» WarCraft 3 / Дамми спелл по типу "Буран"

Это возможно. Нужно выставить нужные галки в одном из параметров "Канала" и удостовериться что установлен достаточно большой радиус действия.
Однако на сколько я помню невозможно затем в скрипте отследить всех юнитов которые попали в область. Придется самому считать от центра применения способности.
0
22
5 лет назад
0

» Повелитель Бездны / Главная страница

Обновлю по крайней мере английскую версию в феврале. Если дело пойдет гладко, то и русскую версию тоже.
0
22
5 лет назад
0

» WarCraft 3 / Галерея скриншотов ландшафта

Очередная карта для WarCraft 3
Да, на снимках почти ничего не видно. Они здесь лишь как повод чтобы задать вопрос.
Как сделать классический уровень приятным? Такой уровень будет содержать обычные воду и утёсы. Я сам могу додуматься добавить густой туман и парочку новых декораций. И да, я читал статью Шурика и пару книжек на эту тему. Что ещё? Какова программа минимум для классического уровня?
BranaR,
Грубоватый интерфейс портит всё впечатление. Проходящие сквозь друг друга колонны на первом снимке и на некоторых других слегка не к месту мне кажется. Хотя это только мне так кажется, возможно.
В остальном, впечатляюще.