ACMD_FUNC(mobinfo)
{
unsigned char msize[SZ_ALL][7] = { "Small", "Medium", "Large" };
unsigned char mrace[RC_ALL][11] = { "Formless", "Undead", "Beast", "Plant", "Insect", "Fish", "Demon", "Demi-Human", "Angel", "Dragon", "Player" };
unsigned char melement[ELE_ALL][8] = { "Neutral", "Water", "Earth", "Fire", "Wind", "Poison", "Holy", "Dark", "Ghost", "Undead" };
char mmode[29][35] = { "Can Move", "Looter", "Aggressive", "Assist", "Cast Sensor", "No Random Walk", "No Skills", "Can-Attack", "IMAFREEBITCHBABY",
"Change Target", "Change Chase", "Aggressive", "Change Target (Melee)", "Change Target (Chase)", "Ignores targets above level %d",
"Random Targets", "Ignores Melee", "Ignores Magic", "Ignores Ranged", "Boss-Type", "Plant-Type", "Immune to Knockback", "CAN TELEPORT NO MATTER THE RULES",
"ALSOFREE", "NO LOOT", "Fixed Item Drops", "Detector", "Status Immune", "Immune to Skills" };
char atcmd_output2[CHAT_SIZE_MAX];
struct item_data *item_data;
struct mob_db *mob;
uint16 mob_ids[MAX_SEARCH];
int count;
int i, k;
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(atcmd_output2, '\0', sizeof(atcmd_output2));
if (!message || !*message) {
clif_displaymessage(fd, msg_txt(sd,1239)); // Please enter a monster name/ID (usage: @mobinfo <monster_name_or_monster_ID>).
return -1;
}
// If monster identifier/name argument is a name
if ((i = mobdb_checkid(atoi(message))))
{
mob_ids[0] = i;
count = 1;
} else
count = mobdb_searchname_array(message, mob_ids, MAX_SEARCH);
if (!count) {
clif_displaymessage(fd, msg_txt(sd,40)); // Invalid monster ID or name.
return -1;
}
if (count >= MAX_SEARCH) {
sprintf(atcmd_output, msg_txt(sd,269), MAX_SEARCH); // Displaying first %d matches
clif_displaymessage(fd, atcmd_output);
count = MAX_SEARCH;
}
for (k = 0; k < count; k++) {
unsigned int j;
char hp[32] = { '\0' };
uint16 maxflee = 0, maxhit = 0;
unsigned int base_kp;
char kp[32] = { '\0' };
unsigned int base_exp, job_exp;
char bxp[32] = { '\0' };
char jxp[32] = { '\0' };
mob = mob_db(mob_ids[k]);
base_exp = mob->base_exp;
job_exp = mob->job_exp;
commas(mob->status.max_hp, hp);
if (battle_config.mvpkp_active)
{
base_kp = mob->kp_party;
commas(mob->status.max_hp, hp);
commas(base_kp, kp);
}
commas(base_exp, bxp);
commas(job_exp, jxp);
if (pc_isvip(sd)) { // Display EXP rate increase for VIP
base_exp = (base_exp * battle_config.vip_base_exp_increase) / 100;
job_exp = (job_exp * battle_config.vip_job_exp_increase) / 100;
}
#ifdef RENEWAL_EXP
if (battle_config.atcommand_mobinfo_type) {
base_exp = base_exp * pc_level_penalty_mod(mob->lv - sd->status.base_level, mob->status.class_, mob->status.mode, 1) / 100;
job_exp = job_exp * pc_level_penalty_mod(mob->lv - sd->status.base_level, mob->status.class_, mob->status.mode, 1) / 100;
}
#endif
#ifdef RENEWAL
maxhit = MOB_FLEE(mob) + 100;
maxflee = MOB_HIT(mob) -5;
#else
maxhit = MOB_FLEE(mob) + 20;
maxflee = MOB_HIT(mob) + 75;
#endif
// stats
if (mob->mexp)
sprintf(atcmd_output, msg_txt(sd,1240), mob->name, mob->jname, mob->sprite, mob->vd.class_); // MVP Monster: '%s'/'%s'/'%s' (%d)
else
sprintf(atcmd_output, msg_txt(sd,1241), mob->name, mob->jname, mob->sprite, mob->vd.class_); // Monster: '%s'/'%s'/'%s' (%d)
clif_displaymessage(fd, atcmd_output);
sprintf(atcmd_output, " Lv:%u HP:%s ", mob->lv, hp);
clif_displaymessage(fd, atcmd_output);
if (battle_config.mvpkp_active && mob->mexp)
{
sprintf(atcmd_output, " KP:%s", kp);
clif_displaymessage(fd, atcmd_output);
}
sprintf(atcmd_output, " BEXP: %s JEXP: %s", bxp, jxp);
clif_displaymessage(fd, atcmd_output);
sprintf(atcmd_output, " ATK: %d~%d | MATK: %d~%d | DEF: %d+%d | MDEF: %d+%d | ASPD: %3.1f",
mob->status.rhw.atk, mob->status.rhw.atk2, mob->status.matk_min, mob->status.matk_max,
#ifdef RENEWAL
mob->status.def2, mob->status.def,
mob->status.mdef2, mob->status.mdef,
#else
mob->status.def, mob->status.def2,
mob->status.mdef, mob->status.mdef2,
#endif
200. - (double)mob->status.adelay / 20.);
clif_displaymessage(fd, atcmd_output);
sprintf(atcmd_output, " 100%% Hit: %d | 95%% Flee: %d | Critshield: %.2f%%", maxhit, maxflee, (double)mob->status.luk / 5.);
clif_displaymessage(fd, atcmd_output);
sprintf(atcmd_output, " Size: %s | Race: %s | Element: %s (Lv:%d)",
msize[mob->status.size],
mrace[mob->status.race], melement[mob->status.def_ele], mob->status.ele_lv);
clif_displaymessage(fd, atcmd_output);
sprintf(atcmd_output, " Range: (Attack: %d View: %d Chase: %d)", mob->status.rhw.range, mob->range2, mob->range3);
clif_displaymessage(fd, atcmd_output);
clif_displaymessage(fd, " Modes:");
strcpy(atcmd_output, " ");
strcpy(atcmd_output2, " ");
j = 0;
for (i = 0; i < 14; i++) {
if (mob->status.mode&(1 << i))
{
// let's just output everything because why not flood the chat window
sprintf(atcmd_output2, " - %s", mmode[i]);
}
else
continue;
strcat(atcmd_output, atcmd_output2);
if (++j % 4 == 0)
{
clif_displaymessage(fd, atcmd_output);
strcpy(atcmd_output, " ");
}
}
if (j == 0)
clif_displaymessage(fd, "None");
else if (j % 4 != 0)
clif_displaymessage(fd, atcmd_output);
// drops
clif_displaymessage(fd, msg_txt(sd,1245)); // Drops:
strcpy(atcmd_output, " ");
j = 0;
for (i = 0; i < MAX_MOB_DROP_TOTAL; i++) {
int droprate;
char itemlink[CHAT_SIZE_MAX] = "";
if (mob->dropitem[i].nameid <= 0 || mob->dropitem[i].p < 1 || (item_data = itemdb_exists(mob->dropitem[i].nameid)) == NULL)
continue;
droprate = mob->dropitem[i].p;
#ifdef RENEWAL_DROP
if( battle_config.atcommand_mobinfo_type ) {
droprate = droprate * pc_level_penalty_mod(mob->lv - sd->status.base_level, mob->status.class_, mob->status.mode, 2) / 100;
if (droprate <= 0 && !battle_config.drop_rate0item)
droprate = 1;
}
#endif
char itemlink[CHAT_SIZE_MAX] = "";
itemdb_idlinkcreate(itemlink, mob->dropitem[i].nameid);
if (pc_isvip(sd)) // Display drop rate increase for VIP
droprate += (droprate * battle_config.vip_drop_increase) / 100;
sprintf(atcmd_output2, " - %s %02.02f%%", itemlink, (float)droprate / 100);
strcat(atcmd_output, atcmd_output2);
if (++j % 3 == 0) {
clif_displaymessage(fd, atcmd_output);
strcpy(atcmd_output, " ");
}
}
if (j == 0)
clif_displaymessage(fd, msg_txt(sd,1246)); // This monster has no drops.
else if (j % 3 != 0)
clif_displaymessage(fd, atcmd_output);
// mvp
if (mob->mexp) {
float mvppercent, mvpremain;
char mxp[32] = { '\0' };
commas(mob->mexp, mxp);
sprintf(atcmd_output, msg_txt(sd, 1247), mob->mexp); // MVP Bonus EXP:%u
clif_displaymessage(fd, atcmd_output);
if (battle_config.mvpkp_active)
{
char mkp[16] = { '\0' };
commas(mob->kp_mvp, mkp);
sprintf(atcmd_output, "MVP Bonus KP: %s", mkp); // MVP Bonus EXP:%u
clif_displaymessage(fd, atcmd_output);
}
strcpy(atcmd_output, msg_txt(sd,1248)); // MVP Items:
mvpremain = 100.0; //Remaining drop chance for official mvp drop mode
j = 0;
for (i = 0; i < MAX_MVP_DROP_TOTAL; i++) {
if (mob->mvpitem[i].nameid <= 0 || (item_data = itemdb_exists(mob->mvpitem[i].nameid)) == NULL)
continue;
//Because if there are 3 MVP drops at 50%, the first has a chance of 50%, the second 25% and the third 12.5%
mvppercent = (float)mob->mvpitem[i].p * mvpremain / 10000.0f;
if(battle_config.item_drop_mvp_mode == 0) {
mvpremain -= mvppercent;
}
if (mvppercent > 0) {
char itemlink[CHAT_SIZE_MAX] = "";
j++;
itemdb_idlinkcreate(itemlink, mob->mvpitem[i].nameid);
if (j == 1) {
sprintf(atcmd_output2, " %s %02.02f%%", itemlink, mvppercent);
} else {
sprintf(atcmd_output2, " - %s %02.02f%%", itemlink, mvppercent);
}
strcat(atcmd_output, atcmd_output2);
}
}
if (j == 0)
clif_displaymessage(fd, msg_txt(sd,1249)); // This monster has no MVP prizes.
else
clif_displaymessage(fd, atcmd_output);
}
}
return 0;
}
ACMD_FUNC(iteminfo)
{
struct item_data *item_array[MAX_SEARCH];
int i, count = 1;
if (!message || !*message) {
clif_displaymessage(fd, msg_txt(sd,1276)); // Please enter an item name/ID (usage: @ii/@iteminfo <item name/ID>).
return -1;
}
if ((item_array[0] = itemdb_exists(atoi(message))) == NULL)
count = itemdb_searchname_array(item_array, MAX_SEARCH, message);
if (!count) {
clif_displaymessage(fd, msg_txt(sd,19)); // Invalid item ID or name.
return -1;
}
if (count == MAX_SEARCH) {
sprintf(atcmd_output, msg_txt(sd,269), MAX_SEARCH); // Displaying first %d matches
clif_displaymessage(fd, atcmd_output);
}
for (i = 0; i < count; i++) {
struct item_data * item_data = item_array[i];
char itemlink[CHAT_SIZE_MAX] = "";
itemdb_idlinkcreate(itemlink, item_data->nameid);
/*
sprintf(atcmd_output, msg_txt(sd,1277), // Item: '%s'/'%s'[%d] (%hu) Type: %s | Extra Effect: %s
item_data->name,item_data->jname,item_data->slot,item_data->nameid,
(item_data->type != IT_AMMO) ? itemdb_typename((enum item_types)item_data->type) : itemdb_typename_ammo((enum e_item_ammo)item_data->look),
(item_data->script==NULL)? msg_txt(sd,1278) : msg_txt(sd,1279) // None / With script
);
*/
sprintf(atcmd_output, "Item: %s / %s (%hu) Type : %s | Extra Effect : %s", // Item: %s Type: %s | Extra Effect: %s
itemlink, item_data->name, item_data->nameid,
(item_data->type != IT_AMMO) ? itemdb_typename((enum item_types)item_data->type) : itemdb_typename_ammo((enum e_item_ammo)item_data->look),
(item_data->script == NULL) ? msg_txt(sd, 1278) : msg_txt(sd, 1279) // None / With script
);
clif_displaymessage(fd, atcmd_output);
sprintf(atcmd_output, msg_txt(sd,1280), item_data->value_buy, item_data->value_sell, item_data->weight/10. ); // NPC Buy:%dz, Sell:%dz | Weight: %.1f
clif_displaymessage(fd, atcmd_output);
if (item_data->maxchance == -1) {
strcpy(atcmd_output, msg_txt(sd,1281)); // - Available in the shops only.
clif_displaymessage(fd, atcmd_output);
}
else if (!battle_config.atcommand_mobinfo_type) {
if (item_data->maxchance)
sprintf(atcmd_output, msg_txt(sd,1282), (float)item_data->maxchance / 100 ); // - Maximal monsters drop chance: %02.02f%%
else
strcpy(atcmd_output, msg_txt(sd,1283)); // - Monsters don't drop this item.
}
}
return 0;
}