System Get Costs and Bounty

Nestharus

o-o
Reaction score
84
Gcsn- Get Costs and States by Nestharus

Stock
JASS:

native GetUnitGoldCost takes integer unitid returns integer
native GetUnitWoodCost takes integer unitid returns integer

library Stock initializer Initialization uses PlayerTracker
/*Utility Information
//===================================================================
Name: Stock (gold/wood stock, item charge stock, bounty stock)
Version: 6.2
Author: Nestharus

Settings:
*///===================================================================
//! textmacro Stock_USER_SETTINGS
    set coordX = GetRectCenterX(bj_mapInitialPlayableArea)
    set coordY = GetRectCenterY(bj_mapInitialPlayableArea)
//! endtextmacro

//! textmacro Stock_EXTRA_PLAYERS
    /*call TriggerRegisterPlayerUnitEvent(unitUpgradeStartTracking, GetPlayer(x), EVENT_PLAYER_UNIT_UPGRADE_START, null)
    call TriggerRegisterPlayerUnitEvent(unitUpgradeFinishTracking, GetPlayer(x), EVENT_PLAYER_UNIT_UPGRADE_FINISH, null)
    call TriggerRegisterPlayerUnitEvent(unitFinishResearching, GetPlayer(x), EVENT_PLAYER_UNIT_RESEARCH_FINISH, null)*/
//! endtextmacro

globals
    private constant integer BOUNTY_ACCURACY = 3
    private constant damagetype damageType = DAMAGE_TYPE_UNKNOWN
    private constant attacktype attackType = ATTACK_TYPE_CHAOS
    private constant weapontype weaponType = WEAPON_TYPE_WHOKNOWS
endglobals
/*//===================================================================

Description:
    What does it do-
        Retrieves various costs and states for players, units, and items
        Players: 
            Total Gold including all owned items, units, and techs.
        Units: 
            total gold/wood cost (all items on them), unit type id
            gold/wood cost, unit average cached bounty, on the spot
            bounty, and gold/wood upgrades
        Items:
            total gold/wood cost including charges, item type id
            gold/wood cost, default item charges
        Research:
            gold/wood cost in a range. Powerful but hard to use.
    How does it do it-
        Creates a unit for player 14 at designed coordinates. It hides it, gives it
        locust, etc, etc so that it is as safe as possible. 
        
        To get item and or gold cost, the hidden unit sells the item to itself and records the cost. Items
        are enumerated in a removal rect and if the enumerated item matches the type of the item running
        through the system, it is removed. This is the primary reason why it can be dangerous for this system
        to be running in an open area where items may be dropped. Also, this is the reason that the area
        has to be a place where items can be dropped, otherwise it cannot retrieve the items for cleaning.
        
        For unit costs, it sells the unit to itself and records the cost. When the unit enters the removal 
        area, it is removed. Only units owned by Player 14 of the current type are removed, but again
        can be dangerous if the map is using player 14. It only uses this method if the unit is a hero, 
        otherwise it defaults to the JASS AI Natives.
        
        For unit bounty, it creates a unit at the invis unit's coordinates and then makes the invis unit
        kill it with a damage function. The bounty is then recorded and the unit is removed.
        
        Item default charges are recorded as the item is enumerated in the removal area.
        
        For upgrades on units, it runs whenever a unit begins upgrading. When units go out of scope (leave the
        rect), they are automatically cleaned. For the tracking to work, TrackUpgrades must be called. 
        The reason for this is so that everything can run as efficiently and as quickly as possible. 
        There is no point to track upgrades on a unit that will never upgrade.
        
Requirements: PTN- hiveworkshop.com/forums/jass-functions-413/system-pt-player-tracking-142554/
              Recycle- thehelper.net/forums/showthread.php?t=136087
            
Installation: NA

Variables and Settings:
------------------------------------------------------------------
BOUNTY_ACCURACY- how accurate bounty will be. Higher is slower and more
accurate. Smaller is faster and less accurate.

coordX- the x coordinate where the invisible unit that runs this
system will be. Keep this at edge of map.

coordY- the y coordinate where the invisible unit that runs this
system will be. Keep this at edge of map.

damage/attack/weapon type- used when killing a unit to determine
its bounty.
    
Stock_EXTRA_PLAYERS-
    Refers to other players that this system runs for. Does not go
    through a loop. All players from 0-11 are automatically registered.
------------------------------------------------------------------

Functions:
------------------------------------------------------------------
-GetResearchGoldCost(unitTypeId, techId, start, finish)
    will return the gold tech cost of techId for upgrading from
    level start to level finish, aka level 0 to 1. The unitTypeId
    is used to create a unit for retrieving the tech cost. The unit
    must have the tech on it or the cost cannot be retrieved.
    
-GetResearchWoodCost(unitTypeId, techId, start, finish)
    will return the wood tech cost of techId for upgrading from
    level start to level finish, aka level 0 to 1. The unitTypeId
    is used to create a unit for retrieving the tech cost. The unit
    must have the tech on it or the cost cannot be retrieved.
    
-GetUnitCachedBounty(unitTypeId)
    will return the current cached value of gold bounty
    for a unit and cache it if the record is new
    
-GetUnitBounty(unitTypeId, accuracy)
    will return an average gold bounty given an accuracy
    and will always do it new. Accuracy should typically be 1
    
-UpdateBounty(integer unitTypeId, integer min, integer max)
    Will forcefully update the averaged bounty for a given unit id if the
    min is smaller than the currently registered min and or the max is greater
    than the currently registered max. Bounty is automatically updated
    to get the best possible average as GetUnitBounty is used and it is updated
    as the Bounty utility runs (an optional add-on to this).
    
-GetUnitGold(unitTypeId)
    will return the gold cost of the unit type

-GetUnitWood(unitTypeId)
    will return the wood cost of the unit type
    
-GetUnitGoldUpgrades(unit)
    will return the total gold upgrades of a unit
    
-GetUnitWoodUpgrades(unit)
    will return the total wood upgrades of a unit
    
-TrackUpgrades(unit)
    will make the system track a unit's upgrades. It
    will only track the unit's upgrades if this is called.
    Once tracking has begun, it cannot be stopped until the unit
    is removed from the game.
    
-StopUpgradeTracking(unit)
    Will stop tracking a unit and clean it from the system
    
-GetItemGoldCost(itemTypeId)
    will return the gold cost of the item type
    
-GetItemWoodCost(itemTypeId)
    will return the wood cost of the item type
    
-GetItemCharge(itemTypeId)
    will return the starting charges of the item type
    
-GetItemTotalGoldCost(item)
    will return the total gold cost of the item, charges and all
    
-GetItemTotalWoodCost(item)
    will return the total wood cost of the item, charges and all
    
-GetUnitTotalGoldCost(unit)
    will return the total gold cost of the unit, items and all
    
-GetUnitTotalWoodCost(unit)
    will return the total wood cost of the unit, items and all
    
-GetPlayerGoldResearch(player)
    returns the the total gold the player spent on researching
    
-GetPlayerWoodResearch(player)
    retursn the total wood the player spent on researching
    
-UpdatePlayer(player)
    will update the player's total gold and wood, including all
    units and items that player owns
    
-GetPlayerTotalGold(player)
    will return the player's total gold. The player must
    be updated for this to work.
    
-GetPlayerTotalWood(player)
    will return the player's total wood. The player must
    be updated for this to work.
------------------------------------------------------------------*/
    globals
        private rect removalArea
        private integer unitCheckerId = 'hpea'
        private real coordX
        private real coordY
        private player playerChecker
        private unit costRetriever
        private integer array goldResource[24]
        private integer array woodResource[24]
        private constant integer RESOURCE_LIMIT = 1000000
        private group unitGroup = CreateGroup()
        private trigger unitRemoval = CreateTrigger()
        private region unitRemovalRegion
        private trigger unitUpgradeStartTracking = CreateTrigger()
        private trigger stopUnitUpgradeTracking = CreateTrigger()
        private trigger unitUpgradeFinishTracking = CreateTrigger()
        private trigger unitFinishResearching = CreateTrigger()
        private region world
        private hashtable items = InitHashtable()
        private hashtable units = InitHashtable()
        private hashtable unitTypes = InitHashtable()
        private hashtable research = InitHashtable()
        private integer runningUnitTypeId = 0
        private integer runningItemTypeId = 0
        private unit runningUnit = null
        private integer runningUnitTypeStackId = 0
        private integer runningItemTypeStackId = 0
        private integer runningUnitStackId = 0
        private item runningItem = null
        private integer runningItemStackId = 0
        private boolexpr removeItems
        private boolexpr checkUnit
    endglobals
    
    private struct ItemTypeStack
    endstruct
    
    private struct UnitTypeStack
    endstruct
    
    private struct UnitStack
    endstruct
    
    //Items
        globals
            private integer array itemGoldCost
            private integer array itemWoodCost
            private integer array itemCharges
        endglobals
        
        globals
            private integer currentItemType
            private integer currentItemId
        endglobals
        
        private function RemoveItems takes nothing returns boolean
            local item i = GetFilterItem()
            local integer typeId = GetItemTypeId(i)
            if typeId == currentItemType then
                set itemCharges[currentItemId] = GetItemCharges(i)
                call RemoveItem(i)
                set currentItemType = 0
                set currentItemId = 0
            endif
            set i = null
            return false
        endfunction
        
        private function GetItemId takes integer itemTypeId returns integer
            local integer playerGold
            local integer playerWood
            local integer id
            if runningItemTypeId != itemTypeId then
                if not HaveSavedInteger(items, itemTypeId, 0) then
                    set id = ItemTypeStack.create()
                    call SaveInteger(items, itemTypeId, 0, id)
                    set playerGold = GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD)
                    set playerWood = GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER)
                    set currentItemType = itemTypeId
                    set currentItemId = id
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, RESOURCE_LIMIT)
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER, RESOURCE_LIMIT)
                    call AddItemToStock(costRetriever, itemTypeId, 1, 1)
                    call IssueNeutralImmediateOrderById(playerChecker, costRetriever, itemTypeId)
                    set itemGoldCost[id] = RESOURCE_LIMIT - GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD)
                    set itemWoodCost[id] = RESOURCE_LIMIT - GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER)
                    call RemoveItemFromStock(costRetriever, itemTypeId)
                    call EnumItemsInRect(removalArea, removeItems, null)
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, playerGold)
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER, playerWood)
                    set runningItemTypeStackId = id
                else
                    set runningItemTypeStackId = LoadInteger(items, itemTypeId, 0)
                endif
                set runningItemTypeId = itemTypeId
            endif
            return runningItemTypeStackId
        endfunction
    //End Items
    
    //Units
        globals
            private integer array unitGoldCost
            private integer array unitWoodCost
            private integer array goldBountyMax
            private integer array goldBountyMin
            private integer array goldBounty
            
            private integer array unitGoldUpgrades
            private integer array unitWoodUpgrades
            private integer array unitGoldUpgradesLast
            private integer array unitWoodUpgradesLast
            private integer array unitGoldUpgradesPending
            private integer array unitWoodUpgradesPending
        endglobals
        
        globals
            private integer currentUnitType = 0
        endglobals
        
        private function RemoveUnits takes nothing returns boolean
            local unit u = GetFilterUnit()
            if GetUnitTypeId(u) == currentUnitType and GetOwningPlayer(u) == playerChecker then
                call RemoveUnit(u)
                set currentUnitType = 0
            endif
            set u = null
            return false
        endfunction
        
        private function UnitGetId takes integer unitTypeId returns integer
            local integer id
            if runningUnitTypeId != unitTypeId then
                if not HaveSavedInteger(unitTypes, unitTypeId, 0) then
                    set id = UnitTypeStack.create()
                    call SaveInteger(unitTypes, unitTypeId, 0, id)
                    set runningUnitTypeStackId = id
                else
                    set runningUnitTypeStackId = LoadInteger(unitTypes, unitTypeId, 0)
                endif
                set runningUnitTypeId = unitTypeId
            endif
            return runningUnitTypeStackId
        endfunction
        
        function UpdateBounty takes integer unitTypeId, integer min, integer max returns nothing
            local integer id = UnitGetId(unitTypeId)
            if min < goldBountyMin[id] then
                set goldBountyMin[id] = min
            endif
            if max > goldBountyMax[id] then
                set goldBountyMax[id] = max
            endif
            set goldBounty[id] = (goldBountyMin[id]+goldBountyMax[id])/2
        endfunction
        
        function GetUnitBounty takes integer unitTypeId, integer accuracy returns integer
            local integer averageGold = 0
            local integer count = 0
            local unit array u
            local boolean bounty = (GetPlayerState(playerChecker, PLAYER_STATE_GIVES_BOUNTY) == 1)
            local integer playerGold = GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD)
            local boolean allied = GetPlayerAlliance(playerChecker, Player(12), ALLIANCE_PASSIVE)
            local integer minGold = 1000000
            local integer maxGold = 0
            local integer currentGold
            if not bounty then
                call SetPlayerState(playerChecker, PLAYER_STATE_GIVES_BOUNTY, 1)
            endif
            if allied then
                call SetPlayerAlliance(playerChecker, Player(12), ALLIANCE_PASSIVE, false)
            endif
            loop
                exitwhen count == accuracy
                call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, 0)
                set u[count] = CreateUnit(Player(12), unitTypeId, coordX, coordY, 270)
                call ShowUnit(u[count], false)
                call SetUnitState(u[count], UNIT_STATE_LIFE, 1)
                call SetUnitInvulnerable(u[count], false)
                call UnitDamageTarget(costRetriever, u[count], 100000000, true, false, attackType, damageType, weaponType)
                call RemoveUnit(u[count])
                set u[count] = null
                set currentGold = GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD)
                if currentGold < minGold then
                    set minGold = currentGold
                endif
                if currentGold > maxGold then
                    set maxGold = currentGold
                endif
                if averageGold == 0 then
                    set averageGold = currentGold
                else
                    set averageGold = (averageGold+GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD))/2
                endif
                set count = count + 1
            endloop
            call UpdateBounty(unitTypeId, minGold, maxGold)
            if not bounty then
                call SetPlayerState(playerChecker, PLAYER_STATE_GIVES_BOUNTY, 0)
            endif
            if allied then
                call SetPlayerAlliance(playerChecker, Player(12), ALLIANCE_PASSIVE, true)
            endif
            call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, playerGold)
            return averageGold
        endfunction
        
        private function GetTypeUnitId takes integer unitTypeId returns integer
            local integer id = UnitGetId(unitTypeId)
            local integer foodCap
            local integer playerGold
            local integer playerWood
            local unit u
            if not HaveSavedBoolean(unitTypes, unitTypeId, 1) then
                call SaveBoolean(unitTypes, unitTypeId, 1, true)
                set u = CreateUnit(Player(12), unitTypeId, coordX, coordY, 0)
                if not IsUnitType(u, UNIT_TYPE_HERO) then
                    set unitGoldCost[id] = GetUnitGoldCost(unitTypeId)
                    set unitWoodCost[id] = GetUnitWoodCost(unitTypeId)
                else
                    set currentUnitType = unitTypeId
                    set foodCap = GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_FOOD_CAP)
                    set playerGold = GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD)
                    set playerWood = GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER)
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_FOOD_CAP, -1)
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, RESOURCE_LIMIT)
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER, RESOURCE_LIMIT)
                    call AddUnitToStock(costRetriever, unitTypeId, 1, 1)
                    call IssueNeutralImmediateOrderById(playerChecker, costRetriever, unitTypeId)
                    set unitGoldCost[id] = RESOURCE_LIMIT - GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD)
                    set unitWoodCost[id] = RESOURCE_LIMIT - GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER)
                    call RemoveUnitFromStock(costRetriever, unitTypeId)
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_FOOD_CAP, foodCap)
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, playerGold)
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER, playerWood)
                endif
                call RemoveUnit(u)
                call GetUnitBounty(unitTypeId, BOUNTY_ACCURACY)
                set u = null
            endif
            return id
        endfunction
        
        private function GetUnitId takes unit u returns integer
            local integer handleId
            debug if GetHandleId(u) > 0 then
                if runningUnit != u then
                    set handleId = GetHandleId(u)
                    if not HaveSavedInteger(units, handleId, 0) then
                        set runningUnitStackId = UnitStack.create()
                        call SaveInteger(units, handleId, 0, runningUnitStackId)
                    else
                        set runningUnitStackId = LoadInteger(units, handleId, 0)
                    endif
                    set runningUnit = u
                endif
                return runningUnitStackId
            debug endif
            debug return 0
        endfunction
        
        private function TrackUpgradeFinish takes nothing returns nothing
            local unit u = GetTriggerUnit()
            local integer handleId = GetHandleId(u)
            local integer id
            if HaveSavedInteger(units, handleId, 0) then
                set id = LoadInteger(units, handleId, 0)
                set unitGoldUpgrades[id] = unitGoldUpgrades[id] + unitGoldUpgradesPending[id]
                set unitWoodUpgrades[id] = unitWoodUpgrades[id] + unitWoodUpgradesPending[id]
                set unitGoldUpgradesPending[id] = unitWoodUpgradesLast[id]
                set unitWoodUpgradesPending[id] = unitWoodUpgradesLast[id]
            endif
            set u = null
        endfunction
        
        private function TrackUpgradeStart takes nothing returns nothing
            local unit u = GetTriggerUnit()
            local integer handleId = GetHandleId(u)
            local integer id
            local integer unitTypeId
            if HaveSavedInteger(units, handleId, 0) then
                set id = LoadInteger(units, handleId, 0)
                set unitTypeId = GetTypeUnitId(GetUnitTypeId(u))
                set unitGoldUpgradesLast[id] = unitGoldCost[unitTypeId]
                set unitWoodUpgradesLast[id] = unitWoodCost[unitTypeId]
            endif
            set u = null
        endfunction
        
        private function StopTrackUpgrade takes nothing returns boolean
            local integer id
            local integer handleId = GetHandleId(GetTriggerUnit())
            if HaveSavedInteger(units, handleId, 0) then
                set id = LoadInteger(units, handleId, 0)
                call RemoveSavedInteger(units, handleId, 0)
                call UnitStack(id).destroy()
                set unitGoldUpgrades[id] = 0
                set unitWoodUpgrades[id] = 0
            endif
            return false
        endfunction
    //End Units
    
    //Research
        globals
            private integer array researchGold[30]
            private integer array researchWood[30]
        endglobals
        
        function GetResearchGoldCost takes integer unitTypeId, integer techId, integer levelStart, integer levelFinish returns integer
            local integer playerGold = GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD)
            local integer playerWood = GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER)
            local integer techLevel = GetPlayerTechCount(playerChecker, techId, true)
            local integer cost = 0
            local integer count = levelStart
            local unit u = CreateUnit(playerChecker, unitTypeId, coordX, coordY, 0)
            call SetUnitPosition(u, coordX, coordY)
            call SetPlayerTechResearched(playerChecker, techId, levelStart)
            loop
                exitwhen count >= levelFinish
                if not HaveSavedInteger(research, techId, count) then
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, RESOURCE_LIMIT)
                    call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER, RESOURCE_LIMIT)
                    call IssueImmediateOrderById(u, techId)
                    call AddPlayerTechResearched(playerChecker, techId, 1)
                    set cost = RESOURCE_LIMIT - GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD) + cost
                    call SaveInteger(research, techId, count, RESOURCE_LIMIT - GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD))
                else
                    set cost = cost + LoadInteger(research, techId, count)
                endif
                set count = count + 1
            endloop
            call RemoveUnit(u)
            call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, 0)
            call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER, 0)
            call SetPlayerTechResearched(playerChecker, techId, 0)
            set u = null
            call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, playerGold)
            call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER, playerWood)
            call SetPlayerTechResearched(playerChecker, techId, techLevel)
            return cost
        endfunction
        
        function GetResearchWoodCost takes integer unitTypeId, integer techId, integer levelStart, integer levelFinish returns integer
            local integer playerGold = GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD)
            local integer playerWood = GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER)
            local integer techLevel = GetPlayerTechCount(playerChecker, techId, true)
            local integer cost = 0
            local integer count = levelStart
            local unit u = CreateUnit(playerChecker, unitTypeId, coordX, coordY, 0)
            call SetUnitPosition(u, coordX, coordY)
            call SetPlayerTechResearched(playerChecker, techId, levelStart)
            loop
                exitwhen count >= levelFinish
                call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, RESOURCE_LIMIT)
                call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER, RESOURCE_LIMIT)
                call IssueImmediateOrderById(u, techId)
                call AddPlayerTechResearched(playerChecker, techId, 1)
                set cost = RESOURCE_LIMIT - GetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER) + cost
                set count = count + 1
            endloop
            call RemoveUnit(u)
            call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, 0)
            call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER, 0)
            call SetPlayerTechResearched(playerChecker, techId, 0)
            set u = null
            call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_GOLD, playerGold)
            call SetPlayerState(playerChecker, PLAYER_STATE_RESOURCE_LUMBER, playerWood)
            call SetPlayerTechResearched(playerChecker, techId, techLevel)
            return cost
        endfunction
        
        private function TrackResearch takes nothing returns nothing
            local player p = GetTriggerPlayer()
            local integer playerId = GetPlayerId(p)
            local integer unitTypeId = GetUnitTypeId(GetTriggerUnit())
            local integer researched = GetResearched()
            local integer techCount = GetPlayerTechCount(p, researched, true)
            set researchGold[playerId] = researchGold[playerId] + GetResearchGoldCost(unitTypeId, researched, techCount, techCount+1)
            set researchWood[playerId] = researchWood[playerId] + GetResearchWoodCost(unitTypeId, researched, techCount, techCount+1)
        endfunction
    //End Research
    
    function StopUpgradeTracking takes unit u returns nothing
        local integer handleId = GetHandleId(u)
        local integer id
        if HaveSavedInteger(units, handleId, 0) then
            set id = LoadInteger(units, handleId, 0)
            call RemoveSavedInteger(units, handleId, 0)
            call UnitStack(id).destroy()
            set unitGoldUpgrades[id] = 0
            set unitWoodUpgrades[id] = 0
        endif
    endfunction
    
    function TrackUpgrades takes unit u returns nothing
        local integer id = GetUnitId(u)
        local integer unitTypeId = GetTypeUnitId(GetUnitTypeId(u))
        set unitGoldUpgradesPending[id] = unitGoldCost[unitTypeId]
        set unitWoodUpgradesPending[id] = unitWoodCost[unitTypeId]
    endfunction
    
    function GetPlayerGoldResearch takes player p returns integer
        return researchGold[GetPlayerId(p)]
    endfunction
    
    function GetPlayerWoodResearch takes player p returns integer
        return researchWood[GetPlayerId(p)]
    endfunction
    
    function GetUnitGoldUpgrades takes unit u returns integer
        return unitGoldUpgrades[GetUnitId(u)]
    endfunction
    
    function GetUnitWoodUpgrades takes unit u returns integer
        return unitWoodUpgrades[GetUnitId(u)]
    endfunction
    
    function GetUnitCachedBounty takes integer unitTypeId returns integer
        return goldBounty[GetTypeUnitId(unitTypeId)]
    endfunction
    
    function GetUnitGold takes integer unitTypeId returns integer
        return unitGoldCost[GetTypeUnitId(unitTypeId)]
    endfunction
    
    function GetUnitWood takes integer unitTypeId returns integer
        return unitWoodCost[GetTypeUnitId(unitTypeId)]
    endfunction
    
    function GetItemGoldCost takes integer itemTypeId returns integer
        return itemGoldCost[GetItemId(itemTypeId)]
    endfunction
    
    function GetItemWoodCost takes integer itemTypeId returns integer
        return itemWoodCost[GetItemId(itemTypeId)]
    endfunction
    
    function GetItemCharge takes integer itemTypeId returns integer
        return itemCharges[GetItemId(itemTypeId)]
    endfunction
    
    function GetItemTotalGoldCost takes item i returns integer
        local integer itemTypeId = GetItemId(GetItemTypeId(i))
        return (itemGoldCost[itemTypeId]*GetItemCharges(i))/itemCharges[itemTypeId]
    endfunction
    
    function GetItemTotalWoodCost takes item i returns integer
        local integer itemTypeId = GetItemId(GetItemTypeId(i))
        return (itemWoodCost[itemTypeId]*GetItemCharges(i))/itemCharges[itemTypeId]
    endfunction
    
    function GetUnitTotalGoldCost takes unit u returns integer
        local integer unitTypeId = GetUnitTypeId(u)
        local integer handleId = GetHandleId(u)
        local integer cost = unitGoldCost[GetTypeUnitId(unitTypeId)]
        local integer x = 0
        local integer inventorySize = UnitInventorySize(u)
        local item i
        if HaveSavedInteger(units, handleId, 0) then
            set cost = cost + GetUnitGoldUpgrades(u)
        endif
        if inventorySize > 0 then
            loop
                exitwhen x == inventorySize
                set i = UnitItemInSlot(u, x)
                if i != null then
                    set cost = cost + GetItemTotalGoldCost(i)
                endif
                set x = x + 1
            endloop
        endif
        set i = null
        set u = null
        return cost
    endfunction
    
    function GetUnitTotalWoodCost takes unit u returns integer
        local integer unitTypeId = GetUnitTypeId(u)
        local integer cost = unitWoodCost[GetTypeUnitId(unitTypeId)]
        local integer handleId = GetHandleId(u)
        local integer x = 0
        local integer inventorySize = UnitInventorySize(u)
        local item i
        if HaveSavedInteger(units, handleId, 0) then
            set cost = cost + GetUnitWoodUpgrades(u)
        endif
        if inventorySize > 0 then
            loop
                exitwhen x == inventorySize
                set i = UnitItemInSlot(u, x)
                if i != null then
                    set cost = cost + GetItemTotalWoodCost(i)
                endif
                set x = x + 1
            endloop
        endif
        set i = null
        set u = null
        return cost
    endfunction
    
    private function CheckUnit takes nothing returns boolean
        local integer playerId
        local unit u = GetFilterUnit()
        if GetUnitState(u, UNIT_STATE_LIFE) > 0 or IsUnitType(u, UNIT_TYPE_HERO) then
            set playerId = GetPlayerId(GetOwningPlayer(u))
            set goldResource[playerId] = goldResource[playerId] + GetUnitTotalGoldCost(u)
            set woodResource[playerId] = woodResource[playerId] + GetUnitTotalWoodCost(u)
        endif
        set u = null
        return false
    endfunction
    
    function UpdatePlayer takes player p returns nothing
        local integer playerId = GetPlayerId(p)
        set goldResource[playerId] = GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD) + researchGold[playerId]
        set woodResource[playerId] = GetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER) + researchWood[playerId]
        call GroupEnumUnitsOfPlayer(unitGroup, p, checkUnit)
        call GroupClear(unitGroup)
    endfunction
    
    constant function GetPlayerTotalGold takes integer playerId returns integer
        return goldResource[playerId]
    endfunction
    
    constant function GetPlayerTotalWood takes integer playerId returns integer
        return woodResource[playerId]
    endfunction
    
    private function StopBug takes nothing returns nothing
        if (GetUnitX(costRetriever) != coordX) or (GetUnitY(costRetriever) != coordY-64) then
            call IssueImmediateOrder(costRetriever, "stop")
            call IssuePointOrder(costRetriever, "move", coordX, coordY-64)
        endif
    endfunction
    
    private function Initialization takes nothing returns nothing
        local integer x = 11
        //! runtextmacro Stock_USER_SETTINGS()
        playerChecker = Player(14)
        set world = CreateRegion()
        set unitRemovalRegion = CreateRegion()
        set removalArea = Rect(coordX-64, coordY-128, coordX+64, coordY+64)
        call RegionAddRect(unitRemovalRegion, removalArea)
        call RegionAddRect(world, bj_mapInitialPlayableArea)
        call TriggerRegisterEnterRegion(unitRemoval, unitRemovalRegion, Condition(function RemoveUnits))
        set costRetriever = CreateUnit(playerChecker, unitCheckerId, 0, 0, 270)
        call SetUnitUseFood(costRetriever, false)
        call UnitAddAbility(costRetriever,'Asid')
        call UnitAddAbility(costRetriever,'Asud')
        call UnitAddAbility(costRetriever, 'Aloc')
        call UnitRemoveAbility(costRetriever, 'Awan')
        call UnitRemoveAbility(costRetriever, 'Aneu')
        call UnitRemoveAbility(costRetriever, 'Ane2')
        call ShowUnit(costRetriever, false)
        call SetUnitPosition(costRetriever, coordX, coordY-64)
        call SetUnitAcquireRange(costRetriever, 0)
        loop
            set x = x - 1
            call TriggerRegisterPlayerUnitEvent(unitUpgradeStartTracking, GetPlayer(x), EVENT_PLAYER_UNIT_UPGRADE_START, null)
            call TriggerRegisterPlayerUnitEvent(unitUpgradeFinishTracking, GetPlayer(x), EVENT_PLAYER_UNIT_UPGRADE_FINISH, null)
            call TriggerRegisterPlayerUnitEvent(unitFinishResearching, GetPlayer(x), EVENT_PLAYER_UNIT_RESEARCH_FINISH, null)
            exitwhen x == 0
        endloop
        //! runtextmacro Stock_EXTRA_PLAYERS()
        call TriggerRegisterLeaveRegion(stopUnitUpgradeTracking, world, Condition(function StopTrackUpgrade))
        call TriggerAddAction(unitUpgradeStartTracking, function TrackUpgradeStart)
        call TriggerAddAction(unitUpgradeFinishTracking, function TrackUpgradeFinish)
        call TriggerAddAction(unitFinishResearching, function TrackResearch)
        call TimerStart(CreateTimer(), .5, true, function StopBug)
        set removeItems = Condition(function RemoveItems)
        set checkUnit = Condition(function CheckUnit)
    endfunction
