O TEMA DO FÓRUM ESTÁ EM MANUTENÇÃO. FEEDBACKS AQUI: ACESSAR

Scene_Expertise 0.1

Iniciado por Corvo, 13/01/2019 às 09:05

13/01/2019 às 09:05 Última edição: 14/01/2019 às 18:09 por Corvo
Scene_Expertise


Condições de Uso:
Livre para membros registrados em centrorpg.com.


Descrição:
Como diz este pedido, o script adiciona uma nova cena e novos atributos aos personagens que podem ser usados tanto fora quanto dentro das batalhas. No momento, o script só suporta o uso de um único personagem e os atributos são atualizados com as variáveis de seu respectivo ID.


[box class=errorbox]Nota:
O código ainda está um pouco bagunçado, a configuração está horrível, mas já é funcional. Só estou disponibilizando como está para o caso de nosso amigo do pedido acima ter pressa. Com o tempo vou arrumando as coisas.[/box]


Instruções
O código ficou um pouco chato de configurar, então recomendo fortemente que os interessados tenham alguma noção de Ruby. Agora, vamos por partes. Primeiro, para alterar o nome da opção que irá aparecer no menu, troque o texto da linha 180 pelo que preferir:

def self.expertise;     return "Expertises";   end


A configuração dos parâmetros deve ser feita em partes. Primeiro, no topo do script, você encontra a lista de novos parâmetros:

  def p_8;  param(8);   end    # Parâmetro 8
  def p_9;  param(9);   end    # Parâmetro 9
  def p_10;  param(10);   end    # Parâmetro 10
  def p_11;  param(11);   end    # Parâmetro 11
  def p_12;  param(12);   end    # Parâmetro 12


Os números entre parêntesis são suas respectivas IDs e também as IDs das variáveis que terão o valor dos mesmos. p_n é a abreviação do nome do parâmetro e você pode alterá-lo para algo mais explícito. Por exemplo:

def agr;  param(9);   end    # Agarrar

O objetivo é que facilite seu entendimento ao usar os parâmetros nas fórmulas de dano:

a.atk + a.agr - b.def

Entretanto você também pode usá-los como estão:

a.atk + a.p_9 - b.def


Terminada a lista, o próximo passo é definir os nomes dos parâmetros da forma como serão exibidos ao jogador. Se você já trocou o nome da opção como dito acima, não preciso detalhar esta parte. O método está na linha 71.

  def get_param_name(param_id)
    if param_id = 8
      return "param(8)"
    elsif param_id = 9
      return "param(9)"
    elsif param_id = 10
      return "param(10)"
    elsif param_id = 11
      return "param(11)"
    elsif param_id = 12
      return "param(12)"
    end
  end


Depois, na linha 136, basta desenhá-los na tela. É preciso explicar esta parte, pois depende do número de parâmetros que você quer adicionar.

  def draw_expertises_list(x, y)
    draw_actor_param(@actor, x, y + line_height, 8)
    draw_actor_param(@actor, x, y + line_height * 2, 9)
    draw_actor_param(@actor, x, y + line_height * 3, 10)
    draw_actor_param(@actor, x, y + line_height * 4, 11)
    draw_actor_param(@actor, x, y + line_height * 5, 12)
  end

Sendo que  o comando é o seguinte:

draw_actor_param(@actor, x, y + line_height * n, param_id)

Copie e cole tudo, alterando somente:
n = Número da linha. Remova '* n' caso seja a primeira linha da cena.
param_id = ID do parâmetro configurado no início do script.



Imagens:
Opção no Menu
[close]
Cena
[close]


Código:
#==============================================================================
# ** Scene_Expertise
#------------------------------------------------------------------------------
#  Esta classe cria uma cena para atributos extras.
#==============================================================================


