• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!
  • ✅ The POLL for Hive's Texturing Contest #34 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!
  • ✅ The POLL for Hive's Techtree Contest #20 is OPEN! Vote for the TOP 3 FACTIONS! 🔗Click here to cast your vote!

Tech Tree Requirements & Research Level Requirements Dummy Unit Fixes

Level 2
Joined
Jul 15, 2023
Messages
4
I came across this specific thread

Hey all, so I've run into a little problem with my map. Instead of the townhall upgrading to keep upgrading to a castle and whatnot to advance to the next tech level in my map, I have a research that advances the tech level. It goes Age of Enlightenment, Age of Magic and Age of Wonders. Now that that's out of the way, my problem is this: The armor and damage upgrades for my units also have multiple levels, which each level requiring an advancement to the next age. The problem is, it works for the level that requires Age of Enlightenment, but I'm able to advance to the next levels of my armor and damage upgrades without advancing to the Age of Magic and the Age of Wonders. I've added values to the level requirements for each level of my armor and damage upgrades, but it doesn't seem to work. Is it bugged, or am I missing something? It works fine for a tech that's only one level that requires the Age of Wonders or something, but it just doesn't work with these techs that have multiple levels.
by SerenityInFire

An issue 6 years ago. I wanted to clarify for those looking for help since that forum is closed. Using a Dummy Unit is extremely versatile when interacting with requirements inside the game. If you are smart enough you can use it for all tech tree requirements fake tier upgrades and even hero level ability requirements.
JASS:
library AbilityLevelRequirements initializer Init requires Table, BeastmasterAura

globals
    private constant integer UNLOCK_COUNT = 3

    private constant integer array UNLOCK_HERO_ID
    private constant integer array UNLOCK_LEVEL
    private constant integer array UNLOCK_DUMMY_ABIL
    private constant integer array UNLOCK_REAL_ABIL

    // Global array for accessing the dummy unlock unit: indexed by player id
    unit array StampedeDummy
    private constant integer STAMPEDE_UNIT_ID = 'e00P' // Dummy unit rawcode for Stampede unlock
endglobals

private function SetupRequirements takes nothing returns nothing
    set UNLOCK_HERO_ID[0] = 'N015'
    set UNLOCK_LEVEL[0]   = 5
    set UNLOCK_DUMMY_ABIL[0] = 'A06N'
    set UNLOCK_REAL_ABIL[0]  = 'A06L'

    set UNLOCK_HERO_ID[1] = 'N015'
    set UNLOCK_LEVEL[1]   = 2
    set UNLOCK_DUMMY_ABIL[1] = 'A06O'
    set UNLOCK_REAL_ABIL[1]  = 'A063'

    set UNLOCK_HERO_ID[2] = 'N015'
    set UNLOCK_LEVEL[2]   = 6
    set UNLOCK_DUMMY_ABIL[2] = 'A06R'
    set UNLOCK_REAL_ABIL[2]  = 'A06Q'
endfunction

// === Dummy Creation Helper ===
function StampedeDummy_CreateForPlayer takes player p returns nothing
    local integer pid = GetPlayerId(p)
    if StampedeDummy[pid] == null or not UnitAlive(StampedeDummy[pid]) then
        set StampedeDummy[pid] = CreateUnit(p, STAMPEDE_UNIT_ID, 0., 0., 0.)
        call ShowUnit(StampedeDummy[pid], false)
        call SetUnitInvulnerable(StampedeDummy[pid], true)
        call UnitAddAbility(StampedeDummy[pid], 'Aloc') // Locust to make untargetable
    endif
endfunction

function AbilityUnlock_CheckAllForUnit takes unit u returns nothing
    local integer i = 0
    local integer utype = GetUnitTypeId(u)
    local integer level
    loop
        exitwhen i >= UNLOCK_COUNT
        if utype == UNLOCK_HERO_ID[i] then
            set level = GetHeroLevel(u)
            if level >= UNLOCK_LEVEL[i] then
                // Remove dummy if present
                if GetUnitAbilityLevel(u, UNLOCK_DUMMY_ABIL[i]) > 0 then
                    call UnitRemoveAbility(u, UNLOCK_DUMMY_ABIL[i])
                endif
                // Add real ability if not present
                if GetUnitAbilityLevel(u, UNLOCK_REAL_ABIL[i]) == 0 then
                    call UnitAddAbility(u, UNLOCK_REAL_ABIL[i])
                    if UNLOCK_REAL_ABIL[i] == 'A06L' then
                        call BeastmasterAura_RegisterRexxar(u)
                    endif
                endif
            else
                // If below unlock level, ensure dummy present and real gone
                if GetUnitAbilityLevel(u, UNLOCK_REAL_ABIL[i]) > 0 then
                    call UnitRemoveAbility(u, UNLOCK_REAL_ABIL[i])
                endif
                if GetUnitAbilityLevel(u, UNLOCK_DUMMY_ABIL[i]) == 0 then
                    call UnitAddAbility(u, UNLOCK_DUMMY_ABIL[i])
                endif
            endif
        endif
        set i = i + 1
    endloop
endfunction

private function OnHeroLevel takes nothing returns nothing
    call AbilityUnlock_CheckAllForUnit(GetTriggerUnit())
endfunction

private function OnUnitEnter takes nothing returns nothing
    local unit u = GetEnteringUnit()
    if IsUnitType(u, UNIT_TYPE_HERO) then
        call AbilityUnlock_CheckAllForUnit(u)
        if GetUnitTypeId(u) == 'N015' then // Beastmaster/Rexxar
            call StampedeDummy_CreateForPlayer(GetOwningPlayer(u))
        endif
    endif
    set u = null
endfunction

private function OnStart takes nothing returns nothing
    local integer i = 0
    local group g
    local unit u
    loop
        exitwhen i >= bj_MAX_PLAYER_SLOTS
        set g = CreateGroup()
        call GroupEnumUnitsOfPlayer(g, Player(i), null)
        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            if IsUnitType(u, UNIT_TYPE_HERO) then
                call AbilityUnlock_CheckAllForUnit(u)
                if GetUnitTypeId(u) == 'N015' then
                    call StampedeDummy_CreateForPlayer(Player(i))
                endif
            endif
            call GroupRemoveUnit(g, u)
        endloop
        call DestroyGroup(g)
        set i = i + 1
    endloop
endfunction

private function Init takes nothing returns nothing
    local trigger trgLevel = CreateTrigger()
    local trigger trgEnter = CreateTrigger()
    local trigger trgStart = CreateTrigger()
    call SetupRequirements()
    call TriggerRegisterAnyUnitEventBJ(trgLevel, EVENT_PLAYER_HERO_LEVEL)
    call TriggerAddAction(trgLevel, function OnHeroLevel)
    call TriggerRegisterEnterRectSimple(trgEnter, GetPlayableMapRect())
    call TriggerAddAction(trgEnter, function OnUnitEnter)
    call TriggerRegisterTimerEventSingle(trgStart, 0.01)
    call TriggerAddAction(trgStart, function OnStart)
endfunction

endlibrary
 
Back
Top