summaryrefslogtreecommitdiff
path: root/src/map/mob.c
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-04-12 16:32:34 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-04-12 16:32:34 +0000
commit1b28f3cc0bc670b82e71d12ad67e263f4e04d1f3 (patch)
treed16af0b7ad223dab2257f55fa7c03966e6fc1458 /src/map/mob.c
parentaa12e269a5affb4daa1f7d5c05160cab22d05aca (diff)
downloadhercules-1b28f3cc0bc670b82e71d12ad67e263f4e04d1f3.tar.gz
hercules-1b28f3cc0bc670b82e71d12ad67e263f4e04d1f3.tar.bz2
hercules-1b28f3cc0bc670b82e71d12ad67e263f4e04d1f3.tar.xz
hercules-1b28f3cc0bc670b82e71d12ad67e263f4e04d1f3.zip
- Simplified the mob-drops structure by using a single timer with a linked list of drops instead of separate timers for each drop.
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@6014 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map/mob.c')
-rw-r--r--src/map/mob.c145
1 files changed, 75 insertions, 70 deletions
diff --git a/src/map/mob.c b/src/map/mob.c
index d532aa75a..41011495e 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -48,7 +48,8 @@ struct mob_db *mob_dummy = NULL; //Dummy mob to be returned when a non-existant
struct mob_db *mob_db(int index) { if (index < 0 || index > MAX_MOB_DB || mob_db_data[index] == NULL) return mob_dummy; return mob_db_data[index]; }
-static struct eri *delay_drop_ers; //For loot drops delay structures.
+static struct eri *item_drop_ers; //For loot drops delay structures.
+static struct eri *item_drop_list_ers;
#define CLASSCHANGE_BOSS_NUM 21
/*==========================================
@@ -1380,30 +1381,29 @@ static int mob_ai_hard(int tid,unsigned int tick,int id,int data)
* Data is put in and passed to this structure object.
*------------------------------------------
*/
-struct delay_item_drop {
- int m,x,y;
+struct item_drop {
struct item item_data;
+ struct item_drop *next;
+};
+
+struct item_drop_list {
+ int m,x,y;
struct map_session_data *first_sd,*second_sd,*third_sd;
+ struct item_drop *item;
};
/*==========================================
* Initializes the delay drop structure for mob-dropped items.
*------------------------------------------
*/
-static struct delay_item_drop* mob_setdropitem(int nameid, int qty, int m, int x, int y,
- struct map_session_data* first_sd, struct map_session_data* second_sd, struct map_session_data* third_sd)
+static struct item_drop* mob_setdropitem(int nameid, int qty)
{
- struct delay_item_drop *drop = ers_alloc(delay_drop_ers, struct delay_item_drop);
+ struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop);
memset(&drop->item_data, 0, sizeof(struct item));
drop->item_data.nameid = nameid;
drop->item_data.amount = qty;
drop->item_data.identify = !itemdb_isequip3(nameid);
- drop->m = m;
- drop->x = x;
- drop->y = y;
- drop->first_sd = first_sd;
- drop->second_sd = second_sd;
- drop->third_sd = third_sd;
+ drop->next = NULL;
return drop;
};
@@ -1411,17 +1411,11 @@ static struct delay_item_drop* mob_setdropitem(int nameid, int qty, int m, int x
* Initializes the delay drop structure for mob-looted items.
*------------------------------------------
*/
-static struct delay_item_drop* mob_setlootitem(struct item* item, int m, int x, int y,
- struct map_session_data* first_sd, struct map_session_data* second_sd, struct map_session_data* third_sd)
+static struct item_drop* mob_setlootitem(struct item* item)
{
- struct delay_item_drop *drop = ers_alloc(delay_drop_ers, struct delay_item_drop);
+ struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop);
memcpy(&drop->item_data, item, sizeof(struct item));
- drop->m = m;
- drop->x = x;
- drop->y = y;
- drop->first_sd = first_sd;
- drop->second_sd = second_sd;
- drop->third_sd = third_sd;
+ drop->next = NULL;
return drop;
};
@@ -1431,22 +1425,30 @@ static struct delay_item_drop* mob_setlootitem(struct item* item, int m, int x,
*/
static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data)
{
- struct delay_item_drop *ditem;
- ditem=(struct delay_item_drop *)id;
-
- map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
- ers_free(delay_drop_ers, ditem);
+ struct item_drop_list *list;
+ struct item_drop *ditem, *ditem_prev;
+ list=(struct item_drop_list *)id;
+ ditem = list->item;
+ while (ditem) {
+ map_addflooritem(&ditem->item_data,ditem->item_data.amount,
+ list->m,list->x,list->y,
+ list->first_sd,list->second_sd,list->third_sd,0);
+ ditem_prev = ditem;
+ ditem = ditem->next;
+ ers_free(item_drop_ers, ditem_prev);
+ }
+ ers_free(item_drop_list_ers, list);
return 0;
}
/*==========================================
- * Sets a timer to drop an item on the ground
+ * 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.
*------------------------------------------
* by [Skotlex]
*/
-static void mob_item_drop(struct mob_data *md, unsigned int tick, struct delay_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)
{
if(log_config.pick > 0)
{ //Logs items, dropped by mobs [Lupus]
@@ -1456,21 +1458,21 @@ static void mob_item_drop(struct mob_data *md, unsigned int tick, struct delay_i
log_pick((struct map_session_data*)md, "M", md->class_, ditem->item_data.nameid, -ditem->item_data.amount, NULL);
}
- if (ditem->first_sd && ditem->first_sd->state.autoloot &&
- (drop_rate <= ditem->first_sd->state.autoloot ||
- ditem->first_sd->state.autoloot >= 10000) //Fetch 100% drops
+ if (dlist->first_sd && dlist->first_sd->state.autoloot &&
+ (drop_rate <= dlist->first_sd->state.autoloot)
) { //Autoloot.
if (party_share_loot(
- ditem->first_sd->status.party_id?
- party_search(ditem->first_sd->status.party_id):
+ dlist->first_sd->status.party_id?
+ party_search(dlist->first_sd->status.party_id):
NULL,
- ditem->first_sd,&ditem->item_data) == 0
+ dlist->first_sd,&ditem->item_data) == 0
) {
- ers_free(delay_drop_ers, ditem);
+ ers_free(item_drop_ers, ditem);
return;
}
}
- add_timer(tick, mob_delay_item_drop, (int)ditem, 0);
+ ditem->next = dlist->item;
+ dlist->item = ditem;
}
int mob_timer_delete(int tid, unsigned int tick, int id, int data)
@@ -1557,7 +1559,6 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
struct item item;
int ret, mode;
int drop_rate;
- int base_drop_delay;
int race;
char buffer[64];
@@ -1720,11 +1721,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(src && src->type == BL_MOB)
mob_unlocktarget((struct mob_data *)src,tick);
- base_drop_delay = battle_config.delay_battle_damage?0:500;
if(sd) {
int sp = 0, hp = 0;
- if (sd->state.attack_type == BF_MAGIC)
- base_drop_delay = 500;
if (sd->state.attack_type == BF_MAGIC && sd->ud.skilltarget == md->bl.id && (i=pc_checkskill(sd,HW_SOULDRAIN))>0)
{ //Soul Drain should only work on targetted spells [Skotlex]
if (pc_issit(sd)) pc_setstand(sd); //Character stuck in attacking animation while 'sitting' fix. [Skotlex]
@@ -1914,21 +1912,27 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
// item drop
if (!(type&1)) {
+ struct item_drop_list *dlist = ers_alloc(item_drop_list_ers, struct item_drop_list);
+ struct item_drop *ditem;
int drop_ore = -1, drop_items = 0; //slot N for DROP LOG, number of dropped items
int log_item[10]; //8 -> 10 Lupus
memset(&log_item,0,sizeof(log_item));
+ dlist->m = md->bl.m;
+ dlist->x = md->bl.x;
+ dlist->y = md->bl.y;
+ dlist->first_sd = mvp_sd;
+ dlist->second_sd = second_sd;
+ dlist->third_sd = third_sd;
+ dlist->item = NULL;
+
+ if (map[md->bl.m].flag.nomobloot ||
+ (md->master_id && md->special_state.ai && (
+ battle_config.alchemist_summon_reward == 0 || //Noone gives items
+ (md->class_ != 1142 && battle_config.alchemist_summon_reward == 1) //Non Marine spheres don't drop items
+ )))
+ ; //No normal loot.
+ else
for (i = 0; i < 10; i++) { // 8 -> 10 Lupus
- struct delay_item_drop *ditem;
-
- if (md->master_id && md->special_state.ai && (
- battle_config.alchemist_summon_reward == 0 || //Noone gives items
- (md->class_ != 1142 && battle_config.alchemist_summon_reward == 1) //Non Marine spheres don't drop items
- ))
- break; // End
- //mapflag: noloot check [Lorky]
- if (map[md->bl.m].flag.nomobloot) break;;
- //end added [Lorky]
-
if (md->db->dropitem[i].nameid <= 0)
continue;
drop_rate = md->db->dropitem[i].p;
@@ -1954,41 +1958,39 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
}
drop_items++; //we count if there were any drops
- ditem = mob_setdropitem(md->db->dropitem[i].nameid, 1, md->bl.m, md->bl.x, md->bl.y, mvp_sd, second_sd, third_sd);
+ ditem = mob_setdropitem(md->db->dropitem[i].nameid, 1);
log_item[i] = ditem->item_data.nameid;
//A Rare Drop Global Announce by Lupus
if(drop_rate<=battle_config.rare_drop_announce) {
struct item_data *i_data;
char message[128];
- i_data = itemdb_exists(ditem->item_data.nameid);
+ i_data = itemdb_search(ditem->item_data.nameid);
sprintf (message, msg_txt(541), (mvp_sd?mvp_sd->status.name:"???"), md->db->jname, i_data->jname, (float)drop_rate/100);
//MSG: "'%s' won %s's %s (chance: %%%0.02f)"
intif_GMmessage(message,strlen(message)+1,0);
}
// Announce first, or else ditem will be freed. [Lance]
// By popular demand, use base drop rate for autoloot code. [Skotlex]
- mob_item_drop(md, tick+base_drop_delay+i, ditem, 0, md->db->dropitem[i].p);
+ mob_item_drop(md, dlist, ditem, 0, md->db->dropitem[i].p);
}
// Ore Discovery [Celest]
- if (sd == mvp_sd && map[md->bl.m].flag.nomobloot==0 && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/10 >= rand()%10000) {
- struct delay_item_drop *ditem;
- ditem = mob_setdropitem(itemdb_searchrandomid(6), 1, md->bl.m, md->bl.x, md->bl.y, mvp_sd, second_sd, third_sd);
+ if (sd == mvp_sd && !map[md->bl.m].flag.nomobloot && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/10 >= rand()%10000) {
+ ditem = mob_setdropitem(itemdb_searchrandomid(6), 1);
if (drop_ore<0) drop_ore=8; //we have only 10 slots in LOG, there's a check to not overflow (9th item usually a card, so we use 8th slot)
log_item[drop_ore] = ditem->item_data.nameid; //it's for logging only
drop_items++; //we count if there were any drops
- mob_item_drop(md, tick+base_drop_delay+drop_ore, ditem, 0, battle_config.finding_ore_rate/10);
+ mob_item_drop(md, dlist, ditem, 0, battle_config.finding_ore_rate/10);
}
//this drop log contains ALL dropped items + ORE (if there was ORE Recovery) [Lupus]
if(sd && log_config.drop > 0 && drop_items) //we check were there any drops.. and if not - don't write the log
log_drop(sd, md->class_, log_item); //mvp_sd
- if(sd/* && sd->state.attack_type == BF_WEAPON*/) { //Player reports indicate this SHOULD work with all skills. [Skotlex]
+ if(sd) {
int itemid = 0;
for (i = 0; i < sd->add_drop_count; i++) {
- struct delay_item_drop *ditem;
if (sd->add_drop[i].id < 0)
continue;
if (sd->add_drop[i].race & (1<<race) ||
@@ -2012,21 +2014,22 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id :
itemdb_searchrandomgroup(sd->add_drop[i].group);
- ditem = mob_setdropitem(itemid, 1, md->bl.m, md->bl.x, md->bl.y, mvp_sd, second_sd, third_sd);
- mob_item_drop(md, tick+base_drop_delay+20+i, ditem, 0, drop_rate);
+ mob_item_drop(md, dlist, mob_setdropitem(itemid,1), 0, drop_rate);
}
}
+
if(sd->get_zeny_num && rand()%100 < sd->get_zeny_rate) //Gets get_zeny_num per level +/-10% [Skotlex]
pc_getzeny(sd,md->db->lv*sd->get_zeny_num*(90+rand()%21)/100);
}
if(md->lootitem) {
- for(i=0;i<md->lootitem_count;i++) {
- struct delay_item_drop *ditem;
-
- ditem = mob_setlootitem(&md->lootitem[i], md->bl.m, md->bl.x, md->bl.y, mvp_sd, second_sd, third_sd);
- mob_item_drop(md, tick+base_drop_delay+40+i, ditem, 1, 10000);
- }
+ for(i=0;i<md->lootitem_count;i++)
+ mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000);
}
+ if (dlist->item) //There are drop items.
+ add_timer(tick + ((!battle_config.delay_battle_damage || (sd && sd->state.attack_type == BF_MAGIC))?500:0),
+ mob_delay_item_drop, (int)dlist, 0);
+ else //No drops
+ ers_free(item_drop_list_ers, dlist);
}
// mvpˆ—
@@ -3933,7 +3936,8 @@ int do_init_mob(void)
memset(mob_db_data,0,sizeof(mob_db_data)); //Clear the array
mob_db_data[0] = aCalloc(1, sizeof (struct mob_data)); //This mob is used for random spawns
mob_makedummymobdb(0); //The first time this is invoked, it creates the dummy mob
- delay_drop_ers = ers_new((uint32)sizeof(struct delay_item_drop));
+ item_drop_ers = ers_new((uint32)sizeof(struct item_drop));
+ item_drop_list_ers = ers_new((uint32)sizeof(struct item_drop_list));
#ifndef TXT_ONLY
if(db_use_sqldbs)
@@ -3980,6 +3984,7 @@ int do_final_mob(void)
mob_db_data[i] = NULL;
}
}
- ers_destroy(delay_drop_ers);
+ ers_destroy(item_drop_ers);
+ ers_destroy(item_drop_list_ers);
return 0;
}