#include "Human.h"
#include "PlayerGame.h"
#include "Wildling.h"
#include "../Interface/Actions.h"
#include "../Interface/General.h"
#include "Inventory.h"
#include "Den.h"

namespace mechanics {
	Human::Human(Animator &base, Animator &hair, OwnerType::Type owner, Gender::Type given_gender) : Object(base, owner),
		animatorHair(hair),
		mGender(given_gender), mLevel(-1), mXp(0), mAttackTarget(NULL),
		currentDirection(North), currentAnim("Stand"),
		actionTarget(NULL), actionType(NONE), mIsControllable(false)
	{
	}

	void Human::locateTo(const gge::utils::Point &given_location)
	{
		Object::locateTo(given_location);
		Map::current().getPointInfoMap()(location).walkable = false;
		Map::current().getPointInfoMap()(location).object=this;

		movementTarget=location;

		setSight();
	}

	void Human::setLocation(const gge::utils::Point &given_location) {
		if(given_location == location) {
			return;
		}

		Map::current().getPointInfoMap()(location).walkable = true;
		Map::current().getPointInfoMap()(location).object=NULL;
		//!if there is another object below the guy switch it to object

		Object::setLocation(given_location);

		Map::current().getPointInfoMap()(location).walkable = false;
		Map::current().getPointInfoMap()(location).object=this;

		rebuildSight();
	}

	void Human::removeFromMap() {
		Map::current().getPointInfoMap()(location).walkable = true;
		Map::current().getPointInfoMap()(location).object=NULL;
		Object::removeFromMap();

		rebuildSight();
	}

	std::string Human::info() {
		std::stringstream out;

		out << ((gender() == Gender::male) ? "Male" : "Female") << std::endl
			<< stat() << std::endl
			<< "HP: " << (int)HP() << "/" << (int)maximumHP() << "Sta: " << (int)stamina() << "/" << (int)maximumStamina();

		return out.str();
	}

	float Human::str() const {
		return mStat.str;
	}

	float Human::dex() const {
		return mStat.dex;
	}

	float Human::acc() const {
		return mStat.acc-accMod();
	}

	float Human::spe() const {
		return mStat.spe-speMod();
	}

	float Human::intl() const {
		return mStat.intl;
	}

	float Human::vit() const {
		return mStat.vit;
	}

	std::string Human::name() const {
		return mName;
	}

	void Human::name(std::string value) {
		mName = value;
	}

	std::string Human::surname() const {
		return mSurname;
	}

	void Human::surname(std::string value) {
		mSurname = value;
	}

	Gender::Type Human::gender() const {
		return mGender;
	}

	int Human::level() const {
		return mLevel;
	}

	float Human::xp() const {
		return mXp;
	}

	Stat Human::stat() const {
		return mStat;
	}

	float Human::maximumHP() const { //!const
		return assets::constants::human::HPBase + mStat.vit + (mLevel * assets::constants::human::HPLvlMultiplier);
	}

	float Human::stamina() const {
		return mStamina;
	}

	void Human::stamina(float value) {
		value=gge::utils::Limit(value, 0.f, maximumStamina());

		mStamina = value;
	}

	float Human::maximumStamina() const { //!const
		return assets::constants::human::staminaBase + mStat.vit + mStat.str + (mLevel * assets::constants::human::HPLvlMultiplier);
	}

	float Human::movementSpeed() const {
		return 
			(assets::constants::human::movementBase + 
			mStat.spe * assets::constants::human::movementSpeMultiplier + 
			mLevel    * assets::constants::human::movementLvlMultiplier)*movementSpeedModifier();
	}

	float Human::baseAttackCooldown() const {
		if(mInventory.mainHand) {
			return mInventory.mainHand->cooldown();
		}
		//! const
		return 5000;
	}

	float Human::attackCooldown() const {
		return mAttackCooldown;
	}

	void Human::attackCooldown(float value) {
		mAttackCooldown = value;
	}

	Attackable *Human::attackTarget() const {
		return mAttackTarget;
	}

	float Human::sightRange(bool nighttime) const {
		if(nighttime) {
			return (
				assets::constants::human::nightSightBase + 
				mStat.vit  * assets::constants::human::nightSightVitMultiplier + 
				mStat.intl * assets::constants::human::nightSightIntlMultiplier+ 
				mLevel     * assets::constants::human::nightSightLvlMultiplier )*sightRangeModifier();
		}

		return (
			assets::constants::human::daySightBase + 
			mStat.vit * assets::constants::human::daySightVitMultiplier +
			mLevel    * assets::constants::human::daySightLvlMultiplier) * sightRangeModifier() ;
	}

	float Human::dodge() const {
		//! constant
		return assets::constants::human::dogdgeBase + assets::constants::human::dodgeAccMultiplier * acc() + assets::constants::human::dodgeIntlMultiplier * intl() + assets::constants::human::dodgeLvlMultiplier * level();
	}

	float Human::parry() const {
		float parryPoint = 0.0f;
		for(int i=0; i < assets::Item::Max; i++) {
			if(mInventory.items[i] != NULL && mInventory.items[i]->canParry() && mInventory.items[i]->canBeUsed()) {
				parryPoint += mInventory.items[i]->parryPrecision();
			}
		}

		return parryPoint;
	}

	float Human::block() const {

		float blockPoint = 0.0f;

		if(mInventory.offHand != NULL && mInventory.offHand->canBlock() && mInventory.offHand->canBeUsed()) {
			blockPoint += mInventory.offHand->blockPrecision();
		}
		else if(mInventory.mainHand != NULL && mInventory.mainHand->canBlock() && mInventory.mainHand->canBeUsed()) {
			blockPoint += mInventory.mainHand->blockPrecision();
		}

		return blockPoint;

	}

	void Human::levelUp() {
		if(mLevel>=assets::constants::stats::maxLvl) return;

		mLevel++;
		mHP = maximumHP();
		mStamina = maximumStamina();

		if(mLevel==assets::constants::stats::maxLvl) {
			PlayerGame::current().addHappiness(assets::constants::happiness::happinesDeathModifier*2); //!constant
			log("Level up!");
		}
		else if(mLevel) {
			PlayerGame::current().addHappiness(assets::constants::happiness::happinesDeathModifier); //!constant
			log("Level up!");
		}
	}

	void Human::increaseXP(float value) {
		float xp = value * (1 + ((mStat.intl - assets::constants::leveling::XPIntlModifier) / assets::constants::leveling::XPIntlDenominator));
		mXp += xp;

		if(mXp >= nextLevelXP()) {
			levelUp();
		}
	}

	float Human::XPReward() const {
		//! constant
		return mXp * 0.5f / maximumHP();
	}

	Inventory &Human::inventory() {
		return mInventory;
	}

	Item *Human::inventory(assets::Item::Slot slot) const {
		return mInventory.items[slot];
	}

	void Human::setAnimation(Direction direction, std::string animationID, bool isLooping, float speed) {
		Object::setAnimation(direction, animationID, isLooping, speed);
		animatorHair.setAnimation(direction, animationID, isLooping, speed);
		currentDirection = direction;
		currentAnim = animationID;
		this->isLooping = isLooping;
		currentSpeed = speed;
	}

	void Human::setDirection(Direction direction, std::string animationID) {
		Object::setDirection(direction, animationID);		
		animatorHair.setDirection(direction, animationID);
		currentDirection = direction;
		currentAnim = animationID;
	}


	void Human::setMoveDirection(Direction direction) {
		setDirection(direction, "Walk");
	}

	void Human::animSetMove(Direction direction, float speed) {
		setAnimation(direction, "Walk", true, speed);
	}

	void Human::animStopMove(Direction direction) {
		setAnimation(direction, "Stand");
	}

	void Human::setSight() {
		auto mapsize=Map::current().getPointInfoMap().GetSize();

		int sightRange = (int)(this->sightRange(isNight()) / TILE_SIZE);

		int xmin=std::max(0, location.x-sightRange);
		int xmax=std::min(mapsize.Width, location.x+1+sightRange);

		int ymin=std::max(0, location.y-sightRange);
		int ymax=std::min(mapsize.Height, location.y+1+sightRange);

		for(int y=ymin;y<ymax;y++) {
			for(int x=xmin;x<xmax;x++) {
				if(gge::utils::Point(x,y).Distance(location)<sightRange) {
					Map::current().getPointInfoMap()(x, y).inSight = true;
					if(!Map::current().getPointInfoMap()(x, y).revealed) {
						Map::current().getPointInfoMap()(x, y).revealed=true;
						for(auto it=Map::current().revealedEvents.begin();it!=Map::current().revealedEvents.end();++it) {
							if(!it->isTriggered && it->location==gge::utils::Point(x,y) && interface::showEvent(*it)) {
								it->isTriggered=true;
							}
						}
					}
				}
			}
		}
	}

	void Human::rebuildSight() {
		Map::current().getPointInfoMap().ForAllCells([&](const gge::utils::Point &location, PointInfo &pointInfo) {
			pointInfo.inSight = (pointInfo.townCenter);
		});

		auto &objects = PlayerGame::current().getHumanList();
		for(auto it=objects.begin();it!=objects.end();++it) {
			(*it)->setSight();
		}
	}

	std::vector<Item*> &Human::getItemList() {
		return mItemList;
	}

	void Human::addItem(Item &item, bool equip) {
		mItemList.push_back(&item);

		item.wielder(this);

		if(equip) {
			equipItem(item);
		}
	}

	void Human::removeItem(Item *ptr) {
		ptr->wielder(NULL);
		unequipItem(*ptr);

		for(unsigned i=0; i < mItemList.size(); i++) {
			if(mItemList[i] == ptr) {
				mItemList.erase(mItemList.begin() + i);
				break;
			}
		}
	}

	void Human::equipItem(Item &item) {
		mInventory.items[item.provider().slot] = &item;
		setAnimation(currentDirection, currentAnim, isLooping, currentSpeed);
		if(item.provider().slot==assets::Item::MainHand) 
			mAttackCooldown=item.cooldown()*1.5;
	}

	void Human::unequipItem(Item &item) {
		if(mInventory.items[item.provider().slot] == &item) {
			unequipItem(item.provider().slot);
		}
	}

	void Human::unequipItem(assets::Item::Slot slot) {
		mInventory.items[slot] = NULL;
	}

	std::string Human::title() const {
		std::stringstream out;

		//! constant - title level
		if(mLevel >= 10) {
			out << (mGender == Gender::male ? assets::constants::general::maleTitle : assets::constants::general::femaleTitle);
		}

		out << mName << " " << mSurname;

		return out.str();
	}

	bool Human::ValidTarget(Object *object, bool ranged) {
		if(dynamic_cast<Wildling*>(object) && dynamic_cast<Wildling*>(object)->isAlive()) {
			return true;
		}

		if(ranged && dynamic_cast<Obstacle*>(object)) {
			return true;
		}

		return false;
	}

	void Human::CheckAttack() {
		if(!dynamic_cast<Soldier*>(this)) return; //!WTH
		if(mAttackTarget == NULL) {
			if(!actionTarget && actionType==NONE) {
				int sightrange=4;

				//if(!isNight()) sightrange/=2; //!constant

				int mindistance=sightrange*sightrange;
				Object *selected=NULL;

				for(int x=location.x-sightrange;x<=location.x+sightrange;x++) {
					for(int y=location.y-sightrange;y<=location.y+sightrange;y++) {
						if(ValidTarget(Map::current().getPointInfoMap().Get(x,y).object, true) && (x-location.x)*(x-location.x)+(y-location.y)*(y-location.y)<sightrange*sightrange) {
							int dist=gge::utils::Point(x,y).Distance(location);
							if(dist<mindistance) {
								mindistance=dist;
								selected=Map::current().getPointInfoMap()(x,y).object;
							}
						}
					}
				}

				if(selected)
					attackTo(selected);
			}
			else if(actionType==NONE || actionType==ATTACK) {
				if(dynamic_cast<Wildling*>(Map::current().getPointInfoMap().Get(location.x, location.y-1).object)) {
					attackTo(Map::current().getPointInfoMap().Get(location.x, location.y-1).object);
					return;
				}
				if(dynamic_cast<Wildling*>(Map::current().getPointInfoMap().Get(location.x, location.y+1).object)) {
					attackTo(Map::current().getPointInfoMap().Get(location.x, location.y+1).object);
					return;
				}
				if(dynamic_cast<Wildling*>(Map::current().getPointInfoMap().Get(location.x-1, location.y).object)) {
					attackTo(Map::current().getPointInfoMap().Get(location.x-1, location.y).object);
					return;
				}
				if(dynamic_cast<Wildling*>(Map::current().getPointInfoMap().Get(location.x+1, location.y).object)) {
					attackTo(Map::current().getPointInfoMap().Get(location.x+1, location.y).object);
					return;
				}
			}

			return;
		}

		if(actionTarget==NULL) {
			mAttackTarget=NULL;
			return;
		}

		if(!mAttackTarget->isAlive()) {
			mAttackTarget = NULL;
			setAnimation(currentDirection, "Stand");
			actionType=NONE;
			actionTarget=NULL;
			return;
		}

		if(mInventory.mainHand == NULL) {
			return;
		}

		if(!inHitRange()) {
			mAttackTarget=NULL;
			checkPerformAction();
			return;
		}

		if(currentGameTime - mLastAttackTime <= mAttackCooldown) {
			return;
		}

		BaseWeapon *weapon = dynamic_cast<BaseWeapon*>(mInventory.mainHand);

		if(!weapon->canBeUsed()) {
			return;
		}


		float damage = gge::utils::Random(0.f, attackDamage());
		float damagedone=mAttackTarget->Damage(this, weapon, damage);

		weapon->use();

		auto targetlocation=actionTarget->currentLocation()-location;
		if(abs(targetlocation.x)>abs(targetlocation.y)) {
			if(targetlocation.x>0)
				currentDirection=East;
			else
				currentDirection=West;
		}
		else {
			if(targetlocation.y>0)
				currentDirection=South;
			else
				currentDirection=North;
		}

		setAnimation(currentDirection, mInventory.mainHand->animationType(), false, 1000/mInventory.mainHand->cooldown());

		increaseXP(mAttackTarget->XPReward()*damagedone);

		mLastAttackTime = currentGameTime;
		mAttackCooldown=baseAttackCooldown();
	}

