Помощь - Поиск - Пользователи - Календарь
Полная версия: Для программистов
Форум студии Seaward.Ru > Форумы аддонов к играм ПКМ, КВЛ, ГПК > Модификации для игр на ядре Storm 2.x
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
BUKA_E}l{EBUKA
(ВМЛ) Подскажите проверку (или в каком месте в коде можно найти подобное), находится ли ГГ сейчас в море.
Не на суше/карте мира/каюте/палубе/абордаже, а именно в море на корабле от 3-го лица.

Пробовала IsEntity(Sea) / IsEntity(&Sea) / IsEntity(AISea) / IsEntity(&AISea), но результат не оправдал ожиданий.

UPD: разобралась, но решила делать по-другому.

На случай если кому понадобится, потестите это:
if (bSeaActive && !bAbordageStarted)
или:
if (bSeaActive && !bAbordageStarted && SeaCameras.Camera != "SeaDeckCamera")
BUKA_E}l{EBUKA
(ВМЛ) Спустя некоторое время после окончания битвы на суше, игра позволяет сохраняться.

Но некоторое время назад появилась проблема:
Иконки персонажей продолжают моргать красным и все еще звучит боевая музыка.
И пока локацию не сменишь, это не прекратится.

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

Буду весьма признательна если кто-то поопытнее мне подскажет что делать

P.S.
Файл 'options' в порядке, я его регулярно чищу.
Хоть я и повысила лимит на кол-во сейвов, но папку время от времени освобождаю и обычно в ней 15-70 файлов.
Быстрым сохранением не пользуюсь.

В error.log нет ничего кроме постоянно появляющихся
Код
RUNTIME ERROR - file: seadogs.c; line: 590
Save - ARef to non existing attributes branch
где строка 590 это закрывающая '}' функции 'void OnSave()'

UPD:
Поковырялась еще и обнаружила некое несоответствие кода и первым 2/3 времени проведенного мной в игре.

Как было у меня со старта игры:
Во время битвы (при наличии живых врагов) - 1. иконки моргают красным
2. нельзя сохраняться, неважно вытащено оружие или нет
После битвы (живых врагов не осталось) - проходит некоторое время, моргание прекращается и можно сохраняться (черт подери, это моргание на протяжении многих десятков часов прохождения служило у меня индикатором когда игра разрешит засейвица)

Как должно быть согласно коду:
Во время битвы - 1. можно сохраняться если оружие убрано, я не вижу никаких проверок на наличие в локации враждебных юнитов
2. никаких "спустя некоторое время" я тоже не вижу, убрал оружие - сейвись хоть прям сразу

Кто еще помнит свои похождения ВМЛ - как было у вас?


UPD2:
AlexusB, по поводу строки из этого ченджлога:
"15. Переделал запрет сохранения в бою. Раньше при мигании тревоги был запрет. Теперь запрет, только если боевой режим (обнажен меч)."
Вы случайно не помните, что и где там менялось?
Verdugo
Глянул мельком, на истину не претендую. rolleyes.gif

Цитата(BUKA_E}l{EBUKA @ Sep 21 2020, 18:38) *

(ВМЛ) Спустя некоторое время после окончания битвы на суше, игра позволяет сохраняться.
Но некоторое время назад появилась проблема:
Иконки персонажей продолжают моргать красным и все еще звучит боевая музыка.
И пока локацию не сменишь, это не прекратится.


У меня стоит не ВМЛ, но скрипты похожие. Может быть и у вас это сработает, как у меня.
Я просто повесил все эти команды на клавишу F10 в Debuger.c
Команды см. в LAi_groups.c

Например, вы подрались в таверне с офицером - враг уже помер давно, а аларм все не проходит:

Код
void ActiveF10Control()
{
    LAi_grp_playeralarm = 0;
    LAi_grp_alarmactive = false;
    LAi_group_Release();
    Sound_OnAlarm(false);
}

Война выключается, можно беседовать с барменом/выпивохами и т.д, никто ругаться не будет.
У меня в ККС, по крайней мере, это работает.

Если сохраниться по прежнему нельзя, может быть, туда стоит добавить:

InterfaceStates.Buttons.Save.enable = 1;


Если, допустим, вы начали колотить охранника в городе, а потом вдруг передумали biggrin.gif

void ActiveF10Control()
{
SendMessage(&LAi_grp_relations, "s", "LoadDataRelations");
}

Восстанавливает отношение (из объекта, вероятно?).

Или вы уже поколотили охранника, потом сменили локацию (зашли в кабак, например)
а кабатчик называет грязным убийцей, и не хочет налить рому laugh.gif

void ActiveF10Control()
{
SendMessage(&LAi_grp_relations, "s", "RestoreStates");
}

При смене локации, горькие обиды пишутся (в объект, вероятно?).

Цитата

В error.log нет ничего кроме постоянно появляющихся
RUNTIME ERROR - file: seadogs.c; line: 590
Save - ARef to non existing attributes branch


У меня в скриптах ВМЛ строка 590 это:
void ClearLocationsSaveData()
{
aref loc = GetEventData(); // а это, вероятно, искомый ARef
SendMessage(loc, "l", MSG_LOCATION_CLRCHRPOSITIONS);
}



Цитата

Как было у меня со старта игры:
Во время битвы (при наличии живых врагов) - 1. иконки моргают красным
2. нельзя сохраняться, неважно вытащено оружие или нет
После битвы (живых врагов не осталось) - проходит некоторое время, моргание прекращается и можно сохраняться (черт подери, это моргание на протяжении многих десятков часов прохождения служило у меня индикатором когда игра разрешит засейвица)

Как должно быть согласно коду:
Во время битвы - 1. можно сохраняться если оружие убрано, я не вижу никаких проверок на наличие в локации враждебных юнитов
2. никаких "спустя некоторое время" я тоже не вижу, убрал оружие - сейвись хоть прям сразу


Гляньте в LAi_fight.c
или в LAi_player.c
может быть, это оно?

CODE
//Процессирование типа персонажа
void LAi_type_player_CharacterUpdate(aref chr, float dltTime)
{
float time;
if(SendMessage(chr, "ls", MSG_CHARACTER_EX_MSG, "IsActive") != 0)
{
chr.chr_ai.type.weapontime = "0";
}
if(LAi_group_GetPlayerAlarm())
{
chr.chr_ai.type.weapontime = "0";
}
if(LAi_IsFightMode(chr)) // <<<<<<<<<< ?
{
time = stf(chr.chr_ai.type.weapontime) + dltTime;
chr.chr_ai.type.weapontime = time;
if(time > 300.0) // <<<<<<<<<< "спустя некоторое время"?
{
chr.chr_ai.type.weapontime = "0";
SendMessage(chr, "lsl", MSG_CHARACTER_EX_MSG, "ChangeFightMode", false); // <<<<<<<<<< ?
}
}else{
chr.chr_ai.type.weapontime = "0";
}
}


Цитата

"Переделал запрет сохранения в бою. Раньше при мигании тревоги был запрет. Теперь запрет, только если боевой режим (обнажен меч)."


Наверное, вот так:

Код
bool QuickSaveGameEnabled()
{
    bool TmpBool = true;
    //if(LAi_group_IsActivePlayerAlarm() && !bBettaTestMode) TmpBool = false; // <-- "Раньше при мигании тревоги был запрет."
    ref mchref = GetMainCharacter();
    if (LAi_IsFightMode(mchref) && !bBettaTestMode) TmpBool = false; // <-- "Теперь запрет, только если боевой режим (обнажен меч)."
    if(!LAi_IsCharacterControl(GetMainCharacter())) TmpBool = false;
    if (dialogRun) TmpBool = false;
    if (IsEntity(worldMap)) TmpBool = true;
    return TmpBool;
}


BUKA_E}l{EBUKA
Вопрос тем, кто знаком с кодом ВМЛ версий более ранних чем выложенные исходники:

В прошлых ВМЛ везение случайно не называлось 'sneak' в коде? Или когда-то было только везение, затем добавили скрытность и часть проверок/бонусов везения сменили на скрытность (судя по комментариям к предметам)?.

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

CharacterUtilite.c
SKILL_SNEAK в кол-ве сожранного крысами (void DailyRatsEatGoodsUpdate)
Код
iQuantity = 1+ rand(makeint(iQuantity / (2+GetSummonSkillFromNameToOld(chref, SKILL_REPAIR) + GetSummonSkillFromNameToOld(chref,SKILL_SNEAK))));


characters_init.c
Коммент говорит сам за себя
Код
        if (!CheckAttribute(rCharacter, "skill.Pistol"))
        {
            rCharacter.skill.Pistol = 3 + rand(5);
            rCharacter.skill.Sneak  = 1 + rand(8); // удача влияет на раны от пистолета
        }


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


P.S.
Цитата(Verdugo @ Sep 23 2020, 23:59) *
Глянул мельком

Спасибо за развернутый ответ! Многое из этого мне пригодится

Судя по тому, что интенсивный гуглинг такой проблемы ни у кого не показал - что-то не так на моей стороне.
И даже подозреваю что:
Я начала игру на релизной версии ВМЛ, отыграла много часов, поверх накатила исходники ВМЛ (для твиков) и продолжила играть на том же сейве.

Так что я забила на это дело. Все пути ведут в ядро, тот же eventAllarm, который триггерит смену звука на боевой и обратно.
Буду играть как есть. Сохраняться можно, а боевую музыку и моргание я как-нибудь переживу, бывало и хуже (однажды в сталкере, на глубоком-глубоком сейве, я решила подправить аномалии. И сломала визуалку у доброй половины. А бэкап файлов под шумок удалил антивирь. Так и играла - с невидимыми, но болючими laugh.gif )
Slayer
Камрады, кто в курсе - почему он постоянно мне сдается вообще даже без боя? что не так в коде? вроде всё ок должно быть . Причем в тестовом режиме когда смотрю в трубу на него есть лог - не сдается! - ..
============================================

Group_FindOrCreateGroup("Beltrop_Attack");
Group_SetType("Beltrop_Attack", "war");
sld = characterFromID("Beltrop");
sld.rank = 55;
LAi_SetHP(sld, 400, 400);
SetSPECIAL(sld, 10, 10, 10, 9, 8, 10, 9); //сил.воспр.вын.автор.обуч.реакц.удача
SetSelfSkill(sld, 80, 95, 100, 100, 100);
//SetShipSkill(sld, 75, 50, 100, 100, 100, 80, 100, 100, 100);
sld.MultiFighter = 1.5;
sld.MultiShooter = 1.5;
SetHalfPerksToChar(sld, false);
SetCharacterPerk(sld, "Energaiser");
SetCharacterPerk(sld, "BasicDefense"); //
SetCharacterPerk(sld, "AdvancedDefense");
SetCharacterPerk(sld, "CriticalHit");
SetCharacterPerk(sld, "Tireless");
SetCharacterPerk(sld, "SwordplayProfessional");
SetCharacterPerk(sld, "Sliding");
SetCharacterPerk(sld, "Gunman");
SetCharacterPerk(sld, "GunProfessional");
SetCharacterPerk(sld, "HardHitter");
SetCharacterPerk(sld, "ByWorker");
SetCharacterPerk(sld, "ShipEscape");
SetCharacterPerk(sld, "IronWill");
SetCharacterPerk(sld, "Doctor1");
SetCharacterPerk(sld, "Doctor2");
sld.DontRansackCaptain = true;
FantomMakeCoolSailor(sld, SHIP_BLACKPEARL, "Скиталец", CANNON_TYPE_CANNON_LBS32, 100, 100, 100);// черн. жемчужина
sld.name = "Чарльз";
sld.lastname = "Вейн";
//SetBaseShipData(sld);
sld.ship.crew.quantity = 500;
sld.ship.Crew.Morale = 100;
sld.Ship.Crew.Exp.Sailors = 100;
sld.Ship.Crew.Exp.Cannoners = 100;
sld.Ship.Crew.Exp.Soldiers = 100;
RealShips[sti(sld.Ship.Type)].ship.upgrades.hull = 3;
sld.DontRansackCaptain = true;
sld.AnalizeShips = true;
sld.Coastal_Captain = true;
sld.WatchFort = true; // форты видит
sld.LockTask = true;
sld.AlwaysEnemy = true;
sld.SinkTenPercent = false;// не сдавать сяч не тонуть при 10%
DeleteAttribute(sld, "SaveItemsForDead"); //вещи не сохранять
DeleteAttribute(sld, "DontClearDead");
sld.Ship.Mode = "war";
if (MOD_SKILL_ENEMY_RATE > 2) SetCharacterPerk(sld, "MusketsShoot");
Group_AddCharacter("Beltrop_Attack", "Beltrop");
Group_SetGroupCommander("Beltrop_Attack", "Beltrop");
Group_SetAddress("Beltrop_Attack", "Maracaibo", "quest_ships", "quest_ship_1");
ALexusB
sld.DontRansackCaptain = true; - это не сдаваться
проверяется в LAi_StartBoarding
Если там вкл чит сдачи (дебуг ф11), то все сдаются всегда
Slayer
Цитата(ALexusB @ Sep 30 2020, 17:06) *

sld.DontRansackCaptain = true; - это не сдаваться
проверяется в LAi_StartBoarding
Если там вкл чит сдачи (дебуг ф11), то все сдаются всегда

на Ф11 уже другое назначение . Но наверное потому что я ставил себе бессмертие + команду на корабле 3500 челов. Наверно из за этого . даже ставя ставки сдачи по 0.0 - все равно сдавались. Потом сравнл с обычной игрой с мощным кораблем - сдаваться перестали.. видимо дело было в ГГ. но сама прична так и осталась неизвестна)
BUKA_E}l{EBUKA
Причастные к разработке аддона ВМЛ, проконсультируйте пожалуйста 3.gif

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


Почему спрашиваю:

Нашла First Mate с авторитетом и навой по 100, ну и решила освободить свой инвентарь от шмота на + к этим скилам. Позже заметила, что мэры стали значительно реже соглашаться со мной играть.

Пошла искать причину
Оказалось, у мэра помимо есть проверка на авторитет, помимо прочих.
Вот только сделана она не через GetSummonSkillFromNameToOld (учитывает скилы офицеров), а через GetCharacterSkillToOld (учитывает только скил ГГ).

Уж очень меня сие удивило
Как получить стратегически важдую инфу о местонахождении губера - ну вон та рожа из твоей свиты мне знакома, мужик надежный, значит и ты свой чувак, записывай
А как в картишки перекинуться - да ну, ты ж хрен с горы еще колоду мне погрызешь вали отсюдова
laugh.gif
ALexusB
в ВМЛ нет GetSummonSkillFromNameToOld, есть GetSummonSkillFromName
Это уже какие-то доработки на местах

авторитет - личный скил ГГ, уже не помню по ВМЛ, в КВЛ так
http://www.seaward.ru/scr.php?srcimg=img03.jpg
BUKA_E}l{EBUKA
Не подскажете, где код отвечающий за перенос вещей в каюте при обмене кораблями?

У меня все рассортировано по разным сундукам, а при смене корабля все скидывает в один.
И я тут поймала себя на мысли что не подбираю корабль получше (и не апгрейжу компаньонов) только потому, что лень потом снова сортировать барахлишко unsure.gif

Глянуть бы как там устроено, мож справлюсь допилить под свои хотелки
ALexusB
Поиск по коду рулил
Set_My_Cabin()

BUKA_E}l{EBUKA
Чтобы найти Set_My_Cabin, нужно искать по Set_My_Cabin biggrin.gif

Если не горит вотпрямщас, то почему бы не спросить, и заниматься другими делами. Вдруг кто-то знает нужное место/название или поможет сузить круг поиска.

Вот вы сэкономили мне час-два поисков вслепую по словам типа 'cabin' и 'каюта' с просмотром контекста каждой строки из сотен выданных на предмет соответствия искомому. Спасибо!
ALexusB
нужно искать по ключевым словам "Cabin", или открыть Интерфейсы, найти там захват корабля и покопать в сторону его захвата.
"то почему бы не спросить, и заниматься другими делами."
Я пожалуй тоже так буду делать smile.gif

Т.к. "я даю вам не рыбу, а учу ее ловить"
И на аналогичные вопросы ответ будет, как найти, а не сам ответ (или буду заниматься другими делами, что тоже хорошо) smile.gif

Лень - оружие в обе стороны.
BUKA_E}l{EBUKA
Цитата
"то почему бы не спросить, и заниматься другими делами."
Я пожалуй тоже так буду делать

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

Цитата
И на аналогичные вопросы ответ будет, как найти, а не сам ответ

Вы не поверите, но я буду очень благодарна и за это. Потому что это даже больше, чем я ожидаю получить, спрашивая в интернете.

В зависимости от направления сайта, его аудитории, возраста/пола/душевного состояния отвечающего, наличия Нептуна в Водолее, тебе могут:
. дать заведомо неверный ответ
. послать нах
. предложить доказать причастность к женскому полу (посему во многих местах я пишу от мужского лица)
. ответить через 3 дня, 2 недели, месяц, 10 лет
. не ответить вообще
Спрашивая в интернете, ты как бы принимаешь подобные условия.
Я не считаю это чем-то ужасным, так уж исторически сложилось. По ту сторону экрана тебе никто ничего не должен.


Цитата
или открыть Интерфейсы, найти там захват корабля и покопать в сторону его захвата

Давайте попробуем, может это и правда легко и быстро.

1. Начнем с Program\INTERFACE\transfer_main.c как самого логичного претендента, т.к. именно там у нас обмен кораблями
2. void SwapProcess(), где-то здесь то что нам нужно
3. Среди ее содержимого три неизвестных функции (SeaAI_SwapShipsAttributes, SeaAI_SwapShipAfterAbordage, WasChangeData), какая-то из них ведет куда надо
4. void WasChangeData сразу смотрим и отметаем
5. void SeaAI_SwapShipsAttributes состоит только из CopyAttributes и DeleteAttribute, никакой информации это нам не несет
6. В bool SeaAI_SwapShipAfterAbordage два пути - UpdateRelations и AI_MESSAGE_SWAP_SHIPS в SendMessage
7. AI_MESSAGE_SWAP_SHIPS - ведет в тупик "#define AI_MESSAGE_SWAP_SHIPS 51014"
8. UpdateRelations - аналогично, к череде #define
9. DEAD END

Ради интереса, пойдем от противного.
Попробуем раскопать цепь событий ведущих к Set_My_Cabin от нее самой
1. Поиск по функции - 3 результата, дебаг исключаем
2. Варианты - void Sea_CabinStartNow() в Cabin.c и void Sea_DeckStartNow() в Deck.c
3. Копаем от Sea_CabinStartNow, ведь в названии фигурирует каюта
4. Вызывается она в двух местах: void BI_LaunchCommand() (BattleInterface.c) и void QuestComplete (quests_reaction.c). По идее, нам нужна первая
5. В void BI_LaunchCommand() нужная нам Sea_CabinStartNow вызывается через switch(commandName) кейсом BI_Cabin.
Откуда берется commandName? Из EventData, конечно!
Сама BI_LaunchCommand вызывается одноименным ивентом, поиск по котором выдает единственное совпадение в которм присутствуют параметры - Event("BI_LaunchCommand","lsls", charIdx, "BI_SailTo", targetNum, locName); что нам по идее не очень подходит.
DEAD END

Я конечно могла где-то свернуть не туда или что-то упустить, но я и не знакома ни с кодом ВМЛ, ни с языком его скриптов настолько хорошо насколько знакомы с этим вы.

Так что мне бы оставалось только искать нотепадом++ по cabin в папке Program, перебирая все 394 hits in 29 files в надежде что нужный мне кейворд именно cabin.
Verdugo
Цитата
Доброго времени суток!
Я случайно увидел твои сообщения на сивардовском форуме, где ты описываешь непонятную работу эвента NPC_Event_EnableStun в ККС.
Дело в том, что у меня тоже трудности с этим местом, а логи выдают информацию, которая с трудом поддаётся интерпретации.
В общем, я хотел бы поинтересоваться, не получилось ли у тебя в итоге разобраться с обработкой этого эвента?


Здравствуйте. Нет, способа как это сделать я не нашел.
Вероятно, для того чтобы сделать динамическое изменение стана ГГ, без правок в движке не обойтись. Надеюсь, что это будет добавлено в грядущем патче от БМС.
Я тогда заметил, что NPC_Event_EnableStun действует на анимации hit_attack и hit_fire, но не действует на hit_feint. Но поиск по скриптам, опять же, ничего не дал.

Там рядом еще был момент интересный, связан с распределением атакующих весов для NPC. Эти функции опрашиваются разово при загрузке локации, для всех персонажей в локации (включая ГГ) То есть, если ваш абордажник зайдет в локацию с топором, ему будут прописаны веса согласно chr_ai.fencingtype = FencingH. Если после этого вы оденете ему рапиру и вступите в бой, до смены локации абордажник будет намахивать шпагой как топором.

CODE

float npc_return_tmp;
bool npc_return_tmpb;

//Вес выбора удара "fast", 0 - никогда не выбирать
#event_handler("NPC_Event_GetAttackWeightFast","LAi_NPC_GetAttackWeightFast");
float LAi_NPC_GetAttackWeightFast()
{
aref chr = GetEventData();
npc_return_tmp = 20.0 * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingL", 1.0, 3.0);
npc_return_tmp = npc_return_tmp * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingH", 1.0, 0.5);
npc_return_tmp = npc_return_tmp * (0.8 + (0.1 * MOD_SKILL_ENEMY_RATE));
return npc_return_tmp;
}

//Вес выбора удара "force", 0 - никогда не выбирать
#event_handler("NPC_Event_GetAttackWeightForce","LAi_NPC_GetAttackWeightForce");
float LAi_NPC_GetAttackWeightForce()
{
aref chr = GetEventData();
npc_return_tmp = 50.0 * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingS", 1.0, 3.0);
npc_return_tmp = npc_return_tmp * (0.8 + (0.1 * MOD_SKILL_ENEMY_RATE));
return npc_return_tmp;
}

// boal 20.01.08 коммент - забавно, что спустя два года, понал как и что с вероятностями.
Они все приводятся к 0-1 от веса общей суммы, то есть фактически
умножение на сложность или цифры распределяют сумму по другим акшенам, а не усиливают этот
// Экшены идут парами - все атаки и защита (блок + пари)


Интересно, что в ККС "fast" - это рубящие атаки, а "force" - атаки выпадом.
При расчете дамага это учтено, а здесь выходит, что саблист - самый часто колющий NPC.
Может быть, есть знающий человек, кто сможет подсказать как работают эти веса?

CODE

Смелый флибустьер:

Рапиры/Шпаги - Fight Level: 1.00
Рубящий (fast) 84.0
Колющий (force) 70.0
Круговой (round) 28.0
Пробивающий (break) 12.0
Финт (feint) 12.0

Сабли/Тесаки - Fight Level: 1.00
Рубящий (fast) 28.0
Колющий (force) 210.0
Круговой (round) 28.0
Пробивающий (break) 24.0
Финт (feint) 12.0

Палаши/Топоры - Fight Level: 1.00
Рубящий (fast) 14.0
Колющий (force) 70.0
Круговой (round) 28.0
Пробивающий (break) 72.0
Финт (feint) 12.0

Отчаянный корсар:

Рапиры/Шпаги - Fight Level: 1.00
Рубящий (fast) 108.0
Колющий (force) 90.0
Круговой (round) 36.0
Пробивающий (break) 16.0
Финт (feint) 16.0

Сабли/Тесаки - Fight Level: 1.00
Рубящий (fast) 36.0
Колющий (force) 270.0
Круговой (round) 36.0
Пробивающий (break) 32.0
Финт (feint) 16.0

Палаши/Топоры - Fight Level: 1.00
Рубящий (fast) 18.0
Колющий (force) 90.0
Круговой (round) 36.0
Пробивающий (break) 96.0
Финт (feint) 16.0


У саблиста сумма весов на треть больше, чем у других классов.
Тестировал на даньке с анимацией К3/КСМ, т.к. на дефолтной анимации нельзя просто взять и отличить колющий от рубящего.
Stor
Цитата(Verdugo @ Oct 21 2020, 20:39) *

Здравствуйте. Нет, способа как это сделать я не нашел.
Вероятно, для того чтобы сделать динамическое изменение стана ГГ, без правок в движке не обойтись. Надеюсь, что это будет добавлено в грядущем патче от БМС.
Спасибо за ответ. С этой функцией вообще много странностей. К примеру, при выводе логов для нпс всё выводится корректно, а вот если поставить принудительный вызов эвента каждый фрейм для ГГ, то для него в логах будет выводиться попеременно истина и ложь, без повторений. То есть, даже если вероятность значения "истина" равна одной десятитысячной, на экран будет выведено только одно сообщение "ложь" (а не тысячи подряд), а следующее за ним будет обязательно "истина", пусть и через заметный промежуток времени, и сразу опять "ложь".
Также наблюдается проблема с проверкой условий типа (chr == GetMainCharacter()) - они просто пробрасываются, автоматически считаясь в этой функции за истинные. Мало того, если условие объединено логическим оператором && с другим, пробрасываются оба условия. При этом условие типа (sti(chr.index) == GetMainCharacterIndex()) обрабатывается нормально. Я понимаю, что ресурсы для вызова этих функций требуются разные, но вместо ошибки памяти или тормозов вся строчка if просто игнорируется.

То, что в случае ГГ эта функция после загрузки локации уже ни на что не влияет, ещё объяснимо: возможно, "загрузочное" значение перезаписывается в другую переменную, и в дальнейшем при обработке эвента на получение удара берётся уже оттуда. Но получается, этот эвент с MainCharacter в принципе не дружит и что-то там лочит, вызывая, например, помимо этой функции ещё и ряд других, прописанных в движке.
Цитата

Я тогда заметил, что NPC_Event_EnableStun действует на анимации hit_attack и hit_fire, но не действует на hit_feint. Но поиск по скриптам, опять же, ничего не дал.
Ну да, это анимации, вызов которых происходит где-то в движковой части. Тут даже для функции расчёта возможности стана свой эвент прописан.
Цитата

Там рядом еще был момент интересный, связан с распределением атакующих весов для NPC. Эти функции опрашиваются разово при загрузке локации, для всех персонажей в локации (включая ГГ) То есть, если ваш абордажник зайдет в локацию с топором, ему будут прописаны веса согласно chr_ai.fencingtype = FencingH. Если после этого вы оденете ему рапиру и вступите в бой, до смены локации абордажник будет намахивать шпагой как топором.
Вот этой особенности не заметил, спасибо)
Цитата
Интересно, что в ККС "fast" - это рубящие атаки, а "force" - атаки выпадом.
При расчете дамага это учтено, а здесь выходит, что саблист - самый часто колющий NPC.
Думаю, это обычная ошибка или недоработка. Эта функция вообще особо ни к чему реальному не привязана. Она не определяет оптимальный тип удара, не проверяет ни параметры оружия, ни что-либо ещё, только тип оружия, да ещё и близко не с теми коэффициентами, что указаны в формулах урона. До ККС у оружия не было профильного типа удара, поэтому и учитывать было нечего, были только базовые значения 20/50/20/20/10 и ничего не меняющая привязка к сложности.

