diff options
author | skotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2008-03-07 15:02:32 +0000 |
---|---|---|
committer | skotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2008-03-07 15:02:32 +0000 |
commit | e8ab2885e6c07cdff08e66b55ac6bf5572e39402 (patch) | |
tree | 252a6f6b5d8b5fe93f18041e8b55b543cde956e1 /src/map/mob.c | |
parent | 88d795a036a4f954df1987fe3b241964df182a65 (diff) | |
download | hercules-e8ab2885e6c07cdff08e66b55ac6bf5572e39402.tar.gz hercules-e8ab2885e6c07cdff08e66b55ac6bf5572e39402.tar.bz2 hercules-e8ab2885e6c07cdff08e66b55ac6bf5572e39402.tar.xz hercules-e8ab2885e6c07cdff08e66b55ac6bf5572e39402.zip |
- Added config settings mob_active_time and boss_active_time, what they do is specify a duration during which monsters will keep running their active AI after all players have left their vecinity. Their current defaults are set to 0 (disabled).
- Script induced status changes can now be reduced by stats/cards (but only trigger rate is reduced, not duration)
- Battle delay timers will now check if the target player has the invincible timer active or not.
- Adjusted mob_ai_sub_hard to return a bool indicating whether the AI was executed or not.
- Adjusted clif_damage and clif_skill_damage to set the endure type value based on dmotion and damage, rather than hardchecking for SC_ENDURE.
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@12315 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map/mob.c')
-rw-r--r-- | src/map/mob.c | 113 |
1 files changed, 70 insertions, 43 deletions
diff --git a/src/map/mob.c b/src/map/mob.c index 480442efb..4c7da69cb 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -781,6 +781,7 @@ int mob_spawn (struct mob_data *md) md->state.skillstate = MSS_IDLE; md->next_walktime = tick+rand()%5000+1000; md->last_linktime = tick; + md->last_pcneartime = 0; for (i = 0, c = tick-1000*3600*10; i < MAX_MOBSKILL; i++) md->skilldelay[i] = c; @@ -1199,40 +1200,33 @@ int mob_warpchase(struct mob_data *md, struct block_list *target) /*========================================== * AI of MOB whose is near a Player *------------------------------------------*/ -static int mob_ai_sub_hard(struct block_list *bl,va_list ap) +static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) { - struct mob_data *md; struct block_list *tbl = NULL, *abl = NULL; - unsigned int tick; int dist; int mode; int search_size; int view_range, can_move; - md = (struct mob_data*)bl; - tick = va_arg(ap, unsigned int); - if(md->bl.prev == NULL || md->status.hp <= 0) - return 1; + return false; - if(!md->state.spotted) //Hard AI triggered. - md->state.spotted = 1; - if (DIFF_TICK(tick, md->last_thinktime) < MIN_MOBTHINKTIME) - return 0; + return false; + md->last_thinktime = tick; if (md->ud.skilltimer != -1) - return 0; + return false; if(md->ud.walktimer != -1 && md->ud.walkpath.path_pos <= 3) - return 0; + return false; // Abnormalities if((md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT) || md->sc.data[SC_BLADESTOP]) { //Should reset targets. md->target_id = md->attacked_id = 0; - return 0; + return false; } if (md->sc.count && md->sc.data[SC_BLIND]) @@ -1255,7 +1249,7 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) ((TBL_PC*)tbl)->invincible_timer != INVALID_TIMER) )) { //Unlock current target. if (mob_warpchase(md, tbl)) - return 0; //Chasing this target. + return true; //Chasing this target. mob_unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Imediately do random walk. tbl = NULL; } @@ -1274,17 +1268,17 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) ) && md->state.attacked_count++ >= RUDE_ATTACKED_COUNT && !mobskill_use(md, tick, MSC_RUDEATTACKED) && //If can't rude Attack - can_move && unit_escape(bl, tbl, rand()%10 +1)) //Attempt escape + can_move && unit_escape(&md->bl, tbl, rand()%10 +1)) //Attempt escape { //Escaped md->attacked_id = 0; - return 0; + return true; } } else if ((abl= map_id2bl(md->attacked_id)) && (!tbl || mob_can_changetarget(md, abl, mode))) { if (md->bl.m != abl->m || abl->prev == NULL || (dist = distance_bl(&md->bl, abl)) >= MAX_MINCHASE || - battle_check_target(bl, abl, BCT_ENEMY) <= 0 || - (battle_config.mob_ai&0x2 && !status_check_skilluse(bl, abl, 0, 0)) || //Retaliate check + battle_check_target(&md->bl, abl, BCT_ENEMY) <= 0 || + (battle_config.mob_ai&0x2 && !status_check_skilluse(&md->bl, abl, 0, 0)) || //Retaliate check (!battle_check_range(&md->bl, abl, md->status.rhw.range) && ( //Reach check (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && @@ -1295,13 +1289,13 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) ) { //Rude attacked if (md->state.attacked_count++ >= RUDE_ATTACKED_COUNT && !mobskill_use(md, tick, MSC_RUDEATTACKED) && can_move && - !tbl && unit_escape(bl, abl, rand()%10 +1)) + !tbl && unit_escape(&md->bl, abl, rand()%10 +1)) { //Escaped. //TODO: Maybe it shouldn't attempt to run if it has another, valid target? md->attacked_id = 0; - return 0; + return true; } - } else if (!(battle_config.mob_ai&0x2) && !status_check_skilluse(bl, abl, 0, 0)) { + } else if (!(battle_config.mob_ai&0x2) && !status_check_skilluse(&md->bl, abl, 0, 0)) { //Can't attack back, but didn't invoke a rude attacked skill... } else { //Attackable if (!tbl || dist < md->status.rhw.range || !check_distance_bl(&md->bl, tbl, dist) @@ -1324,7 +1318,7 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) // Processing of slave monster if (md->master_id > 0 && mob_ai_sub_hard_slavemob(md, tick)) - return 0; + return true; // Scan area for targets if (!tbl && mode&MD_LOOTER && md->lootitem && DIFF_TICK(tick, md->ud.canact_tick) > 0 && @@ -1351,7 +1345,7 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) md->state.aggressive = 1; //Restore angry state when no targets are available. //This handles triggering idle walk/skill. mob_unlocktarget(md, tick); - return 0; + return true; } //Target exists, attack or loot as applicable. @@ -1359,29 +1353,29 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) { //Loot time. struct flooritem_data *fitem; if (md->ud.target == tbl->id && md->ud.walktimer != -1) - return 0; //Already locked. + return true; //Already locked. if (md->lootitem == NULL) { //Can't loot... mob_unlocktarget (md, tick); - return 0; + return true; } if (!check_distance_bl(&md->bl, tbl, 1)) { //Still not within loot range. if (!(mode&MD_CANMOVE)) { //A looter that can't move? Real smart. mob_unlocktarget(md,tick); - return 0; + return true; } if (!can_move) //Stuck. Wait before walking. - return 0; + return true; md->state.skillstate = MSS_LOOT; if (!unit_walktobl(&md->bl, tbl, 0, 1)) mob_unlocktarget(md, tick); //Can't loot... - return 0; + return true; } //Within looting range. if (md->ud.attacktimer != -1) - return 0; //Busy attacking? + return true; //Busy attacking? fitem = (struct flooritem_data *)tbl; if(log_config.enable_logs&0x10) //Logs items, taken by (L)ooter Mobs [Lupus] @@ -1404,17 +1398,17 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) //Clear item. map_clearflooritem (tbl->id); mob_unlocktarget (md,tick); - return 0; + return true; } //Attempt to attack. //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 != -1) //Already locked. - return 0; + return true; if (battle_check_range (&md->bl, tbl, md->status.rhw.range)) { //Target within range, engage unit_attack(&md->bl,tbl->id,1); - return 0; + return true; } //Out of range... @@ -1423,7 +1417,7 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) md->state.skillstate = MSS_IDLE; if (!mobskill_use(md, tick, -1)) mob_unlocktarget(md,tick); - return 0; + return true; } if (!can_move) @@ -1431,7 +1425,7 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) md->state.skillstate = MSS_IDLE; if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL)) mobskill_use(md, tick, -1); - return 0; + return true; } if (md->ud.walktimer != -1 && md->ud.target == tbl->id && @@ -1439,13 +1433,26 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) !(battle_config.mob_ai&0x1) || check_distance_blxy(tbl, md->ud.to_x, md->ud.to_y, md->status.rhw.range) )) //Current target tile is still within attack range. - return 0; + return true; //Follow up if possible. if(!mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) || !unit_walktobl(&md->bl, tbl, md->status.rhw.range, 2)) mob_unlocktarget(md,tick); + return true; +} + +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)) + { //Hard AI triggered. + if(!md->state.spotted) + md->state.spotted = 1; + md->last_pcneartime = tick; + } return 0; } @@ -1456,7 +1463,7 @@ static int mob_ai_sub_foreachclient(struct map_session_data *sd,va_list ap) { unsigned int tick; tick=va_arg(ap,unsigned int); - map_foreachinrange(mob_ai_sub_hard,&sd->bl, AREA_SIZE+ACTIVE_AI_RANGE, BL_MOB,tick); + map_foreachinrange(mob_ai_sub_hard_timer,&sd->bl, AREA_SIZE+ACTIVE_AI_RANGE, BL_MOB,tick); return 0; } @@ -1475,20 +1482,39 @@ static int mob_ai_sub_lazy(DBKey key,void * data,va_list ap) if(md->bl.prev == NULL) return 0; + tick=va_arg(ap,unsigned int); + if (md->nd || (battle_config.mob_ai&0x20 && map[md->bl.m].users>0)) - return mob_ai_sub_hard(&md->bl, ap); + return (int)mob_ai_sub_hard(md, tick); - tick=va_arg(ap,unsigned int); + if (md->bl.prev==NULL || md->status.hp == 0) + return 1; + + if(battle_config.mob_active_time && + md->last_pcneartime && + !(md->status.mode&MD_BOSS) && + DIFF_TICK(tick,md->last_thinktime) > MIN_MOBTHINKTIME) + { + if (DIFF_TICK(tick,md->last_pcneartime) < battle_config.mob_active_time) + return (int)mob_ai_sub_hard(md, tick); + md->last_pcneartime = 0; + } + + if(battle_config.boss_active_time && + md->last_pcneartime && + (md->status.mode&MD_BOSS) && + DIFF_TICK(tick,md->last_thinktime) > MIN_MOBTHINKTIME) + { + if (DIFF_TICK(tick,md->last_pcneartime) < battle_config.boss_active_time) + return (int)mob_ai_sub_hard(md, tick); + md->last_pcneartime = 0; + } if(DIFF_TICK(tick,md->last_thinktime)< 10*MIN_MOBTHINKTIME) return 0; md->last_thinktime=tick; - if (md->bl.prev==NULL || md->status.hp == 0) - return 1; - - // 取り巻きモンスターの処理(呼び戻しされた時) if (md->master_id) { mob_ai_sub_hard_slavemob (md,tick); return 0; @@ -2345,6 +2371,7 @@ void mob_revive(struct mob_data *md, unsigned int hp) md->last_thinktime = tick; md->next_walktime = tick+rand()%50+5000; md->last_linktime = tick; + md->last_pcneartime = 0; if (!md->bl.prev) map_addblock(&md->bl); if(pcdb_checkid(md->vd->class_) && md->nd) |