mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-08-04 08:41:58 +02:00
Implemented equipment and equip graphics. Add some zone callbacks and "first start" functionality. Added playtime.
This commit is contained in:
parent
c9116005d6
commit
44e5430fdc
17 changed files with 676 additions and 129 deletions
|
@ -4,6 +4,7 @@ using FFXIVClassic_Map_Server.dataobjects;
|
|||
using FFXIVClassic_Map_Server.dataobjects.chara;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||
using MoonSharp.Interpreter;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -20,7 +21,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
public ushort weatherNormal, weatherCommon, weatherRare;
|
||||
public ushort bgmDay, bgmNight, bgmBattle;
|
||||
|
||||
|
||||
private string classPath;
|
||||
|
||||
public int boundingGridSize = 50;
|
||||
|
@ -31,6 +31,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
private Dictionary<uint, Actor> mActorList = new Dictionary<uint,Actor>();
|
||||
private List<Actor>[,] mActorBlock;
|
||||
|
||||
Script areaScript;
|
||||
|
||||
public Area(uint id, string zoneName, ushort regionId, string className, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid)
|
||||
: base(id)
|
||||
{
|
||||
|
@ -66,7 +68,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
mActorBlock[x, y] = new List<Actor>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override SubPacket createScriptBindPacket(uint playerActorId)
|
||||
|
@ -117,7 +119,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
mActorBlock[gridX, gridY].Add(actor);
|
||||
}
|
||||
|
||||
public void removeActorToZone(Actor actor)
|
||||
public void removeActorFromZone(Actor actor)
|
||||
{
|
||||
mActorList.Remove(actor.actorId);
|
||||
|
||||
|
|
|
@ -16,29 +16,32 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
public const int FACEINFO = 2;
|
||||
public const int HIGHLIGHT_HAIR = 3;
|
||||
public const int VOICE = 4;
|
||||
public const int WEAPON1 = 5;
|
||||
public const int WEAPON2 = 6;
|
||||
public const int WEAPON3 = 7;
|
||||
public const int UNKNOWN1 = 8;
|
||||
public const int UNKNOWN2 = 9;
|
||||
public const int UNKNOWN3 = 10;
|
||||
public const int UNKNOWN4 = 11;
|
||||
public const int MAINHAND = 5;
|
||||
public const int OFFHAND = 6;
|
||||
public const int SPMAINHAND = 7;
|
||||
public const int SPOFFHAND = 8;
|
||||
public const int THROWING = 9;
|
||||
public const int PACK = 10;
|
||||
public const int POUCH = 11;
|
||||
public const int HEADGEAR = 12;
|
||||
public const int BODYGEAR = 13;
|
||||
public const int LEGSGEAR = 14;
|
||||
public const int HANDSGEAR = 15;
|
||||
public const int FEETGEAR = 16;
|
||||
public const int WAISTGEAR = 17;
|
||||
public const int UNKNOWN5 = 18;
|
||||
public const int R_EAR = 19;
|
||||
public const int L_EAR = 20;
|
||||
public const int UNKNOWN6 = 21;
|
||||
public const int UNKNOWN7 = 22;
|
||||
public const int R_FINGER = 23;
|
||||
public const int L_FINGER = 24;
|
||||
public const int NECKGEAR = 18;
|
||||
public const int L_EAR = 19;
|
||||
public const int R_EAR = 20;
|
||||
public const int R_WRIST = 21;
|
||||
public const int L_WRIST = 22;
|
||||
public const int R_RINGFINGER = 23;
|
||||
public const int L_RINGFINGER = 24;
|
||||
public const int R_INDEXFINGER = 25;
|
||||
public const int L_INDEXFINGER = 26;
|
||||
public const int UNKNOWN = 27;
|
||||
|
||||
public uint modelId;
|
||||
public uint[] appearanceIds = new uint[0x1D];
|
||||
public uint[] appearanceIds = new uint[28];
|
||||
|
||||
public uint animationId = 0;
|
||||
|
||||
|
|
|
@ -49,9 +49,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
{
|
||||
List<LuaParam> lParams;
|
||||
|
||||
LuaEngine lua = Server.getServer().GetLuaEngine();
|
||||
Player player = Server.getServer().GetWorldManager().GetPCInWorld(playerActorId);
|
||||
lParams = lua.doActorOnInstantiate(player, this);
|
||||
lParams = LuaEngine.doActorOnInstantiate(player, this);
|
||||
|
||||
if (lParams == null)
|
||||
{
|
||||
|
@ -154,7 +153,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
appearanceIds[Character.FACEINFO] = PrimitiveConversion.ToUInt32(CharacterUtils.getFaceInfo(reader.GetByte(6), reader.GetByte(7), reader.GetByte(5), reader.GetByte(14), reader.GetByte(13), reader.GetByte(12), reader.GetByte(11), reader.GetByte(10), reader.GetByte(9), reader.GetByte(8)));
|
||||
appearanceIds[Character.HIGHLIGHT_HAIR] = (uint)(reader.GetUInt32(3) | reader.GetUInt32(2) << 10); //5- Hair Highlight, 4 - Hair Style
|
||||
appearanceIds[Character.VOICE] = reader.GetUInt32(17);
|
||||
appearanceIds[Character.WEAPON1] = reader.GetUInt32(19);
|
||||
appearanceIds[Character.MAINHAND] = reader.GetUInt32(19);
|
||||
//appearanceIds[Character.WEAPON2] = reader.GetUInt32(22);
|
||||
appearanceIds[Character.HEADGEAR] = reader.GetUInt32(26);
|
||||
appearanceIds[Character.BODYGEAR] = reader.GetUInt32(27);
|
||||
|
@ -164,8 +163,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
appearanceIds[Character.WAISTGEAR] = reader.GetUInt32(31);
|
||||
appearanceIds[Character.R_EAR] = reader.GetUInt32(32);
|
||||
appearanceIds[Character.L_EAR] = reader.GetUInt32(33);
|
||||
appearanceIds[Character.R_FINGER] = reader.GetUInt32(36);
|
||||
appearanceIds[Character.L_FINGER] = reader.GetUInt32(37);
|
||||
appearanceIds[Character.R_RINGFINGER] = reader.GetUInt32(36);
|
||||
appearanceIds[Character.L_RINGFINGER] = reader.GetUInt32(37);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,24 +13,24 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
{
|
||||
class Equipment
|
||||
{
|
||||
public const int SLOT_MAINHAND = 0x00;
|
||||
public const int SLOT_OFFHAND = 0x01;
|
||||
public const int SLOT_THROWINGWEAPON = 0x04;
|
||||
public const int SLOT_PACK = 0x05;
|
||||
public const int SLOT_POUCH = 0x06;
|
||||
public const int SLOT_HEAD = 0x08;
|
||||
public const int SLOT_UNDERSHIRT = 0x09;
|
||||
public const int SLOT_BODY = 0x0A;
|
||||
public const int SLOT_UNDERGARMENT = 0x0B;
|
||||
public const int SLOT_LEGS = 0x0C;
|
||||
public const int SLOT_HANDS = 0x0D;
|
||||
public const int SLOT_BOOTS = 0x0E;
|
||||
public const int SLOT_WAIST = 0x0F;
|
||||
public const int SLOT_NECK = 0x10;
|
||||
public const int SLOT_EARS = 0x11;
|
||||
public const int SLOT_WRISTS = 0x13;
|
||||
public const int SLOT_RIGHTFINGER = 0x15;
|
||||
public const int SLOT_LEFTFINGER = 0x16;
|
||||
public const int SLOT_MAINHAND = 0;
|
||||
public const int SLOT_OFFHAND = 1;
|
||||
public const int SLOT_THROWINGWEAPON = 4;
|
||||
public const int SLOT_PACK = 5;
|
||||
public const int SLOT_POUCH = 6;
|
||||
public const int SLOT_HEAD = 8;
|
||||
public const int SLOT_UNDERSHIRT = 9;
|
||||
public const int SLOT_BODY = 10;
|
||||
public const int SLOT_UNDERGARMENT = 11;
|
||||
public const int SLOT_LEGS = 12;
|
||||
public const int SLOT_HANDS = 13;
|
||||
public const int SLOT_BOOTS = 14;
|
||||
public const int SLOT_WAIST = 15;
|
||||
public const int SLOT_NECK = 16;
|
||||
public const int SLOT_EARS = 17;
|
||||
public const int SLOT_WRISTS = 19;
|
||||
public const int SLOT_RIGHTFINGER = 21;
|
||||
public const int SLOT_LEFTFINGER = 22;
|
||||
|
||||
private Player owner;
|
||||
private ushort inventoryCapacity;
|
||||
|
@ -71,6 +71,27 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
owner.queuePacket(InventorySetEndPacket.buildPacket(owner.actorId));
|
||||
}
|
||||
|
||||
public void SetEquipment(ushort[] slots, ushort[] itemSlots)
|
||||
{
|
||||
if (slots.Length != itemSlots.Length)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
InventoryItem item = normalInventory.getItem(itemSlots[i]);
|
||||
|
||||
if (item == null)
|
||||
continue;
|
||||
|
||||
Database.equipItem(owner, slots[i], itemSlots[i]);
|
||||
list[slots[i]] = normalInventory.getItem(itemSlots[i]);
|
||||
}
|
||||
|
||||
owner.queuePacket(InventoryBeginChangePacket.buildPacket(owner.actorId));
|
||||
SendFullEquipment(false);
|
||||
owner.queuePacket(InventoryEndChangePacket.buildPacket(owner.actorId));
|
||||
}
|
||||
|
||||
public void SetEquipment(List<Tuple<ushort, InventoryItem>> toEquip)
|
||||
{
|
||||
List<ushort> slotsToUpdate = new List<ushort>();
|
||||
|
@ -81,6 +102,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
}
|
||||
}
|
||||
|
||||
public void Equip(ushort slot, ushort invSlot)
|
||||
{
|
||||
InventoryItem item = normalInventory.getItem(invSlot);
|
||||
|
||||
if (item == null)
|
||||
return;
|
||||
|
||||
Equip(slot, item);
|
||||
}
|
||||
|
||||
public void Equip(ushort slot, InventoryItem item)
|
||||
{
|
||||
if (slot >= list.Length)
|
||||
|
|
|
@ -70,6 +70,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
owner.queuePacket(InventorySetEndPacket.buildPacket(owner.actorId));
|
||||
}
|
||||
|
||||
public void addItem(uint itemId)
|
||||
{
|
||||
addItem(itemId, 1, 1);
|
||||
}
|
||||
|
||||
public void addItem(uint itemId, int quantity)
|
||||
{
|
||||
addItem(itemId, quantity, 1);
|
||||
}
|
||||
|
||||
public void addItem(uint itemId, int quantity, byte quality)
|
||||
{
|
||||
if (!isSpaceForAdd(itemId, quantity))
|
||||
|
@ -119,7 +129,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
//New item that spilled over
|
||||
while (quantityCount > 0)
|
||||
{
|
||||
InventoryItem addedItem = Database.addItem(owner, itemId, Math.Min(quantityCount, 5), quality, gItem.isExclusive ? (byte)0x3 : (byte)0x0, gItem.durability, inventoryCode);
|
||||
InventoryItem addedItem = Database.addItem(owner, itemId, Math.Min(quantityCount, gItem.maxStack), quality, gItem.isExclusive ? (byte)0x3 : (byte)0x0, gItem.durability, inventoryCode);
|
||||
|
||||
|
||||
list.Add(addedItem);
|
||||
|
@ -137,6 +147,31 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
owner.queuePacket(InventoryEndChangePacket.buildPacket(owner.actorId));
|
||||
}
|
||||
|
||||
public void addItem(uint[] itemId)
|
||||
{
|
||||
if (!isSpaceForAdd(itemId[0], itemId.Length))
|
||||
return;
|
||||
|
||||
//Update lists and db
|
||||
owner.queuePacket(InventoryBeginChangePacket.buildPacket(owner.actorId));
|
||||
owner.queuePacket(InventorySetBeginPacket.buildPacket(owner.actorId, inventoryCapacity, inventoryCode));
|
||||
|
||||
int startPos = list.Count;
|
||||
|
||||
//New item that spilled over
|
||||
for (int i = 0; i < itemId.Length; i++)
|
||||
{
|
||||
Item gItem = Server.getItemGamedata(itemId[i]);
|
||||
InventoryItem addedItem = Database.addItem(owner, itemId[i], 1, (byte)1, gItem.isExclusive ? (byte)0x3 : (byte)0x0, gItem.durability, inventoryCode);
|
||||
list.Add(addedItem);
|
||||
}
|
||||
|
||||
sendInventoryPackets(startPos);
|
||||
|
||||
owner.queuePacket(InventorySetEndPacket.buildPacket(owner.actorId));
|
||||
owner.queuePacket(InventoryEndChangePacket.buildPacket(owner.actorId));
|
||||
}
|
||||
|
||||
public void removeItem(uint itemId, int quantity)
|
||||
{
|
||||
if (!hasItem(itemId, quantity))
|
||||
|
|
|
@ -59,6 +59,9 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
public uint[] timers = new uint[20];
|
||||
public ushort currentJob;
|
||||
public uint currentTitle;
|
||||
public uint playTime;
|
||||
public uint lastPlayTimeUpdate;
|
||||
public bool isGM = false;
|
||||
|
||||
//Inventory
|
||||
private Dictionary<ushort, Inventory> inventories = new Dictionary<ushort, Inventory>();
|
||||
|
@ -162,6 +165,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
charaWork.parameterTemp.tp = 3000;
|
||||
|
||||
Database.loadPlayerCharacter(this);
|
||||
lastPlayTimeUpdate = Utils.UnixTimeStampUTC();
|
||||
}
|
||||
|
||||
public List<SubPacket> create0x132Packets(uint playerActorId)
|
||||
|
@ -545,6 +549,34 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
}
|
||||
}
|
||||
|
||||
public void setDCFlag(bool flag)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
broadcastPacket(SetActorIconPacket.buildPacket(actorId, actorId, SetActorIconPacket.DISCONNECTING), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isGM)
|
||||
broadcastPacket(SetActorIconPacket.buildPacket(actorId, actorId, SetActorIconPacket.ISGM), true);
|
||||
else
|
||||
broadcastPacket(SetActorIconPacket.buildPacket(actorId, actorId, 0), true);
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanupAndSave()
|
||||
{
|
||||
//Remove actor from zone and main server list
|
||||
zone.removeActorFromZone(this);
|
||||
Server.getServer().removePlayer(this);
|
||||
|
||||
//Save Player
|
||||
Database.savePlayerPlayTime(this);
|
||||
Database.savePlayerPosition(this);
|
||||
|
||||
Log.info(String.Format("{0} has been logged out and saved.", this.customDisplayName));
|
||||
}
|
||||
|
||||
public Zone getZone()
|
||||
{
|
||||
return zone;
|
||||
|
@ -558,11 +590,25 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
public void logout()
|
||||
{
|
||||
queuePacket(LogoutPacket.buildPacket(actorId));
|
||||
cleanupAndSave();
|
||||
}
|
||||
|
||||
public void quitGame()
|
||||
{
|
||||
queuePacket(QuitPacket.buildPacket(actorId));
|
||||
cleanupAndSave();
|
||||
}
|
||||
|
||||
public uint getPlayTime(bool doUpdate)
|
||||
{
|
||||
if (doUpdate)
|
||||
{
|
||||
uint curTime = Utils.UnixTimeStampUTC();
|
||||
playTime += curTime - lastPlayTimeUpdate;
|
||||
lastPlayTimeUpdate = curTime;
|
||||
}
|
||||
|
||||
return playTime;
|
||||
}
|
||||
|
||||
public void changeMusic(ushort musicId)
|
||||
|
@ -635,33 +681,62 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
//zone.broadcastPacketAroundActor(this, worldMasterMessage);
|
||||
}
|
||||
|
||||
public void graphicChange(uint slot, uint graphicId)
|
||||
{
|
||||
appearanceIds[slot] = graphicId;
|
||||
broadcastPacket(createAppearancePacket(actorId), true);
|
||||
}
|
||||
|
||||
public void graphicChange(uint slot, uint weapId, uint equipId, uint variantId, uint colorId)
|
||||
{
|
||||
|
||||
uint mixedVariantId;
|
||||
|
||||
if (weapId == 0)
|
||||
mixedVariantId = ((variantId & 0x1F) << 5) | colorId;
|
||||
else
|
||||
mixedVariantId = variantId;
|
||||
|
||||
uint graphicId =
|
||||
(weapId & 0x3FF) << 20 |
|
||||
(equipId & 0x3FF) << 10 |
|
||||
(mixedVariantId & 0x3FF);
|
||||
|
||||
appearanceIds[slot] = graphicId;
|
||||
broadcastPacket(createAppearancePacket(actorId), true);
|
||||
|
||||
}
|
||||
|
||||
public void graphicChange(int slot, InventoryItem invItem)
|
||||
{
|
||||
Item item = Server.getItemGamedata(invItem.itemId);
|
||||
|
||||
if (item == null)
|
||||
if (invItem == null)
|
||||
appearanceIds[slot] = 0;
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
else if (item is EquipmentItem)
|
||||
{
|
||||
EquipmentItem eqItem = (EquipmentItem)item;
|
||||
|
||||
uint graphicId;
|
||||
|
||||
if (eqItem.graphicsWeaponId == null || eqItem.graphicsEquipmentId == null || eqItem.graphicsVariantId == null)
|
||||
graphicId = 1025;
|
||||
else
|
||||
Item item = Server.getItemGamedata(invItem.itemId);
|
||||
if (item is EquipmentItem)
|
||||
{
|
||||
graphicId =
|
||||
eqItem.graphicsWeaponId << 20 |
|
||||
eqItem.graphicsEquipmentId << 10 |
|
||||
eqItem.graphicsVariantId << 5 |
|
||||
eqItem.graphicsColorId << 5;
|
||||
EquipmentItem eqItem = (EquipmentItem)item;
|
||||
|
||||
uint mixedVariantId;
|
||||
|
||||
if (eqItem.graphicsWeaponId == 0)
|
||||
mixedVariantId = ((eqItem.graphicsVariantId & 0x1F) << 5) | eqItem.graphicsColorId;
|
||||
else
|
||||
mixedVariantId = eqItem.graphicsVariantId;
|
||||
|
||||
uint graphicId =
|
||||
(eqItem.graphicsWeaponId & 0x3FF) << 20 |
|
||||
(eqItem.graphicsEquipmentId & 0x3FF) << 10 |
|
||||
(mixedVariantId & 0x3FF);
|
||||
|
||||
appearanceIds[slot] = graphicId;
|
||||
}
|
||||
appearanceIds[BODYGEAR] = graphicId;
|
||||
broadcastPacket(createAppearancePacket(actorId), true);
|
||||
}
|
||||
}
|
||||
|
||||
Database.savePlayerAppearance(this);
|
||||
|
||||
broadcastPacket(createAppearancePacket(actorId), true);
|
||||
}
|
||||
|
||||
public Inventory getInventory(ushort type)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue