Ver Fonte

recipe and tradeskill updates

-- Fixed issue when examining recipes from book Live vs Classic recipe info would be displayed ( now uses ID vs name to retrieve recipe info
-- fixed issue where create recipe would not show all available primary items that are available in inventory
-- hover/examine recipe now show toal number available correctly
-- fixed issue where examining a recipe from book in inventory would crash the server if book was not scriped already
Robert Allen há 1 ano atrás
pai
commit
a4ed5802c7

+ 1 - 1
EQ2/source/WorldServer/Commands/Commands.cpp

@@ -2302,7 +2302,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 									if (recipes.empty() && item->recipebook_info) {
 										//Backup I guess if the recipe book is empty for whatever reason?
 										for (auto& itr : item->recipebook_info->recipes) {
-											Recipe* r = master_recipe_list.GetRecipeByName(itr.c_str());
+											Recipe* r = master_recipe_list.GetRecipe(itr);   //GetRecipeByName(itr.c_str());
 											if (r) {
 												recipes.push_back(r);
 											}

+ 3 - 3
EQ2/source/WorldServer/Items/Items.cpp

@@ -2463,10 +2463,10 @@ void Item::serialize(PacketStruct* packet, bool show_name, Player* player, int16
 				// Recipe Books
 				if(recipebook_info){
 					packet->setArrayLengthByName("num_recipes", recipebook_info->recipes.size());
-					for(int32 i = 0; i < recipebook_info->recipes.size(); i++){
-						packet->setArrayDataByName("recipe_name", recipebook_info->recipes.at(i).c_str(), i);
-						Recipe* recipe = master_recipe_list.GetRecipeByName(recipebook_info->recipes.at(i).c_str());
+					for (int32 i = 0; i < recipebook_info->recipes.size(); i++) {
+						Recipe* recipe = master_recipe_list.GetRecipe(recipebook_info->recipes.at(i));
 						if (recipe) {
+							packet->setArrayDataByName("recipe_name", recipe->GetName(), i);
 							packet->setArrayDataByName("recipe_id", recipe->GetID(), i);
 							packet->setArrayDataByName("recipe_icon", recipe->GetIcon(), i);
 						}

+ 1 - 1
EQ2/source/WorldServer/Items/Items.h

@@ -868,7 +868,7 @@ public:
 		int8                    fence_commission;
 	};
 	struct RecipeBook_Info{
-		vector<string>			recipes;
+		vector<uint32>			recipes;
 		int32					recipe_id;
 		int8					uses;
 	};

+ 4 - 4
EQ2/source/WorldServer/Items/ItemsDB.cpp

@@ -493,25 +493,25 @@ int32 WorldDatabase::LoadRecipeBookItems(int32 item_id)
 	//std::string select_query_addition = std::string(" where item_id = ") + std::to_string(item_id);
 	//MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT item_id, name FROM item_details_recipe_items%s", (item_id == 0) ? "" : select_query_addition.c_str());
 	std::string select_query_addition = std::string(" and r.item_id = ") + std::to_string(item_id);
-	MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT  r.item_id, ri.recipe_id ,ri.`name` FROM item_details_recipe r LEFT JOIN item_details_recipe_items ri ON ri.recipe_id = r.recipe_id where ri.recipe_id is not null%s", (item_id == 0) ? "" : select_query_addition.c_str());
+	MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT  r.item_id, ri.recipe_id ,ri.`name`,ri.soe_recipe_crc FROM item_details_recipe r LEFT JOIN item_details_recipe_items ri ON ri.recipe_id = r.recipe_id where ri.recipe_id is not null%s", (item_id == 0) ? "" : select_query_addition.c_str());
 	
 	int32 total = 0;
 	int32 id = 0;
-
+	uint32 soe_id = 0;
 	if (result)
 	{
 		while(result && (row = mysql_fetch_row(result)))
 		{
 			id = strtoul(row[0], NULL, 0);
 			Item* item = master_item_list.GetItem(id);
-
+			soe_id = strtoul(row[3], NULL, 0);
 			if(item)
 			{
 				LogWrite(ITEM__DEBUG, 5, "Items", "\tRecipe Book for item_id %u", id);
 				LogWrite(ITEM__DEBUG, 5, "Items", "\tType: %i, '%s'", ITEM_TYPE_RECIPE, row[2]);
 				item->SetItemType(ITEM_TYPE_RECIPE);
 				item->recipebook_info->recipe_id = (atoi(row[1]));
-				item->recipebook_info->recipes.push_back(string(row[2]));
+				item->recipebook_info->recipes.push_back(soe_id);
 				//item->recipebook_info->recipe_id(row[1]);
 				total++;
 			}

+ 11 - 5
EQ2/source/WorldServer/Recipes/Recipe.cpp

@@ -346,8 +346,15 @@ EQ2Packet * Recipe::SerializeRecipe(Client *client, Recipe *recipe, bool display
 	packet->setSubstructDataByName("recipe_info", "unknown4aa", 1);
 	packet->setSubstructDataByName("recipe_info", "unknown5a", 20);//level *10
 	packet->setSubstructDataByName("recipe_info", "product_classes", recipe->GetClasses());
-	packet->setSubstructDataByName("recipe_info", "show_previous", client->GetPlayer()->GetRecipeList()->GetRecipe(recipe->GetID())->highestStage);//     recipe->highestStage);
-
+	int32 HS = 0;
+	if (client->GetPlayer()->GetRecipeList()->GetRecipe(recipe->GetID()) == NULL)
+		HS = 0;
+	else 
+		HS = client->GetPlayer()->GetRecipeList()->GetRecipe(recipe->GetID())->highestStage;
+
+	 
+	packet->setSubstructDataByName("recipe_info", "show_previous", HS);//     recipe->highestStage);
+	
 
 	rp = recipe->products[1];
 	if (rp->product_id > 0) {
@@ -439,7 +446,7 @@ EQ2Packet * Recipe::SerializeRecipe(Client *client, Recipe *recipe, bool display
 	// Check to see if we have a primary component (slot = 0)
 	vector<Item*> itemss;
 	if (recipe->components.count(0) > 0) {
-		
+		int16 have_qty = 0;
 		vector<int32> rc = recipe->components[0];
 		for (itr = rc.begin(); itr != rc.end(); itr++, i++) {
 			item = master_item_list.GetItem(*itr);
@@ -450,14 +457,13 @@ EQ2Packet * Recipe::SerializeRecipe(Client *client, Recipe *recipe, bool display
 			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;
 			}
 		}
+		packet->setSubstructDataByName("recipe_info", "primary_qty_avail", have_qty);
 	}
 	
 	

+ 3 - 0
EQ2/source/WorldServer/Recipes/Recipe.h

@@ -51,6 +51,7 @@ public:
 
 	EQ2Packet *SerializeRecipe(Client *client, Recipe *recipe, bool display, int8 packet_type = 0, int8 sub_packet_type = 0, const char *struct_name = 0);
 	void SetID(int32 id) {this->id = id;}
+	void SetSoeID(int32 soe_id) { this->soe_id = soe_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)); }
@@ -86,6 +87,7 @@ public:
 	void SetPrimaryComponentQuantity(int8 qty) { primary_comp_qty = qty; }
 
 	int32 GetID() {return id;}
+	int32 GetSoeID() { return soe_id; }
 	int32 GetBookID() {return book_id;}
 	const char * GetName() {return name;}
 	const char* GetDescription() { return description; }
@@ -147,6 +149,7 @@ public:
 
 private:
 	int32 id;
+	int32 soe_id;
 	int32 book_id;
 	char name[256];
 	char description[256];

+ 9 - 4
EQ2/source/WorldServer/Recipes/RecipeDB.cpp

@@ -35,7 +35,7 @@ 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`,r.`description`,i.`name` as `book`,r.`bench`,ipc.`adventure_classes`, "
+		"SELECT r.`id`,r.`soe_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"
@@ -60,6 +60,7 @@ void WorldDatabase::LoadRecipes() {
 		int32 i = 0;
 		Recipe* recipe = new Recipe();
 		recipe->SetID(res.GetInt32(i++));
+		recipe->SetSoeID(res.GetInt32(i++));
 		recipe->SetLevel(res.GetInt32(i++));
 		recipe->SetTier(recipe->GetLevel() / 10 + 1);
 		recipe->SetIcon(res.GetInt32(i++));
@@ -268,11 +269,15 @@ void WorldDatabase::LoadRecipeComponents() {
 			if (!recipe) {
 				continue;
 			}
-			recipe->AddBuildComp(res.GetInt32(1), 0);
-			recipe->AddBuildComp(res.GetInt32(2), 5);
+		
 		}
 		if (recipe && !res.IsNull(3)) {
-			recipe->AddBuildComp(res.GetInt32(3), res.GetInt8(4));
+			if (find(recipe->components[0].begin(), recipe->components[0].end(), res.GetInt32(1)) == recipe->components[0].end())
+				recipe->AddBuildComp(res.GetInt32(1), 0);
+			if (find(recipe->components[5].begin(), recipe->components[5].end(), res.GetInt32(2)) == recipe->components[5].end())
+				recipe->AddBuildComp(res.GetInt32(2), 5);
+			if (find(recipe->components[res.GetInt8(4)].begin(), recipe->components[res.GetInt8(4)].end(), res.GetInt32(3)) == recipe->components[res.GetInt8(4)].end())
+				recipe->AddBuildComp(res.GetInt32(3), res.GetInt8(4));
 		}
 		//else
 			//LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Error loading `recipe_build_comps`, Recipe ID: %u", id);

+ 0 - 1
EQ2/source/WorldServer/Tradeskills/Tradeskills.cpp

@@ -372,7 +372,6 @@ void TradeskillMgr::StopCrafting(Client* client, bool lock) {
 	item_id = recipe->components[5][0];
 	float tsx = 0;
 	int8 HS = playerRecipe->GetHighestStage();
-	client->Message(CHANNEL_COLOR_RED, "%s: StopCrafting Error finding item %u to remove quantity for recipe id %u!", client->GetPlayer()->GetName(), dur);
 	if (progress < 400) { //stage 0
 		if (recipe->products.count(0) > 0) {
 			item_id = recipe->products[0]->product_id;

+ 18 - 10
EQ2/source/WorldServer/Tradeskills/TradeskillsPackets.cpp

@@ -112,6 +112,17 @@ void ClientPacketFunctions::SendCreateFromRecipe(Client* client, int32 recipeID)
 	if (recipe->components.count(0) > 0) {
 		vector<int32> rc = recipe->components[0];
 			vector <pair<int32, int16>> selected_items;
+
+			int32 total_primary_items = 0;
+		for (itr = rc.begin(); itr != rc.end(); itr++) {
+			itemss = client->GetPlayer()->item_list.GetAllItemsFromID((*itr));
+			if (itemss.size() > 0)
+				total_primary_items += itemss.size();
+		}
+		packet->setArrayLengthByName("num_primary_choices", total_primary_items);
+
+
+		int16 have_qty = 0;
 		for (itr = rc.begin(); itr != rc.end(); itr++, i++) {
 			if (firstID == 0)
 				firstID = *itr;
@@ -128,14 +139,12 @@ void ClientPacketFunctions::SendCreateFromRecipe(Client* client, int32 recipeID)
 			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++) {
+				for (int8 i = 0; i < itemss.size(); i++, k++) {
 					IDcount++;
 					if (have_qty < needed_qty) {
 
@@ -144,11 +153,11 @@ void ClientPacketFunctions::SendCreateFromRecipe(Client* client, int32 recipeID)
 						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_component", itemss[i]->name.c_str(), k);
+					packet->setArrayDataByName("primary_item_id", itemss[i]->details.unique_id, k);
+					packet->setArrayDataByName("primary_icon", itemss[i]->details.icon, k);
+					packet->setArrayDataByName("primary_total_quantity", itemss[i]->details.count, k);
+					//packet->setArrayDataByName("primary_supply_depot", itemss[i]->details.count, k);  // future need
 					//packet->setArrayDataByName("primary_unknown3a",);      // future need
 				}
 				packet->setDataByName("primary_id", itemss[0]->details.unique_id);
@@ -185,6 +194,7 @@ void ClientPacketFunctions::SendCreateFromRecipe(Client* client, int32 recipeID)
 		i = 0;
 		firstID = 0;
 		item = 0;
+		k = 0;
 	}
 	else {
 		LogWrite(TRADESKILL__ERROR, 0, "Recipes", "Recipe has no primary component");
@@ -224,8 +234,6 @@ void ClientPacketFunctions::SendCreateFromRecipe(Client* client, int32 recipeID)
 			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;

+ 0 - 1
EQ2/source/WorldServer/client.cpp

@@ -11408,7 +11408,6 @@ void Client::TriggerSpellSave()
 		save_spell_state_time_bucket = 0;
 		save_spell_state_timer.Start(interval, true);
 	}
-	
 	else
 	{
 		int32 elapsed_time = save_spell_state_timer.GetElapsedTime();