瀏覽代碼

- Moved the duel functions to pc.c since they are so totally out of place in atcommand.c
- Fixed Spider Web not ending when hit by a fireelemental attack.
- Cast-time reductions from status changes will not be executed until right before casting, to prevent status changes from ending when attempting to cast and the attempt fails (invalid cells, not enough sp, wrong target, etc, etc)
- Added check to prevent Wand of Hermod from seeking for a partner to encore, since the partner is supposed to be the warp.
- Moved the duel auto-reject on logout from map_quit to unit_free
- Corrected the mob spawn reading code so that the event-name can be up to 50 characters long (which is the actual event length) and so that it can read spaces within them, it will also strip the leading/trailing quotes if you use them so that the event is actually found on mob-death (so you can do stuff like "My NPC::OnDead" as a valid event).
- Moved the homunc inherit speed from the master from status_calc_pc to LoadEndAck, since the hom's speed matches that of the master each time the master changes maps.


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

skotlex 18 年之前
父節點
當前提交
405f4633ec
共有 14 個文件被更改,包括 247 次插入216 次删除
  1. 16 0
      Changelog-Trunk.txt
  2. 0 171
      src/map/atcommand.c
  3. 0 3
      src/map/atcommand.h
  4. 5 1
      src/map/battle.c
  5. 4 2
      src/map/clif.c
  6. 0 8
      src/map/map.c
  7. 22 14
      src/map/mob.c
  8. 1 1
      src/map/npc.c
  9. 171 0
      src/map/pc.c
  10. 9 0
      src/map/pc.h
  11. 2 7
      src/map/skill.c
  12. 1 0
      src/map/skill.h
  13. 0 5
      src/map/status.c
  14. 16 4
      src/map/unit.c

+ 16 - 0
Changelog-Trunk.txt

@@ -3,6 +3,22 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
+2006/11/08
+	* Fixed Spider Web not ending when hit by a fireelemental attack. [Skotlex]
+	* Cast-time reductions from status changes will not be executed until right
+	  before casting, to prevent status changes from ending when attempting to
+	  cast and the attempt fails (invalid cells, not enough sp, wrong target,
+	  etc, etc) [Skotlex]
+	* Added check to prevent Wand of Hermod from seeking for a partner to
+	  encore, since the partner is supposed to be the warp. [Skotlex]
+	* Corrected the mob spawn reading code so that the event-name can be up to
+	  50 characters long (which is the actual event length) and so that it can
+	  read spaces within them, it will also strip the leading/trailing quotes if
+	  you use them so that the event is actually found on mob-death (so you can
+	  do stuff like "My NPC::OnDead" as a valid event). [Skotlex]
+	* Moved the homunc inherit speed from the master from status_calc_pc to
+	  LoadEndAck, since the hom's speed matches that of the master each time the
+	  master changes maps. [Skotlex]
 2006/11/07
 	* Applied FlavioJs's patch which enables colored console output for Windows
 	  systems. It also includes a config setting called

+ 0 - 171
src/map/atcommand.c

@@ -1003,177 +1003,6 @@ int atcommand_config_read(const char *cfgName) {
 	return 0;
 }
 
