From b098c36a440f8052ab3c548420920bad92c7d872 Mon Sep 17 00:00:00 2001 From: Lance Date: Thu, 29 Jun 2006 08:47:14 +0000 Subject: * [Fixed] - Scripting system screwing up script position after mixing timers with menus. - NPC attached AI mobs display as alive when dead. - View data not updating after buildin_unitdeadsit. [Improved] - NPCE_LOADMAP to execute after all (area) objects are sent to the player. - Simplified scripting system. sd will now use pointer to the script state itself. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@7388 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-Trunk.txt | 10 ++ src/map/clif.h | 1 + src/map/map.c | 4 - src/map/map.h | 4 +- src/map/mob.c | 21 ++-- src/map/npc.c | 12 +-- src/map/pc.c | 13 +-- src/map/script.c | 280 +++++++++++++++++++++++++++++----------------------- src/map/script.h | 4 +- 9 files changed, 195 insertions(+), 154 deletions(-) diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 49ad1d438..604ba5e71 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,6 +3,16 @@ 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/05/29 + * [Fixed] + - Scripting system screwing up script position after mixing timers with menus. + - NPC attached AI mobs display as alive when dead. + - View data not updating after buildin_unitdeadsit. + [Improved] + - NPCE_LOADMAP to execute after all (area) objects are sent to the player. + - Simplified scripting system. sd will now use pointer to the script state itself. + [Lance] + 2006/05/28 * changed: dynamic_pass_failure_ban_how_many:from 3 to 7 diff --git a/src/map/clif.h b/src/map/clif.h index 7cae56cdf..64c0ef2eb 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -317,6 +317,7 @@ int clif_pet_emotion(struct pet_data *pd,int param); int clif_pet_performance(struct block_list *bl,int param); int clif_pet_equip(struct pet_data *pd,int nameid); int clif_pet_food(struct map_session_data *sd,int foodid,int fail); +int clif_send (unsigned char *buf, int len, struct block_list *bl, int type); //friends list int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap); diff --git a/src/map/map.c b/src/map/map.c index 98af550c2..c43ed5ca2 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1678,10 +1678,6 @@ int map_quit(struct map_session_data *sd) { unit_remove_map(&sd->pd->bl, 0); } } - if (sd->stack) { - script_free_stack(sd->stack); - sd->stack= NULL; - } //Do we really need to remove the name? idb_remove(charid_db,sd->status.char_id); diff --git a/src/map/map.h b/src/map/map.h index a0d19f04e..9e92dea70 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -526,11 +526,9 @@ struct map_session_data { unsigned int client_tick; int npc_id,areanpc_id,npc_shopid; int npc_item_flag; //Marks the npc_id with which you can use items during interactions with said npc (see script command enable_itemuse) - int npc_pos; int npc_menu; int npc_amount; - struct script_stack *stack; - struct script_code *npc_script,*npc_scriptroot; + struct script_state *st; int npc_scriptstate; char npc_str[256]; int npc_timer_id; //For player attached npc timers. [Skotlex] diff --git a/src/map/mob.c b/src/map/mob.c index ab195ecac..63b71b941 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -774,12 +774,12 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) if ((*target) == bl || !status_check_skilluse(&md->bl, bl, 0, 0)) return 0; - if(md->nd && mob_script_callback(md, bl, CALLBACK_DETECT)) - return 1; // We have script handling the work. - if(battle_check_target(&md->bl,bl,BCT_ENEMY)<=0) return 0; + if(md->nd && mob_script_callback(md, bl, CALLBACK_DETECT)) + return 1; // We have script handling the work. + switch (bl->type) { case BL_PC: @@ -2120,9 +2120,10 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) if(pcdb_checkid(md->vd->class_)) { //Player mobs are not removed automatically by the client. - if(md->nd) + if(md->nd){ + md->vd->dead_sit = 1; return 1; // Let the dead body stay there.. we have something to do with it :D - else + } else clif_clearchar_delay(tick+3000,&md->bl,0); } @@ -2400,8 +2401,13 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int skill_id) md= mob_spawn_dataset(&data); md->special_state.cached= battle_config.dynamic_mobs; //[Skotlex] - if(skill_id == NPC_SUMMONSLAVE) + if(skill_id == NPC_SUMMONSLAVE){ md->master_id=md2->bl.id; + md->state.killer = md2->state.killer; + md->special_state.ai = md2->special_state.ai; + md->nd = md2->nd; + md->callback_flag = md2->callback_flag; + } mob_spawn(md); if (hp_rate) //Scale HP @@ -2418,9 +2424,6 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int skill_id) clif_skill_nodamage(&md->bl,&md->bl,skill_id,amount,1); } - if(md2->nd) - mob_convertslave(md2); - return 0; } diff --git a/src/map/npc.c b/src/map/npc.c index 6f3fe5f00..a81a63b23 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -818,7 +818,7 @@ int npc_event_sub(struct map_session_data *sd, struct event_data *ev, const unsi return 0; } - sd->npc_pos=run_script(ev->nd->u.scr.script,ev->pos,sd->bl.id,ev->nd->bl.id); + run_script(ev->nd->u.scr.script,ev->pos,sd->bl.id,ev->nd->bl.id); return 0; } @@ -1108,7 +1108,7 @@ int npc_click(struct map_session_data *sd,struct block_list *bl) npc_event_dequeue(sd); break; case SCRIPT: - sd->npc_pos=run_script(nd->u.scr.script,0,sd->bl.id,nd->bl.id); + run_script(nd->u.scr.script,0,sd->bl.id,nd->bl.id); break; } @@ -1129,14 +1129,12 @@ int npc_scriptcont(struct map_session_data *sd,int id) } if(id != fake_nd->bl.id) { // Not item script - struct npc_data *nd; - if ((nd = npc_checknear(sd,map_id2bl(id))) == NULL){ + if ((npc_checknear(sd,map_id2bl(id))) == NULL){ ShowWarning("npc_scriptcont: failed npc_checknear test.\n"); return 1; } - sd->npc_pos=run_script(nd->u.scr.script,sd->npc_pos,sd->bl.id,id); - } else // Item script, continue execution... - sd->npc_pos=run_script(sd->npc_scriptroot,sd->npc_pos,sd->bl.id,id); + } + run_script_main(sd->st); return 0; } diff --git a/src/map/pc.c b/src/map/pc.c index fc7e5c7a8..ac3a054f2 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4679,8 +4679,13 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) pc_setglobalreg(sd,"PC_DIE_COUNTER",++sd->die_counter); - if (sd->state.event_death && (!src || src->type != BL_PC)) - pc_setglobalreg(sd, "killerrid", 0); + if (sd->state.event_death){ + if(!src) + pc_setglobalreg(sd, "killerrid", 0); + else + pc_setglobalreg(sd,"killerrid",src->id); + npc_script_event(sd,NPCE_DIE); + } if (src) switch (src->type) { @@ -4705,10 +4710,6 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) case BL_PC: { struct map_session_data *ssd = (struct map_session_data *)src; - if (sd->state.event_death){ - pc_setglobalreg(sd,"killerrid",(ssd->status.account_id)); - npc_script_event(sd,NPCE_DIE); - } if (ssd->state.event_kill_pc) { pc_setglobalreg(ssd, "killedrid", sd->bl.id); npc_script_event(ssd, NPCE_KILLPC); diff --git a/src/map/script.c b/src/map/script.c index 3f7b98aaa..818280012 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -404,7 +404,7 @@ int buildin_setd(struct script_state *st); int buildin_petstat(struct script_state *st); // [Lance] Pet Stat Rq: Dubby int buildin_callshop(struct script_state *st); // [Skotlex] int buildin_npcshopitem(struct script_state *st); // [Lance] -int buildin_npcshopadditem(struct script_state *st); +int buildin_npcshopadditem(struct script_state *st); int buildin_npcshopdelitem(struct script_state *st); int buildin_equip(struct script_state *st); int buildin_autoequip(struct script_state *st); @@ -741,7 +741,7 @@ struct { {buildin_petstat,"petstat","i"}, {buildin_callshop,"callshop","si"}, // [Skotlex] {buildin_npcshopitem,"npcshopitem","sii*"}, // [Lance] - {buildin_npcshopadditem,"npcshopadditem","sii*"}, + {buildin_npcshopadditem,"npcshopadditem","sii*"}, {buildin_npcshopdelitem,"npcshopdelitem","si*"}, {buildin_equip,"equip","i"}, {buildin_autoequip,"autoequip","ii"}, @@ -8992,18 +8992,18 @@ int buildin_movenpc(struct script_state *st) x = conv_num(st,& (st->stack->stack_data[st->start+3])); y = conv_num(st,& (st->stack->stack_data[st->start+4])); - if ((nd = npc_name2id(npc)) == NULL) - return -1; - - if ((m=nd->bl.m) < 0 || nd->bl.prev == NULL) - return -1; //Not on a map. - - if (x < 0) x = 0; - else if (x >= map[m].xs) x = map[m].xs-1; - if (y < 0) y = 0; - else if (y >= map[m].ys) y = map[m].ys-1; - map_foreachinrange(clif_outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); - map_moveblock(&nd->bl, x, y, gettick()); + if ((nd = npc_name2id(npc)) == NULL) + return -1; + + if ((m=nd->bl.m) < 0 || nd->bl.prev == NULL) + return -1; //Not on a map. + + if (x < 0) x = 0; + else if (x >= map[m].xs) x = map[m].xs-1; + if (y < 0) y = 0; + else if (y >= map[m].ys) y = map[m].ys-1; + map_foreachinrange(clif_outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); + map_moveblock(&nd->bl, x, y, gettick()); map_foreachinrange(clif_insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); return 0; @@ -10134,83 +10134,83 @@ int buildin_npcshopitem(struct script_state *st) return 0; } -int buildin_npcshopadditem(struct script_state *st) { - struct npc_data *nd=NULL; - int n = 0; - int i = 3; - int amount; - - char* npcname = conv_str(st, & (st->stack->stack_data[st->start+2])); - nd = npc_name2id(npcname); - - if (nd && nd->bl.subtype==SHOP){ - amount = ((st->end-2)/2)+1; - while (nd->u.shop_item[n].nameid && n < MAX_SHOPITEM) +int buildin_npcshopadditem(struct script_state *st) { + struct npc_data *nd=NULL; + int n = 0; + int i = 3; + int amount; + + char* npcname = conv_str(st, & (st->stack->stack_data[st->start+2])); + nd = npc_name2id(npcname); + + if (nd && nd->bl.subtype==SHOP){ + amount = ((st->end-2)/2)+1; + while (nd->u.shop_item[n].nameid && n < MAX_SHOPITEM) n++; nd = (struct npc_data *)aRealloc(nd,sizeof(struct npc_data) + - sizeof(nd->u.shop_item[0]) * (amount+n)); - - while(st->end > st->start + i){ - nd->u.shop_item[n].nameid = conv_num(st, & (st->stack->stack_data[st->start+i])); - i++; - nd->u.shop_item[n].value = conv_num(st, & (st->stack->stack_data[st->start+i])); - i++; - n++; - } - - // Marks the last of our stuff.. - nd->u.shop_item[n].value = 0; - nd->u.shop_item[n].nameid = 0; - - map_addiddb(&nd->bl); - nd->master_nd = ((struct npc_data *)map_id2bl(st->oid)); - } else { - ShowError("buildin_npcshopadditem: shop not found.\n"); - } - - return 0; -} - -int buildin_npcshopdelitem(struct script_state *st) -{ - struct npc_data *nd=NULL; - int n=0; - int i=3; - int size = 0; - - char* npcname = conv_str(st, & (st->stack->stack_data[st->start+2])); - nd = npc_name2id(npcname); - - if (nd && nd->bl.subtype==SHOP) { - while (nd->u.shop_item[size].nameid) - size++; - - while (st->end > st->start+i) { - for(n=0;nd->u.shop_item[n].nameid && n < MAX_SHOPITEM;n++) { - if (nd->u.shop_item[n].nameid == conv_num(st, & (st->stack->stack_data[st->start+i]))) { - // We're moving 1 extra empty block. Junk data is eliminated later. - memmove(&nd->u.shop_item[n], &nd->u.shop_item[n+1], sizeof(nd->u.shop_item[0])*(size-n)); - } - } - i++; - } - - size = 0; - - while (nd->u.shop_item[size].nameid) - size++; - - nd = (struct npc_data *)aRealloc(nd,sizeof(struct npc_data) + - sizeof(nd->u.shop_item[0]) * (size+1)); - - map_addiddb(&nd->bl); - nd->master_nd = ((struct npc_data *)map_id2bl(st->oid)); - } else { - ShowError("buildin_npcshopdelitem: shop not found.\n"); - } - - return 0; + sizeof(nd->u.shop_item[0]) * (amount+n)); + + while(st->end > st->start + i){ + nd->u.shop_item[n].nameid = conv_num(st, & (st->stack->stack_data[st->start+i])); + i++; + nd->u.shop_item[n].value = conv_num(st, & (st->stack->stack_data[st->start+i])); + i++; + n++; + } + + // Marks the last of our stuff.. + nd->u.shop_item[n].value = 0; + nd->u.shop_item[n].nameid = 0; + + map_addiddb(&nd->bl); + nd->master_nd = ((struct npc_data *)map_id2bl(st->oid)); + } else { + ShowError("buildin_npcshopadditem: shop not found.\n"); + } + + return 0; +} + +int buildin_npcshopdelitem(struct script_state *st) +{ + struct npc_data *nd=NULL; + int n=0; + int i=3; + int size = 0; + + char* npcname = conv_str(st, & (st->stack->stack_data[st->start+2])); + nd = npc_name2id(npcname); + + if (nd && nd->bl.subtype==SHOP) { + while (nd->u.shop_item[size].nameid) + size++; + + while (st->end > st->start+i) { + for(n=0;nd->u.shop_item[n].nameid && n < MAX_SHOPITEM;n++) { + if (nd->u.shop_item[n].nameid == conv_num(st, & (st->stack->stack_data[st->start+i]))) { + // We're moving 1 extra empty block. Junk data is eliminated later. + memmove(&nd->u.shop_item[n], &nd->u.shop_item[n+1], sizeof(nd->u.shop_item[0])*(size-n)); + } + } + i++; + } + + size = 0; + + while (nd->u.shop_item[size].nameid) + size++; + + nd = (struct npc_data *)aRealloc(nd,sizeof(struct npc_data) + + sizeof(nd->u.shop_item[0]) * (size+1)); + + map_addiddb(&nd->bl); + nd->master_nd = ((struct npc_data *)map_id2bl(st->oid)); + } else { + ShowError("buildin_npcshopdelitem: shop not found.\n"); + } + + return 0; } /*========================================== @@ -10709,7 +10709,7 @@ int buildin_unitwarp(struct script_state *st){ y = conv_num(st, & (st->stack->stack_data[st->start+5])); bl = map_id2bl(id); - m = mapindex_name2id(map); + m = map_mapname2mapid(map); if(m && bl){ push_val(st->stack,C_INT,unit_warp(bl, m, (short)x, (short)y, 0)); } else { @@ -10831,7 +10831,8 @@ int buildin_unitdeadsit(struct script_state *st){ id = conv_num(st, & (st->stack->stack_data[st->start+2])); action = conv_num(st, & (st->stack->stack_data[st->start+3])); if((bl = map_id2bl(id))){ - if(action > -1 && action < 3){ + if(action > -1 && action < 4){ + unsigned char *buf = NULL; switch(bl->type){ case BL_MOB: ((TBL_MOB *)bl)->vd->dead_sit = action; @@ -10848,6 +10849,10 @@ int buildin_unitdeadsit(struct script_state *st){ case BL_PET: ((TBL_PET *)bl)->vd.dead_sit = action; break; + WBUFW(buf, 0) = 0x8a; + WBUFL(buf, 2) = bl->id; + WBUFB(buf,26) = (unsigned char)action; + clif_send(buf, 61, bl, AREA); } }else { ShowError("buildin_unitdeadsit: Invalid action.\n"); @@ -11391,12 +11396,24 @@ int run_func(struct script_state *st) * スクリプトの実行メイン部分 *------------------------------------------ */ -int run_script_main(struct script_state *st) +void run_script_main(struct script_state *st) { int c/*,rerun_pos*/; int cmdcount=script_config.check_cmdcount; int gotocount=script_config.check_gotocount; struct script_stack *stack=st->stack; + TBL_PC *sd = (TBL_PC *)map_id2bl(st->rid); + struct script_state *bk_st = NULL; + int bk_npcid = 0; + + if(sd){ + if(sd->st != st){ + bk_st = sd->st; + bk_npcid = sd->npc_id; + } + sd->st = st; + sd->npc_id = st->oid; + } if(st->state == RERUNLINE) { st->state = RUN; @@ -11404,7 +11421,7 @@ int run_script_main(struct script_state *st) if(st->state == GOTO){ st->state = RUN; } - } else { + } else if(st->state != END){ st->state = RUN; } while( st->state == RUN) { @@ -11501,9 +11518,8 @@ int run_script_main(struct script_state *st) break; case END: { - struct map_session_data *sd=st->rid?map_id2sd(st->rid):NULL; st->pos=-1; - if(sd && (sd->npc_id==st->oid || sd->state.using_fake_npc)){ + if(sd){ if(sd->state.using_fake_npc){ clif_clearchar_id(sd->npc_id, 0, sd->fd); sd->state.using_fake_npc = 0; @@ -11513,6 +11529,21 @@ int run_script_main(struct script_state *st) } break; case RERUNLINE: + if(bk_st && sd->st != bk_st && st->sleep.tick <= 0){ + ShowWarning("Unable to restore stack! Double continuation!\n"); + script_free_stack(bk_st->stack); + aFree(bk_st); + } + if(st->sleep.tick > 0) + { //Delay execution + if(sd) + st->sleep.charid = sd->char_id; + else + st->sleep.charid = 0; + st->sleep.timer = add_timer(gettick()+st->sleep.tick, + run_script_timer, st->sleep.charid, (int)st); + linkdb_insert(&sleep_db, (void*)st->oid, st); + } // Do not call function of commands two time! [ Eoe / jA 1094 ] // For example: select "1", "2", callsub(...); // If current script position is changed, callsub will be called two time. @@ -11524,12 +11555,20 @@ int run_script_main(struct script_state *st) } if(st->state == END) { - script_free_stack (st->stack); - st->stack = NULL; - aFree(st); - st = NULL; - return 0; - }else{ + if(sd){ + script_free_stack(sd->st->stack); + aFree(sd->st); + sd->st = bk_st; + sd->npc_id = bk_npcid; + if (sd->state.reg_dirty&2) + intif_saveregistry(sd,2); + if (sd->state.reg_dirty&1) + intif_saveregistry(sd,1); + } else { + script_free_stack (st->stack); + aFree(st); + } + }/*else{ if(st->sleep.tick > 0) { //Delay execution TBL_PC *sd = (TBL_PC *)map_id2bl(st->rid); @@ -11538,41 +11577,33 @@ int run_script_main(struct script_state *st) run_script_timer, st->sleep.charid, (int)st); linkdb_insert(&sleep_db, (void*)st->oid, st); } - } + }*/ - return 1; + return; } /*========================================== * スクリプトの実行 *------------------------------------------ */ -int run_script(struct script_code *rootscript,int pos,int rid,int oid) +void run_script(struct script_code *rootscript,int pos,int rid,int oid) { struct script_state *st; struct map_session_data *sd=NULL; //Variables for backing up the previous script and restore it if needed. [Skotlex] - struct script_code *bck_script = NULL; - struct script_code *bck_scriptroot = NULL; - int bck_scriptstate = 0,bck_npcid = 0; + //struct script_code *bck_script = NULL; + //struct script_code *bck_scriptroot = NULL; + //int bck_scriptstate = 0,bck_npcid = 0; struct script_stack *bck_stack = NULL; if (rootscript == NULL || pos < 0) - return -1; + return; st = aCalloc(sizeof(struct script_state), 1); - if ((sd = map_id2sd(rid)) && sd->stack && sd->npc_scriptroot == rootscript){ - // we have a stack for the same script, should continue exec. - st->script = sd->npc_script; - st->stack = sd->stack; - st->state = sd->npc_scriptstate; - // and clear vars - sd->stack = NULL; - sd->npc_script = NULL; - sd->npc_scriptroot = NULL; - sd->npc_scriptstate = 0; + if ((sd = map_id2sd(rid)) && sd->st && sd->st->scriptroot == rootscript && sd->st->pos == pos){ + st = sd->st; } else { // the script is different, make new script_state and stack st->stack = aMalloc (sizeof(struct script_stack)); @@ -11584,7 +11615,7 @@ int run_script(struct script_code *rootscript,int pos,int rid,int oid) st->state = RUN; st->script = rootscript; - if (sd){ + /*if (sd){ if(sd->stack) { // if there's a sd and a stack - back it up and restore it if possible. bck_script = sd->npc_script; @@ -11595,15 +11626,15 @@ int run_script(struct script_code *rootscript,int pos,int rid,int oid) } bck_npcid = sd->npc_id; sd->npc_id = oid; - } + }*/ } st->pos = pos; st->rid = rid; st->oid = oid; st->sleep.timer = -1; - if(run_script_main(st)){ - if (st->state != END){ + run_script_main(st); + /* if (st->state != END){ pos = st->pos; if(!st->sleep.tick && sd) { // script is not finished, store data in sd. @@ -11636,8 +11667,8 @@ int run_script(struct script_code *rootscript,int pos,int rid,int oid) if (sd->state.reg_dirty&1) intif_saveregistry(sd,1); } - } - return 0; + }*/ + return; } /*========================================== @@ -11683,6 +11714,9 @@ int run_script_timer(int tid, unsigned int tick, int id, int data) } node = node->next; } + if(st->rid && !sd) + st->state = END; + run_script_main(st); return 0; } diff --git a/src/map/script.h b/src/map/script.h index d94348e43..85ddc2d6a 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -64,14 +64,14 @@ struct script_state { }; struct script_code *parse_script(unsigned char *,int); -int run_script(struct script_code *rootscript,int pos,int rid,int oid); +void run_script(struct script_code *rootscript,int pos,int rid,int oid); int set_var(struct map_session_data *sd, char *name, void *val); int conv_num(struct script_state *st,struct script_data *data); char* conv_str(struct script_state *st,struct script_data *data); void setd_sub(struct script_state *st, struct map_session_data *sd, char *varname, int elem, void *value, struct linkdb_node **ref); int run_script_timer(int tid, unsigned int tick, int id, int data); -int run_script_main(struct script_state *st); +void run_script_main(struct script_state *st); struct linkdb_node* script_erase_sleepdb(struct linkdb_node *n); void script_free_code(struct script_code* code); -- cgit v1.2.3-70-g09d2