Update 34: July 2023
Hi all!
As you’ll see below, we’re continuing to hammer on our second dungeon, Tel Ekir, while revamping Shaded Dunes and fleshing out Sungreet Strand. Character work is going on in parallel and we’ve got a bigger tech update for you, as we promised in last month’s update.
Enjoy!
Character Art
Iterated on Halflings
Integrated initial pass on Goblin NPCs and player models
Added Halfling Skeleton
Added Evil Eye
Environment Art
Shaded Dunes
Zone revamped, including new transition to Tel Ekir dungeon
An Ashira camp/oasis area before the Tel Ekir zoneline
An Ashira overlook area
Completely revamped existing Blender geometry keeping the same footprint
Created new areas throughout the zone
Extended the western edge of the zone to make room for the new Tel Ekir zoneline
A rocky canyon area along the western edge of the zone
Created a new material animated ghostly material for the Ghoul Island spire
Created a new column mesh for the ruins in Shaded Dunes
Modified existing stone material to create a temp texture for the columns
Sungreet Strand
Muhktar Brewery added
Lowland Farms added
Blocked out Ruined Upland Farms
Tel Ekir
Props added in most areas
UV and Material clean up
Various small geo adjustments
Modeled Bloody Nose Goblin tents
Modeled Ashira Ward/banner stand mesh
Created collision meshes for Ashira, and Bloody Nose
Created prefab for Ashira, and Bloody Nose tents
Misc
Updated Dhow Ship Prefab to use the correct version of the ship
Animation
Rigged Halfling
Rigged Goblin
Goblin Animations
Evil Eye Rig and animations
Design
Integrated Beastmaster Quest #2
Integrated Shaman Quest #3
Adjustments of existing MUD objects using the new MUD Action tooling
Various fixes for cooking
First pass on base population spawn points of most Tel Ekir areas
Tel Ekir NPCs and Items started
Population work in Shaded Dunes, Night Harbor, and Sungreet Strand
Additional items available from merchants
Various quest bug fixes
Continued abilities and spell work
Tech
Ali’s Tech Update June/July
Every month brings tons of small changes, incremental improvements, fixes and rebalances to Monsters and Memories. It has been a monumental effort these last 3 years to build not only an MMO with such a small team, but to also do it in a way that is designer focused and highly data driven.
Our intention as the technology team has always been to give our design and art teams the tools to support rapid creation of compelling content (in as rapid a manner possible).
And in that vein, we thought it would be great to do another tech update where we highlight some of the bigger systems that went in these last two months, and to give a bit more details on what they are and how they work.
Character Material System
The Character Material System got a big upgrade this last stint. If you remember from previous updates, we had been clothing our characters by generating our textures then attaching them to the model.
This was done in a layered approach, where each texture layer (picked up from a server generated texture layer definition) would be essentially composited into a final single texture, which is then attached to the model.
In theory, this would have been a great solution because each texture variation would be just one final texture attached to the model (ie. All Night Harbor guards would share one texture for their bodies). In practice, this was problematic for a couple of reasons.
1) Texture layering was achieved via “blitting” a render texture. This means that for every layer, we are sending the layer texture to the GPU then asking the GPU to overlay it over the composite texture. Every step would have to be done discreetly with no chance of doing anything in parallel. In general, we have to repeat this 8-16 times per texture composite. This led to this process taking too long when you are entering an area and must composite 300-500 new textures in a couple of frames.
2) The resulting texture could not be compressed and must be held along with all its mip maps in an uncompressed state on GPU memory per variation. This was expected to be more efficient than having to hold multiple textures per material, but in practice was less efficient than the new method and led to situations where graphics cards that are memory constrained performing a lot worse than expected, even such cards as an RTX 3060 Ti.
Therefore, we pivoted to a new method that was in effect the same type of layered texture approach, but was something that could be handled in real time on the GPU.
We handled this by shifting over to a pretty complex shader that takes all the source textures as is and builds the result on the GPU without the need to keep feeding it textures in discreet steps. We thought this would be better, but we were not prepared for HOW MUCH better it would be.
In terms of loading speed, it could now do all the feeding of textures in ONE STEP and can handle a lot more in parallel (all the compositing would happen using the entire power of the GPU).
In terms of graphics memory utilization, we could now feed a single mip level in a highly compressed format (DHT5) directly into the GPU. We could stream in different mip levels as required. If something is further away, it would use a much smaller texture size. If something was closer, it would stream in higher resolution mips. Overall, it brought graphics memory utilization down by over 80%!
Combat Tuning
While combat formulas were created after a great deal of thought, discussion, and iteration, we were finding some unexpected results, especially when we started testing them over the entire range of levels.
We knew that in order to really get to the bottom of this, we needed a way to very quickly simulate a variety of combat situations and validate our formulas for errors and for intent.
And so that is what we got busy doing! In order to achieve this, a few foundational changes needed to be made. We had initially had different formulas governing player and NPC combat. In order to simplify simulation (which would require basically copying a player or NPC into a simulant or a group of simulants) and in order to reduce the chances for error, both technical and in design, we had to unify those formulas.
Unifying the formulas meant that we had to change the way NPCs worked and how their stats worked. We had to figure out in player terms, what those stats needed to be. We then converted everything to be on player scale and switched it over to using the same formulas as a player exactly. This immediately introduced a ton of bugs!
We were having NPCs in the higher levels hitting players for BILLIONS of damage. Even though that was hilarious, especially when the target was a gnome, it was something that needed to be fixed. We traced it to an unsigned integer underflow, which wraps a negative number to a very large positive number, which came about due to conversion NPC damage ranges into “player weapon” terms.
In the end, the work was worth it, because we found a lot of compounding issues in our formulas which were causing unintended effects at higher levels. We were able to tune the formulas not only for our entire level range, but to support years of combat scaling in the future.
Plus, it’s pretty cool to pick a player from our database, pick a target, and make them fight against each other thousands of times. It’s like a little fast-forwarding gladiator arena!
Getting the foundation firmly in place, we were able to balance AC budgets, stat budgets, NPC AC and stats, and base hit and miss rates to make combat feel tight.
The next targets on our list were % chance combat events. With a good baseline, a simulation engine, and quite a few parses in our logs, we were able to balance parries, dodges, shield blocks, spell channeling, and weapon procs. They now also feel tight over the range.
Finally, we wanted to round off this stint with some love for pet users. We worked out how weapons should affect NPC damage, which allowed us to let pet users give weapons to their pets. This necessitated building out the underlying persistent NPC inventory system, which we are going to enjoy playing around with in the future.
We also wanted to prevent AFK farming with a pet, which led to working out all the rules of kill credits with regards to pet credit, party member credit, damage shields, and edge cases that come about due to Feign Death and other disengages.
In the course of all this, we had multiple rounds of rebalancing threat generation in the context of all these changes.
Activatable Item Graphics
Since implementing activatable items like torches, which can be deactivated to save charges, we needed a way to reflect that on the item graphics. We have implemented very advanced tech that allows us to disable the flames on torches when they are disabled!
Special Ruleset Support
To support hardcore character mode and self-found character mode, we have implemented binary success checks on many regular operations.
For example, we now check CanPickup when trying to pick up an item that has been placed on the ground. Within this hook, we can check if we are self-found activated, and then we can check if it is our item before we allow it to be picked up.
We have refactored a lot of code to have these general purpose hooks in anticipation of having more and varied rulesets.
While these are systems we wanted to highlight this month, we have been busy improving many other facets of MnM. Below is a condensed list of all the changes that went in throughout July:
Enabled Halfling Male, Female, and their customization options in character creation screen
Undershirt rendering order fix
Dressing Room/NPC Editor Bug Fixes, UX improvements
Slain by message added when you die
Partial bug fix for unintended skillups when shooting unequipped bow
Partial bug fix for pressing server connect button too fast soft locks screen
Send BowLoose animation trigger for bow normal attacks
Fix spazzy camera when changing focus between unity editor and in-game viewport
ZoneSpawn tooling (In Progress)
Added mud volume editing tool
Added box support for mud volumes
Escape no longer removes icons from the cursor
Charged Items now use charges when the effect causes you to zone
Reworked /hidecorpse command and added /showcorpse command
New Material Shader
Replaced all async/awaits with UniTask for better 2022.3 LTS compatibility
Adjusted character controllers for swimming and better fitting in doors
No cleaning up invisible entities
Tightened up fall damage
Feign death combat credit changes
Feign death threat changes
Feign death reaggro implemented
Added weather to all zones
Pet combat credit changes
Better tracking of consolidated combat credit (parties, pets, etc)
Ability book UI changes
Holding alt to show icon labels cleaned up so they only appear when expected
Better handling of combat state for NPCs when enemies feign death
NPC Combat formulas converted to use the same formulas as other entities
Protected against damage underflows which deal billions of damage
Immediately interrupt casting when target dies
GHOST SHADERS
Charmed pets now immediately leave combat, which allows you to trade items to them immediately rather than having to wait for them to exit combat naturally
Allow trading bags
Allow looting bags off the floor
Allow dropping bags to the floor
Fix merchant edge cases which allowed you to sell some unsellable items for 1c
Async logging extensions that allow you to target the emitting object even if done on a thread or in a Task
Allow simultaneous loading of entities on the client, up to 100 entities at a time
Fix NPC AI to not sometimes forget where in their AI commands they are when they cast a spell or are hailed
Prevent invisible and other break on damage buffs from breaking from fall damage
Ability to set certain abilities to not break buffs when used (such as feign death while invisible)
Channeling, parry, dodge, block formula adjustments
Adjust player and npc damage bonuses
Fix render order for underwear (no more panties over your pants, sorry Superheroes)
Fix to parties causing infinite loading screens sometimes due to a race condition
Changes to sit aggro
Change to the method pets transfer their hate to their owner when they die
Implement mip map streaming for equipment textures
Corpse opening hooks to accommodate special rulesets
Dropping and picking up hooks to accommodate special rulesets
Trading hooks to accommodate special rulesets
Adjustment to NPC HP values
Properly apply HP buffs AFTER any NPC health modifiers to avoid multiplicative HP buffs
Prevent clients that are leaving the zone from keeping their locks on containers in the zone
Cooldown edge case fix to prevent instant cooldowns for NPCs
Corpse slot numbers changes to allow more types of corpses in the future
Strength damage bonus adjustments
NPC on NPC faction checks now check factions both ways and takes the worse of the two
Adjust low hp threat
Adjust int/wis contribution to total mana
Adjust ac contribution to mitigation
Adjust combat skill gain formulas
Prevent entities that you have targeted from leaving your Sphere of Influence if they are too far
More GM tooling to see whats going on with NPC logic, AI, and stats
Prevent interacting with corpses, widgets, harvest nodes, etc when dead, stunned, feigned death, or sitting
GM tooling to allow a quick reload of all active services when data changes while live
Require items to be in your possession for any Quest tag (NPC, MUD Action, Volume etc)
Separate icon name from its mouse over hover label. This allows having different information represented on each
Add confirmation prompt for looting NO DROP items off an NPC corpse
Activatable items can now activate and deactivate parts of their model
Buff window customization (different grid types and anchors)
Adjustments to song and healing threat, and all AoE effect threat
Properly update the client with new skill caps when levelling up
Becoming hardcore or self found now properly resets your character so that it is exactly as it was when first created
Properly clean up disconnected players from /who all
Restore ability to fish
Daze now has an icon on your buff bar
Prevent an edge case that allowed you to equip a primary 2 hander and a utility item in your secondary slot
Add functionality in the client model spawner for more lighting control for static lights
Volume checking now does a broad pass first so that it does not need to throttle itself when thousands of players are online
Fix world kicking your client during log in due to a rare race condition
While idle, NPC AI checks casting on a smaller range to avoid many unneeded casting checks in dense areas such as dungeons
Make clients see stealth when they can see invisible
World and zone have been refactored to differentiate between "Client" and "Character", with one representing a client connection and the other representing loaded character data
Adjustments to mez and stun threat, separating logic on the two
Campfires may now be created dynamically by players
Refactor on player and NPC cooldown tracking. It is now more resilient against errors and can be properly persisted
Updates to dual wield skill caps and formula
In Closing
Thanks for reading this far!
There’s always a lot going on, so check out our YouTube channel or watch us work live on Twitch to see more details or stay current.
As always, please join our Discord if you want to ask questions about what you’ve seen here. We try to stay active there.
Join our Mailing List if you haven’t already, if you’d like to be informed when these updates go live.
See you next month!