Class-Actor-Skill Hybrid?

Started by shintashi, October 06, 2011, 09:46:57 pm

Previous topic - Next topic

KK20

October 11, 2011, 05:46:41 pm #20 Last Edit: October 11, 2011, 05:51:03 pm by KK20
Haha oh no. 'def setup_techniques' isn't another method; it's an alias for 'def setup'. What I meant as a placeholder was this:
alias setup_techniques setup
def setup(actor_id)
  setup_techniques(actor_id) # Actor.setup(actor_id)
  # This was where I was gonna edit/add stuff, inside this area. Right here where this comment is at.
end
Unless you actually deleted 'alias setup_techniques setup' and 'def setup' in class Game_Actor, your fix will cause an error for setting up your game actors.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

shintashi

October 11, 2011, 06:03:26 pm #21 Last Edit: October 11, 2011, 06:05:34 pm by shintashi
Ahh, that makes more sense then. it seemed like it was just hanging out, and when I moved it into Game Actor, it didn't seem to have a place.

meanwhile, I ran into a serious problem with equipping characters:

$data_classes[i].weapon_set.push(1)

is based on classes. So if I had two fighters, and one had gained sword access, the other would also have sword access.

Quote
module RPG
 class Class
   def initialize
     @id = 0
     @name = ""
     @position = 0
    @weapon_set = []
     @armor_set = []
     @element_ranks = Table.new(1)
     @state_ranks = Table.new(1)
     @learnings = []
   end
   attr_accessor :id
   attr_accessor :name
   attr_accessor :position
   attr_accessor :weapon_set
   attr_accessor :armor_set
   attr_accessor :element_ranks
   attr_accessor :state_ranks
   attr_accessor :learnings
 end
end


Since the purpose of techniques is to more or less create custom classes from within the actor, changing classes shouldn't be the way to do it. Instead I need to find a way to tell the computer "if is actor" to skip the regular class $data_classes[ i ].weapon_set and go to some 'new and improved' game_actor[ i ].weapon_set, which inherits all the base weapons from the actor's base class (which might be zero), but then has more (or less) of them.

is that even possible? And why do I feel like Alias is a way to do it?

KK20

Just make each actor be its own unique class? Or do you plan to still have the option to change classes?

Anyways, yes, you're right that if you push a weapon into the $data_classes, you affect EVERY instance of any actor that may be of that class type. If you want to make weapons actor-specific, there might be a script for that already. Otherwise, you will have to edit a portion of the other RMXP default scripts (like the Equip_Windows).

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

shintashi

October 11, 2011, 06:45:58 pm #23 Last Edit: October 11, 2011, 07:14:58 pm by shintashi
Quote from: KK20 on October 11, 2011, 06:27:30 pm
Just make each actor be its own unique class? Or do you plan to still have the option to change classes?

Anyways, yes, you're right that if you push a weapon into the $data_classes, you affect EVERY instance of any actor that may be of that class type. If you want to make weapons actor-specific, there might be a script for that already. Otherwise, you will have to edit a portion of the other RMXP default scripts (like the Equip_Windows).


so I added an attr_accessor for weapon set in game_actor, then made one of these:


 def weapon_set
 weapons = $data_classes[2].weapon_set
 return weapons
 end


And had an event display my actor's weapon_set, and it displayed the numbered array I expected, which is a good thing. Next, I think I need to change "classes[2]" to whatever my class is, then I can change these:


   if item.is_a?(RPG::Weapon)
     # If included among equippable weapons in current class
     if $data_classes[@class_id].weapon_set.include?(item.id)
       return true
     end
   end

...
   # Add equippable weapons
   if @equip_type == 0
     weapon_set = $data_classes[@actor.class_id].weapon_set
     for i in 1...$data_weapons.size
       if $game_party.weapon_number(i) > 0 and weapon_set.include?(i)
         @data.push($data_weapons[i])
       end
     end
   end


Edit:

Game_Actor

  def weapon_set
  weapons = $data_classes[self.class_id].weapon_set
  return weapons
  end




Game_Actor

   if item.is_a?(RPG::Weapon)
      # If included among equippable weapons in current class
      if @weapon_set.include?(item.id)
        return true
      end
    end

...

Window_EquipItem

if @equip_type == 0
      weapon_set = @actor.weapon_set
      for i in 1...$data_weapons.size
        if $game_party.weapon_number(i) > 0 and weapon_set.include?(i)
          @data.push($data_weapons[i])
        end
      end
    end


And I think that wraps up putting in the 'base' weapons, now I just need to figure out how to edit that list.

KK20

