• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Another Question About Anachron's Inventory System

Status
Not open for further replies.
Level 4
Joined
Apr 19, 2013
Messages
86
Hey again, this inventory system is really awesome, I don't mind how difficult it is to implement, slow and steady wins the race.. muahahaha.

One thing I've always wondered though was if it's possible to modify the portait view that appears at the center of the inventory? Once you try the test map you'll see the example is a Paladin. It appears just to be the portrait of one, because whenever you pick up items that have special effects, the effects will only show on the real hero, the inventory portrait model still looks standard issue (no effects were applied). An easy way to test what I mean is to pick up the item "Shaman Claw" it will create an Inner Fire affect on the overhead of the paladin, but in the inventory view, the Paladin just looks the same as ever.

Is it possible to create a view that is inclusive of any/all effects on the hero the inventory is associated with? Maybe a camera?

Also I'm still struggling with how to create Item Sets, if anyone can throw me a bone for either of these things I'll be very grateful and make it rain rep.

Haha, thanks for reading!
 
Level 4
Joined
Apr 19, 2013
Messages
86
Yeah, good point. I did actually. But I noticed the dude hasn't posted in a while so I tried the forums. It's a pretty popular system right? I was hoping someone would know what I'm talking about.
 
Level 20
Joined
Apr 14, 2012
Messages
2,901
Yes, creating effects on the dummy is possible.

You can link the dummy and the real unit with a hashtable for example. Whenever an item is equipped/unequipped, you create/destroy a special effect.

Woah how exactly does one link the dummy unit with the real unit using hashtables (I would personally like to know... because I'm still learning Hashtables) ?
 
I don't have access to the script, but you can just save the dummy unit under the real unit's handle ID.

But to do that, you first have to find some way to reference the dummy unit. I assume Anachron privatized that, so the best way to do it (in GUI) is to group all units of the player (you have to use "group units of player" so that it will count locust units) and then filter them out with (Unit-Type of (Picked Unit)) Equal to <Dummy Hero>. iirc, Anachron made a custom unit to serve as the dummy model (in order to get the pitch/roll angle). So basically, just check for that and then store it under the real unit's ID.

It should work, I haven't tested it though.
 
Level 4
Joined
Apr 19, 2013
Messages
86
Yess,thank you guys for lending an ear. I'm off to a decent start now to figuring this out. I think I found at least part of the code of interest.

It is in Vjass, so I'm not sure how much I can do with the gui method mentioned above, but thanks all the same. I'm starting to get a feel for the concept behind it all.

Here it is for all to see.

JASS:
 private function init takes nothing returns nothing
        local unit fakeInv = null
        local unit hero = null
        local integer i = 0
        
        loop
            exitwhen i >= 12
        
            if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(i)) == MAP_CONTROL_USER then
                set fakeInv = CreateInventoryUnit(Player(i), 'h00P')
                set hero = CreateUnit(Player(i), 'U006', 5420., 2940., 0.)
                call CreateInventoryUI(hero, fakeInv)
            endif
        
            set i = i +1
        endloop
    endfunction
    
endscope

So if I want effects to be applied to the dummy unit, otherwise known as: InventoryUnit(Player(i),'h00P') in this example, I would have to create a hashtable to link it with the effects applied via the items. That much I understand, but I'm not sure how or where or which trigger to do that in.

Here is the item effect code (sorry for how lengthy, I don't want to omit anything important)

JASS:
struct CIItemEffects
        public effect array effects[4]
        public string array sfx[4]
        public string array attachments[4]
        public integer index = 0
        
        implement TableMacros
        public static method create takes integer id returns thistype
            local thistype this = thistype.allocate()
            
            set .ID = id
            call .save()
            
            return this
        endmethod
        
        public static method new takes item theItem returns thistype
            local thistype this = thistype.load(GetItemTypeId(theItem))
            local thistype that = thistype.allocate()
            local integer i = .index
            
            set that.index = .index
            loop
                exitwhen i == 0
                
                set that.sfx[i] = .sfx[i]
                set that.attachments[i] = .attachments[i]
                
                set i = i -1
            endloop
            
            return that
        endmethod
        
        public method activate takes unit theUnit returns nothing
            local integer i = .index
            
            loop
                exitwhen i == 0
                
                call DestroyEffect(.effects[i])
                if theUnit != null then
                    set .effects[i] = AddSpecialEffectTarget(.sfx[i], theUnit, .attachments[i])
                endif
                
                set i = i -1
            endloop
        endmethod
        
        public method addSFX takes string sfx, string pos returns nothing
            if .index < 3 then
                set .index = .index +1
                
                set .sfx[.index] = sfx
                set .attachments[.index] = pos
            endif
        endmethod
    endstruct
endlibrary

module CIItemEffect
    public CIItemEffects eff = 0
    public method addSfx takes string sfx, string pos returns nothing
        if .eff == 0 then
            set .eff = CIItemEffects.create(.ID)
        endif
        call .eff.addSFX(sfx, pos)
    endmethod
    
    public method addEffects takes unit theUnit returns nothing
        call .eff.activate(theUnit)
    endmethod
    
    public method removeEffects takes nothing returns nothing
        call .eff.activate(null)
    endmethod
endmodule

Could I just take a brute force type of solution and copy and paste the following:

set .effects = AddSpecialEffectTarget(.sfx, theUnit, .attachments)
endif

where I would change 'theunit' to 'inventoryunit'. ??

Can't wait to feel that triumphant moment when I figure it out haha.
 
Last edited:
Well, you can't really brute force it that way exactly.

First, if you do that then you lose the value of .effects (therefore the hero sfx will no longer be referenced to). You have to make a separate effect array.

Underneath public effect array effects[4] you would make something like:
JASS:
public effect array dummyEffects[4]

Then you would mimic the style of adding in the method "activate". The only problem is that you can't reference the dummy inventory unit. Preferably, you want to be able to reference it through the main unit. To do this, you can just use a hashtable.
JASS:
globals
    hashtable HeroHash = InitHashtable()
endglobals

    private function init takes nothing returns nothing
        local unit fakeInv = null
        local unit hero = null
        local integer i = 0
        
        loop
            exitwhen i >= 12
        
            if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(i)) == MAP_CONTROL_USER then
                set fakeInv = CreateInventoryUnit(Player(i), 'h00P')
                set hero = CreateUnit(Player(i), 'U006', 5420., 2940., 0.)
                call CreateInventoryUI(hero, fakeInv)
                call SaveUnit(HeroHash, GetHandleId(hero), 1337, fakeInv) // here it is
            endif
        
            set i = i +1
        endloop
    endfunction

An alternative method would be to use whatever function the system has that allows you to reference the dummy unit. Since I don't have access to the script right now, however, I will just stick to the hashtable.

Next, you would mimic the style of adding the effect in the method "activate":
JASS:
        public method activate takes unit theUnit returns nothing
            local integer i = .index
            
            loop
                exitwhen i == 0
                
                call DestroyEffect(.effects[i])
                if theUnit != null then
                    set .effects[i] = AddSpecialEffectTarget(.sfx[i], theUnit, .attachments[i])
                endif
                
                call DestroyEffect(.dummyEffects[i])
                if theUnit != null then
                    set .dummyEffects[i] = AddSpecialEffectTarget(.sfx[i], LoadUnit(HeroHash, GetHandleId(theUnit), 1337), .attachments[i]) // 
                endif

                set i = i -1
            endloop
        endmethod

Now the only issue to resolve is destroying the effect when the item is removed (unless the method calls .activate(null)). Try to find the snippet of code that has EVENT_PLAYER_UNIT_DROP_ITEM in it, and paste it here (and preferably whatever function it calls).

Note: Some of this might not be optimized to the fullest but these are just methods to allow you to get it to work.

There is also a GUI way of doing it that may be somewhat simpler, but if you want to try editing the code itself (it is always nice to experiment) then go for it.
 
Level 4
Joined
Apr 19, 2013
Messages
86
Ohh, I see. It almost worked. After adding the dummy effect array I went on to the activate part to add the hashtable. I think I got that much right. For the third step, maybe I did something wrong, but I tripple checked my work. Here is what my mimic initialize effect looks like:

JASS:
scope apply

 public method activate takes unit theUnit returns nothing
            local integer i = .index
            
            loop
                exitwhen i == 0
                
                call DestroyEffect(.effects[i])
                if theUnit != null then
                    set .effects[i] = AddSpecialEffectTarget(.sfx[i], theUnit, .attachments[i])
                endif
                
                call DestroyEffect(.dummyEffects[i])
                if theUnit != null then
                    set .dummyEffects[i] = AddSpecialEffectTarget(.sfx[i], LoadUnit(HeroHash, GetHandleId(theUnit), 1337), .attachments[i]) // 
                endif

                set i = i -1
            endloop
        endmethod

It keeps giving me: Expected: "type", "struct", "interface", "function", "function", "keyword" or "scope" -- referencing this line: public method activate takes unit theUnit returns nothing

Have you ever had this problem? What is your method reffering to 'theunit' as? Was that supposed to be the dummy unit? That one is InventoryUnit in the other triggers.

I'm not sure what its deal is haha, but here is the other code (I think)


JASS:
 public method drop takes CustomItem ci returns nothing
            local unit eventUnit = .inventory.getOwner()
            
            call ci.remBoni(eventUnit)
            call ci.unLock()
            call ci.unEquip()
            call ci.removeEffects()
            
            set eventUnit = null
        endmethod

Thanks!!
 
Last edited:
Why does it say "scope apply" at the top?

I meant for you to just change the function directly, rather than putting it in a separate scope. :) Also, for future reference, all of the blocks (scopes, globals, functions, etc.) should be accompanied with an end keyword (such as endscope, endglobals, endfunction, etc.)

Also, "theUnit" is the hero unit. From that, we can get the inventory unit.

As for the second part, try looking for the method "removeEffects" (go through the CustomInventory triggers and do Ctrl+F to search for "removeEffects")
 
Level 4
Joined
Apr 19, 2013
Messages
86
Ok awesome!! I think I'm like seconds away, but it keeps giving me:

Undeclared function SaveUnit and Undeclared function LoadUnit, citing those lines.

I know like usually that happens when you try to call a private function where you aren't supposed to. But like, we're just calling a hashtable right? Does that mean it doesn't recognize the hashtable we made? Do I have to declare it earlier or something?
 
Last edited:
Level 4
Joined
Apr 19, 2013
Messages
86
If it's any help here are the current versions

(Effects Trigger)

JASS:
library CIItemEffect

    struct CIItemEffects
        public effect array effects[4]
        public effect array dummyEffects[4]
        public string array sfx[4]
        public string array attachments[4]
        public integer index = 0
        
        implement TableMacros
        public static method create takes integer id returns thistype
            local thistype this = thistype.allocate()
            
            set .ID = id
            call .save()
            
            return this
        endmethod
        
        public static method new takes item theItem returns thistype
            local thistype this = thistype.load(GetItemTypeId(theItem))
            local thistype that = thistype.allocate()
            local integer i = .index
            
            set that.index = .index
            loop
                exitwhen i == 0
                
                set that.sfx[i] = .sfx[i]
                set that.attachments[i] = .attachments[i]
                
                set i = i -1
            endloop
            
            return that
        endmethod
        
        public method activate takes unit theUnit returns nothing
            local integer i = .index
            
            loop
                exitwhen i == 0
                
                call DestroyEffect(.effects[i])
                if theUnit != null then
                    set .effects[i] = AddSpecialEffectTarget(.sfx[i], theUnit, .attachments[i])
                endif
                
                 call DestroyEffect(.dummyEffects[i])
                if theUnit != null then
                    set .dummyEffects[i] = AddSpecialEffectTarget(.sfx[i], LoadUnit(HeroHash, GetHandleId(theUnit), 1337), .attachments[i])
                endif
                
                set i = i -1
            endloop
        endmethod
        
        public method addSFX takes string sfx, string pos returns nothing
            if .index < 3 then
                set .index = .index +1
                
                set .sfx[.index] = sfx
                set .attachments[.index] = pos
            endif
        endmethod
    endstruct
endlibrary

module CIItemEffect
    public CIItemEffects eff = 0
    public method addSfx takes string sfx, string pos returns nothing
        if .eff == 0 then
            set .eff = CIItemEffects.create(.ID)
        endif
        call .eff.addSFX(sfx, pos)
    endmethod
    
    public method addEffects takes unit theUnit returns nothing
        call .eff.activate(theUnit)
    endmethod
    
    public method removeEffects takes nothing returns nothing
        call .eff.activate(null)
    endmethod
endmodule

and this is the test trigger

JASS:
scope test initializer init
globals
    hashtable HeroHash = InitHashtable()
endglobals

    private function init takes nothing returns nothing
        local unit fakeInv = null
        local unit hero = null
        local integer i = 0
        
        loop
            exitwhen i >= 12
        
            if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(i)) == MAP_CONTROL_USER then
                set fakeInv = CreateInventoryUnit(Player(i), 'h00P')
                set hero = CreateUnit(Player(i), 'U006', 5400., 3000., 270.)
                call CreateInventoryUI(hero, fakeInv)
                call SaveUnit(HeroHash, GetHandleId(hero), 1337, fakeInv)
            endif
        
            set i = i +1
        endloop
    endfunction
    
endscope

I would be so lost otherwise man, so thank you, I'm giving as much rep as I can!!
 
Level 20
Joined
Apr 14, 2012
Messages
2,901
If it's any help here are the current versions

(Effects Trigger)

JASS:
library CIItemEffect

    struct CIItemEffects
        public effect array effects[4]
        public effect array dummyEffects[4]
        public string array sfx[4]
        public string array attachments[4]
        public integer index = 0
        
        implement TableMacros
        public static method create takes integer id returns thistype
            local thistype this = thistype.allocate()
            
            set .ID = id
            call .save()
            
            return this
        endmethod
        
        public static method new takes item theItem returns thistype
            local thistype this = thistype.load(GetItemTypeId(theItem))
            local thistype that = thistype.allocate()
            local integer i = .index
            
            set that.index = .index
            loop
                exitwhen i == 0
                
                set that.sfx[i] = .sfx[i]
                set that.attachments[i] = .attachments[i]
                
                set i = i -1
            endloop
            
            return that
        endmethod
        
        public method activate takes unit theUnit returns nothing
            local integer i = .index
            
            loop
                exitwhen i == 0
                
                call DestroyEffect(.effects[i])
                if theUnit != null then
                    set .effects[i] = AddSpecialEffectTarget(.sfx[i], theUnit, .attachments[i])
                endif
                
                 call DestroyEffect(.dummyEffects[i])
                if theUnit != null then
                    set .dummyEffects[i] = AddSpecialEffectTarget(.sfx[i], LoadUnit(HeroHash, GetHandleId(theUnit), 1337), .attachments[i])
                endif
                
                set i = i -1
            endloop
        endmethod
        
        public method addSFX takes string sfx, string pos returns nothing
            if .index < 3 then
                set .index = .index +1
                
                set .sfx[.index] = sfx
                set .attachments[.index] = pos
            endif
        endmethod
    endstruct
endlibrary

module CIItemEffect
    public CIItemEffects eff = 0
    public method addSfx takes string sfx, string pos returns nothing
        if .eff == 0 then
            set .eff = CIItemEffects.create(.ID)
        endif
        call .eff.addSFX(sfx, pos)
    endmethod
    
    public method addEffects takes unit theUnit returns nothing
        call .eff.activate(theUnit)
    endmethod
    
    public method removeEffects takes nothing returns nothing
        call .eff.activate(null)
    endmethod
endmodule

and this is the test trigger

JASS:
scope test initializer init
globals
    hashtable HeroHash = InitHashtable()
endglobals

    private function init takes nothing returns nothing
        local unit fakeInv = null
        local unit hero = null
        local integer i = 0
        
        loop
            exitwhen i >= 12
        
            if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(i)) == MAP_CONTROL_USER then
                set fakeInv = CreateInventoryUnit(Player(i), 'h00P')
                set hero = CreateUnit(Player(i), 'U006', 5400., 3000., 270.)
                call CreateInventoryUI(hero, fakeInv)
                call SaveUnit(HeroHash, GetHandleId(hero), 1337, fakeInv)
            endif
        
            set i = i +1
        endloop
    endfunction
    
endscope

I would be so lost otherwise man, so thank you, I'm giving as much rep as I can!!

Please avoid double posting. Either you edit your last post or you wait 48 hours :thumbs_up:
 
Level 4
Joined
Apr 19, 2013
Messages
86
Oh woe is me, it's been three days and I can't figure out why the vjass keeps throwin this- Error: Undeclared Function SaveUnit.

Any fresh ideas? I wonder what it means..... i looked up what that error usually refers to, and its like calling a private function publically.

But I thought I implemented the hashtable as directed. Any pointers?
 
Status
Not open for further replies.
Top