Harvest?

Azlier

Old World Ghost
Reaction score
461
Never seen a script that detects when units return resources to a town hall, sadly. Worthy of being a resource? Well, you tell me.

Well, this does so. But it has these flaws:
  • The town hall that the resources were returned to cannot be gotten accurately.
  • It cannot get the object which the resources originated from accurately.
  • If the resources are modified in any way within 0.01 seconds of any unit being issued an order, there'll be problems. Big problems.
  • It only works with units that use the Human method of gold/lumber gathering (peasants, peons, ghouls, Mur'gul slaves, Goblin Shredders).

And here's the code. Requires AIDS and Event.
JASS:
library Harvest initializer Init requires AIDS, Event

globals
    private constant real PERIOD = 0.01
    //The bigger the period, the less work the computer must do.
    //...But the greater chance of certain bugs happening.
    
    //Explanation:
    //  If a unit returns resources within the same time period
    //  as anything else the modifies the player's resource number
    //  (triggers, tribute, other harvesters...), there'll be weird bugs.
endglobals

globals
    private timer Timer = CreateTimer()
    private integer array pgold
    private integer array plumber
    private player array pl
    
    private constant integer RESUME_HARVEST = 0xD0031
    private constant integer HARVEST = 0xD0032
    private constant integer SMART = 0xD0003
    
    private integer i
    
    private integer gamount
    private integer lamount
    private integer pid
    
    private Event gEv
    private Event lEv
endglobals

function TriggerRegisterHarvestGoldEvent takes trigger whichTrigger returns nothing
    call gEv.register(whichTrigger)
endfunction

function TriggerRegisterHarvestLumberEvent takes trigger whichTrigger returns nothing
    call lEv.register(whichTrigger)
endfunction

function GetHarvestedGold takes nothing returns integer
    return gamount
endfunction

function GetHarvestedLumber takes nothing returns integer
    return lamount
endfunction

private struct Data extends array
    //! runtextmacro AIDS()
    boolean b
    
    method AIDS_onDestroy takes nothing returns nothing
        set b = false
    endmethod
endstruct

private function ITO takes nothing returns boolean
    set i = GetIssuedOrderId()
    //if i == HARVEST then
        if Data[GetTriggerUnit()].b then
            set pid = GetPlayerId(GetTriggerPlayer())
            set gamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_GOLD) - pgold[pid]
            if gamount > 0 then
                call gEv.fire()
                set gamount = 0
                return false
            endif
            set gamount = 0
            set lamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_LUMBER) - plumber[pid]
            if lamount > 0 then
                call lEv.fire()
            endif
            set lamount = 0
        endif
    if i == RESUME_HARVEST or i == SMART then
        set Data[GetTriggerUnit()].b = true
    else
        set Data[GetTriggerUnit()].b = false
    endif
    return false
endfunction

private function IPO takes nothing returns boolean
    if Data[GetTriggerUnit()].b then
        set pid = GetPlayerId(GetTriggerPlayer())
        set gamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_GOLD) - pgold[pid]
        if gamount > 0 then
            call gEv.fire()
            set gamount = 0
            return false
        endif
        set gamount = 0
        set lamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_LUMBER) - plumber[pid]
        if lamount > 0 then
            call lEv.fire()
        endif
        set lamount = 0
    endif
    set Data[GetTriggerUnit()].b = false
    return false
endfunction

private function IO takes nothing returns boolean
    if Data[GetTriggerUnit()].b then
        set pid = GetPlayerId(GetTriggerPlayer())
        set gamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_GOLD) - pgold[pid]
        if gamount > 0 then
            call gEv.fire()
            set gamount = 0
            return false
        endif
        set gamount = 0
        set lamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_LUMBER) - plumber[pid]
        if lamount > 0 then
            call lEv.fire()
        endif
        set lamount = 0
    endif
    set Data[GetTriggerUnit()].b = GetIssuedOrderId() == RESUME_HARVEST
    return false
endfunction

private function UpdateResources takes nothing returns nothing
    set i = 15
    loop
        set pgold<i> = GetPlayerState(pl<i>, PLAYER_STATE_RESOURCE_GOLD)
        set plumber<i> = GetPlayerState(pl<i>, PLAYER_STATE_RESOURCE_LUMBER)
        exitwhen i == 0
        set i = i - 1
    endloop
endfunction

