Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines
(+1)

A button that randomly chooses a label is pretty straightforward. Paste this as the button’s “click” handler:

on click do
 # Different texts the button might show
 texts:"Click me!","Poke","Nudge","Boop"
 
 # Remove the button's current text from the list,
 # so we don't show the same label twice
 texts:me.text drop texts
 
 # Pick a random text and apply it to the button.
 me.text:random[texts]
end

Cycling through texts is a little more complicated, because we have to figure out where we currently are in the list of options, and what to do when we reach the end:

on click do
 # Different texts the button might show
 texts:"5","4","3","2","1","Boom!"

 # Search through texts looking for
 # the one that matches the old button text 
 oldindex:-1
 each t i in texts
  # If we have found the old text,
  # save its index number as the old index
  if me.text=t oldindex:i end
 end
 
 # If the old index was the last text...
 if oldindex = (count texts)-1
  # ...restart the cycle
  me.text:first texts
  # (you might choose to do something else,
  # like go to the next card)
  
 # If the current text wasn't found...
 elseif oldindex = -1
  # ...start from the beginning
  me.text:first texts
  
 # Otherwise just pick the next text.
 else
  me.text:texts[oldindex+1]
 end

end

(A compact and cryptic way to calculate oldindex might be sum (me.text = texts) * range count texts, I don’t know if there’s an even more compact way)

(+2)

I might write the second example as

on click do
 t:"|" split "5|4|3|2|1|Boom!"
 me.text:t[(count t)%1+sum(me.text=t)*keys t]
end

Using the mod operator (%), taking advantage that for a list x, "keys x" is equivalent to "range count x", and that a failure to find a match for the current button text is harmlessly equivalent to matching the first option.

(3 edits) (+1)

Thanks to both of you!! This example worked perfectly for what I need the title card to do, thank you!

If I'm understanding things correctly, variables are only reserved in the same widget / card? So, for example, if I wanted to invoke this same list of text options elsewhere, I would need to direct it to titlebutton.texts? Can I do that across cards, too?

EDIT: Also, I'm having trouble getting in-line links in fields to work? I want to link to the PUSH SRD  and I've highlighted the relevant text and inserted the link with the Text -> Link menu, but clicking on it with the interact tool doesn't do anything.

(+2)

Variables in scripts within Decker only persist for the duration of an event handler. Static data that you just want to be able to reference from multiple places throughout a deck could be placed in the Deck-level script; go to File -> Properties... in the main menu, click "Script..." and then you can enter a declaration like

title_texts:"First","Second","Third","Fourth"

And then refer to the variable 'title_texts' from any card or widget script.

Again, this is for static data. For information that can change over time- like status flags or an inventory system in a game- you'll need to store the information in widgets somewhere on a card. This is a key idea in Decker: state and code live in physical, observable places within a deck. 

For example, you could also place this list within a field named 'texts' on a card named 'title' in JSON format:

["First","Second","Third","Fourth"]

And then access the contents of that field as a list from elsewhere in a script like

title.widgets.texts.data

For links in a rich text field to be clickable, you need to lock the field. In widget mode, select the field and choose "Widgets -> Locked" from the main menu.

If you haven't seen it already, I highly recommend reading through Phinxel's Phield Notes; it's very beginner-friendly and full of examples you can play with and borrow from for your own projects.

(+1)

I have seen Phinxels! I remembered seeing something about how to lock widgets in there but when I went to find it, I couldn't, so thank you.

One last question and I should hopefully be able to figure the rest out on my own— is there a way to make a button invisible until something else happens? I saw in some other comments in here the idea to make a "gamestate" card with checkboxes for things I want to track, and I'd like to be able to hide a button until a "gamestate.widgets.X.value" is checked.

To provide probably more context than necessary, I'm making a faux-ttrpg as an "about me" for a job application for a creative project. I want the user to click on a button next to the Name field of the "character sheet" to get a story about my name to appear in a text field, and log that they've seen that to make the button for the next character sheet field appear. Once all the fields have been filled, out, I want a "Begin Adventure" button to appear to go to the next section of the game.

I see that there's an "invisible" setting for buttons, but I'm not sure how I could toggle the button type based on a variable. Changing the text field is probably just an "if card.widgets.variable.value then print: "whatever"" kinda deal, so I'm mostly worried about the button visibility.

(1 edit) (+2)

To start with, you probably need the "Show" attribute. Specifically to set things to .show:"none" 

Invisible buttons are more useful for things you want to be able to click that don't look like buttons (for example, navigating around a scene in a point-and-click game). And a "None" button is truly hidden and unclickable until you change their setting, so that seems like what you might be after.

To set a widget to "none" visibility you can do it in code or with the menu while you're editing.  
While Editing you deck: Select a widget and use the menu Widgets > Show None ]

And in code, this sets the visibility of a widget:

widgetname.show:"none"

To make it visible again you would need to set it's show attribute to one of the other visibilities, so this...

widgetname.show:"solid" 

...would set it back to the default visibility it had when you made it. (Other options: "transparent" and "invert")

Just a thought, but if you only need to track the progress on one card for now and you don't need to check back on it later you could just make things appear one by one in the button scripts.

For example, here's a simple example script for a button that sets some text in a field then makes the next button visible:

on click do
myname.text:"Pyrefly Studio"
favefoodbutton.show:"solid"
end

and then script in the next button (favefoodbutton, which just became visible) could be something like

on click do
favefood.text:"Blueberry Ice Cream"
coolfactbutton.show:"solid"
end

etc, etc. These widget names (fields: myname, favefood / buttons: favefoodbutton, coolfactbutton) are made up, of course, so you'll want to make any names match the widgets that actually exist. 

But I hope this helps you get started changing widget visibility and setting the text of a field using scripts.