Help with different types of random events

@MarcyRangel You’re welcome to ask questions here. However, it sounds as though you’re a new Twine author and trying to make a pretty complicated RPG/VN/schedule management game as your first effort and those are notoriously difficult to understand even though they are built up out of lots of simple processes and loops.

I’d suggest starting smaller and working on each element you want to include one at a time. Try building a small experimental game that’s just about visiting a shop keeper with random dialogue and see how far you get. If you have problems, post the code you’re having problems with so people can point to something and give more specific detailed help.

It’s not that people don’t want to assist; you’ve basically just asked such general fundamental questions about RPG game structure in Twine that it’s hard to answer without writing a long essay tutorial about game design. Those do exist - you can find some here by searching, and elsewhere on the internet. That’s what @souppilouliouma meant by searching - people have asked your questions and answered them in the past and you can benefit from that existing knowledge.


I’m sorry :frowning: I didn’t realize how much of a bother I as being. This year I dint have the time to work on this project but this month In finally having the time for it that’s why I got excited and wanted to learn as much as possible so quick. I will stop now, I’m really sorry.

You’re welcome here @MarcyRangel and it’s no bother; you’ll just get quicker and more detailed help on this forum asking a question like

“I’m having trouble solving for x in the equation (x-1) = (23*y), what am I doing wrong?”

as opposed to

“Can someone please explain how math works?”

I see you deleted a post called “Questions about Mad Exile’s Gregorian Date & Time Widgets” - that was a much better specific question, but if you’ve already solved it yourself, that’s good!

I understand. I’m sorry again

@MarcyRangel you’re abolutely not a bother, and I certainly don’t want to allow nor disallow people asking questions.
I may have sounded harsh and @HanonO seems to say things more smoothly than me.

1 Like

I didnt solved, I deleted because I didn’t want to be a bother again haha That’s ok, I will try to learn alone

@souppilouliouma you wasn’t harsh, you were right, I was really being inconvenient. I will work harder from now on tofind a solution when I have difficulty in something instead of going to ask help right away :relaxed:

Again, we’re here to support you and you’re not alone. So long as you’re aware you’ll get better and quicker feedback if you post a specific problem and someone can say “You forgot to close your parentheses here…” as opposed to composing a lengthy explanation on design theory. :slight_smile:

1 Like

Thank you so much!! And is ok, they’re right, I was being really inconvenient these days with lots of questions. I deleted my previous questions and from now on I will work higher to find a solution by myself instead of going ask help right away :relaxed:

It’s not that people don’t want to learn by themselves, but obviously beginners don’t even know what keywords to search for. If you don’t want to drop links to resources, at the very least give out keywords to search for, lest your answer basically sounds “dismissive and patronizing”, acting all high and mighty telling people they do wrong without even pointing them the way to go.

For example:

Have you considered different ways to make rpg games in Twine available on Google?

You can see the emphasis on searchable keywords, which is better than “rpg game structure”, BTW. See how easy it is to be helpful? Why not help them?

Telling people not to ask questions without telling them what to research beforehand is to shut them out, simply because they can’t find any “good” resource. Is that what you want?

So true. This is usually why I ask “stupid” questions… because I can’t find the correct search term to lead me to the right place to learn.

1 Like

@HanonO I manage to find a solution to all my MadExile Time widget questions , except for one: how do I calculate remaining time using that widget? Like, if current date is x and event is y, what is the code to calculate the remaining days? I cant find this information anywhere and I am horrible at math :sob: I swear to god I looked everywhere . I found how to create widgets, how to set events, how to change days and months. But not this. Do you have any tips? I swear I will not post anything again for at least months, it’s just this one problem that I need to solve as soon as possible to move my story foward

No need to cry. You can ask as many questions as needed. When you say “day”, do you mean turn based events ?

No, not turn based events. I use MadExile time widget (found in this thread (MadExile's Gregorian date & time widgets) How might I advance this game clock to a certain day and time? - Twine Q&A) to set the date of my story. Some events happens in specific dates (for example, npc birthdays is on 12/4). I want to make a widget to the game calculate how many days between current date and event day. Let’s suppose current date is 11/05, I want to print how many days remain until the npc birthday on 12/04. I hope I made sense, english is not my native language :sweat:

You will need a table with number of days each month, but maybe this will help

Edit: have you tried Twine mad exile on the search engine on this board? I think one of those post will work for you.

1 Like

Hopefully @TheMadExile will chime in here. I honestly don’t work extensively in Twine and Sugarcube, so I’m not the person to ask.

You don’t have to swear off asking questions! I wasn’t in any way trying to silence you, I was hoping to give you tips on how to get better advice here.

Check this thread also:

1 Like

Here is how I would approach the problem:

  1. Click the magnifying glass icon in the upper right to get a search bar drop-down.

  2. Enter gregorian date into the search bar. It’s often best to start with a specific term in order not to get irrelevant results. (If there are no results, you can always broaden the search.)

  3. In the search results, the second topic looks very promising, titled [Sugarcube 2.31.1] Events triggered based on calendar date.

  4. That thread seems to provide very useful hints for the usage of the widget. (Although, probably not the exact solution to the days problem.)

  5. So then, I’d look closely at the code of the widget itself, to see whether it contains built-in definitions that would solve the task directly. That doesn’t seem so.

  6. However, from the widget’s setup code (and from a Twinery forum post where TheMadExile provides the widget), we see that the JavaScript Date object is used.

  7. So, I would read up on the JS Date object. TME provided a link in that post, otherwise it’s the first Google hit for JavaScript Date object:
    Date - JavaScript | MDN

  8. That can look fairly intimidating if you aren’t used to it, but we can at first just skim-read it, since we are only looking for a method to calculate days between dates.

  9. We don’t immediately find a promising method name, but at the bottom of the page, there’s a section called “Calculating elapsed time”.

  10. There we see that we can subtract one date from another (or equivalently subtract the values returned by their getTime() methods), and we will get back the time difference in milliseconds. So, to get what that means in days, we will need to divide it by the number of milliseconds in a day (1 day = 24 hours = 1440 minutes = 86400 seconds = 86400000 milliseconds).

  11. As a quicker alternative to steps 7-10, we could have googled javascript calculate days between dates, the first hit is:
    How to calculate the number of days between two dates in javascript? - GeeksforGeeks
    Where we find:

// To calculate the time difference of two dates
var Difference_In_Time = date2.getTime() - date1.getTime();
// To calculate the no. of days between two dates
var Difference_In_Days = Difference_In_Time / (1000 * 3600 * 24);
  1. I’m not well-versed in Twine, but I think for Sugarcube it should be something like:
<<set $gameDate to new Date(2015, 2, 17, 3, 24);>>
<<set $futureDate to new Date(2015, 2, 24, 3, 24);>>

<<set $diffdays to ($futureDate.getTime() - $gameDate.getTime()) / 86400000>>

I hope this helps or provides some necessary building blocks.

1 Like

I noticed that some of your questions have to do with introducing random events, so I’ll try to help you out with that question.

Because you’re working with SugarCube, you can use a Config.navigation.override function to redirect passage navigation for these random events. I’ll give you an example of how you can use this function for random events.

To make things simple for this example, let’s say you have “normal” passages, “travel” passages, and “event” passages. When going to “normal” or “event” passages, there’s no chance of random events, but for “travel” passages there’s a 30% chance of ending up at an “event” passage instead, unless you’re already coming from an “event” passage, in which case you’ll always make it to the “travel” passage. That will prevent triggering multiple events in a row. To be able to recognize all of the “travel” and “event” passages, they’ll all need to be marked with a “travel” or “event” tag, respectively. (I’d also recommend picking colors for those tags, to make those passages easier to spot.) Any passages without either of those tags will be a “normal” passage.

Now that we have that structure figured out, you can implement that by putting this in your JavaScript section:

// This function is triggered just before each passage navigation event.
Config.navigation.override = function (dest) {
	if (tags(dest).includes("travel") && !tags().includes("event")) {
		// If the destination is a "travel" tagged passage and
		// the current passage is NOT an "event" tagged passage, then...
		if (random(1, 10) <= 3) {  // ...there's a 30% chance of:
			// Storing the original destination in the $continue variable.
			State.variables.continue = dest;
			// Changing to a random "event" tagged passage.
			dest = Story.lookup("tags", "event").random().title;
		} // ...otherwise continue to the original destination passage.
	} else {  // For non-"travel" tagged destination passages:
		// Clear the value in $continue since it shouldn't be needed anymore.
		delete State.variables.continue;
	// Go to the passage named in the "dest" variable.
	return dest;

Note that the code which looks at the tags is case sensitive, so tagging a passage with “Travel” instead of “travel” will not work.

That code uses the SugarCube tags() function to get an array of tags in a passage, the .includes() method to determine if a value is in an array, the random() function to get a random number, the State.variables object to access SugarCube story variables (since you can’t directly use SugarCube story or temporary variable names within JavaScript code), the Story.lookup() method to get an array of passage objects with a particular tag, the .random() method to get a random element from an array, and the .title property to get the title of a passage from a passage object. It also uses the JavaScript delete operator to remove the $continue story variable from the State.variables object (it’s the JavaScript equivalent of the SugarCube <<unset>> macro).

Once you have added that to your code and added “travel” and “event” tags to the appropriate passages, it will then automatically have a 30% chance of redirecting any movement to a “travel” tagged passage to an “event” tagged passage, unless you were already in an “event” tagged passage.

If you want to have a link in an “event” passage that sends you back to the original “travel” passage that you were heading to, you can use the $continue variable in the “event” passage to know which passage to go to. So the code you can use to exit your “event” passage may look like this:

<<link "Continue" $continue>><</link>>

That will display a link that says “Continue”, and clicking on it will send you to the original destination “travel” passage that you were attempting to go to when you were interrupted with the event.

Note: As the code is currently, the $continue variable will be deleted once you exit any “event” passage. This is to prevent unnecessary “bloat” in the game history, which can happen if you store a bunch of unneeded story variables, since that extra data will slow down saves, loads, and passage transitions.

Now, to be clear, there is no reason why you would have to do things exactly as I’ve shown. That’s merely a simple example of one way that it could be done. There are millions of different ways you could do that, including having different odds, not automatically deleting the $continue variable, having different events possible depending on things such as player level or destination passage, etc… It’s entirely up to your imagination and coding skills. Feel free to modify it into whatever you want.

Hopefully, though, this should give you a basic foundation for setting up random events that can trigger in your game. Please let me know if you have any questions on how any of the above works.

Enjoy! :slight_smile:

1 Like

@HiEv Oh my god :scream: THIS WILL HELP ME A LOT, THANK YOU SO MUCH!! :heart_eyes::heart_eyes::heart_eyes:

@StJohnLimbo thank you so much!! :heart_eyes: