• 🏆 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!

How to create this alternative gold and wood gain system.

Status
Not open for further replies.
Level 6
Joined
Jul 8, 2018
Messages
129
So I'm trying to create that gold and wood system you find in Azeroth wars were you destroy this thing and it gives you gold and wood every x amount of time. I've looked around and I'm not too sure how to create a thing like that. What I want to be able to do is that when you destroy this thing it will switch to your side and every minute gold and lumber is added based on the amount of these you have. I don't know if I'm being dumb or anything like that so anyone able to help?
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,010
  • Events
    • Unit - A unit dies
  • Conditions
    • (Unit-type of (Triggering Unit)) equal to YOUR_UNIT
  • Actions
    • Unit - Set life of (triggering unit) to 100%
    • Unit - Change owner of (Triggering Unit) to (Owner of (Killing Unit))
  • Events
    • Time - Every 60.00 seconds of game-time
  • Conditions
  • Actions
    • Custom script: set bj_wantDestroyGroup = true //cleans the group leak in the next line
    • Unit Group - Pick every unit in (Units of type YOUR_UNIT) and do (Actions)
      • Loop - Actions
        • Player - Add GOLD_PER_UNIT to (Owner of (Picked Unit)) current gold
        • Player - Add LUMBER_PER_UNIT to (Owner of (Picked Unit)) current lumber
If the resources should go to you and all players you're allied with do this instead:

  • Events
    • Time - Every 60.00 seconds of game-time
  • Conditions
  • Actions
    • For each (Integer A) from 1 to MAX_PLAYER_NUMBER do (Actions)
      • Loop - Actions
        • Set GoldBonus[(Integer A)] = 0
        • Set LumberBonus[(Integer A)] = 0
    • Custom script: set bj_wantDestroyGroup = true //cleans the group leak in the next line
    • Unit Group - Pick every unit in (Units of type YOUR_UNIT) and do (Actions)
      • Loop - Actions
        • Set GoldBonus[Player Number of (Owner of (Picked Unit))] = GoldBonus[Player Number of (Owner of (Picked Unit))] + GOLD_PER_UNIT
        • Set LumberBonus[Player Number of (Owner of (Picked Unit))] = LumberBonus[Player Number of (Owner of (Picked Unit))] + LUMBER_PER_UNIT
    • Player Group - Pick every player in (All Players) and do (Actions)
      • Loop - Actions
        • Set AllyForce = All allies of (Picked Player)
        • Set PNum = Player number of (Picked Player)
        • Player Group - Pick every player in AllyForce and do (Actions)
          • Loop - Actions
            • Player - Add GoldBonus[PNum] to (Picked Player) current gold
            • Player - Add LumberBonus[PNum] to (Picked Player) current lumber
        • Custom script: call DestroyForce(udg_AllyForce) //cleans the player group leak, change the variable name to match your variable but keep the udg_ prefix
 
  • Events
    • Unit - A unit dies
  • Conditions
    • (Unit-type of (Triggering Unit)) equal to YOUR_UNIT
  • Actions
    • Unit - Set life of (triggering unit) to 100%
    • Unit - Change owner of (Triggering Unit) to (Owner of (Killing Unit))
I'm pretty sure that doesn't work.
If you want to preserve the unit, use a unit takes damage event, otherwise just replace the dying unit.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,197
Azeroth wars worked by giving the players some multiple of their free food...

Any way if it is based on capture point ownership the idea is to periodically give them wood and gold for every capture point they own. If capture points are worth different amounts, one can use a set of arrays working as a list to store data for all capture points. One then iterates through the list of capture points and adds the associated gold/wood to the owner.
 
Level 39
Joined
Feb 27, 2007
Messages
5,010
Ohh my bad. I'll change it to take damage then
You'll need a Damage Detection System for this, if you are not aware.
Hey pyro I don't know how to exactly get that second one to work where you add the gold to a player...
It's called Player - Add Property.
I'm pretty sure that doesn't work.
Didn't test, so I expect you're right. The replace unit function technically leaks 2 or 3 local variable references, so I would recommend not using it in large quantities.
JASS:
function ReplaceUnitBJ takes unit whichUnit, integer newUnitId, integer unitStateMethod returns unit
    local unit    oldUnit = whichUnit //not nulled
    local unit    newUnit //leaked via return
    local boolean wasHidden
    local integer index
    local item    indexItem //not nulled if item slot 6 is occupied
    local real    oldRatio

   // If we have bogus data, don't attempt the replace.
    if (oldUnit == null) then
        set bj_lastReplacedUnit = oldUnit
        return oldUnit
    endif

   // Hide the original unit.
    set wasHidden = IsUnitHidden(oldUnit)
    call ShowUnit(oldUnit, false)

   // Create the replacement unit.
    if (newUnitId == 'ugol') then
        set newUnit = CreateBlightedGoldmine(GetOwningPlayer(oldUnit), GetUnitX(oldUnit), GetUnitY(oldUnit), GetUnitFacing(oldUnit))
    else
        set newUnit = CreateUnit(GetOwningPlayer(oldUnit), newUnitId, GetUnitX(oldUnit), GetUnitY(oldUnit), GetUnitFacing(oldUnit))
    endif

   // Set the unit's life and mana according to the requested method.
    if (unitStateMethod == bj_UNIT_STATE_METHOD_RELATIVE) then
       // Set the replacement's current/max life ratio to that of the old unit.
       // If both units have mana, do the same for mana.
        if (GetUnitState(oldUnit, UNIT_STATE_MAX_LIFE) > 0) then
            set oldRatio = GetUnitState(oldUnit, UNIT_STATE_LIFE) / GetUnitState(oldUnit, UNIT_STATE_MAX_LIFE)
            call SetUnitState(newUnit, UNIT_STATE_LIFE, oldRatio * GetUnitState(newUnit, UNIT_STATE_MAX_LIFE))
        endif

        if (GetUnitState(oldUnit, UNIT_STATE_MAX_MANA) > 0) and (GetUnitState(newUnit, UNIT_STATE_MAX_MANA) > 0) then
            set oldRatio = GetUnitState(oldUnit, UNIT_STATE_MANA) / GetUnitState(oldUnit, UNIT_STATE_MAX_MANA)
            call SetUnitState(newUnit, UNIT_STATE_MANA, oldRatio * GetUnitState(newUnit, UNIT_STATE_MAX_MANA))
        endif
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_ABSOLUTE) then
       // Set the replacement's current life to that of the old unit.
       // If the new unit has mana, do the same for mana.
        call SetUnitState(newUnit, UNIT_STATE_LIFE, GetUnitState(oldUnit, UNIT_STATE_LIFE))
        if (GetUnitState(newUnit, UNIT_STATE_MAX_MANA) > 0) then
            call SetUnitState(newUnit, UNIT_STATE_MANA, GetUnitState(oldUnit, UNIT_STATE_MANA))
        endif
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_DEFAULTS) then
       // The newly created unit should already have default life and mana.
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_MAXIMUM) then
       // Use max life and mana.
        call SetUnitState(newUnit, UNIT_STATE_LIFE, GetUnitState(newUnit, UNIT_STATE_MAX_LIFE))
        call SetUnitState(newUnit, UNIT_STATE_MANA, GetUnitState(newUnit, UNIT_STATE_MAX_MANA))
    else
       // Unrecognized unit state method - ignore the request.
    endif

   // Mirror properties of the old unit onto the new unit.
   //call PauseUnit(newUnit, IsUnitPaused(oldUnit))
    call SetResourceAmount(newUnit, GetResourceAmount(oldUnit))

   // If both the old and new units are heroes, handle their hero info.
    if (IsUnitType(oldUnit, UNIT_TYPE_HERO) and IsUnitType(newUnit, UNIT_TYPE_HERO)) then
        call SetHeroXP(newUnit, GetHeroXP(oldUnit), false)

        set index = 0
        loop
            set indexItem = UnitItemInSlot(oldUnit, index)
            if (indexItem != null) then
                call UnitRemoveItem(oldUnit, indexItem)
                call UnitAddItem(newUnit, indexItem)
            endif

            set index = index + 1
            exitwhen index >= bj_MAX_INVENTORY
        endloop
    endif

   // Remove or kill the original unit.  It is sometimes unsafe to remove
   // hidden units, so kill the original unit if it was previously hidden.
    if wasHidden then
        call KillUnit(oldUnit)
        call RemoveUnit(oldUnit)
    else
        call RemoveUnit(oldUnit)
    endif

    set bj_lastReplacedUnit = newUnit
    return newUnit
endfunction
 
You'll need a Damage Detection System for this, if you are not aware.
Not necessarily.
Assuming all the control points are pre-placed in the editor, he could just do something like this:
  • UnitDamaged
    • Events
    • Conditions
      • ((Life of (Triggering unit)) - (Damage taken)) Less than 1.00
    • Actions
      • Event Response - Set Damage of Unit Damaged Event to 0.00
      • Unit - Set life of (Triggering unit) to 100.00%
      • Unit - Change ownership of (Triggering unit) to (Owner of (Damage source)) and Change color
  • UnitDamagedInit
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Unit Group - Pick every unit in (Units of type <Unit Type>) and do (Actions)
        • Loop - Actions
          • Trigger - Add to UnitDamaged <gen> the event (Unit - (Picked unit) Takes damage)
The replace unit function technically leaks 2 or 3 local variable references, so I would recommend not using it in large quantities.
So does every Blizzard.j unit group getter function. I wouldn't worry about local agent reference leaks for GUI users.

  • Events
    • Time - Every 60.00 seconds of game-time
  • Conditions
  • Actions
    • Custom script: set bj_wantDestroyGroup = true //cleans the group leak in the next line
    • Unit Group - Pick every unit in (Units of type YOUR_UNIT) and do (Actions)
      • Loop - Actions
        • Player - Add GOLD_PER_UNIT to (Owner of (Picked Unit)) current gold
        • Player - Add LUMBER_PER_UNIT to (Owner of (Picked Unit)) current lumber
Forgot to mention, bj_wantDestroyGroup will not work with the function Units Of Type:
JASS:
function GetUnitsOfTypeIdAll takes integer unitid returns group
    local group   result = CreateGroup() // While on the topic of
    local group   g      = CreateGroup() // local agent reference leaks...
    local integer index

    set index = 0
    loop
        set bj_groupEnumTypeId = unitid
        call GroupClear(g)
        call GroupEnumUnitsOfPlayer(g, Player(index), filterGetUnitsOfTypeIdAll)
        call GroupAddGroup(g, result)

        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    call DestroyGroup(g)

    return result
endfunction
JASS:
function GroupAddGroup takes group sourceGroup, group destGroup returns nothing
    // If the user wants the group destroyed, remember that fact and clear
    // the flag, in case it is used again in the callback.
    local boolean wantDestroy = bj_wantDestroyGroup
    set bj_wantDestroyGroup = false

    set bj_groupAddGroupDest = destGroup
    call ForGroup(sourceGroup, function GroupAddGroupEnum)

    // If the user wants the group destroyed, do so now.
    if (wantDestroy) then
        call DestroyGroup(sourceGroup)
    endif
endfunction
 
Level 39
Joined
Feb 27, 2007
Messages
5,010
Well fuck me that lack of wantDestroy support might rank up there with dumbest Blizzard.j decisions. In fact it borks the whole process by destroying the internal player unit group used in the loop prematurely. Thanks.
 
Status
Not open for further replies.
Top