endlibrary


Bounty
JASS:

library Bounty initializer Initialization requires Stock
/*Utility Information
//===================================================================
Name: Bounty
Version: 1.1
Author: Nestharus

Settings:
*///===================================================================
globals
    private constant boolean ARCHIVES = false
    private constant real GOLD_UPDATE_INTERVAL = .03125
endglobals
/*//===================================================================

Description:
    What does it do-
        This creates a variable that stores the bounty of the last killed unit. This will not
        get bounty at a whim. Stock has various functions for retrieving cached bounty and randomized
        bounty on a whim. This will also make Stock's cached bounty more accurate.
        
    How does it do it-
        Player gold is stored through out the game. As players kill, the gold is updated
        and the difference between the new gold and the old gold is stored into the bounty
        variable. From here, the bounty variable can be retrieved at any time. Bounty is also archived
        for each unit type. There is a function for retrieving bounty from 30 kills back for a specific
        unit type. This archiving is only done if it is turned on.
        There is a function for retrieving bounty from 30 kills back for a specific unit type.
        
Requirements: PTN- hiveworkshop.com/forums/jass-functions-413/system-pt-player-tracking-142554/
              Recycle- thehelper.net/forums/showthread.php?t=136087
              Stock
            
Installation: NA

Variables and Settings:
------------------------------------------------------------------
ARCHIVES- whether the system archives bounty or not.

GOLD_UPDATE_INTERVAL- How often gold is updated. Gold is updated
to keep bounty accurate. Whenever players buy units or items or sell
things or gold is added to them, the gold value stored in the system
differs from that of the actual player. This results in a bounty that
isn't accurate.
------------------------------------------------------------------

Functions:
------------------------------------------------------------------
-Bounty_GetLastBounty() returns integer
    A constant function that returns the last bounty.

-Bounty_GetArchivedBounty(integer unitTypeId, integer stepsBack) returns integer
    Will return archived bounty from x steps back. 0 would be
    exactly like GetLastBounty. Stores the archive into a hashtable.
------------------------------------------------------------------*/
    globals
        private integer array playerGold
        private trigger unitBountyRecord = CreateTrigger()
        private integer lastBounty
        private hashtable bountyArchive
        private timer goldUpdate = CreateTimer()
    endglobals
    
    public function GetLastBounty takes nothing returns integer
        return lastBounty
    endfunction
    
    public function GetArchivedBounty takes integer unitTypeId, integer stepsBack returns integer
        if ARCHIVES then
            return LoadInteger(bountyArchive, unitTypeId, LoadInteger(bountyArchive, unitTypeId, -1)-stepsBack)
        endif
        return 0
    endfunction
    
    private function IntervalBounty takes nothing returns nothing
        local integer x = 16
        loop
            set x = x - 1
            set playerGold[x] = GetPlayerState(GetPlayer(x), PLAYER_STATE_RESOURCE_GOLD)
            exitwhen x == 0
        endloop
    endfunction
    
    private function UpdateBounty takes nothing returns boolean
        local player p = GetOwningPlayer(GetTriggerUnit())
        local integer playerId = GetPlayerId(p)
        local integer unitTypeId = GetUnitTypeId(GetTriggerUnit())
        local integer index
        local integer gold = GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD)
        set lastBounty = gold-playerGold[playerId]
        set playerGold[playerId] = gold
        call Stock_UpdateBounty(unitTypeId, lastBounty, lastBounty)
        if ARCHIVES then
            set index = LoadInteger(bountyArchive, unitTypeId, -1)+1
            call SaveInteger(bountyArchive, unitTypeId, -1, index)
            call SaveInteger(bountyArchive, unitTypeId, index, lastBounty)
        endif
        return false
    endfunction
    
    private function Initialization takes nothing returns nothing
        local integer x = 16
        call TriggerAddCondition(unitBountyRecord, Condition(function UpdateBounty))
        loop
            set x = x - 1
            call TriggerRegisterPlayerUnitEvent(unitBountyRecord, GetPlayer(x), EVENT_PLAYER_UNIT_DEATH, null)
            exitwhen x == 0
        endloop
        if ARCHIVES then
            set bountyArchive = InitHashtable()
        endif
        call TimerStart(goldUpdate, GOLD_UPDATE_INTERVAL, true, function IntervalBounty)
    endfunction
