PDA

View Full Version : FFCs Carry Over after Death



sps999
03-09-2009, 05:33 PM
I'm using the ball and chain script and it requires an Item and the appropriate FFC on the screen. The room the Ball and Chain is in has the FFC in it with the Carry Over flag checked. The Ball and Chain will carry over with me, until I die. Then, the only way to get the Ball and Chain to work is if I go into the original room to get the FFC back. Anyone know a way aroung this?

Joe123
03-10-2009, 01:38 PM
Use a global script rather than an ffc script.

jman2050
03-10-2009, 01:40 PM
You could also note all the points in your quest where you can continue after you die and place the ball-and-chain script on those screens to ensure that the script will reactivate. I believe this is what C-Dawg was doing in his Zodiac quest.

sps999
03-10-2009, 05:05 PM
Use a global script rather than an ffc script.


If I could I would, but I don't know how to change an FFC to a global script. Especially considering I didn't make it.

And putting an FFC on each continue screen is a pain, but I would do it as a lst resort.

Joe123
03-10-2009, 06:09 PM
Post the script and I'll do it.
Shouldn't take more than a couple of minutes.

sps999
03-10-2009, 06:18 PM
Here is the FFC:


//FFC Script BallnChain
//Simply handles the ball and chain item's functionality.
ffc script BallnChain {
void run() {
ballChainUse = false;
int rotCount = 360;
int ballLoc = 0;
int ballX = 0;
int ballY = 0;
while(true)
{
if (ballChainUse && rotCount > 359)
{
ballChainUse = false;
if (Link->Dir == DIR_RIGHT)
{
rotCount = 0;
}
else if (Link->Dir == DIR_RIGHTDOWN)
{
rotCount = 45;
}
else if (Link->Dir == DIR_DOWN)
{
rotCount = 90;
}
else if (Link->Dir == DIR_LEFTDOWN)
{
rotCount = 135;
}
else if (Link->Dir == DIR_LEFT)
{
rotCount = 180;
}
else if (Link->Dir == DIR_LEFTUP)
{
rotCount = 225;
}
else if (Link->Dir == DIR_UP)
{
rotCount = 270;
}
else if (Link->Dir == DIR_RIGHTUP)
{
rotCount = 315;
}
}
if (rotCount > 359)
{
Waitframe();
}
else
{
while(Link->InputB)
{
Link->InputA = false;
Link->Action = LA_CHARGING;
ballX = Link->X + (Cos(rotCount) * 32.1);
ballY = Link->Y + (Sin(rotCount) * 32.1) - 3;
Screen->DrawTile(2, Link->X + (Cos(rotCount) * 8.1), Link->Y + (Sin(rotCount) * 8.1) - 2,
itemTile + 1, 1, 1, itemCSet, 1, 0, 0, 0, 0, 1, 128);
Screen->DrawTile(2, Link->X + (Cos(rotCount) * 16.1), Link->Y + (Sin(rotCount) * 16.1) - 2,
itemTile + 1, 1, 1, itemCSet, 1, 0, 0, 0, 0, 1, 128);
Screen->DrawTile(2, Link->X + (Cos(rotCount) * 24.1), Link->Y + (Sin(rotCount) * 24.1) - 2,
itemTile + 1, 1, 1, itemCSet, 1, 0, 0, 0, 0, 1, 128);
Screen->DrawTile(2, ballX, ballY, itemTile, 1, 1, itemCSet, 1, 0, 0, 0, 0, 1, 128);
Waitframe();
rotCount+=5;
if (rotCount >= 360)
{
rotCount = 0;
}
//Standard 4-way facing
if (rotCount >= 315 || rotCount < 45)
{
Link->Dir = DIR_RIGHT;
}
else if (rotCount >= 225)
{
Link->Dir = DIR_UP;
}
else if (rotCount >= 130)
{
Link->Dir = DIR_LEFT;
}
else if (rotCount >= 45)
{
Link->Dir = DIR_DOWN;
}
//Only use if diagonal facing is supported
//if (rotCount >= 340 || rotCount < 25)
//{
// Link->Dir = DIR_RIGHT;
//}
//else if (rotCount >= 295)
//{
// Link->Dir = DIR_RIGHTUP;
//}
//else if (rotCount >= 250)
//{
// Link->Dir = DIR_UP;
//}
//else if (rotCount >= 205)
//{
// Link->Dir = DIR_LEFTUP;
//}
//else if (rotCount >= 160)
//{
// Link->Dir = DIR_LEFT;
//}
//else if (rotCount >= 115)
//{
// Link->Dir = DIR_LEFTDOWN;
//}
//else if (rotCount >= 70)
//{
// Link->Dir = DIR_DOWN;
//}
//else if (rotCount >= 25)
//{
// Link->Dir = DIR_RIGHTDOWN;
//}
//ballLoc = ComboAt(ball->X + 8, ball->Y + 8);
ballLoc = ComboAt(ballX + 8, ballY + 8);
if (Screen->ComboI[ballLoc] == CF_SCRIPT1 && Screen->ComboT[ballLoc] == CT_PUSHHEAVY2)
{
Screen->ComboD[ballLoc]++;
}
int enemyCount;
int inc;
enemyCount = Screen->NumNPCs();
for (inc = 1; inc < enemyCount + 1; inc++)
{
npc hitEnemy = Screen->LoadNPC(inc);
if (Abs(hitEnemy->X - ballX) < 6 && Abs(hitEnemy->Y - ballY) < 6)
{
hitEnemy->HP-=itemDamage;
}
}
}
rotCount = 360;
}
}
}

And if neccasery, here is the Item that uses the FFC:


//Item Ball and Chain
//D0 = The tile used by the ball itself. The chain tiles are the tile after the ball tile
//D1 = The CSet of the ball
//D2 = The damage the ball will deal to enemies
item script BallandChain {
void run(int ballTile, int ballCSet, int damage) {
ballChainUse = true;
itemTile = ballTile;
itemCSet = ballCSet;
itemDamage = damage;
}
}



Oh, and if you could (don't have to) lable the parts of the script so I could put it into my global script. (Function, Variables, Function Call, etc.) I'm actually not sure if those would even be in it, but if they are I would respect if they're labled.

Joe123
03-11-2009, 12:51 PM
import "std.zh"
//Global input constants
const int CF_BALLCHAIN = 98; //BallandChain->Next flag
const int T_BALL = 0; //Tile for the ball to use
const int T_CHAIN = 0; //Tile for the chain segments to use
const int BallChainCSet = 0; //CSet for the ball and chain to use
const int BallChainDamage = 0; //Damage for the ball to deal
const int BallChainSpeed = 5; //Speed with which the ball is swung

//Global variables
bool BallChainUse;
int BallChainCounter;

//Global functions
//Store whether Link pressed A or B to use an item
int StoreInput;
void StoreInput(){
if(Link->InputA && !Link->InputB) StoreInput = 1;
else if(Link->InputB && !Link->InputA) StoreInput = 2;
else StoreInput = 0;
}

//Global script
global script Slot2{
void run(){
while(true){
//Call the ball and chain functions
if(BallChainUse) BallChain();

Waitframe();
}
}
//The ball and chain functions
void BallChain(){
//Check whether the ball should still be going
if((StoreInput == 1 && Link->InputA) || (StoreInput == 2 && Link->InputB)){
//Draw the ball and chain
for(int i=1;i<=4;i++) DrawBall(BallChainCounter,i*8);

//Enemy damage routines
int ballX = Link->X+32*Cos(BallChainCounter);
int ballY = Link->Y+32*Sin(BallChainCounter);
for(int i=1;i<=Screen->NumNPCs();i++){
npc e = Screen->LoadNPC(i);
if(Abs(e->X-ballX) < 6 && Abs(e->Y-ballY) < 6) e->HP-=BallChainDamage;
}
//BallAndChain->Next routines
int loc = ComboAt(ballX+8,ballY+8);
if(Screen->ComboI[loc] == CF_BALLCHAIN || Screen->ComboF[loc] == CF_BALLCHAIN) Screen->ComboD[loc]++;

//Link's graphics
Link->Action = LA_CHARGING;
if(BallChainCounter >= 315 || BallChainCounter < 45) Link->Dir = DIR_RIGHT;
else if(BallChainCounter >= 225) Link->Dir = DIR_UP;
else if(BallChainCounter >= 130) Link->Dir = DIR_LEFT;
else if(BallChainCounter >= 45) Link->Dir = DIR_DOWN;

//Move the ball around the circle
BallChainCounter = (BallChainCounter%(360*BallChainSpeed))+BallChainS peed;
}else BallChainUse = false;
}
//The ball drawing functions
void DrawBall(int i,int r){
int x = Link->X+r*Cos(i); int y = Link->Y-2+r*Sin(i);
int tile = T_CHAIN;
if(r>30) tile = T_BALL;
Screen->DrawTile(3,x,y,tile,1,1,BallChainCSet,1,0,0,0,0,1, 128);
}
}

//Ball and Chain activiation script
item script BallChain{
void run(){
BallChainUse = true;
if(Link->Dir == DIR_RIGHT) BallChainCounter = 0;
else if(Link->Dir == DIR_DOWN) BallChainCounter = 90;
else if(Link->Dir == DIR_LEFT) BallChainCounter = 180;
else if(Link->Dir == DIR_UP) BallChainCounter = 270;
}
}
I ended up re-writing most of it because it was really messy.
As to why it uses drawtile and loading the enemy rather than creating lweapons I'm not entirely sure, but I couldn't be bothered to change that much.

I haven't actually tested it yet, but it should work. If it doesn't just poke me and I'll fix it, there's nothing major wrong with it. Obviously you have to input how you want it to work at the top of the script this time, rather than in the item's D0 etc.
I also added an extra speed variable.

I noted it up for you too :thumbsup:

HeroOfFire
03-11-2009, 02:25 PM
The origins of this script are old. Really old. As in, prior to the enemy editor, betas are called betas old. To say the least, lweapons were not around back then.

I had cleaned up the script over time, but I only recently worked with lweapons and making them "pass through" enemies. I have not worked with global scripts before though, but it looks like a simple conversion.

One thing to note is the variables set in the item script are there because then the ball and chain script supports multiple ball and chain items. I generally avoid constants unless they are something like "ATK_MELEE_STAB = 1". I do like the idea of rotation speed being variable.

Due to really bad computer luck, I have access to the script but no access to the quest I was using it in. I was planning on an update of that script collection, with new scripts and additional functionality, and I will look at improving the ball and chain script.

sps999
03-11-2009, 04:20 PM
An error message occured...

...TMP, Line 43: Error T39: That pointer type does not have a variable NumNPCs...

Straight from ZC.

Joe123
03-11-2009, 04:47 PM
I edited it, try again now.

sps999
03-12-2009, 05:03 PM
How do I actually use it in game, cause you said you changed it. The old one had to use the letter, is that changed to Custom Item Class? Either way, neither of them do anything at all in game.

Joe123
03-12-2009, 05:24 PM
Custom item class would be preferable yes...

Tell me what you're doing exactly, because the set-up should be the same (except you have to set the constansts at the top).