diff options
author | Lance <Lance@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2006-06-29 08:47:14 +0000 |
---|---|---|
committer | Lance <Lance@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2006-06-29 08:47:14 +0000 |
commit | b098c36a440f8052ab3c548420920bad92c7d872 (patch) | |
tree | c6a8382322944e6951ea748ecb870230274d5632 /src/map | |
parent | 19ae14bb0f371886508be6d51c1b851e03ba65e1 (diff) | |
download | hercules-b098c36a440f8052ab3c548420920bad92c7d872.tar.gz hercules-b098c36a440f8052ab3c548420920bad92c7d872.tar.bz2 hercules-b098c36a440f8052ab3c548420920bad92c7d872.tar.xz hercules-b098c36a440f8052ab3c548420920bad92c7d872.zip |
* [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
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/clif.h | 1 | ||||
-rw-r--r-- | src/map/map.c | 4 | ||||
-rw-r--r-- | src/map/map.h | 4 | ||||
-rw-r--r-- | src/map/mob.c | 21 | ||||
-rw-r--r-- | src/map/npc.c | 12 | ||||
-rw-r--r-- | src/map/pc.c | 13 | ||||
-rw-r--r-- | src/map/script.c | 280 | ||||
-rw-r--r-- | src/map/script.h | 4 |
8 files changed, 185 insertions, 154 deletions
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);
|