summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map/Makefile.in4
-rw-r--r--src/map/battle.c127
-rw-r--r--src/map/battle.h12
-rw-r--r--src/map/clif.c554
-rw-r--r--src/map/clif.h21
-rw-r--r--src/map/guild.c11
-rw-r--r--src/map/map.c5
-rw-r--r--src/map/map.h5
-rw-r--r--src/map/mob.c45
-rw-r--r--src/map/mob.h4
-rw-r--r--src/map/npc.c45
-rw-r--r--src/map/pc.c63
-rw-r--r--src/map/pc.h3
-rw-r--r--src/map/script.c267
-rw-r--r--src/map/skill.c32
-rw-r--r--src/map/skill.h1
-rw-r--r--src/map/status.c32
-rw-r--r--src/map/unit.c4
18 files changed, 1021 insertions, 214 deletions
diff --git a/src/map/Makefile.in b/src/map/Makefile.in
index f1eccdf8d..931b86c6a 100644
--- a/src/map/Makefile.in
+++ b/src/map/Makefile.in
@@ -15,7 +15,7 @@ COMMON_SQL_H = ../common/sql.h
MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \
npc_chat.o chat.o path.o itemdb.o mob.o script.o \
- storage.o skill.o atcommand.o battle.o \
+ storage.o skill.o atcommand.o battle.o battleground.o \
intif.o trade.o party.o vending.o guild.o pet.o \
log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o
MAP_TXT_OBJ = $(MAP_OBJ:%=obj_txt/%) \
@@ -24,7 +24,7 @@ MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \
obj_sql/mapreg_sql.o
MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \
chat.h itemdb.h mob.h script.h path.h \
- storage.h skill.h atcommand.h battle.h \
+ storage.h skill.h atcommand.h battle.h battleground.h \
intif.h trade.h party.h vending.h guild.h pet.h \
log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h mapreg.h
diff --git a/src/map/battle.c b/src/map/battle.c
index f9bbd08b6..b1bc7287d 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -24,6 +24,7 @@
#include "guild.h"
#include "party.h"
#include "battle.h"
+#include "battleground.h"
#include <stdio.h>
#include <stdlib.h>
@@ -277,12 +278,18 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
nullpo_retr(0, bl);
- if (!damage)
+ if( !damage )
return 0;
-
if( mob_ksprotected(src, bl) )
return 0;
+ if( bl->type == BL_MOB )
+ { // Event Emperiums works like GvG Emperiums
+ struct mob_data *md = BL_CAST(BL_MOB, bl);
+ if( map[bl->m].flag.battleground && (md->class_ == 1914 || md->class_ == 1915) && flag&BF_SKILL )
+ return 0; // Crystal Cannot receive magic damage on battlegrounds
+ }
+
if (bl->type == BL_PC) {
sd=(struct map_session_data *)bl;
//Special no damage states
@@ -522,6 +529,42 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
}
/*==========================================
+ * Calculates BG related damage adjustments.
+ *------------------------------------------*/
+int battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int damage, int div_, int skill_num, int skill_lv, int flag)
+{
+ if( !damage ) return 0;
+ switch( skill_num )
+ {
+ case PA_PRESSURE:
+ case HW_GRAVITATION:
+ case NJ_ZENYNAGE:
+ break;
+ default:
+ if( flag&BF_SKILL )
+ { //Skills get a different reduction than non-skills. [Skotlex]
+ if( flag&BF_WEAPON )
+ damage = damage * battle_config.bg_weapon_damage_rate/100;
+ if( flag&BF_MAGIC )
+ damage = damage * battle_config.bg_magic_damage_rate/100;
+ if( flag&BF_MISC )
+ damage = damage * battle_config.bg_misc_damage_rate/100;
+ }
+ else
+ { //Normal attacks get reductions based on range.
+ if( flag&BF_SHORT )
+ damage = damage * battle_config.bg_short_damage_rate/100;
+ if( flag&BF_LONG )
+ damage = damage * battle_config.bg_long_damage_rate/100;
+ }
+
+ if( !damage ) damage = 1;
+ }
+
+ return damage;
+}
+
+/*==========================================
* Calculates GVG related damage adjustments.
*------------------------------------------*/
int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag)
@@ -536,7 +579,7 @@ int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int dama
if (bl->type == BL_MOB)
md=(struct mob_data *)bl;
-
+
if(md && md->guardian_data) {
if(class_ == MOBID_EMPERIUM && flag&BF_SKILL)
//Skill immunity.
@@ -2083,19 +2126,25 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
{ //There is a total damage value
if(!wd.damage2) {
wd.damage=battle_calc_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
- if (map_flag_gvg2(target->m))
+ if( map_flag_gvg2(target->m) )
wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
+ else if( map[target->m].flag.battleground )
+ wd.damage=battle_calc_bg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
} else
if(!wd.damage) {
wd.damage2=battle_calc_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag);
- if (map_flag_gvg2(target->m))
+ if( map_flag_gvg2(target->m) )
wd.damage2=battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag);
+ else if( map[target->m].flag.battleground )
+ wd.damage=battle_calc_bg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag);
} else
{
int d1=wd.damage+wd.damage2,d2=wd.damage2;
wd.damage=battle_calc_damage(src,target,d1,wd.div_,skill_num,skill_lv,wd.flag);
- if (map_flag_gvg2(target->m))
+ if( map_flag_gvg2(target->m) )
wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
+ else if( map[target->m].flag.battleground )
+ wd.damage=battle_calc_bg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
wd.damage2=(d2*100/d1)*wd.damage/100;
if(wd.damage > 1 && wd.damage2 < 1) wd.damage2=1;
wd.damage-=wd.damage2;
@@ -2494,8 +2543,10 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
ad.damage = ad.damage>0?1:-1;
ad.damage=battle_calc_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag);
- if (map_flag_gvg2(target->m))
+ if( map_flag_gvg2(target->m) )
ad.damage=battle_calc_gvg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag);
+ else if( map[target->m].flag.battleground )
+ ad.damage=battle_calc_bg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag);
return ad;
}
@@ -2721,8 +2772,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
md.damage=battle_calc_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag);
- if (map_flag_gvg2(target->m))
+ if( map_flag_gvg2(target->m) )
md.damage=battle_calc_gvg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag);
+ else if( map[target->m].flag.battleground )
+ md.damage=battle_calc_bg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag);
if (skill_num == NJ_ZENYNAGE && sd)
{ //Time to Pay Up.
@@ -3210,6 +3263,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if( !((agit_flag || agit2_flag) && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id )
return 0; // Disable guardians/emperiums owned by Guilds on non-woe times.
+ if( md->state.inmunity && flag&BCT_ENEMY )
+ return 0;
break;
}
}
@@ -3261,10 +3316,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
return 0; // You can't target anything out of your duel
}
}
- if (map_flag_gvg(m) && !sd->status.guild_id &&
- t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data)
+ if( map_flag_gvg(m) && !sd->status.guild_id && t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data )
return 0; //If you don't belong to a guild, can't target guardians/emperium.
- if (t_bl->type != BL_PC)
+ if( t_bl->type != BL_PC )
state |= BCT_ENEMY; //Natural enemy.
break;
}
@@ -3315,28 +3369,34 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if( map_flag_vs(m) )
{ //Check rivalry settings.
- if (flag&(BCT_PARTY|BCT_ENEMY)) {
+ int sbg_id = 0, tbg_id = 0;
+ if( map[m].flag.battleground )
+ {
+ sbg_id = bg_team_get_id(s_bl);
+ tbg_id = bg_team_get_id(t_bl);
+ }
+ if( flag&(BCT_PARTY|BCT_ENEMY) )
+ {
int s_party = status_get_party_id(s_bl);
- if (
- !(map[m].flag.pvp && map[m].flag.pvp_noparty) &&
- !(map_flag_gvg(m) && map[m].flag.gvg_noparty) &&
- s_party && s_party == status_get_party_id(t_bl)
- )
+ if( s_party && s_party == status_get_party_id(t_bl) && !(map[m].flag.pvp && map[m].flag.pvp_noparty) && !(map_flag_gvg(m) && map[m].flag.gvg_noparty) && (!map[m].flag.battleground || sbg_id == tbg_id) )
state |= BCT_PARTY;
else
state |= BCT_ENEMY;
}
- if (flag&(BCT_GUILD|BCT_ENEMY)) {
+ if( flag&(BCT_GUILD|BCT_ENEMY) )
+ {
int s_guild = status_get_guild_id(s_bl);
int t_guild = status_get_guild_id(t_bl);
- if( !(map[m].flag.pvp && map[m].flag.pvp_noguild) && s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)) )
+ if( !(map[m].flag.pvp && map[m].flag.pvp_noguild) && s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)) && (!map[m].flag.battleground || sbg_id == tbg_id) )
state |= BCT_GUILD;
else
state |= BCT_ENEMY;
}
- if (state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) &&
- s_bl->type == BL_PC && t_bl->type == BL_PC)
- { //Prevent novice engagement on pk_mode (feature by Valaris)
+ if( state&BCT_ENEMY && map[m].flag.battleground && sbg_id && sbg_id == tbg_id )
+ state &= ~BCT_ENEMY;
+
+ if( state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) && s_bl->type == BL_PC && t_bl->type == BL_PC )
+ { // Prevent novice engagement on pk_mode (feature by Valaris)
TBL_PC *sd = (TBL_PC*)s_bl, *sd2 = (TBL_PC*)t_bl;
if (
(sd->class_&MAPID_UPPERMASK) == MAPID_NOVICE ||
@@ -3345,15 +3405,19 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
(int)sd2->status.base_level < battle_config.pk_min_level ||
(battle_config.pk_level_range && abs((int)sd->status.base_level - (int)sd2->status.base_level) > battle_config.pk_level_range)
)
- state&=~BCT_ENEMY;
+ state &= ~BCT_ENEMY;
}
- } else { //Non pvp/gvg, check party/guild settings.
- if (flag&BCT_PARTY || state&BCT_ENEMY) {
+ }
+ else
+ { //Non pvp/gvg, check party/guild settings.
+ if( flag&BCT_PARTY || state&BCT_ENEMY )
+ {
int s_party = status_get_party_id(s_bl);
if(s_party && s_party == status_get_party_id(t_bl))
state |= BCT_PARTY;
}
- if (flag&BCT_GUILD || state&BCT_ENEMY) {
+ if( flag&BCT_GUILD || state&BCT_ENEMY )
+ {
int s_guild = status_get_guild_id(s_bl);
int t_guild = status_get_guild_id(t_bl);
if(s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)))
@@ -3768,6 +3832,17 @@ static const struct _battle_data {
{ "auction_maximumprice", &battle_config.auction_maximumprice, 500000000, 0, MAX_ZENY, },
{ "gm_viewequip_min_lv", &battle_config.gm_viewequip_min_lv, 0, 0, 99, },
{ "homunculus_auto_vapor", &battle_config.homunculus_auto_vapor, 0, 0, 1, },
+// BattleGround Settings
+ { "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, },
+ { "bg_guild_id1", &battle_config.bg_guild_id1, 0, 0, INT_MAX, },
+ { "bg_guild_id2", &battle_config.bg_guild_id2, 0, 0, INT_MAX, },
+ { "bg_short_attack_damage_rate", &battle_config.bg_short_damage_rate, 80, 0, INT_MAX, },
+ { "bg_long_attack_damage_rate", &battle_config.bg_long_damage_rate, 80, 0, INT_MAX, },
+ { "bg_weapon_attack_damage_rate", &battle_config.bg_weapon_damage_rate, 60, 0, INT_MAX, },
+ { "bg_magic_attack_damage_rate", &battle_config.bg_magic_damage_rate, 60, 0, INT_MAX, },
+ { "bg_misc_attack_damage_rate", &battle_config.bg_misc_damage_rate, 60, 0, INT_MAX, },
+ { "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, },
+ { "bg_idle_announce", &battle_config.bg_idle_announce, 0, 0, INT_MAX, },
};
diff --git a/src/map/battle.h b/src/map/battle.h
index 4326fb6ee..20b1b9b2b 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -43,6 +43,7 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
// ダメージ最終計算
int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag);
int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag);
+int battle_calc_bg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag);
enum { // 最終計算のフラグ
BF_WEAPON = 0x0001,
@@ -460,6 +461,17 @@ extern struct Battle_Config
int auction_maximumprice;
int gm_viewequip_min_lv;
int homunculus_auto_vapor; //Keep Homunculus from Vaporizing when master dies. [L0ne_W0lf]
+ // [BattleGround Settings]
+ int bg_update_interval;
+ int bg_guild_id1;
+ int bg_guild_id2;
+ int bg_short_damage_rate;
+ int bg_long_damage_rate;
+ int bg_weapon_damage_rate;
+ int bg_magic_damage_rate;
+ int bg_misc_damage_rate;
+ int bg_flee_penalty;
+ int bg_idle_announce;
} battle_config;
void do_init_battle(void);
diff --git a/src/map/clif.c b/src/map/clif.c
index 94f0dceef..739805f04 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -25,6 +25,7 @@
#include "atcommand.h"
#include "intif.h"
#include "battle.h"
+#include "battleground.h"
#include "mob.h"
#include "party.h"
#include "unit.h"
@@ -231,6 +232,7 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
struct map_session_data *sd, *tsd;
struct party_data *p = NULL;
struct guild *g = NULL;
+ struct battleground_data *bg = NULL;
int x0 = 0, x1 = 0, y0 = 0, y1 = 0, fd;
struct s_mapiterator* iter;
@@ -415,6 +417,7 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
case GUILD_SAMEMAP_WOS:
case GUILD:
case GUILD_WOS:
+ case GUILD_NOBG:
if (sd && sd->status.guild_id)
g = guild_search(sd->status.guild_id);
@@ -425,10 +428,13 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
if( !(fd=sd->fd) )
continue;
+ if( type == GUILD_NOBG && sd->state.bg_id )
+ continue;
+
if( sd->bl.id == bl->id && (type == GUILD_WOS || type == GUILD_SAMEMAP_WOS || type == GUILD_AREA_WOS) )
continue;
- if( type != GUILD && type != GUILD_WOS && sd->bl.m != bl->m )
+ if( type != GUILD && type != GUILD_NOBG && type != GUILD_WOS && sd->bl.m != bl->m )
continue;
if( (type == GUILD_AREA || type == GUILD_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) )
@@ -459,6 +465,38 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
}
break;
+ case BG_AREA:
+ case BG_AREA_WOS:
+ x0 = bl->x - AREA_SIZE;
+ y0 = bl->y - AREA_SIZE;
+ x1 = bl->x + AREA_SIZE;
+ y1 = bl->y + AREA_SIZE;
+ case BG_SAMEMAP:
+ case BG_SAMEMAP_WOS:
+ case BG:
+ case BG_WOS:
+ if( sd && sd->state.bg_id && (bg = bg_team_search(sd->state.bg_id)) != NULL )
+ {
+ for( i = 0; i < MAX_BG_MEMBERS; i++ )
+ {
+ if( (sd = bg->members[i].sd) == NULL || !(fd = sd->fd) )
+ continue;
+ if( sd->bl.id == bl->id && (type == BG_WOS || type == BG_SAMEMAP_WOS || type == BG_AREA_WOS) )
+ continue;
+ if( type != BG && type != BG_WOS && sd->bl.m != bl->m )
+ continue;
+ if( (type == BG_AREA || type == BG_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) )
+ continue;
+ if( packet_db[sd->packet_ver][RBUFW(buf,0)].len )
+ { // packet must exist for the client version
+ WFIFOHEAD(fd,len);
+ memcpy(WFIFOP(fd,0), buf, len);
+ WFIFOSET(fd,len);
+ }
+ }
+ }
+ break;
+
default:
ShowError("clif_send: Unrecognized type %d\n",type);
return -1;
@@ -774,8 +812,8 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS )
{ //The hell, why flags work like this?
- WBUFL(buf,22) = status_get_emblem_id(bl);
- WBUFL(buf,26) = status_get_guild_id(bl);
+ WBUFL(buf,22) = clif_bg_emblem_id(bl);
+ WBUFL(buf,26) = clif_bg_guild_id(bl);
}
WBUFW(buf,28) = vd->hair_color;
@@ -789,8 +827,8 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
WBUFB(buf,40) = 0;
return packet_len(0x7c);
}
- WBUFL(buf,34) = status_get_guild_id(bl);
- WBUFW(buf,38) = status_get_emblem_id(bl);
+ WBUFL(buf,34) = clif_bg_guild_id(bl);
+ WBUFW(buf,38) = clif_bg_emblem_id(bl);
WBUFW(buf,40) = (sd)? sd->status.manner : 0;
#if PACKETVER >= 7
if (!type) {
@@ -870,8 +908,8 @@ static int clif_set_unit_walking(struct block_list* bl, struct unit_data* ud, un
WBUFW(buf,32) = vd->hair_color;
WBUFW(buf,34) = vd->cloth_color;
WBUFW(buf,36) = (sd)? sd->head_dir : 0;
- WBUFL(buf,38) = status_get_guild_id(bl);
- WBUFW(buf,42) = status_get_emblem_id(bl);
+ WBUFL(buf,38) = clif_bg_guild_id(bl);
+ WBUFW(buf,42) = clif_bg_emblem_id(bl);
WBUFW(buf,44) = (sd)? sd->status.manner : 0;
#if PACKETVER < 7
WBUFW(buf,46) = (sc)? sc->opt3 : 0;
@@ -2060,6 +2098,9 @@ int clif_guild_xy(struct map_session_data *sd)
*------------------------------------------*/
int clif_guild_xy_single(int fd, struct map_session_data *sd)
{
+ if( sd->state.bg_id )
+ return 0;
+
WFIFOHEAD(fd,packet_len(0x1eb));
WFIFOW(fd,0)=0x1eb;
WFIFOL(fd,2)=sd->status.account_id;
@@ -2152,10 +2193,12 @@ int clif_updatestatus(struct map_session_data *sd,int type)
break;
case SP_HP:
WFIFOL(fd,4)=sd->battle_status.hp;
- if (battle_config.disp_hpmeter)
+ if( battle_config.disp_hpmeter )
clif_hpmeter(sd);
- if (!battle_config.party_hp_mode && sd->status.party_id)
+ if( !battle_config.party_hp_mode && sd->status.party_id )
clif_party_hp(sd);
+ if( sd->state.bg_id )
+ clif_bg_hp(sd);
break;
case SP_SP:
WFIFOL(fd,4)=sd->battle_status.sp;
@@ -3352,9 +3395,9 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d
if(dstsd->spiritball > 0)
clif_spiritball_single(sd->fd, dstsd);
- if((sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting.
- (battle_config.disp_hpmeter && (gmlvl = pc_isGM(sd)) >= battle_config.disp_hpmeter && gmlvl >= pc_isGM(dstsd))
- )
+ if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting.
+ (sd->state.bg_id && sd->state.bg_id == dstsd->state.bg_id) || //BattleGround
+ (battle_config.disp_hpmeter && (gmlvl = pc_isGM(sd)) >= battle_config.disp_hpmeter && gmlvl >= pc_isGM(dstsd)) )
clif_hpmeter_single(sd->fd, dstsd->bl.id, dstsd->battle_status.hp, dstsd->battle_status.max_hp);
// display link (sd - dstsd) to sd
@@ -5585,26 +5628,29 @@ int clif_hpmeter(struct map_session_data *sd)
WBUFW(buf,0) = 0x106;
WBUFL(buf,2) = sd->status.account_id;
- if (sd->battle_status.max_hp > SHRT_MAX) { //To correctly display the %hp bar. [Skotlex]
+ if( sd->battle_status.max_hp > SHRT_MAX )
+ { //To correctly display the %hp bar. [Skotlex]
WBUFW(buf,6) = sd->battle_status.hp/(sd->battle_status.max_hp/100);
WBUFW(buf,8) = 100;
- } else {
+ }
+ else
+ {
WBUFW(buf,6) = sd->battle_status.hp;
WBUFW(buf,8) = sd->battle_status.max_hp;
}
- for (i = 0; i < fd_max; i++) {
- if (session[i] && session[i]->func_parse == clif_parse &&
- (sd2 = (struct map_session_data*)session[i]->session_data) &&
- sd != sd2 && sd2->state.active) {
- if (sd2->bl.m != sd->bl.m ||
- sd2->bl.x < x0 || sd2->bl.y < y0 ||
- sd2->bl.x > x1 || sd2->bl.y > y1 ||
- (level = pc_isGM(sd2)) < battle_config.disp_hpmeter ||
- level < pc_isGM(sd))
- continue;
- WFIFOHEAD (i, packet_len(0x106));
- memcpy (WFIFOP(i,0), buf, packet_len(0x106));
- WFIFOSET (i, packet_len(0x106));
+
+ for( i = 0; i < fd_max; i++ )
+ {
+ if( session[i] && session[i]->func_parse == clif_parse && (sd2 = (struct map_session_data*)session[i]->session_data) && sd != sd2 && sd2->state.active )
+ {
+ if( sd2->bl.m != sd->bl.m || sd2->bl.x < x0 || sd2->bl.y < y0 || sd2->bl.x > x1 || sd2->bl.y > y1 )
+ continue; // Not in the Visual Area
+ if( battle_config.disp_hpmeter && (level = pc_isGM(sd2)) >= battle_config.disp_hpmeter && level >= pc_isGM(sd) )
+ {
+ WFIFOHEAD(i,packet_len(0x106));
+ memcpy(WFIFOP(i,0),buf,packet_len(0x106));
+ WFIFOSET(i,packet_len(0x106));
+ }
}
}
@@ -6045,16 +6091,16 @@ int clif_guild_created(struct map_session_data *sd,int flag)
/*==========================================
* ギルド所属通知
*------------------------------------------*/
-int clif_guild_belonginfo(struct map_session_data *sd,struct guild *g)
+int clif_guild_belonginfo(struct map_session_data *sd, struct guild *g)
{
int ps,fd;
-
nullpo_retr(0, sd);
+ if( sd->state.bg_id )
+ return clif_bg_belonginfo(sd);
nullpo_retr(0, g);
fd=sd->fd;
ps=guild_getposition(g,sd);
-
WFIFOHEAD(fd,packet_len(0x16c));
memset(WFIFOP(fd,0),0,packet_len(0x16c));
WFIFOW(fd,0)=0x16c;
@@ -6150,20 +6196,25 @@ int clif_guild_basicinfo(struct map_session_data *sd)
{
int fd,i,t;
struct guild *g;
- struct guild_castle *gc=NULL;
+ struct guild_castle *gc = NULL;
+ struct battleground_data *bg = NULL;
nullpo_retr(0, sd);
+ fd = sd->fd;
- fd=sd->fd;
- g=guild_search(sd->status.guild_id);
- if(g==NULL)
+ if( sd->state.bg_id && (g = bg_guild_get(sd->state.bg_id)) != NULL )
+ bg = bg_team_search(sd->state.bg_id);
+ else
+ g = guild_search(sd->status.guild_id);
+
+ if( g == NULL )
return 0;
WFIFOHEAD(fd,packet_len(0x1b6));
WFIFOW(fd, 0)=0x1b6;//0x150;
WFIFOL(fd, 2)=g->guild_id;
WFIFOL(fd, 6)=g->guild_lv;
- WFIFOL(fd,10)=g->connect_member;
+ WFIFOL(fd,10)=bg?bg->count:g->connect_member;
WFIFOL(fd,14)=g->max_member;
WFIFOL(fd,18)=g->average_lv;
WFIFOL(fd,22)=g->exp;
@@ -6196,11 +6247,13 @@ int clif_guild_allianceinfo(struct map_session_data *sd)
struct guild *g;
nullpo_retr(0, sd);
+ if( !sd->state.bg_id || (g = bg_guild_get(sd->state.bg_id)) == NULL )
+ g = guild_search(sd->status.guild_id);
- fd=sd->fd;
- g=guild_search(sd->status.guild_id);
- if(g==NULL)
+ if( g == NULL )
return 0;
+
+ fd = sd->fd;
WFIFOHEAD(fd, MAX_GUILDALLIANCE * 32 + 4);
WFIFOW(fd, 0)=0x14c;
for(i=c=0;i<MAX_GUILDALLIANCE;i++){
@@ -6225,14 +6278,13 @@ int clif_guild_memberlist(struct map_session_data *sd)
int fd;
int i,c;
struct guild *g;
-
nullpo_retr(0, sd);
- fd=sd->fd;
- if (!fd)
+ if( (fd = sd->fd) == 0 )
return 0;
- g=guild_search(sd->status.guild_id);
- if(g==NULL)
+ if( sd->state.bg_id )
+ return clif_bg_memberlist(sd);
+ if( (g = guild_search(sd->status.guild_id)) == NULL )
return 0;
WFIFOHEAD(fd, g->max_member * 104 + 4);
@@ -6268,11 +6320,13 @@ int clif_guild_positionnamelist(struct map_session_data *sd)
struct guild *g;
nullpo_retr(0, sd);
+ if( !sd->state.bg_id || (g = bg_guild_get(sd->state.bg_id)) == NULL )
+ g = guild_search(sd->status.guild_id);
- fd=sd->fd;
- g=guild_search(sd->status.guild_id);
- if(g==NULL)
+ if( g == NULL )
return 0;
+
+ fd = sd->fd;
WFIFOHEAD(fd, MAX_GUILDPOSITION * 28 + 4);
WFIFOW(fd, 0)=0x166;
for(i=0;i<MAX_GUILDPOSITION;i++){
@@ -6292,11 +6346,13 @@ int clif_guild_positioninfolist(struct map_session_data *sd)
struct guild *g;
nullpo_retr(0, sd);
+ if( !sd->state.bg_id || (g = bg_guild_get(sd->state.bg_id)) == NULL )
+ g = guild_search(sd->status.guild_id);
- fd=sd->fd;
- g=guild_search(sd->status.guild_id);
- if(g==NULL)
+ if( g == NULL )
return 0;
+
+ fd = sd->fd;
WFIFOHEAD(fd, MAX_GUILDPOSITION * 16 + 4);
WFIFOW(fd, 0)=0x160;
for(i=0;i<MAX_GUILDPOSITION;i++){
@@ -6356,14 +6412,13 @@ int clif_guild_memberpositionchanged(struct guild *g,int idx)
int clif_guild_emblem(struct map_session_data *sd,struct guild *g)
{
int fd;
-
nullpo_retr(0, sd);
nullpo_retr(0, g);
- fd=sd->fd;
-
- if(g->emblem_len<=0)
+ fd = sd->fd;
+ if( g->emblem_len <= 0 )
return 0;
+
WFIFOHEAD(fd,g->emblem_len+12);
WFIFOW(fd,0)=0x152;
WFIFOW(fd,2)=g->emblem_len+12;
@@ -6385,8 +6440,8 @@ void clif_guild_emblem_area(struct block_list* bl)
// (emblem in the flag npcs and emblem over the head in agit maps) [FlavioJS]
WBUFW(buf,0) = 0x1B4;
WBUFL(buf,2) = bl->id;
- WBUFL(buf,6) = status_get_guild_id(bl);
- WBUFW(buf,10) = status_get_emblem_id(bl);
+ WBUFL(buf,6) = clif_bg_guild_id(bl);
+ WBUFW(buf,10) = clif_bg_emblem_id(bl);
clif_send(buf, 12, bl, AREA_WOS);
}
@@ -6400,12 +6455,13 @@ int clif_guild_skillinfo(struct map_session_data* sd)
int i,c;
nullpo_retr(0, sd);
+ if( !sd->state.bg_id || (g = bg_guild_get(sd->state.bg_id)) == NULL )
+ g = guild_search(sd->status.guild_id);
- fd = sd->fd;
- g = guild_search(sd->status.guild_id);
- if(g == NULL)
+ if( g == NULL )
return 0;
+ fd = sd->fd;
WFIFOHEAD(fd, 6 + MAX_GUILDSKILL*37);
WFIFOW(fd,0) = 0x0162;
WFIFOW(fd,4) = g->skill_point;
@@ -6505,7 +6561,7 @@ int clif_guild_leave(struct map_session_data *sd,const char *name,const char *me
WBUFW(buf, 0)=0x15a;
memcpy(WBUFP(buf, 2),name,NAME_LENGTH);
memcpy(WBUFP(buf,26),mes,40);
- clif_send(buf,packet_len(0x15a),&sd->bl,GUILD);
+ clif_send(buf,packet_len(0x15a),&sd->bl,GUILD_NOBG);
return 0;
}
@@ -6522,7 +6578,7 @@ int clif_guild_expulsion(struct map_session_data *sd,const char *name,const char
safestrncpy((char*)WBUFP(buf, 2),name,NAME_LENGTH);
safestrncpy((char*)WBUFP(buf,26),mes,40);
safestrncpy((char*)WBUFP(buf,66),"",NAME_LENGTH); // account name (not used for security reasons)
- clif_send(buf,packet_len(0x15c),&sd->bl,GUILD);
+ clif_send(buf,packet_len(0x15c),&sd->bl,GUILD_NOBG);
return 0;
}
@@ -6536,11 +6592,13 @@ int clif_guild_expulsionlist(struct map_session_data *sd)
struct guild *g;
nullpo_retr(0, sd);
+ if( !sd->state.bg_id || (g = bg_guild_get(sd->state.bg_id)) == NULL )
+ g = guild_search(sd->status.guild_id);
- fd=sd->fd;
- g=guild_search(sd->status.guild_id);
- if(g==NULL)
+ if( g == NULL )
return 0;
+
+ fd = sd->fd;
WFIFOHEAD(fd,4 + MAX_GUILDEXPULSION * 88);
WFIFOW(fd,0)=0x163;
for(i=c=0;i<MAX_GUILDEXPULSION;i++){
@@ -6572,7 +6630,7 @@ int clif_guild_message(struct guild *g,int account_id,const char *mes,int len)
memcpy(WBUFP(buf,4), mes, len);
if ((sd = guild_getavailablesd(g)) != NULL)
- clif_send(buf, WBUFW(buf,2), &sd->bl, GUILD);
+ clif_send(buf, WBUFW(buf,2), &sd->bl, GUILD_NOBG);
if(buf) aFree(buf);
@@ -7080,7 +7138,7 @@ int clif_refresh(struct map_session_data *sd)
int clif_charnameack (int fd, struct block_list *bl)
{
unsigned char buf[103];
- int cmd = 0x95;
+ int cmd = 0x95, i, ps = -1;
nullpo_retr(0, bl);
@@ -7097,7 +7155,7 @@ int clif_charnameack (int fd, struct block_list *bl)
//Requesting your own "shadow" name. [Skotlex]
if (ssd->fd == fd && ssd->disguise)
- WBUFL(buf,2) = -bl->id;
+ WBUFL(buf,2) = -bl->id;
if (strlen(ssd->fakename)>1) {
memcpy(WBUFP(buf,6), ssd->fakename, NAME_LENGTH);
@@ -7108,8 +7166,16 @@ int clif_charnameack (int fd, struct block_list *bl)
if (ssd->status.party_id > 0)
p = party_search(ssd->status.party_id);
- if (ssd->status.guild_id > 0)
- g = guild_search(ssd->status.guild_id);
+ if (ssd->state.bg_id > 0)
+ {
+ g = bg_guild_get(ssd->state.bg_id);
+ ps = 0;
+ }
+ else if( ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL )
+ {
+ ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id);
+ if( i < g->max_member ) ps = g->member[i].position;
+ }
if (p == NULL && g == NULL)
break;
@@ -7120,26 +7186,11 @@ int clif_charnameack (int fd, struct block_list *bl)
else
WBUFB(buf,30) = 0;
- if (g)
+ if (g && ps >= 0 && ps < MAX_GUILDPOSITION)
{
- int i, ps = -1;
- for(i = 0; i < g->max_member; i++) {
- if (g->member[i].account_id == ssd->status.account_id &&
- g->member[i].char_id == ssd->status.char_id )
- {
- ps = g->member[i].position;
- break;
- }
- }
- if (ps >= 0 && ps < MAX_GUILDPOSITION)
- {
- memcpy(WBUFP(buf,54), g->name,NAME_LENGTH);
- memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH);
- } else { //Assume no guild.
- WBUFB(buf,54) = 0;
- WBUFB(buf,78) = 0;
- }
- } else {
+ memcpy(WBUFP(buf,54), g->name,NAME_LENGTH);
+ memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH);
+ } else { //Assume no guild.
WBUFB(buf,54) = 0;
WBUFB(buf,78) = 0;
}
@@ -7161,27 +7212,39 @@ int clif_charnameack (int fd, struct block_list *bl)
case BL_MOB:
{
struct mob_data *md = (struct mob_data *)bl;
+ struct guild *g;
+ struct battleground_data *bg;
nullpo_retr(0, md);
memcpy(WBUFP(buf,6), md->name, NAME_LENGTH);
- if (md->guardian_data && md->guardian_data->guild_id) {
+ if( md->guardian_data && md->guardian_data->guild_id )
+ {
WBUFW(buf, 0) = cmd = 0x195;
WBUFB(buf,30) = 0;
memcpy(WBUFP(buf,54), md->guardian_data->guild_name, NAME_LENGTH);
memcpy(WBUFP(buf,78), md->guardian_data->castle->castle_name, NAME_LENGTH);
- } else if (battle_config.show_mob_info) {
+ }
+ else if( md->state.bg_id && (bg = bg_team_search(md->state.bg_id)) != NULL && (g = bg->g) != NULL )
+ {
+ WBUFW(buf, 0) = cmd = 0x195;
+ WBUFB(buf,30) = 0;
+ memcpy(WBUFP(buf,54), g->name, NAME_LENGTH);
+ memcpy(WBUFP(buf,78), g->position[0].name, NAME_LENGTH);
+ }
+ else if( battle_config.show_mob_info )
+ {
char mobhp[50], *str_p = mobhp;
-
WBUFW(buf, 0) = cmd = 0x195;
- if (battle_config.show_mob_info&4)
+ if( battle_config.show_mob_info&4 )
str_p += sprintf(str_p, "Lv. %d | ", md->level);
- if (battle_config.show_mob_info&1)
+ if( battle_config.show_mob_info&1 )
str_p += sprintf(str_p, "HP: %u/%u | ", md->status.hp, md->status.max_hp);
- if (battle_config.show_mob_info&2)
+ if( battle_config.show_mob_info&2 )
str_p += sprintf(str_p, "HP: %d%% | ", get_percentage(md->status.hp, md->status.max_hp));
//Even thought mobhp ain't a name, we send it as one so the client
//can parse it. [Skotlex]
- if (str_p != mobhp) {
+ if( str_p != mobhp )
+ {
*(str_p-3) = '\0'; //Remove trailing space + pipe.
memcpy(WBUFP(buf,30), mobhp, NAME_LENGTH);
WBUFB(buf,54) = 0;
@@ -7216,7 +7279,7 @@ int clif_charnameack (int fd, struct block_list *bl)
int clif_charnameupdate (struct map_session_data *ssd)
{
unsigned char buf[103];
- int cmd = 0x195;
+ int cmd = 0x195, ps = -1, i;
struct party_data *p = NULL;
struct guild *g = NULL;
@@ -7230,37 +7293,32 @@ int clif_charnameupdate (struct map_session_data *ssd)
memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH);
- if (ssd->status.party_id > 0)
+ if( ssd->status.party_id > 0 )
p = party_search(ssd->status.party_id);
- if (ssd->status.guild_id > 0)
- g = guild_search(ssd->status.guild_id);
+ if( ssd->state.bg_id > 0 )
+ {
+ g = bg_guild_get(ssd->state.bg_id);
+ ps = 0;
+ }
+ else if( ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL )
+ {
+ ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id);
+ if( i < g->max_member ) ps = g->member[i].position;
+ }
- if (p)
+ if( p )
memcpy(WBUFP(buf,30), p->party.name, NAME_LENGTH);
else
WBUFB(buf,30) = 0;
- if (g)
+ if( g && ps >= 0 && ps < MAX_GUILDPOSITION )
+ {
+ memcpy(WBUFP(buf,54), g->name,NAME_LENGTH);
+ memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH);
+ }
+ else
{
- int i, ps = -1;
- for(i = 0; i < g->max_member; i++) {
- if (g->member[i].account_id == ssd->status.account_id &&
- g->member[i].char_id == ssd->status.char_id )
- {
- ps = g->member[i].position;
- break;
- }
- }
- if (ps >= 0 && ps < MAX_GUILDPOSITION)
- {
- memcpy(WBUFP(buf,54), g->name,NAME_LENGTH);
- memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH);
- } else { //Assume no guild.
- WBUFB(buf,54) = 0;
- WBUFB(buf,78) = 0;
- }
- } else {
WBUFB(buf,54) = 0;
WBUFB(buf,78) = 0;
}
@@ -7860,6 +7918,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
clif_party_hp(sd); // Show hp after displacement [LuzZza]
}
+ if( sd->state.bg_id ) clif_bg_hp(sd); // BattleGround System
+
if(map[sd->bl.m].flag.pvp) {
if(!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris]
if (!map[sd->bl.m].flag.pvp_nocalcrank)
@@ -7887,10 +7947,10 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
}
}
- if(map_flag_gvg(sd->bl.m))
+ if( map_flag_gvg(sd->bl.m) || map[sd->bl.m].flag.battleground )
{
clif_set0199(sd,3);
- if (battle_config.gvg_flee_penalty != 100)
+ if( battle_config.gvg_flee_penalty != 100 || battle_config.bg_flee_penalty != 100 )
status_calc_bl(&sd->bl, SCB_FLEE); //Apply flee penalty
}
@@ -8142,7 +8202,7 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
y = ((RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0]+1) & 0x3f) << 4) +
(RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[0] + 2) >> 4);
//Set last idle time... [Skotlex]
- sd->idletime = last_tick;
+ pc_update_last_action(sd);
unit_walktoxy(&sd->bl, x, y, 4);
}
@@ -8434,7 +8494,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
}
pc_delinvincibletimer(sd);
- sd->idletime = last_tick;
+ pc_update_last_action(sd);
unit_attack(&sd->bl, target_id, action_type != 0);
break;
case 0x02: // sitdown
@@ -8794,7 +8854,7 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd)
pc_delinvincibletimer(sd);
//Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex]
- sd->idletime = last_tick;
+ pc_update_last_action(sd);
n = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2;
if(n <0 || n >= MAX_INVENTORY)
@@ -9307,7 +9367,7 @@ 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;
+ pc_update_last_action(sd);
if( pc_cant_act(sd) )
return;
@@ -9433,7 +9493,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, short skil
}
//Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
- sd->idletime = last_tick;
+ pc_update_last_action(sd);
if( skillnotok(skillnum, sd) )
return;
@@ -10158,9 +10218,11 @@ void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd)
*------------------------------------------*/
void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd)
{
- if (!sd->status.guild_id)
+ if( !sd->status.guild_id && !sd->state.bg_id )
return;
- switch(RFIFOL(fd,2)){
+
+ switch( RFIFOL(fd,2) )
+ {
case 0: // ギルド基本情報、同盟敵対情報
clif_guild_basicinfo(sd);
clif_guild_allianceinfo(sd);
@@ -10221,9 +10283,15 @@ void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd)
*------------------------------------------*/
void clif_parse_GuildRequestEmblem(int fd,struct map_session_data *sd)
{
- struct guild* g = guild_search(RFIFOL(fd,2));
- if(g!=NULL)
+ struct guild* g;
+ int guild_id = RFIFOL(fd,2);
+
+ if( (g = guild_search(guild_id)) != NULL )
clif_guild_emblem(sd,g);
+ else if( guild_id == battle_config.bg_guild_id1 )
+ clif_bg_emblem(sd, &bg_guild[0]);
+ else if( guild_id == battle_config.bg_guild_id2 )
+ clif_bg_emblem(sd, &bg_guild[1]);
}
/*==========================================
@@ -10300,6 +10368,12 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd)
clif_displaymessage(fd, msg_txt(228));
return;
}
+ if( sd->state.bg_id )
+ {
+ clif_displaymessage(fd, "You can't leave battleground guilds.");
+ return;
+ }
+
guild_leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14));
}
@@ -10309,8 +10383,8 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd)
*------------------------------------------*/
void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd)
{
- if(map[sd->bl.m].flag.guildlock)
- { //Guild locked.
+ if( map[sd->bl.m].flag.guildlock || sd->state.bg_id )
+ { // Guild locked.
clif_displaymessage(fd, msg_txt(228));
return;
}
@@ -10346,7 +10420,10 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd)
sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
}
- guild_send_message(sd, text, textlen);
+ if( sd->state.bg_id )
+ bg_send_message(sd, text, textlen);
+ else
+ guild_send_message(sd, text, textlen);
}
/*==========================================
@@ -10432,7 +10509,7 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd)
*------------------------------------------*/
void clif_parse_GuildBreak(int fd, struct map_session_data *sd)
{
- if(map[sd->bl.m].flag.guildlock)
+ if( map[sd->bl.m].flag.guildlock )
{ //Guild locked.
clif_displaymessage(fd, msg_txt(228));
return;
@@ -12677,6 +12754,217 @@ void clif_readbook(int fd, int book_id, int page)
WFIFOSET(fd,10);
}
+/*------------------------------------------
+ * BattleGround Packets
+ *------------------------------------------*/
+int clif_bg_hp(struct map_session_data *sd)
+{
+ unsigned char buf[16];
+ nullpo_retr(0, sd);
+
+ WBUFW(buf,0)=0x106;
+ WBUFL(buf,2) = sd->status.account_id;
+ if( sd->battle_status.max_hp > SHRT_MAX )
+ { // To correctly display the %hp bar. [Skotlex]
+ WBUFW(buf,6) = sd->battle_status.hp/(sd->battle_status.max_hp/100);
+ WBUFW(buf,8) = 100;
+ }
+ else
+ {
+ WBUFW(buf,6) = sd->battle_status.hp;
+ WBUFW(buf,8) = sd->battle_status.max_hp;
+ }
+ clif_send(buf, packet_len(0x106), &sd->bl, BG_AREA_WOS);
+ return 0;
+}
+
+int clif_bg_xy(struct map_session_data *sd)
+{
+ unsigned char buf[10];
+ nullpo_retr(0, sd);
+
+ WBUFW(buf,0)=0x1eb;
+ WBUFL(buf,2)=sd->status.account_id;
+ WBUFW(buf,6)=sd->bl.x;
+ WBUFW(buf,8)=sd->bl.y;
+ clif_send(buf, packet_len(0x1eb), &sd->bl, BG_SAMEMAP_WOS);
+ return 0;
+}
+
+int clif_bg_xy_remove(struct map_session_data *sd)
+{
+ unsigned char buf[10];
+ nullpo_retr(0, sd);
+
+ WBUFW(buf,0)=0x1eb;
+ WBUFL(buf,2)=sd->status.account_id;
+ WBUFW(buf,6)=-1;
+ WBUFW(buf,8)=-1;
+ clif_send(buf,packet_len(0x1eb),&sd->bl,BG_SAMEMAP_WOS);
+ return 0;
+}
+
+int clif_bg_belonginfo(struct map_session_data *sd)
+{
+ int fd;
+ struct guild *g;
+ nullpo_retr(0, sd);
+
+ if( !sd->state.bg_id || (g = bg_guild_get(sd->state.bg_id)) == NULL )
+ return 0;
+
+ fd = sd->fd;
+ WFIFOHEAD(fd,packet_len(0x16c));
+ memset(WFIFOP(fd,0),0,packet_len(0x16c));
+ WFIFOW(fd,0) = 0x16c;
+ WFIFOL(fd,2) = g->guild_id;
+ WFIFOL(fd,6) = g->emblem_id;
+ WFIFOL(fd,10) = 0;
+ memcpy(WFIFOP(fd,19), g->name, NAME_LENGTH);
+ WFIFOSET(fd,packet_len(0x16c));
+ return 1;
+}
+
+int clif_bg_guild_id(struct block_list *bl)
+{
+ struct battleground_data *bg;
+ int bg_id;
+ nullpo_retr(0, bl);
+
+ if( (bg_id = bg_team_get_id(bl)) > 0 && (bg = bg_team_search(bg_id)) != NULL && bg->g )
+ return bg->g->guild_id;
+ else
+ return status_get_guild_id(bl);
+}
+
+int clif_bg_emblem_id(struct block_list *bl)
+{
+ struct battleground_data *bg;
+ int bg_id;
+ nullpo_retr(0, bl);
+
+ if( (bg_id = bg_team_get_id(bl)) > 0 && (bg = bg_team_search(bg_id)) != NULL && bg->g )
+ return bg->g->emblem_id;
+ else
+ return status_get_emblem_id(bl);
+}
+
+int clif_bg_emblem(struct map_session_data *sd, struct guild *g)
+{
+ int fd;
+
+ nullpo_retr(0, sd);
+ nullpo_retr(0, g);
+ fd = sd->fd;
+
+ if( g->emblem_len <= 0 )
+ return 0;
+
+ WFIFOHEAD(fd,g->emblem_len+12);
+ WFIFOW(fd,0)=0x152;
+ WFIFOW(fd,2)=g->emblem_len+12;
+ WFIFOL(fd,4)=g->guild_id;
+ WFIFOL(fd,8)=g->emblem_id;
+ memcpy(WFIFOP(fd,12),g->emblem_data,g->emblem_len);
+ WFIFOSET(fd,WFIFOW(fd,2));
+ return 0;
+}
+
+int clif_bg_memberlist(struct map_session_data *sd)
+{
+ int fd, i, c;
+ struct battleground_data *bg;
+ struct map_session_data *psd;
+ nullpo_retr(0, sd);
+
+ if( (fd = sd->fd) == 0 )
+ return 0;
+ if( !sd->state.bg_id || (bg = bg_team_search(sd->state.bg_id)) == NULL )
+ return 0;
+
+ WFIFOHEAD(fd,bg->count * 104 + 4);
+ WFIFOW(fd,0) = 0x154;
+ for( i = 0, c = 0; i < bg->count; i++ )
+ {
+ if( (psd = bg->members[i].sd) == NULL )
+ continue;
+ WFIFOL(fd,c*104+ 4) = psd->status.account_id;
+ WFIFOL(fd,c*104+ 8) = psd->status.char_id;
+ WFIFOW(fd,c*104+12) = psd->status.hair;
+ WFIFOW(fd,c*104+14) = psd->status.hair_color;
+ WFIFOW(fd,c*104+16) = psd->status.sex;
+ WFIFOW(fd,c*104+18) = psd->status.class_;
+ WFIFOW(fd,c*104+20) = psd->status.base_level;
+ WFIFOL(fd,c*104+22) = 0;
+ WFIFOL(fd,c*104+26) = 1;
+ WFIFOL(fd,c*104+30) = c;
+ memset(WFIFOP(fd,c*104+34),0,50);
+ memcpy(WFIFOP(fd,c*104+84),psd->status.name,NAME_LENGTH);
+ c++;
+ }
+ WFIFOW(fd, 2)=c*104+4;
+ WFIFOSET(fd,WFIFOW(fd,2));
+ return 0;
+}
+
+int clif_bg_leave(struct map_session_data *sd, const char *name, const char *mes)
+{
+ unsigned char buf[128];
+ nullpo_retr(0, sd);
+
+ WBUFW(buf,0)=0x15a;
+ memcpy(WBUFP(buf, 2),name,NAME_LENGTH);
+ memcpy(WBUFP(buf,26),mes,40);
+ clif_send(buf,packet_len(0x15a),&sd->bl,BG);
+ return 0;
+}
+
+int clif_bg_leave_single(struct map_session_data *sd, const char *name, const char *mes)
+{
+ int fd;
+ nullpo_retr(0, sd);
+
+ fd = sd->fd;
+ WFIFOHEAD(fd,66);
+ WFIFOW(fd,0) = 0x15a;
+ memcpy(WFIFOP(fd,2), name, NAME_LENGTH);
+ memcpy(WFIFOP(fd,26), mes, 40);
+ WFIFOSET(fd,66);
+ return 0;
+}
+
+int clif_bg_message(struct battleground_data *bg, int account_id, const char *mes, int len)
+{
+ struct map_session_data *sd;
+ unsigned char *buf;
+
+ buf = (unsigned char*)aMallocA((len + 4)*sizeof(unsigned char));
+
+ WBUFW(buf, 0) = 0x17f;
+ WBUFW(buf, 2) = len + 4;
+ memcpy(WBUFP(buf,4), mes, len);
+
+ if( (sd = bg_getavailablesd(bg)) != NULL )
+ clif_send(buf, WBUFW(buf,2), &sd->bl, BG);
+ if( buf ) aFree(buf);
+ return 0;
+}
+
+int clif_bg_expulsion_single(struct map_session_data *sd, const char *name, const char *mes)
+{
+ int fd;
+ nullpo_retr(0, sd);
+
+ fd = sd->fd;
+ WFIFOHEAD(fd, 90);
+ WFIFOW(fd,0) = 0x15c;
+ safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH);
+ safestrncpy((char*)WFIFOP(fd,26), mes, 40);
+ safestrncpy((char*)WFIFOP(fd,66), "", NAME_LENGTH);
+ WFIFOSET(fd,90);
+ return 0;
+}
+
/*==========================================
* パケットデバッグ
*------------------------------------------*/
diff --git a/src/map/clif.h b/src/map/clif.h
index b64d94b48..87c6a2953 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -23,6 +23,7 @@ struct s_vending;
struct party;
struct party_data;
struct guild;
+struct battleground_data;
struct quest;
#include <stdarg.h>
@@ -90,10 +91,17 @@ typedef enum send_target {
GUILD_SAMEMAP_WOS,
GUILD_AREA,
GUILD_AREA_WOS,
+ GUILD_NOBG,
DUEL,
DUEL_WOS,
CHAT_MAINCHAT, // everyone on main chat
SELF,
+ BG, // BattleGround System
+ BG_WOS,
+ BG_SAMEMAP,
+ BG_SAMEMAP_WOS,
+ BG_AREA,
+ BG_AREA_WOS,
} send_target;
int clif_setip(const char* ip);
@@ -330,6 +338,19 @@ int clif_guild_xy(struct map_session_data *sd);
int clif_guild_xy_single(int fd, struct map_session_data *sd);
int clif_guild_xy_remove(struct map_session_data *sd);
+// Battleground
+int clif_bg_hp(struct map_session_data *sd);
+int clif_bg_xy(struct map_session_data *sd);
+int clif_bg_xy_remove(struct map_session_data *sd);
+int clif_bg_belonginfo(struct map_session_data *sd);
+int clif_bg_guild_id(struct block_list *bl);
+int clif_bg_emblem_id(struct block_list *bl);
+int clif_bg_emblem(struct map_session_data *sd, struct guild *g);
+int clif_bg_memberlist(struct map_session_data *sd);
+int clif_bg_leave(struct map_session_data *sd, const char *name, const char *mes);
+int clif_bg_leave_single(struct map_session_data *sd, const char *name, const char *mes);
+int clif_bg_message(struct battleground_data *bg, int account_id, const char *mes, int len);
+int clif_bg_expulsion_single(struct map_session_data *sd, const char *name, const char *mes);
// atcommand
int clif_displaymessage(const int fd,const char* mes);
diff --git a/src/map/guild.c b/src/map/guild.c
index 8f9137943..5296f5970 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -373,12 +373,11 @@ int guild_send_xy_timer_sub(DBKey key,void *data,va_list ap)
for(i=0;i<g->max_member;i++){
//struct map_session_data* sd = g->member[i].sd;
struct map_session_data* sd = map_charid2sd(g->member[i].char_id); // temporary crashfix
- if( sd != NULL ) {
- if(sd->guild_x!=sd->bl.x || sd->guild_y!=sd->bl.y){
- clif_guild_xy(sd);
- sd->guild_x=sd->bl.x;
- sd->guild_y=sd->bl.y;
- }
+ if( sd != NULL && (sd->guild_x != sd->bl.x || sd->guild_y != sd->bl.y) && !sd->state.bg_id )
+ {
+ clif_guild_xy(sd);
+ sd->guild_x = sd->bl.x;
+ sd->guild_y = sd->bl.y;
}
}
return 0;
diff --git a/src/map/map.c b/src/map/map.c
index 5dbdaae04..f80b9c226 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -31,6 +31,7 @@
#include "party.h"
#include "unit.h"
#include "battle.h"
+#include "battleground.h"
#include "script.h"
#include "mapreg.h"
#include "guild.h"
@@ -1514,6 +1515,8 @@ int map_quit(struct map_session_data *sd)
if (sd->npc_timer_id != -1) //Cancel the event timer.
npc_timerevent_quit(sd);
+ if( sd->state.bg_id )
+ bg_team_leave(sd,1);
npc_script_event(sd, NPCE_LOGOUT);
//Unit_free handles clearing the player related data,
@@ -3272,6 +3275,7 @@ void do_final(void)
do_final_skill();
do_final_status();
do_final_unit();
+ do_final_battleground();
map_db->destroy(map_db, map_db_final);
@@ -3504,6 +3508,7 @@ int do_init(int argc, char *argv[])
do_init_mercenary();
do_init_npc();
do_init_unit();
+ do_init_battleground();
#ifndef TXT_ONLY /* mail system [Valaris] */
if (log_config.sql_logs)
log_sql_init();
diff --git a/src/map/map.h b/src/map/map.h
index 02314318e..8fcfc6195 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -157,13 +157,13 @@ enum {
#define DEFAULT_AUTOSAVE_INTERVAL 5*60*1000
//Specifies maps where players may hit each other
-#define map_flag_vs(m) (map[m].flag.pvp || map[m].flag.gvg_dungeon || map[m].flag.gvg || ((agit_flag || agit2_flag) && map[m].flag.gvg_castle))
+#define map_flag_vs(m) (map[m].flag.pvp || map[m].flag.gvg_dungeon || map[m].flag.gvg || ((agit_flag || agit2_flag) && map[m].flag.gvg_castle) || map[m].flag.battleground)
//Specifies maps that have special GvG/WoE restrictions
#define map_flag_gvg(m) (map[m].flag.gvg || ((agit_flag || agit2_flag) && map[m].flag.gvg_castle))
//Specifies if the map is tagged as GvG/WoE (regardless of agit_flag status)
#define map_flag_gvg2(m) (map[m].flag.gvg || map[m].flag.gvg_castle)
// No Kill Steal Protection
-#define map_flag_ks(m) (map[m].flag.town || map[m].flag.pvp || map[m].flag.gvg)
+#define map_flag_ks(m) (map[m].flag.town || map[m].flag.pvp || map[m].flag.gvg || map[m].flag.battleground)
//This stackable implementation does not means a BL can be more than one type at a time, but it's
//meant to make it easier to check for multiple types at a time on invocations such as map_foreach* calls [Skotlex]
@@ -434,6 +434,7 @@ struct map_data {
unsigned gvg : 1; // Now it identifies gvg versus maps that are active 24/7
unsigned gvg_dungeon : 1; // Celest
unsigned gvg_noparty : 1;
+ unsigned battleground : 1; // [BattleGround System]
unsigned nozenypenalty : 1;
unsigned notrade : 1;
unsigned noskill : 1;
diff --git a/src/map/mob.c b/src/map/mob.c
index 2691dc45f..634df71ab 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -662,6 +662,51 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam
}
/*==========================================
+ * Summoning BattleGround [Zephyrus]
+ *------------------------------------------*/
+int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int bg_id)
+{
+ struct mob_data *md = NULL;
+ struct spawn_data data;
+ int m;
+
+ if( (m = map_mapname2mapid(mapname)) < 0 )
+ {
+ ShowWarning("mob_spawn_bg: Map [%s] not found.\n", mapname);
+ return 0;
+ }
+
+ memset(&data, 0, sizeof(struct spawn_data));
+ data.m = m;
+ data.num = 1;
+ if( class_ <= 0 )
+ {
+ class_ = mob_get_random_id(-class_-1,1,99);
+ if( !class_ ) return 0;
+ }
+
+ data.class_ = class_;
+ if( (x <= 0 || y <= 0) && !map_search_freecell(NULL, m, &x, &y, -1,-1, 0) )
+ {
+ ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %d) at map %s\n",class_, bg_id, map[m].name);
+ return 0;
+ }
+
+ data.x = x;
+ data.y = y;
+ safestrncpy(data.name, mobname, sizeof(data.name));
+ safestrncpy(data.eventname, event, sizeof(data.eventname));
+ if( !mob_parse_dataset(&data) )
+ return 0;
+
+ md = mob_spawn_dataset(&data);
+ mob_spawn(md);
+ md->state.bg_id = bg_id; // BG Team ID
+
+ return md->bl.id;
+}
+
+/*==========================================
* Reachability to a Specification ID existence place
* state indicates type of 'seek' mob should do:
* - MSS_LOOT: Looking for item, path must be easy.
diff --git a/src/map/mob.h b/src/map/mob.h
index bef8324d4..472e0bc54 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -112,6 +112,8 @@ struct mob_data {
int provoke_flag; // Celest
unsigned npc_killmonster: 1; //for new killmonster behavior
unsigned rebirth: 1; // NPC_Rebirth used
+ unsigned inmunity: 1; // Monster Cannot be attacked
+ unsigned int bg_id; // BattleGround System
} state;
struct guardian_data* guardian_data;
struct {
@@ -208,6 +210,7 @@ int mob_once_spawn_area(struct map_session_data* sd,int m,int x0,int y0,int x1,i
bool mob_ksprotected (struct block_list *src, struct block_list *target);
int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int guardian, bool has_index); // Spawning Guardians [Valaris]
+int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int bg_id);
int mob_guardian_guildchange(struct block_list *bl,va_list ap); //Change Guardian's ownership. [Skotlex]
int mob_randomwalk(struct mob_data *md,unsigned int tick);
@@ -227,6 +230,7 @@ void mob_heal(struct mob_data *md,unsigned int heal);
#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)) )
void mob_clear_spawninfo();
int do_init_mob(void);
diff --git a/src/map/npc.c b/src/map/npc.c
index 1014cc832..0a37986c8 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2651,13 +2651,18 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
map[m].flag.nozenypenalty=state;
}
else if (!strcmpi(w3,"pvp")) {
- map[m].flag.pvp=state;
- if (state) {
- if (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle)
- ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
- map[m].flag.gvg=0;
- map[m].flag.gvg_dungeon=0;
- map[m].flag.gvg_castle=0;
+ map[m].flag.pvp = state;
+ if( state && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) )
+ {
+ map[m].flag.gvg = 0;
+ map[m].flag.gvg_dungeon = 0;
+ map[m].flag.gvg_castle = 0;
+ ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+ }
+ if( state && map[m].flag.battleground )
+ {
+ map[m].flag.battleground = 0;
+ ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
}
}
else if (!strcmpi(w3,"pvp_noparty"))
@@ -2697,12 +2702,17 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
else if (!strcmpi(w3,"pvp_nocalcrank"))
map[m].flag.pvp_nocalcrank=state;
else if (!strcmpi(w3,"gvg")) {
- map[m].flag.gvg=state;
- if (state && map[m].flag.pvp)
+ map[m].flag.gvg = state;
+ if( state && map[m].flag.pvp )
{
- map[m].flag.pvp=0;
+ map[m].flag.pvp = 0;
ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
}
+ if( state && map[m].flag.battleground )
+ {
+ map[m].flag.battleground = 0;
+ ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+ }
}
else if (!strcmpi(w3,"gvg_noparty"))
map[m].flag.gvg_noparty=state;
@@ -2714,6 +2724,21 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
map[m].flag.gvg_castle=state;
if (state) map[m].flag.pvp=0;
}
+ else if (!strcmpi(w3,"battleground")) {
+ map[m].flag.battleground = state;
+ if( state && map[m].flag.pvp )
+ {
+ map[m].flag.pvp = 0;
+ ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+ }
+ if( state && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) )
+ {
+ map[m].flag.gvg = 0;
+ map[m].flag.gvg_dungeon = 0;
+ map[m].flag.gvg_castle = 0;
+ ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+ }
+ }
else if (!strcmpi(w3,"noexppenalty"))
map[m].flag.noexppenalty=state;
else if (!strcmpi(w3,"nozenypenalty"))
diff --git a/src/map/pc.c b/src/map/pc.c
index a4ed7a62e..00827a055 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -14,6 +14,7 @@
#include "atcommand.h" // get_atcommand_level()
#include "battle.h" // battle_config
+#include "battleground.h"
#include "chrif.h"
#include "clif.h"
#include "date.h" // is_day_of_*()
@@ -81,6 +82,28 @@ int pc_class2idx(int class_) {
return class_;
}
+void pc_update_last_action(struct map_session_data *sd)
+{
+ struct battleground_data *bg;
+ int i;
+
+ sd->idletime = last_tick;
+ if( sd->state.bg_id && (bg = bg_team_search(sd->state.bg_id)) != NULL )
+ { // Update Battleground Idle Timer
+ ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == sd);
+ if( i == MAX_BG_MEMBERS)
+ return;
+
+ if( bg->members[i].afk && bg->g )
+ {
+ char output[128];
+ sprintf(output, "%s : %s is no longer away...", bg->g->name, sd->status.name);
+ clif_bg_message(bg, 0, output, strlen(output));
+ bg->members[i].afk = 0;
+ }
+ }
+}
+
int pc_isGM(struct map_session_data* sd)
{
return sd->gmlevel;
@@ -3740,6 +3763,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
skill_clear_unitgroup(&sd->bl);
party_send_dot_remove(sd); //minimap dot fix [Kevin]
guild_send_dot_remove(sd);
+ bg_send_dot_remove(sd);
if (sd->regen.state.gc)
sd->regen.state.gc = 0;
}
@@ -5139,10 +5163,12 @@ void pc_respawn(struct map_session_data* sd, uint8 clrtype)
{
if( !pc_isdead(sd) )
return; // not applicable
+ if( sd->state.bg_id && bg_member_respawn(sd) )
+ return; // member revived by battleground
pc_setstand(sd);
pc_setrestartvalue(sd,3);
- if(pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype))
+ if( pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype) )
clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
}
@@ -5231,6 +5257,13 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
pc_setglobalreg(sd,"PC_DIE_COUNTER",sd->die_counter+1);
pc_setglobalreg(sd,"killerrid",src?src->id:0);
+ if( sd->state.bg_id )
+ {
+ struct battleground_data *bg;
+ if( (bg = bg_team_search(sd->state.bg_id)) != NULL && bg->die_event[0] )
+ npc_event(sd, bg->die_event, 0);
+ }
+
npc_script_event(sd,NPCE_DIE);
if ( sd && sd->spiritball && (sd->class_&MAPID_BASEMASK)==MAPID_GUNSLINGER ) // maybe also monks' spiritballs ?
@@ -5436,30 +5469,42 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
}
// pvp
// disable certain pvp functions on pk_mode [Valaris]
- if (map[sd->bl.m].flag.gvg_dungeon ||
- (map[sd->bl.m].flag.pvp && !battle_config.pk_mode && !map[sd->bl.m].flag.pvp_nocalcrank))
- { //Pvp points always take effect on gvg_dungeon maps.
+ if( map[sd->bl.m].flag.gvg_dungeon || (map[sd->bl.m].flag.pvp && !battle_config.pk_mode && !map[sd->bl.m].flag.pvp_nocalcrank) )
+ { // Pvp points always take effect on gvg_dungeon maps.
sd->pvp_point -= 5;
sd->pvp_lost++;
- if (src && src->type == BL_PC) {
+ if( src && src->type == BL_PC )
+ {
struct map_session_data *ssd = (struct map_session_data *)src;
ssd->pvp_point++;
ssd->pvp_won++;
}
- if( sd->pvp_point < 0 ){
+ if( sd->pvp_point < 0 )
+ {
sd->pvp_point=0;
add_timer(tick+1000, pc_respawn_timer,sd->bl.id,0);
return 1|8;
}
}
//GvG
- if(map_flag_gvg(sd->bl.m)){
- add_timer(tick+1000, pc_respawn_timer,sd->bl.id,0);
+ if( map_flag_gvg(sd->bl.m) )
+ {
+ add_timer(tick+1000, pc_respawn_timer, sd->bl.id, 0);
return 1|8;
}
+ else if( sd->state.bg_id )
+ {
+ struct battleground_data *bg = bg_team_search(sd->state.bg_id);
+ if( bg && bg->mapindex > 0 )
+ { // Respawn by BG
+ add_timer(tick+1000, pc_respawn_timer, sd->bl.id, 0);
+ return 1|8;
+ }
+ }
+
//Reset "can log out" tick.
- if (battle_config.prevent_logout)
+ if( battle_config.prevent_logout )
sd->canlog_tick = gettick() - battle_config.prevent_logout;
return 1;
}
diff --git a/src/map/pc.h b/src/map/pc.h
index a22f0c5ad..e04038943 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -115,6 +115,7 @@ struct map_session_data {
unsigned noks : 3; // [Zeph Kill Steal Protection]
bool changemap;
struct guild *gmaster_flag;
+ unsigned int bg_id;
} state;
struct {
unsigned char no_weapon_damage, no_magic_damage, no_misc_damage;
@@ -715,6 +716,8 @@ extern int night_timer_tid;
int map_day_timer(int tid, unsigned int tick, int id, intptr data); // by [yor]
int map_night_timer(int tid, unsigned int tick, int id, intptr data); // by [yor]
+void pc_update_last_action(struct map_session_data *sd);
+
// Rental System
void pc_inventory_rentals(struct map_session_data *sd);
int pc_inventory_rental_clear(struct map_session_data *sd);
diff --git a/src/map/script.c b/src/map/script.c
index 05779ed9e..f69dc2665 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -35,6 +35,7 @@
#include "status.h"
#include "chat.h"
#include "battle.h"
+#include "battleground.h"
#include "party.h"
#include "guild.h"
#include "atcommand.h"
@@ -4066,6 +4067,38 @@ BUILDIN_FUNC(areawarp)
}
/*==========================================
+ * areapercentheal <map>,<x1>,<y1>,<x2>,<y2>,<hp>,<sp>
+ *------------------------------------------*/
+static int buildin_areapercentheal_sub(struct block_list *bl,va_list ap)
+{
+ int hp, sp;
+ hp = va_arg(ap, int);
+ sp = va_arg(ap, int);
+ pc_percentheal((TBL_PC *)bl,hp,sp);
+ return 0;
+}
+BUILDIN_FUNC(areapercentheal)
+{
+ int hp,sp,m;
+ const char *mapname;
+ int x0,y0,x1,y1;
+
+ mapname=script_getstr(st,2);
+ x0=script_getnum(st,3);
+ y0=script_getnum(st,4);
+ x1=script_getnum(st,5);
+ y1=script_getnum(st,6);
+ hp=script_getnum(st,8);
+ sp=script_getnum(st,9);
+
+ if( (m=map_mapname2mapid(mapname))< 0)
+ return 0;
+
+ map_foreachinarea(buildin_areapercentheal_sub,m,x0,y0,x1,y1,BL_PC,hp,sp);
+ return 0;
+}
+
+/*==========================================
* warpchar [LuzZza]
* Useful for warp one player from
* another player npc-session.
@@ -5782,6 +5815,7 @@ BUILDIN_FUNC(getcharid)
case 1: script_pushint(st,sd->status.party_id); break;
case 2: script_pushint(st,sd->status.guild_id); break;
case 3: script_pushint(st,sd->status.account_id); break;
+ case 4: script_pushint(st,sd->state.bg_id); break;
default:
ShowError("buildin_getcharid: invalid parameter (%d).\n", num);
script_pushint(st,0);
@@ -13277,6 +13311,228 @@ BUILDIN_FUNC(setqueststatus)
return 0;
}
+/*==========================================
+ * BattleGround System
+ *------------------------------------------*/
+BUILDIN_FUNC(waitingroom2bg)
+{
+ struct npc_data *nd;
+ struct chat_data *cd;
+ const char *map_name, *ev = "", *dev = "";
+ int x, y, i, mapindex = 0, guild_index, bg_id, n;
+ struct map_session_data *sd;
+
+ if( script_hasdata(st,8) )
+ nd = npc_name2id(script_getstr(st,8));
+ else
+ nd = (struct npc_data *)map_id2bl(st->oid);
+
+ if( nd == NULL || (cd = (struct chat_data *)map_id2bl(nd->chat_id)) == NULL )
+ {
+ script_pushint(st,0);
+ return 0;
+ }
+
+ map_name = script_getstr(st,2);
+ if( strcmp(map_name,"-") != 0 )
+ {
+ mapindex = mapindex_name2id(map_name);
+ if( mapindex == 0 )
+ { // Invalid Map
+ script_pushint(st,0);
+ return 0;
+ }
+ }
+
+ x = script_getnum(st,3);
+ y = script_getnum(st,4);
+ guild_index = script_getnum(st,5);
+ ev = script_getstr(st,6); // Logout Event
+ dev = script_getstr(st,7); // Die Event
+
+ guild_index = cap_value(guild_index, 0, 1);
+ if( (bg_id = bg_create(mapindex, x, y, guild_index, ev, dev)) == 0 )
+ { // Creation failed
+ script_pushint(st,0);
+ return 0;
+ }
+
+ n = cd->users;
+ for( i = 0; i < n && i < MAX_BG_MEMBERS; i++ )
+ {
+ if( (sd = cd->usersd[i]) != NULL && bg_team_join(bg_id, sd) )
+ mapreg_setreg(add_str("$@arenamembers") + (i<<24), sd->bl.id);
+ else
+ mapreg_setreg(add_str("$@arenamembers") + (i<<24), 0);
+ }
+
+ mapreg_setreg(add_str("$@arenamembersnum"), i);
+ script_pushint(st,bg_id);
+ return 0;
+}
+
+BUILDIN_FUNC(waitingroom2bg_single)
+{
+ const char* map_name;
+ struct npc_data *nd;
+ struct chat_data *cd;
+ struct map_session_data *sd;
+ int x, y, mapindex, bg_id;
+
+ bg_id = script_getnum(st,2);
+ map_name = script_getstr(st,3);
+ if( (mapindex = mapindex_name2id(map_name)) == 0 )
+ return 0; // Invalid Map
+
+ x = script_getnum(st,4);
+ y = script_getnum(st,5);
+ nd = npc_name2id(script_getstr(st,6));
+
+ if( nd == NULL || (cd = (struct chat_data *)map_id2bl(nd->chat_id)) == NULL || cd->users <= 0 )
+ return 0;
+
+ if( (sd = cd->usersd[0]) == NULL )
+ return 0;
+
+ if( bg_team_join(bg_id, sd) )
+ {
+ pc_setpos(sd, mapindex, x, y, 3);
+ script_pushint(st,1);
+ }
+ else
+ script_pushint(st,0);
+
+ return 0;
+}
+
+BUILDIN_FUNC(bg_warp)
+{
+ int x, y, mapindex, bg_id;
+ const char* map_name;
+
+ bg_id = script_getnum(st,2);
+ map_name = script_getstr(st,3);
+ if( (mapindex = mapindex_name2id(map_name)) == 0 )
+ return 0; // Invalid Map
+ x = script_getnum(st,4);
+ y = script_getnum(st,5);
+ bg_team_warp(bg_id, mapindex, x, y);
+ return 0;
+}
+
+BUILDIN_FUNC(bg_monster)
+{
+ int class_ = 0, x = 0, y = 0, bg_id = 0;
+ const char *str,*map, *evt="";
+
+ bg_id = script_getnum(st,2);
+ map = script_getstr(st,3);
+ x = script_getnum(st,4);
+ y = script_getnum(st,5);
+ str = script_getstr(st,6);
+ class_ = script_getnum(st,7);
+ if( script_hasdata(st,8) ) evt = script_getstr(st,8);
+ check_event(st, evt);
+ script_pushint(st, mob_spawn_bg(map,x,y,str,class_,evt,bg_id));
+ return 0;
+}
+
+BUILDIN_FUNC(setmobdata)
+{
+ struct mob_data *md;
+ struct block_list *mbl;
+ int id = script_getnum(st,2),
+ type = script_getnum(st,3),
+ value = script_getnum(st,4);
+
+ if( (mbl = map_id2bl(id)) == NULL || mbl->type != BL_MOB )
+ return 0;
+ md = (TBL_MOB *)mbl;
+ switch( type )
+ {
+ case 0: md->state.inmunity = value > 0 ? 1 : 0; break;
+ default:
+ ShowError("script:setmobdata: unknown data identifier %d\n", type);
+ return 1;
+ }
+
+ return 0;
+}
+
+BUILDIN_FUNC(bg_leave)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if( sd == NULL || !sd->state.bg_id )
+ return 0;
+
+ bg_team_leave(sd,0);
+ return 0;
+}
+
+BUILDIN_FUNC(bg_destroy)
+{
+ int bg_id = script_getnum(st,2);
+ bg_team_delete(bg_id);
+ return 0;
+}
+
+BUILDIN_FUNC(bg_getareausers)
+{
+ const char *str;
+ int m, x0, y0, x1, y1, bg_id;
+ int i = 0, c = 0;
+ struct battleground_data *bg = NULL;
+ struct map_session_data *sd;
+
+ bg_id = script_getnum(st,2);
+ str = script_getstr(st,3);
+
+ if( (bg = bg_team_search(bg_id)) == NULL || (m = map_mapname2mapid(str)) < 0 )
+ {
+ script_pushint(st,0);
+ return 0;
+ }
+
+ x0 = script_getnum(st,4);
+ y0 = script_getnum(st,5);
+ x1 = script_getnum(st,6);
+ y1 = script_getnum(st,7);
+
+ for( i = 0; i < MAX_BG_MEMBERS; i++ )
+ {
+ if( (sd = bg->members[i].sd) == NULL )
+ continue;
+ if( sd->bl.m != m || sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1 )
+ continue;
+ c++;
+ }
+
+ script_pushint(st,c);
+ return 0;
+}
+
+BUILDIN_FUNC(bg_get_data)
+{
+ struct battleground_data *bg;
+ int bg_id = script_getnum(st,2),
+ type = script_getnum(st,3);
+
+ if( (bg = bg_team_search(bg_id)) == NULL )
+ {
+ script_pushint(st,0);
+ return 0;
+ }
+
+ switch( type )
+ {
+ case 0: script_pushint(st, bg->count); break;
+ default:
+ ShowError("script:bg_get_data: unknown data identifier %d\n", type);
+ break;
+ }
+
+ return 0;
+}
// declarations that were supposed to be exported from npc_chat.c
#ifdef PCRE_SUPPORT
@@ -13637,5 +13893,16 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(agitstart2,""),
BUILDIN_DEF(agitend2,""),
BUILDIN_DEF(agitcheck2,""),
+ // BattleGround
+ BUILDIN_DEF(waitingroom2bg,"siiiss?"),
+ BUILDIN_DEF(waitingroom2bg_single,"isiis"),
+ BUILDIN_DEF(bg_warp,"isii"),
+ BUILDIN_DEF(bg_monster,"isiisi*"),
+ BUILDIN_DEF(bg_leave,""),
+ BUILDIN_DEF(bg_destroy,"i"),
+ BUILDIN_DEF(areapercentheal,"siiiiii"),
+ BUILDIN_DEF(setmobdata,"iii"),
+ BUILDIN_DEF(bg_get_data,"ii"),
+ BUILDIN_DEF(bg_getareausers,"isiiii"),
{NULL,NULL,NULL},
};
diff --git a/src/map/skill.c b/src/map/skill.c
index a1fe80c06..95783ed5e 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -22,6 +22,7 @@
#include "mob.h"
#include "npc.h"
#include "battle.h"
+#include "battleground.h"
#include "party.h"
#include "itemdb.h"
#include "script.h"
@@ -347,7 +348,7 @@ int skillnotok (int skillid, struct map_session_data *sd)
return 1;
if(map_flag_gvg(m) && skill_get_nocast (skillid) & 4)
return 1;
- if((agit_flag || agit2_flag) && skill_get_nocast (skillid) & 8)
+ if(map[m].flag.battleground && skill_get_nocast (skillid) & 8)
return 1;
if(map[m].flag.restricted && map[m].zone && skill_get_nocast (skillid) & (8*map[m].zone))
return 1;
@@ -1278,7 +1279,7 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in
nullpo_retr(0, src);
- if (src != target && map_flag_gvg(target->m))
+ if (src != target && (map_flag_gvg(target->m) || map[target->m].flag.battleground))
return 0; //No knocking back in WoE
if (count == 0)
return 0; //Actual knockback distance is 0.
@@ -2417,7 +2418,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
unsigned int dir = map_calc_dir(bl, src->x, src->y);
// teleport to target (if not on WoE grounds)
- if( !map_flag_gvg(src->m) && unit_movepos(src, bl->x, bl->y, 0, 1) )
+ if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 0, 1) )
clif_slide(src, bl->x, bl->y);
// cause damage and knockback if the path to target was a straight one
@@ -2847,7 +2848,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
sc_start(src,SC_HIDING,100,skilllv,skill_get_time(skillid,skilllv));
break;
case NJ_KIRIKAGE:
- if (!map_flag_gvg(src->m))
+ if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground )
{ //You don't move on GVG grounds.
short x, y;
map_search_freecell(bl, 0, &x, &y, 1, 1, 0);
@@ -2980,8 +2981,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
int heal = skill_calc_heal(src, bl, skilllv);
int heal_get_jobexp;
- if( status_isimmune(bl) || (dstmd && dstmd->class_ == MOBID_EMPERIUM) )
+ if( status_isimmune(bl) )
heal=0;
+ if( dstmd && (dstmd->class_ == MOBID_EMPERIUM || mob_is_battleground(dstmd)) )
+ heal=0; // Emperium - BattleGround Mobs cannot be Healed
if( sd )
{
if( (i = pc_skillheal_bonus(sd, skillid)) )
@@ -3053,7 +3056,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
break;
case ALL_RESURRECTION:
- if(sd && map_flag_gvg(bl->m))
+ if(sd && (map_flag_gvg(bl->m) || map[bl->m].flag.battleground))
{ //No reviving in WoE grounds!
clif_skill_fail(sd,skillid,0,0);
break;
@@ -5018,8 +5021,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case CG_TAROTCARD:
{
int eff, count = -1;
- if (rand() % 100 > skilllv * 8) {
- if (sd) clif_skill_fail(sd,skillid,0,0);
+ if( rand() % 100 > skilllv * 8 || (dstmd && ((dstmd->guardian_data && dstmd->class_ == MOBID_EMPERIUM) || mob_is_battleground(dstmd))) )
+ {
+ if( sd )
+ clif_skill_fail(sd,skillid,0,0);
+
map_freeblock_unlock();
return 0;
}
@@ -5980,7 +5986,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
break;
case NJ_SHADOWJUMP:
{
- if (!map_flag_gvg(src->m))
+ if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground )
{ //You don't move on GVG grounds.
unit_movepos(src, x, y, 1, 0);
clif_slide(src,x,y);
@@ -6479,7 +6485,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
case HT_FREEZINGTRAP:
case MA_FREEZINGTRAP:
case HT_BLASTMINE:
- if( map_flag_gvg(src->m) )
+ if( map_flag_gvg(src->m) || map[src->m].flag.battleground )
limit *= 4; // longer trap times in WOE [celest]
if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) )
target = BCT_ALL;
@@ -7015,6 +7021,9 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
else
{
int heal = sg->val2;
+ struct mob_data *md = BL_CAST(BL_MOB, bl);
+ if( md && mob_is_battleground(md) )
+ break;
if( tstatus->hp >= tstatus->max_hp )
break;
if( tsc )
@@ -8629,7 +8638,7 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv)
time /=2;
break;
case AS_SONICBLOW:
- if (!map_flag_gvg(bl->m) && sc->data[SC_SPIRIT]->val2 == SL_ASSASIN)
+ if (!map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && sc->data[SC_SPIRIT]->val2 == SL_ASSASIN)
time /= 2;
break;
}
@@ -9668,6 +9677,7 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count,
group->src_id = src->id;
group->party_id = status_get_party_id(src);
group->guild_id = status_get_guild_id(src);
+ group->bg_id = bg_team_get_id(src);
group->group_id = skill_get_new_group_id();
group->unit = (struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
group->unit_count = count;
diff --git a/src/map/skill.h b/src/map/skill.h
index cb7656878..6d32e449b 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -125,6 +125,7 @@ struct skill_unit_group {
int src_id;
int party_id;
int guild_id;
+ int bg_id;
int map;
int target_flag; //Holds BCT_* flag for battle_check_target
int bl_flag; //Holds BL_* flag for map_foreachin* functions
diff --git a/src/map/status.c b/src/map/status.c
index f7da7d505..9acc9da02 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -686,8 +686,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
if ((sce=sc->data[SC_ENDURE]) && !sce->val4) {
//Endure count is only reduced by non-players on non-gvg maps.
//val4 signals infinite endure. [Skotlex]
- if (src && src->type != BL_PC && !map_flag_gvg(target->m)
- && --(sce->val2) < 0)
+ if (src && src->type != BL_PC && !map_flag_gvg(target->m) && !map[target->m].flag.battleground && --(sce->val2) < 0)
status_change_end(target, SC_ENDURE, -1);
}
if ((sce=sc->data[SC_GRAVITATION]) && sce->val3 == BCT_SELF)
@@ -3614,8 +3613,13 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change
static signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee)
{
- if (bl->type == BL_PC && map_flag_gvg(bl->m)) //GVG grounds flee penalty, placed here because it's "like" a status change. [Skotlex]
- flee -= flee * battle_config.gvg_flee_penalty/100;
+ if( bl->type == BL_PC )
+ {
+ if( map_flag_gvg(bl->m) )
+ flee -= flee * battle_config.gvg_flee_penalty/100;
+ else if( map[bl->m].flag.battleground )
+ flee -= flee * battle_config.bg_flee_penalty/100;
+ }
if(!sc || !sc->count)
return cap_value(flee,1,SHRT_MAX);
@@ -4025,14 +4029,14 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
static unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion)
{
- if(!sc || !sc->count || map_flag_gvg(bl->m))
+ if( !sc || !sc->count || map_flag_gvg(bl->m) || map[bl->m].flag.battleground )
return cap_value(dmotion,0,USHRT_MAX);
- if (sc->data[SC_ENDURE])
+ if( sc->data[SC_ENDURE] )
return 0;
- if (sc->data[SC_CONCENTRATION])
+ if( sc->data[SC_CONCENTRATION] )
return 0;
- if(sc->data[SC_RUN])
+ if( sc->data[SC_RUN] )
return 0;
return (unsigned short)cap_value(dmotion,0,USHRT_MAX);
@@ -4777,11 +4781,11 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if( status_isdead(bl) )
return 0;
- if( bl->type == BL_MOB )
+ if( bl->type == BL_MOB && type != SC_SAFETYWALL && type != SC_PNEUMA )
{
struct mob_data *md = BL_CAST(BL_MOB,bl);
- if( md->class_ == MOBID_EMPERIUM && type != SC_SAFETYWALL && type != SC_PNEUMA )
- return 0; //Emperium can't be afflicted by status changes
+ if( md->class_ == MOBID_EMPERIUM || mob_is_battleground(md) )
+ return 0; //Emperium/BG Monsters can't be afflicted by status changes
}
sd = BL_CAST(BL_PC, bl);
@@ -5180,7 +5184,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_ENDURE:
val2 = 7; // Hit-count [Celest]
- if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !val4 )
+ if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && !val4 )
{
struct map_session_data *tsd;
if( sd )
@@ -5473,7 +5477,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE)
val3 -= 40;
val4 = 10+val1*2; //SP cost.
- if (map_flag_gvg(bl->m)) val4 *= 5;
+ if (map_flag_gvg(bl->m) || map[bl->m].flag.battleground) val4 *= 5;
break;
case SC_CLOAKING:
if (!sd) //Monsters should be able to walk with no penalties. [Skotlex]
@@ -5772,7 +5776,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
{ // 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)?2:3;
+ int i = (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)?2:3;
while( i >= 0 )
{
type2 = types[i];
diff --git a/src/map/unit.c b/src/map/unit.c
index 7260930fe..dce211fc9 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -20,6 +20,7 @@
#include "guild.h"
#include "status.h"
#include "battle.h"
+#include "battleground.h"
#include "chat.h"
#include "trade.h"
#include "vending.h"
@@ -1585,7 +1586,7 @@ int unit_skillcastcancel(struct block_list *bl,int type)
return 0;
if (sd && (sd->special_state.no_castcancel2 ||
- (sd->special_state.no_castcancel && !map_flag_gvg(bl->m)))) //fixed flags being read the wrong way around [blackhole89]
+ (sd->special_state.no_castcancel && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground))) //fixed flags being read the wrong way around [blackhole89]
return 0;
}
@@ -1792,6 +1793,7 @@ int unit_remove_map_(struct block_list *bl, int clrtype, const char* file, int l
}
party_send_dot_remove(sd);//minimap dot fix [Kevin]
guild_send_dot_remove(sd);
+ bg_send_dot_remove(sd);
if( map[bl->m].users <= 0 || sd->state.debug_remove_map )
{// this is only place where map users is decreased, if the mobs were removed too soon then this function was executed too many times [FlavioJS]