diff options
-rw-r--r-- | Changelog-Trunk.txt | 3 | ||||
-rw-r--r-- | src/map/map.h | 1 | ||||
-rw-r--r-- | src/map/mob.c | 86 |
3 files changed, 40 insertions, 50 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 55acb5e47..6900159fe 100644 --- a/Changelog-Trunk.txt +++ b/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/10/11
+ * Corrected the mob damagelog structure so that you can't exploit it by
+ switching characters. [Skotlex]
2006/10/09
* Fixed crash when char-server sends to a "random" map-server online on
connect. Thanks to TheUltraMage for pointing it out. [Skotlex]
diff --git a/src/map/map.h b/src/map/map.h index 2d0875cce..e05647bc4 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -953,6 +953,7 @@ struct mob_data { struct {
int id;
int dmg;
+ unsigned flag : 1; //0: Normal. 1: Homunc exp
} dmglog[DAMAGELOG_SIZE];
struct spawn_data *spawn; //Spawn data.
struct item *lootitem;
diff --git a/src/map/mob.c b/src/map/mob.c index cc6a59cb1..f27370587 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1592,7 +1592,7 @@ int mob_respawn(int tid, unsigned int tick, int id,int data ) //Call when a mob has received damage. void mob_damage(struct mob_data *md, struct block_list *src, int damage) { - int id = 0; + int char_id = 0, flag = 0; md->tdmg+=damage; //Store total damage... @@ -1616,8 +1616,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) case BL_PC: { struct map_session_data *sd = (TBL_PC*)src; -// id = sd->status.char_id; - id = sd->bl.id; //[orn] + char_id = sd->status.char_id; if(rand()%1000 < 1000/md->attacked_players) md->attacked_id = src->id; break; @@ -1625,7 +1624,9 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) case BL_HOM: //[orn] { struct homun_data *hd = (TBL_HOM*)src; - id = hd->bl.id; + flag = 1; + if (hd->master) + char_id = hd->master->status.char_id; if(rand()%1000 < 1000/md->attacked_players) md->attacked_id = src->id; break; @@ -1633,13 +1634,12 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) case BL_PET: { struct pet_data *pd = (TBL_PET*)src; - if (battle_config.pet_attack_exp_to_master) { -// id = pd->msd->status.char_id; - id = pd->msd->bl.id; //[orn] + if (battle_config.pet_attack_exp_to_master && pd->msd) { + char_id = pd->msd->status.char_id; damage=(damage*battle_config.pet_attack_exp_rate)/100; //Modify logged damage accordingly. } //Let mobs retaliate against the pet's master [Skotlex] - if(rand()%1000 < 1000/md->attacked_players) + if(pd->msd && rand()%1000 < 1000/md->attacked_players) md->attacked_id = pd->msd->bl.id; break; } @@ -1648,8 +1648,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) struct mob_data* md2 = (TBL_MOB*)src; if(md2->special_state.ai && md2->master_id) { struct map_session_data* msd = map_id2sd(md2->master_id); -// if (msd) id = msd->status.char_id; - if (msd) id = msd->bl.id; //[orn] + if (msd) char_id = msd->status.char_id; } if(rand()%1000 < 1000/md->attacked_players) { //Let players decide whether to retaliate versus the master or the mob. [Skotlex] @@ -1665,13 +1664,15 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) md->attacked_id = src->id; } //Log damage... - if (id && damage > 0) { + if (char_id && damage > 0) { int i,minpos,mindmg; for(i=0,minpos=DAMAGELOG_SIZE-1,mindmg=INT_MAX;i<DAMAGELOG_SIZE;i++){ - if(md->dmglog[i].id==id) + if(md->dmglog[i].id==char_id && + md->dmglog[i].flag==flag) break; if(md->dmglog[i].id==0) { //Store data in first empty slot. - md->dmglog[i].id = id; + md->dmglog[i].id = char_id; + md->dmglog[i].flag= flag; break; } if(md->dmglog[i].dmg<mindmg){ @@ -1682,8 +1683,9 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) if(i<DAMAGELOG_SIZE) md->dmglog[i].dmg+=damage; else { - md->dmglog[minpos].id=id; - md->dmglog[minpos].dmg=damage; + md->dmglog[minpos].id = char_id; + md->dmglog[minpos].flag= flag; + md->dmglog[minpos].dmg = damage; } } @@ -1701,9 +1703,8 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) int mob_dead(struct mob_data *md, struct block_list *src, int type) { struct status_data *status; - struct map_session_data *sd = NULL,/**tmpsd[DAMAGELOG_SIZE],*/ + struct map_session_data *sd = NULL,*tmpsd[DAMAGELOG_SIZE], *mvp_sd = NULL, *second_sd = NULL,*third_sd = NULL; - struct block_list *tmpbl[DAMAGELOG_SIZE] ; //[orn] struct { struct party_data *p; @@ -1738,7 +1739,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) map_freeblock_lock(); - malloc_tsetdword(tmpbl,0,sizeof(tmpbl)); + malloc_tsetdword(tmpsd,0,sizeof(tmpsd)); malloc_set(pt,0,sizeof(pt)); if(src && src->type == BL_MOB) @@ -1767,21 +1768,18 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) for(i=0,mvp_damage=0;i<DAMAGELOG_SIZE && md->dmglog[i].id;i++) { - tmpbl[i] = map_id2bl(md->dmglog[i].id); - if(tmpbl[i] == NULL) + tmpsd[i] = map_charid2sd(md->dmglog[i].id); + if(tmpsd[i] == NULL) continue; - if( (tmpbl[i])->m != md->bl.m || status_isdead(tmpbl[i])) + if(tmpsd[i]->bl.m != md->bl.m || pc_isdead(tmpsd[i])) { - tmpbl[i] = NULL; + tmpsd[i] = NULL; continue; } if(mvp_damage<(unsigned int)md->dmglog[i].dmg){ third_sd = second_sd; second_sd = mvp_sd; - if ( (tmpbl[i])->type == BL_HOM ) - mvp_sd=((struct homun_data *)tmpbl[i])->master ; - else - mvp_sd=(struct map_session_data *)tmpbl[i]; + mvp_sd=tmpsd[i]; mvp_damage=md->dmglog[i].dmg; } } @@ -1800,7 +1798,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) double jper; //For the job-exp int bonus; //Bonus on top of your share. - if (!tmpbl[i]) continue; + if (!tmpsd[i]) continue; if (!battle_config.exp_calc_type && md->tdmg) //jAthena's exp formula based on total damage. @@ -1852,8 +1850,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) if (base_exp < 1) base_exp = 1; } - - if (map[md->bl.m].flag.nojobexp) + //Homun earned job-exp is always lost. + if (map[md->bl.m].flag.nojobexp || md->dmglog[i].flag) job_exp=0; else { if (map[md->bl.m].jexp != 100) @@ -1872,8 +1870,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) job_exp = 1; } - if( (tmpbl[i]->type == BL_PC) && (temp = ((struct map_session_data *)tmpbl[i])->status.party_id )>0 ) //only pc have party [orn] - { + if((temp = tmpsd[i]->status.party_id )>0 && !md->dmglog[i].flag) + { //Homun-done damage (flag 1) is not given to party int j; for(j=0;j<pnum && pt[j].id!=temp;j++); //Locate party. @@ -1903,25 +1901,13 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) flag=0; } } - if(flag) { //homunculus aren't considered in party [orn] - switch( (tmpbl[i])->type ) { - case BL_PC: - if(base_exp || job_exp) - pc_gainexp((struct map_session_data *)tmpbl[i], &md->bl, base_exp,job_exp); - if(zeny) // zeny from mobs [Valaris] - pc_getzeny((struct map_session_data *)tmpbl[i], zeny); - break ; - case BL_HOM: - if(base_exp) { - merc_hom_gainexp((struct homun_data *)tmpbl[i], base_exp); - //homunculus give base_exp to master - pc_gainexp(((struct homun_data *)tmpbl[i])->master, &md->bl, base_exp,0); - } - if(zeny) //homunculus give zeny to master - pc_getzeny((struct map_session_data *)((struct homun_data *)tmpbl[i])->master, zeny); - break ; - - } + if(flag) { + if(base_exp && md->dmglog[i].flag && tmpsd[i]->hd) + merc_hom_gainexp(tmpsd[i]->hd, base_exp); + if(base_exp || job_exp) + pc_gainexp(tmpsd[i], &md->bl, base_exp,job_exp); + if(zeny) // zeny from mobs [Valaris] + pc_getzeny(tmpsd[i], zeny); } } |