viewing paste Unknown #6533 | C

Posted on the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
static bool mob_parse_dbrow(char** str)
{
    struct mob_db *db, entry;
    struct status_data *status;
    int class_, i, k;
    double exp, maxhp;
    struct mob_data data;
 
    class_ = atoi(str[0]);
 
    if (class_ <= 1000 || class_ > MAX_MOB_DB) {
        ShowError("mob_parse_dbrow: Invalid monster ID %d, must be in range %d-%d.\n", class_, 1000, MAX_MOB_DB);
        return false;
    }
    if (pcdb_checkid(class_)) {
        ShowError("mob_parse_dbrow: Invalid monster ID %d, reserved for player classes.\n", class_);
        return false;
    }
 
    if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END) {
        ShowError("mob_parse_dbrow: Invalid monster ID %d. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d).\n", class_, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB);
        return false;
    }
 
    memset(&entry, 0, sizeof(entry));
 
    db = &entry;
    status = &db->status;
 
    db->vd.class_ = class_;
    safestrncpy(db->sprite, str[1], sizeof(db->sprite));
    safestrncpy(db->jname, str[2], sizeof(db->jname));
    safestrncpy(db->name, str[3], sizeof(db->name));
    db->lv = atoi(str[4]);
    db->lv = cap_value(db->lv, 1, USHRT_MAX);
    status->max_hp = atoi(str[5]);
    status->max_sp = atoi(str[6]);
 
    exp = (double)atoi(str[7]) * (double)battle_config.base_exp_rate / 100.;
    db->base_exp = (unsigned int)cap_value(exp, 0, UINT_MAX);
 
    exp = (double)atoi(str[8]) * (double)battle_config.job_exp_rate / 100.;
    db->job_exp = (unsigned int)cap_value(exp, 0, UINT_MAX);
 
    status->rhw.range = atoi(str[9]);
    status->rhw.atk = atoi(str[10]);
    status->rhw.atk2 = atoi(str[11]);
    status->def = atoi(str[12]);
    status->mdef = atoi(str[13]);
    status->str = atoi(str[14]);
    status->agi = atoi(str[15]);
    status->vit = atoi(str[16]);
    status->int_ = atoi(str[17]);
    status->dex = atoi(str[18]);
    status->luk = atoi(str[19]);
    //All status should be min 1 to prevent divisions by zero from some skills. [Skotlex]
    if (status->str < 1) status->str = 1;
    if (status->agi < 1) status->agi = 1;
    if (status->vit < 1) status->vit = 1;
    if (status->int_< 1) status->int_= 1;
    if (status->dex < 1) status->dex = 1;
    if (status->luk < 1) status->luk = 1;
 
    db->range2 = atoi(str[20]);
    db->range3 = atoi(str[21]);
    if (battle_config.view_range_rate != 100) {
        db->range2 = db->range2 * battle_config.view_range_rate / 100;
        if (db->range2 < 1)
            db->range2 = 1;
    }
    if (battle_config.chase_range_rate != 100) {
        db->range3 = db->range3 * battle_config.chase_range_rate / 100;
        if (db->range3 < db->range2)
            db->range3 = db->range2;
    }
 
    status->size = atoi(str[22]);
    status->race = atoi(str[23]);
 
    i = atoi(str[24]); //Element
    status->def_ele = i%10;
    status->ele_lv = i/20;
    if (status->def_ele >= ELE_MAX) {
        ShowError("mob_parse_dbrow: Invalid element type %d for monster ID %d (max=%d).\n", status->def_ele, class_, ELE_MAX-1);
        return false;
    }
    if (status->ele_lv < 1 || status->ele_lv > 4) {
        ShowError("mob_parse_dbrow: Invalid element level %d for monster ID %d, must be in range 1-4.\n", status->ele_lv, class_);
        return false;
    }
 
    status->mode = (int)strtol(str[25], NULL, 0);
    if (!battle_config.monster_active_enable)
        status->mode &= ~MD_AGGRESSIVE;
 
    status->speed = atoi(str[26]);
    status->aspd_rate = 1000;
    i = atoi(str[27]);
    status->adelay = cap_value(i, battle_config.monster_max_aspd*2, 4000);
    i = atoi(str[28]);
    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]);
    if(battle_config.monster_damage_delay_rate != 100)
        status->dmotion = status->dmotion * battle_config.monster_damage_delay_rate / 100;
 
    // Fill in remaining status data by using a dummy monster.
    data.bl.type = BL_MOB;
    data.level = db->lv;
    memcpy(&data.status, status, sizeof(struct status_data));
    iStatus->calc_misc(&data.bl, status, db->lv);
 
    // 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.;
    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]
    maxhp = (double)status->max_hp;
    if (db->mexp > 0) { //Mvp
        if (battle_config.mvp_hp_rate != 100)
            maxhp = maxhp * (double)battle_config.mvp_hp_rate / 100.;
    } else //Normal mob
        if (battle_config.monster_hp_rate != 100)
            maxhp = maxhp * (double)battle_config.monster_hp_rate / 100.;
 
    status->max_hp = (unsigned int)cap_value(maxhp, 1, UINT_MAX);
    if(status->max_sp < 1) status->max_sp = 1;
 
    //Since mobs always respawn with full life...
    status->hp = status->max_hp;
    status->sp = status->max_sp;
 
    // 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]);
        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);
 
        //calculate and store Max available drop chance of the MVP item
        if (db->mvpitem[i].p) {
            struct item_data *id;
            id = itemdb->search(db->mvpitem[i].nameid);
            if (id->maxchance == -1 || (id->maxchance < db->mvpitem[i].p/10 + 1) ) {
                //item has bigger drop chance or sold in shops
                id->maxchance = db->mvpitem[i].p/10 + 1; //reduce MVP drop info to not spoil common drop rate
            }
        }
    }
 
    for(i = 0; i < MAX_MOB_DROP; i++) {
        int rate = 0, rate_adjust, type;
        unsigned short ratemin, ratemax;
        struct item_data *id;
        k = 31 + 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.
            continue;
        }
        id = itemdb->search(db->dropitem[i].nameid);
        type = id->type;
        rate = atoi(str[k+1]);
        if( (class_ >= 1324 && class_ <= 1363) || (class_ >= 1938 && class_ <= 1946) )
        {   //Treasure box drop rates [Skotlex]
            rate_adjust = battle_config.item_rate_treasure;
            ratemin = battle_config.item_drop_treasure_min;
            ratemax = battle_config.item_drop_treasure_max;
        }
        else switch (type)
        { // Added suport to restrict normal drops of MVP's [Reddozen]
        case IT_HEALING:
            rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_heal_boss : battle_config.item_rate_heal;
            ratemin = battle_config.item_drop_heal_min;
            ratemax = battle_config.item_drop_heal_max;
            break;
        case IT_USABLE:
        case IT_CASH:
            rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_use_boss : battle_config.item_rate_use;
            ratemin = battle_config.item_drop_use_min;
            ratemax = battle_config.item_drop_use_max;
            break;
        case IT_WEAPON:
        case IT_ARMOR:
        case IT_PETARMOR:
            rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_equip_boss : battle_config.item_rate_equip;
            ratemin = battle_config.item_drop_equip_min;
            ratemax = battle_config.item_drop_equip_max;
            break;
        case IT_CARD:
            rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_card_boss : battle_config.item_rate_card;
            ratemin = battle_config.item_drop_card_min;
            ratemax = battle_config.item_drop_card_max;
            break;
        default:
            rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_common_boss : battle_config.item_rate_common;
            ratemin = battle_config.item_drop_common_min;
            ratemax = battle_config.item_drop_common_max;
            break;
        }
        item_dropratio_adjust(id->nameid, class_, &rate_adjust);
        db->dropitem[i].p = mob_drop_adjust(rate, rate_adjust, ratemin, ratemax);
 
        //calculate and store Max available drop chance of the item
        if( db->dropitem[i].p && (class_ < 1324 || class_ > 1363) && (class_ < 1938 || class_ > 1946) )
        { //Skip treasure chests.
            if (id->maxchance == -1 || (id->maxchance < db->dropitem[i].p) ) {
                id->maxchance = db->dropitem[i].p; //item has bigger drop chance or sold in shops
            }
            for (k = 0; k< MAX_SEARCH; k++) {
                if (id->mob[k].chance <= db->dropitem[i].p)
                    break;
            }
            if (k == MAX_SEARCH)
                continue;
 
            if (id->mob[k].id != class_)
                memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0]));
            id->mob[k].chance = db->dropitem[i].p;
            id->mob[k].id = class_;
        }
    }
    // Finally insert monster's data into the database.
    if (mob_db_data[class_] == NULL)
        mob_db_data[class_] = (struct mob_db*)aMalloc(sizeof(struct mob_db));
    else
        //Copy over spawn data
        memcpy(&db->spawn, mob_db_data[class_]->spawn, sizeof(db->spawn));      
 
    memcpy(mob_db_data[class_], db, sizeof(struct mob_db));
    return true;
}
 
Viewed 1041 times, submitted by Guest.