The Random Header

SubmittedMay 28, 2017

0.0 rating

Author

Moosh

Description

A set of utility functions, and constants for use with Zelda Classic 2.50.x. Some of these may be incorporated into ZC 2.54 and higher.

Script Setup Details

Import this header into your script files using the import "filename" directive.

Script Contents

//-------------------------------//
// The Random Header - v. 1.0 //
//-------------------------------//

// -------- SETTINGS (edit these) -------- //

const int COMBO_AUTOWARP = 0; // Specify the first of four autowarp combos (A,B,C,D) for scriptWarp() and forceWarp()

// -------- GLOBAL VARIABLES AND CONSTANTS (do not edit!) -------- //

// Input constants for getItemInputSlot()
const int INPUT_NONE = 0;
const int INPUT_A = 1;
const int INPUT_B = 2;

// New Combo Flag Variables
const int CF_STEP = 200;

// -------- FUNCTIONS -------- //

// Function to move Link to an (X,Y) coordinate.
// It pretty much combines Link->X and Link->Y into one command.
void moveLink(int x, int y)
{
Link->X = x;
Link->Y = y;
}

// Initiate a preset sidewarp
// 0 = A 1 = B 2 = C 3 = D
// Note: Uses FFC 31.
void forceWarp(int warpnum)
{
ffc warp = Screen->LoadFFC(31);
warp->Data = COMBO_AUTOWARP + warpnum;
}

// Sets then immediately initiates a side warp (0-3)
// Don't do anything serious with the sidewarp you choose on the current screen.
// Note: Uses FFC 31
void scriptWarp(int dmap, int screen, int type, int warpnum)
{
Screen->SetSideWarp(warpnum, screen, dmap, type);
ffc warp = Screen->LoadFFC(31);
warp->Data = COMBO_AUTOWARP + warpnum;
}
// This is an overload of the above that automatically chooses Sidewarp D.
void scriptWarp(int dmap, int screen, int type)
{
scriptWarp(dmap, screen, type, 3);
}//!End scriptWarp

// A reorganization of Screen->SetSideWarp() because we are really picky
void setSideWarp(int num, int dmap, int screen, int type)
{
Screen->SetSideWarp(num, screen, dmap, type);
}

// This function returns the slot an item is in
int getItemInputSlot(int itemID)
{
// If the item is in slot A
if(GetEquipmentA() == itemID)
return INPUT_A;
// Else if the item is in slot B
else if(GetEquipmentB() == itemID)
return INPUT_B;
// Else the item is not equipped
else
return INPUT_NONE;
} //! End of int getItemInputSlot(int itemID)

// This function gathers the slot the item is in
// and returns true or false for if that button
// is currently being pressed by the player
bool ifItemInput(int itemID)
{
// Get the item slot the item is in
int itemSlot = getItemInputSlot(itemID);

// If the player is pressing A and the item is in slot A
if(itemSlot == INPUT_A && Link->InputA)
return true;
// If the player is pressing B and the item is in slot B
else if(itemSlot == INPUT_B && Link->InputB)
return true;
// If the player is not pressing the item or if it is not equipped
else
return false;
} //! End of bool ifItemInput(int itemID)

// This function gives Link an item. If the function
// is passed "true" for ifHoldUp, then it will force Link
// to hold up the item.
void giveItem(int itemID, bool ifHoldUp)
{
// This creates a new item and places it over Link
item newItem = Screen->CreateItem(itemID);
newItem->HitWidth = 16; newItem->HitHeight = 16;
SetItemPickup(newItem, IP_HOLDUP, ifHoldUp);
newItem->X = Link->X; newItem->Y = Link->Y;
} //! End of bool giveItem(int itemID, bool ifHoldUp)

// This function forces Link input. Essentially,
// it's an easier method of doing all of the Link->Input
// variables and such.
void setInput(bool up, bool down, bool left, bool right, bool a, bool b, bool l, bool r, bool map, bool start)
{
Link->InputUp = up;
Link->InputDown = down;
Link->InputLeft = left;
Link->InputRight = right;
Link->InputA = a;
Link->InputB = b;
Link->InputL = l;
Link->InputR = r;
Link->InputMap = map;
Link->InputStart = start;
}

