Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

uMMORPG Official Thread

Discussion in 'Assets and Asset Store' started by mischa2k, Dec 29, 2015.

  1. MHolmstrom

    MHolmstrom

    Joined:
    Aug 16, 2012
    Posts:
    115
    I was just thinking about, I've been looking here and there and the combat relies on CmdUseSkill.
    I would like to be able to run around the target and still be able to attack it. so I tried getting rid of the
    state == "MOVING" but no luck there.
    I'm using the WASD movement and removed the Destroy(indicator); thingy as well but still no luck.
    Why can't I move around the targeted target and still attack it because I don't like the "CmdNavigateTo" way of approaching monster's.

    Is there something that clears the set target, or is it something with CmdUseSKill that forbids it to be used while moving? Or do we clear the target once moved? thanks in advance :)
    (I'm considering integrating anything else than the current combat system (or find a better solution)) because it have been my enemy since day one :(

    Edit:
    I also tried using OnTriggerEnter to accomplish some more "no targeting / no auto attacking" system but that I just flushed down the toilet. Where do I look for editing the combat (outside selectionhading() ?
     
  2. Natalynn

    Natalynn

    Joined:
    Apr 21, 2013
    Posts:
    197
    I'll try using SQL Server Management Studio then, unless sqlite file browser is clean and free :eek:.
     
  3. gigz09

    gigz09

    Joined:
    Jun 6, 2016
    Posts:
    14
    Hi vis2k,

    The game is being stuck if I try to select "Server & Play" if leave either Name or Pass InputField blank right after I press the button on the popup.

    Then the console keeps on logging this:
    [Server] function 'System.Void Entity::Recover()' called on client
    UnityEngine.Debug:LogWarning(Object)
    Entity:Recover()

    Experienced it with untouched uMMORPG in unity editor with v1.52 and v1.53 (havent tested any build yet).
     
  4. Natalynn

    Natalynn

    Joined:
    Apr 21, 2013
    Posts:
    197
    Are you using 5.5.0p4 unity? That's the best patch & version to use at the moment with uMMORPG. If you are, Vis can guide further.
     
    mischa2k likes this.
  5. gigz09

    gigz09

    Joined:
    Jun 6, 2016
    Posts:
    14

    yes I am using 5.5.0p4. Sorry I forgot to mention that.
     
  6. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    Take a look at the player state machine. You are in the MOVING state while you start casting, which cancels the movement and goes to casting. Perhaps comment out the part that cancels the movement and see how that works (agent.ResetPath).

    It is.
    If you are using firefox, then you can even use this addon: https://addons.mozilla.org/de/firefox/addon/sqlite-manager/?src=

    Does it happen in the Editor?
    Does it work when you don't leave them blank?
    What do you mean with 'being stuck'? It's normal that the game doesn't start server & play mode if you don't enter an account, because server & play tries to start a server and a client at the same time. If it can't start the client because of an invalid account, then it can't really proceed.
     
  7. gigz09

    gigz09

    Joined:
    Jun 6, 2016
    Posts:
    14
    1, Yes, it happens in the editor (I can only test in the editor at the moment).
    2. It works as expected if you dont leave either one of them blank
    3. What I meant by stuck is, ummorpg went to a state that there is no UI for user to interact with. I understand that it shouldn't proceed to start the server or client if invalid credentials are provided but I expect it to return to the UILogin upon prompting the error in the popup. Please see attached screenshot, its right after I pressed the "Got it!" button of popup window, still the same after a couple of seconds.
     

    Attached Files:

  8. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    Progress: fixed a WSAD movement bug which was found by @tvirus06 . Our agent.NearestValidDestination function only worked when passing a position that is on the navmesh. WSAD movement always tries to go a few meters ahead and if there happens to be a big hole in the navmesh at that point, then it would do all kinds of weird things. Here is a screenshot that shows the kind of path that would cause issues:
    2017-01-23_pathfix.png

    The new function will find the nearest navmesh point in such cases and then calculate the nearest valid destination afterwards. This fix will be really useful to a lot of people!

    You are right. I didn't really bother doing that since you'd never use 'Server & Play' in a released MMO, but I will see what I can do anyways.
     
    camta005 and Natalynn like this.
  9. luis29vm

    luis29vm

    Joined:
    Oct 25, 2016
    Posts:
    164
    Hello I have This problem, for long time and I hope some one can help me, I have in my proyect Wand's and Staff's for 2 different Mages, but in the equipment type If I put EquipmentWeaponBow show the staff and if I put EquipmentWeaponStaff not show the weapon and if I put only EquipmentWeapon do same not show the weapon the only way that show the weapon is EquipmentWeaponBow and also I change in this 3 different ways in the Items and all is the same result. also this way I can use Archer weapons so is not good.Im going attach img, I hope some one can help me :) Thank you guys

    https://gyazo.com/152991c23a14a02f4c468f91d5ef5d9e
    not show the weapon

    https://gyazo.com/e3e9e276de5f50388a8dd1b85f9258ec
    Show the weapon
     
  10. jagatai33

    jagatai33

    Joined:
    Feb 2, 2016
    Posts:
    165

    Make sure your model has Player Equipment Location with the accepted category i.e. EquipmentWeaponStaff
     
    mischa2k likes this.
  11. luis29vm

    luis29vm

    Joined:
    Oct 25, 2016
    Posts:
    164
    Can you give me A screen shoot Because Im not sure what u mean.
     
  12. luis29vm

    luis29vm

    Joined:
    Oct 25, 2016
    Posts:
    164
    I find it and solve the Problem Thank you for your help
     
  13. Zhenite

    Zhenite

    Joined:
    Dec 6, 2016
    Posts:
    59
    Friends I'm starting to work on the items, the system I've developed requires a lot of modifications in that sense, studying uMMORPG I've discovered many things, but at some point I'm sure I'll need your help.

    For the moment I just need to know.
    Is there an event associated with dressing or taking out equipment?
     
  14. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    The player's equipment SyncListStruct's callback is used. Whenever it's changed by the server, the equipment is updated in 3D.
     
    Zhenite likes this.
  15. dude4004

    dude4004

    Joined:
    Jul 15, 2014
    Posts:
    181
    Quick question, is there any support for 2D RPG MMO?

    Best regards,
     
  16. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
  17. cioa00

    cioa00

    Joined:
    May 31, 2016
    Posts:
    203
    About character warehouse (ps.: this is character based!) here is the code (just tested with latest uMMORGP version, which is 1.53).

    Code (CSharp):
    1. // create new file UIWarehouse.cs under Scripts\_UI folder
    2. // Note: this script has to be on an always-active UI parent, so that we can
    3. // always react to the hotkey.
    4. using UnityEngine;
    5. using UnityEngine.UI;
    6.  
    7. public class UIWarehouse : MonoBehaviour {
    8.     [SerializeField] GameObject panel;
    9.     [SerializeField] GameObject slotPrefab;
    10.     [SerializeField] Transform content;
    11.     [SerializeField] Text goldText;
    12.  
    13. //    [SerializeField] UIDragAndDropable trash;
    14. //    [SerializeField] GameObject trashOverlay;
    15.  
    16.     void Update() {
    17.         var player = Utils.ClientLocalPlayer();
    18.         if (!player) return;
    19.  
    20.         // only update the panel if it's active
    21.         if (player.target != null && player.target is Npc &&
    22.             Utils.ClosestDistance(player.collider, player.target.collider) <= player.talkRange) {
    23.             // instantiate/destroy enough slots
    24.             UIUtils.BalancePrefabs(slotPrefab, player.warehouse.Count, content);
    25.  
    26.             // refresh all
    27.             for (int i = 0; i < player.warehouse.Count; ++i) {
    28.                 var entry = content.GetChild(i).GetChild(0); // slot entry
    29.                 entry.name = i.ToString(); // for drag and drop
    30.                 var item = player.warehouse[i];
    31.  
    32.                 if (item.valid) {
    33.                     // click event (only if player has minlevel)
    34.                     if (player.level >= item.minLevel) {
    35.                         int icopy = i; // needed for lambdas, otherwise i is Count
    36.                         entry.GetComponent<Button>().onClick.SetListener(() => {
    37.                             //player.CmdUseWarehouseItem(icopy);
    38.                         });
    39.                     } else entry.GetComponent<Button>().onClick.RemoveAllListeners();
    40.              
    41.                     // set state
    42.                     entry.GetComponent<UIShowToolTip>().enabled = true;
    43.                     entry.GetComponent<UIDragAndDropable>().dragable = true;
    44.                     // note: entries should be dropable at all times
    45.  
    46.                     // image
    47.                     entry.GetComponent<Image>().color = Color.white;
    48.                     entry.GetComponent<Image>().sprite = item.image;
    49.                     entry.GetComponent<UIShowToolTip>().text = item.Tooltip();
    50.  
    51.                     // amount overlay
    52.                     entry.GetChild(0).gameObject.SetActive(item.amount > 1);
    53.                     if (item.amount > 1) entry.GetComponentInChildren<Text>().text = item.amount.ToString();
    54.                 } else {
    55.                     // remove listeners
    56.                     entry.GetComponent<Button>().onClick.RemoveAllListeners();
    57.  
    58.                     // set state
    59.                     entry.GetComponent<UIShowToolTip>().enabled = false;
    60.                     entry.GetComponent<UIDragAndDropable>().dragable = false;
    61.  
    62.                     // image
    63.                     entry.GetComponent<Image>().color = Color.clear;
    64.                     entry.GetComponent<Image>().sprite = null;
    65.  
    66.                     // amount overlay
    67.                     entry.GetChild(0).gameObject.SetActive(false);
    68.                 }
    69.             }
    70.  
    71.             // gold
    72.             goldText.text = player.warehousegold.ToString();
    73.         }
    74.     }
    75. }
    76.  

    Code (CSharp):
    1. // open file Scripts\_UI\UINpcDialogue.cs
    2. // add new fields
    3.     [SerializeField] GameObject warehousePanel;
    4.     [SerializeField] Button warehouseButton;
    5.  
    6.  
    7. // inside method Update, add after quests related code block
    8.         // warehouse button
    9.         warehouseButton.gameObject.SetActive(true);
    10.         warehouseButton.onClick.SetListener(() => {
    11.             warehousePanel.SetActive(true);
    12.             panel.SetActive(false);
    13.         });


    Code (CSharp):
    1. // open file Scripts\PlayerDndHandling.cs
    2. // before class end tag add
    3.     ////////////////////////////////////////////////////////////////////////////
    4.     // warehouse DnD methods
    5.     ////////////////////////////////////////////////////////////////////////////
    6.     void OnDnd_WarehouseSlot_WarehouseSlot(int[] slotIndices) {
    7.         // merge? (just check the name, rest is done server sided)
    8.         if (player.warehouse[slotIndices[0]].valid && player.warehouse[slotIndices[1]].valid &&
    9.             player.warehouse[slotIndices[0]].name == player.warehouse[slotIndices[1]].name) {
    10.             player.CmdWarehouseMerge(slotIndices[0], slotIndices[1]);
    11.         // split?
    12.         } else if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) {
    13.             player.CmdWarehouseSplit(slotIndices[0], slotIndices[1]);
    14.         // swap?
    15.         } else {
    16.             player.CmdSwapWarehouseWarehouse(slotIndices[0], slotIndices[1]);
    17.         }
    18.     }
    19.  
    20.     void OnDnd_WarehouseSlot_InventorySlot(int[] slotIndices) {
    21.         if(player.warehouse[slotIndices[0]].valid && player.warehouse[slotIndices[0]].name != "") {
    22.             player.CmdSwapWarehouseInventory(slotIndices[0], slotIndices[1]);
    23.         }
    24.     }
    25.  
    26.     void OnDnd_InventorySlot_WarehouseSlot(int[] slotIndices) {
    27.         if(player.inventory[slotIndices[0]].valid && player.inventory[slotIndices[0]].name != "") {
    28.             player.CmdSwapInventoryWarehouse(slotIndices[0], slotIndices[1]);
    29.         }
    30.     }
    Code (CSharp):
    1. // open file Scripts\Player.cs
    2. // after row
    3. //     public ItemTemplate[] defaultItems;
    4. // add
    5.  
    6.     [Header("Warehouse")]
    7.     public int warehouseSize = 30;
    8.     public SyncListItem warehouse = new SyncListItem();
    9.     public ItemTemplate[] defaultWarehouseItems;
    10.     [SyncVar, HideInInspector] public long warehouseGold = 0;
    11.  
    12.  
    13. // after row
    14. //     public long gold { get { return _gold; } set { _gold = Math.Max(value, 0); } }
    15. // add
    16.     [SerializeField, SyncVar] long _warehousegold = 0;
    17.     public long warehousegold { get { return _warehousegold; } set { _warehousegold = Math.Max(value, 0); } }
    18.  
    19.  
    20. // find comment "npc teleport"
    21. // and before that add
    22.     // warehouse ///////////////////////////////////////////////////////////////
    23.     // helper function to find an item in the warehouse
    24.     public int GetWarehouseIndexByName(string itemName) {
    25.         return warehouse.FindIndex(item => item.valid && item.name == itemName);
    26.     }
    27.  
    28.     // helper function to calculate the free slots
    29.     public int WarehouseSlotsFree() {
    30.         return warehouse.Where(item => !item.valid).Count();
    31.     }
    32.  
    33.     // helper function to calculate the total amount of an item type in warehouse
    34.     public int WarehouseCountAmount(string itemName) {
    35.         return (from item in warehouse
    36.                 where item.valid && item.name == itemName
    37.                 select item.amount).Sum();
    38.     }
    39.  
    40.     // helper function to remove 'n' items from the warehouse
    41.     public bool WarehouseRemoveAmount(string itemName, int amount) {
    42.         for (int i = 0; i < warehouse.Count; ++i) {
    43.             if (warehouse[i].valid && warehouse[i].name == itemName) {
    44.                 var item = warehouse[i];
    45.  
    46.                 // take as many as possible
    47.                 int take = Mathf.Min(amount, item.amount);
    48.                 item.amount -= take;
    49.                 amount -= take;
    50.  
    51.                 // make slot invalid if amount is 0 now
    52.                 if (item.amount == 0) item.valid = false;
    53.  
    54.                 // save all changes
    55.                 warehouse[i] = item;
    56.  
    57.                 // are we done?
    58.                 if (amount == 0) return true;
    59.             }
    60.         }
    61.  
    62.         // if we got here, then we didn't remove enough items
    63.         return false;
    64.     }
    65.  
    66.     // helper function to check if the warehouse has space for 'n' items of type
    67.     // based on InventoryCanAddAmount
    68.     public bool WarehouseCanAddAmount(ItemTemplate item, int amount) {
    69.         // go through each slot
    70.         for (int i = 0; i < warehouse.Count; ++i) {
    71.             // empty? then subtract maxstack
    72.             if (!warehouse[i].valid)
    73.                 amount -= item.maxStack;
    74.             // not empty and same type? then subtract free amount (max-amount)
    75.             else if (warehouse[i].valid && warehouse[i].name == item.name)
    76.                 amount -= (warehouse[i].maxStack - warehouse[i].amount);
    77.  
    78.             // were we able to fit the whole amount already?
    79.             if (amount <= 0) return true;
    80.         }
    81.  
    82.         // if we got here than amount was never <= 0
    83.         return false;
    84.     }
    85.  
    86.     // helper function to put 'n' items of a type into the inventory, while
    87.     // based on InventoryAddAmount
    88.     public bool WarehouseAddAmount(ItemTemplate item, int amount) {
    89.         // we only want to add them if there is enough space for all of them, so
    90.         // let's double check
    91.         if (WarehouseCanAddAmount(item, amount)) {
    92.             // go through each slot
    93.             for (int i = 0; i < warehouse.Count; ++i) {
    94.                 // empty? then fill slot with as many as possible
    95.                 if (!warehouse[i].valid) {
    96.                     int add = Mathf.Min(amount, item.maxStack);
    97.                     warehouse[i] = new Item(item, add);
    98.                     amount -= add;
    99.                 }
    100.                 // not empty and same type? then add free amount (max-amount)
    101.                 else if (warehouse[i].valid && warehouse[i].name == item.name) {
    102.                     int space = warehouse[i].maxStack - warehouse[i].amount;
    103.                     int add = Mathf.Min(amount, space);
    104.                     var temp = warehouse[i];
    105.                     temp.amount += add;
    106.                     warehouse[i] = temp;
    107.                     amount -= add;
    108.                 }
    109.  
    110.                 // were we able to fit the whole amount already?
    111.                 if (amount <= 0) return true;
    112.             }
    113.             // we should have been able to add all of them
    114.             if (amount != 0) Debug.LogError("warehouse add failed: " + item.name + " " + amount);
    115.         }
    116.         return false;
    117.     }
    118.  
    119.     [Command(channel=Channels.DefaultUnreliable)] // unimportant => unreliable
    120.     public void CmdSwapWarehouseWarehouse(int fromIndex, int toIndex) {
    121.         if ((state == "IDLE" || state == "MOVING" || state == "CASTING") &&
    122.             0 <= fromIndex && fromIndex < warehouse.Count &&
    123.             0 <= toIndex && toIndex < warehouse.Count &&
    124.             fromIndex != toIndex) {
    125.             // swap them
    126.             var temp = warehouse[fromIndex];
    127.             warehouse[fromIndex] = warehouse[toIndex];
    128.             warehouse[toIndex] = temp;
    129.         }
    130.     }
    131.  
    132.     [Command(channel=Channels.DefaultUnreliable)] // unimportant => unreliable
    133.     public void CmdSwapWarehouseInventory(int fromIndex, int toIndex) {
    134.         if ((state == "IDLE" || state == "MOVING" || state == "CASTING") &&
    135.             0 <= fromIndex && fromIndex < warehouse.Count &&
    136.             0 <= toIndex && toIndex < inventory.Count &&
    137.             fromIndex != toIndex) {
    138.             // swap them
    139.             var temp = warehouse[fromIndex];
    140.             warehouse[fromIndex] = inventory[toIndex];
    141.             inventory[toIndex] = temp;
    142.         }
    143.     }
    144.  
    145.     [Command(channel=Channels.DefaultUnreliable)] // unimportant => unreliable
    146.     public void CmdSwapInventoryWarehouse(int fromIndex, int toIndex) {
    147.         if ((state == "IDLE" || state == "MOVING" || state == "CASTING") &&
    148.             0 <= fromIndex && fromIndex < inventory.Count &&
    149.             0 <= toIndex && toIndex < warehouse.Count &&
    150.             fromIndex != toIndex) {
    151.             // swap them
    152.             var temp = inventory[fromIndex];
    153.             inventory[fromIndex] = warehouse[toIndex];
    154.             warehouse[toIndex] = temp;
    155.         }
    156.     }
    157.  
    158.  
    159.     [Command(channel=Channels.DefaultUnreliable)] // unimportant => unreliable
    160.     public void CmdWarehouseSplit(int fromIndex, int toIndex) {
    161.         if ((state == "IDLE" || state == "MOVING" || state == "CASTING") &&
    162.             0 <= fromIndex && fromIndex < warehouse.Count &&
    163.             0 <= toIndex && toIndex < warehouse.Count &&
    164.             fromIndex != toIndex) {
    165.             // slotFrom has to have an entry, slotTo has to be empty
    166.             if (warehouse[fromIndex].valid && !warehouse[toIndex].valid) {
    167.                 // from entry needs at least amount of 2
    168.                 if (warehouse[fromIndex].amount >= 2) {
    169.                     // split them serversided (has to work for even and odd)
    170.                     var itemFrom = warehouse[fromIndex];
    171.                     var itemTo = warehouse[fromIndex]; // copy the value
    172.                     //warehouse[toIndex] = warehouse[fromIndex]; // copy value type
    173.                     itemTo.amount = itemFrom.amount / 2;
    174.                     itemFrom.amount -= itemTo.amount; // works for odd too
    175.  
    176.                     // put back into the list
    177.                     warehouse[fromIndex] = itemFrom;
    178.                     warehouse[toIndex] = itemTo;
    179.                 }
    180.             }
    181.         }
    182.     }
    183.  
    184.     [Command(channel=Channels.DefaultUnreliable)] // unimportant => unreliable
    185.     public void CmdWarehouseMerge(int fromIndex, int toIndex) {
    186.         if ((state == "IDLE" || state == "MOVING" || state == "CASTING") &&
    187.             0 <= fromIndex && fromIndex < warehouse.Count &&
    188.             0 <= toIndex && toIndex < warehouse.Count &&
    189.             fromIndex != toIndex) {
    190.             // both items have to be valid
    191.             if (warehouse[fromIndex].valid && warehouse[toIndex].valid) {
    192.                 // make sure that items are the same type
    193.                 if (warehouse[fromIndex].name == warehouse[toIndex].name) {
    194.                     // merge from -> to
    195.                     var itemFrom = warehouse[fromIndex];
    196.                     var itemTo = warehouse[toIndex];
    197.                     int stack = Mathf.Min(itemFrom.amount + itemTo.amount, itemTo.maxStack);
    198.                     int put = stack - itemFrom.amount;
    199.                     itemFrom.amount = itemTo.amount - put;
    200.                     itemTo.amount = stack;
    201.                     // 'from' empty now? then clear it
    202.                     if (itemFrom.amount == 0) itemFrom.valid = false;
    203.                     // put back into the list
    204.                     warehouse[fromIndex] = itemFrom;
    205.                     warehouse[toIndex] = itemTo;
    206.                 }
    207.             }
    208.         }
    209.     }
    210.  

    Code (CSharp):
    1. // open file Scripts\Database.cs
    2. // find method CharacterSave
    3. // after row
    4. // writer.WriteElementObject("equipment", player.equipment.ToList());
    5. // add
    6.             // warehouse
    7.             writer.WriteElementObject("warehouse", player.warehouse.ToList());
    8.  
    9.  
    10. // find method CharacterLoad
    11. // before comment "// load skills based on skill templates"
    12. // add
    13.                     // load warehouse
    14.                     foreach (var item in reader.ReadElementObject< List<Item> >())
    15.                         player.warehouse.Add(item.valid && item.TemplateExists() ? item : new Item());
    16.  
    17.  
    18. // find method CharacterCreate
    19. // before comment " // full health and mana (after equipment so that hpmax is correct)"
    20. // add
    21.         // default warehouse slots + items (if any)
    22.         for (int i = 0; i < player.warehouseSize; ++i)
    23.             player.warehouse.Add(i < player.defaultWarehouseItems.Length
    24.                                  ? new Item(player.defaultWarehouseItems[i])
    25.                                  : new Item());
    26.  
    27.  







    As @luis29vm pointed out on pm, i forgot mention that you guys need add new tag WarehouseSlot for warehouse slot prefab (you can see it also in here
    )



    Now i`ll try prepare code for how to store gold to warehouse and how to re-change this character warehouse account-wide warehouse. And probably totally new video to wrap this all.
     
    Last edited: Jan 24, 2017
    WoogyIM, CrandellWS, mischa2k and 2 others like this.
  18. Zhenite

    Zhenite

    Joined:
    Dec 6, 2016
    Posts:
    59
    Vis, help me, I understand what I have to do, but not how I should do it.

    I want to check if there is any equipment for example in the "EquipmentShield" slot, I understand that it is using "item.valid".
    But how should I do it?

    I am developing an animation system based on the type of the weapon, I created an "int" parameter in the animator and based on the category of the weapon I will change the value of this parameter.
    How do I get the value of the "Category" field of the equipment that is, for example, in the "EquipmentWeapon" slot?

    If I want to add new fields to the items should I do this in the "ItemTemplate.cs" and "Item.cs" only?
     
  19. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    Good morning!

    Nice job, I added the link to the documentation.

    One step after another :)
    The player has a .equipment SyncListStruct that contains all the items. You are right that you can use .valid to check if there is one in that slot. If you need the categories, you can find them in player.equipmentTypes. So equipmentTypes[0] is for .equipment[0] and so on. So if you want the one for the weapon slot, use equipmentTypes to find the index of "EquipmentWeapon", then use .equipment[your_found_index].valid.
     
    Zhenite likes this.
  20. jagatai33

    jagatai33

    Joined:
    Feb 2, 2016
    Posts:
    165
    Good Morning,

    So i finally came to my ends with the SyncVar 32 limit (especially for attributes like Strength, Dexterity, Intelligence etc...), i implemented the following and im hoping due to its simplicity vis2k might adopt it into uMMORPG.

    So first create a script named "Attribute.cs" and fill it in with the code below:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using UnityEngine.Networking;
    5.  
    6. [System.Serializable]
    7. public struct Attribute {
    8.     public string name;
    9.     public bool learned; // for future use
    10.     public int value;
    11.  
    12.     public Attribute(string _name, int _value, bool _learned) {
    13.         name = _name;
    14.         learned = _learned;
    15.         value = _value;
    16.     }
    17. }
    18.  
    19. public class SyncListAttribute : SyncListStruct<Attribute> { }
    20.  
    In Entiy.cs add the following line:
    Code (CSharp):
    1.     [Header("Attributes")]
    2.     public SyncListAttribute attributes = new SyncListAttribute();
    3.  
    In Player.cs replace the two lines that define [SyncVar] strength and intelligence with the following:
    Code (CSharp):
    1.     public int strength {
    2.         get {
    3.             int idx = attributes.FindIndex(att => att.name == "Strength");
    4.             if (idx != -1) return attributes[idx].value;
    5.             return 0;
    6.         }
    7.         set {
    8.             int idx = attributes.FindIndex(att => att.name == "Strength");
    9.             if (idx != -1) {
    10.                 var temp = attributes[idx];
    11.                 temp.value = value;
    12.                 attributes[idx] = temp;
    13.             }
    14.         }
    15.     }
    16.     public int intelligence {
    17.         get {
    18.             int idx = attributes.FindIndex(att => att.name == "Intelligence");
    19.             if (idx != -1) return attributes[idx].value;
    20.             return 0;
    21.         }
    22.         set {
    23.             int idx = attributes.FindIndex(att => att.name == "Intelligence");
    24.             if (idx != -1) {
    25.                 var temp = attributes[idx];
    26.                 temp.value = value;
    27.                 attributes[idx] = temp;
    28.             }
    29.         }
    30.     }
    Now we need to make it persistent in Database.cs by first removing the following two lines from CharacterSave()
    Code (CSharp):
    1.             writer.WriteElementValue("strength", player.strength);
    2.             writer.WriteElementValue("intelligence", player.intelligence);
    Then add the following line after "quests":
    Code (CSharp):
    1.             writer.WriteElementObject("attributes", player.attributes.ToList());
    next remove the following two lines from CharacterLoad()
    Code (CSharp):
    1.                     player.strength     = reader.ReadElementContentAsInt();
    2.                     player.intelligence = reader.ReadElementContentAsInt();
    Then add the following line after "quests":
    Code (CSharp):
    1.                     foreach (var attribute in reader.ReadElementObject<List<Attribute>>())
    2.                         player.attributes.Add(attribute);
    and finally in CharacterCreate() add the following lines after // default equipment slots:
    Code (CSharp):
    1.         // default attributes
    2.         player.attributes.Add(new Attribute("Strength", 0, false));
    3.         player.attributes.Add(new Attribute("Intelligence", 0, false));

    .. and thats it, now you can add as many attributes as you like without all the 32 SyncVar limitation and you dont have to go around replacing all the strength/intelligence since we kept it as a public get/set wrapper.

    Hope this made sense.
    -J
     
    Sarrivin, camta005, bartuq and 2 others like this.
  21. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    Progress: still playing around with SQLite. I added character soft delete to my test Script, which is really cool. If a player accidentally deletes his character then support can restore it by resetting the 'deleted' flag in the database. This will make a lot of players really happy, especially if real money for item mall stuff was involved.

    Cool, I added it to the documentation: https://noobtuts.com/unity/MMORPG#community-addon-attribute-list
    Not sure yet if I'll add it to the official code base. It's definitely useful for people who run into that SyncVar limit, may overcomplicate it for the rest though.
     
  22. dude4004

    dude4004

    Joined:
    Jul 15, 2014
    Posts:
    181
    Ok, so it can be done in your documentation, BUT some code need to be modified.
    Do you know if it's a large process or only a quick one? I'm not bad at all to coding, but I would like to make a MMORPG using sprites, Turn Based Combat.

    best regards,
     
  23. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    Getting it to work with NavMeshAgent2D is not difficult, I tried it a few weeks ago. You just replace NavMeshAgent with the 2D version and then Unity will show you some errors for the places in the code that need to be modified.

    Also I suggest waiting for Navigation2D version 1.13. uMMORPG uses NavMeshAgent.CalculatePath now and I just added that to NavMeshAgent2D today.
     
  24. Zhenite

    Zhenite

    Joined:
    Dec 6, 2016
    Posts:
    59
    I got

    - I added this in "ItemTemplate.cs":
    public equipTipos equipTipo;
    public equipPesos equipPeso;
    public equipTamanhos equipTamanho;
    public enum equipTipos { NaoAplica, Faca, Adaga, Porrete, Espada1M, Espada2M, Escudo, Machado1M, Machado2M}
    public enum equipPesos { NaoAplica, Leve, Medio, Pesado }
    public enum equipTamanhos { NaoAplica, Pequeno, Medio, Grande }

    - This in "Item.cs":
    public int equipTipo {get { return (int)template.equipTipo; } }
    public int equipPeso {get { return (int)template.equipPeso; }}
    public int equipTamanho {get { return (int)template.equipTamanho; }}

    - And this in "Player.cs", inside "void Start()" and "void OnEquipmentChanged":
    animator.SetInteger("EquipTipoIndex", equipment[0].equipTipo); (Just to exemplify)
     
    Last edited: Jan 25, 2017
    mischa2k likes this.
  25. dude4004

    dude4004

    Joined:
    Jul 15, 2014
    Posts:
    181
    I did not buy anything yet, but I just want to make sure it can be done before.
    I'll think about it then.
    If there was a 2d demo showing the result, I would gladly buy it instantly.

    Best regards,
     
  26. Zhenite

    Zhenite

    Joined:
    Dec 6, 2016
    Posts:
    59
    You can buy it with your eyes closed.
    Even me who am a jerk in programming, with the support of Vis, I am able to accomplish very nice things.
    Come to the family and be happy!
     
    mischa2k and Ronith like this.
  27. Zhenite

    Zhenite

    Joined:
    Dec 6, 2016
    Posts:
    59
    @vis2k
    Does not the character attack if unarmed?
    What is the criterion?
    Where can I change this?
     
  28. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    Progress: finished the SQLite database version. Added shadow delete (characters can be restored if they were deleted accidentally). Finished the account system (create if not exists yet, otherwise compare password). There is also a little 'create account' button in the Login UI now, it shows a message about how to create one:
    2017-01-25_accountsystem.png
    With an SQL database and a simple account system in place, I can now research the CMS / item mall problem.


    You can make HasCastWeapon return true at all times if you want to allow attacking without weapons. I didn't do it to save an animation.
     
    camta005, Zhenite and jagatai33 like this.
  29. gigz09

    gigz09

    Joined:
    Jun 6, 2016
    Posts:
    14
    refer to this post:
    https://forum.unity3d.com/threads/ummorpg-official-thread.376636/page-30#post-2873694

    That's all what I did + some adjustments in Navigation2D that will be probably included in v1.13, although I'm still having a problem with the vertical navigation (still trying to figure out on how Unity NavMesh really works before I post my question here, or probably Navigation2D v1.13 can already solve it :D).
     
    mischa2k likes this.
  30. luis29vm

    luis29vm

    Joined:
    Oct 25, 2016
    Posts:
    164
    Nice release, :)
     
  31. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    Not yet, still waiting for V1.54 to be accepted first.
     
  32. jagatai33

    jagatai33

    Joined:
    Feb 2, 2016
    Posts:
    165

    LOL its on the Asset Store :)

    ** also released 5.5.1 ( i think it contains all the network fixes in 5.5.0.p4 )
     
    Last edited: Jan 25, 2017
  33. MHolmstrom

    MHolmstrom

    Joined:
    Aug 16, 2012
    Posts:
    115
    I'd like to see a screencap of how it looks in 2d would be fun :)
     
  34. Natalynn

    Natalynn

    Joined:
    Apr 21, 2013
    Posts:
    197
    uMMORPG 1.54 is out now, and same for Unity 5.5.1. Does Unity 5.5.1 fix any of the issues in uMMORPG, vis?

    Also I found a real small minor bug; The chat doesn't auto scroll to the last message when you click play.
     
    Last edited: Jan 25, 2017
  35. Zhenite

    Zhenite

    Joined:
    Dec 6, 2016
    Posts:
    59
    Vis, how do I make an equipment occupy the space of the right and left hand, for example a two-handed axe?
     
  36. luis29vm

    luis29vm

    Joined:
    Oct 25, 2016
    Posts:
    164
  37. bartuq

    bartuq

    Joined:
    Sep 26, 2016
    Posts:
    127
    It is possible to add item to backpack in this way, by name? Example: "/add sunshield, 1" in PlayerChat.cs will be add Sun Shield x1 to backpack as a command for Game Masters/Admin.
     
  38. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    Update: as was mentioned already, V1.54 is released:
    • NetworkManager OnClientConnect Unity 5.2 bug workaround removed because it's been a while now
    • NetworkManager SavePlayers simplified via LINQ from-where-select
    • NetworkManager CharacterDelete prints character name in log instead of just printing the index. This is useful for MMOs in production.
    • NavMeshAgent.NearestValidDestination extension improved: fixed an issue with positions that are not on a NavMesh; returns agent position in case of failure now.
    • Monster random movement uses Random.insideUnitCircle now. Allows us to remove Utils.RandVec3XZ function and makes sure that the monster stays inside the radius (RandVec3XZwasn't normalized before)
    All of the 5.5.1 fixes are good for us, mostly the networking fixes of course. Can remove the OnDestroy isLocalPlayer workaround then.

    Yes the chat doesn't autoscroll in the beginning, seems like that only works when Update is already running. That might be okay though, most MMOs won't have more than a welcome message there initially and adding a workaround would just overcomplicate things.

    It's designed with shoes / gloves in mind, so one shoe model will be put into all EquipmentFeet slots, not just one. As for a double handed weapon, can't you put it into one hand and rotate it properly?

    It's not implemented, but of course it's possible. Try it :)
     
    Zhenite, jagatai33 and camta005 like this.
  39. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    Check the changelog in the first post, this version had mostly minor improvements.
     
  40. bartuq

    bartuq

    Joined:
    Sep 26, 2016
    Posts:
    127
    Cool project, crafting ideas [LINK] Reminds me of uMMORPG (UI setting) perhaps it served as the base ;)
     
  41. MHolmstrom

    MHolmstrom

    Joined:
    Aug 16, 2012
    Posts:
    115
    For a more RPG 3rd person Camera just replace everything within "CameraMMO.cs".
    working on the first person part at the moment.
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class CameraMMO : MonoBehaviour
    6. {
    7.     //Public
    8.     public Transform target;                                // Player (Leave empty)
    9.     public float targetHeight = 1.7f;                       // Vertical offset (Could be changed into Transform for bone focus ec "Head")
    10.     public float distance = 12.0f;                          // Default Distance
    11.     public float offsetCWall = 0.1f;                        // Bring camera away from any colliding objects based on layers
    12.     public float maxDistance = 10;                          // Maximum zoom Distance
    13.     public float minDistance = 0.1f;                        // Minimum zoom Distance
    14.     public float xRotSpeed = 200.0f;                        // Orbit speed (Left/Right)
    15.     public float yRotSpeed = 200.0f;                        // Orbit speed (Up/Down)
    16.     public float yMinLimit = -80;                           // Look up limit
    17.     public float yMaxLimit = 80;                            // Look down limit
    18.     public float zoomRate = 40;                             // Zoom Speed
    19.     public float rotationDampening = 3.0f;                  // Higher Value makes rot faster
    20.     public float zoomDampening = 5.0f;                      // Higher Value makes Zoom faster
    21.  
    22.     // Collision Fix
    23.     public LayerMask collisionLayers;                         // What layer the camera will collide with
    24.  
    25.     //Misc
    26.     public bool lockToRearOfTarget;                         //Focus camera behind Player
    27.     public bool allowMouseInputX = true;
    28.     public bool allowMouseInputY = true;
    29.  
    30.     //Privates
    31.     private float xAng = 0.0f;
    32.     private float yAng = 0.0f;
    33.     private float currentDistance;
    34.     public float ActiveDistance;
    35.     private float correctDistance;
    36.     private bool rotateBehind;
    37.  
    38.     public bool inFirstPerson;                              // Change conditions to FPS
    39.  
    40.     void Start()
    41.     {
    42.  
    43.         Vector3 angles = transform.eulerAngles;
    44.         xAng = angles.x;
    45.         yAng = angles.y;
    46.         currentDistance = distance;
    47.         ActiveDistance = distance;
    48.         correctDistance = distance;
    49.  
    50.  
    51.         if (lockToRearOfTarget)
    52.             rotateBehind = true;
    53.     }
    54.  
    55.     void Update()
    56.     {
    57.         if (Input.GetAxis("Mouse ScrollWheel") < 0)
    58.         {
    59.  
    60.             if (inFirstPerson == true)
    61.             {
    62.  
    63.                 minDistance = 0;
    64.                 ActiveDistance = 2;
    65.                 inFirstPerson = false;
    66.             }
    67.         }
    68.  
    69.         if (ActiveDistance <= 1)
    70.         {
    71.  
    72.             minDistance = -1;
    73.             ActiveDistance = -1;
    74.             inFirstPerson = true;
    75.         }
    76.     }
    77.  
    78.     //After all update, move Camera
    79.     void LateUpdate()
    80.     {
    81.  
    82.         // Don't do anything if target is not defined
    83.         if (!target)
    84.             return;
    85.        
    86.  
    87.         // If either mouse buttons are down, let the mouse govern camera position
    88.         if (GUIUtility.hotControl == 0)
    89.         {
    90.             if (Input.GetKey(KeyCode.LeftControl))
    91.             {
    92.  
    93.             }
    94.             else {
    95.                 if (!Utils.IsCursorOverUserInterface() && Input.GetMouseButton(1))
    96.                 {
    97.                     //Check to see if mouse input is allowed on the axis
    98.                     if (allowMouseInputX)
    99.                         xAng += Input.GetAxis("Mouse X") * xRotSpeed * 0.02f;
    100.                     if (allowMouseInputY)
    101.                         yAng -= Input.GetAxis("Mouse Y") * yRotSpeed * 0.02f;
    102.  
    103.                 }
    104.             }
    105.         }
    106.         ClampAngle(yAng);
    107.  
    108.         // Camera rotation
    109.         Quaternion rotation = Quaternion.Euler(yAng, xAng, 0);
    110.  
    111.         // Calculate the Active distance
    112.         ActiveDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(ActiveDistance);
    113.         ActiveDistance = Mathf.Clamp(ActiveDistance, minDistance, maxDistance);
    114.         correctDistance = ActiveDistance;
    115.  
    116.         // Calculate desired camera position
    117.         Vector3 vTargetOffset = new Vector3(0, -targetHeight, 0);
    118.         Vector3 position = target.position - (rotation * Vector3.forward * ActiveDistance + vTargetOffset);
    119.  
    120.         // Check for collision based on the target's desired registration point as set by using height
    121.         RaycastHit collisionHit;
    122.         Vector3 trueTargetPosition = new Vector3(target.position.x, target.position.y + targetHeight, target.position.z);
    123.  
    124.         // If there is a Collision, adjust the position of the camera and calculate the correct distance
    125.         bool isCorrected = false;
    126.         if (Physics.Linecast(trueTargetPosition, position, out collisionHit, collisionLayers))
    127.         {
    128.             correctDistance = Vector3.Distance(trueTargetPosition, collisionHit.point) - offsetCWall;
    129.             isCorrected = true;
    130.         }
    131.  
    132.         // For smoothing, lerp distance only if either distance wasn't corrected, or correctDistance is more than ActiveDistance
    133.         currentDistance = !isCorrected || correctDistance > currentDistance ? Mathf.Lerp(currentDistance, correctDistance, Time.deltaTime * zoomDampening) : correctDistance;
    134.  
    135.         // Keep the limits
    136.         currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance);
    137.  
    138.         // Recalculate position based on the new currentDistance
    139.         position = target.position - (rotation * Vector3.forward * currentDistance + vTargetOffset);
    140.  
    141.         //Finally Set rotation and position of camera
    142.         transform.rotation = rotation;
    143.         transform.position = position;
    144.     }
    145.  
    146.     void ClampAngle(float angle)
    147.     {
    148.         if (angle < -360)
    149.             angle += 360;
    150.         if (angle > 360)
    151.             angle -= 360;
    152.  
    153.         yAng = Mathf.Clamp(angle, -60, 80);
    154.     }
    155.  
    156. }
    157.  
     
    Last edited: Feb 1, 2017
  42. GOLDY00

    GOLDY00

    Joined:
    Mar 16, 2013
    Posts:
    139
    Can you do a combine first and third that will be sick that's what I need like maybe push a button it. Changes
     
    CrandellWS likes this.
  43. GOLDY00

    GOLDY00

    Joined:
    Mar 16, 2013
    Posts:
    139
    Also how do you change the crafting so it's a blueprint system instead of the way it is now
     
  44. Ronith

    Ronith

    Joined:
    Feb 20, 2014
    Posts:
    69
    Empty Blueprint Item + Weapon Item = Weapon Blueprint Item
    Weapon Blueprint Item + Resources = Crafted Weapon

    Just an Example :)
     
    mischa2k likes this.
  45. MHolmstrom

    MHolmstrom

    Joined:
    Aug 16, 2012
    Posts:
    115
    EDIT: Fixed minor issue where cursor would not set back unless not colliding.
    Another small thing people might like to add is Hover Over Cursor script that changes the Cursor depending on Tag.
    Open up Player.cs
    Code (CSharp):
    1. //Over [Header("Attributes")] add:
    2. //MISC
    3.     [Header("Misc")]
    4.     public bool HoverOverActive;
    5.     public CursorMode cursorMode = CursorMode.Auto;
    6.     public Vector2 hotSpot = Vector2.zero;
    7.     public Texture2D Monstercursor;
    8.     public Texture2D NPCcursor;
    9.  
    Then add after the void WSADHandling() function ends add
    Code (CSharp):
    1.  
    2.     [Client]
    3.     void HoverCursor()
    4.     {
    5.         Ray ray2 = Camera.main.ScreenPointToRay(Input.mousePosition);
    6.         RaycastHit hit2;
    7.         Cursor.SetCursor(null, Vector2.zero, cursorMode);
    8.         if (Physics.Raycast(ray2, out hit2, 10000))
    9.         {
    10.             if (hit2.transform.tag == "Monster")
    11.             {
    12.                 HoverOverActive = true;
    13.                 Cursor.SetCursor(Monstercursor, hotSpot, cursorMode);
    14.                 //Debug.Log("Monster here");
    15.             }
    16.             else if (hit2.transform.tag == "Npc")
    17.             {
    18.                 HoverOverActive = true;
    19.                 Cursor.SetCursor(NPCcursor, hotSpot, cursorMode);
    20.                 //Debug.Log("Npc here");
    21.             }
    22.         }
    23.         else
    24.         {
    25.             HoverOverActive = false;
    26.             Cursor.SetCursor(null, Vector2.zero, cursorMode);
    27.             //Debug.Log("Normal");
    28.         }
    29.     }
    30.  
    and lastly head over to
    Code (CSharp):
    1. //Then add  HoverCursor();
    2. if (isLocalPlayer) {
    3.                 // simply accept input
    4.                 SelectionHandling();
    5.                 WSADHandling();
    6.                 HoverCursor();


    The HoverOverActive can be taken away if you'd like to but I'm going to use it later for highlightning purpose so I though let's leave it in there!

    Now head over to your Player Prefab and you will find

    Make sure you change the texture on the hover over texture

    If you do want to change the default cursor go to Edit > Project Settings and locate

    Now it should look like this!



    You can not learn blueprints, but you can make a normal item called "axe recipe" then include it in the combination such as "Axe recipe + lumber + stone" but the recipe would be consumed.
    It currently goes into first person mode when active distance is less than 2 and you can add conditions to it :)
     
    Last edited: Jan 30, 2017
    mischa2k likes this.
  46. GOLDY00

    GOLDY00

    Joined:
    Mar 16, 2013
    Posts:
    139
    Ok so you can't change the ui to show the recipe
     
  47. MHolmstrom

    MHolmstrom

    Joined:
    Aug 16, 2012
    Posts:
    115
    You can change the UI Panel :)
    That's as good as it gets for now.
     
    GOLDY00 likes this.
  48. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    Good morning everyone, working on the 5.5.1 upgrade today!

    Cool, I added a link in the documentation!
     
    MHolmstrom likes this.
  49. Ronith

    Ronith

    Joined:
    Feb 20, 2014
    Posts:
    69
    Question:
    is it possible to make a skill depending a different weapon?

    example:
    small gun uses "attack" and "precise shot"
    big gun uses "heavy AOE" (and a equipped big gun is required)


    of course, its possible... but is there a easy way realise that?
     
  50. cioa00

    cioa00

    Joined:
    May 31, 2016
    Posts:
    203
    If you mean like one skill = one weapon, then you could try this way (p.s. this is idea and i haven't done any full test).

    Code (CSharp):
    1. // open file Scripts\SkillTemplate.cs
    2. // add before defining SkillLevel
    3.     public ItemTemplate useItem;
    Now you can drag weapon skill template to that field throught editor.

    Code (CSharp):
    1. // open file Scripts\Skill.cs
    2. // add before method Tooltip
    3.     public string useItem {
    4.         get { return template.useItem != null ? template.useItem.name : ""; }
    5.     }
    Code (CSharp):
    1. // open file Scripts\Player.cs
    2. // find CastSkill(skill);
    3. // and wrap this function call with if condition
    4. // so it looks like
    5. if(GetEquipmentIndexByName(skill.useItem) != -1){
    6.                 CastSkill(skill);
    7.             }
    8.  
    9.  
     
    Sarrivin, mischa2k and Ronith like this.