Introduction

Well it’s time for another scope of work document. We’ve just recently finished the items and inventory sprint, and the system looks pretty good. Now that we can equip items, we need to start working on some basic abilities. The basic abilities will depend on which type of weapon you’re using. So, lets map out of some this from the start.

weapon_chart

Basics

So, lets review some of the above information. We’ve got several different weapon types, but rather few actions to be performed. After some brainstorming last night, it became clear that the only thing different between the melee weapons is the animation, and the attack range. Let me explain.

If you’re using a sword, the animation should be a slash, whereas if you’re using an axe, it should be a hacking animation. Same thing for club (crushing animation), and spear/dagger (stabbing animation).

Now, what’s the difference between a one-handed weapon and a two-handed weapon. Well, the one handed weapon will likely have less reach on it, so the attack range will be shorter than that of a 2H weapon.

On second thought, lets visualize some things real quick. This will help to explain some of the following concepts.

melee_attack_illustrationAs we can see, both the one-handed attack range, as well as hitbox is smaller than the two-handed version. The illustration shows the hitboxes at their max range, so as to illustrate that the maximum range is actually the normal attack range + 1/2 of the hitbox radius.

Shields will provide a passive blocking effect. The hitbox that is illustrated will align itself to whichever direction the player is facing. When a projectile hits the collider, there is some math done, to determine whether or not the shield blocked it, and then some more math will be done to determine if any damage at all is dealt.

This is all well and good, but what about projectiles. How do they work? Again, lets visualize.

ranged_illustration

On the left hand side, we see a player using a wand. The magic projectile leavest he character at an offset from its own collider (shown in red). The offset for all ranged projectiles is the same (-0.5, 0.5). On the right hand side, we can see the player shooting a bow. The collider for the arrow is different from the one of the magic projectile. All projectiles will have their own collider that matches their shape.

On the bottom is where it all makes sense. We can see a player getting hit by an arrow, and we can see that the visual offset matches the collider offset. If we did not have the offset, it would be like projectiles were shot (or cast) from the player’s feet, rather than the midsection.

This brings me to an interesting point. If the creature is larger, then the offset between the projectile and the hitbox should also be larger.

demon_projectileThe offset in the previous illustrations was 16 pixels, the above is 32 pixels. So that implies that we need a way for the projectile script (or whatever script handles this), to know about the size of the caster’s collider (shown in green above), and to scale the animation/collider offset with that. Interesting.

Retro Edit: It turns out that not only does the collider need to rotate, but the sprite needs to rotate as well. In addition, they both need to rotate independent of each other. See the GIF below.

arrow_rotation

Misc Notes

I’d like to note a few things here. I’m not sure where else to put them, so…

  • Dual-wielding will allow for two basic attacks instead of one. This will work by reducing the cooldown time of the melee ability to half of its original time.
  • All abilities will be smart cast, such that if you click out of the range of the circle, it will cast at the maximum allowable range.
  • Ranged projectiles have colliders, and as such, can collide with each other.
    • Physical projectiles (like arrows and bolts) will cancel out in mid-air.
    • Magic projectiles will cancel out depending on which one has more energy.
  • Magic Projectiles and Energy
    • When a wand shoots, it shoots a magic projectile.
    • The projectile will continue in a straight line indefinitely.
    • As the projectile travels, it loses energy.
    • As energy is depleted, the sprite begins to fade, and the damage dealt will be reduced.
    • At some point the magic projectile will fade away to nothing and disappear.
    • The higher the ‘magic skill’ of the wielder, the more energy the projectile has.
  • Spellbooks
    • Spellbooks contain a maximum number of pages.
    • Scrolls can be found, and added to spellbooks.
    • The scrolls in a spellbook determine what spells a player can use.
    • Spellbooks must be equipped in a hand slot to use spells.

Dual Wielding

Dual-wielding offers some really interesting match ups. Lets take a look a the dual-wielding matrix.

dual_wield_chart

Some of the really interesting combinations that pop out at me:

  • Wand / Wand  = projectile spam
  • Melee / Spellbook = spellblade class
  • Spellbook / Ranged = wizard archer?
  • Shield / Shield = ultimate tank
  • Spellbook / Spellbook = professional wizard
  • Melee / Ranged = skirmisher class

Sprint Details

Okay, so a lot of what we’ve been talking about has felt like theory-crafting, and while we’ve come to some useful conclusions, we don’t have a development list, or any idea as to how scripts will work or function. Lets get started on that part now.

Firstly, we’ll need some kind of way of saying that an item is a sword, or a 2-handed sword, or shield, etc. We’ve been sub-classing so far with items, such that an Item can be a Container. I think the next sub-class will be Weapon. This would mean that things like wands, and shields would also be classified as Weapons, which is weird, but I can get over that. WeaponType.Shield makes me itch a bit.

Then we’ll need a way of handling equipping of weapons. This can tie into our Equipment script, and is easy to implement. I was originally thinking we’d have a helper class to handle all of the details, but the logic is fairly simple. All one-handed weapons can be equipped together, no matter the matchup, and a two-handed weapon can only be equipped if nothing else is equipped (in hand slots).

