Sunday, September 30, 2012

Large scale trading

Player/player trading is definitely a must-have because it allows to pass items in-the-field between party members.

But when it comes to facilitating a large scale ingame economy driven by supply and demand, this tool quickly gets to its limits. It's hard to find out who buys and sells what for which price. Players will have to help themselves by creating an external trade platform like a marketplace forum or (when there are some skilled but bored web developers in the community) a marketplace website. And even when people make deals via this platform, they still need to arrange an ingame meeting to fulfill the deal.

To make it easier to trade items with each other, I need an ingame trade platform which allows the players to:
  • place offers
  • browse other players offers (smart searching would be a plus)
  • accept other players offers and perform the transaction, even when the other party is offline
There are two types of items players can offer:

1. commodity items which are in high supply and demand
2. unique items

For commodity items, the price is the result of the current supply and demand in the community. They are often bought or sold in bulk quantities. For trading these items, I would like to create a stock-exchange like system where players place buy- and sell orders ("buy 25 ruby for 50 bugs each"). Like a real commodity market, the system automatically matches these orders and publishes the current price as a guide for buyers and sellers.

For unique items, this approach wouldn't be feasible, because they aren't so interchangeable that you could place a buy offer for them ("buying robe for lvl 25+ with at least 20 fire defense and +10 on ice magic skill and not too high weight and a beautiful color would be nice, too"?). So I would rather prefer an auction-house approach for selling items where players can offer items they found/made and other players can place offers for them.

There are a lot of interesting approaches to auctions, like the Vickery auction or the Dutch auction which might be interesting to try, but the eBay system where sellers place items with a minimum and maximum (instant-buy) price is so widely used that players might expect this system. I could still try to offer all of these auction variants in the same interface, though. The Vickery variant is especially interesting to me, because it doesn't discriminate against casual gamers who only check the market every few days and don't have the time to log in every hour to check that nobody overbid them.

Wednesday, September 19, 2012

NPC shops

NPC shops work. They just have the same problem like the player/player trading dialog: no way to get any information about what you are buying. I think I will move the item details from the inventory window to an independent popup window so that it can be reused by other dialogs.

Looking at the screenshot I also notice that I mix HTML buttons with my own "link with background color and borders" buttons. I need to get rid of one of these methods to get a more consistent interface look.

Tuesday, September 18, 2012

NPC dialogs

I am still not finished with the item milestone, but I had some momentum I didn't want to waste. So last night I implemented NPC scripting like described in my previous posting and today I wrote the GUI part of it. The text in the GUI is fully HTML enabled, so I will be able to embed decorated text, images, links and other shenanigans in NPC dialogs. I could even put in some script tags or javascript: links. This could prove valuable during tutorials to automatize the GUI. I just have to be weary of XSS injections when I integrate any user-generated stuff in NPC texts.

Now I just need some way to place NPC's on maps and I am finished with Milestone 9 before finishing Milestone 8.

How could I do NPC scripting II

