- Added some new config settings: homunculus_autoloot, idle_no_autoloot, max_guild_alliance.

- Added a code to activate a Kill Steal protection and the required mapflags.
* (I will explain this later on forums).

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12203 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
zephyrus 2008-02-14 01:18:19 +00:00
parent 9fd3b6a93b
commit 69ae4766ce
15 changed files with 247 additions and 30 deletions

View File

@ -17,6 +17,9 @@ IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
* Added some security checks in mail system [Zephyrus]
- This supose to fix a bug reported in 622 to limit to MAX_ZENY.
- Also add more checks to free space in your inventory to receive items.
* Added some new config settings: [Zephyrus]
- homunculus_autoloot, idle_no_autoloot, max_guild_alliance.
- Added a code to activate a Kill Steal protection and the required mapflags.
2008/02/11
* 'Forget me Not' no longer blocks ASPD bonuses from working or prevents
their re-casting, they are simply dispelled when the effect takes place.

View File

@ -131,6 +131,9 @@ jailtime: 1
hominfo: 1
homstats: 1
// Kill Steal Protection
noks: 1
//---------------------------
// 10: Super player+ commands
@ -146,6 +149,9 @@ go: 10
// Enables/disables autolooting from killed mobs.
autoloot: 10
// Enables/disables autolooting an item.
alootid: 10
// Allows you continue vending offline.
autotrade: 10
at: 10
@ -278,6 +284,9 @@ gpvpon: 40
gvgoff: 40
gpvpoff: 40
// Activate/Deactivate kill steal protection on a map
allowks: 40
// Modifies your HP/SP.
heal: 40

View File

@ -62,3 +62,8 @@ gvg_eliminate_time: 7000
// and does changing emblems require it? (Note 1)
// P.S: This skill is not implemented on official servers
require_glory_guild: no
// Limit Guild alliances. Value is 0 to 3.
// If you want to change this value, clear the guild alliance table.
// Default is 3
max_guild_alliance: 3

View File

@ -43,3 +43,6 @@ hvan_explosion_intimate: 45000
// Show stat growth to the owner when an Homunculus levels up
homunculus_show_growth: no
// If a monster is killed only by homunculus, can autoloot works?
homunculus_autoloot: yes

View File

@ -199,3 +199,9 @@ mob_clear_delay: 0
// Type 0: On the player that did the most damage to the mob.
// NOTE: This affects who gains the Castle when the Emperium is broken.
mob_npc_event_type: 1
// Time in milliseconds to actitave protection against Kill Steal
// Set to 0 to disable it.
// If this is activated and a player is using @noks, damage from others players (KS) not in the party
// will be reduced to 0.
ksprotection: 0

View File

@ -135,3 +135,7 @@ bone_drop: 0
// 3 = both Normal Classes on Peco have Big Size
// and Baby Classes on Peco have Medium Size
character_size: 0
// Idle characters can receive autoloot?
// Set to the time in seconds where an idle character will stop receiving items from Autoloot.
idle_no_autoloot: 120

View File

