diff options
Diffstat (limited to 'src/map')
49 files changed, 4513 insertions, 3780 deletions
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c index 3ba9ae725..ca4a7a2e8 100644 --- a/src/map/HPMmap.c +++ b/src/map/HPMmap.c @@ -11,6 +11,7 @@ #include "map.h" // +#include "atcommand.h" #include "chat.h" #include "chrif.h" #include "duel.h" @@ -33,6 +34,18 @@ #include <string.h> #include <time.h> +struct HPM_atcommand_list { + //tracking currently not enabled + // - requires modifying how plugins calls atcommand creation + // - needs load/unload during runtime support + //unsigned int pID;/* plugin id */ + char name[ATCOMMAND_LENGTH]; + AtCommandFunc func; +}; + +struct HPM_atcommand_list *atcommand_list = NULL; +unsigned int atcommand_list_items = 0; + void HPM_map_addToMSD(struct map_session_data *sd, void *data, unsigned int id, unsigned int type, bool autofree) { struct HPluginData *HPData; unsigned int i; @@ -103,4 +116,40 @@ void HPM_map_plugin_load_sub(struct hplugin *plugin) { plugin->hpi->addToMSD = HPM->import_symbol("addToMSD",plugin->idx); plugin->hpi->getFromMSD = HPM->import_symbol("getFromMSD",plugin->idx); plugin->hpi->removeFromMSD = HPM->import_symbol("removeFromMSD",plugin->idx); -}
\ No newline at end of file +} + +bool HPM_map_add_atcommand(char *name, AtCommandFunc func) { + unsigned int i = 0; + + for(i = 0; i < atcommand_list_items; i++) { + if( !strcmpi(atcommand_list[i].name,name) ) { + ShowDebug("HPM_map_add_atcommand: duplicate command '%s', skipping...\n", name); + return false; + } + } + + i = atcommand_list_items; + + RECREATE(atcommand_list, struct HPM_atcommand_list , ++atcommand_list_items); + + safestrncpy(atcommand_list[i].name, name, sizeof(atcommand_list[i].name)); + atcommand_list[i].func = func; + + return true; +} + +void HPM_map_atcommands(void) { + unsigned int i; + + for(i = 0; i < atcommand_list_items; i++) { + if( !atcommand->add(atcommand_list[i].name,atcommand_list[i].func) ) { + ShowDebug("HPM_map_atcommands: duplicate command '%s', skipping...\n", atcommand_list[i].name); + continue; + } + } +} + +void HPM_map_do_final(void) { + if( atcommand_list ) + aFree(atcommand_list); +} diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h index a6cac4ace..96515772b 100644 --- a/src/map/HPMmap.h +++ b/src/map/HPMmap.h @@ -5,6 +5,7 @@ #define _HPM_MAP_ #include "../common/cbasetypes.h" +#include "../map/atcommand.h" struct hplugin; struct map_session_data; @@ -13,6 +14,11 @@ void HPM_map_addToMSD(struct map_session_data *sd, void *data, unsigned int id, void *HPM_map_getFromMSD(struct map_session_data *sd, unsigned int id, unsigned int type); void HPM_map_removeFromMSD(struct map_session_data *sd, unsigned int id, unsigned int type); +bool HPM_map_add_atcommand(char *name, AtCommandFunc func); +void HPM_map_atcommands(void); + void HPM_map_plugin_load_sub(struct hplugin *plugin); +void HPM_map_do_final(void); + #endif /* _HPM_MAP_ */ diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 980f61ad9..ed5852b76 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -45,6 +45,7 @@ #include "mapreg.h" #include "quest.h" #include "searchstore.h" +#include "HPMmap.h" #include <stdio.h> #include <stdlib.h> @@ -384,9 +385,7 @@ ACMD(mapmove) { unsigned short mapindex; short x = 0, y = 0; int16 m = -1; - - nullpo_retr(-1, sd); - + memset(map_name, '\0', sizeof(map_name)); if (!message || !*message || @@ -435,7 +434,6 @@ ACMD(mapmove) { ACMD(where) { struct map_session_data* pl_sd; - nullpo_retr(-1, sd); memset(atcmd_player_name, '\0', sizeof atcmd_player_name); if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { @@ -463,9 +461,7 @@ ACMD(where) { *------------------------------------------*/ ACMD(jumpto) { struct map_session_data *pl_sd = NULL; - - nullpo_retr(-1, sd); - + if (!message || !*message) { clif->message(fd, msg_txt(911)); // Please enter a player name (usage: @jumpto/@warpto/@goto <char name/ID>). return false; @@ -504,9 +500,7 @@ ACMD(jumpto) { ACMD(jump) { short x = 0, y = 0; - - nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); sscanf(message, "%hd %hd", &x, &y); @@ -554,9 +548,7 @@ ACMD(who) { */ int display_type = 1; int map_id = -1; - - nullpo_retr(-1, sd); - + if (strstr(command, "map") != NULL) { if (sscanf(message, "%15s %23s", map_name, player_name) < 1 || (map_id = map->mapname2mapid(map_name)) < 0) map_id = sd->bl.m; @@ -650,9 +642,7 @@ ACMD(whogm) char player_name[NAME_LENGTH]; struct guild *g; struct party_data *p; - - nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(match_text, '\0', sizeof(match_text)); memset(player_name, '\0', sizeof(player_name)); @@ -726,9 +716,7 @@ ACMD(whogm) /*========================================== * *------------------------------------------*/ -ACMD(save) -{ - nullpo_retr(-1, sd); +ACMD(save) { pc->setsavepoint(sd, sd->mapindex, sd->bl.x, sd->bl.y); if (sd->status.pet_id > 0 && sd->pd) @@ -746,9 +734,7 @@ ACMD(save) *------------------------------------------*/ ACMD(load) { int16 m; - - nullpo_retr(-1, sd); - + m = map->mapindex2mapid(sd->status.save_point.map); if (m >= 0 && map->list[m].flag.nowarpto && !pc->has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif->message(fd, msg_txt(249)); // You are not authorized to warp to your save map. @@ -771,9 +757,7 @@ ACMD(load) { ACMD(speed) { int speed; - - nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message || sscanf(message, "%d", &speed) < 1) { @@ -782,15 +766,21 @@ ACMD(speed) return false; } - if (speed < 0) { + sd->state.permanent_speed = 0; + + if (speed < 0) sd->base_status.speed = DEFAULT_WALK_SPEED; - sd->state.permanent_speed = 0; // Remove lock when set back to default speed. - } else { + else sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED); - sd->state.permanent_speed = 1; // Set lock when set to non-default speed. - } + status_calc_bl(&sd->bl, SCB_SPEED); - clif->message(fd, msg_txt(8)); // Speed changed. + + if( sd->base_status.speed != DEFAULT_WALK_SPEED ) { + sd->state.permanent_speed = 1; // Set lock when set to non-default speed. + clif->message(fd, msg_txt(8)); // Speed changed. + } else + clif->message(fd, msg_txt(172)); //Speed returned to normal. + return true; } @@ -799,8 +789,6 @@ ACMD(speed) *------------------------------------------*/ ACMD(storage) { - nullpo_retr(-1, sd); - if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag) return false; @@ -820,8 +808,6 @@ ACMD(storage) *------------------------------------------*/ ACMD(guildstorage) { - nullpo_retr(-1, sd); - if (!sd->status.guild_id) { clif->message(fd, msg_txt(252)); return false; @@ -851,7 +837,6 @@ ACMD(guildstorage) ACMD(option) { int param1 = 0, param2 = 0, param3 = 0; - nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d %d %d", ¶m1, ¶m2, ¶m3) < 1 || param1 < 0 || param2 < 0 || param3 < 0) {// failed to match the parameters so inform the user of the options @@ -883,7 +868,6 @@ ACMD(option) * *------------------------------------------*/ ACMD(hide) { - nullpo_retr(-1, sd); if (sd->sc.option & OPTION_INVISIBLE) { sd->sc.option &= ~OPTION_INVISIBLE; if (sd->disguise != -1 ) @@ -927,7 +911,6 @@ ACMD(jobchange) { int job = 0, upper = 0; const char* text; - nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d %d", &job, &upper) < 1) { int i; @@ -989,7 +972,6 @@ ACMD(jobchange) *------------------------------------------*/ ACMD(kill) { - nullpo_retr(-1, sd); status_kill(&sd->bl); clif->message(sd->fd, msg_txt(13)); // A pity! You've died. if (fd != sd->fd) @@ -1002,7 +984,6 @@ ACMD(kill) *------------------------------------------*/ ACMD(alive) { - nullpo_retr(-1, sd); if (!status->revive(&sd->bl, 100, 100)) { clif->message(fd, msg_txt(667)); return false; @@ -1018,7 +999,6 @@ ACMD(alive) ACMD(kami) { unsigned long color=0; - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -1054,7 +1034,6 @@ ACMD(kami) ACMD(heal) { int hp = 0, sp = 0; // [Valaris] thanks to fov - nullpo_retr(-1, sd); sscanf(message, "%d %d", &hp, &sp); @@ -1116,7 +1095,6 @@ ACMD(item) struct item item_tmp; struct item_data *item_data; int get_count, i; - nullpo_retr(-1, sd); memset(item_name, '\0', sizeof(item_name)); @@ -1172,7 +1150,6 @@ ACMD(item2) int item_id, number = 0; int identify = 0, refine = 0, attr = 0; int c1 = 0, c2 = 0, c3 = 0, c4 = 0; - nullpo_retr(-1, sd); memset(item_name, '\0', sizeof(item_name)); @@ -1244,7 +1221,6 @@ ACMD(item2) ACMD(itemreset) { int i; - nullpo_retr(-1, sd); for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == 0) { @@ -1262,7 +1238,7 @@ ACMD(itemreset) ACMD(baselevelup) { int level=0, i=0, status_point=0; - nullpo_retr(-1, sd); + level = atoi(message); if (!message || !*message || !level) { @@ -1322,7 +1298,6 @@ ACMD(baselevelup) ACMD(joblevelup) { int level=0; - nullpo_retr(-1, sd); level = atoi(message); @@ -1375,9 +1350,7 @@ ACMD(help) { const char *command_name = NULL; char *default_command = "help"; AtCommandInfo *tinfo = NULL; - - nullpo_retr(-1, sd); - + if (!message || !*message) { command_name = default_command; // If no command_name specified, display help for @help. } else { @@ -1461,7 +1434,6 @@ int atcommand_pvpoff_sub(struct block_list *bl,va_list ap) } ACMD(pvpoff) { - nullpo_retr(-1, sd); if (!map->list[sd->bl.m].flag.pvp) { clif->message(fd, msg_txt(160)); // PvP is already Off. @@ -1499,7 +1471,6 @@ int atcommand_pvpon_sub(struct block_list *bl,va_list ap) } ACMD(pvpon) { - nullpo_retr(-1, sd); if (map->list[sd->bl.m].flag.pvp) { clif->message(fd, msg_txt(161)); // PvP is already On. @@ -1524,7 +1495,6 @@ ACMD(pvpon) { * *------------------------------------------*/ ACMD(gvgoff) { - nullpo_retr(-1, sd); if (!map->list[sd->bl.m].flag.gvg) { clif->message(fd, msg_txt(162)); // GvG is already Off. @@ -1545,7 +1515,6 @@ ACMD(gvgoff) { * *------------------------------------------*/ ACMD(gvgon) { - nullpo_retr(-1, sd); if (map->list[sd->bl.m].flag.gvg) { clif->message(fd, msg_txt(163)); // GvG is already On. @@ -1567,7 +1536,6 @@ ACMD(gvgon) { ACMD(model) { int hair_style = 0, hair_color = 0, cloth_color = 0; - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -1599,7 +1567,6 @@ ACMD(model) ACMD(dye) { int cloth_color = 0; - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -1626,7 +1593,6 @@ ACMD(dye) ACMD(hair_style) { int hair_style = 0; - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -1653,7 +1619,6 @@ ACMD(hair_style) ACMD(hair_color) { int hair_color = 0; - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -1729,9 +1694,7 @@ ACMD(go) { MAP_MALAYA, 242, 211 }, // 34=Malaya Port { MAP_ECLAGE, 110, 39 }, // 35=Eclage }; - - nullpo_retr(-1, sd); - + memset(map_name, '\0', sizeof(map_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -1881,7 +1844,6 @@ ACMD(monster) int i, k, range; short mx, my; unsigned int size; - nullpo_retr(-1, sd); memset(name, '\0', sizeof(name)); memset(monster, '\0', sizeof(monster)); @@ -1988,7 +1950,6 @@ int atkillmonster_sub(struct block_list *bl, va_list ap) ACMD(killmonster) { int map_id, drop_flag; char map_name[MAP_NAME_LENGTH_EXT]; - nullpo_retr(-1, sd); memset(map_name, '\0', sizeof(map_name)); @@ -2015,7 +1976,6 @@ ACMD(refine) { int i,j, position = 0, refine = 0, current_position, final_refine; int count; - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -2095,7 +2055,6 @@ ACMD(produce) int item_id, attribute = 0, star = 0; struct item_data *item_data; struct item tmp_item; - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(item_name, '\0', sizeof(item_name)); @@ -2151,7 +2110,6 @@ ACMD(produce) ACMD(memo) { int position = 0; - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -2186,7 +2144,6 @@ ACMD(memo) *------------------------------------------*/ ACMD(gat) { int y; - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -2211,7 +2168,6 @@ ACMD(gat) { ACMD(displaystatus) { int i, type, flag, tick, val1 = 0, val2 = 0, val3 = 0; - nullpo_retr(-1, sd); if (!message || !*message || (i = sscanf(message, "%d %d %d %d %d %d", &type, &flag, &tick, &val1, &val2, &val3)) < 1) { clif->message(fd, msg_txt(1009)); // Please enter a status type/flag (usage: @displaystatus <status type> <flag> <tick> {<val1> {<val2> {<val3>}}}). @@ -2283,7 +2239,6 @@ ACMD(skillpoint) { int point; unsigned int new_skill_point; - nullpo_retr(-1, sd); if (!message || !*message || (point = atoi(message)) == 0) { clif->message(fd, msg_txt(1011)); // Please enter a number (usage: @skpoint <number of points>). @@ -2331,7 +2286,6 @@ ACMD(skillpoint) ACMD(zeny) { int zeny=0, ret=-1; - nullpo_retr(-1, sd); if (!message || !*message || (zeny = atoi(message)) == 0) { clif->message(fd, msg_txt(1012)); // Please enter an amount (usage: @zeny <amount>). @@ -2359,7 +2313,6 @@ ACMD(param) { const char* param[] = { "str", "agi", "vit", "int", "dex", "luk" }; short* stats[6]; //we don't use direct initialization because it isn't part of the c standard. - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -2419,7 +2372,6 @@ ACMD(stat_all) { int index, count, value, max, new_value; short* stats[6]; //we don't use direct initialization because it isn't part of the c standard. - nullpo_retr(-1, sd); stats[0] = &sd->status.str; stats[1] = &sd->status.agi; @@ -2478,7 +2430,6 @@ ACMD(guildlevelup) int level = 0; short added_level; struct guild *guild_info; - nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d", &level) < 1 || level == 0) { clif->message(fd, msg_txt(1014)); // Please enter a valid level (usage: @guildlvup/@guildlvlup <# of levels>). @@ -2518,7 +2469,6 @@ ACMD(makeegg) { struct item_data *item_data; int id, pet_id; - nullpo_retr(-1, sd); if (!message || !*message) { clif->message(fd, msg_txt(1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>). @@ -2556,7 +2506,6 @@ ACMD(makeegg) *------------------------------------------*/ ACMD(hatch) { - nullpo_retr(-1, sd); if (sd->status.pet_id <= 0) clif->sendegg(sd); else { @@ -2574,7 +2523,6 @@ ACMD(petfriendly) { int friendly; struct pet_data *pd; - nullpo_retr(-1, sd); if (!message || !*message || (friendly = atoi(message)) < 0) { clif->message(fd, msg_txt(1016)); // Please enter a valid value (usage: @petfriendly <0-1000>). @@ -2611,7 +2559,6 @@ ACMD(pethungry) { int hungry; struct pet_data *pd; - nullpo_retr(-1, sd); if (!message || !*message || (hungry = atoi(message)) < 0) { clif->message(fd, msg_txt(1017)); // Please enter a valid number (usage: @pethungry <0-100>). @@ -2645,7 +2592,6 @@ ACMD(pethungry) ACMD(petrename) { struct pet_data *pd; - nullpo_retr(-1, sd); if (!sd->status.pet_id || !sd->pd) { clif->message(fd, msg_txt(184)); // Sorry, but you have no pet. return false; @@ -2670,7 +2616,6 @@ ACMD(petrename) ACMD(recall) { struct map_session_data *pl_sd = NULL; - nullpo_retr(-1, sd); if (!message || !*message) { clif->message(fd, msg_txt(1018)); // Please enter a player name (usage: @recall <char name/ID>). @@ -2712,7 +2657,6 @@ ACMD(recall) { *------------------------------------------*/ ACMD(char_block) { - nullpo_retr(-1, sd); memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); @@ -2748,7 +2692,6 @@ ACMD(char_ban) int year, month, day, hour, minute, second, value; time_t timestamp; struct tm *tmtime; - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); @@ -2829,7 +2772,6 @@ ACMD(char_ban) *------------------------------------------*/ ACMD(char_unblock) { - nullpo_retr(-1, sd); memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); @@ -2850,7 +2792,6 @@ ACMD(char_unblock) *------------------------------------------*/ ACMD(char_unban) { - nullpo_retr(-1, sd); memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); @@ -2870,7 +2811,6 @@ ACMD(char_unban) * *------------------------------------------*/ ACMD(night) { - nullpo_retr(-1, sd); if (map->night_flag != 1) { pc->map_night_timer(pc->night_timer_tid, 0, 0, 1); @@ -2886,7 +2826,6 @@ ACMD(night) { * *------------------------------------------*/ ACMD(day) { - nullpo_retr(-1, sd); if (map->night_flag != 0) { pc->map_day_timer(pc->day_timer_tid, 0, 0, 1); @@ -2905,9 +2844,7 @@ ACMD(doom) { struct map_session_data* pl_sd; struct s_mapiterator* iter; - - nullpo_retr(-1, sd); - + iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { @@ -2932,9 +2869,7 @@ ACMD(doommap) { struct map_session_data* pl_sd; struct s_mapiterator* iter; - - nullpo_retr(-1, sd); - + iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { @@ -2970,9 +2905,7 @@ ACMD(raise) { struct map_session_data* pl_sd; struct s_mapiterator* iter; - - nullpo_retr(-1, sd); - + iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) if( pc_isdead(pl_sd) ) @@ -2991,9 +2924,7 @@ ACMD(raisemap) { struct map_session_data* pl_sd; struct s_mapiterator* iter; - - nullpo_retr(-1, sd); - + iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) if (sd->bl.m == pl_sd->bl.m && pc_isdead(pl_sd) ) @@ -3011,7 +2942,6 @@ ACMD(raisemap) ACMD(kick) { struct map_session_data *pl_sd; - nullpo_retr(-1, sd); memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); @@ -3043,7 +2973,6 @@ ACMD(kickall) { struct map_session_data* pl_sd; struct s_mapiterator* iter; - nullpo_retr(-1, sd); iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) @@ -3065,7 +2994,6 @@ ACMD(kickall) *------------------------------------------*/ ACMD(allskill) { - nullpo_retr(-1, sd); pc->allskillup(sd); // all skills sd->status.skill_point = 0; // 0 skill points clif->updatestatus(sd, SP_SKILLPOINT); // update @@ -3080,7 +3008,6 @@ ACMD(allskill) ACMD(questskill) { uint16 skill_id, index; - nullpo_retr(-1, sd); if (!message || !*message || (skill_id = atoi(message)) <= 0) {// also send a list of skills applicable to this command @@ -3123,7 +3050,6 @@ ACMD(questskill) ACMD(lostskill) { uint16 skill_id, index; - nullpo_retr(-1, sd); if (!message || !*message || (skill_id = atoi(message)) <= 0) {// also send a list of skills applicable to this command @@ -3169,7 +3095,6 @@ ACMD(spiritball) { int max_spiritballs; int number; - nullpo_retr(-1, sd); max_spiritballs = min(ARRAYLENGTH(sd->spirit_timer), 0x7FFF); @@ -3196,7 +3121,6 @@ ACMD(spiritball) ACMD(party) { char party_name[NAME_LENGTH]; - nullpo_retr(-1, sd); memset(party_name, '\0', sizeof(party_name)); @@ -3217,7 +3141,6 @@ ACMD(guild) { char guild_name[NAME_LENGTH]; int prev; - nullpo_retr(-1, sd); memset(guild_name, '\0', sizeof(guild_name)); @@ -3236,7 +3159,6 @@ ACMD(guild) ACMD(breakguild) { - nullpo_retr(-1, sd); if (sd->status.guild_id) { // Check if the player has a guild struct guild *g; @@ -3269,7 +3191,6 @@ ACMD(breakguild) * *------------------------------------------*/ ACMD(agitstart) { - nullpo_retr(-1, sd); if (map->agit_flag == 1) { clif->message(fd, msg_txt(73)); // War of Emperium is currently in progress. return false; @@ -3286,7 +3207,6 @@ ACMD(agitstart) { * *------------------------------------------*/ ACMD(agitstart2) { - nullpo_retr(-1, sd); if (map->agit2_flag == 1) { clif->message(fd, msg_txt(404)); // "War of Emperium SE is currently in progress." return false; @@ -3303,7 +3223,6 @@ ACMD(agitstart2) { * *------------------------------------------*/ ACMD(agitend) { - nullpo_retr(-1, sd); if (map->agit_flag == 0) { clif->message(fd, msg_txt(75)); // War of Emperium is currently not in progress. return false; @@ -3320,7 +3239,6 @@ ACMD(agitend) { * *------------------------------------------*/ ACMD(agitend2) { - nullpo_retr(-1, sd); if (map->agit2_flag == 0) { clif->message(fd, msg_txt(406)); // "War of Emperium SE is currently not in progress." return false; @@ -3337,8 +3255,6 @@ ACMD(agitend2) { * @mapexit - shuts down the map server *------------------------------------------*/ ACMD(mapexit) { - nullpo_retr(-1, sd); - map->do_shutdown(); return true; } @@ -3351,7 +3267,6 @@ ACMD(idsearch) char item_name[100]; unsigned int i, match; struct item_data *item_array[MAX_SEARCH]; - nullpo_retr(-1, sd); memset(item_name, '\0', sizeof(item_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -3387,7 +3302,6 @@ ACMD(recallall) struct map_session_data* pl_sd; struct s_mapiterator* iter; int count; - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -3434,7 +3348,6 @@ ACMD(guildrecall) int count; char guild_name[NAME_LENGTH]; struct guild *g; - nullpo_retr(-1, sd); memset(guild_name, '\0', sizeof(guild_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -3492,7 +3405,6 @@ ACMD(partyrecall) char party_name[NAME_LENGTH]; struct party_data *p; int count; - nullpo_retr(-1, sd); memset(party_name, '\0', sizeof(party_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -3544,7 +3456,6 @@ ACMD(partyrecall) *------------------------------------------*/ ACMD(reloaditemdb) { - nullpo_retr(-1, sd); itemdb->reload(); clif->message(fd, msg_txt(97)); // Item database has been reloaded. @@ -3555,7 +3466,6 @@ ACMD(reloaditemdb) * *------------------------------------------*/ ACMD(reloadmobdb) { - nullpo_retr(-1, sd); mob->reload(); pet->read_db(); homun->reload(); @@ -3572,7 +3482,6 @@ ACMD(reloadmobdb) { *------------------------------------------*/ ACMD(reloadskilldb) { - nullpo_retr(-1, sd); skill->reload(); homun->reload_skill(); elemental->reload_skilldb(); @@ -3680,7 +3589,6 @@ ACMD(reloadscript) { struct s_mapiterator* iter; struct map_session_data* pl_sd; - nullpo_retr(-1, sd); //atcommand_broadcast( fd, sd, "@broadcast", "Server is reloading scripts..." ); //atcommand_broadcast( fd, sd, "@broadcast", "You will feel a bit of lag at this point !" ); @@ -3732,9 +3640,7 @@ ACMD(mapinfo) { int i, m_id, chat_num = 0, list = 0, vend_num = 0; unsigned short m_index; char mapname[24]; - - nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(mapname, '\0', sizeof(mapname)); memset(direction, '\0', sizeof(direction)); @@ -3975,8 +3881,6 @@ ACMD(mapinfo) { *------------------------------------------*/ ACMD(mount_peco) { - nullpo_retr(-1, sd); - if (sd->disguise != -1) { clif->message(fd, msg_txt(212)); // Cannot mount while in disguise. return false; @@ -4040,7 +3944,6 @@ ACMD(mount_peco) ACMD(guildspy) { char guild_name[NAME_LENGTH]; struct guild *g; - nullpo_retr(-1, sd); memset(guild_name, '\0', sizeof(guild_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -4080,7 +3983,6 @@ ACMD(guildspy) { ACMD(partyspy) { char party_name[NAME_LENGTH]; struct party_data *p; - nullpo_retr(-1, sd); memset(party_name, '\0', sizeof(party_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -4121,7 +4023,6 @@ ACMD(partyspy) { ACMD(repairall) { int count, i; - nullpo_retr(-1, sd); count = 0; for (i = 0; i < MAX_INVENTORY; i++) { @@ -4149,7 +4050,6 @@ ACMD(repairall) *------------------------------------------*/ ACMD(nuke) { struct map_session_data *pl_sd; - nullpo_retr(-1, sd); memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); @@ -4180,9 +4080,7 @@ ACMD(nuke) { ACMD(tonpc) { char npcname[NAME_LENGTH+1]; struct npc_data *nd; - - nullpo_retr(-1, sd); - + memset(npcname, 0, sizeof(npcname)); if (!message || !*message || sscanf(message, "%23[^\n]", npcname) < 1) { @@ -4209,7 +4107,6 @@ ACMD(tonpc) { ACMD(shownpc) { char NPCname[NAME_LENGTH+1]; - nullpo_retr(-1, sd); memset(NPCname, '\0', sizeof(NPCname)); @@ -4235,7 +4132,6 @@ ACMD(shownpc) ACMD(hidenpc) { char NPCname[NAME_LENGTH+1]; - nullpo_retr(-1, sd); memset(NPCname, '\0', sizeof(NPCname)); @@ -4284,7 +4180,6 @@ ACMD(unloadnpc) { struct npc_data *nd; char NPCname[NAME_LENGTH+1]; - nullpo_retr(-1, sd); memset(NPCname, '\0', sizeof(NPCname)); @@ -4354,7 +4249,6 @@ ACMD(servertime) { time_t time_server; // variable for number of seconds (used with time() function) struct tm *datetime; // variable for time in structure ->tm_mday, ->tm_sec, ... char temp[CHAT_SIZE_MAX]; - nullpo_retr(-1, sd); memset(temp, '\0', sizeof(temp)); @@ -4372,7 +4266,8 @@ ACMD(servertime) { } else if (battle_config.night_duration == 0) { if (map->night_flag == 1) { // we start with night timer_data = timer->get(pc->day_timer_tid); - sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,timer->gettick())/1000)); // Game time: The game is actualy in night for %s. + sprintf(temp, msg_txt(233), // Game time: The game is actually in night for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data->tick,timer->gettick())/1000))); clif->message(fd, temp); clif->message(fd, msg_txt(234)); // Game time: After, the game will be in permanent daylight. } else @@ -4380,7 +4275,8 @@ ACMD(servertime) { } else if (battle_config.day_duration == 0) { if (map->night_flag == 0) { // we start with day timer_data = timer->get(pc->night_timer_tid); - sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,timer->gettick())/1000)); // Game time: The game is actualy in daylight for %s. + sprintf(temp, msg_txt(235), // Game time: The game is actualy in daylight for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data->tick,timer->gettick())/1000))); clif->message(fd, temp); clif->message(fd, msg_txt(236)); // Game time: After, the game will be in permanent night. } else @@ -4389,22 +4285,28 @@ ACMD(servertime) { if (map->night_flag == 0) { timer_data = timer->get(pc->night_timer_tid); timer_data2 = timer->get(pc->day_timer_tid); - sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,timer->gettick())/1000)); // Game time: The game is actualy in daylight for %s. + sprintf(temp, msg_txt(235), // Game time: The game is actualy in daylight for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data->tick,timer->gettick())/1000))); clif->message(fd, temp); if (DIFF_TICK(timer_data->tick, timer_data2->tick) > 0) - sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data->interval,DIFF_TICK(timer_data->tick,timer_data2->tick)) / 1000)); // Game time: After, the game will be in night for %s. + sprintf(temp, msg_txt(237), // Game time: After, the game will be in night for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data->interval,DIFF_TICK(timer_data->tick,timer_data2->tick)) / 1000))); else - sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data2->tick,timer_data->tick)/1000)); // Game time: After, the game will be in night for %s. + sprintf(temp, msg_txt(237), // Game time: After, the game will be in night for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data2->tick,timer_data->tick)/1000))); clif->message(fd, temp); } else { timer_data = timer->get(pc->day_timer_tid); timer_data2 = timer->get(pc->night_timer_tid); - sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,timer->gettick()) / 1000)); // Game time: The game is actualy in night for %s. + sprintf(temp, msg_txt(233), // Game time: The game is actualy in night for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data->tick,timer->gettick()) / 1000))); clif->message(fd, temp); if (DIFF_TICK(timer_data->tick,timer_data2->tick) > 0) - sprintf(temp, msg_txt(239), txt_time((timer_data->interval - DIFF_TICK(timer_data->tick, timer_data2->tick)) / 1000)); // Game time: After, the game will be in daylight for %s. + sprintf(temp, msg_txt(239), // Game time: After, the game will be in daylight for %s. + txt_time((unsigned int)((timer_data->interval - DIFF_TICK(timer_data->tick, timer_data2->tick)) / 1000))); else - sprintf(temp, msg_txt(239), txt_time(DIFF_TICK(timer_data2->tick, timer_data->tick) / 1000)); // Game time: After, the game will be in daylight for %s. + sprintf(temp, msg_txt(239), // Game time: After, the game will be in daylight for %s. + txt_time((unsigned int)(DIFF_TICK(timer_data2->tick, timer_data->tick) / 1000))); clif->message(fd, temp); } sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s. @@ -4450,7 +4352,6 @@ ACMD(jail) { struct map_session_data *pl_sd; int x, y; unsigned short m_index; - nullpo_retr(-1, sd); memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); @@ -4540,7 +4441,6 @@ ACMD(jailfor) { char * modif_p; int jailtime = 0,x,y; short m_index = 0; - nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%255s %23[^\n]",atcmd_output,atcmd_player_name) < 2) { clif->message(fd, msg_txt(400)); //Usage: @jailfor <time> <character name> @@ -4650,8 +4550,6 @@ ACMD(jailtime) { int year, month, day, hour, minute; - nullpo_retr(-1, sd); - if (!sd->sc.data[SC_JAILED]) { clif->message(fd, msg_txt(1139)); // You are not in jail. return false; @@ -4682,7 +4580,6 @@ ACMD(jailtime) ACMD(disguise) { int id = 0; - nullpo_retr(-1, sd); if (!message || !*message) { clif->message(fd, msg_txt(1143)); // Please enter a Monster/NPC name/ID (usage: @disguise <name/ID>). @@ -4734,7 +4631,6 @@ ACMD(disguiseall) int mob_id=0; struct map_session_data *pl_sd; struct s_mapiterator* iter; - nullpo_retr(-1, sd); if (!message || !*message) { clif->message(fd, msg_txt(1145)); // Please enter a Monster/NPC name/ID (usage: @disguiseall <name/ID>). @@ -4811,7 +4707,6 @@ ACMD(disguiseguild) *------------------------------------------*/ ACMD(undisguise) { - nullpo_retr(-1, sd); if (sd->disguise != -1) { pc->disguise(sd, -1); clif->message(fd, msg_txt(124)); // Undisguise applied. @@ -4829,7 +4724,6 @@ ACMD(undisguise) ACMD(undisguiseall) { struct map_session_data *pl_sd; struct s_mapiterator* iter; - nullpo_retr(-1, sd); iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) @@ -4851,7 +4745,6 @@ ACMD(undisguiseguild) struct map_session_data *pl_sd; struct guild *g; int i; - nullpo_retr(-1, sd); memset(guild_name, '\0', sizeof(guild_name)); @@ -4881,7 +4774,7 @@ ACMD(exp) { char output[CHAT_SIZE_MAX]; double nextb, nextj; - nullpo_retr(-1, sd); + memset(output, '\0', sizeof(output)); nextb = pc->nextbaseexp(sd); @@ -4903,7 +4796,6 @@ ACMD(exp) *------------------------------------------*/ ACMD(broadcast) { - nullpo_retr(-1, sd); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -4923,8 +4815,6 @@ ACMD(broadcast) *------------------------------------------*/ ACMD(localbroadcast) { - nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!message || !*message) { @@ -4946,7 +4836,6 @@ ACMD(email) { char actual_email[100]; char new_email[100]; - nullpo_retr(-1, sd); memset(actual_email, '\0', sizeof(actual_email)); memset(new_email, '\0', sizeof(new_email)); @@ -4981,7 +4870,6 @@ ACMD(email) ACMD(effect) { int type = 0, flag = 0; - nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d", &type) < 1) { clif->message(fd, msg_txt(1152)); // Please enter an effect number (usage: @effect <effect number>). @@ -4999,7 +4887,6 @@ ACMD(effect) *------------------------------------------*/ ACMD(killer) { - nullpo_retr(-1, sd); sd->state.killer = !sd->state.killer; if(sd->state.killer) @@ -5016,7 +4903,6 @@ ACMD(killer) * enable other people killing you *------------------------------------------*/ ACMD(killable) { - nullpo_retr(-1, sd); sd->state.killable = !sd->state.killable; if(sd->state.killable) @@ -5033,7 +4919,6 @@ ACMD(killable) { * turn skills on for the map *------------------------------------------*/ ACMD(skillon) { - nullpo_retr(-1, sd); map->list[sd->bl.m].flag.noskill = 0; clif->message(fd, msg_txt(244)); return true; @@ -5044,7 +4929,6 @@ ACMD(skillon) { * Turn skills off on the map *------------------------------------------*/ ACMD(skilloff) { - nullpo_retr(-1, sd); map->list[sd->bl.m].flag.noskill = 1; clif->message(fd, msg_txt(243)); return true; @@ -5057,7 +4941,7 @@ ACMD(skilloff) { ACMD(npcmove) { int x = 0, y = 0, m; struct npc_data *nd = 0; - nullpo_retr(-1, sd); + memset(atcmd_player_name, '\0', sizeof atcmd_player_name); if (!message || !*message || sscanf(message, "%d %d %23[^\n]", &x, &y, atcmd_player_name) < 3) { @@ -5096,7 +4980,6 @@ ACMD(addwarp) unsigned short m; struct npc_data* nd; - nullpo_retr(-1, sd); memset(warpname, '\0', sizeof(warpname)); if (!message || !*message || sscanf(message, "%31s %d %d %23[^\n]", mapname, &x, &y, warpname) < 4) { @@ -5127,7 +5010,6 @@ ACMD(addwarp) *------------------------------------------*/ ACMD(follow) { struct map_session_data *pl_sd = NULL; - nullpo_retr(-1, sd); if (!message || !*message) { if (sd->followtarget == -1) @@ -5163,7 +5045,7 @@ ACMD(follow) { ACMD(dropall) { int i; - nullpo_retr(-1, sd); + for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount) { if(sd->status.inventory[i].equip != 0) @@ -5181,7 +5063,6 @@ ACMD(dropall) ACMD(storeall) { int i; - nullpo_retr(-1, sd); if (sd->state.storage_flag != 1) { //Open storage. @@ -5207,7 +5088,6 @@ ACMD(storeall) ACMD(clearstorage) { int i, j; - nullpo_retr(-1, sd); if (sd->state.storage_flag == 1) { clif->message(fd, msg_txt(250)); @@ -5229,7 +5109,6 @@ ACMD(cleargstorage) int i, j; struct guild *g; struct guild_storage *guild_storage; - nullpo_retr(-1, sd); g = sd->guild; @@ -5268,7 +5147,6 @@ ACMD(cleargstorage) ACMD(clearcart) { int i; - nullpo_retr(-1, sd); if (pc_iscarton(sd) == 0) { clif->message(fd, msg_txt(1396)); // You do not have a cart to be cleaned. @@ -5302,9 +5180,7 @@ ACMD(skillid) { DBKey key; DBData *data; char partials[MAX_SKILLID_PARTIAL_RESULTS][MAX_SKILLID_PARTIAL_RESULTS_LEN]; - - nullpo_retr(-1, sd); - + if (!message || !*message) { clif->message(fd, msg_txt(1163)); // Please enter a skill name to look up (usage: @skillid <skill name>). return false; @@ -5348,7 +5224,6 @@ ACMD(useskill) { uint16 skill_id; uint16 skill_lv; char target[100]; - nullpo_retr(-1, sd); if(!message || !*message || sscanf(message, "%hu %hu %23[^\n]", &skill_id, &skill_lv, target) != 3) { clif->message(fd, msg_txt(1165)); // Usage: @useskill <skill ID> <skill level> <target> @@ -5389,10 +5264,9 @@ ACMD(useskill) { *------------------------------------------*/ ACMD(displayskill) { struct status_data *st; - unsigned int tick; + int64 tick; uint16 skill_id; uint16 skill_lv = 1; - nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%hu %hu", &skill_id, &skill_lv) < 1) { clif->message(fd, msg_txt(1166)); // Usage: @displayskill <skill ID> {<skill level>} @@ -5416,7 +5290,6 @@ ACMD(skilltree) { int meets, j, c=0; char target[NAME_LENGTH]; struct skill_tree_entry *ent; - nullpo_retr(-1, sd); if(!message || !*message || sscanf(message, "%hu %23[^\r\n]", &skill_id, target) != 2) { clif->message(fd, msg_txt(1167)); // Usage: @skilltree <skill ID> <target> @@ -5486,9 +5359,7 @@ void getring(struct map_session_data* sd) { ACMD(marry) { struct map_session_data *pl_sd = NULL; char player_name[NAME_LENGTH] = ""; - - nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%23s", player_name) != 1) { clif->message(fd, msg_txt(1172)); // Usage: @marry <char name> return false; @@ -5517,8 +5388,6 @@ ACMD(marry) { *------------------------------------------*/ ACMD(divorce) { - nullpo_retr(-1, sd); - if (pc->divorce(sd) != 0) { sprintf(atcmd_output, msg_txt(1175), sd->status.name); // '%s' is not married. clif->message(fd, atcmd_output); @@ -5561,7 +5430,6 @@ ACMD(changelook) * Turns on/off Autotrade for a specific player *------------------------------------------*/ ACMD(autotrade) { - nullpo_retr(-1, sd); if( map->list[sd->bl.m].flag.autotrade != battle_config.autotrade_mapflag ) { clif->message(fd, msg_txt(1179)); // Autotrade is not allowed on this map. @@ -5598,7 +5466,6 @@ ACMD(autotrade) { ACMD(changegm) { struct guild *g; struct map_session_data *pl_sd; - nullpo_retr(-1, sd); if (sd->status.guild_id == 0 || (g = sd->guild) == NULL || strcmp(g->master,sd->status.name)) { clif->message(fd, msg_txt(1181)); // You need to be a Guild Master to use this command. @@ -5629,7 +5496,6 @@ ACMD(changegm) { * Changes the leader of a party. *------------------------------------------*/ ACMD(changeleader) { - nullpo_retr(-1, sd); if( !message[0] ) { clif->message(fd, msg_txt(1185)); // Usage: @changeleader <party_member_name> @@ -5650,7 +5516,6 @@ ACMD(partyoption) struct party_data *p; int mi, option; char w1[16], w2[16]; - nullpo_retr(-1, sd); if (sd->status.party_id == 0 || (p = party->search(sd->status.party_id)) == NULL) { @@ -5692,7 +5557,7 @@ ACMD(partyoption) ACMD(autoloot) { int rate; - nullpo_retr(-1, sd); + // autoloot command without value if(!message || !*message) { @@ -5819,25 +5684,25 @@ ACMD(autolootitem) * Credits: * chriser,Aleos *------------------------------------------*/ -ACMD(autoloottype){ +ACMD(autoloottype) { int i; uint8 action = 3; // 1=add, 2=remove, 3=help+list (default), 4=reset enum item_types type = -1; int ITEM_NONE = 0; - + if (message && *message) { if (message[0] == '+') { message++; action = 1; - } - else if (message[0] == '-') { + } else if (message[0] == '-') { message++; action = 2; - } - else if (!strcmp(message,"reset")) + } else if (strcmp(message,"reset") == 0) { action = 4; + } - if (action < 3) { // add or remove + if (action < 3) { + // add or remove if (strncmp(message, "healing", 3) == 0) type = IT_HEALING; else if (strncmp(message, "usable", 3) == 0) @@ -5883,16 +5748,21 @@ ACMD(autoloottype){ clif->message(fd, atcmd_output); break; case 3: - clif->message(fd, msg_txt(1495)); // To add an item type to the list, use "@aloottype +<type name>". To remove an item type, use "@aloottype -<type name>". - clif->message(fd, msg_txt(1496)); // Type List: healing, usable, etc, weapon, armor, card, petegg, petarmor, ammo - clif->message(fd, msg_txt(1497)); // "@aloottype reset" will clear your autoloottype list. - if (sd->state.autoloottype == ITEM_NONE) - clif->message(fd, msg_txt(1498)); // Your autoloottype list is empty. - else { - clif->message(fd, msg_txt(1499)); // Item types on your autoloottype list: - for(i=0; i < IT_MAX; i++){ + clif->message(fd, msg_txt(38)); // Invalid location number, or name. + + { + // attempt to find the text help string + const char *text = atcommand_help_string(info); + if (text) clif->messageln(fd, text); // send the text to the client + } + + if (sd->state.autoloottype == ITEM_NONE) { + clif->message(fd, msg_txt(1495)); // Your autoloottype list is empty. + } else { + clif->message(fd, msg_txt(1496)); // Item types on your autoloottype list: + for(i=0; i < IT_MAX; i++) { if (sd->state.autoloottype&(1<<i)) { - sprintf(atcmd_output, " '%s'", itemdb->typename(i)); + sprintf(atcmd_output, " '%s'", itemdb->typename(i)); clif->message(fd, atcmd_output); } } @@ -5900,37 +5770,17 @@ ACMD(autoloottype){ break; case 4: sd->state.autoloottype = ITEM_NONE; - clif->message(fd, msg_txt(1500)); // Your autoloottype list has been reset. + clif->message(fd, msg_txt(1497)); // Your autoloottype list has been reset. break; } - return 0; + return true; } -/** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ -/*========================================== - * It is made to rain. - *------------------------------------------*/ -//ACMD(rain) { -// nullpo_retr(-1, sd); -// if (map->list[sd->bl.m].flag.rain) { -// map->list[sd->bl.m].flag.rain=0; -// clif->weather(sd->bl.m); -// clif->message(fd, msg_txt(1201)); // The rain has stopped. -// } else { -// map->list[sd->bl.m].flag.rain=1; -// clif->weather(sd->bl.m); -// clif->message(fd, msg_txt(1202)); // It has started to rain. -// } -// return true; -//} - /*========================================== * It is made to snow. *------------------------------------------*/ ACMD(snow) { - nullpo_retr(-1, sd); + if (map->list[sd->bl.m].flag.snow) { map->list[sd->bl.m].flag.snow=0; clif->weather(sd->bl.m); @@ -5948,7 +5798,7 @@ ACMD(snow) { * Cherry tree snowstorm is made to fall. (Sakura) *------------------------------------------*/ ACMD(sakura) { - nullpo_retr(-1, sd); + if (map->list[sd->bl.m].flag.sakura) { map->list[sd->bl.m].flag.sakura=0; clif->weather(sd->bl.m); @@ -5965,7 +5815,7 @@ ACMD(sakura) { * Clouds appear. *------------------------------------------*/ ACMD(clouds) { - nullpo_retr(-1, sd); + if (map->list[sd->bl.m].flag.clouds) { map->list[sd->bl.m].flag.clouds=0; clif->weather(sd->bl.m); @@ -5983,7 +5833,7 @@ ACMD(clouds) { * Different type of clouds using effect 516 *------------------------------------------*/ ACMD(clouds2) { - nullpo_retr(-1, sd); + if (map->list[sd->bl.m].flag.clouds2) { map->list[sd->bl.m].flag.clouds2=0; clif->weather(sd->bl.m); @@ -6001,7 +5851,7 @@ ACMD(clouds2) { * Fog hangs over. *------------------------------------------*/ ACMD(fog) { - nullpo_retr(-1, sd); + if (map->list[sd->bl.m].flag.fog) { map->list[sd->bl.m].flag.fog=0; clif->weather(sd->bl.m); @@ -6018,7 +5868,7 @@ ACMD(fog) { * Fallen leaves fall. *------------------------------------------*/ ACMD(leaves) { - nullpo_retr(-1, sd); + if (map->list[sd->bl.m].flag.leaves) { map->list[sd->bl.m].flag.leaves=0; clif->weather(sd->bl.m); @@ -6036,7 +5886,7 @@ ACMD(leaves) { * Fireworks appear. *------------------------------------------*/ ACMD(fireworks) { - nullpo_retr(-1, sd); + if (map->list[sd->bl.m].flag.fireworks) { map->list[sd->bl.m].flag.fireworks=0; clif->weather(sd->bl.m); @@ -6054,11 +5904,7 @@ ACMD(fireworks) { * Clearing Weather Effects by Dexity *------------------------------------------*/ ACMD(clearweather) { - nullpo_retr(-1, sd); - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //map->list[sd->bl.m].flag.rain=0; + map->list[sd->bl.m].flag.snow=0; map->list[sd->bl.m].flag.sakura=0; map->list[sd->bl.m].flag.clouds=0; @@ -6103,9 +5949,7 @@ ACMD(mobsearch) int mob_id; int number = 0; struct s_mapiterator* it; - - nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%99[^\n]", mob_name) < 1) { clif->message(fd, msg_txt(1218)); // Please enter a monster name (usage: @mobsearch <monster name>). return false; @@ -6228,9 +6072,7 @@ ACMD(pettalk) { char mes[100],temp[100]; struct pet_data *pd; - - nullpo_retr(-1, sd); - + if ( battle_config.min_chat_delay ) { if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 ) return true; @@ -6355,9 +6197,7 @@ ACMD(summon) int mob_id = 0; int duration = 0; struct mob_data *md; - unsigned int tick=timer->gettick(); - - nullpo_retr(-1, sd); + int64 tick=timer->gettick(); if (!message || !*message || sscanf(message, "%23s %d", name, &duration) < 1) { @@ -6403,7 +6243,6 @@ ACMD(summon) ACMD(adjgroup) { int new_group = 0; - nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d", &new_group) != 1) { clif->message(fd, msg_txt(1226)); // Usage: @adjgroup <group_id> @@ -6426,7 +6265,6 @@ ACMD(adjgroup) *------------------------------------------*/ ACMD(trade) { struct map_session_data *pl_sd = NULL; - nullpo_retr(-1, sd); if (!message || !*message) { clif->message(fd, msg_txt(1230)); // Please enter a player name (usage: @trade <char name>). @@ -6449,7 +6287,6 @@ ACMD(trade) { ACMD(setbattleflag) { char flag[128], value[128]; - nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%127s %127s", flag, value) != 2) { clif->message(fd, msg_txt(1231)); // Usage: @setbattleflag <flag> <value> @@ -6471,7 +6308,6 @@ ACMD(setbattleflag) *------------------------------------------*/ ACMD(unmute) { struct map_session_data *pl_sd = NULL; - nullpo_retr(-1, sd); if (!message || !*message) { clif->message(fd, msg_txt(1234)); // Please enter a player name (usage: @unmute <char name>). @@ -6503,7 +6339,6 @@ ACMD(uptime) { unsigned long seconds = 0, day = 24*60*60, hour = 60*60, minute = 60, days = 0, hours = 0, minutes = 0; - nullpo_retr(-1, sd); seconds = timer->get_uptime(); days = seconds/day; @@ -6526,7 +6361,7 @@ ACMD(uptime) ACMD(changesex) { int i; - nullpo_retr(-1, sd); + pc->resetskill(sd,4); // to avoid any problem with equipment and invalid sex, equipment is unequiped. for( i=0; i<EQI_MAX; i++ ) @@ -6541,7 +6376,6 @@ ACMD(changesex) ACMD(mute) { struct map_session_data *pl_sd = NULL; int manner; - nullpo_retr(-1, sd); if (!message || !*message || sscanf(message, "%d %23[^\n]", &manner, atcmd_player_name) < 1) { clif->message(fd, msg_txt(1237)); // Usage: @mute <time> <char name> @@ -6580,7 +6414,6 @@ ACMD(mute) { *------------------------------------------*/ ACMD(refresh) { - nullpo_retr(-1, sd); clif->refresh(sd); return true; } @@ -6589,7 +6422,6 @@ ACMD(refreshall) { struct map_session_data* iter_sd; struct s_mapiterator* iter; - nullpo_retr(-1, sd); iter = mapit_getallusers(); for (iter_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); iter_sd = (TBL_PC*)mapit->next(iter)) @@ -6605,9 +6437,7 @@ ACMD(refreshall) ACMD(identify) { int i,num; - - nullpo_retr(-1, sd); - + for(i=num=0;i<MAX_INVENTORY;i++){ if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify!=1){ num++; @@ -6623,7 +6453,7 @@ ACMD(identify) ACMD(misceffect) { int effect = 0; - nullpo_retr(-1, sd); + if (!message || !*message) return false; if (sscanf(message, "%d", &effect) < 1) @@ -6638,7 +6468,6 @@ ACMD(misceffect) { *------------------------------------------*/ ACMD(mail) { - nullpo_ret(sd); mail->openmail(sd); return true; } @@ -6796,9 +6625,7 @@ ACMD(showmobs) int mob_id; int number = 0; struct s_mapiterator* it; - - nullpo_retr(-1, sd); - + if(sscanf(message, "%99[^\n]", mob_name) < 0) return false; @@ -6854,8 +6681,6 @@ ACMD(homlevel) { TBL_HOM * hd; int level = 0; enum homun_type htype; - - nullpo_retr(-1, sd); if( !message || !*message || ( level = atoi(message) ) < 1 ) { clif->message(fd, msg_txt(1253)); // Please enter a level adjustment (usage: @homlevel <number of levels>). @@ -6911,8 +6736,6 @@ ACMD(homlevel) { *------------------------------------------*/ ACMD(homevolution) { - nullpo_retr(-1, sd); - if ( !homun_alive(sd->hd) ) { clif->message(fd, msg_txt(1254)); // You do not have a homunculus. return false; @@ -6929,7 +6752,6 @@ ACMD(homevolution) ACMD(hommutate) { int homun_id; enum homun_type m_class, m_id; - nullpo_retr(-1, sd); if( !homun_alive(sd->hd) ) { clif->message(fd, msg_txt(1254)); // You do not have a homunculus. @@ -6958,7 +6780,6 @@ ACMD(hommutate) { *------------------------------------------*/ ACMD(makehomun) { int homunid; - nullpo_retr(-1, sd); if (!message || !*message) { clif->message(fd, msg_txt(1256)); // Please enter a homunculus ID (usage: @makehomun <homunculus id>). @@ -6996,9 +6817,7 @@ ACMD(makehomun) { ACMD(homfriendly) { int friendly = 0; - - nullpo_retr(-1, sd); - + if ( !homun_alive(sd->hd) ) { clif->message(fd, msg_txt(1254)); // You do not have a homunculus. return false; @@ -7023,9 +6842,7 @@ ACMD(homfriendly) ACMD(homhungry) { int hungry = 0; - - nullpo_retr(-1, sd); - + if ( !homun_alive(sd->hd) ) { clif->message(fd, msg_txt(1254)); // You do not have a homunculus. return false; @@ -7050,9 +6867,7 @@ ACMD(homhungry) ACMD(homtalk) { char mes[100],temp[100]; - - nullpo_retr(-1, sd); - + if ( battle_config.min_chat_delay ) { if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 ) return true; @@ -7086,7 +6901,6 @@ ACMD(homtalk) ACMD(hominfo) { struct homun_data *hd; struct status_data *st; - nullpo_retr(-1, sd); if ( !homun_alive(sd->hd) ) { clif->message(fd, msg_txt(1254)); // You do not have a homunculus. @@ -7124,9 +6938,7 @@ ACMD(homstats) struct s_homunculus_db *db; struct s_homunculus *hom; int lv, min, max, evo; - - nullpo_retr(-1, sd); - + if ( !homun_alive(sd->hd) ) { clif->message(fd, msg_txt(1254)); // You do not have a homunculus. return false; @@ -7188,7 +7000,6 @@ ACMD(homstats) } ACMD(homshuffle) { - nullpo_retr(-1, sd); if(!sd->hd) return false; // nothing to do @@ -7389,7 +7200,6 @@ int atcommand_mutearea_sub(struct block_list *bl,va_list ap) ACMD(mutearea) { int time; - nullpo_ret(sd); if (!message || !*message) { clif->message(fd, msg_txt(1297)); // Please enter a time in minutes (usage: @mutearea/@stfu <time in minutes>). @@ -7410,7 +7220,6 @@ ACMD(rates) { char buf[CHAT_SIZE_MAX]; - nullpo_ret(sd); memset(buf, '\0', sizeof(buf)); snprintf(buf, CHAT_SIZE_MAX, msg_txt(1298), // Experience rates: Base %.2fx / Job %.2fx @@ -7436,7 +7245,6 @@ ACMD(rates) ACMD(me) { char tempmes[CHAT_SIZE_MAX]; - nullpo_retr(-1, sd); memset(tempmes, '\0', sizeof(tempmes)); memset(atcmd_output, '\0', sizeof(atcmd_output)); @@ -7465,7 +7273,6 @@ ACMD(me) ACMD(size) { int size = 0; - nullpo_retr(-1, sd); size = cap_value(atoi(message),SZ_SMALL,SZ_BIG); @@ -7520,7 +7327,6 @@ ACMD(sizeguild) char guild_name[NAME_LENGTH]; struct map_session_data *pl_sd; struct guild *g; - nullpo_retr(-1, sd); memset(guild_name, '\0', sizeof(guild_name)); @@ -7559,9 +7365,7 @@ ACMD(sizeguild) * @monsterignore * => Makes monsters ignore you. [Valaris] *------------------------------------------*/ -ACMD(monsterignore) -{ - nullpo_retr(-1, sd); +ACMD(monsterignore) { if (!sd->state.monster_ignore) { sd->state.monster_ignore = 1; @@ -7577,9 +7381,7 @@ ACMD(monsterignore) * @fakename * => Gives your character a fake name. [Valaris] *------------------------------------------*/ -ACMD(fakename) -{ - nullpo_retr(-1, sd); +ACMD(fakename){ if( !message || !*message ) { @@ -7624,7 +7426,7 @@ ACMD(mapflag) { char flag_name[100]; short flag=0,i; - nullpo_retr(-1, sd); + memset(flag_name, '\0', sizeof(flag_name)); if (!message || !*message || (sscanf(message, "%99s %hd", flag_name, &flag) < 1)) { @@ -7642,7 +7444,7 @@ ACMD(mapflag) { CHECKFLAG(nojobexp); CHECKFLAG(nomobloot); CHECKFLAG(nomvploot); CHECKFLAG(nightenabled); CHECKFLAG(nodrop); CHECKFLAG(novending); CHECKFLAG(loadevent); CHECKFLAG(nochat); CHECKFLAG(partylock); CHECKFLAG(guildlock); CHECKFLAG(src4instance); - CHECKFLAG(notomb); + CHECKFLAG(notomb); CHECKFLAG(nocashshop); clif->message(sd->fd," "); clif->message(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) clif->message(sd->fd,msg_txt(1313)); // Type "@mapflag available" to list the available mapflags. @@ -7679,7 +7481,7 @@ ACMD(mapflag) { SETFLAG(nojobexp); SETFLAG(nomobloot); SETFLAG(nomvploot); SETFLAG(nightenabled); SETFLAG(nodrop); SETFLAG(novending); SETFLAG(loadevent); SETFLAG(nochat); SETFLAG(partylock); SETFLAG(guildlock); SETFLAG(src4instance); - SETFLAG(notomb); + SETFLAG(notomb); SETFLAG(nocashshop); clif->message(sd->fd,msg_txt(1314)); // Invalid flag name or flag. clif->message(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) @@ -7691,7 +7493,7 @@ ACMD(mapflag) { clif->message(sd->fd,"nozenypenalty, notrade, noskill, nowarp, nowarpto, noicewall, snow, clouds, clouds2,"); clif->message(sd->fd,"fog, fireworks, sakura, leaves, nobaseexp, nojobexp, nomobloot,"); clif->message(sd->fd,"nomvploot, nightenabled, nodrop, novending, loadevent, nochat, partylock,"); - clif->message(sd->fd,"guildlock, src4instance, notomb"); + clif->message(sd->fd,"guildlock, src4instance, notomb, nocashshop"); #undef CHECKFLAG #undef SETFLAG @@ -7909,43 +7711,45 @@ ACMD(cash) char output[128]; int value; int ret=0; - nullpo_retr(-1, sd); if( !message || !*message || (value = atoi(message)) == 0 ) { clif->message(fd, msg_txt(1322)); // Please enter an amount. return false; } - if( !strcmpi(command+1,"cash") ) - { + if( !strcmpi(command+1,"cash") ) { if( value > 0 ) { if( (ret=pc->getcash(sd, value, 0)) >= 0){ - sprintf(output, msg_txt(505), ret, sd->cashPoints); - clif->disp_onlyself(sd, output, strlen(output)); - } - else clif->message(fd, msg_txt(149)); // Unable to decrease the number/value. + // If this option is set, the message is already sent by pc function + if( !battle_config.cashshop_show_points ){ + sprintf(output, msg_txt(505), ret, sd->cashPoints); + clif->disp_onlyself(sd, output, strlen(output)); + } + } else + clif->message(fd, msg_txt(149)); // Unable to decrease the number/value. } else { if( (ret=pc->paycash(sd, -value, 0)) >= 0){ sprintf(output, msg_txt(410), ret, sd->cashPoints); clif->disp_onlyself(sd, output, strlen(output)); - } - else clif->message(fd, msg_txt(41)); // Unable to decrease the number/value. + } else + clif->message(fd, msg_txt(41)); // Unable to decrease the number/value. } - } - else - { // @points + } else { // @points if( value > 0 ) { - if( (ret=pc->getcash(sd, 0, value)) >= 0){ - sprintf(output, msg_txt(506), ret, sd->kafraPoints); - clif->disp_onlyself(sd, output, strlen(output)); - } - else clif->message(fd, msg_txt(149)); // Unable to decrease the number/value. + if( (ret=pc->getcash(sd, 0, value)) >= 0) { + // If this option is set, the message is already sent by pc function + if( !battle_config.cashshop_show_points ){ + sprintf(output, msg_txt(506), ret, sd->kafraPoints); + clif->disp_onlyself(sd, output, strlen(output)); + } + } else + clif->message(fd, msg_txt(149)); // Unable to decrease the number/value. } else { if( (ret=pc->paycash(sd, -value, -value)) >= 0){ sprintf(output, msg_txt(411), ret, sd->kafraPoints); clif->disp_onlyself(sd, output, strlen(output)); - } - else clif->message(fd, msg_txt(41)); // Unable to decrease the number/value. + } else + clif->message(fd, msg_txt(41)); // Unable to decrease the number/value. } } @@ -8056,7 +7860,6 @@ ACMD(feelreset) * AUCTION SYSTEM *------------------------------------------*/ ACMD(auction) { - nullpo_ret(sd); if( !battle_config.feature_auction ) { clif->colormes(sd->fd,COLOR_RED,msg_txt(1484)); @@ -8073,8 +7876,6 @@ ACMD(auction) { *------------------------------------------*/ ACMD(ksprotection) { - nullpo_retr(-1,sd); - if( sd->state.noks ) { sd->state.noks = 0; clif->message(fd, msg_txt(1325)); // [ K.S Protection Inactive ] @@ -8105,7 +7906,6 @@ ACMD(ksprotection) * Map Kill Steal Protection Setting *------------------------------------------*/ ACMD(allowks) { - nullpo_retr(-1,sd); if( map->list[sd->bl.m].flag.allowks ) { map->list[sd->bl.m].flag.allowks = 0; @@ -8117,9 +7917,7 @@ ACMD(allowks) { return true; } -ACMD(resetstat) -{ - nullpo_retr(-1, sd); +ACMD(resetstat) { pc->resetstate(sd); sprintf(atcmd_output, msg_txt(207), sd->status.name); @@ -8127,9 +7925,7 @@ ACMD(resetstat) return true; } -ACMD(resetskill) -{ - nullpo_retr(-1,sd); +ACMD(resetskill) { pc->resetskill(sd,1); sprintf(atcmd_output, msg_txt(206), sd->status.name); @@ -8149,9 +7945,7 @@ ACMD(itemlist) const struct item* items; int size; StringBuf buf; - - nullpo_retr(-1, sd); - + if( strcmp(command+1, "storagelist") == 0 ) { location = "storage"; items = sd->status.storage.items; @@ -8351,14 +8145,11 @@ ACMD(stats) return true; } -ACMD(delitem) -{ +ACMD(delitem) { char item_name[100]; int nameid, amount = 0, total, idx; struct item_data* id; - - nullpo_retr(-1, sd); - + if( !message || !*message || ( sscanf(message, "\"%99[^\"]\" %d", item_name, &amount) < 2 && sscanf(message, "%99s %d", item_name, &amount) < 2 ) || amount < 1 ) { clif->message(fd, msg_txt(1355)); // Please enter an item name/ID, a quantity, and a player name (usage: #delitem <player> <item_name_or_ID> <quantity>). @@ -8417,17 +8208,15 @@ ACMD(delitem) /*========================================== * Custom Fonts *------------------------------------------*/ -ACMD(font) -{ +ACMD(font) { int font_id; - nullpo_retr(-1,sd); font_id = atoi(message); if( font_id == 0 ) { - if( sd->user_font ) + if( sd->status.font ) { - sd->user_font = 0; + sd->status.font = 0; clif->message(fd, msg_txt(1356)); // Returning to normal font. clif->font(sd); } @@ -8439,9 +8228,9 @@ ACMD(font) } else if( font_id < 0 || font_id > 9 ) clif->message(fd, msg_txt(1359)); // Invalid font. Use a value from 0 to 9. - else if( font_id != sd->user_font ) + else if( font_id != sd->status.font ) { - sd->user_font = font_id; + sd->status.font = font_id; clif->font(sd); clif->message(fd, msg_txt(1360)); // Font changed. } @@ -9772,24 +9561,39 @@ void atcommand_basecommands(void) { ACMD_DEF(costume), ACMD_DEF(skdebug), }; - AtCommandInfo* cmd; int i; for( i = 0; i < ARRAYLENGTH(atcommand_base); i++ ) { - if(atcommand->exists(atcommand_base[i].command)) { // Should not happen if atcommand_base[] array is OK + if(!atcommand->add(atcommand_base[i].command,atcommand_base[i].func)) { // Should not happen if atcommand_base[] array is OK ShowDebug("atcommand_basecommands: duplicate ACMD_DEF for '%s'.\n", atcommand_base[i].command); continue; } - CREATE(cmd, AtCommandInfo, 1); - safestrncpy(cmd->command, atcommand_base[i].command, sizeof(cmd->command)); - cmd->func = atcommand_base[i].func; - cmd->help = NULL;/* start as null dear */ - cmd->log = true; - strdb_put(atcommand->db, cmd->command, cmd); } + + /* @commands from plugins */ + HPM_map_atcommands(); + return; } +bool atcommand_add(char *name,AtCommandFunc func) { + AtCommandInfo* cmd; + + if(atcommand->exists(name)) //caller will handle/display on false + return false; + + CREATE(cmd, AtCommandInfo, 1); + + safestrncpy(cmd->command, name, sizeof(cmd->command)); + cmd->func = func; + cmd->help = NULL; + cmd->log = true; + + strdb_put(atcommand->db, cmd->command, cmd); + + return true; +} + /*========================================== * Command lookup functions *------------------------------------------*/ @@ -9975,6 +9779,9 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message sprintf(atcmd_msg, "%s", message); } + if( battle_config.idletime_criteria & BCIDLE_ATCOMMAND ) + sd->idletime = last_tick; + //Clearing these to be used once more. memset(command, '\0', sizeof(command)); memset(params, '\0', sizeof(params)); @@ -10298,30 +10105,14 @@ bool atcommand_can_use2(struct map_session_data *sd, const char *command, AtComm return false; } bool atcommand_hp_add(char *name, AtCommandFunc func) { - AtCommandInfo* cmd; - + /* if commands are added after group permissions are thrown in, they end up with no permissions */ + /* so we restrict commands to be linked in during boot */ if( runflag == MAPSERVER_ST_RUNNING ) { ShowDebug("atcommand_hp_add: Commands can't be added after server is ready, skipping '%s'...\n",name); return false; } - if( atcommand->db == NULL ) - atcommand->db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); - - if( atcommand->exists(name) ) { - ShowDebug("atcommand_hp_add: duplicate command '%s', skipping...\n", name); - return false; - } - - CREATE(cmd, AtCommandInfo, 1); - - safestrncpy(cmd->command, name, sizeof(cmd->command)); - cmd->func = func; - cmd->help = NULL;/* start as null dear */ - cmd->log = true; - - strdb_put(atcommand->db, cmd->command, cmd); - return true; + return HPM_map_add_atcommand(name,func); } /** @@ -10407,4 +10198,5 @@ void atcommand_defaults(void) { atcommand->cmd_db_clear_sub = atcommand_db_clear_sub; atcommand->doload = atcommand_doload; atcommand->base_commands = atcommand_basecommands; + atcommand->add = atcommand_add; } diff --git a/src/map/atcommand.h b/src/map/atcommand.h index 603abc0cc..63c38e4d1 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -110,6 +110,7 @@ struct atcommand_interface { int (*cmd_db_clear_sub) (DBKey key, DBData *data, va_list args); void (*doload) (void); void (*base_commands) (void); + bool (*add) (char *name, AtCommandFunc func); }; struct atcommand_interface *atcommand; diff --git a/src/map/battle.c b/src/map/battle.c index fb950860e..94222f663 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -196,7 +196,7 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int return bl_list[rnd()%c]; } -int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { +int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) { struct delay_damage *dat = (struct delay_damage *)data; if ( dat ) { @@ -244,7 +244,7 @@ int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { return 0; } -int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) { +int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) { struct delay_damage *dat; struct status_change *sc; nullpo_ret(src); @@ -349,7 +349,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d y = sg->val3 & 0xffff; skill->unitsetting(src,su->group->skill_id,su->group->skill_lv,x,y,1); sg->val3 = -1; - sg->limit = DIFF_TICK(timer->gettick(),sg->tick)+300; + sg->limit = DIFF_TICK32(timer->gettick(),sg->tick)+300; } } } @@ -2938,27 +2938,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 ) status->change_spread(bl, src); // Deadly infect attacked side - - if( sc && sc->data[SC__SHADOWFORM] ) { - struct block_list *s_bl = map->id2bl(sc->data[SC__SHADOWFORM]->val2); - if( !s_bl || s_bl->m != bl->m ) { // If the shadow form target is not present remove the sc. - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - } else if( status->isdead(s_bl) || !battle->check_target(src,s_bl,BCT_ENEMY)) { // If the shadow form target is dead or not your enemy remove the sc in both. - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - if( s_bl->type == BL_PC ) - ((TBL_PC*)s_bl)->shadowform_id = 0; - } else { - if( (--sc->data[SC__SHADOWFORM]->val3) < 0 ) { // If you have exceded max hits supported, remove the sc in both. - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - if( s_bl->type == BL_PC ) - ((TBL_PC*)s_bl)->shadowform_id = 0; - } else { - status->damage(bl, s_bl, damage, 0, clif->damage(s_bl, s_bl, timer->gettick(), 500, 500, damage, -1, 0, 0), 0); - return ATK_NONE; - } - } - } - } //SC effects from caster side. @@ -5290,14 +5269,14 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama status_zap(tbl, rhp, rsp); } // Deals the same damage to targets in area. [pakpil] -int battle_damage_area( struct block_list *bl, va_list ap) { - unsigned int tick; +int battle_damage_area(struct block_list *bl, va_list ap) { + int64 tick; int amotion, dmotion, damage; struct block_list *src; nullpo_ret(bl); - tick=va_arg(ap, unsigned int); + tick = va_arg(ap, int64); src=va_arg(ap,struct block_list *); amotion=va_arg(ap,int); dmotion=va_arg(ap,int); @@ -5323,7 +5302,7 @@ int battle_damage_area( struct block_list *bl, va_list ap) { /*========================================== * Do a basic physical attack (call trough unit_attack_timer) *------------------------------------------*/ -enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, unsigned int tick, int flag) { +enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, int64 tick, int flag) { struct map_session_data *sd = NULL, *tsd = NULL; struct status_data *sstatus, *tstatus; struct status_change *sc, *tsc; @@ -5533,7 +5512,13 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } map->freeblock_lock(); - battle->delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion, true); + if( skill->check_shadowform(target, damage, wd.div_) ){ + if( !status->isdead(target) ) + skill->additional_effect(src, target, 0, 0, wd.flag, wd.dmg_lv, tick); + if( wd.dmg_lv > ATK_BLOCK) + skill->counter_additional_effect(src, target, 0, 0, wd.flag,tick); + }else + battle->delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion, true); if( tsc ) { if( tsc->data[SC_DEVOTION] ) { struct status_change_entry *sce = tsc->data[SC_DEVOTION]; @@ -6485,6 +6470,7 @@ static const struct _battle_data { { "guild_notice_changemap", &battle_config.guild_notice_changemap, 2, 0, 2, }, { "feature.banking", &battle_config.feature_banking, 1, 0, 1, }, { "feature.auction", &battle_config.feature_auction, 0, 0, 2, }, + { "idletime_criteria", &battle_config.idletime_criteria, 0x25, 1, INT_MAX, }, { "mon_trans_disable_in_gvg", &battle_config.mon_trans_disable_in_gvg, 0, 0, 1, }, }; @@ -6631,7 +6617,7 @@ void Hercules_report(char* date, char *time_c) { #undef BFLAG_LENGTH } -static int Hercules_report_timer(int tid, unsigned int tick, int id, intptr_t data) { +static int Hercules_report_timer(int tid, int64 tick, int id, intptr_t data) { if( chrif->isconnected() ) {/* char server relays it, so it must be online. */ Hercules_report(__DATE__,__TIME__); } @@ -6775,7 +6761,7 @@ int battle_config_read(const char* cfgName) void do_init_battle(void) { battle->delay_damage_ers = ers_new(sizeof(struct delay_damage),"battle.c::delay_damage_ers",ERS_OPT_CLEAR); - timer->add_func_list(battle_delay_damage_sub, "battle_delay_damage_sub"); + timer->add_func_list(battle->delay_damage_sub, "battle_delay_damage_sub"); #ifndef STATS_OPT_OUT timer->add_func_list(Hercules_report_timer, "Hercules_report_timer"); diff --git a/src/map/battle.h b/src/map/battle.h index 1aa07b2be..bf08ab8d6 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -454,7 +454,7 @@ struct Battle_Config { int max_walk_path; int item_enabled_npc; int packet_obfuscation; - + int idletime_criteria; int gm_ignore_warpable_area; int client_accept_chatdori; // [Ai4rei/Mirei] @@ -467,6 +467,20 @@ struct Battle_Config { int mon_trans_disable_in_gvg; } battle_config; +/* criteria for battle_config.idletime_critera */ +enum e_battle_config_idletime { + BCIDLE_WALK = 0x001, + BCIDLE_USESKILLTOID = 0x002, + BCIDLE_USESKILLTOPOS = 0x004, + BCIDLE_USEITEM = 0x008, + BCIDLE_ATTACK = 0x010, + BCIDLE_CHAT = 0x020, + BCIDLE_SIT = 0x040, + BCIDLE_EMOTION = 0x080, + BCIDLE_DROPITEM = 0x100, + BCIDLE_ATCOMMAND = 0x200, +}; + // Dammage delayed info struct delay_damage { int src_id; @@ -504,11 +518,11 @@ struct battle_interface { /* battlegrounds final damage calculation */ int64 (*calc_bg_damage) (struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag); /* normal weapon attack */ - enum damage_lv (*weapon_attack) (struct block_list *bl, struct block_list *target, unsigned int tick, int flag); + enum damage_lv (*weapon_attack) (struct block_list *bl, struct block_list *target, int64 tick, int flag); /* calculate weapon attack */ struct Damage (*calc_weapon_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag); /* delays damage or skills by a timer */ - int (*delay_damage) (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects); + int (*delay_damage) (int64 tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects); /* drain damage */ void (*drain) (struct map_session_data *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int boss); /* damage return/reflect */ @@ -552,7 +566,7 @@ struct battle_interface { int (*get_targeted_sub) (struct block_list *bl, va_list ap); int (*get_enemy_sub) (struct block_list *bl, va_list ap); int (*get_enemy_area_sub) (struct block_list *bl, va_list ap); - int (*delay_damage_sub) (int tid, unsigned int tick, int id, intptr_t data); + int (*delay_damage_sub) (int tid, int64 tick, int id, intptr_t data); int (*blewcount_bonus) (struct map_session_data *sd, uint16 skill_id); /* skill range criteria */ int (*range_type) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv); @@ -573,7 +587,7 @@ struct battle_interface { /* picks a random enemy within the specified range */ struct block_list* (*get_enemy_area) (struct block_list *src, int x, int y, int range, int type, int ignore_id); /* damages area, originally for royal guard's reflect damage */ - int (*damage_area) ( struct block_list *bl, va_list ap); + int (*damage_area) (struct block_list *bl, va_list ap); }; struct battle_interface *battle; diff --git a/src/map/battleground.c b/src/map/battleground.c index e7fe4085b..62688659e 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -249,7 +249,7 @@ int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap) { return 0; } -int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) { +int bg_send_xy_timer(int tid, int64 tick, int id, intptr_t data) { bg->team_db->foreach(bg->team_db, bg->send_xy_timer_sub, tick); return 0; } @@ -534,7 +534,7 @@ void bg_begin(struct bg_arena *arena) { /* currently running only on solo mode so we do it evenly */ } } -int bg_begin_timer(int tid, unsigned int tick, int id, intptr_t data) { +int bg_begin_timer(int tid, int64 tick, int id, intptr_t data) { bg->begin(bg->arena[id]); bg->arena[id]->begin_timer = INVALID_TIMER; return 0; @@ -553,7 +553,7 @@ void bg_queue_pregame(struct bg_arena *arena) { } arena->begin_timer = timer->add( timer->gettick() + (arena->pregame_duration*1000), bg->begin_timer, arena->id, 0 ); } -int bg_fillup_timer(int tid, unsigned int tick, int id, intptr_t data) { +int bg_fillup_timer(int tid, int64 tick, int id, intptr_t data) { bg->queue_pregame(bg->arena[id]); bg->arena[id]->fillup_timer = INVALID_TIMER; return 0; diff --git a/src/map/battleground.h b/src/map/battleground.h index 1c224e1c2..a5e540924 100644 --- a/src/map/battleground.h +++ b/src/map/battleground.h @@ -84,9 +84,9 @@ struct battleground_interface { int (*id2pos) (int queue_id, int account_id); void (*queue_pc_cleanup) (struct map_session_data *sd); void (*begin) (struct bg_arena *arena); - int (*begin_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*begin_timer) (int tid, int64 tick, int id, intptr_t data); void (*queue_pregame) (struct bg_arena *arena); - int (*fillup_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*fillup_timer) (int tid, int64 tick, int id, intptr_t data); void (*queue_ready_ack) (struct bg_arena *arena, struct map_session_data *sd, bool response); void (*match_over) (struct bg_arena *arena, bool canceled); void (*queue_check) (struct bg_arena *arena); @@ -102,7 +102,7 @@ struct battleground_interface { int (*team_get_id) (struct block_list *bl); int (*send_message) (struct map_session_data *sd, const char *mes, int len); int (*send_xy_timer_sub) (DBKey key, DBData *data, va_list ap); - int (*send_xy_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data); /* */ void (*config_read) (void); }; diff --git a/src/map/chrif.c b/src/map/chrif.c index 5308eada9..a13217060 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -682,7 +682,7 @@ int auth_db_cleanup_sub(DBKey key, DBData *data, va_list ap) { return 0; } -int auth_db_cleanup(int tid, unsigned int tick, int id, intptr_t data) { +int auth_db_cleanup(int tid, int64 tick, int id, intptr_t data) { chrif_check(0); chrif->auth_db->foreach(chrif->auth_db, chrif->auth_db_cleanup_sub); return 0; @@ -1139,7 +1139,7 @@ int chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the #ifdef ENABLE_SC_SAVING int i, count=0; - unsigned int tick; + int64 tick; struct status_change_data data; struct status_change *sc = &sd->sc; const struct TimerData *td; @@ -1159,7 +1159,7 @@ int chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the td = timer->get(sc->data[i]->timer); if (td == NULL || td->func != status->change_timer || DIFF_TICK(td->tick,tick) < 0) continue; - data.tick = DIFF_TICK(td->tick,tick); //Duration that is left before ending. + data.tick = DIFF_TICK32(td->tick,tick); //Duration that is left before ending. } else data.tick = -1; //Infinite duration data.type = i; @@ -1212,6 +1212,8 @@ int chrif_load_scdata(int fd) { data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data)); status->change_start(&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 15); } + + pc->scdata_received(sd); #endif return 0; @@ -1462,7 +1464,7 @@ int chrif_parse(int fd) { return 0; } -int send_usercount_tochar(int tid, unsigned int tick, int id, intptr_t data) { +int send_usercount_tochar(int tid, int64 tick, int id, intptr_t data) { chrif_check(-1); WFIFOHEAD(chrif->fd,4); @@ -1509,7 +1511,7 @@ int send_users_tochar(void) { * timerFunction * Chk the connection to char server, (if it down) *------------------------------------------*/ -int check_connect_char_server(int tid, unsigned int tick, int id, intptr_t data) { +int check_connect_char_server(int tid, int64 tick, int id, intptr_t data) { static int displayed = 0; if ( chrif->fd <= 0 || session[chrif->fd] == NULL ) { if ( !displayed ) { diff --git a/src/map/chrif.h b/src/map/chrif.h index 0617a6702..9df4b9931 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -30,11 +30,11 @@ enum sd_state { ST_LOGIN, ST_LOGOUT, ST_MAPCHANGE }; struct auth_node { int account_id, char_id; int login_id1, login_id2, sex, fd; - time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) - struct map_session_data *sd; //Data from logged on char. - struct mmo_charstatus *char_dat; //Data from char server. - unsigned int node_created; //timestamp for node timeouts - enum sd_state state; //To track whether player was login in/out or changing maps. + time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) + struct map_session_data *sd; //Data from logged on char. + struct mmo_charstatus *char_dat; //Data from char server. + int64 node_created; //timestamp for node timeouts + enum sd_state state; //To track whether player was login in/out or changing maps. }; /*===================================== @@ -109,15 +109,15 @@ struct chrif_interface { void (*skillid2idx) (int fd); bool (*sd_to_auth) (TBL_PC* sd, enum sd_state state); - int (*check_connect_char_server) (int tid, unsigned int tick, int id, intptr_t data); + int (*check_connect_char_server) (int tid, int64 tick, int id, intptr_t data); bool (*auth_logout) (TBL_PC* sd, enum sd_state state); void (*save_ack) (int fd); int (*reconnect) (DBKey key, DBData *data, va_list ap); int (*auth_db_cleanup_sub) (DBKey key, DBData *data, va_list ap); void (*char_ask_name_answer) (int acc, const char* player_name, uint16 type, uint16 answer); int (*auth_db_final) (DBKey key, DBData *data, va_list ap); - int (*send_usercount_tochar) (int tid, unsigned int tick, int id, intptr_t data); - int (*auth_db_cleanup) (int tid, unsigned int tick, int id, intptr_t data); + int (*send_usercount_tochar) (int tid, int64 tick, int id, intptr_t data); + int (*auth_db_cleanup) (int tid, int64 tick, int id, intptr_t data); int (*connect) (int fd); int (*connectack) (int fd); diff --git a/src/map/clif.c b/src/map/clif.c index 060509807..c1e7cb1c9 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -56,6 +56,13 @@ struct clif_interface clif_s; +/* re-usable */ +static struct packet_itemlist_normal itemlist_normal; +static struct packet_itemlist_equip itemlist_equip; +static struct packet_storelist_normal storelist_normal; +static struct packet_storelist_equip storelist_equip; +static struct packet_viewequip_ack viewequip_list; + //#define DUMP_UNKNOWN_PACKET //#define DUMP_INVALID_PACKET @@ -282,7 +289,7 @@ int clif_send_sub(struct block_list *bl, va_list ap) { len = va_arg(ap,int); nullpo_ret(src_bl = va_arg(ap,struct block_list*)); type = va_arg(ap,int); - + switch(type) { case AREA_WOS: if (bl == src_bl) @@ -314,6 +321,10 @@ int clif_send_sub(struct block_list *bl, va_list ap) { #endif } + /* unless visible, hold it here */ + if( clif->ally_only && !sd->special_state.intravision && battle->check_target( src_bl, &sd->bl, BCT_ENEMY ) > 0 ) + return 0; + WFIFOHEAD(fd, len); if (WFIFOP(fd,0) == buf) { ShowError("WARNING: Invalid use of clif->send function\n"); @@ -595,12 +606,12 @@ void clif_authok(struct map_session_data *sd) struct packet_authok p; p.PacketType = authokType; - p.startTime = timer->gettick(); + p.startTime = (unsigned int)timer->gettick(); WBUFPOS(&p.PosDir[0],0,sd->bl.x,sd->bl.y,sd->ud.dir); /* do the stupid client math */ p.xSize = p.ySize = 5; /* not-used */ #if PACKETVER >= 20080102 - p.font = sd->user_font; // FIXME: Font is currently not saved. + p.font = sd->status.font; #endif clif->send(&p,sizeof(p),&sd->bl,SELF); @@ -707,7 +718,7 @@ void clif_dropflooritem(struct flooritem_data* fitem) { #if PACKETVER >= 20130000 /* not sure date */ p.type = itemtype(itemdb_type(fitem->item_data.nameid)); #endif - p.IsIdentified = fitem->item_data.identify; + p.IsIdentified = fitem->item_data.identify ? 1 : 0; p.xPos = fitem->bl.x; p.yPos = fitem->bl.y; p.subX = fitem->subx; @@ -787,14 +798,13 @@ void clif_clearunit_area(struct block_list* bl, clr_type type) /// Used to make monsters with player-sprites disappear after dying /// like normal monsters, because the client does not remove those /// automatically. -int clif_clearunit_delayed_sub(int tid, unsigned int tick, int id, intptr_t data) { +int clif_clearunit_delayed_sub(int tid, int64 tick, int id, intptr_t data) { struct block_list *bl = (struct block_list *)data; clif->clearunit_area(bl, (clr_type) id); ers_free(clif->delay_clearunit_ers,bl); return 0; } -void clif_clearunit_delayed(struct block_list* bl, clr_type type, unsigned int tick) -{ +void clif_clearunit_delayed(struct block_list* bl, clr_type type, int64 tick) { struct block_list *tbl = ers_alloc(clif->delay_clearunit_ers, struct block_list); memcpy (tbl, bl, sizeof (struct block_list)); timer->add(tick, clif->clearunit_delayed_sub, (int)type, (intptr_t)tbl); @@ -900,7 +910,7 @@ void clif_set_unit_idle2(struct block_list* bl, struct map_session_data *tsd, en p.GEmblemVer = status->get_emblem_id(bl); p.honor = (sd) ? sd->status.manner : 0; p.virtue = (sc) ? sc->opt3 : 0; - p.isPKModeON = (sd) ? sd->status.karma : 0; + p.isPKModeON = (sd && sd->status.karma) ? 1 : 0; p.sex = vd->sex; WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit->getdir(bl)); p.xSize = p.ySize = (sd) ? 5 : 0; @@ -965,14 +975,14 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu p.GEmblemVer = status->get_emblem_id(bl); p.honor = (sd) ? sd->status.manner : 0; p.virtue = (sc) ? sc->opt3 : 0; - p.isPKModeON = (sd) ? sd->status.karma : 0; + p.isPKModeON = (sd && sd->status.karma) ? 1 : 0; p.sex = vd->sex; WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit->getdir(bl)); p.xSize = p.ySize = (sd) ? 5 : 0; p.state = vd->dead_sit; p.clevel = clif_setlevel(bl); #if PACKETVER >= 20080102 - p.font = (sd) ? sd->user_font : 0; + p.font = (sd) ? sd->status.font : 0; #endif #if PACKETVER >= 20140000 //actual 20120221 if( bl->type == BL_MOB ) { @@ -1034,7 +1044,7 @@ void clif_spawn_unit2(struct block_list* bl, enum send_target target) { p.headpalette = vd->hair_color; p.bodypalette = vd->cloth_color; p.headDir = (sd)? sd->head_dir : 0; - p.isPKModeON = (sd) ? sd->status.karma : 0; + p.isPKModeON = (sd && sd->status.karma) ? 1 : 0; p.sex = vd->sex; WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit->getdir(bl)); p.xSize = p.ySize = (sd) ? 5 : 0; @@ -1094,13 +1104,13 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) { p.GEmblemVer = status->get_emblem_id(bl); p.honor = (sd) ? sd->status.manner : 0; p.virtue = (sc) ? sc->opt3 : 0; - p.isPKModeON = (sd) ? sd->status.karma : 0; + p.isPKModeON = (sd && sd->status.karma) ? 1 : 0; p.sex = vd->sex; WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit->getdir(bl)); p.xSize = p.ySize = (sd) ? 5 : 0; p.clevel = clif_setlevel(bl); #if PACKETVER >= 20080102 - p.font = (sd) ? sd->user_font : 0; + p.font = (sd) ? sd->status.font : 0; #endif #if PACKETVER >= 20140000 //actual 20120221 if( bl->type == BL_MOB ) { @@ -1156,7 +1166,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, p.head = vd->hair_style; p.weapon = vd->weapon; p.accessory = vd->head_bottom; - p.moveStartTime = timer->gettick(); + p.moveStartTime = (unsigned int)timer->gettick(); #if PACKETVER < 7 p.shield = vd->shield; #endif @@ -1172,13 +1182,13 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, p.GEmblemVer = status->get_emblem_id(bl); p.honor = (sd) ? sd->status.manner : 0; p.virtue = (sc) ? sc->opt3 : 0; - p.isPKModeON = (sd) ? sd->status.karma : 0; + p.isPKModeON = (sd && sd->status.karma) ? 1 : 0; p.sex = vd->sex; WBUFPOS2(&p.MoveData[0],0,bl->x,bl->y,ud->to_x,ud->to_y,8,8); p.xSize = p.ySize = (sd) ? 5 : 0; p.clevel = clif_setlevel(bl); #if PACKETVER >= 20080102 - p.font = (sd) ? sd->user_font : 0; + p.font = (sd) ? sd->status.font : 0; #endif #if PACKETVER >= 20140000 //actual 20120221 if( bl->type == BL_MOB ) { @@ -1526,13 +1536,17 @@ void clif_walkok(struct map_session_data *sd) WFIFOHEAD(fd, packet_len(0x87)); WFIFOW(fd,0)=0x87; - WFIFOL(fd,2)=timer->gettick(); + WFIFOL(fd,2)=(unsigned int)timer->gettick(); WFIFOPOS2(fd,6,sd->bl.x,sd->bl.y,sd->ud.to_x,sd->ud.to_y,8,8); WFIFOSET(fd,packet_len(0x87)); } void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *ud) { + struct status_change *sc = NULL; + + if( (sc = status->get_sc(bl)) && sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE|OPTION_CHASEWALK) ) + clif->ally_only = true; clif->set_unit_walking(bl,NULL,ud,AREA_WOS); @@ -1564,6 +1578,8 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u clif->send_petdata(NULL, (TBL_PET*)bl, 3, vd->head_bottom); break; } + + clif->ally_only = false; } @@ -1573,9 +1589,9 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u void clif_move(struct unit_data *ud) { unsigned char buf[16]; - struct view_data* vd; - struct block_list* bl = ud->bl; - + struct view_data *vd; + struct block_list *bl = ud->bl; + struct status_change *sc = NULL; vd = status->get_viewdata(bl); if (!vd || vd->class_ == INVISIBLE_CLASS) return; //This performance check is needed to keep GM-hidden objects from being notified to bots. @@ -1593,23 +1609,28 @@ void clif_move(struct unit_data *ud) clif->move2(bl, vd, ud); return; } + + if( (sc = status->get_sc(bl)) && sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE|OPTION_CHASEWALK) ) + clif->ally_only = true; WBUFW(buf,0)=0x86; WBUFL(buf,2)=bl->id; WBUFPOS2(buf,6,bl->x,bl->y,ud->to_x,ud->to_y,8,8); - WBUFL(buf,12)=timer->gettick(); + WBUFL(buf,12)=(unsigned int)timer->gettick(); clif->send(buf, packet_len(0x86), bl, AREA_WOS); if (disguised(bl)) { WBUFL(buf,2)=-bl->id; clif->send(buf, packet_len(0x86), bl, SELF); } + + clif->ally_only = false; } /*========================================== * Delays the map->quit of a player after they are disconnected. [Skotlex] *------------------------------------------*/ -int clif_delayquit(int tid, unsigned int tick, int id, intptr_t data) { +int clif_delayquit(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd = NULL; //Remove player from map server @@ -1680,11 +1701,11 @@ void clif_blown(struct block_list *bl) /// isn't walkable, the char doesn't move at all. If the char is /// sitting it will stand up (ZC_STOPMOVE). /// 0088 <id>.L <x>.W <y>.W -void clif_fixpos(struct block_list *bl) -{ +void clif_fixpos(struct block_list *bl) { unsigned char buf[10]; + nullpo_retv(bl); - + WBUFW(buf,0) = 0x88; WBUFL(buf,2) = bl->id; WBUFW(buf,6) = bl->x; @@ -2198,8 +2219,8 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { else p.nameid = sd->status.inventory[n].nameid; - p.IsIdentified = sd->status.inventory[n].identify; - p.IsDamaged = sd->status.inventory[n].attribute; + p.IsIdentified = sd->status.inventory[n].identify ? 1 : 0; + p.IsDamaged = sd->status.inventory[n].attribute ? 1 : 0; p.refiningLevel =sd->status.inventory[n].refine; clif->addcards2(&p.slot.card[0], &sd->status.inventory[n]); p.location = pc->equippoint(sd,n); @@ -2290,311 +2311,229 @@ void clif_item_sub(unsigned char *buf, int n, struct item *i, struct item_data * } } -//Unified inventory function which sends all of the inventory (requires two packets, one for equipable items and one for stackable ones. [Skotlex] -void clif_inventorylist(struct map_session_data *sd) { - int i,n,ne,arrow=-1; - unsigned char *buf; - unsigned char *bufe; +void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct item_data *id, int eqp_pos) { -#if PACKETVER < 5 - const int s = 10; //Entry size. -#elif PACKETVER < 20080102 - const int s = 18; -#else - const int s = 22; -#endif -#if PACKETVER < 20071002 - const int se = 20; -#elif PACKETVER < 20100629 - const int se = 26; -#else - const int se = 28; -#endif + p->index = idx; + + if (id->view_id > 0) + p->ITID = id->view_id; + else + p->ITID = i->nameid; - buf = (unsigned char*)aMalloc(MAX_INVENTORY * s + 4); - bufe = (unsigned char*)aMalloc(MAX_INVENTORY * se + 4); + p->type = itemtype(id->type); - for( i = 0, n = 0, ne = 0; i < MAX_INVENTORY; i++ ) - { - if( sd->status.inventory[i].nameid <=0 || sd->inventory_data[i] == NULL ) - continue; +#if PACKETVER < 20120925 + p->IsIdentified = i->identify ? 1 : 0; +#endif + + p->location = eqp_pos; + p->WearState = i->equip; + +#if PACKETVER < 20120925 + p->IsDamaged = i->attribute ? 1 : 0; +#endif + p->RefiningLevel = i->refine; + + clif->addcards2(&p->slot.card[0], i); - if( !itemdb->isstackable2(sd->inventory_data[i]) ) - { //Non-stackable (Equippable) - WBUFW(bufe,ne*se+4)=i+2; - clif->item_sub(bufe, ne*se+6, &sd->status.inventory[i], sd->inventory_data[i], pc->equippoint(sd,i)); - clif->addcards(WBUFP(bufe, ne*se+16), &sd->status.inventory[i]); #if PACKETVER >= 20071002 - WBUFL(bufe,ne*se+24)=sd->status.inventory[i].expire_time; - WBUFW(bufe,ne*se+28)=0; //Unknown + p->HireExpireDate = i->expire_time; #endif + +#if PACKETVER >= 20080102 + p->bindOnEquipType = 0; +#endif + #if PACKETVER >= 20100629 - if (sd->inventory_data[i]->equip&EQP_VISIBLE) - WBUFW(bufe,ne*se+30)= sd->inventory_data[i]->look; - else - WBUFW(bufe,ne*se+30)=0; + p->wItemSpriteNumber = id->equip&EQP_VISIBLE ? id->look : 0; #endif - ne++; - } - else - { //Stackable. - WBUFW(buf,n*s+4)=i+2; - clif->item_sub(buf, n*s+6, &sd->status.inventory[i], sd->inventory_data[i], -2); - if( sd->inventory_data[i]->equip == EQP_AMMO && sd->status.inventory[i].equip ) - arrow=i; + +#if PACKETVER >= 20120925 + p->Flag.IsIdentified = i->identify ? 1 : 0; + p->Flag.IsDamaged = i->attribute ? 1 : 0; + p->Flag.PlaceETCTab = i->favorite ? 1 : 0; + p->Flag.SpareBits = 0; +#endif +} +void clif_item_normal(short idx, struct NORMALITEM_INFO *p, struct item *i, struct item_data *id) { + p->index = idx; + + if (id->view_id > 0) + p->ITID = id->view_id; + else + p->ITID = i->nameid; + + p->type = itemtype(id->type); + +#if PACKETVER < 20120925 + p->IsIdentified = i->identify ? 1 : 0; +#endif + + p->count = i->amount; + p->WearState = id->equip; + #if PACKETVER >= 5 - clif->addcards(WBUFP(buf, n*s+14), &sd->status.inventory[i]); + clif->addcards2(&p->slot.card[0], i); #endif + #if PACKETVER >= 20080102 - WBUFL(buf,n*s+22)=sd->status.inventory[i].expire_time; + p->HireExpireDate = i->expire_time; #endif - n++; - } - } - if( n ) { -#if PACKETVER < 5 - WBUFW(buf,0)=0xa3; -#elif PACKETVER < 20080102 - WBUFW(buf,0)=0x1ee; -#else - WBUFW(buf,0)=0x2e8; + +#if PACKETVER >= 20120925 + p->Flag.IsIdentified = i->identify ? 1 : 0; + p->Flag.PlaceETCTab = i->favorite ? 1 : 0; + p->Flag.SpareBits = 0; #endif - WBUFW(buf,2)=4+n*s; - clif->send(buf, WBUFW(buf,2), &sd->bl, SELF); +} +void clif_inventorylist(struct map_session_data *sd) { + int i, normal = 0, equip = 0; + + for( i = 0; i < MAX_INVENTORY; i++ ) { + + if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL ) + continue; + if( !itemdb->isstackable2(sd->inventory_data[i]) ) //Non-stackable (Equippable) + clif_item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.inventory[i],sd->inventory_data[i],pc->equippoint(sd,i)); + else //Stackable (Normal) + clif_item_normal(i+2,&itemlist_normal.list[normal++],&sd->status.inventory[i],sd->inventory_data[i]); + } + + if( normal ) { + itemlist_normal.PacketType = inventorylistnormalType; + itemlist_normal.PacketLength = 4 + (sizeof(struct NORMALITEM_INFO) * normal); + + clif->send(&itemlist_normal, itemlist_normal.PacketLength, &sd->bl, SELF); } - if( arrow >= 0 ) - clif->arrowequip(sd,arrow); + + if( sd->equip_index[EQI_AMMO] >= 0 ) + clif->arrowequip(sd,sd->equip_index[EQI_AMMO]); + + if( equip ) { + itemlist_equip.PacketType = inventorylistequipType; + itemlist_equip.PacketLength = 4 + (sizeof(struct EQUIPITEM_INFO) * equip); - if( ne ) { -#if PACKETVER < 20071002 - WBUFW(bufe,0)=0xa4; -#else - WBUFW(bufe,0)=0x2d0; -#endif - WBUFW(bufe,2)=4+ne*se; - clif->send(bufe, WBUFW(bufe,2), &sd->bl, SELF); + clif->send(&itemlist_equip, itemlist_equip.PacketLength, &sd->bl, SELF); } -#if PACKETVER >= 20111122 +/* on 20120925 onwards this is a field on clif_item_equip/normal */ +#if PACKETVER >= 20111122 && PACKETVER < 20120925 for( i = 0; i < MAX_INVENTORY; i++ ) { if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL ) continue; - + if ( sd->status.inventory[i].favorite ) clif->favorite_item(sd, i); } #endif - - if( buf ) aFree(buf); - if( bufe ) aFree(bufe); } //Required when items break/get-repaired. Only sends equippable item list. -void clif_equiplist(struct map_session_data *sd) -{ - int i,n,fd = sd->fd; - unsigned char *buf; -#if PACKETVER < 20071002 - const int cmd = 20; -#elif PACKETVER < 20100629 - const int cmd = 26; -#else - const int cmd = 28; -#endif - - WFIFOHEAD(fd, MAX_INVENTORY * cmd + 4); - buf = WFIFOP(fd,0); - - for(i=0,n=0;i<MAX_INVENTORY;i++){ - if (sd->status.inventory[i].nameid <=0 || sd->inventory_data[i] == NULL) +void clif_equiplist(struct map_session_data *sd) { + int i, equip = 0; + + for( i = 0; i < MAX_INVENTORY; i++ ) { + + if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL ) continue; - - if(itemdb->isstackable2(sd->inventory_data[i])) + if( !itemdb->isstackable2(sd->inventory_data[i]) ) //Non-stackable (Equippable) + clif_item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.inventory[i],sd->inventory_data[i],pc->equippoint(sd,i)); + } + + if( equip ) { + itemlist_equip.PacketType = inventorylistequipType; + itemlist_equip.PacketLength = 4 + (sizeof(struct EQUIPITEM_INFO) * equip); + + clif->send(&itemlist_equip, itemlist_equip.PacketLength, &sd->bl, SELF); + } + + /* on 20120925 onwards this is a field on clif_item_equip */ +#if PACKETVER >= 20111122 && PACKETVER < 20120925 + for( i = 0; i < MAX_INVENTORY; i++ ) { + if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL ) continue; - //Equippable - WBUFW(buf,n*cmd+4)=i+2; - clif->item_sub(buf, n*cmd+6, &sd->status.inventory[i], sd->inventory_data[i], pc->equippoint(sd,i)); - clif->addcards(WBUFP(buf, n*cmd+16), &sd->status.inventory[i]); -#if PACKETVER >= 20071002 - WBUFL(buf,n*cmd+24)=sd->status.inventory[i].expire_time; - WBUFW(buf,n*cmd+28)=0; //Unknown -#endif -#if PACKETVER >= 20100629 - if (sd->inventory_data[i]->equip&EQP_VISIBLE) - WBUFW(buf,n*cmd+30)= sd->inventory_data[i]->look; - else - WBUFW(buf,n*cmd+30)=0; -#endif - n++; + + if ( sd->status.inventory[i].favorite ) + clif->favorite_item(sd, i); } - if (n) { -#if PACKETVER < 20071002 - WBUFW(buf,0)=0xa4; -#else - WBUFW(buf,0)=0x2d0; #endif - WBUFW(buf,2)=4+n*cmd; - WFIFOSET(fd,WFIFOW(fd,2)); - } } -void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length) -{ +void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length) { + int i = 0; struct item_data *id; - int i,n,ne; - unsigned char *buf; - unsigned char *bufe; -#if PACKETVER < 5 - const int s = 10; //Entry size. -#elif PACKETVER < 20080102 - const int s = 18; -#else - const int s = 22; -#endif -#if PACKETVER < 20071002 - const int cmd = 20; -#elif PACKETVER < 20100629 - const int cmd = 26; -#else - const int cmd = 28; -#endif - - buf = (unsigned char*)aMalloc(items_length * s + 4); - bufe = (unsigned char*)aMalloc(items_length * cmd + 4); + + do { + int normal = 0, equip = 0, k = 0; - for( i = 0, n = 0, ne = 0; i < items_length; i++ ) - { - if( items[i].nameid <= 0 ) - continue; - id = itemdb->search(items[i].nameid); - if( !itemdb->isstackable2(id) ) - { //Equippable - WBUFW(bufe,ne*cmd+4)=i+1; - clif->item_sub(bufe, ne*cmd+6, &items[i], id, id->equip); - clif->addcards(WBUFP(bufe, ne*cmd+16), &items[i]); -#if PACKETVER >= 20071002 - WBUFL(bufe,ne*cmd+24)=items[i].expire_time; - WBUFW(bufe,ne*cmd+28)=0; //Unknown -#endif - ne++; + for( ; i < items_length && k < 500; i++, k++ ) { + + if( items[i].nameid <= 0 ) + continue; + + id = itemdb->search(items[i].nameid); + + if( !itemdb->isstackable2(id) ) //Non-stackable (Equippable) + clif_item_equip(i+1,&storelist_equip.list[equip++],&items[i],id,id->equip); + else //Stackable (Normal) + clif_item_normal(i+1,&storelist_normal.list[normal++],&items[i],id); } - else - { //Stackable - WBUFW(buf,n*s+4)=i+1; - clif->item_sub(buf, n*s+6, &items[i], id,-1); -#if PACKETVER >= 5 - clif->addcards(WBUFP(buf,n*s+14), &items[i]); -#endif -#if PACKETVER >= 20080102 - WBUFL(buf,n*s+22)=items[i].expire_time; + + if( normal ) { + storelist_normal.PacketType = storagelistnormalType; + storelist_normal.PacketLength = ( sizeof( storelist_normal ) - sizeof( storelist_normal.list ) ) + (sizeof(struct NORMALITEM_INFO) * normal); + +#if PACKETVER >= 20120925 + safestrncpy(storelist_normal.name, "Storage", NAME_LENGTH); #endif - n++; + + clif->send(&storelist_normal, storelist_normal.PacketLength, &sd->bl, SELF); } - } - if( n ) - { -#if PACKETVER < 5 - WBUFW(buf,0)=0xa5; -#elif PACKETVER < 20080102 - WBUFW(buf,0)=0x1f0; -#else - WBUFW(buf,0)=0x2ea; -#endif - WBUFW(buf,2)=4+n*s; - clif->send(buf, WBUFW(buf,2), &sd->bl, SELF); - } - if( ne ) - { -#if PACKETVER < 20071002 - WBUFW(bufe,0)=0xa6; -#else - WBUFW(bufe,0)=0x2d1; + + if( equip ) { + storelist_equip.PacketType = storagelistequipType; + storelist_equip.PacketLength = ( sizeof( storelist_equip ) - sizeof( storelist_equip.list ) ) + (sizeof(struct EQUIPITEM_INFO) * equip); + +#if PACKETVER >= 20120925 + safestrncpy(storelist_equip.name, "Storage", NAME_LENGTH); #endif - WBUFW(bufe,2)=4+ne*cmd; - clif->send(bufe, WBUFW(bufe,2), &sd->bl, SELF); - } - if( buf ) aFree(buf); - if( bufe ) aFree(bufe); + clif->send(&storelist_equip, storelist_equip.PacketLength, &sd->bl, SELF); + } + + } while ( i < items_length ); + } -void clif_cartlist(struct map_session_data *sd) -{ +void clif_cartlist(struct map_session_data *sd) { + int i, normal = 0, equip = 0; struct item_data *id; - int i,n,ne; - unsigned char *buf; - unsigned char *bufe; -#if PACKETVER < 5 - const int s = 10; //Entry size. -#elif PACKETVER < 20080102 - const int s = 18; -#else - const int s = 22; -#endif -#if PACKETVER < 20071002 - const int cmd = 20; -#elif PACKETVER < 20100629 - const int cmd = 26; -#else - const int cmd = 28; -#endif - - buf = (unsigned char*)aMalloc(MAX_CART * s + 4); - bufe = (unsigned char*)aMalloc(MAX_CART * cmd + 4); - - for( i = 0, n = 0, ne = 0; i < MAX_CART; i++ ) - { + + for( i = 0; i < MAX_CART; i++ ) { + if( sd->status.cart[i].nameid <= 0 ) continue; + id = itemdb->search(sd->status.cart[i].nameid); - if( !itemdb->isstackable2(id) ) - { //Equippable - WBUFW(bufe,ne*cmd+4)=i+2; - clif->item_sub(bufe, ne*cmd+6, &sd->status.cart[i], id, id->equip); - clif->addcards(WBUFP(bufe, ne*cmd+16), &sd->status.cart[i]); -#if PACKETVER >= 20071002 - WBUFL(bufe,ne*cmd+24)=sd->status.cart[i].expire_time; - WBUFW(bufe,ne*cmd+28)=0; //Unknown -#endif - ne++; - } - else - { //Stackable - WBUFW(buf,n*s+4)=i+2; - clif->item_sub(buf, n*s+6, &sd->status.cart[i], id,-1); -#if PACKETVER >= 5 - clif->addcards(WBUFP(buf,n*s+14), &sd->status.cart[i]); -#endif -#if PACKETVER >= 20080102 - WBUFL(buf,n*s+22)=sd->status.cart[i].expire_time; -#endif - n++; - } + + if( !itemdb->isstackable2(id) ) //Non-stackable (Equippable) + clif_item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.cart[i],id,id->equip); + else //Stackable (Normal) + clif_item_normal(i+2,&itemlist_normal.list[normal++],&sd->status.cart[i],id); } - if( n ) - { -#if PACKETVER < 5 - WBUFW(buf,0)=0x123; -#elif PACKETVER < 20080102 - WBUFW(buf,0)=0x1ef; -#else - WBUFW(buf,0)=0x2e9; -#endif - WBUFW(buf,2)=4+n*s; - clif->send(buf, WBUFW(buf,2), &sd->bl, SELF); + + if( normal ) { + itemlist_normal.PacketType = cartlistnormalType; + itemlist_normal.PacketLength = 4 + (sizeof(struct NORMALITEM_INFO) * normal); + + clif->send(&itemlist_normal, itemlist_normal.PacketLength, &sd->bl, SELF); } - if( ne ) - { -#if PACKETVER < 20071002 - WBUFW(bufe,0)=0x122; -#else - WBUFW(bufe,0)=0x2d2; -#endif - WBUFW(bufe,2)=4+ne*cmd; - clif->send(bufe, WBUFW(bufe,2), &sd->bl, SELF); + + if( equip ) { + itemlist_equip.PacketType = cartlistequipType; + itemlist_equip.PacketLength = 4 + (sizeof(struct EQUIPITEM_INFO) * equip); + + clif->send(&itemlist_equip, itemlist_equip.PacketLength, &sd->bl, SELF); } - - if( buf ) aFree(buf); - if( bufe ) aFree(bufe); } @@ -3001,7 +2940,8 @@ void clif_updatestatus(struct map_session_data *sd,int type) case SP_HP: WFIFOL(fd,4)=sd->battle_status.hp; // TODO: Won't these overwrite the current packet? - clif->hpmeter(sd); + if( map->list[sd->bl.m].hpmeter_visible ) + clif->hpmeter(sd); if( !battle_config.party_hp_mode && sd->status.party_id ) clif->party_hp(sd); if( sd->bg_id ) @@ -3528,52 +3468,39 @@ void clif_statusupack(struct map_session_data *sd,int type,int ok,int val) /// Notifies the client about the result of a request to equip an item (ZC_REQ_WEAR_EQUIP_ACK). /// 00aa <index>.W <equip location>.W <result>.B /// 00aa <index>.W <equip location>.W <view id>.W <result>.B (PACKETVER >= 20100629) -/// result: -/// 0 = failure -/// 1 = success -/// 2 = failure due to low level -void clif_equipitemack(struct map_session_data *sd,int n,int pos,int ok) -{ - int fd; +void clif_equipitemack(struct map_session_data *sd,int n,int pos,enum e_EQUIP_ITEM_ACK result) { + struct packet_equipitem_ack p; nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xaa)); - WFIFOW(fd,0)=0xaa; - WFIFOW(fd,2)=n+2; - WFIFOW(fd,4)=pos; -#if PACKETVER < 20100629 - WFIFOB(fd,6)=ok; -#else - if (ok && sd->inventory_data[n]->equip&EQP_VISIBLE) - WFIFOW(fd,6)=sd->inventory_data[n]->look; + p.PacketType = equipitemackType; + p.index = n+2; + p.wearLocation = pos; +#if PACKETVER >= 20100629 + if (result == EIA_SUCCESS && sd->inventory_data[n]->equip&EQP_VISIBLE) + p.wItemSpriteNumber = sd->inventory_data[n]->look; else - WFIFOW(fd,6)=0; - WFIFOB(fd,8)=ok; + p.wItemSpriteNumber = 0; #endif - WFIFOSET(fd,packet_len(0xaa)); + p.result = (unsigned char)result; + + clif->send(&p, sizeof(p), &sd->bl, SELF); } /// Notifies the client about the result of a request to take off an item (ZC_REQ_TAKEOFF_EQUIP_ACK). /// 00ac <index>.W <equip location>.W <result>.B -/// result: -/// 0 = failure -/// 1 = success -void clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok) -{ - int fd; +void clif_unequipitemack(struct map_session_data *sd,int n,int pos,enum e_UNEQUIP_ITEM_ACK result) { + struct packet_unequipitem_ack p; nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xac)); - WFIFOW(fd,0)=0xac; - WFIFOW(fd,2)=n+2; - WFIFOW(fd,4)=pos; - WFIFOB(fd,6)=ok; - WFIFOSET(fd,packet_len(0xac)); + p.PacketType = unequipitemackType; + p.index = n+2; + p.wearLocation = pos; + p.result = (unsigned char)result; + + clif->send(&p, sizeof(p), &sd->bl, SELF); } @@ -4430,8 +4357,7 @@ int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, i /// 10 = critical hit /// 11 = lucky dodge /// 12 = (touch skill?) -int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int64 in_damage, int div, int type, int64 in_damage2) -{ +int clif_damage(struct block_list* src, struct block_list* dst, int64 tick, int sdelay, int ddelay, int64 in_damage, int div, int type, int64 in_damage2) { unsigned char buf[33]; struct status_change *sc; int damage,damage2; @@ -4459,7 +4385,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic WBUFW(buf,0)=cmd; WBUFL(buf,2)=src->id; WBUFL(buf,6)=dst->id; - WBUFL(buf,10)=tick; + WBUFL(buf,10)=(uint32)tick; WBUFL(buf,14)=sdelay; WBUFL(buf,18)=ddelay; #if PACKETVER < 20071113 @@ -4516,7 +4442,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic *------------------------------------------*/ void clif_takeitem(struct block_list* src, struct block_list* dst) { - //clif_damage(src,dst,0,0,0,0,0,1,0); + //clif->damage(src,dst,0,0,0,0,0,1,0); unsigned char buf[32]; nullpo_retv(src); @@ -4821,7 +4747,7 @@ int clif_insight(struct block_list *bl,va_list ap) tsd = BL_CAST(BL_PC, tbl); if (tsd && tsd->fd) { //Tell tsd that bl entered into his view - switch(bl->type){ + switch(bl->type) { case BL_ITEM: clif->getareachar_item(tsd,(struct flooritem_data*)bl); break; @@ -5097,7 +5023,7 @@ void clif_skill_fail(struct map_session_data *sd,uint16 skill_id,enum useskill_f /// Skill cooldown display icon (ZC_SKILL_POSTDELAY). /// 043d <skill ID>.W <tick>.L -void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned int tick) +void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned int duration) { #if PACKETVER>=20081112 int fd; @@ -5108,7 +5034,7 @@ void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned WFIFOHEAD(fd,packet_len(0x43d)); WFIFOW(fd,0) = 0x43d; WFIFOW(fd,2) = skill_id; - WFIFOL(fd,4) = tick; + WFIFOL(fd,4) = duration; WFIFOSET(fd,packet_len(0x43d)); #endif } @@ -5117,7 +5043,7 @@ void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned /// Skill attack effect and damage. /// 0114 <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <damage>.W <level>.W <div>.W <type>.B (ZC_NOTIFY_SKILL) /// 01de <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <damage>.L <level>.W <div>.W <type>.B (ZC_NOTIFY_SKILL2) -int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int64 in_damage,int div,uint16 skill_id,uint16 skill_lv,int type) { +int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int64 in_damage, int div, uint16 skill_id, uint16 skill_lv, int type) { unsigned char buf[64]; struct status_change *sc; int damage; @@ -5138,7 +5064,7 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int WBUFW(buf,2)=skill_id; WBUFL(buf,4)=src->id; WBUFL(buf,8)=dst->id; - WBUFL(buf,12)=tick; + WBUFL(buf,12)=(uint32)tick; WBUFL(buf,16)=sdelay; WBUFL(buf,20)=ddelay; if (battle_config.hide_woe_damage && map_flag_gvg2(src->m)) { @@ -5169,7 +5095,7 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int WBUFW(buf,2)=skill_id; WBUFL(buf,4)=src->id; WBUFL(buf,8)=dst->id; - WBUFL(buf,12)=tick; + WBUFL(buf,12)=(uint32)tick; WBUFL(buf,16)=sdelay; WBUFL(buf,20)=ddelay; if (battle_config.hide_woe_damage && map_flag_gvg2(src->m)) { @@ -5205,7 +5131,7 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int /// Ground skill attack effect and damage (ZC_NOTIFY_SKILL_POSITION). /// 0115 <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <x>.W <y>.W <damage>.W <level>.W <div>.W <type>.B #if 0 -int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,uint16 skill_id,uint16 skill_lv,int type) { +int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int damage, int div, uint16 skill_id, uint16 skill_lv, int type) { unsigned char buf[64]; struct status_change *sc; @@ -5225,7 +5151,7 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned in WBUFW(buf,2)=skill_id; WBUFL(buf,4)=src->id; WBUFL(buf,8)=dst->id; - WBUFL(buf,12)=tick; + WBUFL(buf,12)=(uint32)tick; WBUFL(buf,16)=sdelay; WBUFL(buf,20)=ddelay; WBUFW(buf,24)=dst->x; @@ -5295,8 +5221,7 @@ int clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 ski /// Non-damaging ground skill effect (ZC_NOTIFY_GROUNDSKILL). /// 0117 <skill id>.W <src id>.L <level>.W <x>.W <y>.W <tick>.L -void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,int y,int tick) -{ +void clif_skill_poseffect(struct block_list *src, uint16 skill_id, int val, int x, int y, int64 tick) { unsigned char buf[32]; nullpo_retv(src); @@ -5307,7 +5232,7 @@ void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,i WBUFW(buf,8)=val; WBUFW(buf,10)=x; WBUFW(buf,12)=y; - WBUFL(buf,14)=tick; + WBUFL(buf,14)=(uint32)tick; if(disguised(src)) { clif->send(buf,packet_len(0x117),src,AREA_WOS); WBUFL(buf,4)=-src->id; @@ -8951,69 +8876,41 @@ void clif_equpcheckbox(struct map_session_data* sd) /// 02d7 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE, PACKETVER >= 20100629) /// 0859 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE2, PACKETVER >= 20101124) /// 0859 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <robe>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE2, PACKETVER >= 20110111) -void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* tsd) -{ - uint8* buf; - int i, n, fd, offset = 0; -#if PACKETVER < 20100629 - const int s = 26; -#else - const int s = 28; -#endif +void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* tsd) { + int i, k, equip = 0; + nullpo_retv(sd); nullpo_retv(tsd); - fd = sd->fd; - - WFIFOHEAD(fd, MAX_INVENTORY * s + 43); - buf = WFIFOP(fd,0); + + for( i = 0; i < EQI_MAX; i++ ) { + if( (k = tsd->equip_index[i]) >= 0 ) { + + if (tsd->status.inventory[k].nameid <= 0 || tsd->inventory_data[k] == NULL) // Item doesn't exist + continue; + + clif_item_equip(k+2,&viewequip_list.list[equip++],&tsd->status.inventory[k],tsd->inventory_data[k],pc->equippoint(tsd,k)); -#if PACKETVER < 20101124 - WBUFW(buf, 0) = 0x2d7; -#else - WBUFW(buf, 0) = 0x859; -#endif - safestrncpy((char*)WBUFP(buf, 4), tsd->status.name, NAME_LENGTH); - WBUFW(buf,28) = tsd->status.class_; - WBUFW(buf,30) = tsd->vd.hair_style; - WBUFW(buf,32) = tsd->vd.head_bottom; - WBUFW(buf,34) = tsd->vd.head_mid; - WBUFW(buf,36) = tsd->vd.head_top; + } + } + + viewequip_list.PacketType = viewequipackType; + viewequip_list.PacketLength = ( sizeof( viewequip_list ) - sizeof( viewequip_list.list ) ) + ( sizeof(struct EQUIPITEM_INFO) * equip ); + + safestrncpy(viewequip_list.characterName, tsd->status.name, NAME_LENGTH); + + viewequip_list.job = tsd->status.class_; + viewequip_list.head = tsd->vd.hair_style; + viewequip_list.accessory = tsd->vd.head_bottom; + viewequip_list.accessory2 = tsd->vd.head_mid; + viewequip_list.accessory3 = tsd->vd.head_top; #if PACKETVER >= 20110111 - WBUFW(buf,38) = tsd->vd.robe; - offset+= 2; - buf = WBUFP(buf,2); + viewequip_list.robe = tsd->vd.robe; #endif - WBUFW(buf,38) = tsd->vd.hair_color; - WBUFW(buf,40) = tsd->vd.cloth_color; - WBUFB(buf,42) = tsd->vd.sex; - - for(i=0,n=0; i < MAX_INVENTORY; i++) - { - if (tsd->status.inventory[i].nameid <= 0 || tsd->inventory_data[i] == NULL) // Item doesn't exist - continue; - if (!itemdb->isequip2(tsd->inventory_data[i])) // Is not equippable - continue; - - // Inventory position - WBUFW(buf, n*s+43) = i + 2; - // Add refine, identify flag, element, etc. - clif->item_sub(WBUFP(buf,0), n*s+45, &tsd->status.inventory[i], tsd->inventory_data[i], pc->equippoint(tsd, i)); - // Add cards - clif->addcards(WBUFP(buf, n*s+55), &tsd->status.inventory[i]); - // Expiration date stuff, if all of those are set to 0 then the client doesn't show anything related (6 bytes) - WBUFL(buf, n*s+63) = tsd->status.inventory[i].expire_time; - WBUFW(buf, n*s+67) = 0; -#if PACKETVER >= 20100629 - if (tsd->inventory_data[i]->equip&EQP_VISIBLE) - WBUFW(buf, n*s+69) = tsd->inventory_data[i]->look; - else - WBUFW(buf, n*s+69) = 0; -#endif - n++; - } - - WFIFOW(fd, 2) = 43+offset+n*s; // Set length - WFIFOSET(fd, WFIFOW(fd, 2)); + viewequip_list.headpalette = tsd->vd.hair_color; + viewequip_list.bodypalette = tsd->vd.cloth_color; + viewequip_list.sex = tsd->vd.sex; + + clif->send(&viewequip_list, viewequip_list.PacketLength, &sd->bl, SELF); } @@ -9316,6 +9213,8 @@ void clif_hercules_chsys_mjoin(struct map_session_data *sd) { /// Notification from the client, that it has finished map loading and is about to display player's character (CZ_NOTIFY_ACTORINIT). /// 007d void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { + int i; + if(sd->bl.prev != NULL) return; @@ -9369,13 +9268,11 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { if( map->list[sd->bl.m].users++ == 0 && battle_config.dynamic_mobs ) map->spawnmobs(sd->bl.m); + if( !(sd->sc.option&OPTION_INVISIBLE) ) { // increment the number of pvp players on the map map->list[sd->bl.m].users_pvp++; } - if( map->list[sd->bl.m].instance_id >= 0 ) { - instance->list[map->list[sd->bl.m].instance_id].users++; - instance->check_idle(map->list[sd->bl.m].instance_id); - } + sd->state.debug_remove_map = 0; // temporary state to track double remove_map's [FlavioJS] // reset the callshop flag if the player changes map @@ -9429,7 +9326,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { clif->spawn(&sd->pd->bl); clif->send_petdata(sd,sd->pd,0,0); clif->send_petstatus(sd); -// skill->unit_move(&sd->pd->bl,gettick(),1); +// skill->unit_move(&sd->pd->bl,timer->gettick(),1); } } @@ -9565,6 +9462,16 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { clif->broadcast(&sd->bl, output, strlen(output) + 1, BC_BLUE, SELF); } + if( map->list[sd->bl.m].instance_id >= 0 ) { + instance->list[map->list[sd->bl.m].instance_id].users++; + instance->check_idle(map->list[sd->bl.m].instance_id); + } + + if( pc->has_permission(sd,PC_PERM_VIEW_HPMETER) ) { + map->list[sd->bl.m].hpmeter_visible++; + sd->state.hpmeter_visible = 1; + } + map->iwall_get(sd); // Updates Walls Info on this Map to Client status_calc_pc(sd, false);/* some conditions are map-dependent so we must recalculate */ sd->state.changemap = false; @@ -9624,21 +9531,35 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { skill->usave_trigger(sd); } -// Trigger skill effects if you appear standing on them + // Trigger skill effects if you appear standing on them if(!battle_config.pc_invincible_time) skill->unit_move(&sd->bl,timer->gettick(),1); + // NPC Quest / Event Icon Check [Kisuka] +#if PACKETVER >= 20090218 + for(i = 0; i < map->list[sd->bl.m].qi_count; i++) { + struct questinfo *qi = &map->list[sd->bl.m].qi_data[i]; + if( quest->check(sd, qi->quest_id, HAVEQUEST) == -1 ) {// Check if quest is not started + if( qi->hasJob ) { // Check if quest is job-specific, check is user is said job class. + if( sd->class_ == qi->job ) + clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); + } else { + clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); + } + } + } +#endif } /// Server's tick (ZC_NOTIFY_TIME). /// 007f <time>.L -void clif_notify_time(struct map_session_data* sd, unsigned long time) { +void clif_notify_time(struct map_session_data* sd, int64 time) { int fd = sd->fd; WFIFOHEAD(fd,packet_len(0x7f)); WFIFOW(fd,0) = 0x7f; - WFIFOL(fd,2) = time; + WFIFOL(fd,2) = (uint32)time; WFIFOSET(fd,packet_len(0x7f)); } @@ -9734,7 +9655,7 @@ void clif_parse_progressbar(int fd, struct map_session_data * sd) if( timer->gettick() < sd->progressbar.timeout && sd->st ) sd->st->state = END; - sd->state.workinprogress = sd->progressbar.npc_id = sd->progressbar.timeout = 0; + sd->progressbar.timeout = sd->state.workinprogress = sd->progressbar.npc_id = 0; npc->scriptcont(sd, npc_id, false); } @@ -9767,7 +9688,8 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) RFIFOPOS(fd, packet_db[RFIFOW(fd,0)].pos[0], &x, &y, NULL); //Set last idle time... [Skotlex] - sd->idletime = last_tick; + if( battle_config.idletime_criteria & BCIDLE_WALK ) + sd->idletime = last_tick; unit->walktoxy(&sd->bl, x, y, 4); } @@ -9846,7 +9768,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) { clif->charnameack(fd, bl); } -int clif_undisguise_timer(int tid, unsigned int tick, int id, intptr_t data) { +int clif_undisguise_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data * sd; if( (sd = map->id2sd(id)) ) { sd->fontcolor_tid = INVALID_TIMER; @@ -9917,6 +9839,9 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) } } + if( battle_config.idletime_criteria & BCIDLE_CHAT ) + sd->idletime = last_tick; + if( sd->gcbind ) { clif->chsys_send(sd->gcbind,sd,message); return; @@ -10077,6 +10002,9 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd) return; } sd->emotionlasttime = time(NULL); + + if( battle_config.idletime_criteria & BCIDLE_EMOTION ) + sd->idletime = last_tick; if(battle_config.client_reshuffle_dice && emoticon>=E_DICE1 && emoticon<=E_DICE6) {// re-roll dice emoticon = rnd()%6+E_DICE1; @@ -10108,8 +10036,7 @@ void clif_parse_HowManyConnections(int fd, struct map_session_data *sd) { } -void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, unsigned int tick) -{ +void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, int64 tick) { if (pc_isdead(sd)) { clif->clearunit_area(&sd->bl, CLR_DEAD); return; @@ -10151,7 +10078,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, } pc->delinvincibletimer(sd); - sd->idletime = last_tick; + if( battle_config.idletime_criteria & BCIDLE_ATTACK ) + sd->idletime = last_tick; unit->attack(&sd->bl, target_id, action_type != 0); break; case 0x02: // sitdown @@ -10175,6 +10103,9 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, )) //No sitting during these states either. break; + if( battle_config.idletime_criteria & BCIDLE_SIT ) + sd->idletime = last_tick; + pc_setsit(sd); skill->sit(sd,1); clif->sitting(&sd->bl); @@ -10185,6 +10116,10 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, clif->standing(&sd->bl); return; } + + if( battle_config.idletime_criteria & BCIDLE_SIT ) + sd->idletime = last_tick; + pc->setstand(sd); skill->sit(sd,0); clif->standing(&sd->bl); @@ -10376,6 +10311,9 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay; } + if( battle_config.idletime_criteria & BCIDLE_CHAT ) + sd->idletime = last_tick; + // Chat logging type 'W' / Whisper logs->chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message); @@ -10594,6 +10532,9 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd) if (!pc->dropitem(sd, item_index, item_amount)) break; + if( battle_config.idletime_criteria & BCIDLE_DROPITEM ) + sd->idletime = last_tick; + return; } @@ -10619,7 +10560,8 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) return; //Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex] - sd->idletime = last_tick; + if( battle_config.idletime_criteria & BCIDLE_USEITEM ) + sd->idletime = last_tick; n = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-2; if(n <0 || n >= MAX_INVENTORY) @@ -10631,18 +10573,19 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) /// Request to equip an item (CZ_REQ_WEAR_EQUIP). /// 00a9 <index>.W <position>.W -void clif_parse_EquipItem(int fd,struct map_session_data *sd) -{ - int index; +/// 0998 <index>.W <position>.L +void clif_parse_EquipItem(int fd,struct map_session_data *sd) { + struct packet_equip_item *p = P2PTR(fd); if(pc_isdead(sd)) { clif->clearunit_area(&sd->bl,CLR_DEAD); return; } - index = RFIFOW(fd,2)-2; - if (index < 0 || index >= MAX_INVENTORY) - return; //Out of bounds check. + p->index = p->index - 2; + if (p->index >= MAX_INVENTORY) + return; //Out of bounds check. + if( sd->npc_id ) { if ( !sd->npc_item_flag ) return; @@ -10651,24 +10594,27 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) else if ( pc_cant_act2(sd) || sd->state.prerefining ) return; - if(!sd->status.inventory[index].identify) { - clif->equipitemack(sd,index,0,0); // fail + if(!sd->status.inventory[p->index].identify) { + clif->equipitemack(sd,p->index,0,EIA_FAIL);// fail return; } - if(!sd->inventory_data[index]) + if(!sd->inventory_data[p->index]) return; - if(sd->inventory_data[index]->type == IT_PETARMOR){ - pet->equipitem(sd,index); + if(sd->inventory_data[p->index]->type == IT_PETARMOR){ + pet->equipitem(sd,p->index); return; } + if( battle_config.idletime_criteria & BCIDLE_USEITEM ) + sd->idletime = last_tick; + //Client doesn't send the position for ammo. - if(sd->inventory_data[index]->type == IT_AMMO) - pc->equipitem(sd,index,EQP_AMMO); + if(sd->inventory_data[p->index]->type == IT_AMMO) + pc->equipitem(sd,p->index,EQP_AMMO); else - pc->equipitem(sd,index,RFIFOW(fd,4)); + pc->equipitem(sd,p->index,p->wearLocation); } void clif_hercules_chsys_delete(struct hChSysCh *channel) { @@ -10781,6 +10727,9 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd) index = RFIFOW(fd,2)-2; + if( battle_config.idletime_criteria & BCIDLE_USEITEM ) + sd->idletime = last_tick; + pc->unequipitem(sd,index,1); } @@ -11210,8 +11159,7 @@ void clif_parse_SkillUp(int fd,struct map_session_data *sd) pc->skillup(sd,RFIFOW(fd,2)); } -void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id) -{ +void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id) { int lv; if( !hd ) @@ -11232,8 +11180,7 @@ void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_dat unit->skilluse_id(&hd->bl, target_id, skill_id, skill_lv); } -void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) -{ +void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) { int lv; if( !hd ) return; @@ -11253,8 +11200,7 @@ void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_da unit->skilluse_pos(&hd->bl, x, y, skill_id, skill_lv); } -void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id) -{ +void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id) { int lv; if( !md ) @@ -11275,8 +11221,7 @@ void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_ses unit->skilluse_id(&md->bl, target_id, skill_id, skill_lv); } -void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) -{ +void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) { int lv; if( !md ) return; @@ -11307,7 +11252,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) { uint16 skill_id, skill_lv; int tmp, target_id; - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); skill_lv = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0]); skill_id = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[1]); @@ -11330,7 +11275,8 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) } // Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] - sd->idletime = last_tick; + if( battle_config.idletime_criteria & BCIDLE_USESKILLTOID ) + sd->idletime = last_tick; if( sd->npc_id || sd->state.workinprogress&1 ){ #ifdef RENEWAL @@ -11407,7 +11353,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) *------------------------------------------*/ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 skill_lv, uint16 skill_id, short x, short y, int skillmoreinfo) { - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); if( !(skill->get_inf(skill_id)&INF_GROUND_SKILL) ) return; //Using a target skill on the ground? WRONG. @@ -11430,7 +11376,8 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski #endif //Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] - sd->idletime = last_tick; + if( battle_config.idletime_criteria & BCIDLE_USESKILLTOPOS ) + sd->idletime = last_tick; if( skill->not_ok(skill_id, sd) ) return; @@ -12185,6 +12132,9 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd) sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay; } + if( battle_config.idletime_criteria & BCIDLE_CHAT ) + sd->idletime = last_tick; + party->send_message(sd, text, textlen); } @@ -13140,6 +13090,9 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd) sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay; } + if( battle_config.idletime_criteria & BCIDLE_CHAT ) + sd->idletime = last_tick; + if( sd->bg_id ) bg->send_message(sd, text, textlen); else @@ -15529,7 +15482,7 @@ void clif_bossmapinfo(int fd, struct mob_data *md, short flag) unsigned int seconds; int hours, minutes; - seconds = DIFF_TICK(timer_data->tick, timer->gettick()) / 1000 + 60; + seconds = (unsigned int)(DIFF_TICK(timer_data->tick, timer->gettick()) / 1000 + 60); hours = seconds / (60 * 60); seconds = seconds - (60 * 60 * hours); minutes = seconds / 60; @@ -16077,6 +16030,9 @@ void clif_parse_BattleChat(int fd, struct map_session_data* sd) sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay; } + if( battle_config.idletime_criteria & BCIDLE_CHAT ) + sd->idletime = last_tick; + bg->send_message(sd, text, textlen); } @@ -16145,7 +16101,7 @@ void clif_font(struct map_session_data *sd) nullpo_retv(sd); WBUFW(buf,0) = 0x2ef; WBUFL(buf,2) = sd->bl.id; - WBUFW(buf,6) = sd->user_font; + WBUFW(buf,6) = sd->status.font; clif->send(buf, packet_len(0x2ef), &sd->bl, AREA); #endif } @@ -17247,9 +17203,9 @@ void clif_parse_MoveItem(int fd, struct map_session_data *sd) { /* [Ind/Hercules] */ void clif_cashshop_db(void) { config_t cashshop_conf; - config_setting_t *cashshop = NULL; + config_setting_t *cashshop = NULL, *cats = NULL; const char *config_filename = "db/cashshop_db.conf"; // FIXME hardcoded name - int i; + int i, item_count_t = 0; for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) { CREATE(clif->cs.data[i], struct hCSData *, 1); clif->cs.item_count[i] = 0; @@ -17262,67 +17218,53 @@ void clif_cashshop_db(void) { cashshop = config_lookup(&cashshop_conf, "cash_shop"); - if (cashshop != NULL) { - config_setting_t *cats = config_setting_get_elem(cashshop, 0); - config_setting_t *cat; - int k, item_count_t = 0; - + if( cashshop != NULL && (cats = config_setting_get_elem(cashshop, 0)) != NULL ) { for(i = 0; i < CASHSHOP_TAB_MAX; i++) { + config_setting_t *cat; char entry_name[10]; sprintf(entry_name,"cat_%d",i); if( (cat = config_setting_get_member(cats, entry_name)) != NULL ) { - int item_count = config_setting_length(cat); + int k, item_count = config_setting_length(cat); - if( item_count == 0 ) { - ShowWarning("cashshop_db: category '%s' is empty! adding dull apple!\n", entry_name); - RECREATE(clif->cs.data[i], struct hCSData *, ++clif->cs.item_count[i]); - CREATE(clif->cs.data[i][ clif->cs.item_count[i] - 1 ], struct hCSData , 1); - - clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->id = UNKNOWN_ITEM_ID; - clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->price = 999; - } else { - for(k = 0; k < item_count; k++) { - config_setting_t *entry = config_setting_get_elem(cat,k); - const char *name = config_setting_name(entry); - int price = config_setting_get_int(entry); - struct item_data * data = NULL; - - if( price < 1 ) { - ShowWarning("cashshop_db: unsupported price '%d' for entry named '%s' in category '%s'\n", price, name, entry_name); + for(k = 0; k < item_count; k++) { + config_setting_t *entry = config_setting_get_elem(cat,k); + const char *name = config_setting_name(entry); + int price = config_setting_get_int(entry); + struct item_data * data = NULL; + + if( price < 1 ) { + ShowWarning("cashshop_db: unsupported price '%d' for entry named '%s' in category '%s'\n", price, name, entry_name); + continue; + } + + if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) { + if( !( data = itemdb->exists(atoi(name+2))) ) { + ShowWarning("cashshop_db: unknown item id '%s' in category '%s'\n", name+2, entry_name); continue; } - - if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) { - if( !( data = itemdb->exists(atoi(name+2))) ) { - ShowWarning("cashshop_db: unknown item id '%s' in category '%s'\n", name+2, entry_name); - continue; - } - } else { - if( !( data = itemdb->search_name(name) ) ) { - ShowWarning("cashshop_db: unknown item name '%s' in category '%s'\n", name, entry_name); - continue; - } + } else { + if( !( data = itemdb->search_name(name) ) ) { + ShowWarning("cashshop_db: unknown item name '%s' in category '%s'\n", name, entry_name); + continue; } - - - RECREATE(clif->cs.data[i], struct hCSData *, ++clif->cs.item_count[i]); - CREATE(clif->cs.data[i][ clif->cs.item_count[i] - 1 ], struct hCSData , 1); - - clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->id = data->nameid; - clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->price = price; - item_count_t++; } + + + RECREATE(clif->cs.data[i], struct hCSData *, ++clif->cs.item_count[i]); + CREATE(clif->cs.data[i][ clif->cs.item_count[i] - 1 ], struct hCSData , 1); + + clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->id = data->nameid; + clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->price = price; + item_count_t++; } - } else { - ShowError("cashshop_db: category '%s' (%d) not found!!\n",entry_name,i); } } - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", item_count_t, config_filename); config_destroy(&cashshop_conf); } + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", item_count_t, config_filename); } /// Items that are in favorite tab of inventory (ZC_ITEM_FAVORITE). /// 0900 <index>.W <favorite>.B @@ -17362,6 +17304,12 @@ void __attribute__ ((unused)) clif_parse_dull(int fd,struct map_session_data *sd return; } void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) { + + if( map->list[sd->bl.m].flag.nocashshop ) { + clif->colormes(fd,COLOR_RED,msg_txt(1489)); //Cash Shop is disabled in this map + return; + } + WFIFOHEAD(fd, 10); WFIFOW(fd, 0) = 0x845; WFIFOL(fd, 2) = sd->cashPoints; //[Ryuuzaki] - switched positions to reflect proper values @@ -17377,6 +17325,9 @@ void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) { int i, j = 0; for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) { + if( clif->cs.item_count[i] == 0 ) + continue; // Skip empty tabs, the client only expects filled ones + WFIFOHEAD(fd, 8 + ( clif->cs.item_count[i] * 6 ) ); WFIFOW(fd, 0) = 0x8ca; WFIFOW(fd, 2) = 8 + ( clif->cs.item_count[i] * 6 ); @@ -17395,6 +17346,11 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) { unsigned short limit = RFIFOW(fd, 4), i, j; unsigned int kafra_pay = RFIFOL(fd, 6);// [Ryuuzaki] - These are free cash points (strangely #CASH = main cash curreny for us, confusing) + if( map->list[sd->bl.m].flag.nocashshop ) { + clif->colormes(fd,COLOR_RED,msg_txt(1489)); //Cash Shop is disabled in this map + return; + } + for(i = 0; i < limit; i++) { int qty = RFIFOL(fd, 14 + ( i * 10 )); int id = RFIFOL(fd, 10 + ( i * 10 )); @@ -17478,7 +17434,7 @@ void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) { short tab = RFIFOW(fd, 2); int j; - if( tab < 0 || tab > CASHSHOP_TAB_MAX ) + if( tab < 0 || tab > CASHSHOP_TAB_MAX || clif->cs.item_count[tab] == 0 ) return; WFIFOHEAD(fd, 10 + ( clif->cs.item_count[tab] * 6 ) ); @@ -17744,12 +17700,13 @@ void clif_skill_cooldown_list(int fd, struct skill_cd* cd) { for( i = 0; i < cd->cursor; i++ ) { if( cd->entry[i]->duration < 1 ) continue; - WFIFOW(fd, 4 + (count*offset)) = cd->entry[i]->skill_id; - WFIFOL(fd, 6 + (count*offset)) = cd->entry[i]->duration; + WFIFOW(fd, 4 + (count*offset)) = cd->entry[i]->skill_id; #if PACKETVER >= 20120604 + WFIFOL(fd, 6 + (count*offset)) = cd->entry[i]->total; WFIFOL(fd, 10 + (count*offset)) = cd->entry[i]->duration; +#else + WFIFOL(fd, 6 + (count*offset)) = cd->entry[i]->duration; #endif - count++; } @@ -18158,6 +18115,7 @@ void clif_defaults(void) { /* vars */ clif->bind_ip = INADDR_ANY; clif->map_port = 5121; + clif->ally_only = false; /* core */ clif->init = do_init_clif; clif->final = do_final_clif; diff --git a/src/map/clif.h b/src/map/clif.h index 6d0fc0fc1..cbe3fa857 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -426,6 +426,29 @@ enum e_BANKING_WITHDRAW_ACK { BWA_UNKNOWN_ERROR = 0x2, }; +/* because the client devs were replaced by monkeys. */ +enum e_EQUIP_ITEM_ACK { +#if PACKETVER >= 20120925 + EIA_SUCCESS = 0x0, + EIA_FAIL_LV = 0x1, + EIA_FAIL = 0x2, +#else + EIA_SUCCESS = 0x1, + EIA_FAIL_LV = 0x2, + EIA_FAIL = 0x0, +#endif +}; + +/* and again. because the client devs were replaced by monkeys. */ +enum e_UNEQUIP_ITEM_ACK { +#if PACKETVER >= 20120925 + UIA_SUCCESS = 0x0, + UIA_FAIL = 0x1, +#else + UIA_SUCCESS = 0x1, + UIA_FAIL = 0x0, +#endif +}; /** * Structures @@ -500,6 +523,8 @@ struct clif_interface { } cs; /* */ unsigned int cryptKey[3]; + /* */ + bool ally_only; /* core */ int (*init) (void); void (*final) (void); @@ -529,8 +554,8 @@ struct clif_interface { void (*use_card) (struct map_session_data *sd,int idx); void (*cart_additem) (struct map_session_data *sd,int n,int amount,int fail); void (*cart_delitem) (struct map_session_data *sd,int n,int amount); - void (*equipitemack) (struct map_session_data *sd,int n,int pos,int ok); - void (*unequipitemack) (struct map_session_data *sd,int n,int pos,int ok); + void (*equipitemack) (struct map_session_data *sd,int n,int pos,enum e_EQUIP_ITEM_ACK result); + void (*unequipitemack) (struct map_session_data *sd,int n,int pos,enum e_UNEQUIP_ITEM_ACK result); void (*useitemack) (struct map_session_data *sd,int index,int amount,bool ok); void (*addcards) (unsigned char* buf, struct item* item); void (*addcards2) (unsigned short *cards, struct item* item); @@ -542,7 +567,7 @@ struct clif_interface { /* unit-related */ void (*clearunit_single) (int id, clr_type type, int fd); void (*clearunit_area) (struct block_list* bl, clr_type type); - void (*clearunit_delayed) (struct block_list* bl, clr_type type, unsigned int tick); + void (*clearunit_delayed) (struct block_list* bl, clr_type type, int64 tick); void (*walkok) (struct map_session_data *sd); void (*move) (struct unit_data *ud); void (*move2) (struct block_list *bl, struct view_data *vd, struct unit_data *ud); @@ -556,7 +581,7 @@ struct clif_interface { void (*skill_setunit) (struct skill_unit *su); void (*skill_delunit) (struct skill_unit *su); void (*skillunit_update) (struct block_list* bl); - int (*clearunit_delayed_sub) (int tid, unsigned int tick, int id, intptr_t data); + int (*clearunit_delayed_sub) (int tid, int64 tick, int id, intptr_t data); void (*set_unit_idle) (struct block_list* bl, struct map_session_data *tsd,enum send_target target); void (*spawn_unit) (struct block_list* bl, enum send_target target); void (*spawn_unit2) (struct block_list* bl, enum send_target target); @@ -600,7 +625,7 @@ struct clif_interface { void (*scriptclear) (struct map_session_data *sd, int npcid); /* client-user-interface-related */ void (*viewpoint) (struct map_session_data *sd, int npc_id, int type, int x, int y, int id, int color); - int (*damage) (struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int64 damage, int div, int type, int64 damage2); + int (*damage) (struct block_list* src, struct block_list* dst, int64 tick, int sdelay, int ddelay, int64 damage, int div, int type, int64 damage2); void (*sitting) (struct block_list* bl); void (*standing) (struct block_list* bl); void (*arrow_create_list) (struct map_session_data *sd); @@ -616,7 +641,7 @@ struct clif_interface { int (*outsight) (struct block_list *bl,va_list ap); void (*skillcastcancel) (struct block_list* bl); void (*skill_fail) (struct map_session_data *sd,uint16 skill_id,enum useskill_fail_cause cause,int btype); - void (*skill_cooldown) (struct map_session_data *sd, uint16 skill_id, unsigned int tick); + void (*skill_cooldown) (struct map_session_data *sd, uint16 skill_id, unsigned int duration); void (*skill_memomessage) (struct map_session_data* sd, int type); void (*skill_mapinfomessage) (struct map_session_data *sd, int type); void (*skill_produce_mix_list) (struct map_session_data *sd, int skill_id, int trigger); @@ -682,7 +707,7 @@ struct clif_interface { void (*movetoattack) (struct map_session_data *sd,struct block_list *bl); void (*solved_charname) (int fd, int charid, const char* name); void (*charnameupdate) (struct map_session_data *ssd); - int (*delayquit) (int tid, unsigned int tick, int id, intptr_t data); + int (*delayquit) (int tid, int64 tick, int id, intptr_t data); void (*getareachar_pc) (struct map_session_data* sd,struct map_session_data* dstsd); void (*disconnect_ack) (struct map_session_data* sd, short result); void (*PVPInfo) (struct map_session_data* sd); @@ -700,9 +725,9 @@ struct clif_interface { void (*wedding_effect) (struct block_list *bl); void (*divorced) (struct map_session_data* sd, const char* name); void (*callpartner) (struct map_session_data *sd); - int (*skill_damage) (struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int64 damage,int div,uint16 skill_id,uint16 skill_lv,int type); + int (*skill_damage) (struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int64 damage, int div, uint16 skill_id, uint16 skill_lv, int type); int (*skill_nodamage) (struct block_list *src,struct block_list *dst,uint16 skill_id,int heal,int fail); - void (*skill_poseffect) (struct block_list *src,uint16 skill_id,int val,int x,int y,int tick); + void (*skill_poseffect) (struct block_list *src, uint16 skill_id, int val, int x, int y, int64 tick); void (*skill_estimation) (struct map_session_data *sd,struct block_list *dst); void (*skill_warppoint) (struct map_session_data* sd, uint16 skill_id, uint16 skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4); void (*skillcasting) (struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, int property, int casttime); @@ -960,11 +985,11 @@ struct clif_interface { void (*adopt_reply) (struct map_session_data *sd, int type); void (*adopt_request) (struct map_session_data *sd, struct map_session_data *src, int p_id); void (*readbook) (int fd, int book_id, int page); - void (*notify_time) (struct map_session_data* sd, unsigned long time); + void (*notify_time) (struct map_session_data* sd, int64 time); void (*user_count) (struct map_session_data* sd, int count); void (*noask_sub) (struct map_session_data *src, struct map_session_data *target, int type); void (*bc_ready) (void); - int (*undisguise_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*undisguise_timer) (int tid, int64 tick, int id, intptr_t data); /* Hercules Channel System */ void (*chsys_create) (struct hChSysCh *channel, char *name, char *pass, unsigned char color); void (*chsys_msg) (struct hChSysCh *channel, struct map_session_data *sd, char *msg); @@ -998,7 +1023,7 @@ struct clif_interface { void (*pEmotion) (int fd, struct map_session_data *sd); void (*pHowManyConnections) (int fd, struct map_session_data *sd); void (*pActionRequest) (int fd, struct map_session_data *sd); - void (*pActionRequest_sub) (struct map_session_data *sd, int action_type, int target_id, unsigned int tick); + void (*pActionRequest_sub) (struct map_session_data *sd, int action_type, int target_id, int64 tick); void (*pRestart) (int fd, struct map_session_data *sd); void (*pWisMessage) (int fd, struct map_session_data* sd); void (*pBroadcast) (int fd, struct map_session_data* sd); @@ -1032,12 +1057,12 @@ struct clif_interface { void (*pStatusUp) (int fd,struct map_session_data *sd); void (*pSkillUp) (int fd,struct map_session_data *sd); void (*pUseSkillToId) (int fd, struct map_session_data *sd); - void (*pUseSkillToId_homun) (struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id); - void (*pUseSkillToId_mercenary) (struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id); + void (*pUseSkillToId_homun) (struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id); + void (*pUseSkillToId_mercenary) (struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id); void (*pUseSkillToPos) (int fd, struct map_session_data *sd); void (*pUseSkillToPosSub) (int fd, struct map_session_data *sd, uint16 skill_lv, uint16 skill_id, short x, short y, int skillmoreinfo); - void (*pUseSkillToPos_homun) (struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo); - void (*pUseSkillToPos_mercenary) (struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo); + void (*pUseSkillToPos_homun) (struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo); + void (*pUseSkillToPos_mercenary) (struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo); void (*pUseSkillToPosMoreInfo) (int fd, struct map_session_data *sd); void (*pUseSkillMap) (int fd, struct map_session_data* sd); void (*pRequestMemo) (int fd,struct map_session_data *sd); diff --git a/src/map/elemental.c b/src/map/elemental.c index 3251ca992..f15b735b2 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -148,7 +148,7 @@ int elemental_get_lifetime(struct elemental_data *ed) { return 0; td = timer->get(ed->summon_timer); - return (td != NULL) ? DIFF_TICK(td->tick, timer->gettick()) : 0; + return (td != NULL) ? DIFF_TICK32(td->tick, timer->gettick()) : 0; } int elemental_save(struct elemental_data *ed) { @@ -169,7 +169,7 @@ int elemental_save(struct elemental_data *ed) { return 1; } -int elemental_summon_end_timer(int tid, unsigned int tick, int id, intptr_t data) { +int elemental_summon_end_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd; struct elemental_data *ed; @@ -388,7 +388,7 @@ int elemental_clean_effect(struct elemental_data *ed) { return 1; } -int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick) { +int elemental_action(struct elemental_data *ed, struct block_list *bl, int64 tick) { struct skill_condition req; uint16 skill_id, skill_lv; int i; @@ -636,7 +636,7 @@ int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap) { return 0; } -int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, unsigned int tick) { +int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, int64 tick) { struct block_list *target = NULL; int master_dist, view_range, mode; @@ -723,7 +723,7 @@ int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *s } if( battle->check_range(&ed->bl,target,view_range) && rnd()%100 < 2 ) { // 2% chance to cast attack skill. - if( elemental->action(ed,target,tick) ) + if( elemental->action(ed,target,tick) ) return 1; } @@ -746,14 +746,14 @@ int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *s } int elemental_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) { - unsigned int tick = va_arg(ap,unsigned int); + int64 tick = va_arg(ap,int64); if(sd->status.ele_id && sd->ed) elemental->ai_sub_timer(sd->ed,sd,tick); return 0; } -int elemental_ai_timer(int tid, unsigned int tick, int id, intptr_t data) { +int elemental_ai_timer(int tid, int64 tick, int id, intptr_t data) { map->foreachpc(elemental->ai_sub_foreachclient,tick); return 0; } diff --git a/src/map/elemental.h b/src/map/elemental.h index b42d5c0b7..3cd819d53 100644 --- a/src/map/elemental.h +++ b/src/map/elemental.h @@ -57,7 +57,7 @@ struct elemental_data { int summon_timer; int skill_timer; - unsigned last_thinktime, last_linktime, last_spdrain_time; + int64 last_thinktime, last_linktime, last_spdrain_time; short min_chase; int target_id, attacked_id; }; @@ -99,7 +99,7 @@ struct elemental_interface { int (*set_target) (struct map_session_data *sd, struct block_list *bl); int (*clean_single_effect) (struct elemental_data *ed, uint16 skill_id); int (*clean_effect) (struct elemental_data *ed); - int (*action) (struct elemental_data *ed, struct block_list *bl, unsigned int tick); + int (*action) (struct elemental_data *ed, struct block_list *bl, int64 tick); struct skill_condition (*skill_get_requirements) (uint16 skill_id, uint16 skill_lv); int (*read_skilldb) (void); @@ -108,11 +108,11 @@ struct elemental_interface { int (*search_index) (int class_); void (*summon_init) (struct elemental_data *ed); - int (*summon_end_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*summon_end_timer) (int tid, int64 tick, int id, intptr_t data); int (*ai_sub_timer_activesearch) (struct block_list *bl, va_list ap); - int (*ai_sub_timer) (struct elemental_data *ed, struct map_session_data *sd, unsigned int tick); + int (*ai_sub_timer) (struct elemental_data *ed, struct map_session_data *sd, int64 tick); int (*ai_sub_foreachclient) (struct map_session_data *sd, va_list ap); - int (*ai_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*ai_timer) (int tid, int64 tick, int id, intptr_t data); int (*read_db) (void); }; diff --git a/src/map/guild.c b/src/map/guild.c index 30f989f58..0ae45bede 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -279,8 +279,7 @@ int guild_payexp_timer_sub(DBKey key, DBData *data, va_list ap) { return 0; } -int guild_payexp_timer(int tid, unsigned int tick, int id, intptr_t data) -{ +int guild_payexp_timer(int tid, int64 tick, int id, intptr_t data) { guild->expcache_db->clear(guild->expcache_db,guild->payexp_timer_sub); return 0; } @@ -314,8 +313,7 @@ int guild_send_xy_timer_sub(DBKey key, DBData *data, va_list ap) } //Code from party_send_xy_timer [Skotlex] -int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) -{ +int guild_send_xy_timer(int tid, int64 tick, int id, intptr_t data) { guild->db->foreach(guild->db,guild->send_xy_timer_sub,tick); return 0; } @@ -1365,7 +1363,7 @@ void guild_block_skill(struct map_session_data *sd, int time) uint16 skill_id[] = { GD_BATTLEORDER, GD_REGENERATION, GD_RESTORE, GD_EMERGENCYCALL }; int i; for (i = 0; i < 4; i++) - skill->blockpc_start(sd, skill_id[i], time , true); + skill->blockpc_start(sd, skill_id[i], time); } /*==================================================== diff --git a/src/map/guild.h b/src/map/guild.h index 566ca7ce4..348a6c7e4 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -148,13 +148,13 @@ struct guild_interface { /* guild aura */ void (*aura_refresh) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); /* */ - int (*payexp_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*payexp_timer) (int tid, int64 tick, int id, intptr_t data); TBL_PC* (*sd_check) (int guild_id, int account_id, int char_id); bool (*read_guildskill_tree_db) (char* split[], int columns, int current); bool (*read_castledb) (char* str[], int columns, int current); int (*payexp_timer_sub) (DBKey key, DBData *data, va_list ap); int (*send_xy_timer_sub) (DBKey key, DBData *data, va_list ap); - int (*send_xy_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data); DBData (*create_expcache) (DBKey key, va_list args); int (*eventlist_db_final) (DBKey key, DBData *data, va_list ap); int (*expcache_db_final) (DBKey key, DBData *data, va_list ap); diff --git a/src/map/homunculus.c b/src/map/homunculus.c index 1e47053fe..52f0572c0 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -615,7 +615,7 @@ bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd) { return true; } -int homunculus_hunger_timer(int tid, unsigned int tick, int id, intptr_t data) { +int homunculus_hunger_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd; struct homun_data *hd; diff --git a/src/map/homunculus.h b/src/map/homunculus.h index 2cb558930..e3ec38f7b 100644 --- a/src/map/homunculus.h +++ b/src/map/homunculus.h @@ -117,7 +117,7 @@ struct homunculus_interface { void (*save) (struct homun_data *hd); unsigned char (*menu) (struct map_session_data *sd,unsigned char menu_num); bool (*feed) (struct map_session_data *sd, struct homun_data *hd); - int (*hunger_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*hunger_timer) (int tid, int64 tick, int id, intptr_t data); void (*hunger_timer_delete) (struct homun_data *hd); int (*change_name) (struct map_session_data *sd,char *name); bool (*change_name_ack) (struct map_session_data *sd, char* name, int flag); diff --git a/src/map/instance.c b/src/map/instance.c index 6ae1d6141..6b96c3112 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -110,7 +110,10 @@ int instance_create(int owner_id, const char *name, enum instance_owner_type typ instance->list[i].owner_id = owner_id; instance->list[i].owner_type = type; instance->list[i].vars = idb_alloc(DB_OPT_RELEASE_DATA); - + instance->list[i].respawn.map = 0; + instance->list[i].respawn.y = 0; + instance->list[i].respawn.x = 0; + safestrncpy( instance->list[i].name, name, sizeof(instance->list[i].name) ); if( type != IOT_NONE ) { @@ -239,9 +242,17 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const } } + //Mimic questinfo + if( map->list[m].qi_count ) { + map->list[im].qi_count = map->list[m].qi_count; + CREATE( map->list[im].qi_data, struct questinfo, map->list[im].qi_count ); + memcpy( map->list[im].qi_data, map->list[m].qi_data, map->list[im].qi_count * sizeof(struct questinfo) ); + } + map->list[im].m = im; map->list[im].instance_id = instance_id; map->list[im].instance_src_map = m; + map->list[im].flag.src4instance = 0; //clear map->list[m].flag.src4instance = 1; // Flag this map as a src map for instances RECREATE(instance->list[instance_id].map, unsigned short, ++instance->list[instance_id].num_map); @@ -271,6 +282,21 @@ int instance_map2imap(int16 m, int instance_id) { return -1; } +int instance_mapname2imap(const char *map_name, int instance_id) { + int i; + + if( !instance->valid(instance_id) ) { + return -1; + } + + for( i = 0; i < instance->list[instance_id].num_map; i++ ) { + if( instance->list[instance_id].map[i] && !strcmpi(map->list[map->list[instance->list[instance_id].map[i]].instance_src_map].name,map_name) ) + return instance->list[instance_id].map[i]; + } + return -1; +} + + /*-------------------------------------- * m : source map * instance_id : where to search @@ -291,7 +317,6 @@ int instance_mapid2imapid(int16 m, int instance_id) { } /*-------------------------------------- - * map_instance_map_npcsub * Used on Init instance. Duplicates each script on source map *--------------------------------------*/ int instance_map_npcsub(struct block_list* bl, va_list args) { @@ -304,6 +329,19 @@ int instance_map_npcsub(struct block_list* bl, va_list args) { return 1; } +int instance_init_npc(struct block_list* bl, va_list args) { + struct npc_data *nd = (struct npc_data*)bl; + struct event_data *ev; + char evname[EVENT_NAME_LENGTH]; + + snprintf(evname, EVENT_NAME_LENGTH, "%s::OnInstanceInit", nd->exname); + + if( ( ev = strdb_get(npc->ev_db, evname) ) ) + script->run(ev->nd->u.scr.script, ev->pos, 0, ev->nd->bl.id); + + return 1; +} + /*-------------------------------------- * Init all map on the instance. Npcs are created here *--------------------------------------*/ @@ -314,8 +352,11 @@ void instance_init(int instance_id) { return; // nothing to do for( i = 0; i < instance->list[instance_id].num_map; i++ ) - map->foreachinmap(instance_map_npcsub, map->list[instance->list[instance_id].map[i]].instance_src_map, BL_NPC, instance->list[instance_id].map[i]); + map->foreachinmap(instance->map_npcsub, map->list[instance->list[instance_id].map[i]].instance_src_map, BL_NPC, instance->list[instance_id].map[i]); + /* cant be together with the previous because it will rely on all of them being up */ + map->foreachininstance(instance->init_npc, instance_id, BL_NPC); + instance->list[instance_id].state = INSTANCE_BUSY; } @@ -409,6 +450,9 @@ void instance_del_map(int16 m) { aFree(map->list[m].zone_mf); } + if( map->list[m].qi_data ) + aFree(map->list[m].qi_data); + // Remove from instance for( i = 0; i < instance->list[map->list[m].instance_id].num_map; i++ ) { if( instance->list[map->list[m].instance_id].map[i] == m ) { @@ -436,7 +480,7 @@ void instance_del_map(int16 m) { /*-------------------------------------- * Timer to destroy instance by process or idle *--------------------------------------*/ -int instance_destroy_timer(int tid, unsigned int tick, int id, intptr_t data) { +int instance_destroy_timer(int tid, int64 tick, int id, intptr_t data) { instance->destroy(id); return 0; } @@ -566,9 +610,11 @@ void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsign if( progress_timeout ) { instance->list[instance_id].progress_timeout = now + progress_timeout; instance->list[instance_id].progress_timer = timer->add( timer->gettick() + progress_timeout * 1000, instance->destroy_timer, instance_id, 0); + instance->list[instance_id].original_progress_timeout = progress_timeout; } else { instance->list[instance_id].progress_timeout = 0; instance->list[instance_id].progress_timer = INVALID_TIMER; + instance->list[instance_id].original_progress_timeout = 0; } if( idle_timeout ) { @@ -600,6 +646,37 @@ void instance_check_kick(struct map_session_data *sd) { } } +void do_reload_instance(void) { + struct s_mapiterator *iter; + struct map_session_data *sd; + int i, k; + + for(i = 0; i < instance->instances; i++) { + for(k = 0; k < instance->list[i].num_map; k++) { + if( !map->list[map->list[instance->list[i].map[k]].instance_src_map].flag.src4instance ) + break; + } + + if( k != instance->list[i].num_map ) /* any (or all) of them were disabled, we destroy */ + instance->destroy(i); + else { + /* populate the instance again */ + instance->start(i); + /* restart timers */ + instance->set_timeout(i,instance->list[i].original_progress_timeout,instance->list[i].idle_timeoutval); + } + } + + iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { + if(sd && map->list[sd->bl.m].instance_id >= 0) { + pc->setpos(sd,instance->list[map->list[sd->bl.m].instance_id].respawn.map,instance->list[map->list[sd->bl.m].instance_id].respawn.x,instance->list[map->list[sd->bl.m].instance_id].respawn.y,CLR_TELEPORT); + } + } + mapit->free(iter); +} + + void do_final_instance(void) { int i; @@ -623,7 +700,7 @@ void instance_defaults(void) { instance->init = do_init_instance; instance->final = do_final_instance; - + instance->reload = do_reload_instance; /* start point */ instance->start_id = 0; /* count */ @@ -636,6 +713,9 @@ void instance_defaults(void) { instance->del_map = instance_del_map; instance->map2imap = instance_map2imap; instance->mapid2imapid = instance_mapid2imapid; + instance->mapname2imap = instance_mapname2imap; + instance->map_npcsub = instance_map_npcsub; + instance->init_npc = instance_init_npc; instance->destroy = instance_destroy; instance->start = instance_init; instance->check_idle = instance_check_idle; diff --git a/src/map/instance.h b/src/map/instance.h index ba6d26d59..27a9401b4 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -40,11 +40,16 @@ struct instance_data { int idle_timer; unsigned int idle_timeout, idle_timeoutval; + + unsigned int original_progress_timeout; + + struct point respawn;/* reload spawn */ }; struct instance_interface { void (*init) (void); void (*final) (void); + void (*reload) (void); /* start point */ unsigned short start_id; unsigned short instances;/* count */ @@ -56,13 +61,16 @@ struct instance_interface { void (*del_map) (int16 m); int (*map2imap) (int16 m, int instance_id); int (*mapid2imapid) (int16 m, int instance_id); + int (*mapname2imap) (const char *map_name, int instance_id); + int (*map_npcsub) (struct block_list* bl, va_list args); + int (*init_npc) (struct block_list* bl, va_list args); void (*destroy) (int instance_id); void (*start) (int instance_id); void (*check_idle) (int instance_id); void (*check_kick) (struct map_session_data *sd); void (*set_timeout) (int instance_id, unsigned int progress_timeout, unsigned int idle_timeout); bool (*valid) (int instance_id); - int (*destroy_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*destroy_timer) (int tid, int64 tick, int id, intptr_t data); }; struct instance_interface *instance; diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c index 5225672af..f67446629 100644 --- a/src/map/irc-bot.c +++ b/src/map/irc-bot.c @@ -29,7 +29,7 @@ char send_string[IRC_MESSAGE_LENGTH]; * Timer callback to (re-)connect to an IRC server * @see timer->do_timer */ -int irc_connect_timer(int tid, unsigned int tick, int id, intptr_t data) { +int irc_connect_timer(int tid, int64 tick, int id, intptr_t data) { struct hSockOpt opt; if( ircbot->isOn || ++ircbot->fails >= 3 ) return 0; @@ -52,7 +52,7 @@ int irc_connect_timer(int tid, unsigned int tick, int id, intptr_t data) { * Timer callback to send identification commands to an IRC server * @see timer->do_timer */ -int irc_identify_timer(int tid, unsigned int tick, int id, intptr_t data) { +int irc_identify_timer(int tid, int64 tick, int id, intptr_t data) { if( !ircbot->isOn ) return 0; @@ -70,7 +70,7 @@ int irc_identify_timer(int tid, unsigned int tick, int id, intptr_t data) { * Timer callback to join channels (and optionally send NickServ commands) * @see timer->do_timer */ -int irc_join_timer(int tid, unsigned int tick, int id, intptr_t data) { +int irc_join_timer(int tid, int64 tick, int id, intptr_t data) { if( !ircbot->isOn ) return 0; diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h index aafbfccde..52ff0c9be 100644 --- a/src/map/irc-bot.h +++ b/src/map/irc-bot.h @@ -22,7 +22,7 @@ struct irc_func { struct irc_bot_interface { int fd; bool isIn, isOn; - unsigned int last_try; + int64 last_try; unsigned char fails; unsigned long ip; unsigned short port; @@ -43,9 +43,9 @@ struct irc_bot_interface { /* */ struct irc_func* (*func_search) (char* function_name); /* */ - int (*connect_timer) (int tid, unsigned int tick, int id, intptr_t data); - int (*identify_timer) (int tid, unsigned int tick, int id, intptr_t data); - int (*join_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*connect_timer) (int tid, int64 tick, int id, intptr_t data); + int (*identify_timer) (int tid, int64 tick, int id, intptr_t data); + int (*join_timer) (int tid, int64 tick, int id, intptr_t data); /* */ void (*send)(char *str); void (*relay) (char *name, const char *msg); diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 5c698b3c9..3fc8d526b 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -1027,7 +1027,10 @@ void itemdb_read_packages(void) { if( itemdb->packages[count].random_qty ) { CREATE(itemdb->packages[count].random_groups, struct item_package_rand_group, itemdb->packages[count].random_qty); for( c = 0; c < itemdb->packages[count].random_qty; c++ ) { - CREATE(itemdb->packages[count].random_groups[c].random_list, struct item_package_rand_entry, rgroups[ i - 1 ][c]); + if( !rgroups[ i - 1 ][c] ) + ShowError("itemdb_read_packages: package '%s' missing 'Random' field %d! there must not be gaps!\n",config_setting_name(itg),c+1); + else + CREATE(itemdb->packages[count].random_groups[c].random_list, struct item_package_rand_entry, rgroups[ i - 1 ][c]); itemdb->packages[count].random_groups[c].random_qty = 0; } } @@ -1090,7 +1093,7 @@ void itemdb_read_packages(void) { itemdb->packages[count].random_groups[gidx].random_list[r].id = data ? data->nameid : 0; itemdb->packages[count].random_groups[gidx].random_list[r].qty = icount; if( (itemdb->packages[count].random_groups[gidx].random_list[r].rate = rate) == 10000 ) { - ShowWarning("itemdb_read_packages: item '%s' in '%s' has 100% drop rate!! set this item as 'Random: 0' or other items won't drop!!!\n",itname,config_setting_name(itg)); + ShowWarning("itemdb_read_packages: item '%s' in '%s' has 100%% drop rate!! set this item as 'Random: 0' or other items won't drop!!!\n",itname,config_setting_name(itg)); } itemdb->packages[count].random_groups[gidx].random_list[r].hours = expire; itemdb->packages[count].random_groups[gidx].random_list[r].announce = announce == true ? 1 : 0; @@ -1584,6 +1587,9 @@ int itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt) if( nameid <= 0 ) { ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", nameid, line, source); return 0; + } else if ( nameid >= MAX_ITEMDB ) { + ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", beyond MAX_ITEMDB, skipping.\n", nameid, line, source); + return 0; } //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 0f46c1c01..2579d84ca 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -48,6 +48,15 @@ enum item_itemid { ITEMID_TRAP_ALLOY = 7940, ITEMID_ANCILLA = 12333, ITEMID_REINS_OF_MOUNT = 12622, + ITEMID_LOVE_ANGEL = 12287, + ITEMID_SQUIRREL = 12288, + ITEMID_GOGO = 12289, + ITEMID_PICTURE_DIARY = 12304, + ITEMID_MINI_HEART = 12305, + ITEMID_NEWCOMER = 12306, + ITEMID_KID = 12307, + ITEMID_MAGIC_CASTLE = 12308, + ITEMID_BULGING_HEAD = 12309, }; /** diff --git a/src/map/map.c b/src/map/map.c index d920875ee..2a2f98bdc 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -88,8 +88,12 @@ int map_usercount(void) { *------------------------------------------*/ int map_freeblock (struct block_list *bl) { nullpo_retr(map->block_free_lock, bl); + if (map->block_free_lock == 0 || map->block_free_count >= block_free_max) { - aFree(bl); + if( bl->type == BL_ITEM ) + ers_free(map->flooritem_ers, bl); + else + aFree(bl); bl = NULL; if (map->block_free_count >= block_free_max) ShowWarning("map_freeblock: too many free block! %d %d\n", map->block_free_count, map->block_free_lock); @@ -109,11 +113,14 @@ int map_freeblock_lock (void) { * Remove the lock on map_bl *------------------------------------------*/ int map_freeblock_unlock (void) { + if ((--map->block_free_lock) == 0) { int i; - for (i = 0; i < map->block_free_count; i++) - { - aFree(map->block_free[i]); + for (i = 0; i < map->block_free_count; i++) { + if( map->block_free[i]->type == BL_ITEM ) + ers_free(map->flooritem_ers, map->block_free[i]); + else + aFree(map->block_free[i]); map->block_free[i] = NULL; } map->block_free_count = 0; @@ -127,7 +134,7 @@ int map_freeblock_unlock (void) { // Timer function to check if there some remaining lock and remove them if so. // Called each 1s -int map_freeblock_timer(int tid, unsigned int tick, int id, intptr_t data) { +int map_freeblock_timer(int tid, int64 tick, int id, intptr_t data) { if (map->block_free_lock > 0) { ShowError("map_freeblock_timer: block_free_lock(%d) is invalid.\n", map->block_free_lock); map->block_free_lock = 1; @@ -259,8 +266,7 @@ int map_delblock(struct block_list* bl) * Pass flag as 1 to prevent doing skill->unit_move checks * (which are executed by default on BL_CHAR types) *------------------------------------------*/ -int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) -{ +int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) { int x0 = bl->x, y0 = bl->y; struct status_change *sc = NULL; int moveblock = ( x0/BLOCK_SIZE != x1/BLOCK_SIZE || y0/BLOCK_SIZE != y1/BLOCK_SIZE); @@ -1305,7 +1311,7 @@ int map_get_new_object_id(void) * Timered function to clear the floor (remove remaining item) * Called each flooritem_lifetime ms *------------------------------------------*/ -int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data) { +int map_clearflooritem_timer(int tid, int64 tick, int id, intptr_t data) { struct flooritem_data* fitem = (struct flooritem_data*)idb_get(map->id_db, id); if (fitem == NULL || fitem->bl.type != BL_ITEM || (fitem->cleartimer != tid)) { @@ -1330,7 +1336,7 @@ int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data) void map_clearflooritem(struct block_list *bl) { struct flooritem_data* fitem = (struct flooritem_data*)bl; - if( fitem->cleartimer ) + if( fitem->cleartimer != INVALID_TIMER ) timer->delete(fitem->cleartimer,map->clearflooritem_timer); clif->clearflooritem(fitem, 0); @@ -1470,15 +1476,16 @@ int map_addflooritem(struct item *item_data,int amount,int16 m,int16 x,int16 y,i return 0; r=rnd(); - CREATE(fitem, struct flooritem_data, 1); - fitem->bl.type=BL_ITEM; + fitem = ers_alloc(map->flooritem_ers, struct flooritem_data); + + fitem->bl.type = BL_ITEM; fitem->bl.prev = fitem->bl.next = NULL; - fitem->bl.m=m; - fitem->bl.x=x; - fitem->bl.y=y; + fitem->bl.m = m; + fitem->bl.x = x; + fitem->bl.y = y; fitem->bl.id = map->get_new_object_id(); if(fitem->bl.id==0){ - aFree(fitem); + ers_free(map->flooritem_ers, fitem); return 0; } @@ -1715,8 +1722,6 @@ int map_quit(struct map_session_data *sd) { if( sd->state.storage_flag == 1 ) sd->state.storage_flag = 0; // No need to Double Save Storage on Quit. - if (sd->state.permanent_speed == 1) sd->state.permanent_speed = 0; // Remove lock so speed is set back to normal at login. - if( sd->ed ) { elemental->clean_effect(sd->ed); unit->remove_map(&sd->ed->bl,CLR_TELEPORT,ALC_MARK); @@ -2288,8 +2293,7 @@ int map_removemobs_sub(struct block_list *bl, va_list ap) return 1; } -int map_removemobs_timer(int tid, unsigned int tick, int id, intptr_t data) -{ +int map_removemobs_timer(int tid, int64 tick, int id, intptr_t data) { int count; const int16 m = id; @@ -3104,6 +3108,10 @@ void do_final_maps(void) { if( map->list[i].channel ) clif->chsys_delete(map->list[i].channel); + + if( map->list[i].qi_data ) + aFree(map->list[i].qi_data); + } map->zone_db_clear(); @@ -3169,6 +3177,12 @@ void map_flags_init(void) { map->list[i].misc_damage_rate = 100; map->list[i].short_damage_rate = 100; map->list[i].long_damage_rate = 100; + + if( map->list[i].qi_data ) + aFree(map->list[i].qi_data); + + map->list[i].qi_data = NULL; + map->list[i].qi_count = 0; } } @@ -4380,7 +4394,17 @@ bool map_zone_mf_cache(int m, char *flag, char *params) { map_zone_mf_cache_add(m,rflag); } } + } else if (!strcmpi(flag,"nocashshop")) { + if( state && map->list[m].flag.nocashshop ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nocashshop\toff"); + else if( map->list[m].flag.nocashshop ) + map_zone_mf_cache_add(m,"nocashshop"); + } } + return false; } void map_zone_apply(int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath) { @@ -4946,6 +4970,42 @@ void read_map_zone_db(void) { } } +int map_get_new_bonus_id (void) { + return map->bonus_id++; +} + +void map_add_questinfo(int m, struct questinfo *qi) { + unsigned short i; + + /* duplicate, override */ + for(i = 0; i < map->list[m].qi_count; i++) { + if( map->list[m].qi_data[i].nd == qi->nd ) + break; + } + + if( i == map->list[m].qi_count ) + RECREATE(map->list[m].qi_data, struct questinfo, ++map->list[m].qi_count); + + memcpy(&map->list[m].qi_data[i], qi, sizeof(struct questinfo)); +} + +bool map_remove_questinfo(int m, struct npc_data *nd) { + unsigned short i; + + for(i = 0; i < map->list[m].qi_count; i++) { + struct questinfo *qi = &map->list[m].qi_data[i]; + if( qi->nd == nd ) { + memset(&map->list[m].qi_data[i], 0, sizeof(struct questinfo)); + if( i != --map->list[m].qi_count ) { + memmove(&map->list[m].qi_data[i],&map->list[m].qi_data[i+1],sizeof(struct questinfo)*(map->list[m].qi_count-i)); + } + return true; + } + } + + return false; +} + /** * @see DBApply */ @@ -5075,6 +5135,8 @@ void do_final(void) map->list_final(); vending->final(); + HPM_map_do_final(); + map->map_db->destroy(map->map_db, map->db_final); mapindex_final(); @@ -5092,6 +5154,7 @@ void do_final(void) map->sql_close(); ers_destroy(map->iterator_ers); + ers_destroy(map->flooritem_ers); aFree(map->list); @@ -5470,7 +5533,10 @@ int do_init(int argc, char *argv[]) map->zone_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, MAP_ZONE_NAME_LENGTH); map->iterator_ers = ers_new(sizeof(struct s_mapiterator),"map.c::map_iterator_ers",ERS_OPT_NONE); - + + map->flooritem_ers = ers_new(sizeof(struct flooritem_data),"map.c::map_flooritem_ers",ERS_OPT_NONE); + ers_chunk_size(map->flooritem_ers, 100); + map->sql_init(); if (logs->config.sql_logs) logs->sql_init(); @@ -5634,6 +5700,10 @@ void map_defaults(void) { map->iterator_ers = NULL; map->cache_buffer = NULL; + + map->flooritem_ers = NULL; + /* */ + map->bonus_id = SP_LAST_KNOWN; /* funcs */ map->zone_init = map_zone_init; map->zone_remove = map_zone_remove; @@ -5800,7 +5870,12 @@ void map_defaults(void) { map->addblcell = map_addblcell; map->delblcell = map_delblcell; - + + map->get_new_bonus_id = map_get_new_bonus_id; + + map->add_questinfo = map_add_questinfo; + map->remove_questinfo = map_remove_questinfo; + /** * mapit interface **/ diff --git a/src/map/map.h b/src/map/map.h index 3a7990dcb..6b7d2a630 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -339,7 +339,7 @@ struct flooritem_data { unsigned char subx,suby; int cleartimer; int first_get_charid,second_get_charid,third_get_charid; - unsigned int first_get_tick,second_get_tick,third_get_tick; + int64 first_get_tick,second_get_tick,third_get_tick; struct item item_data; }; @@ -406,7 +406,11 @@ enum _sp { SP_ADD_SKILL_BLOW, SP_SP_VANISH_RATE, SP_MAGIC_SP_GAIN_VALUE, SP_MAGIC_HP_GAIN_VALUE, SP_ADD_CLASS_DROP_ITEM, //2041-2045 SP_EMATK, SP_SP_GAIN_RACE_ATTACK, SP_HP_GAIN_RACE_ATTACK, SP_SKILL_USE_SP_RATE, //2046-2049 SP_SKILL_COOLDOWN,SP_SKILL_FIXEDCAST, SP_SKILL_VARIABLECAST, SP_FIXCASTRATE, SP_VARCASTRATE, //2050-2054 - SP_SKILL_USE_SP,SP_MAGIC_ATK_ELE, SP_ADD_FIXEDCAST, SP_ADD_VARIABLECAST //2055-2058 + SP_SKILL_USE_SP,SP_MAGIC_ATK_ELE, SP_ADD_FIXEDCAST, SP_ADD_VARIABLECAST, //2055-2058 + + + /* must be the last, plugins add bonuses from this value onwards */ + SP_LAST_KNOWN, }; enum _look { @@ -553,6 +557,17 @@ struct map_drop_list { int drop_per; }; + +struct questinfo { + struct npc_data *nd; + unsigned short icon; + unsigned char color; + int quest_id; + bool hasJob; + unsigned short job;/* perhaps a mapid mask would be most flexible? */ +}; + + struct map_data { char name[MAP_NAME_LENGTH]; uint16 index; // The map index used by the mapindex* functions. @@ -628,6 +643,7 @@ struct map_data { unsigned chsysnolocalaj : 1; unsigned noknockback : 1; unsigned notomb : 1; + unsigned nocashshop : 1; } flag; struct point save; struct npc_data *npc[MAX_NPC_PER_MAP]; @@ -686,6 +702,13 @@ struct map_data { int (*getcellp)(struct map_data* m,int16 x,int16 y,cell_chk cellchk); void (*setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag); char *cellPos; + + /* ShowEvent Data Cache */ + struct questinfo *qi_data; + unsigned short qi_count; + + /* speeds up clif_updatestatus processing by causing hpmeter to run only when someone with the permission can view it */ + unsigned short hpmeter_visible; }; /// Stores information about a remote map (for multi-mapserver setups). @@ -854,6 +877,10 @@ struct map_interface { /* [Ind/Hercules] */ struct eri *iterator_ers; char *cache_buffer; // Has the uncompressed gat data of all maps, so just one allocation has to be made + /* */ + struct eri *flooritem_ers; + /* */ + int bonus_id; /* funcs */ void (*zone_init) (void); void (*zone_remove) (int m); @@ -876,7 +903,7 @@ struct map_interface { // blocklist manipulation int (*addblock) (struct block_list* bl); int (*delblock) (struct block_list* bl); - int (*moveblock) (struct block_list *bl, int x1, int y1, unsigned int tick); + int (*moveblock) (struct block_list *bl, int x1, int y1, int64 tick); //blocklist nb in one cell int (*count_oncell) (int16 m,int16 x,int16 y,int type); struct skill_unit * (*find_skill_unit_oncell) (struct block_list* target,int16 x,int16 y,uint16 skill_id,struct skill_unit* out_unit, int flag); @@ -888,8 +915,8 @@ struct map_interface { // npc bool (*addnpc) (int16 m,struct npc_data *nd); // map item - int (*clearflooritem_timer) (int tid, unsigned int tick, int id, intptr_t data); - int (*removemobs_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*clearflooritem_timer) (int tid, int64 tick, int id, intptr_t data); + int (*removemobs_timer) (int tid, int64 tick, int id, intptr_t data); void (*clearflooritem) (struct block_list* bl); int (*addflooritem) (struct item *item_data,int amount,int16 m,int16 x,int16 y,int first_charid,int second_charid,int third_charid,int flags); // player to map session @@ -977,7 +1004,7 @@ struct map_interface { void (*do_shutdown) (void); - int (*freeblock_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*freeblock_timer) (int tid, int64 tick, int id, intptr_t data); int (*searchrandfreecell) (int16 m, int16 *x, int16 *y, int stack); int (*count_sub) (struct block_list *bl, va_list ap); DBData (*create_charid2nick) (DBKey key, va_list args); @@ -1020,6 +1047,9 @@ struct map_interface { bool (*arg_next_value) (const char *option, int i, int argc); void (*addblcell) (struct block_list *bl); void (*delblcell) (struct block_list *bl); + int (*get_new_bonus_id) (void); + void (*add_questinfo) (int m, struct questinfo *qi); + bool (*remove_questinfo) (int m, struct npc_data *nd); }; struct map_interface *map; diff --git a/src/map/mapreg.h b/src/map/mapreg.h index 3c1d0ba0e..c8f229cef 100644 --- a/src/map/mapreg.h +++ b/src/map/mapreg.h @@ -34,7 +34,7 @@ struct mapreg_interface { bool (*setregstr) (int uid, const char *str); void (*load) (void); void (*save) (void); - int (*save_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*save_timer) (int tid, int64 tick, int id, intptr_t data); void (*reload) (void); bool (*config_read) (const char *w1, const char *w2); }; diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c index 902b7c39b..c94e42d5d 100644 --- a/src/map/mapreg_sql.c +++ b/src/map/mapreg_sql.c @@ -228,7 +228,7 @@ void script_save_mapreg(void) { } } -int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr_t data) { +int script_autosave_mapreg(int tid, int64 tick, int id, intptr_t data) { mapreg->save(); return 0; } diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 8b8353f46..8c74a5e1e 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -94,7 +94,7 @@ int mercenary_get_lifetime(struct mercenary_data *md) return 0; td = timer->get(md->contract_timer); - return (td != NULL) ? DIFF_TICK(td->tick, timer->gettick()) : 0; + return (td != NULL) ? DIFF_TICK32(td->tick, timer->gettick()) : 0; } int mercenary_get_guild(struct mercenary_data *md) @@ -217,7 +217,7 @@ int mercenary_save(struct mercenary_data *md) return 1; } -int merc_contract_end_timer(int tid, unsigned int tick, int id, intptr_t data) { +int merc_contract_end_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd; struct mercenary_data *md; diff --git a/src/map/mercenary.h b/src/map/mercenary.h index 47f37ac66..3245606cf 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -43,7 +43,7 @@ struct mercenary_data { int contract_timer; unsigned devotion_flag : 1; - unsigned int masterteleport_timer; + int64 masterteleport_timer; }; /*===================================== @@ -89,7 +89,7 @@ struct mercenary_interface { int (*killbonus) (struct mercenary_data *md); int (*search_index) (int class_); - int (*contract_end_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*contract_end_timer) (int tid, int64 tick, int id, intptr_t data); bool (*read_db_sub) (char* str[], int columns, int current); bool (*read_skill_db_sub) (char* str[], int columns, int current); }; diff --git a/src/map/mob.c b/src/map/mob.c index 7023bcb9d..97f8ea6c1 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -332,8 +332,7 @@ int mob_get_random_id(int type, int flag, int lv) /*========================================== * Kill Steal Protection [Zephyrus] *------------------------------------------*/ -bool mob_ksprotected (struct block_list *src, struct block_list *target) -{ +bool mob_ksprotected(struct block_list *src, struct block_list *target) { struct block_list *s_bl, *t_bl; struct map_session_data *sd, // Source @@ -341,7 +340,7 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target) *t_sd; // Mob Target struct status_change_entry *sce; struct mob_data *md; - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); char output[128]; if( !battle_config.ksprotection ) @@ -559,8 +558,8 @@ int mob_once_spawn_area(struct map_session_data* sd, int16 m, int16 x0, int16 y0 /*========================================== * Set a Guardian's guild data [Skotlex] *------------------------------------------*/ -int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t data) -{ //Needed because the guild_data may not be available at guardian spawn time. +int mob_spawn_guardian_sub(int tid, int64 tick, int id, intptr_t data) { + //Needed because the guild_data may not be available at guardian spawn time. struct block_list* bl = map->id2bl(id); struct mob_data* md; struct guild* g; @@ -779,18 +778,17 @@ int mob_can_reach(struct mob_data *md,struct block_list *bl,int range, int state /*========================================== * Links nearby mobs (supportive mobs) *------------------------------------------*/ -int mob_linksearch(struct block_list *bl,va_list ap) -{ +int mob_linksearch(struct block_list *bl,va_list ap) { struct mob_data *md; int class_; struct block_list *target; - unsigned int tick; + int64 tick; nullpo_ret(bl); md=(struct mob_data *)bl; class_ = va_arg(ap, int); target = va_arg(ap, struct block_list *); - tick=va_arg(ap, unsigned int); + tick = va_arg(ap, int64); if (md->class_ == class_ && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME && !md->target_id) @@ -809,7 +807,7 @@ int mob_linksearch(struct block_list *bl,va_list ap) /*========================================== * mob spawn with delay (timer function) *------------------------------------------*/ -int mob_delayspawn(int tid, unsigned int tick, int id, intptr_t data) { +int mob_delayspawn(int tid, int64 tick, int id, intptr_t data) { struct block_list* bl = map->id2bl(id); struct mob_data* md = BL_CAST(BL_MOB, bl); @@ -884,8 +882,8 @@ int mob_count_sub(struct block_list *bl, va_list ap) { int mob_spawn (struct mob_data *md) { int i=0; - unsigned int tick = timer->gettick(); - int c =0; + int64 tick = timer->gettick(); + int64 c = 0; md->last_thinktime = tick; if (md->bl.prev != NULL) @@ -1185,7 +1183,7 @@ int mob_warpchase_sub(struct block_list *bl,va_list ap) { /*========================================== * Processing of slave monsters *------------------------------------------*/ -int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) { +int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) { struct block_list *bl; bl=map->id2bl(md->master_id); @@ -1268,8 +1266,7 @@ int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) { * when trying to pick new targets when the current chosen target is * unreachable. *------------------------------------------*/ -int mob_unlocktarget(struct mob_data *md, unsigned int tick) -{ +int mob_unlocktarget(struct mob_data *md, int64 tick) { nullpo_ret(md); switch (md->state.skillstate) { @@ -1308,8 +1305,7 @@ int mob_unlocktarget(struct mob_data *md, unsigned int tick) /*========================================== * Random walk *------------------------------------------*/ -int mob_randomwalk(struct mob_data *md,unsigned int tick) -{ +int mob_randomwalk(struct mob_data *md, int64 tick) { const int retrycount=20; int i,x,y,c,d; int speed; @@ -1383,8 +1379,7 @@ int mob_warpchase(struct mob_data *md, struct block_list *target) /*========================================== * AI of MOB whose is near a Player *------------------------------------------*/ -bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) -{ +bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { struct block_list *tbl = NULL, *abl = NULL; int mode; int view_range, can_move; @@ -1645,10 +1640,9 @@ bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) return true; } -int mob_ai_sub_hard_timer(struct block_list *bl,va_list ap) -{ +int mob_ai_sub_hard_timer(struct block_list *bl, va_list ap) { struct mob_data *md = (struct mob_data*)bl; - unsigned int tick = va_arg(ap, unsigned int); + int64 tick = va_arg(ap, int64); if (mob->ai_sub_hard(md, tick)) { //Hard AI triggered. if(!md->state.spotted) @@ -1661,9 +1655,9 @@ int mob_ai_sub_hard_timer(struct block_list *bl,va_list ap) /*========================================== * Serious processing for mob in PC field of view (foreachclient) *------------------------------------------*/ -int mob_ai_sub_foreachclient(struct map_session_data *sd,va_list ap) { - unsigned int tick; - tick=va_arg(ap,unsigned int); +int mob_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) { + int64 tick; + tick=va_arg(ap, int64); map->foreachinrange(mob->ai_sub_hard_timer,&sd->bl, AREA_SIZE+ACTIVE_AI_RANGE, BL_MOB,tick); return 0; @@ -1672,16 +1666,15 @@ int mob_ai_sub_foreachclient(struct map_session_data *sd,va_list ap) { /*========================================== * Negligent mode MOB AI (PC is not in near) *------------------------------------------*/ -int mob_ai_sub_lazy(struct mob_data *md, va_list args) -{ - unsigned int tick; +int mob_ai_sub_lazy(struct mob_data *md, va_list args) { + int64 tick; nullpo_ret(md); if(md->bl.prev == NULL) return 0; - tick = va_arg(args,unsigned int); + tick = va_arg(args, int64); if (battle_config.mob_ai&0x20 && map->list[md->bl.m].users>0) return (int)mob->ai_sub_hard(md, tick); @@ -1715,7 +1708,7 @@ int mob_ai_sub_lazy(struct mob_data *md, va_list args) md->last_thinktime=tick; if (md->master_id) { - mob->ai_sub_hard_slavemob (md,tick); + mob->ai_sub_hard_slavemob(md,tick); return 0; } @@ -1740,7 +1733,7 @@ int mob_ai_sub_lazy(struct mob_data *md, va_list args) /*========================================== * Negligent processing for mob outside PC field of view (interval timer function) *------------------------------------------*/ -int mob_ai_lazy(int tid, unsigned int tick, int id, intptr_t data) { +int mob_ai_lazy(int tid, int64 tick, int id, intptr_t data) { map->foreachmob(mob->ai_sub_lazy,tick); return 0; } @@ -1748,7 +1741,7 @@ int mob_ai_lazy(int tid, unsigned int tick, int id, intptr_t data) { /*========================================== * Serious processing for mob in PC field of view (interval timer function) *------------------------------------------*/ -int mob_ai_hard(int tid, unsigned int tick, int id, intptr_t data) { +int mob_ai_hard(int tid, int64 tick, int id, intptr_t data) { if (battle_config.mob_ai&0x20) map->foreachmob(mob->ai_sub_lazy,tick); @@ -1785,8 +1778,7 @@ struct item_drop* mob_setlootitem(struct item* item) /*========================================== * item drop with delay (timer function) *------------------------------------------*/ -int mob_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data) -{ +int mob_delay_item_drop(int tid, int64 tick, int id, intptr_t data) { struct item_drop_list *list; struct item_drop *ditem, *ditem_prev; list=(struct item_drop_list *)data; @@ -1840,7 +1832,7 @@ void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct ite dlist->item = ditem; } -int mob_timer_delete(int tid, unsigned int tick, int id, intptr_t data) { +int mob_timer_delete(int tid, int64 tick, int id, intptr_t data) { struct block_list* bl = map->id2bl(id); struct mob_data* md = BL_CAST(BL_MOB, bl); @@ -1885,7 +1877,7 @@ int mob_deleteslave(struct mob_data *md) { return 0; } // Mob respawning through KAIZEL or NPC_REBIRTH [Skotlex] -int mob_respawn(int tid, unsigned int tick, int id, intptr_t data) { +int mob_respawn(int tid, int64 tick, int id, intptr_t data) { struct block_list *bl = map->id2bl(id); if(!bl) return 0; @@ -2069,7 +2061,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { } pt[DAMAGELOG_SIZE]; int i, temp, count, m = md->bl.m, pnum = 0; int dmgbltypes = 0; // bitfield of all bl types, that caused damage to the mob and are elligible for exp distribution - unsigned int mvp_damage, tick = timer->gettick(); + unsigned int mvp_damage; + int64 tick = timer->gettick(); bool rebirth, homkillonly; mstatus = &md->status; @@ -2610,7 +2603,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { void mob_revive(struct mob_data *md, unsigned int hp) { - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); md->state.skillstate = MSS_IDLE; md->last_thinktime = tick; md->next_walktime = tick+rnd()%50+5000; @@ -2695,8 +2688,8 @@ int mob_random_class (int *value, size_t count) *------------------------------------------*/ int mob_class_change (struct mob_data *md, int class_) { - unsigned int tick = timer->gettick(); - int i, c, hp_rate; + int64 tick = timer->gettick(), c = 0; + int i, hp_rate; nullpo_ret(md); @@ -3032,8 +3025,7 @@ struct mob_data *mob_getfriendstatus(struct mob_data *md,int cond1,int cond2) { /*========================================== * Skill use judging *------------------------------------------*/ -int mobskill_use(struct mob_data *md, unsigned int tick, int event) -{ +int mobskill_use(struct mob_data *md, int64 tick, int event) { struct mob_skill *ms; struct block_list *fbl = NULL; //Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex] struct block_list *bl; @@ -3249,8 +3241,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) /*========================================== * Skill use event processing *------------------------------------------*/ -int mobskill_event(struct mob_data *md, struct block_list *src, unsigned int tick, int flag) -{ +int mobskill_event(struct mob_data *md, struct block_list *src, int64 tick, int flag) { int target_id, res = 0; if(md->bl.prev == NULL || md->status.hp <= 0) @@ -3487,7 +3478,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons { if( md->deletetimer != INVALID_TIMER ) timer->delete(md->deletetimer, mob->timer_delete); - md->deletetimer = timer->add (timer->gettick() + duration, mob->timer_delete, md->bl.id, 0); + md->deletetimer = timer->add(timer->gettick() + duration, mob->timer_delete, md->bl.id, 0); } } diff --git a/src/map/mob.h b/src/map/mob.h index 210983675..2f425e285 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -166,7 +166,7 @@ struct mob_data { int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs) unsigned int bg_id; // BattleGround System - unsigned int next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick; + int64 next_walktime, last_thinktime, last_linktime, last_pcneartime, dmgtick; short move_fail_count; short lootitem_count; short min_chase; @@ -175,7 +175,7 @@ struct mob_data { int master_id,master_dist; int8 skill_idx;// key of array - unsigned int skilldelay[MAX_MOBSKILL]; + int64 skilldelay[MAX_MOBSKILL]; char npc_event[EVENT_NAME_LENGTH]; /** * Did this monster summon something? @@ -266,7 +266,7 @@ struct mob_interface { struct mob_db* (*db) (int index); struct mob_chat* (*chat) (short id); int (*makedummymobdb) (int); - int (*spawn_guardian_sub) (int tid, unsigned int tick, int id, intptr_t data); + int (*spawn_guardian_sub) (int tid, int64 tick, int id, intptr_t data); int (*skill_id2skill_idx) (int class_, uint16 skill_id); int (*db_searchname) (const char *str); int (*db_searchname_array_sub) (struct mob_db *mob, const char *str, int flag); @@ -287,7 +287,7 @@ struct mob_interface { int (*spawn_bg) (const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id); int (*can_reach) (struct mob_data *md, struct block_list *bl, int range, int state); int (*linksearch) (struct block_list *bl, va_list ap); - int (*delayspawn) (int tid, unsigned int tick, int id, intptr_t data); + int (*delayspawn) (int tid, int64 tick, int id, intptr_t data); int (*setdelayspawn) (struct mob_data *md); int (*count_sub) (struct block_list *bl, va_list ap); int (*spawn) (struct mob_data *md); @@ -298,24 +298,24 @@ struct mob_interface { int (*ai_sub_hard_bg_ally) (struct block_list *bl, va_list ap); int (*ai_sub_hard_lootsearch) (struct block_list *bl, va_list ap); int (*warpchase_sub) (struct block_list *bl, va_list ap); - int (*ai_sub_hard_slavemob) (struct mob_data *md, unsigned int tick); - int (*unlocktarget) (struct mob_data *md, unsigned int tick); - int (*randomwalk) (struct mob_data *md, unsigned int tick); + int (*ai_sub_hard_slavemob) (struct mob_data *md, int64 tick); + int (*unlocktarget) (struct mob_data *md, int64 tick); + int (*randomwalk) (struct mob_data *md, int64 tick); int (*warpchase) (struct mob_data *md, struct block_list *target); - bool (*ai_sub_hard) (struct mob_data *md, unsigned int tick); + bool (*ai_sub_hard) (struct mob_data *md, int64 tick); int (*ai_sub_hard_timer) (struct block_list *bl, va_list ap); int (*ai_sub_foreachclient) (struct map_session_data *sd, va_list ap); int (*ai_sub_lazy) (struct mob_data *md, va_list args); - int (*ai_lazy) (int tid, unsigned int tick, int id, intptr_t data); - int (*ai_hard) (int tid, unsigned int tick, int id, intptr_t data); + int (*ai_lazy) (int tid, int64 tick, int id, intptr_t data); + int (*ai_hard) (int tid, int64 tick, int id, intptr_t data); struct item_drop* (*setdropitem) (int nameid, int qty, struct item_data *data); struct item_drop* (*setlootitem) (struct item *item); - int (*delay_item_drop) (int tid, unsigned int tick, int id, intptr_t data); + int (*delay_item_drop) (int tid, int64 tick, int id, intptr_t data); void (*item_drop) (struct mob_data *md, struct item_drop_list *dlist, struct item_drop *ditem, int loot, int drop_rate, unsigned short flag); - int (*timer_delete) (int tid, unsigned int tick, int id, intptr_t data); + int (*timer_delete) (int tid, int64 tick, int id, intptr_t data); int (*deleteslave_sub) (struct block_list *bl, va_list ap); int (*deleteslave) (struct mob_data *md); - int (*respawn) (int tid, unsigned int tick, int id, intptr_t data); + int (*respawn) (int tid, int64 tick, int id, intptr_t data); void (*log_damage) (struct mob_data *md, struct block_list *src, int damage); void (*damage) (struct mob_data *md, struct block_list *src, int damage); int (*dead) (struct mob_data *md, struct block_list *src, int type); @@ -334,8 +334,8 @@ struct mob_interface { struct block_list* (*getmasterhpltmaxrate) (struct mob_data *md, int rate); int (*getfriendstatus_sub) (struct block_list *bl, va_list ap); struct mob_data* (*getfriendstatus) (struct mob_data *md, int cond1, int cond2); - int (*skill_use) (struct mob_data *md, unsigned int tick, int event); - int (*skill_event) (struct mob_data *md, struct block_list *src, unsigned int tick, int flag); + int (*skill_use) (struct mob_data *md, int64 tick, int event); + int (*skill_event) (struct mob_data *md, struct block_list *src, int64 tick, int flag); int (*is_clone) (int class_); int (*clone_spawn) (struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, int mode, int flag, unsigned int duration); int (*clone_delete) (struct mob_data *md); diff --git a/src/map/npc.c b/src/map/npc.c index c52dce325..f0bdd7bd0 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -215,7 +215,7 @@ struct npc_data* npc_name2id(const char* name) /** * Timer to check for idle time and timeout the dialog if necessary **/ -int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data) { +int npc_rr_secure_timeout_timer(int tid, int64 tick, int id, intptr_t data) { #ifdef SECURE_NPCTIMEOUT struct map_session_data* sd = NULL; unsigned int timeout = NPC_SECURE_TIMEOUT_NEXT; @@ -394,8 +394,7 @@ int npc_event_doall(const char* name) * Clock event execution * OnMinute/OnClock/OnHour/OnDay/OnDDHHMM *------------------------------------------*/ -int npc_event_do_clock(int tid, unsigned int tick, int id, intptr_t data) -{ +int npc_event_do_clock(int tid, int64 tick, int id, intptr_t data) { static struct tm ev_tm_b; // tracks previous execution time time_t clock; struct tm* t; @@ -493,9 +492,9 @@ struct timer_event_data { /*========================================== * triger 'OnTimerXXXX' events *------------------------------------------*/ -int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data) { +int npc_timerevent(int tid, int64 tick, int id, intptr_t data) { int old_rid, old_timer; - unsigned int old_tick; + int64 old_tick; struct npc_data* nd=(struct npc_data *)map->id2bl(id); struct npc_timerevent_list *te; struct timer_event_data *ted = (struct timer_event_data*)data; @@ -529,8 +528,7 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data) { ted->next++; if( nd->u.scr.timeramount > ted->next ) { - int next; - next = nd->u.scr.timer_event[ ted->next ].timer - nd->u.scr.timer_event[ ted->next - 1 ].timer; + int next = nd->u.scr.timer_event[ ted->next ].timer - nd->u.scr.timer_event[ ted->next - 1 ].timer; ted->time += next; if( sd ) sd->npc_timer_id = timer->add(tick+next,npc->timerevent,id,(intptr_t)ted); @@ -564,7 +562,7 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data) { *------------------------------------------*/ int npc_timerevent_start(struct npc_data* nd, int rid) { int j; - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); struct map_session_data *sd = NULL; //Player to whom script is attached. nullpo_ret(nd); @@ -642,7 +640,7 @@ int npc_timerevent_stop(struct npc_data* nd) if( !sd && nd->u.scr.timertick ) { - nd->u.scr.timer += DIFF_TICK(timer->gettick(),nd->u.scr.timertick); // Set 'timer' to the time that has passed since the beginning of the timers + nd->u.scr.timer += DIFF_TICK32(timer->gettick(),nd->u.scr.timertick); // Set 'timer' to the time that has passed since the beginning of the timers nd->u.scr.timertick = 0; // Set 'tick' to zero so that we know it's off. } @@ -688,7 +686,7 @@ void npc_timerevent_quit(struct map_session_data* sd) if( ev ) { int old_rid,old_timer; - unsigned int old_tick; + int64 old_tick; //Set timer related info. old_rid = (nd->u.scr.rid == sd->bl.id ? 0 : nd->u.scr.rid); // Detach rid if the last attached player logged off. @@ -715,9 +713,8 @@ void npc_timerevent_quit(struct map_session_data* sd) * Get the tick value of an NPC timer * If it's stopped, return stopped time *------------------------------------------*/ -int npc_gettimerevent_tick(struct npc_data* nd) -{ - int tick; +int64 npc_gettimerevent_tick(struct npc_data* nd) { + int64 tick; nullpo_ret(nd); // TODO: Get player attached timer's tick. Now we can just get it by using 'getnpctimer' inside OnTimer event. @@ -1790,6 +1787,9 @@ int npc_unload(struct npc_data* nd, bool single) { aFree(nd->path);/* remove now that no other instances exist */ } } + + if( single && nd->bl.m != -1 ) + map->remove_questinfo(nd->bl.m,nd); if( (nd->subtype == SHOP || nd->subtype == CASHSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao] aFree(nd->u.shop.shop_item); @@ -2013,6 +2013,53 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con } } +// Parse View +// Support for using Constants in place of NPC View IDs. +int npc_parseview(const char* w4, const char* start, const char* buffer, const char* filepath) { + int val = -1, i = 0; + char viewid[1024]; // Max size of name from const.txt, see script->read_constdb. + + // Extract view ID / constant + while (w4[i] != '\0') { + if (isspace(w4[i]) || w4[i] == '/' || w4[i] == ',') + break; + + i++; + } + + safestrncpy(viewid, w4, i+=1); + + // Check if view id is not an ID (only numbers). + if(!npc->viewisid(viewid)) + { + // Check if constant exists and get its value. + if(!script->get_constant(viewid, &val)) { + ShowWarning("npc_parseview: Invalid NPC constant '%s' specified in file '%s', line'%d'. Defaulting to INVISIBLE_CLASS. \n", viewid, filepath, strline(buffer,start-buffer)); + val = INVISIBLE_CLASS; + } + } else { + // NPC has an ID specified for view id. + val = atoi(w4); + } + + return val; +} + +// View is ID +// Checks if given view is an ID or constant. +bool npc_viewisid(const char * viewid) +{ + if(atoi(viewid) != -1) + { + // Loop through view, looking for non-numeric character. + while (*viewid) { + if (isdigit(*viewid++) == 0) return false; + } + } + + return true; +} + //Add then display an npc warp on map struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y) { int i, flag = 0; @@ -2220,7 +2267,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s nd->bl.y = y; nd->bl.id = npc->get_new_npc_id(); npc->parsename(nd, w3, start, buffer, filepath); - nd->class_ = m==-1?-1:atoi(w4); + nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); nd->speed = 200; ++npc_shop; @@ -2335,7 +2382,7 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f /// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>} /// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>,{<code>} const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, bool runOnInit) { - int x, y, dir = 0, m, xs = 0, ys = 0, class_ = 0; // [Valaris] thanks to fov + int x, y, dir = 0, m, xs = 0, ys = 0; // [Valaris] thanks to fov char mapname[32]; struct script_code *scriptroot; int i; @@ -2383,14 +2430,13 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* CREATE(nd, struct npc_data, 1); - if( sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3 ) + if( sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2 ) {// OnTouch area defined nd->u.scr.xs = xs; nd->u.scr.ys = ys; } else {// no OnTouch area - class_ = atoi(w4); nd->u.scr.xs = -1; nd->u.scr.ys = -1; } @@ -2401,7 +2447,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* nd->bl.y = y; npc->parsename(nd, w3, start, buffer, filepath); nd->bl.id = npc->get_new_npc_id(); - nd->class_ = class_; + nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); nd->speed = 200; nd->u.scr.script = scriptroot; nd->u.scr.label_list = label_list; @@ -2417,7 +2463,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* nd->dir = dir; npc->setcells(nd); map->addblock(&nd->bl); - if( class_ >= 0 ) { + if( nd->class_ >= 0 ) { status->set_viewdata(&nd->bl, nd->class_); if( map->list[nd->bl.m].users ) clif->spawn(&nd->bl); @@ -2465,7 +2511,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* /// npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY> const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) { - int x, y, dir, m, xs = -1, ys = -1, class_ = 0; + int x, y, dir, m, xs = -1, ys = -1; char mapname[32]; char srcname[128]; int i; @@ -2515,9 +2561,8 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch } if( type == WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2 );// <spanx>,<spany> - else if( type == SCRIPT && sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3);// <sprite id>,<triggerX>,<triggerY> - else if( type != WARP ) class_ = atoi(w4);// <sprite id> - else { + else if( type == SCRIPT && sscanf(w4, "%*d,%d,%d", &xs, &ys) == 2);// <sprite id>,<triggerX>,<triggerY> + else if( type == WARP ) { ShowError("npc_parse_duplicate: Invalid span format for duplicate warp in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); return end;// next line, try to continue } @@ -2530,7 +2575,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch nd->bl.y = y; npc->parsename(nd, w3, start, buffer, filepath); nd->bl.id = npc->get_new_npc_id(); - nd->class_ = class_; + nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); nd->speed = 200; nd->src_id = src_id; nd->bl.type = BL_NPC; @@ -2573,7 +2618,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch nd->dir = dir; npc->setcells(nd); map->addblock(&nd->bl); - if( class_ >= 0 ) { + if( nd->class_ >= 0 ) { status->set_viewdata(&nd->bl, nd->class_); if( map->list[nd->bl.m].users ) clif->spawn(&nd->bl); @@ -3439,6 +3484,10 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char map->list[m].short_damage_rate = (state) ? atoi(w4) : 100; } else if ( !strcmpi(w3,"long_damage_rate") ) { map->list[m].long_damage_rate = (state) ? atoi(w4) : 100; + } else if ( !strcmpi(w3,"src4instance") ) { + map->list[m].flag.src4instance = (state) ? 1 : 0; + } else if ( !strcmpi(w3,"nocashshop") ) { + map->list[m].flag.nocashshop = (state) ? 1 : 0; } else ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer)); @@ -3784,10 +3833,8 @@ int npc_reload(void) { npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); itemdb->name_constants(); - - for(i = 0; i < instance->instances; i++) { - instance->destroy(i); - } + + instance->reload(); map->zone_init(); @@ -4043,6 +4090,8 @@ void npc_defaults(void) { npc->addsrcfile = npc_addsrcfile; npc->delsrcfile = npc_delsrcfile; npc->parsename = npc_parsename; + npc->parseview = npc_parseview; + npc->viewisid = npc_viewisid; npc->add_warp = npc_add_warp; npc->parse_warp = npc_parse_warp; npc->parse_shop = npc_parse_shop; diff --git a/src/map/npc.h b/src/map/npc.h index f809cb19c..5ec201e55 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -35,7 +35,7 @@ struct npc_data { char exname[NAME_LENGTH+1];// unique npc name int chat_id; int touching_id; - unsigned int next_walktime; + int64 next_walktime; uint8 dir; unsigned size : 2; @@ -54,7 +54,7 @@ struct npc_data { short xs,ys; // OnTouch area radius int guild_id; int timer,timerid,timeramount,rid; - unsigned int timertick; + int64 timertick; struct npc_timerevent_list *timer_event; int label_list_num; struct npc_label_list *label_list; @@ -92,7 +92,7 @@ enum actor_classes { #define MAX_NPC_CLASS 1000 // New NPC range #define MAX_NPC_CLASS2_START 10000 -#define MAX_NPC_CLASS2_END 10049 +#define MAX_NPC_CLASS2_END 10070 //Checks if a given id is a valid npc id. [Skotlex] //Since new npcs are added all the time, the max valid value is the one before the first mob (Scorpion = 1001) @@ -160,14 +160,14 @@ struct npc_interface { int (*event_do) (const char *name); int (*event_doall_id) (const char *name, int rid); int (*event_doall) (const char *name); - int (*event_do_clock) (int tid, unsigned int tick, int id, intptr_t data); + int (*event_do_clock) (int tid, int64 tick, int id, intptr_t data); void (*event_do_oninit) (void); int (*timerevent_export) (struct npc_data *nd, int i); - int (*timerevent) (int tid, unsigned int tick, int id, intptr_t data); + int (*timerevent) (int tid, int64 tick, int id, intptr_t data); int (*timerevent_start) (struct npc_data *nd, int rid); int (*timerevent_stop) (struct npc_data *nd); void (*timerevent_quit) (struct map_session_data *sd); - int (*gettimerevent_tick) (struct npc_data *nd); + int64 (*gettimerevent_tick) (struct npc_data *nd); int (*settimerevent_tick) (struct npc_data *nd, int newtimer); int (*event) (struct map_session_data *sd, const char *eventname, int ontouch); int (*touch_areanpc_sub) (struct block_list *bl, va_list ap); @@ -197,6 +197,8 @@ struct npc_interface { void (*addsrcfile) (const char *name); void (*delsrcfile) (const char *name); void (*parsename) (struct npc_data *nd, const char *name, const char *start, const char *buffer, const char *filepath); + int (*parseview) (const char *w4, const char *start, const char *buffer, const char *filepath); + bool (*viewisid) (const char *viewid); struct npc_data* (*add_warp) (char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y); const char* (*parse_warp) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath); const char* (*parse_shop) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath); @@ -229,7 +231,7 @@ struct npc_interface { /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] **/ - int (*secure_timeout_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*secure_timeout_timer) (int tid, int64 tick, int id, intptr_t data); }; struct npc_interface *npc; diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 9d7282c92..813aebee0 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -9,12 +9,6 @@ #include "../common/mmo.h" /** - * structs for data - */ -struct EQUIPSLOTINFO { - unsigned short card[4]; -}; -/** * **/ enum packet_headers { @@ -111,12 +105,161 @@ enum packet_headers { #else dropflooritemType = 0x9e, #endif +#if PACKETVER >= 20120925 + inventorylistnormalType = 0x991, +#elif PACKETVER >= 20080102 + inventorylistnormalType = 0x2e8, +#elif PACKETVER >= 20071002 + inventorylistnormalType = 0x1ee, +#else + inventorylistnormalType = 0xa3, +#endif +#if PACKETVER >= 20120925 + inventorylistequipType = 0x992, +#elif PACKETVER >= 20080102 + inventorylistequipType = 0x2d0, +#elif PACKETVER >= 20071002 + inventorylistequipType = 0x295, +#else + inventorylistequipType = 0xa4, +#endif +#if PACKETVER >= 20120925 + storagelistnormalType = 0x995, +#elif PACKETVER >= 20080102 + storagelistnormalType = 0x2ea, +#elif PACKETVER >= 20071002 + storagelistnormalType = 0x295, +#else + storagelistnormalType = 0xa5, +#endif +#if PACKETVER >= 20120925 + storagelistequipType = 0x996, +#elif PACKETVER >= 20080102 + storagelistequipType = 0x2d1, +#elif PACKETVER >= 20071002 + storagelistequipType = 0x296, +#else + storagelistequipType = 0xa6, +#endif +#if PACKETVER >= 20120925 + cartlistnormalType = 0x993, +#elif PACKETVER >= 20080102 + cartlistnormalType = 0x2e9, +#elif PACKETVER >= 20071002 + cartlistnormalType = 0x1ef, +#else + cartlistnormalType = 0x123, +#endif +#if PACKETVER >= 20120925 + cartlistequipType = 0x994, +#elif PACKETVER >= 20080102 + cartlistequipType = 0x2d2, +#elif PACKETVER >= 20071002 + cartlistequipType = 0x297, +#else + cartlistequipType = 0x122, +#endif +#if PACKETVER >= 20120925 + equipitemType = 0x998, +#else + equipitemType = 0xa9, +#endif +#if PACKETVER >= 20120925 + equipitemackType = 0x999, +#else + equipitemackType = 0xaa, +#endif +#if PACKETVER >= 20120925 + unequipitemackType = 0x99a, +#else + unequipitemackType = 0xac, +#endif +#if PACKETVER >= 20120925 + viewequipackType = 0x997, +#elif PACKETVER >= 20101124 + viewequipackType = 0x859, +#else + viewequipackType = 0x2d7, +#endif monsterhpType = 0x977, maptypeproperty2Type = 0x99b, }; #pragma pack(push, 1) +/** + * structs for data + */ +struct EQUIPSLOTINFO { + unsigned short card[4]; +} __attribute__((packed)); + +struct NORMALITEM_INFO { + short index; + unsigned short ITID; + unsigned char type; +#if PACKETVER < 20120925 + uint8 IsIdentified; +#endif + short count; +#if PACKETVER >= 20120925 + unsigned int WearState; +#else + unsigned short WearState; +#endif +#if PACKETVER >= 5 + struct EQUIPSLOTINFO slot; +#endif +#if PACKETVER >= 20080102 + int HireExpireDate; +#endif +#if PACKETVER >= 20120925 + struct { + unsigned char IsIdentified : 1; + unsigned char PlaceETCTab : 1; + unsigned char SpareBits : 6; + } Flag; +#endif +} __attribute__((packed)); + +struct EQUIPITEM_INFO { + short index; + unsigned short ITID; + unsigned char type; +#if PACKETVER < 20120925 + uint8 IsIdentified; +#endif +#if PACKETVER >= 20120925 + unsigned int location; + unsigned int WearState; +#else + unsigned short location; + unsigned short WearState; +#endif +#if PACKETVER < 20120925 + uint8 IsDamaged; +#endif + unsigned char RefiningLevel; + struct EQUIPSLOTINFO slot; +#if PACKETVER >= 20071002 + int HireExpireDate; +#endif +#if PACKETVER >= 20080102 + unsigned short bindOnEquipType; +#endif +#if PACKETVER >= 20100629 + unsigned short wItemSpriteNumber; +#endif +#if PACKETVER >= 20120925 + struct { + unsigned char IsIdentified : 1; + unsigned char IsDamaged : 1; + unsigned char PlaceETCTab : 1; + unsigned char SpareBits : 5; + } Flag; +#endif +} __attribute__((packed)); + struct packet_authok { short PacketType; unsigned int startTime; @@ -147,8 +290,8 @@ struct packet_additem { unsigned short Index; unsigned short count; unsigned short nameid; - bool IsIdentified; - bool IsDamaged; + uint8 IsIdentified; + uint8 IsDamaged; unsigned char refiningLevel; struct EQUIPSLOTINFO slot; #if PACKETVER >= 20120925 @@ -173,7 +316,7 @@ struct packet_dropflooritem { #if PACKETVER >= 20130000 /* not sure date */ unsigned short type; #endif - bool IsIdentified; + uint8 IsIdentified; short xPos; short yPos; unsigned char subX; @@ -205,7 +348,7 @@ struct packet_idle_unit2 { short GEmblemVer; short honor; short virtue; - bool isPKModeON; + uint8 isPKModeON; unsigned char sex; unsigned char PosDir[3]; unsigned char xSize; @@ -233,7 +376,7 @@ struct packet_spawn_unit2 { short headpalette; short bodypalette; short headDir; - bool isPKModeON; + uint8 isPKModeON; unsigned char sex; unsigned char PosDir[3]; unsigned char xSize; @@ -282,7 +425,7 @@ struct packet_spawn_unit { #else short virtue; #endif - bool isPKModeON; + uint8 isPKModeON; unsigned char sex; unsigned char PosDir[3]; unsigned char xSize; @@ -343,7 +486,7 @@ struct packet_unit_walking { #else short virtue; #endif - bool isPKModeON; + uint8 isPKModeON; unsigned char sex; unsigned char MoveData[6]; unsigned char xSize; @@ -401,7 +544,7 @@ struct packet_idle_unit { #else short virtue; #endif - bool isPKModeON; + uint8 isPKModeON; unsigned char sex; unsigned char PosDir[3]; unsigned char xSize; @@ -578,6 +721,90 @@ struct packet_banking_withdraw_ack { int Balance; } __attribute__((packed)); +struct packet_itemlist_normal { + short PacketType; + short PacketLength; + struct NORMALITEM_INFO list[MAX_ITEMLIST]; +} __attribute__((packed)); + +struct packet_itemlist_equip { + short PacketType; + short PacketLength; + struct EQUIPITEM_INFO list[MAX_ITEMLIST]; +} __attribute__((packed)); + +struct packet_storelist_normal { + short PacketType; + short PacketLength; +#if PACKETVER >= 20120925 + char name[NAME_LENGTH]; +#endif + struct NORMALITEM_INFO list[MAX_ITEMLIST]; +} __attribute__((packed)); + +struct packet_storelist_equip { + short PacketType; + short PacketLength; +#if PACKETVER >= 20120925 + char name[NAME_LENGTH]; +#endif + struct EQUIPITEM_INFO list[MAX_ITEMLIST]; +} __attribute__((packed)); + +struct packet_equip_item { + short PacketType; + unsigned short index; +#if PACKETVER >= 20120925 + unsigned int wearLocation; +#else + unsigned short wearLocation; +#endif +} __attribute__((packed)); + +struct packet_equipitem_ack { + short PacketType; + unsigned short index; +#if PACKETVER >= 20120925 + unsigned int wearLocation; +#else + unsigned short wearLocation; +#endif +#if PACKETVER >= 20100629 + unsigned short wItemSpriteNumber; +#endif + unsigned char result; +} __attribute__((packed)); + +struct packet_unequipitem_ack { + short PacketType; + unsigned short index; +#if PACKETVER >= 20120925 + unsigned int wearLocation; +#else + unsigned short wearLocation; +#endif + unsigned char result; +} __attribute__((packed)); + +struct packet_viewequip_ack { + short PacketType; + short PacketLength; + char characterName[NAME_LENGTH]; + short job; + short head; + short accessory; + short accessory2; + short accessory3; +#if PACKETVER >= 20101124 + short robe; +#endif + short headpalette; + short bodypalette; + unsigned char sex; + struct EQUIPITEM_INFO list[MAX_INVENTORY]; +} __attribute__((packed)); + + #pragma pack(pop) #endif /* _PACKETS_STRUCT_H_ */ diff --git a/src/map/party.c b/src/map/party.c index 904110452..ab05c23f7 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -831,8 +831,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id return 0; } -int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) -{ +int party_send_xy_timer(int tid, int64 tick, int id, intptr_t data) { struct party_data* p; DBIterator *iter = db_iterator(party->db); diff --git a/src/map/party.h b/src/map/party.h index 208edb846..ab14d1a31 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -123,7 +123,7 @@ struct party_interface { /* */ int (*vforeachsamemap) (int (*func)(struct block_list *,va_list),struct map_session_data *sd,int range, va_list ap); int (*foreachsamemap) (int (*func)(struct block_list *,va_list),struct map_session_data *sd,int range,...); - int (*send_xy_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data); void (*fill_member) (struct party_member* member, struct map_session_data* sd, unsigned int leader); TBL_PC* (*sd_check) (int party_id, int account_id, int char_id); void (*check_state) (struct party_data *p); diff --git a/src/map/pc.c b/src/map/pc.c index 90a3db853..d98393739 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -117,7 +117,7 @@ bool pc_should_log_commands(struct map_session_data *sd) return pc_group_should_log_commands(sd->group); } -int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data) { +int pc_invincible_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd; if( (sd=(struct map_session_data *)map->id2sd(id)) == NULL || sd->bl.type!=BL_PC ) @@ -155,7 +155,7 @@ void pc_delinvincibletimer(struct map_session_data* sd) } } -int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr_t data) { +int pc_spiritball_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd; int i; @@ -419,7 +419,7 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) { /*========================================== Rental System *------------------------------------------*/ -int pc_inventory_rental_end(int tid, unsigned int tick, int id, intptr_t data) { +int pc_inventory_rental_end(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd = map->id2sd(id); if( sd == NULL ) return 0; @@ -443,11 +443,78 @@ int pc_inventory_rental_clear(struct map_session_data *sd) return 1; } +/* assumes i is valid (from default areas where it is called, it is) */ +void pc_rental_expire(struct map_session_data *sd, int i) { + short nameid = sd->status.inventory[i].nameid; + /* Soon to be dropped, we got plans to integrate it with item db */ + switch( nameid ) { + case ITEMID_REINS_OF_MOUNT: + status_change_end(&sd->bl,SC_ALL_RIDING,INVALID_TIMER); + break; + case ITEMID_LOVE_ANGEL: + if( sd->status.font == 1 ) { + sd->status.font = 0; + clif->font(sd); + } + break; + case ITEMID_SQUIRREL: + if( sd->status.font == 2 ) { + sd->status.font = 0; + clif->font(sd); + } + break; + case ITEMID_GOGO: + if( sd->status.font == 3 ) { + sd->status.font = 0; + clif->font(sd); + } + break; + case ITEMID_PICTURE_DIARY: + if( sd->status.font == 4 ) { + sd->status.font = 0; + clif->font(sd); + } + break; + case ITEMID_MINI_HEART: + if( sd->status.font == 5 ) { + sd->status.font = 0; + clif->font(sd); + } + break; + case ITEMID_NEWCOMER: + if( sd->status.font == 6 ) { + sd->status.font = 0; + clif->font(sd); + } + break; + case ITEMID_KID: + if( sd->status.font == 7 ) { + sd->status.font = 0; + clif->font(sd); + } + break; + case ITEMID_MAGIC_CASTLE: + if( sd->status.font == 8 ) { + sd->status.font = 0; + clif->font(sd); + } + break; + case ITEMID_BULGING_HEAD: + if( sd->status.font == 9 ) { + sd->status.font = 0; + clif->font(sd); + } + break; + } + + clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); +} void pc_inventory_rentals(struct map_session_data *sd) { int i, c = 0; - unsigned int expire_tick, next_tick = UINT_MAX; + int64 expire_tick, next_tick = INT64_MAX; for( i = 0; i < MAX_INVENTORY; i++ ) { // Check for Rentals on Inventory @@ -457,14 +524,9 @@ void pc_inventory_rentals(struct map_session_data *sd) continue; if( sd->status.inventory[i].expire_time <= time(NULL) ) { - if( sd->status.inventory[i].nameid == ITEMID_REINS_OF_MOUNT - && sd->sc.data[SC_ALL_RIDING] ) { - status_change_end(&sd->bl,SC_ALL_RIDING,INVALID_TIMER); - } - clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid); - pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); + pc->rental_expire(sd,i); } else { - expire_tick = (unsigned int)(sd->status.inventory[i].expire_time - time(NULL)) * 1000; + expire_tick = (int64)(sd->status.inventory[i].expire_time - time(NULL)) * 1000; clif->rental_time(sd->fd, sd->status.inventory[i].nameid, (int)(expire_tick / 1000)); next_tick = min(expire_tick, next_tick); c++; @@ -611,6 +673,8 @@ int pc_equippoint(struct map_session_data *sd,int n) if(ep == EQP_HAND_R && (pc->checkskill(sd,AS_LEFT) > 0 || (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN || (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO))//Kagerou and Oboro can dual wield daggers. [Rytech] return EQP_ARMS; + if( ep == EQP_SHADOW_SHIELD )/* are there conditions for those? */ + return EQP_SHADOW_WEAPON|EQP_SHADOW_SHIELD; } return ep; } @@ -927,7 +991,7 @@ int pc_isequip(struct map_session_data *sd,int n) *------------------------------------------*/ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers) { int i; - unsigned long tick = timer->gettick(); + int64 tick = timer->gettick(); uint32 ip = session[sd->fd]->client_addr; sd->login_id2 = login_id2; @@ -1267,8 +1331,6 @@ int pc_reg_received(struct map_session_data *sd) clif->pLoadEndAck(sd->fd, sd); } - pc->inventory_rentals(sd); - if( sd->sc.option & OPTION_INVISIBLE ) { sd->vd.class_ = INVISIBLE_CLASS; clif->message(sd->fd, msg_txt(11)); // Invisible: On @@ -1971,7 +2033,7 @@ int pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus) return 0; } -int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data) { +int pc_endautobonus(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd = map->id2sd(id); struct s_autobonus *autobonus = (struct s_autobonus *)data; @@ -3927,8 +3989,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l /* rental item check */ if( item_data->expire_time ) { if( time(NULL) > item_data->expire_time ) { - clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid); - pc->delitem(sd, i, sd->status.inventory[i].amount, 1, 0, LOG_TYPE_OTHER); + pc->rental_expire(sd,i); } else { int seconds = (int)( item_data->expire_time - time(NULL) ); clif->rental_time(sd->fd, sd->status.inventory[i].nameid, seconds); @@ -4026,7 +4087,7 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount) int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem) { int flag=0; - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); struct map_session_data *first_sd = NULL,*second_sd = NULL,*third_sd = NULL; struct party_data *p=NULL; @@ -4276,7 +4337,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) * 1 = success *------------------------------------------*/ int pc_useitem(struct map_session_data *sd,int n) { - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); int amount, nameid, i; struct script_code *item_script; @@ -4343,7 +4404,7 @@ int pc_useitem(struct map_session_data *sd,int n) { if( i < MAX_ITEMDELAYS ) { if( sd->item_delay[i].nameid ) {// found if( DIFF_TICK(sd->item_delay[i].tick, tick) > 0 ) { - int e_tick = DIFF_TICK(sd->item_delay[i].tick, tick)/1000; + int e_tick = (int)(DIFF_TICK(sd->item_delay[i].tick, tick)/1000); clif->msgtable_num(sd->fd, 0x746, e_tick + 1); // [%d] seconds left until you can use return 0; // Delay has not expired yet } @@ -4791,6 +4852,14 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y stop = true; } } + /* we hit a instance, if empty we populate the spawn data */ + if( map->list[m].instance_id >= 0 && instance->list[map->list[m].instance_id].respawn.map == 0 && + instance->list[map->list[m].instance_id].respawn.x == 0 && + instance->list[map->list[m].instance_id].respawn.y == 0) { + instance->list[map->list[m].instance_id].respawn.map = mapindex; + instance->list[map->list[m].instance_id].respawn.x = x; + instance->list[map->list[m].instance_id].respawn.y = y; + } } sd->state.changemap = (sd->mapindex != mapindex); @@ -5634,7 +5703,7 @@ const char* job_name(int class_) } } -int pc_follow_timer(int tid, unsigned int tick, int id, intptr_t data) { +int pc_follow_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd; struct block_list *tbl; @@ -6592,7 +6661,7 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype) clif->resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet. } -int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data) { +int pc_respawn_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd = map->id2sd(id); if( sd != NULL ) { @@ -6639,7 +6708,7 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h *------------------------------------------*/ int pc_dead(struct map_session_data *sd,struct block_list *src) { int i=0,j=0,k=0; - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); for(k = 0; k < 5; k++) if (sd->devotion[k]){ @@ -8242,7 +8311,7 @@ int pc_setregistry_str(struct map_session_data *sd,const char *reg,const char *v /*========================================== * Exec eventtimer for player sd (retrieved from map_session (id)) *------------------------------------------*/ -int pc_eventtimer(int tid, unsigned int tick, int id, intptr_t data) { +int pc_eventtimer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd=map->id2sd(id); char *p = (char *)data; int i; @@ -8518,13 +8587,13 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) nullpo_ret(sd); if( n < 0 || n >= MAX_INVENTORY ) { - clif->equipitemack(sd,0,0,0); + clif->equipitemack(sd,0,0,EIA_FAIL); return 0; } if( DIFF_TICK(sd->canequip_tick,timer->gettick()) > 0 ) { - clif->equipitemack(sd,n,0,0); + clif->equipitemack(sd,n,0,EIA_FAIL); return 0; } @@ -8535,13 +8604,13 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) ShowInfo("equip %d(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos); if(!pc->isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris] // FIXME: pc->isequip: equip level failure uses 2 instead of 0 - clif->equipitemack(sd,n,0,0); // fail + clif->equipitemack(sd,n,0,EIA_FAIL); // fail return 0; } if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAY_NIGHT_FEVER]) { - clif->equipitemack(sd,n,0,0); // fail + clif->equipitemack(sd,n,0,EIA_FAIL); // fail return 0; } @@ -8581,7 +8650,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) clif->arrow_fail(sd,3); } else - clif->equipitemack(sd,n,pos,1); + clif->equipitemack(sd,n,pos,EIA_SUCCESS); sd->status.inventory[n].equip=pos; @@ -8730,20 +8799,20 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { nullpo_ret(sd); if( n < 0 || n >= MAX_INVENTORY ) { - clif->unequipitemack(sd,0,0,0); + clif->unequipitemack(sd,0,0,UIA_FAIL); return 0; } // if player is berserk then cannot unequip if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAY_NIGHT_FEVER])) { - clif->unequipitemack(sd,n,0,0); + clif->unequipitemack(sd,n,0,UIA_FAIL); return 0; } if( !(flag&2) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] ) { - clif->unequipitemack(sd,n,0,0); + clif->unequipitemack(sd,n,0,UIA_FAIL); return 0; } @@ -8751,7 +8820,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { ShowInfo("unequip %d %x:%x\n",n,pc->equippoint(sd,n),sd->status.inventory[n].equip); if(!sd->status.inventory[n].equip){ //Nothing to unequip - clif->unequipitemack(sd,n,0,0); + clif->unequipitemack(sd,n,0,UIA_FAIL); return 0; } for(i=0;i<EQI_MAX;i++) { @@ -8813,7 +8882,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { clif->changelook(&sd->bl,LOOK_ROBE,sd->status.robe); } - clif->unequipitemack(sd,n,sd->status.inventory[n].equip,1); + clif->unequipitemack(sd,n,sd->status.inventory[n].equip,UIA_SUCCESS); if((sd->status.inventory[n].equip & EQP_ARMS) && sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_TK_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!) @@ -9003,7 +9072,7 @@ int pc_calc_pvprank(struct map_session_data *sd) { /*========================================== * Calculate next sd ranking calculation from config *------------------------------------------*/ -int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr_t data) { +int pc_calc_pvprank_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd; sd=map->id2sd(id); @@ -9216,10 +9285,9 @@ int pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y) } /*========================================== - * Save 1 player data at autosave intervalle + * Save 1 player data at autosave intervall *------------------------------------------*/ -int pc_autosave(int tid, unsigned int tick, int id, intptr_t data) -{ +int pc_autosave(int tid, int64 tick, int id, intptr_t data) { int interval; struct s_mapiterator* iter; struct map_session_data* sd; @@ -9270,7 +9338,7 @@ int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) { * timer to do the day [Yor] * data: 0 = called by timer, 1 = gmcommand/script *------------------------------------------------*/ -int map_day_timer(int tid, unsigned int tick, int id, intptr_t data) { +int map_day_timer(int tid, int64 tick, int id, intptr_t data) { char tmp_soutput[1024]; if (data == 0 && battle_config.day_duration <= 0) // if we want a day @@ -9290,7 +9358,7 @@ int map_day_timer(int tid, unsigned int tick, int id, intptr_t data) { * timer to do the night [Yor] * data: 0 = called by timer, 1 = gmcommand/script *------------------------------------------------*/ -int map_night_timer(int tid, unsigned int tick, int id, intptr_t data) { +int map_night_timer(int tid, int64 tick, int id, intptr_t data) { char tmp_soutput[1024]; if (data == 0 && battle_config.night_duration <= 0) // if we want a night @@ -9368,7 +9436,7 @@ bool pc_can_use_command(struct map_session_data *sd, const char *command) { return atcommand->can_use(sd,command); } -int pc_charm_timer(int tid, unsigned int tick, int id, intptr_t data) { +int pc_charm_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd; int i, type; @@ -10129,6 +10197,10 @@ void pc_bank_withdraw(struct map_session_data *sd, int money) { clif->bank_withdraw(sd,BWA_SUCCESS); } } +/* status change data arrived from char-server */ +void pc_scdata_received(struct map_session_data *sd) { + pc->inventory_rentals(sd); +} /*========================================== * pc Init/Terminate @@ -10191,7 +10263,7 @@ void pc_defaults(void) { { SG_MOON_ANGER, SG_MOON_BLESS, SG_MOON_COMFORT, "PC_FEEL_MOON", "PC_HATE_MOB_MOON", is_day_of_moon }, { SG_STAR_ANGER, SG_STAR_BLESS, SG_STAR_COMFORT, "PC_FEEL_STAR", "PC_HATE_MOB_STAR", is_day_of_star } }; - unsigned short equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_GARMENT,EQP_AMMO}; + unsigned int equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_GARMENT,EQP_AMMO, EQP_SHADOW_ARMOR, EQP_SHADOW_WEAPON, EQP_SHADOW_SHIELD, EQP_SHADOW_SHOES, EQP_SHADOW_ACC_R, EQP_SHADOW_ACC_L }; pc = &pc_s; @@ -10456,4 +10528,7 @@ void pc_defaults(void) { pc->bank_withdraw = pc_bank_withdraw; pc->bank_deposit = pc_bank_deposit; + + pc->rental_expire = pc_rental_expire; + pc->scdata_received = pc_scdata_received; } diff --git a/src/map/pc.h b/src/map/pc.h index bb7bff375..f1535941c 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -48,6 +48,12 @@ enum equip_index { EQI_COSTUME_LOW, EQI_COSTUME_GARMENT, EQI_AMMO, + EQI_SHADOW_ARMOR, + EQI_SHADOW_WEAPON, + EQI_SHADOW_SHIELD, + EQI_SHADOW_SHOES, + EQI_SHADOW_ACC_R, + EQI_SHADOW_ACC_L, EQI_MAX }; struct weapon_data { @@ -172,6 +178,7 @@ struct map_session_data { unsigned int workinprogress : 3; // 1 = disable skill/item, 2 = disable npc interaction, 3 = disable both unsigned int hold_recalc : 1; unsigned int snovice_call_flag : 3; //Summon Angel (stage 1~3) + unsigned int hpmeter_visible : 1; } state; struct { unsigned char no_weapon_damage, no_magic_damage, no_misc_damage; @@ -211,10 +218,10 @@ struct map_session_data { char npc_str[CHATBOX_SIZE]; // for passing npc input box text to script engine int npc_timer_id; //For player attached npc timers. [Skotlex] unsigned int chatID; - time_t idletime; - struct{ + int64 idletime; + struct { int npc_id; - unsigned int timeout; + int64 timeout; } progressbar; //Progress Bar [Inkfish] struct{ char name[NAME_LENGTH]; @@ -226,21 +233,21 @@ struct map_session_data { uint16 skill_id_old,skill_lv_old; uint16 skill_id_dance,skill_lv_dance; short cook_mastery; // range: [0,1999] [Inkfish] - unsigned char blockskill[MAX_SKILL]; + bool blockskill[MAX_SKILL]; int cloneskill_id, reproduceskill_id; int menuskill_id, menuskill_val, menuskill_val2; int invincible_timer; - unsigned int canlog_tick; - unsigned int canuseitem_tick; // [Skotlex] - unsigned int canusecashfood_tick; - unsigned int canequip_tick; // [Inkfish] - unsigned int cantalk_tick; - unsigned int canskill_tick; // used to prevent abuse from no-delay ACT files - unsigned int cansendmail_tick; // [Mail System Flood Protection] - unsigned int ks_floodprotect_tick; // [Kill Steal Protection] + int64 canlog_tick; + int64 canuseitem_tick; // [Skotlex] + int64 canusecashfood_tick; + int64 canequip_tick; // [Inkfish] + int64 cantalk_tick; + int64 canskill_tick; /// used to prevent abuse from no-delay ACT files + int64 cansendmail_tick; /// Mail System Flood Protection + int64 ks_floodprotect_tick; /// [Kill Steal Protection] struct { short nameid; - unsigned int tick; + int64 tick; } item_delay[MAX_ITEMDELAYS]; // [Paradox924X] short weapontype1,weapontype2; short disguise; // [Valaris] @@ -443,7 +450,6 @@ struct map_session_data { const char* debug_func; unsigned int bg_id; - unsigned short user_font; /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] @@ -461,7 +467,7 @@ struct map_session_data { * @info * - It is updated on every NPC iteration as mentioned above **/ - unsigned int npc_idle_tick; + int64 npc_idle_tick; /* */ enum npc_timeout_type npc_idle_type; #endif @@ -486,7 +492,7 @@ struct map_session_data { bool stealth; unsigned char fontcolor; unsigned int fontcolor_tid; - unsigned int hchsysch_tick; + int64 hchsysch_tick; /* [Ind/Hercules] */ struct sc_display_entry **sc_display; @@ -527,21 +533,28 @@ struct map_session_data { //Equip position constants enum equip_pos { - EQP_HEAD_LOW = 0x0001, - EQP_HEAD_MID = 0x0200, //512 - EQP_HEAD_TOP = 0x0100, //256 - EQP_HAND_R = 0x0002, //2 - EQP_HAND_L = 0x0020, //32 - EQP_ARMOR = 0x0010, //16 - EQP_SHOES = 0x0040, //64 - EQP_GARMENT = 0x0004, //4 - EQP_ACC_L = 0x0008, //8 - EQP_ACC_R = 0x0080, //128 - EQP_COSTUME_HEAD_TOP = 0x0400, //1024 - EQP_COSTUME_HEAD_MID = 0x0800, //2048 - EQP_COSTUME_HEAD_LOW = 0x1000, //4096 - EQP_COSTUME_GARMENT = 0x2000, //8192 - EQP_AMMO = 0x8000, //32768 + EQP_HEAD_LOW = 0x000001, + EQP_HEAD_MID = 0x000200, //512 + EQP_HEAD_TOP = 0x000100, //256 + EQP_HAND_R = 0x000002, //2 + EQP_HAND_L = 0x000020, //32 + EQP_ARMOR = 0x000010, //16 + EQP_SHOES = 0x000040, //64 + EQP_GARMENT = 0x000004, //4 + EQP_ACC_L = 0x000008, //8 + EQP_ACC_R = 0x000080, //128 + EQP_COSTUME_HEAD_TOP = 0x000400, //1024 + EQP_COSTUME_HEAD_MID = 0x000800, //2048 + EQP_COSTUME_HEAD_LOW = 0x001000, //4096 + EQP_COSTUME_GARMENT = 0x002000, //8192 + //UNUSED_COSTUME_FLOOR = 0x004000, //16384 + EQP_AMMO = 0x008000, //32768 + EQP_SHADOW_ARMOR = 0x010000, //65536 + EQP_SHADOW_WEAPON = 0x020000, //131072 + EQP_SHADOW_SHIELD = 0x040000, //262144 + EQP_SHADOW_SHOES = 0x080000, //524288 + EQP_SHADOW_ACC_R = 0x100000, //1048576 + EQP_SHADOW_ACC_L = 0x200000, //2097152 }; #define EQP_WEAPON EQP_HAND_R @@ -696,7 +709,7 @@ enum { ADDITEM_EXIST , ADDITEM_NEW , ADDITEM_OVERAMOUNT }; * All cooldowns are reset when server is restarted. **/ struct item_cd { - unsigned int tick[MAX_ITEMDELAYS];//tick + int64 tick[MAX_ITEMDELAYS];//tick short nameid[MAX_ITEMDELAYS];//skill id }; @@ -719,7 +732,7 @@ struct pc_interface { #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) unsigned int level_penalty[3][RC_MAX][MAX_LEVEL*2+1]; #endif - unsigned short equip_pos[EQI_MAX]; + unsigned int equip_pos[EQI_MAX]; /* */ struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE]; struct fame_list smith_fame_list[MAX_FAME_LIST]; @@ -797,7 +810,7 @@ struct pc_interface { int (*addautobonus) (struct s_autobonus *bonus,char max,const char *bonus_script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned short pos,bool onskill); int (*exeautobonus) (struct map_session_data* sd,struct s_autobonus *bonus); - int (*endautobonus) (int tid, unsigned int tick, int id, intptr_t data); + int (*endautobonus) (int tid, int64 tick, int id, intptr_t data); int (*delautobonus) (struct map_session_data* sd,struct s_autobonus *bonus,char max,bool restore); int (*bonus) (struct map_session_data *sd,int type,int val); @@ -879,7 +892,7 @@ struct pc_interface { int (*addeventtimercount) (struct map_session_data *sd,const char *name,int tick); int (*calc_pvprank) (struct map_session_data *sd); - int (*calc_pvprank_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*calc_pvprank_timer) (int tid, int64 tick, int id, intptr_t data); int (*ismarried) (struct map_session_data *sd); int (*marriage) (struct map_session_data *sd,struct map_session_data *dstsd); @@ -910,8 +923,8 @@ struct pc_interface { int (*set_hate_mob) (struct map_session_data *sd, int pos, struct block_list *bl); int (*readdb) (void); - int (*map_day_timer) (int tid, unsigned int tick, int id, intptr_t data); // by [yor] - int (*map_night_timer) (int tid, unsigned int tick, int id, intptr_t data); // by [yor] + int (*map_day_timer) (int tid, int64 tick, int id, intptr_t data); // by [yor] + int (*map_night_timer) (int tid, int64 tick, int id, intptr_t data); // by [yor] // Rental System void (*inventory_rentals) (struct map_session_data *sd); int (*inventory_rental_clear) (struct map_session_data *sd); @@ -935,10 +948,10 @@ struct pc_interface { int (*level_penalty_mod) (int diff, unsigned char race, unsigned short mode, int type); int (*calc_skillpoint) (struct map_session_data* sd); - int (*invincible_timer) (int tid, unsigned int tick, int id, intptr_t data); - int (*spiritball_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*invincible_timer) (int tid, int64 tick, int id, intptr_t data); + int (*spiritball_timer) (int tid, int64 tick, int id, intptr_t data); int (*check_banding) ( struct block_list *bl, va_list ap ); - int (*inventory_rental_end) (int tid, unsigned int tick, int id, intptr_t data); + int (*inventory_rental_end) (int tid, int64 tick, int id, intptr_t data); void (*check_skilltree) (struct map_session_data *sd, int skill_id); int (*bonus_autospell) (struct s_autospell *spell, int max, short id, short lv, short rate, short flag, short card_id); int (*bonus_autospell_onskill) (struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, short card_id); @@ -946,16 +959,16 @@ struct pc_interface { int (*bonus_addeff_onskill) (struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill_id, unsigned char target); int (*bonus_item_drop) (struct s_add_drop *drop, const short max, short id, short group, int race, int rate); void (*calcexp) (struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src); - int (*respawn_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*respawn_timer) (int tid, int64 tick, int id, intptr_t data); int (*jobchange_killclone) (struct block_list *bl, va_list ap); int (*getstat) (struct map_session_data* sd, int type); int (*setstat) (struct map_session_data* sd, int type, int val); - int (*eventtimer) (int tid, unsigned int tick, int id, intptr_t data); + int (*eventtimer) (int tid, int64 tick, int id, intptr_t data); int (*daynight_timer_sub) (struct map_session_data *sd,va_list ap); - int (*charm_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*charm_timer) (int tid, int64 tick, int id, intptr_t data); bool (*readdb_levelpenalty) (char* fields[], int columns, int current); - int (*autosave) (int tid, unsigned int tick, int id, intptr_t data); - int (*follow_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*autosave) (int tid, int64 tick, int id, intptr_t data); + int (*follow_timer) (int tid, int64 tick, int id, intptr_t data); void (*read_skill_tree) (void); int (*isUseitem) (struct map_session_data *sd,int n); int (*show_steal) (struct block_list *bl,va_list ap); @@ -965,6 +978,9 @@ struct pc_interface { void (*bank_deposit) (struct map_session_data *sd, int money); void (*bank_withdraw) (struct map_session_data *sd, int money); + + void (*rental_expire) (struct map_session_data *sd, int i); + void (*scdata_received) (struct map_session_data *sd); }; struct pc_interface *pc; diff --git a/src/map/pet.c b/src/map/pet.c index 023059a6b..7dcf06c02 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -186,7 +186,7 @@ int pet_sc_check(struct map_session_data *sd, int type) return 0; } -int pet_hungry(int tid, unsigned int tick, int id, intptr_t data) { +int pet_hungry(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd; struct pet_data *pd; int interval; @@ -656,7 +656,7 @@ int pet_equipitem(struct map_session_data *sd,int index) { nameid = sd->status.inventory[index].nameid; if(pd->petDB->AcceID == 0 || nameid != pd->petDB->AcceID || pd->pet.equip != 0) { - clif->equipitemack(sd,0,0,0); + clif->equipitemack(sd,0,0,EIA_FAIL); return 1; } @@ -666,7 +666,7 @@ int pet_equipitem(struct map_session_data *sd,int index) { clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); if (battle_config.pet_equip_required) { //Skotlex: start support timers if need - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); if (pd->s_skill && pd->s_skill->timer == INVALID_TIMER) { if (pd->s_skill->id) pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000, pet->skill_support_timer, sd->bl.id, 0); @@ -771,8 +771,7 @@ int pet_food(struct map_session_data *sd, struct pet_data *pd) return 0; } -int pet_randomwalk(struct pet_data *pd,unsigned int tick) -{ +int pet_randomwalk(struct pet_data *pd, int64 tick) { nullpo_ret(pd); Assert((pd->msd == 0) || (pd->msd->pd == pd)); @@ -812,8 +811,7 @@ int pet_randomwalk(struct pet_data *pd,unsigned int tick) return 0; } -int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, unsigned int tick) -{ +int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick) { struct block_list *target = NULL; if(pd->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL) @@ -924,16 +922,15 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, unsigned i return 0; } -int pet_ai_sub_foreachclient(struct map_session_data *sd,va_list ap) -{ - unsigned int tick = va_arg(ap,unsigned int); +int pet_ai_sub_foreachclient(struct map_session_data *sd,va_list ap) { + int64 tick = va_arg(ap,int64); if(sd->status.pet_id && sd->pd) pet->ai_sub_hard(sd->pd,sd,tick); return 0; } -int pet_ai_hard(int tid, unsigned int tick, int id, intptr_t data) { +int pet_ai_hard(int tid, int64 tick, int id, intptr_t data) { map->foreachpc(pet->ai_sub_foreachclient,tick); return 0; @@ -966,7 +963,7 @@ int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap) return 0; } -int pet_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data) { +int pet_delay_item_drop(int tid, int64 tick, int id, intptr_t data) { struct item_drop_list *list; struct item_drop *ditem, *ditem_prev; list=(struct item_drop_list *)data; @@ -1034,7 +1031,7 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd) /*========================================== * pet bonus giving skills [Valaris] / Rewritten by [Skotlex] *------------------------------------------*/ -int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data) { +int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd=map->id2sd(id); struct pet_data *pd; int bonus; @@ -1075,7 +1072,7 @@ int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data) { /*========================================== * pet recovery skills [Valaris] / Rewritten by [Skotlex] *------------------------------------------*/ -int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data) { +int pet_recovery_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd=map->id2sd(id); struct pet_data *pd; @@ -1102,7 +1099,7 @@ int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data) { return 0; } -int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { +int pet_heal_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd=map->id2sd(id); struct status_data *st; struct pet_data *pd; @@ -1139,7 +1136,7 @@ int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { /*========================================== * pet support skills [Skotlex] *------------------------------------------*/ -int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data) { +int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd=map->id2sd(id); struct pet_data *pd; struct status_data *st; diff --git a/src/map/pet.h b/src/map/pet.h index 2f8e0b7c2..f95e860a2 100644 --- a/src/map/pet.h +++ b/src/map/pet.h @@ -86,7 +86,7 @@ struct pet_data { unsigned skillbonus : 1; } state; int move_fail_count; - unsigned int next_walktime,last_thinktime; + int64 next_walktime, last_thinktime; short rate_fix; //Support rate as modified by intimacy (1000 = 100%) [Skotlex] struct pet_recovery* recovery; @@ -116,7 +116,7 @@ struct pet_interface { int (*attackskill) (struct pet_data *pd, int target_id); int (*target_check) (struct map_session_data *sd, struct block_list *bl, int type); int (*sc_check) (struct map_session_data *sd, int type); - int (*hungry) (int tid, unsigned int tick, int id, intptr_t data); + int (*hungry) (int tid, int64 tick, int id, intptr_t data); int (*search_petDB_index) (int key, int type); int (*hungry_timer_delete) (struct pet_data *pd); int (*performance) (struct map_session_data *sd, struct pet_data *pd); @@ -135,16 +135,16 @@ struct pet_interface { int (*change_name) (struct map_session_data *sd, char *name); int (*change_name_ack) (struct map_session_data *sd, char *name, int flag); int (*equipitem) (struct map_session_data *sd, int index); - int (*randomwalk) (struct pet_data *pd, unsigned int tick); - int (*ai_sub_hard) (struct pet_data *pd, struct map_session_data *sd, unsigned int tick); + int (*randomwalk) (struct pet_data *pd, int64 tick); + int (*ai_sub_hard) (struct pet_data *pd, struct map_session_data *sd, int64 tick); int (*ai_sub_foreachclient) (struct map_session_data *sd, va_list ap); - int (*ai_hard) (int tid, unsigned int tick, int id, intptr_t data); - int (*delay_item_drop) (int tid, unsigned int tick, int id, intptr_t data); + int (*ai_hard) (int tid, int64 tick, int id, intptr_t data); + int (*delay_item_drop) (int tid, int64 tick, int id, intptr_t data); int (*lootitem_drop) (struct pet_data *pd, struct map_session_data *sd); - int (*skill_bonus_timer) (int tid, unsigned int tick, int id, intptr_t data); - int (*recovery_timer) (int tid, unsigned int tick, int id, intptr_t data); - int (*heal_timer) (int tid, unsigned int tick, int id, intptr_t data); - int (*skill_support_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*skill_bonus_timer) (int tid, int64 tick, int id, intptr_t data); + int (*recovery_timer) (int tid, int64 tick, int id, intptr_t data); + int (*heal_timer) (int tid, int64 tick, int id, intptr_t data); + int (*skill_support_timer) (int tid, int64 tick, int id, intptr_t data); int (*read_db) (); }; diff --git a/src/map/script.c b/src/map/script.c index c74eff07b..944759f39 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -3184,7 +3184,7 @@ void script_stop_instances(struct script_code *code) { /*========================================== * Timer function for sleep *------------------------------------------*/ -int run_script_timer(int tid, unsigned int tick, int id, intptr_t data) { +int run_script_timer(int tid, int64 tick, int id, intptr_t data) { struct script_state *st = idb_get(script->st_db,(int)data); if( st ) { TBL_PC *sd = map->id2sd(st->rid); @@ -5639,7 +5639,7 @@ BUILDIN(checkweight2) int nb_it, nb_nb; //array size TBL_PC *sd = script->rid2sd(st); - nullpo_retr(1,sd); + nullpo_retr(false,sd); data_it = script_getdata(st, 2); data_nb = script_getdata(st, 3); @@ -7993,7 +7993,7 @@ BUILDIN(gettimetick) { /* Asgard Version */ case 0: default: //type 0:(System Ticks) - script_pushint(st,timer->gettick()); + script_pushint(st,(int)timer->gettick()); // TODO: change this to int64 when we'll support 64 bit script values break; } return true; @@ -8821,7 +8821,7 @@ BUILDIN(getnpctimer) { } switch( type ) { - case 0: val = npc->gettimerevent_tick(nd); break; + case 0: val = (int)npc->gettimerevent_tick(nd); break; // FIXME: change this to int64 when we'll support 64 bit script values case 1: if( nd->u.scr.rid ) { sd = map->id2sd(nd->u.scr.rid); @@ -8995,8 +8995,8 @@ BUILDIN(itemeffect) { struct script_data *data; struct item_data *item_data; - nullpo_retr( 1, ( sd = script->rid2sd( st ) ) ); - nullpo_retr( 1, ( nd = (TBL_NPC *)map->id2bl( sd->npc_id ) ) ); + nullpo_retr( false, ( sd = script->rid2sd( st ) ) ); + nullpo_retr( false, ( nd = (TBL_NPC *)map->id2bl( sd->npc_id ) ) ); data = script_getdata( st, 2 ); script->get_val( st, data ); @@ -9505,7 +9505,7 @@ BUILDIN(getstatus) if( td ) { // return the amount of time remaining - script_pushint(st, td->tick - timer->gettick()); + script_pushint(st, (int)(td->tick - timer->gettick())); // TODO: change this to int64 when we'll support 64 bit script values } } break; @@ -10201,6 +10201,7 @@ BUILDIN(getmapflag) case MF_BATTLEGROUND: script_pushint(st,map->list[m].flag.battleground); break; case MF_RESET: script_pushint(st,map->list[m].flag.reset); break; case MF_NOTOMB: script_pushint(st,map->list[m].flag.notomb); break; + case MF_NOCASHSHOP: script_pushint(st,map->list[m].flag.nocashshop); break; } } @@ -10317,6 +10318,7 @@ BUILDIN(setmapflag) { case MF_BATTLEGROUND: map->list[m].flag.battleground = (val <= 0 || val > 2) ? 1 : val; break; case MF_RESET: map->list[m].flag.reset = 1; break; case MF_NOTOMB: map->list[m].flag.notomb = 1; break; + case MF_NOCASHSHOP: map->list[m].flag.nocashshop = 1; break; } } @@ -10402,6 +10404,7 @@ BUILDIN(removemapflag) { case MF_BATTLEGROUND: map->list[m].flag.battleground = 0; break; case MF_RESET: map->list[m].flag.reset = 0; break; case MF_NOTOMB: map->list[m].flag.notomb = 0; break; + case MF_NOCASHSHOP: map->list[m].flag.nocashshop = 0; break; } } @@ -12685,7 +12688,7 @@ BUILDIN(summon) const char *str,*event=""; TBL_PC *sd; struct mob_data *md; - int tick = timer->gettick(); + int64 tick = timer->gettick(); sd=script->rid2sd(st); if (!sd) return true; @@ -14012,7 +14015,7 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle) if( SQL_ERROR == SQL->QueryStr(handle, query) ) { Sql_ShowDebug(handle); - script_pushint(st, 0); + st->state = END; return false; } @@ -14540,7 +14543,7 @@ BUILDIN(checkidle) { sd = script->rid2sd(st); if (sd) - script_pushint(st, DIFF_TICK(last_tick, sd->idletime)); + script_pushint(st, DIFF_TICK32(last_tick, sd->idletime)); // TODO: change this to int64 when we'll support 64 bit script values else script_pushint(st, 0); @@ -15453,19 +15456,89 @@ BUILDIN(readbook) Questlog script commands *******************/ +BUILDIN(questinfo) +{ + struct npc_data *nd = map->id2nd(st->oid); + int quest, icon, job, color = 0; + struct questinfo qi; + + if( nd == NULL || nd->bl.m == -1 ) + return true; + + quest = script_getnum(st, 2); + icon = script_getnum(st, 3); + + #if PACKETVER >= 20120410 + if(icon < 0 || (icon > 8 && icon != 9999) || icon == 7) + icon = 9999; // Default to nothing if icon id is invalid. + #else + if(icon < 0 || icon > 7) + icon = 0; + else + icon = icon + 1; + #endif + + qi.quest_id = quest; + qi.icon = (unsigned char)icon; + qi.nd = nd; + + if( script_hasdata(st, 4) ) { + color = script_getnum(st, 4); + if( color < 0 || color > 3 ) { + ShowWarning("buildin_questinfo: invalid color '%d', changing to 0\n",color); + script->reportfunc(st); + color = 0; + } + qi.color = (unsigned char)color; + } + + qi.hasJob = false; + + if(script_hasdata(st, 5)) { + job = script_getnum(st, 5); + + if (!pcdb_checkid(job)) + ShowError("buildin_questinfo: Nonexistant Job Class.\n"); + else { + qi.hasJob = true; + qi.job = (unsigned short)job; + } + } + + map->add_questinfo(nd->bl.m,&qi); + + return true; +} + BUILDIN(setquest) { struct map_session_data *sd = script->rid2sd(st); - nullpo_ret(sd); + unsigned short i; + if (!sd) + return false; + quest->add(sd, script_getnum(st, 2)); + + // If questinfo is set, remove quest bubble once quest is set. + for(i = 0; i < map->list[sd->bl.m].qi_count; i++) { + struct questinfo *qi = &map->list[sd->bl.m].qi_data[i]; + if( qi->quest_id == script_getnum(st, 2) ) { +#if PACKETVER >= 20120410 + clif->quest_show_event(sd, &qi->nd->bl, 9999, 0); +#else + clif->quest_show_event(sd, &qi->nd->bl, 0, 0); +#endif + } + } + return true; } BUILDIN(erasequest) { struct map_session_data *sd = script->rid2sd(st); - nullpo_ret(sd); + nullpo_retr(false,sd); quest->delete(sd, script_getnum(st, 2)); return true; @@ -15474,7 +15547,7 @@ BUILDIN(erasequest) BUILDIN(completequest) { struct map_session_data *sd = script->rid2sd(st); - nullpo_ret(sd); + nullpo_retr(false,sd); quest->update_status(sd, script_getnum(st, 2), Q_COMPLETE); return true; @@ -15483,7 +15556,7 @@ BUILDIN(completequest) BUILDIN(changequest) { struct map_session_data *sd = script->rid2sd(st); - nullpo_ret(sd); + nullpo_retr(false,sd); quest->change(sd, script_getnum(st, 2),script_getnum(st, 3)); return true; @@ -15494,7 +15567,7 @@ BUILDIN(checkquest) struct map_session_data *sd = script->rid2sd(st); quest_check_type type = HAVEQUEST; - nullpo_ret(sd); + nullpo_retr(false,sd); if( script_hasdata(st, 3) ) type = (quest_check_type)script_getnum(st, 3); @@ -15507,17 +15580,32 @@ BUILDIN(checkquest) BUILDIN(showevent) { TBL_PC *sd = script->rid2sd(st); struct npc_data *nd = map->id2nd(st->oid); - int state, color; + int icon, color = 0; if( sd == NULL || nd == NULL ) return true; - state = script_getnum(st, 2); - color = script_getnum(st, 3); - - if( color < 0 || color > 3 ) - color = 0; // set default color + + icon = script_getnum(st, 2); + if( script_hasdata(st, 3) ) { + color = script_getnum(st, 3); + if( color < 0 || color > 3 ) { + ShowWarning("buildin_showevent: invalid color '%d', changing to 0\n",color); + script->reportfunc(st); + color = 0; + } + } + + #if PACKETVER >= 20120410 + if(icon < 0 || (icon > 8 && icon != 9999) || icon == 7) + icon = 9999; // Default to nothing if icon id is invalid. + #else + if(icon < 0 || icon > 7) + icon = 0; + else + icon = icon + 1; + #endif - clif->quest_show_event(sd, &nd->bl, state, color); + clif->quest_show_event(sd, &nd->bl, icon, color); return true; } @@ -16141,10 +16229,10 @@ BUILDIN(setfont) if( sd == NULL ) return true; - if( sd->user_font != font ) - sd->user_font = font; + if( sd->status.font != font ) + sd->status.font = font; else - sd->user_font = 0; + sd->status.font = 0; clif->font(sd); return true; @@ -17455,6 +17543,74 @@ BUILDIN(bg_match_over) { return true; } + +BUILDIN(instance_mapname) { + const char *map_name; + int m; + short instance_id = -1; + + map_name = script_getstr(st,2); + + if( script_hasdata(st,3) ) + instance_id = script_getnum(st,3); + else + instance_id = st->instance_id; + + // Check that instance mapname is a valid map + if( instance_id == -1 || (m = instance->mapname2imap(map_name,instance_id)) == -1 ) + script_pushconststr(st, ""); + else + script_pushconststr(st, map->list[m].name); + + return true; +} +/* modify an instances' reload-spawn point */ +/* instance_set_respawn <map_name>,<x>,<y>{,<instance_id>} */ +/* returns 1 when successful, 0 otherwise. */ +BUILDIN(instance_set_respawn) { + const char *map_name; + short instance_id = -1; + short mid; + short x,y; + + map_name = script_getstr(st,2); + x = script_getnum(st, 3); + y = script_getnum(st, 4); + + if( script_hasdata(st, 5) ) + instance_id = script_getnum(st, 5); + else + instance_id = st->instance_id; + + if( instance_id == -1 || !instance->valid(instance_id) ) + script_pushint(st, 0); + else if( (mid = map->mapname2mapid(map_name)) == -1 ) { + ShowError("buildin_instance_set_respawn: unknown map '%s'\n",map_name); + script_pushint(st, 0); + } else { + int i; + + for(i = 0; i < instance->list[instance_id].num_map; i++) { + if( map->list[instance->list[instance_id].map[i]].m == mid ) { + instance->list[instance_id].respawn.map = map_id2index(mid); + instance->list[instance_id].respawn.x = x; + instance->list[instance_id].respawn.y = y; + break; + } + } + + if( i != instance->list[instance_id].num_map ) + script_pushint(st, 1); + else { + ShowError("buildin_instance_set_respawn: map '%s' not part of instance '%s'\n",map_name,instance->list[instance_id].name); + script_pushint(st, 0); + } + } + + + return true; +} + // declarations that were supposed to be exported from npc_chat.c #ifdef PCRE_SUPPORT BUILDIN(defpattern); @@ -17920,6 +18076,9 @@ void script_parse_builtin(void) { BUILDIN_DEF(has_instance,"s?"), BUILDIN_DEF(instance_warpall,"sii?"), BUILDIN_DEF(instance_check_party,"i???"), + BUILDIN_DEF(instance_mapname,"s?"), + BUILDIN_DEF(instance_set_respawn,"sii?"), + /** * 3rd-related **/ @@ -17952,12 +18111,13 @@ void script_parse_builtin(void) { BUILDIN_DEF(useatcmd, "s"), //Quest Log System [Inkfish] + BUILDIN_DEF(questinfo, "ii??"), BUILDIN_DEF(setquest, "i"), BUILDIN_DEF(erasequest, "i"), BUILDIN_DEF(completequest, "i"), BUILDIN_DEF(checkquest, "i?"), BUILDIN_DEF(changequest, "ii"), - BUILDIN_DEF(showevent, "ii"), + BUILDIN_DEF(showevent, "i?"), /** * hQueue [Ind/Hercules] @@ -18050,7 +18210,7 @@ void script_label_add(int key, int pos) { void script_defaults(void) { // aegis->athena slot position conversion table - unsigned int equip[SCRIPT_EQUIP_TABLE_SIZE] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_GARMENT}; + unsigned int equip[SCRIPT_EQUIP_TABLE_SIZE] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_GARMENT,EQP_SHADOW_ARMOR, EQP_SHADOW_WEAPON, EQP_SHADOW_SHIELD, EQP_SHADOW_SHOES, EQP_SHADOW_ACC_R, EQP_SHADOW_ACC_L}; script = &script_s; diff --git a/src/map/script.h b/src/map/script.h index c00086ef9..a4d14c777 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -35,7 +35,7 @@ struct eri; //#define SCRIPT_HASH_SDBM #define SCRIPT_HASH_ELF -#define SCRIPT_EQUIP_TABLE_SIZE 14 +#define SCRIPT_EQUIP_TABLE_SIZE 20 //#define SCRIPT_DEBUG_DISP //#define SCRIPT_DEBUG_DISASM @@ -287,7 +287,8 @@ enum { MF_PVP_NOCALCRANK, //50 MF_BATTLEGROUND, MF_RESET, - MF_NOTOMB + MF_NOTOMB, + MF_NOCASHSHOP }; /** @@ -535,7 +536,7 @@ struct script_interface { void (*label_add)(int key, int pos); void (*run) (struct script_code *rootscript,int pos,int rid,int oid); void (*run_main) (struct script_state *st); - int (*run_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*run_timer) (int tid, int64 tick, int id, intptr_t data); int (*set_var) (struct map_session_data *sd, char *name, void *val); void (*stop_instances) (struct script_code *code); void (*free_code) (struct script_code* code); diff --git a/src/map/skill.c b/src/map/skill.c index 9db10bbc7..b70e58c46 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -460,7 +460,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) return 1; } - if (sd->blockskill[idx] > 0) { + if (sd->blockskill[idx]) { clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); return 1; } @@ -639,7 +639,7 @@ struct s_skill_unit_layout* skill_get_unit_layout (uint16 skill_id, uint16 skill /*========================================== * *------------------------------------------*/ -int skill_additional_effect(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int dmg_lv, unsigned int tick) { +int skill_additional_effect(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int dmg_lv, int64 tick) { struct map_session_data *sd, *dstsd; struct mob_data *md, *dstmd; struct status_data *sstatus, *tstatus; @@ -1139,12 +1139,12 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 sc_start4(bl,SC_BURNING,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv)); break; case WL_EARTHSTRAIN: - { - // lv 1 & 2 = Strip Helm, lv 3 = Strip Armor, lv 4 = Strip Weapon and lv 5 = Strip Accessory. [malufett] - const int pos[5] = { EQP_HELM, EQP_HELM, EQP_ARMOR, EQP_WEAPON, EQP_ACC }; - skill->strip_equip(bl, pos[skill_lv], 6 * skill_lv + status->get_lv(src) / 4 + status_get_dex(src) / 10, - skill_lv, skill->get_time2(skill_id,skill_lv)); - } + { + // lv 1 & 2 = Strip Helm, lv 3 = Strip Armor, lv 4 = Strip Weapon and lv 5 = Strip Accessory. [malufett] + const int pos[5] = { EQP_HELM, EQP_HELM, EQP_ARMOR, EQP_WEAPON, EQP_ACC }; + skill->strip_equip(bl, pos[skill_lv-1], 6 * skill_lv + status->get_lv(src) / 4 + status_get_dex(src) / 10, + skill_lv, skill->get_time2(skill_id,skill_lv)); + } break; case WL_JACKFROST: sc_start(bl,SC_FREEZE,100,skill_lv,skill->get_time(skill_id,skill_lv)); @@ -1569,7 +1569,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 return 0; } -int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint16 skill_id, unsigned int tick) { +int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint16 skill_id, int64 tick) { int temp, skill_lv, i, type, notok; struct block_list *tbl; @@ -1667,7 +1667,7 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1 * type of skills, so not every instance of skill->additional_effect needs a call * to this one. */ -int skill_counter_additional_effect(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, unsigned int tick) { +int skill_counter_additional_effect(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int64 tick) { int rate; struct map_session_data *sd=NULL; struct map_session_data *dstsd=NULL; @@ -2109,7 +2109,7 @@ int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type) * 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) *-------------------------------------------------------------------------*/ -int skill_attack (int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) { +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; struct status_data *sstatus, *tstatus; struct status_change *sc; @@ -2117,7 +2117,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds int type; int64 damage; int8 rmdamage=0;//magic reflected - bool additional_effects = true; + bool additional_effects = true, shadow_flag = false; if(skill_id > 0 && !skill_lv) return 0; @@ -2357,7 +2357,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds break; } //Switch End if (flag) { //Possible to chain - if ( (flag = DIFF_TICK(sd->ud.canact_tick, tick)) < 50 ) flag = 50;/* less is a waste. */ + if ( (flag = DIFF_TICK32(sd->ud.canact_tick, tick)) < 50 ) flag = 50;/* less is a waste. */ sc_start2(src,SC_COMBOATTACK,100,skill_id,bl->id,flag); clif->combo_delay(src, flag); } @@ -2574,10 +2574,12 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if (ud && DIFF_TICK(ud->attackabletime, tick + type) < 0) ud->attackabletime = tick + type; } + + shadow_flag = skill->check_shadowform(bl, damage, dmg.div_); if( !dmg.amotion ) { //Instant damage - if( !sc || (!sc->data[SC_DEVOTION] && skill_id != CR_REFLECTSHIELD) ) + if( (!sc || (!sc->data[SC_DEVOTION] && skill_id != CR_REFLECTSHIELD)) && !shadow_flag) status_fix_damage(src,bl,damage,dmg.dmotion); //Deal damage before knockback to allow stuff like firewall+storm gust combo. if( !status->isdead(bl) && additional_effects ) skill->additional_effect(src,bl,skill_id,skill_lv,dmg.flag,dmg.dmg_lv,tick); @@ -2657,8 +2659,15 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds } //Delayed damage must be dealt after the knockback (it needs to know actual position of target) - if (dmg.amotion) - battle->delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion, additional_effects); + if (dmg.amotion){ + if( shadow_flag ){ + if( !status->isdead(bl) && additional_effects ) + skill->additional_effect(src,bl,skill_id,skill_lv,dmg.flag,dmg.dmg_lv,tick); + if( dmg.flag > ATK_BLOCK ) + skill->counter_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,tick); + }else + battle->delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion, additional_effects); + } if( sc && sc->data[SC_DEVOTION] && skill_id != PA_PRESSURE ) { struct status_change_entry *sce = sc->data[SC_DEVOTION]; @@ -2758,21 +2767,21 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds * Checking bl battle flag and display dammage * then call func with source,target,skill_id,skill_lv,tick,flag *------------------------------------------*/ -int skill_area_sub (struct block_list *bl, va_list ap) { +int skill_area_sub(struct block_list *bl, va_list ap) { struct block_list *src; uint16 skill_id,skill_lv; int flag; - unsigned int tick; + int64 tick; SkillFunc func; nullpo_ret(bl); - src=va_arg(ap,struct block_list *); - skill_id=va_arg(ap,int); - skill_lv=va_arg(ap,int); - tick=va_arg(ap,unsigned int); - flag=va_arg(ap,int); - func=va_arg(ap,SkillFunc); + src = va_arg(ap,struct block_list *); + skill_id = va_arg(ap,int); + skill_lv = va_arg(ap,int); + tick = va_arg(ap,int64); + flag = va_arg(ap,int); + func = va_arg(ap,SkillFunc); if(battle->check_target(src,bl,flag) > 0) { // several splash skills need this initial dummy packet to display correctly @@ -3027,14 +3036,14 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, /*========================================== * what the hell it doesn't need to receive this many params, it doesn't do anything ~_~ *------------------------------------------*/ -int skill_area_sub_count (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) { +int skill_area_sub_count(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) { return 1; } /*========================================== * *------------------------------------------*/ -int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { +int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { struct block_list *src = map->id2bl(id),*target; struct unit_data *ud = unit->bl2ud(src); struct skill_timerskill *skl; @@ -3059,8 +3068,23 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { break; // Target not on Map if(src->m != target->m) break; // Different Maps - if(status->isdead(src)) - break; // Caster is Dead + if(status->isdead(src)){ + // Exceptions + switch(skl->skill_id){ + case WL_CHAINLIGHTNING_ATK: + case WL_TETRAVORTEX_FIRE: + case WL_TETRAVORTEX_WATER: + case WL_TETRAVORTEX_WIND: + case WL_TETRAVORTEX_GROUND: + case SR_FLASHCOMBO_ATK_STEP1: + case SR_FLASHCOMBO_ATK_STEP2: + case SR_FLASHCOMBO_ATK_STEP3: + case SR_FLASHCOMBO_ATK_STEP4: + break; + default: + continue; // Caster is Dead + } + } if(status->isdead(target) && skl->skill_id != RG_INTIMIDATE && skl->skill_id != WZ_WATERBALL) break; @@ -3129,12 +3153,12 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { case WL_TETRAVORTEX_WIND: case WL_TETRAVORTEX_GROUND: clif->skill_nodamage(src, target, skl->skill_id, skl->skill_lv, 1); - skill_attack(BF_MAGIC, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag); + skill->attack(BF_MAGIC, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag); skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify if( skl->type == 4 ){ const enum sc_type scs[] = { SC_BURNING, SC_BLOODING, SC_FROSTMISTY, SC_STUN }; // status inflicts are depend on what summoned element is used. int rate = skl->y, index = skl->x-1; - sc_start2(target, scs[index], rate, skl->skill_lv, src->id, skill->get_time(WL_TETRAVORTEX,index)); + sc_start2(target, scs[index], rate, skl->skill_lv, src->id, skill->get_time(WL_TETRAVORTEX,index+1)); } break; case WM_REVERBERATION_MELEE: @@ -3245,8 +3269,7 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { /*========================================== * *------------------------------------------*/ -int skill_addtimerskill (struct block_list *src, unsigned int tick, int target, int x,int y, uint16 skill_id, uint16 skill_lv, int type, int flag) -{ +int skill_addtimerskill(struct block_list *src, int64 tick, int target, int x,int y, uint16 skill_id, uint16 skill_lv, int type, int flag) { int i; struct unit_data *ud; nullpo_retr(1, src); @@ -3285,6 +3308,17 @@ int skill_cleartimerskill (struct block_list *src) for(i=0;i<MAX_SKILLTIMERSKILL;i++) { if(ud->skilltimerskill[i]) { + switch(ud->skilltimerskill[i]->skill_id){ + case WL_TETRAVORTEX_FIRE: + case WL_TETRAVORTEX_WATER: + case WL_TETRAVORTEX_WIND: + case WL_TETRAVORTEX_GROUND: + case SR_FLASHCOMBO_ATK_STEP1: + case SR_FLASHCOMBO_ATK_STEP2: + case SR_FLASHCOMBO_ATK_STEP3: + case SR_FLASHCOMBO_ATK_STEP4: + continue; + } timer->delete(ud->skilltimerskill[i]->timer, skill->timerskill); ers_free(skill->timer_ers, ud->skilltimerskill[i]); ud->skilltimerskill[i]=NULL; @@ -3299,7 +3333,7 @@ int skill_activate_reverbetion( struct block_list *bl, va_list ap) { return 0; if( su->alive && (sg = su->group) && sg->skill_id == WM_REVERBERATION ) { map->foreachinrange(skill->trap_splash, bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, timer->gettick()); - su->limit=DIFF_TICK(timer->gettick(),sg->tick); + su->limit=DIFF_TICK32(timer->gettick(),sg->tick); sg->unit_id = UNT_USED_TRAPS; } return 0; @@ -3320,7 +3354,7 @@ int skill_reveal_trap (struct block_list *bl, va_list ap) { * * *------------------------------------------*/ -int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) { +int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) { struct map_session_data *sd = NULL; struct status_data *tstatus; struct status_change *sc; @@ -4185,7 +4219,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint } } if(cooldown) - skill->blockpc_start(sd, skill_id, cooldown, false); + skill->blockpc_start(sd, skill_id, cooldown); }else if( sc ){ // Summon Balls int i = SC_SUMMON5; for(; i >= SC_SUMMON1; i--){ @@ -4522,8 +4556,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint /*========================================== * *------------------------------------------*/ -int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) -{ +int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { struct block_list *target, *src; struct map_session_data *sd; struct mob_data *md; @@ -4734,7 +4767,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) } } if(cooldown) - skill->blockpc_start(sd, ud->skill_id, cooldown, false); + skill->blockpc_start(sd, ud->skill_id, cooldown); } if( battle_config.display_status_timers && sd ) clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); @@ -4785,7 +4818,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check. if( sc->data[SC_DANCING] && skill->get_inf2(ud->skill_id)&INF2_SONG_DANCE && sd ) - skill->blockpc_start(sd,BD_ADAPTATION,3000, false); + skill->blockpc_start(sd,BD_ADAPTATION,3000); } if( sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish] @@ -4850,8 +4883,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) /*========================================== * *------------------------------------------*/ -int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) -{ +int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) { struct map_session_data *sd, *dstsd; struct mob_data *md, *dstmd; struct homun_data *hd; @@ -4930,11 +4962,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } - return skill->castend_damage_id (src, bl, skill_id, skill_lv, tick, flag); + return skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, flag); } break; case NPC_SMOKING: //Since it is a self skill, this one ends here rather than in damage_id. [Skotlex] - return skill->castend_damage_id (src, bl, skill_id, skill_lv, tick, flag); + return skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, flag); case MH_STEINWAND: { struct block_list *s_src = battle->get_master(src); short ret = 0; @@ -5406,7 +5438,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui // Initiate 10% of your damage becomes fire element. sc_start4(src,SC_SUB_WEAPONPROPERTY,100,3,20,0,0,skill->get_time2(skill_id, skill_lv)); if( sd ) - skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv), false); + skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv)); else if( bl->type == BL_MER ) skill->blockmerc_start((TBL_MER*)bl, skill_id, skill->get_time(skill_id, skill_lv)); break; @@ -5575,7 +5607,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); if (sd) - skill->blockpc_start (sd, skill_id, skill->get_time2(skill_id,skill_lv), false); + skill->blockpc_start (sd, skill_id, skill->get_time2(skill_id,skill_lv)); break; case ALL_ANGEL_PROTECT: @@ -7072,8 +7104,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case UNT_TALKIEBOX: su->group->unit_id = UNT_USED_TRAPS; clif->changetraplook(bl, UNT_USED_TRAPS); - su->group->limit=DIFF_TICK(tick+1500,su->group->tick); - su->limit=DIFF_TICK(tick+1500,su->group->tick); + su->group->limit=DIFF_TICK32(tick+1500,su->group->tick); + su->limit=DIFF_TICK32(tick+1500,su->group->tick); } } } @@ -7098,7 +7130,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start4(bl,type,100,skill_lv,skill_id,src->id,skill->get_time(skill_id,skill_lv),1000)); #ifndef RENEWAL - if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000, false); + if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000); #endif break; @@ -8873,7 +8905,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui duration = 9000; break; } - skill->blockpc_start(sd, skill_id, duration, false); + skill->blockpc_start(sd, skill_id, duration); } break; @@ -9084,7 +9116,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui md->special_state.ai = AI_ZANZOU; if( md->deletetimer != INVALID_TIMER ) timer->delete(md->deletetimer, mob->timer_delete); - md->deletetimer = timer->add (timer->gettick() + skill->get_time(skill_id, skill_lv), mob->timer_delete, md->bl.id, 0); + md->deletetimer = timer->add(timer->gettick() + skill->get_time(skill_id, skill_lv), mob->timer_delete, md->bl.id, 0); mob->spawn( md ); pc->setinvincibletimer(sd,500);// unlock target lock clif->skill_nodamage(src,bl,skill_id,skill_lv,1); @@ -9317,7 +9349,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui /*========================================== * *------------------------------------------*/ -int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) { +int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) { struct block_list* src = map->id2bl(id); int maxcount; struct map_session_data *sd; @@ -9430,7 +9462,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) { } } if(cooldown) - skill->blockpc_start(sd, ud->skill_id, cooldown, false); + skill->blockpc_start(sd, ud->skill_id, cooldown); } if( battle_config.display_status_timers && sd ) clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); @@ -9617,8 +9649,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char /*========================================== * *------------------------------------------*/ -int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) -{ +int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) { struct map_session_data* sd; struct status_change* sc; struct status_change_entry *sce; @@ -9908,7 +9939,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui clif->skill_poseffect(src,skill_id,skill_lv,src->x,src->y,tick); #endif if (sd) - skill->blockpc_start (sd, MO_EXTREMITYFIST, 2000, false); + skill->blockpc_start (sd, MO_EXTREMITYFIST, 2000); } break; case NJ_SHADOWJUMP: @@ -9933,7 +9964,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui md->special_state.ai = (skill_id == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA; if( md->deletetimer != INVALID_TIMER ) timer->delete(md->deletetimer, mob->timer_delete); - md->deletetimer = timer->add (timer->gettick() + skill->get_time(skill_id,skill_lv), mob->timer_delete, md->bl.id, 0); + md->deletetimer = timer->add(timer->gettick() + skill->get_time(skill_id,skill_lv), mob->timer_delete, md->bl.id, 0); mob->spawn (md); //Now it is ready for spawning. } } @@ -10031,7 +10062,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui { if( md->deletetimer != INVALID_TIMER ) timer->delete(md->deletetimer, mob->timer_delete); - md->deletetimer = timer->add (tick + i, mob->timer_delete, md->bl.id, 0); + md->deletetimer = timer->add(tick + i, mob->timer_delete, md->bl.id, 0); } mob->spawn (md); } @@ -10162,7 +10193,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui md->special_state.ai = AI_FLORA; if( md->deletetimer != INVALID_TIMER ) timer->delete(md->deletetimer, mob->timer_delete); - md->deletetimer = timer->add (timer->gettick() + skill->get_time(skill_id, skill_lv), mob->timer_delete, md->bl.id, 0); + md->deletetimer = timer->add(timer->gettick() + skill->get_time(skill_id, skill_lv), mob->timer_delete, md->bl.id, 0); mob->spawn( md ); } } @@ -10570,7 +10601,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ old_sg->skill_id == SA_VIOLENTGALE ) && old_sg->limit > 0) { //Use the previous limit (minus the elapsed time) [Skotlex] - limit = old_sg->limit - DIFF_TICK(timer->gettick(), old_sg->tick); + limit = old_sg->limit - DIFF_TICK32(timer->gettick(), old_sg->tick); if (limit < 0) //This can happen... limit = skill->get_time(skill_id,skill_lv); } @@ -10927,7 +10958,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ /*========================================== * *------------------------------------------*/ -int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned int tick) { +int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick) { struct skill_unit_group *sg; struct block_list *ss; struct status_change *sc; @@ -10967,14 +10998,14 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned if( status->change_start(bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8) ) { const struct TimerData* td = sc->data[type]?timer->get(sc->data[type]->timer):NULL; if( td ) - sec = DIFF_TICK(td->tick, tick); + sec = DIFF_TICK32(td->tick, tick); map->moveblock(bl, src->bl.x, src->bl.y, tick); clif->fixpos(bl); sg->val2 = bl->id; } else sec = 3000; //Couldn't trap it? - sg->limit = DIFF_TICK(tick,sg->tick)+sec; + sg->limit = DIFF_TICK32(tick,sg->tick)+sec; } break; case UNT_SAFETYWALL: @@ -11100,7 +11131,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned // case UNT_ICEWALL: //Destroy the cell. [Skotlex] // src->val1 = 0; // if(src->limit + sg->tick > tick + 700) - // src->limit = DIFF_TICK(tick+700,sg->tick); + // src->limit = DIFF_TICK32(tick+700,sg->tick); // break; case UNT_MOONLIT: @@ -11138,7 +11169,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned /*========================================== * *------------------------------------------*/ -int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, unsigned int tick) { +int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int64 tick) { struct skill_unit_group *sg; struct block_list *ss; TBL_PC* tsd; @@ -11182,7 +11213,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if ((ts = skill->unitgrouptickset_search(bl,sg,tick))) { //Not all have it, eg: Traps don't have it even though they can be hit by Heaven's Drive [Skotlex] - diff = DIFF_TICK(tick,ts->tick); + diff = DIFF_TICK32(tick,ts->tick); if (diff < 0) return 0; ts->tick = tick+sg->interval; @@ -11282,7 +11313,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns status->charge(ss, 0, 8); //costs additional 8 SP if miss } else { // mobs //should end when out of sp. - sg->limit = DIFF_TICK(tick,sg->tick); + sg->limit = DIFF_TICK32(tick,sg->tick); break; } } while( x == bl->x && y == bl->y @@ -11325,7 +11356,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns skill->blown(&src->bl,bl,skill->get_blewcount(sg->skill_id,sg->skill_lv),unit->getdir(bl),0); sg->unit_id = UNT_USED_TRAPS; clif->changetraplook(&src->bl, UNT_USED_TRAPS); - sg->limit=DIFF_TICK(tick,sg->tick)+1500; + sg->limit=DIFF_TICK32(tick,sg->tick)+1500; } break; @@ -11336,7 +11367,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( status->change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 8) ) { const struct TimerData* td = tsc->data[type]?timer->get(tsc->data[type]->timer):NULL; if( td ) - sec = DIFF_TICK(td->tick, tick); + sec = DIFF_TICK32(td->tick, tick); if( sg->unit_id == UNT_MANHOLE || battle_config.skill_trap_type || !map_flag_gvg2(src->bl.m) ) { unit->movepos(bl, src->bl.x, src->bl.y, 0, 0); clif->fixpos(bl); @@ -11353,7 +11384,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns **/ clif->changetraplook(&src->bl, UNT_ANKLESNARE); } - sg->limit = DIFF_TICK(tick,sg->tick)+sec; + sg->limit = DIFF_TICK32(tick,sg->tick)+sec; sg->interval = -1; src->range = 0; } @@ -11405,7 +11436,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); if (sg->unit_id != UNT_FIREPILLAR_ACTIVE) clif->changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); - sg->limit=DIFF_TICK(tick,sg->tick)+1500 + + sg->limit=DIFF_TICK32(tick,sg->tick)+1500 + (sg->unit_id== UNT_CLUSTERBOMB || sg->unit_id== UNT_ICEBOUNDTRAP?1000:0);// Cluster Bomb/Icebound has 1s to disappear once activated. sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again. break; @@ -11417,7 +11448,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns clif->talkiebox(&src->bl, sg->valstr); sg->unit_id = UNT_USED_TRAPS; clif->changetraplook(&src->bl, UNT_USED_TRAPS); - sg->limit = DIFF_TICK(tick, sg->tick) + 5000; + sg->limit = DIFF_TICK32(tick, sg->tick) + 5000; sg->val2 = -1; } break; @@ -11594,7 +11625,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns &src->bl,tick); sg->unit_id = UNT_USED_TRAPS; //clif->changetraplook(&src->bl, UNT_FIREPILLAR_ACTIVE); - sg->limit=DIFF_TICK(tick,sg->tick)+1500; + sg->limit=DIFF_TICK32(tick,sg->tick)+1500; break; /** * 3rd stuff @@ -11647,7 +11678,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_REVERBERATION: clif->changetraplook(&src->bl,UNT_USED_TRAPS); map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); - sg->limit = DIFF_TICK(tick,sg->tick)+1000; + sg->limit = DIFF_TICK32(tick,sg->tick)+1000; sg->unit_id = UNT_USED_TRAPS; break; @@ -11659,7 +11690,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( !(status_get_mode(bl)&MD_BOSS) && ss != bl && battle->check_target(&src->bl, bl, BCT_PARTY) > 0 ) { if( !(tsc && tsc->data[type]) ){ sc_start(bl, type, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv)); - sg->limit = DIFF_TICK(tick,sg->tick); + sg->limit = DIFF_TICK32(tick,sg->tick); sg->unit_id = UNT_USED_TRAPS; } } @@ -11671,13 +11702,13 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( sc_start(bl, type, 100, sg->skill_lv, sec) ) { const struct TimerData* td = tsc->data[type]?timer->get(tsc->data[type]->timer):NULL; if( td ) - sec = DIFF_TICK(td->tick, tick); + sec = DIFF_TICK32(td->tick, tick); ///map->moveblock(bl, src->bl.x, src->bl.y, tick); // in official server it doesn't behave like this. [malufett] clif->fixpos(bl); sg->val2 = bl->id; } else sec = 3000; // Couldn't trap it? - sg->limit = DIFF_TICK(tick, sg->tick) + sec; + sg->limit = DIFF_TICK32(tick, sg->tick) + sec; } else if( tsc->data[SC_THORNS_TRAP] && bl->id == sg->val2 ) skill->attack(skill->get_type(GN_THORNS_TRAP), ss, ss, bl, sg->skill_id, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION); } @@ -11715,7 +11746,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( battle->check_target(&src->bl,bl,BCT_ENEMY) > 0 ) skill->attack(skill->get_type(GN_HELLS_PLANT_ATK), ss, &src->bl, bl, GN_HELLS_PLANT_ATK, sg->skill_lv, tick, 0); if( ss != bl) //The caster is the only one who can step on the Plants, without destroying them - sg->limit = DIFF_TICK(tick, sg->tick) + 100; + sg->limit = DIFF_TICK32(tick, sg->tick) + 100; break; case UNT_CLOUD_KILL: @@ -11765,7 +11796,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_VACUUM_EXTREME: {// TODO: official behavior in gvg area. [malufett] - int sec = sg->limit - DIFF_TICK(tick, sg->tick); + int sec = sg->limit - DIFF_TICK32(tick, sg->tick); int range = skill->get_unit_range(sg->skill_id, sg->skill_lv); if( tsc && !tsc->data[type] && @@ -11828,7 +11859,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_LAVA_SLIDE: skill->attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); if(++sg->val1 > 4) //after 5 stop hit and destroy me - sg->limit = DIFF_TICK(tick, sg->tick); + sg->limit = DIFF_TICK32(tick, sg->tick); break; case UNT_POISON_MIST: @@ -11845,7 +11876,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns /*========================================== * Triggered when a char steps out of a skill cell *------------------------------------------*/ -int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned int tick) { +int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick) { struct skill_unit_group *sg; struct status_change *sc; struct status_change_entry *sce; @@ -11888,7 +11919,7 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in if (target && target==bl) { if (sce && sce->val3 == sg->group_id) status_change_end(bl, type, INVALID_TIMER); - sg->limit = DIFF_TICK(tick,sg->tick)+1000; + sg->limit = DIFF_TICK32(tick,sg->tick)+1000; } } break; @@ -11899,7 +11930,7 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in /*========================================== * Triggered when a char steps out of a skill group (entirely) [Skotlex] *------------------------------------------*/ -int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned int tick) { +int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) { struct status_change *sc; struct status_change_entry *sce; enum sc_type type; @@ -12005,10 +12036,10 @@ int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned int tick * flag&1: Invoke onplace function (otherwise invoke onout) * flag&4: Invoke a onleft call (the unit might be scheduled for deletion) *------------------------------------------*/ -int skill_unit_effect (struct block_list* bl, va_list ap) { +int skill_unit_effect(struct block_list* bl, va_list ap) { struct skill_unit* su = va_arg(ap,struct skill_unit*); struct skill_unit_group* group = su->group; - unsigned int tick = va_arg(ap,unsigned int); + int64 tick = va_arg(ap,int64); unsigned int flag = va_arg(ap,unsigned int); uint16 skill_id; bool dissonance; @@ -12044,8 +12075,7 @@ int skill_unit_effect (struct block_list* bl, va_list ap) { /*========================================== * *------------------------------------------*/ -int skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl, int64 damage, unsigned int tick) -{ +int skill_unit_ondamaged(struct skill_unit *src, struct block_list *bl, int64 damage, int64 tick) { struct skill_unit_group *sg; nullpo_ret(src); @@ -14152,8 +14182,7 @@ void skill_brandishspear_dir (struct square* tc, uint8 dir, int are) { } } -void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) -{ +void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) { int c,n=4; uint8 dir = map->calc_dir(src,bl->x,bl->y); struct square tc; @@ -14490,10 +14519,10 @@ int skill_sit (struct map_session_data *sd, int type) /*========================================== * *------------------------------------------*/ -int skill_frostjoke_scream (struct block_list *bl, va_list ap) { +int skill_frostjoke_scream(struct block_list *bl, va_list ap) { struct block_list *src; uint16 skill_id,skill_lv; - unsigned int tick; + int64 tick; nullpo_ret(bl); nullpo_ret(src=va_arg(ap,struct block_list*)); @@ -14501,7 +14530,7 @@ int skill_frostjoke_scream (struct block_list *bl, va_list ap) { skill_id=va_arg(ap,int); skill_lv=va_arg(ap,int); if(!skill_lv) return 0; - tick=va_arg(ap,unsigned int); + tick=va_arg(ap,int64); if (src == bl || status->isdead(bl)) return 0; @@ -14534,22 +14563,22 @@ void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint16 skill /*========================================== * *------------------------------------------*/ -int skill_attack_area (struct block_list *bl, va_list ap) { +int skill_attack_area(struct block_list *bl, va_list ap) { struct block_list *src,*dsrc; int atk_type,skill_id,skill_lv,flag,type; - unsigned int tick; + int64 tick; if(status->isdead(bl)) return 0; atk_type = va_arg(ap,int); - src=va_arg(ap,struct block_list*); - dsrc=va_arg(ap,struct block_list*); - skill_id=va_arg(ap,int); - skill_lv=va_arg(ap,int); - tick=va_arg(ap,unsigned int); - flag=va_arg(ap,int); - type=va_arg(ap,int); + src = va_arg(ap,struct block_list*); + dsrc = va_arg(ap,struct block_list*); + skill_id = va_arg(ap,int); + skill_lv = va_arg(ap,int); + tick = va_arg(ap,int64); + flag = va_arg(ap,int); + type = va_arg(ap,int); if (skill->area_temp[1] == bl->id) //This is the target of the skill, do a full attack and skip target checks. @@ -14704,7 +14733,7 @@ int skill_detonator(struct block_list *bl, va_list ap) { map->foreachinrange(skill->trap_splash,bl,skill->get_splash(su->group->skill_id,su->group->skill_lv),su->group->bl_flag,bl,su->group->tick); } clif->changetraplook(bl, UNT_USED_TRAPS); - su->group->limit = DIFF_TICK(timer->gettick(),su->group->tick) + + su->group->limit = DIFF_TICK32(timer->gettick(),su->group->tick) + (unit_id == UNT_TALKIEBOX ? 5000 : (unit_id == UNT_CLUSTERBOMB || unit_id == UNT_ICEBOUNDTRAP? 2500 : (unit_id == UNT_FIRINGTRAP ? 0 : 1500)) ); su->group->unit_id = UNT_USED_TRAPS; break; @@ -14841,15 +14870,15 @@ int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap) /*========================================== * *------------------------------------------*/ -int skill_trap_splash (struct block_list *bl, va_list ap) { +int skill_trap_splash(struct block_list *bl, va_list ap) { struct block_list *src; - int tick; + int64 tick; struct skill_unit *su; struct skill_unit_group *sg; struct block_list *ss; src = va_arg(ap,struct block_list *); su = (struct skill_unit *)src; - tick = va_arg(ap,int); + tick = va_arg(ap,int64); if( !su->alive || bl->prev == NULL ) return 0; @@ -14927,7 +14956,7 @@ int skill_trap_splash (struct block_list *bl, va_list ap) { case UNT_FIRINGTRAP: case UNT_ICEBOUNDTRAP: clif->changetraplook(bl, UNT_USED_TRAPS); - su->group->limit = DIFF_TICK(timer->gettick(),su->group->tick) + 1500; + su->group->limit = DIFF_TICK32(timer->gettick(),su->group->tick) + 1500; su->group->unit_id = UNT_USED_TRAPS; } break; @@ -15046,6 +15075,39 @@ bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *s return wall; } +bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit){ + struct status_change *sc; + struct block_list *src; + + nullpo_retr(false, bl); + + sc = status->get_sc(bl); + + if( sc && sc->data[SC__SHADOWFORM] && damage ) { + src = map->id2bl(sc->data[SC__SHADOWFORM]->val2); + + if( !src || src->m != bl->m ) { + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + return false; + } + + if( src && (status->isdead(src) || !battle->check_target(bl,src,BCT_ENEMY)) ){ + if( src->type == BL_PC ) + ((TBL_PC*)src)->shadowform_id = 0; + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + return false; + } + + status->damage(bl, src, damage, 0, clif->damage(src, src, timer->gettick(), 500, 500, damage, hit, (hit > 1 ? 8 : 0), 0), 0); + if( (--sc->data[SC__SHADOWFORM]->val3) <= 0 ) { + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + if( src->type == BL_PC ) + ((TBL_PC*)src)->shadowform_id = 0; + } + return true; + } + return false; +} /*========================================== * *------------------------------------------*/ @@ -15220,11 +15282,11 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, if(i == MAX_SKILLUNITGROUP) { // array is full, make room by discarding oldest group int j=0; - unsigned maxdiff=0,x,tick=timer->gettick(); + int64 maxdiff = 0, x, tick = timer->gettick(); for(i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++) - if((x=DIFF_TICK(tick,ud->skillunit[i]->tick))>maxdiff){ - maxdiff=x; - j=i; + if( (x=DIFF_TICK(tick,ud->skillunit[i]->tick)) > maxdiff ) { + maxdiff = x; + j = i; } skill->del_unitgroup(ud->skillunit[j],ALC_MARK); //Since elements must have shifted, we use the last slot. @@ -15411,7 +15473,7 @@ int skill_clear_unitgroup (struct block_list *src) /*========================================== * *------------------------------------------*/ -struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_list *bl, struct skill_unit_group *group, int tick) { +struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl, struct skill_unit_group *group, int64 tick) { int i,j=-1,k,s,id; struct unit_data *ud; struct skill_unit_group_tickset *set; @@ -15451,10 +15513,10 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_lis /*========================================== * *------------------------------------------*/ -int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) { +int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap) { struct skill_unit* su = va_arg(ap,struct skill_unit *); struct skill_unit_group* group = su->group; - unsigned int tick = va_arg(ap,unsigned int); + int64 tick = va_arg(ap,int64); if( !su->alive || bl->prev == NULL ) return 0; @@ -15478,7 +15540,7 @@ int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) { int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { struct skill_unit* su = DB->data2ptr(data); struct skill_unit_group* group = su->group; - unsigned int tick = va_arg(ap,unsigned int); + int64 tick = va_arg(ap,int64); bool dissonance; struct block_list* bl = &su->bl; @@ -15502,8 +15564,8 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { case UNT_GROUNDDRIFT_FIRE: group->unit_id = UNT_USED_TRAPS; //clif->changetraplook(bl, UNT_FIREPILLAR_ACTIVE); - group->limit=DIFF_TICK(tick+1500,group->tick); - su->limit=DIFF_TICK(tick+1500,group->tick); + group->limit=DIFF_TICK32(tick+1500,group->tick); + su->limit=DIFF_TICK32(tick+1500,group->tick); break; case UNT_ANKLESNARE: @@ -15582,8 +15644,8 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { } clif->changetraplook(bl,UNT_USED_TRAPS); map->foreachinrange(skill->trap_splash, bl, skill->get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); - group->limit = DIFF_TICK(tick,group->tick)+1000; - su->limit = DIFF_TICK(tick,group->tick)+1000; + group->limit = DIFF_TICK32(tick,group->tick)+1000; + su->limit = DIFF_TICK32(tick,group->tick)+1000; group->unit_id = UNT_USED_TRAPS; break; @@ -15604,8 +15666,8 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { break; } // This unit isn't removed while SC_BANDING is active. - group->limit = DIFF_TICK(tick+group->interval,group->tick); - su->limit = DIFF_TICK(tick+group->interval,group->tick); + group->limit = DIFF_TICK32(tick+group->interval,group->tick); + su->limit = DIFF_TICK32(tick+group->interval,group->tick); } break; @@ -15618,7 +15680,7 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { // icewall loses 50 hp every second su->val1 -= SKILLUNITTIMER_INTERVAL/20; // trap's hp if( su->val1 <= 0 && su->limit + group->tick > tick + 700 ) - su->limit = DIFF_TICK(tick+700,group->tick); + su->limit = DIFF_TICK32(tick+700,group->tick); break; case UNT_BLASTMINE: case UNT_SKIDTRAP: @@ -15635,7 +15697,7 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { skill->delunit(su); else { clif->changetraplook(bl, group->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); - group->limit = DIFF_TICK(tick, group->tick) + 1500; + group->limit = DIFF_TICK32(tick, group->tick) + 1500; group->unit_id = UNT_USED_TRAPS; } } @@ -15644,15 +15706,15 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { if( su->val1 <= 0 ) { clif->changetraplook(bl,UNT_USED_TRAPS); map->foreachinrange(skill->trap_splash, bl, skill->get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); - group->limit = DIFF_TICK(tick,group->tick)+1000; - su->limit = DIFF_TICK(tick,group->tick)+1000; + group->limit = DIFF_TICK32(tick,group->tick)+1000; + su->limit = DIFF_TICK32(tick,group->tick)+1000; group->unit_id = UNT_USED_TRAPS; } break; case UNT_WALLOFTHORN: if( su->val1 <= 0 ) { group->unit_id = UNT_USED_TRAPS; - group->limit = DIFF_TICK(tick, group->tick) + 1500; + group->limit = DIFF_TICK32(tick, group->tick) + 1500; } break; } @@ -15689,7 +15751,7 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { /*========================================== * Executes on all skill units every SKILLUNITTIMER_INTERVAL miliseconds. *------------------------------------------*/ -int skill_unit_timer(int tid, unsigned int tick, int id, intptr_t data) { +int skill_unit_timer(int tid, int64 tick, int id, intptr_t data) { map->freeblock_lock(); skill->unit_db->foreach(skill->unit_db, skill->unit_timer_sub, tick); @@ -15702,12 +15764,12 @@ int skill_unit_timer(int tid, unsigned int tick, int id, intptr_t data) { /*========================================== * *------------------------------------------*/ -int skill_unit_move_sub (struct block_list* bl, va_list ap) { +int skill_unit_move_sub(struct block_list* bl, va_list ap) { struct skill_unit* su = (struct skill_unit *)bl; struct skill_unit_group* group = su->group; struct block_list* target = va_arg(ap,struct block_list*); - unsigned int tick = va_arg(ap,unsigned int); + int64 tick = va_arg(ap,int64); int flag = va_arg(ap,int); bool dissonance; @@ -15799,7 +15861,7 @@ int skill_unit_move_sub (struct block_list* bl, va_list ap) { * units to figure out when they have left a group. * flag&4: Force a onleft event (triggered when the bl is killed, for example) *------------------------------------------*/ -int skill_unit_move (struct block_list *bl, unsigned int tick, int flag) { +int skill_unit_move(struct block_list *bl, int64 tick, int flag) { nullpo_ret(bl); if( bl->prev == NULL ) @@ -15824,10 +15886,9 @@ int skill_unit_move (struct block_list *bl, unsigned int tick, int flag) { /*========================================== * *------------------------------------------*/ -int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 dx, int16 dy) -{ +int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx, int16 dy) { int i,j; - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); int *m_flag; struct skill_unit *su1; struct skill_unit *su2; @@ -16681,7 +16742,7 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) { md->special_state.ai = AI_FLORA; if( md->deletetimer != INVALID_TIMER ) timer->delete(md->deletetimer, mob->timer_delete); - md->deletetimer = timer->add (timer->gettick() + skill->get_time(NC_MAGICDECOY,skill_id), mob->timer_delete, md->bl.id, 0); + md->deletetimer = timer->add(timer->gettick() + skill->get_time(NC_MAGICDECOY,skill_id), mob->timer_delete, md->bl.id, 0); mob->spawn(md); md->status.matk_min = md->status.matk_max = 250 + (50 * skill_id); } @@ -16879,13 +16940,13 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite /** * for Royal Guard's LG_TRAMPLE **/ -int skill_destroy_trap( struct block_list *bl, va_list ap ) { +int skill_destroy_trap(struct block_list *bl, va_list ap) { struct skill_unit *su = (struct skill_unit *)bl; struct skill_unit_group *sg; - unsigned int tick; + int64 tick; nullpo_ret(su); - tick = va_arg(ap, unsigned int); + tick = va_arg(ap, int64); if (su->alive && (sg = su->group) && skill->get_inf2(sg->skill_id)&INF2_TRAP) { switch( sg->unit_id ) { @@ -16912,13 +16973,14 @@ int skill_destroy_trap( struct block_list *bl, va_list ap ) { /*========================================== * *------------------------------------------*/ -int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) { +int skill_blockpc_end(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd = map->id2sd(id); struct skill_cd * cd = NULL; if (data <= 0 || data >= MAX_SKILL) return 0; - if (!sd) return 0; + if (!sd || !sd->blockskill[data]) + return 0; if( ( cd = idb_get(skill->cd_db,sd->status.char_id) ) ) { int i; @@ -16952,22 +17014,21 @@ int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) { } } - if (sd->blockskill[data] != (0x1|(tid&0xFE))) return 0; - - sd->blockskill[data] = 0; + sd->blockskill[data] = false; return 1; } /** * flags a singular skill as being blocked from persistent usage. * @param sd the player the skill delay affects - * @param skill_id the skill which should be delayed + * @param skill_id the skill which should be delayed * @param tick the length of time the delay should last - * @param load whether this assignment is being loaded upon player login * @return 0 if successful, -1 otherwise */ -int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, bool load) { +int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick) { + struct skill_cd* cd = NULL; uint16 idx = skill->get_index(skill_id); + int64 now = timer->gettick(); nullpo_retr (-1, sd); @@ -16975,53 +17036,63 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, return -1; if (tick < 1) { - sd->blockskill[idx] = 0; + sd->blockskill[idx] = false; return -1; } - if( !load && battle_config.display_status_timers ) + if( battle_config.display_status_timers ) clif->skill_cooldown(sd, skill_id, tick); - - if( !load ) {// not being loaded initially so ensure the skill delay is recorded - struct skill_cd* cd = NULL; + + if( !(cd = idb_get(skill->cd_db,sd->status.char_id)) ) {// create a new skill cooldown object for map storage + cd = ers_alloc(skill->cd_ers, struct skill_cd); + + cd->cursor = 0; + memset(cd->entry, 0, sizeof(cd->entry)); + + idb_put( skill->cd_db, sd->status.char_id, cd ); + } else { int i; - if( !(cd = idb_get(skill->cd_db,sd->status.char_id)) ) {// create a new skill cooldown object for map storage - cd = ers_alloc(skill->cd_ers, struct skill_cd); - - cd->cursor = 0; - memset(cd->entry, 0, sizeof(cd->entry)); - - idb_put( skill->cd_db, sd->status.char_id, cd ); - } - for(i = 0; i < MAX_SKILL_TREE; i++) { - if( !cd->entry[i] ) + if( cd->entry[i] && cd->entry[i]->skidx == idx ) break; } - - if( i == MAX_SKILL_TREE ) { - ShowError("skill_blockpc_start: '%s' got over '%d' skill cooldowns, no room to save!\n",sd->status.name,MAX_SKILL_TREE); - } else { - cd->entry[cd->cursor] = ers_alloc(skill->cd_entry_ers,struct skill_cd_entry); - - cd->entry[cd->cursor]->duration = tick; + + if( i != MAX_SKILL_TREE ) {/* duplicate, update necessary */ + cd->entry[i]->duration = tick; #if PACKETVER >= 20120604 - cd->entry[cd->cursor]->total = tick; + cd->entry[i]->total = tick; #endif - cd->entry[cd->cursor]->skidx = idx; - cd->entry[cd->cursor]->skill_id = skill_id; - cd->entry[cd->cursor]->started = timer->gettick(); - - cd->cursor++; + cd->entry[i]->started = now; + timer->settick(cd->entry[i]->timer,now+tick); + return 0; } + } + + if( cd->cursor == MAX_SKILL_TREE ) { + ShowError("skill_blockpc_start: '%s' got over '%d' skill cooldowns, no room to save!\n",sd->status.name,MAX_SKILL_TREE); + return -1; + } + + cd->entry[cd->cursor] = ers_alloc(skill->cd_entry_ers,struct skill_cd_entry); + + cd->entry[cd->cursor]->duration = tick; +#if PACKETVER >= 20120604 + cd->entry[cd->cursor]->total = tick; +#endif + cd->entry[cd->cursor]->skidx = idx; + cd->entry[cd->cursor]->skill_id = skill_id; + cd->entry[cd->cursor]->started = now; + cd->entry[cd->cursor]->timer = timer->add(now+tick,skill->blockpc_end,sd->bl.id,idx); + + cd->cursor++; - sd->blockskill[idx] = 0x1|(0xFE&timer->add(timer->gettick()+tick,skill->blockpc_end,sd->bl.id,idx)); + sd->blockskill[idx] = true; return 0; } -int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) { //[orn] +int skill_blockhomun_end(int tid, int64 tick, int id, intptr_t data) { //[orn] struct homun_data *hd = (TBL_HOM*)map->id2bl(id); if (data <= 0 || data >= MAX_SKILL) return 0; @@ -17046,7 +17117,7 @@ int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { / return timer->add(timer->gettick() + tick, skill->blockhomun_end, hd->bl.id, idx); } -int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr_t data) {//[orn] +int skill_blockmerc_end(int tid, int64 tick, int id, intptr_t data) {//[orn] struct mercenary_data *md = (TBL_MER*)map->id2bl(id); if( data <= 0 || data >= MAX_SKILL ) return 0; @@ -17514,7 +17585,7 @@ int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) { void skill_cooldown_save(struct map_session_data * sd) { int i; struct skill_cd* cd = NULL; - unsigned int now = 0; + int64 now = 0; // always check to make sure the session properly exists nullpo_retv(sd); @@ -17527,7 +17598,11 @@ void skill_cooldown_save(struct map_session_data * sd) { // process each individual cooldown associated with the character for( i = 0; i < cd->cursor; i++ ) { - cd->entry[i]->duration = DIFF_TICK(cd->entry[i]->started+cd->entry[i]->duration,now); + cd->entry[i]->duration = DIFF_TICK32(cd->entry[i]->started+cd->entry[i]->duration,now); + if( cd->entry[i]->timer != INVALID_TIMER ) { + timer->delete(cd->entry[i]->timer,skill->blockpc_end); + cd->entry[i]->timer = INVALID_TIMER; + } } } @@ -17538,7 +17613,7 @@ void skill_cooldown_save(struct map_session_data * sd) { void skill_cooldown_load(struct map_session_data * sd) { int i; struct skill_cd* cd = NULL; - unsigned int now = 0; + int64 now = 0; // always check to make sure the session properly exists nullpo_retv(sd); @@ -17554,8 +17629,8 @@ void skill_cooldown_load(struct map_session_data * sd) { // process each individual cooldown associated with the character for( i = 0; i < cd->cursor; i++ ) { cd->entry[i]->started = now; - // block the skill from usage but ensure it is not recorded (load = true) - skill->blockpc_start( sd, cd->entry[i]->skill_id, cd->entry[i]->duration, true ); + cd->entry[i]->timer = timer->add(timer->gettick()+cd->entry[i]->duration,skill->blockpc_end,sd->bl.id,cd->entry[i]->skidx); + sd->blockskill[cd->entry[i]->skidx] = true; } } @@ -17608,6 +17683,7 @@ bool skill_parse_row_skilldb(char* split[], int columns, int current) { safestrncpy(skill->db[idx].name, trim(split[15]), sizeof(skill->db[idx].name)); safestrncpy(skill->db[idx].desc, trim(split[16]), sizeof(skill->db[idx].desc)); strdb_iput(skill->name2id_db, skill->db[idx].name, skill_id); + script->set_constant2(skill->db[idx].name,(int)skill_id,0); return true; } @@ -18291,4 +18367,5 @@ void skill_defaults(void) { skill->cooldown_save = skill_cooldown_save; skill->maelstrom_suction = skill_maelstrom_suction; skill->get_new_group_id = skill_get_new_group_id; + skill->check_shadowform = skill_check_shadowform; } diff --git a/src/map/skill.h b/src/map/skill.h index 0f89cd3be..fca4952ef 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -909,7 +909,14 @@ enum e_skill { NPC_VENOMFOG, NPC_MILLENNIUMSHIELD, NPC_COMET, - + NPC_WIDEWEB, + NPC_WIDESUCK, + NPC_STORMGUST2, + NPC_FIRESTORM, + NPC_REVERBERATION, + NPC_REVERBERATION_ATK, + NPC_LEX_AETERNA, + KN_CHARGEATK = 1001, CR_SHRINK, AS_SONICACCEL, @@ -1271,7 +1278,7 @@ enum e_skill { RL_R_TRIP_PLUSATK, RL_B_FLICKER_ATK, RL_GLITTERING_GREED_ATK, - + KO_YAMIKUMO = 3001, KO_RIGHT, KO_LEFT, @@ -1679,7 +1686,7 @@ struct skill_unit_group { int map; int target_flag; //Holds BCT_* flag for battle_check_target int bl_flag; //Holds BL_* flag for map_foreachin* functions - unsigned int tick; + int64 tick; int limit,interval; uint16 skill_id,skill_lv; @@ -1708,7 +1715,7 @@ struct skill_unit { }; struct skill_unit_group_tickset { - unsigned int tick; + int64 tick; int id; }; @@ -1740,10 +1747,11 @@ struct s_skill_magicmushroom_db { struct skill_cd_entry { int duration;//milliseconds #if PACKETVER >= 20120604 - int total; + int total;/* used for display on newer clients */ #endif short skidx;//the skill index entries belong to - unsigned int started; + int64 started;/* gettick() of when it started, used vs duration to measure how much left upon logout */ + int timer;/* timer id */ uint16 skill_id;//skill id }; @@ -1783,7 +1791,7 @@ struct s_skill_spellbook_db { int point; }; -typedef int (*SkillFunc)(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag); +typedef int (*SkillFunc)(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 tick, int flag); /** * Skill.c Interface @@ -1875,13 +1883,13 @@ struct skill_interface { int (*get_casttype2) (uint16 index); int (*name2id) (const char* name); int (*isammotype) (struct map_session_data *sd, int skill); - int (*castend_id) (int tid, unsigned int tick, int id, intptr_t data); - int (*castend_pos) (int tid, unsigned int tick, int id, intptr_t data); + int (*castend_id) (int tid, int64 tick, int id, intptr_t data); + int (*castend_pos) (int tid, int64 tick, int id, intptr_t data); int (*castend_map) ( struct map_session_data *sd,uint16 skill_id, const char *mapname); int (*cleartimerskill) (struct block_list *src); - int (*addtimerskill) (struct block_list *src,unsigned int tick,int target,int x,int y,uint16 skill_id,uint16 skill_lv,int type,int flag); - int (*additional_effect) ( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,int attack_type,int dmg_lv,unsigned int tick); - int (*counter_additional_effect) ( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,int attack_type,unsigned int tick); + int (*addtimerskill) (struct block_list *src, int64 tick, int target, int x, int y, uint16 skill_id, uint16 skill_lv, int type, int flag); + int (*additional_effect) (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int dmg_lv, int64 tick); + int (*counter_additional_effect) (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int64 tick); int (*blown) (struct block_list* src, struct block_list* target, int count, int8 dir, int flag); int (*break_equip) (struct block_list *bl, unsigned short where, int rate, int flag); int (*strip_equip) (struct block_list *bl, unsigned short where, int rate, int lv, int time); @@ -1893,8 +1901,8 @@ struct skill_interface { int (*del_unitgroup) (struct skill_unit_group *group, const char* file, int line, const char* func); int (*clear_unitgroup) (struct block_list *src); int (*clear_group) (struct block_list *bl, int flag); - int (*unit_onplace) (struct skill_unit *src, struct block_list *bl, unsigned int tick); - int (*unit_ondamaged) (struct skill_unit *src,struct block_list *bl,int64 damage,unsigned int tick); + int (*unit_onplace) (struct skill_unit *src, struct block_list *bl, int64 tick); + int (*unit_ondamaged) (struct skill_unit *src, struct block_list *bl, int64 damage, int64 tick); int (*cast_fix) ( struct block_list *bl, uint16 skill_id, uint16 skill_lv); int (*cast_fix_sc) ( struct block_list *bl, int time); int (*vf_cast_fix) ( struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv); @@ -1904,12 +1912,12 @@ struct skill_interface { int (*consume_requirement) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type); struct skill_condition (*get_requirement) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); int (*check_pc_partner) (struct map_session_data *sd, uint16 skill_id, uint16* skill_lv, int range, int cast_flag); - int (*unit_move) (struct block_list *bl,unsigned int tick,int flag); - int (*unit_onleft) (uint16 skill_id, struct block_list *bl,unsigned int tick); - int (*unit_onout) (struct skill_unit *src, struct block_list *bl, unsigned int tick); + int (*unit_move) (struct block_list *bl, int64 tick, int flag); + int (*unit_onleft) (uint16 skill_id, struct block_list *bl, int64 tick); + int (*unit_onout) (struct skill_unit *src, struct block_list *bl, int64 tick); int (*unit_move_unit_group) ( struct skill_unit_group *group, int16 m,int16 dx,int16 dy); int (*sit) (struct map_session_data *sd, int type); - void (*brandishspear) (struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag); + void (*brandishspear) (struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag); void (*repairweapon) (struct map_session_data *sd, int idx); void (*identify) (struct map_session_data *sd,int idx); void (*weaponrefine) (struct map_session_data *sd,int idx); @@ -1924,25 +1932,25 @@ struct skill_interface { int (*can_produce_mix) ( struct map_session_data *sd, int nameid, int trigger, int qty); int (*produce_mix) ( struct map_session_data *sd, uint16 skill_id, int nameid, int slot1, int slot2, int slot3, int qty ); int (*arrow_create) ( struct map_session_data *sd,int nameid); - int (*castend_nodamage_id) ( struct block_list *src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag ); - int (*castend_damage_id) ( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag ); - int (*castend_pos2) ( struct block_list *src, int x,int y,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag); - int (*blockpc_start) (struct map_session_data *sd, uint16 skill_id, int tick, bool load); + int (*castend_nodamage_id) (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag); + int (*castend_damage_id) (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick,int flag); + int (*castend_pos2) (struct block_list *src, int x, int y, uint16 skill_id, uint16 skill_lv, int64 tick, int flag); + int (*blockpc_start) (struct map_session_data *sd, uint16 skill_id, int tick); int (*blockhomun_start) (struct homun_data *hd, uint16 skill_id, int tick); int (*blockmerc_start) (struct mercenary_data *md, uint16 skill_id, int tick); - int (*attack) ( int attack_type, struct block_list* src, struct block_list *dsrc,struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag ); + int (*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); int (*attack_area) (struct block_list *bl,va_list ap); int (*area_sub) (struct block_list *bl, va_list ap); - int (*area_sub_count) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag); + int (*area_sub_count) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 tick, int flag); int (*check_unit_range) (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv); int (*check_unit_range_sub) (struct block_list *bl, va_list ap); int (*check_unit_range2) (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv); int (*check_unit_range2_sub) (struct block_list *bl, va_list ap); void (*toggle_magicpower) (struct block_list *bl, uint16 skill_id); int (*magic_reflect) (struct block_list* src, struct block_list* bl, int type); - int (*onskillusage) (struct map_session_data *sd, struct block_list *bl, uint16 skill_id, unsigned int tick); + int (*onskillusage) (struct map_session_data *sd, struct block_list *bl, uint16 skill_id, int64 tick); int (*cell_overlap) (struct block_list *bl, va_list ap); - int (*timerskill) (int tid, unsigned int tick, int id, intptr_t data); + int (*timerskill) (int tid, int64 tick, int id, intptr_t data); int (*trap_splash) (struct block_list *bl, va_list ap); int (*check_condition_mercenary) (struct block_list *bl, int skill_id, int lv, int type); struct skill_unit_group *(*locate_element_field) (struct block_list *bl); @@ -1955,26 +1963,26 @@ struct skill_interface { 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, int tick); + 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); int (*check_condition_mob_master_sub) (struct block_list *bl, va_list ap); void (*brandishspear_first) (struct square *tc, uint8 dir, int16 x, int16 y); void (*brandishspear_dir) (struct square* tc, uint8 dir, int are); - int (*get_fixed_cast) ( uint16 skill_id ,uint16 skill_lv ); + int (*get_fixed_cast) ( uint16 skill_id ,uint16 skill_lv ); int (*sit_count) (struct block_list *bl, va_list ap); int (*sit_in) (struct block_list *bl, va_list ap); int (*sit_out) (struct block_list *bl, va_list ap); void (*unitsetmapcell) (struct skill_unit *src, uint16 skill_id, uint16 skill_lv, cell_t cell, bool flag); - int (*unit_onplace_timer) (struct skill_unit *src, struct block_list *bl, unsigned int tick); + int (*unit_onplace_timer) (struct skill_unit *src, struct block_list *bl, int64 tick); int (*unit_effect) (struct block_list* bl, va_list ap); int (*unit_timer_sub_onplace) (struct block_list* bl, va_list ap); int (*unit_move_sub) (struct block_list* bl, va_list ap); - int (*blockpc_end) (int tid, unsigned int tick, int id, intptr_t data); - int (*blockhomun_end) (int tid, unsigned int tick, int id, intptr_t data); - int (*blockmerc_end) (int tid, unsigned int tick, int id, intptr_t data); + int (*blockpc_end) (int tid, int64 tick, int id, intptr_t data); + int (*blockhomun_end) (int tid, int64 tick, int id, intptr_t data); + int (*blockmerc_end) (int tid, int64 tick, int id, intptr_t data); int (*split_atoi) (char *str, int *val); - int (*unit_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*unit_timer) (int tid, int64 tick, int id, intptr_t data); int (*unit_timer_sub) (DBKey key, DBData *data, va_list ap); void (*init_unit_layout) (void); bool (*parse_row_skilldb) (char* split[], int columns, int current); @@ -2011,6 +2019,7 @@ struct skill_interface { void (*cooldown_save) (struct map_session_data * sd); int (*maelstrom_suction) (struct block_list *bl, va_list ap); int (*get_new_group_id) (void); + bool (*check_shadowform) (struct block_list *bl, int64 damage, int hit); }; struct skill_interface *skill; diff --git a/src/map/status.c b/src/map/status.c index 8a2ac7cd6..c06de4dfe 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -906,6 +906,8 @@ void initChangeTables(void) { status->IconChangeTable[SC_REBOUND] = SI_REBOUND; status->IconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING; status->IconChangeTable[SC_MONSTER_TRANSFORM] = SI_MONSTER_TRANSFORM; + status->IconChangeTable[SC_MOONSTAR] = SI_MOONSTAR; + status->IconChangeTable[SC_SUPER_STAR] = SI_SUPER_STAR; //Other SC which are not necessarily associated to skills. status->ChangeFlagTable[SC_ATTHASTE_POTION1] = SCB_ASPD; @@ -995,6 +997,9 @@ void initChangeTables(void) { status->ChangeFlagTable[SC_MTF_MATK] = SCB_MATK; status->ChangeFlagTable[SC_MTF_MLEATKED] |= SCB_ALL; + status->ChangeFlagTable[SC_MOONSTAR] |= SCB_NONE; + status->ChangeFlagTable[SC_SUPER_STAR] |= SCB_NONE; + /* status->DisplayType Table [Ind/Hercules] */ status->DisplayType[SC_ALL_RIDING] = true; status->DisplayType[SC_PUSH_CART] = true; @@ -1019,6 +1024,8 @@ void initChangeTables(void) { status->DisplayType[SC__SHADOWFORM] = true; status->DisplayType[SC__MANHOLE] = true; status->DisplayType[SC_MONSTER_TRANSFORM] = true; + status->DisplayType[SC_MOONSTAR] = true; + status->DisplayType[SC_SUPER_STAR] = true; #ifdef RENEWAL_EDP // renewal EDP increases your weapon atk @@ -2382,11 +2389,17 @@ int status_calc_pc_(struct map_session_data* sd, bool first) { clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_CLAIRVOYANCE); memset(&sd->special_state,0,sizeof(sd->special_state)); - memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp))); - - //FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex] - if (!sd->state.permanent_speed) + + if (!sd->state.permanent_speed) { + memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp))); bstatus->speed = DEFAULT_WALK_SPEED; + } else { + int pSpeed = bstatus->speed; + memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp))); + bstatus->speed = pSpeed; + } + + //FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex] //Give them all modes except these (useful for clones) bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK); @@ -3663,6 +3676,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { if(flag&SCB_SPEED) { struct unit_data *ud = unit->bl2ud(bl); + st->speed = status->calc_speed(bl, sc, bst->speed); //Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER @@ -3671,13 +3685,11 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { if (ud) ud->state.change_walk_target = ud->state.speed_changed = 1; - if( bl->type&BL_PC && st->speed < battle_config.max_walk_speed ) + if( bl->type&BL_PC && !(sd && sd->state.permanent_speed) && st->speed < battle_config.max_walk_speed ) st->speed = battle_config.max_walk_speed; if( bl->type&BL_HOM && battle_config.hom_setting&0x8 && ((TBL_HOM*)bl)->master) st->speed = status->get_speed(&((TBL_HOM*)bl)->master->bl); - - } if(flag&SCB_CRI && bst->cri) { @@ -5038,11 +5050,8 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc TBL_PC* sd = BL_CAST(BL_PC, bl); int speed_rate; - if( sc == NULL ) - return cap_value(speed,10,USHRT_MAX); - - if (sd && sd->state.permanent_speed) - return (short)cap_value(speed,10,USHRT_MAX); + if( sc == NULL || ( sd && sd->state.permanent_speed ) ) + return (unsigned short)cap_value(speed,MIN_WALK_SPEED,MAX_WALK_SPEED); if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || sd->ud.skill_id == LG_EXEEDBREAK) ) { @@ -5215,7 +5224,7 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc } - return (short)cap_value(speed,10,USHRT_MAX); + return (unsigned short)cap_value(speed,MIN_WALK_SPEED,MAX_WALK_SPEED); } // flag&1 - fixed value [malufett] @@ -6497,46 +6506,46 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed. return 0; // Immune to status ailements switch( type ) { - case SC_QUAGMIRE://Tester said it protects against this and decrease agi. - case SC_DEC_AGI: - case SC_BURNING: - case SC_FROSTMISTY: + case SC_QUAGMIRE://Tester said it protects against this and decrease agi. + case SC_DEC_AGI: + case SC_BURNING: + case SC_FROSTMISTY: //case SC_WHITEIMPRISON://Need confirm. Protected against this in the past. [Rytech] - case SC_MARSHOFABYSS: - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_DEATHHURT: - case SC_PYREXIA: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: - case SC_COLD: ////08/31/2011 - Class Balance Changes - case SC_DEEP_SLEEP: - case SC_MANDRAGORA: - return 0; + case SC_MARSHOFABYSS: + case SC_TOXIN: + case SC_PARALYSE: + case SC_VENOMBLEED: + case SC_MAGICMUSHROOM: + case SC_DEATHHURT: + case SC_PYREXIA: + case SC_OBLIVIONCURSE: + case SC_LEECHESEND: + case SC_COLD: ////08/31/2011 - Class Balance Changes + case SC_DEEP_SLEEP: + case SC_MANDRAGORA: + return 0; } } else if( sc->data[SC_INSPIRATION] ) { if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX ) return 0; // Immune to status ailements switch( type ) { - case SC_DEEP_SLEEP: - case SC_SATURDAY_NIGHT_FEVER: - case SC_PYREXIA: - case SC_DEATHHURT: - case SC_MAGICMUSHROOM: - case SC_VENOMBLEED: - case SC_TOXIN: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: - case SC__ENERVATION: - case SC__GROOMY: - case SC__LAZINESS: - case SC__UNLUCKY: - case SC__WEAKNESS: - case SC__BODYPAINT: - case SC__IGNORANCE: - return 0; + case SC_DEEP_SLEEP: + case SC_SATURDAY_NIGHT_FEVER: + case SC_PYREXIA: + case SC_DEATHHURT: + case SC_MAGICMUSHROOM: + case SC_VENOMBLEED: + case SC_TOXIN: + case SC_OBLIVIONCURSE: + case SC_LEECHESEND: + case SC__ENERVATION: + case SC__GROOMY: + case SC__LAZINESS: + case SC__UNLUCKY: + case SC__WEAKNESS: + case SC__BODYPAINT: + case SC__IGNORANCE: + return 0; } } @@ -6551,292 +6560,292 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val undead_flag = battle->check_undead(st->race,st->def_ele); //Check for inmunities / sc fails switch (type) { - case SC_DRUMBATTLE: - case SC_NIBELUNGEN: - case SC_INTOABYSS: - case SC_SIEGFRIED: - if( bl->type == BL_PC) { - struct map_session_data *sd = BL_CAST(BL_PC,bl); - if (!sd->status.party_id) return 0; - } - break; - case SC_ANGRIFFS_MODUS: - case SC_GOLDENE_FERSE: - if ((type==SC_GOLDENE_FERSE && sc->data[SC_ANGRIFFS_MODUS]) - || (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE]) - ) - return 0; - case SC_STONE: - if(sc->data[SC_POWER_OF_GAIA]) - return 0; - case SC_FREEZE: - //Undead are immune to Freeze/Stone - if (undead_flag && !(flag&1)) - return 0; - case SC_DEEP_SLEEP: - case SC_SLEEP: - case SC_STUN: - case SC_FROSTMISTY: - case SC_COLD: - if (sc->opt1) - return 0; //Cannot override other opt1 status changes. [Skotlex] - if((type == SC_FREEZE || type == SC_FROSTMISTY || type == SC_COLD) && sc->data[SC_WARMER]) - return 0; //Immune to Frozen and Freezing status if under Warmer status. [Jobbie] - break; + case SC_DRUMBATTLE: + case SC_NIBELUNGEN: + case SC_INTOABYSS: + case SC_SIEGFRIED: + if( bl->type == BL_PC) { + struct map_session_data *sd = BL_CAST(BL_PC,bl); + if (!sd->status.party_id) return 0; + } + break; + case SC_ANGRIFFS_MODUS: + case SC_GOLDENE_FERSE: + if ((type==SC_GOLDENE_FERSE && sc->data[SC_ANGRIFFS_MODUS]) + || (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE]) + ) + return 0; + case SC_STONE: + if(sc->data[SC_POWER_OF_GAIA]) + return 0; + case SC_FREEZE: + //Undead are immune to Freeze/Stone + if (undead_flag && !(flag&1)) + return 0; + case SC_DEEP_SLEEP: + case SC_SLEEP: + case SC_STUN: + case SC_FROSTMISTY: + case SC_COLD: + if (sc->opt1) + return 0; //Cannot override other opt1 status changes. [Skotlex] + if((type == SC_FREEZE || type == SC_FROSTMISTY || type == SC_COLD) && sc->data[SC_WARMER]) + return 0; //Immune to Frozen and Freezing status if under Warmer status. [Jobbie] + break; - //There all like berserk, do not everlap each other - case SC_BERSERK: - if( sc->data[SC__BLOODYLUST] || sc->data[SC_SATURDAY_NIGHT_FEVER] ) - return 0; - break; + //There all like berserk, do not everlap each other + case SC_BERSERK: + if( sc->data[SC__BLOODYLUST] || sc->data[SC_SATURDAY_NIGHT_FEVER] ) + return 0; + break; - case SC_BURNING: - if(sc->opt1 || sc->data[SC_FROSTMISTY]) - return 0; - break; + case SC_BURNING: + if(sc->opt1 || sc->data[SC_FROSTMISTY]) + return 0; + break; - case SC_CRUCIS: - //Only affects demons and undead element (but not players) - if((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC) - return 0; - break; - case SC_LEXAETERNA: - if( (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) || sc->data[SC_FREEZE] ) - return 0; - break; - case SC_KYRIE: - if (bl->type == BL_MOB) - return 0; - break; - case SC_OVERTHRUST: - if (sc->data[SC_OVERTHRUSTMAX]) - return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex] - case SC_OVERTHRUSTMAX: - if( sc->option&OPTION_MADOGEAR ) - return 0;//Overthrust and Overthrust Max cannot be used on Mado Gear [Ind] - break; - case SC_ADRENALINE: - if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE))) - return 0; - if (sc->data[SC_QUAGMIRE] || - sc->data[SC_DEC_AGI] || - sc->option&OPTION_MADOGEAR //Adrenaline doesn't affect Mado Gear [Ind] + case SC_CRUCIS: + //Only affects demons and undead element (but not players) + if((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC) + return 0; + break; + case SC_LEXAETERNA: + if( (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) || sc->data[SC_FREEZE] ) + return 0; + break; + case SC_KYRIE: + if (bl->type == BL_MOB) + return 0; + break; + case SC_OVERTHRUST: + if (sc->data[SC_OVERTHRUSTMAX]) + return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex] + case SC_OVERTHRUSTMAX: + if( sc->option&OPTION_MADOGEAR ) + return 0;//Overthrust and Overthrust Max cannot be used on Mado Gear [Ind] + break; + case SC_ADRENALINE: + if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE))) + return 0; + if (sc->data[SC_QUAGMIRE] || + sc->data[SC_DEC_AGI] || + sc->option&OPTION_MADOGEAR //Adrenaline doesn't affect Mado Gear [Ind] + ) + return 0; + break; + case SC_ADRENALINE2: + if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE2))) + return 0; + if (sc->data[SC_QUAGMIRE] || + sc->data[SC_DEC_AGI] ) - return 0; - break; - case SC_ADRENALINE2: - if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE2))) - return 0; - if (sc->data[SC_QUAGMIRE] || - sc->data[SC_DEC_AGI] - ) - return 0; - break; - case SC_MAGNIFICAT: - if( sc->data[SC_OFFERTORIUM] || sc->option&OPTION_MADOGEAR ) //Mado is immune to magnificat - return 0; - break; - case SC_ONEHANDQUICKEN: - case SC_MER_QUICKEN: - case SC_TWOHANDQUICKEN: - if(sc->data[SC_DEC_AGI]) - return 0; + return 0; + break; + case SC_MAGNIFICAT: + if( sc->data[SC_OFFERTORIUM] || sc->option&OPTION_MADOGEAR ) //Mado is immune to magnificat + return 0; + break; + case SC_ONEHANDQUICKEN: + case SC_MER_QUICKEN: + case SC_TWOHANDQUICKEN: + if(sc->data[SC_DEC_AGI]) + return 0; - case SC_CONCENTRATION: - case SC_SPEARQUICKEN: - case SC_TRUESIGHT: - case SC_WINDWALK: - case SC_CARTBOOST: - case SC_ASSNCROS: - if(sc->option&OPTION_MADOGEAR) - return 0;//Mado is immune to wind walk, cart boost, etc (others above) [Ind] - case SC_INC_AGI: - if (sc->data[SC_QUAGMIRE]) - return 0; - break; - case SC_CLOAKING: - //Avoid cloaking with no wall and low skill level. [Skotlex] - //Due to the cloaking card, we have to check the wall versus to known - //skill level rather than the used one. [Skotlex] - //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL)) - if( sd && pc->checkskill(sd, AS_CLOAKING) < 3 && !skill->check_cloaking(bl,NULL) ) - return 0; - break; - case SC_MODECHANGE: - { - int mode; - struct status_data *bst = status->get_base_status(bl); - if (!bst) return 0; - if (sc->data[type]) { - //Pile up with previous values. - if(!val2) val2 = sc->data[type]->val2; - val3 |= sc->data[type]->val3; - val4 |= sc->data[type]->val4; - } - mode = val2 ? val2 : bst->mode; //Base mode - if (val4) mode&=~val4; //Del mode - if (val3) mode|= val3; //Add mode - if (mode == bst->mode) { //No change. - if (sc->data[type]) //Abort previous status - return status_change_end(bl, type, INVALID_TIMER); - return 0; - } - } - break; - //Strip skills, need to divest something or it fails. - case SC_NOEQUIPWEAPON: - if (sd && !(flag&4)) { //apply sc anyway if loading saved sc_data - int i; - opt_flag = 0; //Reuse to check success condition. - if(sd->bonus.unstripable_equip&EQP_WEAPON) + case SC_CONCENTRATION: + case SC_SPEARQUICKEN: + case SC_TRUESIGHT: + case SC_WINDWALK: + case SC_CARTBOOST: + case SC_ASSNCROS: + if(sc->option&OPTION_MADOGEAR) + return 0;//Mado is immune to wind walk, cart boost, etc (others above) [Ind] + case SC_INC_AGI: + if (sc->data[SC_QUAGMIRE]) + return 0; + break; + case SC_CLOAKING: + //Avoid cloaking with no wall and low skill level. [Skotlex] + //Due to the cloaking card, we have to check the wall versus to known + //skill level rather than the used one. [Skotlex] + //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL)) + if( sd && pc->checkskill(sd, AS_CLOAKING) < 3 && !skill->check_cloaking(bl,NULL) ) return 0; + break; + case SC_MODECHANGE: + { + int mode; + struct status_data *bst = status->get_base_status(bl); + if (!bst) return 0; + if (sc->data[type]) { + //Pile up with previous values. + if(!val2) val2 = sc->data[type]->val2; + val3 |= sc->data[type]->val3; + val4 |= sc->data[type]->val4; + } + mode = val2 ? val2 : bst->mode; //Base mode + if (val4) mode&=~val4; //Del mode + if (val3) mode|= val3; //Add mode + if (mode == bst->mode) { //No change. + if (sc->data[type]) //Abort previous status + return status_change_end(bl, type, INVALID_TIMER); + return 0; + } + } + break; + //Strip skills, need to divest something or it fails. + case SC_NOEQUIPWEAPON: + if (sd && !(flag&4)) { //apply sc anyway if loading saved sc_data + int i; + opt_flag = 0; //Reuse to check success condition. + if(sd->bonus.unstripable_equip&EQP_WEAPON) + return 0; - i = sd->equip_index[EQI_HAND_R]; - if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) { - opt_flag|=2; + i = sd->equip_index[EQI_HAND_R]; + if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) { + opt_flag|=2; + pc->unequipitem(sd,i,3); + } + if (!opt_flag) return 0; + } + if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + break; + case SC_NOEQUIPSHIELD: + if( val2 == 1 ) val2 = 0; //GX effect. Do not take shield off.. + else + if (sd && !(flag&4)) { + int i; + if(sd->bonus.unstripable_equip&EQP_SHIELD) + return 0; + i = sd->equip_index[EQI_HAND_L]; + if ( i < 0 || !sd->inventory_data[i] || sd->inventory_data[i]->type != IT_ARMOR ) + return 0; + pc->unequipitem(sd,i,3); + } + if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + break; + case SC_NOEQUIPARMOR: + if (sd && !(flag&4)) { + int i; + if(sd->bonus.unstripable_equip&EQP_ARMOR) + return 0; + i = sd->equip_index[EQI_ARMOR]; + if ( i < 0 || !sd->inventory_data[i] ) + return 0; pc->unequipitem(sd,i,3); } - if (!opt_flag) return 0; - } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC - break; - case SC_NOEQUIPSHIELD: - if( val2 == 1 ) val2 = 0; //GX effect. Do not take shield off.. - else + if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + break; + case SC_NOEQUIPHELM: if (sd && !(flag&4)) { int i; - if(sd->bonus.unstripable_equip&EQP_SHIELD) + if(sd->bonus.unstripable_equip&EQP_HELM) return 0; - i = sd->equip_index[EQI_HAND_L]; - if ( i < 0 || !sd->inventory_data[i] || sd->inventory_data[i]->type != IT_ARMOR ) + i = sd->equip_index[EQI_HEAD_TOP]; + if ( i < 0 || !sd->inventory_data[i] ) return 0; pc->unequipitem(sd,i,3); } if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; - case SC_NOEQUIPARMOR: - if (sd && !(flag&4)) { - int i; - if(sd->bonus.unstripable_equip&EQP_ARMOR) + case SC_MER_FLEE: + case SC_MER_ATK: + case SC_MER_HP: + case SC_MER_SP: + case SC_MER_HIT: + if( bl->type != BL_MER ) + return 0; // Stats only for Mercenaries + break; + case SC_FOOD_STR: + if (sc->data[SC_FOOD_STR_CASH] && sc->data[SC_FOOD_STR_CASH]->val1 > val1) return 0; - i = sd->equip_index[EQI_ARMOR]; - if ( i < 0 || !sd->inventory_data[i] ) + break; + case SC_FOOD_AGI: + if (sc->data[SC_FOOD_AGI_CASH] && sc->data[SC_FOOD_AGI_CASH]->val1 > val1) return 0; - pc->unequipitem(sd,i,3); - } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC - break; - case SC_NOEQUIPHELM: - if (sd && !(flag&4)) { - int i; - if(sd->bonus.unstripable_equip&EQP_HELM) + break; + case SC_FOOD_VIT: + if (sc->data[SC_FOOD_VIT_CASH] && sc->data[SC_FOOD_VIT_CASH]->val1 > val1) return 0; - i = sd->equip_index[EQI_HEAD_TOP]; - if ( i < 0 || !sd->inventory_data[i] ) + break; + case SC_FOOD_INT: + if (sc->data[SC_FOOD_INT_CASH] && sc->data[SC_FOOD_INT_CASH]->val1 > val1) return 0; - pc->unequipitem(sd,i,3); - } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC - break; - case SC_MER_FLEE: - case SC_MER_ATK: - case SC_MER_HP: - case SC_MER_SP: - case SC_MER_HIT: - if( bl->type != BL_MER ) - return 0; // Stats only for Mercenaries - break; - case SC_FOOD_STR: - if (sc->data[SC_FOOD_STR_CASH] && sc->data[SC_FOOD_STR_CASH]->val1 > val1) - return 0; - break; - case SC_FOOD_AGI: - if (sc->data[SC_FOOD_AGI_CASH] && sc->data[SC_FOOD_AGI_CASH]->val1 > val1) - return 0; - break; - case SC_FOOD_VIT: - if (sc->data[SC_FOOD_VIT_CASH] && sc->data[SC_FOOD_VIT_CASH]->val1 > val1) - return 0; - break; - case SC_FOOD_INT: - if (sc->data[SC_FOOD_INT_CASH] && sc->data[SC_FOOD_INT_CASH]->val1 > val1) - return 0; - break; - case SC_FOOD_DEX: - if (sc->data[SC_FOOD_DEX_CASH] && sc->data[SC_FOOD_DEX_CASH]->val1 > val1) - return 0; - break; - case SC_FOOD_LUK: - if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > val1) - return 0; - break; - case SC_FOOD_STR_CASH: - if (sc->data[SC_FOOD_STR] && sc->data[SC_FOOD_STR]->val1 > val1) - return 0; - break; - case SC_FOOD_AGI_CASH: - if (sc->data[SC_FOOD_AGI] && sc->data[SC_FOOD_AGI]->val1 > val1) - return 0; - break; - case SC_FOOD_VIT_CASH: - if (sc->data[SC_FOOD_VIT] && sc->data[SC_FOOD_VIT]->val1 > val1) - return 0; - break; - case SC_FOOD_INT_CASH: - if (sc->data[SC_FOOD_INT] && sc->data[SC_FOOD_INT]->val1 > val1) - return 0; - break; - case SC_FOOD_DEX_CASH: - if (sc->data[SC_FOOD_DEX] && sc->data[SC_FOOD_DEX]->val1 > val1) - return 0; - break; - case SC_FOOD_LUK_CASH: - if (sc->data[SC_FOOD_LUK] && sc->data[SC_FOOD_LUK]->val1 > val1) - return 0; - break; - case SC_CAMOUFLAGE: - if( sd && pc->checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill->check_camouflage(bl,NULL) ) - return 0; - break; - case SC__STRIPACCESSARY: - if( sd ) { - int i = -1; - if( !(sd->bonus.unstripable_equip&EQP_ACC_L) ) { - i = sd->equip_index[EQI_ACC_L]; - if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR ) - pc->unequipitem(sd,i,3); //L-Accessory - } if( !(sd->bonus.unstripable_equip&EQP_ACC_R) ) { - i = sd->equip_index[EQI_ACC_R]; - if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR ) - pc->unequipitem(sd,i,3); //R-Accessory + break; + case SC_FOOD_DEX: + if (sc->data[SC_FOOD_DEX_CASH] && sc->data[SC_FOOD_DEX_CASH]->val1 > val1) + return 0; + break; + case SC_FOOD_LUK: + if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > val1) + return 0; + break; + case SC_FOOD_STR_CASH: + if (sc->data[SC_FOOD_STR] && sc->data[SC_FOOD_STR]->val1 > val1) + return 0; + break; + case SC_FOOD_AGI_CASH: + if (sc->data[SC_FOOD_AGI] && sc->data[SC_FOOD_AGI]->val1 > val1) + return 0; + break; + case SC_FOOD_VIT_CASH: + if (sc->data[SC_FOOD_VIT] && sc->data[SC_FOOD_VIT]->val1 > val1) + return 0; + break; + case SC_FOOD_INT_CASH: + if (sc->data[SC_FOOD_INT] && sc->data[SC_FOOD_INT]->val1 > val1) + return 0; + break; + case SC_FOOD_DEX_CASH: + if (sc->data[SC_FOOD_DEX] && sc->data[SC_FOOD_DEX]->val1 > val1) + return 0; + break; + case SC_FOOD_LUK_CASH: + if (sc->data[SC_FOOD_LUK] && sc->data[SC_FOOD_LUK]->val1 > val1) + return 0; + break; + case SC_CAMOUFLAGE: + if( sd && pc->checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill->check_camouflage(bl,NULL) ) + return 0; + break; + case SC__STRIPACCESSARY: + if( sd ) { + int i = -1; + if( !(sd->bonus.unstripable_equip&EQP_ACC_L) ) { + i = sd->equip_index[EQI_ACC_L]; + if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR ) + pc->unequipitem(sd,i,3); //L-Accessory + } if( !(sd->bonus.unstripable_equip&EQP_ACC_R) ) { + i = sd->equip_index[EQI_ACC_R]; + if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR ) + pc->unequipitem(sd,i,3); //R-Accessory + } + if( i < 0 ) + return 0; } - if( i < 0 ) + if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + break; + case SC_TOXIN: + case SC_PARALYSE: + case SC_VENOMBLEED: + case SC_MAGICMUSHROOM: + case SC_DEATHHURT: + case SC_PYREXIA: + case SC_OBLIVIONCURSE: + case SC_LEECHESEND: + { // it doesn't stack or even renewed + int i = SC_TOXIN; + for(; i<= SC_LEECHESEND; i++) + if(sc->data[i]) return 0; + } + break; + case SC_SATURDAY_NIGHT_FEVER: + if (sc->data[SC_BERSERK] || sc->data[SC_INSPIRATION]) return 0; - } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC - break; - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_DEATHHURT: - case SC_PYREXIA: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: - { // it doesn't stack or even renewed - int i = SC_TOXIN; - for(; i<= SC_LEECHESEND; i++) - if(sc->data[i]) return 0; - } - break; - case SC_SATURDAY_NIGHT_FEVER: - if (sc->data[SC_BERSERK] || sc->data[SC_INSPIRATION]) - return 0; - break; - case SC_OFFERTORIUM: - if (sc->data[SC_MAGNIFICAT]) - return 0; - break; + break; + case SC_OFFERTORIUM: + if (sc->data[SC_MAGNIFICAT]) + return 0; + break; } //Check for BOSS resistances @@ -6844,1574 +6853,1891 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX) return 0; switch (type) { - case SC_BLESSING: - case SC_DEC_AGI: - case SC_PROVOKE: - case SC_COMA: - case SC_GRAVITATION: - case SC_NJ_SUITON: - case SC_RICHMANKIM: - case SC_ROKISWEIL: - case SC_FOGWALL: - case SC_FROSTMISTY: - case SC_BURNING: - case SC_MARSHOFABYSS: - case SC_ADORAMUS: - case SC_NEEDLE_OF_PARALYZE: - case SC_DEEP_SLEEP: - case SC_COLD: + case SC_BLESSING: + case SC_DEC_AGI: + case SC_PROVOKE: + case SC_COMA: + case SC_GRAVITATION: + case SC_NJ_SUITON: + case SC_RICHMANKIM: + case SC_ROKISWEIL: + case SC_FOGWALL: + case SC_FROSTMISTY: + case SC_BURNING: + case SC_MARSHOFABYSS: + case SC_ADORAMUS: + case SC_NEEDLE_OF_PARALYZE: + case SC_DEEP_SLEEP: + case SC_COLD: + + // Exploit prevention - kRO Fix + case SC_PYREXIA: + case SC_DEATHHURT: + case SC_TOXIN: + case SC_PARALYSE: + case SC_VENOMBLEED: + case SC_MAGICMUSHROOM: + case SC_OBLIVIONCURSE: + case SC_LEECHESEND: + + // Ranger Effects + case SC_WUGBITE: + case SC_ELECTRICSHOCKER: + case SC_MAGNETICFIELD: + + // Masquerades + case SC__ENERVATION: + case SC__GROOMY: + case SC__LAZINESS: + case SC__UNLUCKY: + case SC__WEAKNESS: + case SC__IGNORANCE: - // Exploit prevention - kRO Fix - case SC_PYREXIA: - case SC_DEATHHURT: - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: - - // Ranger Effects - case SC_WUGBITE: - case SC_ELECTRICSHOCKER: - case SC_MAGNETICFIELD: - - // Masquerades - case SC__ENERVATION: - case SC__GROOMY: - case SC__LAZINESS: - case SC__UNLUCKY: - case SC__WEAKNESS: - case SC__IGNORANCE: - - return 0; + return 0; } } //Before overlapping fail, one must check for status cured. switch (type) { - case SC_BLESSING: - //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM - //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm] - if ((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC) { - status_change_end(bl, SC_CURSE, INVALID_TIMER); - if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) - status_change_end(bl, SC_STONE, INVALID_TIMER); - } - break; - case SC_INC_AGI: - status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); - break; - case SC_QUAGMIRE: - status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER); - status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER); - status_change_end(bl, SC_WINDWALK, INVALID_TIMER); - //Also blocks the ones below... - case SC_DEC_AGI: - status_change_end(bl, SC_CARTBOOST, INVALID_TIMER); - //Also blocks the ones below... - case SC_DONTFORGETME: - status_change_end(bl, SC_INC_AGI, INVALID_TIMER); - status_change_end(bl, SC_ADRENALINE, INVALID_TIMER); - status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); - status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); - status_change_end(bl, SC_ACCELERATION, INVALID_TIMER); - break; - case SC_ONEHANDQUICKEN: - //Removes the Aspd potion effect, as reported by Vicious. [Skotlex] - status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); - break; - case SC_OVERTHRUSTMAX: - //Cancels Normal Overthrust. [Skotlex] - status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER); - break; - case SC_KYRIE: - //Cancels Assumptio - status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); - break; - case SC_DELUGE: - if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND]) - status_change_end(bl, SC_BLIND, INVALID_TIMER); - break; - case SC_SILENCE: - if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) - status_change_end(bl, SC_GOSPEL, INVALID_TIMER); - break; - case SC_HIDING: - status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER); - status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER); - break; - case SC_BERSERK: - if( val3 == SC__BLOODYLUST ) - break; - if(battle_config.berserk_cancels_buffs) { - status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); - status_change_end(bl, SC_PARRYING, INVALID_TIMER); - status_change_end(bl, SC_AURABLADE, INVALID_TIMER); - status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); - } -#ifdef RENEWAL - else { - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - } -#endif - break; - case SC_ASSUMPTIO: - status_change_end(bl, SC_KYRIE, INVALID_TIMER); - status_change_end(bl, SC_KAITE, INVALID_TIMER); - break; - case SC_KAITE: - status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); - break; - case SC_CARTBOOST: - if(sc->data[SC_DEC_AGI]) - { //Cancel Decrease Agi, but take no further effect [Skotlex] - status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); - return 0; - } - break; - case SC_FUSION: - status_change_end(bl, SC_SOULLINK, INVALID_TIMER); - break; - case SC_GS_ADJUSTMENT: - status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER); - break; - case SC_GS_MADNESSCANCEL: - status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER); - break; - //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up - case SC_PROPERTYUNDEAD: - status_change_end(bl, SC_BLESSING, INVALID_TIMER); - status_change_end(bl, SC_INC_AGI, INVALID_TIMER); - break; - case SC_FOOD_STR: - status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER); - break; - case SC_FOOD_AGI: - status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER); - break; - case SC_FOOD_VIT: - status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER); - break; - case SC_FOOD_INT: - status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER); - break; - case SC_FOOD_DEX: - status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER); - break; - case SC_FOOD_LUK: - status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER); - break; - case SC_FOOD_STR_CASH: - status_change_end(bl, SC_FOOD_STR, INVALID_TIMER); - break; - case SC_FOOD_AGI_CASH: - status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER); - break; - case SC_FOOD_VIT_CASH: - status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER); - break; - case SC_FOOD_INT_CASH: - status_change_end(bl, SC_FOOD_INT, INVALID_TIMER); - break; - case SC_FOOD_DEX_CASH: - status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER); - break; - case SC_FOOD_LUK_CASH: - status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER); - break; - case SC_ENDURE: - if( val4 ) - status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); - break; - case SC_FIGHTINGSPIRIT: - status_change_end(bl, type, INVALID_TIMER); // Remove previous one. - break; - case SC_MARSHOFABYSS: - status_change_end(bl, SC_INCAGI, INVALID_TIMER); - status_change_end(bl, SC_WINDWALK, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); - break; - case SC_SWING: - case SC_SYMPHONY_LOVE: - case SC_MOONLIT_SERENADE: - case SC_RUSH_WINDMILL: - case SC_ECHOSONG: - case SC_HARMONIZE: //group A doesn't overlap - if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER); - if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER); - if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER); - if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER); - if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); - if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); - break; - case SC_SIREN: - case SC_DEEP_SLEEP: - case SC_GLOOMYDAY: - case SC_SONG_OF_MANA: - case SC_DANCE_WITH_WUG: - case SC_SATURDAY_NIGHT_FEVER: - case SC_LERADS_DEW: - case SC_MELODYOFSINK: - case SC_BEYOND_OF_WARCRY: - case SC_UNLIMITED_HUMMING_VOICE: //group B - if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER); - if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER); - if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER); - if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); - if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER); - if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER); - if (type != SC_GLOOMYDAY) { - status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER); - status_change_end(bl, SC_GLOOMYDAY_SK, INVALID_TIMER); - } - if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER); - if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER); - if (type != SC_SATURDAY_NIGHT_FEVER) { - if (sc->data[SC_SATURDAY_NIGHT_FEVER]) { - sc->data[SC_SATURDAY_NIGHT_FEVER]->val2 = 0; //mark to not lose hp - status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER); + case SC_BLESSING: + //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM + //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm] + if ((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC) { + status_change_end(bl, SC_CURSE, INVALID_TIMER); + if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) + status_change_end(bl, SC_STONE, INVALID_TIMER); } - } - break; - case SC_REFLECTSHIELD: - status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER); - break; - case SC_LG_REFLECTDAMAGE: - status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); - break; - case SC_SHIELDSPELL_DEF: - case SC_SHIELDSPELL_MDEF: - case SC_SHIELDSPELL_REF: - status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER); - if( type != SC_SHIELDSPELL_DEF ) - status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER); - if( type != SC_SHIELDSPELL_MDEF ) - status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER); - if( type != SC_SHIELDSPELL_REF ) - status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER); - break; - case SC_GENTLETOUCH_ENERGYGAIN: - case SC_GENTLETOUCH_CHANGE: - case SC_GENTLETOUCH_REVITALIZE: - if( type != SC_GENTLETOUCH_REVITALIZE ) - status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER); - if( type != SC_GENTLETOUCH_ENERGYGAIN ) - status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER); - if( type != SC_GENTLETOUCH_CHANGE ) - status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER); - break; - case SC_INVINCIBLE: - status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER); - break; - case SC_INVINCIBLEOFF: - status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER); - break; - case SC_MAGICPOWER: - status_change_end(bl, type, INVALID_TIMER); - break; - } - - //Check for overlapping fails - if( (sce = sc->data[type]) ) { - switch( type ) { - case SC_MER_FLEE: - case SC_MER_ATK: - case SC_MER_HP: - case SC_MER_SP: - case SC_MER_HIT: - if( sce->val1 > val1 ) - val1 = sce->val1; break; - case SC_ADRENALINE: - case SC_ADRENALINE2: - case SC_WEAPONPERFECT: - case SC_OVERTHRUST: - if (sce->val2 > val2) - return 0; + case SC_INC_AGI: + status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); break; - case SC_S_LIFEPOTION: - case SC_L_LIFEPOTION: - case SC_CASH_BOSS_ALARM: - case SC_STUN: - case SC_SLEEP: - case SC_POISON: - case SC_CURSE: - case SC_SILENCE: - case SC_CONFUSION: - case SC_BLIND: - case SC_BLOODING: - case SC_DPOISON: - case SC_RG_CCONFINE_S: //Can't be re-closed in. - case SC_MARIONETTE_MASTER: - case SC_MARIONETTE: - case SC_NOCHAT: - case SC_HLIF_CHANGE: //Otherwise your Hp/Sp would get refilled while still within effect of the last invocation. - case SC__INVISIBILITY: - case SC__ENERVATION: - case SC__GROOMY: - case SC__IGNORANCE: - case SC__LAZINESS: - case SC__WEAKNESS: - case SC__UNLUCKY: - return 0; - case SC_COMBOATTACK: - case SC_DANCING: - case SC_DEVOTION: - case SC_ATTHASTE_POTION1: - case SC_ATTHASTE_POTION2: - case SC_ATTHASTE_POTION3: - case SC_ATTHASTE_INFINITY: - case SC_PLUSATTACKPOWER: - case SC_PLUSMAGICPOWER: - case SC_ENCHANTARMS: - case SC_ARMORPROPERTY: - case SC_ARMOR_RESIST: - break; - case SC_GOSPEL: - //Must not override a casting gospel char. - if(sce->val4 == BCT_SELF) - return 0; - if(sce->val1 > val1) - return 1; + case SC_QUAGMIRE: + status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER); + status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER); + status_change_end(bl, SC_WINDWALK, INVALID_TIMER); + //Also blocks the ones below... + case SC_DEC_AGI: + status_change_end(bl, SC_CARTBOOST, INVALID_TIMER); + //Also blocks the ones below... + case SC_DONTFORGETME: + status_change_end(bl, SC_INC_AGI, INVALID_TIMER); + status_change_end(bl, SC_ADRENALINE, INVALID_TIMER); + status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); + status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); + status_change_end(bl, SC_ACCELERATION, INVALID_TIMER); break; - case SC_ENDURE: - if(sce->val4 && !val4) - return 1; //Don't let you override infinite endure. - if(sce->val1 > val1) - return 1; + case SC_ONEHANDQUICKEN: + //Removes the Aspd potion effect, as reported by Vicious. [Skotlex] + status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); break; - case SC_KAAHI: - //Kaahi overwrites previous level regardless of existing level. - //Delete timer if it exists. - if (sce->val4 != INVALID_TIMER) { - timer->delete(sce->val4,status->kaahi_heal_timer); - sce->val4 = INVALID_TIMER; - } + case SC_OVERTHRUSTMAX: + //Cancels Normal Overthrust. [Skotlex] + status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER); break; - case SC_JAILED: - //When a player is already jailed, do not edit the jail data. - val2 = sce->val2; - val3 = sce->val3; - val4 = sce->val4; + case SC_KYRIE: + //Cancels Assumptio + status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); break; - case SC_LERADS_DEW: - if (sc && sc->data[SC_BERSERK]) - return 0; - case SC_SHAPESHIFT: - case SC_PROPERTYWALK: + case SC_DELUGE: + if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND]) + status_change_end(bl, SC_BLIND, INVALID_TIMER); break; - case SC_LEADERSHIP: - case SC_GLORYWOUNDS: - case SC_SOULCOLD: - case SC_HAWKEYES: - if( sce->val4 && !val4 )//you cannot override master guild aura - return 0; + case SC_SILENCE: + if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) + status_change_end(bl, SC_GOSPEL, INVALID_TIMER); break; - case SC_JOINTBEAT: - val2 |= sce->val2; // stackable ailments - default: - if(sce->val1 > val1) - return 1; //Return true to not mess up skill animations. [Skotlex] - } - } - - vd = status->get_viewdata(bl); - calc_flag = status->ChangeFlagTable[type]; - if(!(flag&4)) { //&4 - Do not parse val settings when loading SCs - switch(type) { - case SC_DEC_AGI: - case SC_INC_AGI: - val2 = 2 + val1; //Agi change + case SC_HIDING: + status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER); + status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER); break; - case SC_ENDURE: - val2 = 7; // Hit-count [Celest] - if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground && !val4 ) { - struct map_session_data *tsd; - if( sd ) { - int i; - for( i = 0; i < 5; i++ ) { - if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) ) - status->change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); - } - } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) - status->change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); + case SC_BERSERK: + if( val3 == SC__BLOODYLUST ) + break; + if(battle_config.berserk_cancels_buffs) { + status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); + status_change_end(bl, SC_PARRYING, INVALID_TIMER); + status_change_end(bl, SC_AURABLADE, INVALID_TIMER); + status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); } - //val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk) - if( val4 ) - tick = -1; + #ifdef RENEWAL + else { + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); + } + #endif break; - case SC_AUTOBERSERK: - if (st->hp < st->max_hp>>2 && - (!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0)) - sc_start4(bl,SC_PROVOKE,100,10,1,0,0,60000); - tick = -1; + case SC_ASSUMPTIO: + status_change_end(bl, SC_KYRIE, INVALID_TIMER); + status_change_end(bl, SC_KAITE, INVALID_TIMER); break; - case SC_CRUCIS: - val2 = 10 + 4*val1; //Def reduction - tick = -1; - clif->emotion(bl,E_SWT); + case SC_KAITE: + status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); break; - case SC_MAXIMIZEPOWER: - tick_time = val2 = tick>0?tick:60000; - tick = -1; // duration sent to the client should be infinite + case SC_CARTBOOST: + if(sc->data[SC_DEC_AGI]) + { //Cancel Decrease Agi, but take no further effect [Skotlex] + status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); + return 0; + } break; - case SC_EDP: // [Celest] - val2 = val1 + 2; //Chance to Poison enemies. - val3 = 50*(val1+1); //Damage increase (+50 +50*lv%) -#ifdef RENEWAL_EDP - val4 = 100 * ((val1 + 1)/2 + 2); -#endif - if( sd )//[Ind] - iROwiki says each level increases its duration by 3 seconds - tick += pc->checkskill(sd,GC_RESEARCHNEWPOISON)*3000; + case SC_FUSION: + status_change_end(bl, SC_SOULLINK, INVALID_TIMER); break; - case SC_POISONREACT: - val2=(val1+1)/2 + val1/10; // Number of counters [Skotlex] - val3=50; // + 5*val1; //Chance to counter. [Skotlex] + case SC_GS_ADJUSTMENT: + status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER); break; - case SC_MAGICROD: - val2 = val1*20; //SP gained + case SC_GS_MADNESSCANCEL: + status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER); break; - case SC_KYRIE: - val2 = (int64)st->max_hp * (val1 * 2 + 10) / 100; //%Max HP to absorb - val3 = (val1 / 2 + 5); //Hits + //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up + case SC_PROPERTYUNDEAD: + status_change_end(bl, SC_BLESSING, INVALID_TIMER); + status_change_end(bl, SC_INC_AGI, INVALID_TIMER); break; - case SC_MAGICPOWER: - //val1: Skill lv - val2 = 1; //Lasts 1 invocation - val3 = 5*val1; //Matk% increase - val4 = 0; // 0 = ready to be used, 1 = activated and running - break; - case SC_SACRIFICE: - val2 = 5; //Lasts 5 hits - tick = -1; - break; - case SC_ENCHANTPOISON: - val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate - case SC_ASPERSIO: - case SC_PROPERTYFIRE: - case SC_PROPERTYWATER: - case SC_PROPERTYWIND: - case SC_PROPERTYGROUND: - case SC_PROPERTYDARK: - case SC_PROPERTYTELEKINESIS: - skill->enchant_elemental_end(bl,type); - break; - case SC_ARMOR_PROPERTY: - // val1 : Element Lvl (if called by skill lvl 1, takes random value between 1 and 4) - // val2 : Element (When no element, random one is picked) - // val3 : 0 = called by skill 1 = called by script (fixed level) - if( !val2 ) val2 = rnd()%ELE_MAX; - - if( val1 == 1 && val3 == 0 ) - val1 = 1 + rnd()%4; - else if( val1 > 4 ) - val1 = 4; // Max Level - val3 = 0; // Not need to keep this info. + case SC_FOOD_STR: + status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER); break; - case SC_PROVIDENCE: - val2=val1*5; //Race/Ele resist + case SC_FOOD_AGI: + status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER); break; - case SC_REFLECTSHIELD: - val2=10+val1*3; // %Dmg reflected - if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) ) { - struct map_session_data *tsd; - if( sd ) { - int i; - for( i = 0; i < 5; i++ ) { - if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) ) - status->change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); - } - } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) - status->change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); - } + case SC_FOOD_VIT: + status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER); break; - case SC_NOEQUIPWEAPON: - if (!sd) //Watk reduction - val2 = 25; + case SC_FOOD_INT: + status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER); break; - case SC_NOEQUIPSHIELD: - if (!sd) //Def reduction - val2 = 15; + case SC_FOOD_DEX: + status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER); break; - case SC_NOEQUIPARMOR: - if (!sd) //Vit reduction - val2 = 40; + case SC_FOOD_LUK: + status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER); break; - case SC_NOEQUIPHELM: - if (!sd) //Int reduction - val2 = 40; + case SC_FOOD_STR_CASH: + status_change_end(bl, SC_FOOD_STR, INVALID_TIMER); break; - case SC_AUTOSPELL: - //Val1 Skill LV of Autospell - //Val2 Skill ID to cast - //Val3 Max Lv to cast - val4 = 5 + val1*2; //Chance of casting + case SC_FOOD_AGI_CASH: + status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER); break; - case SC_VOLCANO: - val2 = val1*10; //Watk increase -#ifndef RENEWAL - if (st->def_ele != ELE_FIRE) - val2 = 0; -#endif + case SC_FOOD_VIT_CASH: + status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER); break; - case SC_VIOLENTGALE: - val2 = val1*3; //Flee increase -#ifndef RENEWAL - if (st->def_ele != ELE_WIND) - val2 = 0; -#endif + case SC_FOOD_INT_CASH: + status_change_end(bl, SC_FOOD_INT, INVALID_TIMER); break; - case SC_DELUGE: - val2 = skill->deluge_eff[val1-1]; //HP increase -#ifndef RENEWAL - if(st->def_ele != ELE_WATER) - val2 = 0; -#endif + case SC_FOOD_DEX_CASH: + status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER); break; - case SC_NJ_SUITON: - if (!val2 || (sd && (sd->class_&MAPID_BASEMASK) == MAPID_NINJA)) { - //No penalties. - val2 = 0; //Agi penalty - val3 = 0; //Walk speed penalty - break; - } - val3 = 50; - val2 = 3*((val1+1)/3); - if (val1 > 4) val2--; - break; - case SC_ONEHANDQUICKEN: - case SC_TWOHANDQUICKEN: - val2 = 300; - if (val1 > 10) //For boss casted skills [Skotlex] - val2 += 20*(val1-10); - break; - case SC_MER_QUICKEN: - val2 = 300; + case SC_FOOD_LUK_CASH: + status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER); break; -#ifndef RENEWAL_ASPD - case SC_SPEARQUICKEN: - val2 = 200+10*val1; - break; -#endif - case SC_DANCING: - //val1 : Skill ID + LV - //val2 : Skill Group of the Dance. - //val3 : Brings the skill_lv (merged into val1 here) - //val4 : Partner - if (val1 == CG_MOONLIT) - clif->status_change(bl,SI_MOON,1,tick,0, 0, 0); - val1|= (val3<<16); - val3 = tick/1000; //Tick duration - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_LONGING: -#ifdef RENEWAL - val2 = 50 + 10 * val1; -#else - val2 = 500-100*val1; //Aspd penalty. -#endif + case SC_ENDURE: + if( val4 ) + status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); break; - case SC_EXPLOSIONSPIRITS: - val2 = 75 + 25*val1; //Cri bonus + case SC_FIGHTINGSPIRIT: + status_change_end(bl, type, INVALID_TIMER); // Remove previous one. break; - - case SC_ATTHASTE_POTION1: - case SC_ATTHASTE_POTION2: - case SC_ATTHASTE_POTION3: - case SC_ATTHASTE_INFINITY: - val2 = 50*(2+type-SC_ATTHASTE_POTION1); + case SC_MARSHOFABYSS: + status_change_end(bl, SC_INCAGI, INVALID_TIMER); + status_change_end(bl, SC_WINDWALK, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); break; - - case SC_WEDDING: - case SC_XMAS: - case SC_SUMMER: - case SC_HANBOK: - if (!vd) return 0; - //Store previous values as they could be removed. - unit->stop_attack(bl); + case SC_SWING: + case SC_SYMPHONY_LOVE: + case SC_MOONLIT_SERENADE: + case SC_RUSH_WINDMILL: + case SC_ECHOSONG: + case SC_HARMONIZE: //group A doesn't overlap + if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER); + if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER); + if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER); + if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER); + if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); + if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); break; - case SC_NOCHAT: - // [GodLesZ] FIXME: is this correct? a hardcoded interval of 60sec? what about configuration ?_? - tick = 60000; - val1 = battle_config.manner_system; //Mute filters. - if (sd) - { - clif->changestatus(sd,SP_MANNER,sd->status.manner); - clif->updatestatus(sd,SP_MANNER); + case SC_SIREN: + case SC_DEEP_SLEEP: + case SC_GLOOMYDAY: + case SC_SONG_OF_MANA: + case SC_DANCE_WITH_WUG: + case SC_SATURDAY_NIGHT_FEVER: + case SC_LERADS_DEW: + case SC_MELODYOFSINK: + case SC_BEYOND_OF_WARCRY: + case SC_UNLIMITED_HUMMING_VOICE: //group B + if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER); + if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER); + if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER); + if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); + if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER); + if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER); + if (type != SC_GLOOMYDAY) { + status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER); + status_change_end(bl, SC_GLOOMYDAY_SK, INVALID_TIMER); } - break; - - case SC_STONE: - val3 = tick/1000; //Petrified HP-damage iterations. - if(val3 < 1) val3 = 1; - tick = val4; //Petrifying time. - if(val4 > 500) // not with WL_SIENNAEXECRATE - tick = max(tick, 1000); //Min time - calc_flag = 0; //Actual status changes take effect on petrified state. - break; - - case SC_DPOISON: - //Lose 10/15% of your life as long as it doesn't brings life below 25% - if (st->hp > st->max_hp>>2) { - int diff = st->max_hp*(bl->type==BL_PC?10:15)/100; - if (st->hp - diff < st->max_hp>>2) - diff = st->hp - (st->max_hp>>2); - if( val2 && bl->type == BL_MOB ) { - struct block_list* src = map->id2bl(val2); - if( src ) - mob->log_damage((TBL_MOB*)bl,src,diff); + if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER); + if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER); + if (type != SC_SATURDAY_NIGHT_FEVER) { + if (sc->data[SC_SATURDAY_NIGHT_FEVER]) { + sc->data[SC_SATURDAY_NIGHT_FEVER]->val2 = 0; //mark to not lose hp + status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER); } - status_zap(bl, diff, 0); } - // fall through - case SC_POISON: - val3 = tick/1000; //Damage iterations - if(val3 < 1) val3 = 1; - tick_time = 1000; // [GodLesZ] tick time - //val4: HP damage - if (bl->type == BL_PC) - val4 = (type == SC_DPOISON) ? 3 + st->max_hp/50 : 3 + st->max_hp*3/200; - else - val4 = (type == SC_DPOISON) ? 3 + st->max_hp/100 : 3 + st->max_hp/200; - - break; - case SC_CONFUSION: - clif->emotion(bl,E_WHAT); break; - case SC_BLOODING: - val4 = tick/10000; - if (!val4) val4 = 1; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_S_LIFEPOTION: - case SC_L_LIFEPOTION: - if( val1 == 0 ) return 0; - // val1 = heal percent/amout - // val2 = seconds between heals - // val4 = total of heals - if( val2 < 1 ) val2 = 1; - if( (val4 = tick/(val2 * 1000)) < 1 ) - val4 = 1; - tick_time = val2 * 1000; // [GodLesZ] tick time + case SC_REFLECTSHIELD: + status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER); break; - case SC_CASH_BOSS_ALARM: - if( sd != NULL ) { - struct mob_data *boss_md = map->getmob_boss(bl->m); // Search for Boss on this Map - if( boss_md == NULL || boss_md->bl.prev == NULL ) { - // No MVP on this map - MVP is dead - clif->bossmapinfo(sd->fd, boss_md, 1); - return 0; // No need to start SC - } - val1 = boss_md->bl.id; - if( (val4 = tick/1000) < 1 ) - val4 = 1; - tick_time = 1000; // [GodLesZ] tick time - } + case SC_LG_REFLECTDAMAGE: + status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); break; - case SC_HIDING: - val2 = tick/1000; - tick_time = 1000; // [GodLesZ] tick time - val3 = 0; // unused, previously speed adjustment - val4 = val1+3; //Seconds before SP substraction happen. + case SC_SHIELDSPELL_DEF: + case SC_SHIELDSPELL_MDEF: + case SC_SHIELDSPELL_REF: + status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER); + if( type != SC_SHIELDSPELL_DEF ) + status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER); + if( type != SC_SHIELDSPELL_MDEF ) + status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER); + if( type != SC_SHIELDSPELL_REF ) + status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER); + break; + case SC_GENTLETOUCH_ENERGYGAIN: + case SC_GENTLETOUCH_CHANGE: + case SC_GENTLETOUCH_REVITALIZE: + if( type != SC_GENTLETOUCH_REVITALIZE ) + status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER); + if( type != SC_GENTLETOUCH_ENERGYGAIN ) + status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER); + if( type != SC_GENTLETOUCH_CHANGE ) + status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER); break; - case SC_CHASEWALK: - val2 = tick>0?tick:10000; //Interval at which SP is drained. - val3 = 35 - 5 * val1; //Speed adjustment. - if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_ROGUE) - val3 -= 40; - val4 = 10+val1*2; //SP cost. - if (map_flag_gvg(bl->m) || map->list[bl->m].flag.battleground) val4 *= 5; + case SC_INVINCIBLE: + status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER); break; - case SC_CLOAKING: - if (!sd) //Monsters should be able to walk with no penalties. [Skotlex] - val1 = 10; - tick_time = val2 = tick>0?tick:60000; //SP consumption rate. - tick = -1; // duration sent to the client should be infinite - val3 = 0; // unused, previously walk speed adjustment - //val4&1 signals the presence of a wall. - //val4&2 makes cloak not end on normal attacks [Skotlex] - //val4&4 makes cloak not end on using skills - if (bl->type == BL_PC || (bl->type == BL_MOB && ((TBL_MOB*)bl)->special_state.clone) ) //Standard cloaking. - val4 |= battle_config.pc_cloak_check_type&7; - else - val4 |= battle_config.monster_cloak_check_type&7; + case SC_INVINCIBLEOFF: + status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER); break; - case SC_SIGHT: /* splash status */ - 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 + case SC_MAGICPOWER: + status_change_end(bl, type, INVALID_TIMER); break; + } - //Permanent effects. - case SC_LEXAETERNA: - case SC_MODECHANGE: - case SC_WEIGHTOVER50: - case SC_WEIGHTOVER90: - case SC_BROKENWEAPON: - case SC_BROKENARMOR: - case SC_STORMKICK_READY: - case SC_DOWNKICK_READY: - case SC_COUNTERKICK_READY: - case SC_TURNKICK_READY: - case SC_DODGE_READY: - case SC_PUSH_CART: - case SC_ALL_RIDING: - tick = -1; - break; - - case SC_AUTOGUARD: - if( !(flag&1) ) { - struct map_session_data *tsd; - int i,t; - for( i = val2 = 0; i < val1; i++) { - t = 5-(i>>1); - val2 += (t < 0)? 1:t; + //Check for overlapping fails + if( (sce = sc->data[type]) ) { + switch( type ) { + case SC_MER_FLEE: + case SC_MER_ATK: + case SC_MER_HP: + case SC_MER_SP: + case SC_MER_HIT: + if( sce->val1 > val1 ) + val1 = sce->val1; + break; + case SC_ADRENALINE: + case SC_ADRENALINE2: + case SC_WEAPONPERFECT: + case SC_OVERTHRUST: + if (sce->val2 > val2) + return 0; + break; + case SC_S_LIFEPOTION: + case SC_L_LIFEPOTION: + case SC_CASH_BOSS_ALARM: + case SC_STUN: + case SC_SLEEP: + case SC_POISON: + case SC_CURSE: + case SC_SILENCE: + case SC_CONFUSION: + case SC_BLIND: + case SC_BLOODING: + case SC_DPOISON: + case SC_RG_CCONFINE_S: //Can't be re-closed in. + case SC_MARIONETTE_MASTER: + case SC_MARIONETTE: + case SC_NOCHAT: + case SC_HLIF_CHANGE: //Otherwise your Hp/Sp would get refilled while still within effect of the last invocation. + case SC__INVISIBILITY: + case SC__ENERVATION: + case SC__GROOMY: + case SC__IGNORANCE: + case SC__LAZINESS: + case SC__WEAKNESS: + case SC__UNLUCKY: + return 0; + case SC_COMBOATTACK: + case SC_DANCING: + case SC_DEVOTION: + case SC_ATTHASTE_POTION1: + case SC_ATTHASTE_POTION2: + case SC_ATTHASTE_POTION3: + case SC_ATTHASTE_INFINITY: + case SC_PLUSATTACKPOWER: + case SC_PLUSMAGICPOWER: + case SC_ENCHANTARMS: + case SC_ARMORPROPERTY: + case SC_ARMOR_RESIST: + break; + case SC_GOSPEL: + //Must not override a casting gospel char. + if(sce->val4 == BCT_SELF) + return 0; + if(sce->val1 > val1) + return 1; + break; + case SC_ENDURE: + if(sce->val4 && !val4) + return 1; //Don't let you override infinite endure. + if(sce->val1 > val1) + return 1; + break; + case SC_KAAHI: + //Kaahi overwrites previous level regardless of existing level. + //Delete timer if it exists. + if (sce->val4 != INVALID_TIMER) { + timer->delete(sce->val4,status->kaahi_heal_timer); + sce->val4 = INVALID_TIMER; } + break; + case SC_JAILED: + //When a player is already jailed, do not edit the jail data. + val2 = sce->val2; + val3 = sce->val3; + val4 = sce->val4; + break; + case SC_LERADS_DEW: + if (sc && sc->data[SC_BERSERK]) + return 0; + case SC_SHAPESHIFT: + case SC_PROPERTYWALK: + break; + case SC_LEADERSHIP: + case SC_GLORYWOUNDS: + case SC_SOULCOLD: + case SC_HAWKEYES: + if( sce->val4 && !val4 )//you cannot override master guild aura + return 0; + break; + case SC_JOINTBEAT: + val2 |= sce->val2; // stackable ailments + default: + if(sce->val1 > val1) + return 1; //Return true to not mess up skill animations. [Skotlex] + } + } - if( bl->type&(BL_PC|BL_MER) ) { + vd = status->get_viewdata(bl); + calc_flag = status->ChangeFlagTable[type]; + if(!(flag&4)) { //&4 - Do not parse val settings when loading SCs + switch(type) { + case SC_DEC_AGI: + case SC_INC_AGI: + val2 = 2 + val1; //Agi change + break; + case SC_ENDURE: + val2 = 7; // Hit-count [Celest] + if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground && !val4 ) { + struct map_session_data *tsd; + if( sd ) { + int i; + for( i = 0; i < 5; i++ ) { + if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) ) + status->change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); + } + } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + status->change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); + } + //val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk) + if( val4 ) + tick = -1; + break; + case SC_AUTOBERSERK: + if (st->hp < st->max_hp>>2 && + (!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0)) + sc_start4(bl,SC_PROVOKE,100,10,1,0,0,60000); + tick = -1; + break; + case SC_CRUCIS: + val2 = 10 + 4*val1; //Def reduction + tick = -1; + clif->emotion(bl,E_SWT); + break; + case SC_MAXIMIZEPOWER: + tick_time = val2 = tick>0?tick:60000; + tick = -1; // duration sent to the client should be infinite + break; + case SC_EDP: // [Celest] + val2 = val1 + 2; //Chance to Poison enemies. + val3 = 50*(val1+1); //Damage increase (+50 +50*lv%) + #ifdef RENEWAL_EDP + val4 = 100 * ((val1 + 1)/2 + 2); + #endif + if( sd )//[Ind] - iROwiki says each level increases its duration by 3 seconds + tick += pc->checkskill(sd,GC_RESEARCHNEWPOISON)*3000; + break; + case SC_POISONREACT: + val2=(val1+1)/2 + val1/10; // Number of counters [Skotlex] + val3=50; // + 5*val1; //Chance to counter. [Skotlex] + break; + case SC_MAGICROD: + val2 = val1*20; //SP gained + break; + case SC_KYRIE: + val2 = (int64)st->max_hp * (val1 * 2 + 10) / 100; //%Max HP to absorb + val3 = (val1 / 2 + 5); //Hits + break; + case SC_MAGICPOWER: + //val1: Skill lv + val2 = 1; //Lasts 1 invocation + val3 = 5*val1; //Matk% increase + val4 = 0; // 0 = ready to be used, 1 = activated and running + break; + case SC_SACRIFICE: + val2 = 5; //Lasts 5 hits + tick = -1; + break; + case SC_ENCHANTPOISON: + val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate + case SC_ASPERSIO: + case SC_PROPERTYFIRE: + case SC_PROPERTYWATER: + case SC_PROPERTYWIND: + case SC_PROPERTYGROUND: + case SC_PROPERTYDARK: + case SC_PROPERTYTELEKINESIS: + skill->enchant_elemental_end(bl,type); + break; + case SC_ARMOR_PROPERTY: + // val1 : Element Lvl (if called by skill lvl 1, takes random value between 1 and 4) + // val2 : Element (When no element, random one is picked) + // val3 : 0 = called by skill 1 = called by script (fixed level) + if( !val2 ) val2 = rnd()%ELE_MAX; + + if( val1 == 1 && val3 == 0 ) + val1 = 1 + rnd()%4; + else if( val1 > 4 ) + val1 = 4; // Max Level + val3 = 0; // Not need to keep this info. + break; + case SC_PROVIDENCE: + val2=val1*5; //Race/Ele resist + break; + case SC_REFLECTSHIELD: + val2=10+val1*3; // %Dmg reflected + if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) ) { + struct map_session_data *tsd; if( sd ) { + int i; for( i = 0; i < 5; i++ ) { if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) ) status->change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); } - } - else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) status->change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); } - } - break; + break; + case SC_NOEQUIPWEAPON: + if (!sd) //Watk reduction + val2 = 25; + break; + case SC_NOEQUIPSHIELD: + if (!sd) //Def reduction + val2 = 15; + break; + case SC_NOEQUIPARMOR: + if (!sd) //Vit reduction + val2 = 40; + break; + case SC_NOEQUIPHELM: + if (!sd) //Int reduction + val2 = 40; + break; + case SC_AUTOSPELL: + //Val1 Skill LV of Autospell + //Val2 Skill ID to cast + //Val3 Max Lv to cast + val4 = 5 + val1*2; //Chance of casting + break; + case SC_VOLCANO: + val2 = val1*10; //Watk increase + #ifndef RENEWAL + if (st->def_ele != ELE_FIRE) + val2 = 0; + #endif + break; + case SC_VIOLENTGALE: + val2 = val1*3; //Flee increase + #ifndef RENEWAL + if (st->def_ele != ELE_WIND) + val2 = 0; + #endif + break; + case SC_DELUGE: + val2 = skill->deluge_eff[val1-1]; //HP increase + #ifndef RENEWAL + if(st->def_ele != ELE_WATER) + val2 = 0; + #endif + break; + case SC_NJ_SUITON: + if (!val2 || (sd && (sd->class_&MAPID_BASEMASK) == MAPID_NINJA)) { + //No penalties. + val2 = 0; //Agi penalty + val3 = 0; //Walk speed penalty + break; + } + val3 = 50; + val2 = 3*((val1+1)/3); + if (val1 > 4) val2--; + break; + case SC_ONEHANDQUICKEN: + case SC_TWOHANDQUICKEN: + val2 = 300; + if (val1 > 10) //For boss casted skills [Skotlex] + val2 += 20*(val1-10); + break; + case SC_MER_QUICKEN: + val2 = 300; + break; + #ifndef RENEWAL_ASPD + case SC_SPEARQUICKEN: + val2 = 200+10*val1; + break; + #endif + case SC_DANCING: + //val1 : Skill ID + LV + //val2 : Skill Group of the Dance. + //val3 : Brings the skill_lv (merged into val1 here) + //val4 : Partner + if (val1 == CG_MOONLIT) + clif->status_change(bl,SI_MOON,1,tick,0, 0, 0); + val1|= (val3<<16); + val3 = tick/1000; //Tick duration + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_LONGING: + #ifdef RENEWAL + val2 = 50 + 10 * val1; + #else + val2 = 500-100*val1; //Aspd penalty. + #endif + break; + case SC_EXPLOSIONSPIRITS: + val2 = 75 + 25*val1; //Cri bonus + break; + + case SC_ATTHASTE_POTION1: + case SC_ATTHASTE_POTION2: + case SC_ATTHASTE_POTION3: + case SC_ATTHASTE_INFINITY: + val2 = 50*(2+type-SC_ATTHASTE_POTION1); + break; + + case SC_WEDDING: + case SC_XMAS: + case SC_SUMMER: + case SC_HANBOK: + if (!vd) return 0; + //Store previous values as they could be removed. + unit->stop_attack(bl); + break; + case SC_NOCHAT: + // [GodLesZ] FIXME: is this correct? a hardcoded interval of 60sec? what about configuration ?_? + tick = 60000; + val1 = battle_config.manner_system; //Mute filters. + if (sd) + { + clif->changestatus(sd,SP_MANNER,sd->status.manner); + clif->updatestatus(sd,SP_MANNER); + } + break; + + case SC_STONE: + val3 = tick/1000; //Petrified HP-damage iterations. + if(val3 < 1) val3 = 1; + tick = val4; //Petrifying time. + if(val4 > 500) // not with WL_SIENNAEXECRATE + tick = max(tick, 1000); //Min time + calc_flag = 0; //Actual status changes take effect on petrified state. + break; - case SC_DEFENDER: - if (!(flag&1)) { - val2 = 5 + 15*val1; //Damage reduction + case SC_DPOISON: + //Lose 10/15% of your life as long as it doesn't brings life below 25% + if (st->hp > st->max_hp>>2) { + int diff = st->max_hp*(bl->type==BL_PC?10:15)/100; + if (st->hp - diff < st->max_hp>>2) + diff = st->hp - (st->max_hp>>2); + if( val2 && bl->type == BL_MOB ) { + struct block_list* src = map->id2bl(val2); + if( src ) + mob->log_damage((TBL_MOB*)bl,src,diff); + } + status_zap(bl, diff, 0); + } + // fall through + case SC_POISON: + val3 = tick/1000; //Damage iterations + if(val3 < 1) val3 = 1; + tick_time = 1000; // [GodLesZ] tick time + //val4: HP damage + if (bl->type == BL_PC) + val4 = (type == SC_DPOISON) ? 3 + st->max_hp/50 : 3 + st->max_hp*3/200; + else + val4 = (type == SC_DPOISON) ? 3 + st->max_hp/100 : 3 + st->max_hp/200; + + break; + case SC_CONFUSION: + clif->emotion(bl,E_WHAT); + break; + case SC_BLOODING: + val4 = tick/10000; + if (!val4) val4 = 1; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_S_LIFEPOTION: + case SC_L_LIFEPOTION: + if( val1 == 0 ) return 0; + // val1 = heal percent/amout + // val2 = seconds between heals + // val4 = total of heals + if( val2 < 1 ) val2 = 1; + if( (val4 = tick/(val2 * 1000)) < 1 ) + val4 = 1; + tick_time = val2 * 1000; // [GodLesZ] tick time + break; + case SC_CASH_BOSS_ALARM: + if( sd != NULL ) { + struct mob_data *boss_md = map->getmob_boss(bl->m); // Search for Boss on this Map + if( boss_md == NULL || boss_md->bl.prev == NULL ) { + // No MVP on this map - MVP is dead + clif->bossmapinfo(sd->fd, boss_md, 1); + return 0; // No need to start SC + } + val1 = boss_md->bl.id; + if( (val4 = tick/1000) < 1 ) + val4 = 1; + tick_time = 1000; // [GodLesZ] tick time + } + break; + case SC_HIDING: + val2 = tick/1000; + tick_time = 1000; // [GodLesZ] tick time val3 = 0; // unused, previously speed adjustment - val4 = 250 - 50*val1; //Aspd adjustment + val4 = val1+3; //Seconds before SP substraction happen. + break; + case SC_CHASEWALK: + val2 = tick>0?tick:10000; //Interval at which SP is drained. + val3 = 35 - 5 * val1; //Speed adjustment. + if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_ROGUE) + val3 -= 40; + val4 = 10+val1*2; //SP cost. + if (map_flag_gvg(bl->m) || map->list[bl->m].flag.battleground) val4 *= 5; + break; + case SC_CLOAKING: + if (!sd) //Monsters should be able to walk with no penalties. [Skotlex] + val1 = 10; + tick_time = val2 = tick>0?tick:60000; //SP consumption rate. + tick = -1; // duration sent to the client should be infinite + val3 = 0; // unused, previously walk speed adjustment + //val4&1 signals the presence of a wall. + //val4&2 makes cloak not end on normal attacks [Skotlex] + //val4&4 makes cloak not end on using skills + if (bl->type == BL_PC || (bl->type == BL_MOB && ((TBL_MOB*)bl)->special_state.clone) ) //Standard cloaking. + val4 |= battle_config.pc_cloak_check_type&7; + else + val4 |= battle_config.monster_cloak_check_type&7; + break; + case SC_SIGHT: /* splash status */ + 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 + break; - if (sd) { + //Permanent effects. + case SC_LEXAETERNA: + case SC_MODECHANGE: + case SC_WEIGHTOVER50: + case SC_WEIGHTOVER90: + case SC_BROKENWEAPON: + case SC_BROKENARMOR: + case SC_STORMKICK_READY: + case SC_DOWNKICK_READY: + case SC_COUNTERKICK_READY: + case SC_TURNKICK_READY: + case SC_DODGE_READY: + case SC_PUSH_CART: + case SC_ALL_RIDING: + tick = -1; + break; + + case SC_AUTOGUARD: + if( !(flag&1) ) { struct map_session_data *tsd; - int i; - for (i = 0; i < 5; i++) { - //See if there are devoted characters, and pass the status to them. [Skotlex] - if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i]))) - status->change_start(&tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1); + int i,t; + for( i = val2 = 0; i < val1; i++) { + t = 5-(i>>1); + val2 += (t < 0)? 1:t; + } + + if( bl->type&(BL_PC|BL_MER) ) { + if( sd ) { + for( i = 0; i < 5; i++ ) { + if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) ) + status->change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + } + } + else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + status->change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); } } - } - break; + break; - case SC_TENSIONRELAX: - if (sd) { - pc_setsit(sd); - clif->sitting(&sd->bl); - } - val2 = 12; //SP cost - val4 = 10000; //Decrease at 10secs intervals. - val3 = tick/val4; - tick = -1; // duration sent to the client should be infinite - tick_time = val4; // [GodLesZ] tick time - break; - case SC_PARRYING: - val2 = 20 + val1*3; //Block Chance - break; + case SC_DEFENDER: + if (!(flag&1)) { + val2 = 5 + 15*val1; //Damage reduction + val3 = 0; // unused, previously speed adjustment + val4 = 250 - 50*val1; //Aspd adjustment + + if (sd) { + struct map_session_data *tsd; + int i; + for (i = 0; i < 5; i++) { + //See if there are devoted characters, and pass the status to them. [Skotlex] + if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i]))) + status->change_start(&tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1); + } + } + } + break; - case SC_WINDWALK: - val2 = (val1+1)/2; // Flee bonus is 1/1/2/2/3/3/4/4/5/5 - break; + case SC_TENSIONRELAX: + if (sd) { + pc_setsit(sd); + clif->sitting(&sd->bl); + } + val2 = 12; //SP cost + val4 = 10000; //Decrease at 10secs intervals. + val3 = tick/val4; + tick = -1; // duration sent to the client should be infinite + tick_time = val4; // [GodLesZ] tick time + break; + case SC_PARRYING: + val2 = 20 + val1*3; //Block Chance + break; - case SC_JOINTBEAT: - if( val2&BREAK_NECK ) - sc_start2(bl,SC_BLOODING,100,val1,val3,skill->get_time2(status->sc2skill(type),val1)); - break; + case SC_WINDWALK: + val2 = (val1+1)/2; // Flee bonus is 1/1/2/2/3/3/4/4/5/5 + break; - case SC_BERSERK: - if( val3 == SC__BLOODYLUST ) - sc_start(bl,(sc_type)val3,100,val1,tick); - if( !val3 && !(!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4) ) - sc_start4(bl, SC_ENDURE, 100,10,0,0,2, tick); - //HP healing is performing after the calc_status call. - //Val2 holds HP penalty - if (!val4) val4 = skill->get_time2(status->sc2skill(type),val1); - if (!val4) val4 = 10000; //Val4 holds damage interval - val3 = tick/val4; //val3 holds skill duration - tick_time = val4; // [GodLesZ] tick time - break; - - case SC_GOSPEL: - if(val4 == BCT_SELF) { - // self effect - val2 = tick/10000; - tick_time = 10000; // [GodLesZ] tick time - status->change_clear_buffs(bl,3); //Remove buffs/debuffs - } - break; + case SC_JOINTBEAT: + if( val2&BREAK_NECK ) + sc_start2(bl,SC_BLOODING,100,val1,val3,skill->get_time2(status->sc2skill(type),val1)); + break; - case SC_MARIONETTE_MASTER: - { - int stat; + case SC_BERSERK: + if( val3 == SC__BLOODYLUST ) + sc_start(bl,(sc_type)val3,100,val1,tick); + if( !val3 && !(!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4) ) + sc_start4(bl, SC_ENDURE, 100,10,0,0,2, tick); + //HP healing is performing after the calc_status call. + //Val2 holds HP penalty + if (!val4) val4 = skill->get_time2(status->sc2skill(type),val1); + if (!val4) val4 = 10000; //Val4 holds damage interval + val3 = tick/val4; //val3 holds skill duration + tick_time = val4; // [GodLesZ] tick time + break; - val3 = 0; - val4 = 0; - stat = ( sd ? sd->status.str : status->get_base_status(bl)->str ) / 2; val3 |= cap_value(stat,0,0xFF)<<16; - stat = ( sd ? sd->status.agi : status->get_base_status(bl)->agi ) / 2; val3 |= cap_value(stat,0,0xFF)<<8; - stat = ( sd ? sd->status.vit : status->get_base_status(bl)->vit ) / 2; val3 |= cap_value(stat,0,0xFF); - stat = ( sd ? sd->status.int_: status->get_base_status(bl)->int_) / 2; val4 |= cap_value(stat,0,0xFF)<<16; - stat = ( sd ? sd->status.dex : status->get_base_status(bl)->dex ) / 2; val4 |= cap_value(stat,0,0xFF)<<8; - stat = ( sd ? sd->status.luk : status->get_base_status(bl)->luk ) / 2; val4 |= cap_value(stat,0,0xFF); - } - break; - case SC_MARIONETTE: - { - int stat,max_stat; - // fetch caster information - struct block_list *pbl = map->id2bl(val1); - struct status_change *psc = pbl ? status->get_sc(pbl) : NULL; - struct status_change_entry *psce = psc ? psc->data[SC_MARIONETTE_MASTER] : NULL; - // fetch target's stats - struct status_data* tst = status->get_status_data(bl); // battle status - - if (!psce) - return 0; + case SC_GOSPEL: + if(val4 == BCT_SELF) { + // self effect + val2 = tick/10000; + tick_time = 10000; // [GodLesZ] tick time + status->change_clear_buffs(bl,3); //Remove buffs/debuffs + } + break; - val3 = 0; - val4 = 0; - max_stat = battle_config.max_parameter; //Cap to 99 (default) - stat = (psce->val3 >>16)&0xFF; stat = min(stat, max_stat - tst->str ); val3 |= cap_value(stat,0,0xFF)<<16; - stat = (psce->val3 >> 8)&0xFF; stat = min(stat, max_stat - tst->agi ); val3 |= cap_value(stat,0,0xFF)<<8; - stat = (psce->val3 >> 0)&0xFF; stat = min(stat, max_stat - tst->vit ); val3 |= cap_value(stat,0,0xFF); - stat = (psce->val4 >>16)&0xFF; stat = min(stat, max_stat - tst->int_); val4 |= cap_value(stat,0,0xFF)<<16; - stat = (psce->val4 >> 8)&0xFF; stat = min(stat, max_stat - tst->dex ); val4 |= cap_value(stat,0,0xFF)<<8; - stat = (psce->val4 >> 0)&0xFF; stat = min(stat, max_stat - tst->luk ); val4 |= cap_value(stat,0,0xFF); - } - break; - case SC_SWORDREJECT: - val2 = 15*val1; //Reflect chance - val3 = 3; //Reflections - tick = -1; - break; + case SC_MARIONETTE_MASTER: + { + int stat; + + val3 = 0; + val4 = 0; + stat = ( sd ? sd->status.str : status->get_base_status(bl)->str ) / 2; val3 |= cap_value(stat,0,0xFF)<<16; + stat = ( sd ? sd->status.agi : status->get_base_status(bl)->agi ) / 2; val3 |= cap_value(stat,0,0xFF)<<8; + stat = ( sd ? sd->status.vit : status->get_base_status(bl)->vit ) / 2; val3 |= cap_value(stat,0,0xFF); + stat = ( sd ? sd->status.int_: status->get_base_status(bl)->int_) / 2; val4 |= cap_value(stat,0,0xFF)<<16; + stat = ( sd ? sd->status.dex : status->get_base_status(bl)->dex ) / 2; val4 |= cap_value(stat,0,0xFF)<<8; + stat = ( sd ? sd->status.luk : status->get_base_status(bl)->luk ) / 2; val4 |= cap_value(stat,0,0xFF); + } + break; + case SC_MARIONETTE: + { + int stat,max_stat; + // fetch caster information + struct block_list *pbl = map->id2bl(val1); + struct status_change *psc = pbl ? status->get_sc(pbl) : NULL; + struct status_change_entry *psce = psc ? psc->data[SC_MARIONETTE_MASTER] : NULL; + // fetch target's stats + struct status_data* tst = status->get_status_data(bl); // battle status + + if (!psce) + return 0; - case SC_MEMORIZE: - val2 = 5; //Memorized casts. - tick = -1; - break; + val3 = 0; + val4 = 0; + max_stat = battle_config.max_parameter; //Cap to 99 (default) + stat = (psce->val3 >>16)&0xFF; stat = min(stat, max_stat - tst->str ); val3 |= cap_value(stat,0,0xFF)<<16; + stat = (psce->val3 >> 8)&0xFF; stat = min(stat, max_stat - tst->agi ); val3 |= cap_value(stat,0,0xFF)<<8; + stat = (psce->val3 >> 0)&0xFF; stat = min(stat, max_stat - tst->vit ); val3 |= cap_value(stat,0,0xFF); + stat = (psce->val4 >>16)&0xFF; stat = min(stat, max_stat - tst->int_); val4 |= cap_value(stat,0,0xFF)<<16; + stat = (psce->val4 >> 8)&0xFF; stat = min(stat, max_stat - tst->dex ); val4 |= cap_value(stat,0,0xFF)<<8; + stat = (psce->val4 >> 0)&0xFF; stat = min(stat, max_stat - tst->luk ); val4 |= cap_value(stat,0,0xFF); + } + break; + case SC_SWORDREJECT: + val2 = 15*val1; //Reflect chance + val3 = 3; //Reflections + tick = -1; + break; - case SC_GRAVITATION: - val2 = 50*val1; //aspd reduction - break; + case SC_MEMORIZE: + val2 = 5; //Memorized casts. + tick = -1; + break; - case SC_GDSKILL_REGENERATION: - if (val1 == 1) - val2 = 2; - else - val2 = val1; //HP Regerenation rate: 200% 200% 300% - val3 = val1; //SP Regeneration Rate: 100% 200% 300% - //if val4 comes set, this blocks regen rather than increase it. - break; + case SC_GRAVITATION: + val2 = 50*val1; //aspd reduction + break; - case SC_DEVOTION: - { - struct block_list *d_bl; - struct status_change *d_sc; - - if( (d_bl = map->id2bl(val1)) && (d_sc = status->get_sc(d_bl)) && d_sc->count ) { - // Inherits Status From Source - const enum sc_type types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE }; - enum sc_type type2; - int i = (map_flag_gvg(bl->m) || map->list[bl->m].flag.battleground)?2:3; - while( i >= 0 ) { - type2 = types[i]; - if( d_sc->data[type2] ) - sc_start(bl, type2, 100, d_sc->data[type2]->val1, skill->get_time(status->sc2skill(type2),d_sc->data[type2]->val1)); - i--; + case SC_GDSKILL_REGENERATION: + if (val1 == 1) + val2 = 2; + else + val2 = val1; //HP Regerenation rate: 200% 200% 300% + val3 = val1; //SP Regeneration Rate: 100% 200% 300% + //if val4 comes set, this blocks regen rather than increase it. + break; + + case SC_DEVOTION: + { + struct block_list *d_bl; + struct status_change *d_sc; + + if( (d_bl = map->id2bl(val1)) && (d_sc = status->get_sc(d_bl)) && d_sc->count ) { + // Inherits Status From Source + const enum sc_type types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE }; + enum sc_type type2; + int i = (map_flag_gvg(bl->m) || map->list[bl->m].flag.battleground)?2:3; + while( i >= 0 ) { + type2 = types[i]; + if( d_sc->data[type2] ) + sc_start(bl, type2, 100, d_sc->data[type2]->val1, skill->get_time(status->sc2skill(type2),d_sc->data[type2]->val1)); + i--; + } } + break; } - break; - } - case SC_COMA: //Coma. Sends a char to 1HP. If val2, do not zap sp - if( val3 && bl->type == BL_MOB ) { - struct block_list* src = map->id2bl(val3); - if( src ) - mob->log_damage((TBL_MOB*)bl,src,st->hp - 1); + case SC_COMA: //Coma. Sends a char to 1HP. If val2, do not zap sp + if( val3 && bl->type == BL_MOB ) { + struct block_list* src = map->id2bl(val3); + if( src ) + mob->log_damage((TBL_MOB*)bl,src,st->hp - 1); + } + status_zap(bl, st->hp-1, val2 ? 0 : st->sp); + return 1; + break; + case SC_RG_CCONFINE_S: + { + struct block_list *src = val2 ? map->id2bl(val2) : NULL; + struct status_change *sc2 = src ? status->get_sc(src) : NULL; + struct status_change_entry *sce2 = sc2 ? sc2->data[SC_RG_CCONFINE_M] : NULL; + if (src && sc2) { + if (!sce2) //Start lock on caster. + sc_start4(src,SC_RG_CCONFINE_M,100,val1,1,0,0,tick+1000); + else { //Increase count of locked enemies and refresh time. + (sce2->val2)++; + timer->delete(sce2->timer, status->change_timer); + sce2->timer = timer->add(timer->gettick()+tick+1000, status->change_timer, src->id, SC_RG_CCONFINE_M); + } + } else //Status failed. + return 0; } - status_zap(bl, st->hp-1, val2 ? 0 : st->sp); - return 1; - break; - case SC_RG_CCONFINE_S: - { - struct block_list *src = val2 ? map->id2bl(val2) : NULL; - struct status_change *sc2 = src ? status->get_sc(src) : NULL; - struct status_change_entry *sce2 = sc2 ? sc2->data[SC_RG_CCONFINE_M] : NULL; - if (src && sc2) { - if (!sce2) //Start lock on caster. - sc_start4(src,SC_RG_CCONFINE_M,100,val1,1,0,0,tick+1000); - else { //Increase count of locked enemies and refresh time. - (sce2->val2)++; - timer->delete(sce2->timer, status->change_timer); - sce2->timer = timer->add(timer->gettick()+tick+1000, status->change_timer, src->id, SC_RG_CCONFINE_M); + break; + case SC_KAITE: + val2 = 1+val1/5; //Number of bounces: 1 + skill_lv/5 + break; + case SC_KAUPE: + switch (val1) { + case 3: //33*3 + 1 -> 100% + val2++; + case 1: + case 2: //33, 66% + val2 += 33*val1; + val3 = 1; //Dodge 1 attack total. + break; + default: //Custom. For high level mob usage, higher level means more blocks. [Skotlex] + val2 = 100; + val3 = val1-2; + break; } - } else //Status failed. - return 0; - } - break; - case SC_KAITE: - val2 = 1+val1/5; //Number of bounces: 1 + skill_lv/5 - break; - case SC_KAUPE: - switch (val1) { - case 3: //33*3 + 1 -> 100% - val2++; - case 1: - case 2: //33, 66% - val2 += 33*val1; - val3 = 1; //Dodge 1 attack total. break; - default: //Custom. For high level mob usage, higher level means more blocks. [Skotlex] - val2 = 100; - val3 = val1-2; + + case SC_COMBOATTACK: { + //val1: Skill ID + //val2: When given, target (for autotargetting skills) + //val3: When set, this combo time should NOT delay attack/movement + //val3: TK: Last used kick + //val4: TK: Combo time + struct unit_data *ud = unit->bl2ud(bl); + if (ud && !val3) { + tick += 300 * battle_config.combo_delay_rate/100; + ud->attackabletime = timer->gettick()+tick; + unit->set_walkdelay(bl, timer->gettick(), tick, 1); + } + val3 = 0; + val4 = tick; + } + break; + case SC_EARTHSCROLL: + val2 = 11-val1; //Chance to consume: 11-skill_lv% break; + case SC_RUN: + { + //Store time at which you started running. + int64 currenttick = timer->gettick(); + // Note: this int64 value is stored in two separate int32 variables (FIXME) + val3 = (int)(currenttick&0x00000000ffffffffLL); + val4 = (int)((currenttick&0xffffffff00000000LL)>>32); } - break; + tick = -1; + break; + case SC_KAAHI: + val2 = 200*val1; //HP heal + val3 = 5*val1; //SP cost + val4 = INVALID_TIMER; //Kaahi Timer. + break; + case SC_BLESSING: + if ((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC) + val2 = val1; + else + val2 = 0; //0 -> Half stat. + break; + case SC_TRICKDEAD: + if (vd) vd->dead_sit = 1; + tick = -1; + break; + case SC_CONCENTRATION: + val2 = 2 + val1; + if (sd) { //Store the card-bonus data that should not count in the % + val3 = sd->param_bonus[1]; //Agi + val4 = sd->param_bonus[4]; //Dex + } else { + val3 = val4 = 0; + } + break; + case SC_OVERTHRUSTMAX: + val2 = 20*val1; //Power increase + break; + case SC_OVERTHRUST: + //val2 holds if it was casted on self, or is bonus received from others + val3 = 5*val1; //Power increase + if(sd && pc->checkskill(sd,BS_HILTBINDING)>0) + tick += tick / 10; + break; + case SC_ADRENALINE2: + case SC_ADRENALINE: + val3 = (val2) ? 300 : 200; // aspd increase + case SC_WEAPONPERFECT: + if(sd && pc->checkskill(sd,BS_HILTBINDING)>0) + tick += tick / 10; + break; + case SC_LKCONCENTRATION: + val2 = 5*val1; //Batk/Watk Increase + val3 = 10*val1; //Hit Increase + val4 = 5*val1; //Def reduction + sc_start(bl, SC_ENDURE, 100, 1, tick); //Endure effect + break; + case SC_ANGELUS: + val2 = 5*val1; //def increase + break; + case SC_IMPOSITIO: + val2 = 5*val1; //watk increase + break; + case SC_MELTDOWN: + val2 = 100*val1; //Chance to break weapon + val3 = 70*val1; //Change to break armor + break; + case SC_TRUESIGHT: + val2 = 10*val1; //Critical increase + val3 = 3*val1; //Hit increase + break; + case SC_SUN_COMFORT: + val2 = (status->get_lv(bl) + st->dex + st->luk)/2; //def increase + break; + case SC_MOON_COMFORT: + val2 = (status->get_lv(bl) + st->dex + st->luk)/10; //flee increase + break; + case SC_STAR_COMFORT: + val2 = (status->get_lv(bl) + st->dex + st->luk); //Aspd increase + break; + case SC_QUAGMIRE: + val2 = (sd?5:10)*val1; //Agi/Dex decrease. + break; - case SC_COMBOATTACK: { - //val1: Skill ID - //val2: When given, target (for autotargetting skills) - //val3: When set, this combo time should NOT delay attack/movement - //val3: TK: Last used kick - //val4: TK: Combo time - struct unit_data *ud = unit->bl2ud(bl); - if (ud && !val3) { - tick += 300 * battle_config.combo_delay_rate/100; - ud->attackabletime = timer->gettick()+tick; - unit->set_walkdelay(bl, timer->gettick(), tick, 1); - } - val3 = 0; - val4 = tick; - } - break; - case SC_EARTHSCROLL: - val2 = 11-val1; //Chance to consume: 11-skill_lv% - break; - case SC_RUN: - val4 = timer->gettick(); //Store time at which you started running. - tick = -1; - break; - case SC_KAAHI: - val2 = 200*val1; //HP heal - val3 = 5*val1; //SP cost - val4 = INVALID_TIMER; //Kaahi Timer. - break; - case SC_BLESSING: - if ((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC) - val2 = val1; - else - val2 = 0; //0 -> Half stat. - break; - case SC_TRICKDEAD: - if (vd) vd->dead_sit = 1; - tick = -1; - break; - case SC_CONCENTRATION: - val2 = 2 + val1; - if (sd) { //Store the card-bonus data that should not count in the % - val3 = sd->param_bonus[1]; //Agi - val4 = sd->param_bonus[4]; //Dex - } else { - val3 = val4 = 0; - } - break; - case SC_OVERTHRUSTMAX: - val2 = 20*val1; //Power increase - break; - case SC_OVERTHRUST: - //val2 holds if it was casted on self, or is bonus received from others - val3 = 5*val1; //Power increase - if(sd && pc->checkskill(sd,BS_HILTBINDING)>0) - tick += tick / 10; - break; - case SC_ADRENALINE2: - case SC_ADRENALINE: - val3 = (val2) ? 300 : 200; // aspd increase - case SC_WEAPONPERFECT: - if(sd && pc->checkskill(sd,BS_HILTBINDING)>0) - tick += tick / 10; - break; - case SC_LKCONCENTRATION: - val2 = 5*val1; //Batk/Watk Increase - val3 = 10*val1; //Hit Increase - val4 = 5*val1; //Def reduction - sc_start(bl, SC_ENDURE, 100, 1, tick); //Endure effect - break; - case SC_ANGELUS: - val2 = 5*val1; //def increase - break; - case SC_IMPOSITIO: - val2 = 5*val1; //watk increase - break; - case SC_MELTDOWN: - val2 = 100*val1; //Chance to break weapon - val3 = 70*val1; //Change to break armor - break; - case SC_TRUESIGHT: - val2 = 10*val1; //Critical increase - val3 = 3*val1; //Hit increase - break; - case SC_SUN_COMFORT: - val2 = (status->get_lv(bl) + st->dex + st->luk)/2; //def increase - break; - case SC_MOON_COMFORT: - val2 = (status->get_lv(bl) + st->dex + st->luk)/10; //flee increase - break; - case SC_STAR_COMFORT: - val2 = (status->get_lv(bl) + st->dex + st->luk); //Aspd increase - break; - case SC_QUAGMIRE: - val2 = (sd?5:10)*val1; //Agi/Dex decrease. - break; + // gs_something1 [Vicious] + case SC_GS_GATLINGFEVER: + val2 = 20*val1; //Aspd increase + val4 = 5*val1; //Flee decrease + #ifndef RENEWAL + val3 = 20+10*val1; //Batk increase + #endif + break; - // gs_something1 [Vicious] - case SC_GS_GATLINGFEVER: - val2 = 20*val1; //Aspd increase - val4 = 5*val1; //Flee decrease -#ifndef RENEWAL - val3 = 20+10*val1; //Batk increase -#endif - break; + case SC_FLING: + if (bl->type == BL_PC) + val2 = 0; //No armor reduction to players. + else + val2 = 5*val1; //Def reduction + val3 = 5*val1; //Def2 reduction + break; + case SC_PROVOKE: + //val2 signals autoprovoke. + val3 = 2+3*val1; //Atk increase + val4 = 5+5*val1; //Def reduction. + break; + case SC_HLIF_AVOID: + //val2 = 10*val1; //Speed change rate. + break; + case SC_HAMI_DEFENCE: + val2 = 2*val1; //Def bonus + break; + case SC_HAMI_BLOODLUST: + val2 = 20+10*val1; //Atk rate change. + val3 = 3*val1; //Leech chance + val4 = 20; //Leech percent + break; + case SC_HLIF_FLEET: + val2 = 30*val1; //Aspd change + val3 = 5+5*val1; //bAtk/wAtk rate change + break; + case SC_MINDBREAKER: + val2 = 20*val1; //matk increase. + val3 = 12*val1; //mdef2 reduction. + break; + case SC_SKA: + val2 = tick/1000; + val3 = rnd()%100; //Def changes randomly every second... + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_JAILED: + //Val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time. + tick = val1>0?1000:250; + if (sd) + { + if (sd->mapindex != val2) + { + int pos = (bl->x&0xFFFF)|(bl->y<<16); /// Current Coordinates + int mapindex = sd->mapindex; /// Current Map + //1. Place in Jail (val2 -> Jail Map, val3 -> x, val4 -> y + pc->setpos(sd,(unsigned short)val2,val3,val4, CLR_TELEPORT); + //2. Set restore point (val3 -> return map, val4 return coords + val3 = mapindex; + val4 = pos; + } else if (!val3 || val3 == sd->mapindex) { //Use save point. + val3 = sd->status.save_point.map; + val4 = (sd->status.save_point.x&0xFFFF) + |(sd->status.save_point.y<<16); + } + } + break; + case SC_NJ_UTSUSEMI: + val2=(val1+1)/2; // number of hits blocked + val3=skill->get_blewcount(NJ_UTSUSEMI, val1); //knockback value. + break; + case SC_NJ_BUNSINJYUTSU: + val2=(val1+1)/2; // number of hits blocked + break; + case SC_HLIF_CHANGE: + val2= 30*val1; //Vit increase + val3= 20*val1; //Int increase + break; + case SC_SWOO: + if(st->mode&MD_BOSS) + tick /= 5; //TODO: Reduce skill's duration. But for how long? + break; + case SC_SPIDERWEB: + if( bl->type == BL_PC ) + tick /= 2; + break; + case SC_ARMOR: + //NPC_DEFENDER: + val2 = 80; //Damage reduction + //Attack requirements to be blocked: + val3 = BF_LONG; //Range + val4 = BF_WEAPON|BF_MISC; //Type + break; + case SC_ENCHANTARMS: + //end previous enchants + skill->enchant_elemental_end(bl,type); + //Make sure the received element is valid. + if (val2 >= ELE_MAX) + val2 = val2%ELE_MAX; + else if (val2 < 0) + val2 = rnd()%ELE_MAX; + break; + case SC_CRITICALWOUND: + val2 = 20*val1; //Heal effectiveness decrease + break; + case SC_MAGICMIRROR: + case SC_SLOWCAST: + val2 = 20*val1; //Magic reflection/cast rate + break; - case SC_FLING: - if (bl->type == BL_PC) - val2 = 0; //No armor reduction to players. - else - val2 = 5*val1; //Def reduction - val3 = 5*val1; //Def2 reduction - break; - case SC_PROVOKE: - //val2 signals autoprovoke. - val3 = 2+3*val1; //Atk increase - val4 = 5+5*val1; //Def reduction. - break; - case SC_HLIF_AVOID: - //val2 = 10*val1; //Speed change rate. - break; - case SC_HAMI_DEFENCE: - val2 = 2*val1; //Def bonus - break; - case SC_HAMI_BLOODLUST: - val2 = 20+10*val1; //Atk rate change. - val3 = 3*val1; //Leech chance - val4 = 20; //Leech percent - break; - case SC_HLIF_FLEET: - val2 = 30*val1; //Aspd change - val3 = 5+5*val1; //bAtk/wAtk rate change - break; - case SC_MINDBREAKER: - val2 = 20*val1; //matk increase. - val3 = 12*val1; //mdef2 reduction. - break; - case SC_SKA: - val2 = tick/1000; - val3 = rnd()%100; //Def changes randomly every second... - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_JAILED: - //Val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time. - tick = val1>0?1000:250; - if (sd) + case SC_STONESKIN: + if (val2 == NPC_ANTIMAGIC) + { //Boost mdef + val2 =-20; + val3 = 20; + } else { //Boost def + val2 = 20; + val3 =-20; + } + val2*=val1; //20% per level + val3*=val1; + break; + case SC_CASH_PLUSEXP: + case SC_CASH_PLUSONLYJOBEXP: + if (val1 < 0) + val1 = 0; + break; + case SC_PLUSAVOIDVALUE: + case SC_CRITICALPERCENT: + val2 = val1*10; //Actual boost (since 100% = 1000) + break; + case SC_SUFFRAGIUM: + val2 = 15 * val1; //Speed cast decrease + break; + case SC_HEALPLUS: + if (val1 < 1) + val1 = 1; + break; + case SC_ILLUSION: + val2 = 5+val1; //Factor by which displayed damage is increased by + break; + case SC_DOUBLECASTING: + val2 = 30+10*val1; //Trigger rate + break; + case SC_KAIZEL: + val2 = 10*val1; //% of life to be revived with + break; + // case SC_ARMORPROPERTY: + // case SC_ARMOR_RESIST: + // Mod your resistance against elements: + // val1 = water | val2 = earth | val3 = fire | val4 = wind + // break; + //case ????: + //Place here SCs that have no SCB_* data, no skill associated, no ICON + //associated, and yet are not wrong/unknown. [Skotlex] + //break; + + case SC_MER_FLEE: + case SC_MER_ATK: + case SC_MER_HIT: + val2 = 15 * val1; + break; + case SC_MER_HP: + case SC_MER_SP: + val2 = 5 * val1; + break; + case SC_REBIRTH: + val2 = 20*val1; //% of life to be revived with + break; + + case SC_MANU_DEF: + case SC_MANU_ATK: + case SC_MANU_MATK: + val2 = 1; // Manuk group + break; + case SC_SPL_DEF: + case SC_SPL_ATK: + case SC_SPL_MATK: + val2 = 2; // Splendide group + break; + /** + * General + **/ + case SC_FEAR: + val2 = 2; + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_BURNING: + val4 = tick / 3000; // Total Ticks to Burn!! + tick_time = 3000; // [GodLesZ] tick time + break; + /** + * Rune Knight + **/ + case SC_DEATHBOUND: + val2 = 500 + 100 * val1; + break; + case SC_STONEHARDSKIN: + if( sd ) + val1 = sd->status.job_level * pc->checkskill(sd, RK_RUNEMASTERY) / 4; //DEF/MDEF Increase + break; + case SC_ABUNDANCE: + val4 = tick / 10000; + tick_time = 10000; // [GodLesZ] tick time + break; + /** + * Arch Bishop + **/ + case SC_RENOVATIO: + val4 = tick / 5000; + tick_time = 5000; + break; + case SC_SECRAMENT: + val2 = 10 * val1; + break; + case SC_VENOMIMPRESS: + val2 = 10 * val1; + break; + case SC_WEAPONBLOCKING: + val2 = 10 + 2 * val1; // Chance + val4 = tick / 3000; + tick_time = 3000; // [GodLesZ] tick time + break; + case SC_TOXIN: + val4 = tick / 10000; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_MAGICMUSHROOM: + val4 = tick / 4000; + tick_time = 4000; // [GodLesZ] tick time + break; + case SC_PYREXIA: + status->change_start(bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds + val4 = tick / 3000; + tick_time = 3000; // [GodLesZ] tick time + break; + case SC_LEECHESEND: + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_OBLIVIONCURSE: + val4 = tick / 3000; + tick_time = 3000; // [GodLesZ] tick time + break; + case SC_CLOAKINGEXCEED: + val2 = ( val1 + 1 ) / 2; // Hits + val3 = 90 + val1 * 10; // Walk speed + if (bl->type == BL_PC) + val4 |= battle_config.pc_cloak_check_type&7; + else + val4 |= battle_config.monster_cloak_check_type&7; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_HALLUCINATIONWALK: + val2 = 50 * val1; // Evasion rate of physical attacks. Flee + val3 = 10 * val1; // Evasion rate of magical attacks. + break; + case SC_WHITEIMPRISON: + status_change_end(bl, SC_BURNING, INVALID_TIMER); + status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER); + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + break; + case SC_MARSHOFABYSS: + val2 = 6 * val1; + if( sd ) // half on players + val2 >>= 1; + break; + case SC_FROSTMISTY: + status_change_end(bl, SC_BURNING, INVALID_TIMER); + break; + case SC_READING_SB: + // val2 = sp reduction per second + tick_time = 5000; // [GodLesZ] tick time + break; + case SC_SUMMON1: + case SC_SUMMON2: + case SC_SUMMON3: + case SC_SUMMON4: + case SC_SUMMON5: + val4 = tick / 1000; + if( val4 < 1 ) + val4 = 1; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_SHAPESHIFT: + switch( val1 ) + { + case 1: val2 = ELE_FIRE; break; + case 2: val2 = ELE_EARTH; break; + case 3: val2 = ELE_WIND; break; + case 4: val2 = ELE_WATER; break; + } + break; + case SC_ELECTRICSHOCKER: + case SC_COLD: + case SC_MEIKYOUSISUI: + val4 = tick / 1000; + if( val4 < 1 ) + val4 = 1; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_CAMOUFLAGE: + val4 = tick/1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_WUGDASH: { - if (sd->mapindex != val2) + //Store time at which you started running. + int64 currenttick = timer->gettick(); + // Note: this int64 value is stored in two separate int32 variables (FIXME) + val3 = (int)(currenttick&0x00000000ffffffffLL); + val4 = (int)((currenttick&0xffffffff00000000LL)>>32); + } + tick = -1; + break; + case SC__SHADOWFORM: { + struct map_session_data * s_sd = map->id2sd(val2); + if( s_sd ) + s_sd->shadowform_id = bl->id; + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + } + break; + case SC__STRIPACCESSARY: + if (!sd) + val2 = 20; + break; + case SC__INVISIBILITY: + val2 = 50 - 10 * val1; // ASPD + val3 = 20 * val1; // CRITICAL + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC__ENERVATION: + val2 = 20 + 10 * val1; // ATK Reduction + if( sd ) pc->delspiritball(sd,sd->spiritball,0); + break; + case SC__GROOMY: + 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); + } + break; + case SC__LAZINESS: + val2 = 10 + 10 * val1; // Cast reduction + val3 = 10 * val1; // Flee Reduction + break; + case SC__UNLUCKY: + val2 = 10 * val1; // Crit and Flee2 Reduction + break; + case SC__WEAKNESS: + val2 = 10 * val1; + // bypasses coating protection and MADO + sc_start(bl,SC_NOEQUIPWEAPON,100,val1,tick); + sc_start(bl,SC_NOEQUIPSHIELD,100,val1,tick); + break; + case SC_GN_CARTBOOST: + if( val1 < 3 ) + val2 = 50; + else if( val1 < 5 ) + val2 = 75; + else + val2 = 100; + break; + case SC_PROPERTYWALK: + val3 = 0; + break; + case SC_WARMER: + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER); + status_change_end(bl, SC_COLD, INVALID_TIMER); + break; + case SC_STRIKING: + val1 = 6 - val1;//spcost = 6 - level (lvl1:5 ... lvl 5: 1) + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_BLOOD_SUCKER: + { + struct block_list *src = map->id2bl(val2); + val3 = 1; + if(src) + val3 = 200 + 100 * val1 + status_get_int(src); + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + } + break; + case SC_VACUUM_EXTREME: + tick -= (st->str / 20) * 1000; + val4 = val3 = tick / 100; + tick_time = 100; // [GodLesZ] tick time + break; + case SC_SWING: + val2 = 4 * val1; // Walk speed and aspd reduction. + break; + case SC_SYMPHONY_LOVE: + case SC_RUSH_WINDMILL: + case SC_ECHOSONG: + val2 = 6 * val1; + val2 += val3; //Adding 1% * Lesson Bonus + val2 += (int)(val4*2/10); //Adding 0.2% per JobLevel + break; + case SC_MOONLIT_SERENADE: + val2 = 10 * val1; + break; + case SC_HARMONIZE: + val2 = 5 + 5 * val1; + break; + case SC_SIREN: + val4 = tick / 2000; + tick_time = 2000; // [GodLesZ] tick time + break; + case SC_DEEP_SLEEP: + val4 = tick / 2000; + tick_time = 2000; // [GodLesZ] tick time + break; + case SC_SIRCLEOFNATURE: + val2 = 1 + val1; //SP consume + val3 = 40 * val1; //HP recovery + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_SONG_OF_MANA: + val3 = 10 + (2 * val2); + val4 = tick/3000; + tick_time = 3000; // [GodLesZ] tick time + break; + case SC_SATURDAY_NIGHT_FEVER: + if (!val4) val4 = skill->get_time2(status->sc2skill(type),val1); + if (!val4) val4 = 3000; + val3 = tick/val4; + tick_time = val4; // [GodLesZ] tick time + break; + case SC_GLOOMYDAY: + val2 = 20 + 5 * val1; // Flee reduction. + val3 = 15 + 5 * val1; // ASPD reduction. + if( sd && rand()%100 < val1 ){ // (Skill Lv) % + val4 = 1; // reduce walk speed by half. + if( pc_isriding(sd) ) pc->setriding(sd, 0); + if( pc_isridingdragon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_DRAGON); + } + break; + case SC_GLOOMYDAY_SK: + // Random number between [15 ~ (Voice Lesson Skill Level x 5) + (Skill Level x 10)] %. + val2 = 15 + rand()%( (sd?pc->checkskill(sd, WM_LESSON)*5:0) + val1*10 ); + break; + case SC_SITDOWN_FORCE: + case SC_BANANA_BOMB_SITDOWN_POSTDELAY: + if( sd && !pc_issit(sd) ) { - int pos = (bl->x&0xFFFF)|(bl->y<<16); /// Current Coordinates - int mapindex = sd->mapindex; /// Current Map - //1. Place in Jail (val2 -> Jail Map, val3 -> x, val4 -> y - pc->setpos(sd,(unsigned short)val2,val3,val4, CLR_TELEPORT); - //2. Set restore point (val3 -> return map, val4 return coords - val3 = mapindex; - val4 = pos; - } else if (!val3 || val3 == sd->mapindex) { //Use save point. - val3 = sd->status.save_point.map; - val4 = (sd->status.save_point.x&0xFFFF) - |(sd->status.save_point.y<<16); + pc_setsit(sd); + skill->sit(sd,1); + clif->sitting(bl); + } + break; + case SC_DANCE_WITH_WUG: + val3 = (5 * val1) + (1 * val2); //Still need official value. + break; + case SC_LERADS_DEW: + val3 = (5 * val1) + (1 * val2); + break; + case SC_MELODYOFSINK: + val3 = (5 * val1) + (1 * val2); + break; + case SC_BEYOND_OF_WARCRY: + val3 = (5 * val1) + (1 * val2); + break; + case SC_UNLIMITED_HUMMING_VOICE: + { + struct unit_data *ud = unit->bl2ud(bl); + if( ud == NULL ) return 0; + ud->state.skillcastcancel = 0; + val3 = 15 - (2 * val2); + } + break; + case SC_LG_REFLECTDAMAGE: + val2 = 15 + 5 * val1; + val3 = (val1==5)?20:(val1+4)*2; // SP consumption + val4 = tick/10000; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_FORCEOFVANGUARD: // This is not the official way to handle it but I think we should use it. [pakpil] + val2 = 20 + 12 * (val1 - 1); // Chance + val3 = 5 + (2 * val1); // Max rage counters + tick = -1; //endless duration in the client + tick_time = 6000; // [GodLesZ] tick time + break; + case SC_EXEEDBREAK: + val1 *= 150; // 150 * skill_lv + if( sd && sd->inventory_data[sd->equip_index[EQI_HAND_R]] ) { // Chars. + val1 += (sd->inventory_data[sd->equip_index[EQI_HAND_R]]->weight/10 * sd->inventory_data[sd->equip_index[EQI_HAND_R]]->wlv * status->get_lv(bl) / 100); + val1 += 15 * (sd ? sd->status.job_level:50) + 100; + } else // Mobs + val1 += (400 * status->get_lv(bl) / 100) + (15 * (status->get_lv(bl) / 2)); // About 1138% at mob_lvl 99. Is an aproximation to a standard weapon. [pakpil] + break; + case SC_PRESTIGE: // Based on suggested formula in iRO Wiki and some test, still need more test. [pakpil] + val2 = ((st->int_ + st->luk) / 6) + 5; // Chance to evade magic damage. + val1 *= 15; // Defence added + if( sd ) + val1 += 10 * pc->checkskill(sd,CR_DEFENDER); + break; + case SC_BANDING: + tick_time = 5000; // [GodLesZ] tick time + break; + case SC_MAGNETICFIELD: + val3 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_INSPIRATION: + if( sd ) { + val2 = (40 * val1) + (3 * sd->status.job_level); // ATK bonus + val3 = (sd->status.job_level / 10) * 2 + 12; // All stat bonus + } + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + status->change_clear_buffs(bl,3); //Remove buffs/debuffs + break; + case SC_CRESCENTELBOW: + val2 = 94 + val1; + break; + case SC_LIGHTNINGWALK: // [(Job Level / 2) + (40 + 5 * Skill Level)] % + val1 = (sd?sd->status.job_level:2)/2 + 40 + 5 * val1; + break; + case SC_RAISINGDRAGON: + val3 = tick / 5000; + tick_time = 5000; // [GodLesZ] tick time + break; + case SC_GENTLETOUCH_CHANGE: + {// take note there is no def increase as skill desc says. [malufett] + struct block_list * src; + val3 = st->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] % + if( (src = map->id2bl(val2)) ){ + val4 = ( 200/status_get_int(src) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] + val2 = ( status_get_dex(src)/4 + status_get_str(src)/2 ) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5] } } - break; - case SC_NJ_UTSUSEMI: - val2=(val1+1)/2; // number of hits blocked - val3=skill->get_blewcount(NJ_UTSUSEMI, val1); //knockback value. - break; - case SC_NJ_BUNSINJYUTSU: - val2=(val1+1)/2; // number of hits blocked - break; - case SC_HLIF_CHANGE: - val2= 30*val1; //Vit increase - val3= 20*val1; //Int increase - break; - case SC_SWOO: - if(st->mode&MD_BOSS) - tick /= 5; //TODO: Reduce skill's duration. But for how long? - break; - case SC_SPIDERWEB: - if( bl->type == BL_PC ) - tick /= 2; - break; - case SC_ARMOR: - //NPC_DEFENDER: - val2 = 80; //Damage reduction - //Attack requirements to be blocked: - val3 = BF_LONG; //Range - val4 = BF_WEAPON|BF_MISC; //Type - break; - case SC_ENCHANTARMS: - //end previous enchants - skill->enchant_elemental_end(bl,type); - //Make sure the received element is valid. - if (val2 >= ELE_MAX) - val2 = val2%ELE_MAX; - else if (val2 < 0) - val2 = rnd()%ELE_MAX; - break; - case SC_CRITICALWOUND: - val2 = 20*val1; //Heal effectiveness decrease - break; - case SC_MAGICMIRROR: - case SC_SLOWCAST: - val2 = 20*val1; //Magic reflection/cast rate - break; - - case SC_STONESKIN: - if (val2 == NPC_ANTIMAGIC) - { //Boost mdef - val2 =-20; - val3 = 20; - } else { //Boost def - val2 = 20; - val3 =-20; + break; + case SC_GENTLETOUCH_REVITALIZE: + {// take note there is no vit,aspd,speed increase as skill desc says. [malufett] + struct block_list * src; + val3 = val1 * 30 + 150; // Natural HP recovery increase: [(Skill Level x 30) + 50] % + if( (src = map->id2bl(val2)) ) // the stat def is not shown in the status window and it is process differently + val4 = ( status_get_vit(src)/4 ) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level] } - val2*=val1; //20% per level - val3*=val1; - break; - case SC_CASH_PLUSEXP: - case SC_CASH_PLUSONLYJOBEXP: - if (val1 < 0) - val1 = 0; - break; - case SC_PLUSAVOIDVALUE: - case SC_CRITICALPERCENT: - val2 = val1*10; //Actual boost (since 100% = 1000) - break; - case SC_SUFFRAGIUM: - val2 = 15 * val1; //Speed cast decrease - break; - case SC_HEALPLUS: - if (val1 < 1) - val1 = 1; - break; - case SC_ILLUSION: - val2 = 5+val1; //Factor by which displayed damage is increased by - break; - case SC_DOUBLECASTING: - val2 = 30+10*val1; //Trigger rate - break; - case SC_KAIZEL: - val2 = 10*val1; //% of life to be revived with - break; - // case SC_ARMORPROPERTY: - // case SC_ARMOR_RESIST: - // Mod your resistance against elements: - // val1 = water | val2 = earth | val3 = fire | val4 = wind - // break; - //case ????: - //Place here SCs that have no SCB_* data, no skill associated, no ICON - //associated, and yet are not wrong/unknown. [Skotlex] - //break; + break; + case SC_HEATER_OPTION: + val2 = 120; // Watk. TODO: Renewal (Atk2) + val3 = 33; // % Increase effects. + val4 = 3; // Change into fire element. + break; + case SC_TROPIC_OPTION: + val2 = 180; // Watk. TODO: Renewal (Atk2) + val3 = MG_FIREBOLT; + break; + case SC_AQUAPLAY_OPTION: + val2 = 40; + break; + case SC_COOLER_OPTION: + val2 = 80; // % Freezing chance + val3 = 33; // % increased damage + val4 = 1; // Change into water elemet + break; + case SC_CHILLY_AIR_OPTION: + val2 = 120; // Matk. TODO: Renewal (Matk1) + val3 = MG_COLDBOLT; + break; + case SC_WIND_STEP_OPTION: + val2 = 50; // % Increase speed and flee. + break; + case SC_BLAST_OPTION: + val2 = 20; + val3 = ELE_WIND; + break; + case SC_WILD_STORM_OPTION: + val2 = MG_LIGHTNINGBOLT; + break; + case SC_PETROLOGY_OPTION: + val2 = 5; + val3 = 50; + break; + case SC_CURSED_SOIL_OPTION: + val2 = 10; + val3 = 33; + val4 = 2; + break; + case SC_UPHEAVAL_OPTION: + val2 = WZ_EARTHSPIKE; + break; + case SC_CIRCLE_OF_FIRE_OPTION: + val2 = 300; + break; + case SC_FIRE_CLOAK_OPTION: + case SC_WATER_DROP_OPTION: + case SC_WIND_CURTAIN_OPTION: + case SC_STONE_SHIELD_OPTION: + val2 = 20; // Elemental modifier. Not confirmed. + break; + case SC_CIRCLE_OF_FIRE: + case SC_FIRE_CLOAK: + case SC_WATER_DROP: + case SC_WATER_SCREEN: + case SC_WIND_CURTAIN: + case SC_WIND_STEP: + case SC_STONE_SHIELD: + case SC_SOLID_SKIN: + val2 = 10; + tick_time = 2000; // [GodLesZ] tick time + break; + case SC_WATER_BARRIER: + val2 = 40; // Increasement. Mdef1 ??? + val3 = 20; // Reductions. Atk2, Flee1, Matk1 ???? + break; + case SC_ZEPHYR: + val2 = 22; // Flee. + break; + case SC_TIDAL_WEAPON: + val2 = 20; // Increase Elemental's attack. + break; + case SC_ROCK_CRUSHER: + case SC_ROCK_CRUSHER_ATK: + case SC_POWER_OF_GAIA: + val2 = 33; + break; + case SC_MELON_BOMB: + case SC_BANANA_BOMB: + val1 = 15; + break; + case SC_STOMACHACHE: + val2 = 8; // SP consume. + val4 = tick / 10000; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_KYOUGAKU: + val2 = 2*val1 + rand()%(3 * val1); + clif->status_change(bl, SI_ACTIVE_MONSTER_TRANSFORM, 1, 0, 1002, 0, 0); // Poring in disguise + break; + case SC_KAGEMUSYA: + val3 = val1 * 2; + case SC_IZAYOI: + val2 = tick/1000; + tick_time = 1000; + break; + case SC_ZANGETSU: + val2 = val4 = status->get_lv(bl) / 3 + 20 * val1; + val3 = status->get_lv(bl) / 2 + 30 * val1; + val2 = (!(status_get_hp(bl)%2) ? val2 : -val3); + val3 = (!(status_get_sp(bl)%2) ? val4 : -val3); + break; + case SC_GENSOU: - case SC_MER_FLEE: - case SC_MER_ATK: - case SC_MER_HIT: - val2 = 15 * val1; - break; - case SC_MER_HP: - case SC_MER_SP: - val2 = 5 * val1; - break; - case SC_REBIRTH: - val2 = 20*val1; //% of life to be revived with - break; + #define PER( a ) do { \ + if( a <= 15 ) lv = 1; \ + else if( a <= 30 ) lv = 2; \ + else if( a <= 50 ) lv = 3; \ + else if( a <= 75 ) lv = 4; \ + } while(0) - case SC_MANU_DEF: - case SC_MANU_ATK: - case SC_MANU_MATK: - val2 = 1; // Manuk group - break; - case SC_SPL_DEF: - case SC_SPL_ATK: - case SC_SPL_MATK: - val2 = 2; // Splendide group - break; - /** - * General - **/ - case SC_FEAR: - val2 = 2; - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_BURNING: - val4 = tick / 3000; // Total Ticks to Burn!! - tick_time = 3000; // [GodLesZ] tick time - break; - /** - * Rune Knight - **/ - case SC_DEATHBOUND: - val2 = 500 + 100 * val1; - break; - case SC_STONEHARDSKIN: - if( sd ) - val1 = sd->status.job_level * pc->checkskill(sd, RK_RUNEMASTERY) / 4; //DEF/MDEF Increase - break; + { + int hp = status_get_hp(bl), sp = status_get_sp(bl), lv = 5; + + if( rand()%100 > (25 + 10 * val1) - status_get_int(bl) / 2) + return 0; + + PER( 100 / (status_get_max_hp(bl) / hp) ); + status->heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, 1); + + PER( 100 / (status_get_max_sp(bl) / sp) ); + status->heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), 1); + } + #undef PER + break; + case SC_ANGRIFFS_MODUS: + val2 = 50 + 20 * val1; //atk bonus + val3 = 40 + 20 * val1; // Flee reduction. + val4 = tick/1000; // hp/sp reduction timer + tick_time = 1000; + break; + case SC_NEUTRALBARRIER: + tick_time = tick; + tick = -1; + break; + case SC_GOLDENE_FERSE: + val2 = 10 + 10*val1; //max hp bonus + val3 = 6 + 4 * val1; // Aspd Bonus + val4 = 2 + 2 * val1; // Chance of holy attack + break; + case SC_OVERED_BOOST: + val2 = 300 + 40*val1; //flee bonus + val3 = 179 + 2*val1; //aspd bonus + break; + case SC_GRANITIC_ARMOR: + val2 = 2*val1; //dmg reduction + val3 = 6*val1; //dmg on status end + break; + case SC_MAGMA_FLOW: + val2 = 3*val1; //activation chance + break; + case SC_PYROCLASTIC: + val2 += 10*val1; //atk bonus + break; + case SC_NEEDLE_OF_PARALYZE: //[Lighta] need real info + val2 = 2*val1; //def reduction + val3 = 500*val1; //varcast augmentation + break; + case SC_PAIN_KILLER: //[Lighta] need real info + val2 = 2*val1; //aspd reduction % + val3 = 2*val1; //dmg reduction % + if(sc->data[SC_NEEDLE_OF_PARALYZE]) + sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration + break; + case SC_STYLE_CHANGE: //[Lighta] need real info + tick = -1; + if(val2 == MH_MD_FIGHTING) val2 = MH_MD_GRAPPLING; + else val2 = MH_MD_FIGHTING; + break; + case SC_FULL_THROTTLE: + status_percent_heal(bl,100,0); + val2 = 7 - val1; + tick_time = 1000; + val4 = tick / tick_time; + break; + case SC_KINGS_GRACE: + val2 = 3 + val1; + tick_time = 1000; + val4 = tick / tick_time; + break; + case SC_TELEKINESIS_INTENSE: + val2 = 10 * val1; + val3 = 40 * val1; + break; + case SC_OFFERTORIUM: + val2 = 30 * val1; + break; + case SC_FRIGG_SONG: + val2 = 5 * val1; + val3 = 1000 + 100 * val1; + tick_time = 10000; + val4 = tick / tick_time; + break; + case SC_MONSTER_TRANSFORM: + if( !mob->db_checkid(val1) ) + val1 = 1002; // default poring + break; + default: + if( calc_flag == SCB_NONE && status->SkillChangeTable[type] == 0 && status->IconChangeTable[type] == 0 ) + { //Status change with no calc, no icon, and no skill associated...? + ShowError("UnknownStatusChange [%d]\n", type); + return 0; + } + } + } else { //Special considerations when loading SC data. + switch( type ) { + case SC_WEDDING: + case SC_XMAS: + case SC_SUMMER: + case SC_HANBOK: + if( !vd ) break; + clif->changelook(bl,LOOK_BASE,vd->class_); + clif->changelook(bl,LOOK_WEAPON,0); + clif->changelook(bl,LOOK_SHIELD,0); + clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); + break; + case SC_KAAHI: + val4 = INVALID_TIMER; + break; + case SC_KYOUGAKU: + clif->status_change(bl, SI_ACTIVE_MONSTER_TRANSFORM, 1, 0, 1002, 0, 0); // Poring in disguise + break; + } + } + + /* values that must be set regardless of flag&4 e.g. val_flag */ + switch(type) { case SC_FIGHTINGSPIRIT: val_flag |= 1|2; break; - case SC_ABUNDANCE: - val4 = tick / 10000; - tick_time = 10000; // [GodLesZ] tick time - break; - /** - * Arch Bishop - **/ - case SC_RENOVATIO: - val4 = tick / 5000; - tick_time = 5000; - break; - case SC_SECRAMENT: - val2 = 10 * val1; - break; case SC_VENOMIMPRESS: - val2 = 10 * val1; val_flag |= 1|2; break; case SC_POISONINGWEAPON: val_flag |= 1|2|4; break; case SC_WEAPONBLOCKING: - val2 = 10 + 2 * val1; // Chance - val4 = tick / 3000; - tick_time = 3000; // [GodLesZ] tick time val_flag |= 1|2; break; - case SC_TOXIN: - val4 = tick / 10000; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_MAGICMUSHROOM: - val4 = tick / 4000; - tick_time = 4000; // [GodLesZ] tick time - break; - case SC_PYREXIA: - status->change_start(bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds - val4 = tick / 3000; - tick_time = 3000; // [GodLesZ] tick time - break; - case SC_LEECHESEND: - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_OBLIVIONCURSE: - val4 = tick / 3000; - tick_time = 3000; // [GodLesZ] tick time - break; case SC_ROLLINGCUTTER: val_flag |= 1; break; case SC_CLOAKINGEXCEED: - val2 = ( val1 + 1 ) / 2; // Hits - val3 = 90 + val1 * 10; // Walk speed val_flag |= 1|2|4; - if (bl->type == BL_PC) - val4 |= battle_config.pc_cloak_check_type&7; - else - val4 |= battle_config.monster_cloak_check_type&7; - tick_time = 1000; // [GodLesZ] tick time break; case SC_HALLUCINATIONWALK: - val2 = 50 * val1; // Evasion rate of physical attacks. Flee - val3 = 10 * val1; // Evasion rate of magical attacks. val_flag |= 1|2|4; break; - case SC_WHITEIMPRISON: - status_change_end(bl, SC_BURNING, INVALID_TIMER); - status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER); - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); - break; - case SC_MARSHOFABYSS: - val2 = 6 * val1; - if( sd ) // half on players - val2 >>= 1; - break; - case SC_FROSTMISTY: - status_change_end(bl, SC_BURNING, INVALID_TIMER); - break; - case SC_READING_SB: - // val2 = sp reduction per second - tick_time = 5000; // [GodLesZ] tick time - break; case SC_SUMMON1: case SC_SUMMON2: case SC_SUMMON3: case SC_SUMMON4: case SC_SUMMON5: - val4 = tick / 1000; - if( val4 < 1 ) - val4 = 1; - tick_time = 1000; // [GodLesZ] tick time val_flag |= 1; break; - case SC_SHAPESHIFT: - switch( val1 ) - { - case 1: val2 = ELE_FIRE; break; - case 2: val2 = ELE_EARTH; break; - case 3: val2 = ELE_WIND; break; - case 4: val2 = ELE_WATER; break; - } - break; - case SC_ELECTRICSHOCKER: - case SC_COLD: - case SC_MEIKYOUSISUI: - val4 = tick / 1000; - if( val4 < 1 ) - val4 = 1; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_CAMOUFLAGE: - val4 = tick/1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_WUGDASH: - val4 = timer->gettick(); //Store time at which you started running. - tick = -1; - break; - case SC__SHADOWFORM: { - struct map_session_data * s_sd = map->id2sd(val2); - if( s_sd ) - s_sd->shadowform_id = bl->id; - val4 = tick / 1000; + case SC__SHADOWFORM: val_flag |= 1|2|4; - tick_time = 1000; // [GodLesZ] tick time - } - break; - case SC__STRIPACCESSARY: - if (!sd) - val2 = 20; break; case SC__INVISIBILITY: - val2 = 50 - 10 * val1; // ASPD - val3 = 20 * val1; // CRITICAL - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time val_flag |= 1|2; break; case SC__ENERVATION: - val2 = 20 + 10 * val1; // ATK Reduction val_flag |= 1|2; - if( sd ) pc->delspiritball(sd,sd->spiritball,0); break; case SC__GROOMY: - val2 = 20 + 10 * val1; //ASPD. Need to confirm if Movement Speed reduction is the same. [Jobbie] - val3 = 20 * val1; //HIT val_flag |= 1|2|4; - 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); - } break; case SC__LAZINESS: - val2 = 10 + 10 * val1; // Cast reduction - val3 = 10 * val1; // Flee Reduction val_flag |= 1|2|4; break; case SC__UNLUCKY: - val2 = 10 * val1; // Crit and Flee2 Reduction val_flag |= 1|2|4; break; case SC__WEAKNESS: - val2 = 10 * val1; val_flag |= 1|2; - // bypasses coating protection and MADO - sc_start(bl,SC_NOEQUIPWEAPON,100,val1,tick); - sc_start(bl,SC_NOEQUIPSHIELD,100,val1,tick); - break; - case SC_GN_CARTBOOST: - if( val1 < 3 ) - val2 = 50; - else if( val1 < 5 ) - val2 = 75; - else - val2 = 100; break; case SC_PROPERTYWALK: val_flag |= 1|2; - val3 = 0; - break; - case SC_WARMER: - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER); - status_change_end(bl, SC_COLD, INVALID_TIMER); - break; - case SC_STRIKING: - val1 = 6 - val1;//spcost = 6 - level (lvl1:5 ... lvl 5: 1) - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_BLOOD_SUCKER: - { - struct block_list *src = map->id2bl(val2); - val3 = 1; - if(src) - val3 = 200 + 100 * val1 + status_get_int(src); - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - } - break; - case SC_VACUUM_EXTREME: - tick -= (st->str / 20) * 1000; - val4 = val3 = tick / 100; - tick_time = 100; // [GodLesZ] tick time - break; - case SC_SWING: - val2 = 4 * val1; // Walk speed and aspd reduction. - break; - case SC_SYMPHONY_LOVE: - case SC_RUSH_WINDMILL: - case SC_ECHOSONG: - val2 = 6 * val1; - val2 += val3; //Adding 1% * Lesson Bonus - val2 += (int)(val4*2/10); //Adding 0.2% per JobLevel - break; - case SC_MOONLIT_SERENADE: - val2 = 10 * val1; - break; - case SC_HARMONIZE: - val2 = 5 + 5 * val1; - break; - case SC_SIREN: - val4 = tick / 2000; - tick_time = 2000; // [GodLesZ] tick time - break; - case SC_DEEP_SLEEP: - val4 = tick / 2000; - tick_time = 2000; // [GodLesZ] tick time - break; - case SC_SIRCLEOFNATURE: - val2 = 1 + val1; //SP consume - val3 = 40 * val1; //HP recovery - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_SONG_OF_MANA: - val3 = 10 + (2 * val2); - val4 = tick/3000; - tick_time = 3000; // [GodLesZ] tick time - break; - case SC_SATURDAY_NIGHT_FEVER: - if (!val4) val4 = skill->get_time2(status->sc2skill(type),val1); - if (!val4) val4 = 3000; - val3 = tick/val4; - tick_time = val4; // [GodLesZ] tick time - break; - case SC_GLOOMYDAY: - val2 = 20 + 5 * val1; // Flee reduction. - val3 = 15 + 5 * val1; // ASPD reduction. - if( sd && rand()%100 < val1 ){ // (Skill Lv) % - val4 = 1; // reduce walk speed by half. - if( pc_isriding(sd) ) pc->setriding(sd, 0); - if( pc_isridingdragon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_DRAGON); - } - break; - case SC_GLOOMYDAY_SK: - // Random number between [15 ~ (Voice Lesson Skill Level x 5) + (Skill Level x 10)] %. - val2 = 15 + rand()%( (sd?pc->checkskill(sd, WM_LESSON)*5:0) + val1*10 ); - break; - case SC_SITDOWN_FORCE: - case SC_BANANA_BOMB_SITDOWN_POSTDELAY: - if( sd && !pc_issit(sd) ) - { - pc_setsit(sd); - skill->sit(sd,1); - clif->sitting(bl); - } - break; - case SC_DANCE_WITH_WUG: - val3 = (5 * val1) + (1 * val2); //Still need official value. - break; - case SC_LERADS_DEW: - val3 = (5 * val1) + (1 * val2); - break; - case SC_MELODYOFSINK: - val3 = (5 * val1) + (1 * val2); break; - case SC_BEYOND_OF_WARCRY: - val3 = (5 * val1) + (1 * val2); - break; - case SC_UNLIMITED_HUMMING_VOICE: - { - struct unit_data *ud = unit->bl2ud(bl); - if( ud == NULL ) return 0; - ud->state.skillcastcancel = 0; - val3 = 15 - (2 * val2); - } - break; - case SC_LG_REFLECTDAMAGE: - val2 = 15 + 5 * val1; - val3 = (val1==5)?20:(val1+4)*2; // SP consumption - val4 = tick/10000; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_FORCEOFVANGUARD: // This is not the official way to handle it but I think we should use it. [pakpil] - val2 = 20 + 12 * (val1 - 1); // Chance - val3 = 5 + (2 * val1); // Max rage counters - tick = -1; //endless duration in the client - tick_time = 6000; // [GodLesZ] tick time + case SC_FORCEOFVANGUARD: val_flag |= 1|2|4; break; - case SC_EXEEDBREAK: - val1 *= 150; // 150 * skill_lv - if( sd && sd->inventory_data[sd->equip_index[EQI_HAND_R]] ) { // Chars. - val1 += (sd->inventory_data[sd->equip_index[EQI_HAND_R]]->weight/10 * sd->inventory_data[sd->equip_index[EQI_HAND_R]]->wlv * status->get_lv(bl) / 100); - val1 += 15 * (sd ? sd->status.job_level:50) + 100; - } else // Mobs - val1 += (400 * status->get_lv(bl) / 100) + (15 * (status->get_lv(bl) / 2)); // About 1138% at mob_lvl 99. Is an aproximation to a standard weapon. [pakpil] - break; - case SC_PRESTIGE: // Based on suggested formula in iRO Wiki and some test, still need more test. [pakpil] - val2 = ((st->int_ + st->luk) / 6) + 5; // Chance to evade magic damage. - val1 *= 15; // Defence added - if( sd ) - val1 += 10 * pc->checkskill(sd,CR_DEFENDER); + case SC_PRESTIGE: val_flag |= 1|2; break; case SC_BANDING: - tick_time = 5000; // [GodLesZ] tick time val_flag |= 1; break; case SC_SHIELDSPELL_DEF: @@ -8419,554 +8745,312 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_SHIELDSPELL_REF: val_flag |= 1|2; break; - case SC_MAGNETICFIELD: - val3 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_INSPIRATION: - if( sd ) { - val2 = (40 * val1) + (3 * sd->status.job_level); // ATK bonus - val3 = (sd->status.job_level / 10) * 2 + 12; // All stat bonus - } - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - status->change_clear_buffs(bl,3); //Remove buffs/debuffs - break; case SC_SPELLFIST: case SC_CURSEDCIRCLE_ATKER: val_flag |= 1|2|4; break; case SC_CRESCENTELBOW: - val2 = 94 + val1; val_flag |= 1|2; break; - case SC_LIGHTNINGWALK: // [(Job Level / 2) + (40 + 5 * Skill Level)] % - val1 = (sd?sd->status.job_level:2)/2 + 40 + 5 * val1; + case SC_LIGHTNINGWALK: val_flag |= 1; break; - case SC_RAISINGDRAGON: - val3 = tick / 5000; - tick_time = 5000; // [GodLesZ] tick time - break; - case SC_GENTLETOUCH_CHANGE: - {// take note there is no def increase as skill desc says. [malufett] - struct block_list * src; - val3 = st->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] % - if( (src = map->id2bl(val2)) ){ - val4 = ( 200/status_get_int(src) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] - val2 = ( status_get_dex(src)/4 + status_get_str(src)/2 ) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5] - } - } - break; - case SC_GENTLETOUCH_REVITALIZE: - {// take note there is no vit,aspd,speed increase as skill desc says. [malufett] - struct block_list * src; - val3 = val1 * 30 + 150; // Natural HP recovery increase: [(Skill Level x 30) + 50] % - if( (src = map->id2bl(val2)) ) // the stat def is not shown in the status window and it is process differently - val4 = ( status_get_vit(src)/4 ) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level] - } - break; case SC_PYROTECHNIC_OPTION: val_flag |= 1|2|4; break; case SC_HEATER_OPTION: - val2 = 120; // Watk. TODO: Renewal (Atk2) - val3 = 33; // % Increase effects. - val4 = 3; // Change into fire element. val_flag |= 1|2|4; break; - case SC_TROPIC_OPTION: - val2 = 180; // Watk. TODO: Renewal (Atk2) - val3 = MG_FIREBOLT; - break; case SC_AQUAPLAY_OPTION: - val2 = 40; val_flag |= 1|2|4; break; case SC_COOLER_OPTION: - val2 = 80; // % Freezing chance - val3 = 33; // % increased damage - val4 = 1; // Change into water elemet val_flag |= 1|2|4; break; case SC_CHILLY_AIR_OPTION: - val2 = 120; // Matk. TODO: Renewal (Matk1) - val3 = MG_COLDBOLT; val_flag |= 1|2; break; case SC_GUST_OPTION: val_flag |= 1|2; break; - case SC_WIND_STEP_OPTION: - val2 = 50; // % Increase speed and flee. - break; case SC_BLAST_OPTION: - val2 = 20; - val3 = ELE_WIND; val_flag |= 1|2|4; break; case SC_WILD_STORM_OPTION: - val2 = MG_LIGHTNINGBOLT; val_flag |= 1|2; break; case SC_PETROLOGY_OPTION: - val2 = 5; - val3 = 50; val_flag |= 1|2|4; break; case SC_CURSED_SOIL_OPTION: - val2 = 10; - val3 = 33; - val4 = 2; val_flag |= 1|2|4; break; case SC_UPHEAVAL_OPTION: - val2 = WZ_EARTHSPIKE; val_flag |= 1|2; break; case SC_CIRCLE_OF_FIRE_OPTION: - val2 = 300; val_flag |= 1|2; break; - case SC_FIRE_CLOAK_OPTION: - case SC_WATER_DROP_OPTION: - case SC_WIND_CURTAIN_OPTION: - case SC_STONE_SHIELD_OPTION: - val2 = 20; // Elemental modifier. Not confirmed. - break; - case SC_CIRCLE_OF_FIRE: - case SC_FIRE_CLOAK: - case SC_WATER_DROP: - case SC_WATER_SCREEN: - case SC_WIND_CURTAIN: - case SC_WIND_STEP: - case SC_STONE_SHIELD: - case SC_SOLID_SKIN: - val2 = 10; - tick_time = 2000; // [GodLesZ] tick time - break; case SC_WATER_BARRIER: - val2 = 40; // Increasement. Mdef1 ??? - val3 = 20; // Reductions. Atk2, Flee1, Matk1 ???? val_flag |= 1|2|4; break; - case SC_ZEPHYR: - val2 = 22; // Flee. - break; - case SC_TIDAL_WEAPON: - val2 = 20; // Increase Elemental's attack. - break; - case SC_ROCK_CRUSHER: - case SC_ROCK_CRUSHER_ATK: - case SC_POWER_OF_GAIA: - val2 = 33; - break; - case SC_MELON_BOMB: - case SC_BANANA_BOMB: - val1 = 15; - break; - case SC_STOMACHACHE: - val2 = 8; // SP consume. - val4 = tick / 10000; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_KYOUGAKU: - val2 = 2*val1 + rand()%(3 * val1); - clif->status_change(bl, SI_ACTIVE_MONSTER_TRANSFORM, 1, 0, 1002, 0, 0); // Poring in disguise - break; - case SC_KAGEMUSYA: - val3 = val1 * 2; - case SC_IZAYOI: - val2 = tick/1000; - tick_time = 1000; - break; - case SC_ZANGETSU: - val2 = val4 = status->get_lv(bl) / 3 + 20 * val1; - val3 = status->get_lv(bl) / 2 + 30 * val1; - val2 = (!(status_get_hp(bl)%2) ? val2 : -val3); - val3 = (!(status_get_sp(bl)%2) ? val4 : -val3); - break; - case SC_GENSOU: - -#define PER( a ) do { \ - if( a <= 15 ) lv = 1; \ - else if( a <= 30 ) lv = 2; \ - else if( a <= 50 ) lv = 3; \ - else if( a <= 75 ) lv = 4; \ -} while(0) - - { - int hp = status_get_hp(bl), sp = status_get_sp(bl), lv = 5; - - if( rand()%100 > (25 + 10 * val1) - status_get_int(bl) / 2) - return 0; - - PER( 100 / (status_get_max_hp(bl) / hp) ); - status->heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, 1); - - PER( 100 / (status_get_max_sp(bl) / sp) ); - status->heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), 1); - } -#undef PER - break; - case SC_ANGRIFFS_MODUS: - val2 = 50 + 20 * val1; //atk bonus - val3 = 40 + 20 * val1; // Flee reduction. - val4 = tick/1000; // hp/sp reduction timer - tick_time = 1000; - break; - case SC_NEUTRALBARRIER: - tick_time = tick; - tick = -1; - break; - case SC_GOLDENE_FERSE: - val2 = 10 + 10*val1; //max hp bonus - val3 = 6 + 4 * val1; // Aspd Bonus - val4 = 2 + 2 * val1; // Chance of holy attack - break; - case SC_OVERED_BOOST: - val2 = 300 + 40*val1; //flee bonus - val3 = 179 + 2*val1; //aspd bonus - break; - case SC_GRANITIC_ARMOR: - val2 = 2*val1; //dmg reduction - val3 = 6*val1; //dmg on status end - break; - case SC_MAGMA_FLOW: - val2 = 3*val1; //activation chance - break; - case SC_PYROCLASTIC: - val2 += 10*val1; //atk bonus - break; - case SC_NEEDLE_OF_PARALYZE: //[Lighta] need real info - val2 = 2*val1; //def reduction - val3 = 500*val1; //varcast augmentation - break; - case SC_PAIN_KILLER: //[Lighta] need real info - val2 = 2*val1; //aspd reduction % - val3 = 2*val1; //dmg reduction % - if(sc->data[SC_NEEDLE_OF_PARALYZE]) - sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration - break; - case SC_STYLE_CHANGE: //[Lighta] need real info - tick = -1; - if(val2 == MH_MD_FIGHTING) val2 = MH_MD_GRAPPLING; - else val2 = MH_MD_FIGHTING; - break; - case SC_FULL_THROTTLE: - status_percent_heal(bl,100,0); - val2 = 7 - val1; - tick_time = 1000; - val4 = tick / tick_time; - break; - case SC_KINGS_GRACE: - val2 = 3 + val1; - tick_time = 1000; - val4 = tick / tick_time; - break; - case SC_TELEKINESIS_INTENSE: - val2 = 10 * val1; - val3 = 40 * val1; - break; - case SC_OFFERTORIUM: - val2 = 30 * val1; - break; - case SC_FRIGG_SONG: - val2 = 5 * val1; - val3 = 1000 + 100 * val1; - tick_time = 10000; - val4 = tick / tick_time; - break; - case SC_MONSTER_TRANSFORM: - if( !mob->db_checkid(val1) ) - val1 = 1002; // default poring - val_flag |= 1; - break; - default: - if( calc_flag == SCB_NONE && status->SkillChangeTable[type] == 0 && status->IconChangeTable[type] == 0 ) - { //Status change with no calc, no icon, and no skill associated...? - ShowError("UnknownStatusChange [%d]\n", type); - return 0; - } - } - } else { //Special considerations when loading SC data. - switch( type ) { - case SC_WEDDING: - case SC_XMAS: - case SC_SUMMER: - case SC_HANBOK: - if( !vd ) break; - clif->changelook(bl,LOOK_BASE,vd->class_); - clif->changelook(bl,LOOK_WEAPON,0); - clif->changelook(bl,LOOK_SHIELD,0); - clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); - break; - case SC_KAAHI: - val4 = INVALID_TIMER; - break; - case SC_SUMMON1: - case SC_SUMMON2: - case SC_SUMMON3: - case SC_SUMMON4: - case SC_SUMMON5: + case SC_CASH_PLUSEXP: + case SC_CASH_PLUSONLYJOBEXP: case SC_MONSTER_TRANSFORM: + case SC_CASH_RECEIVEITEM: val_flag |= 1; break; - case SC_KYOUGAKU: - clif->status_change(bl, SI_ACTIVE_MONSTER_TRANSFORM, 1, 0, 1002, 0, 0); // Poring in disguise - break; - } } - + /* [Ind/Hercules] */ if( sd && status->DisplayType[type] ) { int dval1 = 0, dval2 = 0, dval3 = 0; switch( type ) { - case SC_ALL_RIDING: - dval1 = 1; - break; - default: /* all others: just copy val1 */ - dval1 = val1; - break; + case SC_ALL_RIDING: + dval1 = 1; + break; + default: /* all others: just copy val1 */ + dval1 = val1; + break; } status->display_add(sd,type,dval1,dval2,dval3); } //Those that make you stop attacking/walking.... switch (type) { - case SC_FREEZE: - case SC_STUN: - case SC_SLEEP: - case SC_STONE: - case SC_DEEP_SLEEP: - if (sd && pc_issit(sd)) //Avoid sprite sync problems. - pc->setstand(sd); - case SC_TRICKDEAD: - status_change_end(bl, SC_DANCING, INVALID_TIMER); - // Cancel cast when get status [LuzZza] - if (battle_config.sc_castcancel&bl->type) - unit->skillcastcancel(bl, 0); - case SC_WHITEIMPRISON: - unit->stop_attack(bl); - case SC_STOP: - case SC_CONFUSION: - case SC_RG_CCONFINE_M: - case SC_RG_CCONFINE_S: - case SC_SPIDERWEB: - case SC_ELECTRICSHOCKER: - case SC_WUGBITE: - case SC_THORNS_TRAP: - case SC__MANHOLE: - case SC_COLD: - case SC_CURSEDCIRCLE_ATKER: - case SC_CURSEDCIRCLE_TARGET: - case SC_FEAR: - case SC_NETHERWORLD: - case SC_MEIKYOUSISUI: - case SC_KYOUGAKU: - case SC_NEEDLE_OF_PARALYZE: - case SC_DEATHBOUND: - unit->stop_walking(bl,1); - break; - case SC_ANKLESNARE: - if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) ) + case SC_FREEZE: + case SC_STUN: + case SC_SLEEP: + case SC_STONE: + case SC_DEEP_SLEEP: + if (sd && pc_issit(sd)) //Avoid sprite sync problems. + pc->setstand(sd); + case SC_TRICKDEAD: + status_change_end(bl, SC_DANCING, INVALID_TIMER); + // Cancel cast when get status [LuzZza] + if (battle_config.sc_castcancel&bl->type) + unit->skillcastcancel(bl, 0); + case SC_WHITEIMPRISON: + unit->stop_attack(bl); + case SC_STOP: + case SC_CONFUSION: + case SC_RG_CCONFINE_M: + case SC_RG_CCONFINE_S: + case SC_SPIDERWEB: + case SC_ELECTRICSHOCKER: + case SC_WUGBITE: + case SC_THORNS_TRAP: + case SC__MANHOLE: + case SC_COLD: + case SC_CURSEDCIRCLE_ATKER: + case SC_CURSEDCIRCLE_TARGET: + case SC_FEAR: + case SC_NETHERWORLD: + case SC_MEIKYOUSISUI: + case SC_KYOUGAKU: + case SC_NEEDLE_OF_PARALYZE: + case SC_DEATHBOUND: unit->stop_walking(bl,1); - break; - case SC_HIDING: - case SC_CLOAKING: - case SC_CLOAKINGEXCEED: - case SC_CHASEWALK: - case SC_WEIGHTOVER90: - case SC_CAMOUFLAGE: - case SC_SIREN: - unit->stop_attack(bl); - break; - case SC_SILENCE: - if (battle_config.sc_castcancel&bl->type) - unit->skillcastcancel(bl, 0); - break; - /* */ - case SC_ITEMSCRIPT: - if( sd ) { - switch( val1 ) { - //case 4121://Phree - //case 4047://Ghostring - case 4302://Gunka - clif->status_change(bl,SI_MVPCARD_TAOGUNKA,1,tick,0,0,0); - break; - case 4132://Mistress - clif->status_change(bl,SI_MVPCARD_MISTRESS,1,tick,0,0,0); - break; - case 4143://Orc Hero - clif->status_change(bl,SI_MVPCARD_ORCHERO,1,tick,0,0,0); - break; - case 4135://Orc Lord - clif->status_change(bl,SI_MVPCARD_ORCLORD,1,tick,0,0,0); - break; + break; + case SC_ANKLESNARE: + if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) ) + unit->stop_walking(bl,1); + break; + case SC_HIDING: + case SC_CLOAKING: + case SC_CLOAKINGEXCEED: + case SC_CHASEWALK: + case SC_WEIGHTOVER90: + case SC_CAMOUFLAGE: + case SC_SIREN: + unit->stop_attack(bl); + break; + case SC_SILENCE: + if (battle_config.sc_castcancel&bl->type) + unit->skillcastcancel(bl, 0); + break; + /* */ + case SC_ITEMSCRIPT: + if( sd ) { + switch( val1 ) { + //case 4121://Phree + //case 4047://Ghostring + case 4302://Gunka + clif->status_change(bl,SI_MVPCARD_TAOGUNKA,1,tick,0,0,0); + break; + case 4132://Mistress + clif->status_change(bl,SI_MVPCARD_MISTRESS,1,tick,0,0,0); + break; + case 4143://Orc Hero + clif->status_change(bl,SI_MVPCARD_ORCHERO,1,tick,0,0,0); + break; + case 4135://Orc Lord + clif->status_change(bl,SI_MVPCARD_ORCLORD,1,tick,0,0,0); + break; + } } - } - break; + break; } // Set option as needed. opt_flag = 1; switch(type) { //OPT1 - case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break; - case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break; - case SC_STUN: sc->opt1 = OPT1_STUN; break; - case SC_DEEP_SLEEP: opt_flag = 0; - case SC_SLEEP: sc->opt1 = OPT1_SLEEP; break; - case SC_BURNING: sc->opt1 = OPT1_BURNING; break; // Burning need this to be showed correctly. [pakpil] - case SC_WHITEIMPRISON: sc->opt1 = OPT1_IMPRISON; break; - case SC_COLD: sc->opt1 = OPT1_CRYSTALIZE; break; + case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break; + case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break; + case SC_STUN: sc->opt1 = OPT1_STUN; break; + case SC_DEEP_SLEEP: opt_flag = 0; + case SC_SLEEP: sc->opt1 = OPT1_SLEEP; break; + case SC_BURNING: sc->opt1 = OPT1_BURNING; break; // Burning need this to be showed correctly. [pakpil] + case SC_WHITEIMPRISON: sc->opt1 = OPT1_IMPRISON; break; + case SC_COLD: sc->opt1 = OPT1_CRYSTALIZE; break; //OPT2 - case SC_POISON: sc->opt2 |= OPT2_POISON; break; - case SC_CURSE: sc->opt2 |= OPT2_CURSE; break; - case SC_SILENCE: sc->opt2 |= OPT2_SILENCE; break; + case SC_POISON: sc->opt2 |= OPT2_POISON; break; + case SC_CURSE: sc->opt2 |= OPT2_CURSE; break; + case SC_SILENCE: sc->opt2 |= OPT2_SILENCE; break; - case SC_CRUCIS: - sc->opt2 |= OPT2_SIGNUMCRUCIS; - break; + case SC_CRUCIS: + sc->opt2 |= OPT2_SIGNUMCRUCIS; + break; - case SC_BLIND: sc->opt2 |= OPT2_BLIND; break; - case SC_ANGELUS: sc->opt2 |= OPT2_ANGELUS; break; - case SC_BLOODING: sc->opt2 |= OPT2_BLEEDING; break; - case SC_DPOISON: sc->opt2 |= OPT2_DPOISON; break; + case SC_BLIND: sc->opt2 |= OPT2_BLIND; break; + case SC_ANGELUS: sc->opt2 |= OPT2_ANGELUS; break; + case SC_BLOODING: sc->opt2 |= OPT2_BLEEDING; break; + case SC_DPOISON: sc->opt2 |= OPT2_DPOISON; break; //OPT3 - case SC_TWOHANDQUICKEN: - case SC_ONEHANDQUICKEN: - case SC_SPEARQUICKEN: - case SC_LKCONCENTRATION: - case SC_MER_QUICKEN: - sc->opt3 |= OPT3_QUICKEN; - opt_flag = 0; - break; - case SC_OVERTHRUSTMAX: - case SC_OVERTHRUST: - case SC_SWOO: //Why does it shares the same opt as Overthrust? Perhaps we'll never know... - sc->opt3 |= OPT3_OVERTHRUST; - opt_flag = 0; - break; - case SC_ENERGYCOAT: - case SC_SKE: - sc->opt3 |= OPT3_ENERGYCOAT; - opt_flag = 0; - break; - case SC_INCATKRATE: - //Simulate Explosion Spirits effect for NPC_POWERUP [Skotlex] - if (bl->type != BL_MOB) { + case SC_TWOHANDQUICKEN: + case SC_ONEHANDQUICKEN: + case SC_SPEARQUICKEN: + case SC_LKCONCENTRATION: + case SC_MER_QUICKEN: + sc->opt3 |= OPT3_QUICKEN; opt_flag = 0; break; - } - case SC_EXPLOSIONSPIRITS: - sc->opt3 |= OPT3_EXPLOSIONSPIRITS; - opt_flag = 0; - break; - case SC_STEELBODY: - case SC_SKA: - sc->opt3 |= OPT3_STEELBODY; - opt_flag = 0; - break; - case SC_BLADESTOP: - sc->opt3 |= OPT3_BLADESTOP; - opt_flag = 0; - break; - case SC_AURABLADE: - sc->opt3 |= OPT3_AURABLADE; - opt_flag = 0; - break; - case SC_BERSERK: - opt_flag = 0; - sc->opt3 |= OPT3_BERSERK; - break; - // case ???: // doesn't seem to do anything - // sc->opt3 |= OPT3_LIGHTBLADE; - // opt_flag = 0; - // break; - case SC_DANCING: - if ((val1&0xFFFF) == CG_MOONLIT) - sc->opt3 |= OPT3_MOONLIT; - opt_flag = 0; - break; - case SC_MARIONETTE_MASTER: - case SC_MARIONETTE: - sc->opt3 |= OPT3_MARIONETTE; - opt_flag = 0; - break; - case SC_ASSUMPTIO: - sc->opt3 |= OPT3_ASSUMPTIO; - opt_flag = 0; - break; - case SC_WARM: //SG skills [Komurka] - sc->opt3 |= OPT3_WARM; - opt_flag = 0; - break; - case SC_KAITE: - sc->opt3 |= OPT3_KAITE; - opt_flag = 0; - break; - case SC_NJ_BUNSINJYUTSU: - sc->opt3 |= OPT3_BUNSIN; - opt_flag = 0; - break; - case SC_SOULLINK: - sc->opt3 |= OPT3_SOULLINK; - opt_flag = 0; - break; - case SC_PROPERTYUNDEAD: - sc->opt3 |= OPT3_UNDEAD; - opt_flag = 0; - break; - // case ???: // from DA_CONTRACT (looks like biolab mobs aura) - // sc->opt3 |= OPT3_CONTRACT; - // opt_flag = 0; - // break; + case SC_OVERTHRUSTMAX: + case SC_OVERTHRUST: + case SC_SWOO: //Why does it shares the same opt as Overthrust? Perhaps we'll never know... + sc->opt3 |= OPT3_OVERTHRUST; + opt_flag = 0; + break; + case SC_ENERGYCOAT: + case SC_SKE: + sc->opt3 |= OPT3_ENERGYCOAT; + opt_flag = 0; + break; + case SC_INCATKRATE: + //Simulate Explosion Spirits effect for NPC_POWERUP [Skotlex] + if (bl->type != BL_MOB) { + opt_flag = 0; + break; + } + case SC_EXPLOSIONSPIRITS: + sc->opt3 |= OPT3_EXPLOSIONSPIRITS; + opt_flag = 0; + break; + case SC_STEELBODY: + case SC_SKA: + sc->opt3 |= OPT3_STEELBODY; + opt_flag = 0; + break; + case SC_BLADESTOP: + sc->opt3 |= OPT3_BLADESTOP; + opt_flag = 0; + break; + case SC_AURABLADE: + sc->opt3 |= OPT3_AURABLADE; + opt_flag = 0; + break; + case SC_BERSERK: + opt_flag = 0; + sc->opt3 |= OPT3_BERSERK; + break; +// case ???: // doesn't seem to do anything +// sc->opt3 |= OPT3_LIGHTBLADE; +// opt_flag = 0; +// break; + case SC_DANCING: + if ((val1&0xFFFF) == CG_MOONLIT) + sc->opt3 |= OPT3_MOONLIT; + opt_flag = 0; + break; + case SC_MARIONETTE_MASTER: + case SC_MARIONETTE: + sc->opt3 |= OPT3_MARIONETTE; + opt_flag = 0; + break; + case SC_ASSUMPTIO: + sc->opt3 |= OPT3_ASSUMPTIO; + opt_flag = 0; + break; + case SC_WARM: //SG skills [Komurka] + sc->opt3 |= OPT3_WARM; + opt_flag = 0; + break; + case SC_KAITE: + sc->opt3 |= OPT3_KAITE; + opt_flag = 0; + break; + case SC_NJ_BUNSINJYUTSU: + sc->opt3 |= OPT3_BUNSIN; + opt_flag = 0; + break; + case SC_SOULLINK: + sc->opt3 |= OPT3_SOULLINK; + opt_flag = 0; + break; + case SC_PROPERTYUNDEAD: + sc->opt3 |= OPT3_UNDEAD; + opt_flag = 0; + break; +// case ???: // from DA_CONTRACT (looks like biolab mobs aura) +// sc->opt3 |= OPT3_CONTRACT; +// opt_flag = 0; +// break; //OPTION - case SC_HIDING: - sc->option |= OPTION_HIDE; - opt_flag = 2; - break; - case SC_CLOAKING: - case SC_CLOAKINGEXCEED: - case SC__INVISIBILITY: - sc->option |= OPTION_CLOAK; - opt_flag = 2; - break; - case SC_CHASEWALK: - sc->option |= OPTION_CHASEWALK|OPTION_CLOAK; - opt_flag = 2; - break; - case SC_SIGHT: - sc->option |= OPTION_SIGHT; - break; - case SC_RUWACH: - sc->option |= OPTION_RUWACH; - break; - case SC_WEDDING: - sc->option |= OPTION_WEDDING; - opt_flag |= 0x4; - break; - case SC_XMAS: - sc->option |= OPTION_XMAS; - opt_flag |= 0x4; - break; - case SC_SUMMER: - sc->option |= OPTION_SUMMER; - opt_flag |= 0x4; - break; - case SC_HANBOK: - sc->option |= OPTION_HANBOK; - opt_flag |= 0x4; - break; - case SC_ORCISH: - sc->option |= OPTION_ORCISH; - break; - case SC_FUSION: - sc->option |= OPTION_FLYING; - break; - default: - opt_flag = 0; + case SC_HIDING: + sc->option |= OPTION_HIDE; + opt_flag = 2; + break; + case SC_CLOAKING: + case SC_CLOAKINGEXCEED: + case SC__INVISIBILITY: + sc->option |= OPTION_CLOAK; + opt_flag = 2; + break; + case SC_CHASEWALK: + sc->option |= OPTION_CHASEWALK|OPTION_CLOAK; + opt_flag = 2; + break; + case SC_SIGHT: + sc->option |= OPTION_SIGHT; + break; + case SC_RUWACH: + sc->option |= OPTION_RUWACH; + break; + case SC_WEDDING: + sc->option |= OPTION_WEDDING; + opt_flag |= 0x4; + break; + case SC_XMAS: + sc->option |= OPTION_XMAS; + opt_flag |= 0x4; + break; + case SC_SUMMER: + sc->option |= OPTION_SUMMER; + opt_flag |= 0x4; + break; + case SC_HANBOK: + sc->option |= OPTION_HANBOK; + opt_flag |= 0x4; + break; + case SC_ORCISH: + sc->option |= OPTION_ORCISH; + break; + case SC_FUSION: + sc->option |= OPTION_FLYING; + break; + default: + opt_flag = 0; } //On Aegis, when turning on a status change, first goes the option packet, then the sc packet. @@ -9020,81 +9104,81 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing switch (type) { - case SC_BERSERK: - if (!(sce->val2)) { //don't heal if already set - status->heal(bl, st->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block. - status->set_sp(bl, 0, 0); //Damage all SP - } - sce->val2 = 5 * st->max_hp / 100; - break; - case SC_HLIF_CHANGE: - status_percent_heal(bl, 100, 100); - break; - case SC_RUN: - { - struct unit_data *ud = unit->bl2ud(bl); - if( ud ) - ud->state.running = unit->run(bl); - } - break; - case SC_CASH_BOSS_ALARM: - clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message - break; - case SC_MER_HP: - status_percent_heal(bl, 100, 0); // Recover Full HP - break; - case SC_MER_SP: - status_percent_heal(bl, 0, 100); // Recover Full SP - break; - /** - * Ranger - **/ - case SC_WUGDASH: - { - struct unit_data *ud = unit->bl2ud(bl); - if( ud ) - ud->state.running = unit->wugdash(bl, sd); - } - break; - case SC_COMBOATTACK: - switch (sce->val1) { - case TK_STORMKICK: - clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1); + case SC_BERSERK: + if (!(sce->val2)) { //don't heal if already set + status->heal(bl, st->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block. + status->set_sp(bl, 0, 0); //Damage all SP + } + sce->val2 = 5 * st->max_hp / 100; break; - case TK_DOWNKICK: - clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1); + case SC_HLIF_CHANGE: + status_percent_heal(bl, 100, 100); break; - case TK_TURNKICK: - clif->skill_nodamage(bl,bl,TK_READYTURN,1,1); + case SC_RUN: + { + struct unit_data *ud = unit->bl2ud(bl); + if( ud ) + ud->state.running = unit->run(bl); + } break; - case TK_COUNTER: - clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); + case SC_CASH_BOSS_ALARM: + clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message break; - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - if (sd) - clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); + case SC_MER_HP: + status_percent_heal(bl, 100, 0); // Recover Full HP break; - case TK_JUMPKICK: - if (sd) - clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); + case SC_MER_SP: + status_percent_heal(bl, 0, 100); // Recover Full SP break; - case MO_TRIPLEATTACK: - if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0) - clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); + /** + * Ranger + **/ + case SC_WUGDASH: + { + struct unit_data *ud = unit->bl2ud(bl); + if( ud ) + ud->state.running = unit->wugdash(bl, sd); + } break; - case SR_FALLENEMPIRE: - if (sd){ - clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); - clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); + case SC_COMBOATTACK: + switch (sce->val1) { + case TK_STORMKICK: + clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1); + break; + case TK_DOWNKICK: + clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1); + break; + case TK_TURNKICK: + clif->skill_nodamage(bl,bl,TK_READYTURN,1,1); + break; + case TK_COUNTER: + clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); + break; + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + if (sd) + clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); + break; + case TK_JUMPKICK: + if (sd) + clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); + break; + case MO_TRIPLEATTACK: + if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0) + clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); + break; + case SR_FALLENEMPIRE: + if (sd){ + clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); + clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); + } + break; } break; - } - break; - case SC_RAISINGDRAGON: - sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie] - break; + case SC_RAISINGDRAGON: + sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie] + break; } if( opt_flag&2 && sd && sd->touching_id ) @@ -9252,6 +9336,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const { struct unit_data *ud = unit->bl2ud(bl); bool begin_spurt = true; + // Note: this int64 value is stored in two separate int32 variables (FIXME) + int64 starttick = (int64)sce->val3&0x00000000ffffffffLL; + starttick |= ((int64)sce->val4<<32)&0xffffffff00000000LL; + if (ud) { if(!ud->state.running) begin_spurt = false; @@ -9260,7 +9348,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const unit->stop_walking(bl,1); } if (begin_spurt && sce->val1 >= 7 - && DIFF_TICK(timer->gettick(), sce->val4) <= 1000 + && DIFF_TICK(timer->gettick(), starttick) <= 1000 && (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0)) ) sc_start(bl,SC_STRUP,100,sce->val1,skill->get_time2(status->sc2skill(type), sce->val1)); @@ -9869,7 +9957,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const return 1; } -int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { +int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) { struct block_list *bl; struct status_change *sc; struct status_change_entry *sce; @@ -9907,7 +9995,7 @@ int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { * For recusive status, like for each 5s we drop sp etc. * Reseting the end timer. *------------------------------------------*/ -int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) { +int status_change_timer(int tid, int64 tick, int id, intptr_t data) { enum sc_type type = (sc_type)data; struct block_list *bl; struct map_session_data *sd; @@ -10291,7 +10379,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) { if (sd && !pc_issit(sd)) { //can't cast if sit int mushroom_skill_id = 0, i; unit->stop_attack(bl); - unit->skillcastcancel(bl,1); + unit->skillcastcancel(bl,0); do { i = rnd() % MAX_SKILL_MAGICMUSHROOM_DB; mushroom_skill_id = skill->magicmushroom_db[i].skill_id; @@ -10299,15 +10387,15 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) { while( mushroom_skill_id == 0 ); switch( skill->get_casttype(mushroom_skill_id) ) { // Magic Mushroom skills are buffs or area damage - case CAST_GROUND: - skill->castend_pos2(bl,bl->x,bl->y,mushroom_skill_id,1,tick,0); - break; - case CAST_NODAMAGE: - skill->castend_nodamage_id(bl,bl,mushroom_skill_id,1,tick,0); - break; - case CAST_DAMAGE: - skill->castend_damage_id(bl,bl,mushroom_skill_id,1,tick,0); - break; + case CAST_GROUND: + skill->castend_pos2(bl,bl->x,bl->y,mushroom_skill_id,1,tick,0); + break; + case CAST_NODAMAGE: + skill->castend_nodamage_id(bl,bl,mushroom_skill_id,1,tick,0); + break; + case CAST_DAMAGE: + skill->castend_damage_id(bl,bl,mushroom_skill_id,1,tick,0); + break; } } @@ -10723,7 +10811,7 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) { struct block_list* src = va_arg(ap,struct block_list*); struct status_change_entry* sce = va_arg(ap,struct status_change_entry*); enum sc_type type = (sc_type)va_arg(ap,int); //gcc: enum args get promoted to int - unsigned int tick = va_arg(ap,unsigned int); + int64 tick = va_arg(ap, int64); if (status->isdead(bl)) return 0; @@ -10977,7 +11065,7 @@ int status_change_clear_buffs (struct block_list* bl, int type) { int status_change_spread( struct block_list *src, struct block_list *bl ) { int i, flag = 0; struct status_change *sc = status->get_sc(src); - unsigned int tick; + int64 tick; struct status_change_data data; if( !sc || !sc->count ) @@ -11019,7 +11107,7 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) { const struct TimerData *td = timer->get(sc->data[i]->timer); if (td == NULL || td->func != status->change_timer || DIFF_TICK(td->tick,tick) < 0) continue; - data.tick = DIFF_TICK(td->tick,tick); + data.tick = DIFF_TICK32(td->tick,tick); } else data.tick = INVALID_TIMER; break; @@ -11247,8 +11335,9 @@ int status_natural_heal(struct block_list* bl, va_list args) { } //Natural heal main timer. -int status_natural_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { - status->natural_heal_diff_tick = DIFF_TICK(tick,status->natural_heal_prev_tick); +int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) { + // This difference is always positive and lower than UINT_MAX (~24 days) + status->natural_heal_diff_tick = (unsigned int)cap_value(DIFF_TICK(tick,status->natural_heal_prev_tick), 0, UINT_MAX); map->foreachregen(status->natural_heal); status->natural_heal_prev_tick = tick; return 0; diff --git a/src/map/status.h b/src/map/status.h index 9b1721d1a..254f3bfab 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -677,6 +677,9 @@ typedef enum sc_type { SC_MTF_MLEATKED, SC_MTF_CRIDAMAGE, + SC_MOONSTAR, + SC_SUPER_STAR, + SC_MAX, //Automatically updated max, used in for's to check we are within bounds. } sc_type; // Official status change ids, used to display status icons on the client. @@ -1858,7 +1861,8 @@ struct status_interface { sc_conf_type sc_conf[SC_MAX]; struct eri *data_ers; //For sc_data entries struct status_data dummy; - unsigned int natural_heal_prev_tick,natural_heal_diff_tick; + int64 natural_heal_prev_tick; + unsigned int natural_heal_diff_tick; /* */ int (*init) (void); void (*final) (void); @@ -1902,8 +1906,8 @@ struct status_interface { int (*get_sc_def) (struct block_list *bl, enum sc_type type, int rate, int tick, int flag); int (*change_start) (struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag); int (*change_end_) (struct block_list* bl, enum sc_type type, int tid, const char* file, int line); - int (*kaahi_heal_timer) (int tid, unsigned int tick, int id, intptr_t data); - int (*change_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*kaahi_heal_timer) (int tid, int64 tick, int id, intptr_t data); + int (*change_timer) (int tid, int64 tick, int id, intptr_t data); int (*change_timer_sub) (struct block_list* bl, va_list ap); int (*change_clear) (struct block_list* bl, int type); int (*change_clear_buffs) (struct block_list* bl, int type); @@ -1967,7 +1971,7 @@ struct status_interface { void (*display_add) (struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3); void (*display_remove) (struct map_session_data *sd, enum sc_type type); int (*natural_heal) (struct block_list *bl, va_list args); - int (*natural_heal_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*natural_heal_timer) (int tid, int64 tick, int id, intptr_t data); bool (*readdb_job1) (char *fields[], int columns, int current); bool (*readdb_job2) (char *fields[], int columns, int current); bool (*readdb_sizefix) (char *fields[], int columns, int current); diff --git a/src/map/unit.c b/src/map/unit.c index a7aca10b9..c7ba2f6f9 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -82,9 +82,6 @@ struct unit_data* unit_bl2ud2(struct block_list *bl) { return unit->bl2ud(bl); } -int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data); -int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data); - int unit_walktoxy_sub(struct block_list *bl) { int i; @@ -137,7 +134,7 @@ int unit_walktoxy_sub(struct block_list *bl) return 1; } -int unit_walktoxy_timer(int tid, unsigned int 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; uint8 dir; @@ -322,7 +319,7 @@ int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data) { return 0; } -int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data) { +int unit_delay_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { struct block_list *bl = map->id2bl(id); if (!bl || bl->prev == NULL) @@ -402,7 +399,7 @@ static inline void set_mobstate(struct block_list* bl, int flag) md->state.skillstate = md->state.aggressive ? MSS_FOLLOW : MSS_RUSH; } -int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr_t data) { +int unit_walktobl_sub(int tid, int64 tick, int id, intptr_t data) { struct block_list *bl = map->id2bl(id); struct unit_data *ud = bl?unit->bl2ud(bl):NULL; @@ -854,7 +851,7 @@ int unit_stop_walking(struct block_list *bl,int type) { struct unit_data *ud; const struct TimerData* td; - unsigned int tick; + int64 tick; nullpo_ret(bl); ud = unit->bl2ud(bl); @@ -1001,7 +998,7 @@ int unit_can_move(struct block_list *bl) { * Resume running after a walk delay *------------------------------------------*/ -int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data) { +int unit_resume_running(int tid, int64 tick, int id, intptr_t data) { struct unit_data *ud = (struct unit_data *)data; TBL_PC * sd = map->id2sd(id); @@ -1025,8 +1022,7 @@ int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data) { * if type is 0, this is a damage induced delay: if previous delay is active, do not change it. * if type is 1, this is a skill induced delay: walk-delay may only be increased, not decreased. *------------------------------------------*/ -int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int type) -{ +int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) { struct unit_data *ud = unit->bl2ud(bl); if (delay <= 0 || !ud) return 0; @@ -1073,7 +1069,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui struct status_change *sc; struct map_session_data *sd = NULL; struct block_list * target = NULL; - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); int temp = 0, range; nullpo_ret(src); @@ -1437,7 +1433,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui struct unit_data *ud = NULL; struct status_change *sc; struct block_list bl; - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); int range; nullpo_ret(src); @@ -1795,8 +1791,7 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir) /*========================================== * Continuous Attack (function timer) *------------------------------------------*/ -int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int tick) -{ +int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) { struct block_list *target; struct unit_data *ud; struct status_data *sstatus; @@ -1915,7 +1910,7 @@ int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int tick) } if(ud->state.attack_continue) { - if( src->type == BL_PC ) + if( src->type == BL_PC && battle_config.idletime_criteria & BCIDLE_ATTACK ) ((TBL_PC*)src)->idletime = last_tick; ud->attacktimer = timer->add(ud->attackabletime,unit->attack_timer,src->id,0); } @@ -1923,7 +1918,7 @@ int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int tick) return 1; } -int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data) { +int unit_attack_timer(int tid, int64 tick, int id, intptr_t data) { struct block_list *bl; bl = map->id2bl(id); if(bl && unit->attack_timer_sub(bl, tid, tick) == 0) @@ -1940,7 +1935,7 @@ int unit_skillcastcancel(struct block_list *bl,int type) { struct map_session_data *sd = NULL; struct unit_data *ud = unit->bl2ud( bl); - unsigned int tick=timer->gettick(); + int64 tick = timer->gettick(); int ret=0, skill_id; nullpo_ret(bl); @@ -1971,7 +1966,7 @@ int unit_skillcastcancel(struct block_list *bl,int type) else ret = timer->delete( ud->skilltimer, skill->castend_id ); if( ret < 0 ) - ShowError("delete timer error : skill_id : %d\n",ret); + ShowError("delete timer error %d : skill %d (%s)\n",ret,skill_id,skill->get_name(skill_id)); ud->skilltimer = INVALID_TIMER; @@ -2021,8 +2016,7 @@ int unit_counttargeted(struct block_list* bl) /*========================================== * *------------------------------------------*/ -int unit_fixdamage(struct block_list *src,struct block_list *target,unsigned int tick,int sdelay,int ddelay,int64 damage,int div,int type,int64 damage2) -{ +int unit_fixdamage(struct block_list *src, struct block_list *target, int64 tick, int sdelay, int ddelay, int64 damage, int div, int type, int64 damage2) { nullpo_ret(target); if(damage+damage2 <= 0) @@ -2200,6 +2194,10 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i instance->list[map->list[bl->m].instance_id].users--; instance->check_idle(map->list[bl->m].instance_id); } + if( sd->state.hpmeter_visible ) { + map->list[bl->m].hpmeter_visible--; + sd->state.hpmeter_visible = 0; + } sd->state.debug_remove_map = 1; // temporary state to track double remove_map's [FlavioJS] sd->debug_file = file; sd->debug_line = line; diff --git a/src/map/unit.h b/src/map/unit.h index be7b789d9..0567688a1 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -30,10 +30,10 @@ struct unit_data { int target_to; int attacktimer; int walktimer; - int chaserange; - unsigned int attackabletime; - unsigned int canact_tick; - unsigned int canmove_tick; + int chaserange; + int64 attackabletime; + int64 canact_tick; + int64 canmove_tick; uint8 dir; unsigned char walk_count; unsigned char target_count; @@ -77,12 +77,12 @@ struct unit_interface { /* */ struct unit_data* (*bl2ud) (struct block_list *bl); struct unit_data* (*bl2ud2) (struct block_list *bl); - int (*attack_timer) (int tid, unsigned int tick, int id, intptr_t data); - int (*walktoxy_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*attack_timer) (int tid, int64 tick, int id, intptr_t data); + int (*walktoxy_timer) (int tid, int64 tick, int id, intptr_t data); int (*walktoxy_sub) (struct block_list *bl); - int (*delay_walktoxy_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*delay_walktoxy_timer) (int tid, int64 tick, int id, intptr_t data); int (*walktoxy) (struct block_list *bl, short x, short y, int flag); - int (*walktobl_sub) (int tid, unsigned int tick, int id, intptr_t data); + int (*walktobl_sub) (int tid, int64 tick, int id, intptr_t data); int (*walktobl) (struct block_list *bl, struct block_list *tbl, int range, int flag); int (*run) (struct block_list *bl); int (*wugdash) (struct block_list *bl, struct map_session_data *sd); @@ -96,8 +96,8 @@ struct unit_interface { int (*skilluse_id) (struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv); int (*is_walking) (struct block_list *bl); int (*can_move) (struct block_list *bl); - int (*resume_running) (int tid, unsigned int tick, int id, intptr_t data); - int (*set_walkdelay) (struct block_list *bl, unsigned int tick, int delay, int type); + int (*resume_running) (int tid, int64 tick, int id, intptr_t data); + int (*set_walkdelay) (struct block_list *bl, int64 tick, int delay, int type); int (*skilluse_id2) (struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel); int (*skilluse_pos) (struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv); int (*skilluse_pos2) (struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel); @@ -109,11 +109,11 @@ struct unit_interface { bool (*can_reach_pos) (struct block_list *bl, int x, int y, int easy); bool (*can_reach_bl) (struct block_list *bl, struct block_list *tbl, int range, int easy, short *x, short *y); int (*calc_pos) (struct block_list *bl, int tx, int ty, uint8 dir); - int (*attack_timer_sub) (struct block_list *src, int tid, unsigned int tick); + int (*attack_timer_sub) (struct block_list *src, int tid, int64 tick); int (*skillcastcancel) (struct block_list *bl, int type); void (*dataset) (struct block_list *bl); int (*counttargeted) (struct block_list *bl); - int (*fixdamage) (struct block_list *src, struct block_list *target, unsigned int tick, int sdelay, int ddelay, int64 damage, int div, int type, int64 damage2); + int (*fixdamage) (struct block_list *src, struct block_list *target, int64 tick, int sdelay, int ddelay, int64 damage, int div, int type, int64 damage2); int (*changeviewsize) (struct block_list *bl, short size); int (*remove_map) (struct block_list *bl, clr_type clrtype, const char *file, int line, const char *func); void (*remove_map_pc) (struct map_session_data *sd, clr_type clrtype); |