Cleanup and adds configuration for crashguard (#240)
This commit is contained in:
parent
55ae0f8778
commit
7dbfa086bc
39 changed files with 1248 additions and 97 deletions
|
|
@ -33,7 +33,9 @@ namespace Server.Ethics
|
|||
if ((item.SavedFlags & 0x100) != 0)
|
||||
{
|
||||
if (item.Hue == Hero.Definition.PrimaryHue)
|
||||
{
|
||||
return Hero;
|
||||
}
|
||||
|
||||
item.SavedFlags &= ~0x100;
|
||||
}
|
||||
|
|
@ -41,7 +43,9 @@ namespace Server.Ethics
|
|||
if ((item.SavedFlags & 0x200) != 0)
|
||||
{
|
||||
if (item.Hue == Evil.Definition.PrimaryHue)
|
||||
{
|
||||
return Evil;
|
||||
}
|
||||
|
||||
item.SavedFlags &= ~0x200;
|
||||
}
|
||||
|
|
@ -54,12 +58,18 @@ namespace Server.Ethics
|
|||
var itemEthic = Find(item);
|
||||
|
||||
if (itemEthic == null || Find(newOwner) == itemEthic)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (itemEthic == Hero)
|
||||
{
|
||||
(from == newOwner ? to : from).SendMessage("Only heros may receive this item.");
|
||||
}
|
||||
else if (itemEthic == Evil)
|
||||
{
|
||||
(from == newOwner ? to : from).SendMessage("Only the evil may receive this item.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -69,12 +79,18 @@ namespace Server.Ethics
|
|||
var itemEthic = Find(item);
|
||||
|
||||
if (itemEthic == null || Find(from) == itemEthic)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (itemEthic == Hero)
|
||||
{
|
||||
from.SendMessage("Only heros may wear this item.");
|
||||
}
|
||||
else if (itemEthic == Evil)
|
||||
{
|
||||
from.SendMessage("Only the evil may wear this item.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -84,28 +100,43 @@ namespace Server.Ethics
|
|||
public static bool IsImbued(Item item, bool recurse)
|
||||
{
|
||||
if (Find(item) != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (recurse)
|
||||
{
|
||||
foreach (var child in item.Items)
|
||||
{
|
||||
if (IsImbued(child, true))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
public static void Configure()
|
||||
{
|
||||
Enabled = ServerConfiguration.GetOrUpdateSetting("ethics.enable", false);
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if (Enabled)
|
||||
{
|
||||
EventSink.Speech += EventSink_Speech;
|
||||
}
|
||||
}
|
||||
|
||||
public static void EventSink_Speech(SpeechEventArgs e)
|
||||
{
|
||||
if (e.Blocked || e.Handled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pl = Player.Find(e.Mobile);
|
||||
|
||||
|
|
@ -116,13 +147,19 @@ namespace Server.Ethics
|
|||
var ethic = Ethics[i];
|
||||
|
||||
if (!ethic.IsEligible(e.Mobile))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Insensitive.Equals(ethic.Definition.JoinPhrase.String, e.Speech))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!e.Mobile.GetItemsInRange(2).Any(item => item is AnkhNorth || item is AnkhWest))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pl = new Player(ethic, e.Mobile);
|
||||
|
||||
|
|
@ -138,7 +175,9 @@ namespace Server.Ethics
|
|||
else
|
||||
{
|
||||
if (e.Mobile is PlayerMobile mobile && mobile.DuelContext != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var ethic = pl.Ethic;
|
||||
|
||||
|
|
@ -147,10 +186,14 @@ namespace Server.Ethics
|
|||
var power = ethic.Definition.Powers[i];
|
||||
|
||||
if (!Insensitive.Equals(power.Definition.Phrase.String, e.Speech))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!power.CheckInvoke(pl))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
power.BeginInvoke(pl);
|
||||
e.Handled = true;
|
||||
|
|
@ -169,16 +212,26 @@ namespace Server.Ethics
|
|||
var pl = Player.Find(mob);
|
||||
|
||||
if (pl != null)
|
||||
{
|
||||
return pl.Ethic;
|
||||
}
|
||||
|
||||
if (inherit && mob is BaseCreature bc)
|
||||
{
|
||||
if (bc.Controlled)
|
||||
{
|
||||
return Find(bc.ControlMaster, false);
|
||||
}
|
||||
|
||||
if (bc.Summoned)
|
||||
{
|
||||
return Find(bc.SummonMaster, false);
|
||||
}
|
||||
|
||||
if (allegiance)
|
||||
{
|
||||
return bc.EthicAllegiance;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
@ -201,7 +254,9 @@ namespace Server.Ethics
|
|||
var pl = new Player(this, reader);
|
||||
|
||||
if (pl.Mobile != null)
|
||||
{
|
||||
Timer.DelayCall(pl.CheckAttach);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -216,7 +271,9 @@ namespace Server.Ethics
|
|||
writer.WriteEncodedInt(m_Players.Count);
|
||||
|
||||
for (var i = 0; i < m_Players.Count; ++i)
|
||||
{
|
||||
m_Players[i].Serialize(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace Server.Factions
|
|||
if (faction == null && from.AccessLevel < AccessLevel.GameMaster)
|
||||
return; // TODO: Message?
|
||||
|
||||
if (m_Town.Owner == null || @from.AccessLevel < AccessLevel.GameMaster && faction != m_Town.Owner)
|
||||
if (m_Town.Owner == null || from.AccessLevel < AccessLevel.GameMaster && faction != m_Town.Owner)
|
||||
from.SendLocalizedMessage(1010332); // Your faction does not control this town
|
||||
else if (!m_Town.Owner.IsCommander(from))
|
||||
from.SendLocalizedMessage(1005242); // Only faction Leaders can use townstones
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@ namespace Server.Engines.MLQuests
|
|||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
if (line.Length == 0 || line.StartsWith("#"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var split = line.Split('\t');
|
||||
|
||||
|
|
@ -52,11 +54,13 @@ namespace Server.Engines.MLQuests
|
|||
if (type == null || !baseQuestType.IsAssignableFrom(type))
|
||||
{
|
||||
if (Debug)
|
||||
{
|
||||
Console.WriteLine(
|
||||
"Warning: {1} quest type '{0}'",
|
||||
split[0],
|
||||
type == null ? "Unknown" : "Invalid"
|
||||
);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
|
@ -73,7 +77,9 @@ namespace Server.Engines.MLQuests
|
|||
}
|
||||
|
||||
if (quest == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Register(type, quest);
|
||||
|
||||
|
|
@ -84,11 +90,13 @@ namespace Server.Engines.MLQuests
|
|||
if (questerType == null || !baseQuesterType.IsAssignableFrom(questerType))
|
||||
{
|
||||
if (Debug)
|
||||
{
|
||||
Console.WriteLine(
|
||||
"Warning: {1} quester type '{0}'",
|
||||
split[i],
|
||||
questerType == null ? "Unknown" : "Invalid"
|
||||
);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
|
@ -115,7 +123,9 @@ namespace Server.Engines.MLQuests
|
|||
private static void RegisterQuestGiver(MLQuest quest, Type questerType)
|
||||
{
|
||||
if (!QuestGivers.TryGetValue(questerType, out var questList))
|
||||
{
|
||||
QuestGivers[questerType] = questList = new List<MLQuest>();
|
||||
}
|
||||
|
||||
questList.Add(quest);
|
||||
}
|
||||
|
|
@ -125,20 +135,33 @@ namespace Server.Engines.MLQuests
|
|||
Register(quest.GetType(), quest);
|
||||
|
||||
foreach (var questerType in questerTypes)
|
||||
{
|
||||
RegisterQuestGiver(quest, questerType);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
Enabled = ServerConfiguration.GetOrUpdateSetting("questSystem.enableMLQuests", Core.ML);
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
Enabled = ServerConfiguration.GetOrUpdateSetting("questSystem.enableMLQuests", Core.ML);
|
||||
|
||||
if (!Enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (AutoGenerateNew)
|
||||
{
|
||||
foreach (var quest in Quests.Values)
|
||||
{
|
||||
if (quest?.Deserialized == false)
|
||||
{
|
||||
quest.Generate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MLQuestPersistence.EnsureExistence();
|
||||
|
||||
|
|
@ -205,9 +228,11 @@ namespace Server.Engines.MLQuests
|
|||
m.SendMessage("Serialization for quest {0} is now {1}.", quest.GetType().Name, enable ? "enabled" : "disabled");
|
||||
|
||||
if (AutoGenerateNew && !enable)
|
||||
{
|
||||
m.SendMessage(
|
||||
"Please note that automatic generation of new quests is ON. This quest will be regenerated on the next server start."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Usage("SaveAllQuests [saveEnabled=true]")]
|
||||
|
|
@ -225,14 +250,18 @@ namespace Server.Engines.MLQuests
|
|||
var enable = e.Length == 1 ? e.GetBoolean(0) : true;
|
||||
|
||||
foreach (var quest in Quests.Values)
|
||||
{
|
||||
quest.SaveEnabled = enable;
|
||||
}
|
||||
|
||||
m.SendMessage("Serialization for all quests is now {0}.", enable ? "enabled" : "disabled");
|
||||
|
||||
if (AutoGenerateNew && !enable)
|
||||
{
|
||||
m.SendMessage(
|
||||
"Please note that automatic generation of new quests is ON. All quests will be regenerated on the next server start."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Usage("InvalidQuestItems")]
|
||||
|
|
@ -244,19 +273,29 @@ namespace Server.Engines.MLQuests
|
|||
var found = new List<object>();
|
||||
|
||||
foreach (var item in World.Items.Values)
|
||||
{
|
||||
if (item.QuestItem)
|
||||
{
|
||||
if (item.Parent is Backpack pack)
|
||||
{
|
||||
if (pack.Parent is PlayerMobile player && player.Backpack == pack)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
found.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (found.Count == 0)
|
||||
{
|
||||
m.SendMessage("No matching objects found.");
|
||||
}
|
||||
else
|
||||
{
|
||||
m.SendGump(new InterfaceGump(m, new[] { "Object" }, found, 0, null));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool FindQuest(
|
||||
|
|
@ -272,6 +311,7 @@ namespace Server.Engines.MLQuests
|
|||
|
||||
// 1. Check quests in progress with this NPC (overriding deliveries is intended)
|
||||
if (context != null)
|
||||
{
|
||||
foreach (var questEntry in quests)
|
||||
{
|
||||
var instance = context.FindInstance(questEntry);
|
||||
|
|
@ -284,6 +324,7 @@ namespace Server.Engines.MLQuests
|
|||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Check deliveries (overriding chain offers is intended)
|
||||
if ((entry = HandleDelivery(pm, quester, questerType)) != null)
|
||||
|
|
@ -294,12 +335,16 @@ namespace Server.Engines.MLQuests
|
|||
|
||||
// 3. Check chain quest offers
|
||||
if (context != null)
|
||||
{
|
||||
foreach (var questEntry in quests)
|
||||
{
|
||||
if (questEntry.IsChainTriggered && context.ChainOffers.Contains(questEntry))
|
||||
{
|
||||
quest = questEntry;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Random quest
|
||||
quest = RandomStarterQuest(quester, pm, context);
|
||||
|
|
@ -310,7 +355,9 @@ namespace Server.Engines.MLQuests
|
|||
public static void OnDoubleClick(IQuestGiver quester, PlayerMobile pm)
|
||||
{
|
||||
if (quester.Deleted || !pm.Alive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var context = GetContext(pm);
|
||||
|
||||
|
|
@ -325,13 +372,22 @@ namespace Server.Engines.MLQuests
|
|||
TurnToFace(quester, pm);
|
||||
|
||||
if (entry.Failed)
|
||||
{
|
||||
return; // Note: OSI sends no gump at all for failed quests, they have to be cancelled in the quest overview
|
||||
}
|
||||
|
||||
if (entry.ClaimReward)
|
||||
{
|
||||
entry.SendRewardOffer();
|
||||
}
|
||||
else if (entry.IsCompleted())
|
||||
{
|
||||
entry.SendReportBackGump();
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.SendProgressGump();
|
||||
}
|
||||
}
|
||||
else if (quest.CanOffer(quester, pm, context, true))
|
||||
{
|
||||
|
|
@ -346,9 +402,15 @@ namespace Server.Engines.MLQuests
|
|||
var context = GetContext(pm);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
foreach (var quest in context.QuestInstances)
|
||||
{
|
||||
if (!quest.ClaimReward && quest.AllowsQuestItem(item, type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -358,7 +420,9 @@ namespace Server.Engines.MLQuests
|
|||
var context = GetContext(pm);
|
||||
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var instances = context.QuestInstances;
|
||||
|
||||
|
|
@ -368,14 +432,18 @@ namespace Server.Engines.MLQuests
|
|||
var instance = instances[i];
|
||||
|
||||
if (instance.ClaimReward)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var objective in instance.Objectives)
|
||||
{
|
||||
if (!objective.Expired && objective.AllowsQuestItem(item, type))
|
||||
{
|
||||
objective.CheckComplete(); // yes, this can happen multiple times (for multiple quests)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -399,7 +467,9 @@ namespace Server.Engines.MLQuests
|
|||
var context = GetContext(pm);
|
||||
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var instances = context.QuestInstances;
|
||||
|
||||
|
|
@ -408,15 +478,19 @@ namespace Server.Engines.MLQuests
|
|||
var instance = instances[i];
|
||||
|
||||
if (instance.ClaimReward)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var objective in instance.Objectives)
|
||||
{
|
||||
if (!objective.Expired && objective is GainSkillObjectiveInstance objectiveInstance &&
|
||||
objectiveInstance.Handles(skill))
|
||||
{
|
||||
objectiveInstance.CheckComplete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -425,7 +499,9 @@ namespace Server.Engines.MLQuests
|
|||
var context = GetContext(pm);
|
||||
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var instances = context.QuestInstances;
|
||||
|
||||
|
|
@ -436,13 +512,16 @@ namespace Server.Engines.MLQuests
|
|||
var instance = instances[i];
|
||||
|
||||
if (instance.ClaimReward)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* A kill only counts for a single objective within a quest,
|
||||
* but it can count for multiple quests. This is something not
|
||||
* currently observable on OSI, so it is assumed behavior.
|
||||
*/
|
||||
foreach (var objective in instance.Objectives)
|
||||
{
|
||||
if (!objective.Expired && objective is KillObjectiveInstance kill)
|
||||
{
|
||||
type ??= mob.GetType();
|
||||
|
|
@ -453,6 +532,7 @@ namespace Server.Engines.MLQuests
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -461,7 +541,9 @@ namespace Server.Engines.MLQuests
|
|||
var context = GetContext(pm);
|
||||
|
||||
if (context == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var instances = context.QuestInstances;
|
||||
MLQuestInstance deliverInstance = null;
|
||||
|
|
@ -476,6 +558,7 @@ namespace Server.Engines.MLQuests
|
|||
|
||||
foreach (var objective in instance.Objectives)
|
||||
// Note: On OSI, expired deliveries can still be completed. Bug?
|
||||
{
|
||||
if (!objective.Expired && objective is DeliverObjectiveInstance deliver &&
|
||||
deliver.IsDestination(quester, questerType))
|
||||
{
|
||||
|
|
@ -492,6 +575,7 @@ namespace Server.Engines.MLQuests
|
|||
|
||||
break; // don't return, we may have to complete more deliveries
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return deliverInstance;
|
||||
|
|
@ -507,7 +591,9 @@ namespace Server.Engines.MLQuests
|
|||
public static MLQuestContext GetOrCreateContext(PlayerMobile pm)
|
||||
{
|
||||
if (!Contexts.TryGetValue(pm, out var context))
|
||||
{
|
||||
Contexts[pm] = context = new MLQuestContext(pm);
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
|
@ -541,7 +627,9 @@ namespace Server.Engines.MLQuests
|
|||
var instance = instances[i];
|
||||
|
||||
if (instance.Quester == quester)
|
||||
{
|
||||
instance.OnQuesterDeleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -549,7 +637,9 @@ namespace Server.Engines.MLQuests
|
|||
public static void EventSink_QuestGumpRequest(Mobile m)
|
||||
{
|
||||
if (!Enabled || !(m is PlayerMobile pm))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pm.SendGump(new QuestLogGump(pm));
|
||||
}
|
||||
|
|
@ -559,7 +649,9 @@ namespace Server.Engines.MLQuests
|
|||
var quests = quester.MLQuests;
|
||||
|
||||
if (quests.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
m_EligiblePool.Clear();
|
||||
MLQuest fallback = null;
|
||||
|
|
@ -567,7 +659,9 @@ namespace Server.Engines.MLQuests
|
|||
foreach (var quest in quests)
|
||||
{
|
||||
if (quest.IsChainTriggered || context?.IsDoingQuest(quest) == true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save first quest that reaches the CanOffer call.
|
||||
|
|
@ -576,7 +670,9 @@ namespace Server.Engines.MLQuests
|
|||
fallback ??= quest;
|
||||
|
||||
if (quest.CanOffer(quester, pm, context, false))
|
||||
{
|
||||
m_EligiblePool.Add(quest);
|
||||
}
|
||||
}
|
||||
|
||||
return m_EligiblePool.Count == 0 ? fallback : m_EligiblePool.RandomElement();
|
||||
|
|
@ -585,7 +681,9 @@ namespace Server.Engines.MLQuests
|
|||
public static void TurnToFace(IQuestGiver quester, Mobile mob)
|
||||
{
|
||||
if (quester is Mobile m)
|
||||
{
|
||||
m.Direction = m.GetDirectionTo(mob);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Tell(IQuestGiver quester, PlayerMobile pm, int cliloc)
|
||||
|
|
@ -593,11 +691,17 @@ namespace Server.Engines.MLQuests
|
|||
TurnToFace(quester, pm);
|
||||
|
||||
if (quester is Mobile mobile)
|
||||
{
|
||||
mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, cliloc, pm.NetState);
|
||||
}
|
||||
else if (quester is Item item)
|
||||
{
|
||||
MessageHelper.SendLocalizedMessageTo(item, pm, cliloc, SpeechColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
pm.SendLocalizedMessage(cliloc);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Tell(IQuestGiver quester, PlayerMobile pm, int cliloc, string args)
|
||||
|
|
@ -605,11 +709,17 @@ namespace Server.Engines.MLQuests
|
|||
TurnToFace(quester, pm);
|
||||
|
||||
if (quester is Mobile mobile)
|
||||
{
|
||||
mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, cliloc, args, pm.NetState);
|
||||
}
|
||||
else if (quester is Item item)
|
||||
{
|
||||
MessageHelper.SendLocalizedMessageTo(item, pm, cliloc, args, SpeechColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
pm.SendLocalizedMessage(cliloc, args);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Tell(IQuestGiver quester, PlayerMobile pm, string message)
|
||||
|
|
@ -617,22 +727,34 @@ namespace Server.Engines.MLQuests
|
|||
TurnToFace(quester, pm);
|
||||
|
||||
if (quester is Mobile mobile)
|
||||
{
|
||||
mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, false, message, pm.NetState);
|
||||
}
|
||||
else if (quester is Item item)
|
||||
{
|
||||
MessageHelper.SendMessageTo(item, pm, message, SpeechColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
pm.SendMessage(SpeechColor, message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void TellDef(IQuestGiver quester, PlayerMobile pm, TextDefinition def)
|
||||
{
|
||||
if (def == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (def.Number > 0)
|
||||
{
|
||||
Tell(quester, pm, def.Number);
|
||||
}
|
||||
else if (def.String != null)
|
||||
{
|
||||
Tell(quester, pm, def.String);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteQuestRef(IGenericWriter writer, MLQuest quest)
|
||||
|
|
@ -645,12 +767,16 @@ namespace Server.Engines.MLQuests
|
|||
var typeName = reader.ReadString();
|
||||
|
||||
if (typeName == null)
|
||||
{
|
||||
return null; // not serialized
|
||||
}
|
||||
|
||||
var questType = AssemblyHandler.FindFirstTypeForName(typeName);
|
||||
|
||||
if (questType == null)
|
||||
{
|
||||
return null; // no longer a type
|
||||
}
|
||||
|
||||
return FindQuest(questType);
|
||||
}
|
||||
|
|
@ -713,9 +839,13 @@ namespace Server.Engines.MLQuests
|
|||
public override void Execute(CommandEventArgs e, object obj)
|
||||
{
|
||||
if (!(obj is PlayerMobile pm))
|
||||
{
|
||||
LogFailure("They have no ML quest context.");
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendGump(new PropertiesGump(e.Mobile, GetOrCreateContext(pm)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,38 +18,38 @@ namespace Server.Engines.PartySystem
|
|||
|
||||
if (from == m)
|
||||
{
|
||||
@from.SendLocalizedMessage(1005439); // You cannot add yourself to a party.
|
||||
from.SendLocalizedMessage(1005439); // You cannot add yourself to a party.
|
||||
}
|
||||
else if (p != null && p.Leader != from)
|
||||
{
|
||||
@from.SendLocalizedMessage(1005453); // You may only add members to the party if you are the leader.
|
||||
from.SendLocalizedMessage(1005453); // You may only add members to the party if you are the leader.
|
||||
}
|
||||
else if (m.Party is Mobile)
|
||||
{
|
||||
}
|
||||
else if (p != null && p.Members.Count + p.Candidates.Count >= Party.Capacity)
|
||||
{
|
||||
@from.SendLocalizedMessage(1008095); // You may only have 10 in your party (this includes candidates).
|
||||
from.SendLocalizedMessage(1008095); // You may only have 10 in your party (this includes candidates).
|
||||
}
|
||||
else if (!m.Player && m.Body.IsHuman)
|
||||
{
|
||||
m.SayTo(@from, 1005443); // Nay, I would rather stay here and watch a nail rust.
|
||||
m.SayTo(from, 1005443); // Nay, I would rather stay here and watch a nail rust.
|
||||
}
|
||||
else if (!m.Player)
|
||||
{
|
||||
@from.SendLocalizedMessage(1005444); // The creature ignores your offer.
|
||||
from.SendLocalizedMessage(1005444); // The creature ignores your offer.
|
||||
}
|
||||
else if (mp != null && mp == p)
|
||||
{
|
||||
@from.SendLocalizedMessage(1005440); // This person is already in your party!
|
||||
from.SendLocalizedMessage(1005440); // This person is already in your party!
|
||||
}
|
||||
else if (mp != null)
|
||||
{
|
||||
@from.SendLocalizedMessage(1005441); // This person is already in a party!
|
||||
from.SendLocalizedMessage(1005441); // This person is already in a party!
|
||||
}
|
||||
else
|
||||
{
|
||||
Party.Invite(@from, m);
|
||||
Party.Invite(from, m);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server
|
|||
|
||||
public IPoint3D Goal { get; }
|
||||
|
||||
public static void Initialize()
|
||||
public static void Configure()
|
||||
{
|
||||
Enabled = ServerConfiguration.GetOrUpdateSetting("pathfinding.enable", true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,8 +284,8 @@ namespace Server.Engines.Plants
|
|||
}
|
||||
|
||||
public bool IsUsableBy(Mobile from) =>
|
||||
IsChildOf(from.Backpack) || IsChildOf(from.FindBankNoCreate()) || IsLockedDown && IsAccessibleTo(@from) ||
|
||||
RootParent is Item root && root.IsSecure && root.IsAccessibleTo(@from);
|
||||
IsChildOf(from.Backpack) || IsChildOf(from.FindBankNoCreate()) || IsLockedDown && IsAccessibleTo(from) ||
|
||||
RootParent is Item root && root.IsSecure && root.IsAccessibleTo(from);
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ namespace Server.Engines.Quests.Doom
|
|||
);
|
||||
Effects.PlaySound(loc, Map, 0x1FE);
|
||||
|
||||
Chyloth = new Chyloth { Direction = (Direction)(7 & (4 + (int)@from.GetDirectionTo(loc))) };
|
||||
Chyloth = new Chyloth { Direction = (Direction)(7 & (4 + (int)from.GetDirectionTo(loc))) };
|
||||
|
||||
Chyloth.MoveToWorld(loc, Map);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ namespace Server.Engines.VeteranRewards
|
|||
get
|
||||
{
|
||||
if (m_Categories == null)
|
||||
{
|
||||
SetupRewardTables();
|
||||
}
|
||||
|
||||
return m_Categories;
|
||||
}
|
||||
|
|
@ -33,7 +35,9 @@ namespace Server.Engines.VeteranRewards
|
|||
get
|
||||
{
|
||||
if (m_Lists == null)
|
||||
{
|
||||
SetupRewardTables();
|
||||
}
|
||||
|
||||
return m_Lists;
|
||||
}
|
||||
|
|
@ -45,15 +49,22 @@ namespace Server.Engines.VeteranRewards
|
|||
|
||||
for (var j = 0; j < entries.Count; ++j)
|
||||
// RewardEntry entry = entries[j];
|
||||
{
|
||||
if (HasAccess(mob, entries[j]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool HasAccess(Mobile mob, RewardEntry entry)
|
||||
{
|
||||
if (Core.Expansion < entry.RequiredExpansion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return HasAccess(mob, entry.List, out var _);
|
||||
}
|
||||
|
|
@ -77,7 +88,9 @@ namespace Server.Engines.VeteranRewards
|
|||
ts = list.Age - totalTime;
|
||||
|
||||
if (ts <= TimeSpan.Zero)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -85,7 +98,9 @@ namespace Server.Engines.VeteranRewards
|
|||
public static int GetRewardLevel(Mobile mob)
|
||||
{
|
||||
if (!(mob.Account is Account acct))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return GetRewardLevel(acct);
|
||||
}
|
||||
|
|
@ -100,7 +115,9 @@ namespace Server.Engines.VeteranRewards
|
|||
public static bool HasHalfLevel(Mobile mob)
|
||||
{
|
||||
if (!(mob.Account is Account acct))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return HasHalfLevel(acct);
|
||||
}
|
||||
|
|
@ -119,10 +136,14 @@ namespace Server.Engines.VeteranRewards
|
|||
ComputeRewardInfo(mob, out var cur, out var max);
|
||||
|
||||
if (cur >= max)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(mob.Account is Account acct))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// if (mob.AccessLevel < AccessLevel.GameMaster)
|
||||
acct.SetTag("numRewardsChosen", (cur + 1).ToString());
|
||||
|
|
@ -154,14 +175,22 @@ namespace Server.Engines.VeteranRewards
|
|||
var tag = acct.GetTag("numRewardsChosen");
|
||||
|
||||
if (string.IsNullOrEmpty(tag))
|
||||
{
|
||||
cur = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur = Utility.ToInt32(tag);
|
||||
}
|
||||
|
||||
if (level >= 6)
|
||||
{
|
||||
max = 9 + (level - 6) * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = 2 + level;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CheckIsUsableBy(Mobile from, Item item, object[] args = null)
|
||||
|
|
@ -178,12 +207,16 @@ namespace Server.Engines.VeteranRewards
|
|||
for (var j = 0; j < entries.Length; ++j)
|
||||
{
|
||||
if (entries[j].ItemType != type)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (args == null && entries[j].Args.Length == 0)
|
||||
{
|
||||
if (isRelaxedRules && i <= 0 || HasAccess(from, list, out var ts))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
from.SendLocalizedMessage(
|
||||
1008126,
|
||||
|
|
@ -195,17 +228,23 @@ namespace Server.Engines.VeteranRewards
|
|||
}
|
||||
|
||||
if (args?.Length != entries[j].Args.Length)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var match = true;
|
||||
|
||||
for (var k = 0; match && k < args.Length; ++k)
|
||||
{
|
||||
match = args[k].Equals(entries[j].Args[k]);
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
if (isRelaxedRules && i <= 0 || HasAccess(from, list, out var ts))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
from.SendLocalizedMessage(
|
||||
1008126,
|
||||
|
|
@ -240,22 +279,30 @@ namespace Server.Engines.VeteranRewards
|
|||
var entries = list.Entries;
|
||||
|
||||
for (var j = 0; j < entries.Length; ++j)
|
||||
{
|
||||
if (entries[j].ItemType == type)
|
||||
{
|
||||
if (args == null && entries[j].Args.Length == 0)
|
||||
{
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
if (args?.Length == entries[j].Args.Length)
|
||||
{
|
||||
var match = true;
|
||||
|
||||
for (var k = 0; match && k < args.Length; ++k)
|
||||
{
|
||||
match = args[k].Equals(entries[j].Args[k]);
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no entry?
|
||||
|
|
@ -532,20 +579,27 @@ namespace Server.Engines.VeteranRewards
|
|||
};
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
public static void Configure()
|
||||
{
|
||||
Enabled = ServerConfiguration.GetOrUpdateSetting("vetRewards.enable", true);
|
||||
SkillCapRewards = ServerConfiguration.GetOrUpdateSetting("vetRewards.skillCapRewards", true);
|
||||
RewardInterval = ServerConfiguration.GetOrUpdateSetting("vetRewards.rewardInterval", TimeSpan.FromDays(30.0));
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if (Enabled)
|
||||
{
|
||||
EventSink.Login += EventSink_Login;
|
||||
}
|
||||
}
|
||||
|
||||
private static void EventSink_Login(Mobile m)
|
||||
{
|
||||
if (!m.Alive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ComputeRewardInfo(m, out var cur, out var max, out var level);
|
||||
|
||||
|
|
@ -555,9 +609,13 @@ namespace Server.Engines.VeteranRewards
|
|||
level = Math.Clamp(level, 0, 4);
|
||||
|
||||
if (SkillCapRewards)
|
||||
{
|
||||
m.SkillsCap = 7000 + level * 50;
|
||||
}
|
||||
else
|
||||
{
|
||||
m.SkillsCap = 7000;
|
||||
}
|
||||
}
|
||||
|
||||
if (Core.ML && m is PlayerMobile pm && !pm.HasStatReward && HasHalfLevel(pm))
|
||||
|
|
@ -567,7 +625,9 @@ namespace Server.Engines.VeteranRewards
|
|||
}
|
||||
|
||||
if (cur < max)
|
||||
{
|
||||
m.SendGump(new RewardNoticeGump(m));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue