Bladeren bron

- Added a npc-script-event cache to avoid looking up event-scripts every time they need to be executed. Events cached are all those defined in script_config.
- Since the cache holds direct pointers to the npcs/events, do NOT unload the related NPCs or you'll get dangling pointers. However, @reloadscript will work fine.
- Set the etc_log to on to see a summary of npcs/events loaded for script execution on startup.


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

skotlex 19 jaren geleden
bovenliggende
commit
db83032024
7 gewijzigde bestanden met toevoegingen van 136 en 92 verwijderingen
  1. 8 0
      Changelog-Trunk.txt
  2. 1 10
      src/map/clif.c
  3. 2 12
      src/map/map.c
  4. 3 14
      src/map/mob.c
  5. 103 1
      src/map/npc.c
  6. 13 0
      src/map/npc.h
  7. 6 55
      src/map/pc.c

+ 8 - 0
Changelog-Trunk.txt

@@ -4,6 +4,14 @@ 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/05
+	* Added a npc-script-event cache to avoid looking up event-scripts every
+	  time they need to be executed. Events cached are all those defined in
+	  script_config (on login, logout, mapchange, death, kill, level up) [Skotlex]
+	- Since the cache holds direct pointers to the npcs/events, do NOT unload
+	  the related NPCs or you'll get dangling pointer crashes. However,
+	  @reloadscript will work fine.
+	- Set the etc_log to on to see a summary of npcs/events loaded for script
+	  execution on startup.
 	* The Rest bonus activated by using /doridori while in rest should now
 	  trigger with all the class tree (TK/SL/SG) [Skotlex]
 	* Fixed Kaupe always triggering when the one who was under Kaupe was a

+ 1 - 10
src/map/clif.c

@@ -8228,16 +8228,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		sc_start(&sd->bl,SC_NOCHAT,100,0,0);
 
 // Lance
-	if (script_config.event_script_type == 0) {
-		struct npc_data *npc;
-		if ((npc = npc_name2id(script_config.loadmap_event_name))) {  
-			run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id);
-			ShowStatus("Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.loadmap_event_name);
-		}
-	} else {
-		ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
-			npc_event_doall_id(script_config.loadmap_event_name, sd->bl.id), script_config.loadmap_event_name);
-	}
+	npc_script_event(sd, NPCE_LOADMAP);
 
 	if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd))
 		clif_status_load(&sd->bl, SI_DEVIL, 1);  //blindness [Komurka]

+ 2 - 12
src/map/map.c

@@ -1648,18 +1648,8 @@ int map_quit(struct map_session_data *sd) {
 	if(!sd->state.waitingdisconnect) {
 		if (sd->npc_timer_id != -1) //Cancel the event timer.
 			npc_timerevent_quit(sd);
-		if (sd->state.event_disconnect) {
-			if (script_config.event_script_type == 0) {
-				struct npc_data *npc;
-				if ((npc = npc_name2id(script_config.logout_event_name))) {
-					run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLogoutNPC
-					ShowStatus("Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.logout_event_name);
-				}
-			} else {
-				ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
-					npc_event_doall_id(script_config.logout_event_name, sd->bl.id), script_config.logout_event_name);
-			}
-		}
+		if (sd->state.event_disconnect)
+			npc_script_event(sd, NPCE_LOGOUT);
 		if (sd->pd) unit_free(&sd->pd->bl);
 		unit_free(&sd->bl);
 		pc_clean_skilltree(sd);

+ 3 - 14
src/map/mob.c

@@ -2119,21 +2119,10 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
 		else if(mvp_sd)
 			npc_event(mvp_sd,md->npc_event,0);
 
-	} else if (mvp_sd) {
-	//lordalfa
+	} else if (mvp_sd) {	//lordalfa
 		pc_setglobalreg(mvp_sd,"killedrid",(md->class_));
-		if(mvp_sd->state.event_kill_mob){
-			if (script_config.event_script_type == 0) {
-				struct npc_data *npc;
-				if ((npc = npc_name2id(script_config.kill_mob_event_name))) {
-					run_script(npc->u.scr.script,0,mvp_sd->bl.id,npc->bl.id); // PCKillNPC [Lance]
-					ShowStatus("Event '"CL_WHITE"%s"CL_RESET"' executed.\n",script_config.kill_mob_event_name);
-				}
-			} else {
-				ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",	
-				npc_event_doall_id(script_config.kill_mob_event_name, mvp_sd->bl.id), script_config.kill_mob_event_name);
-			}
-		}
+		if(mvp_sd->state.event_kill_mob)
+			npc_script_event(mvp_sd, NPCE_KILLNPC); // PCKillNPC [Lance]
 	}
 	if(md->level) md->level=0;
 	map_freeblock_unlock();

+ 103 - 1
src/map/npc.c

@@ -67,6 +67,14 @@ static struct eri *timer_event_ers; //For the npc timer data. [Skotlex]
 //For holding the view data of npc classes. [Skotlex]
 static struct view_data npc_viewdb[MAX_NPC_CLASS];
 
+static struct
+{	//Holds pointers to the commonly executed scripts for speedup. [Skotlex]
+	struct npc_data *nd;
+	struct event_data *event[UCHAR_MAX];
+	unsigned char *event_name[UCHAR_MAX];
+	unsigned char event_count;
+} script_event[NPCE_MAX];
+
 struct view_data* npc_get_viewdata(int class_)
 {	//Returns the viewdata for normal npc classes.
 	if (class_ == INVISIBLE_CLASS)
@@ -2535,6 +2543,96 @@ void npc_parsesrcfile (char *name)
 	return;
 }
 
+int npc_script_event(TBL_PC* sd, int type) {
+	int i;
+	if (type < 0 || type >= NPCE_MAX)
+		return 0;
+	if (!sd) {
+		if (battle_config.error_log)
+			ShowError("npc_script_event: NULL sd. Event Type %d\n", type);
+		return 0;
+	}
+	if (script_event[type].nd) {
+		TBL_NPC *nd = script_event[type].nd;
+		run_script(nd->u.scr.script,0,sd->bl.id,nd->bl.id);
+		return 1;
+	} else if (script_event[type].event_count) {
+		for (i = 0; i<script_event[type].event_count; i++) {
+			npc_event_sub(sd,script_event[type].event[i],script_event[type].event_name[i]);
+		}
+		return i;
+	} 
+	return 0;
+}
+
+static int npc_read_event_script_sub(DBKey key,void *data,va_list ap)
+{
+	unsigned char *p = key.str;
+	unsigned char *name = va_arg(ap,unsigned char *);
+	struct event_data **event_buf = va_arg(ap,struct event_data**);
+	unsigned char **event_name = va_arg(ap,unsigned char **);
+	unsigned char *count = va_arg(ap,char *);;
+
+	if (*count >= UCHAR_MAX) return 0;
+	
+	if((p=strchr(p,':')) && p && strcmpi(name,p)==0 )
+	{
+		event_buf[*count] = (struct event_data *)data;
+		event_name[*count] = key.str;
+		(*count)++;
+		return 1;
+	}
+	return 0;
+}
+
+static void npc_read_event_script(void)
+{
+	int i;
+	unsigned char buf[64]="::";
+	struct {
+		char *name;
+		char *event_name;
+	} config[] = {
+		{"Login Event",script_config.login_event_name},
+		{"Logout Event",script_config.logout_event_name},
+		{"Load Map Event",script_config.loadmap_event_name},
+		{"Base LV Up Event",script_config.baselvup_event_name},
+		{"Job LV Up Event",script_config.joblvup_event_name},
+		{"Die Event",script_config.die_event_name},
+		{"Kill PC Event",script_config.kill_pc_event_name},
+		{"Kill NPC Event",script_config.kill_mob_event_name},
+	};
+
+	for (i = 0; i < NPCE_MAX; i++) {
+		if (script_event[i].nd)
+			script_event[i].nd = NULL;
+		if (script_event[i].event_count)
+			script_event[i].event_count = 0;
+		if (!script_config.event_script_type) {
+			//Use a single NPC as event source.
+			script_event[i].nd = npc_name2id(config[i].event_name);
+		} else {
+			//Use an array of Events
+			strncpy(buf+2,config[i].event_name,62);
+			ev_db->foreach(ev_db,npc_read_event_script_sub,buf,
+				&script_event[i].event,
+				&script_event[i].event_name,
+				&script_event[i].event_count);
+		}
+	}
+	if (battle_config.etc_log) {
+		//Print summary.
+		for (i = 0; i < NPCE_MAX; i++) {
+			if(!script_config.event_script_type) {
+				if (script_event[i].nd)
+					ShowInfo("%s: Using NPC named '%s'.\n", config[i].name, config[i].event_name);
+				else
+					ShowInfo("%s: No NPC found with name '%s'.\n", config[i].name, config[i].event_name);
+			} else
+				ShowInfo("%s: %d '%s' events.\n", config[i].name, script_event[i].event_count, config[i].event_name);
+		}
+	}
+}
 static int npc_read_indoors (void)
 {
 	char *buf, *p;
@@ -2646,6 +2744,9 @@ int npc_reload (void)
 		CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
 		npc_id - npc_new_min, "", npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
 
+	//Re-read the NPC Script Events cache.
+	npc_read_event_script();
+	
 	//Execute the OnInit event for freshly loaded npcs. [Skotlex]
 	ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"
 	CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit"));
@@ -2787,7 +2888,8 @@ int do_init_npc(void)
 		CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
 		npc_id - START_NPC_NUM, "", npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
 
-
+	memset(script_event, 0, sizeof(script_event));
+	npc_read_event_script();
 	//Debug function to locate all endless loop warps.
 	npc_debug_warps();
 	

+ 13 - 0
src/map/npc.h

@@ -20,6 +20,18 @@ void npc_chat_finalize(struct npc_data *nd);
 int mob_chat_sub(struct block_list *bl, va_list ap);
 #endif
 
+//Script NPC events.
+enum {
+	NPCE_LOGIN,
+	NPCE_LOGOUT,
+	NPCE_LOADMAP,
+	NPCE_BASELVUP,
+	NPCE_JOBLVUP,
+	NPCE_DIE,
+	NPCE_KILLPC,
+	NPCE_KILLNPC,
+	NPCE_MAX
+};
 struct view_data* npc_get_viewdata(int class_);
 int npc_chat_sub(struct block_list *bl, va_list ap);
 int npc_event_dequeue(struct map_session_data *sd);
@@ -65,6 +77,7 @@ int npc_settimerevent_tick(struct npc_data *nd,int newtimer);
 int npc_remove_map(struct npc_data *nd);
 int npc_unload(struct npc_data *nd);
 int npc_reload(void);
+int npc_script_event(TBL_PC* sd, int type);
 
 extern int dummy_npc_id;
 

+ 6 - 55
src/map/pc.c

@@ -877,17 +877,7 @@ int pc_reg_received(struct map_session_data *sd)
 		sd->state.event_kill_mob = 1;
 	}
 
