# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: /home/lighta/Documents/Myscript/RO/Servs/rathena/src/map # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: atcommand.c --- atcommand.c Base (BASE) +++ atcommand.c Locally Modified (Based On LOCAL) @@ -6197,7 +6197,7 @@ unsigned long color=0; if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return -1; @@ -6248,7 +6248,7 @@ } if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return -1; @@ -7006,7 +7006,7 @@ } if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return -1; @@ -7433,7 +7433,7 @@ memset(atcmd_output, '\0', sizeof(atcmd_output)); if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return -1; Index: battle.c --- battle.c Base (BASE) +++ battle.c Locally Modified (Based On LOCAL) @@ -915,7 +915,7 @@ if( bl->type == BL_MOB ) { struct mob_data* md = BL_CAST(BL_MOB, bl); - if( map[bl->m].flag.battleground && (md->class_ == 1914 || md->class_ == 1915) && flag&BF_SKILL ) + if( map[bl->m].flag.battleground && (md->class_ == MOBID_BLUE_CRYST || md->class_ == MOBID_PINK_CRYST) && flag&BF_SKILL ) return 0; // Crystal cannot receive skill damage on battlegrounds } @@ -1818,7 +1818,7 @@ skillratio += sc->data[SC_OVERTHRUST]->val3; if(sc->data[SC_MAXOVERTHRUST]) skillratio += sc->data[SC_MAXOVERTHRUST]->val2; - if(sc->data[SC_BERSERK]) + if(sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) skillratio += 100; if(sc->data[SC_ZENKAI] && sstatus->rhw.ele == sc->data[SC_ZENKAI]->val2 ) skillratio += sc->data[SC_ZENKAI]->val1 * 2; Index: clif.c --- clif.c Base (BASE) +++ clif.c Locally Modified (Based On LOCAL) @@ -191,9 +191,6 @@ static int clif_parse (int fd); /*========================================== - * mapï¿œIᅵᅵipᅵݒᅵ - *------------------------------------------*/ -/*========================================== * Ip setting of map-server *------------------------------------------*/ int clif_setip(const char* ip) @@ -4422,6 +4419,8 @@ WFIFOW(fd,12)=unit->bl.y; if (battle_config.traps_setting&1 && skill_get_inf2(unit->group->skill_id)&INF2_TRAP) WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps. + else if (skill_get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT)) + WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps. else WFIFOB(fd,14)=unit->group->unit_id; WFIFOB(fd,15)=1; // ignored by client (always gets set to 1) @@ -5116,6 +5115,8 @@ WBUFW(buf,12)=unit->bl.y; if (unit->group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE) WBUFB(buf,14)=unit->val2&UF_SONG?UNT_DISSONANCE:UNT_UGLYDANCE; + else if (skill_get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT)) + WBUFB(buf, 14) = UNT_DUMMYSKILL; // Only display the unit at center. else WBUFB(buf,14)=unit->group->unit_id; WBUFB(buf,15)=1; // ignored by client (always gets set to 1) @@ -9623,7 +9624,7 @@ if( is_atcommand(fd, sd, message, 1) ) return; - if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; if( battle_config.min_chat_delay ) @@ -9934,7 +9935,7 @@ if ( is_atcommand(fd, sd, message, 1) ) return; - if (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) + if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) return; if (battle_config.min_chat_delay) { //[Skotlex] @@ -11578,7 +11579,7 @@ if( is_atcommand(fd, sd, message, 1) ) return; - if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; if( battle_config.min_chat_delay ) @@ -11904,22 +11905,22 @@ switch( RFIFOL(fd,2) ) { - case 0: // ï¿œMᅵᅵᅵhᅵᅵ{ᅵᅵᅵAᅵᅵᅵᅵᅵGᅵΏᅵᅵ + case 0: // Basic Information Guild, hostile alliance information clif_guild_basicinfo(sd); clif_guild_allianceinfo(sd); break; - case 1: // ᅵᅵᅵᅵᅵoï¿œ[ᅵᅵᅵXï¿œgï¿œAᅵᅵEᅵᅵᅵᅵᅵXï¿œg + case 1: // Members list, list job title clif_guild_positionnamelist(sd); clif_guild_memberlist(sd); break; - case 2: // ᅵᅵEᅵᅵᅵᅵᅵXï¿œgï¿œAᅵᅵEᅵᅵñƒŠƒXï¿œg + case 2: // List job title, title information list clif_guild_positionnamelist(sd); clif_guild_positioninfolist(sd); break; - case 3: // ï¿œXï¿œLᅵᅵᅵᅵᅵXï¿œg + case 3: // Skill list clif_guild_skillinfo(sd); break; - case 4: // ᅵǕᅵXï¿œg + case 4: // Expulsion list clif_guild_expulsionlist(sd); break; default: @@ -12113,7 +12114,7 @@ if( is_atcommand(fd, sd, message, 1) ) return; - if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; if( battle_config.min_chat_delay ) @@ -14978,7 +14979,7 @@ if( is_atcommand(fd, sd, message, 1) ) return; - if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; if( battle_config.min_chat_delay ) @@ -16422,7 +16423,7 @@ #endif #if PACKETVER < 2 3, 28, 19, 11, 3, -1, 9, 5, 52, 51, 56, 58, 41, 2, 6, 6, -#elif PACKETVER < 20071106 // 78-7b ï¿œTᅵᅵᅵȍ~ lv99ï¿œGï¿œtï¿œFï¿œNï¿œgï¿œp +#elif PACKETVER < 20071106 // 78-7b Lv99 effect for later Kameshima 3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6, #elif PACKETVER <= 20081217 // change in 0x78 and 0x7c 3, 28, 19, 11, 3, -1, 9, 5, 55, 53, 58, 60, 42, 2, 6, 6, @@ -16457,7 +16458,7 @@ 6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6, #if PACKETVER < 1 90, 86, 24, 6, 30,102, 8, 4, 8, 4, 14, 10, -1, 6, 2, 6, -#else // 196 comodoᅵȍ~ ᅵᅵԕ\ᅵᅵᅵAï¿œCï¿œRᅵᅵᅵp +#else // 196 comodo icon status display for later 90, 86, 24, 6, 30,102, 9, 4, 8, 4, 14, 10, -1, 6, 2, 6, #endif #if PACKETVER < 20081126 Index: map.c --- map.c Base (BASE) +++ map.c Locally Modified (Based On LOCAL) @@ -1687,6 +1687,7 @@ status_change_end(&sd->bl, SC_AUTOTRADE, INVALID_TIMER); status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER); status_change_end(&sd->bl, SC_BERSERK, INVALID_TIMER); + status_change_end(&sd->bl, SC__BLOODYLUST, INVALID_TIMER); status_change_end(&sd->bl, SC_TRICKDEAD, INVALID_TIMER); status_change_end(&sd->bl, SC_LEADERSHIP, INVALID_TIMER); status_change_end(&sd->bl, SC_GLORYWOUNDS, INVALID_TIMER); Index: map.h --- map.h Base (BASE) +++ map.h Locally Modified (Based On LOCAL) @@ -44,12 +44,24 @@ #define MAX_IGNORE_LIST 20 // official is 14 #define MAX_VENDING 12 #define MAX_MAP_SIZE 512*512 // Wasn't there something like this already? Can't find it.. [Shinryo] -#define MOBID_EMPERIUM 1288 + // Added definitions for WoESE objects. [L0ne_W0lf] -#define MOBID_BARRICADE1 1905 -#define MOBID_BARRICADE2 1906 -#define MOBID_GUARIDAN_STONE1 1907 -#define MOBID_GUARIDAN_STONE2 1908 +enum MOBID { + MOBID_EMPERIUM = 1288, + MOBID_TREAS01 = 1324, + MOBID_TREAS40 = 1363, + MOBID_BARRICADE1 = 1905, + MOBID_BARRICADE2, + MOBID_GUARIDAN_STONE1, + MOBID_GUARIDAN_STONE2, + MOBID_FOOD_STOR, + MOBID_BLUE_CRYST = 1914, + MOBID_PINK_CRYST, + MOBID_TREAS41 = 1938, + MOBID_TREAS49 = 1946, + MOBID_SILVERSNIPER = 2042, + MOBID_MAGICDECOY_WIND = 2046, +}; //The following system marks a different job ID system used by the map server, //which makes a lot more sense than the normal one. [Skotlex] @@ -706,7 +718,7 @@ #define mapit_geteachnpc() mapit_alloc(MAPIT_NORMAL,BL_NPC) #define mapit_geteachiddb() mapit_alloc(MAPIT_NORMAL,BL_ALL) -// ‚»‚Ì‘Œ +// ᅵᅵᅵ̑ᅵ int map_check_dir(int s_dir,int t_dir); unsigned char map_calc_dir( struct block_list *src,int x,int y); int map_random_dir(struct block_list *bl, short *x, short *y); // [Skotlex] Index: mob.c --- mob.c Base (BASE) +++ mob.c Locally Modified (Based On LOCAL) @@ -2740,7 +2740,7 @@ if (md->guardian_data) return 0; //Guardians/Emperium - if( (md->class_ >= 1324 && md->class_ <= 1363) || (md->class_ >= 1938 && md->class_ <= 1946) ) + if( mob_is_treasure(md) ) return 0; //Treasure Boxes if( md->special_state.ai > 1 ) @@ -2792,7 +2792,7 @@ } /*========================================== - * mob‰ñ•œ + * mobᅵᅵ *------------------------------------------*/ void mob_heal(struct mob_data *md,unsigned int heal) { @@ -3544,7 +3544,7 @@ } // -// ‰Šú‰» +// ᅵᅵᅵᅵ // /*========================================== * Since un-setting [ mob ] up was used, it is an initial provisional value setup. Index: mob.h --- mob.h Base (BASE) +++ mob.h Locally Modified (Based On LOCAL) @@ -268,7 +268,9 @@ #define mob_stop_walking(md, type) unit_stop_walking(&(md)->bl, type) #define mob_stop_attack(md) unit_stop_attack(&(md)->bl) -#define mob_is_battleground(md) ( map[(md)->bl.m].flag.battleground && ((md)->class_ == 1906 || ((md)->class_ >= 1909 && (md)->class_ <= 1915)) ) +#define mob_is_battleground(md) ( map[(md)->bl.m].flag.battleground && ((md)->class_ == MOBID_BARRICADE2 || ((md)->class_ >= MOBID_FOOD_STOR && (md)->class_ <= MOBID_PINK_CRYST)) ) +#define mob_is_gvg(md) (map[(md)->bl.m].flag.gvg_castle && ( (md)->class_ == MOBID_EMPERIUM || (md)->class_ == MOBID_BARRICADE1 || (md)->class_ == MOBID_GUARIDAN_STONE1 || (md)->class_ == MOBID_GUARIDAN_STONE2) ) +#define mob_is_treasure(md) (((md)->class_ >= MOBID_TREAS01 && (md)->class_ <= MOBID_TREAS40) || ((md)->class_ >= MOBID_TREAS41 && (md)->class_ <= MOBID_TREAS49)) void mob_clear_spawninfo(); int do_init_mob(void); Index: pc.c --- pc.c Base (BASE) +++ pc.c Locally Modified (Based On LOCAL) @@ -4073,7 +4073,7 @@ case 12243: // Mercenary's Berserk Potion if( sd->md == NULL || sd->md->db == NULL ) return 0; - if( sd->md->sc.data[SC_BERSERK] ) + if (sd->md->sc.data[SC_BERSERK] || sd->md->sc.data[SC_SATURDAYNIGHTFEVER] || sd->md->sc.data[SC__BLOODYLUST]) return 0; if( nameid == 12242 && sd->md->db->lv < 40 ) return 0; @@ -4173,7 +4173,7 @@ return 0; if( sd->sc.count && ( - sd->sc.data[SC_BERSERK] || + sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) || sd->sc.data[SC_TRICKDEAD] || sd->sc.data[SC_HIDING] || @@ -4490,9 +4490,7 @@ sd_status= status_get_status_data(&sd->bl); md_status= status_get_status_data(bl); - if( md->master_id || md_status->mode&MD_BOSS || - (md->class_ >= 1324 && md->class_ < 1364) || // Treasure Boxes WoE - (md->class_ >= 1938 && md->class_ < 1946) || // Treasure Boxes WoE SE + if( md->master_id || md_status->mode&MD_BOSS || mob_is_treasure(md) || map[bl->m].flag.nomobloot || // check noloot map flag [Lorky] (battle_config.skill_steal_max_tries && //Reached limit of steal attempts. [Lupus] md->state.steal_flag++ >= battle_config.skill_steal_max_tries) @@ -4566,7 +4564,7 @@ if( md->state.steal_coin_flag || md->sc.data[SC_STONE] || md->sc.data[SC_FREEZE] || md->status.mode&MD_BOSS ) return 0; - if( (md->class_ >= 1324 && md->class_ < 1364) || (md->class_ >= 1938 && md->class_ < 1946) ) + if( mob_is_treasure(md) ) return 0; // FIXME: This formula is either custom or outdated. @@ -8176,7 +8174,7 @@ return 0; } - if( sd->sc.data[SC_BERSERK] ) + if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || sd->sc.data[SC__BLOODYLUST]) { clif_equipitemack(sd,n,0,0); // fail return 0; @@ -8363,7 +8361,7 @@ } // if player is berserk then cannot unequip - if( !(flag&2) && sd->sc.count && sd->sc.data[SC_BERSERK] ) + if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || sd->sc.data[SC__BLOODYLUST])) { clif_unequipitemack(sd,n,0,0); return 0; Index: pc.h --- pc.h Base (BASE) +++ pc.h Locally Modified (Based On LOCAL) @@ -215,6 +215,7 @@ 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] + unsigned int bloodylust_tick; // bloodylust player timer [out/in re full-heal protection] struct { short nameid; Index: skill.c --- skill.c Base (BASE) +++ skill.c Locally Modified (Based On LOCAL) @@ -589,8 +589,11 @@ return 1; } break; - case WM_LULLABY_DEEPSLEEP: + case WM_SIRCLEOFNATURE: + case WM_SOUND_OF_DESTRUCTION: + case SC_MANHOLE: + case WM_LULLABY_DEEPSLEEP: case WM_SATURDAY_NIGHT_FEVER: if( !map_flag_vs(m) ) { clif_skill_teleportmessage(sd,2); // This skill uses this msg instead of skill fails. @@ -2826,6 +2829,7 @@ case RA_FIRINGTRAP: case RA_ICEBOUNDTRAP: case SC_DIMENSIONDOOR: + case SC_BLOODYLUST: //Non stackable on themselves and traps (including venom dust which does not has the trap inf2 set) if (skillid != g_skillid && !(skill_get_inf2(g_skillid)&INF2_TRAP) && g_skillid != AS_VENOMDUST && g_skillid != MH_POISON_MIST) return 0; @@ -4720,8 +4724,8 @@ bl = src; dstsd = sd; } - } else - if (tsc->data[SC_BERSERK]) + } + else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAYNIGHTFEVER] || tsc->data[SC__BLOODYLUST]) heal = 0; //Needed so that it actually displays 0 when healing. } clif_skill_nodamage (src, bl, skillid, heal, 1); @@ -6321,7 +6325,7 @@ continue; break; } - if(i==SC_BERSERK) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. + if(i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. status_change_end(bl, (sc_type)i, INVALID_TIMER); } break; @@ -7552,13 +7556,13 @@ { i = skill_calc_heal(src, bl, AL_HEAL, pc_checkskill(sd, AL_HEAL), true); - if( (dstsd && pc_ismadogear(dstsd)) || status_isimmune(bl) || (tsc && tsc->data[SC_BERSERK])) + if( (dstsd && pc_ismadogear(dstsd)) || status_isimmune(bl)) i = 0; // Should heal by 0 or won't do anything?? in iRO it breaks the healing to members.. [malufett] clif_skill_nodamage(bl, bl, skillid, i, 1); if( tsc && tsc->data[SC_AKAITSUKI] && i ) i = ~i + 1; - status_heal(bl, i, 0, 1); + status_heal(bl, i, 0, 0); } } else if( sd ) @@ -7675,7 +7679,7 @@ continue; break; } - if(i==SC_BERSERK /*|| i==SC_SATURDAYNIGHTFEVER*/) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. + if(i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. status_change_end(bl,(sc_type)i,INVALID_TIMER); } break; @@ -7941,7 +7945,7 @@ { if( bl->type != BL_MOB ) break; md = map_id2md(bl->id); - if( md && md->class_ >= 2042 && md->class_ <= 2046 ) + if( md && md->class_ >= MOBID_SILVERSNIPER && md->class_ <= MOBID_MAGICDECOY_WIND ) status_kill(bl); clif_skill_nodamage(src, bl, skillid, skilllv, 1); } @@ -9512,7 +9516,6 @@ case SC_MANHOLE: case SC_DIMENSIONDOOR: case SC_CHAOSPANIC: - case SC_BLOODYLUST: case SC_MAELSTROM: case WM_REVERBERATION: case WM_SEVERE_RAINSTORM: @@ -9991,6 +9994,10 @@ sc_start2(src, type, 100, skillid, skilllv, skill_get_time(skillid, skilllv))); break; + case SC_BLOODYLUST: //set in another group so instance will move if recasted + flag |= 33; + skill_unitsetting(src, skillid, skilllv, x, y, 0); + break; default: if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) { if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd ) @@ -10046,7 +10053,7 @@ sd->sc.data[SC_AUTOCOUNTER] || sd->sc.data[SC_STEELBODY] || (sd->sc.data[SC_DANCING] && skill_num < RK_ENCHANTBLADE && !pc_checkskill(sd, WM_LESSON)) || - sd->sc.data[SC_BERSERK] || + sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_BASILICA] || sd->sc.data[SC_MARIONETTE] || sd->sc.data[SC_WHITEIMPRISON] || @@ -10575,7 +10582,10 @@ break; case SO_VACUUM_EXTREME: range++; + break; + case SC_BLOODYLUST: + skill_clear_group(src, 32); case GN_WALLOFTHORN: if( flag&1 ) limit = 3000; @@ -10813,6 +10823,19 @@ if (!sce) sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); break; + case UNT_BLOODYLUST: + if (sg->src_id == bl->id) + break; //Does not affect the caster. + if (!sce) { + TBL_PC *sd = BL_CAST(BL_PC, bl); + if (sd && sd->bloodylust_tick && DIFF_TICK(gettick(), sd->bloodylust_tick) < skill_get_time2(SC_BLOODYLUST, 1)) + sc_start4(bl, type, 100, sg->skill_lv, 1, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv)); //do not refull heal + else { + if (sd) sd->bloodylust_tick = gettick(); + sc_start4(bl, type, 100, sg->skill_lv, 0, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv)); + } + } + break; case UNT_WARP_WAITING: { int working = sg->val1&0xffff; @@ -11569,7 +11592,7 @@ case UNT_EARTH_INSIGNIA: case UNT_ZEPHYR: sc_start(bl,type, 100, sg->skill_lv, sg->interval); - if (!battle_check_undead(tstatus->race, tstatus->def_ele)) { + if (sg->unit_id != UNT_ZEPHYR && !battle_check_undead(tstatus->race, tstatus->def_ele)) { int hp = tstatus->max_hp / 100; //+1% each 5s if ((sg->val3) % 5) { //each 5s if (tstatus->def_ele == skill_get_ele(sg->skill_id,sg->skill_lv)){ @@ -11582,10 +11605,9 @@ status_heal(bl, -hp, 0, 0); } } - } sg->val3++; //timer - if (sg->val3 > 5) - sg->val3 = 0; + if (sg->val3 > 5) sg->val3 = 0; + } break; case UNT_VACUUM_EXTREME: @@ -11763,7 +11785,6 @@ case HW_GRAVITATION: case NJ_SUITON: case SC_MAELSTROM: - case SC_BLOODYLUST: case EL_WATER_BARRIER: case EL_ZEPHYR: case EL_POWER_OF_GAIA: @@ -11774,6 +11795,12 @@ if (sce) status_change_end(bl, type, INVALID_TIMER); break; + case SC_BLOODYLUST: + if (sce) { + status_change_end(bl, type, INVALID_TIMER); + status_set_sp(bl, 0, 0); //set sp to 0 when quitting zone + } + break; case BA_POEMBRAGI: case BA_WHISTLE: @@ -14217,6 +14244,10 @@ if( flag&8 ) group[count++]= ud->skillunit[i]; break; + case SC_BLOODYLUST: + if (flag & 32) + group[count++] = ud->skillunit[i]; + break; default: if (flag&2 && skill_get_inf2(ud->skillunit[i]->skill_id)&INF2_TRAP) group[count++]= ud->skillunit[i]; @@ -14248,6 +14279,7 @@ case NJ_SUITON: case SO_WARMER: case SO_CLOUD_KILL: + case SC_BLOODYLUST: return ud->skillunit[i]; } } Index: status.c --- status.c Base (BASE) +++ status.c Locally Modified (Based On LOCAL) @@ -624,7 +624,7 @@ set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSORY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK ); set_sc_with_vfx( SC_MANHOLE , SC__MANHOLE , SI_MANHOLE , SCB_NONE ); add_sc( SC_CHAOSPANIC , SC_CONFUSION ); - set_sc( SC_BLOODYLUST , SC__BLOODYLUST , SI_BLOODYLUST , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); + set_sc( SC_BLOODYLUST , SC__BLOODYLUST , SI_BLOODYLUST , SCB_DEF | SCB_DEF2 | SCB_MDEF | SCB_MDEF2 | SCB_FLEE | SCB_SPEED | SCB_ASPD | SCB_MAXHP | SCB_REGEN ); /** * Sura **/ @@ -1022,6 +1022,7 @@ StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST; StatusChangeStateTable[SC_STEELBODY] |= SCS_NOCAST; StatusChangeStateTable[SC_BERSERK] |= SCS_NOCAST; + StatusChangeStateTable[SC__BLOODYLUST] |= SCS_NOCAST; StatusChangeStateTable[SC_OBLIVIONCURSE] |= SCS_NOCAST; StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOCAST; StatusChangeStateTable[SC__INVISIBILITY] |= SCS_NOCAST; @@ -1214,6 +1215,8 @@ status_change_end(target, SC_RAISINGDRAGON, INVALID_TIMER); if (sc->data[SC_SATURDAYNIGHTFEVER] && status->hp <= 100) status_change_end(target, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); + if (sc->data[SC__BLOODYLUST] && status->hp <= 100) + status_change_end(target, SC__BLOODYLUST, INVALID_TIMER); } switch (target->type) { @@ -1343,7 +1346,7 @@ } if(hp) { - if( sc && sc->data[SC_BERSERK] ) { + if( sc && (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) ) { if( flag&1 ) flag &= ~2; else @@ -2280,7 +2283,7 @@ b_max_weight = sd->max_weight; b_cart_weight_max = sd->cart_weight_max; - pc_calc_skilltree(sd); // ï¿œXï¿œLᅵᅵᅵcᅵᅵ?ᅵ̌vï¿œZ + pc_calc_skilltree(sd); // SkillTree calculation sd->max_weight = max_weight_base[pc_class2idx(sd->status.class_)]+sd->status.str*300; @@ -3389,7 +3392,7 @@ if ( (sc->data[SC_POISON] && !sc->data[SC_SLOWPOISON]) || (sc->data[SC_DPOISON] && !sc->data[SC_SLOWPOISON]) - || sc->data[SC_BERSERK] + || sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST] || sc->data[SC_TRICKDEAD] || sc->data[SC_BLEEDING] || sc->data[SC_MAGICMUSHROOM] @@ -4382,8 +4385,6 @@ batk += 100; if(sc->data[SC__ENERVATION]) batk -= batk * sc->data[SC__ENERVATION]->val2 / 100; - if(sc->data[SC__BLOODYLUST]) - batk += batk * 32 / 100; if(sc->data[SC_RUSHWINDMILL]) batk += batk * sc->data[SC_RUSHWINDMILL]->val2/100; if(sc->data[SC_SATURDAYNIGHTFEVER]) @@ -4447,8 +4448,6 @@ } if(sc->data[SC__ENERVATION]) watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; - if(sc->data[SC__BLOODYLUST]) - watk += watk * 32 / 100; if(sc->data[SC_FLEET]) watk += watk * sc->data[SC_FLEET]->val3/100; if(sc->data[SC_CURSE]) @@ -4461,8 +4460,6 @@ watk += sc->data[SC_FIGHTINGSPIRIT]->val1; if(sc->data[SC__ENERVATION]) watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; - if(sc->data[SC__BLOODYLUST]) - watk += watk * 32 / 100; if(sc->data[SC_STRIKING]) watk += sc->data[SC_STRIKING]->val2; if(sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3) @@ -4634,7 +4631,7 @@ flee += 10; if(sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) flee -= flee * 50/100; - if(sc->data[SC_BERSERK]) + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) flee -= flee * 50/100; if(sc->data[SC_BLIND]) flee -= flee * 25/100; @@ -4701,7 +4698,7 @@ if(!sc || !sc->count) return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX); - if(sc->data[SC_BERSERK]) + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) return 0; if(sc->data[SC_SKA]) return sc->data[SC_SKA]->val3; @@ -4750,8 +4747,6 @@ def -= def * ( 6 + 6 * sc->data[SC_MARSHOFABYSS]->val3/10 + (bl->type == BL_MOB ? 5 : 3) * sc->data[SC_MARSHOFABYSS]->val2/36 ) / 100; if( sc->data[SC_ANALYZE] ) def -= def * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; - if( sc->data[SC__BLOODYLUST] ) - def -= def * 55 / 100; if( sc->data[SC_FORCEOFVANGUARD] ) def += def * 2 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100; if(sc->data[SC_SATURDAYNIGHTFEVER]) @@ -4783,7 +4778,7 @@ return (short)cap_value(def2,1,SHRT_MAX); #endif - if(sc->data[SC_BERSERK]) + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) return 0; if(sc->data[SC_ETERNALCHAOS]) return 0; @@ -4841,7 +4836,7 @@ if(!sc || !sc->count) return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); - if(sc->data[SC_BERSERK]) + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) return 0; if(sc->data[SC_BARRIER]) return 100; @@ -4895,7 +4890,7 @@ #endif - if(sc->data[SC_BERSERK]) + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) return 0; if(sc->data[SC_SKA]) return 90; @@ -5041,7 +5036,7 @@ val = max( val, 1 * pc_checkskill(sd,TF_MISS) ); if( sc->data[SC_CLOAKING] && (sc->data[SC_CLOAKING]->val4&1) == 1 ) val = max( val, sc->data[SC_CLOAKING]->val1 >= 10 ? 25 : 3 * sc->data[SC_CLOAKING]->val1 - 3 ); - if( sc->data[SC_BERSERK] ) + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) val = max( val, 25 ); if( sc->data[SC_RUN] ) val = max( val, 55 ); @@ -5156,7 +5151,7 @@ } } - if(sc->data[SC_BERSERK] && skills1 < 15) + if((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) && skills1 < 15) skills1 = 15; else if(sc->data[SC_MADNESSCANCEL] && skills1 < 15) // needs more info skills1 = 15; @@ -5286,7 +5281,7 @@ } aspd_rate -= max; - if(sc->data[SC_BERSERK]) + if((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])) aspd_rate -= 300; else if(sc->data[SC_MADNESSCANCEL]) aspd_rate -= 200; @@ -5384,7 +5379,7 @@ maxhp += maxhp * sc->data[SC_APPLEIDUN]->val2/100; if(sc->data[SC_DELUGE]) maxhp += maxhp * sc->data[SC_DELUGE]->val2/100; - if(sc->data[SC_BERSERK]) + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) maxhp += maxhp * 2; if(sc->data[SC_MARIONETTE]) maxhp -= 1000; @@ -5553,8 +5548,10 @@ } /*========================================== - * ᅵΏۂᅵClassᅵᅵԂᅵ(ᅵėp) - * ᅵ߂ᅵ͐ᅵᅵᅵᅵᅵ0ᅵȏᅵ + * Get the class of the current bl + * return + * 0 = fail + * class_id = success *------------------------------------------*/ int status_get_class(struct block_list *bl) { nullpo_ret(bl); @@ -5570,8 +5567,10 @@ return 0; } /*========================================== - * ᅵΏۂ̃ᅵᅵxᅵᅵᅵᅵԂᅵ(ᅵėp) - * ᅵ߂ᅵ͐ᅵᅵᅵᅵᅵ0ᅵȏᅵ + * Get the base level of the current bl + * return + * 1 = fail + * level = success *------------------------------------------*/ int status_get_lv(struct block_list *bl) { nullpo_ret(bl); @@ -6019,6 +6018,7 @@ case SC__LAZINESS: case SC__UNLUCKY: case SC__WEAKNESS: + case SC__BLOODYLUST: return 0; } @@ -6236,11 +6236,13 @@ if( status_isdead(bl) && type != SC_NOCHAT ) // SC_NOCHAT should work even on dead characters return 0; - if( bl->type == BL_MOB && type != SC_SAFETYWALL && type != SC_PNEUMA ) + if( bl->type == BL_MOB) { struct mob_data *md = BL_CAST(BL_MOB,bl); - if( md->class_ == MOBID_EMPERIUM || mob_is_battleground(md) ) + if(md && (md->class_ == MOBID_EMPERIUM || mob_is_battleground(md)) && type != SC_SAFETYWALL && type != SC_PNEUMA) return 0; //Emperium/BG Monsters can't be afflicted by status changes + // if(md && mob_is_gvg(md) && status_sc2scb_flag(type)&SCB_MAXHP) + // return 0; //prevent status addinh hp to gvg mob (like bloodylust=hp*3 etc... } if( sc->data[SC_REFRESH] ) { @@ -6321,6 +6323,16 @@ 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__BLOODYLUST: + if(!sd) return 0; //should only affect player + case SC_BERSERK: + if (((type == SC_BERSERK) && (sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC__BLOODYLUST])) + || ((type == SC__BLOODYLUST) && (sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC_BERSERK])) + ) + return 0; + break; + case SC_BURNING: if(sc->opt1 || sc->data[SC_FREEZING]) return 0; @@ -6569,6 +6581,10 @@ if(sc->data[i]) return 0; } break; + case SC_SATURDAYNIGHTFEVER: + if (sc->data[SC_BERSERK] || sc->data[SC_INSPIRATION] || sc->data[SC__BLOODYLUST]) + return 0; + break; case SC_INTRAVISION: if(sd && sd->special_state.intravision) return 0; //we already have the status by maya P break; @@ -6671,6 +6687,7 @@ status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER); status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); break; + case SC__BLOODYLUST: case SC_BERSERK: if(battle_config.berserk_cancels_buffs) { status_change_end(bl, SC_ONEHAND, INVALID_TIMER); @@ -6789,7 +6806,7 @@ case SC_BEYONDOFWARCRY: case SC_UNLIMITEDHUMMINGVOICE: if( sc->data[type] ) // Don't remove same sc. - break; + break; //FIXME this is wrong as it'll prevent other being remove as well status_change_end(bl, SC_SONGOFMANA, INVALID_TIMER); status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); @@ -6916,7 +6933,7 @@ val4 = sce->val4; break; case SC_LERADSDEW: - if( sc && sc->data[SC_BERSERK] ) + if (sc && (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])) return 0; case SC_SHAPESHIFT: case SC_PROPERTYWALK: @@ -7177,8 +7194,7 @@ val3 = tick/1000; //Petrified HP-damage iterations. if(val3 < 1) val3 = 1; tick = val4; //Petrifying time. - if (tick < 1000) - tick = 1000; //Min time + tick = max(tick, 1000); //Min time calc_flag = 0; //Actual status changes take effect on petrified state. break; @@ -7196,7 +7212,7 @@ status_zap(bl, diff, 0); } // fall through - case SC_POISON: /* ᅵᅵ */ + case SC_POISON: val3 = tick/1000; //Damage iterations if(val3 < 1) val3 = 1; tick_time = 1000; // [GodLesZ] tick time @@ -7269,7 +7285,7 @@ else val4 |= battle_config.monster_cloak_check_type&7; break; - case SC_SIGHT: /* ï¿œTï¿œCï¿œg/ᅵᅵᅵAï¿œt */ + case SC_SIGHT: /* splash status */ case SC_RUWACH: case SC_SIGHTBLASTER: val3 = skill_get_splash(val2, val1); //Val2 should bring the skill-id. @@ -7364,6 +7380,7 @@ sc_start(bl,SC_BLEEDING,100,val1,skill_get_time2(status_sc2skill(type),val1)); break; + case SC__BLOODYLUST: case SC_BERSERK: if (!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4) sc_start4(bl, SC_ENDURE, 100,10,0,0,2, tick); @@ -7991,8 +8008,6 @@ sc_start(bl,SC_STRIPWEAPON,100,val1,tick); sc_start(bl,SC_STRIPSHIELD,100,val1,tick); break; - case SC__BLOODYLUST: - val_flag |= 1|2; break; case SC_GN_CARTBOOST: if( val1 < 3 ) @@ -8179,9 +8194,9 @@ case SC_GT_CHANGE: {// take note there is no def increase as skill desc says. [malufett] struct block_list * src; - val3 = status->agi * val1 / 60; // ASPD increase: [(Targetï¿œs AGI x Skill Level) / 60] % + val3 = status->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ï¿œs INT) x Skill Level] + val4 = ( 200/status_get_int(src) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] } break; case SC_GT_REVITALIZE: @@ -8189,7 +8204,7 @@ 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ï¿œs VIT / 4) x Skill Level] + val4 = ( status_get_vit(src)/4 ) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level] } break; case SC_PYROTECHNIC_OPTION: @@ -8460,6 +8475,7 @@ sc->opt3 |= OPT3_AURABLADE; opt_flag = 0; break; + case SC__BLOODYLUST: case SC_BERSERK: sc->opt3 |= OPT3_BERSERK; opt_flag = 0; @@ -8596,12 +8612,14 @@ if(sd && sd->pd) pet_sc_check(sd, type); //Skotlex: Pet Status Effect Healing - switch( type ) - { + switch (type) { + case SC__BLOODYLUST: case SC_BERSERK: - sce->val2 = 5*status->max_hp/100; + if (!(sce->val2)) { //don't heal if already set status_heal(bl, status->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 * status->max_hp / 100; break; case SC_CHANGE: status_percent_heal(bl, 100, 100); @@ -8678,12 +8696,14 @@ return 1; } + /*========================================== - * ï¿œXï¿œeï¿œ[ï¿œ^ï¿œXᅵُᅵSᅵᅵᅵᅵ + * Ending all status except those listed. + * @TODO maybe usefull for dispel instead reseting a liste there. * type: - * 0 - ??? - * 1 - ??? - * 2 - ??? + * 0 - PC killed -> Place here statuses that do not dispel on death. + * 1 - If for some reason status_change_end decides to still keep the status when quitting. + * 2 - Do clif *------------------------------------------*/ int status_change_clear(struct block_list* bl, int type) { @@ -8778,7 +8798,7 @@ } /*========================================== - * ï¿œXï¿œeï¿œ[ï¿œ^ï¿œXᅵُᅵIᅵᅵ + * Special condition we want to effectuate, check before ending a status. *------------------------------------------*/ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line) { @@ -9075,10 +9095,11 @@ } break; + case SC__BLOODYLUST: case SC_BERSERK: case SC_SATURDAYNIGHTFEVER: //If val2 is removed, no HP penalty (dispelled?) [Skotlex] - if(status->hp > 100 && sce->val2) + if (status->hp > 100 && sce->val2 && type != SC__BLOODYLUST) status_set_hp(bl, 100, 0); if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2) { @@ -9362,6 +9383,7 @@ sc->opt3 &= ~OPT3_AURABLADE; opt_flag = 0; break; + case SC__BLOODYLUST: case SC_BERSERK: sc->opt3 &= ~OPT3_BERSERK; opt_flag = 0; @@ -9475,7 +9497,8 @@ } /*========================================== - * ï¿œXï¿œeï¿œ[ï¿œ^ï¿œXᅵُᅵIᅵᅵᅵ^ï¿œCï¿œ}ï¿œ[ + * 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) { @@ -9681,7 +9704,7 @@ } break; - case SC_DANCING: //ï¿œ_ᅵᅵᅵXï¿œXï¿œLᅵᅵᅵ̎ᅵᅵᅵSPᅵᅵᅵᅵ + case SC_DANCING: //SP consumption by time of dancing skills { int s = 0; int sp = 1; @@ -9737,7 +9760,7 @@ return 0; } break; - + case SC__BLOODYLUST: case SC_BERSERK: // 5% every 10 seconds [DracoRPG] if( --( sce->val3 ) > 0 && status_charge(bl, sce->val2, 0) && status->hp > 100 ) @@ -9815,7 +9838,6 @@ break; case SC_ABUNDANCE: if(--(sce->val4) > 0) { - if( !sc->data[SC_BERSERK] ) status_heal(bl,0,60,0); sc_timer_next(10000+tick, status_change_timer, bl->id, data); } @@ -9864,7 +9886,7 @@ } if( !flag ) { // Random Skill Cast - if( sd ) { + if (sd && !pc_issit(sd)) { //can't cast if sit int mushroom_skillid = 0, i; unit_stop_attack(bl); unit_skillcastcancel(bl,1); @@ -9899,7 +9921,7 @@ { //Damage is every 10 seconds including 3%sp drain. map_freeblock_lock(); clif_damage(bl,bl,tick,status_get_amotion(bl),1,1,0,0,0); - status_damage(NULL,bl,1,status->max_sp*3/100,0,16); + status_damage(NULL, bl, 1, status->max_sp * 3 / 100, 0, 0); //cancel dmg only if cancelable if( sc->data[type] ) { sc_timer_next(10000 + tick, status_change_timer, bl->id, data ); } @@ -10293,7 +10315,7 @@ } /*========================================== - * ï¿œXï¿œeï¿œ[ï¿œ^ï¿œXᅵُᅵ^ï¿œCï¿œ}ï¿œ[ᅵ͈͏ᅵᅵᅵ + * Foreach iteration of repetitive status *------------------------------------------*/ int status_change_timer_sub(struct block_list* bl, va_list ap) { @@ -10310,7 +10332,7 @@ tsc = status_get_sc(bl); switch( type ) { - case SC_SIGHT: /* ï¿œTï¿œCï¿œg */ + case SC_SIGHT: /* Reveal hidden ennemy on 3*3 range */ if( tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] % status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); @@ -10321,7 +10343,7 @@ status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); break; - case SC_RUWACH: /* ᅵᅵᅵAï¿œt */ + case SC_RUWACH: /* Reveal hidden target and deal little dammages if ennemy */ if (tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || tsc->data[SC_CAMOUFLAGE] || tsc->data[SC_CLOAKINGEXCEED] || tsc->data[SC__INVISIBILITY])) { @@ -10465,6 +10487,7 @@ continue; break; //The rest are buffs that can be removed. + case SC__BLOODYLUST: case SC_BERSERK: case SC_SATURDAYNIGHTFEVER: if (!(type&1))