summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-05-11 20:03:22 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-05-11 20:03:22 +0000
commita3cd04965d83f00ee9ca0020f60bea1f5c83ac6b (patch)
tree63da4f4d60806a5eb790b7d1072e042d38872b3a /src
parent7eaf99edd466011a1ac3c909157b0422120cae4e (diff)
downloadhercules-a3cd04965d83f00ee9ca0020f60bea1f5c83ac6b.tar.gz
hercules-a3cd04965d83f00ee9ca0020f60bea1f5c83ac6b.tar.bz2
hercules-a3cd04965d83f00ee9ca0020f60bea1f5c83ac6b.tar.xz
hercules-a3cd04965d83f00ee9ca0020f60bea1f5c83ac6b.zip
- Changed a bit the MAX_ZENY checks in trade.c to prevent overflows.
- Rewrote npc_selllist for a more proper-clean implementation. - Increased NPC_POWERUP's dex bonus to +25*lv - Moved TK_DOWNKICK's stun time from time to time2 - Added TK_TURNKICK's stun to splash-pushed mobs. Duration is 2secs (time2) git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@6557 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src')
-rw-r--r--src/map/clif.c22
-rw-r--r--src/map/npc.c88
-rw-r--r--src/map/skill.c27
-rw-r--r--src/map/trade.c16
4 files changed, 81 insertions, 72 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index b020d3f9f..75f374abf 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9272,30 +9272,18 @@ void clif_parse_NpcBuyListSend(int fd,struct map_session_data *sd)
*/
void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd)
{
- int fail=0,n,i;
+ int fail=0,n;
unsigned short *item_list;
- unsigned char npc_ev[51];
- struct npc_data *nd;
RFIFOHEAD(fd);
n = (RFIFOW(fd,2)-4) /4;
item_list = (unsigned short*)RFIFOP(fd,4);
- if (sd->state.trading|| !sd->npc_shopid)
+ if (sd->state.trading || !sd->npc_shopid)
fail = 1;
- else{
- if((nd = ((struct npc_data *)map_id2bl(sd->npc_shopid))->master_nd)){
- sprintf(npc_ev, "%s::OnSellItem", nd->exname);
- for(i=0;i<n;i++){
- setd_sub(sd, "@sold_nameid", i, (void *)((int)sd->status.inventory[item_list[i*2]-2].nameid));
- setd_sub(sd, "@sold_quantity", i, (void *)((int)item_list[i*2+1]));
- }
- npc_event(sd, npc_ev, 0);
- fail = 0;
- }else{
- fail = npc_selllist(sd,n,item_list);
- }
- }
+ else
+ fail = npc_selllist(sd,n,item_list);
+
sd->npc_shopid = 0; //Clear shop data.
WFIFOHEAD(fd,packet_len_table[0xcb]);
diff --git a/src/map/npc.c b/src/map/npc.c
index 7d9db7358..c463b0282 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1223,52 +1223,59 @@ int npc_selllist(struct map_session_data *sd,int n,unsigned short *item_list)
{
double z;
int i,skill,itemamount=0;
-
+ struct npc_data *nd;
+
nullpo_retr(1, sd);
nullpo_retr(1, item_list);
+ nd = (struct npc_data *)map_id2bl(sd->npc_shopid);
+ if (!nd) return 1;
+ nd = nd->master_nd; //For OnSell triggers.
+
//if (npc_checknear(sd,sd->npc_shopid))
// return 1;
for(i=0,z=0;i<n;i++) {
- int nameid;
- if (item_list[i*2]-2 <0 || item_list[i*2]-2 >=MAX_INVENTORY)
- return 1;
- nameid=sd->status.inventory[item_list[i*2]-2].nameid;
- if (nameid == 0 ||
- sd->status.inventory[item_list[i*2]-2].amount < item_list[i*2+1])
- return 1;
- if (itemdb_value_notoc(nameid))
- z+=(double)itemdb_value_sell(nameid) * item_list[i*2+1];
+ int nameid, idx, qty;
+ idx = item_list[i*2]-2;
+ qty = item_list[i*2+1];
+
+ if (idx <0 || idx >=MAX_INVENTORY || qty < 0)
+ break;
+
+ nameid=sd->status.inventory[idx].nameid;
+ if (nameid == 0 || !sd->inventory_data[idx] ||
+ sd->status.inventory[idx].amount < qty)
+ break;
+
+ if (sd->inventory_data[idx]->flag.value_notoc)
+ z+=(double)qty*sd->inventory_data[idx]->value_sell;
else
- z+=(double)pc_modifysellvalue(sd,itemdb_value_sell(nameid)) * item_list[i*2+1];
- itemamount+=item_list[i*2+1];
+ z+=(double)qty*pc_modifysellvalue(sd,sd->inventory_data[idx]->value_sell);
+
+ if(sd->inventory_data[idx]->type==7 && sd->status.inventory[idx].card[0] == (short)0xff00)
+ {
+ if(search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0)
+ intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1],sd->status.inventory[idx].card[2]));
+ }
+
+ if(log_config.pick) //Logs items, Sold to NPC (S)hop [Lupus]
+ log_pick(sd, "S", 0, nameid, qty, &sd->status.inventory[idx]);
+
+ if(nd) {
+ setd_sub(sd, "@sold_nameid", i, (void *)(int)sd->status.inventory[idx].nameid);
+ setd_sub(sd, "@sold_quantity", i, (void *)(int)qty);
+ }
+ itemamount+=qty;
+ pc_delitem(sd,idx,qty,0);
}
if (z > MAX_ZENY) z = MAX_ZENY;
- //Logs (S)hopping Zeny [Lupus]
- if(log_config.zeny > 0 )
+ if(log_config.zeny) //Logs (S)hopping Zeny [Lupus]
log_zeny(sd, "S", sd, (int)z);
- //Logs
pc_getzeny(sd,(int)z);
- for(i=0;i<n;i++) {
- int item_id=item_list[i*2]-2;
- if( sd->status.inventory[item_id].nameid>0 && sd->inventory_data[item_id] != NULL &&
- sd->inventory_data[item_id]->type==7 && sd->status.inventory[item_id].amount>0 &&
- sd->status.inventory[item_id].card[0] == (short)0xff00)
- if(search_petDB_index(sd->status.inventory[item_id].nameid, PET_EGG) >= 0)
- intif_delete_petdata(MakeDWord(sd->status.inventory[item_id].card[1],sd->status.inventory[item_id].card[2]));
-
- //Logs items, Sold to NPC (S)hop [Lupus]
- if(sd && log_config.pick > 0 )
- log_pick(sd, "S", 0, sd->status.inventory[item_id].nameid, -item_list[i*2+1], &sd->status.inventory[item_id]);
- //Logs
-
- pc_delitem(sd,item_id,item_list[i*2+1],0);
- }
-
- //lol
+
if (battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_OVERCHARGE)) > 0) {
if (sd->status.skill[MC_OVERCHARGE].flag != 0)
skill = sd->status.skill[MC_OVERCHARGE].flag - 2;
@@ -1279,9 +1286,22 @@ int npc_selllist(struct map_session_data *sd,int n,unsigned short *item_list)
pc_gainexp(sd,0,(int)z);
}
}
-
+
+ if(nd) {
+ unsigned char npc_ev[51];
+ sprintf(npc_ev, "%s::OnSellItem", nd->exname);
+ npc_event(sd, npc_ev, 0);
+ }
+
+ if (i<n) {
+ //Error/Exploit... of some sort. If we return 1, the client will not mark
+ //any item as deleted even though a few were sold. In such a case, we
+ //have no recourse but to kick them out so their inventory will refresh
+ //correctly on relog. [Skotlex]
+ if (i) clif_setwaitclose(sd->fd);
+ return 1;
+ }
return 0;
-
}
int npc_remove_map (struct npc_data *nd)
diff --git a/src/map/skill.c b/src/map/skill.c
index c72eccfd6..0d819e5ba 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -1259,7 +1259,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
break;
case TK_DOWNKICK:
- sc_start(bl,SC_STUN,100,skilllv,skill_get_time(skillid,skilllv));
+ sc_start(bl,SC_STUN,100,skilllv,skill_get_time2(skillid,skilllv));
break;
case TK_JUMPKICK:
@@ -1284,6 +1284,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
status_change_end(bl, SC_ADRENALINE2, -1);
}
break;
+ case TK_TURNKICK:
case MO_BALKYOUNG: //Note: attack_type is passed as BF_WEAPON for the actual target, BF_MISC for the splash-affected mobs.
if(attack_type == BF_MISC) //70% base stun chance...
sc_start(bl,SC_STUN,70,skilllv,skill_get_time2(skillid,skilllv));
@@ -4955,7 +4956,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case NPC_POWERUP:
sc_start(bl,SC_INCATKRATE,100,40*skilllv,skill_get_time(skillid, skilllv));
//From experience it appears powerup is more hit, not +all stats.
- sc_start(bl,SC_INCDEX,100,20*skilllv,skill_get_time(skillid, skilllv));
+ sc_start(bl,SC_INCDEX,100,25*skilllv,skill_get_time(skillid, skilllv));
// sc_start(bl,SC_INCALLSTATUS,100,skilllv*5,skill_get_time(skillid, skilllv));
clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
@@ -5361,24 +5362,24 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
sc_start(src,SC_SMA,100,skilllv,skill_get_time(SL_SMA,skilllv));
break;
- case SL_SKA: // [marquis007]
case SL_SWOO:
- case SL_SKE:
- if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
- status_change_start(src,SC_STUN,10000,skilllv,0,0,0,500,10);
- clif_skill_fail(sd,skillid,0,0);
- break;
- }
-
- if (skillid == SL_SWOO && tsc && tsc->data[type].timer != -1) {
+ if (tsc && tsc->data[type].timer != -1) {
sc_start(src,SC_STUN,100,skilllv,10000);
break;
}
- clif_skill_nodamage(src,bl,skillid,skilllv,
- sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
+ case SL_SKA: // [marquis007]
+ case SL_SKE:
+ if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB)
+ clif_skill_fail(sd,skillid,0,0);
+ else
+ clif_skill_nodamage(src,bl,skillid,skilllv,
+ sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
if (skillid == SL_SKE)
sc_start(src,SC_SMA,100,skilllv,skill_get_time(SL_SMA,skilllv));
+
+ //Regardless of who you target, caster gets stunned for 0.5 [Skotlex]
+ status_change_start(src,SC_STUN,10000,skilllv,0,0,0,500,10);
break;
// New guild skills [Celest]
diff --git a/src/map/trade.c b/src/map/trade.c
index 002d974da..5de4ffd91 100644
--- a/src/map/trade.c
+++ b/src/map/trade.c
@@ -187,21 +187,21 @@ int impossible_trade_check(struct map_session_data *sd) {
* Checks if trade is possible (against zeny limits, inventory limits, etc)
*------------------------------------------
*/
-int trade_check(struct map_session_data *sd, struct map_session_data *target_sd) {
+int trade_check(struct map_session_data *sd, struct map_session_data *tsd) {
struct item inventory[MAX_INVENTORY];
struct item inventory2[MAX_INVENTORY];
struct item_data *data;
int trade_i, i, amount, n;
// check zenys value against hackers (Zeny was already checked on time of adding, but you never know when you lost some zeny since then.
- if(sd->deal.zeny > sd->status.zeny || (target_sd->status.zeny + sd->deal.zeny) > MAX_ZENY)
+ if(sd->deal.zeny > sd->status.zeny || (tsd->status.zeny > MAX_ZENY - sd->deal.zeny))
return 0;
- if(target_sd->deal.zeny > target_sd->status.zeny || (sd->status.zeny + target_sd->deal.zeny) > MAX_ZENY)
+ if(tsd->deal.zeny > tsd->status.zeny || (sd->status.zeny > MAX_ZENY - tsd->deal.zeny))
return 0;
// get inventory of player
memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY);
- memcpy(&inventory2, &target_sd->status.inventory, sizeof(struct item) * MAX_INVENTORY);
+ memcpy(&inventory2, &tsd->status.inventory, sizeof(struct item) * MAX_INVENTORY);
// check free slot in both inventory
for(trade_i = 0; trade_i < 10; trade_i++) {
@@ -240,10 +240,10 @@ int trade_check(struct map_session_data *sd, struct map_session_data *target_sd)
// memset(&inventory[n], 0, sizeof(struct item));
}
}
- amount = target_sd->deal.item[trade_i].amount;
+ amount = tsd->deal.item[trade_i].amount;
if (!amount)
continue;
- n = target_sd->deal.item[trade_i].index;
+ n = tsd->deal.item[trade_i].index;
if (amount > inventory2[n].amount)
return 0;
// search if it's possible to add item (for full inventory)
@@ -297,8 +297,8 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount) {
if (index == 0)
{ //Adding Zeny
- if (amount >= 0 && amount <= MAX_ZENY && amount <= sd->status.zeny && // check amount
- (target_sd->status.zeny + amount) <= MAX_ZENY) // fix positiv overflow
+ if (amount >= 0 && amount <= sd->status.zeny && // check amount
+ (amount <= MAX_ZENY - target_sd->status.zeny)) // fix positiv overflow
{ //Check Ok
sd->deal.zeny = amount;
clif_tradeadditem(sd, target_sd, 0, amount);