Sneak Peek

posted in Beals Software
Published May 17, 2006
Advertisement
Ethereal Darkness Interactive UpdateI've got a nice little chunk of a part that happens later in the game wrote down. I'm going to switch though and focus on the beginning since we have maps and such and a lot more of it has discussed. I'm doing my best to eliminate the common messages (i.e. 'using' a person doesn't seldom gives you the 'I don't think he/she would like that message.')

I can't believe how customizable this scripting system is. For example, I can easily change a verb via setKey(). So, say you have a bottle of liquid. You'd have to open the bottle first, so you'd want "open bottle of liquid", then after you open it you'd want something different, like "drink delicious smelling liquid", and then you may want to change it to something like "lick empty bottle". This can be done easily:
function onCreate(this)	setKey(this, "name", "bottle of liquid");	setKey(this, "verbHand", "open");	setKey(this, "verbMouth", "pry lid off of");	setKey(this, "verbEye", "examine");endfunction onHand(this)	if stateBottleOfWater == 0 then		w0=talk(donny, "Thank God its a twist off");		wait(donny,w0);		stateBottleOfWater = 1;		setKey(this, "verbHand", "close");	elseif stateBottleOfWater == 1 then		w0=talk(donny, "Best to save it for later");		wait(donny,w0);		stateBottleOfWater = 0;		setKey(this, "verbHand", "open");	endendfunction onMouth(this)	if stateBottleOfWater == 0 then		w0=talk(donny,"I can't drink from it while its closed");		wait(donny,w0);	elseif stateBottleOfWater == 1 then		w0=talk(donny,"Ahhh... refreshing!");		wait(donny,w0);		stateBottleOfWater = 2;		setKey(this,"verbMouth", "lick");		setKey(this,"name", "empty bottle");	elseif stateBottleOfWater == 2 then		w0=talk(donny,"I'd rather keep my dignity.");		wait(donny,w0);	endend

Pretty simple in my opinion, especially compared to some of the scripting I've dealt with before *shudders*. Also, since stateBottleOfWater is a global variable I can have another script control it. For example say I have a pile of bottles. I only want the player to have one:
function onCreate(this)	setKey(this,"name","pile of bottled water");	setKey(this,"verbHand","take bottle from");	setKey(this,"verbMouth","spit on");	setKey(this,"verbEye","count bottles in");endfunction onHand(this)	if stateBottleOfWater < 2 then		w0=talk(donny,"I already have a bottle");		wait(donny,w0);	elseif stateBottleOfWater == 2 then		w0=talk(donny,"I'll put this empty one back and get a fresh one");		wait(donny,w0);		stateBottleOfWater = 0;	elseif stateBottleOfWater == 3 then		w0=talk(donny,"I have enough room for one");		wait(donny,w0);		stateBottleOfWater = 0;	endend

donny is a fictional object that represents me, thus the sucky/lame dialogue presented above.


DragonForge TechnologyI've decided to not show any demo related screenies until friday or saturday.

