Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Город Мастеров _ Neverwinter Nights Aurora Toolset _ Крафт в Neverwinter Nights - а это вообще возможно?

Автор: Chiffa Nov 5 2017, 04:09

Собственно, началась тема на WRG, откуда я скачал http://www.wrg.ru/download.php?view.175. Поставил за нее десятку, и до сих пор считаю, что поступил правильно. Несмотря на все грабли, на которые наступил. Переношу сюда два последних поста с WRG, потому что в них, собственно, суть. (Продолжать обсужденние в теме на WRG, думаю, неправильно, это превращать тему "файлы" в форум.
Итак, собственно грабли:

Цитата
Записал дословно сообщение сисемы. Вот это:
"Скрипт pt_axcrf_activ OID ffffffff, Tag:, ОШИБКА СЛИШКОМ МНОГО ИНСТРУКЦИЙ
Скрипт x2_mod_def_act, OID 80000000, Tag:, ОШИБКА СЛИШКОМ МНОГО ИНСТРУКЦИЙ"
В очередной раз это произошло сразу после входа в игру. Расстроился. Дело в том, что герой как раз присел отдохнуть перед крафтом. Что ж это, прощай атмосферность? А я то разгубастился и на рискованный отдых, и на систему от Авадона с ковриками-кострами, эх!
Ладно, заменил скрипт отдыха на "родной". Снова зашел. То же самое. И тоже прям сразу.
Подумал, может проблема в хаке? Но вот хак то - курам на смех, всего то заменил четыре из бесчисленных и доставших донельзя дефолтных флагов на мокрую водичку 1х1 и 4х4 (это где герой в затопленной палубе фрегата задыхается.)
Ладно, убрал хак. Короче, все настройки - родные. Поиграл полчаса. Собщение системы то же самое.
А компилятор от обоих скриптов в восторге. Прямо тащатся от удовольствия, какие они правильные, белые и пушистые.
И еще. Если в переменной "pt_CRAFT_PROCESS_PC_CUSTOM_SCRIPT" действительно сдуру поставить какой-нибудь скрипт (даже самый простенький, с анимацией присесть когда что-то мастеришь или "говорить убедительно", когда ветку от дерева отламываешь или руду "киркой" долбишь, то скрипт запустится, но никакого крафта уже не будет.
Ставить в переменных скилы и прочие навыки не стал. Страшно...


И ответ уважаемого Aiwanа на этот пост:

Цитата
Чаще всего такое происходит, когда какой-то скрипт не отключается и постоянно выдает какие-то задания. Чаще всего это забытый новичком скрипт на хертбите НПС или модуля или триггероах. Или неккоректно сделана проверка в скрипте и он постоянно циклично работает


Aiwan, при всем уважении, нет там у меня никаких неписей, герой "адын на льдине". Для теста даже монстров не ставил. Примерно половина (минимум треть) модуля задумана как исключительно робинзонада, нет магазинов, никто ничо не подарит, все сам, все ручками, от кремневого ножа до лохмотьев и простейших зелий. Настройки модуля, как и писал, все вернул "родные", от PaiNtа. Триггер единственный, это "REST_ZONA". и сильно сомневаюсь, что он будет выдавать цикличные инструкции.

Остаются скрипты? Первый, на который жалуется система и которым восхищается компилятор, это скрипт настроек модуля "x2_mod_def_act", стоит на OnActivateltem. Вот он, целиком, совсем короткий:

Neverwinter Script
//::///////////////////////////////////////////////
//:: Example XP2 OnActivate Script Script
//:: x2_mod_def_act
//:: © 2003 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Put into: OnItemActivate Event

*/

//:://////////////////////////////////////////////
//:: Created By: Georg Zoeller
//:: Created On: 2003-07-16
//:://////////////////////////////////////////////

#include "x2_inc_switches"
void main()
{
    object oItem = GetItemActivated();

    // * Generic Item Script Execution Code
    // * If MODULE_SWITCH_EXECUTE_TAGBASED_SCRIPTS is set to TRUE on the module,
    // * it will execute a script that has the same name as the item's tag
    // * inside this script you can manage scripts for all events by checking against
    // * GetUserDefinedItemEventNumber(). See x2_it_example.nss
    if (GetModuleSwitchValue(MODULE_SWITCH_ENABLE_TAGBASE
D_SCRIPTS) == TRUE)
    {
        SetUserDefinedItemEventNumber(X2_ITEM_EVENT_ACTIVA
TE);
        int nRet =  ExecuteScriptAndReturnInt(GetUserDefinedItemEventS
criptName(oItem),OBJECT_SELF);
        if (nRet == X2_EXECUTE_SCRIPT_END)
        {
          return;
        }

    }



//Execute PaiNt activate craft-tool script
if(GetStringLeft(GetTag(oItem), 14)=="pt_craft_tool_")
    {
    object oActivator=GetItemActivator();

    SetLocalObject(oActivator, "pt_ActTool", oItem);
    SetLocalObject(oActivator, "pt_ActTarget", GetItemActivatedTarget());


    ExecuteScript("pt_axcrf_activ", oActivator);
    };
}


Смотрю на него, как известное рунное животное на известный новый плейстейбл и в упор не понимаю, чему тут зацикливаться...

Второй скрипт "pt_axcrf_activ" куда серьезней. Даже не уверен, поместится ли, но рискну таки. Вот он:

Neverwinter Script
//Óíèâåðñàëüíûé ñêðèïò àêòèâàöèè èíñòðóìåíòà

#include "pt_frame000"
#include "x3_inc_string"
#include "pt_axcrf_md_cons"






void pCreateObjectInLocal(object oTarget, string sName, int nObjectType, string sTemplate, location lLocation, int bUseAppearAnimation=FALSE, string sNewTag="")
{
SetLocalObject(oTarget, sName, CreateObject(nObjectType, sTemplate, lLocation, bUseAppearAnimation, sNewTag));
}



void main()
{
object oModule=GetModule();
object oActivator=OBJECT_SELF;
if(GetLocalInt(oActivator, "pt_curCraftProcess_Mode")) return;
object oTool=GetLocalObject(oActivator, "pt_ActTool");DeleteLocalObject(oActivator, "pt_ActTool");
object oTarget=GetLocalObject(oActivator, "pt_ActTarget");DeleteLocalObject(oActivator, "pt_ActTarget");
object oParentRawTarget;






//Î÷èñòêà äèàëîãîâûõ ïåðåìåííûõ
SetLocalInt(oActivator, "pt_craft_dialNodeArray_Length", 0);
SetLocalInt(oActivator, "pt_craft_dialTok"+IntToString(pt_CUSTTOK_NODE_ONE)+"_Index", -1);
SetLocalInt(oActivator, "pt_craft_dialTok"+IntToString(pt_CUSTTOK_NODE_TWO)+"_Index", -1);
SetLocalInt(oActivator, "pt_craft_dialTok"+IntToString(pt_CUSTTOK_NODE_THREE)+"_Index", -1);
SetLocalInt(oActivator, "pt_craft_dialTok"+IntToString(pt_CUSTTOK_NODE_FOUR)+"_Index", -1);
SetLocalInt(oActivator, "pt_craft_dialTok"+IntToString(pt_CUSTTOK_NODE_FIVE)+"_Index", -1);
SetCustomToken(pt_CUSTTOK_NODE_ONE, "");
SetCustomToken(pt_CUSTTOK_NODE_TWO, "");
SetCustomToken(pt_CUSTTOK_NODE_THREE, "");
SetCustomToken(pt_CUSTTOK_NODE_FOUR, "");
SetCustomToken(pt_CUSTTOK_NODE_FIVE, "");
SetLocalInt(oActivator, "pt_craft_dialMinI", 0);
SetLocalInt(oActivator, "pt_craft_dialMaxI", 0);
int iNumDialogNodes=-1;

//Î÷èñòêà ïåðåìåííûõ ñëóæåáíûõ ïðåäìåòîâ
SetLocalInt(oActivator, "pt_craft_dialToolIsBook", FALSE);
SetLocalInt(oActivator, "pt_craft_dialToolIsSkillStick", FALSE);
SetLocalInt(oActivator, "pt_craft_dialToolIsToolTool", FALSE);

SetLocalInt(oActivator, "pt_craft_dialToolIsRawCreateSp", FALSE);
SetLocalInt(oActivator, "pt_craft_dialToolIsRawSeeRawSp", FALSE);
SetLocalInt(oActivator, "pt_craft_dialToolIsRawSeeToolSp", FALSE);
SetLocalInt(oActivator, "pt_craft_dialToolIsRawSeeSkillSp", FALSE);
SetLocalInt(oActivator, "pt_craft_dialToolIsRawCreateSkillSt", FALSE);




//Èìÿ èíñòðóìåíòà,êîòîðûé âûçâàë ñêðèïò äëÿ äèàëîãà
SetLocalString(oActivator, "pt_craft_dialTool", GetName(oTool));

//Òàã èíñòðóìåíòà, êîòîðûé âûçâàë ñêðèïò
string sToolTag=GetTag(oTool);



/////////////////////////////////////////////
//Ñëóæåáíûå ïðåäìåòû äëÿ óïðàâëåíèÿ ñèñòåìîé

//Áîëüøàÿ êíèãà êðàôòà
if(sToolTag=="pt_craft_tool_DMbook")
    {
    SetLocalInt(oActivator, "pt_craft_dialToolIsBook", TRUE);
    }


//Áîëüøàÿ ïàëêà íàâûêîâ
    else if(sToolTag=="pt_craft_tool_DMs00")
    {
    if(GetObjectType(oTarget)!=OBJECT_TYPE_CREATURE) {FloatingTextStringOnCreature("Íå ïîäõîäÿùèé ïðåäìåò.", oActivator, FALSE); return;};

    SetLocalInt(oActivator, "pt_craft_dialToolIsSkillStick", TRUE);
    SetLocalObject(oActivator, "pt_craft_dialToolIsSkillStickTarget", oTarget);
    }


//Áîëüøàÿ ïàëêà Èíñòðóìåíòîâ
    else if(sToolTag=="pt_craft_tool_DMs10")
    {
    if(GetObjectType(oTarget)!=OBJECT_TYPE_ITEM && GetObjectType(oTarget)!=OBJECT_TYPE_PLACEABLE && GetObjectType(oTarget)!=OBJECT_TYPE_CREATURE) {FloatingTextStringOnCreature("Íå ïîäõîäÿùèé ïðåäìåò.", oActivator, FALSE); return;};

    SetLocalInt(oActivator, "pt_craft_dialToolIsToolTool", TRUE);
    SetLocalObject(oActivator, "pt_craft_dialToolIsToolToolTarget", oTarget);

    AssignCommand(oActivator, ActionStartConversation(oActivator, "pt_axcrf_main", TRUE, FALSE));
    return;
    }


/////////////////////////////////////////////////////
//Ñëóæåáíûå ïðåäìåòû äëÿ ââîäà â ñèñòåìó èíãðèäèåíòîâ

//Áîëüøàÿ côåðà òðàíñôîðìàöèè
    else if(sToolTag=="pt_craft_tool_DMs01")
    {
    if(GetObjectType(oTarget)!=OBJECT_TYPE_ITEM) {DeleteLocalObject(oActivator, "pt_craft_dialToolIsRawCreateTarget"); FloatingTextStringOnCreature("Íå ïîäõîäÿùèé ïðåäìåò.", oActivator, FALSE); return;};

    SetLocalInt(oActivator, "pt_craft_dialToolIsRawCreateSp", TRUE);
    SetLocalObject(oActivator, "pt_craft_dialToolIsRawCreateTarget", oTarget);


    //Çàäàíèå ïåðåìåííûõ äëÿ äèàëîãà
    string sRawsString=GetLocalString(oTarget, "pt_CRAFT_RAW"), sToolsString=GetLocalString(oTarget, "pt_CRAFT_TOOL"), sSkillsString=GetLocalString(oTarget, "pt_CRAFT_SKILL_ID"), sRTtempstring, sNumDialogNodes;
    int x, iRawLen=pArrayLength(sRawsString), iToolLen=pArrayLength(sToolsString), iSkillLen=pArrayLength(sSkillsString);

    iNumDialogNodes=-1;
    for(x=0; x<iRawLen; x++)
        {
        sRTtempstring=pArray(sRawsString, x);
        if(sRTtempstring=="") continue;

        iNumDialogNodes++;
        sNumDialogNodes=IntToString(iNumDialogNodes);

        SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_ItemRawTag", sRTtempstring);
        };
    iNumDialogNodes=-1;
    for(x=0; x<iToolLen; x++)
        {
        sRTtempstring=pArray(sToolsString, x);
        if(sRTtempstring=="") continue;

        iNumDialogNodes++;
        sNumDialogNodes=IntToString(iNumDialogNodes);

        SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_ItemToolTag", sRTtempstring);
        };
    iNumDialogNodes=-1;
    for(x=0; x<iSkillLen; x++)
        {
        sRTtempstring=pArray(sSkillsString, x);
        if(sRTtempstring=="") continue;

        iNumDialogNodes++;
        sNumDialogNodes=IntToString(iNumDialogNodes);

        SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_ItemSkillId", sRTtempstring);
        };

    //Çàäàíèå äëèííû ìàññèâà
    SetLocalInt(oActivator, "pt_craft_dialNodeArray_Length", iRawLen+((iRawLen<iToolLen)?abs(iRawLen-iToolLen):0));
    //debug
    //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Çàïèñü äàííûõ â ïåðåìåííûå");



    AssignCommand(oActivator, ActionStartConversation(oActivator, "pt_axcrf_main", TRUE, FALSE));
    return;
    }


//Ìàëàÿ ïàëêà ñûðüÿ
    else if(sToolTag=="pt_craft_tool_DMs02")
    {
    oParentRawTarget=GetLocalObject(oActivator, "pt_craft_dialToolIsRawCreateTarget");
    if(!GetIsObjectValid(oParentRawTarget)) {FloatingTextStringOnCreature("Âû íå âûáðàëè ïðåäìåò äëÿ ðåäàêòèðîâàíèÿ ñ ïîìîùüþ ñôåðû òðàíñôîðìàöèè.", oActivator, FALSE); return;};

    if(GetIsObjectValid(oTarget) && GetObjectType(oTarget)==OBJECT_TYPE_ITEM)
        {
        FloatingTextStringOnCreature("Ïðåäìåò äîáàâëåí â êà÷åñòâå ñûðüÿ ê '"+GetName(oParentRawTarget)+"'" , oActivator, FALSE);
        }
        else
        {
        FloatingTextStringOnCreature("Íå ïîäõîäÿùèé ïðåäìåò.", oActivator, FALSE);
        SetLocalInt(oActivator, "pt_craft_dialToolIsRawSeeRawSp", TRUE);
        AssignCommand(oActivator, ActionStartConversation(oActivator, "pt_axcrf_main", TRUE, FALSE));
        return;
        };

    //Çàäàíèå ïåðåìåííûõ äëÿ äèàëîãà
    string sRawsString=GetLocalString(oParentRawTarget, "pt_CRAFT_RAW");
    int iRawLen=pArrayLength(sRawsString);

    iNumDialogNodes=iRawLen;
    iNumDialogNodes++;
    string sNumDialogNodes=IntToString(iNumDialogNodes);

    SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_ItemRawTag", GetTag(oTarget));
    if(sRawsString!="") {sRawsString+=","+GetTag(oTarget);} else{sRawsString=GetTag(oTarget);};
    SetLocalString(oParentRawTarget, "pt_CRAFT_RAW", sRawsString);

    //Çàäàíèå äëèííû ìàññèâà
    SetLocalInt(oActivator, "pt_craft_dialNodeArray_Length", iNumDialogNodes);
    //debug
    //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Çàïèñü äàííûõ â ïåðåìåííûå");

    SetLocalInt(oActivator, "pt_craft_dialToolIsRawSeeRawSp", TRUE);
    AssignCommand(oActivator, ActionStartConversation(oActivator, "pt_axcrf_main", TRUE, FALSE));

    return;
    }


//Ìàëàÿ ïàëêà èíñòðóìåíòîâ
    else if(sToolTag=="pt_craft_tool_DMs04")
    {
    oParentRawTarget=GetLocalObject(oActivator, "pt_craft_dialToolIsRawCreateTarget");
    if(!GetIsObjectValid(oParentRawTarget)){FloatingText
StringOnCreature("Âû íå âûáðàëè ïðåäìåò äëÿ ðåäàêòèðîâàíèÿ ñ ïîìîùüþ ñôåðû òðàíñôîðìàöèè.", oActivator, FALSE);return;};

    if(GetIsObjectValid(oTarget))
        {
        FloatingTextStringOnCreature("Ïðåäìåò äîáàâëåí â êà÷åñòâå èíñòðóìåíòà ê '"+GetName(oParentRawTarget)+"'" , oActivator, FALSE);
        }
        else
        {
        FloatingTextStringOnCreature("Íå ïîäõîäÿùèé ïðåäìåò.", oActivator, FALSE);
        SetLocalInt(oActivator, "pt_craft_dialToolIsRawSeeToolSp", TRUE);
        AssignCommand(oActivator, ActionStartConversation(oActivator, "pt_axcrf_main", TRUE, FALSE));
        return;
        };
    //Çàäàíèå ïåðåìåííûõ äëÿ äèàëîãà
    string sToolsString=GetLocalString(oParentRawTarget, "pt_CRAFT_TOOL");
    int iToolLen=pArrayLength(sToolsString);

    iNumDialogNodes=iToolLen;
    iNumDialogNodes++;
    string sNumDialogNodes=IntToString(iNumDialogNodes);

    SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_ItemToolTag", GetTag(oTarget));
    if(sToolsString!="") {sToolsString+=","+GetTag(oTarget);} else{sToolsString=GetTag(oTarget);};
    SetLocalString(oParentRawTarget, "pt_CRAFT_TOOL", sToolsString);

    //Çàäàíèå äëèííû ìàññèâà
    SetLocalInt(oActivator, "pt_craft_dialNodeArray_Length", iNumDialogNodes);
    //debug
    //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Çàïèñü äàííûõ â ïåðåìåííûå");

    SetLocalInt(oActivator, "pt_craft_dialToolIsRawSeeToolSp", TRUE);
    AssignCommand(oActivator, ActionStartConversation(oActivator, "pt_axcrf_main", TRUE, FALSE));

    return;
    }


//Ìàëàÿ ïàëêà íàâûêîâ
    else if(sToolTag=="pt_craft_tool_DMs06")
    {
    oParentRawTarget=GetLocalObject(oActivator, "pt_craft_dialToolIsRawCreateTarget");
    if(!GetIsObjectValid(oParentRawTarget)){FloatingText
StringOnCreature("Âû íå âûáðàëè ïðåäìåò äëÿ ðåäàêòèðîâàíèÿ ñ ïîìîùüþ ñôåðû òðàíñôîðìàöèè.", oActivator, FALSE);return;};

    FloatingTextStringOnCreature("Ïðîèçíåñèòå èäåíòèôèêàòîð íàâûêà", oActivator, FALSE);

    SetLocalInt(oActivator, "pt_craft_dialToolIsRawCreateSkillSt", TRUE);

    return;
    }



//Ìàëàÿ ñôåðà ïðîñìîòðà ñûðüÿ
    else if(sToolTag=="pt_craft_tool_DMs03")
    {
    oParentRawTarget=GetLocalObject(oActivator, "pt_craft_dialToolIsRawCreateTarget");
    if(!GetIsObjectValid(oParentRawTarget)) {FloatingTextStringOnCreature("Âû íå âûáðàëè ïðåäìåò äëÿ ðåäàêòèðîâàíèÿ ñ ïîìîùüþ ñôåðû òðàíñôîðìàöèè.", oActivator, FALSE); return;};

    SetLocalInt(oActivator, "pt_craft_dialToolIsRawSeeRawSp", TRUE);

    AssignCommand(oActivator, ActionStartConversation(oActivator, "pt_axcrf_main", TRUE, FALSE));
    return;
    }


//Ìàëàÿ ñôåðà ïðîñìîòðà èíñòðóìåíòîâ
    else if(sToolTag=="pt_craft_tool_DMs05")
    {
    oParentRawTarget=GetLocalObject(oActivator, "pt_craft_dialToolIsRawCreateTarget");
    if(!GetIsObjectValid(oParentRawTarget)) {FloatingTextStringOnCreature("Âû íå âûáðàëè ïðåäìåò äëÿ ðåäàêòèðîâàíèÿ ñ ïîìîùüþ ñôåðû òðàíñôîðìàöèè.", oActivator, FALSE); return;};

    SetLocalInt(oActivator, "pt_craft_dialToolIsRawSeeToolSp", TRUE);

    AssignCommand(oActivator, ActionStartConversation(oActivator, "pt_axcrf_main", TRUE, FALSE));
    return;
    }


//Ìàëàÿ ñôåðà ïðîñìîòðà íàâûêîâ
    else if(sToolTag=="pt_craft_tool_DMs07")
    {
    oParentRawTarget=GetLocalObject(oActivator, "pt_craft_dialToolIsRawCreateTarget");
    if(!GetIsObjectValid(oParentRawTarget)) {FloatingTextStringOnCreature("Âû íå âûáðàëè ïðåäìåò äëÿ ðåäàêòèðîâàíèÿ ñ ïîìîùüþ ñôåðû òðàíñôîðìàöèè.", oActivator, FALSE); return;};

    SetLocalInt(oActivator, "pt_craft_dialToolIsRawSeeSkillSp", TRUE);

    AssignCommand(oActivator, ActionStartConversation(oActivator, "pt_axcrf_main", TRUE, FALSE));
    return;
    };
////////////////////////////////////////////////////
////////////////////////////////////////////////////





//////////////////////////
//Èíñòðóìåíò èçíàøèâàåòñÿ
int iMaxUses=GetLocalInt(oTool, "pt_CRAFT_PROCESS_NUMUSE");
int iCurUses=GetLocalInt(oTool, "pt_curCraftProcess_uses");
iCurUses++;
SetLocalInt(oTool, "pt_curCraftProcess_uses", iCurUses);
if(iCurUses>iMaxUses && iMaxUses>0)
    {
    //debug
    FloatingTextStringOnCreature("Ïðîöåññ íåâîçìîæåí. Ðåñóðñ èíñòðóìåíòà èñ÷åðïàí.", oActivator, FALSE);

    int iToolObjectType=GetObjectType(oTool);
    float fRespTime=GetLocalFloat(oTool, "pt_CRAFT_PROCESS_RESPTIME");
    if(fRespTime>0.0 && iToolObjectType!=OBJECT_TYPE_ITEM && iToolObjectType!=OBJECT_TYPE_TRIGGER)
        {
        string sToolResRef=GetResRef(oTool);
        object oBuoy=CreateObject(OBJECT_TYPE_PLACEABLE, "plc_invisobj", GetLocation(oTool));
        float fCurRespTime=fRespTime+IntToFloat(Random(FloatToIn
t(fRespTime)/2));

        AssignCommand(oBuoy, DelayCommand(fCurRespTime, pCreateObjectInLocal(oBuoy, "pt_curCraftProcess_buoytool", iToolObjectType, sToolResRef, GetLocation(oBuoy))));

        AssignCommand(oBuoy, DelayCommand(fCurRespTime+0.1, SetLocalInt(GetLocalObject(oBuoy, "pt_curCraftProcess_buoytool"), "pt_CRAFT_PROCESS_NUMUSE", iMaxUses)));
        AssignCommand(oBuoy, DelayCommand(fCurRespTime+0.1, SetLocalFloat(GetLocalObject(oBuoy, "pt_curCraftProcess_buoytool"), "pt_CRAFT_PROCESS_RESPTIME", fRespTime)));

        AssignCommand(oBuoy, DelayCommand(fCurRespTime+0.1, DestroyObject(oBuoy)));
        };

    DeleteLocalInt(oActivator, "pt_curCraftProcess_Mode");
    DeleteLocalInt(oActivator, "pt_curCraftProcess_ScriptMode");
    DeleteLocalLocation(oActivator, "pt_craft_PClocation");
    DestroyObject(oTool);

    return;
    };









//Øêóðà àêòèâàòîðà
object oSkin=GetItemInSlot(INVENTORY_SLOT_CARMOUR, oActivator);

//Ïîñëåäíèé èñïîëüçóåìûé èíñòðóìåíò, ìîæåò èñïîëüçîâàòüñÿ â ñêðèïòàõ ïðîöåññà.
SetLocalObject(oActivator, "pt_craft_lastUsedTool", oTool);







//////////////////////////////////////////////
///Íà÷àëî öèêëà ïîñòðîåíèÿ âîçìîæíûõ ïðîöåññîâ
//////////////////////////////////////////////
int i, k, l, m;
int iMaxIItem=GetLocalInt(oModule, "pt_CraftItemBoxArray_Length");
for(i=0; i<iMaxIItem; i++)
    {
    string sI=IntToString(i);
    DeleteLocalObject(oActivator, "pt_craft_dialNodeArray"+sI+"_Object");
    DeleteLocalString(oActivator, "pt_craft_dialNodeArray"+sI+"_ItemName");
    ///////////////////////////////////////////////////////////////////////
    object oCrftItem=GetLocalObject(oModule, "pt_CraftItemBoxArray"+sI);

    if(!GetIsObjectValid(oCrftItem)) continue;


    //Áîëüøàÿ êíèãà êðàôòà
    if(GetTag(oTool)=="pt_craft_tool_DMbook")
        {
        iNumDialogNodes++;
        string sNumDialogNodes=IntToString(iNumDialogNodes);

        SetLocalObject(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_Object", oCrftItem);
        SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_ItemName", GetName(oCrftItem));

        SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_Skills", GetLocalString(oCrftItem, "pt_CRAFT_SKILL_ID"));
        SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_SkillsVal", GetLocalString(oCrftItem, "pt_CRAFT_SKILL_VALUE"));
        SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_RawNames", GetLocalString(oCrftItem, "pt_CRAFT_RAW"));
        SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_RawCost", GetLocalString(oCrftItem, "pt_CRAFT_RAW_COST"));

        SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_ToolNames", GetLocalString(oCrftItem, "pt_CRAFT_TOOL"));

        //debug
        //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Çàïèñü äàííûõ â ïåðåìåííûå");

        continue;
        };



















///////////////////
////Ïðîâåðêà íàâûêà
    string sProcSkill=GetLocalString(oCrftItem, "pt_CRAFT_SKILL_ID");
    string sProcSkillVal=GetLocalString(oCrftItem, "pt_CRAFT_SKILL_VALUE");
    int iSkillLen=pArrayLength(sProcSkill);
    int iSkillValLen=pArrayLength(sProcSkillVal);
    int bClosedSkill=FALSE;
    for(k=0; k<iSkillLen; k++)
        {
        int iValK=(k<=(iSkillValLen-1)?k:iSkillValLen-1);

        string sSkillID=pArray(sProcSkill, k);
        sSkillID=GetStringLeft(sSkillID, 35);

        //Áîëüøàÿ ïàëêà íàâûêîâ
        if(GetTag(oTool)=="pt_craft_tool_DMs00")
            {
            int z, bHasThatSkill;
            bHasThatSkill=FALSE;
            for(z=0; z<=iNumDialogNodes+1; z++)
                {
                if(GetLocalString(oActivator, "pt_craft_dialNodeArray"+IntToString(z)+"_ItemName")==sSkillID) {bHasThatSkill=TRUE; break;};
                };
            if(!bHasThatSkill)
                {
                iNumDialogNodes++;
                string sNumDialogNodes=IntToString(iNumDialogNodes);

                SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_ItemName", sSkillID);
                };

            //debug
            //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Çàïèñü äàííûõ â ïåðåìåííûå");

            continue;
            }
            else
            {
            float fActivatorSkill=GetLocalFloat(oSkin, "pt_craft_skill_"+sSkillID+"_value");

            if(fActivatorSkill<0.0 || GetLocalInt(oSkin, "pt_craft_skill_"+sSkillID+"_DMblock")) {bClosedSkill=TRUE; break;};
            };
        };
    if(bClosedSkill) continue;
    //debug
    //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Ïðîâåðêà ñêèëà óñïåøíà.");


    //Áîëüøàÿ ïàëêà íàâûêîâ
    if(GetTag(oTool)=="pt_craft_tool_DMs00")
        {
        continue;
        };























////////////////////////////////////
////Ïðîâåðêà âûçûâàþùåãî èíñòðóìåíòà
    string sProcTool=GetLocalString(oCrftItem, "pt_CRAFT_TOOL");
    string sProcToolNames=sProcTool;
    int iToolLen=pArrayLength(sProcTool);

    string sCurToolTag=sToolTag;
    int iCurToolIndex=-1;
    for(k=0; k<iToolLen; k++)
        {
        string sToolTemp=pArray(sProcTool, k);
        if(sCurToolTag==sToolTemp || ((sProcTool=="" || sProcTool=="pt_craft_tool_") && sCurToolTag=="pt_craft_tool_")) {sProcToolNames=pArray(sProcToolNames, k, GetName(oTool)); iCurToolIndex=k; break;};
        };
    if(iCurToolIndex<0) continue;
    //debug
    //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' âûäåëèëè èíñòðóìåíò âûçîâà. ("+pArray(sProcTool, iCurToolIndex)+")");















/////////////////////////
////Ïðîâåðêà èíñòðóìåíòîâ
    int bNotHasAllTool=FALSE;
    for(k=0; k<iToolLen; k++)
        {
        int bHasTool=FALSE;

        if(iCurToolIndex==k) continue;

        string sToolTag=pArray(sProcTool, k);


        object oPlaTool=GetNearestObjectByTag(sToolTag, oActivator); //Scan near activator
        if(GetIsObjectValid(oPlaTool) && GetObjectType(oPlaTool)!=OBJECT_TYPE_ITEM && GetDistanceBetween(oPlaTool, oActivator)<=3.0) {sProcToolNames=pArray(sProcToolNames, k, GetName(oPlaTool)); bHasTool=TRUE;};
        if(!bHasTool)
            {
            int iCurItemSlot=0;
            object oActItem=GetItemInSlot(iCurItemSlot, oActivator);
            while(!bHasTool && iCurItemSlot<=17) //Scan in equipeble slots
                {
                if(GetTag(oActItem)==sToolTag) {sProcToolNames=pArray(sProcToolNames, k, GetName(oActItem)); bHasTool=TRUE; break;};

                iCurItemSlot++; oActItem=GetItemInSlot(iCurItemSlot, oActivator);
                };
            if(!bHasTool)
                {
                oActItem=GetFirstItemInInventory(oActivator);
                while(!bHasTool && GetIsObjectValid(oActItem)) //Scan in inventory
                    {
                    if(GetTag(oActItem)==sToolTag) {sProcToolNames=pArray(sProcToolNames, k, GetName(oActItem)); bHasTool=TRUE; break;};

                    oActItem=GetNextItemInInventory(oActivator);
                    };
                };
            };

        if(!bHasTool) {bNotHasAllTool=TRUE; break;};
        };
    if(bNotHasAllTool) continue;
    //debug
    //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Ïðîâåðêà îñòàëüíûõ èíñòðóìåíòîâ óñïåøíà");




































//////////////////////////////
////Ïðîâåðêà íèìåíîâàíèé ñûðüÿ
    string sProcRaw=GetLocalString(oCrftItem, "pt_CRAFT_RAW");
    string sProcRawNames=GetLocalString(oCrftItem, "pt_CRAFT_RAW");
    string sProcRawCost=GetLocalString(oCrftItem, "pt_CRAFT_RAW_COST");
    string sProcActivatorRawValue="0";

    int iRawLen=pArrayLength(sProcRaw);
    int iRawCostLen=pArrayLength(sProcRawCost);

    int bNotHasAllRaw=FALSE;
    for(k=0; k<iRawLen; k++)
        {
        string sRawTag=pArray(sProcRaw, k);

        int bHasRaw=TRUE;
        object oActItem=GetFirstItemInInventory(oActivator);
        while(GetIsObjectValid(oActItem))
            {
            if(GetTag(oActItem)==sRawTag)
                {
                sProcRawNames=pArray(sProcRawNames, k, GetName(oActItem));

                int iActRawVal=StringToInt(pArray(sProcActivatorRawVal
ue, k));
                iActRawVal+=GetItemStackSize(oActItem);
                sProcActivatorRawValue=pArray(sProcActivatorRawVal
ue, k, IntToString(iActRawVal));
                bHasRaw=TRUE;
                };

            oActItem=GetNextItemInInventory(oActivator);
            };
        if(!bHasRaw) {bNotHasAllRaw=TRUE; break;};
        };
    if(bNotHasAllRaw) continue;
    //debug
    //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Ôîðìèðîâàíèå ìàññèâà íàëè÷èÿ ñûðüÿ óñïåøíî.");















/////////////////////////////
////Ïðîâåðêà êîëè÷åñòâà ñûðüÿ

    //debug
    //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Òðåáîâàíèå ñûðüÿ: "+sProcRawCost);
    //debug
    //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Íàëè÷èå ñûðüÿ: "+sProcActivatorRawValue);
    int bNotHasAllRawQuant=FALSE;
    for(k=0; k<iRawLen; k++)
        {
        int iCostK=(k<=(iRawCostLen-1)?k:iRawCostLen-1);

        int iCurRawCost=StringToInt(pArray(sProcRawCost, iCostK));
        int iCurRawHave=StringToInt(pArray(sProcActivatorRawVa
lue, iCostK));

        if(iCurRawCost<0) iCurRawCost=1;

        if(iCurRawHave<iCurRawCost) {bNotHasAllRawQuant=TRUE; break;};
        };
    if(bNotHasAllRawQuant) continue;
    //debug
    //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Ïðîâåðêà êîëè÷åñòâà ñûðüÿ ó èãðîêà óñïåøíà.");



















/////////////////////////////////////////////////////////////////////
////Çàäàíèå ïåðåìåííûõ åñëè âñå ïðîâåðêè óñïåøíû äëÿ äàííîãî ïðîöåññà
    iNumDialogNodes++;
    string sNumDialogNodes=IntToString(iNumDialogNodes);

    SetLocalObject(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_Object", oCrftItem);
    SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_ItemName", GetName(oCrftItem));

    SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_Skills", sProcSkill);
    SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_SkillsVal", sProcSkillVal);
    SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_RawNames", sProcRawNames);
    SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_RawCost", sProcRawCost);

    SetLocalString(oActivator, "pt_craft_dialNodeArray"+sNumDialogNodes+"_ToolNames", sProcToolNames);

    //debug
    //SendMessageToPC(GetFirstPC(), "'"+GetName(oCrftItem)+"' Çàïèñü äàííûõ â ïåðåìåííûå");



    };
/////////////////////////////////////////////
//Çàäàíèå äëèííû ìàññèâà ïîëó÷åííûõ ïðîöåññîâ
SetLocalInt(oActivator, "pt_craft_dialNodeArray_Length", iNumDialogNodes+1);




/////////////////////////
//Çàïóñê äèàëîãîâîãî ìåíþ
if(iNumDialogNodes>=0) AssignCommand(oActivator, ActionStartConversation(oActivator, "pt_axcrf_main", TRUE, FALSE));
}


Собственно, это и есть универсальный скрипт активации инструмента. Думаю, уважаемый PaiNt оставил пробелы, чтобы юзер мог дописать что-то нужное конкретно ему. Но тут я понять что-то и не пытаюсь, не мой уровень. Может, кто-то из мастеров поймет?
А если нет, или просто лениво вникать, то господь с ней, с системой PaiNt_craft. Потому что тема не только и не столько о ней. Но об этом позже, и так пост раздулся, лопнет еще...

Пока писал, подумал (я уже говорил, со мной такое случается rolleyes.gif ).
Обратил внимание на строчку " ExecuteScript("pt_axcrf_activ", oActivator);" скрипта настроек модуля "x2_mod_def_act". Она же запускает главный скрипт инструмента! Тот самый, который второй и такой большой...
Может она это постоянно делать, поскольку в настройках модуля прописана? Если так, то понятно. Такого ни один грузчик не выдержит, не то что мой маленький модуль.
Однако, надо полагать, уважаемый PaiNt не просто так ее вписал... И не мог не предусмотреть какую-то "страховку" от зацикливания команды?

Автор: denis0k Nov 5 2017, 12:54

На этапе компиляции в скрипт подцепляются все инклуды, поэтому ошибка может быть как в самом скрипте, так и в его "вложениях". Слишком много инструкций - это в 99% случаев цикл с большим количеством итераций. Под большим имеется в виду реальное большое число, скорее всего это тысячи итераций (зависит от количества кода в цикле).

В нвскрипте есть защита от зацикливания. Инструкции - это базовый набор команд, на которых скриптовая машина работает - присвоение, арифметические операции, вызов функций и т.п. Лимит на количество инструкций - 131к. Это с виду много, но одним хорошим циклом его легко выработать.

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


Что касается конкретно этого скрипта - я в нём не разбирался, это долго и бессмысленно, т.к. без нвн его всё равно не проверить smile.gif Но там есть циклы for, смотри в первую очередь туда. Возможно, условие окончания цикла слишком далеко - там считывается какая-то переменная, поставь её гораздо меньше. Или она вообще у тебя отсутствует, скрипт считает её за 0 и бажит.


Что касается крафта в нвн в принципе. Я писал довольно сложные. Всё, что нужно, в нвн есть - создание итемов, навешивание на них свойств. Сложность только с изменением внешнего вида сложных итемов (это можно, но гемор), но тут можно пойти по пути других игр и просто сделать в палитре несколько разных болванок и играть с ними.

Автор: Chiffa Nov 5 2017, 15:33

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

Цитата(denis0k @ Nov 5 2017, 12:54) *
это долго и бессмысленно

Так что и правда, господь с ней, с системой PaiNt_craft. По крайней мере, пока. Поговорить хотелось о другом.
Цитата(denis0k @ Nov 5 2017, 12:54) *
Что касается крафта в нвн в принципе. Я писал довольно сложные. Всё, что нужно, в нвн есть - создание итемов, навешивание на них свойств. Сложность только с изменением внешнего вида сложных итемов

Тут позволю себе не согласиться. Крафт, ПМСМ, начинается все-таки не с этого. А с добычи. А это не только и не столько монстры ради шкурок-костей и т.п. Это активные плейсы. Я в "робинзонаде" пока поставил только четыре вида. Это "выход горной породы" (добывать кремень для ножиков-топоров), это "пласт песчанника" (точильные камни и стройматериал), это "годный куст" (волокно для тканей-веревок), ну и "годное дерево" - понятно для чего.
И произошло следующее. Герой стал дергаться, как эпилептик. Постоянно поворачивается куда угодно, только не туда, куда его посылаешь мышкой. Его атакует "морская тыдра" (ну не называть же эту тварь на "вы" - выдрой biggrin.gif), а он куда-то опять поворачивается. У него захлопывается инвентарь сразу после открывания. Он не может подобрать дроп без нажатого пробела - все схлопывается.
Много еще он чего не так делает, но если в двух словах, то ПС стал практически неуправляем.
Да, сначала добыча у меня начиналась через диалог типа "Ага, вот деревце, а где мой топор?" и т. п. Но у меня таки хватило ума ставить скрипт, включающий эти диалоги, на "OnUsed" плейсов, а не на "OnClick" или куда похуже. Расстояние - 2 метра. Так он за километры пытается побеседовать "по душам" с плейсом, вместо того, что от него требуется.
Очень дорожу атмосферностью, но при таких делах отключил диалоги вовсе. Не помогло... Плейс "поговорить" не хочет и уже не может, а герой все одно дергается.
Убрал все породы и песчанники под землю, в пещеру к крысам. Кустики-деревца перенес на соседний островок. Не помогло.
Как говорил прапорщик Наливайко "или я дурак или одно из двух".
Понимаю, что не имея нвн и не видя моего мода, сходу не сообразишь, в чем беда. Но, уважаемые мастера, у вас нет нвн, зато есть опыт. И вы можете хотя бы предположить, в чем проблема? В моей, миль пардон, рукожопости или все-таки, упаси бог, в движке авроры?
Спасибо.
З.Ы.Да, насчет сложности крафта я не сильно парюсь. (За исключением этой чертовой добычи!) Взял систему из ПЛ, которую, если я правильно понял, сочинял DBColl. А этот гений (пишу без кавычек, заметьте!) нагородил огород из секретных плейсов, ящиков, специальных полезных таблиц 2ДА и много еще чего, но у него, как у ТруЪ-индуса непонятно почему, но все работает. И я почему-то не сомневаюсь, что даже когда 2ДА-табличка раздуется до размеров "Войны и мира", все равно будет все работать.



Автор: denis0k Nov 5 2017, 23:58

Вообще не представляю, в чём проблема smile.gif Я могу только сказать, что я на двух шардах работал и ещё несколько модулей пилил, нигде персонажи эпилепсией не страдали smile.gif Но я обычно не брал цельные чужие наработки, всё больше писал сам с нуля. Или разбирался досконально и всё равно писал с нуля скелет, втыкая в него готовые авторские модули функций/скриптов.

Индусского кода действительно очень много, в любых языках программирования. Тут сложно что-то посоветовать, кроме как двух вариантов: либо разобраться в программировании самому, либо найти другую систему, которая таки заработает. Поковыряй https://neverwintervault.org/.

Автор: Chiffa Nov 6 2017, 04:28

Цитата(denis0k @ Nov 5 2017, 23:58) *
Вообще не представляю, в чём проблема smile.gif

Разобрался сам. Но с твоей помощью, спасибо. Понимаешь, столь уверенное заявление мастера, что "такого не может быть, потому что не может быть никогда" подсказало мне идею провести жестокий эксперимент. Над собой, любимым, прежде всего.
Посидел ночку, нарисовал нечто подобное моей робинзонаде, только в "Шадоу". Скопипастил туда скрипты и диалоги блокнотиком (экспорт-импорт невозможен по понятным причинам). И специально нарисовал этих пресловутых активных плейсов побольше, побольше, побольше... biggrin.gif
И что? Да, герой чуть дергается, но играть это не мешает. А когда свел количество плейсов к оптимальному, так и это дерганье прекратилось.
Скопировал что получилось в "лошадки". Там - опять эпилепсия у героя, да еще какая!
И биовари, кстати, тоже в этот раз не виноваты. Мне досталась какая-то локализация с локализации версии НВН. И чего там еще накосячено - сам Бейн не разберется.
Просто к слову, типа примера:
Этот неизвестный , извините за выражение, локализатор налепил в папку "portraits":
1. Агроном, сын Агронома - 8 штук,
2. Гиви, сын Реваза - 3 штуки,
3 эльф Логоваз - 7 штук
4 Пендальф - поленился считать, но много.
Всегда с настороженностью относился к толкиенутым...
Фотографии безобразные. Полдня сидел в инете, подыскивая морды поприличнее и еще два дня сидел за фотошопом, приводя папку "portraits" в более менее приличный вид.
И вот почему я сразу, еще тогда, не подумал, что не надо ждать от этой толкиенутой версии "лошадок" ничего хорошего!!!
Дважды наступил ведь на эти грабли! Вывод: мне просто надо найти нормальную локализацию. И не "лошадок" даже, а все-таки "Хордесов".
Как резюме: тему можно закрывать, толком не открыв swoon.gif. Крафт в НВН возможен. Причем именно такой, ради которого я и затеял эту тему. То есть крафт полного цикла, от добычи самого простого сырья до изготовления самых сложных вещей.
Только просьба к уважаемым модераторам пока ее не закрывать. У меня еще немало вопросов по робинзонаде. Хотелось бы получить пусть не ответы, то хотя бы подсказки.
З.Ы.
Цитата(denis0k @ Nov 5 2017, 23:58) *
сложно что-то посоветовать, кроме как двух вариантов: либо разобраться в программировании самому, либо найти другую систему, которая таки заработает. Поковыряй волт.

Увы, поздно. Я, честно говоря, староват даже для того, чтобы просто учить английский, не говоря уже о программировании. Потому и был так рад тому, что форум ГМ еще жив.
И важное уточнение. denis0k, извини, если моя манера изложения навела тебя на ложные мысли. Я не "катил бочку" на систему крафта от DBColl, а совсем наоборот. Работает она как часики, несмотря на ее странности. Впрочем, может и "странности" эти таковыми кажутся только мне, а для специалиста - норма.


З.Ы.Ы.
Вероятно, в нормальной НВН и система PaiNtа будет работать без "зацикливаний". Просто у DBColl, как я понял, очень важную роль играет именно 2ДА-табличка, а уж до нее наш "локализатор" не имел никакой возможности добраться. Найду нормальный невер - проверю обязательно.

Автор: Aiwan Nov 6 2017, 06:59

Chiffa, дружище, первое правило начинающего горнолыжника - не есть желтый снег. Первое правило модульмейкера - никаких кастрированных НВН. Только оригинал пропатченый до нужной версии. По поводу лагов. У нас в ПЛ был случай, хеньчша Каэтан в моем модуле жестко тупила вплоть до ухода в дауни, нвн лагал. Она никакая на команды не реагировала, перезагрузка не помогала. Ее я импортировал из ДБа модуля. Так вот, решил я ее сделать с нуля новую, без импорта. Импорт хотел сделал только диалог, позже. И о чудо, она зашавелилась, забегала, глюки пропали. Я ее везде проверил, решил все, импорт диалога и тут бац! Она опять объелась твиксов, так что весь нвн тупить стал. Посоветовались мы и решили ее утопить smile.gif Но потом я решил все же (а я упертый) все диалоги перенести текстом на созданный заново персонаж. Ну и что? Все заработало. Так вот, косячил просто диалог без скриптов который я импортировал. Как, почему, какого хрена? ХЗ. Вот такие косяки бывали у нас.

Автор: denis0k Nov 6 2017, 07:51

Да, с НПС беда конечно. Я когда ИИ боссам писал, отхлебнул smile.gif В результате босса-кастера, способного биться несколько минут, так и не сделал - каст через некоторое время просто зависает, в каждой попытке через разное количество времени. Возможно, этот баг никто не заметил, т.к. ~200-300 хитов выбиваются за пару раундов в обычных условиях (до зависания), но при 5000+ хп с закосом под фазированные бои ММО злой маг просто выключается в бою, т.к. перестают работать ActionCastSpell*.

Но вот с крафтом проблем не было smile.gif

Автор: Chiffa Nov 6 2017, 09:33

Цитата(Aiwan @ Nov 6 2017, 06:59) *
первое правило начинающего горнолыжника

Не-е, я на пост Президента РФ не претендую. biggrin.gif
Больше нравится система воспитания детишек у чукчей. Всего два правила. Первое: "Нельзя есть желтый снег!". Второе: "Желтый снег есть нельзя!" Оба правила знал назубок - и вот так вляпался...
Цитата(Aiwan @ Nov 6 2017, 06:59) *
...никаких кастрированных НВН.

Ладно бы кастрированная. Так наоборот, с лишними э-э-э ... органами.
Цитата(Aiwan @ Nov 6 2017, 06:59) *
...а я упертый...

Я тоже. Потому и угробил ночь, сев за комп просто в омерзительном настроении, ибо не имел понятия, какой получу результат и получу ли его вообще. Теперь, правда, выходит, что не так уж и угробил. Хотя мог бы давно сообразить: человек, напрочь лишенный вкуса, ничего путного не сделает. Ведь и фильм хороший (особенно гоблинский вариант biggrin.gif ) и артисты там обаятельные. И такие отвратные рожи с так криворуко сделанных скринов. "Локализация" могла быть только соответствующая.
Но заканчиваю флуд, попробую насмешить народ немного более иначе. У меня в робинзонаде снова получился чит, и опять невольный. А дело вот в чем. Все больше и больше я усложняю жизнь своему робинзону. Приучаю к дисциплине и аккуратности. Чтобы породу долбил строго киркой, дерево рубил топором, кусты, соответственно, серпом. Но тут ничего сложного: бьешь киркой породу - флаг сюжета снимается, бьешь чем-то другим - вешается взад. Впрочем, прошу прощения: кому я это объясняю... bb.gif
В общем, все проверки работают безупречно, а дальше получается смех. Вот, собственно:
Neverwinter Script
void main()
{
int HIT = GetLocalInt(OBJECT_SELF,"HIT");
int HP = GetLocalInt(OBJECT_SELF,"HP");
int CHP = GetCurrentHitPoints(OBJECT_SELF);
if (HP==0)
  {
  HP=GetMaxHitPoints();
  }
HIT = HIT + HP-CHP;
SetLocalInt(OBJECT_SELF,"HP",CHP);
if (HIT >=30)
  {
  HIT = HIT - 100;
  if (GetIsPC(GetLastDamager()))
        CreateItemOnObject("itm_peschan",GetLastDamager(),1);

  SendMessageToPC(GetLastDamager(),"Вы откололи кусок песчанника");
  }
SetLocalInt(OBJECT_SELF,"HIT",HIT);

{

string ref="";
switch(Random(30))

  {

  case 0: ref = "itm_ametist"; break; // Дополнительная награда за усердие, малодрагоценные камни. Драгоценные будут падать из руд металлов
  case 1: ref = "itm_awantyr"; break;
  case 2: ref = "itm_fire_agat"; break;
  case 3: ref = "itm_kvarcz"; break;
  case 4: ref = "itm_apatit"; break;
  case 5: ref = "itm_flourit"; break;
  }
if (ref!="")
  {

  object oItem = CreateItemOnObject(ref,GetLastDamager(),1);
  SetDroppableFlag(oItem,TRUE);
  }
}
}


Aiwan, что-то знакомое, так? Он самый, слегка измененный и чуть дописанный скрипт прокладки туннелей, куда безжалостный Lex загонял ПС-штрафников. Работает, ясен пень, тоже безупречно. А смех вот в чем. Я был уверен, что все эти аметисты-апатиты тоже привязаны к урону. То есть снес булыге 100 ХП - получи кусок печанника (ну, или кремня) + махонький рандомный камушек (не всегда).
Оказалось - нет. Если взять вместо кирки меч поострее, то никаких песчанников-кремней ты не отколешь, булыгу защитит флаг. А вот дополнительная награда будет сыпаться. Под аккомпанемент дефолтных визгов: "Оружие неэффективно!" "Вы не можете нанести повреждение текущим оружием!" biggrin.gif
И чем острее оружие тестера, тем больше будет этих камушков!
Почему, собственно? Ведь скрипт строит на OnDamaged булыжника. И просто по определению должен быть привязан к нанесенному плейсу демагу. Или нет?
Как прекратить это безобразие? Я пытался вставить проверку на хиты и урон еще раз, перед камушками. На все мои попытки компилятор ругался тупо и косноязычно, как малолетний гопник.
Надеюсь, повеселил. Спасибо.
З.Ы. Пока не нашел нормальную НВН, переселяю робинзона в "Шадоу" насовсем. Редактор скрипта моих кастрированных лошадок час назад выделил строку "object oPC = GetPCSpeaker();" и написал "Непонятное условие компилятора."
Занавес...

Автор: denis0k Nov 6 2017, 17:32

Так и не понял, что хотел сделать автор арифметической магией в начале скрипта, но могу сказать, что скрипт работает с любым оружием, т.к. проверки на него нет smile.gif В нвскрипте есть функция на получение итема в слоте рук(и), можно просто проверить по тэгу - если не кирка, то return.

Автор: Chiffa Nov 7 2017, 02:40

Цитата(denis0k @ Nov 6 2017, 17:32) *
могу сказать, что скрипт работает с любым оружием, т.к. проверки на него нет smile.gif


Совершенно верно. Скрипт проверки стоит не на демаге (OnDamaged), а на физической атаке (OnPhysicalAttacked) булыжника. То есть герой только начинает атаковать, а ему:
Neverwinter Script
if(GetTag(oWeap)!="itm_kam_kirka" && (GetTag(oWeap)!="itm_krem_kirka")) // Не каменная и не кремневая кирка
SetPlotFlag(OBJECT_SELF,TRUE);
SendMessageToPC(GetLastDamager(),"Камни надо долбить киркой");

Ну, а если "инструмент" какой надо, тогда:
Neverwinter Script
if(GetTag(oWeap)=="itm_kam_kirka" || (GetTag(oWeap)=="itm_krem_kirka")) // Они, родимые, та или другая
SetPlotFlag(OBJECT_SELF,FALSE); // Убираем галку "сюжет" и демаж хоть до потери пульса


Хочешь сказать, что я ошибся и скрипты стоит слепить в один? Но куда его ставить, на демаг или на атаку?
Да и вряд ли это поможет, потому что смех совсем в другом. Скрипт проверки нормально работает, уж сколько раз проверял. Когда в руке меч хоть на +100500 biggrin.gif, все равно нет и не может быть никакого демага. Это со всей ответственностью подтверждают дефолтные визги "Оружие неэффективно!".
А скрипт, стоящий как раз на этом демаге сыплет тебе аметисты-аппатиты (основной добычи нет, тут все "честно").
Получилась этакая вечная читерская булыга. Долби ее чем угодно, кроме кирок, и всякие аметисты-агаты будут сыпаться бесконечно...
Вот я и спросил, как это безобразие прекратить?
Основная добыча (кремень, песчанник) привязана к хит-пойнтам булыги. Снял 100 ХП - получи кусок кремня. Снял еще сотню - еще один и так, пока все не раздолбишь. А дополнительная, получается, нет. Как привязать и ее тоже? Или что-то более другое надо сделать?

З.Ы. denis0k, извини, забыл поблагодарить за ссылку. Про волт я знал, но тем не менее спасибо. И вопрос. Помню, на этих волтах была огромная библиотека хаков. Причем русская. Она жива? Если да, то где, не в курсе, случайно? Старые ссылки показывают 404...


Цитата(denis0k @ Nov 6 2017, 17:32) *
Так и не понял, что хотел сделать автор арифметической магией в начале скрипта

denis0k, ты уникум! Мастер с заглавной буквы "М", у тебя даже подколки идут на пользу делу. biggrin.gif
Короче, проблема решена. Я также задумался, зачем эта арифметическая магия понадобилась? Не будет же Lex просто так заниматься арифметическим словоблудием (цифроблудием, точнее). И понял (скорее на интуитивном уровне): да это же он хиты горемычной булыги подсчитывает! Сколько их имеется, сколько осталось, сколько ПС снес. Ну и потом что ему за этот демаг выдать.
Конечный скрипт стал даже короче:
Neverwinter Script
void main()
{
int HIT = GetLocalInt(OBJECT_SELF,"HIT");
int HP = GetLocalInt(OBJECT_SELF,"HP");
int CHP = GetCurrentHitPoints(OBJECT_SELF);
if (HP==0)
{
string ref="";
if (ref!="")
switch(Random(30))

  {
  case 0: ref = "itm_ametist"; break;
  case 1: ref = "itm_awantyr"; break;
  case 2: ref = "itm_fire_agat"; break;
  case 3: ref = "itm_kvarcz"; break;
  case 4: ref = "itm_apatit"; break;
  case 5: ref = "itm_flourit"; break;

  {
  HP=GetMaxHitPoints();
  }
HIT = HIT + HP-CHP;
SetLocalInt(OBJECT_SELF,"HP",CHP);
if (HIT >=30)
  {
  HIT = HIT - 100;
  if (GetIsPC(GetLastDamager()))
    CreateItemOnObject("ITM_KREM",GetLastDamager(),1);
  SendMessageToPC(GetLastDamager(),"Âû îòêîëîëè êóñîê êðåìíÿ");

    object oItem = CreateItemOnObject(ref,GetLastDamager(),1);
    SetDroppableFlag(oItem,TRUE);
    }

    SetLocalInt(OBJECT_SELF,"HIT",HIT);
    }
  }
}

И работает именно так, как я хотел. Выдает полудрагоценный камешек примерно после каждого второго добытого куска кремня или чуть реже. Я специально поставил тестового перса долбить эту булыгу хорошими мечами и ушел курить. Вернулся - он все долбит, но фиг ему что в инвентарь упало. Взял "кирку" и все пошло, как и было задумано.
Спасибо, уважаемые мастера! Прежде всего за моральную поддержку, дельные советы (желтого снега больше в рот не возьму! biggrin.gif ) и за к месту сказанные подколки. biggrin.gif


З.Ы.Ы. Вообще-то выше два разных поста, написаны с перерывом больше часа. Слепились в один почему-то. Хотел это объяснить, а также еще сказать о том, что проблема была для меня ну оч-чень важна. Не век же мой робинзон будет кремний долбить, в задумках и руды металлов, причем далеко не одного вида. И призовые камешки из этих руд будут сыпаться уже гораздо более другие. Вечные читерские рудные залежи стали бы кошмаром...
Спасибо!

Автор: denis0k Nov 7 2017, 07:44

Очевидно, что OnDamaged всё равно запускается, даже если урон нулевой. К слову, на неписях он запускается от любого урона, попробуй скалу атаковать спеллом после атаки киркой - так плот-флага не будет (после кирки), а урон пройдёт smile.gif

Автор: Melisse Nov 7 2017, 15:08

Если стоит ПлотФлаг событие не работает

Автор: denis0k Nov 7 2017, 17:55

Событие не работает, а итемы создаются xD Мб у автора не 1.69, а ранее баги были просто.

Автор: Chiffa Nov 8 2017, 00:29

Цитата(denis0k @ Nov 7 2017, 07:44) *
Очевидно, что OnDamaged всё равно запускается, даже если урон нулевой. К слову, на неписях он запускается от любого урона, попробуй скалу атаковать спеллом после атаки киркой - так плот-флага не будет (после кирки), а урон пройдёт smile.gif

Даже проверять не буду, не сомневаюсь, что ты прав. Собственно, уже проверено. За подсказку про спеллы спасибо. Сейчас это не актуально, вряд ли кастер 1-4 уровня будет тратить на булыгу свой невеликий запас спеллов и каждый раз бегать в зону отдыха. Но когда дело дойдет до руд металлов, придется и эту тему вспомнить. rolleyes.gif
Цитата(Melisse @ Nov 7 2017, 15:08) *
Если стоит ПлотФлаг событие не работает

Разумеется. Вот только я и есть тот самый специальный полезный парень на котором удобно проверять все мыслимые и немыслимые исключения из всех правил. Если есть грабли - наступлю обязательно. Это называется "карма". biggrin.gif Одна только галка "ландшафт" чего стоила...

Цитата(denis0k @ Nov 7 2017, 17:55) *
Событие не работает, а итемы создаются xD Мб у автора не 1.69, а ранее баги были просто.

Конечно, баги. Только они и в "лошадках" и в 1.69, в старой, надежной как лом "Шадоу" (Держу, собственно, ради ПЛ). Говорю же, если грабли существуют в принципе - наступлю обязательно (см. выше).
Вот еще пример на тему просто похохотать. Как выяснилось, скрипт, второй, которому я радовался, вообще не работает. От слова "совсем". Когда он стоит, ничего из булыги не вышибешь. Ни ТруЪ-киркой, ни мечом на плюс стопитьсот, ни ядреной бомбой.
А произошло следующее. Тестер долбил мечами, пока я курил, одну булыгу. Потом я вернулся, дал ему кирку и кинул атаковать ... другую булыгу. Просто по запарке, рядом она стояла. И оказалась единственной, на которой я забыл старый скрипт. Вот у него и посыпались все, что надо и типа "как надо". vava.gif biggrin.gif
Говорю же, карма...
Сроду не признался бы в таком позорище, но, во-первых, должен поблагодарить мастеров за поддержку и участие, а лучший способ - улыбнуть. Во-вторых, я таки решил проблему. Понял, что все попытки запрячь в одну упряжку коня надежных и проверенных скриптов на рандом от Aiwanа и трепетную лань Lexовой "арифметической магии" (с) denis0k - и есть ошибка. Проще надо быть. this.gif
И решение оказалось действительно простым до смешного. Теперь, когда ПС снял 100 ХП с горемычной булыги, включается локалка. Тут же проверяется, если адын - начинают сыпаться всякие апатиты-флоуриты. Скрипт на OnDeath булыги и скрипты проверки оружия сбрасывают локалку на ноль. Profit!
Надеюсь, повеселил. Есть еще несколько проблем, но задам вопросы и/или попрошу подсказки попозже. Побьюсь пока сам, вдруг справлюсь.
Спасибо.

З.Ы. Еще раз хочу спросить насчет волтов. Там была огромная библиотека хаков. И все названия, пояснения, комменты в ней были на русском языке, ИЧСХ, слева направо. Вопрос купца Елисеева анекдота: кому она помешала?
Или она таки жива? Может, кто-то знает ссылку (старые не работают)?

Автор: Aiwan Nov 8 2017, 09:08

Волат помер, ща какая-то новая версия сайта. https://neverwintervault.org/

Автор: Chiffa Nov 9 2017, 06:04

Цитата(Aiwan @ Nov 8 2017, 09:08) *
Волат помер, ща какая-то новая версия сайта. https://neverwintervault.org/

А вот это на самом деле неприятно. Ждал от проклятых буржуинов любой гадости, но вот что они применят против нас ТАКИЕ санкции! Все-таки всему должны быть какие-то рамки! sad.gif
Прошу прощения, что так неуклюже шучу, это от злости. За ссылку спасибо, только зная я ее, да и denis0k на днях дал ее же. То есть, похоже, других серьезных ресурсов больше не осталось. Только там все на поросячьей латыни (так римляне называли языки англосаксов, а римляне дураками не были). А я как старый цирковой пес, который уже не может научиться новым фокусам. Да и не хочет, если уж честно.
Просто прикинул, КАКОВО будет искать где-то и впихивать в хак эти каменные топоры, пальмовые юбки дикарок (не век же робинзонить!) и прочие шаманские бубны. И все это через гугл-переводчик... дурно делается.
Ладно, прекращаю нытье.
Уважаемые мастера, подскажите, есть ли способ уничтожать в инвентаре героя несколько предметов с одинаковым тегом? Точнее, не просто несколько, а совершенно определенное количество. Вот простой пример, робинзон делает ткань из местного травяного волокна:
Neverwinter Script
#include "lm_tsurl_lib"// Как я понял, инклюда, которую Lex сочинил специально для того, чтобы выдавать алкашу Вагису пиво строго по одной бутылочке.
void main()
{
object oVol = FindItem("trav_volokno",GetFirstPC()); // Травяное волокно в инвентаре ПС.
int Number = GetItemStackSize(oVol);
if (Number==1)
    DestroyObject(oVol);  //"Арифметическая магия", в которой я не разобрался...
else

SetItemStackSize(oVol,Number-4); // По идее, должен вычесть 4 куска волокна. Но только по идее, увы...

{
DelayCommand(0.5,AssignCommand(GetFirstPC(),ActionPlayAnimation(AN
IMATION_LOOPING_MEDITATE ,1.0f,5.0f))); //Ну с анимацией я еще покопаюсь, а пока фиг с ней, не до нее.
DelayCommand(2.5,AssignCommand(GetFirstPC(),ActionPlayAnimation(AN
IMATION_PLACEABLE_OPEN ,1.0f,5.0f)));
DelayCommand(4.5,AssignCommand(GetFirstPC(),ActionPlayAnimation(AN
IMATION_PLACEABLE_DEACTIVATE ,1.0f,5.0f)));
CreateItemOnObject("itm_rogozha", GetFirstPC(),1); // Получите, сеньор робинзон кусок ткани, который вы "лично сплели" из 4-х кусков волокна.
}
}


Скрип вполне себе рабочий. И волокно забирает, и ткань выдает. Только забирает не 4 куска волокна, а только один. В общем, что бы ни точил русский токарь, все-равно получается АКМ. Чтобы ни мудрил Chiffa, все равно получается читерство. biggrin.gif
ИЧСХ, скрипт проверки (основан на том же принципе) вполне себе корректный. Если волокон в инвентаре меньше четырех, строка диалога "займусь тканью" не открывается.
Понятно, обходные пути есть. Так, веревку сплести и ткань соткать - это я могу вписать в 2ДА табличку имени DBCollа. Но как быть с плейсами, под них эта табличка вовсе не "заточена". Вот герою надо "сколотить" сундук. С палитры я этот ящик вызову, но как сделать, чтобы на его "изготовление" ушло именно 4 доски (а не одна и не восемь) + 20 дубовых гвоздей и 2 веревки?
Прописать в табличку итем-"пустышку", а в конце диалога вместо его выдачи ставить сундук с палитры? Тоже ничего себе способ... Но, во-первых, все-таки не хочется раздувать табличку до размеров "Войны и мира". Во-вторых, хочется разнообразить диалоги, а у крафта он практически один на все случаи.
Может, все-таки существует способ проще? Подскажите, что делать, где искать...
Спасибо.

Все-таки упертым быть, тяжело, но иногда полезно. Не верите, спросите у Aiwanа...
Изгалялся над скриптом до утра. Сначала просто тупо повторил строчку "SetItemStackSize(oVol,Number-1);" четыре раза. Ничего не изменилось. Потом написал "SetItemStackSize(oVol,Number-1-1-1-1);" . Тоже не помогло. Потом повыше вместо "if (Number==+1)" написал "if (Number==1+1+1+1)". Так получился чит еще круче: ткань выдает, но волокно не берет.
В общем, долго я издевался над этой "арифметической магией", чего только не перепробовал. Странно, но компилятор на все эти дикости почти не ругался. Но вот под утро "зоркий сокол" таки заметил забавное слово "Stac" в обоих командах.
Так, какие предметы у меня в стек складываются? Пока только "прочные деревянные гвозди" (обычные арбалетные болты). В результате утреннего "выноса мозга" и вообще досады на собственную тупость родилась новая ветка диалога (Г - герой, И - инструмент):

Г: - А забью-ка я себе в задницу десяток гвоздей!
И: - Почему нет? Гвозди прочые, из мореного дуба.
Г: -Заколачиваю!

Срабатывает скрипт, есссно, с другими рефами и строкой "SetItemStackSize(oVol,Number-10);".
Понятно, все получилось. Герой потратил ровно 10 гвоздей и получил с палитры итем "Утыканная гвоздями задница".

В общем, все ясно. Скрипт очень даже корректный, просто для стековых итемов. Потому вопрос формулирую несколько более иначе:

Существует ли способ уничтожать в инвентаре ПС точно количество итемов с одинаковым тегом, если эти итемы - НЕ стековые? Если да, то где копать?

З.Ы. Сначала я попробовал тупо убрать слово "Stac" из переменной. Результат немного предсказуем: потеря анализатора. Потом чисто от безысходности написал "SetItemNoStackSize". Ясен пень, снова потеря анализатора переменной...

З.Ы.Ы. Два поста написаны опять с перерывом, теперь уже часов в шесть, но, скорее всего, опять слипнутся в один. Потому прошу прощения за многабукаф. Спасибо.

Автор: denis0k Nov 9 2017, 13:33

https://nwnlexicon.com/index.php?title=TakeNumItems

Автор: Aiwan Nov 9 2017, 14:51

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

Автор: Chiffa Nov 10 2017, 03:14

Цитата(Aiwan @ Nov 9 2017, 14:51) *
Chiffa, полистай мои скрипты в монетке, там много чего я делал и все описал кратко. Найдешь кучу интересного и нужного.

Aiwan, мне даже неловко малость. И так львиную долю скриптов натаскал именно у тебя. И монетку, кстати, ковыряю уже давно, так что рад, что получил теперь на это официальное разрешение. rolleyes.gif
Там и правда очень много полезного. А самое полезное - высокая культура оформления. Спасибо.
Досадно одно: пока я там не нашел ничего похожего на мой случай. Надеюсь, пока не нашел...
denis0k, спасибо за ссылку, она выводит именно на итемы. Понять бы еще, чего там буржуины понаписали на своем тарабарском языке... sad.gif
Впрочем, кое-что с помощью гугла-переводчика даже я кое-что понял. Например, что oTarget - это (цитирую дословно): "объект для удаления нескольких элементов". И что есть специальная полезная переменная nNumItems, которая обозначает (тоже дословно): "Максимальное количество элементов, найденных в инвентаре объектов, для удаления."
Казалось бы, куда уж яснее...
Пишу скрипт:
Neverwinter Script
void main()
{
object oTarget = GetItemPossessedBy(GetFirstPC(), "trav_volokno"); // Определяем, что там для удаления
int Number = 4; // Удалить надо 4 штуки
DestroyObject(oTarget); Number; //Удаляем. По идее, 4 штуки, только фиг!
CreateItemOnObject("itm_rogozha", GetFirstPC(),1); //Выдаем с палитры рогожу, которую ПС из этих четырех волокон типа скрафтил.
}

Компилятор вынес вердикт "составлено верно". А движок все равно убивает только один итем. Пытался писать через запятую "DestroyObject(oTarget, Number;" и "Number++" и менять циферку после этого Numberа. И подключал инклюду "nw_i0_plot". Что с ней, что без нее - все бесполезно... С первым выражением компилятор меня просто послал, все остальные принимал, но это ничего не меняло.
В конце-концов, написав "int Number = 0;" я понял, что движок эту переменную просто не видит...
Что я сделал не так? Чего не хватает? Или что лишнее (хотя уж чему тут быть лишнем!)
Спасибо.

Автор: Aiwan Nov 10 2017, 07:04

Цитата(Chiffa @ Nov 10 2017, 06:14) *
Aiwan, мне даже неловко малость. И так львиную долю скриптов натаскал именно у тебя. И монетку, кстати, ковыряю уже давно, так что рад, что получил теперь на это официальное разрешение. rolleyes.gif
Там и правда очень много полезного. А самое полезное - высокая культура оформления. Спасибо.
Досадно одно: пока я там не нашел ничего похожего на мой случай. Надеюсь, пока не нашел...


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

В ПЛ в моем модуле, есть квест, где надо принести несколько бутылок с зельем. Там в одном скрипте их проверяют, сколько в слоте у РС, а в другом уничтожают заданное количество. Я точно не помню, но где-то на пристане НПС ему типа нужны зелья какие-то. this.gif

Автор: denis0k Nov 10 2017, 07:44

Neverwinter Script
#include "nw_i0_plot"

void main() {

...

TakeNumItems(GetFirstPC(), "trav_volokno", 4);

...

}

Автор: Aiwan Nov 10 2017, 09:09

Точно smile.gif

Автор: Chiffa Nov 10 2017, 09:43

Aiwan. denis0k, ребята, СПА-СИ-БО!!!
Уже проверил скрипт на "Полигоне" (это у меня специальный полезный мод для издевательств над ПС). Все работает как часики! Блин, всего одна строчка, а все в корне меняется и уже на жизнь смотришь по-другому. biggrin.gif biggrin.gif biggrin.gif
denis0k, тебе подошел бы титул Лаконичный Мастер. Твой подарок действительно трудно переоценить, настолько он для меня важен. Спасибо еще раз!
Правда что ли за инглиш взяться? Как там у Маяковского "Да будь я негром преклонных годов"? Я, увы, не негр. И хотя годов вполне преклонных, но уже не думаю, что понять английский страшнее, чем плавать в Тамбовском море в ноябре месяце (именно плавать, т. е. подолгу, а не "моржевать"). Но это так, к слову.
Aiwan, а с твоего Андра-Дуна я практически начинал свою "Долбанутую сказку". Правда, не с вина, а с ковыряния твоих ... ох, прости! - пиратских, конечно, ушей. biggrin.gif Там герой убивал нехороших ребят и приносил с них особый трофей (опозновательное колечко) хорошим гномам. Менял колечки на мифрил, его, ясен пень, только у этих шахтеров и можно было достать. И только таким способом. Скрипт занял, как ты уже понял, у секретаря сэра Генри.
И сценку с вином найду и посмотрю обязательно. Хотя вино и складывается в стек, а насчет стеков я уже вроде что-то стал понимать. Но наверняка найду что-то для себя новое и полезное.
Спасибо!

З.Ы. И еще в моей сказке герой много плавает. На корабле. Откуда дровишки, в смысле скриптики, объяснять не надо, думаю? Разница только в том, что фамилия у капитана другая. Не Огнев...

Автор: Chiffa Nov 16 2017, 16:33

Уважаемые мастера, надеюсь, я не слишком вас достал. Пишу только потому, что сам не смог добиться толку за трое суток. Проблема наверняка из серии "галка на ландшафте" или "демаг, которого не может быть, но он есть". Но она превращает мою робинзонаду в клоунаду. vava.gif
Вот, взгляните, в чем "провинился" этот несложный скрипт. Надеюсь, увидите ошибку:

Neverwinter Script
#include "nw_i0_plot"
#include "lm_tsurl_lib" //для работы со стеками
void main()
{
object oPC = GetPCSpeaker();
object oGvo = FindItem("itm_der_gvozd",GetPCSpeaker());
int Number = GetItemStackSize(oGvo);
if (Number==1)
    DestroyObject(oGvo);
else
    SetItemStackSize(oGvo,Number-10); // Это гвозди, которые уничтожаются ровно по 10 штук, все корректно...
TakeNumItems(oPC, "itm_dosk_kor", 4); // Тут тоже ок, спасибо, denis0k!
location oLoc = GetLocation(GetNearestObjectByTag("PLACE_CHEST")); // Невидимый объект, статик
DelayCommand(0.0,ActionPauseConversation()); // А вот отсюда начинается какая-то хрень!
DelayCommand(0.5,AssignCommand(oPC,ActionForceMoveToObject(GetObje
ctByTag("PLASE_CHEST")))); // НИКОГДА не идет, зараза!
DelayCommand(1.5,AssignCommand(oPC,ActionPlayAnimation(ANIMATION_L
OOPING_GET_LOW ,1.0f,3.0f))); //Иногда корячится, но чаще стоит столбом
DelayCommand(2.5,AssignCommand(oPC,ActionPlayAnimation(ANIMATION_L
OOPING_SIT_CROSS ,1.0f,5.0f))); // То же самое
DelayCommand(3.5,AssignCommand(oPC,ActionPlayAnimation(ANIMATION_L
OOPING_TALK_FORCEFUL ,1.0f,3.0f))); // То же самое
DelayCommand(5.0,AssignCommand (oPC, SpeakString("Уф... упарился, аж в глазах потемнело."))); // Чаще молчит, гад
DelayCommand(7.5, ActionCreate(OBJECT_TYPE_PLACEABLE, "SAMOD_CHEST",oLoc)); //Вызывается. Иногда. Есть любопытная закономерность
DelayCommand(8.5,ActionResumeConversation());
}


Как вы поняли, это мой "робонзон" сколачивает ящик, накопил барахлишка, инвентарь не резиновый. Скрипт стоит на диалоге с невидимым монстром. Монстр вызывается, когда юзаешь молоток. Тут полная аналогия с маршрутизаторами ПЛ и "Саги". Монстра я импортировал, естественно, поменяв теги, рефы и вызываемые диалоги.
Но монстр вряд ли в чем виноват. Потому что есть еще монстры, например, мультитул, к нему никаких претензий.
Скажу сразу: дело не в моих глюканутых "лошадках". Проверял и в старой, надежной "Шадоу", и в недавно установленной 1.69 - везде одинаково. (Кстати, "лошадок" я пока не стер. Возможно, проблема даже не в них, а в 64-разрядной винде).
Так вот, что происходит.
1. Если скрипт стоит на "совершены действия" ПС, то герой стоит столбом и вообще ничего не делает. Ящик с палитры не вызывается. Никогда.
2. Если переставить на "совершены действия" непися (монстра), герой изображает "танцы с бубном", а также вполне спикает и стрингает, но к плейсу не идет и ящик не вызывается.
3. Если поставить на "совершены действия" обычного непися (специально рисовал для проверки) - тогда и танцы с бубном, и спики-стринги, - все ок, и ящик вызывается. Всегда. За километр от героя, точно на плейсе. Казалось бы, куда уж яснее: "ActionForceMoveToObject(GetObjectByTag("PLASE_CHEST"))));" - так не двигается! Говорю, не робинзонада, а клоунада...
Конечно, я пробовал и несколько более иначе. Без "DelayCommand", а просто "AssignCommand", естественно, через ActionWait(1.5f); или побольше. Как и учил нас, нубов, уважаемый Aiwan. Получилось еще смешнее. Тут даже герой к плейсу пошел, и все танцы исполнил. Вот только ящик плевать хотел на эту вашу "ActionWait". Появляется с палитры сразу, без малейшей задержки. И герой "сколачивает" уже готовый ящик.
Может, проблема в том, что монстр-мультитул работает исключительно с предметами, потому к нему и нет претензий. А к плейстейблам нужен какой другой подход?
В общем, печалька...
Ведь робинзону предстоит еще по такой же схеме делать и ткацкую раму, и печку для плавки, и много еще чего в задумках. А тут такая фигня...
Спасибо.

З.Ы. Проделал еще один опыт, такой же дурачий, как и сама ситуация. У всех невидимых монстров слоты чистые, кроме двух, на "OnHeartbeat" (коротенький скрипт, заставляет уничтожаться после использования) и на "OnSpawn" - скрипт вызова.
Так вот, я взял и тупо поставил все дефолтные скрипты на эти чистые слоты. И получилось все, как в разговоре со специально подрисованным неписем.
Ну вот что за фигня, на самом деле?!

Автор: Aiwan Nov 16 2017, 18:51

Основная твоя ошибка ты понятия не имеешь зачем все эти DelayCommand, AssignCommand и бла бла бла. Читал мануал по тулсету давно и невнимательно.
Первое. Что бы построить цепочку действий с двумя или тремя объектами, нужен диспетчер. Тот, кто будет следить за исполнением команды. Ни РС ни НПС на это слабо подходят. Либо им забивать стэки команд и делать их глухими для всего, либо через диспетчера. Что бы все шло по рельсам, нужно, например надовать действий игроку и пусть он выполняет их по очереди. Для этого нужно правильно уметь раздавать команды и понимать какая команда кем выполняется. В твоем скрипте все действия разданы хаотично и большинство из них исполняет тот на ком скрипт по умолчания OBJECT_SELF. Вот и вся петрушка. Кратко:

Neverwinter Script
#include "nw_i0_plot"
#include "lm_tsurl_lib" //для работы со стеками
void main()
{
object oPC = GetPCSpeaker();
object oGvo = FindItem("itm_der_gvozd",GetPCSpeaker());
int Number = GetItemStackSize(oGvo);
if (Number==1)
    DestroyObject(oGvo);
else
    SetItemStackSize(oGvo,Number-10); // Это гвозди, которые уничтожаются ровно по 10 штук, все корректно...
TakeNumItems(oPC, "itm_dosk_kor", 4); // Тут тоже ок, спасибо, denis0k!
location oLoc = GetLocation(GetNearestObjectByTag("PLACE_CHEST")); // Невидимый объект, статик
DelayCommand(0.0,ActionPauseConversation()); // Задержку 0.0 никогда не делай.
DelayCommand(0.5,AssignCommand(oPC,ActionForceMoveToObject(GetObje
ctByTag("PLASE_CHEST")))); // Игрок получает команду выполнить и...
DelayCommand(1.5,AssignCommand(oPC,ActionPlayAnimation(ANIMATION_L
OOPING_GET_LOW ,1.0f,3.0f))); // ... через 1 секунду его сбивает эта команда выполнения движения.
DelayCommand(2.5,AssignCommand(oPC,ActionPlayAnimation(ANIMATION_L
OOPING_SIT_CROSS ,1.0f,5.0f))); // потом эта
DelayCommand(3.5,AssignCommand(oPC,ActionPlayAnimation(ANIMATION_L
OOPING_TALK_FORCEFUL ,1.0f,3.0f))); // и эта
DelayCommand(5.0,AssignCommand (oPC, SpeakString("Уф... упарился, аж в глазах потемнело."))); // Эта команда не идет в стек и срабатывает иногда
DelayCommand(7.5, ActionCreate(OBJECT_TYPE_PLACEABLE, "SAMOD_CHEST",oLoc)); //
DelayCommand(8.5,ActionResumeConversation()); // Если скрипт на РС то он продолжит, если нет... сам понимаешь.
/*игрока можно отправлять в катсцену и в конце всех актионов снимать ее
ActionDoCommand(SetCutsceneMode(oPC,TRUE)) - ставим
ActionDoCommand(SetCutsceneMode(oPC,FALSE)) - снимаем
*/


}


Action можно игроку или НПС выдавать по очереди и он их будет выполнять пока они не кончатся или его не собьет с действия какой либо скрипт в слотах или округи.
В общем у тебя полная жопа с понятием основ. Я конечно могу исправить скрипт, посижу часик, но не думаю, что это поможет. Возьми для начала и перечитай мою тему построения скриптовых сцен. Там четко написано кто и почему делает так как в скриптах. В катсценах участвуют куча НПС и РС и все до долей секунд исполняют написанный сценарий. Помешь как оно работает, поймешь свои ошибки.


Тебе сюда: http://www.city-of-masters.ru/forums/index.php?showtopic=123

Автор: denis0k Nov 16 2017, 19:28

location oLoc = GetLocation(GetNearestObjectByTag("PLACE_CHEST"));
DelayCommand(0.5,AssignCommand(oPC,ActionForceMove
ToObject(GetObjectByTag("PLASE_CHEST"))));

Автор: Chiffa Nov 17 2017, 11:33

denis0k, спасибо за поправку. Как всегда у тебя: очень коротко и очень по делу.
Aiwan, спасибо за науку. Я люблю иногда почитывать твои саркастичные посты. И вот теперь оценил, насколько ты был ко мне доброжелателен. biggrin.gif
Ясен пень, я первым делом полез по ссылке. И хлопнул себя по лбу: я ж акции герою не почистил! Вот только где он их испачкать успел, засранец? vava.gif Ведь только вошел на "Полигон" - и на тебе!
Почистил. Побежал, как миленький, к плейсу. Только почему-то в самом коце скрипта, когда уже и ящик стоял, и все танцы с бубном были исполнены.
Ладно... С этим смехом уж сам как-нибудь теперь разберусь.
Еще раз спасибо, ребята.
З.Ы. Aiwan, извини, немножко не в тему, но... Короче, "вылечил" я ПЛ-овского бандита. Точнее, вылечил ПЛ от знаменитого бандитского зависания, которое столько крови испортило игрокам.
Ты меня, конечно, напугал Великим Джедаем. Но потом я подумал: а какого лешего... ну, джедай... Дык я всегда смогу вернуть все взад, если накосячу, долго ли модуль в отдельную папку скопировать. Тупо снял катсцену с задержкой 20 секунд. Все. Бандит по-прежнему нападает, а если ему нападать лениво, катсцена соскакивает сама. prankster2.gif


Автор: Aiwan Nov 17 2017, 13:53

Цитата(Chiffa @ Nov 17 2017, 14:33) *
З.Ы. Aiwan, извини, немножко не в тему, но... Короче, "вылечил" я ПЛ-овского бандита. Точнее, вылечил ПЛ от знаменитого бандитского зависания, которое столько крови испортило игрокам.
Ты меня, конечно, напугал Великим Джедаем. Но потом я подумал: а какого лешего... ну, джедай... Дык я всегда смогу вернуть все взад, если накосячу, долго ли модуль в отдельную папку скопировать. Тупо снял катсцену с задержкой 20 секунд. Все. Бандит по-прежнему нападает, а если ему нападать лениво, катсцена соскакивает сама.

i-m_so_happy.gif

Автор: Chiffa Nov 20 2017, 12:12

Приветствую еще раз, уважаемые мастера!
Aiwan, а не мог бы ты еще разок меня куда-нибудь послать, мне понравилось. biggrin.gif

Только не туда, куда посылают самых жестких нубофф. По полезному адресу. Благодаря твоему последнему посылу мой "робинзон" и ящик сколотил, и лежанку соорудил в пещере, и наковальню и даже ткацкую раму. А плавильную печь будет сооружать вообще по феншую, с камерами-векторами. Прежде я от катсцен шарахался, как дьякон от борделя, по причине застарелого страха от висяков ПЛ-овского бандита. А вот теперь наоборот, жалею: сколько эпизодов в моей "Сказке" просят, просто умоляют: сделай меня фильмом! Эх...

Ладно... Извините за многабукаф, это профессионально-нравственная деформация, лечить бесполезно. А мне всего-то и надо, что корректно вставить в хак TGA-шные файлы типа "iit_midmisc_", "iit_thnmisc_" и т. п. то есть "портреты" вещей. Самое смешное, всегда думал, что умею работать в фотошопе. И действительно делал куда более сложные вещи, чем "заточка" рисунков под нужный размер и формат. А вот на тебе! Получается не "каменный наконечник для копья", а рисунок этого чертова наконечника на черном полотне.
Сначала поступил просто: сделал прозрачный файл 64х64 и тупо перетащил в него этот наконечник. Результат понятен: при записи tga-файла фотошоп все слои слепил в один и эту прозрачность убрал...
Стал рыть. Ответ нашел не на ГМ и даже не на WRG, а на форуме "Рыцарской саги". Там наш друг Геннадий небрежно, типа между прочим сообщает:

Цитата
Чтобы добавить прозрачность, нужно добавить рисунку альфо канал.

А дальше еще и пишет, что научил его этому некто Aiwan, известный...
Подумал, может, я чего пропустил? Ведь Геннадий практически слово в слово твою, Aiwan, PDF-ку пересказывает! Посмотрел. Нет. Там после вставления в хак портретов НПС и "кстати о музыке" сразу идут диалоги. Про прозрачность вообще ни слова.
Ну, бывал я в этом Бологом... пардон, нашел этот канал "Альфа 1". Добавил. А толку? TGA-формат при сохранении его "забывает". В PSD. PDD и т. п. - хоть сто порций. Но эти форматы не поймет уже Аврора. Пометить галкой строку "сохранить прозрачность" уже фотошоп не позволяет.
В общем, чувствую, дело в какой-нибудь ерунде, но я вот об нее спотыкаюсь. Только, прошу, не надо посылать меня в раздел "Работа с 2DA-таблицами". Читал. Там народ серьезными вещами занят, новые расы-классы добавляет, спеллы и т. п. Так спросишь у профессора высшей математики про дважды два, а ему и поплохеет. А у тебя, Aiwan, закалка возни с нубами с начала нулевых, тебя такой ерундой не проймешь. prankster2.gif
Вот я и интересуюсь: может, существует какой "букварь" по хакам, навроде твоей знаменитой PDF-ки? А уж если его автор понимает: то, что само собой разумеется для него, Автора, далеко не всегда само собой разумеется для всех остальных, - так вовсе было бы замечательно.
Спасибо.
З.Ы. Вопрос далеко не срочный. Моему "робинзону" пока есть чем заняться. Но потом пойдут каменные топоры и прочее, а Макс, зараза, по-прежнему MDL-формат в упор не видит, как и 10 лет назад. В будущее смотрю с содроганием... biggrin.gif

Автор: Aiwan Nov 20 2017, 13:19

Блин, я уже и не помню prankster2.gif Старею... biggrin.gif

Автор: Melisse Nov 20 2017, 14:38

ТГА сохраняется в 3х видах. Чтобы сохранить альфу нужно 32битный сохранять. По умолчанию 24бита.


Автор: Chiffa Nov 20 2017, 14:44

Aiwan, спасибо за участие. Разобрался. Моя привычка наступать на грабли, которых нет. Карма, так ее растак.
Короче, Геннадий правильно не стал усложнять и разжевывать. Потому что надо тупо добавлять эту альфу и не ставить ей "Непрозрачность 0", как это я делал. Нужно оставлять "Непрозрачность 100", как по умолчанию. Почему все получается правильно - понять не могу, но тут, как у ТруЪ-индусов все работает вопреки всякой логике.

Помнишь анекдот про прапорщика Наливайко: "Люлюмен - самое легкое железо. А кто шибко грамотный идет грузить чугунину". Вот я весь день эту чугунину в фотошопе и грузил. biggrin.gif

Автор: Melisse Nov 20 2017, 14:46

Цитата
Макс, зараза, по-прежнему MDL-формат в упор не видит, как и 10 лет назад.

Попробуй это
https://neverwintervault.org/project/nwn1/other/tool/nwmax-version-08c00-updated-3dsmax2015

Автор: Chiffa Nov 20 2017, 14:51

Melisse, спасибо за подсказку. Но и при "традиционных" 24-х все пахает прекрасно, только что проверил. Но если комп приличный, берем 32, конечно, красивше же подучается. biggrin.gif
Еще раз спасибо за скрипт! Он работает вообще только тогда, когда у моего робинзона этот молоток в правой руке. То есть реализм рулит!

З.Ы. Ну а за подсказку по максу и не знаю, как благодарить. Больная мозоль. И очень давно...

Автор: Aiwan Nov 20 2017, 16:08

Давай, делай свой модуль о приключениях ЗК на лесоповале smile.gif

Автор: Chiffa Nov 20 2017, 16:43

Цитата(Aiwan @ Nov 20 2017, 16:08) *
Давай, делай свой модуль о приключениях ЗК на лесоповале smile.gif


Этот пост будет чистой воды офтопом, так что карайте, админы, если что не так.

Melisse, Aiwan, denis0k, просто хочу сказать спасибо за то, что вы есть. angel.gif
Понимаете, без ваших подсказок, помощи, без дружеских подначек начинаю чувствовать себя маразматиком, который занят не пойми чем. И фиг бы я вообще сделал хоть что-то , не говоря уже о таких сложных вещах, как приключения ЗК на лесоповале. biggrin.gif
А зайдешь на ГМ - и это мерзкое чувство сразу испаряется.

Вообще засесть за "робинзонаду" меня заставило жесткое разочарование в игре "ARK Survival Evolved", от которой я некоторое время буквально фанател. Начиналась она именно как робинзонада, причем очень хорошая. Но вскоре разрабы испохабили ее донельзя (это ПМСМ, разумеется). Я не стал материть разрабов, как многие форумчане на Стиме. Могу понять людей, денег всем хочется, вот и пошли на поводу у массовой школотной аудитории. Ладно, речь не об этом. Просто вместо того, чтобы бессмысленно ломать копья на Стиме, вспомнил старое правило: если хочешь, чтобы что-то было сделано хорошо, делай это сам. Правило действительно мощное, исключение из него, пожалуй, только одно - секс. Да и то, как наслышан, далеко не всегда и вовсе не у всех. prankster2.gif

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

К счастью, оказался не один. Спасибо!!!


Автор: Aiwan Nov 20 2017, 18:34

Ну так ПЛ и делался из расчета того, что оригинал НВН не воткнул. Прям непонятно все было как-то smile.gif Захотелось сделать что-то свое.
Успешных мучений и увлечений wink3.gif Эх, вспоминаю бессонные ночи у тулсета, тестинг кривоскриптов, мапинг, диалогописание...

Автор: denis0k Nov 21 2017, 15:52

Бренд НВН и так слабо узнаваем, в отличие от того же Морровинда (а они одногодки). Если бы не тулсет, про него вообще бы никто не знал smile.gif

Автор: Chiffa Nov 22 2017, 20:15

Цитата(denis0k @ Nov 21 2017, 15:52) *
Бренд НВН и так слабо узнаваем, в отличие от того же Морровинда (а они одногодки). Если бы не тулсет, про него вообще бы никто не знал smile.gif

Что верно, то верно. "Беседка" вообще "делает" биоварей как хочет. И ДЭ супротив Скайрима что Невер сутротив Морра... ну и так далее. Помню, как сын, поглядев на мои мытарства, стал мне втолковывать: "Да делай ты свою робинзонаду в Скайриме! Разберешся быстрее и легче, и возможностей больше, а про графу вообще молчу!"
Но все-таки неверовкий френди-тулсет (так его однажды обозвал Lex) позволяет сделать то, что вряд ли возможно сделать в мастерских от "Беседки". А именно это, то есть характеры, личности, отношения между ними меня как раз интересуют больше всего. И мне трудно представить ПЛ (не говоря уже о "Монетке"!) на движке "Морровинда"...
Но это, разумеется, ПМСМ. И вообще заканчиваю флуд, перехожу к делу.
А дело застревает в дверях. Точнее, на дверях.
Задумался о будущем робинзона. Не век же ему робинзонить и жить в пещере. Нарыл на волте один интересный хак, перетащил оттуда модельки тросниковых и глинобитных хижин. Избушки смотрятся чудо как хорошо, даже хотел скрины выложить.
Ну, думаю, щас я в очередной раз ограблю Aiwanа, благо, он разрешает. Вытащу его знаменитые двери из полотна. И заменю полотно на бамбук.
И вот пока сижу, курю этот самый бамбук. prankster2.gif
Потому что ни одна дверь, что стандартная, что полотняная на плейс не ставится. Только секретные двери, которые вообще можно лепить куда угодно, хоть в молельне Сан в Арбонне, хоть на палатку командира гномов в Верхнем Тракте, хоть на "мои" тросниковые хижины.
Но даже деревянная секретная дверь на этой хижине смотрится инородным телом. Всю красотищщщу уродует. Про каменные вообще молчу...
И вот очень мне интересно: а можно ли вообще присобачить на плейс дверной проем как у тайла? Или как-то более иначе это решить? Например, отбамбучить секретную дверь? Она вроде тоже плейс, но в табличке "placeables.2da" ее нет. Как и в табличке "genericdoors.2da".
Не подскажете, что и в каком направлении ковырять?
И еще... Наверное, вопрос больше к вам, уважаемые Melisse и denis0k. Помню, вы обсуждали тему, разрешать игрокам на шарде строить свои дома или нет? Если я правильно вас понял, технически эта задача давно решена, и спор шел в основном о том, что "город не резиновый".
Не подскажете методу? Нет, эту тросниковую хижину с палитры вызвать легко, типа герой ее "постороил". Тут дело в другом. В хижинах у меня будет жить племя прекрасных дикарок. А герой себе "построит" что-то более другое, типа бревенчатой избы. Причем хотелось бы реализовать это поэтапно. То есть, вот фундамент заложил. Вот одна стенка, потом другая. Ну и крышей заканчивается, как везде в России...
Если это сложно и "чайник" вроде меня вряд ли такое осилит, так и скажите. Никаких обидок, давно этим не болею...
Спасибо.


Автор: Aiwan Nov 22 2017, 20:22

Цитата(Chiffa @ Nov 22 2017, 23:15) *
Потому что ни одна дверь, что стандартная, что полотняная на плейс не ставится.

Если палатки твои это плейс, то никак. Хотя, я может и отстал от жизни... prankster2.gif
Только если есть хак плс дверей, типа секретных.

Автор: Chiffa Nov 22 2017, 21:53

Спасибо! Ты прав. Нашел секретную дверь. Буду ее бамбучить... Хотя жалко. Шибко уж хотелось, чтобы бамбук раздвигался, как тряпоч... ой, прости! - шикарные полотнища в "Монетке".
Но видать, не судьба. swoon.gif

Автор: denis0k Nov 23 2017, 23:17

Цитата
А герой себе "построит" что-то более другое, типа бревенчатой избы. Причем хотелось бы реализовать это поэтапно. То есть, вот фундамент заложил. Вот одна стенка, потом другая. Ну и крышей заканчивается, как везде в России...
Для этого, очевидно, нужны плейсы в виде фундамента, стен и т.п.

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

Вообще, самый простой вариант для сингла - фазировка. Несколько версий одной и той же локации на разных стадиях развития сюжета.

Автор: Chiffa Nov 24 2017, 14:10

Цитата(denis0k @ Nov 23 2017, 23:17) *
Для этого, очевидно, нужны плейсы в виде фундамента, стен и т.п.

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

Вообще, самый простой вариант для сингла - фазировка. Несколько версий одной и той же локации на разных стадиях развития сюжета.


И по моему ПМСМ тоже дурное. И на все грабли, которые ты описал, я успел споткнуться. Ну, как обычно. biggrin.gif
Нарыл домик-плейс на волте (кстати, спасибо за ссылку, с гугл-переводчиком даже я с там там коей-чего понимать). Смех, но домик - один в один тайловый деревенский 1х1. Поставил рядом - точно, он! Только плейс.
Вызываю с палитры - герой сквозь него ходит. Ну ладно, об этом читал в теме Melisse, она же и учила, как это лечить. Вылечил. Герой вызвал домик с палитры и в нем... ты уже догадался, да? - ну ясен пень, застрял. biggrin.gif
Продолжаем умственный изврат. Герой бежит к исполнять танцы с бубном одному плейсу, а домик спавнится на другом, чуть в стороне. В конце-концов добился, что домик появляется стенкой прямо у физии героя, а тот молотком машет, типа заколачивает последние гвозди. prankster2.gif
Ну и вторая серия Мерлезонского балета. Если домик валиден, включается триггер. Герой спикстрингает: "Ну все, осталось только навесить дверь". Бежит к дверному проему, опять танцы с бубном, спавнится дверь. Вот ведь не думал, что когда-то самую обычную, дефолтную деревянную дверь буду выдирать из базы и прописывать в хак как секретную! Но что делать, на таком деревенском домике именно она смотрится наиболее органично. Дефолтная секретка скорее для внутренней отделки.
Ну чего мне стоило добиться, чтобы дверь спавнилась точно в проеме - писать не буду. Она вообще сначала поперек становилась. biggrin.gif
Понятно, всем этим извратом я занимался на "Полигоне". Два дня... И теперь локу, где все таки получилось, очищу от всего лишнего и аккуратненько экспортирую в "робинзонаду". И все эти тросниковые круглые хижины прелестных дикарок (кстати, еще ню-хак на волте нарыл, тоже подключу, дикарки же!) - буду расставлять возле подготовленного места, где герой свой дом "посторит".

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

З.Ы. Кстати, о тросниковых хижинах. Они и правда чудо как хороши. Француз, который их нарисовал - ну настоящий Художник. Блин, с заглавной буквы "Х"! biggrin.gif
Только вот он напрочь забыл о такой фигне, как гемплей.
В самый большой домик еще как-то становится широкая секретка ("злая каменная" дверь, которую я переделал на бамбуковую). Но она маловата во высоте. В самую маленькую я запихал ... тюк сена, - герой хоть черта лысого проюзает за хвост, если на этом хвосте нужный скрипт. А что делать со средней пока ума не приложу. Все двери торчат углами из арки - смотрится отвратительно.
Но это не вопрос, сами понимаете. Так, к слову...

Автор: denis0k Nov 24 2017, 23:58

Цитата
И вот мне по прежнему интересно: как же вы собирались на шарде игрокам разрешать строительство? Это уже не с целью перенять методу, а просто интересно. Так сказать, для общего развития... Не фазировкой же, на самом деле!
Самое простое - поставить готовые дома (как многоквартирные, так и одиночные), и туда уже пускать игроков с ключами (т.е. не строить, а покупать готовое). Можно сделать каждому по интерьеру, который он сам может обставлять как хочет, а при тычке в триггер уже телепортировать куда надо.

Автор: Melisse Nov 25 2017, 12:58

Цитата
И вот мне по прежнему интересно: как же вы собирались на шарде игрокам разрешать строительство? Это уже не с целью перенять методу, а просто интересно. Так сказать, для общего развития... Не фазировкой же, на самом деле!
Спасибо.

Несколько вариантов:
1. Игрок рисует - разраб вставляет.
2. Инстансинг локации. т.е. в определенном месте вы выбираете себе вариант дома из N вариантов и его интерьер из N вариантов - инстансите эти локации - вуаля у вас свой дом, который построен в таком-то месте. К нему есть доступ и все прочее.
3. Уже готовые дома - выбираем интерьеры и инстансим локации. Можно и без инстансов в это случае - тогда дома будут, что называется - физически присутствовать.

Автор: Chiffa Nov 25 2017, 15:40

Цитата(Melisse @ Nov 25 2017, 12:58) *
1. Игрок рисует - разраб вставляет.

Дико извиняюсь за каламбур, но в шардах я не шарю. Впрочем, как и во многом другом. biggrin.gif
Я правильно понял: игрок просто делает себе домик в своем тулсете, а потом отправляет разрабу ерефку? Разраб ее импортирует и подключает к шарду, как новую локацимю?
Цитата(Melisse @ Nov 25 2017, 12:58) *
2. Инстансинг локации. т.е. в определенном месте вы выбираете себе вариант дома из N вариантов и его интерьер из N вариантов - инстансите эти локации - вуаля у вас свой дом, который построен в таком-то месте. К нему есть доступ и все прочее.

Можно чуть подробнее начиная со слова "инстансинг"? Шард имеет несколько, так сказать, "спрятанных" локаций, которые никому, кроме разрабов и ДМ-ов, не видны? А потом игрок выполнил какой-то суперский квест или еще что важное сделал, получил право на свой дом. Ему предлагают выбор, игрок его делает, и невидимая лока мгновеннно (таки инстант!) делается видимой, доступной и все такое? Или я опять какую-то фигню несу?

Я к чему спрашиваю. Для общего развития, все так. Но мне еще и хочется благодаря этому развитию сочинить свою методу строительства, взяв полезное от уже действующих. Например, как строят в игре "Life is Feudal". Там разрабы не стали заморачиваться с последовательным возведением фундаментов, стен и так далее. Надо тебе дом. Выбираешь место. Если подходящее, то появляется даже не фундамент, а так, разметка, четыре бревна прямоугольником и пара досок наискось. Но эта разметка, как я понял, есть контейнер со счетчиком. Пихать в этот контейнер можно только то, что требуется для строительства и ровно столько, сколько надо. Пытаешься положить "лишнее" бревно - оно уже не лезет. А когда все собрано, становиться доступна команда "построить" - и вуаля! - "из ниоткуда" появляется твой домишко. Или целый замок, если вы всем кланом таскали туда мрамор (его 5.000 надо, а больше сотни ни один игрок не утащит, и еще камень, его не то 20, не то 40 к надо, не помню, + бревна, доски ets...).
Как сами понимаете, на "Полигоне" я спавнил домишко и дверь и подгонял их друг к другу, не затрачивая никаких ресурсов. Но в игре их тратить придется! Причем если прописать, что на целый дом ушло, к примеру, по 5 бревен, кирпичей и извести, то никакого правдоподобия не будет. Где это видано, чтобы ресы для дома все целиком в инвентарь влезли! Зараз. Так не бывает...
Найти плоскость и покрасить ее "под кирпич" нетрудно. Также легко сделать этот "фундамент" контейнером. Но вот как приладить к нему "счетчик" и какой? Пока никаких толковых идей...

Ладно, иногда хорошие идеи приходят сами, если отвлечься от темы. Так что пойду я, уважаемая Melisse, ковырять твою тему. Очень уж меня табличка "appearance.2da" интересует. И в самом деле, зачем мне 4 слона! Двух за глаза хватит, большого и поменьше. Тем более, что одного вообще назвали мамонтом. Не умеешь нарисовать нормальную шерсть зверюге, так и нечего обзывать его именем благородного животного. prankster2.gif
И носорог... Это ж простой кабан, которому рог нелепо прилепили. Нет, носорог нужен, но не такой же...
А вот крокодил - красавец! Только он, зараза, совсем в другом хаке.

Короче, мне есть чем заняться. Чего не пойму, спрошу, ладно? И если кому из мастеров какие идеи насчет фундамента-контейнера случайно придут в голову - поделитесь? А нет, так нет. Мне главное, как уже писал, понимание того, что я не одинок.
Спасибо.

Автор: Melisse Nov 27 2017, 20:20

Цитата
Я правильно понял: игрок просто делает себе домик в своем тулсете, а потом отправляет разрабу ерефку? Разраб ее импортирует и подключает к шарду, как новую локацимю?

да
На некоторых шардах процесс с интерьерами домов был в таком виде и автоматизирован. Т.е. ты загружаешь - локация проверяется - и просто заходишь туда героем и все

Цитата
Можно чуть подробнее начиная со слова "инстансинг"?

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

Автор: Chiffa Nov 30 2017, 23:18

Доброго времени суток!

Возник один вопрос, как всегда у меня, нелепый. А именно: как велика "грузоподъемность" ПС в смысле локалок? Сколько их на него можно повесить?

А дело вот в чем. У меня три монстра-невидимки привязаны к иструментам. Это мультитул, молоток и клещи для наковальни. Но потом их будет гораздо больше. Так вот, я заметил, что у этих монстров не регулируются ветки диалога. Ставишь локалку, проверяешь ее - не работает.

Сначала думал - глюк какой-то. Монстр же один, тег и даже реф один и тот же. Вся и разница, что вызывается с палитры каждый раз заново. Потом дошло, что в этой разнице и дело. Получается, что движок ставит на монстра переменную. Примерно так, как и мы ее пишем в тулсете. Но монстр уничтожается в конце диалога. Заново вызывается пусть тот же, но "свеженький", без переменной.
Это верно?
И получается, что локалки можно вешать только на героя. Тогда диалог будет переключаться, как надо.
Проверил. Так оно и есть.

Вот я и малость встревожился: монстров-"инструментов" у меня много будет. Мой ПС не "надорвется"? И если надорвется, есть способ это лечить?

Автор: Aiwan Dec 1 2017, 05:35

Можешь вешать локалки хоть на невидимый объект, или на локацию в которой действие, без разницы. Создай на локации невидимый объект или поставь вейпоинт где спавнится твой монстр инструмент, это и будет хранитель локальных переменных.

Автор: denis0k Dec 1 2017, 08:05

Какое-то внутреннее ограничение, связанное с размером массива, конечно есть. Но вряд ли оно достижимо при разумном использовании. Моё мнение - самый минимум, который там может быть, - 8 бит. Это 128 или 256 (зависит от того, хранится ли знак "минус").

Автор: Aiwan Dec 1 2017, 09:34

У локальных переменных есть числовые значения. Я боюсь ты не вдавался в тонкости этого вопроса smile.gif Или вдавался?
Приведи пример скрипта, мы поможем с оптимизацией.

Автор: Chiffa Dec 1 2017, 15:05

Aiwan, denis0k, спасибо. Кажется, я правильно вас понял. Правда, не совсем усвоил насчет знака минус. В ПЛ я скоммуниздил очень нужный мне скрип, который регулирует отношения хеньша к игроку. И решил проверить, может ли он переходить за ноль. Оказалось, еще как может. Заставил ПС постоянно хамить хеньше, довел отношения до -100, после чего портнул хеньша в клозет (то есть на закрытую арену), а ПС закатал в тюрягу "за попытку изнасилования собственной помощницы" biggrin.gif Это все на "Полигоне", я говорил, что есть у меня специальный полезный мод для издевательств над ПС.
denis0k, ты что-то подобное имел ввиду, когда говорил о знаке минус, или совсем другое?
Насчет цифровых значений тоже вроде вникал. Правда, довольно поверхностно и скорее интуитивно. Aiwan, вот, к примеру, твой скрипт из Андры:

Neverwinter Script
//:://////////////////////////////////////////////
//:: Created By: WRG! Aiwan aiwan@e-mail.ru
//:://////////////////////////////////////////////
//::   ЗАКРЫВАЕТ СТРОКУ НПС ПОСЛЕ РАЗГОВОРА
//:://////////////////////////////////////////////
int StartingConditional()
{
    if (!GetLocalInt(OBJECT_SELF,"SPEAK_1"))
      {
      SetLocalInt(OBJECT_SELF,"SPEAK_1",TRUE);
        return TRUE;
      }
       return FALSE;
}


Очень полезный скрипт, иногда просто незаменим. Одна беда: он, зараза, действителен для всех без исключения неписей модуля. То есть если тебе надо закрыть еще одну веточку в диалоге любого непися, будь любезен, пиши: "SPEAK_2", потом "SPEAK_3" ну и так далее... Таким макаром можно наплодить стопитьсот этих "SPEAK_ов" и просто в них запутаться. Я этот скрипт немного переделал. Примерно так:
Neverwinter Script
int StartingConditional()
{
    if (!GetLocalInt(OBJECT_SELF,"SPEAK_1"+ GetTag(OBJECT_SELF)))
      {
      SetLocalInt(OBJECT_SELF,"SPEAK_1"+ GetTag(OBJECT_SELF),TRUE);
        return TRUE;
      }
       return FALSE;
}

То есть теперь он привязан к конкретному неписю, на другого его можно смело ставить с тем же номером, ветка диалога закроется. Проверил - работает. Естественно, я сохранил его под другим названием. Потому что оказываться от твоего, Aiwan, скрипта, я не собираюсь, иногда требуется заткнуть рот на определенную тему именно всем неписям...
Это как, можно считать "вниканием" в числовые значения, или я очередную глупость сморозил? prankster2.gif

Ну, а за предложение помощи в отладке просто и не знаю, как благодарить! И тут уж, без обид, ловлю на слове. Потому что где она точно понадобится - это когда у меня дело дойдет до фильмов. Я говорил, что шарахался от катсцен, запуганный "висяками" ПЛ-овского бандита. Но теперь бояться перестал и очень даже начинаю увлекаться.
Так что спасибо еще раз.

З.Ы. Кстати, Aiwan, у тебя я тоже занял скрипты Алишан, очень понравилось, что они регулируют отношения независимо от того, хеньша она или еще нет. Надеюсь на их основе налаживать отношения с фракцией очаровательных дикарок, которых мой робинзон найдет ближе к середине мода. Причем тут надо разные значения. Ну, с конкретной дикаркой, которой ПС принес рыбину вкусную или ожерелье какое красивое сразу Love+10 и одновременно с фракцией Love+1. Вот так и пахай, парень, пока фракция ТруЪ_Нейтрал не перейдет во фракцию Друг_ПС. Только тогда с тобой заговорит Великий Шаман (нарыл фотку настолько татуированного полинезийца, что понять не могу, как он выжил, бедняга).
Тут тоже в отладке, боюсь, без вас, ребята, вряд ли что выйдет путное...

З.Ы.Ы. Сорри за многабукафф. Говорил уже, профессионально-нравственная деформация. Лечению не поддается

Автор: denis0k Dec 1 2017, 18:18

Разговор вроде был о количестве локалок, так что я о нём. Поясню.

Как ни крути, локалки сохраняются в массиве, у массива есть размер. Если предположить, что размер массива не зарезан специально до какого-то абсурдного числа (типа 10, 50 и т.п., что в 21-м веке редко, но таки бывает), то ограничивает нас тип переменной индекса этого массива. Самый минимум, что могли сделать биовари - 1 байт (8 бит, 2^8=256 "значений"). И тут два варианта:
- знаковый int8/char: диапазон -128...127, но т.к. индекс массива обычно 0+, то это даёт размер в 128 (этот же диапазон, например, у скиллов и абилок);
- беззнаковый unsigned int8/char: диапазон 0...255, размер 256.

Это именно тот минус, о котором я говорил, - часть реализации массива, а не особенности внутри скрипта.

Хотя я ни разу не замечал проблем с локалками. Местами использовал довольно много, даже массивы на локалках реализовывал, да и не только я. А на старых серверах без внешней бд даже все фишки чара/акка хранили в локалках на итемах.

Автор: Chiffa Dec 1 2017, 18:34

Цитата(denis0k @ Dec 1 2017, 18:18) *
Это именно тот минус, о котором я говорил, - часть реализации массива, а не особенности внутри скрипта.

Хотя я ни разу не замечал проблем с локалками. Местами использовал довольно много, даже массивы на локалках реализовывал, да и не только я. А на старых серверах без внешней бд даже все фишки чара/акка хранили в локалках на итемах.


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

Тем более, что благодаря подсказке Aiwanа я уж точно не стану грузить на ПС лишнее. Стоит наковальня, статичный плейс - так пусть хоть локалки хранит, все польза. Это ведь только с мультитулом герой по всему острову бегает. А все остальные "инструменты" вполне могут поработать "чемоданами".

Спасибо.

Автор: Melisse Dec 2 2017, 23:54

В кастомных ELC значения из 2да вешались массивами на 1 объект, это тысячи локалок. Все работало как часы.

Автор: Aiwan Dec 3 2017, 06:08

Цитата(Chiffa @ Dec 1 2017, 18:05) *
Насчет цифровых значений тоже вроде вникал. Правда, довольно поверхностно и скорее интуитивно. Aiwan, вот, к примеру, твой скрипт из Андры:

Ну я тебя читаю на раз два smile.gif Скорее всего из-за того, что я сам был точно такой как ты, гуманитарий скорее чем скриптер-логик. Короче, ты все понял не так snoozer_17.gif Разжевываю, хоть это и есть в мануале по авроре, почитай вниматочно.
Локальная переменная это как название улицы. Например, переменная "УЛИЦА_СТРОИТЕЛЕЙ", и это "стринг" буквенное обозначение. Но, кроме всего оно имеет и числовое обозначение "интеджер" типа номер дома. Если мы не указываем его конкретное значение, то оно будет 1 или TRUE (что значит ИСТИНА для языка компьютера).
Итак что имеем:
Neverwinter Script
int StartingConditional()
{
    object oPC = GetPCSpeaker();
    SetLocalInt(oPC,"QUEST_KILL_BILL", 1);
}


Это вторая часть Марлезонского балета.

Neverwinter Script
int StartingConditional()
{
    object oPC = GetPCSpeaker();
    SetLocalInt(oPC,"QUEST_KILL_BILL", 2);
}


Это третья часть...

Neverwinter Script
int StartingConditional()
{
    object oPC = GetPCSpeaker();
    SetLocalInt(oPC,"QUEST_KILL_BILL", 3);
}


И таких частей может быть сто тыщ мульонов. А ты делаешь так:

Neverwinter Script
int StartingConditional()
{
    object oPC = GetPCSpeaker();
    SetLocalInt(oPC,"QUEST_KILL_BILL_1", TRUE);
}


Часть два
Neverwinter Script
int StartingConditional()
{
    object oPC = GetPCSpeaker();
    SetLocalInt(oPC,"QUEST_KILL_BILL_2", TRUE);
}


Часть три:

Neverwinter Script
int StartingConditional()
{
    object oPC = GetPCSpeaker();
    SetLocalInt(oPC,"QUEST_KILL_BILL_3", TRUE);
}


Что в принципе работает но реализовано через задний проход. В общем быстро в тему для скриптов для начинающих и грызи PDF по авроре, что я писал.


Автор: denis0k Dec 3 2017, 11:30

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

Я изучал программирование в вузе (правда при этом я занимался им с 5-го или 7-го класса школы), абсолютное большинство студентов просто зубрит конструкции. Экзамены сдать это позволяет, а вот программировать - не очень. Рекомендую искать инфу по основам программирования, где рассказывается про алгоритмы, блок-схемы и т.п.

Автор: Aiwan Dec 3 2017, 12:26

Я тоже учил языки программирования, и тоже был ни в зуб ногой. Только Аврора дала понять что ЭТО такое и как там все просто и сложно.

Автор: Chiffa Dec 3 2017, 16:59

Цитата(Aiwan @ Dec 3 2017, 06:08) *
В общем быстро в тему для скриптов для начинающих и грызи PDF по авроре, что я писал.

Слушаюсь, мой генерал! prankster2.gif
Нет, серьезно, спасибо за разжевывание. Твой труд не пропал даром, все-таки ты имеешь дело не с самым безнадежным тупицей.
Цитата(denis0k @ Dec 3 2017, 11:30) *
Нужны базовые знания по программированию и составлению алгоритмов. После этого язык значения не имеет вовсе, можно со справочником писать на любом после пары-тройки дней знакомства с синтаксисом.

Я изучал программирование в вузе (правда при этом я занимался им с 5-го или 7-го класса школы), абсолютное большинство студентов просто зубрит конструкции. Экзамены сдать это позволяет, а вот программировать - не очень. Рекомендую искать инфу по основам программирования, где рассказывается про алгоритмы, блок-схемы и т.п.

Кстати, весьма заметно, что программирование ты постигал именно вниканием, а уж не зубрежкой. По твоей логике заметно. Это я понял, просто прочитав два-три твоих поста. Тут как у Жванецкого: "Я не разбираюсь в автомобильных шинах, моя работа - разбираться в людях."
К слову, "зубрежный" подход универсален для любых ВУЗов, не обязательно технических. У нас тоже таких хватало: вызубрят в чем отличие статьи от корреспонденции, к примеру, экзамен сдадут на "отлично". Только потом над их писаниной покатывается со смеху весь Мухосранск.
За совет спасибо. Попробую именно вникать. В базу. ГСУ сильно мешает, ясен пень, но ... попробую...

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)