• Уважаемые гости и новички, приветствуем Вас на нашем форуме
    Здесь вы можете найти ответы практически на все свои вопросы о серии игр «Готика» (в том числе различных модах на нее), «Ведьмак», «Ризен», «Древние свитки», «Эра дракона» и о многих других играх. Можете также узнать свежие новости о разработке новых проектов, восхититься творчеством наших форумчан, либо самим показать, что вы умеете. Ну и наконец, можете обсудить общие увлечения или просто весело пообщаться с посетителями «Таверны».

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!

Вопросы по скриптингу

MaGoth

★★★★★★★★★★★
Администратор
Регистрация
7 Янв 2003
Сообщения
19.367
Благодарности
7.815
Баллы
995
  • Первое сообщение
  • #1
Прежде чем задавать вопросы, ознакомьтесь с документацией..
1) Читать онлайн
2) Архив с офлайн-версией(chm) во вложении
 

Вложения

  • Vam_tutor.rar
    171,6 KB · Просмотры: 573
Последнее редактирование модератором:

redleha


Модостроитель
Регистрация
26 Фев 2008
Сообщения
735
Благодарности
665
Баллы
245
Вопрос такой:
вот цитата из тутора Вама:
"int Wld_DetectNpc (c_npc self, int instance, func aiState, int guild); - эта функция инициализирует глобальную переменную скриптов other, отличную от НПС self, где instance – производная от класса c_npc, которая должна быть найдена и проинициализирована (-1 – любая производная), guild – гильдия, членом которой должен быть искомый НПС (-1 – любая гильдия), aiState – функция AI состояния, в котором должен находится искомый НПС (NOFUNC – любое AI состояние). Функция возвращает 1 в случае успешного завершения (other инициализирован найденным НПС), 0 – неудача (other не определен)."
Есть такая ситуация: НПС-маг и два одинаковых монстра около него.
Можно ли неким образом инициализировать обоих этих монстров и произвести с ними обоими какое-то действие за один заход. Оба монстра - одинаковые, находятся в одном и том же состоянии.
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Можно, если ты им обьявишь, в скриптах, разные имена, отличные от оригинала.
Например "Кусач" из аддона.
Это оригинал
instance OrcBiter(Mst_Default_OrcBiter)
{
Set_OrcBiter_Visuals();
Npc_SetToFistMode(self);
CreateInvItems(self,ItFoMuttonRaw,2);
};
Что нужно тебе
instance OrcBiter_Mag1(Mst_Default_OrcBiter)
{
Set_OrcBiter_Visuals();
Npc_SetToFistMode(self);
CreateInvItems(self,ItFoMuttonRaw,2);
};
и
instance OrcBiter_Mag2(Mst_Default_OrcBiter)
{
Set_OrcBiter_Visuals();
Npc_SetToFistMode(self);
CreateInvItems(self,ItFoMuttonRaw,2);
};
И вот этим двум и делай то что тебе надо.
 

redleha


Модостроитель
Регистрация
26 Фев 2008
Сообщения
735
Благодарности
665
Баллы
245
2MEG@VOLT:
Так то это понятно, меня именно моя ситуация интересовала.
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Блин, а я про что говорю???
Перечитай наши с тобой последние посты ВНИМАТЕЛЬНО!
Как я тебя понимаю Маг говорит ФАС - они оба должны ломиться, так?
Дык вот и создай функцию, когда твой маг говорит Фас - переадресация на функцию - в самой функции:
if(Wld_DetectNpc(self, (твой монстр1), func aiState, int guild) && Wld_DetectNpc(self, (твой монстр2), func aiState, int guild))
{
return true;
(тут все что тебе заблогароссудится)
};
return false;
 

redleha


