TradeskillsPackets.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. EQ2Emulator is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. EQ2Emulator is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <algorithm>
  17. #include "../ClientPacketFunctions.h"
  18. #include "../client.h"
  19. #include "../../common/ConfigReader.h"
  20. #include "../../common/PacketStruct.h"
  21. #include "../Recipes/Recipe.h"
  22. #include "../../common/Log.h"
  23. #include "../Spells.h"
  24. #include "../../common/MiscFunctions.h"
  25. #include "../World.h"
  26. extern ConfigReader configReader;
  27. extern MasterRecipeList master_recipe_list;
  28. extern MasterSpellList master_spell_list;
  29. extern World world;
  30. void ClientPacketFunctions::SendCreateFromRecipe(Client* client, int32 recipeID) {
  31. // if recipeID is 0 we are repeating the last recipe, if not set the players current recipe to the new one
  32. if (recipeID == 0)
  33. recipeID = client->GetPlayer()->GetCurrentRecipe();
  34. else
  35. client->GetPlayer()->SetCurrentRecipe(recipeID);
  36. Recipe* playerRecipe = client->GetPlayer()->GetRecipeList()->GetRecipe(recipeID);
  37. // Get the recipe
  38. Recipe* recipe = master_recipe_list.GetRecipe(recipeID);
  39. if(!playerRecipe)
  40. {
  41. LogWrite(TRADESKILL__ERROR, 0, "Tradeskills", "%s: ClientPacketFunctions::SendCreateFromRecipe Error finding player recipe %s in their recipe book for recipe id %u", client->GetPlayer()->GetName(), client->GetPlayer()->GetName(), recipe ? recipe->GetID() : 0);
  42. client->Message(CHANNEL_COLOR_RED, "You do not have %s (%u) in your recipe book.", recipe ? recipe->GetName() : "Unknown", recipe ? recipe->GetID() : 0);
  43. client->GetPlayer()->SetCurrentRecipe(0);
  44. return;
  45. }
  46. if (!recipe) {
  47. client->GetPlayer()->SetCurrentRecipe(0);
  48. LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Error loading recipe (%u) in ClientPacketFunctions::SendCreateFromRecipe()", recipeID);
  49. return;
  50. }
  51. // Create the packet
  52. PacketStruct* packet = configReader.getStruct("WS_CreateFromRecipe", client->GetVersion());
  53. if (!packet) {
  54. client->GetPlayer()->SetCurrentRecipe(0);
  55. LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Error loading WS_CreateFromRecipe in ClientPacketFunctions::SendCreateFromRecipe()");
  56. return;
  57. }
  58. vector<int32>::iterator itr;
  59. vector<Item*> itemss;
  60. int8 i = 0;
  61. int8 k = 0;
  62. int32 firstID = 0;
  63. int32 IDcount = 0;
  64. int32 primary_comp_id = 0;
  65. Item* first_item = 0;
  66. Item* item = 0;
  67. Item* item_player = 0;
  68. Spawn* target = client->GetPlayer()->GetTarget();
  69. int32 device_id = GetDeviceID(std::string(recipe->GetDevice()));
  70. if (!target || !target->IsObject() || device_id == 0 || (device_id != 0xFFFFFFFF && ((Object*)target)->GetDeviceID() != device_id)) {
  71. client->GetPlayer()->SetCurrentRecipe(0);
  72. client->Message(CHANNEL_COLOR_YELLOW, "You must be at a %s in order to craft this recipe", recipe->GetDevice());
  73. LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Failed to begin crafting with recipe id %u, recipe device_id is %u (%s), target object is %u.", recipe->GetID(), device_id, recipe->GetDevice(), (target && target->IsObject()) ? ((Object*)target)->GetDeviceID() : 0);
  74. return;
  75. }
  76. // Recipe and crafting table info
  77. packet->setDataByName("crafting_station", recipe->GetDevice());
  78. packet->setDataByName("recipe_name", recipe->GetName());
  79. packet->setDataByName("tier", recipe->GetTier());
  80. // Mass Production
  81. int32 mpq = 1;
  82. int32 mp = 5;
  83. vector<int> v{ 1,2,4,6,11,21 };
  84. // mpq will eventually be retrieved from achievement for mass production
  85. mpq = v[mp];
  86. packet->setArrayLengthByName("num_mass_production_choices",mpq);
  87. packet->setArrayDataByName("mass_qty", 1, 0);
  88. for (int x = 1; x < mpq; x++) {
  89. packet->setArrayDataByName("mass_qty", x * 5, x);
  90. }
  91. // Product info
  92. item = master_item_list.GetItem(recipe->GetProductID());
  93. packet->setDataByName("product_name", item->name.c_str());
  94. packet->setDataByName("icon", item->GetIcon(client->GetVersion()));
  95. packet->setDataByName("product_qty", recipe->GetProductQuantity());
  96. packet->setDataByName("primary_title", recipe->GetPrimaryBuildComponentTitle());
  97. packet->setDataByName("primary_qty_needed", recipe->GetPrimaryComponentQuantity());
  98. packet->setDataByName("unknown6", 11);
  99. packet->setDataByName("unknown3", 18);
  100. // Reset item to 0
  101. item, item_player = 0;
  102. // Check to see if we have a primary component (slot = 0)
  103. if (recipe->components.count(0) > 0) {
  104. vector<int32> rc = recipe->components[0];
  105. vector <pair<int32, int16>> selected_items;
  106. int32 total_primary_items = 0;
  107. for (itr = rc.begin(); itr != rc.end(); itr++) {
  108. itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
  109. if (itemss.size() > 0)
  110. total_primary_items += itemss.size();
  111. }
  112. packet->setArrayLengthByName("num_primary_choices", total_primary_items);
  113. int16 have_qty = 0;
  114. for (itr = rc.begin(); itr != rc.end(); itr++, i++) {
  115. if (firstID == 0)
  116. firstID = *itr;
  117. item = master_item_list.GetItem(*itr);
  118. if (!item)
  119. {
  120. client->GetPlayer()->SetCurrentRecipe(0);
  121. LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Error creating packet to client missing item %u", *itr);
  122. client->Message(CHANNEL_COLOR_RED, "Error producing create recipe packet! Recipe is trying to find item %u, but it is missing!", *itr);
  123. safe_delete(packet);
  124. return;
  125. }
  126. item_player = 0;
  127. item_player = client->GetPlayer()->item_list.GetItemFromID((*itr));
  128. itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
  129. if (itemss.size() > 0) {
  130. int16 needed_qty = recipe->GetPrimaryComponentQuantity();
  131. if (firstID == 0)
  132. firstID = *itr;
  133. for (int8 i = 0; i < itemss.size(); i++, k++) {
  134. IDcount++;
  135. if (have_qty < needed_qty) {
  136. int16 stack_count = itemss[i]->details.count;
  137. int16 min_qty = min(stack_count, int16(needed_qty - have_qty));
  138. selected_items.push_back(make_pair(int32(itemss[i]->details.unique_id), min_qty));
  139. have_qty += min_qty;
  140. }
  141. packet->setArrayDataByName("primary_component", itemss[i]->name.c_str(), k);
  142. packet->setArrayDataByName("primary_item_id", itemss[i]->details.unique_id, k);
  143. packet->setArrayDataByName("primary_icon", itemss[i]->GetIcon(client->GetVersion()), k);
  144. packet->setArrayDataByName("primary_total_quantity", itemss[i]->details.count, k);
  145. //packet->setArrayDataByName("primary_supply_depot", itemss[i]->details.count, k); // future need
  146. //packet->setArrayDataByName("primary_unknown3a",); // future need
  147. }
  148. packet->setDataByName("primary_id", itemss[0]->details.unique_id);
  149. packet->setDataByName("primary_default_selected_id", itemss[0]->details.unique_id);
  150. for (int8 i = 0; i < selected_items.size(); i++) {
  151. }
  152. int16 qty = 0;
  153. if (item) {
  154. qty = (int8)item->details.count;
  155. if (qty > 0 && firstID == primary_comp_id)
  156. qty -= 1;
  157. }
  158. }
  159. else
  160. packet->setDataByName("primary_id",*itr);
  161. }
  162. // store the id of the primary comp
  163. primary_comp_id = firstID;
  164. // Set the default item id to the first component id
  165. packet->setArrayLengthByName("num_primary_items_selected", selected_items.size());
  166. for (int8 i = 0; i < selected_items.size(); i++) {
  167. packet->setArrayDataByName("primary_selected_item_qty", selected_items[i].second,i );
  168. packet->setArrayDataByName("primary_selected_item_id", selected_items[i].first,i);
  169. }
  170. // Reset the variables we will reuse
  171. i = 0;
  172. firstID = 0;
  173. item = 0;
  174. k = 0;
  175. }
  176. else {
  177. LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Recipe has no primary component");
  178. return;
  179. }
  180. // Check to see if we have build components (slot = 1 - 4)
  181. int8 total_build_components = 0;
  182. if (recipe->components.count(1) > 0)
  183. total_build_components++;
  184. if (recipe->components.count(2))
  185. total_build_components++;
  186. if (recipe->components.count(3))
  187. total_build_components++;
  188. if (recipe->components.count(4))
  189. total_build_components++;
  190. //--------------------------------------------------------------Start Build Components-------------------------------------------------------------
  191. if (total_build_components > 0) {
  192. packet->setArrayLengthByName("num_build_components", total_build_components);
  193. LogWrite(TRADESKILL__INFO, 0, "Recipes", "num_build_components %u", total_build_components);
  194. for (int8 index = 0; index < 4; index++) {
  195. if (recipe->components.count(index + 1) == 0)
  196. continue;
  197. packet->setArrayDataByName("build_slot", index, index);
  198. vector<int32> rc = recipe->components[index + 1];
  199. int32 total_component_items = 0;
  200. int8 hasComp = 0;
  201. vector <pair<int32, int16>> selected_items;
  202. for (itr = rc.begin(); itr != rc.end(); itr++) {
  203. itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
  204. if (itemss.size() > 0)
  205. total_component_items += itemss.size();
  206. }
  207. packet->setSubArrayLengthByName("num_build_choices", total_component_items, index);// get # build choces first
  208. hasComp = 0;
  209. char msgbuf[200] = "";
  210. for (itr = rc.begin(); itr != rc.end(); itr++) {// iterates through each recipe component to find the stacks in inventory
  211. item = master_item_list.GetItem(*itr);
  212. itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
  213. if (itemss.size() > 0) {
  214. int16 needed_qty = 0;
  215. int16 have_qty = 0;
  216. if (index == 0) {
  217. needed_qty = recipe->GetBuild1ComponentQuantity();
  218. have_qty = 0;
  219. }
  220. else if (index == 1) {
  221. needed_qty = recipe->GetBuild2ComponentQuantity();
  222. have_qty = 0;
  223. }
  224. else if (index == 2) {
  225. needed_qty = recipe->GetBuild3ComponentQuantity();
  226. have_qty = 0;
  227. }
  228. else if (index == 3) {
  229. needed_qty = recipe->GetBuild4ComponentQuantity();
  230. have_qty = 0;
  231. }
  232. if (firstID == 0)
  233. firstID = *itr;
  234. if (hasComp == 0) {
  235. hasComp = 100 + k;
  236. }
  237. for (int8 j = 0; j < itemss.size(); j++, k++) { // go through each stack of a compnent
  238. if (have_qty < needed_qty) {
  239. int16 stack_count = itemss[j]->details.count;
  240. int16 min_qty = min(stack_count, int16(needed_qty - have_qty));
  241. selected_items.push_back(make_pair(int32(itemss[j]->details.unique_id), min_qty));
  242. have_qty += min_qty;
  243. }
  244. item = master_item_list.GetItem(itemss[j]->details.item_id);
  245. packet->setSubArrayDataByName("build_component", itemss[j]->name.c_str(), index, k);
  246. packet->setSubArrayDataByName("build_item_id", itemss[j]->details.unique_id, index, k);
  247. packet->setSubArrayDataByName("build_icon", itemss[j]->GetIcon(client->GetVersion()), index, k);
  248. packet->setSubArrayDataByName("build_total_quantity", itemss[j]->details.count, index, k);
  249. //packet->setSubArrayDataByName("build_supply_depot",); // future need
  250. //packet->setSubArrayDataByName("build_unknown3",); // future need
  251. }
  252. }
  253. }
  254. packet->setSubArrayLengthByName("num_build_items_selected", selected_items.size(),index );
  255. for (int8 i = 0; i < selected_items.size(); i++) {
  256. packet->setSubArrayDataByName("build_selected_item_qty", selected_items[i].second,index, i);
  257. packet->setSubArrayDataByName("build_selected_item_id", selected_items[i].first,index, i);
  258. }
  259. int16 qty = 0;
  260. if (item) {
  261. qty = (int16)item->details.count;
  262. if (qty > 0 && firstID == primary_comp_id)
  263. qty -= 1;
  264. }
  265. if (index == 0) {
  266. packet->setArrayDataByName("build_title", recipe->GetBuild1ComponentTitle(), index);
  267. packet->setArrayDataByName("build_qty_needed", recipe->GetBuild1ComponentQuantity(), index);
  268. if (item)
  269. packet->setArrayDataByName("build_selected_item_qty_have", min(qty, recipe->GetBuild1ComponentQuantity()), index);
  270. }
  271. else if (index == 1) {
  272. packet->setArrayDataByName("build_title", recipe->GetBuild2ComponentTitle(), index);
  273. packet->setArrayDataByName("build_qty_needed", recipe->GetBuild2ComponentQuantity(), index);
  274. if (item)
  275. packet->setArrayDataByName("build_selected_item_qty_have", min(qty, recipe->GetBuild2ComponentQuantity()), index);
  276. }
  277. else if (index == 2) {
  278. packet->setArrayDataByName("build_title", recipe->GetBuild3ComponentTitle(), index);
  279. packet->setArrayDataByName("build_qty_needed", recipe->GetBuild3ComponentQuantity(), index);
  280. if (item)
  281. packet->setArrayDataByName("build_selected_item_qty_have", min(qty, recipe->GetBuild3ComponentQuantity()), index);
  282. }
  283. else {
  284. packet->setArrayDataByName("build_title", recipe->GetBuild4ComponentTitle(), index);
  285. packet->setArrayDataByName("build_qty_needed", recipe->GetBuild4ComponentQuantity(), index);
  286. if (item)
  287. packet->setArrayDataByName("build_selected_item_qty_have", min(qty, recipe->GetBuild4ComponentQuantity()), index);
  288. }
  289. // Reset the variables we will reuse
  290. i = 0;
  291. firstID = 0;
  292. item = 0;
  293. k = 0;
  294. }
  295. int32 xxx = 0;
  296. }
  297. // Check to see if we have a fuel component (slot = 5)
  298. if (recipe->components.count(5) > 0) {
  299. vector<int32> rc = recipe->components[5];
  300. vector <pair<int32, int16>> selected_items;
  301. for (itr = rc.begin(); itr != rc.end(); itr++, i++) {
  302. if (firstID == 0)
  303. firstID = *itr;
  304. item = master_item_list.GetItem(*itr);
  305. if (!item)
  306. {
  307. LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Error creating packet to client missing item %u", *itr);
  308. client->Message(CHANNEL_COLOR_RED, "Error producing create recipe packet! Recipe is trying to find item %u, but it is missing!", *itr);
  309. safe_delete(packet);
  310. return;
  311. }
  312. item_player = 0;
  313. item_player = client->GetPlayer()->item_list.GetItemFromID((*itr));
  314. if(client->GetVersion() <= 561) {
  315. packet->setDataByName("fuel_qty", item->details.count);
  316. packet->setDataByName("fuel_icon", item->GetIcon(client->GetVersion()));
  317. }
  318. itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
  319. packet->setArrayLengthByName("num_fuel_choices", itemss.size());
  320. if (itemss.size() > 0) {
  321. int16 needed_qty = recipe->GetFuelComponentQuantity();
  322. int16 have_qty = 0;
  323. if (firstID == 0)
  324. firstID = *itr;
  325. for (int8 i = 0; i < itemss.size(); i++) {
  326. IDcount++;
  327. if (have_qty < needed_qty) {
  328. int16 stack_count = itemss[i]->details.count;
  329. int16 min_qty = min(stack_count, int16(needed_qty - have_qty));
  330. selected_items.push_back(make_pair(int32(itemss[i]->details.unique_id), min_qty));
  331. have_qty += min_qty;
  332. }
  333. packet->setArrayDataByName("fuel_component", itemss[i]->name.c_str(), i);
  334. packet->setArrayDataByName("fuel_item_id", itemss[i]->details.unique_id, i);
  335. packet->setArrayDataByName("fuel_icon", itemss[i]->GetIcon(client->GetVersion()), i);
  336. packet->setArrayDataByName("fuel_total_quantity", itemss[i]->details.count, i);
  337. //packet->setArrayDataByName("fuel_supply_depot", itemss[i]->details.count, i); // future need
  338. //packet->setArrayDataByName("primary_unknown3a",); // future need
  339. }
  340. packet->setDataByName("fuel_selected_item_id", itemss[0]->details.unique_id);
  341. int16 qty = 0;
  342. if (item) {
  343. qty = (int8)item->details.count;
  344. if (qty > 0 && firstID == primary_comp_id)
  345. qty -= 1;
  346. }
  347. }
  348. else
  349. packet->setDataByName("primary_vvv", *itr);
  350. }
  351. // store the id of the primary comp
  352. primary_comp_id = firstID;
  353. // Set the default item id to the first component id
  354. packet->setArrayLengthByName("num_fuel_items_selected", selected_items.size());
  355. for (int8 i = 0; i < selected_items.size(); i++) {
  356. packet->setArrayDataByName("fuel_selected_item_qty", selected_items[i].second, i);
  357. packet->setArrayDataByName("fuel_selected_item_id", selected_items[i].first, i);
  358. }
  359. packet->setDataByName("fuel_title", recipe->GetFuelComponentTitle());
  360. packet->setDataByName("fuel_qty_needed", recipe->GetFuelComponentQuantity());
  361. // Reset the variables we will reuse
  362. i = 0;
  363. firstID = 0;
  364. item = 0;
  365. }
  366. else {
  367. LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Recipe has no fuel component");
  368. return;
  369. }
  370. packet->setDataByName("recipe_id", recipeID);
  371. packet->PrintPacket();
  372. EQ2Packet* outapp = packet->serialize();
  373. //DumpPacket(outapp);
  374. // Send the packet
  375. client->QueuePacket(outapp);
  376. safe_delete(packet);
  377. }
  378. void ClientPacketFunctions::SendItemCreationUI(Client* client, Recipe* recipe) {
  379. // Check for valid recipe
  380. if (!recipe) {
  381. LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Recipe = null in ClientPacketFunctions::SendItemCreationUI()");
  382. return;
  383. }
  384. // Load the packet
  385. PacketStruct* packet = configReader.getStruct("WS_ShowItemCreation", client->GetVersion());
  386. if (!packet) {
  387. LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Error loading WS_ShowItemCreation in ClientPacketFunctions::SendItemCreationUI()");
  388. return;
  389. }
  390. int16 item_version = GetItemPacketType(packet->GetVersion());
  391. Item* item = 0;
  392. RecipeProducts* rp = 0;
  393. packet->setDataByName("max_possible_durability", 1000);
  394. packet->setDataByName("max_possible_progress", 1000);
  395. // All the packets I have looked at these unknowns are always the same
  396. // so hardcoding them until they are identified.
  397. packet->setDataByName("unknown2", 1045220557, 0);
  398. packet->setDataByName("unknown2", 1061997773, 1);
  399. // Highest stage the player has been able to complete
  400. // TODO: store this for the player, for now use 0 (none known)
  401. Recipe* playerRecipe = client->GetPlayer()->GetRecipeList()->GetRecipe(recipe->GetID());
  402. if(!playerRecipe)
  403. {
  404. LogWrite(TRADESKILL__ERROR, 0, "Tradeskills", "%s: ClientPacketFunctions::SendItemCreationUI Error finding player recipe in their recipe book for recipe id %u", client->GetPlayer()->GetName(), recipe->GetID());
  405. client->Message(CHANNEL_COLOR_RED, "%s: SendItemCreationUI Error finding player recipe in their recipe book for recipe id %u!", client->GetPlayer()->GetName(), recipe->GetID());
  406. safe_delete(packet);
  407. return;
  408. }
  409. packet->setDataByName("progress_levels_known", playerRecipe ? playerRecipe->GetHighestStage() : 0);
  410. packet->setArrayLengthByName("num_process", 4);
  411. for (int8 i = 0; i < 4; i++) {
  412. // Don't like this code but need to change the IfVariableNotSet value on unknown3 element
  413. // to point to the currect progress_needed
  414. vector<DataStruct*> dataStructs = packet->GetDataStructs();
  415. vector<DataStruct*>::iterator itr;
  416. for (itr = dataStructs.begin(); itr != dataStructs.end(); itr++) {
  417. DataStruct* data = *itr;
  418. char tmp[20] = {0};
  419. sprintf(tmp,"_%i",i);
  420. string name = "unknown3";
  421. name.append(tmp);
  422. if (strcmp(data->GetName(), name.c_str()) == 0) {
  423. name = "progress_needed";
  424. name.append(tmp);
  425. data->SetIfNotSetVariable(name.c_str());
  426. }
  427. }
  428. if (i == 1)
  429. packet->setArrayDataByName("progress_needed", 400, i);
  430. else if (i == 2)
  431. packet->setArrayDataByName("progress_needed", 600, i);
  432. else if (i == 3)
  433. packet->setArrayDataByName("progress_needed", 800, i);
  434. // get the product for this stage, if none found default to fuel
  435. if (recipe->products.count(i) > 0)
  436. rp = recipe->products[i];
  437. if (!rp || (rp->product_id == 0)) {
  438. rp = new RecipeProducts;
  439. rp->product_id = recipe->components[5].front();
  440. rp->product_qty = recipe->GetFuelComponentQuantity();
  441. rp->byproduct_id = 0;
  442. rp->byproduct_qty = 0;
  443. recipe->products[i] = rp;
  444. }
  445. item = master_item_list.GetItem(rp->product_id);
  446. if (!item) {
  447. LogWrite(TRADESKILL__ERROR, 0, "Recipe", "Error loading item (%u) in ClientPacketFunctions::SendItemCreationUI()", rp->product_id);
  448. return;
  449. }
  450. packet->setArrayDataByName("item_name", item->name.c_str(), i);
  451. packet->setArrayDataByName("item_icon", item->GetIcon(client->GetVersion()), i);
  452. if(client->GetVersion() < 860) {
  453. packet->setItemArrayDataByName("item", item, client->GetPlayer(), i, 0, client->GetClientItemPacketOffset());
  454. //packet->setItemArrayDataByName("item", item, client->GetPlayer(), i, 0, -1);
  455. }
  456. else if (client->GetVersion() < 1193)
  457. packet->setItemArrayDataByName("item", item, client->GetPlayer(), i);
  458. else
  459. packet->setItemArrayDataByName("item", item, client->GetPlayer(), i, 0, 2);
  460. if (rp->byproduct_id > 0) {
  461. item = 0;
  462. item = master_item_list.GetItem(rp->byproduct_id);
  463. if (item) {
  464. packet->setArrayDataByName("item_byproduct_name", item->name.c_str(), i);
  465. packet->setArrayDataByName("item_byproduct_icon", item->GetIcon(client->GetVersion()), i);
  466. }
  467. }
  468. packet->setArrayDataByName("packettype", item_version, i);
  469. packet->setArrayDataByName("packetsubtype", 0xFF, i);
  470. item = 0;
  471. rp = 0;
  472. }
  473. packet->setDataByName("product_progress_needed", 1000);
  474. rp = recipe->products[4];
  475. item = master_item_list.GetItem(rp->product_id);
  476. packet->setDataByName("product_item_name", item->name.c_str());
  477. packet->setDataByName("product_item_icon", item->GetIcon(client->GetVersion()));
  478. if(client->GetVersion() < 860)
  479. packet->setItemByName("product_item", item, client->GetPlayer(), 0, client->GetClientItemPacketOffset());
  480. else if (client->GetVersion() < 1193)
  481. packet->setItemByName("product_item", item, client->GetPlayer());
  482. else
  483. packet->setItemByName("product_item", item, client->GetPlayer(), 0, 2);
  484. //packet->setItemByName("product_item", item, client->GetPlayer());
  485. if (rp->byproduct_id > 0) {
  486. item = 0;
  487. item = master_item_list.GetItem(rp->byproduct_id);
  488. if (item) {
  489. packet->setDataByName("product_byproduct_name", item->name.c_str());
  490. packet->setDataByName("product_byproduct_icon", item->GetIcon(client->GetVersion()));
  491. }
  492. }
  493. packet->setDataByName("packettype", item_version);
  494. packet->setDataByName("packetsubtype", 0xFF);
  495. // Start of basic work to get the skills to show on the tradeskill window
  496. // not even close to accurate but skills do get put on the ui
  497. int8 index = 0;
  498. int8 size = 0;
  499. vector<int32>::iterator itr;
  500. vector<int32> spells = client->GetPlayer()->GetSpellBookSpellIDBySkill(recipe->GetTechnique());
  501. for (itr = spells.begin(); itr != spells.end(); itr++) {
  502. size++;
  503. Spell* spell = master_spell_list.GetSpell(*itr,1);
  504. if(!spell) {
  505. return;
  506. }
  507. if (size > 6) {
  508. // only 6 slots for skills on the ui
  509. break;
  510. }
  511. packet->setDataByName("skill_id", *itr ,spell->GetSpellData()->ts_loc_index -1);
  512. }
  513. packet->PrintPacket();
  514. EQ2Packet* outapp = packet->serialize();
  515. DumpPacket(outapp);
  516. client->QueuePacket(outapp);
  517. safe_delete(packet);
  518. }
  519. void ClientPacketFunctions::StopCrafting(Client* client) {
  520. if(client->GetPlayer()) {
  521. client->GetPlayer()->SetTempVisualState(-1);
  522. }
  523. client->QueuePacket(new EQ2Packet(OP_StopItemCreationMsg, 0, 0));
  524. }
  525. void ClientPacketFunctions::CounterReaction(Client* client, bool countered) {
  526. PacketStruct* packet = configReader.getStruct("WS_TSEventReaction", client->GetVersion());
  527. if (packet) {
  528. packet->setDataByName("counter_reaction", countered ? 1 : 0);
  529. client->QueuePacket(packet->serialize());
  530. }
  531. safe_delete(packet);
  532. }