Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // This script makes an FFC act as a guard. If Link enters its field of
- // vision, it will either warp him to another screen or become an enemy.
- // It can also play a sound and display a message when it spots him.
- // Setup
- //
- // The guard uses eight combos. The first four show it standing still,
- // facing up, down, left, and right, respectively. The next four show
- // it walking in the same directions. The combos facing upward must have
- // numbers divisible by 4; that is, they must be in the left column of
- // the list. The FFC must start out on one of the standing combos, even
- // if it will walk constantly. If the combos are set up correctly, it
- // will automatically figure out which way it's facing.
- //
- // Set flag 46 on flags that guards should not be able to see through.
- // If the guard will move, set flag 44 and 45 to mark its path. It will
- // always move straight ahead if it can. When it reaches the point where
- // it can't go any farther, if it is standing on flag 45, it will stop
- // and turn around for a moment before moving on. Both placed and inherent
- // flags will work.
- // Arguments
- //
- // If an argument has a default value, this will be used if you leave the
- // value at 0. The script will try to correct invalid values except for D0.
- //
- // D0: Movement type
- // Determines how the guard moves.
- // 0: Walks along flags 44 and 45; at an intersection, the guard will
- // turn left if possible
- // 1: The same as 0, except it will try to turn right instead of left
- // 2: The guard will not move at all
- // 3: The guard will stand in place, turning clockwise
- // 4: The guard will stand in place, turning counterclockwise
- // 5: The guard stand in place, turning left and right
- // D1: Reaction to Link
- // What the guard will do if it sees Link.
- // 0: Warp Link to another screen
- // 1: Turn into an enemy
- // D2: Speed
- // How fast the guard will move. Affects both walking and turning speed.
- // You can set a default below, which will be used if D2 is left at 0.
- // D3: Message
- // When the guard sees Link, it will show this message. If this is left
- // at 0, no message will be displayed.
- // D4: Destination DMap
- // If the guard warps Link when it spots him, this is the DMap it will
- // warp him to.
- // D5: Destination screen
- // If the guard warps Link when it spots him, this is the screen it will
- // warp him to. Remember that this must be converted from the hexadecimal
- // numbers used in ZQuest.
- // D6: Enemy ID
- // If the guard becomes an enemy when it spots Link, this is the ID number
- // of the type of enemy it will become.
- // D7: Screen->D index
- // When the guard spots Link, it will set this screen variable. This will
- // alert all other guards that use the same number, and potentially other
- // scripts. This must be a whole number between 0 and 7. If you have both
- // warping and enemy guards on the same screen, they should not use the
- // same number. If this is set to a negative number, it will not be used.
- // The guard's speed if D2 is left at 0.
- const int CGUARD_DEFAULT_SPEED=0.75;
- // The guard will play this sound when it sees Link. If this is set to 0, no
- // sound will be played.
- const int CGUARD_SOUND=88;
- // If this is set to anything but 0, the guard will notice Link if he's very
- // close, even if he's out of sight.
- const int CGUARD_FIND_LINK_IF_CLOSE=1;
- // How close Link must be to be found when out of sight.
- const int CGUARD_FIND_LINK_DISTANCE=24;
- // The angle of the guard's field of vision.
- const int CGUARD_VISION_ANGLE=75;
- // The maximum distance at which the guard can see Link.
- const int CGUARD_VISION_RANGE=160;
- // Movement types
- const int CGUARD_PATROL_LEFT=0;
- const int CGUARD_PATROL_RIGHT=1;
- const int CGUARD_STAND=2;
- const int CGUARD_ROTATE_CW=3;
- const int CGUARD_ROTATE_CCW=4;
- const int CGUARD_LEFT_AND_RIGHT=5;
- // Reaction types
- const int CGUARD_WARP=0;
- const int CGUARD_BECOME_ENEMY=1;
- const int CGUARD_WALK_FLAG=44;
- const int CGUARD_TURN_FLAG=45;
- const int CGUARD_BLOCK_FLAG=46;
- ffc script CastleGuard
- {
- void run(int movement, int reaction, float speed, int message,
- int destDMap, int destScreen, int enemyID, int screenDIndex){
- // Infer direction from combo number
- int direction=this->Data%4;
- // First standing and walking combos
- int baseStandCombo=this->Data-direction;
- int baseWalkCombo=baseStandCombo+4;
- // Initialize the screen variable
- if(screenDIndex>=0)
- Screen->D[screenDIndex]=0;
- if(speed==0)
- speed=CGUARD_DEFAULT_SPEED;
- // Stand in place
- if(movement==CGUARD_STAND)
- {
- while(true)
- Wait(1, reaction, message, destDMap, destScreen,
- enemyID, screenDIndex, this);
- }
- // Turn clockwise
- else if(movement==CGUARD_ROTATE_CW){
- while(true)
- {
- Wait(120/speed, reaction, message, destDMap, destScreen,
- enemyID, screenDIndex, this);
- direction=TurnRight(direction);
- this->Data=baseStandCombo+direction;
- }
- }
- // Turn clockwise
- else if(movement==CGUARD_ROTATE_CCW)
- {
- while(true)
- {
- Wait(120/speed, reaction, message, destDMap, destScreen,
- enemyID, screenDIndex, this);
- direction=TurnLeft(direction);
- this->Data=baseStandCombo+direction;
- }
- }
- // Turn left and right
- else if(movement==CGUARD_LEFT_AND_RIGHT)
- {
- while(true)
- {
- Wait(120/speed, reaction, message, destDMap, destScreen, enemyID, screenDIndex, this);
- direction=TurnLeft(direction);
- this->Data=baseStandCombo+direction;
- Wait(120/speed, reaction, message, destDMap, destScreen,
- enemyID, screenDIndex, this);
- direction=TurnRight(direction);
- this->Data=baseStandCombo+direction;
- Wait(120/speed, reaction, message, destDMap, destScreen,
- enemyID, screenDIndex, this);
- direction=TurnRight(direction);
- this->Data=baseStandCombo+direction;
- Wait(120/speed, reaction, message, destDMap, destScreen,
- enemyID, screenDIndex, this);
- direction=TurnLeft(direction);
- this->Data=baseStandCombo+direction;
- }
- }
- // Patrol mode; don't need to compare again
- this->Data=baseWalkCombo+direction;
- while(true)
- {
- // Walk forward, if possible
- if(CanMove(direction, speed, this))
- Move(direction, speed, this);
- // Can't go any farther this direction?
- else
- {
- // Align with the tile, first
- this->X+=8;
- this->X-=this->X%16;
- this->Y+=8;
- this->Y-=this->Y%16;
- // See if this was a "stop and turn" tile
- if(Screen->ComboF[ComboAt(this->X, this->Y)]==CGUARD_TURN_FLAG ||
- Screen->ComboI[ComboAt(this->X, this->Y)]==CGUARD_TURN_FLAG)
- {
- // If it was, then do so
- direction=TurnAround(direction);
- this->Data=baseStandCombo+direction;
- Wait(60/speed, reaction, message, destDMap, destScreen,
- enemyID, screenDIndex, this);
- direction=TurnAround(direction);
- }
- // If this guard tries turning left first...
- if(movement==CGUARD_PATROL_LEFT)
- {
- // Turn left and try moving that way
- direction=TurnLeft(direction);
- if(!CanMove(direction, speed, this))
- {
- // Maybe right?
- direction=TurnAround(direction);
- if(!CanMove(direction, speed, this))
- // Better go back the other way, then
- direction=TurnRight(direction);
- }
- }
- // Try right first
- else
- {
- direction=TurnRight(direction);
- if(!CanMove(direction, speed, this))
- {
- direction=TurnAround(direction);
- if(!CanMove(direction, speed, this))
- direction=TurnLeft(direction);
- }
- }
- // Keep going
- this->Data=baseWalkCombo+direction;
- Move(direction, speed, this);
- }
- Wait(1, reaction, message, destDMap, destScreen, enemyID,
- screenDIndex, this);
- }
- }
- bool CheckForLink(int direction, ffc this)
- {
- float distance;
- float angle;
- float adjustedAngle;
- // Check the distance first
- distance=Distance(this->X, this->Y, Link->X, Link->Y);
- if(distance>CGUARD_VISION_RANGE)
- return false;
- if(CGUARD_FIND_LINK_IF_CLOSE!=0 && distance<=CGUARD_FIND_LINK_DISTANCE)
- return true;
- // See if the angle's good, then
- angle=ArcTan(Link->X-this->X, Link->Y-this->Y)*180/PI;
- adjustedAngle=angle;
- if(direction==DIR_UP)
- adjustedAngle+=90;
- else if(direction==DIR_DOWN)
- adjustedAngle-=90;
- else if(direction==DIR_LEFT)
- adjustedAngle+=180;
- if(adjustedAngle>180)
- adjustedAngle-=360;
- if(Abs(adjustedAngle)>CGUARD_VISION_ANGLE/2)
- return false;
- // Check each tile along the line
- // This is kind of a crude way of doing it, but it'll work for now
- int checkX=this->X+8;
- int checkY=this->Y+8;
- float xDiff=Cos(angle)/5;
- float yDiff=Sin(angle)/5;
- int i;
- for(i=0; i<=distance*5; i++)
- {
- if(Screen->ComboF[ComboAt(checkX, checkY)]==CGUARD_BLOCK_FLAG ||
- Screen->ComboI[ComboAt(checkX, checkY)]==CGUARD_BLOCK_FLAG)
- return false;
- checkX+=xDiff;
- checkY+=yDiff;
- }
- return true;
- }
- // Called instead of Waitframe(). Handles things that need to be done
- // every frame.
- void Wait(int numFrames, int reaction, int message, int destDMap,
- int destScreen, int enemyID, int screenDIndex, ffc this)
- {
- // Can't take another argument, so just figure out the direction
- int direction=this->Data%4;
- for(; numFrames>0; numFrames--)
- {
- if(screenDIndex>=0)
- {
- // First, see if someone else just saw Link; if so...
- if(Screen->D[screenDIndex]==1)
- {
- // A warping guard will let the other guy handle it
- if(reaction==CGUARD_WARP)
- Quit();
- // An enemy guard will change
- else
- {
- npc enemy=Screen->CreateNPC(enemyID);
- enemy->X=this->X;
- enemy->Y=this->Y;
- enemy->Dir=direction;
- this->Data=0;
- Quit();
- }
- }
- }
- // See Link?
- if(CheckForLink(direction, this))
- {
- // Alert the others, play the sound, and show the message
- if(screenDIndex>=0)
- Screen->D[screenDIndex]=1;
- Game->PlaySound(CGUARD_SOUND);
- if(message>0)
- {
- Screen->Message(message);
- // If this is a warping guard, don't let Link move
- if(reaction==CGUARD_WARP)
- {
- Waitframes(1);
- //while(!Link->InputA)
- //{
- //Link->InputB=false;
- //Link->InputUp=false;
- //Link->InputDown=false;
- //Link->InputLeft=false;
- //Link->InputRight=false;
- //Waitframe();
- //}
- }
- }
- if(reaction==CGUARD_WARP)
- Link->Warp(destDMap, destScreen);
- else
- // Become an enemy
- {
- npc enemy=Screen->CreateNPC(enemyID);
- enemy->X=this->X;
- enemy->Y=this->Y;
- enemy->Dir=direction;
- this->Data=0;
- Quit();
- }
- }
- Waitframe();
- }
- }
- // Find the guard's new direction if it turns left
- int TurnLeft(int dir)
- {
- if((dir&10b)==0)
- return (dir+10b);
- else
- return ((dir^11b)&11b);
- }
- // Find the guard's new direction if it turns right
- int TurnRight(int dir)
- {
- if((dir&10b)==0)
- return ((dir^11b)&11b);
- else
- return (dir-10b);
- }
- // Find the guard's new direction if it turns around
- int TurnAround(int dir)
- {
- return dir^((~dir&10b)|01b);
- }
- // Checks whether the guard can walk on the tile it's trying to move to
- bool CanMove(int dir, float speed, ffc this)
- {
- int xPos;
- int yPos;
- if(dir==DIR_UP)
- {
- xPos=this->X;
- yPos=Floor(this->Y-speed);
- }
- else if(dir==DIR_DOWN)
- {
- xPos=this->X;
- yPos=Ceiling(this->Y+15+speed);
- }
- else if(dir==DIR_LEFT)
- {
- xPos=Floor(this->X-speed);
- yPos=this->Y;
- }
- else
- // Right
- {
- xPos=Ceiling(this->X+15+speed);
- yPos=this->Y;
- }
- return Screen->ComboF[ComboAt(xPos, yPos)]==CGUARD_WALK_FLAG ||
- Screen->ComboF[ComboAt(xPos, yPos)]==CGUARD_TURN_FLAG ||
- Screen->ComboI[ComboAt(xPos, yPos)]==CGUARD_WALK_FLAG ||
- Screen->ComboI[ComboAt(xPos, yPos)]==CGUARD_TURN_FLAG;
- }
- // Walks forward
- void Move(int dir, float speed, ffc this)
- {
- if(dir==DIR_UP)
- this->Y-=speed;
- else if(dir==DIR_DOWN)
- this->Y+=speed;
- else if(dir==DIR_LEFT)
- this->X-=speed;
- else
- // Right
- this->X+=speed;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement