PDA

View Full Version : GS2 Character Creation


cbk1994
11-23-2008, 08:39 AM
This script generates a GS2 script of a character, as opposed to the GS1 script produced by the level editor.

Copy and paste the code given as output into a level NPC, upload it to a server, and it will show the character as you set it.

Screenshots:

http://img56.imageshack.us/img56/208/changedirqm4.png

http://img56.imageshack.us/img56/9030/dropdownpn8.png

http://img224.imageshack.us/img224/6647/outputtt6.png


Say "/create char" to open the window. It should be quite simple to add a different way to open the window.



//#CLIENTSIDE
function showInterface() {
if (CreateChar_Window != null) {
CreateChar_Window.destroy();
}

new GuiWindowCtrl("CreateChar_Window") {
profile = "GuiBlueWindowProfile";

width = 212;
height = 356;

x = GraalControl.width / 2 - (width / 2);
y = GraalControl.height / 2 - (height / 2);

canClose = visible = true;
canMaximize = canMinimize = canResize = false;

text = "Character Creation";

new GuiShowImgCtrl("CreateChar_Doll") {
ani = "idle";

x = CreateChar_Window.width / 2 - 25;
y = 32;

hint = "Click to change direction.";
}

temp.fields = {
{"bodyimg", "Body"},
{"headimg", "Head"},
{"shield", "Shield"},
{"attr[1]", "Hat"},
{"ani", "Ani"}
};

temp.parts = getParts();

temp.colors = getColors();

for (temp.field : fields) {
new GuiTextCtrl("CreateChar_FieldLabel_" @ field[1]) {
profile = "GuiBlueTextProfile";

x = 13;
y = 90 + 23 * fields.index(@ field);

text = field[1] @ ":";
}
new GuiTextEditCtrl("CreateChar_Field_" @ field[1]) {
profile = "GuiBlueTextEditProfile";

width = 150;
height = 20;

x = 50;
y = 90 + (height + 3) * fields.index(@ field);

if (field[0] == "attr[1]") {
text = CreateChar_Doll.actor.attr[1];
} else {
text = CreateChar_Doll.actor.(@ field[0]);
}

if (text == null) {
text = "";
}

thiso.catchevent(name, "onAction", "onTextChanges");

this.part = field[0];
}
}
for (temp.part : parts) {
new GuiTextCtrl("CreateChar_PartLabel_" @ part) {
profile = "GuiBlueTextProfile";

x = 13;
y = 206 + 23 * parts.index(@ part);

text = part @ ":";
}
new GuiPopUpMenuCtrl("CreateChar_Part_" @ part) {
profile = "GuiBluePopUpMenuProfile";
scrollprofile = "GuiBlueScrollProfile";
textprofile = "GuiBlueTextListProfile";

width = 150;
height = 20;

x = 50;
y = 206 + (height + 3) * parts.index(@ part);

clearRows();

for (temp.c : colors) {
addRow(0, c);
}

setSelectedRow(CreateChar_Doll.actor.colors[parts.index(@ part)]);

thiso.catchevent(name, "onSelect", "onColorSelected");

this.p = part;
}
}

new GuiButtonCtrl("CreateChar_Generate") {
profile = "GuiBlueButtonProfile";

width = 60;
height = 22;

x = CreateChar_Window.width / 2 - (width / 2);
y = 323;

text = "Generate";
}
}
}
function CreateChar_Generate.onAction() {
temp.char = CreateChar_Doll;
// {dir, body, head, shield, hat, ani, colors}
temp.generateFrom = {char.actor.dir, char.actor.bodyimg, char.actor.headimg, char.actor.shield, char.actor.attr[1], char.ani, char.actor.colors};

generateCode(generateFrom);

CreateChar_Window.destroy();
}
function CreateChar_Doll.onMouseDown() {
CreateChar_Doll.actor.dir ++;
}
function onTextChanges(control, newtext) {
temp.part = control.part;

if (part == "attr[1]") {
CreateChar_Doll.actor.attr[1] = newtext;
return;
}
if (part == "ani") {
CreateChar_Doll.ani = newtext;
}

CreateChar_Doll.actor.(@ part) = newtext;
}
function onColorSelected(control) {
temp.colors = getColors();
temp.parts = getParts();

temp.part = parts.index(@ (@control).p);
temp.c = colors.index(@ (@ control).getSelectedText());

CreateChar_Doll.actor.colors[part] = c;
}
function getParts() {
return {
"Skin",
"Coat",
"Sleeves",
"Shoes",
"Belt"
};
}
function getColors() {
return {
"White",
"Yellow",
"Orange",
"Pink",
"Red",
"Dark Red",
"Light Green",
"Green",
"Dark Green",
"Light Blue",
"Blue",
"Dark Blue",
"Brown",
"Cynober",
"Purple",
"Dark Purple",
"Light Gray",
"Gray",
"Black",
"Transparent"
};
}
function generateCode(from) {
// {dir, body, head, shield, hat, ani, colors}

temp.lines = {"/" @ "/ Made by" SPC player.nick, "/" @ "/#CLIENTSIDE", "function onCreated() {", " showcharacter();"};

temp.vars = {
"bodyimg",
"headimg",
"shield",
"hat",
"ani"
};

lines.add(" this.dir = " @ from[0] @ ";");

temp.inc = 1;

for (temp.v : vars) {
if (from[inc] != null) {
lines.add(" this." @ v SPC "= \"" @ from[inc] @ "\";");
}
inc ++;
}

for (temp.c = 0; c < 5; c ++) {
lines.add(" this.colors[" @ c @ "] =" SPC from[6][c] @ ";");
}

lines.add("}");
lines.add("function onPlayerEnters() {");
lines.add(" onCreated();");
lines.add("}");

if (CreateCharOutput_Window != null) {
CreateCharOutput_Window.destroy();
}
new GuiWindowCtrl("CreateCharOutput_Window") {
profile = "GuiBlueWindowProfile";

width = 212;
height = 356;

x = GraalControl.width / 2 - (width / 2);
y = GraalControl.height / 2 - (height / 2);

canClose = visible = true;
canMinimize = canMaximize = canResize = false;

text = "Create Character: Output";

new GuiScrollCtrl("CreateCharOutput_Scroll") {
profile = "GuiBlueScrollProfile";

x = 10;
y = 28;

width = 192;
height = 319;

vScrollBar = "alwaysOn";
hScrollBar = "alwaysOff";

new GuiMLTextCtrl("CreateCharOutput_Text") {
profile = "GuiBlueTextProfile";

width = 202;

x = 0;
y = 1;

text = null;

for (temp.line : lines) {
if (text == null) {
text = line;
} else {
text @= "\n" @ line;
}
}
}
}
}
}
function onPlayerChats() {
if (player.chat = "/create char") {
showInterface();
}
}

DustyPorViva
11-23-2008, 08:42 AM
Nice stuff, though I would prefer 16x16 blocks of colors in rows and columns to minimize the size of the drop menu... I hate selecting colors like that.

Umat
11-23-2008, 08:48 AM
nice! :)

Crow
11-23-2008, 10:46 AM
Nice, this can be very useful :)

xXziroXx
11-23-2008, 12:22 PM
Use setCharAni("ANI"); :frown:

DustyPorViva
11-23-2008, 12:26 PM
setCharani("ani",null); :P

cbk1994
11-23-2008, 06:48 PM
Use setCharAni("ANI"); :frown:

Why?

xXziroXx
11-23-2008, 11:05 PM
Why?

Because it's the preferred way. :oo:

cbk1994
11-23-2008, 11:47 PM
Because it's the preferred way. :oo:

Why? It works both ways.

ApothiX
12-02-2008, 06:58 AM
Why? It works both ways.
GScript1 still works, why use GScript2?

cbk1994
12-02-2008, 11:47 PM
GScript1 still works, why use GScript2?

I guess you were with the idea of using setCharAni?

this.ani seems to me to be a much better way to set it; setCharAni was probably kept mostly for compatibility, though I could be wrong. As far as I know, 'this.ani', using commas for parameters, can duplicate the functionality.

I don't see why you claim it's the preferred way. Seems more of an opinion thing to me; if it wasn't intended to be used, it would not have been added. It didn't exist in GS1, remember.

Crono
12-02-2008, 11:55 PM
Seems more of an opinion thing to me

oh...really?

xXziroXx
12-03-2008, 12:27 AM
I guess you were with the idea of using setCharAni?

this.ani seems to me to be a much better way to set it; setCharAni was probably kept mostly for compatibility, though I could be wrong. As far as I know, 'this.ani', using commas for parameters, can duplicate the functionality.

I don't see why you claim it's the preferred way. Seems more of an opinion thing to me; if it wasn't intended to be used, it would not have been added. It didn't exist in GS1, remember.

The function is supposed to be used to set it, and the string supposed to be used to read the players ani. While it does work setting it that way, it's not the preferred way. What do I base that one? Simple, that you can send params to the gani, hinting that a function is the preferred way.

cbk1994
12-03-2008, 03:24 AM
The function is supposed to be used to set it, and the string supposed to be used to read the players ani. While it does work setting it that way, it's not the preferred way. What do I base that one? Simple, that you can send params to the gani, hinting that a function is the preferred way.

You can take it either way, I guess. Feel free to modify my code if it annoys you that much.

However, I will continue to use 'this.ani', as it, in my opinion, fits better with the style of everything else.

By the way, there are also functions for setting head, etc. I guess I should be using setcharprop instead of this.headimg, right?

Tolnaftate2004
12-03-2008, 07:49 AM
words

It is less costly to set the string.

Inverness
12-03-2008, 01:33 PM
Considering that the Graal documentation says the ani variable is read-only, I think GScript is once again compensating for something you shouldn't be doing normally.

I would prefer if Stefan would make setani() a function of the TGaniObject instead of a global. That way you could do player.setani() or npcobject.setani(), it would be the natural thing to do in object-oriented programming.

xXziroXx
12-03-2008, 05:27 PM
By the way, there are also functions for setting head, etc. I guess I should be using setcharprop instead of this.headimg, right?

setcharprop is clearly a deprecated way of doing things, now you're just mocking me :(

Codein
12-03-2008, 05:31 PM
I would prefer if Stefan would make setani() a function of the TGaniObject instead of a global. That way you could do player.setani() or npcobject.setani(), it would be the natural thing to do in object-oriented programming.

I agree.

cbk1994
12-04-2008, 02:11 AM
would prefer if Stefan would make setani() a function of the TGaniObject instead of a global. That way you could do player.setani() or npcobject.setani(), it would be the natural thing to do in object-oriented programming.
Agreed completely. The fact that there is a seperate setAni and setCharAni almost says that they should be deprecated.
setcharprop is clearly a deprecated way of doing things, now you're just mocking me :(

:p

ApothiX
12-04-2008, 05:59 PM
this.ani seems to me to be a much better way to set it; setCharAni was probably kept mostly for compatibility, though I could be wrong. As far as I know, 'this.ani', using commas for parameters, can duplicate the functionality.
The fact that you're using commas in a string instead of the parameters of the function proves that that isn't the preferred way to do it. Like I said in my last post, you are reverting back to what made GScript1 a horrible scripting language: The ability to do things you shouldn't be able to. What if you had a filename with a comma in it? Using your method, you'd be screwed.

Anyways, Inverness is right. TGaniObject::ani is supposed to be read-only. Not to mention the fact that it's defined as an "object", not a string.

TGaniObject (TLevelObject):
ani - object (read only)

Reference: http://wiki.graal.net/index.php/Creation/Dev/Script/Client/TGaniObject

cbk1994
03-03-2010, 01:12 AM
A couple of amendments:


//#CLIENTSIDE
function showInterface() {
if (CreateChar_Window != null) {
CreateChar_Window.destroy();
}

new GuiWindowCtrl("CreateChar_Window") {
profile = "GuiBlueWindowProfile";

width = 212;
height = 356;

x = GraalControl.width / 2 - (width / 2);
y = GraalControl.height / 2 - (height / 2);

canClose = visible = true;
canMaximize = canMinimize = canResize = false;

text = "Character Creation";

new GuiShowImgCtrl("CreateChar_Doll") {
ani = "idle";

x = CreateChar_Window.width / 2 - 25;
y = 32;

hint = "Click to change direction.";
}

temp.fields = {
{"bodyimg", "Body"},
{"headimg", "Head"},
{"shield", "Shield"},
{"attr[1]", "Hat"},
{"ani", "Ani"}
};

temp.parts = getParts();

temp.colors = getColors();

for (temp.field : fields) {
new GuiTextCtrl("CreateChar_FieldLabel_" @ field[1]) {
profile = "GuiBlueTextProfile";

x = 13;
y = 90 + 23 * fields.index(@ field);

text = field[1] @ ":";
}
new GuiTextEditCtrl("CreateChar_Field_" @ field[1]) {
profile = "GuiBlueTextEditProfile";

width = 150;
height = 20;

x = 50;
y = 90 + (height + 3) * fields.index(@ field);

if (field[0] == "attr[1]") {
text = CreateChar_Doll.actor.attr[1];
} else {
text = CreateChar_Doll.actor.(@ field[0]);
}

if (text == null) {
text = "";
}

thiso.catchevent(name, "onAction", "onTextChanges");

this.part = field[0];
}
}
for (temp.part : parts) {
new GuiTextCtrl("CreateChar_PartLabel_" @ part) {
profile = "GuiBlueTextProfile";

x = 13;
y = 206 + 23 * parts.index(@ part);

text = part @ ":";
}
new GuiPopUpMenuCtrl("CreateChar_Part_" @ part) {
profile = "GuiBluePopUpMenuProfile";
scrollprofile = "GuiBlueScrollProfile";
textprofile = "GuiBlueTextListProfile";

width = 150;
height = 20;

x = 50;
y = 206 + (height + 3) * parts.index(@ part);

clearRows();

for (temp.c : colors) {
addRow(0, c);
}

setSelectedRow(CreateChar_Doll.actor.colors[parts.index(@ part)]);

thiso.catchevent(name, "onSelect", "onColorSelected");

this.p = part;
}
}

new GuiButtonCtrl("CreateChar_Generate") {
profile = "GuiBlueButtonProfile";

width = 60;
height = 22;

x = CreateChar_Window.width / 2 - (width / 2);
y = 323;

text = "Generate";
}
}
}
function CreateChar_Generate.onAction() {
temp.char = CreateChar_Doll;
// {dir, body, head, shield, hat, ani, colors}
temp.generateFrom = {char.actor.dir, char.actor.bodyimg, char.actor.headimg, char.actor.shield, char.actor.attr[1], char.ani, char.actor.colors};

generateCode(generateFrom);

CreateChar_Window.destroy();
}
function CreateChar_Doll.onMouseDown() {
CreateChar_Doll.actor.dir ++;
}
function onTextChanges(control, newtext) {
temp.part = control.part;

if (part == "attr[1]") {
CreateChar_Doll.actor.attr[1] = newtext;
return;
}
if (part == "ani") {
CreateChar_Doll.ani = newtext;
}

CreateChar_Doll.actor.(@ part) = newtext;
}
function onColorSelected(control) {
temp.colors = getColors();
temp.parts = getParts();

temp.part = parts.index(@ (@control).p);
temp.c = colors.index(@ (@ control).getSelectedText());

CreateChar_Doll.actor.colors[part] = c;
}
function getParts() {
return {
"Skin",
"Coat",
"Sleeves",
"Shoes",
"Belt"
};
}
function getColors() {
return {
"White",
"Yellow",
"Orange",
"Pink",
"Red",
"Dark Red",
"Light Green",
"Green",
"Dark Green",
"Light Blue",
"Blue",
"Dark Blue",
"Brown",
"Cynober",
"Purple",
"Dark Purple",
"Light Gray",
"Gray",
"Black",
"Transparent"
};
}
function generateCode(from) {
// {dir, body, head, shield, hat, ani, colors}

temp.lines = {"/" @ "/ Made by" SPC player.nick, "/" @ "/#CLIENTSIDE", "function onCreated() {", " showcharacter();"};

temp.vars = {
"bodyimg",
"headimg",
"shield",
"attr[1]",
"ani"
};

lines.add(" this.dir = " @ from[0] @ ";");

temp.inc = 1;

for (temp.v : vars) {
if (from[inc] != null) {
lines.add(" this." @ v SPC "= \"" @ from[inc] @ "\";");
}
inc ++;
}

for (temp.c = 0; c < 5; c ++) {
lines.add(" this.colors[" @ c @ "] =" SPC from[6][c] @ ";");
}

lines.add("}");
lines.add("function onPlayerEnters() {");
lines.add(" onCreated();");
lines.add("}");

if (CreateCharOutput_Window != null) {
CreateCharOutput_Window.destroy();
}
new GuiWindowCtrl("CreateCharOutput_Window") {
profile = "GuiBlueWindowProfile";

width = 212;
height = 356;

x = GraalControl.width / 2 - (width / 2);
y = GraalControl.height / 2 - (height / 2);

canClose = visible = true;
canMinimize = canMaximize = canResize = false;

text = "Create Character: Output";

new GuiScrollCtrl("CreateCharOutput_Scroll") {
profile = "GuiBlueScrollProfile";

x = 10;
y = 28;

width = 192;
height = 319;

vScrollBar = "alwaysOn";
hScrollBar = "alwaysOff";

new GuiMLTextCtrl("CreateCharOutput_Text") {
profile = "GuiBlueTextProfile";

width = 202;

x = 0;
y = 1;

text = null;

for (temp.line : lines) {
if (text == null) {
text = line;
} else {
text @= "\n" @ line;
}
}
}
}
}
}
function onPlayerChats() {
if (player.chat == "/create char") {
showInterface();
}
}

- fixed if (player.chat = "/create char")
- fixed some imaginary variable I invented called "this.hat" to "this.attr[1]"... :confused:

Immolate
03-03-2010, 01:49 AM
"/" @ "/"

Why?

cbk1994
03-03-2010, 02:06 AM
"/" @ "/"

Why?

// was doing something weird with the syntax highlighting because it's like a comment. I don't think it actually matters as far as the script, though.