#==============================================================================
# ** Game_BattlerBase
#------------------------------------------------------------------------------
#  Esta classe gerencia os battlers. Contém os principais método de
# cálculo da características especiais.
# Esta classe é usada como superclasse da classe Game_Battler.
#==============================================================================
class Game_BattlerBase
  #--------------------------------------------------------------------------
  # * Aquisição dos parametros
  #--------------------------------------------------------------------------
  def p_8;  param(8);   end    # Parâmetro 8
  def p_9;  param(9);   end    # Parâmetro 9
  def p_10;  param(10);   end    # Parâmetro 10
  def p_11;  param(11);   end    # Parâmetro 11
  def p_12;  param(12);   end    # Parâmetro 12
    
  #--------------------------------------------------------------------------
  # * Aquisição do parâmetro base
  #     param_id : ID do parâmetro
  #--------------------------------------------------------------------------
  def param(param_id)
    if param_id < 8
      value = param_base(param_id) + param_plus(param_id)
      value *= param_rate(param_id) * param_buff_rate(param_id)
      [[value, param_max(param_id)].min, param_min(param_id)].max.to_i
    else
      value = $game_variables[param_id]
    end
  end
end

#==============================================================================
# ** Window_Expertise
#------------------------------------------------------------------------------
#  Esta janela exibe as especificações completas na janela de atributos.
#==============================================================================

class Window_Expertise < Window_Selectable
  #--------------------------------------------------------------------------
  # * Inicialização do objeto
  #     actor : herói
  #--------------------------------------------------------------------------
  def initialize(actor)
    super(0, 0, Graphics.width * 0.6, Graphics.height)
    @actor = actor
    refresh
    activate
  end
  #--------------------------------------------------------------------------
  # * Definição dos nomes dos Parâmetros
  #     param_id : Parâmetro
  #--------------------------------------------------------------------------
  def draw_actor_param(actor, x, y, param_id)
    if param_id < 8
      change_color(system_color)
      draw_text(x, y, 120, line_height, Vocab::param(param_id))
      change_color(normal_color)
      draw_text(x + 120, y, 36, line_height, actor.param(param_id), 2)
    else
      change_color(system_color)
      draw_text(x, y, 120, line_height, get_param_name(param_id))
      change_color(normal_color)
      draw_text(x + 120, y, 36, line_height, actor.param(param_id), 2)
    end
  end
  #--------------------------------------------------------------------------
  # * Definição do nome dos Parâmetros
  #     param_id : parâmetro
  #--------------------------------------------------------------------------
  def get_param_name(param_id)
    if param_id == 8
      return "param(8)"
    elsif param_id == 9
      return "param(9)"
    elsif param_id == 10
      return "param(10)"
    elsif param_id == 11
      return "param(11)"
    elsif param_id == 12
      return "param(12)"
    end
  end
  #--------------------------------------------------------------------------
  # * Definição de herói
  #     actor : herói
  #--------------------------------------------------------------------------
  def actor=(actor)
    return if @actor == actor
    @actor = actor
    refresh
  end
  #--------------------------------------------------------------------------
  # * Renovação
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    draw_header(line_height * 0)
    draw_horz_line(line_height * 1)
    draw_expertises(line_height * 2)
  end
  #--------------------------------------------------------------------------
  # * Desenho do bloco 1
  #     y : coordenada Y
  #--------------------------------------------------------------------------
  def draw_header(y)
    draw_actor_name(@actor, 4, y)
    draw_actor_class(@actor, 128, y)
    draw_actor_nickname(@actor, 288, y)
  end  
  #--------------------------------------------------------------------------
  # * Desenho do bloco 3
  #     y : coordenada Y
  #--------------------------------------------------------------------------
  def draw_expertises(y)
    draw_expertises_list(32, y)
  end
  #--------------------------------------------------------------------------
  # * Desenho de uma linha horzontal
  #--------------------------------------------------------------------------
  def draw_horz_line(y)
    line_y = y + line_height / 2 - 1
    contents.fill_rect(0, line_y, contents_width, 2, line_color)
  end
  #--------------------------------------------------------------------------
  # * Aquisção da cor da linha horizontal
  #--------------------------------------------------------------------------
  def line_color
    color = normal_color
    color.alpha = 48
    color
  end
  #--------------------------------------------------------------------------
  # * Draw Expertise List
  #--------------------------------------------------------------------------
  def draw_expertises_list(x, y)
    draw_actor_param(@actor, x, y + line_height, 8)
    draw_actor_param(@actor, x, y + line_height * 2, 9)
    draw_actor_param(@actor, x, y + line_height * 3, 10)
    draw_actor_param(@actor, x, y + line_height * 4, 11)
    draw_actor_param(@actor, x, y + line_height * 5, 12)
  end
end
#==============================================================================
# ** Scene_Expertise
#------------------------------------------------------------------------------
#  Esta classe executa o processamento da tela de perícias.
#==============================================================================

