таро

Тема в разделе "Ошибки", создана пользователем kop6en, 1 мар 2018.

  1. ФАРАЙ

    ФАРАЙ Игрок

    На форуме с:
    5 окт 2017
    Сообщения:
    1,631
    Адрес:
    Москва
    нитка не магия
    валя шмот не должен ломаться ни как
    хватит гореть с гтб
  2. Misconception

    Misconception Игрок

    На форуме с:
    14 окт 2017
    Сообщения:
    1,329
    то же самое что и при использовании госпела и род хермонда (простите за это слово, но оно шикарно)
  3. f0und3r

    f0und3r Игрок

    На форуме с:
    21 янв 2012
    Сообщения:
    933
    В чистом эмуляторе 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
    
    Но если честно, я потерялся в том, что Вам нужно уточнить, могу проверить / приложить исходники почему это так (эмулятор на котором будет проведено тестирования по механике совпадает с фриро).

    Листинги функций выше актуальны?
    Могу приложить файлы (ссылки) или вырезки из них.
  4. Misconception

    Misconception Игрок

    На форуме с:
    14 окт 2017
    Сообщения:
    1,329
    думаю и так норм

    должно ли ломать карта таро колесница предметы под протектом
    + должно ли ломать карто таро колесница предметы на которых указано свойство - неломаемый
  5. Red King

    Red King Read Only

    На форуме с:
    14 авг 2015
    Сообщения:
    3,030
    А можно узнать как-то как таро работает, скажем, на kro, ну или хотя бы на iro?
  6. kop6en

    kop6en Read Only

    На форуме с:
    10 янв 2010
    Сообщения:
    2,059
    Адрес:
    Якудза Питер
    я не эти функции запрашивал :)
  7. f0und3r

    f0und3r Игрок

    На форуме с:
    21 янв 2012
    Сообщения:
    933
    Беглый осмотр ниже без проверки "боем", если есть сомнения - завтра проверю, сейчас с ноута просто для информации.

    Если речь идет про 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 (без мода, который здесь есть):
    Код:
    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;
    }
    

    Код:
    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;
    }
    
    kop6en нравится это.
  8. kop6en

    kop6en Read Only

    На форуме с:
    10 янв 2010
    Сообщения:
    2,059
    Адрес:
    Якудза Питер
    а что вызывает у нас таро?
  9. f0und3r

    f0und3r Игрок

    На форуме с:
    21 янв 2012
    Сообщения:
    933
    Поправил код (верстка похерилась), обновите страничку
  10. f0und3r

    f0und3r Игрок

    На форуме с:
    21 янв 2012
    Сообщения:
    933
    Таро вызывает (для поломки):
    Код:
    				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;
    

    Код:
    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.
    }
    
  11. kop6en

    kop6en Read Only

    На форуме с:
    10 янв 2010
    Сообщения:
    2,059
    Адрес:
    Якудза Питер
    как я вижу, то диспел с таро, а он же
    status_change_clear_buffs вызывает в итоге status_change_end как у обычного диспела.

    так что заявления про то что с таро летит не диспел - можете сбросить в утиль
  12. f0und3r

    f0und3r Игрок

    На форуме с:
    21 янв 2012
    Сообщения:
    933
    Наверное это не ко мне, а к предыдущим ребятам (не читал), но напомню, что по-хорошему, нужно ориентироваться на другие исходники, есть возможность "боем" проверить необходимые Вам кейсы, главное, опишите - найду время, отпишусь о результатах (обычно день-два :D).
    kop6en нравится это.
  13. kop6en

    kop6en Read Only

    На форуме с:
    10 янв 2010
    Сообщения:
    2,059
    Адрес:
    Якудза Питер
    икс, иди уже сюда.
    не будь тепличным
  14. Misconception

    Misconception Игрок

    На форуме с:
    14 окт 2017
    Сообщения:
    1,329
    отнюдь
    тогда сразу вызывался бы деспел
    однако сначала вызывается процедура (которая не магия опятьже и проканает на линкера и на рога с линком) проверяет кучу условий и уже она стартует диспел.. че не так?
    а на выходе таки да диспел не равно карта таро пристка - таро круче
  15. kop6en

    kop6en Read Only

    На форуме с:
    10 янв 2010
    Сообщения:
    2,059
    Адрес:
    Якудза Питер
    я уже выше расписывал основное условие разницы это:
    что в диспеле есть строчка проверки на иммун
  16. f0und3r

    f0und3r Игрок

    На форуме с:
    21 янв 2012
    Сообщения:
    933
    Опишите кейсы которые нужно проверить "боем", в исходниках далеко не всегда все углядеть если не работать / копаться в них (особенно когда они 1к+ строк и наименования так и пытаются тебя подставить (EQI_*/EQP_*)).
  17. Misconception

    Misconception Игрок

    На форуме с:
    14 окт 2017
    Сообщения:
    1,329
    диспелл+
    новая формула
    ЕЩЁ еффективнее
    NEW
    ТЕПЕРЬ игнорит ГТБ !!
  18. kop6en

    kop6en Read Only

    На форуме с:
    10 янв 2010
    Сообщения:
    2,059
    Адрес:
    Якудза Питер
    так и смотрят два лица, окаянные.
    Мяурицо и f0und3r нравится это.
  19. f0und3r

    f0und3r Игрок

    На форуме с:
    21 янв 2012
    Сообщения:
    933
    @kop6en @Misconception доброе утро!
    протестировал первый кейс (на эмуляторе с механикой как здесь), таро по ФП, смотрим.

    P. S. Сейчас поправлю исходники чтобы вылетала только колесница, тестить будет проще (без ком :D), еще и кастомный клиент - граффити в добавок.
  20. f0und3r

    f0und3r Игрок

    На форуме с:
    21 янв 2012
    Сообщения:
    933
    @kop6en @Misconception второй тест, таро по валькосету с ФП (сорри, получился жирнее, но можно сделать некоторые выводы)

    Ну, вывод первый - щиты под ФП не ломаются, без ФП - на ура.
    Вывод второй - ломаемые вещи под ФП - ломаются, а которые не ломаются - не ломаются.

    @kop6en что нужно проверить с диспелом / диспелом от таро?