Skip to content

Commit

Permalink
Fix item usablility in menu
Browse files Browse the repository at this point in the history
* Usable is based on the "user" of the item.
* For non-skill items, target == source
* For skill items, highest level actor must be able
  to use the item.
  • Loading branch information
fmatthew5876 committed Dec 7, 2018
1 parent b436171 commit cb5760f
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 51 deletions.
4 changes: 2 additions & 2 deletions src/game_actor.cpp
Expand Up @@ -84,7 +84,7 @@ int Game_Actor::GetId() const {
return actor_id;
}

bool Game_Actor::UseItem(int item_id) {
bool Game_Actor::UseItem(int item_id, const Game_Battler* source) {
const RPG::Item* item = ReaderUtil::GetElement(Data::items, item_id);
if (!item) {
Output::Warning("UseItem: Can't use invalid item %d", item_id);
Expand All @@ -110,7 +110,7 @@ bool Game_Actor::UseItem(int item_id) {
return true;
}

return Game_Battler::UseItem(item_id);
return Game_Battler::UseItem(item_id, source);
}

bool Game_Actor::IsItemUsable(int item_id) const {
Expand Down
2 changes: 1 addition & 1 deletion src/game_actor.h
Expand Up @@ -73,7 +73,7 @@ class Game_Actor : public Game_Battler {
* @param item_id ID if item to use
* @return true if item affected anything
*/
bool UseItem(int item_id) override;
bool UseItem(int item_id, const Game_Battler* source) override;

/**
* Checks if the actor is permitted to use the item at all.
Expand Down
16 changes: 7 additions & 9 deletions src/game_battler.cpp
Expand Up @@ -233,7 +233,7 @@ bool Game_Battler::IsSkillUsable(int skill_id) const {
return true;
}

bool Game_Battler::UseItem(int item_id) {
bool Game_Battler::UseItem(int item_id, const Game_Battler* source) {
const RPG::Item* item = ReaderUtil::GetElement(Data::items, item_id);
if (!item) {
Output::Warning("UseItem: Can't use item with invalid ID %d", item_id);
Expand Down Expand Up @@ -282,7 +282,7 @@ bool Game_Battler::UseItem(int item_id) {
return true;
}

bool do_skill = RPG::Item::Type_special
bool do_skill = (item->type == RPG::Item::Type_special)
|| (item->use_skill && (
item->type == RPG::Item::Type_weapon
|| item->type == RPG::Item::Type_shield
Expand All @@ -294,19 +294,17 @@ bool Game_Battler::UseItem(int item_id) {

if (do_skill) {
auto* skill = ReaderUtil::GetElement(Data::skills, item->skill_id);
if (skill != nullptr) {
Game_Battler* source = this;
if (skill->scope != RPG::Skill::Scope_self) {
source = Main_Data::game_party->GetHighestLeveledActorWhoCanAct();
}
UseSkill(item->skill_id, source);
if (skill == nullptr) {
Output::Warning("UseItem: Can't use item %d skill with invalid ID %d", item->ID, item->skill_id);
return false;
}
UseSkill(item->skill_id, source);
}

return false;
}

bool Game_Battler::UseSkill(int skill_id, Game_Battler* source) {
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);
Expand Down
4 changes: 2 additions & 2 deletions src/game_battler.h
Expand Up @@ -352,7 +352,7 @@ class Game_Battler {
* @param item_id ID if item to use
* @return true if item affected anything
*/
virtual bool UseItem(int item_id);
virtual bool UseItem(int item_id, const Game_Battler* source);

/**
* Applies the effects of a skill.
Expand All @@ -364,7 +364,7 @@ class Game_Battler {
* @param source battler who threw the skill
* @return true if skill affected anything
*/
virtual bool UseSkill(int skill_id, Game_Battler* source);
virtual bool UseSkill(int skill_id, const Game_Battler* source);

/**
* Calculates the Skill costs including all modifiers.
Expand Down
107 changes: 72 additions & 35 deletions src/game_party.cpp
Expand Up @@ -218,34 +218,36 @@ bool Game_Party::IsItemUsable(int item_id, const Game_Actor* target) const {
return false;
}

if (item_id > 0 && item_id <= (int)Data::items.size() && data().party.size() > 0) {
if (data().party.size() == 0) {
return false;
}

switch (item->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:
return item->use_skill && IsSkillUsable(item->skill_id, nullptr, true);
case RPG::Item::Type_special:
return IsSkillUsable(item->skill_id, nullptr, true);
}

if (Game_Temp::battle_running) {
switch (item->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:
return item->use_skill && IsSkillUsable(item->skill_id, nullptr, true);
case RPG::Item::Type_special:
return IsSkillUsable(item->skill_id, nullptr, true);
case RPG::Item::Type_medicine:
return !item->occasion_field1;
case RPG::Item::Type_switch:
return item->occasion_battle;
}

if (Game_Temp::battle_running) {
switch (item->type) {
case RPG::Item::Type_medicine:
return !item->occasion_field1;
case RPG::Item::Type_switch:
return item->occasion_battle;
}
} else {
switch (item->type) {
case RPG::Item::Type_medicine:
case RPG::Item::Type_material:
case RPG::Item::Type_book:
return true;
case RPG::Item::Type_switch:
return item->occasion_field2;
}
} else {
switch (item->type) {
case RPG::Item::Type_medicine:
case RPG::Item::Type_material:
case RPG::Item::Type_book:
return true;
case RPG::Item::Type_switch:
return item->occasion_field2;
}
}

Expand All @@ -255,16 +257,49 @@ bool Game_Party::IsItemUsable(int item_id, const Game_Actor* target) const {
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) {
if (IsItemUsable(item_id, target)) {
was_used = target->UseItem(item_id);
const auto* source = fixed_source ? fixed_source : target;
if (IsItemUsable(item_id, source)) {
was_used = target->UseItem(item_id, source);
}
} else {
std::vector<Game_Actor*> actors = GetActors();
std::vector<Game_Actor*>::iterator it;
for (it = actors.begin(); it != actors.end(); ++it) {
if (IsItemUsable(item_id, (*it))) {
was_used |= (*it)->UseItem(item_id);
for (auto* actor: GetActors()) {
const auto* source = fixed_source ? fixed_source : actor;
if (IsItemUsable(item_id, source)) {
was_used |= actor->UseItem(item_id, source);
}
}
}
Expand Down Expand Up @@ -632,11 +667,13 @@ bool Game_Party::IsAnyControllable() {
return false;
}

Game_Actor* Game_Party::GetHighestLeveledActorWhoCanAct() const {
Game_Actor* Game_Party::GetHighestLeveledActorWhoCanUse(const RPG::Item* item) const {
Game_Actor* best = nullptr;

for (auto* actor : GetActors()) {
if (actor->CanAct() && (best == nullptr || best->GetLevel() < actor->GetLevel())) {
if (actor->CanAct()
&& actor->IsItemUsable(item->ID)
&& (best == nullptr || best->GetLevel() < actor->GetLevel())) {
best = actor;
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/game_party.h
Expand Up @@ -342,11 +342,13 @@ class Game_Party : public Game_Party_Base {
bool IsAnyControllable();

/**
* Gets the actor with the highest level who can act. If there are many, choose the one with the earliest position in the group.
* Gets the actor with the highest level who can act and use the given item. If there are many, choose the one with the earliest position in the group.
*
* @param the item to check
*
* @return The first Highest leveled actor who can act.
*/
Game_Actor* GetHighestLeveledActorWhoCanAct() const;
Game_Actor* GetHighestLeveledActorWhoCanUse(const RPG::Item*) const;

private:
const RPG::SaveInventory& data() const;
Expand Down

0 comments on commit cb5760f

Please sign in to comment.