protected internal void LateApplyStatusEffects(StatusEffect status) { if (!string.IsNullOrEmpty(this.ComplicationStatusIdentifier)) { var complicStatus = ResourcesPrefabManager.Instance.GetStatusEffectPrefab(this.ComplicationStatusIdentifier); if (complicStatus) { status.ComplicationStatus = complicStatus; } } if (!string.IsNullOrEmpty(RequiredStatusIdentifier)) { var required = ResourcesPrefabManager.Instance.GetStatusEffectPrefab(this.RequiredStatusIdentifier); if (required) { status.RequiredStatus = required; } } if (!string.IsNullOrEmpty(this.AmplifiedStatusIdentifier)) { var amp = ResourcesPrefabManager.Instance.GetStatusEffectPrefab(AmplifiedStatusIdentifier); if (amp) { At.SetField(status, "m_amplifiedStatus", amp); } else { SL.Log("StatusEffect.ApplyTemplate - could not find AmplifiedStatusIdentifier " + this.AmplifiedStatusIdentifier); } } // setup signature and finalize if (EffectBehaviour == EditBehaviours.Destroy) { UnityHelpers.DestroyChildren(status.transform); } Transform signature; if (status.transform.childCount < 1) { signature = new GameObject($"SIGNATURE_{status.IdentifierName}").transform; signature.parent = status.transform; var comp = signature.gameObject.AddComponent <EffectSignature>(); comp.SignatureUID = new UID($"{NewStatusID}_{status.IdentifierName}"); } else { signature = status.transform.GetChild(0); } if (Effects != null) { if (signature) { SL_EffectTransform.ApplyTransformList(signature, Effects, EffectBehaviour); } else { SL.Log("Could not get effect signature!"); } } // fix StatusData for the new effects CompileEffectsToData(status); var sigComp = signature.GetComponent <EffectSignature>(); sigComp.enabled = true; var effects = signature.GetComponentsInChildren <Effect>(); sigComp.Effects = effects.ToList(); // Fix the effect signature for reference families if (status.FamilyMode == StatusEffect.FamilyModes.Reference) { signature.transform.parent = SL.CloneHolder; var family = status.EffectFamily; family.EffectSignature = sigComp; status.StatusData.EffectSignature = sigComp; } // Need to reset description after changing effects. At.Invoke(status, "RefreshLoc"); }
public static StatusData.EffectData[] GenerateEffectsData(List <Effect> effects, int level = 1) { // Create a list to generate the EffectData[] array into. var list = new List <StatusData.EffectData>(); // Iterate over the effects foreach (var effect in effects) { // Create a blank holder, in the case this effect isn't supported or doesn't serialize anything. var data = new StatusData.EffectData() { Data = new string[] { "" } }; var type = effect.GetType(); if (typeof(PunctualDamage).IsAssignableFrom(type)) { var comp = effect as PunctualDamage; // For PunctualDamage, Data[0] is the entire damage, and Data[1] is the impact. // Each damage goes "Damage : Type", and separated by a ';' char. // So we just iterate over the damage and serialize like that. var dmgString = ""; foreach (var dmg in comp.Damages) { if (dmgString != "") { dmgString += ";"; } dmgString += $"{dmg.Damage * level}:{dmg.Type}"; } // finally, set data data.Data = new string[] { dmgString, comp.Knockback.ToString() }; } else if (typeof(AffectNeed).IsAssignableFrom(type)) { var fi = At.GetFieldInfo(typeof(AffectNeed), "m_affectQuantity"); data.Data = new string[] { ((float)fi.GetValue(effect) * level).ToString() }; } // For most AffectStat components, the only thing that is serialized is the AffectQuantity. else if (At.GetFieldInfo(type, "AffectQuantity") is FieldInfo fi_AffectQuantity) { data.Data = new string[] { ((float)fi_AffectQuantity.GetValue(effect) * level).ToString() }; } // AffectMana uses "Value" instead of AffectQuantity for some reason... else if (At.GetFieldInfo(type, "Value") is FieldInfo fi_Value) { data.Data = new string[] { ((float)fi_Value.GetValue(effect) * level).ToString() }; } else // otherwise maybe I need to add support for this effect... { //SL.Log("[StatusEffect] Unsupported effect: " + type, 1); } list.Add(data); } return(list.ToArray()); }
public virtual void SetStats(Character character) { if (character.GetComponent <PlayerCharacterStats>()) { CustomCharacters.FixStats(character); } var stats = character.GetComponent <CharacterStats>(); if (!stats) { return; } if (Health != null) { var m_maxHealthStat = (Stat)At.GetField(stats, "m_maxHealthStat"); m_maxHealthStat.AddStack(new StatStack(SL_STAT_ID, (float)Health - 100), false); } if (HealthRegen != null) { var m_healthRegenStat = (Stat)At.GetField(stats, "m_healthRegen"); m_healthRegenStat.AddStack(new StatStack(SL_STAT_ID, (float)HealthRegen), false); } if (ImpactResist != null) { var m_impactResistance = (Stat)At.GetField(stats, "m_impactResistance"); m_impactResistance.AddStack(new StatStack(SL_STAT_ID, (float)ImpactResist), false); } if (Protection != null) { var m_damageProtection = (Stat[])At.GetField(stats, "m_damageProtection"); m_damageProtection[0].AddStack(new StatStack(SL_STAT_ID, (float)Protection), false); } if (this.Barrier != null) { var m_barrier = (Stat)At.GetField(stats, "m_barrierStat"); m_barrier.AddStack(new StatStack(SL_STAT_ID, (float)Barrier), false); } if (Damage_Resists != null) { var m_damageResistance = (Stat[])At.GetField(stats, "m_damageResistance"); for (int i = 0; i < 6; i++) { m_damageResistance[i].AddStack(new StatStack(SL_STAT_ID, Damage_Resists[i]), false); } } if (Damage_Bonus != null) { var m_damageTypesModifier = (Stat[])At.GetField(stats, "m_damageTypesModifier"); for (int i = 0; i < 6; i++) { m_damageTypesModifier[i].AddStack(new StatStack(SL_STAT_ID, Damage_Bonus[i]), false); } } // status immunity if (this.Status_Immunity != null) { var immunities = new List <TagSourceSelector>(); foreach (var tagName in this.Status_Immunity) { if (CustomItems.GetTag(tagName) is Tag tag && tag != Tag.None) { immunities.Add(new TagSourceSelector(tag)); } } At.SetField(stats, "m_statusEffectsNaturalImmunity", immunities.ToArray()); } }
internal virtual void Internal_ApplyTemplate(StatusEffect status) { SL.Log("Applying Status Effect template: " + Name ?? status.name); SLPackManager.AddLateApplyListener(OnLateApply, status); CustomStatusEffects.SetStatusLocalization(status, Name, Description); if (status.StatusData == null) { status.StatusData = new StatusData(); } if (Lifespan != null) { status.StatusData.LifeSpan = (float)Lifespan; } if (RefreshRate != null) { status.RefreshRate = (float)RefreshRate; } if (this.Priority != null) { At.SetField(status, "m_priority", (int)this.Priority); } if (this.Purgeable != null) { At.SetField(status, "m_purgeable", (bool)this.Purgeable); } if (this.DelayedDestroyTime != null) { status.DelayedDestroyTime = (int)this.DelayedDestroyTime; } if (BuildupRecoverySpeed != null) { status.BuildUpRecoverSpeed = (float)BuildupRecoverySpeed; } if (IgnoreBuildupIfApplied != null) { status.IgnoreBuildUpIfApplied = (bool)IgnoreBuildupIfApplied; } if (DisplayedInHUD != null) { status.DisplayInHud = (bool)DisplayedInHUD; } if (IsHidden != null) { status.IsHidden = (bool)IsHidden; } if (IsMalusEffect != null) { status.IsMalusEffect = (bool)this.IsMalusEffect; } if (this.ActionOnHit != null) { At.SetField(status, "m_actionOnHit", (StatusEffect.ActionsOnHit) this.ActionOnHit); } if (this.RemoveRequiredStatus != null) { status.RemoveRequiredStatus = (bool)this.RemoveRequiredStatus; } if (this.NormalizeDamageDisplay != null) { status.NormalizeDamageDisplay = (bool)this.NormalizeDamageDisplay; } if (this.IgnoreBarrier != null) { status.IgnoreBarrier = (bool)this.IgnoreBarrier; } if (this.StatusIdentifier != this.TargetStatusIdentifier) { At.SetField(status, "m_effectType", new TagSourceSelector(Tag.None)); } if (Tags != null) { var tagSource = CustomTags.SetTagSource(status.gameObject, Tags, true); At.SetField(status, "m_tagSource", tagSource); } else if (!status.GetComponent <TagSource>()) { var tagSource = status.gameObject.AddComponent <TagSource>(); At.SetField(status, "m_tagSource", tagSource); } if (this.PlayFXOnActivation != null) { status.PlayFXOnActivation = (bool)this.PlayFXOnActivation; } if (this.VFXInstantiationType != null) { status.FxInstantiation = (StatusEffect.FXInstantiationTypes) this.VFXInstantiationType; } if (this.VFXPrefab != null) { if (this.VFXPrefab == SL_PlayVFX.VFXPrefabs.NONE) { status.FXPrefab = null; } else { var clone = GameObject.Instantiate(SL_PlayVFX.GetVfxSystem((SL_PlayVFX.VFXPrefabs) this.VFXPrefab)); GameObject.DontDestroyOnLoad(clone); status.FXPrefab = clone.transform; } } if (this.FXOffset != null) { status.FxOffset = (Vector3)this.FXOffset; } if (this.PlaySpecialFXOnStop != null) { status.PlaySpecialFXOnStop = (bool)this.PlaySpecialFXOnStop; } // setup family if (this.FamilyMode == null && this.StatusIdentifier != this.TargetStatusIdentifier) { // Creating a new status, but no unique bind family was declared. Create one. var family = new StatusEffectFamily { Name = this.StatusIdentifier + "_FAMILY", LengthType = StatusEffectFamily.LengthTypes.Short, MaxStackCount = 1, StackBehavior = StatusEffectFamily.StackBehaviors.IndependantUnique }; At.SetField(status, "m_bindFamily", family); At.SetField(status, "m_familyMode", StatusEffect.FamilyModes.Bind); } if (this.FamilyMode == StatusEffect.FamilyModes.Bind) { At.SetField(status, "m_familyMode", StatusEffect.FamilyModes.Bind); if (this.BindFamily != null) { At.SetField(status, "m_bindFamily", this.BindFamily.CreateAsBindFamily()); } } else if (this.FamilyMode == StatusEffect.FamilyModes.Reference) { At.SetField(status, "m_familyMode", StatusEffect.FamilyModes.Reference); if (this.ReferenceFamilyUID != null) { At.SetField(status, "m_stackingFamily", new StatusEffectFamilySelector() { SelectorValue = this.ReferenceFamilyUID }); } } // check for custom icon if (!string.IsNullOrEmpty(SerializedSLPackName) && !string.IsNullOrEmpty(SerializedSubfolderName) && SL.GetSLPack(SerializedSLPackName) is SLPack pack) { var dir = $@"{pack.GetPathForCategory<StatusCategory>()}\{SerializedSubfolderName}"; if (pack.FileExists(dir, "icon.png")) { var tex = pack.LoadTexture2D(dir, "icon.png"); var sprite = CustomTextures.CreateSprite(tex, CustomTextures.SpriteBorderTypes.NONE); status.OverrideIcon = sprite; At.SetField(status, "m_defaultStatusIcon", new StatusTypeIcon(Tag.None) { Icon = sprite }); } } }
public override void ApplyToItem(Item item) { base.ApplyToItem(item); var comp = item as ItemContainer; if (this.BaseContainerCapacity != null) { At.SetField(comp, "m_baseContainerCapacity", (float)this.BaseContainerCapacity); } if (this.SpecialType != null) { comp.SpecialType = (ItemContainer.SpecialContainerTypes) this.SpecialType; } if (this.OpenSound != null) { comp.OpenSoundOverride = (GlobalAudioManager.Sounds) this.OpenSound; } if (this.AllowOverCapacity != null) { comp.AllowOverCapacity = (bool)this.AllowOverCapacity; } if (this.CanContainMoney != null) { comp.CanContainMoney = (bool)this.CanContainMoney; } if (this.CanReceiveCharacterItems != null) { comp.CanReceiveCharacterItems = (bool)this.CanReceiveCharacterItems; } if (this.CanRemoveItems != null) { At.SetField(comp, "m_canRemoveItems", (bool)this.CanRemoveItems); } if (this.NonSavableContent != null) { comp.NonSavableContent = (bool)this.NonSavableContent; } if (this.ShowMoneyIfEmpty != null) { comp.ShowMoneyIfEmpty = (bool)this.ShowMoneyIfEmpty; } if (this.VisibleIfEmpty != null) { comp.VisibleIfEmpty = (bool)this.VisibleIfEmpty; } if (this.ItemFilter != null) { ItemFilter filterComp = comp.gameObject.GetOrAddComponent <ItemFilter>(); ItemFilter.ApplyToItemFilter(filterComp); } }
public void SetWeaponStats(CustomWeapon template) { if (ResourcesPrefabManager.Instance.GetItemPrefab(template.New_ItemID) is Item item) { WeaponStats stats = (item as Weapon).Stats; // equipment stats (which weapons can actually use and display) At.SetValue(template.DamageBonuses, typeof(EquipmentStats), stats as EquipmentStats, "m_damageAttack"); At.SetValue(template.ManaUseModifier, typeof(EquipmentStats), stats as EquipmentStats, "m_manaUseModifier"); // set base weapon stats stats.BaseDamage = template.BaseDamage; stats.Impact = template.Impact; stats.AttackSpeed = template.AttackSpeed; // set attack steps for (int i = 0; i < stats.Attacks.Count(); i++) { var step = stats.Attacks[i]; List <float> newDamage = new List <float>(); foreach (DamageType type in template.BaseDamage.List) { newDamage.Add(type.Damage); } float newImpact = template.Impact; StatHelpers.SetScaledDamages((item as Weapon).Type, i, ref newDamage, ref newImpact); step.Damage = newDamage; step.Knockback = newImpact; } // =========== hit effects ============= // remove existing hit effects if (item.transform.Find("HitEffects") is Transform t) { t.transform.parent = null; DestroyImmediate(t.gameObject); } // make new hit effects GameObject hiteffects = new GameObject("HitEffects"); hiteffects.transform.parent = item.transform; foreach (string effect in template.hitEffects) { if (string.IsNullOrEmpty(effect)) { continue; } if (ResourcesPrefabManager.Instance.GetStatusEffectPrefab(effect) is StatusEffect status) { hiteffects.AddComponent(new AddStatusEffectBuildUp { Status = status, BuildUpValue = 60.0f, }); } } } }
public static void SetItemTags(Item item, string[] tags, bool destroyExisting) { var tagsource = CustomTags.SetTagSource(item.gameObject, tags, destroyExisting); At.SetField(item, "m_tagSource", tagsource); }
/// <summary> /// Use this to create or modify an Imbue Effect status. /// </summary> /// <param name="template">The SL_ImbueEffect Template for this imbue.</param> public static ImbueEffectPreset CreateCustomImbue(SL_ImbueEffect template) { var original = (ImbueEffectPreset)GetOrigEffectPreset(template.TargetStatusID); if (!original) { SL.LogError("Could not find an ImbueEffectPreset with the Preset ID " + template.TargetStatusID); return(null); } ImbueEffectPreset newEffect; if (template.TargetStatusID == template.NewStatusID) { if (!OrigEffectPresets.ContainsKey(template.TargetStatusID)) { // instantiate and cache original var cached = GameObject.Instantiate(original.gameObject).GetComponent <EffectPreset>(); cached.gameObject.SetActive(false); GameObject.DontDestroyOnLoad(cached.gameObject); OrigEffectPresets.Add(template.TargetStatusID, cached); } newEffect = original; } else { // instantiate original and use that as newEffect newEffect = GameObject.Instantiate(original.gameObject).GetComponent <ImbueEffectPreset>(); newEffect.gameObject.SetActive(false); // Set Preset ID At.SetField <EffectPreset>(newEffect, "m_StatusEffectID", template.NewStatusID); // Fix localization GetImbueLocalization(original, out string name, out string desc); SetImbueLocalization(newEffect, name, desc); } newEffect.gameObject.name = template.NewStatusID + "_" + (template.Name ?? newEffect.Name); // fix RPM_Presets dictionary if (!References.RPM_EFFECT_PRESETS.ContainsKey(template.NewStatusID)) { References.RPM_EFFECT_PRESETS.Add(template.NewStatusID, newEffect.GetComponent <EffectPreset>()); } else { References.RPM_EFFECT_PRESETS[template.NewStatusID] = newEffect; } // Always do this GameObject.DontDestroyOnLoad(newEffect.gameObject); //// Apply template //if (SL.PacksLoaded) // template.ApplyTemplate(); //else // SL.INTERNAL_ApplyStatuses += template.ApplyTemplate; return(newEffect); }
public override void ApplyToItem(ItemStats stats) { base.ApplyToItem(stats); var eStats = stats as EquipmentStats; if (this.Damage_Resistance != null) { At.SetField(eStats, "m_damageResistance", this.Damage_Resistance); } if (this.Impact_Resistance != null) { At.SetField(eStats, "m_impactResistance", (float)this.Impact_Resistance); } if (this.Damage_Protection != null) { At.SetField(eStats, "m_damageProtection", new float[9] { (float)this.Damage_Protection, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f }); } if (this.Damage_Bonus != null) { At.SetField(eStats, "m_damageAttack", this.Damage_Bonus); } if (this.Impact_Bonus != null) { At.SetField(eStats, "m_baseImpactModifier", this.Impact_Bonus); } if (this.Stamina_Use_Penalty != null) { At.SetField(eStats, "m_staminaUsePenalty", (float)this.Stamina_Use_Penalty); } if (this.Mana_Use_Modifier != null) { At.SetField(eStats, "m_manaUseModifier", (float)this.Mana_Use_Modifier); } if (this.Mana_Regen != null) { At.SetField(eStats, "m_baseManaRegenBonus", (float)this.Mana_Regen); } if (this.Movement_Penalty != null) { At.SetField(eStats, "m_movementPenalty", (float)this.Movement_Penalty); } if (this.Pouch_Bonus != null) { At.SetField(eStats, "m_pouchCapacityBonus", (float)this.Pouch_Bonus); } if (this.Heat_Protection != null) { At.SetField(eStats, "m_heatProtection", (float)this.Heat_Protection); } if (this.Cold_Protection != null) { At.SetField(eStats, "m_coldProtection", (float)this.Cold_Protection); } if (this.Corruption_Protection != null) { At.SetField(eStats, "m_corruptionProtection", (float)this.Corruption_Protection); } if (this.Cooldown_Reduction != null) { At.SetField(eStats, "m_baseCooldownReductionBonus", (float)this.Cooldown_Reduction); } if (this.Health_Regen != null) { At.SetField(eStats, "m_baseHealthRegenBonus", (float)this.Health_Regen); } if (this.BarrierProtection != null) { At.SetField(eStats, "m_baseBarrierProtection", (float)this.BarrierProtection); } if (this.GlobalStatusEffectResistance != null) { At.SetField(eStats, "m_baseStatusEffectResistance", (float)this.GlobalStatusEffectResistance); } if (this.StaminaRegenModifier != null) { At.SetField(eStats, "m_baseStaminaRegen", this.StaminaRegenModifier); } }
internal void Internal_ApplyTemplate() { SL.Log($"Applying Enchantment Recipe, ID: {this.EnchantmentID}, Name: {this.Name}"); var recipe = ScriptableObject.CreateInstance <EnchantmentRecipe>(); recipe.RecipeID = this.EnchantmentID; recipe.ResultID = this.EnchantmentID; if (ResourcesPrefabManager.Instance.GetItemPrefab(this.IncenseItemID) is Item incense) { var list = new List <EnchantmentRecipe.PillarData>(); foreach (var pillar in this.PillarDatas) { list.Add(new EnchantmentRecipe.PillarData { Direction = (UICardinalPoint_v2.CardinalPoint)pillar.Direction, IsFar = pillar.IsFar, CompatibleIngredients = new EnchantmentRecipe.IngredientData[] { new EnchantmentRecipe.IngredientData { Type = EnchantmentRecipe.IngredientData.IngredientType.Specific, SpecificIngredient = incense } } }); } recipe.PillarDatas = list.ToArray(); } recipe.CompatibleEquipments = new EnchantmentRecipe.EquipmentData { EquipmentTag = new TagSourceSelector(CustomTags.GetTag(this.CompatibleEquipment.RequiredTag)), }; if (this.CompatibleEquipment.Equipments != null) { var equipList = new List <EnchantmentRecipe.IngredientData>(); foreach (var ingData in this.CompatibleEquipment.Equipments) { var data = new EnchantmentRecipe.IngredientData(); if (ingData.SelectorType == IngredientTypes.Tag) { data.Type = EnchantmentRecipe.IngredientData.IngredientType.Generic; data.IngredientTag = new TagSourceSelector(CustomTags.GetTag(ingData.SelectorValue)); } else if (ingData.SelectorType == IngredientTypes.SpecificItem) { data.Type = EnchantmentRecipe.IngredientData.IngredientType.Specific; data.SpecificIngredient = ResourcesPrefabManager.Instance.GetItemPrefab(ingData.SelectorValue); } equipList.Add(data); } recipe.CompatibleEquipments.CompatibleEquipments = equipList.ToArray(); } else { recipe.CompatibleEquipments.CompatibleEquipments = new EnchantmentRecipe.IngredientData[0]; } recipe.TimeOfDay = this.TimeOfDay ?? new Vector2[0]; recipe.Region = this.Areas ?? new AreaManager.AreaEnum[0]; recipe.Temperature = this.Temperature ?? new TemperatureSteps[0]; recipe.WindAltarActivated = this.WindAltarActivated; if (!string.IsNullOrEmpty(this.QuestEventUID)) { recipe.QuestEvent = new QuestEventReference() { m_eventUID = QuestEventUID, UID = QuestEventUID }; } if (this.WeatherConditions != null) { var list = new List <EnchantmentRecipe.WeaterCondition>(); foreach (var condition in this.WeatherConditions) { list.Add(new EnchantmentRecipe.WeaterCondition { Invert = condition.Invert, Weather = (EnchantmentRecipe.WeaterType)condition.WeatherType }); } recipe.Weather = list.ToArray(); } else { recipe.Weather = new EnchantmentRecipe.WeaterCondition[0]; } recipe.TableIsInBuilding = this.IsEnchantingGuildRecipe; // ========== Create actual Enchantment effects prefab ========== var enchantmentObject = new GameObject(this.EnchantmentID + "_" + this.Name); GameObject.DontDestroyOnLoad(enchantmentObject); var enchantment = enchantmentObject.AddComponent <Enchantment>(); At.SetField <EffectPreset>(enchantment, "m_StatusEffectID", this.EnchantmentID); SetLocalization(this, out enchantment.CustomDescLocKey); enchantment.EnchantTime = this.EnchantTime; if (this.Effects != null) { SL_EffectTransform.ApplyTransformList(enchantment.transform, this.Effects?.ToArray(), EditBehaviours.Override); } if (this.AddedDamages != null) { var list = new List <Enchantment.AdditionalDamage>(); foreach (var dmg in this.AddedDamages) { list.Add(new Enchantment.AdditionalDamage { BonusDamageType = dmg.AddedDamageType, ConversionRatio = dmg.ConversionRatio, SourceDamageType = dmg.SourceDamageType }); } enchantment.AdditionalDamages = list.ToArray(); } if (this.StatModifications != null) { var list = new Enchantment.StatModificationList(); foreach (var mod in this.StatModifications) { list.Add(new Enchantment.StatModification { Name = mod.Stat, Type = mod.Type, Value = mod.Value }); } enchantment.StatModifications = list; } if (this.FlatDamageAdded != null) { enchantment.DamageBonus = SL_Damage.GetDamageList(this.FlatDamageAdded); } if (this.DamageModifierBonus != null) { enchantment.DamageModifier = SL_Damage.GetDamageList(this.DamageModifierBonus); } if (this.DamageResistanceBonus != null) { enchantment.ElementalResistances = SL_Damage.GetDamageList(this.DamageResistanceBonus); } enchantment.HealthAbsorbRatio = this.HealthAbsorbRatio; enchantment.StaminaAbsorbRatio = this.StaminaAbsorbRatio; enchantment.ManaAbsorbRatio = this.ManaAbsorbRatio; enchantment.Indestructible = this.Indestructible; enchantment.TrackDamageRatio = this.TrackDamageRatio; enchantment.GlobalStatusResistance = this.GlobalStatusResistance; // =========== SET DICTIONARY REFS ============ // Recipe dict if (References.ENCHANTMENT_RECIPES.ContainsKey(this.EnchantmentID)) { References.ENCHANTMENT_RECIPES[this.EnchantmentID] = recipe; } else { References.ENCHANTMENT_RECIPES.Add(this.EnchantmentID, recipe); } // Enchantment dict if (References.ENCHANTMENT_PREFABS.ContainsKey(this.EnchantmentID)) { References.ENCHANTMENT_PREFABS[this.EnchantmentID] = enchantment; } else { References.ENCHANTMENT_PREFABS.Add(this.EnchantmentID, enchantment); } }
public IEnumerator ReplaceActiveAssets() { SideLoader.Log("Replacing Materials.."); float start = Time.time; // ============ materials ============ var list = Resources.FindObjectsOfTypeAll <Material>() .Where(x => x.mainTexture != null && SL.Instance.TextureData.ContainsKey(x.mainTexture.name)) .ToList(); SideLoader.Log(string.Format("Found {0} materials to replace.", list.Count)); int i = 0; foreach (Material m in list) { string name = m.mainTexture.name; i++; SideLoader.Log(string.Format(" - Replacing material {0} of {1}: {2}", i, list.Count, name)); // set maintexture (diffuse map) m.mainTexture = SL.Instance.TextureData[name]; // ======= set other shader material layers ======= if (name.EndsWith("_d")) { name = name.Substring(0, name.Length - 2); } // try remove the _d suffix, if its there // check each shader material suffix name foreach (KeyValuePair <string, string> entry in TextureSuffixes) { if (entry.Key == "_d") { continue; } // already set MainTex if (SL.Instance.TextureData.ContainsKey(name + entry.Key)) { SideLoader.Log(" - Setting " + entry.Value + " for " + m.name); m.SetTexture(entry.Value, SL.Instance.TextureData[name + entry.Key]); } } yield return(null); } // ========= sprites ========= SideLoader.Log("Replacing PrefabManager icons..."); if (At.GetValue(typeof(ResourcesPrefabManager), null, "ITEM_PREFABS") is Dictionary <string, Item> dict) { foreach (Item item in dict.Values .Where(x => x.ItemID > 2000000 && x.ItemIcon != null && x.ItemIcon.texture != null && SL.Instance.TextureData.ContainsKey(x.ItemIcon.texture.name))) { string name = item.ItemIcon.texture.name; SideLoader.Log(string.Format(" - Replacing item icon: {0}", name)); var tex = SL.Instance.TextureData[name]; var sprite = CreateSprite(tex); At.SetValue(sprite, typeof(Item), item, "m_itemIcon"); } } // ============================================== SideLoader.Log("Active assets replaced. Time: " + (Time.time - start), 0); SL.Instance.Loading = false; }
public override void ApplyToComponent <T>(T component) { var comp = component as Sleepable; if (!string.IsNullOrEmpty(this.RestStatusIdentifier)) { var status = ResourcesPrefabManager.Instance.GetStatusEffectPrefab(this.RestStatusIdentifier); if (status) { At.SetField(comp, "m_restEffect", status); } } if (this.AffectFoodDrink != null) { comp.AffectFoodDrink = (bool)this.AffectFoodDrink; } if (this.AmbushReduction != null) { comp.AmbushReduction = (int)this.AmbushReduction; } if (this.Capacity != null) { comp.Capacity = (int)this.Capacity; } if (this.CharAnimOffset != null) { comp.CharAnimOffset = (Vector3)this.CharAnimOffset; } if (this.ColdProtection != null) { comp.ColdProtection = (int)this.ColdProtection; } if (this.CorruptionDamage != null) { comp.CorruptionDamage = (int)this.CorruptionDamage; } if (this.HealthRecuperationModifier != null) { comp.HealthRecuperationModifier = (int)this.HealthRecuperationModifier; } if (this.HeatProtection != null) { comp.HeatProtection = (int)this.HeatProtection; } if (this.IsInnsBed != null) { comp.IsInnsBed = (bool)this.IsInnsBed; } if (this.ManaPreservationModifier != null) { comp.ManaPreservationModifier = (int)this.ManaPreservationModifier; } if (this.Rejuvenate != null) { comp.Rejuvenate = (bool)this.Rejuvenate; } if (this.StaminaRecuperationModifier != null) { comp.StaminaRecuperationModifier = (int)this.StaminaRecuperationModifier; } }
public static IEnumerator SetVisuals(Character character, string visualData) { var visuals = character.GetComponentInChildren <CharacterVisuals>(true); var newData = CharacterVisualData.CreateFromNetworkData(visualData); if (newData.SkinIndex == -999) { yield break; } float start = Time.time; while (!visuals && Time.time - start < 5f) { yield return(new WaitForSeconds(0.5f)); visuals = character.GetComponentInChildren <CharacterVisuals>(true); } yield return(new WaitForSeconds(0.5f)); if (visuals) { // disable default visuals visuals.transform.Find("HeadWhiteMaleA")?.gameObject.SetActive(false); ((ArmorVisuals)At.GetField(visuals, "m_defaultHeadVisuals"))?.gameObject.SetActive(false); visuals.transform.Find("MBody0")?.gameObject.SetActive(false); visuals.transform.Find("MFeet0")?.gameObject.SetActive(false); // failsafe for head index based on skin and gender ClampHeadVariation(ref newData.HeadVariationIndex, (int)newData.Gender, newData.SkinIndex); // set visual data var data = visuals.VisualData; data.Gender = newData.Gender; data.SkinIndex = newData.SkinIndex; data.HeadVariationIndex = newData.HeadVariationIndex; data.HairColorIndex = newData.HairColorIndex; data.HairStyleIndex = newData.HairStyleIndex; // set to the character too character.VisualData = data; var presets = CharacterManager.CharacterVisualsPresets; // get the skin material var mat = (data.Gender == 0) ? presets.MSkins[data.SkinIndex] : presets.FSkins[data.SkinIndex]; At.SetField(visuals, "m_skinMat", mat); // apply the visuals var hideface = false; var hidehair = false; if (visuals.ActiveVisualsHead) { hideface = visuals.ActiveVisualsHead.HideFace; hidehair = visuals.ActiveVisualsHead.HideHair; } //SL.Log("hideface: " + hideface); if (!hideface) { visuals.LoadCharacterCreationHead(data.SkinIndex, (int)data.Gender, data.HeadVariationIndex); } if (!hidehair) { ApplyHairVisuals(visuals, data.HairStyleIndex, data.HairColorIndex); } if (!character.Inventory.Equipment.GetEquippedItem(EquipmentSlot.EquipmentSlotIDs.Chest)) { visuals.LoadCharacterCreationBody((int)data.Gender, data.SkinIndex); } if (!character.Inventory.Equipment.GetEquippedItem(EquipmentSlot.EquipmentSlotIDs.Foot)) { visuals.LoadCharacterCreationBoots((int)data.Gender, data.SkinIndex); } } else { SL.Log("Couldn't get visuals!"); } }
public virtual void SerializeStatus(StatusEffect status) { var preset = status.GetComponent <EffectPreset>(); this.NewStatusID = preset?.PresetID ?? -1; this.TargetStatusIdentifier = status.IdentifierName; this.StatusIdentifier = status.IdentifierName; this.IgnoreBuildupIfApplied = status.IgnoreBuildUpIfApplied; this.BuildupRecoverySpeed = status.BuildUpRecoverSpeed; this.DisplayedInHUD = status.DisplayInHud; this.IsHidden = status.IsHidden; this.Lifespan = status.StatusData.LifeSpan; this.RefreshRate = status.RefreshRate; this.AmplifiedStatusIdentifier = status.AmplifiedStatus?.IdentifierName ?? ""; this.PlayFXOnActivation = status.PlayFXOnActivation; this.ComplicationStatusIdentifier = status.ComplicationStatus?.IdentifierName; this.FXOffset = status.FxOffset; this.IgnoreBarrier = status.IgnoreBarrier; this.IsMalusEffect = status.IsMalusEffect; this.NormalizeDamageDisplay = status.NormalizeDamageDisplay; this.PlaySpecialFXOnStop = status.PlaySpecialFXOnStop; this.RemoveRequiredStatus = status.RemoveRequiredStatus; this.RequiredStatusIdentifier = status.RequiredStatus?.IdentifierName; this.SpecialSFX = status.SpecialSFX; this.VFXInstantiationType = status.FxInstantiation; this.ActionOnHit = status.ActionOnHit; this.Priority = (int)At.GetField(status, "m_priority"); this.DelayedDestroyTime = status.DelayedDestroyTime; this.Purgeable = status.Purgeable; CustomStatusEffects.GetStatusLocalization(status, out Name, out Description); var tags = At.GetField(status, "m_tagSource") as TagListSelectorComponent; if (tags) { Tags = tags.Tags.Select(it => it.TagName).ToArray(); } var vfx = status.FXPrefab?.GetComponent <VFXSystem>(); if (vfx) { VFXPrefab = SL_PlayVFX.GetVFXSystemEnum(vfx); } // PARSE EFFECT FAMILY FamilyMode = status.FamilyMode; if (status.EffectFamily != null) { if (FamilyMode == StatusEffect.FamilyModes.Bind) { BindFamily = SL_StatusEffectFamily.ParseEffectFamily(status.EffectFamily); } else { ReferenceFamilyUID = status.EffectFamily.UID; } } // For existing StatusEffects, the StatusData contains the real values, so we need to SetValue to each Effect. var statusData = status.StatusData.EffectsData; var components = status.GetComponentsInChildren <Effect>(); for (int i = 0; i < components.Length; i++) { var comp = components[i]; if (comp && comp.Signature.Length > 0) { comp.SetValue(statusData[i].Data); } } var effects = new List <SL_EffectTransform>(); Transform signature; if (status.transform.childCount > 0) { signature = status.transform.GetChild(0); if (signature.transform.childCount > 0) { foreach (Transform child in signature.transform) { var effectsChild = SL_EffectTransform.ParseTransform(child); if (effectsChild.HasContent) { effects.Add(effectsChild); } } } } Effects = effects.ToArray(); }
private void OnLateApply(object[] obj) { var comp = obj[0] as LevelStatusEffect; int origMax = (int)At.GetField(comp, "m_maxLevel"); int newMax = MaxLevel ?? origMax; At.SetField(comp, "m_maxLevel", newMax); Sprite[] origIcons = new Sprite[origMax - 1]; // prepare the level data array and get current icons if (comp.StatusLevelData == null) { comp.StatusLevelData = new LevelStatusEffect.LevelData[newMax - 1]; } else if (comp.StatusLevelData.Length > 0) { comp.StatusLevelData = comp.StatusLevelData.OrderBy(it => it.LevelIndex).ToArray(); for (int i = 0; i < origMax - 1; i++) { origIcons[i] = comp.StatusLevelData[i].Icon; } } if (origMax != newMax) { Array.Resize(ref comp.StatusLevelData, newMax - 1); } // set the level datas for (int i = 0; i < newMax - 1; i++) { if (comp.StatusLevelData[i] == null) { comp.StatusLevelData[i] = new LevelStatusEffect.LevelData(); } var level = comp.StatusLevelData[i]; level.LevelIndex = i; level.StatusData = new StatusData(comp.StatusData) { EffectsData = GenerateEffectsData(comp.StatusEffectSignature.Effects, i + 2) }; } // check for custom level icons if (!string.IsNullOrEmpty(SerializedSLPackName) && !string.IsNullOrEmpty(SerializedSubfolderName) && SL.GetSLPack(SerializedSLPackName) is SLPack pack) { var dir = $@"{pack.GetPathForCategory<StatusCategory>()}\{SerializedSubfolderName}"; for (int i = 0; i < newMax - 1; i++) { if (pack.FileExists(dir, $@"icon{i + 2}.png")) { var tex = pack.LoadTexture2D(dir, $@"icon{i + 2}.png"); var sprite = CustomTextures.CreateSprite(tex, CustomTextures.SpriteBorderTypes.NONE); //list.Add(sprite); comp.StatusLevelData[i].Icon = sprite; } } } // ensure all levels at least have some icon for (int i = 0; i < newMax - 1; i++) { if (!comp.StatusLevelData[i].Icon) { comp.StatusLevelData[i].Icon = comp.StatusIcon; } } }
/// <summary> /// Get the Localization for the Status Effect (name and description). /// </summary> /// <param name="effect">The Status Effect to get localization for.</param> /// <param name="name">The output name.</param> /// <param name="desc">The output description.</param> public static void GetStatusLocalization(StatusEffect effect, out string name, out string desc) { name = LocalizationManager.Instance.GetLoc((string)At.GetField(effect, "m_nameLocKey")); desc = LocalizationManager.Instance.GetLoc((string)At.GetField(effect, "m_descriptionLocKey")); }
public override void SerializeStatus(StatusEffect status) { base.SerializeStatus(status); this.MaxLevel = (int)At.GetField(status as LevelStatusEffect, "m_maxLevel"); }
/// <summary> /// Use this to create or modify a Status Effect. /// </summary> /// <param name="template">The SL_StatusEffect template.</param> /// <returns>The new or existing StatusEffect.</returns> public static StatusEffect CreateCustomStatus(SL_StatusEffect template) { var original = ResourcesPrefabManager.Instance.GetStatusEffectPrefab(template.TargetStatusIdentifier); if (!original) { SL.Log($"CreateCustomStatus - Could not find any status with the Identifier '{template.TargetStatusIdentifier}' (or none was set)."); return(null); } var preset = original.GetComponent <EffectPreset>(); if (!preset && template.NewStatusID < -1 || template.NewStatusID > 0) { preset = original.gameObject.AddComponent <EffectPreset>(); At.SetField(preset, "m_StatusEffectID", template.NewStatusID); } StatusEffect status; if (template.TargetStatusIdentifier == template.StatusIdentifier) { // editing orig status if (!OrigStatusEffects.ContainsKey(template.TargetStatusIdentifier)) { // instantiate and cache original var cached = GameObject.Instantiate(original.gameObject).GetComponent <StatusEffect>(); cached.gameObject.SetActive(false); GameObject.DontDestroyOnLoad(cached.gameObject); OrigStatusEffects.Add(template.TargetStatusIdentifier, cached); } status = original; } else { // instantiate original and use that as newEffect status = GameObject.Instantiate(original.gameObject).GetComponent <StatusEffect>(); status.gameObject.SetActive(false); // Set Status identifier At.SetField(status, "m_identifierName", template.StatusIdentifier); if (preset && (template.NewStatusID < -1 || template.NewStatusID > 0)) { At.SetField(preset, "m_StatusEffectID", template.NewStatusID); } // Fix localization GetStatusLocalization(original, out string name, out string desc); SetStatusLocalization(status, name, desc); // Fix status data and stack At.SetField(status, "m_statusStack", null); At.SetField(status, "m_amplifiedStatus", null); } var gameType = Serializer.GetGameType(template.GetType()); if (gameType != status.GetType()) { status = (StatusEffect)UnityHelpers.FixComponentType(gameType, status); } int presetID = status.GetComponent <EffectPreset>()?.PresetID ?? -1; var id = ""; if (presetID < -1 || presetID > 0) { id += presetID + "_"; } status.gameObject.name = id + status.IdentifierName; // fix RPM_STATUS_EFFECTS dictionary if (!References.RPM_STATUS_EFFECTS.ContainsKey(status.IdentifierName)) { References.RPM_STATUS_EFFECTS.Add(status.IdentifierName, status); } else { References.RPM_STATUS_EFFECTS[status.IdentifierName] = status; } // fix RPM_Presets dictionary if (template.NewStatusID < -1 || template.NewStatusID > 0) { if (!References.RPM_EFFECT_PRESETS.ContainsKey(template.NewStatusID)) { References.RPM_EFFECT_PRESETS.Add(template.NewStatusID, status.GetComponent <EffectPreset>()); } else { References.RPM_EFFECT_PRESETS[template.NewStatusID] = status.GetComponent <EffectPreset>(); } } // Always do this GameObject.DontDestroyOnLoad(status.gameObject); return(status); }
internal void Internal_ApplyRecipe() { try { SL.Log("Defining recipe UID: " + this.UID); if (string.IsNullOrEmpty(this.UID)) { SL.LogWarning("No UID was set! Please set a UID, for example 'myname.myrecipe'. Aborting."); return; } if (m_applied) { SL.Log("Trying to apply an SL_Recipe that is already applied! This is not allowed."); return; } var results = new List <ItemReferenceQuantity>(); foreach (var result in this.Results) { var resultItem = ResourcesPrefabManager.Instance.GetItemPrefab(result.ItemID); if (!resultItem) { SL.Log("Error: Could not get recipe result id : " + result.ItemID); return; } results.Add(new ItemReferenceQuantity(resultItem, result.Quantity)); } var ingredients = new List <RecipeIngredient>(); foreach (var ingredient in this.Ingredients) { // legacy support if (!string.IsNullOrEmpty(ingredient.Ingredient_Tag)) { ingredient.SelectorValue = ingredient.Ingredient_Tag; } else if (ingredient.Ingredient_ItemID != 0) { ingredient.SelectorValue = ingredient.Ingredient_ItemID.ToString(); } if (ingredient.Type == RecipeIngredient.ActionTypes.AddGenericIngredient) { var tag = CustomTags.GetTag(ingredient.SelectorValue); if (tag == Tag.None) { SL.LogWarning("Could not get a tag by the name of '" + ingredient.SelectorValue); return; } ingredients.Add(new RecipeIngredient { ActionType = ingredient.Type, AddedIngredientType = new TagSourceSelector(tag) }); } else { int.TryParse(ingredient.SelectorValue, out int id); if (id == 0) { SL.LogWarning("Picking an Ingredient based on Item ID, but no ID was set. Check your XML and make sure there are no logical errors. Aborting"); return; } var ingredientItem = ResourcesPrefabManager.Instance.GetItemPrefab(id); if (!ingredientItem) { SL.Log("Error: Could not get ingredient id : " + id); return; } // The item needs the station type tag in order to be used in a manual recipe on that station var tag = TagSourceManager.GetCraftingIngredient(StationType); if (!ingredientItem.HasTag(tag)) { //SL.Log($"Adding tag {tag.TagName} to " + ingredientItem.name); if (!ingredientItem.GetComponent <TagSource>()) { ingredientItem.gameObject.AddComponent <TagSource>(); } ((List <TagSourceSelector>)At.GetField <TagListSelectorComponent>(ingredientItem.GetComponent <TagSource>(), "m_tagSelectors")) .Add(new TagSourceSelector(tag)); } ingredients.Add(new RecipeIngredient() { ActionType = RecipeIngredient.ActionTypes.AddSpecificIngredient, AddedIngredient = ingredientItem, }); } } var recipe = ScriptableObject.CreateInstance <Recipe>(); recipe.SetCraftingType(this.StationType); At.SetField(recipe, "m_results", results.ToArray()); recipe.SetRecipeIngredients(ingredients.ToArray()); // set or generate UID if (string.IsNullOrEmpty(this.UID)) { var uid = $"{recipe.Results[0].ItemID}{recipe.Results[0].Quantity}"; foreach (var ing in recipe.Ingredients) { if (ing.AddedIngredient != null) { uid += $"{ing.AddedIngredient.ItemID}"; } else if (ing.AddedIngredientType != null) { uid += $"{ing.AddedIngredientType.Tag.TagName}"; } } this.UID = uid; At.SetField(recipe, "m_uid", new UID(uid)); } else { At.SetField(recipe, "m_uid", new UID(this.UID)); } recipe.Init(); // fix Recipe Manager dictionaries to contain our recipe var dict = References.ALL_RECIPES; var dict2 = References.RECIPES_PER_UTENSIL; if (dict.ContainsKey(recipe.UID)) { dict[recipe.UID] = recipe; } else { dict.Add(recipe.UID, recipe); } if (!dict2.ContainsKey(recipe.CraftingStationType)) { dict2.Add(recipe.CraftingStationType, new List <UID>()); } if (!dict2[recipe.CraftingStationType].Contains(recipe.UID)) { dict2[recipe.CraftingStationType].Add(recipe.UID); } m_applied = true; } catch (Exception e) { SL.LogWarning("Error applying recipe!"); SL.LogInnerException(e); } }
public void SetItemIcon(Item item, Texture2D icon) { var sprite = TexReplacer.CreateSprite(icon); At.SetValue(sprite, typeof(Item), item, "m_itemIcon"); }
/// <summary> /// Apply the SL_ItemVisual prefab to the Item. /// </summary> /// <param name="item">The Item to set to.</param> public void ApplyToItem(Item item) { if (CustomItemVisuals.GetOrigItemVisuals(item, Type) is Transform origPrefab) { bool setPrefab = false; // Check for AssetBundle Prefabs first if (!string.IsNullOrEmpty(Prefab_SLPack) && SL.GetSLPack(Prefab_SLPack) is SLPack pack) { if (pack.AssetBundles.ContainsKey(Prefab_AssetBundle)) { var newVisuals = pack.AssetBundles[Prefab_AssetBundle].LoadAsset <GameObject>(Prefab_Name); origPrefab = SetCustomVisualPrefab(item, this.Type, newVisuals.transform, origPrefab).transform; SL.Log("Loaded custom visual prefab: " + newVisuals.name); setPrefab = true; } } // Not using AssetBundle, check for ResourcesPrefabPath. else if (!string.IsNullOrEmpty(ResourcesPrefabPath)) { // Only set this if the user has defined a different value than what exists on the item. bool set = false; switch (Type) { case VisualPrefabType.VisualPrefab: set = item.VisualPrefabPath == ResourcesPrefabPath; break; case VisualPrefabType.SpecialVisualPrefabDefault: set = item.SpecialVisualPrefabDefaultPath == ResourcesPrefabPath; break; case VisualPrefabType.SpecialVisualPrefabFemale: set = item.SpecialVisualPrefabFemalePath == ResourcesPrefabPath; break; } if (!set) { // Get the original visual prefab to clone from var orig = ResourcesPrefabManager.Instance.GetItemVisualPrefab(ResourcesPrefabPath); if (!orig) { SL.Log("SL_ItemVisual: Could not find an Item Visual at the Resources path: " + ResourcesPrefabPath); } else { CustomItemVisuals.CloneAndSetVisuals(item, orig.gameObject, Type); switch (Type) { case VisualPrefabType.VisualPrefab: At.SetField(item, "m_visualPrefabPath", ResourcesPrefabPath); break; case VisualPrefabType.SpecialVisualPrefabDefault: At.SetField(item, "m_specialVisualPrefabDefaultPath", ResourcesPrefabPath); break; case VisualPrefabType.SpecialVisualPrefabFemale: At.SetField(item, "m_specialVisualPrefabFemalePath", ResourcesPrefabPath); break; } setPrefab = true; } } } // If we didn't change the Visual Prefab in any way, clone the original to avoid conflicts. if (!setPrefab) { origPrefab = CustomItemVisuals.CloneVisualPrefab(item, Type).transform; } // Get the actual visuals (for weapons and a lot of items, this is not the base prefab). Transform actualVisuals = origPrefab.transform; if (this.Type == VisualPrefabType.VisualPrefab) { if (origPrefab.childCount > 0) { foreach (Transform child in origPrefab) { if (child.gameObject.activeSelf && child.GetComponent <BoxCollider>() && child.GetComponent <MeshRenderer>()) { actualVisuals = child; break; } } } } if (actualVisuals) { var visualComp = origPrefab.GetComponent <ItemVisual>(); ApplyItemVisualSettings(visualComp, actualVisuals); } } }
protected override void ApplyToCharacter(Character character) { var aiRootPrefab = new GameObject("BasicMelee_AIRoot").AddComponent <AIRoot>(); aiRootPrefab.gameObject.SetActive(false); aiRootPrefab.transform.parent = character.transform; // -- create base state objects -- // state 1: Wander var wanderState = new GameObject("1_Wander").AddComponent <AISWander>(); wanderState.transform.parent = aiRootPrefab.transform; // state 2: Suspicious var susState = new GameObject("2_Suspicious").AddComponent <AISSuspicious>(); susState.transform.parent = aiRootPrefab.transform; //state 3: alert var alertState = new GameObject("3_Alert").AddComponent <AISSuspicious>(); alertState.transform.parent = aiRootPrefab.transform; //state 4: Combat var combatState = new GameObject("4_Combat").AddComponent <AISCombatMelee>(); combatState.transform.parent = aiRootPrefab.transform; // ---- setup actual state parameters and links ---- // setup 1 - Wander wanderState.ContagionRange = this.AIContagionRange; wanderState.ForceNotCombat = this.ForceNonCombat; wanderState.SpeedModif = this.Wander_Speed; wanderState.WanderFar = this.CanWanderFar; wanderState.AutoFollowPlayer = this.Wander_FollowPlayer; if (this.Wander_PatrolWaypoints != null && this.Wander_Type == AISWander.WanderType.Patrol) { var wanderTrans = new GameObject($"Waypoints_{character.UID}"); wanderState.WaypointsParent = wanderTrans.transform; for (int i = 0; i < this.Wander_PatrolWaypoints.Length; i++) { var waypointObj = new GameObject("Waypoint " + i + 1); var waypoint = waypointObj.AddComponent <Waypoint>(); waypointObj.transform.parent = wanderTrans.transform; waypointObj.transform.position = Wander_PatrolWaypoints[i].WorldPosition; waypoint.RandomRadius = Wander_PatrolWaypoints[i].RandomRadius; waypoint.WaitTime = Wander_PatrolWaypoints[i].WaitTime; } } var wanderDetection = new GameObject("Detection").AddComponent <AICEnemyDetection>(); wanderDetection.transform.parent = wanderState.transform; var wanderDetectEffects = new GameObject("DetectEffects").AddComponent <AIESwitchState>(); wanderDetectEffects.ToState = susState; wanderDetectEffects.transform.parent = wanderDetection.transform; wanderDetection.DetectEffectsTrans = wanderDetectEffects.transform; //setup 2 - Suspicious susState.SpeedModif = this.Suspicious_Speed; susState.SuspiciousDuration = this.Suspicious_Duration; susState.Range = this.Suspicious_Range; susState.WanderFar = this.CanWanderFar; susState.TurnModif = this.Suspicious_TurnModif; var susEnd = new GameObject("EndSuspiciousEffects").AddComponent <AIESwitchState>(); susEnd.ToState = wanderState; var sheathe = susEnd.gameObject.AddComponent <AIESheathe>(); sheathe.Sheathed = true; susEnd.transform.parent = susState.transform; susState.EndSuspiciousEffectsTrans = susEnd.transform; var susDetection = new GameObject("Detection").AddComponent <AICEnemyDetection>(); susDetection.transform.parent = susState.transform; var susDetectEffects = new GameObject("DetectEffects").AddComponent <AIESwitchState>(); susDetectEffects.ToState = combatState; susDetectEffects.transform.parent = susDetection.transform; susDetection.DetectEffectsTrans = susDetectEffects.transform; var susSuspiciousEffects = new GameObject("SuspiciousEffects").AddComponent <AIESwitchState>(); susSuspiciousEffects.ToState = alertState; susSuspiciousEffects.transform.parent = susDetection.transform; susDetection.SuspiciousEffectsTrans = susSuspiciousEffects.transform; // setup 3 - alert alertState.SpeedModif = this.Suspicious_Speed; alertState.SuspiciousDuration = this.Suspicious_Duration; alertState.Range = this.Suspicious_Range; alertState.WanderFar = this.CanWanderFar; alertState.TurnModif = this.Suspicious_TurnModif; var alertEnd = new GameObject("EndSuspiciousEffects").AddComponent <AIESwitchState>(); alertEnd.ToState = susState; var alertsheathe = alertEnd.gameObject.AddComponent <AIESheathe>(); alertsheathe.Sheathed = true; alertEnd.transform.parent = alertState.transform; alertState.EndSuspiciousEffectsTrans = alertEnd.transform; var alertDetection = new GameObject("Detection").AddComponent <AICEnemyDetection>(); alertDetection.transform.parent = alertState.transform; var alertDetectEffects = new GameObject("DetectEffects").AddComponent <AIESwitchState>(); alertDetectEffects.ToState = combatState; alertDetectEffects.transform.parent = alertDetection.transform; alertDetection.DetectEffectsTrans = alertDetectEffects.transform; // setup 4 - Combat combatState.ChargeTime = this.Combat_ChargeTime; combatState.TargetVulnerableChargeTimeMult = this.Combat_TargetVulnerableChargeModifier; combatState.ChargeAttackRangeMult = this.Combat_ChargeAttackRangeMulti; combatState.ChargeAttackTimeToAttack = this.Combat_ChargeTimeToAttack; combatState.ChargeStartRangeMult = this.Combat_ChargeStartRangeMult; combatState.AttackPatterns = this.Combat_AttackPatterns; combatState.SpeedModifs = this.Combat_SpeedModifiers; combatState.ChanceToAttack = this.Combat_ChanceToAttack; combatState.KnowsUnblockable = this.Combat_KnowsUnblockable; combatState.DodgeCooldown = this.Combat_DodgeCooldown; combatState.CanBlock = this.CanBlock; combatState.CanDodge = this.CanDodge; var combatDetect = new GameObject("Detection").AddComponent <AICEnemyDetection>(); combatDetect.transform.parent = combatState.transform; var combatEnd = new GameObject("EndCombatEffects").AddComponent <AIESwitchState>(); combatEnd.ToState = wanderState; combatEnd.transform.parent = combatState.transform; // add required components for AIs (no setup required) character.gameObject.AddComponent <NavMeshAgent>(); character.gameObject.AddComponent <AISquadMember>(); character.gameObject.AddComponent <EditorCharacterAILoadAI>(); if (character.GetComponent <NavMeshObstacle>() is NavMeshObstacle navObstacle) { GameObject.Destroy(navObstacle); } // add our basic AIStatesPrefab to a CharacterAI component. This is the prefab set up by SetupBasicAIPrefab(), below. CharacterAI charAI = character.gameObject.AddComponent <CharacterAI>(); At.SetField(charAI, "m_character", character); charAI.AIStatesPrefab = aiRootPrefab; // initialize the AI States (not entirely necessary, but helpful if we want to do something with the AI immediately after) At.Invoke(charAI, "GetAIStates", null); }
// ~~~~~~~~~~~~~~~~ Tempate applying ~~~~~~~~~~~~~~~~ public virtual void ApplyToCharacter(Character character, bool loadingFromSave) { SL.Log("Applying SL_Character template, template UID: " + this.UID + ", char UID: " + character.UID); character.NonSavable = true; // set name if (Name != null) { At.SetField(character, "m_nameLocKey", ""); At.SetField(character, "m_name", Name); } // set scale character.transform.localScale = this.Scale; // set starting pose if (!PhotonNetwork.isNonMasterClientInRoom) { SLPlugin.Instance.StartCoroutine(DelayedSetPose(character)); } // if host if (!PhotonNetwork.isNonMasterClientInRoom) { character.OnDeath += () => { OnDeath(character); }; // set faction if (Faction != null) { character.ChangeFaction((Character.Factions)Faction); } if (!loadingFromSave) { SetItems(character); } } // AI if (this.AI != null) { //SL.Log("SL_Character AI is " + this.AI.GetType().FullName + ", applying..."); this.AI.Apply(character); } // stats SetStats(character); if (this.AI is SL_CharacterAIMelee aiMelee && aiMelee.ForceNonCombat) { this.TargetableFactions = new Character.Factions[0]; } if (this.TargetableFactions != null) { var targeting = character.GetComponent <TargetingSystem>(); if (targeting) { targeting.TargetableFactions = this.TargetableFactions; } else { SL.LogWarning("SL_Character: Could not get TargetingSystem component!"); } } // loot/death if (LootableOnDeath) { var lootable = character.gameObject.AddComponent <LootableOnDeath>(); lootable.DropWeapons = this.DropWeapons; lootable.EnabledPouch = this.DropPouchContents; At.SetField(lootable, "m_character", character); // todo droptables lootable.SkinDrops = new DropInstance[0]; lootable.LootDrops = new DropInstance[0]; } character.gameObject.SetActive(true); }