I'm currently working on a custom fix for an issue with the Devotion skill and its interaction with Defender on my private server. After numerous tests, I've run into a roadblock that I can't seem to resolve.
The problem is that on the first cast of Devotion while Defender is active, the party member receiving Devotion does not inherit the Defender buff. For the buff to apply, I need to deactivate and reactivate Defender after casting Devotion. This behavior is inconsistent and problematic during gameplay, particularly when the party member is dispelled by Clown or Professor. Even if I recast Devotion immediately, Defender is not inherited until I toggle it off and on again.
Here are the key tests I've performed:
Initial Devotion with Defender Active: The party member does not receive the Defender buff on the first cast.
Toggling Defender Off and On: After manually toggling Defender, the party member successfully inherits the buff.
Post-Dispel Scenario: If the party member is dispelled, reapplying Devotion alone does not reinstate Defender; I need to recast Defender first.
I have tried integrating various code adjustments, including forced status updates and reapplications, but the issue persists.
If anyone has encountered a similar problem or has suggestions on how to ensure Defender properly inherits on the first Devotion cast, I would greatly appreciate the assistance.
case SC_DEVOTION:
{
struct block_list *d_bl;
struct status_change *d_sc;
// Get the devotion target (party member) and their status change structure
if ((d_bl = map_id2bl(val1)) && (d_sc = status_get_sc(d_bl)) && d_sc->count) {
struct status_change *src_sc = status_get_sc(bl); // Paladin's status changes
if (src_sc) {
// Check if Paladin has Defender active
if (src_sc->data[SC_DEFENDER]) {
// Get the level of Paladin's Defender
int defender_level = src_sc->data[SC_DEFENDER]->val1;
// Check if the devoted target already has Defender
if (!d_sc->data[SC_DEFENDER]) {
// Apply Defender to the devotion target on the first cast
status_change_start(
d_bl, bl, SC_DEFENDER, 10000, defender_level, 0, 0, 0,
skill_get_time(status_sc2skill(SC_DEFENDER), defender_level),
SCSTART_NOAVOID
);
} else {
// If target already has Defender, update the timer and level
struct status_change_entry *sce = d_sc->data[SC_DEFENDER];
if (sce->timer != INVALID_TIMER) {
// If the timer is active, update the Defender level and reset the timer
delete_timer(sce->timer, status_change_timer);
}
sce->val1 = defender_level; // Update Defender level
sce->timer = add_timer(
gettick() + skill_get_time(status_sc2skill(SC_DEFENDER), defender_level),
status_change_timer,
d_bl->id, SC_DEFENDER
);
}
}
// Check and apply other buffs (Autoguard, Reflectshield, Endure)
const enum sc_type types[] = { SC_AUTOGUARD, SC_REFLECTSHIELD, SC_ENDURE };
int i = 0;
while (i < sizeof(types)/sizeof(types[0])) {
enum sc_type type = types[i];
if (src_sc->data[type]) {
struct status_change_entry *sce = src_sc->data[type];
int level = sce->val1; // Get the level of the buff
// Check if the target already has the status
if (!d_sc->data[type]) {
// Apply the status to the target (1st time cast)
status_change_start(
d_bl, bl, type, 10000, level, 0, 0, (type == SC_REFLECTSHIELD ? 1 : 0),
skill_get_time(status_sc2skill(type), level),
SCSTART_NOAVOID
);
} else {
// Update the status on target (for all buffs except Defender)
struct status_change_entry *target_sce = d_sc->data[type];
target_sce->val1 = level;
if (target_sce->timer != INVALID_TIMER) {
delete_timer(target_sce->timer, status_change_timer);
}
target_sce->timer = add_timer(
gettick() + skill_get_time(status_sc2skill(type), level),
status_change_timer,
d_bl->id, type
);
}
}
i++;
}
}
}
break;
}
Question
agamanaros
I'm currently working on a custom fix for an issue with the Devotion skill and its interaction with Defender on my private server. After numerous tests, I've run into a roadblock that I can't seem to resolve.
The problem is that on the first cast of Devotion while Defender is active, the party member receiving Devotion does not inherit the Defender buff. For the buff to apply, I need to deactivate and reactivate Defender after casting Devotion. This behavior is inconsistent and problematic during gameplay, particularly when the party member is dispelled by Clown or Professor. Even if I recast Devotion immediately, Defender is not inherited until I toggle it off and on again.
Here are the key tests I've performed:
I have tried integrating various code adjustments, including forced status updates and reapplications, but the issue persists.
If anyone has encountered a similar problem or has suggestions on how to ensure Defender properly inherits on the first Devotion cast, I would greatly appreciate the assistance.
Thanks in advance for your help!
Here is my status.cpp BEFORE:
case SC_DEVOTION: { struct block_list *d_bl; struct status_change *d_sc; if( (d_bl = map_id2bl(val1)) && (d_sc = status_get_sc(d_bl)) && d_sc->count ) { // Inherits Status From Source const enum sc_type types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE }; int i = (map_flag_gvg2(bl->m) || map_getmapflag(bl->m, MF_BATTLEGROUND))?2:3; while( i >= 0 ) { enum sc_type type2 = types[i]; if( d_sc->data[type2] ) status_change_start(d_bl, bl, type2, 10000, d_sc->data[type2]->val1, 0, 0, (type2 == SC_REFLECTSHIELD ? 1 : 0), skill_get_time(status_sc2skill(type2),d_sc->data[type2]->val1), (type2 == SC_DEFENDER) ? SCSTART_NOAVOID : SCSTART_NOAVOID|SCSTART_NOICON); i--; } } break; }
And my status.cpp AFTER:
case SC_DEVOTION: { struct block_list *d_bl; struct status_change *d_sc; // Get the devotion target (party member) and their status change structure if ((d_bl = map_id2bl(val1)) && (d_sc = status_get_sc(d_bl)) && d_sc->count) { struct status_change *src_sc = status_get_sc(bl); // Paladin's status changes if (src_sc) { // Check if Paladin has Defender active if (src_sc->data[SC_DEFENDER]) { // Get the level of Paladin's Defender int defender_level = src_sc->data[SC_DEFENDER]->val1; // Check if the devoted target already has Defender if (!d_sc->data[SC_DEFENDER]) { // Apply Defender to the devotion target on the first cast status_change_start( d_bl, bl, SC_DEFENDER, 10000, defender_level, 0, 0, 0, skill_get_time(status_sc2skill(SC_DEFENDER), defender_level), SCSTART_NOAVOID ); } else { // If target already has Defender, update the timer and level struct status_change_entry *sce = d_sc->data[SC_DEFENDER]; if (sce->timer != INVALID_TIMER) { // If the timer is active, update the Defender level and reset the timer delete_timer(sce->timer, status_change_timer); } sce->val1 = defender_level; // Update Defender level sce->timer = add_timer( gettick() + skill_get_time(status_sc2skill(SC_DEFENDER), defender_level), status_change_timer, d_bl->id, SC_DEFENDER ); } } // Check and apply other buffs (Autoguard, Reflectshield, Endure) const enum sc_type types[] = { SC_AUTOGUARD, SC_REFLECTSHIELD, SC_ENDURE }; int i = 0; while (i < sizeof(types)/sizeof(types[0])) { enum sc_type type = types[i]; if (src_sc->data[type]) { struct status_change_entry *sce = src_sc->data[type]; int level = sce->val1; // Get the level of the buff // Check if the target already has the status if (!d_sc->data[type]) { // Apply the status to the target (1st time cast) status_change_start( d_bl, bl, type, 10000, level, 0, 0, (type == SC_REFLECTSHIELD ? 1 : 0), skill_get_time(status_sc2skill(type), level), SCSTART_NOAVOID ); } else { // Update the status on target (for all buffs except Defender) struct status_change_entry *target_sce = d_sc->data[type]; target_sce->val1 = level; if (target_sce->timer != INVALID_TIMER) { delete_timer(target_sce->timer, status_change_timer); } target_sce->timer = add_timer( gettick() + skill_get_time(status_sc2skill(type), level), status_change_timer, d_bl->id, type ); } } i++; } } } break; }
Link to comment
Share on other sites
4 answers to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.