Jump to content
  • 0

Blacksmith Blessing Behavior


Bulizik

Question


  • Group:  Members
  • Topic Count:  1
  • Topics Per Day:  0.00
  • Content Count:  1
  • Reputation:   0
  • Joined:  08/30/23
  • Last Seen:  

/**
 * Opens the refine UI on the designated client.
 * 0aa0
 */
void clif_refineui_open( struct map_session_data* sd ){
#if PACKETVER >= 20161012
	int fd = sd->fd;

	WFIFOHEAD(fd,packet_len(0x0AA0));
	WFIFOW(fd,0) = 0x0AA0;
	WFIFOSET(fd,packet_len(0x0AA0));

	sd->state.refineui_open = true;
#endif
}

/**
 * Parses cancel/close of the refine UI on client side.
 * 0aa4
 */
void clif_parse_refineui_close( int fd, struct map_session_data* sd ){
#if PACKETVER >= 20161012
	sd->state.refineui_open = false;
#endif
}

#define REFINEUI_MAT_BS_BLESS 4
#define REFINEUI_MAT_CNT (REFINEUI_MAT_BS_BLESS+1)

/**
 * Structure to store all required data about refine requirements
 */
struct refine_materials {
	struct refine_cost cost;
	uint8 chance;
	struct refine_bs_blessing bs_bless;
};

/**
 * Fills the given index with the requested data for that item and
 * returns true on success or false on failure.
 */
static inline bool clif_refineui_materials_sub( struct item *item, struct item_data *id, struct refine_materials materials[REFINEUI_MAT_CNT], int index, enum refine_cost_type type ){
	if( index < 0 || index >= REFINEUI_MAT_CNT ){
		return false;
	}

	struct refine_cost *cost = status_get_refine_cost_((enum refine_type)id->refine_type, type);
	if (!cost || !cost->refineui)
		return false;
	memcpy(&materials[index].cost, cost, sizeof(struct refine_cost));

	// Get the chance for refining the item with this material
	materials[index].chance = status_get_refine_chance((enum refine_type)id->refine_type, item->refine, type);

	// Either of the values was not set
	if( materials[index].cost.nameid == 0 || materials[index].cost.zeny == 0 || materials[index].chance == 0 ){
		// Reset all entries properly
		materials[index].cost.nameid = materials[index].cost.zeny = materials[index].chance = 0;
		return false;
	}else{
		// Everything was set properly
		return true;
	}
}

/**
 * Calculates all possible materials for the given item.
 * Returns the count of materials that were filled in the materials array.
 */
static inline uint8 clif_refineui_materials( struct item *item, struct item_data *id, struct refine_materials materials[REFINEUI_MAT_CNT] ){
	// Initialize the counter
	uint8 count = 0;

	// Zero the memory
	memset( materials, 0, sizeof(struct refine_materials)*REFINEUI_MAT_CNT );

	/**
	 * Default material indexing is follow as
	 * 0: Normal refine for +1 ~ +10 or +11 ~ +20
	 * 1: HD materials for +7 ~ +9 and +11 ~ +20
	 * 2: Enriched
	 * 3: Undecided yet, you can add yours later
	 * 4: Is always for 'Blacksmith Blessing' item to prevent downrefine/break
	 **/

	for (int i = 0; i < REFINE_COST_MAX; i++) {
		if (clif_refineui_materials_sub(item, id, materials, count, (enum refine_cost_type)i))
			count++;
	}

	// Blacksmith Blessing requirements if any
	status_get_refine_blacksmithBlessing(&materials[REFINEUI_MAT_BS_BLESS].bs_bless, (enum refine_type)id->wlv, item->refine);

	// Return the amount of found materials
	return count;
}

void clif_refineui_notrefineable(struct map_session_data *sd, uint16 index) {
	int fd = sd->fd;
	WFIFOHEAD(fd, 7);
	WFIFOW(fd, 0) = 0x0AA2;
	WFIFOW(fd, 2) = 7;
	WFIFOW(fd, 4) = index + 2;
	WFIFOB(fd, 6) = 0;
	WFIFOSET(fd, 7);
}

