Dawn of Light
The Dark Age of Camelot Server Emulator
A Dark Age of Camelot open source server emulator project written in C# started in 2003 by fans. We have created from scratch a server framework with database, packet and server logic.
The project aims were to create a framework which not only allowed for live-like behaviour but completely custom rulesets.
DOL Server - The server application
DAoC Portal - An application which allows your game client to connect to custom servers.
Uthgard - Our most successful server focusing on classic DAoC and Realm vs Realm fights in Old Frontiers.
Storm D2 - Our custom flagship server focusing on a Diablo 2 ruleset in the DAoC world.
Project News, Blogs and Code Commits
Posted 3 weeks ago
A lot of Startup Mechanisms have been updated.
You should notice updates around Character Creation Events, Game Entering Events, Player Loading Events, and other early startup mechanisms used in DOL to have a proper working shard.
- Character Creation Packet Handler is now highly revamped, using Global Constants to track legit Realm/Race/Class Combination, taking base class into account, most of scripted mechanisms are relocated to game server scripts (Startup Location, Startup Craft Skills, Starter Equipment, and other starting properties like money/level/Ra's etc...)
- The use of global constants for tracking Class and Race helped in revamping a whole part of Trainer Promoting Code...
Trainer now use mostly CharacterClass Attribute Hierarchy (keep hierarchy between your base CharacterClass and Advanced CharacterClass) and new constants to offer promoting options.
- Character Creation Revamp allowed to enable again Character Customization ! You can now safely change your base starting stats in the limit of 30 bonus points, or reshape your character face
- Updated the Behavior of DataCareer Skill Handlers when promoting from Base Class, this could leave some remaining base class skills up to now
- Starting As Base Class strongly revamped and should now work more steadily
Some Character Class Fixed to be in the class hierarchy of their base class.
- Respec Gift on specific levels relocated to game server script.
- New DatabaseEvent on Player Loaded From Database, this allow to trigger any "Fix" before the loaded data is used to create a "GamePlayer"
- New Refresh Command Util available to Admin to reload most of these new Module Static Data Cache "Lively", this could be used more generally for other properties cache...
- Tested with client 1.95, 1.109 and 1.116 for startup zone, base class match, trainer promoting, new 1.116 player race/class options are forbidden by global constants actually but can be easily enabled.
This shouldn't change your everyday experience on DOL except if I broke something badly
But you should notice better behavior of the character creation screen or easier customization around all those "Startup" Scripts !
Posted 1 month ago
Small Revamp of ServerProperties Class.
I had to build some code to list "ALL" server properties (in DB, in Runtime, in Attributes...), I made some specific methods to retrieve all this data in a dictionary, and thought it could be useful for any Dev so I've put this method in the Core Properties...
Finally adding these methods to "Properties" Static Class showed that it could be pretty easy to use it for loading and saving...
..And I updated how the Properties are initialized on server server startup to use these new methods
It only use one DB query for all loading (faster server start), the Properties are now loaded only once after scripts are compiled (there was a static constructor before...) , "slash commands" have been moved from script compilation, to be loaded after server properties ! (there is a server prop "Disabled_commands"... so we need this before loading commands !)
This shouldn't change anything in server behavior, just some startup speed-up and optimization
Posted 1 month ago
Upgrade to GameServerScript to Allow for Modular Behavior.
Revision 3394 to 3396
Main upgrades are around Compilation Assembly References that should now be automated for locally copied libraries.
This mean you can now drop-in any dependency DLL in Dawn of Light "lib" directory and they will be automatically referenced when building game server scripts.
This enable distribution of complete "Modules" through GSS, dependencies copied to "lib", sources copied to "scripts" and Runtime Compilation will enable all of this for you !
Another Feature to handle these new modules correctly is around ServerProperty, up to know they were only registering the Core Properties hard-coded in ServerProperty.Properties.
Script Manager will now trigger another lookup of all "ServerProperty" available in GameServerScript Assembly !
The Refresh Handler has been updated to reflect this behavior, thus /refresh command will now work for scripted properties too...
As an example Proof of Concept a new project "DOLNancyWeb" can be checked out, through : https://github.com/dol-leodagan/DOLNancyWeb
Simply "Download ZIP" and extract to your working Dawn of Light Directory, this will copy the necessary DLL and the according Scripts Sources to your server's "scripts" directory, next time you'll start your server you will be able to use a "Demo" Web Page embedded in DOL
New ServerProperties will be available in your database to setup this Embedded Server, no serverconfig.xml updates are needed !
Default access : http://localhost:10200/
Posted 3 months ago
This Topic is about a Huge Update of DOL Revision 3375
- If you're using a previous revision nothing applies from what is written in this topic !
- If you're having trouble with the behavior of DOL in this Revision you can still Checkout the Revision 3374
- If you need any help/support you can ask in this topic to share any solution with everyone
- If you're having trouble updating your shard, and you didn't made too much custom change, think about starting from this new Revision with a blank database
New DOL Revision enable Data-Driven Career system based on existing and new tables to describe skill awarding through player journey.
Up to now Class Skills were awarded through hard-coded C# subclass implementing level or spec constraint.
Master Levels were implemented using SpellLines only and hard-coded appending to player database record.
Champion Levels were implemented using dedicated Manager and Dynamic SpellLine initialization to append a custom ID in player record.
Realm Abilities were awarded through trainers according to a link table between class and skill, appending the skills and level to Player database "SerializedAbilities" record
New Specialization Object are now used to targets these Skill Granting, and will use records saved in database to do such.
Specialization Object Base
The base Specialization Object now have 4 important Methods :
- GetAbilitiesForLiving() // Retrieve Abilities attached to this spec
- GetSpellLinesForLiving() // Retrieve Spell Lines attached to this spec
- GetLineSpellsForLiving() // Retrieve Spells attached to this spec (will use spellLines to list Spells)
- GetStylesForLiving() // Retrieve Styles attached to this spec
These methods are used to enables Skills, Abilities, Spells, Styles for player character, they are retrieved through Player "GetAllUsableSkills" or "GetAllUsableLineSpells", for displaying through Update Skill Packet or activating through Player Skill Request Handler.
Subclassing this base Specialization Allows for enabling custom spec behaviorSpecialization Object Live Subclasses
This update comes with a small number of Specialization Subclass to enable the Live Server Behavior.
Observed Behaviors are : Trained Spec, Master Level Spec, Champion Level Spec, Hybrid / List Caster Specs, Class Career Spec, and Realm Abilities Career. The combination of given Specs can already enable a lot of Custom use which will work flawlessly with current Client implementation, other Subclass must be written Carefully to keep in mind client constraints.
- Specialization - Mother of all Classes, Handles "Level" as assigned value (Mostly through training or any other script that increment the Skill Level), provide Abilities, Styles, Spells (as List Cast) as expected for official Trainable Specialization
- UntrainableSpecialization - Base class for all Untrainable Spec (that shouldn't be displayed in Player UI or Trainer)
- LiveCareerSpecialization - Untrainable base Specialization that improves through Leveling (used for class specific Skills)
- LiveMasterLevelsSpecialization - Specialization targeted at Master Level, Merge Abilities and Styles inside List Cast Skill (Yes INDEED the client can handle Styles and Abilities INSIDE list cast "spells") Spec dependent of ML Level (incompatible with livings...), Player will use "MLLine" field as an index to choose the designated ML spec available in their career tree.
- LiveRealmAbilitiesSpecialization - Custom Specialization that build a list of Abilities out of Player "SerializedRealmAbilities" Field, this is used as an indexer for Realm Abilities chosen by player. (incompatible with livings...)
- LiveChampionsSpecialization - Hybrid Spec that build a resulting skill list depending on "MiniLineSpecs" attached to player, this is a "Grouping" Spec expecting specific Subclass to be used for MiniLineSpecs to target correctly Champions Skills depending on training and current Champion Level. (incompatible with livings...)
- MiniLineSpecialization - SubSpec, will not display or return anything to usual Methods, can retrieve a 0-base index line of Abilities/Spells/Styles that are granted through "Champion Training" (even if it's still Untrainable), Trainer will need to use the specific methods to act on "MiniLine" instead of "Trainable Spec" methods, "Master Spec" will gather skill to display them in a fitted way.
- LiveChampionsLineSpec - MiniLine Subclass, that doesn't override anything, just a base class used for sorting CL sub spec appart !
- LiveSpellHybridSpecialization - Same as base Specialization except that it delivers Lines Spells as an Hybrid List and set Hybrid flag to append these skills to global skill list (at the opposite of list cast skills which are sent with specific List Packet)
- LiveAbilitySpecialization - Unused, just a subclass that filters out every other skill except Abilities.
- LiveSpellLineSpecialization - Unused just a subclass that filters out Styles to have a Spell oriented Spec.
- LiveWeaponSpecialization- Unused just a subclass that filters out Spell to have a Style oriented Spec.
Most of Spec are just using the base "Specialization", hybrid specs are specifically targeted by the use of Hybrid Subclass (and weirdly there are pretty few Hybrid Specs...), mostly all class have their own "Career" Spec to attach their Abilities (Some Classes allowed to groud specs, like most list caster have the same Career, Light Tanks/Assassin/Tanks have similar Career in all realms...)
Master Level are pretty straightforward spec, as they are list cast they can handle common building with the constraint of having a single "SKILL" for each level...
Champion Level are a bit weirder, they gather mini spec skills and just use Level as an Index over skill list, meaning if you change anything in there and have 2 skill sharing the same index it will have "range mismatch", like Master Level they Should share a single "SKILL" for each "index" but will tolerate more errors as they are handled as Hybrid List !
Realm Abilities are totally "scripted" using a player field to gather the skills it should be granting, Trainers and Abstract Rules will have to keep handling the skill costs / acquiring and respec. it's a good area to put RR5 granting... this is an example of how Specialization can still be used to handle totally scripted Career (and send skills in the expected format for packet lib without any other code update !!)
GameLiving Compatible Specializations could be used to improve NPC code and allow them to use "Skill Tree", actually the only way to grant skills to Mobs is through NPCtemplate's list of Styles/Abilities/Spells, some specific method may even try to change skill level or other value to scale with Mob level...
Using Spec Tree for NPC will allow to easily give "Template of Skills" to mobs, which will use the granted skill to their current level (and no more scripted changes !) and will solve a lot of combat mechanisms that could try to check spec level when casting or styling... (With the downside of having to create a little overhead of link-record to attach everything correctly...)Careers Tables and Data storage
The current update moved most skill logic to database tables, most of tables where already describing Skills or Relation between them, the only "new table" is ClassXSpecialization, other tables have receive improvement to handle "missing" data that could only be guessed through hard-coded values.ClassXSpecialization
Table : Career Table describing which spec is awarded at which level, Spec can be any Specialization Subclass implementing their own levelup/training mechanisms.Specialization
Table : This table now have a "Classtype" Field allowing for custom instantiation of Specialization Objects. (Defaults to Base Specialization)SpecxAbility
Table : Retrieves abilities attached to a spec based on spec level, this is useful for Shield or Stealth Spec to grant Engage/Guard Abilities or Safe Fall Abilities depending on training, it's also massively used for "Career Spec" that will attach Abilities through player Leveling
A new "Class Hint" field is also used to tell apart which abilities should be granted to which class, this should only be used to tell apart skills in "Trainable Spec" that are shared by multiple classes, even if it can further handle any kind of Class-Split Abilities in the same spec ! (Actually only Used for Assassin's Stealth specific Skills...)
It can be used for any Specialization that need to handle Abilities in fact
(as long as they aren't filtered out...)Styles
Table : Not much change here, styles are attached to Specs using the SpecKeyName field/SpecRequiredLevel constraint, can use a "class hint" to deliver custom styles based on player class ID.
There are still a lot of "hard-coding" withing DOL to have trouble creating "Styles" Spec that aren't matched to a "Weapon Type" (For damage calc, or weapon constraint), The Critical Strike examples can be used for "Any Weapon" Styles which is enough for Champion Styles or ML Styles !SpellLine
Table : Added a Class Hint field, this will be used to match which spec line is given to which class, this was hard-coded until now, and there isn't anything to describe which class should have which spec anywhere... 0 value is used for shared baseline that should match every class, except if there is a dedicated baseline ! (Heretic/Valewalker example...)
No change around Spell table or StyleXSpell table for now...ChampSpecs
table become obsolete, Player Records like Serialized Spell Lines, Serialized CL Spells are now useless.DOLCharacters
- Player Records will now use the following for enabling skills :
- SerializedRealmAbilities - To enable chosen Career RA's
- SerializedSpecialization - To enable trained Specs, chosen CL's Skills, or other saved specs
- ML Enable - to enable ML Spec
- ML Level - to set ML Spec Training level
- ML - Index of the chosen line
- CL Level - to set CL skill point count
- RealmLevel - to set Realm Ability Skill point count
The SerializedAbilities Field is not used to enable any Skills anymore, it will be loaded before any skill displaying to get the Order in which they were granted to player, they will then be enabled/replaced/disabled according to the real player Specs...
Deleting SerializedSpecs will trigger a player Trained Specs AND CL Skill Respec.
ML can't be forcibly Respec as soon as ML are granted and a ML Level is enabled ML will default on the first ML Line.
Deleting SerializedRealmAbilities will trigger a player RA Respec and won't delete any career abilities, the serializedAbilities field should be left alone, it will be updated after player relog.Classes Career
Classes Special Skills
- Classes Specs
Classes Specs are now described in ClassXSpecialization Table, in this table you can set the required level for the spec, the class ID who will receive the spec (or 0 for all class), setting negative level or 0 level requirement will be checked againt level 1 player and enable them as Level 1 is higher than any 0 or negative value, this can be useful to enforce display order, Trainable Specs are ordered by their level requirement ! (then by ID...)
Trainers / TrainerRequest / Detail Info Request have been updated to match the new behavior of trainable spec.
This lead to some improvement in how Trainer Window is working and will now enable "Ability" display when advancing a trainable spec cursor - If you change the Level of Shield Spec in your trainer window Shield Ability will get displayed (Guard, Engage...) at the correct level they're earned, and they will display tooltip accordingly !
As the Spell Lines table now include a "Class Hint", Specialized Spell Line have been targeted to their according class to prevent adding all advanced class lines from a single Specialization (I don't want Sorcerer to get 'Matter' Spec Line from Cabalist added to their own spec line !)
- Career Specs
Career Specs are specialization that evolves with player level, this is useful to grant class abilities depending on player level and not any trained spec (Sprint/Quickcast/Berserk etc...)
In Current implementation there is a Career Spec for each Class and Base Class, Advanced Class are referencing their Base Career Spec too for completion (except some special classes like Darkness Rising that doesn't inherit all their base class abilities...)
Some class use shared "Career" like Pure Tank, Light Tank, Assassin, Pure Caster which have much in common !
- Realm Abilities Spec
Specific Spec that will behave like a Career Spec to enable all skills at the same level of player (useful to set spell lines level according to caster level without using hardcoded spell line)
This also handle the loading/saving of chosen Realm Abilities within serialized field.
GamePlayer / DOLCharacter Change
- Master Levels
Master Level spec are gained automatically at level 40. Both available lines are attached to every character, the line will be enabled based on the "MLLine" integer field being used as an "index" (MLLine 0 = first line, MLLine 1 = second line, if anyone want to customize further they can increment this value !)
These Lines will only advance and grant skills based on player MLLevel (starting from Level 1 to get first skill...)
Once ML are over Level 0 player will always receive skills based on the defaut MLLine value (the only way to remove a player ML Skills is to remove its ML status !)
Master Levels aren't Attached to any trainer or training request, they offer no "skill tree display" so they didn't need any more change to be as "much" available as they were before (meaning NONE on Storm RVR !!) With current implementation Storm RvR could just add a NPC that enable MLLine choosing (0 or 1 indexed...) and give away MLLevel for BP/Glass Token Live-Like, it won't need anymore scripting than setting these ONLY TWO fields to fully enable Master Levels !
- Champion Levels
Actually I'm not proud of the Champion implementation...
For each Champion "Base Class" there is a specific code Subclass, these code subclass are enabled through "Champion" MiniSpecLines, which means every "Champion Master Line" have 4 to 5 "Subspec" MiniLines, this add about 60 specific specialization to database.
Each Realm have its own "Champion Master Line" to enable realm-specific ability to handle base-class weapon at level 3.
This adds to the previous constraints of the ~60 mini Lines...
For Each mini Lines we will find some Spell Line (1 Ideally but there may be some need of a "Specific" Necro-based Champion Skill Line), some Styles attached, and hopefully no Abilities (as this would get a mess to handle !!)
And For Each Master Lines there is a need for an empty Spell Line that will be used for casting mini Lines ability through this master line... (which should be at player MaxLevel for damage calc !!)
MiniLines in the same "Master Line" that share exactly same skill at same level will be MERGED, this is made to mimic Live Like Champion Skill Tree... I wasn't really passionate by the Champion Lines coding, so I didn't think of any way of "Splitting" miniLines...
Anyway experiments done while updating Trainer/TrainerWindow/TrainingRequest/DisplayDetail shows that client Champion Tree Skill Display is pretty much customizable ! But for now only 2-Lines and 3-Lines Merged are handled, client hasn't been fully tested for "Weird Cases" or Other type of trees.
the main purpose around all these change is to TOTALLY move all Champion Weird Scripting into Specialization Code, so it use the same tables, work mostly the same, and all code (even if I feel that some code is pretty badly written) is in the same area of the development tree !
Gameplayer have gone through a lot of changes, methods to retrieve skills have been updated to support Data-Driven Career, some names have been change to forces script using them to update to the new behavior, Some property have been removed or made "read only" to take advantage of new computation system instead of "recorded" amount in database.
The major changes are around methods to retrieve Skills and Spells, they now return formatted collection to be handled by PacketLib or other Handlers that will retrieve the same "collection" that was sent through network (way more easier to handle the indexes exchanged between server and client this way)
I reviewed most Player skill collections (Abilities collection, styles collection, spellline collection, spec collections) so they are now properly locked when accessed in every method, they also return copied collections instead of references to the private collection when using accessors this remove the "lock" requirement in other part of the code when iterating over player skills.
Most of these collections aren't used anymore for displaying skills or enabling them (at least for GamePlayer as they are inherited from living...) the computed collection for displaying (GetAllUsable***()) is the best way to retrieve an "enabled" skill for a player !
I also removed properties handling Skill~Spec points or Realm Ability Spec points, these properties are deleted from Database and DataObject, they are not used anymore, Realm Ability Spec Points is computed through ServerRules (Realm Level == Realm Spec Points, if it's PvEServerRules level - 19 is added if player is above level 20 !), Spec skill point is now computed through the "VerifySkillPoint" method, and champion spec points is retrieved from champion Level (CL points == CL Level) and only checked in custom Champion Specialization And Training Request !
All previous "Getters" have been kept but now return the ("Total Pool of Points" - "Sum of Total Used Points"), which means no script has to take care of adding or removing point on train/respec anymore, just check that there is always enough points for the next skill "Add cost", any negative value would mean that something went wrong and a forceful respec could be needed !
With the fully Specialization implementation a lot of "Serialized" fields are also obsolete : Serialized Spell Line
is now useless, spell lines are added from Specs Skill Tree, if you want to add a custom spell line to a character : do it through a custom spec !Serialized Champion Spell
is now useless, champion spell use mini Spec Line that support "training" and "saving" through the SerializedSpecialization field !Serialized Abilities
is now useless for enabling skill, this field won't be obeyed for anything except Ability display Order !
Abilities is the only part of the Player Skill list that isn't indexed by it's level or icon or spell line, client only keep track of quick bars through the position of the Ability within the server sent list... This require to remember every Ability a player received and in which order to always get the same display, other skill list like styles, spells, list spells, have "hint mechanisms" to retrieve the according spell even if the order change between two login, but as long as abilities won't have something similar we'll have to keep it ordered in database !
An new Serialized Field is now used for Serialized Realm Abilities
, it was prepared for a long time with a beautiful comment "For Later Use", Later is today ! This field now tracks all player's Bought Realm Abilities ! This allow to forcefully respec realm by just emptying this field for EVERY record (and realm points will be computed back to normal !).
The SerializedAbilities should never be handled "humanly" anyway it won't have any effet, removing any abilities from there won't disable anything, keeping disabled abilities in there won't enable anything easier, it's just an hint for displaying !Migration
For users that were using a previous version of DOL updating to this revision can need some work !
If you're not using the given SQL File, you'll have to enter all ClassXSpecialization by hand, which mean using your own rule to grant player their trainable skills, and even granting them their Career class specific Skill is up to the data you've entered in this table !
Without record in there players won't get ANY skill tree ! (No spec to train, no Free abilities, not even sprint or ability to use Staves !!)
Granting existing specs is an easy task, the Specialization table should contains everything needed for Trainable Skills !
From their you can decide how you will give player their starting abilities, they can be attached to a trainable spec (giving Blades Ability with a Blade spec Level 1 would be a smart move, it's not how I handle it for now...), or they can be attached to a specific "Career" Spec you will create for every players or specific class and that advance with leveling (that's how I handle it in the files provided)
From their you still have to make sure your skill tree are correctly build, every spec will reference Styles (using Style ID and Spec Key Name, depending on SpecLevelRequirement) , Abilities (using SpecXAbility table with Ability Keyname, Spec Keyname, depending on SpecLevelRequirement, and using the given Ability Level), Spell Lines (using the spellline table, joining on the Spec field, you must provide according class Hint to Specific Class Spec Line for this to work correctly ! without class ID all class will receive all Spec Line, you don't want an Eldritch Mana Spec'd being able to cast Regen Power Buffs ?), finally you have to make sure lineXspell table is using the correct Spell Line Key Name, Spell ID, and Level the spell is awarded
This will need a lot of table "join" queries to have a "view" of skill tree, but it's the only way to get rid of hard coded class
The part that need the most "micro-management" are special Paths like Master Level and Champion Level, their "Skill Tree" is merged in One Single Skill Line ! So you have to make sure every skill is awarded at a single level through all table's records for this Spec !
Once you re-open the shard to players with all the according update you will need to reset the ML Line field (DOLCharacter.ML = 0), the code revision includes a Master Level Merchant (GameServerScript) that can switch ML path for 5000 bp, you can award your player base with 5000 bps for changing their line (DOLCharacter.BountyPoints = DOLCharacter.BountyPoints + 5000 WHERE ML != 0) or give them a "Star of Destiny" from the Scripted Merchant Items...
You don't need to change any other field to be fully compatible, Serialized Specialization handling will reset Champion Level Skill and any Custom lines to the ones only available in Class Career's, Serialized Abilities will be updated accordingly, a forceful RA respec will be issued due to the lack of data in Serialized Realm Abilities, and most older custom field for Spell Lines or Champion Lines will be ignored (the table can be later altered to DROP those columns !)
No player Level, Player XP, Player Realm Points, Player Skill Point, Player Champion Skill Point, Player Realm Ability Skill point etc etc... Needs ANY editing ! In fact the new Career System is some kind of "auto-healing" if the data is wrong in the player fields, and most of skill points count aren't used any more in fact. (by auto-healing it's just because the code is made to handle merge between previous data with newer skill states and can gracefully drop or add skills without hurting anything and make sure everything is granted for the level/training of the player, no more no less !)
Here are the available Records used to create "Live-Like" Careers actually used on Storm RvR, this data can be used as a starting point to implement a custom rule set, the way class are handled now enable the use of "database snapshots" to set the game state in any revision of the Live DAOC server, I hope admins will be able to make classic revision of their database, or targeting a specific client version and share it to have a bigger choice of working bases (DAOC Charplan can be a great source for implementing this)
- Setting Spell Data with unique Tooltip :
- Code: Select all
SELECT @i :=0;
UPDATE `spell` SET `TooltipId` = @i := @i +1 WHERE 1 ;
- Table exports :
- Code: Select all
ALTER TABLE `dolcharacters`
Posted 4 months ago
Finally I spent some time on looking why we couldn't have the nice "Finish Quest" Icon on DOL.
This Quest-like Icon have a blue aura to tell players that this NPC can give them a reward for a finished quest.
This doesn't work for One-Step Quest... (Obviously the regular Quest Icon can apply there if needed)
This work only for DataQuest and RewardQuest that gives Methods to know when they are finished and who is rewarding (for RewardQuest it's always the QuestGiver...)
This gives a nice feeling when completing multiple quest in the tutorial area (which is a playful area for quest of all types !) it's easy to match the quest rewarder, and maybe this get the feeling that something could be done for mid-step npc !
The patch is short and not really written to support all type of Quest, but "DataQuest"-alike should be the future for implementing quests, and could be improved to give more description on every step (which DataQuest does nicely, but RewardQuest is another story !!)
Here is the Commit Log :
- Code: Select all
Update : Improve Quest Icon Handling to allow for the "Quest Finish" Icon displaying over NPC when they allow to finish a quest.
That work for kill finishing step too, so be careful if you target too much NPC on the Last Step of a DataQuest it could spam with Finish Quest Icons over Mob Spots !
Quest Finish Icon Only works for DataQuest and RewardQuest Type, the other quest type don't allow to easily check who is the last step and when it's the last step !
Best way to test this change, build a level 1 character, test the first Tutorial Quest (DataQuest with KillFinish event on sparring guard), then test Tutorial Armory Quest (RewardQuest)
Fix : Missing update from RegionTimerResync