Tradeskill Update

Many tradeskill updates, the following issues should be resolved
- Counter successes/fails don't seem to have any effect on durability/progress more than a regular tick.
- Every recipe has the description "The art of sculpting metal into a candelabra." in the mouseover tooltip.
- Materials and fuels stored in bank are counted for use in recipes.
- Recipes with a primary component that is not owned in inventory (or bank) show as "Primary Component: [0]" in the recipe tooltip when hovering the recipe icon in the recipe window, instead of red-colored text "Primary Component: Bronze Cluster [0]". This is only with primary components. Build components and fuel components don't have this same behavior.
- Recipes can be crafted from recipe window, without having a crafting station selected or even being near one.
- T1 rawhide leather pelts harvested from dens are not the same pelts needed for any recipe that requires rawhide leather pelts:
    Alder, Bronze, Sackcloth, Tranquil Sackcloth, Waxed Leather, Woven Waxed, Elm, Rawhide Leather, Woven Rawhide, Threadbare, Tranquil Threadbare, Tin (probably more)
- examine recipe windows fixed, including showing total amounts of components in your inventory and previously created stage now displays as intended
- when in the craft recipe screen (prior to pressing begin) you may now select components to craft with, all available will be listed that can be used
This commit is contained in:
Robert Allen 2022-11-25 12:05:42 -06:00
parent d7ee900396
commit 12a348199a
10 changed files with 528 additions and 433 deletions

View file

@ -3180,7 +3180,34 @@ bool PlayerItemList::GetFirstFreeSlot(sint32* bag_id, sint16* slot) {
MPlayerItems.releasereadlock(__FUNCTION__, __LINE__);
return ret;
}
vector<Item*> PlayerItemList::GetAllItemsFromID(int32 id, bool include_bank, bool lock) {
//first check for an exact count match
map<sint32, map<int8, map<int16, Item*>> >::iterator itr;
map<int16, Item*>::iterator slot_itr;
vector<Item*> ret ;
if (lock)
MPlayerItems.readlock(__FUNCTION__, __LINE__);
for (itr = items.begin(); itr != items.end(); itr++) {
if (include_bank || (!include_bank && itr->first >= 0)) {
for (int8 i = 0; i < MAX_EQUIPMENT; i++)
{
for (slot_itr = itr->second[i].begin(); slot_itr != itr->second[i].end(); slot_itr++) {
if (slot_itr->second && slot_itr->second->details.item_id == id) {
if (lock)
MPlayerItems.releasereadlock(__FUNCTION__, __LINE__);
int32 yyy = 0;
ret.push_back(slot_itr->second);
//return slot_itr->second;
}
}
}
}
}
return ret;
}
Item* PlayerItemList::CanStack(Item* item, bool include_bank){
if(!item || item->stack_count < 2)
return 0;

View file

@ -1042,6 +1042,7 @@ public:
Item* GetItem(int32 id);
Item* GetItemByName(const char *name);
Item* GetAllItemsByClassification(const char* name);
ItemStatsValues* CalculateItemBonuses(int32 item_id, Entity* entity = 0);
ItemStatsValues* CalculateItemBonuses(Item* desc, Entity* entity = 0, ItemStatsValues* values = 0);
vector<Item*>* GetItems(string name, int64 itype, int64 ltype, int64 btype, int64 minprice, int64 maxprice, int8 minskill, int8 maxskill, string seller, string adornment, int8 mintier, int8 maxtier, int16 minlevel, int16 maxlevel, sint8 itemclass);
@ -1092,7 +1093,7 @@ public:
bool HasFreeBagSlot();
void DestroyItem(int16 index);
Item* CanStack(Item* item, bool include_bank = false);
vector<Item*> GetAllItemsFromID(int32 item, bool include_bank = false, bool lock = false);
void RemoveItem(Item* item, bool delete_item = false);
bool AddItem(Item* item);

View file

@ -28,6 +28,7 @@
extern ConfigReader configReader;
extern MasterItemList master_item_list;
Recipe::Recipe() {
id = 0;
book_id = 0;
@ -304,7 +305,7 @@ EQ2Packet * Recipe::SerializeRecipe(Client *client, Recipe *recipe, bool display
RecipeProducts* rp = 0;
vector<int32>::iterator itr;
vector<RecipeComp> comp_list;
int8 i = 0;
int32 firstID = 0;
int32 primary_comp_id = 0;
@ -341,43 +342,69 @@ EQ2Packet * Recipe::SerializeRecipe(Client *client, Recipe *recipe, bool display
packet->setSubstructDataByName("recipe_info", "unknown3", 1);
packet->setSubstructDataByName("recipe_info", "adventure_id", 0xFF);
packet->setSubstructDataByName("recipe_info", "tradeskill_id", client ? client->GetPlayer()->GetTradeskillClass() : 0);
packet->setSubstructDataByName("recipe_info", "unknown4", 100);
packet->setSubstructDataByName("recipe_info", "unknown4a", 100);
packet->setSubstructDataByName("recipe_info", "unknown4aa", 1);
packet->setSubstructDataByName("recipe_info", "unknown5a", 20);
packet->setSubstructDataByName("recipe_info", "unknown5a", 20);//level *10
packet->setSubstructDataByName("recipe_info", "product_classes", recipe->GetClasses());
packet->setSubstructDataByName("recipe_info", "show_previous", 15);
packet->setSubstructDataByName("recipe_info", "previous1_icon", 186);
packet->setSubstructDataByName("recipe_info", "previous1_name", "previous1_name");
packet->setSubstructDataByName("recipe_info", "previous1_qty", 1);
packet->setSubstructDataByName("recipe_info", "previous1_item_id", 4142);
packet->setSubstructDataByName("recipe_info", "previous1_item_crc", -853046774);
packet->setSubstructDataByName("recipe_info", "previous2_icon", 186);
packet->setSubstructDataByName("recipe_info", "previous2_name", "previous2_name");
packet->setSubstructDataByName("recipe_info", "previous2_qty", 1);
packet->setSubstructDataByName("recipe_info", "previous2_item_id", 4142);
packet->setSubstructDataByName("recipe_info", "previous2_item_crc", -853046774);
packet->setSubstructDataByName("recipe_info", "previous3_icon", 186);
packet->setSubstructDataByName("recipe_info", "previous3_name", "previous3_name");
packet->setSubstructDataByName("recipe_info", "previous3_qty", 1);
packet->setSubstructDataByName("recipe_info", "previous3_item_id", 4142);
packet->setSubstructDataByName("recipe_info", "previous3_item_crc", -853046774);
packet->setSubstructDataByName("recipe_info", "firstbar_icon", 186);
packet->setSubstructDataByName("recipe_info", "firstbar_name", "firstbar_name");
packet->setSubstructDataByName("recipe_info", "firstbar_qty", 1);
packet->setSubstructDataByName("recipe_info", "firstbar_item_id", 4142);
packet->setSubstructDataByName("recipe_info", "firstbar_item_crc", -853046774);
packet->setSubstructDataByName("recipe_info", "secondbar_icon", 186);
packet->setSubstructDataByName("recipe_info", "secondbar_name", "secondbar_name");
packet->setSubstructDataByName("recipe_info", "secondbar_qty", 1);
packet->setSubstructDataByName("recipe_info", "secondbar_item_id", 4142);
packet->setSubstructDataByName("recipe_info", "secondbar_item_crc", -853046774);
packet->setSubstructDataByName("recipe_info", "thirdbar_icon", 198);
packet->setSubstructDataByName("recipe_info", "thirdbar_name", "thirdbar_name");
packet->setSubstructDataByName("recipe_info", "thirdbar_qty", 1);
packet->setSubstructDataByName("recipe_info", "thirdbar_item_id", 12098);
packet->setSubstructDataByName("recipe_info", "show_previous", client->GetPlayer()->GetRecipeList()->GetRecipe(recipe->GetID())->highestStage);// recipe->highestStage);
packet->setSubstructDataByName("recipe_info", "thirdbar_item_crc", -2065846136);
item = master_item_list.GetItemByName(recipe->GetName());
rp = recipe->products[1];
if (rp->product_id > 0) {
item = 0;
item = master_item_list.GetItem(rp->product_id);
if (item) {
packet->setSubstructDataByName("recipe_info", "previous1_icon", item->details.icon);
packet->setSubstructDataByName("recipe_info", "previous1_name", "previous1_name");
packet->setSubstructDataByName("recipe_info", "previous1_qty", recipe->products[1]->product_qty);
packet->setSubstructDataByName("recipe_info", "previous1_item_id", recipe->products[1]->product_id);
packet->setSubstructDataByName("recipe_info", "previous1_item_crc", -853046774);
packet->setSubstructDataByName("recipe_info", "firstbar_icon", item->details.icon);
packet->setSubstructDataByName("recipe_info", "firstbar_name", "firstbar_name");
packet->setSubstructDataByName("recipe_info", "firstbar_qty", recipe->products[1]->product_qty);
packet->setSubstructDataByName("recipe_info", "firstbar_item_id", recipe->products[2]->product_id);
packet->setSubstructDataByName("recipe_info", "firstbar_item_crc", -853046774);
}
}
rp = recipe->products[2];
if (rp->product_id > 0) {
item = 0;
item = master_item_list.GetItem(rp->product_id);
if (item) {
packet->setSubstructDataByName("recipe_info", "previous2_icon", item->details.icon);
packet->setSubstructDataByName("recipe_info", "previous2_name", "previous2_name");
packet->setSubstructDataByName("recipe_info", "previous2_qty", recipe->products[2]->product_qty);
packet->setSubstructDataByName("recipe_info", "previous2_item_id", recipe->products[2]->product_id);
packet->setSubstructDataByName("recipe_info", "previous2_item_crc", -853046774);
packet->setSubstructDataByName("recipe_info", "secondbar_icon", item->details.icon);
packet->setSubstructDataByName("recipe_info", "secondbar_name", "secondbar_name");
packet->setSubstructDataByName("recipe_info", "secondbar_qty", recipe->products[2]->product_qty);
packet->setSubstructDataByName("recipe_info", "secondbar_item_id", recipe->products[2]->product_id);
packet->setSubstructDataByName("recipe_info", "secondbar_item_crc", -853046774);
}
}
rp = recipe->products[3];
if (rp->product_id > 0) {
item = 0;
item = master_item_list.GetItem(rp->product_id);
if (item) {
packet->setSubstructDataByName("recipe_info", "previous3_icon", item->details.icon);
packet->setSubstructDataByName("recipe_info", "previous3_name", "previous3_name");
packet->setSubstructDataByName("recipe_info", "previous3_qty", recipe->products[3]->product_qty);
packet->setSubstructDataByName("recipe_info", "previous3_item_id", recipe->products[3]->product_id);
packet->setSubstructDataByName("recipe_info", "previous3_item_crc", -853046774);
packet->setSubstructDataByName("recipe_info", "thirdbar_icon", item->details.icon);
packet->setSubstructDataByName("recipe_info", "thirdbar_name", "thirdbar_name");
packet->setSubstructDataByName("recipe_info", "thirdbar_qty", recipe->products[3]->product_qty);
packet->setSubstructDataByName("recipe_info", "thirdbar_item_id", recipe->products[3]->product_id);
packet->setSubstructDataByName("recipe_info", "thirdbar_item_crc", -2065846136);
}
}
item = master_item_list.GetItemByName(recipe->GetName());// TODO: MJ we should be getting item by item number in case of multiple items with same name
if(item) {
packet->setSubstructDataByName("recipe_info", "product_icon", item->details.icon); //item->details.icon);
packet->setSubstructDataByName("recipe_info", "product_name", item->name.c_str()); //item->name);
@ -385,6 +412,7 @@ EQ2Packet * Recipe::SerializeRecipe(Client *client, Recipe *recipe, bool display
packet->setSubstructDataByName("recipe_info", "product_item_id", item->details.item_id); //item->details.item_id);
packet->setSubstructDataByName("recipe_info", "product_item_crc", 0); //item->details.item_crc);
}
rp = recipe->products[0];
if (rp->byproduct_id > 0) {
item = 0;
@ -393,48 +421,46 @@ EQ2Packet * Recipe::SerializeRecipe(Client *client, Recipe *recipe, bool display
packet->setSubstructDataByName("recipe_info", "byproduct_icon", item->details.icon);//11
packet->setSubstructDataByName("recipe_info", "byproduct_id", item->details.item_id);
}
}
//string xxx = recipe->
//item = master_item_list.GetItemByName (recipe->GetBuild1ComponentTitle());
// Reset item to 0
rp = recipe->products[1];
if (rp->product_id > 0) {
item = 0;
item = master_item_list.GetItem(rp->product_id);
if (item) {
packet->setSubstructDataByName("recipe_info", "byproduct_icon", item->details.icon);//11
packet->setSubstructDataByName("recipe_info", "byproduct_id", item->details.item_id);
}
}
item = 0;
// Check to see if we have a primary component (slot = 0)
vector<Item*> itemss;
if (recipe->components.count(0) > 0) {
vector<int32> rc = recipe->components[0];
for (itr = rc.begin(); itr != rc.end(); itr++, i++) {
if (firstID == 0)
firstID = *itr;
item = master_item_list.GetItem(*itr);
packet->setSubstructDataByName("recipe_info", "primary_comp", recipe->primary_build_comp_title);
packet->setSubstructDataByName("recipe_info", "primary_qty", recipe->GetPrimaryComponentQuantity());
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID((*itr));
if (item) {
packet->setSubstructDataByName("recipe_info", "primary_qty_avail", item->details.count);
packet->setSubstructDataByName("recipe_info", "primary_comp", recipe->primary_build_comp_title);
itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
if (itemss.size() > 0) {
int16 needed_qty = recipe->GetPrimaryComponentQuantity();
int16 have_qty = 0;
for (int8 i = 0; i < itemss.size(); i++) {
have_qty += itemss[i]->details.count;
}
packet->setSubstructDataByName("recipe_info", "primary_qty_avail", have_qty);
break;
}
}
}
// store the id of the primary comp
primary_comp_id = firstID;
// Set the default item id to the first component id
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID(firstID);
if (item) {
}
// Reset the variables we will reuse
i = 0;
firstID = 0;
item = 0;
}
else {
LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Recipe has no primary component");
}
int8 total_build_components = 0;
if (recipe->components.count(1) > 0)
@ -450,205 +476,64 @@ EQ2Packet * Recipe::SerializeRecipe(Client *client, Recipe *recipe, bool display
if (total_build_components > 0) {
packet->setSubstructArrayLengthByName("recipe_info", "num_comps", total_build_components);
for (int8 index = 0; index < 4; index++) {
if (recipe->components.count(index + 1) == 0)
continue;
//packet->setArrayDataByName("build_slot", index, index);
vector<int32> rc = recipe->components[index + 1];
//packet->setSubArrayLengthByName("num_build_choices", rc.size(), index);
int16 have_qty = 0;
string comp_title;
int8 comp_qty;
for (itr = rc.begin(); itr != rc.end(); itr++, i++) {
if (firstID == 0)
firstID = *itr;
string comp_title;
int8 comp_qty;
if (index == 0) {
comp_title = recipe->build1_comp_title;
comp_qty = recipe->build_comp_qty;
item = master_item_list.GetItem(*itr);
packet->setArrayDataByName("build_comp", comp_title.c_str(), index );
packet->setArrayDataByName("build_comp_qty", comp_qty, index );
item = master_item_list.GetItem(*itr);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID((*itr));
if (item) {
packet->setArrayDataByName("build_comp_qty_avail", item->details.count, index );
}
comp_qty = recipe->build1_comp_qty;
}
else if (index == 1) {
comp_title = recipe->build2_comp_title;
comp_qty = recipe->build2_comp_qty;
item = master_item_list.GetItem(*itr);
packet->setArrayDataByName("build_comp", comp_title.c_str(), index );
packet->setArrayDataByName("build_comp_qty", comp_qty, index );
item = master_item_list.GetItem(*itr);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID((*itr));
if (item) {
packet->setArrayDataByName("build_comp_qty_avail", item->details.count, index );
break;
}
}
else if (index == 2) {
comp_title = recipe->build3_comp_title;
comp_qty = recipe->build3_comp_qty;
item = master_item_list.GetItem(*itr);
packet->setArrayDataByName("build_comp", comp_title.c_str(), index );
packet->setArrayDataByName("build_comp_qty", comp_qty, index );
item = master_item_list.GetItem(*itr);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID((*itr));
if (item) {
packet->setArrayDataByName("build_comp_qty_avail", item->details.count, index );
break;
}
}
else if (index == 3) {
comp_title = recipe->build4_comp_title;
comp_qty = recipe->build4_comp_qty;
item = master_item_list.GetItem(*itr);
packet->setArrayDataByName("build_comp", comp_title.c_str(), index );
packet->setArrayDataByName("build_comp_qty", comp_qty, index );
item = master_item_list.GetItem(*itr);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID((*itr));
if (item) {
packet->setArrayDataByName("build_comp_qty_avail", item->details.count, index );
break;
}
}
//item = master_item_list.GetItem(*itr);
//packet->setArrayDataByName("build_comp", comp_title.c_str(), index -1);
//packet->setArrayDataByName("build_comp_qty", comp_qty, index - 1);
//item = master_item_list.GetItem(*itr);
//item = 0;
//item = client->GetPlayer()->item_list.GetItemFromID((*itr));
//if (item) {
// packet->setArrayDataByName("build_comp_qty_avail", item->details.count, index - 1);
//}
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID((*itr));
if (item) {
//packet->setSubArrayDataByName("build_total_quantity", item->details.count, index, i);
}
item = master_item_list.GetItem(*itr);
itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
for (int8 j = 0; j < itemss.size(); j++) {
have_qty += itemss[j]->details.count;
}
// Set the default item id to the first component id
//packet->setArrayDataByName("build_item_selected", 1, index);
//packet->setArrayDataByName("build_selected_item_id", firstID, index);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID(firstID);
int8 qty = 0;
if (item) {
qty = (int8)item->details.count;
if (qty > 0 && firstID == primary_comp_id)
qty -= 1;
}
if (index == 0) {
// packet->setArrayDataByName("build_title", recipe->GetBuild1ComponentTitle(), index);
//packet->setArrayDataByName("build_qty", recipe->GetBuild1ComponentQuantity(), index);
if (item) {
// packet->setArrayDataByName("build_selected_item_qty", min(qty, recipe->GetBuild1ComponentQuantity()), index);
}
}
else if (index == 1) {
// packet->setArrayDataByName("build_title", recipe->GetBuild2ComponentTitle(), index);
// packet->setArrayDataByName("build_qty", recipe->GetBuild2ComponentQuantity(), index);
if (item) {
// packet->setArrayDataByName("build_selected_item_qty", min(qty, recipe->GetBuild2ComponentQuantity()), index);
}
}
else if (index == 2) {
// packet->setArrayDataByName("build_title", recipe->GetBuild3ComponentTitle(), index);
// packet->setArrayDataByName("build_qty", recipe->GetBuild3ComponentQuantity(), index);
if (item) {
// packet->setArrayDataByName("build_selected_item_qty", min(qty, recipe->GetBuild3ComponentQuantity()), index);
}
}
else {
// packet->setArrayDataByName("build_title", recipe->GetBuild4ComponentTitle(), index);
// packet->setArrayDataByName("build_qty", recipe->GetBuild4ComponentQuantity(), index);
if (item) {
//packet->setArrayDataByName("build_selected_item_qty", min(qty, recipe->GetBuild4ComponentQuantity()), index);
}
}
// Reset the variables we will reuse
i = 0;
firstID = 0;
item = 0;
}
packet->setArrayDataByName("build_comp", comp_title.c_str(), index);
packet->setArrayDataByName("build_comp_qty", comp_qty, index);
packet->setArrayDataByName("build_comp_qty_avail", have_qty, index);
}
}
//packet->setArrayDataByName("build_comp", "build_comp1", 0);
//packet->setArrayDataByName("build_comp_qty", 1, 0);
//packet->setArrayDataByName("build_comp_qty_avail", 24, 0);
//packet->setArrayDataByName("build_comp", "build_comp2", 1);
//packet->setArrayDataByName("build_comp_qty", 1, 1);
//packet->setArrayDataByName("build_comp_qty_avail", 16, 1);
//packet->setArrayDataByName("build_comp", "build_comp3", 2);
//packet->setArrayDataByName("build_comp_qty", 1, 2);
//packet->setArrayDataByName("build_comp_qty_avail", 15, 2);
// Check to see if we have a fuel component (slot = 5)
if (recipe->components.count(5) > 0) {
vector<int32> rc = recipe->components[5];
//packet->setArrayLengthByName("num_fuel_choices", rc.size());
for (itr = rc.begin(); itr != rc.end(); itr++, i++) {
if (firstID == 0)
firstID = *itr;
item = master_item_list.GetItem(*itr);
//packet->setSubstructDataByName("recipe_info", "fuel_comp_qty_avail", item->details.count);
packet->setSubstructDataByName("recipe_info", "fuel_comp", recipe->fuel_comp_title);
packet->setSubstructDataByName("recipe_info", "fuel_comp_qty", recipe->fuel_comp_qty);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID((*itr));
if (item) {
packet->setSubstructDataByName("recipe_info", "fuel_comp_qty_avail", item->details.count);
itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
if (itemss.size() > 0) {
int16 have_qty = 0;
for (int8 i = 0; i < itemss.size(); i++) {
have_qty += itemss[i]->details.count;
}
packet->setSubstructDataByName("recipe_info", "fuel_comp_qty_avail", have_qty);
break;
}
// Set the default item id to the first component id
//packet->setDataByName("fuel_selected_item_id", firstID);
//packet->setDataByName("fuel_item_selected", 1);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID(firstID);
if (item) {
// packet->setDataByName("fuel_selected_item_qty", min(recipe->GetFuelComponentQuantity(), (int8)item->details.count));
}
//packet->setDataByName("fuel_title", recipe->GetFuelComponentTitle());
//packet->setDataByName("fuel_qty", recipe->GetFuelComponentQuantity());
// Reset the variables we will reuse
i = 0;
firstID = 0;
item = 0;
}
else {
LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Recipe has no fuel component");
}
packet->setSubstructDataByName("recipe_info", "fuel_comp", recipe->fuel_comp_title);
packet->setSubstructDataByName("recipe_info", "fuel_comp_qty", recipe->fuel_comp_qty);
//packet->setSubstructDataByName("recipe_info", "fuel_comp_qty_avail", 10);
packet->setSubstructDataByName("recipe_info", "build_comp_qty_avail_flag", 1);
packet->setSubstructDataByName("recipe_info", "unknown6", 4, 0);
packet->setSubstructDataByName("recipe_info", "min_product", 1);
@ -656,7 +541,7 @@ EQ2Packet * Recipe::SerializeRecipe(Client *client, Recipe *recipe, bool display
packet->setSubstructDataByName("recipe_info", "available_flag", 4);
packet->setSubstructDataByName("recipe_info", "not_commissionable", 1);
packet->setSubstructDataByName("recipe_info", "recipe_name", recipe->GetName());
packet->setSubstructDataByName("recipe_info", "recipe_description", "The art of sculpting metal into a candelabra.");
packet->setSubstructDataByName("recipe_info", "recipe_description", recipe->GetDescription());
//packet->PrintPacket();
EQ2Packet* data = packet->serialize();
EQ2Packet* app = new EQ2Packet(OP_ClientCmdMsg, data->pBuffer, data->size);

View file

@ -53,6 +53,7 @@ public:
void SetID(int32 id) {this->id = id;}
void SetBookID(int32 book_id) {this->book_id = book_id;}
void SetName(const char *name) {strncpy(this->name, name, sizeof(this->name));}
void SetDescription(const char* description) { strncpy(this->description, description, sizeof(this->description)); }
void SetBookName(const char *book_name) {strncpy(this->book_name, book_name, sizeof(this->book_name));}
void SetBook(const char *book) {strncpy(this->book, book, sizeof(this->book));}
void SetDevice(const char *device) {strncpy(this->device, device, sizeof(this->device));}
@ -64,27 +65,30 @@ public:
void SetKnowledge(int32 knowledge) {this->knowledge = knowledge;}
void SetClasses(int32 classes) {this->classes = classes;}
void SetDevice_Sub_Type(int8 device_sub_type) {this->device_sub_type = device_sub_type;}
void SetUnknown1(int8 unknown1) {this->unknown1 = unknown1;}
void SetUnknown2(int32 unknown2) {this->unknown2 = unknown2;}
void SetUnknown3(int32 unknown3) {this->unknown3 = unknown3;}
void SetUnknown4(int32 unknown4) {this->unknown4 = unknown4;}
void SetProductID(int32 itemID) { product_item_id = itemID; }
void SetProductQuantity(int8 qty) { product_qty = qty; }
void SetProductName(const char* productName) { strncpy(product_name, productName, sizeof(product_name)); }
void SetBuildComponentTitle(const char* title) { strncpy(build1_comp_title, title, sizeof(build1_comp_title)); }
void SetBuild1ComponentTitle(const char* title) { strncpy(build1_comp_title, title, sizeof(build1_comp_title)); }
void SetBuild2ComponentTitle(const char* title) { strncpy(build2_comp_title, title, sizeof(build2_comp_title)); }
void SetBuild3ComponentTitle(const char* title) { strncpy(build3_comp_title, title, sizeof(build3_comp_title)); }
void SetBuild4ComponentTitle(const char* title) { strncpy(build4_comp_title, title, sizeof(build4_comp_title)); }
void SetFuelComponentTitle(const char* title) { strncpy(fuel_comp_title, title, sizeof(fuel_comp_title)); }
void SetPrimaryComponentTitle(const char* title) { strncpy(primary_build_comp_title, title, sizeof(primary_build_comp_title)); }
void SetBuild1ComponentQuantity(int8 qty) { build_comp_qty = qty; }
void SetBuild1ComponentQuantity(int8 qty) { build1_comp_qty = qty; }
void SetBuild2ComponentQuantity(int8 qty) { build2_comp_qty = qty; }
void SetBuild3ComponentQuantity(int8 qty) { build3_comp_qty = qty; }
void SetBuild4ComponentQuantity(int8 qty) { build4_comp_qty = qty; }
void SetFuelComponentQuantity(int8 qty) { fuel_comp_qty = qty; }
void SetPrimaryComponentQuantity(int8 qty) { primary_comp_qty = qty; }
int32 GetID() {return id;}
int32 GetBookID() {return book_id;}
const char * GetName() {return name;}
const char* GetDescription() { return description; }
const char * GetBookName() {return book_name;}
const char * GetBook() {return book;}
const char * GetDevice() {return device;}
@ -106,6 +110,7 @@ public:
return item->generic_info.tradeskill_classes < 4 || (1 << class_id) & item->generic_info.tradeskill_classes;
}
int8 GetDevice_Sub_Type() {return device_sub_type;}
int8 GetUnknown1() {return unknown1;}
int32 GetUnknown2() {return unknown2;}
int32 GetUnknown3() {return unknown3;}
int32 GetUnknown4() {return unknown4;}
@ -119,17 +124,18 @@ public:
const char* GetBuild3ComponentTitle() { return build3_comp_title; }
const char* GetBuild4ComponentTitle() { return build4_comp_title; }
const char* GetFuelComponentTitle() { return fuel_comp_title; }
int8 GetBuild1ComponentQuantity() { return build_comp_qty; }
int8 GetBuild2ComponentQuantity() { return build2_comp_qty; }
int8 GetBuild3ComponentQuantity() { return build3_comp_qty; }
int8 GetBuild4ComponentQuantity() { return build4_comp_qty; }
int8 GetFuelComponentQuantity() { return fuel_comp_qty; }
int16 GetBuild1ComponentQuantity() { return build1_comp_qty; }
int16 GetBuild2ComponentQuantity() { return build2_comp_qty; }
int16 GetBuild3ComponentQuantity() { return build3_comp_qty; }
int16 GetBuild4ComponentQuantity() { return build4_comp_qty; }
int16 GetFuelComponentQuantity() { return fuel_comp_qty; }
int16 GetPrimaryComponentQuantity() { return primary_comp_qty; }
///<summary>Add a build component to this recipe</summary>
///<param name="itemID">Item id of the component</param>
///<param name="slot">Slot id for this component</param>
void AddBuildComp(int32 itemID, int8 slot, bool preferred = 0);
// int8 = slot, vector = itemid
map<int8, vector<int32> > components;
@ -143,6 +149,7 @@ private:
int32 id;
int32 book_id;
char name[256];
char description[256];
char book_name[256];
char book[256];
char device[30];
@ -154,6 +161,7 @@ private:
int32 knowledge;
int8 device_sub_type;
int32 classes;
int8 unknown1;
int32 unknown2;
int32 unknown3;
int32 unknown4;
@ -167,11 +175,12 @@ private:
char build3_comp_title[256];
char build4_comp_title[256];
char fuel_comp_title[256];
int8 build_comp_qty;
int8 build2_comp_qty;
int8 build3_comp_qty;
int8 build4_comp_qty;
int8 fuel_comp_qty;
int16 build1_comp_qty;
int16 build2_comp_qty;
int16 build3_comp_qty;
int16 build4_comp_qty;
int16 fuel_comp_qty;
int16 primary_comp_qty;
int8 highestStage;
};

View file

@ -29,13 +29,14 @@
extern MasterRecipeList master_recipe_list;
extern MasterRecipeBookList master_recipebook_list;
extern MasterItemList master_item_list;
void WorldDatabase::LoadRecipes() {
DatabaseResult res;
bool status = database_new.Select(&res,
"SELECT r.`id`,r.`level`,r.`icon`,r.`skill_level`,r.`technique`,r.`knowledge`,r.`name`,i.`name` as `book`,r.`bench`,ipc.`adventure_classes`, "
"r.`stage4_id`, r.`name`, r.`stage4_qty`, pcl.`name` as primary_comp_title, fcl.name as `fuel_comp_title`, r.fuel_comp_qty, "
"SELECT r.`id`,r.`level`,r.`icon`,r.`skill_level`,r.`technique`,r.`knowledge`,r.`name`,r.`description`,i.`name` as `book`,r.`bench`,ipc.`adventure_classes`, "
"r.`stage4_id`, r.`name`, r.`stage4_qty`, pcl.`name` as primary_comp_title,r.primary_comp_qty, fcl.name as `fuel_comp_title`, r.fuel_comp_qty, "
"bc.`name` AS build_comp_title, bc.qty AS build_comp_qty, bc2.`name` AS build2_comp_title, bc2.qty AS build2_comp_qty, "
"bc3.`name` AS build3_comp_title, bc3.qty AS build3_comp_qty, bc4.`name` AS build4_comp_title, bc4.qty AS build4_comp_qty,\n"
"r.stage0_id, r.stage1_id, r.stage2_id, r.stage3_id, r.stage4_id, r.stage0_qty, r.stage1_qty, r.stage2_qty, r.stage3_qty, r.stage4_qty,\n"
@ -66,6 +67,7 @@ void WorldDatabase::LoadRecipes() {
recipe->SetTechnique(res.GetInt32(i++));
recipe->SetKnowledge(res.GetInt32(i++));
recipe->SetName(res.GetString(i++));
recipe->SetDescription(res.GetString(i++));
recipe->SetBook(res.GetString(i++));
//Convert the device string
@ -86,17 +88,18 @@ void WorldDatabase::LoadRecipes() {
recipe->SetProductName(res.GetString(i++));
recipe->SetProductQuantity(res.GetInt8(i++));
recipe->SetPrimaryComponentTitle(res.GetString(i++));
recipe->SetPrimaryComponentQuantity(res.GetInt16(i++));
recipe->SetFuelComponentTitle(res.GetString(i++));
recipe->SetFuelComponentQuantity(res.GetInt8(i++));
recipe->SetFuelComponentQuantity(res.GetInt16(i++));
recipe->SetBuildComponentTitle(res.GetString(i++));
recipe->SetBuild1ComponentQuantity(res.GetInt8(i++));
recipe->SetBuild1ComponentTitle(res.GetString(i++));
recipe->SetBuild1ComponentQuantity(res.GetInt16(i++));
recipe->SetBuild2ComponentTitle(res.GetString(i++));
recipe->SetBuild2ComponentQuantity(res.GetInt8(i++));
recipe->SetBuild2ComponentQuantity(res.GetInt16(i++));
recipe->SetBuild3ComponentTitle(res.GetString(i++));
recipe->SetBuild3ComponentQuantity(res.GetInt8(i++));
recipe->SetBuild3ComponentQuantity(res.GetInt16(i++));
recipe->SetBuild4ComponentTitle(res.GetString(i++));
recipe->SetBuild4ComponentQuantity(res.GetInt8(i++));
recipe->SetBuild4ComponentQuantity(res.GetInt16(i++));
LogWrite(TRADESKILL__DEBUG, 7, "Recipes", "Loading recipe: %s (%u)", recipe->GetName(), recipe->GetID());

View file

@ -233,7 +233,7 @@ void TradeskillMgr::Process() {
m_tradeskills.releasewritelock(__FUNCTION__, __LINE__);
}
void TradeskillMgr::BeginCrafting(Client* client, vector<int32> components) {
void TradeskillMgr::BeginCrafting(Client* client, vector<pair<int32,int8>> components) {
Recipe* recipe = master_recipe_list.GetRecipe(client->GetPlayer()->GetCurrentRecipe());
if (!recipe) {
@ -243,13 +243,13 @@ void TradeskillMgr::BeginCrafting(Client* client, vector<int32> components) {
}
// TODO: use the vecotr to lock inventory slots
vector<int32>::iterator itr;
vector<pair<int32, int8>>::iterator itr;
bool missingItem = false;
int32 itemid = 0;
vector<Item*> tmpItems;
for (itr = components.begin(); itr != components.end(); itr++) {
itemid = *itr;
Item* item = client->GetPlayer()->item_list.GetItemFromID(itemid);
itemid = itr->first;
Item* item = client->GetPlayer()->item_list.GetItemFromUniqueID(itemid);
if(!item)
{
@ -317,7 +317,7 @@ void TradeskillMgr::StopCrafting(Client* client, bool lock) {
int32 dur = tradeskill->currentDurability;
int32 progress = tradeskill->currentProgress;
Recipe* recipe = tradeskill->recipe;
vector<int32>::iterator itr;
vector<pair<int32, int8>>::iterator itr;
Item* item = 0;
int32 item_id = 0;
int8 i = 0;
@ -336,23 +336,12 @@ void TradeskillMgr::StopCrafting(Client* client, bool lock) {
bool updateInvReq = false;
// cycle through the list of used items and remove them
for (itr = tradeskill->usedComponents.begin(); itr != tradeskill->usedComponents.end(); itr++, i++) {
// get the quantity to remove, first item in the vectore is always the primary, last is always the fuel
if (i == 0)
qty = 1;
else if (i == 1 && i != tradeskill->usedComponents.size() - 1)
qty = recipe->GetBuild1ComponentQuantity();
else if (i == 2 && i != tradeskill->usedComponents.size() - 1)
qty = recipe->GetBuild2ComponentQuantity();
else if (i == 3 && i != tradeskill->usedComponents.size() - 1)
qty = recipe->GetBuild3ComponentQuantity();
else if (i == 4 && i != tradeskill->usedComponents.size() - 1)
qty = recipe->GetBuild4ComponentQuantity();
else if (i == 5 || i == tradeskill->usedComponents.size() - 1)
qty = recipe->GetFuelComponentQuantity();
// Get the item in the players inventory and remove or reduce the quantity
int32 itmid = *itr;
item = client->GetPlayer()->item_list.GetItemFromID(itmid);
int32 itmid = itr->first;
qty = itr->second;
item = client->GetPlayer()->item_list.GetItemFromUniqueID(itmid);
if (item && item->details.count <= qty)
{
item->details.item_locked = false;
@ -381,10 +370,13 @@ void TradeskillMgr::StopCrafting(Client* client, bool lock) {
item = 0;
qty = recipe->GetFuelComponentQuantity();
item_id = recipe->components[5][0];
int8 HS = playerRecipe->GetHighestStage();
if (progress >= 400 && progress < 600) {
if (playerRecipe->GetHighestStage() < 1) {
playerRecipe->SetHighestStage(1);
database.UpdatePlayerRecipe(client->GetPlayer(), recipe->GetID(), 1);
if (HS & (1 << (1 - 1))) {
}
else {
playerRecipe->SetHighestStage(HS + 1 );
database.UpdatePlayerRecipe(client->GetPlayer(), recipe->GetID(), playerRecipe->GetHighestStage());
}
if (recipe->products.count(1) > 0) {
item_id = recipe->products[1]->product_id;
@ -392,9 +384,11 @@ void TradeskillMgr::StopCrafting(Client* client, bool lock) {
}
}
else if ((dur < 200 && progress >= 600) || (dur >= 200 && progress >= 600 && progress < 800)) {
if (playerRecipe->GetHighestStage() < 2) {
playerRecipe->SetHighestStage(2);
database.UpdatePlayerRecipe(client->GetPlayer(), recipe->GetID(), 2);
if (HS & (1 << (2 - 1))) {
}
else {
playerRecipe->SetHighestStage(HS + 2);
database.UpdatePlayerRecipe(client->GetPlayer(), recipe->GetID(), playerRecipe->GetHighestStage());
}
if (recipe->products.count(2) > 0) {
item_id = recipe->products[2]->product_id;
@ -402,9 +396,11 @@ void TradeskillMgr::StopCrafting(Client* client, bool lock) {
}
}
else if ((dur >= 200 && dur < 800 && progress >= 800) || (dur >= 800 && progress >= 800 && progress < 1000)) {
if (playerRecipe->GetHighestStage() < 3) {
playerRecipe->SetHighestStage(3);
database.UpdatePlayerRecipe(client->GetPlayer(), recipe->GetID(), 3);
if (HS & (1 << (3 - 1))) {
}
else {
playerRecipe->SetHighestStage(HS + 4);
database.UpdatePlayerRecipe(client->GetPlayer(), recipe->GetID(), playerRecipe->GetHighestStage());
}
if (recipe->products.count(3) > 0) {
item_id = recipe->products[3]->product_id;
@ -412,9 +408,11 @@ void TradeskillMgr::StopCrafting(Client* client, bool lock) {
}
}
else if (dur >= 800 && progress >= 1000) {
if (playerRecipe->GetHighestStage() < 4) {
playerRecipe->SetHighestStage(4);
database.UpdatePlayerRecipe(client->GetPlayer(), recipe->GetID(), 4);
if (HS & (1 << (4 - 1))) {
}
else {
playerRecipe->SetHighestStage(HS + 8);
database.UpdatePlayerRecipe(client->GetPlayer(), recipe->GetID(), playerRecipe->GetHighestStage());
}
if (recipe->products.count(4) > 0) {
item_id = recipe->products[4]->product_id;

View file

@ -54,7 +54,7 @@ struct Tradeskill
int32 currentProgress;
int32 currentDurability;
int32 nextUpdateTime;
vector<int32> usedComponents;
vector<pair<int32, int8>> usedComponents;
TradeskillEvent* CurrentEvent;
bool eventChecked;
bool eventCountered;
@ -72,7 +72,7 @@ public:
/// <summary>Starts the actual crafting process</summary>
/// <param name='client'>Client that is crafting</param>
/// <param name='components'>List of items the player is using to craft</param>
void BeginCrafting(Client* client, vector<int32> components);
void BeginCrafting(Client* client, vector<pair<int32, int8>> components);
/// <summary>Stops the crafting process</summary>
/// <param name='client'>Client that stopped crafting</param>

View file

@ -64,61 +64,123 @@ void ClientPacketFunctions::SendCreateFromRecipe(Client* client, int32 recipeID)
return;
}
vector<int32>::iterator itr;
vector<Item*> itemss;
int8 i = 0;
int8 k = 0;
int32 firstID = 0;
int32 IDcount = 0;
int32 primary_comp_id = 0;
Item* first_item = 0;
Item* item = 0;
Item* item_player = 0;
Spawn* target = 0;
if (!(target = client->GetPlayer()->GetTarget())) {
client->Message(CHANNEL_COLOR_YELLOW, "You must be at a %s in order to crafte this recipe", recipe->GetDevice());
return;
}
// Recipe and crafting table info
packet->setDataByName("crafting_station", recipe->GetDevice());
packet->setDataByName("recipe_name", recipe->GetName());
packet->setDataByName("tier", recipe->GetTier());
// Mass Production
int32 mpq = 1;
int32 mp = 5;
vector<int> v{ 1,2,4,6,11,21 };
// mpq will eventually be retrieved from achievement for mass production
mpq = v[mp];
packet->setArrayLengthByName("num_mass_production_choices",mpq);
packet->setArrayDataByName("mass_qty", 1, 0);
for (int x = 1; x < mpq; x++) {
packet->setArrayDataByName("mass_qty", x * 5, x);
}
// Product info
item = master_item_list.GetItem(recipe->GetProductID());
packet->setDataByName("product_name", item->name.c_str());
packet->setDataByName("icon", item->details.icon);
packet->setDataByName("product_qty", recipe->GetProductQuantity());
packet->setDataByName("primary_title", recipe->GetPrimaryBuildComponentTitle());
packet->setDataByName("primary_qty", 1);
packet->setDataByName("primary_qty_needed", recipe->GetPrimaryComponentQuantity());
packet->setDataByName("unknown6", 11);
packet->setDataByName("unknown3", 18);
// Reset item to 0
item = 0;
item, item_player = 0;
// Check to see if we have a primary component (slot = 0)
if (recipe->components.count(0) > 0) {
vector<int32> rc = recipe->components[0];
packet->setArrayLengthByName("num_primary_choices", rc.size());
vector <pair<int32, int16>> selected_items;
for (itr = rc.begin(); itr != rc.end(); itr++, i++) {
if (firstID == 0)
firstID = *itr;
item = master_item_list.GetItem(*itr);
if(!item)
if (!item)
{
LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Error creating packet to client missing item %u", *itr);
client->Message(CHANNEL_COLOR_RED, "Error producing create recipe packet! Recipe is trying to find item %u, but it is missing!", *itr);
safe_delete(packet);
return;
}
packet->setArrayDataByName("primary_component", item->name.c_str(), i);
packet->setArrayDataByName("primary_item_id", (*itr), i);
packet->setArrayDataByName("primary_icon", item->details.icon, i);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID((*itr));
if (item)
packet->setArrayDataByName("primary_total_quantity", item->details.count, i);
item_player = 0;
item_player = client->GetPlayer()->item_list.GetItemFromID((*itr));
itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
packet->setArrayLengthByName("num_primary_choices", itemss.size());
if (itemss.size() > 0) {
int16 needed_qty = recipe->GetPrimaryComponentQuantity();
int16 have_qty = 0;
if (firstID == 0)
firstID = *itr;
for (int8 i = 0; i < itemss.size(); i++) {
IDcount++;
if (have_qty < needed_qty) {
int16 stack_count = itemss[i]->details.count;
int16 min_qty = min(stack_count, int16(needed_qty - have_qty));
selected_items.push_back(make_pair(int32(itemss[i]->details.unique_id), min_qty));
have_qty += min_qty;
}
packet->setArrayDataByName("primary_component", itemss[i]->name.c_str(), i);
packet->setArrayDataByName("primary_item_id", itemss[i]->details.unique_id, i);
packet->setArrayDataByName("primary_icon", itemss[i]->details.icon, i);
packet->setArrayDataByName("primary_total_quantity", itemss[i]->details.count, i);
//packet->setArrayDataByName("primary_supply_depot", itemss[i]->details.count, i); // future need
//packet->setArrayDataByName("primary_unknown3a",); // future need
}
packet->setDataByName("primary_id", itemss[0]->details.unique_id);
packet->setDataByName("primary_default_selected_id", itemss[0]->details.unique_id);
for (int8 i = 0; i < selected_items.size(); i++) {
}
int16 qty = 0;
if (item) {
qty = (int8)item->details.count;
if (qty > 0 && firstID == primary_comp_id)
qty -= 1;
}
}
else
packet->setDataByName("primary_id",*itr);
}
// store the id of the primary comp
primary_comp_id = firstID;
// Set the default item id to the first component id
packet->setDataByName("primary_item_selected", 1);
packet->setDataByName("primary_default_selected_id", firstID);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID(firstID);
if (item)
packet->setDataByName("primary_selected_item_qty", min((int8)1, (int8)item->details.count));
packet->setArrayLengthByName("num_primary_items_selected", selected_items.size());
for (int8 i = 0; i < selected_items.size(); i++) {
packet->setArrayDataByName("primary_selected_item_qty", selected_items[i].second,i );
packet->setArrayDataByName("primary_selected_item_id", selected_items[i].first,i);
}
// Reset the variables we will reuse
i = 0;
firstID = 0;
@ -131,7 +193,7 @@ void ClientPacketFunctions::SendCreateFromRecipe(Client* client, int32 recipeID)
// Check to see if we have build components (slot = 1 - 4)
int8 total_build_components = 0;
if (recipe->components.count(1) > 0)
if (recipe->components.count(1) > 0)
total_build_components++;
if (recipe->components.count(2))
total_build_components++;
@ -139,107 +201,187 @@ void ClientPacketFunctions::SendCreateFromRecipe(Client* client, int32 recipeID)
total_build_components++;
if (recipe->components.count(4))
total_build_components++;
//--------------------------------------------------------------Start Build Components-------------------------------------------------------------
if (total_build_components > 0) {
packet->setArrayLengthByName("num_build_components", total_build_components);
LogWrite(TRADESKILL__ERROR, 0, "Recipes", "num_build_components ", total_build_components);
for (int8 index = 0; index < 4; index++) {
if (recipe->components.count(index + 1) == 0)
continue;
packet->setArrayDataByName("build_slot", index, index);
vector<int32> rc = recipe->components[index + 1];
packet->setSubArrayLengthByName("num_build_choices", rc.size(), index);
for (itr = rc.begin(); itr != rc.end(); itr++, i++) {
if (firstID == 0)
firstID = *itr;
item = master_item_list.GetItem(*itr);
packet->setSubArrayDataByName("build_component", item->name.c_str(), index, i);
packet->setSubArrayDataByName("build_item_id", (*itr), index, i);
packet->setSubArrayDataByName("build_icon", item->details.icon, index, i);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID((*itr));
if (item)
packet->setSubArrayDataByName("build_total_quantity", item->details.count, index, i);
int32 total_component_items = 0;
int8 hasComp = 0;
vector <pair<int32, int16>> selected_items;
for (itr = rc.begin(); itr != rc.end(); itr++) {
itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
if (itemss.size() > 0)
total_component_items += itemss.size();
}
packet->setSubArrayLengthByName("num_build_choices", total_component_items, index);// get # build choces first
hasComp = 0;
char msgbuf[200] = "";
for (itr = rc.begin(); itr != rc.end(); itr++) {// iterates through each recipe component to find the stacks in inventory
item = master_item_list.GetItem(*itr);
itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
sprintf(msgbuf, "k=%d hascomp=%d \n", k, hasComp);
OutputDebugString(msgbuf);
if (itemss.size() > 0) {
int16 needed_qty = 0;
int16 have_qty = 0;
if (index == 0) {
needed_qty = recipe->GetBuild1ComponentQuantity();
have_qty = 0;
}
else if (index == 1) {
needed_qty = recipe->GetBuild2ComponentQuantity();
have_qty = 0;
}
else if (index == 2) {
needed_qty = recipe->GetBuild3ComponentQuantity();
have_qty = 0;
}
else if (index == 3) {
needed_qty = recipe->GetBuild4ComponentQuantity();
have_qty = 0;
}
if (firstID == 0)
firstID = *itr;
if (hasComp == 0) {
hasComp = 100 + k;
}
for (int8 j = 0; j < itemss.size(); j++, k++) { // go through each stack of a compnent
if (have_qty < needed_qty) {
// Set the default item id to the first component id
packet->setArrayDataByName("build_item_selected", 1, index);
packet->setArrayDataByName("build_selected_item_id", firstID, index);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID(firstID);
int8 qty = 0;
int16 stack_count = itemss[j]->details.count;
int16 min_qty = min(stack_count, int16(needed_qty - have_qty));
selected_items.push_back(make_pair(int32(itemss[j]->details.unique_id), min_qty));
have_qty += min_qty;
}
item = master_item_list.GetItem(itemss[j]->details.item_id);
packet->setSubArrayDataByName("build_component", itemss[j]->name.c_str(), index, k);
packet->setSubArrayDataByName("build_item_id", itemss[j]->details.unique_id, index, k);
packet->setSubArrayDataByName("build_icon", itemss[j]->details.icon, index, k);
packet->setSubArrayDataByName("build_total_quantity", itemss[j]->details.count, index, k);
//packet->setSubArrayDataByName("build_supply_depot",); // future need
//packet->setSubArrayDataByName("build_unknown3",); // future need
}
}
}
packet->setArrayLengthByName("num_build_items_selected", selected_items.size());
for (int8 i = 0; i < selected_items.size(); i++) {
packet->setArrayDataByName("build_selected_item_qty", selected_items[i].second, i);
packet->setArrayDataByName("build_selected_id", selected_items[i].first, i);
}
int16 qty = 0;
if (item) {
qty = (int8)item->details.count;
qty = (int16)item->details.count;
if (qty > 0 && firstID == primary_comp_id)
qty -= 1;
}
if (index == 0) {
packet->setArrayDataByName("build_title", recipe->GetBuild1ComponentTitle(), index);
packet->setArrayDataByName("build_qty", recipe->GetBuild1ComponentQuantity(), index);
packet->setArrayDataByName("build_qty_needed", recipe->GetBuild1ComponentQuantity(), index);
if (item)
packet->setArrayDataByName("build_selected_item_qty", min(qty, recipe->GetBuild1ComponentQuantity()), index);
packet->setArrayDataByName("build_selected_item_qty_have", min(qty, recipe->GetBuild1ComponentQuantity()), index);
}
else if (index == 1) {
packet->setArrayDataByName("build_title", recipe->GetBuild2ComponentTitle(), index);
packet->setArrayDataByName("build_qty", recipe->GetBuild2ComponentQuantity(), index);
packet->setArrayDataByName("build_qty_needed", recipe->GetBuild2ComponentQuantity(), index);
if (item)
packet->setArrayDataByName("build_selected_item_qty", min(qty, recipe->GetBuild2ComponentQuantity()), index);
packet->setArrayDataByName("build_selected_item_qty_have", min(qty, recipe->GetBuild2ComponentQuantity()), index);
}
else if (index == 2) {
packet->setArrayDataByName("build_title", recipe->GetBuild3ComponentTitle(), index);
packet->setArrayDataByName("build_qty", recipe->GetBuild3ComponentQuantity(), index);
packet->setArrayDataByName("build_qty_needed", recipe->GetBuild3ComponentQuantity(), index);
if (item)
packet->setArrayDataByName("build_selected_item_qty", min(qty, recipe->GetBuild3ComponentQuantity()), index);
packet->setArrayDataByName("build_selected_item_qty_have", min(qty, recipe->GetBuild3ComponentQuantity()), index);
}
else {
packet->setArrayDataByName("build_title", recipe->GetBuild4ComponentTitle(), index);
packet->setArrayDataByName("build_qty", recipe->GetBuild4ComponentQuantity(), index);
packet->setArrayDataByName("build_qty_needed", recipe->GetBuild4ComponentQuantity(), index);
if (item)
packet->setArrayDataByName("build_selected_item_qty", min(qty, recipe->GetBuild4ComponentQuantity()), index);
packet->setArrayDataByName("build_selected_item_qty_have", min(qty, recipe->GetBuild4ComponentQuantity()), index);
}
// Reset the variables we will reuse
i = 0;
firstID = 0;
item = 0;
}
k = 0;
}
int32 xxx = 0;
}
// Check to see if we have a fuel component (slot = 5)
if (recipe->components.count(5) > 0) {
vector<int32> rc = recipe->components[5];
packet->setArrayLengthByName("num_fuel_choices", rc.size());
vector <pair<int32, int16>> selected_items;
for (itr = rc.begin(); itr != rc.end(); itr++, i++) {
if (firstID == 0)
firstID = *itr;
item = master_item_list.GetItem(*itr);
if (!item)
{
LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Error creating packet to client missing item %u", *itr);
client->Message(CHANNEL_COLOR_RED, "Error producing create recipe packet! Recipe is trying to find item %u, but it is missing!", *itr);
safe_delete(packet);
return;
}
item_player = 0;
item_player = client->GetPlayer()->item_list.GetItemFromID((*itr));
packet->setArrayDataByName("fuel_component", item->name.c_str(), i);
packet->setArrayDataByName("fuel_item_id", (*itr), i);
packet->setArrayDataByName("fuel_icon", item->details.icon, i);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID((*itr));
if (item)
packet->setArrayDataByName("fuel_total_quantity", item->details.count, i);
itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
packet->setArrayLengthByName("num_fuel_choices", itemss.size());
if (itemss.size() > 0) {
int16 needed_qty = recipe->GetFuelComponentQuantity();
int16 have_qty = 0;
if (firstID == 0)
firstID = *itr;
for (int8 i = 0; i < itemss.size(); i++) {
IDcount++;
if (have_qty < needed_qty) {
int16 stack_count = itemss[i]->details.count;
int16 min_qty = min(stack_count, int16(needed_qty - have_qty));
selected_items.push_back(make_pair(int32(itemss[i]->details.unique_id), min_qty));
have_qty += min_qty;
}
packet->setArrayDataByName("fuel_component", itemss[i]->name.c_str(), i);
packet->setArrayDataByName("fuel_item_id", itemss[i]->details.unique_id, i);
packet->setArrayDataByName("fuel_icon", itemss[i]->details.icon, i);
packet->setArrayDataByName("fuel_total_quantity", itemss[i]->details.count, i);
//packet->setArrayDataByName("fuel_supply_depot", itemss[i]->details.count, i); // future need
//packet->setArrayDataByName("primary_unknown3a",); // future need
}
packet->setDataByName("fuel_selected_item_id", itemss[0]->details.unique_id);
int16 qty = 0;
if (item) {
qty = (int8)item->details.count;
if (qty > 0 && firstID == primary_comp_id)
qty -= 1;
}
}
else
packet->setDataByName("primary_vvv", *itr);
}
// store the id of the primary comp
primary_comp_id = firstID;
// Set the default item id to the first component id
packet->setDataByName("fuel_selected_item_id", firstID);
packet->setDataByName("fuel_item_selected", 1);
item = 0;
item = client->GetPlayer()->item_list.GetItemFromID(firstID);
if (item)
packet->setDataByName("fuel_selected_item_qty", min(recipe->GetFuelComponentQuantity(), (int8)item->details.count));
packet->setDataByName("fuel_title",recipe->GetFuelComponentTitle());
packet->setDataByName("fuel_qty",recipe->GetFuelComponentQuantity());
packet->setArrayLengthByName("num_fuel_items_selected", selected_items.size());
for (int8 i = 0; i < selected_items.size(); i++) {
packet->setArrayDataByName("fuel_selected_item_qty", selected_items[i].second, i);
packet->setArrayDataByName("fuel_selected_item_id", selected_items[i].first, i);
}
packet->setDataByName("fuel_title", recipe->GetFuelComponentTitle());
packet->setDataByName("fuel_qty_needed", recipe->GetFuelComponentQuantity());
// Reset the variables we will reuse
i = 0;
@ -251,10 +393,9 @@ void ClientPacketFunctions::SendCreateFromRecipe(Client* client, int32 recipeID)
return;
}
packet->setDataByName("unknown1", recipeID);
packet->setDataByName("unknown8", 1); // Possible array for amount you can craft
packet->setDataByName("unknown8", 1, 1); // amounts you can craft
//packet->PrintPacket();
packet->setDataByName("recipe_id", recipeID);
packet->PrintPacket();
// Send the packet
client->QueuePacket(packet->serialize());
safe_delete(packet);

View file

@ -1682,27 +1682,49 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
if (packet) {
packet->LoadPacketData(app->pBuffer, app->size);
int32 item = 0;
vector<int32> items;
char tmp_item_id[20];
item = packet->getType_int32_ByName("primary_component_id");
if (item > 0)
items.push_back(item);
item = 0;
int8 build_components = packet->getType_int8_ByName("num_build_components");
for (int8 i = 0; i < build_components; i++) {
memset(tmp_item_id, 0, 20);
sprintf(tmp_item_id, "component_id_%i", i);
int8 qty = 0;
vector<pair<int32, int8>> items;
char tmp_item_id[30];
int8 num_primary_selected_items = packet->getType_int8_ByName("num_primary_selected_items");
for (int8 i = 0; i < num_primary_selected_items; i++) {
memset(tmp_item_id, 0, 30);
sprintf(tmp_item_id, "primary_selected_item_id_%i", i);
item = packet->getType_int32_ByName(tmp_item_id);
sprintf(tmp_item_id, "primary_selected_item_qty_%i", i);
qty = packet->getType_int8_ByName(tmp_item_id);
if (item > 0)
items.push_back(item);
items.push_back(make_pair(item,qty));
item = 0;
}
int8 build_components = packet->getType_int8_ByName("num_build_components");
for (int8 i = 0; i < build_components; i++) {
memset(tmp_item_id, 0, 30);
sprintf(tmp_item_id, "num_selected_items_%i", i);
int8 num_selected_items = packet->getType_int8_ByName(tmp_item_id);
for (int8 j = 0; j < num_selected_items; j++) {
memset(tmp_item_id, 0, 30);
sprintf(tmp_item_id, "selected_id%i_%i", i,j);
item = packet->getType_int32_ByName(tmp_item_id);
sprintf(tmp_item_id, "selected_qty%i_%i", i, j);
qty = packet->getType_int8_ByName(tmp_item_id);
if (item > 0)
items.push_back(make_pair(item, qty));
item = packet->getType_int32_ByName("fuel_id");
if (item > 0)
items.push_back(item);
item = 0;
}
}
int8 num_fuel_items = packet->getType_int8_ByName("num_fuel_items");
for (int8 i = 0; i < num_fuel_items; i++) {
memset(tmp_item_id, 0, 30);
sprintf(tmp_item_id, "selected_id_%i", i);
item = packet->getType_int32_ByName(tmp_item_id);
sprintf(tmp_item_id, "selected_qty_%i", i);
qty = packet->getType_int8_ByName(tmp_item_id);
if (item > 0)
items.push_back(make_pair(item, qty));
item = 0;
}
GetCurrentZone()->GetTradeskillMgr()->BeginCrafting(this, items);
safe_delete(packet);
@ -2848,7 +2870,8 @@ void Client::HandleExamineInfoRequest(EQApplicationPacket* app) {
if (type == 3) {
Spell* spell = 0;
bool trait_display;
request = configReader.getStruct("WS_ExamineInfoRequest", GetVersion());
request = configReader.getStruct("WS_ExamineInfoRequestMsg", GetVersion());
if (!request) {
return;
}
@ -3039,7 +3062,7 @@ void Client::HandleExamineInfoRequest(EQApplicationPacket* app) {
}
}
else if (type == 5) { // recipe info
request = configReader.getStruct("WS_ExamineInfoRequest", GetVersion());
request = configReader.getStruct("WS_ExamineInfoRequestMsg", GetVersion());
if (!request)
return;
request->LoadPacketData(app->pBuffer, app->size);
@ -3056,7 +3079,7 @@ void Client::HandleExamineInfoRequest(EQApplicationPacket* app) {
Spell* spell = 0;
//Spell* spell2 = 0;
//AltAdvanceData* data = 0;
request = configReader.getStruct("WS_ExamineInfoRequest", GetVersion());
request = configReader.getStruct("WS_ExamineInfoRequestMsg", GetVersion());
if (!request)
return;
request->LoadPacketData(app->pBuffer, app->size);

View file

@ -6405,19 +6405,19 @@ to zero and treated like placeholders." />
<Data ElementName="unique_id" Type="int32" />
<Data ElementName="unknown5" Type="int16" />
</Struct>
<Struct Name="WS_ExamineInfoRequest" ClientVersion="1" >
<Struct Name="WS_ExamineInfoRequestMsg" ClientVersion="1" OpcodeName="OP_ExamineInfoRequestMsg">
<Data ElementName="type" Type="int8" Size="1" />
<Data ElementName="id" Type="int32" />
<Data ElementName="display" Type="int8" />
</Struct>
<Struct Name="WS_ExamineInfoRequest" ClientVersion="546" >
<Struct Name="WS_ExamineInfoRequestMsg" ClientVersion="546" OpcodeName="OP_ExamineInfoRequestMsg">
<Data ElementName="type" Type="int8" Size="1" />
<Data ElementName="unique_id" Type="int32" />
<Data ElementName="id" Type="int32" />
<Data ElementName="unknown5" Type="int8" />
<Data ElementName="display" Type="int8" />
</Struct>
<Struct Name="WS_ExamineInfoRequest" ClientVersion="860" >
<Struct Name="WS_ExamineInfoRequestMsg" ClientVersion="860" OpcodeName="OP_ExamineInfoRequestMsg">
<Data ElementName="type" Type="int8" Size="1" />
<Data ElementName="unknown_id" Type="int32" />
<Data ElementName="unknown" Type="int32" />
@ -6425,7 +6425,7 @@ to zero and treated like placeholders." />
<Data ElementName="id" Type="int32" />
<Data ElementName="unknown5" Type="int16" />
</Struct>
<Struct Name="WS_ExamineInfoRequest" ClientVersion="1188" >
<Struct Name="WS_ExamineInfoRequestMsg" ClientVersion="1188" OpcodeName="OP_ExamineInfoRequestMsg">
<Data ElementName="type" Type="int8" Size="1" />
<Data ElementName="unknown_id" Type="int32" />
<Data ElementName="unknown2" Type="int32" />
@ -6434,7 +6434,7 @@ to zero and treated like placeholders." />
<Data ElementName="id" Type="int32" />
<Data ElementName="unknown6" Type="int16" />
</Struct>
<Struct Name="WS_ExamineInfoRequest" ClientVersion="60114" >
<Struct Name="WS_ExamineInfoRequestMsg" ClientVersion="60114" OpcodeName="OP_ExamineInfoRequestMsg">
<Data ElementName="type" Type="int8" Size="1" />
<Data ElementName="unknown_id" Type="int32" />
<Data ElementName="unknown2" Type="int32" />
@ -6443,7 +6443,7 @@ to zero and treated like placeholders." />
<Data ElementName="id" Type="int32" />
<Data ElementName="unknown6" Type="int16" />
</Struct>
<Struct Name="WS_ExamineInfoRequest" ClientVersion="63119" >
<Struct Name="WS_ExamineInfoRequestMsg" ClientVersion="63119" OpcodeName="OP_ExamineInfoRequestMsg">
<Data ElementName="type" Type="int8" Size="1" />
<Data ElementName="id" Type="int32" />
<Data ElementName="unique_id" Type="int32" />
@ -16026,7 +16026,7 @@ to zero and treated like placeholders." />
</Struct>
<Struct Name="WS_CreateFromRecipe" ClientVersion="57048" OpcodeName="OP_ShowCreateFromRecipeUIMsg">
<Data ElementName="crafting_station" Type="EQ2_16Bit_String" />
<Data ElementName="unknown1" Type="int32" Size="1" />
<Data ElementName="recipe_id" Type="int32" Size="1" />
<Data ElementName="recipe_name" Type="EQ2_16Bit_String" />
<Data ElementName="tier" Type="int8" Size="1" />
<Data ElementName="unknown3" Type="int32" Size="1" />
@ -16036,29 +16036,35 @@ to zero and treated like placeholders." />
<Data ElementName="unknown5" Type="int16" Size="1" />
<Data ElementName="unknown6" Type="int8" Size="1" />
<Data ElementName="unknown7" Type="int16" Size="1" />
<Data ElementName="unknown8" Type="int8" Size="3" />
<Data ElementName="num_mass_production_choices" Type="int8" Size="1" />
<Data ElementName="mass_array" Type="Array" ArraySizeVariable="num_mass_production_choices">
<Data ElementName="mass_qty" Type="int16" Size="1" />
</Data>
<Data ElementName="primary_title" Type="EQ2_16Bit_String" />
<Data ElementName="unknown9" Type="int8" Size="1" />
<Data ElementName="primary_id" Type="int32" Size="1" />
<Data ElementName="unknown10" Type="int8" Size="6" />
<Data ElementName="primary_qty" Type="int16" Size="1" />
<Data ElementName="primary_qty_needed" Type="int16" Size="1" />
<Data ElementName="num_primary_choices" Type="int8" />
<Data ElementName="primary_array" Type="Array" ArraySizeVariable="num_primary_choices">
<Data ElementName="primary_component" Type="EQ2_16Bit_String" />
<Data ElementName="primary_item_id" Type="int32" Size="1" />
<Data ElementName="primary_icon" Type="int16" Size="1" />
<Data ElementName="primary_total_quantity" Type="int16" Size="1" />
<Data ElementName="primary_supply_depot" Type="int8" Size="1" />
<Data ElementName="primary_unknown3" Type="int8" Size="4" />
<Data ElementName="primary_unknown3" Type="int8" Size="2" />
<Data ElementName="primary_supply_depot" Type="int8" Size="1" />
<Data ElementName="primary_unknown3a" Type="int8" Size="2" />
</Data>
<Data ElementName="primary_item_selected" Type="int8" />
<Data ElementName="primary_default_selected_id" Type="int32" Size="1" />
<Data ElementName="primary_selected_item_qty" Type="int16" Size="1" />
<Data ElementName="num_primary_items_selected" Type="int8" />
<Data ElementName="primary_items_selected_array" Type="Array" ArraySizeVariable="num_primary_items_selected">
<Data ElementName="primary_selected_item_id" Type="int32" Size="1" />
<Data ElementName="primary_selected_item_qty" Type="int16" Size="1" />
</Data>
<Data ElementName="num_build_components" Type="int8" />
<Data ElementName="build_array" Type="Array" ArraySizeVariable="num_build_components">
<Data ElementName="build_slot" Type="int32" />
<Data ElementName="build_title" Type="EQ2_16Bit_String" />
<Data ElementName="build_qty" Type="int16" />
<Data ElementName="build_qty_needed" Type="int16" />
<Data ElementName="build_unknown1" Type="int32" Size="1" />
<Data ElementName="num_build_choices" Type="int8" Size="1" />
<Data ElementName="build_components_array" Type="Array" ArraySizeVariable="num_build_choices">
@ -16066,29 +16072,35 @@ to zero and treated like placeholders." />
<Data ElementName="build_item_id" Type="int32" Size="1" />
<Data ElementName="build_icon" Type="int16" Size="1" />
<Data ElementName="build_total_quantity" Type="int16" Size="1" />
<Data ElementName="build_supply_depot" Type="int8" Size="1" />
<Data ElementName="build_unknown6" Type="int8" Size="3" />
<Data ElementName="build_unknown6" Type="int8" Size="2" />
<Data ElementName="build_supply_depot" Type="int8" Size="1" />
<Data ElementName="build_unknown6a" Type="int8" Size="1" />
</Data>
<Data ElementName="build_item_selected" Type="int8" Size="1" />
<Data ElementName="build_selected_item_id" Type="int32" Size="1" />
<Data ElementName="build_selected_item_qty" Type="int8" Size="1" />
<Data ElementName="unknown" Type="int8" Size="1" />
<Data ElementName="num_build_items_selected" Type="int8" />
<Data ElementName="build_items_selected_array" Type="Array" ArraySizeVariable="num_build_items_selected">
<Data ElementName="build_selected_item_id" Type="int32" Size="1" />
<Data ElementName="build_selected_item_qty" Type="int8" Size="1" />
<Data ElementName="unknown" Type="int8" Size="1" />
</Data>
</Data>
<Data ElementName="fuel_title" Type="EQ2_16Bit_String" />
<Data ElementName="fuel_qty" Type="int16" />
<Data ElementName="fuel_qty_needed" Type="int16" />
<Data ElementName="num_fuel_choices" Type="int8" Size="1" />
<Data ElementName="fuel_component_array" Type="Array" ArraySizeVariable="num_fuel_choices">
<Data ElementName="fuel_component" Type="EQ2_16Bit_String" />
<Data ElementName="fuel_item_id" Type="int32" Size="1" />
<Data ElementName="fuel_icon" Type="int16" />
<Data ElementName="fuel_total_quantity" Type="int16" Size="1" />
<Data ElementName="fuel_unknown4" Type="int8" Size="2" />
<Data ElementName="fuel_supply_depot" Type="int8" Size="1" />
<Data ElementName="fuel_unknown4" Type="int8" Size="3" />
<Data ElementName="fuel_unknown4a" Type="int8" Size="1" />
</Data>
<Data ElementName="num_fuel_items_selected" Type="int8" />
<Data ElementName="fuel_items_selected_array" Type="Array" ArraySizeVariable="num_fuel_items_selected">
<Data ElementName="fuel_selected_item_id" Type="int32" Size="1" />
<Data ElementName="fuel_selected_item_qty" Type="int16" Size="1" />
</Data>
<Data ElementName="fuel_item_selected" Type="int8" Size="1" />
<Data ElementName="fuel_selected_item_id" Type="int32" Size="1" />
<Data ElementName="fuel_selected_item_qty" Type="int16" Size="1" />
</Struct>
<Struct Name="WS_CreateFromRecipe" ClientVersion="63119" OpcodeName="OP_ShowCreateFromRecipeUIMsg">
<Data ElementName="crafting_station" Type="EQ2_16Bit_String" />
@ -16202,19 +16214,26 @@ to zero and treated like placeholders." />
<Data ElementName="fuel_qty" Type="int16" Size="1" />
</Struct>
<Struct Name="WS_BeginItemCreation" ClientVersion="1199" OpcodeName="OP_BeginItemCreationMsg">
<Data ElementName="unknown1" Type="int8" Size="11" />
<Data ElementName="primary_component_id" Type="int32" Size="1" />
<Data ElementName="primary_component_qty" Type="int16" Size="1" />
<Data ElementName="unknown1" Type="int8" Size="10" />
<Data ElementName="num_primary_selected_items" Type="int8" Size="1" />
<Data ElementName="primary_selected_items_array" Type="Array" ArraySizeVariable="num_primary_selected_items">
<Data ElementName="primary_selected_item_id" Type="int32" Size="1" />
<Data ElementName="primary_selected_item_qty" Type="int16" Size="1" />
</Data>
<Data ElementName="num_build_components" Type="int8" Size="1" />
<Data ElementName="component_array" Type="Array" ArraySizeVariable="num_build_components">
<Data ElementName="component_num" Type="int32" Size="1" />
<Data ElementName="component_unknown" Type="int8" Size="1" />
<Data ElementName="component_id" Type="int32" Size="1" />
<Data ElementName="component_qty" Type="int16" Size="1" />
</Data>
<Data ElementName="unknown2" Type="int8" Size="1" />
<Data ElementName="fuel_id" Type="int32" Size="1" />
<Data ElementName="fuel_qty" Type="int16" Size="1" />
<Data ElementName="unknown" Type="int32" Size="1" />
<Data ElementName="num_selected_items" Type="int8" Size="1" />
<Data ElementName="selected_item_array" Type="Array" ArraySizeVariable="num_selected_items">
<Data ElementName="selected_id" Type="int32" Size="1" />
<Data ElementName="selected_qty" Type="int16" Size="1" />
</Data>
</Data>
<Data ElementName="num_fuel_items" Type="int8" Size="1" />
<Data ElementName="fuel_item_array" Type="Array" ArraySizeVariable="num_fuel_items">
<Data ElementName="fuel_id" Type="int32" Size="1" />
<Data ElementName="fuel_qty" Type="int16" Size="1" />
</Data>
</Struct>
<Struct Name="WS_RecipeList" ClientVersion="1" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_RecipeList">
<Data ElementName="unknown" Type="int8" Size="1" />
@ -16504,7 +16523,7 @@ to zero and treated like placeholders." />
<Data ElementName="bag_name" Type="EQ2_8Bit_String" Size="1" />
</Struct>
<Struct Name="WS_SupplyDepot" ClientVersion="1096" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_SupplyDepot">
<Data ElementName="unknown1" Type="int8" Size="4" />
<Data ElementName="depot_id" Type="int32" Size="1" />
<Data ElementName="depot_name" Type="EQ2_16Bit_String" />
<Data ElementName="num_items" Type="int16" Size="1" />
<Data ElementName="max_items" Type="int16" Size="1" />
@ -18349,17 +18368,6 @@ to zero and treated like placeholders." />
<Data ElementName="unknown3" Type="int8" />
<Data ElementName="unknown4" Type="int8" />
</Struct>
<Struct Name="WS_ExamineInfoRequestMsg" ClientVersion="50000" OpcodeName="OP_ExamineInfoRequestMsg">
<Data ElementName="unknown" Type="int32" />
<Data ElementName="unknown1" Type="int32" />
<Data ElementName="unknown2" Type="int32" />
<Data ElementName="unknown3" Type="int32" />
<Data ElementName="unknown4" Type="int32" />
<Data ElementName="item_crc" Type="int32" />
<Data ElementName="unknown5" Type="int32" />
<Data ElementName="item_id" Type="int32" />
<Data ElementName="unknown6" Type="int16" />
</Struct>
<Struct Name="WS_PredictionUpdateMsg" ClientVersion="1" OpcodeName="OP_PredictionUpdateMsg">
</Struct>
<Struct Name="WS_QuestJournalInspectMsg" ClientVersion="1" OpcodeName="OP_QuestJournalInspectMsg">