Improving script functionality and textblock structure

Started by The Crazy Animal, Jul 17, 2006, 01:35 PM

Previous topic - Next topic

The Crazy Animal

One of the things MMUD really lacked was the ability to implement new textblock functions and character abilities without requiring the game engine to be altered. This is something that I would really like to see changed in Greatermud. By moving away from hard-coded scripting functions this will help maximize the flexibility of Greatermud?s game engine and allow it to more readily address the needs of content designers. This type of soft-coded script design has become quite common place in current games so it is a great time to look into doing this and there are quite a few well supported options in how to go about doing this for Greatermud using commonly embedded script languages. However it can be done completely custom if that?s what?s wanted.

GameMonkey Scripting language:
http://www.gamedev.net/reference/articles/article2282.asp
http://www.gamedev.net/reference/articles/article2296.asp
http://www.evolutional.co.uk/gamemonkey/index.asp
http://www.somedude.net/gamemonkey/

Lua Scripting Language:
http://www.gamedev.net/reference/articles/article2275.asp
http://www.lua.org/
http://lua-users.org/wiki/LuaVersusPython

Python Scripting Language:
http://www.gamasutra.com/features/20020821/dawson_01.htm (needs subscription)
http://www.python.org/

I?ve seen many of these script languages used in this way to create some mind blowing effects such as imbuing items the ability to converse with their wielders to assuming control over a NPC from static objects such a room acting as the witness of a player?s actions on other objects in a room.

Now we already have one legacy scripting language in the game engine the textblocks but they are very limited to working with the established hard-coded functions provided by the game engine. So what we need to do is have something that can function at a more involved engine hook level providing us with the ability to build our own functions and otherwise extend the abilities of textblocks. Since these scripts would need to be accessed either from a textblock or from another database table we should take a look at how we can bring them up to a level able to work with a scripting language first.

Before we really pick a Scripting language we need to improve some other aspects of textblocks mainly how textblocks are parsed and otherwise store their data. While doing this we need to keep in mind the content designers needs and generally make the design of a textblock easier to write and understand. Since we are using SQL as the backend what we should look at is XML because that can be easily contained in SQL databases.

XML:
http://www.gamedev.net/reference/articles/article1928.asp
http://www.gamedev.net/reference/articles/article2159.asp
http://www.gamasutra.com/features/20060427/luerig_01.shtml (needs subscription)

Storing XML in SQL:
http://www.stylusstudio.com/sqlxml_tutorial.html

XML can easily offer us all the formatting that we could want via its tokens and tags and would also give us the ability avoid the need of using multiple textblocks for simple operations. This is because we could rely on the structure of the XML to define the segregation of the parts of a textblock that ranges from dialog and response to functions. XML gives us an easy way of commenting in the actual code to show how things work something that was entirely lacking in MMUD. Each command in the XML would be interpreted so we can set up our own formatting sets that clearly show intent which would help us communicate the codes purposes to fellow designers. All Legacy functionality would be kept intact by providing a check for the xml header. If the textblock is lacking this header the textblock would be treated like a standard textblock.

This is the type of formatting sets I?m talking about:
<Dialog ?keyword?>Dialog Response</Dialog>
<Merchant ?keyword?>Functions</Merchant>
<Message>?Message Number?</Message>
<Response ?Emoted Action?>?Dialog or function?</Response>
<Textblock_function>?textblock commands?</Textblock_function>
<Load Textblock>?textblock number?</Load Textblock>
<Price ?value?>?fail message number? or ?<Line1></Line1><Line3></Line3>?</Price>
<Giveitem>?Item number?</Giveitem>
<VM Script>?Embedded scripting language?<VM Script>
<Load VM Script>?Script Number from database or maybe filename.?</Load VM Script>

In textblocks your word triggers were set by creating a list of words or sayings with linking textblocks attached to each word then linking that a to textblock with the main greet dialog. Doing this way the interpreter would then auto generate a dynamic watch list for things like keywords and things like responses that would be targeted at the character that triggering it. This has the effect of reducing a little of the work needed to be done by a designer and automatically reduces the amount of textblocks by 1 textblock per multi NPC dialog then further reduces the textblock count by 1 per topic.?