-/*==========================================
- * Duel organizing functions [LuzZza]
- *------------------------------------------
- */
-void duel_savetime(struct map_session_data* sd) {
-
-	time_t timer;
-	struct tm *t;
-	
-	time(&timer);
-	t = localtime(&timer);
-	
-	pc_setglobalreg(sd, "PC_LAST_DUEL_TIME",
-		t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min);	
-	return;
-}
-
-int duel_checktime(struct map_session_data* sd) {
-
-	int diff;
-	time_t timer;
-	struct tm *t;
-	
-	time(&timer);
-    t = localtime(&timer);
-	
-	diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min -
-		pc_readglobalreg(sd, "PC_LAST_DUEL_TIME");
-	
-	return !(diff >= 0 && diff < battle_config.duel_time_interval);
-}
-static int duel_showinfo_sub(struct map_session_data* sd,va_list va) {
-	struct map_session_data *ssd = va_arg(va, struct map_session_data*);
-	int *p = va_arg(va, int*);
-	char output[256];
-
-	if (sd->duel_group != ssd->duel_group) return 0;
-	
-	sprintf(output, "      %d. %s", ++(*p), (unsigned char *)sd->status.name);
-	clif_disp_onlyself(ssd, output, strlen(output));
-	return 1;
-}
-
-int duel_showinfo(
-	const unsigned int did, struct map_session_data* sd)
-{
-	int p=0;
-	char output[256];
-
-	if(duel_list[did].max_players_limit > 0)
-		sprintf(output, msg_txt(370), //" -- Duels: %d/%d, Members: %d/%d, Max players: %d --"
-			did, duel_count,
-			duel_list[did].members_count,
-			duel_list[did].members_count + duel_list[did].invites_count,
-			duel_list[did].max_players_limit);
-	else
-		sprintf(output, msg_txt(371), //" -- Duels: %d/%d, Members: %d/%d --"
-			did, duel_count,
-			duel_list[did].members_count,
-			duel_list[did].members_count + duel_list[did].invites_count);
-
-	clif_disp_onlyself(sd, output, strlen(output));
-   clif_foreachclient(duel_showinfo_sub, sd, &p);
-	return 0;
-}
-
-int duel_create(
-	struct map_session_data* sd, const unsigned int maxpl)
-{
-	int i=1;
-	char output[256];
-	
-	while(duel_list[i].members_count > 0 && i < MAX_DUEL) i++;
-	if(i == MAX_DUEL) return 0;
-	
-	duel_count++;
-	sd->duel_group = i;
-	duel_list[i].members_count++;
-	duel_list[i].invites_count = 0;
-	duel_list[i].max_players_limit = maxpl;
-	
-	strcpy(output, msg_txt(372)); // " -- Duel has been created (@invite/@leave) --"
-	clif_disp_onlyself(sd, output, strlen(output));
-	
-	clif_set0199(sd->fd, 1);
-	//clif_misceffect2(&sd->bl, 159);
-	return i;
-}
-
-int duel_invite(
-	const unsigned int did, struct map_session_data* sd,
-	struct map_session_data* target_sd)
-{
-	char output[256];
-
-	sprintf(output, msg_txt(373), // " -- Player %s invites %s to duel --"
-		(unsigned char *)sd->status.name, (unsigned char *)target_sd->status.name);
-
-	clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
-
-	target_sd->duel_invite = did;
-	duel_list[did].invites_count++;
-	
-	// "Blue -- Player %s invites you to PVP duel (@accept/@reject) --"
-	sprintf(output, msg_txt(374), (unsigned char *)sd->status.name);
-	clif_GMmessage((struct block_list *)target_sd, output, strlen(output)+1, 3);
-	return 0;
-}
-
-static int duel_leave_sub(struct map_session_data* sd,va_list va) {
-	int did = va_arg(va, int);
-	if (sd->duel_invite == did)
-		sd->duel_invite = 0;
-	return 0;
-}
-
-int duel_leave(
-	const unsigned int did, struct map_session_data* sd)
-{
-	char output[256];
-	
-	// " <- Player %s has left duel --"
-	sprintf(output, msg_txt(375), (unsigned char *)sd->status.name);
-	clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
-	
-	duel_list[did].members_count--;
-	
-	if(duel_list[did].members_count == 0) {
-		clif_foreachclient(duel_leave_sub, did); 
-		duel_count--;
-	}
-	
-	sd->duel_group = 0;
-	duel_savetime(sd);
-	clif_set0199(sd->fd, 0);
-	return 0;
-}
-
-int duel_accept(
-	const unsigned int did, struct map_session_data* sd)
-{
-	char output[256];
-	
-	duel_list[did].members_count++;
-	sd->duel_group = sd->duel_invite;
-	duel_list[did].invites_count--;
-	sd->duel_invite = 0;
-	
-	// " -> Player %s has accepted duel --"
-	sprintf(output, msg_txt(376), (unsigned char *)sd->status.name);
-	clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
-
-	clif_set0199(sd->fd, 1);
-	//clif_misceffect2(&sd->bl, 159);
-	return 0;
-}
-
-int duel_reject(
-	const unsigned int did, struct map_session_data* sd)
-{
-	char output[256];
-	
-	// " -- Player %s has rejected duel --"
-	sprintf(output, msg_txt(377), (unsigned char *)sd->status.name);
-	clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
-	
-	duel_list[did].invites_count--;
-	sd->duel_invite = 0;
-	return 0;
-}
-
 /*==========================================
 // @ command processing functions
  *------------------------------------------

+ 0 - 3
src/map/atcommand.h

@@ -318,9 +318,6 @@ int atcommand_jumpto(const int fd, struct map_session_data* sd, const char* comm
 int atcommand_recall(const int fd, struct map_session_data* sd, const char* command, const char* message); // [Yor]
 int atcommand_monster(const int fd, struct map_session_data* sd, const char* command, const char* message);
 
-int duel_leave(const unsigned int did, struct map_session_data* sd); // [LuzZza]
-int duel_reject(const unsigned int did, struct map_session_data* sd); // [LuzZza]
-
 int atcommand_config_read(const char *cfgName);
 int msg_config_read(const char *cfgName);
 void do_final_msg(void);

+ 5 - 1
src/map/battle.c

@@ -212,8 +212,12 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
 			if (tsc->data[SC_ARMOR_ELEMENT].val3 == atk_elem)
 				ratio -= tsc->data[SC_ARMOR_ELEMENT].val4;
 		}
-		if(tsc->data[SC_SPIDERWEB].timer!=-1 && atk_elem == ELE_FIRE) // [Celest]
+		if(tsc->data[SC_SPIDERWEB].timer!=-1 && atk_elem == ELE_FIRE)
+		{	// [Celest]
 			damage <<= 1;
+			status_change_end(target, SC_SPIDERWEB, -1);
+		}
+
 	}
 	return damage*ratio/100;
 }

+ 4 - 2
src/map/clif.c

@@ -320,7 +320,7 @@ int clif_send_sub(struct block_list *bl, va_list ap)
 				//Check if hidden, better to modify the char's buffer than the
 				//given buffer to prevent intravision affecting the packet as 
 				//it's being received by everyone. [Skotlex]
-				/* New implemenation... not quite correct yet as the client no longer
+				/* New implementation... not quite correct yet as the client no longer
 				 * displays correctly the SI_INTRAVISION effect.
 				if ((sd->special_state.intravision || sd->sc.data[SC_INTRAVISION].timer != -1 )
 						&& bl != src_bl && WFIFOW(sd->fd,0) == 0x0196)
@@ -8345,11 +8345,13 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 	if(merc_is_hom_active(sd->hd)) {
 		map_addblock(&sd->hd->bl);
 		clif_spawn(&sd->hd->bl);
-//		clif_homunack(sd);
 		clif_hominfo(sd,sd->hd,1);
 		clif_hominfo(sd,sd->hd,0); //for some reason, at least older clients want this sent twice
 		clif_send_homdata(sd,0,0);
 		clif_homskillinfoblock(sd);
+		//Homunc mimic their master's speed on each map change. [Skotlex]
+		if (battle_config.slaves_inherit_speed)
+			status_calc_bl(&sd->hd->bl, SCB_SPEED);
 	}
 
 	// view equipment item

+ 0 - 8
src/map/map.c

@@ -1682,14 +1682,6 @@ int map_quit(struct map_session_data *sd) {
 		}
 	}
 	
-	// Force exiting from duel and rejecting
-	// all duel invitations when player quit [LuzZza]
-	if(sd->duel_group > 0)
-		duel_leave(sd->duel_group, sd);
-	   
-	if(sd->duel_invite > 0)
-		duel_reject(sd->duel_invite, sd);
-
 	//Do we really need to remove the name?
 	idb_remove(charid_db,sd->status.char_id);
 	idb_remove(id_db,sd->bl.id);

+ 22 - 14
src/map/mob.c

@@ -159,20 +159,28 @@ int mob_parse_dataset(struct spawn_data *data) {
 		return 0;
 
 	//better safe than sorry, current md->npc_event has a size of 50
-	if (strlen(data->eventname) >= 50)
+	if ((i=strlen(data->eventname)) >= 50)
 		return 0;
 
-	if (data->eventname[0] && strlen(data->eventname) <= 2)
-	{ //Portable monster big/small implementation. [Skotlex]
-		i = atoi(data->eventname);
-		if (i) {
-			if (i&2)
-				data->state.size=1;
-			else if (i&4)
-				data->state.size=2;
-			if (i&8)
-				data->state.ai=1;
-			data->eventname[0] = '\0'; //Clear event as it is not used.
+	if (data->eventname[0])
+	{
+		if(i <= 2)
+		{	//Portable monster big/small implementation. [Skotlex]
+			i = atoi(data->eventname);
+			if (i) {
+				if (i&2)
+					data->state.size=1;
+				else if (i&4)
+					data->state.size=2;
+				if (i&8)
+					data->state.ai=1;
+				data->eventname[0] = '\0'; //Clear event as it is not used.
+			}
+		} else {
+			if (data->eventname[i-1] == '"');
+				data->eventname[i-1] = '\0'; //Remove trailing quote.
+			if (data->eventname[0] == '"') //Strip leading quotes
+				memmove(data->eventname, data->eventname+1, i-1);
 		}
 	}
 	if (!data->level)
@@ -2784,7 +2792,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
 			}
 			md->skillidx = i;
 			flag = unit_skilluse_pos2(&md->bl, x, y, ms[i].skill_id, ms[i].skill_lv,
-				skill_castfix_sc(&md->bl, ms[i].casttime), ms[i].cancel);
+				ms[i].casttime, ms[i].cancel);
 			if (!flag) md->skillidx = -1; //Skill failed.
 			return flag;
 		} else {
@@ -2814,7 +2822,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
 				}
 				md->skillidx = i;
 				flag = (bl && unit_skilluse_id2(&md->bl, bl->id, ms[i].skill_id, ms[i].skill_lv,
-					skill_castfix_sc(&md->bl,ms[i].casttime),	ms[i].cancel));
+					ms[i].casttime, ms[i].cancel));
 				if (!flag) md->skillidx = -1;
 				return flag;
 			} else {

+ 1 - 1
src/map/npc.c

@@ -2209,7 +2209,7 @@ int npc_parse_mob (char *w1, char *w2, char *w3, char *w4)
 
 	// ˆø�”‚ÌŒÂ�”ƒ`ƒFƒbƒN
 	if (sscanf(w1, "%15[^,],%d,%d,%d,%d", mapname, &x, &y, &xs, &ys) < 3 ||
-		sscanf(w4, "%d,%d,%u,%u,%23s", &class_, &num, &mob.delay1, &mob.delay2, mob.eventname) < 2 ) {
+		sscanf(w4, "%d,%d,%u,%u,%49[^\r\n]", &class_, &num, &mob.delay1, &mob.delay2, mob.eventname) < 2 ) {
 		ShowError("bad monster line : %s %s %s (file %s)\n", w1, w3, w4, current_file);
 		return 1;
 	}

+ 171 - 0
src/map/pc.c

@@ -7006,6 +7006,177 @@ void pc_setstand(struct map_session_data *sd){
 	sd->state.dead_sit = sd->vd.dead_sit = 0;
 }
 
+/*==========================================
+ * Duel organizing functions [LuzZza]
+ *------------------------------------------
+ */
+void duel_savetime(struct map_session_data* sd) {
+
+	time_t timer;
+	struct tm *t;
+	
+	time(&timer);
+	t = localtime(&timer);
+	
+	pc_setglobalreg(sd, "PC_LAST_DUEL_TIME",
+		t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min);	
+	return;
+}
+
+int duel_checktime(struct map_session_data* sd) {
+
+	int diff;
+	time_t timer;
+	struct tm *t;
+	
+	time(&timer);
+    t = localtime(&timer);
+	
+	diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min -
+		pc_readglobalreg(sd, "PC_LAST_DUEL_TIME");
+	
+	return !(diff >= 0 && diff < battle_config.duel_time_interval);
+}
+static int duel_showinfo_sub(struct map_session_data* sd,va_list va) {
+	struct map_session_data *ssd = va_arg(va, struct map_session_data*);
+	int *p = va_arg(va, int*);
+	char output[256];
+
+	if (sd->duel_group != ssd->duel_group) return 0;
+	
+	sprintf(output, "      %d. %s", ++(*p), (unsigned char *)sd->status.name);
+	clif_disp_onlyself(ssd, output, strlen(output));
+	return 1;
+}
+
+int duel_showinfo(
+	const unsigned int did, struct map_session_data* sd)
+{
+	int p=0;
+	char output[256];
+
+	if(duel_list[did].max_players_limit > 0)
+		sprintf(output, msg_txt(370), //" -- Duels: %d/%d, Members: %d/%d, Max players: %d --"
+			did, duel_count,
+			duel_list[did].members_count,
+			duel_list[did].members_count + duel_list[did].invites_count,
+			duel_list[did].max_players_limit);
+	else
+		sprintf(output, msg_txt(371), //" -- Duels: %d/%d, Members: %d/%d --"
+			did, duel_count,
+			duel_list[did].members_count,
+			duel_list[did].members_count + duel_list[did].invites_count);
+
+	clif_disp_onlyself(sd, output, strlen(output));
+   clif_foreachclient(duel_showinfo_sub, sd, &p);
+	return 0;
+}
+
+int duel_create(
+	struct map_session_data* sd, const unsigned int maxpl)
+{
+	int i=1;
+	char output[256];
+	
+	while(duel_list[i].members_count > 0 && i < MAX_DUEL) i++;
+	if(i == MAX_DUEL) return 0;
+	
+	duel_count++;
+	sd->duel_group = i;
+	duel_list[i].members_count++;
+	duel_list[i].invites_count = 0;
+	duel_list[i].max_players_limit = maxpl;
+	
+	strcpy(output, msg_txt(372)); // " -- Duel has been created (@invite/@leave) --"
+	clif_disp_onlyself(sd, output, strlen(output));
+	
+	clif_set0199(sd->fd, 1);
+	//clif_misceffect2(&sd->bl, 159);
+	return i;
+}
+
+int duel_invite(
+	const unsigned int did, struct map_session_data* sd,
+	struct map_session_data* target_sd)
+{
+	char output[256];
+
+	sprintf(output, msg_txt(373), // " -- Player %s invites %s to duel --"
+		(unsigned char *)sd->status.name, (unsigned char *)target_sd->status.name);
+
+	clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+
+	target_sd->duel_invite = did;
+	duel_list[did].invites_count++;
+	
+	// "Blue -- Player %s invites you to PVP duel (@accept/@reject) --"
+	sprintf(output, msg_txt(374), (unsigned char *)sd->status.name);
+	clif_GMmessage((struct block_list *)target_sd, output, strlen(output)+1, 3);
+	return 0;
+}
+
+static int duel_leave_sub(struct map_session_data* sd,va_list va) {
+	int did = va_arg(va, int);
+	if (sd->duel_invite == did)
+		sd->duel_invite = 0;
+	return 0;
+}
+
+int duel_leave(
+	const unsigned int did, struct map_session_data* sd)
+{
+	char output[256];
+	
+	// " <- Player %s has left duel --"
+	sprintf(output, msg_txt(375), (unsigned char *)sd->status.name);
+	clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+	
+	duel_list[did].members_count--;
+	
+	if(duel_list[did].members_count == 0) {
+		clif_foreachclient(duel_leave_sub, did); 
+		duel_count--;
+	}
+	
+	sd->duel_group = 0;
+	duel_savetime(sd);
+	clif_set0199(sd->fd, 0);
+	return 0;
+}
+
+int duel_accept(
+	const unsigned int did, struct map_session_data* sd)
+{
+	char output[256];
+	
+	duel_list[did].members_count++;
+	sd->duel_group = sd->duel_invite;
+	duel_list[did].invites_count--;
+	sd->duel_invite = 0;
+	
+	// " -> Player %s has accepted duel --"
+	sprintf(output, msg_txt(376), (unsigned char *)sd->status.name);
+	clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+
+	clif_set0199(sd->fd, 1);
+	//clif_misceffect2(&sd->bl, 159);
+	return 0;
+}
+
+int duel_reject(
+	const unsigned int did, struct map_session_data* sd)
+{
+	char output[256];
+	
+	// " -- Player %s has rejected duel --"
+	sprintf(output, msg_txt(377), (unsigned char *)sd->status.name);
+	clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+	
+	duel_list[did].invites_count--;
+	sd->duel_invite = 0;
+	return 0;
+}
+
 int pc_split_str(char *str,char **val,int num)
 {
 	int i;

+ 9 - 0
src/map/pc.h

@@ -304,6 +304,15 @@ extern int night_timer_tid;
 int map_day_timer(int,unsigned int,int,int); // by [yor]
 int map_night_timer(int,unsigned int,int,int); // by [yor]
 
+//Duel functions // [LuzZza]
+int duel_create(struct map_session_data* sd, const unsigned int maxpl);
+int duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd);
+int duel_accept(const unsigned int did, struct map_session_data* sd);
+int duel_reject(const unsigned int did, struct map_session_data* sd);
+int duel_leave(const unsigned int did, struct map_session_data* sd);
+int duel_showinfo(const unsigned int did, struct map_session_data* sd);
+int duel_checktime(struct map_session_data* sd);
+
 int pc_read_motd(void); // [Valaris]
 int pc_disguise(struct map_session_data *sd, int class_);
 #endif