Модостроитель
Регистрация
26 Фев 2008
Сообщения
735
Благодарности
665
Баллы
245
2MEG@VOLT:
Не горячись, пжалста!
Видимо, я не до конца правильно выразился.
Да, ты прав есть маг. А рядом с ним представь 100 неписей - одинаковых инстанций от одного прототипа, имеющих одно и тоже instanceName.
То есть когда маг инициализирует одного монстра, как ему инициализировать сразу после этого второго монстра. Второй и первый монстр имеют одно и тоже состояние, instanceName и гильдию.
Да, не заморачиваясь, можно просто всем монстрюгам дать уникальное имя и всё. Либо производить действия над мострами через ихнюю инициализацию этого мага.
Просто хотелось узнать возможность функции Wld_DetectNpc, ведь она инициализирует глобальную переменную other c первым попавшим НПС, подходящего по описанию,указанному в скобках функции.
МНЕ просто это интересно. Обходных путей много, но вопрос именно задан таким образом.
Заранее спасибо! Надеюсь теперь я правильно выразился. ;)
 

Финкрег

Участник форума
Регистрация
16 Май 2007
Сообщения
69
Благодарности
0
Баллы
155
Я решил сделать себе зелье типа Эмбарла Фиргасто.
И не знаю в какой строке писать на сколько я хочу увеличить атрибуты.
Пожалуйста, напишите, кто знает, в какой.

Вот пример:
Код:
instance ItPo_Perm_Mana(C_Item)
{
	name = NAME_Trank;
	mainflag = ITEM_KAT_POTIONS;
	flags = ITEM_MULTI;
	value = Value_ManaMaxElixier;
	visual = "ItPo_Perm_Mana.3ds";
	material = MAT_GLAS;
	on_state[0] = UseItPo_Perm_Mana;
	scemeName = "POTIONFAST";
	wear = WEAR_EFFECT;
	effect = "SPELLFX_MANAPOTION";
	description = "Эликсир духа";
	text[1] = NAME_Bonus_ManaMax;
	count[1] = ManaMax_Elixier;
	text[5] = NAME_Value;
	count[5] = Value_ManaMaxElixier;
};


func void UseItPo_Perm_Mana()
{
	B_RaiseAttribute(self,ATR_MANA_MAX,ManaMax_Elixier);
	Npc_ChangeAttribute(self,ATR_MANA,ManaMax_Elixier);
};
 

marazmus

★★★★★★★★★★★
Основатель
Регистрация
7 Янв 2003
Сообщения
2.117
Благодарности
914
Баллы
385
Код:
B_RaiseAttribute(self,ATR_MANA_MAX,ManaMax_Elixier);

Подставь вместо ManaMax_Elixie свое число.
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
2redleha: Возможностей у этой данной не так уж и много.
Данная Wld_DetectNpc инициализирует непися, по описанию в ней, ближайшего... Только и всего
Еще один из вариантов обхода, если не хочешь задавать каждому монстру уникальное имя:
Так же банально:
Маг говорит ФАС, один монстр ломится, тут же срабатывает функция, и начинает ломиться уже ближайший монстр, т.е. второй, когда первый уже убежал... Что-то типа того...
 

Финкрег

Участник форума
Регистрация
16 Май 2007
Сообщения
69
Благодарности
0
Баллы
155
Я решил привязать к напитку временный эффект, как у зелья ускорения. Однако трбалы.
Код:
instance ItPo_Mana(C_Item)
{
	name = NAME_Trank;
	mainflag = ITEM_KAT_POTIONS;
	flags = ITEM_MULTI;
	value = Value_Mana;
	visual = "ItPo_Speed.3ds";
	material = MAT_GLAS;
	on_state[0] = UseItPo_Mana;
	scemeName = "POTIONFAST";
	wear = WEAR_EFFECT;
	effect = "SPELLFX_ITEMGLIMMER";
	description = "Зелье";
	text[1] = "Временно повышает ману.";
	text[3] = NAME_Duration;
	count[3] = Time_Mana / 60000;
	text[5] = NAME_Value;
	count[5] = value;
};


func void UseItPo_Mana()
{
	Mdl_ApplyOverlayMdsTimed(self,"HUMANS.MDS",Time_Mana);
};

count[3] = Time_Mana / 60000;
-это значит, время.

Прописал также в файле константы
const int Value_Mana = 1000;
const int Time_Mana = 120;

В чем может быть проблема? Может я что-то не так далю? И где надо написать, чтобы в игре появлялось надпись о том, какое время действует.
Заранее спасибо.
 

Myxomop

Почетный форумчанин
Регистрация
28 Май 2005
Сообщения
3.239
Благодарности
2.581
Баллы
455
2Финкрег:
Напиток ускорения работает на основе ускоренной анимации, которой можно задать время.
Мана - это НЕ анимация, это атрибут, который временно задавать таким образом нельзя! Чтобы временно задавать изменяемые атрибуты нужно минимум знать работу с триггерами в спайсере и написать для этого свою циклическую функцию. Как это сделать, объяснять не буду, т.к. ты все равно не сделаешь, ибо задаешь слишком много простых вопросов, в которых можно разобарться самому и вообще превратил форум в чат.
 

alex_draven


Модостроитель
Регистрация
13 Сен 2007
Сообщения
2.183
Благодарности
2.880
Баллы
420
Хм, а вот это может быть полезно... Стоит задача отработки циклической функции вне зависимости от того, в какой точке игрового мира гаходится ГГ. Функция, естественно, будет как-то влиять на героя. Подумывал, что могут сгодится триггеры (жуки-шпиЁны не подошли). Если не трудно, всё же был бы очень благодарен за краткое разъяснение, каким образом такую функцию можно повесить на триггер и будет ли это вообще работать. Функцию напишем, а вот по триггерам есть чему ещё поучиться: какого типа брать, какие параметры в первую очередь настроить.
 

redleha


Модостроитель
Регистрация
26 Фев 2008
Сообщения
735
Благодарности
665
Баллы
245
2alex_draven:
Одно могу сказать. Таким образом было реализовано отравление в моде Jaktil.
Там в Startup'е пускался триггер(ссылается на текстовый скрипт) в мир - обработка состояния любого непися на предмет заражения. А в конце этого скрипта опять вызывается этот триггер, ссылающийся на этот скрипт. Получается циклический триггер такой, обрабатывающийся постоянно системой.
 

Myxomop

Почетный форумчанин
Регистрация
28 Май 2005
Сообщения
3.239
Благодарности
2.581
Баллы
455
redleha написал(а):
2alex_draven:
Одно могу сказать. Таким образом было реализовано отравление в моде Jaktil.
Совершенно верно! Именно об этом я и говорил и на основе этого мода делал свои циклические функции. Сейчас на работе, сегодня вечером, если не забухаю смогу описать более подробно и с иллюстрациями.
 
Последнее редактирование модератором:

Myxomop

Почетный форумчанин
Регистрация
28 Май 2005
Сообщения
3.239
Благодарности
2.581
Баллы
455
Ну вообщем вот пример:

Создание скриптового триггера в Spacer

Триггер можно разместить в ЛЮБОМ месте мира, хоть в небе, хоть под землей.

На данном скриншоте основные параметры обведены рамкой, но в любом случае и остальные параметры лучше сделать также.


vobName: GLOBAL_INIT //Должен в точности соответствовать вызываемому триггеру из скриптовой функции описанной ниже.

ActivationFilter: Поставить все значения в TRUE, иначе не будет работать, все остальные параметры в рамке тоже по скрину.

FireBehavior:
fireDelaySec:0.1 //Время ответа триггера для вызова скриптовой функции, т.е. время цикла, в данный момент 1/10 секунды.
sendUntrigger:TRUE

scriptFunc:B_GlobalInit //Собственно, сама вызываемая зацикленная функция, может быть только типа void


func void B_GlobalInit()
{
if(hero.attribute[ATR_HITPOINTS_MAX] == 0) //Проверка, является ли ГГ живым, иначе сразу вызов триггера без продолжения выполнения функции.
{
Wld_SendTrigger("GLOBAL_INIT"); //Вызов триггера для зацикливания всей функции. Call trigger for cycle all function.
return; //Выход из функции. Exit from function
};

//Дальше идут множество своих функций...

MyFunction1();
MyFunction2();
MyFunction3();

Wld_SendTrigger("GLOBAL_INIT"); //Вызов триггера c именем GLOBAL_INIT для зацикливания всей функции. Call trigger with name GLOBAL_INIT for cycle all function.
};

-----------------------------------

startup.d

func void init_world() //функция инициализации мира, срабатывает при каждой загрузке мира, в том числе из сохранения игры, где world является именем WORLD.ZEN.
{
B_GlobalInit(); //вызов описанной ранее скриптовой функции при инициализации мира.
};

-----------------------------------
P.S. С помошью этой циклической связки, в моде StrongHand сделаны такие фишки, как например регулирование выносливости во время боя и бега, прицеливание, восстановление атрибутов, отображение индикаторов, сохранение и изменение внешнего вида ГГ и многое другое.
 
Последнее редактирование модератором:

redleha


Модостроитель
Регистрация
26 Фев 2008
Сообщения
735
Благодарности
665
Баллы
245
Вот тут подумал, и придумал переделать функцию. Вещь маленькая, но очень приятная.
Все знают функцию B_GiveInvItems(var C_Npc giver,var C_Npc taker,var int itemInstance,var int amount)
func int B_GiveInvItems(var C_Npc giver,var C_Npc taker,var int itemInstance,var int amount)
{
var string concatText;
var string itemname;
if(Npc_IsPlayer(giver))
{
if(amount >Npc_HasItems(giver,itemInstance))
{
return FALSE;
};
};
if(amount == 0)
{
return TRUE;
};
Npc_RemoveInvItems(giver,itemInstance,amount);
CreateInvItems(taker,itemInstance,amount);
itemname = item.name;
if(Npc_IsPlayer(giver))
{
if(itemInstance == ItMi_Gold)
{
concatText = ConcatStrings(IntToString(amount),PRINT_GoldGegeben);
AI_PrintScreen(concatText,-1,YPOS_GoldGiven,FONT_ScreenSmall,2);
}
else if(amount == 1)
{
concatText = ConcatStrings(itemname,PRINT_Addon_gegeben);
AI_PrintScreen(concatText,-1,YPOS_ItemGiven,FONT_ScreenSmall,2);
}
else
{
concatText = ConcatStrings(IntToString(amount),PRINT_ItemsGegeben);
concatText = ConcatStrings(concatText,"(");
concatText = ConcatStrings(concatText,itemname);
concatText = ConcatStrings(concatText,")");
AI_PrintScreen(concatText,-1,YPOS_ItemGiven,FONT_ScreenSmall,2);
};
}
else if(Npc_IsPlayer(taker))
{
if(itemInstance == ItMi_Gold)
{
concatText = ConcatStrings(IntToString(amount),PRINT_GoldErhalten);
AI_PrintScreen(concatText,-1,YPOS_GoldTaken,FONT_ScreenSmall,2);
}
else if(amount == 1)
{
concatText = ConcatStrings(itemname,PRINT_Addon_erhalten);
AI_PrintScreen(concatText,-1,YPOS_ItemTaken,FONT_ScreenSmall,2);
}
else
{
concatText = ConcatStrings(IntToString(amount),PRINT_ItemsErhalten);
concatText = ConcatStrings(concatText,"(");
concatText = ConcatStrings(concatText,itemname);
concatText = ConcatStrings(concatText,")");
AI_PrintScreen(concatText,-1,YPOS_ItemTaken,FONT_ScreenSmall,2);
};
};
return TRUE;
};
Так вот придуал внести в эту функцию аргумент:
B_GiveInvItems(var C_Npc giver,var C_Npc taker,var int itemInstance,var int amount, var int screenpercent)
Здесь screenpercent - это аргумент, который будет задействован в функции отбражения текста на экране: AI_PrintScreen внутри тела функции B_GiveInvItems.
К чему я веду: к тому, что если в теле диалога приходится передать несколько предметов, то происходит накладка текста. А таким образом мы можем вставлять функцию с аргументом, отвечающим за расположение надписи на экране.
----------------------------------------------
P.S. Может кому-то окажется полезным...  ;)
 
Последнее редактирование модератором:

Myxomop

Почетный форумчанин
Регистрация
28 Май 2005
Сообщения
3.239
Благодарности
2.581
Баллы
455
2redleha:
А результаты изменения функции где? Это не тема для предложений. Тут задаются вопросы и даются на них ответы.
 

redleha


Модостроитель
Регистрация
26 Фев 2008
Сообщения
735
Благодарности
665
Баллы
245
2ukur:
извиняюсь, исправляюсь. Просто хотел оказать мелкую помощь.
func int B_GiveInvItems_New(var C_Npc giver,var C_Npc taker,var C_ITEM itm,var int amount, var int screenprocent)
{
var string concatText;
var string itemname;
var int itemInstance;
itemInstance = Hlp_GetInstanceID(itm);
if(Npc_IsPlayer(giver))
{
if(amount >Npc_HasItems(giver,itemInstance))
{
return FALSE;
};
};
if(amount == 0)
{
return TRUE;
};
Npc_RemoveInvItems(giver,itemInstance,amount);
CreateInvItems(taker,itemInstance,amount);
itemname = item.name;
if(Npc_IsPlayer(giver))
{
if(Hlp_IsItem(itm,itmi_gold))
{
concatText = ConcatStrings(IntToString(amount),PRINT_GoldGegeben);
AI_PrintScreen(concatText,-1,YPOS_GoldGiven,FONT_ScreenSmall,2);
}
else if(amount == 1)
{
concatText = ConcatStrings(itemname,PRINT_Addon_gegeben);
AI_PrintScreen(concatText,-1,screenprocent,FONT_ScreenSmall,2);
}
else
{
concatText = ConcatStrings(IntToString(amount),PRINT_ItemsGegeben);
concatText = ConcatStrings(concatText,"(");
concatText = ConcatStrings(concatText,itemname);
concatText = ConcatStrings(concatText,")");
AI_PrintScreen(concatText,-1,screenprocent,FONT_ScreenSmall,2);
};
}
else if(Npc_IsPlayer(taker))
{
if(Hlp_IsItem(itm,itmi_gold))
{
concatText = ConcatStrings(IntToString(amount),PRINT_GoldErhalten);
AI_PrintScreen(concatText,-1,YPOS_GoldTaken,FONT_ScreenSmall,2);
}
else if(amount == 1)
{
concatText = ConcatStrings(itemname,PRINT_Addon_erhalten);
AI_PrintScreen(concatText,-1,screenprocent,FONT_ScreenSmall,2);
}
else
{
concatText = ConcatStrings(IntToString(amount),PRINT_ItemsErhalten);
concatText = ConcatStrings(concatText,"(");
concatText = ConcatStrings(concatText,itemname);
concatText = ConcatStrings(concatText,")");
AI_PrintScreen(concatText,-1,screenprocent,FONT_ScreenSmall,2);
};
};
return TRUE;
};
Ну, и пример:
B_GiveInvItems_New(other,self,ItMi_DarkPearl,1,34);
B_GiveInvItems_New(other,self,ItMi_Aquamarine,3,36);
B_GiveInvItems_New(other,self,ItMi_Nugget,5,38);
 
Последнее редактирование модератором:

s@m


Модостроитель
Регистрация
2 Мар 2007
Сообщения
315
Благодарности
56
Баллы
195
Но там же проверка тока на голд, а ты написал B_GiveInvItems_New(other,self,ItMi_DarkPearl,1,34);

Лучще было бы, еслиб это число(B_GiveInvItems_New(other,self,ItMi_DarkPearl,1,34);) расчитывалось бы автоматом. А то функция всё равно наполовину ручная ещё.
 

vmazz

Участник форума
Регистрация
18 Дек 2008
Сообщения
218
Благодарности
1
Баллы
165
2ukur: Не знаю, толи я косой, толи Г1 невоспринимает такое зацикливание, уже пробывал повсякому - не получается. По идеи требуется зацикливание для постоянного выполнения функции
 
Сверху Снизу