- 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.
|
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
|
||||||
|
|
||||||
2006/07/26
|
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
|
* 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.
|
the constant SC_ALL so you can use in scripts "sc_end SC_ALL;" instead.
|
||||||
[Skotlex]
|
[Skotlex]
|
||||||
|
246
src/map/battle.c
246
src/map/battle.c
@ -2985,6 +2985,46 @@ int battle_check_undead(int race,int element)
|
|||||||
return 0;
|
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)
|
* Checks the state between two targets (rewritten by Skotlex)
|
||||||
* (enemy, friend, party, guild, etc)
|
* (enemy, friend, party, guild, etc)
|
||||||
@ -3013,43 +3053,67 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
|
|||||||
return -1;
|
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.
|
||||||
struct skill_unit *su = (struct skill_unit *)target;
|
if ((t_bl = battle_get_master(target)) == NULL)
|
||||||
if (!su->group)
|
t_bl = target;
|
||||||
return 0;
|
|
||||||
if (skill_get_inf2(su->group->skill_id)&INF2_TRAP)
|
if ((s_bl = battle_get_master(src)) == NULL)
|
||||||
{ //Only a few skills can target traps...
|
s_bl = src;
|
||||||
switch (battle_getcurrentskill(src))
|
|
||||||
{
|
switch (target->type)
|
||||||
case HT_REMOVETRAP:
|
{ //Checks on actual target
|
||||||
case AC_SHOWER:
|
case BL_PC:
|
||||||
case WZ_HEAVENDRIVE:
|
if (((TBL_PC*)target)->invincible_timer != -1 || pc_isinvisible((TBL_PC*)target))
|
||||||
state |= BCT_ENEMY;
|
return -1; //Cannot be targeted yet.
|
||||||
strip_enemy = 0;
|
break;
|
||||||
break;
|
case BL_MOB:
|
||||||
default:
|
if (((TBL_MOB*)target)->special_state.ai == 2)
|
||||||
return 0;
|
{ //Mines are sort of universal enemies.
|
||||||
|
state |= BCT_ENEMY;
|
||||||
|
strip_enemy = 0;
|
||||||
}
|
}
|
||||||
} else if (su->group->skill_id==WZ_ICEWALL)
|
break;
|
||||||
{ //Icewall can be hit by anything except skills.
|
case BL_SKILL:
|
||||||
if (src->type == BL_SKILL)
|
{
|
||||||
|
TBL_SKILL *su = (TBL_SKILL*)target;
|
||||||
|
if (!su->group)
|
||||||
return 0;
|
return 0;
|
||||||
state |= BCT_ENEMY;
|
if (skill_get_inf2(su->group->skill_id)&INF2_TRAP)
|
||||||
strip_enemy = 0;
|
{ //Only a few skills can target traps...
|
||||||
} else //Excepting traps and icewall, you should not be able to target skills.
|
switch (battle_getcurrentskill(src))
|
||||||
|
{
|
||||||
|
case HT_REMOVETRAP:
|
||||||
|
case AC_SHOWER:
|
||||||
|
case WZ_HEAVENDRIVE:
|
||||||
|
state |= BCT_ENEMY;
|
||||||
|
strip_enemy = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (su->group->skill_id==WZ_ICEWALL)
|
||||||
|
{ //Icewall can be hit by anything except skills.
|
||||||
|
if (src->type == BL_SKILL)
|
||||||
|
return 0;
|
||||||
|
state |= BCT_ENEMY;
|
||||||
|
strip_enemy = 0;
|
||||||
|
} else //Excepting traps and icewall, you should not be able to target skills.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//Valid targets with no special checks here.
|
||||||
|
case BL_HOMUNCULUS:
|
||||||
|
break;
|
||||||
|
//All else not specified is an invalid target.
|
||||||
|
default:
|
||||||
return 0;
|
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.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (t_bl->type)
|
switch (t_bl->type)
|
||||||
{
|
{ //Checks on target master
|
||||||
case BL_PC:
|
case BL_PC:
|
||||||
{
|
{
|
||||||
TBL_PC *sd = (TBL_PC*)t_bl;
|
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)
|
if (sd->state.monster_ignore && t_bl != s_bl && flag&BCT_ENEMY)
|
||||||
return 0; //Global inmunity to attacks.
|
return 0; //Global inmunity to attacks.
|
||||||
if (sd->special_state.killable && t_bl != s_bl)
|
if (sd->special_state.killable && t_bl != s_bl)
|
||||||
@ -3067,57 +3131,47 @@ 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)
|
if (!agit_flag && md->guardian_data && md->guardian_data->guild_id)
|
||||||
return 0; //Disable guardians/emperiums owned by Guilds on non-woe times.
|
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;
|
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
|
||||||
struct skill_unit *su = (struct skill_unit *)src;
|
case BL_MOB:
|
||||||
if (!su->group)
|
if (!agit_flag && ((TBL_MOB*)src)->guardian_data && ((TBL_MOB*)src)->guardian_data->guild_id)
|
||||||
return 0;
|
return 0; //Disable guardians/emperium owned by Guilds on non-woe times.
|
||||||
|
break;
|
||||||
if (su->group->src_id == target->id)
|
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:
|
||||||
{
|
{
|
||||||
int inf2;
|
struct skill_unit *su = (struct skill_unit *)src;
|
||||||
inf2 = skill_get_inf2(su->group->skill_id);
|
if (!su->group)
|
||||||
if (inf2&INF2_NO_TARGET_SELF)
|
return 0;
|
||||||
return -1;
|
|
||||||
if (inf2&INF2_TARGET_SELF)
|
//For some mysterious reason ground-skills can't target homun.
|
||||||
return 1;
|
if (target->type == BL_HOMUNCULUS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (su->group->src_id == target->id)
|
||||||
|
{
|
||||||
|
int inf2;
|
||||||
|
inf2 = skill_get_inf2(su->group->skill_id);
|
||||||
|
if (inf2&INF2_NO_TARGET_SELF)
|
||||||
|
return -1;
|
||||||
|
if (inf2&INF2_TARGET_SELF)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
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.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (s_bl->type)
|
switch (s_bl->type)
|
||||||
{
|
{ //Checks on source master
|
||||||
case BL_PC:
|
case BL_PC:
|
||||||
{
|
{
|
||||||
TBL_PC *sd = (TBL_PC*) s_bl;
|
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:
|
case BL_MOB:
|
||||||
{
|
{
|
||||||
TBL_MOB*md = (TBL_MOB*)s_bl;
|
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)
|
if (!agit_flag && md->guardian_data && md->guardian_data->guild_id)
|
||||||
return 0; //Disable guardians/emperium owned by Guilds on non-woe times.
|
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
|
if(md->state.killer) // Is on a rampage too :D
|
||||||
state |= BCT_ENEMY;
|
state |= BCT_ENEMY;
|
||||||
else if (!md->special_state.ai) { //Normal mobs.
|
else if (!md->special_state.ai) { //Normal mobs.
|
||||||
@ -3178,38 +3216,13 @@ 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)
|
if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
|
||||||
state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs.
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case BL_HOMUNCULUS:
|
default:
|
||||||
{
|
//Need some sort of default behaviour for unhandled types.
|
||||||
//[blackhole89] -- check homunculus' targeting by their masters.
|
if (t_bl->type != s_bl->type)
|
||||||
if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
|
state |= BCT_ENEMY;
|
||||||
state |= BCT_ENEMY; //Default enemy. Normal mobs.
|
|
||||||
//Pass on to master.
|
|
||||||
s_bl=(struct block_list *)((struct homun_data*)src)->master;
|
|
||||||
break;
|
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 ((flag&BCT_ALL) == BCT_ALL) { //All actually stands for all attackable chars
|
||||||
@ -3217,7 +3230,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
|
|||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return -1;
|
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;
|
return -1;
|
||||||
|
|
||||||
if (t_bl == s_bl)
|
if (t_bl == s_bl)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user