Posts that were made prior to this (and prior to October 9th) are before I was hired by Carbine Studios. From this date forward, I am under NDA. All posts are representative of myself and only myself and do not represent Carbine Studios or NCsoft in any capacity.
Character creation in Aion was one of the most involving aspects of the game itself. It starts off by presenting two faction options: Elyos or Asmodean. In vanilla Aion, this had a large impact on your gameplay, as your faction would determine some of the abilities you would get access to later. While this was eventually changed, there remained a factional imbalance with how the maps were set up. That aspect will NOT be covered in this article.
After that, you are presented with 12 options for classes to play. In vanilla, there were only 8 options. There aren’t 12 classes to play, though. The game presents male/female as different versions of the classes, although there is no difference in gameplay between the two. The differences are purely cosmetic.
One of the more confusing aspects of this window is that you are presented with 6 stats in the lower left: power, health, agility, accuracy, knowledge, and will. There is no explanation what these stats are for, and it is entirely up to the player to learn. There is no equipment within the game itself that has these stats on them either, as HP is the stat that appears on gear NOT health.
These stats cannot be changed in any way, shape, or form until 5.0. In 5.0, players are given a talent-point style system (called Essence Allocation), and I will cover this system in great detail in the future. Before the Essence Allocation System, though, these stats were completely immutable, and they also did not indicate what they were for.
After a lot of experimentation by the player base, it was discovered that these stats indicated how well this specific class scaled with stats. If a character had 100 knowledge, they gained 100% of the value of every point of magic boost. If a character had 95 knowledge, they only gained 95% of the value of every point of magic boost. If a character had 130 knowledge, they gained a whopping 130% of the value of every point of magic boost.
While I do view more knobs to help balance a game as a valuable tool, these particular stats always puzzled me. They were presented to the player at class selection, and seemed to be of vital importance. While they were very important, the way they were presented always made it feel like they were a stat that could be changed, or a stat that would come into direct play later.
But neither of these things are true. These stats were always hidden in the background, and it was never something that factored into gameplay decisions later. In fact, at 10, when you ascended to become your true class, these stats changed again.
This gave character creation in Aion a confusing feel, as it would sometimes present you with information that was neither important nor relevant.
Then comes the cosmetic portion. I am sure virtually everyone has seen pictures of hideous and beautiful Aion characters, so I will not cover those here. Instead, I am going to talk about the armor and ability showcase mode. In this mode, you can view 4 types of armor:
Low level armor
Mid-high level armor
High level armor
You can also view 6 different abilities. Of these 6 abilities, some may not actually be in the game, though. This was one of the odder realizations I had when I bought a plastic surgery ticket (a character appearance modification item).
While this may not seem major, one of the cooler abilities that it showed for sorcerers was an ability that didn’t even exist within the game, at least not for sorcerers.
In conclusion, the game’s creator has a lot of cosmetic options, but it also has a bunch of information that only serves to confuse players (or simply be forgotten). The stats, along with the sometimes missing abilities, are a confusing combination of things to present the player with that seems to serve no actual purpose in the game.
This version will be the final version that is a standalone version that requires all of the players to download the game in its entirety. In future versions, a small patch file will be available to jump users from version to version. This will reduce download sizes from 5 GB to 20-25 MB (except in graphically large patches).
Spell effects now display on the HUD for both yourself and your target!
See below for a known bug involving the spell effects display.
Gear is now equipped or unequipped by right clicking not by left clicking.
Left clicking on spells still works.
Left clicking on a HUD element should not have the unintentional consequence of clicking through and clicking onto a player or object underneath, causing you to potentially change targets.
Right clicking on a player’s status bar will now properly bring up a context menu, allowing you to invite to a private party or to mark the target
SetPlayerClass X where X is the number of the class you want to become (stored in alphabetical order). This will be disabled when there is a better way for players to switch classes. This command is case insensitive.
Private Groups and Marking:
Private groups have been added to the game. You are able to opt out of the public group experience and instead control who is allowed into your party. By entering a private group, you also gain the ability to use the mark component.
You mark someone by applying a number or symbol above their head. Once a target has a number or symbol above their head, it follows them around, and the user is able to target that specific mark with a hotkey, making for easier targeting. As stated in the private groups section, you cannot mark in public groups. This may change in the future.
Chat now wraps instead of truncating at the end of the line.
The chat scroll bar will now stick to the bottom of the chat log if you have not adjusted the offset, and it will stick to your offset if you have.
Added a threat management component to all pawns so that threat is properly propagated across all of the targets.
Threat is handled through an algorithm that combines enmity, distance to target, and health of target.
Targets that are closer are favored over targets that are farther away.
Targets that are low on health are favored over targets that are fuller on health.
Targets that have more enmity are favored over targets that have less enmity.
Necromancer moved from “class fantasy design phase” to “first ability pass: implementation phase”.
Assassin – First ability pass: Test ready
Berserker – First ability pass: Test ready
ChaosBlade – Undergoing class concept revamp
Cleric – First ability pass: Test ready
Dreadnaught – First ability pass: Implementation phase
Druid – First ability pass: Test ready
Magus – First ability pass: Late design phase
Mesmer – First ability pass: Early design phase
Monk – First ability pass: Early design phase
Necromancer – First ability pass: Early design phase
Oracle – First ability pass: Implementation phase
Paladin – Class fantasy design phase
Ranger – First ability pass: Early design phase
Shaman – First ability pass: Early design phase
Troubadour – First ability pass: Early design phase
Warrior – First ability phase: Late design phase [Guardian was merged into Warrior]
Warlock – Class fantasy design phase
Wizard – First ability pass: Early design phase
Zealot – First ability pass: Late design phase
Frostbolt no longer hits friends and foes alike.
Chat log no longer cleared on death.
The local player no longer sees every chat message as originating from them.
Overhead mark is now invisible until set, and it returns to being invisible upon unmarking.
Auto attacking now turns off if you are dead.
Clicking off of a target does not remove the spell effects display.
Right click turning does not replicate until you move without right click held down.
Minor rubber banding when you stop moving unless you are an authoritative client.
Ammunition is not consumed even if it is required for a weapon.
Only one character can be saved per server. This is a shared quantity across all users.
Frames outside of the hotbars are not able to be dragged.
Blueprint Nativization crashes the game packaging process due to errors in Boost Bimap.
Sending a chat message attaches the camera to your cursor.
NPCs will continue auto attacking you after your death.
Spawning too many NPCs simultaneously will cause any player that also attempted to join the game to crash.
Second demo with decals toggled on and off to show the performance of the system when decals are enabled vs. disabled:
This map is hideous.
Yeah it is. This is a sandbox-test map that I use to demo anything before putting it into a “real” map.
How does it work?
It is a double buffered event-driven influence map that is based off of this article by Alex Champandard.
It appears to update in rows. Why is that?
The amount of grids that are updated per tick (from the server’s perspective) are editable in the actor details panel on the right side of the picture shown below.
It updates a limited number of grids per run to keep the overhead low. Setting the “Updates Per Tick” value to 0 results in it updating all of the grids at once.
What is the purpose of the influence map in this game?
The purpose of the influence map in this game is to simulate areas of control by the different factions within the game to indicate to the AI where it should focus their efforts.
What is the “BP_Outpost” that was added to the map?
The BP_Outpost added to the map is a constant influence point that the AI will construct to add spawn points closer to the front lines of battles. The BP_Outpost, in its current state, adds no true gameplay ramification outside of the influence applier. In the future, it will add spawn points to the world.
What does all of this lead to?
The goal for this is to create a system wherein the actions of the players or the NPCs can sightly shift the behaviors of the NPCs in the world.
What still needs to happen in the influence map?
Adding support for multiple factions
“Smarter” spawning – Some of the grids being spawned simply can’t be pathed to, so spawning them in the current way is suboptimal.
What kind of performance upgrades are you looking at doing?
Now I’m going a bit on the technical end. Right now, it spawns an actor for every single grid square. That is horrendous, performance wise, although kudos to the Unreal Engine for being able to handle over 250,000 actors being on the map. These are not ticking actors. Only the original “InfluenceMap” actor is a ticking actor, and it chooses small subsets of the population to update.
I have a plan for a major performance overhaul which does involve moving away from actors for the influence grid and moving to a far, far more efficient system.
How large have you expanded it to?
512×512 is the highest I have managed to get into a game. It is around 6 GB worth of influence map data on its own, although that is partially caused by them all being actors, and it is VERY obvious whenever a chunk updates. So, that made it painfully obvious that I had to completely overhaul my system.
That seems excessively large.
It is. Especially since no performance upgrades have been done yet. This is the goal, though. 512×512 is the “target” for my project. My project’s world map is intended to be split into an 8×8 grid of 64×64.
When is the next update planned?
I want to have the next implementation of the influence map ready to go by the end of next weekend. I won’t have the debug visualization completed by then.
Hopefully I will have more specifics for the next blog post.
1.) The UI. The UI is definitely not the prettiest thing, but as this project was entirely a prototype to get ready for the “real” project, I was willing to just make something functional, albeit not pretty.
2.) The inventory system is only 10 slots, but every item can have multiple features:
ItemID – The ID that the item attempts to emplace.
Unique – If the item is unique, more than one stack cannot exist.
Stackable – If the item is stackable, more than one item can be placed into one stack.
StacksTo – If the item is stackable, this is the cap for its stacking capabilities.
It also handles all combination cases, such as…
A non-unique stackable item going over the StacksTo cap will overflow into the next stack.
A unique non-stackable item will check the entire inventory before emplacing to ensure the ItemID doesn’t come up later.
A unique stackable item will check the entire inventory before emplacing to check for the ItemID and will handle overflow.
3.) Respawning. Respawning works for players, but death does nothing to NPCs. They are unstoppable!
To start with, AMO is short for “Arena Masters Online”. It was originally intended to be a multiplayer PVP arena game with traditional MMORPG style combat. While this project was a Blueprint/Code hybrid project, this project is probably 99% Blueprint. I will indicate the systems that are not. I will try to screenshot as many systems as I can, but if you want to check out the project in all of its crash-prone prototype glory, click here. There have only been a couple changes in the past 6 months, and those were all updates to the spell table and updating the project and solution to 4.12.5 compatibility. If you download the project, keep in mind that the project does not contain all of the assets that appear in these clips. Some of the assets are purchased from the shop.
First, a really quick introduction: A three way fight, followed by an explanation of the AI.
It isn’t the most visually stunning fight, but allow me to explain what is happening. I am playing in the editor itself. The two enemies are enemies of both myself and each other. Being that everyone starts at 5% health, their first reaction is to find a hiding spot to heal up in. I target one of the AI and follow him. As you can see, he runs to a spot that is out of line of sight of everyone and begins casting Tranquility, which creates an enormous collision sphere. Tranquility then applies the Tranquility HOT to the 5 lowest health targets every tick. In this case, he is the only one, but what if there are, say…. 84 AI running around in this arena, but they’re only divided into two teams?
As you can see, the frame rate is horrible, and they also get stuck on each other a lot, but notice how I’m not casting, but I’m getting healed, as are quite a few others. This is because one AI started casting Tranquility, and it applied to the five lowest health units within the AOE. You can also see by the top left that the AI is announcing what spell it is casting. How many spells in total are there?
The AI will only cast two: PC_DruTranquility and TEST_Frostbolt. The AI’s behavior is very erratic, I will admit that. That is because the AI wasn’t setup to actually fight in the prototype. They had very, very primitive logic.
That is likely illegible, so I will explain. The top of the tree is the root followed by a selector named “RealRoot” and then a selector. You can ignore the “RealRoot” selector. The unnamed selector is the important one. It will attempt to go into the first sequence node. If “IsEnemyVisible” is set, it will check its own status. If it is defensive (< 35% health), it will attempt to run away and find an enemy hiding spot by using an EQS query. The EQS is very basic.
Yes, it is called TestEQS. I apologize for the name, but like I said, this is a prototyping project, and this was my first venture into EQS. But this EQS does as follows:
Create a pathing grid of 1500 units with 100 space between with a 2048 height projection.
Discard all unreachable nodes. We don’t need the system to be doing calculations to locations that it cannot reach.
It then attempts to do a basic visibility line trace to enemies from individual nodes. It does not score on this, it simply discards nodes that are out of line of sight of an enemy.
At this stage, the only pathing nodes we have left to choose from are ones out of line of sight of the enemy.
We now measure the distance to this node from the querier, but we prefer lesser. So, we want the closest node to the AI. We score this on an x1 scale.
We now measure the distance from this node to the enemy unit, but we prefer greater. We want the furthest node from our enemy. We score this on an x1 scale.
We then take into account the facing direction our enemy. We want to prefer spots behind the enemy or on the peripherals if they are close enough. We score it based on this factor.
This means the AI’s hiding spot will be an out of line-of-sight node that is somewhere in the middle of being close to the AI and far from his enemy. This generally generates spots that are very close to walls or other surfaces that obstruct LOS.
Hence, the very vertical, oddly shaped map I was testing it in. As you can see in the first video, the AI stopped running down the steps to heal because he had already obstructed LOS there. That spot met all of the criteria.
If they went on the offensive, the AI was much simpler (perhaps to a fault)
It would poll all actors of type ArenaCharacter within 2000 units of the AI. It would then check for LOS existing. If LOS does not exist between the enemy and the AI, the enemy is discarded. Then, once it has all enemies in LOS, it prefers enemies that are further away.
This was designed specifically for ranged caster AI that only used 2 of the original 4 spells (the other two being TEST_FlameJet and TEST_Firefield). TEST_Bloom came a lot later, but I will explain that then.
The reason the AI was built to prefer far away targets is because the caster is more likely to be able to escape a far away target than an up close target. If it could find no targets in line of sight…
Above is the “search for enemy” EQS. That’s all it does. It finds the furthest location on the pathing grid (size 1000, 1024 height) out of line of sight and goes towards it. If everything is in line of sight as far as it can tell, it will prefer the furthest spot that is in line of sight.
The logic for this basic search was that if everything is in line of sight, the furthest point is the most likely point to take you to an area with more cover and hiding spots. This is a pretty big assumption, but keep in mind, most of the areas that currently existed within the game were small, tight corridors where this assumption worked.
It would regularly get the AI caught in a loop of spots and never get out.
Those are the rest of the traits for each ability. Almost every trait on the other two slides is functional.
Let’s touch on some of the more important ones.
RawSpellID – This was a storage mechanism so that I could replicate the lookup ID in the table without needing to replicate the entire spell. I could send “PC_DruReplenish” to all clients, and then all clients knew to look up PC_DruReplenish for all effects.
Spell Logic – This was the actor that was spawned by the spell.
Casting Type – Cast, Channeled, Charged. Cast spells went off upon reaching the target cast time. Channeled spells went off multiple times throughout the cast. Charged spells could be released early with reduced effectiveness.
Disable Type – None, Silence, Disarm, Either, Both. None means the spell can always be cast. Silence means that the spell can be cast while disarmed but not while silenced. Disarm means the spell can be cast while silenced but not while disarmed. Either means that the spell cannot be cast while either disarmed or silenced. Both means that the spell cannot be cast while both disarmed AND silenced.
Aiming Type – Frame Targeted, Skill Shot, Ground Targeted, Auto Targeted, Toggled. Frame targeted requires a target of some kind. It has some smart targeting features. If you are casting a friendly-only spell while targeting an enemy, it will attempt to target the enemy’s target. If the enemy’s target is also an enemy, it will cast on you. It does this for many different circumstances. Skill Shots shoot directly ahead. Ground targeted are exactly what they sound like – Ground targeted. Auto targeted spells are generally self centered AOEs, such as tranquility. Toggled was extremely buggy and couldn’t be trusted to work in most circumstances.
Player Targeting Rules – Enemy, Friendly, Friendly (Other), Self, Either. Enemy could only be cast on enemies. Friendly could be targeted on yourself or any other friendly unit. Friendly (Other) could only be used on friendly targets besides yourself. Self could only target yourself. Either could target friend or foe. In the C++ edition, I added “Enemy or Self” to the list.
Damage Type – There were 18 damage types, although most of the types on the picture are either physical, shadow, healing, absorb, or nature. Most of the damage types, admittedly, do not have a difference in this version (outside of healing inverting the damage).
Magic Schools – This was only used for lockout purposes. Yes, interrupts existed and worked (PC_AssPommelStrike is an interrupt).
Base Cast While Moving – Can this spell be cast while moving?
CD Line Name – Most of the time, this one is “None”. But this one is sometimes set to something else. Let’s say “PC_BerRecklessness”. When you cast PC_BerRecklessness, it triggers a CD Line called “BerRageLine”. This means that ALL BerRageLine abilities are on CD for the duration. This is for situations where two or more abilities all share a CD.
CDs Also Triggered – Most of the time, this array is empty. When it isn’t, it puts all abilities listed on CD for a custom time. So, if we decided PC_BerRecklessness and PC_BerRampage shouldn’t be in the same line, but they shouldn’t be usable simultaneously, we may decide to handle it through this. We may put “PC_BerRampage” on CD for 8 seconds so that it can’t be used within 8 seconds of PC_BerRecklessness.
SelfEffects and TargetEffects do not work.
Casting Particles – I split the particles into 3 categories: Hands, body, feet. They attach to the bones at the respective positions as well.
Casting Particles Offsets – I added vector offsets to the particles for hands, body, and feet if you wish to adjust where the particle is.
Targeting Scale doesn’t work.
Damage scaling doesn’t work as levels don’t exist.
Resource cost scaling doesn’t work as levels don’t exist.
Base level doesn’t matter as you cannot acquire abilities.
Cast animation worked until I accidentally overwrote the animation sequence with a blank animation sequence during a hard drive transfer.
LookupID is the lookup ID for the spell’s damage range on the SQLite table.
IsBuilder – Some classes have abilities that spend mana and some have abilities that build mana.
IsVariableSpender – This is for abilities that do not spend a fixed amount.
SpendingIntervals – This is the amount of mana that each incremental level increases by.
MinimumSpend – This is the minimum amount that can be spent by the spell.
MaximumSpend – This is the maximum amount that can be spent by the spell.
ModifierIDs – These are effects that the game will check the caster or target for. To stick with the Berserker examples, perhaps an ability can only be cast while Recklessness is up. This is where that would be handled. Or perhaps while Recklessness is up, this specific ability costs 50% less. This is where it would be handled. The big thing is that these aren’t always necessary. On the other hand, it will return true if ONE necessary feature is found, but not if ALL necessary features are found. It is better to use AlternativeResourceID for this purpose.
Alternative Resource Spent ID – Let’s say that every time you cast PC_CleSplashHeal, it gives the cleric a stack of Divine Favor. Divine Favor stacks to 10. For some spells, Divine Favor may be required. This is where the ID of that required resource would be listed. This is separate from ModifierIDs because ModifierIDs was a very binary solution with, as mentioned in the end of the paragraph, a difficulty dealing with multiple requirements.
MinAltResource – This is the minimum amount that can be spent by the spell.
MaximumAltResource (off the end of the image) – This is the maximum amount that can be spent by the spell.
I’d like to take a few moments to talk about “ModifierIDs”, though.
That is what the modifier ID struct looks like. In it, you see 5 options:
BuffID – Indicates the ID of the buff it is looking for.
IsOptional – As mentioned earlier, if it is not optional, only one non-optional buff is required.
IsSelf – Checks self or checks target
IsPositiveBuffID – If it is a positive or negative buff ID
AbsenceRequired – If it is required to NOT be on the target.
To use an example from World of Warcraft, Paladin Blessing of Protection would have the BuffID of Forebearance (whatever that is), it would NOT be optional, it would not simply be self, it would be a positive buff ID, and absence would be required.
Here’s a short video going through some of the blueprints required to make this happen.
If you want to see them all, the source is available up at the very beginning. Hopefully you can find some use or inspiration from them. Yes, the drag-and-drop works in the inventory and spellbook. The inventory mostly works.
Here’s a short video showing how many blueprints there are total:
I chose to start working on the C++ version of the project whenever UE4.11 preview 4 was pushed into the main branch and I accidentally updated, corrupting the project for a long time (it would crash when I made any changes to the Blueprints). I would have loved to continue working on the project, but by the time this project was functional again, the new C++ project was well on its way.