native GetUnitBuildTime takes integer unitid returns integer
Name | Type | is_array | initial_value |
library GameStatus uses optional PlayerUtils
/***************************************************************
*
* v1.0.0 by TriggerHappy
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* Simple API for detecting if the game is online, offline, or a replay.
* _________________________________________________________________________
* 1. Installation
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* Copy the script to your map and save it (requires JassHelper *or* JNGP)
* _________________________________________________________________________
* 2. API
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* This library provides one function
*
* function GetGameStatus takes nothing returns integer
*
* It returns one of the following constants
*
* - GAME_STATUS_OFFLINE
* - GAME_STATUS_ONLINE
* - GAME_STATUS_REPLAY
*
***************************************************************/
// Configuration:
globals
// The dummy unit is only created once, and removed directly after.
private constant integer DUMMY_UNIT_ID = 'hfoo'
endglobals
// (end)
globals
constant integer GAME_STATUS_OFFLINE = 0
constant integer GAME_STATUS_ONLINE = 1
constant integer GAME_STATUS_REPLAY = 2
private integer status = 0
endglobals
function GetGameStatus takes nothing returns integer
return status
endfunction
private module GameStatusInit
private static method onInit takes nothing returns nothing
local player firstPlayer
local unit u
local boolean selected
// find an actual player
static if not (LIBRARY_PlayerUtils) then
set firstPlayer = Player(0)
loop
exitwhen (GetPlayerController(firstPlayer) == MAP_CONTROL_USER and GetPlayerSlotState(firstPlayer) == PLAYER_SLOT_STATE_PLAYING)
set firstPlayer = Player(GetPlayerId(firstPlayer)+1)
endloop
else
set firstPlayer = User.fromPlaying(0).toPlayer()
endif
// force the player to select a dummy unit
set u = CreateUnit(firstPlayer, DUMMY_UNIT_ID, 0, 0, 0)
call SelectUnit(u, true)
set selected = IsUnitSelected(u, firstPlayer)
call RemoveUnit(u)
set u = null
if (selected) then
// detect if replay or offline game
if (ReloadGameCachesFromDisk()) then
set status = GAME_STATUS_OFFLINE
else
set status = GAME_STATUS_REPLAY
endif
else
// if the unit wasn't selected instantly, the game is online
set status = GAME_STATUS_ONLINE
endif
endmethod
endmodule
private struct GameStatus
implement GameStatusInit
endstruct
endlibrary
library FrameLoader initializer init_function
// in 1.31 and upto 1.32.9 PTR (when I wrote this). Frames are not correctly saved and loaded, breaking the game.
// This library runs all functions added to it with a 0s delay after the game was loaded.
// function FrameLoaderAdd takes code func returns nothing
// func runs when the game is loaded.
globals
private trigger eventTrigger = CreateTrigger()
private trigger actionTrigger = CreateTrigger()
private timer t = CreateTimer()
endglobals
function FrameLoaderAdd takes code func returns nothing
call TriggerAddAction(actionTrigger, func)
endfunction
private function timerAction takes nothing returns nothing
call TriggerExecute(actionTrigger)
endfunction
private function eventAction takes nothing returns nothing
call TimerStart(t, 0, false, function timerAction)
endfunction
private function init_function takes nothing returns nothing
call TriggerRegisterGameEvent(eventTrigger, EVENT_GAME_LOADED)
call TriggerAddAction(eventTrigger, function eventAction)
endfunction
endlibrary
library ProductionDataRepository initializer InitProductionDataRepository
globals
hashtable ProductionTable = InitHashtable()
integer TypeIdBaseProductionTime = -1 // typeId - base build time (research, hero)
integer TypeIdIncrementProductionTime = -2 // typeId - level increment build time (research)
integer IsTypeIdResearch = -5 // type id - can create an unit out of this id
integer TypeIdIconPath = -100 // TODO
real DefaultProductionTime = 0 // fallback value, will result in the progression bar not updating
real DefaultBaseHeroProductionTime = 55 // the default training time for Melee heroes
real DefaultBaseResearchProductionTime = 60 // all multi-tiered researches (weapon, armor, caster, human wood/buildings, orc spikes...)
real DefaultIncreamentResearchProductionTime = 15 // all multi-tiered researches (weapon, armor, caster, human wood/buildings, orc spikes...)
endglobals
// setters for hard-coded production time values
function SetTypeIdBaseProductionTime takes integer typeId, real baseProductionTime returns nothing
call SaveReal(ProductionTable, TypeIdBaseProductionTime, typeId, baseProductionTime)
endfunction
function SetTypeIdIncrementProductionTime takes integer typeId, real incrementProductionTime returns nothing
call SaveReal(ProductionTable, TypeIdIncrementProductionTime, typeId, incrementProductionTime)
endfunction
// setters for hard-coded icon path
function SetTypeIdIconPath takes integer typeId, integer level, string iconPath returns nothing
call SaveStr(ProductionTable, TypeIdIconPath - level, typeId, iconPath)
endfunction
// utility getters
function IsUnitId takes integer typeId returns boolean
return GetUnitBuildTime(typeId) > 0
endfunction
function IsResearchId takes integer typeId returns boolean
local unit temp
if(IsUnitId(typeId))then
return false
endif
if(HaveSavedBoolean(ProductionTable, IsTypeIdResearch, typeId) == false)then
set temp = CreateUnit(Player(0), typeId, 0, 0, 0)
call SaveBoolean(ProductionTable, IsTypeIdResearch, typeId, temp == null)
call RemoveUnit(temp)
set temp = null
endif
return LoadBoolean(ProductionTable, IsTypeIdResearch, typeId)
endfunction
function IsHeroId takes integer typeId returns boolean
if(IsHeroUnitId(typeId) == false)then
return false
endif
return IsResearchId(typeId) == false // IsHeroUnitId returns true for some research, so we have to double-check that
endfunction
// production time getters
function GetTypeIdProductionTime takes integer typeId returns real
local real output = GetUnitBuildTime(typeId)
// try use the object data time if any
if(output != 0)then
return output
endif
// try to use a user defined base production time
if(HaveSavedReal(ProductionTable, TypeIdBaseProductionTime, typeId))then
set output = LoadReal(ProductionTable, TypeIdBaseProductionTime, typeId)
endif
// if no user-defined production time exists, try to use default hero production time
if(output == 0 and IsHeroUnitId(typeId))then
return DefaultBaseHeroProductionTime
endif
// if a user-defined prouction time exists, and we are not dealing ith a hero, use that
if(output != 0 and IsHeroUnitId(typeId) == false)then
return output
endif
// use the fallback value, causing the progress bar to not update
return DefaultProductionTime
endfunction
function GetHeroReviveTime takes integer typeId, integer level returns real
if(level == 1)then
return 36.0
elseif(level == 2)then
return 72.0
elseif(level == 3)then
return 107.0
else // >= 4
return 110.0
endif
endfunction
function GetResearchTime takes integer typeId, integer level returns real
local real baseTime = DefaultBaseResearchProductionTime
local real incrementTime = DefaultIncreamentResearchProductionTime
if(HaveSavedReal(ProductionTable, TypeIdBaseProductionTime, typeId))then
set baseTime = LoadReal(ProductionTable, TypeIdBaseProductionTime, typeId)
endif
if(level == 1)then
return baseTime
endif
if(HaveSavedReal(ProductionTable, TypeIdIncrementProductionTime, typeId))then
set incrementTime = LoadReal(ProductionTable, TypeIdIncrementProductionTime, typeId)
endif
return baseTime + (level - 1) * incrementTime
endfunction
// icon path getter
function GetTypeIdIconPath takes integer typeId, integer level returns string
if(HaveSavedString(ProductionTable, TypeIdIconPath - level, typeId))then
return LoadStr(ProductionTable, TypeIdIconPath - level, typeId)
endif
return BlzGetAbilityIcon(typeId)
endfunction
// init function
function InitProductionDataRepository takes nothing returns nothing
// USER DEFINED HERO TIMES
// call SetTypeIdBaseProductionTime('Hpal', 55)
// USER DEFINED RESEARCH ICONS
// human
call SetTypeIdIconPath('Rhme', 2, "ReplaceableTextures\\CommandButtons\\BTNThoriumMelee.blp")
call SetTypeIdIconPath('Rhme', 3, "ReplaceableTextures\\CommandButtons\\BTNArcaniteMelee.blp")
call SetTypeIdIconPath('Rhar', 2, "ReplaceableTextures\\CommandButtons\\BTNHumanArmorUpTwo.blp")
call SetTypeIdIconPath('Rhar', 3, "ReplaceableTextures\\CommandButtons\\BTNHumanArmorUpThree.blp")
call SetTypeIdIconPath('Rhra', 2, "ReplaceableTextures\\CommandButtons\\BTNHumanMissileUpTwo.blp")
call SetTypeIdIconPath('Rhra', 3, "ReplaceableTextures\\CommandButtons\\BTNHumanMissileUpThree.blp")
call SetTypeIdIconPath('Rhla', 2, "ReplaceableTextures\\CommandButtons\\BTNLeatherUpgradeTwo.blp")
call SetTypeIdIconPath('Rhla', 3, "ReplaceableTextures\\CommandButtons\\BTNLeatherUpgradeThree.blp")
call SetTypeIdIconPath('Rhpt', 2, "ReplaceableTextures\\CommandButtons\\BTNPriestMaster.blp")
call SetTypeIdIconPath('Rhst', 2, "ReplaceableTextures\\CommandButtons\\BTNSorceressMaster.blp")
call SetTypeIdIconPath('Rhlh', 2, "ReplaceableTextures\\CommandButtons\\BTNHumanLumberUpgrade2.blp")
call SetTypeIdIconPath('Rhpt', 2, "ReplaceableTextures\\CommandButtons\\BTNArcaniteArchitecture.blp")
call SetTypeIdIconPath('Rhst', 3, "ReplaceableTextures\\CommandButtons\\BTNImbuedMasonry.blp")
// orc
call SetTypeIdIconPath('Rome', 2, "ReplaceableTextures\\CommandButtons\\BTNOrcMeleeUpTwo.blp")
call SetTypeIdIconPath('Rome', 3, "ReplaceableTextures\\CommandButtons\\BTNOrcMeleeUpThree.blp")
call SetTypeIdIconPath('Rora', 2, "ReplaceableTextures\\CommandButtons\\BTNThoriumRanged.blp")
call SetTypeIdIconPath('Rora', 3, "ReplaceableTextures\\CommandButtons\\BTNArcaniteRanged.blp")
call SetTypeIdIconPath('Roar', 2, "ReplaceableTextures\\CommandButtons\\BTNThoriumArmor.blp")
call SetTypeIdIconPath('Roar', 3, "ReplaceableTextures\\CommandButtons\\BTNArcaniteArmor.blp")
call SetTypeIdIconPath('Rost', 2, "ReplaceableTextures\\CommandButtons\\BTNShamanMaster.blp")
call SetTypeIdIconPath('Rowd', 2, "ReplaceableTextures\\CommandButtons\\BTNWitchDoctorMaster.blp")
call SetTypeIdIconPath('Rowt', 2, "ReplaceableTextures\\CommandButtons\\BTNSpiritWalkerMasterTraining.blp")
call SetTypeIdIconPath('Rosp', 2, "ReplaceableTextures\\CommandButtons\\BTNImprovedSpikedBarricades.blp")
call SetTypeIdIconPath('Rosp', 3, "ReplaceableTextures\\CommandButtons\\BTNAdvancedSpikedBarricades.blp")
// undead
call SetTypeIdIconPath('Rume', 2, "ReplaceableTextures\\CommandButtons\\BTNImprovedUnholyStrength.blp")
call SetTypeIdIconPath('Rume', 3, "ReplaceableTextures\\CommandButtons\\BTNAdvancedUnholyStrength.blp")
call SetTypeIdIconPath('Ruar', 2, "ReplaceableTextures\\CommandButtons\\BTNImprovedUnholyArmor.blp")
call SetTypeIdIconPath('Ruar', 3, "ReplaceableTextures\\CommandButtons\\BTNAdvancedUnholyArmor.blp")
call SetTypeIdIconPath('Rura', 2, "ReplaceableTextures\\CommandButtons\\BTNImprovedCreatureAttack.blp")
call SetTypeIdIconPath('Rura', 3, "ReplaceableTextures\\CommandButtons\\BTNAdvancedCreatureAttack.blp")
call SetTypeIdIconPath('Rucr', 2, "ReplaceableTextures\\CommandButtons\\BTNImprovedCreatureCarapace.blp")
call SetTypeIdIconPath('Rucr', 3, "ReplaceableTextures\\CommandButtons\\BTNAdvancedCreatureCarapace.blp")
call SetTypeIdIconPath('Rune', 2, "ReplaceableTextures\\CommandButtons\\BTNNecromancerMaster.blp")
call SetTypeIdIconPath('Ruba', 2, "ReplaceableTextures\\CommandButtons\\BTNBansheeMaster.blp")
// night elf
call SetTypeIdIconPath('Resm', 2, "ReplaceableTextures\\CommandButtons\\BTNImprovedStrengthOfTheMoon.blp")
call SetTypeIdIconPath('Resm', 3, "ReplaceableTextures\\CommandButtons\\BTNAdvancedStrengthOfTheMoon.blp")
call SetTypeIdIconPath('Rema', 2, "ReplaceableTextures\\CommandButtons\\BTNImprovedMoonArmor.blp")
call SetTypeIdIconPath('Rema', 3, "ReplaceableTextures\\CommandButtons\\BTNAdvancedMoonArmor.blp")
call SetTypeIdIconPath('Resw', 2, "ReplaceableTextures\\CommandButtons\\BTNImprovedStrengthOfTheWild.blp")
call SetTypeIdIconPath('Resw', 3, "ReplaceableTextures\\CommandButtons\\BTNAdvancedStrengthOfTheWild.blp")
call SetTypeIdIconPath('Rerh', 2, "ReplaceableTextures\\CommandButtons\\BTNImprovedReinforcedHides.blp")
call SetTypeIdIconPath('Rerh', 3, "ReplaceableTextures\\CommandButtons\\BTNAdvancedReinforcedHides.blp")
call SetTypeIdIconPath('Redc', 2, "ReplaceableTextures\\CommandButtons\\BTNDOCMasterTraining.blp")
call SetTypeIdIconPath('Redt', 2, "ReplaceableTextures\\CommandButtons\\BTNDOTMasterTraining.blp")
// other
call SetTypeIdIconPath('Rnat', 2, "ReplaceableTextures\\CommandButtons\\BTNNagaWeaponUp2.blp")
call SetTypeIdIconPath('Rnat', 3, "ReplaceableTextures\\CommandButtons\\BTNNagaWeaponUp3.blp")
call SetTypeIdIconPath('Rnam', 2, "ReplaceableTextures\\CommandButtons\\BTNNagaArmorUp2.blp")
call SetTypeIdIconPath('Rnam', 3, "ReplaceableTextures\\CommandButtons\\BTNNagaArmorUp3.blp")
call SetTypeIdIconPath('Rnsw', 2, "ReplaceableTextures\\CommandButtons\\BTNSirenMaster.blp")
// USER DEFINED RESEARCH TIMES
// human
call SetTypeIdBaseProductionTime('Rhan', 40)
call SetTypeIdBaseProductionTime('Rhpm', 20)
call SetTypeIdBaseProductionTime('Rhrt', 40)
call SetTypeIdBaseProductionTime('Rhcd', 35)
call SetTypeIdBaseProductionTime('Rhss', 45)
call SetTypeIdBaseProductionTime('Rhde', 45)
call SetTypeIdBaseProductionTime('Rhfc', 40)
call SetTypeIdBaseProductionTime('Rhfl', 30)
call SetTypeIdBaseProductionTime('Rhgb', 35)
call SetTypeIdBaseProductionTime('Rhfs', 40)
call SetTypeIdBaseProductionTime('Rhri', 30)
call SetTypeIdBaseProductionTime('Rhse', 30)
call SetTypeIdBaseProductionTime('Rhhb', 45)
call SetTypeIdBaseProductionTime('Rhsb', 40)
// orc
call SetTypeIdBaseProductionTime('Ropm', 20)
call SetTypeIdBaseProductionTime('Robk', 40)
call SetTypeIdBaseProductionTime('Robs', 40)
call SetTypeIdBaseProductionTime('Robf', 30)
call SetTypeIdBaseProductionTime('Roen', 40)
call SetTypeIdBaseProductionTime('Rovs', 40)
call SetTypeIdBaseProductionTime('Rolf', 75)
call SetTypeIdBaseProductionTime('Ropg', 45)
call SetTypeIdBaseProductionTime('Rows', 40)
//call SetTypeIdBaseProductionTime('Rorb', 60)
call SetTypeIdBaseProductionTime('Rotr', 35)
call SetTypeIdBaseProductionTime('Rwdm', 40)
// undead
call SetTypeIdBaseProductionTime('Rupm', 20)
call SetTypeIdBaseProductionTime('Rubu', 45)
call SetTypeIdBaseProductionTime('Ruac', 30)
//call SetTypeIdBaseProductionTime('Rusp', 60)
call SetTypeIdBaseProductionTime('Rupc', 45)
call SetTypeIdBaseProductionTime('Ruex', 20)
//call SetTypeIdBaseProductionTime('Rufb', 60)
call SetTypeIdBaseProductionTime('Rugf', 45)
//call SetTypeIdBaseProductionTime('Rusl', 60)
call SetTypeIdBaseProductionTime('Rusm', 45)
call SetTypeIdBaseProductionTime('Rusf', 40)
call SetTypeIdBaseProductionTime('Ruwb', 30)
// nightelf
call SetTypeIdBaseProductionTime('Resi', 45)
call SetTypeIdBaseProductionTime('Repm', 20)
call SetTypeIdBaseProductionTime('Recb', 40)
call SetTypeIdBaseProductionTime('Rehs', 40)
call SetTypeIdBaseProductionTime('Reht', 30)
call SetTypeIdBaseProductionTime('Reib', 35)
call SetTypeIdBaseProductionTime('Reeb', 20)
call SetTypeIdBaseProductionTime('Reec', 20)
call SetTypeIdBaseProductionTime('Remk', 40)
//call SetTypeIdBaseProductionTime('Renb', 60)
call SetTypeIdBaseProductionTime('Rers', 75)
call SetTypeIdBaseProductionTime('Resc', 20)
call SetTypeIdBaseProductionTime('Reuv', 45)
call SetTypeIdBaseProductionTime('Remg', 35)
//call SetTypeIdBaseProductionTime('Repb', 60)
call SetTypeIdBaseProductionTime('Rews', 30)
// special
call SetTypeIdBaseProductionTime('Rnsi', 45)
call SetTypeIdBaseProductionTime('Roch', 0)
call SetTypeIdBaseProductionTime('Rnen', 40)
call SetTypeIdBaseProductionTime('Rnsb', 20)
endfunction
endlibrary
library IntList
globals
intList EmptyIntList = -1
endglobals
struct intList
integer array data[24]
integer size
method ToString takes nothing returns string
local string output
local integer i
if(this.size == 0)then
return "<empty>"
endif
set output = I2S(this.data[0])
set i = 1
loop
exitwhen i == this.size or i == 255
set output = output + "," + I2S(this.data[i])
set i = i + 1
endloop
return output
endmethod
method AddValue takes integer value returns nothing
set this.data[this.size] = value
set this.size = this.size + 1
endmethod
method RemoveValue takes integer value returns nothing
local integer i = 0
local boolean removed = false
loop
exitwhen i == this.size or i == 255
if(removed)then
// shifting values
set this.data[i - 1] = this.data[i]
endif
if(removed == false and this.data[i] == value)then
// remove only the first instance of the value
set removed = true
endif
set i = i + 1
endloop
if(removed)then
set this.size = this.size - 1
endif
endmethod
method ContainsValue takes integer value returns boolean
local integer i = 0
loop
exitwhen i == this.size or i == 255
if(this.data[i] == value)then
return TRUE
endif
set i = i + 1
endloop
return FALSE
endmethod
method GetValueIndex takes integer value returns integer
local integer i = 0
loop
exitwhen i == this.size or i == 255
if(this.data[i] == value)then
return i
endif
set i = i + 1
endloop
return -1
endmethod
method GetValueIndexAfter takes integer value, integer after returns integer
local integer i = after
loop
exitwhen i >= this.size or i >= 255
if(this.data[i] == value)then
return i
endif
set i = i + 1
endloop
return -1
endmethod
method GetValueAt takes integer index returns integer
return this.data[index]
endmethod
endstruct
function CreateIntList takes nothing returns intList
local intList output = intList.create()
set output.size = 0
return output
endfunction
endlibrary
library ProductionData
struct productionData
integer typeId
string iconPath
real progress
integer count
unit producer
static method create takes integer typeId, string iconPath, real progress, integer count, unit producer returns thistype
local thistype this = productionData.allocate()
set this.typeId = typeId
set this.iconPath = iconPath
set this.progress = progress
set this.count = count
set this.producer = producer
return this
endmethod
method onDestroy takes nothing returns nothing
set this.producer = null
set this.iconPath = null
endmethod
endstruct
function CreateProductionData takes integer typeId, string iconPath, real progress, integer count, unit producer returns productionData
local productionData output = productionData.create(typeId, iconPath, progress, count, producer)
return output
endfunction
endlibrary
library ProductionPanelElement
struct productionPanelElement
static hashtable ProductionElementTable = InitHashtable()
private static integer ProductionTriggerUnit = 1
static method ProductionElementClickAction takes nothing returns nothing
local trigger t = GetTriggeringTrigger()
local player p = GetTriggerPlayer()
local unit u = LoadUnitHandle(productionPanelElement.ProductionElementTable, ProductionTriggerUnit, GetHandleId(t))
if(p == GetLocalPlayer())then
call ClearSelection()
call SelectUnit(u, true)
call SetCameraPosition(GetUnitX(u), GetUnitY(u))
endif
set t = null
set p = null
set u = null
endmethod
integer playerId
integer index
framehandle panel
framehandle element
framehandle iconButton
framehandle icon
framehandle number
framehandle progress
trigger onClick
method Show takes boolean flag returns nothing
call BlzFrameSetVisible(this.element, flag)
endmethod
method Update takes string iconPath, integer count, real progress, unit producer returns nothing
call BlzFrameSetTexture(this.icon, iconPath, 0, false)
call BlzFrameSetText(this.number, I2S(count))
call BlzFrameSetSize(this.progress, (IconSize - ProgressBarOffset * 2) * progress, ProgressBarSize)
if(HaveSavedHandle(ProductionElementTable, ProductionTriggerUnit, GetHandleId(onClick)))then
// cleanup existing unit handle
call RemoveSavedHandle(ProductionElementTable, ProductionTriggerUnit, GetHandleId(onClick))
endif
call SaveUnitHandle(ProductionElementTable, ProductionTriggerUnit, GetHandleId(onClick), producer)
endmethod
endstruct
function CreateProductionPanelElement takes integer playerId, integer index, framehandle panel, framehandle element, framehandle iconButton, framehandle icon, framehandle number, framehandle progress returns productionPanelElement
local productionPanelElement output = productionPanelElement.create()
set output.playerId = playerId
set output.index = index
set output.panel = panel
set output.element = element
set output.iconButton = iconButton
set output.icon = icon
set output.number = number
set output.progress = progress
set output.onClick = CreateTrigger()
call BlzTriggerRegisterFrameEvent(output.onClick, iconButton, FRAMEEVENT_CONTROL_CLICK)
call TriggerAddAction(output.onClick, function productionPanelElement.ProductionElementClickAction)
return output
endfunction
endlibrary
library ProductionOverlayData initializer InitProductionOverlayData requires IntList, ProductionData, ProductionDataRepository
globals
//hashtable ProductionTable is initialkized in ProductionDataRepository
//integer TypeIdProductionTime = -1 // fallback for GetUnitBuildTime(typeId) == 0
integer PlayerShiftFactor = 10 // shift all player indexes to group them easily
integer PlayerProducerList = 0 // producing typeId - list of producer ids
integer PlayerProgressTimer = 1 // producer handle - production progress timer
integer PlayerPlayerProduceUnits = 2 // producer handle - producer unit
//integer PlayerProducerTypeId = 3 // producer handle - production type id
//integer PlayerProducerQueueSize = 4 // producer handle - production queue size
intList array PlayerProductionTypes
endglobals
// read function for the UI
function GetPlayerProductionDataList takes player p returns intList
local integer playerId = GetPlayerId(p)
local integer playerShift = playerId * PlayerShiftFactor
local intList playerProductionTypes = PlayerProductionTypes[playerId]
local integer typeId
local string iconPath
local intList typeIdProducerList
local integer producerId
local integer producingCount
local timer producingTimer
local real progress
local unit producer
local integer i = 0
local intList output
// quick return if nothing is being produced
if(playerProductionTypes.size == 0)then
return EmptyIntList
endif
set output = CreateIntList()
loop
set typeId = playerProductionTypes.GetValueAt(i)
set typeIdProducerList = LoadInteger(ProductionTable, playerShift + PlayerProducerList, typeId)
set producerId = typeIdProducerList.GetValueAt(0)
set producingCount = typeIdProducerList.size
set producingTimer = LoadTimerHandle(ProductionTable, playerShift + PlayerProgressTimer, producerId)
set progress = TimerGetTimeout(producingTimer)
if(progress == DefaultProductionTime)then
set progress = 0 // stops the progress bar from updating
else
set progress = TimerGetElapsed(producingTimer) / TimerGetTimeout(producingTimer)
endif
if(IsResearchId(typeId))then
// dealing with a research, the displayed count should reflect the research level
set producingCount = 1 + GetPlayerTechCount(p, typeId, true)
set iconPath = GetTypeIdIconPath(typeId, producingCount)
else
set iconPath = BlzGetAbilityIcon(typeId)
endif
//TODO: in case of hero revive, have the displayed count reflect the hero level
set producer = LoadUnitHandle(ProductionTable, playerShift + PlayerPlayerProduceUnits, producerId)
call output.AddValue(CreateProductionData(typeId, iconPath, progress, producingCount, producer))
set i = i + 1
exitwhen i == playerProductionTypes.size
endloop
set producingTimer = null
set producer = null
return output
endfunction
// write functions for the events
function StartProduction takes player p, unit producer, integer typeId, real productionTime returns nothing
local integer playerId = GetPlayerId(p)
local integer playerShift = playerId * PlayerShiftFactor
local integer producerId = GetHandleId(producer)
local timer productionProgressTimer = null
local intList playerProductionTypes = PlayerProductionTypes[playerId]
local intList playerProducerList = 0
// ensure the hashtable is setup for this typeId
if(HaveSavedInteger(ProductionTable, playerShift + PlayerProducerList, typeId))then
set playerProducerList = LoadInteger(ProductionTable, playerShift + PlayerProducerList, typeId)
else
set playerProducerList = CreateIntList()
call SaveInteger(ProductionTable, playerShift + PlayerProducerList, typeId, playerProducerList)
//call Debug(" - created playerProducerList")
endif
// indicate that a new producer started producing the specified typeId
call playerProducerList.AddValue(producerId)
// save the unit handle in case we need to select it later
call SaveUnitHandle(ProductionTable, playerShift + PlayerPlayerProduceUnits, producerId, producer)
// start the production timer for the new producer
set productionProgressTimer = CreateTimer()
call TimerStart(productionProgressTimer, productionTime, false, null)
call SaveTimerHandle(ProductionTable, playerShift + PlayerProgressTimer, producerId, productionProgressTimer)
// make sure the typeId is in the overview list so it can be processed in the read function
if(playerProductionTypes.ContainsValue(typeId) == false)then
// setup production queue
call playerProductionTypes.AddValue(typeId)
endif
// cleanup
set productionProgressTimer = null
endfunction
function EndProduction takes player p, unit producer, integer typeId returns nothing
local integer playerId = GetPlayerId(p)
local integer playerShift = playerId * PlayerShiftFactor
local integer producerId = GetHandleId(producer)
local timer productionProgressTimer = null
local intList playerProductionTypes = PlayerProductionTypes[playerId]
local intList playerProducerList = LoadInteger(ProductionTable, playerShift + PlayerProducerList, typeId)
// check for a false-positive
if(HaveSavedHandle(ProductionTable, playerShift + PlayerProgressTimer, producerId) == false)then
return // producer is not actually producing, skip that logic. This can happen when something is first added to the queue
endif
// indicate that a producer stopped producing the specified typeId (either finished, cancelled, or died)
call playerProducerList.RemoveValue(producerId)
// save the unit handle in case we need to select it later
call RemoveSavedHandle(ProductionTable, playerShift + PlayerPlayerProduceUnits, producerId)
// cleanup the progress timer
set productionProgressTimer = LoadTimerHandle(ProductionTable, playerShift + PlayerProgressTimer, producerId)
call DestroyTimer(productionProgressTimer)
call RemoveSavedHandle(ProductionTable, playerShift + PlayerProgressTimer, producerId)
// if the typeId is not produced by anything anymore, then remove it from the overview list so it is not processed by the read function anymore
if(playerProducerList.size == 0)then
// setup production queue
call playerProductionTypes.RemoveValue(typeId)
endif
// cleanup
set productionProgressTimer = null
endfunction
// init functions
function InitProductionOverlayDataForPlayer takes integer playerId, player p returns nothing
if(GetPlayerSlotState(p) != PLAYER_SLOT_STATE_PLAYING)then
// don't initialize a player that is not playing
return
endif
set PlayerProductionTypes[playerId] = CreateIntList()
endfunction
function InitProductionOverlayData takes nothing returns nothing
local integer i = 0
loop
call InitProductionOverlayDataForPlayer(i, Player(i))
set i = i + 1
exitwhen i == bj_MAX_PLAYERS
endloop
endfunction
endlibrary
library ProductionOverlayEvent initializer InitProductionOverlayEvent requires IntList, ProductionDataRepository, ProductionOverlayData
globals
//hashtable ProductionTable is initialkized in ProductionDataRepository
//integer PlayerShiftFactor = 10 // shift all player indexes to group them easily
//integer PlayerProducerList = 0 // producing typeId - list of producer ids
//integer PlayerProgressTimer = 1 // producer handle - production progress timer
//integer PlayerPlayerProduceUnits = 2 // producer handle - producer unit
integer PlayerProducerTypeId = 3 // producer handle - production type id
integer PlayerProducerQueueSize = 4 // producer handle - production queue size
private trigger PlayerProducerTrainOrder
private trigger PlayerProducerStartUnit
private trigger PlayerProducerCancelUnit
private trigger PlayerProducerFinishUnit
private trigger PlayerProducerStartRevive
private trigger PlayerProducerCancelRevive
private trigger PlayerProducerFinishRevive
private trigger PlayerProducerStartStructure
private trigger PlayerProducerCancelStructure
private trigger PlayerProducerFinishStructure
private trigger PlayerProducerStartUpgrade
private trigger PlayerProducerCancelUpgrade
private trigger PlayerProducerFinishUpgrade
private trigger PlayerProducerStartResearch
private trigger PlayerProducerCancelResearch
private trigger PlayerProducerFinishResearch
private trigger PlayerProducerDeath
private constant string EMPTY_STRING = "Default string" // This is an indicator for an invalid ObjectName.
endglobals
// queue size tracking utilities
private function IncreaseQueueSize takes unit producer returns nothing
local integer producerId = GetHandleId(producer)
local integer queueSize = 0
if(HaveSavedInteger(ProductionTable, PlayerProducerQueueSize, producerId))then
set queueSize = LoadInteger(ProductionTable, PlayerProducerQueueSize, producerId)
endif
set queueSize = queueSize + 1
call SaveInteger(ProductionTable, PlayerProducerQueueSize, producerId, queueSize)
endfunction
private function DecreaseQueueSize takes unit producer returns nothing
local integer producerId = GetHandleId(producer)
local integer queueSize = LoadInteger(ProductionTable, PlayerProducerQueueSize, producerId)
set queueSize = queueSize - 1
if(queueSize == 0)then
call RemoveSavedInteger(ProductionTable, PlayerProducerQueueSize, producerId)
else
call SaveInteger(ProductionTable, PlayerProducerQueueSize, producerId, queueSize)
endif
endfunction
private function GetQueueSize takes unit producer returns integer
local integer producerId = GetHandleId(producer)
if(HaveSavedInteger(ProductionTable, PlayerProducerQueueSize, producerId))then
return LoadInteger(ProductionTable, PlayerProducerQueueSize, producerId)
endif
return 0
endfunction
private function CleanupQueue takes unit producer returns nothing
local integer producerId = GetHandleId(producer)
if(HaveSavedInteger(ProductionTable, PlayerProducerQueueSize, producerId))then
call RemoveSavedInteger(ProductionTable, PlayerProducerQueueSize, producerId)
endif
endfunction
// trigger utilities
function CleanupProducer takes integer playerId, unit producer returns nothing
local integer playerShift = PlayerShiftFactor * playerId
local integer producerId = GetHandleId(producer)
call RemoveSavedInteger(ProductionTable, playerShift + PlayerProducerTypeId, producerId)
endfunction
function FinishProduction takes unit producer returns nothing
local integer producerId = GetHandleId(producer)
local player p = GetOwningPlayer(producer)
local integer playerId = GetPlayerId(p)
local integer playerShift = PlayerShiftFactor * playerId
local integer typeId = LoadInteger(ProductionTable, playerShift + PlayerProducerTypeId, producerId)
call EndProduction(p, producer, typeId)
call CleanupProducer(playerId, producer)
set p = null
endfunction
function SetupProducer takes integer playerId, unit producer, integer typeId returns nothing
local integer playerShift = PlayerShiftFactor * playerId
local integer producerId = GetHandleId(producer)
call SaveInteger(ProductionTable, playerShift + PlayerProducerTypeId, producerId, typeId)
endfunction
// MAIN PRODUCTION EVENTS
// train order detection - thanks IcemanBo https://www.hiveworkshop.com/threads/trainingdetection-v3-1a.248978/#resource-47168
private function TrainOrderAction takes nothing returns nothing
local integer orderId = GetIssuedOrderId()
if(GetObjectName(orderId) != EMPTY_STRING and GetObjectName(orderId) != null)then
call IncreaseQueueSize(GetTriggerUnit())
endif
endfunction
// unit
function StartUnitProductionAction takes nothing returns nothing
local unit producer = GetTriggerUnit()
local player p = GetOwningPlayer(producer)
local integer playerId = GetPlayerId(p)
local integer typeId = GetTrainedUnitType()
local real productionTime = GetTypeIdProductionTime(typeId)
call EndProduction(p, producer, typeId)
call StartProduction(p, producer, typeId, productionTime)
call SetupProducer(playerId, producer, typeId)
endfunction
function CancelUnitProductionAction takes nothing returns nothing
call DecreaseQueueSize(GetTriggerUnit())
if(GetQueueSize(GetTriggerUnit()) == 0)then
call FinishProduction(GetTriggerUnit())
endif
endfunction
function FinishUnitProductionAction takes nothing returns nothing
call FinishProduction(GetTriggerUnit())
call DecreaseQueueSize(GetTriggerUnit())
endfunction
// structure
function StartStructureProductionAction takes nothing returns nothing
local unit building = GetConstructingStructure()
local player p = GetOwningPlayer(building)
local integer playerId = GetPlayerId(p)
local integer typeId = GetUnitTypeId(building)
local real productionTime = GetTypeIdProductionTime(typeId)
call EndProduction(p, building, typeId)
call StartProduction(p, building, typeId, productionTime)
call SetupProducer(playerId, building, typeId)
endfunction
function CancelStructureProductionAction takes nothing returns nothing
call FinishProduction(GetCancelledStructure())
endfunction
function FinishStructureProductionAction takes nothing returns nothing
call FinishProduction(GetConstructedStructure())
endfunction
// upgrade
function StartUpgradeProductionAction takes nothing returns nothing
local unit building = GetTriggerUnit()
local player p = GetOwningPlayer(building)
local integer playerId = GetPlayerId(p)
local integer typeId = GetUnitTypeId(building)
local real productionTime = GetTypeIdProductionTime(typeId)
call EndProduction(p, building, typeId)
call StartProduction(p, building, typeId, productionTime)
call SetupProducer(playerId, building, typeId)
endfunction
function CancelUpgradeProductionAction takes nothing returns nothing
call CleanupQueue(GetTriggerUnit())
call FinishProduction(GetTriggerUnit())
endfunction
function FinishUpgradeProductionAction takes nothing returns nothing
call CleanupQueue(GetTriggerUnit())
call FinishProduction(GetTriggerUnit())
endfunction
// research
function StartResearchProductionAction takes nothing returns nothing
local unit producer = GetResearchingUnit()
local player p = GetOwningPlayer(producer)
local integer playerId = GetPlayerId(p)
local integer typeId = GetResearched()
local integer level = GetPlayerTechCount(p, typeId, true) + 1
local real productionTime = GetResearchTime(typeId, level)
call EndProduction(p, producer, typeId)
call StartProduction(p, producer, typeId, productionTime)
call SetupProducer(playerId, producer, typeId)
endfunction
function CancelResearchProductionAction takes nothing returns nothing
call DecreaseQueueSize(GetResearchingUnit())
if(GetQueueSize(GetResearchingUnit()) == 0)then
call FinishProduction(GetResearchingUnit())
endif
endfunction
function FinishResearchProductionAction takes nothing returns nothing
call DecreaseQueueSize(GetResearchingUnit())
call FinishProduction(GetResearchingUnit())
endfunction
// revive
function StartReviveProductionAction takes nothing returns nothing
local unit producer = GetTriggerUnit()
local player p = GetOwningPlayer(producer)
local integer playerId = GetPlayerId(p)
local unit hero = GetRevivingUnit()
local integer typeId = GetUnitTypeId(hero)
local integer level = GetHeroLevel(hero)
local real productionTime = GetHeroReviveTime(typeId, level)
call EndProduction(p, producer, typeId)
call StartProduction(p, producer, typeId, productionTime)
call SetupProducer(playerId, producer, typeId)
endfunction
function CancelReviveProductionAction takes nothing returns nothing
call DecreaseQueueSize(GetTriggerUnit())
if(GetQueueSize(GetTriggerUnit()) == 0)then
call FinishProduction(GetTriggerUnit())
endif
endfunction
function FinishReviveProductionAction takes nothing returns nothing
call DecreaseQueueSize(GetTriggerUnit())
call FinishProduction(GetTriggerUnit())
endfunction
// death
function ProducerDeathAction takes nothing returns nothing
call CleanupQueue(GetTriggerUnit())
call FinishProduction(GetDyingUnit())
endfunction
// init functions
function InitProductionOverlayEventForPlayer takes integer playerId, player p returns nothing
if(GetPlayerSlotState(p) != PLAYER_SLOT_STATE_PLAYING)then
// don't initialize a player that is not playing
return
endif
call TriggerRegisterPlayerUnitEvent(PlayerProducerTrainOrder, p, EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerStartUnit, p, EVENT_PLAYER_UNIT_TRAIN_START, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerCancelUnit, p, EVENT_PLAYER_UNIT_TRAIN_CANCEL, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerFinishUnit, p, EVENT_PLAYER_UNIT_TRAIN_FINISH, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerStartStructure, p, EVENT_PLAYER_UNIT_CONSTRUCT_START, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerCancelStructure, p, EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerFinishStructure, p, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerStartUpgrade, p, EVENT_PLAYER_UNIT_UPGRADE_START, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerCancelUpgrade, p, EVENT_PLAYER_UNIT_UPGRADE_CANCEL, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerFinishUpgrade, p, EVENT_PLAYER_UNIT_UPGRADE_FINISH, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerStartResearch, p, EVENT_PLAYER_UNIT_RESEARCH_START, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerCancelResearch, p, EVENT_PLAYER_UNIT_RESEARCH_CANCEL, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerFinishResearch, p, EVENT_PLAYER_UNIT_RESEARCH_FINISH, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerStartRevive, p, EVENT_PLAYER_HERO_REVIVE_START, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerCancelRevive, p, EVENT_PLAYER_HERO_REVIVE_CANCEL, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerFinishRevive, p, EVENT_PLAYER_HERO_REVIVE_FINISH, null)
call TriggerRegisterPlayerUnitEvent(PlayerProducerDeath, p, EVENT_PLAYER_UNIT_DEATH, null)
endfunction
function RunInitProductionOverlayEvent takes nothing returns nothing
local integer i = 0
set PlayerProducerTrainOrder = CreateTrigger()
call TriggerAddAction(PlayerProducerTrainOrder, function TrainOrderAction)
set PlayerProducerStartUnit = CreateTrigger()
call TriggerAddAction(PlayerProducerStartUnit, function StartUnitProductionAction)
set PlayerProducerCancelUnit = CreateTrigger()
call TriggerAddAction(PlayerProducerCancelUnit, function CancelUnitProductionAction)
set PlayerProducerFinishUnit = CreateTrigger()
call TriggerAddAction(PlayerProducerFinishUnit, function FinishUnitProductionAction)
set PlayerProducerStartStructure = CreateTrigger()
call TriggerAddAction(PlayerProducerStartStructure, function StartStructureProductionAction)
set PlayerProducerCancelStructure = CreateTrigger()
call TriggerAddAction(PlayerProducerCancelStructure, function CancelStructureProductionAction)
set PlayerProducerFinishStructure = CreateTrigger()
call TriggerAddAction(PlayerProducerFinishStructure, function FinishStructureProductionAction)
set PlayerProducerStartUpgrade = CreateTrigger()
call TriggerAddAction(PlayerProducerStartUpgrade, function StartUpgradeProductionAction)
set PlayerProducerCancelUpgrade = CreateTrigger()
call TriggerAddAction(PlayerProducerCancelUpgrade, function CancelUpgradeProductionAction)
set PlayerProducerFinishUpgrade = CreateTrigger()
call TriggerAddAction(PlayerProducerFinishUpgrade, function FinishUpgradeProductionAction)
set PlayerProducerStartResearch = CreateTrigger()
call TriggerAddAction(PlayerProducerStartResearch, function StartResearchProductionAction)
set PlayerProducerCancelResearch = CreateTrigger()
call TriggerAddAction(PlayerProducerCancelResearch, function CancelResearchProductionAction)
set PlayerProducerFinishResearch = CreateTrigger()
call TriggerAddAction(PlayerProducerFinishResearch, function FinishResearchProductionAction)
set PlayerProducerStartRevive = CreateTrigger()
call TriggerAddAction(PlayerProducerStartRevive, function StartReviveProductionAction)
set PlayerProducerCancelRevive = CreateTrigger()
call TriggerAddAction(PlayerProducerCancelRevive, function CancelReviveProductionAction)
set PlayerProducerFinishRevive = CreateTrigger()
call TriggerAddAction(PlayerProducerFinishRevive, function FinishReviveProductionAction)
set PlayerProducerDeath = CreateTrigger()
call TriggerAddAction(PlayerProducerDeath, function ProducerDeathAction)
loop
call InitProductionOverlayEventForPlayer(i, Player(i))
set i = i + 1
exitwhen i == bj_MAX_PLAYERS
endloop
endfunction
function InitProductionOverlayEvent takes nothing returns nothing
// don't setup on map init avoid the Night Elf instant Entangle, which doesn't fire a CONSTRUCT_FINISH event
local trigger t = CreateTrigger()
call TriggerRegisterTimerEvent(t, 0, false)
call TriggerAddAction(t, function RunInitProductionOverlayEvent)
endfunction
endlibrary
library ProductionOverlayUi initializer InitProductionOverlayUi requires IntList, ProductionPanelElement, ProductionOverlayData , GameStatus, optional FrameLoader, optional CastingOverlay, optional OverlayDefines
globals
framehandle ProductionOverlayRootPanel
string ProductionOverlayName = "Production"
integer ProductionOverlayPanelCount = 0
framehandle array ProductionOverlayPanels
intList array ProductionOverlayPanelElements
string array PlayerColorTexturePath
real IconSize = 0.02
real OffsetSize = 0.005
real NullSize = 0.00001
real ProgressBarSize = 0.003
real ProgressBarOffset = 0.003 / 5
real ColorIndicatorSize = 0.005
endglobals
function GetTeamColorTexturePath takes playercolor pc returns string
local integer i = 0
local string output = "replaceabletextures\\teamcolor\\teamcolor"
loop
if(pc == ConvertPlayerColor(i))then
if(i < 10)then
return output + "0" + I2S(i)
else
return output + I2S(i)
endif
endif
set i = i + 1
exitwhen i == bj_MAX_PLAYERS
endloop
return output + "00"
endfunction
function CreatePlayerProductionElementIconButton takes integer playerId, integer index, framehandle parent returns framehandle
local framehandle elementIconButton = BlzCreateFrameByType("BUTTON", "PlayerProductionElementIconButton-" + I2S(playerId) + "-" + I2S(index), parent, "ScriptDialogButton", 0)
call BlzFrameSetPoint(elementIconButton, FRAMEPOINT_TOPLEFT, parent, FRAMEPOINT_TOPLEFT, 0, 0)
call BlzFrameSetSize(elementIconButton, IconSize, IconSize)
return elementIconButton
endfunction
function CreatePlayerProductionElementIcon takes integer playerId, integer index, framehandle parent returns framehandle
local framehandle elementIcon = BlzCreateFrameByType("BACKDROP", "PlayerProductionElementIcon-" + I2S(playerId) + "-" + I2S(index), parent, "", 0)
call BlzFrameSetAllPoints(elementIcon, parent)
call BlzFrameSetTexture(elementIcon, "", 0, false)
call BlzFrameSetEnable(elementIcon, false)
return elementIcon
endfunction
function CreatePlayerProductionElementNumber takes integer playerId, integer index, framehandle parent returns framehandle
local framehandle elementNumberBackdrop = BlzCreateFrameByType("BACKDROP", "PlayerProductionElementNumberBackdrop-" + I2S(playerId) + "-" + I2S(index), parent, "", 0)
local framehandle elementNumber = BlzCreateFrameByType("TEXT", "PlayerProductionElementNumber-" + I2S(playerId) + "-" + I2S(index), elementNumberBackdrop, "", 0)
// backdrop
call BlzFrameSetPoint(elementNumberBackdrop, FRAMEPOINT_BOTTOMRIGHT, parent, FRAMEPOINT_BOTTOMRIGHT, 0, 0)
call BlzFrameSetSize(elementNumberBackdrop, IconSize / 2, IconSize / 3)
call BlzFrameSetTexture(elementNumberBackdrop, "UI\\Widgets\\Console\\Human\\human-transport-slot", 0, true)
call BlzFrameSetEnable(elementNumberBackdrop, false)
// text
call BlzFrameSetAllPoints(elementNumber, elementNumberBackdrop)
call BlzFrameSetText(elementNumber, I2S(0))
call BlzFrameSetTextAlignment(elementNumber, TEXT_JUSTIFY_MIDDLE, TEXT_JUSTIFY_CENTER)
call BlzFrameSetEnable(elementNumber, false)
call BlzFrameSetScale(elementNumber, 2.0 / 3.0) // only way to adjust text size?
return elementNumber
endfunction
function CreatePlayerProductionElementProgress takes integer playerId, integer index, framehandle parent returns framehandle
local framehandle elementProgress = BlzCreateFrameByType("BACKDROP", "PlayerProductionElementProgress-" + I2S(playerId) + "-" + I2S(index), parent, "", 0)
call BlzFrameSetPoint(elementProgress, FRAMEPOINT_TOPLEFT, parent, FRAMEPOINT_TOPLEFT, ProgressBarOffset, -IconSize)
call BlzFrameSetSize(elementProgress, (IconSize - ProgressBarOffset * 2) * 0, ProgressBarSize)
call BlzFrameSetTexture(elementProgress, PlayerColorTexturePath[playerId], 0, true)
call BlzFrameSetEnable(elementProgress, false)
return elementProgress
endfunction
function CreatePlayerProductionElement takes integer playerId, integer index returns productionPanelElement
local framehandle parent = ProductionOverlayPanels[playerId]
local framehandle element = BlzCreateFrameByType("BACKDROP", "PlayerProductionElement-" + I2S(playerId) + "-" + I2S(index), parent, "", 0)
local framehandle iconButton = CreatePlayerProductionElementIconButton(playerId, index, element)
local framehandle icon = CreatePlayerProductionElementIcon(playerId, index, iconButton)
local framehandle number = CreatePlayerProductionElementNumber(playerId, index, iconButton)
local framehandle progress = CreatePlayerProductionElementProgress(playerId, index, icon)
local productionPanelElement output = CreateProductionPanelElement(playerId, index, parent, element, iconButton, icon, number, progress)
call BlzFrameSetPoint(element, FRAMEPOINT_TOPLEFT, parent, FRAMEPOINT_TOPLEFT, ColorIndicatorSize + OffsetSize + (IconSize + OffsetSize) * index, 0)
call BlzFrameSetSize(element, IconSize, IconSize + ProgressBarSize)
call BlzFrameSetTexture(element, "Textures\\Black32.blp", 0, true)
call BlzFrameSetEnable(element, true)
return output
endfunction
function CreatePlayerColorIndicator takes integer playerId, framehandle parent returns framehandle
local framehandle colorIndicator = BlzCreateFrameByType("BACKDROP", "PlayerColorIndicator-" + I2S(playerId), parent, "", 0)
call BlzFrameSetPoint(colorIndicator, FRAMEPOINT_TOPLEFT, parent, FRAMEPOINT_TOPLEFT, 0, 0)
call BlzFrameSetSize(colorIndicator, ColorIndicatorSize, IconSize + ProgressBarSize)
call BlzFrameSetTexture(colorIndicator, PlayerColorTexturePath[playerId], 0, true)
return colorIndicator
endfunction
function CreatePlayerProductionPanel takes integer playerId, framehandle parent returns framehandle
local framehandle playerPanel = BlzCreateFrameByType("BACKDROP", "PlayerProductionQueuePanel-" + I2S(playerId), parent, "", 0)
call BlzFrameSetPoint(playerPanel, FRAMEPOINT_TOPLEFT, parent, FRAMEPOINT_TOPLEFT, 0, (OffsetSize + IconSize + ProgressBarSize) * -ProductionOverlayPanelCount)
call BlzFrameSetSize(playerPanel, NullSize, NullSize)
call CreatePlayerColorIndicator(playerId, playerPanel)
set ProductionOverlayPanelCount = ProductionOverlayPanelCount + 1
set ProductionOverlayPanels[playerId] = playerPanel
set ProductionOverlayPanelElements[playerId] = CreateIntList()
return playerPanel
endfunction
function SetOverlayVisiblityForActivePlayer takes player p returns nothing
static if(LIBRARY_CastingOverlay)then
return // let the casting overlay manage visibility
else
if(GetGameStatus() == GAME_STATUS_REPLAY)then
return // always display the overlay during a replay
endif
// GAME_STATUS_TEST when please :pray:
if(GetGameStatus() == GAME_STATUS_OFFLINE)then
return // probably a test session, just display it
endif
// active player slots are non-osbervers/referees, they shouldn't see the prodution overlay
if(p == GetLocalPlayer())then
call BlzFrameSetVisible(ProductionOverlayRootPanel, false)
endif
endif
endfunction
function SetPlayerProductionElementCount takes integer playerId, integer count returns nothing
local intList playerElements = ProductionOverlayPanelElements[playerId]
local productionPanelElement element
local integer i = 0
loop
if(i == playerElements.size)then
set element = CreatePlayerProductionElement(playerId, i)
call playerElements.AddValue(element)
else
set element = playerElements.GetValueAt(i)
endif
call element.Show(false)
set i = i + 1
exitwhen i == IMaxBJ(count, playerElements.size)
endloop
endfunction
function SetPlayerProductionElement takes integer playerId, integer index, string iconPath, integer number, real progress, unit producer returns nothing
local intList playerElements = ProductionOverlayPanelElements[playerId]
local productionPanelElement element = playerElements.GetValueAt(index)
call element.Update(iconPath, number, progress, producer)
call element.Show(true)
endfunction
function UpdateProductionOverlayForPlayer takes player p returns nothing
local integer playerId = GetPlayerId(p)
local intList playerProduction = GetPlayerProductionDataList(p)
local integer i = 0
local productionData data
if(playerProduction == EmptyIntList)then
call SetPlayerProductionElementCount(playerId, 0)
return
endif
call SetPlayerProductionElementCount(playerId, playerProduction.size)
loop
set data = playerProduction.GetValueAt(i)
call SetPlayerProductionElement(playerId, i, data.iconPath, data.count, data.progress, data.producer)
call data.destroy()
set i = i + 1
exitwhen i == playerProduction.size
endloop
call playerProduction.destroy()
endfunction
function UpdateProductionOverlay takes nothing returns nothing
local integer i = 0
loop
if(GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING)then
call UpdateProductionOverlayForPlayer(Player(i))
endif
set i = i + 1
exitwhen i == bj_MAX_PLAYERS
endloop
endfunction
function RunInitProductionOverlayUi takes nothing returns nothing
local integer i = 0
set ProductionOverlayRootPanel = BlzCreateFrameByType("BACKDROP", "RootProductionPanel", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0)
call BlzFrameSetAbsPoint(ProductionOverlayRootPanel, FRAMEPOINT_TOPLEFT, 0, 0.6 - 0.04)
call BlzFrameSetSize(ProductionOverlayRootPanel, NullSize, NullSize)
call BlzFrameSetVisible(ProductionOverlayRootPanel, true)
loop
if(GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING)then
// create the UI for this active player
call CreatePlayerProductionPanel(i, ProductionOverlayRootPanel)
// apply the overlay visibility for this player depending on the context
call SetOverlayVisiblityForActivePlayer(Player(i))
endif
set i = i + 1
exitwhen i == bj_MAX_PLAYERS
endloop
static if(LIBRARY_CastingOverlay)then
call RegisterOverlay(ProductionOverlayRootPanel, ProductionOverlayName)
endif
endfunction
function RerunInitProductionOverlayUi takes nothing returns nothing
local integer i = 0
// reset all the players element lists
loop
call ProductionOverlayPanelElements[i].destroy()
set i = i + 1
exitwhen i == bj_MAX_PLAYERS
endloop
// reset the panel counter so we can create them again from scratch
set ProductionOverlayPanelCount = 0
// recreate the root frame and all production panels
call RunInitProductionOverlayUi()
endfunction
function InitProductionOverlayUi takes nothing returns nothing
local integer i = 0
local trigger initTrigger = CreateTrigger()
local trigger updateTrigger = CreateTrigger()
// setup the frames at gametime 0, because they can't be created at map init
call TriggerRegisterTimerEvent(initTrigger, 0, false)
call TriggerAddAction(initTrigger, function RunInitProductionOverlayUi)
// refresh the Ui at regular interval
call TriggerRegisterTimerEvent(updateTrigger, 0.35, true)
call TriggerAddAction(updateTrigger, function UpdateProductionOverlay)
// init player teamcolor texture paths
loop
set PlayerColorTexturePath[i] = GetTeamColorTexturePath(GetPlayerColor(Player(i)))
set i = i + 1
exitwhen i == bj_MAX_PLAYERS
endloop
static if (LIBRARY_FrameLoader)then
// handle reloading a saved game
call FrameLoaderAdd(function RerunInitProductionOverlayUi)
endif
endfunction
endlibrary