Jump to content

  •  

Bug Tracker Migration

June 3rd
Good news everyone! The staff has decided that it is time to slowly kill off this Bug Tracker. We will begin the process of slowly migrating from this Bug Tracker over to our Github Issues which can be found here: https://github.com/HerculesWS/Hercules/issues

Over the next couple of days, I will be closing off any opportunity to create new reports. However, I still will keep the opportunity to reply to existing Bug Reports. Doing this will allow us to slowly fix any bug reports we have listed here so that we can easily migrate over to our Issue Tracker.

Update - June 7th 2015: Creating new bug posts has been disabled. Please use our https://github.com/HerculesWS/Hercules/issues tracker to post bugs. Users are still able to reply to existing bug posts.

- Administration

Issue Information

  • #006168

  • 0 - None Assigned

  • Working as Intended

Issue Confirmations

  • Yes (0)No (4)
Photo

Duplicates and . variables

Posted by Hercules Bot on 04 July 2012 - 05:49 AM

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


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

Script Example:
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

Problem:
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"

Reason:
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?

Originally posted by og2
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.


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

I disabled this line in case u want to test
/* callfunc "MiningRocks","CopperRock"; */

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 >.<

Originally posted by Eradicate
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...

Originally posted by KeyWorld
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 ).

Originally posted by malufett
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....

Originally posted by Euphy
Imagine the pain that would be caused by scripts like these:
http://sushiduy.ples...ywarper_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.

Originally posted by Myzter
We could add a new command to the core:

-	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, {

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

-	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;
}

Regards,
Myzter

Originally posted by Euphy
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:

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

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

I think, if 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.

Originally posted by Myzter

@MyzterIt will be to difficult to add a module base on label overwrite, a label isn't structured to stop somewhere.I think, if 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.

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.

Originally posted by KeyWorld
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.

Originally posted by Myzter
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.