From 1b28f3cc0bc670b82e71d12ad67e263f4e04d1f3 Mon Sep 17 00:00:00 2001 From: skotlex Date: Wed, 12 Apr 2006 16:32:34 +0000 Subject: - 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 --- src/map/battle.c | 11 +++-- src/map/mob.c | 145 ++++++++++++++++++++++++++++--------------------------- 2 files changed, 81 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/map/battle.c b/src/map/battle.c index cb12328c6..6986826f0 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1136,7 +1136,7 @@ static struct Damage battle_calc_weapon_attack( break; case CR_SHIELDCHARGE: - flag.weapon = 0; +// flag.weapon = 0; case NPC_PIERCINGATT: wd.flag=(wd.flag&~BF_RANGEMASK)|BF_SHORT; break; @@ -1924,11 +1924,12 @@ static struct Damage battle_calc_weapon_attack( vit_def = def2 + (vit_def>0?rand()%vit_def:0); } - if ((sd && battle_config.player_defense_type) - || (md && battle_config.monster_defense_type) - || (pd && battle_config.pet_defense_type) - ) + if (sd && battle_config.player_defense_type) vit_def += def1*battle_config.player_defense_type; + else if (md && battle_config.monster_defense_type) + vit_def += def1*battle_config.monster_defense_type; + else if(pd && battle_config.pet_defense_type) + vit_def += def1*battle_config.pet_defense_type; else ATK_RATE2(flag.idef?100:100-def1, flag.idef2?100:100-def1); ATK_ADD2(flag.idef?0:-vit_def, flag.idef2?0:-vit_def); 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<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;ilootitem_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;ilootitem_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; } -- cgit v1.2.3-70-g09d2