Sfoglia il codice sorgente

- Added mob skill conditions myhpinrate and friendhpinrate for using HP ranges instead of a fixed "less than" condition.
- Added mob_ai condition &16, enables skills that are normally used on 'friends' to also pick up caster as target.
- Fixed npc_shopid not being reset to 0 when buying/selling. FIXME: The client sends a packet when you cancel? It is required so that npc_shopid will be cleared and prevent the player from being stuck.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@5380 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex 19 anni fa
parent
commit
ada437dcaf
6 ha cambiato i file con 42 aggiunte e 22 eliminazioni
  1. 1 0
      conf-tmpl/battle/monster.conf
  2. 5 1
      db/mob_skill_db.txt
  3. 4 2
      src/map/clif.c
  4. 26 17
      src/map/mob.c
  5. 2 0
      src/map/mob.h
  6. 4 2
      src/map/status.c

+ 1 - 0
conf-tmpl/battle/monster.conf

@@ -59,6 +59,7 @@ monster_max_aspd: 199
 // 8: If set, when a mob loses track of their target, they stop walking inmediately. Otherwise, they continue
 //    to their last target tile. When set mobs also scatter as soon as they lose their target. Use this mode to 
 //    make it much harder to mob-train by hiding and collecting them on a single spot (ie: GrimTooth training)
+//16: If set, mob skills defined for friends will also trigger on themselves.
 monster_ai: 0
 
 // Allow monsters to be aggresive and attack first? (Note 1)

+ 5 - 1
db/mob_skill_db.txt

@@ -28,9 +28,13 @@
 //	always			unconditional
 //	onspawn			when the mob spawns/respawns.
 //	myhpltmaxrate		when the mob's hp drops to a certain %
+//	myhpinrate		when the mob's hp is in a certain % range ('a condition value'
+//                is the lower cap, while 'a value 1' is the upper cap).
 //	mystatuson		If the mob has any abnormalities in status (condition value),
 //	mystatusoff		If the mob has ended any abnormalities in status (condition value),
-//	friendhpltmaxrate	when the mobs' friend's hp drops to a certain %
+//	friendhpltmaxrate	when the mob's friend's hp drops to a certain %
+//	friendhpinrate		when the mob's friend's hp is in a certain % range (range
+//                   defined the same way as in myhpinrate)
 //	friendstatuson		If the friend has any abnormalities in status (condition value),
 //	friendstatusoff		If the friend has ended any abnormalities in status (condition value),
 //	attackpcgt		Attack PC becomes more than the  number of specification

+ 4 - 2
src/map/clif.c

@@ -9805,11 +9805,12 @@ void clif_parse_NpcBuyListSend(int fd,struct map_session_data *sd)
 	n = (RFIFOW(fd,2)-4) /4;
 	item_list = (unsigned short*)RFIFOP(fd,4);
 
-	if (sd->trade_partner != 0)
+	if (sd->trade_partner || !sd->npc_shopid)
 		fail = 1;
 	else
 		fail = npc_buylist(sd,n,item_list);
 
+	sd->npc_shopid = 0; //Clear shop data.
 	WFIFOHEAD(fd,packet_len_table[0xca]);
 	WFIFOW(fd,0)=0xca;
 	WFIFOB(fd,2)=fail;
@@ -9829,10 +9830,11 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd)
 	n = (RFIFOW(fd,2)-4) /4;
 	item_list = (unsigned short*)RFIFOP(fd,4);
 
-	if (sd->trade_partner != 0)
+	if (sd->trade_partner || !sd->npc_shopid)
 		fail = 1;
 	else
 		fail = npc_selllist(sd,n,item_list);
+	sd->npc_shopid = 0; //Clear shop data.
 
 	WFIFOHEAD(fd,packet_len_table[0xcb]);
 	WFIFOW(fd,0)=0xcb;

+ 26 - 17
src/map/mob.c

@@ -3585,19 +3585,18 @@ int mobskill_use_pos( struct mob_data *md,
  * Friendly Mob whose HP is decreasing by a nearby MOB is looked for.
  *------------------------------------------
  */
-int mob_getfriendhpltmaxrate_sub(struct block_list *bl,va_list ap)
+int mob_getfriendhprate_sub(struct block_list *bl,va_list ap)
 {
-	int rate;
+	int min_rate, max_rate,rate;
 	struct block_list **fr;
 	struct mob_data *md;
 
-	nullpo_retr(0, bl);
-	nullpo_retr(0, ap);
-	nullpo_retr(0, md=va_arg(ap,struct mob_data *));
-	rate=va_arg(ap,int);
+	md = va_arg(ap,struct mob_data *);
+	min_rate=va_arg(ap,int);
+	max_rate=va_arg(ap,int);
 	fr=va_arg(ap,struct block_list **);
 
-	if( md->bl.id == bl->id )
+	if( md->bl.id == bl->id && !(battle_config.mob_ai&16))
 		return 0;
 
 	if ((*fr) != NULL) //A friend was already found.
@@ -3606,11 +3605,13 @@ int mob_getfriendhpltmaxrate_sub(struct block_list *bl,va_list ap)
 	if (battle_check_target(&md->bl,bl,BCT_ENEMY)>0)
 		return 0;
 	
-	if (status_get_hp(bl) < status_get_max_hp(bl) * rate / 100)
+	rate = 100*status_get_hp(bl)/status_get_max_hp(bl);
+	
+	if (rate >= min_rate && rate <= max_rate)
 		(*fr) = bl;
-	return 0;
+	return 1;
 }
-struct block_list *mob_getfriendhpltmaxrate(struct mob_data *md,int rate)
+static struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,int max_rate)
 {
 	struct block_list *fr=NULL;
 	int type = BL_MOB;
@@ -3620,7 +3621,7 @@ struct block_list *mob_getfriendhpltmaxrate(struct mob_data *md,int rate)
 	if (md->special_state.ai) //Summoned creatures. [Skotlex]
 		type = BL_PC;
 	
-	map_foreachinrange(mob_getfriendhpltmaxrate_sub, &md->bl, 8, type,md,rate,&fr);
+	map_foreachinrange(mob_getfriendhprate_sub, &md->bl, 8, type,md,min_rate,max_rate,&fr);
 	return fr;
 }
 /*==========================================
@@ -3652,8 +3653,9 @@ int mob_getfriendstatus_sub(struct block_list *bl,va_list ap)
 	nullpo_retr(0, md=(struct mob_data *)bl);
 	nullpo_retr(0, mmd=va_arg(ap,struct mob_data *));
 
-	if( mmd->bl.id == bl->id )
+	if( mmd->bl.id == bl->id && !(battle_config.mob_ai&16) )
 		return 0;
+
 	if (battle_check_target(&mmd->bl,bl,BCT_ENEMY)>0)
 		return 0;
 	cond1=va_arg(ap,int);
@@ -3724,10 +3726,13 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
 				case MSC_ALWAYS:
 					flag = 1; break;
 				case MSC_MYHPLTMAXRATE:		// HP< maxhp%
-					{
-						int max_hp = status_get_max_hp(&md->bl);
-						flag = (md->hp < max_hp * c2 / 100); break;
-					}
+					flag = 100*md->hp/status_get_max_hp(&md->bl);
+					flag = (flag <= c2);
+				  	break;
+				case MSC_MYHPINRATE:
+					flag = 100*md->hp/status_get_max_hp(&md->bl);
+					flag = (flag >= c2 && flag <= ms[i].val[0]);
+					break;
 				case MSC_MYSTATUSON:		// status[num] on
 				case MSC_MYSTATUSOFF:		// status[num] off
 					if (!md->sc.count) {
@@ -3742,7 +3747,9 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
 					}
 					flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF); break;
 				case MSC_FRIENDHPLTMAXRATE:	// friend HP < maxhp%
-					flag = ((fbl = mob_getfriendhpltmaxrate(md, ms[i].cond2)) != NULL); break;
+					flag = ((fbl = mob_getfriendhprate(md, 0, ms[i].cond2)) != NULL); break;
+				case MSC_FRIENDHPINRATE	:
+					flag = ((fbl = mob_getfriendhprate(md, ms[i].cond2, ms[i].val[0])) != NULL); break;
 				case MSC_FRIENDSTATUSON:	// friend status[num] on
 				case MSC_FRIENDSTATUSOFF:	// friend status[num] off
 					flag = ((fmd = mob_getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); break;					
@@ -4545,7 +4552,9 @@ static int mob_readskilldb(void)
 	} cond1[] = {
 		{	"always",			MSC_ALWAYS				},
 		{	"myhpltmaxrate",	MSC_MYHPLTMAXRATE		},
+		{  "myhpinrate",		MSC_MYHPINRATE 		},
 		{	"friendhpltmaxrate",MSC_FRIENDHPLTMAXRATE	},
+		{	"friendhpinrate",	MSC_FRIENDHPINRATE	},
 		{	"mystatuson",		MSC_MYSTATUSON			},
 		{	"mystatusoff",		MSC_MYSTATUSOFF			},
 		{	"friendstatuson",	MSC_FRIENDSTATUSON		},

+ 2 - 0
src/map/mob.h

@@ -67,7 +67,9 @@ enum {
 
 	MSC_ALWAYS			=	0x0000,
 	MSC_MYHPLTMAXRATE,
+	MSC_MYHPINRATE,
 	MSC_FRIENDHPLTMAXRATE,
+	MSC_FRIENDHPINRATE,
 	MSC_MYSTATUSON,
 	MSC_MYSTATUSOFF,
 	MSC_FRIENDSTATUSON,

+ 4 - 2
src/map/status.c

@@ -1364,7 +1364,8 @@ int status_calc_pc(struct map_session_data* sd,int first)
 
 	if(sd->status.max_hp > battle_config.max_hp)
 		sd->status.max_hp = battle_config.max_hp;
-	if(sd->status.max_hp <= 0) sd->status.max_hp = 1;
+	else if(sd->status.max_hp <= 0)
+		sd->status.max_hp = 1;
 	if(sd->status.hp>sd->status.max_hp)
 		sd->status.hp=sd->status.max_hp;
 
@@ -1423,9 +1424,10 @@ int status_calc_pc(struct map_session_data* sd,int first)
 	
 	if(sd->status.max_sp > battle_config.max_sp)
 		sd->status.max_sp = battle_config.max_sp;
+	else if(sd->status.max_sp <= 0)
+	  	sd->status.max_sp = 1;
 	if(sd->status.sp>sd->status.max_sp)
 		sd->status.sp=sd->status.max_sp;
-	if(sd->status.max_sp <= 0) sd->status.max_sp = 1;
 
 	if(sd->sc.data[SC_DANCING].timer==-1){
 		// Basic natural SP regeneration value