[Resolved][XP] Status Effect Window Implementation

Started by Jaiden, October 25, 2017, 08:38:31 pm

Previous topic - Next topic

Jaiden

October 25, 2017, 08:38:31 pm Last Edit: October 26, 2017, 12:23:30 pm by BoisterousHero
I'm hoping someone can help me with writing a script. I'm not really looking for free code as much as I'm looking for assistance figuring out how to implement something, so I can learn how to code better.

Right now I have a custom status menu with a standard help window. The user can select and scroll through the list of stats to see a description of what each one does (Though it's kind of broken, see below).

I now want to create a window that displays the actors current status effects (states) and populates information to the help window about each state. I understand I'll need a custom array that associates each state with a description, as RPG Maker XP does not provide state descriptions by default. I am using Blizz's states as icons scripts, if that helps.

I actually already have the framework for the window (I know how to create the window, make it active/inactive, set the index, the screenshot below is all in-game with the exception of the white text/icons), but I'm not entirely sure what the best way to draw each state and its associated icon on the list and assure it is properly selected and populated into the help window.

Here is a screenshot example:
Spoiler: ShowHide


Bonus question:
For some reason, my stats window isn't working properly. The first item on the list is selected properly, but nothing happens when I scroll (the index doesn't change?). Is it because I need to explicitly set the "commands"? In this case, I would happy to accept help, but I feel like I really need to figure it out on my own.

Here is the code:
class Window_Stats < Window_Selectable

include CMS_Config

  #--------------------------------------------------------------------------
  # * Object Initialization
  #     actor : actor
  #--------------------------------------------------------------------------
  def initialize(actor)
super(0, 0, 152, 246)
self.contents = Bitmap.new(width - 32, height - 32)
@item_max = 8
@column_max = 1
@actor = actor
self.z += 10
self.active = false
self.index = -1
refresh
  end
 
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
 
  def refresh
self.contents.clear
for i in 0...7
draw_actor_parameter(@actor, 0, i*32, i)
end
update_cursor_rect
  end

  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    super
      #update cursor rectangle
  update_cursor_rect
  end

    # Update cursor rectangle
      def update_cursor_rect
if @index < 0
self.cursor_rect.empty
else
# Get current row
row = @index / @column_max
# If current row is before top row
if row < self.top_row
# Scroll so that current row becomes top row
self.top_row = row
end
# If current row is more to back than back row
if row > self.top_row + (self.page_row_max - 1)
# Scroll so that current row becomes back row
self.top_row = row - (self.page_row_max - 1)
end
# Calculate cursor width
cursor_width = self.width / @column_max - 16
# Calculate cursor coordinates
x = 4
y = @index * 32
# Update cursor rectangle
self.cursor_rect.set(x, y, cursor_width, 32)
end
end

 
  #--------------------------------------------------------------------------
  # * Help Text Update
  #--------------------------------------------------------------------------

  def update_help
@help_window.set_text(self.index < 0 ? "" : STAT_DESCRIPTIONS[@index], 0)
  end
 
  #--------------------------------------------------------------------------
  # * Draw Parameters
  #     actor : actor
  #     x     : draw spot x-coordinate
  #     y     : draw spot y-coordinate
  #     type  : parameter type (0-6)
  #--------------------------------------------------------------------------
  def draw_actor_parameter(actor, x, y, type)
    case type
    when 0
      parameter_name = $data_system.words.atk
      parameter_value = actor.atk
    when 1
      parameter_name = $data_system.words.pdef
      parameter_value = actor.pdef
    when 2
      parameter_name = $data_system.words.mdef
      parameter_value = actor.mdef
    when 3
      parameter_name = $data_system.words.str
      parameter_value = actor.str
    when 4
      parameter_name = $data_system.words.dex
      parameter_value = actor.dex
    when 5
      parameter_name = $data_system.words.agi
      parameter_value = actor.agi
    when 6
      parameter_name = $data_system.words.int
      parameter_value = actor.int
    end
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 80, 32, parameter_name)
    self.contents.font.color = normal_color
    self.contents.draw_text(x + 80, y, 36, 32, parameter_value.to_s, 2)
  end

end


Thanks everyone!

KK20

You will need to make another configuration where the status ID is associated with a icon graphic file. You can do something similar to Window_Base#draw_item_name or Window_Skill#draw_item.

# In your configuration module...

def self.status_icons(id)
  return case id
    when 1 then '001-Weapon01'
    when 2 then 'anothericon'
  else
    nil
  end
end


Not sure by what you mean with the cursor being wrong. It was scrolling when I tried it (the cursor rect was drawn in wrong places as I moved it down though).

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!

Jaiden

Thanks for the response! I was thinking something along those lines, I'll give it a try and see how it goes.

QuoteNot sure by what you mean with the cursor being wrong. It was scrolling when I tried it (the cursor rect was drawn in wrong places as I moved it down though).


This was exactly the hint I needed, thanks! I had the index being set to 0 on the update method, d'oh!

