• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

GetItemCost

This system allows you to get gold/lumber cost of items (in Hero's inventory or on the ground). Takes into account the number of charges.

The map is for demonstration purposes only.
The map is for demonstration purposes only.
Writing same sentence twice makes people less likely to ignore it.

How to use:
Code:
function GetItemTypeIdCharges takes integer itemTypeId returns integer
function GetItemTypeIdGoldCost takes integer itemTypeId returns integer
function GetItemTypeIdLumberCost takes integer itemTypeId returns integer
function GetItemGoldCost takes item whichItem returns integer
function GetItemLumberCost takes item whichItem returns integer


How to add to your map:
1. Create Trigger
2. Convert it to Custom Text
3. Copy and paste the following code:
[jass=the following code]library GetItemCost
//================================================================
// Version 1.3
//
//================================================================
//Changelog
//V1.3 - Removed fail-safe check in favor of (ab)using Locust ability
//
//V1.2 - Added fail-safe check (whether global dummies are dead)
// - Changed initializer (now code can be called from inside a module initializer
// or struct initializer thread)
//
//V1.1 - Added global dummies
//
//V1.0 - Created
//================================================================
// Provides functions for getting gold/lumber costs of the item,
// in other words amount of gold or lumber you'd get for selling
// that item to a vendor.
// By default, it's 50% of the price you'd pay for buying the item.
// It can be changed here:
// Gameplay Constant -> Inventory - Sell Item Return Rate
//================================================================
// The API provides following functions:
//
// GetItemTypeIdCharges takes integer itemTypeId returns integer
// GetItemTypeIdGoldCost takes integer itemTypeId returns integer
// GetItemTypeIdLumberCost takes integer itemTypeId returns integer
// GetItemGoldCost takes item whichItem returns integer
// GetItemLumberCost takes item whichItem returns integer
//================================================================
// Constant "dummy" used in this library is standard Sentry Ward.
// You can (and should) replace it with your own dummy.
//================================================================
// This library cannot determine cost of items classified as
// "Power Up" and will always return 0 for them.
//================================================================

globals
//Hashtable for storing item costs and charges
private hashtable ItemCost = InitHashtable()

//Constants to be used as hash keys
private constant integer ITEM_COST_GOLD = 0
private constant integer ITEM_COST_LUMBER = 1
private constant integer ITEM_DEFAULT_CHARGES = 3

//Player (Neutral Passive) for buying/selling
private constant player NP = Player(PLAYER_NEUTRAL_PASSIVE)

//Dummy unit - feel free to replace it
private constant integer dummy = 'oeye'

//A vendor (shop) and a customer
private unit vendor = null
private unit seller = null
endglobals

//Initializer (vendor)
private function CreateVendor takes nothing returns nothing
//Create vendor
set vendor = CreateUnit(NP, dummy, 0, 0, 0)
//Hide vendor
call ShowUnit(vendor, false)
call SetUnitPathing(vendor, false)
//Give vendor ability to buy items
call UnitAddAbility(vendor, 'Apit')
//Give vendor locust
call UnitAddAbility(vendor, 'Aloc')
endfunction

//Initializer (seller)
private function CreateSeller takes nothing returns nothing
//Create seller
set seller = CreateUnit(NP, dummy, 0, 0, 0)
//Move it to the vendor
call SetUnitPathing(seller, false)
call SetUnitX(seller, GetUnitX(vendor))
call SetUnitY(seller, GetUnitY(vendor))
//Hide seller
call ShowUnit(seller, false)
//Give seller ability to carry items
call UnitAddAbility(seller, 'AInv')
//Give seller locust
call UnitAddAbility(seller, 'Aloc')
endfunction

//Initializer (module)
private module Initialize
private static method onInit takes nothing returns nothing
call CreateVendor()
call CreateSeller()
endmethod
endmodule

//Initializer (struct)
struct Initializer extends array
implement Initialize
endstruct

//======================Rather self-explanatory===================
function GetItemTypeIdCharges takes integer itemTypeId returns integer
local item whichItem
local integer charges

//load default number of charges from hashtable
if (HaveSavedInteger(ItemCost, itemTypeId, ITEM_DEFAULT_CHARGES)) then
set charges = LoadInteger(ItemCost, itemTypeId, ITEM_DEFAULT_CHARGES)
else
//or create new item of the same type and get it's number of charges
set whichItem = CreateItem(itemTypeId, 0, 0)
set charges = GetItemCharges(whichItem)
call SaveInteger(ItemCost, itemTypeId, ITEM_DEFAULT_CHARGES, charges)
call RemoveItem(whichItem)
set whichItem = null
endif

return charges
endfunction

//=======================Calculate Cost===========================
private function CalculateItemCost takes integer itemTypeId returns nothing
local integer gold
local integer lumber
local integer goldcost
local integer lumbercost

//Creates new instance of the item
local item goods = CreateItem(itemTypeId, 0, 0)

//Detects if the item is power-up.
if (GetItemType(goods) == ITEM_TYPE_POWERUP) then
call RemoveItem(goods)
set goods = null
//Save both costs in the Hashtable
call SaveInteger(ItemCost, itemTypeId, ITEM_COST_GOLD, 0)
call SaveInteger(ItemCost, itemTypeId, ITEM_COST_LUMBER, 0)
return
endif

//Store Neutral Passive's gold and lumber
set gold = GetPlayerState(NP, PLAYER_STATE_RESOURCE_GOLD)
set lumber = GetPlayerState(NP, PLAYER_STATE_RESOURCE_LUMBER)

//Give dummy the item
call UnitAddItem(seller, goods)

//Make dummy sell item
call ShowUnit(vendor, true)
call UnitDropItemTarget(seller, goods, vendor)
call ShowUnit(vendor, false)

set goods = null

//Calculate cost (Neutral Passive's gold/lumber)
set goldcost = GetPlayerState(NP, PLAYER_STATE_RESOURCE_GOLD) - gold
set lumbercost = GetPlayerState(NP, PLAYER_STATE_RESOURCE_LUMBER) - lumber

//Save both costs in the Hashtable
call SaveInteger(ItemCost, itemTypeId, ITEM_COST_GOLD, goldcost)
call SaveInteger(ItemCost, itemTypeId, ITEM_COST_LUMBER, lumbercost)

//Also save charges, while you're at it
call GetItemTypeIdCharges(itemTypeId)

//Restore Neutral Passive's gold and lumber
call SetPlayerState(NP, PLAYER_STATE_RESOURCE_GOLD, gold)
call SetPlayerState(NP, PLAYER_STATE_RESOURCE_LUMBER, lumber)
endfunction

//==================Load Cost (or calculate)======================
private function GetItemCost takes integer itemTypeId, integer costType returns integer
//Store item data in hashtable if its not there already
if (not(HaveSavedInteger(ItemCost, itemTypeId, costType))) then
call CalculateItemCost(itemTypeId)
endif
//Read cost from hashtable
return LoadInteger(ItemCost, itemTypeId, costType)
endfunction

//===========================API==================================
function GetItemTypeIdGoldCost takes integer itemTypeId returns integer
return GetItemCost(itemTypeId, ITEM_COST_GOLD)
endfunction

function GetItemTypeIdLumberCost takes integer itemTypeId returns integer
return GetItemCost(itemTypeId, ITEM_COST_LUMBER)
endfunction

function GetItemGoldCost takes item whichItem returns integer
local integer cost = GetItemTypeIdGoldCost(GetItemTypeId(whichItem))
if (GetItemCharges(whichItem) > 0) then
set cost = cost*GetItemCharges(whichItem)/GetItemTypeIdCharges(GetItemTypeId(whichItem))
endif
return cost
endfunction

function GetItemLumberCost takes item whichItem returns integer
local integer cost = GetItemTypeIdLumberCost(GetItemTypeId(whichItem))
if (GetItemCharges(whichItem) > 0) then
set cost = cost*GetItemCharges(whichItem)/GetItemTypeIdCharges(GetItemTypeId(whichItem))
endif
return cost
endfunction

endlibrary[/code]

This system uses hashtable. Idea is, if it already calculated item's value, it doesn't have to do that ever again because it cannot be changed ingame.

Keywords:
Item, ItemCost, Cost, GetItemCost, Gold, Lumber, Price, Value
Contents

Just another Warcraft III map (Map)

Reviews
00:35, 11th Feb 2016 Criticism: One of few possibilities to access the gold, lumber and charges field of item type ids. The way you've chosen has a few ( small ) flaws, namely: Items of type ITEM_TYPE_POWERUP can only be accessed by creating...

Moderator

M

Moderator

00:35, 11th Feb 2016

Criticism:

One of few possibilities to access the gold, lumber and charges field of item type ids.
The way you've chosen has a few ( small ) flaws, namely:
  • Items of type ITEM_TYPE_POWERUP can only be accessed by creating a hero type dummy unit.
  • Your system is inefficient on further gold or lumber lookups of the same item type id.

From moderator to user:

You'll not be able to calculate the resource cost of powerup items,
such as tomes or glyphs are.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Item costs are absolute values and must not be rounded by using +.5 in R2I.
Why are costs saved as real in the first place? Resouce costs are integer values.

The API should also cover:
function GetItemTypeIdGoldCost takes integer itemTypeId returns integer
function GetItemTypeIdLumberCost takes integer itemTypeId returns integer
function GetItemTypeIdCharges takes integer itemTypeId returns integer

JASS:
private function GetItemChargesIgnoreZero takes item whichItem returns integer
    return IMaxBJ(1, GetItemCharges(whichItem))
endfunction

Once done you should restore the resource state of the neutral player.
You can't know for what a map maker is using it.
--> Get previous resource state --> Do your stuff --> Restore it.

function UnitAddItemSwapped takes item whichItem, unit whichHero returns boolean
is a wrapper function to UnitAddItem takes unit u, item whichItem returns boolean
Which does not inline, because Blizzard is sometimes stupid.

How does this system work for items of type ITEM_TYPE_POWERUP?
I can tell you want happens. The game season will end in a fatal error,
because adding power ups by function call to non-hero units does crash the game.

costs == 0 can be a valid resource cost information for items.
For example when an item costs 0 lumber.
Better go with HaveSavedInteger(hash, itemId, typeOfCost)

It's very costly to get the item cost in exchange of two unit handles and one item handle.

You might want to compare your code to GetItemCost
This one also has flaws ( I guess ), when the edge of the map is not pathable for units.
In that case the rect enumeration is incorrect, as the shop will not stand in the desired point.
The system never double checks for a properly created shop, hence can fail.

The rect must be draw from the center of the unit with a width and height of 1088
to north, west, south and east.
Also the system must first enumerate all items in the rect and mark them other items.
( SaveBoolean(hash, GetHandleId(enumItem), 0, true)
before ordering the shop command.
The enumerate again all items and find the one which fits in type id and is not marked.
Only then the system works flawless.

Marking an item that it gets ignored is important as items have item-user-data or can
be reference by handle id in other system.

I have a ItemCost library somewhere on my computer.
I can submit it.

Small hint: A not rendered unit ( ShowUnit(u, false) ) can still perform shop orders.
 
Last edited:
Level 3
Joined
Mar 31, 2015
Messages
28
Thanks for the detailed review.

Why are costs saved as real in the first place? Resouce costs are integer values.
I tried to avoid saving default number of charges in the hashtable, and the only way I could think of was saving price per charge instead of price.

The API should also cover:
function GetItemTypeIdGoldCost takes integer itemTypeId returns integer
function GetItemTypeIdLumberCost takes integer itemTypeId returns integer
function GetItemTypeIdCharges takes integer itemTypeId returns integer
Did the first two. Why should GetItemTypeIdCharges be part of API?

Once done you should restore the resource state of the neutral player.
You can't know for what a map maker is using it.
--> Get previous resource state --> Do your stuff --> Restore it.
Fixed.

function UnitAddItemSwapped takes item whichItem, unit whichHero returns boolean
is a wrapper function to UnitAddItem takes unit u, item whichItem returns boolean
Which does not inline, because Blizzard is sometimes stupid.
Fixed.

How does this system work for items of type ITEM_TYPE_POWERUP?
I can tell you want happens. The game season will end in a fatal error,
because adding power ups by function call to non-hero units does crash the game.
I see your point, but I cannot think of a way to calculate power-up cost because it cannot be sold to a shop, and so the value returned will be 0. To fix crashing, dummy is now hero-dummy.

costs == 0 can be a valid resource cost information for items.
For example when an item costs 0 lumber.
Better go with HaveSavedInteger(hash, itemId, typeOfCost)
Fixed.

As for the rest, I think I'm missing something very obvious because it seems I've solved the non-pathable fail by
JASS:
    call SetUnitPathing(seller,false)
    call SetUnitX(seller,0)
    call SetUnitY(seller,0)
and thus skipped the whole enumeration part. What am I missing?

Small hint: A not rendered unit ( ShowUnit(u, false) ) can still perform shop orders.
Partially true. Shop has still to be shown.

- A good documentation is the first step to proper debugging.
I thought I did proper documentation, or at least placed a lot of comments and tried to make code readable.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
- A good documentation is the first step to proper debugging.

It's his signature btw. I'm not sure tho is it supposed to be a part of of his review or not because somehow your documentation also could use some works :p Kind of tricky :\

I thought I did proper documentation, or at least placed a lot of comments and tried to make code readable.
You also need to write some documentations as the header of the code. At least it should includes name and short description (and maybe version number) of the resource, required systems, how to import, user API, and credits (depends on the resource tho).
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Did the first two. Why should GetItemTypeIdCharges be part of API?
Charges directly influence the cost of an item.
An item id can have by default x charges, which determines is base resource cost.
You have to calculcate the default charges anyway, therefore you can also provide an
API to get the default charges set in the object editor.

I see your point, but I cannot think of a way to calculate power-up cost because it cannot be sold to a shop, and so the value returned will be 0. To fix crashing, dummy is now hero-dummy.

ItemResourceCost is a further developed version of Nestharus ItemCost library.
It does allow the calculation of resource cost for items of type powerup.

I thought I did proper documentation, or at least placed a lot of comments and tried to make code readable.
It's my signature and appears everywhere I make a comment. :)

-------------------------

private function GetItemTypeIdCharges takes integer itemTypeId returns integer
^
This function shouldn't be private.

JASS:
    //load default number of charges from hashtable
    if (HaveSavedInteger(ItemCost, itemTypeId, ITEM_DEFAULT_CHARGES)) then
        set charges = LoadInteger(ItemCost, itemTypeId, ITEM_DEFAULT_CHARGES)
    else
    //or create new item of the same type and get it's number of charges
        set whichItem = CreateItem(itemTypeId, 0, 0)
        set charges = GetItemChargesProperly(whichItem)
        call SaveInteger(ItemCost, itemTypeId, ITEM_DEFAULT_CHARGES, charges)
        call RemoveItem(whichItem)
        set whichItem = null
    endif
    return charges
^
Returns 1 for items ids with 0 charges and 1 for item ids with 1 charge.

call ShowUnit(seller,false)
^
As you remove the shop inside the function, this line is not required.
You only need it, if the shop is a static unit.

JASS:
    //just in case that point (0,0) is non-pathable
    call SetUnitPathing(seller,false)
    call SetUnitX(seller,0)
    call SetUnitY(seller,0)
^
In case 0, 0 is not pathable, the shop will also not be on that spot.

Player(PLAYER_NEUTRAL_AGGRESSIVE)
^
Should be stored into a local player.

You have to deal with the case of an item beeing of type power up.
Using a hero unit may not be the best idea. I'm not even sure if heroes
are flushed from the memory once created and removed.

Better disallow to calculate power ups by detecting this item type in the first place.

The system has an unperformant design, as the computation costs are very high for the CreateUnit native.
Especially if one detects unit enter region events via unit indexer systems.
 
Last edited:
Level 3
Joined
Mar 31, 2015
Messages
28
You have to calculcate the default charges anyway, therefore you can also provide an API to get the default charges set in the object editor.
This function shouldn't be private.
Fine. Fine. You win. It's part of the API now.


ItemResourceCost is a further developed version of Nestharus ItemCost library.
It does allow the calculation of resource cost for items of type powerup.
You can calculate item buying price, sure, but certainly not selling price. Except by assuming that Gameplay Constants are not modified, but that's cheating.

^
Returns 1 for items ids with 0 charges and 1 for item ids with 1 charge.
I had no problem with that until I've made GetItemTypeIdCharges public. Now it's fixed and I check for zero charges elsewhere.

^
In case 0, 0 is not pathable, the shop will also not be on that spot.
Fixed that as well. I included "new" test map where (0,0) is not pathable (I used Abyss terrain).

You have to deal with the case of an item beeing of type power up.
Using a hero unit may not be the best idea. I'm not even sure if heroes
are flushed from the memory once created and removed.
Fixed. Now it checks itemType before attempting to calculate its cost.

The system has an unperformant design, as the computation costs are very high for the CreateUnit native.
Especially if one detects unit enter region events via unit indexer systems.
Fixed that as well. Now I have two global dummies.




One more thing. For some reason, it doesn't restore gold/lumber properly (at all). The prices are returned correctly, though.
 
Level 3
Joined
Mar 31, 2015
Messages
28
Items of type ITEM_TYPE_POWERUP can only be accessed by creating a hero type dummy unit.
I've abandoned idea of using hero dummy. Now I detect item type and return 0 if it's powerup. So dummy isn't hero unit anymore.

Your system is inefficient on further gold or lumber lookups of the same item type id.
Why? I read from hashtable and return result. What more efficient way there is?

While saving gold costs you could also save lumber costs in the same process and vis-à-vis.
I've changed it and now it does exactly that.

Your system code will fail if called inside a module initializer or struct initializer thread.
Why and how to fix that? Could you explain that to me in little more detail?

Currently the neutral player resource is not reset properly. I explained in the comment why.
Fixed that as well. Thanks for pointing it out.

I seldom give such sharp criticism
The point of criticism is to make me improve my code. As long as its precise (e.g. "this here doesn't work properly because of that"), it's very much appreciated.
 
Level 13
Joined
Mar 19, 2010
Messages
870
Whats wrong with this existing library? It exists a long time and work perfect... Just take a few minutes on google... and there it is :) - Don't wastn your time with coding a system which already exists :)

Code:

JASS:
/*
            GetItemCost v1.0.0
               by kingking
               
    GetItemCost is a simple snippet that let you to get the cost 
    of an item without entering the relative cost and item id to
    database, like hashtable.
    
    Function provided :
    GetItemGold(itemId) -> integer
    GetItemLumber(itemId) -> integer
    
    Mechanism description :
    GetItemCost creates a dummy at the middle of map.
    To get item cost, simply add the item to the dummy and ask
    the dummy to buy the item.
    Then store the difference between before and after of the
    lumber and gold.
    
    Requires :
    Table
*/
library GetItemCost requires Table
    
    globals
        private Table Gold
        private Table Lumber
        private unit Dummy
        private integer array ItemIdStack
        private integer StackLevel = 0
    endglobals
    
    private function PreloadItemCost takes integer id returns nothing
        local integer gold
        local integer lumber
        call SetPlayerState(Player(15),PLAYER_STATE_RESOURCE_GOLD,1000000)
        call SetPlayerState(Player(15),PLAYER_STATE_RESOURCE_LUMBER,1000000)
        call AddItemToStock(Dummy,id,1,1)
        set StackLevel = StackLevel + 1
        set ItemIdStack[StackLevel] = id
        call IssueImmediateOrderById(Dummy, id)
        set gold = GetPlayerState(Player(15),PLAYER_STATE_RESOURCE_GOLD)
        set lumber = GetPlayerState(Player(15),PLAYER_STATE_RESOURCE_LUMBER)
        set Gold[id] = 1000000 - gold
        set Lumber[id] = 1000000 - lumber
        // All right, get the item cost here and save to hashtable.
    endfunction
    
    function GetItemGold takes integer id returns integer
        if Gold.exists(id) == false then
            call PreloadItemCost(id)
        endif
        return Gold[id]
    endfunction
    
    function GetItemLumber takes integer id returns integer
        if Lumber.exists(id) == false then
            call PreloadItemCost(id)
        endif
        return Lumber[id]
    endfunction
    
    private struct Initializer extends array
        private static timer t
        private static rect r
        private static integer nearest_id
        private static real nearest_range
        private static item nearest_item
        
        private static method getNearestItem takes nothing returns boolean
            local item i = GetFilterItem()
            local real range
            if nearest_id == GetItemTypeId(i) then
                set range = GetWidgetX(i) * GetWidgetX(i) + GetWidgetY(i) * GetWidgetY(i)
                if range <= nearest_range then
                    set nearest_range = range
                    set nearest_item = i
                endif
            endif
            set i = null
            return false
        endmethod
        
        private static method removeItems takes nothing returns nothing
            loop
            exitwhen StackLevel == 0
                set thistype.nearest_range = 10000000000.
                set thistype.nearest_id = ItemIdStack[StackLevel]
                set thistype.nearest_item = null
                call EnumItemsInRect(r,Condition(function thistype.getNearestItem),null)
                call RemoveItem(thistype.nearest_item)
                set StackLevel = StackLevel - 1
            endloop
        endmethod
        
        private static method addDelay takes nothing returns boolean
            call ResumeTimer(thistype.t)
            //Zero callback, else created item can't be found.
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            local trigger trig
            
            set Gold = Table.create()
            set Lumber = Table.create()
            set r = GetWorldBounds()
            
            set Dummy = CreateUnit(Player(15),'nshe',0.,0.,0.)
            call SetUnitPathing(Dummy,false)
            call ShowUnit(Dummy,false)
            call UnitAddAbility(Dummy,'Asid')
            
            set trig = CreateTrigger()
            call TriggerRegisterUnitEvent(trig,Dummy,EVENT_UNIT_ISSUED_ORDER)
            call TriggerAddCondition(trig,Condition(function thistype.addDelay))
            //We have to removed the created item.
            
            set thistype.t = CreateTimer()
            call TimerStart(thistype.t,0.0,false,function thistype.removeItems)
        endmethod
    endstruct
    
endlibrary
 
Level 3
Joined
Mar 31, 2015
Messages
28
Whats wrong with this existing library? It exists a long time and work perfect...

I wanted to be able to detect item selling price, and all the existing libraries I could find detected buying price.

I do realize that it could be done just by multiplying it with Sell Item Return Rate factor (0.5), but I wanted to avoid that.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Jass lesson 1.0

Whats wrong with this existing library? It exists a long time and work perfect... Just take a few minutes on google... and there it is :) - Don't wastn your time with coding a system which already exists :)