В коде есть ещё пара мест, странным образом привязывающих тип клинка к непрофильному удару. Например, перк HardHitter, дающий бонусы выпадам для СТ и рубящим для РШ. Хотя, может, таким образом хотели отвести внимание игроков от профильных ударов? Чтобы, мол, игрок мог выбрать, потратить свою энергию на нанесение урона рубящим ударом или на снятие 10% энергии противника выпадом практически без урона. Ну, по такой логике можно и преобладание выпадов для нпс-саблистов обосновать тем, что это и так самый быстрый удар, а подкреплённый высоким уровнем навыка и хорошим клинком, ещё и с увеличенной вероятностью от ГГ просто куски мяса отрезать будет.
Цитата

У саблиста сумма весов на треть больше, чем у других классов.
Тестировал на даньке с анимацией К3/КСМ, т.к. на дефолтной анимации нельзя просто взять и отличить колющий от рубящего.
Сумма весов ни на что особо не влияет, такая система обычно используется для более удобного задания соотношений связанных общей суммой параметров. На реальные проценты выпадения влияет именно соотношение весов. И 100 из 200, и 150 из 300 приведутся к 50% - никакой разницы математически нет.
Цитата

Может быть, есть знающий человек, кто сможет подсказать как работают эти веса?
Ну, программировал их, судя по всему, AlexusB, так что теоретически он мог бы прояснить нам абсолютно всю базу. Но пока он не ответил, могу выложить свою статистику. Расчётный вес немного не соответствует наблюдаемым соотношениям в самой игре, очевидно, где-то ещё в движке дообрабатываясь. У меня, например, получилась такая картина с учётом типа оружия и уровня энергии атакующего персонажа (прошу прощения, спойлеров на форуме не нашёл):
Изображение
Эта статистика (также прошу прощения за вырвиглазное оформление, у меня на тот момент гигнулся d3d8, поэтому я быстренько перенастроил вывод на стандартные переменные) вызывает пару вопросов.