	void Human::checkTrain() {
		if(!dynamic_cast<Soldier*>(this)) return; //!WTH
		if(actionType!=TRAIN || actionTarget==NULL) return;

		if(lastTrainAttack==0) lastTrainAttack=currentGameTime;
		
		auto tb=dynamic_cast<TrainingBuilding*>(actionTarget);

		if(level()>=tb->provider().maxLvl) {
			actionType=NONE;
			actionTarget=NULL;
			tb->release(trainPoint);
			log("Training finished.");
			setAnimation(South, "Stand", false);
			return;
		}

		if(mInventory.mainHand == NULL) {
			return;
		}

		if(currentGameTime-lastTrainAttack>baseAttackCooldown()) {
			increaseXP(tb->provider().XPPerHit);

			setAnimation(currentDirection, mInventory.mainHand->animationType(), false);
			lastTrainAttack=currentGameTime;
		}
	}

	void Human::Killed(Attacker *attacker, BaseWeapon *weapon) {
		Attackable::Killed(attacker, weapon);

		setAnimation(currentDirection, "Hurt", false);
		
		cancelMovement();
		mAttackTarget=NULL;
		actionTarget=NULL;
		mIsControllable=false;

		Map::current().getPointInfoMap()(location).walkable = true;
		Map::current().getPointInfoMap()(location).object=NULL;
		PlayerGame::current().destroyHuman(this);

		if(interface::selectedObject==this) {
			interface::selectObject(NULL);
		}


		if(attacker != NULL) {
			PlayerGame::current().AddToGameLog(title() + " is killed by " + attacker->title() + ".");
		}
		else {
			PlayerGame::current().AddToGameLog(title() + " is died.");
		}
	}

	bool Human::Dodge(Attacker *attacker, BaseWeapon *weapon) {
		float attackPrecision;

		if(attacker != NULL) {
			attackPrecision = attacker->attackPrecision();
		}
		else {
			//! constant
			attackPrecision = 0.5f;
		}

		if(dodge() * (mDodgeBonus/100+1) < attackPrecision) {
			if(mDodgeBonus<0)
				mDodgeBonus=0;
			else
				mDodgeBonus += assets::constants::combat::dodgeChanceModifier;
			return false;
		}

		if(mDodgeBonus>0)
			mDodgeBonus=0;
		else
			mDodgeBonus -= assets::constants::combat::dodgeChanceModifier;

		log("dodged");
		return true;
	}

