• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Custom ResourcesCost

This bundle is marked as awaiting update. A staff member has requested changes to it before it can be approved.
Custom Resources Cost - an addon for Custom Resources 1.20

Allows to define custom cost for units training, upgrade structures, build structures and researches.

With this addon instaled "Resource_Event" will fire:
  • upon resource delivery by worker
  • when order is issued to train/build/upgrade structure/research
  • when you cancel train/build/upgrade structure/research
so this event is like an indicator "resource has been changed"
Use as real variable "Resource_Event" becomes equal to X, where X is Resource_Number defined in triggers "ResourceNAME". Variables available inside trigger: "Resource_Player" - owner who's resource X changed, value is: "Resource_Value" (positive or negative)

library
JASS:
//=========================================================
library CustomResourcesCosts initializer Init uses CustomResources

//------------------------------------------------------------------------------------------------
globals
    private constant boolean    PRINT_WARNING = true
    private group                       g_groupCancel = CreateGroup()
    private timer                        g_timerCancel = CreateTimer()
    private integer array           g_upgradeTarget
    private constant string        GREEN = "|cff00ff00"
    private constant string        RED = "|cffff0000" 
    trigger                     g_triggerMultiOrderCancel = CreateTrigger()
endglobals
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
/*
   //for Addon
    601 -- units/structure/research/upgradeBuilding ID as parentKey -- >
    saves boolean true for registered objects for prices purposes
    call SaveBoolean(g_hashCR, objectId, 601, true)
    if LoadBoolean(g_hashCR, objectId, 601) then ...
    602 .. and up - for prices -- object ID as parent key
*/

function CustomResource_SaveCosts takes nothing returns nothing
    local integer x=2 // we do not start from "1" as 1 is normal-wood
    local integer parentKey
    //is it object or research?
    if udg_Resource_CostUnit>0 then
        set parentKey = udg_Resource_CostUnit
    elseif udg_Resource_CostResearch>0 then
        set parentKey = udg_Resource_CostResearch
    endif
 
    call SaveBoolean(CustomResources_g_hashCR, parentKey, 601, true) // save "true" as sign that object is registered
    loop
        exitwhen x>CustomResources_g_customResourcesCount
        call SaveInteger(CustomResources_g_hashCR, parentKey, 600+x, udg_Resource_Cost[x])
        // remember resource2 cost at 602 key, resource3 at 603 key, .. etc
        //reset for next object:
        set udg_Resource_Cost[x] = 0
        set x=x+1
    endloop 
    //reset integers:
    set udg_Resource_CostUnit = 0
    set udg_Resource_CostResearch = 0 
endfunction
//------------------------------------------------------------------------------------------------
function IsCustomCostDefined takes integer objectId returns boolean // object: unit/structure/upgrade-building/research
    return LoadBoolean(CustomResources_g_hashCR, objectId, 601)
endfunction
//------------------------------------------------------------------------------------------------
function GetObjectCost takes integer objectId, integer resourceNumber returns integer
    // resourceNumber = defined in ResourceMUSHROOM and so on triggers, as udg_Resource_Number
    // will not return value for resourceNumber=1 as it is normal war3 wood!
    return LoadInteger(CustomResources_g_hashCR, objectId, 600+resourceNumber)
endfunction



//=========================================================
//------------------------TRIGGERS  RELATED---------------------------------------------------
//=========================================================

//------------------------------------------------------------------------------
function CancelOrder_Enum takes nothing returns nothing
    local unit u = GetEnumUnit()
    call GroupRemoveUnit(g_groupCancel, u)
    call IssueImmediateOrderById(u, 851976) //upgrades , researches , trains
    call IssueImmediateOrderById(u, ORDER_stop) //for builders
    set u=null
endfunction

function CancelOrder takes nothing returns nothing
    call DisableTrigger(g_triggerMultiOrderCancel)
    call ForGroup(g_groupCancel, function CancelOrder_Enum)
    call EnableTrigger(g_triggerMultiOrderCancel)     
endfunction

function UnitCancelOrder takes unit u returns nothing
    call GroupAddUnit(g_groupCancel, u)
    call TimerStart(g_timerCancel, 0.00, false, function CancelOrder)
