В чистом эмуляторе eAthena, таро которое ломает, имеет следующий список: Код: int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; В моде, который здесь установлен, список такой же. Далее, вызывается функция (если персонаж не умер после 1к урона), она рандомит одно из 5 выше значений: Код: skill_break_equip(bl, where[rand()%5], 10000, BCT_ENEMY); В этой функции есть общие проверки типа: Код: if (sd) { if (sd->unbreakable_equip) where &= ~sd->unbreakable_equip; if (sd->unbreakable) rate -= rate*sd->unbreakable/100; if (where&EQP_WEAPON) { switch (sd->status.weapon) { case W_FIST: //Bare fists should not break :P case W_1HAXE: case W_2HAXE: case W_MACE: // Axes and Maces can't be broken [DracoRPG] case W_2HMACE: case W_STAFF: case W_2HSTAFF: case W_BOOK: //Rods and Books can't be broken [Skotlex] case W_HUUMA: where &= ~EQP_WEAPON; } } } Из описания структуры: Код: unsigned short unbreakable_equip; //100% break resistance on certain equipment Но если честно, я потерялся в том, что Вам нужно уточнить, могу проверить / приложить исходники почему это так (эмулятор на котором будет проведено тестирования по механике совпадает с фриро). Листинги функций выше актуальны? Могу приложить файлы (ссылки) или вырезки из них.
думаю и так норм должно ли ломать карта таро колесница предметы под протектом + должно ли ломать карто таро колесница предметы на которых указано свойство - неломаемый
Беглый осмотр ниже без проверки "боем", если есть сомнения - завтра проверю, сейчас с ноута просто для информации. Если речь идет про bonus bUnbreakableArmor,0; (как у валькоармора), из документации эмулятора: Код: bonus bUnbreakableArmor,n; Armor cannot be damaged/broken by any means (n is meaningless) Этот бонус как раз влияет на переменную выше: Код: case SP_UNBREAKABLE_ARMOR: if(sd->state.lr_flag!=2) sd->unbreakable_equip|= EQP_ARMOR; break; Валькоармор таро ломать не должно. По поводу ФП, оно делает следующее: Код: status_change_end(bl, (sc_type)(SC_STRIPWEAPON + i), INVALID_TIMER); sc_start(bl,(sc_type)(SC_CP_WEAPON + i),100,skilllv,skilltime); Опять же возращаясь к skill_break_equip, в нем есть список: Код: const enum sc_type scdef[4] = {SC_CP_WEAPON, SC_CP_ARMOR, SC_CP_SHIELD, SC_CP_HELM}; Этот список эквипа не ломает. Для eAthena (без мода, который здесь есть): Спойлер: status_change_end_ Код: int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line) { struct map_session_data *sd; struct status_change *sc; struct status_change_entry *sce; struct status_data *status; struct view_data *vd; int opt_flag=0, calc_flag; nullpo_ret(bl); sc = status_get_sc(bl); status = status_get_status_data(bl); if(type < 0 || type >= SC_MAX || !sc || !(sce = sc->data[type])) return 0; sd = BL_CAST(BL_PC,bl); if (sce->timer != tid && tid != INVALID_TIMER) return 0; if (tid == INVALID_TIMER) { if (type == SC_ENDURE && sce->val4) //Do not end infinite endure. return 0; if (sce->timer != INVALID_TIMER) //Could be a SC with infinite duration delete_timer(sce->timer,status_change_timer); if (sc->opt1) switch (type) { //"Ugly workaround" [Skotlex] //delays status change ending so that a skill that sets opt1 fails to //trigger when it also removed one case SC_STONE: sce->val3 = 0; //Petrify time counter. case SC_FREEZE: case SC_STUN: case SC_SLEEP: if (sce->val1) { //Removing the 'level' shouldn't affect anything in the code //since these SC are not affected by it, and it lets us know //if we have already delayed this attack or not. sce->val1 = 0; sce->timer = add_timer(gettick()+10, status_change_timer, bl->id, type); return 1; } } } sc->data[type] = NULL; (sc->count)--; vd = status_get_viewdata(bl); calc_flag = StatusChangeFlagTable[type]; switch(type){ case SC_WEDDING: case SC_XMAS: case SC_SUMMER: if (!vd) break; if (sd) { //Load data from sd->status.* as the stored values could have changed. //Must remove OPTION to prevent class being rechanged. sc->option &= type==SC_WEDDING?~OPTION_WEDDING:type==SC_XMAS?~OPTION_XMAS:~OPTION_SUMMER; clif_changeoption(&sd->bl); status_set_viewdata(bl, sd->status.class_); } else { vd->class_ = sce->val1; vd->weapon = sce->val2; vd->shield = sce->val3; vd->cloth_color = sce->val4; } clif_changelook(bl,LOOK_BASE,vd->class_); clif_changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); clif_changelook(bl,LOOK_WEAPON,vd->weapon); clif_changelook(bl,LOOK_SHIELD,vd->shield); if(sd) clif_skillinfoblock(sd); break; case SC_RUN: { struct unit_data *ud = unit_bl2ud(bl); bool begin_spurt = true; if (ud) { if(!ud->state.running) begin_spurt = false; ud->state.running = 0; if (ud->walktimer != INVALID_TIMER) unit_stop_walking(bl,1); } if (begin_spurt && sce->val1 >= 7 && DIFF_TICK(gettick(), sce->val4) <= 1000 && (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0)) ) sc_start(bl,SC_SPURT,100,sce->val1,skill_get_time2(status_sc2skill(type), sce->val1)); } break; case SC_AUTOBERSERK: if (sc->data[SC_PROVOKE] && sc->data[SC_PROVOKE]->val2 == 1) status_change_end(bl, SC_PROVOKE, INVALID_TIMER); break; case SC_ENDURE: case SC_DEFENDER: case SC_REFLECTSHIELD: case SC_AUTOGUARD: { struct map_session_data *tsd; if( bl->type == BL_PC ) { // Clear Status from others int i; for( i = 0; i < 5; i++ ) { if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) && tsd->sc.data[type] ) status_change_end(&tsd->bl, type, INVALID_TIMER); } } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag ) { // Clear Status from Master tsd = ((TBL_MER*)bl)->master; if( tsd && tsd->sc.data[type] ) status_change_end(&tsd->bl, type, INVALID_TIMER); } } break; case SC_DEVOTION: { struct block_list *d_bl = map_id2bl(sce->val1); if( d_bl ) { if( d_bl->type == BL_PC ) ((TBL_PC*)d_bl)->devotion[sce->val2] = 0; else if( d_bl->type == BL_MER ) ((TBL_MER*)d_bl)->devotion_flag = 0; clif_devotion(d_bl, NULL); } status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER); status_change_end(bl, SC_DEFENDER, INVALID_TIMER); status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); status_change_end(bl, SC_ENDURE, INVALID_TIMER); } break; case SC_BLADESTOP: if(sce->val4) { int tid = sce->val4; struct block_list *tbl = map_id2bl(tid); struct status_change *tsc = status_get_sc(tbl); sce->val4 = 0; if(tbl && tsc && tsc->data[SC_BLADESTOP]) { tsc->data[SC_BLADESTOP]->val4 = 0; status_change_end(tbl, SC_BLADESTOP, INVALID_TIMER); } clif_bladestop(bl, tid, 0); } break; case SC_DANCING: { const char* prevfile = "<unknown>"; int prevline = 0; struct map_session_data *dsd; struct status_change_entry *dsc; struct skill_unit_group *group; if( sd ) { if( sd->delunit_prevfile ) {// initially this is NULL, when a character logs in prevfile = sd->delunit_prevfile; prevline = sd->delunit_prevline; } else { prevfile = "<none>"; } sd->delunit_prevfile = file; sd->delunit_prevline = line; } if(sce->val4 && sce->val4 != BCT_SELF && (dsd=map_id2sd(sce->val4))) {// end status on partner as well dsc = dsd->sc.data[SC_DANCING]; if(dsc) { //This will prevent recursive loops. dsc->val2 = dsc->val4 = 0; status_change_end(&dsd->bl, SC_DANCING, INVALID_TIMER); } } if(sce->val2) {// erase associated land skill group = skill_id2group(sce->val2); if( group == NULL ) { ShowDebug("status_change_end: SC_DANCING is missing skill unit group (val1=%d, val2=%d, val3=%d, val4=%d, timer=%d, tid=%d, char_id=%d, map=%s, x=%d, y=%d, prev=%s:%d, from=%s:%d). Please report this! (#3504)\n", sce->val1, sce->val2, sce->val3, sce->val4, sce->timer, tid, sd ? sd->status.char_id : 0, mapindex_id2name(map_id2index(bl->m)), bl->x, bl->y, prevfile, prevline, file, line); } sce->val2 = 0; skill_delunitgroup(group); } if((sce->val1&0xFFFF) == CG_MOONLIT) clif_status_change(bl,SI_MOONLIT,0,0); status_change_end(bl, SC_LONGING, INVALID_TIMER); } break; case SC_NOCHAT: if (sd && sd->status.manner < 0 && tid != INVALID_TIMER) sd->status.manner = 0; if (sd && tid == INVALID_TIMER) { pc_onstatuschanged(sd,SP_MANNER); } break; case SC_SPLASHER: { struct block_list *src=map_id2bl(sce->val3); if(src && tid != INVALID_TIMER) skill_castend_damage_id(src, bl, sce->val2, sce->val1, gettick(), SD_LEVEL ); } break; case SC_CLOSECONFINE2: { struct block_list *src = sce->val2?map_id2bl(sce->val2):NULL; struct status_change *sc2 = src?status_get_sc(src):NULL; if (src && sc2 && sc2->data[SC_CLOSECONFINE]) { //If status was already ended, do nothing. //Decrease count if (--(sc2->data[SC_CLOSECONFINE]->val1) <= 0) //No more holds, free him up. status_change_end(src, SC_CLOSECONFINE, INVALID_TIMER); } } case SC_CLOSECONFINE: if (sce->val2 > 0) { //Caster has been unlocked... nearby chars need to be unlocked. int range = 1 +skill_get_range2(bl, status_sc2skill(type), sce->val1) +skill_get_range2(bl, TF_BACKSLIDING, 1); //Since most people use this to escape the hold.... map_foreachinarea(status_change_timer_sub, bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,BL_CHAR,bl,sce,type,gettick()); } break; case SC_COMBO: if( sd ) switch (sce->val1) { case MO_COMBOFINISH: case CH_TIGERFIST: case CH_CHAINCRUSH: clif_skillinfo(sd, MO_EXTREMITYFIST, 0); break; case TK_JUMPKICK: clif_skillinfo(sd, TK_JUMPKICK, 0); break; } break; case SC_MARIONETTE: case SC_MARIONETTE2: /// Marionette target if (sce->val1) { // check for partner and end their marionette status as well enum sc_type type2 = (type == SC_MARIONETTE) ? SC_MARIONETTE2 : SC_MARIONETTE; struct block_list *pbl = map_id2bl(sce->val1); struct status_change* sc2 = pbl?status_get_sc(pbl):NULL; if (sc2 && sc2->data[type2]) { sc2->data[type2]->val1 = 0; status_change_end(pbl, type2, INVALID_TIMER); } } break; case SC_BERSERK: //If val2 is removed, no HP penalty (dispelled?) [Skotlex] if(status->hp > 100 && sce->val2) status_set_hp(bl, 100, 0); if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2) { sc->data[SC_ENDURE]->val4 = 0; status_change_end(bl, SC_ENDURE, INVALID_TIMER); } sc_start4(bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill_get_time(LK_BERSERK, sce->val1)); break; case SC_GOSPEL: if (sce->val3) { //Clear the group. struct skill_unit_group* group = skill_id2group(sce->val3); sce->val3 = 0; skill_delunitgroup(group); } break; case SC_HERMODE: if(sce->val3 == BCT_SELF) skill_clear_unitgroup(bl); break; case SC_BASILICA: //Clear the skill area. [Skotlex] skill_clear_unitgroup(bl); break; case SC_TRICKDEAD: if (vd) vd->dead_sit = 0; break; case SC_WARM: if (sce->val4) { //Clear the group. struct skill_unit_group* group = skill_id2group(sce->val4); sce->val4 = 0; skill_delunitgroup(group); } break; case SC_KAAHI: //Delete timer if it exists. if (sce->val4 != INVALID_TIMER) delete_timer(sce->val4,kaahi_heal_timer); break; case SC_JAILED: if(tid == INVALID_TIMER) break; //natural expiration. if(sd && sd->mapindex == sce->val2) pc_setpos(sd,(unsigned short)sce->val3,sce->val4&0xFFFF, sce->val4>>16, CLR_TELEPORT); break; //guess hes not in jail :P case SC_CHANGE: if (tid == INVALID_TIMER) break; // "lose almost all their HP and SP" on natural expiration. status_set_hp(bl, 10, 0); status_set_sp(bl, 10, 0); break; case SC_AUTOTRADE: if (tid == INVALID_TIMER) break; // Note: vending/buying is closed by unit_remove_map, no // need to do it here. map_quit(sd); // Because map_quit calls status_change_end with tid -1 // from here it's not neccesary to continue return 1; break; case SC_STOP: if( sce->val2 ) { struct block_list* tbl = map_id2bl(sce->val2); sce->val2 = 0; if( tbl && (sc = status_get_sc(tbl)) && sc->data[SC_STOP] && sc->data[SC_STOP]->val2 == bl->id ) status_change_end(tbl, SC_STOP, INVALID_TIMER); } break; } opt_flag = 1; switch(type){ case SC_STONE: case SC_FREEZE: case SC_STUN: case SC_SLEEP: sc->opt1 = 0; break; case SC_POISON: case SC_CURSE: case SC_SILENCE: case SC_BLIND: sc->opt2 &= ~(1<<(type-SC_POISON)); break; case SC_DPOISON: sc->opt2 &= ~OPT2_DPOISON; break; case SC_SIGNUMCRUCIS: sc->opt2 &= ~OPT2_SIGNUMCRUCIS; break; case SC_HIDING: sc->option &= ~OPTION_HIDE; opt_flag|= 2|4; //Check for warp trigger + AoE trigger break; case SC_CLOAKING: sc->option &= ~OPTION_CLOAK; opt_flag|= 2; break; case SC_CHASEWALK: sc->option &= ~(OPTION_CHASEWALK|OPTION_CLOAK); opt_flag|= 2; break; case SC_SIGHT: sc->option &= ~OPTION_SIGHT; break; case SC_WEDDING: sc->option &= ~OPTION_WEDDING; break; case SC_XMAS: sc->option &= ~OPTION_XMAS; break; case SC_SUMMER: sc->option &= ~OPTION_SUMMER; break; case SC_ORCISH: sc->option &= ~OPTION_ORCISH; break; case SC_RUWACH: sc->option &= ~OPTION_RUWACH; break; case SC_FUSION: sc->option &= ~OPTION_FLYING; break; //opt3 case SC_TWOHANDQUICKEN: case SC_ONEHAND: case SC_SPEARQUICKEN: case SC_CONCENTRATION: case SC_MERC_QUICKEN: sc->opt3 &= ~OPT3_QUICKEN; opt_flag = 0; break; case SC_OVERTHRUST: case SC_MAXOVERTHRUST: case SC_SWOO: sc->opt3 &= ~OPT3_OVERTHRUST; opt_flag = 0; break; case SC_ENERGYCOAT: case SC_SKE: sc->opt3 &= ~OPT3_ENERGYCOAT; opt_flag = 0; break; case SC_INCATKRATE: //Simulated Explosion spirits effect. if (bl->type != BL_MOB) { opt_flag = 0; break; } case SC_EXPLOSIONSPIRITS: sc->opt3 &= ~OPT3_EXPLOSIONSPIRITS; opt_flag = 0; break; case SC_STEELBODY: case SC_SKA: sc->opt3 &= ~OPT3_STEELBODY; opt_flag = 0; break; case SC_BLADESTOP: sc->opt3 &= ~OPT3_BLADESTOP; opt_flag = 0; break; case SC_AURABLADE: sc->opt3 &= ~OPT3_AURABLADE; opt_flag = 0; break; case SC_BERSERK: sc->opt3 &= ~OPT3_BERSERK; opt_flag = 0; break; // case ???: // doesn't seem to do anything // sc->opt3 &= ~OPT3_LIGHTBLADE; // opt_flag = 0; // break; case SC_DANCING: if ((sce->val1&0xFFFF) == CG_MOONLIT) sc->opt3 &= ~OPT3_MOONLIT; opt_flag = 0; break; case SC_MARIONETTE: case SC_MARIONETTE2: sc->opt3 &= ~OPT3_MARIONETTE; opt_flag = 0; break; case SC_ASSUMPTIO: sc->opt3 &= ~OPT3_ASSUMPTIO; opt_flag = 0; break; case SC_WARM: //SG skills [Komurka] sc->opt3 &= ~OPT3_WARM; opt_flag = 0; break; case SC_KAITE: sc->opt3 &= ~OPT3_KAITE; opt_flag = 0; break; case SC_BUNSINJYUTSU: sc->opt3 &= ~OPT3_BUNSIN; opt_flag = 0; break; case SC_SPIRIT: sc->opt3 &= ~OPT3_SOULLINK; opt_flag = 0; break; case SC_CHANGEUNDEAD: sc->opt3 &= ~OPT3_UNDEAD; opt_flag = 0; break; // case ???: // from DA_CONTRACT (looks like biolab mobs aura) // sc->opt3 &= ~OPT3_CONTRACT; // opt_flag = 0; // break; default: opt_flag = 0; } if (calc_flag&SCB_DYE) { //Restore DYE color if (vd && !vd->cloth_color && sce->val4) clif_changelook(bl,LOOK_CLOTHES_COLOR,sce->val4); calc_flag&=~SCB_DYE; } //On Aegis, when turning off a status change, first goes the sc packet, then the option packet. if( vd && (pcdb_checkid(vd->class_) || bl->type == BL_MER ) ) clif_status_change(bl,StatusIconChangeTable[type],0,0); else if (sd) clif_status_load(bl,StatusIconChangeTable[type],0); if(opt_flag) clif_changeoption(bl); if (calc_flag) status_calc_bl(bl,calc_flag); if(opt_flag&4) //Out of hiding, invoke on place. skill_unit_move(bl,gettick(),1); if(opt_flag&2 && sd && map_getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) npc_touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event. ers_free(sc_data_ers, sce); return 1; } int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { struct block_list *bl; struct status_change *sc; struct status_change_entry *sce; struct status_data *status; int hp; if(!((bl=map_id2bl(id))&& (sc=status_get_sc(bl)) && (sce = sc->data[SC_KAAHI]))) return 0; if(sce->val4 != tid) { ShowError("kaahi_heal_timer: Timer mismatch: %d != %d\n", tid, sce->val4); sce->val4 = INVALID_TIMER; return 0; } status=status_get_status_data(bl); if(!status_charge(bl, 0, sce->val3)) { sce->val4 = INVALID_TIMER; return 0; } hp = status->max_hp - status->hp; if (hp > sce->val2) hp = sce->val2; if (hp) status_heal(bl, hp, 0, 2); sce->val4 = INVALID_TIMER; return 1; } Спойлер: status_change_clear_buffs Код: int status_change_clear_buffs (struct block_list* bl, int type) { int i; struct status_change *sc= status_get_sc(bl); if (!sc || !sc->count) return 0; if (type&2) //Debuffs for( i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++ ) { status_change_end(bl, (sc_type)i, INVALID_TIMER); } for( i = SC_COMMON_MAX+1; i < SC_MAX; i++ ) { if(!sc->data[i]) continue; switch (i) { //Stuff that cannot be removed case SC_WEIGHT50: case SC_WEIGHT90: case SC_COMBO: case SC_SMA: case SC_DANCING: case SC_GUILDAURA: case SC_SAFETYWALL: case SC_PNEUMA: case SC_NOCHAT: case SC_JAILED: case SC_ANKLE: case SC_BLADESTOP: case SC_CP_WEAPON: case SC_CP_SHIELD: case SC_CP_ARMOR: case SC_CP_HELM: case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD: case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD: case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD: case SC_WATKFOOD: case SC_MATKFOOD: case SC_FOOD_STR_CASH: case SC_FOOD_AGI_CASH: case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH: case SC_FOOD_INT_CASH: case SC_FOOD_LUK_CASH: case SC_EXPBOOST: case SC_JEXPBOOST: case SC_ITEMBOOST: continue; //Debuffs that can be removed. case SC_HALLUCINATION: case SC_QUAGMIRE: case SC_SIGNUMCRUCIS: case SC_DECREASEAGI: case SC_SLOWDOWN: case SC_MINDBREAKER: case SC_WINKCHARM: case SC_STOP: case SC_ORCISH: case SC_STRIPWEAPON: case SC_STRIPSHIELD: case SC_STRIPARMOR: case SC_STRIPHELM: if (!(type&2)) continue; break; //The rest are buffs that can be removed. case SC_BERSERK: if (!(type&1)) continue; sc->data[i]->val2 = 0; break; default: if (!(type&1)) continue; break; } status_change_end(bl, (sc_type)i, INVALID_TIMER); } return 0; }
Таро вызывает (для поломки): Спойлер: case 3 Код: case 3: // 1000 damage, random armor destroyed { int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; status_fix_damage(src, bl, 1000, 0); clif_damage(src,bl,tick,0,0,1000,0,0,0); if( !status_isdead(bl) ) skill_break_equip(bl, where[rand()%5], 10000, BCT_ENEMY); } break; Спойлер: skill_break_equip Код: int skill_break_equip (struct block_list *bl, unsigned short where, int rate, int flag) { const int where_list[4] = {EQP_WEAPON, EQP_ARMOR, EQP_SHIELD, EQP_HELM}; const enum sc_type scatk[4] = {SC_STRIPWEAPON, SC_STRIPARMOR, SC_STRIPSHIELD, SC_STRIPHELM}; const enum sc_type scdef[4] = {SC_CP_WEAPON, SC_CP_ARMOR, SC_CP_SHIELD, SC_CP_HELM}; struct status_change *sc = status_get_sc(bl); int i,j; TBL_PC *sd; sd = BL_CAST(BL_PC, bl); if (sc && !sc->count) sc = NULL; if (sd) { if (sd->unbreakable_equip) where &= ~sd->unbreakable_equip; if (sd->unbreakable) rate -= rate*sd->unbreakable/100; if (where&EQP_WEAPON) { switch (sd->status.weapon) { case W_FIST: //Bare fists should not break :P case W_1HAXE: case W_2HAXE: case W_MACE: // Axes and Maces can't be broken [DracoRPG] case W_2HMACE: case W_STAFF: case W_2HSTAFF: case W_BOOK: //Rods and Books can't be broken [Skotlex] case W_HUUMA: where &= ~EQP_WEAPON; } } } if (flag&BCT_ENEMY) { if (battle_config.equip_skill_break_rate != 100) rate = rate*battle_config.equip_skill_break_rate/100; } else if (flag&(BCT_PARTY|BCT_SELF)) { if (battle_config.equip_self_break_rate != 100) rate = rate*battle_config.equip_self_break_rate/100; } for (i = 0; i < 4; i++) { if (where&where_list[i]) { if (sc && sc->count && sc->data[scdef[i]]) where&=~where_list[i]; else if (rand()%10000 >= rate) where&=~where_list[i]; else if (!sd && !(status_get_mode(bl)&MD_BOSS)) //Cause Strip effect. sc_start(bl,scatk[i],100,0,skill_get_time(status_sc2skill(scatk[i]),1)); } } if (!where) //Nothing to break. return 0; if (sd) { for (i = 0; i < EQI_MAX; i++) { j = sd->equip_index[i]; if (j < 0 || sd->status.inventory[j].attribute == 1 || !sd->inventory_data[j]) continue; flag = 0; switch(i) { case EQI_HEAD_TOP: //Upper Head flag = (where&EQP_HELM); break; case EQI_ARMOR: //Body flag = (where&EQP_ARMOR); break; case EQI_HAND_R: //Left/Right hands case EQI_HAND_L: flag = ( (where&EQP_WEAPON && sd->inventory_data[j]->type == IT_WEAPON) || (where&EQP_SHIELD && sd->inventory_data[j]->type == IT_ARMOR)); break; case EQI_SHOES: flag = (where&EQP_SHOES); break; case EQI_GARMENT: flag = (where&EQP_GARMENT); break; default: continue; } if (flag) { sd->status.inventory[j].attribute = 1; pc_unequipitem(sd, j, 3); } } clif_equiplist(sd); } return where; //Return list of pieces broken. }
как я вижу, то диспел с таро, а он же status_change_clear_buffs вызывает в итоге status_change_end как у обычного диспела. так что заявления про то что с таро летит не диспел - можете сбросить в утиль
Наверное это не ко мне, а к предыдущим ребятам (не читал), но напомню, что по-хорошему, нужно ориентироваться на другие исходники, есть возможность "боем" проверить необходимые Вам кейсы, главное, опишите - найду время, отпишусь о результатах (обычно день-два :D).
отнюдь тогда сразу вызывался бы деспел однако сначала вызывается процедура (которая не магия опятьже и проканает на линкера и на рога с линком) проверяет кучу условий и уже она стартует диспел.. че не так? а на выходе таки да диспел не равно карта таро пристка - таро круче
Опишите кейсы которые нужно проверить "боем", в исходниках далеко не всегда все углядеть если не работать / копаться в них (особенно когда они 1к+ строк и наименования так и пытаются тебя подставить (EQI_*/EQP_*)).
@kop6en @Misconception доброе утро! протестировал первый кейс (на эмуляторе с механикой как здесь), таро по ФП, смотрим. P. S. Сейчас поправлю исходники чтобы вылетала только колесница, тестить будет проще (без ком :D), еще и кастомный клиент - граффити в добавок.
@kop6en @Misconception второй тест, таро по валькосету с ФП (сорри, получился жирнее, но можно сделать некоторые выводы) Ну, вывод первый - щиты под ФП не ломаются, без ФП - на ура. Вывод второй - ломаемые вещи под ФП - ломаются, а которые не ломаются - не ломаются. @kop6en что нужно проверить с диспелом / диспелом от таро?