- Menus can now scroll up and down if they're too big to fit in the textbox. This won't work correctly unless each menu item fits on one line, however.
- Added menu scrolling indicator style attributes.
- Menu cursors can now move smoothly between choices.
- In non-text menus, menu items can now be moved after they're placed.
- Added cursor size style attributes and reworked drawing to allow highlight-style cursors.
- Added centered and right-aligned text options for complex backdrops.
- Added Tango_SlotIsFinished(), which returns true as soon as text is finished printing.
- Added an option to log all messages, errors only, or nothing.
- Added an optional onscreen notification when an error is logged.
- Added Tango_ValidateConfiguration(), which will look for common configuration errors and write a report to allegro.log.
- Changed the default configuration to allow more styles and menu items and enable string control codes.
- Added tangoFAQ.txt, which will hopefully address some common inquiries.
tango.zh
#241
Posted 05 January 2016 - 02:57 PM
#242
Posted 06 January 2016 - 10:57 AM
If one were to use your new version, which tango files would have to be updated? All of em?
Any chance of producing an example .qst or just a script that shows us how to run the menu system (old or new, really)? I'm still having trouble using your prior menu system working.
Of course, if you want to hold my hand and walk me through the process of creating a 3-option menu, that'd be super swell. All I need to be able to do is (1) let the player choose one of three options; and (2) store the result. From there, I can make shops, branching conversation trees, etc. It's the tango part that's flummoxing me ![]()
#243
Posted 06 January 2016 - 12:22 PM
Yes. The files are in tango/1.1 now, so they can exist alongside the previous version, and you can switch back easily.If one were to use your new version, which tango files would have to be updated? All of em?
There are a few new settings in the main file, and the array sizes are different now, but you can copy and paste the input functions, at least.
Aside from the renamed style attribute and a bug fix or two, any existing scripts should work the same as before.
There are a lot of different ways you can make menus. For a non-text menu, the simplest example would be something like this:Of course, if you want to hold my hand and walk me through the process of creating a 3-option menu, that'd be super swell. All I need to be able to do is (1) let the player choose one of three options; and (2) store the result. From there, I can make shops, branching conversation trees, etc. It's the tango part that's flummoxing me
Tango_InitializeMenu();
Tango_SetMenuCursor(cursorCombo, cursorCSet); // The width and height can be set, too
Tango_SetMenuSFX(moveSFX, selectSFX, cancelSFX); // Optional
for(int i=1; i<=3; i++) // Add choices wih values 1 to 3 (don't use 0)
Tango_AddChoice(i, 56+i*32, 96); // Value, X, Y
Tango_ActivateMenu(true); // Argument is whether the user can cancel
while(Tango_MenuIsActive())
{
// Draw menu options here
Waitframe();
}
int selected=Tango_GetLastMenuChoice(); // Get the result - 0 means user cancelledText menus use @choice() and @domenu(). The cursor and sounds are set as part of the style.int menuStr[]="@choice(1)Option 1@26@choice(2)Option 2@26@choice(3)Option 3@domenu(1)@close()";
// This will appear as:
// > Option 1
// Option 2
// Option 3
// Argument 1 to @domenu() means user can cancel
// @close() closes the text box afterward without prompting for input
ShowString(menuStr);
while(!Tango_MenuIsActive())
// It will take at least one frame to become active
Waitframe();
while(Tango_MenuIsActive())
Waitframe();
int selected=Tango_GetLastMenuChoice(); // As before, 0 means user cancelled(I can't believe I haven't added Tango_MenuWait() already... Well, something for the next update.)For more complex cases, like dialogue trees, you might want functions to build menus programatically. Something along the lines of:
int MenuSlot;
bool FirstMenuChoice;
void InitMenu()
{
MenuSlot=Tango_GetFreeSlot(SLOT_MENU); // Or just hardcode it
Tango_ClearSlot(MenuSlot);
Tango_SetSlotStyle(MenuSlot, STYLE_MENU);
Tango_SetSlotPosition(MenuSlot, MENU_X, MENU_Y);
FirstMenuChoice=true;
}
void AddMenuChoice(int value, int text)
{
// Start a new line if this isn't the first choice
if(FirstMenuChoice)
FirstMenuChoice=false;
else
{
int nl[]="@26";
Tango_AppendString(MenuSlot, nl);
}
int buffer[100];
int format[]="@choice(%d)%s";
sprintf(buffer, format, value, text);
Tango_AppendString(MenuSlot, buffer);
}
int ActivateMenu()
{
int end[]="@domenu(1)@close()";
Tango_AppendString(MenuSlot, end);
Tango_ActivateSlot(MenuSlot);
while(!Tango_MenuIsActive())
Waitframe();
while(Tango_MenuIsActive())
Waitframe();
return Tango_GetLastMenuChoice();
}That would be used like this:int yes[]="Yes";
int no[]="No";
InitMenu();
AddMenuChoice(1, yes);
AddMenuChoice(2, no);
if(showMaybe)
{
int maybe[]="Maybe";
AddMenuChoice(3, maybe);
}
int result=ActivateMenu();If you'd like more concrete examples, I'll be glad to provide them.
- Timelord likes this
#244
Posted 24 January 2016 - 10:41 AM
If you'd like more concrete examples, I'll be glad to provide them.
Yeah, I think I need to understand Tango better. I follow your code up until the "draw menu" part of your first example. I certainly could just draw tiles to the screen in three locations, and draw a cursor to the screen in the proper place... but as far as drawing one-three menu options using Tango and allowing the player to choose? No idea. See, using tiles, I'd just draw each tile-based option and the cursor each frame, easy. With Tango, I don't think I can or should draw all three options each frame; I suspect Tango takes care of that in its menu option. I just don't know how it works or how to set it up.
#245
Posted 24 January 2016 - 10:46 AM
while(Tango_MenuIsActive())
{
// Coordinates a tile right from the cursor stops
Screen->FastTile(6, 104, 96, 103, 7, OP_OPAQUE);
Screen->FastTile(6, 136, 96, 241, 8, OP_OPAQUE);
Screen->FastTile(6, 168, 96, 160, 7, OP_OPAQUE);
Waitframe();
}
#246
Posted 24 January 2016 - 05:04 PM
Can I draw strings based on the selected item? Like this?
while(Tango_MenuIsActive())
{
// Let user scroll through options
if(currentChoice!=lastChoice){
if(choiceSlot!=TANGO_INVALID) Tango_ClearSlot(choiceSlot);
if(currentChoice == 1) choiceSlot = ShowString(choice1, TANGO_SLOT_NORMAL, STYLE_MENU, 16, 80);
else if(currentChoice == 2) choiceSlot = ShowString(choice2, TANGO_SLOT_NORMAL, STYLE_PLAIN, 16, 80);
else if(currentChoice == 3) choiceSlot = ShowString(choice3, TANGO_SLOT_NORMAL, STYLE_PLAIN, 16, 80);
}
lastChoice = currentChoice;
Waitframe();
}
That gives me more space to put slightly longer "responses" for dialogue chains.
FYI here's what I have now; it does not display any of the choiceStrings:
int TextMenu(int message, int choice1, int choice2, int choice3){
// This script displays the message in a dialog box on the top of the screen
// and lets the player choose an option. It will display any messages
// that do not contain 0 only.
// Returns 1, 2, or 3 depending on choice made.
// Error checking; ensure that 1 has data, and if 3 does, 2 does as well.
if(choice1 == 0) return -1;
if(choice3 != 0 && choice2 == 0) return -1;
int numChoices = 1;
if(choice3 != 0) numChoices = 3;
else if (choice2 != 0) numChoices = 2;
int talkSlot;
int choiceSlot=TANGO_INVALID;
int currentChoice = 1;
int lastChoice=-1;
int choiceX[]={ 78, 78, 78 };
int choiceY[]={ 110, 136, 152 };
talkSlot=ShowString(message, TANGO_SLOT_NORMAL, STYLE_PLAIN, 32, 16);
Tango_InitializeMenu();
Tango_SetMenuCursor(13829, 0, 1, 1);
Tango_SetMenuSFX(66, 67, 0);
for(int i=1; i<=numChoices; i++) // Add choices wih values 1 to 3 (don't use 0)
Tango_AddMenuChoice(i, choiceX[i], choiceY[i]);
Tango_ActivateMenu(true); // Argument is whether the user can cancel
while(Tango_MenuIsActive())
{
// Let user scroll through options
if(currentChoice!=lastChoice){
if(choiceSlot!=TANGO_INVALID) Tango_ClearSlot(choiceSlot);
if(currentChoice == 1) choiceSlot = ShowString(choice1, TANGO_SLOT_NORMAL, STYLE_MENU, 16, 80);
else if(currentChoice == 2) choiceSlot = ShowString(choice2, TANGO_SLOT_NORMAL, STYLE_PLAIN, 16, 80);
else if(currentChoice == 3) choiceSlot = ShowString(choice3, TANGO_SLOT_NORMAL, STYLE_PLAIN, 16, 80);
}
lastChoice = currentChoice;
Waitframe();
}
int selected=Tango_GetLastMenuChoice(); // Get the result - 0 means user cancelled
return selected;
} // end of TextMenu
#247
Posted 24 January 2016 - 05:29 PM
#248
Posted 24 January 2016 - 07:51 PM
Does Tango automatically handle moving the player between currentChoices? It looks from your code like it does, but it's not acting that way. Seems like it would have to in order for Tango to know what the selection was.
EDIT: And, if not, what does Menu actually... do? Just handle drawing a cursor on top of the Tango window?
EDIT2: Working on that assumption, I got the shop working. So that's keen. I need to set the shop up as it's own FFC module, however, to ensure the NPC keeps drawing itself on the screen during the internal waitframe. For some reason, when I tried to use the same TextMenu() function to make a branching conversation with Uncle Wiggle Beard, it never shows the menu. Huh. Anyway, updated the drop box if you wanna see what I'm up to.
Edited by C-Dawg, 25 January 2016 - 12:09 AM.
#249
Posted 25 January 2016 - 11:25 AM
If something doesn't work, be sure to check allegro.log to see if it detected a problem.
#250
Posted 25 January 2016 - 06:22 PM
Edited by C-Dawg, 25 January 2016 - 10:42 PM.
#251
Posted 31 January 2016 - 06:02 PM
So, I messing around with this and don't have a huge understanding but I am slowly getting it. I am having trouble with one thing:
So I basically what to do a somewhat combined of the NPC and the itemObtained Script (the movement portion). So basically when you talk to the NPC, the string/text box moves from offscreen to the screen to its position. And when you are done talking to it, it moves back away offscreen.
I know that the itemObtained script within the demo has this:
int movement[]="@while(@greater(@y 130) @inc(@y -3))@delay(240)@while(@less(@y 168) @inc(@y 3))"; //and later says this to append it: Tango_AppendString(slot, movement);
However, I can't figure out how to do this same thing on the NPC script, I don't know how I would place this in the code:
ffc script NPC
{
void run(int message)
{
while(true)
{
if(StartTalking(this))
{
// Display the assigned message
int slot=ShowMessage(message, TANGO_SLOT_NORMAL, STYLE_PLAIN, 32, 32);
// If the message was displayed successfully...
if(slot!=TANGO_INVALID)
{
// Wait for it to be closed
while(Tango_SlotIsActive(slot))
{UnpressButtons();
Waitframe();}
}
StopTalking();
}
Waitframe();
}}
Can I get some help? Thanks!
#252
Posted 31 January 2016 - 07:32 PM
int ShowMovingMessage(int message, int type, int style, float x) // No need for a Y argument
{
int slot=Tango_GetFreeSlot(type);
if(slot==TANGO_INVALID)
return TANGO_INVALID;
int movement[]="@while(@greater(@y 130) @inc(@y -3))@delay(240)@while(@less(@y 168) @inc(@y 3))";
Tango_ClearSlot(slot);
Tango_LoadMessage(slot, message);
Tango_AppendString(slot, movement);
Tango_SetSlotStyle(slot, style);
Tango_SetSlotPosition(slot, x, 168);
Tango_ActivateSlot(slot);
return slot;
}You could also handle the movement in ZScript with Tango_SetSlotPosition().
#253
Posted 31 January 2016 - 10:59 PM
Thank you! I am trying to get it to work, but I am having a hard time getting the text box to show up. I thought it was what I had added that was the problem, but I guess it is my variable: typeOf. Here is the text code I am working with:
ffc script NPC
{
void run(int message, int typeOf, int xPos)
{
while(true)
{
if(StartTalking(this) && (typeOf == 0))
{
// Display the assigned message
int slot=ShowMessage(message, TANGO_SLOT_NORMAL, STYLE_PLAIN, 32, 32);
// If the message was displayed successfully...
if(slot!=TANGO_INVALID)
{
// Wait for it to be closed
while(Tango_SlotIsActive(slot))
{
Waitframe();}
}
StopTalking();
}
else if(StartTalking(this) && (typeOf == 1))
{
// Display the assigned message
int slot=ShowMessage(message, TANGO_SLOT_NORMAL, STYLE_PLAIN, 32, 32);
//int slot = ShowMovingMessage(message, TANGO_SLOT_CLOUDPOPUP, STYLE_CLOUDPOPUP, xPos);//This is what I will be adding once I have the above working...
// If the message was displayed successfully...
if(slot!=TANGO_INVALID)
{
// Wait for it to be closed
while(Tango_SlotIsActive(slot))
{
Waitframe();}
}
StopTalking();
}
Waitframe();
}
}
}
I did this as a test because I was planning on separating NPC to have different affects with the "typeOf" variable; typeOf == 0 is default, and the typeOf == 1 is where it moves. However, when I put typeOf (d1) as 1, it doesn't bring up the text box, it also makes it so the other NPC in the screen doesn't work. Maybe I just need help understanding why this is the case.
I don't know if you need this too (not sure if I set this section up right), so I will just paste it here:
int __Tango_SlotDefs[] = {
// 0
TANGO_SLOT_POPUP,
64, 128,
256, 64,
128, 64,
// 1
TANGO_SLOT_CLOUDPOPUP,
0, 1024,
256, 64,
128, 64,
// 2
TANGO_SLOT_NORMAL,
0, 1024, // Starting index and length in __Tango_StringBuffer
0, 0, // X, Y on offscreen bitmap
256, 512, // Width, height on offscreen bitmap
// 3
TANGO_SLOT_NORMAL,
1024, 1024,
256, 0,
256, 512
};
#254
Posted 01 February 2016 - 01:44 AM
if(StartTalking(this))
{
int slot;
if(typeOf==0)
slot=ShowMessage(message, TANGO_SLOT_NORMAL, STYLE_PLAIN, 32, 32);
else
slot = ShowMovingMessage(message, TANGO_SLOT_CLOUDPOPUP, STYLE_CLOUDPOPUP, 32);
// Wait for it to close...
}
#255
Posted 01 February 2016 - 10:48 AM
Shoelace, when I started working with Tango, one of the first things I did was make my own global function, "Say," that makes displaying strings from Tango much easier. It takes input that determines the type of tango style to display (which you set up separately per Saffith's excellent examples), where to say it, and what to say. The "Say" function then checks to make sure the text box is on screen, that it is placed correctly relative to the speaker, and all that jazz, then displays the right one. It has been invaluable as I do more complicated things with Tango!
The function header is like this:
Say(int x, int y, int style, int string)
Where "string" is a ZScript integer array pretending to be a character string. One thing I've learned as I tinker is that you can't just define a string in a function call, sadly. So my calls tend to all look like this:
message int[] = "This is the text to display.";
Say(this->X, this->Y, current_style, message);
I really recommend that you do something like that before you start adding string functionality to FFC scripts as it makes things sooo much easier. Not only that, but it frees you up from having Tango work just with dedicated FFCs. Every script in the game can "Say" something, so you can make screens a lot more information dense without doing much extra work.
Edited by C-Dawg, 01 February 2016 - 10:49 AM.
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users

