public override void ResolveReferences(LootAffixDef parentDef)
 {
     // Among other overrides from HarmonyPatches
     affectedField = "requireLineOfSight";
     newValue      = false;
     base.ResolveReferences(parentDef);
 }
예제 #2
0
        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));
                }
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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
        }
예제 #6
0
        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;
     }
 }
예제 #9
0
        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();
        }
예제 #10
0
        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;
            }
        }
예제 #13
0
        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);
            }
        }
예제 #14
0
        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);
            }
        }
예제 #15
0
        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);
                }
            }
        }
예제 #17
0
        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);
        }
예제 #19
0
        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);
        }
예제 #23
0
        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);
            }
        }
예제 #24
0
        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);
            }
        }
예제 #25
0
        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);
 }
예제 #29
0
 public virtual void PostDestroy(ThingWithComps parentThing, LootAffixDef parentDef)
 {
 }
예제 #30
0
 public virtual void PostShotFired(ThingWithComps parentThing, LootAffixDef parentDef)
 {
 }