+ 2 - 7
src/map/skill.c

@@ -8533,7 +8533,6 @@ int skill_check_condition (struct map_session_data *sd, int skill, int lv, int t
  */
 int skill_castfix (struct block_list *bl, int skill_id, int skill_lv)
 {
-	int castnodex = skill_get_castnodex(skill_id, skill_lv);
 	int time = skill_get_cast(skill_id, skill_lv);	
 	struct map_session_data *sd;
 
@@ -8541,7 +8540,7 @@ int skill_castfix (struct block_list *bl, int skill_id, int skill_lv)
 	BL_CAST(BL_PC, bl, sd);
 	
 	// calculate base cast time (reduced by dex)
-	if (!(castnodex&1)) {			// castnodex&~1? wtf. [blackhole89]
+	if (!(skill_get_castnodex(skill_id, skill_lv)&1)) {
 		int scale = battle_config.castrate_dex_scale - status_get_dex(bl);
 		if (scale > 0)	// not instant cast
 			time = time * scale / battle_config.castrate_dex_scale;
@@ -8556,10 +8555,6 @@ int skill_castfix (struct block_list *bl, int skill_id, int skill_lv)
 	if (battle_config.cast_rate != 100)
 		time = time * battle_config.cast_rate / 100;
 
-  	// calculate cast time reduced by skill bonuses
-	if (!(castnodex&2))
-		time = skill_castfix_sc(bl, time);
-
 	// return final cast time
 	return (time > 0) ? time : 0;
 }
@@ -9743,7 +9738,7 @@ struct skill_unit_group *skill_initunitgroup (struct block_list *src, int count,
 			sd->skilllv_dance=skilllv;
 		}
 		sc_start4(src,SC_DANCING,100,skillid,(int)group,skilllv,(i&UF_ENSEMBLE?BCT_SELF:0),skill_get_time(skillid,skilllv)+1000);
-		if (sd && i&UF_ENSEMBLE &&
+		if (sd && i&UF_ENSEMBLE && skillid != CG_HERMODE && //Hermod is a encore with a warp!
 			battle_config.player_skill_partner_check &&
 			(!battle_config.gm_skilluncond || pc_isGM(sd) < battle_config.gm_skilluncond)
 			) {

+ 1 - 0
src/map/skill.h

@@ -164,6 +164,7 @@ int	skill_get_delay( int id ,int lv );
 int	skill_get_walkdelay( int id ,int lv );
 int	skill_get_time( int id ,int lv );
 int	skill_get_time2( int id ,int lv );
+int	skill_get_castnodex( int id ,int lv );
 int	skill_get_castdef( int id );
 int	skill_get_weapontype( int id );
 int	skill_get_ammotype( int id );

+ 0 - 5
src/map/status.c

@@ -2266,12 +2266,7 @@ int status_calc_pc(struct map_session_data* sd,int first)
 	if(memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill)))
 		clif_skillinfoblock(sd);
 	if(b_status.speed != status->speed)
-	{
 		clif_updatestatus(sd,SP_SPEED);
-		// If speed changes & slaves should inherits master's speed & master have homunc, update it
-		if (sd->hd && battle_config.slaves_inherit_speed)
-			status_calc_bl(&sd->hd->bl, SCB_SPEED);
-	}
 	if(b_weight != sd->weight)
 		clif_updatestatus(sd,SP_WEIGHT);
 	if(b_max_weight != sd->max_weight) {

+ 16 - 4
src/map/unit.c

@@ -930,6 +930,9 @@ int unit_skilluse_id2(struct block_list *src, int target_id, int skill_num, int
 		casttime = casttime * ((distance_bl(src,target)-1)/3+1);
 		break;
 	}
+  	
+	if (!(skill_get_castnodex(skill_num, skill_lv)&2))
+		casttime = skill_castfix_sc(src, casttime);
 
 	if( casttime>0 || temp){ 
 
@@ -1047,12 +1050,14 @@ int unit_skilluse_pos2( struct block_list *src, int skill_x, int skill_y, int sk
 	unit_stop_attack(src);
 	ud->state.skillcastcancel = castcancel;
 
+
+	if (!(skill_get_castnodex(skill_num, skill_lv)&2))
+		casttime = skill_castfix_sc(src, casttime);
+
 	if( casttime>0 ) {
 		unit_stop_walking( src, 1);
 		clif_skillcasting(src, src->id, 0, skill_x,skill_y, skill_num,casttime);
-	}
-
-	if( casttime<=0 )
+	} else
 		ud->state.skillcastcancel=0;
 
 	ud->canact_tick  = tick + casttime + 100;
@@ -1727,7 +1732,14 @@ int unit_free(struct block_list *bl, int clrtype) {
 		}
 		if (sd->followtimer != -1)
 			pc_stop_following(sd);
-		
+		// Force exiting from duel and rejecting
+	// all duel invitations when player quit [LuzZza]
+		if(sd->duel_group > 0)
+			duel_leave(sd->duel_group, sd);
+			
+		if(sd->duel_invite > 0)
+			duel_reject(sd->duel_invite, sd);
+	
 		// Notify friends that this char logged out. [Skotlex]
 		clif_foreachclient(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0);
 		party_send_logout(sd);