Jump to content

Photo

N64-Style Guards and Stone Mask


  • Please log in to reply
10 replies to this topic

#1 MarinaraSauce

MarinaraSauce

    Magus

  • Members
  • Real Name:Grant
  • Location:New York

Posted 29 June 2015 - 08:14 PM

I did some searching around, and was amazed that I couldn't find any scripts like this.  Maybe I just wasn't looking hard enough/in the right place, so if scripts for these things do exist, please point me to them.  Now, on to my request.

 

First, I would like a script that creates guards that have tunnel vision and kick Link out of the dungeon if they see him.  The way this should work is that the guards can see Link if he is straight ahead of them, unless there is a solid combo between them.  I'd also like some way to make them move around, but I have basically no idea how FFCs work, so I don't really know how that should work.  If the guards do see Link, a string should play, and Link should be teleported to a specific screen on a different Dmap.

 

Second, I'd like a stone mask item that makes it so that guards can't see Link.  I'd want it to be a button item, and change Link's sprite when used.

 

If something I asked for doesn't exist and needs to be elaborated on, let me know and I'll try to explain it in better detail.


  • SkyLizardGirl likes this

#2 ywkls

ywkls

    Master

  • Members

Posted 27 July 2015 - 09:42 AM

I'm working on this. This is what I have so far. A stationary guard, a guard that moves horizontally, vertically, clockwise and counterclockwise. (Moving guards must bump into solid objects.) I want a guard that circles objects, like hedges; but haven't got it worked out yet. When my internet is restored, I'll post them. (It may not be until later this week.) For the mask, I haven't tried that yet, but it shouldn't be too hard.

Edited by ywkls, 27 July 2015 - 09:43 AM.

  • MarinaraSauce likes this

#3 Saffith

Saffith

    IPv7 user

  • ZC Developers

Posted 27 July 2015 - 11:01 AM

It's not exactly what you asked for, but I made a guard script a while ago. To be honest, I don't entirely remember how it works. :P
Shouldn't be hard to modify it for the stone mask, though. Just stick a check in CanSeeLink().

Script


D0: Movement type
* 0: Walks along flags 98 and 99; 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: Doesn't move at all
* 3: Stands in place, turning clockwise
* 4: Stands in place, turning counterclockwise
* 5: Stands in place, turning left and right
D1: Initial direction
D2: Action when Link is spotted
* 0: Warp
* 1: Become an enemy
D3: Movement speed in pixels per frame (defaults to 0.75)
D4: Message to show when Link is spotted
D5: DMap to warp to
D6: DMap screen to warp to
D7: Enemy to turn into

By default, they'll walk along flag 98 (if using movement type 0 or 1), and flag 100 will block their vision.
Combos should be up, down, left, right, in order. Set both the combo and D2 to match the initial direction.
  • MarinaraSauce and ywkls like this

#4 ywkls

ywkls

    Master

  • Members

Posted 31 July 2015 - 06:00 PM

Mine works along a lot of the same principles as Saffith's except it doesn't need flags to direct the path. (Though I can probably include the option to have certain flags block the line of sight, once I have some time to mull over the code.)

 

Here's what I have so far. This includes a setup for the Stone Mask. I don't have tiles for it, so you'll either have to create some or get somebody to do that for you since I am not very good at making tiles. The basic set up is a little crazy, since I used some premade combos for the guards and created my code to match that rather than make new ones. Also, the movement is still a little touchy and they don't turn into enemies. Given time, I might be able to combine the two.

import "std.zh"

const int CMB_AUTOWARP = 3;//Combo for an autowarp type A combo.
const int Guard_Combo = 31832;//First of four combos used for the guards. Should be in this order. Up, right, down, left.

//D0- Which direction the guard initially faces. Must be set in any instance.
//    1- Left
//    2- Right
//    3- Down
//    4- Up
//D1- How far away you have to be before the guard sees you, in pixels.
//D2- Type of guard.
//    Zero- Stationary, looking in one direction.
//    1- Horizontal
//    2- Vertical
//    3- Clockwise.
//    4- Counterclockwise.
//    5- Not yet implemented. Intended to be clockwise movement that circles solid objects.
//    6- Not yet implemented. Intended to be counterclockwise movement that circles solid objects.
//    Moving guards must hit solid object to turn. Be careful in placing them, or they could get stuck.
//D3- How long to wait before making a turn, in frames.

