System Detect Resources Exchange System

Status
Not open for further replies.

Troll-Brain

You can change this now in User CP.
Reaction score
85
I don't really like to name it as a "system", cause it's a very simple logic but i think it's not a snippet.

Because blizzard suck and don't create an event to register when a player give gold or lumber to another player, i made this thing.

It requires a vJass compiler (for the system alone) and the jass new gen pack with UMWSE activated for the demo map with a gui example.
I attached a demo map without the UMWSE features.

I highly recommend to use UMWSE for gui users.
For the if/then/else multiple actions, the events,actions,conditions added, etc.

You need to be two players at least to test the map.

Here is the code :

JASS:
//==============================================================================
//      DRES -> DETECT RESOURCE EXCHANGE SYSTEM -- v1.3 // by Troll-Brain
//==============================================================================
//
//      REQUIREMENTS :
//              * The last JassHelper
//              * The library DataSystem by grim001, more infos about that :
//                 <a href="http://wc3campaigns.net/pastebint.php?t=100400&amp;code=87e482563039fa6408a045efca81ea5e" target="_blank" class="link link--external" rel="nofollow ugc noopener">http://wc3campaigns.net/pastebint.php?t=100400&amp;code=87e482563039fa6408a045efca81ea5e</a>
//                 
//      THE GOAL :
//              * Detect when a player gives gold or wood to an allie, and ofc to know wich one is the donor, the receiver
//                and the amount of the deal.
//
//      HOW IT WORKS :
//              * It add a new TriggerRegisterPlayerStateEvent event to your trigger, for each player in the force you define
//                and also a condition because this function don&#039;t have a boolexpr parameter.
//
//      HOW TO IMPORT:
//              * Just create a trigger named DRES or whatever.
//              * Convert it to text and replace the trigger text with this one.
//              * Do the same with the library DataSystem.
//
//      HOW TO USE IT :
//              * Read the documentation and check the example in the demo map.

library DRES initializer init needs DataSystem

    globals
        public constant integer GOLD= 1 // If you don&#039;t already use these common name for constants
        public constant integer LUMBER= 2 // , then you can remove the public attribute
        private constant real MAX= 1000000.0 // you should not edit this value, because it&#039;s simply the max possible of a resource
        private constant real TIME_OUT= 1.0 // i think that&#039;s a good value
    endglobals
    
    globals // don&#039;t edit them
        private timer Tim= null                             
        private trigger Trig= null
        private integer Ref= 0
        public playerstate Ple= null
        private integer Count= 1
    endglobals
    
    //! runtextmacro DataDeclareFast(&quot;DRES_GoldTrig&quot;,&quot;trigger&quot;)
    //! runtextmacro DataDeclareFast(&quot;DRES_LumberTrig&quot;,&quot;trigger&quot;)
    
    //Or use the textmacro DataDeclare instead, if you REALLY need more.
        
    //! textmacro DRES_Resource takes TYPE , NAME
    globals
        private player $TYPE$Donor= null
        private player $TYPE$PossibleDonor= null
        private player $TYPE$Receiver= null
        private integer array $TYPE$Given
        private real $TYPE$Time= 0.0
        private conditionfunc $TYPE$C= null
        private integer $TYPE$Deal= 0
        private integer $TYPE$PossibleDeal= 0
    endglobals
    
    private function $TYPE$Check takes nothing returns boolean
        local player p= GetTriggerPlayer()
    
        if GetEventPlayerState () == PLAYER_STATE_RESOURCE_$NAME$ then
            if TimerGetElapsed(Tim)*Count != $TYPE$Time then
                set $TYPE$PossibleDonor= GetTriggerPlayer()
                set $TYPE$Time= TimerGetElapsed(Tim)*Count
                return false
            else
                set Ref= GetPlayerId($TYPE$PossibleDonor)
                set $TYPE$PossibleDeal= GetPlayerScore($TYPE$PossibleDonor, PLAYER_SCORE_$NAME$_GIVEN) - $TYPE$Given[Ref] 
                if $TYPE$PossibleDeal == 0 then
                    set $TYPE$PossibleDonor= GetTriggerPlayer()
                    return false
                endif
                set $TYPE$Deal= $TYPE$PossibleDeal
                set $TYPE$Donor= $TYPE$PossibleDonor
                set $TYPE$Receiver= GetTriggerPlayer()
                set $TYPE$Given[Ref] = GetPlayerScore($TYPE$Donor, PLAYER_SCORE_$NAME$_GIVEN)
            endif
            set $TYPE$Time= TimerGetElapsed(Tim)*Count
        endif
        
        return true
    endfunction
        
    private function $TYPE$ForForce takes nothing returns nothing
        call TriggerRegisterPlayerStateEvent( Trig, GetEnumPlayer(), PLAYER_STATE_RESOURCE_$NAME$, NOT_EQUAL, MAX )
    endfunction
        
    function Get$TYPE$Donor takes nothing returns player
        if GetEventPlayerState()!= PLAYER_STATE_RESOURCE_$NAME$ then
            debug call BJDebugMsg(&quot;you tried to use the function Get$TYPE$Donor with a bad event&quot;)
            return null
        elseif GetDRES_$TYPE$Trig(GetTriggeringTrigger()) != GetTriggeringTrigger() then
            debug call BJDebugMsg(&quot;you didn&#039;t use the function TriggerRegisterTrade to register the $TYPE$ trade&quot;)
            return null
        endif
        return $TYPE$Donor
    endfunction
        
    function Get$TYPE$Receiver takes nothing returns player
        if GetEventPlayerState()!= PLAYER_STATE_RESOURCE_$NAME$ then
            debug call BJDebugMsg(&quot;you tried to use the function Get$TYPE$Receiver with a bad event&quot;)
            return null
        elseif GetDRES_$TYPE$Trig(GetTriggeringTrigger()) != GetTriggeringTrigger() then
            debug call BJDebugMsg(&quot;you didn&#039;t use the function TriggerRegisterTrade to register the $TYPE$ trade&quot;)
            return null
        endif
        return $TYPE$Receiver
    endfunction
        
    function Get$TYPE$Deal takes nothing returns integer
        if GetEventPlayerState()!= PLAYER_STATE_RESOURCE_$NAME$ then
            debug call BJDebugMsg(&quot;you tried to use the function Get$TYPE$Deal with a bad event&quot;)
            return 0
        elseif GetDRES_$TYPE$Trig(GetTriggeringTrigger()) != GetTriggeringTrigger() then
            debug call BJDebugMsg(&quot;you didn&#039;t use the function TriggerRegisterTrade to register the $TYPE$ trade&quot;)
            return 0
        endif
        return $TYPE$Deal
    endfunction
    
    function GetLast$TYPE$Donor takes nothing returns player
        return $TYPE$Donor
    endfunction
    
    function GetLast$TYPE$Receiver takes nothing returns player
        return $TYPE$Receiver
    endfunction
    
    function GetLast$TYPE$Deal takes nothing returns integer
        return $TYPE$Deal
    endfunction
    
    //! endtextmacro
    //! runtextmacro DRES_Resource(&quot;Gold&quot;,&quot;GOLD&quot;)
    //! runtextmacro DRES_Resource(&quot;Lumber&quot;,&quot;LUMBER&quot;)
    
    function TriggerRegisterTrade takes trigger t , force f , integer resourceType returns boolean
            
        if f== null then
            debug call BJDebugMsg(&quot;the force taken in the function TriggerRegisterTrade is null&quot;)
            return false
        elseif t== null then
            debug call BJDebugMsg(&quot;the trigger taken in the function TriggerRegisterTrade is null&quot;)
            return false
        endif
        set Trig= t
            
       if resourceType== GOLD then

            if GetDRES_GoldTrig(t)== t then
                debug call BJDebugMsg(&quot;You had already register a gold exchange for this trigger&quot;)
                return false
            endif
            call ForForce(f,function GoldForForce)
            call TriggerAddCondition(t,Condition(function GoldCheck))
            call SetDRES_GoldTrig(t,t)
            return true
        elseif resourceType== LUMBER then

            if GetDRES_LumberTrig(t)== t then
                debug call BJDebugMsg(&quot;You had already register a lumber exchange for this trigger&quot;)
                return false
            endif
            call ForForce(f,function LumberForForce)
            call TriggerAddCondition(t,Condition(function LumberCheck))
            call SetDRES_LumberTrig(t,t)
            return true
        endif
            
        debug call BJDebugMsg(&quot;the resourceType taken in the function TriggerRegisterTrade is invalid&quot;) 
        return false
    endfunction
    
// This textmacro should be used if you want other events in your trigger, because in the case of a trade, the conditions will be evaluated two times.
// Using this macro won&#039;t avoid the double evaluation but if you use it just after the local declaration in your condition, it will return false
// if the players events GOLD or LUMBER start the trigger. Check the demo trigger to see an example of usage.

    //! textmacro DRES_C
        set DRES_Ple = GetEventPlayerState()
        if DRES_Ple== PLAYER_STATE_RESOURCE_GOLD or DRES_Ple== PLAYER_STATE_RESOURCE_GOLD then
            return true
        endif
    //! endtextmacro
    
    private function TimeOut takes nothing returns nothing
        set Count= Count+1
    endfunction
    
    private function init takes nothing returns nothing
        local trigger t=CreateTrigger()
        call TriggerAddAction(t,function TimeOut)
        set Tim=CreateTimer()
        call TimerStart(Tim,TIME_OUT,true,null)
        set GoldC=Condition(function GoldCheck)
        set LumberC=Condition(function LumberCheck)
    endfunction
    
endlibrary


Here is the documentation :

JASS:
//      ~~ CHANGELOG
        
    * v1.3
        -updated with the new library DataSystem
        
    * v1.2
        - Fixed a bug, i used GetTriggerEventId() instead of GetEventPlayerState() without any compilation error ...
        
    * v1.1
        - Renamed the function TriggerRegisterResourceExchange by this shorter name : TriggerRegisterTrade.
        - Added a demo map.
        
    * v1.0
        - Edited the code to follow the jass convention.
        - Added the functions GetLast...
        - Fixed a possible bug if the time beetween two trades was very closed.
        - Now i&#039;ts completly friendly user, because :
            ~ you won&#039;t be able to add many time the same ResourceExchange event in a same trigger, even if you call it.
            ~ the gets returns null if it&#039;s not the right event.
            ~ added a texmacro for your trigger conditions.
            ~ added more debug messages.

    * v0.2
        - Added a miss setting of the variables $TYPE$Time in the Alt$TYPE$Check functions.
        - Added more comments about how to use the AltRegister$TYPE$Exchange function.
        
    * v0.1
        - Initial Release.
        
//      ~~ HOW TO USE IT

    I will comment the functions.
    
&gt;&gt;&gt;      Register function      &lt;&lt;&lt;

    You should use only allies for the force parameter but if the alliance can change in the game,
    or if you can give resource to ennemies then simply add all players.
    The function below is friendly user, it will add for you the events and the condition to your trigger.

    ** function TriggerRegisterResourceExchange takes trigger t , force f , integer resourceType returns boolean
            - Use this function to register a trade. For the ressourceType simply use the constants DRES_GOLD and DRES_LUMBER.
               or GOLD and LUMBER if you can delete the public attribute of them in the library.
            - It returns true if the event is register and false if not.
    
    You are not allowed to add the same event in the same trigger with this function.
    If you try it it won&#039;t add it anyway, so just don&#039;t.

    Now it&#039;s hardier.
    The function TriggerRegisterResourceExchange add players event PLAYER_STATE_RESOURCE_(GOLD or LUMBER) to your trigger.
    You can add more other events to your trigger but you must consider these facts:
    
    - You are not allowed to add these players event PLAYER_STATE_RESOURCE_GOLD or PLAYER_STATE_RESOURCE_LUMBER.
    - Your conditions will be evaluated when a resource player change (gold or lumber ofc).
    - In case of a trade, the conditions will be evaluated two times.
    - I have created a textmacro to fix this problem, check the example.

    The condition added by the function TriggerRegisterResourceExchange returns true when the system detect an exchange of ressources between players, but also true,
    when the event which fire the trigger, is different to PLAYER_STATE_RESOURCE_(GOLD or LUMBER). To allow the other conditions evaluate.

           
&gt;&gt;&gt;      Get functions      &lt;&lt;&lt;
           
    The different Get return null if you try to use it with a bad event.
    But ofc you can use the GetLast... anywhere.

    ** function GetGoldDonor takes nothing returns player
            - Use this function to return which player gives gold.

    ** function GetGoldReceiver takes nothing returns player
            - Use this function to return which player get gold.

    ** function GetLumberDonor takes nothing returns player
            - Use this function to return which player gives lumber.

    ** function GetLumberReceiver takes nothing returns player
            - Use this function to return which player get lumber.

    ** function GetGoldDeal takes nothing returns integer
            - Use this function to return the amount of the gold exchange.

    ** function GetLumberDeal takes nothing returns integer
            - Use this function to return the amount of the lumber exchange.

    ** function GetLastGoldDonor takes nothing returns player
            - Use this function to return the last gold donor.
            
    ** function GetLastLumberDonor takes nothing returns player
            - Use this function to return the last lumber donor.
            
    ** function GetLastGoldReceiver takes nothing returns player
            - Use this function to return the last gold receiver.

    ** function GetLastLumberReceiver takes nothing returns player
            - Use this function to return the last lumber receiver.

    ** function GetLastGoldDeal takes nothing returns integer
            - Use this function to return the last gold deal.
            
    ** function GetLastLumberDeal takes nothing returns integer
            - Use this function to return the last lumber deal.  

//      ~~ SPECIAL THANKS TO

            //! popp
                - Asked me the system and tested it a lot with me.
            //! Blubb-Tec
                - Found a code error and reminder me the double evaluation of the trigger.
            //! Earth-Fury
                - Helped me for respect the jass convention and gave me some tips.
            //! grim001
                - For his library DataSystem.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
I know why blizzard didn't make this event, that's simply because nobody needs it.
But i lie, i found 1,5 players on the earth (one will use it, and one simply always wondered how one would do something like that :p )
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,495
> I know why Blizzard didn't add this event, that's simply because nobody needs it.

Indeed.
Common, and, actually, the only, needs on resource exchange are
- how to give more, faster
- how to turn it off

Simple gameplay constant settings.


Anyway, what exactly would I need this for?

Just from looking at the code, it's also not clear how to actually use this.
I guess the map helps there...


Does it notice:
- Player - Add -100 to Current gold of Player 1
- Player - Add 100 to Current gold of Player 2

If yes, why?
If no, why not?
And, what if I need that? Or don't need that?


> with UMWSE activated for the demo map

An extremely weird requirement I might add...
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
> I know why Blizzard didn't add this event, that's simply because nobody needs it.

Indeed.
Common, and, actually, the only, needs on resource exchange are
- how to give more, faster
- how to turn it off

Simple gameplay constant settings.


Anyway, what exactly would I need this for?

Just from looking at the code, it's also not clear how to actually use this.
I guess the map helps there...


Does it notice:
- Player - Add -100 to Current gold of Player 1
- Player - Add 100 to Current gold of Player 2

If yes, why?
If no, why not?
And, what if I need that? Or don't need that?


> with UMWSE activated for the demo map

An extremely weird requirement I might add...

With this "system" you can "easily" turn it on/off when you want by giving the resource to the donor and takes the resource to the receiver.
It's just for catch the trade event which don't exist.

I will make a really gui example.

Read the documentation for more infos .

But simply if you use this custom event it will added player events and a condition.
If it's not a trade but simply a resource change the condition will return false, the condition added will return true if it's a trade or an other event, to allow using multiple events on a same trigger.
Because you can't control this added condition, it's a part of the register event.
There is no boolexpr filter for this player event, and anyway using a filter with an event seems to be useless.
I tried with PLAYER_UNIT... receive an order and all the Get returns null, great ...

Btw there is already a jass example in the map without UMWSE.
But you're right i will remove this requirement.
 
Status
Not open for further replies.
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top