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

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

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

MaGoth

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

Вложения

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

Диккен

Участник форума
Регистрация
12 Июн 2004
Сообщения
469
Благодарности
127
Баллы
210
1. Подскажите пож-ста, в чем моя ошибка и как её наиболее рационально и правильно реализовать через ГС?
2. Можно ли реализовать стандартыми средствами вызов из инстанции on_equip = Equip_1H(8); и почему нельзя передать аргумент?

Спасибо)

Задача: присвоить произвольно любому из мечей свойство text[4] = NAME_ADDON_BONUS_1H; и count[4] = Waffenbonus_08; которые будут меняться, в зависимости от переменной slf.aivar[REAL_TALENT_1H]; и совместить все функции on_equip = Equip_1H; в одно целое.

Einhand_EquipBonus.d
Код:
var int hero_1h_max_bonus;
// var int hero_2h_max_bonus;
 
func void Equip_1H()
{
[CODE]
    var C_Item meleeweapon;
    var int valueweapon;
    var c_npc her;
//    получить ссылку на ГГ
    hero = Hlp_GetNpc(self);
    if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(hero))
    {
        meleeweapon = Npc_GetEquippedMeleeWeapon(hero);
        valueweapon = Hlp_GetInstanceID(item);
        Npc_GetInvItem(hero,valueweapon);
        HERO_1H_MAX_BONUS = 100 - self.HitChance[NPC_TALENT_1H];
        if(HERO_1H_MAX_BONUS >= item.count[4])
        {
            HERO_1H_MAX_BONUS = item.count[4];
        };
        B_AddFightSkill(self,NPC_TALENT_1H,HERO_1H_MAX_BONUS);
    };
};
 
func void UnEquip_1H()
{
    if(self.voice == 15)
    {
        B_AddFightSkill(self,NPC_TALENT_1H,-HERO_1H_MAX_BONUS);
    };
};

Код:
instance ItMw_ElBastardo(C_Item)
{
    name = "Эль'Бастардо";
    mainflag = ITEM_KAT_NF;
    flags = ITEM_AXE;
    material = MAT_METAL;
    value = Value_ElBastardo;
    damageTotal = Damage_ElBastardo;
    damagetype = DAM_EDGE;
    range = Range_ElBastardo;
    on_equip = Equip_1H;
    on_unequip = UnEquip_1H;
    cond_atr[2] = ATR_STRENGTH;
    cond_value[2] = Condition_ElBastardo;
    visual = "ItMw_065_1h_sword_bastard_05.3DS";
    description = name;
    text[1] = NAME_Dam_Edge;
    count[1] = damageTotal;
    text[2] = NAME_Str_needed;
    count[2] = cond_value[2];
    text[3] = NAME_RADIUS;
    count[3] = range;
    text[4] = NAME_ADDON_BONUS_1H;
    count[4] = Waffenbonus_08;
    text[5] = NAME_Value;
    count[5] = value;
};

Кольцо Моргана (работает)

Код:
var int hero_morganring_1h_max_bonus;
instance ItRi_Addon_MorgansRing_Mission(C_Item)
...
func void Equip_MorgansRing()
{
    if(self.voice == 15)
    {
        HERO_MORGANRING_1H_MAX_BONUS = 100 - self.HitChance[NPC_TALENT_1H];
        if(HERO_MORGANRING_1H_MAX_BONUS >= 10)
        {
            HERO_MORGANRING_1H_MAX_BONUS = 10;
        };
        B_AddFightSkill(self,NPC_TALENT_1H,HERO_MORGANRING_1H_MAX_BONUS);
    };
};
 
func void UnEquip_MorgansRing()
{
    if(self.voice == 15)
    {
        B_AddFightSkill(self,NPC_TALENT_1H,-HERO_MORGANRING_1H_MAX_BONUS);
    };
};
 

НастасьСанна

Участник форума
Регистрация
6 Дек 2012
Сообщения
350
Благодарности
521
Баллы
325
Присваивание on_equip = Equip_1H(8) нельзя сделать принципиально. on_equip - это переменная, в которой сохраняется сама функция (точнее, ее индекс в скриптах), чтобы движок мог в нужный момент эту функцию вызвать. Там просто нет места для хранения параметров. Запись Equip_1H(8) вообще означает не саму функцию, а значение, которое она возвращает.

Однако эту проблему можно обойти с небольшими потерями. Примерно такой конструкцией:
Код:
func void Equip_1H(var int bonus_value)
{
    if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PC_Hero))
    {
        HERO_1H_MAX_BONUS = 100 - self.HitChance[NPC_TALENT_1H];
        if(HERO_1H_MAX_BONUS > bonus_value)
        {
            HERO_1H_MAX_BONUS = bonus_value;
        };
        B_AddFightSkill(self,NPC_TALENT_1H,HERO_1H_MAX_BONUS);
    };
};
Код:
instance ItMw_ElBastardo(C_Item)
{
    ...
    on_equip = Equip_1H_8;
    ...
};
 
func void Equip_1H_8()
{
    Equip_1H(8);
};

Не совсем понятно, что имелось в виду под "присвоить произвольно любому из мечей". Во время игры? Откуда будет браться значение бонуса, много ли вариантов значений? Когда это будет срабатывать? Для разных мечей или для одного определенного? Ответ зависит от этих и других нюансов. В целом, с изменением свойств итемов "на ходу" одна большая проблема - эти изменения никак не закрепляются в сейвах. Так что при сохранении-загрузке игры все итемы становятся такими, как написано в инстанции.

Если говорить про ошибки приведенного кода , то их две:
1.hero = Hlp_GetNpc(self);
hero - это и так ГГ. По логике получается, что любого npc, экипировавшегося мечом, надо сделать ГГ (хотя реально это не сработает). Подразумевалось, наверное, her = Hlp_GetNpc(self);, но оно лишнее, т.к. дальше нигде переменная her не используется.
2.meleeweapon = Npc_GetEquippedMeleeWeapon(hero);
Оружие еще не экипировано, поэтому оно не будет найдено. Ну и весь дальнейший код теряет смысл. Печально, но из equip/unequip узнать что именно экипируется довольно проблематично.
valueweapon и Npc_GetInvItem, в принципе, тоже лишние, но конкретно они на результат не влияют.
 

Диккен

Участник форума
Регистрация
12 Июн 2004
Сообщения
469
Благодарности
127
Баллы
210
Все получилось, пошел по другому пути..
AI_Constants.d
const int AIV_WEAP_TALENT_1H = 92;
const int AIV_WEAP_TALENT_2H = 93;

Код:
instance ItMw_ElBastardo(C_Item)
{
...
    hero.aivar[AIV_WEAP_TALENT_1H] = Waffenbonus_08;
};

Код:
var int hero_1h_max_bonus;
// var int hero_2h_max_bonus;
 
func void Equip_1H()
{
    if(self.voice == 15)
    {
        HERO_1H_MAX_BONUS = 100 - self.HitChance[NPC_TALENT_1H];
        if(HERO_1H_MAX_BONUS >= self.aivar[AIV_WEAP_TALENT_1H])
        {
            HERO_1H_MAX_BONUS = self.aivar[AIV_WEAP_TALENT_1H];
        };
        B_AddFightSkill(self,NPC_TALENT_1H,HERO_1H_MAX_BONUS);
    };
};
 
func void UnEquip_1H()
{
    if(self.voice == 15)
    {
        self.aivar[AIV_WEAP_TALENT_1H] = 0;
        B_AddFightSkill(self,NPC_TALENT_1H,-HERO_1H_MAX_BONUS);
    };
};
 

Диккен

Участник форума
Регистрация
12 Июн 2004
Сообщения
469
Благодарности
127
Баллы
210
Не совсем понятно, что имелось в виду под "присвоить произвольно любому из мечей". Во время игры? Откуда будет браться значение бонуса, много ли вариантов значений? Когда это будет срабатывать?


Также предлагаю реализовать новую систему бонусов для одноручного, по принципу:
- чем тяжелее оружие, тем выше штраф к навыку.
- чем легче оружие, тем меньше штраф к навыку, так например клык волка будет иметь +10 к навыку.
- шкала всех бонусов от -10 до +10
- обучение улучшает бонус в виде (slf.aivar[REAL_TALENT_1H] + 5) / 10
- самокованные чуть лучше, грубые чуть хуже
- что-то еще придумать
в таком случае, меч "убийца орков" 130/130/длина100 будет иметь штраф -10 к навыку.

Когда это будет срабатывать?
В реальном времени, после переодевания, после чтение скрижалей, после обучения

На примере ЭльБастарда
Код:
instance ItMw_ElBastardo(C_Item)
{
...
    on_equip = Equip_1H_02p;
    on_unequip = UnEquip_1H;
...
    text[4] = NAME_ADDON_BONUS_1H;
    count[4] = Waffenbonus_08 - range / 10;

Код:
var int hero_1h_max_bonus;
// var int hero_2h_max_bonus;
 
func void Equip_1H(var int weap_bonus)
{
    if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PC_Hero))
    //if(self.voice == 15)
    {
        HERO_1H_MAX_BONUS = (weap_bonus + self.aivar[REAL_TALENT_1H] + 5 / 10);
        if(HERO_1H_MAX_BONUS > 100 - self.HitChance[NPC_TALENT_1H])
        {
            HERO_1H_MAX_BONUS = 100 - self.HitChance[NPC_TALENT_1H];
        };
        B_AddFightSkill(self,NPC_TALENT_1H,HERO_1H_MAX_BONUS);
    };
};
 
func void UnEquip_1H()
{
    if(self.voice == 15)
    {
        B_AddFightSkill(self,NPC_TALENT_1H,-HERO_1H_MAX_BONUS);
    };
};
...
func void Equip_1H_02p()
{
    Equip_1H(Waffenbonus_02p);
};
 

Диккен

Участник форума
Регистрация
12 Июн 2004
Сообщения
469
Благодарности
127
Баллы
210
Все получилось, пошел по другому пути..
Нет, опять ошибка, инстанция изменяет глобальную переменную, к. работает для всех мечей. Видно не избежать решения от НастасьСанна. :{

Большое спасибо, все работает отлично... с Наступающими Всех!

Код:
var int hero_1h_max_bonus;
// var int hero_2h_max_bonus;
 
func void Equip_1H(var int weap_bonus)
{
    if(Hlp_GetInstanceID(self) == Hlp_GetInstanceID(PC_Hero))
    //if(self.voice == 15)
    {
        HERO_1H_MAX_BONUS = 100 - self.HitChance[NPC_TALENT_1H];
        if(HERO_1H_MAX_BONUS > weap_bonus)
        {
            HERO_1H_MAX_BONUS = weap_bonus;
        };
        B_AddFightSkill(self,NPC_TALENT_1H,HERO_1H_MAX_BONUS);
    };
};
 
func void UnEquip_1H()
{
    if(self.voice == 15)
    {
        B_AddFightSkill(self,NPC_TALENT_1H,-HERO_1H_MAX_BONUS);
    };
};

Код:
func void Equip_1H_08()
{
    Equip_1H(Waffenbonus_08);
 
};
 
func void Equip_1H_08p()
{
    Equip_1H(Waffenbonus_08p);
 
};

Код:
const int Waffenbonus_01 = 1;
const int Waffenbonus_01p = -1;
const int Waffenbonus_02 = 2;
const int Waffenbonus_02p = -2;
const int Waffenbonus_03 = 3;
const int Waffenbonus_03p = -3;
const int Waffenbonus_04 = 4;
const int Waffenbonus_04p = -4;
const int Waffenbonus_05 = 5;
const int Waffenbonus_05p = -5;
const int Waffenbonus_06 = 6;
const int Waffenbonus_06p = -6;
const int Waffenbonus_07 = 7;
const int Waffenbonus_07p = -7;
const int Waffenbonus_08 = 8;
const int Waffenbonus_08p = -8;
const int Waffenbonus_09 = 9;
const int Waffenbonus_09p = -9;
const int Waffenbonus_10 = 10
const int Waffenbonus_10p = -10;

instance ItMw_ElBastardo(C_Item)
{
...
on_equip = Equip_1H_08;
on_unequip = UnEquip_1H;
 

НастасьСанна

Участник форума
Регистрация
6 Дек 2012
Сообщения
350
Благодарности
521
Баллы
325
Нет, опять ошибка, инстанция изменяет глобальную переменную, к. работает для всех мечей.
Все, что находится внутри instance срабатывает при каждой вставке предмета в мир или чей угодно инвентарь - при загрузке мира, при CreateInvItem, при создании в слоте модели и т.д. Но не каждая экипировка вызывает вставку итема, он может просто переместиться из инвентаря на модель. Так что в итоге в hero.aivar[AIV_WEAP_TALENT_1H] может оказаться значение не для нужного оружия, а для последнего вставленного.


С отображением динамического бонуса довольно тяжко. Назначить-то не так трудно. Просто выскажу кое-какие соображения, может помогут.

Как я понимаю, бонус будет зависеть а) от свойств самого меча б) от реального навыка ГГ, причем этот бонус должен быть у всего оружия, в чьем бы инвентаре оно ни находилось. Тогда давать/убирать бонус ГГ надо при equip/unequip и изменении реального навыка. А изменять описание итемов надо при изменении навыка и в каждой загрузке игры. Возможности изменять описание при каждом обращении к итему в скриптах нет.

В такой постановке вопроса самым трудным будет при изменении навыка ГГ поменять описание всего (!:eek:) оружия в игре. Стандартные скрипты просто не дают такой возможности. Через Икарус можно, и то придется повозиться. Более простым решением будет в свойствах итема отображать постоянное значение бонуса, которое зависит только от (а). А уже когда оружие экипируется, через PrintScreen писать реально полученный бонус.

Внутри instance итема можно использовать любые конструкции скриптов, в том числе if, вызов функций, какие-то вычисления и значения глобальных переменных. А вот self будет недоступен. hero будет недоступен в момент загрузки игры - сначала загружаются глобальные переменные, потом вставляются npc и предметы, а потом уже присваивается значение hero.

Отлавливать изменение (б) достаточно только в B_RaiseRealFightTalentPercent. И для обучения, и для табличек.

Чуть не забыла. Еще может возникнуть такая ситуация: ГГ надел, скажем, кольцо с бонусом к навыку и меч с бонусом, так что в сумме они дали больше 100%. Потом игрок кольцо снял, стало меньше 100%. Тогда от меча бонус будет меньше правильного, пока игрок его не снимет-наденет.
 

Диккен

Участник форума
Регистрация
12 Июн 2004
Сообщения
469
Благодарности
127
Баллы
210
С отображением динамического бонуса довольно тяжко.
Спасибо за подсказку, более-менее для меня лично приемлем вариант, к. изложил в ответе #1795. Нет нужды перезаписывать свойства каждого предмета, пусть они отражают начальные бонусы. Реальный бонус коснется только свойств ГГ, к. обновляются только после ручном переодевании меча.

Чуть не забыла. Еще может возникнуть такая ситуация: ГГ надел, скажем, кольцо с бонусом к навыку и меч с бонусом, так что в сумме они дали больше 100%. Потом игрок кольцо снял, стало меньше 100%. Тогда от меча бонус будет меньше правильного, пока игрок его не снимет-наденет.
Именно эта проблема лежала в основе моих страданий по скриптингу, надеюсь приведенный совместными усилиями (Zorres, Вы и я) в порядок метод проверки сможет помочь модмейкерам. :)

Внутри instance итема можно использовать любые конструкции скриптов, в том числе if, вызов функций, какие-то вычисления и значения глобальных переменных
Может быть задействовать прототип для мечей, чтобы вписать нужные данные по бонусам в автомате? Еще не встречал ни одного прототипа для предметов, это возможно сделать? Пришла хорошая мысль, каким образом реализовать "- шкала всех бонусов от -10 до +10" для одноручных.

Prototype ITMW_Default_1H(C_Item)
{
count[4] = (75 - range) * 2 / 5;
};

