/*!
 * @file Creature.cpp
 * @brief ゲーム中のクリーチャーを定義する
 * @date 2013/12/10
 * @author Deskull
 * 2013 Sikabane Works.
 */

#include "stdafx.h"
#include "Creature.h"

const SOUL Creature::soulLevel[CREATURE_MAX_LEVEL] =
{
//  0    // ロスト域
	50,	 // Lv1デフォルト基準ソウル
	100, // Lv2到達ソウル
	130, // :
	180,
	260,
	360,
	480,
	630,
	880,
	1280, // Lv10到達ソウル
	1700,
	2200,
	2800,
	3600,
	4600,
	6100,
	8800,
	10600,
	12600,
	15000, // Lv20到達ソウル
	18000,
	24000,
	35000,
	50000,
	75000,
	100000,
	150000,
	200000,
	275000,
	350000, // Lv30到達ソウル
	450000,
	550000,
	700000,
	1000000,
	1500000,
	2100000,
	2700000,
	3600000,
	4700000,
	6000000, // Lv40到達ソウル
	7500000,
	9000000,
	11500000,
	14500000,
	19000000,
	26000000,
	33000000,
	45000000,
	60000000,
	90000000, // Lv50到達ソウル
	150000000,
	230000000,
	400000000,
	620000000,
	880000000,
	1150000000,
	1500000000,
	3200000000,
	6400000000,
	11100000000, // Lv60到達ソウル
};

Creature::Creature(Species *speciesPtr, ID id, TAG tag, GameWorld *gameWorld) : GameElement(id, tag, gameWorld)
{
	return;
}

Creature::Creature(ID id, TAG tag, GameWorld *gameWorld) : GameElement(id, tag, gameWorld)
{
	Creature();
	return;
}

Creature::Creature(void)
{
	this->name = "ダミー";
	this->currentMp = this->maxMp = this->maxMaxMp = 10;
	this->currentSoul = this->maxSoul = Creature::soulLevel[0];
	this->currentDiscipilne.SetPoint(0, 0, 0, 0, 0);
	this->height = 160;
	this->weight = 50;
	this->divineLevel = -1;
	savings.Set(10, 10, 10);
	this->currentFeed = this->maxFeed = 20000;

	currentStatus.Set(8, 8, 8, 8, 8, 8);
	maxStatus.Set(8, 8, 8, 8, 8, 8);
	maxMaxStatus.Set(20, 20, 20, 20, 20, 20);

	this->calcHPTable();
	currentHp = max_hp = this->GetNorMaxHP();

}

Creature::~Creature(void)
{
	return;
}

bool Creature::IsAlive(void)
{
	return this->currentHp > 0 && this->currentSoul > 0;
}

bool Creature::TakeEffect(Effect *effectPtr, POWER amount)
{
	return false;
}

void Creature::die(void)
{
}

int Creature::move(ID floor_ID, int x, int y)
{
	this->floorID = floor_ID;
	return 0;
}

int Creature::move(ID floor_ID, Coordinates coord)
{
	this->move(floor_ID, coord.GetX(), coord.GetY());
	return 0;
}

void Creature::calcHPTable(void)
{
	int lev;
	HP hitDice = this->GetSize();
	HP minLine = hitDice * (CREATURE_MAX_LEVEL + 4) * 70 / 100;
	HP maxLine = hitDice * (CREATURE_MAX_LEVEL + 4) * 130 / 100;

	do
	{
		this->hpTable[0] = hitDice + Dice::Cast(3, hitDice);
		for(lev = 0; lev < CREATURE_MAX_LEVEL - 1; lev++)
		{
			this->hpTable[lev + 1] = this->hpTable[lev] + Dice::Rand1(hitDice);
		}
	}
	while(this->hpTable[CREATURE_MAX_LEVEL - 1] < minLine && this->hpTable[CREATURE_MAX_LEVEL - 1] > maxLine);
}


void Creature::calcHP(HP amount)
{
	this->currentHp += amount;
	if(this->currentHp > this->max_hp) this->currentHp = this->max_hp;
	if(this->currentHp < 1) this->die();
}