Jaiden

I've made some progress, but I've hit a bit of a wall trying to figure out the logic behind drawing the help text.

I am trying to store the descriptions for each status into an array, but it isn't working too well. Everything else works (scrolling through the list, etc). I think my lack of Ruby fundementals is crippling me here, because there is probably a simple way to do it.

Any hints/suggestions would be awesome.

Here is screenshot of the progress:
Spoiler: ShowHide


And the class:
class Window_Effects < Window_Selectable

include SPEC_INFO

  #--------------------------------------------------------------------------
  # * Object Initialization
  #     actor : actor
  #--------------------------------------------------------------------------
 
  def initialize(actor)
super(0, 0, 194, 416)
self.contents = Bitmap.new(width - 32, height - 32)
@actor = actor
@column_max = 1
self.z += 10
self.active = false
self.index = -1
refresh
  end
 
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
 
  def refresh
self.contents.clear
# Get actor's current states to determine maximum items in the list
states = @actor.states.find_all {|id| $data_states[id].rating > 0}
@item_max = states.count

# Draw actor states + icons on each line
for i in 0...states.count
draw_actor_state(@actor, x, y + i*30, i)
end

    end
   
   def update_cursor_rect
if @index < 0
    self.cursor_rect.empty
else
# Calculate cursor width
cursor_width = self.width / @column_max - 32
# Calculate cursor coordinates
x = 0
y = @index * 30
# Update cursor rectangle
self.cursor_rect.set(x, y, cursor_width, 32)
end
end
   
def draw_actor_state (actor, x, y, state)
if actor != nil
s = actor.states.find_all {|id| $data_states[id].rating > 0}
icon = RPG::Cache.icon("State/#{$data_states[s[state]].name}")
self.contents.blt(x + 4, y + 4, icon, Rect.new(0, 0, 24, 24))
self.contents.draw_text(x + 32, y, 100, 32, "#{$data_states[s[state]].name}")
end
end
 
   
  #--------------------------------------------------------------------------
  # * Help Text Update
  #--------------------------------------------------------------------------

  def update_help
#s = @actor.states.find_all {|id| $data_states[id].rating > 0}
#@help_window.set_text(self.index < 0 ? "" : STATE_DESCRIPTIONS[s[@index]], 0)
  end
 
end


I've commented out the obviously incorrect code. I figured I would create an array that associates each state ID with a description, like so:
  #This is an array containing descriptions for particular status effects
  #Each index applies to states as listed in the database
  STATE_DESCRIPTIONS = [
  "Should be knockout",
  "Should be stun",
  "Should be venom",
  "Should be dazzle",
  ""]


But I imagine there may be a better way.

KK20

I'd first modify your window methods to these:

def draw_actor_state (actor, x, y, state)
  if actor != nil
    icon = RPG::Cache.icon("State/#{state.name}")
    self.contents.blt(x + 4, y + 4, icon, Rect.new(0, 0, 24, 24))
    self.contents.draw_text(x + 32, y, 100, 32, state.name)
  end
end

def refresh
  self.contents.clear
  # Get actor's current states to determine maximum items in the list
  @states = @actor.states.find_all {|id| $data_states[id].rating > 0}
  @item_max = @states.count
 
  # Draw actor states + icons on each line
  for i in 0...@states.count
    draw_actor_state(@actor, x, y + i*30, $data_states[@states[i]])
  end
end

def update_help
  id = @states[self.index]
  @help_window.set_text(self.index < 0 ? '' : state_description(id))
end

I'm assuming SPEC_INFO is a module, so you can add this method to it:

module SPEC_INFO
  def state_description(state_id)
    case state_id
    when 1 then 'The actor is dead. You must revive him.'
    when 2 then 'The actor is shocked at the enemy\'s mad skills.'
    #... add more
    else ''
    end
  end
end


Rather then having to filter through the actor's states every time in your methods, do it once and have the window keep track of it with a variable (in this case, @states). You can then reference the states array and access the state ID you need through the window's cursor index. Other windows do this too, like Window_Item.

Also are you using Gemini to edit your script? The tab formatting is wonky as hell.

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!

Jaiden

Awesome, thank you! That's super helpful. Not sure why I forgot about variable scope ._.

Yes, SPEC_INFO is a module, so that is perfect.

QuoteAlso are you using Gemini to edit your script? The tab formatting is wonky as hell.

I am using Notepad++, and then copying/pasting back and forth from RPG maker. It's doing horrible things to my tabs and I'm not keeping up with fixing them. Quite convoluted, I should probably look into setting up a formal IDE and using it with RPG Maker but I keep putting it off.

KK20


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!

Jaiden

Quote from: KK20 on October 26, 2017, 11:50:46 am
At the very least, give my script a try: http://forum.chaos-project.com/index.php/topic,15072.0.html

Indeed, I was actually looking at this earlier today, so I certainly will.

Thanks again for your help, this menu is killer now!
Spoiler: ShowHide