Snippet GetItemCost

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
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

Relative Link : Table

I think you won't need demo map for this simple thing, as the implementation step is just CnP and you can start using it already.

Changelog :
v1.0.0 - Initial Release
 
Why use Table? Using a regular old hashtable is just as fine, and you don't add a requirement.
 
Table is already a hashtable, and why create OTHER hashtable if you can use one already created?
 
Because I might not use Table anywhere else, and I don't want to add an unnecessary system to my map when I could just get this one snippet.
 
I want to make the data storage of the map as consolidate as possible.
 
Because I might not use Table anywhere else, and I don't want to add an unnecessary system to my map when I could just get this one snippet.

I'd rather not add yet another one just for a small snippet. :p
 
Fair argument. Why not make it optional, then, if JASSHelper gives us the ability to do so?
 
king's item removal is flawed. It works, but it like does it in a crappy way as compared to how it's been done in the past.

There have been 3 item cost snippets before this one and 2 that have worked, and the 2 that worked did a much better job of item removal than king's.

Already mentioned this in msn, but it looks like he's going to ignore me ^_^.
 
Sigh, this is still terribly done for removing bought items.

Look at the ItemCost portion to see how to do this better w/o a timer.
http://www.hiveworkshop.com/forums/submissions-414/system-costs-getunitcost-getitemcost-196894/


Note that the script I linked to does the same thing with less overhead >.>.


Also keep in mind that this can easily overflow-
[ljass]GetWidgetX(i) * GetWidgetX(i) + GetWidgetY(i) * GetWidgetY(i)[/ljass]


So not only does this script have more overhead, but it will bug up on larger maps.


In fact, this value here already overflows-
10000000000
2147483647 is max.


And ofc I shouldn't have to point out that if a module initializer used this lib, it would fail.
 
[ljass]GetWidgetX(i) * GetWidgetX(i) + GetWidgetY(i) * GetWidgetY(i)[/ljass]

So not only does this script have more overhead, but it will bug up on larger maps.

In fact, this value here already overflows-
10000000000
2147483647 is max.
You're kidding, right?

2147483647 is the maximum value for integers in WC3, not for reals (and in case you didn't know, the ones you're talking about are reals). Reals can go much higher than that.

Sure, I agree that your script is better (hey, this one is even graveyarded), but please, do not spread such rubbish.
 
2147483647 is the maximum value for integers in WC3, not for reals (and in case you didn't know, the ones you're talking about are reals). Reals can go much higher than that.

Uh no, that is 100% wrong... Reals in wc3 are not longs... reals are floats and are 32 bit just like integers, and as such they have the same maximum. However, keep in mind that a float of that size will not be 2147483647 as it loses accuracy.


Now I do get that in regular programming, like c++ or c#, floats aren't used very often. Most people use longs so that they can keep the accuracy. However, don't let this confuse you into thinking that longs are the same things as floats.


To keep from posting blatantly wrong information, you should learn the basic types used in computing, like integers, floats, strings, characters, booleans, and etc.


I also recommend learning about structures like stacks, queues, dequeues, and linked lists in general. You could also go a bit further and get into computation geometry, learning about such structures as the Kd-Tree and the Range Tree.
 
No, Nestharus, you should learn the basic types, because you're the one who's posting blatantly wrong information.

Or you can go and test it and see that those don't (and never will) overflow. The maximum value for floats (single-precision floating point) is ~3.4028234 * 10^38, while the minimum is ~-3.4028234 * 10^38 (the reals in WC3 might be a bit different due to unknown reasons, but shouldn't differ much). The precision is screwed up even at lower values.

You obviously do not know the difference between a float and an integer. And possibly between a float and a long as well.
 
Dude, you need to test it yourself..

I dare you to plug 2147483649 into R2S and tell me that it doesn't go negative.

edit
And the max is 3.40282346638528860e+38 and the min is 1.40129846432481707e-45 for regular floats just to let you know.


However, in wc3, reals can only go up to 2^31-1 before they overflow (go into negatives).


If you don't believe me, test it yourself.

And yes, BBQ thinks reals are regular floats as well, but he's wrong too...

output of that number I just told you: -2147483520.000
JASS:

