General Mobs Base Class - UQcsse3200/2023-studio-3 GitHub Wiki

Introduction

The purpose of the class is to be a base structure for all mobs. It functions as a container for relevant information to all mobs and provides a consistent base to build future specialised mobs from. It holds all enemy stats such as health, speed, base attack, and all abilities including long-range and close-range attacks. It lacks functionality aside from retrieving information of a specific enemy and is only to be used as a base structure, helping to streamline enemy construction.

UML Diagram

Below is a UML diagram containing the key functionalities of the general mobs base class and their associated components, interfaces, animation controllers and tasks.

Sprint2_UML

BaseEnemyConfig

The BaseEnemyConfig holds all relevant information to initialise an advanced CombatStatsComponent which is responsible for handling combat-related statistics including dealing and taking damage.

BaseEnemyConfig config = configs.specialtyEnemy;
…
….addComponent(new CombatStatsComponent(conifg.fullHealth, config.baseAttack, config.drops, config.getCloseRangeAbilities, config.getLongRangeAbilities)…

specialtyEnemy is a predefined enemy type. This has minimal functionality and should only be used to define a Speciality Enemy and not be used as an enemy itself.

Weapon Interface

The Melee and Projectile classes implement the Weapon interface. The purpose of this interface is to promise the implementation of necessary functions and values to classes which can be used to attack. This interface is primarily featured in CombatStatsComponent.

public Weapon getWeapon(Entity target) {
  ArrayList<Melee> withinRange = withinRange(target);
  if (withinRange.size() > 0) {
  	return withinRange.get(pickRandom(withinRange));
  }
  return longRangeAttack();
}

The type of weapon will depend on the distance from the target and therefore cannot be promised as a singular type. Using the weapon interface ensures the returning value has required functionality for future uses of the value.

Melee

The Melee class is used to define an ability that will deal damage but requires a minimum distance from the target. It is implemented as a sibling to Projectiles where the CombatStatsComponent will call for a Weapon and return a Melee for close range or Projectile for long range. It is designed as a base to predefined Melee abilities and is used in PredefinedWeapons class. Its purpose is to store all relevant attributes required to attack a target.

Melee(int damage, int attackDamage, String element, int castTime, int cooldown)
 
Melee sword= new Melee(10, 4, “fire”, 1, 1);

PredefinedWeapons

This class is responsible for the storage of all weapons. All weapons should be defined in this class and accessed later. It is purely a container for weapon storage and does not have any other functionality, nor should it be used as anything else. When Specific mobs are built from the BaseEnemyConfig they will only contain predefined weapons from this class.

public class PredefinedWeapons {
	public static Melee sword = new Melee(10, 4, "fire", 1, 1);
	public static Melee punch = new Melee(3, 1, "air", 1, 1);
…

TouchAttackComponent

Below notes the changes that have been made to TouchAttackComponent.

onCollisionStart()

This was changed to a public function to be accessed from MobAttackTask.

chooseWeapon()

This method is used to select a weapon to attack the target at the provided Fixture. It will return a Weapon if there the entity has a long range or close-range ability that can be used against the target.

CombatStatsComponent

CombatStatsComponent was expanded upon to incorporate the abilities, close-range and long-range, that enemies have. There are two initialisers for this component including the original init and a new init which requires the drops, close range and long range of the entity. There were minimal changes, majority of alterations to this file were additions. The changes made include the addition of updating the state of the entity whenever health is updated.

The additional methods are:

  • getWeapon(): return a Weapon
  • withinRange(): return a list of all Melee which can attack the target (if close enough to use)
  • longRangeAttack(): pick a random long range attack if one exists
  • pickRandom(): pick a random index of the provided list
  • drop(): pick a random currency to drop

pickRandom(), withinRange() and longRangeAttack() work together to return the appropriate weapon when touchAttackComponent requests a weapon. getWeapon() receives a target Entity which will be passed to withinRange(). The withinRange() function will measure the distance between this and the target Entity’s location. For each closeRangeAttack, if the target is within range, it is added to a list of possible Melee weapons to use and it returned to getWeapon(). If none are returned then a Projectile is provided to touchAttackComponent, else a Melee is selected at random.

public void changeState() {
	if (this.health <= (this.fullHealth * 0.33)) {
    	…	
    }
}

NPCFactory

The NPCFactory is used to create the different kinds of non-playable character entities. This includes the general mobs, such as the Xeno Grunt.

createBaseNPC

The createBaseNPC() method has been edited to add the two AIComponent tasks. These are shown in the code snippet below, which comes after a new NPC entity is created.

new AITaskComponent()
            .addTask(new MobWanderTask(new Vector2(2f, 2f), 2f))
            .addTask(new MobAttackTask(2, 40));

createXenoGrunt

The createXenoGrunt() method has been modified to better suit the behaviour of the Xeno Grunts. The hitbox of the Xeno Grunt has been adjusted to be much smaller, meaning there are fewer collisions. This method first creates a base NPC, using createBaseNPC(), before adding specific functionality related to the Xeno Grunt. Additionally, the size of the hitbox has been changed to (.3, .5), which was determined by testing a range of different values and observing their effect on the game.

xenoGrunt.getComponent(HitboxComponent.class)
            .setAsBoxAligned(new Vector2(.3f, .5f), 
            PhysicsComponent.AlignX.RIGHT, PhysicsComponent.AlignY.BOTTOM)

PhysicsEngine

Some notable changes have been made in the PhysicsEngine, which are outlined below.

raycastGetHit()

This function will cast a straight line from one point to another and will return the Fixture of the first hit in the provided physics layer.

Test Plan

Tests for the NPCFactory, to ensure the Xeno Grunts are being created correctly, can be found in NPCFactoryTest. Below is an example test, which ensures the Xeno is not null.

@Test
public void testCreateXenoGruntNotNull() {
    assertNotNull(xenoGrunt, "Xeno Grunt should not be null");
}
⚠️ **GitHub.com Fallback** ⚠️