These weeks in Veloren 248

44 minute read13 June 2025Apr 1 -> Apr 16

Authored by horblegorble

Chillwater lake โ€” by Limina

Let's hop back on the blog-wagon, loaded up with fixes, kits, and seasonal fun. Hopefully not too much luggage for catching the i18n train.

- horblegorble, TWiV Contributor

Contributor work

Thanks to everyone who contributed to veloren these last weeks: @drunicornthe1, @Crabo, @unii, @juliancoffee, @isse, @horblegorble, @do-no-van, @walpo, @xMAC94X, @Knightress_Paladin, @coffee-compiler, @Caigh, @imbris, @floppy, and @srpapinha.

Thanks to the weblate translators who contributed these last weeks:

LanguageTranslators
CzechJanez
Englishevgenkot | Arriona
FrenchLimina
Germancoffee-compiler
Koreanjuliancoffee
Russianevgenkot | caesarrxx | LevmurDev | MBKenny | Arriona | Trauvel | Manifure | LuckyCoin | Carrotism | lucius_pilgrim | VVolsha
Ukrainianjuliancoffee | Akumo33 | ministergoose | Sinari | Iced | lomkada | Karaya | DDmytroO

Merged work

Chatty changes

Are you a chatterbox that loves to have a bunch of conversations going at once, but the friction of switching gears is slowing you down? @drunicornthe1 knows the feeling - and what to do about it. For their first merge request, they got their hands into the grime of the gearbox to tune up the mode swap transmission. Now it feels like driving a race car, with spacebar as the snappy paddle shifter.

Clear up the clutter and stay on message

Gitlab: !4849 โœจ


@Crabo has opened up the chat window for us to jump straight into Veloren's wiki:

I added the /wiki command. The idea came from a GitLab issue created in September of 2020. It was easy to do because it uses REST to delegate the searching and redirecting to the wiki itself. I'm starting to see more people use it to point newcomers to the right wiki pages. I tell people to type "/wiki recipes" and "/wiki weapons" all the time.

Answers at your fingertips

Do keep in mind that the wiki is community driven, and doesn't always keep up with the traffic of development.

Gitlab: !4823

Axe juggling

A recalibration may be in order for your knife-on-a-stick playstyle, with lower combo for several abilities and changes to fierce raze.

Pulling off another balancing act

Let's spell out the details of @unii's tweaks:

  • combo reductions: bulkhead, capsize, execute, maelstrom, riptide
  • one-hand fierce raze: reduced damage
  • two-hand fierce raze: increased damage, reduced range, increased energy cost

Combo-related ability descriptions have also been updated to have their numerical values separate from i18n files. That's one less ball in the air for future jugglers.

Gitlab: !4850

Fixing up fonts

If it felt like the voxel style of Veloren was being taken a bit too far with some languages, @juliancoffee would agree. The sight of all these blocks activated his mining instinct, and he swung the coding pickaxe to reveal their true forms:

We've tweaked our fonts a bit.

TL;DR: Complicated Latin languages like Norwegian or Czech can now be rendered properly. Arabic can be rendered now. You can't use convert_utf8_to_ascii anymore, because we've removed it.

High fidelity pickaxe sculpting

As for a more in-depth explanation, each language had 5 fonts attached:

  • Alkhemikal, super fancy font.
  • OpenSans, super generic font.
  • Cyri, which I believe stands for Cyrillic, is used as a regular font for most text you see on the screen.
  • Wizard, unused.
  • Metamorph, unused.

We've removed the unused Wizard and Metamorph fonts, and we've replaced OpenSans with GoNotoCurrent.ttf. The point of OpenSans is to be a universal font for formal information where we want the most complete coverage, for example, in chat. Except it didn't cover a lot of languages, so we've replaced it with another font that now covers almost everything, except Korean. And, because this is the font that should be the same for all languages, it's added by default, you don't need to specify it in the language's manifest.

Additionally, we've added EnterCommand from Font End Dev, which is a bit different, but supports more Latin characters, so I take it as a win. Oh, and we set GoNotoCurrent font as regular font for Arabic. How good is support for RTL languages is to be seen, I know it's not ideal, but at least we can render it now. Oh, and I've added า‘ า characters to our Cyri font, I'm an artist now ๐Ÿ‘€

Gitlab: !4875

No need to shout

@isse has been a busy bee, patching up all kinds of quirks in the codebase.

Town NPCs can save their voice with much more reasonable interaction distances.

Boombox -> voicebox

Airships return to their normal docking positions, taking the pressure off of player's knees.

No more spring-loaded boarding process

Caving is back to being a subterranean adventure, as their markers come out of hiding on the map.

Let's call it early practice for discoverable maps

But wait, there's more!

  • throwable items get a pickup sound
  • desert town NPCs can direct you to crafting workshops
  • waterlogged cave entrances are less likely to be marked on the map
  • using interpolated character positions make it easier to perform interactions at high speed, e.g. with sprites on airships

Gitlab: !4851 + !4854

Kitting out

If you're allergic to Nth-wall breaking narrations, turn back now. It's @horblegorble with the lowdown on loadouts:

The /kit emporium has expanded its catalogue of adventuring supplies to include a variety of new bits and bobs, outfits and bombs. Some are new to the store, while others are more bespoke bundles of existing products. As always, simply flash your admin badge at the door to unlock the unlimited shopping experience! New customers may wish to pickup an "Admin's Black Hole" bag before getting lost in the aisles. A complimentary one is included in the /kit debug package.

Booty a-plenty

For those curious about details further up the supply chain, here's a look at the adjustments to the specification and generation of modular weapons for kit and loadout configs.

KitSpec::ModularWeapon got split by suffix into Set and Random variants that generate (respectively) a full set of compatible weapons, or a single one chosen at random. The handling of handedness was adjusted to properly enforce the optional hands argument across all primary and secondary component combinations. With these two changes, /kit pirate could be set up to give two randomly selected one-handed swords. The hand compatibility also applied to ItemSpec::ModularWeapon for loadouts, which got Grim Salvagers to stick to their spec of two-handed hammers. No more smuggling in a close enough one-hander and calling it a day.

Cheers to @juliancoffee for advice on the coding process, as well as @Tarhun and @Sam for review feedback.

On a housekeeping note (and where this merge request started off), the new multi-model metal armour sets now have consistent names and ordering in their .vox files. This tidied up the .ron manifests, and hopefully mitigates the re-occurrence of some index mixups that arose from copy-paste modifications.

Gitlab: !4798

Better beams

@do-no-van had always heard it was advantageous to have a well-rounded skillset, but found that beam attacks were taking this advice a bit far. Specifically, it got a bit funky when their radius was being added onto their nominal range. After a small trim, things lined up much neater.

Mind the gap

Gitlab: !4869

One iter to rule them all

It began with the forging of the Great Data Structures. Fields were given to the Structs; immortal, simplest and pointiest of all beings. Variants to the Enum Lords, great matchers and unionisers of the double colon halls. And traits... Traits were gifted to the Race of Types, who above all else desire strictness.

For within these structures was bound the memory addresses and assembly to govern each abstraction. But they were all of them deceived, for another abstraction was made. In the land of Ukraine, in the fires of Neovim, the Dark Lord @juliancoffee forged, in secret, declarative macros to enumerate all others. And into these macros he poured all his caffeination, his rust-fu and his will to iterate all variants:

Ok, this is a super technical thing, but hey, it's a dev blog. Let me introduce you to a few macros I've been working on, with @imbris's help.

Well, you [may] know you can define enum in Rust:

enum Dir {
   Up,
   Down,
}

Let's say you have some function that takes Dir as output, so it'd be cool to automatically test it on all Dirs and check that it doesn't throws errors or something like that. Except, you can't get all Dirs, Rust doesn't provide such functionality...

Except, you can write such functionality yourself with a bit of dark magic by rewriting Rust code at compile time. One such magical rewriter is the strum crate, which we are using, which will generate a method iter() that will do just that. Unfortunately, strum can't handle anything more complex.

Let's say you want to nest these enums:

enum Boost {
   Health,
   Gravity(Dir),
}

You'd expect to get Boost::Health, Boost::Gravity(Dir::Up), Boost::Gravity(Dir::Down), but strum won't generate them, because ... it won't.

So I made a macro that would generate them. And that's not all. What if you don't have just enum? What if you have some struct you want to iterate over?

enum Species { Butterfly, Bird }
enum BodyType { Male, Female }
struct Body {
   species: Species,
   body_type: BodyType,
}

Well, that's another macro I've added which generates you all possible combinations of these Bodies, which would contain male and female versions for Butterflies and Birds. And if we already have that, why don't we apply that to exactly such an enum in our codebase: Body, which defines every possible "entity" we can have. By entity, I mean something abstract, but it includes everything from humanoids to rabbits, to even items and objects and airships. Not campfires though, which are entities as well, but well, special.

So this MR adds Body::iter function, which gives you a list of all possible entities. As a nice bonus, it will also generate some constants for you, like the number of kinds an enum has or if you ask it nicely, it will also give you all variants it can get. Unfortunately, the latter doesn't work with nested enums.

enum_iter! {
    ~const_array(ALL)
    #[derive(Eq, PartialEq, Debug)]
    enum Shade {
        Good,
        Meh,
        Bad,
    }
}
// it is, in fact, three kinds, as you can see
assert_eq!(Shade::NUM_KINDS, 3);
// and these shades are really what you'd expect
const ALL_SHADES: [Shade; Shade::NUM_KINDS] = Shade::ALL;
assert_eq!(ALL_SHADES, [Shade::Good, Shade::Meh, Shade::Bad]);

This is all done using so-called declarative macros or macros-by-example, which are powerful enough to achieve what I just showed you, but still not as convenient to write (or use) compared to more powerful kinds of macros: procedural macros. These ones don't just rewrite your code, they let you write the code to write new code.

In the future, we plan to come up with alternative versions of these using procedural macros, and I'd personally want to release them to the general Rust ecosystem.

Gitlab: !4843

Making mug shots

Whether you want to create wanted posters, a future bestiary, or establish the database for a surveillance dystopia - @isse's expansion of img_export to NPCs has got you covered.

Pick your fighter

Here's a simple example that'll give you everything at once:

cargo run --bin img_export -- --all-npcs

And another one with some of the bells and whistles:

cargo run --bin img_export -- --all-npcs --filter traveler --seed 0 20

This will give you an image for all NPC paths that contain 'traveler', with a seed value to control randomised characteristics. Note that the final positional scale argument is applied to a 10x10 image, so the default of 20 gives 200x200 output. The command can be run from the top veloren directory of a git repository, with output saved in a img-export folder.

If you're looking for pixel-perfect results, be aware there's still some minor glitches in the rendering at lower resolutions.

Gitlab: !4871

Don't git confused

Know your repo

Mirror, mirror, in the cloud; why are my changes not allowed?

Famed is thy git commit;

but hold, this kitty is not it.

Ears cannot hide the tentacle.

Alas, vulpes vulpes is where you fit.

A lash for thee, that heed not @walpo's note:

Due to user feedback, @walpo and @xMAC94x have updated the mirror repositories on GitHub in order to mitigate confusion with real repositories. The changes are:

  • New pull requests are automatically closed.
  • Some features of those repositories have been disabled to make them look "less real".

Remember folks, development takes place on GitLab, and not GitHub!

Gitlab: !4853 + !4857 + !4859 + !4868 + !4870

UI gooey

With a light makeover from @Crabo, crafting scrollbars are feeling much more confident in standing out to their mouse crush. This also inspired the footer section to give up their barefoot phase and slip on a 'boot bar' for some tidy delineation of their own.

A bit of brightening up around the edges

Gitlab: !4801

All aboard the i18n train

Dodging the bus factor

Based on a true story

Headlight eyes cut through the night. A low roar rumbles up through radiator jaws. All barrelling down at you with 7 tonnes of fury. The star of the show is ready, but @juliancoffee wants out of this road-rage thriller:

So there was a problem of bus-factor with our i18n system, in that, frankly, I was probably the only person who fully understood how it works and how to interact with it, so well, I decided to fix this problem.

This guide covers:

  • all the i18n crates (or well, ones that do matter, I'm pretending that i18n-helpers doesn't exist, because)
  • best practices and how to properly make UIs localizable
  • a few simple examples

(Oh, and btw, I've added a section about fonts to "Managing Weblate'", which is inspired by the post above.)

Gitlab: !211

What shall I call thee?

They have went by many names, floating between anonymities as boss after boss has called them to arms. After all these years of thankless, nameless service, @juliancoffee finally gives them something they can identify with.

A history of summons

Gitlab: !4883

Back in the bottle

Some buffing items were overflowing with power, eager to info-dump into your inventory. Keeping them in line was @Knightress_Paladin, by removing a doubled up concatenation and separating out duration information. At least this work was easier than putting toothpaste back in its tube.

Don't cry over spilled potion

Gitlab: !4873 + !4877

All the other carriages
  • localised some trade messages - @coffee-compiler !4862
  • changed "gigas frost" to "frost gigas" in English i18n - @Crabo - !4865
  • consolidated HUD .ftl files that aren't yet components in weblate - @coffee-compiler - !4820
  • localised player names in the trade interface - @Caigh - !4880 โœจ
  • localised /players command - @Caigh - !4882
  • merged weblate translations - @juliancoffee - !4884
  • localised CommandResult in voxygen - @Caigh + @juliancoffee !4893

New names, old stories

Grab your marshmallows and settle in by the campfire. @juliancoffee has a yarn to spin:

Ok, I don't even know where to start with this.

We can now translate NPC names! ๐Ÿฅณ

The shortcut to getting a 'new' job title

TL;DR

For devs:

  • in assets/common/npc_names.ron the generic field had been changed to represent an i18n key
  • in assets/common/entity configs, the name now uses Translate with an i18n key

For devs and translators:

  • animals are now translated like this:
name-body-quadruped_medium-lion =
    .fem = Lioness
    .masc = Lion
  • profession names and such are translated in an identical way:
name-custom-village-hunter =
    .fem = Huntress
    .masc = Hunter
  • objects don't have any gendering information, so they only request one attribute: neut
name-custom-dungeon-cultist-turret =
    .neut = Possessed Turret

And frankly, it was an MR [Merge Request] with a fairly small diff, only 1977 lines added and 665 removed. The internalization system saw bigger ones.

But it's the one that brings me a lot of joy, because in some way, it is the last internationalization MR.

A last internationalization MR. We've come a long way.

A beginning

When I joined the project around April 2021, a fair amount of work was poured into Veloren's translation, and most of the user interface could be translated via our in-house system of .ron files (json-like config files for Rust ). We even supported fallbacks if your current language didn't have all its strings translated (thanks to @Christof). It worked fine, but obviously it had its limitations; after all, it's just a key-value store. You ask for translated "yes" and receive "Yes" in return. Or "Oui", or "Ja", or "ะขะฐะบ", or "ใฏใ„". You get the point. It becomes complicated when you want to pass some values or, even act slightly differently depending on these values, for example, you don't want to end up in a situation where an item costs "one coins".

So, in early August 2022, we fixed it. We adopted a new format: Fluent, created by Mozilla. It was similar enough in its flow to our existing system, but at the same time, it's super expressive, probably the most expressive format at that point and even today. You can read about it more in a blog post about all that or in the RFC document, which quickly describes how it all works. (I think that RFC is the cooler one, but you can decide for yourself ๐Ÿ˜‰)

Fluent is a cool format, and it's enough of a reason to adopt it, but there was more to it. First of all, there was an issue with the translation experience itself. At the time, if you wanted to add localization to your language, you had to go through the same procedure all developers use, create a Gitlab account, learn how to work with Git, create a Merge Request, potentially manage your branch in case it needed updating... it wasn't easy.

So yeah, to solve that problem, we picked Weblate. It's a web service that provides a more human-oriented interface and an improved management system. It took us some time to migrate, and I must thank @walpo and @fnetx for pushing through it; it wasn't easy. As well as the Codeberg project for hosting. Right now, we're using it for all translations.

The tale of two worlds

We were working on creating and improving the internal framework for localization, but I must mention a significant limitation of said framework. You can only translate a message into a language, if you know what language to translate to. And while it would be possible to thread this information from the client you're using (and today, we do that to display server rules), it wouldn't be as convenient as you'd need to pretty much create two localization systems. Instead, we come up with the idea of delayed evaluation of messages. I could claim the idea here, but credit goes to @zesterer when he implemented the Content type while working on NPC messages. The process is simple: instead of giving the client the final string, we give it a key for a string and the required context to evaluate this key.

What this meant is that now you can translate not only the user interface. Now you can translate everything.

We started with translations for NPC messages, continued with server commands, items and finally, NPC professions and animal names. And at this point, we've translated pretty much all there is. Of course, there is stuff we forgot here and there, but it's a matter of someone going through beginner issues and implementing left-out pieces. You, dear reader, can do it as well.

Hit me up at Discord or Zulip, I'll probably be able to guide you. And if you're a translator and notice that something is missing from the game and there are no issues for that, feel free to create one (don't forget to add wg:translation label).

The future

So what would be the next chapter for Veloren internationalization? With our near complete coverage, we need to fill small holes, probably also implement i18n for plugins, and focus on QoL improvements. Maybe even contribute to Weblate, who knows?

But if I'd draw a big theme, I would say one word: Gender.

It's a complicated topic, but that makes it even more exciting. And I think I'll share some thoughts on it with you all. To begin, we already have a (bit shaky) foundation to build on. Check out assets/voxygen/i18n/it/hud/chat.ftl:

hud-chat-connection_lost =
    { $user_gender ->
        [she] Connessione persa. Verrai scollegata tra { $time } secondi.
       *[he] Connessione persa. Verrai scollegato tra { $time } secondi.
    }

I don't read Italian, but I bet you'd have an even harder time with the Ukrainian example, so bear with me. You can see the power of Fluent here, every message can not just splice passed arguments to it, it can act on them. Which is especially useful for numbers, as Fluent supports the whole Unicode standard for them, but it can be used for other stuff as well.

Almost all strings in chat have one or multiple arguments which specify the gender attribute of an actor in context. In this case, we check if the user's gender is masculine - we use one form, if the user's gender is feminine - we use another. (scollegata vs scollegato). (If we don't know, we default to masculine in this case, that is what * is for)

And if you go to the beginning of that file, NPC names follow a similar pattern, except here we employ a different tactic. The reason is that in both cases we 'match' on gender, but it's not the same kind of gender. There is more than one gender; in fact, there are more than two. As you can guess, hud-chat-connection_lost in English has no matches. That's because English lacks the concept of grammatical genders almost completely. It has the concept of sex, and it has the concept of gender. After all, we have all the pronouns.

Yet the word "left" is the same whether it's "she" who left, or "he", or "they" or even "it". There's no "scollegata" and "scollegato". And most importantly, while most languages have a similar concept of sex and gender, because it's not really a linguistic thing, the concept of grammatical genders can be wildly different, so we couldn't just expose one attribute to handle everything.

By the way, if you're still wondering, what I mean by grammatical gender, let me very quickly explain it. In some languages, every word has a gender. In most European languages, it influences the article and the word's ending. So "cat" in German would be "die Katze", which declares cats are inherently feminine. In Spanish, "the red cat" would be "el gato rojo" while "the red flower" would be "la flor roja". And so on. Read the Wikipedia page on it, if you want to know more.

With all that, I define three concepts we need to consider. Sex, social gender, and grammatical gender.

These are linked, and we're most interested in social (for names and such) and grammatical gender (for everything else). Unfortunately, at this point, we only have one: sex, which we in our codebase call the BodyType, a binary enumeration for Male and Female. We need to extend this system, create the concept of social gender for players and NPCs and then figure out a way to infer or define grammatical gender. The challenge lies in the fact that grammatical gender rules are kinda totally different for every language, so it will be fun.

I'll end it there. Feel free to jump to our Zulip or Gitlab issues if you have some ideas.

Gitlab: !4829

Zulip: [review] Name i18n !4829

More changes:

  • updated sponsorship link on github - @walpo - !4852
  • re-oriented Level of Detail (LoD) model for Haniwa Catacombs - @horblegorble - !4844
  • solidified a floor of the Myrmidon dungeon - @floppy - !4855
  • updated item quality ratings for recipes, bombs, and medium potions - @horblegorble - !4867
  • the re-orient express chugged along with modifiers for ranged attacks - @srpapinha - !4861
  • reverted some duplicate commits for a cleaner history - @juliancoffee - !4876
  • fixed armour manifest entry for dwarven guard hands - @horblegorble - !4878
  • limited git lfs checks to correct use of pointers - @imbris - !4879
  • replaced string arrays with enums for diary sections and skill trees - @coffee-compiler - !4888
  • rotated totems summoned by Gnarling Chieftain to face their target - @horblegorble - !4887

Ongoing unmerged work

(Re)trial by fire

The hypercritical steam engine โ€” by @Necti

@do-no-van's coding and @Necti's balancing was put through the crucible of combat in round 2 of Spicy Gigas playtesting. The big fella faced up against players and NPCs alike; thankfully all the commotion didn't cook @isse's server.

Pyretic pillars โ€” @horblegorble

Travellers gang up on Gigas โ€” @horblegorble

Discussions

Begun, the storage wars have

@Knightress_Paladin has penned the latest chapter in the Veloren RFC anthology, with an ode to bags, banks, and boxes. Given the different roads to travel, they've charted and articulated a course to travel, along with hazards of the terrain. All to reach one destination: a place for all things, be they necessity or novelty.

Let's take a look inside:

  • Per player, town based persistent storage at 'bank' structures
    • Can transfer between characters via stashes
    • Map UI toggle to show active stashes
  • Motivations
    • Can dedicate your inventory to a particular outing, freeing space to grab shiny new things
    • Dethrones inventory bag size from being the top stat
    • Developers get some freedom to add items without encumbering players
  • Site shuffles automatically transfer stashes to their nearest town
    • Done at time of player login, to avoid drifting over multiple shuffles
    • Possible courier system to alleviate work of relocating items after site shuffle
    • Differentiating between underground and above-ground settlements in the future
  • Open questions
    • How to decide which towns have storage? e.g. requires an airship dock
    • How do NPCs interact with the storage system?
    • Should there be theft from storage and couriers?
  • Future possibilities
    • Upgrades of storage at each town (capacity, security?)
      • Could range from one-time fee(s) to embedding with a quest system
    • Faction / sentiment influences
      • Out of scope for the moment, but likely to influence things in the future
      • Alignments between towns could scale courier costs
      • Various settlements could have their own pricing systems and rates
      • Non-friendly alignment might mean upfront/time-based costs for storage
      • Hostile settlement should not receive items after a site shuffle

Although landing a persistent storage feature would provide the staging area for weight based inventories (or other inventory nerfs), it is not desired for these to take place before matters of storage are properly unboxed. Wouldn't want to end up with the worst of both worlds.

Counting critters

The open sky breaks through the canopy's shade as you step into the open glade. Before you now, a sight to perplex the ecological mind: half a dozen wolves, packed up against a flock of sheep. Neither with a care in the world for the other. As it has always been, but maybe not in futures yet to be seen.

Rather than wildlife as islands unto themselves, what other geographies might be possible? A grand RTSIM archipelago would be the straight road guess, but could make quite a mess of the tracking budget. So instead of a world-scale game of "this little piggy", taking a more zoomed out view could avoid slimming down the CPU's piggy bank.

The Pangea Project is leading an expedition into this game design space, with a recent brainstorming session on linking up regionally tracked populations. In attendance amongst the crowd of khaki was @Neura, @zesterer, @isse, @juliancoffee, @Gemu, and @Knightress_Paladin. Here are their ideas so far:

  • Wildlife spawns based on population counts that are tracked by region/chunk
    • Terrain permitting, these populations diffuse and spread between adjacent regions
    • Entity interactions lead to a kill, death, or retreat that is tallied up against the population
  • Dynamic predator/prey modelling (simple or complex) running alongside gameplay interactions
    • With enough fudge in the numbers (sounds yummy!), this should lead to stable systems
    • There's a few different ways to split up wildlife categories for tracking
      • Species, body kind, ecosystem role (prey, (apex) predator)
    • Clamping effects and repopulation mechanics may be necessary to avoid global extinctions
      • e.g. a local extinction may trigger the re-seeding of the population elsewhere
    • Since post-apocalyptic settings are all the rage, could always let players roam free and annihilate everything - we love seeing that our actions have consequences, right?
  • A follow up point: NPCs could maintain sentiments towards particular species of wildlife (rather than individuals), communicating this to other NPCs and feeding into a quest generating system.

A questing checklist

You there, traveller! Fetch me 10 randomly dropped Gnarling bracelets and I shall grant you full gameplay immersion. That sounds realistic, right? @isse begs to differ, and reckons the recipe for quests is gonna be more than some microwave meal:

Just to name a few properties we want of the top of my head:

  • It has to be implemented in rtsim, our world simulation, and have effects on that.
  • Quests should be based on actual needs the npc/faction has. If there has been a cyclops attacking recently they could generate a quest to slay that. (We lack a lot of simulation for the needs of more interesting quests though).
  • We want a global tracker for quests, but each quest should have an actor/faction that gave the quest to also return to to complete it. And an actor/faction that received the quest.
  • Since quests are based on needs, that means they're also somewhat time based as needs can be fulfilled. Someone else could kill the cyclops, or the quest taker took to long so the npc decided to do it themselves etc. And the quest system should be able to handle this, in some way.
  • Not needed for first iteration, but quests should be able to handle cases where the original npc that gave the quest died. And migrate the quest to potentially another npc that npc knew.
  • Also not needed for first iterations, but since a huge majority of a veloren world's population are npcs, they should be able to take on quests too.

Community showcase

Concept art

First-hand accounts of various explorations in voxel space. A mix of things intended for use in-game, and more experimental ideations.

Go, go, slimer rangers! โ€” by @GoodMan29

High altitude headgear โ€” by @Supa

Pipe dreams โ€” by @Supa + a recolouring by @Dan113

This is the way

Airships are great for travelling fast, but a good map is what you want to travel smart. To help us plan out our commutes, @Limina swapped hats from translator to tool builder, taking a blog driven development approach to the task:

After seeing the full map of airship routes by @Froggy in devblog 245, I took it upon myself to fulfil the comment under it: "Now we just need a trip planner app."

Ask and ye shall receive! The Veloren Trip Planner for Veloren's official server is available at itch.io, all on the web - no download required! Code is over at github, under the GPLv3 license. I'll update any incorrect paths I come across - feel free to let me know if there are any I missed! For those that want more details, read on - else, you can just skip to the next section. I won't judge (much).

The tool was made with Godot 4.1.1, as it's my preferred engine to work with (and it's open source, too!). It uses A* pathfinding to figure out the shortest path between cities - paths are hardcoded, since we know all of them. They're easy enough to swap out though: each "town" is a node that hold a list of every other city it's connected to. That came especially in handy when I noticed some of the paths had changed since @Froggy's map was made!

Currently, it recreates paths every time we ask it for one - admittedly, I could skip that step and just generate it once, but it doesn't matter much given the amount of paths is quite low. That would also allow for dynamically ignoring cities or even adding/deleting them at runtime if we want to - although that's not a thing yet. :P Once we know the starting and ending cities, we can just use the paths that are created with the A* algorithm, and voila, we have a path!

I don't really have a to-do list, so any suggestions are welcome - or even pull requests if you so wish~

Weave got a new challenger

Looming over the competition is a new entry from @Moaaswell to the previously featured carpet challenge. Taking us beyond the simple square, will this stretch the fabric of the contest?

Think outside the box. Be an even bigger box!

Explosive new meta

Get ready to have your mind blown by @Necti's feature of the throwable bomb meta that is blasting away all other playstyles. Learn about shockwave proofing your loadout, dig into make-your-own trench warfare, and stick around for some charming tips on dealing even more damage.

Not hard to imagine an aerial bombardment support role

Veloren's coconut farmers are greedily rubbing their palms together in anticipation of increased demand. But time will tell if player's appetities are lasting, and whether these would-be profiteers will survive the fallout.

Phoenix fireworks

After converting their inventories into dedicated bomb factories, the players of Sporia faced a shortage of velorite and coconuts that threatened to derail their regularly scheluded fireworks display. To fill in for the local pyrotechnics shortfall, some resourceful individuals decided to import a brand new light show.

@horblegorble brings us a photographic account of the family un-friendly event that followed. Identities and profanities have been redacted to protect the (not so) innocent.

Reel 'er in

Lighting up main street

Recipes for disaster

Waned enthusiasm

Here comes the rain

A new sun rises

Getting upstaged

Arrow time

Bird's eye view

A crispy aftermath

Events

'twas the season of springtime sillyness in Veloren, when familiar tricksters and treasure eggs popped into play. But this year also threw an unexpected curlball into the mix.

April fools

We'll let @Necti do the grand reveal, with this inside scoop on Veloren's newest celebrity.

Pay no heed to false leads โ€” by @Necti

The master has arrived

The Pigmaster is a swine to swoon over - at least, that's what their possy of rats will tell you if you ask them about forming this leaning tower of trouble. Finish off the smolest one (without losing track of it) for a chance at getting a Rat Tail of your own.

Master, rat, small, tiny, mini, smol โ€” @horblegorble | @Alley_Oop | @Crabo

This stack of suprises was smuggled bundled into a package of 'small changes' by @isse, along with collaborators unknown.

Exciting as it all was, the new buzz didn't steal the whole show. Folks got up to a lot of the usual unusual April Fools fun.

Hop, skip, and a roll to get to the concert on time โ€” by @Supa

An annual tradition โ€” by @souffle

They get themselves into all sorts of tricky spots โ€” by (โžœ) @souffle | @horblegorble x3

Blazing trails โ€” @horblegorble

@Necti blends in to lead the band โ€” @horblegorble

A curious potion turns the tables on @horblegorble

Rooftop rats โ€” @horblegorble

Easter

Although slightly overshadowed by the fresh excitement of foolish festivities, players were still keen to hop into the Easter event. After all, you don't get to throw around surprise eggs for the rest of the year without stocking up first.

Ear ye, ear ye! โ€” by @souffle | @horblegorble

@souffle woke up to find out the tooth fairy was helping with Easter deliveries this year

In the wild

There and back again

Let yourself be carried away by the narration of @Gbone, as they regale us a tale of marvel and mishap. Will this band of adventurers conquer all, or will the world conquer them? See them face up against wolves, caves, dungeons, and even airships and town NPCs - as well as unintentional levels of friendly fire. All in good fun as they find their way back home.

Fame, fortune, glory, and tomato salad! โ€” @Gbone

Screenshots

We've only got the one bridge, so it better be sturdy โ€” by @isse

Small worlds make for big parties โ€” by @Alley_Oop

Demonstrating the value of all those neck stretches โ€” by @unii

Inviting aromas โ€” by @isse

Catching a ride โ€” by (โžœ) @Val | @Limina | @horblegorble

Flying into fresh dawns โ€” @horblegorble

Volcanaurora โ€” @Alley_Oop

Valley of light โ€” @horblegorble

Foraging for honey-root โ€” @horblegorble

Boing boing boing... โ€” @Trentus

Vibing โ€” @Limina

Did I find Atlantis? โ€” @isse

Sahagin envy โ€” by @Alley_Oop

Foggy humps โ€” by @Sam113

Living the well-shaded life โ€” by @term_junkie

Pining for a new day โ€” @horblegorble

Late nights on the beachfront โ€” by @Sam113

Pointed reflections โ€” by @Sam113

Highrise district โ€” by @Alley_Oop

Heard you like silly scribbles

Surprised tower-chu face

'bigflyingrock' โ€” by @Supa, named by @Sam113

Grave of the flying hero โ€” @horblegorble, found by @Alley_Oop

Definitely some kind of cave entrance โ€” @DaforLynx

Extra spicy shrooms โ€” by @Alley_Oop

Liminal lines โ€” by @And_i

Sparkling spelunking (say that five times fast) โ€” by @And_i

Chillwater cliffs โ€” by @Limina

This developer blog is based on information collected in #blog-content, where game contributors are always invited to communicate their updates or simply post a link to a different channel.

The lost legoom contemplates a darker path. Let's hope they find their way back to us :)