- Joined
- Jan 31, 2009
- Messages
- 166
I have been experiencing a persistent and obnoxious bug in one of my map Fortress builders economy system.
The system is supposed to tally up the amount of units with certain abilities that players have that signify those units produce or consume certain resources. The system then decides whether they have a surplus of that resource or if they need more and buy or sells that resource to a global market accordingly. Resources are dynamically priced based on supply and demand. All of this normally works fine.
The problem after a period of time (usually about an hour) in multiplayer games the system starts to fall apart. Specifically the resources start failing to trade one at a time. The economy report (which tells a player all the transactions made each income) starts growing shorter and eventually becomes full of null values. (it just prints out the word null a bunch of times). I think this is caused by one of the methods quitting prematurely due to encountering a null variable. But I do not know which variable is causing this.
If anyone could help me find the null variable by inspecting my code, or knows a good technique for finding null variables (the only one I know is spamming BJDebug messages and trying to see which lines of code are reached) I would be very greatful.
To make matters worst I have not been able to replicate the error in single player. Only in multiplayer and only after a decent period of time.
Here are the methods I suspect might be causing the error
And here is the entire system
If you would like any clarification about how any part of the system works feel free to ask (I know that it is far from the cleanest of code).
Thank you for your time.
Update: Changed ConvertedPlayer() to use native. Added more comments and simplified code a little.
The system is supposed to tally up the amount of units with certain abilities that players have that signify those units produce or consume certain resources. The system then decides whether they have a surplus of that resource or if they need more and buy or sells that resource to a global market accordingly. Resources are dynamically priced based on supply and demand. All of this normally works fine.
The problem after a period of time (usually about an hour) in multiplayer games the system starts to fall apart. Specifically the resources start failing to trade one at a time. The economy report (which tells a player all the transactions made each income) starts growing shorter and eventually becomes full of null values. (it just prints out the word null a bunch of times). I think this is caused by one of the methods quitting prematurely due to encountering a null variable. But I do not know which variable is causing this.
If anyone could help me find the null variable by inspecting my code, or knows a good technique for finding null variables (the only one I know is spamming BJDebug messages and trying to see which lines of code are reached) I would be very greatful.
To make matters worst I have not been able to replicate the error in single player. Only in multiplayer and only after a decent period of time.
Here are the methods I suspect might be causing the error
JASS:
// Update the prices for each comodity as stored in the CommodityPrices array.
// Prices are then used in both the main economy and to update the multiboard.
private static method updatePrices takes nothing returns nothing
local integer PriceCommodityIndex = 1
local real Price = 1
loop
set GlobalDemand = 0
set GlobalSupply = 0
set LoopIndex = 1
loop
set LoopPlayer = Player(LoopIndex - 1)
set Demand[LoopIndex] = ComputeCommodityProduction(ConsumptionID[PriceCommodityIndex], ConsumptionPerLevel[PriceCommodityIndex], LoopPlayer)
set Supply[LoopIndex] = ComputeCommodityProduction(ProductionID[PriceCommodityIndex], ProductionPerLevel[PriceCommodityIndex], LoopPlayer)
set GlobalSupply = GlobalSupply + Supply[LoopIndex]
set GlobalDemand = GlobalDemand + Demand[LoopIndex]
exitwhen LoopIndex > 9
set LoopIndex = LoopIndex + 1
endloop
set GlobalSupply = GlobalSupply + NPCSupply[PriceCommodityIndex]
set GlobalDemand = GlobalDemand + NPCDemand[PriceCommodityIndex]
set Price = NPCPrice[CommodityIndex] // Price to be used if there is no supply to avoid
// a division by zero error.
if GlobalSupply > 0 then
set Price = CalculateCommodityPrice(BasePrice[PriceCommodityIndex], I2R(GlobalDemand), I2R(GlobalSupply))
endif
set CommodityPrices[PriceCommodityIndex] = Price
exitwhen PriceCommodityIndex == CommodityTotal
set PriceCommodityIndex = PriceCommodityIndex + 1
endloop
endmethod
// In this function we determine how much supply and demand there is for each commodity.
// As we go we store the amount each player is producing as string.
// Allso deals with tax income
private static method CommoditiesLoop takes nothing returns nothing
local real Price = 1
call updatePrices()
set CommodityIndex = 1
loop // for each commodity
// Get and store each players demand for the commodity we are working with
// Also handle their tax income
set LoopIndex = 1
loop //for each player
set LoopPlayer = Player(LoopIndex - 1)
set Demand[LoopIndex] = ComputeCommodityProduction(ConsumptionID[CommodityIndex], ConsumptionPerLevel[CommodityIndex], LoopPlayer)
set Supply[LoopIndex] = ComputeCommodityProduction(ProductionID[CommodityIndex], ProductionPerLevel[CommodityIndex], LoopPlayer)
set TaxIncome[LoopIndex] = ComputeCommodityProduction('A037', 1000 , LoopPlayer)
exitwhen LoopIndex > 9
set LoopIndex = LoopIndex + 1
endloop
set Price = CommodityPrices[CommodityIndex]
// Store the price of the commodity we are working with (printer 1 will be printed to all players)
set printer[1] = printer[1] + CommodityName[CommodityIndex] + " costs " + R2S(Price) + " || "
// Print to each player how much they have and require of each commodity.
// Then print out how much money they made or lost on each commodity.
set LoopIndex = 1
loop
set LoopPlayer = Player(LoopIndex - 1)
set printer2[LoopIndex] = printer2[LoopIndex] + "You have " + I2S (Supply[LoopIndex]) + " " + CommodityName[CommodityIndex] + " || "
set printer3[LoopIndex] = printer3[LoopIndex] + "You require " + I2S (Demand[LoopIndex]) + " " + CommodityName[CommodityIndex] + " || "
set CurrencyCalculation = R2I((Supply[LoopIndex]-Demand[LoopIndex]) * Price)
if (CurrencyCalculation > 0) then
set printer4[LoopIndex] = printer4[LoopIndex] + "|c0000cc00 You made " + I2S (CurrencyCalculation) + " Currency selling " + CommodityName[CommodityIndex] + "|r || "
elseif (CurrencyCalculation < 0) then
set printer4[LoopIndex] = printer4[LoopIndex] + "|c00990000 You lost " + I2S (IAbsBJ(CurrencyCalculation)) + " Currency buying " + CommodityName[CommodityIndex] + "|r||"
else
set printer4[LoopIndex] = printer4[LoopIndex] + "|c00999999You did not trade " + CommodityName[CommodityIndex] + "|r || "
endif
set total[LoopIndex] = total[LoopIndex] + CurrencyCalculation
exitwhen LoopIndex > 9
set LoopIndex = LoopIndex + 1
endloop
// When half the information for half commodities have been stored in the pritners display the information to the screne and clear them
if CommodityIndex == 3 then
call PrintInfo()
call InitPrinters()
endif
// Exit the loop when all commodities have been looped through
exitwhen CommodityIndex == CommodityTotal
set CommodityIndex = CommodityIndex + 1
endloop // Exit commodities loop
endmethod
JASS:
// Fix bug where part of the econmy dissapers!
// Needs to be fixed to use proper timer
// Also requires balance (chek spreadsheet) The sprad should more accuratly represnt true prices with new curve.
// Consider adding
// Global Economy Reports
// Sabatoge
// NPC supply/demand/events
// Strech goals
// Banking
// Population system
struct EconomySystem
// Very Long list of private static variables used in econ system
// These variables represent the stats of each commodity. They should not change over the course of the game.
private static string array CommodityName // Eg Grain, Gold, Jewlry
private static integer array ProductionID
private static integer array ConsumptionID
private static integer array ProductionPerLevel
private static integer array ConsumptionPerLevel
private static integer array NPCPrice // Amount the NPC will charge if no one is supplying it.
private static integer array NPCSupply
private static integer array NPCDemand
private static integer array NPCAverage
private static integer CommodityTotal = 6 // Total number of commodities (For loop)
private static real array BasePrice // Base Price of a commdity
private static real MerchantBonus = 1.20
private static real BarbarianPenalty = 0.85
// These variables represent the stats of the demon economy. They should not change over time
private static real Curruption = udg_Curruption * udg_DemonIncomeMultiplier // default value .05 about 12 / 100 This is for demons income
// System variables that store temporary information
private static player LoopPlayer = Player(0) // Used to shorten lines and avoding calying player() repetitivly
private static integer CommodityIndex = 1 // Just a loop index for the main comodities loop
private static integer TotalCommerce = 0 // Used to store total amount of money made for demon economy (demons get a percentage of all humans income)
private static integer LoopIndex = 1
// Variables used to sum up the money a player makes.
private static integer array TaxIncome
private static integer AdjustedTotal =0
private static integer CurrencyCalculation =0 // The amount of money a player will gain or lose from a commdity
private static integer array total
// Variables used to calculate the cost per commodity each time the economy runs. These chance each time.
private static real array CommodityPrices
private static integer array Demand // A players demand for a commodity
private static integer array Supply // A players supply for a commodity
private static integer GlobalDemand = 0 // All players demand for a commodity
private static integer GlobalSupply = 0 // All players supply of a commodity
// These variables are used in order to concatinate many strings together
// into coherent messages which can be displayed to each payer when the economy report runs.
private static string array printer
private static string array printer2
private static string array printer3
private static string array printer4
private static method onInit takes nothing returns nothing
// Primary trigger runs the economy
local trigger t = CreateTrigger()
call TriggerRegisterTimerExpireEventBJ( t, udg_IncomeTimer )
//call TriggerAddCondition(t, function thistype.run)
call TriggerAddAction(t, function thistype.run)
set t = null
// Secondary trigger, initilizes multiboard
set t = CreateTrigger()
call TriggerRegisterTimerEvent(t,2,false)
call TriggerAddCondition(t, function thistype.CreateEconomyMultiboard)
set t = null
// Tirtiary trigger, updates multiboard
set t = CreateTrigger()
call TriggerRegisterTimerEvent(t,7,true)
call TriggerAddCondition(t, function thistype.UpdateEconMultiboard)
set t = null
debug call BJDebugMsg("Init income system")
// Initialize private variables
set CommodityTotal = 6
set CommodityName[1] = "Grain"
set ProductionID[1] = 'A038'
set ConsumptionID[1] = 'A039'
set ProductionPerLevel[1] = 1000
set ConsumptionPerLevel[1] = 100
set BasePrice[1] = 1.5
set NPCPrice[1] = 3
set NPCAverage[1] = 4000
set CommodityName[2] = "Iron Ore"
set ProductionID[2] = 'A03A' //
set ConsumptionID[2] = 'A03B' //
set ProductionPerLevel[2] = 10
set ConsumptionPerLevel[2] = 10
set BasePrice[2] = 65
set NPCPrice[2] = 100
set NPCAverage[2] = 90
set CommodityName[3] = "Iron Alloy"
set ProductionID[3] = 'A03C' //
set ConsumptionID[3] = 'A03D' //
set ProductionPerLevel[3] = 10
set ConsumptionPerLevel[3] = 10
set BasePrice[3] = 140
set NPCPrice[3] = 200
set NPCAverage[3] = 45
set CommodityName[4] = "Swords"
set ProductionID[4] = 'A03E' //
set ConsumptionID[4] = 'A03F' //
set ProductionPerLevel[4] = 10
set ConsumptionPerLevel[4] = 1
set BasePrice[4] = 320
set NPCPrice[4] = 250
set NPCAverage[4] = 20
set CommodityName[5] = "Mana"
set ProductionID[5] = 'A03G' //
set ConsumptionID[5] = 'A03H' //
set ProductionPerLevel[5] = 1000
set ConsumptionPerLevel[5] = 1000
set BasePrice[5] = 1
set NPCPrice[5] = 2
set NPCAverage[5] = 6000
set CommodityName[6] = "Craft Goods"
set ProductionID[6] = 'A03J' //
set ConsumptionID[6] = 'A03I' //
set ProductionPerLevel[6] = 10
set ConsumptionPerLevel[6] = 10
set BasePrice[6] = 80
set NPCPrice[6] = 200
set NPCAverage[6] = 75
// Creates some base supply and demand at the start of the game.
call InitNPCValues()
debug call BJDebugMsg("Init income Finished")
endmethod
// This method is left public for debuging reasons (so it can be reseeded using a debug command)
// This method sets the NPC suply and demand for each commodity.
// It should be used only once, at map initilization.
// Each commodity demand is set to a random variation of an average demand. (called NPCAverage)
public static method InitNPCValues takes nothing returns nothing
set LoopIndex = 1
loop
exitwhen LoopIndex == 7
set NPCSupply[LoopIndex] = R2I(I2R(NPCAverage[LoopIndex]) * GetRandomReal(0.5,1.5))
set NPCDemand[LoopIndex] = R2I(I2R(NPCAverage[LoopIndex]) * GetRandomReal(0.5,1.5))
debug call BJDebugMsg(CommodityName[LoopIndex] + ": Supply =" + I2S(NPCSupply[LoopIndex]) + " Demand = " + I2S(NPCDemand[LoopIndex]))
set LoopIndex = LoopIndex + 1
endloop
endmethod
//debuging functions
public static method SetNPCDemand takes integer TargetCommodityIndex, integer NewDemand returns nothing
set NPCDemand[TargetCommodityIndex]=NewDemand
debug call BJDebugMsg("Updating " + I2S(TargetCommodityIndex))
debug call BJDebugMsg(CommodityName[TargetCommodityIndex] + ": Supply =" + I2S(NPCSupply[TargetCommodityIndex]) + " Demand = " + I2S(NPCDemand[TargetCommodityIndex]))
endmethod
public static method SetNPCSupply takes integer TargetCommodityIndex, integer NewSupply returns nothing
set NPCSupply[TargetCommodityIndex]=NewSupply
debug call BJDebugMsg("Updating " + I2S(TargetCommodityIndex))
debug call BJDebugMsg(CommodityName[TargetCommodityIndex] + ": Supply =" + I2S(NPCSupply[TargetCommodityIndex]) + " Demand = " + I2S(NPCDemand[TargetCommodityIndex]))
endmethod
// Multiboard stuff starts here
private static multiboard EconomyMultiboard
private static method SetEconBoardItemValue takes integer x, integer y, string value, real width, boolean title returns nothing
local multiboarditem tempItem = MultiboardGetItem(EconomyMultiboard,x,y)
call MultiboardSetItemValue(tempItem,value)
call MultiboardSetItemWidth(tempItem,width)
call MultiboardSetItemStyle(tempItem, true, false)
if title == true then
call MultiboardSetItemValueColor(tempItem, 207,175,55,0)
endif
set tempItem = null
endmethod
private static method CreateEconomyMultiboard takes nothing returns boolean
local integer rowIndex = 1
local integer finalRow = CommodityTotal + 1
local real defaultRowWidth = 0.06
set EconomyMultiboard = CreateMultiboard()
debug call BJDebugMsg("Init Economy Multiboard")
call MultiboardClear(EconomyMultiboard)
call MultiboardSetColumnCount(EconomyMultiboard, 4)
call MultiboardSetRowCount(EconomyMultiboard, finalRow)
call MultiboardSetTitleText(EconomyMultiboard,"Commodity Prices")
// Titles
call SetEconBoardItemValue(0,0, "Commodity", defaultRowWidth,true)
call SetEconBoardItemValue(0,1, "Price", defaultRowWidth,true)
call SetEconBoardItemValue(0,2, "Base Price", defaultRowWidth,true)
call SetEconBoardItemValue(0,3, "Valuation", defaultRowWidth,true)
loop
exitwhen rowIndex == finalRow
call SetEconBoardItemValue(rowIndex,0, CommodityName[rowIndex], defaultRowWidth,true)
call SetEconBoardItemValue(rowIndex,1, "0", defaultRowWidth,false)
call SetEconBoardItemValue(rowIndex,2, R2S(BasePrice[rowIndex]), defaultRowWidth,false)
call SetEconBoardItemValue(rowIndex,3, "0", defaultRowWidth,false)
set rowIndex = rowIndex +1
endloop
call MultiboardDisplay(EconomyMultiboard,true)
return false
endmethod
private static method GetValuation takes real valuationPrice, integer index returns string
local string Valuation = "Very Cheap"
if (valuationPrice >= BasePrice[index] * 0.5) then
set Valuation = "Quite Cheap"
endif
if (valuationPrice >= BasePrice[index] * 0.75) then
set Valuation = "Slighly Cheap"
endif
if (valuationPrice >= BasePrice[index]*0.95) then
set Valuation = "Standard"
endif
if (valuationPrice >= BasePrice[index]*1.05) then
set Valuation = "Above Average"
endif
if (valuationPrice >= BasePrice[index] * 1.5) then
set Valuation = "Quite Expensive"
endif
if (valuationPrice >= BasePrice[index] * 2) then
set Valuation = "Very Expensive"
endif
return Valuation
endmethod
private static method UpdateEconMultiboard takes nothing returns boolean
local integer rowIndex = 1
local integer finalRow = CommodityTotal + 1
debug call BJDebugMsg("Updating multiboard")
call updatePrices()
loop
exitwhen rowIndex == finalRow
call MultiboardSetItemValue(MultiboardGetItem(EconomyMultiboard,rowIndex,1),R2S(CommodityPrices[rowIndex]))
call MultiboardSetItemValue(MultiboardGetItem(EconomyMultiboard,rowIndex,3),GetValuation(CommodityPrices[rowIndex], rowIndex))
set rowIndex = rowIndex +1
endloop
call MultiboardDisplay(EconomyMultiboard,true)
return false
endmethod
// Multiboard stuff ends here
// Main trigger which runs the entire economy system.
// Runs once per economy timer
public static method run takes nothing returns nothing
debug call BJDebugMsg("Running Economy System")
set CommodityIndex = 1 // This needs to be rest every time run is called
// Make sure all printers are full of blank lines (printers are varialbes which concentrate strings)
call InitPrinters()
// Set the total amount of money each player recives to 0
call InitTotal()
call PrintToHumans("|c00ffcc00----------------= Economic Report =-----------------|r")
// Calculate the global prices and decide how much money each pleyer gets
call CommoditiesLoop()
// Communicate prices and buy/sell ratios to all the players
call PrintInfo()
call PrintToHumans("|c0000cc00You gain 1000 currency from your personal wealth|r")
// This is where we give all of the players their gold, or take it away if they lost money.
call DistributeMoney()
// Give the demons resources based on curruption values
call DemonEconomy()
debug call BJDebugMsg("Economy System Finish")
//return false
endmethod
// Fill all the printer variables with blank lines
private static method InitPrinters takes nothing returns nothing
//debug call BJDebugMsg("Initing Printers")
set LoopIndex = 1
loop
set printer[LoopIndex] = ""
set printer2[LoopIndex] = ""
set printer3[LoopIndex] = ""
set printer4[LoopIndex] = ""
exitwhen LoopIndex > 9
set LoopIndex = LoopIndex + 1
endloop
//debug call BJDebugMsg("Done Initing Printers")
endmethod
// reset the total amount of gold each player gets to 0
private static method InitTotal takes nothing returns nothing
set LoopIndex = 1
loop
set total[LoopIndex] = 0
exitwhen LoopIndex > 9
set LoopIndex = LoopIndex + 1
endloop
endmethod
// Calculate the amount of a certain commodity is being produced or used by a certain player.
public static method ComputeCommodityProduction takes integer ID, integer PerLevel, player whichPlayer returns integer
local group g
local integer sum = 0
local unit u
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g, whichPlayer, null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
set sum = sum + GetUnitAbilityLevel(u, ID)
call GroupRemoveUnit(g, u)
endloop
call DestroyGroup(g)
set g = null
set u = null
return sum * PerLevel
endmethod
// Calculate what the price of commodity should be based on supply, demand, its base price, and a 3/4ths root curve.
public static method CalculateCommodityPrice takes real BasePrice, real Demand, real Supply returns real
local real Multiplier = Pow(Demand/Supply, 0.75)
return BasePrice*Multiplier
endmethod
// Update the prices for each comodity as stored in the CommodityPrices array.
// Prices are then used in both the main economy and to update the multiboard.
private static method updatePrices takes nothing returns nothing
local integer PriceCommodityIndex = 1
local real Price = 1
loop
set GlobalDemand = 0
set GlobalSupply = 0
set LoopIndex = 1
loop
set LoopPlayer = Player(LoopIndex - 1)
set Demand[LoopIndex] = ComputeCommodityProduction(ConsumptionID[PriceCommodityIndex], ConsumptionPerLevel[PriceCommodityIndex], LoopPlayer)
set Supply[LoopIndex] = ComputeCommodityProduction(ProductionID[PriceCommodityIndex], ProductionPerLevel[PriceCommodityIndex], LoopPlayer)
set GlobalSupply = GlobalSupply + Supply[LoopIndex]
set GlobalDemand = GlobalDemand + Demand[LoopIndex]
exitwhen LoopIndex > 9
set LoopIndex = LoopIndex + 1
endloop
set GlobalSupply = GlobalSupply + NPCSupply[PriceCommodityIndex]
set GlobalDemand = GlobalDemand + NPCDemand[PriceCommodityIndex]
set Price = NPCPrice[CommodityIndex] // Price to be used if there is no supply to avoid
// a division by zero error.
if GlobalSupply > 0 then
set Price = CalculateCommodityPrice(BasePrice[PriceCommodityIndex], I2R(GlobalDemand), I2R(GlobalSupply))
endif
set CommodityPrices[PriceCommodityIndex] = Price
exitwhen PriceCommodityIndex == CommodityTotal
set PriceCommodityIndex = PriceCommodityIndex + 1
endloop
endmethod
// In this function we determine how much supply and demand there is for each commodity.
// As we go we store the amount each player is producing as string.
// Allso deals with tax income
private static method CommoditiesLoop takes nothing returns nothing
local real Price = 1
call updatePrices()
set CommodityIndex = 1
loop // for each commodity
// Get and store each players demand for the commodity we are working with
// Also handle their tax income
set LoopIndex = 1
loop //for each player
set LoopPlayer = Player(LoopIndex - 1)
set Demand[LoopIndex] = ComputeCommodityProduction(ConsumptionID[CommodityIndex], ConsumptionPerLevel[CommodityIndex], LoopPlayer)
set Supply[LoopIndex] = ComputeCommodityProduction(ProductionID[CommodityIndex], ProductionPerLevel[CommodityIndex], LoopPlayer)
set TaxIncome[LoopIndex] = ComputeCommodityProduction('A037', 1000 , LoopPlayer)
exitwhen LoopIndex > 9
set LoopIndex = LoopIndex + 1
endloop
set Price = CommodityPrices[CommodityIndex]
// Store the price of the commodity we are working with (printer 1 will be printed to all players)
set printer[1] = printer[1] + CommodityName[CommodityIndex] + " costs " + R2S(Price) + " || "
// Print to each player how much they have and require of each commodity.
// Then print out how much money they made or lost on each commodity.
set LoopIndex = 1
loop
set LoopPlayer = Player(LoopIndex - 1)
set printer2[LoopIndex] = printer2[LoopIndex] + "You have " + I2S (Supply[LoopIndex]) + " " + CommodityName[CommodityIndex] + " || "
set printer3[LoopIndex] = printer3[LoopIndex] + "You require " + I2S (Demand[LoopIndex]) + " " + CommodityName[CommodityIndex] + " || "
set CurrencyCalculation = R2I((Supply[LoopIndex]-Demand[LoopIndex]) * Price)
if (CurrencyCalculation > 0) then
set printer4[LoopIndex] = printer4[LoopIndex] + "|c0000cc00 You made " + I2S (CurrencyCalculation) + " Currency selling " + CommodityName[CommodityIndex] + "|r || "
elseif (CurrencyCalculation < 0) then
set printer4[LoopIndex] = printer4[LoopIndex] + "|c00990000 You lost " + I2S (IAbsBJ(CurrencyCalculation)) + " Currency buying " + CommodityName[CommodityIndex] + "|r||"
else
set printer4[LoopIndex] = printer4[LoopIndex] + "|c00999999You did not trade " + CommodityName[CommodityIndex] + "|r || "
endif
set total[LoopIndex] = total[LoopIndex] + CurrencyCalculation
exitwhen LoopIndex > 9
set LoopIndex = LoopIndex + 1
endloop
// When half the information for half commodities have been stored in the pritners display the information to the screne and clear them
if CommodityIndex == 3 then
call PrintInfo()
call InitPrinters()
endif
// Exit the loop when all commodities have been looped through
exitwhen CommodityIndex == CommodityTotal
set CommodityIndex = CommodityIndex + 1
endloop // Exit commodities loop
endmethod
// Prints out half the economy system information at once.
// Should be called twice, once halfway through the comodities loop and once at the end of the comodities loop
private static method PrintInfo takes nothing returns nothing
set LoopIndex = 1
call PrintToHumans (printer[1])
loop
call DisplayTimedTextToPlayer(Player(LoopIndex - 1),0,0,30,printer2[LoopIndex])
call DisplayTimedTextToPlayer(Player(LoopIndex - 1),0,0,30,printer3[LoopIndex])
call DisplayTimedTextToPlayer(Player(LoopIndex - 1),0,0,30,printer4[LoopIndex])
exitwhen LoopIndex > 9
set LoopIndex = LoopIndex + 1
endloop
endmethod
// Give all the players their money, taking into account bonuses and debts.
private static method DistributeMoney takes nothing returns nothing
// Bonuses Tax and Totals
// Culture 1 = Normal, 2 = Mercantalist, 3 = Barb, 4 = Imperial
set LoopIndex = 1
loop
call DisplayTimedTextToPlayer(Player(LoopIndex - 1),0,0,30, "Tax income = " + I2S(TaxIncome[LoopIndex]))
set total[LoopIndex] = total[LoopIndex] + 1000
set total[LoopIndex] = total[LoopIndex] + TaxIncome[LoopIndex]
// Merchant Bonus
if (udg_CultureType[LoopIndex] == 2) then
if (total[LoopIndex] > 0) then
set AdjustedTotal = R2I(I2R(total[LoopIndex]) * MerchantBonus)
else
set AdjustedTotal = total[LoopIndex]
endif
call DisplayTimedTextToPlayer(Player(LoopIndex - 1),0,0,30, "Total income = " + I2S(total[LoopIndex]) + " With Merchant Bonus = " + I2S(AdjustedTotal))
// Barbrian Penalty
elseif (udg_CultureType[LoopIndex] == 3) then
if total[LoopIndex] > 0 then
set AdjustedTotal = R2I(I2R(total[LoopIndex]) * BarbarianPenalty)
else
set AdjustedTotal = total[LoopIndex]
endif
call DisplayTimedTextToPlayer(Player(LoopIndex - 1),0,0,30, "Total income = " + I2S(total[LoopIndex]) + " With Barbarian Penalty = " + I2S(AdjustedTotal))
// Everyone else
else
set AdjustedTotal = total[LoopIndex]
call DisplayTimedTextToPlayer(Player(LoopIndex - 1),0,0,30, "Total income = " + I2S(AdjustedTotal))
endif
if (udg_IncomeRansomDeduct[LoopIndex] > 0) then
if (udg_IncomeRansomDeduct[LoopIndex] > AdjustedTotal) then
set udg_IncomeRansomDeduct[LoopIndex] = udg_IncomeRansomDeduct[LoopIndex] - AdjustedTotal
call SetPlayerState(udg_PlayerOwed[LoopIndex], PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(udg_PlayerOwed[LoopIndex],PLAYER_STATE_RESOURCE_GOLD) + AdjustedTotal)
call DisplayTimedTextToPlayer(udg_PlayerOwed[LoopIndex],0,0,30, "You recieved " + I2S(AdjustedTotal) + " Gold from a ransom")
call DisplayTimedTextToPlayer(Player(LoopIndex - 1),0,0,30, "Unfortunatly you give up all of your income to pay ransoms you still owe " + I2S(udg_IncomeRansomDeduct[LoopIndex]) + " Gold")
set AdjustedTotal = 0
else
call SetPlayerState(udg_PlayerOwed[LoopIndex], PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(udg_PlayerOwed[LoopIndex],PLAYER_STATE_RESOURCE_GOLD) + udg_IncomeRansomDeduct[LoopIndex])
call DisplayTimedTextToPlayer(udg_PlayerOwed[LoopIndex],0,0,30, "You recieved " + I2S(AdjustedTotal) + " Gold from a ransom")
call DisplayTimedTextToPlayer(Player(LoopIndex - 1),0,0,30, "Unfortunatly you give up " + I2S(udg_IncomeRansomDeduct[LoopIndex]) + " Gold to a ransom")
set AdjustedTotal = AdjustedTotal - udg_IncomeRansomDeduct[LoopIndex]
set udg_IncomeRansomDeduct[LoopIndex] = 0
endif
endif
call SetPlayerState(Player(LoopIndex - 1), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(Player(LoopIndex - 1),PLAYER_STATE_RESOURCE_GOLD) + AdjustedTotal)
set TotalCommerce = TotalCommerce + AdjustedTotal
exitwhen LoopIndex > 9
set LoopIndex = LoopIndex + 1
endloop
endmethod
private static method DemonEconomy takes nothing returns nothing
call DisplayTimedTextToPlayer(Player(10),0,0,30, "|c0000cc00 You recieved " + R2S(Curruption * 100.0) +"% of the human economy which is " + R2S(I2R(TotalCommerce)*Curruption) + " Gold |r" )
call DisplayTimedTextToPlayer(Player(11),0,0,30, "|c0000cc00 You recieved " + R2S(Curruption * 100.0) +"% of the human economy which is " + R2S(I2R(TotalCommerce)*Curruption) + " Gold |r" )
call AddGold(Player(10), R2I(I2R(TotalCommerce)*Curruption))
call AddGold(Player(11), R2I(I2R(TotalCommerce)*Curruption))
endmethod
endstruct
If you would like any clarification about how any part of the system works feel free to ask (I know that it is far from the cleanest of code).
Thank you for your time.
Update: Changed ConvertedPlayer() to use native. Added more comments and simplified code a little.
Last edited: