Issue information

Issue ID
#8413
Status
New
Severity
None
Started
kyeme
Oct 22, 2014 11:15
Last Post
Zephyr
Oct 23, 2014 1:00
Confirmation
Yes (1)
No (0)

kyeme - Oct 22, 2014 11:15

On official should be the same behavior like the emperium inside a castle. cant be damaged by magic or other skills.

But here in hercules, the emperium outside castle it can be damaged by magic or other skills.

This post has been edited by kyeme on Oct 22, 2014 11:17

GmOcean - Oct 22, 2014 23:21

Can confirm, that this is not working as on official.

I suggest we discard battle.c checks to see if the " target is an emperium " and instead switch to a custom mob-state which prevents and blocks all damage unless it's an auto-attack. It'd also be better in the long run since it can be applied to different monsters.

Then we can simply just do something like the following: if( target->state.emperium ){ //Auto-attack can only hit and a select few skills like gravitation. } else { //invalid target }

Zephyr - Oct 23, 2014 1:00

[font='lucida sans unicode', 'lucida grande', sans-serif]I think this happens because when you spawn a monster using the "monster" script command, the source identify the ID and set the guardian data:[/font][code=auto:0] if ( class_ == MOBID_EMPERIUM && !no_guardian_data ) { struct guild_castle* gc = guild->mapindex2gc(map_id2index(m)); struct guild* g = (gc) ? guild->search(gc->guild_id) : NULL; if( gc ) { md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data)); md->guardian_data->castle = gc; md->guardian_data->number = MAX_GUARDIANS; if( g ) md->guardian_data->g = g; else if( gc->guild_id ) //Guild not yet available, retry in 5. timer->add(timer->gettick()+5000,mob->spawn_guardian_sub,md->bl.id,gc->guild_id); } } // end addition [Valaris] [/code]

[font='lucida sans unicode', 'lucida grande', sans-serif]And then, battle.c checks this data from the Emperium setted before:[/font][code=auto:0] if(md && md->guardian_data) { if(class_ == MOBID_EMPERIUM && flag&BF_SKILL) { //Skill immunity. switch (skill_id) { #ifndef RENEWAL case MO_TRIPLEATTACK: case HW_GRAVITATION: #endif case TF_DOUBLE: break; default: return 0; } } if(src->type != BL_MOB) { struct guild *g = src->type == BL_PC ? ((TBL_PC *)src)->guild : guild->search(status->get_guild_id(src)); if (class_ == MOBID_EMPERIUM && (!g || guild->checkskill(g,GD_APPROVAL) <= 0 )) return 0; if (g && battle_config.guild_max_castles && guild->checkcastles(g)>=battle_config.guild_max_castles) return 0; // [MouseJstr] } } [/code]
[font='lucida sans unicode', 'lucida grande', sans-serif]But when you summon it with @monster/@spawn, it's summoned without the guardian data, and users can spam skills on it normally:

atcommand.c calling a @monster mob.[/font][code=auto:0] k = mob->once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, eventname, size, AI_NONE|(mob_id == MOBID_EMPERIUM?0x200:0x0)); [/code]
[font='lucida sans unicode', 'lucida grande', sans-serif]mob.c handling the AI.[/font][code=auto:0] if( ai && ai&0x200 ) { no_guardian_data = true; ai &=~ 0x200; } [/code]
[font='lucida sans unicode', 'lucida grande', sans-serif]So, bellow, this check can't be reached on mob.c:[/font][code=auto:0] if ( class_ == MOBID_EMPERIUM && !no_guardian_data ) { ... } [/code]
[font='lucida sans unicode', 'lucida grande', sans-serif]...because no_guardian_data = true.

So, that check above on battle.c cannot be reachable too:[/font][code=auto:0] if(md && md->guardian_data) { if(class_ == MOBID_EMPERIUM && flag&BF_SKILL) { [/code]
[font='lucida sans unicode', 'lucida grande', sans-serif]That's why we can cast any skills on Emperium. I think one variable can do the job, modifiying the check above to:[/font][code=auto:0] if(md && md->guardian_data && ourvar) { if(class_ == MOBID_EMPERIUM && flag&BF_SKILL) { //Skill immunity. switch (skill_id) { #ifndef RENEWAL case MO_TRIPLEATTACK: case HW_GRAVITATION: #endif case TF_DOUBLE: break; default: return 0; } } if(src->type != BL_MOB && !ourvar) { struct guild *g = src->type == BL_PC ? ((TBL_PC *)src)->guild : guild->search(status->get_guild_id(src)); if (class_ == MOBID_EMPERIUM && (!g || guild->checkskill(g,GD_APPROVAL) <= 0 )) return 0; if (g && battle_config.guild_max_castles && guild->checkcastles(g)>=battle_config.guild_max_castles) return 0; // [MouseJstr] } } [/code]
[font='lucida sans unicode', 'lucida grande', sans-serif]And at the mob.c AI check:[/font][code=auto:0] if( ai && ai&0x200 ) { no_guardian_data = true; ourvar = true; ai &=~ 0x200; } [/code]
[font='lucida sans unicode', 'lucida grande', sans-serif]I didn't tested anything, and I'm not good at the src, so I just THINK it can work. Of course there's more job to do, declaring the variable, etc. To avoid declaring another variable, we can also use the no_guardian_data to do the trick too. But both ways we have to modify all the functions to add one more argument, etc, etc...[/font]

[font='lucida sans unicode', 'lucida grande', sans-serif]OR we can just remove this check:[/font][code=auto:0] if(md && md->guardian_data) { [/code]
[font='lucida sans unicode', 'lucida grande', sans-serif]And pray. :lol: [/font]

This post has been edited by Zephyr on Oct 23, 2014 1:09