ffc script Guard{
    void run(int direction, int distance, int type, int turndelay){
         int SpeedX = this->Vx;
         int SpeedY = this->Vy;
         while(true){
             if(direction ==4)this->Data = Guard_Combo;
             else if(direction == 2)this->Data = Guard_Combo+1;
             else if(direction == 3)this->Data = Guard_Combo+2;
             else if(direction == 1)this->Data = Guard_Combo+3;
             if(!Mask_On){
                 if(direction == 1 && Abs(Link->X-this->X) <=distance && Link->Y >=this->Y && Link->Y <= this->Y + 16 && Link->X <=this->X)this->Data = CMB_AUTOWARP;
                 else if(direction == 2 && Abs(Link->X-this->X) <=distance && Link->Y >=this->Y && Link->Y <= this->Y + 16 && Link->X >= this->X)this->Data = CMB_AUTOWARP;
                 else if(direction == 3 && Abs(Link->Y-this->Y) <=distance && Link->X >=this->X && Link->X <= this->X + 16 && Link->Y >= this->Y)this->Data = CMB_AUTOWARP;
                 else if(direction == 4 && Abs(Link->Y-this->Y) <=distance && Link->X >=this->X && Link->X <= this->X + 16 && Link->Y <= this->Y)this->Data = CMB_AUTOWARP;
             }   
             if(type ==1){
                      for (int i = 0; i < 16; i++){
                           if(Screen->isSolid(this->X - 1, this->Y + i+ 8) && direction ==1){
                                this->Vx = 0;
                                Waitframes(turndelay);
                                this->Vx = SpeedX;
                                direction = 2;
                           }
                           else if(Screen->isSolid(this->X + 17, this->Y + i+ 8) && direction==2){
                                this->Vx = 0;
                                Waitframes(turndelay);
		                this->Vx = -1 * SpeedX;
                                direction = 1;
                           }
                      }
                }
                else if(type ==2){
                      for (int i = 0; i < 16; i++){
                           if(Screen->isSolid(this->X + i+ 8, this->Y - 1) && direction ==4){
		               this->Vy = 0;
                               Waitframes(turndelay);
                               this->Vy = SpeedY;
                               direction = 3;
                           }
                           else if(Screen->isSolid(this->X + i+ 8, this->Y + 17)&& direction ==3){
		               this->Vy = 0;
                               Waitframes(turndelay);
                               this->Vy = -1 * SpeedY;
                               direction = 4;
                           }
                      }
                }
                else if(type == 3){
                      for (int i = 0; i < 16; i++){
                           if(Screen->isSolid(this->X + i+ 8, this->Y + 17) && direction ==3){
		                this->Vy = 0;
                                Waitframes(turndelay);
                                this->Vx = SpeedY;
                                direction = 1;
                           }
                           else if(Screen->isSolid(this->X - 1, this->Y + i+ 8) && direction ==1){
                                this->Vx = 0;
                                Waitframes(turndelay);
                                this->Vy = SpeedY;
                                direction =4;
                           }
                           else if(Screen->isSolid(this->X + i+ 8, this->Y - 1) && direction ==4){
		                this->Vy = 0;
                                Waitframes(turndelay);
                                this->Vx = -1 * SpeedY;
                                direction = 2;
                           }
                           else if(Screen->isSolid(this->X + 17, this->Y + i+ 8) && direction==2){
                                this->Vx = 0;
                                Waitframes(turndelay);
                                this->Vy = -1* SpeedY;
                                direction = 3;
                           }
                      }
                }
                else if(type == 4){
                      for (int i = 0; i < 16; i++){
                           if(Screen->isSolid(this->X + i+ 8, this->Y + 17) && direction ==3){
		                this->Vy = 0;
                                Waitframes(turndelay);
                                this->Vx = -1 * SpeedX;
                                direction = 2;
                           }
                           else if(Screen->isSolid(this->X - 1, this->Y + i+ 8) && direction ==1){
                               this->Vx = 0;
                               Waitframes(turndelay);
                               this->Vy = -1 * SpeedX;
                               direction = 3;
                           }
                           else if(Screen->isSolid(this->X + i+ 8, this->Y - 1) && direction ==4){
		               this->Vy = 0;
                               Waitframes(turndelay);
                               this->Vx = SpeedX;
                               direction = 1;
                           }
                           else if(Screen->isSolid(this->X + 17, this->Y + i+ 8) && direction==2){
                               this->Vx = 0;
                               Waitframes(turndelay);
                               this->Vy = SpeedX;
                               direction = 4;
                           }
                      }
                  }
                  else if(type == 5){
                      for (int i = 0; i < 16; i++){
                           if(!Screen->isSolid(this->X + 17, this->Y + i+ 8) && !Screen->isSolid(this->X + 25, this->Y-8)  && direction ==3){
                                this->Vy = 0;
                                Waitframes(turndelay);
                                this->Vx = SpeedY;
                                direction = 2;
                           }
                           else if(!Screen->isSolid(this->X + i+ 8, this->Y - 8) && !Screen->isSolid(this->X-8, this->Y - 8)&& direction ==2){
                                this->Vx = 0;
                                Waitframes(turndelay);
                                this->Vy = -1 * SpeedY;
                                direction = 4;
                           }
                           else if(!Screen->isSolid(this->X - 8, this->Y + i+ 8) && !Screen->isSolid(this->X - 8, this->Y+ 25) && direction ==4){
		                this->Vy = 0;
                                Waitframes(turndelay);
                                this->Vx = -1 * SpeedY;
                                direction = 1;
                           }
                           else if(!Screen->isSolid(this->X + i+ 8, this->Y + 17) && !Screen->isSolid(this->X+ 25, this->Y + 25)&& direction==1){
                                this->Vx = 0;
                                Waitframes(turndelay);
                                this->Vy = SpeedY;
                                direction = 3;
                           }
                       }
                   }
                   else if(type == 6){
                       for (int i = 0; i < 16; i++){
                           if(!Screen->isSolid(this->X-1, this->Y + i+ 8) && !Screen->isSolid(this->X -8, this->Y-8) && direction ==3){
                                this->Vy = 0;
                                Waitframes(turndelay);
		                this->Vx = -1 * SpeedY;                           
                                direction = 1;
                           }
                           else if(!Screen->isSolid(this->X + i+ 8, this->Y +17) && !Screen->isSolid(this->X+25, this->Y +8)&& direction ==1){
                                this->Vx = 0;
                                Waitframes(turndelay);
                                this->Vy = -1 * SpeedY;
                                direction = 4;
                           }
                           else if(!Screen->isSolid(this->X - 1, this->Y + i+ 8) && !Screen->isSolid(this->X-8, this->Y+25) && direction ==4){
		                this->Vy = 0;
                                Waitframes(turndelay);
                                this->Vx = SpeedY;
                           direction = 2;
                      }
                      else if(!Screen->isSolid(this->X-i-8, this->Y + 17) && !Screen->isSolid(this->X-8, this->Y + 25)&& direction==2){
                           this->Vx = 0;
                           Waitframes(turndelay);
                           this->Vy = SpeedY;
                           direction = 3;
                      }
                 }
             }
             if (LinkCollision(this))this->Data = CMB_AUTOWARP;
             Waitframe();
         }
    }
}

const int MASK_TILE = 64076;//First of 4 tiles for the Mask.

item script Stone_Mask{
      void run(){
            if(!Mask_On)Mask_On = true;
            else{
                 Mask_On = false;
            }
      }
}

bool Mask_On = false;//Governs whether the mask is worn. Could be expanded into a whole mask system once I have tiles and ideas for what the masks do.

//Uses a global script so the mask is always displayed.
global script globalscript{
     void run(){
          while(true){
               if(Mask_On)Wear_Mask();
               Waitframe();
          }
     }
}


//This function draws the mask based on the direction Link is facing.
void Wear_Mask(){
     int Face_Tile;
     while(true){
          if(Link->Dir == DIR_DOWN)Face_Tile = MASK_TILE;
          else if(Link->Dir == DIR_LEFT)Face_Tile = MASK_TILE+1;
          else if(Link->Dir == DIR_UP)Face_Tile = MASK_TILE+2;
          else if(Link->Dir == DIR_RIGHT)Face_Tile = MASK_TILE+3;
          if(Mask_On)Screen->DrawTile(3, Link->X, Link->Y, Face_Tile, 1, 1, 6, 16, 16, 0, 0, 0, 0, false, 1284);
          Waitframe();
     }
}
          
          


I'll try to look over Saffith's code over the weekend now that my internet is back up and see if I can combine the two.



#5 ywkls

ywkls

    Master

  • Members

Posted 05 August 2015 - 09:16 AM

I'd suggest using this modified version of Saffith's code.

 

Spoiler

 

 

Again, I don't have tiles for the mask. Sorry.


Edited by ywkls, 05 August 2015 - 09:26 AM.

  • MarinaraSauce likes this

#6 xenomicx

xenomicx

    Zelda Arcade

  • Members
  • Location:Chi-town

Posted 09 December 2019 - 07:44 PM

I'd suggest using this modified version of Saffith's code.

 

Spoiler

 

 

Again, I don't have tiles for the mask. Sorry.

ywkls!!!! THIS IS WHAT WE NEED FOR AOTS!!! I've been messing around with it on my Metal Gear Tileset and trying to get it to work with an Enemy Uniform. I'm finding all kinds of bugs with it after it compiles successfully. This really needs to be convertered into a Ghosted enemy because ALL of the guards in Metal Gear work in this manner. They patrol and when they see you they attack. This will revolutionalize the game if we can get this down. 

 

As of right now I get get the guards to patrol, turn, face left/right, stand still etc. They don't aleart when I have the uniform on and alert when its off. However, when the FFC is on the screen, all other FFC scrpts no longer work in the entire quest. I can't firgure out why. Tango doesn't work, Ghost doesn't work, Lweapons doesn't work nothing....but as soon as I remove this 1 tiny FFC everything goes back to working. I'm sure its something to do with the waitframe at the end which is why I think this is needing a revamp ASAP. 

The guards in our Metal Gear section in AOTS just attack you as soon as you enter the screen which can be annoying, deadly, and tedious. This is NEVER what I intended. I inteded for Link to sneak around these guards undetected or at least concealed with a speacial item...or face an onslaught of vicious attacks if spotted. THIS SCRIPT IS THE BEGINING OF SOMETHING BEAUTIFUL!!! 

 

Please lets do this and I will revamp the Metal Gear portion of AOTS immediately.


Edited by xenomicx, 09 December 2019 - 08:35 PM.


#7 ywkls

ywkls

    Master

  • Members

Posted 09 December 2019 - 11:56 PM

ywkls!!!! THIS IS WHAT WE NEED FOR AOTS!!! I've been messing around with it on my Metal Gear Tileset and trying to get it to work with an Enemy Uniform. I'm finding all kinds of bugs with it after it compiles successfully. This really needs to be convertered into a Ghosted enemy because ALL of the guards in Metal Gear work in this manner. They patrol and when they see you they attack. This will revolutionalize the game if we can get this down. 

 

As of right now I get get the guards to patrol, turn, face left/right, stand still etc. They don't aleart when I have the uniform on and alert when its off. However, when the FFC is on the screen, all other FFC scrpts no longer work in the entire quest. I can't firgure out why. Tango doesn't work, Ghost doesn't work, Lweapons doesn't work nothing....but as soon as I remove this 1 tiny FFC everything goes back to working. I'm sure its something to do with the waitframe at the end which is why I think this is needing a revamp ASAP. 

The guards in our Metal Gear section in AOTS just attack you as soon as you enter the screen which can be annoying, deadly, and tedious. This is NEVER what I intended. I inteded for Link to sneak around these guards undetected or at least concealed with a speacial item...or face an onslaught of vicious attacks if spotted. THIS SCRIPT IS THE BEGINING OF SOMETHING BEAUTIFUL!!! 

 

Please lets do this and I will revamp the Metal Gear portion of AOTS immediately.

 

Glad to see your enthusiasm.  :D

 

I hadn't thought about reworking the guards in that way, but it would be feasible.

Of course, now I know that including that Waitframe was a mistake in the global script.

I am not sure what the problems that you were having were, but we can definitely discuss it further here or on Discord.

 

In the meantime, I will try and adapt the code above to AotS.



#8 xenomicx

xenomicx

    Zelda Arcade

  • Members
  • Location:Chi-town

Posted 10 December 2019 - 12:24 AM

I'll make a video in the morning and send it to you on discord. But for anyone else that may read this, there were a few syntax errors I had to correct before I compiled. I also changed some name to fit our naming conventions.

Spoiler

 

Basically before I make a video, I'll try to describe the problem the best I can. The FFC enemy will patrol alone the path (using Flag 8) just as expected, and I have the sprites for the Metal Gear Soldier being used in my combos.


Edited by xenomicx, 10 December 2019 - 12:56 AM.


#9 xenomicx

xenomicx

    Zelda Arcade

  • Members
  • Location:Chi-town

Posted 10 December 2019 - 12:56 AM

  • The first problem is, its not really an enemy and cannot be killed by stealth. I can sneak up on him and shoot him, stab him, burn him...and nothing happens. He has to see me and change into an enemy first before he can be killed. He turns into an enemy just fine...just as long as I DON'T use the uniform first. Once I use the Uniform, the enemy will freeze on screen and no other FFC or script in the entire quest will work.
  • The second problem is just describe above. I can use the uniform and sneak past the patrolling soldiers, but if I take it off in front of them the alarms go off, and then he freezes on screen. If I don't use the uniform at all or don't ever pick it up, the script works fine...other than the fact I can't sneak attack him.
  • Third problem is if I use the uniform, take it off and set off the alarm...or at any point set off the alarm and put the uniform back on. The soldier then disapears.


#10 ywkls

ywkls

    Master

  • Members

Posted 10 December 2019 - 02:24 AM

It's going to take a bit for me to parse all of that code and see where things went awry.

Right off the bat, I can say that the while loop in "Wear_Uniform" and it's associated Waitframe aren't needed.

I will try to work out a version of this over the next couple of days which may or may not resemble this code.



#11 Emily

Emily

    Scripter / Dev

  • ZC Developers

Posted 25 December 2019 - 04:07 AM

Not quite what you wanted, but I made Wind Waker style guards for 2.55, including spotlights and guards that patrol.

https://www.purezc.n...=scripts&id=341

 

While there's no MASK for not being seen, it uses picking up barrels to achieve the same effect; I would think modifying the script to use a mask instead should be absolutely trivial.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users