RMRK is retiring.
Registration is disabled. The site will remain online, but eventually become a read-only archive. More information.

RMRK.net has nothing to do with Blockchains, Cryptocurrency or NFTs. We have been around since the early 2000s, but there is a new group using the RMRK name that deals with those things. We have nothing to do with them.
NFTs are a scam, and if somebody is trying to persuade you to buy or invest in crypto/blockchain/NFT content, please turn them down and save your money. See this video for more information.
A few questions about scripting

0 Members and 1 Guest are viewing this topic.

*
*crack*
Rep:
Level 64
2012 Best Newbie2012 Most Unsung MemberFor frequently finding and reporting spam and spam bots
I kinda went into Ruby scripting using what I already know from other languages, I have noticed that loops don't seem to work the way that I imagine they should.

Code: C++ [Select]

float fCurrentFrame = 0.f;
unsigned int iFrameIncrement = 1;
float fDeltaTime;

while( fCurrentFrame <= 600.0f )
{
  fDeltaTime = GetFPS(); // Which may or may not give you an error depending on what library you are using.
  fCurrentFrame += iFrameIncrement * fDeltaTime; // Which essentially slows down the FPS to 60
}


That would work just the same as a wait command in RPGMaker, it will wait for 10 seconds.


So I tried doing the same thing here
Code: [Select]
@currentframe = 0
@framewaitamount = 600

#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
loop do
  @currentframe += 1
end until @currentframe >= @framewaitamount
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
loop do
  @currentframe += 1
end unless @currentframe < @framewaitamount
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
loop do
  @currentframe += 1
end if @currentframe >= @framewaitamount
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
I was also using While and For loops, but it really didn't work at all.
Stepping through the code using the print keyword reveals that the count continues much further than the set amount.
And once the loop ends, the count is shown to be 600 ???

I'm not sure why this loop doesn't seem to work with Ruby, is it doing something different than what the loop does in C++?


I have resolved that problem by using
Graphics.wait(@framewaitamount)

But I'm still curious.









I also have an issue with my Actor Death BGM script (and before anyone mentions it, yes I have changed it from playing a BGM to an ME already :P)
Spoiler for code:
Code: [Select]
#==============================================================================
#  Actor Death BGM & Common Events
#  Version: 1.0
#  Author: DiamondandPlatinum3
#  Date: July 31, 2012
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  Description:
#    This script will allow you to play a BGM when one of your actors die in
#    battle. It'll also allow you to use a common event when it occurs.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#------------------------------------------------------------------------------
#  Instructions:

#     - Place this script in the materials section, above Main.
#
#     - Edit the editable region options
#
#     - Set your common events to do what you want them to do (in the database)
# If you don't want any common event to run for any specific actor - set the value to zero.
#
#==============================================================================
class Scene_Battle < Scene_Base
  def actor_death_bgm_play(which_actor) #integer variable
   
  #=========================================================
  #               EDITABLE REGION
  #=========================================================
    @death_bgm        = "Town5" # Set to nil if you don't want any bgm to play upon death
    @bgm_volume       = 100
    @bgm_pitch        = 100
    @framewait_amount = 100 # Set to zero if not using any bgm
   
    #-------------------------------------------------------
    @common_event_id_to_run = [  0,  # Don't touch this line
    #-------------------------------------------------------
    10,       #Actor1's Common Event to run if incapacitated
    11,       #Actor2's Common Event to run if incapacitated
    12,       #Actor3's Common Event to run if incapacitated
    13,       #Actor4's Common Event to run if incapacitated
    14,       #Actor5's Common Event to run if incapacitated
    15,       #Actor6's Common Event to run if incapacitated
    16,       #Actor7's Common Event to run if incapacitated
    17,       #Actor8's Common Event to run if incapacitated
    18,       #Actor9's Common Event to run if incapacitated
   
  #=========================================================
  ]#            END OF EDITABLE REGION
  #=========================================================
 
 
  #-------------------------------------------------
  #         Play Actor Death BGM
  #-------------------------------------------------
    Audio.bgm_play("Audio/BGM/" + @death_bgm, @bgm_volume, @bgm_pitch) unless @death_bgm == nil
    Graphics.wait(@framewait_amount)
    $game_temp.reserve_common_event(@common_event_id_to_run[which_actor])
    $game_system.battle_bgm.play
  end 
 
  #-------------------------------------------------
  #         Check Actors for Incapacity
  #-------------------------------------------------
  def check_actors_for_incapacity
    @actor_array = [$game_party.members.size]
    for actor in $game_party.members
      @actor_array[actor.id] = actor.state?(1)
      actor_death_bgm_play(actor.id) if @actor_array[actor.id]
    end
  end
 
  #-------------------------------------------------
  #           Display Added States
  #-------------------------------------------------
  alias play_bgm_on_actor_death process_action_end
  def process_action_end(*args)
    play_bgm_on_actor_death(*args)
    check_actors_for_incapacity
  end
end

Basically at the moment, it plays the death BGM on an actor when they die but plays it on that same actor yet again when the function is called once more (you can imagine how annoying that might be if you have three dead actors and you hear the death BGM play after every single action).


I have thought of using two boolean arrays to achieve my aim, but that seems kind of wasteful and I'm sure there is an easier and more efficient way
Spoiler for code:
Code: [Select]
#-------------------------------------------------
  #         Check Actors for Incapacity
  #-------------------------------------------------
  def check_actors_for_incapacity
   
    # Instance arrays, this will not work as intended!
    # I'm just using it as an example
   
    @adbactor_array = [$game_party.members.size]
    @adbdead_actors = [@adbactor_array.size]
    for actor in $game_party.members
     
      # Define whether Actor is dead or not
      @adbactor_array[actor.id] = actor.state?(1)
     
      # Call the Death BGM Function
      actor_death_bgm_play(actor.id) if @adbactor_array[actor.id] && !@adbdead_actors[actor.id]
     
      # Set the boolean after the function is called, so that it will play the BGM at least once
      @adbdead_actors[actor.id] = adbactor_array[actor.id]
     
    end
  end


Any suggestions on what I should do to achieve my aim here? :)
Thanks everyone.
« Last Edit: August 13, 2012, 09:51:06 AM by D&P3 »
All of my scripts are totally free to use for commercial use. You don't need to ask me for permission. I'm too lazy to update every single script post I ever made with this addendum. So ignore whatever "rule" I posted there. :)

All scripts can be found at: https://pastebin.com/u/diamondandplatinum3

*
? ? ? ? ? ? ? ? ? The nice kind of alien~
Rep:
Level 92
Martian - Occasionally kind
Your problem is a syntactic matter and the very dynamic nature of Ruby.
I highly recommend checking out the syntax nicely described here: http://www.zenspider.com/Languages/Ruby/QuickRef.html#control-expressions

To help you understand what your code does let me rearrange the code: (The resulting abstract syntax tree is probably the equivalent)
Code: [Select]
@currentframe = 0
@framewaitamount = 600

#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
until @currentframe >= @framewaitamount
  loop do
    @currentframe += 1
  end
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
unless @currentframe < @framewaitamount
  loop do
    @currentframe += 1
    break;
  end
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
if @currentframe >= @framewaitamount
  loop do
    @currentframe += 1
    break;
  end
end
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

You are using the following constructs:
expr if     bool-expr
expr unless bool-expr
expr until  bool-expr


To help you understand let me show you how you can implement the loop method like this:
Code: [Select]
def my_loop
  while (true) do
    yield
  end
end

What you would want to use is one of the following expressions:
while bool-expr [do]
 body
end

until bool-expr [do]
 body
end

begin
 body
end while bool-expr

begin
 body
end until bool-expr



In terms of actually waiting a frame you can use Graphics.update or Graphics.wait.
The latter is equivalent to: (Taken from the help file, not tested for typoes)
Code: [Select]
def Graphics.wait(duration)
  duration.times do
    Graphics.update
  end
end



For the second issue I suggest that you make your changes to where the code for handling battler death actually resides rather than trying to introspect after each action. (Hint: Search for die. (Ctrl+Shift+F for searching all sections))

*hugs*

*
*crack*
Rep:
Level 64
2012 Best Newbie2012 Most Unsung MemberFor frequently finding and reporting spam and spam bots
Simple and easy enough to understand, thanks a lot for your help Zeriab. ;8
I appreciate it :)
All of my scripts are totally free to use for commercial use. You don't need to ask me for permission. I'm too lazy to update every single script post I ever made with this addendum. So ignore whatever "rule" I posted there. :)

All scripts can be found at: https://pastebin.com/u/diamondandplatinum3

*
? ? ? ? ? ? ? ? ? The nice kind of alien~
Rep:
Level 92
Martian - Occasionally kind
I'm glad I helped you understand it ^_^
Let me know if there is else you have trouble with.
You can also try poking my student (Modern Algebra)

*hugs*

*
*crack*
Rep:
Level 64
2012 Best Newbie2012 Most Unsung MemberFor frequently finding and reporting spam and spam bots
I have a few more now:


When I use an alias, I just alias the method name like so:
Code: [Select]
alias alias_name_goes_here      method_name
But I've seen other people use symbols
Code: [Select]
alias :alias_name_goes_here      :method_name
are there any advantages/disadvantages to using symbols?





What is the correct term for when you put an asterisk in front of an array?
Code: [Select]
def method( *args )

array = [ 0, "Text", 1.7, false ]
method( *array )
I have been calling this 'dereferencing an array' because it's using the same tactic as deferencing a pointer in C++




Does Ruby use another name for Boolean?
I've often used:
Code: [Select]
object.is_a?(Integer)
object.is_a?(Float)
object.is_a?(String)

# But when trying
object.is_a?(Boolean)
I get myself an error for unitialized constant 'Boolean' ...?

I managed to come across a fix for that
Code: [Select]
if !!object == object
I'm still curious though.
All of my scripts are totally free to use for commercial use. You don't need to ask me for permission. I'm too lazy to update every single script post I ever made with this addendum. So ignore whatever "rule" I posted there. :)

All scripts can be found at: https://pastebin.com/u/diamondandplatinum3

*
Rep:
Level 82
I'm not sure if there's any benefits or detriments to using one or the other with alias. Preliminary research seems to say that it makes it look more Ruby like to use symbols. It's also more apparent as opposed to using what was called "naked words". Another seems to say that because you are using them like labels as a way to refer to the names rather than directly referencing them. Visually, I prefer the symbol format, especially in VX Ace since the names come up in that yellow/orange colour.

I've also taken more to using alias_method(old_name, new_name) as well. Not sure why, just something of a personal preference. Whilst I can't say I know whether using them with or without the colons is good or bad, I can at least bring something in regards to alias vs alias_method with one of those having something to do with scoping. This might be useful for that: http://www.ruby-forum.com/topic/135598



The asterisk in Ruby isn't to do with deferencing like it is in C++ (I initially believed this too, so you aren't alone). In Ruby, it allows for variable length argument lists, which is also the name for it maybe. For example (original code found from the link below):

Code: [Select]
def varargs(arg1, *rest)
  "Got #{arg1} and #{rest.join(', ')}"
end
varargs("one") » "Got one and "
varargs("one", "two") » "Got one and two"
varargs("one", "two", "three") » "Got one and two, three"

* http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_methods.html

If you look at scripts that modern and some other scripters including myself have written, when we alias methods we will do this:

Code: [Select]
alias :old_method :new_method
def new_method(*args, &block)
  old_method(*args, &block)
end

We do this because we might not be sure, or we don't really care maybe, about the arguments coming in. The original method might not take arguments, but what if some other script aliased the old method and he did want some things passed in. We aren't building our script with theirs in mind, but we want to increase compatibility. Using a variable length argument, like *args, achieves that.



Ruby doesn't have a Boolean object type. It has two types in place of that: TrueClass and FalseClass. When you use the keyword 'true' or 'false' it is a keyword that references an object of the respective type (true is a TrueClass, false is a FalseClass). When you come to checking the object type with the .is_a? method, you will have to check for it being a TrueClass object or a FalseClass one. What I do, sometimes, is a make a method that I might call #is_bool?(variable) that will return true if it's either a TrueClass or FalseClass, or false otherwise. It's not great, but it does the trick.
(Why do I always feel like it's the end of the world and I'm the last man standing?)

*
*crack*
Rep:
Level 64
2012 Best Newbie2012 Most Unsung MemberFor frequently finding and reporting spam and spam bots
I did not think there would be a difference between the two, still thought I'd ask. The colour scheme does seem to make symbols more appealing to the eye though :)



I knew what it was doing, however it was a thrill to do some revision based on your words :)
According to the link you provided, it seems the term for it is 'Variable-Length Argument Lists' just as you suggested. I will think of it as so, since I have never seen that used outside of method arguments.



I did not know that 'true' & 'false' were seperate entities on their own, that's surprising. I think I'll stick with the '!!boolean == boolean' since I'd find it more readable and pleasing to the eyes that way.




Thanks for the advice Logan :)
All of my scripts are totally free to use for commercial use. You don't need to ask me for permission. I'm too lazy to update every single script post I ever made with this addendum. So ignore whatever "rule" I posted there. :)

All scripts can be found at: https://pastebin.com/u/diamondandplatinum3