	bool Human::Parry(Attacker *attacker, BaseWeapon *weapon) {
		float attackPrecision;

		if(mInventory.mainHand == NULL || !mInventory.mainHand->canParry()) {
			return false;
		}

		if(!mInventory.mainHand->canBeUsed()) {
			return false;
		}

		if(attacker != NULL) {
			attackPrecision = attacker->attackPrecision();
		}
		else {
			//! constant, how can attacker be null
			attackPrecision = 0.5f;
		}

		if(parry() * (mParryBonus/100+1) < attackPrecision) {

			if(mParryBonus<0) 
				mParryBonus=0;
			else
				mParryBonus += 20;//! constant
			return false;
		}

		//! constant, should work with base parry value
		if(mParryBonus>0)
			mParryBonus=0;
		else
			mParryBonus -= 20;

		mInventory.mainHand->use(0.5f);//!use const

		log("parried");
		return true;
	}

	bool Human::Block(Attacker *attacker, BaseWeapon *weapon, float damage) {
		float attackPrecision;

		Item *blockitem=NULL;
		if(mInventory.offHand == NULL || !mInventory.offHand->canBlock() || !mInventory.offHand->canBeUsed()) {
			if(!mInventory.mainHand || mInventory.mainHand->canBlock()) {
				return false;
			}
			else {
				blockitem=mInventory.mainHand;
			}
		}
		else
			blockitem=mInventory.offHand;

		if(attacker != NULL) {
			attackPrecision = attacker->attackPrecision();
		}
		else {
			//! constant
			attackPrecision = 0.5f;
		}

		if(block() * (mBlockBonus/100+1) < attackPrecision) {
			if(mBlockBonus<0)
				mBlockBonus=0;
			else
				mBlockBonus += assets::constants::combat::blockChanceModifier;
			return false;
		}

		if(mBlockBonus>0)
			mBlockBonus=0;
		else
			mBlockBonus -= assets::constants::combat::blockChanceModifier;

		blockitem->use();

		log("blocked");
		return true;
	}

	float Human::CalculateDamageReduction(Attacker *attacker, BaseWeapon *weapon, float damage) {
		float dmg = Attackable::CalculateDamageReduction(attacker, weapon, damage);

		for(int i=0; i < assets::Item::Max; i++) {
			if(mInventory.items[i] != NULL) {
				dmg -= mInventory.items[i]->damageReduction();
			}
		}

		return std::max(dmg,0.f);
	}

	float Human::staggerBonus(float damage, float staggerPoint) {

		float percentage = 0.0f;
		for(int i=0; i < assets::Item::Max; i++) {
			if(mInventory.items[i] != NULL && mInventory.items[i]->canBeUsed()) {
				percentage += mInventory.items[i]->stagger();
			}
		}

		return staggerPoint * (percentage * 0.01);

	}

	float Human::attackDamage() {

		float damage = Attacker::attackDamage();
		for(int i=0; i < assets::Item::Max; i++) {
			if(mInventory.items[i] != NULL && mInventory.items[i]->canBeUsed()) {
				damage += mInventory.items[i]->attackDamage();
			}
		}

		return damage;

	}

	float Human::attackPrecision() {

		float precision = Attacker::attackPrecision();
		for(int i=0; i < assets::Item::Max; i++) {
			if(mInventory.items[i] != NULL && mInventory.items[i]->canBeUsed()) {
				precision += mInventory.items[i]->attackPrecision();
			}
		}

		return precision;

	}

	float Human::CalculateStagger(Attacker *attacker, BaseWeapon *weapon, float damage, float reducedDamage) {
		float stagger = Attackable::CalculateStagger(attacker, weapon, damage, reducedDamage);

		float pointReduction = (str() / assets::constants::combat::staggerStrDenominator) + (vit() / assets::constants::combat::staggerVitDenominator) + (level() * assets::constants::combat::staggerMultiplier);
		stagger -= pointReduction;

		float percentage = 0.0f;
		for(int i=0; i < assets::Item::Max; i++) {
			if(mInventory.items[i] != NULL) {
				percentage += mInventory.items[i]->staggerReduction();
			}
		}

		stagger -= stagger * (percentage * 0.01);

		if(stagger < 0) {
			stagger=0;
		}

		stamina(stamina() - (stagger / assets::constants::combat::staggerStaminaDenominator));
		attackCooldown(attackCooldown() * (stagger / assets::constants::combat::staggerAtckCDDenominator));

		return stagger;
	}

	void Human::doAction(gge::utils::Point pnt) {
		actionTarget=NULL;
		mAttackTarget=NULL;
		if(mIsControllable) {
			actionType=MOVE;
			moveTo(pnt);
		}
	}

