Is it possible to have a variable determine what skill is learned at a given level?

Discussion in 'RPG Maker MV' started by ddblue, May 24, 2018.

  1. ddblue

    ddblue 新人 Veteran

    Messages:
    120
    Likes Received:
    15
    Location:
    Japan
    First Language:
    English
    Hello!

    I was wondering if it’s possible to achieve the following:

    Harold speaks to an NPC
    During the conversation, Harold is faced with a “good” dialogue choice and an “evil” dialogue choice.
    Good choice = good variable +1
    Evil choice = evil variable +1

    Depending upon whether Harold has more good or evil points, the skill he learns upon leveling up changes.

    If he’s got a higher good variable, he automatically learns “heal” at level 2

    If he’s got a higher evil variable, he instead automatically learns “hurt” at level 2


    Is this possible?
     
    #1
  2. Shaz

    Shaz Veteran Veteran

    Messages:
    36,911
    Likes Received:
    10,849
    Location:
    Australia
    First Language:
    English
    Primarily Uses:
    RMMV
    Yes, with a plugin.
     
    #2
    ddblue likes this.
  3. gstv87

    gstv87 Veteran Veteran

    Messages:
    1,488
    Likes Received:
    565
    First Language:
    Spanish
    Primarily Uses:
    RMVXA
    Code:
    Game_Actor.prototype.levelUp = function() {
        this._level++;
        this.currentClass().learnings.forEach(function(learning) {
            if (learning.level === this._level) {
                this.learnSkill(learning.skillId);
            }
        }, this);
    };
    
    Code:
    this.learnSkill(learning.skillId);
    
    that's your entry point.
    learning.skillId is what defines which skill of the library is to be learned.
    you make that ID the result of a function, where you evaluate your variables.
     
    #3
    ddblue likes this.
  4. ddblue

    ddblue 新人 Veteran

    Messages:
    120
    Likes Received:
    15
    Location:
    Japan
    First Language:
    English
    Thank you. Is there one you could suggest?

    I can tell this is a well-thought out response, but I'm not great with code just yet.
    Would I create a plugin using this? Or is this a script call? And how might I change the level to be a specific level (for example at level 5 learn either Heal or Hurt)?
     
    #4
  5. gstv87

    gstv87 Veteran Veteran

    Messages:
    1,488
    Likes Received:
    565
    First Language:
    Spanish
    Primarily Uses:
    RMVXA
    you could.
    it depends on how big you might want to need it to be.
    this is just part of the code of the game,.... it runs *on* this, so it should work for you, even with modifications.

    it could be.
    if you take the line that loads the skill itself, you can make *that* part of a function, and then call it from somewhere else (replacing that line on that code by a call to your function instead, so it all goes to where you want it)

    what you need has three parts to it: the user end, the decision, and the back end.
    the back end already exists: it's what drives the game as it is.
    the user end, is what you use to handle the user input (I assume its a choice window sending the input to a game variable)
    the decision, is what will ultimately send the data to a game event, or, to the back end code.
    if you create a plugin out of this, it'll go to the back end code.
    if you make a common event, it'll go to a common event, but if that is the case you won't be able to use the actor's class' own system to store all the skills available for learning (as it is, normally, regardless of the learning system)

    the class' learning list is actually a stack of Learning objects, each of them holding a level value, a skill value, and a notes space.
    if you want to have two skills available at level 5, you set them to level 5 as you would in a regular class, but modify the selection of them from "attained level" to "result of this comparison between variables"

    something like:

    Code:
    Game_Actor.prototype.levelUp = function() {
       this._level++;
       this.currentClass().learnings.forEach(function(learning) {
           if (learning.level === this._level) {
               this.learnSkill(this.getSkillID());
           }
       }, this);
    };
    
    Game_Actor.prototype.getSkillID = function() {
     if ($gameVariables[id] > $gameVariables[id]) {
      return skillid1;
     }else{
      return skillid2;
     };
    };
    
    
    you can pass the actor's own ID as a parameter, if you want a more complex selection:
    Code:
    Game_Actor.prototype.getSkillID = function(actorid) {
     actorid = actorid || this._actorId;
      switch (actorid){
       case 1:
        if ($gameVariables[id] > $gameVariables[id]) {
         return skillid1;
        }else{
         return skillid2;
        };
        break;
       case 2:
        (different formula)
        break;
       case 3:
        (etc etc)
        break;
       };
    };
    };
    
    getSkillID will always return a number.
    that number, is what LearnSkill() uses as it's own parameter to decide which skill to load.
     
    #5
  6. AuralPC

    AuralPC Veteran Veteran

    Messages:
    48
    Likes Received:
    14
    Location:
    China
    First Language:
    Chinese
    Primarily Uses:
    RMMV
    While this can be done by a plugin, I think you can also do this by a little complicated common event, if I didn't misunderstand your request.

    Here is what I would do:
    1.png
    First of all, set up 3 variables:
    good variable, evil variable, and Actor level.
    2.png
    And then set up 1 switch:
    Skill Learn.

    Now, lets set up the common event as follow:
    3.png

    5.png
    This line is to set the variable 'Actor Level' we just set up equals to Actor1's level, which is Harold in my case.
    9.png

    Then lets set up an autorun map event to turn on the switch 'Skill Learn' so the common event we just set up can start running.
    6.png
    Last but not least, lets set up a map event to test out.
    7.png
    8.png
    :kaojoy:

    If you have more skills, just add more conditional branch in the common event.

    Hope this helps.:kaoluv:
     

    Attached Files:

    • 4.png
      4.png
      File size:
      31.7 KB
      Views:
      1
    #6
    ddblue and mobiusclimber like this.
  7. Shaz

    Shaz Veteran Veteran

    Messages:
    36,911
    Likes Received:
    10,849
    Location:
    Australia
    First Language:
    English
    Primarily Uses:
    RMMV
    I wouldn't go that way. You are setting up a parallel process common event which will run 60 times a second for the entire game just to do something that only needs to happen once in a while. And if the condition is true that would cause the skill to be learned, it will keep trying to learn the skill, 60 times a second, from the moment the condition is true until the actor gains another level.

    Unfortunately, this is the kind of event that causes games to lag.

    You absolutely could do it that way, don't get me wrong. It would work. But you would be introducing other issues in the process.

    I said a plugin would be necessary, because it is only through the scripts where you can make something happen at the time the actor gains a level without having to sit and check for it repeatedly.
     
    #7
    ddblue likes this.
  8. AuralPC

    AuralPC Veteran Veteran

    Messages:
    48
    Likes Received:
    14
    Location:
    China
    First Language:
    Chinese
    Primarily Uses:
    RMMV
    @Shaz Good point, I am actually thought about this problem last night.

    While, I agree plugins and scripts are always the best way to solve problems, just.....as long as you have the knowledge to create them.

    For people like me, who have no Javascript background, it is really improsible to write a script to solve the problem. It's much easier to just play with MV's default functions.

    I always question myself why my major wasn't software programming, when everytime I stuck with my project. LOL!

    Anyway, lets go back to the problem.

    I spent some time this morning and played with MV a bit, and found a few other ways to set up the same function.

    Among them I believe use parallel common event to set up this function is still the easiest way. But, if parallel common event really causes lagging problems to @ddblue your project, I can give you an alternative solution.

    Forgive me not upload images this time. It really gives me headache to adjust all the screenshots. If you're interested in the alternative solution, and need example of it. Just Notify me. I will upload images when I got time.

    First of all, lets start with what we need.

    We still need 3 variables:
    good variable, evil variable, Actor level.

    Then we need 5 switches:
    Good skill learn, evil skill learn, Moral state check, Level Check, and Battle Check.

    Now lets set up the events.

    First of all, set up an autorun map event to turn on Battle Check switch. Remember to also turn on selfswithch-A for this event, and add a second page which runs when selfswitch-A is on. This is to stop this event.

    As for my understanding, the good variable and the evil variable will be changed through events.

    So, we can add a trigger at the end of those events to turn on Moral state check switch.

    Create a common event that autoruns when Moral state check switch is on.
    In this event, there are two conditional branches:
    If good variable is greater than evil variable
    ------turn on Good skill learn switch
    ------turn off evil skill learn switch.
    If evil variable is greater than good variable,
    ------turn on evil skill learn switch
    ------turn off good skill learn switch.
    And below above two conditional branches, add 'turn on Level Check switch'.
    At the end of this event, turn off Moral state check switch, so this event stops running.

    Next, lets go to Troops page in database, in each Troop, add a battel event to turn on Level Check switch under condition when Battle Check switch is on, span: Battle.

    Now, create an autorun common event when Level Check switch is on.
    5.png
    Add this at the top to get the actors level.
    And then, add two Conditional Braches.
    ------If good skill learn switch is on.
    ------If evil skill learn switch is on.
    Under each conditional brach, add below conditional braches to teach actor corresponding skills.
    If: variable Actor Level = X
    ------Change Skils = ActorX, +Skill name
    Finally, at the end of this event, turn off Level check switch.

    Last but not least, upon revise my solution, I just realized that you may want to delete all the learned skills incase the actor changed his moral state halfway in the game.
    I am guessing you don't want the actor to keep good skills when his evil variable becomes greater in the middle of the game, vice versa.
    If I'm wrong, just ignore the following.

    In the common event that runs when Level Check switch is on, add below content under conditional branches 'if good skill learn switch is on'.
    Change skill = ActorsX, -All the evil skills

    And add below content under conditional branches 'if evil skill learn switch is on'.
    Change skill = ActorsX, -All the good skills

    This should do the trick.

    Hope this helps!:kaojoy:
     
    Last edited: May 27, 2018
    #8
    ddblue likes this.
  9. Shaz

    Shaz Veteran Veteran

    Messages:
    36,911
    Likes Received:
    10,849
    Location:
    Australia
    First Language:
    English
    Primarily Uses:
    RMMV
    Actually, they're not. It is smart to look for a way to solve a problem without plugins/scripts first, and then only resort to them if you can't find one, or can't find one that works well (a continual parallel process, for example, when the condition is only going to be true now and then).

    Your second suggestion is a very nice non-plugin solution. However I'd use parallel process events all the way through, rather than autorun. Autorun is mainly used for cutscenes, and only one will run at a time - if you actually had a cutscene with an autorun event, it, or the event you've listed, would be delayed. Parallel process events can run at the same time as other things, so don't delay any processing (though yours would be completed in a flash anyway). And in all engines prior to MV at least, parallel process events run before the map has faded in and is visible, while autorun events run after the map becomes visible.
     
    #9
    AuralPC likes this.
  10. AuralPC

    AuralPC Veteran Veteran

    Messages:
    48
    Likes Received:
    14
    Location:
    China
    First Language:
    Chinese
    Primarily Uses:
    RMMV
    Learned something!

    I never thought there would be that many differences between parallel events and autorun events.

    Before today, I thought the only difference is one loops itself and the other don't......lol
     
    #10
  11. Shaz

    Shaz Veteran Veteran

    Messages:
    36,911
    Likes Received:
    10,849
    Location:
    Australia
    First Language:
    English
    Primarily Uses:
    RMMV
    They both loop :)

    Autorun events will only run one at a time, and the player cannot do anything while they are running - no movement, no menu access.
    Parallel process events can run in conjunction with each other, and the player has the usual control while they're running.

    This is why autorun events are good for cutscenes (you don't want to direct the PC to walk up to an NPC and start talking, then have the player make them go over and look at stuff while it's happening), or maybe for puzzles where you want strict control over player input, but not for much else.
     
    #11
    AuralPC likes this.

Share This Page