Changed how Quest ENPCs work. They should now automatically update themselves whenever data is update for immediate effect changes. Fixed wrong map qflag value. Fixed quest gm command. Fixed Director actorId clobbering areaMasters.

This commit is contained in:
Filip Maj 2022-02-06 12:12:26 -05:00
parent b11007b263
commit 8b3431e557
8 changed files with 180 additions and 179 deletions

View file

@ -1550,23 +1550,20 @@ namespace Meteor.Map.Actors
}
}
public void ReplaceQuest(uint oldId, uint newId)
public void ReplaceQuest(Quest oldQuest, string questCode)
{
if (HasQuest(oldId))
for (int i = 0; i < questScenario.Length; i++)
{
for (int i = 0; i < questScenario.Length; i++)
if (questScenario[i] != null && questScenario[i].Equals(oldQuest))
{
if (questScenario[i] != null && questScenario[i].GetQuestId() == oldId)
{
Quest baseQuest = (Quest) Server.GetStaticActors((0xA0F00000 | newId));
playerWork.questScenario[i] = (0xA0F00000 | newId);
questScenario[i] = new Quest(this, baseQuest);
Database.SaveQuest(this, questScenario[i]);
SendQuestClientUpdate(i);
break;
}
Quest baseQuest = (Quest) Server.GetStaticActors(questCode);
questScenario[i] = new Quest(this, baseQuest);
playerWork.questScenario[i] = questScenario[i].Id;
Database.SaveQuest(this, questScenario[i]);
SendQuestClientUpdate(i);
break;
}
}
}
}
public bool CanAcceptQuest(string name)
@ -1638,6 +1635,11 @@ namespace Meteor.Map.Actors
return false;
}
public bool HasQuest(Quest quest)
{
return HasQuest(quest.className);
}
public bool HasGuildleve(uint id)
{
for (int i = 0; i < work.guildleveId.Length; i++)

View file

@ -46,7 +46,7 @@ namespace Meteor.Map.actors.director
private Coroutine currentCoroutine;
public Director(uint id, Area zone, string directorPath, bool hasContentGroup, params object[] args)
: base((6 << 28 | zone.CurrentArea.ZoneId << 19 | (uint)id))
: base((6 << 28 | zone.ZoneId << 19 | (uint)id + 2))
{
directorId = id;
CurrentArea = zone;

View file

@ -51,6 +51,24 @@ namespace Meteor.Map.Actors
this.isEmoteEnabled = isEmoteEnabled;
this.isPushEnabled = isPushEnabled;
}
public bool IsChanged(byte flagType, bool isTalkEnabled, bool isPushEnabled, bool isEmoteEnabled, bool isSpawned)
{
return flagType != this.questFlagType
|| isTalkEnabled != this.isTalkEnabled
|| isPushEnabled != this.isPushEnabled
|| isEmoteEnabled != this.isEmoteEnabled
|| isSpawned != this.isSpawned;
}
public void Update(byte flagType, bool isTalkEnabled, bool isPushEnabled, bool isEmoteEnabled, bool isSpawned)
{
this.questFlagType = flagType;
this.isSpawned = isSpawned;
this.isTalkEnabled = isTalkEnabled;
this.isEmoteEnabled = isEmoteEnabled;
this.isPushEnabled = isPushEnabled;
}
}
private struct QuestData
@ -73,65 +91,44 @@ namespace Meteor.Map.Actors
private Player Owner;
private ushort currentSequence;
private QuestData data = new QuestData();
private Dictionary<uint, ENpcQuestInstance> ActiveENpcs = new Dictionary<uint, ENpcQuestInstance>();
private bool dataDirty = false;
private Dictionary<uint, ENpcQuestInstance> CurrentENPCs = new Dictionary<uint, ENpcQuestInstance>();
private Dictionary<uint, ENpcQuestInstance> OldENPCs = new Dictionary<uint, ENpcQuestInstance>();
public void AddENpc(uint classId, byte flagType = 0, bool isTalkEnabled = true, bool isEmoteEnabled = false, bool isPushEnabled = false, bool isSpawned = false)
public void AddENpc(uint classId, byte flagType = 0, bool isTalkEnabled = true, bool isPushEnabled = false, bool isEmoteEnabled = false, bool isSpawned = false)
{
if (ActiveENpcs.ContainsKey(classId))
return;
ENpcQuestInstance instanceUpdated = null;
ENpcQuestInstance instance = new ENpcQuestInstance(classId, flagType, isSpawned, isTalkEnabled, isEmoteEnabled, isPushEnabled);
ActiveENpcs.Add(classId, instance);
Owner.playerSession.UpdateQuestNpcInInstance(instance);
}
public void ClearENpcs()
{
foreach (ENpcQuestInstance instance in ActiveENpcs.Values)
Owner.playerSession.UpdateQuestNpcInInstance(instance, true);
ActiveENpcs.Clear();
}
public void UpdateENpc(uint classId, ENpcProperty property, object value)
{
if (!ActiveENpcs.ContainsKey(classId))
return;
ENpcQuestInstance instance = ActiveENpcs[classId];
switch (property)
if (OldENPCs.ContainsKey(classId))
{
case ENpcProperty.QuestFlag:
if (value is double)
instance.questFlagType = (byte)(double)value;
else if (value is int)
instance.questFlagType = (byte)value;
break;
case ENpcProperty.CanTalk:
instance.isTalkEnabled = (bool)value;
break;
case ENpcProperty.CanPush:
instance.isPushEnabled = (bool)value;
break;
case ENpcProperty.CanEmote:
instance.isEmoteEnabled = (bool)value;
break;
if (OldENPCs[classId].IsChanged(flagType, isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned))
{
instanceUpdated = OldENPCs[classId];
instanceUpdated.Update(flagType, isTalkEnabled, isPushEnabled, isEmoteEnabled, isSpawned);
CurrentENPCs.Add(classId, instanceUpdated);
}
OldENPCs.Remove(classId);
}
else
{
instanceUpdated = new ENpcQuestInstance(classId, flagType, isSpawned, isTalkEnabled, isEmoteEnabled, isPushEnabled);
CurrentENPCs.Add(classId, instanceUpdated);
}
Owner.playerSession.UpdateQuestNpcInInstance(instance, false);
if (instanceUpdated != null)
Owner.playerSession.UpdateQuestNpcInInstance(instanceUpdated);
}
public ENpcQuestInstance GetENpcInstance(uint classId)
{
if (ActiveENpcs.ContainsKey(classId))
return ActiveENpcs[classId];
if (CurrentENPCs.ContainsKey(classId))
return CurrentENPCs[classId];
return null;
}
public void OnTalk(Player caller, Npc npc)
{
LuaEngine.GetInstance().CallLuaFunction(caller, this, "onTalk", true, npc);
LuaEngine.GetInstance().CallLuaFunction(caller, this, "onTalk", true, npc);
}
public void OnEmote(Player caller, Npc npc, Command command)
@ -154,11 +151,25 @@ namespace Meteor.Map.Actors
LuaEngine.GetInstance().CallLuaFunction(caller, this, "onNpcLS", true, npcLSId);
}
public void UpdateENPCs()
{
if (dataDirty)
{
OldENPCs = CurrentENPCs;
CurrentENPCs = new Dictionary<uint, ENpcQuestInstance>();
LuaEngine.GetInstance().CallLuaFunctionForReturn(Owner, this, "onSequence", false, currentSequence);
foreach (var enpc in OldENPCs)
Owner.playerSession.UpdateQuestNpcInInstance(enpc.Value);
OldENPCs = null;
dataDirty = false;
}
}
public bool IsQuestENPC(Player caller, Npc npc)
{
List<LuaParam> returned = LuaEngine.GetInstance().CallLuaFunctionForReturn(caller, this, "IsQuestENPC", true, npc, this);
bool scriptReturned = returned != null && returned.Count != 0 && returned[0].typeID == 3;
return scriptReturned || ActiveENpcs.ContainsKey(npc.GetActorClassId());
return scriptReturned || CurrentENPCs.ContainsKey(npc.GetActorClassId());
}
@ -195,7 +206,8 @@ namespace Meteor.Map.Actors
Owner.SendGameMessage(Server.GetWorldManager().GetActor(), 25116, 0x20, (object)GetQuestId());
currentSequence = sequence;
LuaEngine.GetInstance().CallLuaFunction(Owner, this, "onSequence", false, currentSequence);
dataDirty = true;
UpdateENPCs();
}
public void ClearData()
@ -206,70 +218,88 @@ namespace Meteor.Map.Actors
public void SetFlag(int index)
{
if (index >= 0 && index < 32)
{
data.flags |= (uint)(1 << index);
dataDirty = true;
}
}
public void ClearFlag(int index)
{
if (index >= 0 && index < 32)
{
data.flags &= (uint)~(1 << index);
dataDirty = true;
}
}
public void IncCounter(int num)
{
dataDirty = true;
switch (num)
{
case 0:
data.counter1++;
break;
return;
case 1:
data.counter2++;
break;
return;
case 2:
data.counter3++;
break;
return;
case 3:
data.counter4++;
break;
}
return;
}
dataDirty = false;
}
public void DecCounter(int num)
{
dataDirty = true;
switch (num)
{
case 0:
data.counter1--;
break;
return;
case 1:
data.counter2--;
break;
return;
case 2:
data.counter3--;
break;
return;
case 3:
data.counter4--;
break;
return;
}
dataDirty = false;
}
public void SetCounter(int num, ushort value)
{
dataDirty = true;
switch (num)
{
case 0:
data.counter1 = value;
break;
return;
case 1:
data.counter2 = value;
break;
return;
case 2:
data.counter3 = value;
break;
return;
case 3:
data.counter4 = value;
break;
return;
}
dataDirty = false;
}
public bool GetFlag(int index)

View file

@ -39,6 +39,9 @@ using Meteor.Map.actors.chara.ai;
using Meteor.Map.actors.chara.ai.controllers;
using Meteor.Map.DataObjects;
using Meteor.Map.actors.chara.player;
using Meteor.Map.Actors.Chara;
using Meteor.Map.dataobjects.chara;
using Meteor.Map.actors.chara;
namespace Meteor.Map.lua
{
@ -69,12 +72,16 @@ namespace Meteor.Map.lua
UserData.RegisterType<LuaEngine>();
UserData.RegisterType<Player>();
UserData.RegisterType<CharaWork>();
UserData.RegisterType<ParameterSave>();
UserData.RegisterType<PlayerWork>();
UserData.RegisterType<Command>();
UserData.RegisterType<Npc>();
UserData.RegisterType<Quest>();
UserData.RegisterType<Zone>();
UserData.RegisterType<InventoryItem>();
UserData.RegisterType<ItemPackage>();
UserData.RegisterType<ReferencedItemPackage>();
UserData.RegisterType<PrivateArea>();
UserData.RegisterType<PrivateAreaContent>();
UserData.RegisterType<Director>();