- Joined
- Aug 7, 2013
- Messages
- 1,342
Hi,
I was curious if there were any leaks in this dialog system I wrote.
I'm a bit nervous because I am handling a lot of shuffling of units between different data structures, and it's possible my logic actually causes me to lose handles to these "units," in which case I'd have leaks. I'm also dealing with removing units completely, but not sure if this is done right either.
It's a little long, but if there any leaks I would appreciate help in fixing them.
Note that the struct "Farmer" is only created once, so the globals don't get overwritten. The design may seem stupid, but I'll get to fixing it once I know my logic/leak fixing is correct.
Here's the other bit of companion code for
I was curious if there were any leaks in this dialog system I wrote.
I'm a bit nervous because I am handling a lot of shuffling of units between different data structures, and it's possible my logic actually causes me to lose handles to these "units," in which case I'd have leaks. I'm also dealing with removing units completely, but not sure if this is done right either.
It's a little long, but if there any leaks I would appreciate help in fixing them.
Note that the struct "Farmer" is only created once, so the globals don't get overwritten. The design may seem stupid, but I'll get to fixing it once I know my logic/leak fixing is correct.
JASS:
library FarmerStruct requires NPCStruct
globals
private dialog intro
private button takeBttn //the player wishes to take a monster from the farm
private button dropoffBttn //the player wishes to drop a monster off at the farm
private button swapBttn //the player wishes to swap a monster from the party with one from the farm
private button releaseBttn //the player wishes to get rid of a monster at the farm
private button quitBttn //option to leave the dialog
private string introMessage = "|cffff8000Monster Keeper|r:\n |cfff0f000Picking up or dropping off?|r"
endglobals
//a player effectively gets rid of one his monsters at the farm
private function releaseMon takes nothing returns boolean
local button b = GetClickedButton()
local player p = GetTriggerPlayer()
local integer pid = GetPlayerId(p)
local integer i = 0 //counter
local MonsterGroup farm
local Monster target
set farm = playerDatum[pid].farm
loop
exitwhen i == MAX_FARM_SIZE
if b == farm.bttns[i] then
set target = farm.monsters[i]
set target.toRelease = true
call DialogSetMessage(playerDatum[pid].release, "Release your " + target.toString() + "?\nOnce you do, it's gone forever")
call DialogDisplay(p, playerDatum[pid].release, true) //the release is handled by PlayerData itself
endif
set i = i + 1
endloop
set b = null
set p = null
//call target.destroy()
//call party.destroy()
//call farm.destroy()
call DestroyTrigger(playerDatum[pid].npcTrig)
return false
endfunction
//swap a monster from the party and the farm
private function swapMon2 takes nothing returns boolean
local button b = GetClickedButton()
local player p = GetTriggerPlayer()
local integer pid = GetPlayerId(p)
local integer i = 0 //counter
local integer j = 0 //a second loop counter for going through the player's party
local MonsterGroup party
local MonsterGroup farm
local Monster temp
set party = playerDatum[pid].party
set farm = playerDatum[pid].farm
loop
exitwhen i == MAX_FARM_SIZE
if b == farm.bttns[i] then
loop
exitwhen j == MAX_PARTY_SIZE
if party.monsters[j].toSwap == true then
set party.monsters[j].toSwap = false
set temp = party.monsters[j]
set party.monsters[j] = farm.monsters[i]
set farm.monsters[i] = temp
call SetUnitOwner(party.monsters[j].u, p, true)
call SetUnitOwner(farm.monsters[i].u, BOT_ALLY, true)
call DisplayTimedTextToPlayer(p, 0, 0, DSPLY_TXT_DUR, "|cffff8000Monster Keeper|r: Swapped out " + farm.monsters[i].toString() + " for " + party.monsters[j].toString())
endif
set j = j + 1
endloop
endif
set i = i + 1
endloop
loop
exitwhen i == 0
if party.monsters[i].toSwap == true then
set party.monsters[i].toSwap = false
endif
set i = i + 1
endloop
set b = null
set p = null
//call target.destroy()
//call party.destroy()
//call farm.destroy()
call DestroyTrigger(playerDatum[pid].npcTrig)
return false
endfunction
//swap a monster from the party and the farm
private function swapMon takes nothing returns boolean
local button b = GetClickedButton()
local player p = GetTriggerPlayer()
local integer pid = GetPlayerId(p)
local integer i = 0 //counter
local trigger t //a second trigger
local trigger d //a reference to the old NPC trig
local MonsterGroup party
local Monster target
set party = playerDatum[pid].party
set d = playerDatum[pid].npcTrig
loop
exitwhen i == MAX_PARTY_SIZE
if b == party.bttns[i] then
set target = party.monsters[i]
set target.toSwap = true //set the monster's swap flag to true, we're swapping it!
call playerDatum[pid].farm.displayGroup(true, "Which monster will be taking?")
set t = CreateTrigger()
call TriggerRegisterDialogEvent(t, playerDatum[pid].farm.mDialog)
call TriggerAddCondition(t, Condition(function swapMon2))
set playerDatum[pid].npcTrig = t
endif
set i = i + 1
endloop
set b = null
set p = null
set t = null
//call target.destroy()
//call party.destroy()
//call farm.destroy()
call DestroyTrigger(d)
set d = null
return false
endfunction
private function takeMon takes nothing returns boolean
local button b = GetClickedButton()
local player p = GetTriggerPlayer()
local integer pid = GetPlayerId(p)
local integer i = 0 //counter
local MonsterGroup party
local MonsterGroup farm
local Monster target
set party = playerDatum[pid].party
set farm = playerDatum[pid].farm
loop
exitwhen i == MAX_FARM_SIZE
if b == farm.bttns[i] then
set target = farm.monsters[i]
if farm.moveMonster(party, target) then
call DisplayTimedTextToPlayer(p, 0, 0, DSPLY_TXT_DUR, "|cffff8000Monster Keeper|r: Your " + target.toString() + " is happy to join you. It really missed you!")
call SetUnitOwner(target.u, p, true) //get back the player's monster
else //somehow we failed when we shouldn't have
call DisplayTimedTextToPlayer(p, 0, 0, DSPLY_TXT_DUR, "Error: Could not move " + target.toString() + " when we should be able to.")
endif
endif
set i = i + 1
endloop
set b = null
set p = null
//call target.destroy()
//call party.destroy()
//call farm.destroy()
call DestroyTrigger(playerDatum[pid].npcTrig)
return false
endfunction
private function dropoffMon takes nothing returns boolean
local button b = GetClickedButton()
local player p = GetTriggerPlayer()
local integer pid = GetPlayerId(p)
local integer i = 0 //counter
local MonsterGroup party
local MonsterGroup farm
local Monster target
set party = playerDatum[pid].party
set farm = playerDatum[pid].farm
loop
exitwhen i == MAX_PARTY_SIZE
if b == party.bttns[i] then
set target = party.monsters[i]
if party.moveMonster(farm, target) then
call DisplayTimedTextToPlayer(p, 0, 0, DSPLY_TXT_DUR, "|cffff8000Monster Keeper|r: Your " + target.toString() + " is now at the farm.")
call SetUnitOwner(target.u, BOT_ALLY, true) //change the ownership for now
else //somehow we failed when we shouldn't have
call DisplayTimedTextToPlayer(p, 0, 0, DSPLY_TXT_DUR, "Error: Could not move " + target.toString() + " when we should be able to.")
endif
endif
set i = i + 1
endloop
set b = null
set p = null
//call target.destroy()
//call party.destroy()
//call farm.destroy()
call DestroyTrigger(playerDatum[pid].npcTrig)
return false
endfunction
private function introMain takes nothing returns boolean
local button b = GetClickedButton()
local player p = GetTriggerPlayer()
local integer pid = GetPlayerId(p)
local MonsterGroup party
local MonsterGroup farm
local trigger t
set party = playerDatum[pid].party
set farm = playerDatum[pid].farm
if b == quitBttn then
call DialogClear(intro)
elseif b == takeBttn then //first check to see if the player has enough party room
if party.size == MAX_PARTY_SIZE then //party is full, end the dialog
call DisplayTimedTextToPlayer(Player(pid), 0, 0, DSPLY_TXT_DUR, "|cffff8000Monster Keeper|r: Your party is already full with " + I2S(party.size) + " monsters in it. Drop off a monster first.")
else //the player's party isn't full, so we need to list his farm monsters
call farm.displayGroup(true, "Which monster will you be taking?")
set t = CreateTrigger()
call TriggerRegisterDialogEvent(t, farm.mDialog)
call TriggerAddCondition(t, Condition(function takeMon))
set playerDatum[pid].npcTrig = t
endif
elseif b == dropoffBttn then
if party.size == MIN_PARTY_SIZE then //party cannot go below one monsters
call DisplayTimedTextToPlayer(Player(pid), 0, 0, DSPLY_TXT_DUR, "|cffff8000Monster Keeper|r: You can't go around without any monsters! Take another monster first.")
elseif farm.size == MAX_FARM_SIZE then //the farm is full, player cannot store more monsters there
call DisplayTimedTextToPlayer(Player(pid), 0, 0, DSPLY_TXT_DUR, "|cffff8000Monster Keeper|r: The farm is full with " + I2S(farm.size) + " monsters. Switch monsters or release one.")
else //the player's party has at least 2 monsters, so we need to list his party monsters
call party.displayGroup(true, "Which monster will you be dropping off?")
set t = CreateTrigger()
call TriggerRegisterDialogEvent(t, party.mDialog)
call TriggerAddCondition(t, Condition(function dropoffMon))
set playerDatum[pid].npcTrig = t
endif
elseif b == swapBttn then
if farm.size == 0 then //the farm is empty, no swapping allowed!
call DisplayTimedTextToPlayer(Player(pid), 0, 0, DSPLY_TXT_DUR, "|cffff8000Monster Keeper|r: You can't swap monsters--the farm is empty!")
endif
//else we begin the swapping dialogs...
call party.displayGroup(true, "Which monster will you swap from your party?")
set t = CreateTrigger()
call TriggerRegisterDialogEvent(t, party.mDialog)
call TriggerAddCondition(t, Condition(function swapMon))
set playerDatum[pid].npcTrig = t
else //b == releaseBttn
call farm.displayGroup(true, "Which monster will be released?\nOnce it's released into the wild,\n it's gone forever.")
set t = CreateTrigger()
call TriggerRegisterDialogEvent(t, farm.mDialog)
call TriggerAddCondition(t, Condition(function releaseMon))
set playerDatum[pid].npcTrig = t
endif
set b = null
set t = null
//call party.destroy()
//call farm.destroy()
return false
endfunction
struct Farmer extends NPC
static method create takes integer unitType returns thistype
local thistype this = thistype.allocate(unitType)
local trigger t = CreateTrigger()
set intro = DialogCreate()
set takeBttn = DialogAddButton(intro, "Pick up a monster", 1)
set dropoffBttn = DialogAddButton(intro, "Drop off a monster", 2)
set swapBttn = DialogAddButton(intro, "Swap monsters", 3)
set releaseBttn = DialogAddButton(intro, "Release a monster", 4)
set quitBttn = DialogAddButton(intro, quitMessage, 5)
call DialogSetMessage(intro, introMessage)
call TriggerRegisterDialogEvent(t, intro)
call TriggerAddCondition(t, Condition(function introMain))
set t = null
return this
endmethod
//creates the triggers necessary to run the priest's actions
method interact takes integer pid returns nothing
call DialogDisplay(Player(pid), intro, true)
endmethod
endstruct
endlibrary
Here's the other bit of companion code for
releaseMon
:
JASS:
library PlayerDataStruct requires MonsterGroupStruct
globals
endglobals
private function releaseMain takes nothing returns boolean
local button b = GetClickedButton()
local player p = GetTriggerPlayer()
local integer pid = GetPlayerId(p)
local integer i = 0 //search the farm for the to be released monster
local Monster target
local MonsterGroup farm
if b == playerDatum[pid].releaseYes then
set farm = playerDatum[pid].farm
loop
exitwhen i == MAX_FARM_SIZE
if farm.monsters[i].toRelease == true then //remove it
set target = farm.monsters[i]
call DisplayTimedTextToPlayer(p, 0, 0, 10, "Farmer: Say goodbye to your " + target.toString() + "; it's been released back into the wild.")
call farm.removeMonster(target)
call RemoveUnit(target.u)
call target.destroy()
endif
set i = i + 1
endloop
endif
//else b == releaseNo
loop
exitwhen i == MAX_FARM_SIZE
if farm.monsters[i].toRelease == true then //set the flag back to false, since we aren't releasing it yet
set farm.monsters[i].toRelease = false
endif
set i = i + 1
endloop
set b = null
set p = null
call target.destroy()
call farm.destroy()
return false
endfunction
struct PlayerData
integer pid = 0 //the player's unique id
MonsterGroup party //the player's party monsters
MonsterGroup farm //the player's farm monsters
dialog release //make sure the player wants to remove this monster
button releaseYes //the player does want to remove this monster
button releaseNo //the player doesn't want to release this monster
trigger npcTrig //the current npc trig, destroyed everytime a convo finishes
unit u //the monster master handle
static method create takes integer pid returns thistype
local thistype this = thistype.allocate()
local trigger t = CreateTrigger()
set this.u = CreateUnit(Player(pid), 'H013', CITY_CENTER_X, CITY_CENTER_Y, 0)
set this.pid = pid
set this.party = MonsterGroup.create(PARTY, pid) //initialize the party
set this.farm = MonsterGroup.create(FARM, pid) //initialze the farm
set this.release = DialogCreate()
set this.releaseYes = DialogAddButton(release, "Yes, release this monster.", 1)
set this.releaseNo = DialogAddButton(release, "No, don't release it!", 2)
call TriggerRegisterDialogEvent(t, release)
call TriggerAddCondition(t, Condition(function releaseMain))
set t = null
return this
endmethod
endstruct
endlibrary