Now, we’ll also need a way of triggering actions. This means we’ll need to upgrade our keybinds stuff to include keybinds for up to ten actions. The UI and other code for this is already in place, just need to add them.

The action bar will need its own script. This means showing the hotkey options for each option, as well as the click-drag functionality that allows us to move action icons to the action bar.

This brings me to the next point. Where do we drag actions from? Well, all of basic abilities are ‘physical abilities’ (even swinging a wand, as the action of swinging is physical). So, we should create a window that shows all the available physical actions. This UI can expand to include other physical abilities at a later time (charge, whirlwind, etc).

Now this brings up the question of how do we save the action bar settings, when the player logs in and out. Suppose I set ‘melee attack’ to E, and ‘ranged attack’ to R, when I log out, and then back in, I expect those same actions to be on the action bar. So, we need to serialize the action settings. Maybe we’ll need to make another table, maybe we’ll just tack this into the player table. I’m leaning towards the first option despite it being more code.

Then we need a way of handling physical attacks. The way these work is they’re given a position, they create a collider at that position, and play an animation and sound. When the collider triggers something, or after it hits nothing, the collider is destroyed, and damage is dealt. So, lets call this ‘physical attack’.

We also need a way of handling ranged attacks. This would be fairly similar for physical, as well as magic attacks. They both have colliders, animations, and sound effects. The only difference is the collision handling between them, as well as the damage calculation. Lets call these ranged attacks.

I can already tell that there are going to be some components that are shared between these features. I can’t yet tell which they are, but I’m sure I can re-use a good deal of code between these features.

Then we need to handle how shields work. Shields should have a block chance, and a block amount (chance varies with the size of the shield, block amount varies with the material of the shield). Shields should not block magic (at least not for now).

All of the stuff to do with the actual calculation of damage will be pushed off to another sprint following this one.

All abilities should cost some quantity of stamina. Some should cost more than others. So, that means that we need to subtract stamina from the creature as it uses physical abilities.

Also, the logic for smart-casting and all of that should be built in as well.

We’ll also need a bunch of sound assets to make sounds for all of the abilities.

There is also the issue of ranged weapon and projectile. Arrows for example, should stack, and be placed in the projectile slot. They are used by the bow in the main hand slot. Spears or throwing daggers should be stackable, and should be in the main hand slot, and NOT the projectile slot. This will be somewhat interesting, and looks kind of foggy to me right now.

This scope is already getting fairly large, so lets draw the line somewhere. I’m sure I’ve forgotten something, but I’m also sure I’ll revisit this post mid-way during development. Man, this is going to be another 2-3 week sprint at least.

Sprint To-Do List:

  • Weapon Sub-class
  • Update equipment class to include weapon equip rules
  • Add action keybinds
  • Action bar script
  • Physical abilities UI
  • Action serialization to database
  • Physical attacks
  • Ranged attacks
  • Shield blocks
  • Stamina resource cost
  • Smart-cast logic
  • Sound assets
  • Ranged weapon / projectile logic
  • Stackable items

Further Considerations (3/22/2016)

 

So I’m working on this sprint, and I’ve hit a bit of a tough spot. I’d like to once again work this problem out here, so that I might know where to go. The issue is to do with actions, or how we’ll implement abilities. I’m trying to think ahead to support a number of ideas, and not just hack something together to make it work for this sprint.

Firstly, lets make a quick list of possible actions, grouped by type:

  • Basic Abilities
    • Melee attack
    • Ranged attack
    • Wand attack
  • Spells
    • Fireball
    • Magic missile
    • etc
  • Divine Abilities
    • Heal
    • Bless
    • etc
  • Consumable Items
    • Health potion
    • Rune stone
    • etc

So basic abilities are those that are involved with the usage of weapons of some sort. The idea is that to use a melee attack for example, you need to have a melee weapon equipped (1h, dual wield, or 2h). To use a ranged attack, you need to have a bow, or spear, or whatever equipped, etc.

This brings me to an interesting idea. Lets imagine that physical damage has sub-categories. For example, hacking, slashing, or crushing. Now lets say you’re dual-wielding an axe and a mace. Now lets suppose you’re fighting some monster that is immune to crushing damage.

Now in the ‘current’ system, you would press your physical attack button, and it would trigger, and it would strike first with the axe (dealing damage). Then the cooldown would be reset, and you would swing with your mace (dealing no damage). However, making the 2nd attack would cost stamina, and as such it would be wasted. You can see the problem here. Imagine if each weapon had its own cooldown, and you were able to trigger each weapon independently. Then you could only use your axe, and not waste stamina.

Another example would be if we considered dual-wielding ranged items. In the ‘current’ system, all ranged items are 2H, but I see no reason why there can’t be a 1H crossbow for example. Its already possible to dual-wield 1h spears, and they’re thrown (not ranged). Some of the possible thrown weapons include spears, daggers, and stones.

Now imagine we had a stone equipped in the left hand, and a spear in the right hand. Again, in the current system we would click on our ranged attack, and one would fire, then we’d wait, click again, and the other would fire. Sure there’s the same stamina problem as previously mentioned, but in addition, there’s no way to ‘burst’ the enemy with two spears thrown either together or in quick succession.

So here’s my idea. What if instead of having abilities, all actions were somewhat dependent on items. That already makes sense for weapons, and shields. It also makes sense for spells (since they’re just scrolls stored in spellbooks), and of course it works for consumables.

But what about divine abilities. Originally I was going to let these just be abilities that are known by the priest, but I suppose I could make them dependent on items as well. Maybe we utilize some of the odd sprites that Tibia has and make Relics which allow for certain abilities to be used. Instead of keeping a set number of scrolls in a spellbook, the priest could keep any number of relics in their backpack. Thats an interesting concept.

Well, I’m not sure yet, but I think this idea might have hit a dead end. What about physical abilities like the warrior’s whirlwind, or the rogue’s stealth. There’s no real way to tie those actions to items. Hmm. I think I still want to do all of the above ideas, but I need to reconsider removing abilities all together.

I think the nature of my query is that I need to consider the relationship between ‘item use’ and ‘ability/action’.

So, I think every item will have a Use() function. Each item could also have an option to choose from a drop down to selection the action that fires when the item is used. Lets imagine what some of these could be.

  • Sword/Axe/Club/etc – these could call some system and ask it to DoMeleeAttack()
  • Wand / Ranged – these would work the same way and call DoRangedAttack or DoWandAttack
  • Spellbook / Scroll / Relic – again, similarly this would call DoCastSpell() or DoCastDivine()
  • Potions / Consumable – this would call DoConsumeItem() and then trigger some effect
  • Whirlwind / Stealth – this could call something like DoPhysicalAbility()

Okay, but how are these scirpts actually called. I imagine the flow to be something like this:

actions_diagram

I had thought about just adding the action scripts to items as a mono behaviour, but that doesn’t seem that appealing. The reason is that I’d have a script sitting there, doing mostly nothing, consuming memory, especially if there’s lots of copies of an item. In addition, I just feel like its not the right way of going about it.

I’d rather just have the items or abilities call a singleton component (action system), which then relays the information to the correct action script. I think this is the right way of going about things, and I’m going to try it out. If it doesn’t work, I’ll be back.

Even Furtherer Considerations (3/24/2016)

Progress is going well, and I’m happy with the ideas that I have currently. However, I’ve gotten to the point where I can click and drag a weapon onto the action bar, and I’m able to hit the keybind for that slot. It goes all the way to the server, where the server then fires a currently empty Melee Attack script.

What I’d like to figure out now is how to do the effect system. See there are all kinds of effects that need to be displayed, for various reasons, and in different ways. Let me list some of them, and describe them.

  • Single-Animation: these are the ‘poofs’ and ‘sparks’ of classic tibia, as well as the blood hits that show when damage has been done.
    • These effects occur only for a second, for the animation to play once, and then are destroyed.
    • These would also include things like the explosion effect at the end of a fireball.
  • Projectile Effects: these are the effects on things like fireballs, magic missiles, ice shots, etc.
    • These effects are oriented in the direction they are traveling.
  • Dependent-Looping-Animation: these would be things like the casting animation when a player casts a spell.
    • The animation loops for some time, and is dependent on the player not being interrupted.
  • Semi-Permanent Animation: these are animations that are either very long duration, or permanent.
    • This would include for example a fire field that exists for up to ten minutes.
    • This would also include a permanent shimmer effect on some statue for example.

All of these effects would have to exist in the correct render order, and would be need to be sorted correctly by the player camera script. Currently that would mean having a network identity, and being spawned across the server, but it doesn’t have to work that way.

Lets talk about the way in which these different animations would exist in the world.

  • Single-Animation: this would be an object that is spawned in the world, the animation plays, and the object is destroyed at the end of it.
  • Projectile-Animation: this is tied to the actual projectile with its collider. The animation would be destroyed on collision probably.
  • Dependent-Looping: this would also be tied to some game object, which would be destroyed when the spell is completed or canceled.
  • Semi-Permanent: this would also be tied to the object. Very simple.

So, I think my concern here is that I could potentially be spawning a lot of single animation effects. Say for example a warrior does a whirlwind ability (which triggers 16 ‘poof’ animations around him) at the same time as a wizards fireball explodes (triggering, another 16 explosion animations). Thats 32 game objects we just instantiated over the network, and that will probably be sent to all players on the network. I’m not sure if thats entirely correct, there might be some stuff Unity does behind the scenes.

I suppose the alternative would be to figure out who’s able to see the animaiton, and then send them a message, and then the client-side spoofs the animation. This has two problems:

1. We need to figure out who sees the animation, which is hard to do considering floors, and visibility. We could just use a distance check, but thats also expensive and not very good.
2. The client-side spoofing would imply that we’d need to hack that into our player camera script so that its included with all the other network behaviors, despite not having one.

So, I think the answer is clear. I’ll go with the lazy way, which might mean more network traffic, but for now, I can’t see any other way. We’ll give that a shot and if there’s performance problems, we’ll figure something else out.