-	if (script_config.event_script_type == 0) {
-		struct npc_data *npc;
-		if ((npc = npc_name2id(script_config.login_event_name))) {
-			run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLoginNPC
-			ShowStatus("Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.login_event_name);
-		}
-	} else {
-		ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
-			npc_event_doall_id(script_config.login_event_name, sd->bl.id), script_config.login_event_name);
-	}
-
+	npc_script_event(sd, NPCE_LOGIN);
 	return 0;
 }
 
@@ -3786,17 +3776,7 @@ int pc_checkbaselevelup(struct map_session_data *sd)
 		}
 		clif_misceffect(&sd->bl,0);
 		//LORDALFA - LVLUPEVENT
-		if (script_config.event_script_type == 0) {
-			struct npc_data *npc;
-			if ((npc = npc_name2id(script_config.baselvup_event_name))) {
-				run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLvlUPNPC
-				ShowStatus("Event '"CL_WHITE"%s"CL_RESET"' executed.\n",script_config.baselvup_event_name);
-			}
-		} else {
-				ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
-				npc_event_doall_id(script_config.baselvup_event_name, sd->bl.id), script_config.baselvup_event_name);
-		}
-
+		npc_script_event(sd, NPCE_BASELVUP);
 		return 1;
 		}
 
@@ -3827,17 +3807,7 @@ int pc_checkjoblevelup(struct map_session_data *sd)
 		if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd))
 			clif_status_change(&sd->bl,SI_DEVIL, 1); //Permanent blind effect from SG_DEVIL.
 
-		if (script_config.event_script_type == 0) {
-			struct npc_data *npc;
-			if ((npc = npc_name2id(script_config.joblvup_event_name))) {
-				run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLvlUPNPC
-				ShowStatus("Event '"CL_WHITE"%s"CL_RESET"' executed.\n",script_config.joblvup_event_name);
-			}
-		} else {
-				ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
-				npc_event_doall_id(script_config.joblvup_event_name, sd->bl.id), script_config.joblvup_event_name);
-		}
-
+		npc_script_event(sd, NPCE_JOBLVUP);
 		return 1;
 	}
 
@@ -4569,16 +4539,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
 				pc_setglobalreg(sd,"killerrid",(ssd->status.account_id));
 			if (ssd->state.event_kill_pc) {
 				pc_setglobalreg(ssd, "killedrid", sd->bl.id);
-				if (script_config.event_script_type == 0) {
-					struct npc_data *npc;
-					if ((npc = npc_name2id(script_config.kill_pc_event_name))) {
-						run_script(npc->u.scr.script,0,ssd->bl.id,npc->bl.id); // PCKillPC [Lance]
-						ShowStatus("Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.kill_pc_event_name);
-					}
-				} else {
-					ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
-						npc_event_doall_id(script_config.kill_pc_event_name, ssd->bl.id), script_config.kill_pc_event_name);
-				}
+				npc_script_event(ssd, NPCE_KILLPC);
 			}
 			if (battle_config.pk_mode && ssd->status.manner >= 0 && battle_config.manner_system) {
 				ssd->status.manner -= 5;
@@ -4608,18 +4569,8 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
 		pc_setglobalreg(sd, "killerrid", 0);
 	}
 
-	if (sd->state.event_death) {
-		if (script_config.event_script_type == 0) {
-			struct npc_data *npc;
-			if ((npc = npc_name2id(script_config.die_event_name))) {
-				run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCDeathNPC
-				ShowStatus("Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.die_event_name);
-			}
-		} else {
-			ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
-				npc_event_doall_id(script_config.die_event_name, sd->bl.id), script_config.die_event_name);
-		}
-	}
+	if (sd->state.event_death)
+		npc_script_event(sd,NPCE_DIE);
 
 // PK/Karma system code (not enabled yet) [celest]
 	/*if(sd->status.karma > 0) {