PDA

View Full Version : Gun script



C-Dawg
01-03-2007, 10:07 AM
I'll check this out when I get home, but just coded up a gun script.



// ===================================
// gun - This FFC will act as a gun. The user
// specifies which direction the gun will fire. When
// the player is lined up with the proper direction,
// the gun will briefly switch to the next combo.
// It will move the projectile FFC to its location, and
// send it outwards in the proper direction. Projectiles will
// be blocked by solid combos on layer 0.
// D0 = delay between shots.
// D1 = FFC number of the projectile combo
// D2 = speed of the projectile
// D3 = 1 if the gun can shoot north
// D4 = 1 if the gun can shoot south
// D5 = 1 if the gun can shoot east
// D6 = 1 if the gun can shoot west
// D7 = 1 if the gun is omnidirectional (meaning it will
// fire at angles, regardless of where the player is.)
// NOTE - If you make the projectile move too fast, it may zip off
// of the screen before the script can save it. Keep the speed under
// 16 to prevent this.
// ==========================================

ffc script gun{

void run(int shot_delay, int projectile_ffc_number, int projectile_speed, int shoots_north,
int shoots_south, int shoots_east, int shoots_west, int omnidirectional){

int gun_state = 0; // 0 = primed and waiting for the player to come in range.
// 1 = firing
// 2 = waiting

int firing_delay = 20; // Hard-coded delay while gun animation plays. Counter for state 1.

int delay_counter = shot_delay; // Counter for state 2.

int side_A; int side_B; int side_C; // Used to calculate the angle in an omnidirectional gun.

projectile = ffc Screen->LoadFFC(projectile_ffc_number);

while (true){

if (gun_state == 0){

if ( (shoots_north == 1) && (Link->X < this->X+16) && (Link->X > this->X-1) && (Link->Y < this->Y)){

projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vy = -projectile_speed;
projectile->Vx = 0;
gun_state = 1;
this->Data++;
}

if ( (shoots_south == 1) && (Link->X < this->X+16) && (Link->X > this->X-1) && (Link->Y > this->Y)){

projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vy = projectile_speed;
projectile->Vx = 0;
gun_state = 1;
this->Data++;
}

if ( (shoots_east == 1) && (Link->Y < this->Y+16) && (Link->Y > this->Y-1) && (Link->X > this->X)){

projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vx = projectile_speed;
projectile->Vy = 0;
gun_state = 1;
this->Data++;
}

if ( (shoots_west == 1) && (Link->Y < this->Y+16) && (Link->Y > this->Y-1) && (Link->X < this->X)){

projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vx = -projectile_speed;
projectile->Vy = 0;
gun_state = 1;
this->Data++;
}

if(omnidirectional == 1){

// First, check to see if the player is linked up vertically with the gun. Need to do this
// because, otherwise, the angle checking code will divide by zero OH SHI

if(Link->X = this->X){
if ( Link->Y > this->Y){
projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vy = projectile_speed;
projectile->Vx = 0;
gun_state = 1;
this->Data++;
}
if ( Link->Y < this->Y){
projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vy = -projectile_speed;
projectile->Vx = 0;
gun_state = 1;
this->Data++;
}

// If not, calculate the angle to move the shooter.
else{

side_A = this->Y - Link->y; // length of side of right triangle parallel to X axis
side_B = this->X; // length of side of right triangle perpendicular to X axis
side_C = Sqrt( (side_A*sideA) + (sideB*sideB) ); // length of hypotenuse

projectile->X = this->X;
projectile->Y = this->Y;

projectile->Vy = speed * (side_A / side_C); // Sin of the angle is opp/hyp
projectile->Vx = speed * (side_B / side_C); // Cos of the angle is adj/hyp

gun_state = 1;
this->Data++;
}
}

} // end of state 0

if ( gun_state == 1){

if(firing_delay >= 0){
firing_delay--;
}
else{
firing_delay = 20;
this->Data--;
gun_state = 2;
}

} // end of state 1

if ( gun_state == 2){

if(delay_counter >= 0){
delay_counter--;
}
else{
delay_counter = shot_delay;
gun_state = 0;
}
} // end of state 2

if ( projectile is off the screen) {

projectile->Vx = 0;
projectile->Vy = 0;
projectile->X = 0;
projectile->Y = -16;
}

Waitframe();
} // end of while loop

} // end of void run

} // end of ffc script

Majora
01-03-2007, 10:25 PM
Is this gun like a shooter enemy? or does it make Link a GTA character?

Revfan9
01-03-2007, 11:47 PM
Yes MW, it's like a shooting enemy. Pretty cool C-Dawg.

C-Dawg
01-04-2007, 12:09 AM
It's buggy. I'm fixing it now, it'll be in script showcase in a moment.

Or not. I'm getting wierd behavior now.



// ===================================
// gun - This FFC will act as a gun. The user
// specifies which direction the gun will fire. When
// the player is lined up with the proper direction,
// the gun will briefly switch to the next combo.
// It will move the projectile FFC to its location, and
// send it outwards in the proper direction. Projectiles will
// be blocked by solid combos on layer 0.
// D0 = delay between shots.
// D1 = FFC number of the projectile combo
// D2 = speed of the projectile
// D3 = 1 if the gun can shoot north
// D4 = 1 if the gun can shoot south
// D5 = 1 if the gun can shoot east
// D6 = 1 if the gun can shoot west
// D7 = 1 if the gun is omnidirectional (meaning it will
// fire at angles, regardless of where the player is.)
// NOTE - If you make the projectile move too fast, it may zip off
// of the screen before the script can save it. Keep the speed under
// 16 to prevent this.
// ==========================================

ffc script gun{

void run(int shot_delay, int projectile_ffc_number, int projectile_speed, int shoots_north,
int shoots_south, int shoots_east, int shoots_west, int omnidirectional){

int gun_state = 0; // 0 = primed and waiting for the player to come in range.
// 1 = firing
// 2 = waiting

int firing_delay = 20; // Hard-coded delay while gun animation plays. Counter for state 1.

int delay_counter = shot_delay; // Counter for state 2.

int side_A; int side_B; int side_C; // Used to calculate the angle in an omnidirectional gun.

ffc projectile = Screen->LoadFFC(projectile_ffc_number);

while (true){

if (gun_state == 0){

if ( (shoots_north == 1) && (Link->X < this->X+16) && (Link->X > this->X-1) && (Link->Y < this->Y)){

projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vy = -projectile_speed;
projectile->Vx = 0;
gun_state = 1;
this->Data++;
}

if ( (shoots_south == 1) && (Link->X < this->X+16) && (Link->X > this->X-1) && (Link->Y > this->Y)){

projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vy = projectile_speed;
projectile->Vx = 0;
gun_state = 1;
this->Data++;
}

if ( (shoots_east == 1) && (Link->Y < this->Y+16) && (Link->Y > this->Y-1) && (Link->X > this->X)){

projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vx = projectile_speed;
projectile->Vy = 0;
gun_state = 1;
this->Data++;
}

if ( (shoots_west == 1) && (Link->Y < this->Y+16) && (Link->Y > this->Y-1) && (Link->X < this->X)){

projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vx = -projectile_speed;
projectile->Vy = 0;
gun_state = 1;
this->Data++;
}

if(omnidirectional == 1){

// First, check to see if the player is linked up vertically with the gun. Need to do this
// because, otherwise, the angle checking code will divide by zero OH SHI

if(Link->X == this->X){
if ( Link->Y > this->Y){
projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vy = projectile_speed;
projectile->Vx = 0;
gun_state = 1;
this->Data++;
}
else{
projectile->X = this->X;
projectile->Y = this->Y;
projectile->Vy = -projectile_speed;
projectile->Vx = 0;
gun_state = 1;
this->Data++;
}
}
// If not, calculate the angle to move the shooter.
else{

side_A = this->Y - Link->Y; // length of side of right triangle parallel to X axis
side_B = this->X; // length of side of right triangle perpendicular to X axis
side_C = Sqrt( (side_A*side_A) + (side_B*side_B) ); // length of hypotenuse

projectile->X = this->X;
projectile->Y = this->Y;

projectile->Vy = projectile_speed * (side_A / side_C); // Sin of the angle is opp/hyp
projectile->Vx = projectile_speed * (side_B / side_C); // Cos of the angle is adj/hyp

gun_state = 1;
this->Data++;
}
}

} // end of state 0

if ( gun_state == 1){

if(firing_delay >= 0){
firing_delay--;
}
else{
firing_delay = 20;
this->Data--;
gun_state = 2;
}

} // end of state 1

if ( gun_state == 2){

if(delay_counter >= 0){
delay_counter--;
}
else{
delay_counter = shot_delay;
gun_state = 0;
}
} // end of state 2

if ( (projectile->X < 0) || (projectile->Y < 0) ||
(projectile->Y > 160) || (projectile->X > 240) ) {

projectile->Vx = 0;
projectile->Vy = 0;
projectile->X = 0;
projectile->Y = -16;
}

Waitframe();

} // end of while loop

} // end of void run

} // end of ffc script


A gun shooting N, S, E, or W works just fine. But add a second gun to the same screen and it gets all weird. Unpredictable effects. THIS SHOULD NOT HAPPEN THERE ARE NO GLOBAL VARIABLES.

The omnidirectional gun doesn't seem to work at all. It fires towards the upper right constantly in my test.

_L_
01-04-2007, 02:06 AM
The scripting system was made under the assumption that no two FFCs would ever run the same script. See here (http://www.armageddongames.net/showthread.php?t=94173) for what's being done about it.

jman2050
01-04-2007, 10:59 AM
An alternative, for the time being, is to copy the script and have it compile it two or three different times, depending on how many you want on-screen simultaneously. It wastes script slots, but until the scripting system is tweaked I don't see a choice.

C-Dawg
01-04-2007, 02:20 PM
Not a problem. If I max out the script slots, I'll just whine for you guys to increase the number.

Still, it's awfully nice to have a grip on why multiple FFCs go haywire now. I've been using ZQuest long enough to have made my peace with workarounds. Hell, they usually lead to new ways to use the engine.

C-Dawg
01-05-2007, 01:13 AM
Actually, I don't think that works. Anyone actually tried making multiple copies of the same FFC script with different names? It seems like all of the scripts keep working as if they were all running on FFC1 or something.

Saffith
01-05-2007, 01:57 AM
Yeah, that seems to be exactly what it's doing. Apparently, each FFC's script affects FFC #1 instead of whichever it's attached to. Another problem with REFFFC, perhaps?
Sigh. It'd be great if all this stuff would work right, but...

C-Dawg
01-05-2007, 12:14 PM
The problem seems to be that "this->whatever" always points to FFC1. That doesn't sound too hard to fix. (DarkDragon?)