From 7a05377b6e5ccbefd3f3cc87e55f6962c2906f07 Mon Sep 17 00:00:00 2001
From: cydh <cydh@54d463be-8e91-2dee-dedb-b68131a5f0ec>
Date: Mon, 24 Jun 2013 07:23:36 +0000
Subject: [PATCH] - bugreport:7758 -- Fixed logout delay after attacking --
 Fixed clear dmglog on MVP when player is logging out - bugreport:7684 --
 Fixed vender_id and buyer_id - Fixed typo on conf/channels.conf

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@17384 54d463be-8e91-2dee-dedb-b68131a5f0ec
---
 conf/channels.conf    |  4 +--
 src/map/buyingstore.c |  2 +-
 src/map/clif.c        |  2 ++
 src/map/map.c         |  1 +
 src/map/mob.c         |  8 ++++++
 src/map/pc.c          | 58 +++++++++++++++++++++++++++++++++++++++++++
 src/map/pc.h          |  8 ++++++
 src/map/unit.c        |  9 +++++++
 src/map/vending.c     |  2 +-
 9 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/conf/channels.conf b/conf/channels.conf
index a6e33cbd2c..c0a76fd506 100644
--- a/conf/channels.conf
+++ b/conf/channels.conf
@@ -25,8 +25,8 @@ chsys: (
 		/* Add as many colors as you'd like. */
 	}
 
-	/* Allow users to create their own (private) channels through @channels command? */
-	/* (must also allow players to use @channels in groups.conf) */
+	/* Allow users to create their own (private) channels through @channel command? */
+	/* (must also allow players to use @channel in groups.conf) */
 	allow_user_channel_creation: true
 
 	/* "map_local_channel" is an instanced channel unique to each map. */
diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c
index 8a472d1b55..a53aee3e25 100644
--- a/src/map/buyingstore.c
+++ b/src/map/buyingstore.c
@@ -41,7 +41,7 @@ static const short buyingstore_blankslots[MAX_SLOTS] = { 0 };  // used when chec
 /// Returns unique buying store id
 static unsigned int buyingstore_getuid(void)
 {
-	return buyingstore_nextid++;
+	return ++buyingstore_nextid;
 }
 
 
diff --git a/src/map/clif.c b/src/map/clif.c
index 4df9c358be..561fca4f6f 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9611,6 +9611,7 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd)
 		(!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
 	{
 		set_eof(fd);
+		pc_damage_log_clear(sd,0);
 		clif_disconnect_ack(sd, 0);
 	} else {
 		clif_disconnect_ack(sd, 1);
@@ -9980,6 +9981,7 @@ void clif_parse_Restart(int fd, struct map_session_data *sd)
 		if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] &&
 			(!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
 		{	//Send to char-server for character selection.
+			pc_damage_log_clear(sd,0);
 			chrif_charselectreq(sd, session[fd]->client_addr);
 		} else {
 			clif_disconnect_ack(sd, 1);
diff --git a/src/map/map.c b/src/map/map.c
index 53fa002d9a..5d42619b0c 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -1724,6 +1724,7 @@ int map_quit(struct map_session_data *sd) {
 		}
 	}
 
+	pc_damage_log_clear(sd,0);
 	party_booking_delete(sd); // Party Booking [Spiria]
 	pc_makesavestatus(sd);
 	pc_clean_skilltree(sd);
diff --git a/src/map/mob.c b/src/map/mob.c
index bfc5c122a7..7a3a276c8e 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -2019,6 +2019,9 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
 			if(md->dmglog[i].id==0) {	//Store data in first empty slot.
 				md->dmglog[i].id  = char_id;
 				md->dmglog[i].flag= flag;
+
+				if(md->db->mexp)
+					pc_damage_log_add(map_charid2sd(char_id),md->bl.id);
 				break;
 			}
 			if(md->dmglog[i].dmg<mindmg && i)
@@ -2033,6 +2036,9 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
 			md->dmglog[minpos].id  = char_id;
 			md->dmglog[minpos].flag= flag;
 			md->dmglog[minpos].dmg = damage;
+
+			if(md->db->mexp)
+				pc_damage_log_add(map_charid2sd(char_id),md->bl.id);
 		}
 	}
 	return;
@@ -2160,6 +2166,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 			case MDLF_HOMUN:  dmgbltypes|= BL_HOM; break;
 			case MDLF_PET:    dmgbltypes|= BL_PET; break;
 		}
+		if( md->db->mexp )
+			pc_damage_log_clear(tsd,md->bl.id);
 	}
 
 	// determines, if the monster was killed by homunculus' damage only
diff --git a/src/map/pc.c b/src/map/pc.c
index e864ff7c8f..d7982120fd 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -9962,6 +9962,64 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) {
 	return;
 }
 
+void pc_clear_log_damage_sub(int char_id, struct mob_data *md)
+{
+	int i;
+	ARR_FIND(0,DAMAGELOG_SIZE,i,md->dmglog[i].id == char_id);
+	if( i < DAMAGELOG_SIZE )
+	{
+		md->dmglog[i].id=0;
+		md->dmglog[i].dmg=0;
+		md->dmglog[i].flag=0;
+	}
+}
+
+void pc_damage_log_add(struct map_session_data *sd, int id)
+{
+	int i = 0;
+
+	if( !sd )
+		return;
+
+	for(i = 0; i < DAMAGELOG_SIZE_PC && sd->dmglog[i].id != id; i++)
+		if( !sd->dmglog[i].id )
+		{
+			sd->dmglog[i].id = id;
+			break;
+		}
+	return;
+}
+
+void pc_damage_log_clear(struct map_session_data *sd, int id)
+{
+	int i;
+	struct mob_data *md = NULL;
+	if( !sd )
+		return;
+
+	if( !id )
+	{
+		for(i = 0; i < DAMAGELOG_SIZE_PC; i++)	// track every id
+		{
+			if( !sd->dmglog[i].id )	//skip the empty value
+				continue;
+
+			if( (md = map_id2md(sd->dmglog[i].id)) )
+				pc_clear_log_damage_sub(sd->status.char_id,md);
+		}
+		memset(sd->dmglog,0,sizeof(sd->dmglog));	// clear all
+	}
+	else
+	{
+		if( (md = map_id2md(id)) )
+			pc_clear_log_damage_sub(sd->status.char_id,md);
+
+		ARR_FIND(0,DAMAGELOG_SIZE_PC,i,sd->dmglog[i].id == id);	// find the id position
+		if( i < DAMAGELOG_SIZE_PC )
+			sd->dmglog[i].id = 0;
+	}
+}
+
 /*==========================================
  * pc Init/Terminate
  *------------------------------------------*/
diff --git a/src/map/pc.h b/src/map/pc.h
index 7aabcda2cd..744a6f46b9 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -23,6 +23,7 @@
 #define MAX_PC_BONUS 10
 #define MAX_PC_SKILL_REQUIRE 5
 #define MAX_PC_FEELHATE 3
+#define DAMAGELOG_SIZE_PC 100	// Any idea for this value?
 
 //Equip indexes constants. (eg: sd->equip_index[EQI_AMMO] returns the index
 //where the arrows are equipped)
@@ -515,6 +516,10 @@ struct map_session_data {
 	const char* delunit_prevfile;
 	int delunit_prevline;
 
+	struct {
+		int id;
+	} dmglog[DAMAGELOG_SIZE_PC];
+
 };
 
 //Update this max as necessary. 55 is the value needed for Super Baby currently
@@ -965,6 +970,9 @@ int pc_del_talisman(struct map_session_data *sd,int count,int type);
 
 void pc_baselevelchanged(struct map_session_data *sd);
 
+void pc_damage_log_add(struct map_session_data *sd, int id);
+void pc_damage_log_clear(struct map_session_data *sd, int id);
+
 #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
 int pc_level_penalty_mod(struct map_session_data *sd, int mob_level, uint32 mob_race, uint32 mob_mode, int type);
 #endif
diff --git a/src/map/unit.c b/src/map/unit.c
index aa0482ace1..9e1dd8f81e 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1421,6 +1421,9 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
 	} else
 		skill_castend_id(ud->skilltimer,tick,src->id,0);
 
+	if( sd )
+		sd->canlog_tick = gettick();
+
 	return 1;
 }
 
@@ -1554,6 +1557,9 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
 		ud->skilltimer = INVALID_TIMER;
 		skill_castend_pos(ud->skilltimer,tick,src->id,0);
 	}
+
+	if( sd )
+		sd->canlog_tick = gettick();
 	return 1;
 }
 
@@ -1920,6 +1926,9 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
 	if(ud->state.attack_continue)
 		ud->attacktimer = add_timer(ud->attackabletime,unit_attack_timer,src->id,0);
 
+	if( sd )
+		sd->canlog_tick = gettick();
+
 	return 1;
 }
 
diff --git a/src/map/vending.c b/src/map/vending.c
index a7931d6cc0..5c346e5e9e 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -29,7 +29,7 @@ DBMap * vending_getdb(){
 /// Returns an unique vending shop id.
 static int vending_getuid(void)
 {
-	return vending_nextid++;
+	return ++vending_nextid;
 }
 
 /*==========================================