mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2025-08-20 04:20:40 +00:00
Merge branch 'master' of https://github.com/OpenFusionProject/OpenFusion into master
This commit is contained in:
commit
25e83f12b8
@ -24,7 +24,7 @@ Currently the client by default connects to a public server hosted by Cake. Chan
|
||||
You have two randomized characters available to you on the Character Selection screen, one boy, one girl.
|
||||
You can also make your own character and play through the tutorial. The tutorial can be skipped by pressing the ~ key.
|
||||
|
||||
If you want, [compiled binaries (artifacts) for each new commit can be found on AppVeyor.](https://ci.appveyor.com/project/Raymonf/openfusion)
|
||||
If you want, [compiled binaries (artifacts) for each new commit can be found on AppVeyor.](https://ci.appveyor.com/project/OpenFusionProject/openfusion)
|
||||
|
||||
For a more detailed overview of the game's architecture and how to configure it, read the following sections.
|
||||
|
||||
|
@ -18,7 +18,8 @@ randomcharacters=true
|
||||
port=8002
|
||||
ip=127.0.0.1
|
||||
# distance at which other players and NPCs become visible
|
||||
view=20000
|
||||
playerdistance=20000
|
||||
npcdistance=16000
|
||||
# little message players see when they enter the game
|
||||
motd=Welcome to OpenFusion!
|
||||
# NPC json data
|
||||
@ -30,6 +31,6 @@ gm=true
|
||||
|
||||
# spawn coordinates (Z is height)
|
||||
# the supplied defaults are at City Hall
|
||||
spawnx=179213
|
||||
spawny=268451
|
||||
spawnz=-4210
|
||||
spawnx=632032
|
||||
spawny=187177
|
||||
spawnz=-5500
|
||||
|
@ -85,6 +85,7 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) {
|
||||
int64_t UID = charInfo.sPC_Style.iPC_UID;
|
||||
loginSessions[sock].characters[UID] = Player();
|
||||
loginSessions[sock].characters[UID].level = charInfo.iLevel;
|
||||
loginSessions[sock].characters[UID].money = 9001;
|
||||
loginSessions[sock].characters[UID].slot = charInfo.iSlot;
|
||||
loginSessions[sock].characters[UID].FEKey = sock->getFEKey();
|
||||
loginSessions[sock].characters[UID].x = charInfo.iX;
|
||||
@ -213,6 +214,7 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) {
|
||||
|
||||
loginSessions[sock].characters[UID] = Player();
|
||||
loginSessions[sock].characters[UID].level = 36;
|
||||
loginSessions[sock].characters[UID].money = 9001;
|
||||
loginSessions[sock].characters[UID].FEKey = sock->getFEKey();
|
||||
loginSessions[sock].characters[UID].PCStyle = character->PCStyle;
|
||||
loginSessions[sock].characters[UID].PCStyle2.iAppearanceFlag = 1;
|
||||
|
@ -200,7 +200,7 @@ void CNSocket::step() {
|
||||
|
||||
if (activelyReading && readBufferIndex - readSize <= 0) {
|
||||
// decrypt readBuffer and copy to CNPacketData
|
||||
CNSocketEncryption::decryptData(readBuffer, (uint8_t*)(&EKey), readSize);
|
||||
CNSocketEncryption::decryptData((uint8_t*)&readBuffer, (uint8_t*)(&EKey), readSize);
|
||||
|
||||
void* tmpBuf = xmalloc(readSize-sizeof(int32_t));
|
||||
memcpy(tmpBuf, readBuffer+sizeof(uint32_t), readSize-sizeof(int32_t));
|
||||
|
@ -104,7 +104,7 @@ private:
|
||||
uint64_t EKey;
|
||||
uint64_t FEKey;
|
||||
int32_t readSize = 0;
|
||||
uint8_t* readBuffer = new uint8_t[MAX_PACKETSIZE];
|
||||
uint8_t readBuffer[MAX_PACKETSIZE];
|
||||
int readBufferIndex = 0;
|
||||
bool activelyReading = false;
|
||||
bool alive = true;
|
||||
|
@ -8,6 +8,15 @@ void ItemManager::init() {
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ITEM_DELETE, itemDeleteHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GIVE_ITEM, itemGMGiveHandler);
|
||||
//Trade handlers
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_OFFER, itemTradeOfferHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_OFFER_ACCEPT, itemTradeOfferAcceptHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_OFFER_REFUSAL, itemTradeOfferRefusalHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_CONFIRM, itemTradeConfirmHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_CONFIRM_CANCEL, itemTradeConfirmCancelHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_ITEM_REGISTER, itemTradeRegisterItemHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_ITEM_UNREGISTER, itemTradeUnregisterItemHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_CASH_REGISTER, itemTradeRegisterCashHandler);
|
||||
}
|
||||
|
||||
void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) {
|
||||
@ -19,8 +28,8 @@ void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) {
|
||||
|
||||
PlayerView& plr = PlayerManager::players[sock];
|
||||
|
||||
if (itemmove->eFrom == 0 && itemmove->eTo == 0) {
|
||||
// this packet should never happen, tell the client to do nothing and do nothing ourself
|
||||
if (plr.plr->Equip[itemmove->iFromSlotNum].iType != 0 && itemmove->eFrom == 0 && itemmove->eTo == 0) {
|
||||
// this packet should never happen unless it is a weapon, tell the client to do nothing and do nothing ourself
|
||||
resp.eTo = itemmove->eFrom;
|
||||
resp.iToSlotNum = itemmove->iFromSlotNum;
|
||||
resp.ToSlotItem = plr.plr->Equip[itemmove->iToSlotNum];
|
||||
@ -28,7 +37,7 @@ void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) {
|
||||
resp.iFromSlotNum = itemmove->iToSlotNum;
|
||||
resp.FromSlotItem = plr.plr->Equip[itemmove->iFromSlotNum];
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_ITEM_DELETE_SUCC, sizeof(sP_FE2CL_REP_PC_ITEM_DELETE_SUCC));
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_PC_ITEM_MOVE_SUCC, sizeof(sP_FE2CL_PC_ITEM_MOVE_SUCC));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -126,7 +135,7 @@ void ItemManager::itemGMGiveHandler(CNSocket* sock, CNPacketData* data) {
|
||||
if (itemreq->eIL == 2) {
|
||||
// Quest item, not a real item, handle this later, stubbed for now
|
||||
// sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_REP_PC_GIVE_ITEM_FAIL, sizeof(sP_FE2CL_REP_PC_GIVE_ITEM_FAIL), sock->getFEKey()));
|
||||
} else if (itemreq->eIL == 1 && itemreq->Item.iType >= 0 && itemreq->Item.iType <= 8) {
|
||||
} else if (itemreq->eIL == 1 && itemreq->Item.iType >= 0 && itemreq->Item.iType <= 10) {
|
||||
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_GIVE_ITEM_SUCC, resp);
|
||||
|
||||
@ -137,16 +146,473 @@ void ItemManager::itemGMGiveHandler(CNSocket* sock, CNPacketData* data) {
|
||||
plr.plr->Inven[itemreq->iSlotNum] = itemreq->Item;
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_GIVE_ITEM_SUCC, sizeof(sP_FE2CL_REP_PC_GIVE_ITEM_SUCC));
|
||||
|
||||
// some items require a level, for now we're just going to bypass this by setting your level to 36
|
||||
//plr.plr->level = 36;
|
||||
|
||||
//sP_FE2CL_REP_PC_CHANGE_LEVEL resp2;
|
||||
|
||||
//resp2.iPC_ID = plr.plr->iID;
|
||||
//resp2.iPC_Level = 36;
|
||||
|
||||
//sock->sendPacket((void*)&resp2, P_FE2CL_REP_PC_CHANGE_LEVEL, sizeof(sP_FE2CL_REP_PC_CHANGE_LEVEL));
|
||||
// saving this for later use on a /level command
|
||||
}
|
||||
}
|
||||
|
||||
void ItemManager::itemTradeOfferHandler(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_OFFER))
|
||||
return; // ignore the malformed packet
|
||||
|
||||
sP_CL2FE_REQ_PC_TRADE_OFFER* pacdat = (sP_CL2FE_REQ_PC_TRADE_OFFER*)data->buf;
|
||||
|
||||
int iID_Check;
|
||||
|
||||
if (pacdat->iID_Request == pacdat->iID_From) {
|
||||
iID_Check = pacdat->iID_To;
|
||||
} else {
|
||||
iID_Check = pacdat->iID_From;
|
||||
}
|
||||
|
||||
CNSocket* otherSock = sock;
|
||||
|
||||
for (auto pair : PlayerManager::players) {
|
||||
if (pair.second.plr->iID == iID_Check) {
|
||||
otherSock = pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_OFFER, resp);
|
||||
|
||||
resp.iID_Request = pacdat->iID_Request;
|
||||
resp.iID_From = pacdat->iID_From;
|
||||
resp.iID_To = pacdat->iID_To;
|
||||
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_OFFER, sizeof(sP_FE2CL_REP_PC_TRADE_OFFER));
|
||||
}
|
||||
|
||||
void ItemManager::itemTradeOfferAcceptHandler(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_OFFER_ACCEPT))
|
||||
return; // ignore the malformed packet
|
||||
|
||||
sP_CL2FE_REQ_PC_TRADE_OFFER_ACCEPT* pacdat = (sP_CL2FE_REQ_PC_TRADE_OFFER_ACCEPT*)data->buf;
|
||||
|
||||
int iID_Check;
|
||||
|
||||
if (pacdat->iID_Request == pacdat->iID_From) {
|
||||
iID_Check = pacdat->iID_To;
|
||||
} else {
|
||||
iID_Check = pacdat->iID_From;
|
||||
}
|
||||
|
||||
CNSocket* otherSock = sock;
|
||||
|
||||
for (auto pair : PlayerManager::players) {
|
||||
if (pair.second.plr->iID == iID_Check) {
|
||||
otherSock = pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_OFFER, resp);
|
||||
|
||||
resp.iID_Request = pacdat->iID_Request;
|
||||
resp.iID_From = pacdat->iID_From;
|
||||
resp.iID_To = pacdat->iID_To;
|
||||
|
||||
// Clearing up trade slots
|
||||
|
||||
PlayerView& plr = PlayerManager::players[sock];
|
||||
PlayerView& plr2 = PlayerManager::players[otherSock];
|
||||
|
||||
plr.plr->IsTradeConfirm = false;
|
||||
plr2.plr->IsTradeConfirm = false;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
plr.plr->Trade[i].iID = 0;
|
||||
plr.plr->Trade[i].iType = 0;
|
||||
plr.plr->Trade[i].iOpt = 0;
|
||||
plr.plr->Trade[i].iInvenNum = 0;
|
||||
plr.plr->Trade[i].iSlotNum = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
plr2.plr->Trade[i].iID = 0;
|
||||
plr2.plr->Trade[i].iType = 0;
|
||||
plr2.plr->Trade[i].iOpt = 0;
|
||||
plr2.plr->Trade[i].iInvenNum = 0;
|
||||
plr2.plr->Trade[i].iSlotNum = 0;
|
||||
}
|
||||
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_OFFER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_OFFER_SUCC));
|
||||
}
|
||||
|
||||
void ItemManager::itemTradeOfferRefusalHandler(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_OFFER_REFUSAL))
|
||||
return; // ignore the malformed packet
|
||||
|
||||
sP_CL2FE_REQ_PC_TRADE_OFFER_REFUSAL* pacdat = (sP_CL2FE_REQ_PC_TRADE_OFFER_REFUSAL*)data->buf;
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_OFFER_REFUSAL, resp);
|
||||
|
||||
resp.iID_Request = pacdat->iID_Request;
|
||||
resp.iID_From = pacdat->iID_From;
|
||||
resp.iID_To = pacdat->iID_To;
|
||||
|
||||
int iID_Check;
|
||||
|
||||
if (pacdat->iID_Request == pacdat->iID_From) {
|
||||
iID_Check = pacdat->iID_To;
|
||||
} else {
|
||||
iID_Check = pacdat->iID_From;
|
||||
}
|
||||
|
||||
CNSocket* otherSock = sock;
|
||||
|
||||
for (auto pair : PlayerManager::players) {
|
||||
if (pair.second.plr->iID == iID_Check) {
|
||||
otherSock = pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_OFFER_REFUSAL, sizeof(sP_FE2CL_REP_PC_TRADE_OFFER_REFUSAL));
|
||||
}
|
||||
|
||||
void ItemManager::itemTradeConfirmHandler(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_CONFIRM))
|
||||
return; // ignore the malformed packet
|
||||
|
||||
sP_CL2FE_REQ_PC_TRADE_CONFIRM* pacdat = (sP_CL2FE_REQ_PC_TRADE_CONFIRM*)data->buf;
|
||||
|
||||
int iID_Check;
|
||||
|
||||
if (pacdat->iID_Request == pacdat->iID_From) {
|
||||
iID_Check = pacdat->iID_To;
|
||||
} else {
|
||||
iID_Check = pacdat->iID_From;
|
||||
}
|
||||
|
||||
CNSocket* otherSock = sock;
|
||||
|
||||
for (auto pair : PlayerManager::players) {
|
||||
if (pair.second.plr->iID == iID_Check) {
|
||||
otherSock = pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerView& plr = PlayerManager::players[sock];
|
||||
PlayerView& plr2 = PlayerManager::players[otherSock];
|
||||
|
||||
if (plr2.plr->IsTradeConfirm) {
|
||||
|
||||
plr.plr->IsTrading = false;
|
||||
plr2.plr->IsTrading = false;
|
||||
plr.plr->IsTradeConfirm = false;
|
||||
plr2.plr->IsTradeConfirm = false;
|
||||
|
||||
// Check if we have enough free slots
|
||||
int freeSlots = 0;
|
||||
int freeSlotsNeeded = 0;
|
||||
int freeSlots2 = 0;
|
||||
int freeSlotsNeeded2 = 0;
|
||||
|
||||
for (int i = 0; i < AINVEN_COUNT; i++) {
|
||||
if (plr.plr->Inven[i].iID == 0)
|
||||
freeSlots++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (plr.plr->Trade[i].iID != 0)
|
||||
freeSlotsNeeded++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < AINVEN_COUNT; i++) {
|
||||
if (plr2.plr->Inven[i].iID == 0)
|
||||
freeSlots2++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (plr2.plr->Trade[i].iID != 0)
|
||||
freeSlotsNeeded2++;
|
||||
}
|
||||
|
||||
DEBUGLOG(
|
||||
std::cout << "Slots Free and Needed:" << std::endl;
|
||||
std::cout << "\tfreeSlots: " << (int)freeSlots << std::endl;
|
||||
std::cout << "\tfreeSlotsNeeded: " << (int)freeSlotsNeeded << std::endl;
|
||||
std::cout << "\tfreeSlots2: " << (int)freeSlots2 << std::endl;
|
||||
std::cout << "\tfreeSlotsNeeded2: " << (int)freeSlotsNeeded2 << std::endl;
|
||||
)
|
||||
|
||||
if (freeSlotsNeeded2 - freeSlotsNeeded > freeSlots) {
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, resp);
|
||||
|
||||
resp.iID_Request = pacdat->iID_Request;
|
||||
resp.iID_From = pacdat->iID_From;
|
||||
resp.iID_To = pacdat->iID_To;
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL));
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL));
|
||||
return; // Fail trade because of the lack of slots
|
||||
}
|
||||
|
||||
if (freeSlotsNeeded - freeSlotsNeeded2 > freeSlots2) {
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, resp);
|
||||
|
||||
resp.iID_Request = pacdat->iID_Request;
|
||||
resp.iID_From = pacdat->iID_From;
|
||||
resp.iID_To = pacdat->iID_To;
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL));
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL));
|
||||
return; // Fail trade because of the lack of slots
|
||||
}
|
||||
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM, resp);
|
||||
|
||||
resp.iID_Request = pacdat->iID_Request;
|
||||
resp.iID_From = pacdat->iID_From;
|
||||
resp.iID_To = pacdat->iID_To;
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM));
|
||||
// ^^ this is a must have or else the player won't accept a succ packet for some reason
|
||||
|
||||
for (int i = 0; i < freeSlotsNeeded; i++) {
|
||||
plr.plr->Inven[plr.plr->Trade[i].iInvenNum].iID = 0;
|
||||
plr.plr->Inven[plr.plr->Trade[i].iInvenNum].iType = 0;
|
||||
plr.plr->Inven[plr.plr->Trade[i].iInvenNum].iOpt = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < freeSlotsNeeded2; i++) {
|
||||
plr2.plr->Inven[plr2.plr->Trade[i].iInvenNum].iID = 0;
|
||||
plr2.plr->Inven[plr2.plr->Trade[i].iInvenNum].iType = 0;
|
||||
plr2.plr->Inven[plr2.plr->Trade[i].iInvenNum].iOpt = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < AINVEN_COUNT; i++) {
|
||||
if (freeSlotsNeeded <= 0)
|
||||
break;
|
||||
|
||||
if (plr2.plr->Inven[i].iID == 0) {
|
||||
|
||||
plr2.plr->Inven[i].iID = plr.plr->Trade[freeSlotsNeeded - 1].iID;
|
||||
plr2.plr->Inven[i].iType = plr.plr->Trade[freeSlotsNeeded - 1].iType;
|
||||
plr2.plr->Inven[i].iOpt = plr.plr->Trade[freeSlotsNeeded - 1].iOpt;
|
||||
plr.plr->Trade[freeSlotsNeeded - 1].iInvenNum = i;
|
||||
DEBUGLOG(
|
||||
std::cout << "Player 1 Trade Item #" << (int)freeSlotsNeeded << std::endl;
|
||||
std::cout << "\tiID: " << (int)plr.plr->Trade[freeSlotsNeeded - 1].iID << std::endl;
|
||||
std::cout << "\tiType: " << (int)plr.plr->Trade[freeSlotsNeeded - 1].iType << std::endl;
|
||||
std::cout << "\tiOpt: " << (int)plr.plr->Trade[freeSlotsNeeded - 1].iOpt << std::endl;
|
||||
std::cout << "\tiInvenNum: " << (int)plr.plr->Trade[freeSlotsNeeded - 1].iInvenNum << std::endl;
|
||||
std::cout << "\tiSlotNum: " << (int)plr.plr->Trade[freeSlotsNeeded - 1].iSlotNum << std::endl;
|
||||
std::cout << "\t added item " << (int)plr2.plr->Inven[i].iID << " to slot " << (int)i << std::endl;
|
||||
)
|
||||
freeSlotsNeeded--;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < AINVEN_COUNT; i++) {
|
||||
if (freeSlotsNeeded2 <= 0)
|
||||
break;
|
||||
|
||||
if (plr.plr->Inven[i].iID == 0) {
|
||||
|
||||
plr.plr->Inven[i].iID = plr2.plr->Trade[freeSlotsNeeded2 - 1].iID;
|
||||
plr.plr->Inven[i].iType = plr2.plr->Trade[freeSlotsNeeded2 - 1].iType;
|
||||
plr.plr->Inven[i].iOpt = plr2.plr->Trade[freeSlotsNeeded2 - 1].iOpt;
|
||||
plr2.plr->Trade[freeSlotsNeeded2 - 1].iInvenNum = i;
|
||||
DEBUGLOG(
|
||||
std::cout << "Player 2 Trade Item #" << (int)freeSlotsNeeded2 << std::endl;
|
||||
std::cout << "\tiID: " << (int)plr2.plr->Trade[freeSlotsNeeded2 - 1].iID << std::endl;
|
||||
std::cout << "\tiType: " << (int)plr2.plr->Trade[freeSlotsNeeded2 - 1].iType << std::endl;
|
||||
std::cout << "\tiOpt: " << (int)plr2.plr->Trade[freeSlotsNeeded2 - 1].iOpt << std::endl;
|
||||
std::cout << "\tiInvenNum: " << (int)plr2.plr->Trade[freeSlotsNeeded2 - 1].iInvenNum << std::endl;
|
||||
std::cout << "\tiSlotNum: " << (int)plr2.plr->Trade[freeSlotsNeeded2 - 1].iSlotNum << std::endl;
|
||||
std::cout << "\t added item " << (int)plr.plr->Inven[i].iID << " to slot " << (int)i << std::endl;
|
||||
)
|
||||
freeSlotsNeeded2--;
|
||||
}
|
||||
}
|
||||
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM_SUCC, resp2);
|
||||
|
||||
resp2.iID_Request = pacdat->iID_Request;
|
||||
resp2.iID_From = pacdat->iID_From;
|
||||
resp2.iID_To = pacdat->iID_To;
|
||||
|
||||
plr.plr->money = plr.plr->money + plr2.plr->moneyInTrade - plr.plr->moneyInTrade;
|
||||
resp2.iCandy = plr.plr->money;
|
||||
|
||||
memcpy(resp2.Item, plr2.plr->Trade, sizeof(plr2.plr->Trade));
|
||||
memcpy(resp2.ItemStay, plr.plr->Trade, sizeof(plr.plr->Trade));
|
||||
|
||||
sock->sendPacket((void*)&resp2, P_FE2CL_REP_PC_TRADE_CONFIRM_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_SUCC));
|
||||
|
||||
plr2.plr->money = plr2.plr->money + plr.plr->moneyInTrade - plr2.plr->moneyInTrade;
|
||||
resp2.iCandy = plr2.plr->money;
|
||||
|
||||
memcpy(resp2.Item, plr.plr->Trade, sizeof(plr.plr->Trade));
|
||||
memcpy(resp2.ItemStay, plr2.plr->Trade, sizeof(plr2.plr->Trade));
|
||||
|
||||
otherSock->sendPacket((void*)&resp2, P_FE2CL_REP_PC_TRADE_CONFIRM_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_SUCC));
|
||||
} else {
|
||||
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM, resp);
|
||||
|
||||
resp.iID_Request = pacdat->iID_Request;
|
||||
resp.iID_From = pacdat->iID_From;
|
||||
resp.iID_To = pacdat->iID_To;
|
||||
|
||||
plr.plr->IsTradeConfirm = true;
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM));
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM));
|
||||
}
|
||||
}
|
||||
|
||||
void ItemManager::itemTradeConfirmCancelHandler(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_CONFIRM_CANCEL))
|
||||
return; // ignore the malformed packet
|
||||
|
||||
sP_CL2FE_REQ_PC_TRADE_CONFIRM_CANCEL* pacdat = (sP_CL2FE_REQ_PC_TRADE_CONFIRM_CANCEL*)data->buf;
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, resp);
|
||||
|
||||
resp.iID_Request = pacdat->iID_Request;
|
||||
resp.iID_From = pacdat->iID_From;
|
||||
resp.iID_To = pacdat->iID_To;
|
||||
|
||||
int iID_Check;
|
||||
|
||||
if (pacdat->iID_Request == pacdat->iID_From) {
|
||||
iID_Check = pacdat->iID_To;
|
||||
} else {
|
||||
iID_Check = pacdat->iID_From;
|
||||
}
|
||||
|
||||
CNSocket* otherSock = sock;
|
||||
|
||||
for (auto pair : PlayerManager::players) {
|
||||
if (pair.second.plr->iID == iID_Check) {
|
||||
otherSock = pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerView& plr = PlayerManager::players[sock];
|
||||
|
||||
plr.plr->IsTradeConfirm = false;
|
||||
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL));
|
||||
}
|
||||
|
||||
void ItemManager::itemTradeRegisterItemHandler(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_ITEM_REGISTER))
|
||||
return; // ignore the malformed packet
|
||||
|
||||
sP_CL2FE_REQ_PC_TRADE_ITEM_REGISTER* pacdat = (sP_CL2FE_REQ_PC_TRADE_ITEM_REGISTER*)data->buf;
|
||||
|
||||
if (pacdat->Item.iSlotNum < 0 || pacdat->Item.iSlotNum > 4)
|
||||
return; // sanity check
|
||||
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_ITEM_REGISTER_SUCC, resp);
|
||||
|
||||
resp.iID_Request = pacdat->iID_Request;
|
||||
resp.iID_From = pacdat->iID_From;
|
||||
resp.iID_To = pacdat->iID_To;
|
||||
resp.TradeItem = pacdat->Item;
|
||||
resp.InvenItem = pacdat->Item;
|
||||
|
||||
int iID_Check;
|
||||
|
||||
if (pacdat->iID_Request == pacdat->iID_From) {
|
||||
iID_Check = pacdat->iID_To;
|
||||
} else {
|
||||
iID_Check = pacdat->iID_From;
|
||||
}
|
||||
|
||||
CNSocket* otherSock = sock;
|
||||
|
||||
for (auto pair : PlayerManager::players) {
|
||||
if (pair.second.plr->iID == iID_Check) {
|
||||
otherSock = pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerView& plr = PlayerManager::players[sock];
|
||||
plr.plr->Trade[pacdat->Item.iSlotNum] = pacdat->Item;
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_ITEM_REGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_ITEM_REGISTER_SUCC));
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_ITEM_REGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_ITEM_REGISTER_SUCC));
|
||||
}
|
||||
|
||||
void ItemManager::itemTradeUnregisterItemHandler(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_ITEM_UNREGISTER))
|
||||
return; // ignore the malformed packet
|
||||
|
||||
sP_CL2FE_REQ_PC_TRADE_ITEM_UNREGISTER* pacdat = (sP_CL2FE_REQ_PC_TRADE_ITEM_UNREGISTER*)data->buf;
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_SUCC, resp);
|
||||
|
||||
resp.iID_Request = pacdat->iID_Request;
|
||||
resp.iID_From = pacdat->iID_From;
|
||||
resp.iID_To = pacdat->iID_To;
|
||||
resp.TradeItem = pacdat->Item;
|
||||
|
||||
PlayerView& plr = PlayerManager::players[sock];
|
||||
resp.InvenItem = plr.plr->Trade[pacdat->Item.iSlotNum];
|
||||
|
||||
int iID_Check;
|
||||
|
||||
if (pacdat->iID_Request == pacdat->iID_From) {
|
||||
iID_Check = pacdat->iID_To;
|
||||
} else {
|
||||
iID_Check = pacdat->iID_From;
|
||||
}
|
||||
|
||||
CNSocket* otherSock = sock;
|
||||
|
||||
for (auto pair : PlayerManager::players) {
|
||||
if (pair.second.plr->iID == iID_Check) {
|
||||
otherSock = pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
int temp_num = pacdat->Item.iSlotNum;
|
||||
|
||||
if (temp_num >= 0 && temp_num <= 4) {
|
||||
plr.plr->Trade[temp_num].iID = 0;
|
||||
plr.plr->Trade[temp_num].iType = 0;
|
||||
plr.plr->Trade[temp_num].iOpt = 0;
|
||||
plr.plr->Trade[temp_num].iInvenNum = 0;
|
||||
plr.plr->Trade[temp_num].iSlotNum = 0;
|
||||
}
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_SUCC));
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_SUCC));
|
||||
}
|
||||
|
||||
void ItemManager::itemTradeRegisterCashHandler(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_CASH_REGISTER))
|
||||
return; // ignore the malformed packet
|
||||
|
||||
sP_CL2FE_REQ_PC_TRADE_CASH_REGISTER* pacdat = (sP_CL2FE_REQ_PC_TRADE_CASH_REGISTER*)data->buf;
|
||||
|
||||
if (pacdat->iCandy < 0)
|
||||
return; // famous glitch, begone
|
||||
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CASH_REGISTER_SUCC, resp);
|
||||
|
||||
resp.iID_Request = pacdat->iID_Request;
|
||||
resp.iID_From = pacdat->iID_From;
|
||||
resp.iID_To = pacdat->iID_To;
|
||||
resp.iCandy = pacdat->iCandy;
|
||||
|
||||
int iID_Check;
|
||||
|
||||
if (pacdat->iID_Request == pacdat->iID_From) {
|
||||
iID_Check = pacdat->iID_To;
|
||||
} else {
|
||||
iID_Check = pacdat->iID_From;
|
||||
}
|
||||
|
||||
CNSocket* otherSock = sock;
|
||||
|
||||
for (auto pair : PlayerManager::players) {
|
||||
if (pair.second.plr->iID == iID_Check) {
|
||||
otherSock = pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerView& plr = PlayerManager::players[sock];
|
||||
|
||||
plr.plr->moneyInTrade = pacdat->iCandy;
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CASH_REGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_CASH_REGISTER_SUCC));
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CASH_REGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_CASH_REGISTER_SUCC));
|
||||
}
|
||||
|
@ -7,4 +7,13 @@ namespace ItemManager {
|
||||
void itemMoveHandler(CNSocket* sock, CNPacketData* data);
|
||||
void itemDeleteHandler(CNSocket* sock, CNPacketData* data);
|
||||
void itemGMGiveHandler(CNSocket* sock, CNPacketData* data);
|
||||
void itemTradeOfferHandler(CNSocket* sock, CNPacketData* data);
|
||||
//void itemTradeOfferCancel(CNSocket* sock, CNPacketData* data);
|
||||
void itemTradeOfferAcceptHandler(CNSocket* sock, CNPacketData* data);
|
||||
void itemTradeOfferRefusalHandler(CNSocket* sock, CNPacketData* data);
|
||||
void itemTradeConfirmHandler(CNSocket* sock, CNPacketData* data);
|
||||
void itemTradeConfirmCancelHandler(CNSocket* sock, CNPacketData* data);
|
||||
void itemTradeRegisterItemHandler(CNSocket* sock, CNPacketData* data);
|
||||
void itemTradeUnregisterItemHandler(CNSocket* sock, CNPacketData* data);
|
||||
void itemTradeRegisterCashHandler(CNSocket* sock, CNPacketData* data);
|
||||
}
|
||||
|
19
src/NPC.hpp
19
src/NPC.hpp
@ -1,5 +1,4 @@
|
||||
#ifndef _NPCCLASS_HPP
|
||||
#define _NPCCLASS_HPP
|
||||
#pragma once
|
||||
|
||||
#include "CNStructs.hpp"
|
||||
|
||||
@ -21,6 +20,18 @@ public:
|
||||
// hopefully no collisions happen :eyes:
|
||||
appearanceData.iNPC_ID = (int32_t)rand();
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
BaseNPC(int x, int y, int z, int type, int hp, int cond, int angle, int barker) {
|
||||
appearanceData.iX = x;
|
||||
appearanceData.iY = y;
|
||||
appearanceData.iZ = z;
|
||||
appearanceData.iNPCType = type;
|
||||
appearanceData.iHP = hp;
|
||||
appearanceData.iAngle = angle;
|
||||
appearanceData.iConditionBitFlag = cond;
|
||||
appearanceData.iBarkerType = barker;
|
||||
|
||||
// hopefully no collisions happen :eyes:
|
||||
appearanceData.iNPC_ID = (int32_t)rand();
|
||||
}
|
||||
};
|
||||
|
@ -31,11 +31,30 @@ void NPCManager::init() {
|
||||
RespawnPoints.push_back({npc.value()["x"], npc.value()["y"], ((int)npc.value()["z"]) + RESURRECT_HEIGHT});
|
||||
}
|
||||
|
||||
std::cout << "[INFO] populated " << NPCs.size() << " NPCs" << std::endl;
|
||||
} catch (const std::exception& err) {
|
||||
std::cerr << "[WARN] Malformed NPCs.json file! Reason:" << err.what() << std::endl;
|
||||
}
|
||||
|
||||
// load temporary mob dump
|
||||
try {
|
||||
std::ifstream inFile("mobs.json"); // not in settings, since it's temp
|
||||
nlohmann::json npcData;
|
||||
|
||||
// read file into json
|
||||
inFile >> npcData;
|
||||
|
||||
for (nlohmann::json::iterator npc = npcData.begin(); npc != npcData.end(); npc++) {
|
||||
BaseNPC tmp(npc.value()["iX"], npc.value()["iY"], npc.value()["iZ"], npc.value()["iNPCType"],
|
||||
npc.value()["iHP"], npc.value()["iConditionBitFlag"], npc.value()["iAngle"], npc.value()["iBarkerType"]);
|
||||
|
||||
NPCs[tmp.appearanceData.iNPC_ID] = tmp;
|
||||
}
|
||||
|
||||
std::cout << "[INFO] populated " << NPCs.size() << " NPCs" << std::endl;
|
||||
} catch (const std::exception& err) {
|
||||
std::cerr << "[WARN] Malformed mobs.json file! Reason:" << err.what() << std::endl;
|
||||
}
|
||||
|
||||
try {
|
||||
std::ifstream infile(settings::WARPJSON);
|
||||
nlohmann::json warpData;
|
||||
@ -67,7 +86,7 @@ void NPCManager::updatePlayerNPCS(CNSocket* sock, PlayerView& view) {
|
||||
int diffX = abs(view.plr->x - pair.second.appearanceData.iX);
|
||||
int diffY = abs(view.plr->y - pair.second.appearanceData.iY);
|
||||
|
||||
if (diffX < settings::VIEWDISTANCE && diffY < settings::VIEWDISTANCE) {
|
||||
if (diffX < settings::NPCDISTANCE && diffY < settings::NPCDISTANCE) {
|
||||
yesView.push_back(pair.first);
|
||||
} else {
|
||||
noView.push_back(pair.first);
|
||||
@ -81,10 +100,10 @@ void NPCManager::updatePlayerNPCS(CNSocket* sock, PlayerView& view) {
|
||||
|
||||
if (std::find(noView.begin(), noView.end(), id) != noView.end()) {
|
||||
// it shouldn't be visible, send NPC_EXIT
|
||||
|
||||
|
||||
exitData.iNPC_ID = id;
|
||||
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
|
||||
|
||||
// remove from view
|
||||
view.viewableNPCs.erase(i++);
|
||||
}
|
||||
@ -99,7 +118,7 @@ void NPCManager::updatePlayerNPCS(CNSocket* sock, PlayerView& view) {
|
||||
|
||||
enterData.NPCAppearanceData = NPCs[id].appearanceData;
|
||||
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||
|
||||
|
||||
// add to viewable
|
||||
view.viewableNPCs.push_back(id);
|
||||
}
|
||||
@ -113,6 +132,7 @@ void NPCManager::npcWarpHandler(CNSocket* sock, CNPacketData* data) {
|
||||
return; // malformed packet
|
||||
|
||||
sP_CL2FE_REQ_PC_WARP_USE_NPC* warpNpc = (sP_CL2FE_REQ_PC_WARP_USE_NPC*)data->buf;
|
||||
PlayerView& plrv = PlayerManager::players[sock];
|
||||
|
||||
// sanity check
|
||||
if (Warps.find(warpNpc->iWarpID) == Warps.end())
|
||||
@ -123,7 +143,11 @@ void NPCManager::npcWarpHandler(CNSocket* sock, CNPacketData* data) {
|
||||
resp.iX = Warps[warpNpc->iWarpID].x;
|
||||
resp.iY = Warps[warpNpc->iWarpID].y;
|
||||
resp.iZ = Warps[warpNpc->iWarpID].z;
|
||||
|
||||
|
||||
// force player & NPC reload
|
||||
plrv.viewable.clear();
|
||||
plrv.viewableNPCs.clear();
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_NPC_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC));
|
||||
|
||||
}
|
||||
@ -137,7 +161,7 @@ void NPCManager::npcSummonHandler(CNSocket *sock, CNPacketData *data) {
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
// permission & sanity check
|
||||
if (!plr->IsGM || req->iNPCType >= NPCs.size())
|
||||
if (!plr->IsGM || req->iNPCType >= 3314)
|
||||
return;
|
||||
|
||||
resp.NPCAppearanceData.iNPC_ID = rand(); // cpunch-style
|
||||
|
@ -20,16 +20,20 @@ void NanoManager::nanoEquipHandler(CNSocket* sock, CNPacketData* data) {
|
||||
INITSTRUCT(sP_FE2CL_REP_NANO_EQUIP_SUCC, resp);
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
if (nano->iNanoSlotNum > 2)
|
||||
// sanity check
|
||||
if (nano->iNanoSlotNum > 2 || nano->iNanoSlotNum < 0)
|
||||
return;
|
||||
|
||||
resp.iNanoID = nano->iNanoID;
|
||||
resp.iNanoSlotNum = nano->iNanoSlotNum;
|
||||
|
||||
|
||||
// Update player
|
||||
plr->equippedNanos[nano->iNanoSlotNum] = nano->iNanoID;
|
||||
|
||||
// unsummon nano if replaced
|
||||
if (plr->activeNano == plr->equippedNanos[nano->iNanoSlotNum])
|
||||
summonNano(sock, -1);
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_NANO_EQUIP_SUCC, sizeof(sP_FE2CL_REP_NANO_EQUIP_SUCC));
|
||||
}
|
||||
|
||||
@ -41,11 +45,16 @@ void NanoManager::nanoUnEquipHandler(CNSocket* sock, CNPacketData* data) {
|
||||
INITSTRUCT(sP_FE2CL_REP_NANO_UNEQUIP_SUCC, resp);
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
if (nano->iNanoSlotNum > 2)
|
||||
// sanity check
|
||||
if (nano->iNanoSlotNum > 2 || nano->iNanoSlotNum < 0)
|
||||
return;
|
||||
|
||||
resp.iNanoSlotNum = nano->iNanoSlotNum;
|
||||
|
||||
// unsummon nano if removed
|
||||
if (plr->equippedNanos[nano->iNanoSlotNum] == plr->activeNano)
|
||||
summonNano(sock, -1);
|
||||
|
||||
// update player
|
||||
plr->equippedNanos[nano->iNanoSlotNum] = 0;
|
||||
|
||||
@ -75,33 +84,9 @@ void NanoManager::nanoSummonHandler(CNSocket* sock, CNPacketData* data) {
|
||||
sP_CL2FE_REQ_NANO_ACTIVE* pkt = (sP_CL2FE_REQ_NANO_ACTIVE*)data->buf;
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
summonNano(sock, pkt->iNanoSlotNum);
|
||||
|
||||
// Send to client
|
||||
INITSTRUCT(sP_FE2CL_REP_NANO_ACTIVE_SUCC, resp);
|
||||
resp.iActiveNanoSlotNum = pkt->iNanoSlotNum;
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_NANO_ACTIVE_SUCC, sizeof(sP_FE2CL_REP_NANO_ACTIVE_SUCC));
|
||||
|
||||
if (pkt->iNanoSlotNum > 2)
|
||||
return;
|
||||
|
||||
int nanoId = plr->equippedNanos[pkt->iNanoSlotNum];
|
||||
|
||||
if (nanoId > 36)
|
||||
return; // sanity check
|
||||
|
||||
sNano nano = plr->Nanos[nanoId];
|
||||
|
||||
// Send to other players
|
||||
INITSTRUCT(sP_FE2CL_NANO_ACTIVE, pkt1);
|
||||
|
||||
pkt1.iPC_ID = plr->iID;
|
||||
pkt1.Nano = nano;
|
||||
|
||||
for (CNSocket* s : PlayerManager::players[sock].viewable)
|
||||
s->sendPacket((void*)&pkt1, P_FE2CL_NANO_ACTIVE, sizeof(sP_FE2CL_NANO_ACTIVE));
|
||||
|
||||
// update player
|
||||
plr->activeNano = nanoId;
|
||||
|
||||
DEBUGLOG(
|
||||
std::cout << U16toU8(plr->PCStyle.szFirstName) << U16toU8(plr->PCStyle.szLastName) << " requested to summon nano slot: " << pkt->iNanoSlotNum << std::endl;
|
||||
)
|
||||
@ -158,6 +143,37 @@ void NanoManager::addNano(CNSocket* sock, int16_t nanoId, int16_t slot) {
|
||||
plr->Nanos[nanoId] = resp.Nano;
|
||||
}
|
||||
|
||||
void NanoManager::summonNano(CNSocket *sock, int slot) {
|
||||
INITSTRUCT(sP_FE2CL_REP_NANO_ACTIVE_SUCC, resp);
|
||||
resp.iActiveNanoSlotNum = slot;
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_NANO_ACTIVE_SUCC, sizeof(sP_FE2CL_REP_NANO_ACTIVE_SUCC));
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
std::cout << "summon nano\n";
|
||||
|
||||
if (slot > 2 || slot < 0)
|
||||
return; //sanity check
|
||||
|
||||
int nanoId = plr->equippedNanos[slot];
|
||||
|
||||
if (nanoId > 36 || nanoId < 0)
|
||||
return; // sanity check
|
||||
|
||||
sNano nano = plr->Nanos[nanoId];
|
||||
|
||||
// Send to other players
|
||||
INITSTRUCT(sP_FE2CL_NANO_ACTIVE, pkt1);
|
||||
|
||||
pkt1.iPC_ID = plr->iID;
|
||||
pkt1.Nano = nano;
|
||||
|
||||
for (CNSocket* s : PlayerManager::players[sock].viewable)
|
||||
s->sendPacket((void*)&pkt1, P_FE2CL_NANO_ACTIVE, sizeof(sP_FE2CL_NANO_ACTIVE));
|
||||
|
||||
// update player
|
||||
plr->activeNano = nanoId;
|
||||
}
|
||||
|
||||
void NanoManager::setNanoSkill(CNSocket* sock, int16_t nanoId, int16_t skillId) {
|
||||
if (nanoId > 36)
|
||||
return;
|
||||
|
@ -13,6 +13,7 @@ namespace NanoManager {
|
||||
|
||||
// Helper methods
|
||||
void addNano(CNSocket* sock, int16_t nanoId, int16_t slot);
|
||||
void summonNano(CNSocket* sock, int slot);
|
||||
void setNanoSkill(CNSocket* sock, int16_t nanoId, int16_t skillId);
|
||||
void resetNanoSkill(CNSocket* sock, int16_t nanoId);
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#ifndef _PLR_HPP
|
||||
#define _PLR_HPP
|
||||
|
||||
#include "CNProtocol.hpp"
|
||||
#include "CNStructs.hpp"
|
||||
|
||||
@ -15,6 +14,7 @@ struct Player {
|
||||
int level;
|
||||
int HP;
|
||||
int slot; // player slot, not nano slot
|
||||
int32_t money;
|
||||
sPCStyle PCStyle;
|
||||
sPCStyle2 PCStyle2;
|
||||
sNano Nanos[37]; // acquired nanos
|
||||
@ -25,7 +25,9 @@ struct Player {
|
||||
int x, y, z, angle;
|
||||
sItemBase Equip[AEQUIP_COUNT];
|
||||
sItemBase Inven[AINVEN_COUNT];
|
||||
sItemTrade Trade[12];
|
||||
int32_t moneyInTrade;
|
||||
bool IsTrading;
|
||||
bool IsTradeConfirm;
|
||||
bool IsGM;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -55,18 +55,18 @@ void PlayerManager::removePlayer(CNSocket* key) {
|
||||
for (CNSocket* otherSock : players[key].viewable) {
|
||||
players[otherSock].viewable.remove(key); // gone
|
||||
|
||||
// now sent PC_EXIT packet
|
||||
// now send PC_EXIT packet
|
||||
sP_FE2CL_PC_EXIT exitPacket;
|
||||
exitPacket.iID = players[key].plr->iID;
|
||||
|
||||
otherSock->sendPacket((void*)&exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT));
|
||||
}
|
||||
|
||||
delete cachedView.plr;
|
||||
players.erase(key);
|
||||
|
||||
std::cout << U16toU8(cachedView.plr->PCStyle.szFirstName) << U16toU8(cachedView.plr->PCStyle.szLastName) << " has left!" << std::endl;
|
||||
std::cout << players.size() << " players" << std::endl;
|
||||
|
||||
delete cachedView.plr;
|
||||
players.erase(key);
|
||||
}
|
||||
|
||||
void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z) {
|
||||
@ -85,7 +85,7 @@ void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z) {
|
||||
int diffX = abs(pair.second.plr->x - X); // the map is like a grid, X and Y are your position on the map, Z is the height. very different from other games...
|
||||
int diffY = abs(pair.second.plr->y - Y);
|
||||
|
||||
if (diffX < settings::VIEWDISTANCE && diffY < settings::VIEWDISTANCE) {
|
||||
if (diffX < settings::PLAYERDISTANCE && diffY < settings::PLAYERDISTANCE) {
|
||||
yesView.push_back(pair.first);
|
||||
}
|
||||
else {
|
||||
@ -196,12 +196,14 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
response.PCLoadData2CL.iUserLevel = 1;
|
||||
response.PCLoadData2CL.iHP = 3625; //TODO: Check player levelupdata and get this right
|
||||
response.PCLoadData2CL.iLevel = plr.level;
|
||||
response.PCLoadData2CL.iCandy = plr.money;
|
||||
response.PCLoadData2CL.iMentor = 1;
|
||||
response.PCLoadData2CL.iMentorCount = 4;
|
||||
response.PCLoadData2CL.iMapNum = 0;
|
||||
response.PCLoadData2CL.iX = plr.x;
|
||||
response.PCLoadData2CL.iY = plr.y;
|
||||
response.PCLoadData2CL.iZ = plr.z;
|
||||
response.PCLoadData2CL.iAngle = 130;
|
||||
response.PCLoadData2CL.iActiveNanoSlotNum = -1;
|
||||
response.PCLoadData2CL.iFatigue = 50;
|
||||
response.PCLoadData2CL.PCStyle = plr.PCStyle;
|
||||
@ -256,6 +258,7 @@ void PlayerManager::loadPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
|
||||
sP_CL2FE_REQ_PC_LOADING_COMPLETE* complete = (sP_CL2FE_REQ_PC_LOADING_COMPLETE*)data->buf;
|
||||
INITSTRUCT(sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC, response);
|
||||
Player *plr = getPlayer(sock);
|
||||
|
||||
DEBUGLOG(
|
||||
std::cout << "P_CL2FE_REQ_PC_LOADING_COMPLETE:" << std::endl;
|
||||
@ -264,6 +267,9 @@ void PlayerManager::loadPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
|
||||
response.iPC_ID = complete->iPC_ID;
|
||||
|
||||
// reload players & NPCs
|
||||
updatePlayerPosition(sock, plr->x, plr->y, plr->z);
|
||||
|
||||
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_LOADING_COMPLETE_SUCC, sizeof(sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC));
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,8 @@ bool settings::LOGINRANDCHARACTERS = false;
|
||||
|
||||
int settings::SHARDPORT = 8002;
|
||||
std::string settings::SHARDSERVERIP = "127.0.0.1";
|
||||
int settings::VIEWDISTANCE = 20000;
|
||||
int settings::PLAYERDISTANCE = 20000;
|
||||
int settings::NPCDISTANCE = 16000;
|
||||
|
||||
// default spawn point is city hall
|
||||
int settings::SPAWN_X = 179213;
|
||||
@ -39,7 +40,8 @@ void settings::init() {
|
||||
LOGINRANDCHARACTERS = reader.GetBoolean("login", "randomcharacters", LOGINRANDCHARACTERS);
|
||||
SHARDPORT = reader.GetInteger("shard", "port", SHARDPORT);
|
||||
SHARDSERVERIP = reader.Get("shard", "ip", "127.0.0.1");
|
||||
VIEWDISTANCE = reader.GetInteger("shard", "view", VIEWDISTANCE);
|
||||
PLAYERDISTANCE = reader.GetInteger("shard", "playerdistance", PLAYERDISTANCE);
|
||||
NPCDISTANCE = reader.GetInteger("shard", "npcdistance", NPCDISTANCE);
|
||||
SPAWN_X = reader.GetInteger("shard", "spawnx", SPAWN_X);
|
||||
SPAWN_Y = reader.GetInteger("shard", "spawny", SPAWN_Y);
|
||||
SPAWN_Z = reader.GetInteger("shard", "spawnz", SPAWN_Z);
|
||||
|
@ -6,7 +6,8 @@ namespace settings {
|
||||
extern bool LOGINRANDCHARACTERS;
|
||||
extern int SHARDPORT;
|
||||
extern std::string SHARDSERVERIP;
|
||||
extern int VIEWDISTANCE;
|
||||
extern int PLAYERDISTANCE;
|
||||
extern int NPCDISTANCE;
|
||||
extern int SPAWN_X;
|
||||
extern int SPAWN_Y;
|
||||
extern int SPAWN_Z;
|
||||
|
Loading…
x
Reference in New Issue
Block a user