-- -- Created by IntelliJ IDEA. -- User: RJ -- Date: 20/03/2017 -- Time: 12:09 -- To change this template use File | Settings | File Templates. -- ISFishingUI = ISPanelJoypad:derive("ISFishingUI"); ISFishingUI.instance = {}; ISFishingUI.messages = {}; local FONT_HGT_SMALL = getTextManager():getFontHeight(UIFont.Small) local FONT_HGT_MEDIUM = getTextManager():getFontHeight(UIFont.Medium) local function noise(str) if getDebug() then print(str) end end local function predicateFishingLure(item) return item:isFishingLure() end local function predicateFishingRodOrSpear(item, playerObj) if item:isBroken() then return false end if not item:hasTag("FishingRod") and not item:hasTag("FishingSpear") then return false end return true end --************************************************************************-- --** ISFishingUI:initialise --** --************************************************************************-- function ISFishingUI:setVisible(bVisible) if self.javaObject == nil then self:instantiate(); end self.javaObject:setVisible(bVisible); if self.visibleTarget and self.visibleFunction then self.visibleFunction(self.visibleTarget, self); end end function ISFishingUI:initialise() ISPanelJoypad.initialise(self); local btnWid = 100 local btnHgt = math.max(FONT_HGT_SMALL + 3 * 2, 25) local padBottom = 10 self.ok = ISButton:new(10, self:getHeight() - padBottom - btnHgt, btnWid, btnHgt, getText("UI_Ok"), self, ISFishingUI.onClick); self.ok.internal = "OK"; self.ok.anchorTop = false self.ok.anchorBottom = true self.ok:initialise(); self.ok:instantiate(); self.ok.borderColor = self.buttonBorderColor; self:addChild(self.ok); self.cancel = ISButton:new(self.ok:getRight() + 5, self:getHeight() - padBottom - btnHgt, btnWid, btnHgt, getText("UI_Cancel"), self, ISFishingUI.onClick); self.cancel.internal = "CANCEL"; self.cancel.anchorTop = false self.cancel.anchorBottom = true self.cancel:initialise(); self.cancel:instantiate(); self.cancel.borderColor = self.buttonBorderColor; self:addChild(self.cancel); self.close = ISButton:new(self:getWidth() - btnWid - 10, self:getHeight() - padBottom - btnHgt, btnWid, btnHgt, getText("UI_Close"), self, ISFishingUI.onClick); self.close.internal = "CLOSE"; self.close.anchorLeft = false self.close.anchorRight = true self.close.anchorTop = false self.close.anchorBottom = true self.close:initialise(); self.close:instantiate(); self.close.borderColor = self.buttonBorderColor; self:addChild(self.close); -- rod options self.rods = ISRadioButtons:new(10, 50, 150, 20, self, ISFishingUI.clickedRod) self.rods.choicesColor = {r=1, g=1, b=1, a=1} self.rods:initialise() self.rods.autoWidth = true; self:addChild(self.rods) self:updateRods(); -- lure options self.lures = ISRadioButtons:new(10, self.rods:getBottom() + 20, 150, 20) self.lures.choicesColor = {r=1, g=1, b=1, a=1} self.lures:initialise() self.lures.autoWidth = true; self:addChild(self.lures) self:updateLures(); -- Destination container options local bagsX = math.max(self.rods:getRight(), self.lures:getRight()) + 10 --self.bagOptions = ISRadioButtons:new(bagsX, self.rods.y, 100, 20) --self.bagOptions.choicesColor = {r=1, g=1, b=1, a=1} --self.bagOptions:initialise() --self.bagOptions.autoWidth = true; --self:addChild(self.bagOptions) self.containersLbl = ISLabel:new(bagsX, self.rods.y, 10, getText("IGUI_FishingUI_CatchBag"),1,1,1,1,UIFont.Small, true); self:addChild(self.containersLbl); self.containerSelector = ISComboBox:new(bagsX, self.rods.y + 20, 200, 20); self.containerSelector:initialise(); self:addChild(self.containerSelector); self:doBagOptions(); self.barPadY = 4 self.btnHgt = btnHgt self.padBottom = padBottom self.barY = self.lures:getBottom() + self.barPadY self:insertNewLineOfButtons(self.rods) self:insertNewLineOfButtons(self.lures) self:insertNewLineOfButtons(self.ok, self.cancel, self.close) self:updateSize(); self:updateZoneProgress(); end function ISFishingUI:updateSize() local bagsX = math.max(self.rods:getRight(), self.lures:getRight()) + 10 self.containerSelector:setX(bagsX) self:setWidth(self.containerSelector:getRight() + 10) self.lures:setY(self.rods:getBottom() + 20) self.barY = self.lures:getBottom() + self.barPadY local fishY = self.containerSelector:getBottom() + 10 local fishHgt = FONT_HGT_SMALL * self.maxFish self.barY = math.max(self.barY, fishY + fishHgt + self.barPadY) self:setHeight(self.barY + self.barHgt + self.barPadY + self.barHgt + self.barPadY + self.btnHgt + self.padBottom) end function ISFishingUI:clickedRod(buttons, index) self:updateButtons(); self:updateLures(); self.usingSpear = false; if WeaponType.getWeaponType(self.selectedRod) == WeaponType.spear then self.usingSpear = true; end end function ISFishingUI:updateRods() self.rods:clear(); local rods = {}; local sorted = {} self.items_array:clear() self.player:getInventory():getAllEvalRecurse(predicateFishingRodOrSpear, self.items_array) for i=1,self.items_array:size() do local item = self.items_array:get(i-1) if not rods[item:getType()] then local rod = {}; rod.item = item; rod.equipped = item:isEquipped(); -- disable the option if not lure for a rod (spears don't need them tho) if not ISWorldObjectContextMenu.getFishingLure(self.player, item) then rod.disabled = true; end rods[item:getType()] = rod; table.insert(sorted, rod); end end table.sort(sorted, function(a,b) return not string.sort(a.item:getDisplayName(), b.item:getDisplayName()) end) local index = 1; local indexToSelect = -1; for _,v in ipairs(sorted) do self.rods:addOption(v.item:getDisplayName(), v.item, v.item:getTexture()); if v.equipped then indexToSelect = index end if v.disabled then self.rods:setOptionEnabled(index, false); else if indexToSelect == -1 then indexToSelect = index; end end index = index + 1; end if indexToSelect > -1 then self.selectedRod = self.rods:getOptionData(indexToSelect); self.rods:setSelected(indexToSelect); if WeaponType.getWeaponType(self.selectedRod) == WeaponType.spear then self.usingSpear = true; end end end function ISFishingUI:updateSelectedRod() for i=1,#self.rods.options do if self.rods:isSelected(i) then self.selectedRod = self.rods:getOptionData(i); return self.selectedRod; end end end function ISFishingUI:updateLures() self:updateSelectedRod(); self.lures:clear(); self.luresEnabled = self.selectedRod and (WeaponType.getWeaponType(self.selectedRod) ~= WeaponType.spear); -- if not self.selectedRod then return; end local lures = {}; local sorted = {}; self.items_array:clear() self.player:getInventory():getAllEvalRecurse(predicateFishingLure, self.items_array) for i=1,self.items_array:size() do local item = self.items_array:get(i-1); if not lures[item:getType()] then local lure = {}; lure = {}; lure.item = item; lure.nbr = 1; lures[item:getType()] = lure; table.insert(sorted, lure); else lures[item:getType()].nbr = lures[item:getType()].nbr + 1; end end table.sort(sorted, function(a,b) return not string.sort(a.item:getDisplayName(), b.item:getDisplayName()) end) local index = 1; local indexToSelect = -1; for _,v in ipairs(sorted) do self.lures:addOption(v.item:getDisplayName() .. " (" .. v.item:getContainer():getNumberOfItem(v.item:getFullType()) .. ")", v.item, v.item:getTexture()); -- spears don't need lures, we disable all options if self.luresEnabled then if v.item:isEquipped() then indexToSelect = index; elseif indexToSelect == -1 then indexToSelect = index; end else self.lures:setOptionEnabled(index, false); end index = index + 1; end if indexToSelect ~= -1 then self.lures:setSelected(indexToSelect); end end function ISFishingUI:render() ISPanelJoypad.render(self); local actionQueue = ISTimedActionQueue.getTimedActionQueue(self.player) local currentAction = actionQueue.queue[1] self:updateButtons(currentAction); -- display no rods found self:updateSelectedRod(); if not self.selectedRod and self.rods:isEmpty() then self:drawText(getText("IGUI_FishingUI_NoRod"), self.rods:getX(), self.rods:getY(), 1,0.3,0.3,1, UIFont.Small); end if self.lures:isEmpty() and ((self.selectedRod and WeaponType.getWeaponType(self.selectedRod) ~= WeaponType.spear) or not self.selectedRod) then self:drawText(getText("IGUI_FishingUI_NoLure"), self.rods:getX(), self.lures:getY(), 1,0.3,0.3,1, UIFont.Small); end -- Fishes zone items left local color = ColorInfo.new(0, 0, 0, 1) getCore():getBadHighlitedColor():interp(getCore():getGoodHighlitedColor(), self.zoneProgress/100, color); local zoneProgressBar = {r=color:getR(), g=color:getG(), b=color:getB(), a=1} local barY = self.barY + self.barHgt + self.barPadY self:drawProgressBar(10, barY, self.width - 20, self.barHgt, self.zoneProgress / 100, zoneProgressBar) self:drawTextCentre(getText("IGUI_FishingUI_FishAbundance") .. self.zoneProgress .. "%", self.width/2, barY, 1,1,1,1, UIFont.Small); -- Display current action progress bar if currentAction and (currentAction.Type == "ISFishingAction") and currentAction.action then local fishingProgressBar = {r=getCore():getGoodHighlitedColor():getR(), g=getCore():getGoodHighlitedColor():getG(), b=getCore():getGoodHighlitedColor():getB(), a=1} self:drawProgressBar(10, self.barY, self.width - 20, self.barHgt, currentAction.action:getJobDelta(), fishingProgressBar) self:drawTextCentre(getText("ContextMenu_Fishing"), self.width/2, self.barY, 1,1,1,1, UIFont.Small); end local listY = self.containerSelector.y + self.containerSelector.height + 10; local texWH = FONT_HGT_SMALL local numFishes = #self.fishes local minFish = math.max(numFishes - self.maxFish + 1, 1) for i=numFishes,1,-1 do local v = self.fishes[i]; self:drawTextureScaled(v.texture, self.containerSelector:getX(), listY, texWH, texWH, v.alpha, 1, 1, 1); self:drawText(v.item:getDisplayName(), self.containerSelector:getX() + texWH + 2, listY, 1,1,1, v.alpha, UIFont.Small); -- Fade over time --v.alphaTimer = v.alphaTimer - (UIManager.getMillisSinceLastRender() / 33.3); --if v.alphaTimer <= 0 then -- v.alphaTimer = 0; -- v.alpha = v.alpha - 0.01; -- if v.alpha < 0 then -- table.remove(self.fishes, i); -- end --end listY = listY + FONT_HGT_SMALL; end end function ISFishingUI:prerender() local z = 20; local splitPoint = 100; local x = 10; self:drawRect(0, 0, self.width, self.height, self.backgroundColor.a, self.backgroundColor.r, self.backgroundColor.g, self.backgroundColor.b); self:drawRectBorder(0, 0, self.width, self.height, self.borderColor.a, self.borderColor.r, self.borderColor.g, self.borderColor.b); self:drawTextCentre(getText("ContextMenu_Fishing"), self.width/2, self.titleY, 1,1,1,1, UIFont.Medium); if self.joyfocus and self:getJoypadFocus() == self.ok and self.joyfocus.isActive then self:setISButtonForA(self.ok) elseif self.ok.isJoypad then self.ISButtonA = nil self.ok.isJoypad = false end local now = getTimestampMs() if now - (self.checkStuffTime or 0) > 500 then self.checkStuffTime = now self:checkInventory() self:checkPlayerPosition() end end function ISFishingUI:checkInventory() if self:checkInventoryLures() or self:checkInventoryRods() or self:checkInventoryBags() then self:updateRods() self:updateSelectedRod() self:updateLures() self:doBagOptions() self:updateSize() end end function ISFishingUI:checkInventoryRods() local playerInv = self.player:getInventory() local hasRod = {} for i=1,self.rods:getNumOptions() do local item = self.rods:getOptionData(i) if not playerInv:containsRecursive(item) then noise('checkInventoryRods') return true end hasRod[item:getType()] = true end self.items_array:clear() local items = playerInv:getAllEvalRecurse(predicateFishingRodOrSpear, self.items_array) for i=1,items:size() do if not hasRod[items:get(i-1):getType()] then noise('checkInventoryRods') return true end end return false end function ISFishingUI:checkInventoryLures() local luresEnabled = self.selectedRod and (WeaponType.getWeaponType(self.selectedRod) ~= WeaponType.spear); if luresEnabled ~= self.luresEnabled then noise('checkInventoryLures') return true end local playerInv = self.player:getInventory() local hasLure = {} for i=1,self.lures:getNumOptions() do local item = self.lures:getOptionData(i) if not playerInv:containsRecursive(item) then noise('checkInventoryLures') return true end hasLure[item:getType()] = true end self.items_array:clear() local items = playerInv:getAllEvalRecurse(predicateFishingLure, self.items_array) for i=1,items:size() do if not hasLure[items:get(i-1):getType()] then noise('checkInventoryLures') return true end end return false end local function testBag(item) return instanceof(item, "InventoryContainer") and item or nil end function ISFishingUI:checkInventoryBags() --[[local playerInv = self.player:getInventory() local itemPrimary = testBag(self.player:getPrimaryHandItem()) local itemSecondary = testBag(self.player:getSecondaryHandItem()) local itemBack = testBag(self.player:getClothingItem_Back()) -- A bag could change from primary to secondary hand, so can't just check if still holding it. if (itemPrimary ~= self.bagPrimary) or (itemSecondary ~= self.bagSecondary) or (itemBack ~= self.bagBack) then noise('checkInventoryBags') return true end--]] local newContainers = self.player:getInventory():getItemsFromCategory("Container"); if(newContainers:size() ~= self.containers:size()) then noise('checkInventoryBags'); return true; end for i=0, self.containers:size() - 1 do local bag = self.containers:get(i); local bagNew = newContainers:get(i); if(bag ~= bagNew) then noise('checkInventoryBags'); return true; end end return false end function ISFishingUI:getSelectedBag() return self.containerSelector.options[self.containerSelector.selected].data; end function ISFishingUI:updateButtons(currentAction) self.ok.enable = false; self.cancel.enable = false; local lure = false; self.selectedRod = nil; if (currentAction and (currentAction.Type == "ISFishingAction") and currentAction.action) then self.cancel.enable = true; self.ok.enable = false; return; end for i=1,self.rods:getNumOptions() do if self.rods:isSelected(i) then self.selectedRod = self.rods:getOptionData(i); end end if self.selectedRod then local checkLure = true; -- spear doesn't need lures! if WeaponType.getWeaponType(self.selectedRod) == WeaponType.spear then self.ok.enable = true; checkLure = false; end if checkLure then for i=1,#self.lures.options do if self.lures:isSelected(i) then self.ok.enable = true; end end end end self.ok.tooltip = nil; if not self.canFishDistance then self.ok.enable = false; self.ok.tooltip = getText("IGUI_GetCloserToWater"); end end function ISFishingUI:onClick(button) if button.internal == "OK" then self:equipItems(); local action = ISFishingAction:new(self.player, self.clickedSquare, self.selectedRod, self.selectedLure, self); ISTimedActionQueue.add(action); elseif button.internal == "CLOSE" then self:setVisible(false); self:removeFromUIManager(); local playerNum = self.player:getPlayerNum() if JoypadState.players[playerNum+1] then setJoypadFocus(playerNum, nil) end elseif button.internal == "CANCEL" then local actionQueue = ISTimedActionQueue.getTimedActionQueue(self.player) local currentAction = actionQueue.queue[1] if currentAction and (currentAction.Type == "ISFishingAction") and currentAction.action then currentAction.action:forceStop() end end end function ISFishingUI:onGainJoypadFocus(joypadData) ISPanelJoypad.onGainJoypadFocus(self, joypadData) self.joypadIndexY = 3 self.joypadIndex = 1 self.joypadButtons = self.joypadButtonsY[self.joypadIndexY] self.joypadButtons[self.joypadIndex]:setJoypadFocused(true) self:setISButtonForB(self.cancel) self:setISButtonForY(self.close) end function ISFishingUI:onJoypadBeforeDeactivate(joypadData) self.cancel:clearJoypadButton() self.close:clearJoypadButton() self:clearJoypadFocus(joypadData) end function ISFishingUI:onJoypadBeforeReactivate(joypadData) self:setISButtonForB(self.cancel) self:setISButtonForY(self.close) self:restoreJoypadFocus(joypadData) end function ISFishingUI:onJoypadDown(button) ISPanelJoypad.onJoypadDown(self, button) if button == Joypad.BButton then self:onClick(self.cancel) end end function ISFishingUI:setFish(item) self:updateRods(); self:updateLures(); self:updateSize(); if not item then return; end local newItem = {}; newItem.item = item; newItem.texture = item:getTexture(); newItem.alpha = 1; newItem.alphaTimer = 40; local fishesNum = #self.fishes; if (fishesNum > 2) then table.remove(self.fishes, 1); end table.insert(self.fishes, newItem); end function ISFishingUI:doBagOptions() --[[self.bagOptions:clear(); self.bagPrimary = nil; self.bagSecondary = nil; self.bagBack = nil; self.bagOptions:addOption(getText("IGUI_ScavengeUI_PutItemInPlayerInv"), self.player:getInventory()); if self.player:getPrimaryHandItem() and instanceof(self.player:getPrimaryHandItem(), "InventoryContainer") then self.bagOptions:addOption(getText("IGUI_ScavengeUI_PutItemInBag", self.player:getPrimaryHandItem():getDisplayName(), getText("IGUI_ScavengeUI_1stHand")), self.player:getPrimaryHandItem():getInventory()); self.bagPrimary = self.player:getPrimaryHandItem(); end if self.player:getSecondaryHandItem() and instanceof(self.player:getSecondaryHandItem(), "InventoryContainer") then self.bagOptions:addOption(getText("IGUI_ScavengeUI_PutItemInBag", self.player:getSecondaryHandItem():getDisplayName(), getText("IGUI_ScavengeUI_2ndHand")), self.player:getSecondaryHandItem():getInventory()); self.bagSecondary = self.player:getSecondaryHandItem(); end if self.player:getClothingItem_Back() and instanceof(self.player:getClothingItem_Back(), "InventoryContainer") then self.bagOptions:addOption(getText("IGUI_ScavengeUI_PutItemInBag", self.player:getClothingItem_Back():getDisplayName(), getText("IGUI_ScavengeUI_Back")), self.player:getClothingItem_Back():getInventory()); self.bagBack = self.player:getClothingItem_Back(); end self.bagOptions:setSelected(1, true);--]] self.containerSelector:clear(); -- First option is player's main inventory self.containerSelector:addOptionWithData("Main Inventory", self.player:getInventory()); -- Then we fill the ComboBox with the containers on player's inventory self.containers = self.player:getInventory():getItemsFromCategory("Container"); for i=0, self.containers:size() - 1 do local bag = self.containers:get(i); if (bag:getType() ~= "KeyRing") then self.containerSelector:addOptionWithData(bag:getName(), bag); end end --self.containerSelector:setSelected(1, true); end function ISFishingUI:updateZoneProgress(zoneClicked) self.zoneProgress = 100; if not zoneClicked then zoneClicked = ISFishingAction.getFishingZoneFixed(self.clickedSquareX, self.clickedSquareY, self.clickedSquareZ); end if zoneClicked and zoneClicked:getName() == "0" then self.zoneProgress = 0; end if zoneClicked then local currentFish = tonumber(zoneClicked:getName()); local totalFish = tonumber(zoneClicked:getOriginalName()); if not currentFish or not totalFish or currentFish <= 0 or totalFish <= 0 then self.zoneProgress = 0; else self.zoneProgress = math.floor((currentFish / totalFish) * 100); end end end function ISFishingUI:equipItems() self.selectedLure = nil; for i=1,#self.rods.options do if self.rods:isSelected(i) then self.selectedRod = self.rods:getOptionData(i); local twohands = false; if WeaponType.getWeaponType(self.selectedRod) == WeaponType.spear then twohands = true; end self.selectedRod = ISWorldObjectContextMenu.equip(self.player, self.player:getPrimaryHandItem(), self.selectedRod:getType(), true, twohands); end end if WeaponType.getWeaponType(self.selectedRod) ~= WeaponType.spear then for i=1,#self.lures.options do if self.lures:isSelected(i) then self.selectedLure = self.lures:getOptionData(i); self.selectedLure = ISWorldObjectContextMenu.equip(self.player, self.player:getSecondaryHandItem(), self.selectedLure:getType(), false); end end end end function ISFishingUI:checkPlayerPosition() local playerObj = self.player; local plyrX = math.floor(playerObj:getX()); local plyrY = math.floor(playerObj:getY()); if plyrX == self.checkPlayerX and plyrY == self.checkPlayerY then return end noise('checkPlayerPosition') self.checkPlayerX = plyrX; self.checkPlayerY = plyrY; self.canFishDistance = false; local dist = 4; if self.usingSpear then dist = 1; end if playerObj:getZ() > 1 then return; end -- This zone is nil where the player has never caught anything. local zoneClicked = ISFishingAction.getFishingZoneFixed(self.clickedSquareX, self.clickedSquareY, self.clickedSquareZ); self.squareWithSameZone = self.squareWithSameZone or {} self.squareWithOtherZone = self.squareWithOtherZone or {} self.squareWithoutZone = self.squareWithoutZone or {} table.wipe(self.squareWithSameZone) table.wipe(self.squareWithOtherZone) table.wipe(self.squareWithoutZone) local z = playerObj:getZ() for x=plyrX - dist, plyrX + dist do for y=plyrY - dist, plyrY + dist do local sq = getSquare(x, y, z); if sq and sq:getFloor() and sq:getFloor():getSprite() then if sq:getFloor():getSprite():getProperties():Is(IsoFlagType.water) then local zone = ISFishingAction.getFishingZoneFixed(x, y, z) if zone ~= nil and zone == zoneClicked then table.insert(self.squareWithSameZone, sq) elseif zone ~= nil then table.insert(self.squareWithOtherZone, sq) else table.insert(self.squareWithoutZone, sq) end end end end end local bestSquare = nil if #self.squareWithSameZone > 0 then bestSquare = self:pickBestSquare(self.squareWithSameZone) elseif #self.squareWithOtherZone > 0 then bestSquare = self:pickBestSquare(self.squareWithOtherZone) elseif #self.squareWithoutZone > 0 then bestSquare = self:pickBestSquare(self.squareWithoutZone) end if bestSquare then self.canFishDistance = true if bestSquare:getFloor() ~= self.clickedSquare then noise(string.format('clickedSquare %d,%d,%d', bestSquare:getX(), bestSquare:getY(), bestSquare:getZ())) self.clickedSquare = bestSquare:getFloor() self.clickedSquareX = bestSquare:getX() self.clickedSquareY = bestSquare:getY() self.clickedSquareZ = bestSquare:getZ() end self:updateZoneProgress() else self.zoneProgress = 0 end end function ISFishingUI:pickBestSquare(squares) local playerObj = self.player local bestDot = -1 local bestSquare = nil local bestDist = 10000 for _,square in ipairs(squares) do local dot = playerObj:getDotWithForwardDirection(square:getX() + 0.5, square:getY() + 0.5) local dist = playerObj:DistToSquared(square:getX() + 0.5, square:getY() + 0.5) if not bestSquare or (dot > bestDot) or (dot == bestDot and dist < bestDist) then bestSquare = square bestDot = dot bestDist = dist end end return bestSquare end --************************************************************************-- --** ISFishingUI:new --** --************************************************************************-- function ISFishingUI:new(x, y, width, height, player, clickedSquare) local o = {} if y == 0 then y = getPlayerScreenTop(player:getPlayerNum()) + (getPlayerScreenHeight(player:getPlayerNum()) - height) / 2 y = y + 200; end if x == 0 then x = getPlayerScreenLeft(player:getPlayerNum()) + (getPlayerScreenWidth(player:getPlayerNum()) - width) / 2 end local o = ISPanelJoypad.new(self, x, y, width, height); o.borderColor = {r=0.4, g=0.4, b=0.4, a=1}; o.backgroundColor = {r=0, g=0, b=0, a=0.6}; o.width = width; o.titleY = 10 o.barHgt = FONT_HGT_SMALL; o.height = height; o.player = player; o.moveWithMouse = true; o.clickedSquare = clickedSquare; o.clickedSquareX = clickedSquare:getX() o.clickedSquareY = clickedSquare:getY() o.clickedSquareZ = clickedSquare:getZ() o.buttonBorderColor = {r=0.7, g=0.7, b=0.7, a=0.5}; o.fishes = {}; o.maxFish = 4; o.rod = rod; o.zoneProgress = 100; o.items_array = ArrayList.new(); ISFishingUI.instance[player:getPlayerNum()+1] = o; return o; end