///ALTER TABLE `mob_db` ADD `attr` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `Mode` ///ALTER TABLE `mob_db2` ADD `attr` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `Mode` Index: src/map/status.h =================================================================== --- src/map/status.h (revision 17271) +++ src/map/status.h (working copy) @@ -1428,6 +1428,15 @@ MD_MASK = 0xFFFF, }; +enum e_attr { + ATR_IGNOREMELEE = 0x01, //takes 1 HP damage from melee physical attacks + ATR_IGNOREMAGIC = 0x02, //takes 1 HP damage from magic + ATR_IGNORERANGED = 0x04, //takes 1 HP damage from ranged physical attacks + ATR_MVP = 0x08, //MVP - instant kill / coma-like skills don't work + ATR_IGNOREMISC = 0x10, //takes 1 HP damage from "none" attack type + ATR_KNOCKBACK_IMMUNE = 0x20, //can't be knocked back +}; + //Status change option definitions (options are what makes status changes visible to chars //who were not on your field of sight when it happened) @@ -1616,6 +1625,7 @@ speed, amotion, adelay, dmotion, mode; + enum e_attr attr; //attribute short hit, flee, cri, flee2, def2, mdef2, @@ -1780,6 +1790,7 @@ #define status_get_race(bl) status_get_status_data(bl)->race #define status_get_size(bl) status_get_status_data(bl)->size #define status_get_mode(bl) status_get_status_data(bl)->mode +#define status_get_attr(bl) status_get_status_data(bl)->attr int status_get_party_id(struct block_list *bl); int status_get_guild_id(struct block_list *bl); int status_get_emblem_id(struct block_list *bl); Index: src/map/battle.c =================================================================== --- src/map/battle.c (revision 17271) +++ src/map/battle.c (working copy) @@ -737,6 +737,7 @@ struct status_change *sc; struct status_change_entry *sce; int div_ = d->div_, flag = d->flag; + int attr; nullpo_ret(bl); @@ -745,6 +746,20 @@ if( battle_config.ksprotection && mob_ksprotected(src, bl) ) return 0; + attr = status_get_attr(bl); + if (attr) { + if (attr&ATR_KNOCKBACK_IMMUNE) //no pushback + d->blewcount = 0; + if ( (attr&ATR_IGNOREMELEE && flag&(BF_SHORT|BF_WEAPON) == (BF_LONG|BF_WEAPON) ) //physical melee + || (attr&ATR_IGNOREMAGIC && flag&(BF_MAGIC) ) //magic + || (attr&ATR_IGNORERANGED && flag&(BF_LONG|BF_WEAPON) == (BF_LONG|BF_WEAPON) ) //physical ranged + || (attr&ATR_IGNOREMISC && flag&(BF_MISC) ) //misc + ) { + d->damage = d->damage2 = 1; + return 1; //do 1 dammage + } + } + if (bl->type == BL_PC) { sd=(struct map_session_data *)bl; //Special no damage states @@ -760,6 +775,7 @@ if(!damage) return 0; } + sc = status_get_sc(bl); if( sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) @@ -1692,7 +1708,7 @@ //Initial flag flag.rh=1; flag.weapon=1; - flag.infdef=(tstatus->mode&MD_PLANT && skill_id != RA_CLUSTERBOMB + flag.infdef=( (tstatus->mode&MD_PLANT) && skill_id != RA_CLUSTERBOMB #ifdef RENEWAL && skill_id != HT_FREEZINGTRAP #endif @@ -3460,7 +3476,7 @@ #ifdef RENEWAL if( flag.cri ){ - ATK_ADDRATE( sd->bonus.crit_atk_rate >= 100 ? sd->bonus.crit_atk_rate - 60 : 40 ); + ATK_ADDRATE( sd->bonus.crit_atk_rate >= 100 ? sd->bonus.crit_atk_rate - 60 : 40 ); } #endif Index: src/map/mob.c =================================================================== --- src/map/mob.c (revision 17271) +++ src/map/mob.c (working copy) @@ -3739,18 +3739,19 @@ status->mode = (int)strtol(str[25], NULL, 0); if (!battle_config.monster_active_enable) status->mode &= ~MD_AGGRESSIVE; + status->attr = (int)strtol(str[26], NULL, 0); - status->speed = atoi(str[26]); + status->speed = atoi(str[27]); status->aspd_rate = 1000; - i = atoi(str[27]); + i = atoi(str[28]); status->adelay = cap_value(i, battle_config.monster_max_aspd*2, 4000); - i = atoi(str[28]); + i = atoi(str[29]); status->amotion = cap_value(i, battle_config.monster_max_aspd, 2000); //If the attack animation is longer than the delay, the client crops the attack animation! //On aegis there is no real visible effect of having a recharge-time less than amotion anyway. if (status->adelay < status->amotion) status->adelay = status->amotion; - status->dmotion = atoi(str[29]); + status->dmotion = atoi(str[30]); if(battle_config.monster_damage_delay_rate != 100) status->dmotion = status->dmotion * battle_config.monster_damage_delay_rate / 100; @@ -3762,7 +3763,7 @@ // MVP EXP Bonus: MEXP // Some new MVP's MEXP multipled by high exp-rate cause overflow. [LuzZza] - exp = (double)atoi(str[30]) * (double)battle_config.mvp_exp_rate / 100.; + exp = (double)atoi(str[31]) * (double)battle_config.mvp_exp_rate / 100.; db->mexp = (unsigned int)cap_value(exp, 0, UINT_MAX); //Now that we know if it is an mvp or not, apply battle_config modifiers [Skotlex] @@ -3784,13 +3785,13 @@ // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per for(i = 0; i < MAX_MVP_DROP; i++) { int rate_adjust = battle_config.item_rate_mvp;; - db->mvpitem[i].nameid = atoi(str[31+i*2]); + db->mvpitem[i].nameid = atoi(str[32+i*2]); if (!db->mvpitem[i].nameid) { db->mvpitem[i].p = 0; //No item.... continue; } item_dropratio_adjust(db->mvpitem[i].nameid, class_, &rate_adjust); - db->mvpitem[i].p = mob_drop_adjust(atoi(str[32+i*2]), rate_adjust, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max); + db->mvpitem[i].p = mob_drop_adjust(atoi(str[33+i*2]), rate_adjust, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max); //calculate and store Max available drop chance of the MVP item if (db->mvpitem[i].p) { @@ -3807,7 +3808,7 @@ int rate = 0, rate_adjust, type; unsigned short ratemin, ratemax; struct item_data *id; - k = 31 + MAX_MVP_DROP*2 + i*2; + k = 32 + MAX_MVP_DROP*2 + i*2; db->dropitem[i].nameid = atoi(str[k]); if (!db->dropitem[i].nameid) { db->dropitem[i].p = 0; //No drop. @@ -3914,7 +3915,7 @@ } } - sv_readdb(db_path, filename[fi], ',', 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, -1, &mob_readdb_sub); + sv_readdb(db_path, filename[fi], ',', 32+2*MAX_MVP_DROP+2*MAX_MOB_DROP, 32+2*MAX_MVP_DROP+2*MAX_MOB_DROP, -1, &mob_readdb_sub); } } @@ -3939,12 +3940,12 @@ while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) { // wrap the result into a TXT-compatible format char line[1024]; - char* str[31+2*MAX_MVP_DROP+2*MAX_MOB_DROP]; + char* str[32+2*MAX_MVP_DROP+2*MAX_MOB_DROP]; char* p; int i; lines++; - for(i = 0, p = line; i < 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP; i++) + for(i = 0, p = line; i < 32+2*MAX_MVP_DROP+2*MAX_MOB_DROP; i++) { char* data; size_t len;