endfunction
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
function PlayerHasMoneyForObject takes player pla, integer objectId returns boolean
    local integer x=2
    local integer cost=0
    local string s = " "
    local boolean hasMoney = true
    loop
        exitwhen x>CustomResources_g_customResourcesCount
        set cost = GetObjectCost(objectId, x)
        if cost>0 then
            if cost <= GetPlayerCustomResource(pla, x) then
                set s = s + (GREEN+udg_Resource_Name[x] + "|r(" + I2S(cost) + ") ") // green color
            else // not enough resource nr x
                set hasMoney=false
                set s = s + (RED+udg_Resource_Name[x] + "|r(" + I2S(cost) + ") ") // red color
            endif
        endif
        set x=x+1
    endloop
 
    if (not hasMoney) and PRINT_WARNING then
        call DisplayTextToPlayer(pla, 0.00, 0.00, "Not enough resources: " + s)
    endif
    return hasMoney
endfunction
//-------------------------------------------------------------------------------------------
function PlayerPayPriceForObject takes player pla, integer objectId returns nothing
    local integer x=2
    local integer cost=0
    loop
        exitwhen x>CustomResources_g_customResourcesCount
        set cost = GetObjectCost(objectId, x)
        if cost>0 then
            call AdjustPlayerCustomResource(pla, x, - cost)
            //event
            set udg_Resource_Player = pla
            set udg_Resource_Value = -cost
            set udg_Resource_Event = 0.00
            set udg_Resource_Event = I2R(x)
            set udg_Resource_Event = 0.00
            set udg_Resource_Player = null
            set udg_Resource_Value = 0
        endif
        set x=x+1
    endloop
endfunction
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
function Trig_MultiOrder_Cond takes nothing returns boolean
    return IsCustomCostDefined(GetIssuedOrderId())
endfunction
//------------------------------------------------------------------------------
function Trig_MultiOrder_Act takes nothing returns nothing
    local integer h = GetHandleId(GetTriggerEventId())
    local unit u = GetOrderedUnit()
    local player pla = GetOwningPlayer(u)
    local integer ord = GetIssuedOrderId()
    local integer id = GetUnitUserData(u)
 
    if h==38 then // instant: TRAIN  UNIT or RESEARCH or UPGRADE
            //call BJDebugMsg("cost2: " + I2S(GetObjectCost(ord, 2)) + ", cost3: " + I2S(GetObjectCost(ord, 3)) + ", cost4: " + I2S(GetObjectCost(ord, 4)))
            if not PlayerHasMoneyForObject(pla, ord) then //no $$$ ?
                call UnitCancelOrder(u)
            else //has $?, pay price:
                set g_upgradeTarget[id] = ord //if it is UPGRADE save target-building (ord) as variable under number id
                call PlayerPayPriceForObject(pla, ord)
            endif
 
    elseif h==39 and (UnitId2String(ord) != null) then // point-order: BUILD  STRUCTURE
            //call BJDebugMsg("cost2: " + I2S(GetObjectCost(ord, 2)) + ", cost3: " + I2S(GetObjectCost(ord, 3)) + ", cost4: " + I2S(GetObjectCost(ord, 4)))
            if not PlayerHasMoneyForObject(pla, ord) then //no $$$ ?
                call UnitCancelOrder(u)
            endif // paying is executed under event EVENT_PLAYER_UNIT_CONSTRUCT_START
    endif
 
    set u=null
    set pla=null
endfunction

//----------------------------------------------------------------------------------
//---------------------------trigger Begins Construction -------------------------
//----------------------------------------------------------------------------------
function Trig_BeginsConstr_Cond takes nothing returns boolean              
    return IsCustomCostDefined(GetUnitTypeId(GetConstructingStructure()))
endfunction
//------------------------------------------------------------------
function Trig_BeginsConstr_Act takes nothing returns nothing
    local unit u = GetConstructingStructure()
    local player pla = GetOwningPlayer(u)
    local integer objectId = GetUnitTypeId(u)
    if not PlayerHasMoneyForObject(pla, objectId) then //no $$$ ?
        call UnitCancelOrder(u)     
    else //has $?, pay price:
        call PlayerPayPriceForObject(pla, objectId)
    endif
    set u=null
    set pla=null
endfunction

//---------------------------------------------------------------------------------------------
// --------------------------trigger CANCEL--------------------------------------------------
//---------------------------------------------------------------------------------------------
private function GiveMoneyBackOnCancel takes player pla, integer objectId returns nothing
    local integer x=2
    local integer cost=0
    loop
        exitwhen x>CustomResources_g_customResourcesCount
        set cost = GetObjectCost(objectId, x)
        call AdjustPlayerCustomResource(pla, x, cost)
        //event
        set udg_Resource_Player = pla
        set udg_Resource_Value = cost
        set udg_Resource_Event = 0.00
        set udg_Resource_Event = I2R(x)
        set udg_Resource_Event = 0.00
        set udg_Resource_Player = null
        set udg_Resource_Value = 0

        set x=x+1
    endloop
endfunction
//---------------------------------------------------------------------------------------------
private function Trig_MultiOrderCancel_Actions takes nothing returns nothing
    local integer h = GetHandleId(GetTriggerEventId()) 
    local unit u = GetTriggerUnit() // the same for all 4 events
    local player pla = GetOwningPlayer(u) // the same for all 4 events
    local integer objectId
    //---------------------------------------------------------------------------
    if h==33 then // EVENT_PLAYER_UNIT_TRAIN_CANCEL
        set objectId = GetTrainedUnitType()
        if IsCustomCostDefined(objectId) then
            call GiveMoneyBackOnCancel(pla, objectId)
            //call DisplayTextToForce( GetPlayersAll(), GetUnitName(u) + " canceled custom-cost TRAIN" )
        endif     
    //---------------------------------------------------------------------------
    elseif h==27 then // EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL
        set objectId = GetUnitTypeId(u)
        if IsCustomCostDefined(objectId) then
            call GiveMoneyBackOnCancel(pla, objectId)
            //call DisplayTextToForce( GetPlayersAll(), "canceled custom-cost BUILD" )
        endif
    //---------------------------------------------------------------------------
    elseif h==36 then // EVENT_PLAYER_UNIT_RESEARCH_CANCEL
        set objectId = GetResearched()
        if IsCustomCostDefined(objectId) then
            call GiveMoneyBackOnCancel(pla, objectId)
            //call DisplayTextToForce( GetPlayersAll(), "canceled custom-cost research" )
        endif
    //---------------------------------------------------------------------------
    elseif h==30 then // EVENT_PLAYER_UNIT_UPGRADE_CANCEL
        set objectId = g_upgradeTarget[GetUnitUserData(u)] // upgrade TARGET building
                                                                        // (gives Keep - if Keep cancels upgrade and revert itself to TownHall)
        if IsCustomCostDefined(objectId) then
            call GiveMoneyBackOnCancel(pla, objectId)
            //call DisplayTextToForce( GetPlayersAll(), "canceled custom-cost upgrade-building" )
        endif
    //--------------------------------------------------------------------------- 
    endif
    set u=null
    set pla=null
endfunction
//=========================================================
//=========================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_ISSUED_ORDER )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
    call TriggerAddCondition( t, Condition(function Trig_MultiOrder_Cond))
    call TriggerAddAction( t, function Trig_MultiOrder_Act )
 
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_CONSTRUCT_START )
    call TriggerAddCondition( t, Condition( function Trig_BeginsConstr_Cond ) )
    call TriggerAddAction( t, function Trig_BeginsConstr_Act )

    call TriggerRegisterAnyUnitEventBJ( g_triggerMultiOrderCancel, EVENT_PLAYER_UNIT_TRAIN_CANCEL )
    call TriggerRegisterAnyUnitEventBJ( g_triggerMultiOrderCancel, EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL )
    call TriggerRegisterAnyUnitEventBJ( g_triggerMultiOrderCancel, EVENT_PLAYER_UNIT_RESEARCH_CANCEL )
    call TriggerRegisterAnyUnitEventBJ( g_triggerMultiOrderCancel, EVENT_PLAYER_UNIT_UPGRADE_CANCEL )
    call TriggerAddAction( g_triggerMultiOrderCancel, function Trig_MultiOrderCancel_Actions )

    set t=null
