// CustomResources library requires:
// 1. Player Resources Monitoring ver 1.01
// https://www.hiveworkshop.com/threads/player-resource-monitoring-v1-01.276158/
// 2. GUI Unit Event by Bribe, version 2.4.0.0
// https://www.hiveworkshop.com/threads/gui-unit-event-v2-4-0-0.201641/
// 3. OrderList
// https://www.thehelper.net/threads/order-ids.148097/
// Installation:
// Copy&Paste unit "DummyTreeChecker" from demo-map. It should have abilities: 'Ahrl' 'Avul' 'Aloc'
// Copy&Paste destructable "DummyTree" from demo-map.
// Copy&Paste whole category "CustomResources" from demo-map.
// Configuration is done in "CustomResourcesConfig" trigger. There is nothing to configure here.
// Prepare 1 harvest ability for *each* custom resource (for normal lumber-also). Base it on 'Ahrl' "Harvest (Ghouls Lumber)"
// You must use diffrent harvest ability for each custom resource.
// Prepare workers (max99 for each resource), returning-structures (max99 for each resource) and
// destructables based on tree (max99 for each resource).
// All registered workers should have one harvest ability from this system set it in ObjectEditor.
// If worker is able to harvest more then 1 resource, then this ability you set in OE will be default (after training/creating).
// All registered Buildings must have ability "Return Lumber" 'Arlm' or "Return Gold and Lumber" 'Argl'
// You can use the same Worker(s) in many custom resources.
// You can use the same Building(s) in many custom resources.
// You -->cannot<-- use the same destructable in more then one custom resource.
// "ResourceWOOD" is obligatory trigger. It must exist. Define there all trees that will be harvest-able for lumber.
// Next triggers (4 in demo map) are examples. Edit them freely, add new triggers (as many as you want).
// Every trigger represents one resource. Follow instruction inside triggers.
// Example1: To have only 1 custom resource:
// Set ability/workers/structures/destructables in "ResourceWOOD" trigger
// Rename "ResourceMUSHROOMS", use "Resource_Number=2" and set ability/workers/structures/destructables.
// delete triggers "ResourceSTONES", "ResourceICEROCKS", "ResourcePlants".
// Example2: To have 5 custom resources:
// Edit existing triggers "ResourceWood/Mushrooms/Stones/Icerocks/Plants".
// Copy/paste "ResourcePLANTS" trigger. Rename it. Set "Resource_Number=5" and
// set ability/workers/structures/destructables inside this new trigger. Done.
// Available functions:
// AdjustPlayerCustomResource(player <p>, integer <resourceNumber>, integer <value>) returns nothing
// use negative <value> to subtract or positive to add resource
// GetPlayerCustomResource(player <p>, integer <resourceNumber>) returns integer
// <resourceNumber> is an integer used in configuration ResourceSOMENAME triggers in first line (Set Resource_Number = X)
// "Custom resource has been changed EVENT"
// use as event "Resource_Event" becomes equal to X (where X is Resource_Number defined in triggers "ResourceSOMENAME")
// variables available inside trigger: "Resource_Player" - owner whos resource nr X has been changed, value is: "Resource_Value" and
// "Resource_Number" - resource's number (defined in triggers "ResourceSOMENAME")
// Tip: in game, to change workers ability to harvest diffrent resource-type:
// right-click on resource (left-click and order "harvest" targeted on new destructable-type is blocked)
// Additionaly library "CustomResource" offers boolean variable that returns true for building under construction. Use like this:
// if udg_isBuildingUnderConstruction[Custom Value of Unit] then ...
library CustomResources initializer Init uses ORDER //v1.31 25-12-2017
globals
public hashtable g_hashCR
private integer array g_harvestAbility
public integer g_customResourcesCount=0
unit g_resourceUnitTreeChecker=null
private real array g_timeStampLastLumberRecived // [player id]
private integer array g_lastLumberRecivedValue // [player id]
private timer g_stopWorkerTimer = CreateTimer()
private timer g_gameTimer = CreateTimer()
private group g_workerToStopGroup = CreateGroup()
private group g_workerRedirectGroup = CreateGroup()
private timer g_workerRedirectTimer = CreateTimer()
private real array g_X // [GetUnitUserData(u)]
private real array g_Y // [GetUnitUserData(u)]
private integer array g_workerHarvestAbi // [GetUnitUserData(u)]
private unit g_closestStructure = null
private unit g_returningWorker = null
private real g_tempDistance2 = 0.00
private group array g_deliveryStructureGroup
private destructable array g_connectedDummyTree // [structure's UnitUserData]
public trigger g_trg_WorkerBringsResources = CreateTrigger()
private trigger g_trg_ResumeharvestingRedirect = CreateTrigger()
private trigger g_trg_DummyTreeDies = CreateTrigger()
//hashtable keys:
private constant integer KEY_100 = 100 // total workers quantity, connected with harvest ability (abilityId as a parentKey)
private constant integer KEY_200 = 200 // total destructables quantity, connected with harvest ability (abilityId as a parentKey)
private constant integer KEY_300 = 300 // total structures quantity, connected with harvest ability (abilityId as a parentKey)
private constant integer KEY_400 = 400 // for saving abilityId able to harvest given destructable (destructableId as parentKey)
private constant integer KEY_401 = 401 // for saving boolean, as a sign that destructable is registered (destructableId as parentKey)
private constant integer KEY_410 = 410 // for saving boolean, as a sign that worker is registered (workerId as parentKey)
private constant integer KEY_420 = 420 // for saving integer udg_Resource_Number set up at ResourceXXXXX triggers (abilityId as a parentKey)
private constant integer KEY_430 = 430 // for saving boolean, as a sign that structure is registered (structureId as parentKey)
private constant integer KEY_500 = 500 // for saving each players custom resource value (abilityId as a parentKey)
//used in "CustomResourcesCost" addon:
public constant integer KEY_600 = 600 // for saving prices, used as 600 + resourceNumber, (objectId as parentKey)
// remember resource2 cost at 602 key, resource3 at 603 key, .. etc
public constant integer KEY_601 = 601 // for saving boolean, as a sign that object is registered (objectId as parentKey)
endglobals
//=============================================================
function MsgD takes string s returns nothing //for developing mode messages
if udg_Resource_PrintMsgDeveloping then
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 10.00, s)
endif
endfunction
function Msg takes player p, string s returns nothing //warning messages
if udg_Resource_PrintWarnings then
call DisplayTextToPlayer(p, 0.00, 0.00, s)
endif
endfunction
private function OnConstruct_Start_Cond takes nothing returns boolean
set udg_isBuildingUnderConstruction[GetUnitUserData(GetConstructingStructure())]=true
return false
endfunction
private function OnConstruct_Finish_Cond takes nothing returns boolean
set udg_isBuildingUnderConstruction[GetUnitUserData(GetConstructedStructure())]=false
return false
endfunction
private function OnBuilding_Enters_Cond takes nothing returns boolean
if IsUnitType(udg_UDexUnits[udg_UDex], UNIT_TYPE_STRUCTURE) then
set udg_isBuildingUnderConstruction[udg_UDex]=false
endif
return false
endfunction
//=============================================================
private function InitSettingGUIVariables takes nothing returns nothing // run at init
local integer x=1
loop
exitwhen x>99
set udg_Resource_Worker[x]=0
set udg_Resource_Destructable[x]=0
set udg_Resource_Structure[x]=0
set x=x+1
endloop
endfunction
//---------------------------------------------------------------------------------------
private function InitResource_SaveWorkers takes nothing returns nothing
local integer x=1
loop
exitwhen udg_Resource_Worker[x]==0 or x>99
call SaveInteger(g_hashCR, udg_Resource_Ability, KEY_100+x, udg_Resource_Worker[x]) // remember 1st worker "id" at 101 key
call SaveBoolean(g_hashCR, udg_Resource_Worker[x], KEY_410, true) // save "true" as sign that worker is registered in this system
set x=x+1
endloop
// abilityId as a parentKey , KEY_420 -- abilityId Number (integer)
call SaveInteger(g_hashCR, udg_Resource_Ability, KEY_420, udg_Resource_Number)
//save total workers quantity at "100 key" for this ability
call SaveInteger(g_hashCR, udg_Resource_Ability, KEY_100, x-1)
//reset:
loop
exitwhen x==0
set udg_Resource_Worker[x]=0
set x=x-1
endloop
endfunction
//--------------------------------------------------------------------------------
private function InitResource_SaveDestructables takes nothing returns nothing
local integer x=1
loop
exitwhen udg_Resource_Destructable[x]==0 or x>99
call SaveInteger(g_hashCR, udg_Resource_Ability, KEY_200+x, udg_Resource_Destructable[x]) // remember 1st destruct at 201 key
call SaveInteger(g_hashCR, udg_Resource_Destructable[x], KEY_400, udg_Resource_Ability) // remember abiID to harvest this destr
call SaveBoolean(g_hashCR, udg_Resource_Destructable[x], KEY_401, true) // for IsDestructableRegistered
set x=x+1
endloop
//save total destructables quantity at "200 key" for this ability
call SaveInteger(g_hashCR, udg_Resource_Ability, KEY_200, x-1)
//reset:
loop
exitwhen x==0
set udg_Resource_Destructable[x]=0
set x=x-1
endloop
endfunction
//--------------------------------------------------------------------------------
private function InitResource_SaveStructures takes nothing returns nothing
local integer x=1
loop
exitwhen udg_Resource_Structure[x]==0 or x>99
call SaveInteger(g_hashCR, udg_Resource_Ability, KEY_300+x, udg_Resource_Structure[x]) // remember 1st structure at 301 key
call SaveBoolean(g_hashCR, udg_Resource_Structure[x], KEY_430, true) // saves boolean for registered structures
set x=x+1
endloop
//save total structures quantity at "300 key" for this ability
call SaveInteger(g_hashCR, udg_Resource_Ability, KEY_300, x-1)
//reset:
loop
exitwhen x==0
set udg_Resource_Structure[x]=0
set x=x-1
endloop
endfunction
//--------------------------------------------------------------------------------
function InitResource takes nothing returns nothing
set g_harvestAbility[udg_Resource_Number] = udg_Resource_Ability
if udg_Resource_Number > g_customResourcesCount then
set g_customResourcesCount = udg_Resource_Number
endif
set g_deliveryStructureGroup[udg_Resource_Number] = CreateGroup()
call InitResource_SaveWorkers()
call InitResource_SaveDestructables()
call InitResource_SaveStructures()
endfunction
//=============================================================
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
/*
HASHTABLE KEYS
KEY_100 -- workers quantity (abilityId as a parentKey)
101--199 - workers Id's (abilityId as a parentKey)
KEY_200 -- destructables quantity (abilityId as a parentKey)
201--299 - destructables Id's (abilityId as a parentKey)
KEY_300 -- structures quantity (abilityId as a parentKey)
301--399 - structures Id's (abilityId as a parentKey)
KEY_400 -- destructableId as parentKey --> remembers abilityId to harvest this destructabe
call SaveInteger(g_hashCR, destructableId, KEY_400, abiId) --> set abiId = LoadInteger(g_hashCR, destructableId, KEY_400)
KEY_401 -- destructableId as parentKey --> remembers boolean true as sign that destructabe is registered in system
call SaveBoolean(g_hashCR, destructableId, KEY_401, true) --> if LoadBoolean(g_hashCR, destructableId, KEY_401) then ...
KEY_410 -- workerId as parentKey -- > saves boolean true for registered workers in this system
call SaveBoolean(g_hashCR, workerId, KEY_410, true) --> if LoadBoolean(g_hashCR, workerId, KEY_410) then ...
abilityId as a parentKey
KEY_420 -- abilityId Number - integer: udg_Resource_Number (set up at ResourceXXXXX triggers by a user)
KEY_430 -- structureId as parentKey -- > saves boolean true for registered structures in this system
call SaveBoolean(g_hashCR, structureId, KEY_430, true) --> if LoadBoolean(g_hashCR, structureId, KEY_430) then ...
abilityId as a parentKey
KEY_500+playerId => 500 ..to.. 511 - each players resource value
//for Addon "CustomResourcesCost"
KEY_601 -- units/structure/research/upgradeBuilding/items ID as parentKey -- > saves boolean true for registered objects for prices purposes
call SaveBoolean(g_hashCR, objectId, KEY_601, true) --> if LoadBoolean(g_hashCR, objectId, KEY_601) then ...
KEY_600+resourceNumber => 602 .. and up for prices -- object ID as parent key
*/
//-------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------
function IsTree takes destructable d returns boolean
return (IssueTargetOrderById(g_resourceUnitTreeChecker, ORDER_harvest, d)) and (IssueImmediateOrderById(g_resourceUnitTreeChecker, ORDER_stop))
endfunction
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
// is harvest allowed by ability worker currently has:
//------------------------------------------------------------------------------------
private function IsHarvestAllowed takes unit u, integer destructableId returns boolean
local integer x=1
local integer abi = g_workerHarvestAbi[GetUnitUserData(u)] // ability unit has to harvest
local integer count = LoadInteger(g_hashCR, abi, KEY_200) // gives total number of destructables quantity at 200 key
loop
exitwhen x>count
if LoadInteger(g_hashCR, abi, KEY_200+x) == destructableId then
return true
endif
set x=x+1
endloop
return false
endfunction
//----------------------------------------------------------------------------------
// can worker change ability to new one
//----------------------------------------------------------------------------------
private function IsAbilityAllowedForWorker takes integer abi, integer workerId returns boolean
local integer x=1
local integer count = LoadInteger(g_hashCR, abi, KEY_100) // total number of workers at 100 key
loop
exitwhen x>count
if LoadInteger(g_hashCR, abi, KEY_100+x) == workerId then
return true
endif
set x=x+1
endloop
return false
endfunction
//----------------------------------------------------------------------------------
private function ChangeAbilityToHarvestDestructable takes unit u, integer destructableId returns boolean
local integer abi = LoadInteger(g_hashCR, destructableId, KEY_400) //-- > gives abiId able to harvest given destructable
local integer x=1
if abi>0 and IsAbilityAllowedForWorker(abi, GetUnitTypeId(u)) then //can unit have this abi?
call AddUnitAnimationProperties(u, "Lumber", false)
set g_workerHarvestAbi[GetUnitUserData(u)] = abi
loop //remove ALL other harvest abils
exitwhen x>g_customResourcesCount
call UnitRemoveAbility(u, g_harvestAbility[x])
set x=x+1
endloop
call UnitAddAbility(u, abi)
return true
endif
return false
endfunction
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
private function IsWorkerRegistered takes integer workerId returns boolean
return LoadBoolean(g_hashCR, workerId, KEY_410)
endfunction
//----------------------------------------------------------------------------------
private function IsDestructableRegistered takes integer destructableId returns boolean
return LoadBoolean(g_hashCR, destructableId, KEY_401)
endfunction
//----------------------------------------------------------------------------------
private function IsStructureRegistered takes integer structureId returns boolean
return LoadBoolean(g_hashCR, structureId, KEY_430)
endfunction
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
// returns udg_Resource_Number set up at ResourceXXXXX triggers by user
private function GetHarvestAbilityNumber takes integer workerCurentAbi returns integer
return LoadInteger(g_hashCR, workerCurentAbi, KEY_420)
endfunction
//-----------------------------------------------------------------------------------------------------------
//------------------------------DELIVERY STRUCTURES---------------------------------------------------
//-----------------------------------------------------------------------------------------------------------
private function RemoveDeliveryStructureFromAllGroups takes unit structure returns nothing
local integer c=1
loop //loop over all groups
exitwhen c>g_customResourcesCount
call GroupRemoveUnit(g_deliveryStructureGroup[c], structure)
set c=c+1
endloop
endfunction
//----------------------------------------------------------------------------------
private function AddDeliveryStructureToGroups takes unit structure returns nothing
local integer structureId = GetUnitTypeId(structure)
local integer abi
local integer count
local integer x
local integer c=1
loop //loop over all harvest abiliies
exitwhen c>g_customResourcesCount
//inside loop begin
set abi = g_harvestAbility[c]
set count = LoadInteger(g_hashCR, abi, KEY_300) // total number of structures for this abi (at 300 key)
set x=1
loop
exitwhen x>count
if LoadInteger(g_hashCR, abi, KEY_300+x) == structureId then
call GroupAddUnit(g_deliveryStructureGroup[c], structure)
endif
set x=x+1
endloop
//inside loop end
set c=c+1
endloop
endfunction
//----------------------------------------------------------------------------------
private function IsDeliveryStructureValid takes unit u, unit structure returns boolean
local integer abi = g_workerHarvestAbi[GetUnitUserData(u)] // current worker's ability to harvest
local integer nr = GetHarvestAbilityNumber(abi)
return IsUnitInGroup(structure, g_deliveryStructureGroup[nr])
endfunction
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//this not for a user:
private function AdjustPlayerCustomResource_ByAbility takes integer playerId, integer abi, integer value returns nothing
local integer resourceNr = GetHarvestAbilityNumber(abi)
local integer currentValue = LoadInteger(g_hashCR, abi, KEY_500+playerId)
local integer newValue = currentValue+value
if newValue<0 then //resource level cannot be negative
set newValue=0
endif
call SaveInteger(g_hashCR, abi, KEY_500+playerId, newValue)
// here FIRE EVENT (changed 22-12-2017)
set udg_Resource_Player = Player(playerId)
set udg_Resource_Value = value
set udg_Resource_Number = resourceNr
set udg_Resource_Event = 0.00
set udg_Resource_Event = I2R(resourceNr)
set udg_Resource_Event = 0.00
endfunction
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//for user: (use negative "value" to subtract or positive to add resource)
function AdjustPlayerCustomResource takes player p, integer resourceNumber, integer value returns nothing
call AdjustPlayerCustomResource_ByAbility(GetPlayerId(p), g_harvestAbility[resourceNumber], value)
endfunction
//----------------------------------------------------------------------------------
//for user:
function GetPlayerCustomResource takes player p, integer resourceNumber returns integer
local integer abi = g_harvestAbility[resourceNumber]
return LoadInteger(g_hashCR, abi, KEY_500+GetPlayerId(p))
endfunction
//===========================================================================
//===========================================================================
//-------------------------------TRIGGERS RELATED FUNCTIONS--------------------------------------------------------------
//===========================================================================
//===========================================================================
private function Trig_LumberChanged takes nothing returns nothing // "udg_PRM_EVENT", EQUAL, 2.00
local integer i = GetPlayerId(udg_PRM_Player)
if udg_PRM_Change > 0 then
//it fires as 1st, after this - "order harvest" (or other) runs
//remember time-stamp for this player and value:
set g_timeStampLastLumberRecived[i] = TimerGetElapsed(g_gameTimer)
set g_lastLumberRecivedValue[i] = udg_PRM_Change
call MsgD("(PRM) time stamp: " + R2S(TimerGetElapsed(g_gameTimer)) + ", " + GetPlayerName(udg_PRM_Player) + ", value: " + I2S(udg_PRM_Change))
endif
endfunction
//===========================================================================
// this is an EVENT "worker brings resources"
// we got unit "u", g_lastLumberRecivedValue[playerId], and g_workerHarvestAbi[GetunitUserData(u)] - integer abiId
private function Trig_WorkerBringsResources_Cond takes nothing returns boolean
//if peasant recive ANY order like: harvest dummyTree, harvest normal resources ,
//or player queued any order (stop, attack, move, etc) then:
if TimerGetElapsed(g_gameTimer) == g_timeStampLastLumberRecived[GetPlayerId(GetOwningPlayer(GetOrderedUnit()))] then
return IsWorkerRegistered(GetUnitTypeId(GetOrderedUnit()))
// ordered unit is 'last lumber supplier'
endif
return false
endfunction
//------------------------------------------------------------------------------------
private function Trig_WorkerBringsResources_Act takes nothing returns nothing
local unit u = GetOrderedUnit()
local player pla = GetOwningPlayer(u)
local integer i = GetPlayerId(pla)
local integer abi = g_workerHarvestAbi[GetUnitUserData(u)]
local integer resourceNr = GetHarvestAbilityNumber(abi) // new <---
if not (abi == g_harvestAbility[1]) then // it is *custom resource* - subtract from normal wood!
set udg_PRM_FireEvent = false
call SetPlayerState(pla, PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(pla, PLAYER_STATE_RESOURCE_LUMBER)-g_lastLumberRecivedValue[i])
set udg_PRM_FireEvent = true
call AdjustPlayerCustomResource_ByAbility(i, abi, g_lastLumberRecivedValue[i]) // writes value in hash (we're not writing "normal lumber")
call MsgD(GetUnitName(u) + " brings resource nr(" + I2S(resourceNr) +"), value: " + I2S(g_lastLumberRecivedValue[i]) + ", time stamp: " + R2S(TimerGetElapsed(g_gameTimer)))
endif //FIRE EVENT - MOVED 22-12-2017
set u=null
set pla=null
endfunction
//===========================================================================
private function StopWorker_Enum takes nothing returns nothing
call IssueImmediateOrderById(GetEnumUnit(), ORDER_stop)
call GroupRemoveUnit(g_workerToStopGroup, GetEnumUnit())
endfunction
private function StopWorker takes nothing returns nothing
call DisableTrigger(g_trg_WorkerBringsResources) // protect agains double fire "worker brings resource" event
call ForGroup(g_workerToStopGroup, function StopWorker_Enum)
call EnableTrigger(g_trg_WorkerBringsResources)
endfunction
//--------------------------------------------------------------------------------
private function Trig_HarvestSmartOffset_Cond takes nothing returns boolean
local integer ord=GetIssuedOrderId() // ORDER_OFFSET when building right-cick on destructable and trained worker start walking
if ord==ORDER_harvest or ord==ORDER_smart or ord==ORDER_OFFSET then // 851970
return GetOrderTargetDestructable() != null and IsWorkerRegistered(GetUnitTypeId(GetOrderedUnit()))
endif
return false
endfunction
//--------------------------------------------------------------------------------
private function Trig_HarvestSmartOffset_Act takes nothing returns nothing
local unit u = GetOrderedUnit()
local integer destructableId = GetDestructableTypeId(GetOrderTargetDestructable())
local integer ord = GetIssuedOrderId()
if ord==ORDER_harvest and (not IsHarvestAllowed(u, destructableId)) then
// does current ability allow to harvest this destr? if no, then stop worker
call GroupAddUnit(g_workerToStopGroup, u)
call TimerStart(g_stopWorkerTimer, 0.00, false, function StopWorker)
endif
// 851970 --> when worker trained with rally-point set up on tree
// 851970 or "smart" order --> need to change ability harvest for diffrent destructables
if (ord==ORDER_smart or ord==ORDER_OFFSET) and IsTree(GetOrderTargetDestructable()) then
if (not IsHarvestAllowed(u, destructableId)) then
if not ChangeAbilityToHarvestDestructable(u, destructableId) then
call Msg(GetOwningPlayer(u), GetUnitName(u) + " |cffff0000cannot|r harvest " + GetDestructableName(GetOrderTargetDestructable()))
call GroupAddUnit(g_workerToStopGroup, u)
call TimerStart(g_stopWorkerTimer, 0.00, false, function StopWorker)
endif
endif
endif
set u=null
endfunction
//---------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------
private function Trig_PointOrderHarvestSmartOffset_Cond takes nothing returns boolean
local integer ord=GetIssuedOrderId() // ORDER_OFFSET = 851970 when building right-cick on destructable and trained worker start walking
return (ord==ORDER_harvest or ord==ORDER_smart or ord==ORDER_OFFSET) and IsWorkerRegistered(GetUnitTypeId(GetOrderedUnit()))
endfunction
//---------------------------------------------------------------------------------------------------------------
private function RedirectWorker_Enum takes nothing returns nothing
call IssuePointOrder(GetEnumUnit(), "smart", g_X[GetUnitUserData(GetEnumUnit())], g_Y[GetUnitUserData(GetEnumUnit())]) //attack-move
call GroupRemoveUnit(g_workerRedirectGroup, GetEnumUnit())
endfunction
private function RedirectWorker takes nothing returns nothing
call ForGroup(g_workerRedirectGroup, function RedirectWorker_Enum)
endfunction
//------------------------------------
private function Trig_PointOrderHarvestSmartOffset_Act takes nothing returns nothing
local unit u=GetOrderedUnit()
if not IsVisibleToPlayer(GetOrderPointX(), GetOrderPointY(), GetOwningPlayer(u)) then
set g_X[GetUnitUserData(u)]=GetOrderPointX()
set g_Y[GetUnitUserData(u)]=GetOrderPointY()
call GroupAddUnit(g_workerRedirectGroup, u)
call TimerStart(g_workerRedirectTimer, 0.00, false, function RedirectWorker)
endif
set u=null
endfunction
//===========================================================================
private function FindClosestStructure_Enum takes nothing returns nothing
local unit u = GetEnumUnit()
local real dx = GetUnitX(g_returningWorker)-GetUnitX(u)
local real dy = GetUnitY(g_returningWorker)-GetUnitY(u)
local real dist2 = SquareRoot(dx * dx + dy * dy)
if GetOwningPlayer(u)==GetOwningPlayer(g_returningWorker) and (not udg_isBuildingUnderConstruction[GetUnitUserData(u)]) then
if dist2 < g_tempDistance2 then
set g_tempDistance2 = dist2
set g_closestStructure = u
endif
endif
set u=null
endfunction
//-----------------------------------------------------------------------------
private function FindClosestStructure takes unit worker returns nothing
local integer id = GetUnitUserData(worker)
local integer nr = GetHarvestAbilityNumber(g_workerHarvestAbi[id])
set g_tempDistance2 = 999999.00
set g_closestStructure = null
set g_returningWorker = worker
call ForGroup(g_deliveryStructureGroup[nr], function FindClosestStructure_Enum)
endfunction
//-----------------------------------------------------------------------------
private function Trig_ResumeharvestingRedirect_Cond takes nothing returns boolean
return GetIssuedOrderId()==ORDER_resumeharvesting and IsWorkerRegistered(GetUnitTypeId(GetOrderedUnit()))
endfunction
//-----------------------------------------------------------------------------
// when button "return resources" clicked OR auto come-back with resources
private function Trig_ResumeharvestingRedirect_Act takes nothing returns nothing
local unit u = GetOrderedUnit()
local integer id = GetUnitUserData(u)
call FindClosestStructure(u) // it writes global "g_closestStructure" as a valid building to deliver resources
if g_closestStructure != null then
call DisableTrigger(g_trg_ResumeharvestingRedirect) // this trigger
if IssueTargetOrderById(u, ORDER_resumeharvesting, g_closestStructure) then//and udg_Resource_PrintMsgDeveloping then
call MsgD("Redirecting " + GetUnitName(u) + " to " + GetUnitName(g_closestStructure))
endif
call EnableTrigger(g_trg_ResumeharvestingRedirect)
else //no valid structure..
call Msg(GetOwningPlayer(u), GetUnitName(u) + ": |cffffff00 No proper building found to return. |r")
call GroupAddUnit(g_workerToStopGroup, u)
call TimerStart(g_stopWorkerTimer, 0.00, false, function StopWorker)
endif
set u=null
endfunction
//===========================================================================
private function Trig_ReturnSmartRestrictions_Cond takes nothing returns boolean
if GetIssuedOrderId() == ORDER_smart then
if GetOrderTargetUnit() != null and IsWorkerRegistered(GetUnitTypeId(GetOrderedUnit())) then
return GetOwningPlayer(GetOrderedUnit()) == GetOwningPlayer(GetOrderTargetUnit())
endif
endif
return false
endfunction
//-------------------------------------------------------------------------------------
//if player give order "smart" on Worker and if building is not valid to take resources then convert smart-->move order
private function Trig_ReturnSmartRestrictions_Act takes nothing returns nothing
local unit u = GetOrderedUnit()
local unit target = GetOrderTargetUnit()
//check if worker is returning resources (it may also be order repair/finish construction)
call DisableTrigger(g_trg_ResumeharvestingRedirect)
if IssueTargetOrderById(u, ORDER_resumeharvesting, target) then //he has resources
if (not IsDeliveryStructureValid(u, target)) then
call IssueTargetOrderById(u, ORDER_move, target)
endif
endif
call EnableTrigger(g_trg_ResumeharvestingRedirect)
set u=null
set target=null
endfunction
//===========================================================================
private function Trig_WorkerStructureCreated_Cond takes nothing returns boolean
local integer unitId = GetUnitTypeId(udg_UDexUnits[udg_UDex])
return IsStructureRegistered(unitId) or IsWorkerRegistered(unitId)
endfunction
//------------------------------------------------------------------------------------
private function Trig_WorkerStructureCreated_Act takes nothing returns nothing
local integer x=1
local integer unitId = GetUnitTypeId(udg_UDexUnits[udg_UDex])
if IsStructureRegistered(unitId) then //BUILDING CREATED:
//find x/y for DummyTree : item (Wirt's Leg) version
set bj_lastCreatedItem = CreateItem('wtlg', GetUnitX(udg_UDexUnits[udg_UDex]), GetUnitY(udg_UDexUnits[udg_UDex]))
set g_connectedDummyTree[udg_UDex] = CreateDestructable(udg_Resource_DummyTree, GetItemX(bj_lastCreatedItem), GetItemY(bj_lastCreatedItem), 0.00, 1, 0)
call RemoveItem(bj_lastCreatedItem)
call TriggerRegisterDeathEvent(g_trg_DummyTreeDies, g_connectedDummyTree[udg_UDex]) //add event to DummyTreeDies
call AddDeliveryStructureToGroups(udg_UDexUnits[udg_UDex]) //add to delivery group
elseif IsWorkerRegistered(unitId) then //WORKER CREATED:
//------------------------------------------------------------------------------
// all registered workers should have one harvest ability from this system (set in OE)
//-----------------------------------------------------------------------------
loop
exitwhen x>g_customResourcesCount // loop over all harvest abilities and set variable
if GetUnitAbilityLevel(udg_UDexUnits[udg_UDex], g_harvestAbility[x])>0 then
set g_workerHarvestAbi[udg_UDex] = g_harvestAbility[x]
return
endif
set x=x+1
endloop
endif
endfunction
//===========================================================================
private function Trig_StructureUpgraded_Act takes nothing returns nothing // runs when structure *finishes* upgrade
call RemoveDeliveryStructureFromAllGroups(udg_UDexUnits[udg_UDex]) //remove from groups
if IsStructureRegistered(GetUnitTypeId(udg_UDexUnits[udg_UDex])) then // is upgraded building registered?
call AddDeliveryStructureToGroups(udg_UDexUnits[udg_UDex]) // add this new upgraded building
//if connected dummy TREE is dead/none (means previous structure was not registered)
if g_connectedDummyTree[udg_UDex]==null or GetDestructableLife(g_connectedDummyTree[udg_UDex]) <= 0 then
//find x/y for DummyTree : item version
set bj_lastCreatedItem = CreateItem('wtlg', GetUnitX(udg_UDexUnits[udg_UDex]), GetUnitY(udg_UDexUnits[udg_UDex]))
set g_connectedDummyTree[udg_UDex] = CreateDestructable(udg_Resource_DummyTree, GetItemX(bj_lastCreatedItem), GetItemY(bj_lastCreatedItem), 0.00, 1, 0)
call RemoveItem(bj_lastCreatedItem)
call TriggerRegisterDeathEvent(g_trg_DummyTreeDies, g_connectedDummyTree[udg_UDex]) //add event to DummyTreeDies
endif
else // New (upgraded) structure is not registered --> remove connected dummy TREE
call RemoveDestructable(g_connectedDummyTree[udg_UDex])
endif
endfunction
//===========================================================================
private function Trig_RegisteredStructureDies_Cond takes nothing returns boolean
if IsStructureRegistered(GetUnitTypeId(GetDyingUnit())) then
call RemoveDeliveryStructureFromAllGroups(GetDyingUnit()) //remove from all groups
call RemoveDestructable(g_connectedDummyTree[GetUnitUserData(GetDyingUnit())]) //remove connected dummy TREE
endif
return false
endfunction
//===========================================================================
private function Trig_DummyTreeDies_Actions takes nothing returns nothing
call DestructableRestoreLife(GetDyingDestructable(), GetDestructableMaxLife(GetDyingDestructable()), false) //resurect
endfunction
//===========================================================================
//===========================================================================
//===========================================================================
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i=0
loop
set g_timeStampLastLumberRecived[i] = 0.00
set i=i+1
exitwhen i==bj_MAX_PLAYERS //12
endloop
set udg_Resource_Event = 0.00
set g_hashCR = InitHashtable()
call TimerStart(g_gameTimer, 36000.00, false, null)
call InitSettingGUIVariables()
//moved to the trigger "CustomResourcesConfig"
//set udg_UnitIndexerEnabled = false
//set g_resourceUnitTreeChecker = CreateUnit(Player(15), udg_Resource_Dummy, 0.00, 0.00, 0.00)
//set udg_UnitIndexerEnabled = true
//call ShowUnit(g_resourceUnitTreeChecker, false)
//--------for udg_isBuildingUnderConstruction check [GetUnitUserData(u)] ------------
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_CONSTRUCT_START)
call TriggerAddCondition(t, Condition(function OnConstruct_Start_Cond))
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH)
call TriggerAddCondition(t, Condition(function OnConstruct_Finish_Cond))
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 1.00)
call TriggerAddCondition(t, Condition(function OnBuilding_Enters_Cond))
//----for lumber changed trigger -----------------------------------------------------
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_PRM_EVENT", EQUAL, 2.00)
call TriggerAddAction(t, function Trig_LumberChanged)
//-----------for worker-brings-resources event --------------------------------------
call TriggerRegisterAnyUnitEventBJ(g_trg_WorkerBringsResources, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
call TriggerRegisterAnyUnitEventBJ(g_trg_WorkerBringsResources, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
call TriggerRegisterAnyUnitEventBJ(g_trg_WorkerBringsResources, EVENT_PLAYER_UNIT_ISSUED_ORDER)
call TriggerAddCondition(g_trg_WorkerBringsResources, Condition(function Trig_WorkerBringsResources_Cond))
call TriggerAddAction(g_trg_WorkerBringsResources, function Trig_WorkerBringsResources_Act)
// ----------harvest destructable, orders: harvest/smart/offset ---------------------
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
call TriggerAddCondition(t, Condition(function Trig_HarvestSmartOffset_Cond))
call TriggerAddAction(t, function Trig_HarvestSmartOffset_Act)
// point order on destructable - if point not visible redirect order to "smart" to prevent auto-harvest on not-valid destructables
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
call TriggerAddCondition(t, Condition(function Trig_PointOrderHarvestSmartOffset_Cond))
call TriggerAddAction(t, function Trig_PointOrderHarvestSmartOffset_Act)
//------ for order resumeharvesting -> redirect -------------------------------------
call TriggerRegisterAnyUnitEventBJ(g_trg_ResumeharvestingRedirect, EVENT_PLAYER_UNIT_ISSUED_ORDER) // when button "return resources" clicked
call TriggerRegisterAnyUnitEventBJ(g_trg_ResumeharvestingRedirect, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER) // auto come-back
call TriggerAddCondition(g_trg_ResumeharvestingRedirect, Condition(function Trig_ResumeharvestingRedirect_Cond))
call TriggerAddAction(g_trg_ResumeharvestingRedirect, function Trig_ResumeharvestingRedirect_Act)
// if player give order "smart" on Worker and if building is not valid to take resources then convert smart-->move order
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
call TriggerAddCondition(t, Condition( function Trig_ReturnSmartRestrictions_Cond))
call TriggerAddAction(t, function Trig_ReturnSmartRestrictions_Act)
// worker / building created -----------------------------------------------------------
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 1.00)
call TriggerAddCondition(t, Condition( function Trig_WorkerStructureCreated_Cond))
call TriggerAddAction(t, function Trig_WorkerStructureCreated_Act)
// building transformed (upgraded) ---------------------------------------------------
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitTypeEvent", EQUAL, 1.00)
call TriggerAddAction(t, function Trig_StructureUpgraded_Act)
// building dies ------------------------------------------------------------------------
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
call TriggerAddCondition(t, Condition( function Trig_RegisteredStructureDies_Cond))
// dummy tree dies -------------------------------------------------------------------
set g_trg_DummyTreeDies = CreateTrigger()
call TriggerAddAction(g_trg_DummyTreeDies, function Trig_DummyTreeDies_Actions)
call MsgD("Init in library CS finished succefully")
set t=null
endfunction
endlibrary