Przeglądaj źródła

- 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://svn.code.sf.net/p/rathena/svn/trunk@6014 54d463be-8e91-2dee-dedb-b68131a5f0ec
skotlex 19 lat temu
rodzic
commit
d29c6d8a27
3 zmienionych plików z 84 dodań i 75 usunięć
  1. 3 0
      Changelog-Trunk.txt
  2. 6 5
      src/map/battle.c
  3. 75 70
      src/map/mob.c

+ 3 - 0
Changelog-Trunk.txt

@@ -3,6 +3,9 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
+2006/04/12
+	* Simplified the mob-drops structure by using a single timer with a linked
+	  list of drops instead of separate timers for each drop. [Skotlex]
 2006/04/11
 	* Added special_state changebase to identify when a character has a
 	  special-view associated with some equipment to correctly revert the look

+ 6 - 5
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);

+ 75 - 70
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;
 }