From 4e6902207238a91564917d9b0924d08fcb6de0fe Mon Sep 17 00:00:00 2001 From: Filip Maj Date: Fri, 17 Jun 2016 23:17:24 -0400 Subject: [PATCH] New style of scripting for better complex menus. --- FFXIVClassic Map Server/PacketProcessor.cs | 10 +- .../actors/chara/npc/Npc.cs | 29 +++--- .../actors/chara/player/Player.cs | 46 ++++++--- .../dataobjects/ConnectedPlayer.cs | 20 ++-- FFXIVClassic Map Server/lua/LuaEngine.cs | 8 +- .../npc/populace/shop/PopulaceGuildShop.lua | 15 +++ .../populace/shop/PopulaceShopSalesman.lua | 94 +++++++++++++++++-- .../PopulaceShopSalesman/jossy.lua | 6 ++ 8 files changed, 170 insertions(+), 58 deletions(-) create mode 100644 data/scripts/unique/sea0Town01a/PopulaceShopSalesman/jossy.lua diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index 09b203aa..43ac25c8 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -273,8 +273,8 @@ namespace FFXIVClassic_Map_Server } } } - - LuaEngine.DoActorOnEventStarted(player.GetActor(), ownerActor, eventStart); + + player.GetActor().StartEvent(ownerActor, eventStart); Program.Log.Debug("\n===Event START===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nEvent Starter: {4}\nParams: {5}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.val1, eventStart.val2, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams)); break; @@ -286,7 +286,7 @@ namespace FFXIVClassic_Map_Server subpacket.DebugPrintSubPacket(); EventUpdatePacket eventUpdate = new EventUpdatePacket(subpacket.data); Program.Log.Debug("\n===Event UPDATE===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nStep: 0x{4:X}\nParams: {5}", eventUpdate.actorID, eventUpdate.scriptOwnerActorID, eventUpdate.val1, eventUpdate.val2, eventUpdate.step, LuaUtils.DumpParams(eventUpdate.luaParams)); - + /* //Is it a static actor? If not look in the player's instance Actor updateOwnerActor = Server.GetStaticActors(player.GetActor().currentEventOwner); if (updateOwnerActor == null) @@ -299,8 +299,10 @@ namespace FFXIVClassic_Map_Server if (updateOwnerActor == null) break; } + */ + player.GetActor().UpdateEvent(eventUpdate); - LuaEngine.DoActorOnEventUpdated(player.GetActor(), updateOwnerActor, eventUpdate); + //LuaEngine.DoActorOnEventUpdated(player.GetActor(), updateOwnerActor, eventUpdate); break; case 0x012F: diff --git a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs index 69e43813..e12c367a 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs @@ -181,6 +181,11 @@ namespace FFXIVClassic_Map_Server.Actors return BasePacket.CreatePacket(propPacketUtil.Done(), true, false); } + public string GetUniqueId() + { + return uniqueIdentifier; + } + public uint GetActorClassId() { return actorClassId; @@ -322,7 +327,7 @@ namespace FFXIVClassic_Map_Server.Actors return lparams; } - public void DoEventStart(Player player, EventStartPacket eventStart) + public Coroutine GetEventStartCoroutine(Player player) { Script parent = null, child = null; @@ -331,31 +336,23 @@ namespace FFXIVClassic_Map_Server.Actors if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier))) child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier)); - if (parent == null) + if (parent == null && child == null) { LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", GetName())); - return; + return null; } - //Have to do this to combine LuaParams - List objects = new List(); - objects.Add(player); - objects.Add(this); - objects.Add(eventStart.triggerName); - - if (eventStart.luaParams != null) - objects.AddRange(LuaUtils.CreateLuaParamObjectList(eventStart.luaParams)); - //Run Script - DynValue result; + Coroutine coroutine; if (child != null && !child.Globals.Get("onEventStarted").IsNil()) - result = child.Call(child.Globals["onEventStarted"], objects.ToArray()); + coroutine = child.CreateCoroutine(child.Globals["onEventStarted"]).Coroutine; else if (!parent.Globals.Get("onEventStarted").IsNil()) - result = parent.Call(parent.Globals["onEventStarted"], objects.ToArray()); + coroutine = parent.CreateCoroutine(parent.Globals["onEventStarted"]).Coroutine; else - return; + return null; + return coroutine; } public void DoEventUpdate(Player player, EventUpdatePacket eventUpdate) diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 53be333c..215da839 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -15,6 +15,8 @@ using FFXIVClassic_Map_Server.packets.send.player; using FFXIVClassic_Map_Server.utils; using System; using System.Collections.Generic; +using MoonSharp.Interpreter; +using FFXIVClassic_Map_Server.packets.receive.events; namespace FFXIVClassic_Map_Server.Actors { @@ -82,8 +84,8 @@ namespace FFXIVClassic_Map_Server.Actors public uint currentCommand = 0; public string currentCommandName = ""; - - public uint eventMenuId = 0; + + public Coroutine currentEventRunning; //Player Info public uint[] timers = new uint[20]; @@ -1118,6 +1120,35 @@ namespace FFXIVClassic_Map_Server.Actors QueuePacket(spacket); } + public void StartEvent(Actor owner, EventStartPacket start) + { + //Have to do this to combine LuaParams + List objects = new List(); + objects.Add(this); + objects.Add(owner); + objects.Add(start.triggerName); + + if (start.luaParams != null) + objects.AddRange(LuaUtils.CreateLuaParamObjectList(start.luaParams)); + + if (owner is Npc) + { + currentEventRunning = ((Npc)owner).GetEventStartCoroutine(this); + currentEventRunning.Resume(objects.ToArray()); + } + else + LuaEngine.DoActorOnEventStarted(this, owner, start); + } + + public void UpdateEvent(EventUpdatePacket update) + { + if (currentEventRunning == null) + return; + + if (currentEventRunning.State == CoroutineState.Suspended) + currentEventRunning.Resume(LuaUtils.CreateLuaParamObjectList(update.luaParams)); + } + public void KickEvent(Actor actor, string conditionName, params object[] parameters) { if (actor == null) @@ -1150,7 +1181,6 @@ namespace FFXIVClassic_Map_Server.Actors currentEventOwner = 0; currentEventName = ""; - eventMenuId = 0; } public void EndCommand() @@ -1163,16 +1193,6 @@ namespace FFXIVClassic_Map_Server.Actors currentCommandName = ""; } - public void SetCurrentMenuId(uint id) - { - eventMenuId = id; - } - - public uint GetCurrentMenuId() - { - return eventMenuId; - } - public void SendInstanceUpdate() { diff --git a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs index f5eef9a4..e2f59293 100644 --- a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs +++ b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs @@ -47,7 +47,7 @@ namespace FFXIVClassic_Map_Server.dataobjects break; } } - + public bool IsClientConnectionsReady() { return (zoneConnection != null && chatConnection != null); @@ -57,7 +57,7 @@ namespace FFXIVClassic_Map_Server.dataobjects { zoneConnection.Disconnect(); chatConnection.Disconnect(); - } + } public bool IsDisconnected() { @@ -71,7 +71,7 @@ namespace FFXIVClassic_Map_Server.dataobjects public void QueuePacket(SubPacket subPacket, bool isAuthed, bool isEncrypted) { - zoneConnection.QueuePacket(subPacket, isAuthed, isEncrypted); + zoneConnection.QueuePacket(subPacket, isAuthed, isEncrypted); } public Player GetActor() @@ -97,7 +97,7 @@ namespace FFXIVClassic_Map_Server.dataobjects } public void UpdatePlayerActorPosition(float x, float y, float z, float rot, ushort moveState) - { + { playerActor.oldPositionX = playerActor.positionX; playerActor.oldPositionY = playerActor.positionY; playerActor.oldPositionZ = playerActor.positionZ; @@ -110,11 +110,11 @@ namespace FFXIVClassic_Map_Server.dataobjects playerActor.moveState = moveState; GetActor().zone.UpdateActorPosition(GetActor()); - - } - + + } + public void UpdateInstance(List list) - { + { List basePackets = new List(); List RemoveActorSubpackets = new List(); List posUpdateSubpackets = new List(); @@ -125,7 +125,7 @@ namespace FFXIVClassic_Map_Server.dataobjects if (!list.Contains(actorInstanceList[i])) { GetActor().QueuePacket(RemoveActorPacket.BuildPacket(playerActor.actorId, actorInstanceList[i].actorId)); - actorInstanceList.RemoveAt(i); + actorInstanceList.RemoveAt(i); } } @@ -145,7 +145,7 @@ namespace FFXIVClassic_Map_Server.dataobjects { GetActor().QueuePacket(actor.GetSpawnPackets(playerActor.actorId, 1)); GetActor().QueuePacket(actor.GetInitPackets(playerActor.actorId)); - GetActor().QueuePacket(actor.GetSetEventStatusPackets(playerActor.actorId)); + GetActor().QueuePacket(actor.GetSetEventStatusPackets(playerActor.actorId)); actorInstanceList.Add(actor); if (actor is Npc) diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs index fef4e299..fa1db54c 100644 --- a/FFXIVClassic Map Server/lua/LuaEngine.cs +++ b/FFXIVClassic Map Server/lua/LuaEngine.cs @@ -57,13 +57,7 @@ namespace FFXIVClassic_Map_Server.lua } public static void DoActorOnEventStarted(Player player, Actor target, EventStartPacket eventStart) - { - if (target is Npc) - { - ((Npc)target).DoEventStart(player, eventStart); - return; - } - + { string luaPath; if (target is Command) diff --git a/data/scripts/base/chara/npc/populace/shop/PopulaceGuildShop.lua b/data/scripts/base/chara/npc/populace/shop/PopulaceGuildShop.lua index dcdb098b..a3727d1f 100644 --- a/data/scripts/base/chara/npc/populace/shop/PopulaceGuildShop.lua +++ b/data/scripts/base/chara/npc/populace/shop/PopulaceGuildShop.lua @@ -45,6 +45,21 @@ function onEventStarted(player, npc) end player:RunEventFunction("welcomeTalk", nil, saySheetId, player); + coroutine.yield(); + + while (true) do + player:RunEventFunction("selectMode", nil, npc:GetActorClassId(), false, 1000001); --Step 2, state your business + choice = coroutine.yield(); + + if (choice == 3) then + + elseif (choice == 4) then + player:EndEvent(); + break; + end + + end + end function onEventUpdate(player, npc, step, menuOptionSelected) diff --git a/data/scripts/base/chara/npc/populace/shop/PopulaceShopSalesman.lua b/data/scripts/base/chara/npc/populace/shop/PopulaceShopSalesman.lua index a06d99ce..067cf001 100644 --- a/data/scripts/base/chara/npc/populace/shop/PopulaceShopSalesman.lua +++ b/data/scripts/base/chara/npc/populace/shop/PopulaceShopSalesman.lua @@ -1,15 +1,93 @@ +--[[ + +PopulaceShopSalesman Script + +Functions: + +welcomeTalk(sheetId, player) - Start Message +selectMode(askMode) - Shows buy/sell modes. If askmode > 0 show guild tutorial. If askmode == -7/-8/-9 show nothing. Else show affinity/condition tutorials. +selectModeOfClassVendor() - Opens categories for class weapons and gear +selectModeOfMultiWeaponVendor(consumptionTutorialId) - Opens categories for weapons/tools (war/magic/land/hand). Arg consumptionTutorialId appends location of item repair person. -1: Ul'dah, -2: Gridania, -3: Limsa +selectModeOfMultiArmorVendor(consumptionTutorialId) - Opens categories for armor in different slots. Arg consumptionTutorialId appends location of item repair person. -1: Ul'dah, -2: Gridania, -3: Limsa + +openShopBuy(player, shopPack, currancyItemId) - ShopPack: Items to appear in window. CurrancyItemId: What is being used to buy these items. +selectShopBuy(player) - Call after openShopBuy() to open widget +closeShopBuy(player) - Closes the buy window + +openShopSell(player) - Call this to open sell window +selectShopSell(player) - Call after openShopSell() +closeShopSell(player) - Closes the sell window + +selectFacility(?, sheetId, 3) - Opens the facility chooser. +confirmUseFacility(player, cost) - Facility cost confirm + +informSellPrice(1, chosenItem, price) - Shows sell confirm window. ChosenItem must be correct. + +startTutorial(nil, tutorialId) - Opens up a tutorial menu for each guild type based on tutorialId + +finishTalkTurn() - Done at the end. + +--]] + +function callClientFunction(player, functionName, ...) + player:RunEventFunction(functionName, ...); + result = coroutine.yield(); + return result; +end + function init(npc) return false, false, 0, 0; end function onEventStarted(player, npc) - player:SendMessage(0x20, "", "This PopulaceShopSalesman actor has no event set. Actor Class Id: " .. tostring(npc:GetActorClassId())) - player:EndEvent(); - --player:RunEventFunction("welcomeTalk"); -end -function onEventUpdate(player, npc, step, menuOptionSelected, lsName, lsCrest) - - player:EndEvent(); + require("/unique/".. npc.zone.zoneName .."/PopulaceShopSalesman/" .. npc:GetUniqueId()) -end \ No newline at end of file + callClientFunction(player, "welcomeTalk", shopInfo.welcomeText, player); + + while (true) do + choice = callClientFunction(player, "selectMode", 1); + + if (choice == nil) then + break; + elseif (choice == 1) then + callClientFunction(player, "openShopBuy", player, shopInfo.shopPack, shopInfo.shopCurrancy); + + while (true) do + buyResult = callClientFunction(player, "selectShopBuy", player); + + if (buyResult == 0) then + callClientFunction(player, "closeShopBuy", player); + break; + else + player:SendMessage(0x20, "", "Player bought a thing at slot " .. tostring(buyResult).."."); + end + + end + + elseif (choice == 2) then + callClientFunction(player, "openShopSell", player); + + while (true) do + sellResult = callClientFunction(player, "selectShopSell", player); + + if (sellResult == nil) then + callClientFunction(player, "closeShopSell", player); + break; + else + player:SendMessage(0x20, "", "Player sold a thing at slot " .. tostring(sellResult).."."); + end + + end + elseif (choice == 3) then + callClientFunction(player, "selectFacility", 2, 35, 3); + callClientFunction(player, "confirmUseFacility", player, 35); + elseif (choice == 4) then + callClientFunction(player, "startTutorial", nil, 29); + end + end + + callClientFunction(player, "finishTalkTurn", player); + player:EndEvent(); + +end diff --git a/data/scripts/unique/sea0Town01a/PopulaceShopSalesman/jossy.lua b/data/scripts/unique/sea0Town01a/PopulaceShopSalesman/jossy.lua new file mode 100644 index 00000000..b0781436 --- /dev/null +++ b/data/scripts/unique/sea0Town01a/PopulaceShopSalesman/jossy.lua @@ -0,0 +1,6 @@ + +shopInfo = { +welcomeText = 94, +shopPack = 0x67, +shopCurrancy = nil +} \ No newline at end of file