Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - llamazing

Quote from: Christopho on September 24, 2016, 12:08:32 PM
But what is the problem with obstacles in the first place? If I remember correctly, when an entity with a path movement encounters an obstacle, it is temporarily stopped and the movement continues normally when the route is cleared.

I'm wanting to do something similar to Majora's Mask where NPCs follow precise routes at different times of the day. So at a certain time the NPC will be in an exact spot. If the NPC were to stop temporarily because the player got in their way, then not only would the NPC be delayed in getting to their destination, but there would also be discontinuities in the NPC's movements as the player transitions between maps.

This also means that when the player enters a map, the map script has to calculate where the NPCs are supposed to be depending on what time it is. This turned out to be not as difficult as I thought it would be, and I have code to do this that has been working well.

Quote from: Diarandor on September 24, 2016, 08:09:35 AM
Another solution is making NPCs traversable, for the hero, during their movements. When they stop moving, you can make them  to be a solid obstacle, unless the hero is overlapping them (in that case, wait with a timer until the hero stops overlapping the NPC).

I think this solution will work for me. Thanks!

I think I came up with a better solution than using a timer. Once the NPC stops its movement, I assign a function to hero:on_position_changed(), and then every time the hero moves I check if there's still overlap with the NPC. When the hero is not overlapping the NPC, I make the NPC non-traversable again and then set hero.on_position_changed to nil so that the function stops getting called every time the hero moves.

I'll improve the code so that it works with multiple NPCs moving around at the same time (and I'd have to modify it a bit if I ever want to use hero:on_position_changed() for something else), but here's example code for illustrative purposes:

Code (lua) Select

--Code to begin an NPCs movement
local hero = game:get_hero() --this is not a map script, so hero needs to be defined


local mov = sol.movement.create"path"

mov:start(npc, function()
--set npc back to non-traversable once player is no longer overlapping
hero.on_position_changed = function(self, x, y, layer)
if not self:overlaps(npc, "overlapping") then
hero.on_position_changed = nil

if npc_loc.facing then npc:get_sprite():set_direction(npc_loc.facing) end
Development / NPC movement paths and obstacle detection
September 23, 2016, 10:44:15 PM
I've been playing around with assigning path movements to npcs in order to have them follow a fixed route. The problem I'm running into is obstacle avoidance. Now it's easy enough to choose a route for the NPC that is clear of obstacles on the map, and I'd only have the NPCs moving around inside of towns where there are no enemies, so collisions with enemies are not a concern either. It's just collisions with the hero that I have to worry about.

I started off by setting set_ignore_obstacles(true) for the NPC movement. For the most part, that works. If the NPC's path goes through the hero's position then the hero will just get stuck for a little while until the NPC passes the hero, and it's just a little annoyance. The problem occurs if the hero happens to be standing where the NPCs path stops (and the NPC just stands in that spot for a while). Now the hero cannot move at all until the NPC starts a new path movement.

So then I played around with trying to push the hero out of the way when there's a collision with the NPC. So in the NPC movement's on_position_changed() function (any time the NPC moves), I check if the NPC and hero overlap with NPC:overlaps(hero, "overlapping"), and if they do, I assign a movement to the hero to nudge the hero out of the NPC's path.

I'm assuming that I need to move the hero one pixel at a time so that if the hero gets pushed over a 16x16 teletransporter (say inside a doorway), that the hero doesn't get pushed too far and skip the teletransporter. Is that correct? Pixel movement also seems preferable over path movement so that the hero can be moved just a couple pixels out of the way of the NPC instead of multiples of 8 pixels.

So I got something setup to move the hero when an NPC walks into him, but now I'm running into problems with making sure the hero doesn't get pushed into an obstacle when nudged. As an example, consider an NPCs walking along a path in the North direction with the Hero to the North of the NPC. When a collision occurs, I want to nudge the hero to the NW because if I only nudge the hero N, then the NPC could end up pushing the hero for the entire length of the path.

To nudge the hero to the NW, I give the hero's pixel movement a trajectory with several entries of {-1, -1}. The problem now is if there is an obstruction on the map to the west of the hero, I still want the hero to be moved to the N. It seems the hero's movement just calls on_obstacle_reached() and doesn't move the hero at all, even though there is no obstacle to the North.

The workaround I then used for the above problem is to give a trajectory that only moves one pixel W then one pixel N, alternating (i.e. {{-1,0}, {0,-1}, {-1,0}, {0,-1}...etc.}). This actually works for the most part, but there are still a few corner cases that don't quite work.

See the example image below, where the green 16x16 box is the hero, the blue is the npc, who is walking to the north to the doorway in the building above. The grey pixels (and the doorway) are traversable. So then the first time the NPC and hero bounding boxes overlap, there are six pixels (cyan) where the overlap occurs. Now obviously nudging the hero to the north fails because there is a building in the way, but nudging the hero to the east also fails because if the hero is moved 1 pixel to the east, the hero still overlaps the NPC by 5 pixels.

I don't have a good solution to this problem. The only thing I can think of is to do set_ignore_obstacles(true) for the hero and do my own manual obstacle detection, but that's tricky because it runs the risk of pushing the hero into the side of a building and getting stuck. I'm assuming I'd have to use map:get_ground() to do my own collision text, but how does that work? With a "wall_top_right" tile, for example, the bottom left corner of the tile is traversable and the top right corner is not. So does that mean that a coordinate in the top right half of the tile returns "wall_top_right" whereas a coordinate in the bottom left half of the tile returns "traversable"?

Or does anyone have any better ideas?
Your projects / Re: Zelda: Book of Mudora
September 22, 2016, 04:03:11 AM
Aren't you going to increment the version number of the updated quest?
Your projects / Re: Need programmers for Game
September 14, 2016, 06:17:10 AM
I'm willing to help out one task at a time as time permits.
Development / Pattern matching and UTF-8
September 08, 2016, 02:47:52 AM
I'm working on a custom dialog manager script for the features I described in this topic. A few questions have arisen in the process regarding UTF-8 characters:

1) In the text of my dialogs.dat file, keywords are denoted by prefacing the keyword with the "@" character. My original concept was to iterate through the keywords in the text using the following: text:gmatch("@(%w+)")which works great for ASCII text and forces keywords to only be alpha-numeric characters. However, my limited testing seems to conclude that it will not work as intended if UTF-8 characters are used.

It looks like a better solution is to instead use the following: text:gmatch("@([^%p%s]+)")which grabs all characters between the @ character and the first punctuation or space character (it only looks at one line at a time, so new-line characters are excluded).

Am I correct that pattern matching doesn't work with UTF-8 characters, and is my second proposed solution viable for when UTF-8 characters are used?

2) I also convert the text input of the player (in their native language) to lowercase with string.lower() so that case does not matter. My testing seems to indicate that string.lower() does not do anything for UTF-8 characters, but I see a note in the lua manual for the string.lower() entry that it depends on the locale.

How does the locale affect string.lower() and is the locale set automatically by the Solarus engine? Or perhaps by the operating system?

3) I've noticed that string.len() doesn't work the way I want it to in regard to UTF-8 (multibyte) characters since it returns the number of bytes in the string, and not the number of actual characters. It's easy enough to write my own custom function to count the number of characters in a string, but I figure I may as well ask...

Are there any included lua functions in the Solarus engine that return the number of characters in a string? It looks like lua 5.3 might have support for that, but as far as I can tell, Solarus appears to be using lua 5.1.
Development / Re: Getting all strings in strings.dat?
September 05, 2016, 07:27:19 PM
Quote from: wrightmat on September 05, 2016, 05:10:05 PM
Cool idea! Why do you even need the custom script though? Couldn't the strings.dat key just match the dialogs.dat id exactly?

The explanation I gave is the simplified version, and the workings of my conversation manager script to link the strings with the dialogs are fairly complex. The reason they cannot match one-to-one is because one strings.dat key can be linked with multiple dialogs and the conversation manager script decides which dialog to use based on saved game values, the current map, etc.

If you look closely at the dialogs.dat example I gave, you'll see that I defined "Greg.hat_lost" and "Greg.hat_found". So Greg's response to the keyword "hat" initially is the "oh no, I lost my hat" dialog, but if the player finds and returns his hat, then his response becomes the "thanks for finding my hat" dialog.

Another example is if there ends up being multiple dialogs that have all their conditions met, then the conversation manager picks one of them at random. Just a way of mixing things up a little.

Quote from: Christopho on September 05, 2016, 05:31:03 PM
As suggested by wrightmat, you can parse the files with Lua itself because the syntax is valid Lua. This can be done with sol.main.load_file() and setfenv().

I tried it and it was easier than I thought to parse. Thanks!
Development / Re: Getting all strings in strings.dat?
September 05, 2016, 02:09:01 AM
I'm working on implementing an interactive dialog system for talking to NPCs where the player types single word responses (in their native language), which in turn trigger additional dialog with that NPC. So basically, given a value from an entry in strings.dat (text the player types in), I need to find the associated strings.dat key for that value. And I know that the strings.dat key begins with "topic.(NPC_name)." -- I just need to find out what the last part of the key is.

Then I have a script to associate the strings.dat key with a dialogs.dat id. It's actually a bit more complicated than that since one strings.dat key can be linked with multiple dialogs.dat ids, and depending on the current state of the game, the script chooses which one of those dialogs it's going to display.

But since I've been working on the problem some more, I think I've come up with a better solution by doing things in the reverse order that I was originally envisioning, and doing things that way doesn't require parsing the strings.dat file.

In case you aren't following all that, here is an example:
Quote> hello

"Hello, my name is Greg. I'd stay and chat, but I'm busy looking for my hat."

> hat

"My hat was a gift from my wife. I lost it when a gust of wind blew it off my head
as I was exiting the church. I know it is around here somewhere..."

> wife

"My wife Sally runs the inn where you can get a bed to rest for the night."

> inn

"The inn is located at the northwest corner of the town, just past the blacksmith."

The english strings.dat file would contain:
text{ key = "topic.Greg.hello", value = "hello" }
text{ key = "topic.Greg.hat", value = "hat" }
text{ key = "topic.Greg.wife", value = "wife" }
text{ key = "topic.Greg.inn", value = "inn" }

The english dialogs.dat file would contain:
dialog{ id="Greg.greeting", text = "\nHello, my name is Greg. I'd stay and chat, but I'm busy looking for my @hat.\n"}
dialog{ id="Greg.hat_lost", text = "\nMy hat was a gift from my @wife. I lost it when a gust of wind blew it off my head\nas I was exiting the @church. I know it is around here somewhere...\n"}
dialog{ id="Greg.hat_found", text = "\nThank you for finding my hat!\n"}
dialog{ id="Greg.wife", text = "\nMy wife Sally runs the @inn where you can get a bed to rest for the night.\n"}
dialog{ id="Greg.inn_directions", text = "\nThe inn is located at the northwest corner of the town, just past the blacksmith.\n"}

A custom script would then link the string key "topic.Greg.hello" with the dialog id "Greg.greeting"
Development / Getting all strings in strings.dat?
September 04, 2016, 06:22:04 PM
It there a good way to either get all key/value entries in strings.dat for a given language or just the ones with keys beginning with a certain pattern?

Or do I have to parse strings.dat in my own script to extract the info myself?

I was trying to manually keep a list of strings.dat keys I'm interested in, but there's too many and it's becoming too much of a hassle.
I get the following error when launching the Quest Editor from the 1.5 OSX package:

QuoteCould not locate the assets directory.
Some features like creating a new quest will not be available.
Please make sure that Solarus Quest Editor is correctly installed.

I can load existing quests, but it doesn't let me create a new one. The 1.4.5 version of the Quest Editor did not have this problem.

I found an assets directory included with the Windows build. Copying that assets directory over to the directory containing the OSX Quest Editor does not fix it. I also tried copying that assets directory to ~/Library/Application Support/Solarus where the saved games get stored, but that did not fix it either.

Any ideas?
General discussion / Re: Noob Alert!!
July 09, 2016, 09:09:26 PM
For general Lua assistance, see the following sources:

Lua 5.1 Reference

Programming in Lua E-book

Basic Lua Tutorials
I've heard  good things about musagi, though I haven't used it myself. It's by the same guy who wrote sfxr for making sound effects for games.