Outward

using System;
using UnityEngine;
using Partiality.Modloader;
using System.Collections;
using System.Reflection;
using On;

public class MyOutwardMod : PartialityMod
{
    // Constructor setting the fields of the PartialityMod class
    public MyOutwardMod() {
        this.ModID = "BetterCooldownFormatting";
        this.Version = "2";
        //this.loadPriority = 0;
        this.author = "Stian";
    }

    // OnEnable() is called when a mod is enabled (also when it's loaded)
    public override void OnEnable() {
        // We're overriding this method, so call the original
        base.OnEnable();

        On.ItemDetailsDisplay.RefreshDetail += new On.ItemDetailsDisplay.hook_RefreshDetail(ItemDetailsDisplay_RefreshDetail);
        On.StatusEffectDetailDisplay.RefreshDisplay += new On.StatusEffectDetailDisplay.hook_RefreshDisplay(StatusEffectDetailDisplay_RefreshDisplay);
    }

    // Hook the RefreshDetail method to modify the text formatting of cooldown time
    public bool ItemDetailsDisplay_RefreshDetail(On.ItemDetailsDisplay.orig_RefreshDetail orig, ItemDetailsDisplay self, int _rowIndex, ItemDetailsDisplay.DisplayedInfos _infoType) {
        // We're overriding this method, so call the original
        bool result = orig(self, _rowIndex, _infoType);

        // We're only gonna do custom stuff if we've been called to display a skill's cooldown
        if (_infoType == ItemDetailsDisplay.DisplayedInfos.Cooldown) {

            // Use reflection to access private/protected field ´cachedSkill´
            FieldInfo fieldInfo = self.GetType().GetField("cachedSkill",
                                                          BindingFlags.Public |
                                                          BindingFlags.NonPublic |
                                                          BindingFlags.Instance);
            Skill cachedSkill = (Skill)fieldInfo.GetValue(self);

            // Just a sanity check
            if (cachedSkill) {
                // Use reflection to call private method ´GetRow()´
                MethodInfo methodInfo = self.GetType().GetMethod("GetRow",
                                                                BindingFlags.Public |
                                                                BindingFlags.NonPublic |
                                                                BindingFlags.Instance);
                ItemDetailRowDisplay row = (ItemDetailRowDisplay)methodInfo.Invoke(self, new object[] { _rowIndex });

                // Format the duration and actually set the text label
                string formattedCooldown = FormatDuration(cachedSkill.Cooldown);
                row.SetInfo(LocalizationManager.Instance.GetLoc("ItemStat_Cooldown"), formattedCooldown);
            }
         }

        // This is the return value of the original method, since we don't do anything with the returned value, just some text formatting
        return result;
    }

    // Hook the RefreshDisplay method to modify the text formatting of duration time
    public void StatusEffectDetailDisplay_RefreshDisplay(On.StatusEffectDetailDisplay.orig_RefreshDisplay orig, StatusEffectDetailDisplay self) {
        // We're overriding this method, so call the original
        orig(self);

        // Use reflection to access private/protected field ´m_lblTimer´
        FieldInfo fieldInfo = self.GetType().GetField("m_lblTimer",
                                                      BindingFlags.Public |
                                                      BindingFlags.NonPublic |
                                                      BindingFlags.Instance);
        Text m_lblTimer = (Text)fieldInfo.GetValue(self);

        // Just a sanity check
        if (m_lblTimer) {
            if (m_lblTimer.text != string.Empty) {
                // The base implementation has calculated the duration to show, and prepared it for presentaton in ´m_lblTimer.text´
                // Cut off the " sec." suffix added by the base implementation
                string durationText = m_lblTimer.text.Substring(0, m_lblTimer.text.Length - 5);
                float duration = Convert.ToSingle(durationText);

                // Format the duration and actually set the text label
                string formattedDuration = FormatDuration(duration);
                m_lblTimer.text = formattedDuration;
            }
        }
    }

    // Format a number of seconds into presentable text: "60 sec" or "1 min 10 sec"
    private string FormatDuration(float seconds) {
        string cooldownText = "";
        float cooldownMinutes = Mathf.Round(seconds / 60);
        float cooldownSeconds = seconds - (cooldownMinutes * 60);
        if (cooldownMinutes > 0f) {
            cooldownText += cooldownMinutes.ToString() + " min";
        }
        if (cooldownSeconds > 0f) {
            if (cooldownMinutes > 0f) {
                cooldownText += " ";
            }
            cooldownText += cooldownSeconds.ToString() + " sec";
        }
        return cooldownText;
    }
}

Article information

Added on

Edited on

Written by

kongenav

0 comments