Improved enemy item selection by adjusting to player items.
This commit is contained in:
parent
0daf1cf6d6
commit
7c2848972f
19 changed files with 175 additions and 72 deletions
10
src/Game.cpp
10
src/Game.cpp
|
@ -31,7 +31,6 @@ Game::Game(tgui::Window& window) :
|
|||
mWindow.setKeyRepeatEnabled(false);
|
||||
srand(time(nullptr));
|
||||
|
||||
mGenerator.generateCurrentAreaIfNeeded(Vector2f());
|
||||
initPlayer();
|
||||
|
||||
mCrosshairTexture = ResourceManager::i().acquire(Loader::i()
|
||||
|
@ -54,8 +53,13 @@ Game::Game(tgui::Window& window) :
|
|||
}
|
||||
|
||||
void Game::initPlayer() {
|
||||
Character::EquippedItems playerItems = {
|
||||
Weapon::WeaponType::PISTOL, Weapon::WeaponType::KNIFE,
|
||||
Gadget::GadgetType::NONE, Gadget::GadgetType::NONE
|
||||
};
|
||||
mGenerator.generateCurrentAreaIfNeeded(Vector2f(), playerItems);
|
||||
mPlayer = std::shared_ptr<Player>(new Player(mWorld, mPathfinder,
|
||||
mGenerator.getPlayerSpawn()));
|
||||
mGenerator.getPlayerSpawn(), playerItems));
|
||||
mWorld.insertCharacter(mPlayer);
|
||||
}
|
||||
|
||||
|
@ -92,7 +96,7 @@ Game::loop() {
|
|||
|
||||
render();
|
||||
|
||||
mGenerator.generateCurrentAreaIfNeeded(mPlayer->getPosition());
|
||||
mGenerator.generateCurrentAreaIfNeeded(mPlayer->getPosition(), mPlayer->getEquippedItems());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@ Generator::Generator(World& world, Pathfinder& pathfinder) :
|
|||
* GENERATE_AREA_SIZE and GENERATE_AREA_RANGE).
|
||||
*/
|
||||
void
|
||||
Generator::generateCurrentAreaIfNeeded(const Vector2f& playerPosition) {
|
||||
Generator::generateCurrentAreaIfNeeded(const Vector2f& playerPosition,
|
||||
const Character::EquippedItems& playerItems) {
|
||||
std::map<Vector2i, float> open;
|
||||
std::set<Vector2i> closed;
|
||||
|
||||
|
@ -65,11 +66,11 @@ Generator::generateCurrentAreaIfNeeded(const Vector2f& playerPosition) {
|
|||
Vector2i(GENERATE_AREA_SIZE, GENERATE_AREA_SIZE) / 2,
|
||||
Vector2i(GENERATE_AREA_SIZE, GENERATE_AREA_SIZE));
|
||||
generateTiles(area);
|
||||
for (const auto& enemy : getEnemySpawns(area)) {
|
||||
float distance = thor::length(enemy.first - playerPosition);
|
||||
for (const auto& spawn : getEnemySpawns(area)) {
|
||||
float distance = thor::length(spawn - playerPosition);
|
||||
if (distance > Character::VISION_DISTANCE)
|
||||
mWorld.insertCharacter(std::shared_ptr<Enemy>(new Enemy(
|
||||
mWorld, mPathfinder, enemy.first, enemy.second)));
|
||||
mWorld, mPathfinder, spawn, playerItems)));
|
||||
}
|
||||
}
|
||||
if (mGenerated[current.x][current.y] && distance <= GENERATE_AREA_RANGE) {
|
||||
|
@ -261,19 +262,16 @@ Generator::generateTiles(const sf::IntRect& area) {
|
|||
* @param area Area for which enemy spawns should be returned.
|
||||
* @return Pairs of spawn points together with seeds.
|
||||
*/
|
||||
std::vector<std::pair<Vector2f, float> >
|
||||
std::vector<Vector2f>
|
||||
Generator::getEnemySpawns(const sf::IntRect& area) {
|
||||
std::vector<std::pair<Vector2f, float> > spawns;
|
||||
std::vector<Vector2f> spawns;
|
||||
for (int x = area.left; x < area.left + area.width; x++) {
|
||||
for (int y = area.top; y < area.top + area.height; y++) {
|
||||
float noise = mCharacterNoise.getNoise(x, y);
|
||||
if (noise <= -0.85f) {
|
||||
Vector2i tilePosition = findClosestFloor(Vector2i(x, y));
|
||||
// Bad way to get a pseudo random, but deterministic value.
|
||||
// Just using noise would be better, but that is not uniformly distributed.
|
||||
int seed = ((int) noise * 100000) xor x xor y;
|
||||
spawns.push_back(std::make_pair(Vector2f(tilePosition.x * Tile::TILE_SIZE.x,
|
||||
tilePosition.y * Tile::TILE_SIZE.y), seed));
|
||||
spawns.push_back(Vector2f(tilePosition.x * Tile::TILE_SIZE.x,
|
||||
tilePosition.y * Tile::TILE_SIZE.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#include "../sprites/abstract/Character.h"
|
||||
#include "../sprites/Tile.h"
|
||||
#include "SimplexNoise.h"
|
||||
#include "../util/Vector.h"
|
||||
|
@ -23,9 +24,10 @@ class Pathfinder;
|
|||
class Generator : public sf::Drawable {
|
||||
public:
|
||||
explicit Generator(World& world, Pathfinder& pathfinder);
|
||||
void generateCurrentAreaIfNeeded(const Vector2f& position);
|
||||
void generateCurrentAreaIfNeeded(const Vector2f& position,
|
||||
const Character::EquippedItems& playerItems);
|
||||
Vector2f getPlayerSpawn() const;
|
||||
std::vector<std::pair<Vector2f, float> > getEnemySpawns(const sf::IntRect& area);
|
||||
std::vector<Vector2f> getEnemySpawns(const sf::IntRect& area);
|
||||
|
||||
private:
|
||||
typedef std::map<int, std::map<int, Tile::Type> > array;
|
||||
|
|
|
@ -21,33 +21,46 @@
|
|||
* @param seed Random value to seed random number generator.
|
||||
*/
|
||||
Enemy::Enemy(World& world, Pathfinder& pathfinder,
|
||||
const Vector2f& position, float seed) :
|
||||
const Vector2f& position, const EquippedItems& playerItems) :
|
||||
Character(position, CATEGORY_ACTOR, MASK_ALL, Yaml("enemy.yaml"), world,
|
||||
pathfinder) {
|
||||
std::ranlux24_base generator(seed);
|
||||
pathfinder, generateItems(playerItems)) {
|
||||
}
|
||||
|
||||
// Select primary weapon.
|
||||
switch (std::uniform_int_distribution<int>(0, 4)(generator)) {
|
||||
case 0: setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::ASSAULT_RIFLE)); break;
|
||||
case 1: setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::AUTO_SHOTGUN)); break;
|
||||
case 2: setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::HMG)); break;
|
||||
case 3: setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::RIFLE)); break;
|
||||
case 4: setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::SHOTGUN)); break;
|
||||
/**
|
||||
* Returns the items this enemy has equipped, based on items equipped by player.
|
||||
*
|
||||
* To do this, a random item is replaced by a slightly better one.
|
||||
*/
|
||||
Character::EquippedItems
|
||||
Enemy::generateItems(EquippedItems playerItems) {
|
||||
// Uses cast from enum to int to enum in order to increment enum values.
|
||||
switch (rand() % 4) {
|
||||
case 0:
|
||||
if (playerItems.primary + 1 != Weapon::WeaponType::_LAST)
|
||||
playerItems.primary =
|
||||
(Weapon::WeaponType) (((int) (playerItems.primary) + 1));
|
||||
|
||||
break;
|
||||
case 1:
|
||||
if (playerItems.secondary + 1 != Weapon::WeaponType::_LAST)
|
||||
playerItems.secondary =
|
||||
(Weapon::WeaponType) (((int) (playerItems.secondary) + 1));
|
||||
|
||||
break;
|
||||
case 2:
|
||||
if (playerItems.left + 1 != Gadget::GadgetType::_LAST)
|
||||
playerItems.left = (Gadget::GadgetType) (((int) (playerItems.left)
|
||||
+ 1));
|
||||
|
||||
break;
|
||||
case 3:
|
||||
if (playerItems.right + 1 != Gadget::GadgetType::_LAST)
|
||||
playerItems.left = (Gadget::GadgetType) (((int) (playerItems.left)
|
||||
+ 1));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Select secondary weapon.
|
||||
switch (std::uniform_int_distribution<int>(0, 1)(generator)) {
|
||||
case 0: setSecondWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::PISTOL)); break;
|
||||
case 1: setSecondWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::KNIFE)); break;
|
||||
}
|
||||
|
||||
// Select gadget.
|
||||
switch (std::uniform_int_distribution<int>(0, 2)(generator)) {
|
||||
case 0: setLeftGadget(std::shared_ptr<Gadget>(new Heal())); break;
|
||||
case 1: setLeftGadget(std::shared_ptr<Gadget>(new Shield())); break;
|
||||
case 2: setLeftGadget(std::shared_ptr<Gadget>(new RingOfFire(world))); break;
|
||||
}
|
||||
|
||||
return playerItems;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -15,10 +15,11 @@ class World;
|
|||
class Enemy : public Character {
|
||||
public:
|
||||
explicit Enemy(World& world, Pathfinder& pathfinder,
|
||||
const Vector2f& position, float seed);
|
||||
const Vector2f& position, const EquippedItems& playerItems);
|
||||
|
||||
private:
|
||||
virtual void onThink(int elapsed) override;
|
||||
static EquippedItems generateItems(EquippedItems playerItems);
|
||||
};
|
||||
|
||||
#endif /* DG_ENEMY_H_ */
|
||||
|
|
|
@ -16,12 +16,10 @@
|
|||
* Initializes Sprite.
|
||||
*/
|
||||
Player::Player(World& world, Pathfinder& pathfinder,
|
||||
const Vector2f& position) :
|
||||
const Vector2f& position, const EquippedItems& items) :
|
||||
Character(position, CATEGORY_ACTOR, MASK_ALL, Yaml("player.yaml"), world,
|
||||
pathfinder),
|
||||
pathfinder, items),
|
||||
mDirection(0) {
|
||||
setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::PISTOL));
|
||||
setSecondWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::KNIFE));
|
||||
}
|
||||
|
||||
Vector2f
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
|
||||
public:
|
||||
explicit Player(World& world, Pathfinder& pathfinder,
|
||||
const Vector2f& position);
|
||||
const Vector2f& position, const EquippedItems& items);
|
||||
|
||||
Vector2f getCrosshairPosition() const;
|
||||
void setCrosshairPosition(const Vector2f& position);
|
||||
|
|
|
@ -25,7 +25,7 @@ const float Character::ITEM_PICKUP_MAX_DISTANCE = 50.0f;
|
|||
*/
|
||||
Character::Character(const Vector2f& position, Category category,
|
||||
unsigned short mask, const Yaml& config, World& world,
|
||||
Pathfinder& pathfinder) :
|
||||
Pathfinder& pathfinder, const EquippedItems& items) :
|
||||
Circle(position, category, mask, config),
|
||||
mWorld(world),
|
||||
mPathfinder(pathfinder),
|
||||
|
@ -35,6 +35,10 @@ Character::Character(const Vector2f& position, Category category,
|
|||
mActiveWeapon(mFirstWeapon),
|
||||
mLastPosition(getPosition()),
|
||||
mFaction((Faction) config.get("faction", 1)) {
|
||||
setFirstWeapon(Weapon::getWeapon(world, *this, items.primary));
|
||||
setSecondWeapon(Weapon::getWeapon(world, *this, items.secondary));
|
||||
setLeftGadget(Gadget::getGadget(world, items.left));
|
||||
setRightGadget(Gadget::getGadget(world, items.right));
|
||||
}
|
||||
|
||||
Character::~Character() {
|
||||
|
@ -346,3 +350,13 @@ Character::pickUpItem() {
|
|||
}
|
||||
mWorld.remove(closest);
|
||||
}
|
||||
|
||||
Character::EquippedItems
|
||||
Character::getEquippedItems() const {
|
||||
return {
|
||||
(mFirstWeapon) ? mFirstWeapon->getType() : Weapon::WeaponType::NONE,
|
||||
(mSecondWeapon) ? mSecondWeapon->getType() : Weapon::WeaponType::NONE,
|
||||
(mLeftGadget) ? mLeftGadget->getType() : Gadget::GadgetType::NONE,
|
||||
(mRightGadget) ? mRightGadget->getType() : Gadget::GadgetType::NONE
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
#include "Circle.h"
|
||||
|
||||
#include "../items/Gadget.h"
|
||||
#include "../items/Weapon.h"
|
||||
|
||||
class Pathfinder;
|
||||
class World;
|
||||
class Weapon;
|
||||
class Yaml;
|
||||
|
||||
/**
|
||||
|
@ -27,6 +27,14 @@ public:
|
|||
FACTION_ENEMIES = 2
|
||||
};
|
||||
|
||||
struct EquippedItems {
|
||||
public:
|
||||
Weapon::WeaponType primary;
|
||||
Weapon::WeaponType secondary;
|
||||
Gadget::GadgetType left;
|
||||
Gadget::GadgetType right;
|
||||
};
|
||||
|
||||
/// Maximum distance where an enemy will be detected.
|
||||
static const float VISION_DISTANCE;
|
||||
/// Maximum distance from character where an item can be picked up.
|
||||
|
@ -35,11 +43,12 @@ public:
|
|||
public:
|
||||
explicit Character(const Vector2f& position, Category category,
|
||||
unsigned short mask, const Yaml& config, World& world,
|
||||
Pathfinder& pathfinder);
|
||||
Pathfinder& pathfinder, const EquippedItems& items);
|
||||
virtual ~Character() = 0;
|
||||
|
||||
void onDamage(int damage);
|
||||
Faction getFaction() const;
|
||||
EquippedItems getEquippedItems() const;
|
||||
|
||||
protected:
|
||||
virtual void onThink(int elapsed);
|
||||
|
@ -69,8 +78,6 @@ protected:
|
|||
std::string getRightGadgetName() const;
|
||||
void pickUpItem();
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
void move();
|
||||
void dropItem(std::shared_ptr<Item> item);
|
||||
|
|
|
@ -8,12 +8,32 @@
|
|||
#include "Gadget.h"
|
||||
|
||||
#include "../abstract/Character.h"
|
||||
#include "Heal.h"
|
||||
#include "Shield.h"
|
||||
#include "RingOfFire.h"
|
||||
|
||||
Gadget::Gadget(std::string name) :
|
||||
Item(sf::Vector2f(32, 32), "item.png"),
|
||||
mName(name) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new gadget of type and returns a pointer to it.
|
||||
*/
|
||||
std::shared_ptr<Gadget>
|
||||
Gadget::getGadget(World& world, GadgetType type) {
|
||||
switch (type) {
|
||||
case SHIELD:
|
||||
return std::shared_ptr<Gadget>(new Shield());
|
||||
case HEAL:
|
||||
return std::shared_ptr<Gadget>(new Heal());
|
||||
case RINGOFFIRE:
|
||||
return std::shared_ptr<Gadget>(new RingOfFire(world));
|
||||
default:
|
||||
return std::shared_ptr<Gadget>();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gadget::use(Character& character) {
|
||||
if (mCooldownTimer.isExpired()) {
|
||||
|
|
|
@ -15,15 +15,29 @@
|
|||
class Character;
|
||||
|
||||
class Gadget : public Item {
|
||||
public:
|
||||
/**
|
||||
* Gadgets, ordered by strength.
|
||||
*/
|
||||
enum GadgetType {
|
||||
NONE,
|
||||
SHIELD,
|
||||
HEAL,
|
||||
RINGOFFIRE,
|
||||
_LAST
|
||||
};
|
||||
|
||||
public:
|
||||
Gadget(std::string name);
|
||||
static std::shared_ptr<Gadget> getGadget(World& world, GadgetType type);
|
||||
void use(Character& character);
|
||||
virtual void onThink(int elapsed) = 0;
|
||||
std::string getName() const;
|
||||
virtual GadgetType getType() const = 0;
|
||||
|
||||
protected:
|
||||
virtual void onUse(Character& character) = 0;
|
||||
virtual sf::Time getCooldownTime() = 0;
|
||||
virtual sf::Time getCooldownTime() const = 0;
|
||||
|
||||
protected:
|
||||
thor::Timer mCooldownTimer;
|
||||
|
|
|
@ -29,7 +29,12 @@ Heal::onThink(int elapsed) {
|
|||
}
|
||||
|
||||
sf::Time
|
||||
Heal::getCooldownTime() {
|
||||
Heal::getCooldownTime() const {
|
||||
return sf::seconds(5);
|
||||
}
|
||||
|
||||
Gadget::GadgetType
|
||||
Heal::getType() const {
|
||||
return GadgetType::HEAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@ public:
|
|||
protected:
|
||||
void onUse(Character& character) override;
|
||||
void onThink(int elapsed) override;
|
||||
sf::Time getCooldownTime() override;
|
||||
sf::Time getCooldownTime() const override;
|
||||
GadgetType getType() const override;
|
||||
|
||||
private:
|
||||
Character* mCharacter;
|
||||
|
|
|
@ -42,7 +42,12 @@ RingOfFire::onThink(int elapsed) {
|
|||
}
|
||||
|
||||
sf::Time
|
||||
RingOfFire::getCooldownTime() {
|
||||
RingOfFire::getCooldownTime() const {
|
||||
return sf::seconds(5);
|
||||
}
|
||||
|
||||
Gadget::GadgetType
|
||||
RingOfFire::getType() const {
|
||||
return GadgetType::RINGOFFIRE;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ public:
|
|||
protected:
|
||||
void onUse(Character& character) override;
|
||||
void onThink(int elapsed) override;
|
||||
sf::Time getCooldownTime() override;
|
||||
sf::Time getCooldownTime() const override;
|
||||
GadgetType getType() const override;
|
||||
|
||||
private:
|
||||
static const int WAVES_PER_USE = 3;
|
||||
|
|
|
@ -35,6 +35,11 @@ Shield::onThink(int elapsed) {
|
|||
}
|
||||
|
||||
sf::Time
|
||||
Shield::getCooldownTime() {
|
||||
Shield::getCooldownTime() const {
|
||||
return sf::seconds(10);
|
||||
}
|
||||
|
||||
Shield::GadgetType
|
||||
Shield::getType() const {
|
||||
return GadgetType::SHIELD;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ public:
|
|||
protected:
|
||||
void onUse(Character& character) override;
|
||||
void onThink(int elapsed) override;
|
||||
sf::Time getCooldownTime() override;
|
||||
sf::Time getCooldownTime() const override;
|
||||
GadgetType getType() const override;
|
||||
|
||||
private:
|
||||
Character* mCharacter;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "../effects/Bullet.h"
|
||||
#include "../../util/Yaml.h"
|
||||
|
||||
Weapon::Weapon(World& world, Character& holder, const Yaml& config) :
|
||||
Weapon::Weapon(World& world, Character& holder, const Yaml& config, WeaponType type) :
|
||||
Item(Vector2f(32, 32), "item.png"),
|
||||
mWorld(world),
|
||||
mHolder(&holder),
|
||||
|
@ -35,7 +35,8 @@ Weapon::Weapon(World& world, Character& holder, const Yaml& config) :
|
|||
mSpread(config.get("spread", 0.0f)),
|
||||
mSpreadMoving(config.get("spread_moving", 0.0f)),
|
||||
mMaxRange(config.get("max_range", 0.0f)),
|
||||
mRequiresAmmo(!config.get("requires_no_ammo", false)) {
|
||||
mRequiresAmmo(!config.get("requires_no_ammo", false)),
|
||||
mType(type) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,20 +47,21 @@ std::shared_ptr<Weapon>
|
|||
Weapon::getWeapon(World& world, Character& holder, WeaponType type) {
|
||||
switch (type) {
|
||||
case WeaponType::KNIFE:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("knife.yaml")));
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("knife.yaml"), type));
|
||||
case WeaponType::PISTOL:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("pistol.yaml")));
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("pistol.yaml"), type));
|
||||
case WeaponType::ASSAULT_RIFLE:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("assault_rifle.yaml")));
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("assault_rifle.yaml"), type));
|
||||
case WeaponType::SHOTGUN:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("shotgun.yaml")));
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("shotgun.yaml"), type));
|
||||
case WeaponType::AUTO_SHOTGUN:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("auto_shotgun.yaml")));
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("auto_shotgun.yaml"), type));
|
||||
case WeaponType::RIFLE:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("rifle.yaml")));
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("rifle.yaml"), type));
|
||||
case WeaponType::HMG:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("hmg.yaml")));
|
||||
default: return std::shared_ptr<Weapon>();
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("hmg.yaml"), type));
|
||||
default:
|
||||
return std::shared_ptr<Weapon>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,3 +196,8 @@ Weapon::insertProjectile(float angle) {
|
|||
mDamage, mMaxRange));
|
||||
mWorld.insert(projectile);
|
||||
}
|
||||
|
||||
Weapon::WeaponType
|
||||
Weapon::getType() const {
|
||||
return mType;
|
||||
}
|
||||
|
|
|
@ -25,18 +25,23 @@ class Yaml;
|
|||
|
||||
class Weapon : public Item {
|
||||
public:
|
||||
enum class WeaponType {
|
||||
/**
|
||||
* Weapons, ordered by strength.
|
||||
*/
|
||||
enum WeaponType {
|
||||
NONE,
|
||||
KNIFE,
|
||||
PISTOL,
|
||||
RIFLE,
|
||||
ASSAULT_RIFLE,
|
||||
SHOTGUN,
|
||||
AUTO_SHOTGUN,
|
||||
RIFLE,
|
||||
HMG
|
||||
HMG,
|
||||
_LAST
|
||||
};
|
||||
|
||||
public:
|
||||
explicit Weapon(World& world, Character& holder, const Yaml& config);
|
||||
explicit Weapon(World& world, Character& holder, const Yaml& config, WeaponType type);
|
||||
static std::shared_ptr<Weapon> getWeapon(World& world, Character& holder, WeaponType type);
|
||||
|
||||
void pullTrigger();
|
||||
|
@ -48,6 +53,7 @@ public:
|
|||
void reload();
|
||||
void cancelReload();
|
||||
void setHolder(Character& holder);
|
||||
WeaponType getType() const;
|
||||
|
||||
private:
|
||||
void fire();
|
||||
|
@ -80,6 +86,7 @@ private:
|
|||
const float mMaxRange;
|
||||
const float mRequiresAmmo;
|
||||
std::default_random_engine mGenerator;
|
||||
WeaponType mType;
|
||||
|
||||
};
|
||||
|
||||
|
|
Reference in a new issue