diff --git a/WorldBoxMod.cs b/WorldBoxMod.cs index 5e2c6d5..2d81755 100644 --- a/WorldBoxMod.cs +++ b/WorldBoxMod.cs @@ -9,7 +9,6 @@ using NeoModLoader.services; using NeoModLoader.ui; using NeoModLoader.utils; -using NeoModLoader.utils.Builders; using UnityEngine; namespace NeoModLoader; @@ -80,7 +79,6 @@ private void Update() Harmony.CreateAndPatchAll(typeof(LM), Others.harmony_id); Harmony.CreateAndPatchAll(typeof(ResourcesPatch), Others.harmony_id); Harmony.CreateAndPatchAll(typeof(CustomAudioManager), Others.harmony_id); - Harmony.CreateAndPatchAll(typeof(AssetPatches), Others.harmony_id); if (!SmoothLoader.isLoading()) SmoothLoader.prepare(); SmoothLoader.add(() => @@ -124,7 +122,7 @@ private void Update() } }, "Compile Mod " + mod.mod_decl.Name); } - MasterBuilder Builder = new(); + AssetLinker Linker = new(); foreach (var mod in mod_nodes) { SmoothLoader.add(() => @@ -132,11 +130,9 @@ private void Update() if (mods_to_load.Contains(mod.mod_decl)) { ResourcesPatch.LoadResourceFromFolder(Path.Combine(mod.mod_decl.FolderPath, - Paths.ModResourceFolderName), out List builders); - Builder.AddBuilders(builders); + Paths.ModResourceFolderName), Linker); ResourcesPatch.LoadResourceFromFolder(Path.Combine(mod.mod_decl.FolderPath, - Paths.NCMSAdditionModResourceFolderName), out List builders2); - Builder.AddBuilders(builders2); + Paths.NCMSAdditionModResourceFolderName), Linker); ResourcesPatch.LoadAssetBundlesFromFolder(Path.Combine(mod.mod_decl.FolderPath, Paths.ModAssetBundleFolderName)); } @@ -146,7 +142,7 @@ private void Update() SmoothLoader.add(() => { ModCompileLoadService.loadMods(mods_to_load); - Builder.BuildAll(); + Linker.AddAssets(); ModInfoUtils.SaveModRecords(); NCMSCompatibleLayer.Init(); var successfulInit = new Dictionary(); diff --git a/services/ModCompileLoadService.cs b/services/ModCompileLoadService.cs index c1bb9dc..6c3d9e7 100644 --- a/services/ModCompileLoadService.cs +++ b/services/ModCompileLoadService.cs @@ -11,7 +11,6 @@ using NeoModLoader.General; using NeoModLoader.ncms_compatible_layer; using NeoModLoader.utils; -using NeoModLoader.utils.Builders; using UnityEngine; namespace NeoModLoader.services; @@ -628,15 +627,13 @@ public static bool TryCompileAndLoadModAtRuntime(ModDeclare mod_declare) bool compile_success = TryCompileModAtRuntime(mod_declare); if (!compile_success) return false; - MasterBuilder Builder = new MasterBuilder(); - ResourcesPatch.LoadResourceFromFolder(Path.Combine(mod_declare.FolderPath, Paths.ModResourceFolderName), out List builders); + AssetLinker Linker = new AssetLinker(); + ResourcesPatch.LoadResourceFromFolder(Path.Combine(mod_declare.FolderPath, Paths.ModResourceFolderName), Linker); ResourcesPatch.LoadResourceFromFolder(Path.Combine(mod_declare.FolderPath, - Paths.NCMSAdditionModResourceFolderName), out List builders2); + Paths.NCMSAdditionModResourceFolderName), Linker); LoadMod(mod_declare); - Builder.AddBuilders(builders); - Builder.AddBuilders(builders2); - Builder.BuildAll(); + Linker.AddAssets(); return true; } diff --git a/services/ModReloadService.cs b/services/ModReloadService.cs index db83c1c..680fb3a 100644 --- a/services/ModReloadService.cs +++ b/services/ModReloadService.cs @@ -2,7 +2,6 @@ using NeoModLoader.constants; using NeoModLoader.General; using NeoModLoader.utils; -using NeoModLoader.utils.Builders; namespace NeoModLoader.services; @@ -18,14 +17,12 @@ public static bool HotfixMethods(IReloadable pMod, ModDeclare pModDeclare) public static bool ReloadResources(IMod pMod) { - MasterBuilder Builder = new(); + AssetLinker Linker = new(); ResourcesPatch.LoadResourceFromFolder(Path.Combine(pMod.GetDeclaration().FolderPath, - Paths.ModResourceFolderName), out List builders); + Paths.ModResourceFolderName), Linker); ResourcesPatch.LoadResourceFromFolder(Path.Combine(pMod.GetDeclaration().FolderPath, - Paths.NCMSAdditionModResourceFolderName), out List builders2); - Builder.AddBuilders(builders); - Builder.AddBuilders(builders2); - Builder.BuildAll(); + Paths.NCMSAdditionModResourceFolderName), Linker); + Linker.AddAssets(); return false; } diff --git a/utils/AssetLinker.cs b/utils/AssetLinker.cs new file mode 100644 index 0000000..2efa200 --- /dev/null +++ b/utils/AssetLinker.cs @@ -0,0 +1,712 @@ +using HarmonyLib; +using NeoModLoader.services; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; + +namespace NeoModLoader.utils +{ + public delegate void Linker(Asset Asset); + /// + /// General purpose asset linker which links your assets and can load them as Files + /// + public class AssetLinker + { + public List Assets = new List(); + Dictionary CustomLinkers = new Dictionary(); + internal List AssetFilePaths = new List(); + /// + /// gets the library of this asset + /// + public static void AddToLibrary(Asset Asset) + { + foreach(BaseAssetLibrary library in AssetManager._instance._list) + { + var type = library.GetType(); + if (type?.GetField("t", BindingFlags.NonPublic | BindingFlags.Instance)?.FieldType == Asset.GetType()) + { + type.GetMethod("add").Invoke(library, new object[] { Asset }); + return; + } + } + throw new Exception($"could not get the library of asset {Asset.GetType().Name}!"); + } + /// + /// gets an asset from its Name + /// + /// not the ID of the asset, the Name of its type + public static Type GetAssetFromName(string Name) + { + return Type.GetType(Name + ", Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"); + } + /// + /// Adds an asset to the linker to be linked + /// + /// + public Asset AddAsset(Asset Asset) + { + Assets.Add(Asset); + return Asset; + } + /// + /// Adds Assets to their Libraries + /// + public void AddAssets(bool Link = true) + { + foreach (string FilePath in AssetFilePaths) + { + try + { + Assets.Add(LoadFile(FilePath)); + } + catch (Exception e) + { + LogService.LogError($"Could not load Asset of type {Path.GetExtension(FilePath)}!"); + } + } + foreach (Asset asset in Assets) + { + AddToLibrary(asset); + } + if (Link) + { + LinkAssets(); + } + } + /// + /// adds a custom linker function for a asset. can be a custom or native asset + /// + public void AddCustomLinker(Type Type, Linker Linker) + { + if(CustomLinkers.ContainsKey(Type)){ + LogService.LogError($"Asset of Type {Type} already has linker!"); + } + CustomLinkers.Add(Type, Linker); + } + /// + /// links an asset with other assets, along with post-init modifications + /// + /// not all assets have a linker, to add your own linker, call the AddLinker Function + public void LinkAsset(Asset asset) + { + string type = asset.GetType().Name; + MethodInfo Function = typeof(AssetLinker).GetMethod("Link" + type, BindingFlags.Static | BindingFlags.Public); + if (Function == null) + { + if(!CustomLinkers.TryGetValue(asset.GetType(), out Linker linker)) + { + LogService.LogWarning($"there is no asset linker for asset type {type}!"); + return; + } + Function = linker.Method; + } + Function.Invoke(null, new object[] { asset }); + } + /// + /// Links the Assets + /// + public void LinkAssets() + { + foreach (Asset asset in Assets) + { + LinkAsset(asset); + } + } + /// + /// Loads a asset from a file + /// + public static Asset LoadFile(string FilePath) + { + SerializableAsset assetSerialized = JsonConvert.DeserializeObject(File.ReadAllText(FilePath)); + return SerializableAsset.ToAsset(assetSerialized, GetAssetFromName(Path.GetExtension(FilePath))); + } + /// + /// saves a asset to a folder + /// + public static void SaveFile(string FilePath, Asset Asset) + { + SerializableAsset assetSerialized = SerializableAsset.FromAsset(Asset); + File.WriteAllText(FilePath + "/" + Asset.id + "." + Asset.GetType().Name, JsonConvert.SerializeObject(assetSerialized)); + } + #region Linkers + public static void GenerateZombie(ActorAsset Asset) + { + ActorAssetLibrary Library = AssetManager.actor_library; + if (!Asset.isTemplateAsset() && Asset.zombie_auto_asset && Asset.can_turn_into_zombie) + { + string tZombieID = Asset.getZombieID(); + ActorAsset tGeneratedZombieAsset = Library.clone(tZombieID, Asset.id); + ActorAsset ZombieAsset = tGeneratedZombieAsset; + Library.setDefaultZombieFields(Library.t, Asset, Asset.default_animal); + ActorTextureSubAsset tSubTexture = new ActorTextureSubAsset(Asset.texture_path_zombie_for_auto_loader_main, Library.t.has_advanced_textures); + Library.t.texture_asset = tSubTexture; + ActorTextureSubAsset tOriginalSubTexture = Asset.texture_asset; + tSubTexture.shadow = tOriginalSubTexture.shadow; + tSubTexture.shadow_texture = tOriginalSubTexture.shadow_texture; + tSubTexture.shadow_texture_egg = tOriginalSubTexture.shadow_texture_egg; + tSubTexture.shadow_texture_baby = tOriginalSubTexture.shadow_texture_baby; + if (Library.hasSpriteInResources(Asset.texture_path_zombie_for_auto_loader_main)) + { + tSubTexture.texture_path_main = Asset.texture_path_zombie_for_auto_loader_main; + tSubTexture.texture_heads = Asset.texture_path_zombie_for_auto_loader_heads; + } + else + { + tSubTexture.texture_path_main = Asset.texture_asset.texture_path_main; + tSubTexture.texture_heads = Asset.texture_asset.texture_heads; + Library.t.dynamic_sprite_zombie = true; + } + if (Asset.animation_swim == null) + { + Library.t.animation_swim = null; + } + Library.loadTexturesAndSprites(ZombieAsset); + } + + } + public static void LinkWithAchievment(BaseUnlockableAsset Asset) + { + if (Asset.unlocked_with_achievement) + { + Achievement pAchievement = AssetManager.achievements.get(Asset.achievement_id); + if (pAchievement.unlock_assets == null) + { + pAchievement.unlock_assets = new List(); + pAchievement.unlocks_something = true; + } + pAchievement.unlock_assets.Add(Asset); + } + } + public static void LinkActorAsset(Asset asset) + { + ActorAsset Asset = asset as ActorAsset; + ActorAssetLibrary Library = AssetManager.actor_library; + Library.loadTexturesAndSprites(Asset); + GenerateZombie(Asset); + if (Asset.shadow) + { + Asset.texture_asset.loadShadow(); + } + if (!Asset.is_boat) + { + Asset.generateFmodPaths(Asset.id); + } + if (Asset.action_dead_animation != null) + { + Asset.special_dead_animation = true; + } + if (!string.IsNullOrEmpty(Asset.base_asset_id)) + { + ActorAsset tBaseAsset = Library.get(Asset.base_asset_id); + Asset.units = tBaseAsset.units; + } + if (Asset.is_humanoid && !Asset.unit_zombie) + { + Library._humanoids_amount++; + } + if (Asset.avatar_prefab != string.Empty) + { + Asset.has_avatar_prefab = true; + } + if (Asset.get_override_sprite != null) + { + Asset.has_override_sprite = true; + } + if (Asset.get_override_avatar_frames != null) + { + Asset.has_override_avatar_frames = true; + } + if (!string.IsNullOrEmpty(Asset.architecture_id)) + { + Asset.architecture_asset = AssetManager.architecture_library.get(Asset.architecture_id); + } + if (Asset.spell_ids != null && Asset.spell_ids.Count != 0) + { + Asset.spells = new SpellHolder(); + Asset.spells.mergeWith(Asset.spell_ids); + } + if (Asset.is_boat) + { + Library.list_only_boat_assets.Add(Asset); + } + if (Asset.color_hex != null) + { + Asset.color = new Color32?(Toolbox.makeColor(Asset.color_hex)); + } + if (Asset.check_flip == null) + { + Asset.check_flip = (BaseSimObject _, WorldTile _) => true; + } + LinkWithAchievment(Asset); + } + public static void LinkArchitectureAsset(Asset asset) + { + ArchitectureAsset Asset = asset as ArchitectureAsset; + if (!string.IsNullOrEmpty(Asset.spread_biome_id)) + { + Asset.spread_biome = true; + } + if (!Asset.isTemplateAsset()) + { + AssetManager.architecture_library.loadAutoBuildingsForAsset(Asset); + foreach (ValueTuple tSharedBuilding in Asset.shared_building_orders) + { + Asset.addBuildingOrderKey(tSharedBuilding.Item1, tSharedBuilding.Item2); + } + } + if (!Asset.isTemplateAsset() && Asset.generate_buildings) + { + string id = Asset.id; + foreach (string text in Asset.styled_building_orders) + { + string text2 = Asset.building_ids_for_construction[text]; + string generation_target = Asset.generation_target; + BuildingAsset building = AssetManager.architecture_library.get(generation_target).getBuilding(text); + BuildingAsset buildingAsset = AssetManager.buildings.clone(text2, building.id); + buildingAsset.group = "civ_building"; + buildingAsset.mini_civ_auto_load = true; + buildingAsset.civ_kingdom = id; + buildingAsset.main_path = "buildings/civ_main/" + id + "/"; + buildingAsset.can_be_upgraded = false; + buildingAsset.has_sprite_construction = true; + if (Asset.spread_biome) + { + buildingAsset.spread_biome = true; + buildingAsset.spread_biome_id = Asset.spread_biome_id; + } + buildingAsset.material = Asset.material; + if (buildingAsset.material == "jelly") + { + buildingAsset.setAtlasID("buildings_wobbly", "buildings"); + } + buildingAsset.shadow = Asset.has_shadows; + buildingAsset.burnable = Asset.burnable_buildings; + buildingAsset.affected_by_acid = Asset.acid_affected_buildings; + if (text == "order_library") + { + buildingAsset.fundament = new BuildingFundament(2, 2, 2, 0); + } + else if (text == "order_temple") + { + buildingAsset.fundament = new BuildingFundament(2, 2, 3, 0); + } + + else if (text == "order_hall_0") + { + buildingAsset.fundament = new BuildingFundament(3, 3, 4, 0); + } + + else if (text == "order_tent") + { + buildingAsset.fundament = new BuildingFundament(2, 2, 2, 0); + } + + else if (!(text == "order_house_0")) + { + } + if (!(text == "order_barracks")) + { + } + else if (text == "order_windmill_0") + { + buildingAsset.fundament = new BuildingFundament(2, 2, 2, 0); + if (buildingAsset.shadow) + { + buildingAsset.setShadow(0.4f, 0.38f, 0.47f); + } + } + + if (text == "order_watch_tower") + { + buildingAsset.fundament = new BuildingFundament(1, 1, 1, 0); + } + else if (text == "order_docks_0") + { + string text3 = "docks_" + id; + buildingAsset.upgrade_to = text3; + buildingAsset.can_be_upgraded = true; + } + + else if (text == "order_docks_1") + { + string text4 = "fishing_docks_" + id; + buildingAsset.upgraded_from = text4; + buildingAsset.has_sprites_main_disabled = false; + } + } + } + } + public static void LinkPhenotype(Asset asset) + { + PhenotypeAsset Asset = asset as PhenotypeAsset; + PhenotypeLibrary Library = AssetManager.phenotype_library; + Library.createShades(Asset); + Asset.phenotype_index = Library.list.Count - 1; + Library._phenotypes_assets_by_index.Add(Asset.phenotype_index, Asset); + } + public static void LinkItem(Asset asset) + { + EquipmentAsset Asset = asset as EquipmentAsset; + if (Asset.item_modifier_ids != null) + { + Asset.item_modifiers = new ItemModAsset[Asset.item_modifier_ids.Length]; + for (int i = 0; i < Asset.item_modifier_ids.Length; i++) + { + string tModID = Asset.item_modifier_ids[i]; + ItemModAsset tModData = AssetManager.items_modifiers.get(tModID); + if (tModData == null) + { + BaseAssetLibrary.logAssetError("ItemLibrary: Item Modifier Asset not found", tModID); + } + else + { + Asset.item_modifiers[i] = tModData; + } + } + } + if (Asset.is_pool_weapon) + { + Asset.path_gameplay_sprite = "items/weapons/w_" + Asset.id; + } + if (string.IsNullOrEmpty(Asset.path_icon)) + { + Asset.path_icon = "ui/Icons/items/icon_" + Asset.id; + int tResourcesGoldCostResources = 0; + if (Asset.cost_resource_id_1 != "none") + { + ResourceAsset tResource = AssetManager.resources.get(Asset.cost_resource_id_1); + tResourcesGoldCostResources += tResource.money_cost; + } + if (Asset.cost_resource_id_2 != "none") + { + ResourceAsset tResource2 = AssetManager.resources.get(Asset.cost_resource_id_2); + tResourcesGoldCostResources += tResource2.money_cost; + } + Asset.cost_coins_resources = tResourcesGoldCostResources; + } + if (Asset.is_pool_weapon) + { + Asset.gameplay_sprites = SpriteTextureLoader.getSpriteList(Asset.path_gameplay_sprite, false); + if (Asset.gameplay_sprites.Length == 0) + { + Debug.LogError("Weapon Texture is Missing: " + Asset.path_gameplay_sprite); + } + } + LinkAugmentationAsset(Asset); + } + public static void LinkItemModifier(Asset asset) + { + ItemModAsset Asset = asset as ItemModAsset; + ItemModifierLibrary Library = AssetManager.items_modifiers; + for (int i = 0; i < Asset.rarity; i++) + { + if (Asset.pool.Contains("weapon")) + { + Library.pools["weapon"].Add(Asset); + } + if (Asset.pool.Contains("armor")) + { + Library.pools["armor"].Add(Asset); + } + if (Asset.pool.Contains("accessory")) + { + Library.pools["accessory"].Add(Asset); + } + } + LinkAugmentationAsset(Asset); + } + public static void LinkAugmentationAsset(BaseAugmentationAsset Asset) + { + if (Asset.decision_ids != null) + { + Asset.decisions_assets = new DecisionAsset[Asset.decision_ids.Count]; + for (int i = 0; i < Asset.decision_ids.Count; i++) + { + string tDecisionID = Asset.decision_ids[i]; + DecisionAsset tDecisionAsset = AssetManager.decisions_library.get(tDecisionID); + Asset.decisions_assets[i] = tDecisionAsset; + } + } + Asset.linkSpells(); + Asset.linkCombatActions(); + LinkWithAchievment(Asset); + } + public static void LinkSubspeciesTrait(Asset asset) + { + SubspeciesTrait Asset = asset as SubspeciesTrait; + SubspeciesTraitLibrary Library = AssetManager.subspecies_traits; + if (Asset.id_phenotype != null) + { + PhenotypeAsset Phenotype = AssetManager.phenotype_library.get(Asset.id_phenotype); + Phenotype.subspecies_trait_id = Asset.id; + Asset.priority = Phenotype.priority; + } + if (Asset.is_mutation_skin) + { + OpposeOtherTraits(Asset, (SubspeciesTrait trait) => trait.is_mutation_skin, AssetManager.subspecies_traits); + } + if (Asset.phenotype_skin) + { + OpposeOtherTraits(Asset, (SubspeciesTrait trait) => trait.phenotype_skin, AssetManager.subspecies_traits); + } + if (Asset.phenotype_egg) + { + OpposeOtherTraits(Asset, (SubspeciesTrait trait) => trait.phenotype_egg, AssetManager.subspecies_traits); + } + if (Asset.spawn_random_trait_allowed) + { + Library._pot_allowed_to_be_given_randomly.Add(Asset); + } + if (Asset.in_mutation_pot_add) + { + int tRate = Asset.rarity.GetRate(); + Library._pot_mutation_traits_add.AddTimes(tRate, Asset); + } + if (Asset.in_mutation_pot_remove) + { + int tRate2 = Asset.rarity.GetRate(); + Library._pot_mutation_traits_remove.AddTimes(tRate2, Asset); + } + if (Asset.phenotype_egg && Asset.after_hatch_from_egg_action != null) + { + Asset.has_after_hatch_from_egg_action = true; + } + Library.loadSpritesPaths(Asset); + if (Asset.spawn_random_trait_allowed) + { + Library._pot_allowed_to_be_given_randomly.Add(Asset); + } + if (Asset.in_mutation_pot_add) + { + int tRate = Asset.rarity.GetRate(); + Library._pot_mutation_traits_add.AddTimes(tRate, Asset); + } + if (Asset.in_mutation_pot_remove) + { + int tRate2 = Asset.rarity.GetRate(); + Library._pot_mutation_traits_remove.AddTimes(tRate2, Asset); + } + if (Asset.phenotype_egg && Asset.after_hatch_from_egg_action != null) + { + Asset.has_after_hatch_from_egg_action = true; + } + LinkBaseTrait(Asset, Library); + } + public static void OpposeOtherTraits(A Trait, Func Oppose, BaseTraitLibrary Library) where A : BaseTrait + { + foreach (A asset in Library.list) + { + if (asset.id != Trait.id && Oppose(asset)) + { + Trait.addOpposite(asset.id); + } + } + } + public static void LinkBaseTrait(A Asset, BaseTraitLibrary Library) where A : BaseTrait + { + foreach (ActorAsset tActorAsset in AssetManager.actor_library.list) + { + List traits = Library.getDefaultTraitsForMeta(tActorAsset); + if (traits != null && traits.Contains(Asset.id)) + { + Asset.default_for_actor_assets ??= new List(); + Asset.default_for_actor_assets.Add(tActorAsset); + } + } + if (Asset.opposite_list != null && Asset.opposite_list.Count > 0) + { + Asset.opposite_traits = new HashSet(Asset.opposite_list.Count); + foreach (string tID in Asset.opposite_list) + { + A tOppositeTrait = Library.get(tID); + Asset.opposite_traits.Add(tOppositeTrait); + } + } + if (Asset.traits_to_remove_ids != null) + { + int tCount = Asset.traits_to_remove_ids.Length; + Asset.traits_to_remove = new A[tCount]; + for (int i = 0; i < tCount; i++) + { + string ID = Asset.traits_to_remove_ids[i]; + A tTraitToAdd = Library.get(ID); + Asset.traits_to_remove[i] = tTraitToAdd; + } + } + if (string.IsNullOrEmpty(Asset.path_icon)) + { + Asset.path_icon = Library.icon_path + Asset.getLocaleID(); + } + if (Asset.spawn_random_trait_allowed) + { + Library._pot_allowed_to_be_given_randomly.AddTimes(Asset.spawn_random_rate, Asset); + } + LinkAugmentationAsset(Asset); + } + public static void LinkActorTrait(Asset asset) + { + ActorTrait Asset = asset as ActorTrait; + ActorTraitLibrary Library = AssetManager.traits; + if (Asset.in_training_dummy_combat_pot) + { + Library.pot_traits_combat.Add(Asset); + } + if (Asset.is_mutation_box_allowed) + { + Library.pot_traits_mutation_box.Add(Asset); + } + if (Asset.rate_acquire_grow_up != 0) + { + for (int j = 0; j < Asset.rate_acquire_grow_up; j++) + { + Library.pot_traits_growup.Add(Asset); + } + } + if (Asset.rate_birth != 0) + { + for (int i = 0; i < Asset.rate_birth; i++) + { + Library.pot_traits_birth.Add(Asset); + } + } + Library.checkDefault(Asset); + Asset.only_active_on_era_flag = Asset.era_active_moon || Asset.era_active_night; + LinkBaseTrait(Asset, Library); + } + public static void LinkClanTrait(Asset asset) + { + LinkBaseTrait(asset as ClanTrait, AssetManager.clan_traits); + } + public static void LinkCultureTrait(Asset asset) + { + CultureTrait Asset = asset as CultureTrait; + if (Asset.town_layout_plan) + { + OpposeOtherTraits(Asset, (CultureTrait trait) => trait.town_layout_plan, AssetManager.culture_traits); + } + LinkBaseTrait(Asset, AssetManager.culture_traits); + } + public static void LinkKingdomAsset(Asset assett) + { + KingdomAsset Asset = assett as KingdomAsset; + KingdomLibrary Library = AssetManager.kingdoms; + Asset.addTag("everyone"); + if (Asset.friendship_for_everyone && !Asset.brain) + { + foreach (KingdomAsset asset in Library.list) + { + asset.addFriendlyTag(Asset.id); + } + } + if (Asset.default_kingdom_color != null) + { + if (string.Equals(Asset.default_kingdom_color.id, "ASSET_ID")) + { + Asset.default_kingdom_color.id = "kingdom_library_color_" + Asset.id; + } + } + else + { + Asset.default_kingdom_color = Library._shared_default_color; + } + } + public static void LinkBuildingAsset(Asset asset) + { + BuildingAsset Asset = asset as BuildingAsset; + if (Asset.step_action != null) + { + Asset.has_step_action = true; + } + if (Asset.get_map_icon_color != null) + { + Asset.has_get_map_icon_color = true; + } + BuildingAsset buildingAsset = Asset; + HashSet biome_tags_growth = Asset.biome_tags_growth; + buildingAsset.has_biome_tags = biome_tags_growth != null && biome_tags_growth.Count > 0; + BuildingAsset buildingAsset2 = Asset; + HashSet biome_tags_spread = Asset.biome_tags_spread; + buildingAsset2.has_biome_tags_spread = biome_tags_spread != null && biome_tags_spread.Count > 0; + } + public static void LinkBiomeAsset(Asset asset) + { + AssetManager.biome_library.addBiomeToPool(asset as BiomeAsset); + } + public static void LinkSpellAsset(Asset asset) + { + SpellAsset spellAsset = asset as SpellAsset; + if (spellAsset.decision_ids != null) + { + spellAsset.decisions_assets = new DecisionAsset[spellAsset.decision_ids.Count]; + for (int i = 0; i < spellAsset.decision_ids.Count; i++) + { + string text = spellAsset.decision_ids[i]; + DecisionAsset decisionAsset = AssetManager.decisions_library.get(text); + spellAsset.decisions_assets[i] = decisionAsset; + } + } + } + public static void LinkStatusAsset(Asset asset) + { + StatusAsset statusAsset = asset as StatusAsset; + if (statusAsset.get_override_sprite != null) + { + statusAsset.has_override_sprite = true; + statusAsset.need_visual_render = true; + } + if (statusAsset.get_override_sprite_position != null) + { + statusAsset.has_override_sprite_position = true; + } + if (statusAsset.get_override_sprite_rotation_z != null) + { + statusAsset.has_override_sprite_rotation_z = true; + } + if (statusAsset.texture != null) + { + statusAsset.need_visual_render = true; + } + if (statusAsset.texture != null && statusAsset.sprite_list == null) + { + statusAsset.sprite_list = SpriteTextureLoader.getSpriteList("effects/" + statusAsset.texture, false); + } + } + public static void LinkHotkeyAsset(Asset asset) + { + HotkeyAsset hotkeyAsset = asset as HotkeyAsset; + hotkeyAsset.overridden_key_1 = hotkeyAsset.default_key_1; + hotkeyAsset.overridden_key_2 = hotkeyAsset.default_key_2; + hotkeyAsset.overridden_key_3 = hotkeyAsset.default_key_3; + hotkeyAsset.overridden_key_mod_1 = hotkeyAsset.default_key_mod_1; + hotkeyAsset.overridden_key_mod_2 = hotkeyAsset.default_key_mod_2; + hotkeyAsset.overridden_key_mod_3 = hotkeyAsset.default_key_mod_3; + if (hotkeyAsset.default_key_mod_1 != null) + { + HotkeyLibrary.mod_keys = HotkeyLibrary.mod_keys.AddToArray(hotkeyAsset.default_key_mod_1); + } + if (hotkeyAsset.default_key_mod_2 != null) + { + HotkeyLibrary.mod_keys = HotkeyLibrary.mod_keys.AddToArray(hotkeyAsset.default_key_mod_2); + } + if (hotkeyAsset.default_key_mod_3 != null) + { + HotkeyLibrary.mod_keys = HotkeyLibrary.mod_keys.AddToArray(hotkeyAsset.default_key_mod_3); + } + if (hotkeyAsset.just_pressed_action != null) + { + AssetManager.hotkey_library.action_hotkeys = AssetManager.hotkey_library.action_hotkeys.AddToArray(hotkeyAsset); + } + else if (hotkeyAsset.holding_action != null) + { + AssetManager.hotkey_library.action_hotkeys = AssetManager.hotkey_library.action_hotkeys.AddToArray(hotkeyAsset); + } + } + public static void LinkWorldBehaviourAsset(Asset asset) + { + WorldBehaviourAsset worldBehaviourAsset = asset as WorldBehaviourAsset; + worldBehaviourAsset.manager = new WorldBehaviour(worldBehaviourAsset); + } + #endregion + } +} \ No newline at end of file diff --git a/utils/Builders/ActorAssetBuilder.cs b/utils/Builders/ActorAssetBuilder.cs deleted file mode 100644 index 9e0e0c9..0000000 --- a/utils/Builders/ActorAssetBuilder.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace NeoModLoader.utils.Builders -{ - /// - /// A Builder to create Actor Assets - /// NOT FINUSHED!!!!!!!!!!!!!!!!!!!! - /// - public sealed class ActorAssetBuilder : UnlockableAssetBuilder - { - /// - public ActorAssetBuilder(string ID) : base(ID) { } - /// - public ActorAssetBuilder(string FilePath, bool LoadImmediately) : base(FilePath, LoadImmediately) { } - /// - public ActorAssetBuilder(string ID, string CopyFrom) : base(ID, CopyFrom) { } - } -} diff --git a/utils/Builders/ActorTraitBuilder.cs b/utils/Builders/ActorTraitBuilder.cs deleted file mode 100644 index e0dfed2..0000000 --- a/utils/Builders/ActorTraitBuilder.cs +++ /dev/null @@ -1,146 +0,0 @@ -using NeoModLoader.utils.SerializedAssets; -using Newtonsoft.Json; -using System.Collections.Concurrent; -using strings; - -namespace NeoModLoader.utils.Builders -{ - /// - /// A Method to get Additional custom stats depending on the actor - /// - public delegate BaseStats GetAdditionalBaseStatsMethod(Actor Actor); - /// - /// A Builder for creating Actor Traits - /// - public sealed class ActorTraitBuilder : BaseTraitBuilder - { - internal static ConcurrentDictionary AdditionalBaseStatMethods = new(); - /// - public ActorTraitBuilder(string ID) : base(ID) - { - Group = S_TraitGroup.miscellaneous; - } - /// - protected override void LoadFromPath(string FilePathToBuild) - { - SerializedActorTrait assetSerialized = JsonConvert.DeserializeObject(File.ReadAllText(FilePathToBuild)); - Asset = SerializedActorTrait.ToAsset(assetSerialized); - } - /// - public ActorTraitBuilder(string ID, bool LoadImmediately) : base(ID, LoadImmediately) { } - /// - public ActorTraitBuilder(string ID, string CopyFrom) : base(ID, CopyFrom) { } - void LinkWithLibrary() - { - if (Asset.in_training_dummy_combat_pot) - { - Library.pot_traits_combat.Add(Asset); - } - if (Asset.is_mutation_box_allowed) - { - Library.pot_traits_mutation_box.Add(Asset); - } - if (Asset.rate_acquire_grow_up != 0) - { - for (int j = 0; j < Asset.rate_acquire_grow_up; j++) - { - Library.pot_traits_growup.Add(Asset); - } - } - if (Asset.rate_birth != 0) - { - for (int i = 0; i < Asset.rate_birth; i++) - { - Library.pot_traits_birth.Add(Asset); - } - } - } - /// - public override void Build(bool SetRarityAutomatically = false, bool AutoLocalize = true, bool LinkWithOtherAssets = false) - { - base.Build(SetRarityAutomatically, AutoLocalize, LinkWithOtherAssets); - LinkWithLibrary(); - Library.checkDefault(Asset); - Asset.only_active_on_era_flag = Asset.era_active_moon || Asset.era_active_night; - } - /// - /// (Optional) creates a method which gives custom stats to a actor who has this trait - /// - public GetAdditionalBaseStatsMethod AdditionalBaseStatsMethod { set - { - if (!AdditionalBaseStatMethods.TryAdd(Asset.id, value)) - { - AdditionalBaseStatMethods[Asset.id] = value; - } - } - } - /// - /// if true, actors cannot have this trait if they have the strong minded trait - /// - public bool AffectsMind { get { return Asset.affects_mind; } set { Asset.affects_mind = value; } } - /// - /// if true, actors can cure this trait and remove it - /// - public bool CanBeCured { get { return Asset.can_be_cured; } set { Asset.can_be_cured = value; } } - /// - /// when actors with the subspecies trait accelerated healing age, they can remove traits which have this set to true - /// - public bool RemovedByAcceleratedHealing { get { return Asset.can_be_removed_by_accelerated_healing; } set { Asset.can_be_removed_by_accelerated_healing = value; } } - /// - /// if true, Divine Light can remove this trait from actors - /// - public bool RemovedByDevineLight { get { return Asset.can_be_removed_by_accelerated_healing; } set { Asset.can_be_removed_by_divine_light = value; } } - /// - /// if true, this actor trait represents a combat skill, and actors could try to gain this trait - /// - public bool IsCombatSkill { get { return Asset.in_training_dummy_combat_pot; } set { Asset.in_training_dummy_combat_pot = value; } } - /// - /// if true, the base stats of this trait will only be applied to the actor in the age of dark - /// - public bool ActiveInDarkEra { get { return Asset.era_active_night; } set { Asset.era_active_night = value;} } - /// - /// if true, the base stats of this trait will only be applied to the actor in the age of moon - /// - public bool ActiveInMoonEra { get { return Asset.era_active_moon; } set { Asset.era_active_moon = value; } } - /// - /// The ID of a WILD kingdom (Default, Non Civ) that this trait forces the actor to, the trait must add the forcedkingdomadd effect to its ActionOnAdd, you should also add it to ActionOnLoad - /// - public string ForcedKingdomID { get { return Asset.forced_kingdom; } set { Asset.forced_kingdom = value; } } - /// - /// if true, actors can get this trait from mutation box - /// - public bool UsedInMutationBox { get { return Asset.is_mutation_box_allowed; } set { Asset.is_mutation_box_allowed = value; } } - /// - /// when actors try to make best friends, this goes into account, with increased likeability increasing the chance they become friends - /// - public float ActorsLikeability { get { return Asset.likeability; } set { Asset.likeability = value; } } - /// - /// used for when actors try to make best friends, relations between kings, and kings with city leaders, if the other actor has a trait which is an opposite of this trait, the likeability factor is increased by this devided by 100 - /// - public int OppositeTraitLikeability { get { return Asset.opposite_trait_mod; } set { Asset.opposite_trait_mod = value; } } - /// - /// When an actor turns into an adult, he can get new traits, the chance of getting this trait is determined by its rate - /// - public int RateAcquireWhenGrownUp { get { return Asset.rate_acquire_grow_up; } set { Asset.rate_acquire_grow_up = value; } } - /// - /// the chance of a child inheriting this trait from a parent, also if it is above 0 cloned actors will get this trait from their original - /// - public int RateBirth { get { return Asset.rate_birth; } set { Asset.rate_birth = value; } } - /// - /// same thing as rate birth, if this is 0 it will become rate inherit * 10 - /// - public int RateInherit { get { return Asset.rate_inherit; } set { Asset.rate_inherit = value; } } - /// - /// When creating the zombie varient of a actor asset, the game removes any default traits of the actor asset which have this enabled - /// - public bool RemoveForZombies { get { return Asset.remove_for_zombie_actor_asset; } set { Asset.remove_for_zombie_actor_asset = value; } } - /// - /// basically the same as OppositeTraitLikeability but applied when both actors have this trait - /// - public int SameTraitLikeability { get { return Asset.same_trait_mod; } set { Asset.same_trait_mod = value; } } - /// - /// doesnt do anything - /// - public TraitType Type { get { return Asset.type; } set { Asset.type = value; } } - } -} \ No newline at end of file diff --git a/utils/Builders/AssetBuilder.cs b/utils/Builders/AssetBuilder.cs deleted file mode 100644 index 3ada04e..0000000 --- a/utils/Builders/AssetBuilder.cs +++ /dev/null @@ -1,112 +0,0 @@ -using NeoModLoader.services; -using NeoModLoader.utils.SerializedAssets; -using Newtonsoft.Json; -namespace NeoModLoader.utils.Builders -{ - /// - /// The Base Class for building assets, you only use this if your mod has custom assets, otherwise use its derived types!!!!!!!!!!! - /// - public class AssetBuilder : Builder where A : Asset, new() where AL : AssetLibrary - { - private AssetBuilder() { Library = GetLibrary(); } - /// - /// The Asset being built - /// - public A Asset { get; protected set; } - /// - /// the Library to add the asset to - /// - public readonly AL Library; - /// - /// Used so the child classes can create their asset before the builder inititates - /// - protected virtual A CreateAsset(string ID) { return new A() { id = ID }; } - /// - /// Initiates the builder - /// - protected virtual void Init() { } - /// - /// Loads the asset from FilePathToBuild - /// - protected virtual void LoadFromPath(string FilePathToBuild) - { - SerializableAsset assetSerialized = JsonConvert.DeserializeObject>(File.ReadAllText(FilePathToBuild)); - Asset = SerializableAsset.ToAsset(assetSerialized); - } - void LoadAssetFromPath(string FilePathToBuild) - { - try - { - LoadFromPath(FilePathToBuild); - } - catch - { - LogService.LogError($"the asset {Path.GetFileName(FilePathToBuild)} is outdated or corrupted!, make sure to serialize it on the latest version and use default serialization settings"); - } - } - /// - /// Creates a builder with a new asset with Id ID, other variables are default - /// - public AssetBuilder(string ID) : this() - { - Asset = CreateAsset(ID); - Init(); - } - internal string FilePathToBuild = null; - /// - /// Deserializes a Asset loaded from a file path - /// - /// - /// if LoadImmediatly is false, the asset will be loaded when built - /// - /// this path starts from the operating system root - /// the reason for this is when NML automatically loads file assets, it loads the assets before the mod is compiled, and so it then has to deserialize the assets after the mod is compiled because the assets could have delegates which point to the mod, and deserialization will produce an error if the delegates point to nothing - public AssetBuilder(string FilePath, bool LoadImmediately) : this() - { - if (LoadImmediately) - { - LoadAssetFromPath(FilePath); - } - else - { - FilePathToBuild = FilePath; - } - } - - /// - /// Creates a builder, and the asset being built is copied off a asset with ID CopyFrom - /// - public AssetBuilder(string ID, string CopyFrom) : this() - { - bool Cloned = CopyFrom != null; - if (Cloned) - { - Library.clone(out A Asset, Library.get(CopyFrom)); - Asset.id = ID; - this.Asset = Asset; - } - else - { - Asset = CreateAsset(ID); - } - Init(); - } - AL GetLibrary() { - return AssetManager._instance._list.OfType().FirstOrDefault() ?? throw new NotImplementedException($"No library found for {typeof(A).Name}!"); - } - /// - /// Builds The Asset - /// - public override void Build(bool LinkWithOtherAssets) - { - if (FilePathToBuild != null) - { - LoadAssetFromPath(FilePathToBuild); - } - Library.add(Asset); - base.Build(LinkWithOtherAssets); - } - /// - public override void LinkAssets() { } - } -} \ No newline at end of file diff --git a/utils/Builders/AssetPatches.cs b/utils/Builders/AssetPatches.cs deleted file mode 100644 index 0dc69e7..0000000 --- a/utils/Builders/AssetPatches.cs +++ /dev/null @@ -1,65 +0,0 @@ -using HarmonyLib; -using NeoModLoader.utils.Builders; -using System.Reflection.Emit; -using static NeoModLoader.utils.Builders.ActorTraitBuilder; - -namespace NeoModLoader.utils -{ - internal class AssetPatches - { - [HarmonyPatch(typeof(Actor), "updateStats")] - [HarmonyTranspiler] - static IEnumerable MergeWithCustomStats(IEnumerable instructions) - { - CodeMatcher Matcher = new CodeMatcher(instructions); - Matcher.MatchForward(false, new CodeMatch[] - { - new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BaseStats), nameof(BaseStats.clear))) - }); - Matcher.Advance(1); - Matcher.Insert(new CodeInstruction[] - { - new CodeInstruction(OpCodes.Ldarg_0), - new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(AssetPatches), nameof(MergeCustomStats))) - }); - return Matcher.Instructions(); - } - static void MergeCustomStats(Actor __instance) - { - foreach(ActorTrait trait in __instance.traits) - { - if(AdditionalBaseStatMethods.TryGetValue(trait.id, out GetAdditionalBaseStatsMethod method)) - { - __instance.stats.mergeStats(method(__instance)); - } - } - } - static BaseStats[] GetCustomStats(ActorTrait trait) - { - if(SelectedUnit.unit == null || !SelectedUnit.unit.hasTrait(trait)) - { - return Array.Empty(); - } - if(!AdditionalBaseStatMethods.TryGetValue(trait.id, out GetAdditionalBaseStatsMethod method)) - { - return Array.Empty(); - } - return new BaseStats[] { method(SelectedUnit.unit) }; - } - [HarmonyPatch(typeof(TooltipLibrary), "showTrait")] - [HarmonyTranspiler] - static IEnumerable ShowCustomStats(IEnumerable instructions) - { - CodeMatcher Matcher = new CodeMatcher(instructions); - Matcher.MatchForward(false, new CodeMatch[] - { - new CodeMatch(OpCodes.Call, AccessTools.Field(typeof(Array), nameof(Array.Empty))) - }); - Matcher.RemoveInstruction(); - Matcher.Insert(new CodeInstruction[] { - new CodeInstruction(OpCodes.Ldloc_0), - new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(AssetPatches), nameof(GetCustomStats))) }); - return Matcher.Instructions(); - } - } -} diff --git a/utils/Builders/AugmentationAssetBuilder.cs b/utils/Builders/AugmentationAssetBuilder.cs deleted file mode 100644 index 26464cb..0000000 --- a/utils/Builders/AugmentationAssetBuilder.cs +++ /dev/null @@ -1,115 +0,0 @@ -namespace NeoModLoader.utils.Builders -{ - /// - /// A Builder for building augmentation assets - /// - public class AugmentationAssetBuilder : UnlockableAssetBuilder where A : BaseAugmentationAsset, new() where AL : BaseLibraryWithUnlockables - { - /// - public AugmentationAssetBuilder(string FilePath, bool LoadImmediately) : base(FilePath, LoadImmediately) { } - /// - public AugmentationAssetBuilder(string ID) : base(ID) { } - /// - public AugmentationAssetBuilder(string ID, string CopyFrom) : base(ID, CopyFrom) { } - /// - /// the combat actions in this Asset, any actors with this Asset will have this actiom, and if this Asset is for a clan/subspecies/etc, any actors in that group will also have it - /// - public IEnumerable CombatActions { get - { - return Asset.combat_actions_ids; - } - set - { - foreach(string action in value) - { - Asset.addCombatAction(action); - } - } - } - void LinkDecisions() - { - if (Asset.decision_ids != null) - { - Asset.decisions_assets = new DecisionAsset[Asset.decision_ids.Count]; - for (int i = 0; i < Asset.decision_ids.Count; i++) - { - string tDecisionID = Asset.decision_ids[i]; - DecisionAsset tDecisionAsset = AssetManager.decisions_library.get(tDecisionID); - Asset.decisions_assets[i] = tDecisionAsset; - } - } - } - /// - public override void LinkAssets() - { - LinkDecisions(); - Asset.linkCombatActions(); - Asset.linkSpells(); - base.LinkAssets(); - } - /// - /// the Decisions (Neurons) in the Object with this Asset, if the object is a group like clan or subspecies, all actors in the group get this decision - /// - public IEnumerable Decisions { get { return Asset.decision_ids; } set - { - foreach (string action in value) - { - Asset.addDecision(action); - } - } } - /// - /// the spells in the Asset, which an actor can use - /// - public IEnumerable Spells { get { return Asset.spells_ids; } set - { - foreach(string action in value) - { - Asset.addSpell(action); - } - } } - /// - /// an action performed on something hit by this object or an object apart of a group with this trait - /// - public AttackAction AttackAction { get { return Asset.action_attack_target; } set { Asset.action_attack_target = value; } } - /// - /// The Action Performed on something, when this asset is added to it! - /// - public WorldActionTrait ActionWhenAdded { get { return Asset.action_on_augmentation_add; } set { Asset.action_on_augmentation_add = value; } } - /// - /// The Action Performed on something, when this asset is removed from it! - /// - public WorldActionTrait ActionWhenRemoved { get { return Asset.action_on_augmentation_remove; } set { Asset.action_on_augmentation_remove = value; } } - /// - /// The Action Performed on something with this asset, when that something is loaded from a save file - /// - public WorldActionTrait ActionOnLoad { get { return Asset.action_on_augmentation_load; } set { Asset.action_on_augmentation_load = value; } } - /// - /// The Action Performed on something, this keeps happening until that something is destroyed or this is removed - /// - public WorldAction ActonSpecialEffect { get { return Asset.action_special_effect; } set { Asset.action_special_effect = value; } } - /// - /// the cooldown for the ActionSpecialEffect - /// - public float SpecialEffectCoolDown { get { return Asset.special_effect_interval; } set { Asset.special_effect_interval = value; } } - /// - /// if false, it cant be removed from something - /// - public bool CanBeRemoved { get { return Asset.can_be_removed; } set { Asset.can_be_removed = value; } } - /// - /// if false, this asset cant be given to something, AND it cant be removed - /// - public bool CanBeGiven { get { return Asset.can_be_given; } set { Asset.can_be_given = value; } } - /// - /// The ID of the group this asset is in, you can find them in S_TraitGroup, S_EquipmentGroup, etc - /// - public string Group { get { return Asset.group_id; } set { Asset.group_id = value; } } - /// - /// The Priority used for when this asset is being displayed next to other assets in its Group - /// - public int Priority { get { return Asset.priority; } set { Asset.priority = value; } } - /// - /// If true, Meta Editors like the Plots Editor and Equipment Editor will show this asset - /// - public bool ShowInMetaEditor { get { return Asset.show_in_meta_editor; } set { Asset.show_in_meta_editor = value; } } - } -} diff --git a/utils/Builders/BaseTraitBuilder.cs b/utils/Builders/BaseTraitBuilder.cs deleted file mode 100644 index edaee99..0000000 --- a/utils/Builders/BaseTraitBuilder.cs +++ /dev/null @@ -1,355 +0,0 @@ -using FMOD; -using HarmonyLib; -using NeoModLoader.General; - -namespace NeoModLoader.utils.Builders -{ - /// - /// The Base Builder for Trait builders - /// - public class BaseTraitBuilder : AugmentationAssetBuilder where A : BaseTrait, new() where AL : BaseTraitLibrary - { - /// - public BaseTraitBuilder(string ID) : base(ID) { } - /// - public BaseTraitBuilder(string FilePath, bool LoadImmediately) : base(FilePath, LoadImmediately) { } - /// - public BaseTraitBuilder(string ID, string CopyFrom) : base(ID, CopyFrom) { } - - /// - protected override void Init() - { - Description1ID = null; - Description2ID = null; - NameID = (null); - } - /// - /// the traits in the asset's list of opposite traits, if a object has one of these traits it cannot add this trait - /// - public IEnumerable OppositeTraits - { - set - { - foreach (string trait in value) - { - Asset.addOpposite(trait); - } - } - get - { - return Asset.opposite_list; - } - } - /// - /// the tags in assets base stats meta - /// - public IEnumerable MetaTags - { - get - { - return Asset.base_stats_meta._tags; - } - set - { - foreach (string tag in value) - { - Asset.base_stats_meta.addTag(tag); - } - } - } - /// - /// sets traits which this trait automatically removes when it is added to a object - /// - public IEnumerable TraitsToRemove - { - set - { - Asset.traits_to_remove_ids = TraitsToRemove.ToArray(); - } - get - { - return Asset.traits_to_remove_ids; - } - } - /// - public override void Build(bool LinkWithOtherAssets) - { - Build(false, true, LinkWithOtherAssets); - } - /// - /// all other traits in the library will be added to the opposites list if the ShouldOppose function returns true - /// - /// a function which has a trait as input and outputs true if added to opposites list - public IEnumerable> OpposeAllOtherTraits { set { - foreach(Func func in value) - { - foreach (A asset in Library.list) - { - if (asset.id != Asset.id && func(asset)) - { - Asset.addOpposite(asset.id); - } - } - } - } } - void LinkWithActors() - { - foreach (ActorAsset tActorAsset in AssetManager.actor_library.list) - { - List traits = Library.getDefaultTraitsForMeta(tActorAsset); - if (traits != null && traits.Contains(Asset.id)) - { - Asset.default_for_actor_assets ??= new List(); - Asset.default_for_actor_assets.Add(tActorAsset); - } - } - } - void LinkWithTraits() - { - if (Asset.opposite_list != null && Asset.opposite_list.Count > 0) - { - Asset.opposite_traits = new HashSet(Asset.opposite_list.Count); - foreach (string tID in Asset.opposite_list) - { - A tOppositeTrait = Library.get(tID); - Asset.opposite_traits.Add(tOppositeTrait); - } - } - if (Asset.traits_to_remove_ids != null) - { - int tCount = Asset.traits_to_remove_ids.Length; - Asset.traits_to_remove = new A[tCount]; - for (int i = 0; i < tCount; i++) - { - string ID = Asset.traits_to_remove_ids[i]; - A tTraitToAdd = Library.get(ID); - Asset.traits_to_remove[i] = tTraitToAdd; - } - } - } - void CheckIcon() - { - if (string.IsNullOrEmpty(Asset.path_icon)) - { - Asset.path_icon = Library.icon_path + Asset.getLocaleID(); - } - } - void LinkWithBaseLibrary() - { - if (Asset.spawn_random_trait_allowed) - { - Library._pot_allowed_to_be_given_randomly.AddTimes(Asset.spawn_random_rate, Asset); - } - } - void SetRarityAutomatically() - { - if (Asset.unlocked_with_achievement) - { - Asset.rarity = Rarity.R3_Legendary; - } - else - { - bool tHasDecisions = Asset.decision_ids != null; - bool tHasSpells = Asset.spells_ids != null; - bool tHasCombatActions = Asset.combat_actions_ids != null; - bool tHasTag = Asset.base_stats.hasTags(); - bool tHasPlot = !string.IsNullOrEmpty(Asset.plot_id); - int tCount = 0; - if (Asset.action_death != null || Asset.action_special_effect != null || Asset.action_get_hit != null || Asset.action_birth != null || Asset.action_attack_target != null || Asset.action_on_augmentation_add != null || Asset.action_on_augmentation_remove != null || Asset.action_on_augmentation_load != null) - { - tCount++; - } - if (tHasDecisions) - { - tCount++; - } - if (tHasSpells) - { - tCount++; - } - if (tHasCombatActions) - { - tCount++; - } - if (tHasTag) - { - tCount++; - } - if (tHasPlot) - { - tCount++; - } - if (tCount > 0) - { - if (tCount == 1) - { - Asset.rarity = Rarity.R1_Rare; - } - else - { - Asset.rarity = Rarity.R2_Epic; - } - } - } - } - /// - /// when a creature/group is spawned, this is the chance they get the trait, this is not out of 100 - /// - public int ChanceToGetOnCreation { set { - Asset.spawn_random_rate = value; - Asset.spawn_random_trait_allowed = value > 0; - } - get - { - return Asset.spawn_random_rate; - } - } - /// - public override void LinkAssets() - { - LinkWithTraits(); - LinkWithActors(); - base.LinkAssets(); - } - /// - /// Builds the Trait, if autolocalize is on it will use the ID'S as the translated text - /// - /// - /// if you have opposite traits/traits to remove which you build after you build this, link it with the other traits after you build them! - /// - public virtual void Build(bool SetRarityAutomatically = false, bool AutoLocalize = true, bool LinkWithOtherAssets = false) - { - base.Build(LinkWithOtherAssets); - if (AutoLocalize) - { - Localize(Asset.special_locale_id, Asset.special_locale_description, Asset.special_locale_description_2); - } - if (SetRarityAutomatically) - { - this.SetRarityAutomatically(); - } - CheckIcon(); - LinkWithBaseLibrary(); - } - /// - /// the ID of the Localized Description, setting this does not fully localize the asset, you must either call Localize() or have a localization folder - /// - public string Description1ID { set - { - Asset.special_locale_description = value; - if (value == null) - { - Asset.has_description_1 = false; - } - else - { - Asset.has_description_1 = true; - } - } - get - { - return Asset.special_locale_description; - } - } - /// - /// the ID of the Localized 2nd Description, setting this does not fully localize the asset, you must either call Localize() or have a localization folder - /// - public string Description2ID - { - set - { - Asset.special_locale_description_2 = value; - if (value == null) - { - Asset.has_description_2 = false; - } - else - { - Asset.has_description_2 = true; - } - } - get - { - return Asset.special_locale_description_2; - } - } - /// - /// Localizes the Asset, you must set the ID's of the descriptions and name first - /// - public void Localize(string Name = null, string Description = null, string Description2 = null) - { - if (Name != null) { - LM.AddToCurrentLocale(Asset.special_locale_id, Name); - } - if (Description != null) - { - LM.AddToCurrentLocale(Asset.special_locale_description, Description); - } - if (Description2 != null) - { - LM.AddToCurrentLocale(Asset.special_locale_description_2, Description2); - } - } - /// - /// the ID of the Localized Name, setting this does not fully localize the asset, you must either call Localize() or have a localization folder - /// - public string NameID - { - set - { - Asset.special_locale_id = value; - if (value == null) - { - Asset.has_localized_id = false; - } - else - { - Asset.has_localized_id = true; - } - } - get - { - return Asset.special_locale_id; - } - } - /// - /// The Displayed Rarity of the Trait - /// - /// - /// also, sometimes this controls how common it is like in subspecies traits - /// - public Rarity Rarity { get { return Asset.rarity; } set { Asset.rarity = value; } } - /// - /// just like base stats, but mainly used to add Tags, not stats - /// - public BaseStats BaseStatsMeta { get { return Asset.base_stats_meta; } set { Asset.base_stats_meta = value; } } - /// - /// Not used for actor traits, but for kingdoms, subspecies, clans, etc. any actor born in that group will perform this action - /// - public WorldAction ActionOnBirth { get { return Asset.action_birth; } set { Asset.action_birth = value; } } - /// - /// used for actor traits and groups (kingdoms, clans, etc), any actor with the trait or in the group will perform this action on death - /// - public WorldAction ActionOnDeath { get { return Asset.action_death; } set { Asset.action_death = value; } } - /// - /// Used for groups (subspecies, clan, etc) whenever a actor in this group reaches their birthday (age goes up by one) they perform this action - /// - public WorldAction ActionOnGrowth { get { return Asset.action_growth; } set { Asset.action_growth = value;} } - /// - /// used for actor traits and group traits (traits for kingdoms, clans, etc) any actor with the trait or in the group with this trait perform this when they are hit - /// - public GetHitAction ActionGetHit { get { return Asset.action_get_hit; } set { Asset.action_get_hit = value; } } - /// - /// when an actor writes a book, any trait from his language, culture, his traits, and religion can be in the book and can be transfered to those who read it, a trait must have this set to true to be able to be written - /// - public bool CanBeInBook { get { return Asset.can_be_in_book; } set { Asset.can_be_in_book = value; } } - /// - /// Used for languages and cultures, for languages it is the chance (out of 100) that the book written in this language does its action, and for cultures it controls experience for actors, spread of culture, etc. - /// - public float CustomValue { get { return Asset.value; } set { Asset.value = value;} } - /// - /// this stores an ID of a plot asset, used for religions, if a religion trait has a plotID, the plot can be done by the religion with the trait - /// - public string PlotID { get { return Asset.plot_id; } set { Asset.plot_id = value; } } - } -} \ No newline at end of file diff --git a/utils/Builders/Builder.cs b/utils/Builders/Builder.cs deleted file mode 100644 index 0d25652..0000000 --- a/utils/Builders/Builder.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace NeoModLoader.utils.Builders -{ - /// - /// The Base Class For All Builders - /// - public abstract class Builder - { - /// - /// Builds Something - /// - public virtual void Build(bool LinkWithOtherAssets) { if(LinkWithOtherAssets) { LinkAssets(); } } - /// - /// links this builder with other assets - /// - public abstract void LinkAssets(); - } -} \ No newline at end of file diff --git a/utils/Builders/ClanTraitBuilder.cs b/utils/Builders/ClanTraitBuilder.cs deleted file mode 100644 index 4b68bfb..0000000 --- a/utils/Builders/ClanTraitBuilder.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace NeoModLoader.utils.Builders -{ - /// - /// A Builder to create clan traits - /// - public sealed class ClanTraitBuilder : BaseTraitBuilder - { - /// - public ClanTraitBuilder(string ID) : base(ID) { } - /// - public ClanTraitBuilder(string FilePath, bool LoadImmediately) : base(FilePath, LoadImmediately) { } - /// - public ClanTraitBuilder(string ID, string CopyFrom) : base(ID, CopyFrom) { } - - /// - /// Stats which are applied to Males in this clan - /// - public BaseStats BaseStatsMale - { - get { return Asset.base_stats_male; } - set { Asset.base_stats_male = value; } - } - /// - /// Stats which are applied to Females in this clan - /// - public BaseStats BaseStatsFemale - { - get { return Asset.base_stats_female; } - set { Asset.base_stats_female = value; } - } - } -} diff --git a/utils/Builders/CultureTraitBuilder.cs b/utils/Builders/CultureTraitBuilder.cs deleted file mode 100644 index c9ac926..0000000 --- a/utils/Builders/CultureTraitBuilder.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace NeoModLoader.utils.Builders -{ - /// - /// A Builder to build culture traits - /// - public sealed class CultureTraitBuilder : BaseTraitBuilder - { - /// - public CultureTraitBuilder(string ID) : base(ID) { } - /// - public CultureTraitBuilder(string FilePath, bool LoadImmediately) : base(FilePath, LoadImmediately) { } - /// - public CultureTraitBuilder(string ID, string CopyFrom) : base(ID, CopyFrom) { } - /// - /// the weapons which this culture produces - /// - public IEnumerable Weapons { get { return Asset.related_weapons_ids; } set { foreach (string weapon in value) { Asset.addWeaponSpecial(weapon); } } } - /// - /// the weapon sub types which this culture produces - /// - public IEnumerable WeaponSubTypes { get { return Asset.related_weapon_subtype_ids; } set { foreach (string weapon in value) { Asset.addWeaponSubtype(weapon); } } } - /// - /// used for a cultures building layout plan, the zone checker determines weather buildings can be placed in the target zone or not - /// - public PassableZoneChecker TownLayoutPlan - { - get { return Asset.passable_zone_checker; } - set - { - Asset.setTownLayoutPlan(value); - } - } - /// - public override void LinkAssets() - { - if (Asset.town_layout_plan) - { - OpposeAllOtherTraits = new[] { (CultureTrait trait) => trait.town_layout_plan }; - } - base.LinkAssets(); - } - } -} \ No newline at end of file diff --git a/utils/Builders/GroupAssetBuilder.cs b/utils/Builders/GroupAssetBuilder.cs deleted file mode 100644 index e194d3f..0000000 --- a/utils/Builders/GroupAssetBuilder.cs +++ /dev/null @@ -1,47 +0,0 @@ -using NeoModLoader.General; -using UnityEngine; - -namespace NeoModLoader.utils.Builders -{ - /// - /// A Builder to create group/category assets - /// - public sealed class GroupAssetBuilder : AssetBuilder> where A : BaseCategoryAsset, new() - { - /// - public GroupAssetBuilder(string ID) : base(ID) { } - /// - public GroupAssetBuilder(string FilePath, bool LoadImmediately) : base(FilePath, LoadImmediately) { } - /// - public GroupAssetBuilder(string ID, string CopyFrom) : base(ID, CopyFrom) { } - /// - public override void Build(bool LinkWithOtherAssets) - { - Localize(); - Build(LinkWithOtherAssets); - } - /// - /// Localizes the name - /// - public void Localize(string LocalName = null) - { - LocalName ??= Asset.getLocaleID(); - LM.AddToCurrentLocale(Asset.getLocaleID(), LocalName); - } - /// - /// The ID used for localization - /// - public string Name { get { return Asset.name; } set { Asset.name = value; } } - /// - /// A Hex Value that represents the color - /// - public string ColorHexCode { get { return Asset.color; } set { Asset.color = value; } } - /// - /// Sets the color using a Color - /// - public void SetColor(Color color) - { - ColorHexCode = Toolbox.colorToHex(color); - } - } -} \ No newline at end of file diff --git a/utils/Builders/ItemBuilder.cs b/utils/Builders/ItemBuilder.cs deleted file mode 100644 index a946cb0..0000000 --- a/utils/Builders/ItemBuilder.cs +++ /dev/null @@ -1,265 +0,0 @@ -using NeoModLoader.General; -using NeoModLoader.utils.SerializedAssets; -using Newtonsoft.Json; -using UnityEngine; - -namespace NeoModLoader.utils.Builders -{ - /// - /// A Builder to build items - /// - /*public sealed class ItemBuilder : AugmentationAssetBuilder // congrats melvin, your ItemBuilder broke on a fundamental level within 1 singular update of existing somehow, I am under severe time pressure rn and cannot be bothered to look into the cause so have fun whenever you see this Ig - { - static string GetEquipmentType(EquipmentType pType) => pType switch - { - EquipmentType.Weapon => "$melee", - EquipmentType.Helmet => "$helmet", - EquipmentType.Armor => "$armor", - EquipmentType.Boots => "$boots", - EquipmentType.Ring => "$ring", - EquipmentType.Amulet => "$amulet", - _ => "$equipment" - }; - /// - public ItemBuilder(string Path, bool LoadImmediately) : base(Path, LoadImmediately) { } - /// - public ItemBuilder(string ID, EquipmentType Type) : base(ID, GetEquipmentType(Type)) { } - /// - /// creates a weapon, and if projectileifranged is not null, a ranged weapon with projectileifranged being the ID of the projectile - /// - public ItemBuilder(string WeaponID, string ProjectileIfRanged = null) : base(WeaponID, "$melee") { - if (ProjectileIfRanged != null) - { - ConvertIntoRangedWeapon(ProjectileIfRanged); - } - } - /// - protected override void LoadFromPath(string FilePathToBuild) - { - SerializedItemAsset assetSerialized = JsonConvert.DeserializeObject(File.ReadAllText(FilePathToBuild)); - Asset = SerializedItemAsset.ToAsset(assetSerialized); - CultureTraitsThisWeaponIsIn = assetSerialized.CultureTraitsThisItemIsIn; - CultureTraitsThisWeaponsTypeIsIn = assetSerialized.CultureTraitsThisItemsTypeIsIn; - } - /// - protected override ItemAsset CreateAsset(string ID) - { - ItemAsset asset = new() - { - id = ID, - group_id = "sword", - pool = "equipment", - name_templates = new List() { "armor_name"} - }; - asset.setCost(0); - return asset; - } - /// - /// converts the Asset into a ranged weapon, its type must be Weapon to do this - /// - public void ConvertIntoRangedWeapon(string ProjectileID) - { - Asset.pool = "range"; - Asset.attack_type = WeaponType.Range; - Asset.projectile = ProjectileID; - Asset.base_stats["projectiles"] = 1f; - Asset.base_stats["damage_range"] = 0.6f; - } - /// - public override void LinkAssets() - { - foreach(string CultureTraitID in CultureTraitsThisWeaponIsIn) - { - AssetManager.culture_traits.get(CultureTraitID).addWeaponSpecial(Asset.id); - } - foreach (string CultureTraitID in CultureTraitsThisWeaponsTypeIsIn) - { - AssetManager.culture_traits.get(CultureTraitID).addWeaponSubtype(WeaponSubType); - } - if (Asset.item_modifier_ids != null) - { - Asset.item_modifiers = new ItemAsset[Asset.item_modifier_ids.Length]; - for (int i = 0; i < Asset.item_modifier_ids.Length; i++) - { - string tModID = Asset.item_modifier_ids[i]; - ItemAsset tModData = AssetManager.items_modifiers.get(tModID); - if (tModData == null) - { - BaseAssetLibrary.logAssetError("ItemLibrary: Item Modifier Asset not found", tModID); - } - else - { - Asset.item_modifiers[i] = tModData; - } - } - } - base.LinkAssets(); - } - /// - public override void Build(bool LinkWithOtherAssets) - { - Build(null, true, LinkWithOtherAssets); - } - /// - /// Builds the Item, if description is not null it will automatically localize - /// - /// The Description of the item, if null, localization will have to take place from a localize json file - /// is unlocked by default - /// links with other assets - public void Build(string Description = null, bool UnlockedByDefault = true, bool LinkWithOtherAssets = false) - { - if(Description != null) - { - Localize(Asset.getLocaleID(), Description); - } - AddWeaponsSprite(); - LinkWithLibrary(); - if (UnlockedByDefault) - { - UnlockByDefault(); - } - base.Build(LinkWithOtherAssets); - } - void LinkWithLibrary() - { - if (!Library.equipment_by_subtypes.ContainsKey(Asset.equipment_subtype)) - { - Library.equipment_by_subtypes.Add(Asset.equipment_subtype, new List()); - } - Library.equipment_by_subtypes[Asset.equipment_subtype].Add(Asset); - if (Asset.is_pool_weapon) - { - Library.pool_weapon_assets_all.Add(Asset); - } - if (!Asset.is_pool_weapon) - { - string tGroupId = Asset.group_id; - if (!Library.equipment_by_groups_all.ContainsKey(tGroupId)) - { - Library.equipment_by_groups_all.Add(tGroupId, new List()); - } - Library.equipment_by_groups_all[tGroupId].Add(Asset); - } - if (Asset.isUnlocked()) - { - if (Asset.is_pool_weapon && !Library.pool_weapon_assets_unlocked.Contains(Asset)) - { - Library.pool_weapon_assets_unlocked.Add(Asset); - } - if (!Asset.is_pool_weapon) - { - string tGroupId = Asset.group_id; - if (!Library.equipment_by_groups_unlocked.ContainsKey(tGroupId)) - { - Library.equipment_by_groups_unlocked.Add(tGroupId, new List()); - } - List tList = Library.equipment_by_groups_unlocked[tGroupId]; - if (!tList.Contains(Asset)) - { - tList.Add(Asset); - } - } - } - } - /// - /// the name templates of this item, a random template is chosen when the game uses them - /// - public IEnumerable NameTemplates - { - get { return Asset.name_templates; } - set { Asset.name_templates = value.ToList(); } - } - void AddWeaponsSprite() - { - var dictItems = ActorAnimationLoader._dict_items; - var sprite = Resources.Load("weapons/" + Asset.id); - dictItems.Add("w_" + Asset.id, new List() { sprite }); - } - /// - /// Localizes the Items name and description the current language - /// - public void Localize(string Name, string Description) - { - LM.AddToCurrentLocale(Asset.getLocaleID(), Name); - LM.AddToCurrentLocale(Asset.getDescriptionID(), Description); - } - /// - /// The ID of the Name, doesnt have to be set - /// - public string NameID { get { return Asset.translation_key; } set { Asset.translation_key = value; } } - /// - /// The Displayed Rarity of the Asset - /// - public Rarity Rarity { get { return Asset.quality; } set { Asset.quality = value; } } - /// - /// The Value of this equipment, used for when cities want to craft something, they prefer equipment with higher values - /// - public int EquipmentValue { get { return Asset.equipment_value; } set { Asset.equipment_value = value; } } - /// - /// the texture path to the animation that gets played when a actor holding this weapon attacks something - /// - public string SlashAnimationPath { get { return Asset.path_slash_animation; } set { Asset.path_slash_animation = value;} } - /// - /// if true, the weapon displayed in the actors HAND is animated - /// - public bool Animated { get { return Asset.animated; } set { Asset.animated = value; } } - /// - /// The ID of a group of items (subtype) this item is apart of, different cultures have different prefered sub types, cultures only create weapons apart of their prefered subtypes - /// - public string WeaponSubType { get { return Asset.equipment_subtype; } set { Asset.equipment_subtype = value; } } - /// - /// culture traits who have this items subtype added, MUST be a weapon - /// - /// - /// the builder must link its assets so the cultures actually add it - /// - public IEnumerable CultureTraitsThisWeaponsTypeIsIn; - /// - /// the cultures who have this item in their preferred weapons, it must be a weapon - /// - /// - /// the builder must link its assets so the cultures actually add it - /// - public IEnumerable CultureTraitsThisWeaponIsIn; - /// - /// the amount of coins a city has to spend to craft this item - /// - public int CoinCost { get { return Asset.cost_coins_resources; } set { Asset.cost_coins_resources = value; } } - /// - /// the amount of coins a city has to spend to craft/repair this time - /// - public int GoldCost { get { return Asset.cost_gold; } set { Asset.cost_gold = value; } } - /// - /// The ID of the first material and its amount a city needs to craft this item, and also the Minimum amount required - /// - public ValueTuple Resource1 { get { return new(Asset.cost_resource_id_1, Asset.cost_resource_1, Asset.minimum_city_storage_resource_1); } set { Asset.cost_resource_1 = value.Item2; Asset.minimum_city_storage_resource_1 = value.Item3; Asset.cost_resource_id_1 = value.Item1; } } - /// - /// The ID of the secound material and its amount a city needs to craft this item - /// - public ValueTuple Resource2 { get { return new(Asset.cost_resource_id_2, Asset.cost_resource_2); } set { Asset.cost_resource_id_2 = value.Item1; Asset.cost_resource_2 = value.Item2; } } - /// - /// the durability of the item, by default its 100 - /// - public int Durability { get { return Asset.durability; } set { Asset.durability = value; } } - /// - /// if true, it must also have a SubType - /// - public bool CanBeCraftedByCities { get { return Asset.is_pool_weapon; } set { Asset.is_pool_weapon = value; } } - /// - /// the modifiers in this item's list, when it is created all of them are applied - /// - public IEnumerable ItemModifiers { get { return Asset.item_modifier_ids; } set { Asset.item_modifier_ids = value.ToArray(); } } - /// - /// the material of the item, doesnt change any properties, just for displaying - /// - public string Material { get { return Asset.material; } set { Asset.material = value; } } - /// - /// only used for SFX, if a weapon is metallic and a actor hits someone with it, it produces noise - /// - public bool Metallic { get { return Asset.metallic; } set { Asset.metallic = value; } } - /// - /// not used by the game at the moment! - /// - public int Rate { get { return Asset.pool_rate; } set { Asset.pool_rate = value; } } - }*/ -} \ No newline at end of file diff --git a/utils/Builders/ItemModifierBuilder.cs b/utils/Builders/ItemModifierBuilder.cs deleted file mode 100644 index 62afad0..0000000 --- a/utils/Builders/ItemModifierBuilder.cs +++ /dev/null @@ -1,92 +0,0 @@ -using NeoModLoader.General; - -namespace NeoModLoader.utils.Builders -{ - /// - /// A Builder which creates item modifiers! - /// - /*public sealed class ItemModifierBuilder : AugmentationAssetBuilder // same issue as item assets @melvin @melvin @melvin :3 - { - /// - public ItemModifierBuilder(string FilePath, bool LoadImmediately) :base(FilePath, LoadImmediately) { } - /// - /// A Modifier Builder - /// - public ItemModifierBuilder(string ID, int Tier = 1) : base(ID + Tier, ID+1) { Asset.mod_rank = Tier; Asset.mod_type = ID; } - void LinkWithLibrary() - { - for (int i = 0; i < Asset.rarity; i++) - { - if (Asset.pool.Contains("weapon")) - { - Library.pools["weapon"].Add(Asset); - } - if (Asset.pool.Contains("armor")) - { - Library.pools["armor"].Add(Asset); - } - if (Asset.pool.Contains("accessory")) - { - Library.pools["accessory"].Add(Asset); - } - } - } - /// - public override void Build(bool LinkWithOtherAssets) - { - Build(true, LinkWithOtherAssets); - } - /// - /// Builds the modifier - /// - public void Build(bool Localize = true, bool LinkWithOtherAssets = false) - { - LinkWithLibrary(); - if (Localize) - { - LM.AddToCurrentLocale(Asset.getLocaleID(), Asset.getLocaleID()); - } - base.Build(LinkWithOtherAssets); - } - /// - /// The Displayed Rarity of the Asset - /// - public Rarity Rarity { get { return Asset.quality; } set { Asset.quality = value; } } - /// - /// if true, the player can give this modifier to items - /// - public bool CanModifiersBeGiven { get { return Asset.mod_can_be_given; } set { Asset.mod_can_be_given = value; } } - /// - /// the pools of items (like armor, accessory, etc) this mod is in, any item pools with this added can have it added to an item created - /// - public IEnumerable ItemPools - { - set - { - foreach (string PoolID in value) - { - if (Asset.pool.Length > 0) - { - Asset.pool += "," + PoolID; - } - else - { - Asset.pool = PoolID; - } - } - } - get - { - return Asset.pool.Split(','); - } - } - /// - /// how common this modifier is, in the pools it is in. - /// - public int PoolAmount { get { return Asset.rarity; } set { Asset.rarity = value; } } - /// - /// The ID of the Name, doesnt have to be set - /// - public string NameID { get { return Asset.translation_key; } set { Asset.translation_key = value; } } - }*/ -} diff --git a/utils/Builders/MasterBuilder.cs b/utils/Builders/MasterBuilder.cs deleted file mode 100644 index 94eb3ed..0000000 --- a/utils/Builders/MasterBuilder.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace NeoModLoader.utils.Builders -{ - /// - /// A manager for your builders, meant so you can link all of your assets together - /// - public sealed class MasterBuilder - { - readonly List Builders = new(); - /// - /// Adds a builder - /// - public B AddBuilder(B Builder) where B : Builder - { - Builders.Add(Builder); - return Builder; - } - /// - /// Adds's builders - /// - public void AddBuilders(IEnumerable Builders) - { - if(Builders == null) - { - return; - } - this.Builders.AddRange(Builders); - } - /// - /// Builds all of the builders and links their assets together - /// - public void BuildAll() - { - foreach (var builder in Builders) - { - builder.Build(false); - } - foreach (var builder in Builders) - { - builder.LinkAssets(); - } - } - } -} \ No newline at end of file diff --git a/utils/Builders/SubspeciesTraitBuilder.cs b/utils/Builders/SubspeciesTraitBuilder.cs deleted file mode 100644 index 7d430b2..0000000 --- a/utils/Builders/SubspeciesTraitBuilder.cs +++ /dev/null @@ -1,197 +0,0 @@ -namespace NeoModLoader.utils.Builders -{ - /// - /// used for when building a subspecies trait - /// - public enum SubSpeciesTrait - { - /// - /// A Normal Subspecies trait - /// - Trait, - /// - /// this subspecies trait is a phenotype, linking it with a phenotype asset - /// - PhenoType, - /// - /// this subspecies trait is an egg, it controls the eggs produced from this subspecies (their shape, colors, hatch time) - /// - Egg, - /// - /// this trait is a skin mutation - /// - SkinMutation - } - /// - /// a builder which creates subspecies traits - /// - public sealed class SubspeciesTraitBuilder : BaseTraitBuilder - { - static string TraitToDerive(SubSpeciesTrait trait) => trait switch - { - SubSpeciesTrait.Trait => null, - SubSpeciesTrait.Egg => SubspeciesTraitLibrary.TEMPLATE_EGG, - SubSpeciesTrait.SkinMutation => SubspeciesTraitLibrary.TEMPLATE_SKIN_MUTATION, - _ => null - }; - /// - /// creates a subspecies trait (type egg) with a afterhatchfromeggaction - /// - /// - /// the afterhatchfromeggaction is performed when actors from this subspecies hatch from an egg - /// - public SubspeciesTraitBuilder(string ID, AfterHatchFromEggAction afterHatchFromEggAction) : this(ID, SubSpeciesTrait.Egg) - { - Asset.after_hatch_from_egg_action = afterHatchFromEggAction; - } - /// - /// creates a subspecies trait (type skin mutation), the overridepath species the path to the sprites which overrides the normal sprites - /// - /// - /// an example would be actors/species/mutations/mutation_skin_light_orb - /// any actors in this subspecies who are babys will not render their head if false - public SubspeciesTraitBuilder(string ID, string OverridePath, bool RenderChildHeads) : this(ID, SubSpeciesTrait.SkinMutation) - { - Asset.render_heads_for_children = RenderChildHeads; - Asset.sprite_path = OverridePath; - } - /// - /// builds an asset depending on the Type - /// - public SubspeciesTraitBuilder(string ID, SubSpeciesTrait Type) : base(ID, TraitToDerive(Type)) { - if (Type == SubSpeciesTrait.PhenoType) - { - UsesSpecialIconLogic = true; - PathIcon = "ui/Icons/iconPhenotype"; - Asset.id = "phenotype_skin" + "_" + ID; - Asset.phenotype_skin = true; - Asset.id_phenotype = ID; - Asset.group_id = "phenotypes"; - NameID = "subspecies_trait_phenotype"; - Description1ID = ("subspecies_trait_phenotype_info"); - Asset.spawn_random_trait_allowed = false; - } - else if (Type == SubSpeciesTrait.Egg) - { - Asset.id_egg = Asset.id; - Asset.sprite_path = "eggs/" + Asset.id_egg; - } - } - void LinkWithLibrary() - { - if (Asset.spawn_random_trait_allowed) - { - Library._pot_allowed_to_be_given_randomly.Add(Asset); - } - if (Asset.in_mutation_pot_add) - { - int tRate = Asset.rarity.GetRate(); - Library._pot_mutation_traits_add.AddTimes(tRate, Asset); - } - if (Asset.in_mutation_pot_remove) - { - int tRate2 = Asset.rarity.GetRate(); - Library._pot_mutation_traits_remove.AddTimes(tRate2, Asset); - } - if (Asset.phenotype_egg && Asset.after_hatch_from_egg_action != null) - { - Asset.has_after_hatch_from_egg_action = true; - } - } - /// - public override void Build(bool SetRarityAutomatically = false, bool AutoLocalize = true, bool LinkWithOtherAssets = false) - { - base.Build(SetRarityAutomatically, AutoLocalize, LinkWithOtherAssets); - Library.loadSpritesPaths(Asset); - LinkWithLibrary(); - } - /// - public override void LinkAssets() - { - if (Asset.id_phenotype != null) - { - PhenotypeAsset Phenotype = AssetManager.phenotype_library.get(Asset.id_phenotype); - Phenotype.subspecies_trait_id = Asset.id; - Asset.priority = Phenotype.priority; - } - if (Asset.is_mutation_skin) - { - OpposeAllOtherTraits = new[] { (SubspeciesTrait trait) => trait.is_mutation_skin }; - } - if (Asset.phenotype_skin) - { - OpposeAllOtherTraits = new[] { (SubspeciesTrait trait) => trait.phenotype_skin }; - } - if (Asset.phenotype_egg) - { - OpposeAllOtherTraits = new[] { (SubspeciesTrait trait) => trait.phenotype_egg }; - } - base.LinkAssets(); - - } - /// - public SubspeciesTraitBuilder(string FilePath, bool LoadImmediately) : base(FilePath, LoadImmediately) { } - /// - public SubspeciesTraitBuilder(string ID, string CopyFrom) : base(ID, CopyFrom) { } - /// - /// Used for phenotypes if true the icon will not use the path icon, instead it will use the phenotype color attached to the subspecies trait - /// - public bool UsesSpecialIconLogic { get { return Asset.special_icon_logic; } set { Asset.special_icon_logic = value; } } - /// - /// the file names used for actors in this subspecies's swim animations, along with its speed (default 10) - /// - /// - /// use ActorAnimationSequences as it already has lists of these for you - /// - public ValueTuple SwimAnimation { get { return new(Asset.animation_swim, Asset.animation_swim_speed); } set { Asset.animation_swim = value.Item1; Asset.animation_swim_speed = value.Item2; } } - /// - /// the file names used for actors in this subspecies's walk animations, along with its speed (default 10) - /// - /// - /// use ActorAnimationSequences as it already has lists of these for you - /// - public ValueTuple WalkAnimation { get { return new(Asset.animation_walk, Asset.animation_walk_speed); } set { Asset.animation_walk = value.Item1; Asset.animation_walk_speed = value.Item2; } } - /// - /// the file names used for actors in this subspecies's idle animations, along with its speed (default 10) - /// - /// - /// use ActorAnimationSequences as it already has lists of these for you - /// - public ValueTuple IdleAnimation { get { return new(Asset.animation_idle, Asset.animation_idle_speed); } set { Asset.animation_idle = value.Item1; Asset.animation_idle_speed = value.Item2; } } - /// - /// if true, when subspecies's mutate, they can get this triat, the less its rarity the higher the chance - /// - public bool CanBeAddedFromMutations { get { return Asset.in_mutation_pot_add; } set { Asset.in_mutation_pot_add = value; } } - /// - /// if true, when subspecies's mutate, they can get this triat removed, the less its rarity the higher the chance - /// - public bool CanbeRemovedFromMutations { get { return Asset.in_mutation_pot_remove; } set { Asset.in_mutation_pot_remove = value; } } - /// - /// used if the trait is a skin mutation, this chooses the female skins used - /// - /// names used are like "female_1" for example - public List FemaleSkins { get { return Asset.skin_citizen_female; } set { Asset.skin_citizen_female = value; } } - /// - /// used if the trait is a skin mutation, this chooses the male skins used - /// - /// names used are like "male_1" for example - public List MaleSkins { get { return Asset.skin_citizen_male; } set { Asset.skin_citizen_male = value; } } - /// - /// used if the trait is a skin mutation, this chooses the warrior skins used - /// - /// names used are like "warrior_1" for example - public List WarriorSkins { get { return Asset.skin_warrior; } set { Asset.skin_warrior = value; } } - /// - /// if true, any resources whose diet list has a tag apart of this assets meta tags, any subspecies's with this trait will consume that resource - /// - public bool DietRelated { get { return Asset.is_diet_related; } set { Asset.is_diet_related = value; } } - /// - /// when a zombie subspecies is created they will remove remove any traits with this set to true - /// - public bool RemoveIfZombieSubSpecies { get { return Asset.remove_for_zombies; } set { Asset.remove_for_zombies = value; } } - /// - /// if true, any actors in this subspecies will not rotate when unconscious - /// - public bool DontRotateWhenUnconscious { get { return Asset.prevent_unconscious_rotation; } set { Asset.prevent_unconscious_rotation = value; } } - } -} \ No newline at end of file diff --git a/utils/Builders/UnlockableAssetBuilder.cs b/utils/Builders/UnlockableAssetBuilder.cs deleted file mode 100644 index ebcf978..0000000 --- a/utils/Builders/UnlockableAssetBuilder.cs +++ /dev/null @@ -1,80 +0,0 @@ -namespace NeoModLoader.utils.Builders -{ - /// - /// A builder for building unlockable assets - /// - public class UnlockableAssetBuilder : AssetBuilder where A : BaseUnlockableAsset, new() where AL : BaseLibraryWithUnlockables - { - /// - public UnlockableAssetBuilder(string ID) : base(ID) { BaseStats = new BaseStats(); } - /// - public UnlockableAssetBuilder(string FilePath, bool LoadImmediately) : base(FilePath, LoadImmediately) { } - /// - public UnlockableAssetBuilder(string ID, string CopyFrom) : base(ID, CopyFrom) { } - /// - /// if true, this asset should be discovered by the player to be used - /// - public bool NeedsToBeExplored { set { Asset.needs_to_be_explored = value; } get { return Asset.needs_to_be_explored; } } - void LinkWithAchievment() - { - if (Asset.unlocked_with_achievement) - { - Achievement pAchievement = AssetManager.achievements.get(Asset.achievement_id); - if (pAchievement.unlock_assets == null) - { - pAchievement.unlock_assets = new List(); - pAchievement.unlocks_something = true; - } - pAchievement.unlock_assets.Add(Asset); - } - } - /// - public override void LinkAssets() - { - LinkWithAchievment(); - } - /// - /// the asset unlocked if this achievment has been unlocked - /// - public string AchievmentToUnlockThis { set { Asset.unlocked_with_achievement = value != null; Asset.achievement_id = value; } - get { return Asset.achievement_id; } - } - /// - /// makes the asset available by default - /// - public void UnlockByDefault() - { - Asset.unlocked_with_achievement = false; - Asset.achievement_id = null; - Asset.needs_to_be_explored = false; - } - /// - /// the stats of this asset - /// - /// - /// an example would be Stats = new(){ {"health", 2}, {"armor", 2} }; - /// - public Dictionary Stats - { - set - { - foreach (KeyValuePair valueTuple in value) - { - BaseStats[valueTuple.Key] = valueTuple.Value; - } - } - } - /// - /// The Stats that are applied to the thing that has this asset, like a actor or a Clan - /// - public BaseStats BaseStats { get { return Asset.base_stats; } set { Asset.base_stats = value; } } - /// - /// the path to the icon, starting from the root directory (GameResources) - /// - public string PathIcon { get { return Asset.path_icon; } set { Asset.path_icon = value;} } - /// - /// if true, the Knowledge Window will display this asset - /// - public bool ShowInKnowledgeWindow { get { return Asset.show_in_knowledge_window; } set { Asset.show_in_knowledge_window = value; } } - } -} diff --git a/utils/ResourcesPatch.cs b/utils/ResourcesPatch.cs index 3c8d172..0992d81 100644 --- a/utils/ResourcesPatch.cs +++ b/utils/ResourcesPatch.cs @@ -2,7 +2,6 @@ using HarmonyLib; using NeoModLoader.api.exceptions; using NeoModLoader.services; -using NeoModLoader.utils.Builders; using Newtonsoft.Json; using UnityEngine; using UnityEngine.U2D; @@ -82,51 +81,28 @@ public static Object[] LoadResourceFile(ref string path, ref string pLowerPath) LoadTextAsset(path) }; } - static Builder LoadAsset(string Path, string Extention) => Extention switch - { - //"actorasset" => new ActorAssetBuilder(Path, false), - ".actortraitasset" => new ActorTraitBuilder(Path, false), - ".subspeciestraitasset" => new SubspeciesTraitBuilder(Path, false), - //".itemasset" => new ItemBuilder(Path, false), // had to comment out because whatever generics system melvin set up for this broke and I don't have time to look into it - //".itemmodifierasset" => new ItemModifierBuilder(Path, false), // same issue as above - ".clantraitasset" => new ClanTraitBuilder(Path, false), - ".culturetraitasset" => new CultureTraitBuilder(Path, false), - ".actortraitgroupasset" => new GroupAssetBuilder(Path, false), - ".achievementgroupasset" => new GroupAssetBuilder(Path, false), - ".clantraitgroupasset" => new GroupAssetBuilder(Path, false), - ".culturetraitgroupasset" => new GroupAssetBuilder(Path, false), - ".itemgroupasset" => new GroupAssetBuilder(Path, false), - ".kingdomtraitgroupasset" => new GroupAssetBuilder(Path, false), - ".languagetraitgroupasset" => new GroupAssetBuilder(Path, false), - ".plotcategoryasset" => new GroupAssetBuilder(Path, false), - ".religiontraitgroupasset" => new GroupAssetBuilder(Path, false), - ".subspeciestraitgroupasset" => new GroupAssetBuilder(Path, false), - ".worldlawgroupasset" => new GroupAssetBuilder(Path, false), - _ => throw new NotSupportedException($"the asset {Extention} has not been supported yet!"), - }; /// /// doesnt return anything, simply adds the wav to the wav library that contains all the custom sounds /// - private static void LoadWavFile(string path) + private static void LoadWavFile(string abspath, string path) { - string Name = Path.GetFileNameWithoutExtension(path); - if (CustomAudioManager.AudioWavLibrary.ContainsKey(Name)) + if (CustomAudioManager.AudioWavLibrary.ContainsKey(path)) { - LogService.LogError($"The Sound file {Name} has already been loaded!"); + LogService.LogError($"The Sound file {path} has already been loaded!"); return; } WavContainer container; try { container = JsonConvert.DeserializeObject( - File.ReadAllText(Path.GetDirectoryName(path) + "/" + Name + ".json")); - container.Path = path; + File.ReadAllText(Path.GetDirectoryName(abspath) + "/" + Path.GetFileNameWithoutExtension(abspath) + ".json")); + container.Path = abspath; } catch (Exception) { - container = new WavContainer(path, SoundMode.Stereo3D, 50f); + container = new WavContainer(abspath, SoundMode.Stereo3D, 50f); } - CustomAudioManager.AudioWavLibrary.Add(Name, container); + CustomAudioManager.AudioWavLibrary.Add(path, container); } private static TextAsset LoadTextAsset(string path) @@ -136,20 +112,14 @@ private static TextAsset LoadTextAsset(string path) return textAsset; } - internal static void LoadResourceFromFolder(string pFolder, out List Builders) + internal static void LoadResourceFromFolder(string pFolder, AssetLinker Linker) { - Builders = null; if (!Directory.Exists(pFolder)) return; var files = SystemUtils.SearchFileRecursive(pFolder, filename => !filename.StartsWith("."), dirname => !dirname.StartsWith(".")); foreach (var file in files) { - tree.AddFromFile(file.Replace(pFolder, "").Replace('\\', '/').Substring(1), file, out Builder builder); - if(builder != null) - { - Builders ??= new List(); - Builders.Add(builder); - } + tree.AddFromFile(file.Replace(pFolder, "").Replace('\\', '/').Substring(1), file, Linker); } } @@ -351,20 +321,19 @@ public void Add(string path, Object obj) /// /// Path to resource in tree /// Path to resource in actual filesystem - /// if your folder contains asset files (.actorasset, .itemasset) pass a master builder to load these assets, then make it buildall - public void AddFromFile(string path, string absPath, out Builder Builder) + /// Asset Loader + public void AddFromFile(string path, string absPath, AssetLinker Linker) { - Builder = null; string lower_path = path.ToLower(); if (lower_path.EndsWith(".meta") || lower_path.EndsWith("sprites.json")) return; if (lower_path.EndsWith(".wav")) { - LoadWavFile(absPath); + LoadWavFile(absPath, lower_path.Replace(".wav", "")); return; } - if (lower_path.EndsWith("asset")) + if (Path.GetExtension(lower_path).EndsWith("asset") || Path.GetExtension(lower_path).EndsWith("trait")) { - Builder = LoadAsset(absPath, Path.GetExtension(lower_path)); + Linker.AssetFilePaths.Add(absPath); return; } string parent_path = Path.GetDirectoryName(lower_path); diff --git a/utils/SerializedAssets/SerializableAsset.cs b/utils/SerializableAsset.cs similarity index 57% rename from utils/SerializedAssets/SerializableAsset.cs rename to utils/SerializableAsset.cs index 1656d6a..1dd25ab 100644 --- a/utils/SerializedAssets/SerializableAsset.cs +++ b/utils/SerializableAsset.cs @@ -1,36 +1,30 @@ -using Newtonsoft.Json.Linq; +using NeoModLoader.services; +using Newtonsoft.Json.Linq; using System.Reflection; -namespace NeoModLoader.utils.SerializedAssets +namespace NeoModLoader.utils { /// /// Because delegates like worldaction cannot be serialized, this is used so you can serialize them /// [Serializable] - public class SerializableAsset where A : Asset, new() + public class SerializableAsset { /// /// the variables of the asset /// public Dictionary Variables = new(); /// - /// the delegates of the asset - /// - /// - /// the way it stores delegates is that it stores their name, the path to their class, and then searches the assembly for a matching delegate - /// - public Dictionary Delegates = new(); - /// /// takes delegates and variables from an asset and takes them to a serializable asset /// - public static void Serialize(A Asset, SerializableAsset asset) + public static void Serialize(Asset Asset, SerializableAsset asset) { - foreach (FieldInfo field in typeof(A).GetFields()) + foreach (FieldInfo field in Asset.GetType().GetFields()) { object Value = field.GetValue(Asset); if (Value is Delegate value) { - asset.Delegates.Add(field.Name, value.AsString(false)); + asset.Variables.Add(field.Name, value.AsString(false)); } else { @@ -41,19 +35,27 @@ public static void Serialize(A Asset, SerializableAsset asset) /// /// Converts the augmentation asset to a serializable version /// - public static SerializableAsset FromAsset(A Asset) + public static SerializableAsset FromAsset(Asset Asset) { - SerializableAsset asset = new(); + SerializableAsset asset = new(); Serialize(Asset, asset); return asset; } /// /// takes delegates and variables from a serializable asset and takes them to a asset /// - public static void Deserialize(SerializableAsset Asset, A asset) + public static void Deserialize(SerializableAsset Asset, Asset asset) { static object GetRealValueOfObject(object Value, Type Type) { + if(Value == null) + { + return null; + } + if (typeof(Delegate).IsAssignableFrom(Type)) + { + return (Value as string).AsDelegate(Type); + } if (Type == typeof(int)) { return Convert.ToInt32(Value); @@ -62,22 +64,27 @@ static object GetRealValueOfObject(object Value, Type Type) { return Convert.ToSingle(Value); } - else if (Value is JObject JObject) + else if (typeof(Enum).IsAssignableFrom(Type)) { - return JObject.ToObject(Type); + return Enum.ToObject(Type, Convert.ToInt32(Value)); } - return Value; - } - foreach (FieldInfo field in typeof(A).GetFields()) - { - if (typeof(Delegate).IsAssignableFrom(field.FieldType)) + else if (Value is JObject JObject) { - if (Asset.Delegates.TryGetValue(field.Name, out string Delegate)) + try + { + return JObject.ToObject(Type); + } + catch(Exception e) { - field.SetValue(asset, Delegate.AsDelegate(field.FieldType)); + LogService.LogWarning($"Warning: the field {Type.Name} of Asset {Type.DeclaringType} is invalid."); + return null; } } - else if (Asset.Variables.TryGetValue(field.Name, out object Value)) + return Value; + } + foreach (FieldInfo field in asset.GetType().GetFields()) + { + if (Asset.Variables.TryGetValue(field.Name, out object Value)) { field.SetValue(asset, GetRealValueOfObject(Value, field.FieldType)); } @@ -86,9 +93,9 @@ static object GetRealValueOfObject(object Value, Type Type) /// /// converts the serializable version to its asset /// - public static A ToAsset(SerializableAsset Asset) + public static Asset ToAsset(SerializableAsset Asset, Type AssetType) { - A asset = new(); + Asset asset = Activator.CreateInstance(AssetType) as Asset; Deserialize(Asset, asset); return asset; } diff --git a/utils/SerializedAssets/SerializedActorTrait.cs b/utils/SerializedAssets/SerializedActorTrait.cs deleted file mode 100644 index 7ba39c0..0000000 --- a/utils/SerializedAssets/SerializedActorTrait.cs +++ /dev/null @@ -1,41 +0,0 @@ -using NeoModLoader.utils.Builders; - -namespace NeoModLoader.utils.SerializedAssets -{ - /// - /// a serializable actor trait, including its custom additional base stats method - /// - public class SerializedActorTrait : SerializableAsset - { - /// - /// the class and the method of the additionalbasestatsmethod - /// - public string AdditionalBaseStatsMethod; - /// - /// Converts the actor trait asset to a serializable version - /// - public static SerializedActorTrait FromAsset(ActorTrait Asset, GetAdditionalBaseStatsMethod Method = null) - { - SerializedActorTrait asset = new SerializedActorTrait(); - Serialize(Asset, asset); - if (Method != null) - { - asset.AdditionalBaseStatsMethod = Method.AsString(false); - } - return asset; - } - /// - /// Converts the serializable version to a actor trait asset - /// - public static ActorTrait ToAsset(SerializedActorTrait Asset) - { - ActorTrait asset = new(); - Deserialize(Asset, asset); - if (Asset.AdditionalBaseStatsMethod != null) - { - ActorTraitBuilder.AdditionalBaseStatMethods.TryAdd(asset.id, Asset.AdditionalBaseStatsMethod.AsDelegate()); - } - return asset; - } - } -} diff --git a/utils/SerializedAssets/SerializedItemAsset.cs b/utils/SerializedAssets/SerializedItemAsset.cs deleted file mode 100644 index 1d4e16b..0000000 --- a/utils/SerializedAssets/SerializedItemAsset.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace NeoModLoader.utils.SerializedAssets -{ - /// - /// a serializable item asset, including culture traits which have it and its type - /// - public class SerializedItemAsset : SerializableAsset - { - internal string[] CultureTraitsThisItemIsIn; - internal string[] CultureTraitsThisItemsTypeIsIn; - /// - /// Converts the item asset to a serializable version - /// - public static SerializedItemAsset FromAsset(ItemAsset Asset, IEnumerable cultureTraitsItem = null, IEnumerable cultureTraitsType = null) - { - SerializedItemAsset asset = new(); - Serialize(Asset, asset); - if (cultureTraitsItem != null) - { - asset.CultureTraitsThisItemIsIn = cultureTraitsItem.ToArray(); - } - if (cultureTraitsType != null) - { - asset.CultureTraitsThisItemsTypeIsIn = cultureTraitsType.ToArray(); - } - return asset; - } - /// - /// Converts the serializable version to a actor trait asset - /// - public static ItemAsset ToAsset(SerializedItemAsset Asset) - { - ItemAsset asset = new(); - Deserialize(Asset, asset); - return asset; - } - } -} \ No newline at end of file diff --git a/utils/SoundUtils.cs b/utils/SoundUtils.cs index 7143f3c..8ca3887 100644 --- a/utils/SoundUtils.cs +++ b/utils/SoundUtils.cs @@ -134,6 +134,7 @@ static bool PlaySoundPatch(string pSoundPath, float pX, float pY, bool pGameView { return true; } + pSoundPath = pSoundPath.ToLower(); if (!AudioWavLibrary.ContainsKey(pSoundPath)) return true; LoadCustomSound(pSoundPath, pX, pY); return false; @@ -147,6 +148,7 @@ static bool PlayDrawingSoundPatch(string pSoundPath, float pX, float pY) { return true; } + pSoundPath = pSoundPath.ToLower(); if (!AudioWavLibrary.ContainsKey(pSoundPath)) return true; LoadDrawingSound(pSoundPath, pX, pY); return false; @@ -232,6 +234,7 @@ internal static void AddChannel(Channel channel, Transform AttachedTo = null, Ve /// public static void ModifyWavData(string ID, float Volume, SoundMode Mode, int LoopCount = 0, bool Ramp = false, SoundType Type = SoundType.Sound) { + ID = ID.ToLower(); if (!AudioWavLibrary.ContainsKey(ID)) { return;