• 🏆 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!

Resources That Have Yet To Be Coded

Status
Not open for further replies.

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
The problem with item systems in general is, that you'll never find a "one size fits all" solution.
As Nesth already mentioned: your item system will always be dependant on your combat mechanics or systems. There is no possible way to make all that modular and optional in any realistically usable API. There's just way too many variables to consider.

I think it's okay to have FSI frameworks that ultimately only deal with the displaying of the visual elements and provide the functionality of moving and switching items, but the rest imho should be up to the mapper - simply because you have to hardcode certain elements or you end up making more problems than you actually fix with it.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
@BPower
"Lots of object data required, long setup time."
Sorry BPower, you are talking about a full screen inventory system... it takes long.
However, was there a snippet to get the icon of a unit or item as path?
That would reduce the OE data by 1 destructable per item.

Also, except for tooltips or other information display (which is different for every map)
BonusType is a no-go because it is simply too large
ItemType can be done pretty easily... just requires 2 global variables and a few constants

ItemSubType uhm... I quite added that to ItemType, hence 2 global variables :D

CustomItem, isnt this supposed to be a different system as well?

translate,
Yea, kind of necessary if I understood you.
Have a function that gets item index (which leads to all data of that item from arrays) and returns a (few) strings.

@Nestharus
"onEquip
onUnequip
onPickup
onDrop
onDamaged
onPeriodic
onHover
onRender"

onPickup, onDrop, onHover, ok
onEquip, onUnequip... discussable. an inventory is not necessarily equipment as well.
onDamaged... you mean when the item is damaged? otherwise, hell no, different system.
onPeriodic... ?
onRender... uhm....

onClick no?
also,
"onInteract"
I select item a then click on item b
If item a and item b are the same items and are stackable (potions, etc) then combine stacks.
If item a is a socket and item b is a socketable, then add a to b.
What if slot b is empty? Move a to slot b? What if a is a sword and b is helmet slot?
etc, etc, etc
however this is different for each map so we only leave onInteract as event and do nothing more.

I would say that full Combat System uses GenericItemInventory, equal as all other stuff like DDS, SpellSystem, etc, etc, etc.

However... to start at first... do we have a system that easily creates a full screen window?
If not, that one should come first.

On the other hand... as mentioned by Nes, this will indeed not cover the inventory completely.
Except for the info display, onInteract actions, data sets and maybe more, there is always one thing that is pretty impossible to do without going map specific...

How will it look like?
What I want is not what you want, we all know that.
I would like to have my items in the lower left side of the screen, at the right side, I want the description and data and in the upper left, I want to see my unit.
We can indeed make a few implementations of this system but making that is quite hard (not compared to the system itself but from the perspective of people who want to use this system).
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
@BPower
"Lots of object data required, long setup time."
Sorry BPower, you are talking about a full screen inventory system... it takes long.
However, was there a snippet to get the icon of a unit or item as path?
That would reduce the OE data by 1 destructable per item.

Also, except for tooltips or other information display (which is different for every map)
BonusType is a no-go because it is simply too large
ItemType can be done pretty easily... just requires 2 global variables and a few constants

ItemSubType uhm... I quite added that to ItemType, hence 2 global variables :D

CustomItem, isnt this supposed to be a different system as well?

translate,
Yea, kind of necessary if I understood you.
Have a function that gets item index (which leads to all data of that item from arrays) and returns a (few) strings.

I give you a quick example and you understand me at a glance:

Situation:
You have a full screen equipment system. You design your first item i.e a sword.
The only attribute it has in + strenght.

FSE nowadays:
Existing systems allow you to give your item a name: Iron Sword and a
distinct attribute bonus + 5 strenght.
First item done. The strenght stat is static and will always be + 5 ingame.

What I expect from a better desgined FSE system:
Name: Iron Sword
Strenght: 3 - 15 ( depends on what is rolled )

Conclusion:
One FSE item setup does no longer represent 1 item.
Due to random rolls in range, it can represent x items dependant
on the number of attributes and roll range.
This allows you to have i.e after 10 item setups, 250 different items ingame ( numbers are just random to make an example )
 
Level 11
Joined
Dec 3, 2011
Messages
366
I give you a quick example and you understand me at a glance:

Situation:
You have a full screen equipment system. You design your first item i.e a sword.
The only attribute it has in + strenght.

FSE nowadays:
Existing systems allow you to give your item a name: Iron Sword and a
distinct attribute bonus + 5 strenght.
First item done. The strenght stat is static and will always be + 5 ingame.

What I expect from a better desgined FSE system:
Name: Iron Sword
Strenght: 3 - 15 ( depends on what is rolled )

Conclusion:
One FSE item setup does no longer represent 1 item.
Due to random rolls in range, it can represent x items dependant
on the number of attributes and roll range.
This allows you to have i.e after 10 item setups, 250 different items ingame ( numbers are just random to make an example )

I agree with BPower.

Item random generate like Diablo or other RPG games.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
What I expect from a better desgined FSE system:
Name: Iron Sword
Strenght: 3 - 15 ( depends on what is rolled )

Wrong system.

We support you (as map maker) with the event onEquip and onUnequip.
You can use your own Item Bonus System to instead of giving the stats on item acquire, on the onEquip.
The actual data of an item does NOT matter for the inventory.
We do not want to know and we will never know either.
The only moment when that data comes to the FSE (or FSI Full Screen Inventory) is when we display the data... and we only give you as map maker a function that will take an item as parameter and returns a string which is the information.
We dont care what the attributes are, we dont even want to care.

Have you desided which system you want?
 
Level 7
Joined
Oct 11, 2008
Messages
304
I agreed completely with your point Wietlol, we lack a FSI (Inventory, because we only need the INVENTORY).

Stats, and effect of an item should be a module a part, it's not party of INVENTORY, it's part of ITEM.

Someone needs to do what people did (or are doing, I'm lost in this part lol) with Buff.
Buff is just the icon, the effect, and what buff do, is a module, part of the system but not something already on the system.


But to me (since I'm from Starcraft now) it's not that easy to do a Inventory System. Why? Because each mapper want a specific type of inventory.

One want a inventory like MMORPG, with parts like Gloves, Feet, Right-Hand, etc.
Another want just a simple inventory like one already on Warcraft 3, but with full control of it.
Other want an inventory with 10 slots, but don't want a 'stash'.
And other want a 6 slot inventory (like Warcraft 3 one) but with a 'stash'.

This is the more difficult part, the layout, you can't expect to pleases everyone, it's impossible.

The only method that I saw that MAY be good for most of guys, is something like this:

Inventory System
- Inventory
--- Enable/Disable
--- Change number of slots
--- OnEquip/OnDequip X slot event
--- Slot Class (Disabled by default, also this could be a module, just use if you want MMO style)

Now you ask, where's stash for MMO's Style? Just create ANOTHER instance of Inventory (so we now have 2 inventory) for 1 unit.
(Why OnEquip/OnDequip event for a Stash? I suggested before (before I post it) to don't implement this, but I remembered now about Diablo II, they have Charm Item, that apply effect on 'Stash')

To me this is totally possible, people are able to do this (hello Missile, Index, Buff, Event, Table makers?).

People did more complex things on Warcraft already, but they're misslanding where a Full Screen Inventory System should stand, more like a lack of design.

But about the layout, well, this is the hardest part imo, a dynamic (dynamic because change based on the mapper) layout for a FSI and I have no idea how this is supposed to be. Maybe set the frame x/y of inventories in some position? I don't know lol
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Now that I think of it... it is indeed not even necessary to have anything with a full screen on it.
The inventory system is just the data part.

I think that I even made one :D it is a bit too map specific though.

EDIT:
Data only is very little code.
Full Screen Inventory is the hard part.
 
Last edited:

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
Fullscreen inventories should not actually be part of the inventory system, as strange as it sounds.

Rather, any fullscreen system should just provide the visual representation of the data input.

So basicly, a structure could look like this:


Fullscreen:
- provides all the structs and methods for drawing interface elements
- provides all the events of user interaction; clicking, mouseover, etc
- provides different kinds of sub objects: checkboxes, text windows, icons, borders, etc

Inventory:
- pure "virtual" inventory that can be fed with pure "virtual" items
- basicly only a data structure that provides events and crucial parameters
- works with "item" objects (see below)

Loot & Loottable:
- allows "looting" of virtual items from corpses, shops, etc.
- obviously, uses the Fullscreen library
OR: uses floating clickable models similar to DGUI directly on top of the corpse to not obstruct the whole view of the player ... kind of like a ring-menu with item icons popping up when clicking on a corpse
- takes "item" objects
- provides a weighted droptable complete with per-unit or per-unit-type registries

Item:
- "virtual" item that provides data structure for registration, effects, onDamage, onAttack and any gameplay related events
- can be "loaded" with a list of effects (stats, abilities, properties, etc.)
- allows enumerating through effects on a per-item basis
- can actually "hold" and relate to an object editor item for those people that use a mixture of "real" items and "virtual" items; but this is purely optional
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Very quick look:
JASS:
library cuiSystem //Custom Unit Inventory
    
    globals
        
        integer         udg_CUI_EQUIPMENT_SLOTS                     = 24
            //doesnt need to be exact as long as there are not more slots than this number
        
        integer         udg_CUI_INVENTORY_SLOTS                     = 64
            //maximum slots of inventory
        
        real            udg_CUI_HIDDEN_LOCATION_X                   = 100.
        real            udg_CUI_HIDDEN_LOCATION_Y                   = 100.
            //a location where no unit can come and preferable where no player will look
            
        hashtable       udg_CUI_HASHTABLE                           = InitHashtable()
            //the hashtable that is used, could maybe be used by table
        
    endglobals
    
    
    function CUI_RemoveItem takes unit whichUnit, item whichItem returns nothing
        local integer unitId = GetHandleId(whichUnit)
        local integer itemId = GetHandleId(whichItem)
        
        call RemoveSavedInteger(udg_CUI_HASHTABLE, unitId, LoadInteger(udg_CUI_HASHTABLE, itemId, 1))
        call RemoveSavedInteger(udg_CUI_HASHTABLE, itemId, 0)
        call RemoveSavedInteger(udg_CUI_HASHTABLE, itemId, 1)
        
        call SetItemPosition(whichItem, GetUnitX(whichUnit), GetUnitY(whichUnit))
    endfunction
    
    function CUI_AddItem takes unit whichUnit, item whichItem returns boolean
        local integer i = 0
        local integer unitId = GetHandleId(whichUnit)
        local integer itemId = GetHandleId(whichItem)
        
        loop
            exitwhen i >= udg_CUI_INVENTORY_SLOTS
            
            if LoadInteger(udg_CUI_HASHTABLE, unitId, i+udg_CUI_EQUIPMENT_SLOTS) == 0 then
                call SaveInteger(udg_CUI_HASHTABLE, unitId, i+udg_CUI_EQUIPMENT_SLOTS, itemId)
                call SaveInteger(udg_CUI_HASHTABLE, itemId, 0, unitId)
                call SaveInteger(udg_CUI_HASHTABLE, itemId, 1, i+udg_CUI_EQUIPMENT_SLOTS)
                return true
            endif
            
            set i = i +1
        endloop
        
        return false
    endfunction
    
endlibrary

function AddItem takes nothing returns boolean
    local unit u = GetTriggerUnit()
    local item i = GetManipulatedItem()
    
    if CUI_AddItem(u, i) then
        call UnitRemoveItem(u, i)
        call SetItemPosition(i, udg_CUI_HIDDEN_LOCATION_X, udg_CUI_HIDDEN_LOCATION_Y)
    endif
    
    set u = null
    set i = null
    return false
endfunction

//===========================================================================
function InitTrig_CUI_System takes nothing returns nothing
    local trigger t
    
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM)
    call TriggerAddCondition(t, Filter(function AddItem))
endfunction

What happens is when you pick up or buy or whatever an item, it is moved into your inventory (data array using hashtable)
the actual item is then moved to a location on the map where no unit can ever come and preferably where no player can ever look.
when you remove the item from the inventory it gets placed at the feet of that unit.

MUI, MPI everything.

I think it is a good thing to start with something like this for the actual data storage.
For map specifics, you create the equipment slots.
I have put a limit to 24 slots (using global variable) and have 64 slots of normal inventory.
slots simply refer to an item handle on which data can be stored using an item indexer (which also has to be made I assume)

(remember that I only wrote this in just a little time and didnt test it nor even saved it for syntax check)
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
This is a very naive approach.

First, it actually uses the WC3 implementation of items, which imho is a no-go, as we want to move away from object data, not embrace it.
Second, moving the items somewhere else is impractical, as it can potentially mess with other systems. Rather, the items should be either completely removed or hidden.
Third, struct syntax please.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
In this approach, removing the item is strictly forbidden
however, i do understand why you want to move away from item and use a custom object instead
in that case we can remove the item but id still recommend hiding them
About placing items in a hidden location is how i did it in the system i made before didnt knew about hiding items

About structs... that is something that you can do... i cant
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Hmm.. I wrote a FSI not long ago, and find it easy to make but not trivial. Things like displaying item data (as a plugin) etc. are really time consuming and so boring to do. I have finished basic operations like item swapping/moving, multiple pages handling, item equipping, dropping, adding, removing, stacking, displaying to inventory, etc. And they are all done elegantly using functions, so user can manipulate whatever inside the inventory very easily. But again, when the time to add plugin systems came, I just stopped the development.

Maybe I will look into it once again after posting this.

Gz, I forgot that the system still uses Sharpcraft, that means I need to remove it first.

@BPower:
Can you unlock this thread please.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Anyone here who wrote a circular linked list as module and want to upload it in the jass submission section? Could prove to be useful.

I have a huge collection thing I've been working on that uses all of the latest techniques and practices. If you like, I can send you some of the files so that you can piece together a circular list ; ). I'm supporting a lot of different flavors. It amounts to maybe 200 different collections in total.

Head allocation support (both array/table)
Element allocation support (both array/table)
Accept already allocated head (both array/table)
Accept already allocated node (both array/table)

Every combination of the above for doubly linked lists, queues, stacks, and circular doubly linked lists.

All resources in debug mode will optionally track memory and display standard error messages. All resources undergo rigorous testing to ensure absolutely no bugs.
 
Fullscreen inventories should not actually be part of the inventory system, as strange as it sounds.

This.

The important part of designing full-screen systems in general is to first create all the functions handling the displays, and then work on the full-screen inventory or the talent tree system as a separate entity. So if someone were to release a new FSI, they should first release their full-screen handler as a separate submission for feedback. :)
 
Level 5
Joined
Dec 1, 2008
Messages
120
I actually had such a system written, sadly lost it when I reinstalled Windows. But I don't think it would take me a long time to rewrite it. It was basically a GUI, with elements such as panels, buttons, checkboxes, radiobuttons and sliders. I'm not up to writing an inventory system using it though.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
I have one... a full screen window creator... but I wont say it is pretty good.
It works... mpi... etc, but it replaces a lot of destructables in high frequency when opened.
I didnt notice lagg... when testing for one player, but with 11 players having it opened, the 12th can probably forget playing.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Can u public that :ogre_hurrhurr:
I can.

Trackables say hello. :p old times...
Idd :D

Dont say it fails... I already know it does :D
I made this like 4 months ago.
I didnt even knew what structs meant back then :D

JASS:
globals
    integer         udg_FSW_Index                       = -1
    
    integer array   udg_FSW_Array_LocationX
    integer array   udg_FSW_Array_LocationY
    integer array   udg_FSW_Array_LocationCenterX
    integer array   udg_FSW_Array_LocationCenterY
    integer array   udg_FSW_Array_SizeX
    integer array   udg_FSW_Array_SizeY
    unit array      udg_FSW_Array_DummyUnit
    integer array   udg_FSW_Array_TerrainType
    real array      udg_FSW_Array_CameraDistance
    
    integer         udg_FSW_ObjectType_Destructable     = 1
    integer         udg_FSW_ObjectType_Texttag          = 2
    integer         udg_FSW_ObjectType_Unit             = 3
    
    trigger array   udg_FSW_Trigger_WhileOpen
    integer         udg_FSW_Black_Terrain               = 'Oaby'
    trigger         udg_FSW_Trigger_TrackableClick      = CreateTrigger()
    trigger         udg_FSW_Trigger_TrackableHover      = CreateTrigger()
    string          udg_FSW_Trackable_Model             = "AutoImport\\Models\\Custom Window\\Trackable.mdx"
    hashtable       udg_FSW_Hashtable                   = InitHashtable()
endglobals

library fswSystem
    function FSW_System_SaveStandardDestructable takes integer whichFSW, destructable d returns nothing
        local integer i = 20
        
        loop
            exitwhen LoadInteger(udg_FSW_Hashtable, whichFSW, i) == 0
            set i = i + 2
        endloop
        
        call SaveInteger(udg_FSW_Hashtable, whichFSW, i, udg_FSW_ObjectType_Destructable)
        call SaveDestructableHandle(udg_FSW_Hashtable, whichFSW, i+1, d)
    endfunction

    function FSW_System_SaveStandardTexttag takes integer whichFSW, texttag t returns nothing
        local integer i = 20
        
        loop
            exitwhen LoadInteger(udg_FSW_Hashtable, whichFSW, i) == 0
            set i = i + 2
        endloop
        
        call SaveInteger(udg_FSW_Hashtable, whichFSW, i, udg_FSW_ObjectType_Texttag)
        call SaveTextTagHandle(udg_FSW_Hashtable, whichFSW, i+1, t)
    endfunction

    function FSW_System_SaveStandardUnit takes integer whichFSW, unit u returns nothing
        local integer i = 20
        
        loop
            exitwhen LoadInteger(udg_FSW_Hashtable, whichFSW, i) == 0
            set i = i + 2
        endloop
        
        call SaveInteger(udg_FSW_Hashtable, whichFSW, i, udg_FSW_ObjectType_Unit)
        call SaveUnitHandle(udg_FSW_Hashtable, whichFSW, i+1, u)
    endfunction

    function FSW_System_ShowStandardObjects takes integer whichFSW, boolean show returns nothing
        local integer i = 20
        local integer objectType
        
        loop
            set objectType = LoadInteger(udg_FSW_Hashtable, whichFSW, i)
            exitwhen objectType == 0
            if objectType == udg_FSW_ObjectType_Destructable then
                call ShowDestructable(LoadDestructableHandle(udg_FSW_Hashtable, whichFSW, i+1), show)
            elseif objectType == udg_FSW_ObjectType_Texttag then
                call SetTextTagVisibility(LoadTextTagHandle(udg_FSW_Hashtable, whichFSW, i+1), show)
            elseif objectType == udg_FSW_ObjectType_Unit then
                call ShowUnit(LoadUnitHandle(udg_FSW_Hashtable, whichFSW, i+1), show)
            endif
            set i = i + 2
        endloop
    endfunction

    function FSW_System_SaveTempDestructable takes integer whichFSW, integer pId, destructable d returns nothing
        local integer i = 2000
        
        loop
            exitwhen i > 3000
            if LoadInteger(udg_FSW_Hashtable, whichFSW, i) == 0 then
                call SaveInteger(udg_FSW_Hashtable, whichFSW, i, udg_FSW_ObjectType_Destructable)
                call SaveDestructableHandle(udg_FSW_Hashtable, whichFSW, i+1, d)
                call SaveInteger(udg_FSW_Hashtable, whichFSW, i+2, pId)
                return
            endif
            set i = i + 3
        endloop
    endfunction

    function FSW_System_SaveTempTexttag takes integer whichFSW, integer pId, texttag t returns nothing
        local integer i = 2000
        
        loop
            exitwhen i > 3000
            if LoadInteger(udg_FSW_Hashtable, whichFSW, i) == 0 then
                call SaveInteger(udg_FSW_Hashtable, whichFSW, i, udg_FSW_ObjectType_Texttag)
                call SaveTextTagHandle(udg_FSW_Hashtable, whichFSW, i+1, t)
                call SaveInteger(udg_FSW_Hashtable, whichFSW, i+2, pId)
                return
            endif
            set i = i + 3
        endloop
    endfunction

    function FSW_Remove_Temp_Objects takes integer whichFSW, integer pId returns nothing
        local integer i = 2000
        local integer objectType
        
        loop
            exitwhen i > 3000
            if LoadInteger(udg_FSW_Hashtable, whichFSW, i+2) == pId then
                set objectType = LoadInteger(udg_FSW_Hashtable, whichFSW, i)
                if objectType == udg_FSW_ObjectType_Destructable then
                    call RemoveDestructable(LoadDestructableHandle(udg_FSW_Hashtable, whichFSW, i+1))
                    call SaveInteger(udg_FSW_Hashtable, whichFSW, i, 0)
                elseif objectType == udg_FSW_ObjectType_Texttag then
                    call DestroyTextTag(LoadTextTagHandle(udg_FSW_Hashtable, whichFSW, i+1))
                    call SaveInteger(udg_FSW_Hashtable, whichFSW, i, 0)
                elseif objectType == udg_FSW_ObjectType_Unit then
                    call RemoveUnit(LoadUnitHandle(udg_FSW_Hashtable, whichFSW, i+1))
                    call SaveInteger(udg_FSW_Hashtable, whichFSW, i, 0)
                endif
            endif
            set i = i + 3
        endloop
    endfunction



    function FSW_System_Create_FSW takes integer x, integer y, integer sizeX, integer sizeY, real cameraDistance returns integer
        set udg_FSW_Index = udg_FSW_Index + 1
        set udg_FSW_Array_LocationX[udg_FSW_Index] = x
        set udg_FSW_Array_LocationY[udg_FSW_Index] = y
        set udg_FSW_Array_LocationCenterX[udg_FSW_Index] = x*64 + sizeX*32
        set udg_FSW_Array_LocationCenterY[udg_FSW_Index] = y*64 - sizeY*32
        set udg_FSW_Array_SizeX[udg_FSW_Index] = sizeX
        set udg_FSW_Array_SizeY[udg_FSW_Index] = sizeY
        set udg_FSW_Array_DummyUnit[udg_FSW_Index] = CreateUnit(Player(12), udg_Dummy_Unit_Type, udg_FSW_Array_LocationCenterX[udg_FSW_Index], udg_FSW_Array_LocationCenterY[udg_FSW_Index], 0)
        set udg_FSW_Array_TerrainType[udg_FSW_Index] = GetTerrainType(udg_FSW_Array_LocationCenterX[udg_FSW_Index], udg_FSW_Array_LocationCenterY[udg_FSW_Index])
        set udg_FSW_Array_CameraDistance[udg_FSW_Index] = cameraDistance
        
        return udg_FSW_Index
    endfunction

    function FSW_System_Create_Trackable takes integer whichFSW, integer x, integer y returns trackable
        local integer fswX = udg_FSW_Array_LocationX[whichFSW]
        local integer fswY = udg_FSW_Array_LocationY[whichFSW]
        local trackable t
        local integer id
        local integer i = 0
        local player p
        local string s
        
        loop
            exitwhen i > 12
            set p = Player(i)
            if GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(p) == MAP_CONTROL_USER then
                if GetLocalPlayer() == p then
                    set s = udg_FSW_Trackable_Model
                else
                    set s = ""
                endif
                set t = CreateTrackable(s, (fswX+x) * 64, (fswY-y) * 64, 0)
                set id = GetHandleId(t)
                
                //Register the events for the trackable.
                call TriggerRegisterTrackableHitEvent(udg_FSW_Trigger_TrackableClick, t)
                call TriggerRegisterTrackableTrackEvent(udg_FSW_Trigger_TrackableHover, t)
                
                //Save the data to the hashtable.
                call SaveInteger(udg_FSW_Hashtable, id, 0, i)
                call SaveInteger(udg_FSW_Hashtable, id, 1, fswX + x)
                call SaveInteger(udg_FSW_Hashtable, id, 2, fswY + y)
            endif
            set i = i + 1
        endloop
        return t
    endfunction

    function FSW_System_Create_Destructable takes integer whichFSW, integer destId, integer x, integer y returns destructable
        local real fswX = udg_FSW_Array_LocationX[whichFSW]
        local real fswY = udg_FSW_Array_LocationY[whichFSW]
        local destructable d = CreateDestructable(destId, (fswX+x) * 64, (fswY-y) * 64, 0, 0.7, 0)
        //local destructable d = CreateDeadDestructableZ(destId, (fswX+x) * 64, (fswY-y) * 64, 250, 0, 0.7, 0)
        
        call FSW_System_SaveStandardDestructable(whichFSW, d)
        
        call ShowDestructable(d, false)
        
        return d
    endfunction

    function FSW_System_Create_Texttag takes integer whichFSW, string text, real size, real x, real y, integer RGBA_R, integer RGBA_G, integer RGBA_B, integer RGBA_A returns texttag
        local real fswX = udg_FSW_Array_LocationX[whichFSW]
        local real fswY = udg_FSW_Array_LocationY[whichFSW]
        local texttag t = CreateTextTag()
        call SetTextTagText(t, text, size * 0.0023)
        call SetTextTagPos(t, fswX*64 + x, fswY*64 - y, 0)
        call SetTextTagColor(t, RGBA_R, RGBA_G, RGBA_B, RGBA_A)
        call SetTextTagPermanent(t, true)
        
        call FSW_System_SaveStandardTexttag(whichFSW, t)
        
        call SetTextTagVisibility(t, false)
        
        return t
    endfunction

    function FSW_System_Create_Unit takes integer whichFSW, integer unitType, real x, real y, player whichPlayer, real facing returns unit
        local real fswX = udg_FSW_Array_LocationX[whichFSW]
        local real fswY = udg_FSW_Array_LocationY[whichFSW]
        local unit u = CreateUnit(whichPlayer, unitType, fswX*64 + x, fswY*64 - y, facing)
        
        call FSW_System_SaveStandardUnit(whichFSW, u)
        
        call ShowUnit(u, false)
        
        return u
    endfunction

    function FSW_System_Create_Temp_Destructable takes integer whichFSW, player whichPlayer, integer destId, integer x, integer y returns destructable
        local real fswX = udg_FSW_Array_LocationX[whichFSW]
        local real fswY = udg_FSW_Array_LocationY[whichFSW]
        local destructable d = CreateDestructable(destId, (fswX+x) * 64, (fswY-y) * 64, 0, 0.7, 0)
        local timer Timer
        //local destructable d = CreateDeadDestructableZ(destId, (fswX+x) * 64, (fswY-y) * 64, 5, 0, 0.7, 0)
        
        call FSW_System_SaveTempDestructable(whichFSW, GetPlayerId(whichPlayer), d)
        
        if GetLocalPlayer() == whichPlayer then
            call ShowDestructable(d, true)
        else
            call ShowDestructable(d, false)
        endif
        
        return d
    endfunction

    function FSW_System_Create_Temp_Texttag takes integer whichFSW, player whichPlayer, string text, real size, real x, real y, integer RGBA_R, integer RGBA_G, integer RGBA_B, integer RGBA_A returns texttag
        local real fswX = udg_FSW_Array_LocationX[whichFSW]
        local real fswY = udg_FSW_Array_LocationY[whichFSW]
        local texttag t = CreateTextTag()
        call SetTextTagText(t, text, size * 0.0023)
        call SetTextTagPos(t, fswX*64 + x, fswY*64 - y, 0)
        call SetTextTagColor(t, RGBA_R, RGBA_G, RGBA_B, RGBA_A)
        call SetTextTagPermanent(t, true)
        
        call FSW_System_SaveTempTexttag(whichFSW, GetPlayerId(whichPlayer), t)
        
        if GetLocalPlayer() == whichPlayer then
            call SetTextTagVisibility(t, true)
        else
            call SetTextTagVisibility(t, false)
        endif
        
        return t
    endfunction


    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //  
    //  Handle Functions
    //  
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    function FSW_System_Close_FSW takes integer whichFSW, player whichPlayer returns nothing
        local integer pId = GetPlayerId(whichPlayer)
        
        if (GetLocalPlayer() == whichPlayer) then
            call ResetToGameCamera(0)
            call PanCameraToTimed(GetUnitX(udg_Heroes[pId]), GetUnitY(udg_Heroes[pId]), 0)
        endif
        
        call SetTerrainType(udg_FSW_Array_LocationCenterX[udg_FSW_Index], udg_FSW_Array_LocationCenterY[udg_FSW_Index], udg_FSW_Array_TerrainType[udg_FSW_Index], -1, 8, 1)
        
        call FSW_System_ShowStandardObjects(whichFSW, false)
        call FSW_Remove_Temp_Objects(whichFSW, pId)
        
        call SaveBoolean(udg_FSW_Hashtable, whichFSW, pId, false)
        
        set udg_FSW_Selected_X[pId] = -1
        set udg_FSW_Selected_Y[pId] = -1
        
        set udg_FSW_Event_Window_Closed = 1
        set udg_FSW_Event_Window_Closed = 0
    endfunction

    function FSW_System_Open_FSW takes integer whichFSW, player whichPlayer returns nothing
        local integer pId = GetPlayerId(whichPlayer)
        local integer i = 0
        
        if LoadBoolean(udg_FSW_Hashtable, whichFSW, pId) then
            return
        endif
        
        loop
            exitwhen i > udg_FSW_Index
            if LoadBoolean(udg_FSW_Hashtable, i, pId) then
                call FSW_System_Close_FSW(i, whichPlayer)
                exitwhen true
            endif
            set i = i + 1
        endloop
        
        if (GetLocalPlayer() == whichPlayer) then
            call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, -90, 0)
            call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, udg_FSW_Array_CameraDistance[whichFSW], 0)
            call SetCameraTargetController(udg_FSW_Array_DummyUnit[whichFSW], 0, 0, false)
            
            call SetTerrainType(udg_FSW_Array_LocationCenterX[whichFSW], udg_FSW_Array_LocationCenterY[whichFSW], udg_FSW_Black_Terrain, -1, 8, 1)
            
            call FSW_System_ShowStandardObjects(whichFSW, true)
            
            call SaveBoolean(udg_FSW_Hashtable, whichFSW, pId, true)
            
            set udg_FSW_Selected_X[pId] = -1
            set udg_FSW_Selected_Y[pId] = -1
            
            set udg_FSW_Param_Player = whichPlayer
            set udg_FSW_Param_FSW = whichFSW
            call TriggerExecute(udg_FSW_Trigger_WhileOpen[whichFSW])
            
            set udg_FSW_Event_Window_Opened = 1
            set udg_FSW_Event_Window_Opened = 0
        endif
    endfunction


    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //  
    //  Create Trackable Events
    //  
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //Trackable click event.
    function FSW_System_Trackable_Clicked takes nothing returns boolean
        local integer id = GetHandleId(GetTriggeringTrackable())
        local integer whichFSW
        local integer pId = LoadInteger(udg_FSW_Hashtable, id, 0)
        local integer i = 0
        
        loop
            if i > udg_FSW_Index then
                return false
            endif
            
            if LoadBoolean(udg_FSW_Hashtable, i, pId) then
                set whichFSW = i
                exitwhen true
            endif
            set i = i + 1
        endloop
        
        set udg_FSW_Param_LocationX = -udg_FSW_Array_LocationX[whichFSW] + LoadInteger(udg_FSW_Hashtable, id, 1)
        set udg_FSW_Param_LocationY = -udg_FSW_Array_LocationY[whichFSW] + LoadInteger(udg_FSW_Hashtable, id, 2)
        set udg_FSW_Param_FSW = whichFSW
        set udg_FSW_Param_Player = Player(pId)
        
        if LoadBoolean(udg_FSW_Hashtable, whichFSW, pId) then
            set udg_FSW_Event_Trackable_Clicked = 1
            set udg_FSW_Event_Trackable_Clicked = 0
        endif
        
        return false
    endfunction

    //Trackable hover event.
    function FSW_System_Trackable_Hovered takes nothing returns boolean
        local integer id = GetHandleId(GetTriggeringTrackable())
        local integer whichFSW
        local integer pId = LoadInteger(udg_FSW_Hashtable, id, 0)
        local integer i = 0
        
        loop
            if i > udg_FSW_Index then
                return false
            endif
            
            if LoadBoolean(udg_FSW_Hashtable, i, pId) then
                set whichFSW = i
                exitwhen true
            endif
            set i = i + 1
        endloop
        
        set udg_FSW_Param_LocationX = -udg_FSW_Array_LocationX[whichFSW] + LoadInteger(udg_FSW_Hashtable, id, 1)
        set udg_FSW_Param_LocationY = -udg_FSW_Array_LocationY[whichFSW] + LoadInteger(udg_FSW_Hashtable, id, 2)
        set udg_FSW_Param_FSW = whichFSW
        set udg_FSW_Param_Player = Player(pId)
        
        if LoadBoolean(udg_FSW_Hashtable, whichFSW, pId) then
            set udg_FSW_Event_Trackable_Hovered = 1
            set udg_FSW_Event_Trackable_Hovered = 0
        endif
        
        return false
    endfunction

    function FSW_System_While_Open takes nothing returns boolean
        local integer pId = 0
        local player p
        local integer i = 0
        
        loop
            exitwhen pId > 3
            set p = Player(pId)
            
            loop
                exitwhen i > udg_FSW_Index
                if LoadBoolean(udg_FSW_Hashtable, i, pId) then
                    call FSW_Remove_Temp_Objects(i, pId)
                    set udg_FSW_Param_Player = p
                    set udg_FSW_Param_FSW = i
                    call TriggerEvaluate(udg_FSW_Trigger_WhileOpen[i])
                    exitwhen true
                endif
                set i = i + 1
            endloop
            
            set pId = pId + 1
        endloop
        
        return false
    endfunction
