• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

[Scripting Question] Variable to array

153
Posts
4
Years
  • Age 36
  • Seen Feb 4, 2020
Hey guys,

I've been working on Marin's easy quest script and added some nice modifications. I think the weakness of his systemeven though it is amazing) is that each quest doesn't have an intern progression system. So, I transformed the descriptions in goals and added a variable linked to these goals, so that when one of the goals is accomplished it changes color in the in game description of the quest. Also I added that when all goals are achieved the quest is completed without the need to call the usual function to switch complete to true.

I want to improve this more but first I would like to change the variables goal1, goal2... into one array goal and do the same for goal1done, goal2done variables. What would it take to do so?

here is how it looks now after my changes
Code:
class Quest
  attr_accessor :id
  attr_accessor :name
  attr_accessor :goal1
  
  attr_accessor :goal1done
  attr_accessor :goal2
  attr_accessor :goal2done
  attr_accessor :goal3
  attr_accessor :goal3done
  attr_accessor :goal4
  attr_accessor :goal4done
  attr_accessor :npc
  attr_accessor :sprite
  attr_accessor :location
  attr_accessor :color
  attr_accessor :time
  attr_accessor :completed
  def initialize(id, name,goal1,goal1done,goal2,goal2done,goal3,goal3done,goal4,goal4done, npc, sprite, location, color = :WHITE, time = Time.now, completed = false)
    self.id = id
    self.name = name
    self.goal1 = goal1
    self.goal1done = goal1done
    self.goal2 = goal2
    self.goal2done = goal2done
    self.goal3 = goal3
    self.goal3done = goal3done
    self.goal4 = goal4
    self.goal4done = goal4done
    self.npc = npc
    self.sprite = sprite
    self.location = location
    self.color = pbColor(color)
    self.time = time
    self.completed = completed
  end
end
and this what I added

Code:
def pbSetGoal(id,goalnum,value)
   $Trainer.quests = [] if $Trainer.quests.class == NilClass
  for q in $Trainer.quests
    q.goal1done = value if goalnum ==1 && q.id == id
    q.goal2done = value if goalnum ==2 && q.id == id
    q.goal3done = value if goalnum ==3 && q.id == id
    q.goal4done = value if goalnum ==4 && q.id == id
  end
  for q in $Trainer.quests
    q.completed = true if q.id == id && q.goal1done==true&&q.goal2done==true&&q.goal3done==true&&q.goal4done==true
  end
 end
 
1,403
Posts
10
Years
  • Seen Apr 18, 2024
I imagine you'd end up with something roughly like:
Code:
# TODO: What *is* the thing in goal1, goal2, etc? I've called it id here, but it's just a guess.
Goal = Struct.new :id, :done

class Quest
  attr_accessor :id
  attr_accessor :name
  attr_accessor :goals
  attr_accessor :npc
  attr_accessor :sprite
  attr_accessor :location
  attr_accessor :color
  attr_accessor :time
  attr_accessor :completed
  def initialize(id, name,goal1,goal1done,goal2,goal2done,goal3,goal3done,goal4,goal4done, npc, sprite, location, color = :WHITE, time = Time.now, completed = false)
    self.id = id
    self.name = name
    # TODO: Make this more sensible. You'd probably want to pass a list of Goal objects in.
    self.goals = [
      Goal.new(goal1, goal1done),
      Goal.new(goal2, goal2done),
      Goal.new(goal3, goal3done),
      Goal.new(goal4, goal4done)
    ]
    self.npc = npc
    self.sprite = sprite
    self.location = location
    self.color = pbColor(color)
    self.time = time
    self.completed = completed
  end
end

def pbSetGoal(id,goalnum,value)
  $Trainer.quests = [] if $Trainer.quests.class == NilClass
  for q in $Trainer.quests
    q.goals[goalnum].done = value if q.id == id
  end
  for q in $Trainer.quests
    q.completed = true if q.id == id && q.goals.all? {|g| g.done}
  end
 end
 
153
Posts
4
Years
  • Age 36
  • Seen Feb 4, 2020
Awesome Thx man. i'll work on it this week and tell you what I got.

Goals are one line like "find the blue orb" then another goal would be "bring the red orb" and a third "bring blue and red orb to john". So when you find the blue one the goal is checked as done and the line "find the blue orb" is written in green now
 
Last edited:
153
Posts
4
Years
  • Age 36
  • Seen Feb 4, 2020
OK so I'm on it now but I don't understand where is the link between the Quest class and goals. I guess I have to replace all the goal1, goal1done, goal2... in the Quest initialize by goals?

I guess this should work to create the structure but then how to I give new values the goals of each Quest?
Quest now have this structure:
Code:
QUESTS = [
   Quest.new(0, "Find a Super Rod!","a",false,"b",false,"c",false, "Find a Super Rod somewhere in the field. This item does not have to be handed over.",false, "Quest Master", "trchar098", "Queesting Town", :SUPERLIGHTBLUE),
   Quest.new(1, "Préparer le feu", "Trouver le bois d'allumage",false, "Trouver le bois de chauffage",false,"Préparer le feu",false,"",true, "Pécari", "trchar098", "Camp", :SUPERLIGHTBLUE),
]
So do I have to use the various goal.new under this?
 
1,403
Posts
10
Years
  • Seen Apr 18, 2024
With the code I wrote above, no, you wouldn't actually need to call Goal.new for each pair. But my note about passing a list of goal objects was imagining something like this:

Code:
  def initialize(id, name, goals, npc, sprite, location, color = :WHITE, time = Time.now, completed = false)
    ...
    self.goals = goals.map {|goal| Goal.new(goal, false)}
    ...
  end

Which would give you something like:

Code:
QUESTS = [
  Quest.new(0, "Find a Super Rod!", ["a", "b", "c", "d"], "Find a Super Rod...", false, "Quest Master", "trchar098", "Questing Town", :SUPERLIGHTBLUE),
  ...
]

I've basically moved the "goalXdone" variable inside the initialize method, because I don't think you'd ever need to pass true—it looks like you only use that when there are unused goalXs, but now that it's an array you can simply pass fewer than four.

In the rest of the code, goalX is now goals[X-1].id (which you might want to rename to "name" or something), and goalXdone is goals[X-1].done (-1 because arrays count from zero).
 
Last edited:
153
Posts
4
Years
  • Age 36
  • Seen Feb 4, 2020
OK so I managed to make things work more or less by making Goal a class and initialize it like Quest but I have another problem

Code:
   for i in QUESTS
if i.id==0
  i.goals=[
Goal.new(1,"trouver le fromage",false),
Goal.new(2,"trouver le pain",false)]
elsif i.id==1
    i.goals=[
Goal.new(3,"trouver les fraises",false),
Goal.new(4,"trouver les pommes",false)


]
     end
    end

#I added this small function to check if it works
   
   def printquestdesc(plop)
for i in QUESTS 
  if i.id==plop
  for j in i.goals
   print  j.goaldesc
end
 end
end
end

When I use the printquestdesc it prints the description of the goal two times and I don't understand why

edit: sorry i didn't see your previous message which would have helped me a lot xD
 
Last edited:
153
Posts
4
Years
  • Age 36
  • Seen Feb 4, 2020
I really don't get it. When I replace
Code:
print j.goaldesc
by
Code:
print "plop"
it writes plop 6 times. So it's 2 times the 3 variables. But it's not linked to the number of quest because I tried adding a third quest and it didn't change the number of plops printed
 
153
Posts
4
Years
  • Age 36
  • Seen Feb 4, 2020
When I press enter instead of C it does it only once...


EDIT: Ok it was actually a problem with print
I used receiveitem and it did it once
because you have to press enter to exit the printed message it actually activates it a second time
 
Last edited:

Luka S.J.

Jealous Croatian
1,270
Posts
15
Years
Keep in mind that you cannot modify the contents of a constant from within a function/loop/others, and only during the initialization of that constants. Hence the name ... constant ... its data stays constant.
 
Last edited:
153
Posts
4
Years
  • Age 36
  • Seen Feb 4, 2020
Hey Luka, thanks for your intervention!

I did solve all problems now the quest can have multiple goals, the quest log (now opened from menu) shows goals written in green if they are finished, and if all goals are finished, the quest is considered completed.

I'll see what else I can add before I share these modifications to the community.

Thanks a lot Griffin your first message really put me on the good path.
 
153
Posts
4
Years
  • Age 36
  • Seen Feb 4, 2020
Hey!

I thought I could make a personnalisable back ground so I made 5 different colors from the original one and made them change from the variable Style. This works well if you change the value from the script as you prefer but I would like to make a function that allows this change from ingame.

Code:
Style=5
#change the style to have different background colors
def pbChangeStyle(value)
    @Style=1
  if value==2 
    @Style=2
  elsif value==3 
    @Style=3
  elsif value==4 
    @Style=4
  elsif value==5 
    @Style=5
  end
end

what did I write wrong? I guess there is a difference if a variable is in a function or outside like here. Thank you in advance
 
1,403
Posts
10
Years
  • Seen Apr 18, 2024
You probably don't want a capital letter at the start of Style, because IIUC that makes the variable a constant, which (I imagine) means that @Style isn't able to change it (and in fact, probably refers to a completely different value). You might want to look into what @@ does (IIRC it's for variables that are scoped to the class rather than an instance), or maybe you actually have an instance (it's impossible to tell from your code), in which case I'd just use @style and make sure to set it in the initialize method.

hopefully someone who actually writes Ruby can come along and give a better/correct explanation, I'm mostly guessing
 
153
Posts
4
Years
  • Age 36
  • Seen Feb 4, 2020
OK I solved it by doing $Style everywhere making it a global variable but it might be a problem so I'll try with @style as you suggested. When I tried @Style I had an error, it popped a no method error for "height" which has apparently no link to this

Edit: same error. I want to work on something else so I'll keep it a global variable for now
 
Last edited:
Back
Top