### Asset Path Examples Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/mod-package.md Concrete examples demonstrating the conversion from a file's location within the mod folder to its asset path reference. ```text mods/example/text/champion.i18n -> asset/example/text/champion mods/example/icons/eagle_skill.png -> asset/example/icons/eagle_skill mods/example/ui/layout/test_popup.ui -> asset/example/ui/layout/test_popup ``` -------------------------------- ### Aseprite File Path Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/assets-and-sprite-sheets.md Example of a base Aseprite file path used in mods. ```text mods/example/champions/fire_mage.aseprite ``` -------------------------------- ### Mod Folder Structure Example Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/mod-package.md This illustrates a typical folder structure for a mod, including essential files like mod info and assets. ```text mods/example/ mod.mod_info mod.override_info thumbnail.png preview.png example.dll champion/ eagle.data_champion text/ champion.i18n item.i18n ui.i18n icons/ eagle_skill.png eagle_skill2.png eagle_ult.png sprite/ eagle.png eagle.aseprite spell_icons#sheet.png spell_icons#data.sprite_sheet ui/ layout/ test_popup.ui ``` -------------------------------- ### Basic Mod Initialization Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md This is the typical starting point for a native DLL mod, importing necessary items from the `mod_api` crate. ```rust use mod_api::*; ``` -------------------------------- ### Example Mod Folder Structure Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/README.md Illustrates the typical directory layout for a simple champion mod, including essential files like mod info, data, text, and assets. ```text my_mod/ mod.mod_info thumbnail.png champion/ my_champion.data_champion text/ champion.i18n icons/ my_champion_skill.png my_champion_skill2.png my_champion_ult.png champions/ my_champion.aseprite ``` -------------------------------- ### Asset Path Examples Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/asset-overrides-and-i18n.md Illustrates how file paths within a mod folder are converted to asset paths. These paths are used in data files, native code, and override rules. ```text mods/example/text/ui.i18n -> asset/example/text/ui mods/example/icons/q.png -> asset/example/icons/q ``` -------------------------------- ### Projectile Name Matching Example Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion-schema/visual-bindings.md Illustrates how a projectile's name must match the binding name for projectile visuals. ```json { "effect": { "type": "LinearProjectile", "name": "fire_skill", "speed": 4200, "range": 65000 }, "view_projectiles": [ { "type": "Sprite", "name": "fire_skill", "sprite": "asset/my_mod/projectiles/fire_skill" } ] } ``` -------------------------------- ### DataActionDef Example Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion-schema/actions.md This JSON object defines a 'skill' action for a champion. It specifies properties like duration, cooldown, range, casting behavior, and the associated visual effect. ```json { "action_name": "skill", "description": "#asset/my_mod/text/champion?description.my_mod_fire_mage.skill", "duration": 20, "cooltime": 240, "start_timing": 10, "cancelable": true, "range": 65000, "growth_range": 0, "casting_type": "Direction", "casting_target": "Enemy", "attack_type": "Skill", "can_use_with_move": false, "effect": { "type": "LinearProjectile", "name": "fire_skill", "speed": 4200, "range": 65000, "applied_target": "Enemy", "applied_effects": [] } } ``` -------------------------------- ### Example Workshop ID File for Database Packs Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md This file stores the Workshop ID for a database pack. It is automatically created on the first upload and is used to identify the Workshop item for future updates. ```text my_database_pack/ database_pack.workshop_id ``` -------------------------------- ### Example Data-Only Champion Configuration Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion.md This JSON defines a complete data-only champion, including its stats, abilities, and visual effects. It serves as a template for creating new champions or modifying existing ones. ```json { "id": "my_mod_fire_mage", "category": "Magician", "tags": ["AP", "Range"], "sprite": "asset/base/aseprite_resources/champions/pyromancer", "anim_prefix": "", "skill_icons": [ "asset/my_mod/icons/fire_mage_skill", "asset/my_mod/icons/fire_mage_skill2", "asset/my_mod/icons/fire_mage_ult" ], "stat": { "attack": 40, "magic_power": 65, "hp": 620, "defence": 20, "magic_resistance": 30, "move_speed": 1050, "hp_regen": 2, "stack": 0, "crit_chance": 0 }, "growth": { "attack": 3, "magic_power": 7, "hp": 75, "defence": 3, "magic_resistance": 3, "move_speed": 0, "hp_regen": 1, "stack": 0, "crit_chance": 0 }, "attack": { "action_name": "attack", "duration": 18, "cooltime": 60, "start_timing": 10, "cancelable": true, "range": 52000, "casting_type": "Targeting", "casting_target": "Enemy", "attack_type": "BaseAttack", "effect": { "type": "TargetProjectile", "speed": 4500, "name": "fire_mage_attack", "applied_target": "Enemy", "applied_effects": [ { "effect": { "type": "Attack", "damage": 0, "attack_ratio": 100 }, "casting_type": "Targeting" } ] } }, "skill": { "action_name": "skill", "description": "#asset/my_mod/text/champion?description.my_mod_fire_mage.skill", "duration": 20, "cooltime": 240, "start_timing": 10, "range": 65000, "casting_type": "Direction", "casting_target": "Enemy", "attack_type": "Skill", "effect": { "type": "LinearProjectile", "penetrate": true, "speed": 4200, "range": 65000, "name": "fire_mage_skill", "shape": { "Circle": { "radius": 8000 } }, "applied_target": "Enemy", "applied_effects": [ { "effect": { "type": "ApAttack", "damage": 50, "attack_ratio": 80 }, "casting_type": "Targeting" } ] } }, "skill2": { "action_name": "skill2", "description": "#asset/my_mod/text/champion?description.my_mod_fire_mage.skill2", "duration": 16, "cooltime": 360, "start_timing": 8, "range": 0, "casting_type": "None", "casting_target": "AllyOnlySelf", "attack_type": "Skill", "effect": { "type": "AddCasterBuff", "buff_state": { "name": "fire_focus", "duration": { "Time": { "tick": 180 } }, "magic_power": 20, "skill_cooldown_mult": 15 } } }, "ult": { "action_name": "ult", "description": "#asset/my_mod/text/champion?description.my_mod_fire_mage.ult", "duration": 25, "cooltime": 900, "start_timing": 12, "range": 42000, "casting_type": "None", "casting_target": "Enemy", "attack_type": "Skill", "effect": { "type": "RangeEffect", "shape": { "Circle": { "radius": 42000 } }, "target": "Enemy", "apply_type": "AroundCaster", "effects": [ { "type": "Combine", "effects": [ { "type": "ApAttack", "damage": 120, "attack_ratio": 100 }, { "type": "Stun", "duration": 45 } ] } ] } }, "view_projectiles": [ { "type": "Sprite", "name": "fire_mage_attack", "sprite": "asset/base/sprite/arrow" }, { "type": "Sprite", "name": "fire_mage_skill", "sprite": "asset/base/sprite/arrow" } ] } ``` -------------------------------- ### EntityStat JSON Example Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion-schema/buffs-and-stats.md Defines the base stats for an entity. All fields should be explicitly set for clarity and stability in mods. ```json { "attack": 40, "magic_power": 65, "hp": 620, "defence": 20, "magic_resistance": 30, "move_speed": 1050, "hp_regen": 2, "stack": 0, "crit_chance": 0 } ``` -------------------------------- ### Example Cargo.toml for Mod Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md A sample `Cargo.toml` file for a Rust mod using external crates like `rand` and `serde_json`. Note that `mod-api` should not be added to dependencies. ```toml [package] name = "my_mod" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] rand = "0.8" serde_json = "1.0" ``` -------------------------------- ### Example Workshop ID File for Mods Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md This file stores the Workshop ID for a mod. It is automatically created on the first upload and is used to identify the Workshop item for future updates. ```text my_mod/ mod.workshop_id ``` -------------------------------- ### Champion Animation Sprite Sheet Tags Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/assets-and-sprite-sheets.md Example tags for a champion animation sprite sheet. ```text idle run attack skill skill2 ult dead ``` -------------------------------- ### Effect Name Matching Example Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion-schema/visual-bindings.md Demonstrates how an effect's name must match the binding name for ViewEffect. ```json { "effect": { "type": "ViewEffect", "name": "fire_burst" }, "view_effects": [ { "type": "Animation", "name": "fire_burst", "anim": "asset/my_mod/effects/fire", "tag": "burst" } ] } ``` -------------------------------- ### Skill Icon Sprite Sheet Tags Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/assets-and-sprite-sheets.md Example tags for a skill icon sprite sheet. ```text fire_skill fire_skill2 fire_ult ``` -------------------------------- ### Custom Skill Animation Tag Example Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion.md Example of how to specify a custom animation tag for a 'skill' action. The 'action_name' in the data should match a tag in your sprite's animation data (e.g., in Aseprite or a .fanim file). ```json { "action_name": "fire_cast" } ``` -------------------------------- ### Handle Mod Command and Emit Event (Server) Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md Server-side implementation to handle incoming mod commands and emit events back to the command sender. This example processes a 'mark_seen' command and sends a 'mark_seen_done' event. ```rust impl ModServerExtension for MyServerExtension { fn handle_command(&self, ctx: &mut ServerModContext, command: &ModServerCommand) -> ModServerCommandResult { if command.command != "mark_seen" { return ModServerCommandResult::Pass; } if let Some(team_id) = command.sender_team_id { ctx.database.mod_save_data.set_string(MOD_ID, "last_command_team", team_id.to_string()); } ctx.emit_event_to_command_sender(command, "mark_seen_done", command.payload.clone()); ModServerCommandResult::Handled } } ``` -------------------------------- ### Mod Save Data Version Migration Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/mod-save-data.md This example shows how to check the current version of a mod save data namespace and perform migrations if the version is below a certain threshold. It sets a new string value and updates the namespace version. ```rust let version = data.mod_save_version(MOD_ID); if version < 1 { data.mod_save_set_string(MOD_ID, "initialized", "true"); data.mod_save_set_version(MOD_ID, 1); } ``` -------------------------------- ### Example Published File ID Response Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md This JSON object shows the published file ID returned after a successful upload to the Steam Workshop. This ID is crucial for managing the uploaded item. ```json { "published_file_id": 3725617184 } ``` -------------------------------- ### Emit Server Events to Different Targets Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md Examples of emitting server events to various targets including broadcast, specific players, teams, or the command sender. Use targeted events for specific communication needs. ```rust ctx.emit_event("broadcast_event", vec![]); ctx.emit_event_to_player(PlayerId(0), "player_event", vec![]); ctx.emit_event_to_team(team_id, "team_event", vec![]); ctx.emit_event_to_command_sender(command, "reply_event", vec![]); ``` -------------------------------- ### Rust Custom Skill Action and Effect Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md Defines a custom skill action (`MySkill`) and its associated effect (`MySkillEffect`). This example demonstrates implementing `ModAction` for skill properties like name, duration, cooldown, and targeting, and `ModEffectType` for applying damage to a target. Requires `Clone` derivation for actions that are cloned by the game. ```rust #[derive(Clone, Debug)] struct MySkill; impl ModAction for MySkill { fn clone_box(&self) -> Box { Box::new(self.clone()) } fn action_name(&self) -> &str { "skill" } fn duration(&self) -> usize { 18 } fn cooltime(&self, _stat: &EntityStat, _level: usize) -> usize { 240 } fn casting_target(&self) -> CastingTarget { CastingTarget::Enemy } fn effect(&self) -> Option { Some(ModEffect { range: 65000, growth_range: 0, start_timing: 10, casting: CastingType::Targeting, target: CastingTarget::Enemy, attack_type: AttackType::Skill, effect_type: Box::new(MySkillEffect), }) } } #[derive(Debug)] struct MySkillEffect; impl ModEffectType for MySkillEffect { fn apply(&self, ctx: &mut GameCtx, _rng_seed: u64, caster_id: usize, input: InputTarget) { let InputTarget::Target { target_id } = input else { return; }; let damage = ctx.get_entity(caster_id) .map(|caster| 50 + caster.stat().magic_power) .unwrap_or(50); ctx.deal_damage(caster_id, target_id, 0, damage, AttackType::Skill); } fn expected_damage(&self, caster_stat: &EntityStat) -> (usize, usize) { (0, 50 + caster_stat.magic_power) } } ``` -------------------------------- ### Externally Tagged Enum Example (Unit) Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion-schema/index.md Example of an externally tagged enum where unit values are represented as strings. ```json "Targeting" ``` -------------------------------- ### Externally Tagged Enum Example (Object) Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion-schema/index.md Example of an externally tagged enum where enum values with fields are represented as objects. ```json { "Time": { "tick": 180 } } ``` -------------------------------- ### Internally Tagged Effect Example Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion-schema/index.md Example of an internally tagged effect type, commonly used for data champion effects. ```json { "type": "LinearProjectile", "name": "fire_skill", "speed": 4200, "range": 65000 } ``` -------------------------------- ### Build Simple Rust Mod with SDK Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md Execute the `build_mod.bat` script from the `mod-sdk` directory, providing the path to your single `src/lib.rs` file for simple mods. ```bash cd mod-sdk build_mod.bat path\to\your_mod\src\lib.rs ``` -------------------------------- ### Database Lookups with `data.db()` Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md Demonstrates how to obtain a database borrow using `data.db()` for multiple lookups of team, athlete, match, and champion information. This is efficient when performing several data retrievals. ```rust let db = data.db(); let team = db.team(team_id); let athlete = db.athlete(athlete_id); let match_info = db.normal_match(match_id); let champion = db.champion_info("fighter"); ``` -------------------------------- ### Minimal Champion File Structure Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion-schema/champion-file.md Defines the essential fields for a champion, including ID, category, tags, base stats, growth stats, and core actions (attack, skill, skill2). The 'ult' action is optional. ```json { "id": "my_mod_fire_mage", "category": "Magician", "tags": ["AP", "Range"], "stat": { "attack": 40, "magic_power": 65, "hp": 620, "defence": 20, "magic_resistance": 30, "move_speed": 1050, "hp_regen": 2, "stack": 0, "crit_chance": 0 }, "growth": { "attack": 3, "magic_power": 7, "hp": 75, "defence": 3, "magic_resistance": 3, "move_speed": 0, "hp_regen": 1, "stack": 0, "crit_chance": 0 }, "attack": { "action_name": "attack" }, "skill": { "action_name": "skill" }, "skill2": { "action_name": "skill2" }, "ult": { "action_name": "ult" } } ``` -------------------------------- ### Running the Mod Uploader Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md Execute 'TFM2ModUploader.exe' from the game folder to launch the Steam Workshop publishing tool. Ensure it's located alongside game executables and Steam DLLs. ```text TFM2ModUploader.exe ``` -------------------------------- ### DataBuffStateDef JSON Example Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion-schema/buffs-and-stats.md Defines the state of a buff applied to an entity. Only the 'name' field is strictly required by the Rust struct; others have defaults. ```json { "name": "fire_focus", "duration": { "Time": { "tick": 180 } }, "attack": 0, "attack_mult": 0, "magic_power": 20, "magic_power_mult": 0, "defence": 0, "defence_mult": 0, "hp": 0, "hp_mult": 0, "hp_regen": 0, "magic_resistance": 0, "magic_resistance_mult": 0, "move_speed_mult": 0, "attack_speed_mult": 0, "skill_cooldown_mult": 15, "ult_cooldown_mult": 0, "damaged_amplify": 0, "damaged_reduce": 0, "dot_amplify": 0, "base_attack_enemy_max_hp_damage": 0, "skill_enemy_max_hp_damage": 0, "self_max_hp_damage": 0, "base_attack_damaged_reduce": 0, "skill_damaged_reduce": 0, "defence_penetration": 0, "magic_resistance_penetration": 0, "range": 0, "heal_reduce": 0, "toughness": 0, "crit_chance": 0, "radius_mult": 0, "vamp": 0, "damage_reflect": 0, "cc_immune": false, "undying": false, "ignore_wall": false } ``` -------------------------------- ### Register Client and Server Extensions Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md Register both client and server extensions during mod initialization. Ensure the server extension is registered separately from the client/UI extension. ```rust fn init(_ctx: &GameCtx) -> ModRegistration { let mut reg = ModRegistration::new(MOD_ID); reg.set_extension(MyClientExtension::default()); reg.set_server_extension(MyServerExtension); reg } ``` -------------------------------- ### Merging Champion Text Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/asset-overrides-and-i18n.md Example of merging custom champion text into the base game's champion text table. This allows in-game text to be localized. ```json { "asset/base/text/champion": { "remapping": "asset/my_mod/text/champion", "type": "merge" } } ``` -------------------------------- ### Database Pack Structure Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md Use this directory structure for a Workshop item containing one or more database files. ```text my_database_pack/ database_pack.info league_2026.tfm2db fantasy_rosters.tfm2db preview.png ``` -------------------------------- ### GameCtx Runtime Service Methods Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Methods for registering and querying services within the game context. ```APIDOC ## `GameCtx` Runtime Service Methods ### Description Methods for registering and querying services within the game context. ### Methods - `register_service(&self, service_id: &str, version: ModServiceVersion, service: ModService) -> bool` - `query_service(&self, provider_mod_id: &str, service_id: &str, version_req: &str) -> Option` ``` -------------------------------- ### Database Pack Info File Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md The database_pack.info file uses basic fields similar to mod.mod_info for describing the database pack. ```json { "name": "2026 League Database Pack", "author": "Your Name", "version": "1.0.0", "description": "Custom databases for the 2026 league setup." } ``` -------------------------------- ### Base Asset Loading Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/assets-and-sprite-sheets.md How the game loads the base Aseprite file as an asset. ```text asset/example/champions/fire_mage ``` -------------------------------- ### Using Aseprite Animation Prefixes Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/assets-and-sprite-sheets.md Configure champion data to use animations from a single Aseprite file by specifying an 'anim_prefix'. This allows multiple character variants or animations within one file. ```json { "sprite": "asset/base/aseprite_resources/champions/druid", "anim_prefix": "eagle_" } ``` -------------------------------- ### Save Custom Mod Data in Rust Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md Use `mod_save_set_string` and `mod_save_set_version` within `Scene::InGame` to store persistent data for your mod. This example initializes a string value if it hasn't been set. ```rust impl ModExtension for MyExtension { fn post_update(&self, scene: &mut Scene, _ui: &mut GameUI, _assets: &mut Assets, _dt: f32) { let Scene::InGame { data } = scene else { return; }; if data.mod_save_get_string("my_mod", "initialized").is_none() { data.mod_save_set_version("my_mod", 1); data.mod_save_set_string("my_mod", "initialized", "true"); } } } ``` -------------------------------- ### Database Pack Folder Structure Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md A database pack folder uses 'database_pack.info' directly and can include multiple database files. The 'thumbnail.png' serves as the preview. ```text my_database_pack/ database_pack.info league_2026.tfm2db fantasy_rosters.tfm2db thumbnail.png ``` -------------------------------- ### Accessing Unpacked Base Assets Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md The unpacked base assets are organized similarly to the game's internal structure. For example, 'asset/base/text/ui' in the bundle becomes 'mods/base_unpacked/text/ui.i18n'. Use this as a read-only reference. ```text mods/base_unpacked/text/ui.i18n ``` -------------------------------- ### Optional Preview Image Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md For an enhanced Workshop page, include a 'preview.png' in your mod folder. 'preview.jpg' and 'thumbnail.jpg' are also accepted. ```text my_mod/ preview.png ``` -------------------------------- ### Implement a Runtime Service Provider Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md Expose a runtime service from a native DLL mod. This allows other mods to query and use the provided functionality. ```rust use std::ffi::c_void; use mod_api::*; const MOD_ID: &str = "service_provider"; const SERVICE_ID: &str = "math.v1"; #[repr(C)] pub struct MathServiceV1 { pub bonus: unsafe extern "C" fn(value: u32) -> u32, } unsafe extern "C" fn bonus(value: u32) -> u32 { value + 77 } static MATH_SERVICE: MathServiceV1 = MathServiceV1 { bonus, }; fn init(ctx: &GameCtx) -> ModRegistration { ctx.register_service( SERVICE_ID, ModServiceVersion::new(1, 0, 0), ModService::from_raw( std::ptr::null_mut(), &MATH_SERVICE as *const MathServiceV1 as *const c_void, ), ); ModRegistration::new(MOD_ID) } declare_mod!(init); ``` -------------------------------- ### Recommended Mod SDK Directory Layout Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md This is the recommended directory layout when including the Teamfight Manager 2 Mod SDK for native Rust mods. ```text TeamfightManager2.exe TFM2ModUploader.exe steam_api64.dll bundle.game_data mod-sdk/ deps/ native/ build_mod.bat build_mod_cargo.ps1 rust-toolchain.toml ``` -------------------------------- ### Build Rust Mod with Cargo Dependencies Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md Use the `build_mod.bat` script from the `mod-sdk` directory with the path to your mod's root folder for mods requiring external crates. Ensure your `Cargo.toml` is correctly configured. ```bash cd mod-sdk build_mod.bat path\to\your_mod ``` -------------------------------- ### Standard Mod Folder Structure Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md A typical game mod folder requires a 'mod.mod_info' file and an optional 'thumbnail.png' for the Workshop preview. ```text my_mod/ mod.mod_info thumbnail.png ``` -------------------------------- ### Database Pack Information File Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/getting-started.md Used for sharing custom database files instead of a full mod. The uploader recognizes this file type. ```text database_pack.info ``` -------------------------------- ### PlayerAiContext Methods Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Provides access to player and game state within the AI's decision-making process. Includes methods for retrieving player stats and suggesting actions. ```rust fn player_id(&self) -> usize fn athlete_id(&self) -> usize fn team(&self) -> usize fn position(&self) -> Position fn champion_name(&self) -> &str fn tick(&self) -> usize fn hp(&self) -> Option fn max_hp(&self) -> Option fn hp_ratio_percent(&self) -> Option fn is_hp_below_percent(&self, threshold: usize) -> bool fn is_valid_input(&self, input: &Input) -> bool fn get_run_away_input(&mut self) -> Option fn get_run_away_without_skill_input(&mut self) -> Option fn get_recall_input(&mut self) -> Option fn is_safe_to_recall(&mut self) -> bool ``` -------------------------------- ### Champion Text File Path Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/getting-started.md Indicates the location for internationalized text related to champions. ```text mods/my_mod/text/champion.i18n ``` -------------------------------- ### Asset Path Referencing Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/README.md Shows how to reference files within a mod's asset directory, excluding file extensions. ```text mods/my_mod/icons/my_champion_skill.png is used as: asset/my_mod/icons/my_champion_skill ``` -------------------------------- ### Asset Referencing with Suffixes Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/mod-package.md Illustrates how Aseprite files and manual sprite sheets can expose related assets like image atlases and animation data using '#' suffixes. ```text asset/example/aseprite_resources/champions/ghoul_king#sheet asset/example/aseprite_resources/champions/ghoul_king#anim asset/example/sprite/spell_icons#sheet asset/example/sprite/spell_icons#data ``` -------------------------------- ### Champion Data File Path Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/getting-started.md Specifies the file path for a data-only champion within the mod folder. ```text mods/my_mod/champion/my_champion.data_champion ``` -------------------------------- ### ModChampionInfo Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Defines a champion with its attributes, actions, and abilities. Use `add_champion` to add new champions or `replace_champion` to modify existing ones. ```APIDOC ## ModChampionInfo Defines one champion. Use `add_champion` with a new unique id to add a champion. Use `replace_champion` with an existing base champion id to rework that champion while preserving saved champion ids, ban/pick references, and patch references. If `replace_champion` receives an id that is not present in the base game, it behaves like `add_champion`. ### Methods | Method | Signature | Default | | --- | --- | --- | | `id` | `fn id(&self) -> &str` | required. For `replace_champion`, this must be the exact base champion id. | | `name` | `fn name(&self) -> &str` | `self.id()` | | `skill_icon` | `fn skill_icon(&self, skill_index: usize) -> (String, String)` | `skill_icon` sheet and `{id}_{index}` tag | | `category` | `fn category(&self) -> ChampionCategory` | required | | `tags` | `fn tags(&self) -> Vec` | required | | `stat` | `fn stat(&self) -> EntityStat` | required | | `growth` | `fn growth(&self) -> EntityStat` | required | | `attack` | `fn attack(&self) -> Box` | required | | `skill` | `fn skill(&self) -> Box` | required | | `skill2` | `fn skill2(&self) -> Box` | required | | `ult` | `fn ult(&self) -> Option>` | `None` | | `passive` | `fn passive(&self) -> Option>` | `None` | ``` -------------------------------- ### ModRegistration::new Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Creates a new `ModRegistration` instance with a unique mod identifier. ```APIDOC ## ModRegistration::new ### Description Creates a new `ModRegistration` instance with a unique mod identifier. ### Signature `fn new(mod_id: impl Into) -> Self` ### Parameters * **mod_id** (String) - The unique identifier for the mod. ``` -------------------------------- ### ChampionCategory Methods Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Provides a method to convert ChampionCategory to its string key representation. ```APIDOC ## ChampionCategory ### Methods - `to_text_key(&self) -> String`: Converts the ChampionCategory to its corresponding text key. ``` -------------------------------- ### Declare Mod Dependencies in mod.mod_info Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md Specify dependencies for a consumer mod, including game version and other service provider mods. Ensures required mods are loaded first. ```json { "dependencies": [ { "mod_id": "base", "version": ">=0.1.0" }, { "mod_id": "service_provider", "version": ">=1.0.0, <2.0.0" } ] } ``` -------------------------------- ### ModItemInfo Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Defines an item and its runtime callbacks. Implementations must provide `clone_box` for independent runtime instances. ```APIDOC ## ModItemInfo ### Description Defines an item and its runtime callbacks. Requires `clone_box` for independent runtime instances. ### Methods - **`clone_box`** - Signature: `fn clone_box(&self) -> Box` - Default: required - **`key`** - Signature: `fn key(&self) -> &str` - Default: required - **`icon`** - Signature: `fn icon(&self) -> &str` - Default: `self.key()` - **`price`** - Signature: `fn price(&self) -> usize` - Default: required - **`tier`** - Signature: `fn tier(&self) -> usize` - Default: required - **`stat`** - Signature: `fn stat(&self) -> BuffState` - Default: required - **`next_tier`** - Signature: `fn next_tier(&self) -> Vec` - Default: empty - **`previous_tier`** - Signature: `fn previous_tier(&self) -> Vec` - Default: empty - **`tags`** - Signature: `fn tags(&self) -> Vec` - Default: empty - **`category`** - Signature: `fn category(&self) -> ItemCategory` - Default: `ItemCategory::default()` - **`on_attack`** - Signature: `fn on_attack(&mut self, ctx: &mut GameCtx, caster: usize, target: usize, damage: &mut usize, damage_type: DamageType)` - Default: no-op - **`update`** - Signature: `fn update(&mut self, ctx: &mut GameCtx, rng_seed: u64, player: usize)` - Default: no-op - **`on_spawn`** - Signature: `fn on_spawn(&mut self, ctx: &mut GameCtx, player: usize)` - Default: no-op - **`on_healed`** - Signature: `fn on_healed(&mut self, ctx: &mut GameCtx, caster: Option, entity: usize, heal: usize)` - Default: no-op - **`on_damaged`** - Signature: `fn on_damaged(&mut self, ctx: &mut GameCtx, player: usize, entity: usize, attacker: usize, damage: usize)` - Default: no-op - **`on_kill`** - Signature: `fn on_kill(&mut self, ctx: &mut GameCtx, rng_seed: u64, player: usize, entity: usize)` - Default: no-op - **`on_skill_hit`** - Signature: `fn on_skill_hit(&mut self, ctx: &mut GameCtx, rng_seed: u64, caster: usize, target: usize)` - Default: no-op ``` -------------------------------- ### Exporting Mod Entry Point Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Use `declare_mod!` to export both the DLL symbols required for mod entry and API version checking. This macro simplifies the process of making your mod discoverable by the game. ```rust fn init(ctx: &GameCtx) -> ModRegistration { let mut reg = ModRegistration::new("my_mod"); reg.add_item(MyItem::default()); reg } declare_mod!(init); ``` -------------------------------- ### ModService Null and From Raw Constructors Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Provides methods to create a ModService instance, either as a null service or from raw pointers. ```rust pub const fn null() -> Self pub const fn from_raw(data: *mut c_void, vtable: *const c_void) -> Self ``` -------------------------------- ### Implement Client-Side Extension Hooks Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-rust-mods.md Implement the ModExtension trait to react to the game's scene, UI, and asset lifecycle on the client. ```rust #[derive(Default)] struct MyExtension; impl ModExtension for MyExtension { fn on_init(&self, _scene: &mut Scene, _ui: &mut GameUI, _assets: &mut Assets) {} fn post_update(&self, _scene: &mut Scene, _ui: &mut GameUI, _assets: &mut Assets, _dt: f32) { // UI or scene logic here. } } ``` -------------------------------- ### Skill Icons using Separate PNGs Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion-schema/champion-file.md Specifies individual icon asset paths for skill, skill2, and ultimate actions when each icon is a separate PNG file. ```json { "skill_icons": [ "asset/my_mod/icons/fire_skill", "asset/my_mod/icons/fire_skill2", "asset/my_mod/icons/fire_ult" ] } ``` -------------------------------- ### Cargo Mod Build Configuration Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/workshop-upload.md For Cargo mods, use a standard library crate configuration. Do not add 'mod-api' to dependencies as it's automatically injected by the uploader. ```toml [package] name = "my_mod" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] rand = "0.8" ``` -------------------------------- ### Referencing Localized Text Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/asset-overrides-and-i18n.md Demonstrates how to reference localized text within the game's data files using a specific asset path format. ```text #asset/base/text/champion?description.my_mod_fire_mage.skill ``` -------------------------------- ### ServerModContext Fields and Methods Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Provides access to server state, database, and methods for emitting events within the server environment. ```APIDOC ## `ServerModContext` Represents the server context available to mods. ### Fields - **`mod_id`** (`&str`): The ID of the current mod. - **`database`** (`&mut Database`): Mutable reference to the server's database. - **`server_state`** (`&mut ServerState`): Mutable reference to the server's state. ### Methods - **`emit_event`** - Signature: `fn emit_event(&mut self, event: impl Into, payload: impl Into>) -> bool` - Description: Emits an event to all connected clients. - **`emit_event_to_player`** - Signature: `fn emit_event_to_player(&mut self, player_id: PlayerId, event: impl Into, payload: impl Into>) -> bool` - Description: Emits an event to a specific player. - **`emit_event_to_team`** - Signature: `fn emit_event_to_team(&mut self, team_id: usize, event: impl Into, payload: impl Into>) -> bool` - Description: Emits an event to all players in a specific team. - **`emit_event_to_command_sender`** - Signature: `fn emit_event_to_command_sender(&mut self, command: &ModServerCommand, event: impl Into, payload: impl Into>) -> bool` - Description: Emits an event back to the sender of a command. - **`player_team_id`** - Signature: `fn player_team_id(&self, player_id: PlayerId) -> Option` - Description: Gets the team ID for a given player. - **`team_player_ids`** - Signature: `fn team_player_ids(&self, team_id: usize) -> Vec` - Description: Gets a list of player IDs for a given team. ``` -------------------------------- ### ClientDatabase Helper Methods Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Provides helper methods for accessing and retrieving data from the ClientDatabase. These methods often mirror ClientData read helpers but return direct references. ```APIDOC ## ClientDatabase Helper Methods ### Description Helper methods for accessing client-side data, returning direct references. ### Methods - **player_team_id** - **try_player_team** - **team** - **team_ids** - **athlete** - **athlete_ids** - **athlete_current_region_id** - **athlete_has_visible_solo_rank_in_region** - **visible_solo_rank_athletes** - **staff** - **staff_ids** - **knowledge_base** - **league** - **league_ids** - **tournament** - **tournament_ids** - **match_info** - **normal_match** - **practice_match** - **tutorial_match** - **solo_rank_match_info** - **match_replay** - **match_replay_ids** - **league_competition** - **league_competition_ids** - **tournament_competition** - **tournament_competition_ids** - **solo_rank_match** - **solo_rank_match_ids** - **champion_info** - **mod_events** - **team_display_name** - **multiplayer_chat_sender_display** - **team_salary_total** - **player_team** - **can_pause_save** - **is_player_vs_player_match** - **match_has_player_team** - **due_player_match** - **current_intl_break_target_date** - **version_at_date** - **get_historical_sheet** - **get_historical_game_setting** ``` -------------------------------- ### ModRegistration::add_champion Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Adds a champion definition to the mod registration. ```APIDOC ## ModRegistration::add_champion ### Description Adds a champion definition to the mod registration. ### Signature `fn add_champion(&mut self, info: impl ModChampionInfo + 'static)` ### Parameters * **info** (impl ModChampionInfo + 'static) - The champion information to add. ``` -------------------------------- ### Database Pack Folder Structure Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/mod-package.md This is the required folder structure for a database pack. The folder name serves as the package ID. ```text mods/my_database_pack/ database_pack.info league_2026.tfm2db fantasy_rosters.tfm2db thumbnail.png preview.png ``` -------------------------------- ### ModServerExtension Methods Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md These methods are callbacks that the server mod can implement to hook into the server's lifecycle and command handling. ```APIDOC ## `ModServerExtension` Runs on the server/management side. ### Methods - **`on_server_start`** - Signature: `fn on_server_start(&self, ctx: &mut ServerModContext)` - Description: Called when the server starts. - Default: no-op - **`before_management_tick`** - Signature: `fn before_management_tick(&self, ctx: &mut ServerModContext)` - Description: Called before each management tick. - Default: no-op - **`after_management_tick`** - Signature: `fn after_management_tick(&self, ctx: &mut ServerModContext)` - Description: Called after each management tick. - Default: no-op - **`handle_command`** - Signature: `fn handle_command(&self, ctx: &mut ServerModContext, command: &ModServerCommand) -> ModServerCommandResult` - Description: Handles incoming server commands from mods. - Default: `Pass` ``` -------------------------------- ### Static PNG Sprite Configuration Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/assets-and-sprite-sheets.md Use a static PNG file for a simple, one-frame sprite. Do not set 'anim_prefix' when using a PNG. The game creates basic fallback animations for common tags. ```json { "sprite": "asset/example/champions/fire_mage_idle" } ``` -------------------------------- ### PlayerAiInitContext Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Provides initial context for the player AI, including player and athlete details, team, position, and champion. ```APIDOC ## PlayerAiInitContext ### Description Provides initial context for the player AI, including player and athlete details, team, position, and champion. ### Fields - `player_id` (usize) - `athlete_id` (usize) - `team` (usize) - `position` (Position) - `champion_name` (String) ``` -------------------------------- ### Individual Skill Icon Sprite Sheet Reference Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/assets-and-sprite-sheets.md References individual PNG files as skill icons, providing a list of asset paths. ```json { "skill_icons": [ "asset/example/icons/fire_skill", "asset/example/icons/fire_skill2", "asset/example/icons/fire_ult" ] } ``` -------------------------------- ### PlayerRef Methods Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Methods for accessing properties and state of a player reference. ```APIDOC ## `PlayerRef` Methods ### Description Methods for accessing properties and state of a player reference. ### Methods - `handle(&self) -> PlayerHandle` - `champion(&self) -> Option>` - `level(&self) -> usize` - `gold(&self) -> usize` - `position(&self) -> Position` - `team(&self) -> usize` - `is_alive(&self) -> bool` - `respawn_time(&self) -> usize` - `kills(&self) -> usize` - `deaths(&self) -> usize` - `assists(&self) -> usize` - `cs(&self) -> usize` ``` -------------------------------- ### Mod Override Info Configuration Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/asset-overrides-and-i18n.md Defines how to merge or replace existing game assets. Use 'merge' for JSON objects like i18n and 'override' to replace the entire asset. ```json { "asset/base/text/ui": { "remapping": "asset/example/text/ui", "type": "merge" }, "asset/base/aseprite_resources/champions/example_ghoul": { "remapping": "asset/example/aseprite_resources/champions/ghoul_king", "type": "override" } } ``` -------------------------------- ### MoveTo Effect Configuration Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/data-champion-schema/effects.md Initiates movement towards a target, position, or direction, triggering end effects upon arrival. Use for planned movements with follow-up actions. ```json { "type": "MoveTo", "speed": 3500, "range": 50000, "end_effects": [ { "type": "RangeEffect", "target": "Enemy", "effects": [{ "type": "Attack", "damage": 40 }] } ] } ``` -------------------------------- ### GameCtx Simulation Query Methods Source: https://github.com/teamsamoyed/teamfightmanager2mod/blob/main/docs/native-mod-api-reference.md Methods for querying the current state of the game simulation. ```APIDOC ## `GameCtx` Simulation Query Methods ### Description Methods for querying the current state of the game simulation. ### Methods - `tick(&self) -> usize` - `seed(&self) -> u64` - `score_diff(&self, team: usize) -> i32` - `is_end(&self) -> bool` - `get_entity(&self, id: usize) -> Option>` - `entity_count(&self) -> usize` - `entity_at(&self, index: usize) -> Option>` - `get_player(&self, id: usize) -> Option>` - `champion_count(&self) -> usize` - `champion_id_at(&self, index: usize) -> usize` - `tower_count(&self) -> usize` - `tower_id_at(&self, index: usize) -> usize` - `player_count(&self) -> usize` - `player_at(&self, index: usize) -> Option>` - `projectile_count(&self) -> usize` - `projectile_at(&self, index: usize) -> Option>` - `kill_log_count(&self) -> usize` - `kill_log_at(&self, index: usize) -> KillLogEntry` - `distance_sq(&self, id1: usize, id2: usize) -> u64` - `is_visible(&self, team: usize, id: usize) -> bool` ```