Main Menu
  • Welcome to The RPG Maker Resource Kit.

[VXA] Monster Catalogue

Started by modern algebra, February 05, 2012, 12:49:04 AM

0 Members and 1 Guest are viewing this topic.

Trihan

Thanks for the explanation! That's actually kind of what I thought it was there for, so it's good to know I'm not completely insane. I actually completely follow your logic for doing that, as it's true that different scripters have different approaches.

While I have your attention, could you possibly point me in the right direction on something I'm trying to do for my own bestiary?

Being dynamic, the entries for stats will be approximated based on actions taken in battle. I will, therefore, obviously have to have an approximate counterpart for each stat that will be displayed unless an enemy is "scanned".

Say I decide to store said stats in Game_System::Bestiary::Entry.

In the initialize method for Game_System::Bestiary, could I do something along the lines of

$data_enemies.each { |enemy| $data_bestiary[enemy.id] = Game_System::Bestiary::Entry.new }

Would that work or am I barking up entirely the wrong tree?
It's more like a big ball of wibbly wobbly...timey wimey...stuff.

modern algebra

#26
No, not really. Even assuming that $data_bestiary was a hash and you saved $data_bestiary to the save file, using enemy objects as your keys would be unwise since they are created anew each time and so the enemy object for enemy 1 will be different the next time you open the game. As such, it couldn't serve as a reference to your class. Plus it uses a lot more memory than is necessary. It would be smarter just to use an array and use enemy.id, though you would naturally need to exclude the nil element of $data_enemies when setting it.

Additionally, I think that it might be more prudent to simply create a wrapper class for the array (like Game_Variables) and lazily instantiate the bestiary entries when appropriate, rather than creating them all once. It will save memory and is better for testing since it won't be corrupted every time you edit the enemies tab.

You could make it an instance variable of Game_System or some other Game_ class if you did not want to have to get into DataManager, but I think this is something where it would be appropriate to give it its own global variable. However, I wouldn't call your global variable $data_bestiary, since $data_ variables are all saved as .rv2 files and initialized anew whenever the game is started. Your variable needs to be saved in the save file. The name has no inherent value, naturally, but your variable is unlike every other $data_ variable and so it makes your code confusing to a reader.

Secondly, I don't know if there's much utility to placing your Bestiary module or class inside Game_System, and I would advise removing it as it is also a confusing class structure.

Entry could be a Struct.

That's probably a fairly obtuse block of text, but I can show you what I mean in code if you want.

Trihan

I got a friend to help me out with the structure and took your suggestions on board; this is what I came up with.

class Game_Bestiary
  def initialize
    @entries = []
    $data_enemies.each { |enemy|
      @entries.push(Game_Bestiary::Entry.new($data_enemies.index(enemy));
    }
  end
end

class Game_Bestiary::Entry
  def initialize(enemy_id)
    @enemy_id = enemy_id
    @param = Array.new(8, {:HIGH => 0, :LOW => 0})
  end
  def set_low_param(param_id, value = 0)
    @param[param_id][:LOW] = value
  end
  def set_high_param(param_id, value = 0)
    @param[param_id][:HIGH] = value
  end
 
  def low_param(param_id)
    @param[param_id][:LOW]
  end
  def high_param(param_id)
    @param[param_id][:HIGH]
  end
end

Then I would overload DataManager to create a $game_bestiary global variable.
It's more like a big ball of wibbly wobbly...timey wimey...stuff.

modern algebra

That looks fine and should work.


    for i in 0...$data_enemies.size do @entries.push(Entry.new(i)) end


That's fine (though it doesn't look like you have a way to access @entries from outside the class?), but what I was talking about when I said wrapper was:


class Game_Bestiary
  def initialize
    @data = []
  end
  def [](enemy_id)
    @data[enemy_id] = Entry.new if !@data[enemy_id]
    @data[enemy_id]
  end
  def []=(enemy_id, value)
    @data[enemy_id] = value if value.is_a?(Entry)
    self[enemy_id]
  end
end


Also, I generally don't like embedding classes within classes, but it is sensible enough in this circumstance. I might have used a Struct for Entry and probably just used ranges instead of the hashes, but those are mostly just preference and convenience. You likely wouldn't need many of the methods in Range anyway.

Trihan

#29
Okay, I've got the data structure implemented and working...the only hurdle I have left is that I can't quite figure out how to link up the monster card window and the list. I didn't implement the plethora of options you included (not yet at least) so I'm having some trouble following the path of your code. :P

Edit: Never mind, think I've got it sussed. :D

Edit 2: Sort of. I've implemented the Entry structure I mentioned, but when I do $game_bestiary[id].set_low_param(parameter id, value) for some reason it changes the value of every element in the array.

Edit 3: Fixed! The way the hash was set up it was only creating one instance of the object. Making it a Hash.new outside of the array made it work.
It's more like a big ball of wibbly wobbly...timey wimey...stuff.

pacdiggity

MA, I don't mean to bother you with such menial trivialities, but this is one of the most complicated scripts I've ever seen, and I've seen some... pretty strange ones. There are a lot of techniques you've used in this script that I'm not used to, and can't read into quite as clearly. Would you be so kind as to tell me the simplest way to tell if an enemy has been scanned, or just confirm my suspicion that it's in Game_System#mamc_analyze_ary ?
Thanks in advance.
it's like a metaphor or something i don't know

Trihan

Hope you don't mind me fielding this one MA, but you're right Pacman; mamc_analyze_ary is the array that contains which monsters you've scanned.

Edit: I was also quite confused by his method...method, but on reflection it's actually an incredibly clever way to avoid doubling up on code for methods that do pretty much the same thing but need to be separated.
It's more like a big ball of wibbly wobbly...timey wimey...stuff.

pacdiggity

#32
Thank you for confirming that. Would I check this by using:
if $game_system.mamc_analyze_ary[enemy.id]
  # do stuff that happens when only the enemy is scanned
else
  # do other stuff
end


Thank you again.
it's like a metaphor or something i don't know

Trihan

Just to be on the safe side I'd use

if $game_system.mamc_analyze_ary.include?(enemy.id)
  # do stuff that happens when only the enemy is scanned
else
  # do other stuff
end


But other than that, spot on.
It's more like a big ball of wibbly wobbly...timey wimey...stuff.

Trihan

While I think about it, you've just reminded me of something.

MA, you didn't specify a terms of use agreement in your script comments, and I've been borrowing pretty heavily from this system for my own dynamic bestiary (though I haven't really outright stolen anything it's been a big inspiration and I think I'd be remiss if I didn't include the species/category options). Is my project alright with you or would you prefer I didn't modify anything directly from this script?

Edit: I should point out that I know the general terms of use but I'd intended to publish my bestiary separately when I finish it, crediting you for the inspiration and for anything I use directly that I didn't edit or repurpose.
It's more like a big ball of wibbly wobbly...timey wimey...stuff.

modern algebra

Yeah, I just rely on the General Terms of Use. And yes, it's totally fine with me if you release your bestiary publically.

And yeah, Trihan is right Pacman. The way that array works is that the IDs of any analyzed monsters are added to it, so it would be something like [1, 3, 7] if monster 1, 3, and 7 are analyzed. So, checking array[7] wouldn't reveal whether monster 7 is analyzed - you need to check whether the ID is included in the array.

An alternative way to do it would be:


$game_system.mamc_data_conditions_met?(:analyze, enemy_id)


But that's just an indirect way of doing the same thing.

Sorry that my coding is hard to understand :(

Trihan

I was going to suggest using conditions_met? but thought it relied on a constant. I didn't notice that you supply the condition as a parameter. XD derp!

Also, thanks for confirming that you're cool with me releasing my bestiary. I'm super happy with how it's coming along so far!

So happy in fact, that I'd like you to have this complimentary screenshot.
It's more like a big ball of wibbly wobbly...timey wimey...stuff.

pacdiggity

Quote from: Seamus on April 11, 2012, 05:34:33 PM
Sorry that my coding is hard to understand :(
Not your fault, I should've realised that.
it's like a metaphor or something i don't know

jwei44

Is it just me, or does this script crash battle test?

modern algebra

It doesn't crash during battle test to me, so I don't know.

If you could recreate the error in a new project and send it to me though, I would be happy to take a look.

jwei44

#40
Quote from: modern algebra on April 28, 2012, 01:48:27 AM
It doesn't crash during battle test to me, so I don't know.

If you could recreate the error in a new project and send it to me though, I would be happy to take a look.

Alright, no crash here. I'll try and find a conflicting script. In the mean time, this is the error:



Found the conflicting script: Yanfly Engine Doppelganger

modern algebra

Alright, I know what is causing the error. All Objects have a class method which normally returns the class of the object. So the class method of an instance of Game_Enemy would normally return Game_Enemy, and that is what I expected to be returned when I did that check. Yanfly's script overwrites the class method in Game_Enemy and has it instead return the database class of the doppelganger actor.

The easiest fix would just be to go into my script at line 1355 and change:



        if enemy.class.method_defined?(:mamc_analyze_now) && enemy.mamc_analyze_now


to:



        if enemy.is_a?(Game_Enemy) && enemy.mamc_analyze_now

jwei44

Quote from: modern algebra on April 28, 2012, 02:47:39 AM
Alright, I know what is causing the error...

Alright, thanks! Hopefully soon I understand what you said as I am in the process of learning Ruby.

Acezon

Is it possible to put the monster's sprite beside its illustration? Or just the sprite? I can't seem to find that part in the script, sorry. :)

modern algebra

No, since monsters don't have sprites by default in RMVXA. How would you want to be able to specify what sprite to show?

Acezon

Quote from: modern algebra on May 08, 2012, 04:49:46 AM
No, since monsters don't have sprites by default in RMVXA. How would you want to be able to specify what sprite to show?

I think I'll just use its front pose as the battler. That way the script shows the sprite. Thanks for the help!

Wiimeiser

#46
Do you know what's causing this error? If it's not the same as before than I assume it's JP or something (hence the filename...)

If it helps, it happens when I highlight an enemy I've seen...

modern algebra

What other scripts are you using? Would it be possible for you to recreate the error in a new project and show me?

Wiimeiser

I'm assuming it's a conflict with enemy levels or doppelganger as before, or else the result of a new stat being added...
I'll probably upload a test project when I get around to it.

Wiimeiser

Okay, here's a project. Fiddle around a bit. Seems to occur when displaying the stats, not the battler.