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

4 Resources Using Multiboard

Status
Not open for further replies.
Level 3
Joined
Mar 23, 2006
Messages
33
I. Summary

I've just picked up an old copy of the first Age of Empires game and I am marveled at the complexity of acquiring and managing four different resources.

I realize that Genesis of Empires II (http://epicwar.com/maps/5625/) has accomplished a system with more than the two standard resources.

I think using a multiboard would work the best. This way I could ignore the two standard melee game resources (gold and lumber) and I could use those slots for something else.

Does anyone know how this could work? Could someone provide a script to get me started? All help is appreciated.

III. Harvesting Resources

In Genesis of Empires II a player would use an ability on a resource (iron ore, seaweed, wheat etc.) and an integer would be stored on the multiboard. The game included more than four resources. The problem with this is that you could gather resources anywhere on the map and it would be instantly stored in your multiboard (you would acquire the resources instantaneously) rather than having peasants collecting them and returning them to a Town Hall, or a Lumber Mill.

Is there any way around this?

Thanks again. Hoping for help...

III. Gallery

The third image shows an ability that acquires resources when near them. The last image shows several resources displayed on a multiboard.
 

Attachments

  • example_hunt.png
    example_hunt.png
    38.6 KB · Views: 227
  • example_hunted.png
    example_hunted.png
    38.3 KB · Views: 223
  • example_harvest.png
    example_harvest.png
    52.2 KB · Views: 227
  • example_multiboard.png
    example_multiboard.png
    35.7 KB · Views: 238
Last edited:
Level 40
Joined
Dec 14, 2005
Messages
10,532
Harvesting Resources: you could do something such as:

-add all resource-bearing units to a group; every .n seconds, pick every unit from that group. If there's a storage area for the correct resource type nearby, give the resources and remove the unit in question from the group.

I may get around to writing up a multiboard tomorrow, is GUI or JASS preferrable?
 
Level 3
Joined
Mar 23, 2006
Messages
33
Either is acceptable. I may lean more towards GUI myself because I'm not quite at a stage to modify JASS comfortably, but then again JASS may be more efficient.

JASS would be more preferred, but GUI is always an option if you think it gets too complicated. It is, after all, your time.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Heh, I actually never use GUI unless I'm helping someone who wants GUI and only GUI :p

Aight, here we go. Has some commenting in useful places. Tell me if this is what you were looking for (should be local by player)

Note: in JASS, players are Player(0) = Red to Player(11) = Brown to Neutral Passive = 15, (0-15 instead of 1-16)

Accessing player resources is easy by way of the variables. Note: Red is [0] in the array, Blue is [1], and so on, and so forth. (as stated above, they use JASS player ids)

I added a little dummy update resources + update multiboard trigger for an example, too

Oh, and it's commented to heck, so you probably won't get lost :p
 

Attachments

  • Multiboard.w3x
    19 KB · Views: 122
Level 3
Joined
Mar 23, 2006
Messages
33
Thank you. I'll look through this.

Edit:

I've fiddled with the icons and text color a bit. managed to pick up some coding standard with the double "//" when finding images through a directory with many folders. lol

I see that Multiboard creates a multiboard with four resources, the text and icons. UpdateMultiboard increases your resources when collected.

//if (acquires food or something) then -- true is placeholder

I'm a bit confused here:

if true then
set udg_PlayerLumber[pid] = udg_PlayerLumber[pid] + 1
set mi = MultiboardGetItem(udg_TheMultiboard,0,1)
call MultiboardSetItemValue(mi,I2S(udg_PlayerLumber[lid]))
call MultiboardReleaseItem(mi)
endif

So this is where lumber is added to the multiboard?

Is lumber a unit? Do I assign a variable to a specific event (such as collecting lumber)?

Thanks a lot PurplePoot. Rep rewarded for great work. I don't know where I would have started. I just have a few more questions if that's ok with you.
 
Last edited:
Level 40
Joined
Dec 14, 2005
Messages
10,532
No, lumber is stored in an integer array (PlayerLumber). Effectively, you would change if true then to if <your condition to acquire lumber> then

Then, just change the amount of lumber added (set udg_PlayerLumber[pid] = udg_PlayerLumber[pid] + 1)

So thus, for example, if you wanted to give +1 lumber when a unit casted 'give +1 lumber', you would have if GetSpellAbilityId() == 'your lumber ability id' then (of course having the proper event)

Oh, by the way I did an experiment with local players here. There's a small chance of a desync, but

A) it's easy to fix
B) I doubt there actually is one

Oh, by the way, this would probably fit better in the Spells & Systems forum -- I'll ask wolver to move it (I don't have power over this section)
 
Level 3
Joined
Mar 23, 2006
Messages
33
Ok. I guess we're waiting on wolver then. This is really turning out.

I think the most important direction for this is to make some simple events for obtaining the resources (a casted ability), and then just storing them on the multiboard. When I get familiar with JASS, I could modify it to fit a game of mine. For now, this system is going great as it is.

So I set up a unit Fish (Shore) in the WE. I'm assuming it would use the following criteria (though written in JASS). If an ability is being casted / casted ability equal to Spear Fish / then acquire certain amount of food.

A possibility?: if GetSpellAbilityId() == 'Spear Fish' then set (udg_PlayerFood[pid] = udg_PlayerFood[pid] + 10)

Of course, the Spear Fish ability would only work while near the Fish unit. So then we're missing a condition.

Anyway, I can't wait to see the responses we get in the Spells and Systems forum. Thanks a lot PurplePoot.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Well, what method do you want to use to gather/return resources?

By the way, if you're looking to learn more JASS,

www.wc3jass.com is fairly inactive now, but you occasionally still get an answer. It also has a respectable collection of JASS tutorials and scripts.

JassCraft is a great tool for searching up JASS natives and writing your code with fancy syntax highlighting/automatic indenting (to an extent)

JassNewGenPack is a modern JASSer's best friend; it helps you catch those nasty leaks, divide by 0 errors, array index out of bounds, as well as many other oddities and thread crashes. It also replaces the World Editor's crappy JASS compiler with a far better one. Finally, it adds OOP possibilities to JASS, and makes various other bits of code easier to do, faster to write, and easier to organize.
 
Level 3
Joined
Mar 23, 2006
Messages
33
Well. There are two viable options for gathering resources.

1) A unit uses a specific ability to gather resources. Spear Fish to obtain food from Fish, Forage to obtain food from berry bushes, etc. with all the other resources as well. This method either instantaneously adds the resource integer to the multiboard, or happens over time while the ability is being cast.

2) The second option is to collect resources much like gathering trees in a normal melee game, by physically chopping, spearing, mining, etc. the resources and returning them to a storage building. I dont know where to start with this one.

The first one seems most viable. The problem is I don't really like the idea of instantaneously transporting the resources collected to your multiboard. This isn't good because players could collect resources from incredibly far distances instead of having to return to their base or storage building.

What do you think would make this work?

--------

If you could possibly complete a JASS script that just instantaneously acquires certain resources by the use of an ability (such as Spear Fish, Harvest Wood, Forage), which is found in the game Genesis of Empires II I could continue with this system by developing my JASS skills on the sites you tutorial/community sites you showed in your post.

I'd like to hear from you if you an idea for this resource gathering problem.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
The only real problem in my eyes is displaying a good looking animation (portraying the unit holding the resource), but I suppose you could just say what the heck and ignore that, in favor of just skipping the animation.

The rest of the whole resource-mining system is fairly easy;

First, make your guy cast an ability as stated in #1. However, instead of instantaneously updating the resources, update a value attached to the unit. When the unit is 'full' of xxx resource, find the closest structure on the map that is able to recieve that type of resource. Order the unit to move to there.

Then, there are two options here;

Option #1: Add a "Unit In range" event to every resource-recieving building, detecting when units carrying the correct type of resource arrive nearby, and taking that resource and adding it to the player's storage

Option #2: Loop through each resource storage (or resource carrier loaded with resources, either works) and detect any nearby units that can recieve the resources (or give them, if you're picking from the storage). If there is one, dump the resource and add the money to the player's storage.



Option #1 is almost definately more efficient, as long as you clean up the Unit in Range triggers when the building with them died.
 
Level 3
Joined
Mar 23, 2006
Messages
33
LOL To heck with the animations. I just want a properly working system. I'll probably put a buff on the unit so players can tell which resources they are carrying, and maybe a small animation above their heads (such as Shadow Strike) that doesn't move, but represents the color of the resources they are collected. gold to yellow, food to orange, metal to gray, and wood to green. Something like that.
?
I'll try this out (and great idea by the way), along with those tutorials you showed me.

I'm assuming the Unit In range event is a JASS function. Do you have a site that explains a lot of the functions? A compiled list of them with descriptions would be handy.

For the resource collecting buildings, do I make a unit in range event for the same unit type? Or is some variable stored when the building is created?
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
There aren't any official descriptions (as far as I know), but looking at the parameters in JassCraft often gives you an idea of what they do.

JASS:
native TriggerRegisterUnitInRange takes trigger whichTrigger, unit whichUnit, real range, boolexpr filter returns event

So basically;

trigger whichTrigger is the trigger you want to attach it to.

unit whichUnit is the unit people have to come near

real range is how near they have to get to whichUnit

boolexpr filter allows it to only pick up certain unittypes and such (same idea as, for example, a filter on a group (Unit Group))

So, let's say we created a custom trigger when the unit was built -

Here's a very WIP example of what the resource returning system may look like. Note; untested, even unparsed. It also uses the Local Handle Vars(script)(usage). It would be better done with structs, but this is better for your understanding at the moment.

JASS:
function BuildResourceRecieverConds takes nothing returns boolean
    local integer i = GetUnitTypeId(GetConstructedStructure())
    return i == 'first rawcode' or i == 'second rawcode' //and so on
endfunction

function BuildResourceRecieverFilter takes nothing returns boolean
    return GetHandleInt(GetFilterUnit(),"resourcecarried") > 0
endfunction

function BuildResourceReciever_Child takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local integer i = GetHandleInt(u,"resourcecarried")
    local string s = GetHandleString(u,"resourcetypecarried")
    local unit u2 = GetHandleUnit(GetTriggeringTrigger(),"u")
    local player p = GetOwningPlayer(u)
    local integer pid = GetPlayerId(p)
    if p == GetOwningPlayer(u2) then
        call SetHandleInt(u,"resourcecarried",0)
        call SetHandleString(u,"resourcetypecarried","")
        if s == "gold" then
            set udg_PlayerGold[pid] = udg_PlayerGold[pid] + i
        elseif s == "wood" then
            set udg_PlayerLumber[pid] = udg_PlayerLumber[pid] + i
        elseif s == "food" then
            set udg_PlayerFood[pid] = udg_PlayerFood[pid] + i
        elseif s == "metal" then
            set udg_PlayerMetal[pid] = udg_PlayerMetal[pid] + i
        endif
    endif
    set u = null
    set u2 = null
    set p = null
endfunction

function BuildResourceReciever takes nothing returns boolean
    local trigger t = CreateTrigger()
    local unit u = GetConstructedStructure()
    call TriggerRegisterUnitInRange(t,u,250,Filter(function BuildResourceRecieverFilter))//I picked 250 for the range
    //t and ta would be used far later for deleaking purposes
    call SetHandleHandle(u,"t",t)
    call SetHandleHandle(t,"u",u)
    call SetHandleHandle(t,"ta",TriggerAddAction(t,function BuildResourceReciever_Child))
    set u = null
    set t = null
endfunction

function InitTrig_BuildResourceReciever takes nothing returns nothing
    set gg_trg_BuildResourceReciever = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_BuildResourceReciever,EVENT_PLAYER_UNIT_CONSTRUCT_FINISH)
    call TriggerAddCondition(gg_trg_BuildResourceReciever,Condition(function BuildResourceRecieverConds))
    call TriggerAddAction(gg_trg_BuildResourceReciever,function BuildResourceReciever)
endfunction
 
Level 3
Joined
Mar 23, 2006
Messages
33
Now I guess I have to actually set up a bunch of variables. One of the things I'm confused about JASS is where a unit is physically in the code.
 
Level 3
Joined
Mar 23, 2006
Messages
33
Sorry. I'm going off on a tangent. This may be a fairly naive question but where does it say in the code you provided what the unit-type is for the resourcereceiver.

Where it says first rawcode, second rawcode
What do I put in there? Where do I specify which resourcereceiver building corresponds to each type of resource?
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Those are the unit-types. ('first rawcode', 'second rawcode') (hence the local integer i = GetUnitTypeId(GetConstructedStructure()))

As for specifying what building receives what resource; in the BuildResourceReciever_Child function, there's a unit u2. That's the resource receiver itself. Then, you could just change if s == "gold" then to if s == "gold" and GetUnitTypeId(u2) == 'gold resource receiver rawcode' then, and so on.

(I suggest you make a local integer uid = GetUnitTypeId(u2) for efficiency reasons)
 
Level 3
Joined
Mar 23, 2006
Messages
33
Go it. So where do I actually state that u2 is a particular unit from the object editor, such as a Barracks, Lumber Mill, etc.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
When you press Ctrl+D (Display Values as Raw Data), all the fields will go weird. Noticeably, on the left (the unit tree), you'll see the names changed to something like

hpea (Peasant)
hfoo (Footman)

and so on.

The hpea/hfoo/etc are the unit's 'rawcode'. This rawcode is an integer in JASS, denoted by placing the letters and numbers between single quotes, for example 'hpea' or 'hfoo'.

So thus, if you wanted to know if u2 was a barracks (lets say your custom barracks has id h000), then you would say if GetUnitTypeId(u2) == 'h000' then

make sense?
 
Level 3
Joined
Mar 23, 2006
Messages
33
It makes sense now. I can obtain the raw data by pressing ctrl-d in the object editor and then take that value and insert it into the JASS script.
 
Last edited:
Status
Not open for further replies.
Top