summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/clif.c3
-rw-r--r--src/map/script.c265
2 files changed, 267 insertions, 1 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index ffc447b95..0a4200396 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9177,7 +9177,8 @@ void clif_parse_ChangeCart(int fd,struct map_session_data *sd)
if( (type == 5 && sd->status.base_level > 90) ||
(type == 4 && sd->status.base_level > 80) ||
(type == 3 && sd->status.base_level > 65) ||
- (type == 2 && sd->status.base_level > 40) )
+ (type == 2 && sd->status.base_level > 40) ||
+ (type == 1))
pc_setcart(sd,type);
}
diff --git a/src/map/script.c b/src/map/script.c
index 2f2d3b5a4..da8a3cf55 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -8196,6 +8196,41 @@ BUILDIN_FUNC(debugmes)
}
/*==========================================
+ * 天の声アナウンス(特定マップ)
+ *------------------------------------------*/
+static int buildin_mapannounce_sub(struct block_list *bl,va_list ap)
+{
+ char *str, *color;
+ int len,flag;
+ str=va_arg(ap,char *);
+ len=va_arg(ap,int);
+ flag=va_arg(ap,int);
+ color=va_arg(ap,char *);
+ if (color)
+ clif_announce(bl,str,len, strtol(color, (char **)NULL, 0), flag|3);
+ else
+ clif_GMmessage(bl,str,len,flag|3);
+ return 0;
+}
+BUILDIN_FUNC(mapannounce)
+{
+ const char *mapname,*str, *color=NULL;
+ int flag,m;
+
+ mapname=script_getstr(st,2);
+ str=script_getstr(st,3);
+ flag=script_getnum(st,4);
+ if (script_hasdata(st,5))
+ color=script_getstr(st,5);
+
+ if( (m=map_mapname2mapid(mapname))<0 )
+ return 0;
+
+ map_foreachinmap(buildin_mapannounce_sub,
+ m, BL_PC, str,strlen(str)+1,flag&0x10, color);
+ return 0;
+}
+/*==========================================
*捕獲アイテム使用
*------------------------------------------*/
BUILDIN_FUNC(catchpet)
@@ -10766,6 +10801,236 @@ BUILDIN_FUNC(jump_zero)
return 0;
}
+BUILDIN_FUNC(select)
+{
+ int i;
+ const char* text;
+ TBL_PC* sd;
+
+ sd = script_rid2sd(st);
+ if( sd == NULL )
+ return 0;
+
+ if( sd->state.menu_or_input == 0 )
+ {
+ struct StringBuf buf;
+
+ StringBuf_Init(&buf);
+ sd->npc_menu = 0;
+ for( i = 2; i <= script_lastdata(st); ++i )
+ {
+ text = script_getstr(st, i);
+ if( sd->npc_menu > 0 )
+ StringBuf_AppendStr(&buf, ":");
+ StringBuf_AppendStr(&buf, text);
+ sd->npc_menu += menu_countoptions(text, 0, NULL);
+ }
+
+ st->state = RERUNLINE;
+ sd->state.menu_or_input = 1;
+ clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf));
+ StringBuf_Destroy(&buf);
+ }
+ else if( sd->npc_menu == 0xff )
+ {// Cancel was pressed
+ sd->state.menu_or_input = 0;
+ st->state = END;
+ }
+ else
+ {// return selected option
+ int menu = 0;
+
+ sd->state.menu_or_input = 0;
+ for( i = 2; i <= script_lastdata(st); ++i )
+ {
+ text = script_getstr(st, i);
+ sd->npc_menu -= menu_countoptions(text, sd->npc_menu, &menu);
+ if( sd->npc_menu <= 0 )
+ break;// entry found
+ }
+ pc_setreg(sd, add_str("@menu"), menu);
+ script_pushint(st, menu);
+ }
+ return 0;
+}
+
+/*==========================================
+ * 配列対応select()
+ *------------------------------------------
+ * arrayselect( <source> [, <count>] )
+ * @return : 選ばれた項目に対応する配列のindex
+ */
+int buildin_arrayselect( struct script_state *st )
+{
+ // 第1引数がsource
+ struct script_data *source = &st->stack->stack_data[ st->start + 2 ];
+ // bit:24-31 ; 配列の最初のindex(?)
+ int num = source->u.num, max;
+ // loop用
+ int begin, i = 0;
+ // 配列変数の名前
+ char *name = str_buf + str_data[ ARRAYIDX_GETDATA( num ) ].str;
+ char postfix = name[ strlen( name ) - 1 ];
+
+ struct map_session_data *sd = script_rid2sd( st );
+
+ nullpo_retr( 0, sd );
+
+ if( !check_arrayscope( name[ 0 ], "buildin_arrayselect" ) ) return 0;
+
+ // 配列の最大個数
+ max = getarraysize( st, num, postfix, source->ref );
+ // loopの始点
+ begin = ARRAYIDX_GETIDX( num );
+
+// printf( "num = %d, max = %d, begin = %d, end = %d, count = %d\n", num, max, begin, end, count );
+// printf( "st->start = %d, st->end = %d\n", st->start, st->end );
+
+ // menuもinput windowも表示中ではない
+ if( sd->state.menu_or_input == 0 )
+ {
+ char *buf;
+ size_t len;
+ int count, end;
+
+ // arrayselect()をもう一度実行することでclientからの結果を解析する
+ st->state = RERUNLINE;
+ // set flag
+ sd->state.menu_or_input = 1;
+
+ // 第二引数があるか?
+ if( st->end > st->start + 3 )
+ {
+ count = conv_num( st, &st->stack->stack_data[ st->start + 3 ] );
+ }
+ else
+ {
+ count = -1;
+ }
+
+ // loopの終点
+ end = count != -1 ? count + begin : max;
+
+ // menu用packed文字列に必要な文字列長を計算
+ len = 0;
+ for( i = begin; i < end; ++i )
+ {
+ // 配列要素の値を取得
+ void *elem = get_val2( st, ARRAYIDX_PACK( i, num ), source->ref );
+
+ // str?
+ if( postfix == '$' )
+ {
+ if( elem ) len += strlen( ( char * ) elem );
+ }
+ // int
+ else
+ {
+ // 符号を考慮して1byte余計に確保
+ len += ( size_t )log10( abs( ( int ) elem ) ) + 2;
+ }
+
+ // separator(:)
+ ++len;
+ }
+
+ buf = ( char * ) aCalloc( len + 1, sizeof( char ) );
+ buf[ 0 ] = '\0';
+
+ for( i = begin; i < end; ++i )
+ {
+ void *elem = get_val2( st, ARRAYIDX_PACK( i, num ), source->ref );
+
+ // str?
+ if( postfix == '$' )
+ {
+ if( elem )
+ {
+ strcat( buf, ( char * ) elem );
+ }
+ }
+ else
+ {
+ char temp[ 16 ];
+ snprintf( temp, 16, "%d", ( int ) elem );
+ strcat( buf, temp );
+ }
+
+ strcat( buf, ":" );
+ }
+
+ // show the menu
+ clif_scriptmenu( sd, st->oid, buf );
+
+ // release
+ free( buf );
+ }
+ // 2度目の実行
+ else
+ {
+ // set flag
+ sd->state.menu_or_input = 0;
+
+ // canceled or invalid responce
+ if( sd->npc_menu == 0xff || !( sd->npc_menu > 0 ) )
+ {
+ st->state = END;
+ }
+ // valid responce
+ else
+ {
+ int selected = sd->npc_menu;
+
+ // 長さ0の文字列のメニューはclientには表示されないので, 値を補正する
+ // ex)
+ // 配列 { "あ", "い", "", "え", "お", } で npc_menu が 4 のとき,
+ // 実際に選ばれたのは "え" ではなくて "お" である.
+ // -> 4 を 5 に修正
+ if( postfix == '$' )
+ {
+ int cnt_len0 = 0, cnt_rest = selected;
+
+ // 長さ0でない文字列がselected個現れるまでに, いくつ長さ0の文字列があるか?
+ for( i = begin; cnt_rest > 0; ++i )
+ {
+ void *elem = get_val2( st, ARRAYIDX_PACK( i, num ), source->ref );
+
+ if( !elem || strlen( ( char * ) elem ) == 0 )
+ {
+ ++cnt_len0;
+ }
+ else
+ {
+ --cnt_rest;
+ }
+ }
+
+ selected += cnt_len0;
+ }
+
+ // fix beginning offset & returned value range (1~)
+ selected += begin - 1;
+
+ // overflow?
+ if( selected > max - 1 )
+ {
+ st->state = END;
+ return 0;
+ }
+
+ // return
+ pc_setreg( sd, add_str( "@menu" ), selected );
+ push_val( st->stack, C_INT, selected );
+ }
+ }
+
+ return 0;
+}
+
+#undef ARRAYIDX_GETIDX
+#undef ARRAYIDX_GETDATA
+#undef ARRAYIDX_PACK
+
/*==========================================
* GetMapMobs
returns mob counts on a set map: