I wanted to tell you that I have a problem trying to implement NAPSTER's PvP cell in my emulator. I have my emulator running stable in the latest master version available about 4 months ago.
the problem is that there are certain differences between my rathena codes and the diff code of the patch.
I have successfully implemented the BGex manually and I had no problems. but this pvp_cell has not succeeded.
I leave the patch that I am trying to put!
conf/battle/misc.conf | 39 +++++++++++++++++++++
conf/msg_conf/map_msg.conf | 4 +++
db/const.txt | 3 ++
src/map/atcommand.c | 8 ++---
src/map/battle.c | 30 ++++++++++++----
src/map/battle.h | 10 +++++-
src/map/clif.c | 8 ++++-
src/map/map.cpp | 46 +++++++++++++++++++++++--
src/map/map.h | 12 +++++--
src/map/pc.c | 86 ++++++++++++++++++++++++++++++++++++++++++----
src/map/pc.h | 2 ++
src/map/script_constants.h | 4 ++-
src/map/skill.c | 3 +-
src/map/unit.c | 47 ++++++++++++++++++++++++-
14 files changed, 274 insertions(+), 28 deletions(-)
diff --git a/conf/battle/misc.conf b/conf/battle/misc.conf
index 7c085fd41..37759b659 100644
--- a/conf/battle/misc.conf
+++ b/conf/battle/misc.conf
@@ -176,3 +176,42 @@ mail_delay: 1000
// Hides items from the player's favorite tab from being sold to a NPC. (Note 1)
hide_fav_sell: no
+
+// Addon Cell PVP [Napster]
+// Enable Deathmatch for cell pvp
+// Default: 0
+// 0 = No
+// 1 = Yes
+cellpvp_deathmatch: 1
+
+// Delay player alive deathmatch for cell pvp
+// Default: 1000 (1 secand)
+cellpvp_deathmatch_delay: 1000
+
+// When player is dead recovery HP/SP Rate for cell pvp
+// Default: 100 (recovery 100%)
+deathmatch_hp_rate: 100
+deathmatch_sp_rate: 100
+
+// Enable buff when player is dead for cell pvp
+// Default: 1
+// 0 = No
+// 1 = Yes
+// Request core npc files use name "deathmatch_core"
+cellpvp_autobuff: yes
+
+// Can atk player in party
+// Default: 1
+// 0 = No
+// 1 = Yes
+cellpvp_party_enable: no
+
+// Can atk player in guild
+// Default: 1
+// 0 = No
+// 1 = Yes
+cellpvp_guild_enable: no
+
+// When player move to cell pvp is delay walk out cooldown
+// Default: 5000 (5 secand)
+cellpvp_walkout_delay: 5000
\ No newline at end of file
diff --git a/conf/msg_conf/map_msg.conf b/conf/msg_conf/map_msg.conf
index 50306ef97..d3afebbc8 100644
--- a/conf/msg_conf/map_msg.conf
+++ b/conf/msg_conf/map_msg.conf
@@ -1664,3 +1664,7 @@
//Custom translations
//import: conf/msg_conf/import/map_msg_eng_conf.txt
+
+// Addon Cell PVP [Napster]
+1599: Walking failed. [%s] is cooling down. Wait %.1f minutes.
+1600: Walking failed. [%s] is cooling down. Wait %d seconds.
\ No newline at end of file
diff --git a/db/const.txt b/db/const.txt
index a10cc018b..46bf071f9 100644
--- a/db/const.txt
+++ b/db/const.txt
@@ -2313,3 +2313,6 @@ ARCWANDCLAN 2
GOLDENMACECLAN 3
CROSSBOWCLAN 4
JUMPINGCLAN 5
+
+CELL_PVP 10
+CELL_CHKPVP 16
\ No newline at end of file
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index d8d52b9cc..c6bd4ce11 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -482,7 +482,7 @@ ACMD_FUNC(mapmove)
clif_displaymessage(fd, msg_txt(sd,247)); // You are not authorized to warp to this map.
return -1;
}
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ if (sd->state.pvp || sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif_displaymessage(fd, msg_txt(sd,248)); // You are not authorized to warp from your current map.
return -1;
}
@@ -830,11 +830,11 @@ ACMD_FUNC(load)
nullpo_retr(-1, sd);
m = map_mapindex2mapid(sd->status.save_point.map);
- if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ if (sd->state.pvp && (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))) {
clif_displaymessage(fd, msg_txt(sd,249)); // You are not authorized to warp to your save map.
return -1;
}
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ if (sd->state.pvp && (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))) {
clif_displaymessage(fd, msg_txt(sd,248)); // You are not authorized to warp from your current map.
return -1;
}
@@ -2054,7 +2054,7 @@ ACMD_FUNC(go)
clif_displaymessage(fd, msg_txt(sd,247)); // You are not authorized to warp to this map.
return -1;
}
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ if (sd->state.pvp || sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif_displaymessage(fd, msg_txt(sd,248)); // You are not authorized to warp from your current map.
return -1;
}
diff --git a/src/map/battle.c b/src/map/battle.c
index e2d616bd9..ef7b5e9cd 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -7767,6 +7767,10 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
else
return 0; // You can't target anything out of your duel
}
+ else if( map_getcell( s_bl->m, s_bl->x, s_bl->y, CELL_CHKPVP ) && map_getcell( t_bl->m, t_bl->x, t_bl->y, CELL_CHKPVP ) ) // Addon Cell PVP [Napster]
+ {
+ state |= BCT_ENEMY;
+ }
}
if( map_flag_gvg(m) && !sd->status.guild_id && t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->mob_id == MOBID_EMPERIUM )
return 0; //If you don't belong to a guild, can't target emperium.
@@ -7868,15 +7872,19 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
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(s_party && s_party == status_get_party_id(t_bl) && !(battle_config.cellpvp_party_enable && map_getcell( t_bl->m, t_bl->x, t_bl->y, CELL_CHKPVP )) ) // Addon Cell PVP [Napster]
+ state |= BCT_PARTY;
+ else
+ 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 || (!(flag&BCT_SAMEGUILD) && guild_isallied(s_guild, t_guild))))
- state |= BCT_GUILD;
+ if(s_guild && t_guild && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild_isallied(s_guild, t_guild))) && !(battle_config.cellpvp_guild_enable && map_getcell( t_bl->m, t_bl->x, t_bl->y, CELL_CHKPVP )) ) // Addon Cell PVP [Napster]
+ state |= BCT_GUILD;
+ else
+ state |= BCT_ENEMY;
}
} //end non pvp/gvg chk rivality
@@ -8419,7 +8427,7 @@ static const struct _battle_data {
{ "change_party_leader_samemap", &battle_config.change_party_leader_samemap, 1, 0, 1, },
{ "dispel_song", &battle_config.dispel_song, 0, 0, 1, },
{ "guild_maprespawn_clones", &battle_config.guild_maprespawn_clones, 0, 0, 1, },
- { "hide_fav_sell", &battle_config.hide_fav_sell, 0, 0, 1, },
+ { "hide_fav_sell", &battle_config.hide_fav_sell, 0, 0, 1, },
{ "mail_daily_count", &battle_config.mail_daily_count, 100, 0, INT32_MAX, },
{ "mail_zeny_fee", &battle_config.mail_zeny_fee, 2, 0, 100, },
{ "mail_attachment_price", &battle_config.mail_attachment_price, 2500, 0, INT32_MAX, },
@@ -8427,10 +8435,20 @@ static const struct _battle_data {
{ "banana_bomb_duration", &battle_config.banana_bomb_duration, 0, 0, UINT16_MAX, },
{ "guild_leaderchange_delay", &battle_config.guild_leaderchange_delay, 1440, 0, INT32_MAX, },
{ "guild_leaderchange_woe", &battle_config.guild_leaderchange_woe, 0, 0, 1, },
- { "guild_alliance_onlygm", &battle_config.guild_alliance_onlygm, 0, 0, 1, },
+ { "guild_alliance_onlygm", &battle_config.guild_alliance_onlygm, 0, 0, 1, },
{ "feature.achievement", &battle_config.feature_achievement, 1, 0, 1, },
{ "allow_bound_sell", &battle_config.allow_bound_sell, 1, 0, 1, },
+ // Addon Cell PVP [Napster]
+ { "cellpvp_deathmatch", &battle_config.cellpvp_deathmatch, 1, 0, 1, },
+ { "cellpvp_deathmatch_delay", &battle_config.cellpvp_deathmatch_delay, 1000, 0,INT_MAX, },
+ { "deathmatch_hp_rate", &battle_config.deathmatch_hp_rate, 0, 0, 100, },
+ { "deathmatch_sp_rate", &battle_config.deathmatch_sp_rate, 0, 0, 100, },
+ { "cellpvp_autobuff", &battle_config.cellpvp_autobuff, 1, 0, 1, },
+ { "cellpvp_party_enable", &battle_config.cellpvp_party_enable, 1, 0, 1, },
+ { "cellpvp_guild_enable", &battle_config.cellpvp_guild_enable, 1, 0, 1, },
+ { "cellpvp_walkout_delay", &battle_config.cellpvp_walkout_delay, 5000, 0,INT_MAX, },
+
#include "../custom/battle_config_init.inc"
};
diff --git a/src/map/battle.h b/src/map/battle.h
index 37c86dfbb..abcb2b4a7 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -632,7 +632,15 @@ extern struct Battle_Config
int guild_alliance_onlygm;
int feature_achievement;
int allow_bound_sell;
-
+ // Addon Cell PVP [Napster]
+ int cellpvp_deathmatch;
+ int cellpvp_deathmatch_delay;
+ int deathmatch_hp_rate;
+ int deathmatch_sp_rate;
+ int cellpvp_autobuff;
+ int cellpvp_party_enable;
+ int cellpvp_guild_enable;
+ int cellpvp_walkout_delay;
#include "../custom/battle_config_struct.inc"
} battle_config;
diff --git a/src/map/clif.c b/src/map/clif.c
index e3d4a5abf..8bf9f93dc 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -10446,7 +10446,13 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
mail_clear(sd);
-
+
+ // Addon Cell PVP [Napster]
+ if( !sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) )
+ map_pvp_area(sd, 1);
+ else if( sd->state.pvp && !map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) )
+ map_pvp_area(sd, 0);
+
/* Guild Aura Init */
if( sd->state.gmaster_flag ) {
guild_guildaura_refresh(sd,GD_LEADERSHIP,guild_checkskill(sd->guild,GD_LEADERSHIP));
diff --git a/src/map/map.cpp b/src/map/map.cpp
index 57486ac58..02013af02 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -115,7 +115,7 @@ static int block_free_count = 0, block_free_lock = 0;
static struct block_list *bl_list[BL_LIST_MAX];
static int bl_list_count = 0;
-#define MAP_MAX_MSG 1550
+#define MAP_MAX_MSG 1601
struct map_data map[MAX_MAP_PER_SERVER];
int map_num = 0;
@@ -2092,7 +2092,10 @@ int map_quit(struct map_session_data *sd) {
if (sd->state.buyingstore)
idb_remove(buyingstore_getdb(), sd->status.char_id);
-
+ // Addon Cell PVP [Napster]
+ if( sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP ) )
+ map_pvp_area(sd, 0);
+
pc_damage_log_clear(sd,0);
party_booking_delete(sd); // Party Booking [Spiria]
pc_makesavestatus(sd);
@@ -3068,7 +3071,8 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk)
return (cell.maelstrom);
case CELL_CHKICEWALL:
return (cell.icewall);
-
+ case CELL_CHKPVP: // Addon Cell PVP [Napster]
+ return (cell.pvp);
// special checks
case CELL_CHKPASS:
#ifdef CELL_NOSTACK
@@ -3122,6 +3126,7 @@ void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag)
case CELL_NOCHAT: map[m].cell[j].nochat = flag; break;
case CELL_MAELSTROM: map[m].cell[j].maelstrom = flag; break;
case CELL_ICEWALL: map[m].cell[j].icewall = flag; break;
+ case CELL_PVP: map[m].cell[j].pvp = flag; break; // Addon Cell PVP [Napster]
default:
ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell);
break;
@@ -4054,6 +4059,41 @@ int inter_config_read(const char *cfgName)
return 0;
}
+// Addon Cell PVP [Napster]
+int map_pvp_area(struct map_session_data* sd, bool flag)
+{
+ switch(flag)
+ {
+ case 1:
+ clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF);
+ if (sd->pvp_timer == INVALID_TIMER) {
+ map[sd->bl.m].cell_pvpuser++;
+
+ sd->pvp_timer = add_timer(gettick()+200, pc_calc_pvprank_timer, sd->bl.id, 0);
+ sd->pvp_rank = 0;
+ sd->pvp_lastusers = 0;
+ sd->pvp_point = 5;
+ sd->pvp_won = 0;
+ sd->pvp_lost = 0;
+ sd->state.pvp = 1;
+ sd->pvpcan_walkout_tick = gettick();
+ }
+ break;
+ default:
+ clif_pvpset(sd, 0, 0, 2);
+ map[sd->bl.m].cell_pvpuser--;
+
+ if( sd->pvp_timer != INVALID_TIMER )
+ delete_timer(sd->pvp_timer, pc_calc_pvprank_timer);
+
+ sd->pvp_timer = INVALID_TIMER;
+ sd->state.pvp = 0;
+ break;
+ }
+
+ return 0;
+}
+
/*=======================================
* MySQL Init
*---------------------------------------*/
diff --git a/src/map/map.h b/src/map/map.h
index fd5a6b046..e6687c1fa 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -521,7 +521,7 @@ typedef enum {
CELL_NOCHAT,
CELL_MAELSTROM,
CELL_ICEWALL,
-
+ CELL_PVP,
} cell_t;
// used by map_getcell()
@@ -545,7 +545,7 @@ typedef enum {
CELL_CHKNOCHAT, // Whether the cell denies Player Chat Window
CELL_CHKMAELSTROM, // Whether the cell has Maelstrom
CELL_CHKICEWALL, // Whether the cell has Ice Wall
-
+ CELL_CHKPVP, // Addon Cell PVP [Napster]
} cell_chk;
struct mapcell
@@ -564,7 +564,8 @@ struct mapcell
novending : 1,
nochat : 1,
maelstrom : 1,
- icewall : 1;
+ icewall : 1,
+ pvp : 1; // Addon Cell PVP [Napster]
#ifdef CELL_NOSTACK
unsigned char cell_bl; //Holds amount of bls in this cell.
@@ -624,6 +625,7 @@ struct map_data {
int npc_num;
int users;
int users_pvp;
+ int cell_pvpuser; // Addon Cell PVP [Napster]
int iwall_num; // Total of invisible walls in this map
struct map_flag {
unsigned town : 1; // [Suggestion to protect Mail System]
@@ -684,6 +686,7 @@ struct map_data {
unsigned gvg_te : 1; // GVG WOE:TE. This was added as purpose to change 'gvg' for GVG TE, so item_noequp, skill_nocast exlude GVG TE maps from 'gvg' (flag &4)
unsigned gvg_te_castle : 1; // GVG WOE:TE Castle
unsigned hidemobhpbar : 1;
+
#ifdef ADJUST_SKILL_DAMAGE
unsigned skill_damage : 1;
#endif
@@ -1006,6 +1009,9 @@ extern char roulette_table[32];
void do_shutdown(void);
+// Addon Cell PVP [Napster]
+int map_pvp_area(struct map_session_data* sd, bool flag);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/map/pc.c b/src/map/pc.c
index 4682102bb..3342c74ce 100755
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -672,8 +672,9 @@ void pc_makesavestatus(struct map_session_data *sd) {
sd->status.last_point.x = sd->bl.x;
sd->status.last_point.y = sd->bl.y;
}
-
- if(map[sd->bl.m].flag.nosave) {
+
+ // Addon Cell PVP [Napster]
+ if(map[sd->bl.m].flag.nosave || map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP ) ) {
struct map_data *m=&map[sd->bl.m];
if(m->save.map)
memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point));
@@ -4826,7 +4827,7 @@ bool pc_isUseitem(struct map_session_data *sd,int n)
case ITEMID_WING_OF_FLY:
case ITEMID_GIANT_FLY_WING:
case ITEMID_N_FLY_WING:
- if( map[sd->bl.m].flag.noteleport || map_flag_gvg2(sd->bl.m) ) {
+ if( map[sd->bl.m].flag.noteleport || map_flag_gvg2(sd->bl.m) || map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP )) {
clif_skill_teleportmessage(sd,0);
return false;
}
@@ -4867,7 +4868,7 @@ bool pc_isUseitem(struct map_session_data *sd,int n)
clif_displaymessage(sd->fd, msg_txt(sd,663));
return false;
}
- if( map[sd->bl.m].flag.noreturn && nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && nameid != ITEMID_N_FLY_WING )
+ if( map[sd->bl.m].flag.noreturn && nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && nameid != ITEMID_N_FLY_WING || map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP ))
return false;
break;
case ITEMID_MERCENARY_RED_POTION:
@@ -5478,6 +5479,10 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
}
channel_pcquit(sd,4); //quit map chan
+
+ // Addon Cell PVP [Napster]
+ if(sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP))
+ map[sd->state.pmap].cell_pvpuser--;
}
if( m < 0 )
@@ -5634,7 +5639,7 @@ bool pc_memo(struct map_session_data* sd, int pos)
nullpo_ret(sd);
// check mapflags
- if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) {
+ if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) || map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP ) ) {
clif_skill_teleportmessage(sd, 1); // "Saved point cannot be memorized."
return false;
}
@@ -7528,6 +7533,12 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype)
pc_setrestartvalue(sd,3);
if( pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype) != SETPOS_OK )
clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
+
+ // Addon Cell PVP [Napster]
+ if (sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) )
+ map_pvp_area(sd, 1);
+ else
+ map_pvp_area(sd, 0);
}
static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data)
@@ -7542,6 +7553,55 @@ static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data)
return 0;
}
+// Addon Cell PVP [Napster]
+void pc_deathmatch(struct map_session_data* sd, clr_type clrtype)
+{
+ struct npc_data *nd;
+ short x = 0, y = 0;
+
+ if( !pc_isdead(sd) )
+ return; // not applicable
+
+ if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) && battle_config.cellpvp_deathmatch )
+ {
+ do {
+ x = rand() % (map[sd->bl.m].xs - 2) + 1;
+ y = rand() % (map[sd->bl.m].ys - 2) + 1;
+ } while( !map_getcell(sd->bl.m, x, y, CELL_CHKPVP) );
+
+ pc_setstand(sd, true);
+ pc_setrestartvalue(sd,3);
+ status_percent_heal(&sd->bl, battle_config.deathmatch_hp_rate, battle_config.deathmatch_sp_rate);
+
+ if( pc_setpos(sd, sd->mapindex, x, y, clrtype) )
+ clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
+
+ status_change_clear(&sd->bl, 3);
+
+ if(sd && battle_config.cellpvp_autobuff)
+ {
+ nd = npc_name2id("deathmatch_core");
+ if (nd && nd->subtype == NPCTYPE_SCRIPT)
+ run_script(nd->u.scr.script, 0, sd->bl.id, nd->bl.id);
+ }
+ }
+}
+
+static int pc_deathmatch_timer(int tid, unsigned int tick, int id, intptr_t data)
+{
+ struct map_session_data *sd = map_id2sd(id);
+ if( sd != NULL )
+ {
+ pc_deathmatch(sd, CLR_OUTSIGHT);
+ if (sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP ) )
+ {
+ map_pvp_area(sd, 1);
+ map[sd->bl.m].cell_pvpuser--;
+ }
+ }
+ return 0;
+}
+
/*==========================================
* Invoked when a player has received damage
*------------------------------------------*/
@@ -7779,7 +7839,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
}
if(battle_config.bone_drop==2
- || (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp))
+ || (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp) || map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) && sd->state.pvp)
{
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
@@ -7852,6 +7912,12 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
pc_payzeny(sd, zeny_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL);
}
}
+ // Addon Cell PVP [Napster]
+ if (map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP ) && battle_config.cellpvp_deathmatch && sd->state.pvp)
+ {
+ add_timer(tick+battle_config.cellpvp_deathmatch_delay, pc_deathmatch_timer, sd->bl.id, 0);
+ return 1|8;
+ }
if(map[sd->bl.m].flag.pvp_nightmaredrop) { // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker]
int j;
@@ -10152,6 +10218,14 @@ int pc_calc_pvprank(struct map_session_data *sd)
sd->pvp_rank=1;
map_foreachinmap(pc_calc_pvprank_sub,sd->bl.m,BL_PC,sd);
+
+ // Addon Cell PVP [Napster]
+ if( (old!=sd->pvp_rank || sd->pvp_lastusers!=m->cell_pvpuser) || sd->state.pvp )
+ {
+ clif_pvpset( sd, sd->pvp_rank, sd->pvp_lastusers = m->cell_pvpuser, 0);
+ return sd->pvp_rank;
+ }
+
if(old!=sd->pvp_rank || sd->pvp_lastusers!=m->users_pvp)
clif_pvpset(sd,sd->pvp_rank,sd->pvp_lastusers=m->users_pvp,0);
return sd->pvp_rank;
diff --git a/src/map/pc.h b/src/map/pc.h
index c8be94592..f6ecdeb60 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -268,6 +268,7 @@ struct map_session_data {
bool keepshop; // Whether shop data should be removed when the player disconnects
bool mail_writing; // Whether the player is currently writing a mail in RODEX or not
bool cashshop_open;
+ unsigned int pvp : 1; // Addon Cell PVP [Napster]
} state;
struct {
unsigned char no_weapon_damage, no_magic_damage, no_misc_damage;
@@ -347,6 +348,7 @@ 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 pvpcan_walkout_tick; // Addon Cell PVP [Napster]
struct s_item_delay {
unsigned short nameid;
diff --git a/src/map/script_constants.h b/src/map/script_constants.h
index 408f3ff64..6ddb844be 100644
--- a/src/map/script_constants.h
+++ b/src/map/script_constants.h
@@ -448,6 +448,7 @@
export_constant(CELL_NOCHAT);
export_constant(CELL_MAELSTROM);
export_constant(CELL_ICEWALL);
+ export_constant(CELL_PVP);
/* getcell types */
export_constant(CELL_CHKWALL);
@@ -466,7 +467,8 @@
export_constant(CELL_CHKNOCHAT);
export_constant(CELL_CHKMAELSTROM);
export_constant(CELL_CHKICEWALL);
-
+ export_constant(CELL_CHKPVP);
+
/* parameters */
export_parameter("StatusPoint",SP_STATUSPOINT);
export_parameter("BaseLevel",SP_BASELEVEL);
diff --git a/src/map/skill.c b/src/map/skill.c
index 42d19eef9..789d8745f 100755
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -6976,8 +6976,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case MO_ABSORBSPIRITS:
i = 0;
- if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m) || (sd && sd->duel_group && sd->duel_group == dstsd->duel_group)) &&
- ((dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK) != MAPID_REBELLION)) { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen]
+ if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m) || (map_getcell(src->m,src->x,src->y,CELL_CHKPVP) && map_getcell(bl->m,bl->x,bl->y,CELL_CHKPVP)) || (sd && sd->duel_group && sd->duel_group == dstsd->duel_group)) && ((dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK) != MAPID_REBELLION)) { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen]
if (dstsd->spiritball > 0) {
i = dstsd->spiritball * 7;
pc_delspiritball(dstsd,dstsd->spiritball,0);
diff --git a/src/map/unit.c b/src/map/unit.c
index ef713e1ed..879aef341 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -428,6 +428,12 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
} else
sd->areanpc_id=0;
pc_cell_basilica(sd);
+
+ // Addon Cell PVP [Napster]
+ if( !sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) )
+ map_pvp_area(sd, 1);
+ else if( sd->state.pvp && !map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) )
+ map_pvp_area(sd, 0);
break;
case BL_MOB:
//Movement was successful, reset walktoxy_fail_count
@@ -648,6 +654,28 @@ int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag)
if(!(flag&2) && (!status_bl_has_mode(bl,MD_CANMOVE) || !unit_can_move(bl)))
return 0;
+ // Addon Cell PVP [Napster]
+ if (bl->type == BL_PC)
+ {
+ struct map_session_data* sd = (TBL_PC*)bl;
+ unsigned int tick = gettick();
+
+ if (sd && sd->pvpcan_walkout_tick && !map_getcell( sd->bl.m, x, y, CELL_CHKPVP ) ) {
+ if ( DIFF_TICK(tick, sd->pvpcan_walkout_tick) < battle_config.cellpvp_walkout_delay )
+ {
+ int e_tick = (battle_config.cellpvp_walkout_delay - DIFF_TICK( tick, sd->pvpcan_walkout_tick))/1000;
+ char e_msg[150];
+ if( e_tick > 99 )
+ sprintf(e_msg, msg_txt(sd, 1599), sd->status.name, (double)e_tick / 60);
+ else
+ sprintf(e_msg, msg_txt(sd, 1600), sd->status.name, e_tick+1);
+
+ clif_messagecolor(sd,color_table[COLOR_YELLOW], e_msg, false, SELF);
+ return 0;
+ }
+ }
+ }
+
ud->state.walk_easy = flag&1;
ud->to_x = x;
ud->to_y = y;
@@ -959,7 +987,13 @@ bool unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, boo
return false;
} else
sd->areanpc_id=0;
-
+
+ // Addon Cell PVP [Ize]
+ if( !sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) )
+ map_pvp_area(sd, 1);
+ else if( sd->state.pvp && !map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) )
+ map_pvp_area(sd, 0);
+
if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 ) {
// Check if pet needs to be teleported. [Skotlex]
int flag = 0;
@@ -1302,6 +1336,17 @@ int unit_stop_walking(struct block_list *bl,int type)
*/
int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv)
{
+ // Addon Cell PVP [Napster]
+ struct block_list *bl = map_id2bl(target_id);
+
+ if( bl && src->type == BL_PC && bl->type == BL_PC && src->id != target_id)
+ {
+ struct map_session_data *dstsd = (TBL_PC*)bl;
+
+ if( dstsd && dstsd->state.pvp != ((TBL_PC*)src)->state.pvp )
+ return 0;
+ }
+
return unit_skilluse_id2(
src, target_id, skill_id, skill_lv,
skill_castfix(src, skill_id, skill_lv),
Question
ZodiacoHCK
Hello people!
I wanted to tell you that I have a problem trying to implement NAPSTER's PvP cell in my emulator. I have my emulator running stable in the latest master version available about 4 months ago.
the problem is that there are certain differences between my rathena codes and the diff code of the patch.
I have successfully implemented the BGex manually and I had no problems. but this pvp_cell has not succeeded.
I leave the patch that I am trying to put!
conf/battle/misc.conf | 39 +++++++++++++++++++++ conf/msg_conf/map_msg.conf | 4 +++ db/const.txt | 3 ++ src/map/atcommand.c | 8 ++--- src/map/battle.c | 30 ++++++++++++---- src/map/battle.h | 10 +++++- src/map/clif.c | 8 ++++- src/map/map.cpp | 46 +++++++++++++++++++++++-- src/map/map.h | 12 +++++-- src/map/pc.c | 86 ++++++++++++++++++++++++++++++++++++++++++---- src/map/pc.h | 2 ++ src/map/script_constants.h | 4 ++- src/map/skill.c | 3 +- src/map/unit.c | 47 ++++++++++++++++++++++++- 14 files changed, 274 insertions(+), 28 deletions(-) diff --git a/conf/battle/misc.conf b/conf/battle/misc.conf index 7c085fd41..37759b659 100644 --- a/conf/battle/misc.conf +++ b/conf/battle/misc.conf @@ -176,3 +176,42 @@ mail_delay: 1000 // Hides items from the player's favorite tab from being sold to a NPC. (Note 1) hide_fav_sell: no + +// Addon Cell PVP [Napster] +// Enable Deathmatch for cell pvp +// Default: 0 +// 0 = No +// 1 = Yes +cellpvp_deathmatch: 1 + +// Delay player alive deathmatch for cell pvp +// Default: 1000 (1 secand) +cellpvp_deathmatch_delay: 1000 + +// When player is dead recovery HP/SP Rate for cell pvp +// Default: 100 (recovery 100%) +deathmatch_hp_rate: 100 +deathmatch_sp_rate: 100 + +// Enable buff when player is dead for cell pvp +// Default: 1 +// 0 = No +// 1 = Yes +// Request core npc files use name "deathmatch_core" +cellpvp_autobuff: yes + +// Can atk player in party +// Default: 1 +// 0 = No +// 1 = Yes +cellpvp_party_enable: no + +// Can atk player in guild +// Default: 1 +// 0 = No +// 1 = Yes +cellpvp_guild_enable: no + +// When player move to cell pvp is delay walk out cooldown +// Default: 5000 (5 secand) +cellpvp_walkout_delay: 5000 \ No newline at end of file diff --git a/conf/msg_conf/map_msg.conf b/conf/msg_conf/map_msg.conf index 50306ef97..d3afebbc8 100644 --- a/conf/msg_conf/map_msg.conf +++ b/conf/msg_conf/map_msg.conf @@ -1664,3 +1664,7 @@ //Custom translations //import: conf/msg_conf/import/map_msg_eng_conf.txt + +// Addon Cell PVP [Napster] +1599: Walking failed. [%s] is cooling down. Wait %.1f minutes. +1600: Walking failed. [%s] is cooling down. Wait %d seconds. \ No newline at end of file diff --git a/db/const.txt b/db/const.txt index a10cc018b..46bf071f9 100644 --- a/db/const.txt +++ b/db/const.txt @@ -2313,3 +2313,6 @@ ARCWANDCLAN 2 GOLDENMACECLAN 3 CROSSBOWCLAN 4 JUMPINGCLAN 5 + +CELL_PVP 10 +CELL_CHKPVP 16 \ No newline at end of file diff --git a/src/map/atcommand.c b/src/map/atcommand.c index d8d52b9cc..c6bd4ce11 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -482,7 +482,7 @@ ACMD_FUNC(mapmove) clif_displaymessage(fd, msg_txt(sd,247)); // You are not authorized to warp to this map. return -1; } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + if (sd->state.pvp || sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, msg_txt(sd,248)); // You are not authorized to warp from your current map. return -1; } @@ -830,11 +830,11 @@ ACMD_FUNC(load) nullpo_retr(-1, sd); m = map_mapindex2mapid(sd->status.save_point.map); - if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + if (sd->state.pvp && (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))) { clif_displaymessage(fd, msg_txt(sd,249)); // You are not authorized to warp to your save map. return -1; } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + if (sd->state.pvp && (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))) { clif_displaymessage(fd, msg_txt(sd,248)); // You are not authorized to warp from your current map. return -1; } @@ -2054,7 +2054,7 @@ ACMD_FUNC(go) clif_displaymessage(fd, msg_txt(sd,247)); // You are not authorized to warp to this map. return -1; } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + if (sd->state.pvp || sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, msg_txt(sd,248)); // You are not authorized to warp from your current map. return -1; } diff --git a/src/map/battle.c b/src/map/battle.c index e2d616bd9..ef7b5e9cd 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -7767,6 +7767,10 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f else return 0; // You can't target anything out of your duel } + else if( map_getcell( s_bl->m, s_bl->x, s_bl->y, CELL_CHKPVP ) && map_getcell( t_bl->m, t_bl->x, t_bl->y, CELL_CHKPVP ) ) // Addon Cell PVP [Napster] + { + state |= BCT_ENEMY; + } } if( map_flag_gvg(m) && !sd->status.guild_id && t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->mob_id == MOBID_EMPERIUM ) return 0; //If you don't belong to a guild, can't target emperium. @@ -7868,15 +7872,19 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f 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(s_party && s_party == status_get_party_id(t_bl) && !(battle_config.cellpvp_party_enable && map_getcell( t_bl->m, t_bl->x, t_bl->y, CELL_CHKPVP )) ) // Addon Cell PVP [Napster] + state |= BCT_PARTY; + else + 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 || (!(flag&BCT_SAMEGUILD) && guild_isallied(s_guild, t_guild)))) - state |= BCT_GUILD; + if(s_guild && t_guild && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild_isallied(s_guild, t_guild))) && !(battle_config.cellpvp_guild_enable && map_getcell( t_bl->m, t_bl->x, t_bl->y, CELL_CHKPVP )) ) // Addon Cell PVP [Napster] + state |= BCT_GUILD; + else + state |= BCT_ENEMY; } } //end non pvp/gvg chk rivality @@ -8419,7 +8427,7 @@ static const struct _battle_data { { "change_party_leader_samemap", &battle_config.change_party_leader_samemap, 1, 0, 1, }, { "dispel_song", &battle_config.dispel_song, 0, 0, 1, }, { "guild_maprespawn_clones", &battle_config.guild_maprespawn_clones, 0, 0, 1, }, - { "hide_fav_sell", &battle_config.hide_fav_sell, 0, 0, 1, }, + { "hide_fav_sell", &battle_config.hide_fav_sell, 0, 0, 1, }, { "mail_daily_count", &battle_config.mail_daily_count, 100, 0, INT32_MAX, }, { "mail_zeny_fee", &battle_config.mail_zeny_fee, 2, 0, 100, }, { "mail_attachment_price", &battle_config.mail_attachment_price, 2500, 0, INT32_MAX, }, @@ -8427,10 +8435,20 @@ static const struct _battle_data { { "banana_bomb_duration", &battle_config.banana_bomb_duration, 0, 0, UINT16_MAX, }, { "guild_leaderchange_delay", &battle_config.guild_leaderchange_delay, 1440, 0, INT32_MAX, }, { "guild_leaderchange_woe", &battle_config.guild_leaderchange_woe, 0, 0, 1, }, - { "guild_alliance_onlygm", &battle_config.guild_alliance_onlygm, 0, 0, 1, }, + { "guild_alliance_onlygm", &battle_config.guild_alliance_onlygm, 0, 0, 1, }, { "feature.achievement", &battle_config.feature_achievement, 1, 0, 1, }, { "allow_bound_sell", &battle_config.allow_bound_sell, 1, 0, 1, }, + // Addon Cell PVP [Napster] + { "cellpvp_deathmatch", &battle_config.cellpvp_deathmatch, 1, 0, 1, }, + { "cellpvp_deathmatch_delay", &battle_config.cellpvp_deathmatch_delay, 1000, 0,INT_MAX, }, + { "deathmatch_hp_rate", &battle_config.deathmatch_hp_rate, 0, 0, 100, }, + { "deathmatch_sp_rate", &battle_config.deathmatch_sp_rate, 0, 0, 100, }, + { "cellpvp_autobuff", &battle_config.cellpvp_autobuff, 1, 0, 1, }, + { "cellpvp_party_enable", &battle_config.cellpvp_party_enable, 1, 0, 1, }, + { "cellpvp_guild_enable", &battle_config.cellpvp_guild_enable, 1, 0, 1, }, + { "cellpvp_walkout_delay", &battle_config.cellpvp_walkout_delay, 5000, 0,INT_MAX, }, + #include "../custom/battle_config_init.inc" }; diff --git a/src/map/battle.h b/src/map/battle.h index 37c86dfbb..abcb2b4a7 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -632,7 +632,15 @@ extern struct Battle_Config int guild_alliance_onlygm; int feature_achievement; int allow_bound_sell; - + // Addon Cell PVP [Napster] + int cellpvp_deathmatch; + int cellpvp_deathmatch_delay; + int deathmatch_hp_rate; + int deathmatch_sp_rate; + int cellpvp_autobuff; + int cellpvp_party_enable; + int cellpvp_guild_enable; + int cellpvp_walkout_delay; #include "../custom/battle_config_struct.inc" } battle_config; diff --git a/src/map/clif.c b/src/map/clif.c index e3d4a5abf..8bf9f93dc 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -10446,7 +10446,13 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) mail_clear(sd); - + + // Addon Cell PVP [Napster] + if( !sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) ) + map_pvp_area(sd, 1); + else if( sd->state.pvp && !map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) ) + map_pvp_area(sd, 0); + /* Guild Aura Init */ if( sd->state.gmaster_flag ) { guild_guildaura_refresh(sd,GD_LEADERSHIP,guild_checkskill(sd->guild,GD_LEADERSHIP)); diff --git a/src/map/map.cpp b/src/map/map.cpp index 57486ac58..02013af02 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -115,7 +115,7 @@ static int block_free_count = 0, block_free_lock = 0; static struct block_list *bl_list[BL_LIST_MAX]; static int bl_list_count = 0; -#define MAP_MAX_MSG 1550 +#define MAP_MAX_MSG 1601 struct map_data map[MAX_MAP_PER_SERVER]; int map_num = 0; @@ -2092,7 +2092,10 @@ int map_quit(struct map_session_data *sd) { if (sd->state.buyingstore) idb_remove(buyingstore_getdb(), sd->status.char_id); - + // Addon Cell PVP [Napster] + if( sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP ) ) + map_pvp_area(sd, 0); + pc_damage_log_clear(sd,0); party_booking_delete(sd); // Party Booking [Spiria] pc_makesavestatus(sd); @@ -3068,7 +3071,8 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) return (cell.maelstrom); case CELL_CHKICEWALL: return (cell.icewall); - + case CELL_CHKPVP: // Addon Cell PVP [Napster] + return (cell.pvp); // special checks case CELL_CHKPASS: #ifdef CELL_NOSTACK @@ -3122,6 +3126,7 @@ void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) case CELL_NOCHAT: map[m].cell[j].nochat = flag; break; case CELL_MAELSTROM: map[m].cell[j].maelstrom = flag; break; case CELL_ICEWALL: map[m].cell[j].icewall = flag; break; + case CELL_PVP: map[m].cell[j].pvp = flag; break; // Addon Cell PVP [Napster] default: ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell); break; @@ -4054,6 +4059,41 @@ int inter_config_read(const char *cfgName) return 0; } +// Addon Cell PVP [Napster] +int map_pvp_area(struct map_session_data* sd, bool flag) +{ + switch(flag) + { + case 1: + clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF); + if (sd->pvp_timer == INVALID_TIMER) { + map[sd->bl.m].cell_pvpuser++; + + sd->pvp_timer = add_timer(gettick()+200, pc_calc_pvprank_timer, sd->bl.id, 0); + sd->pvp_rank = 0; + sd->pvp_lastusers = 0; + sd->pvp_point = 5; + sd->pvp_won = 0; + sd->pvp_lost = 0; + sd->state.pvp = 1; + sd->pvpcan_walkout_tick = gettick(); + } + break; + default: + clif_pvpset(sd, 0, 0, 2); + map[sd->bl.m].cell_pvpuser--; + + if( sd->pvp_timer != INVALID_TIMER ) + delete_timer(sd->pvp_timer, pc_calc_pvprank_timer); + + sd->pvp_timer = INVALID_TIMER; + sd->state.pvp = 0; + break; + } + + return 0; +} + /*======================================= * MySQL Init *---------------------------------------*/ diff --git a/src/map/map.h b/src/map/map.h index fd5a6b046..e6687c1fa 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -521,7 +521,7 @@ typedef enum { CELL_NOCHAT, CELL_MAELSTROM, CELL_ICEWALL, - + CELL_PVP, } cell_t; // used by map_getcell() @@ -545,7 +545,7 @@ typedef enum { CELL_CHKNOCHAT, // Whether the cell denies Player Chat Window CELL_CHKMAELSTROM, // Whether the cell has Maelstrom CELL_CHKICEWALL, // Whether the cell has Ice Wall - + CELL_CHKPVP, // Addon Cell PVP [Napster] } cell_chk; struct mapcell @@ -564,7 +564,8 @@ struct mapcell novending : 1, nochat : 1, maelstrom : 1, - icewall : 1; + icewall : 1, + pvp : 1; // Addon Cell PVP [Napster] #ifdef CELL_NOSTACK unsigned char cell_bl; //Holds amount of bls in this cell. @@ -624,6 +625,7 @@ struct map_data { int npc_num; int users; int users_pvp; + int cell_pvpuser; // Addon Cell PVP [Napster] int iwall_num; // Total of invisible walls in this map struct map_flag { unsigned town : 1; // [Suggestion to protect Mail System] @@ -684,6 +686,7 @@ struct map_data { unsigned gvg_te : 1; // GVG WOE:TE. This was added as purpose to change 'gvg' for GVG TE, so item_noequp, skill_nocast exlude GVG TE maps from 'gvg' (flag &4) unsigned gvg_te_castle : 1; // GVG WOE:TE Castle unsigned hidemobhpbar : 1; + #ifdef ADJUST_SKILL_DAMAGE unsigned skill_damage : 1; #endif @@ -1006,6 +1009,9 @@ extern char roulette_table[32]; void do_shutdown(void); +// Addon Cell PVP [Napster] +int map_pvp_area(struct map_session_data* sd, bool flag); + #ifdef __cplusplus } #endif diff --git a/src/map/pc.c b/src/map/pc.c index 4682102bb..3342c74ce 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -672,8 +672,9 @@ void pc_makesavestatus(struct map_session_data *sd) { sd->status.last_point.x = sd->bl.x; sd->status.last_point.y = sd->bl.y; } - - if(map[sd->bl.m].flag.nosave) { + + // Addon Cell PVP [Napster] + if(map[sd->bl.m].flag.nosave || map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP ) ) { struct map_data *m=&map[sd->bl.m]; if(m->save.map) memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point)); @@ -4826,7 +4827,7 @@ bool pc_isUseitem(struct map_session_data *sd,int n) case ITEMID_WING_OF_FLY: case ITEMID_GIANT_FLY_WING: case ITEMID_N_FLY_WING: - if( map[sd->bl.m].flag.noteleport || map_flag_gvg2(sd->bl.m) ) { + if( map[sd->bl.m].flag.noteleport || map_flag_gvg2(sd->bl.m) || map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP )) { clif_skill_teleportmessage(sd,0); return false; } @@ -4867,7 +4868,7 @@ bool pc_isUseitem(struct map_session_data *sd,int n) clif_displaymessage(sd->fd, msg_txt(sd,663)); return false; } - if( map[sd->bl.m].flag.noreturn && nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && nameid != ITEMID_N_FLY_WING ) + if( map[sd->bl.m].flag.noreturn && nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && nameid != ITEMID_N_FLY_WING || map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP )) return false; break; case ITEMID_MERCENARY_RED_POTION: @@ -5478,6 +5479,10 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in } channel_pcquit(sd,4); //quit map chan + + // Addon Cell PVP [Napster] + if(sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP)) + map[sd->state.pmap].cell_pvpuser--; } if( m < 0 ) @@ -5634,7 +5639,7 @@ bool pc_memo(struct map_session_data* sd, int pos) nullpo_ret(sd); // check mapflags - if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) { + if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) || map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP ) ) { clif_skill_teleportmessage(sd, 1); // "Saved point cannot be memorized." return false; } @@ -7528,6 +7533,12 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype) pc_setrestartvalue(sd,3); if( pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype) != SETPOS_OK ) clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet. + + // Addon Cell PVP [Napster] + if (sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) ) + map_pvp_area(sd, 1); + else + map_pvp_area(sd, 0); } static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data) @@ -7542,6 +7553,55 @@ static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data) return 0; } +// Addon Cell PVP [Napster] +void pc_deathmatch(struct map_session_data* sd, clr_type clrtype) +{ + struct npc_data *nd; + short x = 0, y = 0; + + if( !pc_isdead(sd) ) + return; // not applicable + + if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) && battle_config.cellpvp_deathmatch ) + { + do { + x = rand() % (map[sd->bl.m].xs - 2) + 1; + y = rand() % (map[sd->bl.m].ys - 2) + 1; + } while( !map_getcell(sd->bl.m, x, y, CELL_CHKPVP) ); + + pc_setstand(sd, true); + pc_setrestartvalue(sd,3); + status_percent_heal(&sd->bl, battle_config.deathmatch_hp_rate, battle_config.deathmatch_sp_rate); + + if( pc_setpos(sd, sd->mapindex, x, y, clrtype) ) + clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet. + + status_change_clear(&sd->bl, 3); + + if(sd && battle_config.cellpvp_autobuff) + { + nd = npc_name2id("deathmatch_core"); + if (nd && nd->subtype == NPCTYPE_SCRIPT) + run_script(nd->u.scr.script, 0, sd->bl.id, nd->bl.id); + } + } +} + +static int pc_deathmatch_timer(int tid, unsigned int tick, int id, intptr_t data) +{ + struct map_session_data *sd = map_id2sd(id); + if( sd != NULL ) + { + pc_deathmatch(sd, CLR_OUTSIGHT); + if (sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP ) ) + { + map_pvp_area(sd, 1); + map[sd->bl.m].cell_pvpuser--; + } + } + return 0; +} + /*========================================== * Invoked when a player has received damage *------------------------------------------*/ @@ -7779,7 +7839,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) } if(battle_config.bone_drop==2 - || (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp)) + || (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp) || map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) && sd->state.pvp) { struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); @@ -7852,6 +7912,12 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) pc_payzeny(sd, zeny_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL); } } + // Addon Cell PVP [Napster] + if (map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP ) && battle_config.cellpvp_deathmatch && sd->state.pvp) + { + add_timer(tick+battle_config.cellpvp_deathmatch_delay, pc_deathmatch_timer, sd->bl.id, 0); + return 1|8; + } if(map[sd->bl.m].flag.pvp_nightmaredrop) { // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker] int j; @@ -10152,6 +10218,14 @@ int pc_calc_pvprank(struct map_session_data *sd) sd->pvp_rank=1; map_foreachinmap(pc_calc_pvprank_sub,sd->bl.m,BL_PC,sd); + + // Addon Cell PVP [Napster] + if( (old!=sd->pvp_rank || sd->pvp_lastusers!=m->cell_pvpuser) || sd->state.pvp ) + { + clif_pvpset( sd, sd->pvp_rank, sd->pvp_lastusers = m->cell_pvpuser, 0); + return sd->pvp_rank; + } + if(old!=sd->pvp_rank || sd->pvp_lastusers!=m->users_pvp) clif_pvpset(sd,sd->pvp_rank,sd->pvp_lastusers=m->users_pvp,0); return sd->pvp_rank; diff --git a/src/map/pc.h b/src/map/pc.h index c8be94592..f6ecdeb60 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -268,6 +268,7 @@ struct map_session_data { bool keepshop; // Whether shop data should be removed when the player disconnects bool mail_writing; // Whether the player is currently writing a mail in RODEX or not bool cashshop_open; + unsigned int pvp : 1; // Addon Cell PVP [Napster] } state; struct { unsigned char no_weapon_damage, no_magic_damage, no_misc_damage; @@ -347,6 +348,7 @@ 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 pvpcan_walkout_tick; // Addon Cell PVP [Napster] struct s_item_delay { unsigned short nameid; diff --git a/src/map/script_constants.h b/src/map/script_constants.h index 408f3ff64..6ddb844be 100644 --- a/src/map/script_constants.h +++ b/src/map/script_constants.h @@ -448,6 +448,7 @@ export_constant(CELL_NOCHAT); export_constant(CELL_MAELSTROM); export_constant(CELL_ICEWALL); + export_constant(CELL_PVP); /* getcell types */ export_constant(CELL_CHKWALL); @@ -466,7 +467,8 @@ export_constant(CELL_CHKNOCHAT); export_constant(CELL_CHKMAELSTROM); export_constant(CELL_CHKICEWALL); - + export_constant(CELL_CHKPVP); + /* parameters */ export_parameter("StatusPoint",SP_STATUSPOINT); export_parameter("BaseLevel",SP_BASELEVEL); diff --git a/src/map/skill.c b/src/map/skill.c index 42d19eef9..789d8745f 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -6976,8 +6976,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case MO_ABSORBSPIRITS: i = 0; - if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m) || (sd && sd->duel_group && sd->duel_group == dstsd->duel_group)) && - ((dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK) != MAPID_REBELLION)) { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen] + if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m) || (map_getcell(src->m,src->x,src->y,CELL_CHKPVP) && map_getcell(bl->m,bl->x,bl->y,CELL_CHKPVP)) || (sd && sd->duel_group && sd->duel_group == dstsd->duel_group)) && ((dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK) != MAPID_REBELLION)) { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen] if (dstsd->spiritball > 0) { i = dstsd->spiritball * 7; pc_delspiritball(dstsd,dstsd->spiritball,0); diff --git a/src/map/unit.c b/src/map/unit.c index ef713e1ed..879aef341 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -428,6 +428,12 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data } else sd->areanpc_id=0; pc_cell_basilica(sd); + + // Addon Cell PVP [Napster] + if( !sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) ) + map_pvp_area(sd, 1); + else if( sd->state.pvp && !map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) ) + map_pvp_area(sd, 0); break; case BL_MOB: //Movement was successful, reset walktoxy_fail_count @@ -648,6 +654,28 @@ int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag) if(!(flag&2) && (!status_bl_has_mode(bl,MD_CANMOVE) || !unit_can_move(bl))) return 0; + // Addon Cell PVP [Napster] + if (bl->type == BL_PC) + { + struct map_session_data* sd = (TBL_PC*)bl; + unsigned int tick = gettick(); + + if (sd && sd->pvpcan_walkout_tick && !map_getcell( sd->bl.m, x, y, CELL_CHKPVP ) ) { + if ( DIFF_TICK(tick, sd->pvpcan_walkout_tick) < battle_config.cellpvp_walkout_delay ) + { + int e_tick = (battle_config.cellpvp_walkout_delay - DIFF_TICK( tick, sd->pvpcan_walkout_tick))/1000; + char e_msg[150]; + if( e_tick > 99 ) + sprintf(e_msg, msg_txt(sd, 1599), sd->status.name, (double)e_tick / 60); + else + sprintf(e_msg, msg_txt(sd, 1600), sd->status.name, e_tick+1); + + clif_messagecolor(sd,color_table[COLOR_YELLOW], e_msg, false, SELF); + return 0; + } + } + } + ud->state.walk_easy = flag&1; ud->to_x = x; ud->to_y = y; @@ -959,7 +987,13 @@ bool unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, boo return false; } else sd->areanpc_id=0; - + + // Addon Cell PVP [Ize] + if( !sd->state.pvp && map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) ) + map_pvp_area(sd, 1); + else if( sd->state.pvp && !map_getcell( sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKPVP) ) + map_pvp_area(sd, 0); + if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 ) { // Check if pet needs to be teleported. [Skotlex] int flag = 0; @@ -1302,6 +1336,17 @@ int unit_stop_walking(struct block_list *bl,int type) */ int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv) { + // Addon Cell PVP [Napster] + struct block_list *bl = map_id2bl(target_id); + + if( bl && src->type == BL_PC && bl->type == BL_PC && src->id != target_id) + { + struct map_session_data *dstsd = (TBL_PC*)bl; + + if( dstsd && dstsd->state.pvp != ((TBL_PC*)src)->state.pvp ) + return 0; + } + return unit_skilluse_id2( src, target_id, skill_id, skill_lv, skill_castfix(src, skill_id, skill_lv),
if necessary I can put my emulator on a github
Link to comment
Share on other sites
1 answer to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.