diff options
author | glighta <glighta@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-11-01 01:40:29 +0000 |
---|---|---|
committer | glighta <glighta@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-11-01 01:40:29 +0000 |
commit | 85ae075fd230f7e1d08a84dde6a2cfdce8280ecd (patch) | |
tree | 566de83b27be9f1c2449ddef90a8f7a041ab2ca8 /src/map/mob.c | |
parent | a0fb6bc388fb1d4f0fcfd7d3d8af71a9c8cf86ca (diff) | |
download | hercules-85ae075fd230f7e1d08a84dde6a2cfdce8280ecd.tar.gz hercules-85ae075fd230f7e1d08a84dde6a2cfdce8280ecd.tar.bz2 hercules-85ae075fd230f7e1d08a84dde6a2cfdce8280ecd.tar.xz hercules-85ae075fd230f7e1d08a84dde6a2cfdce8280ecd.zip |
-Fix bugreport:6547 (bloodylust) upd bloodylust effect to berserk
-Fix bugreport:6208, bugreport:6805 (chaos panic) fix range effect
-Partial Fix bugreport:5275 (toxin now won't interupt unbreackable castskill)
-Folllow up r16847 fix UNT_ZEPHYR get some unwanted bonus, fix Insignia unit range
-Add UF_RANGEDSINGLEUNIT unit propriety thx to 3ceam, workaround to fix ranged unit without timer.
-Prevent WM_SOUND_OF_DESTRUCTION, SC_MANHOLE, WM_LULLABY_DEEPSLEEP being cast in non pvp map
-Fix SC_MAGICMUSHROOM shouldn't force skill if sit
-Replace some hardcoded mobid by enum
-add some mob_is definition for quicker search (gvg and treasure)
-Remove some duplicate check for status_heal (if berserk already done in status heal)
-Upd few documentation
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16855 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map/mob.c')
-rw-r--r-- | src/map/mob.c | 322 |
1 files changed, 161 insertions, 161 deletions
diff --git a/src/map/mob.c b/src/map/mob.c index e423f7548..50a9397da 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -135,13 +135,13 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time) CREATE(nd, struct npc_data, 1); nd->bl.id = md->tomb_nid = npc_get_new_npc_id(); - + nd->ud.dir = md->ud.dir; nd->bl.m = md->bl.m; nd->bl.x = md->bl.x; nd->bl.y = md->bl.y; nd->bl.type = BL_NPC; - + safestrncpy(nd->name, msg_txt(656), sizeof(nd->name)); nd->class_ = 565; @@ -150,7 +150,7 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time) nd->u.tomb.md = md; nd->u.tomb.kill_time = time; - + if (killer) safestrncpy(nd->u.tomb.killer_name, killer, NAME_LENGTH); else @@ -172,9 +172,9 @@ void mvptomb_destroy(struct mob_data *md) { int m, i; m = nd->bl.m; - + clif_clearunit_area(&nd->bl,CLR_OUTSIGHT); - + map_delblock(&nd->bl); ARR_FIND( 0, map[m].npc_num, i, map[m].npc[i] == nd ); @@ -227,7 +227,7 @@ int mobdb_checkid(const int id) /*========================================== * Returns the view data associated to this mob class. *------------------------------------------*/ -struct view_data * mob_get_viewdata(int class_) +struct view_data * mob_get_viewdata(int class_) { if (mob_db(class_) == mob_dummy) return 0; @@ -248,7 +248,7 @@ int mob_parse_dataset(struct spawn_data *data) data->state.size=SZ_MEDIUM; data->class_ -= MAX_MOB_DB; } - + if ((!mobdb_checkid(data->class_) && !mob_is_clone(data->class_)) || !data->num) return 0; @@ -311,7 +311,7 @@ struct mob_data* mob_spawn_dataset(struct spawn_data *data) status_set_viewdata(&md->bl, md->class_); status_change_init(&md->bl); unit_dataset(&md->bl); - + map_addiddb(&md->bl); return md; } @@ -445,7 +445,7 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target) struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m, short x, short y, const char *mobname, int class_, const char *event) { struct spawn_data data; - + memset(&data, 0, sizeof(struct spawn_data)); data.m = m; data.num = 1; @@ -460,7 +460,7 @@ struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m, short x, short if (event) safestrncpy(data.eventname, event, sizeof(data.eventname)); - + // Locate spot next to player. if (bl && (x < 0 || y < 0)) map_search_freecell(bl, m, &x, &y, 1, 1, 0); @@ -468,7 +468,7 @@ struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m, short x, short // if none found, pick random position on map if (x <= 0 || y <= 0 || map_getcell(m,x,y,CELL_CHKNOREACH)) map_search_freecell(NULL, m, &x, &y, -1, -1, 1); - + data.x = x; data.y = y; @@ -485,7 +485,7 @@ int mob_once_spawn(struct map_session_data* sd, int m, short x, short y, const c { struct mob_data* md = NULL; int count, lv; - + if (m < 0 || amount <= 0) return 0; // invalid input @@ -567,7 +567,7 @@ int mob_once_spawn_area(struct map_session_data* sd,int m,int x0,int y0,int x1,i {// attempt to find an available cell failed if( lx == -1 && ly == -1 ) return 0; // total failure - + // fallback to last good x/y pair x = lx; y = ly; @@ -588,19 +588,19 @@ int mob_once_spawn_area(struct map_session_data* sd,int m,int x0,int y0,int x1,i static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t data) { //Needed because the guild_data may not be available at guardian spawn time. struct block_list* bl = map_id2bl(id); - struct mob_data* md; + struct mob_data* md; struct guild* g; int guardup_lv; if (bl == NULL) //It is possible mob was already removed from map when the castle has no owner. [Skotlex] return 0; - + if (bl->type != BL_MOB) { ShowError("mob_spawn_guardian_sub: Block error!\n"); return 0; } - + md = (struct mob_data*)bl; nullpo_ret(md->guardian_data); g = guild_search((int)data); @@ -670,7 +670,7 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, class_, map[m].name); return 0; } - + if((x<=0 || y<=0) && !map_search_freecell(NULL, m, &x, &y, -1,-1, 1)) { ShowWarning("mob_spawn_guardian: Couldn't locate a spawn cell for guardian class %d (index %d) at castle map %s\n",class_, guardian, map[m].name); @@ -682,7 +682,7 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam safestrncpy(data.eventname, event, sizeof(data.eventname)); if (!mob_parse_dataset(&data)) return 0; - + gc=guild_mapname2gc(map[m].name); if (gc == NULL) { @@ -817,7 +817,7 @@ int mob_linksearch(struct block_list *bl,va_list ap) int class_; struct block_list *target; unsigned int tick; - + nullpo_ret(bl); md=(struct mob_data *)bl; class_ = va_arg(ap, int); @@ -978,10 +978,10 @@ int mob_spawn (struct mob_data *md) memset(md->dmglog, 0, sizeof(md->dmglog)); md->tdmg = 0; - + if (md->lootitem) memset(md->lootitem, 0, sizeof(*md->lootitem)); - + md->lootitem_count = 0; if(md->db->option) @@ -1013,7 +1013,7 @@ static int mob_can_changetarget(struct mob_data* md, struct block_list* target, else if (!(battle_config.mob_ai&0x4)) return 0; } - + switch (md->state.skillstate) { case MSS_BERSERK: if (!(mode&MD_CHANGETARGET_MELEE)) @@ -1105,7 +1105,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) return 0; } - + (*target) = bl; md->target_id=bl->id; md->min_chase= dist + md->db->range3; @@ -1151,11 +1151,11 @@ static int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap) static int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) { struct mob_data *md; struct block_list **target; - + nullpo_ret(bl); md=va_arg(ap,struct mob_data *); target= va_arg(ap,struct block_list**); - + if( status_check_skilluse(&md->bl, bl, 0, 0) && battle_check_target(&md->bl,bl,BCT_ENEMY)<=0 ) { (*target) = bl; } @@ -1175,7 +1175,7 @@ static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap) target= va_arg(ap,struct block_list**); dist=distance_bl(&md->bl, bl); - if(mob_can_reach(md,bl,dist+1, MSS_LOOT) && + if(mob_can_reach(md,bl,dist+1, MSS_LOOT) && ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) //New target closer than previous one. ) { (*target) = bl; @@ -1238,7 +1238,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) md->master_dist=distance_bl(&md->bl, bl); // Since the master was in near immediately before, teleport is carried out and it pursues. - if(bl->m != md->bl.m || + if(bl->m != md->bl.m || (old_dist<10 && md->master_dist>18) || md->master_dist > MAX_MINCHASE ){ @@ -1265,13 +1265,13 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) status_kill(&md->bl); return 1; } - + //Avoid attempting to lock the master's target too often to avoid unnecessary overload. [Skotlex] if (DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME && !md->target_id) { struct unit_data *ud = unit_bl2ud(bl); md->last_linktime = tick; - + if (ud) { struct block_list *tbl=NULL; if (ud->target && ud->state.attack_continue) @@ -1351,7 +1351,7 @@ int mob_randomwalk(struct mob_data *md,unsigned int tick) !unit_can_move(&md->bl) || !(status_get_mode(&md->bl)&MD_CANMOVE)) return 0; - + d =12-md->move_fail_count; if(d<5) d=5; for(i=0;i<retrycount;i++){ // Search of a movable place @@ -1423,7 +1423,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) if(md->bl.prev == NULL || md->status.hp <= 0) return false; - + if (DIFF_TICK(tick, md->last_thinktime) < MIN_MOBTHINKTIME) return false; @@ -1467,7 +1467,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) tbl = NULL; } } - + // Check for target change. if( md->attacked_id && mode&MD_CANATTACK ) { @@ -1538,7 +1538,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) //Clear it since it's been checked for already. md->attacked_id = 0; } - + // Processing of slave monster if (md->master_id > 0 && mob_ai_sub_hard_slavemob(md, tick)) return true; @@ -1564,7 +1564,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) if (!tbl) { //No targets available. if (mode&MD_ANGRY && !md->state.aggressive) md->state.aggressive = 1; //Restore angry state when no targets are available. - + /* bg guardians follow allies when no targets nearby */ if( md->bg_id && mode&MD_CANATTACK ) { if( md->ud.walktimer != INVALID_TIMER ) @@ -1575,12 +1575,12 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) return true;/* we're moving or close enough don't unlock the target. */ } } - + //This handles triggering idle walk/skill. mob_unlocktarget(md, tick); return true; } - + //Target exists, attack or loot as applicable. if (tbl->type == BL_ITEM) { //Loot time. @@ -1637,7 +1637,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) //At this point we know the target is attackable, we just gotta check if the range matches. if (md->ud.target == tbl->id && md->ud.attacktimer != INVALID_TIMER) //Already locked. return true; - + if (battle_check_range (&md->bl, tbl, md->status.rhw.range)) { //Target within range, engage @@ -1683,7 +1683,7 @@ static int mob_ai_sub_hard_timer(struct block_list *bl,va_list ap) { struct mob_data *md = (struct mob_data*)bl; unsigned int tick = va_arg(ap, unsigned int); - if (mob_ai_sub_hard(md, tick)) + if (mob_ai_sub_hard(md, tick)) { //Hard AI triggered. if(!md->state.spotted) md->state.spotted = 1; @@ -1948,7 +1948,7 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage) switch( src->type ) { - case BL_PC: + case BL_PC: { struct map_session_data *sd = (TBL_PC*)src; char_id = sd->status.char_id; @@ -2013,11 +2013,11 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage) if( damage ) md->attacked_id = src->id; break; - } + } default: //For all unhandled types. md->attacked_id = src->id; } - + if( char_id ) { //Log damage... int i,minpos; @@ -2074,10 +2074,10 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) if (battle_config.show_mob_info&3) clif_charnameack (0, &md->bl); - + if (!src) return; - + #if PACKETVER >= 20120404 if( !(md->status.mode&MD_BOSS) ){ int i; @@ -2088,7 +2088,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) } } #endif - + if( md->special_state.ai == 2 ) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex] md->state.alchemist = 1; mobskill_use(md, gettick(), MSC_ALCHEMIST); @@ -2104,7 +2104,7 @@ 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 *mvp_sd = NULL, *second_sd = NULL, *third_sd = NULL; - + struct { struct party_data *p; int id,zeny; @@ -2138,7 +2138,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) if(src && src->type == BL_MOB) mob_unlocktarget((struct mob_data *)src,tick); - + // filter out entries not eligible for exp distribution memset(tmpsd,0,sizeof(tmpsd)); for(i = 0, count = 0, mvp_damage = 0; i < DAMAGELOG_SIZE && md->dmglog[i].id; i++) @@ -2226,7 +2226,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) per = (double)md->dmglog[i].dmg/(double)status->max_hp; if (per > 2) per = 2; // prevents unlimited exp gain } - + if (count>1 && battle_config.exp_bonus_attacker) { //Exp bonus per additional attacker. if (count > battle_config.exp_bonus_max_attacker) @@ -2251,15 +2251,15 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) } if (map[m].flag.nobaseexp || !md->db->base_exp) - base_exp = 0; + base_exp = 0; else base_exp = (unsigned int)cap_value(md->db->base_exp * per * bonus/100. * map[m].bexp/100., 1, UINT_MAX); - + if (map[m].flag.nojobexp || !md->db->job_exp || md->dmglog[i].flag == MDLF_HOMUN) //Homun earned job-exp is always lost. - job_exp = 0; + job_exp = 0; else job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map[m].jexp/100., 1, UINT_MAX); - + if((temp = tmpsd[i]->status.party_id )>0 && !md->dmglog[i].flag == MDLF_HOMUN) //Homun-done damage (flag 1) is not given to party { int j; @@ -2281,12 +2281,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) pt[j].base_exp=UINT_MAX; else pt[j].base_exp+=base_exp; - + if (pt[j].job_exp > UINT_MAX - job_exp) pt[j].job_exp=UINT_MAX; else pt[j].job_exp+=job_exp; - + pt[j].zeny+=zeny; // zeny share [Valaris] flag=0; } @@ -2309,12 +2309,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) pc_getzeny(tmpsd[i], zeny); } } - + for(i=0;i<pnum;i++) //Party share. party_exp_share(pt[i].p, &md->bl, pt[i].base_exp,pt[i].job_exp,pt[i].zeny); } //End EXP giving. - + if( !(type&1) && !map[m].flag.nomobloot && !md->state.rebirth && ( !md->special_state.ai || //Non special mob battle_config.alchemist_summon_reward == 2 || //All summoned give drops @@ -2361,7 +2361,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) //Drops affected by luk as a fixed increase [Valaris] if (battle_config.drops_by_luk) drop_rate += status_get_luk(src)*battle_config.drops_by_luk/100; - //Drops affected by luk as a % increase [Skotlex] + //Drops affected by luk as a % increase [Skotlex] if (battle_config.drops_by_luk2) drop_rate += (int)(0.5+drop_rate*status_get_luk(src)*battle_config.drops_by_luk2/10000.); } @@ -2430,14 +2430,14 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) else //it's positive, then it goes as it is drop_rate = sd->add_drop[i].rate; - + if (rnd()%10000 >= drop_rate) continue; itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb_searchrandomid(sd->add_drop[i].group); mob_item_drop(md, dlist, mob_setdropitem(itemid,1), 0, drop_rate, homkillonly); } } - + // process script-granted zeny bonus (get_zeny_num) [Skotlex] if( sd->bonus.get_zeny_num && rnd()%100 < sd->bonus.get_zeny_rate ) { i = sd->bonus.get_zeny_num > 0 ? sd->bonus.get_zeny_num : -md->level * sd->bonus.get_zeny_num; @@ -2445,7 +2445,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) pc_getzeny(sd, 1+rnd()%i); } } - + // process items looted by the mob if(md->lootitem) { for(i = 0; i < md->lootitem_count; i++) @@ -2474,30 +2474,30 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) unsigned int mexp; struct item item; double exp; - + //mapflag: noexp check [Lorky] if (map[m].flag.nobaseexp || type&2) - exp =1; + exp =1; else { exp = md->db->mexp; if (count > 1) exp += exp*(battle_config.exp_bonus_attacker*(count-1))/100.; //[Gengar] } - + mexp = (unsigned int)cap_value(exp, 1, UINT_MAX); clif_mvp_effect(mvp_sd); clif_mvp_exp(mvp_sd,mexp); pc_gainexp(mvp_sd, &md->bl, mexp,0, false); log_mvp[1] = mexp; - + if( !(map[m].flag.nomvploot || type&1) ) { /* pose them randomly in the list -- so on 100% drop servers it wont always drop the same item */ int mdrop_id[MAX_MVP_DROP]; int mdrop_p[MAX_MVP_DROP]; - + memset(&mdrop_id,0,MAX_MVP_DROP*sizeof(int)); - + for(i = 0; i < MAX_MVP_DROP; i++) { while( 1 ) { int va = rand()%MAX_MVP_DROP; @@ -2508,13 +2508,13 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) } } } - + for(i = 0; i < MAX_MVP_DROP; i++) { if(mdrop_id[i] <= 0) continue; if(!itemdb_exists(mdrop_id[i])) continue; - + temp = mdrop_p[i]; if(temp <= 0 && !battle_config.drop_rate0item) temp = 1; @@ -2526,7 +2526,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) item.identify= itemdb_isidentified(item.nameid); clif_mvp_item(mvp_sd,item.nameid); log_mvp[0] = item.nameid; - + //A Rare MVP Drop Global Announce by Lupus if(temp<=battle_config.rare_drop_announce) { struct item_data *i_data; @@ -2541,7 +2541,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) clif_additem(mvp_sd,0,0,temp); map_addflooritem(&item,1,mvp_sd->bl.m,mvp_sd->bl.x,mvp_sd->bl.y,mvp_sd->status.char_id,(second_sd?second_sd->status.char_id:0),(third_sd?third_sd->status.char_id:0),1); } - + //Logs items, MVP prizes [Lupus] log_pick_mob(md, LOG_TYPE_MVP, -1, &item); break; @@ -2578,12 +2578,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) } pc_setglobalreg(sd,"TK_MISSION_COUNT", sd->mission_count); } - + if( sd->status.party_id ) map_foreachinrange(quest_update_objective_sub,&md->bl,AREA_SIZE,BL_PC,sd->status.party_id,md->class_); else if( sd->avail_quests ) quest_update_objective(sd, md->class_); - + if( sd->md && src && src->type != BL_HOM && mob_db(md->class_)->lv > sd->status.base_level/2 ) mercenary_kills(sd->md); } @@ -2601,7 +2601,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) pc_setparam(mvp_sd, SP_KILLEDRID, md->class_); npc_script_event(mvp_sd, NPCE_KILLNPC); // PCKillNPC [Lance] } - + md->status.hp = 1; } @@ -2614,11 +2614,11 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) **/ if( md->can_summon ) mob_deleteslave(md); - + map_freeblock_unlock(); if( !rebirth ) { - + if( pcdb_checkid(md->vd->class_) ) {//Player mobs are not removed automatically by the client. /* first we set them dead, then we delay the outsight effect */ clif_clearunit_area(&md->bl,CLR_DEAD); @@ -2652,7 +2652,7 @@ void mob_revive(struct mob_data *md, unsigned int hp) md->next_walktime = tick+rnd()%50+5000; md->last_linktime = tick; md->last_pcneartime = 0; - memset(md->dmglog, 0, sizeof(md->dmglog)); // Reset the damage done on the rebirthed monster, otherwise will grant full exp + damage done. [Valaris] + memset(md->dmglog, 0, sizeof(md->dmglog)); // Reset the damage done on the rebirthed monster, otherwise will grant full exp + damage done. [Valaris] md->tdmg = 0; if (!md->bl.prev) map_addblock(&md->bl); @@ -2685,7 +2685,7 @@ int mob_guardian_guildchange(struct mob_data *md) } return 0; } - + g = guild_search(md->guardian_data->castle->guild_id); if (g == NULL) { //Properly remove guardian info from Castle data. @@ -2703,7 +2703,7 @@ int mob_guardian_guildchange(struct mob_data *md) return 1; } - + /*========================================== * Pick a random class for the mob *------------------------------------------*/ @@ -2743,7 +2743,7 @@ int mob_class_change (struct mob_data *md, int class_) if (md->guardian_data) return 0; //Guardians/Emperium - if( (md->class_ >= 1324 && md->class_ <= 1363) || (md->class_ >= 1938 && md->class_ <= 1946) ) + if( mob_is_treasure(md) ) return 0; //Treasure Boxes if( md->special_state.ai > 1 ) @@ -2795,7 +2795,7 @@ int mob_class_change (struct mob_data *md, int class_) } /*========================================== - * mob‰ñ•œ + * mob heal, update display hp info of mob for players *------------------------------------------*/ void mob_heal(struct mob_data *md,unsigned int heal) { @@ -2813,7 +2813,7 @@ int mob_warpslave_sub(struct block_list *bl,va_list ap) short x,y,range=0; master = va_arg(ap, struct block_list*); range = va_arg(ap, int); - + if(md->master_id!=master->id) return 0; @@ -2831,7 +2831,7 @@ int mob_warpslave(struct block_list *bl, int range) { if (range < 1) range = 1; //Min range needed to avoid crashes and stuff. [Skotlex] - + return map_foreachinmap(mob_warpslave_sub, bl->m, BL_MOB, bl, range); } @@ -2843,7 +2843,7 @@ int mob_countslave_sub(struct block_list *bl,va_list ap) int id; struct mob_data *md; id=va_arg(ap,int); - + md = (struct mob_data *)bl; if( md->master_id==id ) return 1; @@ -2891,7 +2891,7 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int skill_id) k = rnd()%count; amount+=k; //Increase final value by same amount to preserve total number to summon. } - + if (!battle_config.monster_class_change_recover && (skill_id == NPC_TRANSFORMATION || skill_id == NPC_METAMORPHOSIS)) hp_rate = get_percentage(md2->status.hp, md2->status.max_hp); @@ -2918,14 +2918,14 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int skill_id) if (!mob_parse_dataset(&data)) continue; - + md= mob_spawn_dataset(&data); if(skill_id == NPC_SUMMONSLAVE){ md->master_id=md2->bl.id; md->special_state.ai = md2->special_state.ai; } mob_spawn(md); - + if (hp_rate) //Scale HP md->status.hp = md->status.max_hp*hp_rate/100; @@ -2991,12 +2991,12 @@ int mob_getfriendhprate_sub(struct block_list *bl,va_list ap) if ((*fr) != NULL) //A friend was already found. return 0; - + if (battle_check_target(&md->bl,bl,BCT_ENEMY)>0) return 0; - + rate = get_percentage(status_get_hp(bl), status_get_max_hp(bl)); - + if (rate >= min_rate && rate <= max_rate) (*fr) = bl; return 1; @@ -3005,12 +3005,12 @@ static struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,i { struct block_list *fr=NULL; int type = BL_MOB; - + nullpo_retr(NULL, md); if (md->special_state.ai) //Summoned creatures. [Skotlex] type = BL_PC; - + map_foreachinrange(mob_getfriendhprate_sub, &md->bl, 8, type,md,min_rate,max_rate,&fr); return fr; } @@ -3104,7 +3104,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) continue; c2 = ms[i].cond2; - + if (ms[i].state != md->state.skillstate) { if (md->state.skillstate != MSS_DEAD && (ms[i].state == MSS_ANY || (ms[i].state == MSS_ANYTARGET && md->target_id && md->state.skillstate != MSS_LOOT) @@ -3115,7 +3115,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) } if (rnd() % 10000 > ms[i].permillage) //Lupus (max value = 10000) continue; - + if (ms[i].cond1 == event) flag = 1; //Trigger skill. else if (ms[i].cond1 == MSC_SKILLUSED) @@ -3176,10 +3176,10 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) break; } } - + if (!flag) continue; //Skill requisite failed to be fulfilled. - + //Execute skill if (skill_get_casttype(ms[i].skill_id) == CAST_GROUND) { //Ground skill. @@ -3198,7 +3198,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) break; case MST_MASTER: bl = &md->bl; - if (md->master_id) + if (md->master_id) bl = map_id2bl(md->master_id); if (bl) //Otherwise, fall through. break; @@ -3210,7 +3210,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) break; } if (!bl) continue; - + x = bl->x; y = bl->y; // Look for an area to cast the spell around... @@ -3240,7 +3240,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) break; case MST_MASTER: bl = &md->bl; - if (md->master_id) + if (md->master_id) bl = map_id2bl(md->master_id); if (bl) //Otherwise, fall through. break; @@ -3257,7 +3257,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) break; } if (!bl) continue; - + md->skillidx = i; map_freeblock_lock(); if( !battle_check_range(&md->bl,bl,skill_get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) || @@ -3267,7 +3267,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) continue; } } - //Skill used. Post-setups... + //Skill used. Post-setups... if ( ms[ i ].msg_id ){ //Display color message [SnakeDrak] struct mob_chat *mc = mob_chat(ms[i].msg_id); char temp[CHAT_SIZE_MAX]; @@ -3303,7 +3303,7 @@ int mobskill_event(struct mob_data *md, struct block_list *src, unsigned int tic target_id = md->target_id; if (!target_id || battle_config.mob_changetarget_byskill) md->target_id = src->id; - + if (flag == -1) res = mobskill_use(md, tick, MSC_CASTTARGETED); else if ((flag&0xffff) == MSC_SKILLUSED) @@ -3312,14 +3312,14 @@ int mobskill_event(struct mob_data *md, struct block_list *src, unsigned int tic res = mobskill_use(md, tick, MSC_CLOSEDATTACKED); else if (flag&BF_LONG && !(flag&BF_MAGIC)) //Long-attacked should not include magic. res = mobskill_use(md, tick, MSC_LONGRANGEATTACKED); - + if (!res) //Restore previous target only if skill condition failed to trigger. [Skotlex] md->target_id = target_id; //Otherwise check if the target is an enemy, and unlock if needed. else if (battle_check_target(&md->bl, src, BCT_ENEMY) <= 0) md->target_id = target_id; - + return res; } @@ -3367,9 +3367,9 @@ int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char status->lhw.atk = status->dex; //Min ATK } if (mode) //User provided mode. - status->mode = mode; + status->mode = mode; else if (flag&1) //Friendly Character, remove looting. - status->mode &= ~MD_LOOTER; + status->mode &= ~MD_LOOTER; status->hp = status->max_hp; status->sp = status->max_sp; memcpy(&db->vd, &sd->vd, sizeof(struct view_data)); @@ -3387,7 +3387,7 @@ int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char **/ fd = sd->fd; sd->fd = 0; - + //Go Backwards to give better priority to advanced skills. for (i=0,j = MAX_SKILL_TREE-1;j>=0 && i< MAX_MOBSKILL ;j--) { skill_id = skill_tree[pc_class2idx(sd->status.class_)][j].id; @@ -3397,7 +3397,7 @@ int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char ) continue; //Normal aggressive mob, disable skills that cannot help them fight - //against players (those with flags UF_NOMOB and UF_NOPC are specific + //against players (those with flags UF_NOMOB and UF_NOPC are specific //to always aid players!) [Skotlex] if (!(flag&1) && skill_get_unit_id(skill_id, 0) && @@ -3408,7 +3408,7 @@ int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char **/ if( !skill_check_condition_castbegin(sd,skill_id,sd->status.skill[skill_id].lv) ) continue; - + memset (&ms[i], 0, sizeof(struct mob_skill)); ms[i].skill_id = skill_id; ms[i].skill_lv = sd->status.skill[skill_id].lv; @@ -3472,7 +3472,7 @@ int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char ms[i].delay += -5000 +(skill_get_time(skill_id, ms[i].skill_lv) + skill_get_time2(skill_id, ms[i].skill_lv))/2; if (ms[i].delay < 2000) ms[i].delay = 2000; //With a minimum of 2 secs. - + if (i+1 < MAX_MOBSKILL) { //duplicate this so it also triggers on self. memcpy(&ms[i+1], &ms[i], sizeof(struct mob_skill)); db->maxskill = ++i; @@ -3498,10 +3498,10 @@ int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char ms[i].permillage = ms[i].permillage*battle_config.mob_skill_rate/100; if (battle_config.mob_skill_delay != 100) ms[i].delay = ms[i].delay*battle_config.mob_skill_delay/100; - + db->maxskill = ++i; } - + /** * We grant the session it's fd value back. **/ @@ -3510,9 +3510,9 @@ int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char //Finally, spawn it. md = mob_once_spawn_sub(&sd->bl, m, x, y, "--en--",class_,event); if (!md) return 0; //Failed? - + md->special_state.clone = 1; - + if (master_id || flag || duration) { //Further manipulate crafted char. if (flag&1) //Friendly Character md->special_state.ai = 1; @@ -3547,7 +3547,7 @@ int mob_clone_delete(struct mob_data *md) } // -// ‰Šú‰» +// Initialization // /*========================================== * Since un-setting [ mob ] up was used, it is an initial provisional value setup. @@ -3641,9 +3641,9 @@ static bool mob_parse_dbrow(char** str) int class_, i, k; double exp, maxhp; struct mob_data data; - + class_ = atoi(str[0]); - + if (class_ <= 1000 || class_ > MAX_MOB_DB) { ShowError("mob_parse_dbrow: Invalid monster ID %d, must be in range %d-%d.\n", class_, 1000, MAX_MOB_DB); return false; @@ -3652,17 +3652,17 @@ static bool mob_parse_dbrow(char** str) ShowError("mob_parse_dbrow: Invalid monster ID %d, reserved for player classes.\n", class_); return false; } - + if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END) { ShowError("mob_parse_dbrow: Invalid monster ID %d. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d).\n", class_, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB); return false; } memset(&entry, 0, sizeof(entry)); - + db = &entry; status = &db->status; - + db->vd.class_ = class_; safestrncpy(db->sprite, str[1], sizeof(db->sprite)); safestrncpy(db->jname, str[2], sizeof(db->jname)); @@ -3671,13 +3671,13 @@ static bool mob_parse_dbrow(char** str) db->lv = cap_value(db->lv, 1, USHRT_MAX); status->max_hp = atoi(str[5]); status->max_sp = atoi(str[6]); - + exp = (double)atoi(str[7]) * (double)battle_config.base_exp_rate / 100.; db->base_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); - + exp = (double)atoi(str[8]) * (double)battle_config.job_exp_rate / 100.; db->job_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); - + status->rhw.range = atoi(str[9]); status->rhw.atk = atoi(str[10]); status->rhw.atk2 = atoi(str[11]); @@ -3696,7 +3696,7 @@ static bool mob_parse_dbrow(char** str) if (status->int_< 1) status->int_= 1; if (status->dex < 1) status->dex = 1; if (status->luk < 1) status->luk = 1; - + db->range2 = atoi(str[20]); db->range3 = atoi(str[21]); if (battle_config.view_range_rate != 100) { @@ -3709,10 +3709,10 @@ static bool mob_parse_dbrow(char** str) if (db->range3 < db->range2) db->range3 = db->range2; } - + status->size = atoi(str[22]); status->race = atoi(str[23]); - + i = atoi(str[24]); //Element status->def_ele = i%10; status->ele_lv = i/20; @@ -3724,11 +3724,11 @@ static bool mob_parse_dbrow(char** str) ShowError("mob_parse_dbrow: Invalid element level %d for monster ID %d, must be in range 1-4.\n", status->ele_lv, class_); return false; } - + status->mode = (int)strtol(str[25], NULL, 0); if (!battle_config.monster_active_enable) status->mode &= ~MD_AGGRESSIVE; - + status->speed = atoi(str[26]); status->aspd_rate = 1000; i = atoi(str[27]); @@ -3748,28 +3748,28 @@ static bool mob_parse_dbrow(char** str) data.level = db->lv; memcpy(&data.status, status, sizeof(struct status_data)); status_calc_misc(&data.bl, status, db->lv); - + // MVP EXP Bonus: MEXP // Some new MVP's MEXP multipled by high exp-rate cause overflow. [LuzZza] exp = (double)atoi(str[30]) * (double)battle_config.mvp_exp_rate / 100.; db->mexp = (unsigned int)cap_value(exp, 0, UINT_MAX); - + //Now that we know if it is an mvp or not, apply battle_config modifiers [Skotlex] maxhp = (double)status->max_hp; if (db->mexp > 0) { //Mvp - if (battle_config.mvp_hp_rate != 100) + if (battle_config.mvp_hp_rate != 100) maxhp = maxhp * (double)battle_config.mvp_hp_rate / 100.; } else //Normal mob - if (battle_config.monster_hp_rate != 100) + if (battle_config.monster_hp_rate != 100) maxhp = maxhp * (double)battle_config.monster_hp_rate / 100.; - + status->max_hp = (unsigned int)cap_value(maxhp, 1, UINT_MAX); if(status->max_sp < 1) status->max_sp = 1; - + //Since mobs always respawn with full life... status->hp = status->max_hp; status->sp = status->max_sp; - + // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per for(i = 0; i < MAX_MVP_DROP; i++) { struct item_data *id; @@ -3781,7 +3781,7 @@ static bool mob_parse_dbrow(char** str) } item_dropratio_adjust(db->mvpitem[i].nameid, class_, &rate_adjust); db->mvpitem[i].p = mob_drop_adjust(atoi(str[32+i*2]), rate_adjust, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max); - + //calculate and store Max available drop chance of the MVP item if (db->mvpitem[i].p) { id = itemdb_search(db->mvpitem[i].nameid); @@ -3791,7 +3791,7 @@ static bool mob_parse_dbrow(char** str) } } } - + for(i = 0; i < MAX_MOB_DROP; i++) { int rate = 0, rate_adjust, type; unsigned short ratemin, ratemax; @@ -3844,7 +3844,7 @@ static bool mob_parse_dbrow(char** str) } item_dropratio_adjust(id->nameid, class_, &rate_adjust); db->dropitem[i].p = mob_drop_adjust(rate, rate_adjust, ratemin, ratemax); - + //calculate and store Max available drop chance of the item if( db->dropitem[i].p && (class_ < 1324 || class_ > 1363) && (class_ < 1938 || class_ > 1946) ) { //Skip treasure chests. @@ -3857,7 +3857,7 @@ static bool mob_parse_dbrow(char** str) } if (k == MAX_SEARCH) continue; - + if (id->mob[k].id != class_) memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0])); id->mob[k].chance = db->dropitem[i].p; @@ -3890,7 +3890,7 @@ static void mob_readdb(void) DBPATH"mob_db.txt", "mob_db2.txt" }; int fi; - + for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) { char path[256]; @@ -3915,16 +3915,16 @@ static int mob_read_sqldb(void) { const char* mob_db_name[] = { mob_db_db, mob_db2_db }; int fi; - + for( fi = 0; fi < ARRAYLENGTH(mob_db_name); ++fi ) { uint32 lines = 0, count = 0; - + // retrieve all rows from the mob database if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", mob_db_name[fi]) ) { Sql_ShowDebug(mmysql_handle); continue; } - + // process rows one by one while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) { // wrap the result into a TXT-compatible format @@ -3932,28 +3932,28 @@ static int mob_read_sqldb(void) char* str[31+2*MAX_MVP_DROP+2*MAX_MOB_DROP]; char* p; int i; - + lines++; for(i = 0, p = line; i < 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP; i++) { char* data; size_t len; Sql_GetData(mmysql_handle, i, &data, &len); - + strcpy(p, data); str[i] = p; p+= len + 1; } - + if (!mob_parse_dbrow(str)) continue; - + count++; } - + // free the query result Sql_FreeResult(mmysql_handle); - + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_db_name[fi]); } return 0; @@ -4135,14 +4135,14 @@ static void mob_readchatdb(void) char line[1024], path[256]; int i, tmp=0; FILE *fp; - sprintf(path, "%s/%s", db_path, arc); + sprintf(path, "%s/%s", db_path, arc); fp=fopen(path, "r"); if(fp == NULL) { ShowWarning("mob_readchatdb: File not found \"%s\", skipping.\n", path); return; } - + while(fgets(line, sizeof(line), fp)) { char *str[3], *p, *np; @@ -4379,17 +4379,17 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current) //Cond2 // numeric value ms->cond2 = atoi(str[11]); - // or special constant + // or special constant ARR_FIND( 0, ARRAYLENGTH(cond2), j, strcmp(str[11],cond2[j].str) == 0 ); if( j < ARRAYLENGTH(cond2) ) ms->cond2 = cond2[j].id; - + ms->val[0]=(int)strtol(str[12],NULL,0); ms->val[1]=(int)strtol(str[13],NULL,0); ms->val[2]=(int)strtol(str[14],NULL,0); ms->val[3]=(int)strtol(str[15],NULL,0); ms->val[4]=(int)strtol(str[16],NULL,0); - + if(ms->skill_id == NPC_EMOTION && mob_id>0 && ms->val[1] == mob_db(mob_id)->status.mode) { @@ -4399,7 +4399,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current) if(ms->skill_id == NPC_EMOTION_ON && mob_id>0 && ms->val[1]) { //Adds a mode to the mob. //Remove aggressive mode when the new mob type is passive. - if (!(ms->val[1]&MD_AGGRESSIVE)) + if (!(ms->val[1]&MD_AGGRESSIVE)) ms->val[3]|=MD_AGGRESSIVE; ms->val[2]|= ms->val[1]; //Add the new mode. ms->val[1] = 0; //Do not "set" it. @@ -4409,7 +4409,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current) ms->emotion=atoi(str[17]); else ms->emotion=-1; - + if(str[18]!=NULL && mob_chat_db[atoi(str[18])]!=NULL) ms->msg_id=atoi(str[18]); else @@ -4484,7 +4484,7 @@ static int mob_read_sqlskilldb(void) { const char* mob_skill_db_name[] = { mob_skill_db_db, mob_skill_db2_db }; int fi; - + if( battle_config.mob_skill_rate == 0 ) { ShowStatus("Mob skill use disabled. Not reading mob skills.\n"); return 0; @@ -4493,13 +4493,13 @@ static int mob_read_sqlskilldb(void) for( fi = 0; fi < ARRAYLENGTH(mob_skill_db_name); ++fi ) { uint32 lines = 0, count = 0; - + // retrieve all rows from the mob skill database if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", mob_skill_db_name[fi]) ) { Sql_ShowDebug(mmysql_handle); continue; } - + // process rows one by one while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) { // wrap the result into a TXT-compatible format @@ -4512,16 +4512,16 @@ static int mob_read_sqlskilldb(void) Sql_GetData(mmysql_handle, i, &str[i], NULL); if( str[i] == NULL ) str[i] = dummy; // get rid of NULL columns } - + if (!mob_parse_row_mobskilldb(str, 19, count)) continue; - + count++; } - + // free the query result Sql_FreeResult(mmysql_handle); - + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_skill_db_name[fi]); } return 0; |