Перейти к содержанию

Nurkz

Donators
  • Постов

    178
  • Зарегистрирован

  • Посещение

  • Победитель дней

    24

Сообщения, опубликованные Nurkz

  1. Ну во первых в участке кода

    if (mob->lookup_const(mobt, "DamageMotion", &i32) && i32 >= 0) {
    	if (battle_config.monster_damage_delay_rate != 100)
    		md.status.dmotion = i32 * battle_config.monster_damage_delay_rate / 100;
    	else
    		md.status.dmotion = i32;
    }

    нужно добавить проверку, считается ли моб боссом

    if (mob->lookup_const(mobt, "DamageMotion", &i32) && i32 >= 0) {
    	if (!(md.status.mode & MD_BOSS) && battle_config.monster_damage_delay_rate != 100)
    		md.status.dmotion = i32 * battle_config.monster_damage_delay_rate / 100;
    	else
    		md.status.dmotion = i32;
    }

    и далее после участка кода

    // MVP EXP Bonus: MEXP
    if (mob->lookup_const(mobt, "MvpExp", &i32) && i32 >= 0) {
    	// Some new MVP's MEXP multiple by high exp-rate cause overflow. [LuzZza]
    	int64 exp = apply_percentrate64(i32, battle_config.mvp_exp_rate, 100);
    	md.mexp = (unsigned int)cap_value(exp, 0, UINT_MAX);
    }

    добавляем

    if ((md.status.mode & MD_BOSS)) {
    	if (md.mexp == 0 && battle_config.boss_damage_delay_rate != 100)
    		md.status.dmotion = md.status.dmotion * battle_config.boss_damage_delay_rate / 100;
    	else if (md.mexp > 0 && battle_config.mvp_damage_delay_rate != 100)
    		md.status.dmotion = md.status.dmotion * battle_config.mvp_damage_delay_rate / 100;
    	else if (battle_config.monster_damage_delay_rate != 100)
    		md.status.dmotion = md.status.dmotion * battle_config.monster_damage_delay_rate / 100;
    }

     

    • Upvote 2
  2. 3 часа назад, Ultima сказал:

    А можно продемонстрировать, как сделаешь это ты?)
    или получается, что такой напарник никому не нужен.
    ( на самом деле мне просто интересно посмотреть, а ещё больше захапать к себе эту модификацию )

    jUWNynw.png

    • Upvote 4
  3. 1 час назад, gloom_lie сказал:

    Старая сборка еамода (2011-2012г.) со старой механикой идеально подходит для нынешней русско-язычной аудитории и более менее стабильна. При должных навыках, все баги правятся быстро. Как мне известно таковая стояла на тервисте и его предшественниках, жалоб не было. Но проблема здесь в другом, новые версии клиентов скорее всего будут несовместимы с этим эмулятором.

    Вы правы, но очень многое было переписано, можно считать это был своего рода эксклюзив. И всё же, за основу брался старенький еАмод. =) Но были и свои проблемы, недочеты, поэтому мы недавно перешли на Herc.

     

  4.  

    Глянул, в последних ра проверку из clif_parse_loadEndAck засунули в src/map/pc.c функция pc_setpos

    		for( i = 0; i < EQI_MAX; i++ ) {
    			if( sd->equip_index[i] >= 0 )
    				if( pc_isequip(sd,sd->equip_index[i]) )
    					pc_unequipitem(sd,sd->equip_index[i],2);
    		}

     

    Ну и в src/map/map.c функция map_quit

    	for (i = 0; i < EQI_MAX; i++) {
    		if (sd->equip_index[i] >= 0)
    			if (pc_isequip(sd,sd->equip_index[i]))
    				pc_unequipitem(sd,sd->equip_index[i],2);
    	}

     

    В обоих случаях просто заменить на банальное.

    	for (i = 0; i < EQI_MAX; i++) {
    		if (sd->equip_index[i] >= 0) {
    			if ((sd->class_ & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level > 96)
    				continue;
    			if (pc_isequip(sd,sd->equip_index[i]))
    				pc_unequipitem(sd,sd->equip_index[i],2);
    		}
    	}

    Не идеально, но сойдет.

    • Upvote 2
  5. Скрытый текст
    
    ACMD(jumptoseller) {
    	struct map_session_data *pl_sd = NULL;
    	char *mapname = "prontera";
    	
    	nullpo_retr(false, sd);
    	memset(atcmd_player_name, 0, sizeof(atcmd_player_name));
    
    	if (!*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
    		clif->message(fd, "Please enter a player name (usage: @jumptoseller <char name>");
    		return false;
    	}
    
    	if (sd->mapindex != mapindex->name2id(mapname))
    		clif->message(fd, "You are not authorized to warp from your current map.");
    		return false;
    	}
    
    	if (pc_isdead(sd)) {
    		clif->message(fd, "You cannot use this command when dead.");
    		return false;
    	}
    
    	if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) {
    		clif->message(fd, "Character not found.");
    		return false;
    	}
    
    	if (pl_sd->mapindex != mapindex->name2id(mapname))
    		clif->message(fd, "You can't jump to this seller/buyer.");
    		return false;
    	}
    	
    	if (!pl_sd->state.vending && !pl_sd->state.buyingstore)
    		clif->message(fd, "Followed character is not a seller/buyer.");
    		return false;
    	}
    
    	if (pl_sd == sd || (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y)) {
    		clif->message(fd, "You already are at your destination!");
    		return false;
    	}
    
    	pc->setpos(sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT);
    	safesnprintf(atcmd_output, sizeof(atcmd_output), "Jumped to %s (x=%d, y=%d)", pl_sd->status.name, pl_sd->bl.x, pl_sd->bl.y);
    	clif->message(fd, atcmd_output);
    
    	return true;
    }
    
    ACMD_DEF(jumptoseller),

     

     

     

    • Upvote 1
  6. Ничего у них не выгорит, опыта 0, навыков 0, денег.. 0? Короче, не доживет и до открытия, нечего тут обсуждать.

    Никогда не отписывался в подобных темах, но с названия пригорело, сам начинал свой путь с руоффа, помню как это было. ^_^

    • Upvote 1
  7. 5 часов назад, Collapse сказал:
      Показать содержимое

    При компиляции получаю ошибку

    
    error: incompatible type for argument 1 of 'status_calc_misc'
      status_calc_misc(nd->bl, &nd->status, nd->level);


     

    status_calc_misc(&nd->bl, &nd->status, nd->level);

    Извиняюсь =)

    Еще было бы правильно поправить status_get_status_data и status_get_base_status.

    Обновил пост выше.

    • Upvote 1
  8. В rA и Herc уже можно давным давно давать статы нпсам, но если у нас eAthena, ничего страшного, всегда можно стырить =)

    Ну во первых изменим в src/map/script.c функции unitskilluseid и unitskillusepos

    Меняем в функции unitskilluseid:

    	if( bl != NULL )
    		unit_skilluse_id(bl, target_id, skill_id, skill_lv);

    На:

    	if (bl != NULL) {
    		if (bl->type == BL_NPC) {
    			if (!((TBL_NPC*)bl)->status.hp)
    				status_calc_npc(((TBL_NPC*)bl), true);
    			else
    				status_calc_npc(((TBL_NPC*)bl), false);
    		}
    		unit_skilluse_id(bl, target_id, skill_id, skill_lv);
        }

    И в unitskillusepos:

    	if( bl != NULL )
    		unit_skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv);

    На:

    	if (bl != NULL) {
    		if (bl->type == BL_NPC) {
    			if (!((TBL_NPC*)bl)->status.hp)
    				status_calc_npc(((TBL_NPC*)bl), true);
    			else
    				status_calc_npc(((TBL_NPC*)bl), false);
    		}
    		unit_skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv);
    	}

     

    Далее добавим функцию добавления статов нпсу =)

    BUILDIN_FUNC(setnpcstats)
    {
    	TBL_NPC* nd = NULL;
    	unsigned int value = 0;
    	
    	if (script_hasdata(st,2))
    		nd = map_id2nd(script_getnum(st,2));
    	else
    		nd = map_id2nd(st->oid);
    	
    	if (nd == NULL)
    		return 0;
    	
    	if (script_hasdata(st,3))
    		value = script_getnum(st,3);
    	
    	if (!nd->status.hp)
    		status_calc_npc(nd, true);
    	else
    		status_calc_npc(nd, false);
    	break;
    	
    	nd->stat_point = value > 0 ? value : 999;
    	status_calc_misc(&nd->bl, &nd->status, nd->level);
    }

    и ниже описываем что она будет принимать: (Всего два необязательных параметра)

    BUILDIN_DEF(setnpcstats,"??"),

     

    Далее идем в src/map/status.c и функцию status_calc_bl_

    в свиче добавляем новый кейс которым будет выглядеть данным образом:

    case BL_NPC: status_calc_npc_(BL_CAST(BL_NPC,bl), first);        break;

    Далее ищем status_get_status_data и добавляем:

    case BL_NPC: return ((mobdb_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : &dummy_status);

    То же самое ниже в status_get_base_status:

    case BL_NPC: return ((mobdb_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : NULL);

    И добавляем функцию status_calc_npc_:

    int status_calc_npc_(struct npc_data *nd, bool first)
    {
    	struct status_data *status = &nd->status;
    
    	if (!nd)
    		return 0;
    
    	if (first) {
    		status->hp = 1;
    		status->sp = 1;
    		status->max_hp = 1;
    		status->max_sp = 1;
    
    		status->def_ele = ELE_NEUTRAL;
    		status->ele_lv = 1;
    		status->race = RC_DEMIHUMAN;
    		status->size = nd->size;
    		status->rhw.range = 1 + status->size;
    		status->mode = (MD_CANMOVE|MD_CANATTACK);
    		status->speed = nd->speed;
    	}
    
    	status->str = nd->stat_point + nd->params.str;
    	status->agi = nd->stat_point + nd->params.agi;
    	status->vit = nd->stat_point + nd->params.vit;
    	status->int_= nd->stat_point + nd->params.int_;
    	status->dex = nd->stat_point + nd->params.dex;
    	status->luk = nd->stat_point + nd->params.luk;
    
    	status_calc_misc(&nd->bl, status, nd->level);
    	status_cpy(&nd->status, status);
    
    	return 0;
    }

    Далее заходим в src/map/status.h

    В самом верху песле строчки:

    struct mercenary_data;

    Добавляем:

    struct npc_data;

    Листаем в самый низ и находим:

    #define status_calc_mercenary(md, first) status_calc_bl_(&(md)->bl, SCB_ALL, first)

    Добавляем следующей строчкой:

    #define status_calc_npc(nd, first) status_calc_bl_(&(nd)->bl, SCB_ALL, first)

    Ниже видим:

    int status_calc_mercenary_(struct mercenary_data *md, bool first);

    Добавляем:

    int status_calc_npc_(struct npc_data *nd, bool first);

    Далее идём в src/map/npc.h и видим строчку:

    unsigned size : 2;

    Ниже добавляем:

    struct status_data status;
    unsigned int level,stat_point;
    struct s_npc_params {
    	unsigned short str, agi, vit, int_, dex, luk;
    } params;

    Вот вроде и всё, рекомпилим и пишем в скрипте:

    getmapxy .@map$, .@x, .@y, 1;
    setnpcstats getnpcid(0), 999;
    unitskillusepos getnpcid(0), WZ_METEOR, 10, .@x, .@y;

     

    ПС! Хотя я бы всё же рекомендовал перейти на rA/Herc и использовать setunitdata.

    Может кому нужно будет, пусть будет.

    • Upvote 1
  9. 1 час назад, Gandalf сказал:

    Вряд ли как - то можно убить мобов скиллом нпца, у нпца нет статов и вообще ничего, даже команды на использование скилла в eAthena, насколько я помню.
    Можно запустить эффект и юзнуть killmonsterall какой-нибудь.

    А почему бы не дать нпцу статов?)

×
×
  • Создать...
Яндекс.Метрика