Во-первых, при низком (<=20%) уровне энергии идёт резкое преобладание выпадов. Это можно объяснить тем, что выпад тратит меньше энергии, поэтому в ситуации, когда для остальных ударов энергии ещё недостаточно, их использование пробрасывается, тогда как выпавшие выпады (невольный каламбур) спокойненько проходят. Также каждую секунду желание (то есть, вероятность) атаковать возрастает (в зависимости от навыка владения оружием, кстати), поэтому очередь выпада если и пропускается, то крайне редко. А ещё есть небольшая вероятность (8,6%), что при невозможности добраться до близкой цели нпс наугад совершит выпад, что тоже может влиять на мою статистику.

Во-вторых, соотношения ударов для остальных уровней энергии хоть и идут весьма ровно, но всё равно отличаются от теоретических значений в пользу выпадов для РШ и пробивающих для ПТ. Для наглядности я скомпоновал данные в процентах для энергии >20%, а в скобках привёл теоретические вероятности:
РШ рубящий - 42% (51%), выпад - 48% (42%), пробивающий - 10% (7%);
СТ рубящий - 8% (11%), выпад - 82% (80%), пробивающий - 10% (9%);
ПТ рубящий - 6% (10%), выпад - 45% (45%), пробивающий - 49% (45%).
В процентах разница небольшая, но для выборки в пару тысяч ударов каждым типом оружия это всё же ощутимо. Можно было бы попытаться объяснить это заложенным преимуществом для "родного" типа удара, если бы не удручающая статистика по СТ, где никакого бонуса для рубящего удара нет и в помине. Что, конечно, тоже может объясняться ошибкой перепутывания fast и force, но сколько можно на это сваливать)
В любом случае, либо я просто недостаточно стоял под градом ударов в Ле Франсуа, либо чего-то не учёл, либо эти функции для определения веса - ещё не всё, что влияет на выбор удара (хоть и имеют явно определяющее значение).
Однако в целом всё довольно понятно, хоть и жаль, что реально вызывается только при загрузке локации. Будет время, поменяю формулы на заготовленные (с показательной функцией для сложности) и ещё попроверяю.

