diff options
-rw-r--r-- | Changelog-Trunk.txt | 2 | ||||
-rw-r--r-- | conf-tmpl/atcommand_athena.conf | 3 | ||||
-rw-r--r-- | doc/item_bonus.txt | 7 | ||||
-rw-r--r-- | src/map/atcommand.c | 50 | ||||
-rw-r--r-- | src/map/atcommand.h | 1 | ||||
-rw-r--r-- | src/map/mob.c | 8 | ||||
-rw-r--r-- | src/map/mob.h | 7 | ||||
-rw-r--r-- | src/map/npc.c | 31 | ||||
-rw-r--r-- | src/map/pc.c | 4 | ||||
-rw-r--r-- | src/map/script.c | 9 |
10 files changed, 113 insertions, 9 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index d59cfd87c..1f0a738b7 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,8 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. 2007/09/02 + * Added @whereis command (displays normal spawn maps for given mobs). + Defaults to a lv10 command. [Skotlex] * Updated Refined Sakkat Box to give only 1 Sakkat instead of 10. [Paradox924X] 2007/08/31 * Added some comments to clif_changechatowner() diff --git a/conf-tmpl/atcommand_athena.conf b/conf-tmpl/atcommand_athena.conf index e459bb85c..183278246 100644 --- a/conf-tmpl/atcommand_athena.conf +++ b/conf-tmpl/atcommand_athena.conf @@ -210,6 +210,9 @@ model: 10 // Locates and displays the position of a certain mob on your mini-map showmobs: 10 +// Prints out in which maps a monster normally spawns at (does not count script-invoked mobs) +whereis: 10 + // Changes your size. size: 10 diff --git a/doc/item_bonus.txt b/doc/item_bonus.txt index abc8ef622..dc9e7ed63 100644 --- a/doc/item_bonus.txt +++ b/doc/item_bonus.txt @@ -133,7 +133,7 @@ bonus3 bAddMonsterDropItem,n,x,y; When killing monsters from race x with physica 0=Formless, 1=Undead, 2=Brute, 3=Plant, 4=Insect, 5=Fish, 6=Demon, 7=Demi-Human, 8=Angel, 9=Dragon, 10=Boss monster, 11=Other than (normal monster) boss monster if 'x' is negative value, then it's a part of formula chance = -x*(killed_mob_level/10)+1 -bonus3 bAutoSpell,n,x,y; Auto Spell casting of spell n at level x with y/10% chance +bonus3 bAutoSpell,n,x,y; Auto Spell casting on attack of spell n at level x with y/10% chance. Skill is casted on target unless it is a self skill. // bAddDamageClass, bAddMagicDamageClass and bAddMonsterDropItem it is setting possible up to 10. Those which exceed 10 are ignored. // those which can be used with the arrow are only bCritical, bAtkEle, bHit, bAddEle, bAddRace, bAddSize and bAddEff. The other things are ignored. @@ -170,9 +170,8 @@ bonus2 bAddRace2,n,x; Increase damage by x% vs. enemies of race n bonus3 bHPLossRate,n,x,y; Lose n amount of hp every x amount of time y: 0=Don't show damage 1=Show damage bonus3 bAutoSpellWhenHit,x,y,n; n/10% chance to cast skill x of level y on - attacker when being hit by a direct - attack. Target must be within spell's - range to go off. + attacker (except if it is a self-skill) when being hit by a + direct attack. Target must be within spell's range to go off. bonus3 bSPDrainRate,n,x,y; When attacking there is a n% chance to either gain SP equivalent to x% of damage dealt, OR drain the amount of sp from the enemy. diff --git a/src/map/atcommand.c b/src/map/atcommand.c index d0bed703b..11d10534f 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -231,6 +231,7 @@ ACMD_FUNC(mutearea); // by MouseJstr ACMD_FUNC(rates); // by MouseJstr ACMD_FUNC(iteminfo); // Lupus ACMD_FUNC(whodrops); //Skotlex +ACMD_FUNC(whereis); //Skotlex ACMD_FUNC(mapflag); // Lupus ACMD_FUNC(me); //added by massdriller, code by lordalfa ACMD_FUNC(monsterignore); // [Valaris] @@ -527,6 +528,7 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_ItemInfo, "@iteminfo", 1, atcommand_iteminfo }, // [Lupus] { AtCommand_ItemInfo, "@ii", 1, atcommand_iteminfo }, // [Lupus] { AtCommand_WhoDrops, "@whodrops", 1, atcommand_whodrops }, // [Skotlex] + { AtCommand_WhereIs, "@whereis", 10, atcommand_whereis }, // [Skotlex] { AtCommand_MapFlag, "@mapflag", 99, atcommand_mapflag }, // [Lupus] { AtCommand_Me, "@me", 20, atcommand_me }, //added by massdriller, code by lordalfa { AtCommand_MonsterIgnore, "@monsterignore", 99, atcommand_monsterignore }, // [Valaris] @@ -8699,6 +8701,54 @@ int atcommand_whodrops(const int fd, struct map_session_data* sd, const char* co return 0; } +int atcommand_whereis(const int fd, struct map_session_data* sd, const char* command, const char* message) +{ + struct mob_db *mob, *mob_array[MAX_SEARCH]; + int count; + int i, j, k; + + if (!message || !*message) { + clif_displaymessage(fd, "Please, enter a Monster/ID (usage: @whereis<monster_name_or_monster_ID>)."); + return -1; + } + + // If monster identifier/name argument is a name + if ((i = mobdb_checkid(atoi(message)))) + { + mob_array[0] = mob_db(i); + count = 1; + } else + count = mobdb_searchname_array(mob_array, MAX_SEARCH, message); + + if (!count) { + clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. + return -1; + } + + if (count > MAX_SEARCH) { + sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); + clif_displaymessage(fd, atcmd_output); + count = MAX_SEARCH; + } + for (k = 0; k < count; k++) { + mob = mob_array[k]; + snprintf(atcmd_output, sizeof atcmd_output, "%s spawns in:", mob->jname); + clif_displaymessage(fd, atcmd_output); + + for (i = 0; i < ARRAYLENGTH(mob->spawn) && mob->spawn[i].qty; i++) + { + j = map_mapindex2mapid(mob->spawn[i].mapindex); + if (j < 0) continue; + snprintf(atcmd_output, sizeof atcmd_output, "%s (%d)", map[j].name, mob->spawn[i].qty); + clif_displaymessage(fd, atcmd_output); + } + if (i == 0) + clif_displaymessage(fd, "This monster does not spawn normally."); + } + + return 0; +} + /*========================================== * @adopt by [Veider] * adopt a novice diff --git a/src/map/atcommand.h b/src/map/atcommand.h index e5b00046c..9b775a00c 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -217,6 +217,7 @@ enum AtCommandType { AtCommand_Rates, // MouseJstr AtCommand_ItemInfo, // Lupus AtCommand_WhoDrops, // Skotlex + AtCommand_WhereIs, // Skotlex AtCommand_MapFlag, // Lupus AtCommand_MonsterIgnore, // [Valaris] AtCommand_FakeName, // [Valaris] diff --git a/src/map/mob.c b/src/map/mob.c index f3cec671a..01679708b 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -3991,6 +3991,14 @@ void mob_reload(void) mob_readdb_race(); } +void mob_clear_spawninfo() +{ //Clears spawn related information for a script reload. + int i; + for (i = 0; i < MAX_MOB_DB; i++) + if (mob_db_data[i]) + memset(&mob_db_data[i]->spawn,0,sizeof(mob_db_data[i]->spawn)); +} + /*========================================== * Circumference initialization of mob *------------------------------------------*/ diff --git a/src/map/mob.h b/src/map/mob.h index 944ab84ac..e75de3912 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -56,6 +56,11 @@ struct mob_skill { short emotion; }; +struct spawn_info { + unsigned short mapindex; + unsigned short qty; +}; + struct mob_db { char sprite[NAME_LENGTH],name[NAME_LENGTH],jname[NAME_LENGTH]; unsigned int base_exp,job_exp; @@ -71,6 +76,7 @@ struct mob_db { int summonper[MAX_RANDOMMONSTER]; int maxskill; struct mob_skill skill[MAX_MOBSKILL]; + struct spawn_info spawn[10]; }; enum { @@ -173,6 +179,7 @@ void mob_heal(struct mob_data *md,unsigned int heal); #define mob_stop_walking(md, type) { if (md->ud.walktimer != -1) unit_stop_walking(&md->bl, type); } #define mob_stop_attack(md) { if (md->ud.attacktimer != -1) unit_stop_attack(&md->bl); } +void mob_clear_spawninfo(); int do_init_mob(void); int do_final_mob(void); diff --git a/src/map/npc.c b/src/map/npc.c index 40df4b678..c2ab39446 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -2341,6 +2341,7 @@ int npc_parse_mob(char* w1, char* w2, char* w3, char* w4) char mapname[MAP_NAME_LENGTH_EXT]; char mobname[NAME_LENGTH]; struct spawn_data mob, *data; + struct mob_db* db; memset(&mob, 0, sizeof(struct spawn_data)); @@ -2397,8 +2398,9 @@ int npc_parse_mob(char* w1, char* w2, char* w3, char* w4) mob.xs = mob.ys = -1; } + db = mob_db(class_); //Apply the spawn delay fix [Skotlex] - mode = mob_db(class_)->status.mode; + mode = db->status.mode; if (mode & MD_BOSS) { //Bosses if (battle_config.boss_spawn_delay != 100) { // Divide by 100 first to prevent overflows @@ -2438,6 +2440,32 @@ int npc_parse_mob(char* w1, char* w2, char* w3, char* w4) if (!mob_parse_dataset(&mob)) //Verify dataset. return 1; + for(x=0; x < ARRAYLENGTH(db->spawn); x++) + { + if (map[mob.m].index == db->spawn[x].mapindex) + { //Update total + db->spawn[x].qty += mob.num; + //Re-sort list + for (y = x; y>0 && db->spawn[y-1].qty < db->spawn[x].qty; y--); + if (y != x) + { + xs = db->spawn[x].mapindex; + ys = db->spawn[x].qty; + memmove(&db->spawn[y+1], &db->spawn[y], (x-y)*sizeof(db->spawn[0])); + db->spawn[y].mapindex = xs; + db->spawn[y].qty = ys; + } + break; + } + if (mob.num > db->spawn[x].qty) + { //Insert into list + memmove(&db->spawn[x+1], &db->spawn[x], sizeof(db->spawn) -(x+1)*sizeof(db->spawn[0])); + db->spawn[x].mapindex = map[mob.m].index; + db->spawn[x].qty = mob.num; + break; + } + } + //Now that all has been validated. We allocate the actual memory //that the re-spawn data will use. data = aMalloc(sizeof(struct spawn_data)); @@ -2940,6 +2968,7 @@ int npc_reload(void) if (map[m].npc_num > 0 && battle_config.error_log) ShowWarning("npc_reload: %d npcs weren't removed at map %s!\n", map[m].npc_num, map[m].name); } + mob_clear_spawninfo(); // anything else we should cleanup? // Reloading npc's now diff --git a/src/map/pc.c b/src/map/pc.c index e564c3554..30d012b5e 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -2365,11 +2365,11 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) break; case SP_AUTOSPELL: if(sd->state.lr_flag != 2) - pc_bonus_autospell(sd->autospell, MAX_PC_BONUS, type2, type3, val, 0, current_equip_card_id); + pc_bonus_autospell(sd->autospell, MAX_PC_BONUS, skill_get_inf(type2)&INF_SELF_SKILL?-type2:type2, type3, val, 0, current_equip_card_id); break; case SP_AUTOSPELL_WHENHIT: if(sd->state.lr_flag != 2) - pc_bonus_autospell(sd->autospell2, MAX_PC_BONUS, type2, type3, val, 0, current_equip_card_id); + pc_bonus_autospell(sd->autospell2, MAX_PC_BONUS, skill_get_inf(type2)&INF_SELF_SKILL?-type2:type2, type3, val, 0, current_equip_card_id); break; case SP_HP_LOSS_RATE: if(sd->state.lr_flag != 2) { diff --git a/src/map/script.c b/src/map/script.c index d115e6df3..a98dffe5c 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -8737,8 +8737,13 @@ BUILDIN_FUNC(homunculus_evolution) { TBL_PC *sd; sd=script_rid2sd(st); - if(merc_is_hom_active(sd->hd) && sd->hd->homunculus.intimacy > 91000) - merc_hom_evolution(sd->hd); + if(merc_is_hom_active(sd->hd)) + { + if (sd->hd->homunculus.intimacy > 91000) + merc_hom_evolution(sd->hd); + else + clif_emotion(&sd->hd->bl, 4) ; //swt + } return 0; } |