int Game_Party::GetFatigue() { std::vector<Game_Actor*> actors = GetActors(); std::vector<Game_Actor*>::iterator it; if (actors.empty()) { return 0; } int hp = 0; int total_hp = 0; int sp = 0; int total_sp = 0; for (Game_Actor* a : actors) { hp += a->GetHp(); total_hp += a->GetMaxHp(); sp += a->GetSp(); total_sp += a->GetMaxSp(); } // SP is always 33.3% of fatigue, which means a 0 SP actor is never above 66% if (total_sp == 0) { total_sp = 1; } return (int)std::ceil(100 - 100.0f * (((float)hp / total_hp * 2.0f + (float)sp / total_sp) / 3.0f)); }
bool Game_Interpreter::CommandChangeHP(RPG::EventCommand const& com) { // Code 10460 std::vector<Game_Actor*> actors = GetActors(com.parameters[0], com.parameters[1]); bool remove = com.parameters[2] != 0; int amount = ValueOrVariable(com.parameters[3], com.parameters[4]); bool lethal = com.parameters[5] != 0; if (remove) amount = -amount; for (std::vector<Game_Actor*>::iterator i = actors.begin(); i != actors.end(); ++i) { Game_Actor* actor = *i; int hp = actor->GetHp() + amount; if (!lethal && hp <= 0) { amount += hp * (-1) + 1; } actor->ChangeHp(amount); } if (lethal) { CheckGameOver(); } return true; }
TArray<FActiveGameplayEffectHandle> FGameplayAbilityTargetData::ApplyGameplayEffectSpec(FGameplayEffectSpec& InSpec, FPredictionKey PredictionKey) { TArray<FActiveGameplayEffectHandle> AppliedHandles; if (!ensure(InSpec.GetContext().IsValid() && InSpec.GetContext().GetInstigatorAbilitySystemComponent())) { return AppliedHandles; } TArray<TWeakObjectPtr<AActor> > Actors = GetActors(); AppliedHandles.Reserve(Actors.Num()); for (TWeakObjectPtr<AActor> TargetActor : Actors) { UAbilitySystemComponent* TargetComponent = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor.Get()); if (TargetComponent) { // We have to make a new effect spec and context here, because otherwise the targeting info gets accumulated and things take damage multiple times FGameplayEffectSpec SpecToApply(InSpec); FGameplayEffectContextHandle EffectContext = SpecToApply.GetContext().Duplicate(); SpecToApply.SetContext(EffectContext); AddTargetDataToContext(EffectContext, false); AppliedHandles.Add(EffectContext.GetInstigatorAbilitySystemComponent()->ApplyGameplayEffectSpecToTarget(SpecToApply, TargetComponent, PredictionKey)); } } return AppliedHandles; }
// Change Experience. bool Game_Interpreter::CommandChangeLevel(RPG::EventCommand const& com) { // Code 10420 std::vector<Game_Actor*> actors = GetActors(com.parameters[0], com.parameters[1]); int value = OperateValue( com.parameters[2], com.parameters[3], com.parameters[4] ); for (std::vector<Game_Actor*>::iterator i = actors.begin(); i != actors.end(); i++) { Game_Actor* actor = *i; actor->ChangeLevel(actor->GetLevel() + value); } if (com.parameters[5] != 0) { // TODO // Show message increase level } else { // Don't show message increase level } // Continue return true; }
void FGameplayAbilityTargetData::AddTargetDataToContext(FGameplayEffectContextHandle& Context, bool bIncludeActorArray) const { if (bIncludeActorArray && (GetActors().Num() > 0)) { Context.AddActors(GetActors()); } if (HasHitResult() && !Context.GetHitResult()) { Context.AddHitResult(*GetHitResult()); } if (HasOrigin()) { Context.AddOrigin(GetOrigin().GetLocation()); } }
bool Game_Party::IsAnyControllable() { for (auto& actor: GetActors()) { if (actor->IsControllable()) { return true; } } return false; }
Game_Actor& Game_Party::operator[] (const int index) { std::vector<Game_Actor*> actors = GetActors(); if (index < 0 || (size_t)index >= actors.size()) { assert(false && "Subscript out of range"); } return *actors[index]; }
bool Game_Party::UseItem(int item_id, Game_Actor* target) { bool was_used = false; auto* item = ReaderUtil::GetElement(Data::items, item_id); if (!item) { Output::Warning("UseItem: Can't use item with invalid ID %d", item_id); return false; } bool do_skill = (item->type == RPG::Item::Type_special) || (item->use_skill && ( item->type == RPG::Item::Type_weapon || item->type == RPG::Item::Type_shield || item->type == RPG::Item::Type_armor || item->type == RPG::Item::Type_helmet || item->type == RPG::Item::Type_accessory ) ); const RPG::Skill* skill = nullptr; if (do_skill) { skill = ReaderUtil::GetElement(Data::skills, item->skill_id); if (skill == nullptr) { Output::Warning("UseItem: Can't use item %d skill with invalid ID %d", item->ID, item->skill_id); return false; } } const Game_Actor* fixed_source = nullptr; if (skill && skill->scope != RPG::Skill::Scope_self) { fixed_source = GetHighestLeveledActorWhoCanUse(item); if (fixed_source == nullptr) { return false; } } if (target) { const auto* source = fixed_source ? fixed_source : target; if (IsItemUsable(item_id, source)) { was_used = target->UseItem(item_id, source); } } else { for (auto* actor: GetActors()) { const auto* source = fixed_source ? fixed_source : actor; if (IsItemUsable(item_id, source)) { was_used |= actor->UseItem(item_id, source); } } } if (was_used) { ConsumeItemUse(item_id); } return was_used; }
void Game_Party::ApplyDamage(int damage, bool lethal) { if (damage <= 0) { return; } std::vector<Game_Actor*> actors = GetActors(); for (std::vector<Game_Actor*>::iterator i = actors.begin(); i != actors.end(); ++i) { Game_Actor* actor = *i; actor->ChangeHp(lethal? -damage : - std::max<int>(0, std::min<int>(damage, actor->GetHp() - 1))); } }
Game_Actor* Game_Party::GetHighestLeveledActorWhoCanUse(const RPG::Item* item) const { Game_Actor* best = nullptr; for (auto* actor : GetActors()) { if (actor->CanAct() && actor->IsItemUsable(item->ID) && (best == nullptr || best->GetLevel() < actor->GetLevel())) { best = actor; } } return best; }
void Game_Party::ApplyDamage(int damage) { if (damage <= 0) { return; } std::vector<Game_Actor*> actors = GetActors(); for (std::vector<Game_Actor*>::iterator i = actors.begin(); i != actors.end(); ++i) { Game_Actor* actor = *i; actor->SetHp(actor->GetHp() - damage); } }
bool Game_Party::ApplyStateDamage() { bool damage = false; std::vector<int16_t> states = GetInflictedStates(); const auto steps = GetSteps(); for (auto state_id : states) { RPG::State *state = ReaderUtil::GetElement(Data::states, state_id); // NOTE: We do steps + 1 here because this gets called before steps are incremented. if (state->hp_change_map_steps > 0 && state->hp_change_map_val > 0 && (((steps + 1) % state->hp_change_map_steps) == 0) ) { for (auto actor : GetActors()) { if (actor->HasState(state_id)) { actor->ChangeHp(-std::max<int>(0, std::min<int>(state->hp_change_map_val, actor->GetHp() - 1))); damage = true; } } } if (state->sp_change_map_steps > 0 && state->sp_change_map_val > 0 && (((steps + 1) % state->sp_change_map_steps) == 0) ){ for (auto actor : GetActors()) { if (actor->HasState(state_id)) { actor->ChangeSp(-state->sp_change_map_val); damage = true; } } } } return damage; }
std::vector<int16_t> Game_Party::GetInflictedStates() const { std::vector<int16_t> states; for (auto actor : GetActors()) { std::vector<int16_t> actor_states = actor->GetInflictedStates(); states.insert(states.end(), actor_states.begin(), actor_states.end()); } if (!states.empty()) { std::sort(states.begin(), states.end()); states.erase(std::unique(states.begin(), states.end()), states.end()); } return states; }
bool Game_Interpreter::CommandFullHeal(RPG::EventCommand const& com) { // Code 10490 std::vector<Game_Actor*> actors = GetActors(com.parameters[0], com.parameters[1]); for (std::vector<Game_Actor*>::iterator i = actors.begin(); i != actors.end(); i++) { Game_Actor* actor = *i; actor->SetHp(actor->GetMaxHp()); actor->SetSp(actor->GetMaxSp()); actor->RemoveAllStates(); } return true; }
int Game_Party::GetAverageLevel() { int party_lvl = 0; std::vector<Game_Actor*> actors = GetActors(); std::vector<Game_Actor*>::iterator it; if (actors.empty()) { return 0; } for (it = actors.begin(); it != actors.end(); ++it) { party_lvl += (*it)->GetLevel(); } return party_lvl /= actors.size(); }
int Game_Party::GetFatigue() { int party_exh = 0; std::vector<Game_Actor*> actors = GetActors(); std::vector<Game_Actor*>::iterator it; if (actors.empty()) { return 0; } for (it = actors.begin(); it != actors.end(); ++it) { // FIXME: this is what the help file says, but it looks wrong party_exh += 100 - (200 * (*it)->GetHp() / (*it)->GetMaxHp() - 100 * (*it)->GetSp() / (*it)->GetMaxSp() / 3); } return party_exh /= actors.size(); }
// Change Experience. bool Game_Interpreter::CommandChangeLevel(RPG::EventCommand const& com) { // Code 10420 std::vector<Game_Actor*> actors = GetActors(com.parameters[0], com.parameters[1]); int value = OperateValue( com.parameters[2], com.parameters[3], com.parameters[4] ); for (std::vector<Game_Actor*>::iterator i = actors.begin(); i != actors.end(); i++) { Game_Actor* actor = *i; actor->ChangeLevel(actor->GetLevel() + value, com.parameters[5] != 0); } return true; }
bool Game_Interpreter::CommandChangeCondition(RPG::EventCommand const& com) { // Code 10480 std::vector<Game_Actor*> actors = GetActors(com.parameters[0], com.parameters[1]); bool remove = com.parameters[2] != 0; int state_id = com.parameters[3]; for (std::vector<Game_Actor*>::iterator i = actors.begin(); i != actors.end(); i++) { Game_Actor* actor = *i; if (remove) actor->RemoveState(state_id); else actor->AddState(state_id); } return true; }
bool Game_Party::UseItem(int item_id, Game_Actor* target) { bool was_used = false; if (target) { was_used = target->UseItem(item_id); } else { std::vector<Game_Actor*> actors = GetActors(); std::vector<Game_Actor*>::iterator it; for (it = actors.begin(); it != actors.end(); ++it) { was_used |= (*it)->UseItem(item_id); } } if (was_used) { ConsumeItemUse(item_id); } return was_used; }
bool Game_Interpreter::CommandChangeSkills(RPG::EventCommand const& com) { // Code 10440 std::vector<Game_Actor*> actors = GetActors(com.parameters[0], com.parameters[1]); bool remove = com.parameters[2] != 0; int skill_id = ValueOrVariable(com.parameters[3], com.parameters[4]); for (std::vector<Game_Actor*>::iterator i = actors.begin(); i != actors.end(); i++) { Game_Actor* actor = *i; if (remove) actor->UnlearnSkill(skill_id); else actor->LearnSkill(skill_id); } return true; }
bool Game_Party::UseSkill(int skill_id, Game_Actor* source, Game_Actor* target) { bool was_used = false; if (target) { was_used = target->UseSkill(skill_id); } else { std::vector<Game_Actor*> actors = GetActors(); std::vector<Game_Actor*>::iterator it; for (it = actors.begin(); it != actors.end(); ++it) { was_used |= (*it)->UseSkill(skill_id); } } if (was_used) { source->SetSp(source->GetSp() - source->CalculateSkillCost(skill_id)); } return was_used; }
bool Game_Interpreter::CommandChangeEquipment(RPG::EventCommand const& com) { // Code 10450 std::vector<Game_Actor*> actors = GetActors(com.parameters[0], com.parameters[1]); int item_id; int type; int slot; switch (com.parameters[2]) { case 0: item_id = ValueOrVariable(com.parameters[3], com.parameters[4]); type = Data::items[item_id - 1].type; switch (type) { case RPG::Item::Type_weapon: case RPG::Item::Type_shield: case RPG::Item::Type_armor: case RPG::Item::Type_helmet: case RPG::Item::Type_accessory: slot = type - 1; default: return true; } break; case 1: item_id = 0; slot = com.parameters[3]; break; default: return false; } for (std::vector<Game_Actor*>::iterator i = actors.begin(); i != actors.end(); i++) { Game_Actor* actor = *i; actor->ChangeEquipment(slot, item_id); } return true; }
bool Game_Interpreter::CommandChangeSP(RPG::EventCommand const& com) { // Code 10470 std::vector<Game_Actor*> actors = GetActors(com.parameters[0], com.parameters[1]); bool remove = com.parameters[2] != 0; int amount = ValueOrVariable(com.parameters[3], com.parameters[4]); if (remove) amount = -amount; for (std::vector<Game_Actor*>::iterator i = actors.begin(); i != actors.end(); i++) { Game_Actor* actor = *i; int sp = actor->GetSp() + amount; if (sp < 0) sp = 0; actor->SetSp(sp); } return true; }
int Game_Party::GetBattlerCount() const { return GetActors().size(); }