Got Fade to White 99% scripted out. Got Path Companion data all setup and saving/loading. Fixed the BgKeepouts and they properly show their msgs. Added quests to MarketEntrances. Fixed MarketEntrances. Hooked cutscene book to the Patch Companion you use.

This commit is contained in:
Filip Maj 2022-04-12 01:06:12 -04:00
parent a5a039ce3d
commit ac22637b4f
11 changed files with 633 additions and 33 deletions

View file

@ -167,6 +167,12 @@ namespace Meteor.Map.Actors
private List<Director> ownedDirectors = new List<Director>();
private Director loginInitDirector = null;
//SNpc (Path Companion)
public string SNpcNickname { set; get; }
public byte SNpcSkin { set; get; }
public byte SNpcPersonality { set; get; }
public short SNpcCoordinate { set; get; }
List<ushort> hotbarSlotsToUpdate = new List<ushort>();
public PlayerWork playerWork = new PlayerWork();
@ -270,6 +276,11 @@ namespace Meteor.Map.Actors
charaWork.parameterTemp.tp = 0;
SNpcNickname = "???";
SNpcSkin = 1;
SNpcPersonality = 1;
SNpcCoordinate = 1;
Database.LoadPlayerCharacter(this);
lastPlayTimeUpdate = Utils.UnixTimeStampUTC();
@ -408,7 +419,7 @@ namespace Meteor.Map.Actors
bool[] testComplete = new bool[2048]; //TODO: Change to playerwork.scenarioComplete
for (int i = 0; i < 2048; i++)
testComplete[i] = true;
QueuePacket(cutsceneBookPacket.BuildPacket(Id, "<Path Companion>", 11, 1, 1, testComplete));
QueuePacket(cutsceneBookPacket.BuildPacket(Id, SNpcNickname, SNpcSkin, SNpcPersonality, SNpcCoordinate, testComplete));
QueuePacket(SetPlayerDreamPacket.BuildPacket(Id, 0x16, GetInnCode()));
}
@ -1729,6 +1740,85 @@ namespace Meteor.Map.Actors
}
#endregion
#region SNpc Functions (Path Companion)
public void SetSNpc(string nickname, uint actorClassId, byte classType)
{
// Set name and appearance
SNpcNickname = nickname;
SNpcSkin = (byte) (actorClassId - 1070000);
switch (SNpcSkin % 16)
{
// Hyur Male
case 1:
SNpcPersonality = 1;
break;
// Hyur Female
case 2:
case 16:
SNpcPersonality = 2;
break;
// Elezen Male
case 3:
case 4:
SNpcPersonality = 3;
break;
// Elezen Female
case 5:
case 6:
SNpcPersonality = 4;
break;
// Lalafel Male
case 7:
case 8:
SNpcPersonality = 5;
break;
// Lalafel Female
case 9:
case 10:
SNpcPersonality = 6;
break;
// Miqo'te
case 11:
case 12:
SNpcPersonality = 8;
break;
// Roegadyn
case 13:
case 14:
SNpcPersonality = 7;
break;
// Highlander
case 15:
SNpcPersonality = 9;
break;
}
// Save to DB
Database.CreateOrUpdateSNpc(this, SNpcNickname, SNpcSkin, SNpcPersonality);
}
public string GetSNpcNickname()
{
return SNpcNickname ?? "???";
}
public byte GetSNpcSkin()
{
return SNpcSkin;
}
public byte GetSNpcPersonality()
{
return SNpcPersonality;
}
public short GetSNpcCoordinate()
{
return SNpcCoordinate;
}
#endregion
#region Guildleves
public void AddGuildleve(uint id)
{
@ -1867,49 +1957,58 @@ namespace Meteor.Map.Actors
return false;
}
public void SetNpcLs(uint npcLSId, uint state)
public void AddNpcLs(uint npcLsId)
{
if (playerWork.npcLinkshellChatExtra[npcLsId] == false && playerWork.npcLinkshellChatCalling[npcLsId] == false)
{
SetNpcLs(npcLsId, NPCLS_INACTIVE);
SendGameMessage(Server.GetWorldManager().GetActor(), 25118, 0x20, npcLsId); // "<NpcLs> linkpearl obtained."
}
}
public void SetNpcLs(uint npcLsId, uint state)
{
bool isCalling, isExtra;
isCalling = isExtra = false;
if (npcLSId < 1 || npcLSId > 40)
if (npcLsId < 1 || npcLsId > 40)
return;
npcLSId--;
npcLsId--;
switch (state)
{
case NPCLS_INACTIVE:
if (playerWork.npcLinkshellChatExtra[npcLSId] == true && playerWork.npcLinkshellChatCalling[npcLSId] == false)
if (playerWork.npcLinkshellChatExtra[npcLsId] == true && playerWork.npcLinkshellChatCalling[npcLsId] == false)
return;
isExtra = true;
break;
case NPCLS_ACTIVE:
if (playerWork.npcLinkshellChatExtra[npcLSId] == false && playerWork.npcLinkshellChatCalling[npcLSId] == true)
if (playerWork.npcLinkshellChatExtra[npcLsId] == false && playerWork.npcLinkshellChatCalling[npcLsId] == true)
return;
isCalling = true;
break;
case NPCLS_ALERT:
if (playerWork.npcLinkshellChatExtra[npcLSId] == true && playerWork.npcLinkshellChatCalling[npcLSId] == true)
if (playerWork.npcLinkshellChatExtra[npcLsId] == true && playerWork.npcLinkshellChatCalling[npcLsId] == true)
return;
isExtra = isCalling = true;
break;
}
playerWork.npcLinkshellChatExtra[npcLSId] = isExtra;
playerWork.npcLinkshellChatCalling[npcLSId] = isCalling;
playerWork.npcLinkshellChatExtra[npcLsId] = isExtra;
playerWork.npcLinkshellChatCalling[npcLsId] = isCalling;
Database.SaveNpcLS(this, npcLSId, isCalling, isExtra);
Database.SaveNpcLS(this, npcLsId, isCalling, isExtra);
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("playerWork/npcLinkshellChat", this);
propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatExtra[{0}]", npcLSId));
propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatCalling[{0}]", npcLSId));
propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatExtra[{0}]", npcLsId));
propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatCalling[{0}]", npcLsId));
QueuePackets(propPacketUtil.Done());
}
@ -2069,7 +2168,7 @@ namespace Meteor.Map.Actors
return;
List<LuaParam> lParams = LuaUtils.CreateLuaParamList(parameters);
SubPacket spacket = KickEventPacket.BuildPacket(Id, actor.Id, eventName, 0, lParams);
SubPacket spacket = KickEventPacket.BuildPacket(Id, actor.Id, eventName, 5, lParams);
spacket.DebugPrintSubPacket();
QueuePacket(spacket);
}

View file

@ -82,7 +82,7 @@ namespace Meteor.Map.actors
public class PushBoxEventCondition
{
public bool isEnabled = true;
public uint bgObj;
public uint instance;
public uint layout;
public string conditionName = "";
public string reactName = "";

View file

@ -1326,6 +1326,28 @@ namespace Meteor.Map
}
}
//Load Path Companion
query = @"
SELECT
nickname,
skin,
personality,
coordinate
FROM characters_snpc WHERE characterId = @charId";
cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charId", player.Id);
using (MySqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
player.SNpcNickname = reader.GetString("nickname");
player.SNpcSkin = reader.GetByte("skin");
player.SNpcPersonality = reader.GetByte("personality");
player.SNpcCoordinate = reader.GetInt16("coordinate");
}
}
player.GetItemPackage(ItemPackage.NORMAL).InitList(GetItemPackage(player, 0, ItemPackage.NORMAL));
player.GetItemPackage(ItemPackage.KEYITEMS).InitList(GetItemPackage(player, 0, ItemPackage.KEYITEMS));
player.GetItemPackage(ItemPackage.CURRENCY_CRYSTALS).InitList(GetItemPackage(player, 0, ItemPackage.CURRENCY_CRYSTALS));
@ -1347,6 +1369,40 @@ namespace Meteor.Map
}
public static void CreateOrUpdateSNpc(Player player, string nickname, uint skin, byte personality)
{
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
{
try
{
conn.Open();
string query = @"
INSERT INTO characters_snpc
(characterId, nickname, skin, personality)
VALUES
(@charId, @nickname, @skin, @personality)
ON DUPLICATE KEY UPDATE
nickname = @nickname, skin = @skin, personality = @personality
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charId", player.Id);
cmd.Parameters.AddWithValue("@nickname", nickname);
cmd.Parameters.AddWithValue("@skin", skin);
cmd.Parameters.AddWithValue("@personality", personality);
cmd.ExecuteNonQuery();
}
catch (MySqlException e)
{
Program.Log.Error(e.ToString());
}
finally
{
conn.Dispose();
}
}
}
public static InventoryItem[] GetEquipment(Player player, ushort classId)
{
InventoryItem[] equipment = new InventoryItem[player.GetEquipment().GetCapacity()];

View file

@ -42,6 +42,7 @@ using Meteor.Map.DataObjects.chara;
using Meteor.Map.actors.chara;
using Meteor.Map.Actors.QuestNS;
using Meteor.Map.actors.group;
using static Meteor.Map.LuaUtils;
namespace Meteor.Map.lua
{
@ -82,6 +83,12 @@ namespace Meteor.Map.lua
UserData.RegisterType<ContentGroup>();
UserData.RegisterType<Zone>();
UserData.RegisterType<InventoryItem>();
UserData.RegisterType<ItemRefParam>();
UserData.RegisterType<Type9Param>();
UserData.RegisterType<WeaponItem>();
UserData.RegisterType<ArmorItem>();
UserData.RegisterType<EquipmentItem>();
UserData.RegisterType<ItemData>();
UserData.RegisterType<ItemPackage>();
UserData.RegisterType<ReferencedItemPackage>();
UserData.RegisterType<PrivateArea>();
@ -643,6 +650,9 @@ namespace Meteor.Map.lua
public void EventStarted(Player player, Actor target, EventStartPacket eventStart)
{
if (eventStart.luaParams == null)
return;
List<LuaParam> lparams = new List<LuaParam>();
lparams.AddRange(eventStart.luaParams);
lparams.Insert(0, new LuaParam(0, eventStart.eventType));

View file

@ -45,7 +45,7 @@ namespace Meteor.Map.packets.send.actor.events
binWriter.Write((UInt32)0x44533088);
binWriter.Write((Single)100.0f);
binWriter.Seek(4, SeekOrigin.Current);
binWriter.Write((Byte)(condition.outwards ? 0x10 : 0x1)); //If == 0x10, Inverted Bounding Box
binWriter.Write((Byte)(condition.outwards ? 0x10 : 0x0)); //If == 0x10, Inverted Bounding Box
binWriter.Write((Byte)0);
binWriter.Write((Byte)(condition.silent ? 0x1 : 0x0)); //Silent Trigger
binWriter.Write(Encoding.ASCII.GetBytes(condition.conditionName), 0, Encoding.ASCII.GetByteCount(condition.conditionName) >= 0x24 ? 0x24 : Encoding.ASCII.GetByteCount(condition.conditionName));

View file

@ -41,7 +41,7 @@ namespace Meteor.Map.packets.send.actor.events
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)condition.bgObj); // bgObj
binWriter.Write((UInt32)condition.instance); // bgObj
binWriter.Write((UInt32)condition.layout); // Layout
binWriter.Write((UInt32)4); // Actor? Always 4 in 1.23
binWriter.Seek(8, SeekOrigin.Current); // Unknowns

View file

@ -79,7 +79,7 @@ namespace Meteor.Map.packets.send.player
public const ushort OPCODE = 0x01A3;
public const uint PACKET_SIZE = 0x150;
public SubPacket BuildPacket(uint sourceActorId, string sNpcName, short sNpcActorIdOffset, byte sNpcSkin, byte sNpcPersonality, bool[] completedQuests)
public SubPacket BuildPacket(uint sourceActorId, string sNpcName, byte sNpcSkin, byte sNpcPersonality, short sNpcCoordinate, bool[] completedQuests)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
@ -93,9 +93,9 @@ namespace Meteor.Map.packets.send.player
binWriter.Seek(0x01 ,SeekOrigin.Begin);
binWriter.Write((Int16)2);
binWriter.Write((Byte)0);
binWriter.Write((Int16)sNpcActorIdOffset);
binWriter.Write((Byte)sNpcSkin);
binWriter.Write((Int16)sNpcSkin);
binWriter.Write((Byte)sNpcPersonality);
binWriter.Write((Byte)sNpcCoordinate);
if (binStream.Length <= PACKET_SIZE - 0x20)
binWriter.Write(binStream);