private function InitZero takes nothing returns nothing
    set i = 15
    loop
        set pgold<i> = GetPlayerState(pl<i>, PLAYER_STATE_RESOURCE_GOLD)
        set plumber<i> = GetPlayerState(pl<i>, PLAYER_STATE_RESOURCE_LUMBER)
        exitwhen i == 0
        set i = i - 1
    endloop
    call TimerStart(Timer, PERIOD, true, function UpdateResources)
endfunction

private function Init takes nothing returns nothing
    local trigger t1 = CreateTrigger()
    local trigger t2 = CreateTrigger()
    local trigger t3 = CreateTrigger()
    call TriggerAddCondition(t1, function ITO)
    call TriggerAddCondition(t2, function IPO)
    call TriggerAddCondition(t3, function IO)
    set i = 15
    loop
        set pl<i> = Player(i)
        call TriggerRegisterPlayerUnitEvent(t1, pl<i>, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null)
        call TriggerRegisterPlayerUnitEvent(t2, pl<i>, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, null)
        call TriggerRegisterPlayerUnitEvent(t3, pl<i>, EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
        exitwhen i == 0
        set i = i - 1
    endloop
    call TimerStart(Timer, 0, false, function InitZero)
    
    set gEv = Event.create()
    set lEv = Event.create()
endfunction

endlibrary</i></i></i></i></i></i></i></i></i></i></i></i>


Here's a test script.
JASS:
library HarvestTest initializer Init requires Harvest

private function GActions takes nothing returns boolean
    call BJDebugMsg(&quot; &quot;)
    call BJDebugMsg(GetUnitName(GetTriggerUnit()))
    call BJDebugMsg(&quot;Gold harvested: &quot; + I2S(GetHarvestedGold()))
    return false
endfunction

private function LActions takes nothing returns boolean
    call BJDebugMsg(&quot; &quot;)
    call BJDebugMsg(GetUnitName(GetTriggerUnit()))
    call BJDebugMsg(&quot;Lumber harvested: &quot; + I2S(GetHarvestedLumber()))
    return false
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterHarvestGoldEvent(t)
    call TriggerAddCondition(t, function GActions)
    
    set t = CreateTrigger()
    call TriggerRegisterHarvestLumberEvent(t)
    call TriggerAddCondition(t, function LActions)
endfunction

endlibrary
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Shift orders can break that.
I've tested one year or more before :(

The only good way is to create a whole system which completely erase and replace the original one.
But that's lot of work, i'm definetly to much lazy to do it, since i won't use it anyway ...
But maybe you're not xD
 

Azlier

Old World Ghost
Reaction score
461
>The only good way is to create a whole system which completely erase and replace the original one.

Quite. But, like total unit recycling, very hard to do.

>Shift orders

Hmm? Just tested. I see. Well, this one goes in the recycle bin.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
I haven't read your code , but i suppose you detect when a worker get the order to collect one more time some gold at the mine, and then that means this unit have given some gold to the townhall ?
If not, then ok but it would be inaccurate so.
 

Azlier

Old World Ghost
Reaction score
461
Precisely that, Troll. And, this one (which is less efficient) appears to work with shift orders, but who knows what sort of bugs I'm inviting to my tea party?

JASS:
library Harvest initializer Init requires AIDS, Event

globals
    private constant real PERIOD = 0.05
    //The bigger the period, the less work the computer must do.
    //...But the greater chance of certain bugs happening.
    
    //Explanation:
    //  If a unit returns resources within the same time period
    //  as anything else the modifies the player&#039;s resource number
    //  (triggers, tribute, other harvesters...), there&#039;ll be weird bugs.
endglobals

globals
    private timer Timer = CreateTimer()
    private integer array pgold
    private integer array plumber
    private player array pl
    
    private constant integer RESUME_HARVEST = 0xD0031
    private constant integer HARVEST = 0xD0032
    private constant integer SMART = 0xD0003
    
    private integer i
    
    private integer gamount
    private integer lamount
    private integer pid
    
    private Event gEv
    private Event lEv
endglobals

function TriggerRegisterHarvestGoldEvent takes trigger whichTrigger returns nothing
    call gEv.register(whichTrigger)
endfunction

function TriggerRegisterHarvestLumberEvent takes trigger whichTrigger returns nothing
    call lEv.register(whichTrigger)
endfunction

function GetHarvestedGold takes nothing returns integer
    return gamount
endfunction

function GetHarvestedLumber takes nothing returns integer
    return lamount
endfunction

private struct Data extends array
    //! runtextmacro AIDS()
    boolean b
    
    method AIDS_onDestroy takes nothing returns nothing
        set b = false
    endmethod
endstruct

private function ITO takes nothing returns boolean
    set i = GetIssuedOrderId()
    //if i == HARVEST then
        if Data[GetTriggerUnit()].b then
            set pid = GetPlayerId(GetTriggerPlayer())
            set gamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_GOLD) - pgold[pid]
            if gamount &gt; 0 then
                call gEv.fire()
                set gamount = 0
                return false
            endif
            set gamount = 0
            set lamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_LUMBER) - plumber[pid]
            if lamount &gt; 0 then
                call lEv.fire()
            endif
            set lamount = 0
        endif
    if i == RESUME_HARVEST or i == SMART then
        set Data[GetTriggerUnit()].b = true
    else
        set Data[GetTriggerUnit()].b = false
    endif
    return false