Да, всё описанное - моё имхо, и я вполне могу ошибаться в любом из своих выводов, так что людей, реально знающих то, что я лишь предполагаю, призываю не серчать, а объяснить мне мою ошибку.
AVL
Доброго времени суток!

Крик о помощи. smile.gif
Опытные и бывалые, помогите, пожалуйста, неофиту. Мой вопрос в теме КВЛ.

P.S. Прошу модераторов и админов простить меня за оффтоп - поиск у меня почему-то не работает, личное сообщение тоже отправить не смог. То ли не разобрался, то ли у меня эти функции не работают. Поэтому нашёл живую тему и запостил здесь.
Очень прошу не убивать этот пост сразу, потерпеть его пару дней - за это время, надеюсь, кто-нибудь подскажет мне в той теме.
Спасибо.
Verdugo
Цитата

Также наблюдается проблема с проверкой условий типа (chr == GetMainCharacter()) - они просто пробрасываются, автоматически считаясь в этой функции за истинные.

Если честно, не понимаю, как это должно работать. ref GetMainCharacter возвращает ссылку на characters[1].
Цитата

int CreateEntity(object& object_reference, string class_name); // bind entity to object, return 0 if failed
Code send entity id "i" to script and it cames as aref variable into script (GetEventData())

А что такое chr? В syntax.txt написано, что id сущности, (связанной с объектом characters, по всей видимости) поступающий в скрипты как aref GetEventData().
Можно ли их вообще проверять на равенство?
Цитата

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