instance ItMw_ElBastardo(ITMW_Default_1H)
{
count[4] += Waffenbonus_08;

Вот такая конструкция возможна?
 

Диккен

Участник форума
Регистрация
12 Июн 2004
Сообщения
469
Благодарности
127
Баллы
210
Создал прототип для мечей, частично работает. При вызове из инстанции переменная on_equip всегда = Equip_1H_00; и расчет count[4] = (75 - range) * 2 / 5 + Waffenbonus_08; при вызове instance ItMw_ElBastardo(ITMW_DEFAULT_1H_EDGE) не влияет на итог.
Код:
prototype ITMW_DEFAULT_1H_EDGE(C_Item)
{
    name = "Кинжал";
    mainflag = ITEM_KAT_NF;
    flags = ITEM_SWD;
    material = MAT_METAL;
    value = 5;
    damageTotal = 5;
    damagetype = DAM_EDGE;
//    range = 50;
    cond_atr[2] = ATR_STRENGTH;
    cond_value[2] = 5;
    visual = "Itmw_005_1h_dagger_01.3DS";
    description = name;
    text[1] = NAME_Dam_Edge;
    count[1] = damageTotal;
    text[2] = NAME_Str_needed;
    count[2] = cond_value[2];
    text[3] = NAME_RADIUS;
    count[3] = range;
    text[4] = NAME_ADDON_BONUS_1H;
//    count[4] = 0;
    text[5] = NAME_Value;
    count[5] = value;
    if(count[4] > 0)
    {
        if(count[4] == Waffenbonus_01)
        {
            on_equip = Equip_1H_01;
        };
        if(count[4] == Waffenbonus_02)
        {
            on_equip = Equip_1H_02;
        };
        if(count[4] == Waffenbonus_03)
        {
            on_equip = Equip_1H_03;
        };
        if(count[4] == Waffenbonus_04)
        {
            on_equip = Equip_1H_04;
        };
        if(count[4] == Waffenbonus_05)
        {
            on_equip = Equip_1H_05;
        };
        if(count[4] == Waffenbonus_06)
        {
            on_equip = Equip_1H_06;
        };
        if(count[4] == Waffenbonus_07)
        {
            on_equip = Equip_1H_07;
        };
        if(count[4] == Waffenbonus_08)
        {
            on_equip = Equip_1H_08;
        };
        if(count[4] == Waffenbonus_09)
        {
            on_equip = Equip_1H_09;
        };
        if(count[4] >= Waffenbonus_10)
        {
            on_equip = Equip_1H_10;
        };
    }
    else if(count[4] < 0)
    {
        if(count[4] == Waffenbonus_01p)
        {
            on_equip = Equip_1H_01p;
        };
        if(count[4] == Waffenbonus_02p)
        {
            on_equip = Equip_1H_02p;
        };
        if(count[4] == Waffenbonus_03p)
        {
            on_equip = Equip_1H_03p;
        };
        if(count[4] == Waffenbonus_04p)
        {
            on_equip = Equip_1H_04p;
        };
        if(count[4] == Waffenbonus_05p)
        {
            on_equip = Equip_1H_05p;
        };
        if(count[4] == Waffenbonus_06p)
        {
            on_equip = Equip_1H_06p;
        };
        if(count[4] == Waffenbonus_07p)
        {
            on_equip = Equip_1H_07p;
        };
        if(count[4] == Waffenbonus_08p)
        {
            on_equip = Equip_1H_08p;
        };
        if(count[4] == Waffenbonus_09p)
        {
            on_equip = Equip_1H_09p;
        };
        if(count[4] <= Waffenbonus_10p)
        {
            on_equip = Equip_1H_10p;
        };
    }
    else
    {
        on_equip = Equip_1H_00;
    };
    on_unequip = UnEquip_1H;
};
 

НастасьСанна

Участник форума
Регистрация
6 Дек 2012
Сообщения
350
Благодарности
521
Баллы
325
Конструкция из поста #1799 возможна, а из #1800 не работает, т.к. сначала обрабатывается все для прототипа, а потом на него "накладывается" инстанция. Соответственно, if всегда срабатывает для значения из прототипа (0), чтобы потом ни присвоили в инстанции.
Можно так:
Код:
var int ElBastardo_Bonus;
instance ItMw_ElBastardo(ITMW_Default_1H)
{
count[4] += Waffenbonus_08;
ElBastardo_Bonus = count[4];
on_equip = equip_ElBastardo;
};
func void equip_ElBastardo()
{
Equip_1H(ElBastardo_Bonus);
};
 

Диккен

Участник форума
Регистрация
12 Июн 2004
Сообщения
469
Благодарности
127
Баллы
210
У меня это получилось, можно спать спокойно. :{
 

Вложения

  • IT_Melee_weapons.d.txt
    3,2 KB · Просмотры: 158
  • Einhand_EquipBonus.d.txt
    3,3 KB · Просмотры: 170

redleha


Модостроитель
Регистрация
26 Фев 2008
Сообщения
735
Благодарности
665
Баллы
245
Вот абсолютно-абсолютно неправильно. Всё в кучу, причём отсебятина, не разобравшись в работе скриптов.
Может стОит начать с малого, а уже потом лезть за что-то сложнее?
 

Test Level

Участник форума
Регистрация
1 Ноя 2011
Сообщения
1.770
Благодарности
557
Баллы
275
1. Как поменять flags по окончании разговора?
2. Как заставить монстра не атаковать ГГ? Т.е. сначала должен идти диалог, по окончании у монстра должен смениться flags на смертный и он должен атаковать.
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Судя по вопросу ГГ уже разговаривает с монстром...

поехали(извиняюсь пишу по памяти)...

self.flag=меняй на нужное

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

Test Level

Участник форума
Регистрация
1 Ноя 2011
Сообщения
1.770
Благодарности
557
Баллы
275
Судя по вопросу ГГ уже разговаривает с монстром...

поехали(извиняюсь пишу по памяти)...

self.flag=меняй на нужное

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


Нет, ГГ не разговаривает. Вот и надо сделать так, чтоб монстр не нападал до диалога.
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.860
Благодарности
6.740
Баллы
1.625
Нет, ГГ не разговаривает. Вот и надо сделать так, чтоб монстр не нападал до диалога.
дай ему гильию горожанина, после разговора поменяй гильдию обратно(self.guild=монстер) и пропиши нападение.
 

Kntm

Участник форума
Регистрация
13 Авг 2013
Сообщения
9
Благодарности
0
Баллы
150
Если пишу в неправильную тему, прошу перенести. По какой то причине перестали в ряде установленных модов подгружаться скрипты (на другие это не влияет). Подгружается только завобленный мир. С чем такое может быть связано, подскажите?
 

Myxomop

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