endlibrary
 

Jesus4Lyf

Good Idea™
Reaction score
397
I don't expect TH moderators to allow users to bring their own custom classifications and apply them on TheHelper.

It is a grave disappointment that you insist everything be done your way instead of trying to get along with the community. (Talking about the Mfn requirement and custom classification and such, honestly you could be compatible and play nice instead.)

What have you used Mfn for here?
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
The way I see this, you could support yourself by requiring Mfn for the (O(n)) search function.


Or you could require J4L's Hash function, which is not only a far smaller block of code, but also more efficient in any situation involving more than one item being loaded into the array, in some cases perhaps hundreds of times as efficient.
 

Nestharus

o-o
Reaction score
84
The way I see this, you could support yourself by requiring Mfn for the (O(n)) search function.


Or you could require J4L's Hash function, which is not only a far smaller block of code, but also more efficient in any situation involving more than one item being loaded into the array, in some cases perhaps hundreds of times as efficient.

Actually, I probably will use hash : ).

But I'll still be requiring Mfn for credits and various variables o-o.

I really wasn't thinking about hash Oo.

Tx uberfoop ^^, +rep to u : D

Change your requirement to an approved one or +graveyard note o_O

Go for it : )
 

Jesus4Lyf

Good Idea™
Reaction score
397
Yes, Hash will bring this a good step in the right direction. That's what it was written for - when I asked what this is using Mfn for, it was because I saw that and was going to suggest Hash but I suppose Uberfoop beat me to it.