endlibrary

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  
//  Initialize variables and the system.
//  
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function InitTrig_FSW_System takes nothing returns nothing
    call TimerStart(CreateTimer(), 0.05, true, function FSW_System_While_Open)
    call TriggerAddCondition(udg_FSW_Trigger_TrackableClick, Filter(function FSW_System_Trackable_Clicked))
    call TriggerAddCondition(udg_FSW_Trigger_TrackableHover, Filter(function FSW_System_Trackable_Hovered))
endfunction

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  
//  End of the FSW System trigger.
//  
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

I have read it myself again and there are some things to point out first:
  • "AutoImport\\Models\\Custom Window\\Trackable.mdx"
    dont mind, that is just the regular trackable placed in a map where I use my local files.
  • functions SaveStandardUnit/Texttag/Destructable is basically to create something that is always visible... like borders, icons, etc.
  • functions SaveTempUnit/Texttag/Destructable are... you know, everything else.
  • Create creates a new one on x,y using size for terrain modification and cameradistance for the camera.
    Dummyunit is used to center the camera.
    I mean, serously, I didnt knew what camerabounds were :D
  • After you created it, you can create a trackable using x,y as relative point to the x,y of the given FullScreenWindow.
    Every trackable gains both events and can be used for every single window that uses that place as something.
  • Close and Open are easy right?
    You can never have opened two at once.
  • WhileOpen is kind of the fourth thing that is really bad :D
    It never stops running (even though that is not so performance heavy) but it also just recreates massive amounts of destructables, units and texttags.
    Every temp object is created inside the triggers of whileOpen.

I will do it over using some better methods, because it is even worse than I thought :D
 
Level 7
Joined
Oct 11, 2008
Messages
304
JASS:
globals
    integer udg_FSW_Index = -1
endglobals
library fswSystem
    function FSW_System_SaveStandardDestructable

This is pretty cute :p

I don't remember right now how trackables are handled by Warcraft III, but at least, we now have a base for the 'dream' (reads Full Screen Inventory). :D
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Inventory is indeed the second stage: implementation of a proper FSW System.

Trackables (used properly) are models placed on the ground.
These models dont have any animation, cannot move or whatsoever.
Each trackable can have two events on it: onClick and onHover.

Using 12 trackables with each different models (none or normal) for each player can make you be able to use those MPI. (regulary, there is no other way to know who clicked on it)

I place those trackables on a 64x64 grid (because of destructables which are easiest for making icons use a 32x32 grid which looks ugly so we use 64x64).
We can use 32x32 but that doesnt matter.

That is a bit how they work and what they do.
 
Level 7
Joined
Oct 11, 2008
Messages
304
What they do I remember :p but thanks for the explanation. :3

I'll still take a look here because I need to think about a shop for my map, and maybe people got some idea while doing a version for warcraft (you can said I wanna steal a concept, but I just need some inspiration :\ )

Also, a little question about trackables, GetTriggerPlayer() doesn't work for onClick/Hover events? :|
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
GetTriggerPlayer() does indeed not work.

So we create 12 trackables.
However, you cannot create a trackable inside GetLocalPlayer().
So the only thing that we do change is the model file ;)
11 players have an invisible (unclickable) trackable and one player has 1 clickable trackable.

That is the only way that I know.

EDIT:
What kind of objects are used when using a full screen window?
Destructable, Unit, Texttag.
Any more?

EDIT2:
This is how far I got it reworked:
Only objects cannot be created yet :D
JASS:
library basicFunctions initializer Init
    
    function LockCameraAtCoordinate takes real x, real y returns nothing
        call SetCameraBounds(x, y, x, y, x, y, x, y)
    endfunction
    
    globals
        player udg_LOCAL_PLAYER
    endglobals
    function Init takes nothing returns nothing
        set udg_LOCAL_PLAYER = GetLocalPlayer()
    endfunction
    
endlibrary

library fswSystem uses basicFunctions
    
    globals
        
        //Object Data
        integer         udg_FSW_Index                       = 0
        integer array   udg_FSW_Location_X
        integer array   udg_FSW_Location_Y
        real array      udg_FSW_Camera_X
        real array      udg_FSW_Camera_Y
        real array      udg_FSW_CameraDistance
        integer array   udg_FSW_Size
        integer array   udg_FSW_TerrainType
        unit array      udg_FSW_DummyUnit
        
        real array      udg_FSW_PlayerCamera_X
        real array      udg_FSW_PlayerCamera_Y
        integer array   udg_FSW_OpenedWindow
        
        //Constants
        integer         udg_FSW_TERRAIN_BLACK               = 'Oaby'
        trigger         udg_FSW_TRIGGER_TRACKABLE_CLICK     = CreateTrigger()
        trigger         udg_FSW_TRIGGER_TRACKABLE_HOVER     = CreateTrigger()
        string          udg_FSW_TRACKABLE_MODEL             = "FSW\\Trackable.mdx"
        hashtable       udg_FSW_HASHTABLE                   = InitHashtable()
        integer         udg_FSW_GRID                        = 64
        player          udg_FSW_PLAYER_NEUTRAL              = Player(0)     //Player(12)
        integer         udg_FSW_DUMMY_UNIT                  = 'hfoo'        //<dummy-unit>
        timer           udg_FSW_TIMER                       = CreateTimer()
        real            udg_FSW_INTERVAL                    = 0.05
        //integer         udg_FSW_STANDARD_OBJECTS_LIMIT      = 10000
        
        //Events
        real            udg_FSW_Event_Trackable_Clicked     = 0
        real            udg_FSW_Event_Trackable_Hovered     = 0
        real            udg_FSW_Event_Window_Opened         = 0
        real            udg_FSW_Event_Window_Closed         = 0
        integer         udg_FSW_EventResponse_LocX
        integer         udg_FSW_EventResponse_LocY
        integer         udg_FSW_EventResponse_Window
        player          udg_FSW_EventResponse_Player
        
    endglobals
    
    function FSW_CloseWindow takes integer windowIndex, player whichPlayer returns nothing
        local real centerX = udg_FSW_Location_X[windowIndex]*udg_FSW_GRID + udg_FSW_Camera_X[windowIndex]
        local real centerY = udg_FSW_Location_Y[windowIndex]*udg_FSW_GRID + udg_FSW_Camera_Y[windowIndex]
        local integer pId = GetPlayerId(whichPlayer)
        
        if udg_LOCAL_PLAYER == whichPlayer then
            call ResetToGameCamera(0)
            call PanCameraToTimed(udg_FSW_PlayerCamera_X[pId], udg_FSW_PlayerCamera_Y[pId], 0)
            call SetTerrainType(centerX, centerY, udg_FSW_TerrainType[windowIndex], -1, udg_FSW_Size[windowIndex], 1)
        endif
        
        //call FSW_System_ShowStandardObjects(whichFSW, false)
        //call FSW_Remove_Temp_Objects(whichFSW, pId)
        
        call SaveBoolean(udg_FSW_HASHTABLE, windowIndex, pId, false)
        set udg_FSW_OpenedWindow[pId] = 0
        
        set udg_FSW_Event_Window_Closed = 1
        set udg_FSW_Event_Window_Closed = 0
    endfunction
    
    function FSW_OpenWindow takes integer windowIndex, player whichPlayer returns nothing
        local real centerX = udg_FSW_Location_X[windowIndex]*udg_FSW_GRID + udg_FSW_Camera_X[windowIndex]
        local real centerY = udg_FSW_Location_Y[windowIndex]*udg_FSW_GRID + udg_FSW_Camera_Y[windowIndex]
        local integer pId = GetPlayerId(whichPlayer)
        
        if udg_FSW_OpenedWindow[pId] > 0 then
            call FSW_CloseWindow(udg_FSW_OpenedWindow[pId], whichPlayer)
        endif
        
        if udg_LOCAL_PLAYER == whichPlayer then
            
            set udg_FSW_PlayerCamera_X[pId] = GetCameraTargetPositionX()
            set udg_FSW_PlayerCamera_Y[pId] = GetCameraTargetPositionY()
            
            call SetCameraTargetController(udg_FSW_DummyUnit[windowIndex], 0, 0, false)
            call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, -90, 0)
            call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, udg_FSW_CameraDistance[windowIndex], 0)
            call SetTerrainType(centerX, centerY, udg_FSW_TERRAIN_BLACK, 0, udg_FSW_Size[windowIndex], 1)
            
            call SaveBoolean(udg_FSW_HASHTABLE, windowIndex, pId, true)
            set udg_FSW_OpenedWindow[pId] = windowIndex
            
            //call FSW_System_ShowStandardObjects(whichFSW, true)
            
            set udg_FSW_EventResponse_Window = windowIndex
            set udg_FSW_EventResponse_Player = whichPlayer
            
            set udg_FSW_Event_Window_Opened = 1
            set udg_FSW_Event_Window_Opened = 0
            
            //call TriggerExecute(udg_FSW_Trigger_WhileOpen[whichFSW])
        endif
    endfunction
    
    function FSW_CreateWindow takes integer x, integer y, real cameraX, real cameraY, real cameraDistance returns integer
        set udg_FSW_Index = udg_FSW_Index +1
        
        set udg_FSW_Location_X[udg_FSW_Index] = x
        set udg_FSW_Location_Y[udg_FSW_Index] = y
        set udg_FSW_Camera_X[udg_FSW_Index] = cameraX
        set udg_FSW_Camera_X[udg_FSW_Index] = cameraY
        set udg_FSW_CameraDistance[udg_FSW_Index] = cameraDistance
        set udg_FSW_Size[udg_FSW_Index] = 9
        set udg_FSW_TerrainType[udg_FSW_Index] = GetTerrainType(x*udg_FSW_GRID + cameraX, y*udg_FSW_GRID + cameraY)
        set udg_FSW_DummyUnit[udg_FSW_Index] = CreateUnit(udg_FSW_PLAYER_NEUTRAL, udg_FSW_DUMMY_UNIT, cameraX, cameraY, 0)
        
        return udg_FSW_Index
    endfunction
    
    function FSW_CreateTrackable takes integer windowIndex, integer x, integer y returns nothing
        local integer fswX = udg_FSW_Location_X[windowIndex]+x
        local integer fswY = udg_FSW_Location_Y[windowIndex]-y
        local real locX = fswX * udg_FSW_GRID
        local real locY = fswY * udg_FSW_GRID
        local trackable t
        local integer id
        local integer i = 0
        local player p
        local string s
        
        loop
            exitwhen i > 12
            set p = Player(i)
            if GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(p) == MAP_CONTROL_USER then
                if udg_LOCAL_PLAYER == p then
                    set s = udg_FSW_TRACKABLE_MODEL
                else
                    set s = ""
                endif
                set t = CreateTrackable(s, locX, locY, 0)
                set id = GetHandleId(t)
                
                //Register the events for the trackable.
                call TriggerRegisterTrackableHitEvent(udg_FSW_TRIGGER_TRACKABLE_CLICK, t)
                call TriggerRegisterTrackableTrackEvent(udg_FSW_TRIGGER_TRACKABLE_HOVER, t)
                
                //Save the data to the hashtable.
                call SaveInteger(udg_FSW_HASHTABLE, id, 0, i)
                call SaveInteger(udg_FSW_HASHTABLE, id, 1, fswX)
                call SaveInteger(udg_FSW_HASHTABLE, id, 2, fswY)
            endif
            set i = i + 1
        endloop
        
        set t = null
        set p = null
    endfunction
    
    function FSW_TrackableClick takes nothing returns boolean
        local integer id = GetHandleId(GetTriggeringTrackable())
        local integer windowIndex
        local integer pId = LoadInteger(udg_FSW_HASHTABLE, id, 0)
        local integer i = 0
        
        loop
            if i > udg_FSW_Index then
                return false
            endif
            
            if LoadBoolean(udg_FSW_HASHTABLE, i, pId) then
                set windowIndex = i
                exitwhen true
            endif
            set i = i + 1
        endloop
        
        set udg_FSW_EventResponse_LocX = -udg_FSW_Location_X[windowIndex] + LoadInteger(udg_FSW_HASHTABLE, id, 1)
        set udg_FSW_EventResponse_LocY = -udg_FSW_Location_Y[windowIndex] + LoadInteger(udg_FSW_HASHTABLE, id, 2)
        set udg_FSW_EventResponse_Window = windowIndex
        set udg_FSW_EventResponse_Player = Player(pId)
        
        set udg_FSW_Event_Trackable_Clicked = 1
        set udg_FSW_Event_Trackable_Clicked = 0
        
        return false
    endfunction
    
    function FSW_TrackableHover takes nothing returns boolean
        local integer id = GetHandleId(GetTriggeringTrackable())
        local integer windowIndex
        local integer pId = LoadInteger(udg_FSW_HASHTABLE, id, 0)
        local integer i = 0
        
        loop
            if i > udg_FSW_Index then
                return false
            endif
            
            if LoadBoolean(udg_FSW_HASHTABLE, i, pId) then
                set windowIndex = i
                exitwhen true
            endif
            set i = i + 1
        endloop
        
        set udg_FSW_EventResponse_LocX = -udg_FSW_Location_X[windowIndex] + LoadInteger(udg_FSW_HASHTABLE, id, 1)
        set udg_FSW_EventResponse_LocY = -udg_FSW_Location_Y[windowIndex] + LoadInteger(udg_FSW_HASHTABLE, id, 2)
        set udg_FSW_EventResponse_Window = windowIndex
        set udg_FSW_EventResponse_Player = Player(pId)
        
        set udg_FSW_Event_Trackable_Hovered = 1
        set udg_FSW_Event_Trackable_Hovered = 0
        
        return false
    endfunction
    
    function FSW_Interval takes nothing returns nothing
        local integer pId = 0
        
        loop
            exitwhen pId > 12
            if udg_FSW_OpenedWindow[pId] > 0 then
                call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, -90, 0)
                call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, udg_FSW_CameraDistance[udg_FSW_OpenedWindow[pId]], 0)
                
                
                
            endif
            set pId = pId +1
        endloop
    endfunction
    
endlibrary

function InitTrig_FSW_System takes nothing returns nothing
    call TimerStart(udg_FSW_TIMER, udg_FSW_INTERVAL, true, function FSW_Interval)
    call TriggerAddCondition(udg_FSW_TRIGGER_TRACKABLE_CLICK, Filter(function FSW_TrackableClick))
    call TriggerAddCondition(udg_FSW_TRIGGER_TRACKABLE_HOVER, Filter(function FSW_TrackableHover))
endfunction
 
Last edited:
Level 24
Joined
Aug 1, 2013
Messages
4,657
Anyone here who wrote a circular linked list as module and want to upload it in the jass submission section? Could prove to be useful.

I dont really know why but I made this today...
Dont know if it works because this is the first time I use a textmacro actually but if this works exactly as intended, then this creates a dynamic linked list.

Neither do I have used a linked list enough to know what a "circular" linked list is, but this is as far as I can go atm.
JASS:
globals
    integer LL_LoopIndex = 0
    //integer LL_LoopId = 0
endglobals

//! textmacro CREATE_LINKED_LIST takes NAME
library LL$NAME$
    globals
        
        integer             LL_$NAME$_NewIndex = 0
        boolean array       LL_$NAME$_IsOccupied
        
        integer array       LL_$NAME$_FirstIndex
        integer array       LL_$NAME$_LastIndex
        
        integer array       LL_$NAME$_PreviousIndex
        integer array       LL_$NAME$_NextIndex
        
    endglobals
    
    //System function
    function $NAME$_NewIndex takes nothing returns integer
        loop
            set LL_$NAME$_NewIndex = LL_$NAME$_NewIndex +1
            if LL_$NAME$_NewIndex >= 8191 then
                set LL_$NAME$_NewIndex = 1
            endif
            exitwhen not LL_$NAME$_IsOccupied[LL_$NAME$_NewIndex]
        endloop
        set LL_$NAME$_IsOccupied[LL_$NAME$_NewIndex] = true
        return LL_$NAME$_NewIndex
    endfunction
    
    //User function
    function $NAME$_CreateIndex takes integer id returns integer
        local integer newIndex = $NAME$_NewIndex()
        set LL_$NAME$_NextIndex[LL_$NAME$_LastIndex[id]] = newIndex
        set LL_$NAME$_PreviousIndex[newIndex] = LL_$NAME$_LastIndex[id]
        set LL_$NAME$_LastIndex[id] = newIndex
        return newIndex
    endfunction
    
    //User function
    function $NAME$_GetIndex takes integer id, integer index returns integer
        local integer i = 0
        local integer result = LL_$NAME$_FirstIndex[id]
        loop
            exitwhen i >= index
            set result = LL_$NAME$_NextIndex[result]
            if result == 0 then
                return -1
            endif
            set i = i +1
        endloop
        return result
    endfunction
    
    //User function
    function $NAME$_RemoveIndex takes integer id, integer index returns nothing
        local integer i = 0
        local integer remove = LL_$NAME$_FirstIndex[id]
        
        loop
            exitwhen i >= index
            set remove = LL_$NAME$_NextIndex[remove]
            set i = i +1
        endloop
        
        set LL_$NAME$_PreviousIndex[LL_$NAME$_NextIndex[remove]] = LL_$NAME$_PreviousIndex[remove]
        set LL_$NAME$_NextIndex[LL_$NAME$_PreviousIndex[remove]] = LL_$NAME$_NextIndex[remove]
        set LL_$NAME$_IsOccupied[remove] = false
        
        if remove == LL_$NAME$_LastIndex[id] then
            set LL_$NAME$_LastIndex[id] = LL_$NAME$_PreviousIndex[remove]
        endif
        if remove == LL_$NAME$_FirstIndex[id] then
            set LL_$NAME$_FirstIndex[id] = LL_$NAME$_NextIndex[remove]
        endif
        
        //if LL_LoopId == id and LL_LoopIndex == remove then
            //set LL_LoopIndex = 
        //endif
    endfunction
    
    //User function
    function $NAME$_Loop takes integer id, trigger callback returns nothing
        set LL_LoopIndex = LL_$NAME$_FirstIndex[id]
        //set LL_LoopId = id
        loop
            exitwhen LL_LoopIndex == 0
            call TriggerEvaluate(callback)
            set LL_LoopIndex = LL_$NAME$_NextIndex[LL_LoopIndex]
        endloop
    endfunction
endlibrary
//! endtextmacro

How to use it:
Create a linked list object:
//! runtextmacro CREATE_LINKED_LIST("MyLL")

Then you must decide what kind of ids you want to use.
For example, you can use the id of a unit via a unit indexer.
Then you can Create new indexes on that unit which link to each other.
This should be used once for each system for example.
And just dont try to make more than 8190 indexes.
The loop function is just something that I will need.
Seems to be fine (not so hard to make either).
 
Last edited:
Level 23
Joined
Apr 16, 2012
Messages
4,041
I'm not a huge fan of this documentation, but I can easily glance over it, thus it is infinitely better than muzzel's, lol.

Do I have to say anything to this, other than you are ridiculous?

Muzzel's system may be nice, but extending structs + stub methods mean a pile of trigger evaluations, which really slow down the thing quite a bit(arguably, it is not that much of a problem, since you only fire these once every setInterval times)
 
Level 11
Joined
Dec 3, 2011
Messages
366
Do I have to say anything to this, other than you are ridiculous?

Muzzel's system may be nice, but extending structs + stub methods mean a pile of trigger evaluations, which really slow down the thing quite a bit(arguably, it is not that much of a problem, since you only fire these once every setInterval times)

He mention muzzel's documentations ...
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Level 24
Joined
Aug 1, 2013
Messages
4,657
Ok new resource:
I assume we all know how you can make a unit completely unselectable right?
(Using locust + morph)

Here is the deal.
How can I make a unit only selectable by certain players?
(Using locust + morph in combination with GetLocaLPlayer())

I think it is very usefull if we can manage it.
 

Ardenian

A

Ardenian

Hm, but for Get Closest Tile Type, doesn't mine ( spell section) or IcemanBo's TileDefinition do the job ?
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Huh? Yours doesn't do the same thing at all? I don't see what you're getting at. Perhaps you don't understand what Get Closest Tile Type is supposed to do?

Using either a quad tree or an octal tree, find the closest point with a given type to a point.

It should be called Get Closest Tile By Type

With that, you could have a bonus that only works while you are within 1024 of water.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Polygon is nice... (I blame Nestharus for forcing me to make id :D)

JASS:
library Polygon2D uses BasicFunctions
    //! runtextmacro CREATE_UNIQUE_ID("Polygon2D")
    //! runtextmacro CREATE_LINKED_LIST("Polygon2D", "false", "8191")
    globals
        real array BF_XVERTICES
        real array BF_YVERTICES
        integer BF_HITS
        real BF_LAST_X
        real BF_LAST_Y
        real BF_LEFT_X
        real BF_TEST_X
        real BF_TEST_Y
    endglobals
    function IPIP_Iteration takes integer vertices, real px, real py, integer i returns nothing
        if BF_YVERTICES[i] == BF_LAST_Y then
            return  
        endif
        
        if BF_XVERTICES[i] < BF_LAST_X then
            if px >= BF_LAST_X then
                return
            endif
            set BF_LEFT_X = BF_XVERTICES[i]
        else
            if px >= BF_XVERTICES[i] then
                return
            endif
            set BF_LEFT_X = BF_LAST_X
        endif
        
        if BF_YVERTICES[i] < BF_LAST_Y then
            if py < BF_YVERTICES[i] or py >= BF_LAST_Y then
                return
            endif
            if (px < BF_LEFT_X) then
                set BF_HITS = BF_HITS +1
                return
            endif
            set BF_TEST_X = px - BF_XVERTICES[i]
            set BF_TEST_Y = py - BF_YVERTICES[i]
        else
            if py < BF_LAST_Y or py >= BF_YVERTICES[i] then
                return
            endif
            if px < BF_LEFT_X then
                set BF_HITS = BF_HITS +1
                return
            endif
            set BF_TEST_X = px - BF_LAST_X
            set BF_TEST_Y = py - BF_LAST_Y
        endif
        
        if BF_TEST_X < (BF_TEST_Y / (BF_LAST_Y - BF_YVERTICES[i]) * (BF_LAST_X - BF_XVERTICES[i])) then
            set BF_HITS = BF_HITS +1
        endif
    endfunction
    function IsPointInPolygon takes integer vertices, real px, real py returns boolean
        local integer i = 0
        set BF_HITS = 0
        
        if vertices <= 2 then
            return false
        endif
        
        set BF_LAST_X = BF_XVERTICES[vertices-1]
        set BF_LAST_Y = BF_YVERTICES[vertices-1]
        
        loop
            exitwhen i >= vertices
            
            call IPIP_Iteration(vertices, px, py, i)
            
            set BF_LAST_X = BF_XVERTICES[i]
            set BF_LAST_Y = BF_YVERTICES[i]
            set i = i +1
        endloop
        
        set BF_HITS = BF_HITS - BF_HITS/2*2
        return BF_HITS != 0
    endfunction
    
    
    globals
        
        //Private variables:
        integer array   polygon2D_N_Points
        
        real array      polygon2D_X_Points
        real array      polygon2D_Y_Points
        
        //Public variables:
        integer         Polygon_Size
        real array      Polygon_X_Coords
        real array      Polygon_Y_Coords
        
    endglobals
    
    function CreatePolygon2D takes nothing returns integer
        local integer polygon = Polygon2D_CreateId()
        local integer vertice
        local integer i = 0
        
        set polygon2D_N_Points[polygon] = Polygon_Size
        loop
            exitwhen i >= Polygon_Size
            
            set vertice = Polygon2D_CreateIndex(polygon)
            set polygon2D_X_Points[vertice] = Polygon_X_Coords[i]
            set polygon2D_Y_Points[vertice] = Polygon_Y_Coords[i]
            
            set i = i +1
        endloop
        
        return polygon
    endfunction
    
    function DestroyPolygon2D takes integer polygon returns nothing
        call Polygon2D_ClearList(polygon)
        call Polygon2D_ReleaseId(polygon)
    endfunction
    
    function GetPolygon2DCenter takes integer polygon returns nothing
        local integer vertice = LL_Polygon2D_FirstIndex[polygon]
        local integer nextVertice
        local real x
        local real y
        
        if vertice == 0 then
            set REAL_ARRAY[0] = 0
            set REAL_ARRAY[1] = 0
            return
        endif
        
        set x = polygon2D_X_Points[vertice]
        set y = polygon2D_Y_Points[vertice]
        
        set vertice = LL_Polygon2D_NextIndex[vertice]
        loop
            exitwhen vertice == 0
            set nextVertice = LL_Polygon2D_NextIndex[vertice]
            
            set x = x + polygon2D_X_Points[vertice]
            set y = y + polygon2D_Y_Points[vertice]
            
            set vertice = nextVertice
        endloop
        
        set REAL_ARRAY[0] = x/vertice
        set REAL_ARRAY[1] = y/vertice
    endfunction
    
    function MovePolygon2D takes integer polygon, real xOffset, real yOffset returns nothing
        local integer vertice = LL_Polygon2D_FirstIndex[polygon]
        local integer nextVertice
        
        loop
            exitwhen vertice == 0
            set nextVertice = LL_Polygon2D_NextIndex[vertice]
            
            set polygon2D_X_Points[vertice] = polygon2D_X_Points[vertice] + xOffset
            set polygon2D_Y_Points[vertice] = polygon2D_Y_Points[vertice] + yOffset
            
            set vertice = nextVertice
        endloop
    endfunction
    
    function SetPolygon2DPosition takes integer polygon, real x, real y returns nothing
        call GetPolygon2DCenter(polygon)
        call MovePolygon2D(polygon, x-REAL_ARRAY[0], y-REAL_ARRAY[1])
    endfunction
    
    function Polygon2DInsertVertice takes integer polygon, real x, real y, integer index returns nothing
        local integer vertice = Polygon2D_InsertIndex(polygon, index)
        set polygon2D_X_Points[vertice] = x
        set polygon2D_Y_Points[vertice] = y
        set polygon2D_N_Points[polygon] = polygon2D_N_Points[polygon] +1
    endfunction
    function Polygon2DAddVertice takes integer polygon, real x, real y returns nothing
        call Polygon2DInsertVertice(polygon, x, y, 0)
    endfunction
    
    function IsPointInPolygon2D takes integer polygon, real px, real py returns boolean
        local integer i = 0
        local integer vertice = LL_Polygon2D_FirstIndex[polygon]
        local integer nextVertice
        
        loop
            exitwhen i >= polygon2D_N_Points[polygon]
            
            set nextVertice = LL_Polygon2D_NextIndex[vertice]
            set BF_XVERTICES[i] = polygon2D_X_Points[vertice]
            set BF_YVERTICES[i] = polygon2D_Y_Points[vertice]
            
            set vertice = nextVertice
            set i = i +1
        endloop
        
        return IsPointInPolygon(polygon2D_N_Points[polygon], px, py)
    endfunction
    
    
    
    
    function CreateTriangle takes real x1, real y1, real x2, real y2, real x3, real y3 returns integer
        set Polygon_Size = 3
        set Polygon_X_Coords[0] = x1
        set Polygon_Y_Coords[0] = y1
        set Polygon_X_Coords[1] = x2
        set Polygon_Y_Coords[1] = y2
        set Polygon_X_Coords[2] = x3
        set Polygon_Y_Coords[2] = y3
        
        return CreatePolygon2D()
    endfunction

endlibrary
(Don't worry about the UNIQUE_ID and the LINKED_LIST.)
I have to apologize for not using structs... but anyone who made a struct lib before can make a struct version out of this... I mean, it is really not that special.
I haven't tested the creation/destruction of polygons so that may have bugs... but I expect them to not have any.

"checking if two polygons intersect and where, the area of an intersection between two polygons"
Working on it.
"Polygons may be 3D."
Dunno if I can do that :/

If someone can make me a "CreateRectangle()" function with top-most efficienct, I would be gratefull... and you will recieve credits :D
The function should take centerX, centerY, width(x-axis), height(y-axis) and angle(degrees) as parameters.

(Test map does not contain Move(), GetCenter() and SetPosition().)
 

Attachments

  • Polygon2D.w3x
    16.5 KB · Views: 131
Last edited:
Max Flow, FFT, Convex Hull, Simplex, etc...?

I wrote FFT once in vJASS, but I got bored and threw the code away.
It can be done recursively pretty safely, but iterative is probably a lot better (idk).

Convex Hull is pretty short to write. It wouldn't require a resource on its own. What's not so trivial is Convex Hull in 3D.

It's not immediately obvious what Simplex would be useful for, but it would be cool to have it out there and see what people could make out of it.
 
Status
Not open for further replies.
Top