struct tester extends array
    private static method onInit takes nothing returns nothing
        call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,R2S(2147483649.00))
        call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"2147483649.00")
    endmethod
endstruct


There's your proof.

edit
Just did another test and apparently wc3 does weird things.. first it converts the value into an integer before it converts it into a float, so that's why the thing was overflowing.

This will not overflow and follows regular float stuff-
JASS:

struct tester extends array
    private static method onInit takes nothing returns nothing
        local real r=2147483520
        call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,R2S(r+1000.))
        call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"2147484520.000")
    endmethod
endstruct



So yea, the reason I always thought it overflowed was because I wasn't thinking that the number might be interpreted as an integer before it was interpreted as a float ; P.


But then that also means that I was right about king's value overflowing...
[ljass]10000000000[/ljass]

will in fact overflow because it will first be interpreted as an integer before it is interpreted as a float.



However, this should not overflow-
[ljass]GetWidgetX(i) * GetWidgetX(i) + GetWidgetY(i) * GetWidgetY(i)[/ljass]

Although it won't be terribly accurate either =P.



So we were both wrong on some counts and both right on other counts.


Case closed =).
 
min is 1.40129846432481707e-45 for regular floats just to let you know..
No, that is the minimum positive value for floats. The minimum value is, like I said, ~-3.4028234 * 10^38 (-3.4028234 * 10^38 is much lower than 1.40129846432481707 * 10^-45).

Note: I'm talking (actually, we both are) about floats here, not WC3 reals, because, apparently, they are indeed screwed up.
 
Oh, I'm talking about wc3 reals : P, which are like weird floats =).


So, you can't work with a straight value that goes outside of integer range. However, once you get the value into the real, it is fine (like a float).

For example-
[ljass]local real r=(2147483647.0+1)*2[/ljass]

That will work just fine, but this will not
[ljass]local real r=4294967296.0[/ljass]
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Hopefully this won't cause problems.
  • Ghan Ghan:
    Hmm
  • Ghan Ghan:
    I have converted the Headline News forum to an Article type forum. It will now show the top 20 threads with more detail of each thread.
  • Ghan Ghan:
    See how we like that.
  • The Helper The Helper:
    I do not see a way to go past the 1st page of posts on the forum though
  • The Helper The Helper:
    It is OK though for the main page to open up on the forum in the view it was before. As long as the portal has its own URL so it can be viewed that way I do want to try it as a regular forum view for a while
  • Ghan Ghan:
    Yeah I'm not sure what the deal is with the pagination.
  • Ghan Ghan:
    It SHOULD be there so I think it might just be an artifact of having an older style.
  • Ghan Ghan:
    I switched it to a "Standard" article forum. This will show the thread list like normal, but the threads themselves will have the first post set up above the rest of the "comments"
  • The Helper The Helper:
    I don't really get that article forum but I think it is because I have never really seen it used on a multi post thread
  • Ghan Ghan:
    RpNation makes more use of it right now as an example: https://www.rpnation.com/news/
  • The Helper The Helper:
  • The Helper The Helper:
    What do you think Tom?
  • tom_mai78101 tom_mai78101:
    I will have to get used to this.
  • tom_mai78101 tom_mai78101:
    The latest news feed looks good
  • The Helper The Helper:
    I would like to see it again like Ghan had it the first time with pagination though - without the pagination that view will not work but with pagination it just might...
  • The Helper The Helper:
    This drink recipe I have had more than a few times back in the day! Mind Eraser https://www.thehelper.net/threads/cocktail-mind-eraser.194720/
  • The Helper The Helper:
    Happy Thursday!
  • Ghan Ghan:
    I'm not so sure, there's still a lot of Thursday left for it to become unhappy.
    +3
  • The Helper The Helper:
    still a few hours
  • The Helper The Helper:
    Its Friday!!!!
    +1
  • Ghan Ghan:
    Thursday 7/10 would Thursday again
    +3
  • The Helper The Helper:
    New forum coming soon going to be for my friend Saylor who is blind and he is doing motivational speaking and has an internet radio show and podcast. I am going to put a forum to promote him and other inspirational speaker stuff going to have some good stuff in it.

      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