diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index a1e692a2..6b81af4d 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -147,6 +147,7 @@ + diff --git a/FFXIVClassic Map Server/actors/Actor.cs b/FFXIVClassic Map Server/actors/Actor.cs index b56f0dfc..b71b618c 100644 --- a/FFXIVClassic Map Server/actors/Actor.cs +++ b/FFXIVClassic Map Server/actors/Actor.cs @@ -29,6 +29,7 @@ namespace FFXIVClassic_Map_Server.Actors public float positionX, positionY, positionZ, rotation; public float oldPositionX, oldPositionY, oldPositionZ, oldRotation; public ushort moveState, oldMoveState; + public float[] moveSpeeds = new float[5]; public uint zoneId; public Zone zone = null; @@ -52,6 +53,11 @@ namespace FFXIVClassic_Map_Server.Actors this.actorName = actorName; this.className = className; this.classParams = classParams; + + this.moveSpeeds[0] = SetActorSpeedPacket.DEFAULT_STOP; + this.moveSpeeds[1] = SetActorSpeedPacket.DEFAULT_WALK; + this.moveSpeeds[2] = SetActorSpeedPacket.DEFAULT_RUN; + this.moveSpeeds[3] = SetActorSpeedPacket.DEFAULT_RUN; } public SubPacket createAddActorPacket(uint playerActorId, byte val) @@ -220,6 +226,30 @@ namespace FFXIVClassic_Map_Server.Actors return classParams; } + public void changeState(ushort newState) + { + currentMainState = newState; + SubPacket changeStatePacket = SetActorStatePacket.buildPacket(actorId, actorId, newState, currentSubState); + zone.broadcastPacketAroundActor(this, changeStatePacket); + } + + public void changeSpeed(int type, float value) + { + moveSpeeds[type] = value; + SubPacket changeSpeedPacket = SetActorSpeedPacket.buildPacket(actorId, actorId, moveSpeeds[0], moveSpeeds[1], moveSpeeds[2]); + zone.broadcastPacketAroundActor(this, changeSpeedPacket); + } + + public void changeSpeed(float speedStop, float speedWalk, float speedRun) + { + moveSpeeds[0] = speedStop; + moveSpeeds[1] = speedWalk; + moveSpeeds[2] = speedRun; + moveSpeeds[3] = speedRun; + SubPacket changeSpeedPacket = SetActorSpeedPacket.buildPacket(actorId, actorId, moveSpeeds[0], moveSpeeds[1], moveSpeeds[2]); + zone.broadcastPacketAroundActor(this, changeSpeedPacket); + } + } } diff --git a/FFXIVClassic Map Server/actors/area/Zone.cs b/FFXIVClassic Map Server/actors/area/Zone.cs index c984468a..147e9cb2 100644 --- a/FFXIVClassic Map Server/actors/area/Zone.cs +++ b/FFXIVClassic Map Server/actors/area/Zone.cs @@ -289,5 +289,22 @@ namespace FFXIVClassic_Map_Server.Actors } } + public void broadcastPacketAroundActor(Actor actor, SubPacket packet) + { + if (zone != null) + { + List aroundActor = getActorsAroundActor(actor, 50); + foreach (Actor a in aroundActor) + { + if (a is Player) + { + SubPacket clonedPacket = new SubPacket(packet, actor.actorId); + Player p = (Player)a; + p.queuePacket(clonedPacket); + } + } + } + } + } } diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 25df3340..c909a770 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -598,7 +598,7 @@ namespace FFXIVClassic_Map_Server.Actors { playerSession.queuePacket(packet, true, false); } - + public void sendMessage(uint logType, string sender, string message) { queuePacket(SendMessagePacket.buildPacket(actorId, actorId, logType, sender, message)); @@ -614,6 +614,32 @@ namespace FFXIVClassic_Map_Server.Actors queuePacket(QuitPacket.buildPacket(actorId)); } + public void changeMusic(ushort musicId) + { + queuePacket(SetMusicPacket.buildPacket(actorId, musicId, 1)); + } + + public void sendChocoboAppearance() + { + queuePacket(SetCurrentMountChocoboPacket.buildPacket(actorId, chocoboAppearance)); + } + + public void sendGoobbueAppearance() + { + queuePacket(SetCurrentMountGoobbuePacket.buildPacket(actorId, 1)); + } + + public void sendWorldMessage(ushort worldMasterId, params object[] msgParams) + { + //queuePacket(WorldMasterPacket.buildPacket()); + } + + public void broadcastWorldMessage(ushort worldMasterId, params object[] msgParams) + { + //SubPacket worldMasterMessage = + //zone.broadcastPacketAroundActor(this, worldMasterMessage); + } + public void runEventFunction(string functionName, params object[] parameters) { List lParams = LuaUtils.createLuaParamList(parameters); diff --git a/FFXIVClassic Map Server/packets/SubPacket.cs b/FFXIVClassic Map Server/packets/SubPacket.cs index 8ef5c83d..87231156 100644 --- a/FFXIVClassic Map Server/packets/SubPacket.cs +++ b/FFXIVClassic Map Server/packets/SubPacket.cs @@ -95,6 +95,17 @@ namespace FFXIVClassic_Lobby_Server.packets header.subpacketSize = (ushort)(SUBPACKET_SIZE + GAMEMESSAGE_SIZE + data.Length); } + public SubPacket(SubPacket original, uint newTargetId) + { + this.header = new SubPacketHeader(); + this.gameMessage = original.gameMessage; + header.subpacketSize = original.header.subpacketSize; + header.type = original.header.type; + header.sourceId = original.header.sourceId; + header.targetId = newTargetId; + data = original.data; + } + public byte[] getHeaderBytes() { int size = Marshal.SizeOf(header); diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetActorSpeedPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorSpeedPacket.cs index 2fed0ebc..a1f388c7 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/SetActorSpeedPacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorSpeedPacket.cs @@ -13,9 +13,9 @@ namespace FFXIVClassic_Map_Server.packets.send.actor public const ushort OPCODE = 0x00D0; public const uint PACKET_SIZE = 0xA8; - public const ushort DEFAULT_STOP = 0x0000; - public const ushort DEFAULT_WALK = 0x4000; - public const ushort DEFAULT_RUN = 0x40A0; + public const float DEFAULT_STOP = 0.0f; + public const float DEFAULT_WALK = 2.0f; + public const float DEFAULT_RUN = 5.0f; public static SubPacket buildPacket(uint playerActorID, uint targetActorID) { @@ -25,20 +25,16 @@ namespace FFXIVClassic_Map_Server.packets.send.actor { using (BinaryWriter binWriter = new BinaryWriter(mem)) { - binWriter.Write((UInt16)00); - binWriter.Write((UInt16)DEFAULT_STOP); + binWriter.Write((Single)DEFAULT_STOP); binWriter.Write((UInt32)0); - binWriter.Write((UInt16)00); - binWriter.Write((UInt16)DEFAULT_WALK); + binWriter.Write((Single)DEFAULT_WALK); binWriter.Write((UInt32)1); - binWriter.Write((UInt16)00); - binWriter.Write((UInt16)DEFAULT_RUN); + binWriter.Write((Single)DEFAULT_RUN); binWriter.Write((UInt32)2); - binWriter.Write((UInt16)00); - binWriter.Write((UInt16)DEFAULT_RUN); + binWriter.Write((Single)DEFAULT_RUN); binWriter.Write((UInt32)3); binWriter.BaseStream.Seek(0x80, SeekOrigin.Begin); @@ -50,7 +46,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor return new SubPacket(OPCODE, playerActorID, targetActorID, data); } - public static SubPacket buildPacket(uint playerActorID, uint targetActorID, ushort stopSpeed, ushort walkSpeed, ushort runSpeed) + public static SubPacket buildPacket(uint playerActorID, uint targetActorID, float stopSpeed, float walkSpeed, float runSpeed) { byte[] data = new byte[PACKET_SIZE - 0x20]; @@ -58,20 +54,17 @@ namespace FFXIVClassic_Map_Server.packets.send.actor { using (BinaryWriter binWriter = new BinaryWriter(mem)) { - binWriter.Write((UInt16)00); - binWriter.Write((UInt16)stopSpeed); + binWriter.Write((Single)stopSpeed); binWriter.Write((UInt32)0); - binWriter.Write((UInt16)00); - binWriter.Write((UInt16)walkSpeed); + binWriter.Write((Single)walkSpeed); binWriter.Write((UInt32)1); binWriter.Write((UInt16)00); - binWriter.Write((UInt16)runSpeed); + binWriter.Write((Single)runSpeed); binWriter.Write((UInt32)2); - - binWriter.Write((UInt16)00); - binWriter.Write((UInt16)runSpeed); + + binWriter.Write((Single)runSpeed); binWriter.Write((UInt32)3); binWriter.BaseStream.Seek(0x90, SeekOrigin.Begin); diff --git a/FFXIVClassic Map Server/packets/send/GameMessagePacket.cs b/FFXIVClassic Map Server/packets/send/GameMessagePacket.cs new file mode 100644 index 00000000..ba05abad --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/GameMessagePacket.cs @@ -0,0 +1,346 @@ +using FFXIVClassic_Lobby_Server.packets; +using FFXIVClassic_Map_Server.lua; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.send +{ + class GameMessagePacket + { + public const ushort OPCODE_GAMEMESSAGE_WITH_ACTOR1 = 0x157; + public const ushort OPCODE_GAMEMESSAGE_WITH_ACTOR2 = 0x158; + public const ushort OPCODE_GAMEMESSAGE_WITH_ACTOR3 = 0x159; + public const ushort OPCODE_GAMEMESSAGE_WITH_ACTOR4 = 0x15a; + public const ushort OPCODE_GAMEMESSAGE_WITH_ACTOR5 = 0x15b; + + public const ushort OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER1 = 0x15c; + public const ushort OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER2 = 0x15d; + public const ushort OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER3 = 0x15e; + public const ushort OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER4 = 0x15f; + public const ushort OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER5 = 0x160; + + public const ushort OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER1 = 0x161; + public const ushort OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER2 = 0x162; + public const ushort OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER3 = 0x163; + public const ushort OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER4 = 0x164; + public const ushort OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER5 = 0x165; + + public const ushort OPCODE_GAMEMESSAGE_WITHOUT_ACTOR1 = 0x166; + public const ushort OPCODE_GAMEMESSAGE_WITHOUT_ACTOR2 = 0x167; + public const ushort OPCODE_GAMEMESSAGE_WITHOUT_ACTOR3 = 0x168; + public const ushort OPCODE_GAMEMESSAGE_WITHOUT_ACTOR4 = 0x169; + public const ushort OPCODE_GAMEMESSAGE_WITHOUT_ACTOR5 = 0x16a; + + public const ushort SIZE_GAMEMESSAGE_WITH_ACTOR1 = 0x30; + public const ushort SIZE_GAMEMESSAGE_WITH_ACTOR2 = 0x38; + public const ushort SIZE_GAMEMESSAGE_WITH_ACTOR3 = 0x40; + public const ushort SIZE_GAMEMESSAGE_WITH_ACTOR4 = 0x50; + public const ushort SIZE_GAMEMESSAGE_WITH_ACTOR5 = 0x70; + + public const ushort SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER1 = 0x48; + public const ushort SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER2 = 0x58; + public const ushort SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER3 = 0x68; + public const ushort SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER4 = 0x78; + public const ushort SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER5 = 0x98; + + public const ushort SIZE_GAMEMESSAGE_WITH_DISPID_SENDER1 = 0x30; + public const ushort SIZE_GAMEMESSAGE_WITH_DISPID_SENDER2 = 0x38; + public const ushort SIZE_GAMEMESSAGE_WITH_DISPID_SENDER3 = 0x40; + public const ushort SIZE_GAMEMESSAGE_WITH_DISPID_SENDER4 = 0x50; + public const ushort SIZE_GAMEMESSAGE_WITH_DISPID_SENDER5 = 0x60; + + public const ushort SIZE_GAMEMESSAGE_WITHOUT_ACTOR1 = 0x28; + public const ushort SIZE_GAMEMESSAGE_WITHOUT_ACTOR2 = 0x38; + public const ushort SIZE_GAMEMESSAGE_WITHOUT_ACTOR3 = 0x38; + public const ushort SIZE_GAMEMESSAGE_WITHOUT_ACTOR4 = 0x48; + public const ushort SIZE_GAMEMESSAGE_WITHOUT_ACTOR5 = 0x68; + + public static SubPacket buildPacket(uint sourceId, uint targetId, uint actorId, uint textOwnerActorId, ushort textId, byte log) + { + byte[] data = new byte[SIZE_GAMEMESSAGE_WITH_ACTOR1 - 0x20]; + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)actorId); + binWriter.Write((UInt32)textOwnerActorId); + binWriter.Write((UInt16)textId); + binWriter.Write((UInt16)log); + } + } + + return new SubPacket(OPCODE_GAMEMESSAGE_WITH_ACTOR1, sourceId, targetId, data); + } + + public static SubPacket buildPacket(uint sourceId, uint targetId, uint actorId, uint textOwnerActorId, ushort textId, byte log, List lParams) + { + int lParamsSize = findSizeOfParams(lParams); + byte[] data; + ushort opcode; + + if (lParamsSize <= 0x8) + { + data = new byte[SIZE_GAMEMESSAGE_WITH_ACTOR2 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_ACTOR2; + } + else if (lParamsSize <= 0x10) + { + data = new byte[SIZE_GAMEMESSAGE_WITH_ACTOR3 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_ACTOR3; + } + else if (lParamsSize <= 0x20) + { + data = new byte[SIZE_GAMEMESSAGE_WITH_ACTOR4 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_ACTOR4; + } + else + { + data = new byte[SIZE_GAMEMESSAGE_WITH_ACTOR5 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_ACTOR5; + } + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)actorId); + binWriter.Write((UInt32)textOwnerActorId); + binWriter.Write((UInt16)textId); + binWriter.Write((UInt16)log); + LuaUtils.writeLuaParams(binWriter, lParams); + + if (lParamsSize <= 0x14-12) + { + binWriter.Seek(0x14, SeekOrigin.Begin); + binWriter.Write((UInt32)8); + } + } + } + + return new SubPacket(opcode, sourceId, targetId, data); + } + + public static SubPacket buildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, string sender, byte log) + { + byte[] data = new byte[SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER1 - 0x20]; + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)textOwnerActorId); + binWriter.Write((UInt16)textId); + binWriter.Write((UInt16)log); + binWriter.Write(Encoding.ASCII.GetBytes(sender), 0, Encoding.ASCII.GetByteCount(sender) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(sender)); + } + } + + return new SubPacket(OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER1, sourceId, targetId, data); + } + + public static SubPacket buildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, string sender, byte log, List lParams) + { + int lParamsSize = findSizeOfParams(lParams); + byte[] data; + ushort opcode; + + if (lParamsSize <= 0x8) + { + data = new byte[SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER2 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER2; + } + else if (lParamsSize <= 0x10) + { + data = new byte[SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER3 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER3; + } + else if (lParamsSize <= 0x20) + { + data = new byte[SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER4 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER4; + } + else + { + data = new byte[SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER5 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER5; + } + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)textOwnerActorId); + binWriter.Write((UInt16)textId); + binWriter.Write((UInt16)log); + binWriter.Write(Encoding.ASCII.GetBytes(sender), 0, Encoding.ASCII.GetByteCount(sender) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(sender)); + LuaUtils.writeLuaParams(binWriter, lParams); + + if (lParamsSize <= 0x14 - 12) + { + binWriter.Seek(0x30, SeekOrigin.Begin); + binWriter.Write((UInt32)8); + } + } + } + + return new SubPacket(opcode, sourceId, targetId, data); + } + + public static SubPacket buildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, uint senderDisplayNameId, byte log) + { + byte[] data = new byte[SIZE_GAMEMESSAGE_WITH_DISPID_SENDER1 - 0x20]; + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)senderDisplayNameId); + binWriter.Write((UInt32)textOwnerActorId); + binWriter.Write((UInt16)textId); + binWriter.Write((UInt16)log); + } + } + + return new SubPacket(OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER1, sourceId, targetId, data); + } + + public static SubPacket buildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, uint senderDisplayNameId, byte log, List lParams) + { + int lParamsSize = findSizeOfParams(lParams); + byte[] data; + ushort opcode; + + if (lParamsSize <= 0x8) + { + data = new byte[SIZE_GAMEMESSAGE_WITH_DISPID_SENDER2 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER2; + } + else if (lParamsSize <= 0x10) + { + data = new byte[SIZE_GAMEMESSAGE_WITH_DISPID_SENDER3 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER3; + } + else if (lParamsSize <= 0x20) + { + data = new byte[SIZE_GAMEMESSAGE_WITH_DISPID_SENDER4 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER4; + } + else + { + data = new byte[SIZE_GAMEMESSAGE_WITH_DISPID_SENDER5 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER5; + } + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)senderDisplayNameId); + binWriter.Write((UInt32)textOwnerActorId); + binWriter.Write((UInt16)textId); + binWriter.Write((UInt16)log); + LuaUtils.writeLuaParams(binWriter, lParams); + + if (lParamsSize <= 0x14 - 12) + { + binWriter.Seek(0x14, SeekOrigin.Begin); + binWriter.Write((UInt32)8); + } + } + } + + return new SubPacket(opcode, sourceId, targetId, data); + } + + public static SubPacket buildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, byte log) + { + byte[] data = new byte[SIZE_GAMEMESSAGE_WITHOUT_ACTOR1 - 0x20]; + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)textOwnerActorId); + binWriter.Write((UInt16)textId); + binWriter.Write((UInt16)log); + } + } + + return new SubPacket(OPCODE_GAMEMESSAGE_WITHOUT_ACTOR1, sourceId, targetId, data); + } + + public static SubPacket buildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, byte log, List lParams) + { + int lParamsSize = findSizeOfParams(lParams); + byte[] data; + ushort opcode; + + if (lParamsSize <= 0x8) + { + data = new byte[SIZE_GAMEMESSAGE_WITHOUT_ACTOR2 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITHOUT_ACTOR2; + } + else if (lParamsSize <= 0x10) + { + data = new byte[SIZE_GAMEMESSAGE_WITHOUT_ACTOR3 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITHOUT_ACTOR3; + } + else if (lParamsSize <= 0x20) + { + data = new byte[SIZE_GAMEMESSAGE_WITHOUT_ACTOR4 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITHOUT_ACTOR4; + } + else + { + data = new byte[SIZE_GAMEMESSAGE_WITHOUT_ACTOR5 - 0x20]; + opcode = OPCODE_GAMEMESSAGE_WITHOUT_ACTOR5; + } + + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)textOwnerActorId); + binWriter.Write((UInt16)textId); + binWriter.Write((UInt16)log); + LuaUtils.writeLuaParams(binWriter, lParams); + + if (lParamsSize <= 0x14 - 12) + { + binWriter.Seek(0x30, SeekOrigin.Begin); + binWriter.Write((UInt32)8); + } + } + } + + return new SubPacket(opcode, sourceId, targetId, data); + } + + private static int findSizeOfParams(List lParams) + { + int total = 0; + foreach (LuaParam l in lParams) + { + switch (l.typeID) + { + case 0: + case 1: + case 6: + total += 5; + break; + case 3: + case 4: + case 5: + total += 1; + break; + } + } + return total + 1; + } + } +}