Item Levels

You are here:
← All Topics
Version: 2019.200 Requirements:uMMORPG3d, ToolsScript Define:_IMMOGUILDUPGRADES
Core Changes:YesTutorial Video:No

Description

This AddOn allows you to have Levels for all in-game items. Includes support for Guild Warehouse, and Player Warehouse. (Optionally include the respected scripts if you’re using either Guild or Player Warehouses).


Core Changes

  1. [Required] Open the following script ItemSlot.cs. See Changes...

    Add this line:
    public int level, experience;

    Replace to Constructor with:

        public ItemSlot(Item item, int amount=1, int level=1, int experience=1) {
          this.item = item;
          this.amount = amount;
          this.level = level;
          this.experience = experience;

    Replace to Tooltip with:

      public string ToolTip()
      {
          if (amount == 0) return "";
    
          // we use a StringBuilder so that addons can modify tooltips later too
          // ('string' itself can't be passed as a mutable object)
          StringBuilder tip = new StringBuilder(item.ToolTip());
          tip.Replace("{AMOUNT}", amount.ToString());
          tip.Replace("{LEVEL}", level.ToString());
          tip.Replace("{EXPERIENCE}", experience.ToString());
          tip.Replace("{GOAL}", computeLevel().ToString());
    
          if (item.data is EquipmentItem) {
          EquipmentItem eItem = ((EquipmentItem) item.data);
              tip.Replace("{DAMAGEBONUSBOOST}", (eItem.damageBonus*eItem.levelMultiplier)*level+"");
              tip.Replace("{DEFENSEBONUSBOOST}", ((eItem.defenseBonus * eItem.levelMultiplier)*level)+"");
              tip.Replace("{HEALTHBONUSBOOST}",  (float) ((eItem.healthBonus * eItem.levelMultiplier)*level)+"");
              tip.Replace("{MANABONUSBOOST}", ((eItem.manaBonus * eItem.levelMultiplier)*level)+"");
              tip.Replace("{BLOCKCHANCEBONUSBOOST}", ((eItem.blockChanceBonus * eItem.levelMultiplier)*level)+"");
              tip.Replace("{CRITICALCHANCEBONUSBOOST}", ((eItem.criticalChanceBonus * eItem.levelMultiplier)*level)+"");
          }
          return tip.ToString();
      }
  2. [Required] Open the following script UIInventory.cs. See Changes...

    In Update locate this line:
          slot.tooltip.enabled = true;
          slot.tooltip.text = itemSlot.ToolTip();
          slot.dragAndDropable.dragable = true;
          slot.image.color = Color.white;
          slot.image.sprite = itemSlot.item.image;
          slot.amountOverlay.SetActive(itemSlot.amount > 1);
          slot.amountText.text = itemSlot.amount.ToString();

    Add to this:

          if(slot.levelTMP != null) { slot.levelTMP.text = "Lv"+itemSlot.level; }
          else { slot.levelText.text = "Lv"+itemSlot.level; }

    In Update locate this line:

    slot.button.onClick.RemoveAllListeners();
          slot.tooltip.enabled = false;
          slot.dragAndDropable.dragable = false;
          slot.image.color = Color.clear;
          slot.image.sprite = null;
          slot.amountOverlay.SetActive(false);

    Add to this:

    if(slot.levelTMP != null) { slot.levelTMP.text = ""; }
          else { slot.levelText.text = ""; }
  3. [Required] Open the following script UIInventorySlot.cs. See Changes...

    Locate this line:
    public class UIInventorySlot : MonoBehaviour

    Modify to match:

    public partial class UIInventorySlot : MonoBehaviour
  4. [Required] Open the following script Player.cs. See Changes...

    Locate this line:
    Public bool CanCompleteQuest(string questName)

    Replace with:

    public bool CanCompleteQuest(string questName)
        {
            // has the quest and not completed yet?
            int index = GetQuestIndexByName(questName);
            if (index != -1 && !quests[index].completed)
            {
                // fulfilled?
                Quest quest = quests[index];
                if(quest.IsFulfilled(this))
                {
                    int tempAmount = 0;
                    for(int i = 0; i < quest.rewardItems.Count; i++) {
                        if(quest.rewardItems[i].amount > quest.rewardItems[i].item.maxStack) tempAmount += 1;
                            tempAmount += 1;
                    }
                    if(InventorySlotsFree() < tempAmount) return false;
                    // enough space for reward item (if any)?
                        return true;
                }
            }
            return false;
        }

    Locate this line:

    public bool CanCompleteQuest(string questName)

    Replace with:

    // helper function to check if the player can complete a quest
        public bool CanCompleteQuest(string questName)
        {
            // has the quest and not completed yet?
            int index = GetQuestIndexByName(questName);
            if (index != -1 && !quests[index].completed)
            {
                // fulfilled?
                Quest quest = quests[index];
                if(quest.IsFulfilled(this))
                {
                    int tempAmount = 0;
                    for(int i = 0; i < quest.rewardItems.Count; i++) {
                        if(quest.rewardItems[i].amount > quest.rewardItems[i].item.maxStack) tempAmount += 1;
                            tempAmount += 1;
                    }
                    if(InventorySlotsFree() < tempAmount) return false;
                    // enough space for reward item (if any)?
                        return true;
                }
            }
            return false;
        }

    Locate this line:

    [Command] 
    public void CmdCompleteQuest

    Replace with:

    [Command]
        public void CmdCompleteQuest(int npcQuestIndex)
        {
            // validate
            // use collider point(s) to also work with big entities
            if (state == "IDLE" &&
                target != null &&
                target.health > 0 &&
                target is Npc &&
                0 <= npcQuestIndex && npcQuestIndex < ((Npc)target).quests.Length &&
                Utils.ClosestDistance(collider, target.collider) <= interactionRange)
            {
                ScriptableQuestOffer npcQuest = ((Npc)target).quests[npcQuestIndex];
                if (npcQuest.completeHere)
                {
                    int index = GetQuestIndexByName(npcQuest.quest.name);
                    if (index != -1)
                    {
                        // can complete it? (also checks inventory space for reward, if any)
                        Quest quest = quests[index];
                        if (CanCompleteQuest(quest.name))
                        {
                            // call quest.OnCompleted to remove quest items from
                            // inventory, etc.
                            quest.OnCompleted(this);
    
                            // gain rewards
                            gold += quest.rewardGold;
                            experience += quest.rewardExperience;
                            
                            if (quest.rewardItems.Count > 0)
                            {
                                foreach(ScriptableItemAndAmount item in quest.rewardItems)
                                    InventoryAdd(new Item(item.item), item.amount, item.level);
                            }
    
                            // complete quest
                            quest.completed = true;
                            quests[index] = quest;
                        }
                    }
                }
            }
        }
  5. [Required] Open the following script ScriptableQuest.cs. See Changes...

    Add this line:
    public List rewardItems = new List();

    Replace Tooltip with:

        public virtual string ToolTip(Player player, Quest quest)
            {
            string rewardItems = "";
            if(quest.rewardItems.Count > 0) {
                for(int i = 0; i < quest.rewardItems.Count; i++) {
                    rewardItems += quest.rewardItems[i].amount+"x Lv"+ quest.rewardItems[i].level+ " "+quest.rewardItems[i].item.name;
                        if(i != quest.rewardItems.Count)
                            rewardItems += " \n";
                }
            }
            StringBuilder tip = new StringBuilder(toolTip);
            tip.Replace("{NAME}", name);
            tip.Replace("{REWARDGOLD}", rewardGold.ToString());
            tip.Replace("{REWARDEXPERIENCE}", rewardExperience.ToString());
            tip.Replace("{REWARDITEM}", rewardItems);
            return tip.ToString();
        }
  6. [Required] Open the following script Entity.cs. See Changes...

    Locate this line:
    Public bool InventoryAdd

    Replace with:

    public bool InventoryAdd(Item item, int amount, int level = 1, int experience = 0)
            {
            // we only want to add them if there is enough space for all of them, so
            // let's double check
            if (InventoryCanAdd(item, amount))
            {
                // add to same item stacks first (if any)
                // (otherwise we add to first empty even if there is an existing
                //  stack afterwards)
                for (int i = 0; i < inventory.Count; ++i)
                {
                    // not empty and same type? then add free amount (max-amount)
                    // note: .Equals because name AND dynamic variables matter (petLevel etc.)
                    if (inventory[i].amount > 0 && inventory[i].item.Equals(item) && inventory[i].level == level && inventory[i].experience == experience)
                    {
                        ItemSlot temp = inventory[i];
                        amount -= temp.IncreaseAmount(amount);
                        temp.level = level;
                        temp.experience = experience;
                        inventory[i] = temp;
                    }
    
                    // were we able to fit the whole amount already? then stop loop
                    if (amount <= 0) return true;
                }
    
                // add to empty slots (if any)
                for (int i = 0; i < inventory.Count; ++i)
                {
                    // empty? then fill slot with as many as possible
                    if (inventory[i].amount == 0)
                    {
                        int add = Mathf.Min(amount, item.maxStack);
                        inventory[i] = new ItemSlot(item, add, level, experience);
                        amount -= add;
                    }
    
                    // were we able to fit the whole amount already? then stop loop
                    if (amount <= 0) return true;
                }
                // we should have been able to add all of them
                if (amount != 0) Debug.LogError("inventory add failed: " + item.name + " " + amount);
            }
            return false;
        }
  7. [Required] Open the following script Player.cs. See Changes...

    Locate this line:
    public override int healthMax... - public override float criticalChance

    Replace with:

    // health
        public override int healthMax
        {
          get
          {
              /* calculate equipment bonus
              int equipmentBonus = (from slot in equipment
                                    where slot.amount > 0
                                    select ((EquipmentItem)slot.item.data).healthBonus).Sum();
    
                  */
                  int equipmentBonus = 0;
    
                  foreach(ItemSlot item in equipment) {
                      if(item.amount > 0) {
                          equipmentBonus += (int) (((EquipmentItem) item.item.data).healthBonus +
                              ((EquipmentItem) item.item.data).healthBonus * (1+item.item.data.levelMultiplier) * (item.level-1));
                      }
                  }
    
              // calculate strength bonus (1 strength means 1% of hpMax bonus)
              int attributeBonus = Convert.ToInt32(_healthMax.Get(level) * (strength * 0.01f));
    
              // base (health + buff) + equip + attributes
              return base.healthMax + equipmentBonus + attributeBonus;
          }
        }
    
        // mana
        public override int manaMax
        {
          get
          {
              // calculate equipment bonus
                  int equipmentBonus = 0;
    
                  foreach(ItemSlot item in equipment) {
                      if(item.amount > 0) {
                          equipmentBonus += (int) (((EquipmentItem) item.item.data).manaBonus +
                              ((EquipmentItem) item.item.data).manaBonus * (1+item.item.data.levelMultiplier) * (item.level-1));
                      }
                  }
    
              // calculate intelligence bonus (1 intelligence means 1% of hpMax bonus)
              int attributeBonus = Convert.ToInt32(_manaMax.Get(level) * (intelligence * 0.01f));
    
              // base (mana + buff) + equip + attributes
              return base.manaMax + equipmentBonus + attributeBonus;
          }
        }
    
        // damage
        public override int damage
        {
          get
          {
              // calculate equipment bonus
                  int equipmentBonus = 0;
    
                  foreach(ItemSlot item in equipment) {
                      if(item.amount > 0) {
                          equipmentBonus += (int) (((EquipmentItem) item.item.data).damageBonus +
                              ((EquipmentItem) item.item.data).damageBonus * (1+item.item.data.levelMultiplier) * (item.level-1));
                      }
                  }
    
              // return base (damage + buff) + equip
              return base.damage + equipmentBonus;
          }
        }
    
        // defense
        public override int defense
        {
          get
          {
              // calculate equipment bonus
                  int equipmentBonus = 0;
    
                  foreach(ItemSlot item in equipment) {
                      if(item.amount > 0) {
                          equipmentBonus += (int) (((EquipmentItem) item.item.data).defenseBonus +
                              ((EquipmentItem) item.item.data).defenseBonus * (1+item.item.data.levelMultiplier) * (item.level-1));
                      }
                  }
    
              // return base (defense + buff) + equip
              return base.defense + equipmentBonus;
          }
        }
    
        // block
        public override float blockChance
        {
          get
          {
              // calculate equipment bonus
                  int equipmentBonus = 0;
    
                  foreach(ItemSlot item in equipment) {
                      if(item.amount > 0) {
                          equipmentBonus += (int) (((EquipmentItem) item.item.data).blockChanceBonus +
                              ((EquipmentItem) item.item.data).blockChanceBonus * (1+item.item.data.levelMultiplier) * (item.level-1));
                      }
                  }
    
              // return base (blockChance + buff) + equip
              return base.blockChance + equipmentBonus;
          }
        }
    
        // crit
        public override float criticalChance
        {
          get
          {
              // calculate equipment bonus
                  int equipmentBonus = 0;
    
                  foreach(ItemSlot item in equipment) {
                      if(item.amount > 0) {
                          equipmentBonus += (int) (((EquipmentItem) item.item.data).criticalChanceBonus +
                              ((EquipmentItem) item.item.data).criticalChanceBonus * (1+item.item.data.levelMultiplier) * (item.level-1));
                      }
                  }
    
              // return base (criticalChance + buff) + equip
              return base.criticalChance + equipmentBonus;
          }
        }
  8. [Optional(GuildWarehouse)] Open the following script UITarget.cs. See Changes...

    Locate this line:
    [Command] 
    public void Cmd_UCE_SaveGuildWarehouse()

    Replace with:

    [Command]
        public void Cmd_UCE_SaveGuildWarehouse()
        {
            if (guild.name == "") return;
            Database.singleton.UCE_SaveGuildWarehouse(this);
            Database.singleton.SaveGuildWarehouseLevels(this);
        }

    Locate this line:

    [Command] 
    public void Cmd_UCE_LoadGuildWarehouse()

    Replace with:

    [Command]
        public void Cmd_UCE_LoadGuildWarehouse()
        {
            if (guild.name == "") return;
            Database.singleton.UCE_LoadGuildWarehouse(this);
            Database.singleton.LoadGuildWarehouseLevels(this);
        }

Installation

  1. [Required] Apply all core changes.
  2. [Required] For all Item Prefabs, Designate a Max Level.
  3. [Required] For all Player Prefabs, adjust Starter Items and Equipment to have >0 Level.

Extra

  • In Item Tooltips you can write bonus + BOOST to get stat boosts by level. Example {DAMAGEBONUSBOOST} for damage bonus boosted by level.
  • In Item Tooltips you can write {LEVEL} to get the items level.
  • In Item Tooltips you can write {GOAL} to get goal experience to next level.
  • In Item Tooltips you can write {EXPERIENCE} to get current level experience.
  • In Quest Tooltips you can write {REWARDITEMS} to get a list of items, amounts, and levels given by quest.

Support the IndieMMO Team Today!

Leave a reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.