/**
 * Adds the selected item into the refine UI and sends the possible materials
 * to the client.
 * 0aa2 <length>.W <index>.W <catalyst count>.B { <material>.W <chance>.B <price>.L }*
 */
void clif_refineui_info( struct map_session_data* sd, uint16 index ){
	int fd = sd->fd;
	struct item *item;
	struct item_data *id;
	uint16 length;
	struct refine_materials materials[REFINEUI_MAT_CNT];
	uint8 i, material_count;

	// Get the item db reference
	id = sd->inventory_data[index];

	// No item data was found
	if( id == NULL || id->refine_type == REFINE_TYPE_MAX){
		return;
	}

	// Check if the item can be refined
	if( id->flag.no_refine ){
		clif_refineui_notrefineable(sd, index);
		return;
	}

	// Check the inventory
	item = &sd->inventory.u.items_inventory[index];

	// No item was found at the given index
	if( item == NULL ){
		return;
	}

	// Check if the item is identified
	if( !item->identify ){
		clif_refineui_notrefineable(sd, index);
		return;
	}

	// Check if the item is broken
	if( item->attribute ){
		clif_refineui_notrefineable(sd, index);
		return;
	}

	// Check the current refine level
	if( item->refine < 0 || item->refine >= MAX_REFINE ){
		clif_refineui_notrefineable(sd, index);
		return;
	}

	// Calculate the possible materials
	material_count = clif_refineui_materials( item, id, materials );

	// No possibilities were found
	if( material_count == 0 ){
		clif_refineui_notrefineable(sd, index);
		return;
	}

	length = 7 + material_count * 7;

	WFIFOHEAD(fd,length);
	WFIFOW(fd,0) = 0x0AA2;
	WFIFOW(fd,2) = length;
	WFIFOW(fd,4) = index + 2;
	WFIFOB(fd,6) = (uint8)materials[REFINEUI_MAT_BS_BLESS].bs_bless.count;

	for( i = 0; i < material_count; i++ ){
		WFIFOW(fd,7 + i * 7) = materials[i].cost.nameid;
		WFIFOB(fd,7 + i * 7 + 2) = materials[i].chance;
		WFIFOL(fd,7 + i * 7 + 3) = materials[i].cost.zeny;
	}

	WFIFOSET(fd,length);
}

/**
 * Client request to add an item to the refine UI.
 * 0aa1 <index>.W
 */
void clif_parse_refineui_add( int fd, struct map_session_data* sd ){
#if PACKETVER >= 20161012
	uint16 index = RFIFOW(fd, 2) - 2;

	// Check if the refine UI is open
	if( !sd->state.refineui_open ){
		return;
	}

	// Check if the index is valid
	if( index < 0 || index >= MAX_INVENTORY ){
		return;
	}

	// Send out the requirements for the refine process
	clif_refineui_info( sd, index );
#endif
}

/**
 * Client requests to try to refine an item.
 * 0aa3 <index>.W <material>.W <catalyst>.B
 */