// This creates an enemy at a random (non-solid) location on the screen
void createEnemy(int enemyNum)
{
// Essentially while you have not found a good place
while(true)
{
// Get a random location on the screen
int x = Rand(12) * 16 + 32;
int y = Rand(7) * 16 + 32;

// Boolean for if the location is acceptable
bool ifLocationOkay = true;

// Make sure the location isn't over Link
if(Distance(x, y, Link->X, Link->Y) isSolid(x, y))
ifLocationOkay = false;

if(Screen->isSolid(x+15, y))
ifLocationOkay = false;

if(Screen->isSolid(x, y+15))
ifLocationOkay = false;

if(Screen->isSolid(x+15, y+15))
ifLocationOkay = false;

if(Screen->isSolid(x+8, y+8))
ifLocationOkay = false;
// End checking for solidity

// Get the combo number and type of the location
int comboNum = ComboAt(x, y);
int comboType = Screen->ComboT[comboNum];

// If the combo type is water or anything preventing enemies, the location is not okay
if(comboType == CT_WATER || comboType == CT_NOENEMY || comboType == CT_NOFLYZONE || comboType == CT_NOJUMPZONE)
ifLocationOkay = false;

// Check if there is a no enemy combo flag on the location
if(Screen->ComboF[comboNum] == CF_NOENEMY)
ifLocationOkay = false;

// If the location is acceptable, create the enemy there
if(ifLocationOkay)
{
CreateNPCAt(enemyNum, x, y);
break;
}
} //! End of while(true)
} //! End of void createEnemy(int enemyNum)

//A shorthand way to get a combo cset on the current layer.
//Layer 0 is the screen itself.
int GetLayerComboC(int layer, int combo) {
if (layer==0)
return Screen->ComboC[combo];
else
return Game->GetComboCSet(Screen->LayerMap(layer), Screen->LayerScreen(layer), combo);
}

//A shorthand way to set a combo cset on the current layer.
//Layer 0 is the screen itself.
void SetLayerComboC(int layer, int combo, int d) {
if (layer == 0)
Screen->ComboC[combo] = d;
else
Game->SetComboCSet(Screen->LayerMap(layer), Screen->LayerScreen(layer), combo, d);
}

// Returns the opposite direction based upon Dir-> values
// The oppositeDir in std.zh looked like it was for angles.
int getOppositeDir(int dir)
{
if(dir == DIR_UP)
return DIR_DOWN;
else if(dir == DIR_DOWN)
return DIR_UP;
else if(dir == DIR_LEFT)
return DIR_RIGHT;
else
return DIR_LEFT;
}

// Function to see if an lweapon has hit a x, y location
bool WeaponCollision(lweapon a, float x1, float y1, float x2, float y2)
{
int ax = a->X + a->HitXOffset;
int ay = a->Y + a->HitYOffset;
return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, x1, y1, x2, y2);
}

// Function to see if an eweapon has hit a x, y location
bool WeaponCollision(eweapon a, float x1, float y1, float x2, float y2)
{
int ax = a->X + a->HitXOffset;
int ay = a->Y + a->HitYOffset;
return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, x1, y1, x2, y2);
}

// Function to return if an lweapon has hit a solid object
bool WeaponSolidCollision(lweapon a)
{
// Variables for the weapon edge locations

bool ifMagic = a->ID == LW_MAGIC || a->ID == LW_REFMAGIC;

// Grab the center of the item
int x = a->X + a->HitXOffset + a->HitWidth / 2;
int y = a->Y + a->HitYOffset + a->HitHeight / 2;

// Loop through all locations and check if they're solid
if(Screen->isSolid(x, y))
{
// Grab the combo type of the location
int combo = Screen->ComboT[ComboAt(x, y)];

if(combo == CT_HOOKSHOTONLY)
return false;
// If the wand item is magic
else if(ifMagic)
{
// If the combo type is NOT a mirror or prism, it hit a solid object
if(combo 49)
return true;
}
// Else the spot is not magic, so it hit a solid object
else
return true;
}

// The weapon did not hit a solid object
return false;
}

// Function to return if an eweapon has hit a solid object
bool WeaponSolidCollision(eweapon a)
{
// Variables for the weapon edge locations

bool ifMagic = a->ID == EW_MAGIC || a->ID == EW_WIND;

// Grab the center of the item
int x = a->X + a->HitXOffset + a->HitWidth / 2;
int y = a->Y + a->HitYOffset + a->HitHeight / 2;

// Loop through all locations and check if they're solid
if(Screen->isSolid(x, y))
{
// If the wand item is magic
if(ifMagic)
{
// Grab the combo type of the location
int combo = Screen->ComboT[ComboAt(x, y)];

// If the combo type is NOT a mirror or prism, it hit a solid object
if(combo 49)
return true;
}
// Else the spot is not magic, so it hit a solid object
else
return true;
}

// The weapon did not hit a solid object
return false;
}

