diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/Makefile.in | 2 | ||||
-rw-r--r-- | src/map/atcommand.c | 42 | ||||
-rw-r--r-- | src/map/battle.c | 17 | ||||
-rw-r--r-- | src/map/battle.h | 1 | ||||
-rw-r--r-- | src/map/chrif.c | 7 | ||||
-rw-r--r-- | src/map/clif.c | 43 | ||||
-rw-r--r-- | src/map/clif.h | 2 | ||||
-rw-r--r-- | src/map/guild.c | 8 | ||||
-rw-r--r-- | src/map/map.c | 29 | ||||
-rw-r--r-- | src/map/map.h | 13 | ||||
-rw-r--r-- | src/map/mob.c | 53 | ||||
-rw-r--r-- | src/map/mob.h | 1 | ||||
-rw-r--r-- | src/map/npc.c | 75 | ||||
-rw-r--r-- | src/map/packets.h | 37 | ||||
-rw-r--r-- | src/map/path.c | 7 | ||||
-rw-r--r-- | src/map/pc.c | 171 | ||||
-rw-r--r-- | src/map/pc.h | 21 | ||||
-rw-r--r-- | src/map/script.c | 404 | ||||
-rw-r--r-- | src/map/script.h | 8 | ||||
-rw-r--r-- | src/map/skill.c | 57 | ||||
-rw-r--r-- | src/map/skill.h | 1 | ||||
-rw-r--r-- | src/map/status.c | 102 | ||||
-rw-r--r-- | src/map/unit.c | 35 |
23 files changed, 665 insertions, 471 deletions
diff --git a/src/map/Makefile.in b/src/map/Makefile.in index fc58c9d70..ee8b7ac56 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -104,7 +104,7 @@ map-server: ../../map-server@EXEEXT@ ../../map-server@EXEEXT@: $(MAP_SERVER_SQL_DEPENDS) Makefile @echo " LD $(notdir $@)" - @$(CC) @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_OBJ) $(COMMON_D)/obj_sql/common_sql.a \ + @$(CC) @STATIC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_OBJ) $(COMMON_D)/obj_sql/common_sql.a \ $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ # map object files diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 049adf1fc..ef528c454 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -583,7 +583,7 @@ ACMD(who) { iter = mapit_getallusers(); for (pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter)) { - if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pc_get_group_level(pl_sd) > level)) { // you can look only lower or same level + if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || pc_isinvisible(pl_sd)) && pc_get_group_level(pl_sd) > level)) { // you can look only lower or same level if (stristr(pl_sd->status.name, player_name) == NULL // search with no case sensitive || (map_id >= 0 && pl_sd->bl.m != map_id)) continue; @@ -689,7 +689,7 @@ ACMD(whogm) continue; } if (pl_level > level) { - if (pl_sd->sc.option & OPTION_INVISIBLE) + if (pc_isinvisible(pl_sd)) continue; sprintf(atcmd_output, msg_txt(913), pl_sd->status.name); // Name: %s (GM) clif->message(fd, atcmd_output); @@ -889,7 +889,7 @@ ACMD(option) * *------------------------------------------*/ ACMD(hide) { - if (sd->sc.option & OPTION_INVISIBLE) { + if (pc_isinvisible(sd)) { sd->sc.option &= ~OPTION_INVISIBLE; if (sd->disguise != -1 ) status->set_viewdata(&sd->bl, sd->disguise); @@ -3923,12 +3923,12 @@ ACMD(mount_peco) clif->message(fd, atcmd_output); return false; } - if( !(sd->sc.option&OPTION_DRAGON1) ) { + if (!pc_isridingdragon(sd)) { clif->message(sd->fd,msg_txt(1119)); // You have mounted your Dragon. - pc->setoption(sd, sd->sc.option|OPTION_DRAGON1); + pc->setridingdragon(sd, OPTION_DRAGON1); } else { clif->message(sd->fd,msg_txt(1120)); // You have released your Dragon. - pc->setoption(sd, sd->sc.option&~OPTION_DRAGON1); + pc->setridingdragon(sd, 0); } return true; } @@ -3940,34 +3940,34 @@ ACMD(mount_peco) } if( !pc_isridingwug(sd) ) { clif->message(sd->fd,msg_txt(1121)); // You have mounted your Warg. - pc->setoption(sd, sd->sc.option|OPTION_WUGRIDER); + pc->setridingwug(sd, true); } else { clif->message(sd->fd,msg_txt(1122)); // You have released your Warg. - pc->setoption(sd, sd->sc.option&~OPTION_WUGRIDER); + pc->setridingwug(sd, false); } return true; } if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) { if( !pc_ismadogear(sd) ) { clif->message(sd->fd,msg_txt(1123)); // You have mounted your Mado Gear. - pc->setoption(sd, sd->sc.option|OPTION_MADOGEAR); + pc->setmadogear(sd, true); } else { clif->message(sd->fd,msg_txt(1124)); // You have released your Mado Gear. - pc->setoption(sd, sd->sc.option&~OPTION_MADOGEAR); + pc->setmadogear(sd, false); } return true; } if( sd->class_&MAPID_SWORDMAN && sd->class_&JOBL_2 ) { - if( !pc_isriding(sd) ) { // if actually no peco + if (!pc_isridingpeco(sd)) { // if actually no peco if (!pc->checkskill(sd, KN_RIDING)) { sprintf(atcmd_output, msg_txt(213), skill->get_desc(KN_RIDING)); // You need %s to mount! clif->message(fd, atcmd_output); return false; } - pc->setoption(sd, sd->sc.option | OPTION_RIDING); + pc->setridingpeco(sd, true); clif->message(fd, msg_txt(102)); // You have mounted a Peco Peco. } else {//Dismount - pc->setoption(sd, sd->sc.option & ~OPTION_RIDING); + pc->setridingpeco(sd, false); clif->message(fd, msg_txt(214)); // You have released your Peco Peco. } return true; @@ -4621,8 +4621,7 @@ ACMD(disguise) return false; } - if(pc_isriding(sd)) - { + if (pc_hasmount(sd)) { clif->message(fd, msg_txt(1144)); // Character cannot be disguised while mounted. return false; } @@ -4709,8 +4708,8 @@ ACMD(disguiseguild) return false; } - for( i = 0; i < g->max_member; i++ ) - if( (pl_sd = g->member[i].sd) && !pc_isriding(pl_sd) ) + for (i = 0; i < g->max_member; i++) + if ((pl_sd = g->member[i].sd) && !pc_hasmount(pl_sd)) pc->disguise(pl_sd, id); clif->message(fd, msg_txt(122)); // Disguise applied. @@ -8358,15 +8357,16 @@ ACMD(charcommands) return true; } /* for new mounts */ -ACMD(mount2) { +ACMD(cashmount) +{ - if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) ) { + if (pc_hasmount(sd)) { clif->message(fd, msg_txt(1476)); // You are already mounting something else return false; } clif->message(sd->fd,msg_txt(1362)); // NOTICE: If you crash with mount your LUA is outdated. - if( !(sd->sc.data[SC_ALL_RIDING]) ) { + if (!sd->sc.data[SC_ALL_RIDING]) { clif->message(sd->fd,msg_txt(1363)); // You have mounted. sc_start(NULL,&sd->bl,SC_ALL_RIDING,100,0,-1); } else { @@ -9634,7 +9634,7 @@ void atcommand_basecommands(void) { ACMD_DEF2("rmvperm", addperm), ACMD_DEF(unloadnpcfile), ACMD_DEF(cart), - ACMD_DEF(mount2), + ACMD_DEF(cashmount), ACMD_DEF(join), ACMD_DEF(channel), ACMD_DEF(fontcolor), diff --git a/src/map/battle.c b/src/map/battle.c index 3b50d3507..1b8e44cb3 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -663,10 +663,10 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in break; case W_1HSPEAR: case W_2HSPEAR: - if((skill_lv = pc->checkskill(sd,KN_SPEARMASTERY)) > 0) { - if(pc_isridingdragon(sd)) + if ((skill_lv = pc->checkskill(sd,KN_SPEARMASTERY)) > 0) { + if (pc_isridingdragon(sd)) damage += (skill_lv * 10); - else if(pc_isriding(sd)) + else if (pc_isridingpeco(sd)) damage += (skill_lv * 5); else damage += (skill_lv * 4); @@ -6144,7 +6144,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f TBL_SKILL *su = (TBL_SKILL*)target; if( !su->group ) return 0; - if( skill->get_inf2(su->group->skill_id)&INF2_TRAP ) { //Only a few skills can target traps... + if( skill->get_inf2(su->group->skill_id)&INF2_TRAP && su->group->unit_id != UNT_USED_TRAPS) { //Only a few skills can target traps... switch( battle->get_current_skill(src) ) { case RK_DRAGONBREATH:// it can only hit traps in pvp/gvg maps case RK_DRAGONBREATH_WATER: @@ -6243,6 +6243,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f break; case BL_SKILL: { struct skill_unit *su = (struct skill_unit *)src; + struct status_change* sc = status->get_sc(target); if (!su->group) return 0; @@ -6253,6 +6254,11 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f if (inf2&INF2_TARGET_SELF) return 1; } + //Status changes that prevent traps from triggering + if (sc && sc->count && skill->get_inf2(su->group->skill_id)&INF2_TRAP) { + if( sc->data[SC_WZ_SIGHTBLASTER] && sc->data[SC_WZ_SIGHTBLASTER]->val2 > 0 && sc->data[SC_WZ_SIGHTBLASTER]->val4%2 == 0) + return -1; + } } break; case BL_MER: @@ -6830,7 +6836,8 @@ static const struct battle_data { { "guild_castle_expulsion", &battle_config.guild_castle_expulsion, 0, 0, 1, }, { "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, } + { "monster_chase_refresh", &battle_config.mob_chase_refresh, 1, 0, 30, }, + { "icewall_walk_block", &battle_config.icewall_walk_block, 75, 0, 255, } }; #ifndef STATS_OPT_OUT /** diff --git a/src/map/battle.h b/src/map/battle.h index 966fa073e..6ac2df391 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -452,6 +452,7 @@ 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] /** 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 a5928bc89..b9cd4cbaf 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -4785,7 +4785,9 @@ int clif_outsight(struct block_list *bl,va_list ap) } if (sd && sd->fd) { //sd is watching tbl go out of view. nullpo_ret(tbl); - if (((vd=status->get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS) && + if(tbl->type == BL_SKILL) //Trap knocked out of sight + clif->clearchar_skillunit((struct skill_unit *)tbl,sd->fd); + else if (((vd=status->get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS) && !(tbl->type == BL_NPC && (((TBL_NPC*)tbl)->option&OPTION_INVISIBLE))) clif->clearunit_single(tbl->id,CLR_OUTSIGHT,sd->fd); } @@ -5831,12 +5833,12 @@ void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type) unsigned char buf[32]; WBUFW(buf,0) = 0x19a; WBUFL(buf,2) = sd->bl.id; - if(sd->sc.option&(OPTION_HIDE|OPTION_CLOAK)) + if (sd->sc.option&(OPTION_HIDE|OPTION_CLOAK)) // TODO[Haru] Should this be pc_ishiding(sd)? (i.e. include Chase Walk and any new options) WBUFL(buf,6) = UINT32_MAX; //On client displays as -- else WBUFL(buf,6) = pvprank; WBUFL(buf,10) = pvpnum; - if(sd->sc.option&OPTION_INVISIBLE || sd->disguise != -1) //Causes crashes when a 'mob' with pvp info dies. + if (pc_isinvisible(sd) || sd->disguise != -1) //Causes crashes when a 'mob' with pvp info dies. clif->send(buf,packet_len(0x19a),&sd->bl,SELF); else if(!type) clif->send(buf,packet_len(0x19a),&sd->bl,AREA); @@ -9338,7 +9340,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { sd->state.hpmeter_visible = 1; } - if( !(sd->sc.option&OPTION_INVISIBLE) ) { // increment the number of pvp players on the map + if (!pc_isinvisible(sd)) { // increment the number of pvp players on the map map->list[sd->bl.m].users_pvp++; } @@ -9359,7 +9361,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { if( sd->bg_id ) clif->bg_hp(sd); // BattleGround System - if(map->list[sd->bl.m].flag.pvp && !(sd->sc.option&OPTION_INVISIBLE)) { + if (map->list[sd->bl.m].flag.pvp && !pc_isinvisible(sd)) { if(!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris] if (!map->list[sd->bl.m].flag.pvp_nocalcrank) sd->pvp_timer = timer->add(timer->gettick()+200, pc->calc_pvprank_timer, sd->bl.id, 0); @@ -9444,11 +9446,11 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { clif->updatestatus(sd,SP_SKILLPOINT); clif->initialstatus(sd); - if (sd->sc.option&OPTION_FALCON) + if (pc_isfalcon(sd)) clif->status_change(&sd->bl, SI_FALCON, 1, 0, 0, 0, 0); - if (sd->sc.option&(OPTION_RIDING|OPTION_DRAGON)) + if (pc_isridingpeco(sd) || pc_isridingdragon(sd)) clif->status_change(&sd->bl, SI_RIDING, 1, 0, 0, 0, 0); - else if (sd->sc.option&OPTION_WUGRIDER) + else if (pc_isridingwug(sd)) clif->status_change(&sd->bl, SI_WUGRIDER, 1, 0, 0, 0, 0); if(sd->status.manner < 0) @@ -10488,7 +10490,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) // if player ignores everyone if (dstsd->state.ignoreAll && pc_get_group_level(sd) <= pc_get_group_level(dstsd)) { - if (dstsd->sc.option & OPTION_INVISIBLE && pc_get_group_level(sd) < pc_get_group_level(dstsd)) + if (pc_isinvisible(dstsd) && pc_get_group_level(sd) < pc_get_group_level(dstsd)) clif->wis_end(fd, 1); // 1: target character is not logged in else clif->wis_end(fd, 3); // 3: everyone ignored by target @@ -11162,16 +11164,17 @@ void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd) /// 012a void clif_parse_RemoveOption(int fd,struct map_session_data *sd) { - if( !(sd->sc.option&(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR)) + if (pc_isridingpeco(sd) || pc_isfalcon(sd) || pc_isridingdragon(sd) || pc_ismadogear(sd)) { + // priority to remove this option before we can clear cart + pc->setoption(sd,sd->sc.option&~(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR)); + } else { #ifdef NEW_CARTS - && sd->sc.data[SC_PUSH_CART] ){ - pc->setcart(sd,0); -#else - ){ + if (sd->sc.data[SC_PUSH_CART]) + pc->setcart(sd,0); +#else // not NEW_CARTS pc->setoption(sd,sd->sc.option&~OPTION_CART); -#endif - }else // priority to remove this option before we can clear cart - pc->setoption(sd,sd->sc.option&~(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR)); +#endif // NEW_CARTS + } } @@ -15116,7 +15119,8 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd) if (body_len > MAIL_BODY_LENGTH) body_len = MAIL_BODY_LENGTH; - if( !mail->setattachment(sd, &msg) ) { // Invalid Append condition + memset(&msg, 0, sizeof(msg)); + if (!mail->setattachment(sd, &msg)) { // Invalid Append condition clif->mail_send(sd->fd, true); // fail mail->removeitem(sd,0); mail->removezeny(sd,0); @@ -15334,9 +15338,10 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) struct auction_data auction; struct item_data *item; - if( !battle_config.feature_auction ) + if (!battle_config.feature_auction) return; + memset(&auction, 0, sizeof(auction)); auction.price = RFIFOL(fd,2); auction.buynow = RFIFOL(fd,6); auction.hours = RFIFOW(fd,10); diff --git a/src/map/clif.h b/src/map/clif.h index bb71db5ae..1013add85 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -18,8 +18,6 @@ **/ struct item; struct item_data; -struct storage_data; -struct guild_storage; struct unit_data; struct map_session_data; struct homun_data; diff --git a/src/map/guild.c b/src/map/guild.c index 595711755..1d9cf03a9 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -459,6 +459,8 @@ int guild_recv_info(struct guild *sg) { struct map_session_data *sd; bool guild_new = false; struct hChSysCh *aChSysSave = NULL; + short *instance_save = NULL; + unsigned short instances_save = 0; nullpo_ret(sg); @@ -538,10 +540,16 @@ int guild_recv_info(struct guild *sg) { before=*g; if( g->channel ) aChSysSave = g->channel; + if( g->instance ) + instance_save = g->instance; + if( g->instances ) + instances_save = g->instances; } memcpy(g,sg,sizeof(struct guild)); g->channel = aChSysSave; + g->instance = instance_save; + g->instances = instances_save; if(g->max_member > MAX_GUILD) { ShowError("guild_recv_info: Received guild with %d members, but MAX_GUILD is only %d. Extra guild-members have been lost!\n", g->max_member, MAX_GUILD); diff --git a/src/map/map.c b/src/map/map.c index 14af392b7..045233e91 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -2420,28 +2420,27 @@ uint8 map_calc_dir(struct block_list* src, int16 x, int16 y) } else if( dx >= 0 && dy >=0 ) { // upper-right - if( dx*2 <= dy ) dir = 0; // up - else if( dx > dy*2 ) dir = 6; // right - else dir = 7; // up-right + if( dx*2 < dy || dx == 0 ) dir = 0; // up + else if( dx > dy*2+1 || dy == 0 ) dir = 6; // right + else dir = 7; // up-right } else if( dx >= 0 && dy <= 0 ) { // lower-right - if( dx*2 <= -dy ) dir = 4; // down - else if( dx > -dy*2 ) dir = 6; // right - else dir = 5; // down-right + if( dx*2 < -dy || dx == 0 ) dir = 4; // down + else if( dx > -dy*2+1 || dy == 0 ) dir = 6; // right + else dir = 5; // down-right } else if( dx <= 0 && dy <= 0 ) { // lower-left - if( dx*2 >= dy ) dir = 4; // down - else if( dx < dy*2 ) dir = 2; // left - else dir = 3; // down-left + if( dx*2 > dy || dx == 0 ) dir = 4; // down + else if( dx < dy*2-1 || dy == 0 ) dir = 2; // left + else dir = 3; // down-left } else { // upper-left - if( -dx*2 <= dy ) dir = 0; // up - else if( -dx > dy*2 ) dir = 2; // left - else dir = 1; // up-left - + if( -dx*2 < dy || dx == 0 ) dir = 0; // up + else if( -dx > dy*2+1 || dy == 0) dir = 2; // left + else dir = 1; // up-left } return dir; } @@ -2587,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: @@ -2646,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; diff --git a/src/map/map.h b/src/map/map.h index c36f905ef..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. @@ -658,13 +661,7 @@ struct map_data { int jexp; // map experience multiplicator int bexp; // map experience multiplicator int nocommand; //Blocks @/# commands for non-gms. [Skotlex] - /** - * Ice wall reference counter for bugreport:3574 - * - since there are a thousand mobs out there in a lot of maps checking on, - * - every targeting for icewall on attack path would just be a waste, so, - * - this counter allows icewall checking be only run when there is a actual ice wall on the map - **/ - int icewall_num; + // Instance Variables int instance_id; int instance_src_map; diff --git a/src/map/mob.c b/src/map/mob.c index 122cc91aa..eaf8c8468 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1076,15 +1076,6 @@ int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) && battle->check_range(&md->bl,bl,md->db->range2) ) { //Pick closest target? - - if( map->list[bl->m].icewall_num && - !path->search_long(NULL,bl->m,md->bl.x,md->bl.y,bl->x,bl->y,CELL_CHKICEWALL) ) { - - if( !check_distance_bl(&md->bl, bl, status_get_range(&md->bl) ) ) - return 0; - - } - (*target) = bl; md->target_id=bl->id; md->min_chase= dist + md->db->range3; @@ -1288,8 +1279,7 @@ int mob_unlocktarget(struct mob_data *md, int64 tick) { md->state.skillstate = MSS_IDLE; case MSS_IDLE: // Idle skill. - if ((md->target_id || !(++md->ud.walk_count%IDLE_SKILL_INTERVAL)) && - mob->skill_use(md, tick, -1)) + if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL) && mob->skill_use(md, tick, -1)) break; //Random walk. if (!md->master_id && @@ -1457,6 +1447,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { || 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->state.attacked_count++ >= RUDE_ATTACKED_COUNT && !mob->skill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack @@ -1479,6 +1470,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { || 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 ) ) ) { @@ -1551,7 +1543,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { } } - //This handles triggering idle walk/skill. + //This handles triggering idle/walk skill. mob->unlocktarget(md, tick); return true; } @@ -1611,8 +1603,8 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { //Attempt to attack. //At this point we know the target is attackable, we just gotta check if the range matches. - if (battle->check_range (&md->bl, tbl, md->status.rhw.range)) - { //Target within range, engage + if (battle->check_range(&md->bl, tbl, md->status.rhw.range) && !(md->sc.option&OPTION_HIDE)) + { //Target within range and able to use normal attack, engage if (md->ud.target != tbl->id || md->ud.attacktimer == INVALID_TIMER) { //Only attack if no more attack delay left if(tbl->type == BL_PC) @@ -1632,27 +1624,30 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { return true; } + //Monsters in berserk state, unable to use normal attacks, will always attempt a skill + if(md->ud.walktimer == INVALID_TIMER && (md->state.skillstate == MSS_BERSERK || md->state.skillstate == MSS_ANGRY)) { + if (DIFF_TICK(md->ud.canmove_tick, tick) <= MIN_MOBTHINKTIME && DIFF_TICK(md->ud.canact_tick, tick) < -MIN_MOBTHINKTIME*IDLE_SKILL_INTERVAL) + { //Only use skill if able to walk on next tick and not used a skill the last second + mob->skill_use(md, tick, -1); + } + } + + //Target still in attack range, no need to chase the target + if(battle->check_range(&md->bl, tbl, md->status.rhw.range)) + return true; + + //Out of range... if (!(mode&MD_CANMOVE) || (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0)) - { //Can't chase. Immobile and trapped mobs should unlock target and use an idle skill on next interval. - if ((md->ud.target != tbl->id || md->ud.attacktimer == INVALID_TIMER)) - { //Only unlock target to use idle skill if no more attack left - md->ud.walk_count = (md->ud.walk_count+1)%250; - if (!(md->ud.walk_count%IDLE_SKILL_INTERVAL)) - mob_unlocktarget(md,tick); + { //Can't chase. Immobile and trapped mobs should unlock target and use an idle skill. + if (md->ud.attacktimer == INVALID_TIMER) + { //Only unlock target if no more attack delay left + //This handles triggering idle/walk skill. + mob->unlocktarget(md,tick); } return true; } - //Before a monster starts to chase a target, it will check if it has a ranged "attack" skill to use on it. - if(md->ud.walktimer == INVALID_TIMER && (md->state.skillstate == MSS_BERSERK || md->state.skillstate == MSS_ANGRY)) - { - if (DIFF_TICK(md->ud.canmove_tick, tick) <= MIN_MOBTHINKTIME && DIFF_TICK(md->ud.canact_tick, tick) < -MIN_MOBTHINKTIME*IDLE_SKILL_INTERVAL) - { //Only use skill if able to walk on next tick and not used a skill the last second - mob->skill_use(md, tick, -1); - } - } - if (md->ud.walktimer != INVALID_TIMER && md->ud.target == tbl->id && ( !(battle_config.mob_ai&0x1) || diff --git a/src/map/mob.h b/src/map/mob.h index 4df96d7f8..848bfbb2f 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -171,6 +171,7 @@ struct mob_data { short move_fail_count; short lootitem_count; short min_chase; + unsigned char walktoxy_fail_count; //Pathfinding succeeds but the actual walking failed (e.g. Icewall lock) int deletetimer; int master_id,master_dist; diff --git a/src/map/npc.c b/src/map/npc.c index a33db6b99..7378ac470 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1818,11 +1818,11 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { for( i = 0; i < n; ++i ) { int nameid = item_list[i*2+1]; int amount = item_list[i*2+0]; - struct item item_tmp; - if (itemdb_type(nameid) == IT_PETEGG) + if (itemdb_type(nameid) == IT_PETEGG) { pet->create_egg(sd, nameid); - else { + } else { + struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); item_tmp.nameid = nameid; item_tmp.identify = 1; @@ -1933,7 +1933,6 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st for( i = 0; i < list_size; ++i ) { int nameid = p->list[i].ITID; int amount = p->list[i].qty; - struct item item_tmp; j = npc_market_qty[i]; @@ -1944,9 +1943,10 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st npc->market_tosql(nd,j); - if (itemdb_type(nameid) == IT_PETEGG) + if (itemdb_type(nameid) == IT_PETEGG) { pet->create_egg(sd, nameid); - else { + } else { + struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); item_tmp.nameid = nameid; item_tmp.identify = 1; @@ -3324,8 +3324,8 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c struct event_data* ev = (struct event_data*)strdb_get(npc->ev_db, eventname); struct npc_data *nd; struct script_state *st; - int i = 0, j = 0, k = 0; - char *temp; + int i = 0, nargs = 0; + size_t len; nullpo_ret(sd); @@ -3353,27 +3353,29 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c st = script->alloc_state(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id); script->setd_sub(st, NULL, ".@atcmd_command$", 0, (void *)command, NULL); - // split atcmd parameters based on spaces - temp = (char*)aMalloc(strlen(message) + 1); - - for( i = 0; i < ( strlen( message ) + 1 ) && k < 127; i ++ ) { - if( message[i] == ' ' || message[i] == '\0' ) { - if( message[ ( i - 1 ) ] == ' ' ) { - continue; // To prevent "@atcmd [space][space]" and .@atcmd_numparameters return 1 without any parameter. - } - temp[k] = '\0'; - k = 0; - if( temp[0] != '\0' ) { - script->setd_sub( st, NULL, ".@atcmd_parameters$", j++, (void *)temp, NULL ); + len = strlen(message); + if (len) { + char *temp, *p; + p = temp = aStrdup(message); + // Sanity check - Skip leading spaces (shouldn't happen) + while (i <= len && temp[i] == ' ') { + p++; + i++; + } + // split atcmd parameters based on spaces + while (i <= len) { + if (temp[i] != ' ' && temp[i] != '\0') { + i++; + continue; } - } else { - temp[k] = message[i]; - k++; + temp[i] = '\0'; + script->setd_sub(st, NULL, ".@atcmd_parameters$", nargs++, (void *)p, NULL); + i++; + p = temp + i; } + aFree(temp); } - - script->setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)h64BPTRSIZE(j), NULL); - aFree(temp); + script->setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)h64BPTRSIZE(nargs), NULL); script->run_main(st); return 0; @@ -4179,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 ) DeprecationWarning("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); } } @@ -4206,22 +4205,6 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { } else { -#ifdef ENABLE_CASE_CHECK - if( strcasecmp(w2, "warp") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "warp", filepath, strline(buffer, p-buffer)); } // TODO - else if( strcasecmp(w2,"shop") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "shop", filepath, strline(buffer, p-buffer)); } // TODO - else if( strcasecmp(w2,"cashshop") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "cashshop", filepath, strline(buffer, p-buffer)); } // TODO - else if( strcasecmp(w2, "script") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "script", filepath, strline(buffer, p-buffer)); } // TODO - else if( strcasecmp(w2,"trader") == 0 ) DeprecationWarning("npc_parsesrcfile", w2, "trader", filepath, strline(buffer, p-buffer)) // TODO - else if( strncasecmp(w2, "duplicate", 9) == 0 ) { - char temp[10]; - safestrncpy(temp, w2, 10); - DeprecationWarning("npc_parsesrcfile", temp, "duplicate", filepath, strline(buffer, p-buffer)); // TODO - } - else if( strcasecmp(w2,"monster") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "monster", filepath, strline(buffer, p-buffer)); } // TODO: - else if( strcasecmp(w2,"boss_monster") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "boss_monster", filepath, strline(buffer, p-buffer)); } // TODO - else if( strcasecmp(w2, "mapflag") == 0 ) { DeprecationWarning("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; @@ -4293,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 ) { - DeprecationWarning2("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/packets.h b/src/map/packets.h index 810f341d4..699bb3fd2 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -2767,6 +2767,39 @@ packet(0x020d,-1); packet(0x09DF,7); #endif +// 2014-10-22bRagexe - YomRawr +#if PACKETVER >= 20141022 + packet(0x0369,7,clif->pActionRequest,2,6); + packet(0x083C,10,clif->pUseSkillToId,2,4,6); + packet(0x0437,5,clif->pWalkToXY,2); + packet(0x035F,6,clif->pTickSend,2); + packet(0x08AD,5,clif->pChangeDir,2,4); + packet(0x094E,6,clif->pTakeItem,2); + packet(0x087D,6,clif->pDropItem,2,4); + packet(0x0878,8,clif->pMoveToKafra,2,4); + packet(0x08AA,8,clif->pMoveFromKafra,2,4); + packet(0x023B,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x096A,6,clif->pGetCharNameRequest,2); + packet(0x0368,6,clif->pSolveCharName,2); + packet(0x0835,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x0940,2,clif->pSearchStoreInfoNextPage,0); + packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x0360,6,clif->pReqClickBuyingStore,2); + packet(0x0817,2,clif->pReqCloseBuyingStore,0); + packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x0955,18,clif->pPartyBookingRegisterReq,2,4); + // packet(0x092B,8); // CZ_JOIN_BATTLE_FIELD + packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x093B,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0896,26,clif->pPartyInvite2,2); + // packet(0x08AB,4); // CZ_GANGSI_RANK + packet(0x091A,26,clif->pFriendsListAdd,2); + packet(0x0899,5,clif->pHomMenu,2,4); + packet(0x0438,36,clif->pStoragePassword,0); +#endif + /* PacketKeys: http://hercules.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */ #if PACKETVER >= 20110817 packetKeys(0x053D5CED,0x3DED6DED,0x6DED6DED); /* Thanks to Shakto */ @@ -2998,6 +3031,10 @@ packet(0x020d,-1); packetKeys(0x04810281,0x42814281,0x42814281); /* Themon */ #endif +#if PACKETVER >= 20141022 + packetKeys(0x290551EA,0x2B952C75,0x2D67669B); /* YomRawr */ +#endif + #if defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3) packetKeys(OBFUSCATIONKEY1,OBFUSCATIONKEY2,OBFUSCATIONKEY3); #endif diff --git a/src/map/path.c b/src/map/path.c index 681dfcb06..d8096ad43 100644 --- a/src/map/path.c +++ b/src/map/path.c @@ -129,9 +129,6 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16 spd->x[0] = x0; spd->y[0] = y0; - if (md->getcellp(md,x1,y1,cell)) - return false; - if (dx > abs(dy)) { weight = dx; spd->ry = 1; @@ -142,8 +139,6 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16 while (x0 != x1 || y0 != y1) { - if (md->getcellp(md,x0,y0,cell)) - return false; wx += dx; wy += dy; if (wx >= weight) { @@ -163,6 +158,8 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16 spd->y[spd->len] = y0; spd->len++; } + if (md->getcellp(md,x0,y0,cell)) + return false; } return true; diff --git a/src/map/pc.c b/src/map/pc.c index 71860340d..85dab4559 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1320,7 +1320,7 @@ int pc_reg_received(struct map_session_data *sd) clif->pLoadEndAck(sd->fd, sd); } - if( sd->sc.option & OPTION_INVISIBLE ) { + if (pc_isinvisible(sd)) { sd->vd.class_ = INVISIBLE_CLASS; clif->message(sd->fd, msg_txt(11)); // Invisible: On // decrement the number of pvp players on the map @@ -1729,7 +1729,7 @@ int pc_disguise(struct map_session_data *sd, int class_) { if (class_ >= 0 && sd->disguise == class_) return 0; - if(sd->sc.option&OPTION_INVISIBLE) { //Character is invisible. Stealth class-change. [Skotlex] + if (pc_isinvisible(sd)) { //Character is invisible. Stealth class-change. [Skotlex] sd->disguise = class_; //viewdata is set on uncloaking. return 2; } @@ -4471,7 +4471,7 @@ int pc_useitem(struct map_session_data *sd,int n) { } else {// not yet used item (all slots are initially empty) sd->item_delay[i].nameid = nameid; } - if( !(nameid == ITEMID_REINS_OF_MOUNT && sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR)) ) + if (!(nameid == ITEMID_REINS_OF_MOUNT && pc_hasmount(sd))) sd->item_delay[i].tick = tick + sd->inventory_data[n]->delay; } else {// should not happen ShowError("pc_useitem: Exceeded item delay array capacity! (nameid=%d, char_id=%d)\n", nameid, sd->status.char_id); @@ -8143,84 +8143,111 @@ int pc_setcart(struct map_session_data *sd,int type) { return 0; } -/*========================================== - * Give player a falcon - *------------------------------------------*/ -int pc_setfalcon(TBL_PC* sd, int flag) +/* FIXME: These setter methods are inconsistent in their class/skill checks. + They should be changed so that they all either do or skip the checks.*/ + +/** + * Gives/removes a falcon. + * + * The target player needs the required skills in order to obtain a falcon. + * + * @param sd Target player. + * @param flag New state. + **/ +void pc_setfalcon(TBL_PC* sd, bool flag) { - if( flag ){ - if( pc->checkskill(sd,HT_FALCON)>0 ) // add falcon if he have the skill + if (flag) { + if (pc->checkskill(sd,HT_FALCON) > 0) // add falcon if he have the skill pc->setoption(sd,sd->sc.option|OPTION_FALCON); - } else if( pc_isfalcon(sd) ){ + } else if (pc_isfalcon(sd)) { pc->setoption(sd,sd->sc.option&~OPTION_FALCON); // remove falcon } - - return 0; } -/*========================================== - * Set player riding - *------------------------------------------*/ -int pc_setriding(TBL_PC* sd, int flag) +/** + * Mounts/dismounts a Peco or Gryphon. + * + * The target player needs the required skills in order to mount a peco. + * + * @param sd Target player. + * @param flag New state. + **/ +void pc_setridingpeco(TBL_PC* sd, bool flag) { - if( flag ) - { - // Rune Knight (Dragon) - if( (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT ) { - if( pc->checkskill(sd, RK_DRAGONTRAINING) ) - pc->setoption(sd, sd->sc.option|flag); - } - // Ranger (Warg) - else if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) { - if( pc->checkskill(sd, RA_WUGRIDER) ) - pc->setoption(sd,sd->sc.option|OPTION_WUGRIDER); - } - // Mechanic (Mado Gear) - else if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) { - if( pc->checkskill(sd, NC_MADOLICENCE) ) - pc->setoption(sd, sd->sc.option|OPTION_MADOGEAR); - } - // Knight / Crusader (Peco Peco) - else { - if( pc->checkskill(sd, KN_RIDING) ) - pc->setoption(sd, sd->sc.option|OPTION_RIDING); - } - } - else if( pc_isriding(sd) ) - { - // Rune Knight (Dragon) - if( (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT ) { - pc->setoption(sd, sd->sc.option&~OPTION_DRAGON); - } - // Ranger (Warg) - else if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) { - pc->setoption(sd,sd->sc.option&~OPTION_WUGRIDER); - } - // Mechanic (Mado Gear) - else if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) { - pc->setoption(sd, sd->sc.option&~OPTION_MADOGEAR); - } - // Knight / Crusaders (Peco Peco) - else { - pc->setoption(sd, sd->sc.option&~OPTION_RIDING); - } + if (flag) { + if (pc->checkskill(sd, KN_RIDING)) + pc->setoption(sd, sd->sc.option|OPTION_RIDING); + } else if (pc_isridingpeco(sd)) { + pc->setoption(sd, sd->sc.option&~OPTION_RIDING); } - - return 0; } /** - * Gives player a mado - * @param flag 1 Set mado + * Gives/removes a Mado Gear. + * + * The target player needs to be the correct class in order to obtain a mado gear. + * + * @param sd Target player. + * @param flag New state. **/ -void pc_setmadogear( struct map_session_data *sd, int flag ) { - if( flag ) { - if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) +void pc_setmadogear(struct map_session_data *sd, bool flag) +{ + if (flag) { + if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC) pc->setoption(sd, sd->sc.option|OPTION_MADOGEAR); - } else if( pc_ismadogear(sd) ) + } else if (pc_ismadogear(sd)) { pc->setoption(sd, sd->sc.option&~OPTION_MADOGEAR); + } +} - return; +/** + * Mounts/dismounts a dragon. + * + * The target player needs the required skills in order to mount a dragon. + * + * @param sd Target player. + * @param type New state. This must be a valid OPTION_DRAGON* or 0. + **/ +void pc_setridingdragon(TBL_PC* sd, unsigned int type) +{ + if (type&OPTION_DRAGON) { + // Ensure only one dragon is set at a time. + if (type&OPTION_DRAGON1) + type = OPTION_DRAGON1; + else if (type&OPTION_DRAGON2) + type = OPTION_DRAGON2; + else if (type&OPTION_DRAGON3) + type = OPTION_DRAGON3; + else if (type&OPTION_DRAGON4) + type = OPTION_DRAGON4; + else if (type&OPTION_DRAGON5) + type = OPTION_DRAGON5; + else + type = OPTION_DRAGON1; + + if (pc->checkskill(sd, RK_DRAGONTRAINING)) + pc->setoption(sd, (sd->sc.option&~OPTION_DRAGON)|type); + } else if (pc_isridingdragon(sd)) { + pc->setoption(sd,sd->sc.option&~OPTION_DRAGON); // remove dragon + } +} + +/** + * Mounts/dismounts a wug. + * + * The target player needs the required skills in order to mount a wug. + * + * @param sd Target player. + * @param flag New state. + **/ +void pc_setridingwug(TBL_PC* sd, bool flag) +{ + if (flag) { + if (pc->checkskill(sd, RA_WUGRIDER) > 0) + pc->setoption(sd,sd->sc.option|OPTION_WUGRIDER); + } else if (pc_isridingwug(sd)) { + pc->setoption(sd,sd->sc.option&~OPTION_WUGRIDER); // remove wug + } } /** @@ -9329,8 +9356,8 @@ int pc_calc_pvprank_sub(struct block_list *bl,va_list ap) sd1=(struct map_session_data *)bl; sd2=va_arg(ap,struct map_session_data *); - if( sd1->sc.option&OPTION_INVISIBLE || sd2->sc.option&OPTION_INVISIBLE ) - {// cannot register pvp rank for hidden GMs + if (pc_isinvisible(sd1) ||pc_isinvisible(sd2)) { + // cannot register pvp rank for hidden GMs return 0; } @@ -9364,8 +9391,8 @@ int pc_calc_pvprank_timer(int tid, int64 tick, int id, intptr_t data) { return 0; sd->pvp_timer = INVALID_TIMER; - if( sd->sc.option&OPTION_INVISIBLE ) - {// do not calculate the pvp rank for a hidden GM + if (pc_isinvisible(sd)) { + // do not calculate the pvp rank for a hidden GM return 0; } @@ -11003,8 +11030,10 @@ void pc_defaults(void) { pc->setoption = pc_setoption; pc->setcart = pc_setcart; pc->setfalcon = pc_setfalcon; - pc->setriding = pc_setriding; + pc->setridingpeco = pc_setridingpeco; pc->setmadogear = pc_setmadogear; + pc->setridingdragon = pc_setridingdragon; + pc->setridingwug = pc_setridingwug; pc->changelook = pc_changelook; pc->equiplookall = pc_equiplookall; diff --git a/src/map/pc.h b/src/map/pc.h index 6159a8f26..580908692 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -589,19 +589,20 @@ struct map_session_data { #endif #define pc_isfalcon(sd) ( (sd)->sc.option&OPTION_FALCON ) -#define pc_isriding(sd) ( (sd)->sc.option&(OPTION_RIDING|OPTION_DRAGON|OPTION_WUGRIDER|OPTION_MADOGEAR) ) #define pc_isinvisible(sd) ( (sd)->sc.option&OPTION_INVISIBLE ) #define pc_is50overweight(sd) ( (sd)->weight*100 >= (sd)->max_weight*battle->bc->natural_heal_weight_rate ) #define pc_is90overweight(sd) ( (sd)->weight*10 >= (sd)->max_weight*9 ) #define pc_maxparameter(sd) ( (((sd)->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO || ((sd)->class_&MAPID_UPPERMASK) == MAPID_REBELLION || ((sd)->class_&MAPID_THIRDMASK) == MAPID_SUPER_NOVICE_E) ? battle->bc->max_extended_parameter : (sd)->class_&JOBL_THIRD ? ((sd)->class_&JOBL_BABY ? battle->bc->max_baby_third_parameter : battle->bc->max_third_parameter) : ((sd)->class_&JOBL_BABY ? battle->bc->max_baby_parameter : battle->bc->max_parameter) ) -/** - * Ranger - **/ +/// Generic check for mounts +#define pc_hasmount(sd) ( (sd)->sc.option&(OPTION_RIDING|OPTION_WUGRIDER|OPTION_DRAGON|OPTION_MADOGEAR) ) +/// Knight classes Peco / Gryphon +#define pc_isridingpeco(sd) ( (sd)->sc.option&(OPTION_RIDING) ) +/// Ranger Warg #define pc_iswug(sd) ( (sd)->sc.option&OPTION_WUG ) #define pc_isridingwug(sd) ( (sd)->sc.option&OPTION_WUGRIDER ) -// Mechanic Magic Gear +/// Mechanic Magic Gear #define pc_ismadogear(sd) ( (sd)->sc.option&OPTION_MADOGEAR ) -// Rune Knight Dragon +/// Rune Knight Dragon #define pc_isridingdragon(sd) ( (sd)->sc.option&OPTION_DRAGON ) #define pc_stop_walking(sd, type) (unit->stop_walking(&(sd)->bl, (type))) @@ -897,9 +898,11 @@ struct pc_interface { int (*jobchange) (struct map_session_data *sd,int job, int upper); int (*setoption) (struct map_session_data *sd,int type); int (*setcart) (struct map_session_data* sd, int type); - int (*setfalcon) (struct map_session_data* sd, int flag); - int (*setriding) (struct map_session_data* sd, int flag); - void (*setmadogear) (struct map_session_data* sd, int flag); + void (*setfalcon) (struct map_session_data *sd, bool flag); + void (*setridingpeco) (struct map_session_data *sd, bool flag); + void (*setmadogear) (struct map_session_data *sd, bool flag); + void (*setridingdragon) (struct map_session_data *sd, unsigned int type); + void (*setridingwug) (struct map_session_data *sd, bool flag); int (*changelook) (struct map_session_data *sd,int type,int val); int (*equiplookall) (struct map_session_data *sd); diff --git a/src/map/script.c b/src/map/script.c index 77b60ddd2..1885c3c2c 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -526,7 +526,7 @@ int script_add_str(const char* p) } } if( existingentry ) { - DeprecationWarning2("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)); @@ -7013,28 +6970,25 @@ BUILDIN(delitem) { TBL_PC *sd; struct item it; - if( script_hasdata(st,4) ) - { + if (script_hasdata(st,4)) { int account_id = script_getnum(st,4); sd = map->id2sd(account_id); // <account id> - if( sd == NULL ) - { + if (sd == NULL) { ShowError("script:delitem: player not found (AID=%d).\n", account_id); st->state = END; return false; } - } - else - { + } else { sd = script->rid2sd(st);// attached player - if( sd == NULL ) + if (sd == NULL) return true; } - if( script_isstringtype(st, 2) ) { + memset(&it, 0, sizeof(it)); + if (script_isstringtype(st, 2)) { const char* item_name = script_getstr(st, 2); struct item_data* id = itemdb->search_name(item_name); - if( id == NULL ) { + if (id == NULL) { ShowError("script:delitem: unknown item \"%s\".\n", item_name); st->state = END; return false; @@ -7042,8 +6996,7 @@ BUILDIN(delitem) { it.nameid = id->nameid;// "<item name>" } else { it.nameid = script_getnum(st, 2);// <item id> - if( !itemdb->exists( it.nameid ) ) - { + if (!itemdb->exists(it.nameid)) { ShowError("script:delitem: unknown item \"%d\".\n", it.nameid); st->state = END; return false; @@ -7074,26 +7027,25 @@ BUILDIN(delitem2) { TBL_PC *sd; struct item it; - if( script_hasdata(st,11) ) { + if (script_hasdata(st,11)) { int account_id = script_getnum(st,11); sd = map->id2sd(account_id); // <account id> - if( sd == NULL ) { + if (sd == NULL) { ShowError("script:delitem2: player not found (AID=%d).\n", account_id); st->state = END; return false; } - } - else - { + } else { sd = script->rid2sd(st);// attached player if( sd == NULL ) return true; } - if( script_isstringtype(st, 2) ) { + memset(&it, 0, sizeof(it)); + if (script_isstringtype(st, 2)) { const char* item_name = script_getstr(st, 2); struct item_data* id = itemdb->search_name(item_name); - if( id == NULL ) { + if (id == NULL) { ShowError("script:delitem2: unknown item \"%s\".\n", item_name); st->state = END; return false; @@ -7667,11 +7619,11 @@ BUILDIN(getbrokencount) sd = script->rid2sd(st); - if( sd == NULL ) + if (sd == NULL) return true; - for(i = 0; i < MAX_INVENTORY; i++) { - if(sd->status.inventory[i].attribute) + for (i = 0; i < MAX_INVENTORY; i++) { + if (sd->status.inventory[i].attribute) counter++; } @@ -8635,10 +8587,10 @@ BUILDIN(checkfalcon) TBL_PC* sd; sd = script->rid2sd(st); - if( sd == NULL ) + if (sd == NULL) return true;// no player attached, report source - if( pc_isfalcon(sd) ) + if (pc_isfalcon(sd)) script_pushint(st, 1); else script_pushint(st, 0); @@ -8653,15 +8605,15 @@ BUILDIN(checkfalcon) /// setfalcon; BUILDIN(setfalcon) { - int flag = 1; + bool flag = true; TBL_PC* sd; sd = script->rid2sd(st); - if( sd == NULL ) + if (sd == NULL) return true;// no player attached, report source - if( script_hasdata(st,2) ) - flag = script_getnum(st,2); + if (script_hasdata(st,2)) + flag = script_getnum(st,2) ? true : false; pc->setfalcon(sd, flag); @@ -8678,10 +8630,10 @@ BUILDIN(checkriding) TBL_PC* sd; sd = script->rid2sd(st); - if( sd == NULL ) - return true;// no player attached, report source + if (sd == NULL) + return true; // no player attached, report source - if( pc_isriding(sd) ) + if (pc_hasmount(sd)) script_pushint(st, 1); else script_pushint(st, 0); @@ -8701,17 +8653,143 @@ BUILDIN(setriding) sd = script->rid2sd(st); - if( sd == NULL ) + if (sd == NULL) return true;// no player attached, report source - if( script_hasdata(st,2) ) + if (script_hasdata(st,2)) flag = script_getnum(st,2); + pc->setridingpeco(sd, flag ? true : false); - // Color variants for Rune Knight dragon mounts. - if( (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT ) - flag = (flag == 1 ? OPTION_DRAGON1 : flag == 2 ? OPTION_DRAGON2 : flag == 3 ? OPTION_DRAGON3 : flag == 4 ? OPTION_DRAGON4 : flag == 5 ? OPTION_DRAGON5 : 0); + return true; +} + +enum setmount_type { + SETMOUNT_TYPE_AUTODETECT = -1, + SETMOUNT_TYPE_NONE = 0, + SETMOUNT_TYPE_PECO = 1, + SETMOUNT_TYPE_WUG = 2, + SETMOUNT_TYPE_MADO = 3, + SETMOUNT_TYPE_DRAGON_GREEN = 4, + SETMOUNT_TYPE_DRAGON_BROWN = 5, + SETMOUNT_TYPE_DRAGON_GRAY = 6, + SETMOUNT_TYPE_DRAGON_BLUE = 7, + SETMOUNT_TYPE_DRAGON_RED = 8, + SETMOUNT_TYPE_MAX, + SETMOUNT_TYPE_DRAGON = SETMOUNT_TYPE_DRAGON_GREEN, +}; + +/** + * Checks if the player is riding a combat mount. + * + * Returns 0 if the player isn't riding, and non-zero if it is. + * The exact returned values are the same used as flag in setmount, except for + * dragons, where SETMOUNT_TYPE_DRAGON is returned, regardless of color. + */ +BUILDIN(checkmount) +{ + TBL_PC* sd; - pc->setriding(sd, flag); + sd = script->rid2sd(st); + if (sd == NULL) + return true; // no player attached, report source + + if (!pc_hasmount(sd)) { + script_pushint(st, SETMOUNT_TYPE_NONE); + } else if (pc_isridingpeco(sd)) { + script_pushint(st, SETMOUNT_TYPE_PECO); + } else if (pc_isridingwug(sd)) { + script_pushint(st, SETMOUNT_TYPE_WUG); + } else if (pc_ismadogear(sd)) { + script_pushint(st, SETMOUNT_TYPE_MADO); + } else { // if (pc_isridingdragon(sd)) + script_pushint(st, SETMOUNT_TYPE_DRAGON); + } + + return true; +} + +/** + * Mounts or dismounts a combat mount. + * + * setmount <flag>; + * setmount; + * + * Accepted values for flag: + * MOUNT_NONE - dismount + * MOUNT_PECO - Peco Peco / Grand Peco / Gryphon (depending on the class) + * MOUNT_WUG - Wug (Rider) + * MOUNT_MADO - Mado Gear + * MOUNT_DRAGON - Dragon (default color) + * MOUNT_DRAGON_GREEN - Green Dragon + * MOUNT_DRAGON_BROWN - Brown Dragon + * MOUNT_DRAGON_GRAY - Gray Dragon + * MOUNT_DRAGON_BLUE - Blue Dragon + * MOUNT_DRAGON_RED - Red Dragon + * + * If an invalid value or no flag is specified, the appropriate mount is + * auto-detected. As a result of this, there is no need to specify a flag at + * all, unless it is a dragon color other than green. + */ +BUILDIN(setmount) +{ + int flag = SETMOUNT_TYPE_AUTODETECT; + TBL_PC* sd; + + sd = script->rid2sd(st); + + if (sd == NULL) + return true;// no player attached, report source + + if (script_hasdata(st,2)) + flag = script_getnum(st,2); + + // Color variants for Rune Knight dragon mounts. + if (flag != SETMOUNT_TYPE_NONE) { + if (flag < SETMOUNT_TYPE_AUTODETECT || flag >= SETMOUNT_TYPE_MAX) { + ShowWarning("script_setmount: Unknown flag %d specified. Using auto-detected value.\n", flag); + flag = SETMOUNT_TYPE_AUTODETECT; + } + // Sanity checks and auto-detection + if ((sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) { + if (pc->checkskill(sd, RK_DRAGONTRAINING)) { + // Rune Knight (Dragon) + unsigned int option; + option = ( flag == SETMOUNT_TYPE_DRAGON_GREEN ? OPTION_DRAGON1 : + flag == SETMOUNT_TYPE_DRAGON_BROWN ? OPTION_DRAGON2 : + flag == SETMOUNT_TYPE_DRAGON_GRAY ? OPTION_DRAGON3 : + flag == SETMOUNT_TYPE_DRAGON_RED ? OPTION_DRAGON4 : + 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)) + pc->setridingwug(sd, true); + } else if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC) { + // 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)) + pc->setridingpeco(sd, true); + } + } else if (pc_hasmount(sd)) { + if (pc_isridingdragon(sd)) { + pc->setridingdragon(sd, 0); + } + if (pc_isridingwug(sd)) { + pc->setridingwug(sd, false); + } + if (pc_ismadogear(sd)) { + pc->setmadogear(sd, false); + } + if (pc_isridingpeco(sd)) { + pc->setridingpeco(sd, false); + } + } return true; } @@ -8763,15 +8841,15 @@ BUILDIN(checkmadogear) /// setmadogear; BUILDIN(setmadogear) { - int flag = 1; + bool flag = true; TBL_PC* sd; sd = script->rid2sd(st); - if( sd == NULL ) + if (sd == NULL) return true;// no player attached, report source - if( script_hasdata(st,2) ) - flag = script_getnum(st,2); + if (script_hasdata(st,2)) + flag = script_getnum(st,2) ? true : false; pc->setmadogear(sd, flag); return true; @@ -13123,14 +13201,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; } @@ -16315,21 +16393,15 @@ BUILDIN(erasequest) { if( sd == NULL ) return false; - if(script_hasdata(st, 3)) - { - if(script_getnum(st, 3) < script_getnum(st, 2)) - { + if (script_hasdata(st, 3)) { + if (script_getnum(st, 3) < script_getnum(st, 2)) { ShowError("buildin_erasequest: The second quest id must be greater than the id of the first.\n"); return false; } - - for(quest_id = script_getnum(st, 2); quest_id < script_getnum(st, 3); quest_id++) - { + for (quest_id = script_getnum(st, 2); quest_id < script_getnum(st, 3); quest_id++) { quest->delete(sd, quest_id); } - } - else - { + } else { quest->delete(sd, script_getnum(st, 2)); } @@ -16343,21 +16415,15 @@ BUILDIN(completequest) { if( sd == NULL ) return false; - if(script_hasdata(st, 3)) - { - if(script_getnum(st, 3) < script_getnum(st, 2)) - { + if (script_hasdata(st, 3)) { + if (script_getnum(st, 3) < script_getnum(st, 2)) { ShowError("buildin_completequest: The second quest id must be greater than the id of the first.\n"); return false; } - - for(quest_id = script_getnum(st, 2); quest_id < script_getnum(st, 3); quest_id++) - { + for (quest_id = script_getnum(st, 2); quest_id < script_getnum(st, 3); quest_id++) { quest->update_status(sd, quest_id, Q_COMPLETE); } - } - else - { + } else { quest->update_status(sd, script_getnum(st, 2), Q_COMPLETE); } @@ -16391,24 +16457,41 @@ BUILDIN(checkquest) { return true; } +BUILDIN(questactive) { + struct map_session_data *sd = script->rid2sd(st); + int quest_progress = 0; + + if (sd == NULL) + return false; + + if (quest->check(sd, script_getnum(st, 2), HAVEQUEST) == Q_ACTIVE) + script_pushint(st, 1); + else + script_pushint(st, 0); + + script_pushint(st, quest_progress); + + return true; +} + BUILDIN(questprogress) { struct map_session_data *sd = script->rid2sd(st); enum quest_check_type type = HAVEQUEST; int quest_progress = 0; - if( sd == NULL ) + if (sd == NULL) return false; - if( script_hasdata(st, 3) ) + if (script_hasdata(st, 3)) type = (enum quest_check_type)script_getnum(st, 3); quest_progress = quest->check(sd, script_getnum(st, 2), type); // "Fix" returned quest state value to make more sense. // 0 = Not Started, 1 = In Progress, 2 = Completed. - if(quest_progress == -1) + if (quest_progress == -1) // Not found quest_progress = 0; - else if(quest_progress == 0 || quest_progress == 1) + else if (quest_progress == 0 || quest_progress == 1) quest_progress = 1; else quest_progress = 2; @@ -17363,9 +17446,10 @@ BUILDIN(setdragon) { } /** - * ismounting() returns 1 if mounting a new mount or 0 otherwise + * hascashmount() returns 1 if mounting a cash mount or 0 otherwise **/ -BUILDIN(ismounting) { +BUILDIN(hascashmount) +{ TBL_PC* sd; if( (sd = script->rid2sd(st)) == NULL ) return true; @@ -17377,20 +17461,22 @@ BUILDIN(ismounting) { } /** - * setmounting() returns 1 on success or 0 otherwise - * - Toggles new mounts on a player when he can mount - * - Will fail if the player is mounting a non-new mount, e.g. dragon, peco, wug, etc. - * - Will unmount the player is he is already mounting + * setcashmount() returns 1 on success or 0 otherwise + * + * - Toggles cash mounts on a player when he can mount + * - Will fail if the player is already riding a standard mount e.g. dragon, peco, wug, mado, etc. + * - Will unmount the player is he is already mounting a cash mount **/ -BUILDIN(setmounting) { +BUILDIN(setcashmount) +{ TBL_PC* sd; - if( (sd = script->rid2sd(st)) == NULL ) + if ((sd = script->rid2sd(st)) == NULL) return true; - if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) ) { + if (pc_hasmount(sd)) { clif->msgtable(sd->fd, 0X78b); script_pushint(st,0);//can't mount with one of these } else { - if( sd->sc.data[SC_ALL_RIDING] ) + if (sd->sc.data[SC_ALL_RIDING]) status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER); else sc_start(NULL,&sd->bl, SC_ALL_RIDING, 100, 0, -1); @@ -18832,7 +18918,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; @@ -18848,6 +18934,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 ) { @@ -18865,13 +18952,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,""), @@ -18896,8 +18990,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"), @@ -18978,6 +19071,8 @@ void script_parse_builtin(void) { BUILDIN_DEF(checkfalcon,""), BUILDIN_DEF(setriding,"?"), BUILDIN_DEF(checkriding,""), + BUILDIN_DEF(setmount,"?"), + BUILDIN_DEF(checkmount,""), BUILDIN_DEF(checkwug,""), BUILDIN_DEF(checkmadogear,""), BUILDIN_DEF(setmadogear,"?"), @@ -19099,7 +19194,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] @@ -19149,7 +19244,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] @@ -19303,8 +19398,8 @@ void script_parse_builtin(void) { BUILDIN_DEF(makerune,"i"), BUILDIN_DEF(checkdragon,""),//[Ind] BUILDIN_DEF(setdragon,"?"),//[Ind] - BUILDIN_DEF(ismounting,""),//[Ind] - BUILDIN_DEF(setmounting,""),//[Ind] + BUILDIN_DEF(hascashmount,""),//[Ind] + BUILDIN_DEF(setcashmount,""),//[Ind] BUILDIN_DEF(checkre,"i"), /** * rAthena and beyond! @@ -19339,8 +19434,9 @@ 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"), BUILDIN_DEF(showevent, "i?"), diff --git a/src/map/script.h b/src/map/script.h index 48abf1487..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 DeprecationWarning(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 DeprecationWarning2(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 51e266559..42aae546d 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -2120,6 +2120,7 @@ int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type) * packet shouldn't display a skill animation) * flag&0x2000 is used to signal that the skill_lv should be passed as -1 to the * client (causes player characters to not scream skill name) + * flag&0x4000 - Return 0 if damage was reflected *-------------------------------------------------------------------------*/ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) { struct Damage dmg; @@ -2791,6 +2792,9 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr map->freeblock_unlock(); + if ((flag&0x4000) && rmdamage == 1) + return 0; //Should return 0 when damage was reflected + return (int)cap_value(damage,INT_MIN,INT_MAX); } @@ -8533,9 +8537,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case NC_SELFDESTRUCTION: - if( sd ) { - if( pc_ismadogear(sd) ) - pc->setmadogear(sd, 0); + if (sd) { + if (pc_ismadogear(sd)) + pc->setmadogear(sd, false); clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); skill->castend_damage_id(src, src, skill_id, skill_lv, tick, flag); status->set_sp(src, 0, 0); @@ -10074,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: @@ -10183,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); @@ -10782,28 +10790,6 @@ bool skill_dance_switch(struct skill_unit* su, int flag) { return true; } -/** - * Upon Ice Wall cast it checks all nearby mobs to find any who may be blocked by the IW - **/ -int skill_icewall_block(struct block_list *bl,va_list ap) { - struct block_list *target = NULL; - struct mob_data *md = ((TBL_MOB*)bl); - - nullpo_ret(bl); - nullpo_ret(md); - if( !md->target_id || ( target = map->id2bl(md->target_id) ) == NULL ) - return 0; - - if( path->search_long(NULL,bl->m,bl->x,bl->y,target->x,target->y,CELL_CHKICEWALL) ) - return 0; - - if( !check_distance_bl(bl, target, status_get_range(bl) ) ) { - mob->unlocktarget(md,timer->gettick()); - mob_stop_walking(md,1); - } - - return 0; -} /*========================================== * Initializes and sets a ground skill. * flag&1 is used to determine when the skill 'morphs' (Warp portal becomes active, or Fire Pillar becomes active) @@ -11013,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: @@ -11303,9 +11289,6 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ //success, unit created. switch( skill_id ) { - case WZ_ICEWALL: - map->foreachinrange(skill->icewall_block, src, AREA_SIZE, BL_MOB); - break; case NJ_TATAMIGAESHI: //Store number of tiles. group->val1 = group->alive_count; break; @@ -13465,7 +13448,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id } break; case ST_RIDING: - if(!pc_isriding(sd) && !pc_isridingdragon(sd)) { + if (!pc_isridingpeco(sd) && !pc_isridingdragon(sd)) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } @@ -13580,7 +13563,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id return 0; } case ST_PECO: - if(!pc_isriding(sd)) { + if (!pc_isridingpeco(sd)) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } @@ -14997,7 +14980,7 @@ int skill_frostjoke_scream(struct block_list *bl, va_list ap) { return 0; if (bl->type == BL_PC) { struct map_session_data *sd = (struct map_session_data *)bl; - if ( sd && sd->sc.option&(OPTION_INVISIBLE|OPTION_MADOGEAR) ) + if (sd && (pc_isinvisible(sd) || pc_ismadogear(sd))) return 0;//Frost Joke / Scream cannot target invisible or MADO Gear characters [Ind] } //It has been reported that Scream/Joke works the same regardless of woe-setting. [Skotlex] @@ -15599,7 +15582,6 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int map->setgatcell(su->bl.m,su->bl.x,su->bl.y,5); clif->changemapcell(0,su->bl.m,su->bl.x,su->bl.y,5,AREA); skill->unitsetmapcell(su,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,true); - map->list[su->bl.m].icewall_num++; break; case SA_LANDPROTECTOR: skill->unitsetmapcell(su,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,true); @@ -15648,10 +15630,10 @@ 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); - map->list[su->bl.m].icewall_num--; // AS_CLOAKING in low levels requires a wall to be cast, thus it needs to be // checked again when a wall disapears! issue:8182 [Panikon] map->foreachinarea(skill->check_cloaking_end, su->bl.m, @@ -18803,7 +18785,6 @@ void skill_defaults(void) { skill->frostjoke_scream = skill_frostjoke_scream; skill->greed = skill_greed; skill->destroy_trap = skill_destroy_trap; - skill->icewall_block = skill_icewall_block; skill->unitgrouptickset_search = skill_unitgrouptickset_search; skill->dance_switch = skill_dance_switch; skill->check_condition_char_sub = skill_check_condition_char_sub; diff --git a/src/map/skill.h b/src/map/skill.h index 6373d9275..4ec742bd0 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -1984,7 +1984,6 @@ struct skill_interface { int (*frostjoke_scream) (struct block_list *bl, va_list ap); int (*greed) (struct block_list *bl, va_list ap); int (*destroy_trap) ( struct block_list *bl, va_list ap ); - int (*icewall_block) (struct block_list *bl,va_list ap); struct skill_unit_group_tickset *(*unitgrouptickset_search) (struct block_list *bl, struct skill_unit_group *group, int64 tick); bool (*dance_switch) (struct skill_unit* su, int flag); int (*check_condition_char_sub) (struct block_list *bl, va_list ap); diff --git a/src/map/status.c b/src/map/status.c index 3cd28e322..824ad1f58 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -2485,13 +2485,14 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK); bstatus->size = (sd->class_&JOBL_BABY)?SZ_SMALL:SZ_MEDIUM; - if (battle_config.character_size && (pc_isriding(sd) || pc_isridingdragon(sd)) ) { //[Lupus] + if (battle_config.character_size && (pc_isridingpeco(sd) || pc_isridingdragon(sd))) { //[Lupus] if (sd->class_&JOBL_BABY) { if (battle_config.character_size&SZ_BIG) bstatus->size++; - } else + } else { if(battle_config.character_size&SZ_MEDIUM) bstatus->size++; + } } bstatus->aspd_rate = 1000; bstatus->ele_lv = 1; @@ -2780,9 +2781,10 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->left_weapon.atkmods[1] = status->atkmods[1][sd->weapontype2]; sd->left_weapon.atkmods[2] = status->atkmods[2][sd->weapontype2]; - if( (pc_isriding(sd) || pc_isridingdragon(sd)) && - (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR)) - { //When Riding with spear, damage modifier to mid-class becomes + if ((pc_isridingpeco(sd) || pc_isridingdragon(sd)) + && (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR) + ) { + //When Riding with spear, damage modifier to mid-class becomes //same as versus large size. sd->right_weapon.atkmods[1] = sd->right_weapon.atkmods[2]; sd->left_weapon.atkmods[1] = sd->left_weapon.atkmods[2]; @@ -3062,9 +3064,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 && (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) bstatus->aspd_rate -= ((skill_lv+1)/2) * 10; - if(pc_isriding(sd)) + if (pc_isridingpeco(sd)) bstatus->aspd_rate += 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY); - else if(pc_isridingdragon(sd)) + else if (pc_isridingdragon(sd)) bstatus->aspd_rate += 250-50*pc->checkskill(sd,RK_DRAGONTRAINING); #else // needs more info if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK) @@ -3074,9 +3076,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 && (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) bstatus->aspd_rate += ((skill_lv+1)/2) * 10; - if(pc_isriding(sd)) + if (pc_isridingpeco(sd)) bstatus->aspd_rate -= 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY); - else if(pc_isridingdragon(sd)) + else if (pc_isridingdragon(sd)) bstatus->aspd_rate -= 250-50*pc->checkskill(sd,RK_DRAGONTRAINING); #endif bstatus->adelay = 2*bstatus->amotion; @@ -3094,7 +3096,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { // Weight if((skill_lv=pc->checkskill(sd,MC_INCCARRY))>0) sd->max_weight += 2000*skill_lv; - if(pc_isriding(sd) && pc->checkskill(sd,KN_RIDING)>0) + if (pc_isridingpeco(sd) && pc->checkskill(sd,KN_RIDING) > 0) sd->max_weight += 10000; else if(pc_isridingdragon(sd)) sd->max_weight += 5000+2000*pc->checkskill(sd,RK_DRAGONTRAINING); @@ -5231,16 +5233,16 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc { int val = 0; - if( sc->data[SC_FUSION] ) + if(sc->data[SC_FUSION]) { val = 25; - else if( sd ) { - if( pc_isriding(sd) || sd->sc.option&(OPTION_DRAGON) || sd->sc.data[SC_ALL_RIDING] ) + } else if (sd) { + if (pc_isridingpeco(sd) || pc_isridingdragon(sd) || sd->sc.data[SC_ALL_RIDING]) val = 25;//Same bonus - else if( pc_isridingwug(sd) ) + else if (pc_isridingwug(sd)) val = 15 + 5 * pc->checkskill(sd, RA_WUGRIDER); - else if( pc_ismadogear(sd) ) { + else if (pc_ismadogear(sd)) { val = (- 10 * (5 - pc->checkskill(sd,NC_MADOLICENCE))); - if( sc->data[SC_ACCELERATION] ) + if (sc->data[SC_ACCELERATION]) val += 25; } } @@ -6013,7 +6015,9 @@ int status_get_party_id(struct block_list *bl) { return ((TBL_MER*)bl)->master->status.party_id; break; case BL_SKILL: - return ((TBL_SKILL*)bl)->group->party_id; + if (((TBL_SKILL*)bl)->group) + return ((TBL_SKILL*)bl)->group->party_id; + break; case BL_ELEM: if (((TBL_ELEM*)bl)->master) return ((TBL_ELEM*)bl)->master->status.party_id; @@ -6056,7 +6060,9 @@ int status_get_guild_id(struct block_list *bl) { return ((TBL_NPC*)bl)->u.scr.guild_id; break; case BL_SKILL: - return ((TBL_SKILL*)bl)->group->guild_id; + if (((TBL_SKILL*)bl)->group) + return ((TBL_SKILL*)bl)->group->guild_id; + break; case BL_ELEM: if (((TBL_ELEM*)bl)->master) return ((TBL_ELEM*)bl)->master->status.guild_id; @@ -6178,7 +6184,7 @@ void status_set_viewdata(struct block_list *bl, int class_) { TBL_PC* sd = (TBL_PC*)bl; if (pcdb_checkid(class_)) { - if (sd->sc.option&OPTION_RIDING) { + if (pc_isridingpeco(sd)) { switch (class_) { //Adapt class to a Mounted one. case JOB_KNIGHT: class_ = JOB_KNIGHT2; @@ -7881,8 +7887,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_RUWACH: case SC_WZ_SIGHTBLASTER: val3 = skill->get_splash(val2, val1); //Val2 should bring the skill-id. - val2 = tick/250; - tick_time = 10; // [GodLesZ] tick time + val2 = tick/20; + tick_time = 20; // [GodLesZ] tick time break; //Permanent effects. @@ -8581,14 +8587,22 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val2 = 20 + 10 * val1; //ASPD. Need to confirm if Movement Speed reduction is the same. [Jobbie] val3 = 20 * val1; //HIT if( sd ) { // Removes Animals - if( pc_isriding(sd) ) pc->setriding(sd, 0); - if( pc_isridingdragon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_DRAGON); - if( pc_iswug(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_WUG); - if( pc_isridingwug(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_WUGRIDER); - if( pc_isfalcon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_FALCON); - if( sd->status.pet_id > 0 ) pet->menu(sd, 3); - if( homun_alive(sd->hd) ) homun->vaporize(sd,HOM_ST_REST); - if( sd->md ) mercenary->delete(sd->md,3); + if (pc_isridingpeco(sd)) + pc->setridingpeco(sd, false); + if (pc_isridingdragon(sd)) + pc->setridingdragon(sd, 0); + if (pc_iswug(sd)) + pc->setoption(sd, sd->sc.option&~OPTION_WUG); + if (pc_isridingwug(sd)) + pc->setridingwug(sd, false); + if (pc_isfalcon(sd)) + pc->setfalcon(sd, false); + if (sd->status.pet_id > 0) + pet->menu(sd, 3); + if (homun_alive(sd->hd)) + homun->vaporize(sd,HOM_ST_REST); + if (sd->md) + mercenary->delete(sd->md,3); } break; case SC__LAZINESS: @@ -8685,8 +8699,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if ( !val3 ) val3 = 50; if( sd ) { - if( pc_isriding(sd) ) pc->setriding(sd, 0); - if( pc_isridingdragon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_DRAGON); + if (pc_isridingpeco(sd)) + pc->setridingpeco(sd, false); + if (pc_isridingdragon(sd)) + pc->setridingdragon(sd, false); } } break; @@ -8782,7 +8798,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] } } @@ -10510,14 +10526,17 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { case SC_SIGHT: case SC_RUWACH: case SC_WZ_SIGHTBLASTER: - if(type == SC_WZ_SIGHTBLASTER) + if(type == SC_WZ_SIGHTBLASTER) { + //Restore trap immunity + if(sce->val4%2) + sce->val4--; map->foreachinrange(status->change_timer_sub, bl, sce->val3, BL_CHAR|BL_SKILL, bl, sce, type, tick); - else + } else map->foreachinrange(status->change_timer_sub, bl, sce->val3, BL_CHAR, bl, sce, type, tick); if( --(sce->val2)>0 ){ - sce->val4 += 250; // use for Shadow Form 2 seconds checking. - sc_timer_next(250+tick, status->change_timer, bl->id, data); + sce->val4 += 20; // use for Shadow Form 2 seconds checking. + sc_timer_next(20+tick, status->change_timer, bl->id, data); return 0; } break; @@ -11312,10 +11331,13 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) { if (battle->check_target( src, bl, BCT_ENEMY ) > 0 && status->check_skilluse(src, bl, WZ_SIGHTBLASTER, 2) ) { - if (sce && !(bl->type&BL_SKILL) //The hit is not counted if it's against a trap - && skill->attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,1,tick,0) - ){ - sce->val2 = 0; //This signals it to end. + struct skill_unit *su = (struct skill_unit *)bl; + 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) { + //Remove trap immunity temporarily so it triggers if you still stand on it + sce->val4++; } } break; diff --git a/src/map/unit.c b/src/map/unit.c index f823a3fed..849e9348f 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -95,6 +95,8 @@ int unit_walktoxy_sub(struct block_list *bl) ud = unit->bl2ud(bl); if(ud == NULL) return 0; + memset(&wpd, 0, sizeof(wpd)); + if( !path->search(&wpd,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) ) return 0; @@ -247,9 +249,24 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { dx = dirx[(int)dir]; dy = diry[(int)dir]; - if(map->getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS)) + //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)) 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)) { + //Needs to be done here so that rudeattack skills are invoked + md->walktoxy_fail_count++; + clif->fixpos(bl); + 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; + } + //Refresh view for all those we lose sight map->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl); @@ -300,6 +317,8 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { sd->hd->masterteleport_timer = 0; } } else if (md) { + //Movement was successful, reset walktoxy_fail_count + md->walktoxy_fail_count = 0; if( map->getcell(bl->m,x,y,CELL_CHKNPC) ) { if( npc->touch_areanpc2(md) ) return 0; // Warped } else @@ -776,6 +795,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag) } if( sd ) { + unit->stop_stepaction(bl); //Stop stepaction when knocked back sd->ud.to_x = nx; sd->ud.to_y = ny; } @@ -1564,6 +1584,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)) @@ -2010,8 +2036,9 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) { sstatus = status->get_status_data(src); range = sstatus->rhw.range; - if( unit->is_walking(target) ) - range++; //Extra range when chasing + if( unit->is_walking(target) && (target->type == BL_PC || !map->getcell(target->m,target->x,target->y,CELL_CHKICEWALL)) ) + range++; // Extra range when chasing (does not apply to mobs locked in an icewall) + if(sd && !check_distance_client_bl(src,target,range)) { // Player tries to attack but target is too far, notify client clif->movetoattack(sd,target); @@ -2367,7 +2394,7 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i sd->debug_file, sd->debug_line, sd->debug_func, file, line, func); } else if (--map->list[bl->m].users == 0 && battle_config.dynamic_mobs) //[Skotlex] map->removemobs(bl->m); - if( !(sd->sc.option&OPTION_INVISIBLE) ) { + if (!(pc_isinvisible(sd))) { // decrement the number of active pvp players on the map --map->list[bl->m].users_pvp; } |