Джагг (17ur) wrote,
Джагг
17ur

  • Mood:
  • Music:

Напильник для леди Арибет.

Если для Вас буквосочетания NwN HotU и BioWare Aurora Neverwinter Nights Toolset ни о чём не говорят, тогда не читайте, не мучайте мозги.

Купил себе DVD NwN Platinum Edition (2200 в Озоне, доставка месяца полтора по Москве, ибо из-за океана). Прошёл насквозь за реакционного клерикала, который Lawful Good, ибо намеренно подлостей почему-то никогда не делаю даже в играх - противно как-то... Это и есть нравственное чувство, хех. И ещё скромность.

Platinum-то оно Platinum, версия 1.638048. Назвать как угодно можно! Вспомнился старый советский анекдот про то, как по новейшим чертежам всё никак не могли собрать ракету - получался то танк, то паровоз, пока умудрённый опытом дядя Вася не разрешил сомнения, показав на строчку мелким шрифтом внизу инструкции: "После сборки обвести по контуру напильником". Так вот, о напильнике применительно к NwN HotU, той самой версии 1.638048.

Открываем тулсетом ...\NWN\nwm\xp2_chapter3.nwm, не забыв предварительно снять с него атрибут рид-онли. Про бэкап тоже не забывайте, я не Господь, за всё не отвечу. Там ищем скрипт h7c_name_pclov10, открываем его и смотрим на строчки 40-ю и 60-ю, где сидит условие iAribethRomance == 1. Заменяем на iAribethRomance == 2 и сохраняем. Потом ищем скрипт hx_ari_romance_1 и заменяем там iRomance == 1 на iRomance == 2. Это МНВ, по товарищу Азимову. В других случаях пришлось бы писать отдельные скрипты, так как авторы внаглую экономили умственные усилия.

В чём штука? В NwN HotU, как и во всех Faerun-сериях прописана the love. Прописана, не буду кривить душой, убого - единственный сколько-нибудь веристичный рОман во всех RPG, виденных мною, есть Вика в BGII и BGII TOB (я мню себя большим специалистом в фэнтези-мирах - в достаточной мере, чтобы бронированные шипастые лифчики и воинственный визг вызывали у меня чувство брезгливого недоумения). Условие iAribethRomance == 1 а) не выполняется, б) ведёт к тому, что если герой сосредоточенно кадрит окружающий женский пол в количестве полутора штук, - одна женщина и один призрак - то при определении своей "истинной любви" - есть там такой момент - он в обязательном порядке получает либо шиш, либо малопонятного журавля в небе, но ни одну из этих дам, что убивает многие варианты концовки. Вот как хотите, а я думаю, это хамская феминистская выходка кого-то из создателей игры. Тем более, что в последнем диалоге прописана возможность заполучить обеих дам одновременно, хех.

А вот байда с последним диалогом на 16-м пересечении - это нечто! Я такого даже в школе не писал, на БК0010Ш. Тоже вырубает вполне себе объявленные опции напрочь. Я переписал функцию PickHenchman в скрипте x2_lasttalk почти полностью. Теперь там имеют шансы проявиться все разрешённые в данной версии диалоги - раньше этого не было. Тестировано.

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

Ниже специально для пиратов и кулибиных приводится переписанный вариант скрипта x2_lasttalk. Я хоть и лицензированный юзер, но, простите, двигать на официальные сайты и помогать разгильдяям, которые поставляют некачественный продукт, не хочу. Насчёт ранешних версий - там это вроде тоже должно сработать, на случай несовпадения имён скриптов напоминаю, что x2_lasttalk висит на триггере перед последней дверью в родной мир, h7c_name_pclov10 вызывается из разговора с Knower of Names и определяет её ответ герою насчёт его "истинной любви" (хех), hx_ari_romance_1 висит в последнем разговоре с Aribeth на одном из её ответов.

В заключение позвольте-таки мне похвастаться тем, что убил я на всё это примерно 6 часов, на Си до того *не программировал* (и дальше не собираюсь). Так что влезу я на один из мраморных крестов на своём кладбище талантов и буду выть в ночи, модулируя сладкозвучную песнь героическим биением себя в могучую грудь...

А потом распишу (и допишу!) концовки в HotU, а то кое-что ребята из Wizards of the Coast убрали, а оставшееся, случается, противоречит друг другу. Скажем, по Мефистофелю надо минимум 10 концовок, а по главному герою - 7.

Кстати, кстати... в сложенном виде помянутый модуль всего-то 1,15 Мб. Обдумать.

/::///////////////////////////////////////////////
//:: x2_lasttalk
//:: Copyright (c) 2003 Bioware Corp.
//:://////////////////////////////////////////////
/*
This is the last trigger where
henchmen will talk to you, right
before the return to Waterdeep.

if Valen Romance [Valen romance > . Valen still henchman]
or
if Aribeth Romance
or
If Nat Romance
else
Random

*/
//:://////////////////////////////////////////////
//:: Created By: Brent
//:: Created On: October 30, 2003
//:: PickHenchman function changed by 17ur (seventeen ugly raccoons)
//:: Changed on: March 8, 2005
//:://////////////////////////////////////////////
#include "x2_inc_banter"


// * This function returns the correct henchman (yeah, yeah, NOW it returns - 17ur)
object PickHenchman(object oMaster)
{
object oHench = OBJECT_INVALID;
// * Get and check variables
int nValenRomanceValue = GetLocalInt(GetModule(), "iValenRomance");
int nAribethRomanceValue = GetLocalInt(GetModule(), "iAribethRomance");
int nNathyrraRomanceValue = GetLocalInt(GetModule(), "iNathyrraRomance");
int bInLoveWithValen = FALSE;
int bInLoveWithAribeth = FALSE;
int bInLoveWithNathyrra = FALSE;

// Well, you may compare these yourselves. I commented out old version - 17ur

// if (nValenRomanceValue > 0)
// {
// bInLoveWithValen = TRUE;
// }
// else
// if (nNathyrraRomanceValue > 0)
// {
// bInLoveWithNathyrra = TRUE;
// }
// else
// if (nAribethRomanceValue > 0)
// {
// bInLoveWithAribeth = TRUE;
// }
//
// * Valen, then Aribeth, then Nath
// if (bInLoveWithValen == TRUE)
// {
// object oValen = GetObjectByTag("x2_hen_valen");
// if (GetIsObjectValid(oValen) && GetMaster(oValen) == oMaster)
// {
// oHench = oValen;
// }
// }
// else
// if (bInLoveWithAribeth == TRUE)
// {
// object oAribeth = GetObjectByTag("H2_Aribeth");
// if (GetIsObjectValid(oAribeth) && GetMaster(oAribeth) == oMaster)
// {
// oHench = oAribeth;
// }
// }
// else
// if (bInLoveWithNathyrra == TRUE)
// {
// object oNathyrra = GetObjectByTag("x2_hen_nathyra");
// if (GetIsObjectValid(oNathyrra) && GetMaster(oNathyrra) == oMaster)
// {
// oHench = oNathyrra;
// }
// }

// * choose a random hench to speak
// else
// {
// oHench = GetRandomHench(oMaster, "x2_inter_nr");
// }
// return oHench;

// And my version: correct one - 17ur

if (nValenRomanceValue > 0)
{
bInLoveWithValen = TRUE;
}
// in love with PC, one girl or both
else
if (nAribethRomanceValue > 0 || nNathyrraRomanceValue > 0)
{
if (nNathyrraRomanceValue > 0)
{
bInLoveWithNathyrra = TRUE;
}
if (nAribethRomanceValue > 0)
{
bInLoveWithAribeth = TRUE;
}
}
// Valen
if (bInLoveWithValen == TRUE)
{
object oValen = GetObjectByTag("x2_hen_valen");
if (GetIsObjectValid(oValen) && GetMaster(oValen) == oMaster)
{
oHench = oValen;
}
}
else
// only Aribeth
if (bInLoveWithAribeth == TRUE && bInLoveWithNathyrra == FALSE)
{
object oAribeth = GetObjectByTag("H2_Aribeth");
if (GetIsObjectValid(oAribeth) && GetMaster(oAribeth) == oMaster)
{
oHench = oAribeth;
}
}
else
// only Nathyrra
if (bInLoveWithNathyrra == TRUE && bInLoveWithAribeth == FALSE)
{
object oNathyrra = GetObjectByTag("x2_hen_nathyra");
if (GetIsObjectValid(oNathyrra) && GetMaster(oNathyrra) == oMaster)
{
oHench = oNathyrra;
}
}
else
// both in love so choose randomly between them
if (bInLoveWithNathyrra == TRUE && bInLoveWithAribeth == TRUE)
{
int iChooseBetweenAandN = Random(2);
object oNathyrra = GetObjectByTag("x2_hen_nathyra");
object oAribeth = GetObjectByTag("H2_Aribeth");
//if Nathyrra in love and here and chosen
if (iChooseBetweenAandN == 1 && (GetIsObjectValid(oNathyrra) && GetMaster(oNathyrra) == oMaster))
{
oHench = oNathyrra;
}
else
//if Aribeth in love and here and chosen
if (iChooseBetweenAandN == 0 && (GetIsObjectValid(oAribeth) && GetMaster(oAribeth) == oMaster))
{
oHench = oAribeth;
}
else
// if Aribeth is chosen, but invalid - check if Nathyrra can be chosen instead
if (iChooseBetweenAandN == 0 && (GetIsObjectValid(oAribeth) == FALSE || GetMaster(oAribeth) != oMaster))
{
if (GetIsObjectValid(oNathyrra) && GetMaster(oNathyrra) == oMaster)
{
oHench = oNathyrra;
}
else
//both girls in love but both invalid so chose random henchPERSON heh and go back
{
oHench = GetRandomHench(oMaster, "x2_inter_nr");
return oHench;
}

}
else
// if Nathyrra is chosen, but invalid - check if Aribeth can be chosen instead
if (iChooseBetweenAandN == 1 && (GetIsObjectValid(oNathyrra) == FALSE || GetMaster(oNathyrra) != oMaster))
{
if (GetIsObjectValid(oAribeth) && GetMaster(oAribeth) == oMaster)
{
oHench = oAribeth;
}
else //both girls in love but both invalid so chose random henchPERSON heh and go back
{
oHench = GetRandomHench(oMaster, "x2_inter_nr");
return oHench;
}

}
}
else
//no one in love so choose random henchman
{
oHench = GetRandomHench(oMaster, "x2_inter_nr");
}
return oHench;
}

void main()
{ // SpawnScriptDebugger();
// * at end of this script, this is the henchman to talk to
object oHench;
object oMaster = GetEnteringObject();
if (GetIsPC(oMaster) == FALSE)
return;

if (GetIsObjectValid(GetObjectByTag("x2_homedoor")) == TRUE)
{
DestroyObject(OBJECT_SELF, 1.0);
}
else
{
return; // * the door to Waterdeep has not been created yet. Not time to speak
}
SetCutsceneMode(oMaster, TRUE);

oHench = PickHenchman(oMaster);

// *
// * Perform actual speaking
// *
if (GetIsObjectValid(oHench) == TRUE)
{
// * End of finding henchman
string sConvFile = GetDialogFileToUse(oMaster, oHench);
AssignCommand(oMaster, ClearAllActions());
AssignCommand(oHench, ClearAllActions());
AssignCommand(oHench, SetHasInterjection(oMaster, TRUE, 16));
AssignCommand(oHench, ActionStartConversation(oMaster, sConvFile));


// WrapInterjection(TRIGGER_INTERJECTION_NONRANDOM, 16, oMaster, oHench, "x2_inter_nr", FALSE, sConvFile);
}
AssignCommand(oMaster, DelayCommand(0.3, SetCutsceneMode(oMaster, FALSE)));
}

Subscribe
  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 1 comment