void Creature::calcMP(MP amount)
{
	this->currentMp += amount;
	if(this->currentMp > this->maxMp) this->currentMp = this->maxMp;
	if(this->currentMp < 0) this->currentMp = 0;
}

void Creature::setHP(HP amount)
{
	this->currentHp = amount;
	if(this->currentHp < this->max_hp) this->currentHp = this->max_hp;
	if(this->currentHp < 1) this->die();
}

void Creature::setMP(MP amount)
{
	this->currentMp += amount;
	if(this->currentMp > this->maxMp) this->currentMp = this->maxMp;
	if(this->currentMp < 0) this->currentMp = 0;
}

const string Creature::GetName(void)
{
	return this->name;
}

LEVEL Creature::GetLevel(void)
{
	LEVEL level;
	if(this->currentSoul <= 0) return 0;
	if(this->currentSoul < Creature::soulLevel[1]) return 1;
	for(level = 2; level < CREATURE_MAX_LEVEL; level++)
	{
		if(Creature::soulLevel[level - 1] > this->currentSoul) return level;
	}
	return level;
}

const HP Creature::GetCurHP(void)
{
	return this->currentHp;
}

const HP Creature::GetMaxHP(void)
{
	return this->max_hp;
}

const HP Creature::GetNorMaxHP(void)
{
	return this->hpTable[this->GetLevel()];
}

const MP Creature::GetCurMP(void)
{
	return this->currentMp;
}

const MP Creature::GetMaxMP(void)
{
	return this->maxMp;
}

const MP Creature::GetNorMaxMP(void)
{
	return this->maxMaxMp;
}

const AC Creature::GetArmorSaving(void)
{
	return this->savings.GetArmor();
}

const EV Creature::GetEvasionSaving(void)
{
	return this->savings.GetEvasion();
}

const VO Creature::GetVolitionSaving(void)
{
	return this->savings.GetVolition();
}

const SOUL Creature::GetCurrentSoul(void)
{
	return this->currentSoul;
}

const SOUL Creature::GetMaxSoul(void)
{
	return this->maxSoul;
}

const BASE_STATUS Creature::GetCurrentStatus(CREATURE_STATUS stat)
{
	return currentStatus.Get(stat);
}

const BASE_STATUS Creature::GetMaxStatus(CREATURE_STATUS stat)
{
	return maxStatus.Get(stat);
}

const BASE_STATUS Creature::GetMaxMAXStatus(CREATURE_STATUS stat)
{
	return maxMaxStatus.Get(stat);
}

const DISCIPLINE_POINT Creature::GetDiscipilnePoint(DISCIPLINE_TYPE typ)
{
	return this->currentDiscipilne.GetPoint(typ);
}

const DISCIPLINE_POINT Creature::GetDiscipilneRank(DISCIPLINE_TYPE typ)
{
	return this->currentDiscipilne.GetRank(typ);
}

const HEIGHT Creature::GetHeight(void)
{
	return this->height;
}

const WEIGHT Creature::GetWeight(void)
{
	return this->weight;
}

const BODY_SIZE Creature::GetSize(void)
{
	return (BODY_SIZE)(sqrt((double)this->height * (double)this->weight) / 10.0f);
}

void Creature::GainSoul(SOUL amount)
{
	SOUL diff;
	if(this->currentSoul < this->maxSoul)
	{
		diff = this->maxSoul - this->currentSoul;
		if(diff < amount)
		{
			this->maxSoul += diff / 20;
			this->currentSoul = this->maxSoul;
			amount -= diff;
		}
		else
		{
			this->maxSoul += amount / 20;
			this->currentSoul += amount;
			amount = 0;
		}
	}
	this->currentSoul += amount;
	this->maxSoul += amount;
}

void Creature::LostSoul(SOUL amount)
{
	this->currentSoul -= amount;
	this->maxSoul -= amount / 20;
	if(this->currentSoul < 1) this->die();
}

const LEVEL Creature::GetDivineLevel(void)
{
	return this->divineLevel;
}

const FEED Creature::GetCurrentFeedPoint(void)
{
	return this->currentFeed;
}
	
const FEED Creature::GetMaxFeedPoint(void)
{
	return this->maxFeed;
}
