Fix the Artisan Upgrade (without anim lvl 11 and 12), improve the inventory check and consumable materials.
This commit is contained in:
parent
9c3ae670b6
commit
4adf4a86b5
@ -8,7 +8,7 @@
|
||||
| | `add` | `!account add test@ 12345678 test` | Allows you to add a new user account |
|
||||
| | `setpassword` | `!account setpassword test@ 12345678` | Allows you to set a new password for account |
|
||||
| | `setbtag` | `!account setbtag test@ NonTest` | Allows you to change battle tag for account |
|
||||
| | `setuserlevel` | `!account setuserlevel admin test@` | Allows you to set a new user level for account |
|
||||
| | `setuserlevel` | `!account setuserlevel test@ admin` | Allows you to set a new user level for account |
|
||||
| Mute Command | `mute` | `!mute test@` | Disable chat functions for user |
|
||||
|
||||
## Game Commands
|
||||
|
||||
@ -856,7 +856,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ItemsSystem
|
||||
Destroy();
|
||||
break;
|
||||
|
||||
case ActorSno._crafting_looted_reagent_05: //Death's Breath
|
||||
case ActorSno._crafting_looted_reagent_05: //Death's Breath GBID? 2087837753
|
||||
playerAcc.CraftItem4++;
|
||||
Destroy();
|
||||
break;
|
||||
|
||||
@ -10,24 +10,34 @@ namespace DiIiS_NA.D3_GameServer.GSSystem.PlayerSystem
|
||||
{
|
||||
private const int maxLevel = 12;
|
||||
private static readonly ArtisanType[] canBeTrained = new[] { ArtisanType.Blacksmith, ArtisanType.Jeweler, ArtisanType.Mystic };
|
||||
|
||||
private static readonly Dictionary<ArtisanType, string> recipeTemplates = new()
|
||||
{
|
||||
[ArtisanType.Blacksmith] = "BlackSmith_Train_Level{0}",
|
||||
[ArtisanType.Jeweler] = "Jeweler_Train_Level{0}",
|
||||
[ArtisanType.Mystic] = "Mystic_Train_Level{0}"
|
||||
};
|
||||
|
||||
private static readonly Dictionary<ArtisanType, long[]> achievements = new()
|
||||
{
|
||||
[ArtisanType.Blacksmith] = new[] { 74987243307767, 74987243307768, 74987243307769, 74987251817289 },
|
||||
[ArtisanType.Jeweler] = new[] { 74987243307781, 74987243307782, 74987243307783, 74987257153995 },
|
||||
[ArtisanType.Mystic] = new[] { 74987253584575, 74987256660015, 74987248802163, 74987251397159 }
|
||||
};
|
||||
|
||||
private static readonly Dictionary<ArtisanType, long> criteriaForLevel10 = new()
|
||||
{
|
||||
[ArtisanType.Blacksmith] = 74987249071497,
|
||||
[ArtisanType.Jeweler] = 74987245845978,
|
||||
[ArtisanType.Mystic] = 74987259424359
|
||||
};
|
||||
|
||||
// To'do it's necessary to get the correct Animation for Lvl 11 and 12.
|
||||
// For now I'm just using the Lvl 10 Animation.
|
||||
// fixme no animation level 11
|
||||
// 0x00011600,
|
||||
// fixme no animation level 12
|
||||
// 0x00011610,
|
||||
private static readonly int[] animationTags = new[] {
|
||||
0x00011500,
|
||||
0x00011510,
|
||||
@ -38,12 +48,15 @@ namespace DiIiS_NA.D3_GameServer.GSSystem.PlayerSystem
|
||||
0x00011560,
|
||||
0x00011570,
|
||||
0x00011580,
|
||||
0x00011590,
|
||||
// fixme no animation
|
||||
0x00011600,
|
||||
// fixme no animation
|
||||
0x00011610,
|
||||
0x00011590
|
||||
};
|
||||
|
||||
// To'do it's necessary to get the correct Animation for Lvl 11 and 12.
|
||||
// For now I'm just using the Lvl 10 Animation.
|
||||
// fixme no animation level 11
|
||||
// 0x00011310,
|
||||
// fixme no animation level 12
|
||||
// 0x00011320
|
||||
private static readonly int[] idleAnimationTags = new[] {
|
||||
0x00011210,
|
||||
0x00011220,
|
||||
@ -54,22 +67,20 @@ namespace DiIiS_NA.D3_GameServer.GSSystem.PlayerSystem
|
||||
0x00011270,
|
||||
0x00011280,
|
||||
0x00011290,
|
||||
0x00011300,
|
||||
// fixme no animation
|
||||
0x00011310,
|
||||
// fixme no animation
|
||||
0x00011320
|
||||
0x00011300
|
||||
};
|
||||
|
||||
|
||||
private readonly ArtisanType artisanType;
|
||||
|
||||
internal ArtisanTrainHelper(DBCraft dBCraft, ArtisanType type)
|
||||
{
|
||||
if (!canBeTrained.Contains(type))
|
||||
throw new ArgumentException("Unsupported artisan type", nameof(type));
|
||||
|
||||
DbRef = dBCraft ?? throw new ArgumentNullException(nameof(dBCraft));
|
||||
artisanType = type;
|
||||
}
|
||||
|
||||
internal DBCraft DbRef { get; }
|
||||
|
||||
internal string TrainRecipeName => string.Format(recipeTemplates[artisanType], Math.Min(DbRef.Level, maxLevel - 1));
|
||||
@ -85,8 +96,27 @@ namespace DiIiS_NA.D3_GameServer.GSSystem.PlayerSystem
|
||||
|
||||
internal ulong? Criteria => DbRef.Level == 10 ? (ulong)criteriaForLevel10[artisanType] : null;
|
||||
|
||||
internal int AnimationTag => animationTags[DbRef.Level - 1];
|
||||
internal int IdleAnimationTag => idleAnimationTags[DbRef.Level - 1];
|
||||
internal int AnimationTag
|
||||
{
|
||||
get
|
||||
{
|
||||
if (DbRef.Level >= 10)
|
||||
return animationTags[9]; // Force to use the LVL 10 Animation.
|
||||
|
||||
return animationTags[DbRef.Level - 1];
|
||||
}
|
||||
}
|
||||
|
||||
internal int IdleAnimationTag
|
||||
{
|
||||
get
|
||||
{
|
||||
if (DbRef.Level >= 10)
|
||||
return idleAnimationTags[9]; // Force to use the LVL 10 Idle Animation.
|
||||
|
||||
return idleAnimationTags[DbRef.Level - 1];
|
||||
}
|
||||
}
|
||||
|
||||
internal int Type => Array.IndexOf(canBeTrained, artisanType);
|
||||
}
|
||||
|
||||
@ -1,28 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using DiIiS_NA.Core.Logging;
|
||||
using DiIiS_NA.Core.Extensions;
|
||||
using DiIiS_NA.Core.Helpers.Math;
|
||||
using DiIiS_NA.Core.Storage.AccountDataBase.Entities;
|
||||
using DiIiS_NA.Core.Logging;
|
||||
using DiIiS_NA.Core.MPQ;
|
||||
using DiIiS_NA.Core.MPQ.FileFormats;
|
||||
using DiIiS_NA.Core.Storage.AccountDataBase.Entities;
|
||||
using DiIiS_NA.GameServer.ClientSystem;
|
||||
using DiIiS_NA.GameServer.Core;
|
||||
using DiIiS_NA.GameServer.Core.Types.SNO;
|
||||
using DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations;
|
||||
using DiIiS_NA.GameServer.GSSystem.ItemsSystem;
|
||||
using DiIiS_NA.GameServer.GSSystem.ObjectsSystem;
|
||||
using DiIiS_NA.GameServer.GSSystem.PlayerSystem;
|
||||
using DiIiS_NA.GameServer.MessageSystem;
|
||||
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Inventory;
|
||||
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.ACD;
|
||||
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Artisan;
|
||||
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Misc;
|
||||
using DiIiS_NA.GameServer.GSSystem.ObjectsSystem;
|
||||
using DiIiS_NA.GameServer.Core;
|
||||
using DiIiS_NA.GameServer.MessageSystem.Message.Fields;
|
||||
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Effect;
|
||||
using DiIiS_NA.GameServer.ClientSystem;
|
||||
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Base;
|
||||
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Effect;
|
||||
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Inventory;
|
||||
using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Misc;
|
||||
using DiIiS_NA.GameServer.MessageSystem.Message.Fields;
|
||||
using DiIiS_NA.LoginServer.AccountsSystem;
|
||||
using Discord;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using static DiIiS_NA.Core.MPQ.FileFormats.GameBalance;
|
||||
using DiIiS_NA.Core.Extensions;
|
||||
|
||||
namespace DiIiS_NA.GameServer.GSSystem.PlayerSystem
|
||||
{
|
||||
@ -98,21 +102,29 @@ namespace DiIiS_NA.GameServer.GSSystem.PlayerSystem
|
||||
return _buybackGrid;
|
||||
}
|
||||
|
||||
public bool HaveEnough(int GBid, int count)
|
||||
public bool HaveEnough(int gBid, int count, Player? player = null)
|
||||
{
|
||||
return (_inventoryGrid.TotalItemCount(GBid) + _stashGrid.TotalItemCount(GBid)) >= count;
|
||||
// 2087837753 = Death's Breath -> AKA: CraftItem4 _crafting_looted_reagent_05.
|
||||
if (player != null && gBid == 2087837753)
|
||||
{
|
||||
var playerAcc = player.InGameClient.BnetClient.Account.GameAccount;
|
||||
return playerAcc.CraftItem4 > count;
|
||||
}
|
||||
|
||||
return (_inventoryGrid.TotalItemCount(gBid) + _stashGrid.TotalItemCount(gBid)) >= count;
|
||||
}
|
||||
|
||||
public void GrabSomeItems(int GBid, int count)
|
||||
public void GrabSomeItems(int gBid, int count)
|
||||
{
|
||||
if (_inventoryGrid.HaveEnough(GBid, count))
|
||||
_inventoryGrid.GrabSomeItems(GBid, count);
|
||||
|
||||
if (_inventoryGrid.HaveEnough(gBid, count))
|
||||
_inventoryGrid.GrabSomeItems(gBid, count);
|
||||
else
|
||||
{
|
||||
int inBag = _inventoryGrid.TotalItemCount(GBid);
|
||||
_inventoryGrid.GrabSomeItems(GBid, inBag);
|
||||
int inBag = _inventoryGrid.TotalItemCount(gBid);
|
||||
_inventoryGrid.GrabSomeItems(gBid, inBag);
|
||||
count -= inBag;
|
||||
_stashGrid.GrabSomeItems(GBid, count);
|
||||
_stashGrid.GrabSomeItems(gBid, count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2938,31 +2938,51 @@ public class Player : Actor, IMessageConsumer, IUpdateable
|
||||
return;
|
||||
|
||||
var recipeDefinition = ItemGenerator.GetRecipeDefinition(trainHelper.TrainRecipeName);
|
||||
|
||||
// 1) Validade the Gold.
|
||||
if (Inventory.GetGoldAmount() < recipeDefinition.Gold)
|
||||
return;
|
||||
|
||||
var requiredIngridients = recipeDefinition.Ingredients.Where(x => x.ItemsGBID > 0);
|
||||
// FIXME: Inventory.HaveEnough doesn't work for some craft consumables
|
||||
var haveEnoughIngredients = requiredIngridients.All(x => Inventory.HaveEnough(x.ItemsGBID, x.Count));
|
||||
if (!haveEnoughIngredients)
|
||||
return;
|
||||
// 2) Extract only valid ingredients (actual items).
|
||||
var requiredIngredients = recipeDefinition.Ingredients
|
||||
.Where(x => x.ItemsGBID > 0 && x.Count > 0)
|
||||
.ToList();
|
||||
|
||||
// 3) If the recipe requires items, validate whether they exist in the Inventory.
|
||||
if (requiredIngredients.Any())
|
||||
{
|
||||
|
||||
var haveEnoughIngredients = requiredIngredients
|
||||
.All(x => Inventory.HaveEnough(x.ItemsGBID, x.Count, this));
|
||||
|
||||
if (!haveEnoughIngredients)
|
||||
return;
|
||||
|
||||
var playerAcc = this.InGameClient.BnetClient.Account.GameAccount;
|
||||
|
||||
// We already know that Artisan training is just consume Death's breath.
|
||||
playerAcc.CraftItem4--;
|
||||
|
||||
}
|
||||
|
||||
// 4) Always discount Gold (all recipes have a gold cost).
|
||||
Inventory.RemoveGoldAmount(recipeDefinition.Gold);
|
||||
foreach (var ingr in requiredIngridients)
|
||||
// FIXME: Inventory.GrabSomeItems doesn't work for some craft consumables
|
||||
Inventory.GrabSomeItems(ingr.ItemsGBID, ingr.Count);
|
||||
|
||||
// 5) Advance the artisan's level.
|
||||
trainHelper.DbRef.Level++;
|
||||
World.Game.GameDbSession.SessionUpdate(trainHelper.DbRef);
|
||||
|
||||
// 6) Related achievements & criteria.
|
||||
if (trainHelper.Achievement is not null)
|
||||
GrantAchievement(trainHelper.Achievement.Value);
|
||||
|
||||
if (trainHelper.Criteria is not null)
|
||||
GrantCriteria(trainHelper.Criteria.Value);
|
||||
|
||||
if (_artisanTrainHelpers.All(x => x.Value.HasMaxLevel))
|
||||
GrantCriteria(74987249993545);
|
||||
|
||||
// 7) Notify the Client.
|
||||
client.SendMessage(new CrafterLevelUpMessage
|
||||
{
|
||||
Type = trainHelper.Type,
|
||||
@ -2972,9 +2992,6 @@ public class Player : Actor, IMessageConsumer, IUpdateable
|
||||
});
|
||||
|
||||
LoadCrafterData();
|
||||
|
||||
|
||||
/**/
|
||||
}
|
||||
|
||||
public void UnlockTransmog(int transmogGBID)
|
||||
|
||||
Loading…
Reference in New Issue
user.block.title