How I Hooked a Vanilla Drakeling Without Remapping It
Where We Were Stuck
The hardest part of this mod was not the XP logic itself.
The real problem was this: we did not have a clean way to know when the important vanilla buff events were happening.
Until that part clicked, the rest of the implementation did not really matter.
What Helped
Vanilla assets checked:
ShoulderDragon_Character_BPBuff_ShoulderDragonCheckXPBuff_ShoulderDragonMountedWeapShoulderDragon
Reviewing those was useful to understand the shoulder flow, but it did not immediately give a clean extension point.
Dead Ends First
- Remap or Drakeling replacement. Rejected early.
- Working only inside
ShoulderDragon_Character_BP. Useful for understanding the lifecycle, but not as the shipping solution. - Looking for a clean global event from the player pawn. I investigated it, but no clear hook showed up.
- Timer polling. It could have worked, but I preferred to avoid it.
What was useful in the vanilla BP was confirming that the shoulder mounted cycle went through:
BPOnSetMountedDinoBPOnClearMountedDino
The Turning Point
The useful shift was stopping the search on the Drakeling side and moving to the player side instead.
A player buff can listen for other buff activity:
BPNotifyOtherBuffActivatedBPNotifyOtherBuffDeactivated
That was the bridge.
Once the detector buff was placed on the player and those notifications were enabled, it became possible to detect when the player gained Buff_ShoulderDragonMounted and react there.
Final Architecture
The final implementation uses two custom buffs.
1. Player detector buff
Content/Core/Buffs/Buff_Player_DrakelingDetector
It does this:
- lives on the player
- listens for the vanilla mounted Drakeling buff
- resolves the Drakeling through
BuffDamageCauser - applies or removes the custom XP buff on the Drakeling
For it to work, these flags have to be enabled:
bUseBPNotifyOtherBuffActivatedbUseBPNotifyOtherBuffDeactivated
2. Drakeling XP buff
Content/Core/Buffs/Buff_DrakelingTamedXPMultiplier
It does this:
- lives on the Drakeling
- listens to
BPNotifyExperienceGained - filters
XP_TAMEDKILLandXP_UNCLAIMEDKILL - computes the restored amount from
ExpectedExpGain * NonWildKillXPMultiplier - handles the XP restore logic on the Drakeling side
Making It Automatic
Once the flow worked manually, the next step was getting rid of the manual part. For that I used:
Content/Core/Data/PrimalGameData_BP_DrakelingTamedXPMultiplierContent/Core/Data/ModDataAsset_DrakelingTamedXPMultiplierContent/Core/Singleton_ApplyPlayerDrakelingDetector
What had to be in place:
ModDataAssetneeded theAdditional Default Buffsentry- it had to target the player pawn
- and
PrimalGameDatahad to actually reference thatModDataAsset
The lesson here was pretty clear: if the correct PrimalGameData is not actually in use, the default buff system looks broken even when it is not.
Later I hit the real limitation of that route: Additional Default Buffs is fine for new spawns and respawns, but a survivor that is already alive when the mod comes online will not automatically receive the detector.
Before landing on the final fix, I also investigated a world-buff bootstrap route through AdditionalWorldBuffDefinitions. I did not end up shipping that route because I could not get it working reliably enough. It may still be a valid path, but I did not have the knowledge to close that implementation properly at the time.
That is why the published bootstrap ended up adding a singleton through:
ModDataAsset -> ServerExtraWorldSingletonActorClasses
The singleton checks logged-in characters and applies Buff_Player_DrakelingDetector if it is missing, so the mod no longer depends on a death/respawn cycle to become active for existing players.
Config
The config ended up in its own GameUserSettings.ini section:
[DrakelingTamedXPMultiplier]
NonWildKillXPPercent=50
I went with TryGetIntOptionIni and an integer percent because it created a cleaner separation between:
- missing key
0as an explicit disable100as full restoration
One Extra DevKit Problem
There was also an annoying publishing issue: the uploader gave a generic error, but the real problem was the icon image.
It was not the gameplay logic. It was the icon asset and the uploader constraints.
In this case, the image could not be larger than 1000x1000, and I was trying to upload a 1024x1024 image.
Related Posts
- Project overview: Drakeling Tamed XP Multiplier
- Short reusable note: ASA Quick Note: Detecting a vanilla shoulder buff with BPNotifyOtherBuffActivated