	bool Human::inHitRange() {
		if(!mInventory.mainHand) {
			return false; //!no attack without weapon
		}

		if(mInventory.mainHand->type()==assets::Item::Ranged || mInventory.mainHand->type()==assets::Item::Cast) {
			if(mInventory.mainHand->overshootRange() <= actionTarget->currentLocation().Distance(location)) {
				return true;
			}
		}
		else if(
				Map::current().getPointInfoMap().Get(location.x, location.y-1).object==actionTarget ||
				Map::current().getPointInfoMap().Get(location.x, location.y+1).object==actionTarget ||
				Map::current().getPointInfoMap().Get(location.x-1, location.y).object==actionTarget ||
				Map::current().getPointInfoMap().Get(location.x+1, location.y).object==actionTarget
				) {
				return true;
		}

		return false;
	}

	void Human::checkPerformAction() {
		if(actionTarget && actionType==ATTACK) {
			if(!mInventory.mainHand) {
				return; //!no attack without weapon
			}

			if(!dynamic_cast<Den*>(actionTarget) && !Map::current().getPointInfoMap()(actionTarget->currentLocation()).inSight) {
				actionTarget=NULL;
				actionType=NONE;
			}
			else if(inHitRange()) {
				mAttackTarget = dynamic_cast<mechanics::Attackable *>(actionTarget);
			}
			else {
				moveTo(actionTarget->currentLocation());
			}
		}
		else if(actionTarget && actionType==TRAIN) {
			if(location!=trainPoint) {
				moveTo(trainPoint);
			}
		}
	}

	void Human::attackTo(mechanics::Object *target) {
		if(!dynamic_cast<Soldier*>(this)) return; //!WTH

		if(dynamic_cast<mechanics::Attackable *>(target)) {
			actionTarget=target;
			actionType=ATTACK;
			checkPerformAction();
		}
	}

	void Human::moveStep() {
		checkPerformAction();
	}

	void Human::moveFinished() {
		if(actionType==MOVE)
			actionType=NONE;

		checkPerformAction();
	}

	void Human::checkAction() {
		CheckAttack();
		checkTrain();

		if(currentGameTime-lastRegen>1000) {
			if(Map::current().getPointInfoMap()(location).buildable) {
				IncHP(1);
				if(!isMoving() && !mAttackTarget)
					stamina(stamina()+2);
			}
			else {
				if(!isMoving() && !mAttackTarget)
					stamina(stamina()+1);
			}
			lastRegen=currentGameTime;
		}
	}

	void Human::setMoverLocation(gge::utils::Point pnt) {
		setLocation(pnt);
	}

	gge::utils::Point Human::getMoverLocation() const {
		return location;
	}

	void Human::startTraining(TrainingBuilding *building) {
		actionType=TRAIN;
		actionTarget=building;

		trainPoint=building->allocate();

		checkPerformAction();
		lastTrainAttack=0;
	}

	void Human::addStamina(float value) {
		if(value<0)
			value*=staminaDrainModifier();

		mStamina=gge::utils::Limit(mStamina+value, 0.f, maximumStamina());
	}

	float Human::staminaDrainModifier() const {
		float drain=1.f;
		for(int i=0;i<assets::Item::Max;i++) {
			if(mInventory.items[i])
				drain+=mInventory.items[i]->staminaDrain()/100;
		}

		return drain;
	}

	float Human::movementSpeedModifier() const {
		float mod=1.f;
		for(int i=0;i<assets::Item::Max;i++) {
			if(mInventory.items[i])
				mod-=mInventory.items[i]->movementSpeed()/100;
		}

		return mod;
	}

	float Human::sightRangeModifier() const {
		float mod=1.f;
		for(int i=0;i<assets::Item::Max;i++) {
			if(mInventory.items[i])
				mod-=mInventory.items[i]->sightRange()/100;
		}

		return mod;
	}

	float Human::accMod() const {
		float mod=1.f;
		for(int i=0;i<assets::Item::Max;i++) {
			if(mInventory.items[i])
				mod-=mInventory.items[i]->statModification().acc;
		}

		return mod;
	}

	float Human::speMod() const {
		float mod=1.f;
		for(int i=0;i<assets::Item::Max;i++) {
			if(mInventory.items[i])
				mod-=mInventory.items[i]->statModification().spe;
		}

		return mod;
	}

}
