- Added battle_get_master which returns the master bl of a given object.
- Recoded battle_check_target to use battle_get_master, the src/target switch has been split into two, so that actual target and master target are seperately treated (same for source). git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@7897 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
7cd47130d0
commit
cfe71d744a
@ -4,6 +4,11 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
|
||||
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
|
||||
|
||||
2006/07/26
|
||||
* Added battle_get_master which returns the master bl of a given object.
|
||||
[Skotlex]
|
||||
* Recoded battle_check_target to use battle_get_master, the src/target
|
||||
switch has been split into two, so that actual target and master target are
|
||||
seperately treated (same for source). [Skotlex]
|
||||
* Added support for "sc_end -1" which will clear all status changes. Added
|
||||
the constant SC_ALL so you can use in scripts "sc_end SC_ALL;" instead.
|
||||
[Skotlex]
|
||||
|
180
src/map/battle.c
180
src/map/battle.c
@ -2985,6 +2985,46 @@ int battle_check_undead(int race,int element)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Returns the upmost level master starting with the given object
|
||||
static struct block_list* battle_get_master(struct block_list *src)
|
||||
{
|
||||
do {
|
||||
switch (src->type) {
|
||||
case BL_PET:
|
||||
if (((TBL_PET*)src)->msd)
|
||||
src = (struct block_list*)((TBL_PET*)src)->msd;
|
||||
else
|
||||
return src;
|
||||
break;
|
||||
case BL_MOB:
|
||||
if (((TBL_MOB*)src)->master_id)
|
||||
src = map_id2bl(((TBL_MOB*)src)->master_id);
|
||||
else
|
||||
return src;
|
||||
break;
|
||||
case BL_HOMUNCULUS:
|
||||
if (((TBL_HOMUNCULUS*)src)->master)
|
||||
src = (struct block_list*)((TBL_HOMUNCULUS*)src)->master;
|
||||
else
|
||||
return src;
|
||||
break;
|
||||
case BL_SKILL:
|
||||
if (((TBL_SKILL*)src)->group && ((TBL_SKILL*)src)->group->src_id)
|
||||
src = map_id2bl(((TBL_SKILL*)src)->group->src_id);
|
||||
else
|
||||
return src;
|
||||
break;
|
||||
default:
|
||||
return src;
|
||||
}
|
||||
#ifdef RECURSIVE_MASTER_CHECK
|
||||
} while (src);
|
||||
#else
|
||||
} while (0); //Single pass check.
|
||||
#endif
|
||||
return src;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Checks the state between two targets (rewritten by Skotlex)
|
||||
* (enemy, friend, party, guild, etc)
|
||||
@ -3013,9 +3053,30 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (target->type == BL_SKILL) //Needed out of the switch in case the ownership needs to be passed skill->mob->master
|
||||
//t_bl/s_bl hold the 'master' of the attack, while src/target are the actual
|
||||
//objects involved.
|
||||
if ((t_bl = battle_get_master(target)) == NULL)
|
||||
t_bl = target;
|
||||
|
||||
if ((s_bl = battle_get_master(src)) == NULL)
|
||||
s_bl = src;
|
||||
|
||||
switch (target->type)
|
||||
{ //Checks on actual target
|
||||
case BL_PC:
|
||||
if (((TBL_PC*)target)->invincible_timer != -1 || pc_isinvisible((TBL_PC*)target))
|
||||
return -1; //Cannot be targeted yet.
|
||||
break;
|
||||
case BL_MOB:
|
||||
if (((TBL_MOB*)target)->special_state.ai == 2)
|
||||
{ //Mines are sort of universal enemies.
|
||||
state |= BCT_ENEMY;
|
||||
strip_enemy = 0;
|
||||
}
|
||||
break;
|
||||
case BL_SKILL:
|
||||
{
|
||||
struct skill_unit *su = (struct skill_unit *)target;
|
||||
TBL_SKILL *su = (TBL_SKILL*)target;
|
||||
if (!su->group)
|
||||
return 0;
|
||||
if (skill_get_inf2(su->group->skill_id)&INF2_TRAP)
|
||||
@ -3039,17 +3100,20 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
|
||||
strip_enemy = 0;
|
||||
} else //Excepting traps and icewall, you should not be able to target skills.
|
||||
return 0;
|
||||
if ((t_bl = map_id2bl(su->group->src_id)) == NULL)
|
||||
t_bl = target; //Fallback on the trap itself, otherwise consider this a "versus caster" scenario.
|
||||
}
|
||||
//Valid targets with no special checks here.
|
||||
case BL_HOMUNCULUS:
|
||||
break;
|
||||
//All else not specified is an invalid target.
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (t_bl->type)
|
||||
{
|
||||
{ //Checks on target master
|
||||
case BL_PC:
|
||||
{
|
||||
TBL_PC *sd = (TBL_PC*)t_bl;
|
||||
if (sd->invincible_timer != -1 || pc_isinvisible(sd))
|
||||
return -1; //Cannot be targeted yet.
|
||||
if (sd->state.monster_ignore && t_bl != s_bl && flag&BCT_ENEMY)
|
||||
return 0; //Global inmunity to attacks.
|
||||
if (sd->special_state.killable && t_bl != s_bl)
|
||||
@ -3067,42 +3131,32 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
|
||||
|
||||
if (!agit_flag && md->guardian_data && md->guardian_data->guild_id)
|
||||
return 0; //Disable guardians/emperiums owned by Guilds on non-woe times.
|
||||
if (md->special_state.ai == 2)
|
||||
{ //Mines are sort of universal enemies.
|
||||
state |= BCT_ENEMY;
|
||||
strip_enemy = 0;
|
||||
}
|
||||
if (md->master_id && (t_bl = map_id2bl(md->master_id)) == NULL)
|
||||
t_bl = &md->bl; //Fallback on the mob itself, otherwise consider this a "versus master" scenario.
|
||||
break;
|
||||
}
|
||||
case BL_PET:
|
||||
{
|
||||
return 0; //Pets cannot be targetted.
|
||||
}
|
||||
case BL_HOMUNCULUS:
|
||||
{
|
||||
//For some mysterious reason ground-skills can't target homun.
|
||||
if (src->type == BL_SKILL)
|
||||
return 0;
|
||||
//Just fallback on master.
|
||||
t_bl=(struct block_list *)((TBL_HOMUNCULUS*)target)->master;
|
||||
if (((TBL_PC*)t_bl)->state.monster_ignore && t_bl != s_bl && flag&BCT_ENEMY)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
case BL_SKILL: //Skill with no owner? Kinda odd... but.. let it through.
|
||||
break;
|
||||
default: //Invalid target
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (src->type == BL_SKILL)
|
||||
switch(src->type)
|
||||
{ //Checks on actual src type
|
||||
case BL_MOB:
|
||||
if (!agit_flag && ((TBL_MOB*)src)->guardian_data && ((TBL_MOB*)src)->guardian_data->guild_id)
|
||||
return 0; //Disable guardians/emperium owned by Guilds on non-woe times.
|
||||
break;
|
||||
case BL_PET:
|
||||
if (t_bl->type != BL_MOB && flag&BCT_ENEMY)
|
||||
return 0; //Pet may not attack non-mobs.
|
||||
if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data && flag&BCT_ENEMY)
|
||||
return 0; //pet may not attack Guardians/Emperium
|
||||
break;
|
||||
case BL_SKILL:
|
||||
{
|
||||
struct skill_unit *su = (struct skill_unit *)src;
|
||||
if (!su->group)
|
||||
return 0;
|
||||
|
||||
//For some mysterious reason ground-skills can't target homun.
|
||||
if (target->type == BL_HOMUNCULUS)
|
||||
return 0;
|
||||
|
||||
if (su->group->src_id == target->id)
|
||||
{
|
||||
int inf2;
|
||||
@ -3112,12 +3166,12 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
|
||||
if (inf2&INF2_TARGET_SELF)
|
||||
return 1;
|
||||
}
|
||||
if ((s_bl = map_id2bl(su->group->src_id)) == NULL)
|
||||
s_bl = src; //Fallback on the trap itself, otherwise consider this a "caster versus enemy" scenario.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (s_bl->type)
|
||||
{
|
||||
{ //Checks on source master
|
||||
case BL_PC:
|
||||
{
|
||||
TBL_PC *sd = (TBL_PC*) s_bl;
|
||||
@ -3149,24 +3203,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
|
||||
case BL_MOB:
|
||||
{
|
||||
TBL_MOB*md = (TBL_MOB*)s_bl;
|
||||
#ifdef RECURSIVE_MASTER_CHECK
|
||||
struct block_list *tmp_bl = NULL;
|
||||
TBL_MOB *tmp_md = NULL;
|
||||
#endif
|
||||
if (!agit_flag && md->guardian_data && md->guardian_data->guild_id)
|
||||
return 0; //Disable guardians/emperium owned by Guilds on non-woe times.
|
||||
#ifdef RECURSIVE_MASTER_CHECK
|
||||
tmp_md = md;
|
||||
while(tmp_md->master_id && (tmp_bl = map_id2bl(tmp_md->master_id))){
|
||||
if(t_bl->id == tmp_bl->id){
|
||||
state |= BCT_PARTY;
|
||||
break;
|
||||
}
|
||||
if(tmp_bl->type != BL_MOB)
|
||||
break;
|
||||
tmp_md = (TBL_MOB *)tmp_bl;
|
||||
}
|
||||
#endif
|
||||
if(md->state.killer) // Is on a rampage too :D
|
||||
state |= BCT_ENEMY;
|
||||
else if (!md->special_state.ai) { //Normal mobs.
|
||||
@ -3178,46 +3216,22 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
|
||||
if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
|
||||
state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs.
|
||||
}
|
||||
if (md->master_id && (s_bl = map_id2bl(md->master_id)) == NULL)
|
||||
s_bl = &md->bl; //Fallback on the mob itself, otherwise consider this a "from master" scenario.
|
||||
break;
|
||||
}
|
||||
case BL_HOMUNCULUS:
|
||||
{
|
||||
//[blackhole89] -- check homunculus' targeting by their masters.
|
||||
if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
|
||||
state |= BCT_ENEMY; //Default enemy. Normal mobs.
|
||||
//Pass on to master.
|
||||
s_bl=(struct block_list *)((struct homun_data*)src)->master;
|
||||
default:
|
||||
//Need some sort of default behaviour for unhandled types.
|
||||
if (t_bl->type != s_bl->type)
|
||||
state |= BCT_ENEMY;
|
||||
break;
|
||||
}
|
||||
case BL_PET:
|
||||
{
|
||||
TBL_PET *pd = (TBL_PET*)s_bl;
|
||||
if (t_bl->type != BL_MOB && flag&BCT_ENEMY)
|
||||
return 0; //Pet may not attack non-mobs.
|
||||
if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data && flag&BCT_ENEMY)
|
||||
return 0; //pet may not attack Guardians/Emperium
|
||||
if (t_bl->type != BL_PC)
|
||||
state |= BCT_ENEMY; //Stock enemy type.
|
||||
if (pd->msd)
|
||||
s_bl = &pd->msd->bl; //"My master's enemies are my enemies..."
|
||||
break;
|
||||
}
|
||||
case BL_SKILL: //Skill with no owner? Fishy, but let it through.
|
||||
break;
|
||||
case BL_NPC: // allows NPC-set skill units to proceed [blackhole89]
|
||||
break;
|
||||
default: //Invalid source of attack?
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((flag&BCT_ALL) == BCT_ALL) { //All actually stands for all attackable chars
|
||||
if (target->type&BL_CHAR)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
} else if (flag == BCT_NOONE) //Why would someone use this? no clue.
|
||||
} else
|
||||
if (flag == BCT_NOONE) //Why would someone use this? no clue.
|
||||
return -1;
|
||||
|
||||
if (t_bl == s_bl)
|
||||
|
Loading…
x
Reference in New Issue
Block a user