• 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.

How to design Mana distribution?

Status
Not open for further replies.
Level 15
Joined
Nov 30, 2007
Messages
1,202
Need help on how to design a distribution system for mana.

Basically mana will represent the current hunger level of a unit. The main building has food stored and the problem is:

There must be an automatic way to distribute this Mana around the main, but at the same time keeping the option of turning it off. The best spell to use for this would be the Obsidian Statue replenish mana, the problem is that 1 mana used can provide for multiple units.

Replenish Mana and Life works but it doesn't give automatically in a pleasing way.
 
Last edited:
Level 15
Joined
Nov 30, 2007
Messages
1,202
Do you want the amount of mana spent equals to amount of many send to all units?

Yes, you can do that with replenish life and magic, only issue is that it doesn't happen automatically (even though it's toggled to) which would lead to idle units getting weak and sick even though they are next to a food source.

Another issue is that you could eat your allies supply by using the ability (replenish life and magic) but that might not be too much of a problem considering you can unally...
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
trigger it.

Every ... seconds of gametime, pick all units in range.
Check if the units are allied... alive... etc. and remove mana from the building and add mana to the picked unit.

Okey it's decided, but is it better to order the main building to cast the spell replenish mana and life on picked unit or increase the units mana and decrease the buildings mana by actions?
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
Okey, don't have a trigger to show for it yet. But this is how I would like it to work:

- loop through all cities
- check for automatic food distribution and if the building has any food
- Pick Every Unit nearby
- Check that the mana of the picked unit is around 80% or less
- Order The picked unit to right-click on the city building (get effected by replenish life and mana).
- Stop the loop when the City is out of food.

Only issue remaining apart from making the damn trigger is how to feed the hungriest unit first. I would have to stack them as they are being picked and pop them out in the order how hungry they are. Otherwise oddities such as 1 guy starving while the others are being well feed might occur...
 
Level 15
Joined
Nov 30, 2007
Messages
1,202
Just a thought:
Give units dropping below a certain amount of mana a "well fed" "hungry" or "starving" buff.
Check for the buffs in your trigger and only feed units who are starving or hungry and ignore well fed.

Or something like that.

That's a good point!

I don't have to index them exactly, only divide them into subgroups 1 to 5, 5 having the highest feeding priority and then empty those groups in order during the feeding period.

Im not too familiar with Unit Groups in JASS, altought I got help counting units in a group once.

basically what I want to do is creating 1 group around x,y and then 5 subgroups all being flushed in the end.
 
Last edited:
Level 15
Joined
Nov 30, 2007
Messages
1,202
I fixed the bug from yesterday, it works like a charm. Not sure how efficient it is currently though.

JASS:
library autoEat initializer Init

globals
    constant integer FEED_RANGE = 600
    private group array g
endglobals

private function Main takes nothing returns nothing
    local integer i = 1
    local integer j = 1
    local player p
    local unit u
    local real x
    local real y
    local real m
    
    loop
        exitwhen cityMain[i] == null
            if autoFeedOn[i] == true and GetUnitState(cityMain[i], UNIT_STATE_MANA) > 0 then
                set p = GetOwningPlayer(cityMain[i])
                set x = GetUnitX(cityMain[i])
                set y = GetUnitY(cityMain[i])
                call GroupEnumUnitsInRange(g[0],x,y,FEED_RANGE,null)
                loop
                    set u = FirstOfGroup(g[0])
                    exitwhen u == null
                    call GroupRemoveUnit(g[0],u)
                    if GetUnitState(u, UNIT_STATE_MAX_MANA) > 0 and  IsUnitType(u, UNIT_TYPE_STRUCTURE) == false and GetOwningPlayer(u) == p then
                        set m = GetUnitState(u, UNIT_STATE_MANA)/GetUnitState(u, UNIT_STATE_MAX_MANA)*100.0
                        if m <= 10.0 then
                            call GroupAddUnit(g[1],u)
                        elseif m <= 30.0  then
                            call GroupAddUnit(g[2],u)
                        elseif m <= 50.0  then
                            call GroupAddUnit(g[3],u)
                        elseif m <= 80.0  then
                            call GroupAddUnit(g[4],u)
                        endif
                    endif
                endloop
                loop
                    exitwhen j > 4
                   loop                                             // I think it would be better to break
                        set u = FirstOfGroup(g[j])                  // When mana reaches 0
                        exitwhen u == null                          // And just destroy the groups in the end
                        call GroupRemoveUnit(g[j], u)               // Not sure...
                        if GetUnitState(cityMain[i], UNIT_STATE_MANA) > 0 then
                            call IssueTargetOrder(u, "smart", cityMain[i])
                        endif
                    endloop
                    set j = j + 1
                endloop
            endif
        set i = i + 1
    endloop
    set u = null
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    loop
        exitwhen i > 4
        set g[i] = CreateGroup()
        set i = i + 1
    endloop
    call TriggerRegisterTimerEvent(t, 7, true)
    call TriggerAddAction(t, function Main)
endfunction

endlibrary

Any suggestions on what kind of weakness and sickness should come from a starving army? ^^
 
Last edited:
Level 15
Joined
Nov 30, 2007
Messages
1,202
A suggestion : GetUnitManaPercent(u) -> GetUnitStatePercent(u, UNIT_STATE_MANA, UNIT_STATE_MAX_MANA)

EDIT :
Nevermind it, seems more or less they're BJs.
Though it saves one time function calls (where the first call the latter)

I'll look into it, but I'm more curious about the overall design.

One way to slim it down might be to calculate how many units the City can serve while adding them or something along those lines.
 
I think your function would be leaking since it runs in periodic, since the unit groups are recreated all over again.
I recommend to create them on Init and then use them on the loop. Seems it's the most suitable way. Add and remove as necessary.

I might be mistaken, as I'm not a good Jasser myself.
 
Last edited:
Status
Not open for further replies.
Top