HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

criticism of dispenser code

12-05-2008, 04:09 AM#1
fX_
i made this code for my map. it allows players to 'browse' through a shop/dispenser - a unit - by attributing to it different 'pages'. each page is actually a different unit that replaces the old one. works with item vendors, mercenary camps, hero taverns, etc.
each player for which the dispenser is enabled is able to interact with his 'face'-dispenser only; so that multiple players can browse the 'shop' at different pages simulatenously.
...dunno about how to apply item cooldown for all other players when one player buys it at his 'face'... suggestions?

it only requires 2 abilities - both based-of any non-targetable ability.

criticism?

Collapse JASS:
library DynamicDispenser initializer test

globals
    private constant integer PREVIOUS_PAGE_ABILITY_ID = 'A006'

    private constant integer NEXT_PAGE_ABILITY_ID = 'A007'

    private constant boolean FLIP_TO_OTHER_END = false
endglobals

struct DynamicDispenser

    private real rX
    private real rY
    private real rFacing
    private integer array intPageUnitId[10]
    private integer intCountPage = 1
    private unit array uFace[16]
    private player array p[16]
    private integer intCountFace = 0
    private integer array intPageIndex[16]

    public static method Create takes integer prime, real x, real y, real facing returns DynamicDispenser
        local DynamicDispenser New = DynamicDispenser.allocate()

        set New.rX = x
        set New.rY = y
        set New.rFacing = facing
        set New.intPageUnitId[0] = prime

        set New.intInstIndex = DynamicDispenser.intCountInst
        set DynamicDispenser.Inst[DynamicDispenser.intCountInst] = New
        set DynamicDispenser.intCountInst = DynamicDispenser.intCountInst + 1
        
        return New
    endmethod

    public method Destroy takes nothing returns nothing
        loop
            exitwhen .intCountFace == 0
            call GroupRemoveUnit(DynamicDispenser.ugDispenser, .uFace[.intCountFace])
            call RemoveUnit(.uFace[.intCountFace])
            set .uFace[.intCountFace] = null
            set .p[.intCountFace] = null
            set .intCountFace = .intCountFace - 1
        endloop

        set DynamicDispenser.intCountInst = DynamicDispenser.intCountInst - 1
        set DynamicDispenser.Inst[DynamicDispenser.intCountInst].intInstIndex = .intInstIndex
        set DynamicDispenser.Inst[.intInstIndex] = DynamicDispenser.Inst[DynamicDispenser.intCountInst]
        set DynamicDispenser.Inst[DynamicDispenser.intCountInst] = 0
    endmethod

    public method SetPosition takes real x, real y, real facing returns nothing
        local integer INT_Index = 0

        set .rX = x
        set .rY = y
        set .rFacing = facing
        
        loop
            exitwhen INT_Index == .intCountFace
            call SetUnitX(.uFace[INT_Index], .rX)
            call SetUnitY(.uFace[INT_Index], .rY)
            call SetUnitFacing(.uFace[INT_Index], .rFacing)
            set INT_Index = INT_Index + 1
        endloop        
    endmethod

    public method EnableForPlayer takes player p returns nothing
        set .p[.intCountFace] = p

        set .intPageIndex[.intCountFace] = 0
        set .uFace[.intCountFace] = CreateUnit(p, .intPageUnitId[.intPageIndex[.intCountFace]], .rX, .rY, .rFacing)
        if GetUnitAbilityLevel(.uFace[.intCountFace], PREVIOUS_PAGE_ABILITY_ID) == 0 then
            call UnitAddAbility(.uFace[.intCountFace], PREVIOUS_PAGE_ABILITY_ID)
        endif
        if GetUnitAbilityLevel(.uFace[.intCountFace], NEXT_PAGE_ABILITY_ID) == 0 then
            call UnitAddAbility(.uFace[.intCountFace], NEXT_PAGE_ABILITY_ID)
        endif
        call GroupAddUnit(DynamicDispenser.ugDispenser, .uFace[.intCountFace])
        if GetLocalPlayer() != .p[.intCountFace] then
            call SetUnitVertexColor(.uFace[.intCountFace], 0, 0, 0, 0)
        endif

        set .intCountFace = .intCountFace + 1
    endmethod

    public method DisableForPlayer takes player p returns boolean
        local integer INT_FaceIndex = 0
        
        loop
            exitwhen INT_FaceIndex >= .intCountFace
            if .p[INT_FaceIndex] == p then

                call GroupRemoveUnit(DynamicDispenser.ugDispenser, .uFace[INT_FaceIndex])
                call RemoveUnit(.uFace[INT_FaceIndex])
                set .uFace[INT_FaceIndex] = null
                loop
                    exitwhen INT_FaceIndex == .intCountFace
                    set .p[INT_FaceIndex] = .p[INT_FaceIndex + 1]
                    set INT_FaceIndex = INT_FaceIndex + 1
                endloop
                set .intCountFace = .intCountFace - 1

                return true
            endif
            set INT_FaceIndex = INT_FaceIndex + 1
        endloop
        
        return false
    endmethod

    public method AddPage takes integer id returns nothing
        set .intPageUnitId[.intCountPage] = id
        set .intCountPage = .intCountPage + 1
    endmethod

    public method RemovePage takes integer id returns boolean
        local integer INT_PageIndex = 0
        local integer INT_Index = 0

        loop
            exitwhen INT_PageIndex >= .intCountPage
            if .intPageUnitId[INT_PageIndex] == id then
                loop
                    exitwhen INT_Index == .intCountPage
                    set .intPageUnitId[INT_Index] = .intPageUnitId[INT_Index + 1]
                    set INT_Index = INT_Index + 1
                endloop
                set .intCountPage = .intCountPage - 1
                if .intCountPage == 0 then
                    call .Destroy()
                endif
                set INT_Index = 0
                loop
                    exitwhen INT_Index == .intCountFace
                    if .intPageIndex[INT_Index] == INT_PageIndex then
                        call .TurnPage(INT_Index, 1)
                        call .TurnPage(INT_Index, -1)
                    endif
                    set INT_Index = INT_Index + 1
                endloop

                return true

            endif
            set INT_PageIndex = INT_PageIndex + 1
        endloop

        return false
    endmethod

    private method TurnPage takes integer faceIndex, integer increment returns nothing
        local player P = GetOwningPlayer(.uFace[faceIndex])
        
        call GroupRemoveUnit(DynamicDispenser.ugDispenser, .uFace[faceIndex])
        call RemoveUnit(.uFace[faceIndex])

        set .intPageIndex[faceIndex] = .intPageIndex[faceIndex] + increment
        if .intPageIndex[faceIndex] < 0 then
            if FLIP_TO_OTHER_END then
                set .intPageIndex[faceIndex] = .intCountPage - 1
            else
                set .intPageIndex[faceIndex] = 0
            endif
        elseif .intPageIndex[faceIndex] >= .intCountPage then
            if FLIP_TO_OTHER_END then
                set .intPageIndex[faceIndex] = 0
            else
                set .intPageIndex[faceIndex] = .intCountPage - 1
            endif
        endif

        set .uFace[faceIndex] = CreateUnit(P, .intPageUnitId[.intPageIndex[faceIndex]], .rX, .rY, .rFacing)
        if GetUnitAbilityLevel(.uFace[faceIndex], PREVIOUS_PAGE_ABILITY_ID) == 0 then
            call UnitAddAbility(.uFace[faceIndex], PREVIOUS_PAGE_ABILITY_ID)
        endif
        if GetUnitAbilityLevel(.uFace[faceIndex], NEXT_PAGE_ABILITY_ID) == 0 then
            call UnitAddAbility(.uFace[faceIndex], NEXT_PAGE_ABILITY_ID)
        endif
        call GroupAddUnit(DynamicDispenser.ugDispenser, .uFace[faceIndex])
        if GetLocalPlayer() != .p[faceIndex] then
            call SetUnitVertexColor(.uFace[faceIndex], 0, 0, 0, 0)
        endif
        if GetLocalPlayer() == .p[faceIndex] then
            call SelectUnit(.uFace[faceIndex], true)
        endif

        set P = null
    endmethod

    private static method IsExecuteTurnPage takes nothing returns boolean
        return (GetSpellAbilityId() == PREVIOUS_PAGE_ABILITY_ID or GetSpellAbilityId() == NEXT_PAGE_ABILITY_ID) and IsUnitInGroup(GetTriggerUnit(), DynamicDispenser.ugDispenser)
    endmethod

    private static method ExecuteTurnPage takes nothing returns nothing
        local unit U = GetTriggerUnit()
        local integer INT_AbilityId = GetSpellAbilityId()
        local integer INT_InstIndex = 0
        local integer INT_FaceIndex

        loop
            set INT_FaceIndex = 0
            loop
                exitwhen DynamicDispenser.Inst[INT_InstIndex].uFace[INT_FaceIndex] == U or INT_FaceIndex == DynamicDispenser.Inst[INT_InstIndex].intCountFace
                set INT_FaceIndex = INT_FaceIndex + 1
            endloop
            exitwhen DynamicDispenser.Inst[INT_InstIndex].uFace[INT_FaceIndex] == U
            set INT_InstIndex = INT_InstIndex + 1
        endloop

        if INT_AbilityId == PREVIOUS_PAGE_ABILITY_ID then
            call DynamicDispenser.Inst[INT_InstIndex].TurnPage(INT_FaceIndex, -1)
        elseif INT_AbilityId == NEXT_PAGE_ABILITY_ID then
            call DynamicDispenser.Inst[INT_InstIndex].TurnPage(INT_FaceIndex, 1)
        endif

        set U = null
    endmethod

    private static trigger trigToggle = CreateTrigger()
    private static group ugDispenser = CreateGroup()

    public static method DynamicDispenserInit takes nothing returns nothing
        call TriggerRegisterAnyUnitEventBJ(DynamicDispenser.trigToggle, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(DynamicDispenser.trigToggle, Condition(function DynamicDispenser.IsExecuteTurnPage))
        call TriggerAddAction(DynamicDispenser.trigToggle, function DynamicDispenser.ExecuteTurnPage)
    endmethod

    private integer intInstIndex
    private static DynamicDispenser array Inst[8190]
    private static integer intCountInst = 0

endstruct

private function test takes nothing returns nothing
local DynamicDispenser a = DynamicDispenser.Create('Hpal',0,0,0)
call DynamicDispenser.DynamicDispenserInit()
call a.EnableForPlayer(Player(0))
call a.AddPage('Hamg')
call a.AddPage('Hmkg')
call a.AddPage('Hblm')
endfunction
endlibrary
12-05-2008, 10:36 PM#2
Beardo
Collapse JASS:
        if GetLocalPlayer() != .p[faceIndex] then
            call SetUnitVertexColor(.uFace[faceIndex], 0, 0, 0, 0)
        endif

Wouldn't this cause a desync?
12-05-2008, 10:57 PM#3
Anitarf
No. SetUnitVertexColor only changes a unit's visual appearance which doesn't have to be the same for all players in order to maintain a synchronised gamestate.