summaryrefslogtreecommitdiff
path: root/src/map/script.c
diff options
context:
space:
mode:
authorzephyrus <zephyrus@54d463be-8e91-2dee-dedb-b68131a5f0ec>2009-06-20 17:56:01 +0000
committerzephyrus <zephyrus@54d463be-8e91-2dee-dedb-b68131a5f0ec>2009-06-20 17:56:01 +0000
commitef7452b497d24f6f475d214f1244ab589b304c7c (patch)
treec24bedb42ecf633efada0475417d7f0592d2e1ab /src/map/script.c
parent6f700c626efe9253ce77865667d1d5e598daab65 (diff)
downloadhercules-ef7452b497d24f6f475d214f1244ab589b304c7c.tar.gz
hercules-ef7452b497d24f6f475d214f1244ab589b304c7c.tar.bz2
hercules-ef7452b497d24f6f475d214f1244ab589b304c7c.tar.xz
hercules-ef7452b497d24f6f475d214f1244ab589b304c7c.zip
- 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
Diffstat (limited to 'src/map/script.c')
-rw-r--r--src/map/script.c436
1 files changed, 408 insertions, 28 deletions
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));
@@ -13637,6 +13721,288 @@ BUILDIN_FUNC(bg_get_data)
}
/*==========================================
+ * 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; i<instance[instance_id].num_map; i++)
+ map_foreachinmap(buildin_mapannounce_sub, instance[instance_id].map[i], BL_PC, str,strlen(str)+1,flag&0x10, color);
+ return 0;
+}
+
+BUILDIN_FUNC(instance_npcname)
+{
+ const char *str;
+ struct npc_data *nd = map_id2nd(st->oid);
+ 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<len; i++ )
+ crc = ((crc >> 8 ) & 0x00FFFFFF) ^ crctab[(crc ^ *dat++) & 0xFF];
+
+ return (crc ^ 0xFFFFFFFF);
+}
+
+/*==========================================
* Custom Fonts
*------------------------------------------*/
BUILDIN_FUNC(setfont)
@@ -13695,37 +14061,38 @@ static int buildin_mobuseskill_sub(struct block_list *bl,va_list ap)
return 0;
}
/*==========================================
- * areamobuseskill "Map Name",<x1>,<y1>,<x2>,<y2>,<Mob ID>,"Skill Name"/<Skill ID>,<Skill Lv>,<Cast Time>,<Cancelable>,<Emotion>,<Target Type>;
+ * areamobuseskill "Map Name",<x>,<y>,<range>,<Mob ID>,"Skill Name"/<Skill ID>,<Skill Lv>,<Cast Time>,<Cancelable>,<Emotion>,<Target Type>;
*------------------------------------------*/
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, &center, 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},
};