endfunction

private function IPO takes nothing returns boolean
    if Data[GetTriggerUnit()].b then
        set pid = GetPlayerId(GetTriggerPlayer())
        set gamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_GOLD) - pgold[pid]
        if gamount &gt; 0 then
            call gEv.fire()
            set gamount = 0
            return false
        endif
        set gamount = 0
        set lamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_LUMBER) - plumber[pid]
        if lamount &gt; 0 then
            call lEv.fire()
        endif
        set lamount = 0
    endif
    set Data[GetTriggerUnit()].b = false
    return false
endfunction

private function IO takes nothing returns boolean
    if Data[GetTriggerUnit()].b then
        set pid = GetPlayerId(GetTriggerPlayer())
        set gamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_GOLD) - pgold[pid]
        if gamount &gt; 0 then
            call gEv.fire()
            set gamount = 0
            return false
        endif
        set gamount = 0
        set lamount = GetPlayerState(pl[pid], PLAYER_STATE_RESOURCE_LUMBER) - plumber[pid]
        if lamount &gt; 0 then
            call lEv.fire()
        endif
        set lamount = 0
    endif
    set Data[GetTriggerUnit()].b = GetIssuedOrderId() == RESUME_HARVEST
    return false
endfunction

private function UpdateResources takes nothing returns nothing
    set i = 15
    loop
        set pgold<i> = GetPlayerState(pl<i>, PLAYER_STATE_RESOURCE_GOLD)
        set plumber<i> = GetPlayerState(pl<i>, PLAYER_STATE_RESOURCE_LUMBER)
        exitwhen i == 0
        set i = i - 1
    endloop
endfunction

private function InitZero takes nothing returns nothing
    set i = 15
    loop
        set pgold<i> = GetPlayerState(pl<i>, PLAYER_STATE_RESOURCE_GOLD)
        set plumber<i> = GetPlayerState(pl<i>, PLAYER_STATE_RESOURCE_LUMBER)
        exitwhen i == 0
        set i = i - 1
    endloop
    call TimerStart(Timer, PERIOD, true, function UpdateResources)
endfunction

private function Init takes nothing returns nothing
    local trigger t1 = CreateTrigger()
    local trigger t2 = CreateTrigger()
    local trigger t3 = CreateTrigger()
    call TriggerAddCondition(t1, function ITO)
    call TriggerAddCondition(t2, function IPO)
    call TriggerAddCondition(t3, function IO)
    set i = 15
    loop
        set pl<i> = Player(i)
        call TriggerRegisterPlayerUnitEvent(t1, pl<i>, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null)
        call TriggerRegisterPlayerUnitEvent(t2, pl<i>, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, null)
        call TriggerRegisterPlayerUnitEvent(t3, pl<i>, EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
        exitwhen i == 0
        set i = i - 1
    endloop
    call TimerStart(Timer, 0, false, function InitZero)
    
    set gEv = Event.create()
    set lEv = Event.create()
endfunction

endlibrary</i></i></i></i></i></i></i></i></i></i></i></i>
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Precisely that, Troll. And, this one (which is less efficient) appears to work with shift orders, but who knows what sort of bugs I'm inviting to my tea party?
No it should be awesomely efficient, see, you use a global player array variable instead of Player() xD

I really hate inaccurate things, but in your way i would check for the player score instead, when player state event fire, and maybe a timer(0) could be needed.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top