Wasn't intended for this tutorial, but it'd fit right in. I coded this as an answer for someone's question on the forum about building units from a barracks.
Should be commented enough to explain everything. I may at some point get around to officially typing this into the tutorial.
Press 's' or 't' to build a unit and watch the loading bars display the current build progress.
REM just some variables I like to use
#CONSTANT FALSE = 0
#CONSTANT TRUE = 1
REM name - of this building
REM maxHp - maximum hitpoints
REM buildTime - unit build time in milliseconds
type BuildingStatsObject
name as string
maxHp as integer
buildTime as integer
endtype
REM stats - basically refers to the type of building this is
REM hp - current hitpoints of building
REM isBuilding - true if this building is in the process of recruiting
REM buildStart - a timestamp of when it started the current recruiting process
type Building
stats as integer
hp as integer
isBuilding as boolean
buildStart as dword
endtype
REM array to hold all our different building types
dim buildingStats(0) as BuildingStatsObject
REM array to hold all of our actual buildings
dim buildings(0) as Building
REM this is our build queue, which keeps track of
REM which buildings are processing new units
dim buildQueue(0)
REM create some buildings
temp1 = addBuildingStatsObject("Barracks", 150, 5000)
temp2 = addBuildingStatsObject("Factory", 350, 7000)
REM store the array indices of the different building types
GLOBAL BARRACKS_ID = temp1
GLOBAL FACTORY_ID = temp2
REM create some buildings to play with
addBuilding(BARRACKS_ID, buildingStats(BARRACKS_ID).maxHp)
addBuilding(BARRACKS_ID, 50) : `a damaged barracks
addBuilding(FACTORY_ID, buildingStats(FACTORY_ID).maxHp)
REM variable for storing current time so
REM everything each loop sees the same time
timestamp as dword
REM Currently, we have 3 buildings in the array
REM as we defined above
set cursor 0,0
print ""
drawStatus(200, 10, 0,0,0)
drawStatus(350, 10, 0,0,0)
drawStatus(500, 10, 0,0,0)
REM ========== MAIN LOOP ==========
DO
REM sort of keeps everything synced
timestamp = timer()
REM User test
gosub TEST
REM loop through all buildings
for b = 1 to array count(buildings())
REM check to see if any buildings are in the process of recruiting
if buildings(b).isBuilding = TRUE
drawStatus(b*150+50,10,buildings(b).buildStart, timestamp, buildingStats(buildings(b).stats).buildTime)
if buildings(b).buildStart + buildingStats(buildings(b).stats).buildTime <= timestamp
REM this building has finished recruiting the current unit
print buildingStats(buildings(b).stats).name,"(",b,") has finished building a new unit."
spawnNewUnit(b)
REM this removes the finished unit from the build queue
REM if this building has any more units left to build then
REM isBuilding stays TRUE, otherwise FALSE
anyLeft = removeFromBuildQueue(b)
if anyLeft = TRUE
buildings(b).isBuilding = TRUE
REM setup variables for building next unit
buildings(b).buildStart = timestamp
print buildingStats(buildings(b).stats).name,"(",b,") has started building a new unit at ",timestamp
else
buildings(b).isBuilding = FALSE
print buildingStats(buildings(b).stats).name,"(",b,") has no more units left to build in its queue."
endif
endif
endif
next b
LOOP
function drawStatus(x, y, t1#, t2#, t3#)
ink rgb(100,100,100),0
box x, y,x+100,y+10
process = ((t2#-t1#)/t3#)*100
ink rgb(150,0,255),0
box x, y,x+process,y+10
endfunction
REM ======= USER TEST ========
TEST:
rem add soldier to build queue, from a random barracks
if inkey$() = "s" and flag = 0 then addToBuildQueue(rnd(1)+1) : flag = 1 : print "Soldier added to queue"
if inkey$() = "t" and flag = 0 then addToBuildQueue(3) : flag = 1 : print "Tank added to queue"
if inkey$() = "" then flag = 0
RETURN
REM SHOULDN'T NEED TO USE THIS
REM Returns true if the building referenced
REM by 'id' has more elements left in the queue
function hasMoreInBuildQueue(id as integer)
for i = 1 to array count(buildQueue())
if buildQueue(i) = id then exitfunction TRUE
next i
endfunction FALSE
REM removes an item from the build queue
REM id - array index reference of which building has produced the item
REM since a building can only produce 1 unit at a time and this is a queue,
REM the first element in the array that matches the building id is the
REM finished unit
REM Returns true if the building has more elements left in the queue
function removeFromBuildQueue(id as integer)
delete = -1
anyLeft = FALSE
for i = 1 to array count(buildQueue())
if buildQueue(i) = id
if delete = -1
delete = i
else
anyLeft = TRUE
exit
endif
endif
next i
if delete > -1 then array delete element buildQueue(delete)
endfunction anyLeft
REM adds an item to the build queue
REM id - array index reference of which building is producing this unit
function addToBuildQueue(id as integer)
array insert at bottom buildQueue()
index = array count(buildQueue())
buildQueue(index) = id
REM flag to building to tell it to start processing
if buildings(id).isBuilding = FALSE
buildings(id).isBuilding = TRUE
buildings(id).buildStart = timer()
endif
endfunction
REM adds a new building to the array
function addBuilding(id as integer, hp as integer)
temp as Building
temp.stats = id
temp.hp = hp
temp.isBuilding = FALSE
temp.BuildStart = 0
array insert at bottom buildings()
buildings(array count(buildings())) = temp
endfunction
REM adds a new building type to the array
REM returns this building's index in the array
function addBuildingStatsObject(name as string, hp as integer, time as integer)
temp as BuildingStatsObject
temp.name = name
temp.maxHp = hp
temp.buildTime = time
array insert at bottom buildingStats()
index = array count(buildingStats())
buildingStats(index) = temp
endfunction index
REM After a unit has been produced from its building,
REM anything that needs to be done to actually create
REM the physical unit goes here.
REM id is the building, so that we know which type
REM of unit to create
function spawnNewUnit(id as integer)
if buildings(id).stats = BARRACKS_ID
rem create a soldier
endif
if buildings(id).stats = FACTORY_ID
rem create a tank
endif
endfunction