Bläddra i källkod

- 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://svn.code.sf.net/p/rathena/svn/trunk@6557 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex 19 år sedan
förälder
incheckning
a0bf90e52c
7 ändrade filer med 95 tillägg och 73 borttagningar
  1. 7 0
      Changelog-Trunk.txt
  2. 4 0
      db/Changelog.txt
  3. 3 1
      db/skill_cast_db.txt
  4. 5 17
      src/map/clif.c
  5. 54 34
      src/map/npc.c
  6. 14 13
      src/map/skill.c
  7. 8 8
      src/map/trade.c

+ 7 - 0
Changelog-Trunk.txt

@@ -4,6 +4,13 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 2006/05/11
+	* Changed a bit the MAX_ZENY checks in trade.c to prevent overflows.
+	  [Skotlex]
+	* Rewrote npc_selllist for a more proper-clean implementation. [Skotlex]
+	* Increased NPC_POWERUP's dex bonus to +25*lv [Skotlex]
+	* Moved TK_DOWNKICK's stun time from time to time2 [Skotlex]
+	* Added TK_TURNKICK's stun to splash-pushed mobs. Duration is 2secs (time2)
+	  [Skotlex]
 	* Merged the code for Ska, Ske, Swoo together. Swoo stun duration is now 10
 	  secs (reducable) if you target a mob that already has Swoo active. [Skotlex]
 	* Added the missing semi-comma from the upgrade_svn6533.sql file. Thanks to

+ 4 - 0
db/Changelog.txt

@@ -26,6 +26,10 @@
 	-----
 
 =========================
+
+05/11
+	* Moved TK_DOWNKICK's stun time from time to time2 [Skotlex]
+	* Added TK_TURNKICK's stun time in skill_cast_db (2secs in time2) [Skotlex]
 05/09
 	* More Aegis X.2 drop updates [Playtester]
 05/08

+ 3 - 1
db/skill_cast_db.txt

@@ -669,7 +669,9 @@
 //-- TK_RUN
 411,6000:5000:4000:3000:2000:1000:0:0:0:0,0,0,1000,150000
 //-- TK_DOWNKICK
-415,0,0,0,3000,0
+415,0,0,0,0,3000
+//-- TK_TURNKICK
+417,0,0,0,0,2000
 //-- TK_SPTIME
 423,0,0,0,1800000,0
 //-- TK_SEVENWIND

+ 5 - 17
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]);

+ 54 - 34
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);
-	}
-
-	//�¤�lŒoŒ±’l
+	
 	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)

+ 14 - 13
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]

+ 8 - 8
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);