@ -6085,9 +6085,55 @@ int atcommand_autoloot(const int fd, struct map_session_data* sd, const char* co
clif_displaymessage(fd, atcmd_output);
}else
clif_displaymessage(fd, "Autoloot is now off.");
return 0;
}
if (sd->state.autoloot && sd->state.autolootid) {
// Autolootitem should be turned off
sd->state.autolootid = 0;
clif_displaymessage(fd, "Autolootitem is now off.");
}
return 0;
}
/*==========================================
* @autolootitem
*------------------------------------------*/
int atcommand_autolootitem(const int fd, struct map_session_data* sd, const char* command, const char* message)
{
struct item_data *item_data = NULL;
if (!message || !*message) {
if (sd->state.autolootid) {
sd->state.autolootid = 0;
clif_displaymessage(fd, "Autolootitem have been turned OFF.");
} else
clif_displaymessage(fd, "Please, enter Item name or its ID (usage: @autolootitem <item_name_or_ID>).");
return -1;
}
if ((item_data = itemdb_exists(atoi(message))) == NULL)
item_data = itemdb_searchname(message);
if (!item_data) {
// No items founds in the DB with Id or Name
clif_displaymessage(fd, "Item not found.");
return -1;
}
sd->state.autolootid = item_data->nameid; // Autoloot Activated
sprintf(atcmd_output, "Autolooting Item: '%s'/'%s' {%d}",
item_data->name, item_data->jname, item_data->nameid);
clif_displaymessage(fd, atcmd_output);
if (sd->state.autolootid && sd->state.autoloot) {
// Autoloot should be turned off
sd->state.autoloot = 0;
clif_displaymessage(fd, "Autoloot is now off (cannot be actitaved together).");
}
return 0;
}
/*==========================================
* It is made to rain.
@ -8115,8 +8161,42 @@ int atcommand_feelreset(const int fd, struct map_session_data* sd, const char* c
return 0;
}
/*==========================================
* Kill Steal Protection
*------------------------------------------*/
int atcommand_ksprotection(const int fd, struct map_session_data *sd, const char *command, const char *message)
{
nullpo_retr(-1,sd);
if( sd->state.noks ) {
sd->state.noks = 0;
sprintf(atcmd_output, "[ K.S Protection Inactive ]");
} else {
sprintf(atcmd_output, "[ K.S Protection Active ]");
sd->state.noks = 1;
}
clif_displaymessage(fd, atcmd_output);
return 0;
}
/*==========================================
* Map Kill Steal Protection Setting
*------------------------------------------*/
int atcommand_allowks(const int fd, struct map_session_data *sd, const char *command, const char *message)
{
nullpo_retr(-1,sd);
if( map[sd->bl.m].flag.allowks ) {
map[sd->bl.m].flag.allowks = 0;
sprintf(atcmd_output, "[ Map K.S Protection Active ]");
} else {
map[sd->bl.m].flag.allowks = 1;
sprintf(atcmd_output, "[ Map K.S Protection Inactive ]");
}
clif_displaymessage(fd, atcmd_output);
return 0;
}
/*==========================================
* atcommand_info[] structure definition
@ -8348,6 +8428,7 @@ AtCommandInfo atcommand_info[] = {
{ "disguiseall", 99, atcommand_disguiseall },
{ "changelook", 60, atcommand_changelook },
{ "autoloot", 10, atcommand_autoloot },
{ "alootid", 10, atcommand_autolootitem },
{ "mobinfo", 1, atcommand_mobinfo },
{ "monsterinfo", 1, atcommand_mobinfo },
{ "mi", 1, atcommand_mobinfo },
@ -8407,6 +8488,8 @@ AtCommandInfo atcommand_info[] = {
{ "showmobs", 10, atcommand_showmobs },
{ "feelreset", 10, atcommand_feelreset },
{ "mail", 1, atcommand_mail },
{ "noks", 0, atcommand_ksprotection },
{ "allowks", 6, atcommand_allowks },
};

View File

@ -259,6 +259,9 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
if (!damage)
return 0;
if( mob_ksprotected(src, bl) )
return 0;
if (bl->type == BL_PC) {
sd=(struct map_session_data *)bl;
//Special no damage states
@ -3139,23 +3142,22 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
case BL_PC:
{
TBL_PC *sd = (TBL_PC*) s_bl;
if (sd->state.killer && s_bl != t_bl)
if( s_bl != t_bl )
{
state |= BCT_ENEMY; //Is on a killing rampage :O
strip_enemy = 0;
} else
if (sd->duel_group && t_bl != s_bl && // Duel [LuzZza]
!(
(!battle_config.duel_allow_pvp && map[m].flag.pvp) ||
(!battle_config.duel_allow_gvg && map_flag_gvg(m))
))
{
if (t_bl->type == BL_PC &&
(sd->duel_group == ((TBL_PC*)t_bl)->duel_group))
//Duel targets can ONLY be your enemy, nothing else.
return (BCT_ENEMY&flag)?1:-1;
else // You can't target anything out of your duel
return 0;
if( sd->state.killer )
{
state |= BCT_ENEMY; //Is on a killing rampage :O
strip_enemy = 0;
}
else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) )
{
if (t_bl->type == BL_PC &&
(sd->duel_group == ((TBL_PC*)t_bl)->duel_group))
//Duel targets can ONLY be your enemy, nothing else.
return (BCT_ENEMY&flag)?1:-1;
else // You can't target anything out of your duel
return 0;
}
}
if (map_flag_gvg(m) && !sd->status.guild_id &&
t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data)
@ -3650,6 +3652,10 @@ static const struct _battle_data {
{ "sg_miracle_skill_duration", &battle_config.sg_miracle_skill_duration, 3600000, 0, INT_MAX, },
{ "hvan_explosion_intimate", &battle_config.hvan_explosion_intimate, 45000, 0, 100000, },
{ "quest_exp_rate", &battle_config.quest_exp_rate, 100, 0, INT_MAX, },
{ "homunculus_autoloot", &battle_config.homunculus_autoloot, 0, 0, 1, },
{ "idle_no_autoloot", &battle_config.idle_no_autoloot, 0, 0, INT_MAX, },
{ "max_guild_alliance", &battle_config.max_guild_alliance, 3, 1, 3, },
{ "ksprotection", &battle_config.ksprotection, 5000, 0, INT_MAX, },
};

View File

@ -438,6 +438,10 @@ extern struct Battle_Config
int homunculus_show_growth ; //[orn]
int homunculus_friendly_rate;
int quest_exp_rate;
int homunculus_autoloot;
int idle_no_autoloot;
int max_guild_alliance;
int ksprotection;
} battle_config;
void do_init_battle(void);

View File

@ -1250,11 +1250,11 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd)
if(sd->status.guild_id == tsd->status.guild_id)
return 0;
if( guild_get_alliance_count(g[0],0)>=3 ) {
if( guild_get_alliance_count(g[0],0) >= battle_config.max_guild_alliance ) {
clif_guild_allianceack(sd,4);
return 0;
}
if( guild_get_alliance_count(g[1],0)>=3 ) {
if( guild_get_alliance_count(g[1],0) >= battle_config.max_guild_alliance ) {
clif_guild_allianceack(sd,3);
return 0;
}
@ -1300,12 +1300,12 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag)
g=guild_search(sd->status.guild_id);
tg=guild_search(tsd->status.guild_id);
if(g==NULL || guild_get_alliance_count(g,0)>=3){
if(g==NULL || guild_get_alliance_count(g,0) >= battle_config.max_guild_alliance){
clif_guild_allianceack(sd,4);
clif_guild_allianceack(tsd,3);
return 0;
}
if(tg==NULL || guild_get_alliance_count(tg,0)>=3){
if(tg==NULL || guild_get_alliance_count(tg,0) >= battle_config.max_guild_alliance){
clif_guild_allianceack(sd,3);
clif_guild_allianceack(tsd,4);
return 0;
@ -1367,7 +1367,7 @@ int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd)
if(sd->status.guild_id == tsd->status.guild_id)
return 0;
if( guild_get_alliance_count(g,1)>=3 ) {
if( guild_get_alliance_count(g,1) >= battle_config.max_guild_alliance ) {
clif_guild_oppositionack(sd,1);
return 0;
}

View File

@ -551,6 +551,8 @@ struct map_session_data {
unsigned doridori : 1;
unsigned ignoreAll : 1;
unsigned short autoloot;
unsigned short autolootid; // [Zephyrus]
unsigned noks : 1; // [Zeph Kill Steal Protection]
struct guild *gmaster_flag;
} state;
struct {
@ -612,6 +614,7 @@ struct map_session_data {
unsigned int canuseitem_tick; // [Skotlex]
unsigned int cantalk_tick;
unsigned int cansendmail_tick; // [Mail System Flood Protection]
unsigned int ks_floodprotect_tick; // [Kill Steal Protection]
short weapontype1,weapontype2;
short disguise; // [Valaris]
@ -911,6 +914,11 @@ struct mob_data {
unsigned int tdmg; //Stores total damage given to the mob, for exp calculations. [Skotlex]
int level;
int target_id,attacked_id;
// Kill Steal Protection
int owner_id;
unsigned int ks_tick;
unsigned int next_walktime,last_thinktime,last_linktime;
short move_fail_count;
short lootitem_count;
@ -1168,6 +1176,7 @@ struct map_data {
int npc_num;
int users;
struct map_flag {
unsigned allowks : 1; // [Kill Steal Protection]
unsigned nomemo : 1;
unsigned noteleport : 1;
unsigned noreturn : 1;

View File

@ -10,6 +10,7 @@
#include "../common/ers.h"
#include "../common/strlib.h"
#include "../common/utils.h"
#include "../common/socket.h"
#include "map.h"
#include "path.h"
@ -275,6 +276,80 @@ int mob_get_random_id(int type, int flag, int lv)
return class_;
}
/*==========================================
* Kill Steal Protection [Zephyrus]
*------------------------------------------*/
bool mob_ksprotected (struct block_list *src, struct block_list *target)
{
struct block_list *s_bl;
struct map_session_data *sd, *pl_sd;
struct mob_data *md;
unsigned int tick = gettick();
char output[128];
if( !battle_config.ksprotection )
return false; // KS Protection Disabled
if( !(md = BL_CAST(BL_MOB,target)) )
return false; // Tarjet is not MOB
if( (s_bl = battle_get_master(src)) == NULL )
s_bl = src;
if( !(sd = BL_CAST(BL_PC,s_bl)) )
return false; // Master is not PC
do {
if( map[md->bl.m].flag.allowks || map[md->bl.m].flag.gvg || map[md->bl.m].flag.pvp )
return false; // Ignores GVG, PVP and AllowKS map flags
if( md->db->mexp || md->master_id )
return false; // MVP and Slaves ignores KS
if( sd->bl.id == md->owner_id )
break; // Same player
if( !md->owner_id || !(pl_sd = map_id2sd(md->owner_id)) )
break; // Not owner or owner offline
if( pl_sd->bl.m != md->bl.m )
break; // Owner on different map
if( DIFF_TICK(md->ks_tick, tick) <= 0 )
break; // Protection Time's Out
if( !pl_sd->state.noks )
return false; // No KS Protected, but this is necessary to protect normal players
if( pl_sd->status.party_id && pl_sd->status.party_id == sd->status.party_id )
break; // Same Party Allow KS
// Message to KS
if( DIFF_TICK(sd->ks_floodprotect_tick, tick) <= 0 )
{
sprintf(output, "[KS Warning!! - Owner : %s]", pl_sd->status.name);
clif_disp_onlyself(sd, output, strlen(output));
sd->ks_floodprotect_tick = tick + 2000;
}
// Message to Owner
if( DIFF_TICK(pl_sd->ks_floodprotect_tick, tick) <= 0 )
{
sprintf(output, "[Warning!! - %s is KS you]", sd->status.name);
clif_disp_onlyself(pl_sd, output, strlen(output));
pl_sd->ks_floodprotect_tick = tick + 2000;
}
return true;
} while(0);
md->owner_id = sd->bl.id;
md->ks_tick = tick + battle_config.ksprotection;
return false;
}
struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m, short x, short y, const char *mobname, int class_, const char *event)
{
@ -1522,8 +1597,9 @@ static int mob_delay_item_drop(int tid, unsigned int tick, int id, int data)
* Sets the item_drop into the item_drop_list.
* Also performs logging and autoloot if enabled.
* rate is the drop-rate of the item, required for autoloot.
* flag : Killed only by homunculus?
*------------------------------------------*/
static void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct item_drop *ditem, int loot, int drop_rate)
static void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct item_drop *ditem, int loot, int drop_rate, unsigned short flag)
{
TBL_PC* sd;
@ -1538,7 +1614,7 @@ static void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, str
sd = map_charid2sd(dlist->first_charid);
if( sd == NULL ) sd = map_charid2sd(dlist->second_charid);
if( sd == NULL ) sd = map_charid2sd(dlist->third_charid);
if( sd && drop_rate <= sd->state.autoloot
if( sd && (drop_rate <= sd->state.autoloot || ditem->item_data.nameid == sd->state.autolootid) && sd->idletime >= (last_tick - battle_config.idle_no_autoloot) && (battle_config.homunculus_autoloot?1:!flag)
#ifdef AUTOLOOT_DISTANCE
&& check_distance_blxy(&sd->bl, dlist->x, dlist->y, AUTOLOOT_DISTANCE)
#endif
@ -1777,6 +1853,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
} pt[DAMAGELOG_SIZE];
int i,temp,count,pnum=0,m=md->bl.m;
unsigned int mvp_damage, tick = gettick();
unsigned short flaghom = 1; // [Zephyrus] Does the mob only received damage from homunculus?
if(src && src->type == BL_PC) {
sd = (struct map_session_data *)src;
@ -1851,6 +1928,9 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
}
tmpsd[i] = tsd; // record as valid damage-log entry
if(!md->dmglog[i].flag && flaghom)
flaghom = 0; // Damage received from other Types != Homunculus
}
if(!battle_config.exp_calc_type && count > 1)
@ -2045,13 +2125,13 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
}
// Announce first, or else ditem will be freed. [Lance]
// By popular demand, use base drop rate for autoloot code. [Skotlex]
mob_item_drop(md, dlist, ditem, 0, md->db->dropitem[i].p);
mob_item_drop(md, dlist, ditem, 0, md->db->dropitem[i].p, flaghom);
}
// Ore Discovery [Celest]
if (sd == mvp_sd && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/10 >= rand()%10000) {
ditem = mob_setdropitem(itemdb_searchrandomid(IG_FINDINGORE), 1);
mob_item_drop(md, dlist, ditem, 0, battle_config.finding_ore_rate/10);
mob_item_drop(md, dlist, ditem, 0, battle_config.finding_ore_rate/10, 0);
}
if(sd) {
@ -2077,7 +2157,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
if (rand()%10000 >= drop_rate)
continue;
itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb_searchrandomid(sd->add_drop[i].group);
mob_item_drop(md, dlist, mob_setdropitem(itemid,1), 0, drop_rate);
mob_item_drop(md, dlist, mob_setdropitem(itemid,1), 0, drop_rate, 0);
}
}
@ -2093,7 +2173,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
// process items looted by the mob
if(md->lootitem) {
for(i = 0; i < md->lootitem_count; i++)
mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000);
mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, 0);
}
if (dlist->item) //There are drop items.
add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, (int)dlist, 0);
@ -2109,7 +2189,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
dlist->third_charid = (third_sd ? third_sd->status.char_id : 0);
dlist->item = NULL;
for(i = 0; i < md->lootitem_count; i++)
mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000);
mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, 0);
add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, (int)dlist, 0);
}

View File

@ -157,6 +157,7 @@ struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m,
int mob_once_spawn(struct map_session_data* sd,int m,short x,short y,const char* mobname,int class_,int amount,const char* event);
int mob_once_spawn_area(struct map_session_data* sd,int m,int x0,int y0,int x1,int y1,const char* mobname,int class_,int amount,const char* event);
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); // Spawning Guardians [Valaris]
int mob_guardian_guildchange(struct block_list *bl,va_list ap); //Change Guardian's ownership. [Skotlex]

View File

@ -2318,6 +2318,8 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
}
map[m].flag.nosave = state;
}
else if (!strcmpi(w3,"allowks"))
map[m].flag.allowks=state; // [Kill Steal Protection]
else if (!strcmpi(w3,"nomemo"))
map[m].flag.nomemo=state;
else if (!strcmpi(w3,"noteleport"))

View File

@ -807,6 +807,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
if(skillnotok(skill_num, sd)) // [MouseJstr]
return 0;
mob_ksprotected(src, map_id2bl(target_id));
switch(skill_num)
{ //Check for skills that auto-select target
case MO_CHAINCOMBO: