• 🏆 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!

[vJASS] Simplfying virtual bank code

Status
Not open for further replies.
Level 15
Joined
Aug 7, 2013
Messages
1,337
Hi,

I am using WC3's dialog type as a primitive shell for the player to perform commands or interact with the environment. Each button is thus an option or shell command.

Each shell is a struct which consists of two members: a Table (Bribe's) and a TableArray (also Bribe's). The Table holds the buttons, their names, and a counter for each, while the TableArray is a 2-D mapping between these and the many different dialogs a shell may have.

Now this system works, but the code is ugly as sin! For example, here is the code for parsing the button command. It works fine, but it's impossible to read unless you've been starting at it for more than a few minutes.

I'd like a way to make it more readable and easier on the eyes, since I'll be making well over a hundred such shells by the time I am done.

JASS:
private function introMain takes nothing returns boolean
    local button b = GetClickedButton()
    local player p = GetTriggerPlayer()
    local integer pid = GetPlayerId(p)
    local trigger t
    local ItemGroup backpack = playerDatum[pid].backpack
    local ItemGroup bank = playerDatum[pid].bank
    local NPC npc = playerDatum[pid].npcs[Bank.index]
    if b == npc.twoD[INTRO * MAX_BTTNS].button[TAKE_BTTN] then
        call bank.displayGroup(IDIALOG_TAKE_MSG)
        set t = CreateTrigger()
        call TriggerRegisterDialogEvent(t, bank.iDialog)
        call TriggerAddCondition(t, Condition(function takeItem))
        set playerDatum[pid].npcTrig = t
    elseif b == npc.twoD[INTRO * MAX_BTTNS].button[PUT_BTTN] then
        if bank.size == bank.maxSize then //the bank is full, player cannot store more items there
            call DisplayTimedTextToPlayer(Player(pid), 0, 0, DSPLY_TXT_DUR, BANK_HEADER + " Your vault is full with " + I2S(bank.size) + " items.")
        else //the player's party has at least 2 monsters, so we need to list his party monsters
            call backpack.displayGroup(IDIALOG_PUT_MSG)
            set t = CreateTrigger()
            call TriggerRegisterDialogEvent(t, backpack.iDialog)
            call TriggerAddCondition(t, Condition(function putItem))
            set playerDatum[pid].npcTrig = t
        endif
    elseif b == npc.twoD[INTRO * MAX_BTTNS].button[REMOVE_BTTN] then
        call bank.displayGroup(IDIALOG_REMOVE_MSG)
        set t = CreateTrigger()
        call TriggerRegisterDialogEvent(t, bank.iDialog)
        call TriggerAddCondition(t, Condition(function removeItem))
        set playerDatum[pid].npcTrig = t
    elseif b == npc.twoD[INTRO * MAX_BTTNS].button[TAKE_GOLD_BTTN] then
        if playerDatum[pid].npcs[Bank.index].gold == 0 then //no gold inside the bank
            call DisplayTimedTextToPlayer(Player(pid), 0, 0, DSPLY_TXT_DUR, ERR_TAKE)
        else
            call DialogSetMessage(npc.oneD.dialog[GOLD_DIALOG], "Withdraw how much?\nAvailable: " + I2S(npc.gold))
            call DialogDisplay(p, npc.oneD.dialog[GOLD_DIALOG], true)
            set t = CreateTrigger()
            call TriggerRegisterDialogEvent(t, npc.oneD.dialog[GOLD_DIALOG])
            call TriggerAddCondition(t, Condition(function takeGold))
        endif
    elseif b == npc.twoD[INTRO * MAX_BTTNS].button[PUT_GOLD_BTTN] then
        if GetPlayerState(Player(pid), PLAYER_STATE_RESOURCE_GOLD) == 0 then //no gold inside the bank
            call DisplayTimedTextToPlayer(Player(pid), 0, 0, DSPLY_TXT_DUR, ERR_PUT)
        else
            call DialogSetMessage(npc.oneD.dialog[GOLD_DIALOG], "Deposit how much?\nAvailable: " + I2S(npc.gold))
            call DialogDisplay(p, npc.oneD.dialog[GOLD_DIALOG], true)
            set t = CreateTrigger()
            call TriggerRegisterDialogEvent(t, npc.oneD.dialog[GOLD_DIALOG])
            call TriggerAddCondition(t, Condition(function putGold))
        endif
    endif
    set b = null
    set t = null
    return false
endfunction
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
JASS:
struct Code
    static method getId takes code self returns integer
        return GetHandleId(Condition(self))
    endmethod
endstruct

struct Trigger
    static hashtable TABLE

    trigger self

    static method getFromCode takes code c returns thistype
        local integer cId = Code.getId(c)

        local thistype this = LoadInteger(TABLE, cId, 0)

        if (this == 0) then
            set this = allocate()

            set self = CreateTrigger()

            call TriggerAddCondition(self, Condition(c))

            call SaveInteger(TABLE, cId, 0, this)
        endif

        return this
    endmethod

    method run takes nothing returns boolean
        return TriggerEvaluate(self)
    endmethod

    static method onInit takes nothing returns nothing
        set TABLE = InitHashtable()
    endmethod
endstruct

struct FuncDialogButton
    static hashtable TABLE

    Trigger action
    button self

    static method getFromSelf takes button self returns thistype
        return LoadInteger(TABLE, GetHandleId(self), 0)
    endmethod

    static method create takes FuncDialog dia, string caption, code actionCode returns thistype
        local thistype this = allocate()

        set self = DialogAddButton(dia.self, caption, 0)

        set action = Trigger.getFromCode(actionCode)

        call SaveInteger(TABLE, GetHandleId(self), 0, this)

        return this
    endmethod

    static method onInit takes nothing returns nothing
        set TABLE = InitHashtable()
    endmethod
endstruct

struct FuncDialog
    static trigger CLICK_TRIG
    static hashtable TABLE

    static thistype array CUR_DISPLAYED

    dialog self

    method hide takes player p returns nothing
        set CUR_DISPLAYED[GetPlayerId(p)] = 0

        call DialogDisplay(p, self, false)
    endmethod

    method show takes player p returns nothing
        local thistype old = CUR_DISPLAYED[GetPlayerId(p)]

        if (old != 0) then
            call old.hide(p)
        endif

        set CUR_DISPLAYED[GetPlayerId(p)] = this

        call DialogDisplay(p, self, true)
    endmethod

    static method onClick takes nothing returns nothing
        local FuncDialogButton but = FuncDialogButton.getFromSelf(GetClickedButton())

        call but.action.run()
    endmethod

    static method create takes string title returns thistype
        local thistype this = allocate()

        set self = DialogCreate()

        call SaveInteger(TABLE, GetHandleId(self), 0, this)

        call DialogSetMessage(self, title)
        call TriggerRegisterDialogEvent(CLICK_TRIG, self)

        return this
    endmethod

    static method onInit takes nothing returns nothing
        local integer i

        set CLICK_TRIG = CreateTrigger()

        call TriggerAddCondition(CLICK_TRIG, function thistype.onClick)

        set TABLE = InitHashtable()

        set i = 11

        loop
            set CUR_DISPLAYED[i] = 0

            set i = i - 1
            exitwhen (i < 0)
        endloop
    endmethod
endstruct
 
Status
Not open for further replies.
Top