All pastes #106286 Raw Edit

Something

public text v1 · immutable
#106286 ·published 2006-07-30 07:15 UTC
rendered paste body
--[[------------------- NOTICE: -----------------------------
	Until I get a UI for this running, modify these values to
	tweak your auctions.
	---------------------------------------------------------]]--
-- Base time alotted for each auction (in seconds)
local auctionBaseTime = 10;
-- Time alotted to extend auction during active bidding (in seconds)
local auctionExtendTime = 5;
-- Time alotted to allow players to call other bids (in seconds x 2)
local auctionCallTime = 3;
-- Time to wait between Q'ed auctions (in seconds)
local auctionTimeBetween = 3;
-- Starting auction points per player
local auctionStartingPoints = 10;
-- Minimum bid on set items
local auctionMinSetBid = 5;
-- Minimum bid on Blue and higher items
local auctionMinBlueBid = 5;

--[[-----------------------------------------------------------------
	DON'T TOUCH ANYTHING BELOW THIS UNLESS YOU KNOW WHAT YOU'RE DOING
	-----------------------------------------------------------------]]--
-- The Item currently being auctioned
local itemCurrentAuction = {};
-- Arbitary value?
MASTERLOOTER_DROPDOWNBUTTON_VALUE = 1337;
-- Hooks -- To Be Removed on successful test
local bliz_GroupLootDropDown_Initialize;
local bliz_GroupLootDropDown_OnLoad;
-- Loot q
local lootQ = {};
-- Auction status: "NOAUCTION", "STARTED", "ACTIVEBIDDING", "GOINGONCE"
-- "GOINGTWICE", "BETWEENAUCTIONS", "ROLLING"
local auctionStatus = "NOAUCTION";
-- Auction timer: startTime, allocTime
local auctionTimer = {};
-- Currently winning bidder's info: name, index, points, bid, status
local auctionWinner = {};
-- The list of players: name, index, points, status
local playerList = {}; 

-- Is our time up?
function IsTimeUp()
	if (GetTime() - auctionTimer.startTime >= auctionTimer.allocTime) then
		return true
	else
		return false
	end
end

-- Returns "RAID" if in raid, "PARTY" if in party
function IsRaidOrParty()
	if (GetNumRaidMembers() > 0) then
		return "RAID"
	else
		return "PARTY"
	end
end

-- Get the elapsed time
function GetElapsedTime()
	return GetTime() - auctionTimer.startTime
end

-- Start the timer and give it the base timetime
function StartAuctionTimer()
	auctionTimer.startTime = GetTime();
	auctionTimer.allocTime = auctionBaseTime;
end

-- Process party chat messages
function MasterLooter_OnChatMsgParty(playerName, msg)
	-- if we're not currently auctioning, or we're in a raid, ignore the message
	if (auctionStatus == "NOAUCTION" or auctionStatus == "BETWEENAUCTIONS" or IsRaidOrParty() == "RAID") then
		return
	end
	
	-- Check to see if text was a bid and if so, a valid one
	local bidTag = ValidateBid(playerName, msg);
	if (bidTag == "INVALID") then
		-- Either the message wasn't a bid or an error ocurred
		return;
	end
	
	-- Text was in fact a bid.  Process the bid.
	ProcessBid(playerName, tonumber(msg), bidTag);
end

-- Todo: process bids and post notification
function ProcessBid(playerName, bid, bidTag)
	if (bidTag == "VALID") then
		-- todo: account for multiple winners
		if (bid > auctionWinner.bid) then
			-- We have a new winner
			local newWinner = GetPlayerByName(playerName);
			if (newWinner) then
				auctionWinner = newWinner;
				auctionWinner.bid = bid;
			end
		end
		return
	end
	if (bidTag == "INVALID_ZEROORLESS") then
		-- Notify the player of his dumbass bid
		SendChatMessage("You can't break me with that bid, sorry.  Nice try, tho. :)", "WHISPER", "COMMON", playerName);
		return
	end
	if (bidTag == "INVALID_NOTENUFFPTS") then
		-- Notify the player of his invalid bid and inform him of his current points
	end
end

