fix: Updates professions & new player gargish equipment (#819)

* Now reads Prof.txt to get the professions
* The templated professions are based on profession `TrueName`
* Adds missing starting equipment
* Implements gargish starting equipment
* Consolidates some of the code
* Moves TC stuff to the TC file.
* Fixes some starting equipment that was wrong.

Note:
* Implementing the original T2A professions is possible on the client side, but requires moving the old clilocs to the current clilocs file. In the current file the entries are blank.
* Using the original LBR professions (they match AOS but without necromancy/chivalry) is kind of confusing because the profession indexes are ripped out of the UOTD/UOR ones and have non-sequential indexes. This will probably cause confusion and people will get no templated items when they select the wrong profession.
This commit is contained in:
Kamron Batman 2021-10-16 10:48:58 -07:00 committed by GitHub
parent 7361c9158b
commit bfbe2a6512
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
80 changed files with 2654 additions and 1409 deletions

View file

@ -58,7 +58,7 @@
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" /> <PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" />
<PackageReference Include="Nerdbank.GitVersioning" Condition="!Exists('packages.config')"> <PackageReference Include="Nerdbank.GitVersioning" Condition="!Exists('packages.config')">
<Version>3.4.231</Version> <Version>3.4.240</Version>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<AdditionalFiles Include=".\Rules.ruleset" /> <AdditionalFiles Include=".\Rules.ruleset" />

View file

@ -0,0 +1,85 @@
Begin
Name Paladin
TrueName "Paladin"
NameId 1061177
DescId 1061227
Desc 5
TopLevel true
Gump 5587
Type Profession
Skill Chivalry 50
Skill Tactics 50
Skill Wrestling 0
Stat Str 30
Stat Dex 25
Stat Int 25
End
Begin
Name Necromancer
TrueName "Necromancer"
NameId 1061178
DescId 1061228
Desc 4
TopLevel true
Gump 5557
Type Profession
Skill Necromancy 50
Skill Swordsmanship 30
Skill Wrestling 0
Skill Tactics 20
Stat Str 25
Stat Dex 20
Stat Int 45
End
Begin
Name Warrior
TrueName "Warrior"
NameId 1061180
DescId 1061230
Desc 1
TopLevel true
Gump 5577
Type Profession
Skill Tactics 50
Skill Healing 45
Skill Swordsmanship 5
Stat Str 35
Stat Dex 35
Stat Int 10
End
Begin
Name Mage
TrueName "Mage"
NameId 1061179
DescId 1061229
Desc 2
TopLevel true
Gump 5569
Type Profession
Skill Magery 50
Skill Meditation 50
Skill Wrestling 0
Stat Str 25
Stat Dex 10
Stat Int 45
End
Begin
Name Blacksmith
TrueName "Blacksmith"
NameId 1061181
DescId 1061231
Desc 3
TopLevel true
Gump 5555
Type Profession
Skill Blacksmith 50
Skill Tinkering 45
Skill Mining 5
Stat Str 60
Stat Dex 10
Stat Int 10
End

View file

@ -0,0 +1,50 @@
Begin
Name Warrior
TrueName "Warrior"
NameId 1061180
DescId 1061230
Desc 1
TopLevel true
Gump 5577
Type Profession
Skill Tactics 50
Skill Healing 45
Skill Swordsmanship 5
Stat Str 35
Stat Dex 35
Stat Int 10
End
Begin
Name Mage
TrueName "Mage"
NameId 1061179
DescId 1061229
Desc 2
TopLevel true
Gump 5569
Type Profession
Skill Magery 50
Skill Meditation 50
Skill Wrestling 0
Stat Str 25
Stat Dex 10
Stat Int 45
End
Begin
Name Blacksmith
TrueName "Blacksmith"
NameId 1061181
DescId 1061231
Desc 3
TopLevel true
Gump 5555
Type Profession
Skill Blacksmith 50
Skill Tinkering 45
Skill Mining 5
Stat Str 60
Stat Dex 10
Stat Int 10
End

View file

@ -0,0 +1,125 @@
Begin
Name Samurai
TrueName "Samurai"
NameId 1062948
DescId 1062950
Desc 6
TopLevel true
Gump 5591
Type Profession
Skill Bushido 30
Skill Swordsmanship 30
Skill Focus 30
Skill Parrying 30
Stat Str 40
Stat Dex 30
Stat Int 20
End
Begin
Name Ninja
TrueName "Ninja"
NameId 1062949
DescId 1062951
Desc 7
TopLevel true
Gump 5589
Type Profession
Skill Ninjitsu 30
Skill Hiding 30
Skill Fencing 30
Skill Stealth 30
Stat Str 40
Stat Dex 30
Stat Int 20
End
Begin
Name Paladin
TrueName "Paladin"
NameId 1061177
DescId 1061227
Desc 5
TopLevel true
Gump 5587
Type Profession
Skill Chivalry 30
Skill Tactics 30
Skill Focus 30
Skill Swordsmanship 30
Stat Str 45
Stat Dex 20
Stat Int 25
End
Begin
Name Necromancer
TrueName "Necromancer"
NameId 1061178
DescId 1061228
Desc 4
TopLevel true
Gump 5557
Type Profession
Skill Necromancy 30
Skill Spirit Speak 30
Skill Swordsmanship 30
Skill Meditation 30
Stat Str 25
Stat Dex 20
Stat Int 45
End
Begin
Name Warrior
TrueName "Warrior"
NameId 1061180
DescId 1061230
Desc 1
TopLevel true
Gump 5577
Type Profession
Skill Tactics 30
Skill Healing 30
Skill Swordsmanship 30
Skill Anatomy 30
Stat Str 45
Stat Dex 35
Stat Int 10
End
Begin
Name Mage
TrueName "Mage"
NameId 1061179
DescId 1061229
Desc 2
TopLevel true
Gump 5569
Type Profession
Skill Magery 30
Skill Meditation 30
Skill Evaluate Intelligence 30
Skill Wrestling 30
Stat Str 25
Stat Dex 20
Stat Int 45
End
Begin
Name Blacksmith
TrueName "Blacksmith"
NameId 1061181
DescId 1061231
Desc 3
TopLevel true
Gump 5555
Type Profession
Skill Blacksmith 30
Skill Tinkering 30
Skill Mining 30
Skill Tailoring 30
Stat Str 60
Stat Dex 15
Stat Int 15
End

View file

@ -0,0 +1,118 @@
Begin
Name Samurai
TrueName "Samurai"
NameId 1062948
DescId 1062950
Desc 6
TopLevel true
Gump 5591
Type Profession
Skill Bushido 50
Skill Swordsmanship 50
Skill Wrestling 0
Stat Str 40
Stat Dex 30
Stat Int 10
End
Begin
Name Ninja
TrueName "Ninja"
NameId 1062949
DescId 1062951
Desc 7
TopLevel true
Gump 5589
Type Profession
Skill Ninjitsu 50
Skill Hiding 50
Skill Wrestling 0
Stat Str 40
Stat Dex 30
Stat Int 10
End
Begin
Name Paladin
TrueName "Paladin"
NameId 1061177
DescId 1061227
Desc 5
TopLevel true
Gump 5587
Type Profession
Skill Chivalry 50
Skill Tactics 50
Skill Wrestling 0
Stat Str 45
Stat Dex 20
Stat Int 15
End
Begin
Name Necromancer
TrueName "Necromancer"
NameId 1061178
DescId 1061228
Desc 4
TopLevel true
Gump 5557
Type Profession
Skill Necromancy 50
Skill Swordsmanship 30
Skill Tactics 20
Stat Str 25
Stat Dex 20
Stat Int 35
End
Begin
Name Warrior
TrueName "Warrior"
NameId 1061180
DescId 1061230
Desc 1
TopLevel true
Gump 5577
Type Profession
Skill Tactics 50
Skill Healing 45
Skill Swordsmanship 5
Stat Str 35
Stat Dex 35
Stat Int 10
End
Begin
Name Mage
TrueName "Mage"
NameId 1061179
DescId 1061229
Desc 2
TopLevel true
Gump 5569
Type Profession
Skill Magery 50
Skill Meditation 50
Skill Wrestling 0
Stat Str 25
Stat Dex 10
Stat Int 45
End
Begin
Name Blacksmith
TrueName "Blacksmith"
NameId 1061181
DescId 1061231
Desc 3
TopLevel true
Gump 5555
Type Profession
Skill Blacksmith 50
Skill Tinkering 45
Skill Mining 5
Stat Str 60
Stat Dex 10
Stat Int 10
End

View file

@ -0,0 +1,58 @@
Alchemy,
Anatomy,
AnimalLore,
ItemID,
ArmsLore,
Parrying,
Begging,
Blacksmith,
Bowcraft,
Peacemaking,
Camping,
Carpentry,
Cartography,
Cooking,
DetectHidden,
Enticement,
EvaluateIntelligence,
Healing,
Fishing,
ForensicEvaluation,
Herding,
Hiding,
Provocation,
Inscription,
Lockpicking,
Magery,
ResistingSpells,
Tactics,
Snooping,
Musicianship,
Poisoning,
Archery,
SpiritSpeak,
Stealing,
Tailoring,
AnimalTaming,
TasteIdentification,
Tinkering,
Tracking,
Veterinary,
Swordsmanship,
MaceFighting,
Fencing,
Wrestling,
Lumberjacking,
Mining,
Meditation,
Stealth,
Disarm,
Necromancy,
Focus,
Chivalry,
Bushido,
Ninjitsu,
Spellweaving,
Mysticism,
Imbuing,
Throwing

View file

@ -11,6 +11,9 @@
<ProjectReference Include="..\Server\Server.csproj" /> <ProjectReference Include="..\Server\Server.csproj" />
<ProjectReference Include="..\UOContent\UOContent.csproj" /> <ProjectReference Include="..\UOContent\UOContent.csproj" />
<DataFiles Include="$(SolutionDir)\Distribution\Data\**" /> <DataFiles Include="$(SolutionDir)\Distribution\Data\**" />
<DataFiles Update="..\..\Distribution\Data\Professions\LBR\prof.txt">
<Link>Data\Professions\LBR\prof.txt</Link>
</DataFiles>
</ItemGroup> </ItemGroup>
<Target Name="CopyData" AfterTargets="AfterBuild"> <Target Name="CopyData" AfterTargets="AfterBuild">
<Copy SourceFiles="@(DataFiles)" DestinationFolder="$(OutDir)\Data\%(RecursiveDir)" /> <Copy SourceFiles="@(DataFiles)" DestinationFolder="$(OutDir)\Data\%(RecursiveDir)" />

View file

@ -23,9 +23,9 @@ namespace Server
public class CharacterCreatedEventArgs public class CharacterCreatedEventArgs
{ {
public CharacterCreatedEventArgs( public CharacterCreatedEventArgs(
NetState state, IAccount a, string name, bool female, int hue, int str, int dex, NetState state, IAccount a, string name, bool female, int hue, StatNameValue[] stats, CityInfo city,
int intel, CityInfo city, SkillNameValue[] skills, int shirtHue, int pantsHue, int hairID, int hairHue, SkillNameValue[] skills, int shirtHue, int pantsHue, int hairID, int hairHue, int beardID, int beardHue,
int beardID, int beardHue, int profession, Race race int profession, Race race
) )
{ {
State = state; State = state;
@ -33,9 +33,7 @@ namespace Server
Name = name; Name = name;
Female = female; Female = female;
Hue = hue; Hue = hue;
Str = str; Stats = stats;
Dex = dex;
Int = intel;
City = city; City = city;
Skills = skills; Skills = skills;
ShirtHue = shirtHue; ShirtHue = shirtHue;
@ -60,11 +58,7 @@ namespace Server
public int Hue { get; } public int Hue { get; }
public int Str { get; } public StatNameValue[] Stats { get; }
public int Dex { get; }
public int Int { get; }
public CityInfo City { get; } public CityInfo City { get; }
@ -87,18 +81,8 @@ namespace Server
public Race Race { get; } public Race Race { get; }
} }
public struct SkillNameValue public readonly record struct SkillNameValue(SkillName Name, int Value);
{ public readonly record struct StatNameValue(StatType Name, int Value);
public SkillName Name { get; }
public int Value { get; }
public SkillNameValue(SkillName name, int value)
{
Name = name;
Value = value;
}
}
public static partial class EventSink public static partial class EventSink
{ {

View file

@ -158,6 +158,30 @@ namespace Server
public class ExpansionInfo public class ExpansionInfo
{ {
public static string GetEraFolder(string parentDirectory)
{
var expansion = Core.Expansion;
var folders = Directory.GetDirectories(
parentDirectory,
"*",
new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive }
);
while (expansion-- >= 0)
{
foreach (var folder in folders)
{
var di = new DirectoryInfo(folder);
if (di.Name.InsensitiveEquals(expansion.ToString()))
{
return folder;
}
}
}
return null;
}
static ExpansionInfo() static ExpansionInfo()
{ {
var path = Path.Combine(Core.BaseDirectory, "Data/expansion.json"); var path = Path.Combine(Core.BaseDirectory, "Data/expansion.json");

View file

@ -17,6 +17,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime; using System.Runtime;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -248,6 +249,17 @@ namespace Server
{ {
fullPath = Path.Combine(p, path); fullPath = Path.Combine(p, path);
if (IsLinux)
{
var fi = new FileInfo(fullPath);
fullPath = fi.Directory!.EnumerateFiles(
fi.Name,
new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive }
).FirstOrDefault()?.FullName;
break;
}
if (File.Exists(fullPath)) if (File.Exists(fullPath))
{ {
break; break;

View file

@ -160,6 +160,8 @@ namespace Server.Network
set => _packetEncoder = value; set => _packetEncoder = value;
} }
public int CurrentPacket { get; internal set; }
public bool SentFirstPacket { get; set; } public bool SentFirstPacket { get; set; }
public bool BlockAllPackets { get; set; } public bool BlockAllPackets { get; set; }

View file

@ -73,40 +73,20 @@ namespace Server.Network
int genderRace = reader.ReadByte(); int genderRace = reader.ReadByte();
int str = reader.ReadByte(); var stats = new StatNameValue[]
int dex = reader.ReadByte(); {
int intl = reader.ReadByte(); new(StatType.Str, reader.ReadByte()),
int is1 = reader.ReadByte(); new(StatType.Dex, reader.ReadByte()),
int vs1 = reader.ReadByte(); new(StatType.Int, reader.ReadByte())
int is2 = reader.ReadByte(); };
int vs2 = reader.ReadByte();
int is3 = reader.ReadByte();
int vs3 = reader.ReadByte();
SkillNameValue[] skills; var skills = new SkillNameValue[state.NewCharacterCreation ? 4 : 3];
skills[0] = new SkillNameValue((SkillName)reader.ReadByte(), reader.ReadByte());
// We have protocol changes by now, so this is ok skills[1] = new SkillNameValue((SkillName)reader.ReadByte(), reader.ReadByte());
skills[2] = new SkillNameValue((SkillName)reader.ReadByte(), reader.ReadByte());
if (state.NewCharacterCreation) if (state.NewCharacterCreation)
{ {
int is4 = reader.ReadByte(); skills[3] = new SkillNameValue((SkillName)reader.ReadByte(), reader.ReadByte());
int vs4 = reader.ReadByte();
skills = new[]
{
new SkillNameValue((SkillName)is1, vs1),
new SkillNameValue((SkillName)is2, vs2),
new SkillNameValue((SkillName)is3, vs3),
new SkillNameValue((SkillName)is4, vs4)
};
}
else
{
skills = new[]
{
new SkillNameValue((SkillName)is1, vs1),
new SkillNameValue((SkillName)is2, vs2),
new SkillNameValue((SkillName)is3, vs3)
};
} }
int hue = reader.ReadUInt16(); int hue = reader.ReadUInt16();
@ -171,9 +151,7 @@ namespace Server.Network
name, name,
female, female,
hue, hue,
str, stats,
dex,
intl,
info[cityIndex], info[cityIndex],
skills, skills,
shirtHue, shirtHue,

View file

@ -34,7 +34,7 @@
<Delete Files="..\..\Distribution\zlib.dll" ContinueOnError="true" /> <Delete Files="..\..\Distribution\zlib.dll" ContinueOnError="true" />
</Target> </Target>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.0.2" /> <PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.1.0" />
<PackageReference Include="PollGroup" Version="1.1.0" /> <PackageReference Include="PollGroup" Version="1.1.0" />
<PackageReference Include="Zlib.Bindings" Version="1.5.0" /> <PackageReference Include="Zlib.Bindings" Version="1.5.0" />
</ItemGroup> </ItemGroup>

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Server.Network; using Server.Network;
@ -384,7 +385,8 @@ namespace Server
{ {
public SkillInfo( public SkillInfo(
int skillID, string name, double strScale, double dexScale, double intScale, string title, int skillID, string name, double strScale, double dexScale, double intScale, string title,
SkillUseCallback callback, double strGain, double dexGain, double intGain, double gainFactor SkillUseCallback callback, double strGain, double dexGain, double intGain, double gainFactor,
string professionSkillName = null
) )
{ {
Name = name; Name = name;
@ -398,7 +400,7 @@ namespace Server
DexGain = dexGain; DexGain = dexGain;
IntGain = intGain; IntGain = intGain;
GainFactor = gainFactor; GainFactor = gainFactor;
ProfessionSkillName = professionSkillName ?? Name.Replace(" ", "");
StatTotal = strScale + dexScale + intScale; StatTotal = strScale + dexScale + intScale;
} }
@ -426,25 +428,27 @@ namespace Server
public double GainFactor { get; set; } public double GainFactor { get; set; }
public string ProfessionSkillName { get; set; }
public static SkillInfo[] Table { get; set; } = public static SkillInfo[] Table { get; set; } =
{ {
new(0, "Alchemy", 0.0, 5.0, 5.0, "Alchemist", null, 0.0, 0.5, 0.5, 1.0), new(0, "Alchemy", 0.0, 5.0, 5.0, "Alchemist", null, 0.0, 0.5, 0.5, 1.0),
new(1, "Anatomy", 0.0, 0.0, 0.0, "Biologist", null, 0.15, 0.15, 0.7, 1.0), new(1, "Anatomy", 0.0, 0.0, 0.0, "Biologist", null, 0.15, 0.15, 0.7, 1.0),
new(2, "Animal Lore", 0.0, 0.0, 0.0, "Naturalist", null, 0.0, 0.0, 1.0, 1.0), new(2, "Animal Lore", 0.0, 0.0, 0.0, "Naturalist", null, 0.0, 0.0, 1.0, 1.0),
new(3, "Item Identification", 0.0, 0.0, 0.0, "Merchant", null, 0.0, 0.0, 1.0, 1.0), new(3, "Item Identification", 0.0, 0.0, 0.0, "Merchant", null, 0.0, 0.0, 1.0, 1.0, "ItemID"),
new(4, "Arms Lore", 0.0, 0.0, 0.0, "Weapon Master", null, 0.75, 0.15, 0.1, 1.0), new(4, "Arms Lore", 0.0, 0.0, 0.0, "Weapon Master", null, 0.75, 0.15, 0.1, 1.0),
new(5, "Parrying", 7.5, 2.5, 0.0, "Duelist", null, 0.75, 0.25, 0.0, 1.0), new(5, "Parrying", 7.5, 2.5, 0.0, "Duelist", null, 0.75, 0.25, 0.0, 1.0),
new(6, "Begging", 0.0, 0.0, 0.0, "Beggar", null, 0.0, 0.0, 0.0, 1.0), new(6, "Begging", 0.0, 0.0, 0.0, "Beggar", null, 0.0, 0.0, 0.0, 1.0),
new(7, "Blacksmithy", 10.0, 0.0, 0.0, "Blacksmith", null, 1.0, 0.0, 0.0, 1.0), new(7, "Blacksmithy", 10.0, 0.0, 0.0, "Blacksmith", null, 1.0, 0.0, 0.0, 1.0, "Blacksmith"),
new(8, "Bowcraft/Fletching", 6.0, 16.0, 0.0, "Bowyer", null, 0.6, 1.6, 0.0, 1.0), new(8, "Bowcraft/Fletching", 6.0, 16.0, 0.0, "Bowyer", null, 0.6, 1.6, 0.0, 1.0, "Bowcraft"),
new(9, "Peacemaking", 0.0, 0.0, 0.0, "Pacifier", null, 0.0, 0.0, 0.0, 1.0), new(9, "Peacemaking", 0.0, 0.0, 0.0, "Pacifier", null, 0.0, 0.0, 0.0, 1.0),
new(10, "Camping", 20.0, 15.0, 15.0, "Explorer", null, 2.0, 1.5, 1.5, 1.0), new(10, "Camping", 20.0, 15.0, 15.0, "Explorer", null, 2.0, 1.5, 1.5, 1.0),
new(11, "Carpentry", 20.0, 5.0, 0.0, "Carpenter", null, 2.0, 0.5, 0.0, 1.0), new(11, "Carpentry", 20.0, 5.0, 0.0, "Carpenter", null, 2.0, 0.5, 0.0, 1.0),
new(12, "Cartography", 0.0, 7.5, 7.5, "Cartographer", null, 0.0, 0.75, 0.75, 1.0), new(12, "Cartography", 0.0, 7.5, 7.5, "Cartographer", null, 0.0, 0.75, 0.75, 1.0),
new(13, "Cooking", 0.0, 20.0, 30.0, "Chef", null, 0.0, 2.0, 3.0, 1.0), new(13, "Cooking", 0.0, 20.0, 30.0, "Chef", null, 0.0, 2.0, 3.0, 1.0),
new(14, "Detecting Hidden", 0.0, 0.0, 0.0, "Scout", null, 0.0, 0.4, 0.6, 1.0), new(14, "Detecting Hidden", 0.0, 0.0, 0.0, "Scout", null, 0.0, 0.4, 0.6, 1.0),
new(15, "Discordance", 0.0, 2.5, 2.5, "Demoralizer", null, 0.0, 0.25, 0.25, 1.0), new(15, "Discordance", 0.0, 2.5, 2.5, "Demoralizer", null, 0.0, 0.25, 0.25, 1.0, "Enticement"),
new(16, "Evaluating Intelligence", 0.0, 0.0, 0.0, "Scholar", null, 0.0, 0.0, 1.0, 1.0), new(16, "Evaluating Intelligence", 0.0, 0.0, 0.0, "Scholar", null, 0.0, 0.0, 1.0, 1.0, "EvaluateIntelligence"),
new(17, "Healing", 6.0, 6.0, 8.0, "Healer", null, 0.6, 0.6, 0.8, 1.0), new(17, "Healing", 6.0, 6.0, 8.0, "Healer", null, 0.6, 0.6, 0.8, 1.0),
new(18, "Fishing", 0.0, 0.0, 0.0, "Fisherman", null, 0.5, 0.5, 0.0, 1.0), new(18, "Fishing", 0.0, 0.0, 0.0, "Fisherman", null, 0.5, 0.5, 0.0, 1.0),
new(19, "Forensic Evaluation", 0.0, 0.0, 0.0, "Detective", null, 0.0, 0.2, 0.8, 1.0), new(19, "Forensic Evaluation", 0.0, 0.0, 0.0, "Detective", null, 0.0, 0.2, 0.8, 1.0),
@ -476,7 +480,7 @@ namespace Server
new(45, "Mining", 20.0, 0.0, 0.0, "Miner", null, 2.0, 0.0, 0.0, 1.0), new(45, "Mining", 20.0, 0.0, 0.0, "Miner", null, 2.0, 0.0, 0.0, 1.0),
new(46, "Meditation", 0.0, 0.0, 0.0, "Stoic", null, 0.0, 0.0, 0.0, 1.0), new(46, "Meditation", 0.0, 0.0, 0.0, "Stoic", null, 0.0, 0.0, 0.0, 1.0),
new(47, "Stealth", 0.0, 0.0, 0.0, "Rogue", null, 0.0, 0.0, 0.0, 1.0), new(47, "Stealth", 0.0, 0.0, 0.0, "Rogue", null, 0.0, 0.0, 0.0, 1.0),
new(48, "Remove Trap", 0.0, 0.0, 0.0, "Trap Specialist", null, 0.0, 0.0, 0.0, 1.0), new(48, "Remove Trap", 0.0, 0.0, 0.0, "Trap Specialist", null, 0.0, 0.0, 0.0, 1.0, "Disarm"),
new(49, "Necromancy", 0.0, 0.0, 0.0, "Necromancer", null, 0.0, 0.0, 0.0, 1.0), new(49, "Necromancy", 0.0, 0.0, 0.0, "Necromancer", null, 0.0, 0.0, 0.0, 1.0),
new(50, "Focus", 0.0, 0.0, 0.0, "Driven", null, 0.0, 0.0, 0.0, 1.0), new(50, "Focus", 0.0, 0.0, 0.0, "Driven", null, 0.0, 0.0, 0.0, 1.0),
new(51, "Chivalry", 0.0, 0.0, 0.0, "Paladin", null, 0.0, 0.0, 0.0, 1.0), new(51, "Chivalry", 0.0, 0.0, 0.0, "Paladin", null, 0.0, 0.0, 0.0, 1.0),
@ -892,16 +896,16 @@ namespace Server
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public SkillsEnumerator GetEnumerator() => new(m_Skills); public Enumerator GetEnumerator() => new(m_Skills);
public ref struct SkillsEnumerator public ref struct Enumerator
{ {
private readonly Skill[] _skills; private readonly Skill[] _skills;
private int _index; private int _index;
private Skill _current; private Skill _current;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal SkillsEnumerator(Skill[] skills) internal Enumerator(Skill[] skills)
{ {
_skills = skills; _skills = skills;
_index = 0; _index = 0;

View file

@ -35,7 +35,7 @@ namespace Server.Engines.Craft
public override double GetChanceAtMin(CraftItem item) public override double GetChanceAtMin(CraftItem item)
{ {
if (item.NameNumber == 1044258 || item.NameNumber == 1046445) // potion keg and faction trap removal kit if (item.NameNumber is 1044258 or 1046445) // potion keg and faction trap removal kit
{ {
return 0.5; // 50% return 0.5; // 50%
} }

View file

@ -0,0 +1,25 @@
namespace Server.Items
{
[Serializable(0)]
[TypeAlias("Server.Items.GargishClothArms", "Server.Items.GargishClothArmsArmor")]
public partial class GargishClothArmsType1 : BaseArmor
{
[Constructible]
public GargishClothArmsType1() : base(0x404) => Weight = 2.0;
public override int BasePhysicalResistance => 5;
public override int BaseFireResistance => 7;
public override int BaseColdResistance => 6;
public override int BasePoisonResistance => 6;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 20;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Cloth;
public override CraftResource DefaultResource => CraftResource.None;
public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,25 @@
namespace Server.Items
{
[Serializable(0)]
[TypeAlias("Server.Items.FemaleGargishClothArms", "Server.Items.FemaleGargishClothArmsArmor")]
public partial class GargishClothArmsType2 : BaseArmor
{
[Constructible]
public GargishClothArmsType2() : base(0x403) => Weight = 2.0;
public override int BasePhysicalResistance => 5;
public override int BaseFireResistance => 7;
public override int BaseColdResistance => 6;
public override int BasePoisonResistance => 6;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 20;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Cloth;
public override CraftResource DefaultResource => CraftResource.None;
public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,25 @@
namespace Server.Items
{
[Serializable(0)]
[TypeAlias("Server.Items.GargishClothChest", "Server.Items.GargishClothChestArmor")]
public partial class GargishClothChestType1 : BaseArmor
{
[Constructible]
public GargishClothChestType1() : base(0x406) => Weight = 2.0;
public override int BasePhysicalResistance => 5;
public override int BaseFireResistance => 7;
public override int BaseColdResistance => 6;
public override int BasePoisonResistance => 6;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 25;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Cloth;
public override CraftResource DefaultResource => CraftResource.None;
public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,25 @@
namespace Server.Items
{
[Serializable(0)]
[TypeAlias("Server.Items.FemaleGargishClothChest", "Server.Items.FemaleGargishClothChestArmor")]
public partial class GargishClothChestType2 : BaseArmor
{
[Constructible]
public GargishClothChestType2() : base(0x405) => Weight = 2.0;
public override int BasePhysicalResistance => 5;
public override int BaseFireResistance => 7;
public override int BaseColdResistance => 6;
public override int BasePoisonResistance => 6;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 25;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Cloth;
public override CraftResource DefaultResource => CraftResource.None;
public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,25 @@
namespace Server.Items
{
[Serializable(0)]
[TypeAlias("Server.Items.GargishClothKilt", "Server.Items.GargishClothKiltArmor")]
public partial class GargishClothKiltType1 : BaseArmor
{
[Constructible]
public GargishClothKiltType1() : base(0x408) => Weight = 2.0;
public override int BasePhysicalResistance => 5;
public override int BaseFireResistance => 7;
public override int BaseColdResistance => 6;
public override int BasePoisonResistance => 6;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 20;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Cloth;
public override CraftResource DefaultResource => CraftResource.None;
public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,25 @@
namespace Server.Items
{
[Serializable(0)]
[TypeAlias("Server.Items.GargishClothKilt", "Server.Items.GargishClothKiltArmor")]
public partial class GargishClothKiltType2 : BaseArmor
{
[Constructible]
public GargishClothKiltType2() : base(0x407) => Weight = 2.0;
public override int BasePhysicalResistance => 5;
public override int BaseFireResistance => 7;
public override int BaseColdResistance => 6;
public override int BasePoisonResistance => 6;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 20;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Cloth;
public override CraftResource DefaultResource => CraftResource.None;
public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,25 @@
namespace Server.Items
{
[Serializable(0)]
[TypeAlias("Server.Items.GargishClothLegs", "Server.Items.GargishClothLegsArmor")]
public partial class GargishClothLegsType1 : BaseArmor
{
[Constructible]
public GargishClothLegsType1() : base(0x40A) => Weight = 2.0;
public override int BasePhysicalResistance => 5;
public override int BaseFireResistance => 7;
public override int BaseColdResistance => 6;
public override int BasePoisonResistance => 6;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 20;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Cloth;
public override CraftResource DefaultResource => CraftResource.None;
public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,25 @@
namespace Server.Items
{
[Serializable(0)]
[TypeAlias("Server.Items.FemaleGargishClothLegs", "Server.Items.FemaleGargishClothLegsArmor")]
public partial class GargishClothLegsType2 : BaseArmor
{
[Constructible]
public GargishClothLegsType2() : base(0x409) => Weight = 2.0;
public override int BasePhysicalResistance => 5;
public override int BaseFireResistance => 7;
public override int BaseColdResistance => 6;
public override int BasePoisonResistance => 6;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 20;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Cloth;
public override CraftResource DefaultResource => CraftResource.None;
public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,26 @@
namespace Server.Items
{
[Serializable(0, false)]
[TypeAlias("Server.Items.GargishStoneArms")]
public partial class GargishStoneArmsType1 : BaseArmor
{
[Constructible]
public GargishStoneArmsType1() : base(0x284) => Weight = 10.0;
public override int RequiredRaces => Race.AllowGargoylesOnly;
public override int BasePhysicalResistance => 6;
public override int BaseFireResistance => 6;
public override int BaseColdResistance => 4;
public override int BasePoisonResistance => 8;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 40;
public override int OldStrReq => 40;
public override int ArmorBase => 40;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Stone;
}
}

View file

@ -0,0 +1,26 @@
namespace Server.Items
{
[Serializable(0, false)]
[TypeAlias("Server.Items.FemaleGargishStoneArms")]
public partial class GargishStoneArmsType2 : BaseArmor
{
[Constructible]
public GargishStoneArmsType2() : base(0x283) => Weight = 10.0;
public override int RequiredRaces => Race.AllowGargoylesOnly;
public override int BasePhysicalResistance => 6;
public override int BaseFireResistance => 6;
public override int BaseColdResistance => 4;
public override int BasePoisonResistance => 8;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 40;
public override int OldStrReq => 40;
public override int ArmorBase => 40;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Stone;
}
}

View file

@ -0,0 +1,26 @@
namespace Server.Items
{
[Serializable(0, false)]
[TypeAlias("Server.Items.GargishStoneChest")]
public partial class GargishStoneChestType1 : BaseArmor
{
[Constructible]
public GargishStoneChestType1() : base(0x286) => Weight = 15.0;
public override int RequiredRaces => Race.AllowGargoylesOnly;
public override int BasePhysicalResistance => 6;
public override int BaseFireResistance => 6;
public override int BaseColdResistance => 4;
public override int BasePoisonResistance => 8;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 40;
public override int OldStrReq => 40;
public override int ArmorBase => 40;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Stone;
}
}

View file

@ -0,0 +1,27 @@
namespace Server.Items
{
[Serializable(0, false)]
[TypeAlias("Server.Items.FemaleGargishStoneChest")]
public partial class GargishStoneChestType2 : BaseArmor
{
[Constructible]
public GargishStoneChestType2() : base(0x285) => Weight = 15.0;
public override int RequiredRaces => Race.AllowGargoylesOnly;
public override int BasePhysicalResistance => 6;
public override int BaseFireResistance => 6;
public override int BaseColdResistance => 4;
public override int BasePoisonResistance => 8;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 40;
public override int OldStrReq => 40;
public override int ArmorBase => 40;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Stone;
}
}

View file

@ -0,0 +1,26 @@
namespace Server.Items
{
[Serializable(0, false)]
[TypeAlias("Server.Items.GargishStoneKilt")]
public partial class GargishStoneKiltType1 : BaseArmor
{
[Constructible]
public GargishStoneKiltType1() : base(0x288) => Weight = 10.0;
public override int RequiredRaces => Race.AllowGargoylesOnly;
public override int BasePhysicalResistance => 6;
public override int BaseFireResistance => 6;
public override int BaseColdResistance => 4;
public override int BasePoisonResistance => 8;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 40;
public override int OldStrReq => 40;
public override int ArmorBase => 40;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Stone;
}
}

View file

@ -0,0 +1,27 @@
namespace Server.Items
{
[Serializable(0, false)]
[TypeAlias("Server.Items.FemaleGargishStoneKilt")]
public partial class GargishStoneKiltType2 : BaseArmor
{
[Constructible]
public GargishStoneKiltType2() : base(0x287) => Weight = 10.0;
public override int RequiredRaces => Race.AllowGargoylesOnly;
public override int BasePhysicalResistance => 6;
public override int BaseFireResistance => 6;
public override int BaseColdResistance => 4;
public override int BasePoisonResistance => 8;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 40;
public override int OldStrReq => 40;
public override int ArmorBase => 40;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Stone;
}
}

View file

@ -0,0 +1,26 @@
namespace Server.Items
{
[Serializable(0, false)]
[TypeAlias("Server.Items.GargishStoneLegs")]
public partial class GargishStoneLegsType1 : BaseArmor
{
[Constructible]
public GargishStoneLegsType1() : base(0x28A) => Weight = 15.0;
public override int RequiredRaces => Race.AllowGargoylesOnly;
public override int BasePhysicalResistance => 6;
public override int BaseFireResistance => 6;
public override int BaseColdResistance => 4;
public override int BasePoisonResistance => 8;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 40;
public override int OldStrReq => 40;
public override int ArmorBase => 40;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Stone;
}
}

View file

@ -0,0 +1,27 @@
namespace Server.Items
{
[Serializable(0, false)]
[TypeAlias("Server.Items.FemaleGargishStoneLegs")]
public partial class GargishStoneLegsType2 : BaseArmor
{
[Constructible]
public GargishStoneLegsType2() : base(0x289) => Weight = 15.0;
public override int RequiredRaces => Race.AllowGargoylesOnly;
public override int BasePhysicalResistance => 6;
public override int BaseFireResistance => 6;
public override int BaseColdResistance => 4;
public override int BasePoisonResistance => 8;
public override int BaseEnergyResistance => 6;
public override int InitMinHits => 40;
public override int InitMaxHits => 50;
public override int AosStrReq => 40;
public override int OldStrReq => 40;
public override int ArmorBase => 40;
public override ArmorMaterialType MaterialType => ArmorMaterialType.Stone;
}
}

View file

@ -624,7 +624,7 @@ namespace Server.Items
public override void OnAfterDuped(Item newItem) public override void OnAfterDuped(Item newItem)
{ {
if (!(newItem is BaseClothing clothing)) if (newItem is not BaseClothing clothing)
{ {
return; return;
} }

View file

@ -0,0 +1,21 @@
namespace Server.Items
{
[Flippable(0x4200, 0x4207)]
[Serializable(0)]
public partial class GargishWoodenShield : BaseShield
{
[Constructible]
public GargishWoodenShield() : base(0x4200) => Weight = 5.0;
public override int BasePhysicalResistance => 0;
public override int BaseFireResistance => 0;
public override int BaseColdResistance => 0;
public override int BasePoisonResistance => 0;
public override int BaseEnergyResistance => 1;
public override int InitMinHits => 20;
public override int InitMaxHits => 25;
public override int AosStrReq => 20;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -3,7 +3,8 @@ using Server.Engines.Craft;
namespace Server.Items namespace Server.Items
{ {
[Flippable(0x1EB8, 0x1EB9)] [Flippable(0x1EB8, 0x1EB9)]
public class TinkerTools : BaseTool [Serializable(0, false)]
public partial class TinkerTools : BaseTool
{ {
[Constructible] [Constructible]
public TinkerTools() : base(0x1EB8) => Weight = 1.0; public TinkerTools() : base(0x1EB8) => Weight = 1.0;
@ -11,58 +12,18 @@ namespace Server.Items
[Constructible] [Constructible]
public TinkerTools(int uses) : base(uses, 0x1EB8) => Weight = 1.0; public TinkerTools(int uses) : base(uses, 0x1EB8) => Weight = 1.0;
public TinkerTools(Serial serial) : base(serial)
{
}
public override CraftSystem CraftSystem => DefTinkering.CraftSystem; public override CraftSystem CraftSystem => DefTinkering.CraftSystem;
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
}
} }
public class TinkersTools : BaseTool [Serializable(0, false)]
public partial class TinkersTools : BaseTool
{ {
[Constructible] [Constructible]
public TinkersTools() public TinkersTools() : base(0x1EBC) => Weight = 1.0;
: base(0x1EBC) =>
Weight = 1.0;
[Constructible] [Constructible]
public TinkersTools(int uses) public TinkersTools(int uses) : base(uses, 0x1EBC) => Weight = 1.0;
: base(uses, 0x1EBC) =>
Weight = 1.0;
public TinkersTools(Serial serial)
: base(serial)
{
}
public override CraftSystem CraftSystem => DefTinkering.CraftSystem; public override CraftSystem CraftSystem => DefTinkering.CraftSystem;
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
}
} }
} }

View file

@ -0,0 +1,24 @@
namespace Server.Items
{
[Flippable(0x8FD, 0x4068)]
[Serializable(0)]
public partial class DualShortAxes : BaseAxe
{
[Constructible]
public DualShortAxes() : base(0x8FD)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike;
public override WeaponAbility SecondaryAbility => WeaponAbility.InfectiousStrike;
public override int AosStrengthReq => 35;
public override int AosMinDamage => 14;
public override int AosMaxDamage => 17;
public override float MlSpeed => 3.00f;
public override int InitMinHits => 31;
public override int InitMaxHits => 110;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,24 @@
namespace Server.Items
{
[Flippable(0x903, 0x406E)]
[Serializable(0)]
public partial class DiscMace : BaseBashing
{
[Constructible]
public DiscMace() : base(0x903)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore;
public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm;
public override int AosStrengthReq => 45;
public override int AosMinDamage => 11;
public override int AosMaxDamage => 15;
public override float MlSpeed => 2.75f;
public override int InitMinHits => 31;
public override int InitMaxHits => 110;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,24 @@
namespace Server.Items
{
[Flippable(0x904, 0x406D)]
[Serializable(0)]
public partial class DualPointedSpear : BaseSpear
{
[Constructible]
public DualPointedSpear() : base(0x904)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike;
public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm;
public override int AosStrengthReq => 50;
public override int AosMinDamage => 11;
public override int AosMaxDamage => 14;
public override float MlSpeed => 2.25f;
public override int InitMinHits => 31;
public override int InitMaxHits => 80;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,23 @@
namespace Server.Items
{
[Flippable(0x905, 0x4070)]
[Serializable(0)]
public partial class GlassStaff : BaseStaff
{
[Constructible]
public GlassStaff() : base(0x905) =>
Weight = 4.0;
public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike;
public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike;
public override int AosStrengthReq => 20;
public override int AosMinDamage => 11;
public override int AosMaxDamage => 14;
public override float MlSpeed => 2.25f;
public override int InitMinHits => 31;
public override int InitMaxHits => 70;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,25 @@
namespace Server.Items
{
[Flippable(0x906, 0x406F)]
[TypeAlias("Server.Items.SerpentStoneStaff")]
[Serializable(0)]
public partial class SerpentstoneStaff : BaseStaff
{
[Constructible]
public SerpentstoneStaff() : base(0x906)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow;
public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount;
public override int AosStrengthReq => 35;
public override int AosMinDamage => 16;
public override int AosMaxDamage => 19;
public override float MlSpeed => 3.50f;
public override int InitMinHits => 31;
public override int InitMaxHits => 50;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -53,33 +53,31 @@ namespace Server.Items
protected override void OnTarget(Mobile from, object targ) protected override void OnTarget(Mobile from, object targ)
{ {
if (targ is BaseCreature bc) if (targ is not BaseCreature bc)
{ {
if (IsHerdable(bc)) from.SendLocalizedMessage(502472); // You don't seem to be able to persuade that to move.
{ return;
if (bc.Controlled) }
{
bc.PrivateOverheadMessage( if (!IsHerdable(bc))
MessageType.Regular, {
0x3B2, from.SendLocalizedMessage(502468); // That is not a herdable animal.
502467, return;
from.NetState }
); // That animal looks tame already.
} if (bc.Controlled)
else {
{ bc.PrivateOverheadMessage(
from.SendLocalizedMessage(502475); // Click where you wish the animal to go. MessageType.Regular,
from.Target = new InternalTarget(bc); 0x3B2,
} 502467, // That animal looks tame already.
} from.NetState
else );
{
from.SendLocalizedMessage(502468); // That is not a herdable animal.
}
} }
else else
{ {
from.SendLocalizedMessage(502472); // You don't seem to be able to persuade that to move. from.SendLocalizedMessage(502475); // Click where you wish the animal to go.
from.Target = new InternalTarget(bc);
} }
} }
@ -136,9 +134,9 @@ namespace Server.Items
m_Creature.PrivateOverheadMessage( m_Creature.PrivateOverheadMessage(
MessageType.Regular, MessageType.Regular,
0x3B2, 0x3B2,
502471, 502471, // That wasn't even challenging.
from.NetState from.NetState
); // That wasn't even challenging. );
} }
if (from.CheckTargetSkill(SkillName.Herding, m_Creature, min, max)) if (from.CheckTargetSkill(SkillName.Herding, m_Creature, min, max))

View file

@ -0,0 +1,29 @@
namespace Server.Items
{
[Flippable(0x8FE, 0x4072)]
[Serializable(0)]
public partial class BloodBlade : BaseSword
{
[Constructible]
public BloodBlade() : base(0x8FE)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack;
public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow;
public override int AosStrengthReq => 10;
public override int AosMinDamage => 10;
public override int AosMaxDamage => 12;
public override float MlSpeed => 2.00f;
public override int DefHitSound => 0x23C;
public override int DefMissSound => 0x238;
public override int InitMinHits => 31;
public override int InitMaxHits => 90;
public override SkillName DefSkill => SkillName.Fencing;
public override WeaponType DefType => WeaponType.Piercing;
public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,26 @@
namespace Server.Items
{
[Flippable(0x90B, 0x4074)]
[Serializable(0)]
public partial class DreadSword : BaseSword
{
[Constructible]
public DreadSword() : base(0x90B)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow;
public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow;
public override int AosStrengthReq => 35;
public override int AosMinDamage => 14;
public override int AosMaxDamage => 18;
public override float MlSpeed => 3.50f;
public override int DefHitSound => 0x237;
public override int DefMissSound => 0x23A;
public override int InitMinHits => 31;
public override int InitMaxHits => 110;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,26 @@
namespace Server.Items
{
[Flippable(0x908, 0x4075)]
[Serializable(0)]
public partial class GargishTalwar : BaseSword
{
[Constructible]
public GargishTalwar() : base(0x908)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack;
public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount;
public override int AosStrengthReq => 40;
public override int AosMinDamage => 16;
public override int AosMaxDamage => 19;
public override float MlSpeed => 3.50f;
public override int DefHitSound => 0x237;
public override int DefMissSound => 0x238;
public override int InitMinHits => 31;
public override int InitMaxHits => 80;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,24 @@
namespace Server.Items
{
[Flippable(0x90C, 0x4073)]
[Serializable(0)]
public partial class GlassSword : BaseSword
{
[Constructible]
public GlassSword() : base(0x90C) => Weight = 6.0;
public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack;
public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike;
public override int AosStrengthReq => 20;
public override int AosMinDamage => 11;
public override int AosMaxDamage => 15;
public override float MlSpeed => 2.75f;
public override int DefHitSound => 0x23B;
public override int DefMissSound => 0x23A;
public override int InitMinHits => 31;
public override int InitMaxHits => 90;
public override int RequiredRaces => Race.AllowGargoylesOnly;
}
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.BloodBlade"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.DiscMace"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.DreadSword"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.DualPointedSpear"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.DualShortAxes"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishClothArmsType1"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishClothArmsType2"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishClothChestType1"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishClothChestType2"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishClothKiltType1"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishClothKiltType2"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishClothLegsType1"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishClothLegsType2"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishStoneArmsType1"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishStoneArmsType2"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishStoneChestType1"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishStoneChestType2"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishStoneKiltType1"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishStoneKiltType2"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishStoneLegsType1"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishStoneLegsType2"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishTalwar"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GargishWoodenShield"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GlassStaff"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.GlassSword"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.SerpentstoneStaff"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.Talwar"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.TinkerTools"
}

View file

@ -0,0 +1,4 @@
{
"version": 0,
"type": "Server.Items.TinkersTools"
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,205 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Server
{
public class ProfessionInfo
{
public static ProfessionInfo[] Professions { get; }
private static bool TryGetSkillName(string name, out SkillName skillName)
{
if (Enum.TryParse(name, out skillName))
{
return true;
}
var lowerName = name.ToLowerInvariant().Replace(" ", "");
foreach (var so in SkillInfo.Table)
{
if (lowerName == so.ProfessionSkillName.ToLowerInvariant())
{
skillName = (SkillName)so.SkillID;
return true;
}
}
return false;
}
static ProfessionInfo()
{
var profs = new List<ProfessionInfo>
{
new()
{
ID = 0, // Custom
Name = "Advanced",
TopLevel = false,
GumpID = 5571
}
};
var file = Core.FindDataFile("prof.txt");
if (!File.Exists(file))
{
var parent = Path.Combine(Core.BaseDirectory, "Data/Professions");
file = Path.Combine(ExpansionInfo.GetEraFolder(parent), "prof.txt");
}
var maxProf = 0;
if (File.Exists(file))
{
using var s = File.OpenText(file);
while (!s.EndOfStream)
{
var line = s.ReadLine();
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
line = line.Trim();
if (!line.InsensitiveStartsWith("Begin"))
{
continue;
}
var prof = new ProfessionInfo();
int stats;
int valid;
var skills = stats = valid = 0;
while (!s.EndOfStream)
{
line = s.ReadLine();
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
line = line.Trim();
if (line.InsensitiveStartsWith("End"))
{
if (valid >= 4)
{
profs.Add(prof);
}
break;
}
var cols = line.Split('\t', StringSplitOptions.RemoveEmptyEntries);
var key = cols[0].ToLowerInvariant();
var value = cols[1].Trim('"');
if (key == "type" && value != "profession")
{
break;
}
switch (key)
{
case "truename":
{
prof.Name = value;
++valid;
}
break;
case "nameid":
prof.NameID = Utility.ToInt32(value);
break;
case "descid":
prof.DescID = Utility.ToInt32(value);
break;
case "desc":
{
prof.ID = Utility.ToInt32(value);
if (prof.ID > maxProf)
{
maxProf = prof.ID;
}
++valid;
}
break;
case "toplevel":
prof.TopLevel = Utility.ToBoolean(value);
break;
case "gump":
prof.GumpID = Utility.ToInt32(value);
break;
case "skill":
{
if (!TryGetSkillName(value, out var skillName))
{
break;
}
prof.Skills[skills++] = new SkillNameValue(skillName, Utility.ToInt32(cols[2]));
if (skills == prof.Skills.Length)
{
++valid;
}
}
break;
case "stat":
{
if (!Enum.TryParse(value, out StatType stat))
{
break;
}
prof.Stats[stats++] = new StatNameValue(stat, Utility.ToInt32(cols[2]));
if (stats == prof.Stats.Length)
{
++valid;
}
}
break;
}
}
}
}
Professions = new ProfessionInfo[1 + maxProf];
foreach (var p in profs)
{
Professions[p.ID] = p;
}
profs.Clear();
profs.TrimExcess();
}
private ProfessionInfo()
{
Name = string.Empty;
Skills = new SkillNameValue[4];
Stats = new StatNameValue[3];
}
public int ID { get; private set; }
public string Name { get; private set; }
public int NameID { get; private set; }
public int DescID { get; private set; }
public bool TopLevel { get; private set; }
public int GumpID { get; private set; }
public SkillNameValue[] Skills { get; }
public StatNameValue[] Stats { get; }
}
}

View file

@ -119,7 +119,8 @@ namespace Server.Mobiles
p = GetSpawnPosition(2); p = GetSpawnPosition(2);
var eable = Map.GetItemsInRange<StainedOoze>(p, 0); var eable = Map.GetItemsInRange<StainedOoze>(p, 0);
bool atLocation = eable.GetEnumerator().MoveNext(); using var enumerator = eable.GetEnumerator();
bool atLocation = enumerator.MoveNext();
eable.Free(); eable.Free();
if (!atLocation) if (!atLocation)
{ {

View file

@ -252,7 +252,8 @@ namespace Server.Mobiles
p = GetSpawnPosition(2); p = GetSpawnPosition(2);
var eable = Map.GetItemsInRange<StainedOoze>(p, 0); var eable = Map.GetItemsInRange<StainedOoze>(p, 0);
bool atLocation = eable.GetEnumerator().MoveNext(); using var enumerator = eable.GetEnumerator();
bool atLocation = enumerator.MoveNext();
eable.Free(); eable.Free();
if (!atLocation) if (!atLocation)
{ {

View file

@ -803,14 +803,21 @@ namespace Server.Mobiles
switch (type) switch (type)
{ {
case BlockMountType.Dazed: case BlockMountType.Dazed:
SendLocalizedMessage(1112457); {
break; // You are still too dazed to fly. SendLocalizedMessage(1112457); // You are still too dazed to fly.
break;
}
case BlockMountType.BolaRecovery: case BlockMountType.BolaRecovery:
SendLocalizedMessage(1112455); {
break; // You cannot fly while recovering from a bola throw. SendLocalizedMessage(1112455); // You cannot fly while recovering from a bola throw.
break;
}
case BlockMountType.DismountRecovery: case BlockMountType.DismountRecovery:
SendLocalizedMessage(1112456); {
break; // You cannot fly while recovering from a dismount maneuver. // You cannot fly while recovering from a dismount maneuver.
SendLocalizedMessage(1112456);
break;
}
} }
} }
else if (Hits < 25) // TODO confirm else if (Hits < 25) // TODO confirm
@ -3204,7 +3211,6 @@ namespace Server.Mobiles
RecentlyReported ??= new List<Mobile>(); RecentlyReported ??= new List<Mobile>();
// Professions weren't verified on 1.0 RC0
if (!CharacterCreation.VerifyProfession(Profession)) if (!CharacterCreation.VerifyProfession(Profession))
{ {
Profession = 0; Profession = 0;

View file

@ -2,7 +2,10 @@ using System;
using System.Text; using System.Text;
using Microsoft.Toolkit.HighPerformance; using Microsoft.Toolkit.HighPerformance;
using Server.Commands; using Server.Commands;
using Server.Factions;
using Server.Gumps; using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Network; using Server.Network;
namespace Server.Misc namespace Server.Misc
@ -84,7 +87,7 @@ namespace Server.Misc
private static void ChangeStrength(Mobile from, int value) private static void ChangeStrength(Mobile from, int value)
{ {
if (value < 10 || value > 125) if (value is < 10 or > 125)
{ {
from.SendLocalizedMessage(1005628); // Stats range between 10 and 125. from.SendLocalizedMessage(1005628); // Stats range between 10 and 125.
} }
@ -106,7 +109,7 @@ namespace Server.Misc
private static void ChangeDexterity(Mobile from, int value) private static void ChangeDexterity(Mobile from, int value)
{ {
if (value < 10 || value > 125) if (value is < 10 or > 125)
{ {
from.SendLocalizedMessage(1005628); // Stats range between 10 and 125. from.SendLocalizedMessage(1005628); // Stats range between 10 and 125.
} }
@ -128,7 +131,7 @@ namespace Server.Misc
private static void ChangeIntelligence(Mobile from, int value) private static void ChangeIntelligence(Mobile from, int value)
{ {
if (value < 10 || value > 125) if (value is < 10 or > 125)
{ {
from.SendLocalizedMessage(1005628); // Stats range between 10 and 125. from.SendLocalizedMessage(1005628); // Stats range between 10 and 125.
} }
@ -186,6 +189,485 @@ namespace Server.Misc
} }
} }
private static Item MakeNewbie(Item item)
{
if (!Core.AOS)
{
item.LootType = LootType.Newbied;
}
return item;
}
private static void PlaceItemIn(Container parent, int x, int y, Item item)
{
parent.AddItem(item);
item.Location = new Point3D(x, y, 0);
}
private static Item MakePotionKeg(PotionEffect type, int hue)
{
var keg = new PotionKeg
{
Held = 100,
Type = type,
Hue = hue
};
return MakeNewbie(keg);
}
private static void FillBankAOS(Mobile m)
{
var bank = m.BankBox;
// The new AOS bankboxes don't have powerscrolls, they are automatically 'applied':
for (var i = 0; i < PowerScroll.Skills.Count; ++i)
{
m.Skills[PowerScroll.Skills[i]].Cap = 120.0;
}
m.StatCap = 250;
Container cont;
// Begin box of money
cont = new WoodenBox { ItemID = 0xE7D, Hue = 0x489 };
PlaceItemIn(cont, 16, 51, new BankCheck(500000));
PlaceItemIn(cont, 28, 51, new BankCheck(250000));
PlaceItemIn(cont, 40, 51, new BankCheck(100000));
PlaceItemIn(cont, 52, 51, new BankCheck(100000));
PlaceItemIn(cont, 64, 51, new BankCheck(50000));
PlaceItemIn(cont, 16, 115, new Silver(9000));
PlaceItemIn(cont, 34, 115, new Gold(60000));
PlaceItemIn(bank, 18, 169, cont);
// End box of money
// Begin bag of potion kegs
cont = new Backpack { Name = "Various Potion Kegs" };
PlaceItemIn(cont, 45, 149, MakePotionKeg(PotionEffect.CureGreater, 0x2D));
PlaceItemIn(cont, 69, 149, MakePotionKeg(PotionEffect.HealGreater, 0x499));
PlaceItemIn(cont, 93, 149, MakePotionKeg(PotionEffect.PoisonDeadly, 0x46));
PlaceItemIn(cont, 117, 149, MakePotionKeg(PotionEffect.RefreshTotal, 0x21));
PlaceItemIn(cont, 141, 149, MakePotionKeg(PotionEffect.ExplosionGreater, 0x74));
PlaceItemIn(cont, 93, 82, new Bottle(1000));
PlaceItemIn(bank, 53, 169, cont);
// End bag of potion kegs
// Begin bag of tools
cont = new Bag { Name = "Tool Bag" };
PlaceItemIn(cont, 30, 35, new TinkerTools(1000));
PlaceItemIn(cont, 60, 35, new HousePlacementTool());
PlaceItemIn(cont, 90, 35, new DovetailSaw(1000));
PlaceItemIn(cont, 30, 68, new Scissors());
PlaceItemIn(cont, 45, 68, new MortarPestle(1000));
PlaceItemIn(cont, 75, 68, new ScribesPen(1000));
PlaceItemIn(cont, 90, 68, new SmithHammer(1000));
PlaceItemIn(cont, 30, 118, new TwoHandedAxe());
PlaceItemIn(cont, 60, 118, new FletcherTools(1000));
PlaceItemIn(cont, 90, 118, new SewingKit(1000));
PlaceItemIn(cont, 36, 51, new RunicHammer(CraftResource.DullCopper, 1000));
PlaceItemIn(cont, 42, 51, new RunicHammer(CraftResource.ShadowIron, 1000));
PlaceItemIn(cont, 48, 51, new RunicHammer(CraftResource.Copper, 1000));
PlaceItemIn(cont, 54, 51, new RunicHammer(CraftResource.Bronze, 1000));
PlaceItemIn(cont, 61, 51, new RunicHammer(CraftResource.Gold, 1000));
PlaceItemIn(cont, 67, 51, new RunicHammer(CraftResource.Agapite, 1000));
PlaceItemIn(cont, 73, 51, new RunicHammer(CraftResource.Verite, 1000));
PlaceItemIn(cont, 79, 51, new RunicHammer(CraftResource.Valorite, 1000));
PlaceItemIn(cont, 36, 55, new RunicSewingKit(CraftResource.SpinedLeather, 1000));
PlaceItemIn(cont, 42, 55, new RunicSewingKit(CraftResource.HornedLeather, 1000));
PlaceItemIn(cont, 48, 55, new RunicSewingKit(CraftResource.BarbedLeather, 1000));
PlaceItemIn(bank, 118, 169, cont);
// End bag of tools
// Begin bag of archery ammo
cont = new Bag { Name = "Bag Of Archery Ammo" };
PlaceItemIn(cont, 48, 76, new Arrow(5000));
PlaceItemIn(cont, 72, 76, new Bolt(5000));
PlaceItemIn(bank, 118, 124, cont);
// End bag of archery ammo
// Begin bag of treasure maps
cont = new Bag { Name = "Bag Of Treasure Maps" };
PlaceItemIn(cont, 30, 35, new TreasureMap(1, Map.Trammel));
PlaceItemIn(cont, 45, 35, new TreasureMap(2, Map.Trammel));
PlaceItemIn(cont, 60, 35, new TreasureMap(3, Map.Trammel));
PlaceItemIn(cont, 75, 35, new TreasureMap(4, Map.Trammel));
PlaceItemIn(cont, 90, 35, new TreasureMap(5, Map.Trammel));
PlaceItemIn(cont, 90, 35, new TreasureMap(6, Map.Trammel));
PlaceItemIn(cont, 30, 50, new TreasureMap(1, Map.Trammel));
PlaceItemIn(cont, 45, 50, new TreasureMap(2, Map.Trammel));
PlaceItemIn(cont, 60, 50, new TreasureMap(3, Map.Trammel));
PlaceItemIn(cont, 75, 50, new TreasureMap(4, Map.Trammel));
PlaceItemIn(cont, 90, 50, new TreasureMap(5, Map.Trammel));
PlaceItemIn(cont, 90, 50, new TreasureMap(6, Map.Trammel));
PlaceItemIn(cont, 55, 100, new Lockpick(30));
PlaceItemIn(cont, 60, 100, new Pickaxe());
PlaceItemIn(bank, 98, 124, cont);
// End bag of treasure maps
// Begin bag of raw materials
cont = new Bag { Hue = 0x835, Name = "Raw Materials Bag" };
PlaceItemIn(cont, 92, 60, new BarbedLeather(5000));
PlaceItemIn(cont, 92, 68, new HornedLeather(5000));
PlaceItemIn(cont, 92, 76, new SpinedLeather(5000));
PlaceItemIn(cont, 92, 84, new Leather(5000));
PlaceItemIn(cont, 30, 118, new Cloth(5000));
PlaceItemIn(cont, 30, 84, new Board(5000));
PlaceItemIn(cont, 57, 80, new BlankScroll(500));
PlaceItemIn(cont, 30, 35, new DullCopperIngot(5000));
PlaceItemIn(cont, 37, 35, new ShadowIronIngot(5000));
PlaceItemIn(cont, 44, 35, new CopperIngot(5000));
PlaceItemIn(cont, 51, 35, new BronzeIngot(5000));
PlaceItemIn(cont, 58, 35, new GoldIngot(5000));
PlaceItemIn(cont, 65, 35, new AgapiteIngot(5000));
PlaceItemIn(cont, 72, 35, new VeriteIngot(5000));
PlaceItemIn(cont, 79, 35, new ValoriteIngot(5000));
PlaceItemIn(cont, 86, 35, new IronIngot(5000));
PlaceItemIn(cont, 30, 59, new RedScales(5000));
PlaceItemIn(cont, 36, 59, new YellowScales(5000));
PlaceItemIn(cont, 42, 59, new BlackScales(5000));
PlaceItemIn(cont, 48, 59, new GreenScales(5000));
PlaceItemIn(cont, 54, 59, new WhiteScales(5000));
PlaceItemIn(cont, 60, 59, new BlueScales(5000));
PlaceItemIn(bank, 98, 169, cont);
// End bag of raw materials
// Begin bag of spell casting stuff
cont = new Backpack { Hue = 0x480, Name = "Spell Casting Stuff" };
PlaceItemIn(cont, 45, 105, new Spellbook(ulong.MaxValue));
PlaceItemIn(cont, 65, 105, new NecromancerSpellbook(0xFFFFUL));
PlaceItemIn(cont, 85, 105, new BookOfChivalry());
PlaceItemIn(cont, 105, 105, new BookOfBushido()); // Default ctor = full
PlaceItemIn(cont, 125, 105, new BookOfNinjitsu()); // Default ctor = full
var runebook = new Runebook(10);
runebook.CurCharges = runebook.MaxCharges;
PlaceItemIn(cont, 145, 105, runebook);
Item toHue = new BagOfReagents(150) { Hue = 0x2D };
PlaceItemIn(cont, 45, 150, toHue);
toHue = new BagOfNecroReagents(150) { Hue = 0x488 };
PlaceItemIn(cont, 65, 150, toHue);
PlaceItemIn(cont, 140, 150, new BagOfAllReagents(500));
for (var i = 0; i < 9; ++i)
{
PlaceItemIn(cont, 45 + i * 10, 75, new RecallRune());
}
PlaceItemIn(cont, 141, 74, new FireHorn());
PlaceItemIn(bank, 78, 169, cont);
// End bag of spell casting stuff
// Begin bag of ethereals
cont = new Backpack { Hue = 0x490, Name = "Bag Of Ethy's!" };
PlaceItemIn(cont, 45, 66, new EtherealHorse());
PlaceItemIn(cont, 69, 82, new EtherealOstard());
PlaceItemIn(cont, 93, 99, new EtherealLlama());
PlaceItemIn(cont, 117, 115, new EtherealKirin());
PlaceItemIn(cont, 45, 132, new EtherealUnicorn());
PlaceItemIn(cont, 69, 66, new EtherealRidgeback());
PlaceItemIn(cont, 93, 82, new EtherealSwampDragon());
PlaceItemIn(cont, 117, 99, new EtherealBeetle());
PlaceItemIn(bank, 38, 124, cont);
// End bag of ethereals
// Begin first bag of artifacts
cont = new Backpack { Hue = 0x48F, Name = "Bag of Artifacts" };
PlaceItemIn(cont, 45, 66, new TitansHammer());
PlaceItemIn(cont, 69, 82, new InquisitorsResolution());
PlaceItemIn(cont, 93, 99, new BladeOfTheRighteous());
PlaceItemIn(cont, 117, 115, new ZyronicClaw());
PlaceItemIn(bank, 58, 124, cont);
// End first bag of artifacts
// Begin second bag of artifacts
cont = new Backpack { Hue = 0x48F, Name = "Bag of Artifacts" };
PlaceItemIn(cont, 45, 66, new GauntletsOfNobility());
PlaceItemIn(cont, 69, 82, new MidnightBracers());
PlaceItemIn(cont, 93, 99, new VoiceOfTheFallenKing());
PlaceItemIn(cont, 117, 115, new OrnateCrownOfTheHarrower());
PlaceItemIn(cont, 45, 132, new HelmOfInsight());
PlaceItemIn(cont, 69, 66, new HolyKnightsBreastplate());
PlaceItemIn(cont, 93, 82, new ArmorOfFortune());
PlaceItemIn(cont, 117, 99, new TunicOfFire());
PlaceItemIn(cont, 45, 115, new LeggingsOfBane());
PlaceItemIn(cont, 69, 132, new ArcaneShield());
PlaceItemIn(cont, 93, 66, new Aegis());
PlaceItemIn(cont, 117, 82, new RingOfTheVile());
PlaceItemIn(cont, 45, 99, new BraceletOfHealth());
PlaceItemIn(cont, 69, 115, new RingOfTheElements());
PlaceItemIn(cont, 93, 132, new OrnamentOfTheMagician());
PlaceItemIn(cont, 117, 66, new DivineCountenance());
PlaceItemIn(cont, 45, 82, new JackalsCollar());
PlaceItemIn(cont, 69, 99, new HuntersHeaddress());
PlaceItemIn(cont, 93, 115, new HatOfTheMagi());
PlaceItemIn(cont, 117, 132, new ShadowDancerLeggings());
PlaceItemIn(cont, 45, 66, new SpiritOfTheTotem());
PlaceItemIn(cont, 69, 82, new BladeOfInsanity());
PlaceItemIn(cont, 93, 99, new AxeOfTheHeavens());
PlaceItemIn(cont, 117, 115, new TheBeserkersMaul());
PlaceItemIn(cont, 45, 132, new Frostbringer());
PlaceItemIn(cont, 69, 66, new BreathOfTheDead());
PlaceItemIn(cont, 93, 82, new TheDragonSlayer());
PlaceItemIn(cont, 117, 99, new BoneCrusher());
PlaceItemIn(cont, 45, 115, new StaffOfTheMagi());
PlaceItemIn(cont, 69, 132, new SerpentsFang());
PlaceItemIn(cont, 93, 66, new LegacyOfTheDreadLord());
PlaceItemIn(cont, 117, 82, new TheTaskmaster());
PlaceItemIn(cont, 45, 99, new TheDryadBow());
PlaceItemIn(bank, 78, 124, cont);
// End second bag of artifacts
// Begin bag of minor artifacts
cont = new Backpack { Hue = 0x48F, Name = "Bag of Minor Artifacts" };
PlaceItemIn(cont, 45, 66, new LunaLance());
PlaceItemIn(cont, 69, 82, new VioletCourage());
PlaceItemIn(cont, 93, 99, new CavortingClub());
PlaceItemIn(cont, 117, 115, new CaptainQuacklebushsCutlass());
PlaceItemIn(cont, 45, 132, new NightsKiss());
PlaceItemIn(cont, 69, 66, new ShipModelOfTheHMSCape());
PlaceItemIn(cont, 93, 82, new AdmiralsHeartyRum());
PlaceItemIn(cont, 117, 99, new CandelabraOfSouls());
PlaceItemIn(cont, 45, 115, new IolosLute());
PlaceItemIn(cont, 69, 132, new GwennosHarp());
PlaceItemIn(cont, 93, 66, new ArcticDeathDealer());
PlaceItemIn(cont, 117, 82, new EnchantedTitanLegBone());
PlaceItemIn(cont, 45, 99, new NoxRangersHeavyCrossbow());
PlaceItemIn(cont, 69, 115, new BlazeOfDeath());
PlaceItemIn(cont, 93, 132, new DreadPirateHat());
PlaceItemIn(cont, 117, 66, new BurglarsBandana());
PlaceItemIn(cont, 45, 82, new GoldBricks());
PlaceItemIn(cont, 69, 99, new AlchemistsBauble());
PlaceItemIn(cont, 93, 115, new PhillipsWoodenSteed());
PlaceItemIn(cont, 117, 132, new PolarBearMask());
PlaceItemIn(cont, 45, 66, new BowOfTheJukaKing());
PlaceItemIn(cont, 69, 82, new GlovesOfThePugilist());
PlaceItemIn(cont, 93, 99, new OrcishVisage());
PlaceItemIn(cont, 117, 115, new StaffOfPower());
PlaceItemIn(cont, 45, 132, new ShieldOfInvulnerability());
PlaceItemIn(cont, 69, 66, new HeartOfTheLion());
PlaceItemIn(cont, 93, 82, new ColdBlood());
PlaceItemIn(cont, 117, 99, new GhostShipAnchor());
PlaceItemIn(cont, 45, 115, new SeahorseStatuette());
PlaceItemIn(cont, 69, 132, new WrathOfTheDryad());
PlaceItemIn(cont, 93, 66, new PixieSwatter());
for (var i = 0; i < 10; i++)
{
PlaceItemIn(cont, 117, 128, new MessageInABottle(Utility.RandomBool() ? Map.Trammel : Map.Felucca, 4));
}
PlaceItemIn(bank, 18, 124, cont);
if (Core.SE)
{
cont = new Bag { Hue = 0x501, Name = "Tokuno Minor Artifacts" };
PlaceItemIn(cont, 42, 70, new Exiler());
PlaceItemIn(cont, 38, 53, new HanzosBow());
PlaceItemIn(cont, 45, 40, new TheDestroyer());
PlaceItemIn(cont, 92, 80, new DragonNunchaku());
PlaceItemIn(cont, 42, 56, new PeasantsBokuto());
PlaceItemIn(cont, 44, 71, new TomeOfEnlightenment());
PlaceItemIn(cont, 35, 35, new ChestOfHeirlooms());
PlaceItemIn(cont, 29, 0, new HonorableSwords());
PlaceItemIn(cont, 49, 85, new AncientUrn());
PlaceItemIn(cont, 51, 58, new FluteOfRenewal());
PlaceItemIn(cont, 70, 51, new PigmentsOfTokuno());
PlaceItemIn(cont, 40, 79, new AncientSamuraiDo());
PlaceItemIn(cont, 51, 61, new LegsOfStability());
PlaceItemIn(cont, 88, 78, new GlovesOfTheSun());
PlaceItemIn(cont, 55, 62, new AncientFarmersKasa());
PlaceItemIn(cont, 55, 83, new ArmsOfTacticalExcellence());
PlaceItemIn(cont, 50, 85, new DaimyosHelm());
PlaceItemIn(cont, 52, 78, new BlackLotusHood());
PlaceItemIn(cont, 52, 79, new DemonForks());
PlaceItemIn(cont, 33, 49, new PilferedDancerFans());
PlaceItemIn(bank, 58, 124, cont);
}
if (Core.SE) // This bag came only after SE.
{
cont = new Bag { Name = "Bag of Bows" };
PlaceItemIn(cont, 31, 84, new Bow());
PlaceItemIn(cont, 78, 74, new CompositeBow());
PlaceItemIn(cont, 53, 71, new Crossbow());
PlaceItemIn(cont, 56, 39, new HeavyCrossbow());
PlaceItemIn(cont, 82, 72, new RepeatingCrossbow());
PlaceItemIn(cont, 49, 45, new Yumi());
for (var i = 0; i < cont.Items.Count; i++)
{
if (cont.Items[i] is BaseRanged bow)
{
bow.Attributes.WeaponSpeed = 35;
bow.Attributes.WeaponDamage = 35;
}
}
PlaceItemIn(bank, 108, 135, cont);
}
}
public static void FillBankbox(Mobile m)
{
if (Core.AOS)
{
FillBankAOS(m);
return;
}
var bank = m.BankBox;
bank.DropItem(new BankCheck(1000000));
// Full spellbook
var book = new Spellbook { Content = ulong.MaxValue };
bank.DropItem(book);
var bag = new Bag();
for (var i = 0; i < 5; ++i)
{
bag.DropItem(new Moonstone(MoonstoneType.Felucca));
}
// Felucca moonstones
bank.DropItem(bag);
bag = new Bag();
for (var i = 0; i < 5; ++i)
{
bag.DropItem(new Moonstone(MoonstoneType.Trammel));
}
// Trammel moonstones
bank.DropItem(bag);
// Treasure maps
bank.DropItem(new TreasureMap(1, Map.Trammel));
bank.DropItem(new TreasureMap(2, Map.Trammel));
bank.DropItem(new TreasureMap(3, Map.Trammel));
bank.DropItem(new TreasureMap(4, Map.Trammel));
bank.DropItem(new TreasureMap(5, Map.Trammel));
// Bag containing 50 of each reagent
bank.DropItem(new BagOfReagents());
// Craft tools
bank.DropItem(MakeNewbie(new Scissors()));
bank.DropItem(MakeNewbie(new SewingKit(1000)));
bank.DropItem(MakeNewbie(new SmithHammer(1000)));
bank.DropItem(MakeNewbie(new FletcherTools(1000)));
bank.DropItem(MakeNewbie(new DovetailSaw(1000)));
bank.DropItem(MakeNewbie(new MortarPestle(1000)));
bank.DropItem(MakeNewbie(new ScribesPen(1000)));
bank.DropItem(MakeNewbie(new TinkerTools(1000)));
// A few dye tubs
bank.DropItem(new Dyes());
bank.DropItem(new DyeTub());
bank.DropItem(new DyeTub());
bank.DropItem(new BlackDyeTub());
bank.DropItem(new DyeTub { DyedHue = 0x485, Redyable = false });
// Some food
bank.DropItem(MakeNewbie(new Apple(1000)));
// Resources
bank.DropItem(MakeNewbie(new Feather(1000)));
bank.DropItem(MakeNewbie(new BoltOfCloth(1000)));
bank.DropItem(MakeNewbie(new BlankScroll(1000)));
bank.DropItem(MakeNewbie(new Hides(1000)));
bank.DropItem(MakeNewbie(new Bandage(1000)));
bank.DropItem(MakeNewbie(new Bottle(1000)));
bank.DropItem(MakeNewbie(new Log(1000)));
bank.DropItem(MakeNewbie(new IronIngot(5000)));
bank.DropItem(MakeNewbie(new DullCopperIngot(5000)));
bank.DropItem(MakeNewbie(new ShadowIronIngot(5000)));
bank.DropItem(MakeNewbie(new CopperIngot(5000)));
bank.DropItem(MakeNewbie(new BronzeIngot(5000)));
bank.DropItem(MakeNewbie(new GoldIngot(5000)));
bank.DropItem(MakeNewbie(new AgapiteIngot(5000)));
bank.DropItem(MakeNewbie(new VeriteIngot(5000)));
bank.DropItem(MakeNewbie(new ValoriteIngot(5000)));
// Reagents
bank.DropItem(MakeNewbie(new BlackPearl(1000)));
bank.DropItem(MakeNewbie(new Bloodmoss(1000)));
bank.DropItem(MakeNewbie(new Garlic(1000)));
bank.DropItem(MakeNewbie(new Ginseng(1000)));
bank.DropItem(MakeNewbie(new MandrakeRoot(1000)));
bank.DropItem(MakeNewbie(new Nightshade(1000)));
bank.DropItem(MakeNewbie(new SulfurousAsh(1000)));
bank.DropItem(MakeNewbie(new SpidersSilk(1000)));
// Some extra starting gold
bank.DropItem(MakeNewbie(new Gold(9000)));
// 5 blank recall runes
for (var i = 0; i < 5; ++i)
{
bank.DropItem(MakeNewbie(new RecallRune()));
}
AddPowerScrolls(bank);
}
private static void AddPowerScrolls(BankBox bank)
{
var bag = new Bag();
for (var i = 0; i < PowerScroll.Skills.Count; ++i)
{
bag.DropItem(new PowerScroll(PowerScroll.Skills[i], 120.0));
}
bag.DropItem(new StatCapScroll(250));
bank.DropItem(bag);
}
public class TCHelpGump : Gump public class TCHelpGump : Gump
{ {
public TCHelpGump() : base(40, 40) public TCHelpGump() : base(40, 40)

View file

@ -40,7 +40,7 @@
</ProjectReference> </ProjectReference>
<PackageReference Include="MailKit" Version="2.15.0" /> <PackageReference Include="MailKit" Version="2.15.0" />
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0" />
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.0.2" /> <PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.1.0" />
<PackageReference Include="Zlib.Bindings" Version="1.5.0" /> <PackageReference Include="Zlib.Bindings" Version="1.5.0" />
<PackageReference Include="Argon2.Bindings" Version="1.9.1" /> <PackageReference Include="Argon2.Bindings" Version="1.9.1" />
<PackageReference Include="Zstd.Binaries" Version="1.0.0" /> <PackageReference Include="Zstd.Binaries" Version="1.0.0" />