////////////////////////////////////////////////////////////////////////////
/// Generic Turn-Based Battle Template /// Rev 0.2 - 7th Febryary, 2018 ///
/// Requires Zelda Classic 2.54 /// By: ZoriaRPG ///
/// ...Alpha 22 or later. /// For educational purposes. ///
////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////
/// Defines for game engine constants ///
/////////////////////////////////////////
//General
const int FFC_INVISIBLE_DATA = 0;
//Screen->D
const int SCREEN_D_BATTLES = 4;
const int SCREEN_D_BATTLE_TIMER_CHANGED = 1;
//Battles[] Array
const int BATTLE_TIMER = 0;
const int BATTLE_TIMER_MIN = 1;
const int BATTLE_TIMER_MAX = 2;
const int BATTLE_TIMER_DOBATTLE = 3;
const int BATTLE_NUMNPCS = 4;
const int BATTLE_MAX = 40;
//NPC Misc / Attributes
const int NPCM_ATTACKTIMER = 0;
const int NPCA_INT = 0;
const int NPCA_WIS = 1;
const int NPCA_MORALE = 2;
const int NPCA_SPEED = 3;
const int NPCA_MP = 4;
const int NPCA_SPELLS = 5;
const int NPCA_INVENTORY = 6;
const int NPCA_SPECIAL_STRING = 7;
//Global Array Sizes
const int GAS_NPCDATA = 512;
const int GAS_MAPDATA = 512;
const int GAS_ITEMDATA = 512;
const int GAS_DROPDATA = 512;
const int GAS_SHOPDATA = 512;
const int GAS_NPCS = 256;
const int GAS_ITEMS = 256;
const int GAS_EWEAPONS = 256;
const int GAS_LWEAPONS = 256;
const int GAS_TEXTBUFFER = 1024;
const int GAS_TYPEBUFFER = 129;
const int GAS_GLOBALRAM = 4096;
//Global arrays
int Battles[BATTLE_MAX];
int Buffer[GAS_TEXTBUFFER];
int TypingBuffer[GAS_TYPEBUFFER];
int GameRAM[GAS_GLOBALRAM]; //Timers go here.
npcdata NData[GAS_NPCDATA];
mapdata MapScr[GAS_MAPDATA];
itemdata IData[GAS_ITEMDATA];
dropsetdata DropData[GAS_DROPDATA];
shopdata ShopData[GAS_SHOPDATA];
ffc GlobalFF[MAX_FFCS];
//For on-screen sprited effects:
npc GlobalNPC[GAS_NPCS];
item GlobalItem[GAS_ITEMS];
eweapon GlobalItem[GAS_EWEAPONS];
lweapon GlobalItem[GAS_LWEAPONS];
///////////////////////////////
/// Battle System Functions ///
///////////////////////////////
//Disable battles, temporarily.
void NoBattles()
{
}
//Sets the minimum and maximum values of a timer.
//These will be parsed as imputs for Rand().
void SetBattleTimerValues(int min, int max)
{
Battles[BATTLE_TIMER_MIN] = min;
Battles[BATTLE_TIMER_MAX] = max;
}
//Sets the precise value of the ticking timer.
void SetBattleTimerTick(int amt)
{
Battles[BATTLE_TIMER] = amt;
}
//Decrements the battle timer, and determines if there is a battle.
//Call in the active script.
void DecrementBattleTimer()
{
--Battles[BATTLE_TIMER];
if ( Battles[BATTLE_TIMER] <= 0 )
{
Battles[BATTLE_TIMER] = 214748;
Battles[BATTLE_TIMER_DOBATTLE] = 1; //this denotes tot he global script that we are runing a random encounter
RandomEncounter();
}
}
//reset values when the battle ends
void BattleOver(npcdata nd, int xp, int cold, int treasure)
{
bool awarded = AwardXP_Gold_Treasure(xp, gold, nd);
SetBattleTimerTick( Rand(Battles[BATTLE_TIMER_MIN], Battles[BATTLE_TIMER_MAX]);
}
//award stuff after battles
bool AwardXP_Gold_Treasure(int xp, int gold, npcdata special)
{
ffc f = Screen->LoadFFC(FFC_MENU_AWARDS);
f->Data = FFC_INVISIBLE_DATA;
f->Script = Game->GetFFCScript("BattleRewards");
f->InitD[3] = special;
return true;
}
//This ffc displays Tango messages after a battle is over.
ffc script BattleRewards
{
void run(int xp, int gold, npcdata special)
{
//Determine what items an npc drops
dropsetdata dr = Game->LoadDropSetData(special->DropSet);
//Do random drop chances based on dropsetdata.
//Tango menus to display this stuff.
}
}
//Place on a screen to have that screen change the battle timer for an area.
ffc script FFC_Set_Battle_Timer_Values
{
void run(int min, int max, int reg, int bit, bool repeat)
{
if ( reg <= 0 ) { reg = SCREEN_D_BATTLES; }
if ( bit <= 0 ) { bit = SCREEN_D_BATTLE_TIMER_CHANGED; }
if ( !repeat )
{
if ( !GetScreenDBit(reg, bit) )
{
Battles[BATTLE_TIMER_MIN] = min;
Battles[BATTLE_TIMER_MAX] = max;
SetScreenDBit(reg, bit, true);
}
}
else
{
Battles[BATTLE_TIMER_MIN] = min;
Battles[BATTLE_TIMER_MAX] = max;
}
Quit();
}
}
//Runs a random encounter, based on the timer.
void RandomEncounter()
{
mapdata m = Game->LoadMapDat(Game->GetCurMap(), Game->GetCurScreen());
npcdata e = Game->LoadNPCData(m-Enemy[Rand(10]l
ffc f = Screen->LoadFFC(32);
f->Script = Game->GetFFCScript("Battle");
f->InitD[0] = e;
f->InitD[1] = m; //for drawing backdrops
}
//The battle menus run from here, as do all enemy actions.
ffc script Battle
{
void run(npcdata e, mapdata m)
{
bool waiting; int mode; int action;
while(1)
{
// Draw background using 'm'
// draw npc using 'e'
// determine e's attacks using it's attributes;
// draw menus
// determine who goes first
mode = Rand(1); //if 1, enemy goes first
while(mode)
{
//do enemy actions
//Waitframe();
}
while(!mode)
{
//player actions
waiting = true;
while(waiting)
{
//do_menus();
action = BattleMenu();
Waitframe();
}
//resolve stuff this round
Waitframe();
}
}
}
// There are certainly other ways to handle these...
// Vars used by the Tango menu.
int menuCommand;
int menuArg;
//Tango Menu Init
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);
}
//Quick way to drop a string into a Tango dialogue box.
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();
}
//The Battle Menus called from the 'Battle' FFC.
int BattleMenu() {
int lineBreak[]="@26";
int line1[]="@choice(1)Attack@tab(40)@choice(2)Spell@26";
int line2[]="@choice(3)Item@tab(40)@choice(4)Item@domenu(1)@suspend()";
SetUpWindow(WINDOW_SLOT_1, WINDOW_STYLE_3, 32, 32, SIZE_LARGE);
Tango_LoadString(WINDOW_SLOT_1, line1);
Tango_AppendString(WINDOW_SLOT_1, line2);
Tango_ActivateSlot(WINDOW_SLOT_1);
while(!Tango_MenuIsActive()){
Waitframe();
}
// Save the state again...
int slotState[278];
int menuState[960];
int cursorPos;
Tango_SaveSlotState(WINDOW_SLOT_1, slotState);
Tango_SaveMenuState(menuState);
int done = 0;
int choice;
while(true){
while( Tango_MenuIsActive() ) {
cursorPos=Tango_GetMenuCursorPosition();
Waitframe();
}
choice = Tango_GetLastMenuChoice();
if ( choice == 1 ) { // Item Info
int text[256];
Game->GetMessage(msg,text); //Load msg into the buffer.
ShowString(text, WINDOW_SLOT_2, WINDOW_STYLE_3, 48, 48);
}
else if ( choice == 2 ) { //Buy
done = choice;
menuArg = choice;
}
else if ( choice == 3 ) { //Cancel
done = choice;
}
else if ( Link->PressEx1 ) {
done = 1;
}
else done = 3;
if ( done ) {
break;
// return choice;
}
else {
Tango_RestoreSlotState(WINDOW_SLOT_1, slotState);
Tango_RestoreMenuState(menuState);
Tango_SetMenuCursorPosition(cursorPos);
}
}
Tango_ClearSlot(WINDOW_SLOT_1);
return done;
}
Comments