-- Is this a bid?  If so, is it a valid one? Find out and tag it.
-- Returns: "VALID", "VALID_TIE", "INVALID", "INVALID_ZEROORLESS", 
-- "INVALID_NOTENUFFPTS", "INVALID_TIE", "SPECIAL_TIE"
function ValidateBid(playerName, msg)
	-- Who is this guy?
	local biddingPlayer = GetPlayerByName(playerName);
	
	if (not biddingPlayer) then
		-- ERRORS BAAAAD!
		message("function ValidateBid("..playerName..", msg) fudged up. Should never see this, btw.");
		return "INVALID";
	end
	
	-- Let's go thru and check all the things that might make this an invalid bid
	if (tonumber(msg) <= 0) then
		-- You can't bid zero or less dumbass
		return "INVALID_ZEROORLESS"
	end
	if (tonumber(msg) > biddingPlayer.points) then
		-- you don't have that many pts dumbass
		return "INVALID_NOTENUFFPTS"
	end
	
	-- Looks like a bid.  Check to see if this bid ties with the winner's.
	if (tonumber(msg) == auctionWinner.bid) then
		-- Ohh, boy.  This *might* be an invalid bid, but we need to find
		-- the player that placed the bid and see if they're both maxed out
		-- before we'll know for sure.
		-- TODO: add a table of winners for rolling
		if (biddingPlayer.points == auctionWinner.bid == auctionWinner.points) then
			-- We have a valid tie.
			return "VALID_TIE"
		end
		
		-- This could be a special case in which the bidding player has spent all his points
		-- in tying with a winner who still has more points to spend.  In this case, the player 
		-- spending all his points should become the new winner and the old winner should be 
		-- notified of the case.
		if (biddingPlayer.points < auctionWinner.points) then
			return "SPECIAL_TIE"
		end
		
		-- I'm sorry, I can't do that Dave.
		return "INVALID_TIE"
	end
	
	-- We got thru everything, it's a valid bid
	return "VALID"
end

-- Returns named player in the player list.  Returns nil on failure.
function GetPlayerByName(name)
	-- Loop thru and find him
	for i = 1, table.getn(playerList), 1 do
		if (playerList[i].name == name) then
			-- We have a winner
			return playerList[i];
		end
	end
	
	-- I've failed you, father!
	return nil
end

-- Allocate time
-- todo: fix this function so that it takes into account total added time
function AllocateAuctionTime(allocTime)
	auctionTimer.allocTime = auctionTimer.allocTime + allocTime;
end

-- Add an item to the end of the lootQ
function AddToLootQ(item)
	table.insert(lootQ, item);
end

-- Remove an item from the lootQ and put it in itemCurrentAuction
function NextInLootQ()
	itemCurrentAuction = table.remove(lootQ, 1);
end

-- Are there items in the lootQ?
function IsItemInQ()
	if (table.getn(lootQ) > 0) then
		return true
	else
		return false
	end
end

-- Hack the game's built in Master Loot drop down
function MasterLooter_GroupLootDropDown_Initialize()
	-- I'm done - Call the original
	bliz_GroupLootDropDown_Initialize();
	
	-- Info struct for adding a drop down button
	local info = {};
	info.text = "- Auction with MasterLooter";
	info.textHeight = 12;
	info.value = MASTERLOOTER_DROPDOWNBUTTON_VALUE; -- Arbitary value?
	info.r = 255; -- Red Text
	info.g = 1;
	info.b = 1;
	info.notCheckable = 1;
	info.func = MasterLooter_AuctionLoot;
	UIDropDownMenu_AddButton(info);
end

-- Greed the current item
function GreedItem()
	-- Find out who has next greed and give them the item
	local greedyPlayer = table.remove(playerList, 1);
	
	-- Give the item
	GiveMasterLoot(currentAuctionItem.selectedSlot, greedyPlayer.index);
	
	-- Potential problems: what if player is no longer in group? or is out of 
	-- range/not in instance?
	
	-- Announce the win
	local msg = GetLootSlotLink(itemCurrentAuction.selectedSlot).." greeded to "..greedyPlayer.name..".";
	SendChatMessage(msg, IsRaidOrParty());
	
	-- Put them on the bottom of the player list
	table.insert(playerList, greedyPlayer);
	
	-- Notify next player
	SendChatMessage("You are next in the Greed Queue.", "WHISPER", "Common", playerList[1].name);
end

-- Add a *new* party member to the playerList
-- todo
function AddPlayer(playerName)
	
end

-- Used to sort players alphabetically
function PlayerSort(player1, player2)
	return player1.name < player2.name
end

-- Generate a list of players
function ResetPlayerList()
	if (GetNumRaidMembers() > 0) then
		-- We're in a raid
		for i = 1, 40, 1 do
			local playerName = GetMasterLootCandidate(i);
			if (playerName) then
				local player = {};
				player.index = i;
				player.name = playerName;
				player.points = auctionStartingPoints;
				table.insert(playerList, player);
			end
		end		
	else
		-- We're in a party
		for i=1, MAX_PARTY_MEMBERS+1, 1 do
			local playerName = GetMasterLootCandidate(i);
			if (playerName) then
				local player = {};
				player.index = i;
				player.name = playerName;
				player.points = auctionStartingPoints;
				table.insert(playerList, player);
			end
		end
	end
	
	-- Sort the greedlist alphabetically
	table.sort(playerList, PlayerSort);
end

-- Add this loot the the queue of loot-to-be-auctioned
function MasterLooter_AuctionLoot()
	-- Get the item we clicked and add it to the q
	local item = {};
	item.name = LootFrame.selectedItemName;
	item.slot = LootFrame.selectedSlot;
	item.quality = LootFrame.selectedQuality;
	AddToLootQ(item);	
	
	-- to be safe
	CloseDropDownMenus();
end

function HookGroupLootDropDown()
	if (GroupLootDropDown_Initialize and GroupLootDropDown_OnLoad) then
		-- Average Joe Hook - Leaving in for now until next successful test
		bliz_GroupLootDropDown_Initialize = GroupLootDropDown_Initialize;
		GroupLootDropDown_Initialize = MasterLooter_GroupLootDropDown_Initialize;
		
		bliz_GroupLootDropDown_OnLoad = GroupLootDropDown_OnLoad;
		GroupLootDropDown_OnLoad = MasterLooter_GroupLootDropDown_OnLoad;
		
		MasterLooter_GroupLootDropDown_OnLoad();
		return
	else
		message("Functions not hooked");
	end
end

-- Register events
function MasterLooter_RegisterEvents()
	this:RegisterEvent("CHAT_MSG_PARTY");
	this:RegisterEvent("CHAT_MSG_RAID");
	this:RegisterEvent("CHAT_MSG_SYSTEM");
end

-- Hookie!
function MasterLooter_Init()
	HookGroupLootDropDown();
	MasterLooter_RegisterEvents();
end

-- Rewrite the GroupLootDropDown
function MasterLooter_GroupLootDropDown_OnLoad()
	UIDropDownMenu_Initialize(GroupLootDropDown, MasterLooter_GroupLootDropDown_Initialize, "MENU");
end

function MasterLooter_OnUpdate()
	if (auctionStatus == "NOAUCTION" and not IsItemInQ()) then 
		return
	end
	
	-- Handle auction events
	if ((auctionStatus == "NOAUCTION" and IsItemInQ())) then
		-- Get the item out of the Q
		NextInLootQ();
		
		-- Announce Item for auctioning
		local msg = "Place your bids for "..GetLootSlotLink(itemCurrentAuction.selectedSlot)..".";
		SendChatMessage(msg, IsRaidOrParty());
		
		-- Start the timer
		StartAuctionTimer();
		
		-- Start the auction
		auctionStatus = "STARTED";
		return
	end
	if (auctionStatus == "STARTED") then
		-- todo: 	Check for bids, if there have been bids, then verify
		-- 			the bids, extend the auction, make it active
		--			and return
		
		-- todo: clean up this check
		if (IsTimeUp() and auctionWinner.index) then
			-- The auction ended without anyone bidding
			-- Greed list the item
			GreedItem();
			
			-- todo: Announce results
			
			if (IsItemInQ()) then
				-- We are now in between auctions, allocate time
				auctionStatus = "BETWEENAUCTIONS";
				AllocateAuctionTime(auctionTimeBetween);
			else
				-- No auctions left
				auctionStatus = "NOAUCTION";
			end
		end
	end
	if (auctionStatus == "BETWEENAUCTIONS") then
		if (IsTimeUp()) then
			-- it's time for the next auction
			auctionStatus = "NOAUCTION";
		end
	end
	if (auctionStatus == "ACTIVEBIDDING") then
		-- todo: process bids, if there are bids, extend active bidding
		--		and return
		
		if (IsTimeUp()) then
			-- todo: Active bidding has subsided, "Going Once"
			AllocateAuctionTime(auctionCallTime);
			auctionStatus = "GOINGONCE";
			return
		end
	end
	if (auctionStatus == "GOINGONCE") then
		-- todo: 	process bids, if there are bids, switch back to active
		--			extend time and return
		
		if (IsTimeUp()) then
			-- todo: Still no bids, "Going Twice"
			AllocateAuctionTime(auctionCallTime);
			auctionStatus = "GOINGTWICE";
			return
		end
	end
	if (auctionStatus == "GOINGTWICE") then
		-- todo: process bids, if there are bids, switch back to active bidding,
		--		extend time and return
		
		if (IsTimeUp()) then
			-- todo: time is up on the auction and the item is sold.  Announce
			--		the winner, distribute the item, deduct points from winner's total
			
			if (IsItemInQ()) then
				-- There's another item in the q to be auctioned, we're between auctions
				AllocateAuctionTime(auctionTimeBetween);
				auctionStatus = "BETWEENAUCTIONS";
				return
			else
				-- Nothing left in the q
				auctionStatus = "NOAUCTION";
				return
			end
		end
	end
end