-
-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(skymp5-server): Recipe checks #1979
Open
ZikkeyLS
wants to merge
9
commits into
skyrim-multiplayer:main
Choose a base branch
from
ZikkeyLS:recipe-checks
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 6 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
ff9e74c
Test Impl (only AND supported)
ZikkeyLS ca25402
Implement full CTDA base calculations
ZikkeyLS 0df3482
Refact
ZikkeyLS 9700f71
Change missdirectory
ZikkeyLS d104a76
Follow SOLID
ZikkeyLS 5f12ff7
Unit tests
ZikkeyLS 78ec499
Refact
ZikkeyLS 6a119b3
Update ActionListener.cpp
Pospelove 5fc2c5d
merge
Pospelove File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
#include "ActionListener.h" | ||
#include "AnimationSystem.h" | ||
#include "Condition.h" | ||
#include "ConsoleCommands.h" | ||
#include "CropRegeneration.h" | ||
#include "DummyMessageOutput.h" | ||
|
@@ -11,15 +12,14 @@ | |
#include "MovementValidation.h" | ||
#include "MpObjectReference.h" | ||
#include "MsgType.h" | ||
#include "UpdateEquipmentMessage.h" | ||
#include "UserMessageOutput.h" | ||
#include "WorldState.h" | ||
#include "script_objects/EspmGameObject.h" | ||
#include <fmt/format.h> | ||
#include <spdlog/spdlog.h> | ||
#include <unordered_set> | ||
|
||
#include "UpdateEquipmentMessage.h" | ||
|
||
namespace { | ||
void SendHostStop(PartOne& partOne, Networking::UserId badHosterUserId, | ||
MpObjectReference& remote) | ||
|
@@ -456,8 +456,37 @@ void UseCraftRecipe(MpActor* me, const espm::COBJ* recipeUsed, | |
spdlog::info("Using craft recipe with EDID {} from espm file with index {}", | ||
recipeUsed->GetEditorId(cache), espmIdx); | ||
|
||
std::vector<Condition*> conditions; | ||
|
||
for (auto& condition : recipeData.conditions) { | ||
// impl race, item, perk? checks | ||
if (condition.IsGetItemCount()) { | ||
conditions.push_back(new ItemCountCondition( | ||
condition.GetDefaultData().firstParameter, condition.comparisonValue, | ||
condition.GetOperator(), condition.GetFlags())); | ||
} else if (condition.IsGetIsRace()) { | ||
conditions.push_back(new RaceCondition( | ||
condition.GetDefaultData().firstParameter, condition.comparisonValue, | ||
condition.GetOperator(), condition.GetFlags())); | ||
} | ||
} | ||
|
||
bool requireAnd = false; | ||
for (auto& cond : conditions) { | ||
if (!cond->Evaluate(me)) { | ||
if (cond->GetFlags() != espm::CTDA::Flags::OR || requireAnd) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we want checking if the flag is set, we have to use & instead of != no matter how:
== and & is not the same. the first one will check that ALL flags are in the same state |
||
spdlog::trace("UseCraftRecipe - blocked by condition: {}", | ||
cond->GetDescription()); | ||
delete cond; | ||
return; | ||
} | ||
} else { | ||
requireAnd = false; | ||
} | ||
|
||
if (cond->GetFlags() == espm::CTDA::Flags::ANDORDEFAULT) { | ||
requireAnd = true; | ||
} | ||
delete cond; | ||
} | ||
|
||
std::vector<Inventory::Entry> entries; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
#include "Condition.h" | ||
|
||
bool CalculateOperationResult(int firstArgument, int secondArgument, | ||
espm::CTDA::Operator conditionOperator) | ||
{ | ||
switch (conditionOperator) { | ||
case espm::CTDA::Operator::EqualTo: | ||
return firstArgument == secondArgument; | ||
case espm::CTDA::Operator::NotEqualTo: | ||
return firstArgument != secondArgument; | ||
case espm::CTDA::Operator::GreaterThen: | ||
return firstArgument > secondArgument; | ||
case espm::CTDA::Operator::GreaterThenOrEqualTo: | ||
return firstArgument >= secondArgument; | ||
case espm::CTDA::Operator::LessThen: | ||
return firstArgument < secondArgument; | ||
case espm::CTDA::Operator::LessThenOrEqualTo: | ||
return firstArgument <= secondArgument; | ||
default: | ||
return false; | ||
} | ||
} | ||
|
||
Condition::Condition(espm::CTDA::Operator conditionOperator, | ||
espm::CTDA::Flags flags) | ||
: conditionOperator(conditionOperator) | ||
, flags(flags) | ||
{ | ||
} | ||
|
||
espm::CTDA::Flags Condition::GetFlags() const | ||
{ | ||
return flags; | ||
} | ||
|
||
ItemCountCondition::ItemCountCondition(int itemId, int comparisonValue, | ||
espm::CTDA::Operator conditionOperator, | ||
espm::CTDA::Flags flags) | ||
: Condition(conditionOperator, flags) | ||
, itemId(itemId) | ||
, comparisonValue(comparisonValue) | ||
{ | ||
} | ||
|
||
bool ItemCountCondition::Evaluate(MpActor* actor) const | ||
{ | ||
int itemCount = actor->GetInventory().GetItemCount(itemId); | ||
bool result = | ||
CalculateOperationResult(itemCount, comparisonValue, conditionOperator); | ||
spdlog::info("ItemCountCondition: itemId = {}, itemCount = {}, " | ||
"comparisonValue = {}, operator = {}, result = {}", | ||
itemId, itemCount, comparisonValue, | ||
static_cast<int>(conditionOperator), result); | ||
return result; | ||
} | ||
|
||
std::string ItemCountCondition::GetDescription() const | ||
{ | ||
return "ItemCountCondition: itemId = " + std::to_string(itemId) + | ||
", comparisonValue = " + std::to_string(comparisonValue) + | ||
", operator = " + std::to_string(static_cast<int>(conditionOperator)); | ||
} | ||
|
||
RaceCondition::RaceCondition(int raceId, int comparisonValue, | ||
espm::CTDA::Operator conditionOperator, | ||
espm::CTDA::Flags flags) | ||
: Condition(conditionOperator, flags) | ||
, raceId(raceId) | ||
, comparisonValue(comparisonValue) | ||
{ | ||
} | ||
|
||
bool RaceCondition::Evaluate(MpActor* actor) const | ||
{ | ||
int raceEquals = actor->GetRaceId() == raceId ? 1 : 0; | ||
bool result = | ||
CalculateOperationResult(raceEquals, comparisonValue, conditionOperator); | ||
spdlog::info("RaceCondition: raceId = {}, raceEquals = {}, " | ||
"comparisonValue = {}, operator = {}, result = {}", | ||
raceId, raceEquals, comparisonValue, | ||
static_cast<int>(conditionOperator), result); | ||
return result; | ||
} | ||
|
||
std::string RaceCondition::GetDescription() const | ||
{ | ||
return "RaceCondition: raceId = " + std::to_string(raceId) + | ||
", comparisonValue = " + std::to_string(comparisonValue) + | ||
", operator = " + std::to_string(static_cast<int>(conditionOperator)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#pragma once | ||
#include "MpActor.h" | ||
#include <spdlog/spdlog.h> | ||
|
||
class Condition | ||
{ | ||
protected: | ||
espm::CTDA::Operator conditionOperator; | ||
espm::CTDA::Flags flags; | ||
|
||
public: | ||
Condition(espm::CTDA::Operator conditionOperator, espm::CTDA::Flags flags); | ||
virtual bool Evaluate(MpActor* actor) const = 0; | ||
virtual std::string GetDescription() const = 0; | ||
espm::CTDA::Flags GetFlags() const; | ||
virtual ~Condition() = default; | ||
}; | ||
|
||
class ItemCountCondition : public Condition | ||
{ | ||
int itemId = 0; | ||
int comparisonValue = 0; | ||
|
||
public: | ||
ItemCountCondition(int itemId, int comparisonValue, | ||
espm::CTDA::Operator conditionOperator, | ||
espm::CTDA::Flags flags); | ||
|
||
bool Evaluate(MpActor* actor) const override; | ||
|
||
std::string GetDescription() const override; | ||
}; | ||
|
||
class RaceCondition : public Condition | ||
{ | ||
int raceId = 0; | ||
int comparisonValue = 0; | ||
|
||
public: | ||
RaceCondition(int raceId, int comparisonValue, | ||
espm::CTDA::Operator conditionOperator, | ||
espm::CTDA::Flags flags); | ||
|
||
bool Evaluate(MpActor* actor) const override; | ||
|
||
std::string GetDescription() const override; | ||
}; |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#include "Condition.h" | ||
#include "TestUtils.hpp" | ||
#include <catch2/catch_all.hpp> | ||
|
||
TEST_CASE("ItemCountCondition evaluates correctly", "[ItemCountCondition]") | ||
{ | ||
MpActor actor(LocationalData(), FormCallbacks::DoNothing()); | ||
|
||
ItemCountCondition condition(0x1, 5, espm::CTDA::Operator::EqualTo, | ||
espm::CTDA::Flags::ANDORDEFAULT); | ||
|
||
REQUIRE(condition.Evaluate(&actor) == false); | ||
|
||
actor.AddItem(0x1, 4); | ||
|
||
REQUIRE(condition.Evaluate(&actor) == false); | ||
|
||
actor.AddItem(0x1, 1); | ||
|
||
REQUIRE(condition.Evaluate(&actor) == true); | ||
} | ||
|
||
TEST_CASE("RaceCondition evaluates correctly", "[RaceCondition]") | ||
{ | ||
MpActor actor(LocationalData(), FormCallbacks::DoNothing()); | ||
Appearance appearance; | ||
appearance.raceId = 0x123; | ||
actor.SetAppearance(&appearance); | ||
|
||
RaceCondition condition(0x21, 1, espm::CTDA::Operator::EqualTo, | ||
espm::CTDA::Flags::ANDORDEFAULT); | ||
|
||
REQUIRE(condition.Evaluate(&actor) == false); | ||
|
||
condition = RaceCondition(0x123, 1, espm::CTDA::Operator::EqualTo, | ||
espm::CTDA::Flags::ANDORDEFAULT); | ||
|
||
REQUIRE(condition.Evaluate(&actor) == true); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
raw pointer detected 🤖
please use
std::unique_ptr
/std::shared_ptr
insteadThis is how we usually do it + I see incorrect
delete
logic which is much easier to replace than fix, re-review, etc