summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2014-03-14 13:41:30 -0300
committershennetsind <ind@henn.et>2014-03-14 13:41:30 -0300
commitf4b1ff7426b1c4cd5e8cac37f7e3983cc03c706e (patch)
tree68b403b855daca7d11b86b02fcf2d95b8de974b4 /src
parent571d9e25008d8b386e28d7f1fd02f2690edf1f8c (diff)
downloadhercules-f4b1ff7426b1c4cd5e8cac37f7e3983cc03c706e.tar.gz
hercules-f4b1ff7426b1c4cd5e8cac37f7e3983cc03c706e.tar.bz2
hercules-f4b1ff7426b1c4cd5e8cac37f7e3983cc03c706e.tar.xz
hercules-f4b1ff7426b1c4cd5e8cac37f7e3983cc03c706e.zip
Added internal awareness of active script instances
Fixes the following issues: - donpcevent could cause a crash when used to a event of the same npc - input/other-dialog-interactions could cause a crash when sending data to a disabled-fakenpc-id'd. Special Thanks to Haruna, ossi0110. Signed-off-by: shennetsind <ind@henn.et>
Diffstat (limited to 'src')
-rw-r--r--src/map/npc.c16
-rw-r--r--src/map/script.c25
-rw-r--r--src/map/script.h3
3 files changed, 32 insertions, 12 deletions
diff --git a/src/map/npc.c b/src/map/npc.c
index 7933f6d43..f77359b5f 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1185,21 +1185,21 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd)
/*==========================================
*
*------------------------------------------*/
-int npc_scriptcont(struct map_session_data* sd, int id, bool closing)
-{
+int npc_scriptcont(struct map_session_data* sd, int id, bool closing) {
+ struct block_list *target = map->id2bl(id);
nullpo_retr(1, sd);
if( id != sd->npc_id ){
TBL_NPC* nd_sd=(TBL_NPC*)map->id2bl(sd->npc_id);
- TBL_NPC* nd=(TBL_NPC*)map->id2bl(id);
+ TBL_NPC* nd = BL_CAST(BL_NPC, target);
ShowDebug("npc_scriptcont: %s (sd->npc_id=%d) is not %s (id=%d).\n",
nd_sd?(char*)nd_sd->name:"'Unknown NPC'", (int)sd->npc_id,
nd?(char*)nd->name:"'Unknown NPC'", (int)id);
return 1;
}
-
+
if(id != npc->fake_nd->bl.id) { // Not item script
- if ((npc->checknear(sd,map->id2bl(id))) == NULL){
+ if ((npc->checknear(sd,target)) == NULL){
ShowWarning("npc_scriptcont: failed npc->checknear test.\n");
return 1;
}
@@ -1219,7 +1219,10 @@ int npc_scriptcont(struct map_session_data* sd, int id, bool closing)
**/
if( sd->progressbar.npc_id && DIFF_TICK(sd->progressbar.timeout,timer->gettick()) > 0 )
return 1;
-
+
+ if( !sd->st )
+ return 1;
+
if( closing && sd->st->state == CLOSE )
sd->st->state = END;
@@ -2226,7 +2229,6 @@ int npc_unload(struct npc_data* nd, bool single) {
aFree(nd->u.scr.timer_event);
if (nd->src_id == 0) {
if(nd->u.scr.script) {
- script->stop_instances(nd->u.scr.script);
script->free_code(nd->u.scr.script);
nd->u.scr.script = NULL;
}
diff --git a/src/map/script.c b/src/map/script.c
index bba771a3c..fca87a81d 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -3208,9 +3208,8 @@ void script_free_vars(struct DBMap* var_storage) {
void script_free_code(struct script_code* code)
{
- script->free_vars(code->local.vars);
- if( code->local.arrays )
- code->local.arrays->destroy(code->local.arrays,script->array_free_db);
+ if( code->instances )
+ script->stop_instances(code);
aFree( code->script_buf );
aFree( code );
}
@@ -3242,6 +3241,13 @@ struct script_state* script_alloc_state(struct script_code* rootscript, int pos,
st->oid = oid;
st->sleep.timer = INVALID_TIMER;
st->npc_item_flag = battle_config.item_enabled_npc;
+
+ if( st->script->instances != USHRT_MAX )
+ st->script->instances++;
+ else {
+ struct npc_data *nd = map->id2nd(oid);
+ ShowError("over 65k instances of '%s' script are being run\n",nd ? nd->name : "unknown");
+ }
if( !st->script->local.vars )
st->script->local.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
@@ -3259,9 +3265,20 @@ struct script_state* script_alloc_state(struct script_code* rootscript, int pos,
/// @param st Script state
void script_free_state(struct script_state* st) {
if( idb_exists(script->st_db,st->id) ) {
+ struct map_session_data *sd = st->rid ? map->id2sd(st->rid) : NULL;
+
if(st->bk_st) {// backup was not restored
ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid);
}
+
+ if(sd && sd->st == st) { //Current script is aborted.
+ if(sd->state.using_fake_npc){
+ clif->clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
+ sd->state.using_fake_npc = 0;
+ }
+ sd->st = NULL;
+ sd->npc_id = 0;
+ }
if( st->sleep.timer != INVALID_TIMER )
timer->delete(st->sleep.timer, script->run_timer);
@@ -3274,7 +3291,7 @@ void script_free_state(struct script_state* st) {
ers_free(script->stack_ers, st->stack);
st->stack = NULL;
}
- if( st->script ) {
+ if( st->script && st->script->instances != USHRT_MAX && --st->script->instances == 0 ) {
if( st->script->local.vars && !db_size(st->script->local.vars) ) {
script->free_vars(st->script->local.vars);
st->script->local.vars = NULL;
diff --git a/src/map/script.h b/src/map/script.h
index 73ba7303e..cf7f22aa9 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -371,6 +371,7 @@ struct script_code {
int script_size;
unsigned char *script_buf;
struct reg_db local; ///< Local (npc) vars
+ unsigned short instances;
};
struct script_stack {
@@ -407,7 +408,7 @@ struct script_state {
int pos;
enum e_script_state state;
int rid,oid;
- struct script_code *script, *scriptroot;
+ struct script_code *script;
struct sleep_data {
int tick,timer,charid;
} sleep;