Browse Source

- Fixed getmonsterinfo to return "null" when returning the name of a non-existing mob instead of -1.
- Extended the status_percent_damage define to include a bolean to specify whether or not the target can be killed from it.
- Corrected CR_CULTIVATION to fail when the target cell has some BL_CHAR on it already.
- Changed the meaning of 'flag' in status_percent_change, to enable differentiation between damage that can kill the object and damage that cannot.
- Script command percentheal will no longer kill the player if the specified amount is negative (and not -100).


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

skotlex 17 years ago
parent
commit
ced9aada8c
9 changed files with 45 additions and 28 deletions
  1. 6 0
      Changelog-Trunk.txt
  2. 2 2
      doc/script_commands.txt
  3. 1 1
      src/map/battle.c
  4. 1 1
      src/map/clif.c
  5. 4 4
      src/map/pc.c
  6. 4 1
      src/map/script.c
  7. 12 9
      src/map/skill.c
  8. 12 7
      src/map/status.c
  9. 3 3
      src/map/status.h

+ 6 - 0
Changelog-Trunk.txt

@@ -4,6 +4,12 @@ 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.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 
 2008/01/10
 2008/01/10
+	* Fixed getmonsterinfo to return "null" when returning the name of a
+	  non-existing mob instead of -1.
+	* Corrected CR_CULTIVATION to fail when the target cell has some BL_CHAR on
+	  it already.
+	* Script command percentheal will no longer kill the player if the
+	  specified amount is negative (and not -100).
 	* Fixed Abracadabra unable to cast non-targeted skills (bugreport:186)
 	* Fixed Abracadabra unable to cast non-targeted skills (bugreport:186)
 	* Another round of login server cleaning [ultramage]
 	* Another round of login server cleaning [ultramage]
 	- fixed passwordencrypt on SQL not behaving correctly (since r10753)
 	- fixed passwordencrypt on SQL not behaving correctly (since r10753)

+ 2 - 2
doc/script_commands.txt

@@ -2839,8 +2839,8 @@ set @i, petstat(PET_CLASS);
 
 
 This function will look up the monster with the specified ID number in the
 This function will look up the monster with the specified ID number in the
 mob database and return the info set by TYPE argument.
 mob database and return the info set by TYPE argument.
-It will return -1 if there is no such item. Due to specific of MOB DB routines,
-it's better to check monster name. It'd return "Dummy" for a non-existing mob.
+It will return -1 if there is no such monster (or the type value is invalid),
+or "null" if you requested the monster's name.
 
 
 Valid types are listed in const.txt:
 Valid types are listed in const.txt:
 	MOB_NAME	0		MOB_LV	1
 	MOB_NAME	0		MOB_LV	1

+ 1 - 1
src/map/battle.c

@@ -2724,7 +2724,7 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage,
 	}
 	}
 
 
 	if (sd->sp_vanish_rate && rand()%1000 < sd->sp_vanish_rate)
 	if (sd->sp_vanish_rate && rand()%1000 < sd->sp_vanish_rate)
-		status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->sp_vanish_per);
+		status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->sp_vanish_per, false);
 	if (!thp && !tsp) return;
 	if (!thp && !tsp) return;
 
 
 	status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1);
 	status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1);

+ 1 - 1
src/map/clif.c

@@ -10238,7 +10238,7 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd)
 		break;
 		break;
 	}
 	}
 	case BL_MOB:
 	case BL_MOB:
