bool Game_BattleAlgorithm::Normal::Execute() {
	Reset();

	int to_hit;
	float multiplier = 1;
	int crit_chance = source->GetCriticalHitChance();
	if (source->GetType() == Game_Battler::Type_Ally) {
		Game_Actor* ally = static_cast<Game_Actor*>(source);
		int hit_chance = source->GetHitChance();
		int weaponID = ally->GetWeaponId() - 1;
		
		if (weaponID == -1) {
			// No Weapon
			// Todo: Two Sword style
			animation = &Data::animations[Data::actors[ally->GetId() - 1].unarmed_animation - 1];
		} else {
			animation = &Data::animations[Data::items[weaponID].animation_id - 1];
			RPG::Item weapon = Data::items[weaponID];
			hit_chance = weapon.hit;
			crit_chance += weapon.critical_hit;
			multiplier = GetAttributeMultiplier(weapon.attribute_set);
		}
		to_hit = (int)(100 - (100 - hit_chance));
		if(weaponID != -1 && !Data::items[weaponID].ignore_evasion) {
			to_hit *= (1 + (1.0 * (*current_target)->GetAgi() / ally->GetAgi() - 1) / 2);
		}
	} else {
		// Source is Enemy
		int hit = source->GetHitChance();
		to_hit = (int)(100 - (100 - hit) * (1 + (1.0 * (*current_target)->GetAgi() / source->GetAgi() - 1) / 2));
	}

	// Damage calculation
	if (rand() % 100 < to_hit) {
		if (!source->IsCharged() && rand() % 100 < crit_chance) {
			critical_hit = true;
		}

		int effect = (source->GetAtk() / 2 - (*current_target)->GetDef() / 4);

		if (effect < 0)
			effect = 0;

		int act_perc = (rand() % 40) - 20;
		// Change rounded up
		int change = (int)(std::ceil(effect * act_perc / 100.0));
		effect += change;
		effect *= multiplier;
		if(effect < 0) {
			effect = 0;
		}
		this->hp = (effect * (critical_hit ? 3 : 1) * (source->IsCharged() ? 2 : 1)) / ((*current_target)->IsDefending() ? 2 : 1);

		if ((*current_target)->GetHp() - this->hp <= 0) {
			// Death state
			killed_by_attack_damage = true;
			conditions.push_back(Data::states[0]);
		}
		else {
			if (source->GetType() == Game_Battler::Type_Ally) {
				int weaponID = static_cast<Game_Actor*>(source)->GetWeaponId() - 1;
				if (weaponID != -1) {
					RPG::Item item = Data::items[static_cast<Game_Actor*>(source)->GetWeaponId() - 1];
					for (int i = 0; i < item.state_set.size(); i++) {
						if (item.state_set[i] && rand() % 100 < (item.state_chance * (*current_target)->GetStateProbability(Data::states[i].ID) / 100)) {
							if (item.state_effect) {
								healing = true;
							}
							conditions.push_back(Data::states[i]);
						}
					}
				}
			}
		}
	}
	else {
		this->success = false;
		return this->success;
	}

	this->success = true;
	return this->success;
}
bool Game_BattleAlgorithm::Skill::Execute() {
	if (item && item->skill_id != skill.ID) {
		assert(false && "Item skill mismatch");
	}

	Reset();

	animation = skill.animation_id == 0 ? NULL : &Data::animations[skill.animation_id - 1];

	this->success = false;

	this->healing =
		skill.scope == RPG::Skill::Scope_ally ||
		skill.scope == RPG::Skill::Scope_party ||
		skill.scope == RPG::Skill::Scope_self;

	if (skill.type == RPG::Skill::Type_normal ||
		skill.type >= RPG::Skill::Type_subskill) {
		if (this->healing) {
			this->success = true;

			if (skill.affect_hp)
				this->hp = skill.power;
			if (skill.affect_sp)
				this->sp = skill.power;
			if (skill.affect_attack)
				this->attack = skill.power;
			if (skill.affect_defense)
				this->defense = skill.power;
			if (skill.affect_spirit)
				this->spirit = skill.power;
			if (skill.affect_agility)
				this->agility = skill.power;

		}
		else if (rand() % 100 < skill.hit) {
			this->success = true;

			int effect = skill.power +
				source->GetAtk() * skill.physical_rate / 20 +
				source->GetSpi() * skill.magical_rate / 40;
			if (!skill.ignore_defense) {
				effect -= (*current_target)->GetDef() * skill.physical_rate / 40 -
					(*current_target)->GetSpi() * skill.magical_rate / 80;
			}
			effect *= GetAttributeMultiplier(skill.attribute_effects);

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

			effect += rand() % (((effect * skill.variance / 10) + 1) - (effect * skill.variance / 20));

			if (effect < 0)
				effect = 0;

			if (skill.affect_hp) {
				this->hp = effect / ((*current_target)->IsDefending() ? 2 : 1);

				if ((*current_target)->GetHp() - this->hp <= 0) {
					// Death state
					killed_by_attack_damage = true;
					conditions.push_back(Data::states[0]);
				}
			}

			if (skill.affect_sp) {
				this->sp = std::min<int>(effect, (*current_target)->GetSp());
			}
				
			if (skill.affect_attack)
				this->attack = effect;
			if (skill.affect_defense)
				this->defense = effect;
			if (skill.affect_spirit)
				this->spirit = effect;
			if (skill.affect_agility)
				this->agility = agility;
		}

		for (int i = 0; i < (int) skill.state_effects.size(); i++) {
			if (!skill.state_effects[i])
				continue;
			if (!healing && rand() % 100 >= skill.hit)
				continue;

			this->success = true;
			
			if (healing || rand() % 100 <= (*current_target)->GetStateProbability(Data::states[i].ID)) {
				conditions.push_back(Data::states[i]);
			}
		}
	}
	else if (skill.type == RPG::Skill::Type_switch) {
		switch_id = skill.switch_id;
		this->success = true;
	}
	else {
		assert(false && "Unsupported skill type");
	}

	absorb = skill.absorb_damage;
	if (absorb && sp != -1) {
		if ((*current_target)->GetSp() == 0) {
			this->success = false;
		}
	}


	return this->success;
}
bool Game_Battler::UseSkill(int skill_id, const Game_Battler* source) {
	const RPG::Skill* skill = ReaderUtil::GetElement(Data::skills, skill_id);
	if (!skill) {
		Output::Warning("UseSkill: Can't use skill with invalid ID %d", skill_id);
		return false;
	}

	bool cure_hp_percentage = false;
	bool was_used = false;

	if (skill->type == RPG::Skill::Type_normal || skill->type >= RPG::Skill::Type_subskill) {
		// Only takes care of healing skills outside of battle,
		// the other skill logic is in Game_BattleAlgorithm

		if (!(skill->scope == RPG::Skill::Scope_ally ||
			  skill->scope == RPG::Skill::Scope_party ||
			  skill->scope == RPG::Skill::Scope_self)) {
			return false;
		}

		// Calculate effect:
		float mul = GetAttributeMultiplier(skill->attribute_effects);

		int effect = skill->power;
		if (source != nullptr) {
			effect += source->GetAtk() * skill->physical_rate / 20 +
				source->GetSpi() * skill->magical_rate / 40;
		}
		effect *= mul;

		effect += (effect * Utils::GetRandomNumber(-skill->variance * 10, skill->variance * 10) / 100);

		if (effect < 0)
			effect = 0;

		// Cure states
		for (int i = 0; i < (int)skill->state_effects.size(); i++) {
			if (skill->state_effects[i]) {
				if (skill->reverse_state_effect) {
					was_used |= !HasState(Data::states[i].ID);
					AddState(Data::states[i].ID);
				}
				else {
					was_used |= HasState(Data::states[i].ID);
					RemoveState(Data::states[i].ID);

					// If Death is cured and HP is not selected, we set a bool so it later heals HP percentage
					if (i == 0 && !skill->affect_hp) {
						cure_hp_percentage = true;
					}
				}
			}
		}

		// Skills only increase hp and sp outside of battle
		if (effect > 0 && skill->affect_hp && !HasFullHp() && !IsDead()) {
			was_used = true;
			ChangeHp(effect);
		}
		else if (effect > 0 && cure_hp_percentage) {
			was_used = true;
			ChangeHp(GetMaxHp() * effect / 100);
		}

		if (effect > 0 && skill->affect_sp && !HasFullSp() && !IsDead()) {
			was_used = true;
			ChangeSp(effect);
		}

	} else if (skill->type == RPG::Skill::Type_teleport || skill->type == RPG::Skill::Type_escape) {
		Game_System::SePlay(skill->sound_effect);
		was_used = true;
	} else if (skill->type == RPG::Skill::Type_switch) {
		Game_System::SePlay(skill->sound_effect);
		Game_Switches.Set(skill->switch_id, true);
		was_used = true;
	}

	return was_used;
}