I still think the next step should be making this stand-alone. Although you like to build ground up, we tend not to need such approaches with Jass because we can just use an assortment of small pieces on which to build the map...

Systems and Snippets to support the map.

So instead of your framework, you'd have a bunch of small snippets which people use in their systems.

Anyway, just my thoughts on the issues at the moment...
 

Nestharus

o-o
Reaction score
84
I believe that doesn't work on custom items. I'm not even sure it'd detect modified item costs, actually, but that statement is untested.

hmm

JASS:

native function GetItemGoldCost takes integer itemid returns integer
native function GetItemLumberCost takes integer itemid returns integer


So you are saying JassHelper added two of these, or at least one? I know they aren't normal natives, so they would have to have been added via grimoire...

*tries them out*

and they apparently weren't.

I think you are confusing them with-
JASS:

native function GetUnitGoldCost takes integer itemid returns integer
native function GetUnitLumberCost takes integer itemid returns integer


I also googled them and I found "0" information on them.

Are you sure?? I know Blizzard doesn't support it anywhere.

And Jesus4Lyf, all common.ai functions work fine on all customs : \.

Next:
I still think the next step should be making this stand-alone. Although you like to build ground up, we tend not to need such approaches with Jass because we can just use an assortment of small pieces on which to build the map...

to

