Advertiser Content

Scripting Question Variable to array

Started by Tsuina October 11th, 2019 6:29 AM
  • 1113 views
  • 12 replies
Male
Seen 2 Weeks Ago
Posted 4 Weeks Ago
153 posts
182 Days
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
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

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

mgriffin

Online now
Posted 8 Hours Ago
756 posts
5.6 Years
I imagine you'd end up with something roughly like:
# 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
Male
Seen 2 Weeks Ago
Posted 4 Weeks Ago
153 posts
182 Days
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:
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 chaufhage",false,"Préparer le feu",false,"",true, "Pécari", "trchar098", "Camp", :SUPERLIGHTBLUE),
]
So do I have to use the various goal.new under this?

mgriffin

Online now
Posted 8 Hours Ago
756 posts
5.6 Years
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:

  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:

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).
Male
Seen 2 Weeks Ago
Posted 4 Weeks Ago
153 posts
182 Days
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

   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

Luka S.J.

Jealous Croatian

Age 26
Male
Croatia
Seen 1 Week Ago
Posted 4 Weeks Ago
1,145 posts
10.9 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.
Male
Seen 2 Weeks Ago
Posted 4 Weeks Ago
153 posts
182 Days
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.
Male
Seen 2 Weeks Ago
Posted 4 Weeks Ago
153 posts
182 Days
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.

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

mgriffin

Online now
Posted 8 Hours Ago
756 posts
5.6 Years
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
Male
Seen 2 Weeks Ago
Posted 4 Weeks Ago
153 posts
182 Days
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
Advertiser Content