Poison React now activates when character is damaged only - Fixes bugreport:109

Cloaking fixed to official behaviour (Thanks helvetica for the hour of testing) - Concerning bugreport:171
Fixed instancing long map names causing crashes
- Cannot save or memo on instance maps (Lemongrass)
- Map channels are no longer activated on instance maps (Lemongrass)
- Fixed a character save issue with instance maps (Lemongrass)
- Map local channels are disabled by default, this is custom (Lemongrass)
- Just thank Lemongrass overall, I gave him a hard time with this issue

~ Hercules Merge ~
Update Bloody Lust and Maelstrom to official behaviour (Credits: malufett)

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@17408 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
akinari1087 2013-07-09 06:02:39 +00:00
parent 1ed6911a71
commit 81e3b03ace
17 changed files with 196 additions and 124 deletions

View File

@ -30,7 +30,7 @@ chsys: (
allow_user_channel_creation: true
/* "map_local_channel" is an instanced channel unique to each map. */
map_local_channel: true
map_local_channel: false
map_local_channel_name: "map"
map_local_channel_color: "Yellow"
map_local_channel_autojoin: true /* Disable autojoin in specific maps through mapflag 'nomapchannelautojoin'. */

View File

@ -399,7 +399,9 @@
380: Item Failed. [%s] is cooling down. Wait %d seconds.
381: Skill Failed. [%s] requires %dx %s.
382: You're too close to a stone or emperium to use this skill.
//383-389 free
383: You cannot create a savepoint in an instance.
384: You cannot create a memo in an instance.
//385-389 free
//NoAsk
390: Autorejecting is activated.
391: Autorejecting is deactivated.

View File

@ -874,7 +874,7 @@
2300,7,6,2,0,0x1,0,3,1,yes,0,0,1,none,0, SC_DIMENSIONDOOR,Dimension Door
2301,7,6,2,0,0x1,0,3,1,yes,0,0,0,none,0, SC_CHAOSPANIC,Chaos Panic
2302,7,6,2,0,0x1,0,3,1,yes,0,0,0,none,0, SC_MAELSTROM,Maelstrom
2303,7,6,2,0,0x1,0,3,1,yes,0,0,0,none,0, SC_BLOODYLUST,Bloody Lust
2303,7,6,2,0,0x1,3,3,1,yes,0,0,1,none,0, SC_BLOODYLUST,Bloody Lust
2304,0,6,4,-1,0,0,3,1,no,0,0,0,weapon,0, SC_FEINTBOMB,Feint Bomb
//****

View File

@ -729,6 +729,11 @@ ACMD_FUNC(save)
{
nullpo_retr(-1, sd);
if( map[sd->bl.m].instance_id ) {
clif_displaymessage(fd, msg_txt(sd,383)); // You cannot create a savepoint in an instance.
return 1;
}
pc_setsavepoint(sd, sd->mapindex, sd->bl.x, sd->bl.y);
if (sd->status.pet_id > 0 && sd->pd)
intif_save_petdata(sd->status.account_id, &sd->pd->pet);
@ -2221,8 +2226,7 @@ ACMD_FUNC(memo)
return -1;
}
pc_memo(sd, position);
return 0;
return !pc_memo( sd, position );
}
/*==========================================

View File

@ -745,6 +745,10 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
if( battle_config.ksprotection && mob_ksprotected(src, bl) )
return 0;
if( map_getcell(bl->m, bl->x, bl->y, CELL_CHKMAELSTROM) && skill_get_type(skill_id) != BF_MISC
&& skill_get_casttype(skill_id) == CAST_GROUND )
return 0;
if (bl->type == BL_PC) {
sd=(struct map_session_data *)bl;
//Special no damage states
@ -2739,7 +2743,7 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
skillratio += sc->data[SC_OVERTHRUST]->val3;
if(sc->data[SC_MAXOVERTHRUST])
skillratio += sc->data[SC_MAXOVERTHRUST]->val2;
if (sc->data[SC_BERSERK] || sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC__BLOODYLUST])
if (sc->data[SC_BERSERK] || sc->data[SC_SATURDAYNIGHTFEVER])
skillratio += 100;
if(sc->data[SC_ZENKAI] && sstatus->rhw.ele == sc->data[SC_ZENKAI]->val2 )
skillratio += sc->data[SC_ZENKAI]->val1 * 2;
@ -6008,7 +6012,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
}
if (tsc) {
if (tsc->data[SC_POISONREACT] &&
if (damage > 0 && tsc->data[SC_POISONREACT] &&
(rnd()%100 < tsc->data[SC_POISONREACT]->val3
|| sstatus->def_ele == ELE_POISON) &&
// check_distance_bl(src, target, tstatus->rhw.range+1) && Doesn't checks range! o.O;

View File

@ -304,7 +304,22 @@ int chrif_save(struct map_session_data *sd, int flag) {
WFIFOL(char_fd,4) = sd->status.account_id;
WFIFOL(char_fd,8) = sd->status.char_id;
WFIFOB(char_fd,12) = (flag==1)?1:0; //Flag to tell char-server this character is quitting.
memcpy(WFIFOP(char_fd,13), &sd->status, sizeof(sd->status));
// If the user is on a instance map, we have to fake his current position
if( map[sd->bl.m].instance_id ){
struct mmo_charstatus status;
// Copy the whole status
memcpy( &status, &sd->status, sizeof( struct mmo_charstatus ) );
// Change his current position to his savepoint
memcpy( &status.last_point, &status.save_point, sizeof( struct point ) );
// Copy the copied status into the packet
memcpy( WFIFOP( char_fd, 13 ), &status, sizeof( struct mmo_charstatus ) );
} else {
// Copy the whole status into the packet
memcpy( WFIFOP( char_fd, 13 ), &sd->status, sizeof( struct mmo_charstatus ) );
}
WFIFOSET(char_fd, WFIFOW(char_fd,2));
if( sd->status.pet_id > 0 && sd->pd )

View File

@ -1660,7 +1660,7 @@ void clif_quitsave(int fd,struct map_session_data *sd) {
/// Notifies the client of a position change to coordinates on given map (ZC_NPCACK_MAPMOVE).
/// 0091 <map name>.16B <x>.W <y>.W
void clif_changemap(struct map_session_data *sd, short map, int x, int y)
void clif_changemap(struct map_session_data *sd, short m, int x, int y)
{
int fd;
nullpo_retv(sd);
@ -1668,7 +1668,18 @@ void clif_changemap(struct map_session_data *sd, short map, int x, int y)
WFIFOHEAD(fd,packet_len(0x91));
WFIFOW(fd,0) = 0x91;
mapindex_getmapname_ext(mapindex_id2name(map), (char*)WFIFOP(fd,2));
if(map[m].instance_id) { // Instance map check to send client source map name so we don't crash player
struct instance_data *im = &instance_data[map[m].instance_id];
int i;
if(!im) // This shouldn't happen but if it does give them the map we intended to give
mapindex_getmapname_ext(map[m].name, (char*)WFIFOP(fd,2));
for(i = 0; i < MAX_MAP_PER_INSTANCE; i++) // Loop to find the src map we want
if(im->map[i].m == m) {
mapindex_getmapname_ext(map[im->map[i].src_m].name, (char*)WFIFOP(fd,2));
break;
}
} else
mapindex_getmapname_ext(map[m].name, (char*)WFIFOP(fd,2));
WFIFOW(fd,18) = x;
WFIFOW(fd,20) = y;
WFIFOSET(fd,packet_len(0x91));
@ -8286,7 +8297,7 @@ void clif_refresh(struct map_session_data *sd)
int i;
nullpo_retv(sd);
clif_changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y);
clif_changemap(sd,sd->bl.m,sd->bl.x,sd->bl.y);
clif_inventorylist(sd);
if(pc_iscarton(sd)) {
clif_cartlist(sd);
@ -9139,7 +9150,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if (sd->state.rewarp) { //Rewarp player.
sd->state.rewarp = 0;
clif_changemap(sd, sd->mapindex, sd->bl.x, sd->bl.y);
clif_changemap(sd, sd->bl.m, sd->bl.x, sd->bl.y);
return;
}
@ -9379,7 +9390,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
status_calc_pc(sd, false); // Some conditions are map-dependent so we must recalculate
sd->state.changemap = false;
if( Channel_Config.map_enable && Channel_Config.map_autojoin && !map[sd->bl.m].flag.chmautojoin) {
// Instances do not need their own channels
if( Channel_Config.map_enable && Channel_Config.map_autojoin && !map[sd->bl.m].flag.chmautojoin && !map[sd->bl.m].instance_id ) {
channel_mjoin(sd); //join new map
}
}
@ -9567,6 +9579,11 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
if(sd->sc.data[SC_RUN] || sd->sc.data[SC_WUGDASH])
return;
// Cloaking wall check is actually updated when you click to process next movement
// not when you move each cell. This is official behaviour.
if (sd->sc.data[SC_CLOAKING])
skill_check_cloaking(&sd->bl, sd->sc.data[SC_CLOAKING]);
pc_delinvincibletimer(sd);
RFIFOPOS(fd, packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0], &x, &y, NULL);

View File

@ -345,7 +345,7 @@ void clif_clearunit_delayed(struct block_list* bl, clr_type type, unsigned int t
int clif_spawn(struct block_list *bl); //area
void clif_walkok(struct map_session_data *sd); // self
void clif_move(struct unit_data *ud); //area
void clif_changemap(struct map_session_data *sd, short map, int x, int y); //self
void clif_changemap(struct map_session_data *sd, short m, int x, int y); //self
void clif_changemapserver(struct map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port); //self
void clif_blown(struct block_list *bl); // area
void clif_slide(struct block_list *bl, int x, int y); // area

View File

@ -369,7 +369,7 @@ int instance_mapname2mapid(const char *name, short instance_id)
{
struct instance_data *im;
int m = map_mapname2mapid(name);
char iname[12];
char iname[MAP_NAME_LENGTH];
int i;
if(m < 0) {
@ -377,6 +377,8 @@ int instance_mapname2mapid(const char *name, short instance_id)
return m;
}
strcpy(iname,name);
if(instance_id <= 0 || instance_id > MAX_INSTANCE_DATA)
return m;
@ -386,8 +388,13 @@ int instance_mapname2mapid(const char *name, short instance_id)
for(i = 0; i < MAX_MAP_PER_INSTANCE; i++)
if(im->map[i].src_m == m) {
snprintf(iname, sizeof(iname), ((strchr(name,'@') == NULL)?"%.3d#%s":"%.3d%s"), instance_id, name);
return mapindex_name2id(iname);
char alt_name[MAP_NAME_LENGTH];
if((strchr(iname,'@') == NULL) && strlen(iname) > 8) {
memmove(iname, iname+(strlen(iname)-9), strlen(iname));
snprintf(alt_name, sizeof(alt_name),"%d#%s", instance_id, iname);
} else
snprintf(alt_name, sizeof(alt_name),"%.3d%s", instance_id, iname);
return map_mapname2mapid(alt_name);
}
return m;
@ -515,7 +522,7 @@ int instance_enter(struct map_session_data *sd, const char *name)
if((m = instance_mapname2mapid(db->enter.mapname, p->instance_id)) < 0)
return 3;
if(pc_setpos(sd, m, db->enter.x, db->enter.y, 0))
if(pc_setpos(sd, map_id2index(m), db->enter.x, db->enter.y, 0))
return 3;
// If there was an idle timer, let's stop it

View File

@ -425,8 +425,6 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
if (sc->data[SC_DANCING])
skill_unit_move_unit_group(skill_id2group(sc->data[SC_DANCING]->val2), bl->m, x1-x0, y1-y0);
else {
if (sc->data[SC_CLOAKING])
skill_check_cloaking(bl, sc->data[SC_CLOAKING]);
if (sc->data[SC_WARM])
skill_unit_move_unit_group(skill_id2group(sc->data[SC_WARM]->val4), bl->m, x1-x0, y1-y0);
if (sc->data[SC_BANDING])
@ -2181,6 +2179,7 @@ int map_addinstancemap(const char *name, int id)
{
int src_m = map_mapname2mapid(name);
int dst_m = -1, i;
char iname[MAP_NAME_LENGTH];
size_t size;
if(src_m < 0)
@ -2209,8 +2208,16 @@ int map_addinstancemap(const char *name, int id)
// Copy the map
memcpy(&map[dst_m], &map[src_m], sizeof(struct map_data));
strcpy(iname,name);
// Alter the name
snprintf(map[dst_m].name, sizeof(map[dst_m].name), ((strchr(name,'@') == NULL)?"%.3d#%s":"%.3d%s"), id, name);
// Due to this being custom we only worry about preserving as many characters as necessary for accurate map distinguishing
// This also allows us to maintain complete independence with main map functions
if((strchr(iname,'@') == NULL) && strlen(iname) > 8) {
memmove(iname, iname+(strlen(iname)-9), strlen(iname));
snprintf(map[dst_m].name, sizeof(map[dst_m].name),"%d#%s", id, iname);
} else
snprintf(map[dst_m].name, sizeof(map[dst_m].name),"%.3d%s", id, iname);
map[dst_m].name[MAP_NAME_LENGTH-1] = '\0';
map[dst_m].m = dst_m;
@ -2225,6 +2232,7 @@ int map_addinstancemap(const char *name, int id)
map[dst_m].block_mob = (struct block_list **)aCalloc(1,size);
map[dst_m].index = mapindex_addmap(-1, map[dst_m].name);
map[dst_m].channel = NULL;
map_addmap2db(&map[dst_m]);

View File

@ -1091,7 +1091,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
/**
* Fixes login-without-aura glitch (the screen won't blink at this point, don't worry :P)
**/
clif_changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y);
clif_changemap(sd,sd->bl.m,sd->bl.x,sd->bl.y);
}
/**
@ -4211,7 +4211,7 @@ int pc_isUseitem(struct map_session_data *sd,int n)
case 12243: // Mercenary's Berserk Potion
if( sd->md == NULL || sd->md->db == NULL )
return 0;
if (sd->md->sc.data[SC_BERSERK] || sd->md->sc.data[SC_SATURDAYNIGHTFEVER] || sd->md->sc.data[SC__BLOODYLUST])
if (sd->md->sc.data[SC_BERSERK] || sd->md->sc.data[SC_SATURDAYNIGHTFEVER])
return 0;
if( nameid == 12242 && sd->md->db->lv < 40 )
return 0;
@ -4308,7 +4308,7 @@ int pc_useitem(struct map_session_data *sd,int n)
return 0;
if (sd->sc.count && (
sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_SATURDAYNIGHTFEVER] ||
sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] ||
(sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) ||
sd->sc.data[SC_TRICKDEAD] ||
sd->sc.data[SC_HIDING] ||
@ -4879,7 +4879,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
if(sd->bl.prev != NULL){
unit_remove_map_pc(sd,clrtype);
clif_changemap(sd,map[m].index,x,y); // [MouseJstr]
clif_changemap(sd,m,x,y); // [MouseJstr]
} else if(sd->state.active) //Tag player for rewarping after map-loading is done. [Skotlex]
sd->state.rewarp = 1;
@ -4992,6 +4992,11 @@ int pc_memo(struct map_session_data* sd, int pos)
pos = 0;
}
if( map[sd->bl.m].instance_id ) {
clif_displaymessage( sd->fd, msg_txt(sd,384) ); // You cannot create a memo in an instance.
return 0;
}
sd->status.memo_point[pos].map = map_id2index(sd->bl.m);
sd->status.memo_point[pos].x = sd->bl.x;
sd->status.memo_point[pos].y = sd->bl.y;
@ -8553,8 +8558,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
return 0;
}
if( DIFF_TICK(sd->canequip_tick,gettick()) > 0 )
{
if( DIFF_TICK(sd->canequip_tick,gettick()) > 0 ) {
clif_equipitemack(sd,n,0,0);
return 0;
}
@ -8570,8 +8574,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
return 0;
}
if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || sd->sc.data[SC__BLOODYLUST])
{
if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER]) {
clif_equipitemack(sd,n,0,0); // fail
return 0;
}
@ -8582,15 +8585,14 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
pos = sd->equip_index[EQI_ACC_R] >= 0 ? EQP_ACC_L : EQP_ACC_R;
}
if(pos == EQP_ARMS && id->equip == EQP_HAND_R)
{ //Dual wield capable weapon.
if(pos == EQP_ARMS && id->equip == EQP_HAND_R) { //Dual wield capable weapon.
pos = (req_pos&EQP_ARMS);
if (pos == EQP_ARMS) //User specified both slots, pick one for them.
pos = sd->equip_index[EQI_HAND_R] >= 0 ? EQP_HAND_L : EQP_HAND_R;
}
if (pos&EQP_HAND_R && battle_config.use_weapon_skill_range&BL_PC)
{ //Update skill-block range database when weapon range changes. [Skotlex]
if (pos&EQP_HAND_R && battle_config.use_weapon_skill_range&BL_PC) {
//Update skill-block range database when weapon range changes. [Skotlex]
i = sd->equip_index[EQI_HAND_R];
if (i < 0 || !sd->inventory_data[i]) //No data, or no weapon equipped
flag = 1;
@ -8607,7 +8609,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
}
}
if(pos==EQP_AMMO){
if(pos==EQP_AMMO) {
clif_arrowequip(sd,n);
clif_arrow_fail(sd,3);
}

View File

@ -250,7 +250,6 @@ struct map_session_data {
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;

View File

@ -16561,21 +16561,18 @@ BUILDIN_FUNC(instance_npcname)
BUILDIN_FUNC(instance_mapname)
{
const char *str;
char iname[12];
int16 m;
short instance_id = 0;
str = script_getstr(st,2);
if( script_hasdata(st,3) )
instance_id = script_getnum(st,3);
else
instance_id = script_instancegetid(st);
// Build the instance mapname
snprintf(iname, sizeof(iname), ((strchr(str,'@') == NULL)?"%.3d#%s":"%.3d%s"), instance_id, str);
// Check that instance mapname is a valid map
if( !instance_id || (m = map_mapname2mapid(iname)) < 0 )
if(!instance_id || (m = instance_mapname2mapid(str,instance_id)) < 0)
script_pushconststr(st, "");
else
script_pushconststr(st, map[m].name);
@ -16616,7 +16613,6 @@ BUILDIN_FUNC(instance_warpall)
short instance_id;
const char *mapn;
int x, y;
unsigned short mapindex;
mapn = script_getstr(st,2);
x = script_getnum(st,3);
@ -16632,9 +16628,8 @@ BUILDIN_FUNC(instance_warpall)
if( !(p = party_search(instance_data[instance_id].party_id)) )
return 0;
mapindex = map_id2index(m);
for( i = 0; i < MAX_PARTY; i++ )
if( (pl_sd = p->data[i].sd) && map[pl_sd->bl.m].instance_id == instance_id ) pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT);
if( (pl_sd = p->data[i].sd) && map[pl_sd->bl.m].instance_id == instance_id ) pc_setpos(pl_sd,map_id2index(m),x,y,CLR_TELEPORT);
return 0;
}

View File

@ -5028,7 +5028,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
dstsd = sd;
}
}
else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAYNIGHTFEVER] || tsc->data[SC__BLOODYLUST])
else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAYNIGHTFEVER])
heal = 0; //Needed so that it actually displays 0 when healing.
}
clif_skill_nodamage (src, bl, skill_id, heal, 1);
@ -10081,6 +10081,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case SC_DIMENSIONDOOR:
case SC_CHAOSPANIC:
case SC_MAELSTROM:
case SC_BLOODYLUST:
case WM_REVERBERATION:
case WM_SEVERE_RAINSTORM:
case WM_POEMOFNETHERWORLD:
@ -10565,11 +10566,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
sc_start2(src,src, type, 100, skill_id, skill_lv, skill_get_time(skill_id, skill_lv)));
break;
case SC_BLOODYLUST: //set in another group so instance will move if recasted
flag |= 33;
skill_unitsetting(src, skill_id, skill_lv, x, y, 0);
break;
case KO_MAKIBISHI:
for( i = 0; i < (skill_lv+2); i++ ) {
x = src->x - 1 + rnd()%3;
@ -10629,7 +10625,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
sd->sc.data[SC_AUTOCOUNTER] ||
sd->sc.data[SC_STEELBODY] ||
(sd->sc.data[SC_DANCING] && skill_id < RK_ENCHANTBLADE && !pc_checkskill(sd, WM_LESSON)) ||
sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] ||
sd->sc.data[SC_BERSERK] ||
sd->sc.data[SC_BASILICA] ||
sd->sc.data[SC_MARIONETTE] ||
sd->sc.data[SC_WHITEIMPRISON] ||
@ -11163,9 +11159,6 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
case SO_VACUUM_EXTREME:
range++;
break;
case SC_BLOODYLUST:
skill_clear_group(src, 32);
break;
case GN_WALLOFTHORN:
if( flag&1 )
@ -11299,6 +11292,9 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
if (unit_flag&UF_RANGEDSINGLEUNIT && i == (layout->count / 2))
val2 |= UF_RANGEDSINGLEUNIT; // center.
if( sd && map_getcell(src->m, ux, uy, CELL_CHKMAELSTROM) ) //Does not recover SP from monster skills
map_foreachincell(skill_maelstrom_suction,src->m,ux,uy,BL_SKILL,skill_id,skill_lv);
if( range <= 0 )
map_foreachincell(skill_cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src);
if( !alive )
@ -11360,7 +11356,8 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
nullpo_ret(sg=src->group);
nullpo_ret(ss=map_id2bl(sg->src_id));
if( skill_get_type(sg->skill_id) == BF_MAGIC && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR )
if( (skill_get_type(sg->skill_id) == BF_MAGIC && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR) ||
map_getcell(bl->m, bl->x, bl->y, CELL_CHKMAELSTROM) )
return 0; //AoE skills are ineffective. [Skotlex]
if( skill_get_inf2(sg->skill_id)&(INF2_SONG_DANCE|INF2_ENSEMBLE_SKILL) && map_getcell(bl->m, bl->x, bl->y, CELL_CHKBASILICA) )
@ -11400,26 +11397,17 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
sc_start4(ss, bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit);
break;
case UNT_PNEUMA:
case UNT_CHAOSPANIC:
case UNT_MAELSTROM:
if (!sce)
sc_start4(ss, 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); //prevent fullheal exploit
if (sd && sd->bloodylust_tick && DIFF_TICK(gettick(), sd->bloodylust_tick) < skill_get_time2(SC_BLOODYLUST, 1))
clif_skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv,
sc_start4(ss, bl, type, 100, sg->skill_lv, 1, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv)));
else {
if (sd) sd->bloodylust_tick = gettick();
clif_skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv,
sc_start4(ss, bl, type, 100, sg->skill_lv, 0, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv)));
}
}
if( !sce && sc_start4(ss, bl,type,100,sg->skill_lv,0,SC__BLOODYLUST,0,sg->limit) )
sc_start(ss, bl,SC__BLOODYLUST,100,sg->skill_lv,sg->limit);
break;
case UNT_PNEUMA:
case UNT_CHAOSPANIC:
if (!sce)
sc_start4(ss, bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit);
break;
case UNT_WARP_WAITING: {
@ -12413,15 +12401,10 @@ int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned int tick
case SO_WATER_INSIGNIA:
case SO_WIND_INSIGNIA:
case SO_EARTH_INSIGNIA:
case SC_BLOODYLUST:
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_DISSONANCE:
case DC_UGLYDANCE: //Used for updating song timers in overlap instances
{
@ -12908,6 +12891,22 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
break;
case AS_CLOAKING:
{
static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1};
static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1};
if( (sd->bl.type == BL_PC && battle_config.pc_cloak_check_type&1)
|| (sd->bl.type != BL_PC && battle_config.monster_cloak_check_type&1) ) { //Check for walls.
int i;
ARR_FIND( 0, 8, i, map_getcell(sd->bl.m, sd->bl.x+dx[i], sd->bl.y+dy[i], CELL_CHKNOPASS) != 0 );
if( i == 8 ) {
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
}
break;
}
case AL_WARP:
if(!battle_config.duel_allow_teleport && sd->duel_group) { // duel restriction [LuzZza]
char output[128]; sprintf(output, msg_txt(sd,365), skill_get_name(AL_WARP));
@ -15002,10 +15001,6 @@ int skill_clear_group (struct block_list *bl, int flag)
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];
@ -15036,7 +15031,6 @@ struct skill_unit_group *skill_locate_element_field(struct block_list *bl)
case SA_LANDPROTECTOR:
case NJ_SUITON:
case SO_WARMER:
case SC_BLOODYLUST:
return ud->skillunit[i];
}
}
@ -15317,6 +15311,34 @@ static int skill_trap_splash (struct block_list *bl, va_list ap)
return 1;
}
int skill_maelstrom_suction(struct block_list *bl, va_list ap)
{
uint16 skill_id, skill_lv;
struct skill_unit *unit;
skill_id = va_arg(ap,int);
skill_lv = va_arg(ap,int);
unit = (struct skill_unit *)bl;
if( unit == NULL || unit->group == NULL )
return 0;
if( skill_get_inf2(skill_id)&INF2_TRAP )
return 0;
if( unit->group->skill_id == SC_MAELSTROM ){
struct block_list *src;
if( (src = map_id2bl(unit->group->src_id)) ){
int sp = unit->group->skill_lv * skill_lv;
if( src->type == BL_PC )
sp += ((TBL_PC*)src)->status.job_level / 5;
status_heal(src, 0, sp/2, 1);
}
}
return 0;
}
/*==========================================
*
*------------------------------------------*/
@ -15405,6 +15427,9 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
nullpo_retr(NULL, group->unit); // crash-protection against poor coding
nullpo_retr(NULL, unit=&group->unit[idx]);
if( map_getcell(map_id2bl(group->src_id)->m, x, y, CELL_CHKMAELSTROM) )
return unit;
if(!unit->alive)
group->alive_count++;

View File

@ -1865,6 +1865,7 @@ struct s_skill_magicmushroom_db {
uint16 skill_id;
};
extern struct s_skill_magicmushroom_db skill_magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB];
int skill_maelstrom_suction(struct block_list *bl, va_list ap);
/**
* Ranger
**/

View File

@ -496,10 +496,10 @@ void initChangeTables(void) {
set_sc(MH_PAIN_KILLER , SC_PAIN_KILLER , SI_PAIN_KILLER , SCB_ASPD );
add_sc(MH_STYLE_CHANGE , SC_STYLE_CHANGE );
set_sc(MH_TINDER_BREAKER , SC_TINDER_BREAKER2 , SI_TINDER_BREAKER, SCB_FLEE );
set_sc(MH_TINDER_BREAKER , SC_TINDER_BREAKER , SI_TINDER_BREAKER_POSTDELAY, SCB_FLEE );
set_sc(MH_CBC , SC_CBC, SI_CBC , SCB_FLEE );
set_sc(MH_EQC , SC_EQC, SI_EQC , SCB_DEF2|SCB_BATK|SCB_MAXHP );
set_sc(MH_TINDER_BREAKER , SC_TINDER_BREAKER2 , SI_TINDER_BREAKER , SCB_FLEE );
set_sc(MH_TINDER_BREAKER , SC_TINDER_BREAKER , SI_TINDER_BREAKER_POSTDELAY , SCB_FLEE );
set_sc(MH_CBC , SC_CBC , SI_CBC , SCB_FLEE );
set_sc(MH_EQC , SC_EQC , SI_EQC , SCB_DEF2|SCB_BATK|SCB_MAXHP );
add_sc( MER_CRASH , SC_STUN );
set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
@ -635,7 +635,7 @@ void initChangeTables(void) {
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_with_vfx( SC_BLOODYLUST , SC__BLOODYLUST , SI_BERSERK , SCB_DEF | SCB_DEF2 | SCB_MDEF | SCB_MDEF2 | SCB_FLEE | SCB_SPEED | SCB_ASPD | SCB_MAXHP | SCB_REGEN );
add_sc( SC_BLOODYLUST , SC_BERSERK );
/**
* Sura
**/
@ -1048,7 +1048,6 @@ void initChangeTables(void) {
StatusChangeStateTable[SC_BERSERK] |= SCS_NOCHAT;
StatusChangeStateTable[SC_SATURDAYNIGHTFEVER] |= SCS_NOCHAT;
StatusChangeStateTable[SC_DEEPSLEEP] |= SCS_NOCHAT;
StatusChangeStateTable[SC__BLOODYLUST] |= SCS_NOCHAT;
StatusChangeStateTable[SC_NOCHAT] |= SCS_NOCHAT|SCS_NOCHATCOND;
}
@ -1233,8 +1232,6 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
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) {
@ -1367,7 +1364,7 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag)
}
if(hp) {
if( sc && (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) ) {
if( sc && (sc->data[SC_BERSERK]) ) {
if( flag&1 )
flag &= ~2;
else
@ -3488,7 +3485,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
if (
(sc->data[SC_POISON] && !sc->data[SC_SLOWPOISON])
|| (sc->data[SC_DPOISON] && !sc->data[SC_SLOWPOISON])
|| sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]
|| sc->data[SC_BERSERK]
|| sc->data[SC_TRICKDEAD]
|| sc->data[SC_BLEEDING]
|| sc->data[SC_MAGICMUSHROOM]
@ -4910,7 +4907,7 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
flee += flee * sc->data[SC_INCFLEERATE]->val1/100;
if(sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1)
flee -= flee * 50/100;
if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
if(sc->data[SC_BERSERK])
flee -= flee * 50/100;
if(sc->data[SC_BLIND])
flee -= flee * 25/100;
@ -4957,7 +4954,7 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);
if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
if(sc->data[SC_BERSERK])
return 0;
if(sc->data[SC_SKA])
return sc->data[SC_SKA]->val3;
@ -5037,7 +5034,7 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change
return (short)cap_value(def2,1,SHRT_MAX);
#endif
if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
if(sc->data[SC_BERSERK])
return 0;
if(sc->data[SC_ETERNALCHAOS])
return 0;
@ -5095,7 +5092,7 @@ static defType status_calc_mdef(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX);
if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
if(sc->data[SC_BERSERK])
return 0;
if(sc->data[SC_BARRIER])
return 100;
@ -5145,7 +5142,7 @@ static signed short status_calc_mdef2(struct block_list *bl, struct status_chang
#endif
if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
if(sc->data[SC_BERSERK])
return 0;
if(sc->data[SC_SKA])
return 90;
@ -5290,7 +5287,7 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
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] || sc->data[SC__BLOODYLUST])
if( sc->data[SC_BERSERK] )
val = max( val, 25 );
if( sc->data[SC_RUN] )
val = max( val, 55 );
@ -5405,7 +5402,7 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s
}
}
if((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) && skills1 < 15)
if(sc->data[SC_BERSERK] && skills1 < 15)
skills1 = 15;
else if(sc->data[SC_MADNESSCANCEL] && skills1 < 15) // needs more info
skills1 = 15;
@ -5550,7 +5547,7 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
}
aspd_rate -= max;
if((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]))
if(sc->data[SC_BERSERK])
aspd_rate -= 300;
else if(sc->data[SC_MADNESSCANCEL])
aspd_rate -= 200;
@ -5652,7 +5649,7 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang
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] || sc->data[SC__BLOODYLUST])
if(sc->data[SC_BERSERK])
maxhp += maxhp * 2;
if(sc->data[SC_MARIONETTE])
maxhp -= 1000;
@ -6310,7 +6307,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
case SC__LAZINESS:
case SC__UNLUCKY:
case SC__WEAKNESS:
case SC__BLOODYLUST:
return 0;
}
@ -6690,12 +6686,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
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]))
)
if(sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC__BLOODYLUST])
return 0;
break;
@ -6946,7 +6938,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
}
break;
case SC_SATURDAYNIGHTFEVER:
if (sc->data[SC_BERSERK] || sc->data[SC_INSPIRATION] || sc->data[SC__BLOODYLUST])
if (sc->data[SC_BERSERK] || sc->data[SC_INSPIRATION])
return 0;
break;
}
@ -7067,8 +7059,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER);
status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER);
break;
case SC__BLOODYLUST:
case SC_BERSERK:
if( val3 == SC__BLOODYLUST )
break;
if(battle_config.berserk_cancels_buffs) {
status_change_end(bl, SC_ONEHAND, INVALID_TIMER);
status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
@ -7324,7 +7317,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
val4 = sce->val4;
break;
case SC_LERADSDEW:
if (sc && (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]))
if (sc && sc->data[SC_BERSERK])
return 0;
case SC_SHAPESHIFT:
case SC_PROPERTYWALK:
@ -7785,9 +7778,10 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
break;
case SC_BERSERK:
if (!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4)
if( val3 == SC__BLOODYLUST )
sc_start(src,bl,(sc_type)val3,100,val1,tick);
if (!val3 && !(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4))
sc_start4(src,bl, SC_ENDURE, 100,10,0,0,2, tick);
case SC__BLOODYLUST:
//HP healing is performing after the calc_status call.
//Val2 holds HP penalty
if (!val4) val4 = skill_get_time2(status_sc2skill(type),val1);
@ -8962,7 +8956,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
break;
case SC_BERSERK:
opt_flag = 0;
// case SC__BLOODYLUST:
sc->opt3 |= OPT3_BERSERK;
break;
// case ???: // doesn't seem to do anything
@ -9101,7 +9094,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
pet_sc_check(sd, type); //Skotlex: Pet Status Effect Healing
switch (type) {
case SC__BLOODYLUST:
case SC_BERSERK:
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.
@ -9580,15 +9572,15 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
case SC_BERSERK:
case SC_SATURDAYNIGHTFEVER:
//If val2 is removed, no HP penalty (dispelled?) [Skotlex]
if (status->hp > 100 && sce->val2)
if(status->hp > 200 && sc && sc->data[SC__BLOODYLUST]) {
status_percent_heal(bl, 100, 0);
status_change_end(bl, SC__BLOODYLUST, INVALID_TIMER);
} else if (status->hp > 100 && sce->val2) //If val2 is removed, no HP penalty (dispelled?) [Skotlex]
status_set_hp(bl, 100, 0);
if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2)
{
if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2) {
sc->data[SC_ENDURE]->val4 = 0;
status_change_end(bl, SC_ENDURE, INVALID_TIMER);
}
case SC__BLOODYLUST:
sc_start4(bl, bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill_get_time(LK_BERSERK, sce->val1));
if( type == SC_SATURDAYNIGHTFEVER ) //Sit down force of Saturday Night Fever has the duration of only 3 seconds.
sc_start(bl, bl,SC_SITDOWN_FORCE,100,sce->val1,skill_get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1));
@ -9875,7 +9867,6 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_BERSERK:
opt_flag = 0;
// case SC__BLOODYLUST:
sc->opt3 &= ~OPT3_BERSERK;
break;
// case ???: // doesn't seem to do anything
@ -10257,7 +10248,6 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
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 )
@ -11015,7 +11005,6 @@ int status_change_clear_buffs (struct block_list* bl, int type)
continue;
break;
//The rest are buffs that can be removed.
case SC__BLOODYLUST:
case SC_BERSERK:
case SC_SATURDAYNIGHTFEVER:
if (!(type&1))

View File

@ -987,8 +987,7 @@ int unit_can_move(struct block_list *bl) {
(sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT ||
(sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE
) )
|| (sc->data[SC_CLOAKING] && //Need wall at level 1-2
sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1))
|| (sc->data[SC_CLOAKING] && sc->data[SC_CLOAKING]->val1 < 3) // Can't move at level less than 3
)
return 0;
@ -1475,6 +1474,11 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
}
}
if( (skill_id >= SC_MANHOLE && skill_id <= SC_FEINTBOMB) && map_getcell(src->m, skill_x, skill_y, CELL_CHKMAELSTROM) ) {
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
if (!status_check_skilluse(src, NULL, skill_id, 0))
return 0;