/// <summary> /// This will be called at server to order character to unequip equipments /// </summary> /// <param name="fromEquipPosition"></param> protected virtual void NetFuncUnEquipItem(byte byteInventoryType, short index) { if (!CanDoActions()) { return; } EquipWeapons tempEquipWeapons = EquipWeapons; CharacterItem unEquipItem = CharacterItem.Empty; switch ((InventoryType)byteInventoryType) { case InventoryType.EquipWeaponRight: unEquipItem = tempEquipWeapons.rightHand; tempEquipWeapons.rightHand = CharacterItem.Empty; EquipWeapons = tempEquipWeapons; break; case InventoryType.EquipWeaponLeft: unEquipItem = tempEquipWeapons.leftHand; tempEquipWeapons.leftHand = CharacterItem.Empty; EquipWeapons = tempEquipWeapons; break; case InventoryType.EquipItems: unEquipItem = equipItems[index]; equipItems.RemoveAt(index); UpdateEquipItemIndexes(); break; } if (unEquipItem.NotEmptySlot()) { nonEquipItems.Add(unEquipItem); } }
protected virtual void NetFuncSellItem(short index, short amount) { if (IsDead() || index >= nonEquipItems.Count) { return; } if (currentNpcDialog == null || currentNpcDialog.type != NpcDialogType.Shop) { return; } CharacterItem nonEquipItem = nonEquipItems[index]; if (!nonEquipItem.NotEmptySlot() || amount > nonEquipItem.amount) { return; } Item item = nonEquipItem.GetItem(); if (this.DecreaseItemsByIndex(index, amount)) { gameplayRule.IncreaseCurrenciesWhenSellItem(this, item, amount); } }
protected virtual void NetFuncSwapOrMergeNonEquipItems(short index1, short index2) { if (!CanDoActions() || index1 >= nonEquipItems.Count || index2 >= nonEquipItems.Count) { return; } CharacterItem nonEquipItem1 = nonEquipItems[index1]; CharacterItem nonEquipItem2 = nonEquipItems[index2]; if (nonEquipItem1.dataId == nonEquipItem2.dataId && nonEquipItem1.NotEmptySlot() && nonEquipItem2.NotEmptySlot()) { // Merge or swap if (nonEquipItem1.IsFull() || nonEquipItem2.IsFull()) { // Swap NetFuncSwapNonEquipItems(index1, index2); } else { // Merge NetFuncMergeNonEquipItems(index1, index2); } } else { // Swap NetFuncSwapNonEquipItems(index1, index2); } }
private static void RepairItem(IPlayerCharacterData character, CharacterItem repairingItem, System.Action <CharacterItem> onRepaired, out GameMessage.Type gameMessageType) { gameMessageType = GameMessage.Type.CannotRepair; if (!repairingItem.NotEmptySlot()) { // Cannot refine because character item is empty return; } Item equipmentItem = repairingItem.GetEquipmentItem(); if (equipmentItem == null) { // Cannot refine because it's not equipment item return; } ItemRepairPrice repairPrice; if (equipmentItem.CanRepair(character, repairingItem.durability, out repairPrice, out gameMessageType)) { gameMessageType = GameMessage.Type.RepairSuccess; // Repair item repairingItem.durability = equipmentItem.maxDurability; onRepaired.Invoke(repairingItem); // Decrease required gold GameInstance.Singleton.GameplayRule.DecreaseCurrenciesWhenRepairItem(character, repairPrice); } }
protected virtual void NetFuncSwapOrMergeItem(short fromIndex, short toIndex) { if (!CanDoActions() || fromIndex >= NonEquipItems.Count || toIndex >= NonEquipItems.Count) { return; } CharacterItem fromItem = NonEquipItems[fromIndex]; CharacterItem toItem = NonEquipItems[toIndex]; if (!fromItem.NotEmptySlot() || !toItem.NotEmptySlot()) { return; } if (fromItem.dataId.Equals(toItem.dataId) && !fromItem.IsFull() && !toItem.IsFull()) { // Merge if same id and not full short maxStack = toItem.GetMaxStack(); if (toItem.amount + fromItem.amount <= maxStack) { toItem.amount += fromItem.amount; NonEquipItems[fromIndex] = CharacterItem.Empty; NonEquipItems[toIndex] = toItem; } else { short remains = (short)(toItem.amount + fromItem.amount - maxStack); toItem.amount = maxStack; fromItem.amount = remains; NonEquipItems[fromIndex] = fromItem; NonEquipItems[toIndex] = toItem; } } else { // Swap NonEquipItems[fromIndex] = toItem; NonEquipItems[toIndex] = fromItem; } }
private static void EnhanceSocketItem(IPlayerCharacterData character, CharacterItem enhancingItem, int enhancerId, System.Action <CharacterItem> onEnhanceSocket, out GameMessage.Type gameMessageType) { gameMessageType = GameMessage.Type.CannotEnhanceSocket; if (!enhancingItem.NotEmptySlot()) { // Cannot enhance socket because character item is empty return; } Item equipmentItem = enhancingItem.GetEquipmentItem(); if (equipmentItem == null) { // Cannot enhance socket because it's not equipment item return; } if (equipmentItem.maxSocket <= 0) { // Cannot enhance socket because equipment has no socket(s) return; } if (enhancingItem.Sockets.Count >= equipmentItem.maxSocket) { // Cannot enhance socket because socket is full return; } Item enhancerItem; if (!GameInstance.Items.TryGetValue(enhancerId, out enhancerItem) || !enhancerItem.IsSocketEnhancer()) { // Cannot enhance socket because enhancer id is invalid return; } if (!character.DecreaseItems(enhancerItem.DataId, 1)) { // Cannot enhance socket because there is no item gameMessageType = GameMessage.Type.NotEnoughSocketEnchaner; return; } enhancingItem.Sockets.Add(enhancerId); onEnhanceSocket.Invoke(enhancingItem); }
/// <summary> /// This will be called at server to order character to pickup items /// </summary> /// <param name="objectId"></param> protected virtual void NetFuncPickupItem(PackedUInt objectId) { if (!CanDoActions()) { return; } ItemDropEntity itemDropEntity = null; if (!TryGetEntityByObjectId(objectId, out itemDropEntity)) { return; } if (Vector3.Distance(CacheTransform.position, itemDropEntity.CacheTransform.position) > gameInstance.pickUpItemDistance + 5f) { return; } if (!itemDropEntity.IsAbleToLoot(this)) { gameManager.SendServerGameMessage(ConnectionId, GameMessage.Type.NotAbleToLoot); return; } CharacterItem itemDropData = itemDropEntity.dropData; if (!itemDropData.NotEmptySlot()) { // Destroy item drop entity without item add because this is not valid itemDropEntity.MarkAsPickedUp(); itemDropEntity.NetworkDestroy(); return; } if (!this.IncreasingItemsWillOverwhelming(itemDropData.dataId, itemDropData.amount) && this.IncreaseItems(itemDropData)) { itemDropEntity.MarkAsPickedUp(); itemDropEntity.NetworkDestroy(); } }
protected virtual void NetFuncBuild(short itemIndex, Vector3 position, Quaternion rotation, PackedUInt parentObjectId) { if (!CanDoActions() || itemIndex >= NonEquipItems.Count) { return; } BuildingEntity buildingEntity; CharacterItem nonEquipItem = NonEquipItems[itemIndex]; if (!nonEquipItem.NotEmptySlot() || nonEquipItem.GetBuildingItem() == null || nonEquipItem.GetBuildingItem().buildingEntity == null || !GameInstance.BuildingEntities.TryGetValue(nonEquipItem.GetBuildingItem().buildingEntity.DataId, out buildingEntity) || !this.DecreaseItemsByIndex(itemIndex, 1)) { return; } BuildingSaveData buildingSaveData = new BuildingSaveData(); buildingSaveData.Id = GenericUtils.GetUniqueId(); buildingSaveData.ParentId = string.Empty; BuildingEntity parentBuildingEntity; if (TryGetEntityByObjectId(parentObjectId, out parentBuildingEntity)) { buildingSaveData.ParentId = parentBuildingEntity.Id; } buildingSaveData.DataId = buildingEntity.DataId; buildingSaveData.CurrentHp = buildingEntity.maxHp; buildingSaveData.Position = position; buildingSaveData.Rotation = rotation; buildingSaveData.CreatorId = Id; buildingSaveData.CreatorName = CharacterName; gameManager.CreateBuildingEntity(buildingSaveData, false); }
public static bool DecreaseItemsByIndex(IList <CharacterItem> itemList, int index, short amount) { if (index < 0 || index >= itemList.Count) { return(false); } CharacterItem nonEquipItem = itemList[index]; if (!nonEquipItem.NotEmptySlot() || amount > nonEquipItem.amount) { return(false); } if (nonEquipItem.amount - amount == 0) { itemList.RemoveAt(index); } else { nonEquipItem.amount -= amount; itemList[index] = nonEquipItem; } return(true); }
/// <summary> /// This will be called at server to order character to drop items /// </summary> /// <param name="index"></param> /// <param name="amount"></param> protected virtual void NetFuncDropItem(short index, short amount) { if (!CanDoActions() || index >= nonEquipItems.Count) { return; } CharacterItem nonEquipItem = nonEquipItems[index]; if (!nonEquipItem.NotEmptySlot() || amount > nonEquipItem.amount) { return; } if (this.DecreaseItemsByIndex(index, amount)) { // Drop item to the ground CharacterItem dropData = nonEquipItem.Clone(); dropData.amount = amount; ItemDropEntity.DropItem(this, dropData, new uint[] { ObjectId }); } }
public static bool IncreaseItems(IList <CharacterItem> itemList, CharacterItem addingItem) { // If item not valid if (!addingItem.NotEmptySlot()) { return(false); } Item itemData = addingItem.GetItem(); short amount = addingItem.amount; short maxStack = itemData.maxStack; Dictionary <int, CharacterItem> emptySlots = new Dictionary <int, CharacterItem>(); Dictionary <int, CharacterItem> changes = new Dictionary <int, CharacterItem>(); // Loop to all slots to add amount to any slots that item amount not max in stack CharacterItem tempNonEquipItem; for (int i = 0; i < itemList.Count; ++i) { tempNonEquipItem = itemList[i]; if (!tempNonEquipItem.NotEmptySlot()) { // If current entry is not valid, add it to empty list, going to replacing it later emptySlots[i] = tempNonEquipItem; } else if (tempNonEquipItem.dataId == addingItem.dataId) { // If same item id, increase its amount if (tempNonEquipItem.amount + amount <= maxStack) { tempNonEquipItem.amount += amount; changes[i] = tempNonEquipItem; amount = 0; break; } else if (maxStack - tempNonEquipItem.amount >= 0) { amount -= (short)(maxStack - tempNonEquipItem.amount); tempNonEquipItem.amount = maxStack; changes[i] = tempNonEquipItem; } } } // Adding item to new slots or empty slots if needed CharacterItem tempNewItem; if (changes.Count == 0 && emptySlots.Count > 0) { // If there are no changes and there are an empty entries, fill them foreach (int emptySlotIndex in emptySlots.Keys) { tempNewItem = addingItem.Clone(); short addAmount = 0; if (amount - maxStack >= 0) { addAmount = maxStack; amount -= maxStack; } else { addAmount = amount; amount = 0; } tempNewItem.amount = addAmount; changes[emptySlotIndex] = tempNewItem; if (amount == 0) { break; } } } // Apply all changes foreach (KeyValuePair <int, CharacterItem> change in changes) { itemList[change.Key] = change.Value; } // Add new items to new slots while (amount > 0) { tempNewItem = addingItem.Clone(); short addAmount = 0; if (amount - maxStack >= 0) { addAmount = maxStack; amount -= maxStack; } else { addAmount = amount; amount = 0; } tempNewItem.amount = addAmount; itemList.Add(tempNewItem); if (amount == 0) { break; } } return(true); }
private static void RefineItem(IPlayerCharacterData character, CharacterItem refiningItem, System.Action <CharacterItem> onRefine, System.Action onDestroy, out GameMessage.Type gameMessageType) { gameMessageType = GameMessage.Type.CannotRefine; if (!refiningItem.NotEmptySlot()) { // Cannot refine because character item is empty return; } Item equipmentItem = refiningItem.GetEquipmentItem(); if (equipmentItem == null) { // Cannot refine because it's not equipment item return; } if (!equipmentItem.CanRefine(character, refiningItem.level, out gameMessageType)) { // Cannot refine because of some reasons return; } ItemRefineLevel refineLevel = equipmentItem.itemRefine.levels[refiningItem.level - 1]; if (Random.value <= refineLevel.SuccessRate) { // If success, increase item level gameMessageType = GameMessage.Type.RefineSuccess; ++refiningItem.level; onRefine.Invoke(refiningItem); } else { // Fail gameMessageType = GameMessage.Type.RefineFail; if (refineLevel.RefineFailDestroyItem) { // If condition when fail is it has to be destroyed onDestroy.Invoke(); } else { // If condition when fail is reduce its level refiningItem.level -= refineLevel.RefineFailDecreaseLevels; if (refiningItem.level < 1) { refiningItem.level = 1; } onRefine.Invoke(refiningItem); } } if (refineLevel.RequireItems != null) { // Decrease required items foreach (ItemAmount requireItem in refineLevel.RequireItems) { if (requireItem.item != null && requireItem.amount > 0) { character.DecreaseItems(requireItem.item.DataId, requireItem.amount); } } } // Decrease required gold GameInstance.Singleton.GameplayRule.DecreaseCurrenciesWhenRefineItem(character, refineLevel); }
public static T ValidateCharacterData <T>(this T character) where T : IPlayerCharacterData { GameInstance gameInstance = GameInstance.Singleton; PlayerCharacter database; if (!GameInstance.PlayerCharacters.TryGetValue(character.DataId, out database)) { return(character); } // Validating character attributes short returningStatPoint = 0; HashSet <int> validAttributeIds = new HashSet <int>(); IList <CharacterAttribute> characterAttributes = character.Attributes; for (int i = characterAttributes.Count - 1; i >= 0; --i) { CharacterAttribute characterAttribute = characterAttributes[i]; int attributeDataId = characterAttribute.dataId; // If attribute is invalid if (characterAttribute.GetAttribute() == null || validAttributeIds.Contains(attributeDataId)) { returningStatPoint += characterAttribute.amount; character.Attributes.RemoveAt(i); } else { validAttributeIds.Add(attributeDataId); } } character.StatPoint += returningStatPoint; // Add character's attributes foreach (Attribute attribute in GameInstance.Attributes.Values) { // This attribute is valid, so not have to add it if (validAttributeIds.Contains(attribute.DataId)) { continue; } CharacterAttribute characterAttribute = new CharacterAttribute(); characterAttribute.dataId = attribute.DataId; characterAttribute.amount = 0; character.Attributes.Add(characterAttribute); } // Validating character skills short returningSkillPoint = 0; HashSet <int> validSkillIds = new HashSet <int>(); IList <CharacterSkill> characterSkills = character.Skills; for (int i = characterSkills.Count - 1; i >= 0; --i) { CharacterSkill characterSkill = characterSkills[i]; Skill skill = characterSkill.GetSkill(); // If skill is invalid or this character database does not have skill if (characterSkill.GetSkill() == null || !database.CacheSkillLevels.ContainsKey(skill) || validSkillIds.Contains(skill.DataId)) { returningSkillPoint += characterSkill.level; character.Skills.RemoveAt(i); } else { validSkillIds.Add(skill.DataId); } } character.SkillPoint += returningSkillPoint; // Add character's skills Dictionary <Skill, short> skillLevels = database.CacheSkillLevels; foreach (KeyValuePair <Skill, short> skillLevel in skillLevels) { Skill skill = skillLevel.Key; // This skill is valid, so not have to add it if (validSkillIds.Contains(skill.DataId)) { continue; } CharacterSkill characterSkill = new CharacterSkill(); characterSkill.dataId = skill.DataId; characterSkill.level = skillLevel.Value; character.Skills.Add(characterSkill); } // Validating character equip weapons List <CharacterItem> returningItems = new List <CharacterItem>(); EquipWeapons equipWeapons = character.EquipWeapons; CharacterItem rightHand = equipWeapons.rightHand; CharacterItem leftHand = equipWeapons.leftHand; if (rightHand.GetEquipmentItem() == null) { if (rightHand.NotEmptySlot()) { returningItems.Add(rightHand); } equipWeapons.rightHand = CharacterItem.Empty; } if (leftHand.GetEquipmentItem() == null) { if (leftHand.NotEmptySlot()) { returningItems.Add(leftHand); } equipWeapons.leftHand = CharacterItem.Empty; } // Validating character equip items IList <CharacterItem> equipItems = character.EquipItems; for (int i = equipItems.Count - 1; i >= 0; --i) { CharacterItem equipItem = equipItems[i]; // If equipment is invalid if (equipItem.GetEquipmentItem() == null) { if (equipItem.NotEmptySlot()) { returningItems.Add(equipItem); } character.EquipItems.RemoveAt(i); } } // Return items to non equip items foreach (CharacterItem returningItem in returningItems) { character.NonEquipItems.Add(returningItem); } character.FillEmptySlots(); DevExtUtils.InvokeStaticDevExtMethods(ClassType, "ValidateCharacterData", character); return(character); }