So instead of your framework, you'd have a bunch of small snippets which people use in their systems.

You said it yourself. I like to build from the ground up like a pyramid : ). That's my style.
 

Tom Jones

N/A
Reaction score
437
hmm

JASS:

native function GetItemGoldCost takes integer itemid returns integer
native function GetItemLumberCost takes integer itemid returns integer


So you are saying JassHelper added two of these, or at least one? I know they aren't normal natives, so they would have to have been added via grimoire...

*tries them out*

and they apparently weren't.

I think you are confusing them with-
Spot on mate, I confused it with something I once saw at wc3jass.
 

Nestharus

o-o
Reaction score
84
np

I have to add in a getUnitGoldCost anyways

Actually, 2.0 will be up in a sec : D

Gicn is now Gcsn (Get Costs and States) : o.

It has a few new functions and does some other things.

^^
 

Jesus4Lyf

Good Idea™
Reaction score
397
I'm gonna try to just point this out once here, as we talked about this on IRC.
JASS:
    public function getItemGoldCost takes integer itemType returns integer
        return ItemType(ItemType[itemType].new(itemType)).goldCost
    endfunction

    public function getItemWoodCost takes integer itemType returns integer
        return ItemType(ItemType[itemType].new(itemType)).woodCost
    endfunction

The standards we have on TH are CapitalisedFunctionNamesLikeThis, so getItemGoldCost --> GetItemGoldCost. (It's the same standard all BJ JASS and natives follow, except for the "main" and "config" functions which are different as WC3 is meant to access them directly. It's also the standard I've seen used for the past 7 years in all JASS code written.)

I'll refrain from replying to any riposte about this, as it will be off topic and for moderators to bring up if they should choose to.

Aside from that.
It looks like you're using an old version of Hash. Did you take the new one and update it to be a method thing? Just checking.
 

Nestharus

o-o
Reaction score
84
v2.0 has new version of hash, but it uses a special Hybrid version of Hash in Mfn : ).