endfunction

endlibrary

configuration trigger
  • ResourceCost
    • Events
      • Game - UnitIndexEvent becomes Equal to -1.00
    • Conditions
    • Actions
      • -------- UPGRADE --------
      • Set Resource_CostUnit = Keep
      • Set Resource_Cost[3] = 2
      • -------- Resource_Cost[3] refers to "stones" defines in ResourceNAME triggers, number 3 = strones --------
      • -------- Do not use number "1" as it is normal warcraft3 "lumber" --------
      • Set Resource_Cost[4] = 4
      • Custom script: call CustomResource_SaveCosts()
      • -------- ---------------------------- --------
      • -------- RESEARCH --------
      • Set Resource_CostResearch = Iron Forged Swords
      • Set Resource_Cost[2] = 3
      • Set Resource_Cost[3] = 7
      • Custom script: call CustomResource_SaveCosts()
      • -------- ---------------------------- --------
      • -------- UNIT TRAIN --------
      • Set Resource_CostUnit = Peasant
      • Set Resource_Cost[3] = 1
      • Set Resource_Cost[5] = 1
      • Custom script: call CustomResource_SaveCosts()
      • -------- ---------------------------- --------
      • Set Resource_CostUnit = Footman
      • Set Resource_Cost[5] = 2
      • Custom script: call CustomResource_SaveCosts()
      • -------- ---------------------------- --------
      • -------- BUILD STRUCTURE --------
      • Set Resource_CostUnit = Farm
      • Set Resource_Cost[2] = 9
      • Set Resource_Cost[3] = 3
      • Set Resource_Cost[4] = 10
      • Custom script: call CustomResource_SaveCosts()
update: event "Reource_Event" works with this addon
Contents

Custom ResourcesCost (Map)

Reviews
Dr Super Good
This resource is pending update due to the low standard of the demonstration map. The demonstration map provided does not show off the system at all well. Although the system does appear to work, one only finds that out after reading through the...
Level 11
Joined
Mar 31, 2016
Messages
657
you remember that you got map-specific changes in Custom Resources system?

this addon fires event "Reource_Event" whenever resource X has been changed, (so you can update gold based on this event)

Yeah I remember you made some changes to my map.

Uhh, ok - how do I do that? Why is it breaking the harvest system (I implemented all the new triggers)?
EDIT: I examined everything you're telling me to do and I'm still having bugs.
Can you please provide a thoroughly detailed tutorial or can I just send you my map again?
 
Last edited:
Level 11
Joined
Mar 31, 2016
Messages
657
Having trouble setting Upgrades with multiple levels - the 1st level is easily selected, however idk how to select a higher level for the upgrade.
Example, upgrade: Sword (1) has 5 levels, Sword (1) is selectable for the trigger. Sword (2+) however does not appear, nor is there is option for levels (that I see).


Any solutions?
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,190
This resource is pending update due to the low standard of the demonstration map.
The demonstration map provided does not show off the system at all well. Although the system does appear to work, one only finds that out after reading through the triggers to understand what is meant to happen.

The map presents the player with far too many build, train and research choices, of which only 5 in total use the system and can be easily overlooked. Additionally the Tiny Farm, the only obvious choice, cannot be built without modifying the map as the map does not have enough of the required custom resource on it to build. It also appears bugged as the item gets destroyed if not enough custom resources are available instead of refunded to inventory as one would expect.

I recommend adding a lot more custom resource sites (so there is an excess of available resources) to the map. Also streamline player choices to mostly ones that require custom resources so it is easy for the player to encounter and get involved with the system. It might help to create some permanent floating text hints above resources suggesting how to harvest them or at least emphasizing what resource it is.

There seems to be liberal use of magic numbers and hard coded constants scattered around. Generally it is recommended to assign these numbers to named constants for readability and maintainability.
 
Top