• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[General] Capturable Resource Point

Status
Not open for further replies.
Level 3
Joined
Apr 9, 2015
Messages
27
While working on my map, I realized I need a Circle of Power that can be captured(stepped upon, maybe for a few seconds to prevent "stealing") to passively grant gold and lumber periodically to whoever captured it and sets a cooldown so no other player can capture it for a while. How do I write the triggers for that?



You can find my map development thread here
 
Last edited:
Level 19
Joined
Oct 7, 2014
Messages
2,209
That is similar to mine. You could use an event - A unit enters a region
Maybe you could check if someone already occupies the circle of power. I couldn't think of a way to make a cooldown. Then change the ownership to the player. Make a variable where you can save the amount of circle of power a player owns.
I suggest to make a timer and whenever the timer ends it will give each player gold and lumber by the number of captured cities.
 
Level 21
Joined
Nov 4, 2013
Messages
2,017
Create a Unit variable called CapturingUnit then do the following:

  • Capture Resource Point
  • Events
    • Unit - A unit enters (Capture Region)
  • Conditions
    • (Owner of (Entering Unit)) Not equal to (Owner of (Circle of Power))
  • Actions
    • Trigger - Turn off (This Trigger)
    • Set CapturingUnit = (Entering Unit)
    • Wait 5.00 seconds
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • (Capture Region) contains CapturingUnit
        • (CapturingUnit is alive) Equal to True
      • Then - Actions
        • Unit - Change ownership of Circle of Power to (Owner of CapturingUnit) and Change color
        • Wait (The cooldown time you want)
        • Trigger - Turn on (This Trigger)
      • Else - Actions
        • Trigger - Turn on (This Trigger)
Remove all leaks then.
 
Level 3
Joined
Apr 9, 2015
Messages
27
Create a Unit variable called CapturingUnit then do the following:

  • Capture Resource Point
  • Events
    • Unit - A unit enters (Capture Region)
  • Conditions
    • (Owner of (Entering Unit)) Not equal to (Owner of (Circle of Power))
  • Actions
    • Trigger - Turn off (This Trigger)
    • Set CapturingUnit = (Entering Unit)
    • Wait 5.00 seconds
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • (Capture Region) contains CapturingUnit
        • (CapturingUnit is alive) Equal to True
      • Then - Actions
        • Unit - Change ownership of Circle of Power to (Owner of CapturingUnit) and Change color
        • Wait (The cooldown time you want)
        • Trigger - Turn on (This Trigger)
      • Else - Actions
        • Trigger - Turn on (This Trigger)
Remove all leaks then.

Thank you! I'll try it out
 
Level 3
Joined
Apr 9, 2015
Messages
27
@Shadow Fury
Remove the Turn on from ITE and add it below ITE instead.
It might bug because the Entering Unit is global, thus it's possible to be overwritten throughout the wait and cause issues.
Turning it into locals will easily solve it, though I would go with timers instead.

Could you post your take on the trigger here please? I am always eager to learn better ways to write triggers.
 
Level 21
Joined
Nov 4, 2013
Messages
2,017
@Shadow Fury
Remove the Turn on from ITE and add it below ITE instead.
It might bug because the Entering Unit is global, thus it's possible to be overwritten throughout the wait and cause issues.
Turning it into locals will easily solve it, though I would go with timers instead.

Putting Turn On trigger below ITE would cause the bug. If the unit is trying to capture the circle of power and I put Turn On below ITE, then the "cooldown time" would be totally useless.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
  • Wait 5.00 seconds
AAAAAAA IT HURTS MY EYES!

Please NEVER use the wait action like that.

I would do it different.
Make a loop for every 0.03 seconds of gametime.
Pick every unit in region and check if they all belong to the same player/team.
If so, you give the control point a stack and you give it a variable which is the team or player number.
When the stacks reach 5/0.03 = 166.7, you lock the control point by giving it a third variable... the duration.
In that same trigger, you check if the control point is locked and if so, you reduce the duration by 0.03.
When the duration falls below 0, you unlock it again.

When there are units of multiple players/teams in the region, you reduce the stacks, or when a unit of a different player/team is in the region... the same.
 