I'm still awaiting your approval of hybrid version that allows Free Memory : D.
 
Reaction score
91
JASS:

        private constant string SYSTEM = "Gicn"
        private constant string VERSION = "1.1"
        private constant string AUTHOR = "Nestharus"
        private constant string HELPERS = "None"
        private constant string TEXTURE_PATH = "UI\\Feedback\\Resources\\ResourceGold.blp"
        private constant string DESCRIPTION = "Get Item Costs"

?!? Remove this, it does nothing. Totally useless.

JASS:

        call UnitAddAbility(unitChecker,'Asid')
        call UnitAddAbility(unitChecker, 'Aloc')
        call UnitRemoveAbility(unitChecker, 'Awan')
        call UnitRemoveAbility(unitChecker, 'Aneu')
        call UnitRemoveAbility(unitChecker, 'Ane2')


Those are unnamed constants.
 

Nestharus

o-o
Reaction score
84
JASS:
        private constant string SYSTEM = "Gicn"
        private constant string VERSION = "1.1"
        private constant string AUTHOR = "Nestharus"
        private constant string HELPERS = "None"
        private constant string TEXTURE_PATH = "UI\\Feedback\\Resources\\ResourceGold.blp"
        private constant string DESCRIPTION = "Get Item Costs"

?!? Remove this, it does nothing. Totally useless.

