From 9f32aa958f86a228290c43544c8b9bbf3f1c2cc0 Mon Sep 17 00:00:00 2001 From: Haru Date: Thu, 7 Nov 2013 19:47:47 +0100 Subject: Extended script constants to support NPC sprite IDs - Added support for constants whose name begins with a number. - Follow-up to 124ab2a1cdb344f24170a4d91f7000ebabf39b40. - Replaced calls to setnpcdisplay with hardcoded numeric IDs to constants. - Thanks to Yommy. Signed-off-by: Haru --- npc/custom/events/disguise.txt | 8 +-- npc/events/gdevent_aru.txt | 14 ++--- npc/quests/newgears/2004_headgears.txt | 2 +- npc/quests/quests_rachel.txt | 6 +- npc/re/quests/quests_brasilis.txt | 2 +- npc/re/quests/quests_mora.txt | 4 +- src/map/script.c | 111 ++++++++++++++++++++++----------- 7 files changed, 94 insertions(+), 53 deletions(-) diff --git a/npc/custom/events/disguise.txt b/npc/custom/events/disguise.txt index 1b46e9b16..a1d8c11c3 100644 --- a/npc/custom/events/disguise.txt +++ b/npc/custom/events/disguise.txt @@ -38,7 +38,7 @@ prontera,160,155,4 script Disguise Event 4_M_NFDEADMAN,{ setnpctimer 0; stopnpctimer; announce "A GM has decided to turn the Disguise Event off. As a result no further prizes will be given.",bc_map | bc_blue; deletepset 1; - setnpcdisplay "Disguise Event",795; + setnpcdisplay "Disguise Event", 4_M_NFDEADMAN; close; } set .EventON,1; set .Timer,1; setnpctimer 0; initnpctimer; @@ -171,7 +171,7 @@ OnTimer10000: OnTimer30000: if (.Timer) end; set .Change,0; - setnpcdisplay "Disguise Event",795; + setnpcdisplay "Disguise Event", 4_M_NFDEADMAN; npctalk "You took too long to guess what I was. Please wait 10 seconds while I disguise again."; specialeffect 725; set $MonsterName$,""; @@ -230,13 +230,13 @@ iCorrect: getitem .Prize,.PrizeAmt; announce strcharinfo(0)+" is correct! I was disguised as: "+$MonsterName$+"",bc_map | bc_blue; if (.RoundCount>=.Rounds) { - setnpcdisplay "Disguise Event",795; + setnpcdisplay "Disguise Event", 4_M_NFDEADMAN; set .RoundCount,0; set .Change,0; set .EventON,0; setnpctimer 0; stopnpctimer; npctalk "Thank you all for playing. That was the last round of the Disguise Event. Come play again later."; end; } - setnpcdisplay "Disguise Event",795; + setnpcdisplay "Disguise Event", 4_M_NFDEADMAN; set .Change,0; setnpctimer 0; end; diff --git a/npc/events/gdevent_aru.txt b/npc/events/gdevent_aru.txt index e0098bf9b..9f1a9617a 100644 --- a/npc/events/gdevent_aru.txt +++ b/npc/events/gdevent_aru.txt @@ -480,19 +480,19 @@ arug_que01,100,81,3 script Pierrot Pier#aru_gd 4_M_PIERROT,{ specialeffect EF_POISONHIT; set .@sprchg_gd,rand(1,5); if (.@sprchg_gd == 1) { - setnpcdisplay "Pierrot Pier#aru_gd",950; + setnpcdisplay "Pierrot Pier#aru_gd", 4_GHOSTRING; } else if (.@sprchg_gd == 2) { - setnpcdisplay "Pierrot Pier#aru_gd",715; + setnpcdisplay "Pierrot Pier#aru_gd", 4_M_PIERROT; } else if (.@sprchg_gd == 3) { - setnpcdisplay "Pierrot Pier#aru_gd",714; + setnpcdisplay "Pierrot Pier#aru_gd", 4_F_06; } else if (.@sprchg_gd == 4) { - setnpcdisplay "Pierrot Pier#aru_gd",785; + setnpcdisplay "Pierrot Pier#aru_gd", 4_M_UMDANCEKID2; } else { - setnpcdisplay "Pierrot Pier#aru_gd",876; + setnpcdisplay "Pierrot Pier#aru_gd", 4_CAT; } if (checkweight(1201,1) == 0) { mes "- Wait!! -"; @@ -506,7 +506,7 @@ arug_que01,100,81,3 script Pierrot Pier#aru_gd 4_M_PIERROT,{ if ($@gdeventv_a2 == 0) { set .@que_2143,checkquest(2143,PLAYTIME); if (.@que_2143 == -1) { - setnpcdisplay "Pierrot Pier#aru_gd",715; + setnpcdisplay "Pierrot Pier#aru_gd", 4_M_PIERROT; mes "A lonely clown is juggling."; next; mes "When looked at closely, the clown is just a puppet that looks like a human."; @@ -845,7 +845,7 @@ arug_que01,100,81,3 script Pierrot Pier#aru_gd 4_M_PIERROT,{ } else { if ($@gdeventv_a2 == 0) { - setnpcdisplay "Pierrot Pier#aru_gd",715; + setnpcdisplay "Pierrot Pier#aru_gd", 4_M_PIERROT; mes "A lonely clown is juggling."; next; mes "When looked at closely, the clown is just a puppet that looks like a human."; diff --git a/npc/quests/newgears/2004_headgears.txt b/npc/quests/newgears/2004_headgears.txt index 1cfa2bc03..a6638d6a7 100644 --- a/npc/quests/newgears/2004_headgears.txt +++ b/npc/quests/newgears/2004_headgears.txt @@ -2034,7 +2034,7 @@ alde_alche,88,180,0 script Muscle Man#Alarm Mask 4_M_ALCHE_A,{ OnTimer4000: specialeffect EF_FLASHER; - setnpcdisplay "Muscle Man#Alarm Mask", 748; + setnpcdisplay "Muscle Man#Alarm Mask", 4_M_ALCHE_A; disablenpc " #Alarm Mask Man1"; disablenpc " #Alarm Mask Man2"; disablenpc " #Alarm Mask Man3"; diff --git a/npc/quests/quests_rachel.txt b/npc/quests/quests_rachel.txt index cf2e62dcb..fc96796bb 100644 --- a/npc/quests/quests_rachel.txt +++ b/npc/quests/quests_rachel.txt @@ -3131,7 +3131,7 @@ ice_dun02,120,105,3 script Man Stuck in Ice#cave 4_M_FROZEN1,5,5,{ mes "^3355FF*Pzzzzz*"; mes "*CRASH!*^000000"; next; - setnpcdisplay "Man Stuck in Ice#cave",937; + setnpcdisplay "Man Stuck in Ice#cave", 4_M_ARUNA_NFM1; emotion e_gasp; mes "[Maheo]"; mes "Finally...!"; @@ -3193,7 +3193,7 @@ ice_dun02,120,105,3 script Man Stuck in Ice#cave 4_M_FROZEN1,5,5,{ getitem 7574,4; //Ice_Particle close2; cutin "",255; - setnpcdisplay "Man Stuck in Ice#cave",924; + setnpcdisplay "Man Stuck in Ice#cave", 4_M_FROZEN1; end; } @@ -7495,4 +7495,4 @@ OnTouch: //= 2.7 Corrected overlaping warp coordinates. [L0ne_W0lf] //= 2.8 Replaced effect numerics with constants. [L0ne_W0lf] //= 2.9 Replaced effect numerics with constants. [Samuray22] -//============================================================ \ No newline at end of file +//============================================================ diff --git a/npc/re/quests/quests_brasilis.txt b/npc/re/quests/quests_brasilis.txt index 306a19cdb..5276fafe5 100644 --- a/npc/re/quests/quests_brasilis.txt +++ b/npc/re/quests/quests_brasilis.txt @@ -814,7 +814,7 @@ brasilis,56,224,7 script Mage Paje#bra 4_M_BIBI,{ mes "[Mage Paje]"; mes "Abracadabra~"; specialeffect EF_POISONHIT,AREA,"Poring#bra"; - setarray .@display[0],800,876,909; + setarray .@display[0], 4_NFCOCK, 4_CAT, 4_PORING; setnpcdisplay "Poring#bra",.@display[rand(3)]; if (brazil_gua != 5) close; next; diff --git a/npc/re/quests/quests_mora.txt b/npc/re/quests/quests_mora.txt index 9acebd207..1d7e9bbd0 100644 --- a/npc/re/quests/quests_mora.txt +++ b/npc/re/quests/quests_mora.txt @@ -2461,14 +2461,14 @@ bif_fild01,132,338,3 script Lope#pa 4_M_FAIRYSOLDIER2,2,2,{ } end; OnEnable: - setnpcdisplay "Lope#pa",999; + setnpcdisplay "Lope#pa", 4_M_MUT1; end; OnDisable: disablenpc "Lope#pa"; initnpctimer; end; OnReset: - setnpcdisplay "Lope#pa",461; + setnpcdisplay "Lope#pa", 4_M_FAIRYSOLDIER2; enablenpc "Lope#pa"; end; OnTimer2000: diff --git a/src/map/script.c b/src/map/script.c index 7a2f1f24b..b87020253 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -858,50 +858,87 @@ const char* parse_variable(const char* p) { return p; } +/* + * Checks whether the gives string is a number literal + * + * Mainly necessary to differentiate between number literals and NPC name + * constants, since several of those start with a digit. + * + * All this does is to check if the string begins with an optional + or - sign, + * followed by a hexadecimal or decimal number literal literal and is NOT + * followed by a underscore or letter. + * + * @param p Pointer to the string to check + * @return Whether the string is a number literal + */ +bool is_number(const char *p) { + const char *np; + if (!p) + return false; + if (*p == '-' || *p == '+') + p++; + np = p; + if (*p == '0' && p[1] == 'x') { + p+=2; + np = p; + // Hexadecimal + while (ISXDIGIT(*np)) + np++; + } else { + // Decimal + while (ISDIGIT(*np)) + np++; + } + if (p != np && *np != '_' && !ISALPHA(*np)) // At least one digit, and next isn't a letter or _ + return true; + return false; +} + /*========================================== * Analysis section *------------------------------------------*/ -const char* parse_simpleexpr(const char *p) -{ - long long i; +const char* parse_simpleexpr(const char *p) { + int i; p=script->skip_space(p); if(*p==';' || *p==',') disp_error_message("parse_simpleexpr: unexpected end of expression",p); - if(*p=='('){ + if(*p=='(') { if( (i=script->syntax.curly_count-1) >= 0 && script->syntax.curly[i].type == TYPE_ARGLIST ) ++script->syntax.curly[i].count; p=script->parse_subexpr(p+1,-1); p=script->skip_space(p); - if( (i=script->syntax.curly_count-1) >= 0 && script->syntax.curly[i].type == TYPE_ARGLIST && - script->syntax.curly[i].flag == ARGLIST_UNDEFINED && --script->syntax.curly[i].count == 0 - ){ - if( *p == ',' ){ + if( (i=script->syntax.curly_count-1) >= 0 && script->syntax.curly[i].type == TYPE_ARGLIST + && script->syntax.curly[i].flag == ARGLIST_UNDEFINED && --script->syntax.curly[i].count == 0 + ) { + if( *p == ',' ) { script->syntax.curly[i].flag = ARGLIST_PAREN; return p; - } else + } else { script->syntax.curly[i].flag = ARGLIST_NO_PAREN; + } } if( *p != ')' ) disp_error_message("parse_simpleexpr: unmatched ')'",p); ++p; - } else if(ISDIGIT(*p) || ((*p=='-' || *p=='+') && ISDIGIT(p[1]))){ + } else if(is_number(p)) { char *np; - while(*p == '0' && ISDIGIT(p[1])) p++; - i=strtoll(p,&np,0); - if( i < INT_MIN ) { - i = INT_MIN; + long long lli; + while(*p == '0' && ISDIGIT(p[1])) p++; // Skip leading zeros, we don't support octal literals + lli=strtoll(p,&np,0); + if( lli < INT_MIN ) { + lli = INT_MIN; script->disp_warning_message("parse_simpleexpr: underflow detected, capping value to INT_MIN",p); - } else if( i > INT_MAX ) { - i = INT_MAX; + } else if( lli > INT_MAX ) { + lli = INT_MAX; script->disp_warning_message("parse_simpleexpr: overflow detected, capping value to INT_MAX",p); } - script->addi((int)i); + script->addi((int)lli); // Cast is safe, as it's already been checked for overflows p=np; - } else if(*p=='"'){ + } else if(*p=='"') { script->addc(C_STR); p++; - while( *p && *p != '"' ){ + while( *p && *p != '"' ) { if( (unsigned char)p[-1] <= 0x7e && *p == '\\' ) { char buf[8]; size_t len = sv->skip_escaped_c(p) - p; @@ -911,8 +948,9 @@ const char* parse_simpleexpr(const char *p) p += len; script->addb(*buf); continue; - } else if( *p == '\n' ) + } else if( *p == '\n' ) { disp_error_message("parse_simpleexpr: unexpected newline @ string",p); + } script->addb(*p++); } if(!*p) @@ -928,24 +966,24 @@ const char* parse_simpleexpr(const char *p) disp_error_message("parse_simpleexpr: unexpected character",p); l=script->add_word(p); - if( script->str_data[l].type == C_FUNC || script->str_data[l].type == C_USERFUNC || script->str_data[l].type == C_USERFUNC_POS) + if( script->str_data[l].type == C_FUNC || script->str_data[l].type == C_USERFUNC || script->str_data[l].type == C_USERFUNC_POS) { return script->parse_callfunc(p,1,0); #ifdef SCRIPT_CALLFUNC_CHECK - else { + } else { const char* name = script->get_str(l); if( strdb_get(script->userfunc_db,name) != NULL ) { return script->parse_callfunc(p,1,1); } - } #endif + } - if( (pv = script->parse_variable(p)) ) - {// successfully processed a variable assignment + if( (pv = script->parse_variable(p)) ) { + // successfully processed a variable assignment return pv; } p=script->skip_word(p); - if( *p == '[' ){ + if( *p == '[' ) { // array(name[i] => getelementofarray(name,i) ) script->addl(script->buildin_getelementofarray_ref); script->addc(C_ARG); @@ -957,8 +995,9 @@ const char* parse_simpleexpr(const char *p) disp_error_message("parse_simpleexpr: unmatched ']'",p); ++p; script->addc(C_FUNC); - }else + } else { script->addl(l); + } } @@ -1229,8 +1268,16 @@ const char* parse_syntax(const char* p) disp_error_message("parse_syntax: expect space ' '",p); } // check whether case label is integer or not - v = strtol(p,&np,0); - if(np == p) { //Check for constants + if(is_number(p)) { + //Numeric value + v = strtol(p,&np,0); + if((*p == '-' || *p == '+') && ISDIGIT(p[1])) // pre-skip because '-' can not skip_word + p++; + p = script->skip_word(p); + if(np != p) + disp_error_message("parse_syntax: 'case' label is not an integer",np); + } else { + //Check for constants p2 = script->skip_word(p); v = p2-p; // length of word at p2 memcpy(label,p,v); @@ -1238,12 +1285,6 @@ const char* parse_syntax(const char* p) if( !script->get_constant(label, &v) ) disp_error_message("parse_syntax: 'case' label is not an integer",p); p = script->skip_word(p); - } else { //Numeric value - if((*p == '-' || *p == '+') && ISDIGIT(p[1])) // pre-skip because '-' can not skip_word - p++; - p = script->skip_word(p); - if(np != p) - disp_error_message("parse_syntax: 'case' label is not an integer",np); } p = script->skip_space(p); if(*p != ':') -- cgit v1.2.3-60-g2f50