Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

How to create cooldowns (how to use settimer) in twine harlowe 2.0

For the last week I've been creating a twine rpg game and one of the features I really want to include are skills each skill having a cooldown for it, its not like you press the skill and then it gets a cooldown not it has to start with a cooldown say 30 secs for e.g I want it to let the users wait 30 secs before they can use it and once they do the process repeats but I don't even have the slightest idea how to do so

Comments

  • Do you mean 30 seconds of Game time or Real World time?

    Will the Reader be able to navigate between Passages during this time or will they be stuck within the same Passage until the cool-down period is over?
  • greyelf wrote: »
    Do you mean 30 seconds of Game time or Real World time?

    Will the Reader be able to navigate between Passages during this time or will they be stuck within the same Passage until the cool-down period is over?
    stuck in the same passage till he/she beats the enemy then the timer resets, and real world time not game time

  • You can use the (live:) macro to simulate a cool-down, it works as long as the Reader does not leave the current Passage.
    (live: 30s)[
    	... The code you want to happen after a 30 seconds delay ...
    	(stop:)
    ]
    
    ... the (stop:) macro is needed so that the timer event only occurs once.
  • greyelf wrote: »
    You can use the (live:) macro to simulate a cool-down, it works as long as the Reader does not leave the current Passage.
    (live: 30s)[
    	... The code you want to happen after a 30 seconds delay ...
    	(stop:)
    ]
    
    ... the (stop:) macro is needed so that the timer event only occurs once.

    I will give it a shot but I want to also show the time so players can see how much time is remaining till they can use it again basically I'm basing my game to a game I enjoyed alot (swords and souls) and I don't want to do that, that the link will appear every certain amount of time and if they players don't click it they missed their chance and will have to wait again
  • edited August 2016
    greyelf wrote: »
    You can use the (live:) macro to simulate a cool-down, it works as long as the Reader does not leave the current Passage.
    (live: 30s)[
    	... The code you want to happen after a 30 seconds delay ...
    	(stop:)
    ]
    
    ... the (stop:) macro is needed so that the timer event only occurs once.
    yep it doesn't want to work for some reason and the link shows up once for a split second with an error I don't know really, I'm trying to make it so that when the timer is done the user must click it manually for the timer to reset, if xe doesn't it just waits for them to do so, it's driving me crazy, here is what I wrote, I made it so you can test it:
    (set: $hp to 10000)
    (set: $ghoul_hp to 10000)
    (if: (either: 0, 1) is 0)[  
     (set: $hp to $hp - $damage1) (set: $damage1 to (either:0,0.25,1,2,3,4,5,25)*5)
      (if: $hp < 1)[ [[uh-oh did you die->You barely escape]]]  
      (else:)[ Your health is $hp. 
        (live: 1s)[(goto: "fight")] 
        [[Leave that bitch alone and report to the mayor->main]]]  
    (set: $counter to 0)
    (live:20 s)[(set: $counter to it + 1)(set: $var to it + 1)(if: $counter is 100)[(link:"Use Dragon Punch")[(set:$ghoul_hp= $ghoul_hp- (5*5))](stop:)]]] 
        
    (else:)[(set:$ghoul_hp = $ghoul_hp - $damageh)(set: $damageh to (either:0,0.25,1,2,3,4,5,25)*5) 
      (if: $ghoul_hp < 1)[ [[What..What the hell are you]]]  
      (else:)[    
        Its health is $ghoul_hp.
        (live: 1s)[(goto: "fight")] 
        [[Leave that bitch alone and report to the mayor->main]]]  
    (set: $counter to 0)
    (live:20 s)[(set: $counter to it + 1)(set: $var to it + 1)(if: $counter is 100)[(link:"Use Dragon Punch")[(set:$ghoul_hp= $ghoul_hp- (5*5))](stop:)]]]
    
  • note: I am going to assume that the passage in your example is named fight, based on the (go-to:) macros in your code.

    A couple of thoughts about your example:

    1. You have a space character between the 20 and the time unit (s = seconds) in two of your (live:) macros, which is invalid.

    2. Unless something dies you are using a delayed (go-to:) macro to traverse to the fight passage (the current passage?), this means that the 20 second (live:) macros will never fire because they are destroyed during the traversal.

    3. 100 x 20 seconds is 33 and a bit minutes, which is a long time to wait for a link to use a Dragon Punch.

    4. Reloading a passage over and over in a Twine based game is a very expensive activity in both time and memory, because each time a passage is traversed a copy of all known variables is made and that new copy is made available to the passage about to be shown/processed.
  • edited August 2016
    ya its called fight I applied some fixes still not working but error is gone, sadly reloading the passage is way it has to go I can't afford creating a passage for every battle since the number of battle is random number and I will be forced to create 10s maybe even 100s of passages so I have to reload it basically, so if there's a way to transverse live macro please tell me anyway the newer version is this:
    (set: $hp to 10000)
    (set: $ghoul_hp to 10000)
    (if: (either: 0, 1) is 0)[  
     (set: $hp to $hp - $damage1) (set: $damage1 to (either:0,0.25,1,2,3,4,5,25)*5)
      (if: $hp < 1)[ [[uh-oh did you die->You barely escape]]]  
      (else:)[ Your health is $hp. 
        (live: 1s)[(goto: "fight")] 
        [[Leave that bitch alone and report to the mayor->main]]]  
    (set: $counter to 0)
    (live:20s)[(set: $counter to it + 1)(set: $var to it + 1)[(link:"Use Dragon Punch")[(set:$ghoul_hp= $ghoul_hp- (5*5))](if: $counter is 100)(stop:)]]] 
        
    (else:)[(set:$ghoul_hp = $ghoul_hp - $damageh)(set: $damageh to (either:0,0.25,1,2,3,4,5,25)*5) 
      (if: $ghoul_hp < 1)[ [[What..What the hell are you]]]  
      (else:)[    
        Its health is $ghoul_hp.
        (live: 1s)[(goto: "fight")] 
        [[Leave that bitch alone and report to the mayor->main]]]  
    (set: $counter to 0)
    (live:20s)[(set: $counter to it + 1)(set: $var to it + 1)[(link:"Use Dragon Punch")[(set:$ghoul_hp= $ghoul_hp- (5*5))](if: $counter is 100)(stop:)]]]
    
  • Try something like the following, it uses a single (live:) macro to implement an execution loop (common technique used in action games) that handles:

    1. Checking the different conditions that stop the execution loop / fight.
    eg. death, returning to main passage, fight taking to long (Run Away), etc...

    2. Updating the interface (status and options).

    3. Combat between player and ghoul.

    4. Cool-down of Dragon Punch

    The following consists of at least two passages:

    1. The Main passage:
    {
    <!-- Setup the fighters health before the fight starts. -->
    (set: $playerHP to 10000)
    (set: $ghoulHP to 10000)
    
    }\
    [[Start Fight->Fight]]
    
    2. The Fight passage:
    {
    <!-- Initialise important variables. -->\
    (set: $runAway to false)
    (set: $goMain to false)
    (set: $elapsedTime to 0)
    
    }\
    <!-- User interface area. -->\
    status: |status>[]
    
    options:
    |menu>[(link: "Run Away!")[(set: $runAway to true)]
    |action>[]
    |punch>[]
    ]
    {
    <!-- Game logic area. -->
    (live: 1s)[{
    	(set: $elapsedTime to it + 1)
    	<!-- Check for reasons to stop fight. -->
    	(if: $runAway)[
    		(stop:)
    		(replace: ?status)[You chicken out and run away!]
    		(replace: ?menu)[ [[Return to main passage->Main]]]
    	](else-if: $goMain)[
    		(stop:)
    		(go-to: "Main")
    	](else-if: $playerHP < 1)[
    		(stop:)
    		(replace: ?menu)[ [[uh-oh did you die->You barely escape]]]
    	] (else-if: $ghoulHP < 1)[
    		(stop:)
    		(replace: ?menu)[ [[What..What the hell are you]]]
    	]
    
    	<!-- Randomly choose who attacks who. -->
    	(if: (either: 0, 1) is 0)[
    		<!-- The Player. -->
    		(set: $damage to ((either: 0,0.25,1,2,3,4,5,25) * 5))
    		(set: $playerHP to it - $damage)
    		(if: $playerHP >= 1)[
    			(replace: ?status)[Your health is $playerHP]
    			(replace: ?action)[{
    				(link: "Leave that bitch alone and report to the mayor")[(set: $goMain to true)]
    			}]
    		]
    	](else:)[
    		<!-- The Ghoul. -->
    		(set: $damage to ((either: 0,0.25,1,2,3,4,5,25) * 5))
    		(set: $ghoulHP to it - $damage)
    		(if: $ghoulHP >= 1)[
    			(replace: ?status)[Its health is $ghoulHP]
    			(replace: ?action)[
    				(link: "Leave that bitch alone and report to the mayor")[(set: $goMain to true)]]
    		]
    	]
    	<!-- Check cooldown of potion by determining if the Elapsed Time is a multiple of 20. -->
    	(if: $elapsedTime % 20 is 0)[
    		(replace: ?punch)[{
    			(link: "Use Dragon Punch")[
    				(set: $ghoulHP to it - 25)
    			]
    		}]
    	]
    }]
    }
    
    ... you will notice that everything happens within this passage and that this passage is never reloaded using a (go-to:) macro.
  • edited August 2016
    greyelf wrote: »
    Try something like the following, it uses a single (live:) macro to implement an execution loop (common technique used in action games) that handles:

    1. Checking the different conditions that stop the execution loop / fight.
    eg. death, returning to main passage, fight taking to long (Run Away), etc...

    2. Updating the interface (status and options).

    3. Combat between player and ghoul.

    4. Cool-down of Dragon Punch

    The following consists of at least two passages:

    1. The Main passage:
    {
    <!-- Setup the fighters health before the fight starts. -->
    (set: $playerHP to 10000)
    (set: $ghoulHP to 10000)
    
    }\
    [[Start Fight->Fight]]
    
    2. The Fight passage:
    {
    <!-- Initialise important variables. -->\
    (set: $runAway to false)
    (set: $goMain to false)
    (set: $elapsedTime to 0)
    
    }\
    <!-- User interface area. -->\
    status: |status>[]
    
    options:
    |menu>[(link: "Run Away!")[(set: $runAway to true)]
    |action>[]
    |punch>[]
    ]
    {
    <!-- Game logic area. -->
    (live: 1s)[{
    	(set: $elapsedTime to it + 1)
    	<!-- Check for reasons to stop fight. -->
    	(if: $runAway)[
    		(stop:)
    		(replace: ?status)[You chicken out and run away!]
    		(replace: ?menu)[ [[Return to main passage->Main]]]
    	](else-if: $goMain)[
    		(stop:)
    		(go-to: "Main")
    	](else-if: $playerHP < 1)[
    		(stop:)
    		(replace: ?menu)[ [[uh-oh did you die->You barely escape]]]
    	] (else-if: $ghoulHP < 1)[
    		(stop:)
    		(replace: ?menu)[ [[What..What the hell are you]]]
    	]
    
    	<!-- Randomly choose who attacks who. -->
    	(if: (either: 0, 1) is 0)[
    		<!-- The Player. -->
    		(set: $damage to ((either: 0,0.25,1,2,3,4,5,25) * 5))
    		(set: $playerHP to it - $damage)
    		(if: $playerHP >= 1)[
    			(replace: ?status)[Your health is $playerHP]
    			(replace: ?action)[{
    				(link: "Leave that bitch alone and report to the mayor")[(set: $goMain to true)]
    			}]
    		]
    	](else:)[
    		<!-- The Ghoul. -->
    		(set: $damage to ((either: 0,0.25,1,2,3,4,5,25) * 5))
    		(set: $ghoulHP to it - $damage)
    		(if: $ghoulHP >= 1)[
    			(replace: ?status)[Its health is $ghoulHP]
    			(replace: ?action)[
    				(link: "Leave that bitch alone and report to the mayor")[(set: $goMain to true)]]
    		]
    	]
    	<!-- Check cooldown of potion by determining if the Elapsed Time is a multiple of 20. -->
    	(if: $elapsedTime % 20 is 0)[
    		(replace: ?punch)[{
    			(link: "Use Dragon Punch")[
    				(set: $ghoulHP to it - 25)
    			]
    		}]
    	]
    }]
    }
    
    ... you will notice that everything happens within this passage and that this passage is never reloaded using a (go-to:) macro.
    will give it a shot hopefully it will work
    Edit: yep its working now I just have to edit a bit with it and I'll able t add more abilities and potions thanks alot dude :blush: though if you know a way to show how much time is remaining for an ability that would be great
  • edited August 2016
    I was able to tinker with it and add new abilities, I will add more, but I still don't know how to correctly use a consumable like an attack potion. I tried creating a separate timer for the potion that will reset when pressed, and for 10s will increase $AM (which is an attack multiplier) from 1 to 5 and then after the 10s it will return to 1 but the problem is that it's stuck at one tried everything but it's still stuck at freaking one:
    {
    \
    (set: $runAway to false)
    (set: $goMain to false)
    (set: $elapsedTime to 0)
    (set: $elapsedTimep to 0)
    (set: $AM to 1)
    }\
    \
    status: |status>[]
    
    options:
    |menu>[(link: "Run Away!")[(set: $runAway to true)]
    |action>[]
    |punch>[]
    |punch2>[]
    |potion>[]
    ]
    {
    (live: 1s)[{
    	(set: $elapsedTime to it + 1)(set: $elapsedTimep to it +1)
    	(if: $runAway)[
    		(stop:)
    		(replace: ?status)[You chicken out and run away!]
    		(replace: ?menu)[ [[Return to main passage->Main]]]
    	](else-if: $goMain)[
    		(stop:)
    		(go-to: "Main")
    	](else-if: $playerHP < 1)[
    		(stop:)
    		(replace: ?menu)[ [[uh-oh did you die->You barely escape]]]
    	] (else-if: $ghoulHP < 1)[
    		(stop:)
    		(replace: ?menu)[ [[What..What the hell are you]]]
    	]
    
    	(if: (either: 0, 1) is 0)[
    		<!-- The Player. -->
    		(set: $damage to ((either: 0,0.25,1,2,3,4,5,25) * 5))
    		(set: $playerHP to it - $damage)
    		(if: $playerHP >= 1)[
    			(replace: ?status)[Your health is $playerHP]
    			(replace: ?action)[{
    				(link: "Leave that bitch alone and report to the mayor")[(set: $goMain to true)]
    			}]
    		]
    	](else:)[
    		<!-- The Ghoul. -->
    		(set: $damage to ((either: 0,0.25,1,2,3,4,5,25) * 5))
    		(set: $ghoulHP to it - $damage*$AM)
    		(if: $ghoulHP >= 1)[
    			(replace: ?status)[Its health is $ghoulHP]
    			(replace: ?action)[
    				(link: "Leave that bitch alone and report to the mayor")[(set: $goMain to true)]]
    		]
    	]
    		(if: $elapsedTime % 20 is 0)[
    		(replace: ?punch)[{
    			(link: "Use Dragon Punch")[
    				(set: $ghoulHP to it - 25)
    			]
    		}]
    				](if: $elapsedTime % 10 is 0)[
    		(replace: ?punch2)[{
    			(link: "Use Fireball")[
    				(set: $ghoulHP to it - 25)
    				]
    		}]](replace: ?potion)[{(link: "Use attack potion")[(replace: ?status)[Your attack is $AM] (set: $elapsedTimep to 0) (if: $elapsedTimep is < 10s)[(set: $AM to 5)] (else:)[(set: $AM to 1)]]
    		}]
    }]
    }
    
  • Some suggestions:

    1. Use variables named and hook names that describe their purpose, don't uses names like punch2 or AM because you may forget what they represent latter.

    2. Use indentation and extra line-breaks to format your code (especially when debugging it) as it can help you see syntax errors like leaving out square brackets.

    3. If your code is complex (like this will be) add comments to the code to help remember what each part is doing.

    Your new potion related code is replacing the potion link for every loop.

    Try something like the following, it uses three new variables ($showFireballAt, $showPunchAt, and $showPotionAt) to track at which second in the future options or cool-downs should changed, the value of each of the three variables is recalculated each time the related option is used. I also changed the user interface a little.
    {
    <!-- Initialise important variables. -->\
    (set: $runAway to false)
    (set: $goMain to false)
    (set: $elapsedTime to 0)
    (set: $attackModifier to 1)
    
    (set: $showFireballAt to 10)
    (set: $showPunchAt to 20)
    (set: $showPotionAt to 1)
    }\
    <!-- User interface area. -->\
    ''Round'': |round>[]
    ''Status'': |status>[
    Your health is |player>[$playerHP]
    Its health is |ghoul>[$ghoulHP]
    
    Attack Modifier: |buff>[$attackModifier]]
    
    options:
    |menu>[(link: "Run Away!")[(set: $runAway to true)]
    |action>[]
    |fireball>[]
    |punch>[]
    |potion>[]
    ]
    {
    <!-- Game logic area. -->
    (live: 1s)[{
    	(set: $elapsedTime to it + 1)
    	(replace: ?round)[$elapsedTime]
    
    	<!-- Check for reasons to stop fight. -->
    	(if: $runAway)[
    		(stop:)
    		(replace: ?status)[You chicken out and run away!]
    		(replace: ?menu)[ [[Return to main passage->Main]]]
    	](else-if: $goMain)[
    		(stop:)
    		(go-to: "Main")
    	](else-if: $playerHP < 1)[
    		(stop:)
    		(replace: ?menu)[ [[uh-oh did you die->You barely escape]]]
    	] (else-if: $ghoulHP < 1)[
    		(stop:)
    		(replace: ?menu)[ [[What..What the hell are you]]]
    	]
    
    	<!-- Randomly choose who attacks who. -->
    	(if: (random: 1,2) is 1)[
    		<!-- Hit the Player. -->
    		(set: $damage to ((either: 0,0.25,1,2,3,4,5,25) * 5))
    		(set: $playerHP to it - $damage)
    		(if: $playerHP >= 1)[
    			(replace: ?player)[$playerHP]
    			(replace: ?action)[{
    				(link: "Leave that bitch alone and report to the mayor")[(set: $goMain to true)]
    			}]
    		]
    	](else:)[
    		<!-- Hit the Ghoul. -->
    		(set: $damage to ((either: 0,0.25,1,2,3,4,5,25) * 5))
    		(set: $ghoulHP to it - ($damage * $attackModifier))
    		(if: $ghoulHP >= 1)[
    			(replace: ?ghoul)[$ghoulHP]
    			(replace: ?action)[
    				(link: "Leave that bitch alone and report to the mayor")[(set: $goMain to true)]]
    		]
    	]
    
    	<!-- Check all cooldowns. -->
    	
    	<!-- 1. Time to show Fireball option? -->
    	(if: $elapsedTime is $showFireballAt)[
    		(replace: ?fireball)[{
    			(link: "Use Fireball")[{
    				(set: $ghoulHP to it - (25 * $attackModifier))
    				(replace: ?ghoul)[$ghoulHP]
    				<!-- show option in 10 seconds from now. -->
    				(set: $showFireballAt to $elapsedTime + 10)
    			}]
    		}]
    	]
    	
    	<!-- 2. Time to show Dragon Punch option? -->
    	(if: $elapsedTime is $showPunchAt)[
    		(replace: ?punch)[{
    			(link: "Use Dragon Punch")[{
    				(set: $ghoulHP to it - (25 * $attackModifier))
    				(replace: ?ghoul)[$ghoulHP]
    				<!-- show option in 20 seconds from now. -->
    				(set: $showPunchAt to $elapsedTime + 20)
    			}]
    		}]
    	]
    	
    	<!-- 3. Time to show Potion option? -->
    	(if: $elapsedTime is $showPotionAt)[
    		(set: $attackModifier to 1)
    		(replace: ?buff)[$attackModifier]
    		(replace: ?potion)[{
    			(link: "Use attack potion")[{
    				(set: $attackModifier to 5)
    				(replace: ?buff)[$attackModifier]
    				<!-- show option in 10 seconds from now. -->
    				(set: $showPotionAt to $elapsedTime + 10)
    			}]
    		}]
    	]
    }]
    }
    

    note: when replying to/quoting a comment that contains a large block of code in it, it is a good idea to delete that large block of code from your reply if it is not needed.
  • edited August 2016
    greyelf wrote: »
    Some suggestions:

    1. Use variables named and hook names that describe their purpose, don't uses names like punch2 or AM because you may forget what they represent latter.

    2. Use indentation and extra line-breaks to format your code (especially when debugging it) as it can help you see syntax errors like leaving out square brackets.

    3. If your code is complex (like this will be) add comments to the code to help remember what each part is doing.

    Your new potion related code is replacing the potion link for every loop.

    Try something like the following, it uses three new variables ($showFireballAt, $showPunchAt, and $showPotionAt) to track at which second in the future options or cool-downs should changed, the value of each of the three variables is recalculated each time the related option is used. I also changed the user interface a little.

    note: when replying to/quoting a comment that contains a large block of code in it, it is a good idea to delete that large block of code from your reply if it is not needed

    noted, I will try to make it look more tidy and hopefully when I use this code in addition to the inventory macros it will work just as well, if it does I'm officially done with the features in the game and I can finally focus on the story, and thanks alot for your help seriously thanks alot

  • so far so good most of the macros are working hopefully it will work perfectly
  • As I expected it fucked up again the macros are working, no errors in sight the inventory is working side by side easily but one slight problem once I click use dragon claw the multiplier it stays boosted forever, basically I add the inventory if function it fucks up, I remove it its working perfectly IDK what to do really:
    <!-- 3. Time to show small attack potion option? -->
    	(if: $inv contains "dragon_claw")[(if: $elapsedTime is $showPotionAt)[
    		(set: $attackmultiplier to 1)
    		(replace: ?buff)[$attackmultiplier]
    		(replace: ?potion)[{
    			(link: "Use dragon claw")[{
    				(set: $attackmultiplier to 5)
    				(replace: ?buff)[$attackmultiplier]
    				(set: $inv to $inv - (a: "dragon_claw"))
    				<!-- show option in 10 seconds from now. -->
    				(set: $showPotionAt to $elapsedTime + 10)
    			}]
    		}]
        ]]
    
  • You are checking for the item in the inventory before checking if the potion cool-down period is over, this means that if they used their last potion then the cool-down check will never happen which means the attack attack-multiplier will never be reset.

    Try changing the order/placement of the checks like so
    	<!-- 3. Time to reset buff and maybe show Potion option? -->
    	(if: $elapsedTime is $showPotionAt)[
    		(set: $attackModifier to 1)
    		(replace: ?buff)[$attackModifier]
    		(if: $inv contains "dragon_claw")[
    			(replace: ?potion)[{
    				(link: "Use dragon claw")[{
    					(set: $inv to it - (a: "dragon_claw"))
    					(set: $attackModifier to 5)
    					(replace: ?buff)[$attackModifier]
    					<!-- show option in 10 seconds from now. -->
    					(set: $showPotionAt to $elapsedTime + 10)
    				}]
    			}]
    		]
    	]
    
    note: I am using tab characters to indent the code, not space characters.
  • edited August 2016
    greyelf wrote: »
    You are checking for the item in the inventory before checking if the potion cool-down period is over, this means that if they used their last potion then the cool-down check will never happen which means the attack attack-multiplier will never be reset.

    Try changing the order/placement of the checks like so
    	<!-- 3. Time to reset buff and maybe show Potion option? -->
    	(if: $elapsedTime is $showPotionAt)[
    		(set: $attackModifier to 1)
    		(replace: ?buff)[$attackModifier]
    		(if: $inv contains "dragon_claw")[
    			(replace: ?potion)[{
    				(link: "Use dragon claw")[{
    					(set: $inv to it - (a: "dragon_claw"))
    					(set: $attackModifier to 5)
    					(replace: ?buff)[$attackModifier]
    					<!-- show option in 10 seconds from now. -->
    					(set: $showPotionAt to $elapsedTime + 10)
    				}]
    			}]
    		]
    	]
    
    note: I am using tab characters to indent the code, not space characters.

    I will give it a shot hopefully it will be fixed and the last bug will die and finally the game will be done in a day or so
    Edit:its finally over now I can focus on story mode and hopefully everything will go smoothly thanks alot dude :smiley:
Sign In or Register to comment.