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

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

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

MaGoth

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

Вложения

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

maggi1221

Участник форума
Регистрация
7 Окт 2010
Сообщения
218
Благодарности
4
Баллы
165
Кто может объяснить что это такое? (скрин прилагается)
как видно из скрина, у клада функция:

onStateFunc: B_SCGetTreasure_S1

в скриптах нашел эту функцию, вот она (пустая):

func void B_SCGetTreasure_S1()
{
};

еще в скриптах нашел настоящую функцию, которую даже двоичный поиск по ZEN файлу не нашел (именно она и вызывается во время игры):

func void hiddenfind_s1()
{
var C_Npc her;
her = Hlp_GetNpc(PC_Hero);
if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(her))
{
hide_progress_bar_stamina();
self.aivar[AIV_INVINCIBLE] = TRUE;
PLAYER_MOBSI_PRODUCTION = MOBSI_HIDDENFIND;
AI_ProcessInfos(her);
};
};

не пойму в чем тут дело?
 

Вложения

  • wtf.png
    wtf.png
    789,7 KB · Просмотры: 264

Myxomop

Почетный форумчанин
Регистрация
28 Май 2005
Сообщения
3.239
Благодарности
2.581
Баллы
455
maggi1221,
в скриптах нашел эту функцию, вот она (пустая):

func void B_SCGetTreasure_S1()
{
};
В оригинальной Г2-НВ должна быть полная :)
 

maggi1221

Участник форума
Регистрация
7 Окт 2010
Сообщения
218
Благодарности
4
Баллы
165
еще 1 вопрос:

какие условия налагаются на функцию condFunc?

например для функций onStateFunc:

в редакторе: name, в скриптах: name_s1

каков суффикс у функций condFunc?
перепробовал _s1, _c1 и просто так, не работает...

вот код:

func int condChest01_c1()
{
print("condChest01");
return 1;
};
 

Saturas


Модостроитель
Регистрация
11 Фев 2009
Сообщения
2.512
Благодарности
1.334
Баллы
315
Глянул в г1, суфикса там недолжно быть, по пробуй без суфикса, и еще функция обязательно должна быть типа int.
 

maggi1221

Участник форума
Регистрация
7 Окт 2010
Сообщения
218
Благодарности
4
Баллы
165
Не получается....
может это связано с тем, что использую conditionFunc на сундуке? (класс zCLockable или как-то там)
надо бы попробовать с наковальней или чем-то другим...

Итак, есть сундук, у него задана conditionFunc condChest01.
создаю новую игру, захожу проверять - на сундук нет реакции вообще...
проверял ZEN в двоичном редакторе - изменения были найдены (присутствовала функция condChest01)

Перебирал: _s1, _c1, _cond, и вообще без суффикса - ни 1 вариант не работает...
смотрю похожие примеры в моде - там conditionFunc используется с триггерами...

Наконец-то разобрался, функция conditionFunc должна быть полностью написана заглавными буквами (не понимаю юмор разработчиков).
например: не condChest01 а CONDCHEST01.

И еще 1 вопрос:
как узнать когда ГГ взломал сундук? - это когда он поворачивая отмычки туда-сюда находит правильную комбинацию, и открывается окно обмена с мобом...

процесс взлома нашел (поворот отмычки) - это функция:
func void G_PickLock(var int bSuccess,var int bBrokenOpen)
 

Saturas


Модостроитель
Регистрация
11 Фев 2009
Сообщения
2.512
Благодарности
1.334
Баллы
315
Наконец-то разобрался, функция conditionFunc должна быть полностью написана заглавными буквами (не понимаю юмор разработчиков).
например: не condChest01 а CONDCHEST01.
Какой еще юмор? Тут юмора нету, это просто ошибка разрабов, тк вызов функции идет напрямую функцией zCParser::CallFunc(zString name) а эта функция, может работать ТОЛЬКО с заглавными буквами, хотя есть пособо немного другой, вызов функции по ее индексу типа:
Код:
int index = 0;
zCParser* par = zCParser::GetParser();
index = par->GetIndex("Function_0");
par->CallFunc(index);
А причина того, почему функции при вызове по имени проиходит криво, могу объяснить:
Тк в функции zCParser::CallFunc(zString name) также есть недочет, а именно в том что, в ней происходит такая же операция, как я показал в пимере выше, но только разнитца вся в том, что в этой функции, сиволы не переводятся в верхний регистр, а в функции GetIndex - переводится.
Таким образом вызов всегда будет нормльно работать, так что тут скорее всего ошибка разрабов, или халатность=)