// Function to get the direction clockwise to the given direction (only 4 main directions)
int getClockwiseDir(int dir)
{
return getClockwiseDir(dir, false);
}

// Function to get the direction clockwise to the given direction
int getClockwiseDir(int dir, bool eightDir)
{
// If all 8 directions are needed
if(eightDir)
{
// Return the direction to the clockwise of the given direction
if(dir == DIR_UP)
return DIR_RIGHTUP;
else if(dir == DIR_RIGHTUP)
return DIR_RIGHT;
else if(dir == DIR_RIGHT)
return DIR_RIGHTDOWN;
else if(dir == DIR_RIGHTDOWN)
return DIR_DOWN;
else if(dir == DIR_DOWN)
return DIR_LEFTDOWN;
else if(dir == DIR_LEFTDOWN)
return DIR_LEFT;
else if(dir == DIR_LEFT)
return DIR_LEFTUP;
else
return DIR_UP;
}
// Else only the main 4 directions are needed
else
{
// Return the direction to the clockwise of the given direction
if(dir == DIR_UP)
return DIR_RIGHT;
else if(dir == DIR_RIGHT)
return DIR_DOWN;
else if(dir == DIR_DOWN)
return DIR_LEFT;
else
return DIR_UP;
}
} //! End of int getClockwise(int dir, bool eightDir)

int getCounterClockwiseDir(int dir)
{
return getCounterClockwiseDir(dir, false);
}

// Function to get the direction clockwise to the given direction
int getCounterClockwiseDir(int dir, bool eightDir)
{
// If all 8 directions are needed
if(eightDir)
{
// Return the direction to the clockwise of the given direction
if(dir == DIR_UP)
return DIR_LEFTUP;
else if(dir == DIR_LEFTUP)
return DIR_LEFT;
else if(dir == DIR_LEFT)
return DIR_LEFTDOWN;
else if(dir == DIR_LEFTDOWN)
return DIR_DOWN;
else if(dir == DIR_DOWN)
return DIR_RIGHTDOWN;
else if(dir == DIR_RIGHTDOWN)
return DIR_RIGHT;
else if(dir == DIR_RIGHT)
return DIR_RIGHTUP;
else
return DIR_UP;
}
// Else only the main 4 directions are needed
else
{
// Return the direction to the clockwise of the given direction
if(dir == DIR_UP)
return DIR_LEFT;
else if(dir == DIR_LEFT)
return DIR_DOWN;
else if(dir == DIR_DOWN)
return DIR_RIGHT;
else
return DIR_UP;
}
} //! End of int getClockwise(int dir, bool eightDir)

// This function checks if a location is walkable
// As in, it's not solid and it's not water
bool canWalk(float x, float y)
{
// Check if the location is solid
if(Screen->isSolid(x, y))
return false;

// Grab the combo locationj
int combo = ComboAt(x, y);

// If the combo is water, return false
if(Screen->ComboT[combo] == CT_WATER)
return false;

// Check if the location is out of bounds
if(x = 256)
return false;

if(y = 176)
return false;

// Else it's okay, so return true
return true;
}

// Function to see if an x, y location is valid to walk on
// x = x location
// y = y location
// fullTile = Whether a 16x16 area should be checked or the lower half (16x8) should be checked
// True = 16x16
// False = 16x8
bool canWalk(float x, float y, bool fullTile)
{
// If the full 16x16 grid needs to be checked
if(fullTile)
{
// Check all 4 corners of the grid and make sure they're not solid
if(canWalk(x, y) && canWalk(x + 8, y) && canWalk(x + 15, y)
&& canWalk(x, y + 8) && canWalk(x + 15, y + 8)
&& canWalk(x, y + 15) && canWalk(x + 8, y + 15) && canWalk(x + 15, y + 15))
// If they are not, return true
return true;
// Else one of the 4 corners of the grid is solid
else
// Return false
return false;
}
// Else the bottom half of the grid has to be checked
else
{
// Check all 4 corners of the grid and make sure they're not solid
if(canWalk(x, y + 8) && canWalk(x + 8, y + 8) && canWalk(x + 15, y + 8)
&& canWalk(x, y + 15) && canWalk(x + 8, y + 15) && canWalk(x + 15, y + 15))
// If they are not, return truee
return true;
// Else one of the 4 corners of the bottom half of the grid is solid
else
return false;
}
}

// Same as above, but checks a full rectangle
bool canWalk(float x1, float y1, float x2, float y2)
{
// Ensure (x1,y1) is the top left and (x2,y2) which
if(x1 > x2)
{
int temp = x1;
x1 = x2;
x2 = temp;
}

if(y1 > y2)
{
int temp = y1;
y1 = y2;
y2 = temp;
}

// Go through each
for(int x = x1; x < x2; x += 8)
{
if(!canWalk(x, y1))
return false;
if(!canWalk(x, y2))
return false;
}

for(int y = y1; y ComboT[comboNum];

// If the combo type is a no enemy combo
if(comboType == CT_NOENEMY)
return false;

// If it is NOT a flying enemy and the combo is a no ground enemy zone
if(!flying && comboType == CT_NOGROUNDENEMY)
return false;

// If it is a flying enemy and the combo is a no fly zone
if(flying && comboType == CT_NOFLYZONE)
return false;

// Check if there is a no enemy combo flag on the location
if(Screen->ComboF[comboNum] == CF_NOENEMY)
return false;

if(x < 0 || y 256 || y > 168)
return false;

if(flying)
return true;
else
return canWalk(x, y);
}

// Function to see if an x, y location is valid to walk on
// x = x location
// y = y location
// fullTile = Whether a 16x16 area should be checked or the lower half (16x8) should be checked
// True = 16x16
// False = 16x8
bool canWalkEnemy(float x, float y, bool flying, bool fullTile)
{
// If the full 16x16 grid needs to be checked
if(fullTile)
{
// Check all 4 corners of the grid and make sure they're not solid
if(canWalkEnemy(x, y, flying) && canWalkEnemy(x + 8, y, flying) && canWalkEnemy(x + 15, y, flying)
&& canWalkEnemy(x, y + 8, flying) && canWalkEnemy(x + 15, y + 8, flying)
&& canWalkEnemy(x, y + 15, flying) && canWalkEnemy(x + 8, y + 15, flying) && canWalkEnemy(x + 15, y + 15, flying))
// If they are not, return true
return true;
// Else one of the 4 corners of the grid is solid
else
// Return false
return false;
}
// Else the bottom half of the grid has to be checked
else
{
// Check all 4 corners of the grid and make sure they're not solid
if(canWalkEnemy(x, y + 8, flying) && canWalkEnemy(x + 8, y + 8, flying) && canWalkEnemy(x + 15, y + 8, flying)
&& canWalkEnemy(x, y + 15, flying) && canWalkEnemy(x + 8, y + 15, flying) && canWalkEnemy(x + 15, y + 15, flying))
// If they are not, return truee
return true;
// Else one of the 4 corners of the bottom half of the grid is solid
else
return false;
}
}

// Same as above, but checks a full rectangle
bool canWalk(float x1, float y1, float x2, float y2, bool flying)
{
// Ensure (x1,y1) is the top left and (x2,y2) which
if(x1 > x2)
{
int temp = x1;
x1 = x2;
x2 = temp;
}

if(y1 > y2)
{
int temp = y1;
y1 = y2;
y2 = temp;
}

// Go through each
for(int x = x1; x < x2; x += 8)
{
if(canWalkEnemy(x, y1, flying))
return false;
if(canWalkEnemy(x, y2, flying))
return false;
}

for(int y = y1; y X + Link->HitXOffset;
int ay = Link->Y + Link->HitYOffset;

// Check the collision
return RectCollision(ax, ay, ax+Link->HitWidth, ay+Link->HitHeight, x1, y1, x2, y2);
}

// Quickly edit the appearance of a ffc
// Object is a reference to the ffc to edit.
void editFFC(ffc object, int x, int y, int combo, int cset)
{
object->X = x;
object->Y = y;
object->Data = combo;
object->CSet = cset;
}

// Overload of the above that just edits the position
void editFFC(ffc object, int x, int y)
{
editFFC(object, x, y, object->Data, object->CSet);
}

// Basic function to handle secret flags. Returns true if a secret flag is activated
// These are scripted mimics of the ZQuest secret combo flags, but have a bit more flexibility for scripting.
bool checkCFlag(int x, int y, int x2, int y2, int flag)
{
// Flag for regular arrows
if(flag == CF_ARROW)
{
// Loop through all weapons
for(int i = 1; i NumLWeapons(); i++)
{
lweapon current = Screen->LoadLWeapon(i);

// Check if it's the right weapon
if(current->ID == LW_ARROW)
{
// Check if there was a collision
if(WeaponCollision(current, x, y, x2, y2))
{
current->DeadState = WDS_DEAD;
return true;
}
}
}

// Else it didn't hit
return false;
}
// Flag for the bombs
else if(flag == CF_BOMB)
{
// Loop through all weapons
for(int i = 1; i NumLWeapons(); i++)
{
lweapon current = Screen->LoadLWeapon(i);

// Check if it's the right weapon
if(current->ID == LW_BOMBBLAST)
{
// Check if there was a collision
if(WeaponCollision(current, x, y, x2, y2))
{
return true;
}
}
}

// Else it didn't hit
return false;
}
// Flag for the wand's magic
else if(flag == CF_WANDMAGIC)
{
// Loop through all weapons
for(int i = 1; i NumLWeapons(); i++)
{
lweapon current = Screen->LoadLWeapon(i);

// Check if it's the right weapon
if(current->ID == LW_MAGIC)
{
// Check if there was a collision
if(WeaponCollision(current, x, y, x2, y2))
{
current->DeadState = WDS_DEAD;
return true;
}
}
}

// Else it didn't hit
return false;
}
// Flag for a boomerang
else if(flag == CF_BRANG1 || flag == CF_BRANG2 || flag == CF_BRANG3)
{
// Loop through all weapons
for(int i = 1; i NumLWeapons(); i++)
{
lweapon current = Screen->LoadLWeapon(i);

// Check if it's the right weapon
if(current->ID == LW_BRANG)
{
// Check if there was a collision
if(WeaponCollision(current, x, y, x2, y2))
{
current->DeadState = WDS_BOUNCE;
return true;
}
}
}

// Else it didn't hit
return false;
}
// Flag for a sword
else if(flag == CF_SWORD1 || flag == CF_SWORD2 || flag == CF_SWORD3)
{
// Loop through all weapons
for(int i = 1; i NumLWeapons(); i++)
{
lweapon current = Screen->LoadLWeapon(i);

// Check if it's the right weapon
if(current->ID == LW_SWORD)
{
// Check if there was a collision
if(WeaponCollision(current, x, y, x2, y2))
return true;
}
}

// Else it didn't hit
return false;
}
// Flag for a hookshot
else if(flag == CF_HOOKSHOT)
{
// Loop through all weapons
for(int i = 1; i NumLWeapons(); i++)
{
lweapon current = Screen->LoadLWeapon(i);

// Check if it's the right weapon
if(current->ID == LW_HOOKSHOT)
{
// Check if there was a collision
if(WeaponCollision(current, x, y, x2, y2))
{
current->DeadState = WDS_BOUNCE;
return true;
}
}
}

// Else it didn't hit
return false;
}
// Flag for a hammer
else if(flag == CF_HAMMER)
{
// Loop through all weapons
for(int i = 1; i NumLWeapons(); i++)
{
lweapon current = Screen->LoadLWeapon(i);

// Check if it's the right weapon
if(current->ID == LW_HAMMER)
{
// Check if there was a collision
if(WeaponCollision(current, x, y, x2, y2))
{
current->DeadState = WDS_DEAD;
return true;
}
}
}

// Else it didn't hit
return false;
}
// Flag for any weapon
else if(flag == CF_STRIKE)
{
// Loop through all weapons
for(int i = 1; i NumLWeapons(); i++)
{
lweapon current = Screen->LoadLWeapon(i);

if(current->ID == LW_SPARKLE) continue;
if(current->ID == LW_FIRESPARKLE) continue;
if(current->ID == LW_BOMB) continue;
if(current->ID == LW_SBOMB) continue;
if(current->ID == LW_BAIT) continue;
if(current->DeadState > 0 && current->ID != LW_BRANG) continue;
if(!current->CollDetection) continue;

if(WeaponCollision(current, x, y, x2, y2))
{
if(current->ID == LW_BRANG || current->ID == LW_HOOKSHOT)
current->DeadState = WDS_BOUNCE;
else
current->DeadState = WDS_DEAD;
return true;
}
}

// Else it didn't hit
return false;
}
// Flag for a Link step switch
else if(flag == CF_STEP)
{
x = Floor(x / 16) * 16;
y = Floor(y / 16) * 16;

// If the distance from the switch to Link is X, Link->Y, x, y) X+2, object->Y+2, object->X+object->EffectWidth-3, object->Y+object->EffectHeight-3, flag);
}

// Function for an eweapon secret flag
bool checkCFlag(eweapon object, int flag)
{
// Check the span of the eweapon for the flag
int ax = object->X + object->HitXOffset;
int ay = object->Y + object->HitYOffset;

return checkCFlag(ax, ay, ax+object->HitWidth, ay+object->HitHeight, flag);
}

// Function for an npc secret flag
bool checkCFlag(npc object, int flag)
{
// Check the span of the eweapon for the flag
int ax = object->X + object->HitXOffset;
int ay = object->Y + object->HitYOffset;

return checkCFlag(ax+2, ay+2, ax+object->HitWidth-3, ay+object->HitHeight-3, flag);
}

// Function to wait until a secret flag happens in a rectangle
void waitUntilCFlag(int x1, int y1, int x2, int y2, int flag)
{
while(!checkCFlag(x1, y1, x2, y2, flag))
Waitframe();
}

// Function to wait until a secret flag happens in a 16x16 location
void waitUntilCFlag(int x, int y, int flag)
{
while(!checkCFlag(x, y, flag))
Waitframe();
}

// Function to wait until a secret flag happens on a FFC
void waitUntilCFlag(ffc object, int flag)
{
while(!checkCFlag(object, flag))
Waitframe();
}

// Normal CFlag function on a rectangle that will wait until one happens, then activate secrets
void CFlag(int x1, int y1, int x2, int y2, int flag, bool SFX)
{
// Wait until the location was hit
waitUntilCFlag(x1, y1, x2, y2, flag);

// Activate secrets
Screen->TriggerSecrets();

// If requested, play the normal secret SFX
if(SFX)
Game->PlaySound(SFX_SECRET);
}

// Normal CFlag function on combo that will wait until one happens, then activate secrets
void CFlag(int x, int y, int flag, bool SFX)
{
// Wait until the location was hit
waitUntilCFlag(x, y, flag);

// Activate secrets
Screen->TriggerSecrets();

// If requested, play the normal secret SFX
if(SFX)
Game->PlaySound(SFX_SECRET);
}

// Normal CFlag function on combo that will wait until one happens, then activate secrets
void CFlag(ffc object, int flag, bool SFX)
{
// Wait until the location was hit
waitUntilCFlag(object, flag);

// Activate secrets
Screen->TriggerSecrets();

// If requested, play the normal secret SFX
if(SFX)
Game->PlaySound(SFX_SECRET);
}

// Checks if the given direction is the only direction being pressed.
bool isOnlyDirection(int direction)
{
int directions = 0;
// Add up the directions with an offset of 1 (so that Up registers as something)
if(Link->InputUp)
directions += DIR_UP + 1;
if(Link->InputDown)
directions += DIR_DOWN + 1;
if(Link->InputLeft)
directions += DIR_LEFT + 1;
if(Link->InputRight)
directions += DIR_RIGHT + 1;

// Remove offset and do final check...
if(directions - 1 == direction)
return true;
else
return false;
}//!End isOnlyDirection

// Function to move a FFC in the direction of a radian angle
void ffcAngularMovement(ffc theffc, float angle, int speed)
{
// First find out the x and y unit circle values
int unitX = RadianCos(angle);
int unitY = RadianSin(angle);

// Set the ffc's Vx and Vy to speed * unit circle value
theffc->Vx = unitX * speed;
theffc->Vy = unitY * speed;
}

// Function to tell if Link is about to leave the screen
bool leavingScreen()
{
if(Link->X InputLeft)
return true;
else if(Link->Y InputUp)
return true;
else if(Link->X >= 239 && Link->InputRight)
return true;
else if(Link->Y >= 159 && Link->InputDown)
return true;
else
return false;
}

// Function to see if a box has collided with a line
bool lineBoxCollision(int lineX1, int lineY1, int lineX2, int lineY2, int boxX1, int boxY1, int boxX2, int boxY2, int boxBorder)
{
// Shrink down the box for the border
boxX1 += boxBorder; boxY1 += boxBorder;
boxX2 -= boxBorder; boxY2 -= boxBorder;

// If the line isn't vertical
if(lineX2!=lineX1)
{

float i0 = (boxX1 - lineX1)/(lineX2-lineX1);
float i1 = (boxX2 - lineX1)/(lineX2-lineX1);

float yA = lineY1 + i0*(lineY2-lineY1);
float yB = lineY1 + i1*(lineY2-lineY1);

if(Max(boxX1, boxX2) >= Min(lineX1, lineX2) && Min(boxX1, boxX2) = Min(lineY1, lineY2) && Min(boxY1, boxY2) Max(yA, yB) || Max(boxY1, boxY2) = boxX1 && lineX1 lineYMax)
{
lineYMin = lineY2;
lineYMax = lineY1;
}

// If either point intersects
if((boxY1 >= lineYMin && boxY1 = lineYMin && boxY2 = PI)
dif -= 2 * PI;
else if(dif = 0 && x = 0 && y DrawString(layer, x-1, y-1, font, borderColor, -1, alignment, text, opacity);
Screen->DrawString(layer, x, y-1, font, borderColor, -1, alignment, text, opacity);
Screen->DrawString(layer, x+1, y-1, font, borderColor, -1, alignment, text, opacity);
Screen->DrawString(layer, x-1, y, font, borderColor, -1, alignment, text, opacity);
Screen->DrawString(layer, x+1, y, font, borderColor, -1, alignment, text, opacity);
Screen->DrawString(layer, x-1, y+1, font, borderColor, -1, alignment, text, opacity);
Screen->DrawString(layer, x, y+1, font, borderColor, -1, alignment, text, opacity);
Screen->DrawString(layer, x+1, y+1, font, borderColor, -1, alignment, text, opacity);
Screen->DrawString(layer, x, y, font, textColor, -1, alignment, text, opacity);
}

void drawIntegerBordered(int layer, int x, int y, int font, int textColor, int borderColor, int number, int opacity)
{
Screen->DrawInteger(layer, x-1, y-1, font, borderColor, -1, -1, -1, number, 0, opacity);
Screen->DrawInteger(layer, x, y-1, font, borderColor, -1, -1, -1, number, 0, opacity);
Screen->DrawInteger(layer, x+1, y-1, font, borderColor, -1, -1, -1, number, 0, opacity);
Screen->DrawInteger(layer, x-1, y, font, borderColor, -1, -1, -1, number, 0, opacity);
Screen->DrawInteger(layer, x+1, y, font, borderColor, -1, -1, -1, number, 0, opacity);
Screen->DrawInteger(layer, x-1, y+1, font, borderColor, -1, -1, -1, number, 0, opacity);
Screen->DrawInteger(layer, x, y+1, font, borderColor, -1, -1, -1, number, 0, opacity);
Screen->DrawInteger(layer, x+1, y+1, font, borderColor, -1, -1, -1, number, 0, opacity);
Screen->DrawInteger(layer, x, y, font, textColor, -1, -1, -1, number, 0, opacity);
}

void drawCharacterBordered(int layer, int x, int y, int font, int textColor, int borderColor, int glyph, int opacity){
Screen->DrawCharacter(layer, x-1, y-1, font, borderColor, -1, -1, -1, glyph, opacity);
Screen->DrawCharacter(layer, x, y-1, font, borderColor, -1, -1, -1, glyph, opacity);
Screen->DrawCharacter(layer, x+1, y-1, font, borderColor, -1, -1, -1, glyph, opacity);
Screen->DrawCharacter(layer, x-1, y, font, borderColor, -1, -1, -1, glyph, opacity);
Screen->DrawCharacter(layer, x+1, y, font, borderColor, -1, -1, -1, glyph, opacity);
Screen->DrawCharacter(layer, x-1, y+1, font, borderColor, -1, -1, -1, glyph, opacity);
Screen->DrawCharacter(layer, x, y+1, font, borderColor, -1, -1, -1, glyph, opacity);
Screen->DrawCharacter(layer, x+1, y+1, font, borderColor, -1, -1, -1, glyph, opacity);
Screen->DrawCharacter(layer, x, y, font, textColor, -1, -1, -1, glyph, opacity);
}

Credits

Moosh, Evan, Aevin, and all users that have contributed to this work.

Recent Resources