RMRK is retiring.
Registration is disabled. The site will remain online, but eventually become a read-only archive. More information.

RMRK.net has nothing to do with Blockchains, Cryptocurrency or NFTs. We have been around since the early 2000s, but there is a new group using the RMRK name that deals with those things. We have nothing to do with them.
NFTs are a scam, and if somebody is trying to persuade you to buy or invest in crypto/blockchain/NFT content, please turn them down and save your money. See this video for more information.
Making Your own Secondary Exp Pool

0 Members and 1 Guest are viewing this topic.

***
Rep:
Level 82
We learn by living...
So I messed around with this for a while, and I discovered by doing this kind of stuff, you could make a secondary type of experience.

Code: [Select]
class Game_Actor < Game_Battler 

def setup(actor_id)
    @mexp = 0
  end

  #--------------------------------------------------------------------------
  # * Calculate MEXP
  #--------------------------------------------------------------------------
  def mexp=(mexp)
    @mexp = [[mexp, 9999999].min, 0].max
  end

end

Code: [Select]

class Scene_Battle

 def start_phase5
...
    # Initialize EXP, amount of gold, and treasure
    exp = 0
    mexp = 0

...
 exp += Integer(0.50 * enemy.exp)
  mexp += Integer(0.50 * enemy.exp)
...

    # Obtaining EXP
    for i in 0...$game_party.actors.size
      actor = $game_party.actors[i]
      if actor.cant_get_exp? == false
        last_level = actor.level
        actor.exp += exp
        actor.mexp += mexp
end

end


These are partials of what I've been messing with lately, but basically, I created a magic exp vs. nonmagic exp system so depending on your actions and enemies, you could get more of one than the other...

I created a variant of an element I called "Experience" that determines which portion of experience a given monster provides. For example, if the element is listed as "C", then it's 50/50 split, while "A" is 100/0, and "E" is 0/100.


I posted this because I was just happy my attr_accessor finally changes without needing a "base + modifier". For some reason, putting my_var in parenthesis fixes the "always at zero" problem.

Code: [Select]
  def my_var=(my_var)
    @my_var = [[my_var, 9999999].min, 0].max
  end

hopefully I haven't missed anything.

*
Rep:
Level 82
You could make as many exp pools as you wanted to. Similarly, you could have two different kinds of 'MP' pools with skills using up the appropriate one (or a mix of both).

The method my_var= is an overwrite of the = function using on the my_var variable. When you set a variable with attr_accessor, the compiler translates that and sets up two methods in it's place. So if I have

Code: [Select]
attr_accessor: my_var

The compiler adds in the following:

Code: [Select]
def my_var
  return @my_var
end

and

Code: [Select]
def my_var=(val)
@my_var = val
end

The first of those is the reader attribute, the second is the writer (thus using attr_reader will only add that first method, and attr_writer will only add the second).

You can also overwrite those methods yourself to handle the reader/writer methods in a different. In your version, rather than simply saying the variable is equal to the value on the right hand side of the '=' sign, you want it to set the value as long as it's not less than 0 or greater than 9999999 (otherwise it is instead set as 0 or 9999999 depending).

If you don't put the (my_var) after the my_var=, then when you first try to call my_var it is uninitialized which I think returns some very strange number (I've had infinity come up before when I've forgot to initialize a variable).

You can overwrite other operators in the same way too. Take a look at Game_Switches. You'll see it says:

Code: [Select]
def [](switch_id)
    if switch_id <= 5000 and @data[switch_id] != nil
      return @data[switch_id]
    else
      return false
    end
  end

This is an overwrite of the [] operator. It changes the way that a value called from an element of the array is handled. This one prevents the game crashing if you call a non-existent value or try to operate on one. Simply, if the switch hasn't been initialized (value doesn't exist; it is nil) then return false (as if the switch was not on). Otherwise, return the state of the switch because it does exist and has been initialized at some point.

It's a powerful tool if you know what it does and how to use it effectively, especially in cases where you may get bad errors like in the way it is used in the Game_Switches class.

By the way, I'm not assuming you do or do not know this. It's simply an explanation for anyone who may wonder what it is and how it works.
« Last Edit: October 02, 2011, 12:35:30 AM by LoganForrests »
(Why do I always feel like it's the end of the world and I'm the last man standing?)

***
Rep:
Level 74
I'm baaack!
This is pretty cool! Also Logan, is that the full script or just some attributes required to make 2 types of MP? I think that would be a fun feature!