Code:
I was not aware of kingking's library.
After reading the code I have to say it has couple of flaws and can potentially malfunction.

1.) The code will not work if called from a function initalized in a module.
---
This not essentially bad, if you don't use module initializers at all.

2.) The entire map world is enumerated ( You may realise the GetWorldBounds ).
Depending on you map concept that can be
1 up to 1000+ items, which means 1 to 1000+ threads must run.
---
Item pathing checks run up to 1024 units. If there is no valid point in that radius,
the item ignores pathing and is placed directly under the shop.
Therefore only a radius of 1024 + 64 = 1088 must be enumerated.

3.) The library kills the closest item of that item type id, not the item you bought.
Most times it is the same, but for sure not always.
---
Consider what I mentioned above. The pathing thing! If an item of equal type blocks
the pathing for the sold item, that other item will vanish. What is now on the map
is a perfect copy in GetItemTypeId(item), but not in GetHandleId(item) nor GetItemUserData(item).
Systems which reference these values will fail for that item from then on.

4.) Trigger condition + timer timeout + a stack.
---
Seriously not requried complexity and overhead.
Everything can run within one thread as I did it in ItemResource Cost.

5.) It doesn't reset the neutral player resource state.
---
Not a problem for most maps, for others have fun searching until you find the
issue in the library you imported as public resource.


I've abandoned idea of using hero dummy. Now I detect item type and return 0 if it's powerup. So dummy isn't hero unit anymore.
I know, it's just a limit of the code that should be pointed out to users in
the moderator review.

Why? I read from hashtable and return result. What more efficient way there is?
Check how much code is evaluated in my Item Resource Cost to get already
saved lumber and gold cost. You'll it's much shorter. Here you call other
function which evaluate other conditions. Basically you just have to re-arrange the code a bit.
Use Item Resource Cost as template.

Why and how to fix that? Could you explain that to me in little more detail?
This one is intersting. It relates to how the JassHelper is compiling code.

When you make a spell or a system you will end up using
library MyCode initializer Init.
initializer is a key word for the JassHelper that this function should
run on map init after the blizzard variables are initialized.

Now how can we influence what runs before other code.
Obviously you shop must be created before GetItemCost is called.

Four classic initializers are available:
1.) The GUI on map init. This one always runs very last.
2.) library MyCode initializer Init runs before the GUI initializer
3.)
JASS:
struct MyStruct extends array
    private static method onInit takes nothing returns nothing
    endmethod
endstruct
4.)
JASS:
private module Inits 
    private static method onInit takes nothing returns nothing
    endmethod
endmodule 
struct MyStruct extends array
    implement Inits
endstruct

Numer 4 runs first before all other initializers.
Therefore code inside that initializers can't use GetItemCost.

You can see Item Resource Cost, how to use a module initializer.
 
Level 3
Joined
Mar 31, 2015
Messages
28
Your system is inefficient on further gold or lumber lookups of the same item type id.
Rearranged the code a bit. I don't think I could make it any more efficient than this.

Items of type ITEM_TYPE_POWERUP can only be accessed by creating a hero type dummy unit.
Correct me if I'm wrong, but it should not be physically possible to determine selling price of power-up items (without knowing the associated Gameplay Constant).

On a related note, I added some fail-safe mechanism because I now use global dummies and they can be killed. So I gave them invulnerability and still check if they're dead whenever calculated cost is 0.

It could happen, right? Supposing someone casts "kill all units in AoE" spell or something.

What's the point of extends array part?

On a loosely related note, can that item selling sound me temporarily muted while dummy sells the item? I tried fiddling with VolumeGroupSetVolume native but couldn't get it to work. Could it be done? And by done I mean done properly, so none of that "replace sound file with empty file" stuff.
 
Last edited:
Level 19
Joined
Mar 18, 2012
Messages
1,716
First of all we have spamming rules. Please do not double post in our forums
in a short interval ~ 72h. Rather edit your previous post via "Edit" button on the right.

Correct me if I'm wrong, but it should not be physically possible to determine selling price of power-up items (without knowing the associated Gameplay Constant).
But the buying price.
It's ok, I approved the system with a note that this is not possible with this type of code.

On a related note, I added some fail-safe mechanism because I now use global dummies and they can be killed. So I gave them invulnerability and still check if they're dead whenever calculated cost is 0.
Give them locust aka 'Aloc' instead. Then you don't have to check if they are dead.

It could happen, right? Supposing someone casts "kill all units in AoE" spell or something.
For locust units not.

What's the point of extends array part?
Ha... I can't explain that one in 2 sentences.
Just copy it from my code.

For more info tutorial section
 
Level 3
Joined
Mar 31, 2015
Messages
28
Give them locust aka 'Aloc' instead. Then you don't have to check if they are dead.
But they could still be killed with triggers if you're really determined. For example by killing all units owned by neutral passive.

Is it probable scenario?

Or I should just go with locust, and if someone really does kill them, it's his fault?
 
Top