Level 21
Joined
Nov 4, 2013
Messages
2,017
Make a loop for every 0.03 seconds of gametime.
Pick every unit in region and check if they all belong to the same player/team.
If so, you give the control point a stack and you give it a variable which is the team or player number.
When the stacks reach 5/0.03 = 166.7, you lock the control point by giving it a third variable... the duration.
In that same trigger, you check if the control point is locked and if so, you reduce the duration by 0.03.
When the duration falls below 0, you unlock it again.

When there are units of multiple players/teams in the region, you reduce the stacks, or when a unit of a different player/team is in the region... the same.

This sounds so complicated and harder to make leakless. What's wrong with wait actions? Do they leak heavily or something similar?
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Well... "Wait ... seconds of game-time" leaks a local handle... which is not really a big problem because you won't use it in massive loops.
But anyway, the solution is to simple replace all "Wait ... seconds of game-time" with "Custom Script: call WaitTimer(...)" after you put this in the header file:
JASS:
function WaitTimer takes real duration returns nothing
    local timer t
    local real  timeRemaining

    if duration > 0 then
        set t = CreateTimer()
        call TimerStart(t, duration, false, null)
        loop
            set timeRemaining = TimerGetRemaining(t)
            exitwhen timeRemaining <= 0
            
            if timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD then
                call TriggerSleepAction(0.1 * timeRemaining)
            else
                call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
            endif
        endloop
        call DestroyTimer(t)
        set t = null
    endif
endfunction

But you don't use a "Wait ... seconds of game-time" but a "Wait ... seconds".
The difference is that the second one does NOT use game-time. Instead it uses REAL time.
So if you start that cooldown, then put the game on pause for that duration, then unpause the game... that wait has ended already!
That is not even counting game speed.
If game speed is different than 1:1, you will have a problem as well.

And last but not least, both are inacurrate.
Both have a delay of 0.05 to 0.267 seconds.
So your 5 seconds wait is actually 5.05 to 5.267 seconds... imagine that delay on 0.03 waits which become 0.08 to 0.270!
 
Level 21
Joined
Nov 4, 2013
Messages
2,017
But you don't use a "Wait ... seconds of game-time" but a "Wait ... seconds".
The difference is that the second one does NOT use game-time. Instead it uses REAL time.
So if you start that cooldown, then put the game on pause for that duration, then unpause the game... that wait has ended already!
That is not even counting game speed.
If game speed is different than 1:1, you will have a problem as well.

And last but not least, both are inacurrate.
Both have a delay of 0.05 to 0.267 seconds.
So your 5 seconds wait is actually 5.05 to 5.267 seconds... imagine that delay on 0.03 waits which become 0.08 to 0.270!

These delay numbers are almost insignificant. You won't even feel 0.08 to 0.270 seconds. As long as such accuracy is not required, a wait action is the simplest solution.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
But still when pausing or stuff happens... your control point is ruined.
At least use the custom script and put that jass code in the header of all your maps.
I can't make it easier for you.

About the trigger... there are a few flaws about control points when multiple units of different teams enter the region and stuff.
My solution is simply how I think about capture points... the same how the altars are set up in the Twisted Treeline in League of Legends.
 
Level 21
Joined
Nov 4, 2013
Messages
2,017
But still when pausing or stuff happens... your control point is ruined.
At least use the custom script and put that jass code in the header of all your maps.
I can't make it easier for you.

About the trigger... there are a few flaws about control points when multiple units of different teams enter the region and stuff.
My solution is simply how I think about capture points... the same how the altars are set up in the Twisted Treeline in League of Legends.

Well, I have almost no knowledge on custom scripts so I'll not argue about this. Anyway, the trigger should work well. I turned off the trigger to prevent such things like "multiple units of different teams going to the circle of power" to bug the whole thing.
 
Level 3
Joined
Apr 9, 2015
Messages
27
But still when pausing or stuff happens... your control point is ruined.
At least use the custom script and put that jass code in the header of all your maps.
I can't make it easier for you.

About the trigger... there are a few flaws about control points when multiple units of different teams enter the region and stuff.
My solution is simply how I think about capture points... the same how the altars are set up in the Twisted Treeline in League of Legends.

Yes! Exactly, that's the kind of resource point I'm looking for. However, I am not experienced with custom scripts. Is there a easier way or a way to do this in the Trigger Editor?
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Well... the trigger posted by Shadow Fury is for example not interrupted by enemy units entering the region.
That is the thing why I don't support that solution in the first place.

What I am suggesting is this:
  • Give Stacks
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer TempInteger) from 0 to Altar_Amount, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Altar_IsLocked[TempInteger] Equal to True
            • Then - Actions
              • Set Altar_Stacks[TempInteger] = (Altar_Stacks[TempInteger] - 0.03)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Altar_Stacks[TempInteger] Less than or equal to 0.00
                • Then - Actions
                  • Set Altar_IsLocked[TempInteger] = False
                  • Set Altar_Stacks[TempInteger] = 0.00
                  • Set Altar_Owner[TempInteger] = 0
                • Else - Actions
            • Else - Actions
              • Set TempLocation = (Position of Altar[TempInteger])
              • Custom script: set bj_wantDestroyGroup = true
              • Unit Group - Pick every unit in (Units within 512.00 of TempLocation) and do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Altar_IsLocked[TempInteger] Equal to False
                    • Then - Actions
                      • Set TempUnit = (Picked unit)
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (TempUnit is A Hero) Equal to True
                        • Then - Actions
                          • Set Altar_Stacks[TempInteger] = (Altar_Stacks[TempInteger] + 0.03)
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • Altar_Stacks[TempInteger] Greater than or equal to 5.00
                            • Then - Actions
                              • Set Altar_Owner[TempInteger] = (Player number of (Owner of TempUnit))
                              • Set Altar_Stacks[TempInteger] = 90.00
                              • Set Altar_IsLocked[TempInteger] = True
                            • Else - Actions
                        • Else - Actions
                    • Else - Actions
              • Custom script: call RemoveLocation(udg_TempLocation)
With this, it takes 5 seconds to capture the altar (when you are on your own).
When you are with 3 people on the altar at the same time, it only takes 5/3=1.7 seconds.
This trigger does not completely work... as enemy heroes wont be reducing your stacks on it etc.
But this is a little thing to begin with...
I am currently on a map making run and want this one to be finished asap.
I hope you can finish the trigger from here on your own.
 
Level 3
Joined
Apr 9, 2015
Messages
27
Well... the trigger posted by Shadow Fury is for example not interrupted by enemy units entering the region.
That is the thing why I don't support that solution in the first place.

What I am suggesting is this:
  • Give Stacks
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer TempInteger) from 0 to Altar_Amount, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Altar_IsLocked[TempInteger] Equal to True
            • Then - Actions
              • Set Altar_Stacks[TempInteger] = (Altar_Stacks[TempInteger] - 0.03)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Altar_Stacks[TempInteger] Less than or equal to 0.00
                • Then - Actions
                  • Set Altar_IsLocked[TempInteger] = False
                  • Set Altar_Stacks[TempInteger] = 0.00
                  • Set Altar_Owner[TempInteger] = 0
                • Else - Actions
            • Else - Actions
              • Set TempLocation = (Position of Altar[TempInteger])
              • Custom script: set bj_wantDestroyGroup = true
              • Unit Group - Pick every unit in (Units within 512.00 of TempLocation) and do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Altar_IsLocked[TempInteger] Equal to False
                    • Then - Actions
                      • Set TempUnit = (Picked unit)
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (TempUnit is A Hero) Equal to True
                        • Then - Actions
                          • Set Altar_Stacks[TempInteger] = (Altar_Stacks[TempInteger] + 0.03)
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • Altar_Stacks[TempInteger] Greater than or equal to 5.00
                            • Then - Actions
                              • Set Altar_Owner[TempInteger] = (Player number of (Owner of TempUnit))
                              • Set Altar_Stacks[TempInteger] = 90.00
                              • Set Altar_IsLocked[TempInteger] = True
                            • Else - Actions
                        • Else - Actions
                    • Else - Actions
              • Custom script: call RemoveLocation(udg_TempLocation)
With this, it takes 5 seconds to capture the altar (when you are on your own).
When you are with 3 people on the altar at the same time, it only takes 5/3=1.7 seconds.
This trigger does not completely work... as enemy heroes wont be reducing your stacks on it etc.
But this is a little thing to begin with...
I am currently on a map making run and want this one to be finished asap.
I hope you can finish the trigger from here on your own.

I really do not wish to disturb you further, but I have next to no experience with custom scripts or variables. I'll try my best to replicate what you have here though.
 
Status
Not open for further replies.
Top