设为首页收藏本站同能贴吧 切换语言 繁体中文
开启辅助访问 切换到窄版
扫描二维码关注官方公众号
返回列表
+ 发新帖
查看: 64|回复: 0

[制作教程] HOW TO MAKE 2+ FRAME ANIMATED ACTOR FACES IN FRONTVIEW BATTLE STATUS WINDOW: FRE

[复制链接]
累计送礼:
0 个
累计收礼:
1 个
  • TA的每日心情
    开心
    4 天前
  • 签到天数: 209 天

    连续签到: 2 天

    [LV.7]常住居民III

    4609

    主题

    864

    回帖

    2万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    7
    卡币
    23225
    OK点
    16
    推广点
    0
    同能卷
    50
    积分
    28728

    灌水之王

    发表于 2026-7-8 09:02:22 | 显示全部楼层 |阅读模式
    Brief Description/What to Expect: Short, "OMORI"-like, two frame animations of characters’ face in the front view battle status window when idling and/or being affected by certain states. These animations change with your characters if they have a transformation state as well. As a bonus, I’ve provided code for animations that use 3 - 8 unique frames where you can adjust the speed of each frame if needed. That is at the bottom of this post, but, please read before using it as I do not implement this code with the main part of the tutourial.

    Spoiler: What not to Expect:
    Low health animations, static face changes (although this can be easily done if you look at my post or this post by LucasRiot) synchronised animations with party members, death animations, taking damage animations & animations that play before taking an action. However, the last two are fairly easy to do using the same plugins. I’ve yet to implement it but you can probably figure it out by reading through all this. 99.9% sure it can be done if you read this and read up on this: Battle Core VisuStella MZ. If you can’t, I’d be more than happy to make an edit/reply to someone’s request and test a solution I have in mind w/ code (if it works).
    Spoiler: Intro: Why did I make this and share this?
    I have a real fondness for cool, cute and simple visual flairs in games. Small details are very charming to me. In OMORI, the characters have a neat little battle portrait animation that changes depending on the state afflicted on them. I loved that, it was (to me) very unique. It helped differentiate the game from other games where character portraits are static, or worse: non-existent. It brought more liveliness to the screen, was a good visual indicator for what states were applied & as mentioned before: charming.  When I started working on my project, I really wanted to replicate that charm by having my own portrait animations. Unfortunately for me, I couldn’t find any plugin or user created script that did what I wanted to achieve for MZ. I still can’t. Then again, I’m still very new to RPGMaker & game devving in general. I’m also an intermediate coder. I only started touching JS a couple months ago for RPGMaker. I admit, I might’ve not looked up the right things. So maybe there is a plugin/post that does what I did but better. If there is, sorry! If there isn’t, that’s why I’m sharing this. I don’t want others to suffer like I did reading tons of documentation, using up precious time, getting bummed out, giving up or even buying plugins they don’t need. In addition, I hate gatekeeping, I’m not fond of unnecessary monetisation, I see 0 reasons for hiding things that could help others aside from purely selfish ones and I’m a big fan of making education free. I like open resources and seeing people help each other. We’ve only come so far in society by sharing knowledge and working together. I also wanted to be that person who has that oddly specific code that is literally perfect for someone else’s scenario.
    Before you read any further, I'd like to credit This Post by LucasRiot | RPG Maker Forums (rpgmakerweb.com). This post is at the core of this code & the inspiration. Could not have done most of this without it.

    Requirements: Notetags from Skills and States Core VisuStella MZ & Battle Core VisuStella MZ are mandatory to do this. Those plugins are free. The bonus part requires a PAID plugin: Victory Aftermath VisuStella MZ.

    Second preface: I am linking a youtube video of a quick demo I made showcasing my code in action. It will showcase the actor face animations in battle & the actor face victory animations. Just in case my description isn't cutting it. Just to save everyone time.
    https://www.youtube.com/embed/wCjYW4gBjF0

    I will copy and paste all my code and tell you where to put it first. I will also attach line by line explanations of each code in the post. After I show all the code, I will have explanations of choices & code, reasonings for choices & code, file set-up, rules the code abides by & extra questions I thought of.

    --

    MAIN TUTOURIAL


    START IDLE ANIMATION: To get the idle animation at the start of the battle, put this in the Actor Note section (Database > Actors > [Actor ID & Name] > Note) of every actor you intend to have in battle.

    Spoiler: Start Idle Animation: Paste-able code
                    JavaScript:        
    <JS Pre-Start Battle> var faceNamebreathe1 = target._faceName; var faceIndexbreathe1 = 0; var faceNamebreathe2 = target._faceName; var faceIndexbreathe2 = 4; target.setFaceImage(faceNamebreathe1, faceIndexbreathe1);  function swapFaceImages() {     if (target._faceName === faceNamebreathe1 && target._faceIndex === faceIndexbreathe1) {         target.setFaceImage(faceNamebreathe2, faceIndexbreathe2);     } else {         target.setFaceImage(faceNamebreathe1, faceIndexbreathe1);     } } target._faceSwapLoopInterval = setInterval(function() {     swapFaceImages();     target.refresh(); }, 1000); </JS Pre-Start Battle>


    The line by line code explanation is in the file "ActorCode.txt", which is attached to this post

    TRANSFORMATION IDLE ANIMATION: My code allows your character transformation states to be animated & work alongside the states you choose to animate. In the video demo, I show off one transformation state & three status states. So, the code will along with that. This code should go into the State Note section (Database > States > [State ID & Name] > Note) of a state that you intend to be a transformation (a state that changes actor name, class, skills etc...to get a good idea, follow the template of This Post). Remember to check off "Removal at Battle End" in the State settings. Use "Auto-removal Timing" for best results.

    Spoiler: Transformation Idle Animation: Paste-able code
                    JavaScript:        
    <No Death Clear> <JS On Add State> if (target._faceSwapLoopInterval) {     clearInterval(target._faceSwapLoopInterval); } if (!target._prevFaceName) {     target._prevFaceName = 'TestDummy1';     target._prevFaceIndex = 0; } var faceName1 = 'TestDummy1T'; var faceIndex1 = 0; var faceName2 = 'TestDummy1T'; var faceIndex2 = 4;  target.setFaceImage(faceName1, faceIndex1);  if (target.isStateAffected(32)) {     var faceNameMad1 = target._faceName;     var faceIndexMad1 = 0;     var faceNameMad2 = target._faceName;     var faceIndexMad2 = 2;      function swapFaceImagesMad() {         if (target._faceName === faceNameMad1 && target._faceIndex === faceIndexMad1) {             target.setFaceImage(faceNameMad2, faceIndexMad2);         } else {             target.setFaceImage(faceNameMad1, faceIndexMad1);         }     }     target._faceSwapLoopInterval = setInterval(function() {         swapFaceImagesMad();         target.refresh();     }, 1000); } else if (target.isStateAffected(33)) {     var faceNameHappy1 = target._faceName;     var faceIndexHappy1 = 0;     var faceNameHappy2 = target._faceName;     var faceIndexHappy2 = 1;      function swapFaceImagesHappy() {         if (target._faceName === faceNameHappy1 && target._faceIndex === faceIndexHappy1) {             target.setFaceImage(faceNameHappy2, faceIndexHappy2);         } else {             target.setFaceImage(faceNameHappy1, faceIndexHappy1);         }     }     target._faceSwapLoopInterval = setInterval(function() {         swapFaceImagesHappy();         target.refresh();     }, 1000); } else if (target.isStateAffected(34)) {     var faceNameSad1 = target._faceName;     var faceIndexSad1 = 0;     var faceNameSad2 = target._faceName;     var faceIndexSad2 = 3;      function swapFaceImagesSad() {         if (target._faceName === faceNameSad1 && target._faceIndex === faceIndexSad1) {             target.setFaceImage(faceNameSad2, faceIndexSad2);         } else {             target.setFaceImage(faceNameSad1, faceIndexSad1);         }     }     target._faceSwapLoopInterval = setInterval(function() {         swapFaceImagesSad();         target.refresh();     }, 1000); } else {     function swapFaceImagesIdle() {         if (target._faceName === faceName1 && target._faceIndex === faceIndex1) {             target.setFaceImage(faceName2, faceIndex2);         } else {             target.setFaceImage(faceName1, faceIndex1);         }     }     target._faceSwapLoopInterval = setInterval(function() {         swapFaceImagesIdle();         target.refresh();     }, 1000); } </JS On Add State>   <JS On Erase State> if (target._faceSwapLoopInterval) {     clearInterval(target._faceSwapLoopInterval); } var faceName = target._prevFaceName; var faceIndex = target._prevFaceIndex;  target.setFaceImage(faceName, faceIndex);  var faceNameBreathe1 = target._faceName; var faceIndexBreathe1 = 0; var faceNameBreathe2 = target._faceName; var faceIndexBreathe2 = 4;  target._prevFaceName = undefined; target._prevFaceIndex = undefined;  if (target.isStateAffected(32)) {     var faceNameMad1 = target._faceName;     var faceIndexMad1 = 0;     var faceNameMad2 = target._faceName;     var faceIndexMad2 = 2;      function swapFaceImagesMad() {         if (target._faceName === faceNameMad1 && target._faceIndex === faceIndexMad1) {             target.setFaceImage(faceNameMad2, faceIndexMad2);         } else {             target.setFaceImage(faceNameMad1, faceIndexMad1);         }     }     target._faceSwapLoopInterval = setInterval(function() {         swapFaceImagesMad();         target.refresh();     }, 1000); } else if (target.isStateAffected(33)) {     var faceNameHappy1 = target._faceName;     var faceIndexHappy1 = 0;     var faceNameHappy2 = target._faceName;     var faceIndexHappy2 = 1;      function swapFaceImagesHappy() {         if (target._faceName === faceNameHappy1 && target._faceIndex === faceIndexHappy1) {             target.setFaceImage(faceNameHappy2, faceIndexHappy2);         } else {             target.setFaceImage(faceNameHappy1, faceIndexHappy1);         }     }     target._faceSwapLoopInterval = setInterval(function() {         swapFaceImagesHappy();         target.refresh();     }, 1000); } else if (target.isStateAffected(34)) {     var faceNameSad1 = target._faceName;     var faceIndexSad1 = 0;     var faceNameSad2 = target._faceName;     var faceIndexSad2 = 3;      function swapFaceImagesSad() {         if (target._faceName === faceNameSad1 && target._faceIndex === faceIndexSad1) {             target.setFaceImage(faceNameSad2, faceIndexSad2);         } else {             target.setFaceImage(faceNameSad1, faceIndexSad1);         }     }     target._faceSwapLoopInterval = setInterval(function() {         swapFaceImagesSad();         target.refresh();     }, 1000); } else {     function swapFaceImagesIdle() {         if (target._faceName === faceNameBreathe1 && target._faceIndex === faceIndexBreathe1) {             target.setFaceImage(faceNameBreathe2, faceIndexBreathe2);         } else {             target.setFaceImage(faceNameBreathe1, faceIndexBreathe1);         }     }     target._faceSwapLoopInterval = setInterval(function() {         swapFaceImagesIdle();         target.refresh();     }, 1000); } </JS On Erase State>


    Believe it or not, that's the hardest part. If you made it through, congrats. The line by line code explanation is in the file "TransformationCodeExplanation .txt", which is attached in this post.



    STATUS STATE #1 ANIMATION: A Status State is any status effect inflicted in battle. It can increase/decrease stats, have negative/positive effects and I think you get it. This code should go into the State Note section (Database > States > [State ID & Name] > Note) of a state that acts like a status effect. Remember to check off "Removal at Battle End" in the State settings. Using "Auto-removal Timing" is optional.

    Spoiler: Status State Animation #1: Paste-able code
                    JavaScript:        
    <JS On Add State> target.removeState(33); target.removeState(34);  if (target.isActor()) {     if (target._faceSwapLoopInterval) {         clearInterval(target._faceSwapLoopInterval);     }      var faceNameMad1 = target._faceName;     var faceIndexMad1 = 0;     var faceNameMad2 = target._faceName;     var faceIndexMad2 = 2;      target.setFaceImage(faceNameMad1, faceIndexMad1);      function swapFaceImagesMad() {         if (target._faceName === faceNameMad1 && target._faceIndex === faceIndexMad1) {             target.setFaceImage(faceNameMad2, faceIndexMad2);         } else {             target.setFaceImage(faceNameMad1, faceIndexMad1);         }     }      target._faceSwapLoopInterval = setInterval(function() {         swapFaceImagesMad();         target.refresh();     }, 1000); } </JS On Add State>  <JS On Erase State>                                    if (target.isActor()) {                                    if (target._faceSwapLoopInterval) {                                      clearInterval(target._faceSwapLoopInterval);     }      var faceNameBreathe1 = target._faceName;              var faceIndexBreathe1 = 0;                              var faceNameBreathe2 = target._faceName;            var faceIndexBreathe2 = 4;                         target.setFaceImage(faceNameBreathe1, faceIndexBreathe1);          function swapFaceImagesIdle() {                                                                          if (target._faceName === faceNameBreathe1 && target._faceIndex === faceIndexBreathe1) {                 target.setFaceImage(faceNameBreathe2, faceIndexBreathe2);             } else {                                                                                                    target.setFaceImage(faceNameBreathe1, faceIndexBreathe1);             }         }         target._faceSwapLoopInterval = setInterval(function() {                                    swapFaceImagesIdle();                                                                  target.refresh();                                                                }, 1000);                                                                          } </JS On Erase State>


    The line by line code explanation is in the file "StatusState1 .txt", which is attached in this post.

    STATUS STATE #2 ANIMATION: A Status State is any status effect inflicted in battle. It can increase/decrease stats, have negative/positive effects and I think you get it. This code should go into the State Note section (Database > States > [State ID & Name] > Note) of a state that acts like a status effect. Remember to check off "Removal at Battle End" in the State settings. Using "Auto-removal Timing" is optional.

    Spoiler: Status State Animation #2: Paste-able code
                    JavaScript:        
    <JS On Add State> target.removeState(32); target.removeState(34);  if (target.isActor()) {     if (target._faceSwapLoopInterval) {         clearInterval(target._faceSwapLoopInterval);     }      var faceNameHappy1 = target._faceName;     var faceIndexHappy1 = 0;     var faceNameHappy2 = target._faceName;     var faceIndexHappy2 = 1;      target.setFaceImage(faceNameHappy1, faceIndexHappy1);      function swapFaceImagesHappy() {         if (target._faceName === faceNameHappy1 && target._faceIndex === faceIndexHappy1) {             target.setFaceImage(faceNameHappy2, faceIndexHappy2);         } else {             target.setFaceImage(faceNameHappy1, faceIndexHappy1);         }     }      target._faceSwapLoopInterval = setInterval(function() {         swapFaceImagesHappy();         target.refresh();     }, 1000); } </JS On Add State>   <JS On Erase State>                                    if (target.isActor()) {                                    if (target._faceSwapLoopInterval) {                                      clearInterval(target._faceSwapLoopInterval);     }      var faceNameBreathe1 = target._faceName;              var faceIndexBreathe1 = 0;                              var faceNameBreathe2 = target._faceName;            var faceIndexBreathe2 = 4;                         target.setFaceImage(faceNameBreathe1, faceIndexBreathe1);          function swapFaceImagesIdle() {                                                                          if (target._faceName === faceNameBreathe1 && target._faceIndex === faceIndexBreathe1) {                 target.setFaceImage(faceNameBreathe2, faceIndexBreathe2);             } else {                                                                                                    target.setFaceImage(faceNameBreathe1, faceIndexBreathe1);             }         }         target._faceSwapLoopInterval = setInterval(function() {                                    swapFaceImagesIdle();                                                                  target.refresh();                                                                }, 1000);                                                                          } </JS On Erase State>


    The line by line code explanation is in the file "StatusState2.txt", which is attached in this post.

    STATUS STATE #3 ANIMATION: A Status State is any status effect inflicted in battle. It can increase/decrease stats, have negative/positive effects and I think you get it. This code should go into the State Note section (Database > States > [State ID & Name] > Note) of a state that acts like a status effect. Remember to check off "Removal at Battle End" in the State settings. Using "Auto-removal Timing" is optional.

    Spoiler: Status State Animation #3: Paste-able code
                    JavaScript:        
    <JS On Add State> target.removeState(32); target.removeState(33);  if (target.isActor()) {     if (target._faceSwapLoopInterval) {         clearInterval(target._faceSwapLoopInterval);     }      var faceNameSad1 = target._faceName;     var faceIndexSad1 = 0;     var faceNameSad2 = target._faceName;     var faceIndexSad2 = 3;      target.setFaceImage(faceNameSad1, faceIndexSad1);      function swapFaceImagesSad() {         if (target._faceName === faceNameSad1 && target._faceIndex === faceIndexSad1) {             target.setFaceImage(faceNameSad2, faceIndexSad2);         } else {             target.setFaceImage(faceNameSad1, faceIndexSad1);         }     }      target._faceSwapLoopInterval = setInterval(function() {         swapFaceImagesSad();         target.refresh();     }, 1000); } </JS On Add State> <JS On Erase State>                                    if (target.isActor()) {                                    if (target._faceSwapLoopInterval) {                                      clearInterval(target._faceSwapLoopInterval);     }      var faceNameBreathe1 = target._faceName;              var faceIndexBreathe1 = 0;                              var faceNameBreathe2 = target._faceName;            var faceIndexBreathe2 = 4;                         target.setFaceImage(faceNameBreathe1, faceIndexBreathe1);          function swapFaceImagesIdle() {                                                                          if (target._faceName === faceNameBreathe1 && target._faceIndex === faceIndexBreathe1) {                 target.setFaceImage(faceNameBreathe2, faceIndexBreathe2);             } else {                                                                                                    target.setFaceImage(faceNameBreathe1, faceIndexBreathe1);             }         }         target._faceSwapLoopInterval = setInterval(function() {                                    swapFaceImagesIdle();                                                                  target.refresh();                                                                }, 1000);                                                                          } </JS On Erase State>


    The line by line code explanation is in the file "StatusState3.txt", which is attached in this post.

    -- END OF MAIN TUTOURIAL, FUTHER EXPLANATIONS + CODE FOR 3 - 8 FRAME ANIMATIONS BELOW--

    Spoiler: Q: How should I set up my files to make this work best?
    Have one face file of the standard size of 8 indices for each transformation you plan to have and one face file of the standard size of 8 indices for your actor’s typical/normal/default appearance. The default appearance is the one you set for your actors in RPGMaker MZ under Database > Actors > [your actor ID + actor name] > Images > Face:. All face files must be placed in img/faces/. You don’t need to use all 8 indices, I’m just not sure if the faces will display properly if you have more than those 8 indices and a non-standard file size (If you know how you can have more than 8 faces in a single file, please share! That way you can have more complex animations & more unique faces). For each file you use, make sure the face indices for the animations you wish to use are the same across all of them. For example, let’s say you’re using face index 0 and 2 for a “Mad” state. In all the face files you use, make sure you have your “Mad” faces in face index 0 & 2. That way, no matter what your current faceset is, the animation will correctly reflect and change as the states do.
    Spoiler: Q: What is the animation order of precedence and rules?
    The status state animation will play over the transformation idle animation and idle animation. The transformation idle animation will play over the idle animation. The idle animation will play if no transformation or status state (that has the animation code) is applied. You can have only 1 transformation state applied at a time. You can only have 1 status state (that has the animation code) applied at a time. You may have 1 transformation state & 1 status state (that has the animation code) applied at the same time.
    Spoiler: Q: What is the <No Death Clear> notetag and why is it there?
    At the beginning, when trial and erroring this, I came across an undefined error if the battler who died had both a transformation state and a status state. That state notetag on the transformation state fixed it because the state stays in death.. The only downside to having it is that the transformation animation will still play if your battler is transformed. This can be easily fixed by following a fix at the bottom of the page. I haven’t tried removing the notetag but I think it’ll work if you remove it. But that’s up to you to test out.
    Spoiler: Q: Why use ‘target’ instead of ‘user’?
    I’m using ‘target’ for a couple reasons. 1. If you apply the state yourself: you’re the target & user. If the state gets applied to you by something else: you’re just the target. So no matter who applies the state to the battler (the battler themself, their allies & enemies) the code will run smoothly, animations as well. Using a mix of ‘user’ and ‘target’ variables (‘user’ and ‘target’ described here) did not work for me. If I used ‘target.’ and ‘target._’ in one state’s notetag and that state was applied in battle where the battler was affected by a different state’s notetag that was using ‘user.’ and ‘user._’ , it wouldn’t clear out the animation cycle of the one using ‘user’ variables. They would play over each other and sometimes crash the game depending on which state was applied or removed first. Sticking with ‘target’ variables made it so I wouldn’t have to worry who was applying the state or how to change animation cycles. Only one needs to play at a time, so if they clear and overwrite each other it's fine.
    Spoiler: Q: What exactly is prevFaceName & prevFaceIndex?
    I specify a specific file & index in target._prevFaceName and target._prevFaceIndex because they are my defaults, my starting points. Before any states, battle or anything: I want that as my face file & face index. It’s the default expression to fall back to after all the states come and go. I want it to be what’s seen in the menu screen before and after battle. I only use it on transformation states and not status states because of how I set up my states. All my different files have the same expressions in the same indices. So, the only time I need to use target._prevFaceName and target._prevFaceIndex is for my transformation states because they transform into a different character, so they need new face files. The status states like mad, happy & sad change with the transformations, they don't need to save a previous face. The faces are in the same indices, so no matter what face file I'm on: the correct animation will play.
    Spoiler: Q: What is (target.isStateAffected(32)) & (target.isStateAffected(31))?
    State ID 31 is one of my transformation states and State ID 32 is one of my status states. Those are checks to see if State ID 32 & 31 is applied to the battler affected. They are there to help decide what animations are played. The contents of their if statements are similar but not the same. A status state’s animation (ID 32 here) takes priority over a transformation state’s animation. This is because if you are affected by both states, you’d wanna see status state’s animation more than an idle one. Yes, since it individually checks states that means the more states you have: the more bloated the code will be. If anyone sees this and can suggest a more efficient, more optimised way to check different states, that’d be lovely. I’m worried that when I add more states, it might affect gameplay. But for what I have right now, across a full party of 4 with multiple states added: I still get 60 FPS. But who knows in the future? I don’t.
    Spoiler: Q: Why the actor checks on status states but not transformation states?
    It’s because I haven’t decided if I wanted to apply those specific status states to enemies. So, as an easy fix I just made a check for actors around the entire code for emotions. If the state is applied to someone who isn’t an actor, the animation code will simply not execute. They are not on transformations for personal choices. I know that the transformation states will only be applied to a specific actor. So, I didn’t bother making a check for actors there. If you need one, simply follow how the check is applied in the status states. If you want to get even more specific, you can do “if (target.actorId() === []){” after you do “if (target.isActor()) {”. I guess it’s a way to repurpose a state. Like, if you want the state’s notetag code to affect all actors, but have a different effect on a specific actor.
    Spoiler: Q: Why do you define function and certain variables multiple times?
    I realise this is bad practice. I tried using JS: Quick Function from VisuStella MZ's Core Engine Plugin but I may have applied it wrong because it wasn’t working for me. Not sure if there is another place/way to define a function then call it for later use. I haven’t looked into that. There are also slightly different versions of the swapping function. As for the variables, I have to sometimes. Let’s say if you apply state ID 31 to an actor who isn’t affected by state ID 32. It would completely miss out on the definitions for the state ID 32 faces if it were applied first. So, if the actor has state ID 32 & 31 active and state ID 31 gets removed first, it will crash the game since it never defined var faceNameMad1, var faceIndexMad1, etc…I thought those would be defined when state ID 32 would be added but, no, I had to define them in the state ID 31 notetags too. Maybe I did it wrong? Anyone is welcome to correct me, I don’t like having to keep defining things. I’m also unsure if there is another place/way to define and later call variables like this. Would be really nice and save a lot of space.
    Spoiler: Q: I want more status states and more transformation states. How can I add them?
    I only showcase how you can implement 1 transformation state & 3 status states. So, it makes sense if you want more. To implement more status state animations, follow what I did. That means, keep adding to the else if statement on the transformation states & making sure to add on to the user.removeState(ID) on the status states. Unfortunately, until I think of a less convoluted way/if someone points it out it needs to keep following that pattern. For transformations, you don’t have to worry about adding on to pre-existing status states or transformation states. Just copy and paste what you have on another state but change where you might need (face file names & indices).
    Spoiler: Q: Things I’m aware of and how to fix them

    • Animation playing on death, what do?
    You can add <JS On Add State> if(target._faceSwapLoopInterval) { clearInterval(target._faceSwapLoopInterval); }</JS On Add State> in the Dead state to clear the animation. But if you have a state that has <No Death Clear> Notetag, be sure to to add the idle animation back once the dead state is removed in the state tags for the dead state with <JS On Erase State>. I’m sure you can easily apply it with what you’ve read here.
    Spoiler: Q: Can you have an animation with more than 2 frames with each frame operating at a different speed?
    What a specifically odd question you’re asking. But, yes. Now, since I did this with a paid plugin and not with the status and transformation states and their animations, I cannot show you how to integrate this with that. It would follow the same logic obviously but you’d have to make a lot of compromises or rewrite/rethink parts of the code if you want more than 2 frames for a lot of states. Again, the big flaw with the whole face animations thing is the fact that you can only have 8 faces per face file. If it weren’t for that, you could probably have a lot more status animations, with a lot more frames. If you know how to increase the file size to allow for more indices, please share! Well anyway, here’s how I did more than 2 frames for a victory animation.
    -- 2+ FRAME ANIMATIONS + DIFFERENT SPEEDS --

    I’m doing this with the help of Victory Aftermath VisuStella MZ & Battle Core VisuStella MZ. Victory Aftermath VisuStella MZ is a PAID plugin. You don’t need this plugin, I’m just specifying this because this is one of the plugins I used to implement my idea + code. I did NOT implement this with the state animations above, it’s a victory animation. So, unfortunately, I cannot show you how to implement this with the above tutourial if you wanted 2+ frame animations with/without different speeds for those states. But, the code is very similar to the two frame animations so this can be adapted by yourself if needed. If you’re wondering why the second one is very oddly specific, it’s because it’s for my own animation I drew. Again, this is JUST the animation code. NOTHING ELSE. IF you implement this, be sure it fits in with EVERYTHING ELSE YOU DO.

    Spoiler: 1. 8 frame animation, cycles non-stop, consistent speed: Paste-able code
                    JavaScript:        
    <JS Battle Victory> if (target._faceSwapLoopInterval) {     clearInterval(target._faceSwapLoopInterval); } if (!target._prevFaceName) {     target._prevFaceName = 'TestDummy1';     target._prevFaceIndex = 0; }  var faceName = 'TestDummy1'; var faceIndices = [0, 1, 2, 3, 4, 5, 6, 7]; var currentIndex = 0;  target.setFaceImage(faceName, faceIndices[currentIndex]);  function cycleFaceImages() {     currentIndex = (currentIndex + 1) % faceIndices.length;     target.setFaceImage(faceName, faceIndices[currentIndex]); }  target._faceSwapLoopInterval = setInterval(function() {     cycleFaceImages();     target.refresh(); }, 200); </JS Battle Victory>


    The line by line code explanation is in the file "8Frame.txt", which is attached in this post.

    Spoiler: 2. 6 frame animation, plays all 6 frames once then swaps between the last two, different speeds: Paste-able code
                    JavaScript:        
    <JS Battle Victory> if (target._faceSwapLoopInterval) {     clearInterval(target._faceSwapLoopInterval); } if (!target._prevFaceName) {     target._prevFaceName = 'TestDummy1';     target._prevFaceIndex = 0; } var victoryFace = 'TestDummy1'; var faceIndices = [0, 1, 2, 3, 4, 5]; var currentIndex = 0;  target.setFaceImage(victoryFace, faceIndices[currentIndex]);  function cycleFaceImages() {     currentIndex = (currentIndex + 1) % faceIndices.length;      var interval;     if (currentIndex === 3) {         interval = 375;     } else if (currentIndex === 4) {         interval = 575;     } else {         interval = 95;     }      target.setFaceImage(victoryFace, faceIndices[currentIndex]);      if (currentIndex === 5) {         target._faceSwapLoopInterval = setInterval(function () {             currentIndex = (currentIndex === 4) ? 5 : 4;             target.setFaceImage(victoryFace, faceIndices[currentIndex]);         }, 575);     } else {         target._faceSwapLoopInterval = setTimeout(function () {             cycleFaceImages();             target.refresh();         }, interval);     } }  target._faceSwapLoopInterval = setTimeout(function () {     cycleFaceImages();     target.refresh(); }, 95); </JS Battle Victory>


    The line by line code explanation is in the file "6Frame.txt", which is attached in this post.

    -- END OF CODE FOR 3 - 8 FRAME ANIMATIONS, TERMS OF USE BELOW--


    • There are none (kinda)! You don’t need to give me credit, you can use/modify/adapt this in any way you want, you can redistribute it, translate it, do whatever!
    • I know it’s the internet and I can’t stop anyone from reselling and using this for their commercial projects but I’d prefer if you didn’t. Like I said, I like to keep stuff open for everyone, accessibility!
    • Do not credit me, period. No screen name, no abbreviations of it, no alternate names of mine, nothing crediting/referencing me inside or outside your project when it relates to this code. If someone wants to know how you did something achieved by this code, simply send them a link to the original post.
    • If you use anything from this post, you can say thanks by giving me advice on how to improve/fix this! Or you can give me tips related to this coding/scripting stuff in RPGMaker, JS or in general. I don’t know a lot about software stuff, I'm a huge beginner when it comes to software. I’m an intermediate in hardware, that’s my speciality: electronics & computers. My best languages are MATLAB, C, C++, VHDL, LabView & Assembly to name just a few.
    • Kind of similar to the previous point, if you make your own adjustments &/or optimise the code: please share here publicly! If you make it a plugin that has more/better options, better efficiency & is better optimised, share that too! Let’s help each other out c:



    Quick aside: It's really late where I'm at so I'm sorry if there are any inconsistencies, bad grammar, unreadable explanations. I will fix them ASAP. I hope you enjoyed reading this and I hope it works just as well for you as it does for me!

    ------------------------------------

    UPDATES, CHANGES & NEW TUTORIALS  #1: 28/01/24


    As I continue to work on my project, I've come across scenarios where I've gotten unintended side effects involving the in-battle animation notetags. There were some problems that arose in scenarios I tested and situations I didn't think of testing. So these changes are here to fix old & new mistakes. I'm also providing new notetag code for previously discussed topics (like handling the Dead state).  Everything not mentioned in the update has been untouched and still works how they are initially presented. Here are my changes:

    CHANGE #1 - START IDLE ANIMATION: I updated my language & line-by-line explanation in the newly attached .txt file (U1_ActorNoteTag_BattleStartIdleAnimation), which can be found below.. I also added 3 new lines to help with the interactions between the victory and state animations. No huge changes there, but a change you should add. Remember that this code goes in the Actor Note section (Database > Actors > [Actor ID & Name] > Note) of every actor you intend to have in battle. Here's the paste-able code:

    Spoiler: Start Idle Animation v1.1: Paste-able code
                    JavaScript:        
    <JS Pre-Start Battle> if(!target._prevFaceName){     target._prevFaceName = 'YourFileNameHere';     target._prevFaceIndex = 0; }  var faceNamebreathe1 = target._faceName; var faceIndexbreathe1 = 0; var faceNamebreathe2 = target._faceName; var faceIndexbreathe2 = 4;  target.setFaceImage(faceNamebreathe1, faceIndexbreathe1);  function swapFaceImages() {     if (target._faceName === faceNamebreathe1 && target._faceIndex === faceIndexbreathe1) {         target.setFaceImage(faceNamebreathe2, faceIndexbreathe2);     } else {         target.setFaceImage(faceNamebreathe1, faceIndexbreathe1);     } } target._faceSwapLoopInterval = setInterval(function() {     swapFaceImages();     target.refresh(); }, 1000); </JS Pre-Start Battle>


    CHANGE #2 - TRANSFORMATION IDLE ANIMATION: Ok, this one may or may not affect you depending on how you do your transformation state & if you are doing the victory animations or not. There's only a one line change in the <JS On Remove> section, a $gameTemp.reserveCommonEvent script call after target._prevFaceIndex = undefined;. In my new line-by-line explanation I add a bunch of comments explaining it. Here's the short of it. To do my transformation states, I use a skill that grants the state & then plays a common event in the Effects tab. The common event checks if the actor has the transformation state, if they do: they change class, name & and skills. When the state is removed mid-battle, the actor changes back to how they were pre-transformation state via a $gameTemp.reserveCommonEvent script call. This works perfectly in battle, but I noticed some problems after battle (but still on the battle screen) and on the map after the battle. I explain the problem further in the new .txt for the Transformation Idle Animation (U1_StateNoteTag_TransformationIdleAnimation) & in the next change section. If I explain it here I'm getting off-topic. No paste-able code here because it's a one line difference from the paste-able code above. Check the .txt for the explanations and changes, which is attached below..

    CHANGE #3 - VICTORY ANIMATION: Doing the victory animation was a handful. Looking back, posting the code for the complex animations only wasn't enough. Someone would have to research a lot more beyond this post, which was the opposite of what I wanted. Especially after encountering the problem above.

    Now, onto the problem. After winning a battle but not exiting the battle screen, at least for me, common events won't execute. If you checked off "Removal at Battle End," it will remove the state and run the <JS On Remove> code...but it'll skip over the common event script call. Even if you type the script call again under these Visustella notetags from their Battle Core plugin: <JS Battle Victory>, <JS Escape Success>, <JS Pre-End Battle>, and <JS Post-End Battle>. I have no idea why this happens. Maybe it's my plugins? Maybe it's my methods? Maybe I don't understand MZ enough? I've tried nine ways to Sunday to find out why common events won't run there & to make them, but I can't. For me, common events won't run after you complete a battle but do not exit the battle screen.

    So what's the fix? It's a two-parter. The first part is the most important & should be written in your victory animation code if you're doing a victory animation with Visustella's Victory Aftermath Plugin, like I am. There are other reasons I wrote down. I have the first part of the fix + more reasons in the .txt file (U1_ActorNoteTag_VictoryAnimation.txt) for the full victory animation code, which is attached below. This victory animation code has the animation prep + a new sample animation. T
    his code goes in the Actor Note section (Database > Actors > [Actor ID & Name] > Note) of every actor you intend to have in battle. Here's the paste-able code:

    Spoiler: Victory Animation v1.0: Paste-able Code
                    JavaScript:        
    <JS Battle Victory> if($gameActors.actor(Actor ID).isStateAffected(Transformation State ID)) {     $gameActors.actor(Actor ID).removeState(Transformation State ID);     $gameActors.actor(Actor ID).changeClass(Class ID, true);     $gameActors.actor(Actor ID).setName('Name'); } if($gameActors.actor(Actor ID).isStateAffected(Status State 1 ID)) {     $gameActors.actor(Actor ID).removeState(Status State 1 ID); } if($gameActors.actor(Actor ID).isStateAffected(Status State 2 ID)) {     $gameActors.actor(Actor ID).removeState(Status State 2 ID); } if($gameActors.actor(Actor ID).isStateAffected(Status State 3 ID)) {     $gameActors.actor(Actor ID).removeState(Status State 3 ID); } if(target._faceSwapLoopInterval) {     clearInterval(target._faceSwapLoopInterval); } if(!target._prevFaceName) {     target._prevFaceName = 'YourFileNameHere';     target._prevFaceIndex = 0; } var victoryFace = 'YourFileNameHere'; var faceIndices = [0, 1, 2, 3, 4, 5, 6, 7]; var currentIndex = 0; target.setFaceImage(victoryFace, faceIndices[currentIndex]);  function cycleFaceImages() {     currentIndex = (currentIndex + 1) % faceIndices.length;     var interval;     if(currentIndex === 3) {         interval = 375;     } else if(currentIndex === 4) {         interval = 200;     } else if(currentIndex === 5) {         interval = 100;     } else {         interval = 95;     }     target.setFaceImage(victoryFace, faceIndices[currentIndex]);     if(currentIndex === 6) {         target._faceSwapLoopInterval = setInterval(function() {             currentIndex = (currentIndex === 6) ? 7 : 6;             target.setFaceImage(victoryFace, faceIndices[currentIndex]);         }, 575);     } else {         target._faceSwapLoopInterval = setTimeout(function() {             cycleFaceImages();             target.refresh();         }, interval);     } } target._faceSwapLoopInterval = setTimeout(function() {     cycleFaceImages();     target.refresh(); }, 95); </JS Battle Victory>


    CHANGE #4 - POST-VICTORY: This is new NoteTag code added to help with clearing and stopping all animations, the last NoteTag code that will execute. After your victory and before you gain access to the map again. It can also help users using Visustella's Victory Aftermath Plugin. It's explained further in the .txt file(U1_ActorNoteTag_PostVictoryAnimationClear) associated with this section, which is attached below. This code goes in the Actor Note section (Database > Actors > [Actor ID & Name] > Note) of every actor you intend to have in battle. Here's the paste-able code:

    Spoiler: Post-Victory v1.1: Paste-able Code
                    JavaScript:        
    <JS Post-End Battle> setTimeout(function() {     if(target._faceSwapLoopInterval) {         clearInterval(target._faceSwapLoopInterval);     }     if(!target._prevFaceName) {         target._prevFaceName = 'YourFileNameHere';         target._prevFaceIndex = 0;     }     target.setFaceImage(target._prevFaceName, target._prevFaceIndex);     target.refresh();     target._prevFaceName = undefined;     target._prevFaceIndex = undefined; }, 3050); </JS Post-End Battle>


    CHANGE #5 - DEATH STATE: This is new NoteTag code added to help with clearing animations after dying. You probably don't want your battler to be moving when dead, this code is to help with that. I mentioned how to kind of sort of do it in my initial post, but again, it was one of those things where I was like "this might be hard for someone to figure out" and I didn't want to gatekeep that information. I also added some suggestions to make your death state look more fun. The full, line by line explanation is in a .txt file(U1_StateNoteTag_Death), which is attached below. This code should go into the State Note section (Database > States > [State ID & Name] > Note) of State ID 001, Dead. Here is the paste-able code.

    Spoiler: Clear Animations on Death v1.0 - Paste-able Code
                    JavaScript:        
    <JS On Add State> if(target.isActor()) {     if(target._faceSwapLoopInterval) {         clearInterval(target._faceSwapLoopInterval);     }     target.setFaceImage(target._faceName, 0);     target.refresh(); } </JS On Add State> <JS On Erase State> if(target.isActor()) {     var faceNamebreathe1 = target._faceName;     var faceIndexbreathe1 = 0;     var faceNamebreathe2 = target._faceName;     var faceIndexbreathe2 = 4;     target.setFaceImage(faceNamebreathe1, faceIndexbreathe1);      function swapFaceImages() {         if(target._faceName === faceNamebreathe1 && target._faceIndex === faceIndexbreathe1) {             target.setFaceImage(faceNamebreathe2, faceIndexbreathe2);         } else {             target.setFaceImage(faceNamebreathe1, faceIndexbreathe1);         }     }     target._faceSwapLoopInterval = setInterval(function() {         swapFaceImages();         target.refresh();     }, 1000); } </JS On Erase State>


    CHANGE #6 - MAP COMMON EVENT: This is the second part of the fix mentioned earlier. No code for this one, just follow along.

    1. Click on your Plugin Manager



    2. Find and click on your VisuStella Battle Core Plugin



    3. In its Plugin Parameters, scroll to find Mechanics Settings and click on it



    4. In Mechanics Settings, scroll to find Common Events (on Map) & in that section: click on Post-Battle Event. Pick/Create a common event that will undo your transformation state's changes. This is done so that if an actor wins a battle while still transformed, the transformation states changes will be undone by the time the player can open and check the status menu.




    If you made it this far, thanks for reading at this update! The same "Terms of Use" from my original post apply to this update. I hope anyone reading can learn something new, help me learn something new, or can find some use with this!

    ------------------------------------


    本贴来自国际rpgmaker官方论坛作者:NoOne_Really处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/how-to-make-2-frame-animated-actor-faces-in-frontview-battle-status-window-free-bonus-victory-animations-w-actor-faces-28-01-24-update-1.163220/

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x
    天天去同能,天天有童年!
    回复 送礼论坛版权

    使用道具 举报

    文明发言,和谐互动
    文明发言,和谐互动
    高级模式
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    简体中文
    繁體中文
    English(英语)
    日本語(日语)
    Deutsch(德语)
    Русский язык(俄语)
    بالعربية(阿拉伯语)
    Türkçe(土耳其语)
    Português(葡萄牙语)
    ภาษาไทย(泰国语)
    한어(朝鲜语/韩语)
    Français(法语)
    关闭

    幸运抽奖

    社区每日抽奖来袭,快来试试你是欧皇还是非酋~

    立即查看

    聊天机器人
    Loading...

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2026-7-16 17:27 , Processed in 0.162525 second(s), 55 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表