Когда тестировал, все гадал - учитывается ли значение для кругового удара, если противник один. Или же он до расчета не допускается вообще.
Цитата

В любом случае, либо я просто недостаточно стоял под градом ударов в Ле Франсуа, либо чего-то не учёл, либо эти функции для определения веса - ещё не всё, что влияет на выбор удара (хоть и имеют явно определяющее значение).

Я так досконально не тестировал.) Мне хотелось, чтобы данька научилась махать стортой как следует. По дефолту она машинку зингер включает. biggrin.gif
И чтобы NPC с топорами/секирами не атаковали выпадом. Пока так оставил:

feint - - break - - thrust - - cut - - round

FencingL - - 15 - - 15 - - 60 - - 10 - - "10"

FencingS - - 10 - - 30 - - 10 - - 50 - - "10"

FencingH - - 10 - - 40 - - 25 - - 25 - - "10"

Axe Type - - 10 - - 50 - - 00 - - 40 - - "10"


CODE


bool is_weapon_axe(aref actor)
{
if(CheckAttribute(actor, "equip.blade"))
{
string blade_type = actor.equip.blade;
return HasSubStr(blade_type, "topor");
}
return false;
}

float pref;

//Вес выбора рубящего удара "fast", 0 - никогда не выбирать
#event_handler("NPC_Event_GetAttackWeightFast","LAi_NPC_GetAttackWeightFast");
float LAi_NPC_GetAttackWeightFast()
{
aref chr = GetEventData();
switch(chr.chr_ai.fencingtype)
{
case "FencingL": pref = 10.0; break;
case "FencingH": pref = 25.0; break;
default: pref = 50.0; break;
}
if(is_weapon_axe(chr)) pref = 40.0;
return pref;
}

/* if(chr.chr_ai.group == "player")
{
log_info(GetFullName(chr) + " - Fencing: " + XIStr(chr.chr_ai.fencingtype) +
" - Fight Level: " + FloatToString(LAi_GetCharacterFightLevel(chr),2));
log_info("is weapon axe: " + is_weapon_axe(chr));
log_info("Рубящий: " + FloatToString(pref,1));
} */

//Вес выбора колющего удара "force", 0 - никогда не выбирать
#event_handler("NPC_Event_GetAttackWeightForce","LAi_NPC_GetAttackWeightForce");
float LAi_NPC_GetAttackWeightForce()
{
aref chr = GetEventData();
switch(chr.chr_ai.fencingtype)
{
case "FencingL": pref = 60.0; break;
case "FencingH": pref = 25.0; break;
default: pref = 10.0; break;
}
if(is_weapon_axe(chr)) pref = 0.0;
return pref;
}

// if(chr.chr_ai.group == "player") log_info("Колющий: " + FloatToString(pref,1));

//Вес выбора удара "round", 0 - никогда не выбирать, если врагов <3 то удар не выбирается
#event_handler("NPC_Event_GetAttackWeightRound","LAi_NPC_GetAttackWeightRound");
float LAi_NPC_GetAttackWeightRound()
{
aref chr = GetEventData();
pref = 10.0;
return pref;
}

//Вес выбора удара "break", 0 - никогда не выбирать
#event_handler("NPC_Event_GetAttackWeightBreak","LAi_NPC_GetAttackWeightBreak");
float LAi_NPC_GetAttackWeightBreak()
{
aref chr = GetEventData();
switch(chr.chr_ai.fencingtype)
{
case "FencingL": pref = 15.0; break;
case "FencingH": pref = 40.0; break;
default: pref = 30.0; break;
}
if(is_weapon_axe(chr)) pref = 50.0;
return pref;
}

// if(chr.chr_ai.group == "player") log_info("Пробивающий: " + FloatToString(pref,1));

//Вес выбора удара "feint", 0 - никогда не выбирать
#event_handler("NPC_Event_GetAttackWeightFeint","LAi_NPC_GetAttackWeightFeint");
float LAi_NPC_GetAttackWeightFeint()
{
aref chr = GetEventData();

if(LAi_GetBladeFencingType(chr) == "FencingL") pref = 15.0;
else pref = 10.0;
return pref;
}
// if(chr.chr_ai.group == "player") log_info("Финт: " + FloatToString(pref,1));

Slayer
=== Я так досконально не тестировал.) Мне хотелось, чтобы данька научилась махать стортой как следует.===
=================================================================
ну вот я например сделал выбор ударов так - ( если я вас правильно понял)
Код
//Вес выбора удара "fast", 0 - никогда не выбирать
#event_handler("NPC_Event_GetAttackWeightFast","LAi_NPC_GetAttackWeightFast");
float LAi_NPC_GetAttackWeightFast()
{
    aref chr = GetEventData();
    if (chr.chr_ai.group == LAI_GROUP_PLAYER && chr.chr_ai.FencingType == "FencingL")// лесник . приоритет для абордажников
    {
    npc_return_tmp = 40.0 * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingL", 1.0, 3.0);
    npc_return_tmp = npc_return_tmp * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingH", 1.0, 0.5);
    npc_return_tmp = npc_return_tmp * (0.8 + (0.1 * MOD_SKILL_ENEMY_RATE));
    }
    else
    {        
    npc_return_tmp = 20.0 * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingL", 1.0, 3.0);
    npc_return_tmp = npc_return_tmp * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingH", 1.0, 0.5);
    npc_return_tmp = npc_return_tmp * (0.8 + (0.1 * MOD_SKILL_ENEMY_RATE));
    }
    return npc_return_tmp;
}
Код
//Вес выбора удара "break", 0 - никогда не выбирать
#event_handler("NPC_Event_GetAttackWeightBreak","LAi_NPC_GetAttackWeightBreak");
float LAi_NPC_GetAttackWeightBreak()
{
    aref chr = GetEventData(); // лесник приоритет для абордажников
    if (chr.chr_ai.group == LAI_GROUP_PLAYER && GetCharacterEquipByGroup(chr, BLADE_ITEM_TYPE) == "topor_01" || GetCharacterEquipByGroup(chr, BLADE_ITEM_TYPE) == "topor_02" ||
         GetCharacterEquipByGroup(chr, BLADE_ITEM_TYPE) == "topor_03" || GetCharacterEquipByGroup(chr, BLADE_ITEM_TYPE) == "topor_04" ||
         GetCharacterEquipByGroup(chr, BLADE_ITEM_TYPE) == "topor_05" || GetCharacterEquipByGroup(chr, BLADE_ITEM_TYPE) == "topor_06")    
    {
    npc_return_tmp = 100.0 * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingH", 1.0, 3.0);
    npc_return_tmp = npc_return_tmp * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingL", 1.0, 0.5);
    npc_return_tmp = npc_return_tmp * (0.6 + (0.1 * MOD_SKILL_ENEMY_RATE));
    }    
    else
    {    
    npc_return_tmp = 40.0 * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingH", 1.0, 3.0);
    npc_return_tmp = npc_return_tmp * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingL", 1.0, 0.5);
    npc_return_tmp = npc_return_tmp * (0.6 + (0.1 * MOD_SKILL_ENEMY_RATE));
    }
    return npc_return_tmp;
}
Stor
Цитата
Если честно, не понимаю, как это должно работать. ref GetMainCharacter возвращает ссылку на characters[1].
А что такое chr? В syntax.txt написано, что id сущности, (связанной с объектом characters, по всей видимости) поступающий в скрипты как aref GetEventData().
Можно ли их вообще проверять на равенство?

Интересное предположение. Вообще как только мы обращаемся к уже определённой ссылке, мы обращаемся к объекту напрямую. И если сущность связана с объектом, то при проверке на равенство ссылок на них должна выводиться истина, поскольку адрес объекта одинаковый. Честно говоря, не вижу никаких препятствий сравнивать их адреса.
В chr же явно записывается ссылка не на конкретный атрибут id, а на сам объект, иначе проверка на равенство дочерних атрибутов тоже выдавала бы ошибку. Да и в других местах такое сравнение работает, проблемы возникают только при слишком частом обращении, как я понял. Например, можно поставить в LAi_CharacterAttack() в файле LAi_events следующие строчки:
CODE
void LAi_CharacterAttack()
{
aref attack = GetEventData();
aref enemy = GetEventData();
if (attack == GetMainCharacter())
{
Log_SetStringToLog("Атакует ГГ");
}
...
}

- и этот лог будет действительно выводиться только при атаке ГГ.
Если бы сравнение было в принципе некорректным, могла бы выползти ошибка или автоматом выдавалась бы ложь, но вместо этого вся строчка с if пропускается вообще. Хотя это может быть особенностью Шторма.
Полагаю, что это пояснение насчёт id сущности говорит только о том, что происходит до действия функции GetEventData(), а в ней ссылка на id преобразуется в ссылку на сам объект. Единственное, странно, что в таких случаях используется aref, а не ref, потому что синтаксис такого не допускает.

Цитата
Когда тестировал, все гадал - учитывается ли значение для кругового удара, если противник один. Или же он до расчета не допускается вообще.

Никакой практической разницы между этими подходами нет. Соотношение весов остальных ударов будет одинаковым, а следовательно, и теоретическая вероятность их выпадения. Если ты, например, вытягиваешь из колоды карты по одной и говоришь какое-то отдельное слово для каждой конкретной масти, а для бубновых карт никаких действий нет, то на выходе последовательность произнесённых слов будет одинаковой вне зависимости от того, есть ли бубновые карты в колоде.
Так что любая реализация - сначала вычисляется вес кругового, потом проверяется количество противников, или сначала проверяется количество противников, и в случае истины вычисляется вес кругового - ведёт к одинаковому результату.


Цитата
Я так досконально не тестировал.) Мне хотелось, чтобы данька научилась махать стортой как следует. По дефолту она машинку зингер включает. biggrin.gif
И чтобы NPC с топорами/секирами не атаковали выпадом. Пока так оставил:

feint - - break - - thrust - - cut - - round

FencingL - - 15 - - 15 - - 60 - - 10 - - "10"

FencingS - - 10 - - 30 - - 10 - - 50 - - "10"

FencingH - - 10 - - 40 - - 25 - - 25 - - "10"

Axe Type - - 10 - - 50 - - 00 - - 40 - - "10"

Я ещё изрядно потестировал это дело и выявил все проблемы своей предыдущей статистики. Дело в том, что я вёл учёт ударов на этапе вычисления урона, поэтому удары, не пришедшиеся в хитбокс, не учитывались. А в гуще сражения это приводило к тому, что у противников, стоящих на небольшом расстоянии от цели, рубящие удары немного не доставали до ГГ и не входили в статистику, тогда как выпады и пробивающие доставали и проходили. Также сыграло роль то, что я стоял в окружении врагов с убранным в ножны оружием. При этом физический размер уменьшается, и бывают случаи, когда противник одним пробивающим или выпадом задевал сразу ГГ и стоящего за ним коллегу - в итоге для этих типов ударов засчитывалось сразу два попадания подряд. И ещё одна проблема заключалась в том, что в момент первоначальной генерации персонажей их оружие автоматически считается за среднее, и только повторная загрузка локации присваивала каждому персонажу его действительный расчётный вес.
Как только я от этих проблем избавился, то статистика по рубящим, пробивающим и выпадам сразу стала соответствовать матожиданию)

А для себя лично я ввёл систему, которая, во-первых, отталкивается от реальных формул урона и пытается вычислить самый эффективный тип удара, во-вторых, с повышением уровня сложности учитывает всё больше влияющих на урон факторов, и, в-третьих, с увеличением сложности увеличивает относительный вес более эффективных ударов, чтобы персонажи чаще пользовались ими. Раньше модификаторы уровня сложности не работали, поскольку являлись множителями (и, соответственно, не изменяли соотношение весов), и я сделал их показателями степени. Также я ради интереса поменял оптимальные значения баланса в формулах на когда-то упомянутые 0.0-0.35-1.2-1.65-2.0.

CODE
float LAi_NPC_GetAttackWeightForce()
{
aref chr = GetEventData();
npc_return_tmp = 100.0;
ref blade = ItemsFromID(GetCharacterEquipByGroup(chr, BLADE_ITEM_TYPE));
float degDifficulty = 1.0 + 0.1*MOD_SKILL_ENEMY_RATE; // ВП - 1.2, ОП - 1.4, СФ - 1.6, БК - 1.8, ОК - 2.0
float kFencingType = 1.0;
float kLengthCurve = 1.0;
float kBalance = 1.0;
float kPerk = 1.0;
float kItem = 1.0;
if (MOD_SKILL_ENEMY_RATE >= 4)
{
kFencingType = kFencingType * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingS", 1.0, 0.6);
kFencingType = kFencingType * LAi_NPC_GetAttackPreferenceWeight(chr, "FencingH", 1.0, 0.5);
}
// if (MOD_SKILL_ENEMY_RATE >= 6)
// {
// if(CheckCharacterPerk(chr, "<название способности, влияющей на урон выпадом>"))
// {
// kPerk = kPerk*<эффект способности>;
// }
// }
if (MOD_SKILL_ENEMY_RATE >= 8)
{
kLengthCurve = stf(blade.lenght) / stf(blade.curve);
}
if (MOD_SKILL_ENEMY_RATE == 10)
{
kBalance = 1.25 - abs(stf(blade.Balance) - 0.35) * 0.3;
// if(IsEquipCharacterByArtefact(chr, "<название предмета, влияющего на урон выпадом>"))
// {
// kItem = kItem*<эффект предмета>;
// }
}
npc_return_tmp = npc_return_tmp*pow(kFencingType*kPerk*kLengthCurve*kBalance*kItem, degDifficulty); // возведение коэффициентов в степень degDifficulty
return npc_return_tmp;
}
Leviafan
На гитхабе опубликовали исходники Storm 2

https://github.com/storm-devs/storm-engine
tislic
Сижу и думаю, на сколько реально перекомпилировать его понятный для андроида формат
ALexusB
В доработок шансы никакие, Андройд не виндовый же, там нет ДЛЛ, нет ДиректХ
Это графический двиг писать новый (а он как быть есть - Юнити)
А вот туда портировать можно, но тоже сложно.
navy
Эх красота... Надо хоть посмотреть)) Как это изнутри все было...
Thorgal
Подскажите, как изменить высоту камеры за конкретным кораблем? Пробовал сам - не нашел. Хотя бы примерно, где искать? Конечно есть колесо мыши, но каждый раз лихорадочно крутить его такое себе удовольствие...
Slayer
Всем привет! кто может знать - есть ли функция такая чтобы телепортировать корабль с ГГ из любой точки глобы в опред. точку в море ? DoQuestReloadToLocation портирует лишь на сушу, Group_SetAddress портирует группы врагов/друзей ГГ. а самого ГГ как?
ALexusB
Есть методы скакать по локациям через таверну - в читах было. Корабль при этом в порту.
Переход в море с карты идет перекладкой координат карты в море.
В море у локаций суши есть локаторы, где можно поставить корабль (группа главного и локатор для нее)
См как сделано доплыть до - и делай как там.
Метода нарисовать корабли именно на глоб какрте - нет, только через сушу, переход в море и локаторы там.
Но если есть исходники ядра (раздавали аддон-тимам как-то), то там можно свое для карты написать.
Slayer
Цитата(ALexusB @ Jan 9 2023, 19:37) *

См как сделано доплыть до - и делай как там.

спасибо! понял. Я тоже подумал о "доплыть до" . .. Если что - буду проще делать - с суши.
Thorgal
Как реально уменьшить урон парусам? Пробовал в initGoods снижать урон книппелям (и прочим снарядам) по парусам до нуля. Все равно паруса рвутся и убывает процент SP.
sergo-kon
А там в ини хп у парусов есть? Или у мачт?
Может им стоит хп накрутить?
Или там урон в процентах а не в единицах?
ALexusB
Все иниты товаров работают только с новой игры
Конкретно у паруса возможно нет действия урона через скрипты
Там в ядре определяются реальные дырки с пересечением паруса и от них идёт урон в процентах
Ты все технические характеристики паруса на самом деле фикция
Влияет размер текстуры паруса конкретной модели
Thorgal
Цитата(ALexusB @ Jul 16 2023, 12:21) *

Конкретно у паруса возможно нет действия урона через скрипты
Там в ядре определяются реальные дырки с пересечением паруса и от них идёт урон в процентах
Ты все технические характеристики паруса на самом деле фикция
Влияет размер текстуры паруса конкретной модели

Спасибо! Тогда нет смысла тратить на это время.
Thorgal
Делаю для себя сборку на базе ККС 1.7.3 Возникла неприятная проблема с минами. А именно за мгновение перед подрывом фатальной/финальной для корабля мины игру вышибает на рабочий стол. То есть даже анимация взрыва не успевает начаться. Форштевень наезжает на мину и все. Скажем кораблю для полного потопления надо три мины. Первые две отрабатывают нормально, взрывы, разлетаются частицы, все как положено. А последняя - вылет. В случае с тартаной, например, вылет происходит сразу, поскольку на тартану требуется всего одна мина. Логи ничего путного по этому факту не показывают. В каком направлении копать ума не приложу... До этого собирал ту же сборку на 1.6.0 все было в полном порядке.
ALexusB
Ну найти где мина делает урон и напихать туда логов. И для последней мины может какие-то эффекты отлключить.
Мины делал я сам для КВЛ 1.2.3 ХардкорЕдишн. Там все ок
в ККС лучше к авторам, что-то навертели, может какие-то эффекты взрывов. Нет партиклов и падает игра.
Thorgal
Цитата(ALexusB @ Jul 20 2023, 10:23) *

Ну найти где мина делает урон и напихать туда логов. И для последней мины может какие-то эффекты отлключить.
Мины делал я сам для КВЛ 1.2.3 ХардкорЕдишн. Там все ок
в ККС лучше к авторам, что-то навертели, может какие-то эффекты взрывов. Нет партиклов и падает игра.

Да, в КВЛ и ГПК с минами полный порядок.
Буду пробовать. Хотя для моего скила это, как искать черную кошку в темной комнате...
Slayer
Цитата(Thorgal @ Jul 15 2023, 23:17) *

Как реально уменьшить урон парусам? Пробовал в initGoods снижать урон книппелям (и прочим снарядам) по парусам до нуля. Все равно паруса рвутся и убывает процент SP.

а по перке " увеличенные повреждения парусам" не искал? вот она SailsDamageUp смотри в файле .................PROGRAM\battle_interface\BattleInterface.c её условие работы .
Код

if( CheckOfficersPerk(shoot_chr,"SailsDamageUp") )    { fDmgRig *= 1.15; }

надо найти переменную fDmgRig , где ей задается начальное значение без перки и там дописать уже свою формулу.
ALexusB
Если менять параметр урона на ядрах/книппелях - то эффект будет только с новой игры, т.к. инит 1 раз на старте
нужно сделать чит присвоения нового параметра, чтоб заработало на новом сейве
Slayer
Цитата(ALexusB @ Mar 28 2024, 15:06) *

Если менять параметр урона на ядрах/книппелях - то эффект будет только с новой игры, т.к. инит 1 раз на старте
нужно сделать чит присвоения нового параметра, чтоб заработало на новом сейве

вот не советую вообще менять данные параметры. Это фундамент, протестированый годами уже и кучей тестеров. Тем более если трогать урон ядрами, то "до свидания" штурм фортов .. Их то обычно ядрами мочим с расстояния.................. Я лишь предлагаю fDmgRig пересчитать/дополнить просто новой формулой, если уж ему совсем надо уменьшать урон парусам. Просто если перкой можно увеличить, то при каком то условии можно и уменьшить. И это для текущей игры скорей всего уже.
ALexusB
Это баланс, проверенный годами и все эти параметры ставил я сам в 2004г smile.gif
Так что - может кому и не нужно менять. А мне можно, если я сочту это нужным!
Как раз сейчас переношу в ПКМ баланс из ВМЛ и как раз эти самые параметры
Но да, я их делаю, как было, а не какие-то левые цифры, чтоб потом тестить часами, что уже работало.
Slayer
Цитата(ALexusB @ Mar 28 2024, 17:11) *

А мне можно, если я сочту это нужным!

Понятное дело что Вам можно , ибо Вы - отец корсаров ). А вот другие если там будут делать что то . то вряд ли сами поймут что они делают. В их числе и я тоже. Поэтому остальным трогать не надо эти параметры. Именно остальных я и имел ввиду . кроме Вас, конечно.
-------------------------------------------------------------------
Видел Вас в лице разработчика новой группы "BMS". Как разработка? интересно там?
ALexusB
Я пока форму восстанавливаю, как спринтер перед забегом.
Т.к. не помнил уже, только в теории, что такое делал когда-то сам и знаю где код посмотреть ( в ВМЛ/КВЛ)

Вот неделю кодю для ПМК... делаю ВМЛ ++
Не факт что прям 1 в 1 (ВМЛ же есть и работает)
А скорее что-то среднее.
Пока просто эволюция ПКМ до играбельной версии, которой она не была на релизе.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.
Invision Power Board © 2001-2024 Invision Power Services, Inc.