-
Notifications
You must be signed in to change notification settings - Fork 4
Integration & Compatibility
In this section there will be explanations of the classes, events and examples available for you to integrate your mod with LevelUP.
LevelUP works mostly on server side, and all events should be running on the EnumAppSide.Server, for security porpuses, rare situations are controlled by the client side.
Functions will generally have a reference number, so you can easily change and modify the numbers as you wish.
If you need to integrate with your mod and something is missing that you need, you can create a pull request.
Starting: Create your own mod and import the LevelUP.dll in the mod csproj
<ItemGroup>
<Reference Include="LevelUP">
<HintPath>$(VINTAGE_STORY)/Mods/LevelUP/LevelUP.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup>Now you have access to the LevelUP Events, check below
- OnExperienceIncrease
-
Player receives experience,
amountis a reference you can modify it to increase or decrease the quantity received - OnSubExperienceIncrease
-
Player receives sub experience,
amountis a reference you can modify it to increase or decrease the quantity received - OnExperienceReduced
-
Player losed experience,
amountis a reference you can modify it to increase or decrease the quantity received - OnLevelUp
-
Player leveled up, if is a sublevel that leveled up the
typevariable will come with a "/": "Smithing/Knife"
- OnPlayerMeleeDoDamageStart
-
Player does damage with meele weapon (before levelup calculations)
- OnPlayerMeleeDoDamageFinish
-
Player does damage with meele weapon (after levelup calculations)
- OnPlayerRangedDoDamageStart
-
Player does damage with ranged weapon (before levelup calculations)
- OnPlayerRangedDoDamageFinish
-
Player does damage with ranged weapon (after levelup calculations)
- OnPlayerReceiveDamageStart
-
Player receives damage (before levelup calculation, does not include equipped armors)
- OnPlayerReceiveDamageFinish
-
Player receives damage (after levelup calculations, includes equipped armors, but can be null if the damage does not belong to a entity)
- OnPlayerReceiveDamageUnkown
-
Player receives damage from a source that could not be attributed to an attacking entity
- OnPlayerToolViewStats
-
Client is about to view the tool attack power stats,
damageis a reference you can modify - OnPlayerArmorViewStats
-
Client is about to view an armor slot's stats
- OnPlayerArmorReceiveHandleStats
-
Armor slots are about to have their status handled
- OnPlayerArmorReceiveDamageStat
-
Armor slots are about to absorb damage,
damageis a reference you can modify - OnPlayerArmorViewStatsPos
-
Same as
OnPlayerArmorViewStatsbut for the positional/off-hand armor slots - OnPlayerArmorReceiveHandleStatsPos
-
Same as
OnPlayerArmorReceiveHandleStatsbut for the positional/off-hand armor slots - OnPlayerArmorReceiveDamageStatPos
-
Same as
OnPlayerArmorReceiveDamageStatbut for the positional/off-hand armor slots
- OnBowDropChanceRefresh
-
Player arrow drop chance refreshed
- OnSlingshotAimingRefresh
-
Player slingshot aiming refreshed
- OnShieldRefreshed
-
Shield status refreshed with player level
- OnKnifeHarvested
-
Player havested entity with a knife
- OnHoeTill
-
Player tilled a soil
- OnBerryForage
-
Player harvested a berry bush
- OnHarvestCrop
-
Player harvested any crop
- OnCookedSingle
-
Player cooked a single type food
- OnCookedPot
-
Player cooked a pot
- OnHammerItem
-
Player crafted any item using the hammer on anvil
- OnHammerSmith
-
Player split the item on anvil
- OnPanning
-
Player panned
- OnSmithingItem
-
Player crafted any item
- OnSmithingArmor
-
Player crafted any armor
- ExecuteSmithItemCraftedCalculations
-
Execute the smithing craft calculations for a ItemStack and return it
- OnMiningOre
-
Player breaked any ore
Note
The bow/spear aiming-penalty-by-level logic (previously exposed as LevelBowEvents.OnBowAimingRefresh and LevelSpearEvents.OnSpearAimingRefresh) was moved into an internal Harmony patch (LevelUP.Server.OverwriteAimingAccuracy, reading Configuration.BowGetMovePenaltyReductionByLevel/Configuration.SpearGetMovePenaltyReductionByLevel). These events no longer exist and there is currently no public hook to intercept aiming penalty calculations.
- GetExperience
-
Returns the player experience from a level type
- GetSubExperience
-
Returns the player sub experience from a level type and sub level type
- IncreaseExperience
-
Increase a player experience from a level type and action or amount
- IncreaseSubExperience
-
Increase a player experience from a level type, sub level type and amount
You can access all levelup calculation by using the class LevelUP.Configuration
You can access all levelup loaded configuration values by using the class LevelUP.Configuration, both client and server is sync with the configs.
Note: the mod no longer ships its default configuration as JSON files under assets/levelup/config/. Defaults are hardcoded directly in LevelUP.Configuration and the effective config is generated/persisted at runtime under the game's data folder (ModConfig/LevelUP/config/...), not inside the mod's assets.
LevelUP.Server.LevelSmithing.ExecuteSmithItemCraftedCalculations
This function is called everytime a player craft any item, if for some reason the player use the same item to craft the tool or armor it will be ignored by smithing level, levelup also checks for the attribute "repaired" if is true it will be ignored. (Also put the attribute repaired_by to understand who you are)
LevelUP only changes the durability of item, because if you change the attack power and mining speed it will change for all tools of that type, for example if levelup changes for "game:copper-axe" ALL copper axes will have that status, because of this reason levelup create 2 new attributes for storing this status: attackpower and miningspeed, now the levelup will handle the damage in CollectibleObject.GetAttackPower and the mining speed on CollectibleObject.GetMiningSpeed.
Important
Armor and shield bonuses are no longer driven by base attributes stored on the ItemStack. There is no BaseFlatDamageReduction, BaseRelativeProtection, BaseHealingEffectivness, BaseHungerRate, BaseRangedWeaponsAccuracy, BaseRangedWeaponsSpeed, BaseWalkSpeed, BasePassiveProjectile, BaseActiveProjectile, BasePassive, BaseActive, BaseProjectileDamageAbsorption or BaseDamageAbsorption attribute anymore.
Today these bonuses are calculated purely from the player's current level, read directly from Entity.WatchedAttributes (e.g. LevelUP_Level_LeatherArmor, LevelUP_Level_Shield) and passed through per-level Configuration functions, for example:
- Armor:
Configuration.LeatherArmorRelativeProtectionMultiplyByLevel(level)(and the equivalent function for each armor type: Chain, Brigandine, Lamellar, Plate, Scale) - Shield:
Configuration.ShieldGetPassiveProjectileByLevel(level),ShieldGetActiveProjectileByLevel(level),ShieldGetPassiveByLevel(level),ShieldGetActiveByLevel(level),ShieldGetProjectileDamageAbsorptionByLevel(level),ShieldGetDamageAbsorptionByLevel(level)
Smithing still writes one attribute back to the crafted ItemStack: LevelUP_Smithing_StatsMultiply (a float, stored as a culture-invariant string), which is an extra multiplier applied on top of the level-based calculation above for items crafted by a smith with bonus stats. There is no per-armor-type "Base*" attribute to set manually anymore.
LevelUP store some watched attributes so client can easily view their levels. (Changing these watched attributes will have no effect to the server this is only for client visual)
-
LevelUP_{levelType}(long) -
Stores the experience the player has with the level
-
LevelUP_{levelType}_Sub_{subLevelType}(long) -
Stores the experience the player has with the sub level
-
LevelUP_Level_{levelType}(int) -
Stores the current level the player has
-
LevelUP_Level_{levelType}_Sub_{subLevelType}(int) -
Stores the current sub level the player has
LevelUP_{levelType}_MiningSpeed (float)-
Stores the player LEVEL mining speed increase, so it can handle easily the animation of mining speed
-
LevelUP_Level_{levelType}_RemainingNextLevelPercentage(float) -
Stores the player remaining in percentage for the next level 0 -> 100
- CommunicationChannel
-
Communication channel used to send data to the client
- UpdatePlayerLevels
-
Force refresh player levels and status
- ResetPlayerLevels
-
Reduce all player levels, reduce only the level progress (experience towards the next level, not the level itself).
overwriteLoseis the fraction of that progress that is actually lost:0.2-> 20% lose rate,0.5-> 50% lose rate,0.8-> 80% lose rate. Pass-1(the default) to useConfiguration.hardcoreLosePercentageinstead of a custom value.
Register your new level
LevelUP.Configuration.RegisterNewLevel("MyCustomLevel");
LevelUP.Configuration.RegisterNewLevelTypeEXP("MyCustomLevel", (exp) =>
{
Console.WriteLine("My custom exp levels calculation");
return 0;
});
LevelUP.Configuration.RegisterNewEXPLevelType("MyCustomLevel", (level) =>
{
Console.WriteLine("My custom function to get currently exp from level");
return 0;
});
LevelUP.Configuration.RegisterNewMaxLevelByLevelTypeEXP("MyCustomLevel", 999);
foreach (string playerClass in LevelUP.Configuration.ClassExperience.Keys)
LevelUP.Configuration.RegisterNewClassLevel(playerClass, "MyCustomLevel", 1.0f);Now you can use the function LevelUP.Server.Experience.IncreaseExperience(player, "MyCustomLevel", amount) to increase player experience
Force reduce all experience
public override void StartServerSide(ICoreServerAPI api)
{
LevelUP.Server.ExperienceEvents.OnExperienceIncrease += LevelUPOnExperienceIncreased;
}
private void LevelUPOnExperienceIncreased(IPlayer player, string type, ref ulong amount)
{
amount = (ulong)Math.Round(amount * 0.5);
}Notification when player level up
public override void StartServerSide(ICoreServerAPI api)
{
LevelUP.Server.ExperienceEvents.OnLevelUp += LevelUPOnLevelUp;
}
private void LevelUPOnLevelUp(IPlayer player, string type, ulong exp, int level)
{
if (player is IServerPlayer serverPlayer)
{
serverPlayer.SendMessage(0, "Congratulations another levelup notification", EnumChatType.Notification);
}
}Shenanigans cannot do melee damage
public override void StartServerSide(ICoreServerAPI api)
{
LevelUP.Server.OverwriteDamageInteractionEvents.OnPlayerMeleeDoDamageFinish += LevelUPOnPlayerMeleeDoDamageFinish
}
private void LevelUPOnPlayerMeleeDoDamageFinish(IPlayer player, DamageSource damageSource, ref float damage)
{
if (player.PlayerName == "Shenanigans")
{
damage = 0;
}
}Disable axe levels when a player reach 1000 blocks
private static ICoreServerAPI serverAPI;
public override void StartServerSide(ICoreServerAPI api)
{
serverAPI = api
LevelUP.Server.ExperienceEvents.OnExperienceIncrease += LevelUPOnExperienceIncreased;
}
private void LevelUPOnExperienceIncreased(IPlayer player, string type, ref ulong amount)
{
var posX = player.Entity.Pos.X - serverAPI.World.DefaultSpawnPosition.X;
var posZ = player.Entity.Pos.X - serverAPI.World.DefaultSpawnPosition.Z;
if (posX > 1000)
LevelUP.Configuration.enableLevelAxe = false;
if (posZ > 1000)
LevelUP.Configuration.enableLevelAxe = false;
}-
Custom LevelCreate any icon in your projectassets/levelup/textures/levelname.png, if icon is not provided will not be show in level view
public static int GlobalGetLevelByEXP(ulong exp)
{
double baseExp = 100.0;
double multiplier = 0.1;
if (multiplier <= 1.0)
{
return (int)(exp / baseExp);
}
double expDouble = exp;
double level = Math.Log((expDouble * (multiplier - 1) / baseExp) + 1) / Math.Log(multiplier);
return Math.Max(0, (int)Math.Floor(level));
}
public override void StartServerSide(ICoreServerAPI api)
{
foreach (string playerClass in LevelUP.Configuration.ClassExperience.Keys)
LevelUP.Configuration.RegisterNewClassLevel(playerClass, "Global", 1.0f);
LevelUP.Configuration.RegisterNewLevel("Global");
LevelUP.Configuration.RegisterNewLevelTypeEXP("Global", GlobalGetLevelByEXP);
LevelUP.Configuration.RegisterNewMaxLevelByLevelTypeEXP("Global", 999);
LevelUP.Server.ExperienceEvents.OnExperienceIncrease += LevelUPOnPlayerExperienceIncrease;
}
private void LevelUPOnPlayerExperienceIncrease(IPlayer player, string type, ref ulong amount)
{
if (type != "Global")
{
// Increase global levels
LevelUP.Server.Experience.IncreaseExperience(player, "Global", amount);
}
}-
Custom Armor TypeThe best example you can get is literally on the mod codes LevelLeatherArmor.cs, all you need is inside it, you can copy all the code change the name to the type you want. of course you need to callPatch()andInit()functions in serverside and change the configurations. (Instance.api is ICoreServerAPI) -
Custom Weapon TypeThe same way as theCustom Armor Typeyou can simple get any example in LevelAxe.cs