- Added cash shop support. (i need to add documentation, working on it).
- An charcommand is still required to add/remove points. - Scripts command only requires to work on #CASHPOINTS and #KAFRAPOINTS. - I called it "Kafra Points" just because it's how comes in the translation. I allready know this changes between Oficial servers. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12264 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
68c7440203
commit
e6bf7c5458
@ -3,6 +3,8 @@ Date Added
|
||||
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
|
||||
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
|
||||
|
||||
2008/02/28
|
||||
* Added cash shop support [Zephyrus]
|
||||
2008/02/27
|
||||
* Fixed 'cleararray' not able to erase array entry 127 (bugreport:864)
|
||||
* Fixed @reloadmobdb producing memory leaks in pet db (bugreport:1030)
|
||||
|
@ -990,7 +990,7 @@ packet_ver: 22
|
||||
0x01fd,15,repairitem,2
|
||||
|
||||
//2007-02-27aSakexe to 2007-10-02aSakexe
|
||||
0x0288,10
|
||||
0x0288,10,cashshopbuy,2:4:6
|
||||
0x0289,12
|
||||
0x02a6,22
|
||||
0x02a7,22
|
||||
|
@ -11701,6 +11701,57 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd)
|
||||
|
||||
#endif
|
||||
|
||||
/*==========================================
|
||||
* CASH/POINT SHOP
|
||||
*==========================================*/
|
||||
void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd)
|
||||
{
|
||||
int fd,i;
|
||||
|
||||
nullpo_retv(sd);
|
||||
nullpo_retv(nd);
|
||||
|
||||
fd = sd->fd;
|
||||
sd->npc_shopid = nd->bl.id;
|
||||
WFIFOHEAD(fd, 200 * 11 + 12);
|
||||
WFIFOW(fd,0) = 0x287;
|
||||
WFIFOW(fd,2) = 12 + nd->u.shop.count*11;
|
||||
WFIFOL(fd,4) = sd->cashPoints; // Cash Points
|
||||
WFIFOL(fd,8) = sd->kafraPoints; // Kafra Points
|
||||
|
||||
for( i = 0; i < nd->u.shop.count; i++ )
|
||||
{
|
||||
struct item_data* id = itemdb_search(nd->u.shop.shop_item[i].nameid);
|
||||
WFIFOL(fd,12+i*11) = nd->u.shop.shop_item[i].value;
|
||||
WFIFOL(fd,16+i*11) = nd->u.shop.shop_item[i].value; // Discount Prize? Maybe a Discount item
|
||||
WFIFOB(fd,20+i*11) = itemtype(id->type);
|
||||
WFIFOW(fd,21+i*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid;
|
||||
}
|
||||
WFIFOSET(fd,WFIFOW(fd,2));
|
||||
}
|
||||
|
||||
void clif_parse_cashshop_buy(int fd, struct map_session_data *sd)
|
||||
{
|
||||
int fail = 0, amount, points;
|
||||
short nameid;
|
||||
struct npc_data *nd;
|
||||
nullpo_retv(sd);
|
||||
|
||||
nd = (struct npc_data *)map_id2bl(sd->npc_shopid);
|
||||
nameid = RFIFOW(fd,2);
|
||||
amount = RFIFOW(fd,4);
|
||||
points = RFIFOL(fd,6); // Not Implemented. Should be 0
|
||||
|
||||
fail = npc_cashshop_buy(sd, nameid, amount, points);
|
||||
|
||||
WFIFOHEAD(fd,12);
|
||||
WFIFOW(fd,0) = 0x289;
|
||||
WFIFOL(fd,2) = sd->cashPoints;
|
||||
WFIFOL(fd,6) = sd->kafraPoints;
|
||||
WFIFOW(fd,10) = fail;
|
||||
WFIFOSET(fd,12);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Requesting equip of a player
|
||||
*------------------------------------------*/
|
||||
@ -12161,6 +12212,7 @@ static int packetdb_readdb(void)
|
||||
{clif_parse_Mail_winopen,"mailwinopen"},
|
||||
{clif_parse_Mail_send,"mailsend"},
|
||||
#endif
|
||||
{clif_parse_cashshop_buy,"cashshopbuy"},
|
||||
{clif_parse_ViewPlayerEquip,"viewplayerequip"},
|
||||
{clif_parse_EquipTick,"equiptickbox"},
|
||||
{NULL,NULL}
|
||||
|
@ -411,4 +411,6 @@ void clif_Mail_refreshinbox(struct map_session_data *sd);
|
||||
void clif_Mail_getattachment(int fd, uint8 flag);
|
||||
#endif
|
||||
|
||||
void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd);
|
||||
|
||||
#endif /* _CLIF_H_ */
|
||||
|
@ -188,7 +188,7 @@ enum bl_type {
|
||||
#define BL_CHAR (BL_PC|BL_MOB|BL_HOM)
|
||||
#define BL_ALL 0xfff
|
||||
|
||||
enum npc_subtype { WARP, SHOP, SCRIPT };
|
||||
enum npc_subtype { WARP, SHOP, SCRIPT, CASHSHOP };
|
||||
|
||||
enum {
|
||||
RC_FORMLESS=0,
|
||||
@ -782,6 +782,8 @@ struct map_session_data {
|
||||
|
||||
char away_message[128]; // [LuzZza]
|
||||
|
||||
int cashPoints, kafraPoints;
|
||||
|
||||
// Mail System [Zephyrus]
|
||||
struct {
|
||||
short nameid;
|
||||
|
109
src/map/npc.c
109
src/map/npc.c
@ -932,6 +932,9 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd)
|
||||
case SHOP:
|
||||
clif_npcbuysell(sd,nd->bl.id);
|
||||
break;
|
||||
case CASHSHOP:
|
||||
clif_cashshop_show(sd,nd);
|
||||
break;
|
||||
case SCRIPT:
|
||||
run_script(nd->u.scr.script,0,sd->bl.id,nd->bl.id);
|
||||
break;
|
||||
@ -1012,6 +1015,77 @@ static int npc_buylist_sub(struct map_session_data* sd, int n, unsigned short* i
|
||||
npc_event(sd, npc_ev, 0);
|
||||
return 0;
|
||||
}
|
||||
/*==========================================
|
||||
* Cash Shop Buy
|
||||
*------------------------------------------*/
|
||||
int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points)
|
||||
{
|
||||
struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid);
|
||||
struct item_data *item;
|
||||
int i, prize, w;
|
||||
|
||||
if( !nd || nd->subtype != CASHSHOP )
|
||||
return 1;
|
||||
|
||||
if( sd->state.trading )
|
||||
return 4;
|
||||
|
||||
if( (item = itemdb_search(nameid)) == NULL )
|
||||
return 5; // Invalid Item
|
||||
|
||||
ARR_FIND(0, nd->u.shop.count, i, nd->u.shop.shop_item[i].nameid == nameid);
|
||||
if( i == nd->u.shop.count )
|
||||
return 5;
|
||||
if( nd->u.shop.shop_item[i].value <= 0 )
|
||||
return 5;
|
||||
|
||||
if(!itemdb_isstackable(nameid) && amount > 1)
|
||||
{
|
||||
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n",
|
||||
sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
|
||||
amount = 1;
|
||||
}
|
||||
|
||||
switch( pc_checkadditem(sd, nameid, amount) )
|
||||
{
|
||||
case ADDITEM_NEW:
|
||||
if( pc_inventoryblank(sd) == 0 )
|
||||
return 3;
|
||||
break;
|
||||
case ADDITEM_OVERAMOUNT:
|
||||
return 3;
|
||||
}
|
||||
|
||||
w = item->weight * amount;
|
||||
if( w + sd->weight > sd->max_weight )
|
||||
return 3;
|
||||
|
||||
prize = nd->u.shop.shop_item[i].value * amount;
|
||||
if( points > prize )
|
||||
points = prize;
|
||||
|
||||
if( sd->cashPoints < prize - points )
|
||||
return 6;
|
||||
if( sd->kafraPoints < points )
|
||||
return 6;
|
||||
|
||||
pc_paycash(sd, prize, points);
|
||||
|
||||
if( !pet_create_egg(sd, nameid) )
|
||||
{
|
||||
struct item item_tmp;
|
||||
memset(&item_tmp, 0, sizeof(struct item));
|
||||
item_tmp.nameid = nameid;
|
||||
item_tmp.identify = 1;
|
||||
|
||||
pc_additem(sd,&item_tmp, amount);
|
||||
}
|
||||
|
||||
if(log_config.enable_logs&0x20)
|
||||
log_pick_pc(sd, "S", nameid, amount, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
@ -1266,7 +1340,7 @@ int npc_unload(struct npc_data* nd)
|
||||
npc_chat_finalize(nd); // deallocate npc PCRE data structures
|
||||
#endif
|
||||
|
||||
if( nd->subtype == SHOP )
|
||||
if( nd->subtype == SHOP || nd->subtype == CASHSHOP )
|
||||
aFree(nd->u.shop.shop_item);
|
||||
else
|
||||
if( nd->subtype == SCRIPT )
|
||||
@ -1547,7 +1621,7 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
|
||||
return strchr(start,'\n');// continue
|
||||
}
|
||||
|
||||
/// Parses a shop npc.
|
||||
/// Parses a shop/cashshop npc.
|
||||
static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
|
||||
{
|
||||
//TODO: could be rewritten to NOT need this temp array [ultramage]
|
||||
@ -1557,12 +1631,17 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
|
||||
int x, y, dir, m, i;
|
||||
struct npc_data *nd;
|
||||
|
||||
enum npc_subtype type = SHOP;
|
||||
if( !strcasecmp(w2,"cashshop") )
|
||||
type = CASHSHOP;
|
||||
|
||||
if( strcmp(w1,"-") == 0 )
|
||||
{// 'floating' shop?
|
||||
x = 0; y = 0; dir = 0; m = -1;
|
||||
x = y = dir = 0;
|
||||
m = -1;
|
||||
}
|
||||
else
|
||||
{// w1=<map name>,<x>,<y>,<facing>
|
||||
{
|
||||
char mapname[32];
|
||||
if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4
|
||||
|| strchr(w4, ',') == NULL )
|
||||
@ -1570,6 +1649,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
|
||||
ShowError("npc_parse_shop: Invalid shop definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
|
||||
return strchr(start,'\n');// skip and continue
|
||||
}
|
||||
|
||||
m = map_mapname2mapid(mapname);
|
||||
}
|
||||
|
||||
@ -1583,14 +1663,25 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
|
||||
ShowError("npc_parse_shop: Invalid item definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
|
||||
break;
|
||||
}
|
||||
id = itemdb_search(nameid);
|
||||
|
||||
if( (id = itemdb_search(nameid)) == NULL )
|
||||
{
|
||||
ShowError("npc_parse_shop: Invalid sell item in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
|
||||
break;
|
||||
}
|
||||
|
||||
if( value < 0 )
|
||||
value = id->value_buy;
|
||||
if( value*0.75 < id->value_sell*1.24 )
|
||||
{
|
||||
if( type == SHOP ) value = id->value_buy;
|
||||
else value = 0; // Cashshop don't have a "buy prize" in the item_db
|
||||
}
|
||||
|
||||
if( type == SHOP && value*0.75 < id->value_sell*1.24 )
|
||||
{// Expoit possible: you can buy and sell back with profit
|
||||
ShowWarning("npc_parse_shop: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) at file '%s', line '%d'.\n",
|
||||
id->name, nameid, value, (int)(value*0.75), id->value_sell, (int)(id->value_sell*1.24), filepath, strline(buffer,start-buffer));
|
||||
}
|
||||
|
||||
//for logs filters, atcommands and iteminfo script command
|
||||
if( id->maxchance <= 0 )
|
||||
id->maxchance = 10000; //10000 (100% drop chance)would show that the item's sold in NPC Shop
|
||||
@ -1620,7 +1711,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
|
||||
|
||||
++npc_shop;
|
||||
nd->bl.type = BL_NPC;
|
||||
nd->subtype = SHOP;
|
||||
nd->subtype = type;
|
||||
if( m >= 0 )
|
||||
{// normal shop npc
|
||||
map_addnpc(m,nd);
|
||||
@ -2605,7 +2696,7 @@ void npc_parsesrcfile(const char* filepath)
|
||||
{
|
||||
p = npc_parse_warp(w1,w2,w3,w4, p, buffer, filepath);
|
||||
}
|
||||
else if( strcasecmp(w2,"shop") == 0 && count > 3 )
|
||||
else if( (!strcasecmp(w2,"shop") || !strcasecmp(w2,"cashshop")) && count > 3 )
|
||||
{
|
||||
p = npc_parse_shop(w1,w2,w3,w4, p, buffer, filepath);
|
||||
}
|
||||
|
@ -89,6 +89,8 @@ int npc_reload(void);
|
||||
void npc_read_event_script(void);
|
||||
int npc_script_event(struct map_session_data* sd, enum npce_event type);
|
||||
|
||||
int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points);
|
||||
|
||||
extern struct npc_data* fake_nd;
|
||||
|
||||
#endif /* _NPC_H_ */
|
||||
|
63
src/map/pc.c
63
src/map/pc.c
@ -792,6 +792,10 @@ int pc_reg_received(struct map_session_data *sd)
|
||||
sd->change_level = pc_readglobalreg(sd,"jobchange_level");
|
||||
sd->die_counter = pc_readglobalreg(sd,"PC_DIE_COUNTER");
|
||||
|
||||
// Cash shop
|
||||
sd->cashPoints = pc_readaccountreg(sd,"#CASHPOINTS");
|
||||
sd->kafraPoints = pc_readaccountreg(sd,"#KAFRAPOINTS");
|
||||
|
||||
if ((sd->class_&MAPID_BASEMASK)==MAPID_TAEKWON)
|
||||
{ //Better check for class rather than skill to prevent "skill resets" from unsetting this
|
||||
sd->mission_mobid = pc_readglobalreg(sd,"TK_MISSION_ID");
|
||||
@ -2694,6 +2698,65 @@ int pc_payzeny(struct map_session_data *sd,int zeny)
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*==========================================
|
||||
* Cash Shop
|
||||
*------------------------------------------*/
|
||||
|
||||
void pc_paycash(struct map_session_data *sd, int prize, int points)
|
||||
{
|
||||
char output[128];
|
||||
int cash = prize - points;
|
||||
nullpo_retv(sd);
|
||||
|
||||
sd->cashPoints -= cash;
|
||||
sd->kafraPoints -= points;
|
||||
|
||||
pc_setaccountreg(sd,"#CASHPOINTS",sd->cashPoints);
|
||||
pc_setaccountreg(sd,"#KAFRAPOINTS",sd->kafraPoints);
|
||||
|
||||
if( points )
|
||||
{
|
||||
sprintf(output, "Used %d kafra points. %d points remaining.", points, sd->kafraPoints);
|
||||
clif_disp_onlyself(sd, output, strlen(output));
|
||||
}
|
||||
|
||||
if( cash )
|
||||
{
|
||||
sprintf(output, "Used %d cash points. %d points remaining.", cash, sd->cashPoints);
|
||||
clif_disp_onlyself(sd, output, strlen(output));
|
||||
}
|
||||
}
|
||||
|
||||
void pc_getcash(struct map_session_data *sd, int cash, int points)
|
||||
{
|
||||
char output[128];
|
||||
nullpo_retv(sd);
|
||||
|
||||
if( cash > MAX_ZENY - sd->cashPoints )
|
||||
cash = MAX_ZENY - sd->cashPoints;
|
||||
|
||||
sd->cashPoints += cash;
|
||||
|
||||
if( points > MAX_ZENY - sd->kafraPoints )
|
||||
points = MAX_ZENY - sd->kafraPoints;
|
||||
|
||||
sd->kafraPoints += points;
|
||||
|
||||
pc_setaccountreg(sd,"#CASHPOINTS",sd->cashPoints);
|
||||
pc_setaccountreg(sd,"#KAFRAPOINTS",sd->kafraPoints);
|
||||
|
||||
if( cash > 0 )
|
||||
{
|
||||
sprintf(output, "Gained %d cash points. Total %d points", points, sd->cashPoints);
|
||||
clif_disp_onlyself(sd, output, strlen(output));
|
||||
}
|
||||
|
||||
if( points > 0 )
|
||||
{
|
||||
sprintf(output, "Gained %d kafra points. Total %d points", points, sd->kafraPoints);
|
||||
clif_disp_onlyself(sd, output, strlen(output));
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* ‚¨‹à‚𓾂é
|
||||
|
@ -177,6 +177,10 @@ int pc_additem(struct map_session_data*,struct item*,int);
|
||||
int pc_getzeny(struct map_session_data*,int);
|
||||
int pc_delitem(struct map_session_data*,int,int,int);
|
||||
|
||||
// Special Shop System
|
||||
void pc_paycash(struct map_session_data *sd, int prize, int points);
|
||||
void pc_getcash(struct map_session_data *sd, int cash, int points);
|
||||
|
||||
int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amount);
|
||||
int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type);
|
||||
int pc_putitemtocart(struct map_session_data *sd,int idx,int amount);
|
||||
|
Loading…
x
Reference in New Issue
Block a user