class Scene_Expertise < Scene_MenuBase
  #--------------------------------------------------------------------------
  # * Inicialização do processo
  #--------------------------------------------------------------------------
  def start
    super
    @status_window = Window_Expertise.new(@actor)
    @status_window.set_handler(:cancel,   method(:return_scene))
    @status_window.set_handler(:pagedown, method(:next_actor))
    @status_window.set_handler(:pageup,   method(:prev_actor))
  end
  #--------------------------------------------------------------------------
  # * Processo da mudança de herói
  #--------------------------------------------------------------------------
  def on_actor_change
    @expertise_window.actor = @actor
    @expertise_window.activate
  end
end

#==============================================================================
# ** Vocab
#------------------------------------------------------------------------------
#  Este modulo define os termos e mensagens. Ele define algumas informação
# como variáveis constantes. Termos da base de dados são obtidos utilizando a 
# variável global $data_system.
#==============================================================================

module Vocab
  # Nome da Opção no Menu
  def self.expertise;     return "Expertises";   end
end
  
#==============================================================================
# ** Window_MenuCommand
#------------------------------------------------------------------------------
#  Esta janela exibe os comandos do menu.
#==============================================================================
class Window_MenuCommand < Window_Command 
  #--------------------------------------------------------------------------
  # * Adição dos comandos principais
  #--------------------------------------------------------------------------
  def add_main_commands
    add_command(Vocab::item,   :item,   main_commands_enabled)
    add_command(Vocab::skill,  :skill,  main_commands_enabled)
    add_command(Vocab::equip,  :equip,  main_commands_enabled)
    add_command(Vocab::status, :status, main_commands_enabled)
    add_command(Vocab::expertise, :expertise, main_commands_enabled)
  end
end

#==============================================================================
# ** Scene_Menu
#------------------------------------------------------------------------------
#  Esta classe executa o processamento da tela de menu.
#==============================================================================

class Scene_Menu < Scene_MenuBase
  #--------------------------------------------------------------------------
  # * Inicialização do processo
  #--------------------------------------------------------------------------
  def start
    super
    create_command_window
    create_gold_window
    create_status_window
  end
  #--------------------------------------------------------------------------
  # * Criação da janela de comando
  #--------------------------------------------------------------------------
  def create_command_window
    @command_window = Window_MenuCommand.new
    @command_window.set_handler(:item,      method(:command_item))
    @command_window.set_handler(:skill,     method(:command_personal))
    @command_window.set_handler(:equip,     method(:command_personal))
    @command_window.set_handler(:status,    method(:command_personal))
    @command_window.set_handler(:expertise, method(:command_personal))
    @command_window.set_handler(:formation, method(:command_formation))
    @command_window.set_handler(:save,      method(:command_save))
    @command_window.set_handler(:game_end,  method(:command_game_end))
    @command_window.set_handler(:cancel,    method(:return_scene))
  end
  #--------------------------------------------------------------------------
  # * Comandos individuais [Confirmação]
  #--------------------------------------------------------------------------
  def on_personal_ok
    case @command_window.current_symbol
    when :skill
      SceneManager.call(Scene_Skill)
    when :equip
      SceneManager.call(Scene_Equip)
    when :status
      SceneManager.call(Scene_Status)
    when :expertise
      SceneManager.call(Scene_Expertise)
    end
  end
end



Notas:
Não é necessário creditar ninguém, mas caso queira você pode inserir um link para estas aulas. Ao redistribuir, peço que não poste o código diretamente fora deste fórum, apenas redirecione seu público para este tópico.

14/01/2019 às 04:12 #1 Última edição: 14/01/2019 às 04:17 por Nogueira
Novamente, muito obrigado pela ajuda! Tentei usar o código, mas não deu muito certo ainda. Após inserir o script e abrir o jogo para testar o esperado era que aparecessem dentro das Expertises os parâmetros que você deu de exemplo dentro do código ("param(8)", "param(9)", etc...), mas aparece apenas o "param(8)" repetidas vezes. Analisando o código percebi essas linhas aqui que começam na 74:

  #--------------------------------------------------------------------------
  # * Definição do nome dos Parâmetros
  #     param_id : parâmetro
  #--------------------------------------------------------------------------
  def get_param_name(param_id)
    if param_id = 8
      return "param(8)"
    elsif param_id = 9
      return "param(9)"
    elsif param_id = 10
      return "param(10)"
    elsif param_id = 11
      return "param(11)"
    elsif param_id = 12
      return "param(12)"
    end
  end


  Repare que tem um "els" aparentemente desnecessários antes do if nas definições de nome dos parâmetros depois de "param(8)".
