• 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
    • 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 29, 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
    • 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
    • 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 29, 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
    • 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
    • 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
    • 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
    • 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
    • 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 29, 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
    • 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