2

I have a question regarding objects. I develop some kind of a basic RPG. In this game I have a character (let's say this Character object is hero). hero has equipment according to primary hand, body armor etc. This hero wants to attack with the weapon wielded in his primary hand, let's say he has a long sword.

A word regard my Weapon class - the objects in this class have "attack" method. This method gets as an arguments the attacker and the target, so (weapon objects here).attack(hero, hero2) makes hero attack using the weapon object to attack hero2.

My question is as follows - can I avoid using attack(hero, hero2) somehow while the code knows that "hero" is the first objects that calls the attack method ?

That's the attack command:

hero.getEquipment().getPrimaryHand().attack(hero, hero2);

can "some code here" be replaced with something that can replace "hero" in the attack method ?

hero.getEquipment().getPrimaryHand().attack(some code here, hero2);

Edit: Addition of MeleeWeapon Class (subclass of weapon):

public class  MeleeWeapon extends Weapon {

boolean throwable;

MeleeWeapon(String name,String reqTraining, boolean oneHaned, int n, int dice, int attackBonus, int damageBonus,double weight, long cost, boolean throwable) {
    super(name, reqTraining, weight, cost, oneHaned, n, dice, attackBonus, damageBonus);
    this.throwable = throwable;
}

static ArrayList<MeleeWeapon> meleeWeaponList = new ArrayList<MeleeWeapon>();

static
{
    meleeWeaponList.add(new MeleeWeapon("Long Sword","Martial", true, 1, 8, 0, 0,8, 10, false));
    meleeWeaponList.add(new MeleeWeapon("Short Sword", "Martial", true, 1, 6, 0, 0,5, 5, false));
    meleeWeaponList.add(new MeleeWeapon("Dagger","Basic", true, 1, 4, 0, 0,2, 3, true));
    meleeWeaponList.add(new MeleeWeapon("Quarter-staff", "Basic", false,  1, 4, 0, 0,3, 2, false));
    meleeWeaponList.add(new MeleeWeapon("Shield", "Shield", false, 1, 4, 0, 0,8, 8, false));

}


public void attack(Character attacker, Character defender){

    int attackRoll = DiceRoller.roll(20) + attacker.getBaseAttackBonus() + attacker.getModifier(attacker.getStrength()) + getAttackBonus() ;
    System.out.println(attacker.getName() + " attack Roll: " + attackRoll + "AC: " + defender.getArmorClass());

    if (attackRoll >= defender.getArmorClass()){
        System.out.println("Defender: " + defender.getName() + " had " + defender.getCurrentHp());
        int damage = DiceRoller.roll(getN(), getDice()) + attacker.getModifier(attacker.getStrength()) + getDamageBonus() ;
        System.out.println("Damage : " + damage);
        defender.setCurrentHp(attacker.getCurrentHp() - damage);
        System.out.println("Defender: " + defender.getName() + " has " + defender.getCurrentHp());
    } else {
        System.out.println("Missed Attack");
    }

}
5
  • Surely the hand already knows who owns it? Commented Nov 17, 2015 at 10:42
  • 2
    so, a sword makes someone attack someone else. Don't you think it would be more logical if hero attacks an other hero and then find what he use using a sword? For example hero.attack(hero2) Commented Nov 17, 2015 at 10:43
  • of course, that's what I wanted to do in the first place, I just didn't know how. Commented Nov 17, 2015 at 10:43
  • wait a sec, I'll add a subclass of Weapon. Commented Nov 17, 2015 at 10:44
  • A note separate from the question, the constructor has way too many variables to be passed in. I would advise you to look into the Builder design pattern. Even if all of the fields are required, when an object is created the code would be a lot more readable. Commented Nov 17, 2015 at 11:00

2 Answers 2

2

You can have an attack method in your Character class that would wrap your other attack method :

public void attack (Character other) {
    getEquipment().getPrimaryHand().attack (this, other);
}

And you call it simply :

hero.attack (otherHero);
Sign up to request clarification or add additional context in comments.

8 Comments

That would be "Character" class, "hero" is just an object. Anyway, wouldn't it be too much responsibly for "Character" class ?
@Niminim Updated. I wasn't sure about the class names. What do you mean by "too much responsibility"?
Maybe it's wrong, but I thought about delegating the attack method to Weapon class rather than Character class. Is it a bad design ?
@Niminim The character is the one initiating the "attack" action, so it makes sense to have that method there. The Weapon is what causes the actual damage, so it makes sense to have an "attack" method there (or perhaps keep that method but with a different name, since the Weapon can't decide to attack on its own - I'm not sure which name would make sense here).
@Niminim Abstract classes can have implementations. A method that is common to all the sub-classes is usually implemented in the super class, regardless of whether it's abstract or not.
|
0

The weapon shouldn't be the one attacking. The Hero should have the attack method. You would need to pass in the other hero that is being attacked. The weapon being used to attack would be known to the method since it should be accessible within the Hero class as well.

There are a couple of reasons why the hero should have the attack method and not the weapon:

  1. Classes should model the real world so long as it makes sense. In real life a weapon is an extension of the attacker and not anything on its own. The weapon doesn't decide to attack, the character does. The weapon would just have stats that decide how effective the attack is.

  2. What happens if the Hero doesn't have a weapon equipped? This can be solved by having a weapon labelled "Fists" but this doesn't really seem to be neccesary.

This is a quick example of how it would be set up (obviously fields/classes/methods may be missing since its just an example)

class Hero {

    Weapon weapon;
    int health = 100;

    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

    public Weapon getWeapon() {
        return this.weapon;
    }

    public void attack(Hero heroBeingAttacked) {
        if (weapon.getType() == 1)
            heroBeingAttacked.wasAttacked(5);
        else if (weapon.getType() == 2)
            heroBeingAttacked.wasAttacked(15);
        else
            heroBeingAttacked.wasAttacked(0); 
    }

    public void wasAttacked(int damage) {
        this.health -= damage;
        //check if Hero dies, etc.
    }
}

1 Comment

Thanks for the code example! As Eran pointed out, using delegation in this case is not a good idea.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.