public override void ResolveReferences(LootAffixDef parentDef) { // Among other overrides from HarmonyPatches affectedField = "requireLineOfSight"; newValue = false; base.ResolveReferences(parentDef); }
public virtual IEnumerable <string> ConfigErrors(LootAffixDef parentDef, LootAffixModifier modifier) { // min/max sanity checks if (setValue == null && addValue == 0 && multiplier == 1 && preMinValue == -9999999f && minValue == -9999999f && maxValue == 9999999f) { yield return("This modifier doesn't actually change anything"); } if (setValue != null && (addValue != 0 && multiplier != 1 && preMinValue != -9999999f && minValue != -9999999f && maxValue != 9999999f)) { yield return("The setValue option is mutually exclusive to all other value modifier options"); } if (multiplier == 0) { yield return("A multiplier=0 is better displayed as setValue=0"); } if (preMinValue != -9999999f) { if (preMinValue > maxValue) { yield return(string.Format("The preMinValue is higher than the maxValue: {0} > {1}", preMinValue, maxValue)); } } if (minValue != -9999999f) { if (minValue > maxValue) { yield return(string.Format("The minValue is higher than the maxValue: {0} > {1}", minValue, maxValue)); } } }
private static List <DebugMenuOption> Options_AddAffix() { List <DebugMenuOption> debugMenuOptionList = new List <DebugMenuOption>(); foreach (LootAffixDef affixDef in DefDatabase <LootAffixDef> .AllDefs.OrderBy(lad => lad.affixCost)) { LootAffixDef localDef = affixDef; debugMenuOptionList.Add(new DebugMenuOption(localDef.defName, DebugMenuOptionMode.Tool, () => { CompLootAffixableThing comp = Find.CurrentMap.thingGrid. ThingsAt(UI.MouseCell()). Where(t => t is ThingWithComps).Cast <ThingWithComps>(). Select(twc => twc.TryGetComp <CompLootAffixableThing>()). Where(c => c is CompLootAffixableThing). FirstOrDefault() ; var lads = comp.AllAffixDefs; if (lads.Contains(localDef) || lads.Count >= 4) { return; } lads.Add(localDef); comp.PostAffixCleanup(); })); } return(debugMenuOptionList); }
public override void ResolveReferences(LootAffixDef parentDef) { // Set the resolvedDef object, with paranoia checks if (affectedField == null || newDef == null) { return; } FieldInfo field = AccessTools.Field(ObjType, affectedField); if (field == null) { return; } Type type = field.FieldType; if (!typeof(Def).IsAssignableFrom(type)) { return; } Type defDBType = typeof(DefDatabase <>).MakeGenericType(type); MethodInfo getNamedMethod = defDBType.GetMethod("GetNamed"); resolvedDef = (Def)getNamedMethod.Invoke(null, new object[] { newDef, true }); // Call this last, to get the resolvedDef before LootAffixDef needs it for ModifierChangeString base.ResolveReferences(parentDef); }
public override void ResolveReferences(LootAffixDef parentDef) { // Force these on affectedStat.showOnPawns = true; affectedStat.showOnHumanlikes = true; var statPart = new StatPart_LootAffix_Equipped { parentStat = affectedStat, parentStatChanger = this, parentLootAffix = parentDef, }; if (affectedStat.parts == null) { affectedStat.parts = new List <StatPart> { statPart } } ; else { affectedStat.parts.Add(statPart) ; } affectedStat.ResolveReferences(); affectedStat.PostLoad(); // sometimes a reload, since we added a new part }
public override IEnumerable <string> ConfigErrors(LootAffixDef parentDef) { foreach (string configError in base.ConfigErrors(parentDef)) { yield return(configError); } // Check for reflection errors FieldInfo field = AccessTools.Field(typeof(VerbProperties), affectedField); Type type = field.FieldType; if (!ConvertHelper.CanConvert(1f, type)) { yield return("Unsupported type: " + type); } // ValueModifierSet sanity checks if (valueModifier == null) { yield return("The valueModifer is not set!"); yield break; } foreach (string configError in valueModifier.ConfigErrors(parentDef, this)) { yield return(configError); } }
public override void OpenLetter() { Pawn pawn = lookTargets.TryGetPrimaryTarget().Thing as Pawn; ThingWithComps deadlyItem = (ThingWithComps)lookTargets.targets.First(gti => gti.HasThing && gti.Thing.TryGetComp <CompLootAffixableThing>() != null).Thing; var comp = deadlyItem.TryGetComp <CompLootAffixableThing>(); LootAffixDef affix = comp.AllAffixDefs.First(lad => lad.IsNegativeDeadly(deadlyItem)); string affixLabel = comp.AllAffixesByAffixDefs[affix]; TaggedString text = "RimLoot_NegativeDeadlyAffixLetter_Desc".Translate( pawn.Named("PAWN"), deadlyItem.Named("ITEM"), affix.FullStatsReport(deadlyItem, affixLabel).Named("EFFECT") ); DiaNode nodeRoot = new DiaNode(text); nodeRoot.options.AddRange(Choices); Find.WindowStack.Add(new Dialog_NodeTreeWithFactionInfo( nodeRoot: nodeRoot, faction: relatedFaction, radioMode: radioMode, title: title )); }
// FIXME: Still seems to have problems on drop public override void PostApplyAffix(ThingWithComps parentThing, LootAffixDef parentDef) { // Make sure any changes in max values fixes the current HPs if (affectedStat == StatDefOf.MaxHitPoints) { parentThing.HitPoints = parentThing.MaxHitPoints; } }
public override void ResolveReferences(LootAffixDef parentDef) { basicStatDesc = BasicStatDescDef.Named(ObjType, affectedField); fieldInfo = AccessTools.Field(ObjType, affectedField); fieldType = fieldInfo.FieldType; // Call this last, to get the resolvedDef before LootAffixDef needs it for ModifierChangeString base.ResolveReferences(); }
public override void PostShotFired(ThingWithComps parentThing, LootAffixDef parentDef) { // 95+% chance: This should have already been set by ModifyVerbProperties if (GetRealChance(parentThing) >= 0.95f) { return; } ResetVerbProperty(parentThing); }
public override IEnumerable <string> ConfigErrors(LootAffixDef parentDef) { foreach (string configError in base.ConfigErrors(parentDef)) { yield return(configError); } if (mtbDays == 0f) { yield return("mtbDays is not set!"); } }
public override IEnumerable <string> ConfigErrors(LootAffixDef parentDef) { foreach (string configError in base.ConfigErrors(parentDef)) { yield return(configError); } if (extraDamage == null) { yield return("extraDamage is not set!"); yield break; } }
public override void PreShotFired(ThingWithComps parentThing, LootAffixDef parentDef) { // 95+% chance: This should have already been set by ModifyVerbProperties if (GetRealChance(parentThing) >= 0.95f) { return; } // Switch projectile based on chance hit if (ShouldActivate(parentThing)) { ModifyVerbProperty(parentThing); } }
static public void AddNewAffixes(this CompLootAffixableThing comp, float affixPoints = 0, int ttlAffixes = 0) // options for debug only { List <LootAffixDef> affixes = comp.affixes; ThingWithComps thing = comp.parent; affixes.Clear(); if (affixPoints == 0) { affixPoints = CalculateTotalLootAffixPoints(thing); } if (ttlAffixes == 0) { for (int i = 1; i <= 4; i++) { // FIXME: Add config sliders for percentages here // 25% chance for each affix (compounded) if (0.25f < Random.Range(0.0f, 1.0f)) { break; } ttlAffixes = i; } } if (ttlAffixes == 0) { return; } // Baseline of affixes that can be used (since affixPoints could change upward or downward) List <LootAffixDef> baseAffixDefs = DefDatabase <LootAffixDef> .AllDefsListForReading. FindAll(lad => lad.CanBeAppliedToThing(thing)) ; // Affix picking loop for (int curAffixes = affixes.Count + 1; curAffixes <= 4; curAffixes++) { LootAffixDef newAffix = PickAffix(thing, baseAffixDefs, curAffixes, ttlAffixes, affixPoints); if (newAffix == null) { return; } affixes.Add(newAffix); affixPoints -= newAffix.GetRealAffixCost(thing); baseAffixDefs = baseAffixDefs.FindAll(lad => lad.groupName != newAffix.groupName); } }
private static List <DebugMenuOption> Options_RemoveAffix(CompLootAffixableThing comp) { List <DebugMenuOption> debugMenuOptionList = new List <DebugMenuOption>(); foreach (LootAffixDef affixDef in comp.AllAffixDefs) { LootAffixDef localDef = affixDef; debugMenuOptionList.Add(new DebugMenuOption(comp.AllAffixesByAffixDefs[localDef], DebugMenuOptionMode.Action, () => { int i = comp.AllAffixDefs.IndexOf(localDef); comp.AllAffixDefs.RemoveAt(i); comp.PostAffixCleanup(); })); } return(debugMenuOptionList); }
// FIXME: Icons on the affix hyperlinks public override IEnumerable <StatDrawEntry> SpecialDisplayStats() { StatCategoryDef category = parent.def.IsApparel ? StatCategoryDefOf.Apparel : parent.def.IsWeapon ? StatCategoryDefOf.Weapon : StatCategoryDefOf.BasicsImportant ; string reportText = "RimLoot_LootAffixDescription".Translate() + "\n\n"; var affixDict = AllAffixDefsByAffixes; foreach (string affixKey in AffixStrings) { LootAffixDef affix = affixDict[affixKey]; reportText += affix.FullStatsReport(parent, affixKey) + "\n"; } if (Prefs.DevMode) { reportText += "[DEV] Affix Rules:\n " + string.Join("\n ", affixRules) + "\n\n"; reportText += "[DEV] Total Points: " + affixes.Select(lad => lad.GetRealAffixCost(parent)).Sum() + "\n " + string.Join("\n ", affixes.Select(lad => AllAffixesByAffixDefs[lad] + ": " + lad.GetRealAffixCost(parent))) + "\n\n" ; } yield return(new StatDrawEntry( category: category, label: "RimLoot_LootAffixModifiers".Translate(), valueString: GenText.ToCommaList( AllAffixDefsByAffixes.Select(kv => kv.Value.LabelWithStyle(parent, kv.Key)), false ), reportText: reportText, hyperlinks: affixes.SelectMany(lad => lad.GetHyperlinks(parent)), displayPriorityWithinCategory: 1 )); // Add any additional entries from the defs or modifiers foreach (string affixKey in AffixStrings) { LootAffixDef affix = affixDict[affixKey]; foreach (var statDrawEntry in affix.SpecialDisplayStatsForThing(parent, affixKey)) { yield return(statDrawEntry); } } }
public virtual IEnumerable <string> ConfigErrors(LootAffixDef parentDef) { foreach (string configError in base.ConfigErrors()) { yield return(configError); } if (chance == 0f) { yield return("Chance is zero; effect would never occur"); } if (Mathf.Clamp(chance, 0f, 1f) != chance) { yield return("Chance is out-of-bounds; should be between >0 and 1"); } }
public override void ResolveReferences(LootAffixDef parentDef) { // FIXME: Might need to split this framework for ProjectileProperties + SurpriseAttackProps affectedField = "extraMeleeDamages"; if (chance != 1) { extraDamage.chance = chance; } else { chance = extraDamage.chance; } base.ResolveReferences(parentDef); }
public override IEnumerable <string> ConfigErrors(LootAffixDef parentDef) { foreach (string configError in base.ConfigErrors(parentDef)) { yield return(configError); } StatCategoryDef category = affectedStat.category; List <StatCategoryDef> acceptableCategories = new List <StatCategoryDef>() { StatCategoryDefOf.Basics, StatCategoryDefOf.BasicsImportant, StatCategoryDefOf.BasicsNonPawn, StatCategoryDefOf.BasicsPawn, StatCategoryDefOf.BasicsPawnImportant, StatCategoryDefOf.PawnCombat, StatCategoryDefOf.PawnMisc, StatCategoryDefOf.PawnSocial, StatCategoryDefOf.PawnWork, }; if (!acceptableCategories.Contains(category)) { yield return("The affectedStat isn't in the typical stat categories: " + category); } }
// NOTE: This also will get the SpecialDisplayStats entries above public void SpecialDisplayStatsInjectors(StatDrawEntry statDrawEntry) { // Fix firefoam damage displays if ( statDrawEntry.LabelCap == "Damage".Translate() && parent.def.IsWeaponUsingProjectiles && PrimaryVerbProps?.defaultProjectile?.projectile.damageDef?.harmsHealth == false ) { // [Reflection] statDrawEntry.value = 0f FieldInfo valueField = AccessTools.Field(typeof(StatDrawEntry), "value"); valueField.SetValue(statDrawEntry, 0f); } var affixDict = AllAffixDefsByAffixes; foreach (string affixKey in AffixStrings) { LootAffixDef affix = affixDict[affixKey]; affix.SpecialDisplayStatsInjectors(statDrawEntry, parent, affixKey); } }
private void MakeIcons() { Texture2D defIcon = parent.def.uiIcon; uiIcon = defIcon; if (!UnityData.IsInMainThread) { return; // too early to be fetching this stuff } if (AffixCount == 0) { return; } // Use the highest affix cost for the color LootAffixDef highestAffix = affixes.FirstOrFallback( lad => lad.IsDeadly(parent), // deadly overrides others affixes.OrderByDescending(lad => lad.GetRealAffixCost(parent)).First() ); ColorUtility.TryParseHtmlString(highestAffix.LabelColor(parent), out Color color); string texPart = AffixCount + "Affix"; if (highestAffix.IsDeadly(parent)) { texPart = "Deadly"; } // Grab the overlay icon float scale = Mathf.Sqrt(defIcon.width * defIcon.height) / 256; // 64x64 -> 16x16 overlays overlayIcon = IconUtility.FetchOrMakeIcon(texPart, color, scale); // Apply the overlay onto the Thing icon uiIcon = defIcon.CloneAsReadable(); uiIcon.AddOverlayToBLCorner(overlayIcon); uiIcon.Apply(true, true); // apply and lock }
public void CheckAndSendNegativeDeadlyAffixLetter(Pawn pawn) { if (Current.ProgramState != ProgramState.Playing) { return; } LootAffixDef deadlyAffix = affixes.FirstOrFallback(lad => lad.IsNegativeDeadly(parent)); if (deadlyAffix == null || pawn.Faction != Faction.OfPlayer) { return; } ChoiceLetter choiceLetter = LetterMaker.MakeLetter( label: "RimLoot_CursedItem".Translate() + ": " + pawn.LabelShortCap + " → " + deadlyAffix.LabelCap, text: "RimLoot_NegativeDeadlyAffixLetter_Text".Translate(pawn.Named("PAWN")), def: DefDatabase <LetterDef> .GetNamed("RimLoot_NegativeDeadlyAffix"), lookTargets: new LookTargets(new GlobalTargetInfo(pawn), new GlobalTargetInfo(parent)) ); Find.LetterStack.ReceiveLetter(choiceLetter); }
public override IEnumerable <string> ConfigErrors(LootAffixDef parentDef) { foreach (string configError in base.ConfigErrors(parentDef)) { yield return(configError); } if (newValue == null) { yield return("The newValue is not set!"); yield break; } // Check for reflection errors FieldInfo field = AccessTools.Field(typeof(VerbProperties), affectedField); Type type = field.FieldType; if (type != typeof(bool)) { yield return("Unsupported type: " + type); } }
public override IEnumerable <string> ConfigErrors(LootAffixDef parentDef) { foreach (string configError in base.ConfigErrors(parentDef)) { yield return(configError); } if (newDef == null) { yield return("The newDef is not set!"); yield break; } // Check for reflection errors FieldInfo field = AccessTools.Field(typeof(Tool), affectedField); Type type = field.FieldType; if (!typeof(Def).IsAssignableFrom(type)) { yield return("Unsupported type: " + type); } }
public override IEnumerable <string> ConfigErrors(LootAffixDef parentDef) { foreach (string configError in base.ConfigErrors(parentDef)) { yield return(configError); } if (affectedField == null) { yield return("The affectedField is not set!"); yield break; } // Check for reflection errors FieldInfo field = AccessTools.Field(ObjType, affectedField); if (field == null) { yield return("The affectedField doesn't exist in " + ObjType.Name + ": " + affectedField); yield break; } }
// FIXME: Some way to combine StatParts for multiple LADs? public override void ResolveReferences(LootAffixDef parentDef) { var statPart = new StatPart_LootAffix { parentStat = affectedStat, parentStatChanger = this, parentLootAffix = parentDef, }; if (affectedStat.parts == null) { affectedStat.parts = new List <StatPart> { statPart } } ; else { affectedStat.parts.Add(statPart) ; } affectedStat.ResolveReferences(); affectedStat.PostLoad(); // sometimes a reload, since we added a new part }
public override void PostDestroy(ThingWithComps parentThing, LootAffixDef parentDef) { DeregisterFromTickManager(parentThing); }
public override void PostApplyAffix(ThingWithComps parentThing, LootAffixDef parentDef) { RegisterToTickManager(parentThing); }
public virtual void PostDestroy(ThingWithComps parentThing, LootAffixDef parentDef) { }
public virtual void PostShotFired(ThingWithComps parentThing, LootAffixDef parentDef) { }