Issue information

Issue ID
#6168
Status
Working as Intended
Severity
None
Started
Hercules Elf Bot
Jul 4, 2012 5:49
Last Post
Hercules Elf Bot
Jul 10, 2012 14:53
Confirmation
Yes (0)
No (4)

Hercules Elf Bot - Jul 4, 2012 5:49

Originally posted by [b]Eradicate[/b]
Not sure if this should be in the core section or not....


[b]Question:[/b]
Shouldn't the .variables have a scope for that NPC only and not span to the duplicates?

[b]Script Example:[/b]
[CODE]
prontera,120,120,2 script Test1#1 100,{
mes ".var = "+ .var;
close;
OnWhisperGlobal:
set .var, 3;
end;
OnInit:
set .var, atoi(strnpcinfo(2)); // get the hidden name
end;
}
prontera,122,120,2 duplicate(Test1#1) Test2#2 100
[/CODE]

[b]Problem:[/b]
Test1#1 NPC would load first then Test2#2.
In server start-up, both NPCs would say ".var = 2", even though Test1#1 should say ".var = 1"
However, it is inconsistent since if you reload the scripts in-game, both would say ".var = 1"

[b]Reason:[/b]
I think it is because the .var variable is being shared between these two NPCs since, if you whisper Test2#2, setting its .var to 3, talking to Test1#1 will also show 3.

As a scripter, i find it a lot easier to create optimized code and more flexibility if the scope is within an NPC and not span to its duplicates. That is also what I understood from reading the documentation. If it is working as intended, perhaps update the doc then?

Hercules Elf Bot - Jul 4, 2012 8:14

Originally posted by [b]og2[/b]
According to the problem you mentioned it should be in Core.

As in for the issue that you seem to have, I'm not exactly sure if I understood but here's a code I made for a mining script of mine long ago.

[code]

if(.oreinuse$==strnpcinfo(0)) { message strcharinfo(0),"Copper Ore still not yet available!"; end; }
/* callfunc "MiningRocks","CopperRock"; */ set .oreinuse$,strnpcinfo(0); initnpctimer strnpcinfo(0); end;
OnTimer5000: if(.oreinuse$==strnpcinfo(0)) { set .oreinuse$,""; }
end;
}

ein_dun01,218,161,1 duplicate(CopOre) Copper Ore#c1 1620
ein_dun01,216,159,1 duplicate(CopOre) Copper Ore#c2 1620

[/code]
I disabled this line in case u want to test
[color=#ff0000]/* [/color]callfunc "MiningRocks","CopperRock"; [color=#ff0000]*/[/color]

The code seemed to work for me if you want to work with a single code, that works differently, to each duplicate, I mean not differently, more like...the same but with their OWN use, well you know >.<

This post has been edited by og2 on Jul 4, 2012 8:16

Hercules Elf Bot - Jul 4, 2012 8:58

Originally posted by [b]Eradicate[/b]
It's late here so I can't give a full response (but I will in the morning when I am less tired), but og2, I believe you are misunderstanding me. You are updating your variable in such a way that you WANT the scope to span across onto the duplicates... You might as well use a $@variable type instead. Or alternatively, you should be using getvariableofnpc instead (if this bug report is valid).

Well.. I don't think I'm explaining what I mean very well... I'll give a more detailed explanation tomorrow when I'm not tired. The only other example I can provide would be to explain in terms of object oriented programming. Hopefully that won't make things confusing lol

Anyways, Just wanted to clear up that og2's response isn't exactly what I mean so that the devs looking into this issue won't be confused...

Hercules Elf Bot - Jul 4, 2012 9:01

Originally posted by [b]KeyWorld[/b]
I don't think it's a bug, just the way duplicate npc work : there is one source script, all duplicate point to this script (the src don't copy the script for each duplicates).

In my opinion it works as expected and it's an awesome namespace to share variable between npcs without pollute the global variables ($@var). (I use this to manage all my mini-games : chess, bomberman, connect 4, guitare hero and other scripts ).

Hercules Elf Bot - Jul 4, 2012 10:26

Originally posted by [b]malufett[/b]
I agree with Keyworld...when the server duplicates script it doesn't create another object the new script is link with the original one..which it is more efficient in terms of memory spacing/allocation....

Hercules Elf Bot - Jul 4, 2012 13:50

Originally posted by [b]Euphy[/b]
Imagine the pain that would be caused by scripts like these:
http://sushiduy.plesk3.freepgs.com/ROScripts/ToastyWarper/toastywarper_132.txt

In my opinion, NPC variables should always be kept constant within duplicates. Functions are such an easy workaround that there's no reason to change this.

Hercules Elf Bot - Jul 4, 2012 19:43

Originally posted by [b]Myzter[/b]
We could add a new command to the core:

[CODE]- script test -1,{
mes "[Box of Dreams]";
mes "Hi, this is a box of dreams, please select a dream to start the fly.";
next;
switch(select("Nightmare:Peace Heaven:Underwater")) {
case 1: goto f_1;
case 2: goto f_2;
case 3: goto f_3;
case 4: goto f_4;
case 5: goto f_5;
case 6: goto f_6;
}
f_1:
dispbottom "This is the base dream " + .myvar;
end;
f_2:
dispbottom "This is the base dream " + (.myvar + 1);
end;
f_3:
dispbottom "This is the base dream " + (.myvar + 2);
end;
f_4:
dispbottom "This is the base dream " + (.myvar + 3);
end;
f_5:
dispbottom "This is the base dream " + (.myvar + 4);
end;
f_6:
dispbottom "This is the base dream " + (.myvar + 5);
end;
OnInit:
var .myvar, 10;
}

// This could be the new "Inherit" command:
ein_dun01,218,161,1 inherit(test) test#inh 1620, {
f_5:
dispbottom "This is the inherited dream " + (.myvar + 4);
end;
f_6:
dispbottom "This is the inherited dream " + (.myvar + 5);
end;
OnInit:
var .myvar, 20;
}

// This is a common duplicate:
ein_dun01,218,161,1 duplicate(test) test#dup 1620, {[/CODE]

If you talk with the duplicate, the response will be the same as the original script, if you change .myvar in any of the duplicates, the global .myvar in the original namespace will change.

* The inherit command create a copy of the original script but replace all existent labels with the specified in the inherited script, in the sample, the inherited copy will have a re-definition of the f_5 and f_6 and off course, its own namespace, so if you change .myvar the value is not changed in the original script or his duplicates.

Why a command like this?: Allow you to create a powerful method to create modules or enhanced scripts based on any standard script.

// This is the memory version of the inherited script

[CODE]- script test#inh -1,{
mes "[Box of Dreams]";
mes "Hi, this is a box of dreams, please select a dream to start the fly.";
next;
switch(select("Nightmare:Peace Heaven:Underwater")) {
case 1: goto f_1;
case 2: goto f_2;
case 3: goto f_3;
case 4: goto f_4;
case 5: goto f_5;
case 6: goto f_6;
}
f_1:
dispbottom "This is the base dream " + .myvar;
end;
f_2:
dispbottom "This is the base dream " + (.myvar + 1);
end;
f_3:
dispbottom "This is the base dream " + (.myvar + 2);
end;
f_4:
dispbottom "This is the base dream " + (.myvar + 3);
end;
f_5:
dispbottom "This is the inherited dream " + (.myvar + 4);
end;
f_6:
dispbottom "This is the inherited dream " + (.myvar + 5);
end;
OnInit:
var .myvar, 20;
}[/CODE]

Regards,
Myzter

Hercules Elf Bot - Jul 4, 2012 20:58

Originally posted by [b]Euphy[/b]
But Myzter, you can do about everything you've stated with functions. You just need to replace labels with a "switch" and *boom*, same result with no additional source code. Unless I'm missing something? o:

Hercules Elf Bot - Jul 5, 2012 0:17

Originally posted by [b]og2[/b]
I understand the point, but it's still possible with the current script engine, personally I don't see the need on this.

Hercules Elf Bot - Jul 5, 2012 7:49

Originally posted by [b]KeyWorld[/b]
@Myzter
It will be to difficult to add a module base on label overwrite, a label isn't structured to stop somewhere.

I think, [b]if[/b] we have to change something, give an optional argument to duplicate() to know if we point to the source script, or copy the source script. It will be far enough.

Hercules Elf Bot - Jul 5, 2012 14:29

Originally posted by [b]Myzter[/b]
[quote name='KeyWorld' timestamp='1341474553' post='11620']
@MyzterIt will be to difficult to add a module base on label overwrite, a label isn't structured to stop somewhere.I think, [b]if[/b] we have to change something, give an optional argument to duplicate() to know if we point to the source script, or copy the source script. It will be far enough.
[/quote]
You can split the script using the labels as separator, the results are divided in two different sections:

1. Script body
2. Label blocks, every one with a unique name

My point is try to add some inheritance to the scripting language, giving the chance of create programming patterns that simplify the creation of new and more complex scripts.

By example, you could create a quest script with timers, player selection, validations and anything a good script could need, then use that script to create new quest scripts that uses the same functionality but declaring new parameters and adding new specific functionality.

If you fix any bug in the base script, all other scripts based on it will be fixed automatically.

Hercules Elf Bot - Jul 5, 2012 15:01

Originally posted by [b]KeyWorld[/b]
Maybe it will be good to split this suggest on the dev board ?

In my opinion you can't determine portion with label, there is a start but you can't find an end (except if you use "{}" to determine code: LABEL:{ dothis; }).
And it will be a pain to ass to :
-> parse base script to bytecode
-> parse duplicate to bytecode
-> merge duplicate bytecode to base script bytecode (find labels reference in buffer, remove all the content from this label (stop to "end" ? "close" ? "return" ? "goto" ?? "jump_zero" ?? another label ? ) and erase the buffer with new values.

I think it's far better to manage what you want using functions.

Hercules Elf Bot - Jul 5, 2012 15:52

Originally posted by [b]Myzter[/b]
Yes, it's a good idea to split this conversation.

The way to determinate the portion of each label is simple, the next label (or the end of the script) is the end of the current label.

We don't need to remove anything, except the re-coded labels or body, replacing the entire code with the new one, without merging portions of code inside the label block.

To avoid the bitecode problems, we should process the inherited scripts based on the text version of the base script, with a simple "split" or a very basic parser, after that we can process the resultant code as bitecode.

It's true, we can write complex scripts using functions, but you can't orchestrate a pattern script in that way, the functions itself doesn't resolve the limitation of the language.