***
Rep:
Level 82
We learn by living...
be sure to add your alternative Exp system in Window_BattleResult. I just added mine in today. You just expand the list and make room by copying the existing exp pattern.

example

Code: [Select]
class Window_BattleResult < Window_Base
  #--------------------------------------------------------------------------
  # * Object Initialization
  #     exp       : EXP
  #     gold      : amount of gold
  #     treasures : treasures
  #--------------------------------------------------------------------------
  def initialize(exp, mexp, gold, treasures)
    @exp = exp
    @mexp = mexp
    @gold = gold
...

     x = 4
    self.contents.font.color = normal_color
    cx = contents.text_size(@exp.to_s).width
    self.contents.draw_text(x, 0, cx, 32, @exp.to_s)
    x += cx + 4
    self.contents.font.color = system_color
    cx = contents.text_size("EXP").width
    self.contents.draw_text(x, 0, 64, 32, "EXP")
    x += cx + 16
    self.contents.font.color = normal_color
    cx = contents.text_size(@mexp.to_s).width
    self.contents.draw_text(x, 0, cx, 32, @mexp.to_s)
    x += cx + 4
    self.contents.font.color = system_color
    cx = contents.text_size("MXP").width
    self.contents.draw_text(x, 0, 64, 32, "MXP")
    x += cx + 16
    self.contents.font.color = normal_color
    cx = contents.text_size(@gold.to_s).width
    self.contents.draw_text(x, 0, cx, 32, @gold.to_s)
    x += cx + 4
    self.contents.font.color = system_color
    self.contents.draw_text(x, 0, 128, 32, $data_system.words.gold)
    y = 32
 ...

you will also want to add it in your list of scene battle 2:

Code: [Select]
  # Make battle result window
    @result_window = Window_BattleResult.new(exp, mexp, gold, treasures)
    # Set wait count
    @phase5_wait_count = 100

***
Rep:
Level 69
RESIDENT ADONKADONK
Alright, can you give me like a full 'script', I am actually really confused to what it is that I am supposed to be doing with all of this.

I'm back.

*
Rep:
Level 82
I would consider these more of a help to scripters that might want to expand on the ideas, rather than scripts themselves. Think of them like a tutorial for a scripter.

My contribution is simply an expansion of this. I just explained why using attr_accessor (and attr_reader and attr_writer) whilst writing scripts works the way it does.

They're also for RMXP I believe. VX handles the exp in a fairly different way to XP (like most things).

Those script snippets posted by Shintashi won't work if you directly copy them. There's some syntax errors lying around, mostly in the form of missing 'end' keywords. Like the word above them says: 'example'. If you do want a proper script made to fully handle, it might be worth asking for one/waiting.
(Why do I always feel like it's the end of the world and I'm the last man standing?)

***
Rep:
Level 82
We learn by living...
since I'm working on completely overwriting large portions of my game, instead of the normal "put everything at the end above main", there's some pros and cons to me providing the "full" scripts. The most obvious is the fact that I'm going to exceed my line maximum for a single post. All the functioning parts have been posted, but the locations have not.

here's a rough map:


#        *   Completed Snippets (And Locations)   *
#-------------------------------------------------------------------
# line 135-143 of Game_Enemy = element_ranks(element_id) defines MXP/EXP split
# line 142, 150-171, 195 of Scene_Battler_2 = meta exp code vs. elements.
# line 23, 55-58 of Game_Actor = base meta exp codes
# line 113-120 of Game_Actor = meta exp code base
# line 16, 40-47 of Window_BattleResult = meta exp battle reward
# line 215 of Scene_Battler_2 = meta exp battle reward window


note that I created a new element called "Experience". All elements have 6 levels, 1 through 6. By editing Game_Enemy as follows:

Code: [Select]
#--------------------------------------------------------------------------
  # * Get Element Rank Value
  #     element_id : Element ID
  #--------------------------------------------------------------------------
  def element_ranks(element_id)
    # Get a numerical value corresponding to element
    result = $data_enemies[@enemy_id].element_ranks[element_id]
    return result
  end

I was able to allow myself easy access to their element numbers, rather than that 100/200/0/-100 gibberish it would spit out otherwise. Once I had numerical access, I could do this:

Code: [Select]
#=============================================================   
#    ***   Metaphysical Exp Processing ***
#    $data_enemies[i].element_ranks[17]   
#        where i is the enemy id number
        case enemy.element_ranks(17)
        when 1  # Barbarians & Giants
          exp += enemy.exp
        when 2  # Monsters & Monks
          exp += Integer(0.75 * enemy.exp)
          mexp += Integer(0.25 * enemy.exp)
        when 3  # Dragons & Elves
          exp += Integer(0.50 * enemy.exp)
          mexp += Integer(0.50 * enemy.exp)
        when 4  # Wizards & Warlocks
          exp += Integer(0.25 * enemy.exp)
          mexp += Integer(0.75 * enemy.exp)
        when 5  # Spirits
          mexp += enemy.exp
        when 6  # Bad Karma
          mexp -= enemy.exp
        end


in My Scene_Battle 2.

Note that this engine is only using two forms of experience, and using a single element (#17) to divide it. I could just as easily make a dozen new elements each determining what portion of experience is lost or gained. For example, I could make a "book learning", a 'body building", a "magic learning", a "faithfulness" and a "corruption" pool all related to what monsters I killed or what tasks I performed. I just didn't need more than two pools at the time.

*
Rep:
Level 82
If you feel like your script would exceed the length line of a post, you could always save it as a .txt on your computer and upload/attach that file.

It's also not a good idea or good scripting practice to change code from within the default scripts. There's ways of simply overwriting or aliasing methods to add in what you want the system to do. Overwriting the base code causes severe compatibility issues when added to a game that already contain a number of scripts that require the default information.

For your own game, this doesn't matter as much because you can deal with the issues that come up and modify your own additions accordingly (though it is still bad practice). When it comes to other peoples' games, though, you'll have to be ready to address any incompatibility issues that crop up - which I'd expect to be many.

On another note:

Code: [Select]
def element_ranks(element_id)
    # Get a numerical value corresponding to element
    result = $data_enemies[@enemy_id].element_ranks[element_id]
    return result
  end

can be simplified into:

Code: [Select]
def element_ranks(element_id)
    # Get a numerical value corresponding to element
    return $data_enemies[@enemy_id].element_ranks[element_id]
  end

There's no real need to create and initialize a new variable that has no further operations performed on it. It's pretty standard of a get method to simply return what data is needed.
« Last Edit: October 02, 2011, 05:48:10 AM by LoganForrests »
(Why do I always feel like it's the end of the world and I'm the last man standing?)

***
Rep:
Level 82
We learn by living...
I used to think that was true until I ran into issues where it grew exponentially more complicated and incompatible for myself to fix things. For example, various versions of SDK not being compatible, UMS compatibility, ABS, etc. I'm overwriting my game true, but its one of about a dozen different projects.

One of the techniques I've concerned myself with is keeping track of all of my changes in a separate section, including which class file, which lines, and what was changed. I don't recommend a person new to scripting overwrite anything.

When you don't know if it's going to work, comment out what you are replacing and test it. If it fails, you can remove the comments "#" and comment out your own edits and research where you might have gone wrong.

*
Rep:
Level 82
Some good advice, Shin. Definitely not something a new scripter would want to do due to the amount of attention needed to ensure you don't get stuck in a terrible position. It's a position that no one can really help you out of either other than by saying 'start a new project'.

I hope you don't take my comments aimed at what you're doing personally. It doesn't sound like it, but I like to be sure.

They're simply neutral comments aimed at making sure new scripters coming in to get some inspiration or understanding and feeling that overwriting the default scripts is the way to go know that, by standards, it isn't.
(Why do I always feel like it's the end of the world and I'm the last man standing?)

***
Rep:
Level 82
We learn by living...
a person should always have a fresh copy of a working project on the side to pull script from to fix "unworkable" script, and take a few steps back. By documenting your progress, you can avoid tragic mistakes, like the accidental deletion of some definition - that happened to me today while I was trying to reposition the SP/HP text in battle. What do you do when something crashes and you don't know why? You go looking for it in a "stock" program.

You should also test out highly experimental ideas in a "test" project, rather than your main project, before importing them into your main project. That rule applies to pretty much any kind of programming. Also be wary of making something too big outside your main - because when you try to interface it, it's going to have all kinds of meshing problems, possibly being completely unworkable.

Also beware of memory leak and lag. What works in a mini game might only work because there's nothing else going on in your test file. When you have a sizable program, it can noticeably lag with too much stuff running in the background. The types of programmers who can make a game just like they want it and don't run into these problems are a rare and special species I have yet to meet.