Lusamine.DamageCalc
1.3.0
dotnet add package Lusamine.DamageCalc --version 1.3.0
NuGet\Install-Package Lusamine.DamageCalc -Version 1.3.0
<PackageReference Include="Lusamine.DamageCalc" Version="1.3.0" />
<PackageVersion Include="Lusamine.DamageCalc" Version="1.3.0" />
<PackageReference Include="Lusamine.DamageCalc" />
paket add Lusamine.DamageCalc --version 1.3.0
#r "nuget: Lusamine.DamageCalc, 1.3.0"
#:package Lusamine.DamageCalc@1.3.0
#addin nuget:?package=Lusamine.DamageCalc&version=1.3.0
#tool nuget:?package=Lusamine.DamageCalc&version=1.3.0
Lusamine.DamageCalc
A Pokémon damage calculator library for .NET 10, supporting generations 1 to 9. Ported from @smogon/calc.
Installation
dotnet add package Lusamine.DamageCalc
Quick start
using Lusamine.DamageCalc;
using Lusamine.DamageCalc.Data;
// 1. Create a generation data context
var gen = DataIndex.Create(9); // gen 9 (Scarlet/Violet)
// 2. Build attacker, defender, and move
var attacker = new Pokemon(gen, "Gengar", new State.Pokemon {
Item = "Life Orb",
Nature = "Modest",
Evs = new StatsTableInput { Spa = 252 },
Boosts = new StatsTableInput { Spa = 3 },
});
var defender = new Pokemon(gen, "Chansey", new State.Pokemon {
Item = "Eviolite",
Nature = "Bold",
Evs = new StatsTableInput { Hp = 100, Spd = 100 },
Boosts = new StatsTableInput { Spd = 1 },
});
var move = new Move(gen, "Sludge Bomb");
// 3. Calculate
var result = Calc.Calculate(gen, attacker, defender, move);
Console.WriteLine(result.Desc());
// +3 252+ SpA Life Orb Gengar Sludge Bomb vs. +1 100 HP / 100 SpD Eviolite Chansey:
// 204-242 (30.6 - 36.3%) -- 52.9% chance to 3HKO
Console.WriteLine(result.Range()); // (204, 242)
Core concepts
Generations (1 to 9)
Each calculation is scoped to a generation. Create one with DataIndex.Create(int gen). The object is cheap to cache:
var gen4 = DataIndex.Create(4);
var gen9 = DataIndex.Create(9);
The bundled JSON data covers all Pokémon, moves, items, abilities, types, and natures for every generation.
Pokemon
var p = new Pokemon(gen, "Garchomp", new State.Pokemon {
Level = 50,
Nature = "Jolly",
Ability = "Rough Skin",
Item = "Choice Scarf",
Evs = new StatsTableInput { Atk = 252, Spe = 252, Hp = 4 },
Ivs = new StatsTableInput { Spa = 0 }, // dump SpA
Boosts = new StatsTableInput { Atk = 1 }, // +1 after a Dragon Dance
Status = "brn", // "brn" | "par" | "slp" | "frz" | "psn" | "tox"
CurHP = 150, // current HP (defaults to max)
TeraType = "Dragon", // Gen 9 Terastallization
});
Gen 1/2 note: use Ivs with Spc for the Special stat, or set DVs directly—the HP DV is derived automatically.
Move
// Normal move
var move = new Move(gen, "Earthquake");
// Z-Move
var zMove = new Move(gen, "Wood Hammer", new State.Move { UseZ = true });
// Max Move / G-Max Move
var maxMove = new Move(gen, "Flamethrower", new State.Move { UseMax = true });
// Critical hit
var crit = new Move(gen, "Surf", new State.Move { IsCrit = true });
// Multihit override (force 5 hits for Bullet Seed)
var fiveHit = new Move(gen, "Bullet Seed", new State.Move { Hits = 5 });
// Stat overrides (e.g. Tera Blast Physical)
var teraBlast = new Move(gen, "Tera Blast", new State.Move {
Overrides = new DamageCalc.Data.MoveData { Category = "Physical" }
});
Field
var field = new Field(new State.Field {
GameType = GameTypes.Doubles, // "Singles" (default) | "Doubles"
Weather = "Rain", // "Sun" | "Rain" | "Sand" | "Hail" | "Snow"
Terrain = "Electric", // "Electric" | "Grassy" | "Misty" | "Psychic"
AttackerSide = new State.Side {
IsHelpingHand = true,
IsTailwind = true,
},
DefenderSide = new State.Side {
IsSR = true, // Stealth Rock
Spikes = 1, // 1 to 3 layers
IsLightScreen = true,
IsReflect = false,
IsSeeded = true, // Leech Seed
IsFriendGuard = true, // Doubles ally reduction
},
});
Result
var result = Calc.Calculate(gen, attacker, defender, move, field);
// Damage range
(int min, int max) range = result.Range(); // (204, 242)
// Full description string
string desc = result.Desc(); // default % notation
string descPx = result.FullDesc("px"); // pixel notation
// KO chance
var ko = result.Kochance();
Console.WriteLine($"{ko.chance:P1} chance to {ko.n}HKO — {ko.text}");
// Recoil / recovery
var recoil = result.Recoil(); // (double[] recoil, string text)
var recovery = result.Recovery(); // (double[] recovery, string text)
// Access the post-calc state
result.Attacker.Boosts.Spa; // may be modified by e.g. Meteor Beam
result.Field.DefenderSide.IsReflect; // false after Brick Break
Doubles
var field = new Field(new State.Field { GameType = GameTypes.Doubles });
// Spread moves hit all adjacent: pass field to trigger spread damage reduction
var result = Calc.Calculate(gen, attacker, defender, new Move(gen, "Earthquake"), field);
Caching generations
DataIndex.Create parses JSON each call. Cache instances for performance:
// Application startup
private static readonly Dictionary<int, IGeneration> Gens =
Enumerable.Range(1, 9)
.ToDictionary(g => g, DataIndex.Create);
// Usage
var result = Calc.Calculate(Gens[9], attacker, defender, move);
Stat calculator
using DamageCalc;
using DamageCalc.Data;
var gen = DataIndex.Create(9);
int speed = Stats.CalcStat(gen, StatId.Spe, baseSpeed: 130, iv: 31, ev: 252, level: 50, nature: "Jolly");
Custom move/species data
Pass your own data tables to DataIndex.Create to override moves or species for custom game modes:
// Example: give Splash 200 base power
var customMoves = JsonDataLoader.GetMovesTable(9);
// (modify the table as needed)
var gen = DataIndex.Create(9, customMoves, JsonDataLoader.GetSpeciesTable(9));
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.Text.Json (>= 10.0.8)
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.