Friday, October 19, 2012

Roadmap update

I hadn't had a roadmap update in a while, so time for a new one.

Milestone 8 (wealth):
  • Items and Inventory
    • Dropping items
    • Splitting and combining item stacks
  • Player trading
    • Trading cash
  • Shops
    • Selling items
  • Item stack sizes in trade window
  • Item information system
Milestone 9 (adventuring):
  • NPC interaction
  • Scripting
Milestone 10 (security):
  • Permission management
  • Database logging of
    • Logins
    • Administrative actions
    • Usage statistics
  • Prevent multi-logins
  • Brute force protection
 Milestone 11 (eye candy)
  • Animated sprites
  • Animated tiles
  • Particle effects
Alpha Status reached!

Refinement 1: HTML and CSS

The newest beta of my favorite browser Opera finally supports real WebSockets. Unfortunately there are a lot of layout problems (unrelated to canvas support). I need to get the UI to render properly on it, too. There are also some other layout problems, like the inventory grid not being exactly square in all situations.

Refinement 2: Movement

Since I declared my space partitioning and my route finding algorithm for working, I encountered some glitches which need to be addressed.
  • Suboptimal routes in some situations
  • wrong blockmap calculation in some cases
  • one time I got stuck in a tree - reproduce this (or at least create automatic unstuck)

Refinement 3: Performance

The client framerate fell a lot lately. I need to find out why and optimize it so I get at least 20 Fps on my Intel Atom notebook.

Refinement 4: Game System

Refinement 5: Mob AI

I skipped a few AI strategies I had planned. These still need to be implemented:
  • Attack strategies:
    • Pursuit
    • Stalk
    • Flee
  • Roam strategies:
    • Guard
  • Target strategies:
    • Best attacker against team
    • Closest to team
    • Last attacker
    • Last attacker of team

Refinement 6: Attract Mode

Observer random locations in the background during the login sequence.

Thursday, October 18, 2012

Item code improvements

I made a lot of under-the-hood improvements to the inventory handling code on the server. I made it more robust by throwing exceptions when an operation isn't possible instead of just returning null or false. I also added a crude transaction system in order to be able to easily roll-back inventories should an error occur during trade completion. It's crude in the sense that it creates a complete backup copy of the inventory content, and in case of a rollback it empties the content and restores it from the copy. I could do this more elegantly when I would invest some time, but the code isn't performance-critical and I want something simple which doesn't leave much room for bugs.

Any glitches in the inventory code could cause serious, permanent harm in the game by duplicating or destroying valuable items (and I already found and fixed bugs which caused both), so the quality of the inventory handling code is very important.

Rest system

Lately I was again thinking about how I can make my game attractive to those players who already have jobs and thus can't treat an online game like one.

To get some mental input on this I asked this question on I was actually pretty surprised to get an answer from someone like Josh Petrie, a Guild Wars 2 developer. But the other people who answered and commented also had some interesting points.

I decided that the first thing I will do to level the playing fields will be a rest system. After a lot of number crunching in LibreOffice Calc, I came up with a rest system which works like this:

For every minute - online or offline - your character gets a "Luck" point (60 per hour, 1440 per day, 10080 per week). Your character has a luck bonus which is equal to log10(luck)-1.

All gains of skill EXP and SP are multiplied with your current luck bonus. The chance to get rare drops is also increased: Whenever you kill a monster, you roll ceil(luck_bonus) times for each drop. One successful roll is enough to make it drop. When multiple people kill a monster, the best luck bonus of all participants is used.

Every minute where at least one event occurs which uses the luck bonus, the luck points are reduced by 1% (that means your luck will never fall below 100, so your luck bonus will never be below 1).

So when you go to sleep at 10pm and continue the next evening at 8pm (after 22 hours) you will have 1300 luck points, which means that you will get a x2.1 multiplier for a while. After your 120 minute session, you will have about 400 luck points left, so your bonus will have dimished a bit to x1.6. These 400 points will roll over to the next day, where you will have a multiplier of 2.3.

Let's compare that to an unemployed power gamer, who will play 8 hour session, interrupted by 16 hours of rest. He will have 960 luck points the next morning, which is still a bonus of 1.98, not notably worse than yours. But after four hours, his luck bonus will be depleted and his exp rate won't get far above x1. It won't be above 2 the next day either.

Variables for balancing:
  • Increase the percentual luck reduction to make the multiplier go down faster
  • Increase the luck gain per minute to increase the exp multiplier after shorter rests
  • Reduce the base of the logarithm to increase the exp multiplier after longer rests

Friday, October 12, 2012

Network session logging

A small change, but one I could be very grateful for in the future: I added logging of sessions on the database. Every connection to the server is now logged with:

  • Time of connect
  • IP address
  • When it's a websocket connection:
    • HTTP headers sent by client (including User-Agent)
    • Whether or not this header was accepted
  •  Accounts the user logged into successfully (maybe I should log failed attempts, too?)
  • Time of disconnect

Sunday, October 7, 2012

Items on the floor

I added floor items. When a monster dies, the dropped items are now laying around in the game world. Players can pick them up by clicking on them.

I still need a way to drop items from the inventory.

Procedurally generated spells?

I played a lot of Borderlands 2 in the past weeks (great game, by the way) and noticed that the procedurally generated weapons are the greatest motivator in that game. I wondered if I should do something similar with the spells. Instead of having a number of predefined spells, players could find scrolls with spells which have randomized attributes.

Spells aren't learned anymore. Instead of that spells are items which are dragged&dropped in and out of the spellbook while in towns. Spells will still have a wisdom capacity they use and swapping will be impossible outside of towns, so players need to think carefully about how to design their spell palette. When each spell is unique and can only be used by one character, each character will have an unique playing style.

Balancing this will be really hard, but in the end it could be really worth it.

Input for randomization:
  • Element
  • Skill level requirement (primary indicator of the "power level")
  • Rarity
    • Rarity means more special effects, better chance for a more obscure area of effect, more extreme values for range and casting time and a chance for more damage.
Randomized attributes:
  • Damage (proportional to level requirement)
  • Range
  • Casting time (lower is better)
  • Area of effect
    • Single target (most frequent)
    • Splash damage with range X
    • Splash damage with range X, targets the floor 
    • Line damage (damages anything in a direct line between caster and target)
    • Chain damage (damages X enemies, each apart a distance of Y)
  • Special effects
    • Vampiric (steals HP)
    • Ethereal (damages MP instead of HP)
    • DoT (when combined with splash damage, it's an area denial spell)
    • Causes status effects
      • Curse (stat debuff)
      • Snare (reduce move speed)
      • Silence
Attributes calculated from those listed above
  • Mana cost
  • Wisdom cost
  • NPC value

To make all this a bit easier to balance, I could use a "building block" system where each spell has some randomized basic attributes and then gets a number of random blocks which modify it further.

  1. Start out with normal mana cost, damage, wisdom cost and range.
  2. Multiply mana cost, wisdom cost and damage with the level.
  3. Randomize all attributes just a tiny bit for some micro-variety
  4. For each rarity level:
    1. Do a "trade-off" - make one attribute worse by 25%, improve another by 25%
  5. Calculate base name based on the trade-offs made
    1. Good damage: Blast
    2. Good range: Arrow
    3. Good damage, bad range: Shock
    4. Good range, bad damage: Hex
    5. Good damage and range: Strike
    6. Bad damage and range: Trick
    7. Normal damage and range: Bolt
  6. For each rarity level above 1, do one of these bricks (discard duplicates). Each one increases cast time, mana cost and wisdom cost by a different amount.
    • Change the AoE (overrides the base name)
    • Make vampiric
    • Make ethereal
    • Add DoT
    • Cause a status effect on the enemy (multiple different ones are allowed, but not the same multiple times)
  7. Generate the name: [adjectives for bricks] [element] [base name]