Movies don't count as screenies, right?
This is just a little movie of my console that I coded up. Its pretty nice and supports all of my input features (if you're wondering, the 'caret' that is there is just a | that is appended onto the string before rendering [wink]. I have code to have it blinking, but its kind of annoying so I commented it out.) In the movie I'm just showing off that it supports scripted actions (denoted by #) and by the last one you might be able to guess that they can support a couple arguments [grin].

You may also notice that when I first open the console, it already has text in it. I've got it rigged right into my HTML log using the LogListener feature and using the HTML stripper in my code base I can just strip out the HTML tags and poof, it goes right into my console. Setting things up ahead of time actually pays off [grin].

Anyway, my side projects for now are just going to consist of small non-interactive demos (or very little interaction.) I figure this way I don't have to worry about coding a user interface, I can focus on the demo, and I can practice learning scripting and some more advanced 2D stuff. You can expect some uber-awesome screenshots this weekend.

My article series have taken to the back burner since I really have the need to finish something. The only person so far that was really looking forward to it was Kogh, but I can help him with whatever he needs.

Edit: I've modified the command system for the console. I've made it possible to add and remove commands really easily. For example, heres 2 different commands - quit and boot:
void Quit(DebugConsole* pConsole, const std::string& Arguments){    PostQuitMessage(0);}void Boot(DebugConsole* pConsole, const std::string& Arguments){    if(Argument == "")    {        pConsole->AddString("Please specify a user to boot.");        return;    }    std::string Player = dft::GetNode(Arguments, ' ');    std::string Reason = dft::GetNode(0, 0);    pConsole->AddString("Booted " + Player + " because \"" + Reason + "\"");}


And then to register them:
g_Console.Register("#quit", Quit);g_Console.Register("#boot", Boot);


Edit: Ok, I was talking with a buddy and he didn't seem to see how this could be helpful so I figured you guys might not see what I'm seeing. First of all I can register functions that operate on different variables. Yes it requires a lot just to modify a variable, but its much nicer than having to stop the program, modify the code/file and then restart the program.

Second, I can run auto-scripts that use my custom commands. I simply type up a script and then load that in string by string into the console. For example:
sv_connect 414.122.178.1sv_message "This is a test of the the auto script." Programmer16queue 'sv_waitforresponse' 'sv_disconnect' 'quit'runqueue

The system would sit idle until each message was done, going through the queue. This isn't the best example (especially since I've never done any network coding and I'm really tired) but it should get my point across.

This would also allow for macroing in the game (which would be ok since I don't plan on making multiplayer games.) Of course the engine will be hooked into the console too (i.e. binding/unbinding keys, taking screenshots, changing display modes, etc.)

Good night


Discussion


Other news

Next Entry Wow, crazy
0 likes 5 comments

Comments

Mushu
Yeah, I can see the usefulness of being able to easily register new console commands. Heck, you could even dynamically load them from a DLL with a method like that, at runtime, by user command -

/loadcommand DoSomethingFunction mydll.dll

Which would then load the library and register the function returned with GetProcAddress. This would allow you to write plugins and such for your system which can be distributed to your users without rebuilding the actual client.

As a completely unrelated sidenote, I like that scripting system you're using. My one gripe is that the object global states aren't really very informative from a coding perspective; does Lua allow some kind of way to textify them? Like -

WATER_BOTTLE_CLOSED = 1;
WATER_BOTTLE_OPENED = 2;
WATER_BOTTLE_EMPTY = 3;

Personally, I think that would make the code a lot more readable, especially if you had something with considerably more states. Like a Rubrek's Cube. I'm pretty sure you could code one with only 3 commands (twist, rotate along x-axis, rotate along z-axis), but maintaining the state of it would be tricky with your current setup ;)
May 17, 2006 11:05 AM
Telastyn
Fixed function type? Annoying.


void    moo(){
        cout << "moo.\n";
}

long    square(long x){cout << "square: " << x*x << "\n"; return(x*x);}

void    echomoo(string s, int x){
        for (int xx=0; xx<x ; ++xx){
                cout << s ;
        }
        cout << "\n";
}

void    echotwo(string s){
        cout << s << "\n";
}


testcs.add(make_cmd("moo",function<void()>(moo)));
testcs.add(make_cmd("square",function<long(long)>(square)));
testcs.add(make_cmd("echo",function<void(string, int)>(echomoo)));
testcs.add(make_cmd("echotwo",function<void(string)>(echotwo)));



Granted, yours seems better suited for interactivity and more traditional scripting use. Mine's designed as more of an arbitrary pluggable interpreter
May 17, 2006 12:32 PM
Programmer16
@Mushu - Thats an awesome idea and it'd give me a reason to use my dftDLL interfaces (which I've been wanting to do.)

And to tell you the truth, I actually haven't used the global variables or anything (pretty much just the entities, talk(), and wait()) but I wouldn't doubt that LUA has some sort of type defining system (which would be awesome.) I'll have to ask Raymond.

@Telastyn - That looks like a much more functional and nicer system, but also more complicated. I just hacked this together so that I can have it for the demo stuff that I'm working on. I'll keep a copy of your post for when I actually start working on my engine/game.

Thanks guys!
May 17, 2006 05:07 PM
Mushu
@Telastyn - boost::bind is your friend [lol]
May 17, 2006 07:11 PM
Telastyn
Eh?

thread_cs.add(make_cmd("load_sound",function<void(string)>(bind(&fmod_thread::load_sound,this,_1))));
thread_cs.add(make_cmd("play_sound",function<void(string)>(bind(&fmod_thread::play_sound,this,_1))));



This makes the c++ code look a bit horrific though. My C# version is cleaner. And if it's in reference to the fixed function signature, I'd rather have the defined signature so that incorrect parameters and correct type de-serialization can be done at the interpreter level.
May 17, 2006 10:11 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement