Improvements
Randomized Girl damage Better attack range calculation Fixes some errors Better checking for which weapon was used Weapons now increase attack Manga is now consumable Adds a missing wall Stops calling consumables potions Better player stats Removes hp numbers
This commit is contained in:
@ -25,7 +25,8 @@ public class Girl implements INonPlayer {
|
||||
private int hp;
|
||||
private int attack;
|
||||
private int defence;
|
||||
private int visibility;
|
||||
private int visibility;
|
||||
private int damage;
|
||||
private final Backpack backpack = new Backpack();
|
||||
private static final Random random = new Random();
|
||||
private List<Class<?>> validItems;
|
||||
@ -42,30 +43,35 @@ public class Girl implements INonPlayer {
|
||||
maxhp = 30;
|
||||
attack = 10;
|
||||
defence = 50;
|
||||
damage = 1 + random.nextInt(5);
|
||||
visibility = 1;
|
||||
break;
|
||||
case CHILD:
|
||||
maxhp = 50;
|
||||
attack = 20;
|
||||
defence = 40;
|
||||
damage = 2 + random.nextInt(5);
|
||||
visibility = 2;
|
||||
break;
|
||||
case TEEN:
|
||||
maxhp = 70;
|
||||
attack = 25;
|
||||
defence = 30;
|
||||
damage = 3 + random.nextInt(5);
|
||||
visibility = 3;
|
||||
break;
|
||||
case ADULT:
|
||||
maxhp = 100;
|
||||
attack = 30;
|
||||
defence = 20;
|
||||
damage = 4 + random.nextInt(5);
|
||||
visibility = 4;
|
||||
break;
|
||||
case ELDER:
|
||||
maxhp = 70;
|
||||
attack = 15;
|
||||
defence = 35;
|
||||
damage = 3 + random.nextInt(5);
|
||||
visibility = 2;
|
||||
break;
|
||||
}
|
||||
@ -169,11 +175,11 @@ public class Girl implements INonPlayer {
|
||||
}
|
||||
break;
|
||||
case MAGE:
|
||||
if (NPC.tryAttack(game, 2, Attack.MAGIC)) {
|
||||
if (NPC.tryAttack(game, getVision() / 2 + getVision() % 2 == 0 ? 0 : 1, Attack.MAGIC)) {
|
||||
return true;
|
||||
}
|
||||
case BOWSMAN:
|
||||
if (NPC.tryAttack(game, 4, Attack.RANGED)) {
|
||||
if (NPC.tryAttack(game, getVision(), Attack.RANGED)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -213,7 +219,7 @@ public class Girl implements INonPlayer {
|
||||
|
||||
@Override
|
||||
public int getDamage() {
|
||||
return 5;
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -20,7 +20,7 @@ import inf101.v18.rogue101.Main;
|
||||
import inf101.v18.rogue101.enemies.Boss;
|
||||
import inf101.v18.rogue101.enemies.Girl;
|
||||
import inf101.v18.rogue101.examples.Carrot;
|
||||
import inf101.v18.rogue101.examples.Manga;
|
||||
import inf101.v18.rogue101.items.Manga;
|
||||
import inf101.v18.rogue101.items.*;
|
||||
import inf101.v18.rogue101.examples.Rabbit;
|
||||
import inf101.v18.rogue101.map.GameMap;
|
||||
@ -67,7 +67,7 @@ public class Game implements IGame {
|
||||
private final ITurtle painter;
|
||||
private final Printer printer;
|
||||
private int numPlayers = 0;
|
||||
boolean won = false;
|
||||
private boolean won = false;
|
||||
|
||||
public Game(Screen screen, ITurtle painter, Printer printer) {
|
||||
this.painter = painter;
|
||||
@ -91,7 +91,7 @@ public class Game implements IGame {
|
||||
map.add(map.getLocation( 3, 3), new Player()); //We must be sure there is never more than one player
|
||||
|
||||
// Prints some helpful information.
|
||||
String[] info = {"Controls:", "WASD or arrow keys for movement", "E to pick up an item", "Q to drop an item", "1-0 to choose an item (10=0)", "N to change name", "ENTER to confirm", "R to use a ranged attack", "F to use a magic attack", "C to use a potion"};
|
||||
String[] info = {"Controls:", "WASD or arrow keys for movement", "E to pick up an item", "Q to drop an item", "1-0 to choose an item (10=0)", "N to change name", "ENTER to confirm", "R to use a ranged attack", "F to use a magic attack", "C to use a consumable"};
|
||||
for (int i = 0; i < info.length; i++) {
|
||||
this.printer.printAt(Main.COLUMN_RIGHTSIDE_START, 1 + i, info[i]);
|
||||
}
|
||||
@ -125,18 +125,46 @@ public class Game implements IGame {
|
||||
map.add(currentLocation, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes up one floor if possible.
|
||||
*/
|
||||
public void goUp() {
|
||||
if (currentLVL + 1 < maps.size()) {
|
||||
map = maps.get(++currentLVL);
|
||||
if (!map.has(currentLocation, currentActor)) {
|
||||
map.add(currentLocation, currentActor);
|
||||
}
|
||||
actors = new ArrayList<>();
|
||||
displayMessage("You went up the stairs");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes down one floor if possible.
|
||||
*/
|
||||
public void goDown() {
|
||||
if (currentLVL > 0) {
|
||||
map = maps.get(--currentLVL);
|
||||
if (!map.has(currentLocation, currentActor)) {
|
||||
map.add(currentLocation, currentActor);
|
||||
}
|
||||
actors = new ArrayList<>();
|
||||
displayMessage("You went down the stairs");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the attack of an IActor based on equipped items.
|
||||
*
|
||||
* @return The attack
|
||||
*/
|
||||
private int getAttack() {
|
||||
int damage = currentActor.getAttack() + random.nextInt(20) + 1;
|
||||
IBuffItem buff = (IBuffItem)currentActor.getItem(IBuffItem.class);
|
||||
if (buff != null) {
|
||||
damage += buff.getBuffDamage();
|
||||
private int getAttack(Attack type) {
|
||||
int attack = currentActor.getAttack() + random.nextInt(20) + 1;
|
||||
IWeapon weapon = NPC.getWeapon(type, currentActor);
|
||||
if (weapon != null) {
|
||||
attack += weapon.getWeaponAttack();
|
||||
}
|
||||
return damage;
|
||||
return attack;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,42 +183,23 @@ public class Game implements IGame {
|
||||
return defence;
|
||||
}
|
||||
|
||||
public void goUp() {
|
||||
if (currentLVL + 1 < maps.size()) {
|
||||
map = maps.get(++currentLVL);
|
||||
if (!map.has(currentLocation, currentActor)) {
|
||||
map.add(currentLocation, currentActor);
|
||||
}
|
||||
actors = new ArrayList<>();
|
||||
displayMessage("You went up the stairs");
|
||||
}
|
||||
}
|
||||
|
||||
public void goDown() {
|
||||
if (currentLVL > 0) {
|
||||
map = maps.get(--currentLVL);
|
||||
if (!map.has(currentLocation, currentActor)) {
|
||||
map.add(currentLocation, currentActor);
|
||||
}
|
||||
actors = new ArrayList<>();
|
||||
displayMessage("You went down the stairs");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the damage done against the current target.
|
||||
*
|
||||
* @param target The target to evaluate.
|
||||
* @return The damage done to the target.
|
||||
*/
|
||||
private int getDamage(IItem target) {
|
||||
private int getDamage(IItem target, Attack type) {
|
||||
int damage = currentActor.getDamage();
|
||||
IWeapon weapon = (IWeapon)currentActor.getItem(IWeapon.class);
|
||||
IWeapon weapon = NPC.getWeapon(type, currentActor);
|
||||
if (weapon != null) {
|
||||
damage += weapon.getWeaponDamage();
|
||||
}
|
||||
IActor actor = (IActor) target;
|
||||
IBuffItem item = (IBuffItem) actor.getItem(IBuffItem.class);
|
||||
IBuffItem buff = (IBuffItem)currentActor.getItem(IBuffItem.class);
|
||||
if (buff != null) {
|
||||
damage += buff.getBuffDamage();
|
||||
}
|
||||
IBuffItem item = (IBuffItem)((IActor)target).getItem(IBuffItem.class);
|
||||
if (item != null) {
|
||||
damage -= item.getBuffDamageReduction();
|
||||
}
|
||||
@ -209,8 +218,8 @@ public class Game implements IGame {
|
||||
} else {
|
||||
NPC.playSound("audio/Realistic_Punch-Mark_DiAngelo-1609462330.wav");
|
||||
}
|
||||
if (getAttack() >= getDefence(target)) {
|
||||
int actualDamage = target.handleDamage(this, target, getDamage(target));
|
||||
if (getAttack(Attack.MELEE) >= getDefence(target)) {
|
||||
int actualDamage = target.handleDamage(this, target, getDamage(target, Attack.MELEE));
|
||||
if (currentActor != null) {
|
||||
formatMessage("%s hits %s for %d damage", currentActor.getName(), target.getName(), actualDamage);
|
||||
}
|
||||
@ -244,8 +253,8 @@ public class Game implements IGame {
|
||||
} else {
|
||||
NPC.playSound("audio/Snow Ball Throw And Splat-SoundBible.com-992042947.wav");
|
||||
}
|
||||
if (getAttack() >= getDefence(target)) {
|
||||
int damage = getDamage(target) / loc.gridDistanceTo(map.getLocation(target));
|
||||
if (getAttack(type) >= getDefence(target)) {
|
||||
int damage = getDamage(target, type) / loc.gridDistanceTo(map.getLocation(target));
|
||||
int actualDamage = target.handleDamage(this, target, damage);
|
||||
formatMessage("%s hits %s for %d damage", currentActor.getName(), target.getName(), actualDamage);
|
||||
} else {
|
||||
@ -500,6 +509,7 @@ public class Game implements IGame {
|
||||
boolean secondLineWritten = false;
|
||||
boolean thirdLineWritten = false;
|
||||
|
||||
//Makes long messages overflow to the next line.
|
||||
if (lastMessages.size() > 0) {
|
||||
String message = lastMessages.get(0);
|
||||
if (message.length() > 2 * maxLen) {
|
||||
|
@ -15,6 +15,11 @@ public class Bow implements IRangedWeapon {
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWeaponAttack() {
|
||||
return 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentHealth() {
|
||||
return hp;
|
||||
|
@ -23,13 +23,14 @@ public class Chest implements IContainer, IStatic {
|
||||
*/
|
||||
public void fill (int lvl) {
|
||||
Random random = new Random();
|
||||
int itemChance = 5;
|
||||
int itemChance = 3;
|
||||
List<IItem> items = new ArrayList<>();
|
||||
items.add(new Staff());
|
||||
items.add(new Sword());
|
||||
items.add(new Bow());
|
||||
items.add(new Binoculars());
|
||||
items.add(new Shield());
|
||||
items.add(new Manga());
|
||||
for (int i = 0; i < MAX_SIZE; i++) {
|
||||
int num = random.nextInt(100);
|
||||
boolean added = false;
|
||||
|
@ -10,6 +10,13 @@ public interface IWeapon extends IItem {
|
||||
*/
|
||||
int getWeaponDamage();
|
||||
|
||||
/**
|
||||
* Returns the attack ponts of a weapon.
|
||||
*
|
||||
* @return an int
|
||||
*/
|
||||
int getWeaponAttack();
|
||||
|
||||
/**
|
||||
* Retrieves the string path of the sound to play upon an attack.
|
||||
*
|
||||
|
@ -1,9 +1,9 @@
|
||||
package inf101.v18.rogue101.examples;
|
||||
package inf101.v18.rogue101.items;
|
||||
|
||||
import inf101.v18.rogue101.game.IGame;
|
||||
import inf101.v18.rogue101.objects.IItem;
|
||||
|
||||
public class Manga implements IItem {
|
||||
public class Manga implements IConsumable {
|
||||
private int hp = getMaxHealth();
|
||||
|
||||
@Override
|
||||
@ -46,4 +46,19 @@ public class Manga implements IItem {
|
||||
hp -= amount;
|
||||
return amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hpIncrease() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int attackIncrease() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int defenceIncrease() {
|
||||
return 5;
|
||||
}
|
||||
}
|
@ -15,6 +15,11 @@ public class Staff implements IMagicWeapon {
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWeaponAttack() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentHealth() {
|
||||
return hp;
|
||||
|
@ -15,6 +15,11 @@ public class Sword implements IMeleeWeapon {
|
||||
return damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWeaponAttack() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentHealth() {
|
||||
return hp;
|
||||
|
@ -13,7 +13,7 @@ import inf101.v18.rogue101.Main;
|
||||
import inf101.v18.rogue101.examples.Carrot;
|
||||
import inf101.v18.rogue101.game.IllegalMoveException;
|
||||
import inf101.v18.rogue101.items.*;
|
||||
import inf101.v18.rogue101.examples.Manga;
|
||||
import inf101.v18.rogue101.items.Manga;
|
||||
import inf101.v18.rogue101.objects.*;
|
||||
import javafx.scene.canvas.GraphicsContext;
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
# G = #
|
||||
# c G = < #
|
||||
# G = #
|
||||
# ############################### #
|
||||
################################# #
|
||||
# #
|
||||
# G #
|
||||
# ###############################
|
||||
|
@ -46,7 +46,7 @@ public class Player implements IPlayer {
|
||||
tryToMove(game, GridDirection.SOUTH);
|
||||
turnConsumed = true;
|
||||
} else if (key == KeyCode.E) {
|
||||
turnConsumed = pickUpInit(game);
|
||||
turnConsumed = interactInit(game);
|
||||
} else if (key == KeyCode.Q) {
|
||||
turnConsumed = dropInit(game);
|
||||
} else if (key == KeyCode.C) {
|
||||
@ -74,9 +74,9 @@ public class Player implements IPlayer {
|
||||
game.displayMessage("Please enter your name: ");
|
||||
writing = true;
|
||||
} else if (key == KeyCode.R) {
|
||||
turnConsumed = nonMeleeAttack(game, 3, Attack.RANGED, "ranged");
|
||||
turnConsumed = nonMeleeAttack(game, getVision(), Attack.RANGED, "ranged");
|
||||
} else if (key == KeyCode.F) {
|
||||
turnConsumed = nonMeleeAttack(game, 2, Attack.MAGIC, "magic");
|
||||
turnConsumed = nonMeleeAttack(game, getVision() / 2 + getVision() % 2 == 0 ? 0 : 1, Attack.MAGIC, "magic");
|
||||
}
|
||||
showStatus(game);
|
||||
return turnConsumed;
|
||||
@ -136,17 +136,17 @@ public class Player implements IPlayer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the picking up of an item, and does what is needed.
|
||||
* Initializes the interaction with an item, and does what is needed.
|
||||
*
|
||||
* @param game An IGame object
|
||||
* @return True if a turn was consumed. False otherwise
|
||||
*/
|
||||
private boolean pickUpInit(IGame game) {
|
||||
private boolean interactInit(IGame game) {
|
||||
List<IItem> items = game.getLocalItems();
|
||||
if (items.size() < 1) {
|
||||
game.displayMessage("There is nothing to pick up");
|
||||
} else {
|
||||
if (items.get(0) instanceof IStatic && items.get(0) instanceof IContainer) { //Static items are always the biggest (and hopefully the only) item on a tile.
|
||||
if (items.get(0) instanceof IStatic && items.get(0) instanceof IContainer) { //A Static item is always the biggest (and hopefully the only) item on a tile.
|
||||
openChest(game, items);
|
||||
} else if (items.get(0) instanceof IStatic && items.get(0) instanceof StairsUp) {
|
||||
((Game)game).goUp();
|
||||
@ -174,19 +174,19 @@ public class Player implements IPlayer {
|
||||
* @return True if a potion was used. False otherwise
|
||||
*/
|
||||
private boolean useConsumable(IGame game) {
|
||||
IConsumable potion = (IConsumable) equipped.getFirst(IConsumable.class);
|
||||
if (potion != null) {
|
||||
hp += potion.hpIncrease();
|
||||
IConsumable consumable = (IConsumable) equipped.getFirst(IConsumable.class);
|
||||
if (consumable != null) {
|
||||
hp += consumable.hpIncrease();
|
||||
if (hp > getMaxHealth()) {
|
||||
hp = getMaxHealth();
|
||||
}
|
||||
attack += potion.attackIncrease();
|
||||
defence += potion.defenceIncrease();
|
||||
equipped.remove(potion);
|
||||
game.displayMessage("Used " + potion.getName());
|
||||
attack += consumable.attackIncrease();
|
||||
defence += consumable.defenceIncrease();
|
||||
equipped.remove(consumable);
|
||||
game.displayMessage("Used " + consumable.getName());
|
||||
return true;
|
||||
} else {
|
||||
game.displayMessage("You don't have any potions.");
|
||||
game.displayMessage("You don't have any consumables.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -335,8 +335,16 @@ public class Player implements IPlayer {
|
||||
* @param game An IGame object
|
||||
*/
|
||||
private void showStatus(IGame game) {
|
||||
//TODO: Add item bonuses to visible stats.
|
||||
game.formatStatus("HP: %s %d/%d ATK: %d DEF: %s DMG: %s", NPC.hpBar(this), hp, getMaxHealth(), getAttack(), getDefence(), getDamage());
|
||||
game.formatStatus("HP: %s ATK: %d RATK: %d MATK: %d DEF: %s DMG: %s RDMG: %s MDMG: %s",
|
||||
NPC.hpBar(this),
|
||||
getAttack(Attack.MELEE),
|
||||
getAttack(Attack.RANGED),
|
||||
getAttack(Attack.MAGIC),
|
||||
getDefence(),
|
||||
getDamage(Attack.MELEE),
|
||||
getDamage(Attack.RANGED),
|
||||
getDamage(Attack.MAGIC)
|
||||
);
|
||||
printInventory(game);
|
||||
}
|
||||
|
||||
@ -380,16 +388,36 @@ public class Player implements IPlayer {
|
||||
if (game.canGo(dir)) {
|
||||
game.move(dir);
|
||||
} else if (loc.canGo(dir) && game.getMap().hasActors(loc.go(dir))) {
|
||||
NPC.playSound("audio/Sword Swing-SoundBible.com-639083727.wav");
|
||||
game.attack(dir, game.getMap().getActors(loc.go(dir)).get(0));
|
||||
} else {
|
||||
game.displayMessage("Umm, it is not possible to move in that direction.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getAttack() {
|
||||
return attack;
|
||||
IBuffItem buff = (IBuffItem)getItem(IBuffItem.class);
|
||||
if (buff != null) {
|
||||
return attack + buff.getBuffDamage();
|
||||
} else {
|
||||
return attack;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attack with added weapon attack
|
||||
*
|
||||
* @param type The attack type corresponding to the weapon type.
|
||||
* @return Attack as int
|
||||
*/
|
||||
private int getAttack(Attack type) {
|
||||
IWeapon weapon = NPC.getWeapon(type, this);
|
||||
if (weapon != null) {
|
||||
return getAttack() + weapon.getWeaponAttack();
|
||||
} else {
|
||||
return getAttack();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -397,6 +425,21 @@ public class Player implements IPlayer {
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the damage with added weapon damage
|
||||
*
|
||||
* @param type The attack type corresponding to the weapon type.
|
||||
* @return Damage as int
|
||||
*/
|
||||
private int getDamage(Attack type) {
|
||||
IWeapon weapon = NPC.getWeapon(type, this);
|
||||
if (weapon != null) {
|
||||
return getDamage() + weapon.getWeaponDamage();
|
||||
} else {
|
||||
return getDamage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItem getItem(Class<?> type) {
|
||||
for (IItem item : equipped.getContent()) {
|
||||
@ -414,7 +457,12 @@ public class Player implements IPlayer {
|
||||
|
||||
@Override
|
||||
public int getDefence() {
|
||||
return defence;
|
||||
IBuffItem buff = (IBuffItem)getItem(IBuffItem.class);
|
||||
if (buff != null) {
|
||||
return defence + buff.getBuffDamage();
|
||||
} else {
|
||||
return defence;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -462,6 +510,14 @@ public class Player implements IPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a ranged attack on the nearest visible enemy (if any);
|
||||
*
|
||||
* @param game An IGame object
|
||||
* @param range The range of the attack
|
||||
* @param type The attack type
|
||||
* @return True if the player attacked. False otherwise
|
||||
*/
|
||||
private boolean rangedAttack(IGame game, int range, Attack type) {
|
||||
List<ILocation> neighbours = game.getVisible();
|
||||
for (ILocation neighbour : neighbours) {
|
||||
|
@ -4,6 +4,7 @@ import inf101.v18.gfx.textmode.BlocksAndBoxes;
|
||||
import inf101.v18.grid.GridDirection;
|
||||
import inf101.v18.grid.ILocation;
|
||||
import inf101.v18.rogue101.game.IGame;
|
||||
import inf101.v18.rogue101.items.*;
|
||||
import inf101.v18.rogue101.map.IMapView;
|
||||
import inf101.v18.rogue101.objects.IActor;
|
||||
import inf101.v18.rogue101.objects.IItem;
|
||||
@ -194,4 +195,25 @@ public class NPC {
|
||||
str.append(BlocksAndBoxes.BLOCK_HALF);
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the weapon appropriate for the used attack.
|
||||
*
|
||||
* @param type The attack type
|
||||
* @return An IWeapon or null
|
||||
*/
|
||||
public static IWeapon getWeapon(Attack type, IActor actor) {
|
||||
IWeapon weapon = null;
|
||||
switch (type) {
|
||||
case MELEE:
|
||||
weapon = (IWeapon)actor.getItem(IMeleeWeapon.class);
|
||||
break;
|
||||
case RANGED:
|
||||
weapon = (IWeapon)actor.getItem(IRangedWeapon.class);
|
||||
break;
|
||||
case MAGIC:
|
||||
weapon = (IWeapon)actor.getItem(IMagicWeapon.class);
|
||||
}
|
||||
return weapon;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user