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

НПЦ скрипт


E r a

Рекомендуемые сообщения

Здравствуйте, сделала нпц и фантазия заставила нпцеху запускать скилы. Мне нужно что бы в определенный момент нпц запустило метеор и убило вокруг меня всех мобов. Подскажите пожалуйста можно ли как то это воплотить в жизнь на eathena. 

Изменено пользователем E r a
Ссылка на комментарий
Поделиться на другие сайты

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

Изменено пользователем Gandalf
Ссылка на комментарий
Поделиться на другие сайты

Ну я об этом и сказал, что надо настроить время использования команды килмонстералл и добавить еффект метеора в этот момент)

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, Gandalf сказал:

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

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

Ссылка на комментарий
Поделиться на другие сайты

да но)  killmonsterall  убивает без эффекта, моб просто исчезает, наверно можно добавить эффект при убийстве?. Можно сделать НПЦ через unitskilluseid, unitskillusepos, оно кастует и убивает но присутствует задержка. 

Изменено пользователем E r a
Ссылка на комментарий
Поделиться на другие сайты

5 часов назад, Nurkz сказал:

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

Вряд ли человек, который спрашивает как сделать эффекты с убийством, сделает статы нпцу )

Ссылка на комментарий
Поделиться на другие сайты

19 минуту назад, Gandalf сказал:

Вряд ли человек, который спрашивает как сделать эффекты с убийством, сделает статы нпцу )

а все же, как?

Ссылка на комментарий
Поделиться на другие сайты

Не знаю, мб придется переписать структуру нпцов, чтоб статы учитывались и тп.
А мб можно просто захардкодить переменные, и сделать скрипт команду npcskill какую-то и учитывать их.

Ссылка на комментарий
Поделиться на другие сайты

В 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.

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

Изменено пользователем Nurkz
  • Upvote 1
Ссылка на комментарий
Поделиться на другие сайты

например такой скриптик:

zzzz,x,y,5    script    zzzz    zzz,{
  mes "zzzzzz.";
  delitem zzzz,1;
  getitem zzzz,1;
  npcskilleffect zzzz,10,x,y;

killmonsterall "<map name>"{,<type>};
    sleep 500;
    npcskilleffect zzzz,10,x,y;
    sleep 501;
    npcskilleffect zzzz,10,x,y;
    sleep 502;
    npcskilleffect zzzz,10,x,y;
  close;
}

я всовываю не правильно слип и "close;" уже не работает,(

Изменено пользователем E r a
Ссылка на комментарий
Поделиться на другие сайты

попробуй так

 

 zzzz,x,y,5    script    zzzz    zzz,{
  mes "zzzzzz.";
  delitem zzzz,1;
  getitem zzzz,1;
  npcskilleffect zzzz,10,x,y;
  close2;
killmonsterall "<map name>"{,<type>};
    sleep 500;
    npcskilleffect zzzz,10,x,y;
    sleep 501;
    npcskilleffect zzzz,10,x,y;
    sleep 502;
    npcskilleffect zzzz,10,x,y;
  end;
} 

 

Ссылка на комментарий
Поделиться на другие сайты

Скрытый текст
В 05.12.2016в10:50 PM, Nurkz сказал:

В 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 &((TBL_NPC*)bl)->status;

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



case BL_NPC: return &((TBL_NPC*)bl)->status;

И добавляем функцию 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.

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

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

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


 

Ссылка на комментарий
Поделиться на другие сайты

4 минуты назад, Salfer сказал:

Создай новую тему, раз пишешь по другому вопросу, а вообще по мимо ошибки обычно пишет где именно допущена ошибка.

Вопрос все тот же. Ошибка в куске 
 

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);
}
Ссылка на комментарий
Поделиться на другие сайты

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.

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

Изменено пользователем Nurkz
  • Upvote 1
Ссылка на комментарий
Поделиться на другие сайты

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