diff options
-rw-r--r-- | Changelog-Trunk.txt | 8 | ||||
-rw-r--r-- | src/map/clif.c | 11 | ||||
-rw-r--r-- | src/map/map.c | 14 | ||||
-rw-r--r-- | src/map/mob.c | 17 | ||||
-rw-r--r-- | src/map/npc.c | 104 | ||||
-rw-r--r-- | src/map/npc.h | 13 | ||||
-rw-r--r-- | src/map/pc.c | 61 |
7 files changed, 136 insertions, 92 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 243febb6f..e04c3f697 100644 --- a/Changelog-Trunk.txt +++ b/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
diff --git a/src/map/clif.c b/src/map/clif.c index 95a3a5c29..f95c9aec0 100644 --- a/src/map/clif.c +++ b/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]
diff --git a/src/map/map.c b/src/map/map.c index 6357d09d1..3b3944f0b 100644 --- a/src/map/map.c +++ b/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); diff --git a/src/map/mob.c b/src/map/mob.c index 5e6c5765a..cc9b95083 100644 --- a/src/map/mob.c +++ b/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();
diff --git a/src/map/npc.c b/src/map/npc.c index e294f881b..5ff66ef7a 100644 --- a/src/map/npc.c +++ b/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();
diff --git a/src/map/npc.h b/src/map/npc.h index 2ee4999c6..035c6ecf8 100644 --- a/src/map/npc.h +++ b/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;
diff --git a/src/map/pc.c b/src/map/pc.c index ddf9a244e..c1bab8617 100644 --- a/src/map/pc.c +++ b/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) {
|