void clif_parse_refineui_refine( int fd, struct map_session_data* sd ){
#if PACKETVER >= 20161012
	uint16 index = RFIFOW( fd, 2 ) - 2;
	uint16 material = RFIFOW( fd, 4 );
	bool use_blacksmith_blessing = RFIFOB( fd, 6 ) != 0;
	struct refine_materials materials[REFINEUI_MAT_CNT];
	uint8 i, material_count;
	uint16 j;
	struct item *item;
	struct item_data *id;

	// Check if the refine UI is open
	if( !sd->state.refineui_open ){
		return;
	}

	// Check if the index is valid
	if( index < 0 || index >= MAX_INVENTORY ){
		return;
	}

	// Get the item db reference
	id = sd->inventory_data[index];

	// No item data was found
	if( id == NULL || id->refine_type == REFINE_TYPE_MAX){
		return;
	}

	// Check if the item can be refined
	if( id->flag.no_refine ){
		return;
	}

	// Check the inventory
	item = &sd->inventory.u.items_inventory[index];

	// No item was found at the given index
	if( item == NULL ){
		return;
	}

	// Check if the item is identified
	if( !item->identify ){
		return;
	}

	// Check if the item is broken
	if( item->attribute ){
		return;
	}

	// Check the current refine level
	if( item->refine < 0 || item->refine >= MAX_REFINE ){
		return;
	}

	// Check if the player has the selected material
	if( ( j = pc_search_inventory( sd, material ) ) < 0 ){
		return;
	}

	// Calculate the possible materials
	material_count = clif_refineui_materials( item, id, materials );

	// No possibilities were found
	if( material_count == 0 ){
		return;
	}

	// Find the selected material
	ARR_FIND( 0, REFINEUI_MAT_CNT, i, materials[i].cost.nameid == material );

	// The material was not in the list of possible materials
	if( i >= REFINEUI_MAT_CNT || i < 0 ){
		return;
	}

	// Try to pay for the refine. By default, client checked if player has enough zeny or not
	if( pc_payzeny( sd, materials[i].cost.zeny, LOG_TYPE_CONSUME, NULL ) ){
		clif_npc_buy_result( sd, 1 ); // "You do not have enough zeny."
		return;
	}

	// Delete the required material
	if( pc_delitem( sd, j, 1, 0, 0, LOG_TYPE_CONSUME ) ){
		return;
	}

	if (use_blacksmith_blessing && materials[REFINEUI_MAT_BS_BLESS].bs_bless.count) {
		if ((j = pc_search_inventory(sd, materials[REFINEUI_MAT_BS_BLESS].bs_bless.nameid)) < 0) {
			return;
		}

		if (pc_delitem(sd, j, materials[REFINEUI_MAT_BS_BLESS].bs_bless.count, 0, 0, LOG_TYPE_CONSUME)) {
			return;
		}
	}
	else {
		use_blacksmith_blessing = false;
	}

	// Try to refine the item
	if( materials[i].chance >= rnd() % 100 ){
		// Success
		item->refine = cap_value( item->refine + 1, 0, MAX_REFINE );
		clif_misceffect( &sd->bl, 3 );
		clif_refine( fd, 0, index, item->refine );
		achievement_update_objective( sd, AG_REFINE_SUCCESS, 2, id->wlv, item->refine );
		clif_refineui_info( sd, index );
	}else{
		// Failure

		do {
			if (!use_blacksmith_blessing) {
				int r = rnd() % 100;
				if (r < materials[i].cost.breaking) { // Breaking chance
					clif_refine(fd, 1, index, item->refine);
					pc_delitem(sd, index, 1, 0, 0, LOG_TYPE_CONSUME);
					break;
				}
				else if (r < (materials[i].cost.breaking + materials[i].cost.downrefine)) { // Downrefine chance
					item->refine = cap_value(item->refine - materials[i].cost.downrefine_num, 0, MAX_REFINE);
					clif_refine(fd, 2, index, item->refine);
					clif_refineui_info(sd, index);
					break;
				}
			}
			// Blacksmith Blessing were used, no break & no down refine
			clif_refine(fd, 3, index, item->refine);
			clif_refineui_info(sd, index);
		} while (0);

		clif_misceffect( &sd->bl, 2 );
		achievement_update_objective( sd, AG_REFINE_FAIL, 1, 1 );
	}
#endif
}

#undef REFINEUI_MAT_CNT

how can i change the blacksmith blessing to only prevent downrefine only not the unbreakable part thanks

im using these sources https://github.com/cydh/rathena/pull/10

Edited by Bulizik
Link to comment
Share on other sites

0 answers to this question

Recommended Posts

There have been no answers to this question yet

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...