Supports cloning battles for AI purposes.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
14016837d9
commit
a88719e2b3
|
@ -14,3 +14,48 @@ void PkmnLib::Battling::Battle::ClearWeather() {
|
||||||
_weatherScript = nullptr;
|
_weatherScript = nullptr;
|
||||||
_eventHook.Trigger<WeatherChangeEvent>(""_cnc);
|
_eventHook.Trigger<WeatherChangeEvent>(""_cnc);
|
||||||
}
|
}
|
||||||
|
PkmnLib::Battling::Battle* PkmnLib::Battling::Battle::Clone() const {
|
||||||
|
auto parties = ArbUt::List<CreatureLib::Battling::BattleParty*>(_parties.Count());
|
||||||
|
for (auto* party : _parties) {
|
||||||
|
parties.Append(party->Clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* battle =
|
||||||
|
new Battle(_library.ForceAs<const BattleLibrary>(), parties, _canFlee, _numberOfSides, _creaturesPerSide);
|
||||||
|
|
||||||
|
for (int i = 0; i < _numberOfSides; ++i) {
|
||||||
|
battle->_sides.Set(i, _sides[i]->CloneWithoutCreatures());
|
||||||
|
// FIXME: This is horrible code to translate the creature from the old battle into the same creature in the
|
||||||
|
// new battle. This needs to be cleaned up, as it's ugly and slow.
|
||||||
|
for (int creatureIndex = 0; creatureIndex < _creaturesPerSide; ++creatureIndex) {
|
||||||
|
auto creature = _sides[i]->GetCreature(creatureIndex);
|
||||||
|
if (!creature.HasValue()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (size_t j = 0; j < _parties.Count(); ++j) {
|
||||||
|
auto party = _parties[j];
|
||||||
|
if (!party->IsResponsibleForIndex(i, creatureIndex)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto partyIndex = party->GetParty()->GetParty().IndexOf(creature.GetValue());
|
||||||
|
if (partyIndex != -1U) {
|
||||||
|
auto c = battle->_parties.At(j)->GetParty()->GetParty()[partyIndex];
|
||||||
|
battle->_sides.At(i)->SetCreature(c, creatureIndex);
|
||||||
|
j = _parties.Count();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
battle->_random = _random;
|
||||||
|
battle->_hasEnded = _hasEnded;
|
||||||
|
battle->_battleResult = _battleResult;
|
||||||
|
_historyHolder.CloneOnto(battle->_historyHolder);
|
||||||
|
battle->_currentTurn = _currentTurn;
|
||||||
|
_volatile.Clone(battle->_volatile);
|
||||||
|
if (_weatherScript != nullptr) {
|
||||||
|
battle->_weatherScript = std::unique_ptr<CreatureLib::Battling::BattleScript>(_weatherScript->Clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
return battle;
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ namespace PkmnLib::Battling {
|
||||||
scripts.Append(CreatureLib::Battling::ScriptWrapper(
|
scripts.Append(CreatureLib::Battling::ScriptWrapper(
|
||||||
CreatureLib::Battling::ScriptWrapper::FromScript(&_weatherScript)));
|
CreatureLib::Battling::ScriptWrapper::FromScript(&_weatherScript)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Battle* Clone() const override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,12 @@ namespace PkmnLib::Battling {
|
||||||
const ArbUt::BorrowedPtr<const Library::MoveData> GetMoveData() const {
|
const ArbUt::BorrowedPtr<const Library::MoveData> GetMoveData() const {
|
||||||
return GetAttack().ForceAs<const Library::MoveData>();
|
return GetAttack().ForceAs<const Library::MoveData>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LearnedAttack* Clone() const override {
|
||||||
|
auto move = new LearnedMove(GetAttack().ForceAs<const Library::MoveData>(), GetLearnMethod());
|
||||||
|
move->DecreaseUses(GetMaxUses() - GetRemainingUses());
|
||||||
|
return move;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,4 +46,47 @@ void PkmnLib::Battling::Pokemon::ClearStatus() {
|
||||||
if (_battle.HasValue()) {
|
if (_battle.HasValue()) {
|
||||||
_battle.GetValue()->TriggerEventListener<StatusChangeEvent>(this, ""_cnc);
|
_battle.GetValue()->TriggerEventListener<StatusChangeEvent>(this, ""_cnc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CreatureLib::Battling::Creature* PkmnLib::Battling::Pokemon::Clone() const {
|
||||||
|
auto moves = std::vector<CreatureLib::Battling::LearnedAttack*>(_attacks.Count());
|
||||||
|
auto i = 0;
|
||||||
|
for (auto* attack : _attacks) {
|
||||||
|
if (attack == nullptr) {
|
||||||
|
moves[i++] = nullptr;
|
||||||
|
} else {
|
||||||
|
moves[i++] = dynamic_cast<LearnedMove*>(attack->Clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* c = new Pokemon(_library.ForceAs<const BattleLibrary>(), _species.ForceAs<const Library::PokemonSpecies>(),
|
||||||
|
_variant.ForceAs<const Library::PokemonForme>(), _level, _experience, _uniqueIdentifier,
|
||||||
|
_gender, _coloring, _heldItem.ForceAs<const Library::Item>(), _nickname, _talentIndex, moves,
|
||||||
|
_individualValues, _effortValues, _nature, _allowedExperienceGain);
|
||||||
|
c->_displaySpecies = _displaySpecies;
|
||||||
|
c->_displayVariant = _displayVariant;
|
||||||
|
c->_currentHealth = _currentHealth;
|
||||||
|
c->_statBoost = _statBoost;
|
||||||
|
c->_flatStats = _flatStats;
|
||||||
|
c->_boostedStats = _boostedStats;
|
||||||
|
c->_battle = _battle;
|
||||||
|
c->_side = _side;
|
||||||
|
c->_onBattleField = _onBattleField;
|
||||||
|
if (_activeTalent != nullptr) {
|
||||||
|
c->_activeTalent = std::unique_ptr<PkmnScript::BattleScript>(_activeTalent->Clone());
|
||||||
|
}
|
||||||
|
c->_hasOverridenTalent = _hasOverridenTalent;
|
||||||
|
c->_overridenTalentName = _overridenTalentName;
|
||||||
|
if (_status != nullptr) {
|
||||||
|
c->_status = std::unique_ptr<PkmnScript::BattleScript>(_status->Clone());
|
||||||
|
}
|
||||||
|
_volatile.Clone(c->_volatile);
|
||||||
|
c->_types = std::vector<u8>(_types);
|
||||||
|
if (_statusScript != nullptr) {
|
||||||
|
c->_statusScript = std::unique_ptr<PkmnScript::BattleScript>(_statusScript->Clone());
|
||||||
|
}
|
||||||
|
c->_friendship = _friendship;
|
||||||
|
c->RecalculateFlatStats();
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
|
@ -87,6 +87,8 @@ namespace PkmnLib::Battling {
|
||||||
}
|
}
|
||||||
_friendship = newValue;
|
_friendship = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Creature* Clone() const override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,23 @@ namespace PkmnLib::Battling {
|
||||||
: CreatureLib::Battling::CreatureParty(std::move(party)) {}
|
: CreatureLib::Battling::CreatureParty(std::move(party)) {}
|
||||||
PokemonParty(std::initializer_list<CreatureLib::Battling::Creature*> party)
|
PokemonParty(std::initializer_list<CreatureLib::Battling::Creature*> party)
|
||||||
: CreatureLib::Battling::CreatureParty(party) {}
|
: CreatureLib::Battling::CreatureParty(party) {}
|
||||||
|
PokemonParty(size_t size) : CreatureLib::Battling::CreatureParty(size) {}
|
||||||
|
|
||||||
ArbUt::OptionalBorrowedPtr<Pokemon> GetAtIndex(int index) const {
|
ArbUt::OptionalBorrowedPtr<Pokemon> GetAtIndex(int index) const {
|
||||||
return CreatureLib::Battling::CreatureParty::GetAtIndex(index).As<Pokemon>();
|
return CreatureLib::Battling::CreatureParty::GetAtIndex(index).As<Pokemon>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CreatureParty* Clone() const override {
|
||||||
|
auto party = new PokemonParty(GetParty().Count());
|
||||||
|
auto i = 0;
|
||||||
|
for (auto c : GetParty()) {
|
||||||
|
if (c != nullptr) {
|
||||||
|
party->SwapInto(i, c->Clone());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return party;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -294,9 +294,19 @@ void AngelScriptScript::PreventOpponentSwitch(const CreatureLib::Battling::Switc
|
||||||
void AngelScriptScript::OnEndTurn(CreatureLib::Battling::Creature* creature) {
|
void AngelScriptScript::OnEndTurn(CreatureLib::Battling::Creature* creature) {
|
||||||
CALL_HOOK(OnEndTurn, { ctx->SetArgObject(0, (void*)creature); })
|
CALL_HOOK(OnEndTurn, { ctx->SetArgObject(0, (void*)creature); })
|
||||||
}
|
}
|
||||||
void AngelScriptScript::ModifyNumberOfHits(CreatureLib::Battling::AttackTurnChoice* choice, u8* numberOfHits) {
|
void AngelScriptScript::ModifyNumberOfHits(CreatureLib::Battling::AttackTurnChoice* choice,
|
||||||
CALL_HOOK(ModifyNumberOfHits, {
|
u8* numberOfHits){CALL_HOOK(ModifyNumberOfHits,
|
||||||
ctx->SetArgObject(0, (void*)choice);
|
{
|
||||||
ctx->SetArgAddress(1, numberOfHits);
|
ctx->SetArgObject(0, (void*)choice);
|
||||||
})
|
ctx->SetArgAddress(1, numberOfHits);
|
||||||
|
})}
|
||||||
|
|
||||||
|
CreatureLib::Battling::BattleScript* AngelScriptScript::Clone() {
|
||||||
|
auto* ctx = _ctxPool->RequestContext();
|
||||||
|
auto* obj = _type->Instantiate(ctx);
|
||||||
|
if (_obj != nullptr){
|
||||||
|
obj->CopyFrom(_obj);
|
||||||
|
}
|
||||||
|
_ctxPool->ReturnContextToPool(ctx);
|
||||||
|
return new AngelScriptScript(_resolver, _type, obj, _ctxPool);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ public:
|
||||||
|
|
||||||
~AngelScriptScript() override { _obj->Release(); }
|
~AngelScriptScript() override { _obj->Release(); }
|
||||||
|
|
||||||
|
BattleScript* Clone() override;
|
||||||
|
|
||||||
inline asIScriptObject* GetRawAngelscriptObject() const noexcept { return _obj; }
|
inline asIScriptObject* GetRawAngelscriptObject() const noexcept { return _obj; }
|
||||||
|
|
||||||
[[nodiscard]] const ArbUt::StringView& GetName() const noexcept override { return _type->GetName(); }
|
[[nodiscard]] const ArbUt::StringView& GetName() const noexcept override { return _type->GetName(); }
|
||||||
|
|
Loading…
Reference in New Issue