From ef7452b497d24f6f475d214f1244ab589b304c7c Mon Sep 17 00:00:00 2001 From: zephyrus Date: Sat, 20 Jun 2009 17:56:01 +0000 Subject: - Instancing System (Thanks to Sirius White who did most of the code, with some of my work to implement client side information, some optimizations and bugfixes). Also thanks to contributions from UEAUP team and Orcao. - Fixed a bug on areamobuseskill and changed it to make it as Aegis. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13901 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/script.c | 436 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 408 insertions(+), 28 deletions(-) (limited to 'src/map/script.c') diff --git a/src/map/script.c b/src/map/script.c index 465d6fe85..dd4022220 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -71,6 +71,8 @@ // - remove GETVALUE / SETVALUE // - clean up the set_reg / set_val / setd_sub mess +void crc32_init(); + // @@ -153,8 +155,8 @@ /// Composes the uid of a reference from the id and the index #define reference_uid(id,idx) ( (int32)((((uint32)(id)) & 0x00ffffff) | (((uint32)(idx)) << 24)) ) -#define not_server_variable(prefix) ( (prefix) != '$' && (prefix) != '.') -#define not_array_variable(prefix) ( (prefix) != '$' && (prefix) != '@' && (prefix) != '.' ) +#define not_server_variable(prefix) ( (prefix) != '$' && (prefix) != '.' && (prefix) != '\'') +#define not_array_variable(prefix) ( (prefix) != '$' && (prefix) != '@' && (prefix) != '.' && (prefix) != '\'' ) #define is_string_variable(name) ( (name)[strlen(name) - 1] == '$' ) #define FETCH(n, t) \ @@ -277,6 +279,7 @@ typedef struct script_function { extern script_function buildin_func[]; static struct linkdb_node* sleep_db;// int oid -> struct script_state* +uint32 crctab[256]; /*========================================== * ローカルプロトタイプ宣言 (必要な物のみ) @@ -797,6 +800,8 @@ const char* skip_word(const char* p) ++p; break; case '#':// account variable p += ( p[1] == '#' ? 2 : 1 ); break; + case '\'':// instance variable + ++p; break; case '.':// npc variable p += ( p[1] == '@' ? 2 : 1 ); break; case '$':// global variable @@ -2203,6 +2208,14 @@ void get_val(struct script_state* st, struct script_data* data) data->u.str = (char*)linkdb_search(n, (void*)reference_getuid(data)); } break; + case '\'': + { + struct linkdb_node** n = NULL; + if( st->instance_id ) + n = &instance[st->instance_id].svar; + data->u.str = (char*)linkdb_search(n, (void*)reference_getuid(data)); + } + break; default: data->u.str = pc_readglobalreg_str(sd, name); break; @@ -2257,6 +2270,14 @@ void get_val(struct script_state* st, struct script_data* data) data->u.num = (int)linkdb_search(n, (void*)reference_getuid(data)); } break; + case '\'': + { + struct linkdb_node** n = NULL; + if( st->instance_id ) + n = &instance[st->instance_id].ivar; + data->u.num = (int)linkdb_search(n, (void*)reference_getuid(data)); + } + break; default: data->u.num = pc_readglobalreg(sd, name); break; @@ -2309,6 +2330,17 @@ static int set_reg(struct script_state* st, TBL_PC* sd, int num, const char* nam if (str[0]) linkdb_insert(n, (void*)num, aStrdup(str)); } return 1; + case '\'': { + char *p; + struct linkdb_node** n = NULL; + if( st->instance_id ) + n = &instance[st->instance_id].svar; + + p = (char*)linkdb_erase(n, (void*)num); + if (p) aFree(p); + if( str[0] ) linkdb_insert(n, (void*)num, aStrdup(str)); + } + return 1; default: return pc_setglobalreg_str(sd, name, str); } @@ -2349,6 +2381,18 @@ static int set_reg(struct script_state* st, TBL_PC* sd, int num, const char* nam linkdb_replace(n, (void*)num, (void*)val); } return 1; + case '\'': + { + struct linkdb_node** n = NULL; + if( st->instance_id ) + n = &instance[st->instance_id].ivar; + + if( val == 0 ) + linkdb_erase(n, (void*)num); + else + linkdb_replace(n, (void*)num, (void*)val); + return 1; + } default: return pc_setglobalreg(sd, name, val); } @@ -3098,6 +3142,7 @@ void run_script_main(struct script_state *st) struct script_state *bk_st = NULL; int bk_npcid = 0; struct script_stack *stack=st->stack; + struct npc_data *nd; sd = map_id2sd(st->rid); @@ -3110,6 +3155,10 @@ void run_script_main(struct script_state *st) sd->npc_id = st->oid; } + nd = map_id2nd(st->oid); + if( nd && map[nd->bl.m].instance_id > 0 ) + st->instance_id = map[nd->bl.m].instance_id; + if(st->state == RERUNLINE) { run_func(st); if(st->state == GOTO) @@ -3398,6 +3447,7 @@ int do_final_script() *------------------------------------------*/ int do_init_script() { + crc32_init(); userfunc_db=strdb_alloc(DB_OPT_DUP_KEY,0); scriptlabel_db=strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA),50); @@ -7361,7 +7411,7 @@ BUILDIN_FUNC(guildchangegm) *------------------------------------------*/ BUILDIN_FUNC(monster) { - const char* map = script_getstr(st,2); + const char* mapn = script_getstr(st,2); int x = script_getnum(st,3); int y = script_getnum(st,4); const char* str = script_getstr(st,5); @@ -7385,10 +7435,21 @@ BUILDIN_FUNC(monster) sd = map_id2sd(st->rid); - if( sd && strcmp(map,"this") == 0 ) + if( sd && strcmp(mapn,"this") == 0 ) m = sd->bl.m; else - m = map_mapname2mapid(map); + { + m = map_mapname2mapid(mapn); + if( map[m].instance_map[0] && map[m].instance_id == 0 && st->instance_id ) + { + m = map_instance_mapid2imapid(m, st->instance_id); + if( m < 0 ) + { + ShowError("buildin_monster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn); + return 1; + } + } + } mob_once_spawn(sd,m,x,y,str,class_,amount,event); return 0; @@ -7434,7 +7495,7 @@ BUILDIN_FUNC(getmobdrops) *------------------------------------------*/ BUILDIN_FUNC(areamonster) { - const char* map = script_getstr(st,2); + const char* mapn = script_getstr(st,2); int x0 = script_getnum(st,3); int y0 = script_getnum(st,4); int x1 = script_getnum(st,5); @@ -7455,11 +7516,22 @@ BUILDIN_FUNC(areamonster) sd = map_id2sd(st->rid); - if( sd && strcmp(map,"this") == 0 ) + if( sd && strcmp(mapn,"this") == 0 ) m = sd->bl.m; else - m = map_mapname2mapid(map); - + { + m = map_mapname2mapid(mapn); + if( map[m].instance_map[0] && map[m].instance_id == 0 && st->instance_id ) + { + m = map_instance_mapid2imapid(m, st->instance_id); + if( m < 0 ) + { + ShowError("buildin_areamonster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn); + return 1; + } + } + } + mob_once_spawn_area(sd,m,x0,y0,x1,y1,str,class_,amount,event); return 0; } @@ -7513,6 +7585,9 @@ BUILDIN_FUNC(killmonster) if( (m=map_mapname2mapid(mapname))<0 ) return 0; + if( map[m].instance_map[0] && map[m].instance_id == 0 && st->instance_id && (m=map_instance_mapid2imapid(m, st->instance_id)) < 0 ) + return 0; + if( script_hasdata(st,4) ) { if ( script_getnum(st,4) == 1 ) { map_foreachinmap(buildin_killmonster_sub, m, BL_MOB, event ,allflag); @@ -7551,6 +7626,9 @@ BUILDIN_FUNC(killmonsterall) if( (m=map_mapname2mapid(mapname))<0 ) return 0; + if( map[m].instance_map[0] && map[m].instance_id == 0 && st->instance_id && (m=map_instance_mapid2imapid(m, st->instance_id)) < 0 ) + return 0; + if( script_hasdata(st,3) ) { if ( script_getnum(st,3) == 1 ) { map_foreachinmap(buildin_killmonsterall_sub,m,BL_MOB); @@ -9807,6 +9885,12 @@ BUILDIN_FUNC(mobcount) // Added by RoVeRT script_pushint(st,-1); return 0; } + + if( map[m].instance_map[0] && map[m].instance_id == 0 && st->instance_id && (m=map_instance_mapid2imapid(m, st->instance_id)) < 0 ) + { + script_pushint(st,-1); + return 0; + } script_pushint(st,map_foreachinmap(buildin_mobcount_sub, m, BL_MOB, event)); @@ -13636,6 +13720,288 @@ BUILDIN_FUNC(bg_get_data) return 0; } +/*========================================== + * Instancing Script Commands + *------------------------------------------*/ + +BUILDIN_FUNC(instance_create) +{ + const char *name; + int party_id, name_id; + int res; + + name = script_getstr(st, 2); + party_id = script_getnum(st, 3); + name_id = script_getnum(st, 4); + + res = map_instance_create(party_id, name_id, name); + + if( res == -4 ) // Already exists + { + script_pushint(st, -1); + return 0; + } + else if( res < 0 ) + { + char *err; + switch(res) + { + case -3: err = "No free instances"; break; + case -2: err = "Missing parameter"; break; + case -1: err = "Invalid type"; break; + default: err = "Unknown"; break; + } + ShowError("buildin_instance_create: %s [%d].\n", err, res); + script_pushint(st, -2); + return 0; + } + + script_pushint(st, res); + return 0; +} + +BUILDIN_FUNC(instance_destroy) +{ + int instance_id; + + if( script_hasdata(st, 2) ) + instance_id = script_getnum(st, 2); + else + instance_id = st->instance_id; + + if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) + { + ShowError("buildin_instance_destroy: Trying to destroy invalid instance %d.\n", instance_id); + return 0; + } + + map_instance_destroy(instance_id); + return 0; +} + +BUILDIN_FUNC(instance_attachmap) +{ + const char *name; + int m; + int instance_id; + + instance_id = script_getnum(st, 2); + name = script_getstr(st, 3); + + m = map_instance_map(name, instance_id); + + if( m < 0 ) + { + ShowError("buildin_instance_attachmap: instance creation failed (%s): %d\n", name, m); + script_pushconststr(st, ""); + return 0; + } + + script_pushconststr(st, map[m].name); + + return 0; +} + +BUILDIN_FUNC(instance_detachmap) +{ + const char *name; + int m; + + name = script_getstr(st, 2); + + m = map_mapname2mapid(name); + if( m < 0 ) + { + ShowError("buildin_instance_detachmap: Trying to detach invalid map %s\n", name); + return 0; + } + map_instance_del(m); + + return 0; +} + +BUILDIN_FUNC(instance_attach) +{ + int instance_id; + + instance_id = script_getnum(st, 2); + if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) + return 0; + + st->instance_id = instance_id; + return 0; +} + +BUILDIN_FUNC(instance_id) +{ + int type, instance_id; + struct map_session_data *sd = script_rid2sd(st); + struct party_data *p; + + if( script_hasdata(st, 2) ) + { + type = script_getnum(st, 2); + if( type == 0 ) + instance_id = st->instance_id; + else if( type == 1 && sd && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL ) + instance_id = p->instance_id; + else + instance_id = 0; + } + else + instance_id = st->instance_id; + script_pushint(st, instance_id); + return 0; +} + +BUILDIN_FUNC(instance_set_timeout) +{ + int progress_timeout, idle_timeout; + int instance_id; + + progress_timeout = script_getnum(st, 2); + idle_timeout = script_getnum(st, 3); + + if( script_hasdata(st, 4) ) + instance_id = script_getnum(st, 4); + else + instance_id = st->instance_id; + + if( instance_id > 0 ) + map_instance_set_timeout(instance_id, progress_timeout, idle_timeout); + + return 0; +} + +BUILDIN_FUNC(instance_init) +{ + int instance_id; + + instance_id = script_getnum(st, 2); + + map_instance_init(instance_id); + + return 0; +} + +BUILDIN_FUNC(instance_announce) +{ + const char *str, *color=NULL; + int flag,instance_id,i; + + instance_id=script_getnum(st,2); + str=script_getstr(st,3); + flag=script_getnum(st,4); + if (script_hasdata(st,5)) + color=script_getstr(st,5); + + if( instance_id == 0 ) + instance_id = st->instance_id; + + if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) + return 0; + + for(i=0; ioid); + int instance_id; + + str = script_getstr(st, 2); + if( script_hasdata(st, 3) ) + instance_id = script_getnum(st, 3); + else + instance_id = st->instance_id; + + script_pushconststr(st, map_instance_npcname((char*)str, instance_id)); + return 0; +} + +BUILDIN_FUNC(has_instance) +{ + TBL_PC* sd = script_rid2sd(st); + const char *str; + int m; + + str = script_getstr(st, 2); + + if( (m = map_mapname2mapid(str)) < 0 || (m = map_instance_map2imap(m,sd,0)) < 0 ) + { + script_pushconststr(st, ""); + return 0; + } + + script_pushconststr(st, map[m].name); + return 0; +} + +BUILDIN_FUNC(instance_warpall) +{ + TBL_PC *pl_sd; + int m, i; + const char *mapn; + int x, y; + unsigned short mapindex; + struct party_data *p = NULL; + + if( !st->instance_id ) + return 0; + + mapn = script_getstr(st, 2); + x = script_getnum(st, 3); + y = script_getnum(st, 4); + + if( (m=map_mapname2mapid(mapn)) < 0 || (map[m].instance_map[0] && (m=map_instance_mapid2imapid(m,st->instance_id)) < 0) ) + return 0; + + if( !(p = party_search(instance[st->instance_id].party_id)) ) + return 0; + + mapindex = map_id2index(m); + for( i = 0; i < MAX_PARTY; i++ ) + if( (pl_sd = p->data[i].sd) && map[pl_sd->bl.m].instance_id == st->instance_id ) pc_setpos(pl_sd,mapindex,x,y,3); + + return 0; +} + +void crc32_init() +{ + uint32 crc, poly; + uint32 i, c; + + poly = 0xEDB88320; + + for( i = 0; i < 256; i++ ) + { + crc = i; + for( c = 8; c; c-- ) + { + if( crc & 1 ) + crc = (crc >> 1) ^ poly; + else + crc >>= 1; + } + + crctab[i] = crc; + } +} + +uint32 crc32(char *dat, int len) +{ + uint32 crc, i; + + crc = 0xFFFFFFFF; + for( i=0; i> 8 ) & 0x00FFFFFF) ^ crctab[(crc ^ *dat++) & 0xFF]; + + return (crc ^ 0xFFFFFFFF); +} + /*========================================== * Custom Fonts *------------------------------------------*/ @@ -13695,37 +14061,38 @@ static int buildin_mobuseskill_sub(struct block_list *bl,va_list ap) return 0; } /*========================================== - * areamobuseskill "Map Name",,,,,,"Skill Name"/,,,,,; + * areamobuseskill "Map Name",,,,,"Skill Name"/,,,,,; *------------------------------------------*/ BUILDIN_FUNC(areamobuseskill) { - int m,x1,y1,x2,y2,mobid,skillid,skilllv,casttime,emotion,target; + struct block_list center; + int m,range,mobid,skillid,skilllv,casttime,emotion,target; bool cancel; - if( m = map_mapname2mapid(script_getstr(st,2)) < 0 ) + if( (m = map_mapname2mapid(script_getstr(st,2))) < 0 ) { ShowError("areamobuseskill: invalid map name.\n"); return 0; } - skillid = ( script_isstring(st,8) ? skill_name2id(script_getstr(st,8)) : script_getnum(st,8) ); + if( map[m].instance_map[0] && map[m].instance_id == 0 && st->instance_id && (m=map_instance_mapid2imapid(m, st->instance_id)) < 0 ) + return 0; - skilllv = script_getnum(st,9); - if( skilllv > battle_config.mob_max_skilllvl ) + center.m = m; + center.x = script_getnum(st,3); + center.y = script_getnum(st,4); + range = script_getnum(st,5); + mobid = script_getnum(st,6); + skillid = ( script_isstring(st,7) ? skill_name2id(script_getstr(st,7)) : script_getnum(st,7) ); + if( (skilllv = script_getnum(st,8)) > battle_config.mob_max_skilllvl ) skilllv = battle_config.mob_max_skilllvl; - x1 = script_getnum(st,3); - y1 = script_getnum(st,4); - x2 = script_getnum(st,5); - y2 = script_getnum(st,6); - - mobid = script_getnum(st,7); - casttime = script_getnum(st,10); - cancel = script_getnum(st,11); - emotion = script_getnum(st,12); - target = script_getnum(st,13); - - map_foreachinarea(buildin_mobuseskill_sub, m, x1, y1, x2, y2, BL_MOB, mobid,skillid,skilllv,casttime,cancel,emotion,target); + casttime = script_getnum(st,9); + cancel = script_getnum(st,10); + emotion = script_getnum(st,11); + target = script_getnum(st,12); + + map_foreachinrange(buildin_mobuseskill_sub, ¢er, range, BL_MOB, mobid, skillid, skilllv, casttime, cancel, emotion, target); return 0; } @@ -14088,7 +14455,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(mercenary_set_faith,"ii"), BUILDIN_DEF(readbook,"ii"), BUILDIN_DEF(setfont,"i"), - BUILDIN_DEF(areamobuseskill,"siiiiiviiiii"), + BUILDIN_DEF(areamobuseskill,"siiiiviiiii"), // WoE SE BUILDIN_DEF(agitstart2,""), BUILDIN_DEF(agitend2,""), @@ -14106,5 +14473,18 @@ struct script_function buildin_func[] = { BUILDIN_DEF(bg_get_data,"ii"), BUILDIN_DEF(bg_getareausers,"isiiii"), BUILDIN_DEF(bg_updatescore,"sii"), + // Instancing + BUILDIN_DEF(instance_create,"sii?"), + BUILDIN_DEF(instance_destroy,"?"), + BUILDIN_DEF(instance_attachmap,"is"), + BUILDIN_DEF(instance_detachmap,"is"), + BUILDIN_DEF(instance_init,"i"), + BUILDIN_DEF(instance_announce,"isi*"), + BUILDIN_DEF(instance_attach,"i"), + BUILDIN_DEF(instance_npcname,"s?"), + BUILDIN_DEF(has_instance,"s"), + BUILDIN_DEF(instance_id,"?"), + BUILDIN_DEF(instance_warpall,"sii"), + BUILDIN_DEF(instance_set_timeout,"ii?"), {NULL,NULL,NULL}, }; -- cgit v1.2.3-60-g2f50