Now in some cases multiple textblocks may be warranted and there are two ways I came up with for linking to other textblocks for this:

One is per topic such as:
<Dialog link ?keyword?>?Textblock #?</Dialog link>
<Response link ?keyword?>?Textblock #?</Response link>

The keyword would then just be matched against the keywords provided in the linked textblock and any additional functions run remotely from there.

The other would be per textblock:
<Linked>?textedblock#?</Linked>

The linked textblock would be parsed and the keywords and other triggers would be appended to the watch list generated first. Personally I like the second idea since it involves less coding per use.

Secondly since this is an interpreted format we can do things we couldn?t in textblocks like create emotes actions and messages that act like they were pulled from their appropriate database but do not actually exist there. This is good because it reduces the amount of database searches needed to perform a single action and removes those data entries unique to a single NPC from the databases and places them intuitively where they are needed within the context of the dialog. Such as:

<Action Message>
? ? ?<Line1>?First person view?</Line1>
? ? ?<Line2>?Second person view?</Line2>
? ? ?<Line3>?Unknown or otherwise unused?</Line3>
</Action Message>

Or

<Emote Action>
? ? ?<Line1>?Player view (no target)?</Line1>
? ? ?<Line2>?Room view (no target)?</Line2>
? ? ?<Line3>?Player view at target player?</Line3>
? ? ?<Line4>?Target player?s view?</Line4>
? ? ?<Line5>?Room view at target player?</Line5>
? ? ?<Line6>?Player view at target NPC?</Line6>
? ? ?<Line7>?Room view at target NPC?</Line7>
? ? ?<Line8>?Player view at inventory item?</Line8>
? ? ?<Line9>?Room view at inventory item?</Line9>
? ? ?<Line10>?Player view at Floor item?</Line10>
? ? ?<Line11>?Room view at Floor item?</Line11>
</Emote Action>

The nice thing about this is that you only need to provide the lines that are being used so if you are making an emote action to have a NPC point his sword at a player then you only need to provide line 4 and line 5 between the emote action tags.

The other thing this would let us do is use formatting tags to interpret colors and color effects like highlighting words could be simply done such as <color ?red?>text</color>, <highlight>text</highlight>, <blink>text</blink>, or <bold>text</bold> rather then using the antiquated ANSI color codes which are hard to remember or visualize if you don?t have a way of previewing them or have make extensive use of them prior. These interpreted text formatting tags could then be affected by things like the player?s profile color palette settings.

It would also allow use to make up labels for common use tags like harvest to clearly show a simple function of collecting an item.

<Harvest ?keyword?>?function?</Harvest>

Getting to some examples or how this would work:

So if you wanted to have an NPC barmaid slap a PC for kissing her you would just set the response trigger for the NPC?s view of the kiss and then the dialog and or emote action that you want them to call in between the response flags like so:

<Response ?%s kisses you!?>
? ? ?<Dialog>How dare you!</Dialog>
? ? ?<Emote>Slap</Emote>
? ? ?<Dialog>You have some nerve doing that!</Dialog>
</Response>

This would create a dialog followed by the slap followed by more dialog. This manner of trigger and response sets will give more control over scripting in a dialog then textblocks could previously.

If you want dialog to only be triggered in an order and only in that order then you would include child dialog sets like:

<Dialog ?main keyword?>?main dialog?
? ? ?<Dialog ?child keyword?>?child dialog?</Dialog>
</Dialog>

When this dialog statement is reached it would append the additional keywords onto the watch list. If the player tried to use those keywords prior to that they simply would be ignored.

Example of an xml formatted textblock:

Note ? This is indented to have the emote action greet functioning on NPCs as it would on players. Please pardon the formating it seems that the forum didn't like my tabs and got rid of them.

<?xml version="1.0"?>
<!-- Begin main dialog -->
<Response ?%s greets you.?>Greetings to you too <bold>adventurer</bold>, my name is Thortan the <bold>trader</bold> I have many <bold>rare items</bold> for sale if you are interested in doing business with me.</Response>
<Dialog ?hello thortan?>Hello <bold>adventurer</bold>, my name is Thortan the <bold>trader</bold> I have many <bold>rare items</bold> for sale if you are interested in doing business with me.</Dialog>
<Dialog ?hey thortan?>What an informal greeting <bold>adventurer</bold>, my name is Thortan the <bold>trader</bold> I have many <bold>rare items</bold> for sale if you are interested in doing business with me.</Dialog>
<Dialog ?sups thortan?>Whatever is this sups thing you speak of? Never mind, I don?t really need to know. Lets us not waste time that could be better spent with talk of business. You know I have many <bold>rare items</bold> for sale, at very good prices if you are interested in doing business with me. I almost forgot to introduce myself, where are my manners today. My name is Thortan the <bold>trader</bold> and it is a pleasure to make your acquaintance.</Dialog>
<Dialog ?ask thortan adventurer?>Yes, young one it?s that easy to tell that you?re an adventurer</dialog>
<Dialog ?ask thortan trader?>The life of a trader is exciting one to live. I?ve traveled far in wide across the realm from the great lands of <bold>Garbantiam</bold> to the mighty <bold>Kingdoms of Zarbonzo</bold></Dialog>
<Dialog ?ask thortan Garbantiam> It?s really a lovely place maybe one day you?ll go there and see it for yourself.</Dialog>
<Dialog ?ask thortan Zarbonzo?> Ah, the <bold>Kingdoms of Zarbonzo</bold> there are so many of them. </Dialog>
<Dialog ?ask thortan Kingdoms of Zarbonzo?>Lets see there is the kingdoms of Armstrong, Zanzabar, Stronglock, and oh we can?t forget Tarnlick </Dialog>
<Dialog ?ask thortan rare items?>I have many rare items to show you. This sword is a very rare relic ?.blah blah blah.. I can offer it to you for the mere amount of 1000 gold. If that is not your liking I have this powerful axe for the same price.</Dialog>
<!--The tag merchant is used as a trigger similar to dialog and then triggers a textblock function. The textblock then sets the price in copper followed by the message number if the player doesn?t have the cash. On passing it gives the item to the player and then the message to show the transaction in the room-->
<Merchant ?buy sword?>
<textblock_function>price 100000 1001:giveitem 100:message 1000</textblock_function>
</Merchant>
<!--This merchant function is the same function as above but provides all the messaging data-->
<Merchant ?buy axe?>
<Price ?100000?>
<Action Message>
<line1>Thortan looks at you in disgust as you scrounge for cash.</line1>
<line2>Thortan looks at %s in disgust</line2>
</Action Message>
</Price>
<Giveitem>101</Giveitem>
<Action Message>
<line1>Thortan hands over the axe in exchange for your money.</line1>
<line2>%s buys the axe from Thortan.</line2>
</Action Message>
</Merchant>
<!-- End main dialog -->

You can easily see the effect of this as it allows you to see all of this NPC?s dialog and actions clearly and in one place. This should have the effect of speeding up the creation of textblocks as all of the functions of a textblock can be put into one well formatted textblock that is more intuitive to read and write.

Depending on how we go about setting this up if we include ways to access embedded scripts we could also provide the means to set up improved NPCs behavior from directly inside the called textblock. By calling the script to run such as:

<Load VM Script>1232</Load VM Script>

Or by just adding it directly into the XML version of the textblock like so:

Note: I?m not sure how you have your objects set up in the engine so I?m just going to guess at what would be and keep in mind all of these syntaxes are fictional and not really a clear depiction of any one scripting language.

<!-- Begin response set -->
<!--This first response sets both the dialog to being spit on and the action for the NPC to take after saying it. Any of the dialog responses given here only function provided the response has been triggered first. -->
<Response ?%s spits at you!?>
<VM Script>
BeginScript
If character.action.?%s spits at you!?
Set %S = target.character
DO talk ?Civility seems not to be your strongest quality; perhaps I should teach you a lesson.?
DO character.action.line4 ?% readies his sword and points it at you!?: character.action.line5 ?%s readies his sword and points it at %s!?
DO talk ?I?ll give you the choice walk away or face my blade in combat!?
Function start timer
If target.character.talk, ?ask thortan combat?
DO talk ?If that is the way you want it my satisfaction shall come at the sight of your blood running down my blade!?
DO character.npc.action.attack, ?target.character?
Function stop timer
EndScript
Elseif timer >= 300
Function stop timer
If Target.character.inroom = 1
DO talk ?What are you waiting for! If you?re that scared of my challenge maybe you should ask for my forgiveness.?
If target.character.talk, ?ask thortan forgiveness?
DO talk ?All can be forgiven, let us not dwell on this any longer.?
EndScript
Else target.character.talk, ?*? //wild card statement
DO Talk ?That?s the last straw!?
DO character.action.line4 ?% grabs you by the neck and tosses you out of the room!?: character.action.line5 ?%s grabs %s by the neck and is tossed out of the room!?
Target.Character, Force_Move ?east?
EndScript
Elseif Target.character.inroom = 0
If target.character.gender = 0
DO talk ?I guess he was smarter then he looked.?
Endscript
Elseif target.character.gender = 1
Do talk ?I guess she was smarter then she looked?
Endscript
Else
Do talk ?I guess whatever the hell that was smarter then it looked.?
Endscript
Else OnExit{target.character}
Do yell ?I figured you for a coward!?
EndScript
</ VM Script>
</Response>
<!-- End response set -->

One of the things you might notice in that the script is the NPC is treated more like an actor from an interactive fiction story rather then a static NPC from MMUD. The NPC then becomes more then a static content tool and takes on a dynamic and immersive quality pulling the player into the game. By doing this the NPCs can become more interactive and help encourage players to think out of the box. I would expect players would quickly pick up on this and start trying to explore its use in game because there aren?t many players who can say they?ve never slapped or preformed at least one of the emote actions on a monster or other NPC at some point in the game.

Provided this is done correctly we should have seamless control over the characters and objects around them. Unfortunately there is two limitations to this and that is the textblocks have a 2000 characters with spaces limit per textblock and that really isn?t enough space for an entire dialog to be fluidly inputted unless its very short. The second limitation is that the textblocks do not support formatting via indention this can be gotten round a little by using line breaks and an editor that can parse the lines correctly. I have to say I hate limits like this but we have to work around an existing architecture to keep legacy functionality. We can fix some of these limitations like changing the character field limit on textblocks I think we can get as high as 65k characters in SQL for a text type field and just cope with the non-existent indention formatting. If we really find we need the indent formatting we could always add in a way to load an external xml file.

Hope that explains it well enough but if you have questions just ask.


DeathCow

Ok, was I suppose to read that?  Who do you think I am...

The Crazy Animal


DeathCow

NO its too fucking long, and um there are no colors!


I'll get around to reading that later, once i finish my novel.

The Crazy Animal

Ya well the examples kinda make it longer then I wanted but I figured it would be good to have them in there. I thought about colors too but that lost out on some of the research I'm doing on AI and embedded scripting languages right now.


DeathCow

I'm reading 'On the Good Life'  Its interesting too.

The Crazy Animal

Ok I did some reading up on AI while trying to figure out the implications of choosing a scripting language the effects of adopting xml formatting for textblocks. I found that there are quite a few custom XML derivatives geared to this and what we would really be basically doing is making our own derivative rather then using pure XML markup. Secondly I realized that choosing a script language is not as necessary if we are coding the interpreter ourselves for our own derivative as we can interpret the tags any way we really want in C#.

So what we really need to do is take a good hard look at the text blocks and generate a textblock list of what does what and how we can improve its functionality. Imagination and core programming would be the only the limit here. I?ll get back to this as I?m starting to gather the foundation work for an AI system that would work well for us.