A while ago I already wrote an article about how I could define NPC dialogs with JSON. Looking back at it now it's just awful. It's convoluted, error-prone, unreadable and not even very flexible. I got a Javascript engine, so why not do as much with Javascript as possible?

    EVENT_0 {
        this.text = 'Hello.<br/>How can I help you?';
        this.portrait = 'girl.png';
        this.addOption('Where is the castle?', 1);
        this.addOption('I need a job', 2);
        this.addOption('Nothing, goodbye', 3);

    EVENT_1 {
        this.text = 'Just go down the road, you can\'t miss it.';

    EVENT_2 {
        switch(user.getVar('quest_slay_dragon')) {
                this.text = 'I got a quest for you.<br/>Kill the dragon in the mountain.';
                user.setVar('quest_slay_dragon', 1);
                this.text = 'Did you already slay the dragon?';
                this.text = 'Great, you killed the dragon. Here is your reward.';
                user.setVar('quest_slay_dragon', 3);            
                this.text = 'Sorry, I got no more work for you.

    EVENT_3 {
          this.text = 'It was a pleasure to meet you.';
          if (user.getVar('quest_slay_dragon') == 1)
              this.text += ' And good luck with the dragon.';

This does even more than the JSON dialog before with less lines. It is not only much more readable, it also allows to utilize the full power of Javascript to make anything conditional or procedurally generated.

As any reader with Javascript knowledge will notice,
isn't valid Javascript syntax.The great thing is that I can do some preprocessing on the Java side before passing the code to Rhino. So I can expand it to:

    event[0] = new Event();
    event[0].init = function(user) {

So how does the dialog system work?

Each NPC dialog is an array of Event objects. Each Event object gets an additional init function after creation. When a player talks to an NPC, the server calls event[0].init to set up some variables inside the event object. Then it sends the event to the client. When the init function added one or more dialog options using this.addOption, the client can reply with the option it wants to use. When it does, the event with the event number passed to the corresponding addOption() call is processed.

The Event object:

text: HTML which is shown in the main body of the NPC dialog window.
portrait: URL of an image which is shown in the corner of the NPC dialog. When undefined, the portrait of the last event is used.
addOption(text, event): makes the client shows text as a hyperlink at the end of the dialog text. When the user clicks on this link, the client informs the server about which option was selected. The server then processes the corresponding event. When event is undefined, the dialog ends when this option is selected.
next: Event which is processed next when no option is selected. This changes the 'quit' button below the dialog window to a 'next' button.

Monday, September 17, 2012

Progress with trading

The GUI for trading between players is making slow but steady progress. A trade can be started from this neat context menu which appear when the user clicks on another character ("whisper" and "info" are still unimplemented):

I am now able to do the complete trade from start to finish. But there is still a lot to do. Money can not be traded. The icons of the traded items show up, but there is no way to see any info about them - not even their name or the quantity. Also, there is no visual feedback when the trade partner locks his side of the deal. I also found a very obvious exploit: it's possible to add an item multiple times to the trade. When the trade is completed, the item is duplicated. This needs to be blocked client- and server-sided.

Sunday, September 16, 2012

Player trading server-sided

I implemented player/player trading on the server. I implemented this by having a TradeController for each MapInstance, which manages Trade objects, which are state machines with these states:

REQUEST: A player has initiated a trade with someone else.
BARTER: The other player has agreed to do trading and the players are adding and removing items. They can lock and unlock their side of the bargain to signal that their offer is complete.
CONFIRM: When both players have locked their offer, they both have to confirm the deal. Both can unlock their offer to return to the BARTER state. This also removes the lock of the other party and any confirm which has already happened.
FINISHED: When both players have confirmed, the trade contents are again checked against the inventory to make sure that no offered item got lost during the trade. Then the trade is processed.

I hope that I remembered to check all possible error conditions. Otherwise I could have unintentional trades at best and an abusable exploit at worst.

Next will be the GUI on the client-side.

Monday, September 10, 2012

Tweaks to login dialogs

I made some tweaks to the login sequence. The main login prompt, while still looking the same to the user, now looks more like a form to the browser. This has the advantages that the password manager of the browser works and that the Enter key logs you in. Previously you had to click the login button with the mouse. That was mostly for my own convenience. I also improved the character selection. It's still not beautiful, but definitely less ugly. The user at least realizes what to click on.

I will leave the final CSS styling for shortly before launch when I finalized the overall graphic design of the game. The login sequence is the first impression the user has of the game. It must look as awesome as possible.

Sunday, September 9, 2012

Procedurally generated equipment

I finally implemented unique items with attribute bonuses which are generated at runtime. After thinking a lot where to place the templates for unique items, I decided to place them right in the "drops" section of the mob descriptions.

On a related note, I watched Angry Joe's review of Guild Wars 2, which was quite ecstatic. He made a lot of good points about how Guild Wars 2 promotes teamplay over competition in PvE gameplay. The game automatically scales encounters with the number of players participating, which also increases the rewards. Rewards aren't divided - everyone gets the full share. So more players = more exp and loot = more fun. So I decided to reconsider some initial game design choices I made. Experience is now not divided between killers - everyone gets the full share. Also, spawn areas now have two optional parameters number_scale and power_scale, which increase the number and the power (hp and damage output) of newly spawned monsters when the number of players in the map instance increases. The power factor also increases the exp per monsters as well as the randomly generated attribute bonuses of items.

Saturday, September 8, 2012

Current Equipment in Item Window

I added a section to the item window which shows the currently equipped items. The player can equip items by dragging them from the inventory to the equip silhouette, view their details by clicking on them and remove them by dragging them back into the inventory.

Equipment handling does now work adequately. Now I have to write some code on the server-side to create unique items which are actually unique.

Thursday, September 6, 2012


I decided to do equipment before I do trading.

I can now create unique items (well, "unique" is a stretch - the values are hard-coded placeholders), I can equip and unequip them which already modifies the stats of the characters and the current equipment is stored in the database. The new /shell command proved to be really handy during the development of these features, because it allows me to test things on the server I don't have netcode support for yet.

Still missing:
  • Communication of equipment changes
  • Communication of attribute modifiers (this also affects status effects from items)
  • netcode for equipping and unequipping
  • and, of course, any GUI on the client

Saturday, September 1, 2012

Temporary status effects

The stats of player characters can now be modified by temporary or permanent status effects. This allows items which buff player characters, like the potion seen above. The effect requires four lines of script code:

        "use":"var effect = new WizardwarStatusEffect();
               effect.stat = WizardwarPlayer.Stats.INTELLIGENCE;
               effect.absolute = 10;
               user.addTemporaryStatusEffect(effect, 10);

Maybe I should add an alternative way to define temporary status effects for consumable items to save me some typing.

Next up will be equipment. But I am still in the brainstorming phase for my ItemUnique class.