summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-05-05 23:22:16 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-05-05 23:22:16 +0000
commit3fefab81425004d67c61fb911a417ddfdd089693 (patch)
treec7e4062a46ca24a5681950abb9a16bb5e2c56f29 /src/map
parent1db41fdf364af26b0600a43a167d15f2d2ef8244 (diff)
downloadhercules-3fefab81425004d67c61fb911a417ddfdd089693.tar.gz
hercules-3fefab81425004d67c61fb911a417ddfdd089693.tar.bz2
hercules-3fefab81425004d67c61fb911a417ddfdd089693.tar.xz
hercules-3fefab81425004d67c61fb911a417ddfdd089693.zip
- 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://rathena.svn.sourceforge.net/svnroot/rathena/trunk@6494 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map')
-rw-r--r--src/map/clif.c11
-rw-r--r--src/map/map.c14
-rw-r--r--src/map/mob.c17
-rw-r--r--src/map/npc.c104
-rw-r--r--src/map/npc.h13
-rw-r--r--src/map/pc.c61
6 files changed, 128 insertions, 92 deletions
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) {