Tentei deletar essas três letras e deixar apenas o "if param_id [...]" mas quando faço isso o jogo para de funcionar ao tentar testar e aparece a mensagem:

Script 'Expertises' (nome que coloquei no script no editor de scripts) line 157: SyntaxError ocourred.
class definition in method body.

Fiquei sem saber o que fazer ou o que eu estava fazendo de errado.

14/01/2019 às 04:26 #2 Última edição: 14/01/2019 às 04:36 por Corvo
Não são desnecessários, elsif é uma palavra reservada da linguagem para testar várias condições dentro da mesma estrutura. Se você o remove, o programa vai parar de funcionar porque terá iniciado várias estruturas e finalizado apenas uma, com o end no final. Um if/else comum é basicamente isso:

Se (Condição) é cumprida
    Faça isso
Se não
    Faça isso
Fim


O elsif seria isso:

Se (Condição) é cumprida
    Faça isso
Ou se (Condição 2) é cumprida
    Faça isso
[...]
Fim


O erro aí é que me esqueci de usar dois '==' nas linhas das condições. Com apenas um, estou fazendo uma afirmação, logo param_id = 8. Já corrigi no script, se não quiser copiar de novo basta incluir outros '=' deixando dois:

  #--------------------------------------------------------------------------
  # * Definição do nome dos Parâmetros
  #     param_id : parâmetro
  #--------------------------------------------------------------------------
  def get_param_name(param_id)
    if param_id == 8
      return "param(8)"
    elsif param_id == 9
      return "param(9)"
    elsif param_id == 10
      return "param(10)"
    elsif param_id == 11
      return "param(11)"
    elsif param_id == 12
      return "param(12)"
    end
  end

Spoiler
[close]

Opa, quando tu diz que pode ser usado dentro das batalhas, tu conseguiu que esses parâmetros sejam utilizados no cálculo de dano? Porque lembro ter acrescentado mais atributos uma vez, quando utilizava o VX ainda, mas eles serem somente visuais, não influenciavam em nada e como só se usam eles nas batalhas, acho que seria imprescindível.

Consegui sim. Claro que eles precisam ter o valor definido antes do começo das batalhas, mas funciona sem problemas. Joguei dentro do Game_BattlerBase, testei apenas definindo valores pros personagens. Desconfio que também funcione pros inimigos, mas não testei com eles ainda.

14/01/2019 às 09:14 #5 Última edição: 14/01/2019 às 10:44 por Sotelie
Comparado com o que eu lido diariamente seu código tá é limpo, poe aehueahe
Spoiler

É apenas puro C (embora tenha um main.cpp ali). Só ler com calma que cê entende o que tá rolando  :paperplease:
[close]

Mas eu realmente curto bastante scripts assim, que mexem mais com a parte sistemática do jogo. Lembro que usava bastante os do Hime justamente por isso.
Ótimo trabalho o/

14/01/2019 às 15:24 #6 Última edição: 14/01/2019 às 17:24 por Nogueira
Citação de: Corvo online 14/01/2019 às 04:26
Não são desnecessários, elsif é uma palavra reservada da linguagem para testar várias condições dentro da mesma estrutura. Se você o remove, o programa vai parar de funcionar porque terá iniciado várias estruturas e finalizado apenas uma, com o end no final. Um if/else comum é basicamente isso:

Se (Condição) é cumprida
    Faça isso
Se não
    Faça isso
Fim


O elsif seria isso:

Se (Condição) é cumprida
    Faça isso
Ou se (Condição 2) é cumprida
    Faça isso
[...]
Fim


O erro aí é que me esqueci de usar dois '==' nas linhas das condições. Com apenas um, estou fazendo uma afirmação, logo param_id = 8. Já corrigi no script, se não quiser copiar de novo basta incluir outros '=' deixando dois:

  #--------------------------------------------------------------------------
  # * Definição do nome dos Parâmetros
  #     param_id : parâmetro
  #--------------------------------------------------------------------------
  def get_param_name(param_id)
    if param_id == 8
      return "param(8)"
    elsif param_id == 9
      return "param(9)"
    elsif param_id == 10
      return "param(10)"
    elsif param_id == 11
      return "param(11)"
    elsif param_id == 12
      return "param(12)"
    end
  end

Spoiler
[close]

  Aaaaa sim, valeu! Corvo, uma dúvida: atualizei o script e deu certo, mudei os nomes de cada pericia certinho, mas não estou conseguindo atualizar os valores delas. Tentei usar o código que você passou no início do post para atualizar:

$game_party.members[id].param(param_id) = N


Aí tentei de várias maneiras, no evento coloquei "Chamar script" e colei essa linha de código das seguintes maneiras:

$game_party.members[001].param(9) = 10
$game_party.members[001].param(param_9) = 10
$game_party.members[1].param(9) = 10
$game_party.members[1].param(param_9) = 10

mas de nenhuma dessas deu certo. Tentei de forma empírica colocar end e $end também mas não deu.. Em todos os casos aparece a mensagem:

Script 'Game_Interpreter' line 1414: Syntax Error ocourred. Unexpected '=', expecting $end   
$game_party.members[1].param(9) = 10
 

O que estou fazendo de errado?
 
  Outra dúvida: como usar o script na parte prática do jogo? Por exemplo, vamos supôr que determinado NPC dá certa resposta caso o personagem tenha menos de 10 em determinado parâmetro, mas se ele tiver 10 ou mais nesse parâmetro o NPC dá outra resposta totalmente diferente.

Exemplo: para conseguir salvar determinado personagem é preciso que o jogador tenha 20 ou mais em "Medicina"

Gostaria de sugerir um comando em que ao eu definir o valor de alguma variável de minha escolha por evento (por meio do "controle de variável", que é mais fácil) ao chamar o código ele pega o valor atual dessa variável por evento e transforma no valor da variável correspondente do script.
 
Desculpe a ignorância, estou estudando o ruby mas ainda não estou 100% por dentro de muita coisa.  :paperplease:

Citação de: Sotelie online 14/01/2019 às 09:14
[...]

Obrigado. o/
E entendi quase nada mesmo.  :derp:

Nogueira

Tudo isso aí está na lista, o problema agora é ter tempo pra mexer no script. Aliás, se alguém quiser editar antes que eu consiga, à vontade. E pois bem, ignore o que eu disse sobre esse comando. Você pode só alterar a variável relacionada ao parâmetro da forma como preferir e a atualização é automática se não houver nada interferindo. Logo, para usar os parâmetros em condições também é só verificar a variável. Burrice minha em não ter testado.

Agora, usar variáveis por eventos não é uma boa opção. Funciona e por agora eu pretendo deixar assim, mas pense em como você vi fazer pra configurar todas as variáveis de todos os personagens e todos os inimigos que usarem os tais atributos. Seria um saco, a chance de bugar seria alta e seria um saco encontrar o erro depois. É muito provável que eu remova isso e tudo tenha que ser feito em comandos por script mesmo.

Ah, e lembre-se de que o script só suporta um personagem por enquanto.

Corvo, estou tentando usar o script e estudando as aulas de ruby que você indicou, mas mesmo o básico é extremamente difícil de aprender sozinho. Estou tentando inserir uns comandos no "chamar script" para alterar o valor das variáveis e mudar o valor delas do 0 (que aparece no menu) para outro valor de minha escolha, mas não estou conseguindo. Qual comando eu uso para fazer isso? Não é por preguiça de aprender, juro, estou realmente tendo certa dificuldade com as aulas. Se você ou alguém puder me ensinar como alterar o valor delas já consigo usar o script no projeto sem demais problemas. Valeu desde já!

Ainda não tive tempo de corrigir. Sinceramente, não sei quando terei, mas no momento você só precisa alterar o valor da variável. Por exemplo, o primeiro parâmetro extra tem o ID igual à 8. O ID do parâmetro é igual ao ID da variável que segura seu valor, logo, altere a variável de ID = 8:

Control Variables > [0009] Nome da Variável (Operação) (Valor)


Não precisa de comando por script ainda, logo:



Perfeito corvo! Consegui, já consigo ir em frente com meu projeto. O script do jeito que está é o suficiente pra ele, muito obrigado!!