If a weapon can be upgraded (ex. purchase silencer for Beretta 9mm) through purchase of upgrades, and also 'upgraded' through player skill trees (ex. '+10% accuracy with pistols'), I was thinking that it might be best, on creation of the item, to poll the player for their skills and adjust the attributes accordingly and then to have an instance reference of a 'WeaponUpgrade' class which holds the internal (and importantly, specific to that instance of that weapon) upgrades, also adjusting the attributes.

The individual weapons are implemented already ie Beretta9mm extends Pistol, which extends RangedWeapon, so on and so forth back up to Item. The reason for this architecture is to allow a player to have any sort of item, be it a Pistol or a Potion, in their hot bar, and use it by clicking.

The question, or rather more of a implementation proposal since everyone does things their own way, is that I'm suggesting within the class Weapon:

1 2 3 4 5 6 7 8 9 10

publicabstractclassWeaponextendsItem {protecteddoubledamage;protecteddoubleknockback;protecteddoublespeed; //time (in seconds) for a full attack.protecteddoubleatkTime;

protecteddoubleaccuracy; //lower is more accurateprotecteddoubleaccuracyModifier;// etc.. with other attributes, plus:protectedWeaponUpgradeupgrade;

And when the player stops in at the upgrade shop / other gameplay contrivance, the WeaponUpgrade is retrieved from the weapon, an attribute of it is modified, ex:

1 2 3

publicvoidsetAccuracyBonus(doubled){this.accuracyBonus += d;}

and off the player goes, now with a more accurate, reliable weapon.

When the accuracy (or damage, or knockback, or other attribute) of the weapon then needs to be retrieved, it can be grabbed as some calculation performed on:1. the weapon's base attribute2. modifiers provided by specific upgrades to that instance of the weapon3. the player's global benefits for weapons of that class (ie pistols)

If anything, I guess I'm asking if this seems like a reasonable way to go about doing things, or if there's some glaring oversight I'm making.

That's what i'd do, declare all the various upgrade/statistics variables of the UpgradeClass, than when a upgrade is clicked in the shop, set all the variables accordingly to the current level, and set the bonuses++ accordingly to the current upgrade bieng purchased.

His post itemizes many things that you might want to consider for your item framework.

The general consensus is that class hierarchies are too restrictive when designing RPG entities. For example if you have a gun with a bayonet on it how will it fit into your hierarchy? I would recommend some kind of very flat framework or component-based system aka composition to give you the needed flexibility.

I think it would be "cleaner" to keep weapons and player skill upgrades clearly separated. I'd not have any player skill related variables in my Weapon class, and instead pass the PlayerSkills/UpgradeClass (whatever you call it xd) to the Weapon each fire()/update().

I think it would be "cleaner" to keep weapons and player skill upgrades clearly separated. I'd not have any player skill related variables in my Weapon class, and instead pass the PlayerSkills/UpgradeClass (whatever you call it xd) to the Weapon each fire()/update().

Right. The idea is that the Player Skills and Upgrades are 2 separate ideas. IE:

What everyone else has been saying: the less mutation of state you do the better. Wielding a weapon shouldn't modify a "damage" variable on the player, it should simply be included in a "calculateDamage()" method. RPGs can involve dozens of variables for calculating stats, but it's something even the weakest computer nowadays will do in microseconds.

If you want to be fancy, then even an old standby like "hit points" is something you might want to calculate by keeping a list of individual wounds with their respective HP penalty, rather than just decrementing a variable. Then when a player applies the "first aid" skill, you can limit it to removing only wounds that his skill is sufficient to treat. Of course, if your game models a player's health by way of a life bar, then by no means indulge in design overkill like that. Your code design should reflect the game you want

I just said something like this in a previous thread. What's the difference between two ranged weapon? Some data...so you could skip on subclassing RangedWeapon. What's the difference between a MeleeWeapon and a RangedWepon? Some data...so you could skip on subclass Weapon. The point to stop with this kind of thinking is (roughly) when a parent and child require different state data.

I just said something like this in a previous thread. What's the difference between two ranged weapon? Some data...so you could skip on subclassing RangedWeapon. What's the difference between a MeleeWeapon and a RangedWepon? Some data...so you could skip on subclass Weapon. The point to stop with this kind of thinking is (roughly) when a parent and child require different state data.

In my implementation MeleeWeapons and RangedWeapons hold different sorts of data and override methods in different ways, so the subclassing is relevant.

I think he meant that subclasses of RangedWeapon, like LongBow, CrossBow, Sling, etc aren't useful subclasses. The behaviors of ranged and melee are different enough that they might deserve to be subclasses of Weapon, but individual cases of them aren't really sufficient.

That brings us back to the "gun with a bayonet" problem though, and the answer is pretty simple: it's two weapons. The identity of a single object shouldn't be confused with the possibly multiple instances that may constitute its behavior. Similarly a robe with pouches could be armor and a bag. Rather than trying to fake multiple inheritance, you just accept that one item may actually be a composite of several objects.

This has implications for where you put unrelated properties like "sale value" and "durability" for example. The answer there may be you either create a CompositeItem for such chimeras, or you treat Weapon, Armor, and Bag as behaviors attached to Items, not subclasses of Item. I prefer the behavior angle, but there's probably no single right answer there, it's mostly a matter of what you're most comfortable with and what tradeoffs you're willing to make.

I think he meant that subclasses of RangedWeapon, like LongBow, CrossBow, Sling, etc aren't useful subclasses.

Yes. Exactly this. These things only vary by data. And remember that "code" can be considered data. Take a game like the original doom. All weapons could be used in exactly one way (bound to some input). The original Unreal? Each could be exactly used in two ways (by default bound to L&R mouse button). In the "classic" RPG "Dungeon Master" any item could be placed in the "weapon" hand and by clicking the GUI button the player could choose up to three different attacks depending on the item in question. In none of these examples does the "type" of weapon or what the kind of attack does effect how it's triggered. Each just has more or less ways a given item can be used to perform an attack action.

Here's a rough sketch of a possible design direction:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

// concrete sub-classes of this deal with what a given attack "does" and the data (not specific to the given item)// may be stored.publicabstractclassOnAttackextendsPerhapsSomeBaseActionClass{// there could be some "bookkeeping" method here which deals with higher order logic// common to all attacks here, which in turn calls 'exec' or not depending on the // overall design.

I think he meant that subclasses of RangedWeapon, like LongBow, CrossBow, Sling, etc aren't useful subclasses. The behaviors of ranged and melee are different enough that they might deserve to be subclasses of Weapon, but individual cases of them aren't really sufficient.

That brings us back to the "gun with a bayonet" problem though, and the answer is pretty simple: it's two weapons. The identity of a single object shouldn't be confused with the possibly multiple instances that may constitute its behavior. Similarly a robe with pouches could be armor and a bag. Rather than trying to fake multiple inheritance, you just accept that one item may actually be a composite of several objects.

This has implications for where you put unrelated properties like "sale value" and "durability" for example. The answer there may be you either create a CompositeItem for such chimeras, or you treat Weapon, Armor, and Bag as behaviors attached to Items, not subclasses of Item. I prefer the behavior angle, but there's probably no single right answer there, it's mostly a matter of what you're most comfortable with and what tradeoffs you're willing to make.

So I think what you might be getting at with the data part of things (though I am rather ignoring your confusing Robe example), is that instead of :

[EDIT] to clarify, the reason that the Automatic part is specified is that upon use, it may have different attack behavior than a pistol (automatic fire, etc...) or a shotgun (shotgun may generate 8 attacks for spray).

Sometimes that's all you'll need and this form has the most amount of flexibility. If you have odd items you could change "type" -> Set(...).

From there introduce a class hierarchy where it makes sense. You could design your classes so that they just contain static methods that operate on the raw HashMaps thus decoupling your logic from the data.

Anyways, you avoid introducing classes too early which will only end up restricting you.

Notice if you construct your class hierarchy properly then you could have a big list of "active upgrades" and then you just daisy chain the calculations to determine the final actual result to use in combat. You still have access to your original unmodified weapon too (m16).

How much you need to complicate things mostly depend on what kind of upgrades that you have. If you want to be able to add and remove "buffs" and modifiers then you'll need to keep track of the base value of the weapon and either compute the value every update or when a weapon's stat modifiers change. This is to avoid rounding errors, obviously assuming you're using floating point variables for stats. I'd strongly recommend doing so though, since a 10% bonus to a 5 damage weapon is still 5 otherwise...

How much you need to complicate things mostly depend on what kind of upgrades that you have. If you want to be able to add and remove "buffs" and modifiers then you'll need to keep track of the base value of the weapon and either compute the value every update or when a weapon's stat modifiers change.

Exactly! With all entities represented as a simple data structure i.e. a HashMap, this becomes really easy. A damage buff/debuff is stored as a tuple of <String, Integer> e.g. "damage", 10. Negative numbers are debuffs.

Store a list of them and calculate the final value only when you need it. Adding a buff to a weapon/item/mobile/anything is easy: just instantiate another tuple and add it to the list. Expiring buffs are a snap as well: just remove them from the list.

First of all, enums can have fields and constructors, so if you used them to store the stats, you can store them on the enum itself. However, you probably want to avoid this approach, because all instances of enums are staticly defined (which is largely the point of enums), so you would have to recompile your app to add a new weapon. What you're going to want eventually is to read in some kind of config, like xml or json or .ini format, that builds a map of weapon definitions.

First of all, enums can have fields and constructors, so if you used them to store the stats, you can store them on the enum itself. However, you probably want to avoid this approach, because all instances of enums are staticly defined (which is largely the point of enums), so you would have to recompile your app to add a new weapon. What you're going to want eventually is to read in some kind of config, like xml or json or .ini format, that builds a map of weapon definitions.

Personally I'd prefer keeping it out of config files to prevent users from adding their own weapon definitions, especially for a 'campaign mode' style single player.

You can always make java source code the config format, which will effectively freeze the config for whatever mode you're using, but I still wouldn't go as far as hardwiring them into an enum. Even a shooter will want to support mods.

I don't think changing a config file to add a new weapon really counts as "modding" IMO But I do see your point. Things like NPC (written) dialogue, texture filepaths and other sorts might also belong outside of the code.

How much you need to complicate things mostly depend on what kind of upgrades that you have. If you want to be able to add and remove "buffs" and modifiers then you'll need to keep track of the base value of the weapon and either compute the value every update or when a weapon's stat modifiers change.

Exactly! With all entities represented as a simple data structure i.e. a HashMap, this becomes really easy. A damage buff/debuff is stored as a tuple of <String, Integer> e.g. "damage", 10. Negative numbers are debuffs.

Store a list of them and calculate the final value only when you need it. Adding a buff to a weapon/item/mobile/anything is easy: just instantiate another tuple and add it to the list. Expiring buffs are a snap as well: just remove them from the list.

Okay, so now you're storing weapons, their modifiers and items in HashMap<String, Object>s. Are you going to store player properties in a HashMap too? Game objects? I'd say you're completely missing the point of object orientation. HashMaps also do not preserve the ordering of objects. This kills determinism for online games, and it might also be good to be able to control in which order for example modifiers are applied, because you'd want a +20% damage bonus to be applied before a +5 flat damage bonus so the % bonus is applied to the flat bonus too. What you're doing is emulating objects with Strings in HashMaps. HashMaps themselves are in my opinion just a glorified emulation of references anyway, so you're emulating objects and keeping them in emulated references. I'd stay far away from that kind of code if I were you... ._.

Okay, so now you're storing weapons, their modifiers and items in HashMap<String, Object>s. Are you going to store player properties in a HashMap too? Game objects? I'd say you're completely missing the point of object orientation. HashMaps also do not preserve the ordering of objects. This kills determinism for online games, and it might also be good to be able to control in which order for example modifiers are applied, because you'd want a +20% damage bonus to be applied before a +5 flat damage bonus so the % bonus is applied to the flat bonus too. What you're doing is emulating objects with Strings in HashMaps. HashMaps themselves are in my opinion just a glorified emulation of references anyway, so you're emulating objects and keeping them in emulated references. I'd stay far away from that kind of code if I were you... ._.

Nah, the statistics are in the HashMap but the modifiers are stored separately e.g. in a List.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org