nanakra

Villager
Member
Joined
Feb 5, 2015
Messages
8
Reaction score
2
First Language
English
Primarily Uses
RMVXA
Hi there!

I'm trying to figure out how to wipe everything from the party inventory (items, weapons, armor) but keep all key items.
This is for a jail type scene where the party won't get anything back.
However I am treating the key items as protected quest items and don't want to wipe them.
Not quite sure how to do it.
I know that I can use the below to clear everything, but don't know how to filter it so that key items are not included.
Code:
class Game_Party
 def clearitems
  $game_party.members.each do |act|
   act.clear_equipments
  end   
  @items = {}   
  @weapons = {}   
  @armors = {}  
 end
end

Any help is appreciated!
 

Roninator2

Gamer
Veteran
Joined
May 22, 2016
Messages
3,210
Reaction score
728
First Language
English
Primarily Uses
RMVXA
Perhaps a method would be to save the key items to a hash then do $game_party.init_all_items then add the key item hash to the party inventory.
The init_all_items does the same as the
Code:
  @items = {}   
  @weapons = {}   
  @armors = {}
 

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,425
Reaction score
602
First Language
Italian
Primarily Uses
RMVXA
I would use a different approach (mostly due to how ruby handles the garbage collector).
Code:
#------------------------------------------------------------------------------
# ** Game_Party class
#------------------------------------------------------------------------------
class Game_Party
  #----------------------------------------------------------------------------
  # * Clear Item Type
  #----------------------------------------------------------------------------
  def clear_item_type(container)
    container.each_key do |k|
      item = container[k]
      next if (item.is_a?(RPG::Item) && item.key_item?)
      gain_item(item, -item_number(item), true)
    end
  end # Clear Item Type
  #----------------------------------------------------------------------------
  # * Clear Items
  #----------------------------------------------------------------------------
  def clear_items
    clear_item_type($data_weapons)
    clear_item_type($data_armors)
    clear_item_type($data_items)
  end # Clear Items
end # end of Game_Party
Please note that this has been written from mobile and might include syntax errors. I did my best to check it before posting, but do not be afraid to notify me should you find any issue.
 

Roninator2

Gamer
Veteran
Joined
May 22, 2016
Messages
3,210
Reaction score
728
First Language
English
Primarily Uses
RMVXA
a different approach
I do like this better. I had thought about it but I really haven't learned ruby enough to code yet.
However it does have an error.
A quick test and this works.
Code:
#------------------------------------------------------------------------------
# ** Game_Party class
#------------------------------------------------------------------------------
class Game_Party
  #----------------------------------------------------------------------------
  # * Clear Item Type
  #----------------------------------------------------------------------------
  def clear_item_type(container)
    container.each do |item|
      next if (item.is_a?(RPG::Item) && item.key_item?)
      gain_item(item, -item_number(item), true)
    end
  end # Clear Item Type
  #----------------------------------------------------------------------------
  # * Clear Items
  #----------------------------------------------------------------------------
  def clear_items
    clear_item_type($data_weapons)
    clear_item_type($data_armors)
    clear_item_type($data_items)
  end # Clear Items
end # end of Game_Party
 

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,425
Reaction score
602
First Language
Italian
Primarily Uses
RMVXA
@Roninator2 thank you for testing that out. It looks like $data_items (and $data_armors and $data_weapons as well) is an Array even if @items in the Game_Party class is a hash table. Once again, thank you for testing out the code.
 
Last edited:

nanakra

Villager
Member
Joined
Feb 5, 2015
Messages
8
Reaction score
2
First Language
English
Primarily Uses
RMVXA
Last edited:

kyonides

Reforged is laughable
Veteran
Joined
Nov 17, 2019
Messages
356
Reaction score
101
First Language
English
Primarily Uses
RMXP
Bah, there's a more convenient approach than those offered above.

Code:
class Game_Party
  def clear_common_items
    @items.delete_if{|item_id| !$data_items[item_id].key_item? }
    @weapons.delete_if{|wid| !$data_weapons[wid].key_item? }
    @armors.delete_if{|aid| !$data_armors[aid].key_item? }
  end
end

If @weapons or @armors had no way to include key items, you could just use...

Code:
@weapons.clear
@armors.clear

instead of the longer option I have provided above.

Why do I prefer my approach? Because you only test those keys found in your hashes instead of thousands of items, weapons and armors you might have included in your game's database.
 
Last edited:

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,425
Reaction score
602
First Language
Italian
Primarily Uses
RMVXA
EDIT: Never mind, I have just checked the gain_item method and it calls the delete method internally, making my solution unable to address the garbage collector issue as well. A proper solution would be not displaying items with a quantity of 0, but doing that required a complete change in how the engine handles items.

@kyonides it should be
Code:
class Game_Party
  def clear_common_items
   @items.delete_if{ |item_id| !$data_items[item_id].key_item? }
   @weapons.delete_if{ |wid| $data_weapons[wid].key_item? }
   @armors.delete_if{ |aid| $data_armors[aid].key_item? }
  end
end
 
Last edited:

Roninator2

Gamer
Veteran
Joined
May 22, 2016
Messages
3,210
Reaction score
728
First Language
English
Primarily Uses
RMVXA

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,425
Reaction score
602
First Language
Italian
Primarily Uses
RMVXA
@TheoAllen it is a bit tricky, basically ruby GC should theoretically release allocated memory automatically, but, unfortunately, that much does not happen as often as required, leading to increased memory usage over time. There is no need for a memory leak, this is just how ruby works. Of course, there are ways to address something like this, but not all of them are easily accessible to RPG Maker users.

The easiest one is probably to have the GC handle as little dynamic memory as possible, minimizing the amount of wasted memory. A good solution in this situation would be setting the number of owned items of a certain type to 0 and then only show those with a quantity higher than 0 in the inventory. This way there is no need to delete pairs from the hash table and there is no need to rely on the garbage collector to release that memory. After all the maximum amount of different items that the hash can store is well known (the total amount of items in the database), there is no way that you can go higher than that.

EDIT
In the first example, where the whole hash table was cleared using
Code:
hash_table = {}
the result is that your memory is full of arrays (hash key/item pairs are arrays) and you have to hope that the garbage collector clears them all....which might take quite a long time.

Clearing items one by one is not ideal either though, and I edited my post above to mention that, as the gain_item method simply removes the key/item pair from the hash table, leaving that array in your memory to wait until the garbage collector decides to do its work.

Something has been done in later versions of ruby to address this problem (2.2 if I am not wrong and something is being done for ruby 2.7), but RGSS uses ruby 1.9.2, which still has a lot of problems with that.

EDIT 2
Keep in mind that, since it is not a memory leak, unused memory does get released at some point, the problem is when and how. When it happens you might have a lot of allocated memory for no real purpose. The sooner you reach that point, the earlier the garbage collector has to run more frequently to clear it. And scanning your whole memory is not exactly "fast", the lesser you do it, the better.

EDIT 3
If you are interested you can read something about this here. As you can see, the amount of wasted memory can be more than 30 times the amount of real memory used, making it quite a big issue.

@Roninator2 thank you for testing the code, unfortunately, as stated in my previous post (after editing it), I have realized that the gain_item method calls the delete method internally, making it the same as kyonides solution. That being the case, his solution is shorter to write so it is better. Unless the OP wants to change how the engine handles items completely, addressing the issue with the garbage collector, there is no other way to do that.
 
Last edited:

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
6,314
Reaction score
7,844
First Language
Indonesian
Primarily Uses
RMVXA
@Heirukichi while I'm a fan of optimization, is there a real impact if the allocated memory (in this case, a hash table) is not released (properly)? I know if you have undisposed sprite while it loses its reference could lead to RGSS Stopped working, but would a mere hash table lead to some problematic things in RGSS3/RPG Maker VX Ace scope?
 

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,425
Reaction score
602
First Language
Italian
Primarily Uses
RMVXA
@TheoAllen it depends on how many times it is not released properly, of course. If it is just once, I doubt that it is going to have any real impact. If it happens more than once and the amount of memory to scan when garbage collecting increases, you might experience lag spikes in the process. The higher the amount of wasted memory, the more often you have to scan to find potential free spots.

With lag spikes I mean literally lag spikes, not a constant FPS drop, just a temporary drop in your frame rate when running the garbage collector. Nothing too annoying, unless it happens too often.
 

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
6,314
Reaction score
7,844
First Language
Indonesian
Primarily Uses
RMVXA
@Heirukichi in a sense, if the OP uses the "less optimized" way, as long as they don't use it too often, it won't create lag spikes/frameskip? Have you confirmed that it is actually happening and become an annoyance? Should you worry much if you often use hash.clear or array.clear too often would create a lag spike? Any known limit at how it's going to happen? (i.e, RM started to get frame drops if you put like 100 events in map or so)
 

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,425
Reaction score
602
First Language
Italian
Primarily Uses
RMVXA
@TheoAllen I have experienced something like that on a slower machine (AMD A10 CPU), however, it is very hard to tell you how often it happens because it also depends on other factors, not just that method. Each custom script and each tiny bit of code contributes to increase the size of this problem. Using hash.clear or array.clear is not the cause of the problem, it just adds up to an existing problem, making it more noticeable (or still not noticeable at all, depending on the machine; modern gaming computers with fast CPU should be able to handle that in an unnoticeable number of frames).

As an example, one of the machines I work with often experiences lag-spikes, another one, with a much more powerful CPU, has no lag-spike at all, no matter what you throw at it. It is very hard to tell you when and where you are going to pay the price for excessive memory usage.

EDIT
Should you worry much if you often use hash.clear or array.clear too often would create a lag spike?
This also depends on the amount of memory that your game needs and how the code is written. In general, as long as the cost (in terms of planning and writing the code) is not that different from that of using a less efficient solution, why not?
 
Last edited:

kyonides

Reforged is laughable
Veteran
Joined
Nov 17, 2019
Messages
356
Reaction score
101
First Language
English
Primarily Uses
RMXP
Come on! We're talking about a hash that only includes integers! Their memory allocation is minimal! If we were handling sprites (nah!) or bitmaps ( :S ) then we'd be taking it seriously. We can safely clear an items or weapons or armors hash stored in $game_party! Actually it'd be faster for everyone if we get rid of zero valued keys like 1 => 0 (0 Potions) because the smaller the hash gets, the faster it will look for a given key.

In Ruby 1.8 and 1.9, hashes store keys with no clear order. Later versions of Ruby implemented hashes as a double array that handles an array for keys and another one for their respective values, both placed in the same position.

So if any user needs to draw n amount of items and weapons and armors, it's better to clear the hashes to prevent the game from creating too many and unnecessary sprites with their respective bitmaps. :S
 

Heirukichi

Veteran
Veteran
Joined
Sep 24, 2015
Messages
1,425
Reaction score
602
First Language
Italian
Primarily Uses
RMVXA
So if any user needs to draw n amount of items and weapons and armors, it's better to clear the hashes to prevent the game from creating too many and unnecessary sprites with their respective bitmaps.
That much if obvious, and is one of the reasons why I mentioned that, in order to be completely efficient, a change in the menu is required as well.
 
Last edited:

Latest Threads

Latest Profile Posts

Happy Friday, y'all! I just got home from work and am sitting down with a nice cider, and I'm ready to chill and enjoy myself. Not sure if I'm gonna dive into any of my game-related projects or not tonight.... we'll see how I feel after unwinding for a bit I guess!
Just found out that mint tea made from chocolate mint tastes a bit like hot cocoa with candy cane stirred in. As I'm allergic to chocolate this makes me very happy.
It's special day for me tomorrow so time to vanish for 24 hours lol.
So Deltarune Chapter 2 is supposed to release today... if it's out already, has anyone played it? And I can't because I have a stinking Mac and not a Windows PC.

Forum statistics

Threads
115,138
Messages
1,087,540
Members
149,646
Latest member
Kamikayson
Top