[ or, apparently, when I wake ]
Here you are, this is what I use, with six styles, five slots, forty max menu items. Note that the array is primed for only five slots, despite defining the rest of the values for six. To add a sixth, you merely need to add another segment to the array that holds the offscreen bitmap coordinates, and string index positions.
These are marked 0 through 4, at present, and are defined for the sizes of my menu boxes. The maximum distance offscreen is -214747 to +214747, X and Y. If you have any other defined bitmap drawing functions, you will want to ensure that you exclude whatever space that they occupy.
It also includes the present 'TANGO_SLOT_NORMAL' defs, for the purpose of compatibility; but I use 'TANGO_SLOT_WINDOW'. Thus, these two will have overlaps, and will need separate offsets. I should fix that, and add six total slots of both types, and add the additional styles (six slots of each), for general dist.
// tango.zh
// Version 1.0.0
// Standard settings -----------------------------------------------------------
// How fast messages scroll
const int __TANGO_SCROLL_SPEED = 4;
// How much holding A speeds up text
const int __TANGO_SPEEDUP_FACTOR = 5;
// Whether holding A or B speeds up scrolling to the next message
const int __TANGO_SCROLL_SPEEDUP = 1;
// Whether a sound is played when a space is printed
const int __TANGO_SFX_ON_SPACE = 0;
// Whether there's a delay before a space, as with printable characters
const int __TANGO_DELAY_ON_SPACE = 1;
// Strings that advance automatically will wait this long before doing so
const int __TANGO_AUTO_ADVANCE_TIME = 90;
// Layer to draw on
const int __TANGO_DRAWING_LAYER = 6;
// Offscreen bitmap to use for text rendering
const int __TANGO_BITMAP = 6;
// String codes are marked by this character
// 64 is @
const int __TANGO_CODE_DELIMITER = 64;
// Whether the current string scrolls up before displaying the next one
// rather than just disappearing
const int __TANGO_SCROLL_TO_NEXT = 1;
// The maximum length of a string handled by @string.
// Increasing this will make the function take more space in the buffer.
// It's not necessary to account for the null terminator.
const int __TANGO_MAX_STRING_FUNC_LENGTH = 16;
// End standard settings -------------------------------------------------------
// Advanced settings -----------------------------------------------------------
// Custom variables
float Tango_D[8]; // Access as @d0 to @d8; can be safely removed
const float VAR_TANGO_D0 = 0.0055;
const float VAR_TANGO_D7 = 0.0062;
float Tango_GetCustomVar(int var)
{
if(var>=VAR_TANGO_D0 && var<=VAR_TANGO_D7)
return Tango_D[(var-VAR_TANGO_D0)*10000];
else
{
Tango_LogUndefinedVariable(var);
return 0;
}
}
void Tango_SetCustomVar(int var, float value)
{
if(var>=VAR_TANGO_D0 && var<=VAR_TANGO_D7)
Tango_D[(var-VAR_TANGO_D0)*10000]=value;
else
Tango_LogUndefinedVariable(var);
}
// Custom functions
float __Tango_RunCustomFunction(float function, float args)
{
Tango_LogUndefinedFunction(function);
return 0;
}
// Menu data
const int __TANGO_MAX_MENU_ITEMS = 40;
float __Tango_Data[960]; // 24+3*__TANGO_MAX_MENU_ITEMS
// Style data
const int __TANGO_NUM_STYLES = 6;
int __Tango_Styles[156]; // 26 * __TANGO_NUM_STYLES
// Text buffer and slots
int __Tango_Buffer[4096]; // Arbitrary size
const int __TANGO_NUM_SLOTS = 6;
int __Tango_SlotData[240]; // 20 * __TANGO_NUM_SLOTS
// Slot types and definitions
const int TANGO_SLOT_NORMAL = 0;
// Slot types and definitions
const int TANGO_SLOT_WINDOW = 0;
int __Tango_SlotDefs[] = {
// 0
TANGO_SLOT_WINDOW,
0, // Starting index in __Tango_StringBuffer
256, // Maximum length after processing
0, 0, // X, Y on offscreen bitmap
256, 176, // Width, height on offscreen bitmap
// 1
TANGO_SLOT_WINDOW,
256,
256,
256, 0,
256, 176,
//2
TANGO_SLOT_WINDOW,
512,
256,
0, 176,
256, 176,
//3
TANGO_SLOT_WINDOW,
768,
256,
256, 176,
176, 176,
//4
TANGO_SLOT_WINDOW,
1024,
256,
0, 256,
256, 176,
TANGO_SLOT_NORMAL,
0, // Starting index in __Tango_StringBuffer
512, // Maximum length after processing
0, 0, // X, Y on offscreen bitmap
256, 512, // Width, height on offscreen bitmap
// 1
TANGO_SLOT_NORMAL,
512,
512,
256, 0,
256, 512
};
// These must be implemented in order for TANGO_FLAG_FREEZE_SCREEN to work.
// These are used by TANGO_FLAG_FREEZE_SCREEN.
void __Tango_FreezeScreen()
{
ffc freezer=Screen->LoadFFC(31);
freezer->Data=MENU_FREEZE_ALL; //2252
freezer=Screen->LoadFFC(FFC_FREEZE_2);
freezer->Data=0;
SuspendGhostZHScripts();
}
void __Tango_UnfreezeScreen()
{
ffc freezer=Screen->LoadFFC(31);
freezer->Data=0;
freezer=Screen->LoadFFC(FFC_FREEZE_2);
freezer->Data=0;
ResumeGhostZHScripts();
}
// Edit these functions to change which buttons are used.
// Return Link->Press* for advance/end string button
bool __Tango_PressAdvance()
{
return Link->PressA;
}
// Return Link->Input* for advance/end string button
bool __Tango_InputAdvance()
{
return Link->InputA;
}
// Unset Link->Input* and Link->Press* for advance/end string button
void __Tango_UnpressAdvance()
{
Link->InputA=false;
Link->PressA=false;
}
// Return Link->Press* for speedup button
bool __Tango_PressSpeedup()
{
return Link->PressA;
}
// Return Link->Input* for speedup button
bool __Tango_InputSpeedup()
{
return Link->InputA;
}
// Unset Link->Input* and Link->Press* for speedup button
void __Tango_UnpressSpeedup()
{
Link->InputA=false;
Link->PressA=false;
}
// Return Link->Press* for super speed button
bool __Tango_PressSuperSpeed()
{
return Link->PressB;
}
// Return Link->Input* for super speed button
bool __Tango_InputSuperSpeed()
{
return Link->InputB;
}
// Unset Link->Input* and Link->Press* for super speed button
void __Tango_UnpressSuperSpeed()
{
Link->InputB=false;
Link->PressB=false;
}
// Return Link->Press* for menu select button
bool __Tango_PressMenuSelect()
{
return Link->PressA;
}
// Return Link->Press* for menu cancel button
bool __Tango_PressMenuCancel()
{
return Link->PressB;
}
// Return Link->Input* for both menu select and cancel buttons
bool __Tango_InputMenu()
{
return Link->InputA || Link->InputB;
}
// Unset Link->Input* and Link->Press* for menu select and cancel buttons
void __Tango_UnpressMenu()
{
Link->InputA=false;
Link->PressA=false;
Link->InputB=false;
Link->PressB=false;
}
// Import stringControlCode.zh instead of stringControlCodeDisabled.zh
// to enable string control codes.
import "tango/1.0/stringControlCodeDisabled.zh"
//import "tango/1.0/stringControlCode.zh"
// Import loggingFull.zh instead of loggingMinimal.zh for more useful
// error messages. This will bloat scripts, so it should only be used
// for debugging.
import "tango/1.0/loggingIntermediate.zh" //This is a custom file, not part of the ordinary Tango package.
//import "tango/1.0/loggingMinimal.zh"
//import "tango/1.0/loggingFull.zh"
// End advanced settings -------------------------------------------------------
import "tango/1.0/access.zh"
import "tango/1.0/common.zh"
import "tango/1.0/drawing.zh"
import "tango/1.0/font.zh"
import "tango/1.0/functions.zh"
import "tango/1.0/loading.zh"
import "tango/1.0/menu.zh"
import "tango/1.0/messages.zh"
import "tango/1.0/metrics.zh"
import "tango/1.0/processing.zh"
import "tango/1.0/style.zh"
import "tango/1.0/user.zh"
import "tango/1.0/validation.zh"
import "tango/1.0/script.z"
//Some generic styles for menus...
// Effectively identical, but separate so they can be changed independently
const int WINDOW_STYLE_1 = 0;
const int WINDOW_STYLE_2 = 1;
const int WINDOW_STYLE_3 = 2;
const int SIZE_SMALL = 0;
const int SIZE_LARGE = 1;
const int SIZE_WIDE = 2;
void SetCommonStyleData(int style)
{
Tango_SetStyleAttribute(style, TANGO_STYLE_BACKDROP_TYPE, TANGO_BACKDROP_TILE);
Tango_SetStyleAttribute(style, TANGO_STYLE_BACKDROP_CSET, 0);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_FONT, TANGO_FONT_MATRIX);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_CSET, 0);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_COLOR, 1);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_X, 8);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_Y, 8);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_SPEED, 2);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_SFX, 105);
//Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_SFX, 95);
//Tango_SetStyleAttribute(style, TANGO_STYLE_MENU_SELECT_SFX, 101);
//Tango_SetStyleAttribute(style, TANGO_STYLE_MENU_CANCEL_SFX, 103);
Tango_SetStyleAttribute(style, TANGO_STYLE_MENU_CURSOR_COMBO, 2254);
Tango_SetStyleAttribute(style, TANGO_STYLE_MENU_CURSOR_CSET, 0);
Tango_SetStyleAttribute(style, TANGO_STYLE_MENU_CURSOR_WIDTH, 8);
Tango_SetStyleAttribute(style, TANGO_STYLE_MENU_CURSOR_MOVE_SFX, 100);
Tango_SetStyleAttribute(style, TANGO_STYLE_MENU_SELECT_SFX, 101);
Tango_SetStyleAttribute(style, TANGO_STYLE_MENU_CANCEL_SFX, 103);
//Tango_SetStyleAttribute(style, TANGO_STYLE_MENU_ERROR_SFX, 102);
//Z//Establish a function for this.
Tango_SetStyleAttribute(style, TANGO_STYLE_FLAGS, TANGO_FLAG_FREEZE_SCREEN);
}
void SetStyleSize(int style, int size)
{
if(size==SIZE_SMALL)
{
Tango_SetStyleAttribute(style, TANGO_STYLE_BACKDROP_TILE, 29380);
Tango_SetStyleAttribute(style, TANGO_STYLE_BACKDROP_WIDTH, 8);
Tango_SetStyleAttribute(style, TANGO_STYLE_BACKDROP_HEIGHT, 3);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_WIDTH, 112);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_HEIGHT, 24);
//Tango_SetStyleAttribute(style, TANGO_STYLE_FLAGS, TANGO_FLAG_FREEZE_SCREEN);
}
else if (size==SIZE_WIDE)
{
Tango_SetStyleAttribute(style, TANGO_STYLE_BACKDROP_TILE, 29440);
Tango_SetStyleAttribute(style, TANGO_STYLE_BACKDROP_WIDTH, 14);
Tango_SetStyleAttribute(style, TANGO_STYLE_BACKDROP_HEIGHT, 3);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_WIDTH, 112);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_HEIGHT, 24);
//Tango_SetStyleAttribute(style, TANGO_STYLE_FLAGS, TANGO_FLAG_FREEZE_SCREEN);
}
else
{
Tango_SetStyleAttribute(style, TANGO_STYLE_MENU_CURSOR_MOVE_SFX, 104);
Tango_SetStyleAttribute(style, TANGO_STYLE_BACKDROP_TILE, 29768);
Tango_SetStyleAttribute(style, TANGO_STYLE_BACKDROP_WIDTH, 8);
Tango_SetStyleAttribute(style, TANGO_STYLE_BACKDROP_HEIGHT, 5);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_WIDTH, 112);
Tango_SetStyleAttribute(style, TANGO_STYLE_TEXT_HEIGHT, 64);
//Tango_SetStyleAttribute(style, TANGO_STYLE_FLAGS, TANGO_FLAG_FREEZE_SCREEN);
}
///SAMPLE MENU
/// Debug Menu FFC !Z!
const int CHEATLEVEL = 4;
const int MENUFFC = 59;
ffc script DebugMenu {
void run() {
int line1[]="@choice(1)Report Screen@26";
//int line2[]="@choice(4)Enable Cheat@26";
int line3[]="@choice(3)Toggle Cheat@26";
int line2[]="@choice(4)Print Cheat@26";
int line4[]="@choice(5)Full Equip.@26";
int line5[]="@choice(6)Max HP & MP@26";
int line6[]="@choice(7)Max Counters@26";
int line7[]="@26@choice(2)Cancel@domenu(1)@suspend()";
SetUpWindow(WINDOW_SLOT_1, WINDOW_STYLE_1, 16, 16, SIZE_LARGE);
Tango_LoadString(WINDOW_SLOT_1, line1);
Tango_AppendString(WINDOW_SLOT_1, line2);
Tango_AppendString(WINDOW_SLOT_1, line3);
//Tango_AppendString(WINDOW_SLOT_1, line4);
/// Some equipment object in this game fixes Link's position, and does strange things if enabled. That must be excluded, and traced.
Tango_AppendString(WINDOW_SLOT_1, line5);
Tango_AppendString(WINDOW_SLOT_1, line6);
Tango_AppendString(WINDOW_SLOT_1, line7);
Tango_ActivateSlot(WINDOW_SLOT_1);
while(!Tango_MenuIsActive()){
Waitframe();
}
// Save the state of the text slot and menu. The bitmap won't change,
// so it doesn't need saved.
int slotState[278];
int menuState[960];
int cursorPos;
Tango_SaveSlotState(WINDOW_SLOT_1, slotState);
Tango_SaveMenuState(menuState);
bool done=false;
int choice;
while(true) {
if ( Link->PressEx4 ){
done = true;
}
while(Tango_MenuIsActive()){
cursorPos=Tango_GetMenuCursorPosition();
Waitframe();
}
choice=Tango_GetLastMenuChoice();
if(choice==1) { // Report
done=true;
Debug();
int text[]="Report saved to Allegro.log";
Tango_ClearSlot(3);
ShowString(text, WINDOW_SLOT_2, WINDOW_STYLE_2, 48, 48);
menuArg=choice;
}
else if(choice == 2) {
done = 1;
menuArg = choice;
}
else if(choice == 3) {
done = true;
if ( Game->Cheat > 0 ) {
Game->Cheat = 0;
}
else if ( Game-> Cheat == 0 ) {
Game->Cheat = CHEATLEVEL;
}
int cheatNow = Game->Cheat;
int text[]="Current Cheat is:";
TraceS(text);
Trace(cheatNow);
}
else if(choice == 4) {
done = true;
int cheatNow = Game->Cheat;
int text[]="Current Cheat is:";
TraceS(text);
Trace(cheatNow);
}
else if(choice == 5) {
done = true;
CheatEquipment(true);
int text[]="Enabled All Equipment";
TraceS(text);
}
else if(choice == 6) {
done = true;
Link->MaxHP = 9999;
Link->MaxMP = 9999;
Link->HP = 9999;
Link->MP = 9999;
int text[]="Enabled Max HP & MP";
TraceS(text);
}
else if(choice == 7) {
done = true;
MaxCounters();
int text[]="Counters Maximised";
TraceS(text);
}
else if(choice == 8) {
done = true;
godMode(true);
int text[]="godMode Enabled";
TraceS(text);
}
else if (Link->PressEx4){
Quit();
}
else{
done=true;
}
// If we need to return to the top-level menu,
// restore the state and loop again.
if(done){
break;
}
else {
Tango_RestoreSlotState(WINDOW_SLOT_1, slotState);
Tango_RestoreMenuState(menuState);
Tango_SetMenuCursorPosition(cursorPos);
}
}
Tango_ClearSlot(WINDOW_SLOT_1);
}
}
///Functions
void SetUpWindow(int slot, int style, int x, int y, int size)
{
SetStyleSize(style, size);
Tango_ClearSlot(slot);
Tango_SetSlotStyle(slot, style);
Tango_SetSlotPosition(slot, x, y);
}
// Use this function to display a ZScript string (int[]).
// The return value will be the ID of the slot used or
// TANGO_INVALID if no text slot was available.
int ShowString(int str)
{
int slot=Tango_GetFreeSlot(TANGO_SLOT_ANY);
if(slot==TANGO_INVALID)
return TANGO_INVALID;
Tango_ClearSlot(slot);
Tango_LoadString(slot, str);
Tango_SetSlotStyle(slot, STYLE_TQS);
Tango_SetSlotPosition(slot, 48, 32);
Tango_ActivateSlot(slot);
return slot;
}
void ShowString(int string, int slot, int style, int x, int y)
{
SetUpWindow(slot, style, x, y, SIZE_LARGE);
Tango_LoadString(slot, string);
Tango_ActivateSlot(slot);
while(Tango_SlotIsActive(slot))
Waitframe();
}
// Use this function to display a ZC message (Quest->Strings).
// The return value will be the ID of the slot used or
// TANGO_INVALID if no text slot was available.
int ShowMessage(int msg)
{
int slot=Tango_GetFreeSlot(TANGO_SLOT_ANY);
if(slot==TANGO_INVALID)
return TANGO_INVALID;
Tango_ClearSlot(slot);
Tango_LoadMessage(slot, msg);
Tango_SetSlotStyle(slot, STYLE_TQS);
Tango_SetSlotPosition(slot, 48, 32);
Tango_ActivateSlot(slot);
return slot;
}
// Call this function at the beginning of the active global script or
// in the Init script to set up a simple text style.
void Debug(){ //From RPG.zh/RPG_Debug.zlib
int thisScreen = Game->GetCurScreen();
int thisDMAP = Game->GetCurDMap();
int thisMap = Game->GetCurMap();
int thisX = Link->X;
int thisY = Link->Y;
int stringScreen[]="Bug Found on Screen: ";
int stringDMAP[]="on DMAP: ";
int stringMap[]="on Map Number: ";
int stringX[]="at X Coordinate: ";
int stringY[]="at Y Coordinate: ";
TraceNL();
TraceS(stringScreen);
Trace(thisScreen);
TraceNL();
TraceS(stringDMAP);
Trace(thisDMAP);
TraceNL();
TraceS(stringMap);
Trace(thisMap);
TraceNL();
TraceS(stringX);
Trace(thisX);
TraceNL();
TraceS(stringY);
Trace(thisY);
TraceNL();
}
void CheatEquipment(bool enable){
for ( int i = 0; i < 255; i++ ) {
if ( Link->Item[i] != enable ){
Link->Item[i] = enable;
}
}
}
void MaxCounters(){
for (int i = 0; i < 32; i++){
Game->MCounter[i] = 9999;
Game->Counter[i] = 9999;
}
}
void godMode(bool set){
for ( int i = 0; i < 255; i++ ) {
if ( Link->Item[i] != set ){
Link->Item[i] = set;
}
}
for (int i = 0; i < 32; i++){
Game->MCounter[i] = 9999;
Game->Counter[i] = 9999;
}
}
const int FFC_FREEZE_1 = 31;
const int FFC_FREEZE_2 = 32;
const int SCREEN_FREEZE_COMBO_1 = 2252;
const int SCREEN_FREEZE_COMBO_2 = 2252;
const int MENU_FREEZE_ALL = 2252;
}--
[ ... ]
If I expand Tango_D[] to a size of 214747, will I be able to use @d* up to an index value of 214747A, or is the data accessor token not set up for that?
I don't see an actual valid reason to set such a low value for the array size, as if people want to expand it mid-game-development, it might cause problems. The default should at least be 256, or 1024, IMO. The only reason I know not to set arrays like this to a size of MAX_INT, is to keep them optimised in for loops.
Edited by ZoriaRPG, 25 December 2015 - 03:52 AM.

