fix: RemovePartyMember removes actual, not available party member

This commit is contained in:
Vsevolod Kremianskii 2020-12-29 21:05:09 +07:00
parent f50f57e107
commit f2d62e084c
8 changed files with 77 additions and 63 deletions

View file

@ -158,7 +158,7 @@ void CharacterGeneration::finish() {
Party &party = _game->party();
party.clear();
party.addMember(player);
party.addMember(kNpcPlayer, player);
party.setPlayer(player);
_game->loadModule(moduleName);

View file

@ -211,7 +211,7 @@ void MainMenu::onModuleSelected(const string &name) {
player->setTag("PLAYER");
player->setFaction(Faction::Friendly1);
player->setImmortal(true);
party.addMember(player);
party.addMember(kNpcPlayer, player);
party.setPlayer(player);
shared_ptr<Creature> companion(_game->objectFactory().newCreature());
@ -219,7 +219,7 @@ void MainMenu::onModuleSelected(const string &name) {
companion->setFaction(Faction::Friendly1);
companion->setImmortal(true);
companion->actionQueue().add(make_unique<FollowAction>(player, 1.0f));
party.addMember(companion);
party.addMember(0, companion);
_game->loadModule(name);
}

View file

@ -212,7 +212,7 @@ void PartySelection::changeParty() {
Party &party = _game->party();
party.clear();
party.addMember(party.player());
party.addMember(kNpcPlayer, party.player());
shared_ptr<Creature> player(_game->party().player());
@ -227,11 +227,10 @@ void PartySelection::changeParty() {
creature->setFaction(Faction::Friendly1);
creature->setImmortal(true);
creature->actionQueue().add(make_unique<FollowAction>(player, 1.0f));
party.addMember(creature);
party.addMember(i, creature);
}
area->loadParty(player->position(), player->facing());
area->fill(_game->sceneGraph());
area->reloadParty();
}
} // namespace game

View file

@ -466,6 +466,13 @@ void Area::unloadParty() {
}
}
void Area::reloadParty() {
shared_ptr<Creature> player(_game->party().player());
loadParty(player->position(), player->facing());
fill(_game->sceneGraph());
}
bool Area::handle(const SDL_Event &event) {
switch (event.type) {
case SDL_KEYDOWN:

View file

@ -128,6 +128,7 @@ public:
void loadParty(const glm::vec3 &position, float facing);
void unloadParty();
void reloadParty();
// END Party

View file

@ -80,12 +80,15 @@ bool Party::removeAvailableMember(int npc) {
return false;
}
bool Party::addMember(const shared_ptr<Creature> &member) {
bool Party::addMember(int npc, const shared_ptr<Creature> &creature) {
if (_members.size() == kMaxMemberCount) {
warn("Party: cannot add another member");
return false;
}
_members.push_back(member);
Member member;
member.npc = npc;
member.creature = creature;
_members.push_back(move(member));
return true;
}
@ -100,13 +103,13 @@ void Party::switchLeader() {
switch (count) {
case 2: {
shared_ptr<Creature> tmp(_members[0]);
Member tmp(_members[0]);
_members[0] = _members[1];
_members[1] = tmp;
break;
}
case 3: {
shared_ptr<Creature> tmp(_members[0]);
Member tmp(_members[0]);
_members[0] = _members[1];
_members[1] = _members[2];
_members[2] = tmp;
@ -118,11 +121,11 @@ void Party::switchLeader() {
}
void Party::onLeaderChanged() {
_members[0]->actionQueue().clear();
_members[0].creature->actionQueue().clear();
for (int i = 1; i < static_cast<int>(_members.size()); ++i) {
_members[i]->actionQueue().clear();
_members[i]->actionQueue().add(make_unique<FollowAction>(_members[0], 1.0f));
_members[i].creature->actionQueue().clear();
_members[i].creature->actionQueue().add(make_unique<FollowAction>(_members[0].creature, 1.0f));
}
_game->module()->area()->onPartyLeaderMoved();
}
@ -132,7 +135,7 @@ const string &Party::getAvailableMember(int npc) const {
}
shared_ptr<Creature> Party::getMember(int index) const {
return _members.size() > index ? _members[index] : nullptr;
return _members.size() > index ? _members[index].creature : nullptr;
}
bool Party::empty() const {
@ -143,24 +146,10 @@ int Party::size() const {
return static_cast<int>(_members.size());
}
bool Party::isNPCMember(int npc) const {
auto maybeMember = _availableMembers.find(npc);
if (maybeMember == _availableMembers.end()) return false;
if (npc != kNpcPlayer) {
for (auto &member : _members) {
if (member->blueprintResRef() == maybeMember->second) {
return true;
}
}
} else {
for (int i = 0; i < static_cast<int>(_members.size()); ++i) {
if (_members[i]->id() == _player->id()) {
return true;
}
}
bool Party::isMember(int npc) const {
for (auto &member : _members) {
if (member.npc == npc) return true;
}
return false;
}
@ -170,7 +159,7 @@ bool Party::isMemberAvailable(int npc) const {
bool Party::isMember(const Object &object) const {
for (auto &member : _members) {
if (member->id() == object.id()) return true;
if (member.creature->id() == object.id()) return true;
}
return false;
}
@ -180,30 +169,15 @@ shared_ptr<Creature> Party::player() const {
}
shared_ptr<Creature> Party::leader() const {
return !_members.empty() ? _members[0] : nullptr;
return !_members.empty() ? _members[0].creature : nullptr;
}
void Party::setPartyLeader(int npc) {
int memberIdx = -1;
if (npc != kNpcPlayer) {
auto maybeMember = _availableMembers.find(npc);
if (maybeMember == _availableMembers.end()) {
warn("Party: NPC is not available: " + to_string(npc));
return;
}
for (int i = 0; i < static_cast<int>(_members.size()); ++i) {
if (_members[i]->blueprintResRef() == maybeMember->second) {
memberIdx = -1;
break;
}
}
} else {
for (int i = 0; i < static_cast<int>(_members.size()); ++i) {
if (_members[i]->id() == _player->id()) {
memberIdx = i;
break;
}
for (int i = 0; i < static_cast<int>(_members.size()); ++i) {
if (_members[i].npc == npc) {
memberIdx = i;
break;
}
}
if (memberIdx == -1) {
@ -212,7 +186,7 @@ void Party::setPartyLeader(int npc) {
}
if (memberIdx == 0) return;
shared_ptr<Creature> tmp(_members[0]);
Member tmp(_members[0]);
_members[0] = _members[memberIdx];
_members[memberIdx] = tmp;
@ -223,6 +197,15 @@ void Party::setPlayer(const shared_ptr<Creature> &player) {
_player = player;
}
bool Party::removeMember(int npc) {
auto maybeMember = find_if(_members.begin(), _members.end(), [&npc](auto &member) { return member.npc == npc; });
if (maybeMember != _members.end()) {
_members.erase(maybeMember);
return true;
}
return false;
}
} // namespace game
} // namespace reone

View file

@ -42,13 +42,8 @@ public:
bool handle(const SDL_Event &event);
void clear();
bool addMember(const std::shared_ptr<Creature> &member);
void switchLeader();
std::shared_ptr<Creature> getMember(int index) const;
bool isNPCMember(int npc) const;
bool isMember(const Object &object) const;
bool empty() const;
int size() const;
std::shared_ptr<Creature> player() const;
@ -57,6 +52,22 @@ public:
void setPartyLeader(int npc);
void setPlayer(const std::shared_ptr<Creature> &player);
// Members
/**
* @param npc NPC number or kNpcPlayer for the player character
*/
bool addMember(int npc, const std::shared_ptr<Creature> &creature);
bool removeMember(int npc);
bool isMember(int npc) const;
bool isMember(const Object &object) const;
std::shared_ptr<Creature> getMember(int index) const;
// END Members
// Available members
bool addAvailableMember(int npc, const std::string &blueprint);
@ -69,10 +80,15 @@ public:
// END Available members
private:
struct Member {
int npc { 0 };
std::shared_ptr<Creature> creature;
};
Game *_game { nullptr };
std::shared_ptr<Creature> _player;
std::map<int, std::string> _availableMembers;
std::vector<std::shared_ptr<Creature>> _members;
std::vector<Member> _members;
bool handleKeyDown(const SDL_KeyboardEvent &event);

View file

@ -96,7 +96,7 @@ Variable Routines::getPCSpeaker(const VariablesList &args, ExecutionContext &ctx
Variable Routines::isNPCPartyMember(const VariablesList &args, ExecutionContext &ctx) {
int npc = getInt(args, 0);
bool isMember = _game->party().isNPCMember(npc);
bool isMember = _game->party().isMember(npc);
return isMember ? 1 : 0;
}
@ -120,8 +120,16 @@ Variable Routines::addPartyMember(const VariablesList &args, ExecutionContext &c
Variable Routines::removePartyMember(const VariablesList &args, ExecutionContext &ctx) {
int npc = getInt(args, 0);
bool removed = _game->party().removeAvailableMember(npc);
return removed ? 1 : 0;
if (!_game->party().isMember(npc)) return 0;
shared_ptr<Area> area(_game->module()->area());
area->unloadParty();
_game->party().removeMember(npc);
area->reloadParty();
return 1;
}
Variable Routines::getFirstPC(const VariablesList &args, ExecutionContext &ctx) {