• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Trigger] Replace function

Status
Not open for further replies.

Ardenaso

HD Model Reviewer
Level 33
Joined
Jun 22, 2013
Messages
1,814
help.png


Promote is an ability where Renault Mograine heals a targeted Footman for 40pl hit points and converts it into a Captain but for some reason when I test the ability, only the heal function works; did I miss something?
 
It might be replacing the unit before the heal effect kicks in. Is the healing done by the Promote spell itself? If so you might want to do the healing with triggers, like so:
  • Unit - Set life of (Target unit of ability being cast) to ((Life of (Target unit of ability being cast)) + 50.00)
PS: Have you checked if your dummy has the mana to cast Promote?
 
The way replace works is that the game stores whatever values it needs like health and unit coordinates, removes the current one and creates a new unit where the one was. This newly created unit is tagged as the (last replaced unit) and all the previously stored values are applied. If you created an effect on the Scarlet Crusader, that effect goes away with it. You should probably create it after the unit was replaced.
 
Last edited:
Level 8
Joined
Jun 13, 2010
Messages
344
You should really get used to put variables for all units and points. At some point you'll be making a trigger which bugs, due to another active trigger and it will take ages to find a solution for. Better to be cutting edge - but that's just my opinion.

To your post, maybe do like the other guys suggested and use triggers for the heal. Additionally, maybe make the heal affect the unit after the replacement, given the fact that if the Captain unit will have more max hp, it will be healed more efficiently. Just a thought. Also then add the special effects with a trigger and then next remove last created special effect. Will make it play but not store data.

Hope it helps or that your question was solved in any case. :)
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
For people interested in how the GUI replace unit function works here is the underlying function that is called.
JASS:
function ReplaceUnitBJ takes unit whichUnit,integer newUnitId,integer unitStateMethod returns unit
    local unit    oldUnit = whichUnit
    local unit    newUnit
    local boolean wasHidden
    local integer index
    local item    indexItem
    local real    oldRatio
    if (oldUnit == null) then
        set bj_lastReplacedUnit = oldUnit
        return oldUnit
    endif
    set wasHidden = IsUnitHidden(oldUnit)
    call ShowUnit(oldUnit, false)
    if (newUnitId == 'ugol') then
        set newUnit = CreateBlightedGoldmine(GetOwningPlayer(oldUnit), GetUnitX(oldUnit), GetUnitY(oldUnit), GetUnitFacing(oldUnit))
    else
        set newUnit = CreateUnit(GetOwningPlayer(oldUnit), newUnitId, GetUnitX(oldUnit), GetUnitY(oldUnit), GetUnitFacing(oldUnit))
    endif
    if (unitStateMethod == bj_UNIT_STATE_METHOD_RELATIVE) then
        if (GetUnitState(oldUnit, UNIT_STATE_MAX_LIFE) > 0) then
            set oldRatio = GetUnitState(oldUnit, UNIT_STATE_LIFE) / GetUnitState(oldUnit, UNIT_STATE_MAX_LIFE)
            call SetUnitState(newUnit, UNIT_STATE_LIFE, oldRatio * GetUnitState(newUnit, UNIT_STATE_MAX_LIFE))
        endif
        if (GetUnitState(oldUnit, UNIT_STATE_MAX_MANA) > 0) and (GetUnitState(newUnit, UNIT_STATE_MAX_MANA) > 0) then
            set oldRatio = GetUnitState(oldUnit, UNIT_STATE_MANA) / GetUnitState(oldUnit, UNIT_STATE_MAX_MANA)
            call SetUnitState(newUnit, UNIT_STATE_MANA, oldRatio * GetUnitState(newUnit, UNIT_STATE_MAX_MANA))
        endif
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_ABSOLUTE) then
        call SetUnitState(newUnit, UNIT_STATE_LIFE, GetUnitState(oldUnit, UNIT_STATE_LIFE))
        if (GetUnitState(newUnit, UNIT_STATE_MAX_MANA) > 0) then
            call SetUnitState(newUnit, UNIT_STATE_MANA, GetUnitState(oldUnit, UNIT_STATE_MANA))
        endif
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_DEFAULTS) then
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_MAXIMUM) then
        call SetUnitState(newUnit, UNIT_STATE_LIFE, GetUnitState(newUnit, UNIT_STATE_MAX_LIFE))
        call SetUnitState(newUnit, UNIT_STATE_MANA, GetUnitState(newUnit, UNIT_STATE_MAX_MANA))
    else
    endif
    call SetResourceAmount(newUnit, GetResourceAmount(oldUnit))
    if (IsUnitType(oldUnit, UNIT_TYPE_HERO) and IsUnitType(newUnit, UNIT_TYPE_HERO)) then
        call SetHeroXP(newUnit, GetHeroXP(oldUnit), false)
        set index = 0
        loop
            set indexItem = UnitItemInSlot(oldUnit, index)
            if (indexItem != null) then
                call UnitRemoveItem(oldUnit, indexItem)
                call UnitAddItem(newUnit, indexItem)
            endif
            set index = index + 1
            exitwhen index >= bj_MAX_INVENTORY
        endloop
    endif
    if wasHidden then
        call KillUnit(oldUnit)
        call RemoveUnit(oldUnit)
    else
        call RemoveUnit(oldUnit)
    endif
    set bj_lastReplacedUnit = newUnit
    return newUnit
endfunction

To summarize...

The original unit is destroyed and a new unit is created so all variables referencing that old unit now reference a removed unit and not the replacement so have to be updated after the function call. Items and basic unit properties are copied to the replacement unit. Abilities, trigger added abilities, tome effects and anything related to those are not copied so are lost completely. The function leaks a handle reference count for any item in slot 6 of a replaced unit due to a JASS bug, hopefully this will one day be fixed though.
 
Status
Not open for further replies.
Top