HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Leaver Players Screw Hero Revives?

09-12-2006, 11:45 AM#1
Rising_Dusk
Collapse JASS:
//***************************************************************************************************************
//*This trigger is what allows heros to revive when killed.
//*
//****************************************************

function Hero_Revive_Conditions takes nothing returns boolean
    return (IsUnitType(GetDyingUnit(), UNIT_TYPE_HERO) and GetOwningPlayer(GetDyingUnit()) != Player(13) and GetOwningPlayer(GetDyingUnit()) != Player(14))
endfunction

function Hero_Revive_UnInvul takes nothing returns nothing
    local integer k = H2I(GetExpiredTimer())
    local unit u = GetUnit(I2Timer(k), "u")
    call SetUnitInvulnerable(u, false)
    call FlushLocals(I2Timer(k))
    call PauseTimer(I2Timer(k))
    call DestroyTimer(I2Timer(k))
    set u = null
endfunction

function Hero_Revive_Actual takes nothing returns nothing
    local integer i = H2I(GetExpiredTimer())
    local integer k = H2I(CreateTimer())
    local timerdialog window = GetTimerDialog(I2Timer(i), "window")
    local unit u = GetUnit(I2Timer(i), "hero")
    local unit s
    local unit dummy = GetUnit(I2Timer(i), "dummy")
    local player pu = GetOwningPlayer(u)
    local group g
    local real x
    local real y
    
    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Items\\TomeOfRetraining\\TomeOfRetrainingCaster.mdl", GetUnitX(dummy), GetUnitY(dummy)))
    call RemoveUnit(dummy)
    if IsUnitInForce(u, udg_HallowedOrder) then
        set x = 8250
        set y = 3850
    elseif IsUnitInForce(u, udg_BaneOfEternity) then
        set x = -8300
        set y = -4800
    endif
    call ShowUnit(u, true)
//********************************************
//*This is where all of my debugs and tests show it gets to.
//*It appears to explode and not go past this point if the
//*owner of the hero being revived has left the game.
//*
    call ReviveHero(u, x, y, false)
    if GetLocalPlayer() == GetOwningPlayer(u) then
        call PanCameraTo(x, y)
        call SetCameraPosition(x, y)
        call SetCameraQuickPosition(x, y)
        call ClearSelection()
        call SelectUnit(u, true)
    endif
    
    call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MAX_MANA))
    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Items\\TomeOfRetraining\\TomeOfRetrainingCaster.mdl", GetUnitX(u), GetUnitY(u)))
    call PauseTimer(I2Timer(i))
    call DestroyTimer(I2Timer(i))
    call DestroyTimerDialog(window)

    call SetUnitInvulnerable(u, true)
    call SetHandle(I2Timer(k), "u", u)
    call TimerStart(I2Timer(k), 1.0, false, function Hero_Revive_UnInvul)
    
    set window = null
    set dummy = null
    set g = null
    set s = null
    set u = null
endfunction

function Hero_Revive_Actions takes nothing returns nothing
    local timerdialog window 
    local unit u = GetDyingUnit()
    local unit s
    local unit dummy
    local unit visib
    local string heroname = GetProperName(u)
    local real duration
    local integer level = GetHeroLevel(u)
    local integer pu = GetPlayerId(GetOwningPlayer(u))
    local group g
    
    set udg_ReviveTimer[pu] = CreateTimer()
    set window = CreateTimerDialog(udg_ReviveTimer[pu])
    call TimerDialogSetTitle(window, heroname + " Revive")
    call TimerDialogDisplay(window, true)
    if IsMapFlagSet(MAP_RANDOM_RACES) and not bj_isSinglePlayer then
        set duration = (2.0*level)
    else
        set duration = (4.0*level)
    endif
    if u != udg_u_Greel and u != udg_u_Jhita then
        set dummy = CreateUnit(Player(15), GetUnitTypeId(u), GetUnitX(u), GetUnitY(u), GetUnitFacing(u))
        call SetUnitAnimation(dummy, "death")
        call AddHeroEffects(u, dummy)
        call ShowUnit(u, false)
    else
        set dummy = CreateUnit(Player(15), 'H01S', GetUnitX(u), GetUnitY(u), GetUnitFacing(u))
        call SetUnitAnimation(dummy, "birth")
    endif
    set visib = CreateUnit(Player(pu), VisibilityDummy(), GetUnitX(u), GetUnitY(u), 0)
    call UnitApplyTimedLife(visib, 'BTLF', duration)
    call SetHeroLevel(dummy, GetHeroLevel(u), false)
    call UnitAddAbility(dummy, 'Aloc')
    call UnitAddAbility(dummy, 'Avul')
    call PauseUnit(dummy, true)
    
    call SetHandle(dummy, "h_base", u)
    call SetHandle(udg_ReviveTimer[pu], "window", window)
    call SetHandle(udg_ReviveTimer[pu], "hero", u)
    call SetHandle(udg_ReviveTimer[pu], "dummy", dummy)
    call TimerStart(udg_ReviveTimer[pu], duration, false, function Hero_Revive_Actual)
    
    set window = null
    set dummy = null
    set visib = null
    set u = null
    set s = null
    set g = null
endfunction

Comments in the code explain it all.
I've added every bit of it (Except the InitTrig, I know that works).

I swear I can't figure this out for the life of me.
And it's kind of a big deal. :/

Any help would be appreciated!
09-12-2006, 01:29 PM#2
blu_da_noob
One thing I didn't think about last night: check your player leaves trigger. Try disabling it to make sure that it isn't causing this in some way.
09-12-2006, 02:36 PM#3
Naakaloh
Is there any issue with trying to use the functions for a player locally while they are no longer in the game?
09-14-2006, 03:18 AM#4
Rising_Dusk
Quote:
One thing I didn't think about last night: check your player leaves trigger. Try disabling it to make sure that it isn't causing this in some way.

That's a potential idea, but I'm actually quite limited in testing this.
I mean, I need another actual player in-game that leaves and then dies.

It's a good idea to check the player leaves trigger though.
I'll do that right now.

=========================================================

I wanted to update this and mention that Blu was correct yet again.
The issue was that I was removing a player from its force when they leave, and the revive trigger checks the force of the owner of the hero to get the coordinates, causing it to try to revive a hero at an unitialized x/y.

Thanks again Blu, and Naak. :D