-		status_percent_damage(&sd->bl, target, 100, 0);
+		status_percent_damage(&sd->bl, target, 100, 0, true);
 		if(log_config.gm && lv >= log_config.gm) {
 		if(log_config.gm && lv >= log_config.gm) {
 			char message[NAME_LENGTH+16];
 			char message[NAME_LENGTH+16];
 			sprintf(message, "/kick %s (%d)", status_get_name(target), status_get_class(target));
 			sprintf(message, "/kick %s (%d)", status_get_name(target), status_get_class(target));

+ 4 - 4
src/map/pc.c

@@ -5494,22 +5494,22 @@ int pc_percentheal(struct map_session_data *sd,int hp,int sp)
 	if(hp >= 0 && sp >= 0) //Heal
 	if(hp >= 0 && sp >= 0) //Heal
 		return status_percent_heal(&sd->bl, hp, sp);
 		return status_percent_heal(&sd->bl, hp, sp);
 
 
-	if(hp <= 0 && sp <= 0) //Damage (negative rates indicate % of max rather than current)
-		return status_percent_damage(NULL, &sd->bl, hp, sp);
+	if(hp <= 0 && sp <= 0) //Damage (negative rates indicate % of max rather than current), and only kill target IF the specified amount is 100%
+		return status_percent_damage(NULL, &sd->bl, hp, sp, hp==-100);
 
 
 	//Crossed signs
 	//Crossed signs
 	if(hp) {
 	if(hp) {
 		if(hp > 0)
 		if(hp > 0)
 			status_percent_heal(&sd->bl, hp, 0);
 			status_percent_heal(&sd->bl, hp, 0);
 		else
 		else
-			status_percent_damage(NULL, &sd->bl, hp, 0);
+			status_percent_damage(NULL, &sd->bl, hp, 0, hp==-100);
 	}
 	}
 	
 	
 	if(sp) {
 	if(sp) {
 		if(sp > 0)
 		if(sp > 0)
 			status_percent_heal(&sd->bl, 0, sp);
 			status_percent_heal(&sd->bl, 0, sp);
 		else
 		else
-			status_percent_damage(NULL, &sd->bl, 0, sp);
+			status_percent_damage(NULL, &sd->bl, 0, sp, false);
 	}
 	}
 	return 0;
 	return 0;
 }
 }

+ 4 - 1
src/map/script.c

@@ -12104,7 +12104,10 @@ BUILDIN_FUNC(getmonsterinfo)
 	mob_id	= script_getnum(st,2);
 	mob_id	= script_getnum(st,2);
 	if (!mobdb_checkid(mob_id)) {
 	if (!mobdb_checkid(mob_id)) {
 		ShowError("buildin_getmonsterinfo: Wrong Monster ID: %i", mob_id);
 		ShowError("buildin_getmonsterinfo: Wrong Monster ID: %i", mob_id);
-		script_pushint(st,-1);
+		if ( !script_getnum(st,3) ) //requested a string
+			script_pushconststr(st,"null");
+		else
+			script_pushint(st,-1);
 		return -1;
 		return -1;
 	}
 	}
 	mob = mob_db(mob_id);
 	mob = mob_db(mob_id);

+ 12 - 9
src/map/skill.c

@@ -561,7 +561,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 		break;
 		break;
 
 
 	case HT_SHOCKWAVE:
 	case HT_SHOCKWAVE:
-		status_percent_damage(src, bl, 0, 15*skilllv+5);
+		status_percent_damage(src, bl, 0, 15*skilllv+5, false);
 		break;
 		break;
 
 
 	case HT_SANDMAN:
 	case HT_SANDMAN:
@@ -603,7 +603,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 		break;
 		break;
 
 
 	case PA_PRESSURE:
 	case PA_PRESSURE:
-		status_percent_damage(src, bl, 0, 15+5*skilllv);
+		status_percent_damage(src, bl, 0, 15+5*skilllv, false);
 		break;
 		break;
 
 
 	case RG_RAID:
 	case RG_RAID:
@@ -2710,12 +2710,12 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 			clif_skill_nodamage(src,bl,skillid,skilllv,1);
 			clif_skill_nodamage(src,bl,skillid,skilllv,1);
 			if (skilllv == 5)
 			if (skilllv == 5)
 				skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
 				skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
-			status_percent_damage(src, bl, 0, 100);
+			status_percent_damage(src, bl, 0, 100, false);
 		} else {
 		} else {
 			clif_skill_nodamage(src,src,skillid,skilllv,1);
 			clif_skill_nodamage(src,src,skillid,skilllv,1);
 			if (skilllv == 5)
 			if (skilllv == 5)
 				skill_attack(BF_MAGIC,src,src,src,skillid,skilllv,tick,flag);
 				skill_attack(BF_MAGIC,src,src,src,skillid,skilllv,tick,flag);
-			status_percent_damage(src, src, 0, 100);
+			status_percent_damage(src, src, 0, 100, false);
 		}		
 		}		
 		if (sd) skill_blockpc_start (sd, skillid, (skilllv < 5 ? 10000: 15000));
 		if (sd) skill_blockpc_start (sd, skillid, (skilllv < 5 ? 10000: 15000));
 		break;
 		break;
@@ -4261,7 +4261,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 				if(sp < 1) sp = 1;
 				if(sp < 1) sp = 1;
 				status_heal(bl,0,sp,2);
 				status_heal(bl,0,sp,2);
 				clif_skill_nodamage(bl,bl,SA_MAGICROD,tsc->data[SC_MAGICROD]->val1,1);
 				clif_skill_nodamage(bl,bl,SA_MAGICROD,tsc->data[SC_MAGICROD]->val1,1);
-				status_percent_damage(bl, src, 0, -20); //20% max SP damage.
+				status_percent_damage(bl, src, 0, -20, false); //20% max SP damage.
 			} else {
 			} else {
 				struct unit_data *ud = unit_bl2ud(bl);
 				struct unit_data *ud = unit_bl2ud(bl);
 				int bl_skillid=0,bl_skilllv=0,hp = 0;
 				int bl_skillid=0,bl_skilllv=0,hp = 0;
@@ -4787,7 +4787,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 				switch (eff)
 				switch (eff)
 				{
 				{
 				case 0:	// heals SP to 0
 				case 0:	// heals SP to 0
-					status_percent_damage(src, bl, 0, 100);
+					status_percent_damage(src, bl, 0, 100, false);
 					break;
 					break;
 				case 1:	// matk halved
 				case 1:	// matk halved
 					sc_start(bl,SC_INCMATKRATE,100,-50,skill_get_time2(skillid,skilllv));
 					sc_start(bl,SC_INCMATKRATE,100,-50,skill_get_time2(skillid,skilllv));
@@ -5815,14 +5815,17 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 			int i = skilllv - 1;
 			int i = skilllv - 1;
 			int j = pc_search_inventory(sd,skill_db[skillid].itemid[i]);
 			int j = pc_search_inventory(sd,skill_db[skillid].itemid[i]);
 			if(j < 0 || skill_db[skillid].itemid[i] <= 0 || sd->inventory_data[j] == NULL ||
 			if(j < 0 || skill_db[skillid].itemid[i] <= 0 || sd->inventory_data[j] == NULL ||
-				sd->status.inventory[j].amount < skill_db[skillid].amount[i]) {
+				sd->status.inventory[j].amount < skill_db[skillid].amount[i] ||
+				map_count_oncell(src->m,x,y,BL_CHAR) > 0
+			) {
 				clif_skill_fail(sd,skillid,0,0);
 				clif_skill_fail(sd,skillid,0,0);
 				return 1;
 				return 1;
 			}
 			}
+
 			pc_delitem(sd,j,skill_db[skillid].amount[i],0);
 			pc_delitem(sd,j,skill_db[skillid].amount[i],0);
 			clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
 			clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
 			if (rand()%100 < 50)
 			if (rand()%100 < 50)
-				mob_once_spawn(sd, sd->bl.m, x, y, "--ja--",(skilllv < 2 ? 1084+rand()%2 : 1078+rand()%6), 1, "");
+				mob_once_spawn(sd, src->m, x, y, "--ja--",(skilllv < 2 ? 1084+rand()%2 : 1078+rand()%6), 1, "");
 			else
 			else
 				clif_skill_fail(sd,skillid,0,0);
 				clif_skill_fail(sd,skillid,0,0);
 		}
 		}
@@ -10263,7 +10266,7 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in
 	} else {
 	} else {
 		switch (skill_id) {
 		switch (skill_id) {
 			case ASC_CDP: //25% Damage yourself, and display same effect as failed potion.
 			case ASC_CDP: //25% Damage yourself, and display same effect as failed potion.
-				status_percent_damage(NULL, &sd->bl, -25, 0);
+				status_percent_damage(NULL, &sd->bl, -25, 0, true);
 			case AM_PHARMACY:
 			case AM_PHARMACY:
 			case AM_TWILIGHT1:
 			case AM_TWILIGHT1:
 			case AM_TWILIGHT2:
 			case AM_TWILIGHT2:

+ 12 - 7
src/map/status.c

@@ -851,7 +851,8 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag)
 //no exp/drops will be awarded if there is no src (or src is target)
 //no exp/drops will be awarded if there is no src (or src is target)
 //If rates are > 0, percent is of current HP/SP
 //If rates are > 0, percent is of current HP/SP
 //If rates are < 0, percent is of max HP/SP
 //If rates are < 0, percent is of max HP/SP
-//If flag, this is heal, otherwise it is damage.
+//If !flag, this is heal, otherwise it is damage.
+//Furthermore, if flag==2, then the target must not die from the substraction.
 int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag)
 int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag)
 {
 {
 	struct status_data *status;
 	struct status_data *status;
@@ -878,6 +879,9 @@ int status_percent_change(struct block_list *src,struct block_list *target,signe
 	if (hp_rate && !hp)
 	if (hp_rate && !hp)
 		hp = 1;
 		hp = 1;
 
 
+	if (flag == 2 && hp >= status->hp)
+		hp = status->hp-1; //Must not kill target.
+
 	//Should be safe to not do overflow protection here, noone should have
 	//Should be safe to not do overflow protection here, noone should have
 	//millions upon millions of SP
 	//millions upon millions of SP
 	if (sp_rate > 99)
 	if (sp_rate > 99)
@@ -896,19 +900,20 @@ int status_percent_change(struct block_list *src,struct block_list *target,signe
 	if (hp > INT_MAX) {
 	if (hp > INT_MAX) {
 	  	hp -= INT_MAX;
 	  	hp -= INT_MAX;
 		if (flag)
 		if (flag)
-		  	status_heal(target, INT_MAX, 0, 0);
-		else
 			status_damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1));
 			status_damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1));
+		else
+		  	status_heal(target, INT_MAX, 0, 0);
 	}
 	}
   	if (sp > INT_MAX) {
   	if (sp > INT_MAX) {
 		sp -= INT_MAX;
 		sp -= INT_MAX;
 		if (flag)
 		if (flag)
-		  	status_heal(target, 0, INT_MAX, 0);
-		else
 			status_damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1));
 			status_damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1));
+		else
+		  	status_heal(target, 0, INT_MAX, 0);
 	}	
 	}	
-	if (flag) return status_heal(target, hp, sp, 0);
-	return status_damage(src, target, hp, sp, 0, (!src||src==target?5:1));
+	if (flag)
+		return status_damage(src, target, hp, sp, 0, (!src||src==target?5:1));
+	return status_heal(target, hp, sp, 0);
 }
 }
 
 
 int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp)
 int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp)

+ 3 - 3
src/map/status.h

@@ -588,10 +588,10 @@ int status_damage(struct block_list *src,struct block_list *target,int hp,int sp
 int status_charge(struct block_list* bl, int hp, int sp);
 int status_charge(struct block_list* bl, int hp, int sp);
 int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag);
 int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag);
 //Easier handling of status_percent_change
 //Easier handling of status_percent_change
-#define status_percent_heal(bl, hp_rate, sp_rate) status_percent_change(NULL, bl, -(hp_rate), -(sp_rate), 1)
-#define status_percent_damage(src, target, hp_rate, sp_rate) status_percent_change(src, target, hp_rate, sp_rate, 0)
+#define status_percent_heal(bl, hp_rate, sp_rate) status_percent_change(NULL, bl, -(hp_rate), -(sp_rate), 0)
+#define status_percent_damage(src, target, hp_rate, sp_rate, kill) status_percent_change(src, target, hp_rate, sp_rate, (kill)?1:2)
 //Instant kill with no drops/exp/etc
 //Instant kill with no drops/exp/etc
-#define status_kill(bl) status_percent_damage(NULL, bl, 100, 0)
+#define status_kill(bl) status_percent_damage(NULL, bl, 100, 0, true)
 //Used to set the hp/sp of an object to an absolute value (can't kill)
 //Used to set the hp/sp of an object to an absolute value (can't kill)
 int status_set_hp(struct block_list *bl, unsigned int hp, int flag);
 int status_set_hp(struct block_list *bl, unsigned int hp, int flag);
 int status_set_sp(struct block_list *bl, unsigned int sp, int flag);
 int status_set_sp(struct block_list *bl, unsigned int sp, int flag);