Troll-Brain
You can change this now in User CP.
- Reaction score
- 85
Here is a simple and short system :
Requires :
- JassHelper
- The JassNewGenPack with UMWSE enabled if you want to open the demo map
- the library Table
And this is the documentation you can copy/paste it in a deactivated jass trigger.
Read the changelog for more infos.
EDIT : You must be at least 2 players to test it, it seems it's hardcoded in war3.
JASS:
//==============================================================================
// DRES -> DETECT RESOURCE EXCHANGE SYSTEM -- v 2.1 // by Troll-Brain
//==============================================================================
//
// REQUIREMENTS :
// * The last JassHelper
// * The library Table by Vexorian, more infos about that :
// <a href="http://www.wc3campaigns.net/showthread.php?t=101246" target="_blank" class="link link--external" rel="nofollow ugc noopener">http://www.wc3campaigns.net/showthread.php?t=101246</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'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 Table.
//
// HOW TO USE IT :
// * Read the documentation and check the example in the demo map.
// CAREFULL, you can use all the GetLast... everywhere, but the other Get... ONLY in a trigger ACTION, NOT in a trigger CONDITION
library DRES initializer init uses Table
globals
public constant integer GOLD = 1
public constant integer LUMBER = 2
private constant real MAX = 1000000.0 // you should not edit this value, because it's simply the max possible of a resource
private constant real TIME_OUT = 1.0 // i think that's a good value, you shouldn't edit it, unless you perfectly know what you are doing
endglobals
globals // don't edit them
public playerstate Ple = null
private timer Tim = null
private integer Count = 1
private HandleTable GoldTable
private HandleTable LumberTable
private trigger Trig = null
endglobals
//! 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 struct s_$TYPE$
trigger trig
static method create takes trigger t returns s_$TYPE$
local s_$TYPE$ s = s_$TYPE$.allocate()
set s.trig = t
set $TYPE$Table[t] = s
return s
endmethod
method onDestroy takes nothing returns nothing
call $TYPE$Table.flush(.trig)
set .trig = null
endmethod
endstruct
private function $TYPE$Check takes nothing returns boolean
local player p = GetTriggerPlayer()
local integer ref
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
local s_$TYPE$ s
if GetEventPlayerState()!= PLAYER_STATE_RESOURCE_$NAME$ then
debug call BJDebugMsg("you tried to use the function Get$TYPE$Donor with a bad event")
return null
endif
set s = $TYPE$Table[GetTriggeringTrigger()]
if s.trig != GetTriggeringTrigger() then
debug call BJDebugMsg("you didn039;t use the function TriggerRegisterTrade to register the $TYPE$ trade")
return null
endif
return $TYPE$Donor
endfunction
function Get$TYPE$Receiver takes nothing returns player
local s_$TYPE$ s
if GetEventPlayerState() != PLAYER_STATE_RESOURCE_$NAME$ then
debug call BJDebugMsg("you tried to use the function Get$TYPE$Receiver with a bad event")
return null
endif
set s = $TYPE$Table[GetTriggeringTrigger()]
if s.trig != GetTriggeringTrigger() then
debug call BJDebugMsg("you didn039;t use the function TriggerRegisterTrade to register the $TYPE$ trade")
return null
endif
return $TYPE$Receiver
endfunction
function Get$TYPE$Deal takes nothing returns integer
local s_$TYPE$ s
if GetEventPlayerState() != PLAYER_STATE_RESOURCE_$NAME$ then
debug call BJDebugMsg("you tried to use the function Get$TYPE$Deal with a bad event")
return 0
endif
set s = $TYPE$Table[GetTriggeringTrigger()]
if s.trig != GetTriggeringTrigger() then
debug call BJDebugMsg("you didn039;t use the function TriggerRegisterTrade to register the $TYPE$ trade")
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("Gold","GOLD")
//! runtextmacro DRES_Resource("Lumber","LUMBER")
function TriggerRegisterTrade takes trigger t , force f , integer resourceType returns boolean
local s_Gold g
local s_Lumber l
if f == null then
debug call BJDebugMsg("the force taken in the function TriggerRegisterTrade is null")
return false
elseif t == null then
debug call BJDebugMsg("the trigger taken in the function TriggerRegisterTrade is null")
return false
endif
if resourceType == GOLD then
set g = GoldTable[t]
if g.trig == t then
debug call BJDebugMsg("You had already register a gold exchange for this trigger")
return false
endif
if g != 0 and g.trig != t then
call g.destroy()
endif
set g = g.create(t)
set Trig = t
call ForForce(f,function GoldForForce)
call TriggerAddCondition(t,Condition(function GoldCheck))
return true
elseif resourceType == LUMBER then
set l = LumberTable[t]
if l.trig == t then
debug call BJDebugMsg("You had already register a lumber exchange for this trigger")
return false
endif
if l != 0 and l.trig != t then
call l.destroy()
endif
set l = l.create(t)
set Trig = t
call ForForce(f,function LumberForForce)
call TriggerAddCondition(t,Condition(function LumberCheck))
return true
endif
debug call BJDebugMsg("the resourceType taken in the function TriggerRegisterTrade is invalid")
return false
endfunction
public function DestroyTriggerEx takes trigger t returns nothing
local s_Gold g = GoldTable[t]
local s_Lumber l = LumberTable[t]
if g != 0 then
call g.destroy()
endif
if l != 0 then
call l.destroy()
endif
call DestroyTrigger(t)
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'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
set Tim = CreateTimer()
call TimerStart(Tim,TIME_OUT,true,function TimeOut)
set GoldC = Condition(function GoldCheck)
set LumberC = Condition(function LumberCheck)
set GoldTable = HandleTable.create()
set LumberTable = HandleTable.create()
endfunction
endlibrary
Requires :
- JassHelper
- The JassNewGenPack with UMWSE enabled if you want to open the demo map
- the library Table
And this is the documentation you can copy/paste it in a deactivated jass trigger.
JASS:
// ~~ CHANGELOG
* v 2.1
- Changed the name of the custom function DestroyTrigger, now you must use DRES_DestroyTriggerEx, because you can039;t use
a native function name, even if you use the keyword public, my bad ...
* v 2.0
- Use the library Table instead of DataSystem, because we don039;t need the fastest way here.
And i had a bad idea of how the handles are recycled, so in the previous versions, they were leaks,
if you destroyed the DRES triggers. I039;ve added a custom function (DRES_DestroyTrigger) if you want destroy triggers which have trade events.
- Removed an unneeded creation trigger at the map init, and now the integer Count is increased when the timer expire ...
* v 1.3
- updated with the new library DataSystem
* v 1.2
- Fixed a bug, i used GetTriggerEventId() instead of GetEventPlayerState() without any compilation error ...
* v 1.1
- Renamed the function TriggerRegisterResourceExchange by this shorter name : TriggerRegisterTrade.
- Added a demo map.
* v 1.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 i039;ts completly friendly user, because :
~ you won039;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 it039;s not the right event.
~ added a texmacro for your trigger conditions.
~ added more debug messages.
* v 0.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.
* v 0.1
- Initial Release.
// ~~ HOW TO USE IT
I will comment the functions.
>>> Register function <<<
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 won039;t add it anyway, so just don039;t.
Now it039;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.
>>> Get functions <<<
The different Get return null if you try to use it with a bad event.
But ofc you can use the GetLast... anywhere.
CAREFULL, you CAN039;T use them in a trigger condition, just in a trigger action, because how the "system" was made.
But ofc all the GetLast... can be used in a trigger condition as well.
** 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.
//! Vexorian
- For his library Table.
Read the changelog for more infos.
EDIT : You must be at least 2 players to test it, it seems it's hardcoded in war3.