JASS:
        call UnitAddAbility(unitChecker,'Asid')
        call UnitAddAbility(unitChecker, 'Aloc')
        call UnitRemoveAbility(unitChecker, 'Awan')
        call UnitRemoveAbility(unitChecker, 'Aneu')
        call UnitRemoveAbility(unitChecker, 'Ane2')


Those are unnamed constants.

For part 1, no can do : )

???? on part 2? no they aren't?
 

Jesus4Lyf

Good Idea™
Reaction score
397
JASS:
    //! textmacro Hash_CREATE takes new, destroy
        globals
            private constant integer HASH_NEXT = 90
            private constant integer MAX_HASH_VALUE = 8191
            private integer array HashedInt
            private integer array HashIndexes
        endglobals
        
        private function GetIndex takes integer int returns integer
            local integer value = int
            loop
                exitwhen value < 90
                set value = value-HASH_NEXT
            endloop
            return value
        endfunction
        
        public function Hash takes integer int returns integer
            local integer hash=int-(int/MAX_HASH_VALUE)*MAX_HASH_VALUE
            local integer index
            loop
                exitwhen HashedInt[hash] == int
                if HashedInt[hash] == 0 then
                    set HashedInt[hash] = int
                    set index = GetIndex(hash)
                    if HashIndexes[index] < hash then
                        set HashIndexes[index] = hash
                    endif
                    $new$
                    return hash
                endif
                set hash = hash+HASH_NEXT
                if hash >= MAX_HASH_VALUE then
                    set hash = hash - MAX_HASH_VALUE
                endif
            endloop
            return hash
        endfunction
        
        public function FreeHash takes integer int returns nothing
            local integer hash = Hash(int)
            local integer index = GetIndex(hash)
            local integer recycledPosition = HashIndexes[index]
            local integer previousPosition = HashIndexes[index]
            if previousPosition > index then
                set previousPosition = previousPosition - HASH_NEXT
                loop
                    exitwhen HashedInt[previousPosition] != 0 or previousPosition < HASH_NEXT
                    set previousPosition = previousPosition-HASH_NEXT
                endloop
            endif
            if recycledPosition > hash then
                set HashedInt[hash] = HashedInt[recycledPosition]
                set HashedInt[recycledPosition] = 0
            endif
            $destroy$
            set HashedInt[hash] = 0
            set HashIndexes[index] = previousPosition
        endfunction
    //! endtextmacro


gogogo : D
Gosh, that was a terrible algorithm. ;)
 

Nestharus

o-o
Reaction score
84
Well, v3.0 is out now featuring the new-
getBounty(unitType)


Useful for balancing between uneven teams where the smaller team gets extra gold : ). Add % extra bounty per kill based on the size difference between the teams.

This is what I use exactly : D

JASS:

    private function extraBounty takes nothing returns nothing
        local player p = GetOwningPlayer(GetKillingUnit())
        local unit u = GetTriggerUnit()
        local integer killing = Team(Players(players[GetPlayerId(p)]).f).count
        local integer dying = Team(Players(players[GetPlayerId(GetOwningPlayer(u))]).f).count
        local integer amount
        local texttag show
        if killing > dying then
            set amount = R2I((killing-dying)*(BALANCE_PERCENT_BOUNTY/100)*Gcsn_getBounty(GetUnitTypeId(u)))
            call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, R2I(GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD)+amount))
            set show = CreateTextTag()
            call SetTextTagText(show, "|cffffcc00+" + I2S(amount), .022)
            call SetTextTagPermanent(show, false)
            call SetTextTagLifespan(show, 1)
            call SetTextTagFadepoint(show, .5)
            call SetTextTagPos(show, GetUnitX(u), GetUnitY(u), 0)
            if GetLocalPlayer() != p then
                call SetTextTagVisibility(show, false)
            endif
        endif
        set show = null
        set u = null
        set p = null
    endfunction


It will help balance out extra bounty. Any map that has a chance for uneven teams should use this and should just give extra gold to the player at start and give gold to partners of players that leave (I use 25% all the time cuz it seems to work well).

Again, this'll help balance out any team map : D.
 

Dem0n_Hunter

Active Member
Reaction score
2
as I said I'm noob, so I just don't get how is this gonna get those thing u say in there. i mean does this work with commands in game or something like that?
Description:
Retrieves various costs and states
Edit: I just found the command.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top