(Cashshop) Currency

Tranquility

New member
Messages
102
Points
0
Emulator
Greetings,

Upon going through the modifications I have to make for my scripts and ideas to work with Herc, I encountered different kinds of shops and other features.

However, stubborn as I am, I wonder if it is possible to modify clif.c to add/modify the current currencies for an item from our item database?

Taking the source for the Cash/Point shop, I see that currency is being declared, but due to my lack of programming skills I can't think of a way to point it to a new value, namely one from the item database.

Is anyone able to push me in the right direction? I've already located the most likely point of origin to modify for this to be possible, the spoiler below contains the cash shop code from clif.c.

/// CASH/POINT SHOP////// List of items offered in a cash shop (ZC_PC_CASH_POINT_ITEMLIST)./// 0287 <packet len>.W <cash point>.L { <sell price>.L <discount price>.L <item type>.B <name id>.W }*/// 0287 <packet len>.W <cash point>.L <kafra point>.L { <sell price>.L <discount price>.L <item type>.B <name id>.W }* (PACKETVER >= 20070711)void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) { struct npc_item_list *shop = NULL; unsigned short shop_size = 0; int fd,i, c = 0; int currency[2] = { 0,0 };#if PACKETVER < 20070711 const int offset = 8;#else const int offset = 12;#endif nullpo_retv(sd); nullpo_retv(nd); if( nd->subtype == SCRIPT ) { shop = nd->u.scr.shop->item; shop_size = nd->u.scr.shop->items; npc->trader_count_funds(nd, sd); currency[0] = npc->trader_funds[0]; currency[1] = npc->trader_funds[1]; } else { shop = nd->u.shop.shop_item; shop_size = nd->u.shop.count; currency[0] = sd->cashPoints; currency[1] = sd->kafraPoints; } fd = sd->fd; sd->npc_shopid = nd->bl.id; WFIFOHEAD(fd,offset+shop_size*11); WFIFOW(fd,0) = 0x287; /* 0x2 = length, set after parsing */ WFIFOL(fd,4) = currency[0]; // Cash Points#if PACKETVER >= 20070711 WFIFOL(fd,8) = currency[1]; // Kafra Points#endif for( i = 0; i < shop_size; i++ ) { if( shop.nameid ) { struct item_data* id = itemdb->search(shop.nameid); WFIFOL(fd,offset+0+i*11) = shop.value; WFIFOL(fd,offset+4+i*11) = shop.value; // Discount Price WFIFOB(fd,offset+8+i*11) = itemtype(id->type); WFIFOW(fd,offset+9+i*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid; c++; } } WFIFOW(fd,2) = offset+c*11; WFIFOSET(fd,WFIFOW(fd,2));}/// Cashshop Buy Ack (ZC_PC_CASH_POINT_UPDATE)./// 0289 <cash point>.L <error>.W/// 0289 <cash point>.L <kafra point>.L <error>.W (PACKETVER >= 20070711)/// For error return codes see enum [email protected] clif_cashshop_ack(struct map_session_data* sd, int error) { struct npc_data *nd; int fd; int currency[2] = { 0,0 }; nullpo_retv(sd); fd = sd->fd; if( (nd = map->id2nd(sd->npc_shopid)) && nd->subtype == SCRIPT ) { npc->trader_count_funds(nd,sd); currency[0] = npc->trader_funds[0]; currency[1] = npc->trader_funds[1]; } else { currency[0] = sd->cashPoints; currency[1] = sd->kafraPoints; } WFIFOHEAD(fd, packet_len(0x289)); WFIFOW(fd,0) = 0x289; WFIFOL(fd,2) = currency[0];#if PACKETVER < 20070711 WFIFOW(fd,6) = TOW(error);#else WFIFOL(fd,6) = currency[1]; WFIFOW(fd,10) = TOW(error);#endif WFIFOSET(fd, packet_len(0x289));}void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));/// Request to buy item(s) from cash shop (CZ_PC_BUY_CASH_POINT_ITEM)./// 0288 <name id>.W <amount>.W/// 0288 <name id>.W <amount>.W <kafra points>.L (PACKETVER >= 20070711)/// 0288 <packet len>.W <kafra points>.L <count>.W { <amount>.W <name id>.W }.4B*count (PACKETVER >= 20100803)void clif_parse_cashshop_buy(int fd, struct map_session_data *sd){ int fail = 0; if( sd->state.trading || !sd->npc_shopid || pc_has_permission(sd,PC_PERM_DISABLE_STORE) ) fail = 1; else {#if PACKETVER < 20101116 short nameid = RFIFOW(fd,2); short amount = RFIFOW(fd,4); int points = RFIFOL(fd,6); fail = npc->cashshop_buy(sd, nameid, amount, points);#else int len = RFIFOW(fd,2); int points = RFIFOL(fd,4); int count = RFIFOW(fd,8); unsigned short* item_list = (unsigned short*)RFIFOP(fd,10); if( len < 10 || len != 10 + count * 4) { ShowWarning("Player %u sent incorrect cash shop buy packet (len %u:%u)!n", sd->status.char_id, len, 10 + count * 4); return; } fail = npc->cashshop_buylist(sd,points,count,item_list);#endif } clif->cashshop_ack(sd,fail);}



Thanks in advance.

Note: I have done my search and did find this as an option, however I like to expand my horizon and get things done how I have them in mind. Potentially providing a change for others to use.
I'm not too lazy to search, just too stubborn to accept workaround to be a valid solution.

 

 
Last edited by a moderator:
Something like this ? : https://raw.githubusercontent.com/HerculesWS/Hercules/master/doc/sample/npc_trader_sample.txt

Code:
/* custom npc trader */prontera,153,152,1	trader	TestCustom2	4_F_EDEN_OFFICER,{	OnInit:	tradertype(NST_CUSTOM);	sellitem Red_Potion,2;	end;/* allows currency to be item 501 and 502 */OnCountFunds:	setcurrency(countitem(Red_Potion),countitem(Orange_Potion));	end;/* receives @price (total cost) and @points (the secondary input field for cash windows) */OnPayFunds:	dispbottom "Hi: price="+@price+" and points="+@points;	if( countitem(Orange_Potion) < @points || countitem(Red_Potion) < @price-@points )		end;	delitem Orange_Potion,@points;	delitem Red_Potion,@price-@points;	purchaseok();	end;}
 
Something like this ? : https://raw.githubusercontent.com/HerculesWS/Hercules/master/doc/sample/npc_trader_sample.txt

/* custom npc trader */prontera,153,152,1 trader TestCustom2 4_F_EDEN_OFFICER,{ OnInit: tradertype(NST_CUSTOM); sellitem Red_Potion,2; end;/* allows currency to be item 501 and 502 */OnCountFunds: setcurrency(countitem(Red_Potion),countitem(Orange_Potion)); end;/* receives @price (total cost) and @points (the secondary input field for cash windows) */OnPayFunds: dispbottom "Hi: price="+@price+" and points="+@points; if( countitem(Orange_Potion) < @points || countitem(Red_Potion) < @price-@points ) end; delitem Orange_Potion,@points; delitem Red_Potion,@price-@points; purchaseok(); end;}
I'll get back to this soon, need to verify ;p

Else I might have to try make a plugin for this, to have the rA cashshop feature with custom currency here too.

 
Finally tested it and it's a yes/no thing.

Yes I would like the functionality to modify the currency like that script shows there, however I would like to use the original cashshop user interface, located in the rop right to do this.

The currencies are hard-coded inside source, but when reading the original commit for the cashshop, I was hoping a variable could be added that allows to read a currency set in cashshop_db.conf (in this scenario an itemID).

Yet defaulting to the cashpoint variable if nothing is specified.

Hopefully this isn't too far fetched of an idea.

 
by finding pc->paycash command

I found that buying this stuff are actually clif_parse_CashShopBuy located in clif.c

I think you just have to change pc->paycash into your delitem ... something

 
Last edited by a moderator:
by finding pc->paycash command

I found that buying this stuff are actually clif_parse_CashShopBuy located in clif.c

I think you just have to change pc->paycash into your delitem ... something
Hmm, trying to think along here with what you posted. Browing further through clif.c the following is what I've come up with..

First we'd need to verify that if the player has enough currency 'x' to buy item 'y'. Replacing:

if( sd->kafraPoints < kafra_pay ) { result = CSBR_SHORTTAGE_CASH;} else if( (sd->cashPoints+kafra_pay) < (clif->cs.data[tab][j]->price * qty) ) { result = CSBR_SHORTTAGE_CASH;}
Next, replacing the paycash reference for a delitem referrence, however, delitem has more parameters to take into account(?)

pc->paycash(sd, clif->cs.data[tab][j]->price * qty, kafra_pay);// [Ryuuzaki]To something like:pc->delitem(sd,n,clif->cs.data[tab][j]->price * qty,0,DELITEM_NORMAL,LOG_TYPE_NPC);
Honestly I lack the skill or insight to know what I'm doing, but this is what I can deduce from the code elsewhere.

Would reading a variable from the item_cash_db.conf be nicer to know whether or not a custom currency is to be used? Then if the variable isn't set, default will be cashpoints/kafrapoints.

 
Last edited by a moderator:
although its possible to do this on the source, but I'm client noob

I know how to delete item directly when make a purchase

but the client side still shows "x points will be deducted from your kafra credit points"

Would reading a variable from the item_cash_db.conf be nicer to know whether or not a custom currency is to be used? Then if the variable isn't set, default will be cashpoints/kafrapoints.
that will require some intense source modification I guesswhy not just write a plugin and add a configuration for require item ID ?

 
Last edited by a moderator:
although its possible to do this on the source, but I'm client noob

I know how to delete item directly when make a purchase

but the client side still shows "x points will be deducted from your kafra credit points"

Would reading a variable from the item_cash_db.conf be nicer to know whether or not a custom currency is to be used? Then if the variable isn't set, default will be cashpoints/kafrapoints.
that will require some intense source modification I guesswhy not just write a plugin and add a configuration for require item ID ?
Thanks for the input, I'll give it a try. When I get stuck, I'll get back you guys
default_smile.png


 
Back
Top