@@ -328,8 +328,8 @@ static void itemMoveHandler(CNSocket* sock, CNPacketData* data) {
328328 && !(fromItem->iType == 0 && itemmove->iToSlotNum == 7 )
329329 && fromItem->iType != itemmove->iToSlotNum )
330330 return ; // something other than a vehicle or a weapon in a non-matching slot
331- else if (itemmove->iToSlotNum >= AEQUIP_COUNT) // TODO: reject slots >= 9?
332- return ; // invalid slot
331+ else if (itemmove->iToSlotNum > 8 )
332+ return ; // any slot higher than 8 is for a booster, and they can't be equipped via move packet
333333 }
334334
335335 // save items to response
@@ -430,25 +430,14 @@ static void itemDeleteHandler(CNSocket* sock, CNPacketData* data) {
430430 sock->sendPacket (resp, P_FE2CL_REP_PC_ITEM_DELETE_SUCC);
431431}
432432
433- static void itemUseHandler (CNSocket* sock, CNPacketData* data) {
433+ static void useGumball (CNSocket* sock, CNPacketData* data) {
434434 auto request = (sP_CL2FE_REQ_ITEM_USE *)data->buf ;
435435 Player* player = PlayerManager::getPlayer (sock);
436436
437- if (request->iSlotNum < 0 || request->iSlotNum >= AINVEN_COUNT)
438- return ; // sanity check
439-
440437 // gumball can only be used from inventory, so we ignore eIL
441438 sItemBase gumball = player->Inven [request->iSlotNum ];
442439 sNano nano = player->Nanos [player->equippedNanos [request->iNanoSlot ]];
443440
444- // sanity check, check if gumball exists
445- if (!(gumball.iOpt > 0 && gumball.iType == 7 && gumball.iID >=119 && gumball.iID <=121 )) {
446- std::cout << " [WARN] Gumball not found" << std::endl;
447- INITSTRUCT (sP_FE2CL_REP_PC_ITEM_USE_FAIL , response);
448- sock->sendPacket (response, P_FE2CL_REP_PC_ITEM_USE_FAIL);
449- return ;
450- }
451-
452441 // sanity check, check if gumball type matches nano style
453442 int nanoStyle = Nanos::nanoStyle (nano.iID );
454443 if (!((gumball.iID == 119 && nanoStyle == 0 ) ||
@@ -472,11 +461,8 @@ static void itemUseHandler(CNSocket* sock, CNPacketData* data) {
472461 return ;
473462 }
474463
475- if (gumball.iOpt == 0 )
476- gumball = {};
477-
478- uint8_t respbuf[CN_PACKET_BODY_SIZE];
479- memset (respbuf, 0 , CN_PACKET_BODY_SIZE);
464+ uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
465+ memset (respbuf, 0 , resplen);
480466
481467 sP_FE2CL_REP_PC_ITEM_USE_SUCC *resp = (sP_FE2CL_REP_PC_ITEM_USE_SUCC *)respbuf;
482468 sSkillResult_Buff *respdata = (sSkillResult_Buff *)(respbuf+sizeof (sP_FE2CL_NANO_SKILL_USE_SUCC ));
@@ -515,6 +501,54 @@ static void itemUseHandler(CNSocket* sock, CNPacketData* data) {
515501 player->Inven [resp->iSlotNum ] = resp->RemainItem ;
516502}
517503
504+ static void useNanocomBooster (CNSocket* sock, CNPacketData* data) {
505+
506+ }
507+
508+ static void itemUseHandler (CNSocket* sock, CNPacketData* data) {
509+ auto request = (sP_CL2FE_REQ_ITEM_USE *)data->buf ;
510+ Player* player = PlayerManager::getPlayer (sock);
511+
512+ if (request->iSlotNum < 0 || request->iSlotNum >= AINVEN_COUNT)
513+ return ; // sanity check
514+
515+ sItemBase item = player->Inven [request->iSlotNum ];
516+
517+ // sanity check, check the item exists and has correct iType
518+ if (!(item.iOpt > 0 && item.iType == 7 )) {
519+ std::cout << " [WARN] General item not found" << std::endl;
520+ INITSTRUCT (sP_FE2CL_REP_PC_ITEM_USE_FAIL , response);
521+ sock->sendPacket (response, P_FE2CL_REP_PC_ITEM_USE_FAIL);
522+ return ;
523+ }
524+
525+ /*
526+ * TODO: In the XDT, there are subtypes for general-use items
527+ * (m_pGeneralItemTable -> m_pItemData-> m_iItemType) that
528+ * determine their behavior. It would be better to load these
529+ * and use them in this switch, rather than hardcoding by IDs.
530+ */
531+
532+ switch (item.iID ) {
533+ case 119 :
534+ case 120 :
535+ case 121 :
536+ useGumball (sock, data);
537+ break ;
538+ case 153 :
539+ case 154 :
540+ case 155 :
541+ case 156 :
542+ useNanocomBooster (sock, data);
543+ break ;
544+ default :
545+ std::cout << " [INFO] General item " << item.iID << " is unimplemented." << std::endl;
546+ INITSTRUCT (sP_FE2CL_REP_PC_ITEM_USE_FAIL , response);
547+ sock->sendPacket (response, P_FE2CL_REP_PC_ITEM_USE_FAIL);
548+ break ;
549+ }
550+ }
551+
518552static void itemBankOpenHandler (CNSocket* sock, CNPacketData* data) {
519553 Player* plr = PlayerManager::getPlayer (sock);
520554
@@ -633,14 +667,14 @@ Item* Items::getItemData(int32_t id, int32_t type) {
633667}
634668
635669void Items::checkItemExpire (CNSocket* sock, Player* player) {
636- if (player->toRemoveVehicle .eIL == 0 && player->toRemoveVehicle .iSlotNum == 0 )
670+ if (player->expiringItem .eIL == 0 && player->expiringItem .iSlotNum == 0 )
637671 return ;
638672
639673 /* prepare packet
640674 * yes, this is a varadic packet, however analyzing client behavior and code
641675 * it only checks takes the first item sent into account
642676 * yes, this is very stupid
643- * therefore, we delete all but 1 expired vehicle while loading player
677+ * therefore, we delete all but 1 expired item while loading player
644678 * to delete the last one here so player gets a notification
645679 */
646680
@@ -653,18 +687,18 @@ void Items::checkItemExpire(CNSocket* sock, Player* player) {
653687 memset (respbuf, 0 , resplen);
654688
655689 packet->iItemListCount = 1 ;
656- itemData->eIL = player->toRemoveVehicle .eIL ;
657- itemData->iSlotNum = player->toRemoveVehicle .iSlotNum ;
690+ itemData->eIL = player->expiringItem .eIL ;
691+ itemData->iSlotNum = player->expiringItem .iSlotNum ;
658692 sock->sendPacket ((void *)&respbuf, P_FE2CL_PC_DELETE_TIME_LIMIT_ITEM, resplen);
659693
660694 // delete serverside
661- if (player->toRemoveVehicle .eIL == 0 )
662- memset (&player->Equip [8 ], 0 , sizeof (sItemBase ));
695+ if (player->expiringItem .eIL == 0 )
696+ memset (&player->Equip [player-> expiringItem . iSlotNum ], 0 , sizeof (sItemBase ));
663697 else
664- memset (&player->Inven [player->toRemoveVehicle .iSlotNum ], 0 , sizeof (sItemBase ));
698+ memset (&player->Inven [player->expiringItem .iSlotNum ], 0 , sizeof (sItemBase ));
665699
666- player->toRemoveVehicle .eIL = 0 ;
667- player->toRemoveVehicle .iSlotNum = 0 ;
700+ player->expiringItem .eIL = 0 ;
701+ player->expiringItem .iSlotNum = 0 ;
668702}
669703
670704void Items::setItemStats (Player* plr) {
@@ -857,7 +891,6 @@ void Items::giveMobDrop(CNSocket *sock, Mob* mob, const DropRoll& rolled, const
857891void Items::init () {
858892 REGISTER_SHARD_PACKET (P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler);
859893 REGISTER_SHARD_PACKET (P_CL2FE_REQ_PC_ITEM_DELETE, itemDeleteHandler);
860- // this one is for gumballs
861894 REGISTER_SHARD_PACKET (P_CL2FE_REQ_ITEM_USE, itemUseHandler);
862895 // Bank
863896 REGISTER_SHARD_PACKET (P_CL2FE_REQ_PC_BANK_OPEN, itemBankOpenHandler);
0 commit comments