This thread is more for tracking development of some open source work rather than your typical project. If you were hoping for something fancy, or some project you could eventually play then you'd might as well stop reading here.
Still reading? Great.
One of the major blockers with Apollo is the lack of certain features, take combat for example. It's a complex system to put in place and takes a decent amount of time to get right while keeping the code clean enough to push upstream.
Graham, Major, and a few other people put a great deal of effort into Apollo. It's a shame to see it go to waste due to negligence on behalf of the community. It's not perfect, but it's the best we've got.
So enter the Apollo Usability Project. What is it? Well, it's an attempt to make Apollo more approachable and usable for everyone. To get some features on the plate and make it easier for Average Joe to `git clone` the repository and start hacking away. It's a bit of a long shot on my part, but work done here can at least benefit someone in the future. There are many issues to address, but the first one, I think, is the big one. I've been working away at it for a while and it'll soon be ready to merge upstream.
Step 1: Combat
I did have a look at some of the servers scattered around here for use as a reference. Unfortunately most of them were a bit weird. Though there was enough data to sift though and create a simple model.
(don't mind the weird association arrows, draw.io's a bit iffy.)
So there are Weapons, WeaponClasses, CombatStyles, Attacks, and AttackRequirements. If we exclude unique projectiles and other fancy stuff, this allows us to start with melee and ranged. It also gives us a way to define special attacks. Though we still need a good way to start creating weapons and their components and Ruby presents a great way to go about it.
Code:
DAGGER_WIDGET_ID = 89
DAGGER_SPECIAL_CONFIG_ID = 12
DAGGER_SPECIAL_BUTTON_ID = 10
create_weapon_class :dagger, widget: DAGGER_WIDGET_ID do
defaults speed: 4, animation: 7041, attack_type: :stab
attack_bonuses crush: -4, magic: 1
defence_bonuses magic: 1
style :accurate, button: 2
style :aggressive, button: 3
style :alt_aggressive, attack_type: :slash, animation: 7048, button: 4
style :defensive, animation: 7049, button: 5
end
# Need a separate WeaponClass for the dragon dagger because
# of the differing animations
create_weapon_class :dragon_dagger, widget: DAGGER_WIDGET_ID do
defaults speed: 4, animation: 402, attack_type: :stab
special_bar DAGGER_SPECIAL_CONFIG_ID, DAGGER_SPECIAL_BUTTON_ID
attack_bonuses crush: -4, magic: 1
defence_bonuses magic: 1
style :accurate, button: 2
style :aggressive, button: 3
style :alt_aggressive, attack_type: :slash, button: 4
style :defensive, button: 5
end
create_weapon /(?:drag|dragon) dagger.*/, :dragon_dagger do
set_special_attack energy_requirement: 25, animation: 1062, graphic: { id: 252, height: 100 } do
damage! delay: 0
damage! delay: 1
end
end
I think that's pretty nice and easy to work with. There's various options which can be set for the `damage!` call, including a damage modifier or a lambda which calculates damage for an attacker and target. We can set bonuses for the weapon class, and also for the weapon. The actual combat style `Attack`s are created in the create_weapon_class call, and it uses the type of weapon to figure out whether it should create a ranged or melee attack. The Attack implementations themselves are a bit more verbose, and are meant as internals. New attacks can be created via the AttackDSL (like with special attacks).
The simplest BaseAttack looks like this:
Code:
class BaseAttack
attr_reader :requirements, :range, :speed
def initialize(speed:, animation:, graphic: nil, range: 1, requirements: [])
@speed = speed
@animation = animation
@graphic = graphic
@range = range
@requirements = requirements
end
def do(source, target)
source.play_animation(Animation.new(@animation))
unless @graphic.nil?
if @graphic.is_a?(Hash)
source.play_graphic(Graphic.new(@graphic[:id], @graphic[:delay] || 0, @graphic[:height] || 0))
else
source.play_graphic(Graphic.new(@graphic))
end
end
apply(source, target)
end
def apply(_source, _target)
fail 'BaseAttack#apply unimplemented'
end
end
and a melee Attack can extend that like so:
Code:
class Attack < BaseAttack
def apply(source, target)
do_damage! source, target, CombatUtil.calculate_hit(source, target)
end
end
Now that we've got melee attacks working we need a way of dealing with all those unique ranged weapon projectiles. I did manage to find data on this, but large parts of it are missing (see below on how you can help this project!).
When we see a projectile firing, two things happen. First we see a graphic played on the player, and then we see another graphic sent as a projectile. The actual speed, height, falloff and curvature of the projectile varies for different types of ammo. The graphic is different for every item.
We can still set up a nice way to manage this, though. And my first attempt looks a little bit like this:
Here all of the arrows share a projectile type, and only have different graphics. We also define the level requirements and drop rates for the arrows inline (we can do bonuses too, but I haven't got around to that yet).
We can use the same weapon DSL again to create bows which use these arrows:
Again, it's pretty easy to follow and has good results:
There's still a couple of things to do, like making arrows drop and other misc. stuff, but I think it's pretty decent so far. Next up is magic after everything for range is in place and a bit of post-new-feature cleanup is done. There's a feature checklist below for what's still to do and I'll update this thread whenever I need to with more media and info.
[ ] - Support for hooking into combat (for e.g., differentiating between wilderness and safe minigames)
Contributing
There is still lots of information I need to gather to get this as close to RuneScape as possible. I don't have a decent account myself and I don't have the time to sift through all the servers in the Downloads section in search of the data I need. If you want to help at the moment, there's a list of stuff you can do below. More will come up as I uncover new edge cases and weird features so will update as needed.
Find bolt projectile data
Find darts / knives projectile data
Provide dumps of equipment and weapon bonuses
Point out inconsistencies in any of the info I've provided (either in video demos or in code snippets)
Credits where credits are due
sfix
Major
Shiver
The creators of all the spaghetti servers I downloaded who went through the painstaking process of getting info.
Other people who helped with bringing it together: Scu11, S Quare Quxx, Wizard Jesse
When I'm happy with the framework I've written and it's upstream there's a lot more you'd be able to do to contribute. Around then, I'll throw up a simple development sandbox behind a tunnel (no attacking my dedicated server!) so it can be tested out.
Step 2: Hey, Step #1 isn't done yet.
"Im so bluezd out of my box.
Im so fkd i canr even sens makeas Smoke blunt 420hash e tizday" - A legendary guy (1993 - 2015)
Originally Posted by nmopal
I will be creating a grimy dubstep song using these lyrics and vocaloid please prepare your bodies