Bump:
И еще 1 вопрос:
как узнать когда ГГ взломал сундук? - это когда он поворачивая отмычки туда-сюда находит правильную комбинацию, и открывается окно обмена с мобом...

процесс взлома нашел (поворот отмычки) - это функция:
func void G_PickLock(var int bSuccess,var int bBrokenOpen)
Скриптами - никак по моему, хотя восприятия могут помочь...
 

Myxomop

Почетный форумчанин
Регистрация
28 Май 2005
Сообщения
3.239
Благодарности
2.581
Баллы
455
maggi1221,
как узнать когда ГГ взломал сундук? - это когда он поворачивая отмычки туда-сюда находит правильную комбинацию, и открывается окно обмена с мобом...
Ты бы конкретнее объяснил что хочешь сделать? У меня сейчас взлом реализован в моде как в Г3 и там сундук взломанным считается, если conditionFunc вернула значение TRUE. Кроме того можно также повесить проверку на OnStateFunc, которая срабатывает как раз при открытии сундука.
 

maggi1221

Участник форума
Регистрация
7 Окт 2010
Сообщения
218
Благодарности
4
Баллы
165
Ты бы конкретнее объяснил что хочешь сделать? У меня сейчас взлом реализован в моде как в Г3 и там сундук взломанным считается, если conditionFunc вернула значение TRUE. Кроме того можно также повесить проверку на OnStateFunc, которая срабатывает как раз при открытии сундука.
Я то же об этом думал, но в готике 2 это сложно реализовать. взять к примеру зарытые клады и золотые и рудные жилы... там в функции используется ..getDistToWP...- чтоб узнать где именно находится игрок, и массив,в который заносится инфа о том, сколько золота осталось в жиле, или раскопан клад или нет....
если у тебя реализовано элегантнее, можешь прислать код?

и там сундук взломанным считается, если conditionFunc вернула значение TRUE
А если игрок пытается во 2 раз открыть сундук?
дело в том, что я хочу сделать счетчик взломов, на основе которых качается навык взлома (как и карманные кражи, только в качестве жертвы выступает сундук).
Если сундук класса "почти невозможно взломать" а у ГГ не достаточно способностей для этого то выводится сообщение о низком навыке взлома и доступ к сундуку блокируется...

есть еще 1 вариант, сделать по 1 функции на каждый сундук.
формат:
chestcondfunc_ + <класс сложности: L, M, H> + _ + ID сундука:

например:
chestcondfunc_L_001
chestcondfunc_H_032

недостаток: для каждого сундука нужна своя функция.

Кроме того можно также повесить проверку на OnStateFunc, которая срабатывает как раз при открытии сундука.

только что проверил, работает отлично....
после того как ГГ взломал сундук и открыл крышку вызывается именно эта функция - супер!
 

Myxomop

Почетный форумчанин
Регистрация
28 Май 2005
Сообщения
3.239
Благодарности
2.581
Баллы
455
maggi1221,
Я то же об этом думал, но в готике 2 это сложно реализовать. взять к примеру зарытые клады и золотые и рудные жилы... там в функции используется ..getDistToWP...- чтоб узнать где именно находится игрок, и массив,в который заносится инфа о том, сколько золота осталось в жиле, или раскопан клад или нет....
если у тебя реализовано элегантнее, можешь прислать код?

maggi1221,
недостаток: для каждого сундука нужна своя функция.
У меня для каждого сундука уникальное имя VOB, которое проверяется при взломе, уникальная переменная отвечающая за состояние взлома и естественно своя коротенькая функция для каждого сундука, которая уже вызывает общую для всех. Можно считать и недостатком большое количество кода в скриптах, но, ИМХО, по другому точный учет не сделать.
Аналогично и добыче руды и прочих ископаемых, все то же самое как и у сундуков.
 

maggi1221

Участник форума
Регистрация
7 Окт 2010
Сообщения
218
Благодарности
4
Баллы
165
У меня для каждого сундука уникальное имя VOB
Это уже очень интересно, осталось узнать имя моба, с которым взаимодействует ГГ.
пробовал Npc_GetDetectedMob, но он возвращает 1 часть имени визаула.
Какую функцию нужно использовать чтоб узнать имя Vob ?
 

Myxomop

Почетный форумчанин
Регистрация
28 Май 2005
Сообщения
3.239
Благодарности
2.581
Баллы
455
maggi1221,
У меня имя Vob в уникальной функции прописано для каждого сундука.
 

maggi1221

Участник форума
Регистрация
7 Окт 2010
Сообщения
218
Благодарности
4
Баллы
165
Хух, сделал шаблон для разных систем в игре (сундуки, клады, итд) на основе битовых масок.
Файл во вложении.

Функция C_IsChestUnlocked иллюстрирует как применять битовые маски...
 

Вложения

  • bitmask.txt
    3,8 KB · Просмотры: 139

Saturas


Модостроитель
Регистрация
11 Фев 2009
Сообщения
2.512
Благодарности
1.334
Баллы
315
Кстати, не обязательно ставить возле сундука вейпоинт чтобы чекать, что это за сундук, тк функция GetDisttowp(string wp) может мерять расстояние не только до вейпоинта, но и до ЛЮБОГО воба, у которого есть имя, такто
 

maggi1221

Участник форума
Регистрация
7 Окт 2010
Сообщения
218
Благодарности
4
Баллы
165
функция GetDisttowp(string wp) может мерять расстояние не только до вейпоинта, но и до ЛЮБОГО воба, у которого есть имя, такто
нифига не работает!

вот код

concatText = ConcatStrings("r = ", IntToString(_r));
concatText = ConcatStrings(concatText, ", dist = ");
concatText = ConcatStrings(concatText, IntToString(Npc_GetDistToWP(self,"CH_NW_01")));
concatText = ConcatStrings(concatText, ", dist1 = ");
concatText = ConcatStrings(concatText, IntToString(Npc_GetDistToWP(self,"FP_SMALLTALK_HAFEN_01")));
concatText = ConcatStrings(concatText, ", dist2 = ");
concatText = ConcatStrings(concatText, IntToString(Npc_GetDistToWP(self,"NW_XARDAS_TOWER_IN1_31")));
PrintScreen(concatText,-1,55,FONT_ScreenSmall,2);

где CH_NW_01 - имя VOB сундука.
FP_SMALLTALK_HAFEN_01 - FP в гавани.
NW_XARDAS_TOWER_IN1_31 - WP, место у кровати в башне Ксардаса, где лежит Лестер.

игрок был рядом с сундуком, так что он был прогружен.


Не даблпость, используй кнопку "Редактировать" если хочешь что-либо написать дополнительно, в случае если на твое сообщение еще не было ответа от других пользователей.
Читай правила форума, последнее предупреждение...
 

Вложения

  • x11.PNG
    x11.PNG
    57,8 KB · Просмотры: 228

Saturas


Модостроитель
Регистрация
11 Фев 2009
Сообщения
2.512
Благодарности
1.334
Баллы
315
Хм, очень странно, нада будет самому по пробовать, ибо я точно помню что чтото такое было.
 

Bjorn++

Участник форума
Регистрация
28 Июн 2011
Сообщения
1.063
Благодарности
46
Баллы
235
Добрый вечер! У меня тут одна проблемка возникла при разработке моего мода, короче я создал и вставил орков, но я заметил у них одну недороботку, вообщем когда я нападаю и дубасю орка он на это никак не риагирует, тоеть не начинает на меня нападать и даже когда на него напал полевой хищник у него такаеже реакция... Вот скрипт одного из орка
instance NONE_2000_MORA(C_Npc)
{
name[0] = "Шаман Мора";
guild = GIL_FRIENDLY_ORC;
id = 2000;
voice = 18;
level = 20;
npcType = npctype_main;
attribute[ATR_STRENGTH] = 120;
attribute[ATR_DEXTERITY] = 200;
attribute[ATR_HITPOINTS_MAX] = 100;
attribute[ATR_HITPOINTS] = 100;
attribute[ATR_MANA_MAX] = 500;
attribute[ATR_MANA] = 500;
protection[PROT_BLUNT] = 130;
protection[PROT_EDGE] = 130;
protection[PROT_POINT] = 130;
protection[PROT_FIRE] = 130;
protection[PROT_FLY] = 130;
protection[PROT_MAGIC] = 65;
HitChance[NPC_TALENT_1H] = 60;
HitChance[NPC_TALENT_2H] = 60;
HitChance[NPC_TALENT_BOW] = 60;
HitChance[NPC_TALENT_CROSSBOW] = 60;
damagetype = DAM_EDGE;
fight_tactic = FAI_ORC;
senses = SENSE_HEAR | SENSE_SEE | SENSE_SMELL;
senses_range = PERC_DIST_ORC_ACTIVE_MAX;
Mdl_SetVisual(self,"Orc.mds");
Mdl_SetVisualBody(self,"Orc_BodyShaman",DEFAULT,DEFAULT,"Orc_HeadShaman",DEFAULT,DEFAULT,-1);
EquipItem(self,ItMw_2H_OrcAxe_01);
daily_routine = rtn_Prestart_2000;
};



func void Rtn_PreStart_2000()
{
ta_stand_wp(8,0,23,0,"NW_2000_START");
ta_stand_wp(23,0,8,0,"NW_2000_START");
};

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

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

maggi1221

Участник форума
Регистрация
7 Окт 2010
Сообщения
218
Благодарности
4
Баллы
165
guild = GIL_FRIENDLY_ORC;
поменяй на
guild = GIL_ORC;

а также пропиши строчку:
self.aivar[AIV_MM_REAL_ID] = ID_FRIENDLY_ORC;

далее, тебе нужно определить константу ID_FRIENDLY_ORC.
для этого в поиске по файлам ищешь строку "const int ID_WISP" и выходишь на список вида ID_xxx. идешь в конец списка и создаешь константу ID_FRIENDLY_ORC.

далее, в скриптах реакции на ГГ добавляешь условие, чтоб орк с таким ID тебя не атаковал.
можно также похимичить с функцией Npc_SetAttitude или Npc_SetGuildAttitude...
 

Bjorn++

Участник форума
Регистрация
28 Июн 2011
Сообщения
1.063
Благодарности
46
Баллы
235
далее, в скриптах реакции на ГГ добавляешь условие, чтоб орк с таким ID тебя не атаковал.
Вот это не очень понял...
 

maggi1221

Участник форума
Регистрация
7 Окт 2010
Сообщения
218
Благодарности
4
Баллы
165
Вопрос:

каково назначение B_MM_DeSynchronize() ?
провел опыты, смотрю иногда эта функция вызывается у нпц, не понял.
зато если побежать быстро к волку а затем убежать, то debug log показывает:
B_MM_AssessEnemy
ThreatenEnemy: start
ThreatenEnemy: end
B_MM_DeSynchronize

Предполагаю, что B_MM_DeSynchronize это очищение памяти нпц перед новой задачей или что-то подобное... еще она может вызываться когда нпц выходит из области стриминга, но это только догадки... кто точно знает для чего она нужна?
 

MaGoth

★★★★★★★★★★★
Администратор
Регистрация
7 Янв 2003
Сообщения
19.367
Благодарности
7.815
Баллы
995
maggi1221,
каково назначение B_MM_DeSynchronize() ?

// ***********************************
// Функция задержки реакции монстров
// ***********************************
func void B_MM_DeSynchronize()
{
var int msec;
msec = Hlp_Random(1000);
// случайная задержка от 0 до 1 сек
AI_Waitms(self,msec);

};
 
Сверху Снизу