October 11, 2011, 07:16:06 pm #24 Last Edit: October 11, 2011, 07:35:43 pm by KK20
Got it:
Spoiler: ShowHide
class Game_Actor < Game_Battler
  attr_accessor :techniques
  attr_accessor :unique_weapon
  attr_accessor :unique_armor
 
  alias initialize_techniques initialize
  def initialize(actor_id)
    @techniques = []
    @unique_weapon = []
    @unique_armor = []
    initialize_techniques(actor_id)
  end
 
  alias call_actor_setup setup
  def setup(actor_id)
    call_actor_setup(actor_id)
    $data_classes[@class_id].weapon_set.each{|w|
      @unique_weapon.push(w)
    }
    $data_classes[@class_id].armor_set.each{|a|
      @unique_armor.push(a)
    }
  end
 
  # Adds the specified technique to the @techniques array
  def add_tech(tech_id)
    return if @techniques[tech_id] != nil # stops if tech is already possessed
    @techniques[tech_id] = Game_Technique.new(tech_id)
  end


  #--------------------------------------------------------------------------
  # * Determine if Equippable
  #     item : item
  #--------------------------------------------------------------------------
  def equippable?(item)
    # If weapon
    if item.is_a?(RPG::Weapon)
      # If included among equippable weapons in current class
      if @unique_weapon.include?(item.id)
        return true
      end
    end
    # If armor
    if item.is_a?(RPG::Armor)
      # If included among equippable armor in current class
      if @unique_armor.include?(item.id)
        return true
      end
    end
    return false
  end
 
end
#===============================================================================
# Modified Equip Window: Shows the proper equips actor can equip
#===============================================================================
class Window_EquipItem < Window_Selectable
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    @data = []
    # Add equippable weapons
    if @equip_type == 0
      weapon_set = @actor.unique_weapon
      for i in 1...$data_weapons.size
        if $game_party.weapon_number(i) > 0 and weapon_set.include?(i)
          @data.push($data_weapons[i])
        end
      end
    end
    # Add equippable armor
    if @equip_type != 0
      armor_set = @actor.unique_armor
      for i in 1...$data_armors.size
        if $game_party.armor_number(i) > 0 and armor_set.include?(i)
          if $data_armors[i].kind == @equip_type-1
            @data.push($data_armors[i])
          end
        end
      end
    end
    # Add blank page
    @data.push(nil)
    # Make a bit map and draw all items
    @item_max = @data.size
    self.contents = Bitmap.new(width - 32, row_max * 32)
    for i in 0...@item_max-1
      draw_item(i)
    end
  end
end
Tested it a bit. Seemed fine. Also possible to use $game_actors[id].unique_weapon.push(id) to add new items.

Edit: Ninja'd
Edit 2: Wait...you said you needed to find a way to add onto the base. In that case, no ninja. I've provided that.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

shintashi

Unique?  for now I was just trying to expand the existing array using something similar to your add_tech... and my version failed.


# * Custom Weapon Set
  #--------------------------------------------------------------------------
  def weapon_set
  weapons = $data_classes[self.class_id].weapon_set
  return weapons
  end

  #--------------------------------------------------------------------------
  # * Add Weapons *doesn't currently work*
  #--------------------------------------------------------------------------
  def add_weapon(weapon_id)
    return if @weapon_set[weapon_id] != nil
    @weapon_set.push[weapon_id]
  end


weapon_set by itself works, but I don't know how to add new weapons to that set. I modified this line:
 
@weapon_set[weapon_id] = weapon_set.new(weapon_id)


Because I couldn't get it to work, I think its because Game_Technique is its own class, and weapon_set isn't. I wanted to use something like it because your add_tech() thing kicks ass.

KK20

Through testing, I found out that even if you did something like @weapon_set = $data_classes[@class_id].weapon_set and then did @weapon_set.push(100), it would still push 100 as a usable weapon to any actor who shared the same class. As such, I only took the array values from $data_classes[@class_id].weapon_set by using a ".each{}" and stored those values into @unique_weapon. The reason I called it Unique is because only this specific actor has access to this list of weapons. When I did @unique_weapon.push(100)--along with all the modifications I added--only that specific actor was capable of equipping weapon 100. I even had other party members who were the same class and they couldn't equip weapon 100.

Just use my add-on I wrote, and then press CTRL+H to change the names of 'unique_weapon' and 'unique_armor' to whatever you want it to be (I'm guessing 'weapon_set' and 'armor_set').

If you want to make a custom method to add weapons/armors that don't duplicate, do something like:
def add_weapon(id)
    return if @unique_weapon.include?(id)
    @unique_weapon.push(id)
    @unique_weapon.sort!
  end

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

shintashi

I was impressed  8)

I used your thingymabob w/minimal changes and it worked:


  #--------------------------------------------------------------------------
  # * Add Weapons
  #--------------------------------------------------------------------------
  def add_weapon(weapon_id)
    return if @weapon_set.include?(weapon_id)
    @weapon_set.push(weapon_id)
    @weapon_set.sort!
  end



ForeverZer0

You need to initialize it as a clone of $data_whatever, and it will not add to every actor of the same class.
So, instead of doing something like this:

@unique_weapons = []
$data_weapons.each {|w| @unique_weapons.push(w) }


You can simply initialize is it for each actor like this:

@unique_weapons = $data_weapons.clone

I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

shintashi

October 12, 2011, 12:46:12 pm #29 Last Edit: October 12, 2011, 12:54:20 pm by shintashi
Quote from: ForeverZer0 on October 11, 2011, 08:54:46 pm
You need to initialize it as a clone of $data_whatever, and it will not add to every actor of the same class.
So, instead of doing something like this:

@unique_weapons = []
$data_weapons.each {|w| @unique_weapons.push(w) }


You can simply initialize is it for each actor like this:

@unique_weapons = $data_weapons.clone



I don't understand how you got that to work, but

You illustrate a solid point - I just checked and when I have actors of the same class, and give an actor a new weapon, all other actors of that class get the weapon. This makes absolutely no sense to me, since the weapon should be added to an actor's file, not the class file. I don't understand why this is.

starting off with checking two characters of the same class:

p $game_actors[2].weapon_set



p $game_actors[3].weapon_set


and then doing this:


$game_actors[2].add_weapon(35)


Should not have any effect on the weapon_set of actor 3, but it does.

ForeverZer0

You're saying it still adds to both when you do the clone method?
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

KK20

@weapon_set = $data_classes[@class_id].weapon_set.clone
It looks like this, right? I just did that right now and it worked.

Thanks for that 'clone' tip. It actually helped me out with my current project. :P

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

shintashi

Quote from: KK20 on October 12, 2011, 02:06:21 pm
@weapon_set = $data_classes[@class_id].weapon_set.clone
It looks like this, right? I just did that right now and it worked.

Thanks for that 'clone' tip. It actually helped me out with my current project. :P


Ahah!

what I was doing was this

    @weapon_set = $data_classes[self.class_id].weapon_set.clone


instead of this

    @weapon_set = $data_classes[@class_id].weapon_set.clone


and so whenever i tested it, neither actor equipment changed upon adding.

then I tried this

@weapon_set = $data_weapons.clone

and that didn't work out too well at all.

KK20

Really? That first line (self.class_id) shouldn't have done anything. Just tested it--no errors.
And the $data_weapons was just an example, not a fix for the script. $data_weapons is something completely different.

Will be gone for a few hours. Try and find a list of what you want done next when I get back; I'm bored.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

shintashi

ok so I got to sticking the weapons into the actor list based on their techniques,  and this is what I've got:


  #--------------------------------------------------------------------------
  # * Add Techniques
  #--------------------------------------------------------------------------
  def add_tech(tech_id)
    return if @techniques[tech_id] != nil # stops if tech is already possessed
    @techniques[tech_id] = Game_Technique.new(tech_id)
    my_id = tech_id
    weapon_tech(my_id) #this is new
  end
  #--------------------------------------------------------------------------
  # * Custom Weapon Set - technique interface w/ add weapon
  #--------------------------------------------------------------------------
  def weapon_tech(var)
   m = @techniques[var].skills
    if m.include?(6)
      a =  $data_skills[6].str_f
      z =  $data_skills[6].dex_f
          (a..z).step(1) do |n|
        add_weapon(n)
        end
     
    else
      return
   end
  end


Here's how it works:
When a character receives a new technique, the computer checks if that technique comes with weapon proficiencies like swords.

The way I created weapon proficiencies is by creating skills titled stuff like "swords", "axes", "guns", etc. And then exploited the str_f (starting number) and dex_f (end number) to get my number range. The number range is a section of the weapon list. For example, swords might be 1-4, spears 5-8, and axes 9-12. So if my skill was called Swords, I would set str_f to 1, and dex_f to 4, and then my script:


      a =  $data_skills[6].str_f
      z =  $data_skills[6].dex_f
          (a..z).step(1) do |n|
        add_weapon(n)
        end


adds each of these weapons. What I need to know how to do is change that "6", in here:


    if m.include?(6)
      a =  $data_skills[6].str_f
      z =  $data_skills[6].dex_f


into some kind of variable like "i", so it can check not just for skill #6 (which is only swords), but a short list of skills, like 6,7,8,9,10, and maybe some stuff out of order that might come later, like 62 (giant robot weapons?), 63 (joke weapons?), and so on. I just don't know how to turn


if m.include?(6)
      a =  $data_skills[6].str_f
      z =  $data_skills[6].dex_f


into something like


if m.include?([6,7,8,9,10,11,62,63])
      a =  $data_skills[[6,7,8,9,10,11,62,63]].str_f
      z =  $data_skills[[6,7,8,9,10,11,62,63]].dex_f


KK20

Loops. 'nuff said.
Spoiler: ShowHide
  #--------------------------------------------------------------------------
  # * Add Techniques
  #--------------------------------------------------------------------------
  def add_tech(tech_id)
    return if @techniques[tech_id] != nil # stops if tech is already possessed
    @techniques[tech_id] = Game_Technique.new(tech_id)
    weapon_tech(tech_id)
  end
  #--------------------------------------------------------------------------
  # * Custom Weapon Set - technique interface w/ add weapon
  #--------------------------------------------------------------------------
  def weapon_tech(id)
    skills = @techniques[id].skills
    skills.each{|s|
      if [6,7,8,9,10,11,62,63].include?(s)
        a =  $data_skills[s].str_f
        z =  $data_skills[s].dex_f
        for n in a..z
          add_weapon(n)
        end
      end
    }
    p(@weapon_set)
  end
For your array of [6,7,8,9,10,11,62,63], I'm hoping you make that more user-friendly. Unless this script is solely yours...in that case, knock yourself out.

Other Projects
RPG Maker XP Ace  Upgrade RMXP to RMVXA performance!
XPA Tilemap  Tilemap rewrite with many features, including custom resolution!

Nintendo Switch Friend Code: 8310-1917-5318
Discord: KK20 Tyler#8901

Join the CP Discord Server!

shintashi

I originally intended on only having a handful of weapon ranges, and tossed in the ones in the 60s for good measure, in case I added new ones.

I originally thought of making "classes" for the sole purpose of ripping off their weapon sets.

My next task is getting the levels of techniques to count toward attack bonuses. So if you have a level 30 sword, that's +30 to hit. Once "sword" works, I can start proof checking some other aspects, like "swords/level", which turns into "spells/level", since I don't want level 1 characters summoning "bahamut" and casting "meteo", in FF terms.

shintashi

ok, so I've got these techniques that allow me to use weapons, but the techniques also have levels. What I would like to do, is something like the following pseudocode in the Game Battler:


#if using Swords... get technique level
If: wielding $data_weapons[1..4]
Check if @actor.techniques[var].skills[var] includes "6"
If true
attack_skill = @actor.techniques[var].level
else
attack_skill = 0
end

#if using Spears... get technique level
If: wielding $data_weapons[5..8]
Check if @actor.techniques[var].skills[var] includes "7"
If true
attack_skill = @actor.techniques[var].level
else
attack_skill = 0
end

#if using Axes... get technique level
If: wielding $data_weapons[5..8]
Check if @actor.techniques[var].skills[var] includes "9"
If true
attack_skill = @actor.techniques[var].level
else
attack_skill = 0
end


Basically, if I have a Technique that teaches some weapons,

and I'm attacking,

The computer checks my current equipped weapon id,

and then compares that with a small table of weapons:

[weapon id's][skill id]
[1-4]..........[6]
[5-8]..........[7]
[11-12].......[8]
[13-16].......[9]
[17-20].......[10]
[21-24].......[11]

alternatively, I realized that if you have a given weapon id, you probably have the skill related,
so what we really need to do is check to see which technique you have that has the skill id in it's array.

and most importantly, if you have more than one techniques with the same skill id (like 6 for swords),
then stick these technique.levels in an array, sort, and use the highest level.

This somehow seems easier...  :???:

shintashi

This is what I've got so far,


for i in 0.. @actor.techniques.size
a = @actor.techniques[i].skills
if a.include?(6)
sword_skills <<  @actor.techniques[i].level
else
return
end
end


and then I need some kind of sort 'sword_skills' array, which can then be sorted, and then the highest number becomes attack_skill.  :D

shintashi

October 23, 2011, 07:04:31 pm #39 Last Edit: October 23, 2011, 07:19:51 pm by shintashi
well I've messed with it some more, and as usual, ran into some nil errors:


 #--------------------------------------------------------------------------
 # * Get Hit Rate
 #--------------------------------------------------------------------------
 def hit
    if self.is_a?(Game_Actor)
      sword_skills = [] # blank array
      if self.techniques.size == 0
        sword_skills << 0
      else
       for i in 0.. self.techniques.size
          a = self.techniques[i].skills
          p a
          if a.include?(6)
            sword_skills << self.techniques[i].level
          else
            return
          end
        end
      end
     
    n = 1 + sword_skills.max
   #n = 100
   #p self.techniques #works
   else  
   n = 100
   end
   for i in @states
     n *= $data_states[i].hit_rate / 100.0
   end
   return Integer(n)
 end


basically the line it dies on is

 
         a = self.techniques[i].skills


which is odd because I can usually get self.techniques[0,1,2,3..].skills or whatever to print.

edit: I've been getting weird results lately:

like "p self.techniques.size" spitting out 3 or 5 when my actor only has 1 technique.