diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/HPMmap.c | 44 | ||||
-rw-r--r-- | src/map/HPMmap.h | 2 | ||||
-rw-r--r-- | src/map/battle.c | 12 | ||||
-rw-r--r-- | src/map/battle.h | 3 | ||||
-rw-r--r-- | src/map/chrif.c | 7 | ||||
-rw-r--r-- | src/map/clif.c | 5 | ||||
-rw-r--r-- | src/map/itemdb.h | 1 | ||||
-rw-r--r-- | src/map/log.h | 2 | ||||
-rw-r--r-- | src/map/map.c | 7 | ||||
-rw-r--r-- | src/map/map.h | 7 | ||||
-rw-r--r-- | src/map/mob.c | 31 | ||||
-rw-r--r-- | src/map/mob.h | 2 | ||||
-rw-r--r-- | src/map/npc.c | 21 | ||||
-rw-r--r-- | src/map/pc.c | 8 | ||||
-rw-r--r-- | src/map/script.c | 196 | ||||
-rw-r--r-- | src/map/script.h | 8 | ||||
-rw-r--r-- | src/map/skill.c | 34 | ||||
-rw-r--r-- | src/map/status.c | 28 | ||||
-rw-r--r-- | src/map/status.h | 8 | ||||
-rw-r--r-- | src/map/unit.c | 44 |
20 files changed, 236 insertions, 234 deletions
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c index cb8c979c6..a0701ae45 100644 --- a/src/map/HPMmap.c +++ b/src/map/HPMmap.c @@ -74,11 +74,6 @@ struct HPM_atcommand_list { struct HPM_atcommand_list *atcommand_list = NULL; unsigned int atcommand_list_items = 0; -/** - * (char*) data name -> (unsigned int) HPMDataCheck[] index - **/ -DBMap *datacheck_db; - bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) { /* record address */ switch( type ) { @@ -147,29 +142,6 @@ void HPM_map_atcommands(void) { } /** - * Called by HPM->DataCheck on a plugins incoming data, ensures data structs in use are matching! - **/ -bool HPM_map_DataCheck (struct s_HPMDataCheck *src, unsigned int size, char *name) { - unsigned int i, j; - - for(i = 0; i < size; i++) { - - if( !strdb_exists(datacheck_db, src[i].name) ) { - ShowError("HPMDataCheck:%s: '%s' was not found\n",name,src[i].name); - return false; - } else { - j = strdb_uiget(datacheck_db, src[i].name);/* not double lookup; exists sets cache to found data */ - if( src[i].size != HPMDataCheck[j].size ) { - ShowWarning("HPMDataCheck:%s: '%s' size mismatch %u != %u\n",name,src[i].name,src[i].size,HPMDataCheck[j].size); - return false; - } - } - } - - return true; -} - -/** * Adds a new group permission to the HPM-provided list **/ void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned int *mask) { @@ -183,17 +155,9 @@ void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned in } void HPM_map_do_init(void) { - unsigned int i; - - /** - * Populates datacheck_db for easy lookup later on - **/ - datacheck_db = strdb_alloc(DB_OPT_BASE,0); - - for(i = 0; i < HPMDataCheckLen; i++) { - strdb_uiput(datacheck_db, HPMDataCheck[i].name, i); - } - + HPM->load_sub = HPM_map_plugin_load_sub; + HPM->grabHPDataSub = HPM_map_grabHPData; + HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer); } void HPM_map_do_final(void) { @@ -211,5 +175,5 @@ void HPM_map_do_final(void) { if( pcg->HPMpermissions ) aFree(pcg->HPMpermissions); - db_destroy(datacheck_db); + HPM->datacheck_final(); } diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h index 99c4224ff..fa2f625c0 100644 --- a/src/map/HPMmap.h +++ b/src/map/HPMmap.h @@ -22,8 +22,6 @@ void HPM_map_do_final(void); void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned int *mask); -bool HPM_map_DataCheck(struct s_HPMDataCheck *src, unsigned int size, char *name); - void HPM_map_do_init(void); #endif /* MAP_HPMMAP_H */ diff --git a/src/map/battle.c b/src/map/battle.c index 8aeb22fc2..40ef15191 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -5812,6 +5812,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if( --(sc->data[SC_SPELLFIST]->val1) >= 0 ){ struct Damage ad = battle->calc_attack(BF_MAGIC,src,target,sc->data[SC_SPELLFIST]->val3,sc->data[SC_SPELLFIST]->val4,flag|BF_SHORT); wd.damage = ad.damage; + damage_div_fix(wd.damage, wd.div_); }else status_change_end(src,SC_SPELLFIST,INVALID_TIMER); } @@ -6837,8 +6838,8 @@ static const struct battle_data { { "song_timer_reset", &battle_config.song_timer_reset, 0, 0, 1, }, { "snap_dodge", &battle_config.snap_dodge, 0, 0, 1, }, { "monster_chase_refresh", &battle_config.mob_chase_refresh, 1, 0, 30, }, - { "icewall_walk_block", &battle_config.icewall_walk_block, 75, 0, 255, }, - { "feature.roulette", &battle_config.feature_roulette, 1, 0, 1, } + { "mob_icewall_walk_block", &battle_config.mob_icewall_walk_block, 75, 0, 255, }, + { "boss_icewall_walk_block", &battle_config.boss_icewall_walk_block, 0, 0, 255, }, }; #ifndef STATS_OPT_OUT /** @@ -7089,13 +7090,6 @@ void battle_adjust_conf(void) { battle_config.feature_banking = 0; } #endif - -#if PACKETVER < 20141022 - if( battle_config.feature_roulette ) { - ShowWarning("conf/battle/feature.conf roulette is enabled but it requires PACKETVER 2014-10-22 or newer, disabling...\n"); - battle_config.feature_roulette = 0; - } -#endif #if PACKETVER > 20120000 && PACKETVER < 20130515 /* exact date (when it started) not known */ if( battle_config.feature_auction == 1 ) { diff --git a/src/map/battle.h b/src/map/battle.h index 8164153da..7633691a8 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -452,7 +452,8 @@ struct Battle_Config { int mob_size_influence; // Enable modifications on earned experience, drop rates and monster status depending on monster size. [mkbu95] int bowling_bash_area; int mob_chase_refresh; //How often a monster should refresh its chase [Playtester] - int icewall_walk_block; //How long a monster should stay trapped in icewall [Playtester] + int mob_icewall_walk_block; //How a normal monster should be trapped in icewall [Playtester] + int boss_icewall_walk_block; //How a boss monster should be trapped in icewall [Playtester] /** Hercules **/ int skill_trap_type; diff --git a/src/map/chrif.c b/src/map/chrif.c index 34e92bee0..c78b34309 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -1125,9 +1125,12 @@ bool chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of th continue; if (sc->data[i]->timer != INVALID_TIMER) { td = timer->get(sc->data[i]->timer); - if (td == NULL || td->func != status->change_timer || DIFF_TICK(td->tick,tick) < 0) + if (td == NULL || td->func != status->change_timer) continue; - data.tick = DIFF_TICK32(td->tick,tick); //Duration that is left before ending. + if (DIFF_TICK32(td->tick,tick) > 0) + data.tick = DIFF_TICK32(td->tick,tick); //Duration that is left before ending. + else + data.tick = 0; //Negative tick does not necessarily mean that sc has expired } else data.tick = -1; //Infinite duration data.type = i; diff --git a/src/map/clif.c b/src/map/clif.c index 73fc387e3..37cd03119 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -2705,14 +2705,15 @@ void read_channels_config(void) { } else { unsigned char d = 0, dlen = strlen(irc_server); char server[40]; - + if (dlen > 39) + dlen = 39; memset(server, '\0', sizeof(server)); for(d = 0; d < dlen; d++) { if(irc_server[d] == ':') { memcpy(server, irc_server, d); safestrncpy(hChSys.irc_server, server, 40); - memcpy(server, &irc_server[d+1], dlen); + memcpy(server, &irc_server[d+1], dlen - d - 1); hChSys.irc_server_port = atoi(server); break; } diff --git a/src/map/itemdb.h b/src/map/itemdb.h index e8b8588e9..8d8cfd7c2 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -43,6 +43,7 @@ enum item_itemid { ITEMID_BLUE_POTION = 505, ITEMID_APPLE = 512, ITEMID_HOLY_WATER = 523, + ITEMID_PUMPKIN = 535, ITEMID_RED_SLIM_POTION = 545, ITEMID_YELLOW_SLIM_POTION = 546, ITEMID_WHITE_SLIM_POTION = 547, diff --git a/src/map/log.h b/src/map/log.h index 6ab142f87..40dbf6761 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -98,7 +98,7 @@ struct log_interface { char db_ip[32]; int db_port; char db_id[32]; - char db_pw[32]; + char db_pw[100]; char db_name[32]; Sql* mysql_handle; /* */ diff --git a/src/map/map.c b/src/map/map.c index 5fa8779eb..bb3b17822 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -2586,6 +2586,8 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) { return (cell.nochat); case CELL_CHKICEWALL: return (cell.icewall); + case CELL_CHKNOICEWALL: + return (cell.noicewall); // special checks case CELL_CHKPASS: @@ -2645,6 +2647,8 @@ void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) { case CELL_NOVENDING: map->list[m].cell[j].novending = flag; break; case CELL_NOCHAT: map->list[m].cell[j].nochat = flag; break; case CELL_ICEWALL: map->list[m].cell[j].icewall = flag; break; + case CELL_NOICEWALL: map->list[m].cell[j].noicewall = flag; break; + default: ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell); break; @@ -5610,10 +5614,7 @@ int do_init(int argc, char *argv[]) map_load_defaults(); HPM_map_do_init(); - HPM->DataCheck = HPM_map_DataCheck; - HPM->load_sub = HPM_map_plugin_load_sub; HPM->symbol_defaults_sub = map_hp_symbols; - HPM->grabHPDataSub = HPM_map_grabHPData; for( i = 1; i < argc; i++ ) { const char* arg = argv[i]; if( strcmp(arg, "--load-plugin") == 0 ) { diff --git a/src/map/map.h b/src/map/map.h index 751fef67e..5468016b4 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -444,6 +444,7 @@ typedef enum { CELL_NOVENDING, CELL_NOCHAT, CELL_ICEWALL, + CELL_NOICEWALL, } cell_t; @@ -467,6 +468,7 @@ typedef enum { CELL_CHKNOVENDING, CELL_CHKNOCHAT, CELL_CHKICEWALL, + CELL_CHKNOICEWALL, } cell_chk; @@ -484,7 +486,8 @@ struct mapcell { landprotector : 1, novending : 1, nochat : 1, - icewall : 1; + icewall : 1, + noicewall : 1; #ifdef CELL_NOSTACK int cell_bl; //Holds amount of bls in this cell. @@ -847,7 +850,7 @@ struct map_interface { int server_port; char server_ip[32]; char server_id[32]; - char server_pw[32]; + char server_pw[100]; char server_db[32]; Sql* mysql_handle; diff --git a/src/map/mob.c b/src/map/mob.c index eaf8c8468..23706d293 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1429,7 +1429,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { //No valid target if (mob->warpchase(md, tbl)) return true; //Chasing this target. - if(md->ud.walktimer != INVALID_TIMER && md->ud.walkpath.path_pos <= battle_config.mob_chase_refresh) + if(md->ud.walktimer != INVALID_TIMER && (!can_move || md->ud.walkpath.path_pos <= battle_config.mob_chase_refresh)) return true; //Walk at least "mob_chase_refresh" cells before dropping the target mob_unlocktarget(md, tick); //Unlock target tbl = NULL; @@ -1442,13 +1442,14 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { if( md->attacked_id == md->target_id ) { //Rude attacked check. if( !battle->check_range(&md->bl, tbl, md->status.rhw.range) - && ( //Can't attack back and can't reach back. + && ( //Can't attack back and can't reach back. (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1) - || md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP] - || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target. - || !mob->can_reach(md, tbl, md->min_chase, MSS_RUSH) - || md->walktoxy_fail_count > 0 + || md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP] + || md->sc.data[SC__MANHOLE] // Not yet confirmed if boss will teleport once it can't reach target. + || md->walktoxy_fail_count > 0) ) + || !mob->can_reach(md, tbl, md->min_chase, MSS_RUSH) + ) && md->state.attacked_count++ >= RUDE_ATTACKED_COUNT && !mob->skill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack && can_move && unit->escape(&md->bl, tbl, rnd()%10 +1)) // Attempt escape @@ -1466,11 +1467,12 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { || (battle_config.mob_ai&0x2 && !status->check_skilluse(&md->bl, abl, 0, 0)) // Cannot normal attack back to Attacker || (!battle->check_range(&md->bl, abl, md->status.rhw.range) // Not on Melee Range and ... && ( // Reach check - (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1) - || md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP] - || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target. - || !mob->can_reach(md, abl, dist+md->db->range3, MSS_RUSH) - || md->walktoxy_fail_count > 0 + (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1) + || md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP] + || md->sc.data[SC__MANHOLE] // Not yet confirmed if boss will teleport once it can't reach target. + || md->walktoxy_fail_count > 0) + ) + || !mob->can_reach(md, abl, dist+md->db->range3, MSS_RUSH) ) ) ) { @@ -1636,6 +1638,9 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { if(battle->check_range(&md->bl, tbl, md->status.rhw.range)) return true; + //Only update target cell / drop target after having moved at least "mob_chase_refresh" cells + if(md->ud.walktimer != INVALID_TIMER && (!can_move || md->ud.walkpath.path_pos <= battle_config.mob_chase_refresh)) + return true; //Out of range... if (!(mode&MD_CANMOVE) || (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0)) @@ -1655,10 +1660,6 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { )) //Current target tile is still within attack range. return true; - //Only update target cell after having moved at least "mob_chase_refresh" cells - if(md->ud.walktimer != INVALID_TIMER && md->ud.walkpath.path_pos <= battle_config.mob_chase_refresh) - return true; - //Follow up if possible. //Hint: Chase skills are handled in the walktobl routine if(!mob->can_reach(md, tbl, md->min_chase, MSS_RUSH) || diff --git a/src/map/mob.h b/src/map/mob.h index 848bfbb2f..f3937c0d1 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -16,7 +16,7 @@ // Change this to increase the table size in your mob_db to accommodate a larger mob database. // Be sure to note that IDs 4001 to 4048 are reserved for advanced/baby/expanded classes. // Notice that the last 1000 entries are used for player clones, so always set this to desired value +1000 -#define MAX_MOB_DB 4000 +#define MAX_MOB_DB 5000 //The number of drops all mobs have and the max drop-slot that the steal skill will attempt to steal from. #define MAX_MOB_DROP 10 diff --git a/src/map/npc.c b/src/map/npc.c index 46b33bacb..7378ac470 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -4181,9 +4181,6 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { if( strcmp(w1,"function") == 0 ) { p = npc->parse_function(w1, w2, w3, w4, p, buffer, filepath, &success); } else { -#ifdef ENABLE_CASE_CHECK - if( strcasecmp(w1, "function") == 0 ) DeprecationCaseWarning("npc_parsesrcfile", w1, "function", filepath, strline(buffer, p-buffer)); // TODO -#endif // ENABLE_CASE_CHECK p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit?NPO_ONINIT:NPO_NONE, &success); } } @@ -4208,22 +4205,6 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { } else { -#ifdef ENABLE_CASE_CHECK - if( strcasecmp(w2, "warp") == 0 ) { DeprecationCaseWarning("npc_parsesrcfile", w2, "warp", filepath, strline(buffer, p-buffer)); } // TODO - else if( strcasecmp(w2,"shop") == 0 ) { DeprecationCaseWarning("npc_parsesrcfile", w2, "shop", filepath, strline(buffer, p-buffer)); } // TODO - else if( strcasecmp(w2,"cashshop") == 0 ) { DeprecationCaseWarning("npc_parsesrcfile", w2, "cashshop", filepath, strline(buffer, p-buffer)); } // TODO - else if( strcasecmp(w2, "script") == 0 ) { DeprecationCaseWarning("npc_parsesrcfile", w2, "script", filepath, strline(buffer, p-buffer)); } // TODO - else if( strcasecmp(w2,"trader") == 0 ) { DeprecationCaseWarning("npc_parsesrcfile", w2, "trader", filepath, strline(buffer, p-buffer)); } // TODO - else if( strncasecmp(w2, "duplicate", 9) == 0 ) { - char temp[10]; - safestrncpy(temp, w2, 10); - DeprecationCaseWarning("npc_parsesrcfile", temp, "duplicate", filepath, strline(buffer, p-buffer)); // TODO - } - else if( strcasecmp(w2,"monster") == 0 ) { DeprecationCaseWarning("npc_parsesrcfile", w2, "monster", filepath, strline(buffer, p-buffer)); } // TODO: - else if( strcasecmp(w2,"boss_monster") == 0 ) { DeprecationCaseWarning("npc_parsesrcfile", w2, "boss_monster", filepath, strline(buffer, p-buffer)); } // TODO - else if( strcasecmp(w2, "mapflag") == 0 ) { DeprecationCaseWarning("npc_parsesrcfile", w2, "mapflag", filepath, strline(buffer, p-buffer)); } // TODO - else -#endif // ENABLE_CASE_CHECK ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4); p = strchr(p,'\n');// skip and continue success = EXIT_FAILURE; @@ -4295,7 +4276,7 @@ void npc_read_event_script(void) script_event[i].event_count++; #ifdef ENABLE_CASE_CHECK } else if( p && strcasecmp(name, p) == 0 ) { - DeprecationCaseWarning2("npc_read_event_script", p, name, config[i].event_name); // TODO + DeprecationCaseWarning("npc_read_event_script", p, name, config[i].event_name); // TODO #endif // ENABLE_CASE_CHECK } } diff --git a/src/map/pc.c b/src/map/pc.c index 85dab4559..f07858ca6 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -3102,11 +3102,11 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) } if(sd->skillfixcastrate[i].id == type2) - sd->skillfixcastrate[i].val += val; + sd->skillfixcastrate[i].val -= val; else { sd->skillfixcastrate[i].id = type2; - sd->skillfixcastrate[i].val = val; + sd->skillfixcastrate[i].val -= val; } break; @@ -7633,6 +7633,10 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp) // Recovery Potion if( sd->sc.data[SC_HEALPLUS] ) hp += (int)(hp * sd->sc.data[SC_HEALPLUS]->val1/100.); + + // 2014 Halloween Event : Pumpkin Bonus + if ( sd->sc.data[SC_MTF_PUMPKIN] && itemid == ITEMID_PUMPKIN ) + hp += (int)(hp * sd->sc.data[SC_MTF_PUMPKIN]->val1/100); } if(sp) { bonus = 100 + (sd->battle_status.int_<<1) diff --git a/src/map/script.c b/src/map/script.c index b8e161e10..5e368e0ad 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -526,7 +526,7 @@ int script_add_str(const char* p) } } if( existingentry ) { - DeprecationCaseWarning2("script_add_str", p, existingentry, script->parser_current_file); // TODO + DeprecationCaseWarning("script_add_str", p, existingentry, script->parser_current_file); // TODO } #endif // ENABLE_CASE_CHECK @@ -772,6 +772,8 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) script->addl(func); script->addc(C_ARG); arg = script->buildin[script->str_data[func].val]; + if (script->str_data[func].deprecated) + DeprecationWarning(p); if( !arg ) arg = &null_arg; // Use a dummy, null string } else if( script->str_data[func].type == C_USERFUNC || script->str_data[func].type == C_USERFUNC_POS ) { // script defined function @@ -1349,7 +1351,7 @@ const char* parse_curly_close(const char* p) char label[256]; int l; // Remove temporary variables - sprintf(label,"set $@__SW%x_VAL,0;",script->syntax.curly[pos].index); + sprintf(label,"__setr $@__SW%x_VAL,0;",script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; @@ -1431,10 +1433,6 @@ const char* parse_syntax(const char* p) // Closing decision if, for , while p = script->parse_syntax_close(p + 1); return p; -#ifdef ENABLE_CASE_CHECK - } else if( p2 - p == 5 && strncasecmp(p, "break", 5) == 0 ) { - disp_deprecation_message("parse_syntax", "break", p); // TODO -#endif // ENABLE_CASE_CHECK } break; case 'c': @@ -1506,7 +1504,7 @@ const char* parse_syntax(const char* p) disp_error_message("parse_syntax: dup 'case'",p); linkdb_insert(&script->syntax.curly[pos].case_label, (void*)h64BPTRSIZE(v), (void*)1); - sprintf(label,"set $@__SW%x_VAL,0;",script->syntax.curly[pos].index); + sprintf(label,"__setr $@__SW%x_VAL,0;",script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); @@ -1545,12 +1543,6 @@ const char* parse_syntax(const char* p) //Closing decision if, for , while p = script->parse_syntax_close(p + 1); return p; -#ifdef ENABLE_CASE_CHECK - } else if( p2 - p == 4 && strncasecmp(p, "case", 4) == 0 ) { - disp_deprecation_message("parse_syntax", "case", p); // TODO - } else if( p2 - p == 8 && strncasecmp(p, "continue", 8) == 0 ) { - disp_deprecation_message("parse_syntax", "continue", p); // TODO -#endif // ENABLE_CASE_CHECK } break; case 'd': @@ -1604,12 +1596,6 @@ const char* parse_syntax(const char* p) script->set_label(l,script->pos,p); script->syntax.curly_count++; return p; -#ifdef ENABLE_CASE_CHECK - } else if( p2 - p == 7 && strncasecmp(p, "default", 7) == 0 ) { - disp_deprecation_message("parse_syntax", "default", p); // TODO - } else if( p2 - p == 2 && strncasecmp(p, "do", 2) == 0 ) { - disp_deprecation_message("parse_syntax", "do", p); // TODO -#endif // ENABLE_CASE_CHECK } break; case 'f': @@ -1647,7 +1633,7 @@ const char* parse_syntax(const char* p) } else { // Skip to the end point if the condition is false sprintf(label,"__FR%x_FIN",script->syntax.curly[pos].index); - script->addl(script->add_str("jump_zero")); + script->addl(script->add_str("__jump_zero")); script->addc(C_ARG); p=script->parse_expr(p); p=script->skip_space(p); @@ -1749,12 +1735,6 @@ const char* parse_syntax(const char* p) { disp_error_message("expect ';' or '{' at function syntax",p); } -#ifdef ENABLE_CASE_CHECK - } else if( p2 - p == 3 && strncasecmp(p, "for", 3) == 0 ) { - disp_deprecation_message("parse_syntax", "for", p); // TODO - } else if( p2 - p == 8 && strncasecmp(p, "function", 8) == 0 ) { - disp_deprecation_message("parse_syntax", "function", p); // TODO -#endif // ENABLE_CASE_CHECK } break; case 'i': @@ -1772,17 +1752,13 @@ const char* parse_syntax(const char* p) script->syntax.curly[script->syntax.curly_count].flag = 0; sprintf(label,"__IF%x_%x",script->syntax.curly[script->syntax.curly_count].index,script->syntax.curly[script->syntax.curly_count].count); script->syntax.curly_count++; - script->addl(script->add_str("jump_zero")); + script->addl(script->add_str("__jump_zero")); script->addc(C_ARG); p=script->parse_expr(p); p=script->skip_space(p); script->addl(script->add_str(label)); script->addc(C_FUNC); return p; -#ifdef ENABLE_CASE_CHECK - } else if( p2 - p == 2 && strncasecmp(p, "if", 2) == 0 ) { - disp_deprecation_message("parse_syntax", "if", p); // TODO -#endif // ENABLE_CASE_CHECK } break; case 's': @@ -1800,7 +1776,7 @@ const char* parse_syntax(const char* p) script->syntax.curly[script->syntax.curly_count].flag = 0; sprintf(label,"$@__SW%x_VAL",script->syntax.curly[script->syntax.curly_count].index); script->syntax.curly_count++; - script->addl(script->add_str("set")); + script->addl(script->add_str("__setr")); script->addc(C_ARG); script->addl(script->add_str(label)); p=script->parse_expr(p); @@ -1810,10 +1786,6 @@ const char* parse_syntax(const char* p) } script->addc(C_FUNC); return p + 1; -#ifdef ENABLE_CASE_CHECK - } else if( p2 - p == 6 && strncasecmp(p, "switch", 6) == 0 ) { - disp_deprecation_message("parse_syntax", "switch", p); // TODO -#endif // ENABLE_CASE_CHECK } break; case 'w': @@ -1837,17 +1809,13 @@ const char* parse_syntax(const char* p) // Skip to the end point if the condition is false sprintf(label,"__WL%x_FIN",script->syntax.curly[script->syntax.curly_count].index); script->syntax.curly_count++; - script->addl(script->add_str("jump_zero")); + script->addl(script->add_str("__jump_zero")); script->addc(C_ARG); p=script->parse_expr(p); p=script->skip_space(p); script->addl(script->add_str(label)); script->addc(C_FUNC); return p; -#ifdef ENABLE_CASE_CHECK - } else if( p2 - p == 5 && strncasecmp(p, "while", 5) == 0 ) { - disp_deprecation_message("parse_syntax", "while", p); // TODO -#endif // ENABLE_CASE_CHECK } break; } @@ -1909,7 +1877,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag) disp_error_message("need '('",p); } sprintf(label,"__IF%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count); - script->addl(script->add_str("jump_zero")); + script->addl(script->add_str("__jump_zero")); script->addc(C_ARG); p=script->parse_expr(p); p=script->skip_space(p); @@ -1917,10 +1885,6 @@ const char* parse_syntax_close_sub(const char* p,int* flag) script->addc(C_FUNC); *flag = 0; return p; -#ifdef ENABLE_CASE_CHECK - } else if( p2 - p == 2 && strncasecmp(p, "if", 2) == 0 ) { - disp_deprecation_message("parse_syntax", "if", p); // TODO -#endif // ENABLE_CASE_CHECK } else { // else if(!script->syntax.curly[pos].flag) { @@ -1929,10 +1893,6 @@ const char* parse_syntax_close_sub(const char* p,int* flag) return p; } } -#ifdef ENABLE_CASE_CHECK - } else if( !script->syntax.curly[pos].flag && p2 - p == 4 && strncasecmp(p, "else", 4) == 0 ) { - disp_deprecation_message("parse_syntax", "else", p); // TODO -#endif // ENABLE_CASE_CHECK } // Close if script->syntax.curly_count--; @@ -1959,9 +1919,6 @@ const char* parse_syntax_close_sub(const char* p,int* flag) p = script->skip_space(p); p2 = script->skip_word(p); if( p2 - p != 5 || strncmp(p, "while", 5) != 0 ) { -#ifdef ENABLE_CASE_CHECK - if( p2 - p == 5 && strncasecmp(p, "while", 5) == 0 ) disp_deprecation_message("parse_syntax", "while", p); // TODO -#endif // ENABLE_CASE_CHECK disp_error_message("parse_syntax: need 'while'",p); } @@ -1974,7 +1931,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag) script->parse_nextline(false, p); sprintf(label,"__DO%x_FIN",script->syntax.curly[pos].index); - script->addl(script->add_str("jump_zero")); + script->addl(script->add_str("__jump_zero")); script->addc(C_ARG); p=script->parse_expr(p); p=script->skip_space(p); @@ -5681,7 +5638,7 @@ BUILDIN(copyarray); /// The value is converted to the type of the variable. /// /// set(<variable>,<value>) -> <variable> -BUILDIN(setr) { +BUILDIN(__setr) { TBL_PC* sd = NULL; struct script_data* data; //struct script_data* datavalue; @@ -5691,7 +5648,7 @@ BUILDIN(setr) { data = script_getdata(st,2); //datavalue = script_getdata(st,3); - if( !data_isreference(data) || reference_toconstant(data) ) { + if (!data_isreference(data) || reference_toconstant(data)) { ShowError("script:set: not a variable\n"); script->reportdata(script_getdata(st,2)); st->state = END; @@ -5702,9 +5659,9 @@ BUILDIN(setr) { name = reference_getname(data); prefix = *name; - if( not_server_variable(prefix) ) { + if (not_server_variable(prefix)) { sd = script->rid2sd(st); - if( sd == NULL ) { + if (sd == NULL) { ShowError("script:set: no player attached for player variable '%s'\n", name); return true; } @@ -5712,19 +5669,19 @@ BUILDIN(setr) { #if 0 // TODO: see de43fa0f73be01080bd11c08adbfb7c158324c81 - if( data_isreference(datavalue) ) { + if (data_isreference(datavalue)) { // the value being referenced is a variable const char* namevalue = reference_getname(datavalue); - if( !not_array_variable(*namevalue) ) { + if (!not_array_variable(*namevalue)) { // array variable being copied into another array variable - if( sd == NULL && not_server_variable(*namevalue) && !(sd = script->rid2sd(st)) ) { + if (sd == NULL && not_server_variable(*namevalue) && !(sd = script->rid2sd(st))) { // player must be attached in order to copy a player variable ShowError("script:set: no player attached for player variable '%s'\n", namevalue); return true; } - if( is_string_variable(namevalue) != is_string_variable(name) ) { + if (is_string_variable(namevalue) != is_string_variable(name)) { // non-matching array value types ShowWarning("script:set: two array variables do not match in type.\n"); return true; @@ -5739,9 +5696,9 @@ BUILDIN(setr) { } #endif - if( script_hasdata(st, 4) ) { + if (script_hasdata(st, 4)) { // Optional argument used by post-increment/post-decrement constructs to return the previous value - if( is_string_variable(name) ) { + if (is_string_variable(name)) { script_pushstrcopy(st, script_getstr(st, 4)); } else { script_pushint(st, script_getnum(st, 4)); @@ -5751,7 +5708,7 @@ BUILDIN(setr) { script_pushcopy(st,2); } - if( is_string_variable(name) ) + if (is_string_variable(name)) script->set_reg(st,sd,num,name,(void*)script_getstr(st,3),script_getref(st,2)); else script->set_reg(st,sd,num,name,(void*)h64BPTRSIZE(script_getnum(st,3)),script_getref(st,2)); @@ -8804,6 +8761,7 @@ BUILDIN(setmount) flag == SETMOUNT_TYPE_DRAGON_RED ? OPTION_DRAGON5 : OPTION_DRAGON1); // default value pc->setridingdragon(sd, option); + } } else if ((sd->class_&MAPID_THIRDMASK) == MAPID_RANGER) { // Ranger (Warg) if (pc->checkskill(sd, RA_WUGRIDER)) @@ -8812,8 +8770,6 @@ BUILDIN(setmount) // Mechanic (Mado Gear) if (pc->checkskill(sd, NC_MADOLICENCE)) pc->setmadogear(sd, true); - } else if (flag != SETMOUNT_TYPE_PECO) - flag = SETMOUNT_TYPE_PECO; } else { // Knight / Crusader (Peco Peco) if (pc->checkskill(sd, KN_RIDING)) @@ -13244,14 +13200,14 @@ BUILDIN(checkequipedcard) return true; } -BUILDIN(jump_zero) +BUILDIN(__jump_zero) { int sel; sel=script_getnum(st,2); - if(!sel) { + if (!sel) { int pos; - if( !data_islabel(script_getdata(st,3)) ) { - ShowError("script: jump_zero: not label !\n"); + if (!data_islabel(script_getdata(st,3))) { + ShowError("script: jump_zero: not a label !\n"); st->state=END; return false; } @@ -14879,6 +14835,36 @@ BUILDIN(distance) // <--- [zBuffer] List of mathematics commands +BUILDIN(min) +{ + int i, min; + + min = script_getnum(st, 2); + for (i = 3; script_hasdata(st, i); i++) { + int next = script_getnum(st, i); + if (next < min) + min = next; + } + script_pushint(st, min); + + return true; +} + +BUILDIN(max) +{ + int i, max; + + max = script_getnum(st, 2); + for (i = 3; script_hasdata(st, i); i++) { + int next = script_getnum(st, i); + if (next > max) + max = next; + } + script_pushint(st, max); + + return true; +} + BUILDIN(md5) { const char *tmpstr; @@ -18010,6 +17996,7 @@ BUILDIN(montransform) { struct block_list* bl; char msg[CHAT_SIZE_MAX]; int mob_id, val1, val2, val3, val4; + val1 = val2 = val3 = val4 = 0; if( (bl = map->id2bl(st->rid)) == NULL ) return true; @@ -18029,12 +18016,17 @@ BUILDIN(montransform) { } tick = script_getnum(st, 3); - type = (sc_type)script_getnum(st, 4); - val1 = val2 = val3 = val4 = 0; - if( !(type > SC_NONE && type < SC_MAX) ) { - ShowWarning("buildin_montransform: Unsupported status change id %d\n", type); - return false; + if (script_hasdata(st, 4)) + type = (sc_type)script_getnum(st, 4); + else + type = SC_NONE; + + if (script_hasdata(st, 4)) { + if( !(type > SC_NONE && type < SC_MAX) ) { + ShowWarning("buildin_montransform: Unsupported status change id %d\n", type); + return false; + } } if (script_hasdata(st, 5)) @@ -18070,8 +18062,11 @@ BUILDIN(montransform) { clif->ShowScript(&sd->bl, msg); status_change_end(bl, SC_MONSTER_TRANSFORM, INVALID_TIMER); // Clear previous sc_start2(NULL, bl, SC_MONSTER_TRANSFORM, 100, mob_id, type, tick); - sc_start4(NULL, bl, type, 100, val1, val2, val3, val4, tick); + + if (script_hasdata(st, 4)) + sc_start4(NULL, bl, type, 100, val1, val2, val3, val4, tick); } + return true; } @@ -18961,7 +18956,7 @@ bool script_add_builtin(const struct script_function *buildin, bool override) { script->buildin[offset] = NULL; } else { // Adding new function - if( strcmp(buildin->name, "setr") == 0 ) script->buildin_set_ref = n; + if( strcmp(buildin->name, "__setr") == 0 ) script->buildin_set_ref = n; else if( strcmp(buildin->name, "callsub") == 0 ) script->buildin_callsub_ref = n; else if( strcmp(buildin->name, "callfunc") == 0 ) script->buildin_callfunc_ref = n; else if( strcmp(buildin->name, "getelementofarray") == 0 ) script->buildin_getelementofarray_ref = n; @@ -18977,6 +18972,7 @@ bool script_add_builtin(const struct script_function *buildin, bool override) { } script->str_data[n].func = buildin->func; + script->str_data[n].deprecated = (buildin->deprecated ? 1 : 0); /* we only store the arguments, its the only thing used out of this */ if( slen ) { @@ -18994,13 +18990,20 @@ bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st) buildin.name = name; buildin.arg = args; buildin.func = func; + buildin.deprecated = false; return script->add_builtin(&buildin, true); } -#define BUILDIN_DEF(x,args) { buildin_ ## x , #x , args } -#define BUILDIN_DEF2(x,x2,args) { buildin_ ## x , x2 , args } +#define BUILDIN_DEF(x,args) { buildin_ ## x , #x , args, false } +#define BUILDIN_DEF2(x,x2,args) { buildin_ ## x , x2 , args, false } +#define BUILDIN_DEF_DEPRECATED(x,args) { buildin_ ## x , #x , args, true } +#define BUILDIN_DEF2_DEPRECATED(x,x2,args) { buildin_ ## x , x2 , args, true } void script_parse_builtin(void) { struct script_function BUILDIN[] = { + /* Commands for internal use by the script engine */ + BUILDIN_DEF(__jump_zero,"il"), + BUILDIN_DEF(__setr,"rv?"), + // NPC interaction BUILDIN_DEF(mes,"s*"), BUILDIN_DEF(next,""), @@ -19025,8 +19028,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(warpguild,"siii"), // [Fredzilla] BUILDIN_DEF(setlook,"ii"), BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it - BUILDIN_DEF2(setr,"set","rv"), - BUILDIN_DEF(setr,"rv?"), // Not meant to be used directly, required for var++/var-- + BUILDIN_DEF2(__setr,"set","rv"), BUILDIN_DEF(setarray,"rv*"), BUILDIN_DEF(cleararray,"rvi"), BUILDIN_DEF(copyarray,"rri"), @@ -19105,14 +19107,14 @@ void script_parse_builtin(void) { BUILDIN_DEF(checkcart,""), BUILDIN_DEF(setfalcon,"?"), BUILDIN_DEF(checkfalcon,""), - BUILDIN_DEF(setriding,"?"), - BUILDIN_DEF(checkriding,""), + BUILDIN_DEF_DEPRECATED(setriding,"?"), // Deprecated 2014-10-30 [Haru] + BUILDIN_DEF_DEPRECATED(checkriding,""), // Deprecated 2014-10-30 [Haru] BUILDIN_DEF(setmount,"?"), BUILDIN_DEF(checkmount,""), BUILDIN_DEF(checkwug,""), - BUILDIN_DEF(checkmadogear,""), - BUILDIN_DEF(setmadogear,"?"), - BUILDIN_DEF2(savepoint,"save","sii"), + BUILDIN_DEF_DEPRECATED(checkmadogear,""), // Deprecated 2014-10-30 [Haru] + BUILDIN_DEF_DEPRECATED(setmadogear,"?"), // Deprecated 2014-10-30 [Haru] + BUILDIN_DEF2_DEPRECATED(savepoint,"save","sii"), // Deprecated 2014-11-02 [Haru] BUILDIN_DEF(savepoint,"sii"), BUILDIN_DEF(gettimetick,"i"), BUILDIN_DEF(gettime,"i"), @@ -19130,7 +19132,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(clone,"siisi????"), BUILDIN_DEF(doevent,"s"), BUILDIN_DEF(donpcevent,"s"), - BUILDIN_DEF(cmdothernpc,"ss"), + BUILDIN_DEF_DEPRECATED(cmdothernpc,"ss"), // Deprecated 2014-11-02 [Haru] BUILDIN_DEF(addtimer,"is"), BUILDIN_DEF(deltimer,"s"), BUILDIN_DEF(addtimercount,"si"), @@ -19174,8 +19176,8 @@ void script_parse_builtin(void) { BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"), BUILDIN_DEF(enablewaitingroomevent,"?"), BUILDIN_DEF(disablewaitingroomevent,"?"), - BUILDIN_DEF2(enablewaitingroomevent,"enablearena",""), // Added by RoVeRT - BUILDIN_DEF2(disablewaitingroomevent,"disablearena",""), // Added by RoVeRT + BUILDIN_DEF2_DEPRECATED(enablewaitingroomevent,"enablearena",""), // Deprecated 2014-11-02 [Haru] + BUILDIN_DEF2_DEPRECATED(disablewaitingroomevent,"disablearena",""), // Deprecated 2014-11-02 [Haru] BUILDIN_DEF(getwaitingroomstate,"i?"), BUILDIN_DEF(warpwaitingpc,"sii?"), BUILDIN_DEF(attachrid,"i"), @@ -19230,7 +19232,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(petskillbonus,"iiii"), // [Valaris] BUILDIN_DEF(petrecovery,"ii"), // [Valaris] BUILDIN_DEF(petloot,"i"), // [Valaris] - BUILDIN_DEF(petheal,"iiii"), // [Valaris] + BUILDIN_DEF_DEPRECATED(petheal,"iiii"), // Deprecated 2014-10-27 [Haru] BUILDIN_DEF(petskillattack,"viii"), // [Skotlex] BUILDIN_DEF(petskillattack2,"viiii"), // [Valaris] BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex] @@ -19280,7 +19282,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(gethominfo,"i"), BUILDIN_DEF(getmercinfo,"i?"), BUILDIN_DEF(checkequipedcard,"i"), - BUILDIN_DEF(jump_zero,"il"), //for future jA script compatibility + BUILDIN_DEF2_DEPRECATED(__jump_zero,"jump_zero","il"), // Deprecated 2014-10-27 [Haru] BUILDIN_DEF(globalmes,"s?"), //end jA addition BUILDIN_DEF(unequip,"i"), // unequip command [Spectre] BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris] @@ -19311,6 +19313,8 @@ void script_parse_builtin(void) { BUILDIN_DEF(pow,"ii"), BUILDIN_DEF(distance,"iiii"), // <--- [zBuffer] List of mathematics commands + BUILDIN_DEF(min, "i*"), + BUILDIN_DEF(max, "i*"), BUILDIN_DEF(md5,"s"), // [zBuffer] List of dynamic var commands ---> BUILDIN_DEF(getd,"s"), @@ -19432,8 +19436,8 @@ void script_parse_builtin(void) { * 3rd-related **/ BUILDIN_DEF(makerune,"i"), - BUILDIN_DEF(checkdragon,""),//[Ind] - BUILDIN_DEF(setdragon,"?"),//[Ind] + BUILDIN_DEF_DEPRECATED(checkdragon,""), // Deprecated 2014-10-30 [Haru] + BUILDIN_DEF_DEPRECATED(setdragon,"?"), // Deprecated 2014-10-30 [Haru] BUILDIN_DEF(hascashmount,""),//[Ind] BUILDIN_DEF(setcashmount,""),//[Ind] BUILDIN_DEF(checkre,"i"), @@ -19470,7 +19474,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(setquest, "i"), BUILDIN_DEF(erasequest, "i?"), BUILDIN_DEF(completequest, "i?"), - BUILDIN_DEF(checkquest, "i?"), + BUILDIN_DEF_DEPRECATED(checkquest, "i?"), // Deprecated 2014-10-28 [Haru] BUILDIN_DEF(questprogress, "i?"), BUILDIN_DEF(questactive, "i"), BUILDIN_DEF(changequest, "ii"), @@ -19496,7 +19500,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(stand, "?"), BUILDIN_DEF(issit, "?"), - BUILDIN_DEF(montransform, "vii????"), // Monster Transform [malufett/Hercules] + BUILDIN_DEF(montransform, "vi?????"), // Monster Transform [malufett/Hercules] /* New BG Commands [Hercules] */ BUILDIN_DEF(bg_create_team,"sii"), diff --git a/src/map/script.h b/src/map/script.h index 54b3835a7..1a46ba02b 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -26,9 +26,9 @@ struct eri; // TODO: Remove temporary code #define ENABLE_CASE_CHECK #define get_script_source(source) ((source) ? (source) : "Unknown (Possibly source or variables stored in database") -#define DeprecationCaseWarning(func, bad, good, file, line) ShowError("%s: use of deprecated keyword '%s' (use '%s' instead) in file '%s', line '%d'.\n", (func), (bad), (good), get_script_source(file), (line)) -#define DeprecationCaseWarning2(func, bad, good, where) ShowError("%s: detected possible use of wrong case in a script. Found '%s', probably meant to be '%s' (in '%s').\n", (func), (bad), (good), get_script_source(where)) -#define disp_deprecation_message(func, good, p) disp_warning_message(func": use of deprecated keyword (use '"good"' instead).", (p)) +#define DeprecationCaseWarning(func, bad, good, where) ShowError("%s: detected possible use of wrong case in a script. Found '%s', probably meant to be '%s' (in '%s').\n", (func), (bad), (good), get_script_source(where)) + +#define DeprecationWarning(p) disp_warning_message("This command is deprecated and it will be removed in a future update. Please see the script documentation for an alternative.\n", (p)) #define NUM_WHISPER_VAR 10 @@ -433,6 +433,7 @@ struct script_function { bool (*func)(struct script_state *st); char *name; char *arg; + bool deprecated; }; // String buffer structures. @@ -445,6 +446,7 @@ struct str_data_struct { bool (*func)(struct script_state *st); int val; int next; + uint8 deprecated : 1; }; struct script_label_entry { diff --git a/src/map/skill.c b/src/map/skill.c index 31e281d93..992b72857 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -8325,7 +8325,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( flag&1 || (splash = skill->get_splash(skill_id, skill_lv)) < 1 ) { int i; //As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie] - if( bl->type != BL_MOB && battle->check_target(src,bl,BCT_PARTY) <= 0 ) // Only affect mob or party. + if( bl->type != BL_MOB && battle->check_target(src,bl,BCT_PARTY) <= 0 && sd ) // Only affect mob, party or self. break; clif->skill_nodamage(src,bl,skill_id,skill_lv,1); @@ -10078,7 +10078,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case MG_THUNDERSTORM: case AL_PNEUMA: - case WZ_ICEWALL: case WZ_FIREPILLAR: case WZ_QUAGMIRE: case WZ_VERMILION: @@ -10187,6 +10186,11 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui sc_start(src,src,SC_NO_SWITCH_EQUIP,100,0,skill->get_time(skill_id,skill_lv)); skill->unitsetting(src,skill_id,skill_lv,x,y,0); break; + case WZ_ICEWALL: + flag |= 1; + if( skill->unitsetting(src,skill_id,skill_lv,x,y,0) ) + map->list[src->m].setcell(src->m, x, y, CELL_NOICEWALL, true); + break; case RG_GRAFFITI: /* Graffiti [Valaris] */ skill->clear_unitgroup(src); skill->unitsetting(src,skill_id,skill_lv,x,y,0); @@ -10995,11 +10999,11 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ val1 += pc->checkskill(sd,BA_MUSICALLESSON); break; case DC_SERVICEFORYOU: - val1 = 15+skill_lv+(st->int_/10); // MaxSP percent increase TO-DO: this INT bonus value is guessed + val1 = 15+skill_lv+(st->int_/10); // MaxSP percent increase val2 = 20+3*skill_lv+(st->int_/10); // SP cost reduction if(sd){ - val1 += (pc->checkskill(sd,DC_DANCINGLESSON) + 1) / 2; - val2 += (pc->checkskill(sd,DC_DANCINGLESSON) + 1) / 2; + val1 += pc->checkskill(sd,DC_DANCINGLESSON) / 2; + val2 += pc->checkskill(sd,DC_DANCINGLESSON) / 2; } break; case BA_ASSASSINCROSS: @@ -13170,17 +13174,6 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id } } break; - /** - * Keeping as a note: - * Bug Report #17 provides a link to a sep-2011 changelog that shows this requirement was removed - **/ - //case AB_LAUDAAGNUS: - //case AB_LAUDARAMUS: - // if( !sd->status.party_id ) { - // clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - // return 0; - // } - // break; case AB_ADORAMUS: /** @@ -14312,9 +14305,8 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 break; } for( i = 0; i < ARRAYLENGTH(sd->skillfixcastrate) && sd->skillfixcastrate[i].id; i++ ) - if( sd->skillfixcastrate[i].id == skill_id ){ // bonus2 bFixedCastrate - fixcast_r = sd->skillfixcastrate[i].val; // just speculation + fixcast_r = sd->skillfixcastrate[i].val; break; } } @@ -15258,9 +15250,10 @@ int skill_cell_overlap(struct block_list *bl, va_list ap) { break; } break; + case WZ_ICEWALL: case HP_BASILICA: - if (su->group->skill_id == HP_BASILICA) { - //Basilica can't be placed on top of itself to avoid map-cell stacking problems. [Skotlex] + if (su->group->skill_id == skill_id) { + //These can't be placed on top of themselves (duration can't be refreshed) (*alive) = 0; return 1; } @@ -15626,6 +15619,7 @@ int skill_delunit (struct skill_unit* su) { } break; case WZ_ICEWALL: + map->list[su->bl.m].setcell(su->bl.m, su->bl.x, su->bl.y, CELL_NOICEWALL, false); map->setgatcell(su->bl.m,su->bl.x,su->bl.y,su->val2); clif->changemapcell(0,su->bl.m,su->bl.x,su->bl.y,su->val2,ALL_SAMEMAP); // hack to avoid clientside cell bug skill->unitsetmapcell(su,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,false); diff --git a/src/map/status.c b/src/map/status.c index ac7d7d237..66f7db3fa 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -935,13 +935,16 @@ void initChangeTables(void) { status->ChangeFlagTable[SC_INCHITRATE] |= SCB_HIT; status->ChangeFlagTable[SC_INCFLEE] |= SCB_FLEE; status->ChangeFlagTable[SC_INCFLEERATE] |= SCB_FLEE; + status->ChangeFlagTable[SC_MTF_HITFLEE] |= SCB_HIT|SCB_FLEE; status->ChangeFlagTable[SC_CRITICALPERCENT] |= SCB_CRI; status->ChangeFlagTable[SC_INCASPDRATE] |= SCB_ASPD; status->ChangeFlagTable[SC_PLUSAVOIDVALUE] |= SCB_FLEE2; status->ChangeFlagTable[SC_INCMHPRATE] |= SCB_MAXHP; status->ChangeFlagTable[SC_INCMSPRATE] |= SCB_MAXSP; status->ChangeFlagTable[SC_INCMHP] |= SCB_MAXHP; + status->ChangeFlagTable[SC_MTF_MHP] |= SCB_MAXHP; status->ChangeFlagTable[SC_INCMSP] |= SCB_MAXSP; + status->ChangeFlagTable[SC_MTF_MSP] |= SCB_MAXSP; status->ChangeFlagTable[SC_INCATKRATE] |= SCB_BATK|SCB_WATK; status->ChangeFlagTable[SC_INCMATKRATE] |= SCB_MATK; status->ChangeFlagTable[SC_INCDEFRATE] |= SCB_DEF; @@ -1795,9 +1798,9 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin //If targeting, cloak+hide protect you, otherwise only hiding does. hide_flag = flag?OPTION_HIDE:(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK); - // There is no NF for ground skills, but every earth type skill out there - // affects hidding except Stone Curse - if( skill->get_ele(skill_id,1) == ELE_EARTH && skill_id != MG_STONECURSE) + // Applies even if the target hides + if ((skill->get_ele(skill_id,1) == ELE_EARTH && skill_id != MG_STONECURSE) // Ground type + || (flag&1 && skill->get_nk(skill_id)&NK_NO_DAMAGE && skill_id != ALL_RESURRECTION)) // Buff/debuff skills started before hiding hide_flag &= ~OPTION_HIDE; switch( target->type ) { @@ -1809,7 +1812,6 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin return 0; if( tsc ) { if (tsc->option&hide_flag && !is_boss && - !(flag&1 && skill->get_nk(skill_id)&NK_NO_DAMAGE) && // Buff/debuff skills that started casting before hiding still applies ((sd->special_state.perfect_hiding || !is_detect) || (tsc->data[SC_CLOAKINGEXCEED] && is_detect))) return 0; @@ -4713,6 +4715,8 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, if( !viewable ){ /* some statuses that are hidden in the status window */ + if (sc->data[SC_MINDBREAKER]) + matk += matk * sc->data[SC_MINDBREAKER]->val2/100; return (unsigned short)cap_value(matk,0,USHRT_MAX); } @@ -4737,8 +4741,6 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, if (sc->data[SC_IZAYOI]) matk += 25 * sc->data[SC_IZAYOI]->val1; #endif - if (sc->data[SC_MINDBREAKER]) - matk += matk * sc->data[SC_MINDBREAKER]->val2/100; if( sc->data[SC_ZANGETSU] ) matk += sc->data[SC_ZANGETSU]->val3; if (sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4) @@ -4805,6 +4807,8 @@ signed short status_calc_hit(struct block_list *bl, struct status_change *sc, in if(sc->data[SC_INCHIT]) hit += sc->data[SC_INCHIT]->val1; + if(sc->data[SC_MTF_HITFLEE]) + hit += sc->data[SC_MTF_HITFLEE]->val1; if(sc->data[SC_FOOD_BASICHIT]) hit += sc->data[SC_FOOD_BASICHIT]->val1; if(sc->data[SC_TRUESIGHT]) @@ -4856,6 +4860,8 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i if(sc->data[SC_INCFLEE]) flee += sc->data[SC_INCFLEE]->val1; + if(sc->data[SC_MTF_HITFLEE]) + flee += sc->data[SC_MTF_HITFLEE]->val2; if(sc->data[SC_FOOD_BASICAVOIDANCE]) flee += sc->data[SC_FOOD_BASICAVOIDANCE]->val1; if(sc->data[SC_WHISTLE]) @@ -5700,6 +5706,8 @@ unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, maxhp += maxhp * sc->data[SC_INCMHPRATE]->val1/100; if(sc->data[SC_INCMHP]) maxhp += (sc->data[SC_INCMHP]->val1); + if(sc->data[SC_MTF_MHP]) + maxhp += (sc->data[SC_MTF_MHP]->val1); if(sc->data[SC_APPLEIDUN]) maxhp += maxhp * sc->data[SC_APPLEIDUN]->val2/100; if(sc->data[SC_DELUGE]) @@ -5767,6 +5775,8 @@ unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, maxsp += maxsp * sc->data[SC_INCMSPRATE]->val1/100; if(sc->data[SC_INCMSP]) maxsp += (sc->data[SC_INCMSP]->val1); + if(sc->data[SC_MTF_MSP]) + maxsp += (sc->data[SC_MTF_MSP]->val1); if(sc->data[SC_SERVICEFORYOU]) maxsp += maxsp * sc->data[SC_SERVICEFORYOU]->val2/100; if(sc->data[SC_MER_SP]) @@ -8798,7 +8808,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t struct block_list * src2; val3 = st->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] % if( (src2 = map->id2bl(val2)) ){ - val4 = ( 200/status_get_int(src2)?status_get_int(src2):1 ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] + val4 = ( 200/(status_get_int(src2)?status_get_int(src2):1) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] val2 = ( status_get_dex(src2)/4 + status_get_str(src2)/2 ) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5] } } @@ -11335,7 +11345,7 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) { if (sce && skill->attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,sce->val1,tick,0x4000) && (!su || !su->group || !(skill->get_inf2(su->group->skill_id)&INF2_TRAP))) { // The hit is not counted if it's against a trap sce->val2 = 0; // This signals it to end. - } else if((bl->type&BL_SKILL) && sce->val4%2 == 0) { + } else if ((bl->type&BL_SKILL) && sce && sce->val4%2 == 0) { //Remove trap immunity temporarily so it triggers if you still stand on it sce->val4++; } @@ -11384,7 +11394,7 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl if( !(flag&1) ){ if( max > min ) - max = min + rnd()%(max - min); + max = min + rnd()%(max - min + 1); else max = min; } diff --git a/src/map/status.h b/src/map/status.h index 623ba7eb3..e96894e9f 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -730,7 +730,7 @@ typedef enum sc_type { SC__FEINTBOMB_MASTER, SC_FALLENEMPIRE, - SC_FLASHCOMBO, + SC_FLASHCOMBO, // 580 //Vellum Weapon reductions SC_DEFSET, @@ -738,6 +738,12 @@ typedef enum sc_type { SC_NO_SWITCH_EQUIP, + // 2014 Halloween Event + SC_MTF_MHP, + SC_MTF_MSP, + SC_MTF_PUMPKIN, + SC_MTF_HITFLEE, + SC_MAX, //Automatically updated max, used in for's to check we are within bounds. } sc_type; diff --git a/src/map/unit.c b/src/map/unit.c index b4653df00..34a9dcc24 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -108,11 +108,11 @@ int unit_walktoxy_sub(struct block_list *bl) uint8 dir; //Trim the last part of the path to account for range, //but always move at least one cell when requested to move. - for (i = ud->chaserange*10; i > 0 && ud->walkpath.path_len>1;) { + for (i = (ud->chaserange*10)-10; i > 0 && ud->walkpath.path_len>1;) { ud->walkpath.path_len--; dir = ud->walkpath.path[ud->walkpath.path_len]; if(dir&1) - i -= MOVE_DIAGONAL_COST; + i -= MOVE_COST*20; //When chasing, units will target a diamond-shaped area in range [Playtester] else i -= MOVE_COST; ud->to_x -= dirx[dir]; @@ -211,6 +211,7 @@ int unit_step_timer(int tid, int64 tick, int id, intptr_t data) int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { int i; int x,y,dx,dy; + unsigned char icewall_walk_block; uint8 dir; struct block_list *bl; struct map_session_data *sd; @@ -249,19 +250,29 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { dx = dirx[(int)dir]; dy = diry[(int)dir]; + //Get icewall walk block depending on boss mode (players can't be trapped) + if(md && md->status.mode&MD_BOSS) + icewall_walk_block = battle_config.boss_icewall_walk_block; + else if(md) + icewall_walk_block = battle_config.mob_icewall_walk_block; + else + icewall_walk_block = 0; + //Monsters will walk into an icewall from the west and south if they already started walking if(map->getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS) - && (battle_config.icewall_walk_block == 0 || !map->getcell(bl->m,x+dx,y+dy,CELL_CHKICEWALL) || dx < 0 || dy < 0)) + && (icewall_walk_block == 0 || !map->getcell(bl->m,x+dx,y+dy,CELL_CHKICEWALL) || dx < 0 || dy < 0)) return unit->walktoxy_sub(bl); //Monsters can only leave icewalls to the west and south //But if movement fails more than icewall_walk_block times, they can ignore this rule - if(md && md->walktoxy_fail_count < battle_config.icewall_walk_block && map->getcell(bl->m,x,y,CELL_CHKICEWALL) && (dx > 0 || dy > 0)) { + if(md && md->walktoxy_fail_count < icewall_walk_block && map->getcell(bl->m,x,y,CELL_CHKICEWALL) && (dx > 0 || dy > 0)) { //Needs to be done here so that rudeattack skills are invoked md->walktoxy_fail_count++; clif->fixpos(bl); + //Monsters in this situation first use a chase skill, then unlock target and then use an idle skill + if (!(++ud->walk_count%WALK_SKILL_INTERVAL)) + mob->skill_use(md, tick, -1); mob->unlocktarget(md, tick); - //Use idle skill at this point if (!(++ud->walk_count%WALK_SKILL_INTERVAL)) mob->skill_use(md, tick, -1); return 0; @@ -1060,6 +1071,17 @@ int unit_can_move(struct block_list *bl) { return 0; } + + // Icewall walk block special trapped monster mode + if(bl->type == BL_MOB) { + struct mob_data *md = BL_CAST(BL_MOB, bl); + if(md && ((md->status.mode&MD_BOSS && battle_config.boss_icewall_walk_block == 1 && map->getcell(bl->m,bl->x,bl->y,CELL_CHKICEWALL)) + || (!(md->status.mode&MD_BOSS) && battle_config.mob_icewall_walk_block == 1 && map->getcell(bl->m,bl->x,bl->y,CELL_CHKICEWALL)))) { + md->walktoxy_fail_count = 1; //Make sure rudeattacked skills are invoked + return 0; + } + } + return 1; } @@ -1384,6 +1406,12 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui } } break; + case AB_CLEARANCE: + if( target->type != BL_MOB && battle->check_target(src,target,BCT_PARTY) <= 0 && sd ) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0); + return 0; + } + break; case SR_GATEOFHELL: case SR_TIGERCANNON: if (sc && sc->data[SC_COMBOATTACK] && @@ -1584,6 +1612,12 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } + /** + * "WHY IS IT HEREE": ice wall cannot be canceled past this point, the client displays the animation even, + * if we cancel it from castend_pos, so it has to be here for it to not display the animation. + **/ + if ( skill_id == WZ_ICEWALL && map->getcell(src->m, skill_x, skill_y, CELL_CHKNOICEWALL) ) + return 0; } if (!status->check_skilluse(src, NULL, skill_id, 0)) |